diff --git a/README.md b/README.md index 5168936..49964db 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,5 @@ - > This project was bootstrpped with the ![](!inkathon template). [/setup.md](setup instructions) + > This project was bootstrpped with the [!inkathon template](/SETUP.md) --- @@ -8,19 +8,18 @@ Whisper is an app where privacy focused individuals can have ephemeral conversations that disappears almost like a whisper, right after they leave. -[Live Demo](https://whisper-chat-git-main-od41.vercel.app/) +[Live Demo](https://blue-whisper.vercel.app/) ## How it works -1. Get some test tokens for aleph zero and accurast -2. Install your talisman wallet -3. Connect your wallet -4. Create a chatroom -5. Invite your friends +1. Get some test tokens for Aleph Zero or Accurast +2. Install a wallet([Talisman](https://talisman.xyz/) is a good option) +4. Create or join a chatroom +5. Invite your friends (if you created) 6. Talk and talk -7. Destroy chatroom and all messages +7. Delete chatroom and all messages [![Whisper cover photo](https://images.unsplash.com/photo-1576769267415-9642010aa962?q=80&w=1886&auto=format&fit=crop&ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D)](https://youtube.com) diff --git a/frontend/.env.local.example b/frontend/.env.local.example index accd13a..995ac85 100644 --- a/frontend/.env.local.example +++ b/frontend/.env.local.example @@ -16,4 +16,7 @@ NEXT_PUBLIC_DEFAULT_CHAIN=alephzero-testnet ## [Optional] Multiple supported chain identifers the frontend connects to ## IMPORTANT: It's mandatory to use double quotes in the array -# NEXT_PUBLIC_SUPPORTED_CHAINS=[ "development", "alephzero-testnet", "rococo", "shibuya" ] \ No newline at end of file +# NEXT_PUBLIC_SUPPORTED_CHAINS=[ "development", "alephzero-testnet", "rococo", "shibuya" ] + +## Accurast websocket url +# NEXT_PUBLIC_ACCU_DEV_WSS=wss://websocket-proxy.dev.gke.papers.tech/ \ No newline at end of file diff --git a/frontend/package.json b/frontend/package.json index 9fce7f3..2e92615 100644 --- a/frontend/package.json +++ b/frontend/package.json @@ -17,6 +17,7 @@ }, "dependencies": { "@727-ventures/typechain-types": "^1.1.2", + "@acurast/dapp": "^1.0.0", "@azns/resolver-core": "^1.6.0", "@azns/resolver-react": "^1.6.0", "@hookform/resolvers": "^3.3.4", diff --git a/frontend/src/config/environment.ts b/frontend/src/config/environment.ts index f3ed9c9..59d7551 100644 --- a/frontend/src/config/environment.ts +++ b/frontend/src/config/environment.ts @@ -22,4 +22,5 @@ export const env = { description: 'Lorem ipsum', }, ], + ACCU_DEV_WSS: process.env.NEXT_PUBLIC_ACCU_DEV_WSS!, } diff --git a/frontend/src/context/app-context.tsx b/frontend/src/context/app-context.tsx index c3b50a0..3c04245 100644 --- a/frontend/src/context/app-context.tsx +++ b/frontend/src/context/app-context.tsx @@ -3,6 +3,7 @@ import { createContext, useEffect, useState } from 'react' import { ContractIds } from '@/deployments/deployments' +import { useAccurast } from '@/deployments/use-accurast' import { contractQuery, decodeOutput, @@ -23,6 +24,7 @@ type AppContextProps = { inviteFriends: (participants: string[]) => Promise joinChatroom: (chatroomId: string) => Promise refreshMessages: () => Promise + viaAccurast: () => Promise messages: MessageProps[] chatroomId: string | undefined isAppLoading: boolean @@ -39,6 +41,7 @@ const defaultData: AppContextProps = { inviteFriends: async (participants: string[]) => {}, joinChatroom: async (chatroomId: string) => {}, refreshMessages: async () => {}, + viaAccurast: async () => {}, messages: [], chatroomId: undefined, isAppLoading: true, @@ -61,6 +64,7 @@ export function AppProvider({ children }: { children: React.ReactNode }) { // web3 state const { api, activeAccount, activeSigner } = useInkathon() const { contract } = useRegisteredContract(ContractIds.Chatroom) + const { id, send } = useAccurast() // set app as loaded useEffect(() => { @@ -260,6 +264,12 @@ export function AppProvider({ children }: { children: React.ReactNode }) { setIsMessagesLoading(false) } + // accurast + async function viaAccurast() { + // TODO additional testing & implementation + const res = await send(activeAccount?.address, '') + } + return ( { + const [acurastClient, setAcurastClient] = useState(null) + const [id, setId] = useState('') + const [keyPair, setKeyPair] = useState() + const [message, setMessage] = useState() + + useEffect(() => { + const init = async () => { + const acurast = new AcurastClient(DEV_WSS) + setAcurastClient(acurast) + + const keyPair = await crypto.subtle.generateKey( + { + name: 'ECDSA', + namedCurve: 'P-256', + }, + true, + ['sign'], + ) + + const [privateKeyRaw, publicKeyRaw] = await Promise.all([ + // @ts-expect-error can't find the argument that matches call + crypto.subtle + .exportKey('jwk', keyPair.privateKey) + .then((jwk) => Buffer.from(jwk.d, 'base64')), + crypto.subtle + .exportKey('raw', keyPair.publicKey) + .then((arrayBuffer) => Buffer.from(arrayBuffer)), + ]) + + const publicKeyCompressedSize = (publicKeyRaw.length - 1) / 2 + const publicKeyCompressed = Buffer.concat([ + new Uint8Array([publicKeyRaw[2 * publicKeyCompressedSize] % 2 ? 3 : 2]), + publicKeyRaw.subarray(1, publicKeyCompressedSize + 1), + ]) + const publicKeyHash = await crypto.subtle.digest('SHA-256', publicKeyCompressed) + setId(Buffer.from(publicKeyHash.slice(0, 16)).toString('hex')) + setKeyPair({ + // @ts-expect-error allow + privateKey: privateKeyRaw.toString('hex'), + publicKey: publicKeyRaw.toString('hex'), + }) + + return () => { + acurast.close() + } + } + + init() + }, []) + + const send = (recipient: any, payload: any) => { + acurastClient.send(recipient, payload) + } + + useEffect(() => { + if (acurastClient) { + acurastClient.onMessage((message: any) => { + setMessage({ + // @ts-expect-error allow + sender: Buffer.from(message.sender).toString('hex'), + recipient: Buffer.from(message.recipient).toString('hex'), + payload: Buffer.from(message.payload).toString('hex'), + }) + }) + } + }, [acurastClient]) + + return { id, keyPair, message, send } +} diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 0a9c58e..44b395c 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -98,6 +98,9 @@ importers: '@727-ventures/typechain-types': specifier: ^1.1.2 version: 1.1.2 + '@acurast/dapp': + specifier: ^1.0.0 + version: 1.0.0(ws@8.16.0) '@azns/resolver-core': specifier: ^1.6.0 version: 1.6.0(@polkadot/api-contract@10.11.2)(@polkadot/api@10.11.2)(@polkadot/types@10.11.2)(@polkadot/util-crypto@12.6.2)(@polkadot/util@12.6.2) @@ -291,6 +294,31 @@ packages: engines: {node: '>=0.10.0'} dev: true + /@acurast/dapp@1.0.0(ws@8.16.0): + resolution: {integrity: sha512-DxgNKHE3ia99cyUup4lF0nXp5MludIL9t2Ekby2LU0obNtFeVLq/O0K6gQaUjpgRfl2Z766tCppFlQ/bVR6j0A==} + dependencies: + '@acurast/transport-websocket': 1.0.0(ws@8.16.0) + buffer: 6.0.3 + transitivePeerDependencies: + - ws + dev: false + + /@acurast/transport-websocket@1.0.0(ws@8.16.0): + resolution: {integrity: sha512-0yOe/hzvFtYzgEYtXE0ZHjPFq56Onl2WkTuC4LjRwyYKIeTMGLe0JDwnXWMbiqZl107nBIE67vzDuoTe0IMsnQ==} + peerDependencies: + ws: ^8.13.0 + peerDependenciesMeta: + ws: + optional: true + dependencies: + '@stablelib/random': 1.0.2 + '@stablelib/sha256': 1.0.1 + buffer: 6.0.3 + elliptic: 6.5.5 + tslib: 2.6.2 + ws: 8.16.0 + dev: false + /@alloc/quick-lru@5.2.0: resolution: {integrity: sha512-UrcABB+4bUrFABwbluTIBErXwvbsU/V7TZWfmbgJfbkwiBuziS9gxdODUyuiecfdGQ85jglMW6juS3+z5TsKLw==} engines: {node: '>=10'} @@ -2675,6 +2703,39 @@ packages: /@scure/base@1.1.5: resolution: {integrity: sha512-Brj9FiG2W1MRQSTB212YVPRrcbjkv48FoZi/u4l/zds/ieRrqsh7aUf6CLwkAq61oKXr/ZlTzlY66gLIj3TFTQ==} + /@stablelib/binary@1.0.1: + resolution: {integrity: sha512-ClJWvmL6UBM/wjkvv/7m5VP3GMr9t0osr4yVgLZsLCOz4hGN9gIAFEqnJ0TsSMAN+n840nf2cHZnA5/KFqHC7Q==} + dependencies: + '@stablelib/int': 1.0.1 + dev: false + + /@stablelib/hash@1.0.1: + resolution: {integrity: sha512-eTPJc/stDkdtOcrNMZ6mcMK1e6yBbqRBaNW55XA1jU8w/7QdnCF0CmMmOD1m7VSkBR44PWrMHU2l6r8YEQHMgg==} + dev: false + + /@stablelib/int@1.0.1: + resolution: {integrity: sha512-byr69X/sDtDiIjIV6m4roLVWnNNlRGzsvxw+agj8CIEazqWGOQp2dTYgQhtyVXV9wpO6WyXRQUzLV/JRNumT2w==} + dev: false + + /@stablelib/random@1.0.2: + resolution: {integrity: sha512-rIsE83Xpb7clHPVRlBj8qNe5L8ISQOzjghYQm/dZ7VaM2KHYwMW5adjQjrzTZCchFnNCNhkwtnOBa9HTMJCI8w==} + dependencies: + '@stablelib/binary': 1.0.1 + '@stablelib/wipe': 1.0.1 + dev: false + + /@stablelib/sha256@1.0.1: + resolution: {integrity: sha512-GIIH3e6KH+91FqGV42Kcj71Uefd/QEe7Dy42sBTeqppXV95ggCcxLTk39bEr+lZfJmp+ghsR07J++ORkRELsBQ==} + dependencies: + '@stablelib/binary': 1.0.1 + '@stablelib/hash': 1.0.1 + '@stablelib/wipe': 1.0.1 + dev: false + + /@stablelib/wipe@1.0.1: + resolution: {integrity: sha512-WfqfX/eXGiAd3RJe4VU2snh/ZPwtSjLG4ynQ/vYzvghTh7dHFcI1wl+nrkWG6lGhukOxOsUHfv8dUXr58D0ayg==} + dev: false + /@substrate/connect-extension-protocol@1.0.1: resolution: {integrity: sha512-161JhCC1csjH3GE5mPLEd7HbWtwNSPJBg3p1Ksz9SFlTzj/bgEwudiRN2y5i0MoLGCIJRYKyKGMxVnd29PzNjg==} requiresBuild: true @@ -3294,7 +3355,6 @@ packages: /base64-js@1.5.1: resolution: {integrity: sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==} - dev: true /better-path-resolve@1.0.0: resolution: {integrity: sha512-pbnl5XzGBdrFU/wT4jqmJVPn2B6UHPBOhzMQkY/SPUPB6QtUXtmBHBIwCbXJol93mOpGMnQyP/+BB19q04xj7g==} @@ -3315,6 +3375,10 @@ packages: readable-stream: 3.6.2 dev: true + /bn.js@4.12.0: + resolution: {integrity: sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA==} + dev: false + /bn.js@5.2.1: resolution: {integrity: sha512-eXRvHzWyYPBuB4NBy0cmYQjGitUrtqwbvlzP3G6VFnNRbsZQIxQ10PbKKHt8gZ/HW/D/747aDl+QkDqg3KQLMQ==} @@ -3342,6 +3406,10 @@ packages: wcwidth: 1.0.1 dev: true + /brorand@1.1.0: + resolution: {integrity: sha512-cKV8tMCEpQs4hK/ik71d6LrPOnpkpGBR0wzxqr68g2m/LB2GxVYQroAjMJZRVM1Y4BCjCKc3vAamxSzOY2RP+w==} + dev: false + /browserslist@4.22.2: resolution: {integrity: sha512-0UgcrvQmBDvZHFGdYUehrCNIazki7/lUP3kkoi/r3YB2amZbFM9J43ZRkJTXBUZK4gmx56+Sqk9+Vs9mwZx9+A==} engines: {node: ^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7} @@ -3359,6 +3427,13 @@ packages: ieee754: 1.2.1 dev: true + /buffer@6.0.3: + resolution: {integrity: sha512-FTiCpNxtwiZZHEZbcbTIcZjERVICn9yq/pDFkTl95/AxzD1naBctN7YO68riM/gLSDY7sdrMby8hofADYuuqOA==} + dependencies: + base64-js: 1.5.1 + ieee754: 1.2.1 + dev: false + /bufferutil@4.0.8: resolution: {integrity: sha512-4T53u4PdgsXqKaIctwF8ifXlRTTmEPJ8iEPWFdGZvcf7sbwYo6FKFEX9eNNAnzFZ7EzJAQ3CJeOtCRA4rDp7Pw==} engines: {node: '>=6.14.2'} @@ -3842,6 +3917,18 @@ packages: /electron-to-chromium@1.4.643: resolution: {integrity: sha512-QHscvvS7gt155PtoRC0dR2ilhL8E9LHhfTQEq1uD5AL0524rBLAwpAREFH06f87/e45B9XkR6Ki5dbhbCsVEIg==} + /elliptic@6.5.5: + resolution: {integrity: sha512-7EjbcmUm17NQFu4Pmgmq2olYMj8nwMnpcddByChSUjArp8F5DQWcIcpriwO4ZToLNAJig0yiyjswfyGNje/ixw==} + dependencies: + bn.js: 4.12.0 + brorand: 1.1.0 + hash.js: 1.1.7 + hmac-drbg: 1.0.1 + inherits: 2.0.4 + minimalistic-assert: 1.0.1 + minimalistic-crypto-utils: 1.0.1 + dev: false + /emoji-regex@10.3.0: resolution: {integrity: sha512-QpLs9D9v9kArv4lfDEgg1X/gN5XLnf/A6l9cs8SPZLRZR3ZkY9+kwIQTxm+fsSej5UMYGE8fdoaZVIBlqG0XTw==} dev: true @@ -4719,12 +4806,27 @@ packages: has-symbols: 1.0.3 dev: true + /hash.js@1.1.7: + resolution: {integrity: sha512-taOaskGt4z4SOANNseOviYDvjEJinIkRgmp7LbKP2YTTmVxWBl87s/uzK9r+44BclBSp2X7K1hqeNfz9JbBeXA==} + dependencies: + inherits: 2.0.4 + minimalistic-assert: 1.0.1 + dev: false + /hasown@2.0.0: resolution: {integrity: sha512-vUptKVTpIJhcczKBbgnS+RtcuYMB8+oNzPK2/Hp3hanz8JmpATdmmgLgSaadVREkDm+e2giHwY3ZRkyjSIDDFA==} engines: {node: '>= 0.4'} dependencies: function-bind: 1.1.2 + /hmac-drbg@1.0.1: + resolution: {integrity: sha512-Tti3gMqLdZfhOQY1Mzf/AanLiqh1WTiJgEj26ZuYQ9fbkLomzGchCws4FyrSd4VkpBfiNhaE1On+lOz894jvXg==} + dependencies: + hash.js: 1.1.7 + minimalistic-assert: 1.0.1 + minimalistic-crypto-utils: 1.0.1 + dev: false + /hosted-git-info@2.8.9: resolution: {integrity: sha512-mxIDAb9Lsm6DoOJ7xH+5+X4y1LU/4Hi50L9C5sIswK3JzULS4bwk1FvjdBgvYR4bzT4tuUQiC15FE2f5HbLvYw==} dev: true @@ -4787,7 +4889,6 @@ packages: /ieee754@1.2.1: resolution: {integrity: sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==} - dev: true /ignore@5.3.1: resolution: {integrity: sha512-5Fytz/IraMjqpwfd34ke28PTVMjZjJG2MPn5t7OE4eUCUNf8BAa7b5WUS9/Qvr6mwOQS7Mk6vdsMno5he+T8Xw==} @@ -4820,7 +4921,6 @@ packages: /inherits@2.0.4: resolution: {integrity: sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==} - dev: true /internal-slot@1.0.6: resolution: {integrity: sha512-Xj6dv+PsbtwyPpEflsejS+oIZxmMlV44zAhG479uYu89MsjcYOhCFnNyKrkJrihbsiasQyY0afoCl/9BLR65bg==} @@ -5441,6 +5541,14 @@ packages: engines: {node: '>=4'} dev: true + /minimalistic-assert@1.0.1: + resolution: {integrity: sha512-UtJcAD4yEaGtjPezWuO9wC4nwUnVH/8/Im3yEHQP4b67cXlD/Qr9hdITCU1xDbSEXg2XKNaP8jsReV7vQd00/A==} + dev: false + + /minimalistic-crypto-utils@1.0.1: + resolution: {integrity: sha512-JIYlbt6g8i5jKfJ3xz7rF0LXmv2TkDxBLUkiBeZ7bAx4GnnNMr8xFpGnOxn6GhTEHx3SjRrZEoU+j04prX1ktg==} + dev: false + /minimatch@3.1.2: resolution: {integrity: sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==} dependencies: