diff --git a/package-lock.json b/package-lock.json index 1148507..6c48b5a 100644 --- a/package-lock.json +++ b/package-lock.json @@ -12,8 +12,8 @@ "buffer": "^6.0.3", "chai": "^4.3.4", "node-fetch": "^2.6.1", - "xrpio": "^0.1.7", - "xrpl": "^2.6.0-beta.0" + "xrpio": "^0.2.1", + "xrpl": "^2.7.0" }, "devDependencies": { "@types/node": "^18.11.9", @@ -2791,11 +2791,11 @@ } }, "node_modules/ripple-address-codec": { - "version": "4.2.4", - "resolved": "https://registry.npmjs.org/ripple-address-codec/-/ripple-address-codec-4.2.4.tgz", - "integrity": "sha512-roAOjKz94+FboTItey1XRh5qynwt4xvfBLvbbcx+FiR94Yw2x3LrKLF2GVCMCSAh5I6PkcpADg6AbYsUbGN3nA==", + "version": "4.2.5", + "resolved": "https://registry.npmjs.org/ripple-address-codec/-/ripple-address-codec-4.2.5.tgz", + "integrity": "sha512-SZ96zZH+0REeyEcYVFl0vqcsGRXiFXS2RUgHupHhtVkOEk6men53vngVjJwBrSnY+oa6Cri15q1zSni3DEoxNw==", "dependencies": { - "base-x": "3.0.9", + "base-x": "^3.0.9", "create-hash": "^1.1.2" }, "engines": { @@ -2803,19 +2803,19 @@ } }, "node_modules/ripple-binary-codec": { - "version": "1.4.2", - "resolved": "https://registry.npmjs.org/ripple-binary-codec/-/ripple-binary-codec-1.4.2.tgz", - "integrity": "sha512-EDKIyZMa/6Ay/oNgCwjD9b9CJv0zmBreeHVQeG4BYwy+9GPnIQjNeT5e/aB6OjAnhcmpgbPeBmzwmNVwzxlt0w==", + "version": "1.4.3", + "resolved": "https://registry.npmjs.org/ripple-binary-codec/-/ripple-binary-codec-1.4.3.tgz", + "integrity": "sha512-P4ALjAJWBJpRApTQO+dJCrHE6mZxm7ypZot9OS0a3RCKOWTReNw0pDWfdhCGh1qXh71TeQnAk4CHdMLwR/76oQ==", "dependencies": { "assert": "^2.0.0", "big-integer": "^1.6.48", "buffer": "5.6.0", "create-hash": "^1.2.0", "decimal.js": "^10.2.0", - "ripple-address-codec": "^4.2.4" + "ripple-address-codec": "^4.2.5" }, "engines": { - "node": ">=10.22.0" + "node": ">= 10" } }, "node_modules/ripple-binary-codec/node_modules/buffer": { @@ -2828,15 +2828,15 @@ } }, "node_modules/ripple-keypairs": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/ripple-keypairs/-/ripple-keypairs-1.1.4.tgz", - "integrity": "sha512-PMMjTOxZmCSBOvHPj6bA+V/HGx7oFgDtGGI8VcZYuaFO2H87UX0X0jhfHy+LA2Xy31WYlD7GaDIDDt2QO+AMtw==", + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/ripple-keypairs/-/ripple-keypairs-1.1.5.tgz", + "integrity": "sha512-wLJXIBsMVazn2Yp/7oP4PvgA4Gd1HtuZLftdEJFNOLgraf82phqa2AnNK3t9f3XeQnApW1jAe/FcFFOY6QUn5w==", "dependencies": { "bn.js": "^5.1.1", "brorand": "^1.0.5", "elliptic": "^6.5.4", "hash.js": "^1.0.3", - "ripple-address-codec": "^4.2.4" + "ripple-address-codec": "^4.2.5" }, "engines": { "node": ">= 10" @@ -3685,97 +3685,33 @@ } }, "node_modules/xrpio": { - "version": "0.1.7", - "resolved": "https://registry.npmjs.org/xrpio/-/xrpio-0.1.7.tgz", - "integrity": "sha512-X/Hxlf31KC1OONq7NYQ518Esd8LHYpyc/RFN9F1J9Nr8WEjgz/XaJDR4IakV7MrNeC3uIRz6/qGFPFWHw2Rr+g==", + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/xrpio/-/xrpio-0.2.1.tgz", + "integrity": "sha512-2Dmse3BdEHDztXfn7LpV5GSX8W9ue2mGEBu5NvoGJMIauvKZTniSdkBpMU0D1uu3v3OyDin2q+puWERQ8Kqh+g==", "dependencies": { "ripple-lib": "^1.10.0", - "xrpl": "^2.1.1" - } - }, - "node_modules/xrpio/node_modules/ws": { - "version": "8.11.0", - "resolved": "https://registry.npmjs.org/ws/-/ws-8.11.0.tgz", - "integrity": "sha512-HPG3wQd9sNQoT9xHyNCXoDUa+Xw/VevmY9FoHyQ+g+rrMn4j6FB4np7Z0OhdTgjx6MgQLK7jwSy1YecU1+4Asg==", - "engines": { - "node": ">=10.0.0" - }, - "peerDependencies": { - "bufferutil": "^4.0.1", - "utf-8-validate": "^5.0.2" - }, - "peerDependenciesMeta": { - "bufferutil": { - "optional": true - }, - "utf-8-validate": { - "optional": true - } - } - }, - "node_modules/xrpio/node_modules/xrpl": { - "version": "2.5.0", - "resolved": "https://registry.npmjs.org/xrpl/-/xrpl-2.5.0.tgz", - "integrity": "sha512-NaGdOdNFQCVVfZ40etLvCzAdwzfArvKS8vhgZEPnueMuoPxupNZa8dX7ITVcTTD3T4qp+bj9q6jMrRbd/iXe3w==", - "dependencies": { - "bignumber.js": "^9.0.0", - "bip32": "^2.0.6", - "bip39": "^3.0.4", - "https-proxy-agent": "^5.0.0", - "lodash": "^4.17.4", - "ripple-address-codec": "^4.2.4", - "ripple-binary-codec": "^1.4.2", - "ripple-keypairs": "^1.1.4", - "ws": "^8.2.2" - }, - "engines": { - "node": ">=10.13.0" + "xrpl": "^2.7.0" } }, "node_modules/xrpl": { - "version": "2.6.0-beta.0", - "resolved": "https://registry.npmjs.org/xrpl/-/xrpl-2.6.0-beta.0.tgz", - "integrity": "sha512-trxKBR5WKZ6ll0AJSipEJTlcO4pg3RhUJNiXwNQ7ONbKpgQf0wRfOTFHpAR9luIHsnSoUdS2B+xrC5w6P/jDlA==", + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/xrpl/-/xrpl-2.7.0.tgz", + "integrity": "sha512-P4M/Myxn2U7wl1avAG2Y/JuJMlKw2boLNx0f9woYQJLrS68sICmAfGOYKqPSzwRPc9P7kmydNrk+737nmFW5Vw==", "dependencies": { "bignumber.js": "^9.0.0", "bip32": "^2.0.6", "bip39": "^3.0.4", "https-proxy-agent": "^5.0.0", "lodash": "^4.17.4", - "ripple-address-codec": "^4.2.4", - "ripple-binary-codec": "^1.5.0-beta.2", - "ripple-keypairs": "^1.1.4", + "ripple-address-codec": "^4.2.5", + "ripple-binary-codec": "^1.4.3", + "ripple-keypairs": "^1.1.5", "ws": "^8.2.2" }, "engines": { "node": ">=10.13.0" } }, - "node_modules/xrpl/node_modules/buffer": { - "version": "5.6.0", - "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.6.0.tgz", - "integrity": "sha512-/gDYp/UtU0eA1ys8bOs9J6a+E/KWIY+DZ+Q2WESNUA0jFRsJOc0SNUO6xJ5SGA1xueg3NL65W6s+NY5l9cunuw==", - "dependencies": { - "base64-js": "^1.0.2", - "ieee754": "^1.1.4" - } - }, - "node_modules/xrpl/node_modules/ripple-binary-codec": { - "version": "1.5.0-beta.2", - "resolved": "https://registry.npmjs.org/ripple-binary-codec/-/ripple-binary-codec-1.5.0-beta.2.tgz", - "integrity": "sha512-3KRezdZlgN567LiGBgJ4oakeZ2dMxgphoTaRMi9T/8diXUsjAxTlGc8ErjyRjqPo9oGtIBJUYkHyY0rGGWF5xg==", - "dependencies": { - "assert": "^2.0.0", - "big-integer": "^1.6.48", - "buffer": "5.6.0", - "create-hash": "^1.2.0", - "decimal.js": "^10.2.0", - "ripple-address-codec": "^4.2.4" - }, - "engines": { - "node": ">=10.22.0" - } - }, "node_modules/xrpl/node_modules/ws": { "version": "8.11.0", "resolved": "https://registry.npmjs.org/ws/-/ws-8.11.0.tgz", @@ -6076,25 +6012,25 @@ } }, "ripple-address-codec": { - "version": "4.2.4", - "resolved": "https://registry.npmjs.org/ripple-address-codec/-/ripple-address-codec-4.2.4.tgz", - "integrity": "sha512-roAOjKz94+FboTItey1XRh5qynwt4xvfBLvbbcx+FiR94Yw2x3LrKLF2GVCMCSAh5I6PkcpADg6AbYsUbGN3nA==", + "version": "4.2.5", + "resolved": "https://registry.npmjs.org/ripple-address-codec/-/ripple-address-codec-4.2.5.tgz", + "integrity": "sha512-SZ96zZH+0REeyEcYVFl0vqcsGRXiFXS2RUgHupHhtVkOEk6men53vngVjJwBrSnY+oa6Cri15q1zSni3DEoxNw==", "requires": { - "base-x": "3.0.9", + "base-x": "^3.0.9", "create-hash": "^1.1.2" } }, "ripple-binary-codec": { - "version": "1.4.2", - "resolved": "https://registry.npmjs.org/ripple-binary-codec/-/ripple-binary-codec-1.4.2.tgz", - "integrity": "sha512-EDKIyZMa/6Ay/oNgCwjD9b9CJv0zmBreeHVQeG4BYwy+9GPnIQjNeT5e/aB6OjAnhcmpgbPeBmzwmNVwzxlt0w==", + "version": "1.4.3", + "resolved": "https://registry.npmjs.org/ripple-binary-codec/-/ripple-binary-codec-1.4.3.tgz", + "integrity": "sha512-P4ALjAJWBJpRApTQO+dJCrHE6mZxm7ypZot9OS0a3RCKOWTReNw0pDWfdhCGh1qXh71TeQnAk4CHdMLwR/76oQ==", "requires": { "assert": "^2.0.0", "big-integer": "^1.6.48", "buffer": "5.6.0", "create-hash": "^1.2.0", "decimal.js": "^10.2.0", - "ripple-address-codec": "^4.2.4" + "ripple-address-codec": "^4.2.5" }, "dependencies": { "buffer": { @@ -6109,15 +6045,15 @@ } }, "ripple-keypairs": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/ripple-keypairs/-/ripple-keypairs-1.1.4.tgz", - "integrity": "sha512-PMMjTOxZmCSBOvHPj6bA+V/HGx7oFgDtGGI8VcZYuaFO2H87UX0X0jhfHy+LA2Xy31WYlD7GaDIDDt2QO+AMtw==", + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/ripple-keypairs/-/ripple-keypairs-1.1.5.tgz", + "integrity": "sha512-wLJXIBsMVazn2Yp/7oP4PvgA4Gd1HtuZLftdEJFNOLgraf82phqa2AnNK3t9f3XeQnApW1jAe/FcFFOY6QUn5w==", "requires": { "bn.js": "^5.1.1", "brorand": "^1.0.5", "elliptic": "^6.5.4", "hash.js": "^1.0.3", - "ripple-address-codec": "^4.2.4" + "ripple-address-codec": "^4.2.5" } }, "ripple-lib": { @@ -6718,76 +6654,30 @@ "requires": {} }, "xrpio": { - "version": "0.1.7", - "resolved": "https://registry.npmjs.org/xrpio/-/xrpio-0.1.7.tgz", - "integrity": "sha512-X/Hxlf31KC1OONq7NYQ518Esd8LHYpyc/RFN9F1J9Nr8WEjgz/XaJDR4IakV7MrNeC3uIRz6/qGFPFWHw2Rr+g==", + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/xrpio/-/xrpio-0.2.1.tgz", + "integrity": "sha512-2Dmse3BdEHDztXfn7LpV5GSX8W9ue2mGEBu5NvoGJMIauvKZTniSdkBpMU0D1uu3v3OyDin2q+puWERQ8Kqh+g==", "requires": { "ripple-lib": "^1.10.0", - "xrpl": "^2.1.1" - }, - "dependencies": { - "ws": { - "version": "8.11.0", - "resolved": "https://registry.npmjs.org/ws/-/ws-8.11.0.tgz", - "integrity": "sha512-HPG3wQd9sNQoT9xHyNCXoDUa+Xw/VevmY9FoHyQ+g+rrMn4j6FB4np7Z0OhdTgjx6MgQLK7jwSy1YecU1+4Asg==", - "requires": {} - }, - "xrpl": { - "version": "2.5.0", - "resolved": "https://registry.npmjs.org/xrpl/-/xrpl-2.5.0.tgz", - "integrity": "sha512-NaGdOdNFQCVVfZ40etLvCzAdwzfArvKS8vhgZEPnueMuoPxupNZa8dX7ITVcTTD3T4qp+bj9q6jMrRbd/iXe3w==", - "requires": { - "bignumber.js": "^9.0.0", - "bip32": "^2.0.6", - "bip39": "^3.0.4", - "https-proxy-agent": "^5.0.0", - "lodash": "^4.17.4", - "ripple-address-codec": "^4.2.4", - "ripple-binary-codec": "^1.4.2", - "ripple-keypairs": "^1.1.4", - "ws": "^8.2.2" - } - } + "xrpl": "^2.7.0" } }, "xrpl": { - "version": "2.6.0-beta.0", - "resolved": "https://registry.npmjs.org/xrpl/-/xrpl-2.6.0-beta.0.tgz", - "integrity": "sha512-trxKBR5WKZ6ll0AJSipEJTlcO4pg3RhUJNiXwNQ7ONbKpgQf0wRfOTFHpAR9luIHsnSoUdS2B+xrC5w6P/jDlA==", + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/xrpl/-/xrpl-2.7.0.tgz", + "integrity": "sha512-P4M/Myxn2U7wl1avAG2Y/JuJMlKw2boLNx0f9woYQJLrS68sICmAfGOYKqPSzwRPc9P7kmydNrk+737nmFW5Vw==", "requires": { "bignumber.js": "^9.0.0", "bip32": "^2.0.6", "bip39": "^3.0.4", "https-proxy-agent": "^5.0.0", "lodash": "^4.17.4", - "ripple-address-codec": "^4.2.4", - "ripple-binary-codec": "^1.5.0-beta.2", - "ripple-keypairs": "^1.1.4", + "ripple-address-codec": "^4.2.5", + "ripple-binary-codec": "^1.4.3", + "ripple-keypairs": "^1.1.5", "ws": "^8.2.2" }, "dependencies": { - "buffer": { - "version": "5.6.0", - "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.6.0.tgz", - "integrity": "sha512-/gDYp/UtU0eA1ys8bOs9J6a+E/KWIY+DZ+Q2WESNUA0jFRsJOc0SNUO6xJ5SGA1xueg3NL65W6s+NY5l9cunuw==", - "requires": { - "base64-js": "^1.0.2", - "ieee754": "^1.1.4" - } - }, - "ripple-binary-codec": { - "version": "1.5.0-beta.2", - "resolved": "https://registry.npmjs.org/ripple-binary-codec/-/ripple-binary-codec-1.5.0-beta.2.tgz", - "integrity": "sha512-3KRezdZlgN567LiGBgJ4oakeZ2dMxgphoTaRMi9T/8diXUsjAxTlGc8ErjyRjqPo9oGtIBJUYkHyY0rGGWF5xg==", - "requires": { - "assert": "^2.0.0", - "big-integer": "^1.6.48", - "buffer": "5.6.0", - "create-hash": "^1.2.0", - "decimal.js": "^10.2.0", - "ripple-address-codec": "^4.2.4" - } - }, "ws": { "version": "8.11.0", "resolved": "https://registry.npmjs.org/ws/-/ws-8.11.0.tgz", diff --git a/package.json b/package.json index bb8fd5f..79747b2 100644 --- a/package.json +++ b/package.json @@ -13,7 +13,7 @@ "copy-gui": "cp src/frontend/build/index.html gui", "webpack-gateway": "webpack --config webpack.gateway.js --progress && cp build/gateway/main.js gateway", "deploy": "node ./lib/Deploy.js", - "github": "cp gateway/* ~/caisar.github.io && cd ~/caisar.github.io && git add -A && git commit -m \"update\" --allow-empty && git push origin master" + "github": "cp gateway/* ~/caisar.github.io && cd ~/caisar.github.io && git checkout master && git add -A && git commit -m \"update\" --allow-empty && git push origin master --force && git checkout main && git add -A && git commit -m \"update\" --allow-empty && git push origin main --force" }, "author": "", "license": "ISC", @@ -21,8 +21,8 @@ "buffer": "^6.0.3", "chai": "^4.3.4", "node-fetch": "^2.6.1", - "xrpio": "^0.1.7", - "xrpl": "^2.6.0-beta.0" + "xrpio": "^0.2.1", + "xrpl": "^2.7.0" }, "devDependencies": { "@types/node": "^18.11.9", diff --git a/src/Configuration.ts b/src/Configuration.ts index 688f1be..693d93f 100644 --- a/src/Configuration.ts +++ b/src/Configuration.ts @@ -1,8 +1,8 @@ export const config = { "oracle": true, - "secret": "sEdTP9Wkb4FSeaFhBavaob336sUTnqy", - "treasuryAddress": "rffH6RPq8xcKAWVvdYsiGEFrz1mz2iH3oj", - "contractAddress": "rDXi28Ud76cz9LtR2vAwsmGfqMcnfCTm8g", //pk: sEdSMv9Ztd2njbAhL3tTYqVRTKMQEME + "secret": "sEdVwoxNkoxvRxRDaShXwWzVUkrgztd", + "treasuryAddress": "rnhVAr4ri5aTBUfoEzi4PPgc5yVo7jrAa5", + "contractAddress": "rakoA9cbkj9SbArhsQAiYFqm1fYYeWvrji", //pk: sEdVYHB7KJuK8jB1HF6Q8HQq62izZ9f "rippleNode": "wss://s.altnet.rippletest.net:51233", } \ No newline at end of file diff --git a/src/Deploy.ts b/src/Deploy.ts index 5d00223..b81ee90 100644 --- a/src/Deploy.ts +++ b/src/Deploy.ts @@ -15,6 +15,5 @@ const path = require('path'); await api.disconnect() console.log("Done. Your upload is at: ", dataHash); console.log("Building gateway ...") - child_process.exec(`DATA_HASH=${dataHash} npm run webpack-gateway`, console.log) })() \ No newline at end of file diff --git a/src/frontend/src/app/services/ShoutboxData.service.ts b/src/frontend/src/app/services/ShoutboxData.service.ts index 5ed3ec3..71ef7fb 100644 --- a/src/frontend/src/app/services/ShoutboxData.service.ts +++ b/src/frontend/src/app/services/ShoutboxData.service.ts @@ -14,7 +14,7 @@ export class ShoutboxDataService { private userWallet1: any private userWallet2: any - private shoutboxAddress = "rBnbBMZrbWEVHsyi1EWxv3gidzbreJzbgC" + private shoutboxAddress = "rBGqUNVzrNJ6CNpTriBts8QCTNi5VqUMnZ" private rippleApi: any; private xrpio: any; @@ -28,11 +28,23 @@ export class ShoutboxDataService { } private submit = async (shoutHash: string) => { - return await this.xrpio.writeRaw({ data: shoutHash }, this.shoutboxAddress, this.userWallet1.secret) + const data = { + endpoint: 'submit', + data: shoutHash + } + + console.log("Submitting shout root hash", data) + const submitTx = await this.xrpio.writeRaw({data: JSON.stringify(data)}, this.shoutboxAddress, this.userWallet1.secret) + + console.log("submit TX @", submitTx) + + return submitTx } public submitShout = async (shout: any) => { + console.log("writing shout data", shout) const shoutHash = await this.xrpio.treeWrite(JSON.stringify(shout), this.userWallet1.address, this.userWallet2.secret) + console.log("shout data @ ", shoutHash) return await this.submit(shoutHash) } diff --git a/src/frontend/src/app/services/test.ts b/src/frontend/src/app/services/test.ts new file mode 100644 index 0000000..71ef7fb --- /dev/null +++ b/src/frontend/src/app/services/test.ts @@ -0,0 +1,116 @@ +import { Injectable } from "@angular/core"; +import { DataParser } from "../util/Dataparser"; +import { makeTestnetWallet } from "../util/TestnetUtils"; + +declare const xrpIO: any +declare const xrpl: any + +const xrpNode = "wss://s.altnet.rippletest.net:51233" + +@Injectable() +export class ShoutboxDataService { + + public history: any[] = [] + + private userWallet1: any + private userWallet2: any + private shoutboxAddress = "rBGqUNVzrNJ6CNpTriBts8QCTNi5VqUMnZ" + private rippleApi: any; + private xrpio: any; + + private getTransactions = async () => { + const resp = await this.rippleApi.request({ + command: "account_tx", + account: this.shoutboxAddress, + forward: false, + }) + return resp.result.transactions.map((entry: any) => entry.tx) + } + + private submit = async (shoutHash: string) => { + const data = { + endpoint: 'submit', + data: shoutHash + } + + console.log("Submitting shout root hash", data) + const submitTx = await this.xrpio.writeRaw({data: JSON.stringify(data)}, this.shoutboxAddress, this.userWallet1.secret) + + console.log("submit TX @", submitTx) + + return submitTx + } + + public submitShout = async (shout: any) => { + console.log("writing shout data", shout) + const shoutHash = await this.xrpio.treeWrite(JSON.stringify(shout), this.userWallet1.address, this.userWallet2.secret) + console.log("shout data @ ", shoutHash) + return await this.submit(shoutHash) + } + + private parseMemos = async (memos: any) => { + const shouts = await Promise.all(memos + .map((memo: any) => { + if (!memo.Memo || !memo.Memo.MemoData) + return + + try { + return DataParser.parse('TxHash', hex_to_ascii(memo.Memo.MemoData)) + } catch (e) { + return + } + }) + .filter((hash: string) => hash != undefined) + .map((root_hash: string) => this.xrpio.treeRead([root_hash])) + ) + return shouts.map((jsonStr: string) => JSON.parse(jsonStr)) + } + + private loadHistory = async () => { + const raw_txs = await this.getTransactions() + return await this.parseMemos(raw_txs.flatMap((htx: any) => htx.Memos)) + } + + private subscribeTxs = async (callback: Function) => { + this.rippleApi.on('transaction', (tx: any) => callback(tx)) + await this.rippleApi.connection.request({ + command: 'subscribe', + accounts: [this.shoutboxAddress] + }) + } + + private listen = async () => { + await this.subscribeTxs(async (raw_tx: any) => { + const shouts = await this.parseMemos(raw_tx.transaction.Memos) + this.history.unshift(...shouts) + }) + } + + initialize = async () => { + this.userWallet1 = await makeTestnetWallet() + this.userWallet2 = await makeTestnetWallet() + + this.rippleApi = new xrpl.Client(xrpNode) + await this.rippleApi.connect() + + this.xrpio = new xrpIO(xrpNode); + await this.xrpio.connect() + + this.history = await this.loadHistory() + + await this.listen(); + } +} + +export function initShoutboxSvc(svc: ShoutboxDataService): () => Promise { + return svc.initialize; +} + +function hex_to_ascii(input: any) { + var hex = input.toString(); + var str = ''; + for (var n = 0; n < hex.length; n += 2) { + str += String.fromCharCode(parseInt(hex.substr(n, 2), 16)); + } + return str; +} \ No newline at end of file diff --git a/src/frontend/src/index.html b/src/frontend/src/index.html index 813faca..ca4bac1 100644 --- a/src/frontend/src/index.html +++ b/src/frontend/src/index.html @@ -10,8 +10,8 @@ - - + +