From 4c17f46376f998a0788e992eeae03272258094a8 Mon Sep 17 00:00:00 2001 From: Tan Le Date: Thu, 30 Nov 2023 19:18:35 +0700 Subject: [PATCH 01/21] feat: add ping pong messages between dapps and walless on tezos --- apps/web/package.json | 1 + apps/web/scripts/content/index.ts | 2 + apps/web/scripts/content/messaging.ts | 2 +- apps/web/scripts/content/tezos.ts | 40 +++ yarn.lock | 381 +++++++++++++++++++++++++- 5 files changed, 414 insertions(+), 12 deletions(-) create mode 100644 apps/web/scripts/content/tezos.ts diff --git a/apps/web/package.json b/apps/web/package.json index 2b89afe03..ee7a8f893 100644 --- a/apps/web/package.json +++ b/apps/web/package.json @@ -17,6 +17,7 @@ "postinstall": "yarn batch" }, "dependencies": { + "@airgap/beacon-sdk": "^4.0.12", "@metaplex-foundation/js": "0.18.3", "@mysten/sui.js": "0.34.0", "@solana/spl-token": "0.3.7", diff --git a/apps/web/scripts/content/index.ts b/apps/web/scripts/content/index.ts index 83b2a27ee..ff175edd3 100644 --- a/apps/web/scripts/content/index.ts +++ b/apps/web/scripts/content/index.ts @@ -1,3 +1,5 @@ +import './tezos'; + import { initializeMessaging } from './messaging'; import { injectScript } from './utils'; diff --git a/apps/web/scripts/content/messaging.ts b/apps/web/scripts/content/messaging.ts index 99d1c1aad..533bd8a96 100644 --- a/apps/web/scripts/content/messaging.ts +++ b/apps/web/scripts/content/messaging.ts @@ -1,6 +1,6 @@ import { createMessenger } from '@walless/messaging'; -const messenger = createMessenger(); +export const messenger = createMessenger(); export const initializeMessaging = async () => { window.postMessage({ from: 'walless-content-script-loaded' }); diff --git a/apps/web/scripts/content/tezos.ts b/apps/web/scripts/content/tezos.ts new file mode 100644 index 000000000..4dde4f7c8 --- /dev/null +++ b/apps/web/scripts/content/tezos.ts @@ -0,0 +1,40 @@ +import { ExtensionMessageTarget, Serializer } from '@airgap/beacon-sdk'; + +import { messenger } from './messaging'; + +const WALLESS_TEZOS = { + id: chrome.runtime.id, + name: 'Walless', + iconUrl: 'https://walless.io/img/walless-icon.svg', +}; + +window.addEventListener('message', async (e) => { + console.log('on message', e.data); + if ( + e.data?.target !== ExtensionMessageTarget.EXTENSION || + (e.data?.targetId && e.data?.targetId !== WALLESS_TEZOS.id) + ) { + return; + } + + if (e.data?.payload === 'ping') { + window.postMessage({ + target: ExtensionMessageTarget.PAGE, + payload: 'pong', + sender: WALLESS_TEZOS, + } as never); + } else { + let payload; + const rawPayload = e.data?.payload; + if (typeof rawPayload === 'string') { + payload = await new Serializer().deserialize(rawPayload); + } + + const res = await messenger.request('kernel', { + from: 'walless@sdk', + payload, + }); + + window.postMessage(res); + } +}); diff --git a/yarn.lock b/yarn.lock index 588e76784..2726274f3 100644 --- a/yarn.lock +++ b/yarn.lock @@ -19,6 +19,153 @@ __metadata: languageName: node linkType: hard +"@airgap/beacon-blockchain-substrate@npm:4.0.12": + version: 4.0.12 + resolution: "@airgap/beacon-blockchain-substrate@npm:4.0.12" + dependencies: + "@airgap/beacon-types": 4.0.12 + "@airgap/beacon-ui": 4.0.12 + checksum: 31a812aa0a469a5076164553328c9623381705ab67ed9a68c09375fe11cb3fbe2cf92aa41971470da99a7b4667daa8bae40afb0e9b628d46ae117696790acef4 + languageName: node + linkType: hard + +"@airgap/beacon-blockchain-tezos@npm:4.0.12": + version: 4.0.12 + resolution: "@airgap/beacon-blockchain-tezos@npm:4.0.12" + dependencies: + "@airgap/beacon-types": 4.0.12 + "@airgap/beacon-ui": 4.0.12 + checksum: abdd3196f9944d564e5f0a691367d0df1a3b552a567b5b28348cbe5b186ba922c2d5ebc344594fe4d54df5e39358a839e6a7b45044e85919a5eab09bb61270a8 + languageName: node + linkType: hard + +"@airgap/beacon-core@npm:4.0.12": + version: 4.0.12 + resolution: "@airgap/beacon-core@npm:4.0.12" + dependencies: + "@airgap/beacon-types": 4.0.12 + "@airgap/beacon-utils": 4.0.12 + "@stablelib/ed25519": ^1.0.3 + "@stablelib/nacl": ^1.0.4 + "@stablelib/utf8": ^1.0.1 + "@stablelib/x25519-session": ^1.0.4 + bs58check: 2.1.2 + checksum: 027607517641c64f119031d524b8fbb6219dddf923f1024e1b9fdce0ef8c734a2a29813c6e47613de18e375f7e6ea6213642c06c9b3daaca0e3affb656cb5187 + languageName: node + linkType: hard + +"@airgap/beacon-dapp@npm:4.0.12": + version: 4.0.12 + resolution: "@airgap/beacon-dapp@npm:4.0.12" + dependencies: + "@airgap/beacon-core": 4.0.12 + "@airgap/beacon-transport-matrix": 4.0.12 + "@airgap/beacon-transport-postmessage": 4.0.12 + "@airgap/beacon-transport-walletconnect": 4.0.12 + "@airgap/beacon-ui": 4.0.12 + checksum: 8456db2f7ab71ced915290f965f9d9f9bce41b7a1e159db25cfeb104c8dab0366c85772466da1028a9375bdc1713929f9be81d2e52c79aa9451ecbada97d4147 + languageName: node + linkType: hard + +"@airgap/beacon-sdk@npm:^4.0.12": + version: 4.0.12 + resolution: "@airgap/beacon-sdk@npm:4.0.12" + dependencies: + "@airgap/beacon-blockchain-substrate": 4.0.12 + "@airgap/beacon-blockchain-tezos": 4.0.12 + "@airgap/beacon-core": 4.0.12 + "@airgap/beacon-dapp": 4.0.12 + "@airgap/beacon-transport-matrix": 4.0.12 + "@airgap/beacon-transport-postmessage": 4.0.12 + "@airgap/beacon-types": 4.0.12 + "@airgap/beacon-ui": 4.0.12 + "@airgap/beacon-utils": 4.0.12 + "@airgap/beacon-wallet": 4.0.12 + checksum: 97208f2e7b0ec59c99457c84b876b1822bee2a4398039005c033a9bbafa587e8f9db908b19779f592a6bfc7bdb45cf828963c8b93cac5455ea3abbf640b43e9c + languageName: node + linkType: hard + +"@airgap/beacon-transport-matrix@npm:4.0.12": + version: 4.0.12 + resolution: "@airgap/beacon-transport-matrix@npm:4.0.12" + dependencies: + "@airgap/beacon-core": 4.0.12 + "@airgap/beacon-utils": 4.0.12 + axios: 0.24.0 + checksum: 7c375c93c07fa332b63f1c6203abb49d5ae72616dbdcf7ed7bf0a5d0ccf2138d2ffc2b5bba183c8319450522d5b6525b5c3a5a576eec6b23c0841b9456cf1e78 + languageName: node + linkType: hard + +"@airgap/beacon-transport-postmessage@npm:4.0.12": + version: 4.0.12 + resolution: "@airgap/beacon-transport-postmessage@npm:4.0.12" + dependencies: + "@airgap/beacon-core": 4.0.12 + "@airgap/beacon-types": 4.0.12 + "@airgap/beacon-utils": 4.0.12 + checksum: 3ababc0fbc5ebc821c07f710087426d2e14c4406da10cfa13ed42470483e4b7506ca5194588b0b45191859efa492982b7e8236917ba775f9fa7b9e2f3af8b380 + languageName: node + linkType: hard + +"@airgap/beacon-transport-walletconnect@npm:4.0.12": + version: 4.0.12 + resolution: "@airgap/beacon-transport-walletconnect@npm:4.0.12" + dependencies: + "@airgap/beacon-core": 4.0.12 + "@airgap/beacon-types": 4.0.12 + "@airgap/beacon-utils": 4.0.12 + "@walletconnect/sign-client": 2.7.0 + checksum: 1c6a569d033e7fee67b5d5a71d82590829fba3be4938923aecba3431e60d672248fc902428fe1db024f6a681cf120ac2af173cddcaeb204d7686008e1c5b4e7e + languageName: node + linkType: hard + +"@airgap/beacon-types@npm:4.0.12": + version: 4.0.12 + resolution: "@airgap/beacon-types@npm:4.0.12" + dependencies: + "@types/chrome": 0.0.163 + checksum: 9c7678f91336b32aeadba0d8880d635e58962b754539db4904bd6719811333aadb2512712f8994e43fdd9c6bd7084a5da9b4a69e5b3531b32a10b9f31d08ea16 + languageName: node + linkType: hard + +"@airgap/beacon-ui@npm:4.0.12": + version: 4.0.12 + resolution: "@airgap/beacon-ui@npm:4.0.12" + dependencies: + "@airgap/beacon-core": 4.0.12 + "@airgap/beacon-transport-postmessage": 4.0.12 + "@airgap/beacon-types": 4.0.12 + "@airgap/beacon-utils": 4.0.12 + qrcode-svg: ^1.1.0 + solid-js: ^1.6.6 + checksum: 9e4251681982729cfd41aac1ea1ea3e7b8af005125a5ea5f1488ec19ce7b16d081a2f3fe445694f899dda0415fef1a541ed510c8350c886fc290ff713b74c848 + languageName: node + linkType: hard + +"@airgap/beacon-utils@npm:4.0.12": + version: 4.0.12 + resolution: "@airgap/beacon-utils@npm:4.0.12" + dependencies: + "@stablelib/ed25519": ^1.0.3 + "@stablelib/nacl": ^1.0.3 + "@stablelib/random": ^1.0.2 + "@stablelib/utf8": ^1.0.1 + bs58check: 2.1.2 + checksum: 735ecb577978964e1976afa34e0ac3709a3f0a8fe9e9873652e07f9fbdd586fab65468218dcff3942389839dba1a638cdd34be110d69cdcee9794bed7d034c31 + languageName: node + linkType: hard + +"@airgap/beacon-wallet@npm:4.0.12": + version: 4.0.12 + resolution: "@airgap/beacon-wallet@npm:4.0.12" + dependencies: + "@airgap/beacon-core": 4.0.12 + "@airgap/beacon-transport-matrix": 4.0.12 + "@airgap/beacon-transport-postmessage": 4.0.12 + checksum: b41bc19f163b87a6657f2e6443de96bfbc5fb356283c78ee12c14cbf42d35779f31deb08f9296136a84738db379f6b92af5e0c554eb79d87d6b6d5d7a471cd7c + languageName: node + linkType: hard + "@alcalzone/ansi-tokenize@npm:^0.1.3": version: 0.1.3 resolution: "@alcalzone/ansi-tokenize@npm:0.1.3" @@ -8499,7 +8646,7 @@ __metadata: languageName: node linkType: hard -"@stablelib/ed25519@npm:^1.0.3": +"@stablelib/ed25519@npm:^1.0.2, @stablelib/ed25519@npm:^1.0.3": version: 1.0.3 resolution: "@stablelib/ed25519@npm:1.0.3" dependencies: @@ -8555,7 +8702,7 @@ __metadata: languageName: node linkType: hard -"@stablelib/nacl@npm:^1.0.4": +"@stablelib/nacl@npm:^1.0.3, @stablelib/nacl@npm:^1.0.4": version: 1.0.4 resolution: "@stablelib/nacl@npm:1.0.4" dependencies: @@ -8590,7 +8737,7 @@ __metadata: languageName: node linkType: hard -"@stablelib/random@npm:^1.0.2": +"@stablelib/random@npm:^1.0.1, @stablelib/random@npm:^1.0.2": version: 1.0.2 resolution: "@stablelib/random@npm:1.0.2" dependencies: @@ -8633,6 +8780,13 @@ __metadata: languageName: node linkType: hard +"@stablelib/utf8@npm:^1.0.1": + version: 1.0.1 + resolution: "@stablelib/utf8@npm:1.0.1" + checksum: 098d9446f38a641a8ee265a7fc3467fefd561fc46ca65e1216c1df7a9b4d004e616347ce79f4b83d62e944f0f91d6be4af029ad0b027a20c3271951921ebfac5 + languageName: node + linkType: hard + "@stablelib/wipe@npm:^1.0.1": version: 1.0.1 resolution: "@stablelib/wipe@npm:1.0.1" @@ -8640,6 +8794,19 @@ __metadata: languageName: node linkType: hard +"@stablelib/x25519-session@npm:^1.0.4": + version: 1.0.4 + resolution: "@stablelib/x25519-session@npm:1.0.4" + dependencies: + "@stablelib/blake2b": ^1.0.1 + "@stablelib/keyagreement": ^1.0.1 + "@stablelib/random": ^1.0.2 + "@stablelib/wipe": ^1.0.1 + "@stablelib/x25519": ^1.0.3 + checksum: f1c74680174cfb4bb00b091ea53b3e1da4b838147fae7d2fc258427472fa400a4dbbfc0ed3a14f31ac7d35e1e704369f5856a97968600c15de0b061487790f1e + languageName: node + linkType: hard + "@stablelib/x25519@npm:^1.0.3": version: 1.0.3 resolution: "@stablelib/x25519@npm:1.0.3" @@ -10756,6 +10923,16 @@ __metadata: languageName: node linkType: hard +"@types/chrome@npm:0.0.163": + version: 0.0.163 + resolution: "@types/chrome@npm:0.0.163" + dependencies: + "@types/filesystem": "*" + "@types/har-format": "*" + checksum: e47d99d7c581a4dc70c30ae5e6e2980666b25bbf098c6eaa9fd3abd6e1686f0acf2e53bf2c8e7bba339c4639df0828d45d10fa9d66f669d9ef2bb1314b6a9500 + languageName: node + linkType: hard + "@types/chrome@npm:^0.0.231": version: 0.0.231 resolution: "@types/chrome@npm:0.0.231" @@ -11789,6 +11966,7 @@ __metadata: version: 0.0.0-use.local resolution: "@walless/web@workspace:apps/web" dependencies: + "@airgap/beacon-sdk": ^4.0.12 "@metacraft/cli-web3-polyfills": ^0.0.7 "@metaplex-foundation/js": 0.18.3 "@mysten/sui.js": 0.34.0 @@ -11888,6 +12066,38 @@ __metadata: languageName: node linkType: hard +"@walletconnect/core@npm:2.7.0": + version: 2.7.0 + resolution: "@walletconnect/core@npm:2.7.0" + dependencies: + "@walletconnect/heartbeat": 1.2.1 + "@walletconnect/jsonrpc-provider": ^1.0.12 + "@walletconnect/jsonrpc-utils": ^1.0.7 + "@walletconnect/jsonrpc-ws-connection": ^1.0.11 + "@walletconnect/keyvaluestorage": ^1.0.2 + "@walletconnect/logger": ^2.0.1 + "@walletconnect/relay-api": ^1.0.9 + "@walletconnect/relay-auth": ^1.0.4 + "@walletconnect/safe-json": ^1.0.2 + "@walletconnect/time": ^1.0.2 + "@walletconnect/types": 2.7.0 + "@walletconnect/utils": 2.7.0 + events: ^3.3.0 + lodash.isequal: 4.5.0 + uint8arrays: ^3.1.0 + checksum: 86017de59ef2fd48638897878aad109cb43b2bf40ec4c172972389e6569eb3228fe662ae022e345f38432b890d0b39059cc5fda3f3607f8e9024b587b26a5d70 + languageName: node + linkType: hard + +"@walletconnect/environment@npm:^1.0.1": + version: 1.0.1 + resolution: "@walletconnect/environment@npm:1.0.1" + dependencies: + tslib: 1.14.1 + checksum: a18731d857bdca73910147e59992cef3c6e292c37ab3d3013307bd706f06cb216aa804f0f48b25a78df6493ad8127e633629f4b50acb4f69d3765d6ac0524f68 + languageName: node + linkType: hard + "@walletconnect/events@npm:^1.0.1": version: 1.0.1 resolution: "@walletconnect/events@npm:1.0.1" @@ -11909,7 +12119,18 @@ __metadata: languageName: node linkType: hard -"@walletconnect/jsonrpc-types@npm:1.0.3, @walletconnect/jsonrpc-types@npm:^1.0.2": +"@walletconnect/jsonrpc-provider@npm:^1.0.12": + version: 1.0.13 + resolution: "@walletconnect/jsonrpc-provider@npm:1.0.13" + dependencies: + "@walletconnect/jsonrpc-utils": ^1.0.8 + "@walletconnect/safe-json": ^1.0.2 + tslib: 1.14.1 + checksum: 497dfdd9f988432f171bc98336f3583c679059f0a166f95d6e51c8e1937c17abd9a5fd3aadfcebf6964bae14edd1e05fb0453e370d6e3bbc7ff4919fcad7c478 + languageName: node + linkType: hard + +"@walletconnect/jsonrpc-types@npm:1.0.3, @walletconnect/jsonrpc-types@npm:^1.0.2, @walletconnect/jsonrpc-types@npm:^1.0.3": version: 1.0.3 resolution: "@walletconnect/jsonrpc-types@npm:1.0.3" dependencies: @@ -11919,7 +12140,30 @@ __metadata: languageName: node linkType: hard -"@walletconnect/keyvaluestorage@npm:^1.1.1": +"@walletconnect/jsonrpc-utils@npm:^1.0.6, @walletconnect/jsonrpc-utils@npm:^1.0.7, @walletconnect/jsonrpc-utils@npm:^1.0.8": + version: 1.0.8 + resolution: "@walletconnect/jsonrpc-utils@npm:1.0.8" + dependencies: + "@walletconnect/environment": ^1.0.1 + "@walletconnect/jsonrpc-types": ^1.0.3 + tslib: 1.14.1 + checksum: f43a85dfce8150c3e3d1f009e8d8241ab8e10b026ea435f0918edf4db6b3a17586ba9d9c54a93cc61e4d3c685611e5bd5954fc377a581af503acd38e6d84c2ef + languageName: node + linkType: hard + +"@walletconnect/jsonrpc-ws-connection@npm:^1.0.11": + version: 1.0.14 + resolution: "@walletconnect/jsonrpc-ws-connection@npm:1.0.14" + dependencies: + "@walletconnect/jsonrpc-utils": ^1.0.6 + "@walletconnect/safe-json": ^1.0.2 + events: ^3.3.0 + ws: ^7.5.1 + checksum: a401e60b19390098183ef1b2a7b3e15c4dd3c64f9ac87fd2bbc0ae1f7fb31539ba542374ca021193efc4a2ae59fa3b04e588aed98cdf5c364f50524403d50f9f + languageName: node + linkType: hard + +"@walletconnect/keyvaluestorage@npm:^1.0.2, @walletconnect/keyvaluestorage@npm:^1.1.1": version: 1.1.1 resolution: "@walletconnect/keyvaluestorage@npm:1.1.1" dependencies: @@ -11964,6 +12208,20 @@ __metadata: languageName: node linkType: hard +"@walletconnect/relay-auth@npm:^1.0.4": + version: 1.0.4 + resolution: "@walletconnect/relay-auth@npm:1.0.4" + dependencies: + "@stablelib/ed25519": ^1.0.2 + "@stablelib/random": ^1.0.1 + "@walletconnect/safe-json": ^1.0.1 + "@walletconnect/time": ^1.0.2 + tslib: 1.14.1 + uint8arrays: ^3.0.0 + checksum: 35b3229d7b57e74fdb8fe6827d8dd8291dc60bacda880a57b2acb47a34d38f12be46c971c9eff361eb4073e896648b550de7a7a3852ef3752f9619c08dfba891 + languageName: node + linkType: hard + "@walletconnect/safe-json@npm:^1.0.1, @walletconnect/safe-json@npm:^1.0.2": version: 1.0.2 resolution: "@walletconnect/safe-json@npm:1.0.2" @@ -11973,6 +12231,23 @@ __metadata: languageName: node linkType: hard +"@walletconnect/sign-client@npm:2.7.0": + version: 2.7.0 + resolution: "@walletconnect/sign-client@npm:2.7.0" + dependencies: + "@walletconnect/core": 2.7.0 + "@walletconnect/events": ^1.0.1 + "@walletconnect/heartbeat": 1.2.1 + "@walletconnect/jsonrpc-utils": ^1.0.7 + "@walletconnect/logger": ^2.0.1 + "@walletconnect/time": ^1.0.2 + "@walletconnect/types": 2.7.0 + "@walletconnect/utils": 2.7.0 + events: ^3.3.0 + checksum: 85f6ca56d481616202cedec6e9c8af39e21d7d1ad9c021d54a4831d6b9cf71d684a00049474f8368a09c75c4b9425006d73fbfd6d8ac99f3ec23038b01522564 + languageName: node + linkType: hard + "@walletconnect/time@npm:^1.0.2": version: 1.0.2 resolution: "@walletconnect/time@npm:1.0.2" @@ -11996,6 +12271,43 @@ __metadata: languageName: node linkType: hard +"@walletconnect/types@npm:2.7.0": + version: 2.7.0 + resolution: "@walletconnect/types@npm:2.7.0" + dependencies: + "@walletconnect/events": ^1.0.1 + "@walletconnect/heartbeat": 1.2.1 + "@walletconnect/jsonrpc-types": ^1.0.2 + "@walletconnect/keyvaluestorage": ^1.0.2 + "@walletconnect/logger": ^2.0.1 + events: ^3.3.0 + checksum: 3380e52fdcb481c8f4ce048b5d7eb7b8af0ac33d34afcca292022b1e443cbadba2235a0d9a489705515cfcb5f42ab3ee341f41c986e3ad23d28fb8472a31c51a + languageName: node + linkType: hard + +"@walletconnect/utils@npm:2.7.0": + version: 2.7.0 + resolution: "@walletconnect/utils@npm:2.7.0" + dependencies: + "@stablelib/chacha20poly1305": 1.0.1 + "@stablelib/hkdf": 1.0.1 + "@stablelib/random": ^1.0.2 + "@stablelib/sha256": 1.0.1 + "@stablelib/x25519": ^1.0.3 + "@walletconnect/jsonrpc-utils": ^1.0.7 + "@walletconnect/relay-api": ^1.0.9 + "@walletconnect/safe-json": ^1.0.2 + "@walletconnect/time": ^1.0.2 + "@walletconnect/types": 2.7.0 + "@walletconnect/window-getters": ^1.0.1 + "@walletconnect/window-metadata": ^1.0.1 + detect-browser: 5.3.0 + query-string: 7.1.1 + uint8arrays: ^3.1.0 + checksum: 10920058ab4a0455b0aab85fef162fef0d02eccf9e963731b922f1a72d80645ea8dca5b0ed3a1d2299b3c619d173f93078496762cc4324990a578047e1acc571 + languageName: node + linkType: hard + "@walletconnect/utils@npm:^2.5.2": version: 2.10.5 resolution: "@walletconnect/utils@npm:2.10.5" @@ -13247,6 +13559,15 @@ __metadata: languageName: node linkType: hard +"axios@npm:0.24.0": + version: 0.24.0 + resolution: "axios@npm:0.24.0" + dependencies: + follow-redirects: ^1.14.4 + checksum: 468cf496c08a6aadfb7e699bebdac02851e3043d4e7d282350804ea8900e30d368daa6e3cd4ab83b8ddb5a3b1e17a5a21ada13fc9cebd27b74828f47a4236316 + languageName: node + linkType: hard + "axios@npm:0.27.2": version: 0.27.2 resolution: "axios@npm:0.27.2" @@ -13914,7 +14235,7 @@ __metadata: languageName: node linkType: hard -"bs58check@npm:^2.1.2": +"bs58check@npm:2.1.2, bs58check@npm:^2.1.2": version: 2.1.2 resolution: "bs58check@npm:2.1.2" dependencies: @@ -15300,7 +15621,7 @@ __metadata: languageName: node linkType: hard -"csstype@npm:^3.0.2": +"csstype@npm:^3.0.2, csstype@npm:^3.1.0": version: 3.1.2 resolution: "csstype@npm:3.1.2" checksum: e1a52e6c25c1314d6beef5168da704ab29c5186b877c07d822bd0806717d9a265e8493a2e35ca7e68d0f5d472d43fac1cdce70fd79fd0853dff81f3028d857b5 @@ -15407,7 +15728,7 @@ __metadata: languageName: node linkType: hard -"decode-uri-component@npm:^0.2.2": +"decode-uri-component@npm:^0.2.0, decode-uri-component@npm:^0.2.2": version: 0.2.2 resolution: "decode-uri-component@npm:0.2.2" checksum: 95476a7d28f267292ce745eac3524a9079058bbb35767b76e3ee87d42e34cd0275d2eb19d9d08c3e167f97556e8a2872747f5e65cbebcac8b0c98d83e285f139 @@ -17548,7 +17869,7 @@ __metadata: languageName: node linkType: hard -"follow-redirects@npm:^1.14.0, follow-redirects@npm:^1.14.7, follow-redirects@npm:^1.14.8, follow-redirects@npm:^1.14.9, follow-redirects@npm:^1.15.0": +"follow-redirects@npm:^1.14.0, follow-redirects@npm:^1.14.4, follow-redirects@npm:^1.14.7, follow-redirects@npm:^1.14.8, follow-redirects@npm:^1.14.9, follow-redirects@npm:^1.15.0": version: 1.15.3 resolution: "follow-redirects@npm:1.15.3" peerDependenciesMeta: @@ -20804,7 +21125,7 @@ __metadata: languageName: node linkType: hard -"lodash.isequal@npm:^4.5.0": +"lodash.isequal@npm:4.5.0, lodash.isequal@npm:^4.5.0": version: 4.5.0 resolution: "lodash.isequal@npm:4.5.0" checksum: da27515dc5230eb1140ba65ff8de3613649620e8656b19a6270afe4866b7bd461d9ba2ac8a48dcc57f7adac4ee80e1de9f965d89d4d81a0ad52bb3eec2609644 @@ -24045,6 +24366,15 @@ __metadata: languageName: node linkType: hard +"qrcode-svg@npm:^1.1.0": + version: 1.1.0 + resolution: "qrcode-svg@npm:1.1.0" + bin: + qrcode-svg: bin/qrcode-svg.js + checksum: 07f9dcdea55fe11a5264aad6c576ab91a37968bace6997d8cde868aeb8dfb87fd3fb352715ee6f8f26a732231c194af5e2b8fa550103abdb20ed5c8ad0a1bd3e + languageName: node + linkType: hard + "qrcode@npm:^1.5.1": version: 1.5.3 resolution: "qrcode@npm:1.5.3" @@ -24077,6 +24407,18 @@ __metadata: languageName: node linkType: hard +"query-string@npm:7.1.1": + version: 7.1.1 + resolution: "query-string@npm:7.1.1" + dependencies: + decode-uri-component: ^0.2.0 + filter-obj: ^1.1.0 + split-on-first: ^1.0.0 + strict-uri-encode: ^2.0.0 + checksum: b227d1f588ae93f9f0ad078c6b811295fa151dc5a160a03bb2bac5fa0e6919cb1daa570aad1d288e77c8e89fde5362ba505b1014e6e793da9b1e885b59a690a6 + languageName: node + linkType: hard + "query-string@npm:7.1.3, query-string@npm:^7.1.3": version: 7.1.3 resolution: "query-string@npm:7.1.3" @@ -25608,6 +25950,13 @@ __metadata: languageName: node linkType: hard +"seroval@npm:^0.14.1": + version: 0.14.1 + resolution: "seroval@npm:0.14.1" + checksum: 58f4ceabb6b1a56d4703ba081cc62950c6224e4dbcb336996eb31184e9ce0955889eab144803a651aefcd1af35c0d25d9c0cde100b66b8373268fdba60b7327b + languageName: node + linkType: hard + "serve-static@npm:1.15.0, serve-static@npm:^1.13.1": version: 1.15.0 resolution: "serve-static@npm:1.15.0" @@ -25962,6 +26311,16 @@ __metadata: languageName: node linkType: hard +"solid-js@npm:^1.6.6": + version: 1.8.6 + resolution: "solid-js@npm:1.8.6" + dependencies: + csstype: ^3.1.0 + seroval: ^0.14.1 + checksum: 78d0ba89cc46a74eb4c60d9e620432c9c1499523b13357b386de2334300dec617b6b5f0ce53c90eedf9e7a83fbbfd5f286d0a5ee85d0ff2530ddabc6bc6615b1 + languageName: node + linkType: hard + "sonic-boom@npm:^2.2.1": version: 2.8.0 resolution: "sonic-boom@npm:2.8.0" @@ -27466,7 +27825,7 @@ __metadata: languageName: node linkType: hard -"uint8arrays@npm:^3.1.0": +"uint8arrays@npm:^3.0.0, uint8arrays@npm:^3.1.0": version: 3.1.1 resolution: "uint8arrays@npm:3.1.1" dependencies: From 04ccbd6f6dead4db050e39162cd4448cbcb388d3 Mon Sep 17 00:00:00 2001 From: Tan Le Date: Wed, 6 Dec 2023 12:49:11 +0700 Subject: [PATCH 02/21] feat: handle pairing request on tezos --- apps/web/package.json | 1 + apps/web/scripts/content/tezos.ts | 75 ++++++++++++++++++++++++------- apps/web/scripts/content/utils.ts | 11 +++++ yarn.lock | 6 ++- 4 files changed, 76 insertions(+), 17 deletions(-) diff --git a/apps/web/package.json b/apps/web/package.json index ee7a8f893..ac6f0487f 100644 --- a/apps/web/package.json +++ b/apps/web/package.json @@ -18,6 +18,7 @@ }, "dependencies": { "@airgap/beacon-sdk": "^4.0.12", + "@airgap/beacon-utils": "^4.0.12", "@metaplex-foundation/js": "0.18.3", "@mysten/sui.js": "0.34.0", "@solana/spl-token": "0.3.7", diff --git a/apps/web/scripts/content/tezos.ts b/apps/web/scripts/content/tezos.ts index 4dde4f7c8..1c1c3881d 100644 --- a/apps/web/scripts/content/tezos.ts +++ b/apps/web/scripts/content/tezos.ts @@ -1,15 +1,30 @@ -import { ExtensionMessageTarget, Serializer } from '@airgap/beacon-sdk'; +import type { + PostMessagePairingRequest, + PostMessagePairingResponse, +} from '@airgap/beacon-sdk'; +import { ExtensionMessageTarget } from '@airgap/beacon-sdk'; +import { sealCryptobox } from '@airgap/beacon-utils'; import { messenger } from './messaging'; +const TEZOS_PAIRING_REQUEST = 'postmessage-pairing-request'; +const TEZOS_PAIRING_RESPONSE = 'postmessage-pairing-response'; + +import { generateKeyPair } from '@walless/crypto/utils/p2p'; + +import { deserialize } from './utils'; + const WALLESS_TEZOS = { id: chrome.runtime.id, name: 'Walless', iconUrl: 'https://walless.io/img/walless-icon.svg', + appUrl: 'https://walless.io', + version: '1.0.0', }; +const keypair = generateKeyPair(); + window.addEventListener('message', async (e) => { - console.log('on message', e.data); if ( e.data?.target !== ExtensionMessageTarget.EXTENSION || (e.data?.targetId && e.data?.targetId !== WALLESS_TEZOS.id) @@ -18,23 +33,51 @@ window.addEventListener('message', async (e) => { } if (e.data?.payload === 'ping') { - window.postMessage({ - target: ExtensionMessageTarget.PAGE, - payload: 'pong', - sender: WALLESS_TEZOS, - } as never); + return handlePingPong(); } else { - let payload; - const rawPayload = e.data?.payload; - if (typeof rawPayload === 'string') { - payload = await new Serializer().deserialize(rawPayload); + let payload = e.data?.payload; + if (typeof payload === 'string') { + payload = deserialize(payload); } - const res = await messenger.request('kernel', { - from: 'walless@sdk', - payload, - }); + if (payload.type === TEZOS_PAIRING_REQUEST) { + return handlePairingRequest(payload as PostMessagePairingRequest); + } else { + const res = await messenger.request('kernel', { + from: 'walless@sdk', + payload, + }); - window.postMessage(res); + window.postMessage(res); + } } }); + +const handlePingPong = () => { + window.postMessage({ + target: ExtensionMessageTarget.PAGE, + payload: 'pong', + sender: WALLESS_TEZOS, + }); +}; + +const handlePairingRequest = async (payload: PostMessagePairingRequest) => { + const resPayload: PostMessagePairingResponse = { + type: TEZOS_PAIRING_RESPONSE, + publicKey: Buffer.from(keypair.publicKey).toString('hex'), + ...WALLESS_TEZOS, + }; + + const recipientPublicKey = payload.publicKey; + + window.postMessage({ + message: { + target: ExtensionMessageTarget.PAGE, + payload: await sealCryptobox( + JSON.stringify(resPayload), + Uint8Array.from(Buffer.from(recipientPublicKey, 'hex')), + ), + }, + sender: { id: WALLESS_TEZOS.id }, + }); +}; diff --git a/apps/web/scripts/content/utils.ts b/apps/web/scripts/content/utils.ts index 74a763e74..36502c985 100644 --- a/apps/web/scripts/content/utils.ts +++ b/apps/web/scripts/content/utils.ts @@ -1,3 +1,6 @@ +import type { UnknownObject } from '@walless/core'; +import { decode, encode } from 'bs58check'; + export const injectScript = (scriptUri: string) => { try { const container = document.head || document.documentElement; @@ -10,3 +13,11 @@ export const injectScript = (scriptUri: string) => { console.error('script injection failed.', error); } }; + +export const serialize = (data: UnknownObject): string => { + return encode(Buffer.from(JSON.stringify(data))); +}; + +export const deserialize = (encoded: string): UnknownObject => { + return JSON.parse(decode(encoded).toString()); +}; diff --git a/yarn.lock b/yarn.lock index 2726274f3..9c207c41f 100644 --- a/yarn.lock +++ b/yarn.lock @@ -142,7 +142,7 @@ __metadata: languageName: node linkType: hard -"@airgap/beacon-utils@npm:4.0.12": +"@airgap/beacon-utils@npm:4.0.12, @airgap/beacon-utils@npm:^4.0.12": version: 4.0.12 resolution: "@airgap/beacon-utils@npm:4.0.12" dependencies: @@ -11618,6 +11618,9 @@ __metadata: version: 0.0.0-use.local resolution: "@walless/crypto@workspace:packages/crypto" dependencies: + "@stablelib/ed25519": ^1.0.3 + "@stablelib/nacl": ^1.0.4 + "@stablelib/x25519-session": ^1.0.4 "@walless/core": "*" eslint: 8.38.0 languageName: unknown @@ -11967,6 +11970,7 @@ __metadata: resolution: "@walless/web@workspace:apps/web" dependencies: "@airgap/beacon-sdk": ^4.0.12 + "@airgap/beacon-utils": ^4.0.12 "@metacraft/cli-web3-polyfills": ^0.0.7 "@metaplex-foundation/js": 0.18.3 "@mysten/sui.js": 0.34.0 From 9fe126ba471cbb4714065b23e7273b103558ebec Mon Sep 17 00:00:00 2001 From: Tan Le Date: Wed, 6 Dec 2023 15:27:25 +0700 Subject: [PATCH 03/21] feat: send ack response to connect request --- apps/web/scripts/content/tezos.ts | 106 ++++++++++++++++++++++++------ packages/crypto/package.json | 3 + packages/crypto/utils/p2p.ts | 80 ++++++++++++++++++++++ 3 files changed, 169 insertions(+), 20 deletions(-) create mode 100644 packages/crypto/utils/p2p.ts diff --git a/apps/web/scripts/content/tezos.ts b/apps/web/scripts/content/tezos.ts index 1c1c3881d..6e4c9cac8 100644 --- a/apps/web/scripts/content/tezos.ts +++ b/apps/web/scripts/content/tezos.ts @@ -2,27 +2,36 @@ import type { PostMessagePairingRequest, PostMessagePairingResponse, } from '@airgap/beacon-sdk'; +import { BeaconMessageType } from '@airgap/beacon-sdk'; import { ExtensionMessageTarget } from '@airgap/beacon-sdk'; -import { sealCryptobox } from '@airgap/beacon-utils'; +import { + decryptCryptoboxPayload, + encryptCryptoboxPayload, + sealCryptobox, +} from '@airgap/beacon-utils'; +import type { UnknownObject } from '@walless/core'; +import { + createCryptoBoxClient, + createCryptoBoxServer, + generateKeyPair, +} from '@walless/crypto/utils/p2p'; import { messenger } from './messaging'; +import { deserialize, serialize } from './utils'; const TEZOS_PAIRING_REQUEST = 'postmessage-pairing-request'; const TEZOS_PAIRING_RESPONSE = 'postmessage-pairing-response'; -import { generateKeyPair } from '@walless/crypto/utils/p2p'; - -import { deserialize } from './utils'; - const WALLESS_TEZOS = { id: chrome.runtime.id, name: 'Walless', iconUrl: 'https://walless.io/img/walless-icon.svg', appUrl: 'https://walless.io', - version: '1.0.0', + version: '3', }; const keypair = generateKeyPair(); +let recipientPublicKey: string; window.addEventListener('message', async (e) => { if ( @@ -36,19 +45,19 @@ window.addEventListener('message', async (e) => { return handlePingPong(); } else { let payload = e.data?.payload; - if (typeof payload === 'string') { - payload = deserialize(payload); - } - - if (payload.type === TEZOS_PAIRING_REQUEST) { - return handlePairingRequest(payload as PostMessagePairingRequest); - } else { - const res = await messenger.request('kernel', { - from: 'walless@sdk', - payload, - }); + const encryptedPayload = e.data?.encryptedPayload; + if (payload) { + if (typeof payload === 'string') { + payload = deserialize(payload); + } - window.postMessage(res); + if (payload.type === TEZOS_PAIRING_REQUEST) { + return handlePairingRequest(payload as PostMessagePairingRequest); + } else { + return handleKernelActionRequest(payload, e.data.origin); + } + } else if (encryptedPayload) { + handleKernelActionRequest(encryptedPayload, e.data.origin, true); } } }); @@ -68,16 +77,73 @@ const handlePairingRequest = async (payload: PostMessagePairingRequest) => { ...WALLESS_TEZOS, }; - const recipientPublicKey = payload.publicKey; + recipientPublicKey = payload.publicKey; + const recipientPublicKeyBytes = Uint8Array.from( + Buffer.from(recipientPublicKey, 'hex'), + ); window.postMessage({ message: { target: ExtensionMessageTarget.PAGE, payload: await sealCryptobox( JSON.stringify(resPayload), - Uint8Array.from(Buffer.from(recipientPublicKey, 'hex')), + recipientPublicKeyBytes, ), }, sender: { id: WALLESS_TEZOS.id }, }); }; + +const handleKernelActionRequest = async ( + payload: UnknownObject | string, + origin: string, + encrypted: boolean = false, +) => { + if (encrypted) { + payload = (await decryptPayload(payload as string)) as UnknownObject; + console.log('decrypted payload', payload); + sendAckMessage(payload, origin); + } + + const res = await messenger.request('kernel', { + from: 'walless@sdk', + payload, + }); + + window.postMessage(res); +}; + +const sendAckMessage = async (payload: UnknownObject, origin: string) => { + const sharedKey = await createCryptoBoxClient(recipientPublicKey, keypair); + const resPayload = { + type: BeaconMessageType.Acknowledge, + id: payload.id || '', + }; + + const response = { + message: { + target: ExtensionMessageTarget.PAGE, + encryptedPayload: await encryptCryptoboxPayload( + serialize(resPayload), + sharedKey.send, + ), + }, + sender: { id: WALLESS_TEZOS.id }, + }; + + window.postMessage(response, origin); +}; + +const decryptPayload = async (encryptedPayload: string) => { + const sharedKey = await createCryptoBoxServer(recipientPublicKey, keypair); + try { + const payload = await decryptCryptoboxPayload( + Buffer.from(encryptedPayload, 'hex'), + sharedKey.receive, + ); + + return deserialize(payload); + } catch (e) { + console.log('error decrypting payload', e); + } +}; diff --git a/packages/crypto/package.json b/packages/crypto/package.json index 346d66b9f..c619bfece 100644 --- a/packages/crypto/package.json +++ b/packages/crypto/package.json @@ -11,6 +11,9 @@ "lint:fix": "eslint . --fix --max-warnings=0 --ext .ts,.tsx" }, "dependencies": { + "@stablelib/ed25519": "^1.0.3", + "@stablelib/nacl": "^1.0.4", + "@stablelib/x25519-session": "^1.0.4", "@walless/core": "*" }, "devDependencies": { diff --git a/packages/crypto/utils/p2p.ts b/packages/crypto/utils/p2p.ts new file mode 100644 index 000000000..b537a7578 --- /dev/null +++ b/packages/crypto/utils/p2p.ts @@ -0,0 +1,80 @@ +import { randomBytes } from 'crypto'; + +import { + convertPublicKeyToX25519, + convertSecretKeyToX25519, + type KeyPair, +} from '@stablelib/ed25519'; +import { openSecretBox, secretBox } from '@stablelib/nacl'; +import { + clientSessionKeys, + serverSessionKeys, + type SessionKeys, +} from '@stablelib/x25519-session'; + +export const secretbox_NONCEBYTES = 24; +export const secretbox_MACBYTES = 16; + +export const createCryptoBoxClient = async ( + otherPublicKey: string, + keypair: KeyPair, +): Promise => { + return clientSessionKeys( + { + publicKey: convertPublicKeyToX25519(keypair.publicKey), + secretKey: convertSecretKeyToX25519(keypair.secretKey), + }, + convertPublicKeyToX25519(Buffer.from(otherPublicKey, 'hex')), + ); +}; + +export const createCryptoBoxServer = async ( + otherPublicKey: string, + keypair: KeyPair, +): Promise => { + return serverSessionKeys( + { + publicKey: convertPublicKeyToX25519(keypair.publicKey), + secretKey: convertSecretKeyToX25519(keypair.secretKey), + }, + convertPublicKeyToX25519(Buffer.from(otherPublicKey, 'hex')), + ); +}; + +export const encryptMessage = async ( + recipientPublicKey: string, + keypair: KeyPair, + message: string, +) => { + const nonce = Buffer.from(randomBytes(secretbox_NONCEBYTES)); + const sharedKey = await createCryptoBoxClient(recipientPublicKey, keypair); + + const combinedPayload = Buffer.concat([ + nonce, + Buffer.from( + secretBox(sharedKey.receive, nonce, Buffer.from(message, 'utf-8')), + ), + ]); + + return combinedPayload.toString('hex'); +}; + +export const decryptMessage = async ( + payload: Uint8Array, + recipientPublicKey: string, + keypair: KeyPair, +) => { + const sharedKey = await createCryptoBoxClient(recipientPublicKey, keypair); + const nonce = payload.slice(0, secretbox_NONCEBYTES); + const ciphertext = payload.slice(secretbox_NONCEBYTES); + + const openBox = openSecretBox(sharedKey.receive, nonce, ciphertext); + + if (!openBox) { + throw new Error('Could not decrypt message'); + } + + return Buffer.from(openBox).toString('utf-8'); +}; + +export { generateKeyPair } from '@stablelib/ed25519'; From bd9604b653837108eb43c0eaa606f6f1ec6bbd59 Mon Sep 17 00:00:00 2001 From: Tan Le Date: Wed, 6 Dec 2023 15:59:06 +0700 Subject: [PATCH 04/21] refactor: make respond method reusable --- apps/web/scripts/content/tezos.ts | 56 +++++++++++++++++-------------- 1 file changed, 31 insertions(+), 25 deletions(-) diff --git a/apps/web/scripts/content/tezos.ts b/apps/web/scripts/content/tezos.ts index 6e4c9cac8..cd0173d24 100644 --- a/apps/web/scripts/content/tezos.ts +++ b/apps/web/scripts/content/tezos.ts @@ -45,6 +45,7 @@ window.addEventListener('message', async (e) => { return handlePingPong(); } else { let payload = e.data?.payload; + const origin = e.data?.origin || ''; const encryptedPayload = e.data?.encryptedPayload; if (payload) { if (typeof payload === 'string') { @@ -52,12 +53,12 @@ window.addEventListener('message', async (e) => { } if (payload.type === TEZOS_PAIRING_REQUEST) { - return handlePairingRequest(payload as PostMessagePairingRequest); + return handlePairingRequest(payload, origin); } else { return handleKernelActionRequest(payload, e.data.origin); } } else if (encryptedPayload) { - handleKernelActionRequest(encryptedPayload, e.data.origin, true); + handleKernelActionRequest(encryptedPayload, origin, true); } } }); @@ -70,7 +71,10 @@ const handlePingPong = () => { }); }; -const handlePairingRequest = async (payload: PostMessagePairingRequest) => { +const handlePairingRequest = async ( + payload: PostMessagePairingRequest, + origin: string, +) => { const resPayload: PostMessagePairingResponse = { type: TEZOS_PAIRING_RESPONSE, publicKey: Buffer.from(keypair.publicKey).toString('hex'), @@ -82,16 +86,12 @@ const handlePairingRequest = async (payload: PostMessagePairingRequest) => { Buffer.from(recipientPublicKey, 'hex'), ); - window.postMessage({ - message: { - target: ExtensionMessageTarget.PAGE, - payload: await sealCryptobox( - JSON.stringify(resPayload), - recipientPublicKeyBytes, - ), - }, - sender: { id: WALLESS_TEZOS.id }, - }); + const encryptedPayload = await sealCryptobox( + JSON.stringify(resPayload), + recipientPublicKeyBytes, + ); + + respond({ payload: encryptedPayload }, origin); }; const handleKernelActionRequest = async ( @@ -101,7 +101,6 @@ const handleKernelActionRequest = async ( ) => { if (encrypted) { payload = (await decryptPayload(payload as string)) as UnknownObject; - console.log('decrypted payload', payload); sendAckMessage(payload, origin); } @@ -120,18 +119,12 @@ const sendAckMessage = async (payload: UnknownObject, origin: string) => { id: payload.id || '', }; - const response = { - message: { - target: ExtensionMessageTarget.PAGE, - encryptedPayload: await encryptCryptoboxPayload( - serialize(resPayload), - sharedKey.send, - ), - }, - sender: { id: WALLESS_TEZOS.id }, - }; + const encryptedPayload = await encryptCryptoboxPayload( + serialize(resPayload), + sharedKey.send, + ); - window.postMessage(response, origin); + respond({ encryptedPayload }, origin); }; const decryptPayload = async (encryptedPayload: string) => { @@ -147,3 +140,16 @@ const decryptPayload = async (encryptedPayload: string) => { console.log('error decrypting payload', e); } }; + +const respond = (payload: UnknownObject, origin: string) => { + window.postMessage( + { + message: { + target: ExtensionMessageTarget.PAGE, + ...payload, + }, + sender: { id: WALLESS_TEZOS.id }, + }, + origin, + ); +}; From ada4cfc7803e43bdf7a8fcec9656470adb6cae5d Mon Sep 17 00:00:00 2001 From: Tan Le Date: Wed, 6 Dec 2023 19:03:34 +0700 Subject: [PATCH 05/21] refactor: connection popup for multi-chain --- apps/web/src/components/HeaderRequest.tsx | 6 +++++- apps/web/src/screens/Request/Connect.tsx | 18 ++++++++++-------- apps/web/src/utils/hooks/request.ts | 10 ++++++++-- 3 files changed, 23 insertions(+), 11 deletions(-) diff --git a/apps/web/src/components/HeaderRequest.tsx b/apps/web/src/components/HeaderRequest.tsx index ae01bcbc5..ad223f632 100644 --- a/apps/web/src/components/HeaderRequest.tsx +++ b/apps/web/src/components/HeaderRequest.tsx @@ -16,7 +16,11 @@ export const HeaderRequest: FC = ({ title }) => { - {title.length > 10 ? title.substring(0, 10) + '...' : title} + {title.length > 20 + ? title.substring(0, 10) + + '...' + + title.substring(title.length - 10) + : title} diff --git a/apps/web/src/screens/Request/Connect.tsx b/apps/web/src/screens/Request/Connect.tsx index d0369ae62..13771a4a2 100644 --- a/apps/web/src/screens/Request/Connect.tsx +++ b/apps/web/src/screens/Request/Connect.tsx @@ -16,11 +16,11 @@ import { logoSize, logoUri } from './shared'; const RequestConnect = () => { const { requestId } = useParams(); - const { sender } = useRequestData( + const { sender, options } = useRequestData( requestId as string, PopupType.REQUEST_CONNECT_POPUP, ); - const publicKey = usePublicKeys(Networks.solana)[0]; + const publicKey = usePublicKeys(options.network || Networks.solana)[0]; const onApprovePress = () => { handleRequestConnect(requestId as string, true); @@ -48,7 +48,9 @@ const RequestConnect = () => { source={{ uri: sender.tab?.favIconUrl || logoUri }} /> {title} - {sender.tab?.url || 'unknown'} + + {sender.origin || 'unknown'} + @@ -106,11 +108,10 @@ const styles = StyleSheet.create({ flex: 1, padding: 20, }, - titleContainer: { - alignItems: 'center', - }, + titleContainer: {}, title: { fontSize: 20, + textAlign: 'center', }, titleImage: { width: logoSize, @@ -119,9 +120,11 @@ const styles = StyleSheet.create({ borderWidth: 2, borderRadius: 15, marginVertical: 10, + alignSelf: 'center', }, senderName: { fontSize: 18, + textAlign: 'center', }, contentContainer: { backgroundColor: '#202D38', @@ -149,8 +152,7 @@ const styles = StyleSheet.create({ alignItems: 'center', }, bottomContainer: { - flex: 1, - justifyContent: 'flex-end', + marginTop: 'auto', gap: 10, }, deniedButton: { diff --git a/apps/web/src/utils/hooks/request.ts b/apps/web/src/utils/hooks/request.ts index 40fdf35c1..3f4dedd7e 100644 --- a/apps/web/src/utils/hooks/request.ts +++ b/apps/web/src/utils/hooks/request.ts @@ -1,11 +1,12 @@ import { useEffect, useState } from 'react'; -import type { UnknownObject } from '@walless/core'; +import type { ConnectOptions, UnknownObject } from '@walless/core'; import { runtime } from '@walless/core'; import type { MessagePayload } from '@walless/messaging'; import { getDataFromSourceRequest } from 'bridge/listeners'; export const useRequestData = (requestId: string, from: string) => { const [sender, setSender] = useState({}); + const [options, setOptions] = useState({}); const [message, setMessage] = useState(''); const [transaction, setTransaction] = useState(''); const [payload, setPayload] = useState(); @@ -13,7 +14,7 @@ export const useRequestData = (requestId: string, from: string) => { useEffect(() => { const configureSender = async () => { const result = await getDataFromSourceRequest(requestId, from); - const { sender, message, transaction } = result ?? {}; + const { sender, message, transaction, options } = result ?? {}; setPayload(result as MessagePayload); @@ -28,6 +29,10 @@ export const useRequestData = (requestId: string, from: string) => { if (transaction) { setTransaction(transaction); } + + if (options) { + setOptions(options); + } }; if (runtime.isExtension) { @@ -40,5 +45,6 @@ export const useRequestData = (requestId: string, from: string) => { sender, message, transaction, + options, }; }; From 37df90108711e9ce354e3e9575553bc6d0291acb Mon Sep 17 00:00:00 2001 From: Tan Le Date: Wed, 6 Dec 2023 19:04:22 +0700 Subject: [PATCH 06/21] chore: expose tezos meta with generic request type --- packages/auth/utils/keys.ts | 8 ++++++++ packages/core/utils/walletTypes.ts | 3 +++ packages/messaging/utils/types.ts | 16 +++++++++++----- 3 files changed, 22 insertions(+), 5 deletions(-) diff --git a/packages/auth/utils/keys.ts b/packages/auth/utils/keys.ts index 7bda56a3f..1d4158ba5 100644 --- a/packages/auth/utils/keys.ts +++ b/packages/auth/utils/keys.ts @@ -3,6 +3,7 @@ import { Keypair as SolPair } from '@solana/web3.js'; import { generateSecretKey, InMemorySigner } from '@taquito/signer'; import type { ISeedPhraseStore } from '@tkey/common-types'; import { generateID } from '@tkey/common-types'; +import type { UnknownObject } from '@walless/core'; import { Networks } from '@walless/core'; import { encryptWithPasscode } from '@walless/crypto'; import { modules } from '@walless/ioc'; @@ -71,6 +72,7 @@ const generateAndStoreKeypairs = async ( let keyType: string | undefined = undefined; let address: string | undefined = undefined; let privateKey: never | undefined = undefined; + let meta: UnknownObject | undefined = undefined; if (network === Networks.solana) { const seed = derivePath(`m/${path}/0'/0'`, rootSeed.toString('hex')).key; @@ -89,8 +91,13 @@ const generateAndStoreKeypairs = async ( } else if (network === Networks.tezos) { const secret = generateSecretKey(rootSeed, `m/${path}/0'/0'`, 'ed25519'); const keypair = await InMemorySigner.fromSecretKey(secret); + keyType = 'ed25519'; address = await keypair.publicKeyHash(); + meta = { + publicKey: await keypair.publicKey(), + address: await keypair.publicKeyHash(), + }; privateKey = decode(await keypair.secretKey()) as never; } else if (network === Networks.aptos) { const mnemonics = storedSeed.seedPhrase; @@ -118,6 +125,7 @@ const generateAndStoreKeypairs = async ( type: 'PublicKey', privateKeyId: id, network, + meta, }); await Promise.all([putPublicKeyPromise, putPrivateKeyPromise]); diff --git a/packages/core/utils/walletTypes.ts b/packages/core/utils/walletTypes.ts index 3af884e01..3a26ffe3a 100644 --- a/packages/core/utils/walletTypes.ts +++ b/packages/core/utils/walletTypes.ts @@ -6,9 +6,12 @@ import type { VersionedTransaction, } from '@solana/web3.js'; +import type { Networks } from './commonTypes'; + export interface ConnectOptions { onlyIfTrusted?: boolean; domain?: string; + network?: Networks; } export interface ConnectResult { diff --git a/packages/messaging/utils/types.ts b/packages/messaging/utils/types.ts index 58a121999..1c4e3d19d 100644 --- a/packages/messaging/utils/types.ts +++ b/packages/messaging/utils/types.ts @@ -21,14 +21,17 @@ interface IdentifiedPayload { id?: string; } -export type MessagePayload = UnknownObject & +export type MessagePayload = UnknownObject & IdentifiedPayload & { from: string; type: RequestType; requestId: string; - }; + } & T; -export type PureMessagePayload = Omit; +export type PureMessagePayload = Omit< + MessagePayload, + 'requestId' +>; export type ResponsePayload = UnknownObject & IdentifiedPayload & { @@ -58,9 +61,9 @@ export type MessengerSend = ( payload: MessagePayload, ) => Promise; -export type MessengerRequest = ( +export type MessengerRequest = ( channelId: string, - payload: PureMessagePayload | MessagePayload, + payload: PureMessagePayload | MessagePayload, timeout?: number, ) => Promise; @@ -110,6 +113,9 @@ export enum RequestType { CLAIM_TOKEN_ON_APTOS, TRANSFER_COIN_ON_APTOS, TRANSFER_TOKEN_ON_APTOS, + REQUEST_PERMISSION_ON_TEZOS = 'permission_request', + REQUEST_OPERATION_ON_TEZOS = 'operation_request', + SIGN_PAYLOAD_ON_TEZOS = 'sign_payload_request', } export enum PopupType { From 8c1829cc4cad21452194e6db6085e8d8a10fa309 Mon Sep 17 00:00:00 2001 From: Tan Le Date: Wed, 6 Dec 2023 19:05:51 +0700 Subject: [PATCH 07/21] refactor: make connect request work multi-chain --- apps/web/scripts/kernel/handlers/common.ts | 17 +++++++++++------ apps/web/scripts/kernel/utils/middleware.ts | 8 +++++--- packages/store/utils/type.ts | 2 ++ 3 files changed, 18 insertions(+), 9 deletions(-) diff --git a/apps/web/scripts/kernel/handlers/common.ts b/apps/web/scripts/kernel/handlers/common.ts index df5792684..26f272fa0 100644 --- a/apps/web/scripts/kernel/handlers/common.ts +++ b/apps/web/scripts/kernel/handlers/common.ts @@ -18,14 +18,15 @@ export const connect: HandleMethod<{ options?: ConnectOptions }> = async ({ }) => { if (!payload.options) throw new Error('No connection options provided'); - const connectOptions = payload.options; - if (connectOptions.domain) { + const { domain, network = Networks.solana } = payload.options; + if (domain) { const doc = { - _id: connectOptions.domain, + _id: domain, type: 'TrustedDomain', trusted: true, connectCount: 1, connect: true, + network, }; await modules.storage.upsert( doc._id, @@ -34,17 +35,21 @@ export const connect: HandleMethod<{ options?: ConnectOptions }> = async ({ doc.connectCount = prevDoc.connectCount + 1; } + if (!prevDoc.network) { + doc.network = network; + } + return doc as TrustedDomainDocument; }, ); } const publicKeys = await modules.storage.find(selectors.allKeys); - const solKey = (publicKeys.docs as PublicKeyDocument[]).find( - (key) => key.network == Networks.solana, + const publicKey = (publicKeys.docs as PublicKeyDocument[]).find( + (key) => key.network == network, ); - respond(payload.requestId, ResponseCode.SUCCESS, { publicKeys: [solKey] }); + respond(payload.requestId, ResponseCode.SUCCESS, { publicKeys: [publicKey] }); }; export const disconnect: HandleMethod<{ diff --git a/apps/web/scripts/kernel/utils/middleware.ts b/apps/web/scripts/kernel/utils/middleware.ts index 6a98a83fb..486e20c89 100644 --- a/apps/web/scripts/kernel/utils/middleware.ts +++ b/apps/web/scripts/kernel/utils/middleware.ts @@ -46,13 +46,15 @@ export const checkConnection: HandleMethod<{ const domainResponse = await modules.storage.find(selectors.trustedDomains); const trustedDomains = domainResponse.docs as TrustedDomainDocument[]; const savedDomain = trustedDomains.find(({ _id }) => _id == domain); + if (!savedDomain || !savedDomain.connect) { Object.values(requestPool).forEach((ele) => { - if ( + const isDuplicatedRequest = ele.payload.requestId !== payload.requestId && ele.payload.type === RequestType.REQUEST_CONNECT && - ele.payload.options.domain === domain - ) { + ele.payload.options.domain === domain; + + if (isDuplicatedRequest) { respond(ele.payload.requestId, ResponseCode.ERROR); closePopup(ele.payload.popupId); } diff --git a/packages/store/utils/type.ts b/packages/store/utils/type.ts index dacdee019..0cb591453 100644 --- a/packages/store/utils/type.ts +++ b/packages/store/utils/type.ts @@ -12,6 +12,7 @@ import type { System, Token, TrustedDomain, + UnknownObject, Widget, } from '@walless/core'; @@ -57,6 +58,7 @@ export type PrivateKeyDocument = PouchDocument< export type PublicKeyDocument = PouchDocument<{ privateKeyId: string; network: Networks; + meta?: UnknownObject; }>; export type ExtensionDocument = PouchDocument; From 7a90278b196b42a924a72b006c278043730b1362 Mon Sep 17 00:00:00 2001 From: Tan Le Date: Wed, 6 Dec 2023 19:06:34 +0700 Subject: [PATCH 08/21] feat: complete handle tezos permission request --- apps/web/scripts/content/tezos.ts | 60 +++++++++++++++++++++++-------- 1 file changed, 46 insertions(+), 14 deletions(-) diff --git a/apps/web/scripts/content/tezos.ts b/apps/web/scripts/content/tezos.ts index cd0173d24..d5709e02f 100644 --- a/apps/web/scripts/content/tezos.ts +++ b/apps/web/scripts/content/tezos.ts @@ -1,20 +1,27 @@ import type { + Network, PostMessagePairingRequest, PostMessagePairingResponse, } from '@airgap/beacon-sdk'; -import { BeaconMessageType } from '@airgap/beacon-sdk'; +import { + BeaconMessageType, + NetworkType, + PermissionScope, +} from '@airgap/beacon-sdk'; import { ExtensionMessageTarget } from '@airgap/beacon-sdk'; import { decryptCryptoboxPayload, encryptCryptoboxPayload, sealCryptobox, } from '@airgap/beacon-utils'; -import type { UnknownObject } from '@walless/core'; +import type { ConnectOptions } from '@walless/core'; +import { Networks, type UnknownObject } from '@walless/core'; import { createCryptoBoxClient, createCryptoBoxServer, generateKeyPair, } from '@walless/crypto/utils/p2p'; +import { RequestType } from '@walless/messaging'; import { messenger } from './messaging'; import { deserialize, serialize } from './utils'; @@ -45,7 +52,7 @@ window.addEventListener('message', async (e) => { return handlePingPong(); } else { let payload = e.data?.payload; - const origin = e.data?.origin || ''; + const origin = e.origin; const encryptedPayload = e.data?.encryptedPayload; if (payload) { if (typeof payload === 'string') { @@ -55,7 +62,7 @@ window.addEventListener('message', async (e) => { if (payload.type === TEZOS_PAIRING_REQUEST) { return handlePairingRequest(payload, origin); } else { - return handleKernelActionRequest(payload, e.data.origin); + return handleKernelActionRequest(payload, origin); } } else if (encryptedPayload) { handleKernelActionRequest(encryptedPayload, origin, true); @@ -99,24 +106,49 @@ const handleKernelActionRequest = async ( origin: string, encrypted: boolean = false, ) => { - if (encrypted) { + if (encrypted || typeof payload === 'string') { payload = (await decryptPayload(payload as string)) as UnknownObject; - sendAckMessage(payload, origin); } - - const res = await messenger.request('kernel', { - from: 'walless@sdk', - payload, - }); - - window.postMessage(res); + sendAckMessage(payload, origin); + + if (payload?.type === RequestType.REQUEST_PERMISSION_ON_TEZOS) { + const res = await messenger.request<{ options: ConnectOptions }>('kernel', { + from: 'walless@sdk', + type: RequestType.REQUEST_PERMISSION_ON_TEZOS, + options: { + network: Networks.tezos, + domain: payload.origin, + onlyIfTrusted: true, + }, + }); + + const sharedKey = await createCryptoBoxClient(recipientPublicKey, keypair); + respond( + { + encryptedPayload: await encryptCryptoboxPayload( + serialize({ + id: payload.id, + scopes: [PermissionScope.OPERATION_REQUEST, PermissionScope.SIGN], + origin: { type: 'extension', id: chrome.runtime.id }, + type: BeaconMessageType.PermissionResponse, + network: { type: NetworkType.MAINNET }, // TODO: handle custom networks + publicKey: res.publicKeys[0]?.meta?.publicKey, + }), + sharedKey.send, + ), + }, + origin, + ); + } else { + console.log('Unhandled request type'); + } }; const sendAckMessage = async (payload: UnknownObject, origin: string) => { const sharedKey = await createCryptoBoxClient(recipientPublicKey, keypair); const resPayload = { type: BeaconMessageType.Acknowledge, - id: payload.id || '', + id: payload?.id || '', }; const encryptedPayload = await encryptCryptoboxPayload( From fe656b69d7ab529cc4aefa3ad43061083526049e Mon Sep 17 00:00:00 2001 From: Tan Le Date: Wed, 6 Dec 2023 19:20:25 +0700 Subject: [PATCH 09/21] chore: clean --- apps/web/scripts/content/tezos.ts | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/apps/web/scripts/content/tezos.ts b/apps/web/scripts/content/tezos.ts index d5709e02f..c3a3bb331 100644 --- a/apps/web/scripts/content/tezos.ts +++ b/apps/web/scripts/content/tezos.ts @@ -41,10 +41,9 @@ const keypair = generateKeyPair(); let recipientPublicKey: string; window.addEventListener('message', async (e) => { - if ( - e.data?.target !== ExtensionMessageTarget.EXTENSION || - (e.data?.targetId && e.data?.targetId !== WALLESS_TEZOS.id) - ) { + const isNotTezosRequest = e.data?.target !== ExtensionMessageTarget.EXTENSION; + const wrongTarget = e.data?.targetId && e.data?.targetId !== WALLESS_TEZOS.id; + if (isNotTezosRequest || wrongTarget) { return; } From eb09c40f36561ba7e193dfa63ea8990b371d4b08 Mon Sep 17 00:00:00 2001 From: Tan Le Date: Thu, 7 Dec 2023 12:02:51 +0700 Subject: [PATCH 10/21] chore: fix eslint --- apps/web/scripts/content/tezos.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/apps/web/scripts/content/tezos.ts b/apps/web/scripts/content/tezos.ts index c3a3bb331..00027ec08 100644 --- a/apps/web/scripts/content/tezos.ts +++ b/apps/web/scripts/content/tezos.ts @@ -1,5 +1,4 @@ import type { - Network, PostMessagePairingRequest, PostMessagePairingResponse, } from '@airgap/beacon-sdk'; From 2369b2d418bc2eff7d611a5d63fa86c7fdb64a1b Mon Sep 17 00:00:00 2001 From: Tan Le Date: Thu, 7 Dec 2023 13:27:54 +0700 Subject: [PATCH 11/21] chore: clean permission handle --- apps/web/scripts/content/tezos.ts | 85 ++++++++++++++++--------------- 1 file changed, 43 insertions(+), 42 deletions(-) diff --git a/apps/web/scripts/content/tezos.ts b/apps/web/scripts/content/tezos.ts index 00027ec08..01d722a4e 100644 --- a/apps/web/scripts/content/tezos.ts +++ b/apps/web/scripts/content/tezos.ts @@ -1,4 +1,5 @@ import type { + PermissionRequest, PostMessagePairingRequest, PostMessagePairingResponse, } from '@airgap/beacon-sdk'; @@ -22,6 +23,7 @@ import { } from '@walless/crypto/utils/p2p'; import { RequestType } from '@walless/messaging'; +import { handle } from './../kernel/utils/handle'; import { messenger } from './messaging'; import { deserialize, serialize } from './utils'; @@ -53,17 +55,12 @@ window.addEventListener('message', async (e) => { const origin = e.origin; const encryptedPayload = e.data?.encryptedPayload; if (payload) { - if (typeof payload === 'string') { - payload = deserialize(payload); - } - + if (typeof payload === 'string') payload = deserialize(payload); if (payload.type === TEZOS_PAIRING_REQUEST) { return handlePairingRequest(payload, origin); - } else { - return handleKernelActionRequest(payload, origin); } } else if (encryptedPayload) { - handleKernelActionRequest(encryptedPayload, origin, true); + handleEncryptedRequest(encryptedPayload, origin); } } }); @@ -99,49 +96,53 @@ const handlePairingRequest = async ( respond({ payload: encryptedPayload }, origin); }; -const handleKernelActionRequest = async ( - payload: UnknownObject | string, +const handleEncryptedRequest = async ( + encryptedPayload: string, origin: string, - encrypted: boolean = false, ) => { - if (encrypted || typeof payload === 'string') { - payload = (await decryptPayload(payload as string)) as UnknownObject; - } + if (typeof encryptedPayload === 'string') return; + const payload = await decryptPayload(encryptedPayload); + if (!payload) return; sendAckMessage(payload, origin); if (payload?.type === RequestType.REQUEST_PERMISSION_ON_TEZOS) { - const res = await messenger.request<{ options: ConnectOptions }>('kernel', { - from: 'walless@sdk', - type: RequestType.REQUEST_PERMISSION_ON_TEZOS, - options: { - network: Networks.tezos, - domain: payload.origin, - onlyIfTrusted: true, - }, - }); - - const sharedKey = await createCryptoBoxClient(recipientPublicKey, keypair); - respond( - { - encryptedPayload: await encryptCryptoboxPayload( - serialize({ - id: payload.id, - scopes: [PermissionScope.OPERATION_REQUEST, PermissionScope.SIGN], - origin: { type: 'extension', id: chrome.runtime.id }, - type: BeaconMessageType.PermissionResponse, - network: { type: NetworkType.MAINNET }, // TODO: handle custom networks - publicKey: res.publicKeys[0]?.meta?.publicKey, - }), - sharedKey.send, - ), - }, - origin, - ); + handlePermissionRequest(payload as never, origin); } else { console.log('Unhandled request type'); } }; +const handlePermissionRequest = async ( + payload: PermissionRequest, + origin: string, +) => { + const res = await messenger.request<{ options: ConnectOptions }>('kernel', { + from: 'walless@sdk', + type: RequestType.REQUEST_PERMISSION_ON_TEZOS, + options: { + network: Networks.tezos, + domain: origin, + onlyIfTrusted: true, + }, + }); + + const sharedKey = await createCryptoBoxClient(recipientPublicKey, keypair); + const resPayload = { + encryptedPayload: await encryptCryptoboxPayload( + serialize({ + id: payload.id, + type: BeaconMessageType.PermissionResponse, + network: { type: NetworkType.MAINNET }, // TODO: handle custom networks + publicKey: res.publicKeys[0]?.meta?.publicKey, + scopes: [PermissionScope.OPERATION_REQUEST, PermissionScope.SIGN], + }), + sharedKey.send, + ), + }; + + respond(resPayload, origin); +}; + const sendAckMessage = async (payload: UnknownObject, origin: string) => { const sharedKey = await createCryptoBoxClient(recipientPublicKey, keypair); const resPayload = { @@ -171,12 +172,12 @@ const decryptPayload = async (encryptedPayload: string) => { } }; -const respond = (payload: UnknownObject, origin: string) => { +const respond = (message: UnknownObject, origin: string) => { window.postMessage( { message: { target: ExtensionMessageTarget.PAGE, - ...payload, + ...message, }, sender: { id: WALLESS_TEZOS.id }, }, From 9ef0b2d26808bbb0b5d77928698ef20b837b8073 Mon Sep 17 00:00:00 2001 From: Tan Le Date: Thu, 7 Dec 2023 14:04:42 +0700 Subject: [PATCH 12/21] chore: clean handle structure --- apps/web/scripts/content/tezos.ts | 83 ++++++++++++++----------------- packages/messaging/utils/types.ts | 1 - 2 files changed, 37 insertions(+), 47 deletions(-) diff --git a/apps/web/scripts/content/tezos.ts b/apps/web/scripts/content/tezos.ts index 01d722a4e..4243c7d34 100644 --- a/apps/web/scripts/content/tezos.ts +++ b/apps/web/scripts/content/tezos.ts @@ -23,7 +23,6 @@ import { } from '@walless/crypto/utils/p2p'; import { RequestType } from '@walless/messaging'; -import { handle } from './../kernel/utils/handle'; import { messenger } from './messaging'; import { deserialize, serialize } from './utils'; @@ -40,6 +39,7 @@ const WALLESS_TEZOS = { const keypair = generateKeyPair(); let recipientPublicKey: string; +let origin: string; window.addEventListener('message', async (e) => { const isNotTezosRequest = e.data?.target !== ExtensionMessageTarget.EXTENSION; @@ -51,16 +51,16 @@ window.addEventListener('message', async (e) => { if (e.data?.payload === 'ping') { return handlePingPong(); } else { + origin = e.origin; let payload = e.data?.payload; - const origin = e.origin; const encryptedPayload = e.data?.encryptedPayload; if (payload) { if (typeof payload === 'string') payload = deserialize(payload); if (payload.type === TEZOS_PAIRING_REQUEST) { - return handlePairingRequest(payload, origin); + return handlePairingRequest(payload); } } else if (encryptedPayload) { - handleEncryptedRequest(encryptedPayload, origin); + handleEncryptedRequest(encryptedPayload); } } }); @@ -73,10 +73,7 @@ const handlePingPong = () => { }); }; -const handlePairingRequest = async ( - payload: PostMessagePairingRequest, - origin: string, -) => { +const handlePairingRequest = async (payload: PostMessagePairingRequest) => { const resPayload: PostMessagePairingResponse = { type: TEZOS_PAIRING_RESPONSE, publicKey: Buffer.from(keypair.publicKey).toString('hex'), @@ -93,32 +90,33 @@ const handlePairingRequest = async ( recipientPublicKeyBytes, ); - respond({ payload: encryptedPayload }, origin); + respond({ payload: encryptedPayload }); }; -const handleEncryptedRequest = async ( - encryptedPayload: string, - origin: string, -) => { +const handleEncryptedRequest = async (encryptedPayload: string) => { if (typeof encryptedPayload === 'string') return; const payload = await decryptPayload(encryptedPayload); - if (!payload) return; - sendAckMessage(payload, origin); - - if (payload?.type === RequestType.REQUEST_PERMISSION_ON_TEZOS) { - handlePermissionRequest(payload as never, origin); + console.log(payload, '<-- payload after decrypt'); + if (!payload || payload?.type) return; + sendAckMessage(payload); + + if (payload.type === BeaconMessageType.PermissionRequest) { + handlePermissionRequest(payload as never); + } else if (payload.type === BeaconMessageType.Disconnect) { + console.log('handle disconnect'); + } else if (payload.type === BeaconMessageType.SignPayloadRequest) { + console.log('handle sign payload'); + } else if (payload.type === BeaconMessageType.OperationRequest) { + console.log('handle operation request'); } else { - console.log('Unhandled request type'); + console.log('not support this type of request'); } }; -const handlePermissionRequest = async ( - payload: PermissionRequest, - origin: string, -) => { +const handlePermissionRequest = async (payload: PermissionRequest) => { const res = await messenger.request<{ options: ConnectOptions }>('kernel', { from: 'walless@sdk', - type: RequestType.REQUEST_PERMISSION_ON_TEZOS, + type: RequestType.REQUEST_CONNECT, options: { network: Networks.tezos, domain: origin, @@ -126,36 +124,24 @@ const handlePermissionRequest = async ( }, }); - const sharedKey = await createCryptoBoxClient(recipientPublicKey, keypair); const resPayload = { - encryptedPayload: await encryptCryptoboxPayload( - serialize({ - id: payload.id, - type: BeaconMessageType.PermissionResponse, - network: { type: NetworkType.MAINNET }, // TODO: handle custom networks - publicKey: res.publicKeys[0]?.meta?.publicKey, - scopes: [PermissionScope.OPERATION_REQUEST, PermissionScope.SIGN], - }), - sharedKey.send, - ), + id: payload.id, + type: BeaconMessageType.PermissionResponse, + network: { type: NetworkType.MAINNET }, // TODO: handle custom networks + publicKey: res.publicKeys[0]?.meta?.publicKey, + scopes: [PermissionScope.OPERATION_REQUEST, PermissionScope.SIGN], }; - respond(resPayload, origin); + respond(resPayload); }; -const sendAckMessage = async (payload: UnknownObject, origin: string) => { - const sharedKey = await createCryptoBoxClient(recipientPublicKey, keypair); +const sendAckMessage = async (payload: UnknownObject) => { const resPayload = { type: BeaconMessageType.Acknowledge, id: payload?.id || '', }; - const encryptedPayload = await encryptCryptoboxPayload( - serialize(resPayload), - sharedKey.send, - ); - - respond({ encryptedPayload }, origin); + respond(resPayload); }; const decryptPayload = async (encryptedPayload: string) => { @@ -172,12 +158,17 @@ const decryptPayload = async (encryptedPayload: string) => { } }; -const respond = (message: UnknownObject, origin: string) => { +const respond = async (payload: UnknownObject) => { + const sharedKey = await createCryptoBoxClient(recipientPublicKey, keypair); + const encryptedPayload = await encryptCryptoboxPayload( + serialize(payload), + sharedKey.send, + ); window.postMessage( { message: { target: ExtensionMessageTarget.PAGE, - ...message, + encryptedPayload, }, sender: { id: WALLESS_TEZOS.id }, }, diff --git a/packages/messaging/utils/types.ts b/packages/messaging/utils/types.ts index 1c4e3d19d..d03693a86 100644 --- a/packages/messaging/utils/types.ts +++ b/packages/messaging/utils/types.ts @@ -113,7 +113,6 @@ export enum RequestType { CLAIM_TOKEN_ON_APTOS, TRANSFER_COIN_ON_APTOS, TRANSFER_TOKEN_ON_APTOS, - REQUEST_PERMISSION_ON_TEZOS = 'permission_request', REQUEST_OPERATION_ON_TEZOS = 'operation_request', SIGN_PAYLOAD_ON_TEZOS = 'sign_payload_request', } From 634badb6368b79116c244abfbf588e1742ec6500 Mon Sep 17 00:00:00 2001 From: Tan Le Date: Fri, 8 Dec 2023 08:01:51 +0700 Subject: [PATCH 13/21] test: add p2p encryption test --- apps/web/scripts/content/tezos.ts | 32 +++++---- packages/crypto/package.json | 6 +- packages/crypto/tests/p2p.test.ts | 115 ++++++++++++++++++++++++++++++ packages/crypto/utils/p2p.ts | 12 +++- yarn.lock | 97 ++++++++++++++++++++++--- 5 files changed, 236 insertions(+), 26 deletions(-) create mode 100644 packages/crypto/tests/p2p.test.ts diff --git a/apps/web/scripts/content/tezos.ts b/apps/web/scripts/content/tezos.ts index 4243c7d34..b7a801eb4 100644 --- a/apps/web/scripts/content/tezos.ts +++ b/apps/web/scripts/content/tezos.ts @@ -90,15 +90,21 @@ const handlePairingRequest = async (payload: PostMessagePairingRequest) => { recipientPublicKeyBytes, ); - respond({ payload: encryptedPayload }); + window.postMessage({ + message: { + target: ExtensionMessageTarget.PAGE, + payload: encryptedPayload, + }, + sender: { id: WALLESS_TEZOS.id }, + }); }; const handleEncryptedRequest = async (encryptedPayload: string) => { - if (typeof encryptedPayload === 'string') return; + if (typeof encryptedPayload !== 'string') return; const payload = await decryptPayload(encryptedPayload); console.log(payload, '<-- payload after decrypt'); - if (!payload || payload?.type) return; - sendAckMessage(payload); + if (!payload || !payload.type) return; + sendAckMessage(payload.id); if (payload.type === BeaconMessageType.PermissionRequest) { handlePermissionRequest(payload as never); @@ -114,6 +120,7 @@ const handleEncryptedRequest = async (encryptedPayload: string) => { }; const handlePermissionRequest = async (payload: PermissionRequest) => { + // TODO: check network is valid or net, throw error if not const res = await messenger.request<{ options: ConnectOptions }>('kernel', { from: 'walless@sdk', type: RequestType.REQUEST_CONNECT, @@ -132,16 +139,16 @@ const handlePermissionRequest = async (payload: PermissionRequest) => { scopes: [PermissionScope.OPERATION_REQUEST, PermissionScope.SIGN], }; - respond(resPayload); + respondWithSharedKeyEncrypt(resPayload); }; -const sendAckMessage = async (payload: UnknownObject) => { +const sendAckMessage = async (requestId: string) => { const resPayload = { type: BeaconMessageType.Acknowledge, - id: payload?.id || '', + id: requestId, }; - respond(resPayload); + respondWithSharedKeyEncrypt(resPayload); }; const decryptPayload = async (encryptedPayload: string) => { @@ -158,20 +165,17 @@ const decryptPayload = async (encryptedPayload: string) => { } }; -const respond = async (payload: UnknownObject) => { +const respondWithSharedKeyEncrypt = async (payload: UnknownObject) => { const sharedKey = await createCryptoBoxClient(recipientPublicKey, keypair); const encryptedPayload = await encryptCryptoboxPayload( serialize(payload), sharedKey.send, ); - window.postMessage( - { + window.postMessage({ message: { target: ExtensionMessageTarget.PAGE, encryptedPayload, }, sender: { id: WALLESS_TEZOS.id }, - }, - origin, - ); + }); }; diff --git a/packages/crypto/package.json b/packages/crypto/package.json index c619bfece..0dd33074e 100644 --- a/packages/crypto/package.json +++ b/packages/crypto/package.json @@ -14,9 +14,11 @@ "@stablelib/ed25519": "^1.0.3", "@stablelib/nacl": "^1.0.4", "@stablelib/x25519-session": "^1.0.4", - "@walless/core": "*" + "@walless/core": "*", + "base58check": "^2.0.0" }, "devDependencies": { - "eslint": "8.38.0" + "eslint": "8.38.0", + "jest": "^29.4.3" } } diff --git a/packages/crypto/tests/p2p.test.ts b/packages/crypto/tests/p2p.test.ts new file mode 100644 index 000000000..3fecf5e16 --- /dev/null +++ b/packages/crypto/tests/p2p.test.ts @@ -0,0 +1,115 @@ +import { + decryptMessage, + deserialize, + encryptMessage, + generateKeyPair, + serialize, +} from '../utils/p2p'; + +const generateRandomKeyPairs = () => { + const clientKeypair = generateKeyPair(); + const clientPublicKeyHex = Buffer.from(clientKeypair.publicKey).toString( + 'hex', + ); + const serverKeypair = generateKeyPair(); + const serverPublicKeyHex = Buffer.from(serverKeypair.publicKey).toString( + 'hex', + ); + return { + clientKeypair, + clientPublicKeyHex, + serverKeypair, + serverPublicKeyHex, + }; +}; + +test('encrypt/decrypt with shared key', async () => { + const { + clientKeypair, + clientPublicKeyHex, + serverKeypair, + serverPublicKeyHex, + } = generateRandomKeyPairs(); + + const payload = { + message: 'hello world', + }; + + const encryptedPayload = await encryptMessage( + serverPublicKeyHex, + clientKeypair, + serialize(payload), + ); + + const decryptedPayload = deserialize( + await decryptMessage( + Buffer.from(encryptedPayload, 'hex'), + clientPublicKeyHex, + serverKeypair, + ), + ); + + expect(decryptedPayload.message).toBe(payload.message); +}); + +test('encrypt/decrypt with shared key multiple times', async () => { + const { + clientKeypair, + clientPublicKeyHex, + serverKeypair, + serverPublicKeyHex, + } = generateRandomKeyPairs(); + + const payload = { + message: 'hello world', + }; + + for (let i = 0; i < 10; i++) { + payload.message += i; + const encryptedPayload = await encryptMessage( + serverPublicKeyHex, + clientKeypair, + serialize(payload), + ); + + const decryptedPayload = deserialize( + await decryptMessage( + Buffer.from(encryptedPayload, 'hex'), + clientPublicKeyHex, + serverKeypair, + ), + ); + + expect(decryptedPayload.message).toBe(payload.message); + } +}); + +test('encrypt/decrypt big object with shared key', async () => { + const { + clientKeypair, + clientPublicKeyHex, + serverKeypair, + serverPublicKeyHex, + } = generateRandomKeyPairs(); + + const payload = { + message: + "I'd spend hours building things, imagining new worlds, new machines, new concepts, then i'd take them apart and create a whole new idea to explore.I'd spend hours building things, imagining new worlds, new machines, new concepts, then i'd take them apart and create a whole new idea to explore.I'd spend hours building things, imagining new worlds, new machines, new concepts, then i'd take them apart and create a whole new idea to explore.I'd spend hours building things, imagining new worlds, new machines, new concepts, then i'd take them apart and create a whole new idea to explore.I'd spend hours building things, imagining new worlds, new machines, new concepts, then i'd take them apart and create a whole new idea to explore.", + }; + + const encryptedPayload = await encryptMessage( + serverPublicKeyHex, + clientKeypair, + serialize(payload), + ); + + const decryptedPayload = deserialize( + await decryptMessage( + Buffer.from(encryptedPayload, 'hex'), + clientPublicKeyHex, + serverKeypair, + ), + ); + + expect(decryptedPayload.message).toBe(payload.message); +}); diff --git a/packages/crypto/utils/p2p.ts b/packages/crypto/utils/p2p.ts index b537a7578..4d6e23d57 100644 --- a/packages/crypto/utils/p2p.ts +++ b/packages/crypto/utils/p2p.ts @@ -11,6 +11,8 @@ import { serverSessionKeys, type SessionKeys, } from '@stablelib/x25519-session'; +import type { UnknownObject } from '@walless/core'; +import { decode, encode } from 'bs58check'; export const secretbox_NONCEBYTES = 24; export const secretbox_MACBYTES = 16; @@ -52,7 +54,7 @@ export const encryptMessage = async ( const combinedPayload = Buffer.concat([ nonce, Buffer.from( - secretBox(sharedKey.receive, nonce, Buffer.from(message, 'utf-8')), + secretBox(sharedKey.send, nonce, Buffer.from(message, 'utf-8')), ), ]); @@ -77,4 +79,12 @@ export const decryptMessage = async ( return Buffer.from(openBox).toString('utf-8'); }; +export const serialize = (data: UnknownObject): string => { + return encode(Buffer.from(JSON.stringify(data))); +}; + +export const deserialize = (encoded: string): UnknownObject => { + return JSON.parse(decode(encoded).toString()); +}; + export { generateKeyPair } from '@stablelib/ed25519'; diff --git a/yarn.lock b/yarn.lock index 9c207c41f..c128fefbf 100644 --- a/yarn.lock +++ b/yarn.lock @@ -11136,6 +11136,13 @@ __metadata: languageName: node linkType: hard +"@types/libsodium-wrappers@npm:^0.7.13": + version: 0.7.13 + resolution: "@types/libsodium-wrappers@npm:0.7.13" + checksum: 94d608bed8ccd364754c3a7bf5d4c770b229efa33f0c475061b1b82bb8d5da8d57a72df0b8876b887077edbb6ff9594b7a1183029de4d1ad679821d1013f3db9 + languageName: node + linkType: hard + "@types/lodash@npm:^4.14.191": version: 4.14.201 resolution: "@types/lodash@npm:4.14.201" @@ -11353,6 +11360,13 @@ __metadata: languageName: node linkType: hard +"@types/webextension-polyfill@npm:^0.10.7": + version: 0.10.7 + resolution: "@types/webextension-polyfill@npm:0.10.7" + checksum: 372064d5e007ab7889ea4f7b634d311f85bb78b13bf174a28781699ca21e8daa61ccd371dafe6b3f4fa3c9fe1fee11a5dbe52ed66f3cf84c1738cd18a535cbb7 + languageName: node + linkType: hard + "@types/ws@npm:*, @types/ws@npm:^8.0.0": version: 8.5.9 resolution: "@types/ws@npm:8.5.9" @@ -11622,7 +11636,9 @@ __metadata: "@stablelib/nacl": ^1.0.4 "@stablelib/x25519-session": ^1.0.4 "@walless/core": "*" + base58check: ^2.0.0 eslint: 8.38.0 + jest: ^29.4.3 languageName: unknown linkType: soft @@ -11977,6 +11993,8 @@ __metadata: "@solana/spl-token": 0.3.7 "@solana/web3.js": 1.78.4 "@taquito/signer": ^16.2.0 + "@types/libsodium-wrappers": ^0.7.13 + "@types/webextension-polyfill": ^0.10.7 "@walless/core": "*" "@walless/crypto": "*" "@walless/engine": "*" @@ -11998,7 +12016,9 @@ __metadata: eslint: 8.38.0 firebase: 10.7.0 graphql-request: ^6.1.0 + libsodium-wrappers: ^0.7.13 numeral: ^2.0.6 + p-memoize: ^7.1.1 pouchdb-adapter-http: ^8.0.1 pouchdb-adapter-idb: ^8.0.1 pouchdb-core: ^8.0.1 @@ -12014,6 +12034,7 @@ __metadata: rimraf: ^5.0.1 setimmediate: ^1.0.5 valtio: 1.10.5 + webextension-polyfill: ^0.10.0 peerDependencies: "@tkey/chrome-storage": 9.0.0 "@tkey/default": 9.0.0 @@ -13850,6 +13871,13 @@ __metadata: languageName: node linkType: hard +"base-x@npm:^1.1.0": + version: 1.1.0 + resolution: "base-x@npm:1.1.0" + checksum: 54e24c32919442627fe48aaa76338f8ff02187b42eae6e75e829eef3e44e37f43b128a271733322a7c798626ac7f4fb06184db2ef0ce1da7f37c448ef6f76e26 + languageName: node + linkType: hard + "base-x@npm:^3.0.2, base-x@npm:^3.0.6": version: 3.0.9 resolution: "base-x@npm:3.0.9" @@ -13866,6 +13894,15 @@ __metadata: languageName: node linkType: hard +"base58check@npm:^2.0.0": + version: 2.0.0 + resolution: "base58check@npm:2.0.0" + dependencies: + bs58: ^3.0.0 + checksum: 19f77522a38d66d5c9cc16411880e258899a6807b31477e3ac33ebaa64555126e9b29e7d5d2be88748aae8b1d05f91e5eb3aef4847a033af25b8a0c0f995b037 + languageName: node + linkType: hard + "base64-js@npm:^1.0.2, base64-js@npm:^1.1.2, base64-js@npm:^1.3.1, base64-js@npm:^1.5.1": version: 1.5.1 resolution: "base64-js@npm:1.5.1" @@ -14230,6 +14267,15 @@ __metadata: languageName: node linkType: hard +"bs58@npm:^3.0.0": + version: 3.1.0 + resolution: "bs58@npm:3.1.0" + dependencies: + base-x: ^1.1.0 + checksum: 6d757a49958c43bc630f3b327511ce3ee065307c24240aa86189f72df0a4a8245c7ce7e7abad209b637f155006952c7b8f04bb4aa6ee4212a891882424bca82e + languageName: node + linkType: hard + "bs58@npm:^4.0.0, bs58@npm:^4.0.1": version: 4.0.1 resolution: "bs58@npm:4.0.1" @@ -15625,13 +15671,20 @@ __metadata: languageName: node linkType: hard -"csstype@npm:^3.0.2, csstype@npm:^3.1.0": +"csstype@npm:^3.0.2": version: 3.1.2 resolution: "csstype@npm:3.1.2" checksum: e1a52e6c25c1314d6beef5168da704ab29c5186b877c07d822bd0806717d9a265e8493a2e35ca7e68d0f5d472d43fac1cdce70fd79fd0853dff81f3028d857b5 languageName: node linkType: hard +"csstype@npm:^3.1.0": + version: 3.1.3 + resolution: "csstype@npm:3.1.3" + checksum: 8db785cc92d259102725b3c694ec0c823f5619a84741b5c7991b8ad135dfaa66093038a1cc63e03361a6cd28d122be48f2106ae72334e067dd619a51f49eddf7 + languageName: node + linkType: hard + "csv-generate@npm:^4.3.0": version: 4.3.0 resolution: "csv-generate@npm:4.3.0" @@ -20971,6 +21024,22 @@ __metadata: languageName: node linkType: hard +"libsodium-wrappers@npm:^0.7.13": + version: 0.7.13 + resolution: "libsodium-wrappers@npm:0.7.13" + dependencies: + libsodium: ^0.7.13 + checksum: d184395f7c33023414b191ef9ea2171eb1a5cb061503e886ea877590cb7adc3a4feaf794b9b08731a20515518fa23dbf1c1bfcd376e5ab01728e95cf1cb7525a + languageName: node + linkType: hard + +"libsodium@npm:^0.7.13": + version: 0.7.13 + resolution: "libsodium@npm:0.7.13" + checksum: 75a5f70e84c197d54d9b67dcbd852abbd41cca8facd510767c7c8400a52a23da293e83eebf1693831b2c0c0498f266bd9350a8c27ec66f46a055890dff758d38 + languageName: node + linkType: hard + "lines-and-columns@npm:^1.1.6": version: 1.2.4 resolution: "lines-and-columns@npm:1.2.4" @@ -23276,6 +23345,16 @@ __metadata: languageName: node linkType: hard +"p-memoize@npm:^7.1.1": + version: 7.1.1 + resolution: "p-memoize@npm:7.1.1" + dependencies: + mimic-fn: ^4.0.0 + type-fest: ^3.0.0 + checksum: 2fc5b12fc530aed9c1e455f706d8da2a2e6bed4573f611a4e92b2a75f253e8c0acc63ad014b55f155b5d5de110c586b490a4d6612d64bc743106cad626d995fd + languageName: node + linkType: hard + "p-throttle@npm:^5.1.0": version: 5.1.0 resolution: "p-throttle@npm:5.1.0" @@ -25954,10 +26033,10 @@ __metadata: languageName: node linkType: hard -"seroval@npm:^0.14.1": - version: 0.14.1 - resolution: "seroval@npm:0.14.1" - checksum: 58f4ceabb6b1a56d4703ba081cc62950c6224e4dbcb336996eb31184e9ce0955889eab144803a651aefcd1af35c0d25d9c0cde100b66b8373268fdba60b7327b +"seroval@npm:^0.15.1": + version: 0.15.1 + resolution: "seroval@npm:0.15.1" + checksum: 9d84fa556178abb716e5611b68daea0da9984953a4585206047a81a6a2e7402b546778bccf53ab6a1bff14cef4b96a68deaca1032cbd25f2daaa57046cc4e168 languageName: node linkType: hard @@ -26316,12 +26395,12 @@ __metadata: linkType: hard "solid-js@npm:^1.6.6": - version: 1.8.6 - resolution: "solid-js@npm:1.8.6" + version: 1.8.7 + resolution: "solid-js@npm:1.8.7" dependencies: csstype: ^3.1.0 - seroval: ^0.14.1 - checksum: 78d0ba89cc46a74eb4c60d9e620432c9c1499523b13357b386de2334300dec617b6b5f0ce53c90eedf9e7a83fbbfd5f286d0a5ee85d0ff2530ddabc6bc6615b1 + seroval: ^0.15.1 + checksum: 44a9780e0f9ba2667e96e340b1ee1f33d8844a0b962c9c986049ec953b5bdf72077b53a90524cc98cef279ee4c9a6f06b820be4c5e81ebe8f110b912f22e2ee2 languageName: node linkType: hard From 5c980d27a23426a8eb58734685b5ce180c9278d4 Mon Sep 17 00:00:00 2001 From: Tan Le Date: Fri, 8 Dec 2023 11:46:40 +0700 Subject: [PATCH 14/21] feat: handle sign payload request on tezos --- apps/web/scripts/content/tezos.ts | 50 ++++++++++++++++++--- apps/web/scripts/kernel/handlers/kernel.ts | 9 ++++ apps/web/scripts/kernel/handlers/tezos.ts | 16 +++++++ apps/web/scripts/kernel/utils/middleware.ts | 24 ++++++++++ apps/web/src/bridge/listeners/index.ts | 8 +++- 5 files changed, 100 insertions(+), 7 deletions(-) diff --git a/apps/web/scripts/content/tezos.ts b/apps/web/scripts/content/tezos.ts index b7a801eb4..bfc3377d2 100644 --- a/apps/web/scripts/content/tezos.ts +++ b/apps/web/scripts/content/tezos.ts @@ -2,6 +2,8 @@ import type { PermissionRequest, PostMessagePairingRequest, PostMessagePairingResponse, + SignPayloadRequest, + SignPayloadResponse, } from '@airgap/beacon-sdk'; import { BeaconMessageType, @@ -38,10 +40,11 @@ const WALLESS_TEZOS = { }; const keypair = generateKeyPair(); -let recipientPublicKey: string; +let recipientPublicKey: string; // TODO: need to store the public key of dApp let origin: string; window.addEventListener('message', async (e) => { + console.log('On message', e.data, e.origin); const isNotTezosRequest = e.data?.target !== ExtensionMessageTarget.EXTENSION; const wrongTarget = e.data?.targetId && e.data?.targetId !== WALLESS_TEZOS.id; if (isNotTezosRequest || wrongTarget) { @@ -107,11 +110,14 @@ const handleEncryptedRequest = async (encryptedPayload: string) => { sendAckMessage(payload.id); if (payload.type === BeaconMessageType.PermissionRequest) { + console.log('handle permission request'); handlePermissionRequest(payload as never); } else if (payload.type === BeaconMessageType.Disconnect) { console.log('handle disconnect'); + handleDisconnect(); } else if (payload.type === BeaconMessageType.SignPayloadRequest) { console.log('handle sign payload'); + handleSignPayloadRequest(payload as never); } else if (payload.type === BeaconMessageType.OperationRequest) { console.log('handle operation request'); } else { @@ -142,6 +148,26 @@ const handlePermissionRequest = async (payload: PermissionRequest) => { respondWithSharedKeyEncrypt(resPayload); }; +const handleSignPayloadRequest = async (payload: SignPayloadRequest) => { + const res = await messenger.request('kernel', { + from: 'walless@sdk', + type: RequestType.SIGN_PAYLOAD_ON_TEZOS, + payload: payload.payload, + signingType: payload.signingType, + }); + + const resPayload: SignPayloadResponse = { + id: payload.id, + signature: res.signature, + signingType: payload.signingType, + type: BeaconMessageType.SignPayloadResponse, + senderId: payload.senderId, + version: '2', + }; + + respondWithSharedKeyEncrypt(resPayload); +}; + const sendAckMessage = async (requestId: string) => { const resPayload = { type: BeaconMessageType.Acknowledge, @@ -161,7 +187,9 @@ const decryptPayload = async (encryptedPayload: string) => { return deserialize(payload); } catch (e) { + // TODO: need to respond error to client side console.log('error decrypting payload', e); + handleDisconnect(); } }; @@ -172,10 +200,20 @@ const respondWithSharedKeyEncrypt = async (payload: UnknownObject) => { sharedKey.send, ); window.postMessage({ - message: { - target: ExtensionMessageTarget.PAGE, - encryptedPayload, - }, - sender: { id: WALLESS_TEZOS.id }, + message: { + target: ExtensionMessageTarget.PAGE, + encryptedPayload, + }, + sender: { id: WALLESS_TEZOS.id }, + }); +}; + +const handleDisconnect = () => { + messenger.request<{ options: ConnectOptions }>('kernel', { + from: 'walless@sdk', + type: RequestType.REQUEST_DISCONNECT, + options: { + domain: origin, + }, }); }; diff --git a/apps/web/scripts/kernel/handlers/kernel.ts b/apps/web/scripts/kernel/handlers/kernel.ts index 17e044d12..41da6497d 100644 --- a/apps/web/scripts/kernel/handlers/kernel.ts +++ b/apps/web/scripts/kernel/handlers/kernel.ts @@ -6,6 +6,7 @@ import { handle } from '../utils/handle'; import { checkApproval, checkConnection, + deserializePayloadToMessageOnTezos, filterSDKSignatureRequest, forwardToSourceRequest, getPrivateKey, @@ -83,6 +84,14 @@ export const onKernelMessage: MessengerCallback = async (payload, channel) => { getPrivateKey(Networks.sui), sui.signAndExecuteTransaction, ]); + } else if (payload.type === RequestType.SIGN_PAYLOAD_ON_TEZOS) { + handle(payload).execute([ + deserializePayloadToMessageOnTezos, + filterSDKSignatureRequest, + getPrivateKey(Networks.tezos), + forwardToSourceRequest, + tezos.signPayload, + ]); } else if (payload.type === RequestType.TRANSFER_TEZOS_TOKEN) { handle(payload).execute([ getPrivateKey(Networks.tezos), diff --git a/apps/web/scripts/kernel/handlers/tezos.ts b/apps/web/scripts/kernel/handlers/tezos.ts index 5f28b2cc5..69144e829 100644 --- a/apps/web/scripts/kernel/handlers/tezos.ts +++ b/apps/web/scripts/kernel/handlers/tezos.ts @@ -1,9 +1,25 @@ +import { signMessage as tzSignMessage } from '@airgap/beacon-utils'; import { tezosHandler } from '@walless/kernel'; import { ResponseCode } from '@walless/messaging'; import { respond } from '../utils/requestPool'; import type { HandleMethod } from '../utils/types'; +export const signPayload: HandleMethod<{ + privateKey?: Uint8Array; + payload?: string; +}> = async ({ payload }) => { + if (!payload.privateKey || !payload.payload) { + throw Error('Missing privateKey or message'); + } + + const signature = await tzSignMessage(payload.payload as string, { + secretKey: Buffer.from(payload.privateKey), + }); + + respond(payload.requestId, ResponseCode.SUCCESS, { signature }); +}; + export const transferToken: HandleMethod<{ privateKey?: Uint8Array; transaction?: string; diff --git a/apps/web/scripts/kernel/utils/middleware.ts b/apps/web/scripts/kernel/utils/middleware.ts index 486e20c89..6a35f3557 100644 --- a/apps/web/scripts/kernel/utils/middleware.ts +++ b/apps/web/scripts/kernel/utils/middleware.ts @@ -87,6 +87,30 @@ export const checkApproval: HandleMethod<{ respond(requestId, ResponseCode.SUCCESS); }; +export const deserializePayloadToMessageOnTezos: HandleMethod<{ + payload?: string; + signingType?: string; +}> = ({ payload, next }) => { + if (payload.from === 'walless@sdk') { + if (!payload.payload || !payload.signingType) + throw Error('Missing payload or signingType'); + + let message: string; + try { + if (payload.signingType === 'raw') { + message = Buffer.from(payload.payload, 'hex').toString(); + payload.message = message; + } else { + throw Error('not handle this signing'); + } + } catch (e) { + console.log('deserialize failed', e); + } + } + + next?.(payload); +}; + export const filterSDKSignatureRequest: HandleMethod<{ isApproved?: boolean; }> = async ({ payload, next }) => { diff --git a/apps/web/src/bridge/listeners/index.ts b/apps/web/src/bridge/listeners/index.ts index 28f6541ac..f4107a296 100644 --- a/apps/web/src/bridge/listeners/index.ts +++ b/apps/web/src/bridge/listeners/index.ts @@ -98,7 +98,13 @@ export const getDataFromSourceRequest = async ( ); if ('message' in res) { - const displayMessage = new TextDecoder().decode(bs58.decode(res.message)); + let displayMessage; + try { + displayMessage = new TextDecoder().decode(bs58.decode(res.message)); + } catch { + displayMessage = res.message; + } + return { ...res, message: displayMessage, From 8ee9ae5d208bafbaf1ee97b7ada79f00b7789467 Mon Sep 17 00:00:00 2001 From: Tan Le Date: Fri, 8 Dec 2023 11:47:11 +0700 Subject: [PATCH 15/21] feat: add simple tezos wallet sdk doc --- docs/tezos_wallet_sdk.md | 7 +++++++ 1 file changed, 7 insertions(+) create mode 100644 docs/tezos_wallet_sdk.md diff --git a/docs/tezos_wallet_sdk.md b/docs/tezos_wallet_sdk.md new file mode 100644 index 000000000..47bb14a92 --- /dev/null +++ b/docs/tezos_wallet_sdk.md @@ -0,0 +1,7 @@ +# Tezos wallet SDK + +Tezos network uses [tzip10](https://gitlab.com/tezos/tzip/-/blob/master/proposals/tzip-10/tzip-10.md) standard for communication between `dApp` and `wallet`. The standard defined both communication channel as well as request structure and error handling when communicating. + +[Beacon SDK](https://github.com/airgap-it/beacon-sdk) is an implementation of Tzip10, but it just supports well for dApp at the time. We use Beacon SDK for the dApp example have a look of encryption layer (known as transport layer). + +You need to read the tzip10 standard carefully to understand how the transport layer work. From 07cb93bf97cee81c2335d0e628be69d26f79443e Mon Sep 17 00:00:00 2001 From: Tan Le Date: Fri, 8 Dec 2023 18:23:36 +0700 Subject: [PATCH 16/21] feat: impl persist transport keypair and recipient public key --- apps/web/scripts/content/utils.ts | 46 +++++++++++++++++++++++++++++++ 1 file changed, 46 insertions(+) diff --git a/apps/web/scripts/content/utils.ts b/apps/web/scripts/content/utils.ts index 36502c985..792c96106 100644 --- a/apps/web/scripts/content/utils.ts +++ b/apps/web/scripts/content/utils.ts @@ -1,4 +1,8 @@ import type { UnknownObject } from '@walless/core'; +import { + extractPublicKeyFromSecretKey, + generateKeyPair, +} from '@walless/crypto/utils/p2p'; import { decode, encode } from 'bs58check'; export const injectScript = (scriptUri: string) => { @@ -21,3 +25,45 @@ export const serialize = (data: UnknownObject): string => { export const deserialize = (encoded: string): UnknownObject => { return JSON.parse(decode(encoded).toString()); }; + +export const getOrCreateKeypair = async (create = false) => { + if (create) { + const keypair = generateKeyPair(); + chrome.storage.local.set({ + transport_secret_key: Buffer.from(keypair.secretKey).toString('hex'), + }); + return keypair; + } else { + const result = await chrome.storage.local.get(['transport_secret_key']); + const secretKeyString = result['transport_secret_key'] as string; + if (secretKeyString) { + const secretKey = new Uint8Array(Buffer.from(secretKeyString, 'hex')); + const keypair = { + publicKey: extractPublicKeyFromSecretKey(secretKey), + secretKey, + }; + + return keypair; + } else { + const keypair = generateKeyPair(); + chrome.storage.local.set({ + transport_secret_key: Buffer.from(keypair.secretKey).toString('hex'), + }); + + return keypair; + } + } +}; + +export const storeDAppPublicKey = async (publicKey: string) => { + await chrome.storage.local.set({ dapp_public_key: publicKey }); + return publicKey; +}; + +export const getDAppPublicKey = async () => { + const result = await chrome.storage.local.get(['dapp_public_key']); + const publicKey = result['dapp_public_key'] as string; + if (!publicKey) throw Error('Not found dapp public key'); + console.log(publicKey, '<-- dapp public key'); + return publicKey; +}; From 22c2ff86b67f9bedd3571a920d40b0905038d5bc Mon Sep 17 00:00:00 2001 From: Tan Le Date: Fri, 8 Dec 2023 18:24:15 +0700 Subject: [PATCH 17/21] feat: use persist keys --- apps/web/scripts/content/tezos.ts | 39 +++++++++++++++++++------------ packages/crypto/utils/p2p.ts | 10 +++++--- 2 files changed, 31 insertions(+), 18 deletions(-) diff --git a/apps/web/scripts/content/tezos.ts b/apps/web/scripts/content/tezos.ts index bfc3377d2..140274b02 100644 --- a/apps/web/scripts/content/tezos.ts +++ b/apps/web/scripts/content/tezos.ts @@ -7,26 +7,29 @@ import type { } from '@airgap/beacon-sdk'; import { BeaconMessageType, - NetworkType, - PermissionScope, -} from '@airgap/beacon-sdk'; -import { ExtensionMessageTarget } from '@airgap/beacon-sdk'; -import { decryptCryptoboxPayload, encryptCryptoboxPayload, + ExtensionMessageTarget, + NetworkType, + PermissionScope, sealCryptobox, -} from '@airgap/beacon-utils'; -import type { ConnectOptions } from '@walless/core'; -import { Networks, type UnknownObject } from '@walless/core'; +} from '@airgap/beacon-sdk'; +import type { ConnectOptions, UnknownObject } from '@walless/core'; +import { Networks } from '@walless/core'; import { createCryptoBoxClient, createCryptoBoxServer, - generateKeyPair, } from '@walless/crypto/utils/p2p'; import { RequestType } from '@walless/messaging'; import { messenger } from './messaging'; -import { deserialize, serialize } from './utils'; +import { + deserialize, + getDAppPublicKey, + getOrCreateKeypair, + serialize, + storeDAppPublicKey, +} from './utils'; const TEZOS_PAIRING_REQUEST = 'postmessage-pairing-request'; const TEZOS_PAIRING_RESPONSE = 'postmessage-pairing-response'; @@ -39,12 +42,10 @@ const WALLESS_TEZOS = { version: '3', }; -const keypair = generateKeyPair(); -let recipientPublicKey: string; // TODO: need to store the public key of dApp let origin: string; window.addEventListener('message', async (e) => { - console.log('On message', e.data, e.origin); + console.log('ON MESSAGE', e.data, e.origin); const isNotTezosRequest = e.data?.target !== ExtensionMessageTarget.EXTENSION; const wrongTarget = e.data?.targetId && e.data?.targetId !== WALLESS_TEZOS.id; if (isNotTezosRequest || wrongTarget) { @@ -77,13 +78,16 @@ const handlePingPong = () => { }; const handlePairingRequest = async (payload: PostMessagePairingRequest) => { + console.log('HANDSHAKE REQUEST', payload); + const keypair = await getOrCreateKeypair(true); + const recipientPublicKey = await storeDAppPublicKey(payload.publicKey); + const resPayload: PostMessagePairingResponse = { type: TEZOS_PAIRING_RESPONSE, publicKey: Buffer.from(keypair.publicKey).toString('hex'), ...WALLESS_TEZOS, }; - recipientPublicKey = payload.publicKey; const recipientPublicKeyBytes = Uint8Array.from( Buffer.from(recipientPublicKey, 'hex'), ); @@ -126,7 +130,7 @@ const handleEncryptedRequest = async (encryptedPayload: string) => { }; const handlePermissionRequest = async (payload: PermissionRequest) => { - // TODO: check network is valid or net, throw error if not + // TODO: check network is valid or not, throw error if not const res = await messenger.request<{ options: ConnectOptions }>('kernel', { from: 'walless@sdk', type: RequestType.REQUEST_CONNECT, @@ -178,6 +182,8 @@ const sendAckMessage = async (requestId: string) => { }; const decryptPayload = async (encryptedPayload: string) => { + const keypair = await getOrCreateKeypair(); + const recipientPublicKey = await getDAppPublicKey(); const sharedKey = await createCryptoBoxServer(recipientPublicKey, keypair); try { const payload = await decryptCryptoboxPayload( @@ -194,11 +200,14 @@ const decryptPayload = async (encryptedPayload: string) => { }; const respondWithSharedKeyEncrypt = async (payload: UnknownObject) => { + const keypair = await getOrCreateKeypair(); + const recipientPublicKey = await getDAppPublicKey(); const sharedKey = await createCryptoBoxClient(recipientPublicKey, keypair); const encryptedPayload = await encryptCryptoboxPayload( serialize(payload), sharedKey.send, ); + window.postMessage({ message: { target: ExtensionMessageTarget.PAGE, diff --git a/packages/crypto/utils/p2p.ts b/packages/crypto/utils/p2p.ts index 4d6e23d57..a8dc265d3 100644 --- a/packages/crypto/utils/p2p.ts +++ b/packages/crypto/utils/p2p.ts @@ -65,8 +65,8 @@ export const decryptMessage = async ( payload: Uint8Array, recipientPublicKey: string, keypair: KeyPair, -) => { - const sharedKey = await createCryptoBoxClient(recipientPublicKey, keypair); +): Promise => { + const sharedKey = await createCryptoBoxServer(recipientPublicKey, keypair); const nonce = payload.slice(0, secretbox_NONCEBYTES); const ciphertext = payload.slice(secretbox_NONCEBYTES); @@ -87,4 +87,8 @@ export const deserialize = (encoded: string): UnknownObject => { return JSON.parse(decode(encoded).toString()); }; -export { generateKeyPair } from '@stablelib/ed25519'; +export { + extractPublicKeyFromSecretKey, + generateKeyPair, + type KeyPair, +} from '@stablelib/ed25519'; From 7ff6966e70043a9a642aa55b008098340aa93ab9 Mon Sep 17 00:00:00 2001 From: Tan Le Date: Fri, 8 Dec 2023 18:28:49 +0700 Subject: [PATCH 18/21] chore: add timeout to kernel request --- apps/web/scripts/content/tezos.ts | 39 +++++++++++++++++++------------ 1 file changed, 24 insertions(+), 15 deletions(-) diff --git a/apps/web/scripts/content/tezos.ts b/apps/web/scripts/content/tezos.ts index 140274b02..0249beb01 100644 --- a/apps/web/scripts/content/tezos.ts +++ b/apps/web/scripts/content/tezos.ts @@ -34,6 +34,8 @@ import { const TEZOS_PAIRING_REQUEST = 'postmessage-pairing-request'; const TEZOS_PAIRING_RESPONSE = 'postmessage-pairing-response'; +const ONE_MINUTE_TO_MS = 60000; + const WALLESS_TEZOS = { id: chrome.runtime.id, name: 'Walless', @@ -109,7 +111,6 @@ const handlePairingRequest = async (payload: PostMessagePairingRequest) => { const handleEncryptedRequest = async (encryptedPayload: string) => { if (typeof encryptedPayload !== 'string') return; const payload = await decryptPayload(encryptedPayload); - console.log(payload, '<-- payload after decrypt'); if (!payload || !payload.type) return; sendAckMessage(payload.id); @@ -131,15 +132,19 @@ const handleEncryptedRequest = async (encryptedPayload: string) => { const handlePermissionRequest = async (payload: PermissionRequest) => { // TODO: check network is valid or not, throw error if not - const res = await messenger.request<{ options: ConnectOptions }>('kernel', { - from: 'walless@sdk', - type: RequestType.REQUEST_CONNECT, - options: { - network: Networks.tezos, - domain: origin, - onlyIfTrusted: true, + const res = await messenger.request<{ options: ConnectOptions }>( + 'kernel', + { + from: 'walless@sdk', + type: RequestType.REQUEST_CONNECT, + options: { + network: Networks.tezos, + domain: origin, + onlyIfTrusted: true, + }, }, - }); + ONE_MINUTE_TO_MS, + ); const resPayload = { id: payload.id, @@ -153,12 +158,16 @@ const handlePermissionRequest = async (payload: PermissionRequest) => { }; const handleSignPayloadRequest = async (payload: SignPayloadRequest) => { - const res = await messenger.request('kernel', { - from: 'walless@sdk', - type: RequestType.SIGN_PAYLOAD_ON_TEZOS, - payload: payload.payload, - signingType: payload.signingType, - }); + const res = await messenger.request( + 'kernel', + { + from: 'walless@sdk', + type: RequestType.SIGN_PAYLOAD_ON_TEZOS, + payload: payload.payload, + signingType: payload.signingType, + }, + ONE_MINUTE_TO_MS, + ); const resPayload: SignPayloadResponse = { id: payload.id, From 02104d423e611eedbe074d1da3ca9872d0d93716 Mon Sep 17 00:00:00 2001 From: Tan Le Date: Fri, 8 Dec 2023 19:07:51 +0700 Subject: [PATCH 19/21] fix: store keys with origin for different dapps --- apps/web/scripts/content/tezos.ts | 17 ++++++++-------- apps/web/scripts/content/utils.ts | 32 +++++++++++++++++++++---------- 2 files changed, 31 insertions(+), 18 deletions(-) diff --git a/apps/web/scripts/content/tezos.ts b/apps/web/scripts/content/tezos.ts index 0249beb01..cee77ee99 100644 --- a/apps/web/scripts/content/tezos.ts +++ b/apps/web/scripts/content/tezos.ts @@ -44,8 +44,6 @@ const WALLESS_TEZOS = { version: '3', }; -let origin: string; - window.addEventListener('message', async (e) => { console.log('ON MESSAGE', e.data, e.origin); const isNotTezosRequest = e.data?.target !== ExtensionMessageTarget.EXTENSION; @@ -81,8 +79,11 @@ const handlePingPong = () => { const handlePairingRequest = async (payload: PostMessagePairingRequest) => { console.log('HANDSHAKE REQUEST', payload); - const keypair = await getOrCreateKeypair(true); - const recipientPublicKey = await storeDAppPublicKey(payload.publicKey); + const keypair = await getOrCreateKeypair(origin, true); + const recipientPublicKey = await storeDAppPublicKey( + origin, + payload.publicKey, + ); const resPayload: PostMessagePairingResponse = { type: TEZOS_PAIRING_RESPONSE, @@ -191,8 +192,8 @@ const sendAckMessage = async (requestId: string) => { }; const decryptPayload = async (encryptedPayload: string) => { - const keypair = await getOrCreateKeypair(); - const recipientPublicKey = await getDAppPublicKey(); + const keypair = await getOrCreateKeypair(origin); + const recipientPublicKey = await getDAppPublicKey(origin); const sharedKey = await createCryptoBoxServer(recipientPublicKey, keypair); try { const payload = await decryptCryptoboxPayload( @@ -209,8 +210,8 @@ const decryptPayload = async (encryptedPayload: string) => { }; const respondWithSharedKeyEncrypt = async (payload: UnknownObject) => { - const keypair = await getOrCreateKeypair(); - const recipientPublicKey = await getDAppPublicKey(); + const keypair = await getOrCreateKeypair(origin); + const recipientPublicKey = await getDAppPublicKey(origin); const sharedKey = await createCryptoBoxClient(recipientPublicKey, keypair); const encryptedPayload = await encryptCryptoboxPayload( serialize(payload), diff --git a/apps/web/scripts/content/utils.ts b/apps/web/scripts/content/utils.ts index 792c96106..945e4649b 100644 --- a/apps/web/scripts/content/utils.ts +++ b/apps/web/scripts/content/utils.ts @@ -26,16 +26,21 @@ export const deserialize = (encoded: string): UnknownObject => { return JSON.parse(decode(encoded).toString()); }; -export const getOrCreateKeypair = async (create = false) => { +export const getOrCreateKeypair = async (origin: string, create = false) => { + if (!origin) throw Error('require origin'); + + const key = 'transport_secret_key:' + origin; if (create) { const keypair = generateKeyPair(); chrome.storage.local.set({ - transport_secret_key: Buffer.from(keypair.secretKey).toString('hex'), + [key]: Buffer.from(keypair.secretKey).toString('hex'), }); + return keypair; } else { - const result = await chrome.storage.local.get(['transport_secret_key']); - const secretKeyString = result['transport_secret_key'] as string; + const result = await chrome.storage.local.get([key]); + const secretKeyString = result[key] as string; + if (secretKeyString) { const secretKey = new Uint8Array(Buffer.from(secretKeyString, 'hex')); const keypair = { @@ -55,15 +60,22 @@ export const getOrCreateKeypair = async (create = false) => { } }; -export const storeDAppPublicKey = async (publicKey: string) => { - await chrome.storage.local.set({ dapp_public_key: publicKey }); +export const storeDAppPublicKey = async (origin: string, publicKey: string) => { + if (!origin) throw Error('require origin'); + const key = 'dapp_public_key:' + origin; + await chrome.storage.local.set({ [key]: publicKey }); + return publicKey; }; -export const getDAppPublicKey = async () => { - const result = await chrome.storage.local.get(['dapp_public_key']); - const publicKey = result['dapp_public_key'] as string; +export const getDAppPublicKey = async (origin: string) => { + if (!origin) throw Error('require origin'); + + const key = 'dapp_public_key:' + origin; + const result = await chrome.storage.local.get([key]); + const publicKey = result[key]; + if (!publicKey) throw Error('Not found dapp public key'); - console.log(publicKey, '<-- dapp public key'); + return publicKey; }; From d20aada7f60f9b86956532445875cc582f4186c9 Mon Sep 17 00:00:00 2001 From: Tan Le Date: Fri, 8 Dec 2023 20:27:51 +0700 Subject: [PATCH 20/21] fix: complete sign payload on tezos by using built-in signer --- apps/web/scripts/content/tezos.ts | 2 - apps/web/scripts/kernel/handlers/tezos.ts | 11 ++--- apps/web/scripts/kernel/utils/middleware.ts | 8 +++- docs/tezos_wallet_sdk.md | 2 + yarn.lock | 47 +-------------------- 5 files changed, 17 insertions(+), 53 deletions(-) diff --git a/apps/web/scripts/content/tezos.ts b/apps/web/scripts/content/tezos.ts index cee77ee99..29217fb6b 100644 --- a/apps/web/scripts/content/tezos.ts +++ b/apps/web/scripts/content/tezos.ts @@ -45,7 +45,6 @@ const WALLESS_TEZOS = { }; window.addEventListener('message', async (e) => { - console.log('ON MESSAGE', e.data, e.origin); const isNotTezosRequest = e.data?.target !== ExtensionMessageTarget.EXTENSION; const wrongTarget = e.data?.targetId && e.data?.targetId !== WALLESS_TEZOS.id; if (isNotTezosRequest || wrongTarget) { @@ -78,7 +77,6 @@ const handlePingPong = () => { }; const handlePairingRequest = async (payload: PostMessagePairingRequest) => { - console.log('HANDSHAKE REQUEST', payload); const keypair = await getOrCreateKeypair(origin, true); const recipientPublicKey = await storeDAppPublicKey( origin, diff --git a/apps/web/scripts/kernel/handlers/tezos.ts b/apps/web/scripts/kernel/handlers/tezos.ts index 69144e829..4b93afdf9 100644 --- a/apps/web/scripts/kernel/handlers/tezos.ts +++ b/apps/web/scripts/kernel/handlers/tezos.ts @@ -1,6 +1,7 @@ -import { signMessage as tzSignMessage } from '@airgap/beacon-utils'; +import { InMemorySigner } from '@taquito/signer'; import { tezosHandler } from '@walless/kernel'; import { ResponseCode } from '@walless/messaging'; +import { encode } from 'bs58'; import { respond } from '../utils/requestPool'; import type { HandleMethod } from '../utils/types'; @@ -13,11 +14,11 @@ export const signPayload: HandleMethod<{ throw Error('Missing privateKey or message'); } - const signature = await tzSignMessage(payload.payload as string, { - secretKey: Buffer.from(payload.privateKey), - }); + const privateKey = encode(payload.privateKey); + const signer = await InMemorySigner.fromSecretKey(privateKey); + const { prefixSig } = await signer.sign(payload.payload as string); - respond(payload.requestId, ResponseCode.SUCCESS, { signature }); + respond(payload.requestId, ResponseCode.SUCCESS, { signature: prefixSig }); }; export const transferToken: HandleMethod<{ diff --git a/apps/web/scripts/kernel/utils/middleware.ts b/apps/web/scripts/kernel/utils/middleware.ts index 6a35f3557..193442b65 100644 --- a/apps/web/scripts/kernel/utils/middleware.ts +++ b/apps/web/scripts/kernel/utils/middleware.ts @@ -100,8 +100,14 @@ export const deserializePayloadToMessageOnTezos: HandleMethod<{ if (payload.signingType === 'raw') { message = Buffer.from(payload.payload, 'hex').toString(); payload.message = message; + } else if ( + payload.signingType === 'operation' || + payload.signingType === 'micheline' + ) { + message = Buffer.from(payload.payload, 'hex').toString(); + payload.message = message; } else { - throw Error('not handle this signing'); + throw Error(`can not handle this signing type ${payload.signingType}`); } } catch (e) { console.log('deserialize failed', e); diff --git a/docs/tezos_wallet_sdk.md b/docs/tezos_wallet_sdk.md index 47bb14a92..489bba43f 100644 --- a/docs/tezos_wallet_sdk.md +++ b/docs/tezos_wallet_sdk.md @@ -5,3 +5,5 @@ Tezos network uses [tzip10](https://gitlab.com/tezos/tzip/-/blob/master/proposal [Beacon SDK](https://github.com/airgap-it/beacon-sdk) is an implementation of Tzip10, but it just supports well for dApp at the time. We use Beacon SDK for the dApp example have a look of encryption layer (known as transport layer). You need to read the tzip10 standard carefully to understand how the transport layer work. + +Signing mechanism: [https://tezostaquito.io/docs/signing/](https://tezostaquito.io/docs/signing/) diff --git a/yarn.lock b/yarn.lock index c128fefbf..71665f190 100644 --- a/yarn.lock +++ b/yarn.lock @@ -11136,13 +11136,6 @@ __metadata: languageName: node linkType: hard -"@types/libsodium-wrappers@npm:^0.7.13": - version: 0.7.13 - resolution: "@types/libsodium-wrappers@npm:0.7.13" - checksum: 94d608bed8ccd364754c3a7bf5d4c770b229efa33f0c475061b1b82bb8d5da8d57a72df0b8876b887077edbb6ff9594b7a1183029de4d1ad679821d1013f3db9 - languageName: node - linkType: hard - "@types/lodash@npm:^4.14.191": version: 4.14.201 resolution: "@types/lodash@npm:4.14.201" @@ -11360,13 +11353,6 @@ __metadata: languageName: node linkType: hard -"@types/webextension-polyfill@npm:^0.10.7": - version: 0.10.7 - resolution: "@types/webextension-polyfill@npm:0.10.7" - checksum: 372064d5e007ab7889ea4f7b634d311f85bb78b13bf174a28781699ca21e8daa61ccd371dafe6b3f4fa3c9fe1fee11a5dbe52ed66f3cf84c1738cd18a535cbb7 - languageName: node - linkType: hard - "@types/ws@npm:*, @types/ws@npm:^8.0.0": version: 8.5.9 resolution: "@types/ws@npm:8.5.9" @@ -11632,8 +11618,10 @@ __metadata: version: 0.0.0-use.local resolution: "@walless/crypto@workspace:packages/crypto" dependencies: + "@stablelib/blake2b": ^1.0.1 "@stablelib/ed25519": ^1.0.3 "@stablelib/nacl": ^1.0.4 + "@stablelib/utf8": ^1.0.1 "@stablelib/x25519-session": ^1.0.4 "@walless/core": "*" base58check: ^2.0.0 @@ -11993,8 +11981,6 @@ __metadata: "@solana/spl-token": 0.3.7 "@solana/web3.js": 1.78.4 "@taquito/signer": ^16.2.0 - "@types/libsodium-wrappers": ^0.7.13 - "@types/webextension-polyfill": ^0.10.7 "@walless/core": "*" "@walless/crypto": "*" "@walless/engine": "*" @@ -12016,9 +12002,7 @@ __metadata: eslint: 8.38.0 firebase: 10.7.0 graphql-request: ^6.1.0 - libsodium-wrappers: ^0.7.13 numeral: ^2.0.6 - p-memoize: ^7.1.1 pouchdb-adapter-http: ^8.0.1 pouchdb-adapter-idb: ^8.0.1 pouchdb-core: ^8.0.1 @@ -12034,7 +12018,6 @@ __metadata: rimraf: ^5.0.1 setimmediate: ^1.0.5 valtio: 1.10.5 - webextension-polyfill: ^0.10.0 peerDependencies: "@tkey/chrome-storage": 9.0.0 "@tkey/default": 9.0.0 @@ -21024,22 +21007,6 @@ __metadata: languageName: node linkType: hard -"libsodium-wrappers@npm:^0.7.13": - version: 0.7.13 - resolution: "libsodium-wrappers@npm:0.7.13" - dependencies: - libsodium: ^0.7.13 - checksum: d184395f7c33023414b191ef9ea2171eb1a5cb061503e886ea877590cb7adc3a4feaf794b9b08731a20515518fa23dbf1c1bfcd376e5ab01728e95cf1cb7525a - languageName: node - linkType: hard - -"libsodium@npm:^0.7.13": - version: 0.7.13 - resolution: "libsodium@npm:0.7.13" - checksum: 75a5f70e84c197d54d9b67dcbd852abbd41cca8facd510767c7c8400a52a23da293e83eebf1693831b2c0c0498f266bd9350a8c27ec66f46a055890dff758d38 - languageName: node - linkType: hard - "lines-and-columns@npm:^1.1.6": version: 1.2.4 resolution: "lines-and-columns@npm:1.2.4" @@ -23345,16 +23312,6 @@ __metadata: languageName: node linkType: hard -"p-memoize@npm:^7.1.1": - version: 7.1.1 - resolution: "p-memoize@npm:7.1.1" - dependencies: - mimic-fn: ^4.0.0 - type-fest: ^3.0.0 - checksum: 2fc5b12fc530aed9c1e455f706d8da2a2e6bed4573f611a4e92b2a75f253e8c0acc63ad014b55f155b5d5de110c586b490a4d6612d64bc743106cad626d995fd - languageName: node - linkType: hard - "p-throttle@npm:^5.1.0": version: 5.1.0 resolution: "p-throttle@npm:5.1.0" From 3254b88ff854869c76164e00ab9043b4cd7a8254 Mon Sep 17 00:00:00 2001 From: Tan Le Date: Fri, 8 Dec 2023 20:58:09 +0700 Subject: [PATCH 21/21] chore: clean --- apps/web/scripts/content/index.ts | 2 +- apps/web/scripts/content/tezos.ts | 11 +++++++---- yarn.lock | 2 -- 3 files changed, 8 insertions(+), 7 deletions(-) diff --git a/apps/web/scripts/content/index.ts b/apps/web/scripts/content/index.ts index ff175edd3..9117bb78a 100644 --- a/apps/web/scripts/content/index.ts +++ b/apps/web/scripts/content/index.ts @@ -5,7 +5,7 @@ import { injectScript } from './utils'; (async () => { await initializeMessaging(); - console.log('[walless/prod] messaging module intialzied..'); + console.log('[walless/prod] messaging module initialized..'); setTimeout(() => { injectScript('injection.js'); diff --git a/apps/web/scripts/content/tezos.ts b/apps/web/scripts/content/tezos.ts index 29217fb6b..b00d0fc8c 100644 --- a/apps/web/scripts/content/tezos.ts +++ b/apps/web/scripts/content/tezos.ts @@ -1,4 +1,5 @@ import type { + OperationRequest, PermissionRequest, PostMessagePairingRequest, PostMessagePairingResponse, @@ -114,16 +115,13 @@ const handleEncryptedRequest = async (encryptedPayload: string) => { sendAckMessage(payload.id); if (payload.type === BeaconMessageType.PermissionRequest) { - console.log('handle permission request'); handlePermissionRequest(payload as never); } else if (payload.type === BeaconMessageType.Disconnect) { - console.log('handle disconnect'); handleDisconnect(); } else if (payload.type === BeaconMessageType.SignPayloadRequest) { - console.log('handle sign payload'); handleSignPayloadRequest(payload as never); } else if (payload.type === BeaconMessageType.OperationRequest) { - console.log('handle operation request'); + handleOperationRequest(payload as never); } else { console.log('not support this type of request'); } @@ -180,6 +178,11 @@ const handleSignPayloadRequest = async (payload: SignPayloadRequest) => { respondWithSharedKeyEncrypt(resPayload); }; +const handleOperationRequest = async (payload: OperationRequest) => { + // TODO: need to implement + console.log(payload); +}; + const sendAckMessage = async (requestId: string) => { const resPayload = { type: BeaconMessageType.Acknowledge, diff --git a/yarn.lock b/yarn.lock index 71665f190..699de6572 100644 --- a/yarn.lock +++ b/yarn.lock @@ -11618,10 +11618,8 @@ __metadata: version: 0.0.0-use.local resolution: "@walless/crypto@workspace:packages/crypto" dependencies: - "@stablelib/blake2b": ^1.0.1 "@stablelib/ed25519": ^1.0.3 "@stablelib/nacl": ^1.0.4 - "@stablelib/utf8": ^1.0.1 "@stablelib/x25519-session": ^1.0.4 "@walless/core": "*" base58check: ^2.0.0