diff --git a/frontend/.env.example b/frontend/.env.example
new file mode 100644
index 0000000..7327744
--- /dev/null
+++ b/frontend/.env.example
@@ -0,0 +1,23 @@
+# Reown (WalletConnect) Project ID
+# Get one at https://cloud.reown.com
+VITE_REOWN_PROJECT_ID=""
+
+# Contract Addresses - Sepolia
+VITE_CONTRACT_ADDRESS_SEPOLIA_GOLD_TOKEN="0x19ad15A55D28B59775934be8913389F23b38fC34"
+VITE_CONTRACT_ADDRESS_SEPOLIA_LOTTERIE="0xa44599409aDb9D9E69f5e262a9Cc17658D306565"
+VITE_CONTRACT_ADDRESS_SEPOLIA_TOKEN_BRIDGE="0x1AF470D6e52A8aA3b1328Bb74D93967E0DC0F721"
+
+# Contract Addresses - BSC Testnet
+VITE_CONTRACT_ADDRESS_BSC_TESTNET_GOLD_TOKEN="0xaDA54cF66fe2aA440C2c230346a7B7621B61DF31"
+VITE_CONTRACT_ADDRESS_BSC_TESTNET_LOTTERIE="0x0B0970beDa533276435bDcdD45DF9cE2875E6d78"
+VITE_CONTRACT_ADDRESS_BSC_TESTNET_TOKEN_BRIDGE="0x4380FDA9f42BE8aEcda15CC5e6D67C87b20EcA6a"
+
+# RPC URLs
+VITE_RPC_URL_SEPOLIA=""
+VITE_RPC_URL_BSC_TESTNET=""
+
+# Site Metadata
+VITE_SITE_NAME="Golden Bridge"
+VITE_SITE_DESCRIPTION="Gold-backed tokenization with lottery rewards"
+VITE_SITE_URL="http://localhost:5173"
+VITE_SITE_ICON="https://assets.reown.com/reown-profile-pic.png"
diff --git a/frontend/.gitignore b/frontend/.gitignore
new file mode 100644
index 0000000..641e30c
--- /dev/null
+++ b/frontend/.gitignore
@@ -0,0 +1,8 @@
+# Node modules
+node_modules/
+
+# Dist folder
+dist/
+
+# Environment variables
+.env
\ No newline at end of file
diff --git a/frontend/README.md b/frontend/README.md
new file mode 100644
index 0000000..fde8d9c
--- /dev/null
+++ b/frontend/README.md
@@ -0,0 +1,90 @@
+# Golden Bridge Frontend
+
+This is the frontend application for the Golden Bridge project, a gold-backed tokenization platform with lottery rewards and cross-chain bridging capabilities.
+
+## Project Description
+
+The Golden Bridge frontend allows users to:
+
+- Connect their wallet (MetaMask, WalletConnect, etc.)
+- Mint and burn Gold Tokens (GLD)
+- Participate in the daily lottery
+- Bridge tokens between Ethereum Sepolia and BSC Testnet
+- View their token balance and transaction history
+
+## Setup Instructions
+
+1. **Prerequisites:**
+
+ - Node.js (v18 or later)
+ - npm or yarn
+
+2. **Installation:**
+
+ ```bash
+ cd frontend
+ npm install
+ ```
+
+3. **Environment Configuration:**
+
+ - Copy `.env.example` to `.env`:
+ ```bash
+ cp .env.example .env
+ ```
+ - Update the `.env` file with your specific configuration values (RPC URLs, Project ID, etc.).
+
+4. **Running the Application:**
+ ```bash
+ npm run dev
+ ```
+ The application will be available at `http://localhost:5173`.
+
+## Environment Variables
+
+The following environment variables are required in the `.env` file:
+
+- `VITE_REOWN_PROJECT_ID`: Your Reown (ex WalletConnect) Project ID
+- `VITE_CONTRACT_ADDRESS_SEPOLIA_GOLD_TOKEN`: Gold Token contract address on Ethereum Sepolia
+- `VITE_CONTRACT_ADDRESS_SEPOLIA_LOTTERIE`: Lotterie contract address on Ethereum Sepolia
+- `VITE_CONTRACT_ADDRESS_SEPOLIA_TOKEN_BRIDGE`: Token Bridge contract address on Ethereum Sepolia
+- `VITE_CONTRACT_ADDRESS_BSC_TESTNET_GOLD_TOKEN`: Gold Token contract address on BSC Testnet
+- `VITE_CONTRACT_ADDRESS_BSC_TESTNET_LOTTERIE`: Lotterie contract address on BSC Testnet
+- `VITE_CONTRACT_ADDRESS_BSC_TESTNET_TOKEN_BRIDGE`: Token Bridge contract address on BSC Testnet
+- `VITE_RPC_URL_SEPOLIA`: RPC URL for Ethereum Sepolia
+- `VITE_RPC_URL_BSC_TESTNET`: RPC URL for BSC Testnet
+- `VITE_SITE_NAME`: Name of the site (default: "Golden Bridge")
+- `VITE_SITE_DESCRIPTION`: Description of the site
+- `VITE_SITE_URL`: URL of the site
+- `VITE_SITE_ICON`: URL of the site icon
+
+## Available Scripts
+
+- `npm run dev`: Starts the development server
+- `npm run build`: Builds the application for production
+- `npm run preview`: Previews the production build locally
+- `npm run lint`: Runs ESLint to check for code quality issues
+
+## Project Structure
+
+- `src/components`: React components
+ - `Dashboard`: Main dashboard component
+ - `GoldToken`: Components related to Gold Token operations
+ - `Lotterie`: Components related to the lottery
+ - `TokenBridge`: Components related to the bridge
+ - `ui`: Reusable UI components
+- `src/config`: Configuration files (contracts, networks, etc.)
+- `src/hooks`: Custom React hooks
+- `src/styles`: Global styles and CSS modules
+- `src/types`: TypeScript type definitions
+- `src/utils`: Utility functions
+- `abi`: Smart contract ABIs
+
+## Technologies Used
+
+- React
+- TypeScript
+- Vite
+- ethers.js
+- Reown AppKit (WalletConnect)
+- CSS Modules
diff --git a/frontend/abi/goldToken/goldTokenAbi.json b/frontend/abi/goldToken/goldTokenAbi.json
new file mode 100644
index 0000000..0597a29
--- /dev/null
+++ b/frontend/abi/goldToken/goldTokenAbi.json
@@ -0,0 +1,722 @@
+{
+ "abi": [
+ { "type": "constructor", "inputs": [], "stateMutability": "nonpayable" },
+ {
+ "type": "function",
+ "name": "DEFAULT_ADMIN_ROLE",
+ "inputs": [],
+ "outputs": [{ "name": "", "type": "bytes32", "internalType": "bytes32" }],
+ "stateMutability": "view"
+ },
+ {
+ "type": "function",
+ "name": "OWNER_ROLE",
+ "inputs": [],
+ "outputs": [{ "name": "", "type": "bytes32", "internalType": "bytes32" }],
+ "stateMutability": "view"
+ },
+ {
+ "type": "function",
+ "name": "UPGRADE_INTERFACE_VERSION",
+ "inputs": [],
+ "outputs": [{ "name": "", "type": "string", "internalType": "string" }],
+ "stateMutability": "view"
+ },
+ {
+ "type": "function",
+ "name": "addOwner",
+ "inputs": [
+ { "name": "account", "type": "address", "internalType": "address" }
+ ],
+ "outputs": [],
+ "stateMutability": "nonpayable"
+ },
+ {
+ "type": "function",
+ "name": "allowance",
+ "inputs": [
+ { "name": "owner", "type": "address", "internalType": "address" },
+ { "name": "spender", "type": "address", "internalType": "address" }
+ ],
+ "outputs": [{ "name": "", "type": "uint256", "internalType": "uint256" }],
+ "stateMutability": "view"
+ },
+ {
+ "type": "function",
+ "name": "approve",
+ "inputs": [
+ { "name": "spender", "type": "address", "internalType": "address" },
+ { "name": "value", "type": "uint256", "internalType": "uint256" }
+ ],
+ "outputs": [{ "name": "", "type": "bool", "internalType": "bool" }],
+ "stateMutability": "nonpayable"
+ },
+ {
+ "type": "function",
+ "name": "balanceOf",
+ "inputs": [
+ { "name": "account", "type": "address", "internalType": "address" }
+ ],
+ "outputs": [{ "name": "", "type": "uint256", "internalType": "uint256" }],
+ "stateMutability": "view"
+ },
+ {
+ "type": "function",
+ "name": "burn",
+ "inputs": [
+ { "name": "amount", "type": "uint256", "internalType": "uint256" }
+ ],
+ "outputs": [],
+ "stateMutability": "nonpayable"
+ },
+ {
+ "type": "function",
+ "name": "claimEth",
+ "inputs": [],
+ "outputs": [],
+ "stateMutability": "nonpayable"
+ },
+ {
+ "type": "function",
+ "name": "decimals",
+ "inputs": [],
+ "outputs": [{ "name": "", "type": "uint8", "internalType": "uint8" }],
+ "stateMutability": "view"
+ },
+ {
+ "type": "function",
+ "name": "getFees",
+ "inputs": [],
+ "outputs": [{ "name": "", "type": "uint256", "internalType": "uint256" }],
+ "stateMutability": "view"
+ },
+ {
+ "type": "function",
+ "name": "getFeesAddress",
+ "inputs": [],
+ "outputs": [{ "name": "", "type": "address", "internalType": "address" }],
+ "stateMutability": "view"
+ },
+ {
+ "type": "function",
+ "name": "getGoldPriceInEth",
+ "inputs": [],
+ "outputs": [{ "name": "", "type": "int256", "internalType": "int256" }],
+ "stateMutability": "view"
+ },
+ {
+ "type": "function",
+ "name": "getRoleAdmin",
+ "inputs": [
+ { "name": "role", "type": "bytes32", "internalType": "bytes32" }
+ ],
+ "outputs": [{ "name": "", "type": "bytes32", "internalType": "bytes32" }],
+ "stateMutability": "view"
+ },
+ {
+ "type": "function",
+ "name": "getTimestamps",
+ "inputs": [],
+ "outputs": [
+ { "name": "", "type": "address[]", "internalType": "address[]" },
+ { "name": "", "type": "uint256[]", "internalType": "uint256[]" }
+ ],
+ "stateMutability": "view"
+ },
+ {
+ "type": "function",
+ "name": "getUsers",
+ "inputs": [],
+ "outputs": [
+ { "name": "", "type": "address[]", "internalType": "address[]" }
+ ],
+ "stateMutability": "view"
+ },
+ {
+ "type": "function",
+ "name": "grantRole",
+ "inputs": [
+ { "name": "role", "type": "bytes32", "internalType": "bytes32" },
+ { "name": "account", "type": "address", "internalType": "address" }
+ ],
+ "outputs": [],
+ "stateMutability": "nonpayable"
+ },
+ {
+ "type": "function",
+ "name": "hasOwnerRole",
+ "inputs": [
+ { "name": "account", "type": "address", "internalType": "address" }
+ ],
+ "outputs": [{ "name": "", "type": "bool", "internalType": "bool" }],
+ "stateMutability": "view"
+ },
+ {
+ "type": "function",
+ "name": "hasRole",
+ "inputs": [
+ { "name": "role", "type": "bytes32", "internalType": "bytes32" },
+ { "name": "account", "type": "address", "internalType": "address" }
+ ],
+ "outputs": [{ "name": "", "type": "bool", "internalType": "bool" }],
+ "stateMutability": "view"
+ },
+ {
+ "type": "function",
+ "name": "initialize",
+ "inputs": [
+ { "name": "owner", "type": "address", "internalType": "address" },
+ {
+ "name": "dataFeedGoldAddress",
+ "type": "address",
+ "internalType": "address"
+ },
+ {
+ "name": "dataFeedEthAddress",
+ "type": "address",
+ "internalType": "address"
+ }
+ ],
+ "outputs": [],
+ "stateMutability": "nonpayable"
+ },
+ {
+ "type": "function",
+ "name": "mint",
+ "inputs": [],
+ "outputs": [],
+ "stateMutability": "payable"
+ },
+ {
+ "type": "function",
+ "name": "name",
+ "inputs": [],
+ "outputs": [{ "name": "", "type": "string", "internalType": "string" }],
+ "stateMutability": "view"
+ },
+ {
+ "type": "function",
+ "name": "pause",
+ "inputs": [],
+ "outputs": [],
+ "stateMutability": "nonpayable"
+ },
+ {
+ "type": "function",
+ "name": "paused",
+ "inputs": [],
+ "outputs": [{ "name": "", "type": "bool", "internalType": "bool" }],
+ "stateMutability": "view"
+ },
+ {
+ "type": "function",
+ "name": "proxiableUUID",
+ "inputs": [],
+ "outputs": [{ "name": "", "type": "bytes32", "internalType": "bytes32" }],
+ "stateMutability": "view"
+ },
+ {
+ "type": "function",
+ "name": "removeOwner",
+ "inputs": [
+ { "name": "account", "type": "address", "internalType": "address" }
+ ],
+ "outputs": [],
+ "stateMutability": "nonpayable"
+ },
+ {
+ "type": "function",
+ "name": "renounceRole",
+ "inputs": [
+ { "name": "role", "type": "bytes32", "internalType": "bytes32" },
+ {
+ "name": "callerConfirmation",
+ "type": "address",
+ "internalType": "address"
+ }
+ ],
+ "outputs": [],
+ "stateMutability": "nonpayable"
+ },
+ {
+ "type": "function",
+ "name": "revokeRole",
+ "inputs": [
+ { "name": "role", "type": "bytes32", "internalType": "bytes32" },
+ { "name": "account", "type": "address", "internalType": "address" }
+ ],
+ "outputs": [],
+ "stateMutability": "nonpayable"
+ },
+ {
+ "type": "function",
+ "name": "setFeesAddress",
+ "inputs": [
+ { "name": "feesAddress", "type": "address", "internalType": "address" }
+ ],
+ "outputs": [],
+ "stateMutability": "nonpayable"
+ },
+ {
+ "type": "function",
+ "name": "setLotterieAddress",
+ "inputs": [
+ {
+ "name": "lotterieAddress",
+ "type": "address",
+ "internalType": "address"
+ }
+ ],
+ "outputs": [],
+ "stateMutability": "nonpayable"
+ },
+ {
+ "type": "function",
+ "name": "supportsInterface",
+ "inputs": [
+ { "name": "interfaceId", "type": "bytes4", "internalType": "bytes4" }
+ ],
+ "outputs": [{ "name": "", "type": "bool", "internalType": "bool" }],
+ "stateMutability": "view"
+ },
+ {
+ "type": "function",
+ "name": "symbol",
+ "inputs": [],
+ "outputs": [{ "name": "", "type": "string", "internalType": "string" }],
+ "stateMutability": "view"
+ },
+ {
+ "type": "function",
+ "name": "totalSupply",
+ "inputs": [],
+ "outputs": [{ "name": "", "type": "uint256", "internalType": "uint256" }],
+ "stateMutability": "view"
+ },
+ {
+ "type": "function",
+ "name": "transfer",
+ "inputs": [
+ { "name": "to", "type": "address", "internalType": "address" },
+ { "name": "amount", "type": "uint256", "internalType": "uint256" }
+ ],
+ "outputs": [{ "name": "", "type": "bool", "internalType": "bool" }],
+ "stateMutability": "nonpayable"
+ },
+ {
+ "type": "function",
+ "name": "transferFrom",
+ "inputs": [
+ { "name": "from", "type": "address", "internalType": "address" },
+ { "name": "to", "type": "address", "internalType": "address" },
+ { "name": "value", "type": "uint256", "internalType": "uint256" }
+ ],
+ "outputs": [{ "name": "", "type": "bool", "internalType": "bool" }],
+ "stateMutability": "nonpayable"
+ },
+ {
+ "type": "function",
+ "name": "unpause",
+ "inputs": [],
+ "outputs": [],
+ "stateMutability": "nonpayable"
+ },
+ {
+ "type": "function",
+ "name": "upgradeToAndCall",
+ "inputs": [
+ {
+ "name": "newImplementation",
+ "type": "address",
+ "internalType": "address"
+ },
+ { "name": "data", "type": "bytes", "internalType": "bytes" }
+ ],
+ "outputs": [],
+ "stateMutability": "payable"
+ },
+ {
+ "type": "event",
+ "name": "Approval",
+ "inputs": [
+ {
+ "name": "owner",
+ "type": "address",
+ "indexed": true,
+ "internalType": "address"
+ },
+ {
+ "name": "spender",
+ "type": "address",
+ "indexed": true,
+ "internalType": "address"
+ },
+ {
+ "name": "value",
+ "type": "uint256",
+ "indexed": false,
+ "internalType": "uint256"
+ }
+ ],
+ "anonymous": false
+ },
+ {
+ "type": "event",
+ "name": "FeesAddressUpdated",
+ "inputs": [
+ {
+ "name": "previousFeesAddress",
+ "type": "address",
+ "indexed": true,
+ "internalType": "address"
+ },
+ {
+ "name": "newFeesAddress",
+ "type": "address",
+ "indexed": true,
+ "internalType": "address"
+ }
+ ],
+ "anonymous": false
+ },
+ {
+ "type": "event",
+ "name": "GoldTokenInitialized",
+ "inputs": [
+ {
+ "name": "owner",
+ "type": "address",
+ "indexed": true,
+ "internalType": "address"
+ },
+ {
+ "name": "dataFeedGold",
+ "type": "address",
+ "indexed": true,
+ "internalType": "address"
+ },
+ {
+ "name": "dataFeedEth",
+ "type": "address",
+ "indexed": true,
+ "internalType": "address"
+ }
+ ],
+ "anonymous": false
+ },
+ {
+ "type": "event",
+ "name": "Initialized",
+ "inputs": [
+ {
+ "name": "version",
+ "type": "uint64",
+ "indexed": false,
+ "internalType": "uint64"
+ }
+ ],
+ "anonymous": false
+ },
+ {
+ "type": "event",
+ "name": "LotterieAddressUpdated",
+ "inputs": [
+ {
+ "name": "previousLotterieAddress",
+ "type": "address",
+ "indexed": true,
+ "internalType": "address"
+ },
+ {
+ "name": "newLotterieAddress",
+ "type": "address",
+ "indexed": true,
+ "internalType": "address"
+ }
+ ],
+ "anonymous": false
+ },
+ {
+ "type": "event",
+ "name": "Mint",
+ "inputs": [
+ {
+ "name": "to",
+ "type": "address",
+ "indexed": true,
+ "internalType": "address"
+ },
+ {
+ "name": "amount",
+ "type": "uint256",
+ "indexed": false,
+ "internalType": "uint256"
+ }
+ ],
+ "anonymous": false
+ },
+ {
+ "type": "event",
+ "name": "Paused",
+ "inputs": [
+ {
+ "name": "account",
+ "type": "address",
+ "indexed": false,
+ "internalType": "address"
+ }
+ ],
+ "anonymous": false
+ },
+ {
+ "type": "event",
+ "name": "RoleAdminChanged",
+ "inputs": [
+ {
+ "name": "role",
+ "type": "bytes32",
+ "indexed": true,
+ "internalType": "bytes32"
+ },
+ {
+ "name": "previousAdminRole",
+ "type": "bytes32",
+ "indexed": true,
+ "internalType": "bytes32"
+ },
+ {
+ "name": "newAdminRole",
+ "type": "bytes32",
+ "indexed": true,
+ "internalType": "bytes32"
+ }
+ ],
+ "anonymous": false
+ },
+ {
+ "type": "event",
+ "name": "RoleGranted",
+ "inputs": [
+ {
+ "name": "role",
+ "type": "bytes32",
+ "indexed": true,
+ "internalType": "bytes32"
+ },
+ {
+ "name": "account",
+ "type": "address",
+ "indexed": true,
+ "internalType": "address"
+ },
+ {
+ "name": "sender",
+ "type": "address",
+ "indexed": true,
+ "internalType": "address"
+ }
+ ],
+ "anonymous": false
+ },
+ {
+ "type": "event",
+ "name": "RoleRevoked",
+ "inputs": [
+ {
+ "name": "role",
+ "type": "bytes32",
+ "indexed": true,
+ "internalType": "bytes32"
+ },
+ {
+ "name": "account",
+ "type": "address",
+ "indexed": true,
+ "internalType": "address"
+ },
+ {
+ "name": "sender",
+ "type": "address",
+ "indexed": true,
+ "internalType": "address"
+ }
+ ],
+ "anonymous": false
+ },
+ {
+ "type": "event",
+ "name": "Transfer",
+ "inputs": [
+ {
+ "name": "from",
+ "type": "address",
+ "indexed": true,
+ "internalType": "address"
+ },
+ {
+ "name": "to",
+ "type": "address",
+ "indexed": true,
+ "internalType": "address"
+ },
+ {
+ "name": "value",
+ "type": "uint256",
+ "indexed": false,
+ "internalType": "uint256"
+ }
+ ],
+ "anonymous": false
+ },
+ {
+ "type": "event",
+ "name": "Unpaused",
+ "inputs": [
+ {
+ "name": "account",
+ "type": "address",
+ "indexed": false,
+ "internalType": "address"
+ }
+ ],
+ "anonymous": false
+ },
+ {
+ "type": "event",
+ "name": "Upgraded",
+ "inputs": [
+ {
+ "name": "implementation",
+ "type": "address",
+ "indexed": true,
+ "internalType": "address"
+ }
+ ],
+ "anonymous": false
+ },
+ {
+ "type": "event",
+ "name": "UserAdded",
+ "inputs": [
+ {
+ "name": "user",
+ "type": "address",
+ "indexed": true,
+ "internalType": "address"
+ },
+ {
+ "name": "timestamp",
+ "type": "uint256",
+ "indexed": false,
+ "internalType": "uint256"
+ }
+ ],
+ "anonymous": false
+ },
+ {
+ "type": "event",
+ "name": "UserRemoved",
+ "inputs": [
+ {
+ "name": "user",
+ "type": "address",
+ "indexed": true,
+ "internalType": "address"
+ }
+ ],
+ "anonymous": false
+ },
+ { "type": "error", "name": "AccessControlBadConfirmation", "inputs": [] },
+ {
+ "type": "error",
+ "name": "AccessControlUnauthorizedAccount",
+ "inputs": [
+ { "name": "account", "type": "address", "internalType": "address" },
+ { "name": "neededRole", "type": "bytes32", "internalType": "bytes32" }
+ ]
+ },
+ {
+ "type": "error",
+ "name": "AddressEmptyCode",
+ "inputs": [
+ { "name": "target", "type": "address", "internalType": "address" }
+ ]
+ },
+ { "type": "error", "name": "AmountMustBeGreaterThanZero", "inputs": [] },
+ {
+ "type": "error",
+ "name": "ERC1967InvalidImplementation",
+ "inputs": [
+ {
+ "name": "implementation",
+ "type": "address",
+ "internalType": "address"
+ }
+ ]
+ },
+ { "type": "error", "name": "ERC1967NonPayable", "inputs": [] },
+ {
+ "type": "error",
+ "name": "ERC20InsufficientAllowance",
+ "inputs": [
+ { "name": "spender", "type": "address", "internalType": "address" },
+ { "name": "allowance", "type": "uint256", "internalType": "uint256" },
+ { "name": "needed", "type": "uint256", "internalType": "uint256" }
+ ]
+ },
+ {
+ "type": "error",
+ "name": "ERC20InsufficientBalance",
+ "inputs": [
+ { "name": "sender", "type": "address", "internalType": "address" },
+ { "name": "balance", "type": "uint256", "internalType": "uint256" },
+ { "name": "needed", "type": "uint256", "internalType": "uint256" }
+ ]
+ },
+ {
+ "type": "error",
+ "name": "ERC20InvalidApprover",
+ "inputs": [
+ { "name": "approver", "type": "address", "internalType": "address" }
+ ]
+ },
+ {
+ "type": "error",
+ "name": "ERC20InvalidReceiver",
+ "inputs": [
+ { "name": "receiver", "type": "address", "internalType": "address" }
+ ]
+ },
+ {
+ "type": "error",
+ "name": "ERC20InvalidSender",
+ "inputs": [
+ { "name": "sender", "type": "address", "internalType": "address" }
+ ]
+ },
+ {
+ "type": "error",
+ "name": "ERC20InvalidSpender",
+ "inputs": [
+ { "name": "spender", "type": "address", "internalType": "address" }
+ ]
+ },
+ { "type": "error", "name": "EnforcedPause", "inputs": [] },
+ { "type": "error", "name": "EthTransferFailed", "inputs": [] },
+ { "type": "error", "name": "ExpectedPause", "inputs": [] },
+ { "type": "error", "name": "FailedCall", "inputs": [] },
+ { "type": "error", "name": "InvalidGoldPrice", "inputs": [] },
+ { "type": "error", "name": "InvalidInitialization", "inputs": [] },
+ { "type": "error", "name": "NotInitializing", "inputs": [] },
+ { "type": "error", "name": "ReentrancyGuardReentrantCall", "inputs": [] },
+ { "type": "error", "name": "UUPSUnauthorizedCallContext", "inputs": [] },
+ {
+ "type": "error",
+ "name": "UUPSUnsupportedProxiableUUID",
+ "inputs": [
+ { "name": "slot", "type": "bytes32", "internalType": "bytes32" }
+ ]
+ },
+ { "type": "error", "name": "ValueMustBeGreaterThanZero", "inputs": [] }
+ ]
+}
diff --git a/frontend/abi/goldToken/iGoldTokenAbi.json b/frontend/abi/goldToken/iGoldTokenAbi.json
new file mode 100644
index 0000000..844c19c
--- /dev/null
+++ b/frontend/abi/goldToken/iGoldTokenAbi.json
@@ -0,0 +1,286 @@
+{
+ "abi": [
+ {
+ "type": "function",
+ "name": "addOwner",
+ "inputs": [
+ { "name": "account", "type": "address", "internalType": "address" }
+ ],
+ "outputs": [],
+ "stateMutability": "nonpayable"
+ },
+ {
+ "type": "function",
+ "name": "balanceOf",
+ "inputs": [
+ { "name": "account", "type": "address", "internalType": "address" }
+ ],
+ "outputs": [{ "name": "", "type": "uint256", "internalType": "uint256" }],
+ "stateMutability": "view"
+ },
+ {
+ "type": "function",
+ "name": "burn",
+ "inputs": [
+ { "name": "amount", "type": "uint256", "internalType": "uint256" }
+ ],
+ "outputs": [],
+ "stateMutability": "nonpayable"
+ },
+ {
+ "type": "function",
+ "name": "claimEth",
+ "inputs": [],
+ "outputs": [],
+ "stateMutability": "nonpayable"
+ },
+ {
+ "type": "function",
+ "name": "getFees",
+ "inputs": [],
+ "outputs": [{ "name": "", "type": "uint256", "internalType": "uint256" }],
+ "stateMutability": "view"
+ },
+ {
+ "type": "function",
+ "name": "getFeesAddress",
+ "inputs": [],
+ "outputs": [{ "name": "", "type": "address", "internalType": "address" }],
+ "stateMutability": "view"
+ },
+ {
+ "type": "function",
+ "name": "getGoldPriceInEth",
+ "inputs": [],
+ "outputs": [{ "name": "", "type": "int256", "internalType": "int256" }],
+ "stateMutability": "view"
+ },
+ {
+ "type": "function",
+ "name": "getTimestamps",
+ "inputs": [],
+ "outputs": [
+ { "name": "", "type": "address[]", "internalType": "address[]" },
+ { "name": "", "type": "uint256[]", "internalType": "uint256[]" }
+ ],
+ "stateMutability": "view"
+ },
+ {
+ "type": "function",
+ "name": "getUsers",
+ "inputs": [],
+ "outputs": [
+ { "name": "", "type": "address[]", "internalType": "address[]" }
+ ],
+ "stateMutability": "view"
+ },
+ {
+ "type": "function",
+ "name": "hasOwnerRole",
+ "inputs": [
+ { "name": "account", "type": "address", "internalType": "address" }
+ ],
+ "outputs": [{ "name": "", "type": "bool", "internalType": "bool" }],
+ "stateMutability": "view"
+ },
+ {
+ "type": "function",
+ "name": "initialize",
+ "inputs": [
+ { "name": "owner", "type": "address", "internalType": "address" },
+ {
+ "name": "dataFeedGoldAddress",
+ "type": "address",
+ "internalType": "address"
+ },
+ {
+ "name": "dataFeedEthAddress",
+ "type": "address",
+ "internalType": "address"
+ }
+ ],
+ "outputs": [],
+ "stateMutability": "nonpayable"
+ },
+ {
+ "type": "function",
+ "name": "mint",
+ "inputs": [],
+ "outputs": [],
+ "stateMutability": "payable"
+ },
+ {
+ "type": "function",
+ "name": "pause",
+ "inputs": [],
+ "outputs": [],
+ "stateMutability": "nonpayable"
+ },
+ {
+ "type": "function",
+ "name": "removeOwner",
+ "inputs": [
+ { "name": "account", "type": "address", "internalType": "address" }
+ ],
+ "outputs": [],
+ "stateMutability": "nonpayable"
+ },
+ {
+ "type": "function",
+ "name": "setFeesAddress",
+ "inputs": [
+ { "name": "feesAddress", "type": "address", "internalType": "address" }
+ ],
+ "outputs": [],
+ "stateMutability": "nonpayable"
+ },
+ {
+ "type": "function",
+ "name": "setLotterieAddress",
+ "inputs": [
+ {
+ "name": "lotterieAddress",
+ "type": "address",
+ "internalType": "address"
+ }
+ ],
+ "outputs": [],
+ "stateMutability": "nonpayable"
+ },
+ {
+ "type": "function",
+ "name": "transfer",
+ "inputs": [
+ { "name": "to", "type": "address", "internalType": "address" },
+ { "name": "amount", "type": "uint256", "internalType": "uint256" }
+ ],
+ "outputs": [{ "name": "", "type": "bool", "internalType": "bool" }],
+ "stateMutability": "nonpayable"
+ },
+ {
+ "type": "function",
+ "name": "unpause",
+ "inputs": [],
+ "outputs": [],
+ "stateMutability": "nonpayable"
+ },
+ {
+ "type": "event",
+ "name": "FeesAddressUpdated",
+ "inputs": [
+ {
+ "name": "previousFeesAddress",
+ "type": "address",
+ "indexed": true,
+ "internalType": "address"
+ },
+ {
+ "name": "newFeesAddress",
+ "type": "address",
+ "indexed": true,
+ "internalType": "address"
+ }
+ ],
+ "anonymous": false
+ },
+ {
+ "type": "event",
+ "name": "GoldTokenInitialized",
+ "inputs": [
+ {
+ "name": "owner",
+ "type": "address",
+ "indexed": true,
+ "internalType": "address"
+ },
+ {
+ "name": "dataFeedGold",
+ "type": "address",
+ "indexed": true,
+ "internalType": "address"
+ },
+ {
+ "name": "dataFeedEth",
+ "type": "address",
+ "indexed": true,
+ "internalType": "address"
+ }
+ ],
+ "anonymous": false
+ },
+ {
+ "type": "event",
+ "name": "LotterieAddressUpdated",
+ "inputs": [
+ {
+ "name": "previousLotterieAddress",
+ "type": "address",
+ "indexed": true,
+ "internalType": "address"
+ },
+ {
+ "name": "newLotterieAddress",
+ "type": "address",
+ "indexed": true,
+ "internalType": "address"
+ }
+ ],
+ "anonymous": false
+ },
+ {
+ "type": "event",
+ "name": "Mint",
+ "inputs": [
+ {
+ "name": "to",
+ "type": "address",
+ "indexed": true,
+ "internalType": "address"
+ },
+ {
+ "name": "amount",
+ "type": "uint256",
+ "indexed": false,
+ "internalType": "uint256"
+ }
+ ],
+ "anonymous": false
+ },
+ {
+ "type": "event",
+ "name": "UserAdded",
+ "inputs": [
+ {
+ "name": "user",
+ "type": "address",
+ "indexed": true,
+ "internalType": "address"
+ },
+ {
+ "name": "timestamp",
+ "type": "uint256",
+ "indexed": false,
+ "internalType": "uint256"
+ }
+ ],
+ "anonymous": false
+ },
+ {
+ "type": "event",
+ "name": "UserRemoved",
+ "inputs": [
+ {
+ "name": "user",
+ "type": "address",
+ "indexed": true,
+ "internalType": "address"
+ }
+ ],
+ "anonymous": false
+ },
+ { "type": "error", "name": "AmountMustBeGreaterThanZero", "inputs": [] },
+ { "type": "error", "name": "EthTransferFailed", "inputs": [] },
+ { "type": "error", "name": "InvalidGoldPrice", "inputs": [] },
+ { "type": "error", "name": "ValueMustBeGreaterThanZero", "inputs": [] }
+ ]
+}
diff --git a/frontend/abi/lotterie/iLotterieAbi.json b/frontend/abi/lotterie/iLotterieAbi.json
new file mode 100644
index 0000000..c8fdff0
--- /dev/null
+++ b/frontend/abi/lotterie/iLotterieAbi.json
@@ -0,0 +1,468 @@
+{
+ "abi": [
+ {
+ "type": "function",
+ "name": "addOwner",
+ "inputs": [
+ { "name": "account", "type": "address", "internalType": "address" }
+ ],
+ "outputs": [],
+ "stateMutability": "nonpayable"
+ },
+ {
+ "type": "function",
+ "name": "claim",
+ "inputs": [],
+ "outputs": [],
+ "stateMutability": "nonpayable"
+ },
+ {
+ "type": "function",
+ "name": "getCallbackGasLimit",
+ "inputs": [],
+ "outputs": [{ "name": "", "type": "uint32", "internalType": "uint32" }],
+ "stateMutability": "view"
+ },
+ {
+ "type": "function",
+ "name": "getGains",
+ "inputs": [
+ { "name": "account", "type": "address", "internalType": "address" }
+ ],
+ "outputs": [{ "name": "", "type": "uint256", "internalType": "uint256" }],
+ "stateMutability": "view"
+ },
+ {
+ "type": "function",
+ "name": "getGoldToken",
+ "inputs": [],
+ "outputs": [{ "name": "", "type": "address", "internalType": "address" }],
+ "stateMutability": "view"
+ },
+ {
+ "type": "function",
+ "name": "getKeyHash",
+ "inputs": [],
+ "outputs": [{ "name": "", "type": "bytes32", "internalType": "bytes32" }],
+ "stateMutability": "view"
+ },
+ {
+ "type": "function",
+ "name": "getLastRequestId",
+ "inputs": [],
+ "outputs": [{ "name": "", "type": "uint256", "internalType": "uint256" }],
+ "stateMutability": "view"
+ },
+ {
+ "type": "function",
+ "name": "getNumWords",
+ "inputs": [],
+ "outputs": [{ "name": "", "type": "uint32", "internalType": "uint32" }],
+ "stateMutability": "view"
+ },
+ {
+ "type": "function",
+ "name": "getRequestConfirmations",
+ "inputs": [],
+ "outputs": [{ "name": "", "type": "uint16", "internalType": "uint16" }],
+ "stateMutability": "view"
+ },
+ {
+ "type": "function",
+ "name": "getResults",
+ "inputs": [
+ { "name": "requestId", "type": "uint256", "internalType": "uint256" }
+ ],
+ "outputs": [{ "name": "", "type": "address", "internalType": "address" }],
+ "stateMutability": "view"
+ },
+ {
+ "type": "function",
+ "name": "getVrfCoordinator",
+ "inputs": [],
+ "outputs": [{ "name": "", "type": "address", "internalType": "address" }],
+ "stateMutability": "view"
+ },
+ {
+ "type": "function",
+ "name": "getVrfSubscriptionId",
+ "inputs": [],
+ "outputs": [{ "name": "", "type": "uint256", "internalType": "uint256" }],
+ "stateMutability": "view"
+ },
+ {
+ "type": "function",
+ "name": "hasOwnerRole",
+ "inputs": [
+ { "name": "account", "type": "address", "internalType": "address" }
+ ],
+ "outputs": [{ "name": "", "type": "bool", "internalType": "bool" }],
+ "stateMutability": "view"
+ },
+ {
+ "type": "function",
+ "name": "initialize",
+ "inputs": [
+ { "name": "owner", "type": "address", "internalType": "address" },
+ {
+ "name": "vrfSubscriptionId",
+ "type": "uint256",
+ "internalType": "uint256"
+ },
+ {
+ "name": "vrfCoordinator",
+ "type": "address",
+ "internalType": "address"
+ },
+ { "name": "keyHash", "type": "bytes32", "internalType": "bytes32" },
+ {
+ "name": "callbackGasLimit",
+ "type": "uint32",
+ "internalType": "uint32"
+ },
+ {
+ "name": "requestConfirmations",
+ "type": "uint16",
+ "internalType": "uint16"
+ },
+ { "name": "numWords", "type": "uint32", "internalType": "uint32" },
+ { "name": "goldToken", "type": "address", "internalType": "address" }
+ ],
+ "outputs": [],
+ "stateMutability": "nonpayable"
+ },
+ {
+ "type": "function",
+ "name": "randomDraw",
+ "inputs": [],
+ "outputs": [
+ { "name": "requestId", "type": "uint256", "internalType": "uint256" }
+ ],
+ "stateMutability": "nonpayable"
+ },
+ {
+ "type": "function",
+ "name": "removeOwner",
+ "inputs": [
+ { "name": "account", "type": "address", "internalType": "address" }
+ ],
+ "outputs": [],
+ "stateMutability": "nonpayable"
+ },
+ {
+ "type": "function",
+ "name": "setCallbackGasLimit",
+ "inputs": [
+ {
+ "name": "callbackGasLimit",
+ "type": "uint32",
+ "internalType": "uint32"
+ }
+ ],
+ "outputs": [],
+ "stateMutability": "nonpayable"
+ },
+ {
+ "type": "function",
+ "name": "setGoldToken",
+ "inputs": [
+ { "name": "goldToken", "type": "address", "internalType": "address" }
+ ],
+ "outputs": [],
+ "stateMutability": "nonpayable"
+ },
+ {
+ "type": "function",
+ "name": "setKeyHash",
+ "inputs": [
+ { "name": "keyHash", "type": "bytes32", "internalType": "bytes32" }
+ ],
+ "outputs": [],
+ "stateMutability": "nonpayable"
+ },
+ {
+ "type": "function",
+ "name": "setNumWords",
+ "inputs": [
+ { "name": "numWords", "type": "uint32", "internalType": "uint32" }
+ ],
+ "outputs": [],
+ "stateMutability": "nonpayable"
+ },
+ {
+ "type": "function",
+ "name": "setRequestConfirmations",
+ "inputs": [
+ {
+ "name": "requestConfirmations",
+ "type": "uint16",
+ "internalType": "uint16"
+ }
+ ],
+ "outputs": [],
+ "stateMutability": "nonpayable"
+ },
+ {
+ "type": "function",
+ "name": "setVrfCoordinator",
+ "inputs": [
+ {
+ "name": "vrfCoordinator",
+ "type": "address",
+ "internalType": "address"
+ }
+ ],
+ "outputs": [],
+ "stateMutability": "nonpayable"
+ },
+ {
+ "type": "function",
+ "name": "setVrfSubscriptionId",
+ "inputs": [
+ {
+ "name": "vrfSubscriptionId",
+ "type": "uint256",
+ "internalType": "uint256"
+ }
+ ],
+ "outputs": [],
+ "stateMutability": "nonpayable"
+ },
+ {
+ "type": "event",
+ "name": "CallbackGasLimitUpdated",
+ "inputs": [
+ {
+ "name": "previousGasLimit",
+ "type": "uint32",
+ "indexed": true,
+ "internalType": "uint32"
+ },
+ {
+ "name": "newGasLimit",
+ "type": "uint32",
+ "indexed": true,
+ "internalType": "uint32"
+ }
+ ],
+ "anonymous": false
+ },
+ {
+ "type": "event",
+ "name": "GainClaimed",
+ "inputs": [
+ {
+ "name": "account",
+ "type": "address",
+ "indexed": true,
+ "internalType": "address"
+ },
+ {
+ "name": "amount",
+ "type": "uint256",
+ "indexed": false,
+ "internalType": "uint256"
+ }
+ ],
+ "anonymous": false
+ },
+ {
+ "type": "event",
+ "name": "GoldTokenUpdated",
+ "inputs": [
+ {
+ "name": "previousGoldToken",
+ "type": "address",
+ "indexed": true,
+ "internalType": "address"
+ },
+ {
+ "name": "newGoldToken",
+ "type": "address",
+ "indexed": true,
+ "internalType": "address"
+ }
+ ],
+ "anonymous": false
+ },
+ {
+ "type": "event",
+ "name": "KeyHashUpdated",
+ "inputs": [
+ {
+ "name": "previousKeyHash",
+ "type": "bytes32",
+ "indexed": true,
+ "internalType": "bytes32"
+ },
+ {
+ "name": "newKeyHash",
+ "type": "bytes32",
+ "indexed": true,
+ "internalType": "bytes32"
+ }
+ ],
+ "anonymous": false
+ },
+ {
+ "type": "event",
+ "name": "LotterieInitialized",
+ "inputs": [
+ {
+ "name": "owner",
+ "type": "address",
+ "indexed": true,
+ "internalType": "address"
+ },
+ {
+ "name": "vrfCoordinator",
+ "type": "address",
+ "indexed": true,
+ "internalType": "address"
+ },
+ {
+ "name": "goldToken",
+ "type": "address",
+ "indexed": true,
+ "internalType": "address"
+ },
+ {
+ "name": "vrfSubscriptionId",
+ "type": "uint256",
+ "indexed": false,
+ "internalType": "uint256"
+ },
+ {
+ "name": "keyHash",
+ "type": "bytes32",
+ "indexed": false,
+ "internalType": "bytes32"
+ },
+ {
+ "name": "callbackGasLimit",
+ "type": "uint32",
+ "indexed": false,
+ "internalType": "uint32"
+ },
+ {
+ "name": "requestConfirmations",
+ "type": "uint16",
+ "indexed": false,
+ "internalType": "uint16"
+ },
+ {
+ "name": "numWords",
+ "type": "uint32",
+ "indexed": false,
+ "internalType": "uint32"
+ }
+ ],
+ "anonymous": false
+ },
+ {
+ "type": "event",
+ "name": "NumWordsUpdated",
+ "inputs": [
+ {
+ "name": "previousNumWords",
+ "type": "uint32",
+ "indexed": true,
+ "internalType": "uint32"
+ },
+ {
+ "name": "newNumWords",
+ "type": "uint32",
+ "indexed": true,
+ "internalType": "uint32"
+ }
+ ],
+ "anonymous": false
+ },
+ {
+ "type": "event",
+ "name": "RandomDrawed",
+ "inputs": [
+ {
+ "name": "requestId",
+ "type": "uint256",
+ "indexed": true,
+ "internalType": "uint256"
+ }
+ ],
+ "anonymous": false
+ },
+ {
+ "type": "event",
+ "name": "RequestConfirmationsUpdated",
+ "inputs": [
+ {
+ "name": "previousConfirmations",
+ "type": "uint16",
+ "indexed": true,
+ "internalType": "uint16"
+ },
+ {
+ "name": "newConfirmations",
+ "type": "uint16",
+ "indexed": true,
+ "internalType": "uint16"
+ }
+ ],
+ "anonymous": false
+ },
+ {
+ "type": "event",
+ "name": "VrfCoordinatorUpdated",
+ "inputs": [
+ {
+ "name": "previousCoordinator",
+ "type": "address",
+ "indexed": true,
+ "internalType": "address"
+ },
+ {
+ "name": "newCoordinator",
+ "type": "address",
+ "indexed": true,
+ "internalType": "address"
+ }
+ ],
+ "anonymous": false
+ },
+ {
+ "type": "event",
+ "name": "VrfSubscriptionUpdated",
+ "inputs": [
+ {
+ "name": "previousSubscriptionId",
+ "type": "uint256",
+ "indexed": true,
+ "internalType": "uint256"
+ },
+ {
+ "name": "newSubscriptionId",
+ "type": "uint256",
+ "indexed": true,
+ "internalType": "uint256"
+ }
+ ],
+ "anonymous": false
+ },
+ {
+ "type": "event",
+ "name": "Winner",
+ "inputs": [
+ {
+ "name": "winner",
+ "type": "address",
+ "indexed": true,
+ "internalType": "address"
+ }
+ ],
+ "anonymous": false
+ },
+ { "type": "error", "name": "NoGainToClaim", "inputs": [] },
+ { "type": "error", "name": "OneRandomDrawPerDay", "inputs": [] },
+ { "type": "error", "name": "TransferFailed", "inputs": [] }
+ ]
+}
diff --git a/frontend/abi/lotterie/lotterieAbi.json b/frontend/abi/lotterie/lotterieAbi.json
new file mode 100644
index 0000000..ec24e37
--- /dev/null
+++ b/frontend/abi/lotterie/lotterieAbi.json
@@ -0,0 +1,854 @@
+{
+ "abi": [
+ {
+ "type": "constructor",
+ "inputs": [
+ {
+ "name": "vrfCoordinator",
+ "type": "address",
+ "internalType": "address"
+ }
+ ],
+ "stateMutability": "nonpayable"
+ },
+ {
+ "type": "function",
+ "name": "DEFAULT_ADMIN_ROLE",
+ "inputs": [],
+ "outputs": [{ "name": "", "type": "bytes32", "internalType": "bytes32" }],
+ "stateMutability": "view"
+ },
+ {
+ "type": "function",
+ "name": "OWNER_ROLE",
+ "inputs": [],
+ "outputs": [{ "name": "", "type": "bytes32", "internalType": "bytes32" }],
+ "stateMutability": "view"
+ },
+ {
+ "type": "function",
+ "name": "UPGRADE_INTERFACE_VERSION",
+ "inputs": [],
+ "outputs": [{ "name": "", "type": "string", "internalType": "string" }],
+ "stateMutability": "view"
+ },
+ {
+ "type": "function",
+ "name": "acceptOwnership",
+ "inputs": [],
+ "outputs": [],
+ "stateMutability": "nonpayable"
+ },
+ {
+ "type": "function",
+ "name": "addOwner",
+ "inputs": [
+ { "name": "account", "type": "address", "internalType": "address" }
+ ],
+ "outputs": [],
+ "stateMutability": "nonpayable"
+ },
+ {
+ "type": "function",
+ "name": "claim",
+ "inputs": [],
+ "outputs": [],
+ "stateMutability": "nonpayable"
+ },
+ {
+ "type": "function",
+ "name": "getCallbackGasLimit",
+ "inputs": [],
+ "outputs": [{ "name": "", "type": "uint32", "internalType": "uint32" }],
+ "stateMutability": "view"
+ },
+ {
+ "type": "function",
+ "name": "getGains",
+ "inputs": [
+ { "name": "account", "type": "address", "internalType": "address" }
+ ],
+ "outputs": [{ "name": "", "type": "uint256", "internalType": "uint256" }],
+ "stateMutability": "view"
+ },
+ {
+ "type": "function",
+ "name": "getGoldToken",
+ "inputs": [],
+ "outputs": [{ "name": "", "type": "address", "internalType": "address" }],
+ "stateMutability": "view"
+ },
+ {
+ "type": "function",
+ "name": "getKeyHash",
+ "inputs": [],
+ "outputs": [{ "name": "", "type": "bytes32", "internalType": "bytes32" }],
+ "stateMutability": "view"
+ },
+ {
+ "type": "function",
+ "name": "getLastRequestId",
+ "inputs": [],
+ "outputs": [{ "name": "", "type": "uint256", "internalType": "uint256" }],
+ "stateMutability": "view"
+ },
+ {
+ "type": "function",
+ "name": "getNumWords",
+ "inputs": [],
+ "outputs": [{ "name": "", "type": "uint32", "internalType": "uint32" }],
+ "stateMutability": "view"
+ },
+ {
+ "type": "function",
+ "name": "getRequestConfirmations",
+ "inputs": [],
+ "outputs": [{ "name": "", "type": "uint16", "internalType": "uint16" }],
+ "stateMutability": "view"
+ },
+ {
+ "type": "function",
+ "name": "getResults",
+ "inputs": [
+ { "name": "requestId", "type": "uint256", "internalType": "uint256" }
+ ],
+ "outputs": [{ "name": "", "type": "address", "internalType": "address" }],
+ "stateMutability": "view"
+ },
+ {
+ "type": "function",
+ "name": "getRoleAdmin",
+ "inputs": [
+ { "name": "role", "type": "bytes32", "internalType": "bytes32" }
+ ],
+ "outputs": [{ "name": "", "type": "bytes32", "internalType": "bytes32" }],
+ "stateMutability": "view"
+ },
+ {
+ "type": "function",
+ "name": "getVrfCoordinator",
+ "inputs": [],
+ "outputs": [{ "name": "", "type": "address", "internalType": "address" }],
+ "stateMutability": "view"
+ },
+ {
+ "type": "function",
+ "name": "getVrfSubscriptionId",
+ "inputs": [],
+ "outputs": [{ "name": "", "type": "uint256", "internalType": "uint256" }],
+ "stateMutability": "view"
+ },
+ {
+ "type": "function",
+ "name": "grantRole",
+ "inputs": [
+ { "name": "role", "type": "bytes32", "internalType": "bytes32" },
+ { "name": "account", "type": "address", "internalType": "address" }
+ ],
+ "outputs": [],
+ "stateMutability": "nonpayable"
+ },
+ {
+ "type": "function",
+ "name": "hasOwnerRole",
+ "inputs": [
+ { "name": "account", "type": "address", "internalType": "address" }
+ ],
+ "outputs": [{ "name": "", "type": "bool", "internalType": "bool" }],
+ "stateMutability": "view"
+ },
+ {
+ "type": "function",
+ "name": "hasRole",
+ "inputs": [
+ { "name": "role", "type": "bytes32", "internalType": "bytes32" },
+ { "name": "account", "type": "address", "internalType": "address" }
+ ],
+ "outputs": [{ "name": "", "type": "bool", "internalType": "bool" }],
+ "stateMutability": "view"
+ },
+ {
+ "type": "function",
+ "name": "initialize",
+ "inputs": [
+ { "name": "owner", "type": "address", "internalType": "address" },
+ {
+ "name": "vrfSubscriptionId",
+ "type": "uint256",
+ "internalType": "uint256"
+ },
+ {
+ "name": "vrfCoordinator",
+ "type": "address",
+ "internalType": "address"
+ },
+ { "name": "keyHash", "type": "bytes32", "internalType": "bytes32" },
+ {
+ "name": "callbackGasLimit",
+ "type": "uint32",
+ "internalType": "uint32"
+ },
+ {
+ "name": "requestConfirmations",
+ "type": "uint16",
+ "internalType": "uint16"
+ },
+ { "name": "numWords", "type": "uint32", "internalType": "uint32" },
+ { "name": "goldToken", "type": "address", "internalType": "address" }
+ ],
+ "outputs": [],
+ "stateMutability": "nonpayable"
+ },
+ {
+ "type": "function",
+ "name": "owner",
+ "inputs": [],
+ "outputs": [{ "name": "", "type": "address", "internalType": "address" }],
+ "stateMutability": "view"
+ },
+ {
+ "type": "function",
+ "name": "proxiableUUID",
+ "inputs": [],
+ "outputs": [{ "name": "", "type": "bytes32", "internalType": "bytes32" }],
+ "stateMutability": "view"
+ },
+ {
+ "type": "function",
+ "name": "randomDraw",
+ "inputs": [],
+ "outputs": [{ "name": "", "type": "uint256", "internalType": "uint256" }],
+ "stateMutability": "nonpayable"
+ },
+ {
+ "type": "function",
+ "name": "rawFulfillRandomWords",
+ "inputs": [
+ { "name": "requestId", "type": "uint256", "internalType": "uint256" },
+ {
+ "name": "randomWords",
+ "type": "uint256[]",
+ "internalType": "uint256[]"
+ }
+ ],
+ "outputs": [],
+ "stateMutability": "nonpayable"
+ },
+ {
+ "type": "function",
+ "name": "removeOwner",
+ "inputs": [
+ { "name": "account", "type": "address", "internalType": "address" }
+ ],
+ "outputs": [],
+ "stateMutability": "nonpayable"
+ },
+ {
+ "type": "function",
+ "name": "renounceRole",
+ "inputs": [
+ { "name": "role", "type": "bytes32", "internalType": "bytes32" },
+ {
+ "name": "callerConfirmation",
+ "type": "address",
+ "internalType": "address"
+ }
+ ],
+ "outputs": [],
+ "stateMutability": "nonpayable"
+ },
+ {
+ "type": "function",
+ "name": "revokeRole",
+ "inputs": [
+ { "name": "role", "type": "bytes32", "internalType": "bytes32" },
+ { "name": "account", "type": "address", "internalType": "address" }
+ ],
+ "outputs": [],
+ "stateMutability": "nonpayable"
+ },
+ {
+ "type": "function",
+ "name": "s_vrfCoordinator",
+ "inputs": [],
+ "outputs": [
+ {
+ "name": "",
+ "type": "address",
+ "internalType": "contract IVRFCoordinatorV2Plus"
+ }
+ ],
+ "stateMutability": "view"
+ },
+ {
+ "type": "function",
+ "name": "setCallbackGasLimit",
+ "inputs": [
+ {
+ "name": "callbackGasLimit",
+ "type": "uint32",
+ "internalType": "uint32"
+ }
+ ],
+ "outputs": [],
+ "stateMutability": "nonpayable"
+ },
+ {
+ "type": "function",
+ "name": "setCoordinator",
+ "inputs": [
+ {
+ "name": "_vrfCoordinator",
+ "type": "address",
+ "internalType": "address"
+ }
+ ],
+ "outputs": [],
+ "stateMutability": "nonpayable"
+ },
+ {
+ "type": "function",
+ "name": "setGoldToken",
+ "inputs": [
+ { "name": "goldToken", "type": "address", "internalType": "address" }
+ ],
+ "outputs": [],
+ "stateMutability": "nonpayable"
+ },
+ {
+ "type": "function",
+ "name": "setKeyHash",
+ "inputs": [
+ { "name": "keyHash", "type": "bytes32", "internalType": "bytes32" }
+ ],
+ "outputs": [],
+ "stateMutability": "nonpayable"
+ },
+ {
+ "type": "function",
+ "name": "setNumWords",
+ "inputs": [
+ { "name": "numWords", "type": "uint32", "internalType": "uint32" }
+ ],
+ "outputs": [],
+ "stateMutability": "nonpayable"
+ },
+ {
+ "type": "function",
+ "name": "setRequestConfirmations",
+ "inputs": [
+ {
+ "name": "requestConfirmations",
+ "type": "uint16",
+ "internalType": "uint16"
+ }
+ ],
+ "outputs": [],
+ "stateMutability": "nonpayable"
+ },
+ {
+ "type": "function",
+ "name": "setVrfCoordinator",
+ "inputs": [
+ {
+ "name": "vrfCoordinator",
+ "type": "address",
+ "internalType": "address"
+ }
+ ],
+ "outputs": [],
+ "stateMutability": "nonpayable"
+ },
+ {
+ "type": "function",
+ "name": "setVrfSubscriptionId",
+ "inputs": [
+ {
+ "name": "vrfSubscriptionId",
+ "type": "uint256",
+ "internalType": "uint256"
+ }
+ ],
+ "outputs": [],
+ "stateMutability": "nonpayable"
+ },
+ {
+ "type": "function",
+ "name": "supportsInterface",
+ "inputs": [
+ { "name": "interfaceId", "type": "bytes4", "internalType": "bytes4" }
+ ],
+ "outputs": [{ "name": "", "type": "bool", "internalType": "bool" }],
+ "stateMutability": "view"
+ },
+ {
+ "type": "function",
+ "name": "transferOwnership",
+ "inputs": [
+ { "name": "to", "type": "address", "internalType": "address" }
+ ],
+ "outputs": [],
+ "stateMutability": "nonpayable"
+ },
+ {
+ "type": "function",
+ "name": "upgradeToAndCall",
+ "inputs": [
+ {
+ "name": "newImplementation",
+ "type": "address",
+ "internalType": "address"
+ },
+ { "name": "data", "type": "bytes", "internalType": "bytes" }
+ ],
+ "outputs": [],
+ "stateMutability": "payable"
+ },
+ {
+ "type": "event",
+ "name": "CallbackGasLimitUpdated",
+ "inputs": [
+ {
+ "name": "previousGasLimit",
+ "type": "uint32",
+ "indexed": true,
+ "internalType": "uint32"
+ },
+ {
+ "name": "newGasLimit",
+ "type": "uint32",
+ "indexed": true,
+ "internalType": "uint32"
+ }
+ ],
+ "anonymous": false
+ },
+ {
+ "type": "event",
+ "name": "CoordinatorSet",
+ "inputs": [
+ {
+ "name": "vrfCoordinator",
+ "type": "address",
+ "indexed": false,
+ "internalType": "address"
+ }
+ ],
+ "anonymous": false
+ },
+ {
+ "type": "event",
+ "name": "GainClaimed",
+ "inputs": [
+ {
+ "name": "account",
+ "type": "address",
+ "indexed": true,
+ "internalType": "address"
+ },
+ {
+ "name": "amount",
+ "type": "uint256",
+ "indexed": false,
+ "internalType": "uint256"
+ }
+ ],
+ "anonymous": false
+ },
+ {
+ "type": "event",
+ "name": "GoldTokenUpdated",
+ "inputs": [
+ {
+ "name": "previousGoldToken",
+ "type": "address",
+ "indexed": true,
+ "internalType": "address"
+ },
+ {
+ "name": "newGoldToken",
+ "type": "address",
+ "indexed": true,
+ "internalType": "address"
+ }
+ ],
+ "anonymous": false
+ },
+ {
+ "type": "event",
+ "name": "Initialized",
+ "inputs": [
+ {
+ "name": "version",
+ "type": "uint64",
+ "indexed": false,
+ "internalType": "uint64"
+ }
+ ],
+ "anonymous": false
+ },
+ {
+ "type": "event",
+ "name": "KeyHashUpdated",
+ "inputs": [
+ {
+ "name": "previousKeyHash",
+ "type": "bytes32",
+ "indexed": true,
+ "internalType": "bytes32"
+ },
+ {
+ "name": "newKeyHash",
+ "type": "bytes32",
+ "indexed": true,
+ "internalType": "bytes32"
+ }
+ ],
+ "anonymous": false
+ },
+ {
+ "type": "event",
+ "name": "LotterieInitialized",
+ "inputs": [
+ {
+ "name": "owner",
+ "type": "address",
+ "indexed": true,
+ "internalType": "address"
+ },
+ {
+ "name": "vrfCoordinator",
+ "type": "address",
+ "indexed": true,
+ "internalType": "address"
+ },
+ {
+ "name": "goldToken",
+ "type": "address",
+ "indexed": true,
+ "internalType": "address"
+ },
+ {
+ "name": "vrfSubscriptionId",
+ "type": "uint256",
+ "indexed": false,
+ "internalType": "uint256"
+ },
+ {
+ "name": "keyHash",
+ "type": "bytes32",
+ "indexed": false,
+ "internalType": "bytes32"
+ },
+ {
+ "name": "callbackGasLimit",
+ "type": "uint32",
+ "indexed": false,
+ "internalType": "uint32"
+ },
+ {
+ "name": "requestConfirmations",
+ "type": "uint16",
+ "indexed": false,
+ "internalType": "uint16"
+ },
+ {
+ "name": "numWords",
+ "type": "uint32",
+ "indexed": false,
+ "internalType": "uint32"
+ }
+ ],
+ "anonymous": false
+ },
+ {
+ "type": "event",
+ "name": "NumWordsUpdated",
+ "inputs": [
+ {
+ "name": "previousNumWords",
+ "type": "uint32",
+ "indexed": true,
+ "internalType": "uint32"
+ },
+ {
+ "name": "newNumWords",
+ "type": "uint32",
+ "indexed": true,
+ "internalType": "uint32"
+ }
+ ],
+ "anonymous": false
+ },
+ {
+ "type": "event",
+ "name": "OwnershipTransferRequested",
+ "inputs": [
+ {
+ "name": "from",
+ "type": "address",
+ "indexed": true,
+ "internalType": "address"
+ },
+ {
+ "name": "to",
+ "type": "address",
+ "indexed": true,
+ "internalType": "address"
+ }
+ ],
+ "anonymous": false
+ },
+ {
+ "type": "event",
+ "name": "OwnershipTransferred",
+ "inputs": [
+ {
+ "name": "from",
+ "type": "address",
+ "indexed": true,
+ "internalType": "address"
+ },
+ {
+ "name": "to",
+ "type": "address",
+ "indexed": true,
+ "internalType": "address"
+ }
+ ],
+ "anonymous": false
+ },
+ {
+ "type": "event",
+ "name": "RandomDrawed",
+ "inputs": [
+ {
+ "name": "requestId",
+ "type": "uint256",
+ "indexed": true,
+ "internalType": "uint256"
+ }
+ ],
+ "anonymous": false
+ },
+ {
+ "type": "event",
+ "name": "RequestConfirmationsUpdated",
+ "inputs": [
+ {
+ "name": "previousConfirmations",
+ "type": "uint16",
+ "indexed": true,
+ "internalType": "uint16"
+ },
+ {
+ "name": "newConfirmations",
+ "type": "uint16",
+ "indexed": true,
+ "internalType": "uint16"
+ }
+ ],
+ "anonymous": false
+ },
+ {
+ "type": "event",
+ "name": "RoleAdminChanged",
+ "inputs": [
+ {
+ "name": "role",
+ "type": "bytes32",
+ "indexed": true,
+ "internalType": "bytes32"
+ },
+ {
+ "name": "previousAdminRole",
+ "type": "bytes32",
+ "indexed": true,
+ "internalType": "bytes32"
+ },
+ {
+ "name": "newAdminRole",
+ "type": "bytes32",
+ "indexed": true,
+ "internalType": "bytes32"
+ }
+ ],
+ "anonymous": false
+ },
+ {
+ "type": "event",
+ "name": "RoleGranted",
+ "inputs": [
+ {
+ "name": "role",
+ "type": "bytes32",
+ "indexed": true,
+ "internalType": "bytes32"
+ },
+ {
+ "name": "account",
+ "type": "address",
+ "indexed": true,
+ "internalType": "address"
+ },
+ {
+ "name": "sender",
+ "type": "address",
+ "indexed": true,
+ "internalType": "address"
+ }
+ ],
+ "anonymous": false
+ },
+ {
+ "type": "event",
+ "name": "RoleRevoked",
+ "inputs": [
+ {
+ "name": "role",
+ "type": "bytes32",
+ "indexed": true,
+ "internalType": "bytes32"
+ },
+ {
+ "name": "account",
+ "type": "address",
+ "indexed": true,
+ "internalType": "address"
+ },
+ {
+ "name": "sender",
+ "type": "address",
+ "indexed": true,
+ "internalType": "address"
+ }
+ ],
+ "anonymous": false
+ },
+ {
+ "type": "event",
+ "name": "Upgraded",
+ "inputs": [
+ {
+ "name": "implementation",
+ "type": "address",
+ "indexed": true,
+ "internalType": "address"
+ }
+ ],
+ "anonymous": false
+ },
+ {
+ "type": "event",
+ "name": "VrfCoordinatorUpdated",
+ "inputs": [
+ {
+ "name": "previousCoordinator",
+ "type": "address",
+ "indexed": true,
+ "internalType": "address"
+ },
+ {
+ "name": "newCoordinator",
+ "type": "address",
+ "indexed": true,
+ "internalType": "address"
+ }
+ ],
+ "anonymous": false
+ },
+ {
+ "type": "event",
+ "name": "VrfSubscriptionUpdated",
+ "inputs": [
+ {
+ "name": "previousSubscriptionId",
+ "type": "uint256",
+ "indexed": true,
+ "internalType": "uint256"
+ },
+ {
+ "name": "newSubscriptionId",
+ "type": "uint256",
+ "indexed": true,
+ "internalType": "uint256"
+ }
+ ],
+ "anonymous": false
+ },
+ {
+ "type": "event",
+ "name": "Winner",
+ "inputs": [
+ {
+ "name": "winner",
+ "type": "address",
+ "indexed": true,
+ "internalType": "address"
+ }
+ ],
+ "anonymous": false
+ },
+ { "type": "error", "name": "AccessControlBadConfirmation", "inputs": [] },
+ {
+ "type": "error",
+ "name": "AccessControlUnauthorizedAccount",
+ "inputs": [
+ { "name": "account", "type": "address", "internalType": "address" },
+ { "name": "neededRole", "type": "bytes32", "internalType": "bytes32" }
+ ]
+ },
+ {
+ "type": "error",
+ "name": "AddressEmptyCode",
+ "inputs": [
+ { "name": "target", "type": "address", "internalType": "address" }
+ ]
+ },
+ {
+ "type": "error",
+ "name": "ERC1967InvalidImplementation",
+ "inputs": [
+ {
+ "name": "implementation",
+ "type": "address",
+ "internalType": "address"
+ }
+ ]
+ },
+ { "type": "error", "name": "ERC1967NonPayable", "inputs": [] },
+ { "type": "error", "name": "FailedCall", "inputs": [] },
+ { "type": "error", "name": "InvalidInitialization", "inputs": [] },
+ { "type": "error", "name": "NoGainToClaim", "inputs": [] },
+ { "type": "error", "name": "NotInitializing", "inputs": [] },
+ { "type": "error", "name": "OneRandomDrawPerDay", "inputs": [] },
+ {
+ "type": "error",
+ "name": "OnlyCoordinatorCanFulfill",
+ "inputs": [
+ { "name": "have", "type": "address", "internalType": "address" },
+ { "name": "want", "type": "address", "internalType": "address" }
+ ]
+ },
+ {
+ "type": "error",
+ "name": "OnlyOwnerOrCoordinator",
+ "inputs": [
+ { "name": "have", "type": "address", "internalType": "address" },
+ { "name": "owner", "type": "address", "internalType": "address" },
+ { "name": "coordinator", "type": "address", "internalType": "address" }
+ ]
+ },
+ { "type": "error", "name": "ReentrancyGuardReentrantCall", "inputs": [] },
+ { "type": "error", "name": "TransferFailed", "inputs": [] },
+ { "type": "error", "name": "UUPSUnauthorizedCallContext", "inputs": [] },
+ {
+ "type": "error",
+ "name": "UUPSUnsupportedProxiableUUID",
+ "inputs": [
+ { "name": "slot", "type": "bytes32", "internalType": "bytes32" }
+ ]
+ },
+ { "type": "error", "name": "ZeroAddress", "inputs": [] }
+ ]
+}
\ No newline at end of file
diff --git a/frontend/abi/tokenBridge/iTokenBridgeAbi.json b/frontend/abi/tokenBridge/iTokenBridgeAbi.json
new file mode 100644
index 0000000..a04eece
--- /dev/null
+++ b/frontend/abi/tokenBridge/iTokenBridgeAbi.json
@@ -0,0 +1,399 @@
+{
+ "abi": [
+ {
+ "type": "function",
+ "name": "bridgeTokens",
+ "inputs": [
+ { "name": "receiver", "type": "address", "internalType": "address" },
+ { "name": "amount", "type": "uint256", "internalType": "uint256" },
+ {
+ "name": "payFeesIn",
+ "type": "uint8",
+ "internalType": "enum ITokenBridge.PayFeesIn"
+ }
+ ],
+ "outputs": [
+ { "name": "messageId", "type": "bytes32", "internalType": "bytes32" }
+ ],
+ "stateMutability": "payable"
+ },
+ {
+ "type": "function",
+ "name": "destinationChainSelector",
+ "inputs": [],
+ "outputs": [{ "name": "", "type": "uint64", "internalType": "uint64" }],
+ "stateMutability": "view"
+ },
+ {
+ "type": "function",
+ "name": "getGoldTokenBalance",
+ "inputs": [],
+ "outputs": [{ "name": "", "type": "uint256", "internalType": "uint256" }],
+ "stateMutability": "view"
+ },
+ {
+ "type": "function",
+ "name": "getLinkBalance",
+ "inputs": [],
+ "outputs": [{ "name": "", "type": "uint256", "internalType": "uint256" }],
+ "stateMutability": "view"
+ },
+ {
+ "type": "function",
+ "name": "goldToken",
+ "inputs": [],
+ "outputs": [{ "name": "", "type": "address", "internalType": "address" }],
+ "stateMutability": "view"
+ },
+ {
+ "type": "function",
+ "name": "initialize",
+ "inputs": [
+ { "name": "owner", "type": "address", "internalType": "address" },
+ { "name": "_link", "type": "address", "internalType": "address" },
+ { "name": "_goldToken", "type": "address", "internalType": "address" },
+ {
+ "name": "_destinationChainSelector",
+ "type": "uint64",
+ "internalType": "uint64"
+ }
+ ],
+ "outputs": [],
+ "stateMutability": "nonpayable"
+ },
+ {
+ "type": "function",
+ "name": "link",
+ "inputs": [],
+ "outputs": [{ "name": "", "type": "address", "internalType": "address" }],
+ "stateMutability": "view"
+ },
+ {
+ "type": "function",
+ "name": "processedMessages",
+ "inputs": [
+ { "name": "messageId", "type": "bytes32", "internalType": "bytes32" }
+ ],
+ "outputs": [{ "name": "", "type": "bool", "internalType": "bool" }],
+ "stateMutability": "view"
+ },
+ {
+ "type": "function",
+ "name": "setWhitelistedChain",
+ "inputs": [
+ { "name": "chainSelector", "type": "uint64", "internalType": "uint64" },
+ { "name": "enabled", "type": "bool", "internalType": "bool" },
+ { "name": "ccipExtraArgs", "type": "bytes", "internalType": "bytes" }
+ ],
+ "outputs": [],
+ "stateMutability": "nonpayable"
+ },
+ {
+ "type": "function",
+ "name": "setWhitelistedSender",
+ "inputs": [
+ { "name": "sender", "type": "address", "internalType": "address" },
+ { "name": "enabled", "type": "bool", "internalType": "bool" }
+ ],
+ "outputs": [],
+ "stateMutability": "nonpayable"
+ },
+ {
+ "type": "function",
+ "name": "whitelistedChains",
+ "inputs": [
+ { "name": "chainSelector", "type": "uint64", "internalType": "uint64" }
+ ],
+ "outputs": [{ "name": "", "type": "bool", "internalType": "bool" }],
+ "stateMutability": "view"
+ },
+ {
+ "type": "function",
+ "name": "whitelistedSenders",
+ "inputs": [
+ { "name": "sender", "type": "address", "internalType": "address" }
+ ],
+ "outputs": [{ "name": "", "type": "bool", "internalType": "bool" }],
+ "stateMutability": "view"
+ },
+ {
+ "type": "function",
+ "name": "withdraw",
+ "inputs": [
+ { "name": "beneficiary", "type": "address", "internalType": "address" }
+ ],
+ "outputs": [],
+ "stateMutability": "nonpayable"
+ },
+ {
+ "type": "function",
+ "name": "withdrawToken",
+ "inputs": [
+ { "name": "beneficiary", "type": "address", "internalType": "address" },
+ { "name": "token", "type": "address", "internalType": "address" }
+ ],
+ "outputs": [],
+ "stateMutability": "nonpayable"
+ },
+ {
+ "type": "event",
+ "name": "ChainRemoved",
+ "inputs": [
+ {
+ "name": "chainSelector",
+ "type": "uint64",
+ "indexed": true,
+ "internalType": "uint64"
+ }
+ ],
+ "anonymous": false
+ },
+ {
+ "type": "event",
+ "name": "ChainWhitelisted",
+ "inputs": [
+ {
+ "name": "chainSelector",
+ "type": "uint64",
+ "indexed": true,
+ "internalType": "uint64"
+ }
+ ],
+ "anonymous": false
+ },
+ {
+ "type": "event",
+ "name": "MessageProcessedWithoutToken",
+ "inputs": [
+ {
+ "name": "messageId",
+ "type": "bytes32",
+ "indexed": true,
+ "internalType": "bytes32"
+ },
+ {
+ "name": "sourceChainSelector",
+ "type": "uint64",
+ "indexed": true,
+ "internalType": "uint64"
+ }
+ ],
+ "anonymous": false
+ },
+ {
+ "type": "event",
+ "name": "SenderRemoved",
+ "inputs": [
+ {
+ "name": "sender",
+ "type": "address",
+ "indexed": true,
+ "internalType": "address"
+ }
+ ],
+ "anonymous": false
+ },
+ {
+ "type": "event",
+ "name": "SenderWhitelisted",
+ "inputs": [
+ {
+ "name": "sender",
+ "type": "address",
+ "indexed": true,
+ "internalType": "address"
+ }
+ ],
+ "anonymous": false
+ },
+ {
+ "type": "event",
+ "name": "TokenBridgeInitialized",
+ "inputs": [
+ {
+ "name": "owner",
+ "type": "address",
+ "indexed": true,
+ "internalType": "address"
+ },
+ {
+ "name": "link",
+ "type": "address",
+ "indexed": true,
+ "internalType": "address"
+ },
+ {
+ "name": "goldToken",
+ "type": "address",
+ "indexed": true,
+ "internalType": "address"
+ },
+ {
+ "name": "destinationChainSelector",
+ "type": "uint64",
+ "indexed": false,
+ "internalType": "uint64"
+ }
+ ],
+ "anonymous": false
+ },
+ {
+ "type": "event",
+ "name": "TokensBridged",
+ "inputs": [
+ {
+ "name": "messageId",
+ "type": "bytes32",
+ "indexed": true,
+ "internalType": "bytes32"
+ },
+ {
+ "name": "sender",
+ "type": "address",
+ "indexed": true,
+ "internalType": "address"
+ },
+ {
+ "name": "receiver",
+ "type": "address",
+ "indexed": true,
+ "internalType": "address"
+ },
+ {
+ "name": "amount",
+ "type": "uint256",
+ "indexed": false,
+ "internalType": "uint256"
+ },
+ {
+ "name": "destinationChainSelector",
+ "type": "uint64",
+ "indexed": false,
+ "internalType": "uint64"
+ },
+ {
+ "name": "feeToken",
+ "type": "address",
+ "indexed": false,
+ "internalType": "address"
+ },
+ {
+ "name": "fees",
+ "type": "uint256",
+ "indexed": false,
+ "internalType": "uint256"
+ }
+ ],
+ "anonymous": false
+ },
+ {
+ "type": "event",
+ "name": "TokensReceived",
+ "inputs": [
+ {
+ "name": "messageId",
+ "type": "bytes32",
+ "indexed": true,
+ "internalType": "bytes32"
+ },
+ {
+ "name": "receiver",
+ "type": "address",
+ "indexed": true,
+ "internalType": "address"
+ },
+ {
+ "name": "amount",
+ "type": "uint256",
+ "indexed": false,
+ "internalType": "uint256"
+ },
+ {
+ "name": "sourceChainSelector",
+ "type": "uint64",
+ "indexed": true,
+ "internalType": "uint64"
+ }
+ ],
+ "anonymous": false
+ },
+ {
+ "type": "error",
+ "name": "ChainNotWhitelisted",
+ "inputs": [
+ { "name": "chainSelector", "type": "uint64", "internalType": "uint64" }
+ ]
+ },
+ {
+ "type": "error",
+ "name": "FailedToWithdrawEth",
+ "inputs": [
+ { "name": "owner", "type": "address", "internalType": "address" },
+ { "name": "target", "type": "address", "internalType": "address" },
+ { "name": "value", "type": "uint256", "internalType": "uint256" }
+ ]
+ },
+ {
+ "type": "error",
+ "name": "InvalidAmount",
+ "inputs": [
+ { "name": "amount", "type": "uint256", "internalType": "uint256" }
+ ]
+ },
+ {
+ "type": "error",
+ "name": "InvalidChainSelector",
+ "inputs": [
+ { "name": "chainSelector", "type": "uint64", "internalType": "uint64" }
+ ]
+ },
+ {
+ "type": "error",
+ "name": "InvalidSender",
+ "inputs": [
+ { "name": "sender", "type": "address", "internalType": "address" }
+ ]
+ },
+ {
+ "type": "error",
+ "name": "InvalidSourceChain",
+ "inputs": [
+ {
+ "name": "sourceChainSelector",
+ "type": "uint64",
+ "internalType": "uint64"
+ }
+ ]
+ },
+ {
+ "type": "error",
+ "name": "MessageAlreadyProcessed",
+ "inputs": [
+ { "name": "messageId", "type": "bytes32", "internalType": "bytes32" }
+ ]
+ },
+ {
+ "type": "error",
+ "name": "NotEnoughBalance",
+ "inputs": [
+ {
+ "name": "currentBalance",
+ "type": "uint256",
+ "internalType": "uint256"
+ },
+ {
+ "name": "calculatedFees",
+ "type": "uint256",
+ "internalType": "uint256"
+ }
+ ]
+ },
+ {
+ "type": "error",
+ "name": "SenderNotWhitelisted",
+ "inputs": [
+ { "name": "sender", "type": "address", "internalType": "address" }
+ ]
+ }
+ ]
+}
diff --git a/frontend/abi/tokenBridge/tokenBridgeAbi.json b/frontend/abi/tokenBridge/tokenBridgeAbi.json
new file mode 100644
index 0000000..bfa93b7
--- /dev/null
+++ b/frontend/abi/tokenBridge/tokenBridgeAbi.json
@@ -0,0 +1,795 @@
+{
+ "abi": [
+ {
+ "type": "constructor",
+ "inputs": [
+ { "name": "_router", "type": "address", "internalType": "address" }
+ ],
+ "stateMutability": "nonpayable"
+ },
+ { "type": "receive", "stateMutability": "payable" },
+ {
+ "type": "function",
+ "name": "DEFAULT_ADMIN_ROLE",
+ "inputs": [],
+ "outputs": [{ "name": "", "type": "bytes32", "internalType": "bytes32" }],
+ "stateMutability": "view"
+ },
+ {
+ "type": "function",
+ "name": "OWNER_ROLE",
+ "inputs": [],
+ "outputs": [{ "name": "", "type": "bytes32", "internalType": "bytes32" }],
+ "stateMutability": "view"
+ },
+ {
+ "type": "function",
+ "name": "UPGRADE_INTERFACE_VERSION",
+ "inputs": [],
+ "outputs": [{ "name": "", "type": "string", "internalType": "string" }],
+ "stateMutability": "view"
+ },
+ {
+ "type": "function",
+ "name": "addOwner",
+ "inputs": [
+ { "name": "account", "type": "address", "internalType": "address" }
+ ],
+ "outputs": [],
+ "stateMutability": "nonpayable"
+ },
+ {
+ "type": "function",
+ "name": "bridgeTokens",
+ "inputs": [
+ { "name": "receiver", "type": "address", "internalType": "address" },
+ { "name": "amount", "type": "uint256", "internalType": "uint256" },
+ {
+ "name": "payFeesIn",
+ "type": "uint8",
+ "internalType": "enum ITokenBridge.PayFeesIn"
+ }
+ ],
+ "outputs": [{ "name": "", "type": "bytes32", "internalType": "bytes32" }],
+ "stateMutability": "payable"
+ },
+ {
+ "type": "function",
+ "name": "ccipReceive",
+ "inputs": [
+ {
+ "name": "message",
+ "type": "tuple",
+ "internalType": "struct Client.Any2EVMMessage",
+ "components": [
+ {
+ "name": "messageId",
+ "type": "bytes32",
+ "internalType": "bytes32"
+ },
+ {
+ "name": "sourceChainSelector",
+ "type": "uint64",
+ "internalType": "uint64"
+ },
+ { "name": "sender", "type": "bytes", "internalType": "bytes" },
+ { "name": "data", "type": "bytes", "internalType": "bytes" },
+ {
+ "name": "destTokenAmounts",
+ "type": "tuple[]",
+ "internalType": "struct Client.EVMTokenAmount[]",
+ "components": [
+ {
+ "name": "token",
+ "type": "address",
+ "internalType": "address"
+ },
+ {
+ "name": "amount",
+ "type": "uint256",
+ "internalType": "uint256"
+ }
+ ]
+ }
+ ]
+ }
+ ],
+ "outputs": [],
+ "stateMutability": "nonpayable"
+ },
+ {
+ "type": "function",
+ "name": "destinationChainSelector",
+ "inputs": [],
+ "outputs": [{ "name": "", "type": "uint64", "internalType": "uint64" }],
+ "stateMutability": "view"
+ },
+ {
+ "type": "function",
+ "name": "getGoldTokenBalance",
+ "inputs": [],
+ "outputs": [{ "name": "", "type": "uint256", "internalType": "uint256" }],
+ "stateMutability": "view"
+ },
+ {
+ "type": "function",
+ "name": "getLinkBalance",
+ "inputs": [],
+ "outputs": [{ "name": "", "type": "uint256", "internalType": "uint256" }],
+ "stateMutability": "view"
+ },
+ {
+ "type": "function",
+ "name": "getRoleAdmin",
+ "inputs": [
+ { "name": "role", "type": "bytes32", "internalType": "bytes32" }
+ ],
+ "outputs": [{ "name": "", "type": "bytes32", "internalType": "bytes32" }],
+ "stateMutability": "view"
+ },
+ {
+ "type": "function",
+ "name": "getRouter",
+ "inputs": [],
+ "outputs": [{ "name": "", "type": "address", "internalType": "address" }],
+ "stateMutability": "view"
+ },
+ {
+ "type": "function",
+ "name": "goldToken",
+ "inputs": [],
+ "outputs": [{ "name": "", "type": "address", "internalType": "address" }],
+ "stateMutability": "view"
+ },
+ {
+ "type": "function",
+ "name": "grantRole",
+ "inputs": [
+ { "name": "role", "type": "bytes32", "internalType": "bytes32" },
+ { "name": "account", "type": "address", "internalType": "address" }
+ ],
+ "outputs": [],
+ "stateMutability": "nonpayable"
+ },
+ {
+ "type": "function",
+ "name": "hasOwnerRole",
+ "inputs": [
+ { "name": "account", "type": "address", "internalType": "address" }
+ ],
+ "outputs": [{ "name": "", "type": "bool", "internalType": "bool" }],
+ "stateMutability": "view"
+ },
+ {
+ "type": "function",
+ "name": "hasRole",
+ "inputs": [
+ { "name": "role", "type": "bytes32", "internalType": "bytes32" },
+ { "name": "account", "type": "address", "internalType": "address" }
+ ],
+ "outputs": [{ "name": "", "type": "bool", "internalType": "bool" }],
+ "stateMutability": "view"
+ },
+ {
+ "type": "function",
+ "name": "initialize",
+ "inputs": [
+ { "name": "owner", "type": "address", "internalType": "address" },
+ { "name": "_link", "type": "address", "internalType": "address" },
+ { "name": "_goldToken", "type": "address", "internalType": "address" },
+ {
+ "name": "_destinationChainSelector",
+ "type": "uint64",
+ "internalType": "uint64"
+ }
+ ],
+ "outputs": [],
+ "stateMutability": "nonpayable"
+ },
+ {
+ "type": "function",
+ "name": "link",
+ "inputs": [],
+ "outputs": [{ "name": "", "type": "address", "internalType": "address" }],
+ "stateMutability": "view"
+ },
+ {
+ "type": "function",
+ "name": "pause",
+ "inputs": [],
+ "outputs": [],
+ "stateMutability": "nonpayable"
+ },
+ {
+ "type": "function",
+ "name": "paused",
+ "inputs": [],
+ "outputs": [{ "name": "", "type": "bool", "internalType": "bool" }],
+ "stateMutability": "view"
+ },
+ {
+ "type": "function",
+ "name": "processedMessages",
+ "inputs": [
+ { "name": "messageId", "type": "bytes32", "internalType": "bytes32" }
+ ],
+ "outputs": [
+ { "name": "wasProcessed", "type": "bool", "internalType": "bool" }
+ ],
+ "stateMutability": "view"
+ },
+ {
+ "type": "function",
+ "name": "proxiableUUID",
+ "inputs": [],
+ "outputs": [{ "name": "", "type": "bytes32", "internalType": "bytes32" }],
+ "stateMutability": "view"
+ },
+ {
+ "type": "function",
+ "name": "removeOwner",
+ "inputs": [
+ { "name": "account", "type": "address", "internalType": "address" }
+ ],
+ "outputs": [],
+ "stateMutability": "nonpayable"
+ },
+ {
+ "type": "function",
+ "name": "renounceRole",
+ "inputs": [
+ { "name": "role", "type": "bytes32", "internalType": "bytes32" },
+ {
+ "name": "callerConfirmation",
+ "type": "address",
+ "internalType": "address"
+ }
+ ],
+ "outputs": [],
+ "stateMutability": "nonpayable"
+ },
+ {
+ "type": "function",
+ "name": "revokeRole",
+ "inputs": [
+ { "name": "role", "type": "bytes32", "internalType": "bytes32" },
+ { "name": "account", "type": "address", "internalType": "address" }
+ ],
+ "outputs": [],
+ "stateMutability": "nonpayable"
+ },
+ {
+ "type": "function",
+ "name": "setWhitelistedChain",
+ "inputs": [
+ { "name": "chainSelector", "type": "uint64", "internalType": "uint64" },
+ { "name": "enabled", "type": "bool", "internalType": "bool" },
+ { "name": "ccipExtraArgs", "type": "bytes", "internalType": "bytes" }
+ ],
+ "outputs": [],
+ "stateMutability": "nonpayable"
+ },
+ {
+ "type": "function",
+ "name": "setWhitelistedSender",
+ "inputs": [
+ { "name": "sender", "type": "address", "internalType": "address" },
+ { "name": "enabled", "type": "bool", "internalType": "bool" }
+ ],
+ "outputs": [],
+ "stateMutability": "nonpayable"
+ },
+ {
+ "type": "function",
+ "name": "supportsInterface",
+ "inputs": [
+ { "name": "interfaceId", "type": "bytes4", "internalType": "bytes4" }
+ ],
+ "outputs": [{ "name": "", "type": "bool", "internalType": "bool" }],
+ "stateMutability": "view"
+ },
+ {
+ "type": "function",
+ "name": "unpause",
+ "inputs": [],
+ "outputs": [],
+ "stateMutability": "nonpayable"
+ },
+ {
+ "type": "function",
+ "name": "upgradeToAndCall",
+ "inputs": [
+ {
+ "name": "newImplementation",
+ "type": "address",
+ "internalType": "address"
+ },
+ { "name": "data", "type": "bytes", "internalType": "bytes" }
+ ],
+ "outputs": [],
+ "stateMutability": "payable"
+ },
+ {
+ "type": "function",
+ "name": "whitelistedChains",
+ "inputs": [
+ { "name": "chainSelector", "type": "uint64", "internalType": "uint64" }
+ ],
+ "outputs": [{ "name": "", "type": "bool", "internalType": "bool" }],
+ "stateMutability": "view"
+ },
+ {
+ "type": "function",
+ "name": "whitelistedSenders",
+ "inputs": [
+ { "name": "sender", "type": "address", "internalType": "address" }
+ ],
+ "outputs": [
+ { "name": "allowed", "type": "bool", "internalType": "bool" }
+ ],
+ "stateMutability": "view"
+ },
+ {
+ "type": "function",
+ "name": "withdraw",
+ "inputs": [
+ { "name": "beneficiary", "type": "address", "internalType": "address" }
+ ],
+ "outputs": [],
+ "stateMutability": "nonpayable"
+ },
+ {
+ "type": "function",
+ "name": "withdrawToken",
+ "inputs": [
+ { "name": "beneficiary", "type": "address", "internalType": "address" },
+ { "name": "token", "type": "address", "internalType": "address" }
+ ],
+ "outputs": [],
+ "stateMutability": "nonpayable"
+ },
+ {
+ "type": "event",
+ "name": "ChainRemoved",
+ "inputs": [
+ {
+ "name": "chainSelector",
+ "type": "uint64",
+ "indexed": true,
+ "internalType": "uint64"
+ }
+ ],
+ "anonymous": false
+ },
+ {
+ "type": "event",
+ "name": "ChainWhitelisted",
+ "inputs": [
+ {
+ "name": "chainSelector",
+ "type": "uint64",
+ "indexed": true,
+ "internalType": "uint64"
+ }
+ ],
+ "anonymous": false
+ },
+ {
+ "type": "event",
+ "name": "Initialized",
+ "inputs": [
+ {
+ "name": "version",
+ "type": "uint64",
+ "indexed": false,
+ "internalType": "uint64"
+ }
+ ],
+ "anonymous": false
+ },
+ {
+ "type": "event",
+ "name": "MessageProcessedWithoutToken",
+ "inputs": [
+ {
+ "name": "messageId",
+ "type": "bytes32",
+ "indexed": true,
+ "internalType": "bytes32"
+ },
+ {
+ "name": "sourceChainSelector",
+ "type": "uint64",
+ "indexed": true,
+ "internalType": "uint64"
+ }
+ ],
+ "anonymous": false
+ },
+ {
+ "type": "event",
+ "name": "Paused",
+ "inputs": [
+ {
+ "name": "account",
+ "type": "address",
+ "indexed": false,
+ "internalType": "address"
+ }
+ ],
+ "anonymous": false
+ },
+ {
+ "type": "event",
+ "name": "RoleAdminChanged",
+ "inputs": [
+ {
+ "name": "role",
+ "type": "bytes32",
+ "indexed": true,
+ "internalType": "bytes32"
+ },
+ {
+ "name": "previousAdminRole",
+ "type": "bytes32",
+ "indexed": true,
+ "internalType": "bytes32"
+ },
+ {
+ "name": "newAdminRole",
+ "type": "bytes32",
+ "indexed": true,
+ "internalType": "bytes32"
+ }
+ ],
+ "anonymous": false
+ },
+ {
+ "type": "event",
+ "name": "RoleGranted",
+ "inputs": [
+ {
+ "name": "role",
+ "type": "bytes32",
+ "indexed": true,
+ "internalType": "bytes32"
+ },
+ {
+ "name": "account",
+ "type": "address",
+ "indexed": true,
+ "internalType": "address"
+ },
+ {
+ "name": "sender",
+ "type": "address",
+ "indexed": true,
+ "internalType": "address"
+ }
+ ],
+ "anonymous": false
+ },
+ {
+ "type": "event",
+ "name": "RoleRevoked",
+ "inputs": [
+ {
+ "name": "role",
+ "type": "bytes32",
+ "indexed": true,
+ "internalType": "bytes32"
+ },
+ {
+ "name": "account",
+ "type": "address",
+ "indexed": true,
+ "internalType": "address"
+ },
+ {
+ "name": "sender",
+ "type": "address",
+ "indexed": true,
+ "internalType": "address"
+ }
+ ],
+ "anonymous": false
+ },
+ {
+ "type": "event",
+ "name": "SenderRemoved",
+ "inputs": [
+ {
+ "name": "sender",
+ "type": "address",
+ "indexed": true,
+ "internalType": "address"
+ }
+ ],
+ "anonymous": false
+ },
+ {
+ "type": "event",
+ "name": "SenderWhitelisted",
+ "inputs": [
+ {
+ "name": "sender",
+ "type": "address",
+ "indexed": true,
+ "internalType": "address"
+ }
+ ],
+ "anonymous": false
+ },
+ {
+ "type": "event",
+ "name": "TokenBridgeInitialized",
+ "inputs": [
+ {
+ "name": "owner",
+ "type": "address",
+ "indexed": true,
+ "internalType": "address"
+ },
+ {
+ "name": "link",
+ "type": "address",
+ "indexed": true,
+ "internalType": "address"
+ },
+ {
+ "name": "goldToken",
+ "type": "address",
+ "indexed": true,
+ "internalType": "address"
+ },
+ {
+ "name": "destinationChainSelector",
+ "type": "uint64",
+ "indexed": false,
+ "internalType": "uint64"
+ }
+ ],
+ "anonymous": false
+ },
+ {
+ "type": "event",
+ "name": "TokensBridged",
+ "inputs": [
+ {
+ "name": "messageId",
+ "type": "bytes32",
+ "indexed": true,
+ "internalType": "bytes32"
+ },
+ {
+ "name": "sender",
+ "type": "address",
+ "indexed": true,
+ "internalType": "address"
+ },
+ {
+ "name": "receiver",
+ "type": "address",
+ "indexed": true,
+ "internalType": "address"
+ },
+ {
+ "name": "amount",
+ "type": "uint256",
+ "indexed": false,
+ "internalType": "uint256"
+ },
+ {
+ "name": "destinationChainSelector",
+ "type": "uint64",
+ "indexed": false,
+ "internalType": "uint64"
+ },
+ {
+ "name": "feeToken",
+ "type": "address",
+ "indexed": false,
+ "internalType": "address"
+ },
+ {
+ "name": "fees",
+ "type": "uint256",
+ "indexed": false,
+ "internalType": "uint256"
+ }
+ ],
+ "anonymous": false
+ },
+ {
+ "type": "event",
+ "name": "TokensReceived",
+ "inputs": [
+ {
+ "name": "messageId",
+ "type": "bytes32",
+ "indexed": true,
+ "internalType": "bytes32"
+ },
+ {
+ "name": "receiver",
+ "type": "address",
+ "indexed": true,
+ "internalType": "address"
+ },
+ {
+ "name": "amount",
+ "type": "uint256",
+ "indexed": false,
+ "internalType": "uint256"
+ },
+ {
+ "name": "sourceChainSelector",
+ "type": "uint64",
+ "indexed": true,
+ "internalType": "uint64"
+ }
+ ],
+ "anonymous": false
+ },
+ {
+ "type": "event",
+ "name": "Unpaused",
+ "inputs": [
+ {
+ "name": "account",
+ "type": "address",
+ "indexed": false,
+ "internalType": "address"
+ }
+ ],
+ "anonymous": false
+ },
+ {
+ "type": "event",
+ "name": "Upgraded",
+ "inputs": [
+ {
+ "name": "implementation",
+ "type": "address",
+ "indexed": true,
+ "internalType": "address"
+ }
+ ],
+ "anonymous": false
+ },
+ { "type": "error", "name": "AccessControlBadConfirmation", "inputs": [] },
+ {
+ "type": "error",
+ "name": "AccessControlUnauthorizedAccount",
+ "inputs": [
+ { "name": "account", "type": "address", "internalType": "address" },
+ { "name": "neededRole", "type": "bytes32", "internalType": "bytes32" }
+ ]
+ },
+ {
+ "type": "error",
+ "name": "AddressEmptyCode",
+ "inputs": [
+ { "name": "target", "type": "address", "internalType": "address" }
+ ]
+ },
+ {
+ "type": "error",
+ "name": "ChainNotWhitelisted",
+ "inputs": [
+ { "name": "chainSelector", "type": "uint64", "internalType": "uint64" }
+ ]
+ },
+ {
+ "type": "error",
+ "name": "ERC1967InvalidImplementation",
+ "inputs": [
+ {
+ "name": "implementation",
+ "type": "address",
+ "internalType": "address"
+ }
+ ]
+ },
+ { "type": "error", "name": "ERC1967NonPayable", "inputs": [] },
+ { "type": "error", "name": "EnforcedPause", "inputs": [] },
+ { "type": "error", "name": "ExpectedPause", "inputs": [] },
+ { "type": "error", "name": "FailedCall", "inputs": [] },
+ {
+ "type": "error",
+ "name": "FailedToWithdrawEth",
+ "inputs": [
+ { "name": "owner", "type": "address", "internalType": "address" },
+ { "name": "target", "type": "address", "internalType": "address" },
+ { "name": "value", "type": "uint256", "internalType": "uint256" }
+ ]
+ },
+ {
+ "type": "error",
+ "name": "InvalidAmount",
+ "inputs": [
+ { "name": "amount", "type": "uint256", "internalType": "uint256" }
+ ]
+ },
+ {
+ "type": "error",
+ "name": "InvalidChainSelector",
+ "inputs": [
+ { "name": "chainSelector", "type": "uint64", "internalType": "uint64" }
+ ]
+ },
+ { "type": "error", "name": "InvalidInitialization", "inputs": [] },
+ {
+ "type": "error",
+ "name": "InvalidRouter",
+ "inputs": [
+ { "name": "router", "type": "address", "internalType": "address" }
+ ]
+ },
+ {
+ "type": "error",
+ "name": "InvalidSender",
+ "inputs": [
+ { "name": "sender", "type": "address", "internalType": "address" }
+ ]
+ },
+ {
+ "type": "error",
+ "name": "InvalidSourceChain",
+ "inputs": [
+ {
+ "name": "sourceChainSelector",
+ "type": "uint64",
+ "internalType": "uint64"
+ }
+ ]
+ },
+ {
+ "type": "error",
+ "name": "MessageAlreadyProcessed",
+ "inputs": [
+ { "name": "messageId", "type": "bytes32", "internalType": "bytes32" }
+ ]
+ },
+ {
+ "type": "error",
+ "name": "NotEnoughBalance",
+ "inputs": [
+ {
+ "name": "currentBalance",
+ "type": "uint256",
+ "internalType": "uint256"
+ },
+ {
+ "name": "calculatedFees",
+ "type": "uint256",
+ "internalType": "uint256"
+ }
+ ]
+ },
+ { "type": "error", "name": "NotInitializing", "inputs": [] },
+ { "type": "error", "name": "ReentrancyGuardReentrantCall", "inputs": [] },
+ {
+ "type": "error",
+ "name": "SafeERC20FailedOperation",
+ "inputs": [
+ { "name": "token", "type": "address", "internalType": "address" }
+ ]
+ },
+ {
+ "type": "error",
+ "name": "SenderNotWhitelisted",
+ "inputs": [
+ { "name": "sender", "type": "address", "internalType": "address" }
+ ]
+ },
+ { "type": "error", "name": "UUPSUnauthorizedCallContext", "inputs": [] },
+ {
+ "type": "error",
+ "name": "UUPSUnsupportedProxiableUUID",
+ "inputs": [
+ { "name": "slot", "type": "bytes32", "internalType": "bytes32" }
+ ]
+ }
+ ]
+}
diff --git a/frontend/eslint.config.js b/frontend/eslint.config.js
new file mode 100644
index 0000000..116f84c
--- /dev/null
+++ b/frontend/eslint.config.js
@@ -0,0 +1,30 @@
+import js from "@eslint/js";
+import reactHooks from "eslint-plugin-react-hooks";
+import reactRefresh from "eslint-plugin-react-refresh";
+import globals from "globals";
+import tseslint from "typescript-eslint";
+
+export default tseslint.config(
+ { ignores: ["dist"] },
+ {
+ extends: [js.configs.recommended, ...tseslint.configs.recommended],
+ files: ["**/*.{ts,tsx}"],
+ languageOptions: {
+ ecmaVersion: 2020,
+ globals: globals.browser,
+ },
+ plugins: {
+ "react-hooks": reactHooks,
+ "react-refresh": reactRefresh,
+ },
+ rules: {
+ ...reactHooks.configs.recommended.rules,
+ "react-refresh/only-export-components": [
+ "warn",
+ { allowConstantExport: true },
+ ],
+ "@typescript-eslint/no-explicit-any": "warn",
+ "@typescript-eslint/ban-ts-comment": "warn",
+ },
+ }
+);
diff --git a/frontend/index.html b/frontend/index.html
new file mode 100644
index 0000000..b642a85
--- /dev/null
+++ b/frontend/index.html
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+ Golden Bridge
+
+
+
+
+
+
\ No newline at end of file
diff --git a/frontend/package-lock.json b/frontend/package-lock.json
new file mode 100644
index 0000000..db585ae
--- /dev/null
+++ b/frontend/package-lock.json
@@ -0,0 +1,7380 @@
+{
+ "name": "golden-bridge-frontend",
+ "version": "0.0.0",
+ "lockfileVersion": 3,
+ "requires": true,
+ "packages": {
+ "": {
+ "name": "golden-bridge-frontend",
+ "version": "0.0.0",
+ "dependencies": {
+ "@reown/appkit": "1.8.14",
+ "@reown/appkit-adapter-ethers": "1.8.14",
+ "ethers": "6.16.0",
+ "react": "19.2.1",
+ "react-dom": "19.2.1"
+ },
+ "devDependencies": {
+ "@eslint/js": "9.39.1",
+ "@types/react": "19.2.7",
+ "@types/react-dom": "19.2.3",
+ "@vitejs/plugin-react": "5.1.1",
+ "eslint": "9.39.1",
+ "eslint-plugin-react-hooks": "7.0.1",
+ "eslint-plugin-react-refresh": "0.4.24",
+ "globals": "16.5.0",
+ "typescript": "5.9.3",
+ "typescript-eslint": "8.48.1",
+ "vite": "7.2.6"
+ }
+ },
+ "node_modules/@adraffy/ens-normalize": {
+ "version": "1.10.1",
+ "resolved": "https://registry.npmjs.org/@adraffy/ens-normalize/-/ens-normalize-1.10.1.tgz",
+ "integrity": "sha512-96Z2IP3mYmF1Xg2cDm8f1gWGf/HUVedQ3FMifV4kG/PQ4yEP51xDtRAEfhVNt5f/uzpNkZHwWQuUcu6D6K+Ekw==",
+ "license": "MIT"
+ },
+ "node_modules/@babel/code-frame": {
+ "version": "7.27.1",
+ "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.27.1.tgz",
+ "integrity": "sha512-cjQ7ZlQ0Mv3b47hABuTevyTuYN4i+loJKGeV9flcCgIK37cCXRh+L1bd3iBHlynerhQ7BhCkn2BPbQUL+rGqFg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@babel/helper-validator-identifier": "^7.27.1",
+ "js-tokens": "^4.0.0",
+ "picocolors": "^1.1.1"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/compat-data": {
+ "version": "7.28.5",
+ "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.28.5.tgz",
+ "integrity": "sha512-6uFXyCayocRbqhZOB+6XcuZbkMNimwfVGFji8CTZnCzOHVGvDqzvitu1re2AU5LROliz7eQPhB8CpAMvnx9EjA==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/core": {
+ "version": "7.28.5",
+ "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.28.5.tgz",
+ "integrity": "sha512-e7jT4DxYvIDLk1ZHmU/m/mB19rex9sv0c2ftBtjSBv+kVM/902eh0fINUzD7UwLLNR+jU585GxUJ8/EBfAM5fw==",
+ "dev": true,
+ "license": "MIT",
+ "peer": true,
+ "dependencies": {
+ "@babel/code-frame": "^7.27.1",
+ "@babel/generator": "^7.28.5",
+ "@babel/helper-compilation-targets": "^7.27.2",
+ "@babel/helper-module-transforms": "^7.28.3",
+ "@babel/helpers": "^7.28.4",
+ "@babel/parser": "^7.28.5",
+ "@babel/template": "^7.27.2",
+ "@babel/traverse": "^7.28.5",
+ "@babel/types": "^7.28.5",
+ "@jridgewell/remapping": "^2.3.5",
+ "convert-source-map": "^2.0.0",
+ "debug": "^4.1.0",
+ "gensync": "^1.0.0-beta.2",
+ "json5": "^2.2.3",
+ "semver": "^6.3.1"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/babel"
+ }
+ },
+ "node_modules/@babel/core/node_modules/semver": {
+ "version": "6.3.1",
+ "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz",
+ "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==",
+ "dev": true,
+ "license": "ISC",
+ "bin": {
+ "semver": "bin/semver.js"
+ }
+ },
+ "node_modules/@babel/generator": {
+ "version": "7.28.5",
+ "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.28.5.tgz",
+ "integrity": "sha512-3EwLFhZ38J4VyIP6WNtt2kUdW9dokXA9Cr4IVIFHuCpZ3H8/YFOl5JjZHisrn1fATPBmKKqXzDFvh9fUwHz6CQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@babel/parser": "^7.28.5",
+ "@babel/types": "^7.28.5",
+ "@jridgewell/gen-mapping": "^0.3.12",
+ "@jridgewell/trace-mapping": "^0.3.28",
+ "jsesc": "^3.0.2"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/helper-compilation-targets": {
+ "version": "7.27.2",
+ "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.27.2.tgz",
+ "integrity": "sha512-2+1thGUUWWjLTYTHZWK1n8Yga0ijBz1XAhUXcKy81rd5g6yh7hGqMp45v7cadSbEHc9G3OTv45SyneRN3ps4DQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@babel/compat-data": "^7.27.2",
+ "@babel/helper-validator-option": "^7.27.1",
+ "browserslist": "^4.24.0",
+ "lru-cache": "^5.1.1",
+ "semver": "^6.3.1"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/helper-compilation-targets/node_modules/semver": {
+ "version": "6.3.1",
+ "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz",
+ "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==",
+ "dev": true,
+ "license": "ISC",
+ "bin": {
+ "semver": "bin/semver.js"
+ }
+ },
+ "node_modules/@babel/helper-globals": {
+ "version": "7.28.0",
+ "resolved": "https://registry.npmjs.org/@babel/helper-globals/-/helper-globals-7.28.0.tgz",
+ "integrity": "sha512-+W6cISkXFa1jXsDEdYA8HeevQT/FULhxzR99pxphltZcVaugps53THCeiWA8SguxxpSp3gKPiuYfSWopkLQ4hw==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/helper-module-imports": {
+ "version": "7.27.1",
+ "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.27.1.tgz",
+ "integrity": "sha512-0gSFWUPNXNopqtIPQvlD5WgXYI5GY2kP2cCvoT8kczjbfcfuIljTbcWrulD1CIPIX2gt1wghbDy08yE1p+/r3w==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@babel/traverse": "^7.27.1",
+ "@babel/types": "^7.27.1"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/helper-module-transforms": {
+ "version": "7.28.3",
+ "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.28.3.tgz",
+ "integrity": "sha512-gytXUbs8k2sXS9PnQptz5o0QnpLL51SwASIORY6XaBKF88nsOT0Zw9szLqlSGQDP/4TljBAD5y98p2U1fqkdsw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@babel/helper-module-imports": "^7.27.1",
+ "@babel/helper-validator-identifier": "^7.27.1",
+ "@babel/traverse": "^7.28.3"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0"
+ }
+ },
+ "node_modules/@babel/helper-plugin-utils": {
+ "version": "7.27.1",
+ "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.27.1.tgz",
+ "integrity": "sha512-1gn1Up5YXka3YYAHGKpbideQ5Yjf1tDa9qYcgysz+cNCXukyLl6DjPXhD3VRwSb8c0J9tA4b2+rHEZtc6R0tlw==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/helper-string-parser": {
+ "version": "7.27.1",
+ "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.27.1.tgz",
+ "integrity": "sha512-qMlSxKbpRlAridDExk92nSobyDdpPijUq2DW6oDnUqd0iOGxmQjyqhMIihI9+zv4LPyZdRje2cavWPbCbWm3eA==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/helper-validator-identifier": {
+ "version": "7.28.5",
+ "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.28.5.tgz",
+ "integrity": "sha512-qSs4ifwzKJSV39ucNjsvc6WVHs6b7S03sOh2OcHF9UHfVPqWWALUsNUVzhSBiItjRZoLHx7nIarVjqKVusUZ1Q==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/helper-validator-option": {
+ "version": "7.27.1",
+ "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.27.1.tgz",
+ "integrity": "sha512-YvjJow9FxbhFFKDSuFnVCe2WxXk1zWc22fFePVNEaWJEu8IrZVlda6N0uHwzZrUM1il7NC9Mlp4MaJYbYd9JSg==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/helpers": {
+ "version": "7.28.4",
+ "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.28.4.tgz",
+ "integrity": "sha512-HFN59MmQXGHVyYadKLVumYsA9dBFun/ldYxipEjzA4196jpLZd8UjEEBLkbEkvfYreDqJhZxYAWFPtrfhNpj4w==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@babel/template": "^7.27.2",
+ "@babel/types": "^7.28.4"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/parser": {
+ "version": "7.28.5",
+ "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.28.5.tgz",
+ "integrity": "sha512-KKBU1VGYR7ORr3At5HAtUQ+TV3SzRCXmA/8OdDZiLDBIZxVyzXuztPjfLd3BV1PRAQGCMWWSHYhL0F8d5uHBDQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@babel/types": "^7.28.5"
+ },
+ "bin": {
+ "parser": "bin/babel-parser.js"
+ },
+ "engines": {
+ "node": ">=6.0.0"
+ }
+ },
+ "node_modules/@babel/plugin-transform-react-jsx-self": {
+ "version": "7.27.1",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx-self/-/plugin-transform-react-jsx-self-7.27.1.tgz",
+ "integrity": "sha512-6UzkCs+ejGdZ5mFFC/OCUrv028ab2fp1znZmCZjAOBKiBK2jXD1O+BPSfX8X2qjJ75fZBMSnQn3Rq2mrBJK2mw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@babel/helper-plugin-utils": "^7.27.1"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-transform-react-jsx-source": {
+ "version": "7.27.1",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx-source/-/plugin-transform-react-jsx-source-7.27.1.tgz",
+ "integrity": "sha512-zbwoTsBruTeKB9hSq73ha66iFeJHuaFkUbwvqElnygoNbj/jHRsSeokowZFN3CZ64IvEqcmmkVe89OPXc7ldAw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@babel/helper-plugin-utils": "^7.27.1"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "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==",
+ "license": "MIT",
+ "optional": true,
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/template": {
+ "version": "7.27.2",
+ "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.27.2.tgz",
+ "integrity": "sha512-LPDZ85aEJyYSd18/DkjNh4/y1ntkE5KwUHWTiqgRxruuZL2F1yuHligVHLvcHY2vMHXttKFpJn6LwfI7cw7ODw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@babel/code-frame": "^7.27.1",
+ "@babel/parser": "^7.27.2",
+ "@babel/types": "^7.27.1"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/traverse": {
+ "version": "7.28.5",
+ "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.28.5.tgz",
+ "integrity": "sha512-TCCj4t55U90khlYkVV/0TfkJkAkUg3jZFA3Neb7unZT8CPok7iiRfaX0F+WnqWqt7OxhOn0uBKXCw4lbL8W0aQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@babel/code-frame": "^7.27.1",
+ "@babel/generator": "^7.28.5",
+ "@babel/helper-globals": "^7.28.0",
+ "@babel/parser": "^7.28.5",
+ "@babel/template": "^7.27.2",
+ "@babel/types": "^7.28.5",
+ "debug": "^4.3.1"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/types": {
+ "version": "7.28.5",
+ "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.28.5.tgz",
+ "integrity": "sha512-qQ5m48eI/MFLQ5PxQj4PFaprjyCTLI37ElWMmNs0K8Lk3dVeOdNpB3ks8jc7yM5CDmVC73eMVk/trk3fgmrUpA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@babel/helper-string-parser": "^7.27.1",
+ "@babel/helper-validator-identifier": "^7.28.5"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@base-org/account": {
+ "version": "2.4.0",
+ "resolved": "https://registry.npmjs.org/@base-org/account/-/account-2.4.0.tgz",
+ "integrity": "sha512-A4Umpi8B9/pqR78D1Yoze4xHyQaujioVRqqO3d6xuDFw9VRtjg6tK3bPlwE0aW+nVH/ntllCpPa2PbI8Rnjcug==",
+ "license": "Apache-2.0",
+ "optional": true,
+ "dependencies": {
+ "@coinbase/cdp-sdk": "^1.0.0",
+ "@noble/hashes": "1.4.0",
+ "clsx": "1.2.1",
+ "eventemitter3": "5.0.1",
+ "idb-keyval": "6.2.1",
+ "ox": "0.6.9",
+ "preact": "10.24.2",
+ "viem": "^2.31.7",
+ "zustand": "5.0.3"
+ }
+ },
+ "node_modules/@coinbase/cdp-sdk": {
+ "version": "1.38.6",
+ "resolved": "https://registry.npmjs.org/@coinbase/cdp-sdk/-/cdp-sdk-1.38.6.tgz",
+ "integrity": "sha512-l9gGGZqhCryuD3nfqB4Y+i8kfBtsnPJoKB5jxx5lKgXhVJw7/BPhgscKkVhP81115Srq3bFegD1IBwUkJ0JFMw==",
+ "license": "MIT",
+ "optional": true,
+ "dependencies": {
+ "@solana-program/system": "^0.8.0",
+ "@solana-program/token": "^0.6.0",
+ "@solana/kit": "^3.0.3",
+ "@solana/web3.js": "^1.98.1",
+ "abitype": "1.0.6",
+ "axios": "^1.12.2",
+ "axios-retry": "^4.5.0",
+ "jose": "^6.0.8",
+ "md5": "^2.3.0",
+ "uncrypto": "^0.1.3",
+ "viem": "^2.21.26",
+ "zod": "^3.24.4"
+ }
+ },
+ "node_modules/@esbuild/aix-ppc64": {
+ "version": "0.25.12",
+ "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.25.12.tgz",
+ "integrity": "sha512-Hhmwd6CInZ3dwpuGTF8fJG6yoWmsToE+vYgD4nytZVxcu1ulHpUQRAB1UJ8+N1Am3Mz4+xOByoQoSZf4D+CpkA==",
+ "cpu": [
+ "ppc64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "aix"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@esbuild/android-arm": {
+ "version": "0.25.12",
+ "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.25.12.tgz",
+ "integrity": "sha512-VJ+sKvNA/GE7Ccacc9Cha7bpS8nyzVv0jdVgwNDaR4gDMC/2TTRc33Ip8qrNYUcpkOHUT5OZ0bUcNNVZQ9RLlg==",
+ "cpu": [
+ "arm"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "android"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@esbuild/android-arm64": {
+ "version": "0.25.12",
+ "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.25.12.tgz",
+ "integrity": "sha512-6AAmLG7zwD1Z159jCKPvAxZd4y/VTO0VkprYy+3N2FtJ8+BQWFXU+OxARIwA46c5tdD9SsKGZ/1ocqBS/gAKHg==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "android"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@esbuild/android-x64": {
+ "version": "0.25.12",
+ "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.25.12.tgz",
+ "integrity": "sha512-5jbb+2hhDHx5phYR2By8GTWEzn6I9UqR11Kwf22iKbNpYrsmRB18aX/9ivc5cabcUiAT/wM+YIZ6SG9QO6a8kg==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "android"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@esbuild/darwin-arm64": {
+ "version": "0.25.12",
+ "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.25.12.tgz",
+ "integrity": "sha512-N3zl+lxHCifgIlcMUP5016ESkeQjLj/959RxxNYIthIg+CQHInujFuXeWbWMgnTo4cp5XVHqFPmpyu9J65C1Yg==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "darwin"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@esbuild/darwin-x64": {
+ "version": "0.25.12",
+ "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.25.12.tgz",
+ "integrity": "sha512-HQ9ka4Kx21qHXwtlTUVbKJOAnmG1ipXhdWTmNXiPzPfWKpXqASVcWdnf2bnL73wgjNrFXAa3yYvBSd9pzfEIpA==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "darwin"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@esbuild/freebsd-arm64": {
+ "version": "0.25.12",
+ "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.25.12.tgz",
+ "integrity": "sha512-gA0Bx759+7Jve03K1S0vkOu5Lg/85dou3EseOGUes8flVOGxbhDDh/iZaoek11Y8mtyKPGF3vP8XhnkDEAmzeg==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "freebsd"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@esbuild/freebsd-x64": {
+ "version": "0.25.12",
+ "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.25.12.tgz",
+ "integrity": "sha512-TGbO26Yw2xsHzxtbVFGEXBFH0FRAP7gtcPE7P5yP7wGy7cXK2oO7RyOhL5NLiqTlBh47XhmIUXuGciXEqYFfBQ==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "freebsd"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@esbuild/linux-arm": {
+ "version": "0.25.12",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.25.12.tgz",
+ "integrity": "sha512-lPDGyC1JPDou8kGcywY0YILzWlhhnRjdof3UlcoqYmS9El818LLfJJc3PXXgZHrHCAKs/Z2SeZtDJr5MrkxtOw==",
+ "cpu": [
+ "arm"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@esbuild/linux-arm64": {
+ "version": "0.25.12",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.25.12.tgz",
+ "integrity": "sha512-8bwX7a8FghIgrupcxb4aUmYDLp8pX06rGh5HqDT7bB+8Rdells6mHvrFHHW2JAOPZUbnjUpKTLg6ECyzvas2AQ==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@esbuild/linux-ia32": {
+ "version": "0.25.12",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.25.12.tgz",
+ "integrity": "sha512-0y9KrdVnbMM2/vG8KfU0byhUN+EFCny9+8g202gYqSSVMonbsCfLjUO+rCci7pM0WBEtz+oK/PIwHkzxkyharA==",
+ "cpu": [
+ "ia32"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@esbuild/linux-loong64": {
+ "version": "0.25.12",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.25.12.tgz",
+ "integrity": "sha512-h///Lr5a9rib/v1GGqXVGzjL4TMvVTv+s1DPoxQdz7l/AYv6LDSxdIwzxkrPW438oUXiDtwM10o9PmwS/6Z0Ng==",
+ "cpu": [
+ "loong64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@esbuild/linux-mips64el": {
+ "version": "0.25.12",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.25.12.tgz",
+ "integrity": "sha512-iyRrM1Pzy9GFMDLsXn1iHUm18nhKnNMWscjmp4+hpafcZjrr2WbT//d20xaGljXDBYHqRcl8HnxbX6uaA/eGVw==",
+ "cpu": [
+ "mips64el"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@esbuild/linux-ppc64": {
+ "version": "0.25.12",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.25.12.tgz",
+ "integrity": "sha512-9meM/lRXxMi5PSUqEXRCtVjEZBGwB7P/D4yT8UG/mwIdze2aV4Vo6U5gD3+RsoHXKkHCfSxZKzmDssVlRj1QQA==",
+ "cpu": [
+ "ppc64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@esbuild/linux-riscv64": {
+ "version": "0.25.12",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.25.12.tgz",
+ "integrity": "sha512-Zr7KR4hgKUpWAwb1f3o5ygT04MzqVrGEGXGLnj15YQDJErYu/BGg+wmFlIDOdJp0PmB0lLvxFIOXZgFRrdjR0w==",
+ "cpu": [
+ "riscv64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@esbuild/linux-s390x": {
+ "version": "0.25.12",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.25.12.tgz",
+ "integrity": "sha512-MsKncOcgTNvdtiISc/jZs/Zf8d0cl/t3gYWX8J9ubBnVOwlk65UIEEvgBORTiljloIWnBzLs4qhzPkJcitIzIg==",
+ "cpu": [
+ "s390x"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@esbuild/linux-x64": {
+ "version": "0.25.12",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.25.12.tgz",
+ "integrity": "sha512-uqZMTLr/zR/ed4jIGnwSLkaHmPjOjJvnm6TVVitAa08SLS9Z0VM8wIRx7gWbJB5/J54YuIMInDquWyYvQLZkgw==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@esbuild/netbsd-arm64": {
+ "version": "0.25.12",
+ "resolved": "https://registry.npmjs.org/@esbuild/netbsd-arm64/-/netbsd-arm64-0.25.12.tgz",
+ "integrity": "sha512-xXwcTq4GhRM7J9A8Gv5boanHhRa/Q9KLVmcyXHCTaM4wKfIpWkdXiMog/KsnxzJ0A1+nD+zoecuzqPmCRyBGjg==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "netbsd"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@esbuild/netbsd-x64": {
+ "version": "0.25.12",
+ "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.25.12.tgz",
+ "integrity": "sha512-Ld5pTlzPy3YwGec4OuHh1aCVCRvOXdH8DgRjfDy/oumVovmuSzWfnSJg+VtakB9Cm0gxNO9BzWkj6mtO1FMXkQ==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "netbsd"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@esbuild/openbsd-arm64": {
+ "version": "0.25.12",
+ "resolved": "https://registry.npmjs.org/@esbuild/openbsd-arm64/-/openbsd-arm64-0.25.12.tgz",
+ "integrity": "sha512-fF96T6KsBo/pkQI950FARU9apGNTSlZGsv1jZBAlcLL1MLjLNIWPBkj5NlSz8aAzYKg+eNqknrUJ24QBybeR5A==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "openbsd"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@esbuild/openbsd-x64": {
+ "version": "0.25.12",
+ "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.25.12.tgz",
+ "integrity": "sha512-MZyXUkZHjQxUvzK7rN8DJ3SRmrVrke8ZyRusHlP+kuwqTcfWLyqMOE3sScPPyeIXN/mDJIfGXvcMqCgYKekoQw==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "openbsd"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@esbuild/openharmony-arm64": {
+ "version": "0.25.12",
+ "resolved": "https://registry.npmjs.org/@esbuild/openharmony-arm64/-/openharmony-arm64-0.25.12.tgz",
+ "integrity": "sha512-rm0YWsqUSRrjncSXGA7Zv78Nbnw4XL6/dzr20cyrQf7ZmRcsovpcRBdhD43Nuk3y7XIoW2OxMVvwuRvk9XdASg==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "openharmony"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@esbuild/sunos-x64": {
+ "version": "0.25.12",
+ "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.25.12.tgz",
+ "integrity": "sha512-3wGSCDyuTHQUzt0nV7bocDy72r2lI33QL3gkDNGkod22EsYl04sMf0qLb8luNKTOmgF/eDEDP5BFNwoBKH441w==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "sunos"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@esbuild/win32-arm64": {
+ "version": "0.25.12",
+ "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.25.12.tgz",
+ "integrity": "sha512-rMmLrur64A7+DKlnSuwqUdRKyd3UE7oPJZmnljqEptesKM8wx9J8gx5u0+9Pq0fQQW8vqeKebwNXdfOyP+8Bsg==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "win32"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@esbuild/win32-ia32": {
+ "version": "0.25.12",
+ "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.25.12.tgz",
+ "integrity": "sha512-HkqnmmBoCbCwxUKKNPBixiWDGCpQGVsrQfJoVGYLPT41XWF8lHuE5N6WhVia2n4o5QK5M4tYr21827fNhi4byQ==",
+ "cpu": [
+ "ia32"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "win32"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@esbuild/win32-x64": {
+ "version": "0.25.12",
+ "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.25.12.tgz",
+ "integrity": "sha512-alJC0uCZpTFrSL0CCDjcgleBXPnCrEAhTBILpeAp7M/OFgoqtAetfBzX0xM00MUsVVPpVjlPuMbREqnZCXaTnA==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "win32"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@eslint-community/eslint-utils": {
+ "version": "4.9.0",
+ "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.9.0.tgz",
+ "integrity": "sha512-ayVFHdtZ+hsq1t2Dy24wCmGXGe4q9Gu3smhLYALJrr473ZH27MsnSL+LKUlimp4BWJqMDMLmPpx/Q9R3OAlL4g==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "eslint-visitor-keys": "^3.4.3"
+ },
+ "engines": {
+ "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
+ },
+ "funding": {
+ "url": "https://opencollective.com/eslint"
+ },
+ "peerDependencies": {
+ "eslint": "^6.0.0 || ^7.0.0 || >=8.0.0"
+ }
+ },
+ "node_modules/@eslint-community/eslint-utils/node_modules/eslint-visitor-keys": {
+ "version": "3.4.3",
+ "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz",
+ "integrity": "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==",
+ "dev": true,
+ "license": "Apache-2.0",
+ "engines": {
+ "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
+ },
+ "funding": {
+ "url": "https://opencollective.com/eslint"
+ }
+ },
+ "node_modules/@eslint-community/regexpp": {
+ "version": "4.12.2",
+ "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.12.2.tgz",
+ "integrity": "sha512-EriSTlt5OC9/7SXkRSCAhfSxxoSUgBm33OH+IkwbdpgoqsSsUg7y3uh+IICI/Qg4BBWr3U2i39RpmycbxMq4ew==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": "^12.0.0 || ^14.0.0 || >=16.0.0"
+ }
+ },
+ "node_modules/@eslint/config-array": {
+ "version": "0.21.1",
+ "resolved": "https://registry.npmjs.org/@eslint/config-array/-/config-array-0.21.1.tgz",
+ "integrity": "sha512-aw1gNayWpdI/jSYVgzN5pL0cfzU02GT3NBpeT/DXbx1/1x7ZKxFPd9bwrzygx/qiwIQiJ1sw/zD8qY/kRvlGHA==",
+ "dev": true,
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@eslint/object-schema": "^2.1.7",
+ "debug": "^4.3.1",
+ "minimatch": "^3.1.2"
+ },
+ "engines": {
+ "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
+ }
+ },
+ "node_modules/@eslint/config-helpers": {
+ "version": "0.4.2",
+ "resolved": "https://registry.npmjs.org/@eslint/config-helpers/-/config-helpers-0.4.2.tgz",
+ "integrity": "sha512-gBrxN88gOIf3R7ja5K9slwNayVcZgK6SOUORm2uBzTeIEfeVaIhOpCtTox3P6R7o2jLFwLFTLnC7kU/RGcYEgw==",
+ "dev": true,
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@eslint/core": "^0.17.0"
+ },
+ "engines": {
+ "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
+ }
+ },
+ "node_modules/@eslint/core": {
+ "version": "0.17.0",
+ "resolved": "https://registry.npmjs.org/@eslint/core/-/core-0.17.0.tgz",
+ "integrity": "sha512-yL/sLrpmtDaFEiUj1osRP4TI2MDz1AddJL+jZ7KSqvBuliN4xqYY54IfdN8qD8Toa6g1iloph1fxQNkjOxrrpQ==",
+ "dev": true,
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@types/json-schema": "^7.0.15"
+ },
+ "engines": {
+ "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
+ }
+ },
+ "node_modules/@eslint/eslintrc": {
+ "version": "3.3.3",
+ "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-3.3.3.tgz",
+ "integrity": "sha512-Kr+LPIUVKz2qkx1HAMH8q1q6azbqBAsXJUxBl/ODDuVPX45Z9DfwB8tPjTi6nNZ8BuM3nbJxC5zCAg5elnBUTQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "ajv": "^6.12.4",
+ "debug": "^4.3.2",
+ "espree": "^10.0.1",
+ "globals": "^14.0.0",
+ "ignore": "^5.2.0",
+ "import-fresh": "^3.2.1",
+ "js-yaml": "^4.1.1",
+ "minimatch": "^3.1.2",
+ "strip-json-comments": "^3.1.1"
+ },
+ "engines": {
+ "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
+ },
+ "funding": {
+ "url": "https://opencollective.com/eslint"
+ }
+ },
+ "node_modules/@eslint/eslintrc/node_modules/globals": {
+ "version": "14.0.0",
+ "resolved": "https://registry.npmjs.org/globals/-/globals-14.0.0.tgz",
+ "integrity": "sha512-oahGvuMGQlPw/ivIYBjVSrWAfWLBeku5tpPE2fOPLi+WHffIWbuh2tCjhyQhTBPMf5E9jDEH4FOmTYgYwbKwtQ==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=18"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/@eslint/js": {
+ "version": "9.39.1",
+ "resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.39.1.tgz",
+ "integrity": "sha512-S26Stp4zCy88tH94QbBv3XCuzRQiZ9yXofEILmglYTh/Ug/a9/umqvgFtYBAo3Lp0nsI/5/qH1CCrbdK3AP1Tw==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
+ },
+ "funding": {
+ "url": "https://eslint.org/donate"
+ }
+ },
+ "node_modules/@eslint/object-schema": {
+ "version": "2.1.7",
+ "resolved": "https://registry.npmjs.org/@eslint/object-schema/-/object-schema-2.1.7.tgz",
+ "integrity": "sha512-VtAOaymWVfZcmZbp6E2mympDIHvyjXs/12LqWYjVw6qjrfF+VK+fyG33kChz3nnK+SU5/NeHOqrTEHS8sXO3OA==",
+ "dev": true,
+ "license": "Apache-2.0",
+ "engines": {
+ "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
+ }
+ },
+ "node_modules/@eslint/plugin-kit": {
+ "version": "0.4.1",
+ "resolved": "https://registry.npmjs.org/@eslint/plugin-kit/-/plugin-kit-0.4.1.tgz",
+ "integrity": "sha512-43/qtrDUokr7LJqoF2c3+RInu/t4zfrpYdoSDfYyhg52rwLV6TnOvdG4fXm7IkSB3wErkcmJS9iEhjVtOSEjjA==",
+ "dev": true,
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@eslint/core": "^0.17.0",
+ "levn": "^0.4.1"
+ },
+ "engines": {
+ "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
+ }
+ },
+ "node_modules/@ethersproject/bytes": {
+ "version": "5.8.0",
+ "resolved": "https://registry.npmjs.org/@ethersproject/bytes/-/bytes-5.8.0.tgz",
+ "integrity": "sha512-vTkeohgJVCPVHu5c25XWaWQOZ4v+DkGoC42/TS2ond+PARCxTJvgTFUNDZovyQ/uAQ4EcpqqowKydcdmRKjg7A==",
+ "funding": [
+ {
+ "type": "individual",
+ "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2"
+ },
+ {
+ "type": "individual",
+ "url": "https://www.buymeacoffee.com/ricmoo"
+ }
+ ],
+ "license": "MIT",
+ "dependencies": {
+ "@ethersproject/logger": "^5.8.0"
+ }
+ },
+ "node_modules/@ethersproject/logger": {
+ "version": "5.8.0",
+ "resolved": "https://registry.npmjs.org/@ethersproject/logger/-/logger-5.8.0.tgz",
+ "integrity": "sha512-Qe6knGmY+zPPWTC+wQrpitodgBfH7XoceCGL5bJVejmH+yCS3R8jJm8iiWuvWbG76RUmyEG53oqv6GMVWqunjA==",
+ "funding": [
+ {
+ "type": "individual",
+ "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2"
+ },
+ {
+ "type": "individual",
+ "url": "https://www.buymeacoffee.com/ricmoo"
+ }
+ ],
+ "license": "MIT"
+ },
+ "node_modules/@ethersproject/sha2": {
+ "version": "5.8.0",
+ "resolved": "https://registry.npmjs.org/@ethersproject/sha2/-/sha2-5.8.0.tgz",
+ "integrity": "sha512-dDOUrXr9wF/YFltgTBYS0tKslPEKr6AekjqDW2dbn1L1xmjGR+9GiKu4ajxovnrDbwxAKdHjW8jNcwfz8PAz4A==",
+ "funding": [
+ {
+ "type": "individual",
+ "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2"
+ },
+ {
+ "type": "individual",
+ "url": "https://www.buymeacoffee.com/ricmoo"
+ }
+ ],
+ "license": "MIT",
+ "peer": true,
+ "dependencies": {
+ "@ethersproject/bytes": "^5.8.0",
+ "@ethersproject/logger": "^5.8.0",
+ "hash.js": "1.1.7"
+ }
+ },
+ "node_modules/@humanfs/core": {
+ "version": "0.19.1",
+ "resolved": "https://registry.npmjs.org/@humanfs/core/-/core-0.19.1.tgz",
+ "integrity": "sha512-5DyQ4+1JEUzejeK1JGICcideyfUbGixgS9jNgex5nqkW+cY7WZhxBigmieN5Qnw9ZosSNVC9KQKyb+GUaGyKUA==",
+ "dev": true,
+ "license": "Apache-2.0",
+ "engines": {
+ "node": ">=18.18.0"
+ }
+ },
+ "node_modules/@humanfs/node": {
+ "version": "0.16.7",
+ "resolved": "https://registry.npmjs.org/@humanfs/node/-/node-0.16.7.tgz",
+ "integrity": "sha512-/zUx+yOsIrG4Y43Eh2peDeKCxlRt/gET6aHfaKpuq267qXdYDFViVHfMaLyygZOnl0kGWxFIgsBy8QFuTLUXEQ==",
+ "dev": true,
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@humanfs/core": "^0.19.1",
+ "@humanwhocodes/retry": "^0.4.0"
+ },
+ "engines": {
+ "node": ">=18.18.0"
+ }
+ },
+ "node_modules/@humanwhocodes/module-importer": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz",
+ "integrity": "sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==",
+ "dev": true,
+ "license": "Apache-2.0",
+ "engines": {
+ "node": ">=12.22"
+ },
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/nzakas"
+ }
+ },
+ "node_modules/@humanwhocodes/retry": {
+ "version": "0.4.3",
+ "resolved": "https://registry.npmjs.org/@humanwhocodes/retry/-/retry-0.4.3.tgz",
+ "integrity": "sha512-bV0Tgo9K4hfPCek+aMAn81RppFKv2ySDQeMoSZuvTASywNTnVJCArCZE2FWqpvIatKu7VMRLWlR1EazvVhDyhQ==",
+ "dev": true,
+ "license": "Apache-2.0",
+ "engines": {
+ "node": ">=18.18"
+ },
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/nzakas"
+ }
+ },
+ "node_modules/@jridgewell/gen-mapping": {
+ "version": "0.3.13",
+ "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.13.tgz",
+ "integrity": "sha512-2kkt/7niJ6MgEPxF0bYdQ6etZaA+fQvDcLKckhy1yIQOzaoKjBBjSj63/aLVjYE3qhRt5dvM+uUyfCg6UKCBbA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@jridgewell/sourcemap-codec": "^1.5.0",
+ "@jridgewell/trace-mapping": "^0.3.24"
+ }
+ },
+ "node_modules/@jridgewell/remapping": {
+ "version": "2.3.5",
+ "resolved": "https://registry.npmjs.org/@jridgewell/remapping/-/remapping-2.3.5.tgz",
+ "integrity": "sha512-LI9u/+laYG4Ds1TDKSJW2YPrIlcVYOwi2fUC6xB43lueCjgxV4lffOCZCtYFiH6TNOX+tQKXx97T4IKHbhyHEQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@jridgewell/gen-mapping": "^0.3.5",
+ "@jridgewell/trace-mapping": "^0.3.24"
+ }
+ },
+ "node_modules/@jridgewell/resolve-uri": {
+ "version": "3.1.2",
+ "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz",
+ "integrity": "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=6.0.0"
+ }
+ },
+ "node_modules/@jridgewell/sourcemap-codec": {
+ "version": "1.5.5",
+ "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.5.tgz",
+ "integrity": "sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/@jridgewell/trace-mapping": {
+ "version": "0.3.31",
+ "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.31.tgz",
+ "integrity": "sha512-zzNR+SdQSDJzc8joaeP8QQoCQr8NuYx2dIIytl1QeBEZHJ9uW6hebsrYgbz8hJwUQao3TWCMtmfV8Nu1twOLAw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@jridgewell/resolve-uri": "^3.1.0",
+ "@jridgewell/sourcemap-codec": "^1.4.14"
+ }
+ },
+ "node_modules/@lit-labs/ssr-dom-shim": {
+ "version": "1.4.0",
+ "resolved": "https://registry.npmjs.org/@lit-labs/ssr-dom-shim/-/ssr-dom-shim-1.4.0.tgz",
+ "integrity": "sha512-ficsEARKnmmW5njugNYKipTm4SFnbik7CXtoencDZzmzo/dQ+2Q0bgkzJuoJP20Aj0F+izzJjOqsnkd6F/o1bw==",
+ "license": "BSD-3-Clause"
+ },
+ "node_modules/@lit/react": {
+ "version": "1.0.8",
+ "resolved": "https://registry.npmjs.org/@lit/react/-/react-1.0.8.tgz",
+ "integrity": "sha512-p2+YcF+JE67SRX3mMlJ1TKCSTsgyOVdAwd/nxp3NuV1+Cb6MWALbN6nT7Ld4tpmYofcE5kcaSY1YBB9erY+6fw==",
+ "license": "BSD-3-Clause",
+ "optional": true,
+ "peerDependencies": {
+ "@types/react": "17 || 18 || 19"
+ }
+ },
+ "node_modules/@lit/reactive-element": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/@lit/reactive-element/-/reactive-element-2.1.1.tgz",
+ "integrity": "sha512-N+dm5PAYdQ8e6UlywyyrgI2t++wFGXfHx+dSJ1oBrg6FAxUj40jId++EaRm80MKX5JnlH1sBsyZ5h0bcZKemCg==",
+ "license": "BSD-3-Clause",
+ "dependencies": {
+ "@lit-labs/ssr-dom-shim": "^1.4.0"
+ }
+ },
+ "node_modules/@msgpack/msgpack": {
+ "version": "3.1.2",
+ "resolved": "https://registry.npmjs.org/@msgpack/msgpack/-/msgpack-3.1.2.tgz",
+ "integrity": "sha512-JEW4DEtBzfe8HvUYecLU9e6+XJnKDlUAIve8FvPzF3Kzs6Xo/KuZkZJsDH0wJXl/qEZbeeE7edxDNY3kMs39hQ==",
+ "license": "ISC",
+ "engines": {
+ "node": ">= 18"
+ }
+ },
+ "node_modules/@noble/ciphers": {
+ "version": "1.3.0",
+ "resolved": "https://registry.npmjs.org/@noble/ciphers/-/ciphers-1.3.0.tgz",
+ "integrity": "sha512-2I0gnIVPtfnMw9ee9h1dJG7tp81+8Ob3OJb3Mv37rx5L40/b0i7djjCVvGOVqc9AEIQyvyu1i6ypKdFw8R8gQw==",
+ "license": "MIT",
+ "engines": {
+ "node": "^14.21.3 || >=16"
+ },
+ "funding": {
+ "url": "https://paulmillr.com/funding/"
+ }
+ },
+ "node_modules/@noble/curves": {
+ "version": "1.9.7",
+ "resolved": "https://registry.npmjs.org/@noble/curves/-/curves-1.9.7.tgz",
+ "integrity": "sha512-gbKGcRUYIjA3/zCCNaWDciTMFI0dCkvou3TL8Zmy5Nc7sJ47a0jtOeZoTaMxkuqRo9cRhjOdZJXegxYE5FN/xw==",
+ "license": "MIT",
+ "dependencies": {
+ "@noble/hashes": "1.8.0"
+ },
+ "engines": {
+ "node": "^14.21.3 || >=16"
+ },
+ "funding": {
+ "url": "https://paulmillr.com/funding/"
+ }
+ },
+ "node_modules/@noble/curves/node_modules/@noble/hashes": {
+ "version": "1.8.0",
+ "resolved": "https://registry.npmjs.org/@noble/hashes/-/hashes-1.8.0.tgz",
+ "integrity": "sha512-jCs9ldd7NwzpgXDIf6P3+NrHh9/sD6CQdxHyjQI+h/6rDNo88ypBxxz45UDuZHz9r3tNz7N/VInSVoVdtXEI4A==",
+ "license": "MIT",
+ "engines": {
+ "node": "^14.21.3 || >=16"
+ },
+ "funding": {
+ "url": "https://paulmillr.com/funding/"
+ }
+ },
+ "node_modules/@noble/hashes": {
+ "version": "1.4.0",
+ "resolved": "https://registry.npmjs.org/@noble/hashes/-/hashes-1.4.0.tgz",
+ "integrity": "sha512-V1JJ1WTRUqHHrOSh597hURcMqVKVGL/ea3kv0gSnEdsEZ0/+VyPghM1lMNGc00z7CIQorSvbKpuJkxvuHbvdbg==",
+ "license": "MIT",
+ "optional": true,
+ "engines": {
+ "node": ">= 16"
+ },
+ "funding": {
+ "url": "https://paulmillr.com/funding/"
+ }
+ },
+ "node_modules/@phosphor-icons/webcomponents": {
+ "version": "2.1.5",
+ "resolved": "https://registry.npmjs.org/@phosphor-icons/webcomponents/-/webcomponents-2.1.5.tgz",
+ "integrity": "sha512-JcvQkZxvcX2jK+QCclm8+e8HXqtdFW9xV4/kk2aL9Y3dJA2oQVt+pzbv1orkumz3rfx4K9mn9fDoMr1He1yr7Q==",
+ "license": "MIT",
+ "dependencies": {
+ "lit": "^3"
+ }
+ },
+ "node_modules/@reown/appkit": {
+ "version": "1.8.14",
+ "resolved": "https://registry.npmjs.org/@reown/appkit/-/appkit-1.8.14.tgz",
+ "integrity": "sha512-y+Gl5SJ/iqh7QVrNkgtwsWyXnmSlodv5ICP5wWl5zdrAWO49kfopa5sULnKq9U1s/BgupHZAqhZFgqCTIrbaHQ==",
+ "hasInstallScript": true,
+ "license": "SEE LICENSE IN LICENSE.md",
+ "dependencies": {
+ "@reown/appkit-common": "1.8.14",
+ "@reown/appkit-controllers": "1.8.14",
+ "@reown/appkit-pay": "1.8.14",
+ "@reown/appkit-polyfills": "1.8.14",
+ "@reown/appkit-scaffold-ui": "1.8.14",
+ "@reown/appkit-ui": "1.8.14",
+ "@reown/appkit-utils": "1.8.14",
+ "@reown/appkit-wallet": "1.8.14",
+ "@walletconnect/universal-provider": "2.23.0",
+ "bs58": "6.0.0",
+ "semver": "7.7.2",
+ "valtio": "2.1.7",
+ "viem": ">=2.37.9"
+ },
+ "optionalDependencies": {
+ "@lit/react": "1.0.8"
+ }
+ },
+ "node_modules/@reown/appkit-adapter-ethers": {
+ "version": "1.8.14",
+ "resolved": "https://registry.npmjs.org/@reown/appkit-adapter-ethers/-/appkit-adapter-ethers-1.8.14.tgz",
+ "integrity": "sha512-eXdYeWf8OHd2rCldDVEh8ULxK7lktISD0kE8milegmCm7RU0lU6nyDrURUr8T2K9rcYqYjHXHOWXciAckHcWIg==",
+ "license": "SEE LICENSE IN LICENSE.md",
+ "dependencies": {
+ "@reown/appkit": "1.8.14",
+ "@reown/appkit-common": "1.8.14",
+ "@reown/appkit-controllers": "1.8.14",
+ "@reown/appkit-polyfills": "1.8.14",
+ "@reown/appkit-scaffold-ui": "1.8.14",
+ "@reown/appkit-utils": "1.8.14",
+ "@reown/appkit-wallet": "1.8.14",
+ "@walletconnect/universal-provider": "2.23.0",
+ "valtio": "2.1.7"
+ },
+ "peerDependencies": {
+ "@ethersproject/sha2": "5.8.0",
+ "ethers": ">=6"
+ }
+ },
+ "node_modules/@reown/appkit-common": {
+ "version": "1.8.14",
+ "resolved": "https://registry.npmjs.org/@reown/appkit-common/-/appkit-common-1.8.14.tgz",
+ "integrity": "sha512-0dRNtmy2e7f89Vvx3NCA09PD24DFT6S0nO6a/MBeFOj7SlvkvIh4SjBWG2x2F4L8KxCSCtQ5x6dWREmTONZjMA==",
+ "license": "SEE LICENSE IN LICENSE.md",
+ "dependencies": {
+ "big.js": "6.2.2",
+ "dayjs": "1.11.13",
+ "viem": ">=2.37.9"
+ }
+ },
+ "node_modules/@reown/appkit-controllers": {
+ "version": "1.8.14",
+ "resolved": "https://registry.npmjs.org/@reown/appkit-controllers/-/appkit-controllers-1.8.14.tgz",
+ "integrity": "sha512-1EF3xzwMwNfzZp1yd2InwA01EEDSylwHfX6MuGa1t5M6HevY4p1QnbnZISpYAQxN1xklCQsT3Zq5pQh6Ofg+Cg==",
+ "license": "SEE LICENSE IN LICENSE.md",
+ "dependencies": {
+ "@reown/appkit-common": "1.8.14",
+ "@reown/appkit-wallet": "1.8.14",
+ "@walletconnect/universal-provider": "2.23.0",
+ "valtio": "2.1.7",
+ "viem": ">=2.37.9"
+ }
+ },
+ "node_modules/@reown/appkit-pay": {
+ "version": "1.8.14",
+ "resolved": "https://registry.npmjs.org/@reown/appkit-pay/-/appkit-pay-1.8.14.tgz",
+ "integrity": "sha512-6ReXMGV47quXax8v1RQ8wFgclSd6M7MhX/WHJGwsjNHjFttQ6xWbPlYmjZxKgZ+k+K2TG/wo7oU0pF5Qu/L7Tw==",
+ "license": "SEE LICENSE IN LICENSE.md",
+ "dependencies": {
+ "@reown/appkit-common": "1.8.14",
+ "@reown/appkit-controllers": "1.8.14",
+ "@reown/appkit-ui": "1.8.14",
+ "@reown/appkit-utils": "1.8.14",
+ "lit": "3.3.0",
+ "valtio": "2.1.7"
+ }
+ },
+ "node_modules/@reown/appkit-polyfills": {
+ "version": "1.8.14",
+ "resolved": "https://registry.npmjs.org/@reown/appkit-polyfills/-/appkit-polyfills-1.8.14.tgz",
+ "integrity": "sha512-bMMdJpzxni6+FQpMqQomKvXoDy+t9uCunswuKCN33fMRXtXX0A3ui0WMGUFbQ4BKGmQcyUSt/MWid9hZ6KG8Fw==",
+ "license": "SEE LICENSE IN LICENSE.md",
+ "dependencies": {
+ "buffer": "6.0.3"
+ }
+ },
+ "node_modules/@reown/appkit-scaffold-ui": {
+ "version": "1.8.14",
+ "resolved": "https://registry.npmjs.org/@reown/appkit-scaffold-ui/-/appkit-scaffold-ui-1.8.14.tgz",
+ "integrity": "sha512-dhD9vodp1xsVs0yWP2V+b3XkcksHEHNzjNQvXBmTrfDDDpUYiScBTvjKmMRu/MgUxYRrFdxoMDIfAzjYUAwZuw==",
+ "license": "SEE LICENSE IN LICENSE.md",
+ "dependencies": {
+ "@reown/appkit-common": "1.8.14",
+ "@reown/appkit-controllers": "1.8.14",
+ "@reown/appkit-ui": "1.8.14",
+ "@reown/appkit-utils": "1.8.14",
+ "@reown/appkit-wallet": "1.8.14",
+ "lit": "3.3.0"
+ }
+ },
+ "node_modules/@reown/appkit-ui": {
+ "version": "1.8.14",
+ "resolved": "https://registry.npmjs.org/@reown/appkit-ui/-/appkit-ui-1.8.14.tgz",
+ "integrity": "sha512-vExTPCA8QghLaUG3mM2ghUN7IvTGy/dUbVxGYbCrIG/Y7Srshqp8O/vwnWk5RhktRwMNQuOXCRGXf2lWPiuNWQ==",
+ "license": "SEE LICENSE IN LICENSE.md",
+ "dependencies": {
+ "@phosphor-icons/webcomponents": "2.1.5",
+ "@reown/appkit-common": "1.8.14",
+ "@reown/appkit-controllers": "1.8.14",
+ "@reown/appkit-wallet": "1.8.14",
+ "lit": "3.3.0",
+ "qrcode": "1.5.3"
+ }
+ },
+ "node_modules/@reown/appkit-utils": {
+ "version": "1.8.14",
+ "resolved": "https://registry.npmjs.org/@reown/appkit-utils/-/appkit-utils-1.8.14.tgz",
+ "integrity": "sha512-SuXtX2pr8yilaAdTq7nEj2/ulKMUJAKUbtldAcsl3/acsqfD4oKHi13VJEKsHcGx/43sb1uDXA9yB60/g2+NAQ==",
+ "license": "SEE LICENSE IN LICENSE.md",
+ "dependencies": {
+ "@reown/appkit-common": "1.8.14",
+ "@reown/appkit-controllers": "1.8.14",
+ "@reown/appkit-polyfills": "1.8.14",
+ "@reown/appkit-wallet": "1.8.14",
+ "@wallet-standard/wallet": "1.1.0",
+ "@walletconnect/logger": "3.0.0",
+ "@walletconnect/universal-provider": "2.23.0",
+ "valtio": "2.1.7",
+ "viem": ">=2.37.9"
+ },
+ "optionalDependencies": {
+ "@base-org/account": "2.4.0",
+ "@safe-global/safe-apps-provider": "0.18.6",
+ "@safe-global/safe-apps-sdk": "9.1.0"
+ },
+ "peerDependencies": {
+ "valtio": "2.1.7"
+ }
+ },
+ "node_modules/@reown/appkit-wallet": {
+ "version": "1.8.14",
+ "resolved": "https://registry.npmjs.org/@reown/appkit-wallet/-/appkit-wallet-1.8.14.tgz",
+ "integrity": "sha512-p+BgGniq5tSIe98MIUxu1dYPKaccPN/OyYBf4n1M+TgItCrbxDUr7pkbBEqHb3KdyK+EQeTwz3wOJpPQFwHcEQ==",
+ "license": "SEE LICENSE IN LICENSE.md",
+ "dependencies": {
+ "@reown/appkit-common": "1.8.14",
+ "@reown/appkit-polyfills": "1.8.14",
+ "@walletconnect/logger": "3.0.0",
+ "zod": "3.22.4"
+ }
+ },
+ "node_modules/@reown/appkit-wallet/node_modules/zod": {
+ "version": "3.22.4",
+ "resolved": "https://registry.npmjs.org/zod/-/zod-3.22.4.tgz",
+ "integrity": "sha512-iC+8Io04lddc+mVqQ9AZ7OQ2MrUKGN+oIQyq1vemgt46jwCwLfhq7/pwnBnNXXXZb8VTVLKwp9EDkx+ryxIWmg==",
+ "license": "MIT",
+ "funding": {
+ "url": "https://github.com/sponsors/colinhacks"
+ }
+ },
+ "node_modules/@rolldown/pluginutils": {
+ "version": "1.0.0-beta.47",
+ "resolved": "https://registry.npmjs.org/@rolldown/pluginutils/-/pluginutils-1.0.0-beta.47.tgz",
+ "integrity": "sha512-8QagwMH3kNCuzD8EWL8R2YPW5e4OrHNSAHRFDdmFqEwEaD/KcNKjVoumo+gP2vW5eKB2UPbM6vTYiGZX0ixLnw==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/@rollup/rollup-android-arm-eabi": {
+ "version": "4.53.3",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.53.3.tgz",
+ "integrity": "sha512-mRSi+4cBjrRLoaal2PnqH82Wqyb+d3HsPUN/W+WslCXsZsyHa9ZeQQX/pQsZaVIWDkPcpV6jJ+3KLbTbgnwv8w==",
+ "cpu": [
+ "arm"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "android"
+ ]
+ },
+ "node_modules/@rollup/rollup-android-arm64": {
+ "version": "4.53.3",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.53.3.tgz",
+ "integrity": "sha512-CbDGaMpdE9sh7sCmTrTUyllhrg65t6SwhjlMJsLr+J8YjFuPmCEjbBSx4Z/e4SmDyH3aB5hGaJUP2ltV/vcs4w==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "android"
+ ]
+ },
+ "node_modules/@rollup/rollup-darwin-arm64": {
+ "version": "4.53.3",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.53.3.tgz",
+ "integrity": "sha512-Nr7SlQeqIBpOV6BHHGZgYBuSdanCXuw09hon14MGOLGmXAFYjx1wNvquVPmpZnl0tLjg25dEdr4IQ6GgyToCUA==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "darwin"
+ ]
+ },
+ "node_modules/@rollup/rollup-darwin-x64": {
+ "version": "4.53.3",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.53.3.tgz",
+ "integrity": "sha512-DZ8N4CSNfl965CmPktJ8oBnfYr3F8dTTNBQkRlffnUarJ2ohudQD17sZBa097J8xhQ26AwhHJ5mvUyQW8ddTsQ==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "darwin"
+ ]
+ },
+ "node_modules/@rollup/rollup-freebsd-arm64": {
+ "version": "4.53.3",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.53.3.tgz",
+ "integrity": "sha512-yMTrCrK92aGyi7GuDNtGn2sNW+Gdb4vErx4t3Gv/Tr+1zRb8ax4z8GWVRfr3Jw8zJWvpGHNpss3vVlbF58DZ4w==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "freebsd"
+ ]
+ },
+ "node_modules/@rollup/rollup-freebsd-x64": {
+ "version": "4.53.3",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.53.3.tgz",
+ "integrity": "sha512-lMfF8X7QhdQzseM6XaX0vbno2m3hlyZFhwcndRMw8fbAGUGL3WFMBdK0hbUBIUYcEcMhVLr1SIamDeuLBnXS+Q==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "freebsd"
+ ]
+ },
+ "node_modules/@rollup/rollup-linux-arm-gnueabihf": {
+ "version": "4.53.3",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.53.3.tgz",
+ "integrity": "sha512-k9oD15soC/Ln6d2Wv/JOFPzZXIAIFLp6B+i14KhxAfnq76ajt0EhYc5YPeX6W1xJkAdItcVT+JhKl1QZh44/qw==",
+ "cpu": [
+ "arm"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ]
+ },
+ "node_modules/@rollup/rollup-linux-arm-musleabihf": {
+ "version": "4.53.3",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.53.3.tgz",
+ "integrity": "sha512-vTNlKq+N6CK/8UktsrFuc+/7NlEYVxgaEgRXVUVK258Z5ymho29skzW1sutgYjqNnquGwVUObAaxae8rZ6YMhg==",
+ "cpu": [
+ "arm"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ]
+ },
+ "node_modules/@rollup/rollup-linux-arm64-gnu": {
+ "version": "4.53.3",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.53.3.tgz",
+ "integrity": "sha512-RGrFLWgMhSxRs/EWJMIFM1O5Mzuz3Xy3/mnxJp/5cVhZ2XoCAxJnmNsEyeMJtpK+wu0FJFWz+QF4mjCA7AUQ3w==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ]
+ },
+ "node_modules/@rollup/rollup-linux-arm64-musl": {
+ "version": "4.53.3",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.53.3.tgz",
+ "integrity": "sha512-kASyvfBEWYPEwe0Qv4nfu6pNkITLTb32p4yTgzFCocHnJLAHs+9LjUu9ONIhvfT/5lv4YS5muBHyuV84epBo/A==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ]
+ },
+ "node_modules/@rollup/rollup-linux-loong64-gnu": {
+ "version": "4.53.3",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loong64-gnu/-/rollup-linux-loong64-gnu-4.53.3.tgz",
+ "integrity": "sha512-JiuKcp2teLJwQ7vkJ95EwESWkNRFJD7TQgYmCnrPtlu50b4XvT5MOmurWNrCj3IFdyjBQ5p9vnrX4JM6I8OE7g==",
+ "cpu": [
+ "loong64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ]
+ },
+ "node_modules/@rollup/rollup-linux-ppc64-gnu": {
+ "version": "4.53.3",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-ppc64-gnu/-/rollup-linux-ppc64-gnu-4.53.3.tgz",
+ "integrity": "sha512-EoGSa8nd6d3T7zLuqdojxC20oBfNT8nexBbB/rkxgKj5T5vhpAQKKnD+h3UkoMuTyXkP5jTjK/ccNRmQrPNDuw==",
+ "cpu": [
+ "ppc64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ]
+ },
+ "node_modules/@rollup/rollup-linux-riscv64-gnu": {
+ "version": "4.53.3",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.53.3.tgz",
+ "integrity": "sha512-4s+Wped2IHXHPnAEbIB0YWBv7SDohqxobiiPA1FIWZpX+w9o2i4LezzH/NkFUl8LRci/8udci6cLq+jJQlh+0g==",
+ "cpu": [
+ "riscv64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ]
+ },
+ "node_modules/@rollup/rollup-linux-riscv64-musl": {
+ "version": "4.53.3",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-musl/-/rollup-linux-riscv64-musl-4.53.3.tgz",
+ "integrity": "sha512-68k2g7+0vs2u9CxDt5ktXTngsxOQkSEV/xBbwlqYcUrAVh6P9EgMZvFsnHy4SEiUl46Xf0IObWVbMvPrr2gw8A==",
+ "cpu": [
+ "riscv64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ]
+ },
+ "node_modules/@rollup/rollup-linux-s390x-gnu": {
+ "version": "4.53.3",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.53.3.tgz",
+ "integrity": "sha512-VYsFMpULAz87ZW6BVYw3I6sWesGpsP9OPcyKe8ofdg9LHxSbRMd7zrVrr5xi/3kMZtpWL/wC+UIJWJYVX5uTKg==",
+ "cpu": [
+ "s390x"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ]
+ },
+ "node_modules/@rollup/rollup-linux-x64-gnu": {
+ "version": "4.53.3",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.53.3.tgz",
+ "integrity": "sha512-3EhFi1FU6YL8HTUJZ51imGJWEX//ajQPfqWLI3BQq4TlvHy4X0MOr5q3D2Zof/ka0d5FNdPwZXm3Yyib/UEd+w==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ]
+ },
+ "node_modules/@rollup/rollup-linux-x64-musl": {
+ "version": "4.53.3",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.53.3.tgz",
+ "integrity": "sha512-eoROhjcc6HbZCJr+tvVT8X4fW3/5g/WkGvvmwz/88sDtSJzO7r/blvoBDgISDiCjDRZmHpwud7h+6Q9JxFwq1Q==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ]
+ },
+ "node_modules/@rollup/rollup-openharmony-arm64": {
+ "version": "4.53.3",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-openharmony-arm64/-/rollup-openharmony-arm64-4.53.3.tgz",
+ "integrity": "sha512-OueLAWgrNSPGAdUdIjSWXw+u/02BRTcnfw9PN41D2vq/JSEPnJnVuBgw18VkN8wcd4fjUs+jFHVM4t9+kBSNLw==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "openharmony"
+ ]
+ },
+ "node_modules/@rollup/rollup-win32-arm64-msvc": {
+ "version": "4.53.3",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.53.3.tgz",
+ "integrity": "sha512-GOFuKpsxR/whszbF/bzydebLiXIHSgsEUp6M0JI8dWvi+fFa1TD6YQa4aSZHtpmh2/uAlj/Dy+nmby3TJ3pkTw==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "win32"
+ ]
+ },
+ "node_modules/@rollup/rollup-win32-ia32-msvc": {
+ "version": "4.53.3",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.53.3.tgz",
+ "integrity": "sha512-iah+THLcBJdpfZ1TstDFbKNznlzoxa8fmnFYK4V67HvmuNYkVdAywJSoteUszvBQ9/HqN2+9AZghbajMsFT+oA==",
+ "cpu": [
+ "ia32"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "win32"
+ ]
+ },
+ "node_modules/@rollup/rollup-win32-x64-gnu": {
+ "version": "4.53.3",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-gnu/-/rollup-win32-x64-gnu-4.53.3.tgz",
+ "integrity": "sha512-J9QDiOIZlZLdcot5NXEepDkstocktoVjkaKUtqzgzpt2yWjGlbYiKyp05rWwk4nypbYUNoFAztEgixoLaSETkg==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "win32"
+ ]
+ },
+ "node_modules/@rollup/rollup-win32-x64-msvc": {
+ "version": "4.53.3",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.53.3.tgz",
+ "integrity": "sha512-UhTd8u31dXadv0MopwGgNOBpUVROFKWVQgAg5N1ESyCz8AuBcMqm4AuTjrwgQKGDfoFuz02EuMRHQIw/frmYKQ==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "win32"
+ ]
+ },
+ "node_modules/@safe-global/safe-apps-provider": {
+ "version": "0.18.6",
+ "resolved": "https://registry.npmjs.org/@safe-global/safe-apps-provider/-/safe-apps-provider-0.18.6.tgz",
+ "integrity": "sha512-4LhMmjPWlIO8TTDC2AwLk44XKXaK6hfBTWyljDm0HQ6TWlOEijVWNrt2s3OCVMSxlXAcEzYfqyu1daHZooTC2Q==",
+ "license": "MIT",
+ "optional": true,
+ "dependencies": {
+ "@safe-global/safe-apps-sdk": "^9.1.0",
+ "events": "^3.3.0"
+ }
+ },
+ "node_modules/@safe-global/safe-apps-sdk": {
+ "version": "9.1.0",
+ "resolved": "https://registry.npmjs.org/@safe-global/safe-apps-sdk/-/safe-apps-sdk-9.1.0.tgz",
+ "integrity": "sha512-N5p/ulfnnA2Pi2M3YeWjULeWbjo7ei22JwU/IXnhoHzKq3pYCN6ynL9mJBOlvDVv892EgLPCWCOwQk/uBT2v0Q==",
+ "license": "MIT",
+ "optional": true,
+ "dependencies": {
+ "@safe-global/safe-gateway-typescript-sdk": "^3.5.3",
+ "viem": "^2.1.1"
+ }
+ },
+ "node_modules/@safe-global/safe-gateway-typescript-sdk": {
+ "version": "3.23.1",
+ "resolved": "https://registry.npmjs.org/@safe-global/safe-gateway-typescript-sdk/-/safe-gateway-typescript-sdk-3.23.1.tgz",
+ "integrity": "sha512-6ORQfwtEJYpalCeVO21L4XXGSdbEMfyp2hEv6cP82afKXSwvse6d3sdelgaPWUxHIsFRkWvHDdzh8IyyKHZKxw==",
+ "license": "MIT",
+ "optional": true,
+ "engines": {
+ "node": ">=16"
+ }
+ },
+ "node_modules/@scure/base": {
+ "version": "1.2.6",
+ "resolved": "https://registry.npmjs.org/@scure/base/-/base-1.2.6.tgz",
+ "integrity": "sha512-g/nm5FgUa//MCj1gV09zTJTaM6KBAHqLN907YVQqf7zC49+DcO4B1so4ZX07Ef10Twr6nuqYEH9GEggFXA4Fmg==",
+ "license": "MIT",
+ "funding": {
+ "url": "https://paulmillr.com/funding/"
+ }
+ },
+ "node_modules/@scure/bip32": {
+ "version": "1.7.0",
+ "resolved": "https://registry.npmjs.org/@scure/bip32/-/bip32-1.7.0.tgz",
+ "integrity": "sha512-E4FFX/N3f4B80AKWp5dP6ow+flD1LQZo/w8UnLGYZO674jS6YnYeepycOOksv+vLPSpgN35wgKgy+ybfTb2SMw==",
+ "license": "MIT",
+ "dependencies": {
+ "@noble/curves": "~1.9.0",
+ "@noble/hashes": "~1.8.0",
+ "@scure/base": "~1.2.5"
+ },
+ "funding": {
+ "url": "https://paulmillr.com/funding/"
+ }
+ },
+ "node_modules/@scure/bip32/node_modules/@noble/hashes": {
+ "version": "1.8.0",
+ "resolved": "https://registry.npmjs.org/@noble/hashes/-/hashes-1.8.0.tgz",
+ "integrity": "sha512-jCs9ldd7NwzpgXDIf6P3+NrHh9/sD6CQdxHyjQI+h/6rDNo88ypBxxz45UDuZHz9r3tNz7N/VInSVoVdtXEI4A==",
+ "license": "MIT",
+ "engines": {
+ "node": "^14.21.3 || >=16"
+ },
+ "funding": {
+ "url": "https://paulmillr.com/funding/"
+ }
+ },
+ "node_modules/@scure/bip39": {
+ "version": "1.6.0",
+ "resolved": "https://registry.npmjs.org/@scure/bip39/-/bip39-1.6.0.tgz",
+ "integrity": "sha512-+lF0BbLiJNwVlev4eKelw1WWLaiKXw7sSl8T6FvBlWkdX+94aGJ4o8XjUdlyhTCjd8c+B3KT3JfS8P0bLRNU6A==",
+ "license": "MIT",
+ "dependencies": {
+ "@noble/hashes": "~1.8.0",
+ "@scure/base": "~1.2.5"
+ },
+ "funding": {
+ "url": "https://paulmillr.com/funding/"
+ }
+ },
+ "node_modules/@scure/bip39/node_modules/@noble/hashes": {
+ "version": "1.8.0",
+ "resolved": "https://registry.npmjs.org/@noble/hashes/-/hashes-1.8.0.tgz",
+ "integrity": "sha512-jCs9ldd7NwzpgXDIf6P3+NrHh9/sD6CQdxHyjQI+h/6rDNo88ypBxxz45UDuZHz9r3tNz7N/VInSVoVdtXEI4A==",
+ "license": "MIT",
+ "engines": {
+ "node": "^14.21.3 || >=16"
+ },
+ "funding": {
+ "url": "https://paulmillr.com/funding/"
+ }
+ },
+ "node_modules/@solana-program/system": {
+ "version": "0.8.1",
+ "resolved": "https://registry.npmjs.org/@solana-program/system/-/system-0.8.1.tgz",
+ "integrity": "sha512-71U9Mzdpw8HQtfgfJSL5xKZbLMRnza2Llsfk7gGnmg2waqK+o8MMH4YNma8xXS1UmOBptXIiNvoZ3p7cmOVktg==",
+ "license": "Apache-2.0",
+ "optional": true,
+ "peerDependencies": {
+ "@solana/kit": "^3.0"
+ }
+ },
+ "node_modules/@solana-program/token": {
+ "version": "0.6.0",
+ "resolved": "https://registry.npmjs.org/@solana-program/token/-/token-0.6.0.tgz",
+ "integrity": "sha512-omkZh4Tt9rre4wzWHNOhOEHyenXQku3xyc/UrKvShexA/Qlhza67q7uRwmwEDUs4QqoDBidSZPooOmepnA/jig==",
+ "license": "Apache-2.0",
+ "optional": true,
+ "peerDependencies": {
+ "@solana/kit": "^3.0"
+ }
+ },
+ "node_modules/@solana/accounts": {
+ "version": "3.0.3",
+ "resolved": "https://registry.npmjs.org/@solana/accounts/-/accounts-3.0.3.tgz",
+ "integrity": "sha512-KqlePrlZaHXfu8YQTCxN204ZuVm9o68CCcUr6l27MG2cuRUtEM1Ta0iR8JFkRUAEfZJC4Cu0ZDjK/v49loXjZQ==",
+ "license": "MIT",
+ "optional": true,
+ "dependencies": {
+ "@solana/addresses": "3.0.3",
+ "@solana/codecs-core": "3.0.3",
+ "@solana/codecs-strings": "3.0.3",
+ "@solana/errors": "3.0.3",
+ "@solana/rpc-spec": "3.0.3",
+ "@solana/rpc-types": "3.0.3"
+ },
+ "engines": {
+ "node": ">=20.18.0"
+ },
+ "peerDependencies": {
+ "typescript": ">=5.3.3"
+ }
+ },
+ "node_modules/@solana/addresses": {
+ "version": "3.0.3",
+ "resolved": "https://registry.npmjs.org/@solana/addresses/-/addresses-3.0.3.tgz",
+ "integrity": "sha512-AuMwKhJI89ANqiuJ/fawcwxNKkSeHH9CApZd2xelQQLS7X8uxAOovpcmEgiObQuiVP944s9ScGUT62Bdul9qYg==",
+ "license": "MIT",
+ "optional": true,
+ "dependencies": {
+ "@solana/assertions": "3.0.3",
+ "@solana/codecs-core": "3.0.3",
+ "@solana/codecs-strings": "3.0.3",
+ "@solana/errors": "3.0.3",
+ "@solana/nominal-types": "3.0.3"
+ },
+ "engines": {
+ "node": ">=20.18.0"
+ },
+ "peerDependencies": {
+ "typescript": ">=5.3.3"
+ }
+ },
+ "node_modules/@solana/assertions": {
+ "version": "3.0.3",
+ "resolved": "https://registry.npmjs.org/@solana/assertions/-/assertions-3.0.3.tgz",
+ "integrity": "sha512-2qspxdbWp2y62dfCIlqeWQr4g+hE8FYSSwcaP6itwMwGRb8393yDGCJfI/znuzJh6m/XVWhMHIgFgsBwnevCmg==",
+ "license": "MIT",
+ "optional": true,
+ "dependencies": {
+ "@solana/errors": "3.0.3"
+ },
+ "engines": {
+ "node": ">=20.18.0"
+ },
+ "peerDependencies": {
+ "typescript": ">=5.3.3"
+ }
+ },
+ "node_modules/@solana/buffer-layout": {
+ "version": "4.0.1",
+ "resolved": "https://registry.npmjs.org/@solana/buffer-layout/-/buffer-layout-4.0.1.tgz",
+ "integrity": "sha512-E1ImOIAD1tBZFRdjeM4/pzTiTApC0AOBGwyAMS4fwIodCWArzJ3DWdoh8cKxeFM2fElkxBh2Aqts1BPC373rHA==",
+ "license": "MIT",
+ "optional": true,
+ "dependencies": {
+ "buffer": "~6.0.3"
+ },
+ "engines": {
+ "node": ">=5.10"
+ }
+ },
+ "node_modules/@solana/codecs": {
+ "version": "3.0.3",
+ "resolved": "https://registry.npmjs.org/@solana/codecs/-/codecs-3.0.3.tgz",
+ "integrity": "sha512-GOHwTlIQsCoJx9Ryr6cEf0FHKAQ7pY4aO4xgncAftrv0lveTQ1rPP2inQ1QT0gJllsIa8nwbfXAADs9nNJxQDA==",
+ "license": "MIT",
+ "optional": true,
+ "dependencies": {
+ "@solana/codecs-core": "3.0.3",
+ "@solana/codecs-data-structures": "3.0.3",
+ "@solana/codecs-numbers": "3.0.3",
+ "@solana/codecs-strings": "3.0.3",
+ "@solana/options": "3.0.3"
+ },
+ "engines": {
+ "node": ">=20.18.0"
+ },
+ "peerDependencies": {
+ "typescript": ">=5.3.3"
+ }
+ },
+ "node_modules/@solana/codecs-core": {
+ "version": "3.0.3",
+ "resolved": "https://registry.npmjs.org/@solana/codecs-core/-/codecs-core-3.0.3.tgz",
+ "integrity": "sha512-emKykJ3h1DmnDOY29Uv9eJXP8E/FHzvlUBJ6te+5EbKdFjj7vdlKYPfDxOI6iGdXTY+YC/ELtbNBh6QwF2uEDQ==",
+ "license": "MIT",
+ "optional": true,
+ "dependencies": {
+ "@solana/errors": "3.0.3"
+ },
+ "engines": {
+ "node": ">=20.18.0"
+ },
+ "peerDependencies": {
+ "typescript": ">=5.3.3"
+ }
+ },
+ "node_modules/@solana/codecs-data-structures": {
+ "version": "3.0.3",
+ "resolved": "https://registry.npmjs.org/@solana/codecs-data-structures/-/codecs-data-structures-3.0.3.tgz",
+ "integrity": "sha512-R15cLp8riJvToXziW8lP6AMSwsztGhEnwgyGmll32Mo0Yjq+hduW2/fJrA/TJs6tA/OgTzMQjlxgk009EqZHCw==",
+ "license": "MIT",
+ "optional": true,
+ "dependencies": {
+ "@solana/codecs-core": "3.0.3",
+ "@solana/codecs-numbers": "3.0.3",
+ "@solana/errors": "3.0.3"
+ },
+ "engines": {
+ "node": ">=20.18.0"
+ },
+ "peerDependencies": {
+ "typescript": ">=5.3.3"
+ }
+ },
+ "node_modules/@solana/codecs-numbers": {
+ "version": "3.0.3",
+ "resolved": "https://registry.npmjs.org/@solana/codecs-numbers/-/codecs-numbers-3.0.3.tgz",
+ "integrity": "sha512-pfXkH9J0glrM8qj6389GAn30+cJOxzXLR2FsPOHCUMXrqLhGjMMZAWhsQkpOQ37SGc/7EiQsT/gmyGC7gxHqJQ==",
+ "license": "MIT",
+ "optional": true,
+ "dependencies": {
+ "@solana/codecs-core": "3.0.3",
+ "@solana/errors": "3.0.3"
+ },
+ "engines": {
+ "node": ">=20.18.0"
+ },
+ "peerDependencies": {
+ "typescript": ">=5.3.3"
+ }
+ },
+ "node_modules/@solana/codecs-strings": {
+ "version": "3.0.3",
+ "resolved": "https://registry.npmjs.org/@solana/codecs-strings/-/codecs-strings-3.0.3.tgz",
+ "integrity": "sha512-VHBXnnTVtcQ1j+7Vrz+qSYo38no+jiHRdGnhFspRXEHNJbllzwKqgBE7YN3qoIXH+MKxgJUcwO5KHmdzf8Wn2A==",
+ "license": "MIT",
+ "optional": true,
+ "dependencies": {
+ "@solana/codecs-core": "3.0.3",
+ "@solana/codecs-numbers": "3.0.3",
+ "@solana/errors": "3.0.3"
+ },
+ "engines": {
+ "node": ">=20.18.0"
+ },
+ "peerDependencies": {
+ "fastestsmallesttextencoderdecoder": "^1.0.22",
+ "typescript": ">=5.3.3"
+ }
+ },
+ "node_modules/@solana/errors": {
+ "version": "3.0.3",
+ "resolved": "https://registry.npmjs.org/@solana/errors/-/errors-3.0.3.tgz",
+ "integrity": "sha512-1l84xJlHNva6io62PcYfUamwWlc0eM95nHgCrKX0g0cLoC6D6QHYPCEbEVkR+C5UtP9JDgyQM8MFiv+Ei5tO9Q==",
+ "license": "MIT",
+ "optional": true,
+ "dependencies": {
+ "chalk": "5.6.2",
+ "commander": "14.0.0"
+ },
+ "bin": {
+ "errors": "bin/cli.mjs"
+ },
+ "engines": {
+ "node": ">=20.18.0"
+ },
+ "peerDependencies": {
+ "typescript": ">=5.3.3"
+ }
+ },
+ "node_modules/@solana/fast-stable-stringify": {
+ "version": "3.0.3",
+ "resolved": "https://registry.npmjs.org/@solana/fast-stable-stringify/-/fast-stable-stringify-3.0.3.tgz",
+ "integrity": "sha512-ED0pxB6lSEYvg+vOd5hcuQrgzEDnOrURFgp1ZOY+lQhJkQU6xo+P829NcJZQVP1rdU2/YQPAKJKEseyfe9VMIw==",
+ "license": "MIT",
+ "optional": true,
+ "engines": {
+ "node": ">=20.18.0"
+ },
+ "peerDependencies": {
+ "typescript": ">=5.3.3"
+ }
+ },
+ "node_modules/@solana/functional": {
+ "version": "3.0.3",
+ "resolved": "https://registry.npmjs.org/@solana/functional/-/functional-3.0.3.tgz",
+ "integrity": "sha512-2qX1kKANn8995vOOh5S9AmF4ItGZcfbny0w28Eqy8AFh+GMnSDN4gqpmV2LvxBI9HibXZptGH3RVOMk82h1Mpw==",
+ "license": "MIT",
+ "optional": true,
+ "engines": {
+ "node": ">=20.18.0"
+ },
+ "peerDependencies": {
+ "typescript": ">=5.3.3"
+ }
+ },
+ "node_modules/@solana/instruction-plans": {
+ "version": "3.0.3",
+ "resolved": "https://registry.npmjs.org/@solana/instruction-plans/-/instruction-plans-3.0.3.tgz",
+ "integrity": "sha512-eqoaPtWtmLTTpdvbt4BZF5H6FIlJtXi9H7qLOM1dLYonkOX2Ncezx5NDCZ9tMb2qxVMF4IocYsQnNSnMfjQF1w==",
+ "license": "MIT",
+ "optional": true,
+ "dependencies": {
+ "@solana/errors": "3.0.3",
+ "@solana/instructions": "3.0.3",
+ "@solana/promises": "3.0.3",
+ "@solana/transaction-messages": "3.0.3",
+ "@solana/transactions": "3.0.3"
+ },
+ "engines": {
+ "node": ">=20.18.0"
+ },
+ "peerDependencies": {
+ "typescript": ">=5.3.3"
+ }
+ },
+ "node_modules/@solana/instructions": {
+ "version": "3.0.3",
+ "resolved": "https://registry.npmjs.org/@solana/instructions/-/instructions-3.0.3.tgz",
+ "integrity": "sha512-4csIi8YUDb5j/J+gDzmYtOvq7ZWLbCxj4t0xKn+fPrBk/FD2pK29KVT3Fu7j4Lh1/ojunQUP9X4NHwUexY3PnA==",
+ "license": "MIT",
+ "optional": true,
+ "dependencies": {
+ "@solana/codecs-core": "3.0.3",
+ "@solana/errors": "3.0.3"
+ },
+ "engines": {
+ "node": ">=20.18.0"
+ },
+ "peerDependencies": {
+ "typescript": ">=5.3.3"
+ }
+ },
+ "node_modules/@solana/keys": {
+ "version": "3.0.3",
+ "resolved": "https://registry.npmjs.org/@solana/keys/-/keys-3.0.3.tgz",
+ "integrity": "sha512-tp8oK9tMadtSIc4vF4aXXWkPd4oU5XPW8nf28NgrGDWGt25fUHIydKjkf2hPtMt9i1WfRyQZ33B5P3dnsNqcPQ==",
+ "license": "MIT",
+ "optional": true,
+ "dependencies": {
+ "@solana/assertions": "3.0.3",
+ "@solana/codecs-core": "3.0.3",
+ "@solana/codecs-strings": "3.0.3",
+ "@solana/errors": "3.0.3",
+ "@solana/nominal-types": "3.0.3"
+ },
+ "engines": {
+ "node": ">=20.18.0"
+ },
+ "peerDependencies": {
+ "typescript": ">=5.3.3"
+ }
+ },
+ "node_modules/@solana/nominal-types": {
+ "version": "3.0.3",
+ "resolved": "https://registry.npmjs.org/@solana/nominal-types/-/nominal-types-3.0.3.tgz",
+ "integrity": "sha512-aZavCiexeUAoMHRQg4s1AHkH3wscbOb70diyfjhwZVgFz1uUsFez7csPp9tNFkNolnadVb2gky7yBk3IImQJ6A==",
+ "license": "MIT",
+ "optional": true,
+ "engines": {
+ "node": ">=20.18.0"
+ },
+ "peerDependencies": {
+ "typescript": ">=5.3.3"
+ }
+ },
+ "node_modules/@solana/options": {
+ "version": "3.0.3",
+ "resolved": "https://registry.npmjs.org/@solana/options/-/options-3.0.3.tgz",
+ "integrity": "sha512-jarsmnQ63RN0JPC5j9sgUat07NrL9PC71XU7pUItd6LOHtu4+wJMio3l5mT0DHVfkfbFLL6iI6+QmXSVhTNF3g==",
+ "license": "MIT",
+ "optional": true,
+ "dependencies": {
+ "@solana/codecs-core": "3.0.3",
+ "@solana/codecs-data-structures": "3.0.3",
+ "@solana/codecs-numbers": "3.0.3",
+ "@solana/codecs-strings": "3.0.3",
+ "@solana/errors": "3.0.3"
+ },
+ "engines": {
+ "node": ">=20.18.0"
+ },
+ "peerDependencies": {
+ "typescript": ">=5.3.3"
+ }
+ },
+ "node_modules/@solana/programs": {
+ "version": "3.0.3",
+ "resolved": "https://registry.npmjs.org/@solana/programs/-/programs-3.0.3.tgz",
+ "integrity": "sha512-JZlVE3/AeSNDuH3aEzCZoDu8GTXkMpGXxf93zXLzbxfxhiQ/kHrReN4XE/JWZ/uGWbaFZGR5B3UtdN2QsoZL7w==",
+ "license": "MIT",
+ "optional": true,
+ "dependencies": {
+ "@solana/addresses": "3.0.3",
+ "@solana/errors": "3.0.3"
+ },
+ "engines": {
+ "node": ">=20.18.0"
+ },
+ "peerDependencies": {
+ "typescript": ">=5.3.3"
+ }
+ },
+ "node_modules/@solana/promises": {
+ "version": "3.0.3",
+ "resolved": "https://registry.npmjs.org/@solana/promises/-/promises-3.0.3.tgz",
+ "integrity": "sha512-K+UflGBVxj30XQMHTylHHZJdKH5QG3oj5k2s42GrZ/Wbu72oapVJySMBgpK45+p90t8/LEqV6rRPyTXlet9J+Q==",
+ "license": "MIT",
+ "optional": true,
+ "engines": {
+ "node": ">=20.18.0"
+ },
+ "peerDependencies": {
+ "typescript": ">=5.3.3"
+ }
+ },
+ "node_modules/@solana/rpc": {
+ "version": "3.0.3",
+ "resolved": "https://registry.npmjs.org/@solana/rpc/-/rpc-3.0.3.tgz",
+ "integrity": "sha512-3oukAaLK78GegkKcm6iNmRnO4mFeNz+BMvA8T56oizoBNKiRVEq/6DFzVX/LkmZ+wvD601pAB3uCdrTPcC0YKQ==",
+ "license": "MIT",
+ "optional": true,
+ "dependencies": {
+ "@solana/errors": "3.0.3",
+ "@solana/fast-stable-stringify": "3.0.3",
+ "@solana/functional": "3.0.3",
+ "@solana/rpc-api": "3.0.3",
+ "@solana/rpc-spec": "3.0.3",
+ "@solana/rpc-spec-types": "3.0.3",
+ "@solana/rpc-transformers": "3.0.3",
+ "@solana/rpc-transport-http": "3.0.3",
+ "@solana/rpc-types": "3.0.3"
+ },
+ "engines": {
+ "node": ">=20.18.0"
+ },
+ "peerDependencies": {
+ "typescript": ">=5.3.3"
+ }
+ },
+ "node_modules/@solana/rpc-api": {
+ "version": "3.0.3",
+ "resolved": "https://registry.npmjs.org/@solana/rpc-api/-/rpc-api-3.0.3.tgz",
+ "integrity": "sha512-Yym9/Ama62OY69rAZgbOCAy1QlqaWAyb0VlqFuwSaZV1pkFCCFSwWEJEsiN1n8pb2ZP+RtwNvmYixvWizx9yvA==",
+ "license": "MIT",
+ "optional": true,
+ "dependencies": {
+ "@solana/addresses": "3.0.3",
+ "@solana/codecs-core": "3.0.3",
+ "@solana/codecs-strings": "3.0.3",
+ "@solana/errors": "3.0.3",
+ "@solana/keys": "3.0.3",
+ "@solana/rpc-parsed-types": "3.0.3",
+ "@solana/rpc-spec": "3.0.3",
+ "@solana/rpc-transformers": "3.0.3",
+ "@solana/rpc-types": "3.0.3",
+ "@solana/transaction-messages": "3.0.3",
+ "@solana/transactions": "3.0.3"
+ },
+ "engines": {
+ "node": ">=20.18.0"
+ },
+ "peerDependencies": {
+ "typescript": ">=5.3.3"
+ }
+ },
+ "node_modules/@solana/rpc-parsed-types": {
+ "version": "3.0.3",
+ "resolved": "https://registry.npmjs.org/@solana/rpc-parsed-types/-/rpc-parsed-types-3.0.3.tgz",
+ "integrity": "sha512-/koM05IM2fU91kYDQxXil3VBNlOfcP+gXE0js1sdGz8KonGuLsF61CiKB5xt6u1KEXhRyDdXYLjf63JarL4Ozg==",
+ "license": "MIT",
+ "optional": true,
+ "engines": {
+ "node": ">=20.18.0"
+ },
+ "peerDependencies": {
+ "typescript": ">=5.3.3"
+ }
+ },
+ "node_modules/@solana/rpc-spec": {
+ "version": "3.0.3",
+ "resolved": "https://registry.npmjs.org/@solana/rpc-spec/-/rpc-spec-3.0.3.tgz",
+ "integrity": "sha512-MZn5/8BebB6MQ4Gstw6zyfWsFAZYAyLzMK+AUf/rSfT8tPmWiJ/mcxnxqOXvFup/l6D67U8pyGpIoFqwCeZqqA==",
+ "license": "MIT",
+ "optional": true,
+ "dependencies": {
+ "@solana/errors": "3.0.3",
+ "@solana/rpc-spec-types": "3.0.3"
+ },
+ "engines": {
+ "node": ">=20.18.0"
+ },
+ "peerDependencies": {
+ "typescript": ">=5.3.3"
+ }
+ },
+ "node_modules/@solana/rpc-spec-types": {
+ "version": "3.0.3",
+ "resolved": "https://registry.npmjs.org/@solana/rpc-spec-types/-/rpc-spec-types-3.0.3.tgz",
+ "integrity": "sha512-A6Jt8SRRetnN3CeGAvGJxigA9zYRslGgWcSjueAZGvPX+MesFxEUjSWZCfl+FogVFvwkqfkgQZQbPAGZQFJQ6Q==",
+ "license": "MIT",
+ "optional": true,
+ "engines": {
+ "node": ">=20.18.0"
+ },
+ "peerDependencies": {
+ "typescript": ">=5.3.3"
+ }
+ },
+ "node_modules/@solana/rpc-subscriptions": {
+ "version": "3.0.3",
+ "resolved": "https://registry.npmjs.org/@solana/rpc-subscriptions/-/rpc-subscriptions-3.0.3.tgz",
+ "integrity": "sha512-LRvz6NaqvtsYFd32KwZ+rwYQ9XCs+DWjV8BvBLsJpt9/NWSuHf/7Sy/vvP6qtKxut692H/TMvHnC4iulg0WmiQ==",
+ "license": "MIT",
+ "optional": true,
+ "dependencies": {
+ "@solana/errors": "3.0.3",
+ "@solana/fast-stable-stringify": "3.0.3",
+ "@solana/functional": "3.0.3",
+ "@solana/promises": "3.0.3",
+ "@solana/rpc-spec-types": "3.0.3",
+ "@solana/rpc-subscriptions-api": "3.0.3",
+ "@solana/rpc-subscriptions-channel-websocket": "3.0.3",
+ "@solana/rpc-subscriptions-spec": "3.0.3",
+ "@solana/rpc-transformers": "3.0.3",
+ "@solana/rpc-types": "3.0.3",
+ "@solana/subscribable": "3.0.3"
+ },
+ "engines": {
+ "node": ">=20.18.0"
+ },
+ "peerDependencies": {
+ "typescript": ">=5.3.3"
+ }
+ },
+ "node_modules/@solana/rpc-subscriptions-api": {
+ "version": "3.0.3",
+ "resolved": "https://registry.npmjs.org/@solana/rpc-subscriptions-api/-/rpc-subscriptions-api-3.0.3.tgz",
+ "integrity": "sha512-MGgVK3PUS15qsjuhimpzGZrKD/CTTvS0mAlQ0Jw84zsr1RJVdQJK/F0igu07BVd172eTZL8d90NoAQ3dahW5pA==",
+ "license": "MIT",
+ "optional": true,
+ "dependencies": {
+ "@solana/addresses": "3.0.3",
+ "@solana/keys": "3.0.3",
+ "@solana/rpc-subscriptions-spec": "3.0.3",
+ "@solana/rpc-transformers": "3.0.3",
+ "@solana/rpc-types": "3.0.3",
+ "@solana/transaction-messages": "3.0.3",
+ "@solana/transactions": "3.0.3"
+ },
+ "engines": {
+ "node": ">=20.18.0"
+ },
+ "peerDependencies": {
+ "typescript": ">=5.3.3"
+ }
+ },
+ "node_modules/@solana/rpc-subscriptions-channel-websocket": {
+ "version": "3.0.3",
+ "resolved": "https://registry.npmjs.org/@solana/rpc-subscriptions-channel-websocket/-/rpc-subscriptions-channel-websocket-3.0.3.tgz",
+ "integrity": "sha512-zUzUlb8Cwnw+SHlsLrSqyBRtOJKGc+FvSNJo/vWAkLShoV0wUDMPv7VvhTngJx3B/3ANfrOZ4i08i9QfYPAvpQ==",
+ "license": "MIT",
+ "optional": true,
+ "dependencies": {
+ "@solana/errors": "3.0.3",
+ "@solana/functional": "3.0.3",
+ "@solana/rpc-subscriptions-spec": "3.0.3",
+ "@solana/subscribable": "3.0.3"
+ },
+ "engines": {
+ "node": ">=20.18.0"
+ },
+ "peerDependencies": {
+ "typescript": ">=5.3.3",
+ "ws": "^8.18.0"
+ }
+ },
+ "node_modules/@solana/rpc-subscriptions-spec": {
+ "version": "3.0.3",
+ "resolved": "https://registry.npmjs.org/@solana/rpc-subscriptions-spec/-/rpc-subscriptions-spec-3.0.3.tgz",
+ "integrity": "sha512-9KpQ32OBJWS85mn6q3gkM0AjQe1LKYlMU7gpJRrla/lvXxNLhI95tz5K6StctpUreVmRWTVkNamHE69uUQyY8A==",
+ "license": "MIT",
+ "optional": true,
+ "dependencies": {
+ "@solana/errors": "3.0.3",
+ "@solana/promises": "3.0.3",
+ "@solana/rpc-spec-types": "3.0.3",
+ "@solana/subscribable": "3.0.3"
+ },
+ "engines": {
+ "node": ">=20.18.0"
+ },
+ "peerDependencies": {
+ "typescript": ">=5.3.3"
+ }
+ },
+ "node_modules/@solana/rpc-transformers": {
+ "version": "3.0.3",
+ "resolved": "https://registry.npmjs.org/@solana/rpc-transformers/-/rpc-transformers-3.0.3.tgz",
+ "integrity": "sha512-lzdaZM/dG3s19Tsk4mkJA5JBoS1eX9DnD7z62gkDwrwJDkDBzkAJT9aLcsYFfTmwTfIp6uU2UPgGYc97i1wezw==",
+ "license": "MIT",
+ "optional": true,
+ "dependencies": {
+ "@solana/errors": "3.0.3",
+ "@solana/functional": "3.0.3",
+ "@solana/nominal-types": "3.0.3",
+ "@solana/rpc-spec-types": "3.0.3",
+ "@solana/rpc-types": "3.0.3"
+ },
+ "engines": {
+ "node": ">=20.18.0"
+ },
+ "peerDependencies": {
+ "typescript": ">=5.3.3"
+ }
+ },
+ "node_modules/@solana/rpc-transport-http": {
+ "version": "3.0.3",
+ "resolved": "https://registry.npmjs.org/@solana/rpc-transport-http/-/rpc-transport-http-3.0.3.tgz",
+ "integrity": "sha512-bIXFwr2LR5A97Z46dI661MJPbHnPfcShBjFzOS/8Rnr8P4ho3j/9EUtjDrsqoxGJT3SLWj5OlyXAlaDAvVTOUQ==",
+ "license": "MIT",
+ "optional": true,
+ "dependencies": {
+ "@solana/errors": "3.0.3",
+ "@solana/rpc-spec": "3.0.3",
+ "@solana/rpc-spec-types": "3.0.3",
+ "undici-types": "^7.15.0"
+ },
+ "engines": {
+ "node": ">=20.18.0"
+ },
+ "peerDependencies": {
+ "typescript": ">=5.3.3"
+ }
+ },
+ "node_modules/@solana/rpc-types": {
+ "version": "3.0.3",
+ "resolved": "https://registry.npmjs.org/@solana/rpc-types/-/rpc-types-3.0.3.tgz",
+ "integrity": "sha512-petWQ5xSny9UfmC3Qp2owyhNU0w9SyBww4+v7tSVyXMcCC9v6j/XsqTeimH1S0qQUllnv0/FY83ohFaxofmZ6Q==",
+ "license": "MIT",
+ "optional": true,
+ "dependencies": {
+ "@solana/addresses": "3.0.3",
+ "@solana/codecs-core": "3.0.3",
+ "@solana/codecs-numbers": "3.0.3",
+ "@solana/codecs-strings": "3.0.3",
+ "@solana/errors": "3.0.3",
+ "@solana/nominal-types": "3.0.3"
+ },
+ "engines": {
+ "node": ">=20.18.0"
+ },
+ "peerDependencies": {
+ "typescript": ">=5.3.3"
+ }
+ },
+ "node_modules/@solana/signers": {
+ "version": "3.0.3",
+ "resolved": "https://registry.npmjs.org/@solana/signers/-/signers-3.0.3.tgz",
+ "integrity": "sha512-UwCd/uPYTZiwd283JKVyOWLLN5sIgMBqGDyUmNU3vo9hcmXKv5ZGm/9TvwMY2z35sXWuIOcj7etxJ8OoWc/ObQ==",
+ "license": "MIT",
+ "optional": true,
+ "dependencies": {
+ "@solana/addresses": "3.0.3",
+ "@solana/codecs-core": "3.0.3",
+ "@solana/errors": "3.0.3",
+ "@solana/instructions": "3.0.3",
+ "@solana/keys": "3.0.3",
+ "@solana/nominal-types": "3.0.3",
+ "@solana/transaction-messages": "3.0.3",
+ "@solana/transactions": "3.0.3"
+ },
+ "engines": {
+ "node": ">=20.18.0"
+ },
+ "peerDependencies": {
+ "typescript": ">=5.3.3"
+ }
+ },
+ "node_modules/@solana/subscribable": {
+ "version": "3.0.3",
+ "resolved": "https://registry.npmjs.org/@solana/subscribable/-/subscribable-3.0.3.tgz",
+ "integrity": "sha512-FJ27LKGHLQ5GGttPvTOLQDLrrOZEgvaJhB7yYaHAhPk25+p+erBaQpjePhfkMyUbL1FQbxn1SUJmS6jUuaPjlQ==",
+ "license": "MIT",
+ "optional": true,
+ "dependencies": {
+ "@solana/errors": "3.0.3"
+ },
+ "engines": {
+ "node": ">=20.18.0"
+ },
+ "peerDependencies": {
+ "typescript": ">=5.3.3"
+ }
+ },
+ "node_modules/@solana/sysvars": {
+ "version": "3.0.3",
+ "resolved": "https://registry.npmjs.org/@solana/sysvars/-/sysvars-3.0.3.tgz",
+ "integrity": "sha512-GnHew+QeKCs2f9ow+20swEJMH4mDfJA/QhtPgOPTYQx/z69J4IieYJ7fZenSHnA//lJ45fVdNdmy1trypvPLBQ==",
+ "license": "MIT",
+ "optional": true,
+ "dependencies": {
+ "@solana/accounts": "3.0.3",
+ "@solana/codecs": "3.0.3",
+ "@solana/errors": "3.0.3",
+ "@solana/rpc-types": "3.0.3"
+ },
+ "engines": {
+ "node": ">=20.18.0"
+ },
+ "peerDependencies": {
+ "typescript": ">=5.3.3"
+ }
+ },
+ "node_modules/@solana/transaction-confirmation": {
+ "version": "3.0.3",
+ "resolved": "https://registry.npmjs.org/@solana/transaction-confirmation/-/transaction-confirmation-3.0.3.tgz",
+ "integrity": "sha512-dXx0OLtR95LMuARgi2dDQlL1QYmk56DOou5q9wKymmeV3JTvfDExeWXnOgjRBBq/dEfj4ugN1aZuTaS18UirFw==",
+ "license": "MIT",
+ "optional": true,
+ "dependencies": {
+ "@solana/addresses": "3.0.3",
+ "@solana/codecs-strings": "3.0.3",
+ "@solana/errors": "3.0.3",
+ "@solana/keys": "3.0.3",
+ "@solana/promises": "3.0.3",
+ "@solana/rpc": "3.0.3",
+ "@solana/rpc-subscriptions": "3.0.3",
+ "@solana/rpc-types": "3.0.3",
+ "@solana/transaction-messages": "3.0.3",
+ "@solana/transactions": "3.0.3"
+ },
+ "engines": {
+ "node": ">=20.18.0"
+ },
+ "peerDependencies": {
+ "typescript": ">=5.3.3"
+ }
+ },
+ "node_modules/@solana/transaction-messages": {
+ "version": "3.0.3",
+ "resolved": "https://registry.npmjs.org/@solana/transaction-messages/-/transaction-messages-3.0.3.tgz",
+ "integrity": "sha512-s+6NWRnBhnnjFWV4x2tzBzoWa6e5LiIxIvJlWwVQBFkc8fMGY04w7jkFh0PM08t/QFKeXBEWkyBDa/TFYdkWug==",
+ "license": "MIT",
+ "optional": true,
+ "dependencies": {
+ "@solana/addresses": "3.0.3",
+ "@solana/codecs-core": "3.0.3",
+ "@solana/codecs-data-structures": "3.0.3",
+ "@solana/codecs-numbers": "3.0.3",
+ "@solana/errors": "3.0.3",
+ "@solana/functional": "3.0.3",
+ "@solana/instructions": "3.0.3",
+ "@solana/nominal-types": "3.0.3",
+ "@solana/rpc-types": "3.0.3"
+ },
+ "engines": {
+ "node": ">=20.18.0"
+ },
+ "peerDependencies": {
+ "typescript": ">=5.3.3"
+ }
+ },
+ "node_modules/@solana/transactions": {
+ "version": "3.0.3",
+ "resolved": "https://registry.npmjs.org/@solana/transactions/-/transactions-3.0.3.tgz",
+ "integrity": "sha512-iMX+n9j4ON7H1nKlWEbMqMOpKYC6yVGxKKmWHT1KdLRG7v+03I4DnDeFoI+Zmw56FA+7Bbne8jwwX60Q1vk/MQ==",
+ "license": "MIT",
+ "optional": true,
+ "dependencies": {
+ "@solana/addresses": "3.0.3",
+ "@solana/codecs-core": "3.0.3",
+ "@solana/codecs-data-structures": "3.0.3",
+ "@solana/codecs-numbers": "3.0.3",
+ "@solana/codecs-strings": "3.0.3",
+ "@solana/errors": "3.0.3",
+ "@solana/functional": "3.0.3",
+ "@solana/instructions": "3.0.3",
+ "@solana/keys": "3.0.3",
+ "@solana/nominal-types": "3.0.3",
+ "@solana/rpc-types": "3.0.3",
+ "@solana/transaction-messages": "3.0.3"
+ },
+ "engines": {
+ "node": ">=20.18.0"
+ },
+ "peerDependencies": {
+ "typescript": ">=5.3.3"
+ }
+ },
+ "node_modules/@solana/web3.js": {
+ "version": "1.98.4",
+ "resolved": "https://registry.npmjs.org/@solana/web3.js/-/web3.js-1.98.4.tgz",
+ "integrity": "sha512-vv9lfnvjUsRiq//+j5pBdXig0IQdtzA0BRZ3bXEP4KaIyF1CcaydWqgyzQgfZMNIsWNWmG+AUHwPy4AHOD6gpw==",
+ "license": "MIT",
+ "optional": true,
+ "dependencies": {
+ "@babel/runtime": "^7.25.0",
+ "@noble/curves": "^1.4.2",
+ "@noble/hashes": "^1.4.0",
+ "@solana/buffer-layout": "^4.0.1",
+ "@solana/codecs-numbers": "^2.1.0",
+ "agentkeepalive": "^4.5.0",
+ "bn.js": "^5.2.1",
+ "borsh": "^0.7.0",
+ "bs58": "^4.0.1",
+ "buffer": "6.0.3",
+ "fast-stable-stringify": "^1.0.0",
+ "jayson": "^4.1.1",
+ "node-fetch": "^2.7.0",
+ "rpc-websockets": "^9.0.2",
+ "superstruct": "^2.0.2"
+ }
+ },
+ "node_modules/@solana/web3.js/node_modules/@solana/codecs-core": {
+ "version": "2.3.0",
+ "resolved": "https://registry.npmjs.org/@solana/codecs-core/-/codecs-core-2.3.0.tgz",
+ "integrity": "sha512-oG+VZzN6YhBHIoSKgS5ESM9VIGzhWjEHEGNPSibiDTxFhsFWxNaz8LbMDPjBUE69r9wmdGLkrQ+wVPbnJcZPvw==",
+ "license": "MIT",
+ "optional": true,
+ "dependencies": {
+ "@solana/errors": "2.3.0"
+ },
+ "engines": {
+ "node": ">=20.18.0"
+ },
+ "peerDependencies": {
+ "typescript": ">=5.3.3"
+ }
+ },
+ "node_modules/@solana/web3.js/node_modules/@solana/codecs-numbers": {
+ "version": "2.3.0",
+ "resolved": "https://registry.npmjs.org/@solana/codecs-numbers/-/codecs-numbers-2.3.0.tgz",
+ "integrity": "sha512-jFvvwKJKffvG7Iz9dmN51OGB7JBcy2CJ6Xf3NqD/VP90xak66m/Lg48T01u5IQ/hc15mChVHiBm+HHuOFDUrQg==",
+ "license": "MIT",
+ "optional": true,
+ "dependencies": {
+ "@solana/codecs-core": "2.3.0",
+ "@solana/errors": "2.3.0"
+ },
+ "engines": {
+ "node": ">=20.18.0"
+ },
+ "peerDependencies": {
+ "typescript": ">=5.3.3"
+ }
+ },
+ "node_modules/@solana/web3.js/node_modules/@solana/errors": {
+ "version": "2.3.0",
+ "resolved": "https://registry.npmjs.org/@solana/errors/-/errors-2.3.0.tgz",
+ "integrity": "sha512-66RI9MAbwYV0UtP7kGcTBVLxJgUxoZGm8Fbc0ah+lGiAw17Gugco6+9GrJCV83VyF2mDWyYnYM9qdI3yjgpnaQ==",
+ "license": "MIT",
+ "optional": true,
+ "dependencies": {
+ "chalk": "^5.4.1",
+ "commander": "^14.0.0"
+ },
+ "bin": {
+ "errors": "bin/cli.mjs"
+ },
+ "engines": {
+ "node": ">=20.18.0"
+ },
+ "peerDependencies": {
+ "typescript": ">=5.3.3"
+ }
+ },
+ "node_modules/@solana/web3.js/node_modules/base-x": {
+ "version": "3.0.11",
+ "resolved": "https://registry.npmjs.org/base-x/-/base-x-3.0.11.tgz",
+ "integrity": "sha512-xz7wQ8xDhdyP7tQxwdteLYeFfS68tSMNCZ/Y37WJ4bhGfKPpqEIlmIyueQHqOyoPhE6xNUqjzRr8ra0eF9VRvA==",
+ "license": "MIT",
+ "optional": true,
+ "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==",
+ "license": "MIT",
+ "optional": true,
+ "dependencies": {
+ "base-x": "^3.0.2"
+ }
+ },
+ "node_modules/@swc/helpers": {
+ "version": "0.5.17",
+ "resolved": "https://registry.npmjs.org/@swc/helpers/-/helpers-0.5.17.tgz",
+ "integrity": "sha512-5IKx/Y13RsYd+sauPb2x+U/xZikHjolzfuDgTAl/Tdf3Q8rslRvC19NKDLgAJQ6wsqADk10ntlv08nPFw/gO/A==",
+ "license": "Apache-2.0",
+ "optional": true,
+ "dependencies": {
+ "tslib": "^2.8.0"
+ }
+ },
+ "node_modules/@swc/helpers/node_modules/tslib": {
+ "version": "2.8.1",
+ "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz",
+ "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==",
+ "license": "0BSD",
+ "optional": true
+ },
+ "node_modules/@types/babel__core": {
+ "version": "7.20.5",
+ "resolved": "https://registry.npmjs.org/@types/babel__core/-/babel__core-7.20.5.tgz",
+ "integrity": "sha512-qoQprZvz5wQFJwMDqeseRXWv3rqMvhgpbXFfVyWhbx9X47POIA6i/+dXefEmZKoAgOaTdaIgNSMqMIU61yRyzA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@babel/parser": "^7.20.7",
+ "@babel/types": "^7.20.7",
+ "@types/babel__generator": "*",
+ "@types/babel__template": "*",
+ "@types/babel__traverse": "*"
+ }
+ },
+ "node_modules/@types/babel__generator": {
+ "version": "7.27.0",
+ "resolved": "https://registry.npmjs.org/@types/babel__generator/-/babel__generator-7.27.0.tgz",
+ "integrity": "sha512-ufFd2Xi92OAVPYsy+P4n7/U7e68fex0+Ee8gSG9KX7eo084CWiQ4sdxktvdl0bOPupXtVJPY19zk6EwWqUQ8lg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@babel/types": "^7.0.0"
+ }
+ },
+ "node_modules/@types/babel__template": {
+ "version": "7.4.4",
+ "resolved": "https://registry.npmjs.org/@types/babel__template/-/babel__template-7.4.4.tgz",
+ "integrity": "sha512-h/NUaSyG5EyxBIp8YRxo4RMe2/qQgvyowRwVMzhYhBCONbW8PUsg4lkFMrhgZhUe5z3L3MiLDuvyJ/CaPa2A8A==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@babel/parser": "^7.1.0",
+ "@babel/types": "^7.0.0"
+ }
+ },
+ "node_modules/@types/babel__traverse": {
+ "version": "7.28.0",
+ "resolved": "https://registry.npmjs.org/@types/babel__traverse/-/babel__traverse-7.28.0.tgz",
+ "integrity": "sha512-8PvcXf70gTDZBgt9ptxJ8elBeBjcLOAcOtoO/mPJjtji1+CdGbHgm77om1GrsPxsiE+uXIpNSK64UYaIwQXd4Q==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@babel/types": "^7.28.2"
+ }
+ },
+ "node_modules/@types/connect": {
+ "version": "3.4.38",
+ "resolved": "https://registry.npmjs.org/@types/connect/-/connect-3.4.38.tgz",
+ "integrity": "sha512-K6uROf1LD88uDQqJCktA4yzL1YYAK6NgfsI0v/mTgyPKWsX1CnJ0XPSDhViejru1GcRkLWb8RlzFYJRqGUbaug==",
+ "license": "MIT",
+ "optional": true,
+ "dependencies": {
+ "@types/node": "*"
+ }
+ },
+ "node_modules/@types/estree": {
+ "version": "1.0.8",
+ "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.8.tgz",
+ "integrity": "sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/@types/json-schema": {
+ "version": "7.0.15",
+ "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.15.tgz",
+ "integrity": "sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/@types/node": {
+ "version": "24.10.1",
+ "resolved": "https://registry.npmjs.org/@types/node/-/node-24.10.1.tgz",
+ "integrity": "sha512-GNWcUTRBgIRJD5zj+Tq0fKOJ5XZajIiBroOF0yvj2bSU1WvNdYS/dn9UxwsujGW4JX06dnHyjV2y9rRaybH0iQ==",
+ "license": "MIT",
+ "optional": true,
+ "dependencies": {
+ "undici-types": "~7.16.0"
+ }
+ },
+ "node_modules/@types/react": {
+ "version": "19.2.7",
+ "resolved": "https://registry.npmjs.org/@types/react/-/react-19.2.7.tgz",
+ "integrity": "sha512-MWtvHrGZLFttgeEj28VXHxpmwYbor/ATPYbBfSFZEIRK0ecCFLl2Qo55z52Hss+UV9CRN7trSeq1zbgx7YDWWg==",
+ "devOptional": true,
+ "license": "MIT",
+ "peer": true,
+ "dependencies": {
+ "csstype": "^3.2.2"
+ }
+ },
+ "node_modules/@types/react-dom": {
+ "version": "19.2.3",
+ "resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-19.2.3.tgz",
+ "integrity": "sha512-jp2L/eY6fn+KgVVQAOqYItbF0VY/YApe5Mz2F0aykSO8gx31bYCZyvSeYxCHKvzHG5eZjc+zyaS5BrBWya2+kQ==",
+ "dev": true,
+ "license": "MIT",
+ "peerDependencies": {
+ "@types/react": "^19.2.0"
+ }
+ },
+ "node_modules/@types/trusted-types": {
+ "version": "2.0.7",
+ "resolved": "https://registry.npmjs.org/@types/trusted-types/-/trusted-types-2.0.7.tgz",
+ "integrity": "sha512-ScaPdn1dQczgbl0QFTeTOmVHFULt394XJgOQNoyVhZ6r2vLnMLJfBPd53SB52T/3G36VI1/g2MZaX0cwDuXsfw==",
+ "license": "MIT"
+ },
+ "node_modules/@types/uuid": {
+ "version": "8.3.4",
+ "resolved": "https://registry.npmjs.org/@types/uuid/-/uuid-8.3.4.tgz",
+ "integrity": "sha512-c/I8ZRb51j+pYGAu5CrFMRxqZ2ke4y2grEBO5AUjgSkSk+qT2Ea+OdWElz/OiMf5MNpn2b17kuVBwZLQJXzihw==",
+ "license": "MIT",
+ "optional": true
+ },
+ "node_modules/@types/ws": {
+ "version": "7.4.7",
+ "resolved": "https://registry.npmjs.org/@types/ws/-/ws-7.4.7.tgz",
+ "integrity": "sha512-JQbbmxZTZehdc2iszGKs5oC3NFnjeay7mtAWrdt7qNtAVK0g19muApzAy4bm9byz79xa2ZnO/BOBC2R8RC5Lww==",
+ "license": "MIT",
+ "optional": true,
+ "dependencies": {
+ "@types/node": "*"
+ }
+ },
+ "node_modules/@typescript-eslint/eslint-plugin": {
+ "version": "8.48.1",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.48.1.tgz",
+ "integrity": "sha512-X63hI1bxl5ohelzr0LY5coufyl0LJNthld+abwxpCoo6Gq+hSqhKwci7MUWkXo67mzgUK6YFByhmaHmUcuBJmA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@eslint-community/regexpp": "^4.10.0",
+ "@typescript-eslint/scope-manager": "8.48.1",
+ "@typescript-eslint/type-utils": "8.48.1",
+ "@typescript-eslint/utils": "8.48.1",
+ "@typescript-eslint/visitor-keys": "8.48.1",
+ "graphemer": "^1.4.0",
+ "ignore": "^7.0.0",
+ "natural-compare": "^1.4.0",
+ "ts-api-utils": "^2.1.0"
+ },
+ "engines": {
+ "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/typescript-eslint"
+ },
+ "peerDependencies": {
+ "@typescript-eslint/parser": "^8.48.1",
+ "eslint": "^8.57.0 || ^9.0.0",
+ "typescript": ">=4.8.4 <6.0.0"
+ }
+ },
+ "node_modules/@typescript-eslint/eslint-plugin/node_modules/ignore": {
+ "version": "7.0.5",
+ "resolved": "https://registry.npmjs.org/ignore/-/ignore-7.0.5.tgz",
+ "integrity": "sha512-Hs59xBNfUIunMFgWAbGX5cq6893IbWg4KnrjbYwX3tx0ztorVgTDA6B2sxf8ejHJ4wz8BqGUMYlnzNBer5NvGg==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">= 4"
+ }
+ },
+ "node_modules/@typescript-eslint/parser": {
+ "version": "8.48.1",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.48.1.tgz",
+ "integrity": "sha512-PC0PDZfJg8sP7cmKe6L3QIL8GZwU5aRvUFedqSIpw3B+QjRSUZeeITC2M5XKeMXEzL6wccN196iy3JLwKNvDVA==",
+ "dev": true,
+ "license": "MIT",
+ "peer": true,
+ "dependencies": {
+ "@typescript-eslint/scope-manager": "8.48.1",
+ "@typescript-eslint/types": "8.48.1",
+ "@typescript-eslint/typescript-estree": "8.48.1",
+ "@typescript-eslint/visitor-keys": "8.48.1",
+ "debug": "^4.3.4"
+ },
+ "engines": {
+ "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/typescript-eslint"
+ },
+ "peerDependencies": {
+ "eslint": "^8.57.0 || ^9.0.0",
+ "typescript": ">=4.8.4 <6.0.0"
+ }
+ },
+ "node_modules/@typescript-eslint/project-service": {
+ "version": "8.48.1",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/project-service/-/project-service-8.48.1.tgz",
+ "integrity": "sha512-HQWSicah4s9z2/HifRPQ6b6R7G+SBx64JlFQpgSSHWPKdvCZX57XCbszg/bapbRsOEv42q5tayTYcEFpACcX1w==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@typescript-eslint/tsconfig-utils": "^8.48.1",
+ "@typescript-eslint/types": "^8.48.1",
+ "debug": "^4.3.4"
+ },
+ "engines": {
+ "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/typescript-eslint"
+ },
+ "peerDependencies": {
+ "typescript": ">=4.8.4 <6.0.0"
+ }
+ },
+ "node_modules/@typescript-eslint/scope-manager": {
+ "version": "8.48.1",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.48.1.tgz",
+ "integrity": "sha512-rj4vWQsytQbLxC5Bf4XwZ0/CKd362DkWMUkviT7DCS057SK64D5lH74sSGzhI6PDD2HCEq02xAP9cX68dYyg1w==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@typescript-eslint/types": "8.48.1",
+ "@typescript-eslint/visitor-keys": "8.48.1"
+ },
+ "engines": {
+ "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/typescript-eslint"
+ }
+ },
+ "node_modules/@typescript-eslint/tsconfig-utils": {
+ "version": "8.48.1",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/tsconfig-utils/-/tsconfig-utils-8.48.1.tgz",
+ "integrity": "sha512-k0Jhs4CpEffIBm6wPaCXBAD7jxBtrHjrSgtfCjUvPp9AZ78lXKdTR8fxyZO5y4vWNlOvYXRtngSZNSn+H53Jkw==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/typescript-eslint"
+ },
+ "peerDependencies": {
+ "typescript": ">=4.8.4 <6.0.0"
+ }
+ },
+ "node_modules/@typescript-eslint/type-utils": {
+ "version": "8.48.1",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.48.1.tgz",
+ "integrity": "sha512-1jEop81a3LrJQLTf/1VfPQdhIY4PlGDBc/i67EVWObrtvcziysbLN3oReexHOM6N3jyXgCrkBsZpqwH0hiDOQg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@typescript-eslint/types": "8.48.1",
+ "@typescript-eslint/typescript-estree": "8.48.1",
+ "@typescript-eslint/utils": "8.48.1",
+ "debug": "^4.3.4",
+ "ts-api-utils": "^2.1.0"
+ },
+ "engines": {
+ "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/typescript-eslint"
+ },
+ "peerDependencies": {
+ "eslint": "^8.57.0 || ^9.0.0",
+ "typescript": ">=4.8.4 <6.0.0"
+ }
+ },
+ "node_modules/@typescript-eslint/types": {
+ "version": "8.48.1",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.48.1.tgz",
+ "integrity": "sha512-+fZ3LZNeiELGmimrujsDCT4CRIbq5oXdHe7chLiW8qzqyPMnn1puNstCrMNVAqwcl2FdIxkuJ4tOs/RFDBVc/Q==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/typescript-eslint"
+ }
+ },
+ "node_modules/@typescript-eslint/typescript-estree": {
+ "version": "8.48.1",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.48.1.tgz",
+ "integrity": "sha512-/9wQ4PqaefTK6POVTjJaYS0bynCgzh6ClJHGSBj06XEHjkfylzB+A3qvyaXnErEZSaxhIo4YdyBgq6j4RysxDg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@typescript-eslint/project-service": "8.48.1",
+ "@typescript-eslint/tsconfig-utils": "8.48.1",
+ "@typescript-eslint/types": "8.48.1",
+ "@typescript-eslint/visitor-keys": "8.48.1",
+ "debug": "^4.3.4",
+ "minimatch": "^9.0.4",
+ "semver": "^7.6.0",
+ "tinyglobby": "^0.2.15",
+ "ts-api-utils": "^2.1.0"
+ },
+ "engines": {
+ "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/typescript-eslint"
+ },
+ "peerDependencies": {
+ "typescript": ">=4.8.4 <6.0.0"
+ }
+ },
+ "node_modules/@typescript-eslint/typescript-estree/node_modules/brace-expansion": {
+ "version": "2.0.2",
+ "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.2.tgz",
+ "integrity": "sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "balanced-match": "^1.0.0"
+ }
+ },
+ "node_modules/@typescript-eslint/typescript-estree/node_modules/minimatch": {
+ "version": "9.0.5",
+ "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz",
+ "integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==",
+ "dev": true,
+ "license": "ISC",
+ "dependencies": {
+ "brace-expansion": "^2.0.1"
+ },
+ "engines": {
+ "node": ">=16 || 14 >=14.17"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/isaacs"
+ }
+ },
+ "node_modules/@typescript-eslint/utils": {
+ "version": "8.48.1",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.48.1.tgz",
+ "integrity": "sha512-fAnhLrDjiVfey5wwFRwrweyRlCmdz5ZxXz2G/4cLn0YDLjTapmN4gcCsTBR1N2rWnZSDeWpYtgLDsJt+FpmcwA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@eslint-community/eslint-utils": "^4.7.0",
+ "@typescript-eslint/scope-manager": "8.48.1",
+ "@typescript-eslint/types": "8.48.1",
+ "@typescript-eslint/typescript-estree": "8.48.1"
+ },
+ "engines": {
+ "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/typescript-eslint"
+ },
+ "peerDependencies": {
+ "eslint": "^8.57.0 || ^9.0.0",
+ "typescript": ">=4.8.4 <6.0.0"
+ }
+ },
+ "node_modules/@typescript-eslint/visitor-keys": {
+ "version": "8.48.1",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.48.1.tgz",
+ "integrity": "sha512-BmxxndzEWhE4TIEEMBs8lP3MBWN3jFPs/p6gPm/wkv02o41hI6cq9AuSmGAaTTHPtA1FTi2jBre4A9rm5ZmX+Q==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@typescript-eslint/types": "8.48.1",
+ "eslint-visitor-keys": "^4.2.1"
+ },
+ "engines": {
+ "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/typescript-eslint"
+ }
+ },
+ "node_modules/@vitejs/plugin-react": {
+ "version": "5.1.1",
+ "resolved": "https://registry.npmjs.org/@vitejs/plugin-react/-/plugin-react-5.1.1.tgz",
+ "integrity": "sha512-WQfkSw0QbQ5aJ2CHYw23ZGkqnRwqKHD/KYsMeTkZzPT4Jcf0DcBxBtwMJxnu6E7oxw5+JC6ZAiePgh28uJ1HBA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@babel/core": "^7.28.5",
+ "@babel/plugin-transform-react-jsx-self": "^7.27.1",
+ "@babel/plugin-transform-react-jsx-source": "^7.27.1",
+ "@rolldown/pluginutils": "1.0.0-beta.47",
+ "@types/babel__core": "^7.20.5",
+ "react-refresh": "^0.18.0"
+ },
+ "engines": {
+ "node": "^20.19.0 || >=22.12.0"
+ },
+ "peerDependencies": {
+ "vite": "^4.2.0 || ^5.0.0 || ^6.0.0 || ^7.0.0"
+ }
+ },
+ "node_modules/@wallet-standard/base": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/@wallet-standard/base/-/base-1.1.0.tgz",
+ "integrity": "sha512-DJDQhjKmSNVLKWItoKThJS+CsJQjR9AOBOirBVT1F9YpRyC9oYHE+ZnSf8y8bxUphtKqdQMPVQ2mHohYdRvDVQ==",
+ "license": "Apache-2.0",
+ "engines": {
+ "node": ">=16"
+ }
+ },
+ "node_modules/@wallet-standard/wallet": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/@wallet-standard/wallet/-/wallet-1.1.0.tgz",
+ "integrity": "sha512-Gt8TnSlDZpAl+RWOOAB/kuvC7RpcdWAlFbHNoi4gsXsfaWa1QCT6LBcfIYTPdOZC9OVZUDwqGuGAcqZejDmHjg==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@wallet-standard/base": "^1.1.0"
+ },
+ "engines": {
+ "node": ">=16"
+ }
+ },
+ "node_modules/@walletconnect/core": {
+ "version": "2.23.0",
+ "resolved": "https://registry.npmjs.org/@walletconnect/core/-/core-2.23.0.tgz",
+ "integrity": "sha512-W++xuXf+AsMPrBWn1It8GheIbCTp1ynTQP+aoFB86eUwyCtSiK7UQsn/+vJZdwElrn+Ptp2A0RqQx2onTMVHjQ==",
+ "license": "SEE LICENSE IN LICENSE.md",
+ "dependencies": {
+ "@walletconnect/heartbeat": "1.2.2",
+ "@walletconnect/jsonrpc-provider": "1.0.14",
+ "@walletconnect/jsonrpc-types": "1.0.4",
+ "@walletconnect/jsonrpc-utils": "1.0.8",
+ "@walletconnect/jsonrpc-ws-connection": "1.0.16",
+ "@walletconnect/keyvaluestorage": "1.1.1",
+ "@walletconnect/logger": "3.0.0",
+ "@walletconnect/relay-api": "1.0.11",
+ "@walletconnect/relay-auth": "1.1.0",
+ "@walletconnect/safe-json": "1.0.2",
+ "@walletconnect/time": "1.0.2",
+ "@walletconnect/types": "2.23.0",
+ "@walletconnect/utils": "2.23.0",
+ "@walletconnect/window-getters": "1.0.1",
+ "es-toolkit": "1.39.3",
+ "events": "3.3.0",
+ "uint8arrays": "3.1.1"
+ },
+ "engines": {
+ "node": ">=18.20.8"
+ }
+ },
+ "node_modules/@walletconnect/core/node_modules/@walletconnect/keyvaluestorage": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/@walletconnect/keyvaluestorage/-/keyvaluestorage-1.1.1.tgz",
+ "integrity": "sha512-V7ZQq2+mSxAq7MrRqDxanTzu2RcElfK1PfNYiaVnJgJ7Q7G7hTVwF8voIBx92qsRyGHZihrwNPHuZd1aKkd0rA==",
+ "license": "MIT",
+ "dependencies": {
+ "@walletconnect/safe-json": "^1.0.1",
+ "idb-keyval": "^6.2.1",
+ "unstorage": "^1.9.0"
+ },
+ "peerDependencies": {
+ "@react-native-async-storage/async-storage": "1.x"
+ },
+ "peerDependenciesMeta": {
+ "@react-native-async-storage/async-storage": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@walletconnect/core/node_modules/lru-cache": {
+ "version": "10.4.3",
+ "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.4.3.tgz",
+ "integrity": "sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==",
+ "license": "ISC"
+ },
+ "node_modules/@walletconnect/core/node_modules/unstorage": {
+ "version": "1.17.3",
+ "resolved": "https://registry.npmjs.org/unstorage/-/unstorage-1.17.3.tgz",
+ "integrity": "sha512-i+JYyy0DoKmQ3FximTHbGadmIYb8JEpq7lxUjnjeB702bCPum0vzo6oy5Mfu0lpqISw7hCyMW2yj4nWC8bqJ3Q==",
+ "license": "MIT",
+ "dependencies": {
+ "anymatch": "^3.1.3",
+ "chokidar": "^4.0.3",
+ "destr": "^2.0.5",
+ "h3": "^1.15.4",
+ "lru-cache": "^10.4.3",
+ "node-fetch-native": "^1.6.7",
+ "ofetch": "^1.5.1",
+ "ufo": "^1.6.1"
+ },
+ "peerDependencies": {
+ "@azure/app-configuration": "^1.8.0",
+ "@azure/cosmos": "^4.2.0",
+ "@azure/data-tables": "^13.3.0",
+ "@azure/identity": "^4.6.0",
+ "@azure/keyvault-secrets": "^4.9.0",
+ "@azure/storage-blob": "^12.26.0",
+ "@capacitor/preferences": "^6.0.3 || ^7.0.0",
+ "@deno/kv": ">=0.9.0",
+ "@netlify/blobs": "^6.5.0 || ^7.0.0 || ^8.1.0 || ^9.0.0 || ^10.0.0",
+ "@planetscale/database": "^1.19.0",
+ "@upstash/redis": "^1.34.3",
+ "@vercel/blob": ">=0.27.1",
+ "@vercel/functions": "^2.2.12 || ^3.0.0",
+ "@vercel/kv": "^1.0.1",
+ "aws4fetch": "^1.0.20",
+ "db0": ">=0.2.1",
+ "idb-keyval": "^6.2.1",
+ "ioredis": "^5.4.2",
+ "uploadthing": "^7.4.4"
+ },
+ "peerDependenciesMeta": {
+ "@azure/app-configuration": {
+ "optional": true
+ },
+ "@azure/cosmos": {
+ "optional": true
+ },
+ "@azure/data-tables": {
+ "optional": true
+ },
+ "@azure/identity": {
+ "optional": true
+ },
+ "@azure/keyvault-secrets": {
+ "optional": true
+ },
+ "@azure/storage-blob": {
+ "optional": true
+ },
+ "@capacitor/preferences": {
+ "optional": true
+ },
+ "@deno/kv": {
+ "optional": true
+ },
+ "@netlify/blobs": {
+ "optional": true
+ },
+ "@planetscale/database": {
+ "optional": true
+ },
+ "@upstash/redis": {
+ "optional": true
+ },
+ "@vercel/blob": {
+ "optional": true
+ },
+ "@vercel/functions": {
+ "optional": true
+ },
+ "@vercel/kv": {
+ "optional": true
+ },
+ "aws4fetch": {
+ "optional": true
+ },
+ "db0": {
+ "optional": true
+ },
+ "idb-keyval": {
+ "optional": true
+ },
+ "ioredis": {
+ "optional": true
+ },
+ "uploadthing": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@walletconnect/environment": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/@walletconnect/environment/-/environment-1.0.1.tgz",
+ "integrity": "sha512-T426LLZtHj8e8rYnKfzsw1aG6+M0BT1ZxayMdv/p8yM0MU+eJDISqNY3/bccxRr4LrF9csq02Rhqt08Ibl0VRg==",
+ "license": "MIT",
+ "dependencies": {
+ "tslib": "1.14.1"
+ }
+ },
+ "node_modules/@walletconnect/events": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/@walletconnect/events/-/events-1.0.1.tgz",
+ "integrity": "sha512-NPTqaoi0oPBVNuLv7qPaJazmGHs5JGyO8eEAk5VGKmJzDR7AHzD4k6ilox5kxk1iwiOnFopBOOMLs86Oa76HpQ==",
+ "license": "MIT",
+ "dependencies": {
+ "keyvaluestorage-interface": "^1.0.0",
+ "tslib": "1.14.1"
+ }
+ },
+ "node_modules/@walletconnect/heartbeat": {
+ "version": "1.2.2",
+ "resolved": "https://registry.npmjs.org/@walletconnect/heartbeat/-/heartbeat-1.2.2.tgz",
+ "integrity": "sha512-uASiRmC5MwhuRuf05vq4AT48Pq8RMi876zV8rr8cV969uTOzWdB/k+Lj5yI2PBtB1bGQisGen7MM1GcZlQTBXw==",
+ "license": "MIT",
+ "dependencies": {
+ "@walletconnect/events": "^1.0.1",
+ "@walletconnect/time": "^1.0.2",
+ "events": "^3.3.0"
+ }
+ },
+ "node_modules/@walletconnect/jsonrpc-http-connection": {
+ "version": "1.0.8",
+ "resolved": "https://registry.npmjs.org/@walletconnect/jsonrpc-http-connection/-/jsonrpc-http-connection-1.0.8.tgz",
+ "integrity": "sha512-+B7cRuaxijLeFDJUq5hAzNyef3e3tBDIxyaCNmFtjwnod5AGis3RToNqzFU33vpVcxFhofkpE7Cx+5MYejbMGw==",
+ "license": "MIT",
+ "dependencies": {
+ "@walletconnect/jsonrpc-utils": "^1.0.6",
+ "@walletconnect/safe-json": "^1.0.1",
+ "cross-fetch": "^3.1.4",
+ "events": "^3.3.0"
+ }
+ },
+ "node_modules/@walletconnect/jsonrpc-provider": {
+ "version": "1.0.14",
+ "resolved": "https://registry.npmjs.org/@walletconnect/jsonrpc-provider/-/jsonrpc-provider-1.0.14.tgz",
+ "integrity": "sha512-rtsNY1XqHvWj0EtITNeuf8PHMvlCLiS3EjQL+WOkxEOA4KPxsohFnBDeyPYiNm4ZvkQdLnece36opYidmtbmow==",
+ "license": "MIT",
+ "dependencies": {
+ "@walletconnect/jsonrpc-utils": "^1.0.8",
+ "@walletconnect/safe-json": "^1.0.2",
+ "events": "^3.3.0"
+ }
+ },
+ "node_modules/@walletconnect/jsonrpc-types": {
+ "version": "1.0.4",
+ "resolved": "https://registry.npmjs.org/@walletconnect/jsonrpc-types/-/jsonrpc-types-1.0.4.tgz",
+ "integrity": "sha512-P6679fG/M+wuWg9TY8mh6xFSdYnFyFjwFelxyISxMDrlbXokorEVXYOxiqEbrU3x1BmBoCAJJ+vtEaEoMlpCBQ==",
+ "license": "MIT",
+ "dependencies": {
+ "events": "^3.3.0",
+ "keyvaluestorage-interface": "^1.0.0"
+ }
+ },
+ "node_modules/@walletconnect/jsonrpc-utils": {
+ "version": "1.0.8",
+ "resolved": "https://registry.npmjs.org/@walletconnect/jsonrpc-utils/-/jsonrpc-utils-1.0.8.tgz",
+ "integrity": "sha512-vdeb03bD8VzJUL6ZtzRYsFMq1eZQcM3EAzT0a3st59dyLfJ0wq+tKMpmGH7HlB7waD858UWgfIcudbPFsbzVdw==",
+ "license": "MIT",
+ "dependencies": {
+ "@walletconnect/environment": "^1.0.1",
+ "@walletconnect/jsonrpc-types": "^1.0.3",
+ "tslib": "1.14.1"
+ }
+ },
+ "node_modules/@walletconnect/jsonrpc-ws-connection": {
+ "version": "1.0.16",
+ "resolved": "https://registry.npmjs.org/@walletconnect/jsonrpc-ws-connection/-/jsonrpc-ws-connection-1.0.16.tgz",
+ "integrity": "sha512-G81JmsMqh5nJheE1mPst1W0WfVv0SG3N7JggwLLGnI7iuDZJq8cRJvQwLGKHn5H1WTW7DEPCo00zz5w62AbL3Q==",
+ "license": "MIT",
+ "dependencies": {
+ "@walletconnect/jsonrpc-utils": "^1.0.6",
+ "@walletconnect/safe-json": "^1.0.2",
+ "events": "^3.3.0",
+ "ws": "^7.5.1"
+ }
+ },
+ "node_modules/@walletconnect/jsonrpc-ws-connection/node_modules/ws": {
+ "version": "7.5.10",
+ "resolved": "https://registry.npmjs.org/ws/-/ws-7.5.10.tgz",
+ "integrity": "sha512-+dbF1tHwZpXcbOJdVOkzLDxZP1ailvSxM6ZweXTegylPny803bFhA+vqBYw4s31NSAk4S2Qz+AKXK9a4wkdjcQ==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=8.3.0"
+ },
+ "peerDependencies": {
+ "bufferutil": "^4.0.1",
+ "utf-8-validate": "^5.0.2"
+ },
+ "peerDependenciesMeta": {
+ "bufferutil": {
+ "optional": true
+ },
+ "utf-8-validate": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@walletconnect/logger": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/@walletconnect/logger/-/logger-3.0.0.tgz",
+ "integrity": "sha512-DDktPBFdmt5d7U3sbp4e3fQHNS1b6amsR8FmtOnt6L2SnV7VfcZr8VmAGL12zetAR+4fndegbREmX0P8Mw6eDg==",
+ "license": "MIT",
+ "dependencies": {
+ "@walletconnect/safe-json": "^1.0.2",
+ "pino": "10.0.0"
+ }
+ },
+ "node_modules/@walletconnect/relay-api": {
+ "version": "1.0.11",
+ "resolved": "https://registry.npmjs.org/@walletconnect/relay-api/-/relay-api-1.0.11.tgz",
+ "integrity": "sha512-tLPErkze/HmC9aCmdZOhtVmYZq1wKfWTJtygQHoWtgg722Jd4homo54Cs4ak2RUFUZIGO2RsOpIcWipaua5D5Q==",
+ "license": "MIT",
+ "dependencies": {
+ "@walletconnect/jsonrpc-types": "^1.0.2"
+ }
+ },
+ "node_modules/@walletconnect/relay-auth": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/@walletconnect/relay-auth/-/relay-auth-1.1.0.tgz",
+ "integrity": "sha512-qFw+a9uRz26jRCDgL7Q5TA9qYIgcNY8jpJzI1zAWNZ8i7mQjaijRnWFKsCHAU9CyGjvt6RKrRXyFtFOpWTVmCQ==",
+ "license": "MIT",
+ "dependencies": {
+ "@noble/curves": "1.8.0",
+ "@noble/hashes": "1.7.0",
+ "@walletconnect/safe-json": "^1.0.1",
+ "@walletconnect/time": "^1.0.2",
+ "uint8arrays": "^3.0.0"
+ }
+ },
+ "node_modules/@walletconnect/relay-auth/node_modules/@noble/curves": {
+ "version": "1.8.0",
+ "resolved": "https://registry.npmjs.org/@noble/curves/-/curves-1.8.0.tgz",
+ "integrity": "sha512-j84kjAbzEnQHaSIhRPUmB3/eVXu2k3dKPl2LOrR8fSOIL+89U+7lV117EWHtq/GHM3ReGHM46iRBdZfpc4HRUQ==",
+ "license": "MIT",
+ "dependencies": {
+ "@noble/hashes": "1.7.0"
+ },
+ "engines": {
+ "node": "^14.21.3 || >=16"
+ },
+ "funding": {
+ "url": "https://paulmillr.com/funding/"
+ }
+ },
+ "node_modules/@walletconnect/relay-auth/node_modules/@noble/hashes": {
+ "version": "1.7.0",
+ "resolved": "https://registry.npmjs.org/@noble/hashes/-/hashes-1.7.0.tgz",
+ "integrity": "sha512-HXydb0DgzTpDPwbVeDGCG1gIu7X6+AuU6Zl6av/E/KG8LMsvPntvq+w17CHRpKBmN6Ybdrt1eP3k4cj8DJa78w==",
+ "license": "MIT",
+ "engines": {
+ "node": "^14.21.3 || >=16"
+ },
+ "funding": {
+ "url": "https://paulmillr.com/funding/"
+ }
+ },
+ "node_modules/@walletconnect/safe-json": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/@walletconnect/safe-json/-/safe-json-1.0.2.tgz",
+ "integrity": "sha512-Ogb7I27kZ3LPC3ibn8ldyUr5544t3/STow9+lzz7Sfo808YD7SBWk7SAsdBFlYgP2zDRy2hS3sKRcuSRM0OTmA==",
+ "license": "MIT",
+ "dependencies": {
+ "tslib": "1.14.1"
+ }
+ },
+ "node_modules/@walletconnect/sign-client": {
+ "version": "2.23.0",
+ "resolved": "https://registry.npmjs.org/@walletconnect/sign-client/-/sign-client-2.23.0.tgz",
+ "integrity": "sha512-Nzf5x/LnQgC0Yjk0NmkT8kdrIMcScpALiFm9gP0n3CulL+dkf3HumqWzdoTmQSqGPxwHu/TNhGOaRKZLGQXSqw==",
+ "license": "SEE LICENSE IN LICENSE.md",
+ "dependencies": {
+ "@walletconnect/core": "2.23.0",
+ "@walletconnect/events": "1.0.1",
+ "@walletconnect/heartbeat": "1.2.2",
+ "@walletconnect/jsonrpc-utils": "1.0.8",
+ "@walletconnect/logger": "3.0.0",
+ "@walletconnect/time": "1.0.2",
+ "@walletconnect/types": "2.23.0",
+ "@walletconnect/utils": "2.23.0",
+ "events": "3.3.0"
+ }
+ },
+ "node_modules/@walletconnect/time": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/@walletconnect/time/-/time-1.0.2.tgz",
+ "integrity": "sha512-uzdd9woDcJ1AaBZRhqy5rNC9laqWGErfc4dxA9a87mPdKOgWMD85mcFo9dIYIts/Jwocfwn07EC6EzclKubk/g==",
+ "license": "MIT",
+ "dependencies": {
+ "tslib": "1.14.1"
+ }
+ },
+ "node_modules/@walletconnect/types": {
+ "version": "2.23.0",
+ "resolved": "https://registry.npmjs.org/@walletconnect/types/-/types-2.23.0.tgz",
+ "integrity": "sha512-9ZEOJyx/kNVCRncDHh3Qr9eH7Ih1dXBFB4k1J8iEudkv3t4GhYpXhqIt2kNdQWluPb1BBB4wEuckAT96yKuA8g==",
+ "license": "SEE LICENSE IN LICENSE.md",
+ "dependencies": {
+ "@walletconnect/events": "1.0.1",
+ "@walletconnect/heartbeat": "1.2.2",
+ "@walletconnect/jsonrpc-types": "1.0.4",
+ "@walletconnect/keyvaluestorage": "1.1.1",
+ "@walletconnect/logger": "3.0.0",
+ "events": "3.3.0"
+ }
+ },
+ "node_modules/@walletconnect/types/node_modules/@walletconnect/keyvaluestorage": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/@walletconnect/keyvaluestorage/-/keyvaluestorage-1.1.1.tgz",
+ "integrity": "sha512-V7ZQq2+mSxAq7MrRqDxanTzu2RcElfK1PfNYiaVnJgJ7Q7G7hTVwF8voIBx92qsRyGHZihrwNPHuZd1aKkd0rA==",
+ "license": "MIT",
+ "dependencies": {
+ "@walletconnect/safe-json": "^1.0.1",
+ "idb-keyval": "^6.2.1",
+ "unstorage": "^1.9.0"
+ },
+ "peerDependencies": {
+ "@react-native-async-storage/async-storage": "1.x"
+ },
+ "peerDependenciesMeta": {
+ "@react-native-async-storage/async-storage": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@walletconnect/types/node_modules/lru-cache": {
+ "version": "10.4.3",
+ "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.4.3.tgz",
+ "integrity": "sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==",
+ "license": "ISC"
+ },
+ "node_modules/@walletconnect/types/node_modules/unstorage": {
+ "version": "1.17.3",
+ "resolved": "https://registry.npmjs.org/unstorage/-/unstorage-1.17.3.tgz",
+ "integrity": "sha512-i+JYyy0DoKmQ3FximTHbGadmIYb8JEpq7lxUjnjeB702bCPum0vzo6oy5Mfu0lpqISw7hCyMW2yj4nWC8bqJ3Q==",
+ "license": "MIT",
+ "dependencies": {
+ "anymatch": "^3.1.3",
+ "chokidar": "^4.0.3",
+ "destr": "^2.0.5",
+ "h3": "^1.15.4",
+ "lru-cache": "^10.4.3",
+ "node-fetch-native": "^1.6.7",
+ "ofetch": "^1.5.1",
+ "ufo": "^1.6.1"
+ },
+ "peerDependencies": {
+ "@azure/app-configuration": "^1.8.0",
+ "@azure/cosmos": "^4.2.0",
+ "@azure/data-tables": "^13.3.0",
+ "@azure/identity": "^4.6.0",
+ "@azure/keyvault-secrets": "^4.9.0",
+ "@azure/storage-blob": "^12.26.0",
+ "@capacitor/preferences": "^6.0.3 || ^7.0.0",
+ "@deno/kv": ">=0.9.0",
+ "@netlify/blobs": "^6.5.0 || ^7.0.0 || ^8.1.0 || ^9.0.0 || ^10.0.0",
+ "@planetscale/database": "^1.19.0",
+ "@upstash/redis": "^1.34.3",
+ "@vercel/blob": ">=0.27.1",
+ "@vercel/functions": "^2.2.12 || ^3.0.0",
+ "@vercel/kv": "^1.0.1",
+ "aws4fetch": "^1.0.20",
+ "db0": ">=0.2.1",
+ "idb-keyval": "^6.2.1",
+ "ioredis": "^5.4.2",
+ "uploadthing": "^7.4.4"
+ },
+ "peerDependenciesMeta": {
+ "@azure/app-configuration": {
+ "optional": true
+ },
+ "@azure/cosmos": {
+ "optional": true
+ },
+ "@azure/data-tables": {
+ "optional": true
+ },
+ "@azure/identity": {
+ "optional": true
+ },
+ "@azure/keyvault-secrets": {
+ "optional": true
+ },
+ "@azure/storage-blob": {
+ "optional": true
+ },
+ "@capacitor/preferences": {
+ "optional": true
+ },
+ "@deno/kv": {
+ "optional": true
+ },
+ "@netlify/blobs": {
+ "optional": true
+ },
+ "@planetscale/database": {
+ "optional": true
+ },
+ "@upstash/redis": {
+ "optional": true
+ },
+ "@vercel/blob": {
+ "optional": true
+ },
+ "@vercel/functions": {
+ "optional": true
+ },
+ "@vercel/kv": {
+ "optional": true
+ },
+ "aws4fetch": {
+ "optional": true
+ },
+ "db0": {
+ "optional": true
+ },
+ "idb-keyval": {
+ "optional": true
+ },
+ "ioredis": {
+ "optional": true
+ },
+ "uploadthing": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@walletconnect/universal-provider": {
+ "version": "2.23.0",
+ "resolved": "https://registry.npmjs.org/@walletconnect/universal-provider/-/universal-provider-2.23.0.tgz",
+ "integrity": "sha512-3ZEqAsbtCbk+CV0ZLpy7Qzc04KXEnrW4zCboZ+gkkC0ey4H62x9h23kBOIrU9qew6orjA7D5gg0ikRC2Up1lbw==",
+ "license": "SEE LICENSE IN LICENSE.md",
+ "dependencies": {
+ "@walletconnect/events": "1.0.1",
+ "@walletconnect/jsonrpc-http-connection": "1.0.8",
+ "@walletconnect/jsonrpc-provider": "1.0.14",
+ "@walletconnect/jsonrpc-types": "1.0.4",
+ "@walletconnect/jsonrpc-utils": "1.0.8",
+ "@walletconnect/keyvaluestorage": "1.1.1",
+ "@walletconnect/logger": "3.0.0",
+ "@walletconnect/sign-client": "2.23.0",
+ "@walletconnect/types": "2.23.0",
+ "@walletconnect/utils": "2.23.0",
+ "es-toolkit": "1.39.3",
+ "events": "3.3.0"
+ }
+ },
+ "node_modules/@walletconnect/universal-provider/node_modules/@walletconnect/keyvaluestorage": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/@walletconnect/keyvaluestorage/-/keyvaluestorage-1.1.1.tgz",
+ "integrity": "sha512-V7ZQq2+mSxAq7MrRqDxanTzu2RcElfK1PfNYiaVnJgJ7Q7G7hTVwF8voIBx92qsRyGHZihrwNPHuZd1aKkd0rA==",
+ "license": "MIT",
+ "dependencies": {
+ "@walletconnect/safe-json": "^1.0.1",
+ "idb-keyval": "^6.2.1",
+ "unstorage": "^1.9.0"
+ },
+ "peerDependencies": {
+ "@react-native-async-storage/async-storage": "1.x"
+ },
+ "peerDependenciesMeta": {
+ "@react-native-async-storage/async-storage": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@walletconnect/universal-provider/node_modules/lru-cache": {
+ "version": "10.4.3",
+ "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.4.3.tgz",
+ "integrity": "sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==",
+ "license": "ISC"
+ },
+ "node_modules/@walletconnect/universal-provider/node_modules/unstorage": {
+ "version": "1.17.3",
+ "resolved": "https://registry.npmjs.org/unstorage/-/unstorage-1.17.3.tgz",
+ "integrity": "sha512-i+JYyy0DoKmQ3FximTHbGadmIYb8JEpq7lxUjnjeB702bCPum0vzo6oy5Mfu0lpqISw7hCyMW2yj4nWC8bqJ3Q==",
+ "license": "MIT",
+ "dependencies": {
+ "anymatch": "^3.1.3",
+ "chokidar": "^4.0.3",
+ "destr": "^2.0.5",
+ "h3": "^1.15.4",
+ "lru-cache": "^10.4.3",
+ "node-fetch-native": "^1.6.7",
+ "ofetch": "^1.5.1",
+ "ufo": "^1.6.1"
+ },
+ "peerDependencies": {
+ "@azure/app-configuration": "^1.8.0",
+ "@azure/cosmos": "^4.2.0",
+ "@azure/data-tables": "^13.3.0",
+ "@azure/identity": "^4.6.0",
+ "@azure/keyvault-secrets": "^4.9.0",
+ "@azure/storage-blob": "^12.26.0",
+ "@capacitor/preferences": "^6.0.3 || ^7.0.0",
+ "@deno/kv": ">=0.9.0",
+ "@netlify/blobs": "^6.5.0 || ^7.0.0 || ^8.1.0 || ^9.0.0 || ^10.0.0",
+ "@planetscale/database": "^1.19.0",
+ "@upstash/redis": "^1.34.3",
+ "@vercel/blob": ">=0.27.1",
+ "@vercel/functions": "^2.2.12 || ^3.0.0",
+ "@vercel/kv": "^1.0.1",
+ "aws4fetch": "^1.0.20",
+ "db0": ">=0.2.1",
+ "idb-keyval": "^6.2.1",
+ "ioredis": "^5.4.2",
+ "uploadthing": "^7.4.4"
+ },
+ "peerDependenciesMeta": {
+ "@azure/app-configuration": {
+ "optional": true
+ },
+ "@azure/cosmos": {
+ "optional": true
+ },
+ "@azure/data-tables": {
+ "optional": true
+ },
+ "@azure/identity": {
+ "optional": true
+ },
+ "@azure/keyvault-secrets": {
+ "optional": true
+ },
+ "@azure/storage-blob": {
+ "optional": true
+ },
+ "@capacitor/preferences": {
+ "optional": true
+ },
+ "@deno/kv": {
+ "optional": true
+ },
+ "@netlify/blobs": {
+ "optional": true
+ },
+ "@planetscale/database": {
+ "optional": true
+ },
+ "@upstash/redis": {
+ "optional": true
+ },
+ "@vercel/blob": {
+ "optional": true
+ },
+ "@vercel/functions": {
+ "optional": true
+ },
+ "@vercel/kv": {
+ "optional": true
+ },
+ "aws4fetch": {
+ "optional": true
+ },
+ "db0": {
+ "optional": true
+ },
+ "idb-keyval": {
+ "optional": true
+ },
+ "ioredis": {
+ "optional": true
+ },
+ "uploadthing": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@walletconnect/utils": {
+ "version": "2.23.0",
+ "resolved": "https://registry.npmjs.org/@walletconnect/utils/-/utils-2.23.0.tgz",
+ "integrity": "sha512-bVyv4Hl+/wVGueZ6rEO0eYgDy5deSBA4JjpJHAMOdaNoYs05NTE1HymV2lfPQQHuqc7suYexo9jwuW7i3JLuAA==",
+ "license": "SEE LICENSE IN LICENSE.md",
+ "dependencies": {
+ "@msgpack/msgpack": "3.1.2",
+ "@noble/ciphers": "1.3.0",
+ "@noble/curves": "1.9.7",
+ "@noble/hashes": "1.8.0",
+ "@scure/base": "1.2.6",
+ "@walletconnect/jsonrpc-utils": "1.0.8",
+ "@walletconnect/keyvaluestorage": "1.1.1",
+ "@walletconnect/logger": "3.0.0",
+ "@walletconnect/relay-api": "1.0.11",
+ "@walletconnect/relay-auth": "1.1.0",
+ "@walletconnect/safe-json": "1.0.2",
+ "@walletconnect/time": "1.0.2",
+ "@walletconnect/types": "2.23.0",
+ "@walletconnect/window-getters": "1.0.1",
+ "@walletconnect/window-metadata": "1.0.1",
+ "blakejs": "1.2.1",
+ "bs58": "6.0.0",
+ "detect-browser": "5.3.0",
+ "ox": "0.9.3",
+ "uint8arrays": "3.1.1"
+ }
+ },
+ "node_modules/@walletconnect/utils/node_modules/@adraffy/ens-normalize": {
+ "version": "1.11.1",
+ "resolved": "https://registry.npmjs.org/@adraffy/ens-normalize/-/ens-normalize-1.11.1.tgz",
+ "integrity": "sha512-nhCBV3quEgesuf7c7KYfperqSS14T8bYuvJ8PcLJp6znkZpFc0AuW4qBtr8eKVyPPe/8RSr7sglCWPU5eaxwKQ==",
+ "license": "MIT"
+ },
+ "node_modules/@walletconnect/utils/node_modules/@noble/hashes": {
+ "version": "1.8.0",
+ "resolved": "https://registry.npmjs.org/@noble/hashes/-/hashes-1.8.0.tgz",
+ "integrity": "sha512-jCs9ldd7NwzpgXDIf6P3+NrHh9/sD6CQdxHyjQI+h/6rDNo88ypBxxz45UDuZHz9r3tNz7N/VInSVoVdtXEI4A==",
+ "license": "MIT",
+ "engines": {
+ "node": "^14.21.3 || >=16"
+ },
+ "funding": {
+ "url": "https://paulmillr.com/funding/"
+ }
+ },
+ "node_modules/@walletconnect/utils/node_modules/@walletconnect/keyvaluestorage": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/@walletconnect/keyvaluestorage/-/keyvaluestorage-1.1.1.tgz",
+ "integrity": "sha512-V7ZQq2+mSxAq7MrRqDxanTzu2RcElfK1PfNYiaVnJgJ7Q7G7hTVwF8voIBx92qsRyGHZihrwNPHuZd1aKkd0rA==",
+ "license": "MIT",
+ "dependencies": {
+ "@walletconnect/safe-json": "^1.0.1",
+ "idb-keyval": "^6.2.1",
+ "unstorage": "^1.9.0"
+ },
+ "peerDependencies": {
+ "@react-native-async-storage/async-storage": "1.x"
+ },
+ "peerDependenciesMeta": {
+ "@react-native-async-storage/async-storage": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@walletconnect/utils/node_modules/abitype": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/abitype/-/abitype-1.2.0.tgz",
+ "integrity": "sha512-fD3ROjckUrWsybaSor2AdWxzA0e/DSyV2dA4aYd7bd8orHsoJjl09fOgKfUkTDfk0BsDGBf4NBgu/c7JoS2Npw==",
+ "license": "MIT",
+ "funding": {
+ "url": "https://github.com/sponsors/wevm"
+ },
+ "peerDependencies": {
+ "typescript": ">=5.0.4",
+ "zod": "^3.22.0 || ^4.0.0"
+ },
+ "peerDependenciesMeta": {
+ "typescript": {
+ "optional": true
+ },
+ "zod": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@walletconnect/utils/node_modules/lru-cache": {
+ "version": "10.4.3",
+ "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.4.3.tgz",
+ "integrity": "sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==",
+ "license": "ISC"
+ },
+ "node_modules/@walletconnect/utils/node_modules/ox": {
+ "version": "0.9.3",
+ "resolved": "https://registry.npmjs.org/ox/-/ox-0.9.3.tgz",
+ "integrity": "sha512-KzyJP+fPV4uhuuqrTZyok4DC7vFzi7HLUFiUNEmpbyh59htKWkOC98IONC1zgXJPbHAhQgqs6B0Z6StCGhmQvg==",
+ "funding": [
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/wevm"
+ }
+ ],
+ "license": "MIT",
+ "dependencies": {
+ "@adraffy/ens-normalize": "^1.11.0",
+ "@noble/ciphers": "^1.3.0",
+ "@noble/curves": "1.9.1",
+ "@noble/hashes": "^1.8.0",
+ "@scure/bip32": "^1.7.0",
+ "@scure/bip39": "^1.6.0",
+ "abitype": "^1.0.9",
+ "eventemitter3": "5.0.1"
+ },
+ "peerDependencies": {
+ "typescript": ">=5.4.0"
+ },
+ "peerDependenciesMeta": {
+ "typescript": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@walletconnect/utils/node_modules/ox/node_modules/@noble/curves": {
+ "version": "1.9.1",
+ "resolved": "https://registry.npmjs.org/@noble/curves/-/curves-1.9.1.tgz",
+ "integrity": "sha512-k11yZxZg+t+gWvBbIswW0yoJlu8cHOC7dhunwOzoWH/mXGBiYyR4YY6hAEK/3EUs4UpB8la1RfdRpeGsFHkWsA==",
+ "license": "MIT",
+ "dependencies": {
+ "@noble/hashes": "1.8.0"
+ },
+ "engines": {
+ "node": "^14.21.3 || >=16"
+ },
+ "funding": {
+ "url": "https://paulmillr.com/funding/"
+ }
+ },
+ "node_modules/@walletconnect/utils/node_modules/unstorage": {
+ "version": "1.17.3",
+ "resolved": "https://registry.npmjs.org/unstorage/-/unstorage-1.17.3.tgz",
+ "integrity": "sha512-i+JYyy0DoKmQ3FximTHbGadmIYb8JEpq7lxUjnjeB702bCPum0vzo6oy5Mfu0lpqISw7hCyMW2yj4nWC8bqJ3Q==",
+ "license": "MIT",
+ "dependencies": {
+ "anymatch": "^3.1.3",
+ "chokidar": "^4.0.3",
+ "destr": "^2.0.5",
+ "h3": "^1.15.4",
+ "lru-cache": "^10.4.3",
+ "node-fetch-native": "^1.6.7",
+ "ofetch": "^1.5.1",
+ "ufo": "^1.6.1"
+ },
+ "peerDependencies": {
+ "@azure/app-configuration": "^1.8.0",
+ "@azure/cosmos": "^4.2.0",
+ "@azure/data-tables": "^13.3.0",
+ "@azure/identity": "^4.6.0",
+ "@azure/keyvault-secrets": "^4.9.0",
+ "@azure/storage-blob": "^12.26.0",
+ "@capacitor/preferences": "^6.0.3 || ^7.0.0",
+ "@deno/kv": ">=0.9.0",
+ "@netlify/blobs": "^6.5.0 || ^7.0.0 || ^8.1.0 || ^9.0.0 || ^10.0.0",
+ "@planetscale/database": "^1.19.0",
+ "@upstash/redis": "^1.34.3",
+ "@vercel/blob": ">=0.27.1",
+ "@vercel/functions": "^2.2.12 || ^3.0.0",
+ "@vercel/kv": "^1.0.1",
+ "aws4fetch": "^1.0.20",
+ "db0": ">=0.2.1",
+ "idb-keyval": "^6.2.1",
+ "ioredis": "^5.4.2",
+ "uploadthing": "^7.4.4"
+ },
+ "peerDependenciesMeta": {
+ "@azure/app-configuration": {
+ "optional": true
+ },
+ "@azure/cosmos": {
+ "optional": true
+ },
+ "@azure/data-tables": {
+ "optional": true
+ },
+ "@azure/identity": {
+ "optional": true
+ },
+ "@azure/keyvault-secrets": {
+ "optional": true
+ },
+ "@azure/storage-blob": {
+ "optional": true
+ },
+ "@capacitor/preferences": {
+ "optional": true
+ },
+ "@deno/kv": {
+ "optional": true
+ },
+ "@netlify/blobs": {
+ "optional": true
+ },
+ "@planetscale/database": {
+ "optional": true
+ },
+ "@upstash/redis": {
+ "optional": true
+ },
+ "@vercel/blob": {
+ "optional": true
+ },
+ "@vercel/functions": {
+ "optional": true
+ },
+ "@vercel/kv": {
+ "optional": true
+ },
+ "aws4fetch": {
+ "optional": true
+ },
+ "db0": {
+ "optional": true
+ },
+ "idb-keyval": {
+ "optional": true
+ },
+ "ioredis": {
+ "optional": true
+ },
+ "uploadthing": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@walletconnect/window-getters": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/@walletconnect/window-getters/-/window-getters-1.0.1.tgz",
+ "integrity": "sha512-vHp+HqzGxORPAN8gY03qnbTMnhqIwjeRJNOMOAzePRg4xVEEE2WvYsI9G2NMjOknA8hnuYbU3/hwLcKbjhc8+Q==",
+ "license": "MIT",
+ "dependencies": {
+ "tslib": "1.14.1"
+ }
+ },
+ "node_modules/@walletconnect/window-metadata": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/@walletconnect/window-metadata/-/window-metadata-1.0.1.tgz",
+ "integrity": "sha512-9koTqyGrM2cqFRW517BPY/iEtUDx2r1+Pwwu5m7sJ7ka79wi3EyqhqcICk/yDmv6jAS1rjKgTKXlEhanYjijcA==",
+ "license": "MIT",
+ "dependencies": {
+ "@walletconnect/window-getters": "^1.0.1",
+ "tslib": "1.14.1"
+ }
+ },
+ "node_modules/abitype": {
+ "version": "1.0.6",
+ "resolved": "https://registry.npmjs.org/abitype/-/abitype-1.0.6.tgz",
+ "integrity": "sha512-MMSqYh4+C/aVqI2RQaWqbvI4Kxo5cQV40WQ4QFtDnNzCkqChm8MuENhElmynZlO0qUy/ObkEUaXtKqYnx1Kp3A==",
+ "license": "MIT",
+ "optional": true,
+ "funding": {
+ "url": "https://github.com/sponsors/wevm"
+ },
+ "peerDependencies": {
+ "typescript": ">=5.0.4",
+ "zod": "^3 >=3.22.0"
+ },
+ "peerDependenciesMeta": {
+ "typescript": {
+ "optional": true
+ },
+ "zod": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/acorn": {
+ "version": "8.15.0",
+ "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.15.0.tgz",
+ "integrity": "sha512-NZyJarBfL7nWwIq+FDL6Zp/yHEhePMNnnJ0y3qfieCrmNvYct8uvtiV41UvlSe6apAfk0fY1FbWx+NwfmpvtTg==",
+ "dev": true,
+ "license": "MIT",
+ "peer": true,
+ "bin": {
+ "acorn": "bin/acorn"
+ },
+ "engines": {
+ "node": ">=0.4.0"
+ }
+ },
+ "node_modules/acorn-jsx": {
+ "version": "5.3.2",
+ "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz",
+ "integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==",
+ "dev": true,
+ "license": "MIT",
+ "peerDependencies": {
+ "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0"
+ }
+ },
+ "node_modules/aes-js": {
+ "version": "4.0.0-beta.5",
+ "resolved": "https://registry.npmjs.org/aes-js/-/aes-js-4.0.0-beta.5.tgz",
+ "integrity": "sha512-G965FqalsNyrPqgEGON7nIx1e/OVENSgiEIzyC63haUMuvNnwIgIjMs52hlTCKhkBny7A2ORNlfY9Zu+jmGk1Q==",
+ "license": "MIT"
+ },
+ "node_modules/agentkeepalive": {
+ "version": "4.6.0",
+ "resolved": "https://registry.npmjs.org/agentkeepalive/-/agentkeepalive-4.6.0.tgz",
+ "integrity": "sha512-kja8j7PjmncONqaTsB8fQ+wE2mSU2DJ9D4XKoJ5PFWIdRMa6SLSN1ff4mOr4jCbfRSsxR4keIiySJU0N9T5hIQ==",
+ "license": "MIT",
+ "optional": true,
+ "dependencies": {
+ "humanize-ms": "^1.2.1"
+ },
+ "engines": {
+ "node": ">= 8.0.0"
+ }
+ },
+ "node_modules/ajv": {
+ "version": "6.12.6",
+ "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz",
+ "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "fast-deep-equal": "^3.1.1",
+ "fast-json-stable-stringify": "^2.0.0",
+ "json-schema-traverse": "^0.4.1",
+ "uri-js": "^4.2.2"
+ },
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/epoberezkin"
+ }
+ },
+ "node_modules/ansi-regex": {
+ "version": "5.0.1",
+ "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz",
+ "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/ansi-styles": {
+ "version": "4.3.0",
+ "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz",
+ "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==",
+ "license": "MIT",
+ "dependencies": {
+ "color-convert": "^2.0.1"
+ },
+ "engines": {
+ "node": ">=8"
+ },
+ "funding": {
+ "url": "https://github.com/chalk/ansi-styles?sponsor=1"
+ }
+ },
+ "node_modules/anymatch": {
+ "version": "3.1.3",
+ "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz",
+ "integrity": "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==",
+ "license": "ISC",
+ "dependencies": {
+ "normalize-path": "^3.0.0",
+ "picomatch": "^2.0.4"
+ },
+ "engines": {
+ "node": ">= 8"
+ }
+ },
+ "node_modules/anymatch/node_modules/picomatch": {
+ "version": "2.3.1",
+ "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz",
+ "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=8.6"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/jonschlinkert"
+ }
+ },
+ "node_modules/argparse": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz",
+ "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==",
+ "dev": true,
+ "license": "Python-2.0"
+ },
+ "node_modules/asynckit": {
+ "version": "0.4.0",
+ "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz",
+ "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==",
+ "license": "MIT",
+ "optional": true
+ },
+ "node_modules/atomic-sleep": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/atomic-sleep/-/atomic-sleep-1.0.0.tgz",
+ "integrity": "sha512-kNOjDqAh7px0XWNI+4QbzoiR/nTkHAWNud2uvnJquD1/x5a7EQZMJT0AczqK0Qn67oY/TTQ1LbUKajZpp3I9tQ==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=8.0.0"
+ }
+ },
+ "node_modules/axios-retry": {
+ "version": "4.5.0",
+ "resolved": "https://registry.npmjs.org/axios-retry/-/axios-retry-4.5.0.tgz",
+ "integrity": "sha512-aR99oXhpEDGo0UuAlYcn2iGRds30k366Zfa05XWScR9QaQD4JYiP3/1Qt1u7YlefUOK+cn0CcwoL1oefavQUlQ==",
+ "license": "Apache-2.0",
+ "optional": true,
+ "dependencies": {
+ "is-retry-allowed": "^2.2.0"
+ },
+ "peerDependencies": {
+ "axios": "0.x || 1.x"
+ }
+ },
+ "node_modules/balanced-match": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz",
+ "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/base-x": {
+ "version": "5.0.1",
+ "resolved": "https://registry.npmjs.org/base-x/-/base-x-5.0.1.tgz",
+ "integrity": "sha512-M7uio8Zt++eg3jPj+rHMfCC+IuygQHHCOU+IYsVtik6FWjuYpVt/+MRKcgsAMHh8mMFAwnB+Bs+mTrFiXjMzKg==",
+ "license": "MIT"
+ },
+ "node_modules/base64-js": {
+ "version": "1.5.1",
+ "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz",
+ "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==",
+ "funding": [
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/feross"
+ },
+ {
+ "type": "patreon",
+ "url": "https://www.patreon.com/feross"
+ },
+ {
+ "type": "consulting",
+ "url": "https://feross.org/support"
+ }
+ ],
+ "license": "MIT"
+ },
+ "node_modules/baseline-browser-mapping": {
+ "version": "2.8.32",
+ "resolved": "https://registry.npmjs.org/baseline-browser-mapping/-/baseline-browser-mapping-2.8.32.tgz",
+ "integrity": "sha512-OPz5aBThlyLFgxyhdwf/s2+8ab3OvT7AdTNvKHBwpXomIYeXqpUUuT8LrdtxZSsWJ4R4CU1un4XGh5Ez3nlTpw==",
+ "dev": true,
+ "license": "Apache-2.0",
+ "bin": {
+ "baseline-browser-mapping": "dist/cli.js"
+ }
+ },
+ "node_modules/big.js": {
+ "version": "6.2.2",
+ "resolved": "https://registry.npmjs.org/big.js/-/big.js-6.2.2.tgz",
+ "integrity": "sha512-y/ie+Faknx7sZA5MfGA2xKlu0GDv8RWrXGsmlteyJQ2lvoKv9GBK/fpRMc2qlSoBAgNxrixICFCBefIq8WCQpQ==",
+ "license": "MIT",
+ "engines": {
+ "node": "*"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/bigjs"
+ }
+ },
+ "node_modules/blakejs": {
+ "version": "1.2.1",
+ "resolved": "https://registry.npmjs.org/blakejs/-/blakejs-1.2.1.tgz",
+ "integrity": "sha512-QXUSXI3QVc/gJME0dBpXrag1kbzOqCjCX8/b54ntNyW6sjtoqxqRk3LTmXzaJoh71zMsDCjM+47jS7XiwN/+fQ==",
+ "license": "MIT"
+ },
+ "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",
+ "optional": true
+ },
+ "node_modules/borsh": {
+ "version": "0.7.0",
+ "resolved": "https://registry.npmjs.org/borsh/-/borsh-0.7.0.tgz",
+ "integrity": "sha512-CLCsZGIBCFnPtkNnieW/a8wmreDmfUtjU2m9yHrzPXIlNbqVs0AQrSatSG6vdNYUqdc83tkQi2eHfF98ubzQLA==",
+ "license": "Apache-2.0",
+ "optional": true,
+ "dependencies": {
+ "bn.js": "^5.2.0",
+ "bs58": "^4.0.0",
+ "text-encoding-utf-8": "^1.0.2"
+ }
+ },
+ "node_modules/borsh/node_modules/base-x": {
+ "version": "3.0.11",
+ "resolved": "https://registry.npmjs.org/base-x/-/base-x-3.0.11.tgz",
+ "integrity": "sha512-xz7wQ8xDhdyP7tQxwdteLYeFfS68tSMNCZ/Y37WJ4bhGfKPpqEIlmIyueQHqOyoPhE6xNUqjzRr8ra0eF9VRvA==",
+ "license": "MIT",
+ "optional": true,
+ "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==",
+ "license": "MIT",
+ "optional": true,
+ "dependencies": {
+ "base-x": "^3.0.2"
+ }
+ },
+ "node_modules/brace-expansion": {
+ "version": "1.1.12",
+ "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.12.tgz",
+ "integrity": "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "balanced-match": "^1.0.0",
+ "concat-map": "0.0.1"
+ }
+ },
+ "node_modules/browserslist": {
+ "version": "4.28.0",
+ "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.28.0.tgz",
+ "integrity": "sha512-tbydkR/CxfMwelN0vwdP/pLkDwyAASZ+VfWm4EOwlB6SWhx1sYnWLqo8N5j0rAzPfzfRaxt0mM/4wPU/Su84RQ==",
+ "dev": true,
+ "funding": [
+ {
+ "type": "opencollective",
+ "url": "https://opencollective.com/browserslist"
+ },
+ {
+ "type": "tidelift",
+ "url": "https://tidelift.com/funding/github/npm/browserslist"
+ },
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/ai"
+ }
+ ],
+ "license": "MIT",
+ "peer": true,
+ "dependencies": {
+ "baseline-browser-mapping": "^2.8.25",
+ "caniuse-lite": "^1.0.30001754",
+ "electron-to-chromium": "^1.5.249",
+ "node-releases": "^2.0.27",
+ "update-browserslist-db": "^1.1.4"
+ },
+ "bin": {
+ "browserslist": "cli.js"
+ },
+ "engines": {
+ "node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7"
+ }
+ },
+ "node_modules/bs58": {
+ "version": "6.0.0",
+ "resolved": "https://registry.npmjs.org/bs58/-/bs58-6.0.0.tgz",
+ "integrity": "sha512-PD0wEnEYg6ijszw/u8s+iI3H17cTymlrwkKhDhPZq+Sokl3AU4htyBFTjAeNAlCCmg0f53g6ih3jATyCKftTfw==",
+ "license": "MIT",
+ "dependencies": {
+ "base-x": "^5.0.0"
+ }
+ },
+ "node_modules/buffer": {
+ "version": "6.0.3",
+ "resolved": "https://registry.npmjs.org/buffer/-/buffer-6.0.3.tgz",
+ "integrity": "sha512-FTiCpNxtwiZZHEZbcbTIcZjERVICn9yq/pDFkTl95/AxzD1naBctN7YO68riM/gLSDY7sdrMby8hofADYuuqOA==",
+ "funding": [
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/feross"
+ },
+ {
+ "type": "patreon",
+ "url": "https://www.patreon.com/feross"
+ },
+ {
+ "type": "consulting",
+ "url": "https://feross.org/support"
+ }
+ ],
+ "license": "MIT",
+ "dependencies": {
+ "base64-js": "^1.3.1",
+ "ieee754": "^1.2.1"
+ }
+ },
+ "node_modules/call-bind-apply-helpers": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/call-bind-apply-helpers/-/call-bind-apply-helpers-1.0.2.tgz",
+ "integrity": "sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ==",
+ "license": "MIT",
+ "optional": true,
+ "dependencies": {
+ "es-errors": "^1.3.0",
+ "function-bind": "^1.1.2"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ }
+ },
+ "node_modules/callsites": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz",
+ "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/camelcase": {
+ "version": "5.3.1",
+ "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz",
+ "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/caniuse-lite": {
+ "version": "1.0.30001757",
+ "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001757.tgz",
+ "integrity": "sha512-r0nnL/I28Zi/yjk1el6ilj27tKcdjLsNqAOZr0yVjWPrSQyHgKI2INaEWw21bAQSv2LXRt1XuCS/GomNpWOxsQ==",
+ "dev": true,
+ "funding": [
+ {
+ "type": "opencollective",
+ "url": "https://opencollective.com/browserslist"
+ },
+ {
+ "type": "tidelift",
+ "url": "https://tidelift.com/funding/github/npm/caniuse-lite"
+ },
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/ai"
+ }
+ ],
+ "license": "CC-BY-4.0"
+ },
+ "node_modules/chalk": {
+ "version": "5.6.2",
+ "resolved": "https://registry.npmjs.org/chalk/-/chalk-5.6.2.tgz",
+ "integrity": "sha512-7NzBL0rN6fMUW+f7A6Io4h40qQlG+xGmtMxfbnH/K7TAtt8JQWVQK+6g0UXKMeVJoyV5EkkNsErQ8pVD3bLHbA==",
+ "license": "MIT",
+ "optional": true,
+ "engines": {
+ "node": "^12.17.0 || ^14.13 || >=16.0.0"
+ },
+ "funding": {
+ "url": "https://github.com/chalk/chalk?sponsor=1"
+ }
+ },
+ "node_modules/charenc": {
+ "version": "0.0.2",
+ "resolved": "https://registry.npmjs.org/charenc/-/charenc-0.0.2.tgz",
+ "integrity": "sha512-yrLQ/yVUFXkzg7EDQsPieE/53+0RlaWTs+wBrvW36cyilJ2SaDWfl4Yj7MtLTXleV9uEKefbAGUPv2/iWSooRA==",
+ "license": "BSD-3-Clause",
+ "optional": true,
+ "engines": {
+ "node": "*"
+ }
+ },
+ "node_modules/chokidar": {
+ "version": "4.0.3",
+ "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-4.0.3.tgz",
+ "integrity": "sha512-Qgzu8kfBvo+cA4962jnP1KkS6Dop5NS6g7R5LFYJr4b8Ub94PPQXUksCw9PvXoeXPRRddRNC5C1JQUR2SMGtnA==",
+ "license": "MIT",
+ "dependencies": {
+ "readdirp": "^4.0.1"
+ },
+ "engines": {
+ "node": ">= 14.16.0"
+ },
+ "funding": {
+ "url": "https://paulmillr.com/funding/"
+ }
+ },
+ "node_modules/cliui": {
+ "version": "6.0.0",
+ "resolved": "https://registry.npmjs.org/cliui/-/cliui-6.0.0.tgz",
+ "integrity": "sha512-t6wbgtoCXvAzst7QgXxJYqPt0usEfbgQdftEPbLL/cvv6HPE5VgvqCuAIDR0NgU52ds6rFwqrgakNLrHEjCbrQ==",
+ "license": "ISC",
+ "dependencies": {
+ "string-width": "^4.2.0",
+ "strip-ansi": "^6.0.0",
+ "wrap-ansi": "^6.2.0"
+ }
+ },
+ "node_modules/clsx": {
+ "version": "1.2.1",
+ "resolved": "https://registry.npmjs.org/clsx/-/clsx-1.2.1.tgz",
+ "integrity": "sha512-EcR6r5a8bj6pu3ycsa/E/cKVGuTgZJZdsyUYHOksG/UHIiKfjxzRxYJpyVBwYaQeOvghal9fcc4PidlgzugAQg==",
+ "license": "MIT",
+ "optional": true,
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/color-convert": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz",
+ "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==",
+ "license": "MIT",
+ "dependencies": {
+ "color-name": "~1.1.4"
+ },
+ "engines": {
+ "node": ">=7.0.0"
+ }
+ },
+ "node_modules/color-name": {
+ "version": "1.1.4",
+ "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz",
+ "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==",
+ "license": "MIT"
+ },
+ "node_modules/combined-stream": {
+ "version": "1.0.8",
+ "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz",
+ "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==",
+ "license": "MIT",
+ "optional": true,
+ "dependencies": {
+ "delayed-stream": "~1.0.0"
+ },
+ "engines": {
+ "node": ">= 0.8"
+ }
+ },
+ "node_modules/commander": {
+ "version": "14.0.0",
+ "resolved": "https://registry.npmjs.org/commander/-/commander-14.0.0.tgz",
+ "integrity": "sha512-2uM9rYjPvyq39NwLRqaiLtWHyDC1FvryJDa2ATTVims5YAS4PupsEQsDvP14FqhFr0P49CYDugi59xaxJlTXRA==",
+ "license": "MIT",
+ "optional": true,
+ "engines": {
+ "node": ">=20"
+ }
+ },
+ "node_modules/concat-map": {
+ "version": "0.0.1",
+ "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz",
+ "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/convert-source-map": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-2.0.0.tgz",
+ "integrity": "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/cookie-es": {
+ "version": "1.2.2",
+ "resolved": "https://registry.npmjs.org/cookie-es/-/cookie-es-1.2.2.tgz",
+ "integrity": "sha512-+W7VmiVINB+ywl1HGXJXmrqkOhpKrIiVZV6tQuV54ZyQC7MMuBt81Vc336GMLoHBq5hV/F9eXgt5Mnx0Rha5Fg==",
+ "license": "MIT"
+ },
+ "node_modules/cross-fetch": {
+ "version": "3.2.0",
+ "resolved": "https://registry.npmjs.org/cross-fetch/-/cross-fetch-3.2.0.tgz",
+ "integrity": "sha512-Q+xVJLoGOeIMXZmbUK4HYk+69cQH6LudR0Vu/pRm2YlU/hDV9CiS0gKUMaWY5f2NeUH9C1nV3bsTlCo0FsTV1Q==",
+ "license": "MIT",
+ "dependencies": {
+ "node-fetch": "^2.7.0"
+ }
+ },
+ "node_modules/cross-spawn": {
+ "version": "7.0.6",
+ "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz",
+ "integrity": "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "path-key": "^3.1.0",
+ "shebang-command": "^2.0.0",
+ "which": "^2.0.1"
+ },
+ "engines": {
+ "node": ">= 8"
+ }
+ },
+ "node_modules/crossws": {
+ "version": "0.3.5",
+ "resolved": "https://registry.npmjs.org/crossws/-/crossws-0.3.5.tgz",
+ "integrity": "sha512-ojKiDvcmByhwa8YYqbQI/hg7MEU0NC03+pSdEq4ZUnZR9xXpwk7E43SMNGkn+JxJGPFtNvQ48+vV2p+P1ml5PA==",
+ "license": "MIT",
+ "dependencies": {
+ "uncrypto": "^0.1.3"
+ }
+ },
+ "node_modules/crypt": {
+ "version": "0.0.2",
+ "resolved": "https://registry.npmjs.org/crypt/-/crypt-0.0.2.tgz",
+ "integrity": "sha512-mCxBlsHFYh9C+HVpiEacem8FEBnMXgU9gy4zmNC+SXAZNB/1idgp/aulFJ4FgCi7GPEVbfyng092GqL2k2rmow==",
+ "license": "BSD-3-Clause",
+ "optional": true,
+ "engines": {
+ "node": "*"
+ }
+ },
+ "node_modules/csstype": {
+ "version": "3.2.3",
+ "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.2.3.tgz",
+ "integrity": "sha512-z1HGKcYy2xA8AGQfwrn0PAy+PB7X/GSj3UVJW9qKyn43xWa+gl5nXmU4qqLMRzWVLFC8KusUX8T/0kCiOYpAIQ==",
+ "devOptional": true,
+ "license": "MIT"
+ },
+ "node_modules/dayjs": {
+ "version": "1.11.13",
+ "resolved": "https://registry.npmjs.org/dayjs/-/dayjs-1.11.13.tgz",
+ "integrity": "sha512-oaMBel6gjolK862uaPQOVTA7q3TZhuSvuMQAAglQDOWYO9A91IrAOUJEyKVlqJlHE0vq5p5UXxzdPfMH/x6xNg==",
+ "license": "MIT"
+ },
+ "node_modules/debug": {
+ "version": "4.4.3",
+ "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz",
+ "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "ms": "^2.1.3"
+ },
+ "engines": {
+ "node": ">=6.0"
+ },
+ "peerDependenciesMeta": {
+ "supports-color": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/decamelize": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz",
+ "integrity": "sha512-z2S+W9X73hAUUki+N+9Za2lBlun89zigOyGrsax+KUQ6wKW4ZoWpEYBkGhQjwAjjDCkWxhY0VKEhk8wzY7F5cA==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/deep-is": {
+ "version": "0.1.4",
+ "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz",
+ "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/defu": {
+ "version": "6.1.4",
+ "resolved": "https://registry.npmjs.org/defu/-/defu-6.1.4.tgz",
+ "integrity": "sha512-mEQCMmwJu317oSz8CwdIOdwf3xMif1ttiM8LTufzc3g6kR+9Pe236twL8j3IYT1F7GfRgGcW6MWxzZjLIkuHIg==",
+ "license": "MIT"
+ },
+ "node_modules/delay": {
+ "version": "5.0.0",
+ "resolved": "https://registry.npmjs.org/delay/-/delay-5.0.0.tgz",
+ "integrity": "sha512-ReEBKkIfe4ya47wlPYf/gu5ib6yUG0/Aez0JQZQz94kiWtRQvZIQbTiehsnwHvLSWJnQdhVeqYue7Id1dKr0qw==",
+ "license": "MIT",
+ "optional": true,
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/delayed-stream": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz",
+ "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==",
+ "license": "MIT",
+ "optional": true,
+ "engines": {
+ "node": ">=0.4.0"
+ }
+ },
+ "node_modules/destr": {
+ "version": "2.0.5",
+ "resolved": "https://registry.npmjs.org/destr/-/destr-2.0.5.tgz",
+ "integrity": "sha512-ugFTXCtDZunbzasqBxrK93Ik/DRYsO6S/fedkWEMKqt04xZ4csmnmwGDBAb07QWNaGMAmnTIemsYZCksjATwsA==",
+ "license": "MIT"
+ },
+ "node_modules/detect-browser": {
+ "version": "5.3.0",
+ "resolved": "https://registry.npmjs.org/detect-browser/-/detect-browser-5.3.0.tgz",
+ "integrity": "sha512-53rsFbGdwMwlF7qvCt0ypLM5V5/Mbl0szB7GPN8y9NCcbknYOeVVXdrXEq+90IwAfrrzt6Hd+u2E2ntakICU8w==",
+ "license": "MIT"
+ },
+ "node_modules/dijkstrajs": {
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/dijkstrajs/-/dijkstrajs-1.0.3.tgz",
+ "integrity": "sha512-qiSlmBq9+BCdCA/L46dw8Uy93mloxsPSbwnm5yrKn2vMPiy8KyAskTF6zuV/j5BMsmOGZDPs7KjU+mjb670kfA==",
+ "license": "MIT"
+ },
+ "node_modules/dunder-proto": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/dunder-proto/-/dunder-proto-1.0.1.tgz",
+ "integrity": "sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==",
+ "license": "MIT",
+ "optional": true,
+ "dependencies": {
+ "call-bind-apply-helpers": "^1.0.1",
+ "es-errors": "^1.3.0",
+ "gopd": "^1.2.0"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ }
+ },
+ "node_modules/electron-to-chromium": {
+ "version": "1.5.262",
+ "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.262.tgz",
+ "integrity": "sha512-NlAsMteRHek05jRUxUR0a5jpjYq9ykk6+kO0yRaMi5moe7u0fVIOeQ3Y30A8dIiWFBNUoQGi1ljb1i5VtS9WQQ==",
+ "dev": true,
+ "license": "ISC"
+ },
+ "node_modules/emoji-regex": {
+ "version": "8.0.0",
+ "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz",
+ "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==",
+ "license": "MIT"
+ },
+ "node_modules/encode-utf8": {
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/encode-utf8/-/encode-utf8-1.0.3.tgz",
+ "integrity": "sha512-ucAnuBEhUK4boH2HjVYG5Q2mQyPorvv0u/ocS+zhdw0S8AlHYY+GOFhP1Gio5z4icpP2ivFSvhtFjQi8+T9ppw==",
+ "license": "MIT"
+ },
+ "node_modules/es-define-property": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.1.tgz",
+ "integrity": "sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g==",
+ "license": "MIT",
+ "optional": true,
+ "engines": {
+ "node": ">= 0.4"
+ }
+ },
+ "node_modules/es-errors": {
+ "version": "1.3.0",
+ "resolved": "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz",
+ "integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==",
+ "license": "MIT",
+ "optional": true,
+ "engines": {
+ "node": ">= 0.4"
+ }
+ },
+ "node_modules/es-object-atoms": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/es-object-atoms/-/es-object-atoms-1.1.1.tgz",
+ "integrity": "sha512-FGgH2h8zKNim9ljj7dankFPcICIK9Cp5bm+c2gQSYePhpaG5+esrLODihIorn+Pe6FGJzWhXQotPv73jTaldXA==",
+ "license": "MIT",
+ "optional": true,
+ "dependencies": {
+ "es-errors": "^1.3.0"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ }
+ },
+ "node_modules/es-set-tostringtag": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/es-set-tostringtag/-/es-set-tostringtag-2.1.0.tgz",
+ "integrity": "sha512-j6vWzfrGVfyXxge+O0x5sh6cvxAog0a/4Rdd2K36zCMV5eJ+/+tOAngRO8cODMNWbVRdVlmGZQL2YS3yR8bIUA==",
+ "license": "MIT",
+ "optional": true,
+ "dependencies": {
+ "es-errors": "^1.3.0",
+ "get-intrinsic": "^1.2.6",
+ "has-tostringtag": "^1.0.2",
+ "hasown": "^2.0.2"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ }
+ },
+ "node_modules/es-toolkit": {
+ "version": "1.39.3",
+ "resolved": "https://registry.npmjs.org/es-toolkit/-/es-toolkit-1.39.3.tgz",
+ "integrity": "sha512-Qb/TCFCldgOy8lZ5uC7nLGdqJwSabkQiYQShmw4jyiPk1pZzaYWTwaYKYP7EgLccWYgZocMrtItrwh683voaww==",
+ "license": "MIT",
+ "workspaces": [
+ "docs",
+ "benchmarks"
+ ]
+ },
+ "node_modules/es6-promise": {
+ "version": "4.2.8",
+ "resolved": "https://registry.npmjs.org/es6-promise/-/es6-promise-4.2.8.tgz",
+ "integrity": "sha512-HJDGx5daxeIvxdBxvG2cb9g4tEvwIk3i8+nhX0yGrYmZUzbkdg8QbDevheDB8gd0//uPj4c1EQua8Q+MViT0/w==",
+ "license": "MIT",
+ "optional": true
+ },
+ "node_modules/es6-promisify": {
+ "version": "5.0.0",
+ "resolved": "https://registry.npmjs.org/es6-promisify/-/es6-promisify-5.0.0.tgz",
+ "integrity": "sha512-C+d6UdsYDk0lMebHNR4S2NybQMMngAOnOwYBQjTOiv0MkoJMP0Myw2mgpDLBcpfCmRLxyFqYhS/CfOENq4SJhQ==",
+ "license": "MIT",
+ "optional": true,
+ "dependencies": {
+ "es6-promise": "^4.0.3"
+ }
+ },
+ "node_modules/esbuild": {
+ "version": "0.25.12",
+ "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.25.12.tgz",
+ "integrity": "sha512-bbPBYYrtZbkt6Os6FiTLCTFxvq4tt3JKall1vRwshA3fdVztsLAatFaZobhkBC8/BrPetoa0oksYoKXoG4ryJg==",
+ "dev": true,
+ "hasInstallScript": true,
+ "license": "MIT",
+ "bin": {
+ "esbuild": "bin/esbuild"
+ },
+ "engines": {
+ "node": ">=18"
+ },
+ "optionalDependencies": {
+ "@esbuild/aix-ppc64": "0.25.12",
+ "@esbuild/android-arm": "0.25.12",
+ "@esbuild/android-arm64": "0.25.12",
+ "@esbuild/android-x64": "0.25.12",
+ "@esbuild/darwin-arm64": "0.25.12",
+ "@esbuild/darwin-x64": "0.25.12",
+ "@esbuild/freebsd-arm64": "0.25.12",
+ "@esbuild/freebsd-x64": "0.25.12",
+ "@esbuild/linux-arm": "0.25.12",
+ "@esbuild/linux-arm64": "0.25.12",
+ "@esbuild/linux-ia32": "0.25.12",
+ "@esbuild/linux-loong64": "0.25.12",
+ "@esbuild/linux-mips64el": "0.25.12",
+ "@esbuild/linux-ppc64": "0.25.12",
+ "@esbuild/linux-riscv64": "0.25.12",
+ "@esbuild/linux-s390x": "0.25.12",
+ "@esbuild/linux-x64": "0.25.12",
+ "@esbuild/netbsd-arm64": "0.25.12",
+ "@esbuild/netbsd-x64": "0.25.12",
+ "@esbuild/openbsd-arm64": "0.25.12",
+ "@esbuild/openbsd-x64": "0.25.12",
+ "@esbuild/openharmony-arm64": "0.25.12",
+ "@esbuild/sunos-x64": "0.25.12",
+ "@esbuild/win32-arm64": "0.25.12",
+ "@esbuild/win32-ia32": "0.25.12",
+ "@esbuild/win32-x64": "0.25.12"
+ }
+ },
+ "node_modules/escalade": {
+ "version": "3.2.0",
+ "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.2.0.tgz",
+ "integrity": "sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/escape-string-regexp": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz",
+ "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/eslint": {
+ "version": "9.39.1",
+ "resolved": "https://registry.npmjs.org/eslint/-/eslint-9.39.1.tgz",
+ "integrity": "sha512-BhHmn2yNOFA9H9JmmIVKJmd288g9hrVRDkdoIgRCRuSySRUHH7r/DI6aAXW9T1WwUuY3DFgrcaqB+deURBLR5g==",
+ "dev": true,
+ "license": "MIT",
+ "peer": true,
+ "dependencies": {
+ "@eslint-community/eslint-utils": "^4.8.0",
+ "@eslint-community/regexpp": "^4.12.1",
+ "@eslint/config-array": "^0.21.1",
+ "@eslint/config-helpers": "^0.4.2",
+ "@eslint/core": "^0.17.0",
+ "@eslint/eslintrc": "^3.3.1",
+ "@eslint/js": "9.39.1",
+ "@eslint/plugin-kit": "^0.4.1",
+ "@humanfs/node": "^0.16.6",
+ "@humanwhocodes/module-importer": "^1.0.1",
+ "@humanwhocodes/retry": "^0.4.2",
+ "@types/estree": "^1.0.6",
+ "ajv": "^6.12.4",
+ "chalk": "^4.0.0",
+ "cross-spawn": "^7.0.6",
+ "debug": "^4.3.2",
+ "escape-string-regexp": "^4.0.0",
+ "eslint-scope": "^8.4.0",
+ "eslint-visitor-keys": "^4.2.1",
+ "espree": "^10.4.0",
+ "esquery": "^1.5.0",
+ "esutils": "^2.0.2",
+ "fast-deep-equal": "^3.1.3",
+ "file-entry-cache": "^8.0.0",
+ "find-up": "^5.0.0",
+ "glob-parent": "^6.0.2",
+ "ignore": "^5.2.0",
+ "imurmurhash": "^0.1.4",
+ "is-glob": "^4.0.0",
+ "json-stable-stringify-without-jsonify": "^1.0.1",
+ "lodash.merge": "^4.6.2",
+ "minimatch": "^3.1.2",
+ "natural-compare": "^1.4.0",
+ "optionator": "^0.9.3"
+ },
+ "bin": {
+ "eslint": "bin/eslint.js"
+ },
+ "engines": {
+ "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
+ },
+ "funding": {
+ "url": "https://eslint.org/donate"
+ },
+ "peerDependencies": {
+ "jiti": "*"
+ },
+ "peerDependenciesMeta": {
+ "jiti": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/eslint-plugin-react-hooks": {
+ "version": "7.0.1",
+ "resolved": "https://registry.npmjs.org/eslint-plugin-react-hooks/-/eslint-plugin-react-hooks-7.0.1.tgz",
+ "integrity": "sha512-O0d0m04evaNzEPoSW+59Mezf8Qt0InfgGIBJnpC0h3NH/WjUAR7BIKUfysC6todmtiZ/A0oUVS8Gce0WhBrHsA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@babel/core": "^7.24.4",
+ "@babel/parser": "^7.24.4",
+ "hermes-parser": "^0.25.1",
+ "zod": "^3.25.0 || ^4.0.0",
+ "zod-validation-error": "^3.5.0 || ^4.0.0"
+ },
+ "engines": {
+ "node": ">=18"
+ },
+ "peerDependencies": {
+ "eslint": "^3.0.0 || ^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0-0 || ^9.0.0"
+ }
+ },
+ "node_modules/eslint-plugin-react-refresh": {
+ "version": "0.4.24",
+ "resolved": "https://registry.npmjs.org/eslint-plugin-react-refresh/-/eslint-plugin-react-refresh-0.4.24.tgz",
+ "integrity": "sha512-nLHIW7TEq3aLrEYWpVaJ1dRgFR+wLDPN8e8FpYAql/bMV2oBEfC37K0gLEGgv9fy66juNShSMV8OkTqzltcG/w==",
+ "dev": true,
+ "license": "MIT",
+ "peerDependencies": {
+ "eslint": ">=8.40"
+ }
+ },
+ "node_modules/eslint-scope": {
+ "version": "8.4.0",
+ "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-8.4.0.tgz",
+ "integrity": "sha512-sNXOfKCn74rt8RICKMvJS7XKV/Xk9kA7DyJr8mJik3S7Cwgy3qlkkmyS2uQB3jiJg6VNdZd/pDBJu0nvG2NlTg==",
+ "dev": true,
+ "license": "BSD-2-Clause",
+ "dependencies": {
+ "esrecurse": "^4.3.0",
+ "estraverse": "^5.2.0"
+ },
+ "engines": {
+ "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
+ },
+ "funding": {
+ "url": "https://opencollective.com/eslint"
+ }
+ },
+ "node_modules/eslint-visitor-keys": {
+ "version": "4.2.1",
+ "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-4.2.1.tgz",
+ "integrity": "sha512-Uhdk5sfqcee/9H/rCOJikYz67o0a2Tw2hGRPOG2Y1R2dg7brRe1uG0yaNQDHu+TO/uQPF/5eCapvYSmHUjt7JQ==",
+ "dev": true,
+ "license": "Apache-2.0",
+ "engines": {
+ "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
+ },
+ "funding": {
+ "url": "https://opencollective.com/eslint"
+ }
+ },
+ "node_modules/eslint/node_modules/chalk": {
+ "version": "4.1.2",
+ "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz",
+ "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "ansi-styles": "^4.1.0",
+ "supports-color": "^7.1.0"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/chalk/chalk?sponsor=1"
+ }
+ },
+ "node_modules/espree": {
+ "version": "10.4.0",
+ "resolved": "https://registry.npmjs.org/espree/-/espree-10.4.0.tgz",
+ "integrity": "sha512-j6PAQ2uUr79PZhBjP5C5fhl8e39FmRnOjsD5lGnWrFU8i2G776tBK7+nP8KuQUTTyAZUwfQqXAgrVH5MbH9CYQ==",
+ "dev": true,
+ "license": "BSD-2-Clause",
+ "dependencies": {
+ "acorn": "^8.15.0",
+ "acorn-jsx": "^5.3.2",
+ "eslint-visitor-keys": "^4.2.1"
+ },
+ "engines": {
+ "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
+ },
+ "funding": {
+ "url": "https://opencollective.com/eslint"
+ }
+ },
+ "node_modules/esquery": {
+ "version": "1.6.0",
+ "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.6.0.tgz",
+ "integrity": "sha512-ca9pw9fomFcKPvFLXhBKUK90ZvGibiGOvRJNbjljY7s7uq/5YO4BOzcYtJqExdx99rF6aAcnRxHmcUHcz6sQsg==",
+ "dev": true,
+ "license": "BSD-3-Clause",
+ "dependencies": {
+ "estraverse": "^5.1.0"
+ },
+ "engines": {
+ "node": ">=0.10"
+ }
+ },
+ "node_modules/esrecurse": {
+ "version": "4.3.0",
+ "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz",
+ "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==",
+ "dev": true,
+ "license": "BSD-2-Clause",
+ "dependencies": {
+ "estraverse": "^5.2.0"
+ },
+ "engines": {
+ "node": ">=4.0"
+ }
+ },
+ "node_modules/estraverse": {
+ "version": "5.3.0",
+ "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz",
+ "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==",
+ "dev": true,
+ "license": "BSD-2-Clause",
+ "engines": {
+ "node": ">=4.0"
+ }
+ },
+ "node_modules/esutils": {
+ "version": "2.0.3",
+ "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz",
+ "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==",
+ "dev": true,
+ "license": "BSD-2-Clause",
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/ethers": {
+ "version": "6.16.0",
+ "resolved": "https://registry.npmjs.org/ethers/-/ethers-6.16.0.tgz",
+ "integrity": "sha512-U1wulmetNymijEhpSEQ7Ct/P/Jw9/e7R1j5XIbPRydgV2DjLVMsULDlNksq3RQnFgKoLlZf88ijYtWEXcPa07A==",
+ "funding": [
+ {
+ "type": "individual",
+ "url": "https://github.com/sponsors/ethers-io/"
+ },
+ {
+ "type": "individual",
+ "url": "https://www.buymeacoffee.com/ricmoo"
+ }
+ ],
+ "license": "MIT",
+ "peer": true,
+ "dependencies": {
+ "@adraffy/ens-normalize": "1.10.1",
+ "@noble/curves": "1.2.0",
+ "@noble/hashes": "1.3.2",
+ "@types/node": "22.7.5",
+ "aes-js": "4.0.0-beta.5",
+ "tslib": "2.7.0",
+ "ws": "8.17.1"
+ },
+ "engines": {
+ "node": ">=14.0.0"
+ }
+ },
+ "node_modules/ethers/node_modules/@noble/curves": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/@noble/curves/-/curves-1.2.0.tgz",
+ "integrity": "sha512-oYclrNgRaM9SsBUBVbb8M6DTV7ZHRTKugureoYEncY5c65HOmRzvSiTE3y5CYaPYJA/GVkrhXEoF0M3Ya9PMnw==",
+ "license": "MIT",
+ "dependencies": {
+ "@noble/hashes": "1.3.2"
+ },
+ "funding": {
+ "url": "https://paulmillr.com/funding/"
+ }
+ },
+ "node_modules/ethers/node_modules/@noble/hashes": {
+ "version": "1.3.2",
+ "resolved": "https://registry.npmjs.org/@noble/hashes/-/hashes-1.3.2.tgz",
+ "integrity": "sha512-MVC8EAQp7MvEcm30KWENFjgR+Mkmf+D189XJTkFIlwohU5hcBbn1ZkKq7KVTi2Hme3PMGF390DaL52beVrIihQ==",
+ "license": "MIT",
+ "engines": {
+ "node": ">= 16"
+ },
+ "funding": {
+ "url": "https://paulmillr.com/funding/"
+ }
+ },
+ "node_modules/ethers/node_modules/@types/node": {
+ "version": "22.7.5",
+ "resolved": "https://registry.npmjs.org/@types/node/-/node-22.7.5.tgz",
+ "integrity": "sha512-jML7s2NAzMWc//QSJ1a3prpk78cOPchGvXJsC3C6R6PSMoooztvRVQEz89gmBTBY1SPMaqo5teB4uNHPdetShQ==",
+ "license": "MIT",
+ "dependencies": {
+ "undici-types": "~6.19.2"
+ }
+ },
+ "node_modules/ethers/node_modules/tslib": {
+ "version": "2.7.0",
+ "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.7.0.tgz",
+ "integrity": "sha512-gLXCKdN1/j47AiHiOkJN69hJmcbGTHI0ImLmbYLHykhgeN0jVGola9yVjFgzCUklsZQMW55o+dW7IXv3RCXDzA==",
+ "license": "0BSD"
+ },
+ "node_modules/ethers/node_modules/undici-types": {
+ "version": "6.19.8",
+ "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.19.8.tgz",
+ "integrity": "sha512-ve2KP6f/JnbPBFyobGHuerC9g1FYGn/F8n1LWTwNxCEzd6IfqTwUQcNXgEtmmQ6DlRrC1hrSrBnCZPokRrDHjw==",
+ "license": "MIT"
+ },
+ "node_modules/ethers/node_modules/ws": {
+ "version": "8.17.1",
+ "resolved": "https://registry.npmjs.org/ws/-/ws-8.17.1.tgz",
+ "integrity": "sha512-6XQFvXTkbfUOZOKKILFG1PDK2NDQs4azKQl26T0YS5CxqWLgXajbPZ+h4gZekJyRqFU8pvnbAbbs/3TgRPy+GQ==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=10.0.0"
+ },
+ "peerDependencies": {
+ "bufferutil": "^4.0.1",
+ "utf-8-validate": ">=5.0.2"
+ },
+ "peerDependenciesMeta": {
+ "bufferutil": {
+ "optional": true
+ },
+ "utf-8-validate": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/eventemitter3": {
+ "version": "5.0.1",
+ "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-5.0.1.tgz",
+ "integrity": "sha512-GWkBvjiSZK87ELrYOSESUYeVIc9mvLLf/nXalMOS5dYrgZq9o5OVkbZAVM06CVxYsCwH9BDZFPlQTlPA1j4ahA==",
+ "license": "MIT"
+ },
+ "node_modules/events": {
+ "version": "3.3.0",
+ "resolved": "https://registry.npmjs.org/events/-/events-3.3.0.tgz",
+ "integrity": "sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=0.8.x"
+ }
+ },
+ "node_modules/eyes": {
+ "version": "0.1.8",
+ "resolved": "https://registry.npmjs.org/eyes/-/eyes-0.1.8.tgz",
+ "integrity": "sha512-GipyPsXO1anza0AOZdy69Im7hGFCNB7Y/NGjDlZGJ3GJJLtwNSb2vrzYrTYJRrRloVx7pl+bhUaTB8yiccPvFQ==",
+ "optional": true,
+ "engines": {
+ "node": "> 0.1.90"
+ }
+ },
+ "node_modules/fast-deep-equal": {
+ "version": "3.1.3",
+ "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz",
+ "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/fast-json-stable-stringify": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz",
+ "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/fast-levenshtein": {
+ "version": "2.0.6",
+ "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz",
+ "integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/fast-stable-stringify": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/fast-stable-stringify/-/fast-stable-stringify-1.0.0.tgz",
+ "integrity": "sha512-wpYMUmFu5f00Sm0cj2pfivpmawLZ0NKdviQ4w9zJeR8JVtOpOxHmLaJuj0vxvGqMJQWyP/COUkF75/57OKyRag==",
+ "license": "MIT",
+ "optional": true
+ },
+ "node_modules/fdir": {
+ "version": "6.5.0",
+ "resolved": "https://registry.npmjs.org/fdir/-/fdir-6.5.0.tgz",
+ "integrity": "sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=12.0.0"
+ },
+ "peerDependencies": {
+ "picomatch": "^3 || ^4"
+ },
+ "peerDependenciesMeta": {
+ "picomatch": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/file-entry-cache": {
+ "version": "8.0.0",
+ "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-8.0.0.tgz",
+ "integrity": "sha512-XXTUwCvisa5oacNGRP9SfNtYBNAMi+RPwBFmblZEF7N7swHYQS6/Zfk7SRwx4D5j3CH211YNRco1DEMNVfZCnQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "flat-cache": "^4.0.0"
+ },
+ "engines": {
+ "node": ">=16.0.0"
+ }
+ },
+ "node_modules/find-up": {
+ "version": "5.0.0",
+ "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz",
+ "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "locate-path": "^6.0.0",
+ "path-exists": "^4.0.0"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/flat-cache": {
+ "version": "4.0.1",
+ "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-4.0.1.tgz",
+ "integrity": "sha512-f7ccFPK3SXFHpx15UIGyRJ/FJQctuKZ0zVuN3frBo4HnK3cay9VEW0R6yPYFHC0AgqhukPzKjq22t5DmAyqGyw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "flatted": "^3.2.9",
+ "keyv": "^4.5.4"
+ },
+ "engines": {
+ "node": ">=16"
+ }
+ },
+ "node_modules/flatted": {
+ "version": "3.3.3",
+ "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.3.3.tgz",
+ "integrity": "sha512-GX+ysw4PBCz0PzosHDepZGANEuFCMLrnRTiEy9McGjmkCQYwRq4A/X786G/fjM/+OjsWSU1ZrY5qyARZmO/uwg==",
+ "dev": true,
+ "license": "ISC"
+ },
+ "node_modules/follow-redirects": {
+ "version": "1.15.11",
+ "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.11.tgz",
+ "integrity": "sha512-deG2P0JfjrTxl50XGCDyfI97ZGVCxIpfKYmfyrQ54n5FO/0gfIES8C/Psl6kWVDolizcaaxZJnTS0QSMxvnsBQ==",
+ "funding": [
+ {
+ "type": "individual",
+ "url": "https://github.com/sponsors/RubenVerborgh"
+ }
+ ],
+ "license": "MIT",
+ "optional": true,
+ "engines": {
+ "node": ">=4.0"
+ },
+ "peerDependenciesMeta": {
+ "debug": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/form-data": {
+ "version": "4.0.5",
+ "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.5.tgz",
+ "integrity": "sha512-8RipRLol37bNs2bhoV67fiTEvdTrbMUYcFTiy3+wuuOnUog2QBHCZWXDRijWQfAkhBj2Uf5UnVaiWwA5vdd82w==",
+ "license": "MIT",
+ "optional": true,
+ "dependencies": {
+ "asynckit": "^0.4.0",
+ "combined-stream": "^1.0.8",
+ "es-set-tostringtag": "^2.1.0",
+ "hasown": "^2.0.2",
+ "mime-types": "^2.1.12"
+ },
+ "engines": {
+ "node": ">= 6"
+ }
+ },
+ "node_modules/fsevents": {
+ "version": "2.3.3",
+ "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz",
+ "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==",
+ "dev": true,
+ "hasInstallScript": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "darwin"
+ ],
+ "engines": {
+ "node": "^8.16.0 || ^10.6.0 || >=11.0.0"
+ }
+ },
+ "node_modules/function-bind": {
+ "version": "1.1.2",
+ "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz",
+ "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==",
+ "license": "MIT",
+ "optional": true,
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/gensync": {
+ "version": "1.0.0-beta.2",
+ "resolved": "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.2.tgz",
+ "integrity": "sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/get-caller-file": {
+ "version": "2.0.5",
+ "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz",
+ "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==",
+ "license": "ISC",
+ "engines": {
+ "node": "6.* || 8.* || >= 10.*"
+ }
+ },
+ "node_modules/get-intrinsic": {
+ "version": "1.3.0",
+ "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.3.0.tgz",
+ "integrity": "sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ==",
+ "license": "MIT",
+ "optional": true,
+ "dependencies": {
+ "call-bind-apply-helpers": "^1.0.2",
+ "es-define-property": "^1.0.1",
+ "es-errors": "^1.3.0",
+ "es-object-atoms": "^1.1.1",
+ "function-bind": "^1.1.2",
+ "get-proto": "^1.0.1",
+ "gopd": "^1.2.0",
+ "has-symbols": "^1.1.0",
+ "hasown": "^2.0.2",
+ "math-intrinsics": "^1.1.0"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/get-proto": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/get-proto/-/get-proto-1.0.1.tgz",
+ "integrity": "sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g==",
+ "license": "MIT",
+ "optional": true,
+ "dependencies": {
+ "dunder-proto": "^1.0.1",
+ "es-object-atoms": "^1.0.0"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ }
+ },
+ "node_modules/glob-parent": {
+ "version": "6.0.2",
+ "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz",
+ "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==",
+ "dev": true,
+ "license": "ISC",
+ "dependencies": {
+ "is-glob": "^4.0.3"
+ },
+ "engines": {
+ "node": ">=10.13.0"
+ }
+ },
+ "node_modules/globals": {
+ "version": "16.5.0",
+ "resolved": "https://registry.npmjs.org/globals/-/globals-16.5.0.tgz",
+ "integrity": "sha512-c/c15i26VrJ4IRt5Z89DnIzCGDn9EcebibhAOjw5ibqEHsE1wLUgkPn9RDmNcUKyU87GeaL633nyJ+pplFR2ZQ==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=18"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/gopd": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.2.0.tgz",
+ "integrity": "sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==",
+ "license": "MIT",
+ "optional": true,
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/graphemer": {
+ "version": "1.4.0",
+ "resolved": "https://registry.npmjs.org/graphemer/-/graphemer-1.4.0.tgz",
+ "integrity": "sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/h3": {
+ "version": "1.15.4",
+ "resolved": "https://registry.npmjs.org/h3/-/h3-1.15.4.tgz",
+ "integrity": "sha512-z5cFQWDffyOe4vQ9xIqNfCZdV4p//vy6fBnr8Q1AWnVZ0teurKMG66rLj++TKwKPUP3u7iMUvrvKaEUiQw2QWQ==",
+ "license": "MIT",
+ "dependencies": {
+ "cookie-es": "^1.2.2",
+ "crossws": "^0.3.5",
+ "defu": "^6.1.4",
+ "destr": "^2.0.5",
+ "iron-webcrypto": "^1.2.1",
+ "node-mock-http": "^1.0.2",
+ "radix3": "^1.1.2",
+ "ufo": "^1.6.1",
+ "uncrypto": "^0.1.3"
+ }
+ },
+ "node_modules/has-flag": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz",
+ "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/has-symbols": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.1.0.tgz",
+ "integrity": "sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ==",
+ "license": "MIT",
+ "optional": true,
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/has-tostringtag": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.2.tgz",
+ "integrity": "sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==",
+ "license": "MIT",
+ "optional": true,
+ "dependencies": {
+ "has-symbols": "^1.0.3"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/hash.js": {
+ "version": "1.1.7",
+ "resolved": "https://registry.npmjs.org/hash.js/-/hash.js-1.1.7.tgz",
+ "integrity": "sha512-taOaskGt4z4SOANNseOviYDvjEJinIkRgmp7LbKP2YTTmVxWBl87s/uzK9r+44BclBSp2X7K1hqeNfz9JbBeXA==",
+ "license": "MIT",
+ "dependencies": {
+ "inherits": "^2.0.3",
+ "minimalistic-assert": "^1.0.1"
+ }
+ },
+ "node_modules/hasown": {
+ "version": "2.0.2",
+ "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz",
+ "integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==",
+ "license": "MIT",
+ "optional": true,
+ "dependencies": {
+ "function-bind": "^1.1.2"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ }
+ },
+ "node_modules/hermes-estree": {
+ "version": "0.25.1",
+ "resolved": "https://registry.npmjs.org/hermes-estree/-/hermes-estree-0.25.1.tgz",
+ "integrity": "sha512-0wUoCcLp+5Ev5pDW2OriHC2MJCbwLwuRx+gAqMTOkGKJJiBCLjtrvy4PWUGn6MIVefecRpzoOZ/UV6iGdOr+Cw==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/hermes-parser": {
+ "version": "0.25.1",
+ "resolved": "https://registry.npmjs.org/hermes-parser/-/hermes-parser-0.25.1.tgz",
+ "integrity": "sha512-6pEjquH3rqaI6cYAXYPcz9MS4rY6R4ngRgrgfDshRptUZIc3lw0MCIJIGDj9++mfySOuPTHB4nrSW99BCvOPIA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "hermes-estree": "0.25.1"
+ }
+ },
+ "node_modules/humanize-ms": {
+ "version": "1.2.1",
+ "resolved": "https://registry.npmjs.org/humanize-ms/-/humanize-ms-1.2.1.tgz",
+ "integrity": "sha512-Fl70vYtsAFb/C06PTS9dZBo7ihau+Tu/DNCk/OyHhea07S+aeMWpFFkUaXRa8fI+ScZbEI8dfSxwY7gxZ9SAVQ==",
+ "license": "MIT",
+ "optional": true,
+ "dependencies": {
+ "ms": "^2.0.0"
+ }
+ },
+ "node_modules/idb-keyval": {
+ "version": "6.2.1",
+ "resolved": "https://registry.npmjs.org/idb-keyval/-/idb-keyval-6.2.1.tgz",
+ "integrity": "sha512-8Sb3veuYCyrZL+VBt9LJfZjLUPWVvqn8tG28VqYNFCo43KHcKuq+b4EiXGeuaLAQWL2YmyDgMp2aSpH9JHsEQg==",
+ "license": "Apache-2.0"
+ },
+ "node_modules/ieee754": {
+ "version": "1.2.1",
+ "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz",
+ "integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==",
+ "funding": [
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/feross"
+ },
+ {
+ "type": "patreon",
+ "url": "https://www.patreon.com/feross"
+ },
+ {
+ "type": "consulting",
+ "url": "https://feross.org/support"
+ }
+ ],
+ "license": "BSD-3-Clause"
+ },
+ "node_modules/ignore": {
+ "version": "5.3.2",
+ "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.2.tgz",
+ "integrity": "sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">= 4"
+ }
+ },
+ "node_modules/import-fresh": {
+ "version": "3.3.1",
+ "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.1.tgz",
+ "integrity": "sha512-TR3KfrTZTYLPB6jUjfx6MF9WcWrHL9su5TObK4ZkYgBdWKPOFoSoQIdEuTuR82pmtxH2spWG9h6etwfr1pLBqQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "parent-module": "^1.0.0",
+ "resolve-from": "^4.0.0"
+ },
+ "engines": {
+ "node": ">=6"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/imurmurhash": {
+ "version": "0.1.4",
+ "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz",
+ "integrity": "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=0.8.19"
+ }
+ },
+ "node_modules/inherits": {
+ "version": "2.0.4",
+ "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz",
+ "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==",
+ "license": "ISC"
+ },
+ "node_modules/iron-webcrypto": {
+ "version": "1.2.1",
+ "resolved": "https://registry.npmjs.org/iron-webcrypto/-/iron-webcrypto-1.2.1.tgz",
+ "integrity": "sha512-feOM6FaSr6rEABp/eDfVseKyTMDt+KGpeB35SkVn9Tyn0CqvVsY3EwI0v5i8nMHyJnzCIQf7nsy3p41TPkJZhg==",
+ "license": "MIT",
+ "funding": {
+ "url": "https://github.com/sponsors/brc-dd"
+ }
+ },
+ "node_modules/is-buffer": {
+ "version": "1.1.6",
+ "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz",
+ "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==",
+ "license": "MIT",
+ "optional": true
+ },
+ "node_modules/is-extglob": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz",
+ "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/is-fullwidth-code-point": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz",
+ "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/is-glob": {
+ "version": "4.0.3",
+ "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz",
+ "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "is-extglob": "^2.1.1"
+ },
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/is-retry-allowed": {
+ "version": "2.2.0",
+ "resolved": "https://registry.npmjs.org/is-retry-allowed/-/is-retry-allowed-2.2.0.tgz",
+ "integrity": "sha512-XVm7LOeLpTW4jV19QSH38vkswxoLud8sQ57YwJVTPWdiaI9I8keEhGFpBlslyVsgdQy4Opg8QOLb8YRgsyZiQg==",
+ "license": "MIT",
+ "optional": true,
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/isexe": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz",
+ "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==",
+ "dev": true,
+ "license": "ISC"
+ },
+ "node_modules/isomorphic-ws": {
+ "version": "4.0.1",
+ "resolved": "https://registry.npmjs.org/isomorphic-ws/-/isomorphic-ws-4.0.1.tgz",
+ "integrity": "sha512-BhBvN2MBpWTaSHdWRb/bwdZJ1WaehQ2L1KngkCkfLUGF0mAWAT1sQUQacEmQ0jXkFw/czDXPNQSL5u2/Krsz1w==",
+ "license": "MIT",
+ "optional": true,
+ "peerDependencies": {
+ "ws": "*"
+ }
+ },
+ "node_modules/isows": {
+ "version": "1.0.7",
+ "resolved": "https://registry.npmjs.org/isows/-/isows-1.0.7.tgz",
+ "integrity": "sha512-I1fSfDCZL5P0v33sVqeTDSpcstAg/N+wF5HS033mogOVIp4B+oHC7oOCsA3axAbBSGTJ8QubbNmnIRN/h8U7hg==",
+ "funding": [
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/wevm"
+ }
+ ],
+ "license": "MIT",
+ "peerDependencies": {
+ "ws": "*"
+ }
+ },
+ "node_modules/jayson": {
+ "version": "4.2.0",
+ "resolved": "https://registry.npmjs.org/jayson/-/jayson-4.2.0.tgz",
+ "integrity": "sha512-VfJ9t1YLwacIubLhONk0KFeosUBwstRWQ0IRT1KDjEjnVnSOVHC3uwugyV7L0c7R9lpVyrUGT2XWiBA1UTtpyg==",
+ "license": "MIT",
+ "optional": true,
+ "dependencies": {
+ "@types/connect": "^3.4.33",
+ "@types/node": "^12.12.54",
+ "@types/ws": "^7.4.4",
+ "commander": "^2.20.3",
+ "delay": "^5.0.0",
+ "es6-promisify": "^5.0.0",
+ "eyes": "^0.1.8",
+ "isomorphic-ws": "^4.0.1",
+ "json-stringify-safe": "^5.0.1",
+ "stream-json": "^1.9.1",
+ "uuid": "^8.3.2",
+ "ws": "^7.5.10"
+ },
+ "bin": {
+ "jayson": "bin/jayson.js"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/jayson/node_modules/@types/node": {
+ "version": "12.20.55",
+ "resolved": "https://registry.npmjs.org/@types/node/-/node-12.20.55.tgz",
+ "integrity": "sha512-J8xLz7q2OFulZ2cyGTLE1TbbZcjpno7FaN6zdJNrgAdrJ+DZzh/uFR6YrTb4C+nXakvud8Q4+rbhoIWlYQbUFQ==",
+ "license": "MIT",
+ "optional": true
+ },
+ "node_modules/jayson/node_modules/commander": {
+ "version": "2.20.3",
+ "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz",
+ "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==",
+ "license": "MIT",
+ "optional": true
+ },
+ "node_modules/jayson/node_modules/ws": {
+ "version": "7.5.10",
+ "resolved": "https://registry.npmjs.org/ws/-/ws-7.5.10.tgz",
+ "integrity": "sha512-+dbF1tHwZpXcbOJdVOkzLDxZP1ailvSxM6ZweXTegylPny803bFhA+vqBYw4s31NSAk4S2Qz+AKXK9a4wkdjcQ==",
+ "license": "MIT",
+ "optional": true,
+ "engines": {
+ "node": ">=8.3.0"
+ },
+ "peerDependencies": {
+ "bufferutil": "^4.0.1",
+ "utf-8-validate": "^5.0.2"
+ },
+ "peerDependenciesMeta": {
+ "bufferutil": {
+ "optional": true
+ },
+ "utf-8-validate": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/jose": {
+ "version": "6.1.2",
+ "resolved": "https://registry.npmjs.org/jose/-/jose-6.1.2.tgz",
+ "integrity": "sha512-MpcPtHLE5EmztuFIqB0vzHAWJPpmN1E6L4oo+kze56LIs3MyXIj9ZHMDxqOvkP38gBR7K1v3jqd4WU2+nrfONQ==",
+ "license": "MIT",
+ "optional": true,
+ "funding": {
+ "url": "https://github.com/sponsors/panva"
+ }
+ },
+ "node_modules/js-tokens": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz",
+ "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/js-yaml": {
+ "version": "4.1.1",
+ "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.1.tgz",
+ "integrity": "sha512-qQKT4zQxXl8lLwBtHMWwaTcGfFOZviOJet3Oy/xmGk2gZH677CJM9EvtfdSkgWcATZhj/55JZ0rmy3myCT5lsA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "argparse": "^2.0.1"
+ },
+ "bin": {
+ "js-yaml": "bin/js-yaml.js"
+ }
+ },
+ "node_modules/jsesc": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-3.1.0.tgz",
+ "integrity": "sha512-/sM3dO2FOzXjKQhJuo0Q173wf2KOo8t4I8vHy6lF9poUp7bKT0/NHE8fPX23PwfhnykfqnC2xRxOnVw5XuGIaA==",
+ "dev": true,
+ "license": "MIT",
+ "bin": {
+ "jsesc": "bin/jsesc"
+ },
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/json-buffer": {
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.1.tgz",
+ "integrity": "sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/json-schema-traverse": {
+ "version": "0.4.1",
+ "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz",
+ "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/json-stable-stringify-without-jsonify": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz",
+ "integrity": "sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/json-stringify-safe": {
+ "version": "5.0.1",
+ "resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz",
+ "integrity": "sha512-ZClg6AaYvamvYEE82d3Iyd3vSSIjQ+odgjaTzRuO3s7toCdFKczob2i0zCh7JE8kWn17yvAWhUVxvqGwUalsRA==",
+ "license": "ISC",
+ "optional": true
+ },
+ "node_modules/json5": {
+ "version": "2.2.3",
+ "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz",
+ "integrity": "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==",
+ "dev": true,
+ "license": "MIT",
+ "bin": {
+ "json5": "lib/cli.js"
+ },
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/keyv": {
+ "version": "4.5.4",
+ "resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.4.tgz",
+ "integrity": "sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "json-buffer": "3.0.1"
+ }
+ },
+ "node_modules/keyvaluestorage-interface": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/keyvaluestorage-interface/-/keyvaluestorage-interface-1.0.0.tgz",
+ "integrity": "sha512-8t6Q3TclQ4uZynJY9IGr2+SsIGwK9JHcO6ootkHCGA0CrQCRy+VkouYNO2xicET6b9al7QKzpebNow+gkpCL8g==",
+ "license": "MIT"
+ },
+ "node_modules/levn": {
+ "version": "0.4.1",
+ "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz",
+ "integrity": "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "prelude-ls": "^1.2.1",
+ "type-check": "~0.4.0"
+ },
+ "engines": {
+ "node": ">= 0.8.0"
+ }
+ },
+ "node_modules/lit": {
+ "version": "3.3.0",
+ "resolved": "https://registry.npmjs.org/lit/-/lit-3.3.0.tgz",
+ "integrity": "sha512-DGVsqsOIHBww2DqnuZzW7QsuCdahp50ojuDaBPC7jUDRpYoH0z7kHBBYZewRzer75FwtrkmkKk7iOAwSaWdBmw==",
+ "license": "BSD-3-Clause",
+ "dependencies": {
+ "@lit/reactive-element": "^2.1.0",
+ "lit-element": "^4.2.0",
+ "lit-html": "^3.3.0"
+ }
+ },
+ "node_modules/lit-element": {
+ "version": "4.2.1",
+ "resolved": "https://registry.npmjs.org/lit-element/-/lit-element-4.2.1.tgz",
+ "integrity": "sha512-WGAWRGzirAgyphK2urmYOV72tlvnxw7YfyLDgQ+OZnM9vQQBQnumQ7jUJe6unEzwGU3ahFOjuz1iz1jjrpCPuw==",
+ "license": "BSD-3-Clause",
+ "dependencies": {
+ "@lit-labs/ssr-dom-shim": "^1.4.0",
+ "@lit/reactive-element": "^2.1.0",
+ "lit-html": "^3.3.0"
+ }
+ },
+ "node_modules/lit-html": {
+ "version": "3.3.1",
+ "resolved": "https://registry.npmjs.org/lit-html/-/lit-html-3.3.1.tgz",
+ "integrity": "sha512-S9hbyDu/vs1qNrithiNyeyv64c9yqiW9l+DBgI18fL+MTvOtWoFR0FWiyq1TxaYef5wNlpEmzlXoBlZEO+WjoA==",
+ "license": "BSD-3-Clause",
+ "dependencies": {
+ "@types/trusted-types": "^2.0.2"
+ }
+ },
+ "node_modules/locate-path": {
+ "version": "6.0.0",
+ "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz",
+ "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "p-locate": "^5.0.0"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/lodash.merge": {
+ "version": "4.6.2",
+ "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz",
+ "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/lru-cache": {
+ "version": "5.1.1",
+ "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz",
+ "integrity": "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==",
+ "dev": true,
+ "license": "ISC",
+ "dependencies": {
+ "yallist": "^3.0.2"
+ }
+ },
+ "node_modules/math-intrinsics": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/math-intrinsics/-/math-intrinsics-1.1.0.tgz",
+ "integrity": "sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==",
+ "license": "MIT",
+ "optional": true,
+ "engines": {
+ "node": ">= 0.4"
+ }
+ },
+ "node_modules/md5": {
+ "version": "2.3.0",
+ "resolved": "https://registry.npmjs.org/md5/-/md5-2.3.0.tgz",
+ "integrity": "sha512-T1GITYmFaKuO91vxyoQMFETst+O71VUPEU3ze5GNzDm0OWdP8v1ziTaAEPUr/3kLsY3Sftgz242A1SetQiDL7g==",
+ "license": "BSD-3-Clause",
+ "optional": true,
+ "dependencies": {
+ "charenc": "0.0.2",
+ "crypt": "0.0.2",
+ "is-buffer": "~1.1.6"
+ }
+ },
+ "node_modules/mime-db": {
+ "version": "1.52.0",
+ "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz",
+ "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==",
+ "license": "MIT",
+ "optional": true,
+ "engines": {
+ "node": ">= 0.6"
+ }
+ },
+ "node_modules/mime-types": {
+ "version": "2.1.35",
+ "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz",
+ "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==",
+ "license": "MIT",
+ "optional": true,
+ "dependencies": {
+ "mime-db": "1.52.0"
+ },
+ "engines": {
+ "node": ">= 0.6"
+ }
+ },
+ "node_modules/minimalistic-assert": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/minimalistic-assert/-/minimalistic-assert-1.0.1.tgz",
+ "integrity": "sha512-UtJcAD4yEaGtjPezWuO9wC4nwUnVH/8/Im3yEHQP4b67cXlD/Qr9hdITCU1xDbSEXg2XKNaP8jsReV7vQd00/A==",
+ "license": "ISC"
+ },
+ "node_modules/minimatch": {
+ "version": "3.1.2",
+ "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz",
+ "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==",
+ "dev": true,
+ "license": "ISC",
+ "dependencies": {
+ "brace-expansion": "^1.1.7"
+ },
+ "engines": {
+ "node": "*"
+ }
+ },
+ "node_modules/ms": {
+ "version": "2.1.3",
+ "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz",
+ "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==",
+ "devOptional": true,
+ "license": "MIT"
+ },
+ "node_modules/multiformats": {
+ "version": "9.9.0",
+ "resolved": "https://registry.npmjs.org/multiformats/-/multiformats-9.9.0.tgz",
+ "integrity": "sha512-HoMUjhH9T8DDBNT+6xzkrd9ga/XiBI4xLr58LJACwK6G3HTOPeMz4nB4KJs33L2BelrIJa7P0VuNaVF3hMYfjg==",
+ "license": "(Apache-2.0 AND MIT)"
+ },
+ "node_modules/nanoid": {
+ "version": "3.3.11",
+ "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.11.tgz",
+ "integrity": "sha512-N8SpfPUnUp1bK+PMYW8qSWdl9U+wwNWI4QKxOYDy9JAro3WMX7p2OeVRF9v+347pnakNevPmiHhNmZ2HbFA76w==",
+ "dev": true,
+ "funding": [
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/ai"
+ }
+ ],
+ "license": "MIT",
+ "bin": {
+ "nanoid": "bin/nanoid.cjs"
+ },
+ "engines": {
+ "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1"
+ }
+ },
+ "node_modules/natural-compare": {
+ "version": "1.4.0",
+ "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz",
+ "integrity": "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/node-fetch": {
+ "version": "2.7.0",
+ "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.7.0.tgz",
+ "integrity": "sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A==",
+ "license": "MIT",
+ "dependencies": {
+ "whatwg-url": "^5.0.0"
+ },
+ "engines": {
+ "node": "4.x || >=6.0.0"
+ },
+ "peerDependencies": {
+ "encoding": "^0.1.0"
+ },
+ "peerDependenciesMeta": {
+ "encoding": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/node-fetch-native": {
+ "version": "1.6.7",
+ "resolved": "https://registry.npmjs.org/node-fetch-native/-/node-fetch-native-1.6.7.tgz",
+ "integrity": "sha512-g9yhqoedzIUm0nTnTqAQvueMPVOuIY16bqgAJJC8XOOubYFNwz6IER9qs0Gq2Xd0+CecCKFjtdDTMA4u4xG06Q==",
+ "license": "MIT"
+ },
+ "node_modules/node-gyp-build": {
+ "version": "4.8.4",
+ "resolved": "https://registry.npmjs.org/node-gyp-build/-/node-gyp-build-4.8.4.tgz",
+ "integrity": "sha512-LA4ZjwlnUblHVgq0oBF3Jl/6h/Nvs5fzBLwdEF4nuxnFdsfajde4WfxtJr3CaiH+F6ewcIB/q4jQ4UzPyid+CQ==",
+ "license": "MIT",
+ "optional": true,
+ "bin": {
+ "node-gyp-build": "bin.js",
+ "node-gyp-build-optional": "optional.js",
+ "node-gyp-build-test": "build-test.js"
+ }
+ },
+ "node_modules/node-mock-http": {
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/node-mock-http/-/node-mock-http-1.0.3.tgz",
+ "integrity": "sha512-jN8dK25fsfnMrVsEhluUTPkBFY+6ybu7jSB1n+ri/vOGjJxU8J9CZhpSGkHXSkFjtUhbmoncG/YG9ta5Ludqog==",
+ "license": "MIT"
+ },
+ "node_modules/node-releases": {
+ "version": "2.0.27",
+ "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.27.tgz",
+ "integrity": "sha512-nmh3lCkYZ3grZvqcCH+fjmQ7X+H0OeZgP40OierEaAptX4XofMh5kwNbWh7lBduUzCcV/8kZ+NDLCwm2iorIlA==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/normalize-path": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz",
+ "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/ofetch": {
+ "version": "1.5.1",
+ "resolved": "https://registry.npmjs.org/ofetch/-/ofetch-1.5.1.tgz",
+ "integrity": "sha512-2W4oUZlVaqAPAil6FUg/difl6YhqhUR7x2eZY4bQCko22UXg3hptq9KLQdqFClV+Wu85UX7hNtdGTngi/1BxcA==",
+ "license": "MIT",
+ "dependencies": {
+ "destr": "^2.0.5",
+ "node-fetch-native": "^1.6.7",
+ "ufo": "^1.6.1"
+ }
+ },
+ "node_modules/on-exit-leak-free": {
+ "version": "2.1.2",
+ "resolved": "https://registry.npmjs.org/on-exit-leak-free/-/on-exit-leak-free-2.1.2.tgz",
+ "integrity": "sha512-0eJJY6hXLGf1udHwfNftBqH+g73EU4B504nZeKpz1sYRKafAghwxEJunB2O7rDZkL4PGfsMVnTXZ2EjibbqcsA==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=14.0.0"
+ }
+ },
+ "node_modules/optionator": {
+ "version": "0.9.4",
+ "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.4.tgz",
+ "integrity": "sha512-6IpQ7mKUxRcZNLIObR0hz7lxsapSSIYNZJwXPGeF0mTVqGKFIXj1DQcMoT22S3ROcLyY/rz0PWaWZ9ayWmad9g==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "deep-is": "^0.1.3",
+ "fast-levenshtein": "^2.0.6",
+ "levn": "^0.4.1",
+ "prelude-ls": "^1.2.1",
+ "type-check": "^0.4.0",
+ "word-wrap": "^1.2.5"
+ },
+ "engines": {
+ "node": ">= 0.8.0"
+ }
+ },
+ "node_modules/ox": {
+ "version": "0.6.9",
+ "resolved": "https://registry.npmjs.org/ox/-/ox-0.6.9.tgz",
+ "integrity": "sha512-wi5ShvzE4eOcTwQVsIPdFr+8ycyX+5le/96iAJutaZAvCes1J0+RvpEPg5QDPDiaR0XQQAvZVl7AwqQcINuUug==",
+ "funding": [
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/wevm"
+ }
+ ],
+ "license": "MIT",
+ "optional": true,
+ "dependencies": {
+ "@adraffy/ens-normalize": "^1.10.1",
+ "@noble/curves": "^1.6.0",
+ "@noble/hashes": "^1.5.0",
+ "@scure/bip32": "^1.5.0",
+ "@scure/bip39": "^1.4.0",
+ "abitype": "^1.0.6",
+ "eventemitter3": "5.0.1"
+ },
+ "peerDependencies": {
+ "typescript": ">=5.4.0"
+ },
+ "peerDependenciesMeta": {
+ "typescript": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/ox/node_modules/@noble/hashes": {
+ "version": "1.8.0",
+ "resolved": "https://registry.npmjs.org/@noble/hashes/-/hashes-1.8.0.tgz",
+ "integrity": "sha512-jCs9ldd7NwzpgXDIf6P3+NrHh9/sD6CQdxHyjQI+h/6rDNo88ypBxxz45UDuZHz9r3tNz7N/VInSVoVdtXEI4A==",
+ "license": "MIT",
+ "optional": true,
+ "engines": {
+ "node": "^14.21.3 || >=16"
+ },
+ "funding": {
+ "url": "https://paulmillr.com/funding/"
+ }
+ },
+ "node_modules/p-limit": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz",
+ "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "yocto-queue": "^0.1.0"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/p-locate": {
+ "version": "5.0.0",
+ "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz",
+ "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "p-limit": "^3.0.2"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/p-try": {
+ "version": "2.2.0",
+ "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz",
+ "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/parent-module": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz",
+ "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "callsites": "^3.0.0"
+ },
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/path-exists": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz",
+ "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/path-key": {
+ "version": "3.1.1",
+ "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz",
+ "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/picocolors": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz",
+ "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==",
+ "dev": true,
+ "license": "ISC"
+ },
+ "node_modules/picomatch": {
+ "version": "4.0.3",
+ "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.3.tgz",
+ "integrity": "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==",
+ "dev": true,
+ "license": "MIT",
+ "peer": true,
+ "engines": {
+ "node": ">=12"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/jonschlinkert"
+ }
+ },
+ "node_modules/pino": {
+ "version": "10.0.0",
+ "resolved": "https://registry.npmjs.org/pino/-/pino-10.0.0.tgz",
+ "integrity": "sha512-eI9pKwWEix40kfvSzqEP6ldqOoBIN7dwD/o91TY5z8vQI12sAffpR/pOqAD1IVVwIVHDpHjkq0joBPdJD0rafA==",
+ "license": "MIT",
+ "dependencies": {
+ "atomic-sleep": "^1.0.0",
+ "on-exit-leak-free": "^2.1.0",
+ "pino-abstract-transport": "^2.0.0",
+ "pino-std-serializers": "^7.0.0",
+ "process-warning": "^5.0.0",
+ "quick-format-unescaped": "^4.0.3",
+ "real-require": "^0.2.0",
+ "safe-stable-stringify": "^2.3.1",
+ "slow-redact": "^0.3.0",
+ "sonic-boom": "^4.0.1",
+ "thread-stream": "^3.0.0"
+ },
+ "bin": {
+ "pino": "bin.js"
+ }
+ },
+ "node_modules/pino-abstract-transport": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/pino-abstract-transport/-/pino-abstract-transport-2.0.0.tgz",
+ "integrity": "sha512-F63x5tizV6WCh4R6RHyi2Ml+M70DNRXt/+HANowMflpgGFMAym/VKm6G7ZOQRjqN7XbGxK1Lg9t6ZrtzOaivMw==",
+ "license": "MIT",
+ "dependencies": {
+ "split2": "^4.0.0"
+ }
+ },
+ "node_modules/pino-std-serializers": {
+ "version": "7.0.0",
+ "resolved": "https://registry.npmjs.org/pino-std-serializers/-/pino-std-serializers-7.0.0.tgz",
+ "integrity": "sha512-e906FRY0+tV27iq4juKzSYPbUj2do2X2JX4EzSca1631EB2QJQUqGbDuERal7LCtOpxl6x3+nvo9NPZcmjkiFA==",
+ "license": "MIT"
+ },
+ "node_modules/pngjs": {
+ "version": "5.0.0",
+ "resolved": "https://registry.npmjs.org/pngjs/-/pngjs-5.0.0.tgz",
+ "integrity": "sha512-40QW5YalBNfQo5yRYmiw7Yz6TKKVr3h6970B2YE+3fQpsWcrbj1PzJgxeJ19DRQjhMbKPIuMY8rFaXc8moolVw==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=10.13.0"
+ }
+ },
+ "node_modules/postcss": {
+ "version": "8.5.6",
+ "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.6.tgz",
+ "integrity": "sha512-3Ybi1tAuwAP9s0r1UQ2J4n5Y0G05bJkpUIO0/bI9MhwmD70S5aTWbXGBwxHrelT+XM1k6dM0pk+SwNkpTRN7Pg==",
+ "dev": true,
+ "funding": [
+ {
+ "type": "opencollective",
+ "url": "https://opencollective.com/postcss/"
+ },
+ {
+ "type": "tidelift",
+ "url": "https://tidelift.com/funding/github/npm/postcss"
+ },
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/ai"
+ }
+ ],
+ "license": "MIT",
+ "dependencies": {
+ "nanoid": "^3.3.11",
+ "picocolors": "^1.1.1",
+ "source-map-js": "^1.2.1"
+ },
+ "engines": {
+ "node": "^10 || ^12 || >=14"
+ }
+ },
+ "node_modules/preact": {
+ "version": "10.24.2",
+ "resolved": "https://registry.npmjs.org/preact/-/preact-10.24.2.tgz",
+ "integrity": "sha512-1cSoF0aCC8uaARATfrlz4VCBqE8LwZwRfLgkxJOQwAlQt6ayTmi0D9OF7nXid1POI5SZidFuG9CnlXbDfLqY/Q==",
+ "license": "MIT",
+ "optional": true,
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/preact"
+ }
+ },
+ "node_modules/prelude-ls": {
+ "version": "1.2.1",
+ "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz",
+ "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.8.0"
+ }
+ },
+ "node_modules/process-warning": {
+ "version": "5.0.0",
+ "resolved": "https://registry.npmjs.org/process-warning/-/process-warning-5.0.0.tgz",
+ "integrity": "sha512-a39t9ApHNx2L4+HBnQKqxxHNs1r7KF+Intd8Q/g1bUh6q0WIp9voPXJ/x0j+ZL45KF1pJd9+q2jLIRMfvEshkA==",
+ "funding": [
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/fastify"
+ },
+ {
+ "type": "opencollective",
+ "url": "https://opencollective.com/fastify"
+ }
+ ],
+ "license": "MIT"
+ },
+ "node_modules/proxy-compare": {
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/proxy-compare/-/proxy-compare-3.0.1.tgz",
+ "integrity": "sha512-V9plBAt3qjMlS1+nC8771KNf6oJ12gExvaxnNzN/9yVRLdTv/lc+oJlnSzrdYDAvBfTStPCoiaCOTmTs0adv7Q==",
+ "license": "MIT"
+ },
+ "node_modules/proxy-from-env": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.1.0.tgz",
+ "integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==",
+ "license": "MIT",
+ "optional": true
+ },
+ "node_modules/punycode": {
+ "version": "2.3.1",
+ "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz",
+ "integrity": "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/qrcode": {
+ "version": "1.5.3",
+ "resolved": "https://registry.npmjs.org/qrcode/-/qrcode-1.5.3.tgz",
+ "integrity": "sha512-puyri6ApkEHYiVl4CFzo1tDkAZ+ATcnbJrJ6RiBM1Fhctdn/ix9MTE3hRph33omisEbC/2fcfemsseiKgBPKZg==",
+ "license": "MIT",
+ "dependencies": {
+ "dijkstrajs": "^1.0.1",
+ "encode-utf8": "^1.0.3",
+ "pngjs": "^5.0.0",
+ "yargs": "^15.3.1"
+ },
+ "bin": {
+ "qrcode": "bin/qrcode"
+ },
+ "engines": {
+ "node": ">=10.13.0"
+ }
+ },
+ "node_modules/quick-format-unescaped": {
+ "version": "4.0.4",
+ "resolved": "https://registry.npmjs.org/quick-format-unescaped/-/quick-format-unescaped-4.0.4.tgz",
+ "integrity": "sha512-tYC1Q1hgyRuHgloV/YXs2w15unPVh8qfu/qCTfhTYamaw7fyhumKa2yGpdSo87vY32rIclj+4fWYQXUMs9EHvg==",
+ "license": "MIT"
+ },
+ "node_modules/radix3": {
+ "version": "1.1.2",
+ "resolved": "https://registry.npmjs.org/radix3/-/radix3-1.1.2.tgz",
+ "integrity": "sha512-b484I/7b8rDEdSDKckSSBA8knMpcdsXudlE/LNL639wFoHKwLbEkQFZHWEYwDC0wa0FKUcCY+GAF73Z7wxNVFA==",
+ "license": "MIT"
+ },
+ "node_modules/react": {
+ "version": "19.2.1",
+ "resolved": "https://registry.npmjs.org/react/-/react-19.2.1.tgz",
+ "integrity": "sha512-DGrYcCWK7tvYMnWh79yrPHt+vdx9tY+1gPZa7nJQtO/p8bLTDaHp4dzwEhQB7pZ4Xe3ok4XKuEPrVuc+wlpkmw==",
+ "license": "MIT",
+ "peer": true,
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/react-dom": {
+ "version": "19.2.1",
+ "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-19.2.1.tgz",
+ "integrity": "sha512-ibrK8llX2a4eOskq1mXKu/TGZj9qzomO+sNfO98M6d9zIPOEhlBkMkBUBLd1vgS0gQsLDBzA+8jJBVXDnfHmJg==",
+ "license": "MIT",
+ "dependencies": {
+ "scheduler": "^0.27.0"
+ },
+ "peerDependencies": {
+ "react": "^19.2.1"
+ }
+ },
+ "node_modules/react-refresh": {
+ "version": "0.18.0",
+ "resolved": "https://registry.npmjs.org/react-refresh/-/react-refresh-0.18.0.tgz",
+ "integrity": "sha512-QgT5//D3jfjJb6Gsjxv0Slpj23ip+HtOpnNgnb2S5zU3CB26G/IDPGoy4RJB42wzFE46DRsstbW6tKHoKbhAxw==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/readdirp": {
+ "version": "4.1.2",
+ "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-4.1.2.tgz",
+ "integrity": "sha512-GDhwkLfywWL2s6vEjyhri+eXmfH6j1L7JE27WhqLeYzoh/A3DBaYGEj2H/HFZCn/kMfim73FXxEJTw06WtxQwg==",
+ "license": "MIT",
+ "engines": {
+ "node": ">= 14.18.0"
+ },
+ "funding": {
+ "type": "individual",
+ "url": "https://paulmillr.com/funding/"
+ }
+ },
+ "node_modules/real-require": {
+ "version": "0.2.0",
+ "resolved": "https://registry.npmjs.org/real-require/-/real-require-0.2.0.tgz",
+ "integrity": "sha512-57frrGM/OCTLqLOAh0mhVA9VBMHd+9U7Zb2THMGdBUoZVOtGbJzjxsYGDJ3A9AYYCP4hn6y1TVbaOfzWtm5GFg==",
+ "license": "MIT",
+ "engines": {
+ "node": ">= 12.13.0"
+ }
+ },
+ "node_modules/require-directory": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz",
+ "integrity": "sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/require-main-filename": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/require-main-filename/-/require-main-filename-2.0.0.tgz",
+ "integrity": "sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg==",
+ "license": "ISC"
+ },
+ "node_modules/resolve-from": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz",
+ "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/rollup": {
+ "version": "4.53.3",
+ "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.53.3.tgz",
+ "integrity": "sha512-w8GmOxZfBmKknvdXU1sdM9NHcoQejwF/4mNgj2JuEEdRaHwwF12K7e9eXn1nLZ07ad+du76mkVsyeb2rKGllsA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@types/estree": "1.0.8"
+ },
+ "bin": {
+ "rollup": "dist/bin/rollup"
+ },
+ "engines": {
+ "node": ">=18.0.0",
+ "npm": ">=8.0.0"
+ },
+ "optionalDependencies": {
+ "@rollup/rollup-android-arm-eabi": "4.53.3",
+ "@rollup/rollup-android-arm64": "4.53.3",
+ "@rollup/rollup-darwin-arm64": "4.53.3",
+ "@rollup/rollup-darwin-x64": "4.53.3",
+ "@rollup/rollup-freebsd-arm64": "4.53.3",
+ "@rollup/rollup-freebsd-x64": "4.53.3",
+ "@rollup/rollup-linux-arm-gnueabihf": "4.53.3",
+ "@rollup/rollup-linux-arm-musleabihf": "4.53.3",
+ "@rollup/rollup-linux-arm64-gnu": "4.53.3",
+ "@rollup/rollup-linux-arm64-musl": "4.53.3",
+ "@rollup/rollup-linux-loong64-gnu": "4.53.3",
+ "@rollup/rollup-linux-ppc64-gnu": "4.53.3",
+ "@rollup/rollup-linux-riscv64-gnu": "4.53.3",
+ "@rollup/rollup-linux-riscv64-musl": "4.53.3",
+ "@rollup/rollup-linux-s390x-gnu": "4.53.3",
+ "@rollup/rollup-linux-x64-gnu": "4.53.3",
+ "@rollup/rollup-linux-x64-musl": "4.53.3",
+ "@rollup/rollup-openharmony-arm64": "4.53.3",
+ "@rollup/rollup-win32-arm64-msvc": "4.53.3",
+ "@rollup/rollup-win32-ia32-msvc": "4.53.3",
+ "@rollup/rollup-win32-x64-gnu": "4.53.3",
+ "@rollup/rollup-win32-x64-msvc": "4.53.3",
+ "fsevents": "~2.3.2"
+ }
+ },
+ "node_modules/rpc-websockets": {
+ "version": "9.3.1",
+ "resolved": "https://registry.npmjs.org/rpc-websockets/-/rpc-websockets-9.3.1.tgz",
+ "integrity": "sha512-bY6a+i/lEtBJ/mUxwsCTgevoV1P0foXTVA7UoThzaIWbM+3NDqorf8NBWs5DmqKTFeA1IoNzgvkWjFCPgnzUiQ==",
+ "license": "LGPL-3.0-only",
+ "optional": true,
+ "dependencies": {
+ "@swc/helpers": "^0.5.11",
+ "@types/uuid": "^8.3.4",
+ "@types/ws": "^8.2.2",
+ "buffer": "^6.0.3",
+ "eventemitter3": "^5.0.1",
+ "uuid": "^8.3.2",
+ "ws": "^8.5.0"
+ },
+ "funding": {
+ "type": "paypal",
+ "url": "https://paypal.me/kozjak"
+ },
+ "optionalDependencies": {
+ "bufferutil": "^4.0.1",
+ "utf-8-validate": "^5.0.2"
+ }
+ },
+ "node_modules/rpc-websockets/node_modules/@types/ws": {
+ "version": "8.18.1",
+ "resolved": "https://registry.npmjs.org/@types/ws/-/ws-8.18.1.tgz",
+ "integrity": "sha512-ThVF6DCVhA8kUGy+aazFQ4kXQ7E1Ty7A3ypFOe0IcJV8O/M511G99AW24irKrW56Wt44yG9+ij8FaqoBGkuBXg==",
+ "license": "MIT",
+ "optional": true,
+ "dependencies": {
+ "@types/node": "*"
+ }
+ },
+ "node_modules/safe-buffer": {
+ "version": "5.2.1",
+ "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz",
+ "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==",
+ "funding": [
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/feross"
+ },
+ {
+ "type": "patreon",
+ "url": "https://www.patreon.com/feross"
+ },
+ {
+ "type": "consulting",
+ "url": "https://feross.org/support"
+ }
+ ],
+ "license": "MIT",
+ "optional": true
+ },
+ "node_modules/safe-stable-stringify": {
+ "version": "2.5.0",
+ "resolved": "https://registry.npmjs.org/safe-stable-stringify/-/safe-stable-stringify-2.5.0.tgz",
+ "integrity": "sha512-b3rppTKm9T+PsVCBEOUR46GWI7fdOs00VKZ1+9c1EWDaDMvjQc6tUwuFyIprgGgTcWoVHSKrU8H31ZHA2e0RHA==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/scheduler": {
+ "version": "0.27.0",
+ "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.27.0.tgz",
+ "integrity": "sha512-eNv+WrVbKu1f3vbYJT/xtiF5syA5HPIMtf9IgY/nKg0sWqzAUEvqY/xm7OcZc/qafLx/iO9FgOmeSAp4v5ti/Q==",
+ "license": "MIT"
+ },
+ "node_modules/semver": {
+ "version": "7.7.2",
+ "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.2.tgz",
+ "integrity": "sha512-RF0Fw+rO5AMf9MAyaRXI4AV0Ulj5lMHqVxxdSgiVbixSCXoEmmX/jk0CuJw4+3SqroYO9VoUh+HcuJivvtJemA==",
+ "license": "ISC",
+ "bin": {
+ "semver": "bin/semver.js"
+ },
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/set-blocking": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz",
+ "integrity": "sha512-KiKBS8AnWGEyLzofFfmvKwpdPzqiy16LvQfK3yv/fVH7Bj13/wl3JSR1J+rfgRE9q7xUJK4qvgS8raSOeLUehw==",
+ "license": "ISC"
+ },
+ "node_modules/shebang-command": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz",
+ "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "shebang-regex": "^3.0.0"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/shebang-regex": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz",
+ "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/slow-redact": {
+ "version": "0.3.2",
+ "resolved": "https://registry.npmjs.org/slow-redact/-/slow-redact-0.3.2.tgz",
+ "integrity": "sha512-MseHyi2+E/hBRqdOi5COy6wZ7j7DxXRz9NkseavNYSvvWC06D8a5cidVZX3tcG5eCW3NIyVU4zT63hw0Q486jw==",
+ "license": "MIT"
+ },
+ "node_modules/sonic-boom": {
+ "version": "4.2.0",
+ "resolved": "https://registry.npmjs.org/sonic-boom/-/sonic-boom-4.2.0.tgz",
+ "integrity": "sha512-INb7TM37/mAcsGmc9hyyI6+QR3rR1zVRu36B0NeGXKnOOLiZOfER5SA+N7X7k3yUYRzLWafduTDvJAfDswwEww==",
+ "license": "MIT",
+ "dependencies": {
+ "atomic-sleep": "^1.0.0"
+ }
+ },
+ "node_modules/source-map-js": {
+ "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,
+ "license": "BSD-3-Clause",
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/split2": {
+ "version": "4.2.0",
+ "resolved": "https://registry.npmjs.org/split2/-/split2-4.2.0.tgz",
+ "integrity": "sha512-UcjcJOWknrNkF6PLX83qcHM6KHgVKNkV62Y8a5uYDVv9ydGQVwAHMKqHdJje1VTWpljG0WYpCDhrCdAOYH4TWg==",
+ "license": "ISC",
+ "engines": {
+ "node": ">= 10.x"
+ }
+ },
+ "node_modules/stream-chain": {
+ "version": "2.2.5",
+ "resolved": "https://registry.npmjs.org/stream-chain/-/stream-chain-2.2.5.tgz",
+ "integrity": "sha512-1TJmBx6aSWqZ4tx7aTpBDXK0/e2hhcNSTV8+CbFJtDjbb+I1mZ8lHit0Grw9GRT+6JbIrrDd8esncgBi8aBXGA==",
+ "license": "BSD-3-Clause",
+ "optional": true
+ },
+ "node_modules/stream-json": {
+ "version": "1.9.1",
+ "resolved": "https://registry.npmjs.org/stream-json/-/stream-json-1.9.1.tgz",
+ "integrity": "sha512-uWkjJ+2Nt/LO9Z/JyKZbMusL8Dkh97uUBTv3AJQ74y07lVahLY4eEFsPsE97pxYBwr8nnjMAIch5eqI0gPShyw==",
+ "license": "BSD-3-Clause",
+ "optional": true,
+ "dependencies": {
+ "stream-chain": "^2.2.5"
+ }
+ },
+ "node_modules/string-width": {
+ "version": "4.2.3",
+ "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz",
+ "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==",
+ "license": "MIT",
+ "dependencies": {
+ "emoji-regex": "^8.0.0",
+ "is-fullwidth-code-point": "^3.0.0",
+ "strip-ansi": "^6.0.1"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/strip-ansi": {
+ "version": "6.0.1",
+ "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz",
+ "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==",
+ "license": "MIT",
+ "dependencies": {
+ "ansi-regex": "^5.0.1"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/strip-json-comments": {
+ "version": "3.1.1",
+ "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz",
+ "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=8"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/superstruct": {
+ "version": "2.0.2",
+ "resolved": "https://registry.npmjs.org/superstruct/-/superstruct-2.0.2.tgz",
+ "integrity": "sha512-uV+TFRZdXsqXTL2pRvujROjdZQ4RAlBUS5BTh9IGm+jTqQntYThciG/qu57Gs69yjnVUSqdxF9YLmSnpupBW9A==",
+ "license": "MIT",
+ "optional": true,
+ "engines": {
+ "node": ">=14.0.0"
+ }
+ },
+ "node_modules/supports-color": {
+ "version": "7.2.0",
+ "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz",
+ "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "has-flag": "^4.0.0"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/text-encoding-utf-8": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/text-encoding-utf-8/-/text-encoding-utf-8-1.0.2.tgz",
+ "integrity": "sha512-8bw4MY9WjdsD2aMtO0OzOCY3pXGYNx2d2FfHRVUKkiCPDWjKuOlhLVASS+pD7VkLTVjW268LYJHwsnPFlBpbAg==",
+ "optional": true
+ },
+ "node_modules/thread-stream": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/thread-stream/-/thread-stream-3.1.0.tgz",
+ "integrity": "sha512-OqyPZ9u96VohAyMfJykzmivOrY2wfMSf3C5TtFJVgN+Hm6aj+voFhlK+kZEIv2FBh1X6Xp3DlnCOfEQ3B2J86A==",
+ "license": "MIT",
+ "dependencies": {
+ "real-require": "^0.2.0"
+ }
+ },
+ "node_modules/tinyglobby": {
+ "version": "0.2.15",
+ "resolved": "https://registry.npmjs.org/tinyglobby/-/tinyglobby-0.2.15.tgz",
+ "integrity": "sha512-j2Zq4NyQYG5XMST4cbs02Ak8iJUdxRM0XI5QyxXuZOzKOINmWurp3smXu3y5wDcJrptwpSjgXHzIQxR0omXljQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "fdir": "^6.5.0",
+ "picomatch": "^4.0.3"
+ },
+ "engines": {
+ "node": ">=12.0.0"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/SuperchupuDev"
+ }
+ },
+ "node_modules/tr46": {
+ "version": "0.0.3",
+ "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz",
+ "integrity": "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==",
+ "license": "MIT"
+ },
+ "node_modules/ts-api-utils": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-2.1.0.tgz",
+ "integrity": "sha512-CUgTZL1irw8u29bzrOD/nH85jqyc74D6SshFgujOIA7osm2Rz7dYH77agkx7H4FBNxDq7Cjf+IjaX/8zwFW+ZQ==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=18.12"
+ },
+ "peerDependencies": {
+ "typescript": ">=4.8.4"
+ }
+ },
+ "node_modules/tslib": {
+ "version": "1.14.1",
+ "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz",
+ "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==",
+ "license": "0BSD"
+ },
+ "node_modules/type-check": {
+ "version": "0.4.0",
+ "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz",
+ "integrity": "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "prelude-ls": "^1.2.1"
+ },
+ "engines": {
+ "node": ">= 0.8.0"
+ }
+ },
+ "node_modules/typescript": {
+ "version": "5.9.3",
+ "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.9.3.tgz",
+ "integrity": "sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw==",
+ "devOptional": true,
+ "license": "Apache-2.0",
+ "peer": true,
+ "bin": {
+ "tsc": "bin/tsc",
+ "tsserver": "bin/tsserver"
+ },
+ "engines": {
+ "node": ">=14.17"
+ }
+ },
+ "node_modules/typescript-eslint": {
+ "version": "8.48.1",
+ "resolved": "https://registry.npmjs.org/typescript-eslint/-/typescript-eslint-8.48.1.tgz",
+ "integrity": "sha512-FbOKN1fqNoXp1hIl5KYpObVrp0mCn+CLgn479nmu2IsRMrx2vyv74MmsBLVlhg8qVwNFGbXSp8fh1zp8pEoC2A==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@typescript-eslint/eslint-plugin": "8.48.1",
+ "@typescript-eslint/parser": "8.48.1",
+ "@typescript-eslint/typescript-estree": "8.48.1",
+ "@typescript-eslint/utils": "8.48.1"
+ },
+ "engines": {
+ "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/typescript-eslint"
+ },
+ "peerDependencies": {
+ "eslint": "^8.57.0 || ^9.0.0",
+ "typescript": ">=4.8.4 <6.0.0"
+ }
+ },
+ "node_modules/ufo": {
+ "version": "1.6.1",
+ "resolved": "https://registry.npmjs.org/ufo/-/ufo-1.6.1.tgz",
+ "integrity": "sha512-9a4/uxlTWJ4+a5i0ooc1rU7C7YOw3wT+UGqdeNNHWnOF9qcMBgLRS+4IYUqbczewFx4mLEig6gawh7X6mFlEkA==",
+ "license": "MIT"
+ },
+ "node_modules/uint8arrays": {
+ "version": "3.1.1",
+ "resolved": "https://registry.npmjs.org/uint8arrays/-/uint8arrays-3.1.1.tgz",
+ "integrity": "sha512-+QJa8QRnbdXVpHYjLoTpJIdCTiw9Ir62nocClWuXIq2JIh4Uta0cQsTSpFL678p2CN8B+XSApwcU+pQEqVpKWg==",
+ "license": "MIT",
+ "dependencies": {
+ "multiformats": "^9.4.2"
+ }
+ },
+ "node_modules/uncrypto": {
+ "version": "0.1.3",
+ "resolved": "https://registry.npmjs.org/uncrypto/-/uncrypto-0.1.3.tgz",
+ "integrity": "sha512-Ql87qFHB3s/De2ClA9e0gsnS6zXG27SkTiSJwjCc9MebbfapQfuPzumMIUMi38ezPZVNFcHI9sUIepeQfw8J8Q==",
+ "license": "MIT"
+ },
+ "node_modules/undici-types": {
+ "version": "7.16.0",
+ "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-7.16.0.tgz",
+ "integrity": "sha512-Zz+aZWSj8LE6zoxD+xrjh4VfkIG8Ya6LvYkZqtUQGJPZjYl53ypCaUwWqo7eI0x66KBGeRo+mlBEkMSeSZ38Nw==",
+ "license": "MIT",
+ "optional": true
+ },
+ "node_modules/update-browserslist-db": {
+ "version": "1.1.4",
+ "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.1.4.tgz",
+ "integrity": "sha512-q0SPT4xyU84saUX+tomz1WLkxUbuaJnR1xWt17M7fJtEJigJeWUNGUqrauFXsHnqev9y9JTRGwk13tFBuKby4A==",
+ "dev": true,
+ "funding": [
+ {
+ "type": "opencollective",
+ "url": "https://opencollective.com/browserslist"
+ },
+ {
+ "type": "tidelift",
+ "url": "https://tidelift.com/funding/github/npm/browserslist"
+ },
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/ai"
+ }
+ ],
+ "license": "MIT",
+ "dependencies": {
+ "escalade": "^3.2.0",
+ "picocolors": "^1.1.1"
+ },
+ "bin": {
+ "update-browserslist-db": "cli.js"
+ },
+ "peerDependencies": {
+ "browserslist": ">= 4.21.0"
+ }
+ },
+ "node_modules/uri-js": {
+ "version": "4.4.1",
+ "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz",
+ "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==",
+ "dev": true,
+ "license": "BSD-2-Clause",
+ "dependencies": {
+ "punycode": "^2.1.0"
+ }
+ },
+ "node_modules/uuid": {
+ "version": "8.3.2",
+ "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz",
+ "integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==",
+ "license": "MIT",
+ "optional": true,
+ "bin": {
+ "uuid": "dist/bin/uuid"
+ }
+ },
+ "node_modules/valtio": {
+ "version": "2.1.7",
+ "resolved": "https://registry.npmjs.org/valtio/-/valtio-2.1.7.tgz",
+ "integrity": "sha512-DwJhCDpujuQuKdJ2H84VbTjEJJteaSmqsuUltsfbfdbotVfNeTE4K/qc/Wi57I9x8/2ed4JNdjEna7O6PfavRg==",
+ "license": "MIT",
+ "dependencies": {
+ "proxy-compare": "^3.0.1"
+ },
+ "engines": {
+ "node": ">=12.20.0"
+ },
+ "peerDependencies": {
+ "@types/react": ">=18.0.0",
+ "react": ">=18.0.0"
+ },
+ "peerDependenciesMeta": {
+ "@types/react": {
+ "optional": true
+ },
+ "react": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/viem": {
+ "version": "2.40.3",
+ "resolved": "https://registry.npmjs.org/viem/-/viem-2.40.3.tgz",
+ "integrity": "sha512-feYfEpbgjRkZYQpwcgxqkWzjxHI5LSDAjcGetHHwDRuX9BRQHUdV8ohrCosCYpdEhus/RknD3/bOd4qLYVPPuA==",
+ "funding": [
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/wevm"
+ }
+ ],
+ "license": "MIT",
+ "dependencies": {
+ "@noble/curves": "1.9.1",
+ "@noble/hashes": "1.8.0",
+ "@scure/bip32": "1.7.0",
+ "@scure/bip39": "1.6.0",
+ "abitype": "1.1.0",
+ "isows": "1.0.7",
+ "ox": "0.9.6",
+ "ws": "8.18.3"
+ },
+ "peerDependencies": {
+ "typescript": ">=5.0.4"
+ },
+ "peerDependenciesMeta": {
+ "typescript": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/viem/node_modules/@adraffy/ens-normalize": {
+ "version": "1.11.1",
+ "resolved": "https://registry.npmjs.org/@adraffy/ens-normalize/-/ens-normalize-1.11.1.tgz",
+ "integrity": "sha512-nhCBV3quEgesuf7c7KYfperqSS14T8bYuvJ8PcLJp6znkZpFc0AuW4qBtr8eKVyPPe/8RSr7sglCWPU5eaxwKQ==",
+ "license": "MIT"
+ },
+ "node_modules/viem/node_modules/@noble/curves": {
+ "version": "1.9.1",
+ "resolved": "https://registry.npmjs.org/@noble/curves/-/curves-1.9.1.tgz",
+ "integrity": "sha512-k11yZxZg+t+gWvBbIswW0yoJlu8cHOC7dhunwOzoWH/mXGBiYyR4YY6hAEK/3EUs4UpB8la1RfdRpeGsFHkWsA==",
+ "license": "MIT",
+ "dependencies": {
+ "@noble/hashes": "1.8.0"
+ },
+ "engines": {
+ "node": "^14.21.3 || >=16"
+ },
+ "funding": {
+ "url": "https://paulmillr.com/funding/"
+ }
+ },
+ "node_modules/viem/node_modules/@noble/hashes": {
+ "version": "1.8.0",
+ "resolved": "https://registry.npmjs.org/@noble/hashes/-/hashes-1.8.0.tgz",
+ "integrity": "sha512-jCs9ldd7NwzpgXDIf6P3+NrHh9/sD6CQdxHyjQI+h/6rDNo88ypBxxz45UDuZHz9r3tNz7N/VInSVoVdtXEI4A==",
+ "license": "MIT",
+ "engines": {
+ "node": "^14.21.3 || >=16"
+ },
+ "funding": {
+ "url": "https://paulmillr.com/funding/"
+ }
+ },
+ "node_modules/viem/node_modules/abitype": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/abitype/-/abitype-1.1.0.tgz",
+ "integrity": "sha512-6Vh4HcRxNMLA0puzPjM5GBgT4aAcFGKZzSgAXvuZ27shJP6NEpielTuqbBmZILR5/xd0PizkBGy5hReKz9jl5A==",
+ "license": "MIT",
+ "funding": {
+ "url": "https://github.com/sponsors/wevm"
+ },
+ "peerDependencies": {
+ "typescript": ">=5.0.4",
+ "zod": "^3.22.0 || ^4.0.0"
+ },
+ "peerDependenciesMeta": {
+ "typescript": {
+ "optional": true
+ },
+ "zod": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/viem/node_modules/ox": {
+ "version": "0.9.6",
+ "resolved": "https://registry.npmjs.org/ox/-/ox-0.9.6.tgz",
+ "integrity": "sha512-8SuCbHPvv2eZLYXrNmC0EC12rdzXQLdhnOMlHDW2wiCPLxBrOOJwX5L5E61by+UjTPOryqQiRSnjIKCI+GykKg==",
+ "funding": [
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/wevm"
+ }
+ ],
+ "license": "MIT",
+ "dependencies": {
+ "@adraffy/ens-normalize": "^1.11.0",
+ "@noble/ciphers": "^1.3.0",
+ "@noble/curves": "1.9.1",
+ "@noble/hashes": "^1.8.0",
+ "@scure/bip32": "^1.7.0",
+ "@scure/bip39": "^1.6.0",
+ "abitype": "^1.0.9",
+ "eventemitter3": "5.0.1"
+ },
+ "peerDependencies": {
+ "typescript": ">=5.4.0"
+ },
+ "peerDependenciesMeta": {
+ "typescript": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/vite": {
+ "version": "7.2.6",
+ "resolved": "https://registry.npmjs.org/vite/-/vite-7.2.6.tgz",
+ "integrity": "sha512-tI2l/nFHC5rLh7+5+o7QjKjSR04ivXDF4jcgV0f/bTQ+OJiITy5S6gaynVsEM+7RqzufMnVbIon6Sr5x1SDYaQ==",
+ "dev": true,
+ "license": "MIT",
+ "peer": true,
+ "dependencies": {
+ "esbuild": "^0.25.0",
+ "fdir": "^6.5.0",
+ "picomatch": "^4.0.3",
+ "postcss": "^8.5.6",
+ "rollup": "^4.43.0",
+ "tinyglobby": "^0.2.15"
+ },
+ "bin": {
+ "vite": "bin/vite.js"
+ },
+ "engines": {
+ "node": "^20.19.0 || >=22.12.0"
+ },
+ "funding": {
+ "url": "https://github.com/vitejs/vite?sponsor=1"
+ },
+ "optionalDependencies": {
+ "fsevents": "~2.3.3"
+ },
+ "peerDependencies": {
+ "@types/node": "^20.19.0 || >=22.12.0",
+ "jiti": ">=1.21.0",
+ "less": "^4.0.0",
+ "lightningcss": "^1.21.0",
+ "sass": "^1.70.0",
+ "sass-embedded": "^1.70.0",
+ "stylus": ">=0.54.8",
+ "sugarss": "^5.0.0",
+ "terser": "^5.16.0",
+ "tsx": "^4.8.1",
+ "yaml": "^2.4.2"
+ },
+ "peerDependenciesMeta": {
+ "@types/node": {
+ "optional": true
+ },
+ "jiti": {
+ "optional": true
+ },
+ "less": {
+ "optional": true
+ },
+ "lightningcss": {
+ "optional": true
+ },
+ "sass": {
+ "optional": true
+ },
+ "sass-embedded": {
+ "optional": true
+ },
+ "stylus": {
+ "optional": true
+ },
+ "sugarss": {
+ "optional": true
+ },
+ "terser": {
+ "optional": true
+ },
+ "tsx": {
+ "optional": true
+ },
+ "yaml": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/webidl-conversions": {
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz",
+ "integrity": "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==",
+ "license": "BSD-2-Clause"
+ },
+ "node_modules/whatwg-url": {
+ "version": "5.0.0",
+ "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz",
+ "integrity": "sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==",
+ "license": "MIT",
+ "dependencies": {
+ "tr46": "~0.0.3",
+ "webidl-conversions": "^3.0.0"
+ }
+ },
+ "node_modules/which": {
+ "version": "2.0.2",
+ "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz",
+ "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==",
+ "dev": true,
+ "license": "ISC",
+ "dependencies": {
+ "isexe": "^2.0.0"
+ },
+ "bin": {
+ "node-which": "bin/node-which"
+ },
+ "engines": {
+ "node": ">= 8"
+ }
+ },
+ "node_modules/which-module": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/which-module/-/which-module-2.0.1.tgz",
+ "integrity": "sha512-iBdZ57RDvnOR9AGBhML2vFZf7h8vmBjhoaZqODJBFWHVtKkDmKuHai3cx5PgVMrX5YDNp27AofYbAwctSS+vhQ==",
+ "license": "ISC"
+ },
+ "node_modules/word-wrap": {
+ "version": "1.2.5",
+ "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.5.tgz",
+ "integrity": "sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/wrap-ansi": {
+ "version": "6.2.0",
+ "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-6.2.0.tgz",
+ "integrity": "sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA==",
+ "license": "MIT",
+ "dependencies": {
+ "ansi-styles": "^4.0.0",
+ "string-width": "^4.1.0",
+ "strip-ansi": "^6.0.0"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/ws": {
+ "version": "8.18.3",
+ "resolved": "https://registry.npmjs.org/ws/-/ws-8.18.3.tgz",
+ "integrity": "sha512-PEIGCY5tSlUt50cqyMXfCzX+oOPqN0vuGqWzbcJ2xvnkzkq46oOpz7dQaTDBdfICb4N14+GARUDw2XV2N4tvzg==",
+ "license": "MIT",
+ "peer": true,
+ "engines": {
+ "node": ">=10.0.0"
+ },
+ "peerDependencies": {
+ "bufferutil": "^4.0.1",
+ "utf-8-validate": ">=5.0.2"
+ },
+ "peerDependenciesMeta": {
+ "bufferutil": {
+ "optional": true
+ },
+ "utf-8-validate": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/y18n": {
+ "version": "4.0.3",
+ "resolved": "https://registry.npmjs.org/y18n/-/y18n-4.0.3.tgz",
+ "integrity": "sha512-JKhqTOwSrqNA1NY5lSztJ1GrBiUodLMmIZuLiDaMRJ+itFd+ABVE8XBjOvIWL+rSqNDC74LCSFmlb/U4UZ4hJQ==",
+ "license": "ISC"
+ },
+ "node_modules/yallist": {
+ "version": "3.1.1",
+ "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz",
+ "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==",
+ "dev": true,
+ "license": "ISC"
+ },
+ "node_modules/yargs": {
+ "version": "15.4.1",
+ "resolved": "https://registry.npmjs.org/yargs/-/yargs-15.4.1.tgz",
+ "integrity": "sha512-aePbxDmcYW++PaqBsJ+HYUFwCdv4LVvdnhBy78E57PIor8/OVvhMrADFFEDh8DHDFRv/O9i3lPhsENjO7QX0+A==",
+ "license": "MIT",
+ "dependencies": {
+ "cliui": "^6.0.0",
+ "decamelize": "^1.2.0",
+ "find-up": "^4.1.0",
+ "get-caller-file": "^2.0.1",
+ "require-directory": "^2.1.1",
+ "require-main-filename": "^2.0.0",
+ "set-blocking": "^2.0.0",
+ "string-width": "^4.2.0",
+ "which-module": "^2.0.0",
+ "y18n": "^4.0.0",
+ "yargs-parser": "^18.1.2"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/yargs-parser": {
+ "version": "18.1.3",
+ "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-18.1.3.tgz",
+ "integrity": "sha512-o50j0JeToy/4K6OZcaQmW6lyXXKhq7csREXcDwk2omFPJEwUNOVtJKvmDr9EI1fAJZUyZcRF7kxGBWmRXudrCQ==",
+ "license": "ISC",
+ "dependencies": {
+ "camelcase": "^5.0.0",
+ "decamelize": "^1.2.0"
+ },
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/yargs/node_modules/find-up": {
+ "version": "4.1.0",
+ "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz",
+ "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==",
+ "license": "MIT",
+ "dependencies": {
+ "locate-path": "^5.0.0",
+ "path-exists": "^4.0.0"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/yargs/node_modules/locate-path": {
+ "version": "5.0.0",
+ "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz",
+ "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==",
+ "license": "MIT",
+ "dependencies": {
+ "p-locate": "^4.1.0"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/yargs/node_modules/p-limit": {
+ "version": "2.3.0",
+ "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz",
+ "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==",
+ "license": "MIT",
+ "dependencies": {
+ "p-try": "^2.0.0"
+ },
+ "engines": {
+ "node": ">=6"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/yargs/node_modules/p-locate": {
+ "version": "4.1.0",
+ "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz",
+ "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==",
+ "license": "MIT",
+ "dependencies": {
+ "p-limit": "^2.2.0"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/yocto-queue": {
+ "version": "0.1.0",
+ "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz",
+ "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/zod": {
+ "version": "3.25.76",
+ "resolved": "https://registry.npmjs.org/zod/-/zod-3.25.76.tgz",
+ "integrity": "sha512-gzUt/qt81nXsFGKIFcC3YnfEAx5NkunCfnDlvuBSSFS02bcXu4Lmea0AFIUwbLWxWPx3d9p8S5QoaujKcNQxcQ==",
+ "devOptional": true,
+ "license": "MIT",
+ "peer": true,
+ "funding": {
+ "url": "https://github.com/sponsors/colinhacks"
+ }
+ },
+ "node_modules/zod-validation-error": {
+ "version": "4.0.2",
+ "resolved": "https://registry.npmjs.org/zod-validation-error/-/zod-validation-error-4.0.2.tgz",
+ "integrity": "sha512-Q6/nZLe6jxuU80qb/4uJ4t5v2VEZ44lzQjPDhYJNztRQ4wyWc6VF3D3Kb/fAuPetZQnhS3hnajCf9CsWesghLQ==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=18.0.0"
+ },
+ "peerDependencies": {
+ "zod": "^3.25.0 || ^4.0.0"
+ }
+ },
+ "node_modules/zustand": {
+ "version": "5.0.3",
+ "resolved": "https://registry.npmjs.org/zustand/-/zustand-5.0.3.tgz",
+ "integrity": "sha512-14fwWQtU3pH4dE0dOpdMiWjddcH+QzKIgk1cl8epwSE7yag43k/AD/m4L6+K7DytAOr9gGBe3/EXj9g7cdostg==",
+ "license": "MIT",
+ "optional": true,
+ "engines": {
+ "node": ">=12.20.0"
+ },
+ "peerDependencies": {
+ "@types/react": ">=18.0.0",
+ "immer": ">=9.0.6",
+ "react": ">=18.0.0",
+ "use-sync-external-store": ">=1.2.0"
+ },
+ "peerDependenciesMeta": {
+ "@types/react": {
+ "optional": true
+ },
+ "immer": {
+ "optional": true
+ },
+ "react": {
+ "optional": true
+ },
+ "use-sync-external-store": {
+ "optional": true
+ }
+ }
+ }
+ }
+}
diff --git a/frontend/package.json b/frontend/package.json
new file mode 100644
index 0000000..963ab37
--- /dev/null
+++ b/frontend/package.json
@@ -0,0 +1,32 @@
+{
+ "name": "golden-bridge-frontend",
+ "private": true,
+ "version": "0.0.0",
+ "type": "module",
+ "scripts": {
+ "dev": "vite",
+ "build": "tsc -b && vite build",
+ "lint": "eslint .",
+ "preview": "vite preview"
+ },
+ "dependencies": {
+ "@reown/appkit": "1.8.14",
+ "@reown/appkit-adapter-ethers": "1.8.14",
+ "ethers": "6.16.0",
+ "react": "19.2.1",
+ "react-dom": "19.2.1"
+ },
+ "devDependencies": {
+ "@eslint/js": "9.39.1",
+ "@types/react": "19.2.7",
+ "@types/react-dom": "19.2.3",
+ "@vitejs/plugin-react": "5.1.1",
+ "eslint": "9.39.1",
+ "eslint-plugin-react-hooks": "7.0.1",
+ "eslint-plugin-react-refresh": "0.4.24",
+ "globals": "16.5.0",
+ "typescript": "5.9.3",
+ "typescript-eslint": "8.48.1",
+ "vite": "7.2.6"
+ }
+}
diff --git a/frontend/src/App.tsx b/frontend/src/App.tsx
new file mode 100644
index 0000000..6b6939e
--- /dev/null
+++ b/frontend/src/App.tsx
@@ -0,0 +1,39 @@
+import { Dashboard } from "./components/Dashboard/Dashboard";
+import { WalletConnect } from "./components/WalletConnect";
+import "./styles/globals.css";
+
+function App() {
+ return (
+
+
+
+
+ Golden Bridge
+
+
+
+
+
+
+
+
+
+ );
+}
+
+export default App;
diff --git a/frontend/src/components/Admin/AdminPanel.module.css b/frontend/src/components/Admin/AdminPanel.module.css
new file mode 100644
index 0000000..ec29488
--- /dev/null
+++ b/frontend/src/components/Admin/AdminPanel.module.css
@@ -0,0 +1,371 @@
+.adminPanel {
+ background: linear-gradient(135deg, rgba(245, 158, 11, 0.05) 0%, rgba(245, 158, 11, 0.02) 100%);
+ border: 2px solid var(--color-warning);
+ border-radius: var(--radius-xl);
+ padding: 1.5rem;
+ margin-bottom: 1.5rem;
+ position: relative;
+}
+
+.adminPanel::before {
+ content: "";
+ position: absolute;
+ top: 0;
+ left: 0;
+ right: 0;
+ height: 4px;
+ background: linear-gradient(90deg, var(--color-warning), var(--color-primary));
+ border-radius: var(--radius-xl) var(--radius-xl) 0 0;
+}
+
+.header {
+ display: flex;
+ align-items: center;
+ justify-content: space-between;
+ margin-bottom: 1rem;
+ padding-bottom: 1rem;
+ border-bottom: 1px solid rgba(245, 158, 11, 0.2);
+}
+
+.headerLeft {
+ display: flex;
+ align-items: center;
+ gap: 0.75rem;
+}
+
+.warningIcon {
+ font-size: 1.5rem;
+ animation: pulse 2s ease-in-out infinite;
+}
+
+@keyframes pulse {
+
+ 0%,
+ 100% {
+ opacity: 1;
+ }
+
+ 50% {
+ opacity: 0.6;
+ }
+}
+
+.title {
+ font-size: 1.25rem;
+ font-weight: 700;
+ color: var(--color-warning);
+ margin: 0;
+ display: flex;
+ align-items: center;
+ gap: 0.5rem;
+}
+
+.badge {
+ display: inline-flex;
+ align-items: center;
+ gap: 0.25rem;
+ padding: 0.25rem 0.75rem;
+ background: var(--color-warning-light);
+ color: var(--color-warning);
+ border: 1px solid var(--color-warning);
+ border-radius: var(--radius-md);
+ font-size: 0.75rem;
+ font-weight: 600;
+ text-transform: uppercase;
+ letter-spacing: 0.05em;
+}
+
+.collapseButton {
+ background: transparent;
+ border: 1px solid var(--color-warning);
+ color: var(--color-warning);
+ padding: 0.5rem 1rem;
+ border-radius: var(--radius-md);
+ font-size: 0.875rem;
+ cursor: pointer;
+ transition: all var(--transition-fast);
+ display: flex;
+ align-items: center;
+ gap: 0.5rem;
+}
+
+.collapseButton:hover {
+ background: var(--color-warning-light);
+}
+
+.content {
+ display: grid;
+ gap: 1.5rem;
+}
+
+.contentCollapsed {
+ display: none;
+}
+
+/* Contract Section */
+.contractSection {
+ background: var(--color-surface);
+ border: 1px solid var(--color-border);
+ border-radius: var(--radius-lg);
+ padding: 1.25rem;
+}
+
+.contractHeader {
+ display: flex;
+ align-items: center;
+ justify-content: space-between;
+ margin-bottom: 1rem;
+}
+
+.contractTitle {
+ font-size: 1rem;
+ font-weight: 600;
+ color: var(--color-text);
+ display: flex;
+ align-items: center;
+ gap: 0.5rem;
+ margin: 0;
+}
+
+.contractIcon {
+ font-size: 1.25rem;
+}
+
+.statusBadge {
+ display: inline-flex;
+ align-items: center;
+ gap: 0.25rem;
+ padding: 0.25rem 0.5rem;
+ border-radius: var(--radius-sm);
+ font-size: 0.75rem;
+ font-weight: 500;
+}
+
+.statusActive {
+ background: var(--color-success-light);
+ color: var(--color-success);
+}
+
+.statusPaused {
+ background: var(--color-error-light);
+ color: var(--color-error);
+}
+
+.statusUnknown {
+ background: rgba(156, 163, 175, 0.1);
+ color: var(--color-text-muted);
+}
+
+/* Admin Actions */
+.adminActions {
+ display: flex;
+ flex-wrap: wrap;
+ gap: 0.75rem;
+}
+
+.adminButton {
+ display: inline-flex;
+ align-items: center;
+ gap: 0.5rem;
+ padding: 0.625rem 1rem;
+ background: transparent;
+ border: 1px solid var(--color-border);
+ color: var(--color-text);
+ border-radius: var(--radius-md);
+ font-size: 0.875rem;
+ font-weight: 500;
+ cursor: pointer;
+ transition: all var(--transition-fast);
+}
+
+.adminButton:hover:not(:disabled) {
+ background: var(--color-surface);
+ border-color: var(--color-warning);
+ color: var(--color-warning);
+}
+
+.adminButton:disabled {
+ opacity: 0.5;
+ cursor: not-allowed;
+}
+
+.adminButtonDanger {
+ border-color: var(--color-error);
+ color: var(--color-error);
+}
+
+.adminButtonDanger:hover:not(:disabled) {
+ background: var(--color-error-light);
+ border-color: var(--color-error);
+ color: var(--color-error);
+}
+
+.adminButtonSuccess {
+ border-color: var(--color-success);
+ color: var(--color-success);
+}
+
+.adminButtonSuccess:hover:not(:disabled) {
+ background: var(--color-success-light);
+ border-color: var(--color-success);
+ color: var(--color-success);
+}
+
+.adminButtonPrimary {
+ border-color: var(--color-primary);
+ color: var(--color-primary);
+}
+
+.adminButtonPrimary:hover:not(:disabled) {
+ background: var(--color-primary-light);
+ border-color: var(--color-primary);
+ color: var(--color-primary);
+}
+
+.adminButtonSecondary {
+ border-color: var(--color-text-muted);
+ color: var(--color-text-muted);
+}
+
+.adminButtonSecondary:hover:not(:disabled) {
+ background: var(--color-surface);
+ border-color: var(--color-text);
+ color: var(--color-text);
+}
+
+/* Form Section */
+.formSection {
+ margin-top: 1rem;
+ padding-top: 1rem;
+ border-top: 1px solid var(--color-border);
+}
+
+.formTitle {
+ font-size: 0.875rem;
+ font-weight: 600;
+ color: var(--color-text-muted);
+ margin-bottom: 0.75rem;
+}
+
+.formRow {
+ display: flex;
+ gap: 0.75rem;
+ align-items: flex-end;
+}
+
+.formInput {
+ flex: 1;
+}
+
+/* Warning Box */
+.warningBox {
+ display: flex;
+ align-items: flex-start;
+ gap: 0.75rem;
+ padding: 1rem;
+ background: var(--color-warning-light);
+ border: 1px solid var(--color-warning);
+ border-radius: var(--radius-md);
+ margin-bottom: 1rem;
+}
+
+.warningBoxIcon {
+ font-size: 1.25rem;
+ flex-shrink: 0;
+}
+
+.warningBoxContent {
+ flex: 1;
+}
+
+.warningBoxTitle {
+ font-weight: 600;
+ color: var(--color-warning);
+ margin-bottom: 0.25rem;
+}
+
+.warningBoxText {
+ font-size: 0.875rem;
+ color: var(--color-text-muted);
+ line-height: 1.5;
+}
+
+/* Locked State */
+.lockedPanel {
+ background: rgba(156, 163, 175, 0.05);
+ border: 2px dashed var(--color-border);
+ border-radius: var(--radius-xl);
+ padding: 2rem;
+ text-align: center;
+}
+
+.lockedIcon {
+ font-size: 3rem;
+ margin-bottom: 1rem;
+ opacity: 0.5;
+}
+
+.lockedTitle {
+ font-size: 1.125rem;
+ font-weight: 600;
+ color: var(--color-text-muted);
+ margin-bottom: 0.5rem;
+}
+
+.lockedText {
+ font-size: 0.875rem;
+ color: var(--color-text-muted);
+ max-width: 400px;
+ margin: 0 auto;
+}
+
+/* Loading State */
+.loadingState {
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ gap: 0.75rem;
+ padding: 2rem;
+ color: var(--color-text-muted);
+}
+
+.spinner {
+ width: 1.5rem;
+ height: 1.5rem;
+ border: 2px solid var(--color-border);
+ border-top-color: var(--color-warning);
+ border-radius: 50%;
+ animation: spin 1s linear infinite;
+}
+
+@keyframes spin {
+ to {
+ transform: rotate(360deg);
+ }
+}
+
+/* Responsive */
+@media (max-width: 768px) {
+ .adminPanel {
+ padding: 1rem;
+ }
+
+ .header {
+ flex-direction: column;
+ align-items: flex-start;
+ gap: 1rem;
+ }
+
+ .adminActions {
+ flex-direction: column;
+ }
+
+ .adminButton {
+ width: 100%;
+ justify-content: center;
+ }
+
+ .formRow {
+ flex-direction: column;
+ }
+}
\ No newline at end of file
diff --git a/frontend/src/components/Admin/AdminPanel.tsx b/frontend/src/components/Admin/AdminPanel.tsx
new file mode 100644
index 0000000..57998c1
--- /dev/null
+++ b/frontend/src/components/Admin/AdminPanel.tsx
@@ -0,0 +1,626 @@
+import React, { useCallback, useEffect, useState } from "react";
+import { useAdmin } from "../../hooks/useAdmin";
+import { useGoldToken } from "../../hooks/useGoldToken";
+import { useLotterie } from "../../hooks/useLotterie";
+import { useTokenBridge } from "../../hooks/useTokenBridge";
+import { Alert } from "../ui/Alert";
+import { Button } from "../ui/Button";
+import { Input } from "../ui/Input";
+import { InfoIcon, Tooltip } from "../ui/Tooltip";
+import styles from "./AdminPanel.module.css";
+
+interface ContractStatus {
+ isPaused: boolean;
+ isLoading: boolean;
+}
+
+export const AdminPanel: React.FC = () => {
+ const {
+ loading: adminLoading,
+ isGoldTokenOwner,
+ isLotterieOwner,
+ isTokenBridgeOwner,
+ isAnyOwner,
+ } = useAdmin();
+
+ const {
+ loading: goldTokenLoading,
+ pause: pauseGoldToken,
+ unpause: unpauseGoldToken,
+ setFeesAddress,
+ setLotterieAddress,
+ } = useGoldToken();
+
+ const {
+ loading: lotterieLoading,
+ randomDraw,
+ clearError,
+ checkVrfConfiguration,
+ } = useLotterie();
+
+ const {
+ loading: bridgeLoading,
+ pause: pauseBridge,
+ unpause: unpauseBridge,
+ paused: getBridgePaused,
+ setWhitelistedChain,
+ setWhitelistedSender,
+ } = useTokenBridge();
+
+ const [isCollapsed, setIsCollapsed] = useState(false);
+ const [successMsg, setSuccessMsg] = useState(null);
+ const [errorMsg, setErrorMsg] = useState(null);
+
+ // Contract statuses
+ const [bridgeStatus, setBridgeStatus] = useState({
+ isPaused: false,
+ isLoading: true,
+ });
+
+ // Form states
+ const [feesAddressInput, setFeesAddressInput] = useState("");
+ const [lotterieAddressInput, setLotterieAddressInput] = useState("");
+ const [whitelistChainSelector, setWhitelistChainSelector] = useState("");
+ const [whitelistChainEnabled, setWhitelistChainEnabled] = useState(true);
+ const [whitelistSenderAddress, setWhitelistSenderAddress] = useState("");
+ const [whitelistSenderEnabled, setWhitelistSenderEnabled] = useState(true);
+
+ // Fetch bridge status
+ useEffect(() => {
+ if (!isTokenBridgeOwner) return;
+
+ let isMounted = true;
+
+ const fetchStatus = async () => {
+ try {
+ const isPaused = await getBridgePaused();
+ if (isMounted) {
+ setBridgeStatus({ isPaused, isLoading: false });
+ }
+ } catch (err) {
+ console.error("Failed to fetch bridge status:", err);
+ if (isMounted) {
+ setBridgeStatus((prev) => ({ ...prev, isLoading: false }));
+ }
+ }
+ };
+
+ fetchStatus();
+
+ return () => {
+ isMounted = false;
+ };
+ }, [isTokenBridgeOwner, getBridgePaused]);
+
+ const refreshBridgeStatus = useCallback(async () => {
+ try {
+ const isPaused = await getBridgePaused();
+ setBridgeStatus({ isPaused, isLoading: false });
+ } catch (err) {
+ console.error("Failed to fetch bridge status:", err);
+ }
+ }, [getBridgePaused]);
+
+ // Handlers
+ const handlePauseGoldToken = async () => {
+ try {
+ setErrorMsg(null);
+ await pauseGoldToken();
+ setSuccessMsg("GoldToken contract paused successfully!");
+ } catch (err: any) {
+ setErrorMsg(err.message || "Failed to pause GoldToken");
+ }
+ };
+
+ const handleUnpauseGoldToken = async () => {
+ try {
+ setErrorMsg(null);
+ await unpauseGoldToken();
+ setSuccessMsg("GoldToken contract unpaused successfully!");
+ } catch (err: any) {
+ setErrorMsg(err.message || "Failed to unpause GoldToken");
+ }
+ };
+
+ const handleSetFeesAddress = async () => {
+ if (!feesAddressInput) return;
+ try {
+ setErrorMsg(null);
+ await setFeesAddress(feesAddressInput);
+ setSuccessMsg("Fees address updated successfully!");
+ setFeesAddressInput("");
+ } catch (err: any) {
+ setErrorMsg(err.message || "Failed to set fees address");
+ }
+ };
+
+ const handleSetLotterieAddress = async () => {
+ if (!lotterieAddressInput) return;
+ try {
+ setErrorMsg(null);
+ await setLotterieAddress(lotterieAddressInput);
+ setSuccessMsg("Lotterie address updated successfully!");
+ setLotterieAddressInput("");
+ } catch (err: any) {
+ setErrorMsg(err.message || "Failed to set lotterie address");
+ }
+ };
+
+ const handleRandomDraw = async () => {
+ try {
+ setErrorMsg(null);
+ const requestId = await randomDraw();
+ if (requestId) {
+ setSuccessMsg(
+ `Random draw initiated! Request ID: ${requestId.toString()}. Waiting for VRF callback...`
+ );
+ } else {
+ setSuccessMsg("Random draw initiated! Waiting for VRF callback...");
+ }
+ } catch (err: any) {
+ console.error("Random draw failed:", err);
+ setErrorMsg(err.message || "Failed to initiate random draw");
+ }
+ };
+
+ const handleRetryRandomDraw = () => {
+ setErrorMsg(null);
+ setSuccessMsg(null);
+ clearError();
+ };
+
+ const handleCheckVrfConfig = async () => {
+ try {
+ setErrorMsg(null);
+ setSuccessMsg(null);
+ const config = await checkVrfConfiguration();
+ console.log("VRF Configuration:", config);
+ setSuccessMsg("VRF configuration checked. See console for details.");
+ } catch (err: any) {
+ console.error("VRF config check error:", err);
+ setErrorMsg(
+ "Failed to check VRF configuration. See console for details."
+ );
+ }
+ };
+
+ const handlePauseBridge = async () => {
+ try {
+ setErrorMsg(null);
+ await pauseBridge();
+ setSuccessMsg("TokenBridge paused successfully!");
+ refreshBridgeStatus();
+ } catch (err: any) {
+ setErrorMsg(err.message || "Failed to pause bridge");
+ }
+ };
+
+ const handleUnpauseBridge = async () => {
+ try {
+ setErrorMsg(null);
+ await unpauseBridge();
+ setSuccessMsg("TokenBridge unpaused successfully!");
+ refreshBridgeStatus();
+ } catch (err: any) {
+ setErrorMsg(err.message || "Failed to unpause bridge");
+ }
+ };
+
+ const handleSetWhitelistedChain = async () => {
+ if (!whitelistChainSelector) return;
+ try {
+ setErrorMsg(null);
+ // Default CCIP extra args (empty for basic config)
+ const ccipExtraArgs = "0x";
+ await setWhitelistedChain(
+ BigInt(whitelistChainSelector),
+ whitelistChainEnabled,
+ ccipExtraArgs
+ );
+ setSuccessMsg(
+ `Chain ${whitelistChainSelector} ${
+ whitelistChainEnabled ? "whitelisted" : "removed from whitelist"
+ }!`
+ );
+ setWhitelistChainSelector("");
+ } catch (err: any) {
+ setErrorMsg(err.message || "Failed to set whitelisted chain");
+ }
+ };
+
+ const handleSetWhitelistedSender = async () => {
+ if (!whitelistSenderAddress) return;
+ try {
+ setErrorMsg(null);
+ await setWhitelistedSender(
+ whitelistSenderAddress,
+ whitelistSenderEnabled
+ );
+ setSuccessMsg(
+ `Sender ${whitelistSenderAddress.substring(0, 10)}... ${
+ whitelistSenderEnabled ? "whitelisted" : "removed from whitelist"
+ }!`
+ );
+ setWhitelistSenderAddress("");
+ } catch (err: any) {
+ setErrorMsg(err.message || "Failed to set whitelisted sender");
+ }
+ };
+
+ // Loading state
+ if (adminLoading) {
+ return (
+
+
+
+
Checking admin permissions...
+
+
+ );
+ }
+
+ // Not an owner - show locked state
+ if (!isAnyOwner) {
+ return (
+
+
🔒
+
Admin Access Required
+
+ This section is only accessible to contract owners. Connect with an
+ owner wallet to access admin functions.
+
+
+ );
+ }
+
+ return (
+
+ {/* Header */}
+
+
+ ⚠️
+
+ Admin Panel
+
+
+
+ 🔑 Owner Access
+
+
+
setIsCollapsed(!isCollapsed)}
+ >
+ {isCollapsed ? "▼ Expand" : "▲ Collapse"}
+
+
+
+ {/* Alerts */}
+ {successMsg && (
+
setSuccessMsg(null)}
+ >
+ {successMsg}
+
+ )}
+ {errorMsg && (
+
setErrorMsg(null)}>
+ {errorMsg}
+
+ )}
+
+ {/* Content */}
+
+ {/* Warning Box */}
+
+
⚠️
+
+
Caution Required
+
+ Admin actions are irreversible and affect all users. Pausing
+ contracts will prevent all user interactions. Ensure you
+ understand the implications before proceeding.
+
+
+
+
+ {/* GoldToken Admin Section */}
+ {isGoldTokenOwner && (
+
+
+
+ 🪙
+ GoldToken Administration
+
+
+
+ ✓ Owner
+
+
+
+
+
+
+
+ ⏸️ Pause Contract
+
+
+
+
+ ▶️ Unpause Contract
+
+
+
+
+ {/* Set Fees Address */}
+
+
Update Fees Address
+
+
+ setFeesAddressInput(e.target.value)}
+ />
+
+
+ Update
+
+
+
+
+ {/* Set Lotterie Address */}
+
+
Update Lotterie Address
+
+
+ setLotterieAddressInput(e.target.value)}
+ />
+
+
+ Update
+
+
+
+
+ )}
+
+ {/* Lotterie Admin Section */}
+ {isLotterieOwner && (
+
+
+
+ 🎰
+ Lotterie Administration
+
+
+
+ ✓ Owner
+
+
+
+
+
+
+
+
+ {lotterieLoading
+ ? "⏳ Processing..."
+ : "🎲 Trigger Random Draw"}
+
+
+
+ {/* Retry Button - shown when there's an error */}
+ {errorMsg && (
+
+
+ 🔄 Retry
+
+
+ )}
+
+ {/* Debug Button - always visible for troubleshooting */}
+
+
+ 🔧 Debug VRF
+
+
+
+
+
+ )}
+
+ {/* TokenBridge Admin Section */}
+ {isTokenBridgeOwner && (
+
+
+
+ 🌉
+ TokenBridge Administration
+
+
+
+
+ ✓ Owner
+
+
+ {bridgeStatus.isLoading ? (
+
+ Loading...
+
+ ) : (
+
+ {bridgeStatus.isPaused ? "⏸️ Paused" : "✅ Active"}
+
+ )}
+
+
+
+
+
+
+ ⏸️ Pause Bridge
+
+
+
+
+ ▶️ Unpause Bridge
+
+
+
+
+ {/* Whitelist Chain */}
+
+
+ Whitelist Chain
+
+
+
+
+
+ {/* Whitelist Sender */}
+
+
+ Whitelist Sender
+
+
+
+
+
+ )}
+
+
+ );
+};
diff --git a/frontend/src/components/Admin/index.ts b/frontend/src/components/Admin/index.ts
new file mode 100644
index 0000000..a69970e
--- /dev/null
+++ b/frontend/src/components/Admin/index.ts
@@ -0,0 +1 @@
+export * from "./AdminPanel";
diff --git a/frontend/src/components/Dashboard/Dashboard.module.css b/frontend/src/components/Dashboard/Dashboard.module.css
new file mode 100644
index 0000000..df865a5
--- /dev/null
+++ b/frontend/src/components/Dashboard/Dashboard.module.css
@@ -0,0 +1,290 @@
+.container {
+ max-width: 1280px;
+ margin: 0 auto;
+ padding: 1rem;
+}
+
+@media (min-width: 768px) {
+ .container {
+ padding: 1.5rem;
+ }
+}
+
+@media (min-width: 1024px) {
+ .container {
+ padding: 2rem;
+ }
+}
+
+.header {
+ display: flex;
+ justify-content: space-between;
+ align-items: flex-start;
+ margin-bottom: 1.5rem;
+ flex-wrap: wrap;
+ gap: 1rem;
+}
+
+.headerRight {
+ display: flex;
+ align-items: center;
+ gap: 1rem;
+}
+
+/* Mobile-specific adjustments */
+@media (max-width: 640px) {
+ .header {
+ flex-direction: column;
+ align-items: stretch;
+ gap: 0.75rem;
+ }
+
+ .headerRight {
+ justify-content: center;
+ }
+}
+
+.title {
+ font-size: 2rem;
+ font-weight: 700;
+ color: var(--color-primary);
+ margin-bottom: 0.5rem;
+ display: flex;
+ align-items: center;
+ gap: 0.5rem;
+}
+
+.subtitle {
+ color: var(--color-text-muted);
+ font-size: 1.125rem;
+}
+
+/* Progress Section */
+.progressSection {
+ margin-bottom: 1.5rem;
+}
+
+/* Onboarding Section */
+.onboardingSection {
+ margin-bottom: 1.5rem;
+}
+
+/* Admin Section */
+.adminSection {
+ margin-bottom: 1.5rem;
+}
+
+.dismissOnboarding {
+ display: inline-block;
+ margin-top: 1rem;
+ padding: 0.25rem 0.5rem;
+ background: transparent;
+ border: none;
+ color: var(--color-text-muted);
+ font-size: 0.75rem;
+ cursor: pointer;
+ text-decoration: underline;
+}
+
+.dismissOnboarding:hover {
+ color: var(--color-primary);
+}
+
+.grid {
+ display: grid;
+ grid-template-columns: 1fr;
+ gap: 1.5rem;
+}
+
+@media (min-width: 1024px) {
+ .grid {
+ grid-template-columns: 1.5fr 1fr;
+ }
+}
+
+.mainColumn {
+ display: flex;
+ flex-direction: column;
+ gap: 1.5rem;
+}
+
+.sideColumn {
+ display: flex;
+ flex-direction: column;
+ gap: 1.5rem;
+}
+
+.sideItem {
+ flex: 1;
+}
+
+/* Welcome Screen */
+.welcome {
+ text-align: center;
+ padding: 3rem 2rem;
+ background-color: var(--color-surface);
+ border-radius: var(--radius-lg);
+ border: 1px solid var(--color-border);
+ margin-top: 2rem;
+}
+
+.welcomeHeader {
+ margin-bottom: 2rem;
+}
+
+.valueProps {
+ max-width: 500px;
+ margin: 0 auto 2rem auto;
+}
+
+.features {
+ display: grid;
+ grid-template-columns: 1fr;
+ gap: 1.5rem;
+ margin-top: 2rem;
+ margin-bottom: 2rem;
+ text-align: left;
+}
+
+@media (min-width: 768px) {
+ .features {
+ grid-template-columns: repeat(3, 1fr);
+ }
+}
+
+.feature {
+ padding: 1.5rem;
+ background-color: rgba(0, 0, 0, 0.2);
+ border-radius: var(--radius-md);
+ border: 1px solid var(--color-border);
+ transition: border-color 0.2s ease, transform 0.2s ease;
+}
+
+.feature:hover {
+ border-color: var(--color-primary);
+ transform: translateY(-2px);
+}
+
+.featureIcon {
+ font-size: 2rem;
+ display: block;
+ margin-bottom: 0.75rem;
+}
+
+.feature h3 {
+ color: var(--color-primary);
+ margin-bottom: 0.5rem;
+ font-size: 1.125rem;
+}
+
+.feature p {
+ color: var(--color-text-muted);
+ font-size: 0.875rem;
+ margin-bottom: 0.75rem;
+ line-height: 1.5;
+}
+
+/* Technology Stack */
+.techStack {
+ margin-top: 2rem;
+ padding: 1.5rem;
+ background-color: rgba(0, 0, 0, 0.2);
+ border-radius: var(--radius-md);
+ border: 1px solid var(--color-border);
+}
+
+.techTitle {
+ font-size: 1rem;
+ font-weight: 600;
+ color: var(--color-text);
+ margin-bottom: 1rem;
+ display: inline-flex;
+ align-items: center;
+ gap: 0.5rem;
+}
+
+.techItems {
+ display: flex;
+ justify-content: center;
+ gap: 2rem;
+ flex-wrap: wrap;
+}
+
+.techItem {
+ display: flex;
+ flex-direction: column;
+ align-items: center;
+ gap: 0.5rem;
+ padding: 0.75rem 1rem;
+ background-color: rgba(255, 215, 0, 0.05);
+ border: 1px solid rgba(255, 215, 0, 0.2);
+ border-radius: var(--radius-md);
+ cursor: help;
+ transition: all 0.2s ease;
+}
+
+.techItem:hover {
+ background-color: rgba(255, 215, 0, 0.1);
+ border-color: var(--color-primary);
+}
+
+.techItem span:first-child {
+ font-size: 1.5rem;
+}
+
+.techItem span:last-child {
+ font-size: 0.75rem;
+ color: var(--color-text-muted);
+ text-transform: uppercase;
+ letter-spacing: 0.05em;
+}
+
+/* Connect CTA */
+.connectCta {
+ margin-top: 2rem;
+ padding-top: 2rem;
+ border-top: 1px solid var(--color-border);
+}
+
+.ctaText {
+ color: var(--color-text-muted);
+ margin-bottom: 1rem;
+ font-size: 0.875rem;
+}
+
+/* Footer */
+.footer {
+ margin-top: 3rem;
+ padding-top: 1.5rem;
+ border-top: 1px solid var(--color-border);
+}
+
+.footerContent {
+ display: flex;
+ justify-content: space-between;
+ align-items: center;
+ flex-wrap: wrap;
+ gap: 1rem;
+}
+
+.footerText {
+ color: var(--color-text-muted);
+ font-size: 0.875rem;
+}
+
+.footerLinks {
+ display: flex;
+ gap: 1rem;
+}
+
+.footerLink {
+ color: var(--color-text-muted);
+ font-size: 0.875rem;
+ text-decoration: none;
+ transition: color 0.2s ease;
+}
+
+.footerLink:hover {
+ color: var(--color-primary);
+ text-decoration: none;
+}
\ No newline at end of file
diff --git a/frontend/src/components/Dashboard/Dashboard.tsx b/frontend/src/components/Dashboard/Dashboard.tsx
new file mode 100644
index 0000000..84a73b7
--- /dev/null
+++ b/frontend/src/components/Dashboard/Dashboard.tsx
@@ -0,0 +1,354 @@
+import { useAppKitAccount } from "@reown/appkit/react";
+import { formatEther } from "ethers";
+import React, { useEffect, useMemo, useState } from "react";
+import { useAdmin } from "../../hooks/useAdmin";
+import { useGoldToken } from "../../hooks/useGoldToken";
+import { useNetwork } from "../../hooks/useNetwork";
+import { AdminPanel } from "../Admin/AdminPanel";
+import { GoldTokenCard } from "../GoldToken/GoldTokenCard";
+import { LotterieCard } from "../Lotterie/LotterieCard";
+import { NetworkSwitcher } from "../NetworkSwitcher";
+import { TokenBridgeCard } from "../TokenBridge/TokenBridgeCard";
+import { Alert } from "../ui/Alert";
+import { Badge } from "../ui/Badge";
+import { FeatureItem, HighlightBox, InfoCard } from "../ui/InfoCard";
+import { CompactStepIndicator, Step } from "../ui/StepIndicator";
+import { InfoIcon, Tooltip } from "../ui/Tooltip";
+import styles from "./Dashboard.module.css";
+
+// Define the user journey steps
+const JOURNEY_STEPS: Step[] = [
+ {
+ id: "connect",
+ label: "Connect Wallet",
+ icon: "🔗",
+ description: "Connect your Web3 wallet to get started",
+ },
+ {
+ id: "mint",
+ label: "Mint GLD",
+ icon: "🪙",
+ description: "Convert ETH to gold-backed GLD tokens",
+ },
+ {
+ id: "lottery",
+ label: "Lottery",
+ icon: "🎰",
+ description: "Participate in daily draws with your GLD",
+ },
+ {
+ id: "bridge",
+ label: "Bridge",
+ icon: "🌉",
+ description: "Transfer GLD across chains (optional)",
+ },
+];
+
+export const Dashboard: React.FC = () => {
+ const { isConnected, address } = useAppKitAccount();
+ const { isSupportedNetwork } = useNetwork();
+ const { balanceOf } = useGoldToken();
+ const { isAnyOwner } = useAdmin();
+
+ const [balance, setBalance] = useState("0");
+ const [showOnboarding, setShowOnboarding] = useState(true);
+
+ // Fetch user balance to determine step progress
+ useEffect(() => {
+ const fetchBalance = async () => {
+ if (isConnected && address) {
+ try {
+ const bal = await balanceOf(address);
+ setBalance(formatEther(bal));
+ } catch (err) {
+ console.error("Error fetching balance:", err);
+ }
+ }
+ };
+ fetchBalance();
+ }, [isConnected, address, balanceOf]);
+
+ // Compute step progress based on user state (using useMemo to avoid cascading renders)
+ const { currentStep, completedSteps } = useMemo(() => {
+ const completed: string[] = [];
+ let current = "connect";
+
+ if (isConnected) {
+ completed.push("connect");
+ current = "mint";
+
+ if (parseFloat(balance) > 0) {
+ completed.push("mint");
+ current = "lottery";
+
+ if (parseFloat(balance) >= 1) {
+ completed.push("lottery");
+ current = "bridge";
+ }
+ }
+ }
+
+ return { currentStep: current, completedSteps: completed };
+ }, [isConnected, balance]);
+
+ // Welcome screen for non-connected users
+ if (!isConnected) {
+ return (
+
+
+
+
🏆 Welcome to Golden Bridge
+
+ Your gateway to gold-backed tokens on the blockchain
+
+
+
+ {/* Value Proposition */}
+
+
+ 1 GLD = 1 gram of gold
+
+ Hold tokenized gold backed by real-time Chainlink price feeds
+
+
+
+ {/* Feature Cards */}
+
+
+
🪙
+
Gold Token
+
+ Mint GLD tokens backed by real-time gold prices using Chainlink
+ Price Feeds.
+
+
Chainlink Powered
+
+
+
🎰
+
Daily Lottery
+
+ Win rewards from transaction fees in provably fair daily draws.
+
+
VRF Secured
+
+
+
🌉
+
Cross-Chain Bridge
+
Seamlessly transfer GLD between Ethereum and BSC networks.
+
CCIP Enabled
+
+
+
+ {/* How It Works */}
+
+
+
+
+
+
+
+ {/* Technology Stack */}
+
+
+ Powered by Chainlink
+
+
+
+
+
+ 📊
+ Price Feeds
+
+
+
+
+ 🎲
+ VRF
+
+
+
+
+ 🔗
+ CCIP
+
+
+
+
+
+ {/* Connect CTA */}
+
+
+ Connect your wallet to start your golden journey
+
+
+
+
+
+ );
+ }
+
+ return (
+
+ {/* Header with Step Indicator */}
+
+
+
🏆 Dashboard
+
Manage your Golden Bridge assets
+
+
+
+
+
+
+ {/* Progress Indicator */}
+
+
+
+
+ {/* Network Warning */}
+ {!isSupportedNetwork() && (
+
+ Please switch to Sepolia Testnet or BSC Testnet to use the
+ application.
+
+ )}
+
+ {/* Onboarding Tips */}
+ {showOnboarding && completedSteps.length < 3 && (
+
+
+ {currentStep === "mint" && (
+ <>
+
+ Next Step: Mint your first GLD tokens!
+
+
+ Enter an ETH amount in the Gold Token card below and click
+ "Mint GLD" to convert your ETH to gold-backed tokens.
+
+ >
+ )}
+ {currentStep === "lottery" && (
+ <>
+
+ Great progress! You now own GLD tokens.
+
+
+ {parseFloat(balance) >= 1 ? (
+ <>
+ ✅ You're eligible for the lottery! Check the Lottery card
+ to see your pending rewards.
+ >
+ ) : (
+ <>
+ Hold at least 1 GLD to become eligible for daily lottery
+ draws. You currently have {parseFloat(balance).toFixed(4)}{" "}
+ GLD.
+ >
+ )}
+
+ >
+ )}
+ {currentStep === "bridge" && (
+ <>
+
+ You're all set! You can now bridge your GLD
+ to other chains.
+
+
+ Use the Bridge card to transfer GLD between Ethereum and BSC.
+ This is optional but useful for accessing different DeFi
+ ecosystems.
+
+ >
+ )}
+ setShowOnboarding(false)}
+ >
+ Dismiss tips
+
+
+
+ )}
+
+ {/* Admin Panel - Only visible to owners */}
+ {isAnyOwner && (
+
+ )}
+
+ {/* Main Content Grid */}
+
+
+ {/* Footer Info */}
+
+
+
+ Golden Bridge - A Chainlink-powered DeFi showcase
+
+
+
+
+
+ );
+};
diff --git a/frontend/src/components/GoldToken/GoldTokenCard.module.css b/frontend/src/components/GoldToken/GoldTokenCard.module.css
new file mode 100644
index 0000000..1a763e6
--- /dev/null
+++ b/frontend/src/components/GoldToken/GoldTokenCard.module.css
@@ -0,0 +1,224 @@
+.card {
+ height: 100%;
+}
+
+.headerTitle {
+ display: inline-flex;
+ align-items: center;
+ gap: 0.5rem;
+}
+
+.statsGrid {
+ display: grid;
+ grid-template-columns: 1fr 1fr;
+ gap: 1rem;
+ margin-bottom: 1.5rem;
+ padding: 1rem;
+ background-color: rgba(0, 0, 0, 0.2);
+ border-radius: var(--radius-md);
+}
+
+/* Mobile adjustments for stats grid */
+@media (max-width: 640px) {
+ .statsGrid {
+ grid-template-columns: 1fr;
+ gap: 0.75rem;
+ padding: 0.75rem;
+ }
+
+ .statItem {
+ padding: 0.5rem 0;
+ }
+}
+
+.statItem {
+ display: flex;
+ flex-direction: column;
+ align-items: center;
+ text-align: center;
+}
+
+.statLabel {
+ font-size: 0.875rem;
+ color: var(--color-text-muted);
+ margin-bottom: 0.25rem;
+ display: inline-flex;
+ align-items: center;
+ gap: 0.25rem;
+}
+
+.statValue {
+ font-size: 1.25rem;
+ font-weight: 700;
+ color: var(--color-primary);
+}
+
+.tabs {
+ display: flex;
+ border-bottom: 1px solid var(--color-border);
+ margin-bottom: 1.5rem;
+}
+
+.tab {
+ flex: 1;
+ padding: 0.75rem;
+ background: transparent;
+ border: none;
+ border-bottom: 2px solid transparent;
+ color: var(--color-text-muted);
+ font-weight: 500;
+ transition: all 0.2s;
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ gap: 0.5rem;
+ min-height: 44px;
+ /* Touch target */
+}
+
+/* Mobile adjustments for tabs */
+@media (max-width: 640px) {
+ .tab {
+ padding: 0.625rem 0.5rem;
+ font-size: 0.875rem;
+ gap: 0.25rem;
+ }
+
+ .tabIcon {
+ font-size: 0.75rem;
+ }
+}
+
+.tab:hover {
+ color: var(--color-text);
+ background-color: rgba(255, 255, 255, 0.02);
+}
+
+.activeTab {
+ color: var(--color-primary);
+ border-bottom-color: var(--color-primary);
+}
+
+.tabIcon {
+ font-size: 0.875rem;
+}
+
+.tabContent {
+ animation: fadeIn 0.3s ease;
+}
+
+.inputLabel {
+ display: inline-flex;
+ align-items: center;
+ gap: 0.25rem;
+}
+
+.calculationBox {
+ background-color: rgba(255, 215, 0, 0.05);
+ border: 1px solid rgba(255, 215, 0, 0.2);
+ border-radius: var(--radius-md);
+ padding: 0.75rem 1rem;
+ margin-bottom: 0.5rem;
+}
+
+/* Mobile adjustments for calculation box */
+@media (max-width: 640px) {
+ .calculationBox {
+ padding: 0.625rem 0.75rem;
+ }
+
+ .calcRow {
+ font-size: 0.8125rem;
+ flex-direction: column;
+ align-items: flex-start;
+ gap: 0.25rem;
+ }
+
+ .calcRow span:first-child {
+ font-size: 0.8125rem;
+ }
+}
+
+.calcRow {
+ display: flex;
+ justify-content: space-between;
+ align-items: center;
+ font-size: 0.875rem;
+ padding: 0.25rem 0;
+}
+
+.calcRow span:first-child {
+ color: var(--color-text-muted);
+ display: inline-flex;
+ align-items: center;
+ gap: 0.25rem;
+}
+
+.calcValue {
+ font-weight: 600;
+ color: var(--color-primary);
+}
+
+.calcFee {
+ color: var(--color-warning);
+ font-size: 0.8125rem;
+}
+
+.estimation {
+ display: flex;
+ justify-content: space-between;
+ font-size: 0.875rem;
+ padding: 0.5rem;
+ background-color: rgba(255, 215, 0, 0.05);
+ border-radius: var(--radius-sm);
+ margin-bottom: 0.5rem;
+}
+
+.feeInfo {
+ font-size: 0.75rem;
+ color: var(--color-text-muted);
+ text-align: center;
+ margin-bottom: 1rem;
+}
+
+.toggleEducation {
+ display: block;
+ width: 100%;
+ margin-top: 1.5rem;
+ padding: 0.5rem;
+ background: transparent;
+ border: 1px dashed var(--color-border);
+ border-radius: var(--radius-md);
+ color: var(--color-text-muted);
+ font-size: 0.8125rem;
+ cursor: pointer;
+ transition: all 0.2s ease;
+ min-height: 44px;
+ /* Touch target */
+}
+
+/* Mobile adjustments for toggle education */
+@media (max-width: 640px) {
+ .toggleEducation {
+ margin-top: 1rem;
+ padding: 0.75rem;
+ min-height: 48px;
+ /* Larger touch target */
+ font-size: 0.875rem;
+ }
+}
+
+.toggleEducation:hover {
+ border-color: var(--color-primary);
+ color: var(--color-primary);
+}
+
+@keyframes fadeIn {
+ from {
+ opacity: 0;
+ }
+
+ to {
+ opacity: 1;
+ }
+}
\ No newline at end of file
diff --git a/frontend/src/components/GoldToken/GoldTokenCard.tsx b/frontend/src/components/GoldToken/GoldTokenCard.tsx
new file mode 100644
index 0000000..b1cb75b
--- /dev/null
+++ b/frontend/src/components/GoldToken/GoldTokenCard.tsx
@@ -0,0 +1,505 @@
+import { formatEther, formatUnits, parseEther } from "ethers";
+import React, { useEffect, useState } from "react";
+import { useGoldToken } from "../../hooks/useGoldToken";
+import { Alert } from "../ui/Alert";
+import { Badge } from "../ui/Badge";
+import { Button } from "../ui/Button";
+import { Card } from "../ui/Card";
+import { FeatureItem, HighlightBox, InfoCard } from "../ui/InfoCard";
+import { Input } from "../ui/Input";
+import { InfoIcon, Tooltip } from "../ui/Tooltip";
+import styles from "./GoldTokenCard.module.css";
+
+export const GoldTokenCard: React.FC = () => {
+ const {
+ loading,
+ error,
+ isConnected,
+ address,
+ mint,
+ burn,
+ transfer,
+ balanceOf,
+ getGoldPriceInEth,
+ getFees,
+ } = useGoldToken();
+
+ const [balance, setBalance] = useState("0");
+ const [goldPrice, setGoldPrice] = useState("0");
+ const [fees, setFees] = useState("0");
+ const [mintAmount, setMintAmount] = useState("");
+ const [burnAmount, setBurnAmount] = useState("");
+ const [transferTo, setTransferTo] = useState("");
+ const [transferAmount, setTransferAmount] = useState("");
+ const [activeTab, setActiveTab] = useState<"mint" | "burn" | "transfer">(
+ "mint"
+ );
+ const [successMsg, setSuccessMsg] = useState(null);
+ const [showEducation, setShowEducation] = useState(true);
+
+ const fetchData = async () => {
+ try {
+ if (address) {
+ const bal = await balanceOf(address);
+ setBalance(formatEther(bal));
+ }
+ const price = await getGoldPriceInEth();
+ setGoldPrice(formatUnits(price, 8));
+
+ const fee = await getFees();
+ setFees(fee.toString());
+ } catch (err) {
+ console.error("Error fetching data:", err);
+ }
+ };
+
+ useEffect(() => {
+ if (isConnected && address) {
+ fetchData();
+ }
+ // eslint-disable-next-line react-hooks/exhaustive-deps
+ }, [isConnected, address]);
+
+ const handleMint = async () => {
+ try {
+ setSuccessMsg(null);
+ if (!mintAmount) return;
+ await mint(parseEther(mintAmount));
+ setSuccessMsg(`Successfully minted GLD with ${mintAmount} ETH!`);
+ setMintAmount("");
+ fetchData();
+ } catch (err) {
+ console.error(err);
+ }
+ };
+
+ const handleBurn = async () => {
+ try {
+ setSuccessMsg(null);
+ if (!burnAmount) return;
+ await burn(parseEther(burnAmount));
+ setSuccessMsg(`Successfully burned ${burnAmount} GLD!`);
+ setBurnAmount("");
+ fetchData();
+ } catch (err) {
+ console.error(err);
+ }
+ };
+
+ const handleTransfer = async () => {
+ try {
+ setSuccessMsg(null);
+ if (!transferTo || !transferAmount) return;
+ await transfer(transferTo, parseEther(transferAmount));
+ setSuccessMsg(
+ `Successfully transferred ${transferAmount} GLD to ${transferTo.substring(
+ 0,
+ 6
+ )}...${transferTo.substring(38)}!`
+ );
+ setTransferTo("");
+ setTransferAmount("");
+ fetchData();
+ } catch (err) {
+ console.error(err);
+ }
+ };
+
+ const estimatedGld =
+ mintAmount && goldPrice && parseFloat(goldPrice) > 0
+ ? (parseFloat(mintAmount) / parseFloat(goldPrice)).toFixed(4)
+ : "0";
+
+ const feeAmount =
+ mintAmount && parseFloat(mintAmount) > 0
+ ? ((parseFloat(mintAmount) * parseFloat(fees)) / 100).toFixed(6)
+ : "0";
+
+ const isEligible = parseFloat(balance) >= 1;
+
+ return (
+
+
+ 🪙 Gold Token (GLD)
+
+ 1 GLD = 1 gram of gold
+
+ GLD is an ERC-20 token backed by real-time gold prices from
+ Chainlink Price Feeds.
+
+ }
+ size="md"
+ />
+
+ }
+ subtitle="Mint, burn, and transfer gold-backed tokens"
+ action={
+
+
+ {isEligible ? "✓ Lottery Eligible" : "Not Eligible"}
+
+
+ }
+ />
+
+ {/* Stats Section */}
+
+
+
+ Your Balance
+
+
+
+ {parseFloat(balance).toFixed(4)} GLD
+
+
+
+
+ Gold Price
+
+ Current price of 1 gram of gold in ETH.
+
+ Powered by Chainlink Price Feeds
+
+ }
+ size="sm"
+ />
+
+
+ {parseFloat(goldPrice).toFixed(6)} ETH
+
+
+
+
+ {error && (
+ {}}>
+ {error}
+
+ )}
+
+ {successMsg && (
+ setSuccessMsg(null)}
+ >
+ {successMsg}
+
+ )}
+
+ {/* Tabs */}
+
+ setActiveTab("mint")}
+ >
+ 🟢 Mint
+
+ setActiveTab("burn")}
+ >
+ 🔴 Burn
+
+ setActiveTab("transfer")}
+ >
+ 📤 Transfer
+
+
+
+
+ {/* MINT TAB */}
+ {activeTab === "mint" && (
+
+ {showEducation && (
+
+
+ Minting converts your ETH into GLD tokens
+ at the current gold price. Each GLD represents 1 gram of
+ gold.
+
+
+ How it works:
+
+ 1. Enter the amount of ETH you want to spend
+
+ 2. The contract calculates how much GLD you'll receive based
+ on real-time gold prices
+
+ 3. A 5% fee is applied (split between lottery pool and
+ treasury)
+
+
+
+ )}
+
+
+ Amount (ETH)
+
+
+ }
+ placeholder="0.0"
+ value={mintAmount}
+ onChange={(e) => setMintAmount(e.target.value)}
+ type="number"
+ min="0"
+ step="0.0001"
+ rightElement="ETH"
+ />
+
+
+
+ You'll receive (estimated):
+ {estimatedGld} GLD
+
+
+
+ Fee ({fees}%):
+
+ Fee breakdown:
+ • 2.5% → Lottery Pool 🎰
+ • 2.5% → Treasury 🏦
+
+ }
+ size="sm"
+ />
+
+ {feeAmount} ETH
+
+
+
+
+ 🪙 Mint GLD
+
+
+ )}
+
+ {/* BURN TAB */}
+ {activeTab === "burn" && (
+
+ {showEducation && (
+
+
+ Burning destroys your GLD tokens, removing
+ them from circulation. This is how you exit your gold
+ position.
+
+
+ ⚠️ Important: Burning is irreversible. Once
+ burned, tokens cannot be recovered. A 5% fee applies to burn
+ operations.
+
+
+
+ )}
+
+
+ Amount (GLD)
+
+
+ }
+ placeholder="0.0"
+ value={burnAmount}
+ onChange={(e) => setBurnAmount(e.target.value)}
+ type="number"
+ min="0"
+ step="0.0001"
+ rightElement="GLD"
+ />
+
+
+
+ Your balance:
+
+ {parseFloat(balance).toFixed(4)} GLD
+
+
+
+ Fee ({fees}%):
+
+ {burnAmount
+ ? (
+ (parseFloat(burnAmount) * parseFloat(fees)) /
+ 100
+ ).toFixed(4)
+ : "0"}{" "}
+ GLD
+
+
+
+
+
+ 🔥 Burn GLD
+
+
+ )}
+
+ {/* TRANSFER TAB */}
+ {activeTab === "transfer" && (
+
+ {showEducation && (
+
+
+ Send GLD tokens to another wallet address. Transfers are
+ instant and recorded on the blockchain.
+
+
+ 💡 Tip: Double-check the recipient address
+ before sending. Blockchain transactions cannot be reversed!
+
+
+
+ )}
+
+
+ Recipient Address
+
+
+ }
+ placeholder="0x..."
+ value={transferTo}
+ onChange={(e) => setTransferTo(e.target.value)}
+ />
+
setTransferAmount(e.target.value)}
+ type="number"
+ min="0"
+ step="0.0001"
+ rightElement="GLD"
+ />
+
+
+
+ Your balance:
+
+ {parseFloat(balance).toFixed(4)} GLD
+
+
+
+ Remaining after transfer:
+
+ {transferAmount
+ ? Math.max(
+ 0,
+ parseFloat(balance) - parseFloat(transferAmount)
+ ).toFixed(4)
+ : parseFloat(balance).toFixed(4)}{" "}
+ GLD
+
+
+
+
+
+ 📤 Transfer
+
+
+ )}
+
+
+ {/* Toggle Education */}
+ setShowEducation(!showEducation)}
+ >
+ {showEducation ? "Hide" : "Show"} explanations
+
+
+
+ );
+};
diff --git a/frontend/src/components/Lotterie/LotterieCard.module.css b/frontend/src/components/Lotterie/LotterieCard.module.css
new file mode 100644
index 0000000..bf04427
--- /dev/null
+++ b/frontend/src/components/Lotterie/LotterieCard.module.css
@@ -0,0 +1,166 @@
+.card {
+ height: 100%;
+}
+
+.headerTitle {
+ display: inline-flex;
+ align-items: center;
+ gap: 0.5rem;
+}
+
+.jackpotSection {
+ display: flex;
+ flex-direction: column;
+ align-items: center;
+ padding: 2rem;
+ background: linear-gradient(135deg, rgba(255, 215, 0, 0.1) 0%, rgba(255, 215, 0, 0.05) 100%);
+ border-radius: var(--radius-md);
+ border: 1px solid rgba(255, 215, 0, 0.2);
+ margin-bottom: 1.5rem;
+ text-align: center;
+}
+
+.jackpotTitle {
+ font-size: 1rem;
+ color: var(--color-text-muted);
+ margin-bottom: 0.5rem;
+ text-transform: uppercase;
+ letter-spacing: 0.05em;
+ display: inline-flex;
+ align-items: center;
+ gap: 0.5rem;
+}
+
+.jackpotValue {
+ font-size: 2.5rem;
+ font-weight: 800;
+ color: var(--color-primary);
+ text-shadow: 0 2px 4px rgba(0, 0, 0, 0.2);
+}
+
+/* Mobile adjustments for jackpot section */
+@media (max-width: 640px) {
+ .jackpotSection {
+ padding: 1rem;
+ margin-bottom: 1rem;
+ }
+
+ .jackpotTitle {
+ font-size: 0.875rem;
+ margin-bottom: 0.375rem;
+ }
+
+ .jackpotValue {
+ font-size: 1.75rem;
+ /* Much smaller on mobile */
+ line-height: 1.2;
+ }
+}
+
+.infoSection,
+.vrfSection,
+.adminSection {
+ margin-bottom: 1.5rem;
+ padding: 1rem;
+ background-color: rgba(0, 0, 0, 0.2);
+ border-radius: var(--radius-md);
+}
+
+/* Mobile adjustments for info sections */
+@media (max-width: 640px) {
+
+ .infoSection,
+ .vrfSection,
+ .adminSection {
+ margin-bottom: 1rem;
+ padding: 0.75rem;
+ }
+}
+
+.sectionTitle {
+ font-size: 0.875rem;
+ font-weight: 600;
+ color: var(--color-text-muted);
+ margin-bottom: 0.75rem;
+ border-bottom: 1px solid var(--color-border);
+ padding-bottom: 0.5rem;
+ display: inline-flex;
+ align-items: center;
+ gap: 0.5rem;
+ width: 100%;
+}
+
+.infoRow {
+ display: flex;
+ justify-content: space-between;
+ margin-bottom: 0.5rem;
+ font-size: 0.875rem;
+}
+
+/* Mobile adjustments for info rows */
+@media (max-width: 640px) {
+ .infoRow {
+ flex-direction: column;
+ gap: 0.25rem;
+ align-items: flex-start;
+ }
+
+ .infoRow .value {
+ font-size: 0.8125rem;
+ word-break: break-all;
+ max-width: 100%;
+ }
+}
+
+.infoRow:last-child {
+ margin-bottom: 0;
+}
+
+.label {
+ color: var(--color-text-muted);
+ display: inline-flex;
+ align-items: center;
+ gap: 0.25rem;
+}
+
+.value {
+ font-family: monospace;
+ color: var(--color-text);
+}
+
+.adminSection {
+ border: 1px dashed var(--color-border);
+ background-color: transparent;
+}
+
+.toggleEducation {
+ display: block;
+ width: 100%;
+ margin-top: 1.5rem;
+ padding: 0.5rem;
+ background: transparent;
+ border: 1px dashed var(--color-border);
+ border-radius: var(--radius-md);
+ color: var(--color-text-muted);
+ font-size: 0.8125rem;
+ cursor: pointer;
+ transition: all 0.2s ease;
+ min-height: 44px;
+ /* Touch target */
+}
+
+/* Mobile adjustments for toggle education */
+@media (max-width: 640px) {
+ .toggleEducation {
+ margin-top: 1rem;
+ padding: 0.75rem;
+ min-height: 48px;
+ /* Larger touch target */
+ font-size: 0.875rem;
+ }
+}
+
+.toggleEducation:hover {
+ border-color: var(--color-primary);
+ color: var(--color-primary);
+}
\ No newline at end of file
diff --git a/frontend/src/components/Lotterie/LotterieCard.tsx b/frontend/src/components/Lotterie/LotterieCard.tsx
new file mode 100644
index 0000000..7d23f0a
--- /dev/null
+++ b/frontend/src/components/Lotterie/LotterieCard.tsx
@@ -0,0 +1,275 @@
+import { formatEther } from "ethers";
+import React, { useEffect, useState } from "react";
+import { useLotterie } from "../../hooks/useLotterie";
+import { Alert } from "../ui/Alert";
+import { Badge } from "../ui/Badge";
+import { Button } from "../ui/Button";
+import { Card } from "../ui/Card";
+import { FeatureItem, HighlightBox, InfoCard } from "../ui/InfoCard";
+import { InfoIcon, Tooltip } from "../ui/Tooltip";
+import styles from "./LotterieCard.module.css";
+
+export const LotterieCard: React.FC = () => {
+ const {
+ loading,
+ error,
+ isConnected,
+ address,
+ claim,
+ getGains,
+ getLastRequestId,
+ getResults,
+ getVrfSubscriptionId,
+ getVrfCoordinator,
+ getKeyHash,
+ } = useLotterie();
+
+ const [gains, setGains] = useState("0");
+ const [lastRequestId, setLastRequestId] = useState("0");
+ const [lastWinner, setLastWinner] = useState("None");
+ const [vrfInfo, setVrfInfo] = useState({
+ subId: "0",
+ coordinator: "",
+ keyHash: "",
+ });
+ const [successMsg, setSuccessMsg] = useState(null);
+ const [showEducation, setShowEducation] = useState(true);
+
+ const fetchData = async () => {
+ try {
+ if (address) {
+ const userGains = await getGains(address);
+ setGains(formatEther(userGains));
+ }
+
+ const reqId = await getLastRequestId();
+ setLastRequestId(reqId.toString());
+
+ if (reqId > 0n) {
+ const winner = await getResults(reqId);
+ setLastWinner(
+ winner === "0x0000000000000000000000000000000000000000"
+ ? "Pending..."
+ : winner
+ );
+ }
+
+ const subId = await getVrfSubscriptionId();
+ const coord = await getVrfCoordinator();
+ const hash = await getKeyHash();
+
+ setVrfInfo({
+ subId: subId.toString(),
+ coordinator: coord,
+ keyHash: hash,
+ });
+ } catch (err) {
+ console.error("Error fetching lottery data:", err);
+ }
+ };
+
+ useEffect(() => {
+ if (isConnected && address) {
+ fetchData();
+ }
+ // eslint-disable-next-line react-hooks/exhaustive-deps
+ }, [isConnected, address]);
+
+ const handleClaim = async () => {
+ try {
+ setSuccessMsg(null);
+ await claim();
+ setSuccessMsg(`Successfully claimed ${gains} GLD!`);
+ fetchData();
+ } catch (err) {
+ console.error(err);
+ }
+ };
+
+ return (
+
+
+ 🎰 Golden Lottery
+
+ Daily lottery powered by Chainlink VRF
+
+ Winners are selected using verifiable random numbers, ensuring
+ complete fairness and transparency.
+
+ }
+ size="md"
+ />
+
+ }
+ subtitle="Win rewards from transaction fees"
+ action={
+
+ Chainlink VRF (Verifiable Random Function)
+
+ Provides cryptographically secure randomness that can be
+ verified on-chain.
+
+ }
+ >
+ 🔗 VRF Secured
+
+ }
+ />
+
+ {/* Educational Section */}
+ {showEducation && (
+
+
+ The Golden Lottery is funded by 2.5% of all mint and burn fees.
+ Every day, one lucky GLD holder wins the accumulated prize pool!
+
+
+ 📋 Eligibility Requirements:
+ • Hold at least 1 GLD in your wallet
+
+ • Your address is automatically entered when eligible
+ • No additional action needed to participate!
+
+
+
+
+ )}
+
+ {/* Jackpot Section */}
+
+
+ Your Pending Rewards
+
+
+
+ {parseFloat(gains).toFixed(4)} GLD
+
+
+ 🎁 Claim Rewards
+
+
+
+ {error && (
+ {}}>
+ {error}
+
+ )}
+
+ {successMsg && (
+ setSuccessMsg(null)}
+ >
+ {successMsg}
+
+ )}
+
+ {/* Last Draw Info */}
+
+
+ 📊 Last Draw Info
+
+
+
+ Request ID:
+
+ {lastRequestId}
+
+
+
+ Winner:
+
+ {lastWinner !== "None" && lastWinner !== "Pending..."
+ ? `${lastWinner.substring(0, 6)}...${lastWinner.substring(38)}`
+ : lastWinner}
+
+
+
+
+ {/* VRF Configuration */}
+
+
+ 🔐 VRF Configuration
+
+ Chainlink VRF ensures fair and verifiable
+ randomness.
+
+
+ These parameters configure how random numbers are requested
+ and verified on-chain.
+
+ }
+ size="sm"
+ />
+
+
+
+ Subscription ID:
+
+
+ {vrfInfo.subId}
+
+
+
+ Coordinator:
+
+
+
+
+ {vrfInfo.coordinator.substring(0, 10)}...
+
+
+
+
+
+ {/* Toggle Education */}
+ setShowEducation(!showEducation)}
+ >
+ {showEducation ? "Hide" : "Show"} explanations
+
+
+
+ );
+};
diff --git a/frontend/src/components/NetworkSwitcher.module.css b/frontend/src/components/NetworkSwitcher.module.css
new file mode 100644
index 0000000..2d83aed
--- /dev/null
+++ b/frontend/src/components/NetworkSwitcher.module.css
@@ -0,0 +1,103 @@
+.container {
+ position: relative;
+ display: inline-block;
+}
+
+.button {
+ display: flex;
+ align-items: center;
+ gap: 8px;
+ background-color: rgba(255, 255, 255, 0.05);
+ border: 1px solid rgba(255, 215, 0, 0.2);
+ border-radius: 20px;
+ padding: 8px 16px;
+ color: #e5e7eb;
+ font-size: 14px;
+ font-weight: 500;
+ cursor: pointer;
+ transition: all 0.2s ease;
+ min-height: 44px;
+ /* Touch target size */
+}
+
+/* Mobile adjustments for NetworkSwitcher */
+@media (max-width: 640px) {
+ .button {
+ padding: 10px 16px;
+ /* Slightly larger touch target */
+ font-size: 14px;
+ }
+
+ .dropdown {
+ right: auto;
+ left: 0;
+ /* Align dropdown to left on mobile */
+ min-width: 200px;
+ /* Slightly wider on mobile */
+ }
+}
+
+.button:hover {
+ background-color: rgba(255, 215, 0, 0.1);
+ border-color: rgba(255, 215, 0, 0.4);
+}
+
+.button:disabled {
+ opacity: 0.5;
+ cursor: not-allowed;
+}
+
+.networkIcon {
+ width: 8px;
+ height: 8px;
+ border-radius: 50%;
+}
+
+.dropdown {
+ position: absolute;
+ top: 100%;
+ right: 0;
+ margin-top: 8px;
+ background-color: #1f2937;
+ border: 1px solid rgba(255, 215, 0, 0.2);
+ border-radius: 12px;
+ padding: 4px;
+ min-width: 180px;
+ z-index: 50;
+ box-shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.1), 0 2px 4px -1px rgba(0, 0, 0, 0.06);
+}
+
+.menuItem {
+ display: flex;
+ align-items: center;
+ gap: 8px;
+ width: 100%;
+ padding: 8px 12px;
+ border: none;
+ background: none;
+ color: #e5e7eb;
+ font-size: 14px;
+ text-align: left;
+ cursor: pointer;
+ border-radius: 8px;
+ transition: background-color 0.2s;
+}
+
+.menuItem:hover {
+ background-color: rgba(255, 215, 0, 0.1);
+}
+
+.menuItem.active {
+ background-color: rgba(255, 215, 0, 0.15);
+ color: #ffd700;
+}
+
+.unsupported {
+ border-color: #ef4444;
+ color: #ef4444;
+}
+
+.unsupported:hover {
+ background-color: rgba(239, 68, 68, 0.1);
+ border-color: #ef4444;
+}
\ No newline at end of file
diff --git a/frontend/src/components/NetworkSwitcher.tsx b/frontend/src/components/NetworkSwitcher.tsx
new file mode 100644
index 0000000..a5a52ea
--- /dev/null
+++ b/frontend/src/components/NetworkSwitcher.tsx
@@ -0,0 +1,116 @@
+import React, { useEffect, useRef, useState } from "react";
+import { NETWORKS, SUPPORTED_CHAIN_IDS } from "../config/networks";
+import { useNetwork } from "../hooks/useNetwork";
+import styles from "./NetworkSwitcher.module.css";
+
+export const NetworkSwitcher: React.FC = () => {
+ const { chainId, switchNetwork, isSupportedNetwork } = useNetwork();
+ const [isOpen, setIsOpen] = useState(false);
+ const [isSwitching, setIsSwitching] = useState(false);
+ const dropdownRef = useRef(null);
+
+ const currentNetwork = chainId ? NETWORKS[chainId as number] : undefined;
+ const isSupported = isSupportedNetwork();
+
+ useEffect(() => {
+ const handleClickOutside = (event: MouseEvent) => {
+ if (
+ dropdownRef.current &&
+ !dropdownRef.current.contains(event.target as Node)
+ ) {
+ setIsOpen(false);
+ }
+ };
+
+ document.addEventListener("mousedown", handleClickOutside);
+ return () => document.removeEventListener("mousedown", handleClickOutside);
+ }, []);
+
+ const handleSwitch = async (targetChainId: number) => {
+ if (targetChainId === chainId) {
+ setIsOpen(false);
+ return;
+ }
+
+ setIsSwitching(true);
+ try {
+ // Find the network object from supported networks
+ // We need to pass the network object expected by AppKit, but here we are using the ID
+ // The hook's switchNetwork expects a network object.
+ // Let's import the network objects from AppKit networks to be safe
+ const { sepolia, bscTestnet } = await import("@reown/appkit/networks");
+ const targetNetwork = targetChainId === sepolia.id ? sepolia : bscTestnet;
+
+ await switchNetwork(targetNetwork);
+ setIsOpen(false);
+ } catch (error) {
+ console.error("Failed to switch network:", error);
+ } finally {
+ setIsSwitching(false);
+ }
+ };
+
+ return (
+
+
setIsOpen(!isOpen)}
+ disabled={isSwitching}
+ >
+ {isSwitching ? (
+ Switching...
+ ) : (
+ <>
+
+ {currentNetwork?.name || "Unsupported Network"}
+
+
+
+ >
+ )}
+
+
+ {isOpen && (
+
+ {SUPPORTED_CHAIN_IDS.map((id) => {
+ const network = NETWORKS[id];
+ return (
+ handleSwitch(id)}
+ >
+
+ {network.name}
+
+ );
+ })}
+
+ )}
+
+ );
+};
diff --git a/frontend/src/components/TokenBridge/TokenBridgeCard.module.css b/frontend/src/components/TokenBridge/TokenBridgeCard.module.css
new file mode 100644
index 0000000..e5e53db
--- /dev/null
+++ b/frontend/src/components/TokenBridge/TokenBridgeCard.module.css
@@ -0,0 +1,256 @@
+.card {
+ height: 100%;
+}
+
+.headerTitle {
+ display: inline-flex;
+ align-items: center;
+ gap: 0.5rem;
+}
+
+.networkFlow {
+ display: flex;
+ align-items: center;
+ justify-content: space-between;
+ margin-bottom: 1.5rem;
+ padding: 1.25rem;
+ background: linear-gradient(135deg, rgba(59, 130, 246, 0.1) 0%, rgba(139, 92, 246, 0.1) 100%);
+ border: 1px solid rgba(59, 130, 246, 0.2);
+ border-radius: var(--radius-md);
+}
+
+/* Mobile adjustments for network flow */
+@media (max-width: 640px) {
+ .networkFlow {
+ flex-direction: column;
+ gap: 1rem;
+ text-align: center;
+ }
+
+ .networkNode {
+ min-width: auto;
+ width: 100%;
+ }
+
+ .arrow {
+ transform: rotate(90deg);
+ }
+}
+
+.networkNode {
+ display: flex;
+ flex-direction: column;
+ align-items: center;
+ min-width: 120px;
+}
+
+.networkLabel {
+ font-size: 0.75rem;
+ color: var(--color-text-muted);
+ margin-bottom: 0.25rem;
+ text-transform: uppercase;
+ letter-spacing: 0.05em;
+}
+
+.networkValue {
+ font-weight: 600;
+ color: var(--color-text);
+ display: flex;
+ align-items: center;
+ gap: 0.5rem;
+}
+
+.arrow {
+ display: flex;
+ flex-direction: column;
+ align-items: center;
+ gap: 0.25rem;
+ color: var(--color-primary);
+}
+
+.arrowIcon {
+ font-size: 1.5rem;
+ animation: pulse 2s infinite;
+}
+
+.arrowLabel {
+ font-size: 0.625rem;
+ text-transform: uppercase;
+ letter-spacing: 0.1em;
+ color: var(--color-text-muted);
+}
+
+@keyframes pulse {
+
+ 0%,
+ 100% {
+ opacity: 1;
+ }
+
+ 50% {
+ opacity: 0.5;
+ }
+}
+
+.liquidityInfo {
+ display: flex;
+ justify-content: space-between;
+ align-items: center;
+ margin-bottom: 1.5rem;
+ padding: 0.75rem 1rem;
+ background-color: rgba(59, 130, 246, 0.1);
+ border: 1px solid rgba(59, 130, 246, 0.2);
+ border-radius: var(--radius-md);
+}
+
+/* Mobile adjustments for liquidity info */
+@media (max-width: 640px) {
+ .liquidityInfo {
+ flex-direction: column;
+ gap: 0.5rem;
+ text-align: center;
+ padding: 0.625rem 0.75rem;
+ margin-bottom: 1rem;
+ }
+
+ .liquidityLabel {
+ font-size: 0.8125rem;
+ }
+
+ .liquidityValue {
+ font-size: 0.9rem;
+ }
+}
+
+.liquidityLabel {
+ font-size: 0.875rem;
+ color: #93C5FD;
+ display: inline-flex;
+ align-items: center;
+ gap: 0.25rem;
+}
+
+.liquidityValue {
+ font-weight: 700;
+ color: #93C5FD;
+}
+
+.inputLabel {
+ display: inline-flex;
+ align-items: center;
+ gap: 0.25rem;
+}
+
+.feeSelection {
+ margin-bottom: 1rem;
+ padding: 1rem;
+ background-color: rgba(0, 0, 0, 0.2);
+ border-radius: var(--radius-md);
+}
+
+/* Mobile adjustments for fee selection */
+@media (max-width: 640px) {
+ .feeSelection {
+ margin-bottom: 0.75rem;
+ padding: 0.75rem;
+ }
+
+ .feeLabel {
+ font-size: 0.8125rem;
+ margin-bottom: 0.625rem;
+ }
+}
+
+.feeLabel {
+ display: flex;
+ align-items: center;
+ gap: 0.25rem;
+ font-size: 0.875rem;
+ font-weight: 500;
+ color: var(--color-text);
+ margin-bottom: 0.75rem;
+}
+
+.radioGroup {
+ display: flex;
+ gap: 1.5rem;
+}
+
+/* Mobile adjustments for radio group */
+@media (max-width: 640px) {
+ .radioGroup {
+ flex-direction: column;
+ gap: 0.75rem;
+ }
+}
+
+.radioLabel {
+ display: flex;
+ align-items: center;
+ gap: 0.5rem;
+ cursor: pointer;
+ font-size: 0.875rem;
+ padding: 0.5rem 0.75rem;
+ border-radius: var(--radius-md);
+ transition: background-color 0.2s ease;
+ min-height: 44px;
+ /* Touch target size */
+}
+
+/* Mobile adjustments for radio labels */
+@media (max-width: 640px) {
+ .radioLabel {
+ padding: 0.75rem;
+ font-size: 0.9rem;
+ }
+}
+
+.radioLabel:hover {
+ background-color: rgba(255, 255, 255, 0.05);
+}
+
+.radioLabel input[type="radio"] {
+ accent-color: var(--color-primary);
+}
+
+.radioText {
+ display: flex;
+ align-items: center;
+ gap: 0.25rem;
+}
+
+.infoNote {
+ margin-top: 1.5rem;
+}
+
+.toggleEducation {
+ display: block;
+ width: 100%;
+ margin-top: 1.5rem;
+ padding: 0.5rem;
+ background: transparent;
+ border: 1px dashed var(--color-border);
+ border-radius: var(--radius-md);
+ color: var(--color-text-muted);
+ font-size: 0.8125rem;
+ cursor: pointer;
+ transition: all 0.2s ease;
+ min-height: 44px;
+ /* Touch target */
+}
+
+/* Mobile adjustments for toggle education */
+@media (max-width: 640px) {
+ .toggleEducation {
+ margin-top: 1rem;
+ padding: 0.75rem;
+ min-height: 48px;
+ /* Larger touch target */
+ font-size: 0.875rem;
+ }
+}
+
+.toggleEducation:hover {
+ border-color: var(--color-primary);
+ color: var(--color-primary);
+}
\ No newline at end of file
diff --git a/frontend/src/components/TokenBridge/TokenBridgeCard.tsx b/frontend/src/components/TokenBridge/TokenBridgeCard.tsx
new file mode 100644
index 0000000..e2c24e9
--- /dev/null
+++ b/frontend/src/components/TokenBridge/TokenBridgeCard.tsx
@@ -0,0 +1,350 @@
+import { formatEther, parseEther } from "ethers";
+import React, { useEffect, useState } from "react";
+import { NETWORKS } from "../../config/networks";
+import { useNetwork } from "../../hooks/useNetwork";
+import { useTokenBridge } from "../../hooks/useTokenBridge";
+import { PayFeesIn } from "../../types/tokenBridge";
+import { Alert } from "../ui/Alert";
+import { Badge } from "../ui/Badge";
+import { Button } from "../ui/Button";
+import { Card } from "../ui/Card";
+import { FeatureItem, HighlightBox, InfoCard } from "../ui/InfoCard";
+import { Input } from "../ui/Input";
+import { InfoIcon, Tooltip } from "../ui/Tooltip";
+import styles from "./TokenBridgeCard.module.css";
+
+export const TokenBridgeCard: React.FC = () => {
+ const {
+ loading,
+ error,
+ isConnected,
+ address,
+ bridgeTokens,
+ getDestinationChainSelector,
+ getGoldTokenBalance,
+ paused,
+ } = useTokenBridge();
+
+ const { chainId } = useNetwork();
+
+ const [bridgeBalance, setBridgeBalance] = useState("0");
+ const [destChainSelector, setDestChainSelector] = useState("0");
+ const [isPaused, setIsPaused] = useState(false);
+ const [receiver, setReceiver] = useState("");
+ const [amount, setAmount] = useState("");
+ const [payFeesIn, setPayFeesIn] = useState(PayFeesIn.Native);
+ const [successMsg, setSuccessMsg] = useState(null);
+ const [showEducation, setShowEducation] = useState(true);
+
+ const fetchData = async () => {
+ try {
+ const [bal, selector, pausedState] = await Promise.allSettled([
+ getGoldTokenBalance(),
+ getDestinationChainSelector(),
+ paused(),
+ ]);
+
+ if (bal.status === "fulfilled") {
+ setBridgeBalance(formatEther(bal.value));
+ }
+
+ if (selector.status === "fulfilled") {
+ setDestChainSelector(selector.value.toString());
+ }
+
+ if (pausedState.status === "fulfilled") {
+ setIsPaused(pausedState.value);
+ }
+
+ const rejected = [bal, selector, pausedState].filter(
+ (r) => r.status === "rejected"
+ );
+ if (rejected.length > 0) {
+ console.warn(
+ "Some bridge data fetches failed:",
+ rejected.map((r) => (r as PromiseRejectedResult).reason)
+ );
+ }
+ } catch (err) {
+ console.error("Error fetching bridge data:", err);
+ }
+ };
+
+ useEffect(() => {
+ if (isConnected && address) {
+ setReceiver(address);
+ fetchData();
+ }
+ // eslint-disable-next-line react-hooks/exhaustive-deps
+ }, [isConnected, address]);
+
+ const handleBridge = async () => {
+ try {
+ setSuccessMsg(null);
+ if (!receiver || !amount) return;
+
+ await bridgeTokens(receiver, parseEther(amount), payFeesIn);
+
+ setSuccessMsg(`Successfully initiated bridge transfer of ${amount} GLD!`);
+ setAmount("");
+ fetchData();
+ } catch (err) {
+ console.error(err);
+ }
+ };
+
+ const getDestNetworkName = (selector: string) => {
+ if (selector === "16015286601757825753") return "Sepolia Testnet";
+ if (selector === "13264668187771770619") return "BSC Testnet";
+ return "Unknown Chain";
+ };
+
+ const getDestNetworkIcon = (selector: string) => {
+ if (selector === "16015286601757825753") return "🔷"; // Ethereum
+ if (selector === "13264668187771770619") return "🟡"; // BSC
+ return "❓";
+ };
+
+ const currentNetwork = chainId ? NETWORKS[chainId as number] : undefined;
+ const currentNetworkIcon =
+ chainId === 11155111 ? "🔷" : chainId === 97 ? "🟡" : "❓";
+
+ return (
+
+
+ 🌉 Cross-Chain Bridge
+
+ Chainlink CCIP Bridge
+
+ Transfer GLD tokens securely between Ethereum and BSC using
+ Chainlink's Cross-Chain Interoperability Protocol.
+
+ }
+ size="md"
+ />
+
+ }
+ subtitle="Transfer GLD between networks"
+ action={
+
+
+ {isPaused ? "⏸️ Paused" : "✅ Active"}
+
+
+ }
+ />
+
+ {/* Educational Section */}
+ {showEducation && (
+
+
+ Cross-chain bridging allows you to transfer your GLD tokens
+ between different blockchain networks. This enables you to use
+ your tokens on whichever network offers the best opportunities.
+
+
+ 🔗 Powered by Chainlink CCIP
+
+ CCIP (Cross-Chain Interoperability Protocol) is Chainlink's secure
+ messaging protocol that enables safe token transfers across
+ blockchains.
+
+
+
+
+
+ )}
+
+ {/* Network Flow Visualization */}
+
+
+ From
+
+ {currentNetworkIcon} {currentNetwork?.name || "Unknown Network"}
+
+
+
+
+ →
+ CCIP
+
+
+
+ To
+
+ {getDestNetworkIcon(destChainSelector)}{" "}
+ {getDestNetworkName(destChainSelector)}
+
+
+
+
+ {/* Liquidity Info */}
+
+
+ Bridge Liquidity:
+
+
+
+ {parseFloat(bridgeBalance).toFixed(4)} GLD
+
+
+
+ {error && (
+ {}}>
+ {error}
+
+ )}
+
+ {successMsg && (
+ setSuccessMsg(null)}
+ >
+ {successMsg}
+
+ )}
+
+ {/* Bridge Form */}
+
+
+ Receiver Address
+
+
+ }
+ placeholder="0x..."
+ value={receiver}
+ onChange={(e) => setReceiver(e.target.value)}
+ />
+
+
+ Amount (GLD)
+
+
+ }
+ placeholder="0.0"
+ value={amount}
+ onChange={(e) => setAmount(e.target.value)}
+ type="number"
+ min="0"
+ step="0.0001"
+ rightElement="GLD"
+ />
+
+
+
+
+ 🌉 Bridge Tokens
+
+
+
+ {/* Info Note */}
+
+
+ ⏱️ Transfer Time: Bridge transfers typically take
+ 15-30 minutes to complete via Chainlink CCIP. You can track your
+ transfer on the destination chain's block explorer.
+
+
+
+ {/* Toggle Education */}
+ setShowEducation(!showEducation)}
+ >
+ {showEducation ? "Hide" : "Show"} explanations
+
+
+
+ );
+};
diff --git a/frontend/src/components/WalletConnect.tsx b/frontend/src/components/WalletConnect.tsx
new file mode 100644
index 0000000..0edfc90
--- /dev/null
+++ b/frontend/src/components/WalletConnect.tsx
@@ -0,0 +1,22 @@
+import { useAppKitAccount } from "@reown/appkit/react";
+
+export function WalletConnect() {
+ const { isConnected } = useAppKitAccount();
+
+ return (
+
+
+ {isConnected}
+ {/* Reown's built-in button handles connection, network switching, and account view */}
+
+
+
+ );
+}
diff --git a/frontend/src/components/Web3Provider.tsx b/frontend/src/components/Web3Provider.tsx
new file mode 100644
index 0000000..9ddcef7
--- /dev/null
+++ b/frontend/src/components/Web3Provider.tsx
@@ -0,0 +1,11 @@
+import { ReactNode } from "react";
+// Importing the config initializes the AppKit
+import "../config/reown";
+
+interface Props {
+ children: ReactNode;
+}
+
+export function Web3Provider({ children }: Props) {
+ return <>{children}>;
+}
diff --git a/frontend/src/components/ui/Alert.module.css b/frontend/src/components/ui/Alert.module.css
new file mode 100644
index 0000000..b05d706
--- /dev/null
+++ b/frontend/src/components/ui/Alert.module.css
@@ -0,0 +1,64 @@
+.alert {
+ padding: 1rem;
+ border-radius: var(--radius-md);
+ border: 1px solid transparent;
+ display: flex;
+ justify-content: space-between;
+ align-items: flex-start;
+ margin-bottom: 1rem;
+}
+
+.content {
+ flex: 1;
+}
+
+.title {
+ font-weight: 600;
+ margin-bottom: 0.25rem;
+ font-size: 1rem;
+}
+
+.message {
+ font-size: 0.875rem;
+ line-height: 1.5;
+}
+
+.closeButton {
+ background: transparent;
+ border: none;
+ font-size: 1.5rem;
+ line-height: 1;
+ cursor: pointer;
+ padding: 0;
+ margin-left: 1rem;
+ opacity: 0.7;
+}
+
+.closeButton:hover {
+ opacity: 1;
+}
+
+/* Variants */
+.info {
+ background-color: rgba(59, 130, 246, 0.1);
+ border-color: rgba(59, 130, 246, 0.2);
+ color: #93C5FD;
+}
+
+.success {
+ background-color: rgba(16, 185, 129, 0.1);
+ border-color: rgba(16, 185, 129, 0.2);
+ color: #6EE7B7;
+}
+
+.warning {
+ background-color: rgba(245, 158, 11, 0.1);
+ border-color: rgba(245, 158, 11, 0.2);
+ color: #FCD34D;
+}
+
+.error {
+ background-color: rgba(239, 68, 68, 0.1);
+ border-color: rgba(239, 68, 68, 0.2);
+ color: #FCA5A5;
+}
\ No newline at end of file
diff --git a/frontend/src/components/ui/Alert.tsx b/frontend/src/components/ui/Alert.tsx
new file mode 100644
index 0000000..05d0231
--- /dev/null
+++ b/frontend/src/components/ui/Alert.tsx
@@ -0,0 +1,39 @@
+import React from "react";
+import styles from "./Alert.module.css";
+
+interface AlertProps {
+ type?: "success" | "error" | "warning" | "info";
+ title?: string;
+ children: React.ReactNode;
+ className?: string;
+ onClose?: () => void;
+}
+
+export const Alert: React.FC = ({
+ type = "info",
+ title,
+ children,
+ className = "",
+ onClose,
+}) => {
+ return (
+
+
+ {title &&
{title} }
+
{children}
+
+ {onClose && (
+
+ ×
+
+ )}
+
+ );
+};
diff --git a/frontend/src/components/ui/Badge.module.css b/frontend/src/components/ui/Badge.module.css
new file mode 100644
index 0000000..3f71f0e
--- /dev/null
+++ b/frontend/src/components/ui/Badge.module.css
@@ -0,0 +1,47 @@
+.badge {
+ display: inline-flex;
+ align-items: center;
+ padding: 0.125rem 0.5rem;
+ border-radius: 9999px;
+ font-size: 0.75rem;
+ font-weight: 600;
+ line-height: 1.25;
+ white-space: nowrap;
+}
+
+/* Variants */
+.primary {
+ background-color: rgba(255, 215, 0, 0.1);
+ color: var(--color-primary);
+ border: 1px solid rgba(255, 215, 0, 0.2);
+}
+
+.secondary {
+ background-color: var(--color-surface);
+ color: var(--color-text-muted);
+ border: 1px solid var(--color-border);
+}
+
+.success {
+ background-color: rgba(16, 185, 129, 0.1);
+ color: #6EE7B7;
+ border: 1px solid rgba(16, 185, 129, 0.2);
+}
+
+.error {
+ background-color: rgba(239, 68, 68, 0.1);
+ color: #FCA5A5;
+ border: 1px solid rgba(239, 68, 68, 0.2);
+}
+
+.warning {
+ background-color: rgba(245, 158, 11, 0.1);
+ color: #FCD34D;
+ border: 1px solid rgba(245, 158, 11, 0.2);
+}
+
+.info {
+ background-color: rgba(59, 130, 246, 0.1);
+ color: #93C5FD;
+ border: 1px solid rgba(59, 130, 246, 0.2);
+}
\ No newline at end of file
diff --git a/frontend/src/components/ui/Badge.tsx b/frontend/src/components/ui/Badge.tsx
new file mode 100644
index 0000000..7e72045
--- /dev/null
+++ b/frontend/src/components/ui/Badge.tsx
@@ -0,0 +1,20 @@
+import React from "react";
+import styles from "./Badge.module.css";
+
+interface BadgeProps {
+ children: React.ReactNode;
+ variant?: "primary" | "secondary" | "success" | "error" | "warning" | "info";
+ className?: string;
+}
+
+export const Badge: React.FC = ({
+ children,
+ variant = "primary",
+ className = "",
+}) => {
+ return (
+
+ {children}
+
+ );
+};
diff --git a/frontend/src/components/ui/Button.module.css b/frontend/src/components/ui/Button.module.css
new file mode 100644
index 0000000..310c05a
--- /dev/null
+++ b/frontend/src/components/ui/Button.module.css
@@ -0,0 +1,104 @@
+.button {
+ display: inline-flex;
+ align-items: center;
+ justify-content: center;
+ border-radius: var(--radius-md);
+ font-weight: 500;
+ transition: all 0.2s ease;
+ position: relative;
+ border: 1px solid transparent;
+}
+
+.button:disabled {
+ opacity: 0.6;
+ cursor: not-allowed;
+}
+
+/* Variants */
+.primary {
+ background-color: var(--color-primary);
+ color: var(--color-background);
+}
+
+.primary:hover:not(:disabled) {
+ background-color: var(--color-primary-hover);
+}
+
+.secondary {
+ background-color: var(--color-surface);
+ color: var(--color-text);
+ border-color: var(--color-border);
+}
+
+.secondary:hover:not(:disabled) {
+ background-color: var(--color-border);
+}
+
+.danger {
+ background-color: var(--color-error);
+ color: white;
+}
+
+.danger:hover:not(:disabled) {
+ filter: brightness(0.9);
+}
+
+.outline {
+ background-color: transparent;
+ border-color: var(--color-primary);
+ color: var(--color-primary);
+}
+
+.outline:hover:not(:disabled) {
+ background-color: rgba(255, 215, 0, 0.1);
+}
+
+/* Sizes */
+.sm {
+ padding: 0.25rem 0.75rem;
+ font-size: 0.875rem;
+ height: 2rem;
+}
+
+.md {
+ padding: 0.5rem 1rem;
+ font-size: 1rem;
+ height: 2.5rem;
+}
+
+.lg {
+ padding: 0.75rem 1.5rem;
+ font-size: 1.125rem;
+ height: 3rem;
+}
+
+/* Mobile touch target adjustments */
+@media (max-width: 640px) {
+ .md {
+ height: 2.75rem;
+ /* Larger touch target */
+ padding: 0.625rem 1.25rem;
+ }
+
+ .lg {
+ height: 3.25rem;
+ /* Larger touch target */
+ padding: 0.875rem 1.75rem;
+ }
+}
+
+.fullWidth {
+ width: 100%;
+}
+
+.spinnerWrapper {
+ position: absolute;
+ left: 50%;
+ top: 50%;
+ transform: translate(-50%, -50%);
+ display: flex;
+}
+
+.invisible {
+ visibility: hidden;
+}
\ No newline at end of file
diff --git a/frontend/src/components/ui/Button.tsx b/frontend/src/components/ui/Button.tsx
new file mode 100644
index 0000000..6b6adb0
--- /dev/null
+++ b/frontend/src/components/ui/Button.tsx
@@ -0,0 +1,45 @@
+import React from "react";
+import styles from "./Button.module.css";
+import { Spinner } from "./Spinner";
+
+interface ButtonProps extends React.ButtonHTMLAttributes {
+ variant?: "primary" | "secondary" | "danger" | "outline";
+ size?: "sm" | "md" | "lg";
+ isLoading?: boolean;
+ fullWidth?: boolean;
+}
+
+export const Button: React.FC = ({
+ children,
+ variant = "primary",
+ size = "md",
+ isLoading = false,
+ fullWidth = false,
+ className = "",
+ disabled,
+ ...props
+}) => {
+ return (
+
+ {isLoading && (
+
+
+
+ )}
+ {children}
+
+ );
+};
diff --git a/frontend/src/components/ui/Card.module.css b/frontend/src/components/ui/Card.module.css
new file mode 100644
index 0000000..e220e9b
--- /dev/null
+++ b/frontend/src/components/ui/Card.module.css
@@ -0,0 +1,85 @@
+.card {
+ background-color: var(--color-surface);
+ border: 1px solid var(--color-border);
+ border-radius: var(--radius-lg);
+ box-shadow: var(--shadow-md);
+ overflow: hidden;
+ display: flex;
+ flex-direction: column;
+ height: 100%;
+}
+
+.header {
+ padding: 1.5rem;
+ border-bottom: 1px solid var(--color-border);
+ display: flex;
+ justify-content: space-between;
+ align-items: flex-start;
+}
+
+/* Mobile adjustments for card header */
+@media (max-width: 640px) {
+ .header {
+ padding: 1rem;
+ flex-direction: column;
+ gap: 0.75rem;
+ }
+
+ .action {
+ margin-left: 0;
+ align-self: stretch;
+ }
+}
+
+.titleContainer {
+ flex: 1;
+}
+
+.title {
+ font-size: 1.25rem;
+ font-weight: 600;
+ color: var(--color-primary);
+ margin: 0;
+}
+
+/* Mobile adjustments for title */
+@media (max-width: 640px) {
+ .title {
+ font-size: 1.125rem;
+ }
+}
+
+.subtitle {
+ font-size: 0.875rem;
+ color: var(--color-text-muted);
+ margin-top: 0.25rem;
+}
+
+.action {
+ margin-left: 1rem;
+}
+
+.body {
+ padding: 1.5rem;
+ flex: 1;
+}
+
+/* Mobile adjustments for card body */
+@media (max-width: 640px) {
+ .body {
+ padding: 1rem;
+ }
+}
+
+.footer {
+ padding: 1rem 1.5rem;
+ background-color: rgba(0, 0, 0, 0.2);
+ border-top: 1px solid var(--color-border);
+}
+
+/* Mobile adjustments for card footer */
+@media (max-width: 640px) {
+ .footer {
+ padding: 0.75rem 1rem;
+ }
+}
\ No newline at end of file
diff --git a/frontend/src/components/ui/Card.tsx b/frontend/src/components/ui/Card.tsx
new file mode 100644
index 0000000..6056c0e
--- /dev/null
+++ b/frontend/src/components/ui/Card.tsx
@@ -0,0 +1,45 @@
+import React from "react";
+import styles from "./Card.module.css";
+
+interface CardProps {
+ children: React.ReactNode;
+ className?: string;
+}
+
+interface CardHeaderProps {
+ title: React.ReactNode;
+ subtitle?: string;
+ action?: React.ReactNode;
+}
+
+export const Card: React.FC & {
+ Header: React.FC;
+ Body: React.FC<{ children: React.ReactNode }>;
+ Footer: React.FC<{ children: React.ReactNode }>;
+} = ({ children, className = "" }) => {
+ return {children}
;
+};
+
+const CardHeader: React.FC = ({ title, subtitle, action }) => {
+ return (
+
+
+
{title}
+ {subtitle &&
{subtitle}
}
+
+ {action &&
{action}
}
+
+ );
+};
+
+const CardBody: React.FC<{ children: React.ReactNode }> = ({ children }) => {
+ return {children}
;
+};
+
+const CardFooter: React.FC<{ children: React.ReactNode }> = ({ children }) => {
+ return {children}
;
+};
+
+Card.Header = CardHeader;
+Card.Body = CardBody;
+Card.Footer = CardFooter;
diff --git a/frontend/src/components/ui/InfoCard.module.css b/frontend/src/components/ui/InfoCard.module.css
new file mode 100644
index 0000000..455eca6
--- /dev/null
+++ b/frontend/src/components/ui/InfoCard.module.css
@@ -0,0 +1,163 @@
+.infoCard {
+ background-color: rgba(0, 0, 0, 0.2);
+ border: 1px solid var(--color-border);
+ border-radius: var(--radius-md);
+ overflow: hidden;
+ margin-bottom: 1rem;
+}
+
+.infoCard.highlight {
+ border-color: var(--color-primary);
+ background-color: rgba(255, 215, 0, 0.05);
+}
+
+.infoCard.warning {
+ border-color: var(--color-warning);
+ background-color: rgba(245, 158, 11, 0.05);
+}
+
+.infoCard.success {
+ border-color: var(--color-success);
+ background-color: rgba(16, 185, 129, 0.05);
+}
+
+.header {
+ display: flex;
+ justify-content: space-between;
+ align-items: center;
+ padding: 0.75rem 1rem;
+ background-color: rgba(0, 0, 0, 0.2);
+ border-bottom: 1px solid var(--color-border);
+}
+
+.header.clickable {
+ cursor: pointer;
+ transition: background-color 0.2s ease;
+}
+
+.header.clickable:hover {
+ background-color: rgba(0, 0, 0, 0.3);
+}
+
+.titleRow {
+ display: flex;
+ align-items: center;
+ gap: 0.5rem;
+}
+
+.icon {
+ font-size: 1.125rem;
+}
+
+.title {
+ font-size: 0.875rem;
+ font-weight: 600;
+ color: var(--color-text);
+ margin: 0;
+}
+
+.chevron {
+ font-size: 0.625rem;
+ color: var(--color-text-muted);
+ transition: transform 0.2s ease;
+}
+
+.chevron.expanded {
+ transform: rotate(180deg);
+}
+
+.content {
+ padding: 1rem;
+ font-size: 0.875rem;
+ color: var(--color-text-muted);
+ line-height: 1.6;
+}
+
+.content p {
+ margin: 0 0 0.75rem 0;
+}
+
+.content p:last-child {
+ margin-bottom: 0;
+}
+
+/* Feature Item */
+.featureItem {
+ display: flex;
+ align-items: flex-start;
+ gap: 0.75rem;
+ padding: 0.5rem 0;
+}
+
+.featureItem:first-child {
+ padding-top: 0;
+}
+
+.featureItem:last-child {
+ padding-bottom: 0;
+}
+
+.featureIcon {
+ color: var(--color-primary);
+ font-size: 1rem;
+ flex-shrink: 0;
+ margin-top: 0.125rem;
+}
+
+.featureContent {
+ display: flex;
+ flex-direction: column;
+ gap: 0.125rem;
+}
+
+.featureTitle {
+ font-weight: 600;
+ color: var(--color-text);
+ font-size: 0.875rem;
+}
+
+.featureDescription {
+ color: var(--color-text-muted);
+ font-size: 0.8125rem;
+}
+
+/* Highlight Box */
+.highlightBox {
+ padding: 0.75rem 1rem;
+ border-radius: var(--radius-md);
+ font-size: 0.875rem;
+ line-height: 1.5;
+ margin: 0.75rem 0;
+}
+
+.highlightBox:first-child {
+ margin-top: 0;
+}
+
+.highlightBox:last-child {
+ margin-bottom: 0;
+}
+
+.highlight-info {
+ background-color: rgba(59, 130, 246, 0.1);
+ border: 1px solid rgba(59, 130, 246, 0.3);
+ color: #93c5fd;
+}
+
+.highlight-warning {
+ background-color: rgba(245, 158, 11, 0.1);
+ border: 1px solid rgba(245, 158, 11, 0.3);
+ color: #fcd34d;
+}
+
+.highlight-success {
+ background-color: rgba(16, 185, 129, 0.1);
+ border: 1px solid rgba(16, 185, 129, 0.3);
+ color: #6ee7b7;
+}
+
+.highlight-gold {
+ background-color: rgba(255, 215, 0, 0.1);
+ border: 1px solid rgba(255, 215, 0, 0.3);
+ color: var(--color-primary);
+}
\ No newline at end of file
diff --git a/frontend/src/components/ui/InfoCard.tsx b/frontend/src/components/ui/InfoCard.tsx
new file mode 100644
index 0000000..7fc0444
--- /dev/null
+++ b/frontend/src/components/ui/InfoCard.tsx
@@ -0,0 +1,94 @@
+import React, { useState } from "react";
+import styles from "./InfoCard.module.css";
+
+interface InfoCardProps {
+ title: string;
+ icon?: string;
+ children: React.ReactNode;
+ variant?: "default" | "highlight" | "warning" | "success";
+ collapsible?: boolean;
+ defaultExpanded?: boolean;
+ className?: string;
+}
+
+export const InfoCard: React.FC = ({
+ title,
+ icon,
+ children,
+ variant = "default",
+ collapsible = false,
+ defaultExpanded = true,
+ className = "",
+}) => {
+ const [isExpanded, setIsExpanded] = useState(defaultExpanded);
+
+ return (
+
+
setIsExpanded(!isExpanded) : undefined}
+ >
+
+ {icon && {icon} }
+
{title}
+
+ {collapsible && (
+
+ ▼
+
+ )}
+
+ {(!collapsible || isExpanded) && (
+
{children}
+ )}
+
+ );
+};
+
+// Feature list item for use within InfoCard
+interface FeatureItemProps {
+ icon?: string;
+ title: string;
+ description: string;
+}
+
+export const FeatureItem: React.FC = ({
+ icon = "•",
+ title,
+ description,
+}) => {
+ return (
+
+
{icon}
+
+ {title}
+ {description}
+
+
+ );
+};
+
+// Highlight box for important information
+interface HighlightBoxProps {
+ children: React.ReactNode;
+ variant?: "info" | "warning" | "success" | "gold";
+ className?: string;
+}
+
+export const HighlightBox: React.FC = ({
+ children,
+ variant = "info",
+ className = "",
+}) => {
+ return (
+
+ {children}
+
+ );
+};
diff --git a/frontend/src/components/ui/Input.module.css b/frontend/src/components/ui/Input.module.css
new file mode 100644
index 0000000..0944638
--- /dev/null
+++ b/frontend/src/components/ui/Input.module.css
@@ -0,0 +1,88 @@
+.container {
+ display: flex;
+ flex-direction: column;
+ gap: 0.25rem;
+ width: 100%;
+}
+
+.label {
+ font-size: 0.875rem;
+ font-weight: 500;
+ color: var(--color-text);
+}
+
+.inputWrapper {
+ position: relative;
+ display: flex;
+ align-items: center;
+}
+
+.input {
+ width: 100%;
+ padding: 0.5rem 0.75rem;
+ font-size: 1rem;
+ line-height: 1.5;
+ color: var(--color-text);
+ background-color: var(--color-background);
+ border: 1px solid var(--color-border);
+ border-radius: var(--radius-md);
+ transition: border-color 0.2s ease, box-shadow 0.2s ease;
+ min-height: 44px;
+ /* Touch target size */
+}
+
+/* Mobile adjustments for input */
+@media (max-width: 640px) {
+ .input {
+ padding: 0.75rem;
+ font-size: 16px;
+ /* Prevent zoom on iOS */
+ min-height: 48px;
+ /* Larger touch target */
+ }
+}
+
+.input:focus {
+ outline: none;
+ border-color: var(--color-primary);
+ box-shadow: 0 0 0 2px rgba(255, 215, 0, 0.2);
+}
+
+.input:disabled {
+ background-color: var(--color-surface);
+ cursor: not-allowed;
+ opacity: 0.7;
+}
+
+.hasError {
+ border-color: var(--color-error);
+}
+
+.hasError:focus {
+ border-color: var(--color-error);
+ box-shadow: 0 0 0 2px rgba(239, 68, 68, 0.2);
+}
+
+.hasRightElement {
+ padding-right: 2.5rem;
+}
+
+.rightElement {
+ position: absolute;
+ right: 0.75rem;
+ display: flex;
+ align-items: center;
+ color: var(--color-text-muted);
+}
+
+.error {
+ font-size: 0.75rem;
+ color: var(--color-error);
+ margin-top: 0.25rem;
+}
+
+.helperText {
+ font-size: 0.75rem;
+ color: var(--color-text-muted);
+ margin-top: 0.25rem;
+}
\ No newline at end of file
diff --git a/frontend/src/components/ui/Input.tsx b/frontend/src/components/ui/Input.tsx
new file mode 100644
index 0000000..31a049b
--- /dev/null
+++ b/frontend/src/components/ui/Input.tsx
@@ -0,0 +1,50 @@
+import React from "react";
+import styles from "./Input.module.css";
+
+interface InputProps extends React.InputHTMLAttributes {
+ label?: React.ReactNode;
+ error?: string;
+ helperText?: string;
+ rightElement?: React.ReactNode;
+}
+
+export const Input: React.FC = ({
+ label,
+ error,
+ helperText,
+ rightElement,
+ className = "",
+ id,
+ ...props
+}) => {
+ const inputId = React.useMemo(
+ () => id || props.name || crypto.randomUUID(),
+ [id, props.name]
+ );
+
+ return (
+
+ {label && (
+
+ {label}
+
+ )}
+
+
+ {rightElement && (
+
{rightElement}
+ )}
+
+ {error &&
{error}
}
+ {helperText && !error && (
+
{helperText}
+ )}
+
+ );
+};
diff --git a/frontend/src/components/ui/Modal.module.css b/frontend/src/components/ui/Modal.module.css
new file mode 100644
index 0000000..1b1d1bc
--- /dev/null
+++ b/frontend/src/components/ui/Modal.module.css
@@ -0,0 +1,84 @@
+.overlay {
+ position: fixed;
+ top: 0;
+ left: 0;
+ right: 0;
+ bottom: 0;
+ background-color: rgba(0, 0, 0, 0.7);
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ z-index: 1000;
+ backdrop-filter: blur(4px);
+}
+
+.modal {
+ background-color: var(--color-surface);
+ border: 1px solid var(--color-border);
+ border-radius: var(--radius-lg);
+ box-shadow: var(--shadow-lg);
+ width: 100%;
+ max-width: 500px;
+ max-height: 90vh;
+ display: flex;
+ flex-direction: column;
+ margin: 1rem;
+ animation: slideIn 0.2s ease-out;
+}
+
+.header {
+ padding: 1.5rem;
+ border-bottom: 1px solid var(--color-border);
+ display: flex;
+ justify-content: space-between;
+ align-items: center;
+}
+
+.title {
+ font-size: 1.25rem;
+ font-weight: 600;
+ color: var(--color-text);
+ margin: 0;
+}
+
+.closeButton {
+ background: transparent;
+ border: none;
+ font-size: 1.5rem;
+ line-height: 1;
+ color: var(--color-text-muted);
+ cursor: pointer;
+ padding: 0.25rem;
+ border-radius: var(--radius-sm);
+ transition: color 0.2s;
+}
+
+.closeButton:hover {
+ color: var(--color-text);
+}
+
+.body {
+ padding: 1.5rem;
+ overflow-y: auto;
+}
+
+.footer {
+ padding: 1rem 1.5rem;
+ border-top: 1px solid var(--color-border);
+ background-color: rgba(0, 0, 0, 0.2);
+ display: flex;
+ justify-content: flex-end;
+ gap: 0.75rem;
+}
+
+@keyframes slideIn {
+ from {
+ opacity: 0;
+ transform: translateY(10px);
+ }
+
+ to {
+ opacity: 1;
+ transform: translateY(0);
+ }
+}
\ No newline at end of file
diff --git a/frontend/src/components/ui/Modal.tsx b/frontend/src/components/ui/Modal.tsx
new file mode 100644
index 0000000..fcd0eac
--- /dev/null
+++ b/frontend/src/components/ui/Modal.tsx
@@ -0,0 +1,48 @@
+import React, { useEffect } from "react";
+import { createPortal } from "react-dom";
+import styles from "./Modal.module.css";
+
+interface ModalProps {
+ isOpen: boolean;
+ onClose: () => void;
+ title: string;
+ children: React.ReactNode;
+ footer?: React.ReactNode;
+}
+
+export const Modal: React.FC = ({
+ isOpen,
+ onClose,
+ title,
+ children,
+ footer,
+}) => {
+ useEffect(() => {
+ if (isOpen) {
+ document.body.style.overflow = "hidden";
+ } else {
+ document.body.style.overflow = "unset";
+ }
+ return () => {
+ document.body.style.overflow = "unset";
+ };
+ }, [isOpen]);
+
+ if (!isOpen) return null;
+
+ return createPortal(
+
+
e.stopPropagation()}>
+
+
{title}
+
+ ×
+
+
+
{children}
+ {footer &&
{footer}
}
+
+
,
+ document.body
+ );
+};
diff --git a/frontend/src/components/ui/Spinner.module.css b/frontend/src/components/ui/Spinner.module.css
new file mode 100644
index 0000000..724a6c2
--- /dev/null
+++ b/frontend/src/components/ui/Spinner.module.css
@@ -0,0 +1,53 @@
+.spinner {
+ display: inline-block;
+ border-radius: 50%;
+ border-style: solid;
+ border-color: transparent;
+ animation: spin 0.75s linear infinite;
+}
+
+.sm {
+ width: 1rem;
+ height: 1rem;
+ border-width: 2px;
+}
+
+.md {
+ width: 1.5rem;
+ height: 1.5rem;
+ border-width: 3px;
+}
+
+.lg {
+ width: 2.5rem;
+ height: 2.5rem;
+ border-width: 4px;
+}
+
+.primary {
+ border-top-color: var(--color-primary);
+ border-right-color: var(--color-primary);
+}
+
+.white {
+ border-top-color: #ffffff;
+ border-right-color: #ffffff;
+}
+
+.srOnly {
+ position: absolute;
+ width: 1px;
+ height: 1px;
+ padding: 0;
+ margin: -1px;
+ overflow: hidden;
+ clip: rect(0, 0, 0, 0);
+ white-space: nowrap;
+ border-width: 0;
+}
+
+@keyframes spin {
+ to {
+ transform: rotate(360deg);
+ }
+}
\ No newline at end of file
diff --git a/frontend/src/components/ui/Spinner.tsx b/frontend/src/components/ui/Spinner.tsx
new file mode 100644
index 0000000..aa0426a
--- /dev/null
+++ b/frontend/src/components/ui/Spinner.tsx
@@ -0,0 +1,24 @@
+import React from "react";
+import styles from "./Spinner.module.css";
+
+interface SpinnerProps {
+ size?: "sm" | "md" | "lg";
+ color?: "primary" | "white";
+ className?: string;
+}
+
+export const Spinner: React.FC = ({
+ size = "md",
+ color = "primary",
+ className = "",
+}) => {
+ return (
+
+ Loading...
+
+ );
+};
diff --git a/frontend/src/components/ui/StepIndicator.module.css b/frontend/src/components/ui/StepIndicator.module.css
new file mode 100644
index 0000000..326c399
--- /dev/null
+++ b/frontend/src/components/ui/StepIndicator.module.css
@@ -0,0 +1,190 @@
+/* Full Step Indicator */
+.stepIndicator {
+ display: flex;
+ flex-direction: column;
+ gap: 0;
+}
+
+.step {
+ display: flex;
+ align-items: flex-start;
+ gap: 1rem;
+ padding: 1rem;
+ border-radius: var(--radius-md);
+ transition: background-color 0.2s ease;
+}
+
+.step.clickable {
+ cursor: pointer;
+}
+
+.step.clickable:hover {
+ background-color: rgba(255, 255, 255, 0.05);
+}
+
+.stepIcon {
+ width: 2.5rem;
+ height: 2.5rem;
+ border-radius: 50%;
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ font-size: 1.125rem;
+ flex-shrink: 0;
+ transition: all 0.2s ease;
+}
+
+.step.completed .stepIcon {
+ background-color: var(--color-success);
+ color: white;
+}
+
+.step.current .stepIcon {
+ background-color: var(--color-primary);
+ color: var(--color-background);
+ box-shadow: 0 0 0 4px rgba(255, 215, 0, 0.2);
+}
+
+.step.upcoming .stepIcon {
+ background-color: var(--color-border);
+ color: var(--color-text-muted);
+}
+
+.checkmark {
+ font-weight: bold;
+}
+
+.stepContent {
+ display: flex;
+ flex-direction: column;
+ gap: 0.25rem;
+ padding-top: 0.5rem;
+}
+
+.stepLabel {
+ font-weight: 600;
+ font-size: 1rem;
+ color: var(--color-text);
+}
+
+.step.upcoming .stepLabel {
+ color: var(--color-text-muted);
+}
+
+.stepDescription {
+ font-size: 0.875rem;
+ color: var(--color-text-muted);
+}
+
+.connector {
+ width: 2px;
+ height: 1.5rem;
+ background-color: var(--color-border);
+ margin-left: calc(1rem + 1.25rem - 1px);
+ transition: background-color 0.2s ease;
+}
+
+.connectorCompleted {
+ background-color: var(--color-success);
+}
+
+/* Compact Horizontal Indicator */
+.compactIndicator {
+ display: flex;
+ align-items: center;
+ gap: 0;
+ padding: 0.75rem 1rem;
+ background-color: rgba(0, 0, 0, 0.2);
+ border-radius: var(--radius-lg);
+ border: 1px solid var(--color-border);
+ overflow-x: auto;
+}
+
+.compactStep {
+ display: flex;
+ align-items: center;
+ gap: 0.5rem;
+ padding: 0.5rem 0.75rem;
+ border-radius: var(--radius-md);
+ white-space: nowrap;
+ transition: all 0.2s ease;
+}
+
+.compactIcon {
+ width: 1.5rem;
+ height: 1.5rem;
+ border-radius: 50%;
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ font-size: 0.75rem;
+ flex-shrink: 0;
+}
+
+.compactLabel {
+ font-size: 0.8125rem;
+ font-weight: 500;
+}
+
+/* Compact Status Styles */
+.compact-completed .compactIcon {
+ background-color: var(--color-success);
+ color: white;
+}
+
+.compact-completed .compactLabel {
+ color: var(--color-success);
+}
+
+.compact-current {
+ background-color: rgba(255, 215, 0, 0.1);
+}
+
+.compact-current .compactIcon {
+ background-color: var(--color-primary);
+ color: var(--color-background);
+}
+
+.compact-current .compactLabel {
+ color: var(--color-primary);
+ font-weight: 600;
+}
+
+.compact-upcoming .compactIcon {
+ background-color: var(--color-border);
+ color: var(--color-text-muted);
+}
+
+.compact-upcoming .compactLabel {
+ color: var(--color-text-muted);
+}
+
+.compactConnector {
+ width: 1.5rem;
+ height: 2px;
+ background-color: var(--color-border);
+ flex-shrink: 0;
+}
+
+.compactConnectorCompleted {
+ background-color: var(--color-success);
+}
+
+/* Responsive */
+@media (max-width: 768px) {
+ .compactIndicator {
+ padding: 0.5rem;
+ }
+
+ .compactStep {
+ padding: 0.375rem 0.5rem;
+ }
+
+ .compactLabel {
+ display: none;
+ }
+
+ .compactConnector {
+ width: 1rem;
+ }
+}
\ No newline at end of file
diff --git a/frontend/src/components/ui/StepIndicator.tsx b/frontend/src/components/ui/StepIndicator.tsx
new file mode 100644
index 0000000..a46dd07
--- /dev/null
+++ b/frontend/src/components/ui/StepIndicator.tsx
@@ -0,0 +1,132 @@
+import React from "react";
+import styles from "./StepIndicator.module.css";
+
+export interface Step {
+ id: string;
+ label: string;
+ icon: string;
+ description?: string;
+}
+
+interface StepIndicatorProps {
+ steps: Step[];
+ currentStep: string;
+ completedSteps: string[];
+ onStepClick?: (stepId: string) => void;
+ className?: string;
+}
+
+export const StepIndicator: React.FC = ({
+ steps,
+ currentStep,
+ completedSteps,
+ onStepClick,
+ className = "",
+}) => {
+ const getStepStatus = (
+ stepId: string
+ ): "completed" | "current" | "upcoming" => {
+ if (completedSteps.includes(stepId)) return "completed";
+ if (stepId === currentStep) return "current";
+ return "upcoming";
+ };
+
+ return (
+
+ {steps.map((step, index) => {
+ const status = getStepStatus(step.id);
+ const isClickable =
+ onStepClick && (status === "completed" || status === "current");
+
+ return (
+
+ onStepClick(step.id) : undefined}
+ >
+
+ {status === "completed" ? (
+ ✓
+ ) : (
+ {step.icon}
+ )}
+
+
+ {step.label}
+ {step.description && (
+
+ {step.description}
+
+ )}
+
+
+ {index < steps.length - 1 && (
+
+ )}
+
+ );
+ })}
+
+ );
+};
+
+// Compact horizontal version for header
+interface CompactStepIndicatorProps {
+ steps: Step[];
+ currentStep: string;
+ completedSteps: string[];
+ className?: string;
+}
+
+export const CompactStepIndicator: React.FC = ({
+ steps,
+ currentStep,
+ completedSteps,
+ className = "",
+}) => {
+ const getStepStatus = (
+ stepId: string
+ ): "completed" | "current" | "upcoming" => {
+ if (completedSteps.includes(stepId)) return "completed";
+ if (stepId === currentStep) return "current";
+ return "upcoming";
+ };
+
+ return (
+
+ {steps.map((step, index) => {
+ const status = getStepStatus(step.id);
+
+ return (
+
+
+
+ {status === "completed" ? "✓" : step.icon}
+
+ {step.label}
+
+ {index < steps.length - 1 && (
+
+ )}
+
+ );
+ })}
+
+ );
+};
diff --git a/frontend/src/components/ui/Tooltip.module.css b/frontend/src/components/ui/Tooltip.module.css
new file mode 100644
index 0000000..5ec2123
--- /dev/null
+++ b/frontend/src/components/ui/Tooltip.module.css
@@ -0,0 +1,142 @@
+.tooltipWrapper {
+ position: relative;
+ display: inline-flex;
+ align-items: center;
+}
+
+.tooltip {
+ position: absolute;
+ z-index: 1000;
+ pointer-events: none;
+ animation: fadeIn 0.15s ease-in-out;
+}
+
+@keyframes fadeIn {
+ from {
+ opacity: 0;
+ }
+
+ to {
+ opacity: 1;
+ }
+}
+
+.tooltipContent {
+ background-color: var(--color-secondary);
+ color: var(--color-text);
+ padding: 0.5rem 1rem;
+ border-radius: var(--radius-md);
+ font-size: 0.8125rem;
+ line-height: 1.3;
+ width: 280px;
+ /* Mobile-first: narrower width for vertical content display */
+ box-shadow: var(--shadow-lg);
+ border: 1px solid var(--color-border);
+ white-space: normal;
+}
+
+/* Tablet and larger screens: wider layout for horizontal content display */
+@media (min-width: 768px) {
+ .tooltipContent {
+ width: 400px;
+ }
+}
+
+.arrow {
+ position: absolute;
+ width: 8px;
+ height: 8px;
+ background-color: var(--color-secondary);
+ border: 1px solid var(--color-border);
+ transform: rotate(45deg);
+}
+
+/* Position: Top */
+.top {
+ bottom: 100%;
+ left: 50%;
+ transform: translateX(-50%);
+ margin-bottom: 8px;
+}
+
+.top .arrow {
+ bottom: -5px;
+ left: 50%;
+ transform: translateX(-50%) rotate(45deg);
+ border-top: none;
+ border-left: none;
+}
+
+/* Position: Bottom */
+.bottom {
+ top: 100%;
+ left: 50%;
+ transform: translateX(-50%);
+ margin-top: 8px;
+}
+
+.bottom .arrow {
+ top: -5px;
+ left: 50%;
+ transform: translateX(-50%) rotate(45deg);
+ border-bottom: none;
+ border-right: none;
+}
+
+/* Position: Left */
+.left {
+ right: 100%;
+ top: 50%;
+ transform: translateY(-50%);
+ margin-right: 8px;
+}
+
+.left .arrow {
+ right: -5px;
+ top: 50%;
+ transform: translateY(-50%) rotate(45deg);
+ border-left: none;
+ border-bottom: none;
+}
+
+/* Position: Right */
+.right {
+ left: 100%;
+ top: 50%;
+ transform: translateY(-50%);
+ margin-left: 8px;
+}
+
+.right .arrow {
+ left: -5px;
+ top: 50%;
+ transform: translateY(-50%) rotate(45deg);
+ border-right: none;
+ border-top: none;
+}
+
+/* Info Icon */
+.infoIcon {
+ cursor: help;
+ display: inline-flex;
+ align-items: center;
+ justify-content: center;
+ opacity: 0.7;
+ transition: opacity 0.2s ease;
+}
+
+.infoIcon:hover {
+ opacity: 1;
+}
+
+.icon-sm {
+ font-size: 0.75rem;
+}
+
+.icon-md {
+ font-size: 0.875rem;
+}
+
+.icon-lg {
+ font-size: 1rem;
+}
\ No newline at end of file
diff --git a/frontend/src/components/ui/Tooltip.tsx b/frontend/src/components/ui/Tooltip.tsx
new file mode 100644
index 0000000..dce6b5b
--- /dev/null
+++ b/frontend/src/components/ui/Tooltip.tsx
@@ -0,0 +1,59 @@
+import React, { useRef, useState } from "react";
+import styles from "./Tooltip.module.css";
+
+interface TooltipProps {
+ content: React.ReactNode;
+ children: React.ReactNode;
+ position?: "top" | "bottom" | "left" | "right";
+ className?: string;
+}
+
+export const Tooltip: React.FC = ({
+ content,
+ children,
+ position = "top",
+ className = "",
+}) => {
+ const [isVisible, setIsVisible] = useState(false);
+ const tooltipRef = useRef(null);
+
+ return (
+ setIsVisible(true)}
+ onMouseLeave={() => setIsVisible(false)}
+ ref={tooltipRef}
+ >
+ {children}
+ {isVisible && (
+
+ )}
+
+ );
+};
+
+// Info icon component for use with tooltips
+interface InfoIconProps {
+ tooltip: React.ReactNode;
+ size?: "sm" | "md" | "lg";
+ className?: string;
+}
+
+export const InfoIcon: React.FC = ({
+ tooltip,
+ size = "md",
+ className = "",
+}) => {
+ return (
+
+
+ ℹ️
+
+
+ );
+};
diff --git a/frontend/src/components/ui/index.ts b/frontend/src/components/ui/index.ts
new file mode 100644
index 0000000..8088d76
--- /dev/null
+++ b/frontend/src/components/ui/index.ts
@@ -0,0 +1,13 @@
+// Core UI Components
+export { Alert } from "./Alert";
+export { Badge } from "./Badge";
+export { Button } from "./Button";
+export { Card } from "./Card";
+export { Input } from "./Input";
+export { Spinner } from "./Spinner";
+
+// Educational/Guided Experience Components
+export { FeatureItem, HighlightBox, InfoCard } from "./InfoCard";
+export { CompactStepIndicator, StepIndicator } from "./StepIndicator";
+export type { Step } from "./StepIndicator";
+export { InfoIcon, Tooltip } from "./Tooltip";
diff --git a/frontend/src/config/contracts.ts b/frontend/src/config/contracts.ts
new file mode 100644
index 0000000..87b55b7
--- /dev/null
+++ b/frontend/src/config/contracts.ts
@@ -0,0 +1,25 @@
+import { bscTestnet, sepolia } from "@reown/appkit/networks";
+import { ENV } from "./env";
+
+export const CONTRACT_ADDRESSES = {
+ [sepolia.id]: {
+ goldToken: ENV.CONTRACTS.SEPOLIA.GOLD_TOKEN,
+ lotterie: ENV.CONTRACTS.SEPOLIA.LOTTERIE,
+ tokenBridge: ENV.CONTRACTS.SEPOLIA.TOKEN_BRIDGE,
+ },
+ [bscTestnet.id]: {
+ goldToken: ENV.CONTRACTS.BSC_TESTNET.GOLD_TOKEN,
+ lotterie: ENV.CONTRACTS.BSC_TESTNET.LOTTERIE,
+ tokenBridge: ENV.CONTRACTS.BSC_TESTNET.TOKEN_BRIDGE,
+ },
+} as const;
+
+export type ChainId = keyof typeof CONTRACT_ADDRESSES;
+
+export const getContractAddress = (
+ chainId: number | undefined,
+ contract: "goldToken" | "lotterie" | "tokenBridge"
+): string | undefined => {
+ if (!chainId) return undefined;
+ return CONTRACT_ADDRESSES[chainId as ChainId]?.[contract];
+};
diff --git a/frontend/src/config/env.ts b/frontend/src/config/env.ts
new file mode 100644
index 0000000..a329a5c
--- /dev/null
+++ b/frontend/src/config/env.ts
@@ -0,0 +1,40 @@
+const getRequiredEnvVar = (key: string): string => {
+ const value = import.meta.env[key];
+ if (!value) {
+ throw new Error(`Missing required environment variable: ${key}`);
+ }
+ return value;
+};
+
+const getOptionalEnvVar = (key: string, defaultValue: string): string => {
+ return import.meta.env[key] || defaultValue;
+};
+
+export const ENV = {
+ REOWN_PROJECT_ID: getRequiredEnvVar("VITE_REOWN_PROJECT_ID"),
+
+ CONTRACTS: {
+ SEPOLIA: {
+ GOLD_TOKEN: getRequiredEnvVar("VITE_CONTRACT_ADDRESS_SEPOLIA_GOLD_TOKEN"),
+ LOTTERIE: getRequiredEnvVar("VITE_CONTRACT_ADDRESS_SEPOLIA_LOTTERIE"),
+ TOKEN_BRIDGE: getRequiredEnvVar("VITE_CONTRACT_ADDRESS_SEPOLIA_TOKEN_BRIDGE"),
+ },
+ BSC_TESTNET: {
+ GOLD_TOKEN: getRequiredEnvVar("VITE_CONTRACT_ADDRESS_BSC_TESTNET_GOLD_TOKEN"),
+ LOTTERIE: getRequiredEnvVar("VITE_CONTRACT_ADDRESS_BSC_TESTNET_LOTTERIE"),
+ TOKEN_BRIDGE: getRequiredEnvVar("VITE_CONTRACT_ADDRESS_BSC_TESTNET_TOKEN_BRIDGE"),
+ },
+ },
+
+ RPC: {
+ SEPOLIA: getRequiredEnvVar("VITE_RPC_URL_SEPOLIA"),
+ BSC_TESTNET: getRequiredEnvVar("VITE_RPC_URL_BSC_TESTNET"),
+ },
+
+ SITE: {
+ NAME: getOptionalEnvVar("VITE_SITE_NAME", "Golden Bridge"),
+ DESCRIPTION: getOptionalEnvVar("VITE_SITE_DESCRIPTION", "Gold-backed tokenization with lottery rewards"),
+ URL: getOptionalEnvVar("VITE_SITE_URL", "http://localhost:5173"),
+ ICON: getOptionalEnvVar("VITE_SITE_ICON", "https://assets.reown.com/reown-profile-pic.png"),
+ }
+} as const;
\ No newline at end of file
diff --git a/frontend/src/config/index.ts b/frontend/src/config/index.ts
new file mode 100644
index 0000000..6d5209b
--- /dev/null
+++ b/frontend/src/config/index.ts
@@ -0,0 +1,4 @@
+export * from "./contracts";
+export * from "./networks";
+export * from "./reown";
+export * from "./env";
diff --git a/frontend/src/config/networks.ts b/frontend/src/config/networks.ts
new file mode 100644
index 0000000..0552f20
--- /dev/null
+++ b/frontend/src/config/networks.ts
@@ -0,0 +1,52 @@
+import { bscTestnet, sepolia } from "@reown/appkit/networks";
+import { ENV } from "./env";
+
+export interface NetworkConfig {
+ chainId: number;
+ name: string;
+ currency: string;
+ explorerUrl: string;
+ rpcUrl: string;
+ icon?: string;
+}
+
+export const NETWORKS: Record = {
+ [sepolia.id]: {
+ chainId: sepolia.id,
+ name: "Sepolia Testnet",
+ currency: "ETH",
+ explorerUrl: "https://sepolia.etherscan.io",
+ rpcUrl: ENV.RPC.SEPOLIA,
+ },
+ [bscTestnet.id]: {
+ chainId: bscTestnet.id,
+ name: "BSC Testnet",
+ currency: "tBNB",
+ explorerUrl: "https://testnet.bscscan.com",
+ rpcUrl: ENV.RPC.BSC_TESTNET,
+ },
+};
+
+export const SUPPORTED_CHAIN_IDS = [sepolia.id, bscTestnet.id];
+
+export const getNetworkConfig = (
+ chainId: number | undefined
+): NetworkConfig | undefined => {
+ if (!chainId) return undefined;
+ return NETWORKS[chainId];
+};
+
+export const isSupportedNetwork = (chainId: number | undefined): boolean => {
+ if (!chainId) return false;
+ return SUPPORTED_CHAIN_IDS.includes(chainId as any);
+};
+
+export const getExplorerLink = (
+ chainId: number | undefined,
+ hash: string,
+ type: "tx" | "address" = "tx"
+): string => {
+ const config = getNetworkConfig(chainId);
+ if (!config) return "#";
+ return `${config.explorerUrl}/${type}/${hash}`;
+};
diff --git a/frontend/src/config/reown.ts b/frontend/src/config/reown.ts
new file mode 100644
index 0000000..cd60ed8
--- /dev/null
+++ b/frontend/src/config/reown.ts
@@ -0,0 +1,49 @@
+import { EthersAdapter } from "@reown/appkit-adapter-ethers";
+import { bscTestnet, sepolia } from "@reown/appkit/networks";
+import { createAppKit } from "@reown/appkit/react";
+import { ENV } from "./env";
+
+// 1. Get projectId
+const projectId = ENV.REOWN_PROJECT_ID;
+
+// 2. Set the networks
+const customSepolia = {
+ ...sepolia,
+ rpcUrls: {
+ ...sepolia.rpcUrls,
+ default: {
+ http: [ENV.RPC.SEPOLIA],
+ },
+ },
+};
+
+const customBscTestnet = {
+ ...bscTestnet,
+ rpcUrls: {
+ ...bscTestnet.rpcUrls,
+ default: {
+ http: [ENV.RPC.BSC_TESTNET],
+ },
+ },
+};
+
+export const networks = [customSepolia, customBscTestnet];
+
+// 3. Create a metadata object
+const metadata = {
+ name: ENV.SITE.NAME,
+ description: ENV.SITE.DESCRIPTION,
+ url: ENV.SITE.URL,
+ icons: [ENV.SITE.ICON],
+};
+
+// 4. Create the AppKit instance
+export const appKit = createAppKit({
+ adapters: [new EthersAdapter()],
+ networks: [customSepolia, customBscTestnet],
+ metadata,
+ projectId,
+ features: {
+ analytics: true,
+ },
+});
diff --git a/frontend/src/hooks/index.ts b/frontend/src/hooks/index.ts
new file mode 100644
index 0000000..15a0a82
--- /dev/null
+++ b/frontend/src/hooks/index.ts
@@ -0,0 +1,5 @@
+export * from "./useAdmin";
+export * from "./useGoldToken";
+export * from "./useLotterie";
+export * from "./useNetwork";
+export * from "./useTokenBridge";
diff --git a/frontend/src/hooks/useAdmin.ts b/frontend/src/hooks/useAdmin.ts
new file mode 100644
index 0000000..92a997a
--- /dev/null
+++ b/frontend/src/hooks/useAdmin.ts
@@ -0,0 +1,175 @@
+import {
+ useAppKitAccount,
+ useAppKitNetwork,
+ useAppKitProvider,
+} from "@reown/appkit/react";
+import { BrowserProvider, Contract, Eip1193Provider } from "ethers";
+import { useCallback, useEffect, useMemo, useState } from "react";
+import iGoldTokenAbi from "../../abi/goldToken/iGoldTokenAbi.json";
+import iLotterieAbi from "../../abi/lotterie/iLotterieAbi.json";
+import tokenBridgeAbi from "../../abi/tokenBridge/tokenBridgeAbi.json";
+import { getContractAddress } from "../config/contracts";
+
+export interface AdminStatus {
+ isGoldTokenOwner: boolean;
+ isLotterieOwner: boolean;
+ isTokenBridgeOwner: boolean;
+ isAnyOwner: boolean;
+ isAllOwner: boolean;
+}
+
+export const useAdmin = () => {
+ const { address, isConnected } = useAppKitAccount();
+ const { chainId } = useAppKitNetwork();
+ const { walletProvider } = useAppKitProvider("eip155");
+ const [loading, setLoading] = useState(false);
+ const [error, setError] = useState(null);
+ const [adminStatus, setAdminStatus] = useState({
+ isGoldTokenOwner: false,
+ isLotterieOwner: false,
+ isTokenBridgeOwner: false,
+ isAnyOwner: false,
+ isAllOwner: false,
+ });
+
+ const goldTokenAddress = useMemo(
+ () => getContractAddress(chainId as number, "goldToken"),
+ [chainId]
+ );
+
+ const lotterieAddress = useMemo(
+ () => getContractAddress(chainId as number, "lotterie"),
+ [chainId]
+ );
+
+ const tokenBridgeAddress = useMemo(
+ () => getContractAddress(chainId as number, "tokenBridge"),
+ [chainId]
+ );
+
+ const getProvider = useCallback(async () => {
+ if (!walletProvider) throw new Error("Wallet not connected");
+ return new BrowserProvider(walletProvider as Eip1193Provider);
+ }, [walletProvider]);
+
+ const checkOwnerRole = useCallback(async () => {
+ if (!address || !isConnected) {
+ setAdminStatus({
+ isGoldTokenOwner: false,
+ isLotterieOwner: false,
+ isTokenBridgeOwner: false,
+ isAnyOwner: false,
+ isAllOwner: false,
+ });
+ return;
+ }
+
+ setLoading(true);
+ setError(null);
+
+ try {
+ const provider = await getProvider();
+ const results = {
+ isGoldTokenOwner: false,
+ isLotterieOwner: false,
+ isTokenBridgeOwner: false,
+ };
+
+ // Check GoldToken owner role
+ if (goldTokenAddress) {
+ try {
+ const goldTokenContract = new Contract(
+ goldTokenAddress,
+ iGoldTokenAbi.abi,
+ provider
+ );
+ results.isGoldTokenOwner = await goldTokenContract.hasOwnerRole(
+ address
+ );
+ } catch (err) {
+ console.warn("Failed to check GoldToken owner role:", err);
+ }
+ }
+
+ // Check Lotterie owner role
+ if (lotterieAddress) {
+ try {
+ const lotterieContract = new Contract(
+ lotterieAddress,
+ iLotterieAbi.abi,
+ provider
+ );
+ results.isLotterieOwner = await lotterieContract.hasOwnerRole(
+ address
+ );
+ } catch (err) {
+ console.warn("Failed to check Lotterie owner role:", err);
+ }
+ }
+
+ // Check TokenBridge owner role
+ if (tokenBridgeAddress) {
+ try {
+ const tokenBridgeContract = new Contract(
+ tokenBridgeAddress,
+ tokenBridgeAbi.abi,
+ provider
+ );
+ // TokenBridge uses hasRole with OWNER_ROLE constant
+ const OWNER_ROLE =
+ "0xb19546dff01e856fb3f010c267a7b1c60363cf8a4664e21cc89c26224620214e";
+ results.isTokenBridgeOwner = await tokenBridgeContract.hasRole(
+ OWNER_ROLE,
+ address
+ );
+ } catch (err) {
+ console.warn("Failed to check TokenBridge owner role:", err);
+ }
+ }
+
+ const isAnyOwner =
+ results.isGoldTokenOwner ||
+ results.isLotterieOwner ||
+ results.isTokenBridgeOwner;
+
+ const isAllOwner =
+ results.isGoldTokenOwner &&
+ results.isLotterieOwner &&
+ results.isTokenBridgeOwner;
+
+ setAdminStatus({
+ ...results,
+ isAnyOwner,
+ isAllOwner,
+ });
+ } catch (err: any) {
+ setError(err.message || "Failed to check admin status");
+ console.error("Error checking admin status:", err);
+ } finally {
+ setLoading(false);
+ }
+ }, [
+ address,
+ isConnected,
+ getProvider,
+ goldTokenAddress,
+ lotterieAddress,
+ tokenBridgeAddress,
+ ]);
+
+ // Check owner role when wallet connects or chain changes
+ useEffect(() => {
+ if (isConnected && address) {
+ checkOwnerRole();
+ }
+ }, [isConnected, address, chainId, checkOwnerRole]);
+
+ return {
+ loading,
+ error,
+ ...adminStatus,
+ checkOwnerRole,
+ address,
+ isConnected,
+ };
+};
diff --git a/frontend/src/hooks/useGoldToken.ts b/frontend/src/hooks/useGoldToken.ts
new file mode 100644
index 0000000..b801cd6
--- /dev/null
+++ b/frontend/src/hooks/useGoldToken.ts
@@ -0,0 +1,319 @@
+import {
+ useAppKitAccount,
+ useAppKitNetwork,
+ useAppKitProvider,
+} from "@reown/appkit/react";
+import { BrowserProvider, Contract, Eip1193Provider } from "ethers";
+import { useCallback, useMemo, useState } from "react";
+import iGoldTokenAbi from "../../abi/goldToken/iGoldTokenAbi.json";
+import { getContractAddress } from "../config/contracts";
+
+export const useGoldToken = () => {
+ const { address, isConnected } = useAppKitAccount();
+ const { chainId } = useAppKitNetwork();
+ const { walletProvider } = useAppKitProvider("eip155");
+ const [loading, setLoading] = useState(false);
+ const [error, setError] = useState(null);
+
+ const contractAddress = useMemo(
+ () => getContractAddress(chainId as number, "goldToken"),
+ [chainId]
+ );
+
+ const getContract = useCallback(
+ async (withSigner = false) => {
+ if (!contractAddress)
+ throw new Error("Contract not deployed on this network");
+ if (!walletProvider) throw new Error("Wallet not connected");
+
+ const ethersProvider = new BrowserProvider(
+ walletProvider as Eip1193Provider
+ );
+
+ if (withSigner) {
+ const signer = await ethersProvider.getSigner();
+ return new Contract(contractAddress, iGoldTokenAbi.abi, signer);
+ }
+
+ return new Contract(contractAddress, iGoldTokenAbi.abi, ethersProvider);
+ },
+ [contractAddress, walletProvider]
+ );
+
+ // User-Facing Functions
+ const mint = useCallback(
+ async (value: bigint) => {
+ setLoading(true);
+ setError(null);
+ try {
+ const contract = await getContract(true);
+ const tx = await contract.mint({ value });
+ await tx.wait();
+ } catch (err: any) {
+ setError(err.message || "Failed to mint tokens");
+ throw err;
+ } finally {
+ setLoading(false);
+ }
+ },
+ [getContract]
+ );
+
+ const burn = useCallback(
+ async (amount: bigint) => {
+ setLoading(true);
+ setError(null);
+ try {
+ const contract = await getContract(true);
+ const tx = await contract.burn(amount);
+ await tx.wait();
+ } catch (err: any) {
+ setError(err.message || "Failed to burn tokens");
+ throw err;
+ } finally {
+ setLoading(false);
+ }
+ },
+ [getContract]
+ );
+
+ const transfer = useCallback(
+ async (to: string, amount: bigint) => {
+ setLoading(true);
+ setError(null);
+ try {
+ const contract = await getContract(true);
+ const tx = await contract.transfer(to, amount);
+ await tx.wait();
+ return true;
+ } catch (err: any) {
+ setError(err.message || "Failed to transfer tokens");
+ throw err;
+ } finally {
+ setLoading(false);
+ }
+ },
+ [getContract]
+ );
+
+ const balanceOf = useCallback(
+ async (account: string) => {
+ try {
+ const contract = await getContract(false);
+ return await contract.balanceOf(account);
+ } catch (err: any) {
+ setError(err.message || "Failed to get balance");
+ throw err;
+ }
+ },
+ [getContract]
+ );
+
+ const claimEth = useCallback(async () => {
+ setLoading(true);
+ setError(null);
+ try {
+ const contract = await getContract(true);
+ const tx = await contract.claimEth();
+ await tx.wait();
+ } catch (err: any) {
+ setError(err.message || "Failed to claim ETH");
+ throw err;
+ } finally {
+ setLoading(false);
+ }
+ }, [getContract]);
+
+ // View Functions
+ const getGoldPriceInEth = useCallback(async () => {
+ try {
+ const contract = await getContract(false);
+ return await contract.getGoldPriceInEth();
+ } catch (err: any) {
+ setError(err.message || "Failed to get gold price");
+ throw err;
+ }
+ }, [getContract]);
+
+ const getFees = useCallback(async () => {
+ try {
+ const contract = await getContract(false);
+ return await contract.getFees();
+ } catch (err: any) {
+ setError(err.message || "Failed to get fees");
+ throw err;
+ }
+ }, [getContract]);
+
+ const getFeesAddress = useCallback(async () => {
+ try {
+ const contract = await getContract(false);
+ return await contract.getFeesAddress();
+ } catch (err: any) {
+ setError(err.message || "Failed to get fees address");
+ throw err;
+ }
+ }, [getContract]);
+
+ const getUsers = useCallback(async () => {
+ try {
+ const contract = await getContract(false);
+ return await contract.getUsers();
+ } catch (err: any) {
+ setError(err.message || "Failed to get users");
+ throw err;
+ }
+ }, [getContract]);
+
+ const getTimestamps = useCallback(async () => {
+ try {
+ const contract = await getContract(false);
+ const [users, timestamps] = await contract.getTimestamps();
+ return { users, timestamps };
+ } catch (err: any) {
+ setError(err.message || "Failed to get timestamps");
+ throw err;
+ }
+ }, [getContract]);
+
+ const hasOwnerRole = useCallback(
+ async (account: string) => {
+ try {
+ const contract = await getContract(false);
+ return await contract.hasOwnerRole(account);
+ } catch (err: any) {
+ setError(err.message || "Failed to check owner role");
+ throw err;
+ }
+ },
+ [getContract]
+ );
+
+ // Admin Functions
+ const setFeesAddress = useCallback(
+ async (feesAddress: string) => {
+ setLoading(true);
+ setError(null);
+ try {
+ const contract = await getContract(true);
+ const tx = await contract.setFeesAddress(feesAddress);
+ await tx.wait();
+ } catch (err: any) {
+ setError(err.message || "Failed to set fees address");
+ throw err;
+ } finally {
+ setLoading(false);
+ }
+ },
+ [getContract]
+ );
+
+ const setLotterieAddress = useCallback(
+ async (lotterieAddress: string) => {
+ setLoading(true);
+ setError(null);
+ try {
+ const contract = await getContract(true);
+ const tx = await contract.setLotterieAddress(lotterieAddress);
+ await tx.wait();
+ } catch (err: any) {
+ setError(err.message || "Failed to set lottery address");
+ throw err;
+ } finally {
+ setLoading(false);
+ }
+ },
+ [getContract]
+ );
+
+ const addOwner = useCallback(
+ async (account: string) => {
+ setLoading(true);
+ setError(null);
+ try {
+ const contract = await getContract(true);
+ const tx = await contract.addOwner(account);
+ await tx.wait();
+ } catch (err: any) {
+ setError(err.message || "Failed to add owner");
+ throw err;
+ } finally {
+ setLoading(false);
+ }
+ },
+ [getContract]
+ );
+
+ const removeOwner = useCallback(
+ async (account: string) => {
+ setLoading(true);
+ setError(null);
+ try {
+ const contract = await getContract(true);
+ const tx = await contract.removeOwner(account);
+ await tx.wait();
+ } catch (err: any) {
+ setError(err.message || "Failed to remove owner");
+ throw err;
+ } finally {
+ setLoading(false);
+ }
+ },
+ [getContract]
+ );
+
+ const pause = useCallback(async () => {
+ setLoading(true);
+ setError(null);
+ try {
+ const contract = await getContract(true);
+ const tx = await contract.pause();
+ await tx.wait();
+ } catch (err: any) {
+ setError(err.message || "Failed to pause contract");
+ throw err;
+ } finally {
+ setLoading(false);
+ }
+ }, [getContract]);
+
+ const unpause = useCallback(async () => {
+ setLoading(true);
+ setError(null);
+ try {
+ const contract = await getContract(true);
+ const tx = await contract.unpause();
+ await tx.wait();
+ } catch (err: any) {
+ setError(err.message || "Failed to unpause contract");
+ throw err;
+ } finally {
+ setLoading(false);
+ }
+ }, [getContract]);
+
+ return {
+ loading,
+ error,
+ contractAddress,
+ isConnected,
+ address,
+ mint,
+ burn,
+ transfer,
+ balanceOf,
+ claimEth,
+ getGoldPriceInEth,
+ getFees,
+ getFeesAddress,
+ getUsers,
+ getTimestamps,
+ hasOwnerRole,
+ setFeesAddress,
+ setLotterieAddress,
+ addOwner,
+ removeOwner,
+ pause,
+ unpause,
+ };
+};
diff --git a/frontend/src/hooks/useLotterie.ts b/frontend/src/hooks/useLotterie.ts
new file mode 100644
index 0000000..058f40a
--- /dev/null
+++ b/frontend/src/hooks/useLotterie.ts
@@ -0,0 +1,465 @@
+import {
+ useAppKitAccount,
+ useAppKitNetwork,
+ useAppKitProvider,
+} from "@reown/appkit/react";
+import { BrowserProvider, Contract, Eip1193Provider } from "ethers";
+import { useCallback, useMemo, useState } from "react";
+import iLotterieAbi from "../../abi/lotterie/iLotterieAbi.json";
+import { getContractAddress } from "../config/contracts";
+
+export const useLotterie = () => {
+ const { address, isConnected } = useAppKitAccount();
+ const { chainId } = useAppKitNetwork();
+ const { walletProvider } = useAppKitProvider("eip155");
+ const [loading, setLoading] = useState(false);
+ const [error, setError] = useState(null);
+
+ const contractAddress = useMemo(
+ () => getContractAddress(chainId as number, "lotterie"),
+ [chainId]
+ );
+
+ const getContract = useCallback(
+ async (withSigner = false) => {
+ if (!contractAddress)
+ throw new Error("Contract not deployed on this network");
+ if (!walletProvider) throw new Error("Wallet not connected");
+
+ const ethersProvider = new BrowserProvider(
+ walletProvider as Eip1193Provider
+ );
+
+ if (withSigner) {
+ const signer = await ethersProvider.getSigner();
+ return new Contract(contractAddress, iLotterieAbi.abi, signer);
+ }
+
+ return new Contract(contractAddress, iLotterieAbi.abi, ethersProvider);
+ },
+ [contractAddress, walletProvider]
+ );
+
+ // User-Facing Functions
+ const claim = useCallback(async () => {
+ setLoading(true);
+ setError(null);
+ try {
+ const contract = await getContract(true);
+ const tx = await contract.claim();
+ await tx.wait();
+ } catch (err: any) {
+ setError(err.message || "Failed to claim winnings");
+ throw err;
+ } finally {
+ setLoading(false);
+ }
+ }, [getContract]);
+
+ const getGains = useCallback(
+ async (account: string) => {
+ try {
+ const contract = await getContract(false);
+ return await contract.getGains(account);
+ } catch (err: any) {
+ setError(err.message || "Failed to get gains");
+ throw err;
+ }
+ },
+ [getContract]
+ );
+
+ // Lottery State Functions (view)
+ const getLastRequestId = useCallback(async () => {
+ try {
+ const contract = await getContract(false);
+ return await contract.getLastRequestId();
+ } catch (err: any) {
+ setError(err.message || "Failed to get last request ID");
+ throw err;
+ }
+ }, [getContract]);
+
+ const getResults = useCallback(
+ async (requestId: bigint) => {
+ try {
+ const contract = await getContract(false);
+ return await contract.getResults(requestId);
+ } catch (err: any) {
+ setError(err.message || "Failed to get results");
+ throw err;
+ }
+ },
+ [getContract]
+ );
+
+ const getGoldToken = useCallback(async () => {
+ try {
+ const contract = await getContract(false);
+ return await contract.getGoldToken();
+ } catch (err: any) {
+ setError(err.message || "Failed to get gold token address");
+ throw err;
+ }
+ }, [getContract]);
+
+ // VRF Configuration (view)
+ const getVrfSubscriptionId = useCallback(async () => {
+ try {
+ const contract = await getContract(false);
+ return await contract.getVrfSubscriptionId();
+ } catch (err: any) {
+ setError(err.message || "Failed to get VRF subscription ID");
+ throw err;
+ }
+ }, [getContract]);
+
+ const getVrfCoordinator = useCallback(async () => {
+ try {
+ const contract = await getContract(false);
+ return await contract.getVrfCoordinator();
+ } catch (err: any) {
+ setError(err.message || "Failed to get VRF coordinator");
+ throw err;
+ }
+ }, [getContract]);
+
+ const getKeyHash = useCallback(async () => {
+ try {
+ const contract = await getContract(false);
+ return await contract.getKeyHash();
+ } catch (err: any) {
+ setError(err.message || "Failed to get key hash");
+ throw err;
+ }
+ }, [getContract]);
+
+ const getCallbackGasLimit = useCallback(async () => {
+ try {
+ const contract = await getContract(false);
+ return await contract.getCallbackGasLimit();
+ } catch (err: any) {
+ setError(err.message || "Failed to get callback gas limit");
+ throw err;
+ }
+ }, [getContract]);
+
+ const getRequestConfirmations = useCallback(async () => {
+ try {
+ const contract = await getContract(false);
+ return await contract.getRequestConfirmations();
+ } catch (err: any) {
+ setError(err.message || "Failed to get request confirmations");
+ throw err;
+ }
+ }, [getContract]);
+
+ const getNumWords = useCallback(async () => {
+ try {
+ const contract = await getContract(false);
+ return await contract.getNumWords();
+ } catch (err: any) {
+ setError(err.message || "Failed to get num words");
+ throw err;
+ }
+ }, [getContract]);
+
+ // Admin Functions (OWNER_ROLE)
+ const randomDraw = useCallback(async () => {
+ setLoading(true);
+ setError(null);
+ try {
+ const contract = await getContract(true);
+ const tx = await contract.randomDraw();
+ const receipt = await tx.wait();
+
+ // Extract requestId from transaction receipt if available
+ const requestId = receipt?.logs?.[0]?.args?.[0];
+ console.log("VRF Request initiated with ID:", requestId?.toString());
+
+ return requestId;
+ } catch (err: any) {
+ console.error("VRF Random Draw Error:", err);
+
+ // Provide specific error messages for common VRF issues
+ let errorMessage = "Failed to initiate random draw";
+ if (err.message?.includes("gas")) {
+ errorMessage = "Gas estimation failed. Please try again.";
+ } else if (err.message?.includes("OneRandomDrawPerDay")) {
+ errorMessage =
+ "Random draw can only be performed once per day. Please try again tomorrow.";
+ } else if (err.message?.includes("execution reverted")) {
+ errorMessage =
+ "Transaction reverted. Please check your permissions and try again.";
+ } else if (err.message) {
+ errorMessage = err.message;
+ }
+
+ setError(errorMessage);
+ throw err;
+ } finally {
+ setLoading(false);
+ }
+ }, [getContract]);
+
+ const setGoldToken = useCallback(
+ async (goldToken: string) => {
+ setLoading(true);
+ setError(null);
+ try {
+ const contract = await getContract(true);
+ const tx = await contract.setGoldToken(goldToken);
+ await tx.wait();
+ } catch (err: any) {
+ setError(err.message || "Failed to set gold token");
+ throw err;
+ } finally {
+ setLoading(false);
+ }
+ },
+ [getContract]
+ );
+
+ const setVrfSubscriptionId = useCallback(
+ async (vrfSubscriptionId: bigint) => {
+ setLoading(true);
+ setError(null);
+ try {
+ const contract = await getContract(true);
+ const tx = await contract.setVrfSubscriptionId(vrfSubscriptionId);
+ await tx.wait();
+ } catch (err: any) {
+ setError(err.message || "Failed to set VRF subscription ID");
+ throw err;
+ } finally {
+ setLoading(false);
+ }
+ },
+ [getContract]
+ );
+
+ const setVrfCoordinator = useCallback(
+ async (vrfCoordinator: string) => {
+ setLoading(true);
+ setError(null);
+ try {
+ const contract = await getContract(true);
+ const tx = await contract.setVrfCoordinator(vrfCoordinator);
+ await tx.wait();
+ } catch (err: any) {
+ setError(err.message || "Failed to set VRF coordinator");
+ throw err;
+ } finally {
+ setLoading(false);
+ }
+ },
+ [getContract]
+ );
+
+ const setKeyHash = useCallback(
+ async (keyHash: string) => {
+ setLoading(true);
+ setError(null);
+ try {
+ const contract = await getContract(true);
+ const tx = await contract.setKeyHash(keyHash);
+ await tx.wait();
+ } catch (err: any) {
+ setError(err.message || "Failed to set key hash");
+ throw err;
+ } finally {
+ setLoading(false);
+ }
+ },
+ [getContract]
+ );
+
+ const setCallbackGasLimit = useCallback(
+ async (callbackGasLimit: number) => {
+ setLoading(true);
+ setError(null);
+ try {
+ const contract = await getContract(true);
+ const tx = await contract.setCallbackGasLimit(callbackGasLimit);
+ await tx.wait();
+ } catch (err: any) {
+ setError(err.message || "Failed to set callback gas limit");
+ throw err;
+ } finally {
+ setLoading(false);
+ }
+ },
+ [getContract]
+ );
+
+ const setRequestConfirmations = useCallback(
+ async (requestConfirmations: number) => {
+ setLoading(true);
+ setError(null);
+ try {
+ const contract = await getContract(true);
+ const tx = await contract.setRequestConfirmations(requestConfirmations);
+ await tx.wait();
+ } catch (err: any) {
+ setError(err.message || "Failed to set request confirmations");
+ throw err;
+ } finally {
+ setLoading(false);
+ }
+ },
+ [getContract]
+ );
+
+ const setNumWords = useCallback(
+ async (numWords: number) => {
+ setLoading(true);
+ setError(null);
+ try {
+ const contract = await getContract(true);
+ const tx = await contract.setNumWords(numWords);
+ await tx.wait();
+ } catch (err: any) {
+ setError(err.message || "Failed to set num words");
+ throw err;
+ } finally {
+ setLoading(false);
+ }
+ },
+ [getContract]
+ );
+
+ const addOwner = useCallback(
+ async (account: string) => {
+ setLoading(true);
+ setError(null);
+ try {
+ const contract = await getContract(true);
+ const tx = await contract.addOwner(account);
+ await tx.wait();
+ } catch (err: any) {
+ setError(err.message || "Failed to add owner");
+ throw err;
+ } finally {
+ setLoading(false);
+ }
+ },
+ [getContract]
+ );
+
+ const removeOwner = useCallback(
+ async (account: string) => {
+ setLoading(true);
+ setError(null);
+ try {
+ const contract = await getContract(true);
+ const tx = await contract.removeOwner(account);
+ await tx.wait();
+ } catch (err: any) {
+ setError(err.message || "Failed to remove owner");
+ throw err;
+ } finally {
+ setLoading(false);
+ }
+ },
+ [getContract]
+ );
+
+ const hasOwnerRole = useCallback(
+ async (account: string) => {
+ try {
+ const contract = await getContract(false);
+ return await contract.hasOwnerRole(account);
+ } catch (err: any) {
+ setError(err.message || "Failed to check owner role");
+ throw err;
+ }
+ },
+ [getContract]
+ );
+
+ // Diagnostic function to check VRF configuration
+ const checkVrfConfiguration = useCallback(async () => {
+ try {
+ const [
+ subscriptionId,
+ coordinator,
+ keyHash,
+ callbackGasLimit,
+ requestConfirmations,
+ numWords,
+ ] = await Promise.all([
+ getVrfSubscriptionId(),
+ getVrfCoordinator(),
+ getKeyHash(),
+ getCallbackGasLimit(),
+ getRequestConfirmations(),
+ getNumWords(),
+ ]);
+
+ console.log("VRF Configuration Check:");
+ console.log("- Subscription ID:", subscriptionId.toString());
+ console.log("- Coordinator:", coordinator);
+ console.log("- Key Hash:", keyHash);
+ console.log("- Callback Gas Limit:", callbackGasLimit.toString());
+ console.log("- Request Confirmations:", requestConfirmations.toString());
+ console.log("- Num Words:", numWords.toString());
+
+ return {
+ subscriptionId,
+ coordinator,
+ keyHash,
+ callbackGasLimit,
+ requestConfirmations,
+ numWords,
+ };
+ } catch (err: any) {
+ console.error("VRF Configuration Check Failed:", err);
+ setError(err.message || "Failed to check VRF configuration");
+ throw err;
+ }
+ }, [
+ getVrfSubscriptionId,
+ getVrfCoordinator,
+ getKeyHash,
+ getCallbackGasLimit,
+ getRequestConfirmations,
+ getNumWords,
+ ]);
+
+ // Function to manually clear error state
+ const clearError = useCallback(() => {
+ setError(null);
+ }, []);
+
+ return {
+ loading,
+ error,
+ contractAddress,
+ isConnected,
+ address,
+ clearError,
+ claim,
+ getGains,
+ getLastRequestId,
+ getResults,
+ getGoldToken,
+ getVrfSubscriptionId,
+ getVrfCoordinator,
+ getKeyHash,
+ getCallbackGasLimit,
+ getRequestConfirmations,
+ getNumWords,
+ randomDraw,
+ setGoldToken,
+ setVrfSubscriptionId,
+ setVrfCoordinator,
+ setKeyHash,
+ setCallbackGasLimit,
+ setRequestConfirmations,
+ setNumWords,
+ addOwner,
+ removeOwner,
+ hasOwnerRole,
+ checkVrfConfiguration,
+ };
+};
diff --git a/frontend/src/hooks/useNetwork.ts b/frontend/src/hooks/useNetwork.ts
new file mode 100644
index 0000000..80488d6
--- /dev/null
+++ b/frontend/src/hooks/useNetwork.ts
@@ -0,0 +1,39 @@
+import { bscTestnet, sepolia } from "@reown/appkit/networks";
+import { useAppKitNetwork } from "@reown/appkit/react";
+import { isSupportedNetwork as checkSupported } from "../config/networks";
+
+export const useNetwork = () => {
+ const { chainId, switchNetwork } = useAppKitNetwork();
+
+ const isSepoliaNetwork = () => chainId === sepolia.id;
+ const isBscTestnet = () => chainId === bscTestnet.id;
+ const isSupportedNetwork = () => checkSupported(chainId as number);
+
+ const switchToSepolia = async () => {
+ try {
+ await switchNetwork(sepolia);
+ } catch (error) {
+ console.error("Failed to switch to Sepolia:", error);
+ throw error;
+ }
+ };
+
+ const switchToBscTestnet = async () => {
+ try {
+ await switchNetwork(bscTestnet);
+ } catch (error) {
+ console.error("Failed to switch to BSC Testnet:", error);
+ throw error;
+ }
+ };
+
+ return {
+ chainId,
+ isSepoliaNetwork,
+ isBscTestnet,
+ isSupportedNetwork,
+ switchToSepolia,
+ switchToBscTestnet,
+ switchNetwork,
+ };
+};
diff --git a/frontend/src/hooks/useTokenBridge.ts b/frontend/src/hooks/useTokenBridge.ts
new file mode 100644
index 0000000..5577517
--- /dev/null
+++ b/frontend/src/hooks/useTokenBridge.ts
@@ -0,0 +1,296 @@
+import {
+ useAppKitAccount,
+ useAppKitNetwork,
+ useAppKitProvider,
+} from "@reown/appkit/react";
+import { BrowserProvider, Contract, Eip1193Provider } from "ethers";
+import { useCallback, useMemo, useState } from "react";
+import tokenBridgeAbi from "../../abi/tokenBridge/tokenBridgeAbi.json";
+import { getContractAddress } from "../config/contracts";
+import { PayFeesIn } from "../types/tokenBridge";
+
+export const useTokenBridge = () => {
+ const { address, isConnected } = useAppKitAccount();
+ const { chainId } = useAppKitNetwork();
+ const { walletProvider } = useAppKitProvider("eip155");
+ const [loading, setLoading] = useState(false);
+ const [error, setError] = useState(null);
+
+ const contractAddress = useMemo(
+ () => getContractAddress(chainId as number, "tokenBridge"),
+ [chainId]
+ );
+
+ const getContract = useCallback(
+ async (withSigner = false) => {
+ if (!contractAddress)
+ throw new Error("Contract not deployed on this network");
+ if (!walletProvider) throw new Error("Wallet not connected");
+
+ const ethersProvider = new BrowserProvider(
+ walletProvider as Eip1193Provider
+ );
+
+ if (withSigner) {
+ const signer = await ethersProvider.getSigner();
+ return new Contract(contractAddress, tokenBridgeAbi.abi, signer);
+ }
+
+ return new Contract(contractAddress, tokenBridgeAbi.abi, ethersProvider);
+ },
+ [contractAddress, walletProvider]
+ );
+
+ // User-Facing Functions
+ const bridgeTokens = useCallback(
+ async (receiver: string, amount: bigint, payFeesIn: PayFeesIn) => {
+ setLoading(true);
+ setError(null);
+ try {
+ const contract = await getContract(true);
+ const tx = await contract.bridgeTokens(receiver, amount, payFeesIn);
+ const receipt = await tx.wait();
+ // Find the TokensBridged event to get the messageId
+ // This is a simplification, in a real app we might want to parse logs
+ return receipt;
+ } catch (err: any) {
+ setError(err.message || "Failed to bridge tokens");
+ throw err;
+ } finally {
+ setLoading(false);
+ }
+ },
+ [getContract]
+ );
+
+ // State Query Functions (view)
+ const getDestinationChainSelector = useCallback(async () => {
+ try {
+ const contract = await getContract(false);
+ return await contract.destinationChainSelector();
+ } catch (err: any) {
+ setError(err.message || "Failed to get destination chain selector");
+ throw err;
+ }
+ }, [getContract]);
+
+ const getGoldToken = useCallback(async () => {
+ try {
+ const contract = await getContract(false);
+ return await contract.goldToken();
+ } catch (err: any) {
+ setError(err.message || "Failed to get gold token address");
+ throw err;
+ }
+ }, [getContract]);
+
+ const getLink = useCallback(async () => {
+ try {
+ const contract = await getContract(false);
+ return await contract.link();
+ } catch (err: any) {
+ setError(err.message || "Failed to get LINK token address");
+ throw err;
+ }
+ }, [getContract]);
+
+ const getGoldTokenBalance = useCallback(async () => {
+ try {
+ const contract = await getContract(false);
+ return await contract.getGoldTokenBalance();
+ } catch (err: any) {
+ setError(err.message || "Failed to get gold token balance");
+ throw err;
+ }
+ }, [getContract]);
+
+ const getLinkBalance = useCallback(async () => {
+ try {
+ const contract = await getContract(false);
+ return await contract.getLinkBalance();
+ } catch (err: any) {
+ setError(err.message || "Failed to get LINK balance");
+ throw err;
+ }
+ }, [getContract]);
+
+ const getProcessedMessages = useCallback(
+ async (messageId: string) => {
+ try {
+ const contract = await getContract(false);
+ return await contract.processedMessages(messageId);
+ } catch (err: any) {
+ setError(err.message || "Failed to check processed message");
+ throw err;
+ }
+ },
+ [getContract]
+ );
+
+ const getWhitelistedChains = useCallback(
+ async (chainSelector: bigint) => {
+ try {
+ const contract = await getContract(false);
+ return await contract.whitelistedChains(chainSelector);
+ } catch (err: any) {
+ setError(err.message || "Failed to check whitelisted chain");
+ throw err;
+ }
+ },
+ [getContract]
+ );
+
+ const getWhitelistedSenders = useCallback(
+ async (sender: string) => {
+ try {
+ const contract = await getContract(false);
+ return await contract.whitelistedSenders(sender);
+ } catch (err: any) {
+ setError(err.message || "Failed to check whitelisted sender");
+ throw err;
+ }
+ },
+ [getContract]
+ );
+
+ const paused = useCallback(async () => {
+ try {
+ const contract = await getContract(false);
+ return await contract.paused();
+ } catch (err: any) {
+ setError(err.message || "Failed to check pause status");
+ throw err;
+ }
+ }, [getContract]);
+
+ // Admin Functions (OWNER_ROLE)
+ const setWhitelistedChain = useCallback(
+ async (chainSelector: bigint, enabled: boolean, ccipExtraArgs: string) => {
+ setLoading(true);
+ setError(null);
+ try {
+ const contract = await getContract(true);
+ const tx = await contract.setWhitelistedChain(
+ chainSelector,
+ enabled,
+ ccipExtraArgs
+ );
+ await tx.wait();
+ } catch (err: any) {
+ setError(err.message || "Failed to set whitelisted chain");
+ throw err;
+ } finally {
+ setLoading(false);
+ }
+ },
+ [getContract]
+ );
+
+ const setWhitelistedSender = useCallback(
+ async (sender: string, enabled: boolean) => {
+ setLoading(true);
+ setError(null);
+ try {
+ const contract = await getContract(true);
+ const tx = await contract.setWhitelistedSender(sender, enabled);
+ await tx.wait();
+ } catch (err: any) {
+ setError(err.message || "Failed to set whitelisted sender");
+ throw err;
+ } finally {
+ setLoading(false);
+ }
+ },
+ [getContract]
+ );
+
+ const withdraw = useCallback(
+ async (beneficiary: string) => {
+ setLoading(true);
+ setError(null);
+ try {
+ const contract = await getContract(true);
+ const tx = await contract.withdraw(beneficiary);
+ await tx.wait();
+ } catch (err: any) {
+ setError(err.message || "Failed to withdraw ETH");
+ throw err;
+ } finally {
+ setLoading(false);
+ }
+ },
+ [getContract]
+ );
+
+ const withdrawToken = useCallback(
+ async (beneficiary: string, token: string) => {
+ setLoading(true);
+ setError(null);
+ try {
+ const contract = await getContract(true);
+ const tx = await contract.withdrawToken(beneficiary, token);
+ await tx.wait();
+ } catch (err: any) {
+ setError(err.message || "Failed to withdraw token");
+ throw err;
+ } finally {
+ setLoading(false);
+ }
+ },
+ [getContract]
+ );
+
+ const pause = useCallback(async () => {
+ setLoading(true);
+ setError(null);
+ try {
+ const contract = await getContract(true);
+ const tx = await contract.pause();
+ await tx.wait();
+ } catch (err: any) {
+ setError(err.message || "Failed to pause bridge");
+ throw err;
+ } finally {
+ setLoading(false);
+ }
+ }, [getContract]);
+
+ const unpause = useCallback(async () => {
+ setLoading(true);
+ setError(null);
+ try {
+ const contract = await getContract(true);
+ const tx = await contract.unpause();
+ await tx.wait();
+ } catch (err: any) {
+ setError(err.message || "Failed to unpause bridge");
+ throw err;
+ } finally {
+ setLoading(false);
+ }
+ }, [getContract]);
+
+ return {
+ loading,
+ error,
+ contractAddress,
+ isConnected,
+ address,
+ bridgeTokens,
+ getDestinationChainSelector,
+ getGoldToken,
+ getLink,
+ getGoldTokenBalance,
+ getLinkBalance,
+ getProcessedMessages,
+ getWhitelistedChains,
+ getWhitelistedSenders,
+ paused,
+ setWhitelistedChain,
+ setWhitelistedSender,
+ withdraw,
+ withdrawToken,
+ pause,
+ unpause,
+ };
+};
diff --git a/frontend/src/main.tsx b/frontend/src/main.tsx
new file mode 100644
index 0000000..dd64387
--- /dev/null
+++ b/frontend/src/main.tsx
@@ -0,0 +1,12 @@
+import React from "react";
+import ReactDOM from "react-dom/client";
+import App from "./App";
+import { Web3Provider } from "./components/Web3Provider";
+
+ReactDOM.createRoot(document.getElementById("root")!).render(
+
+
+
+
+
+);
diff --git a/frontend/src/styles/globals.css b/frontend/src/styles/globals.css
new file mode 100644
index 0000000..3b55bc7
--- /dev/null
+++ b/frontend/src/styles/globals.css
@@ -0,0 +1,274 @@
+:root {
+ --color-primary: #FFD700;
+ --color-primary-hover: #E6C200;
+ --color-primary-light: rgba(255, 215, 0, 0.1);
+ --color-secondary: #1F2937;
+ --color-background: #111827;
+ --color-surface: #1F2937;
+ --color-text: #F9FAFB;
+ --color-text-muted: #9CA3AF;
+ --color-border: #374151;
+ --color-success: #10B981;
+ --color-success-light: rgba(16, 185, 129, 0.1);
+ --color-error: #EF4444;
+ --color-error-light: rgba(239, 68, 68, 0.1);
+ --color-warning: #F59E0B;
+ --color-warning-light: rgba(245, 158, 11, 0.1);
+ --color-info: #3B82F6;
+ --color-info-light: rgba(59, 130, 246, 0.1);
+
+ --radius-sm: 0.25rem;
+ --radius-md: 0.375rem;
+ --radius-lg: 0.5rem;
+ --radius-xl: 0.75rem;
+
+ --shadow-sm: 0 1px 2px 0 rgba(0, 0, 0, 0.05);
+ --shadow-md: 0 4px 6px -1px rgba(0, 0, 0, 0.1), 0 2px 4px -1px rgba(0, 0, 0, 0.06);
+ --shadow-lg: 0 10px 15px -3px rgba(0, 0, 0, 0.1), 0 4px 6px -2px rgba(0, 0, 0, 0.05);
+
+ --transition-fast: 0.15s ease;
+ --transition-normal: 0.2s ease;
+ --transition-slow: 0.3s ease;
+}
+
+* {
+ box-sizing: border-box;
+ margin: 0;
+ padding: 0;
+}
+
+body {
+ font-family: Inter, system-ui, Avenir, Helvetica, Arial, sans-serif;
+ line-height: 1.5;
+ font-weight: 400;
+ color: var(--color-text);
+ background-color: var(--color-background);
+ min-height: 100vh;
+}
+
+a {
+ color: var(--color-primary);
+ text-decoration: none;
+}
+
+a:hover {
+ text-decoration: underline;
+}
+
+button {
+ cursor: pointer;
+ font-family: inherit;
+}
+
+input,
+select,
+textarea {
+ font-family: inherit;
+}
+
+/* Utility classes */
+.container {
+ max-width: 1280px;
+ margin: 0 auto;
+ padding: 1rem;
+}
+
+@media (min-width: 768px) {
+ .container {
+ padding: 1.5rem;
+ }
+}
+
+@media (min-width: 1024px) {
+ .container {
+ padding: 2rem;
+ }
+}
+
+.text-center {
+ text-align: center;
+}
+
+.text-right {
+ text-align: right;
+}
+
+.text-left {
+ text-align: left;
+}
+
+.flex {
+ display: flex;
+}
+
+.flex-col {
+ flex-direction: column;
+}
+
+.items-center {
+ align-items: center;
+}
+
+.justify-center {
+ justify-content: center;
+}
+
+.justify-between {
+ justify-content: space-between;
+}
+
+.gap-2 {
+ gap: 0.5rem;
+}
+
+.gap-4 {
+ gap: 1rem;
+}
+
+.mt-2 {
+ margin-top: 0.5rem;
+}
+
+.mt-4 {
+ margin-top: 1rem;
+}
+
+.mb-2 {
+ margin-bottom: 0.5rem;
+}
+
+.mb-4 {
+ margin-bottom: 1rem;
+}
+
+.w-full {
+ width: 100%;
+}
+
+.font-bold {
+ font-weight: 700;
+}
+
+.text-sm {
+ font-size: 0.875rem;
+}
+
+.text-lg {
+ font-size: 1.125rem;
+}
+
+.text-xl {
+ font-size: 1.25rem;
+}
+
+.text-2xl {
+ font-size: 1.5rem;
+}
+
+.text-primary {
+ color: var(--color-primary);
+}
+
+.text-muted {
+ color: var(--color-text-muted);
+}
+
+.text-error {
+ color: var(--color-error);
+}
+
+.text-success {
+ color: var(--color-success);
+}
+
+/* Scrollbar */
+::-webkit-scrollbar {
+ width: 8px;
+ height: 8px;
+}
+
+::-webkit-scrollbar-track {
+ background: var(--color-background);
+}
+
+::-webkit-scrollbar-thumb {
+ background: var(--color-border);
+ border-radius: 4px;
+}
+
+::-webkit-scrollbar-thumb:hover {
+ background: var(--color-text-muted);
+}
+
+/* Animation utilities */
+@keyframes fadeIn {
+ from {
+ opacity: 0;
+ }
+
+ to {
+ opacity: 1;
+ }
+}
+
+@keyframes slideUp {
+ from {
+ opacity: 0;
+ transform: translateY(10px);
+ }
+
+ to {
+ opacity: 1;
+ transform: translateY(0);
+ }
+}
+
+@keyframes pulse {
+
+ 0%,
+ 100% {
+ opacity: 1;
+ }
+
+ 50% {
+ opacity: 0.5;
+ }
+}
+
+.animate-fadeIn {
+ animation: fadeIn var(--transition-normal);
+}
+
+.animate-slideUp {
+ animation: slideUp var(--transition-slow);
+}
+
+/* Focus styles for accessibility */
+:focus-visible {
+ outline: 2px solid var(--color-primary);
+ outline-offset: 2px;
+}
+
+/* Selection styles */
+::selection {
+ background-color: var(--color-primary);
+ color: var(--color-background);
+}
+
+/* Emoji styling for consistent display */
+.emoji {
+ font-family: "Apple Color Emoji", "Segoe UI Emoji", "Noto Color Emoji", sans-serif;
+}
+
+/* Screen reader only */
+.sr-only {
+ position: absolute;
+ width: 1px;
+ height: 1px;
+ padding: 0;
+ margin: -1px;
+ overflow: hidden;
+ clip: rect(0, 0, 0, 0);
+ white-space: nowrap;
+ border: 0;
+}
\ No newline at end of file
diff --git a/frontend/src/types/goldToken.ts b/frontend/src/types/goldToken.ts
new file mode 100644
index 0000000..5071da0
--- /dev/null
+++ b/frontend/src/types/goldToken.ts
@@ -0,0 +1,51 @@
+export interface GoldTokenEvents {
+ FeesAddressUpdated: {
+ previousFeesAddress: string;
+ newFeesAddress: string;
+ };
+ GoldTokenInitialized: {
+ owner: string;
+ dataFeedGold: string;
+ dataFeedEth: string;
+ };
+ LotterieAddressUpdated: {
+ previousLotterieAddress: string;
+ newLotterieAddress: string;
+ };
+ Mint: {
+ to: string;
+ amount: bigint;
+ };
+ UserAdded: {
+ user: string;
+ timestamp: bigint;
+ };
+ UserRemoved: {
+ user: string;
+ };
+}
+
+export interface GoldTokenFunctions {
+ // User-Facing
+ mint: (value: bigint) => Promise;
+ burn: (amount: bigint) => Promise;
+ transfer: (to: string, amount: bigint) => Promise;
+ balanceOf: (account: string) => Promise;
+ claimEth: () => Promise;
+
+ // View Functions
+ getGoldPriceInEth: () => Promise;
+ getFees: () => Promise;
+ getFeesAddress: () => Promise;
+ getUsers: () => Promise;
+ getTimestamps: () => Promise<{ users: string[]; timestamps: bigint[] }>;
+ hasOwnerRole: (account: string) => Promise;
+
+ // Admin Functions
+ setFeesAddress: (feesAddress: string) => Promise;
+ setLotterieAddress: (lotterieAddress: string) => Promise;
+ addOwner: (account: string) => Promise;
+ removeOwner: (account: string) => Promise;
+ pause: () => Promise;
+ unpause: () => Promise;
+}
diff --git a/frontend/src/types/index.ts b/frontend/src/types/index.ts
new file mode 100644
index 0000000..9aa3244
--- /dev/null
+++ b/frontend/src/types/index.ts
@@ -0,0 +1,11 @@
+// Export your types here
+export interface User {
+ address: string;
+ balance: string;
+}
+
+export * from "./goldToken";
+
+export * from "./lotterie";
+
+export * from "./tokenBridge";
diff --git a/frontend/src/types/lotterie.ts b/frontend/src/types/lotterie.ts
new file mode 100644
index 0000000..57c3203
--- /dev/null
+++ b/frontend/src/types/lotterie.ts
@@ -0,0 +1,61 @@
+export interface LotterieEvents {
+ CallbackGasLimitUpdated: {
+ previousGasLimit: number;
+ newGasLimit: number;
+ };
+ GainClaimed: {
+ account: string;
+ amount: bigint;
+ };
+ GoldTokenUpdated: {
+ previousGoldToken: string;
+ newGoldToken: string;
+ };
+ KeyHashUpdated: {
+ previousKeyHash: string;
+ newKeyHash: string;
+ };
+ LotterieInitialized: {
+ owner: string;
+ vrfCoordinator: string;
+ goldToken: string;
+ vrfSubscriptionId: bigint;
+ keyHash: string;
+ callbackGasLimit: number;
+ requestConfirmations: number;
+ numWords: number;
+ };
+ NumWordsUpdated: {
+ previousNumWords: number;
+ newNumWords: number;
+ };
+ RandomDrawed: {
+ requestId: bigint;
+ };
+ RequestConfirmationsUpdated: {
+ previousConfirmations: number;
+ newConfirmations: number;
+ };
+ VrfCoordinatorUpdated: {
+ previousCoordinator: string;
+ newCoordinator: string;
+ };
+ VrfSubscriptionUpdated: {
+ previousSubscriptionId: bigint;
+ newSubscriptionId: bigint;
+ };
+ Winner: {
+ winner: string;
+ };
+}
+
+export interface LotterieState {
+ lastRequestId: bigint;
+ goldToken: string;
+ vrfSubscriptionId: bigint;
+ vrfCoordinator: string;
+ keyHash: string;
+ callbackGasLimit: number;
+ requestConfirmations: number;
+ numWords: number;
+}
diff --git a/frontend/src/types/tokenBridge.ts b/frontend/src/types/tokenBridge.ts
new file mode 100644
index 0000000..b8bb96f
--- /dev/null
+++ b/frontend/src/types/tokenBridge.ts
@@ -0,0 +1,85 @@
+export enum PayFeesIn {
+ Native = 0,
+ LINK = 1,
+}
+
+export interface TokenBridgeState {
+ destinationChainSelector: bigint;
+ goldToken: string;
+ link: string;
+ goldTokenBalance: bigint;
+ linkBalance: bigint;
+ isPaused: boolean;
+}
+
+export interface BridgeTokensParams {
+ receiver: string;
+ amount: bigint;
+ payFeesIn: PayFeesIn;
+}
+
+export interface SetWhitelistedChainParams {
+ chainSelector: bigint;
+ enabled: boolean;
+ ccipExtraArgs: string;
+}
+
+export interface SetWhitelistedSenderParams {
+ sender: string;
+ enabled: boolean;
+}
+
+export interface WithdrawParams {
+ beneficiary: string;
+}
+
+export interface WithdrawTokenParams {
+ beneficiary: string;
+ token: string;
+}
+
+// Events
+export interface TokensBridgedEvent {
+ messageId: string;
+ sender: string;
+ receiver: string;
+ amount: bigint;
+ destinationChainSelector: bigint;
+ feeToken: string;
+ fees: bigint;
+}
+
+export interface TokensReceivedEvent {
+ messageId: string;
+ receiver: string;
+ amount: bigint;
+ sourceChainSelector: bigint;
+}
+
+export interface ChainWhitelistedEvent {
+ chainSelector: bigint;
+}
+
+export interface ChainRemovedEvent {
+ chainSelector: bigint;
+}
+
+export interface SenderWhitelistedEvent {
+ sender: string;
+}
+
+export interface SenderRemovedEvent {
+ sender: string;
+}
+
+export interface TokenBridgeInitializedEvent {
+ owner: string;
+ link: string;
+ goldToken: string;
+ destinationChainSelector: bigint;
+}
+
+export interface MessageProcessedWithoutTokenEvent {
+ messageId: string;
+ sourceChainSelector: bigint;
+}
diff --git a/frontend/src/vite-env.d.ts b/frontend/src/vite-env.d.ts
new file mode 100644
index 0000000..d8dff50
--- /dev/null
+++ b/frontend/src/vite-env.d.ts
@@ -0,0 +1,21 @@
+///
+
+interface ImportMetaEnv {
+ readonly VITE_REOWN_PROJECT_ID: string;
+ readonly VITE_CONTRACT_ADDRESS_SEPOLIA_GOLD_TOKEN: string;
+ readonly VITE_CONTRACT_ADDRESS_SEPOLIA_LOTTERIE: string;
+ readonly VITE_CONTRACT_ADDRESS_SEPOLIA_TOKEN_BRIDGE: string;
+ readonly VITE_CONTRACT_ADDRESS_BSC_TESTNET_GOLD_TOKEN: string;
+ readonly VITE_CONTRACT_ADDRESS_BSC_TESTNET_LOTTERIE: string;
+ readonly VITE_CONTRACT_ADDRESS_BSC_TESTNET_TOKEN_BRIDGE: string;
+ readonly VITE_RPC_URL_SEPOLIA: string;
+ readonly VITE_RPC_URL_BSC_TESTNET: string;
+ readonly VITE_SITE_NAME: string;
+ readonly VITE_SITE_DESCRIPTION: string;
+ readonly VITE_SITE_URL: string;
+ readonly VITE_SITE_ICON: string;
+}
+
+interface ImportMeta {
+ readonly env: ImportMetaEnv;
+}
diff --git a/frontend/tsconfig.app.json b/frontend/tsconfig.app.json
new file mode 100644
index 0000000..d739292
--- /dev/null
+++ b/frontend/tsconfig.app.json
@@ -0,0 +1,27 @@
+{
+ "compilerOptions": {
+ "composite": true,
+ "tsBuildInfoFile": "./node_modules/.tmp/tsconfig.app.tsbuildinfo",
+ "target": "ES2020",
+ "useDefineForClassFields": true,
+ "lib": ["ES2020", "DOM", "DOM.Iterable"],
+ "module": "ESNext",
+ "skipLibCheck": true,
+
+ /* Bundler mode */
+ "moduleResolution": "bundler",
+ "allowImportingTsExtensions": true,
+ "resolveJsonModule": true,
+ "isolatedModules": true,
+ "moduleDetection": "force",
+ "noEmit": true,
+ "jsx": "react-jsx",
+
+ /* Linting */
+ "strict": true,
+ "noUnusedLocals": true,
+ "noUnusedParameters": true,
+ "noFallthroughCasesInSwitch": true
+ },
+ "include": ["src"]
+}
diff --git a/frontend/tsconfig.json b/frontend/tsconfig.json
new file mode 100644
index 0000000..c452f43
--- /dev/null
+++ b/frontend/tsconfig.json
@@ -0,0 +1,7 @@
+{
+ "files": [],
+ "references": [
+ { "path": "./tsconfig.app.json" },
+ { "path": "./tsconfig.node.json" }
+ ]
+}
\ No newline at end of file
diff --git a/frontend/tsconfig.node.json b/frontend/tsconfig.node.json
new file mode 100644
index 0000000..3afdd6e
--- /dev/null
+++ b/frontend/tsconfig.node.json
@@ -0,0 +1,13 @@
+{
+ "compilerOptions": {
+ "composite": true,
+ "tsBuildInfoFile": "./node_modules/.tmp/tsconfig.node.tsbuildinfo",
+ "skipLibCheck": true,
+ "module": "ESNext",
+ "moduleResolution": "bundler",
+ "allowSyntheticDefaultImports": true,
+ "strict": true,
+ "noEmit": true
+ },
+ "include": ["vite.config.ts"]
+}
diff --git a/frontend/vite.config.ts b/frontend/vite.config.ts
new file mode 100644
index 0000000..1ff0da0
--- /dev/null
+++ b/frontend/vite.config.ts
@@ -0,0 +1,7 @@
+import react from "@vitejs/plugin-react";
+import { defineConfig } from "vite";
+
+// https://vitejs.dev/config/
+export default defineConfig({
+ plugins: [react()],
+});
diff --git a/lcov.info b/lcov.info
index 451c17b..66b22a6 100644
--- a/lcov.info
+++ b/lcov.info
@@ -1,23 +1,23 @@
TN:
SF:src/GoldToken.sol
-DA:65,375
+DA:65,378
FN:65,GoldToken.constructor
-FNDA:375,GoldToken.constructor
-DA:66,375
-DA:70,373
+FNDA:378,GoldToken.constructor
+DA:66,378
+DA:70,376
FN:70,GoldToken.initialize
-FNDA:373,GoldToken.initialize
-DA:75,373
-DA:76,373
-DA:77,373
-DA:79,373
-DA:81,373
-DA:83,373
-DA:86,373
-DA:90,373
-DA:91,373
-DA:92,373
-DA:94,373
+FNDA:376,GoldToken.initialize
+DA:75,376
+DA:76,376
+DA:77,376
+DA:79,376
+DA:81,376
+DA:83,376
+DA:86,376
+DA:90,376
+DA:91,376
+DA:92,376
+DA:94,376
DA:98,2
FN:98,GoldToken._authorizeUpgrade
FNDA:2,GoldToken._authorizeUpgrade
@@ -43,12 +43,12 @@ FNDA:70,GoldToken.setFeesAddress
DA:129,70
DA:130,70
DA:131,70
-DA:135,380
+DA:135,383
FN:135,GoldToken.setLotterieAddress
-FNDA:380,GoldToken.setLotterieAddress
-DA:136,380
-DA:137,380
-DA:138,380
+FNDA:383,GoldToken.setLotterieAddress
+DA:136,383
+DA:137,383
+DA:138,383
DA:142,257
FN:142,GoldToken.pause
FNDA:257,GoldToken.pause
@@ -57,29 +57,29 @@ DA:147,257
FN:147,GoldToken.unpause
FNDA:257,GoldToken.unpause
DA:148,257
-DA:159,12756
+DA:159,12735
FN:159,GoldToken.mint
-FNDA:12756,GoldToken.mint
-DA:160,12499
+FNDA:12735,GoldToken.mint
+DA:160,12478
BRDA:160,1,0,1
DA:161,1
-DA:164,12498
-DA:165,12498
+DA:164,12477
+DA:165,12477
BRDA:165,2,0,6
DA:166,6
-DA:171,12492
-DA:172,12492
-DA:173,12492
+DA:171,12471
+DA:172,12471
+DA:173,12471
BRDA:173,3,0,10
DA:174,10
-DA:177,12482
-DA:179,12482
-DA:180,12482
-DA:182,12482
-DA:184,12482
-DA:185,12482
-DA:186,12482
-DA:188,12482
+DA:177,12461
+DA:179,12461
+DA:180,12461
+DA:182,12461
+DA:184,12461
+DA:185,12461
+DA:186,12461
+DA:188,12461
DA:192,515
FN:192,GoldToken.burn
FNDA:515,GoldToken.burn
@@ -94,38 +94,38 @@ DA:201,2104
BRDA:201,5,0,1
DA:202,1
DA:204,2103
-BRDA:204,6,0,318
-DA:205,318
+BRDA:204,6,0,322
+DA:205,322
DA:207,2103
DA:208,2103
DA:209,2103
-DA:213,800
+DA:213,804
FN:213,GoldToken._removeUser
-FNDA:800,GoldToken._removeUser
-DA:214,800
-DA:215,800
-DA:216,800
-DA:217,802
-BRDA:217,7,0,780
-DA:218,780
-DA:219,780
-DA:220,780
-DA:221,780
-DA:227,14585
+FNDA:804,GoldToken._removeUser
+DA:214,804
+DA:215,804
+DA:216,804
+DA:217,806
+BRDA:217,7,0,782
+DA:218,782
+DA:219,782
+DA:220,782
+DA:221,782
+DA:227,14564
FN:227,GoldToken._addUser
-FNDA:14585,GoldToken._addUser
-DA:228,14585
-BRDA:228,8,0,14107
-DA:229,14107
-DA:230,14107
-DA:231,14107
-DA:240,1027
+FNDA:14564,GoldToken._addUser
+DA:228,14564
+BRDA:228,8,0,14087
+DA:229,14087
+DA:230,14087
+DA:231,14087
+DA:240,1026
FN:240,GoldToken.getGoldPriceInEth
-FNDA:1027,GoldToken.getGoldPriceInEth
-DA:241,13525
-DA:242,13525
-DA:244,13525
-DA:245,13525
+FNDA:1026,GoldToken.getGoldPriceInEth
+DA:241,13503
+DA:242,13503
+DA:244,13503
+DA:245,13503
DA:249,1
FN:249,GoldToken.getFees
FNDA:1,GoldToken.getFees
@@ -134,10 +134,10 @@ DA:254,27
FN:254,GoldToken.getFeesAddress
FNDA:27,GoldToken.getFeesAddress
DA:255,27
-DA:259,2935
+DA:259,2921
FN:259,GoldToken.getUsers
-FNDA:2935,GoldToken.getUsers
-DA:260,2935
+FNDA:2921,GoldToken.getUsers
+DA:260,2921
DA:264,257
FN:264,GoldToken.getTimestamps
FNDA:257,GoldToken.getTimestamps
@@ -150,10 +150,10 @@ DA:274,2
FN:274,GoldToken.hasOwnerRole
FNDA:2,GoldToken.hasOwnerRole
DA:275,2
-DA:279,16925
+DA:279,16872
FN:279,GoldToken.balanceOf
-FNDA:16925,GoldToken.balanceOf
-DA:280,18508
+FNDA:16872,GoldToken.balanceOf
+DA:280,18457
FNF:22
FNH:22
LF:101
@@ -163,25 +163,27 @@ BRH:9
end_of_record
TN:
SF:src/Lotterie.sol
-DA:72,33
-FN:72,Lotterie.constructor
-FNDA:33,Lotterie.constructor
-DA:73,33
-DA:77,31
-FN:77,Lotterie.initialize
-FNDA:31,Lotterie.initialize
-DA:87,31
-DA:89,31
-DA:91,31
-DA:93,31
-DA:94,31
-DA:95,31
-DA:96,31
-DA:97,31
-DA:98,31
-DA:100,31
-DA:101,31
-DA:103,31
+DA:78,36
+FN:78,Lotterie.constructor
+FNDA:36,Lotterie.constructor
+DA:79,36
+DA:83,34
+FN:83,Lotterie.initialize
+FNDA:34,Lotterie.initialize
+DA:84,34
+DA:86,34
+DA:88,34
+DA:90,34
+DA:91,34
+DA:92,34
+DA:93,34
+DA:94,34
+DA:95,34
+DA:96,34
+DA:97,34
+DA:98,34
+DA:99,34
+DA:101,34
DA:115,2
FN:115,Lotterie._authorizeUpgrade
FNDA:2,Lotterie._authorizeUpgrade
@@ -235,98 +237,118 @@ FNDA:257,Lotterie.setGoldToken
DA:179,257
DA:180,257
DA:181,257
-DA:189,2680
-FN:189,Lotterie.randomDraw
-FNDA:2680,Lotterie.randomDraw
-DA:190,2680
-BRDA:190,0,0,251
-DA:191,251
-DA:194,2429
-DA:206,2429
-DA:207,2429
-DA:208,2429
-DA:209,2429
-DA:212,2166
-FN:212,Lotterie.fulfillRandomWords
-FNDA:2166,Lotterie.fulfillRandomWords
-DA:214,2166
-DA:215,2166
-DA:217,2165
-DA:218,2165
-DA:220,2165
-DA:224,259
-FN:224,Lotterie.claim
+DA:185,257
+FN:185,Lotterie.setRandomDrawCooldown
+FNDA:257,Lotterie.setRandomDrawCooldown
+DA:186,257
+DA:187,257
+DA:188,257
+DA:192,257
+FN:192,Lotterie.setVrfNativePayment
+FNDA:257,Lotterie.setVrfNativePayment
+DA:193,257
+DA:194,257
+DA:195,257
+DA:203,2666
+FN:203,Lotterie.randomDraw
+FNDA:2666,Lotterie.randomDraw
+DA:204,2666
+BRDA:204,0,0,227
+DA:205,227
+DA:208,2439
+DA:219,2439
+DA:220,2439
+DA:221,2439
+DA:222,2439
+DA:225,2152
+FN:225,Lotterie.fulfillRandomWords
+FNDA:2152,Lotterie.fulfillRandomWords
+DA:227,2152
+DA:228,2152
+DA:230,2151
+DA:231,2151
+DA:233,2151
+DA:237,259
+FN:237,Lotterie.claim
FNDA:259,Lotterie.claim
-DA:225,259
-DA:226,259
-BRDA:226,1,0,1
-DA:227,1
-DA:229,258
-DA:230,258
-DA:231,258
-BRDA:231,2,0,1
-DA:232,1
-DA:234,257
-DA:238,2
-FN:238,Lotterie.hasOwnerRole
+DA:238,259
+DA:239,259
+BRDA:239,1,0,1
+DA:240,1
+DA:242,258
+DA:243,258
+DA:244,258
+BRDA:244,2,0,1
+DA:245,1
+DA:247,257
+DA:251,2
+FN:251,Lotterie.hasOwnerRole
FNDA:2,Lotterie.hasOwnerRole
-DA:239,2
-DA:243,2
-FN:243,Lotterie.getLastRequestId
+DA:252,2
+DA:256,2
+FN:256,Lotterie.getLastRequestId
FNDA:2,Lotterie.getLastRequestId
-DA:244,2
-BRDA:244,3,0,1
-DA:245,1
-DA:247,1
-DA:251,1028
-FN:251,Lotterie.getGains
+DA:257,2
+BRDA:257,3,0,1
+DA:258,1
+DA:260,1
+DA:264,1028
+FN:264,Lotterie.getGains
FNDA:1028,Lotterie.getGains
-DA:252,1028
-DA:256,2167
-FN:256,Lotterie.getResults
-FNDA:2167,Lotterie.getResults
-DA:257,2167
-DA:261,2
-FN:261,Lotterie.getVrfCoordinator
+DA:265,1028
+DA:269,2153
+FN:269,Lotterie.getResults
+FNDA:2153,Lotterie.getResults
+DA:270,2153
+DA:274,2
+FN:274,Lotterie.getVrfCoordinator
FNDA:2,Lotterie.getVrfCoordinator
-DA:262,2
-DA:266,2
-FN:266,Lotterie.getKeyHash
+DA:275,2
+DA:279,2
+FN:279,Lotterie.getKeyHash
FNDA:2,Lotterie.getKeyHash
-DA:267,2
-DA:271,258
-FN:271,Lotterie.getCallbackGasLimit
+DA:280,2
+DA:284,258
+FN:284,Lotterie.getCallbackGasLimit
FNDA:258,Lotterie.getCallbackGasLimit
-DA:272,258
-DA:276,258
-FN:276,Lotterie.getRequestConfirmations
+DA:285,258
+DA:289,258
+FN:289,Lotterie.getRequestConfirmations
FNDA:258,Lotterie.getRequestConfirmations
-DA:277,258
-DA:281,258
-FN:281,Lotterie.getNumWords
+DA:290,258
+DA:294,258
+FN:294,Lotterie.getNumWords
FNDA:258,Lotterie.getNumWords
-DA:282,258
-DA:286,257
-FN:286,Lotterie.getGoldToken
+DA:295,258
+DA:299,257
+FN:299,Lotterie.getGoldToken
FNDA:257,Lotterie.getGoldToken
-DA:287,257
-DA:291,258
-FN:291,Lotterie.getVrfSubscriptionId
+DA:300,257
+DA:304,258
+FN:304,Lotterie.getVrfSubscriptionId
FNDA:258,Lotterie.getVrfSubscriptionId
-DA:292,258
-FNF:26
-FNH:26
-LF:95
-LH:95
+DA:305,258
+DA:309,2
+FN:309,Lotterie.getRandomDrawCooldown
+FNDA:2,Lotterie.getRandomDrawCooldown
+DA:310,2
+DA:314,258
+FN:314,Lotterie.getVrfNativePayment
+FNDA:258,Lotterie.getVrfNativePayment
+DA:315,258
+FNF:30
+FNH:30
+LF:109
+LH:109
BRF:4
BRH:4
end_of_record
TN:
SF:src/TokenBridge.sol
-DA:87,522
+DA:87,520
FN:87,TokenBridge.onlyEnabledChain
-FNDA:522,TokenBridge.onlyEnabledChain
-DA:88,522
+FNDA:520,TokenBridge.onlyEnabledChain
+DA:88,520
DA:97,54
FN:97,TokenBridge.constructor
FNDA:54,TokenBridge.constructor
@@ -362,30 +384,30 @@ DA:168,1
FN:168,TokenBridge.removeOwner
FNDA:1,TokenBridge.removeOwner
DA:169,1
-DA:177,523
+DA:177,521
FN:177,TokenBridge.bridgeTokens
-FNDA:523,TokenBridge.bridgeTokens
-DA:184,522
-DA:185,522
-DA:195,522
+FNDA:521,TokenBridge.bridgeTokens
+DA:184,520
+DA:185,520
+DA:195,520
FN:195,TokenBridge._bridgeTokens
-FNDA:522,TokenBridge._bridgeTokens
-DA:200,521
+FNDA:520,TokenBridge._bridgeTokens
+DA:200,519
BRDA:200,1,0,1
-DA:201,520
+DA:201,518
BRDA:201,2,0,1
-DA:203,519
-DA:204,519
-DA:206,519
-DA:207,519
-DA:209,519
-DA:211,519
-DA:219,519
-DA:220,519
-DA:222,519
-BRDA:222,3,0,421
+DA:203,517
+DA:204,517
+DA:206,517
+DA:207,517
+DA:209,517
+DA:211,517
+DA:219,517
+DA:220,517
+DA:222,517
+BRDA:222,3,0,419
BRDA:222,3,1,1
-DA:223,421
+DA:223,419
BRDA:223,4,0,1
DA:225,98
BRDA:225,5,0,2
@@ -394,71 +416,71 @@ DA:227,2
BRDA:227,6,0,1
DA:228,1
DA:230,1
-DA:234,517
-DA:236,517
-DA:238,517
-DA:246,1293
+DA:234,515
+DA:236,515
+DA:238,515
+DA:246,1289
FN:246,TokenBridge._ccipReceive
-FNDA:1293,TokenBridge._ccipReceive
-DA:247,258
-BRDA:247,7,0,258
-DA:248,258
-DA:251,1034
+FNDA:1289,TokenBridge._ccipReceive
+DA:247,257
+BRDA:247,7,0,257
+DA:248,257
+DA:251,1031
BRDA:251,8,0,1
DA:252,1
-DA:255,1033
-DA:256,1033
+DA:255,1030
+DA:256,1030
BRDA:256,9,0,277
-DA:258,756
-DA:259,756
+DA:258,753
+DA:259,753
BRDA:259,10,0,1
-DA:261,755
-DA:262,755
-DA:264,755
-DA:265,755
-BRDA:265,11,0,516
-DA:266,516
-DA:267,516
-BRDA:267,12,0,516
-DA:268,516
-DA:269,516
-DA:271,516
+DA:261,752
+DA:262,752
+DA:264,752
+DA:265,752
+BRDA:265,11,0,515
+DA:266,515
+DA:267,515
+BRDA:267,12,0,515
+DA:268,515
+DA:269,515
+DA:271,515
BRDA:271,13,0,1
-DA:273,515
-DA:275,515
-DA:277,515
-DA:282,754
-BRDA:282,14,0,239
-DA:283,239
-DA:284,239
-DA:293,522
+DA:273,514
+DA:275,514
+DA:277,514
+DA:282,751
+BRDA:282,14,0,237
+DA:283,237
+DA:284,237
+DA:293,520
FN:293,TokenBridge._onlyEnabledChain
-FNDA:522,TokenBridge._onlyEnabledChain
-DA:294,522
+FNDA:520,TokenBridge._onlyEnabledChain
+DA:294,520
BRDA:294,15,0,1
DA:295,1
-DA:304,1079
+DA:304,1077
FN:304,TokenBridge.setWhitelistedChain
-FNDA:1079,TokenBridge.setWhitelistedChain
-DA:309,1079
+FNDA:1077,TokenBridge.setWhitelistedChain
+DA:309,1077
BRDA:309,16,0,1
-DA:311,1078
-DA:313,1076
-BRDA:313,17,0,1076
+DA:311,1076
+DA:313,1074
+BRDA:313,17,0,1074
BRDA:313,17,1,2
-DA:314,1076
+DA:314,1074
DA:316,2
-DA:321,824
+DA:321,821
FN:321,TokenBridge.setWhitelistedSender
-FNDA:824,TokenBridge.setWhitelistedSender
-DA:322,824
+FNDA:821,TokenBridge.setWhitelistedSender
+DA:322,821
BRDA:322,18,0,1
-DA:323,823
-DA:324,545
-BRDA:324,19,0,545
-BRDA:324,19,1,278
-DA:325,545
-DA:327,278
+DA:323,820
+DA:324,543
+BRDA:324,19,0,543
+BRDA:324,19,1,277
+DA:325,543
+DA:327,277
DA:335,857
FN:335,TokenBridge.pause
FNDA:857,TokenBridge.pause
@@ -478,17 +500,17 @@ BRDA:358,21,0,1
DA:360,259
DA:361,259
BRDA:361,22,0,1
-DA:365,262
+DA:365,261
FN:365,TokenBridge.withdrawToken
-FNDA:262,TokenBridge.withdrawToken
-DA:366,262
+FNDA:261,TokenBridge.withdrawToken
+DA:366,261
BRDA:366,23,0,1
-DA:367,261
+DA:367,260
BRDA:367,24,0,1
-DA:369,260
-DA:370,260
+DA:369,259
+DA:370,259
BRDA:370,25,0,1
-DA:372,259
+DA:372,258
DA:380,259
FN:380,TokenBridge.whitelistedChains
FNDA:259,TokenBridge.whitelistedChains
diff --git a/script/deployCoreContracts.s.sol b/script/deployCoreContracts.s.sol
index 078408a..52a862f 100644
--- a/script/deployCoreContracts.s.sol
+++ b/script/deployCoreContracts.s.sol
@@ -4,6 +4,7 @@ pragma solidity 0.8.28;
import {Script, console2} from "forge-std/Script.sol";
import {GoldToken} from "../src/GoldToken.sol";
import {Lotterie} from "../src/Lotterie.sol";
+import {ILotterie} from "../src/interfaces/ILotterie.sol";
import {TokenBridge} from "../src/TokenBridge.sol";
import {ERC1967Proxy} from "@openzeppelin/contracts/proxy/ERC1967/ERC1967Proxy.sol";
@@ -69,9 +70,10 @@ contract DeployCoreContracts is Script {
});
// Chainlink VRF parameters (same for both networks)
- uint32 constant CALLBACK_GAS_LIMIT = 40000;
+ uint32 constant CALLBACK_GAS_LIMIT = 40_000;
uint16 constant REQUEST_CONFIRMATIONS = 3;
uint32 constant NUM_WORDS = 1;
+ uint32 constant RANDOM_DRAW_COOLDOWN = 5 minutes; // low cooldown set for testing purposes
function run() external {
uint256 deployerPrivateKey = vm.envUint("PRIVATE_KEY");
@@ -108,14 +110,17 @@ contract DeployCoreContracts is Script {
bytes memory lotterieData = abi.encodeWithSelector(
Lotterie.initialize.selector,
- deployer,
- config.vrfSubscriptionId,
- config.vrfCoordinator,
- config.keyHash,
- CALLBACK_GAS_LIMIT,
- REQUEST_CONFIRMATIONS,
- NUM_WORDS,
- address(goldToken)
+ ILotterie.LotterieConfig({
+ owner: deployer,
+ vrfSubscriptionId: config.vrfSubscriptionId,
+ vrfCoordinator: config.vrfCoordinator,
+ keyHash: config.keyHash,
+ callbackGasLimit: CALLBACK_GAS_LIMIT,
+ requestConfirmations: REQUEST_CONFIRMATIONS,
+ numWords: NUM_WORDS,
+ randomDrawCooldown: RANDOM_DRAW_COOLDOWN,
+ goldToken: address(goldToken)
+ })
);
ERC1967Proxy lotterieProxy = new ERC1967Proxy(address(lotterieImpl), lotterieData);
Lotterie lotterie = Lotterie(address(lotterieProxy));
diff --git a/script/deployCoreContractsDefender.s.sol b/script/deployCoreContractsDefender.s.sol
index 4b8e25f..0372868 100644
--- a/script/deployCoreContractsDefender.s.sol
+++ b/script/deployCoreContractsDefender.s.sol
@@ -4,6 +4,7 @@ pragma solidity 0.8.28;
import {Script, console2} from "forge-std/Script.sol";
import {GoldToken} from "../src/GoldToken.sol";
import {Lotterie} from "../src/Lotterie.sol";
+import {ILotterie} from "../src/interfaces/ILotterie.sol";
import {TokenBridge} from "../src/TokenBridge.sol";
import {ApprovalProcessResponse, Defender} from "openzeppelin-foundry-upgrades/Defender.sol";
import {Options, Upgrades} from "openzeppelin-foundry-upgrades/Upgrades.sol";
@@ -15,16 +16,17 @@ import {Options, Upgrades} from "openzeppelin-foundry-upgrades/Upgrades.sol";
* openzeppelin-foundry-upgrades so relayers/Safe approvals can manage ownership.
*/
contract DeployCoreContractsWithDefender is Script {
+ // Network specific configurations
struct NetworkConfig {
- address router;
- address link;
- uint256 vrfSubscriptionId;
- uint64 chainSelector;
- uint64 destSelector;
- address goldUsdFeed;
- address ethUsdFeed;
- address vrfCoordinator;
- bytes32 keyHash;
+ address router; // CCIP Router
+ address link; // LINK Token
+ uint256 vrfSubscriptionId; // VRF Subscription ID
+ uint64 chainSelector; // This chain's selector
+ uint64 destSelector; // Destination chain's selector
+ address goldUsdFeed; // Gold/USD price feed
+ address ethUsdFeed; // ETH/USD or BNB/USD price feed
+ address vrfCoordinator; // VRF Coordinator
+ bytes32 keyHash; // VRF key hash
}
error UnsupportedNetwork(uint256 chainId);
@@ -56,9 +58,10 @@ contract DeployCoreContractsWithDefender is Script {
keyHash: 0x8596b430971ac45bdf6088665b9ad8e8630c9d5049ab54b14dff711bee7c0e26
});
- uint32 constant CALLBACK_GAS_LIMIT = 40000;
+ uint32 constant CALLBACK_GAS_LIMIT = 40_000;
uint16 constant REQUEST_CONFIRMATIONS = 3;
uint32 constant NUM_WORDS = 1;
+ uint32 constant RANDOM_DRAW_COOLDOWN = 1 days;
function run() external {
NetworkConfig memory config = _currentNetwork();
@@ -79,16 +82,17 @@ contract DeployCoreContractsWithDefender is Script {
"src/Lotterie.sol",
abi.encodeCall(
Lotterie.initialize,
- (
- owner,
- config.vrfSubscriptionId,
- config.vrfCoordinator,
- config.keyHash,
- CALLBACK_GAS_LIMIT,
- REQUEST_CONFIRMATIONS,
- NUM_WORDS,
- goldTokenProxy
- )
+ (ILotterie.LotterieConfig({
+ owner: owner,
+ vrfSubscriptionId: config.vrfSubscriptionId,
+ vrfCoordinator: config.vrfCoordinator,
+ keyHash: config.keyHash,
+ callbackGasLimit: CALLBACK_GAS_LIMIT,
+ requestConfirmations: REQUEST_CONFIRMATIONS,
+ numWords: NUM_WORDS,
+ randomDrawCooldown: RANDOM_DRAW_COOLDOWN,
+ goldToken: goldTokenProxy
+ }))
),
lotterieOpts
);
diff --git a/src/GoldToken.sol b/src/GoldToken.sol
index f8c6387..17b0cef 100644
--- a/src/GoldToken.sol
+++ b/src/GoldToken.sol
@@ -260,6 +260,16 @@ contract GoldToken is
return _users;
}
+ /// @inheritdoc IGoldToken
+ function getUserByIndex(uint256 index) external view override returns (address) {
+ return _users[index];
+ }
+
+ /// @inheritdoc IGoldToken
+ function getUserCount() external view override returns (uint256) {
+ return _users.length;
+ }
+
/// @inheritdoc IGoldToken
function getTimestamps() external view override returns (address[] memory, uint256[] memory) {
uint256 length = _users.length;
diff --git a/src/Lotterie.sol b/src/Lotterie.sol
index c3556d2..372b53b 100644
--- a/src/Lotterie.sol
+++ b/src/Lotterie.sol
@@ -47,12 +47,15 @@ contract Lotterie is
/// @notice Amount of random words requested per draw
uint32 internal _numWords;
- /// @notice GoldToken proxy feeding participant balances and payouts
- IGoldToken internal _goldToken;
+ /// @notice randomDrawCooldown amount of time required between draws
+ uint256 internal _randomDrawCooldown;
- /// @notice Timestamp of the most recent draw, used to enforce the daily cadence
+ /// @notice Timestamp of the most recent draw, used to enforce the cooldown period
uint256 internal _lastRandomDraw;
+ /// @notice GoldToken proxy feeding participant balances and payouts
+ IGoldToken internal _goldToken;
+
/// @notice Historical record of VRF request identifiers
uint256[] internal _requestIds;
@@ -74,41 +77,33 @@ contract Lotterie is
}
/// @inheritdoc ILotterie
- function initialize(
- address owner,
- uint256 vrfSubscriptionId,
- address vrfCoordinator,
- bytes32 keyHash,
- uint32 callbackGasLimit,
- uint16 requestConfirmations,
- uint32 numWords,
- address goldToken
- ) external override initializer {
+ function initialize(LotterieConfig calldata config) external override initializer {
__AccessControl_init();
- _grantRole(OWNER_ROLE, owner);
+ _grantRole(OWNER_ROLE, config.owner);
_setRoleAdmin(OWNER_ROLE, OWNER_ROLE);
- _vrfSubscriptionId = vrfSubscriptionId;
- s_vrfCoordinator = IVRFCoordinatorV2Plus(vrfCoordinator);
- _vrfKeyHash = keyHash;
- _callbackGasLimit = callbackGasLimit; // 40000
- _requestConfirmations = requestConfirmations; // 3
- _numWords = numWords; // 1
-
+ _vrfSubscriptionId = config.vrfSubscriptionId;
+ s_vrfCoordinator = IVRFCoordinatorV2Plus(config.vrfCoordinator);
+ _vrfKeyHash = config.keyHash;
+ _callbackGasLimit = config.callbackGasLimit;
+ _requestConfirmations = config.requestConfirmations;
+ _numWords = config.numWords;
+ _randomDrawCooldown = config.randomDrawCooldown;
_lastRandomDraw = block.timestamp - 1 days;
- _goldToken = IGoldToken(goldToken);
+ _goldToken = IGoldToken(config.goldToken);
emit LotterieInitialized(
- owner,
- vrfCoordinator,
- goldToken,
- vrfSubscriptionId,
- keyHash,
- callbackGasLimit,
- requestConfirmations,
- numWords
+ config.owner,
+ config.vrfCoordinator,
+ config.goldToken,
+ config.vrfSubscriptionId,
+ config.keyHash,
+ config.callbackGasLimit,
+ config.requestConfirmations,
+ config.numWords,
+ config.randomDrawCooldown
);
}
@@ -181,14 +176,21 @@ contract Lotterie is
emit GoldTokenUpdated(previous, goldToken);
}
+ /// @inheritdoc ILotterie
+ function setRandomDrawCooldown(uint256 randomDrawCooldown) external override onlyRole(OWNER_ROLE) {
+ uint256 previous = _randomDrawCooldown;
+ _randomDrawCooldown = randomDrawCooldown;
+ emit RandomDrawCooldownUpdated(previous, randomDrawCooldown);
+ }
+
/*//////////////////////////////////////////////////////////////
CORE FUNCTIONS
//////////////////////////////////////////////////////////////*/
/// @inheritdoc ILotterie
- function randomDraw() external override onlyRole(OWNER_ROLE) returns (uint256) {
- if (_lastRandomDraw + 1 days > block.timestamp) {
- revert OneRandomDrawPerDay();
+ function randomDraw(bool enableNativePayment) external override onlyRole(OWNER_ROLE) returns (uint256) {
+ if (_lastRandomDraw + _randomDrawCooldown > block.timestamp) {
+ revert DrawCooldownNotExpired(_lastRandomDraw, _randomDrawCooldown, block.timestamp);
}
uint256 requestId = s_vrfCoordinator.requestRandomWords(
@@ -198,8 +200,9 @@ contract Lotterie is
requestConfirmations: _requestConfirmations,
callbackGasLimit: _callbackGasLimit,
numWords: _numWords,
- // Set nativePayment to true to pay for VRF requests with Sepolia ETH instead of LINK
- extraArgs: VRFV2PlusClient._argsToBytes(VRFV2PlusClient.ExtraArgsV1({nativePayment: false}))
+ extraArgs: VRFV2PlusClient._argsToBytes(
+ VRFV2PlusClient.ExtraArgsV1({nativePayment: enableNativePayment})
+ )
})
);
@@ -210,14 +213,19 @@ contract Lotterie is
}
function fulfillRandomWords(uint256 requestId, uint256[] calldata randomWords) internal override {
- // transform the result to a number between 0 and number of participants
- address[] memory users = _goldToken.getUsers();
- uint256 index = (randomWords[0] % users.length);
+ uint256 userCount = _goldToken.getUserCount();
+ if (userCount == 0) {
+ emit Winner(address(0));
+ return;
+ }
- _results[requestId] = users[index];
- _gains[users[index]] = _goldToken.balanceOf(address(this));
+ uint256 index = (randomWords[0] % userCount);
+ address winner = _goldToken.getUserByIndex(index);
- emit Winner(users[index]);
+ _results[requestId] = winner;
+ _gains[winner] = _goldToken.balanceOf(address(this));
+
+ emit Winner(winner);
}
/// @inheritdoc ILotterie
@@ -291,4 +299,9 @@ contract Lotterie is
function getVrfSubscriptionId() external view override returns (uint256) {
return _vrfSubscriptionId;
}
+
+ /// @inheritdoc ILotterie
+ function getRandomDrawCooldown() external view override returns (uint256) {
+ return _randomDrawCooldown;
+ }
}
diff --git a/src/interfaces/IGoldToken.sol b/src/interfaces/IGoldToken.sol
index 29fd64a..4df1829 100644
--- a/src/interfaces/IGoldToken.sol
+++ b/src/interfaces/IGoldToken.sol
@@ -10,6 +10,7 @@ interface IGoldToken {
/*//////////////////////////////////////////////////////////////
EVENTS
//////////////////////////////////////////////////////////////*/
+
/**
* @notice Emitted once during proxy initialization to capture deployment context
* @param owner Address granted OWNER_ROLE and set as initial fee recipient
@@ -55,44 +56,60 @@ interface IGoldToken {
/*//////////////////////////////////////////////////////////////
ERRORS
//////////////////////////////////////////////////////////////*/
+
/// @notice Thrown when a function expecting a positive ETH value receives zero
error ValueMustBeGreaterThanZero();
+
/// @notice Thrown when a mint, burn, or transfer amount is zero
error AmountMustBeGreaterThanZero();
+
/// @notice Thrown when Chainlink feeds yield a non-positive gold price in ETH
error InvalidGoldPrice();
+
/// @notice Thrown when withdrawing ETH to an owner fails
error EthTransferFailed();
/*//////////////////////////////////////////////////////////////
ADMIN FUNCTIONS
//////////////////////////////////////////////////////////////*/
- /// @notice Grants OWNER_ROLE to a new account
- /// @param account Address receiving OWNER_ROLE
+
+ /**
+ * @notice Grants OWNER_ROLE to a new account
+ * @param account Address receiving OWNER_ROLE
+ */
function addOwner(address account) external;
- /// @notice Revokes OWNER_ROLE from an account
- /// @param account Address losing OWNER_ROLE
+
+ /**
+ * @notice Revokes OWNER_ROLE from an account
+ * @param account Address losing OWNER_ROLE
+ */
function removeOwner(address account) external;
+
/// @notice Pauses minting and burning operations
function pause() external;
+
/// @notice Resumes minting and burning operations
function unpause() external;
+
/**
* @notice Updates the recipient of protocol fees
* @param feesAddress Address receiving fees minted during token operations
*/
function setFeesAddress(address feesAddress) external;
+
/**
* @notice Sets the Lotterie contract address used for fee distribution and user tracking
* @param lotterieAddress Address of the Lotterie contract
*/
function setLotterieAddress(address lotterieAddress) external;
+
/// @notice Withdraws the entire ETH balance accumulated in the token contract
function claimEth() external;
/*//////////////////////////////////////////////////////////////
CORE FUNCTIONS
//////////////////////////////////////////////////////////////*/
+
/**
* @notice Initializes the proxy with owner credentials and Chainlink price feeds
* @param owner Address granted OWNER_ROLE and initial fee recipient
@@ -103,11 +120,13 @@ interface IGoldToken {
/// @notice Converts supplied ETH into GLD using Chainlink prices and mints tokens
function mint() external payable;
+
/**
* @notice Burns GLD from the caller and updates lottery eligibility bookkeeping
* @param amount Amount of GLD to burn
*/
function burn(uint256 amount) external;
+
/**
* @notice Transfers GLD while keeping user eligibility data in sync
* @param to Recipient address
@@ -119,32 +138,58 @@ interface IGoldToken {
/*//////////////////////////////////////////////////////////////
VIEW FUNCTIONS
//////////////////////////////////////////////////////////////*/
- /// @notice Returns the protocol fee percentage expressed in whole percents
- /// @return Protocol fee percentage applied to mint/burn amounts
+
+ /**
+ * @notice Returns the protocol fee percentage expressed in whole percents
+ * @return Protocol fee percentage applied to mint/burn amounts
+ */
function getFees() external view returns (uint256);
- /// @notice Returns the address receiving protocol fees
- /// @return Fee recipient address
+
+ /**
+ * @notice Returns the address receiving protocol fees
+ * @return Fee recipient address
+ */
function getFeesAddress() external view returns (address);
- /// @notice Returns the list of lottery-eligible users tracked by GoldToken
- /// @return Array of user addresses
+
+ /**
+ * @notice Returns the list of lottery-eligible users tracked by GoldToken
+ * @return Array of user addresses
+ */
function getUsers() external view returns (address[] memory);
+
+ /**
+ * @notice Returns the user at a specific index in the tracked users array
+ * @param index Index of the user to retrieve
+ * @return User address at the specified index
+ */
+ function getUserByIndex(uint256 index) external view returns (address);
+
+ /**
+ * @notice Returns the total number of tracked users
+ * @return Total count of users
+ */
+ function getUserCount() external view returns (uint256);
+
/**
* @notice Returns users alongside their latest eligibility timestamps
* @return users Array of tracked addresses
* @return timestamps Array of UNIX timestamps matching the users array
*/
function getTimestamps() external view returns (address[] memory, uint256[] memory);
+
/**
* @notice Checks whether an account owns OWNER_ROLE
* @param account Address to inspect
* @return True if OWNER_ROLE is assigned to the account
*/
function hasOwnerRole(address account) external view returns (bool);
+
/**
* @notice Returns the Chainlink-derived gold price expressed in ETH with 18 decimals
* @return Gold price in ETH scaled by 1e18
*/
function getGoldPriceInEth() external view returns (int256);
+
/**
* @notice Returns the GLD balance of an account
* @param account Address to query
diff --git a/src/interfaces/ILotterie.sol b/src/interfaces/ILotterie.sol
index 58c567d..635bf2d 100644
--- a/src/interfaces/ILotterie.sol
+++ b/src/interfaces/ILotterie.sol
@@ -7,14 +7,44 @@ pragma solidity 0.8.28;
* @dev Consumed by GoldToken, deployment scripts, and monitoring infrastructure
*/
interface ILotterie {
+ /*//////////////////////////////////////////////////////////////
+ STRUCTS
+ //////////////////////////////////////////////////////////////*/
+
+ /**
+ * @notice Configuration struct used during Lotterie initialization
+ * @param owner Address granted OWNER_ROLE
+ * @param vrfSubscriptionId Subscription id funding VRF requests
+ * @param vrfCoordinator Address of the VRF coordinator
+ * @param keyHash Chainlink VRF key hash used for randomness
+ * @param callbackGasLimit Gas limit allocated for fulfillRandomWords
+ * @param requestConfirmations Number of confirmations required for VRF responses
+ * @param numWords Number of random words requested per draw
+ * @param randomDrawCooldown Minimum time between draws
+ * @param goldToken Address of the GoldToken proxy
+ */
+ struct LotterieConfig {
+ address owner;
+ uint256 vrfSubscriptionId;
+ address vrfCoordinator;
+ bytes32 keyHash;
+ uint32 callbackGasLimit;
+ uint16 requestConfirmations;
+ uint32 numWords;
+ uint256 randomDrawCooldown;
+ address goldToken;
+ }
+
/*//////////////////////////////////////////////////////////////
EVENTS
//////////////////////////////////////////////////////////////*/
+
/**
* @notice Emitted whenever a VRF request for randomness is sent
* @param requestId Unique identifier for the Chainlink VRF request
*/
event RandomDrawed(uint256 indexed requestId);
+
/**
* @notice Emitted when a winner is determined for the active lottery
* @param winner Address receiving the lottery gains
@@ -31,6 +61,7 @@ interface ILotterie {
* @param callbackGasLimit Gas limit allocated to fulfillRandomWords
* @param requestConfirmations Number of confirmations required per VRF request
* @param numWords Number of random words requested per draw
+ * @param randomDrawCooldown Minimum time required between lottery draws
*/
event LotterieInitialized(
address indexed owner,
@@ -40,7 +71,8 @@ interface ILotterie {
bytes32 keyHash,
uint32 callbackGasLimit,
uint16 requestConfirmations,
- uint32 numWords
+ uint32 numWords,
+ uint256 randomDrawCooldown
);
/**
@@ -92,6 +124,13 @@ interface ILotterie {
*/
event GoldTokenUpdated(address indexed previousGoldToken, address indexed newGoldToken);
+ /**
+ * @notice Emitted when the random draw cooldown changes
+ * @param previousCooldown Cooldown before the update
+ * @param newCooldown Cooldown after the update
+ */
+ event RandomDrawCooldownUpdated(uint256 indexed previousCooldown, uint256 indexed newCooldown);
+
/**
* @notice Emitted when a participant successfully claims lottery gains
* @param account Winner address claiming their gains
@@ -102,88 +141,95 @@ interface ILotterie {
/*//////////////////////////////////////////////////////////////
ERRORS
//////////////////////////////////////////////////////////////*/
- /// @notice Reverts when attempting to draw more than once within a rolling 24-hour window
- error OneRandomDrawPerDay();
+
+ /**
+ * @notice Reverts when attempting to draw more than once within the cooldown period
+ * @param lastDraw Timestamp of the last draw
+ * @param cooldown Minimum time between draws
+ * @param currentTime Current block timestamp
+ */
+ error DrawCooldownNotExpired(uint256 lastDraw, uint256 cooldown, uint256 currentTime);
+
/// @notice Reverts when a user tries to claim gains but has none
error NoGainToClaim();
+
/// @notice Reverts when the GoldToken transfer fails during a claim
error TransferFailed();
/*//////////////////////////////////////////////////////////////
ADMIN FUNCTIONS
//////////////////////////////////////////////////////////////*/
+
/// @notice Grants OWNER_ROLE to a new account
/// @param account Address receiving OWNER_ROLE
function addOwner(address account) external;
+
/// @notice Revokes OWNER_ROLE from an account
/// @param account Address losing OWNER_ROLE
function removeOwner(address account) external;
+
/**
* @notice Updates the Chainlink VRF subscription identifier
* @param vrfSubscriptionId New subscription id
*/
function setVrfSubscriptionId(uint256 vrfSubscriptionId) external;
+
/**
* @notice Updates the VRF coordinator contract reference
* @param vrfCoordinator Address of the VRF coordinator contract
*/
function setVrfCoordinator(address vrfCoordinator) external;
+
/**
* @notice Updates the VRF key hash used for randomness requests
* @param keyHash New VRF key hash
*/
function setKeyHash(bytes32 keyHash) external;
+
/**
* @notice Adjusts the gas limit used for the VRF callback
* @param callbackGasLimit New callback gas limit
*/
function setCallbackGasLimit(uint32 callbackGasLimit) external;
+
/**
* @notice Adjusts the number of confirmations required for VRF requests
* @param requestConfirmations New confirmation count
*/
function setRequestConfirmations(uint16 requestConfirmations) external;
+
/**
* @notice Adjusts the number of random words requested from VRF
* @param numWords New number of random words per request
*/
function setNumWords(uint32 numWords) external;
+
/**
* @notice Updates the GoldToken implementation used to read balances and manage gains
* @param goldToken Address of the GoldToken proxy
*/
function setGoldToken(address goldToken) external;
+ /**
+ * @notice Updates the minimum time required between lottery draws
+ * @param randomDrawCooldown New cooldown period
+ */
+ function setRandomDrawCooldown(uint256 randomDrawCooldown) external;
+
/*//////////////////////////////////////////////////////////////
CORE FUNCTIONS
//////////////////////////////////////////////////////////////*/
- /**
- * @notice Initializes the proxy with VRF configuration and GoldToken reference
- * @param owner Address granted OWNER_ROLE
- * @param vrfSubscriptionId Subscription id funding VRF requests
- * @param vrfCoordinator Address of the VRF coordinator
- * @param keyHash Chainlink VRF key hash used for randomness
- * @param callbackGasLimit Gas limit allocated for fulfillRandomWords
- * @param requestConfirmations Number of confirmations required for VRF responses
- * @param numWords Number of random words requested per draw
- * @param goldToken Address of the GoldToken proxy
- */
- function initialize(
- address owner,
- uint256 vrfSubscriptionId,
- address vrfCoordinator,
- bytes32 keyHash,
- uint32 callbackGasLimit,
- uint16 requestConfirmations,
- uint32 numWords,
- address goldToken
- ) external;
+
+ /// @notice Initializes the proxy with VRF configuration and GoldToken reference
+ function initialize(LotterieConfig calldata config) external;
/**
* @notice Requests randomness from Chainlink to pick a lottery winner
+ * @param enableNativePayment When true, the VRF request will be paid in native tokens otherwise LINK will be used
* @return requestId Identifier of the VRF request
*/
- function randomDraw() external returns (uint256 requestId);
+ function randomDraw(bool enableNativePayment) external returns (uint256 requestId);
+
/// @notice Claims accrued lottery gains for the caller
function claim() external;
@@ -194,8 +240,10 @@ interface ILotterie {
/// @param account Address to inspect
/// @return True when the account has OWNER_ROLE
function hasOwnerRole(address account) external view returns (bool);
+
/// @notice Returns the most recent VRF request identifier
/// @return requestId Last stored VRF request id (zero when no draws)
+
function getLastRequestId() external view returns (uint256);
/**
* @notice Returns the pending gains assigned to an account
@@ -203,45 +251,59 @@ interface ILotterie {
* @return Amount of GLD available to claim
*/
function getGains(address account) external view returns (uint256);
+
/**
* @notice Returns the winner associated with a specific VRF request id
* @param requestId VRF request identifier
* @return Winner address linked to the request
*/
function getResults(uint256 requestId) external view returns (address);
+
/**
* @notice Returns the VRF coordinator in use
* @return Address of the VRF coordinator contract
*/
function getVrfCoordinator() external view returns (address);
+
/**
* @notice Returns the VRF key hash currently configured
* @return VRF key hash value
*/
function getKeyHash() external view returns (bytes32);
+
/**
* @notice Returns the gas limit used for VRF callbacks
* @return Callback gas limit
*/
function getCallbackGasLimit() external view returns (uint32);
+
/**
* @notice Returns the number of confirmations before VRF fulfills requests
* @return Confirmation count
*/
function getRequestConfirmations() external view returns (uint16);
+
/**
* @notice Returns the number of random words requested per draw
* @return Number of random words
*/
function getNumWords() external view returns (uint32);
+
/**
* @notice Returns the GoldToken proxy address used by the lottery
* @return GoldToken address
*/
function getGoldToken() external view returns (address);
+
/**
* @notice Returns the VRF subscription identifier currently configured
* @return Subscription id
*/
function getVrfSubscriptionId() external view returns (uint256);
+
+ /**
+ * @notice Returns the minimum time required between lottery draws
+ * @return Cooldown period
+ */
+ function getRandomDrawCooldown() external view returns (uint256);
}
diff --git a/test/GoldToken.t.sol b/test/GoldToken.t.sol
index 7811fb2..e9ee09f 100644
--- a/test/GoldToken.t.sol
+++ b/test/GoldToken.t.sol
@@ -32,13 +32,6 @@ contract GoldTokenTest is Test {
bytes32 public constant OWNER_ROLE = keccak256("OWNER_ROLE");
- event GoldTokenInitialized(address indexed owner, address indexed dataFeedGold, address indexed dataFeedEth);
- event FeesAddressUpdated(address indexed previousFeesAddress, address indexed newFeesAddress);
- event LotterieAddressUpdated(address indexed previousLotterieAddress, address indexed newLotterieAddress);
- event UserAdded(address indexed user, uint256 timestamp);
- event UserRemoved(address indexed user);
- event Mint(address indexed to, uint256 amount);
-
function setUp() public {
uint256 id;
assembly {
@@ -118,7 +111,7 @@ contract GoldTokenTest is Test {
assertEq(feesAddress, address(this));
vm.expectEmit(true, true, false, false, address(goldToken));
- emit FeesAddressUpdated(address(this), address(signers[0]));
+ emit IGoldToken.FeesAddressUpdated(address(this), address(signers[0]));
goldToken.setFeesAddress(address(signers[0]));
feesAddress = goldToken.getFeesAddress();
@@ -128,7 +121,7 @@ contract GoldTokenTest is Test {
function test_initialize_emits_event() public {
GoldToken implementation = new GoldToken();
vm.expectEmit(true, false, false, true);
- emit GoldTokenInitialized(address(this), address(goldAggregator), address(ethAggregator));
+ emit IGoldToken.GoldTokenInitialized(address(this), address(goldAggregator), address(ethAggregator));
new ERC1967Proxy(
address(implementation),
abi.encodeWithSelector(
@@ -140,7 +133,7 @@ contract GoldTokenTest is Test {
function test_mint_emits_user_added_event() public {
vm.deal(address(this), 1 ether);
vm.expectEmit(true, false, false, true, address(goldToken));
- emit UserAdded(address(this), block.timestamp);
+ emit IGoldToken.UserAdded(address(this), block.timestamp);
goldToken.mint{value: 0.1 ether}();
}
@@ -151,7 +144,7 @@ contract GoldTokenTest is Test {
(uint256 expectedUserMint,,) = GoldReference.calcMintBreakdown(1 ether, goldPrice, ethPrice);
vm.expectEmit(true, false, false, true, address(goldToken));
- emit Mint(address(this), expectedUserMint);
+ emit IGoldToken.Mint(address(this), expectedUserMint);
goldToken.mint{value: 1 ether}();
}
@@ -161,14 +154,14 @@ contract GoldTokenTest is Test {
uint256 balance = goldToken.balanceOf(address(this));
vm.expectEmit(true, false, false, false, address(goldToken));
- emit UserRemoved(address(this));
+ emit IGoldToken.UserRemoved(address(this));
goldToken.burn(balance);
}
/// @notice Table-driven test for various mint scenarios. Check https://getfoundry.sh/forge/advanced-testing/table-testing/ for more details.
function tableMintScenario(MintScenario memory mintScenario) public {
vm.expectEmit(true, true, false, false, address(goldToken));
- emit LotterieAddressUpdated(DEFAULT_LOTTERIE, TABLE_LOTTERIE);
+ emit IGoldToken.LotterieAddressUpdated(DEFAULT_LOTTERIE, TABLE_LOTTERIE);
goldToken.setLotterieAddress(TABLE_LOTTERIE);
goldToken.setFeesAddress(TABLE_FEES);
diff --git a/test/Lotterie.fuzz.t.sol b/test/Lotterie.fuzz.t.sol
index f3a154e..1de1387 100644
--- a/test/Lotterie.fuzz.t.sol
+++ b/test/Lotterie.fuzz.t.sol
@@ -44,9 +44,10 @@ contract LotterieFuzzTest is Test {
vrfSubscriptionId,
address(vrfCoordinator),
bytes32(0x787d74caea10b2b357790d5b5247c2f63d1d91572a9846f780606e4d953677ae),
- 100000,
+ 40_000,
3,
1,
+ 86_400, // One day
address(goldToken)
)
);
@@ -96,7 +97,7 @@ contract LotterieFuzzTest is Test {
vm.warp(block.timestamp + 1 days);
- uint256 requestId = lotterie.randomDraw();
+ uint256 requestId = lotterie.randomDraw(false);
assertGt(requestId, 0, "Request ID should be positive");
// Fulfill the randomness
@@ -129,7 +130,7 @@ contract LotterieFuzzTest is Test {
vm.warp(block.timestamp + 1 days);
- uint256 requestId = lotterie.randomDraw();
+ uint256 requestId = lotterie.randomDraw(false);
vrfCoordinator.fulfillRandomWords(requestId, address(lotterie));
address winner = lotterie.getResults(requestId);
@@ -145,23 +146,31 @@ contract LotterieFuzzTest is Test {
}
/// @notice Fuzz test time constraints between draws
- function testFuzz_randomDraw_timeConstraints(uint32 timeElapsed) public {
- vm.assume(timeElapsed < 2 days);
+ function testFuzz_randomDraw_timeConstraints(uint32 timeElapsed, uint32 cooldown) public {
+ vm.assume(cooldown > 1 hours);
+ vm.assume(cooldown < 365 days);
+ vm.assume(timeElapsed < cooldown * 2);
+
+ lotterie.setRandomDrawCooldown(cooldown);
vm.deal(address(this), 1 ether);
goldToken.mint{value: 1 ether}();
- vm.warp(block.timestamp + 1 days);
- lotterie.randomDraw();
+ vm.warp(block.timestamp + cooldown);
+ lotterie.randomDraw(false);
vm.warp(block.timestamp + timeElapsed);
- if (timeElapsed < 1 days) {
- vm.expectRevert(ILotterie.OneRandomDrawPerDay.selector);
- lotterie.randomDraw();
+ if (timeElapsed < cooldown) {
+ vm.expectRevert(
+ abi.encodeWithSelector(
+ ILotterie.DrawCooldownNotExpired.selector, block.timestamp - timeElapsed, cooldown, block.timestamp
+ )
+ );
+ lotterie.randomDraw(false);
} else {
- uint256 requestId = lotterie.randomDraw();
- assertGt(requestId, 0, "Should succeed after 1 day");
+ uint256 requestId = lotterie.randomDraw(false);
+ assertGt(requestId, 0, "Should succeed after cooldown");
}
}
@@ -186,7 +195,7 @@ contract LotterieFuzzTest is Test {
for (uint256 i = 0; i < drawCount; i++) {
currentTime += 1 days + 1;
vm.warp(currentTime);
- uint256 requestId = lotterie.randomDraw();
+ uint256 requestId = lotterie.randomDraw(false);
assertGt(requestId, 0, "Request ID should be positive");
vrfCoordinator.fulfillRandomWords(requestId, address(lotterie));
@@ -215,7 +224,7 @@ contract LotterieFuzzTest is Test {
}
vm.warp(block.timestamp + 1 days);
- uint256 requestId = lotterie.randomDraw();
+ uint256 requestId = lotterie.randomDraw(false);
vrfCoordinator.fulfillRandomWords(requestId, address(lotterie));
address winner = lotterie.getResults(requestId);
@@ -252,7 +261,7 @@ contract LotterieFuzzTest is Test {
uint256 balanceBefore = goldToken.balanceOf(address(lotterie));
vm.assume(balanceBefore > 0);
- uint256 requestId = lotterie.randomDraw();
+ uint256 requestId = lotterie.randomDraw(false);
vrfCoordinator.fulfillRandomWords(requestId, address(lotterie));
address winner = lotterie.getResults(requestId);
@@ -287,7 +296,7 @@ contract LotterieFuzzTest is Test {
newGoldToken.mint{value: mintAmount2}();
vm.warp(block.timestamp + 1 days);
- uint256 requestId = lotterie.randomDraw();
+ uint256 requestId = lotterie.randomDraw(false);
vrfCoordinator.fulfillRandomWords(requestId, address(lotterie));
address winner = lotterie.getResults(requestId);
@@ -298,7 +307,7 @@ contract LotterieFuzzTest is Test {
/// @notice Documents that draws without users keep winner unset
function test_randomDraw_withoutUsersLeavesWinnerUnset() public {
vm.warp(block.timestamp + 1 days);
- uint256 requestId = lotterie.randomDraw();
+ uint256 requestId = lotterie.randomDraw(false);
vrfCoordinator.fulfillRandomWords(requestId, address(lotterie));
diff --git a/test/Lotterie.t.sol b/test/Lotterie.t.sol
index 8aea0f9..b2a3eab 100644
--- a/test/Lotterie.t.sol
+++ b/test/Lotterie.t.sol
@@ -20,25 +20,6 @@ contract LotterieTest is Test {
Lotterie public lotterie;
VRFCoordinatorV2_5Mock public vrfCoordinator;
- event LotterieInitialized(
- address indexed owner,
- address indexed vrfCoordinator,
- address indexed goldToken,
- uint256 vrfSubscriptionId,
- bytes32 keyHash,
- uint32 callbackGasLimit,
- uint16 requestConfirmations,
- uint32 numWords
- );
- event VrfSubscriptionUpdated(uint256 indexed previousSubscriptionId, uint256 indexed newSubscriptionId);
- event VrfCoordinatorUpdated(address indexed previousCoordinator, address indexed newCoordinator);
- event KeyHashUpdated(bytes32 indexed previousKeyHash, bytes32 indexed newKeyHash);
- event CallbackGasLimitUpdated(uint32 indexed previousGasLimit, uint32 indexed newGasLimit);
- event RequestConfirmationsUpdated(uint16 indexed previousConfirmations, uint16 indexed newConfirmations);
- event NumWordsUpdated(uint32 indexed previousNumWords, uint32 indexed newNumWords);
- event GoldTokenUpdated(address indexed previousGoldToken, address indexed newGoldToken);
- event GainClaimed(address indexed account, uint256 amount);
-
function setUp() public {
vm.deal(address(this), 100 ether);
// Advance time by 2 days to avoid underflow issues with last random draw time (set during initialization to block.timestamp - 1 days)
@@ -69,9 +50,10 @@ contract LotterieTest is Test {
subscription,
address(vrfCoordinator),
bytes32(0x787d74caea10b2b357790d5b5247c2f63d1d91572a9846f780606e4d953677ae),
- 100000,
+ 40_000,
3,
1,
+ 86_400, // One day
address(goldToken)
)
);
@@ -100,15 +82,22 @@ contract LotterieTest is Test {
}
function test_randomDrawBefore1DayWaiting() public {
+ uint256 lastDraw = block.timestamp - 1 days;
+ uint256 cooldown = 1 days;
+
vm.warp(block.timestamp - 1 hours);
- vm.expectRevert(ILotterie.OneRandomDrawPerDay.selector);
- lotterie.randomDraw();
+ uint256 currentTime = block.timestamp;
+
+ vm.expectRevert(
+ abi.encodeWithSelector(ILotterie.DrawCooldownNotExpired.selector, lastDraw, cooldown, currentTime)
+ );
+ lotterie.randomDraw(false);
}
function test_randomDraw() public {
vm.warp(block.timestamp + 1 days);
vm.recordLogs();
- uint256 requestId = lotterie.randomDraw();
+ uint256 requestId = lotterie.randomDraw(false);
Vm.Log[] memory logs = vm.getRecordedLogs();
(Vm.Log memory randomDrawLog, bool found) = _findLog(logs, keccak256("RandomDrawed(uint256)"));
@@ -121,7 +110,7 @@ contract LotterieTest is Test {
function test_randomDrawFulfillmentAndClaimFlow() public {
vm.warp(block.timestamp + 1 days);
goldToken.mint{value: 1 ether}();
- uint256 requestId = lotterie.randomDraw();
+ uint256 requestId = lotterie.randomDraw(false);
assertEq(lotterie.getLastRequestId(), requestId, "last request id should match the recent draw");
@@ -145,7 +134,7 @@ contract LotterieTest is Test {
uint256 winnerBalanceBefore = goldToken.balanceOf(winner);
vm.expectEmit(true, false, false, true, address(lotterie));
- emit GainClaimed(winner, gains);
+ emit ILotterie.GainClaimed(winner, gains);
vm.prank(winner);
lotterie.claim();
@@ -161,7 +150,7 @@ contract LotterieTest is Test {
function test_claim_reverts_when_transfer_fails() public {
vm.warp(block.timestamp + 1 days);
goldToken.mint{value: 1 ether}();
- uint256 requestId = lotterie.randomDraw();
+ uint256 requestId = lotterie.randomDraw(false);
vrfCoordinator.fulfillRandomWords(requestId, address(lotterie));
address winner = lotterie.getResults(requestId);
@@ -184,7 +173,7 @@ contract LotterieTest is Test {
function test_setVrfSubscriptionId() public {
uint256 previous = lotterie.getVrfSubscriptionId();
vm.expectEmit(true, true, false, false, address(lotterie));
- emit VrfSubscriptionUpdated(previous, 10);
+ emit ILotterie.VrfSubscriptionUpdated(previous, 10);
lotterie.setVrfSubscriptionId(10);
uint256 vrfSubscriptionId = lotterie.getVrfSubscriptionId();
assertEq(vrfSubscriptionId, 10, "vrfSubscriptionId should be 10");
@@ -193,7 +182,7 @@ contract LotterieTest is Test {
function test_setVrfCoordinator() public {
address previous = lotterie.getVrfCoordinator();
vm.expectEmit(true, true, false, false, address(lotterie));
- emit VrfCoordinatorUpdated(previous, address(0x1));
+ emit ILotterie.VrfCoordinatorUpdated(previous, address(0x1));
lotterie.setVrfCoordinator(address(0x1));
address vrf = lotterie.getVrfCoordinator();
assertEq(vrf, address(0x1), "vrfCoordinator should be 0x1");
@@ -202,7 +191,7 @@ contract LotterieTest is Test {
function test_setKeyHash() public {
bytes32 expectedKeyHash = keccak256(abi.encodePacked("test-key-hash"));
vm.expectEmit(true, true, false, false, address(lotterie));
- emit KeyHashUpdated(lotterie.getKeyHash(), expectedKeyHash);
+ emit ILotterie.KeyHashUpdated(lotterie.getKeyHash(), expectedKeyHash);
lotterie.setKeyHash(expectedKeyHash);
bytes32 keyHash = lotterie.getKeyHash();
assertEq(keyHash, expectedKeyHash, "keyHash should match expected value");
@@ -210,7 +199,7 @@ contract LotterieTest is Test {
function test_setCallbackGasLimit() public {
vm.expectEmit(true, true, false, false, address(lotterie));
- emit CallbackGasLimitUpdated(lotterie.getCallbackGasLimit(), 10);
+ emit ILotterie.CallbackGasLimitUpdated(lotterie.getCallbackGasLimit(), 10);
lotterie.setCallbackGasLimit(10);
uint32 gasLimit = lotterie.getCallbackGasLimit();
assertEq(gasLimit, 10, "gasLimit should be 10");
@@ -218,7 +207,7 @@ contract LotterieTest is Test {
function test_setRequestConfirmations() public {
vm.expectEmit(true, true, false, false, address(lotterie));
- emit RequestConfirmationsUpdated(lotterie.getRequestConfirmations(), 10);
+ emit ILotterie.RequestConfirmationsUpdated(lotterie.getRequestConfirmations(), 10);
lotterie.setRequestConfirmations(10);
uint16 confirmations = lotterie.getRequestConfirmations();
assertEq(confirmations, 10, "confirmations should be 10");
@@ -226,7 +215,7 @@ contract LotterieTest is Test {
function test_setNumWords() public {
vm.expectEmit(true, true, false, false, address(lotterie));
- emit NumWordsUpdated(lotterie.getNumWords(), 10);
+ emit ILotterie.NumWordsUpdated(lotterie.getNumWords(), 10);
lotterie.setNumWords(10);
uint32 numWords = lotterie.getNumWords();
assertEq(numWords, 10, "numWords should be 10");
@@ -234,17 +223,24 @@ contract LotterieTest is Test {
function test_setGoldToken() public {
vm.expectEmit(true, true, false, false, address(lotterie));
- emit GoldTokenUpdated(address(goldToken), address(0x1));
+ emit ILotterie.GoldTokenUpdated(address(goldToken), address(0x1));
lotterie.setGoldToken(address(0x1));
address goldTokenAddress = lotterie.getGoldToken();
assertEq(goldTokenAddress, address(0x1), "goldToken should be 0x1");
}
+ function test_setRandomDrawCooldown() public {
+ vm.expectEmit(true, true, false, false, address(lotterie));
+ emit ILotterie.RandomDrawCooldownUpdated(lotterie.getRandomDrawCooldown(), 1 days + 1);
+ lotterie.setRandomDrawCooldown(1 days + 1);
+ assertEq(lotterie.getRandomDrawCooldown(), 1 days + 1, "cooldown should be updated");
+ }
+
function test_initialize_emits_event() public {
Lotterie implementation = new Lotterie(address(vrfCoordinator));
uint256 subscription = vrfCoordinator.createSubscription();
vm.expectEmit(true, true, true, true);
- emit LotterieInitialized(
+ emit ILotterie.LotterieInitialized(
address(this),
address(vrfCoordinator),
address(goldToken),
@@ -252,7 +248,8 @@ contract LotterieTest is Test {
bytes32(uint256(0x1111)),
50_000,
2,
- 1
+ 1,
+ 86400
);
new ERC1967Proxy(
address(implementation),
@@ -265,6 +262,7 @@ contract LotterieTest is Test {
50_000,
2,
1,
+ 86400,
address(goldToken)
)
);
diff --git a/test/TokenBridge.t.sol b/test/TokenBridge.t.sol
index 6b45761..7c18cc0 100644
--- a/test/TokenBridge.t.sol
+++ b/test/TokenBridge.t.sol
@@ -37,27 +37,6 @@ contract TokenBridgeTest is Test {
MockV3Aggregator public goldAggregator;
MockV3Aggregator public ethAggregator;
- event TokenBridgeInitialized(
- address indexed owner, address indexed link, address indexed goldToken, uint64 destinationChainSelector
- );
- event MessageProcessedWithoutToken(bytes32 indexed messageId, uint64 indexed sourceChainSelector);
- event TokensBridged(
- bytes32 indexed messageId,
- address indexed sender,
- address indexed receiver,
- uint256 amount,
- uint64 destinationChainSelector,
- address feeToken,
- uint256 fees
- );
- event TokensReceived(
- bytes32 indexed messageId, address indexed receiver, uint256 amount, uint64 indexed sourceChainSelector
- );
- event ChainWhitelisted(uint64 indexed chainSelector);
- event ChainRemoved(uint64 indexed chainSelector);
- event SenderWhitelisted(address indexed sender);
- event SenderRemoved(address indexed sender);
-
function setUp() public {
// Setup accounts
owner = address(this);
@@ -152,7 +131,7 @@ contract TokenBridgeTest is Test {
function test_initialize_emits_event() public {
TokenBridge implementation = new TokenBridge(address(router));
vm.expectEmit(true, true, true, true);
- emit TokenBridgeInitialized(owner, address(linkToken), address(goldToken), BSC_CHAIN_SELECTOR);
+ emit ITokenBridge.TokenBridgeInitialized(owner, address(linkToken), address(goldToken), BSC_CHAIN_SELECTOR);
new ERC1967Proxy(
address(implementation),
abi.encodeWithSelector(
@@ -452,7 +431,7 @@ contract TokenBridgeTest is Test {
});
vm.expectEmit(true, true, false, false, address(tokenBridge));
- emit MessageProcessedWithoutToken(message.messageId, BSC_CHAIN_SELECTOR);
+ emit ITokenBridge.MessageProcessedWithoutToken(message.messageId, BSC_CHAIN_SELECTOR);
vm.prank(address(router));
tokenBridge.ccipReceive(message);
@@ -585,12 +564,12 @@ contract TokenBridgeTest is Test {
Client._argsToBytes(Client.EVMExtraArgsV2({gasLimit: 300_000, allowOutOfOrderExecution: true}));
vm.expectEmit(false, false, false, true, address(tokenBridge));
- emit ChainWhitelisted(newChain);
+ emit ITokenBridge.ChainWhitelisted(newChain);
tokenBridge.setWhitelistedChain(newChain, true, args);
assertTrue(tokenBridge.whitelistedChains(newChain));
vm.expectEmit(false, false, false, true, address(tokenBridge));
- emit ChainRemoved(newChain);
+ emit ITokenBridge.ChainRemoved(newChain);
tokenBridge.setWhitelistedChain(newChain, false, "");
assertFalse(tokenBridge.whitelistedChains(newChain));
}
@@ -599,12 +578,12 @@ contract TokenBridgeTest is Test {
address newSender = signers[0];
vm.expectEmit(false, false, false, true, address(tokenBridge));
- emit SenderWhitelisted(newSender);
+ emit ITokenBridge.SenderWhitelisted(newSender);
tokenBridge.setWhitelistedSender(newSender, true);
assertTrue(tokenBridge.whitelistedSenders(newSender));
vm.expectEmit(false, false, false, true, address(tokenBridge));
- emit SenderRemoved(newSender);
+ emit ITokenBridge.SenderRemoved(newSender);
tokenBridge.setWhitelistedSender(newSender, false);
assertFalse(tokenBridge.whitelistedSenders(newSender));
}