From 52f059b3781f285385c4983d822d79c459080ddf Mon Sep 17 00:00:00 2001 From: Jimmy Madrigal Date: Tue, 20 Aug 2024 17:19:17 -0600 Subject: [PATCH] feat: use canvas wallet adapter --- package-lock.json | 315 +++++++++++++++++++++----------------- package.json | 5 +- src/App.tsx | 61 ++++---- src/canvas-adapter.ts | 144 ----------------- src/canvas-client.ts | 21 +++ src/main.tsx | 24 ++- src/use-canvas-adapter.ts | 162 ++++++++++++++++++++ 7 files changed, 405 insertions(+), 327 deletions(-) delete mode 100644 src/canvas-adapter.ts create mode 100644 src/canvas-client.ts create mode 100644 src/use-canvas-adapter.ts diff --git a/package-lock.json b/package-lock.json index bc5617d..62ddf1b 100644 --- a/package-lock.json +++ b/package-lock.json @@ -9,7 +9,10 @@ "version": "0.0.0", "dependencies": { "@dialectlabs/blinks": "^0.5.0", - "@dscvr-one/canvas-client-sdk": "^1.0.7", + "@dscvr-one/canvas-client-sdk": "^1.1.0", + "@dscvr-one/canvas-wallet-adapter": "^1.0.1", + "@solana/wallet-adapter-base": "^0.9.23", + "@solana/wallet-adapter-react": "^0.15.35", "@solana/web3.js": "^1.95.2", "base58": "^2.0.1", "react": "^18.3.1", @@ -2158,11 +2161,11 @@ } }, "node_modules/@dscvr-one/canvas-client-sdk": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/@dscvr-one/canvas-client-sdk/-/canvas-client-sdk-1.0.7.tgz", - "integrity": "sha512-l5AKxBgC/IrwoE020u1LWxSKpB6nbY/cC8YpDe8rCqKxa8zDuoxGJkvZHesVwzFyk0e76QO1kcuDOcAcXI5B6g==", + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@dscvr-one/canvas-client-sdk/-/canvas-client-sdk-1.1.0.tgz", + "integrity": "sha512-9ooMFjmJxPwYqIxyuztVcttLcYHIyxmYnsdtLCZTR2C0DKkKpUy5GlVY1YTABu4z1PpYXH1byTF+kg/BKTsJjw==", "dependencies": { - "@dscvr-one/canvas-interface": "^1.0.0", + "@dscvr-one/canvas-interface": "^1.1.0", "eventemitter3": "^5.0.1" } }, @@ -2172,10 +2175,106 @@ "integrity": "sha512-GWkBvjiSZK87ELrYOSESUYeVIc9mvLLf/nXalMOS5dYrgZq9o5OVkbZAVM06CVxYsCwH9BDZFPlQTlPA1j4ahA==" }, "node_modules/@dscvr-one/canvas-interface": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/@dscvr-one/canvas-interface/-/canvas-interface-1.0.6.tgz", - "integrity": "sha512-Yv0jtRchgJMshEjfAkFKgJ3NNhXeXeBxVKlxU/0evmoINeCsnMW/XSEaaHkPwzL6FYhL8S/SMFLZzWDM8F61Dw==", + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@dscvr-one/canvas-interface/-/canvas-interface-1.1.0.tgz", + "integrity": "sha512-/D9e24Msh0MKg9pm+KCHu+PsGwxowa816tP5Ze70JkIbot84hcDroivO7cfGXo7xz3UvRwKW//7Eb3S59klbYw==", + "dependencies": { + "zod": "^3.23.8" + } + }, + "node_modules/@dscvr-one/canvas-wallet-adapter": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@dscvr-one/canvas-wallet-adapter/-/canvas-wallet-adapter-1.0.1.tgz", + "integrity": "sha512-k+ZmulhEN86cryVT7QJL8E6g5rDmwhzVaoYn7Az58M54KLid5WAmW8fcdcoraCYbcPelCau7WMa3AEHV8oGEXg==", + "dependencies": { + "@dscvr-one/canvas-client-sdk": "^1.1.0", + "@dscvr-one/canvas-wallet-interface": "^1.0.0", + "@solana/wallet-adapter-base": "^0.9.23", + "@solana/wallet-standard": "^1.1.2", + "@solana/wallet-standard-wallet-adapter-base": "^1.1.2", + "@solana/web3.js": "^1.91.4", + "@wallet-standard/base": "0.0.0-20240703212708", + "@wallet-standard/core": "0.0.0-20240703212708", + "@wallet-standard/wallet": "0.0.0-20240703212708", + "bs58": "^5.0.0" + } + }, + "node_modules/@dscvr-one/canvas-wallet-adapter/node_modules/@wallet-standard/app": { + "version": "0.0.0-20240703212708", + "resolved": "https://registry.npmjs.org/@wallet-standard/app/-/app-0.0.0-20240703212708.tgz", + "integrity": "sha512-9dbm+DtuhD48u0pMXs0vairkCvN1PGzhb2SWCeYNT3bmaYGkv7XfkpNLFf8O8xngm0WdM0pbP9WRfxaJfEIN6w==", + "dependencies": { + "@wallet-standard/base": "^0.0.0-20240703212708" + }, + "engines": { + "node": ">=16" + } + }, + "node_modules/@dscvr-one/canvas-wallet-adapter/node_modules/@wallet-standard/base": { + "version": "0.0.0-20240703212708", + "resolved": "https://registry.npmjs.org/@wallet-standard/base/-/base-0.0.0-20240703212708.tgz", + "integrity": "sha512-D9z2nlH3wyR6NZBVjX2csAMAvSZvhXujWQkyx/5fhZ5QsHnbcrt0g21u231kIC7zuAzmH3tjQ0/xyR/2bfvjgA==", + "engines": { + "node": ">=16" + } + }, + "node_modules/@dscvr-one/canvas-wallet-adapter/node_modules/@wallet-standard/core": { + "version": "0.0.0-20240703212708", + "resolved": "https://registry.npmjs.org/@wallet-standard/core/-/core-0.0.0-20240703212708.tgz", + "integrity": "sha512-KvoLY7XHk9r++bjggJGhYlORUxe8NxJZ7uPyaypvtZf9nJSviZtawWtAVXq+B+YP7EGKF6gW0HuS3mjYfXO2gg==", + "dependencies": { + "@wallet-standard/app": "^0.0.0-20240703212708", + "@wallet-standard/base": "^0.0.0-20240703212708", + "@wallet-standard/errors": "^0.0.0-20240703212708", + "@wallet-standard/features": "^0.0.0-20240703212708", + "@wallet-standard/wallet": "^0.0.0-20240703212708" + }, + "engines": { + "node": ">=16" + } + }, + "node_modules/@dscvr-one/canvas-wallet-adapter/node_modules/@wallet-standard/features": { + "version": "0.0.0-20240703212708", + "resolved": "https://registry.npmjs.org/@wallet-standard/features/-/features-0.0.0-20240703212708.tgz", + "integrity": "sha512-b5U7UKzlI2j+VnNZCWiEXewA4jHGcbD7xVHr91/NYSnGs5sos8Y7YXpnf+07ib/LwInd/X00g3/qzz9wRtv+Ew==", + "dependencies": { + "@wallet-standard/base": "^0.0.0-20240703212708" + }, + "engines": { + "node": ">=16" + } + }, + "node_modules/@dscvr-one/canvas-wallet-adapter/node_modules/@wallet-standard/wallet": { + "version": "0.0.0-20240703212708", + "resolved": "https://registry.npmjs.org/@wallet-standard/wallet/-/wallet-0.0.0-20240703212708.tgz", + "integrity": "sha512-iTPr84ki4BZvEx4YPl/svDZ90rwj6teyAV9ip9p/q5IVLYCofzZOdUKnLu3R81O0rnnIeeDs8i6q4YkzHgtfYA==", + "dependencies": { + "@wallet-standard/base": "^0.0.0-20240703212708" + }, + "engines": { + "node": ">=16" + } + }, + "node_modules/@dscvr-one/canvas-wallet-adapter/node_modules/base-x": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/base-x/-/base-x-4.0.0.tgz", + "integrity": "sha512-FuwxlW4H5kh37X/oW59pwTzzTKRzfrrQwhmyspRM7swOEZcHtDZSCt45U6oKgtuFE+WYPblePMVIPR4RZrh/hw==" + }, + "node_modules/@dscvr-one/canvas-wallet-adapter/node_modules/bs58": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/bs58/-/bs58-5.0.0.tgz", + "integrity": "sha512-r+ihvQJvahgYT50JD05dyJNKlmmSlMoOGwn1lCcEzanPglg7TxYjioQUYehQ9mAR/+hOSd2jRc/Z2y5UxBymvQ==", "dependencies": { + "base-x": "^4.0.0" + } + }, + "node_modules/@dscvr-one/canvas-wallet-interface": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@dscvr-one/canvas-wallet-interface/-/canvas-wallet-interface-1.0.1.tgz", + "integrity": "sha512-X0N6ut3TKJMS8HEP8ctk94QpEQJy9oWEOcKGJW8hsIEfButqLzdHOpsScte72Mac0yxkjEX5+FBy9UBbLy6Lgw==", + "dependencies": { + "@dscvr-one/canvas-interface": "^1.1.0", + "@solana/wallet-adapter-base": "^0.9.23", "zod": "^3.23.8" } }, @@ -4437,7 +4536,6 @@ "version": "2.1.3", "resolved": "https://registry.npmjs.org/@solana-mobile/mobile-wallet-adapter-protocol-web3js/-/mobile-wallet-adapter-protocol-web3js-2.1.3.tgz", "integrity": "sha512-IEvPzp4m39sWTS3gybbVfk1WQ5Bx9TrGlthtRlVw1BJPvjbmT6lTcnndgXp7HmMkz5e6cc8fwJWp3EKx5upAug==", - "peer": true, "dependencies": { "@solana-mobile/mobile-wallet-adapter-protocol": "^2.1.2", "bs58": "^5.0.0", @@ -4474,7 +4572,6 @@ "version": "2.1.3", "resolved": "https://registry.npmjs.org/@solana-mobile/mobile-wallet-adapter-protocol/-/mobile-wallet-adapter-protocol-2.1.3.tgz", "integrity": "sha512-rj1/cSQVjPYdQjHsJDxmlpgRjI9jly/0Md3bEeqCan2sLXPf5F6+TiVlAg9+Hxg+uVWd1peUrepFUdOykbklSw==", - "peer": true, "dependencies": { "@solana/wallet-standard": "^1.1.2", "@solana/wallet-standard-util": "^1.1.1", @@ -4501,6 +4598,19 @@ "url": "https://github.com/chalk/ansi-styles?sponsor=1" } }, + "node_modules/@solana-mobile/mobile-wallet-adapter-protocol-web3js/node_modules/base-x": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/base-x/-/base-x-4.0.0.tgz", + "integrity": "sha512-FuwxlW4H5kh37X/oW59pwTzzTKRzfrrQwhmyspRM7swOEZcHtDZSCt45U6oKgtuFE+WYPblePMVIPR4RZrh/hw==" + }, + "node_modules/@solana-mobile/mobile-wallet-adapter-protocol-web3js/node_modules/bs58": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/bs58/-/bs58-5.0.0.tgz", + "integrity": "sha512-r+ihvQJvahgYT50JD05dyJNKlmmSlMoOGwn1lCcEzanPglg7TxYjioQUYehQ9mAR/+hOSd2jRc/Z2y5UxBymvQ==", + "dependencies": { + "base-x": "^4.0.0" + } + }, "node_modules/@solana-mobile/mobile-wallet-adapter-protocol-web3js/node_modules/chalk": { "version": "4.1.2", "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", @@ -4656,7 +4766,6 @@ "version": "2.1.3", "resolved": "https://registry.npmjs.org/@solana-mobile/wallet-adapter-mobile/-/wallet-adapter-mobile-2.1.3.tgz", "integrity": "sha512-V9gxV7/F1BLode6I+j134kFvQv1mnF0OlN+tYPHEmJOcH4caDfH6rlJy7t9Pktkl9ZEVTO9kT8K19Y4MRl6nxg==", - "peer": true, "dependencies": { "@solana-mobile/mobile-wallet-adapter-protocol-web3js": "^2.1.2", "@solana/wallet-adapter-base": "^0.9.23", @@ -4675,7 +4784,6 @@ "resolved": "https://registry.npmjs.org/@react-native-async-storage/async-storage/-/async-storage-1.24.0.tgz", "integrity": "sha512-W4/vbwUOYOjco0x3toB8QCr7EjIP6nE9G7o8PMguvvjYT5Awg09lyV4enACRx4s++PPulBiBSjL0KTFx2u0Z/g==", "optional": true, - "peer": true, "dependencies": { "merge-options": "^3.0.4" }, @@ -4899,7 +5007,6 @@ "version": "0.9.23", "resolved": "https://registry.npmjs.org/@solana/wallet-adapter-base/-/wallet-adapter-base-0.9.23.tgz", "integrity": "sha512-apqMuYwFp1jFi55NxDfvXUX2x1T0Zh07MxhZ/nCCTGys5raSfYUh82zen2BLv8BSDj/JxZ2P/s7jrQZGrX8uAw==", - "peer": true, "dependencies": { "@solana/wallet-standard-features": "^1.1.0", "@wallet-standard/base": "^1.0.1", @@ -4933,7 +5040,6 @@ "version": "0.15.35", "resolved": "https://registry.npmjs.org/@solana/wallet-adapter-react/-/wallet-adapter-react-0.15.35.tgz", "integrity": "sha512-i4hc/gNLTYNLMEt2LS+4lrrc0QAwa5SU2PtYMnZ2A3rsoKF5m1bv1h6cjLj2KBry4/zRGEBoqkiMOC5zHkLnRQ==", - "peer": true, "dependencies": { "@solana-mobile/wallet-adapter-mobile": "^2.0.0", "@solana/wallet-adapter-base": "^0.9.23", @@ -4970,7 +5076,6 @@ "version": "1.1.2", "resolved": "https://registry.npmjs.org/@solana/wallet-standard/-/wallet-standard-1.1.2.tgz", "integrity": "sha512-o7wk+zr5/QgyE393cGRC04K1hacR4EkBu3MB925ddaLvCVaXjwr2asgdviGzN9PEm3FiEJp3sMmMKYHFnwOITQ==", - "peer": true, "dependencies": { "@solana/wallet-standard-core": "^1.1.1", "@solana/wallet-standard-wallet-adapter": "^1.1.2" @@ -4983,7 +5088,6 @@ "version": "1.1.0", "resolved": "https://registry.npmjs.org/@solana/wallet-standard-chains/-/wallet-standard-chains-1.1.0.tgz", "integrity": "sha512-IRJHf94UZM8AaRRmY18d34xCJiVPJej1XVwXiTjihHnmwD0cxdQbc/CKjrawyqFyQAKJx7raE5g9mnJsAdspTg==", - "peer": true, "dependencies": { "@wallet-standard/base": "^1.0.1" }, @@ -4995,7 +5099,6 @@ "version": "1.1.1", "resolved": "https://registry.npmjs.org/@solana/wallet-standard-core/-/wallet-standard-core-1.1.1.tgz", "integrity": "sha512-DoQ5Ryly4GAZtxRUmW2rIWrgNvTYVCWrFCFFjZI5s4zu2QNsP7sHZUax3kc1GbmFLXNL1FWRZlPOXRs6e0ZEng==", - "peer": true, "dependencies": { "@solana/wallet-standard-chains": "^1.1.0", "@solana/wallet-standard-features": "^1.2.0", @@ -5009,7 +5112,6 @@ "version": "1.2.0", "resolved": "https://registry.npmjs.org/@solana/wallet-standard-features/-/wallet-standard-features-1.2.0.tgz", "integrity": "sha512-tUd9srDLkRpe1BYg7we+c4UhRQkq+XQWswsr/L1xfGmoRDF47BPSXf4zE7ZU2GRBGvxtGt7lwJVAufQyQYhxTQ==", - "peer": true, "dependencies": { "@wallet-standard/base": "^1.0.1", "@wallet-standard/features": "^1.0.3" @@ -5022,7 +5124,6 @@ "version": "1.1.1", "resolved": "https://registry.npmjs.org/@solana/wallet-standard-util/-/wallet-standard-util-1.1.1.tgz", "integrity": "sha512-dPObl4ntmfOc0VAGGyyFvrqhL8UkHXmVsgbj0K9RcznKV4KB3MgjGwzo8CTSX5El5lkb0rDeEzFqvToJXRz3dw==", - "peer": true, "dependencies": { "@noble/curves": "^1.1.0", "@solana/wallet-standard-chains": "^1.1.0", @@ -5036,7 +5137,6 @@ "version": "1.1.2", "resolved": "https://registry.npmjs.org/@solana/wallet-standard-wallet-adapter/-/wallet-standard-wallet-adapter-1.1.2.tgz", "integrity": "sha512-lCwoA+vhPfmvjcmJOhSRV94wouVWTfJv1Z7eeULAe+GodCeKA/0T9/uBYgXHUxQjLHd7o8LpLYIkfm+xjA5sMA==", - "peer": true, "dependencies": { "@solana/wallet-standard-wallet-adapter-base": "^1.1.2", "@solana/wallet-standard-wallet-adapter-react": "^1.1.2" @@ -5045,29 +5145,10 @@ "node": ">=16" } }, - "node_modules/@solana/wallet-standard-wallet-adapter-react": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/@solana/wallet-standard-wallet-adapter-react/-/wallet-standard-wallet-adapter-react-1.1.2.tgz", - "integrity": "sha512-bN6W4QkzenyjUoUz3sC5PAed+z29icGtPh9VSmLl1ZrRO7NbFB49a8uwUUVXNxhL/ZbMsyVKhb9bNj47/p8uhQ==", - "peer": true, - "dependencies": { - "@solana/wallet-standard-wallet-adapter-base": "^1.1.2", - "@wallet-standard/app": "^1.0.1", - "@wallet-standard/base": "^1.0.1" - }, - "engines": { - "node": ">=16" - }, - "peerDependencies": { - "@solana/wallet-adapter-base": "*", - "react": "*" - } - }, - "node_modules/@solana/wallet-standard-wallet-adapter-react/node_modules/@solana/wallet-standard-wallet-adapter-base": { + "node_modules/@solana/wallet-standard-wallet-adapter-base": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/@solana/wallet-standard-wallet-adapter-base/-/wallet-standard-wallet-adapter-base-1.1.2.tgz", "integrity": "sha512-DqhzYbgh3disHMgcz6Du7fmpG29BYVapNEEiL+JoVMa+bU9d4P1wfwXUNyJyRpGGNXtwhyZjIk2umWbe5ZBNaQ==", - "peer": true, "dependencies": { "@solana/wallet-adapter-base": "^0.9.23", "@solana/wallet-standard-chains": "^1.1.0", @@ -5086,63 +5167,21 @@ "bs58": "^4.0.1" } }, - "node_modules/@solana/wallet-standard-wallet-adapter-react/node_modules/base-x": { - "version": "3.0.10", - "resolved": "https://registry.npmjs.org/base-x/-/base-x-3.0.10.tgz", - "integrity": "sha512-7d0s06rR9rYaIWHkpfLIFICM/tkSVdoPC9qYAQRpxn9DdKNWNsKC0uk++akckyLq16Tx2WIinnZ6WRriAt6njQ==", - "peer": true, - "dependencies": { - "safe-buffer": "^5.0.1" - } - }, - "node_modules/@solana/wallet-standard-wallet-adapter-react/node_modules/bs58": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/bs58/-/bs58-4.0.1.tgz", - "integrity": "sha512-Ok3Wdf5vOIlBrgCvTq96gBkJw+JUEzdBgyaza5HLtPm7yTHkjRy8+JzNyHF7BHa0bNWOQIp3m5YF0nnFcOIKLw==", - "peer": true, - "dependencies": { - "base-x": "^3.0.2" - } - }, - "node_modules/@solana/wallet-standard-wallet-adapter/node_modules/@solana/wallet-standard-wallet-adapter-base": { + "node_modules/@solana/wallet-standard-wallet-adapter-react": { "version": "1.1.2", - "resolved": "https://registry.npmjs.org/@solana/wallet-standard-wallet-adapter-base/-/wallet-standard-wallet-adapter-base-1.1.2.tgz", - "integrity": "sha512-DqhzYbgh3disHMgcz6Du7fmpG29BYVapNEEiL+JoVMa+bU9d4P1wfwXUNyJyRpGGNXtwhyZjIk2umWbe5ZBNaQ==", - "peer": true, + "resolved": "https://registry.npmjs.org/@solana/wallet-standard-wallet-adapter-react/-/wallet-standard-wallet-adapter-react-1.1.2.tgz", + "integrity": "sha512-bN6W4QkzenyjUoUz3sC5PAed+z29icGtPh9VSmLl1ZrRO7NbFB49a8uwUUVXNxhL/ZbMsyVKhb9bNj47/p8uhQ==", "dependencies": { - "@solana/wallet-adapter-base": "^0.9.23", - "@solana/wallet-standard-chains": "^1.1.0", - "@solana/wallet-standard-features": "^1.2.0", - "@solana/wallet-standard-util": "^1.1.1", + "@solana/wallet-standard-wallet-adapter-base": "^1.1.2", "@wallet-standard/app": "^1.0.1", - "@wallet-standard/base": "^1.0.1", - "@wallet-standard/features": "^1.0.3", - "@wallet-standard/wallet": "^1.0.1" + "@wallet-standard/base": "^1.0.1" }, "engines": { "node": ">=16" }, "peerDependencies": { - "@solana/web3.js": "^1.58.0", - "bs58": "^4.0.1" - } - }, - "node_modules/@solana/wallet-standard-wallet-adapter/node_modules/base-x": { - "version": "3.0.10", - "resolved": "https://registry.npmjs.org/base-x/-/base-x-3.0.10.tgz", - "integrity": "sha512-7d0s06rR9rYaIWHkpfLIFICM/tkSVdoPC9qYAQRpxn9DdKNWNsKC0uk++akckyLq16Tx2WIinnZ6WRriAt6njQ==", - "peer": true, - "dependencies": { - "safe-buffer": "^5.0.1" - } - }, - "node_modules/@solana/wallet-standard-wallet-adapter/node_modules/bs58": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/bs58/-/bs58-4.0.1.tgz", - "integrity": "sha512-Ok3Wdf5vOIlBrgCvTq96gBkJw+JUEzdBgyaza5HLtPm7yTHkjRy8+JzNyHF7BHa0bNWOQIp3m5YF0nnFcOIKLw==", - "peer": true, - "dependencies": { - "base-x": "^3.0.2" + "@solana/wallet-adapter-base": "*", + "react": "*" } }, "node_modules/@solana/web3.js": { @@ -5167,22 +5206,6 @@ "superstruct": "^2.0.2" } }, - "node_modules/@solana/web3.js/node_modules/base-x": { - "version": "3.0.10", - "resolved": "https://registry.npmjs.org/base-x/-/base-x-3.0.10.tgz", - "integrity": "sha512-7d0s06rR9rYaIWHkpfLIFICM/tkSVdoPC9qYAQRpxn9DdKNWNsKC0uk++akckyLq16Tx2WIinnZ6WRriAt6njQ==", - "dependencies": { - "safe-buffer": "^5.0.1" - } - }, - "node_modules/@solana/web3.js/node_modules/bs58": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/bs58/-/bs58-4.0.1.tgz", - "integrity": "sha512-Ok3Wdf5vOIlBrgCvTq96gBkJw+JUEzdBgyaza5HLtPm7yTHkjRy8+JzNyHF7BHa0bNWOQIp3m5YF0nnFcOIKLw==", - "dependencies": { - "base-x": "^3.0.2" - } - }, "node_modules/@swc/helpers": { "version": "0.5.12", "resolved": "https://registry.npmjs.org/@swc/helpers/-/helpers-0.5.12.tgz", @@ -5559,7 +5582,6 @@ "version": "1.0.1", "resolved": "https://registry.npmjs.org/@wallet-standard/app/-/app-1.0.1.tgz", "integrity": "sha512-LnLYq2Vy2guTZ8GQKKSXQK3+FRGPil75XEdkZqE6fiLixJhZJoJa5hT7lXxwe0ykVTt9LEThdTbOpT7KadS26Q==", - "peer": true, "dependencies": { "@wallet-standard/base": "^1.0.1" }, @@ -5571,7 +5593,6 @@ "version": "1.0.1", "resolved": "https://registry.npmjs.org/@wallet-standard/base/-/base-1.0.1.tgz", "integrity": "sha512-1To3ekMfzhYxe0Yhkpri+Fedq0SYcfrOfJi3vbLjMwF2qiKPjTGLwZkf2C9ftdQmxES+hmxhBzTwF4KgcOwf8w==", - "peer": true, "engines": { "node": ">=16" } @@ -5580,7 +5601,6 @@ "version": "1.0.3", "resolved": "https://registry.npmjs.org/@wallet-standard/core/-/core-1.0.3.tgz", "integrity": "sha512-Jb33IIjC1wM1HoKkYD7xQ6d6PZ8EmMZvyc8R7dFgX66n/xkvksVTW04g9yLvQXrLFbcIjHrCxW6TXMhvpsAAzg==", - "peer": true, "dependencies": { "@wallet-standard/app": "^1.0.1", "@wallet-standard/base": "^1.0.1", @@ -5591,11 +5611,44 @@ "node": ">=16" } }, + "node_modules/@wallet-standard/errors": { + "version": "0.0.0-20240703212708", + "resolved": "https://registry.npmjs.org/@wallet-standard/errors/-/errors-0.0.0-20240703212708.tgz", + "integrity": "sha512-Bord90VSpPAD30ukC3h8MEZYzv0BZoRnG+DNWcsm8MOuivsZzSmWFcnoxX4ErZgKknxaCRT8qLc3+3+k4QVL3w==", + "dependencies": { + "chalk": "^5.3.0", + "commander": "^12.1.0" + }, + "bin": { + "errors": "bin/cli.mjs" + }, + "engines": { + "node": ">=16" + } + }, + "node_modules/@wallet-standard/errors/node_modules/chalk": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-5.3.0.tgz", + "integrity": "sha512-dLitG79d+GV1Nb/VYcCDFivJeK1hiukt9QjRNVOsUtTy1rR1YJsmpGGTZ3qJos+uw7WmWF4wUwBd9jxjocFC2w==", + "engines": { + "node": "^12.17.0 || ^14.13 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/@wallet-standard/errors/node_modules/commander": { + "version": "12.1.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-12.1.0.tgz", + "integrity": "sha512-Vw8qHK3bZM9y/P10u3Vib8o/DdkvA2OtPtZvD871QKjy74Wj1WSKFILMPRPSdUSx5RFK1arlJzEtA4PkFgnbuA==", + "engines": { + "node": ">=18" + } + }, "node_modules/@wallet-standard/features": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/@wallet-standard/features/-/features-1.0.3.tgz", "integrity": "sha512-m8475I6W5LTatTZuUz5JJNK42wFRgkJTB0I9tkruMwfqBF2UN2eomkYNVf9RbrsROelCRzSFmugqjKZBFaubsA==", - "peer": true, "dependencies": { "@wallet-standard/base": "^1.0.1" }, @@ -5607,7 +5660,6 @@ "version": "1.0.1", "resolved": "https://registry.npmjs.org/@wallet-standard/wallet/-/wallet-1.0.1.tgz", "integrity": "sha512-qkhJeuQU2afQTZ02yMZE5SFc91Fo3hyFjFkpQglHudENNyiSG0oUKcIjky8X32xVSaumgTZSQUAzpXnCTWHzKQ==", - "peer": true, "dependencies": { "@wallet-standard/base": "^1.0.1" }, @@ -5924,10 +5976,12 @@ "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==" }, "node_modules/base-x": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/base-x/-/base-x-4.0.0.tgz", - "integrity": "sha512-FuwxlW4H5kh37X/oW59pwTzzTKRzfrrQwhmyspRM7swOEZcHtDZSCt45U6oKgtuFE+WYPblePMVIPR4RZrh/hw==", - "peer": true + "version": "3.0.10", + "resolved": "https://registry.npmjs.org/base-x/-/base-x-3.0.10.tgz", + "integrity": "sha512-7d0s06rR9rYaIWHkpfLIFICM/tkSVdoPC9qYAQRpxn9DdKNWNsKC0uk++akckyLq16Tx2WIinnZ6WRriAt6njQ==", + "dependencies": { + "safe-buffer": "^5.0.1" + } }, "node_modules/base58": { "version": "2.0.1", @@ -6032,22 +6086,6 @@ "text-encoding-utf-8": "^1.0.2" } }, - "node_modules/borsh/node_modules/base-x": { - "version": "3.0.10", - "resolved": "https://registry.npmjs.org/base-x/-/base-x-3.0.10.tgz", - "integrity": "sha512-7d0s06rR9rYaIWHkpfLIFICM/tkSVdoPC9qYAQRpxn9DdKNWNsKC0uk++akckyLq16Tx2WIinnZ6WRriAt6njQ==", - "dependencies": { - "safe-buffer": "^5.0.1" - } - }, - "node_modules/borsh/node_modules/bs58": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/bs58/-/bs58-4.0.1.tgz", - "integrity": "sha512-Ok3Wdf5vOIlBrgCvTq96gBkJw+JUEzdBgyaza5HLtPm7yTHkjRy8+JzNyHF7BHa0bNWOQIp3m5YF0nnFcOIKLw==", - "dependencies": { - "base-x": "^3.0.2" - } - }, "node_modules/brace-expansion": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", @@ -6235,12 +6273,11 @@ } }, "node_modules/bs58": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/bs58/-/bs58-5.0.0.tgz", - "integrity": "sha512-r+ihvQJvahgYT50JD05dyJNKlmmSlMoOGwn1lCcEzanPglg7TxYjioQUYehQ9mAR/+hOSd2jRc/Z2y5UxBymvQ==", - "peer": true, + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/bs58/-/bs58-4.0.1.tgz", + "integrity": "sha512-Ok3Wdf5vOIlBrgCvTq96gBkJw+JUEzdBgyaza5HLtPm7yTHkjRy8+JzNyHF7BHa0bNWOQIp3m5YF0nnFcOIKLw==", "dependencies": { - "base-x": "^4.0.0" + "base-x": "^3.0.2" } }, "node_modules/bser": { @@ -7668,8 +7705,7 @@ "node_modules/eventemitter3": { "version": "4.0.7", "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-4.0.7.tgz", - "integrity": "sha512-8guHBZCwKnFhYdHr2ysuRWErTwhoN2X8XELRlrRwpmfeY2jjuUN4taQMsULKUVo1K4DvZl+0pgfyoysHxvmvEw==", - "peer": true + "integrity": "sha512-8guHBZCwKnFhYdHr2ysuRWErTwhoN2X8XELRlrRwpmfeY2jjuUN4taQMsULKUVo1K4DvZl+0pgfyoysHxvmvEw==" }, "node_modules/events": { "version": "3.3.0", @@ -8578,7 +8614,6 @@ "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-2.1.0.tgz", "integrity": "sha512-YWnfyRwxL/+SsrWYfOpUtz5b3YD+nyfkHvjbcanzk8zgyO4ASD67uVMRt8k5bM4lLMDnXfriRhOpemw+NfT1eA==", "optional": true, - "peer": true, "engines": { "node": ">=8" } @@ -9133,8 +9168,7 @@ "node_modules/js-base64": { "version": "3.7.7", "resolved": "https://registry.npmjs.org/js-base64/-/js-base64-3.7.7.tgz", - "integrity": "sha512-7rCnleh0z2CkXhH67J8K1Ytz0b2Y+yxTPL+/KOJoa20hfnVQ/3/T6W/KflYI4bRHRagNeXeU2bkNGI3v1oS/lw==", - "peer": true + "integrity": "sha512-7rCnleh0z2CkXhH67J8K1Ytz0b2Y+yxTPL+/KOJoa20hfnVQ/3/T6W/KflYI4bRHRagNeXeU2bkNGI3v1oS/lw==" }, "node_modules/js-tokens": { "version": "4.0.0", @@ -9808,7 +9842,6 @@ "resolved": "https://registry.npmjs.org/merge-options/-/merge-options-3.0.4.tgz", "integrity": "sha512-2Sug1+knBjkaMsMgf1ctR1Ujx+Ayku4EdJN4Z+C2+JzoeF7A3OZ9KM2GY0CpQS51NR61LTurMJrRKPhSs3ZRTQ==", "optional": true, - "peer": true, "dependencies": { "is-plain-obj": "^2.1.0" }, diff --git a/package.json b/package.json index 3fbeead..864b162 100644 --- a/package.json +++ b/package.json @@ -12,7 +12,10 @@ }, "dependencies": { "@dialectlabs/blinks": "^0.5.0", - "@dscvr-one/canvas-client-sdk": "^1.0.7", + "@dscvr-one/canvas-client-sdk": "^1.1.0", + "@dscvr-one/canvas-wallet-adapter": "^1.0.1", + "@solana/wallet-adapter-base": "^0.9.23", + "@solana/wallet-adapter-react": "^0.15.35", "@solana/web3.js": "^1.95.2", "base58": "^2.0.1", "react": "^18.3.1", diff --git a/src/App.tsx b/src/App.tsx index 8f2e5de..ad05f16 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -1,60 +1,53 @@ -import { useEffect, useRef, useState } from "react"; -import "./App.css"; -import { - Action, - ActionContainer, -} from "@dialectlabs/blinks"; +import { useEffect, useRef, useState } from 'react'; +import './App.css'; +import { Action, ActionContainer } from '@dialectlabs/blinks'; import '@dialectlabs/blinks/index.css'; -import './blink.css' -import { CanvasAdapter, isIframe } from "./canvas-adapter"; -import { CanvasClient } from "@dscvr-one/canvas-client-sdk"; +import './blink.css'; +import { canvasClient } from './canvas-client'; +import { useCanvasAdapter } from './use-canvas-adapter'; const App = () => { const [action, setAction] = useState(null); - const [_, setIsInIframe] = useState(false); - const [websiteUrl, setWebsiteUrl] = useState(""); - const [websiteText, setWebsiteText] = useState(""); + const [websiteUrl, setWebsiteUrl] = useState(''); + const [websiteText, setWebsiteText] = useState(''); const containerRef = useRef(null); - const canvasClientRef = useRef(); - - useEffect(() => { - const iframe = isIframe(); - - if(iframe) { - canvasClientRef.current = new CanvasClient(); - }; + const { initialize, canvasAdapterRef } = useCanvasAdapter(); - setIsInIframe(iframe); - const adapter = iframe ? new CanvasAdapter() : undefined; + useEffect(() => { + if (canvasClient) { + initialize(); + } const fetchAction = async () => { const url = new URL(window.location.href); - - const actionParam = url.searchParams.get('action') ?? 'https://blink-chat.xyz/api/actions/chat'; - + + const actionParam = + url.searchParams.get('action') ?? + 'https://blink-chat.xyz/api/actions/chat'; + if (actionParam) { try { const actionUrl = new URL(actionParam); - + setWebsiteUrl(actionUrl.toString()); setWebsiteText(actionUrl.host); const action = await Action.fetch( actionParam, - adapter + canvasAdapterRef.current ); setAction(action); } catch (error) { - console.error("Invalid action URL:", error); + console.error('Invalid action URL:', error); } } else { - console.error("No action parameter provided in URL"); + console.error('No action parameter provided in URL'); } }; fetchAction(); const resizeObserver = new ResizeObserver((_) => { - canvasClientRef?.current?.resize(); + canvasClient.resize(); }); if (containerRef.current) { @@ -70,16 +63,16 @@ const App = () => { const exampleCallbacks = { onActionMount: (action: any, url: any, actionState: any) => { - console.log("Action mounted:", action, url, actionState); + console.log('Action mounted:', action, url, actionState); }, }; - const exampleSecurityLevel = "only-trusted"; + const exampleSecurityLevel = 'only-trusted'; const containerStyle = { maxWidth: '450px', margin: '0 auto', - width: '100%' + width: '100%', }; return ( @@ -98,4 +91,4 @@ const App = () => { ); }; -export default App; \ No newline at end of file +export default App; diff --git a/src/canvas-adapter.ts b/src/canvas-adapter.ts deleted file mode 100644 index 408c723..0000000 --- a/src/canvas-adapter.ts +++ /dev/null @@ -1,144 +0,0 @@ -import { ActionAdapter, ActionContext } from "@dialectlabs/blinks"; -import { CanvasClient } from "@dscvr-one/canvas-client-sdk"; -import { - PublicKey, - TransactionInstruction, - TransactionMessage, - VersionedTransaction, -} from "@solana/web3.js"; -import * as base58 from "bs58"; - -const CANVAS_CHAIN_ID = "solana:101"; -const MEMO_PROGRAM_ID = "MemoSq4gqABAXKb96qnH8TysNcWxMyWCqXgDLGmfcHr"; - -const base64tobase58 = (base64: string) => { - return base58.encode(Buffer.from(base64, "base64")); -}; - -const parseTransaction = (base58Tx: string) => { - const txUint8Array = base58.decode(base58Tx); - - try { - return VersionedTransaction.deserialize(txUint8Array); - } catch (error) { - console.error("Error parsing transaction:", error); - return null; - } -}; - -const addMemoTracker = async (base64Tx: string, address: string) => { - let base58Tx = base64tobase58(base64Tx); - - try { - const tx = parseTransaction(base58Tx); - - //can't compose already signed transactions - let isSigned = tx.signatures.some((sig) => sig.some((s) => s > 0)); - if (isSigned) { - return base58Tx; - } - - //handle tx with lookup tables later - if (tx.message.addressTableLookups.length > 0) { - return base58Tx; - } - - var txMessage = TransactionMessage.decompile(tx.message); - txMessage.instructions.push( - new TransactionInstruction({ - programId: new PublicKey(MEMO_PROGRAM_ID), - data: Buffer.from("dscvr.one", "utf8"), - keys: [ - { - pubkey: new PublicKey(address), - isSigner: true, - isWritable: false, - }, - ], - }) - ); - - let newMessage = - tx.version == "legacy" - ? txMessage.compileToLegacyMessage() - : txMessage.compileToV0Message(); - - let newTx = new VersionedTransaction(newMessage); - - const serializedNewTransaction = newTx.serialize(); - - if (serializedNewTransaction.byteLength > 1232) { - return base58Tx; - } - return base58.encode(serializedNewTransaction); - } catch (error) { - console.error("Error adding memo tracker:", error); - return base58Tx; - } -}; - -export const isIframe = () => { - try { - return window.self !== window.top; - } catch (e) { - return true; - } -}; - -export class CanvasAdapter implements ActionAdapter { - canvasClient: CanvasClient; - chainId: string; - address?: string; - constructor(chainId: string = CANVAS_CHAIN_ID) { - this.canvasClient = new CanvasClient(); - this.chainId = chainId; - this.canvasClient.ready().then(() => { - console.log("Canvas client ready"); - }); - } - - connect = async (_context: ActionContext) => { - try { - if (!this.canvasClient) { - throw new Error("Canvas client not initialized"); - } - - let response = await this.canvasClient.connectWallet(this.chainId); - if (!response?.untrusted.success) { - throw new Error("Failed to connect wallet"); - } - this.address = response.untrusted.address; - return response.untrusted.address; - } catch (error) { - console.error("Connection error:", error); - return null; - } - }; - - signTransaction = async (tx: string, _context: ActionContext) => { - try { - console.log("signTransaction", tx, this.address); - const results = await this.canvasClient.signAndSendTransaction({ - unsignedTx: await addMemoTracker(tx, this.address), - awaitCommitment: "confirmed", - chainId: this.chainId, - }); - - if (!results?.untrusted.success) { - throw new Error("Failed to sign transaction"); - } - return { signature: results.untrusted.signedTx }; - } catch (error) { - console.error("Transaction signing error:", error); - return { error: "Failed to sign transaction" }; - } - }; - - confirmTransaction = async (_signature: string, _context: ActionContext) => { - try { - await true; - } catch (error) { - console.error("Transaction confirmation error:", error); - } - }; -} diff --git a/src/canvas-client.ts b/src/canvas-client.ts new file mode 100644 index 0000000..e0f88b2 --- /dev/null +++ b/src/canvas-client.ts @@ -0,0 +1,21 @@ +import { CanvasClient } from '@dscvr-one/canvas-client-sdk'; +import { registerCanvasWallet } from '@dscvr-one/canvas-wallet-adapter'; +import type { WalletName } from '@solana/wallet-adapter-base'; + +export const checkIframe = () => { + try { + return window.self !== window.top; + } catch (e) { + return true; + } +}; + +export const isIframe = checkIframe(); +export const canvasClient = isIframe ? new CanvasClient() : undefined; +const canvasWallet = canvasClient + ? registerCanvasWallet(canvasClient) + : undefined; + +export const CANVAS_WALLET_NAME = canvasWallet + ? (canvasWallet.name as WalletName) + : undefined; diff --git a/src/main.tsx b/src/main.tsx index 3d7150d..8950017 100644 --- a/src/main.tsx +++ b/src/main.tsx @@ -1,10 +1,20 @@ -import React from 'react' -import ReactDOM from 'react-dom/client' -import App from './App.tsx' -import './index.css' +import React from 'react'; +import ReactDOM from 'react-dom/client'; +import { + WalletProvider, + ConnectionProvider, +} from '@solana/wallet-adapter-react'; +import App from './App.tsx'; +import './index.css'; + +const RPC_ENDPOINT = 'https://api.mainnet-beta.solana.com'; ReactDOM.createRoot(document.getElementById('root')!).render( - - , -) + + + + + + +); diff --git a/src/use-canvas-adapter.ts b/src/use-canvas-adapter.ts new file mode 100644 index 0000000..7604b42 --- /dev/null +++ b/src/use-canvas-adapter.ts @@ -0,0 +1,162 @@ +import { ActionAdapter, ActionContext } from '@dialectlabs/blinks'; +import { useConnection, useWallet } from '@solana/wallet-adapter-react'; +import { + PublicKey, + TransactionInstruction, + TransactionMessage, + VersionedTransaction, +} from '@solana/web3.js'; +import * as base58 from 'bs58'; +import { useEffect, useRef } from 'react'; +import { CANVAS_WALLET_NAME, canvasClient } from './canvas-client'; + +const MEMO_PROGRAM_ID = 'MemoSq4gqABAXKb96qnH8TysNcWxMyWCqXgDLGmfcHr'; + +const base64tobase58 = (base64: string) => { + return base58.encode(Buffer.from(base64, 'base64')); +}; + +const parseTransaction = (base58Tx: string) => { + const txUint8Array = base58.decode(base58Tx); + + try { + return VersionedTransaction.deserialize(txUint8Array); + } catch (error) { + console.error('Error parsing transaction:', error); + return null; + } +}; + +const addMemoTracker = async (base64Tx: string, address: string) => { + let base58Tx = base64tobase58(base64Tx); + + try { + const tx = parseTransaction(base58Tx); + + //can't compose already signed transactions + let isSigned = tx.signatures.some((sig) => sig.some((s) => s > 0)); + if (isSigned) { + return base58Tx; + } + + //handle tx with lookup tables later + if (tx.message.addressTableLookups.length > 0) { + return base58Tx; + } + + var txMessage = TransactionMessage.decompile(tx.message); + txMessage.instructions.push( + new TransactionInstruction({ + programId: new PublicKey(MEMO_PROGRAM_ID), + data: Buffer.from('dscvr.one', 'utf8'), + keys: [ + { + pubkey: new PublicKey(address), + isSigner: true, + isWritable: false, + }, + ], + }) + ); + + let newMessage = + tx.version == 'legacy' + ? txMessage.compileToLegacyMessage() + : txMessage.compileToV0Message(); + + let newTx = new VersionedTransaction(newMessage); + + const serializedNewTransaction = newTx.serialize(); + + if (serializedNewTransaction.byteLength > 1232) { + return base58Tx; + } + return base58.encode(serializedNewTransaction); + } catch (error) { + console.error('Error adding memo tracker:', error); + return base58Tx; + } +}; + +export const useCanvasAdapter = () => { + const { connection } = useConnection(); + const { select, connect, wallets, wallet } = useWallet(); + const canvasAdapterRef = useRef(); + + useEffect(() => { + if (!CANVAS_WALLET_NAME || wallet?.adapter.name === CANVAS_WALLET_NAME) + return; + const exists = wallets.find((w) => w.adapter.name === CANVAS_WALLET_NAME); + if (exists) { + select(exists.adapter.name); + } + }, [wallets, wallet]); + + const initialize = async () => { + canvasAdapterRef.current = createAdapter(); + if (!canvasClient) return; + canvasClient.ready().then(() => { + console.log('Canvas client ready'); + }); + }; + + const createAdapter = () => { + const adapter: ActionAdapter = { + connect: async (_context: ActionContext) => { + try { + if (!canvasClient) { + throw new Error('Canvas client not initialized'); + } + + await connect(); + if (!wallet.adapter.connected) { + throw new Error('Failed to connect wallet'); + } + return wallet.adapter.publicKey.toString(); + } catch (error) { + console.error('Connection error:', error); + return null; + } + }, + + signTransaction: async (tx: string, _context: ActionContext) => { + try { + console.log('signTransaction', tx); + const unsignedTxMemo = await addMemoTracker( + tx, + wallet.adapter.publicKey.toString() + ); + // const unsignedTx = base58.decode(tx); + const unsignedTx = parseTransaction(base64tobase58(tx)); + const signature = await wallet.adapter.sendTransaction( + unsignedTx, + connection + ); + + return { signature }; + } catch (error) { + console.error('Transaction signing error:', error); + return { error: 'Failed to sign transaction' }; + } + }, + + confirmTransaction: async ( + _signature: string, + _context: ActionContext + ) => { + try { + await true; + } catch (error) { + console.error('Transaction confirmation error:', error); + } + }, + }; + + return adapter; + }; + + return { + initialize, + canvasAdapterRef, + }; +};