diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index b7104285..9303062e 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -66,6 +66,7 @@ jobs: parse_json: true - name: Run Snyk to check for code vulnerabilities uses: RDXWorks-actions/snyk-actions/node@master + continue-on-error: true with: args: --all-projects --org=${{ env.SNYK_PROJECTS_ORG_ID }} --severity-threshold=high command: code test diff --git a/.gitignore b/.gitignore index d18d228c..6ad61a66 100644 --- a/.gitignore +++ b/.gitignore @@ -43,6 +43,8 @@ yarn-error.log* .envrc +examples/cdn/radix-dapp-toolkit.bundle.umd.cjs + # Editor directories and files .vscode/* !.vscode/extensions.json diff --git a/examples/cdn/index.html b/examples/cdn/index.html new file mode 100644 index 00000000..e671f9a8 --- /dev/null +++ b/examples/cdn/index.html @@ -0,0 +1,31 @@ + + + + + + RDT from CDN + + + +
+
+ + + + + diff --git a/examples/simple-dapp/index.html b/examples/simple-dapp/index.html index 22669479..faa6ed96 100644 --- a/examples/simple-dapp/index.html +++ b/examples/simple-dapp/index.html @@ -6,7 +6,12 @@ Simple dApp -
+ +
diff --git a/examples/simple-dapp/src/main.ts b/examples/simple-dapp/src/main.ts index 7fabc47d..041797da 100644 --- a/examples/simple-dapp/src/main.ts +++ b/examples/simple-dapp/src/main.ts @@ -84,12 +84,12 @@ const gatewayApi = GatewayApiClient.initialize( dAppToolkit.gatewayApi.clientConfig, ) -dAppToolkit.walletApi.provideChallengeGenerator(async () => { - await new Promise((resolve) => setTimeout(resolve, 1000)) - return generateRolaChallenge() -}) +dAppToolkit.walletApi.provideChallengeGenerator(async () => generateRolaChallenge()) -dAppToolkit.walletApi.setRequestData(DataRequestBuilder.persona().withProof()) +dAppToolkit.walletApi.setRequestData( + DataRequestBuilder.persona().withProof(), + DataRequestBuilder.accounts().atLeast(1), +) gatewayConfig.innerHTML = ` [Gateway] diff --git a/examples/simple-dapp/vite.config.ts b/examples/simple-dapp/vite.config.ts index 4965dc5b..9f0678cf 100644 --- a/examples/simple-dapp/vite.config.ts +++ b/examples/simple-dapp/vite.config.ts @@ -7,7 +7,6 @@ fs.writeFileSync( path.resolve(__dirname, 'public', '.well-known', 'radix.json'), JSON.stringify( { - callbackPath: process.env.VITE_RETURN_URL, dApps: [ { dAppDefinitionAddress: process.env.DAPP_DEFINITION_ADDRESS, diff --git a/package-lock.json b/package-lock.json index 2ca69b55..1e79b74c 100644 --- a/package-lock.json +++ b/package-lock.json @@ -8182,9 +8182,9 @@ "dev": true }, "node_modules/@rollup/rollup-android-arm-eabi": { - "version": "4.13.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.13.0.tgz", - "integrity": "sha512-5ZYPOuaAqEH/W3gYsRkxQATBW3Ii1MfaT4EQstTnLKViLi2gLSQmlmtTpGucNP3sXEpOiI5tdGhjdE111ekyEg==", + "version": "4.21.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.21.3.tgz", + "integrity": "sha512-MmKSfaB9GX+zXl6E8z4koOr/xU63AMVleLEa64v7R0QF/ZloMs5vcD1sHgM64GXXS1csaJutG+ddtzcueI/BLg==", "cpu": [ "arm" ], @@ -8195,9 +8195,9 @@ ] }, "node_modules/@rollup/rollup-android-arm64": { - "version": "4.13.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.13.0.tgz", - "integrity": "sha512-BSbaCmn8ZadK3UAQdlauSvtaJjhlDEjS5hEVVIN3A4bbl3X+otyf/kOJV08bYiRxfejP3DXFzO2jz3G20107+Q==", + "version": "4.21.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.21.3.tgz", + "integrity": "sha512-zrt8ecH07PE3sB4jPOggweBjJMzI1JG5xI2DIsUbkA+7K+Gkjys6eV7i9pOenNSDJH3eOr/jLb/PzqtmdwDq5g==", "cpu": [ "arm64" ], @@ -8208,9 +8208,9 @@ ] }, "node_modules/@rollup/rollup-darwin-arm64": { - "version": "4.13.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.13.0.tgz", - "integrity": "sha512-Ovf2evVaP6sW5Ut0GHyUSOqA6tVKfrTHddtmxGQc1CTQa1Cw3/KMCDEEICZBbyppcwnhMwcDce9ZRxdWRpVd6g==", + "version": "4.21.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.21.3.tgz", + "integrity": "sha512-P0UxIOrKNBFTQaXTxOH4RxuEBVCgEA5UTNV6Yz7z9QHnUJ7eLX9reOd/NYMO3+XZO2cco19mXTxDMXxit4R/eQ==", "cpu": [ "arm64" ], @@ -8221,9 +8221,9 @@ ] }, "node_modules/@rollup/rollup-darwin-x64": { - "version": "4.13.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.13.0.tgz", - "integrity": "sha512-U+Jcxm89UTK592vZ2J9st9ajRv/hrwHdnvyuJpa5A2ngGSVHypigidkQJP+YiGL6JODiUeMzkqQzbCG3At81Gg==", + "version": "4.21.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.21.3.tgz", + "integrity": "sha512-L1M0vKGO5ASKntqtsFEjTq/fD91vAqnzeaF6sfNAy55aD+Hi2pBI5DKwCO+UNDQHWsDViJLqshxOahXyLSh3EA==", "cpu": [ "x64" ], @@ -8234,9 +8234,22 @@ ] }, "node_modules/@rollup/rollup-linux-arm-gnueabihf": { - "version": "4.13.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.13.0.tgz", - "integrity": "sha512-8wZidaUJUTIR5T4vRS22VkSMOVooG0F4N+JSwQXWSRiC6yfEsFMLTYRFHvby5mFFuExHa/yAp9juSphQQJAijQ==", + "version": "4.21.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.21.3.tgz", + "integrity": "sha512-btVgIsCjuYFKUjopPoWiDqmoUXQDiW2A4C3Mtmp5vACm7/GnyuprqIDPNczeyR5W8rTXEbkmrJux7cJmD99D2g==", + "cpu": [ + "arm" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-arm-musleabihf": { + "version": "4.21.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.21.3.tgz", + "integrity": "sha512-zmjbSphplZlau6ZTkxd3+NMtE4UKVy7U4aVFMmHcgO5CUbw17ZP6QCgyxhzGaU/wFFdTfiojjbLG3/0p9HhAqA==", "cpu": [ "arm" ], @@ -8247,9 +8260,9 @@ ] }, "node_modules/@rollup/rollup-linux-arm64-gnu": { - "version": "4.13.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.13.0.tgz", - "integrity": "sha512-Iu0Kno1vrD7zHQDxOmvweqLkAzjxEVqNhUIXBsZ8hu8Oak7/5VTPrxOEZXYC1nmrBVJp0ZcL2E7lSuuOVaE3+w==", + "version": "4.21.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.21.3.tgz", + "integrity": "sha512-nSZfcZtAnQPRZmUkUQwZq2OjQciR6tEoJaZVFvLHsj0MF6QhNMg0fQ6mUOsiCUpTqxTx0/O6gX0V/nYc7LrgPw==", "cpu": [ "arm64" ], @@ -8260,9 +8273,9 @@ ] }, "node_modules/@rollup/rollup-linux-arm64-musl": { - "version": "4.13.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.13.0.tgz", - "integrity": "sha512-C31QrW47llgVyrRjIwiOwsHFcaIwmkKi3PCroQY5aVq4H0A5v/vVVAtFsI1nfBngtoRpeREvZOkIhmRwUKkAdw==", + "version": "4.21.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.21.3.tgz", + "integrity": "sha512-MnvSPGO8KJXIMGlQDYfvYS3IosFN2rKsvxRpPO2l2cum+Z3exiExLwVU+GExL96pn8IP+GdH8Tz70EpBhO0sIQ==", "cpu": [ "arm64" ], @@ -8272,10 +8285,23 @@ "linux" ] }, + "node_modules/@rollup/rollup-linux-powerpc64le-gnu": { + "version": "4.21.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-powerpc64le-gnu/-/rollup-linux-powerpc64le-gnu-4.21.3.tgz", + "integrity": "sha512-+W+p/9QNDr2vE2AXU0qIy0qQE75E8RTwTwgqS2G5CRQ11vzq0tbnfBd6brWhS9bCRjAjepJe2fvvkvS3dno+iw==", + "cpu": [ + "ppc64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ] + }, "node_modules/@rollup/rollup-linux-riscv64-gnu": { - "version": "4.13.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.13.0.tgz", - "integrity": "sha512-Oq90dtMHvthFOPMl7pt7KmxzX7E71AfyIhh+cPhLY9oko97Zf2C9tt/XJD4RgxhaGeAraAXDtqxvKE1y/j35lA==", + "version": "4.21.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.21.3.tgz", + "integrity": "sha512-yXH6K6KfqGXaxHrtr+Uoy+JpNlUlI46BKVyonGiaD74ravdnF9BUNC+vV+SIuB96hUMGShhKV693rF9QDfO6nQ==", "cpu": [ "riscv64" ], @@ -8285,10 +8311,23 @@ "linux" ] }, + "node_modules/@rollup/rollup-linux-s390x-gnu": { + "version": "4.21.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.21.3.tgz", + "integrity": "sha512-R8cwY9wcnApN/KDYWTH4gV/ypvy9yZUHlbJvfaiXSB48JO3KpwSpjOGqO4jnGkLDSk1hgjYkTbTt6Q7uvPf8eg==", + "cpu": [ + "s390x" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ] + }, "node_modules/@rollup/rollup-linux-x64-gnu": { - "version": "4.13.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.13.0.tgz", - "integrity": "sha512-yUD/8wMffnTKuiIsl6xU+4IA8UNhQ/f1sAnQebmE/lyQ8abjsVyDkyRkWop0kdMhKMprpNIhPmYlCxgHrPoXoA==", + "version": "4.21.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.21.3.tgz", + "integrity": "sha512-kZPbX/NOPh0vhS5sI+dR8L1bU2cSO9FgxwM8r7wHzGydzfSjLRCFAT87GR5U9scj2rhzN3JPYVC7NoBbl4FZ0g==", "cpu": [ "x64" ], @@ -8299,9 +8338,9 @@ ] }, "node_modules/@rollup/rollup-linux-x64-musl": { - "version": "4.13.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.13.0.tgz", - "integrity": "sha512-9RyNqoFNdF0vu/qqX63fKotBh43fJQeYC98hCaf89DYQpv+xu0D8QFSOS0biA7cGuqJFOc1bJ+m2rhhsKcw1hw==", + "version": "4.21.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.21.3.tgz", + "integrity": "sha512-S0Yq+xA1VEH66uiMNhijsWAafffydd2X5b77eLHfRmfLsRSpbiAWiRHV6DEpz6aOToPsgid7TI9rGd6zB1rhbg==", "cpu": [ "x64" ], @@ -8312,9 +8351,9 @@ ] }, "node_modules/@rollup/rollup-win32-arm64-msvc": { - "version": "4.13.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.13.0.tgz", - "integrity": "sha512-46ue8ymtm/5PUU6pCvjlic0z82qWkxv54GTJZgHrQUuZnVH+tvvSP0LsozIDsCBFO4VjJ13N68wqrKSeScUKdA==", + "version": "4.21.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.21.3.tgz", + "integrity": "sha512-9isNzeL34yquCPyerog+IMCNxKR8XYmGd0tHSV+OVx0TmE0aJOo9uw4fZfUuk2qxobP5sug6vNdZR6u7Mw7Q+Q==", "cpu": [ "arm64" ], @@ -8325,9 +8364,9 @@ ] }, "node_modules/@rollup/rollup-win32-ia32-msvc": { - "version": "4.13.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.13.0.tgz", - "integrity": "sha512-P5/MqLdLSlqxbeuJ3YDeX37srC8mCflSyTrUsgbU1c/U9j6l2g2GiIdYaGD9QjdMQPMSgYm7hgg0551wHyIluw==", + "version": "4.21.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.21.3.tgz", + "integrity": "sha512-nMIdKnfZfzn1Vsk+RuOvl43ONTZXoAPUUxgcU0tXooqg4YrAqzfKzVenqqk2g5efWh46/D28cKFrOzDSW28gTA==", "cpu": [ "ia32" ], @@ -8338,9 +8377,9 @@ ] }, "node_modules/@rollup/rollup-win32-x64-msvc": { - "version": "4.13.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.13.0.tgz", - "integrity": "sha512-UKXUQNbO3DOhzLRwHSpa0HnhhCgNODvfoPWv2FCXme8N/ANFfhIPMGuOT+QuKd16+B5yxZ0HdpNlqPvTMS1qfw==", + "version": "4.21.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.21.3.tgz", + "integrity": "sha512-fOvu7PCQjAj4eWDEuD8Xz5gpzFqXzGlxHZozHP4b9Jxv9APtdxL6STqztDzMLuRXEc4UpXGGhx029Xgm91QBeA==", "cpu": [ "x64" ], @@ -13921,12 +13960,12 @@ } }, "node_modules/braces": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", - "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz", + "integrity": "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==", "dev": true, "dependencies": { - "fill-range": "^7.0.1" + "fill-range": "^7.1.1" }, "engines": { "node": ">=8" @@ -17577,9 +17616,9 @@ } }, "node_modules/fill-range": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", - "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==", + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz", + "integrity": "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==", "dev": true, "dependencies": { "to-regex-range": "^5.0.1" @@ -21041,12 +21080,12 @@ } }, "node_modules/micromatch": { - "version": "4.0.5", - "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.5.tgz", - "integrity": "sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA==", + "version": "4.0.8", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.8.tgz", + "integrity": "sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==", "dev": true, "dependencies": { - "braces": "^3.0.2", + "braces": "^3.0.3", "picomatch": "^2.3.1" }, "engines": { @@ -25736,9 +25775,9 @@ "dev": true }, "node_modules/picocolors": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.0.tgz", - "integrity": "sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==", + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.0.tgz", + "integrity": "sha512-TQ92mBOW0l3LeMeyLV6mzy/kWr8lkd/hp3mTg7wYK7zJhuBStmGMBG0BdeDZS/dZx1IukaX6Bk11zcln25o1Aw==", "dev": true }, "node_modules/picomatch": { @@ -26013,9 +26052,9 @@ } }, "node_modules/postcss": { - "version": "8.4.38", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.38.tgz", - "integrity": "sha512-Wglpdk03BSfXkHoQa3b/oulrotAkwrlLDRSOb9D0bN86FdRyE9lppSp33aHNPgBa0JKCoB+drFLZkQoRRYae5A==", + "version": "8.4.47", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.47.tgz", + "integrity": "sha512-56rxCq7G/XfB4EkXq9Egn5GCqugWvDFjafDOThIdMBsI15iqPqR5r15TfSr1YPYeEI19YeaXMCbY6u88Y76GLQ==", "dev": true, "funding": [ { @@ -26033,8 +26072,8 @@ ], "dependencies": { "nanoid": "^3.3.7", - "picocolors": "^1.0.0", - "source-map-js": "^1.2.0" + "picocolors": "^1.1.0", + "source-map-js": "^1.2.1" }, "engines": { "node": "^10 || ^12 || >=14" @@ -27356,9 +27395,9 @@ } }, "node_modules/rollup": { - "version": "4.13.0", - "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.13.0.tgz", - "integrity": "sha512-3YegKemjoQnYKmsBlOHfMLVPPA5xLkQ8MHLLSw/fBrFaVkEayL51DilPpNNLq1exr98F2B1TzrV0FUlN3gWRPg==", + "version": "4.21.3", + "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.21.3.tgz", + "integrity": "sha512-7sqRtBNnEbcBtMeRVc6VRsJMmpI+JU1z9VTvW8D4gXIYQFz0aLcsE6rRkyghZkLfEgUZgVvOG7A5CVz/VW5GIA==", "dev": true, "dependencies": { "@types/estree": "1.0.5" @@ -27371,19 +27410,22 @@ "npm": ">=8.0.0" }, "optionalDependencies": { - "@rollup/rollup-android-arm-eabi": "4.13.0", - "@rollup/rollup-android-arm64": "4.13.0", - "@rollup/rollup-darwin-arm64": "4.13.0", - "@rollup/rollup-darwin-x64": "4.13.0", - "@rollup/rollup-linux-arm-gnueabihf": "4.13.0", - "@rollup/rollup-linux-arm64-gnu": "4.13.0", - "@rollup/rollup-linux-arm64-musl": "4.13.0", - "@rollup/rollup-linux-riscv64-gnu": "4.13.0", - "@rollup/rollup-linux-x64-gnu": "4.13.0", - "@rollup/rollup-linux-x64-musl": "4.13.0", - "@rollup/rollup-win32-arm64-msvc": "4.13.0", - "@rollup/rollup-win32-ia32-msvc": "4.13.0", - "@rollup/rollup-win32-x64-msvc": "4.13.0", + "@rollup/rollup-android-arm-eabi": "4.21.3", + "@rollup/rollup-android-arm64": "4.21.3", + "@rollup/rollup-darwin-arm64": "4.21.3", + "@rollup/rollup-darwin-x64": "4.21.3", + "@rollup/rollup-linux-arm-gnueabihf": "4.21.3", + "@rollup/rollup-linux-arm-musleabihf": "4.21.3", + "@rollup/rollup-linux-arm64-gnu": "4.21.3", + "@rollup/rollup-linux-arm64-musl": "4.21.3", + "@rollup/rollup-linux-powerpc64le-gnu": "4.21.3", + "@rollup/rollup-linux-riscv64-gnu": "4.21.3", + "@rollup/rollup-linux-s390x-gnu": "4.21.3", + "@rollup/rollup-linux-x64-gnu": "4.21.3", + "@rollup/rollup-linux-x64-musl": "4.21.3", + "@rollup/rollup-win32-arm64-msvc": "4.21.3", + "@rollup/rollup-win32-ia32-msvc": "4.21.3", + "@rollup/rollup-win32-x64-msvc": "4.21.3", "fsevents": "~2.3.2" } }, @@ -28372,9 +28414,9 @@ } }, "node_modules/source-map-js": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.0.tgz", - "integrity": "sha512-itJW8lvSA0TXEphiRoawsCksnlf8SyvmFzIhltqAHluXd88pkCd+cXJVHTDwdCr0IzwptSm035IHQktUu1QUMg==", + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.1.tgz", + "integrity": "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==", "dev": true, "engines": { "node": ">=0.10.0" @@ -33540,6 +33582,7 @@ "semantic-release-replace-plugin": "^1.2.7", "tsup": "^8.0.2", "typescript": "^5.4.4", + "vite-plugin-singlefile": "^2.0.2", "vitest": "^1.4.0", "vitest-mock-extended": "^1.3.1" }, @@ -33547,6 +33590,397 @@ "node": ">=18" } }, + "packages/dapp-toolkit/node_modules/@esbuild/aix-ppc64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.21.5.tgz", + "integrity": "sha512-1SDgH6ZSPTlggy1yI6+Dbkiz8xzpHJEVAlF/AM1tHPLsf5STom9rwtjE4hKAF20FfXXNTFqEYXyJNWh1GiZedQ==", + "cpu": [ + "ppc64" + ], + "dev": true, + "optional": true, + "os": [ + "aix" + ], + "peer": true, + "engines": { + "node": ">=12" + } + }, + "packages/dapp-toolkit/node_modules/@esbuild/android-arm": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.21.5.tgz", + "integrity": "sha512-vCPvzSjpPHEi1siZdlvAlsPxXl7WbOVUBBAowWug4rJHb68Ox8KualB+1ocNvT5fjv6wpkX6o/iEpbDrf68zcg==", + "cpu": [ + "arm" + ], + "dev": true, + "optional": true, + "os": [ + "android" + ], + "peer": true, + "engines": { + "node": ">=12" + } + }, + "packages/dapp-toolkit/node_modules/@esbuild/android-arm64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.21.5.tgz", + "integrity": "sha512-c0uX9VAUBQ7dTDCjq+wdyGLowMdtR/GoC2U5IYk/7D1H1JYC0qseD7+11iMP2mRLN9RcCMRcjC4YMclCzGwS/A==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "android" + ], + "peer": true, + "engines": { + "node": ">=12" + } + }, + "packages/dapp-toolkit/node_modules/@esbuild/android-x64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.21.5.tgz", + "integrity": "sha512-D7aPRUUNHRBwHxzxRvp856rjUHRFW1SdQATKXH2hqA0kAZb1hKmi02OpYRacl0TxIGz/ZmXWlbZgjwWYaCakTA==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "android" + ], + "peer": true, + "engines": { + "node": ">=12" + } + }, + "packages/dapp-toolkit/node_modules/@esbuild/darwin-arm64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.21.5.tgz", + "integrity": "sha512-DwqXqZyuk5AiWWf3UfLiRDJ5EDd49zg6O9wclZ7kUMv2WRFr4HKjXp/5t8JZ11QbQfUS6/cRCKGwYhtNAY88kQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "darwin" + ], + "peer": true, + "engines": { + "node": ">=12" + } + }, + "packages/dapp-toolkit/node_modules/@esbuild/darwin-x64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.21.5.tgz", + "integrity": "sha512-se/JjF8NlmKVG4kNIuyWMV/22ZaerB+qaSi5MdrXtd6R08kvs2qCN4C09miupktDitvh8jRFflwGFBQcxZRjbw==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "darwin" + ], + "peer": true, + "engines": { + "node": ">=12" + } + }, + "packages/dapp-toolkit/node_modules/@esbuild/freebsd-arm64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.21.5.tgz", + "integrity": "sha512-5JcRxxRDUJLX8JXp/wcBCy3pENnCgBR9bN6JsY4OmhfUtIHe3ZW0mawA7+RDAcMLrMIZaf03NlQiX9DGyB8h4g==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "freebsd" + ], + "peer": true, + "engines": { + "node": ">=12" + } + }, + "packages/dapp-toolkit/node_modules/@esbuild/freebsd-x64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.21.5.tgz", + "integrity": "sha512-J95kNBj1zkbMXtHVH29bBriQygMXqoVQOQYA+ISs0/2l3T9/kj42ow2mpqerRBxDJnmkUDCaQT/dfNXWX/ZZCQ==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "freebsd" + ], + "peer": true, + "engines": { + "node": ">=12" + } + }, + "packages/dapp-toolkit/node_modules/@esbuild/linux-arm": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.21.5.tgz", + "integrity": "sha512-bPb5AHZtbeNGjCKVZ9UGqGwo8EUu4cLq68E95A53KlxAPRmUyYv2D6F0uUI65XisGOL1hBP5mTronbgo+0bFcA==", + "cpu": [ + "arm" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "peer": true, + "engines": { + "node": ">=12" + } + }, + "packages/dapp-toolkit/node_modules/@esbuild/linux-arm64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.21.5.tgz", + "integrity": "sha512-ibKvmyYzKsBeX8d8I7MH/TMfWDXBF3db4qM6sy+7re0YXya+K1cem3on9XgdT2EQGMu4hQyZhan7TeQ8XkGp4Q==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "peer": true, + "engines": { + "node": ">=12" + } + }, + "packages/dapp-toolkit/node_modules/@esbuild/linux-ia32": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.21.5.tgz", + "integrity": "sha512-YvjXDqLRqPDl2dvRODYmmhz4rPeVKYvppfGYKSNGdyZkA01046pLWyRKKI3ax8fbJoK5QbxblURkwK/MWY18Tg==", + "cpu": [ + "ia32" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "peer": true, + "engines": { + "node": ">=12" + } + }, + "packages/dapp-toolkit/node_modules/@esbuild/linux-loong64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.21.5.tgz", + "integrity": "sha512-uHf1BmMG8qEvzdrzAqg2SIG/02+4/DHB6a9Kbya0XDvwDEKCoC8ZRWI5JJvNdUjtciBGFQ5PuBlpEOXQj+JQSg==", + "cpu": [ + "loong64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "peer": true, + "engines": { + "node": ">=12" + } + }, + "packages/dapp-toolkit/node_modules/@esbuild/linux-mips64el": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.21.5.tgz", + "integrity": "sha512-IajOmO+KJK23bj52dFSNCMsz1QP1DqM6cwLUv3W1QwyxkyIWecfafnI555fvSGqEKwjMXVLokcV5ygHW5b3Jbg==", + "cpu": [ + "mips64el" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "peer": true, + "engines": { + "node": ">=12" + } + }, + "packages/dapp-toolkit/node_modules/@esbuild/linux-ppc64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.21.5.tgz", + "integrity": "sha512-1hHV/Z4OEfMwpLO8rp7CvlhBDnjsC3CttJXIhBi+5Aj5r+MBvy4egg7wCbe//hSsT+RvDAG7s81tAvpL2XAE4w==", + "cpu": [ + "ppc64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "peer": true, + "engines": { + "node": ">=12" + } + }, + "packages/dapp-toolkit/node_modules/@esbuild/linux-riscv64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.21.5.tgz", + "integrity": "sha512-2HdXDMd9GMgTGrPWnJzP2ALSokE/0O5HhTUvWIbD3YdjME8JwvSCnNGBnTThKGEB91OZhzrJ4qIIxk/SBmyDDA==", + "cpu": [ + "riscv64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "peer": true, + "engines": { + "node": ">=12" + } + }, + "packages/dapp-toolkit/node_modules/@esbuild/linux-s390x": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.21.5.tgz", + "integrity": "sha512-zus5sxzqBJD3eXxwvjN1yQkRepANgxE9lgOW2qLnmr8ikMTphkjgXu1HR01K4FJg8h1kEEDAqDcZQtbrRnB41A==", + "cpu": [ + "s390x" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "peer": true, + "engines": { + "node": ">=12" + } + }, + "packages/dapp-toolkit/node_modules/@esbuild/linux-x64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.21.5.tgz", + "integrity": "sha512-1rYdTpyv03iycF1+BhzrzQJCdOuAOtaqHTWJZCWvijKD2N5Xu0TtVC8/+1faWqcP9iBCWOmjmhoH94dH82BxPQ==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "peer": true, + "engines": { + "node": ">=12" + } + }, + "packages/dapp-toolkit/node_modules/@esbuild/netbsd-x64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.21.5.tgz", + "integrity": "sha512-Woi2MXzXjMULccIwMnLciyZH4nCIMpWQAs049KEeMvOcNADVxo0UBIQPfSmxB3CWKedngg7sWZdLvLczpe0tLg==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "netbsd" + ], + "peer": true, + "engines": { + "node": ">=12" + } + }, + "packages/dapp-toolkit/node_modules/@esbuild/openbsd-x64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.21.5.tgz", + "integrity": "sha512-HLNNw99xsvx12lFBUwoT8EVCsSvRNDVxNpjZ7bPn947b8gJPzeHWyNVhFsaerc0n3TsbOINvRP2byTZ5LKezow==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "openbsd" + ], + "peer": true, + "engines": { + "node": ">=12" + } + }, + "packages/dapp-toolkit/node_modules/@esbuild/sunos-x64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.21.5.tgz", + "integrity": "sha512-6+gjmFpfy0BHU5Tpptkuh8+uw3mnrvgs+dSPQXQOv3ekbordwnzTVEb4qnIvQcYXq6gzkyTnoZ9dZG+D4garKg==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "sunos" + ], + "peer": true, + "engines": { + "node": ">=12" + } + }, + "packages/dapp-toolkit/node_modules/@esbuild/win32-arm64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.21.5.tgz", + "integrity": "sha512-Z0gOTd75VvXqyq7nsl93zwahcTROgqvuAcYDUr+vOv8uHhNSKROyU961kgtCD1e95IqPKSQKH7tBTslnS3tA8A==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "win32" + ], + "peer": true, + "engines": { + "node": ">=12" + } + }, + "packages/dapp-toolkit/node_modules/@esbuild/win32-ia32": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.21.5.tgz", + "integrity": "sha512-SWXFF1CL2RVNMaVs+BBClwtfZSvDgtL//G/smwAc5oVK/UPu2Gu9tIaRgFmYFFKrmg3SyAjSrElf0TiJ1v8fYA==", + "cpu": [ + "ia32" + ], + "dev": true, + "optional": true, + "os": [ + "win32" + ], + "peer": true, + "engines": { + "node": ">=12" + } + }, + "packages/dapp-toolkit/node_modules/@esbuild/win32-x64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.21.5.tgz", + "integrity": "sha512-tQd/1efJuzPC6rCFwEvLtci/xNFcTZknmXs98FYDfGE4wP9ClFV98nyKrzJKVPMhdDnjzLhdUyMX4PsQAPjwIw==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "win32" + ], + "peer": true, + "engines": { + "node": ">=12" + } + }, "packages/dapp-toolkit/node_modules/@lit/reactive-element": { "version": "2.0.4", "resolved": "https://registry.npmjs.org/@lit/reactive-element/-/reactive-element-2.0.4.tgz", @@ -33992,6 +34426,45 @@ "node": "^18.17 || >=20.6.1" } }, + "packages/dapp-toolkit/node_modules/esbuild": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.21.5.tgz", + "integrity": "sha512-mg3OPMV4hXywwpoDxu3Qda5xCKQi+vCTZq8S9J/EpkhB2HzKXq4SNFZE3+NK93JYxc8VMSep+lOUSC/RVKaBqw==", + "dev": true, + "hasInstallScript": true, + "peer": true, + "bin": { + "esbuild": "bin/esbuild" + }, + "engines": { + "node": ">=12" + }, + "optionalDependencies": { + "@esbuild/aix-ppc64": "0.21.5", + "@esbuild/android-arm": "0.21.5", + "@esbuild/android-arm64": "0.21.5", + "@esbuild/android-x64": "0.21.5", + "@esbuild/darwin-arm64": "0.21.5", + "@esbuild/darwin-x64": "0.21.5", + "@esbuild/freebsd-arm64": "0.21.5", + "@esbuild/freebsd-x64": "0.21.5", + "@esbuild/linux-arm": "0.21.5", + "@esbuild/linux-arm64": "0.21.5", + "@esbuild/linux-ia32": "0.21.5", + "@esbuild/linux-loong64": "0.21.5", + "@esbuild/linux-mips64el": "0.21.5", + "@esbuild/linux-ppc64": "0.21.5", + "@esbuild/linux-riscv64": "0.21.5", + "@esbuild/linux-s390x": "0.21.5", + "@esbuild/linux-x64": "0.21.5", + "@esbuild/netbsd-x64": "0.21.5", + "@esbuild/openbsd-x64": "0.21.5", + "@esbuild/sunos-x64": "0.21.5", + "@esbuild/win32-arm64": "0.21.5", + "@esbuild/win32-ia32": "0.21.5", + "@esbuild/win32-x64": "0.21.5" + } + }, "packages/dapp-toolkit/node_modules/escape-string-regexp": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-5.0.0.tgz", @@ -37366,6 +37839,82 @@ "uuid": "dist/bin/uuid" } }, + "packages/dapp-toolkit/node_modules/vite": { + "version": "5.4.6", + "resolved": "https://registry.npmjs.org/vite/-/vite-5.4.6.tgz", + "integrity": "sha512-IeL5f8OO5nylsgzd9tq4qD2QqI0k2CQLGrWD0rCN0EQJZpBK5vJAx0I+GDkMOXxQX/OfFHMuLIx6ddAxGX/k+Q==", + "dev": true, + "peer": true, + "dependencies": { + "esbuild": "^0.21.3", + "postcss": "^8.4.43", + "rollup": "^4.20.0" + }, + "bin": { + "vite": "bin/vite.js" + }, + "engines": { + "node": "^18.0.0 || >=20.0.0" + }, + "funding": { + "url": "https://github.com/vitejs/vite?sponsor=1" + }, + "optionalDependencies": { + "fsevents": "~2.3.3" + }, + "peerDependencies": { + "@types/node": "^18.0.0 || >=20.0.0", + "less": "*", + "lightningcss": "^1.21.0", + "sass": "*", + "sass-embedded": "*", + "stylus": "*", + "sugarss": "*", + "terser": "^5.4.0" + }, + "peerDependenciesMeta": { + "@types/node": { + "optional": true + }, + "less": { + "optional": true + }, + "lightningcss": { + "optional": true + }, + "sass": { + "optional": true + }, + "sass-embedded": { + "optional": true + }, + "stylus": { + "optional": true + }, + "sugarss": { + "optional": true + }, + "terser": { + "optional": true + } + } + }, + "packages/dapp-toolkit/node_modules/vite-plugin-singlefile": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/vite-plugin-singlefile/-/vite-plugin-singlefile-2.0.2.tgz", + "integrity": "sha512-Z2ou6HcvED5CF0hM+vcFSaFa+klyS8RyyLxW0PbMRLnMbvzTI6ueWyxdYNFhpuXZgz/aj6+E/dHFTdEcw6gb9w==", + "dev": true, + "dependencies": { + "micromatch": "^4.0.7" + }, + "engines": { + "node": ">18.0.0" + }, + "peerDependencies": { + "rollup": "^4.18.0", + "vite": "^5.3.1" + } + }, "packages/eslint-config": { "name": "@repo/eslint-config", "version": "0.0.0", diff --git a/packages/connect-button/src/assets/icon-loading.svg b/packages/connect-button/src/assets/icon-loading.svg index 73f37bdb..9f4e88b5 100644 --- a/packages/connect-button/src/assets/icon-loading.svg +++ b/packages/connect-button/src/assets/icon-loading.svg @@ -1,2 +1,5 @@ - \ No newline at end of file + + + + \ No newline at end of file diff --git a/packages/connect-button/src/components/card/card.ts b/packages/connect-button/src/components/card/card.ts index 53a2d86f..83224f55 100644 --- a/packages/connect-button/src/components/card/card.ts +++ b/packages/connect-button/src/components/card/card.ts @@ -119,6 +119,14 @@ export class RadixCard extends LitElement { mask-image: url(${unsafeCSS(IconLoading)}); width: 24px; height: 24px; + transform-origin: center; + animation: spinner 0.75s infinite linear; + } + + @keyframes spinner { + 100% { + transform: rotate(360deg); + } } :host([icon='ignored']) i::before { diff --git a/packages/connect-button/src/components/connect-button.ts b/packages/connect-button/src/components/connect-button.ts index 8155df92..13b3dc61 100644 --- a/packages/connect-button/src/components/connect-button.ts +++ b/packages/connect-button/src/components/connect-button.ts @@ -96,6 +96,8 @@ export class ConnectButton extends LitElement { pristine = true initialBodyOverflow: string + initialBackdropFilter: string + parentElementWithBackdropFilter: HTMLElement | null windowClickEventHandler: (event: MouseEvent) => void @@ -117,6 +119,8 @@ export class ConnectButton extends LitElement { constructor() { super() this.initialBodyOverflow = document.body.style.overflow + this.initialBackdropFilter = '' + this.parentElementWithBackdropFilter = null this.injectFontCSS() this.windowClickEventHandler = (event) => { if (!this.showPopoverMenu) return @@ -170,6 +174,7 @@ export class ConnectButton extends LitElement { this.pristine = false this.showPopoverMenu = !this.showPopoverMenu this.toggleBodyOverflow() + this.toggleParentBackdropFilter() if (this.showPopoverMenu) { this.dispatchEvent( new CustomEvent('onShowPopover', { @@ -188,6 +193,48 @@ export class ConnectButton extends LitElement { : this.initialBodyOverflow } + private toggleParentBackdropFilter() { + const OPACITY_TRANSITION_DURATION = 180 + if (!this.isMobile) return + + if (!this.showPopoverMenu && this.parentElementWithBackdropFilter) { + setTimeout(() => { + this.parentElementWithBackdropFilter?.style.setProperty( + 'backdrop-filter', + this.initialBackdropFilter, + ) + this.initialBackdropFilter = '' + this.parentElementWithBackdropFilter = null + }, OPACITY_TRANSITION_DURATION) + + return + } else { + const parent = this.findParentWithBackdropFilter(this) + if (parent === null) { + return + } + this.initialBackdropFilter = parent.backdropFilter + this.parentElementWithBackdropFilter = parent.element + + parent.element.style.backdropFilter = 'none' + } + } + + private findParentWithBackdropFilter( + element: HTMLElement | null, + ): { element: HTMLElement; backdropFilter: string } | null { + if (!element) { + return null + } + const style = window.getComputedStyle(element) + const backdropFilter = style.getPropertyValue('backdrop-filter') + if (backdropFilter !== 'none') { + return { element, backdropFilter } + } else { + return this.findParentWithBackdropFilter(element.parentElement) + } + } + private connectButtonTemplate() { const buttonText = this.connected ? this.personaLabel : 'Connect' @@ -262,6 +309,7 @@ export class ConnectButton extends LitElement { if (this.pristine) return '' return html` +``` + # Usage ## Getting started @@ -77,7 +87,7 @@ npm install @radixdlt/radix-dapp-toolkit Add the `` element in your HTML code and instantiate `RadixDappToolkit`. ```typescript -import { RadixDappToolkit, RadixNetwork } from '@radixdlt/radix-dapp-toolkit' +import { RadixDappToolkit, RadixNetwork, Logger } from '@radixdlt/radix-dapp-toolkit' const rdt = RadixDappToolkit({ dAppDefinitionAddress: @@ -85,6 +95,7 @@ const rdt = RadixDappToolkit({ networkId: RadixNetwork.Mainnet, applicationName: 'Radix Web3 dApp', applicationVersion: '1.0.0', + logger: Logger(1) }) ``` diff --git a/packages/dapp-toolkit/package.json b/packages/dapp-toolkit/package.json index ad9cc584..0950c18d 100644 --- a/packages/dapp-toolkit/package.json +++ b/packages/dapp-toolkit/package.json @@ -53,8 +53,9 @@ "types" ], "scripts": { - "dev": "npm run build -- --watch", - "build": "tsup", + "dev": "tsup --watch", + "build": "tsup && npm run build:single", + "build:single": "vite build --config vite-single-file.config.ts && cp dist/radix-dapp-toolkit.bundle.umd.cjs ../../examples/cdn", "test": "vitest", "test:watch": "vitest --watch" }, @@ -82,6 +83,7 @@ "semantic-release-replace-plugin": "^1.2.7", "tsup": "^8.0.2", "typescript": "^5.4.4", + "vite-plugin-singlefile": "^2.0.2", "vitest": "^1.4.0", "vitest-mock-extended": "^1.3.1" }, diff --git a/packages/dapp-toolkit/src/helpers/index.ts b/packages/dapp-toolkit/src/helpers/index.ts index 7b25489c..840c47ae 100644 --- a/packages/dapp-toolkit/src/helpers/index.ts +++ b/packages/dapp-toolkit/src/helpers/index.ts @@ -9,4 +9,5 @@ export * from './typed-error' export * from './unwrap-observable' export * from './validate-wallet-response' export * from './generate-rola-challenge' +export * from './validate-rola-challenge' export * from './parse-signed-challenge' diff --git a/packages/dapp-toolkit/src/helpers/validate-rola-challenge.spec.ts b/packages/dapp-toolkit/src/helpers/validate-rola-challenge.spec.ts new file mode 100644 index 00000000..6883f28b --- /dev/null +++ b/packages/dapp-toolkit/src/helpers/validate-rola-challenge.spec.ts @@ -0,0 +1,32 @@ +import { describe, expect, it } from 'vitest' +import { validateRolaChallenge } from './validate-rola-challenge' + +describe('validateRolaChallenge', () => { + const validTestVectors = [ + '3f30f8d67ca69af8b646170d6ddd0a16cb501dcb7d457d0b49ef78a5d1b4beac', + '0a6a5b8beac0e56b8613f1b1a08223b3986aa28b9acc81d16493c75a428f436e', + '2455077b5bb93e1d5c9816513c3385b88293d91b9d44ed6bd652764834eb997a', + '2455077b5BB93e1d5c9816513c3385b88293d91b9d44ed6BD652764834eb997a', + ] + + const invalidTestVectors = [ + 'abc', + '', + undefined, + null, + {}, + '3f30f8d67ca69af8b646170d6ddd0a16cb501dcb7d457d0b49ef78a5d1b4beacz', + ] + + it('should return true for valid challenge', () => { + validTestVectors.forEach((challenge) => { + expect(validateRolaChallenge(challenge)).toBe(true) + }) + }) + + it('should return false for invalid challenge', () => { + invalidTestVectors.forEach((challenge) => { + expect(validateRolaChallenge(challenge)).toBe(false) + }) + }) +}) diff --git a/packages/dapp-toolkit/src/helpers/validate-rola-challenge.ts b/packages/dapp-toolkit/src/helpers/validate-rola-challenge.ts new file mode 100644 index 00000000..cf57079b --- /dev/null +++ b/packages/dapp-toolkit/src/helpers/validate-rola-challenge.ts @@ -0,0 +1,2 @@ +export const validateRolaChallenge = (challenge?: unknown) => + typeof challenge === 'string' && /^[0-9a-f]{64}$/i.test(challenge); \ No newline at end of file diff --git a/packages/dapp-toolkit/src/modules/state/state.module.ts b/packages/dapp-toolkit/src/modules/state/state.module.ts index 10a9f655..c6c2faba 100644 --- a/packages/dapp-toolkit/src/modules/state/state.module.ts +++ b/packages/dapp-toolkit/src/modules/state/state.module.ts @@ -2,8 +2,7 @@ import { BehaviorSubject, Subscription, filter } from 'rxjs' import { RdtState, WalletData, walletDataDefault } from './types' import { Logger } from '../../helpers' import { StorageModule } from '../storage' -import { SdkError } from '../../error' -import { err, ok } from 'neverthrow' +import { ok, okAsync } from 'neverthrow' export type StateModule = ReturnType @@ -23,12 +22,11 @@ export const StateModule = (input: { const getState = () => storageModule .getState() - .andThen((state) => - state ? ok(state) : err(SdkError('StateNotFound', '')), - ) - + .orElse(() => okAsync(defaultState)) + .andThen((state) => (state ? ok(state) : ok(defaultState))) + const patchState = (state: Partial) => - getState().andThen((oldState) => setState({ ...oldState, ...state })) + getState().andThen((oldState) => setState({ ...oldState, ...state } as RdtState)) const defaultState = { walletData: walletDataDefault, @@ -43,17 +41,8 @@ export const StateModule = (input: { const initializeState = () => getState() - .mapErr(() => { - logger?.debug({ - method: `initializeState.loadedCorruptedStateFromStorage`, - }) - resetState().map(() => { - emitWalletData() - }) - }) - .map(() => { - emitWalletData() - }) + .map(() => emitWalletData()) + .orElse(() => resetState()) initializeState() diff --git a/packages/dapp-toolkit/src/modules/storage/local-storage.module.spec.ts b/packages/dapp-toolkit/src/modules/storage/local-storage.module.spec.ts new file mode 100644 index 00000000..23d5c36d --- /dev/null +++ b/packages/dapp-toolkit/src/modules/storage/local-storage.module.spec.ts @@ -0,0 +1,69 @@ +/** + * @vitest-environment jsdom + */ + +import { beforeEach, describe, expect, it } from 'vitest' +import { LocalStorageModule, StorageModule } from './local-storage.module' +import { ResultAsync } from 'neverthrow' + +describe('LocalStorageModule', () => { + let storageModule: StorageModule + + beforeEach(() => { + storageModule = LocalStorageModule(`rdt:${crypto.randomUUID()}:1`) + }) + + it('should store and read data', async () => { + await storageModule.setState({ key: 'value' }) + const data = await storageModule.getState() + expect(data.isOk() && data.value).toEqual({ key: 'value' }) + }) + + describe('getItemById', () => { + it('should get specific item', async () => { + await storageModule.setState({ specific: 'value', key: 'value' }) + const data = await storageModule.getItemById('specific') + expect(data.isOk() && data.value).toEqual('value') + }) + }) + + describe('setItems', () => { + it('should set multiple items separately', async () => { + await storageModule.setItems({ + specific: 'value', + }) + + await storageModule.setItems({ key: 'value' }) + const data = await storageModule.getItems() + expect(data.isOk() && data.value).toEqual({ + specific: 'value', + key: 'value', + }) + }) + + // TODO: This currently fails. Uncomment this test when working on RDT-225 and ensure it's passing + it.skip('should set multiple items at once', async () => { + await ResultAsync.combine([ + storageModule.setItems({ + specific: 'value', + }), + storageModule.setItems({ key: 'value' }), + ]) + + const data = await storageModule.getItems() + expect(data.isOk() && data.value).toEqual({ + specific: 'value', + key: 'value', + }) + }) + }) + + describe('removeItemById', () => { + it('should remove specific item', async () => { + await storageModule.setState({ specific: 'value', key: 'value' }) + await storageModule.removeItemById('specific') + const data = await storageModule.getState() + expect(data.isOk() && data.value).toEqual({ key: 'value' }) + }) + }) +}) diff --git a/packages/dapp-toolkit/src/modules/storage/local-storage.module.ts b/packages/dapp-toolkit/src/modules/storage/local-storage.module.ts index 73063d08..888a8204 100644 --- a/packages/dapp-toolkit/src/modules/storage/local-storage.module.ts +++ b/packages/dapp-toolkit/src/modules/storage/local-storage.module.ts @@ -9,6 +9,7 @@ type PartitionKey = | 'requests' | 'state' | 'connectButton' + | 'walletResponses' | 'connectorExtension' type dAppDefinitionAddress = string @@ -53,6 +54,11 @@ export const LocalStorageModule = ( data ? parseJSON(data) : ok({}), ) + const getState = (): ResultAsync => + ResultAsync.fromPromise(getDataAsync(), typedError).andThen((data) => + data ? parseJSON(data) : ok(undefined), + ) + const getItemById = (id: string): ResultAsync => ResultAsync.fromPromise(getDataAsync(), typedError) .andThen((data) => (data ? parseJSON(data) : ok(undefined))) @@ -61,7 +67,21 @@ export const LocalStorageModule = ( const removeItemById = (id: string): ResultAsync => getItems().andThen((items) => { const { [id]: _, ...newItems } = items - return setItems(newItems) + return stringify(newItems).asyncAndThen((serialized) => { + const result = ResultAsync.fromPromise( + setDataAsync(serialized), + typedError, + ).map(() => { + window.dispatchEvent( + new StorageEvent('storage', { + key: storageKey, + oldValue: JSON.stringify(items), + newValue: serialized, + }), + ) + }) + return result + }) }) const patchItem = (id: string, patch: Partial): ResultAsync => @@ -93,11 +113,6 @@ export const LocalStorageModule = ( const getItemList = (): ResultAsync => getItems().map(Object.values) - const getState = (): ResultAsync => - ResultAsync.fromPromise(getDataAsync(), typedError).andThen((data) => - data ? parseJSON(data) : ok(undefined), - ) - const setState = (newValue: T): ResultAsync => getState().andThen((oldValue) => stringify({ ...(oldValue ?? {}), ...newValue }).asyncAndThen( diff --git a/packages/dapp-toolkit/src/modules/wallet-request/transport/connector-extension/connector-extension.module.ts b/packages/dapp-toolkit/src/modules/wallet-request/transport/connector-extension/connector-extension.module.ts index cf3824e6..0cceadfd 100644 --- a/packages/dapp-toolkit/src/modules/wallet-request/transport/connector-extension/connector-extension.module.ts +++ b/packages/dapp-toolkit/src/modules/wallet-request/transport/connector-extension/connector-extension.module.ts @@ -55,7 +55,7 @@ export const ConnectorExtensionModule = (input: { const subjects = input?.subjects ?? ConnectorExtensionSubjects() const subscription = new Subscription() - const extensionDetectionTime = input?.extensionDetectionTime ?? 100 + const extensionDetectionTime = input?.extensionDetectionTime ?? 200 const requestItemModule = input.providers.requestItemModule const storage = input.providers.storageModule.getPartition('connectorExtension') @@ -239,9 +239,9 @@ export const ConnectorExtensionModule = (input: { filter((value): value is Err => !('eventType' in value)), ) - const sendWalletRequest$ = of( - wrapOutgoingInteraction(walletInteraction), - ).pipe( + const sendWalletRequest$ = extensionStatus$.pipe( + filter((status) => status.isExtensionAvailable), + switchMap(() => of(wrapOutgoingInteraction(walletInteraction))), tap((result) => { result.map((message) => { subjects.outgoingMessageSubject.next(message) diff --git a/packages/dapp-toolkit/src/modules/wallet-request/transport/radix-connect-relay/radix-connect-relay.module.ts b/packages/dapp-toolkit/src/modules/wallet-request/transport/radix-connect-relay/radix-connect-relay.module.ts index 7988bd8f..a1c19e01 100644 --- a/packages/dapp-toolkit/src/modules/wallet-request/transport/radix-connect-relay/radix-connect-relay.module.ts +++ b/packages/dapp-toolkit/src/modules/wallet-request/transport/radix-connect-relay/radix-connect-relay.module.ts @@ -1,4 +1,4 @@ -import { ResultAsync, err, errAsync, ok } from 'neverthrow' +import { ResultAsync, err, errAsync, ok, okAsync } from 'neverthrow' import { Subscription } from 'rxjs' import { EncryptionModule, transformBufferToSealbox } from '../../encryption' import { Session, SessionModule } from '../../session/session.module' @@ -40,6 +40,9 @@ export const RadixConnectRelayModule = (input: { const { baseUrl, providers, walletUrl } = input const { requestItemModule, storageModule } = providers + const walletResponses: StorageModule = + storageModule.getPartition('walletResponses') + const encryptionModule = providers?.encryptionModule ?? EncryptionModule() const deepLinkModule = @@ -75,6 +78,62 @@ export const RadixConnectRelayModule = (input: { const subscriptions = new Subscription() + const wait = (timer = 1500) => + new Promise((resolve) => setTimeout(resolve, timer)) + + const decryptWalletResponse = ( + walletResponse: WalletResponse, + ): ResultAsync => { + if ('error' in walletResponse) { + return errAsync({ reason: walletResponse.error }) + } + + return identityModule.get('dApp').andThen((dAppIdentity) => + dAppIdentity.x25519 + .calculateSharedSecret( + walletResponse.publicKey, + input.dAppDefinitionAddress, + ) + .mapErr(() => ({ reason: 'FailedToDeriveSharedSecret' })) + .asyncAndThen((sharedSecret) => + decryptWalletResponseData(sharedSecret, walletResponse.data), + ), + ) + } + + const checkRelayLoop = async () => { + await requestItemModule.getPending().andThen((pendingItems) => { + if (pendingItems.length === 0) { + return okAsync(undefined) + } + + return sessionModule + .getCurrentSession() + .andThen((session) => + radixConnectRelayApiService.getResponses(session.sessionId), + ) + .andThen((responses) => + ResultAsync.combine( + responses.map((response) => decryptWalletResponse(response)), + ).andThen((decryptedResponses) => { + return walletResponses.setItems( + decryptedResponses.reduce( + (acc, response) => { + acc[response.interactionId] = response + return acc + }, + {} as Record, + ), + ) + }), + ) + }) + await wait() + checkRelayLoop() + } + + checkRelayLoop() + const sendWalletInteractionRequest = ({ session, walletInteraction, @@ -156,13 +215,7 @@ export const RadixConnectRelayModule = (input: { publicKey: dAppIdentity.x25519.getPublicKey(), }), ) - .andThen(() => - waitForWalletResponse({ - session, - interactionId: walletInteraction.interactionId, - dAppIdentity, - }), - ), + .andThen(() => waitForWalletResponse(walletInteraction.interactionId)), ) const decryptWalletResponseData = ( @@ -188,50 +241,19 @@ export const RadixConnectRelayModule = (input: { jsError: error, })) - const waitForWalletResponse = ({ - session, - interactionId, - dAppIdentity, - }: { - session: Session - interactionId: string - dAppIdentity: Curve25519 - }): ResultAsync => + const waitForWalletResponse = ( + interactionId: string, + ): ResultAsync => ResultAsync.fromPromise( new Promise(async (resolve, reject) => { let response: WalletInteractionResponse | undefined let error: SdkError | undefined - let retry = 0 - - const wait = (timer = 1500) => - new Promise((resolve) => setTimeout(resolve, timer)) logger?.debug({ method: 'waitForWalletResponse', - sessionId: session.sessionId, interactionId, }) - const getEncryptedWalletResponses = () => - radixConnectRelayApiService.getResponses(session.sessionId) - - const decryptWalletResponse = ( - walletResponse: WalletResponse, - ): ResultAsync => { - if ('error' in walletResponse) { - return errAsync({ reason: walletResponse.error }) - } - return dAppIdentity.x25519 - .calculateSharedSecret( - walletResponse.publicKey, - input.dAppDefinitionAddress, - ) - .mapErr(() => ({ reason: 'FailedToDeriveSharedSecret' })) - .asyncAndThen((sharedSecret) => - decryptWalletResponseData(sharedSecret, walletResponse.data), - ) - } - while (!response) { const requestItemResult = await requestItemModule.getById(interactionId) @@ -251,41 +273,20 @@ export const RadixConnectRelayModule = (input: { } } - const encryptedWalletResponsesResult = - await getEncryptedWalletResponses() - - if (encryptedWalletResponsesResult.isOk()) { - const encryptedWalletResponses = - encryptedWalletResponsesResult.value - - for (const encryptedWalletResponse of encryptedWalletResponses) { - const walletResponseResult = await decryptWalletResponse( - encryptedWalletResponse, - ) - - if (walletResponseResult.isErr()) - logger?.error({ - method: 'waitForWalletResponse.decryptWalletResponse.error', - error: walletResponseResult.error, - sessionId: session.sessionId, - interactionId, - }) - - if (walletResponseResult.isOk()) { - const walletResponse = walletResponseResult.value + const walletResponse = + await walletResponses.getItemById(interactionId) - if (walletResponse.interactionId === interactionId) { - response = walletResponse - await requestItemModule.patch(walletResponse.interactionId, { - walletResponse, - }) - } - } + if (walletResponse.isOk()) { + if (walletResponse.value) { + response = walletResponse.value + await walletResponses.removeItemById(interactionId) + await requestItemModule.patch(interactionId, { + walletResponse: walletResponse.value, + }) } } if (!response) { - retry += 1 await wait() } } diff --git a/packages/dapp-toolkit/src/modules/wallet-request/wallet-request.ts b/packages/dapp-toolkit/src/modules/wallet-request/wallet-request.ts index 7fa2883c..2e05c099 100644 --- a/packages/dapp-toolkit/src/modules/wallet-request/wallet-request.ts +++ b/packages/dapp-toolkit/src/modules/wallet-request/wallet-request.ts @@ -9,7 +9,7 @@ import { switchMap, tap, } from 'rxjs' -import type { Logger } from '../../helpers' +import { validateRolaChallenge, type Logger } from '../../helpers' import { TransactionStatus } from '../gateway' import { Result, ResultAsync, err, ok, okAsync } from 'neverthrow' import type { @@ -181,6 +181,10 @@ export const WalletRequestModule = (input: { return ResultAsync.fromPromise(challengeGeneratorFn(), () => SdkError('ChallengeGeneratorError', '', 'failed to generate challenge'), + ).andThen((challenge) => + validateRolaChallenge(challenge) + ? ok(challenge) + : err(SdkError('ChallengeValidationError', '', 'challenge is invalid')), ) }