diff --git a/projects/TokenizeRWATemplate-frontend/package-lock.json b/projects/TokenizeRWATemplate-frontend/package-lock.json
index a584322..2b56109 100644
--- a/projects/TokenizeRWATemplate-frontend/package-lock.json
+++ b/projects/TokenizeRWATemplate-frontend/package-lock.json
@@ -9,13 +9,15 @@
"version": "0.1.0",
"dependencies": {
"@algorandfoundation/algokit-utils": "^9.0.0",
+ "@babel/runtime": "^7.28.6",
"@blockshake/defly-connect": "^1.2.1",
"@perawallet/connect": "^1.4.1",
- "@txnlab/use-wallet": "^4.0.0",
- "@txnlab/use-wallet-react": "^4.0.0",
+ "@txnlab/use-wallet": "^4.4.0",
+ "@txnlab/use-wallet-react": "^4.4.0",
"@web3auth/base": "^9.7.0",
"@web3auth/base-provider": "^9.7.0",
"@web3auth/modal": "^9.7.0",
+ "@web3auth/single-factor-auth": "^9.5.0",
"algosdk": "^3.0.0",
"daisyui": "^4.0.0",
"idb-keyval": "^6.2.2",
@@ -25,7 +27,8 @@
"react-dom": "^18.2.0",
"react-icons": "^5.5.0",
"react-router-dom": "^7.11.0",
- "tslib": "^2.6.2"
+ "tslib": "^2.6.2",
+ "tweetnacl": "^1.0.3"
},
"devDependencies": {
"@algorandfoundation/algokit-client-generator": "^5.0.0",
@@ -38,11 +41,13 @@
"@typescript-eslint/parser": "^7.0.2",
"@vitejs/plugin-react": "^4.2.1",
"autoprefixer": "^10.4.14",
+ "buffer": "^6.0.3",
"eslint": "^8.56.0",
"eslint-config-prettier": "^9.1.0",
"eslint-plugin-prettier": "^5.1.3",
"playwright": "^1.35.0",
"postcss": "^8.4.24",
+ "process": "^0.11.10",
"tailwindcss": "3.3.2",
"ts-jest": "^29.1.1",
"ts-node": "^10.9.1",
@@ -618,9 +623,9 @@
}
},
"node_modules/@babel/runtime": {
- "version": "7.28.4",
- "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.28.4.tgz",
- "integrity": "sha512-Q/N6JNWvIvPnLDvjlE1OUBLPQHH6l3CltCEsHIujp45zQUSSh8K+gHnaEX45yAT1nyngnINhvWtzN+Nb9D8RAQ==",
+ "version": "7.28.6",
+ "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.28.6.tgz",
+ "integrity": "sha512-05WQkdpL9COIMz4LjTxGpPNCdlpyimKppYNoJ5Di5EUObifl8t4tuLuUBBZEpoLYOmfvIWrsp9fCl0HoPRVTdA==",
"license": "MIT",
"engines": {
"node": ">=6.9.0"
@@ -3144,13 +3149,13 @@
"license": "MIT"
},
"node_modules/@tanstack/react-store": {
- "version": "0.7.3",
- "resolved": "https://registry.npmjs.org/@tanstack/react-store/-/react-store-0.7.3.tgz",
- "integrity": "sha512-3Dnqtbw9P2P0gw8uUM8WP2fFfg8XMDSZCTsywRPZe/XqqYW8PGkXKZTvP0AHkE4mpqP9Y43GpOg9vwO44azu6Q==",
+ "version": "0.8.0",
+ "resolved": "https://registry.npmjs.org/@tanstack/react-store/-/react-store-0.8.0.tgz",
+ "integrity": "sha512-1vG9beLIuB7q69skxK9r5xiLN3ztzIPfSQSs0GfeqWGO2tGIyInZx0x1COhpx97RKaONSoAb8C3dxacWksm1ow==",
"license": "MIT",
"dependencies": {
- "@tanstack/store": "0.7.2",
- "use-sync-external-store": "^1.5.0"
+ "@tanstack/store": "0.8.0",
+ "use-sync-external-store": "^1.6.0"
},
"funding": {
"type": "github",
@@ -3162,9 +3167,9 @@
}
},
"node_modules/@tanstack/store": {
- "version": "0.7.2",
- "resolved": "https://registry.npmjs.org/@tanstack/store/-/store-0.7.2.tgz",
- "integrity": "sha512-RP80Z30BYiPX2Pyo0Nyw4s1SJFH2jyM6f9i3HfX4pA+gm5jsnYryscdq2aIQLnL4TaGuQMO+zXmN9nh1Qck+Pg==",
+ "version": "0.8.0",
+ "resolved": "https://registry.npmjs.org/@tanstack/store/-/store-0.8.0.tgz",
+ "integrity": "sha512-Om+BO0YfMZe//X2z0uLF2j+75nQga6TpTJgLJQBiq85aOyZNIhkCgleNcud2KQg4k4v9Y9l+Uhru3qWMPGTOzQ==",
"license": "MIT",
"funding": {
"type": "github",
@@ -3214,6 +3219,19 @@
"npm": ">=9.x"
}
},
+ "node_modules/@toruslabs/bs58": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/@toruslabs/bs58/-/bs58-1.0.0.tgz",
+ "integrity": "sha512-osqIgm1MzEB6+fkaQeEUg4tuZXmhhXTn+K7+nZU7xDBcy+8Yr3eGNqJcQ4jds82g+dhkk2cBkge9sffv38iDQQ==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=18.x",
+ "npm": ">=9.x"
+ },
+ "peerDependencies": {
+ "@babel/runtime": "7.x"
+ }
+ },
"node_modules/@toruslabs/constants": {
"version": "14.2.0",
"resolved": "https://registry.npmjs.org/@toruslabs/constants/-/constants-14.2.0.tgz",
@@ -3250,6 +3268,22 @@
"npm": ">=9.x"
}
},
+ "node_modules/@toruslabs/fnd-base": {
+ "version": "14.2.0",
+ "resolved": "https://registry.npmjs.org/@toruslabs/fnd-base/-/fnd-base-14.2.0.tgz",
+ "integrity": "sha512-nqfcigOuz3pQJi+Q+tdCaDUVCaSUkGqqmw0bGnaKK2/PyXBlZhnEDzReM3aUbApJn3xitfrJEhnRvOJhzog/og==",
+ "license": "MIT",
+ "dependencies": {
+ "@toruslabs/constants": "^14.2.0"
+ },
+ "engines": {
+ "node": ">=18.x",
+ "npm": ">=9.x"
+ },
+ "peerDependencies": {
+ "@babel/runtime": "7.x"
+ }
+ },
"node_modules/@toruslabs/http-helpers": {
"version": "7.0.1",
"resolved": "https://registry.npmjs.org/@toruslabs/http-helpers/-/http-helpers-7.0.1.tgz",
@@ -3361,6 +3395,36 @@
"integrity": "sha512-v2YAxEmKaBLahNwE1mjp4WON6huMNeuDvagFZW+ASCuA/ku0bXR9hSMw0XpiqMoA3+rmnyck/tPRSFQkoC9Cuw==",
"license": "MIT"
},
+ "node_modules/@toruslabs/torus.js": {
+ "version": "15.1.1",
+ "resolved": "https://registry.npmjs.org/@toruslabs/torus.js/-/torus.js-15.1.1.tgz",
+ "integrity": "sha512-sLaXA1/R8KTTjU4t+teL3PPaJr2+j01QLYn5IY/t5uTD+1G2nzzfVWpkMDYrk9EfQYw0u4aKJ1lT7j9uKafMlg==",
+ "license": "MIT",
+ "dependencies": {
+ "@toruslabs/bs58": "^1.0.0",
+ "@toruslabs/constants": "^14.0.0",
+ "@toruslabs/eccrypto": "^5.0.4",
+ "@toruslabs/http-helpers": "^7.0.0",
+ "bn.js": "^5.2.1",
+ "elliptic": "^6.5.7",
+ "ethereum-cryptography": "^2.2.1",
+ "json-stable-stringify": "^1.1.1",
+ "loglevel": "^1.9.2"
+ },
+ "engines": {
+ "node": ">=18.x",
+ "npm": ">=9.x"
+ },
+ "peerDependencies": {
+ "@babel/runtime": "7.x"
+ }
+ },
+ "node_modules/@toruslabs/torus.js/node_modules/bn.js": {
+ "version": "5.2.2",
+ "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-5.2.2.tgz",
+ "integrity": "sha512-v2YAxEmKaBLahNwE1mjp4WON6huMNeuDvagFZW+ASCuA/ku0bXR9hSMw0XpiqMoA3+rmnyck/tPRSFQkoC9Cuw==",
+ "license": "MIT"
+ },
"node_modules/@toruslabs/tweetnacl-js": {
"version": "1.0.4",
"resolved": "https://registry.npmjs.org/@toruslabs/tweetnacl-js/-/tweetnacl-js-1.0.4.tgz",
@@ -3396,21 +3460,25 @@
"license": "MIT"
},
"node_modules/@txnlab/use-wallet": {
- "version": "4.3.1",
- "resolved": "https://registry.npmjs.org/@txnlab/use-wallet/-/use-wallet-4.3.1.tgz",
- "integrity": "sha512-kWDOauxROjwmnOmivp5iBAXqdksYHDXaP7P/AbX/uawnv+H+WQiP0dBUKnVLb//eOUbhq7QT33yUGGXC6QATgQ==",
+ "version": "4.4.0",
+ "resolved": "https://registry.npmjs.org/@txnlab/use-wallet/-/use-wallet-4.4.0.tgz",
+ "integrity": "sha512-FMapmviqrLbKk80NsSM2hcChZl2W3fE52hTQ7+6LFfNiLbCQFH//mBZGipV5/bhyIx0pTgxcXMKygRprz6S9Fw==",
"license": "MIT",
"dependencies": {
- "@tanstack/store": "0.7.2"
+ "@tanstack/store": "0.8.0"
},
"peerDependencies": {
"@agoralabs-sh/avm-web-provider": "^1.7.0",
"@blockshake/defly-connect": "^1.2.1",
"@perawallet/connect": "^1.4.1",
"@walletconnect/modal": "^2.7.0",
- "@walletconnect/sign-client": "^2.21.8",
+ "@walletconnect/sign-client": "^2.23.1",
+ "@web3auth/base": "^9.0.0",
+ "@web3auth/base-provider": "^9.0.0",
+ "@web3auth/modal": "^9.0.0",
+ "@web3auth/single-factor-auth": "^9.0.0",
"algosdk": "^3.0.0",
- "lute-connect": "^1.6.2"
+ "lute-connect": "^1.6.3"
},
"peerDependenciesMeta": {
"@agoralabs-sh/avm-web-provider": {
@@ -3428,28 +3496,40 @@
"@walletconnect/sign-client": {
"optional": true
},
+ "@web3auth/base": {
+ "optional": true
+ },
+ "@web3auth/base-provider": {
+ "optional": true
+ },
+ "@web3auth/modal": {
+ "optional": true
+ },
+ "@web3auth/single-factor-auth": {
+ "optional": true
+ },
"lute-connect": {
"optional": true
}
}
},
"node_modules/@txnlab/use-wallet-react": {
- "version": "4.3.1",
- "resolved": "https://registry.npmjs.org/@txnlab/use-wallet-react/-/use-wallet-react-4.3.1.tgz",
- "integrity": "sha512-Gmj1qBNykx2HbFS4FzzqCa8uWI4UkdYw2mk6a+62AVoKU2/hvPe9K6DvdDrc883dJoRSK0xPtSGjJ6lKxT1bCQ==",
+ "version": "4.4.0",
+ "resolved": "https://registry.npmjs.org/@txnlab/use-wallet-react/-/use-wallet-react-4.4.0.tgz",
+ "integrity": "sha512-IQX0cUB8bybnGluhN46t8kCEtBof9yxB1aK6ru4DeysUuTn9pkWAF5/bTDK15+lJTs/88+C4v26CUGvbiNAltQ==",
"license": "MIT",
"dependencies": {
- "@tanstack/react-store": "0.7.3",
- "@txnlab/use-wallet": "4.3.1"
+ "@tanstack/react-store": "0.8.0",
+ "@txnlab/use-wallet": "4.4.0"
},
"peerDependencies": {
"@blockshake/defly-connect": "^1.2.1",
"@magic-ext/algorand": "^24.4.2",
"@perawallet/connect": "^1.4.1",
"@walletconnect/modal": "^2.7.0",
- "@walletconnect/sign-client": "^2.21.8",
+ "@walletconnect/sign-client": "^2.23.1",
"algosdk": "^3.0.0",
- "lute-connect": "^1.6.2",
+ "lute-connect": "^1.6.3",
"magic-sdk": "^29.4.2",
"react": "^17.0.0 || ^18.0.0 || ^19.0.0",
"react-dom": "^17.0.0 || ^18.0.0 || ^19.0.0"
@@ -5180,6 +5260,56 @@
}
}
},
+ "node_modules/@web3auth/single-factor-auth": {
+ "version": "9.5.0",
+ "resolved": "https://registry.npmjs.org/@web3auth/single-factor-auth/-/single-factor-auth-9.5.0.tgz",
+ "integrity": "sha512-50cjvQ6kXDgbUXmjlVgxEN6qV8giMqDn6dc7IykANflLfTjjZKc8EKmis7CwRFlCIESGZ2vIOL4CFo0StHVvpg==",
+ "license": "ISC",
+ "dependencies": {
+ "@toruslabs/base-controllers": "^6.3.2",
+ "@toruslabs/constants": "^14.2.0",
+ "@toruslabs/fnd-base": "^14.2.0",
+ "@toruslabs/session-manager": "^3.2.0",
+ "@toruslabs/torus.js": "^15.1.1",
+ "@web3auth/auth": "^9.6.4",
+ "@web3auth/base": "^9.7.0",
+ "bs58": "^5.0.0"
+ },
+ "engines": {
+ "node": ">=18.x",
+ "npm": ">=9.x"
+ },
+ "optionalDependencies": {
+ "@rollup/rollup-linux-x64-gnu": "^4.34.9"
+ },
+ "peerDependencies": {
+ "@babel/runtime": "^7.x"
+ }
+ },
+ "node_modules/@web3auth/single-factor-auth/node_modules/@toruslabs/base-controllers": {
+ "version": "6.3.3",
+ "resolved": "https://registry.npmjs.org/@toruslabs/base-controllers/-/base-controllers-6.3.3.tgz",
+ "integrity": "sha512-za1QD4jADtSWFMYVDZ9YZJMxzoBtT0T/SWkmQECOiAVtlUQgPn9naIqzc1ApBYdzwp9GUaxe4P1510R+5I/Ncg==",
+ "license": "ISC",
+ "dependencies": {
+ "@ethereumjs/util": "^9.1.0",
+ "@toruslabs/broadcast-channel": "^11.0.0",
+ "@toruslabs/http-helpers": "^7.0.0",
+ "@web3auth/auth": "^9.5.2",
+ "async-mutex": "^0.5.0",
+ "bignumber.js": "^9.1.2",
+ "bowser": "^2.11.0",
+ "jwt-decode": "^4.0.0",
+ "loglevel": "^1.9.2"
+ },
+ "engines": {
+ "node": ">=18.x",
+ "npm": ">=9.x"
+ },
+ "peerDependencies": {
+ "@babel/runtime": "7.x"
+ }
+ },
"node_modules/@web3auth/ui": {
"version": "9.7.0",
"resolved": "https://registry.npmjs.org/@web3auth/ui/-/ui-9.7.0.tgz",
@@ -5633,6 +5763,12 @@
"dev": true,
"license": "MIT"
},
+ "node_modules/base-x": {
+ "version": "4.0.1",
+ "resolved": "https://registry.npmjs.org/base-x/-/base-x-4.0.1.tgz",
+ "integrity": "sha512-uAZ8x6r6S3aUM9rbHGVOIsR15U/ZSc82b3ymnCPsT45Gk1DDvhDPdIgB5MrhirZWt+5K0EEPQH985kNqZgNPFw==",
+ "license": "MIT"
+ },
"node_modules/base64-js": {
"version": "1.5.1",
"resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz",
@@ -5956,6 +6092,15 @@
"node": ">= 6"
}
},
+ "node_modules/bs58": {
+ "version": "5.0.0",
+ "resolved": "https://registry.npmjs.org/bs58/-/bs58-5.0.0.tgz",
+ "integrity": "sha512-r+ihvQJvahgYT50JD05dyJNKlmmSlMoOGwn1lCcEzanPglg7TxYjioQUYehQ9mAR/+hOSd2jRc/Z2y5UxBymvQ==",
+ "license": "MIT",
+ "dependencies": {
+ "base-x": "^4.0.0"
+ }
+ },
"node_modules/bser": {
"version": "2.1.1",
"resolved": "https://registry.npmjs.org/bser/-/bser-2.1.1.tgz",
diff --git a/projects/TokenizeRWATemplate-frontend/package.json b/projects/TokenizeRWATemplate-frontend/package.json
index c36c349..3becf65 100644
--- a/projects/TokenizeRWATemplate-frontend/package.json
+++ b/projects/TokenizeRWATemplate-frontend/package.json
@@ -22,11 +22,13 @@
"@typescript-eslint/parser": "^7.0.2",
"@vitejs/plugin-react": "^4.2.1",
"autoprefixer": "^10.4.14",
+ "buffer": "^6.0.3",
"eslint": "^8.56.0",
"eslint-config-prettier": "^9.1.0",
"eslint-plugin-prettier": "^5.1.3",
"playwright": "^1.35.0",
"postcss": "^8.4.24",
+ "process": "^0.11.10",
"tailwindcss": "3.3.2",
"ts-jest": "^29.1.1",
"ts-node": "^10.9.1",
@@ -36,13 +38,15 @@
},
"dependencies": {
"@algorandfoundation/algokit-utils": "^9.0.0",
+ "@babel/runtime": "^7.28.6",
"@blockshake/defly-connect": "^1.2.1",
"@perawallet/connect": "^1.4.1",
- "@txnlab/use-wallet": "^4.0.0",
- "@txnlab/use-wallet-react": "^4.0.0",
+ "@txnlab/use-wallet": "^4.4.0",
+ "@txnlab/use-wallet-react": "^4.4.0",
"@web3auth/base": "^9.7.0",
"@web3auth/base-provider": "^9.7.0",
"@web3auth/modal": "^9.7.0",
+ "@web3auth/single-factor-auth": "^9.5.0",
"algosdk": "^3.0.0",
"daisyui": "^4.0.0",
"idb-keyval": "^6.2.2",
@@ -52,7 +56,8 @@
"react-dom": "^18.2.0",
"react-icons": "^5.5.0",
"react-router-dom": "^7.11.0",
- "tslib": "^2.6.2"
+ "tslib": "^2.6.2",
+ "tweetnacl": "^1.0.3"
},
"scripts": {
"generate:app-clients": "algokit project link --all",
diff --git a/projects/TokenizeRWATemplate-frontend/src/App.tsx b/projects/TokenizeRWATemplate-frontend/src/App.tsx
index c621da1..68d8bc1 100644
--- a/projects/TokenizeRWATemplate-frontend/src/App.tsx
+++ b/projects/TokenizeRWATemplate-frontend/src/App.tsx
@@ -1,71 +1,99 @@
import { SupportedWallet, WalletId, WalletManager, WalletProvider } from '@txnlab/use-wallet-react'
import { SnackbarProvider } from 'notistack'
+import { useMemo } from 'react'
import { BrowserRouter, Route, Routes } from 'react-router-dom'
-import { Web3AuthProvider } from './components/Web3AuthProvider'
import Home from './Home'
import Layout from './Layout'
import TokenizePage from './TokenizePage'
import { getAlgodConfigFromViteEnvironment, getKmdConfigFromViteEnvironment } from './utils/network/getAlgoClientConfigs'
-// Configure supported wallets based on network environment
-let supportedWallets: SupportedWallet[]
-if (import.meta.env.VITE_ALGOD_NETWORK === 'localnet') {
- // LocalNet: KMD wallet for local development
- const kmdConfig = getKmdConfigFromViteEnvironment()
- supportedWallets = [
- {
- id: WalletId.KMD,
- options: {
- baseServer: kmdConfig.server,
- token: String(kmdConfig.token),
- port: String(kmdConfig.port),
- },
- },
- { id: WalletId.LUTE },
- ]
-} else {
- // TestNet/MainNet: Browser extension wallets (Pera, Defly, Exodus, Lute)
- supportedWallets = [{ id: WalletId.DEFLY }, { id: WalletId.PERA }, { id: WalletId.EXODUS }, { id: WalletId.LUTE }]
-}
+// Get Web3Auth client ID from environment
+const web3AuthClientId = (import.meta.env.VITE_WEB3AUTH_CLIENT_ID ?? '').trim()
/**
- * Main App Component
- * Sets up wallet provider and routing for the Tokenization dApp
+ * Build supported wallets list based on env/network.
+ * NOTE: Web3Auth defaults to sapphire_mainnet unless web3AuthNetwork is provided.
*/
+function buildSupportedWallets(): SupportedWallet[] {
+ if (import.meta.env.VITE_ALGOD_NETWORK === 'localnet') {
+ const kmdConfig = getKmdConfigFromViteEnvironment()
+ return [
+ {
+ id: WalletId.KMD,
+ options: {
+ baseServer: kmdConfig.server,
+ token: String(kmdConfig.token),
+ port: String(kmdConfig.port),
+ },
+ },
+ { id: WalletId.LUTE },
+ ]
+ }
+
+ // TestNet/MainNet wallets
+ const wallets: SupportedWallet[] = [{ id: WalletId.PERA }, { id: WalletId.DEFLY }, { id: WalletId.LUTE }]
+
+ // Only add Web3Auth if we actually have a client id
+ // use-wallet v4.4.0+ includes built-in Web3Auth provider
+ if (web3AuthClientId) {
+ wallets.push({
+ id: WalletId.WEB3AUTH,
+ options: {
+ clientId: web3AuthClientId,
+ // Web3Auth network: 'sapphire_devnet' for development, 'sapphire_mainnet' for production
+ web3AuthNetwork: 'sapphire_devnet',
+ // Optional: Set default login provider (e.g., 'google' for direct Google login)
+ // If not set, shows full provider selection modal
+ // loginProvider: 'google',
+ // Optional: UI customization
+ uiConfig: {
+ appName: 'Tokenize RWA Template',
+ mode: 'auto', // 'auto' | 'light' | 'dark'
+ },
+ },
+ })
+ }
+
+ return wallets
+}
+
export default function App() {
const algodConfig = getAlgodConfigFromViteEnvironment()
- const walletManager = new WalletManager({
- wallets: supportedWallets,
- defaultNetwork: algodConfig.network,
- networks: {
- [algodConfig.network]: {
- algod: {
- baseServer: algodConfig.server,
- port: algodConfig.port,
- token: String(algodConfig.token),
+ const supportedWallets = useMemo(() => buildSupportedWallets(), [])
+ const walletManager = useMemo(() => {
+ const mgr = new WalletManager({
+ wallets: supportedWallets,
+ defaultNetwork: algodConfig.network,
+ networks: {
+ [algodConfig.network]: {
+ algod: {
+ baseServer: algodConfig.server,
+ port: algodConfig.port,
+ token: String(algodConfig.token),
+ },
},
},
- },
- options: {
- resetNetwork: true,
- },
- })
+ options: {
+ resetNetwork: true,
+ },
+ })
+
+ return mgr
+ }, [algodConfig.network, algodConfig.server, algodConfig.port, algodConfig.token, supportedWallets])
return (