From ce0f524c59ea4c28d4fe381c95efd9e31224d212 Mon Sep 17 00:00:00 2001 From: jhfnetboy Date: Sat, 14 Mar 2026 14:23:53 +0700 Subject: [PATCH 01/34] feat(M0): add @aastar/sdk @aastar/core viem deps + env templates - Add @aastar/sdk, @aastar/core, viem to backend and frontend - Add aastar/.env.example with Sepolia canonical addresses - Add aastar-frontend/env.local.template with NEXT_PUBLIC_ vars - Verified backend builds and starts on port 3000 (401 on /api/v1/auth/profile) - Verified applyConfig({ chainId: CHAIN_SEPOLIA }) loads correct addresses Co-Authored-By: Claude Sonnet 4.6 --- aastar-frontend/env.local.template | 15 + aastar-frontend/package.json | 4 +- aastar/.env.example | 124 +-- aastar/package.json | 5 +- package-lock.json | 1673 +++++++++++++++++++++++++++- 5 files changed, 1678 insertions(+), 143 deletions(-) create mode 100644 aastar-frontend/env.local.template diff --git a/aastar-frontend/env.local.template b/aastar-frontend/env.local.template new file mode 100644 index 00000000..4c4e3f8b --- /dev/null +++ b/aastar-frontend/env.local.template @@ -0,0 +1,15 @@ +NEXT_PUBLIC_API_URL=http://localhost:3000/api/v1 +BACKEND_API_URL=http://127.0.0.1:3000 +KMS_PROXY_URL=https://kms1.aastar.io +NEXT_PUBLIC_KMS_URL=https://kms1.aastar.io +NEXT_PUBLIC_KMS_API_KEY= +NEXT_PUBLIC_BLS_SEED_NODE=https://v1.aastar.io +NEXT_PUBLIC_CHAIN_ID=11155111 + +# AAStar canonical contract addresses (Sepolia 11155111) +NEXT_PUBLIC_REGISTRY_ADDRESS=0x7Ba70C5bFDb3A4d0cBd220534f3BE177fefc1788 +NEXT_PUBLIC_GTOKEN_ADDRESS=0x9ceDeC089921652D050819ca5BE53765fc05aa9E +NEXT_PUBLIC_XPNTS_FACTORY_ADDRESS=0x6EafdA3477F3eec1F848505e1c06dFB5532395b6 +NEXT_PUBLIC_APNTS_ADDRESS=0xDf669834F04988BcEE0E3B6013B6b867Bd38778d +NEXT_PUBLIC_SUPER_PAYMASTER_ADDRESS=0x16cE0c7d846f9446bbBeb9C5a84A4D140fAeD94A +NEXT_PUBLIC_PAYMASTER_FACTORY_ADDRESS=0xfDE4671581F21C9e54Cafa95FA6Da98678750F4d diff --git a/aastar-frontend/package.json b/aastar-frontend/package.json index 87223ce7..314ed184 100644 --- a/aastar-frontend/package.json +++ b/aastar-frontend/package.json @@ -16,6 +16,7 @@ "test:ci": "echo \"⚠️ No tests yet - skipping\"" }, "dependencies": { + "@aastar/core": "^0.16.23", "@headlessui/react": "^2.2.9", "@heroicons/react": "^2.2.0", "@simplewebauthn/browser": "^13.2.2", @@ -29,7 +30,8 @@ "react-dom": "19.2.0", "react-hot-toast": "^2.6.0", "react-qr-code": "^2.0.18", - "typescript": "^5" + "typescript": "^5", + "viem": "^2.47.4" }, "devDependencies": { "@eslint/eslintrc": "^3", diff --git a/aastar/.env.example b/aastar/.env.example index 3e905807..6839da99 100644 --- a/aastar/.env.example +++ b/aastar/.env.example @@ -1,112 +1,36 @@ -# =========================================== -# AAStar Backend Configuration -# =========================================== - -# ----------------- -# Server Configuration -# ----------------- PORT=3000 NODE_ENV=development - -# ----------------- -# Authentication & Security -# ----------------- -# JWT secret key for token signing (generate a secure random string) -JWT_SECRET=your-development-jwt-secret-key - -# JWT token expiration time (e.g., 7d, 24h, 60m) +JWT_SECRET=<32-byte-hex-secret> JWT_EXPIRES_IN=7d - -# User data encryption key (must be 32 characters for AES-256) -USER_ENCRYPTION_KEY=your-secret-encryption-key-32-chars - -# Data tools password for import/export operations +USER_ENCRYPTION_KEY=<16-byte-hex-key> DATA_TOOLS_PASSWORD=admin123456 -# ----------------- -# Database Configuration -# ----------------- -# Database type: 'json' for file-based storage, 'postgres' for PostgreSQL DB_TYPE=json -# PostgreSQL connection URL (required if DB_TYPE=postgres) -# Format: postgresql://username:password@host:port/database -# DATABASE_URL=postgresql://aastar:password@localhost:5432/airaccount - -# ----------------- -# Blockchain Configuration -# ----------------- -# Chain ID (10 = OP Mainnet, 11155111 = Sepolia) -CHAIN_ID=10 - -# Ethereum RPC URL (OP Mainnet example) -ETH_RPC_URL=https://optimism-mainnet.infura.io/v3/YOUR_INFURA_PROJECT_ID - -# Bundler RPC URL for ERC-4337 UserOperations -BUNDLER_RPC_URL=https://api.pimlico.io/v2/10/rpc?apikey=YOUR_PIMLICO_API_KEY +CHAIN_ID=11155111 +ETH_RPC_URL=https://eth-sepolia.g.alchemy.com/v2/ +BUNDLER_RPC_URL=https://api.pimlico.io/v2/11155111/rpc?apikey= -# Pimlico API key (for advanced bundler features) -PIMLICO_API_KEY=YOUR_PIMLICO_API_KEY - -# ----------------- -# ERC-4337 Contracts (v0.6) -# ----------------- -ENTRY_POINT_ADDRESS=0x5FF137D4b0FDCD49DcA30c7CF57E578a026d2789 -AASTAR_ACCOUNT_FACTORY_ADDRESS=0xab18406D34B918A0431116755C45AC7af99DcDa6 -VALIDATOR_CONTRACT_ADDRESS=0xD9756c11686B59F7DDf39E6360230316710485af - -# ----------------- -# ERC-4337 Contracts (v0.7) -# ----------------- +# EntryPoint v0.7 (primary) +ENTRY_POINT_ADDRESS=0x0000000071727De22E5E9d8BAf0edAc6f37da032 ENTRY_POINT_V7_ADDRESS=0x0000000071727De22E5E9d8BAf0edAc6f37da032 -AASTAR_ACCOUNT_FACTORY_V7_ADDRESS=0xAae813Ae38418f38701142cEab08D4F52383bF34 +AASTAR_ACCOUNT_FACTORY_V7_ADDRESS=0x91E60482a2B343004dF29EB205C4F6916E864700 VALIDATOR_CONTRACT_V7_ADDRESS=0xD9756c11686B59F7DDf39E6360230316710485af - -# ----------------- -# ERC-4337 Contracts (v0.8) -# ----------------- -ENTRY_POINT_V8_ADDRESS=0x0576a174D229E3cFA37253523E645A78A0C91B57 -AASTAR_ACCOUNT_FACTORY_V8_ADDRESS=0x5675f3e1C97bE92F22315a5af58c9A8f1007F242 -VALIDATOR_CONTRACT_V8_ADDRESS=0xD9756c11686B59F7DDf39E6360230316710485af - -# Default EntryPoint version for new accounts -# Options: "0.6" | "0.7" | "0.8" DEFAULT_ENTRYPOINT_VERSION=0.7 -# ----------------- -# BLS Signer Service -# ----------------- -# Comma-separated list of BLS signer service URLs -BLS_SEED_NODES=http://localhost:3001 - -# ----------------- -# KMS Configuration (Production) -# ----------------- -# Enable KMS for secure key management (set to "true" for production) -KMS_ENABLED=false - -# KMS service endpoint -KMS_ENDPOINT=https://kms.aastar.io - -# ----------------- -# Important Notes -# ----------------- -# 1. NO PRIVATE KEYS NEEDED FOR RUNTIME OPERATION -# - User wallets are auto-generated via KMS (production) or locally (development) -# - Private keys only required for initial contract deployment (in validator/) -# -# 2. Development Setup (Quick Start): -# - Use DB_TYPE=json for no database setup -# - Set KMS_ENABLED=false for local wallet generation -# - Use the reference contract addresses above (Sepolia testnet) -# -# 3. Production Setup: -# - Use DB_TYPE=postgres with secure DATABASE_URL -# - Enable KMS_ENABLED=true for enterprise key management -# - Deploy your own contracts and update addresses -# - Generate secure random strings for JWT_SECRET and USER_ENCRYPTION_KEY (32 chars) -# -# 4. Contract Addresses: -# - Addresses above are reference deployments on Sepolia testnet -# - Deploy your own contracts for production use -# - See validator/ directory for deployment scripts +BLS_SEED_NODES=https://v1.aastar.io + +KMS_ENABLED=true +KMS_ENDPOINT=https://kms1.aastar.io +KMS_API_KEY= + +# AAStar contract addresses (@aastar/core canonical, Sepolia 11155111) +REGISTRY_ADDRESS=0x7Ba70C5bFDb3A4d0cBd220534f3BE177fefc1788 +STAKING_ADDRESS=0x1118eAf2427a5B9e488e28D35338d22EaCBc37fC +SUPER_PAYMASTER_ADDRESS=0x16cE0c7d846f9446bbBeb9C5a84A4D140fAeD94A +GTOKEN_ADDRESS=0x9ceDeC089921652D050819ca5BE53765fc05aa9E +XPNTS_FACTORY_ADDRESS=0x6EafdA3477F3eec1F848505e1c06dFB5532395b6 +PAYMASTER_FACTORY_ADDRESS=0xfDE4671581F21C9e54Cafa95FA6Da98678750F4d +MYSBT_ADDRESS=0x677423f5Dad98D19cAE8661c36F094289cb6171a +APNTS_ADDRESS=0xDf669834F04988BcEE0E3B6013B6b867Bd38778d +PRICE_FEED_ADDRESS=0x694AA1769357215DE4FAC081bf1f309aDC325306 diff --git a/aastar/package.json b/aastar/package.json index 436eaddd..8141ab0c 100644 --- a/aastar/package.json +++ b/aastar/package.json @@ -48,6 +48,8 @@ "typescript": "^5.9.3" }, "dependencies": { + "@aastar/core": "^0.16.23", + "@aastar/sdk": "^0.16.23", "@nestjs/common": "^11.1.6", "@nestjs/config": "^4.0.2", "@nestjs/core": "^11.1.6", @@ -75,6 +77,7 @@ "swagger-ui-express": "^5.0.1", "tar": "^7.5.1", "typeorm": "^0.3.27", - "uuid": "^13.0.0" + "uuid": "^13.0.0", + "viem": "^2.47.4" } } diff --git a/package-lock.json b/package-lock.json index e0899dfd..bfa9783e 100644 --- a/package-lock.json +++ b/package-lock.json @@ -26,6 +26,8 @@ "version": "1.0.0", "license": "ISC", "dependencies": { + "@aastar/core": "^0.16.23", + "@aastar/sdk": "^0.16.23", "@nestjs/common": "^11.1.6", "@nestjs/config": "^4.0.2", "@nestjs/core": "^11.1.6", @@ -53,7 +55,8 @@ "swagger-ui-express": "^5.0.1", "tar": "^7.5.1", "typeorm": "^0.3.27", - "uuid": "^13.0.0" + "uuid": "^13.0.0", + "viem": "^2.47.4" }, "devDependencies": { "@nestjs/cli": "^11.0.10", @@ -79,6 +82,7 @@ "aastar-frontend": { "version": "0.1.0", "dependencies": { + "@aastar/core": "^0.16.23", "@headlessui/react": "^2.2.9", "@heroicons/react": "^2.2.0", "@simplewebauthn/browser": "^13.2.2", @@ -92,7 +96,8 @@ "react-dom": "19.2.0", "react-hot-toast": "^2.6.0", "react-qr-code": "^2.0.18", - "typescript": "^5" + "typescript": "^5", + "viem": "^2.47.4" }, "devDependencies": { "@eslint/eslintrc": "^3", @@ -288,39 +293,1355 @@ "dev": true, "license": "MIT", "dependencies": { - "type-fest": "^0.20.2" + "type-fest": "^0.20.2" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "aastar-frontend/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==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "aastar-frontend/node_modules/type-fest": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz", + "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==", + "dev": true, + "license": "(MIT OR CC0-1.0)", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@aastar/account": { + "version": "0.16.23", + "resolved": "https://registry.npmjs.org/@aastar/account/-/account-0.16.23.tgz", + "integrity": "sha512-Qobp6AeU61goqBHsdX4OkKZa0lwuciX4bzNOufsDZjDJRCyTcQ+35dO/cQA+aV/DsQ5UmrUPYw/d1JxrDaYmoQ==", + "license": "MIT", + "dependencies": { + "@aastar/core": "0.16.23", + "viem": "2.43.3" + } + }, + "node_modules/@aastar/account/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/@aastar/account/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/@aastar/account/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/@aastar/account/node_modules/ox": { + "version": "0.11.1", + "resolved": "https://registry.npmjs.org/ox/-/ox-0.11.1.tgz", + "integrity": "sha512-1l1gOLAqg0S0xiN1dH5nkPna8PucrZgrIJOfS49MLNiMevxu07Iz4ZjuJS9N+xifvT+PsZyIptS7WHM8nC+0+A==", + "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.2.3", + "eventemitter3": "5.0.1" + }, + "peerDependencies": { + "typescript": ">=5.4.0" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/@aastar/account/node_modules/viem": { + "version": "2.43.3", + "resolved": "https://registry.npmjs.org/viem/-/viem-2.43.3.tgz", + "integrity": "sha512-zM251fspfSjENCtfmT7cauuD+AA/YAlkFU7cksdEQJxj7wDuO0XFRWRH+RMvfmTFza88B9kug5cKU+Wk2nAjJg==", + "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.2.3", + "isows": "1.0.7", + "ox": "0.11.1", + "ws": "8.18.3" + }, + "peerDependencies": { + "typescript": ">=5.0.4" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/@aastar/account/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", + "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/@aastar/admin": { + "version": "0.16.23", + "resolved": "https://registry.npmjs.org/@aastar/admin/-/admin-0.16.23.tgz", + "integrity": "sha512-7uyV6RTybkXYWNX0JvhEJCXbcrbr00Lhp0gkKz6r0EYtnDFQWvZ39Zy33n43e56lLoPogXrHUxvl7tayIZy1AA==", + "license": "MIT", + "dependencies": { + "@aastar/core": "0.16.23", + "viem": "2.43.3" + } + }, + "node_modules/@aastar/admin/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/@aastar/admin/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/@aastar/admin/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/@aastar/admin/node_modules/ox": { + "version": "0.11.1", + "resolved": "https://registry.npmjs.org/ox/-/ox-0.11.1.tgz", + "integrity": "sha512-1l1gOLAqg0S0xiN1dH5nkPna8PucrZgrIJOfS49MLNiMevxu07Iz4ZjuJS9N+xifvT+PsZyIptS7WHM8nC+0+A==", + "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.2.3", + "eventemitter3": "5.0.1" + }, + "peerDependencies": { + "typescript": ">=5.4.0" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/@aastar/admin/node_modules/viem": { + "version": "2.43.3", + "resolved": "https://registry.npmjs.org/viem/-/viem-2.43.3.tgz", + "integrity": "sha512-zM251fspfSjENCtfmT7cauuD+AA/YAlkFU7cksdEQJxj7wDuO0XFRWRH+RMvfmTFza88B9kug5cKU+Wk2nAjJg==", + "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.2.3", + "isows": "1.0.7", + "ox": "0.11.1", + "ws": "8.18.3" + }, + "peerDependencies": { + "typescript": ">=5.0.4" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/@aastar/admin/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", + "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/@aastar/core": { + "version": "0.16.23", + "resolved": "https://registry.npmjs.org/@aastar/core/-/core-0.16.23.tgz", + "integrity": "sha512-ZKy/1kb98FOEKnx28I+7doFTz/cdn5FqoqRtyys8FhU+/Zcstvb6PriW56B8tB0pVvcxVH+XMiL/XOFwdKzqzQ==", + "license": "MIT", + "dependencies": { + "@noble/curves": "^1.6.0", + "viem": "2.43.3" + } + }, + "node_modules/@aastar/core/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/@aastar/core/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/@aastar/core/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/@aastar/core/node_modules/ox": { + "version": "0.11.1", + "resolved": "https://registry.npmjs.org/ox/-/ox-0.11.1.tgz", + "integrity": "sha512-1l1gOLAqg0S0xiN1dH5nkPna8PucrZgrIJOfS49MLNiMevxu07Iz4ZjuJS9N+xifvT+PsZyIptS7WHM8nC+0+A==", + "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.2.3", + "eventemitter3": "5.0.1" + }, + "peerDependencies": { + "typescript": ">=5.4.0" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/@aastar/core/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/@aastar/core/node_modules/viem": { + "version": "2.43.3", + "resolved": "https://registry.npmjs.org/viem/-/viem-2.43.3.tgz", + "integrity": "sha512-zM251fspfSjENCtfmT7cauuD+AA/YAlkFU7cksdEQJxj7wDuO0XFRWRH+RMvfmTFza88B9kug5cKU+Wk2nAjJg==", + "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.2.3", + "isows": "1.0.7", + "ox": "0.11.1", + "ws": "8.18.3" + }, + "peerDependencies": { + "typescript": ">=5.0.4" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/@aastar/core/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/@aastar/core/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", + "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/@aastar/dapp": { + "version": "0.16.23", + "resolved": "https://registry.npmjs.org/@aastar/dapp/-/dapp-0.16.23.tgz", + "integrity": "sha512-O2Nb6TuCazX1j4aHe/TIxfRDS29NW4Nr9TJI7f08slIWpuYpVXidLof0Y64pUjWawfEikrUS4kdByMFJ6yqZNA==", + "license": "MIT", + "dependencies": { + "@aastar/core": "0.16.23", + "@aastar/paymaster": "0.16.23", + "react": "18.2.0", + "react-dom": "18.2.0", + "viem": "2.43.3" + } + }, + "node_modules/@aastar/dapp/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/@aastar/dapp/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/@aastar/dapp/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/@aastar/dapp/node_modules/ox": { + "version": "0.11.1", + "resolved": "https://registry.npmjs.org/ox/-/ox-0.11.1.tgz", + "integrity": "sha512-1l1gOLAqg0S0xiN1dH5nkPna8PucrZgrIJOfS49MLNiMevxu07Iz4ZjuJS9N+xifvT+PsZyIptS7WHM8nC+0+A==", + "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.2.3", + "eventemitter3": "5.0.1" + }, + "peerDependencies": { + "typescript": ">=5.4.0" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/@aastar/dapp/node_modules/react": { + "version": "18.2.0", + "resolved": "https://registry.npmjs.org/react/-/react-18.2.0.tgz", + "integrity": "sha512-/3IjMdb2L9QbBdWiW5e3P2/npwMBaU9mHCSCUzNln0ZCYbcfTsGbTJrU/kGemdH2IWmB2ioZ+zkxtmq6g09fGQ==", + "license": "MIT", + "dependencies": { + "loose-envify": "^1.1.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/@aastar/dapp/node_modules/react-dom": { + "version": "18.2.0", + "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-18.2.0.tgz", + "integrity": "sha512-6IMTriUmvsjHUjNtEDudZfuDQUoWXVxKHhlEGSk81n4YFS+r/Kl99wXiwlVXtPBtJenozv2P+hxDsw9eA7Xo6g==", + "license": "MIT", + "dependencies": { + "loose-envify": "^1.1.0", + "scheduler": "^0.23.0" + }, + "peerDependencies": { + "react": "^18.2.0" + } + }, + "node_modules/@aastar/dapp/node_modules/scheduler": { + "version": "0.23.2", + "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.23.2.tgz", + "integrity": "sha512-UOShsPwz7NrMUqhR6t0hWjFduvOzbtv7toDH1/hIrfRNIDBnnBWd0CwJTGvTpngVlmwGCdP9/Zl/tVrDqcuYzQ==", + "license": "MIT", + "dependencies": { + "loose-envify": "^1.1.0" + } + }, + "node_modules/@aastar/dapp/node_modules/viem": { + "version": "2.43.3", + "resolved": "https://registry.npmjs.org/viem/-/viem-2.43.3.tgz", + "integrity": "sha512-zM251fspfSjENCtfmT7cauuD+AA/YAlkFU7cksdEQJxj7wDuO0XFRWRH+RMvfmTFza88B9kug5cKU+Wk2nAjJg==", + "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.2.3", + "isows": "1.0.7", + "ox": "0.11.1", + "ws": "8.18.3" + }, + "peerDependencies": { + "typescript": ">=5.0.4" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/@aastar/dapp/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", + "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/@aastar/enduser": { + "version": "0.16.23", + "resolved": "https://registry.npmjs.org/@aastar/enduser/-/enduser-0.16.23.tgz", + "integrity": "sha512-oVxcsLP3gDMuIrRWNNmFHZZ6jk0dQXN7fwF5oHDrWTt1kw1wVP/XM1nfPPTPDP1T8450SOirGbWHecjDvriunw==", + "license": "MIT", + "dependencies": { + "@aastar/core": "0.16.23", + "@aastar/paymaster": "0.16.23", + "viem": "2.43.3" + } + }, + "node_modules/@aastar/enduser/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/@aastar/enduser/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/@aastar/enduser/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/@aastar/enduser/node_modules/ox": { + "version": "0.11.1", + "resolved": "https://registry.npmjs.org/ox/-/ox-0.11.1.tgz", + "integrity": "sha512-1l1gOLAqg0S0xiN1dH5nkPna8PucrZgrIJOfS49MLNiMevxu07Iz4ZjuJS9N+xifvT+PsZyIptS7WHM8nC+0+A==", + "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.2.3", + "eventemitter3": "5.0.1" + }, + "peerDependencies": { + "typescript": ">=5.4.0" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/@aastar/enduser/node_modules/viem": { + "version": "2.43.3", + "resolved": "https://registry.npmjs.org/viem/-/viem-2.43.3.tgz", + "integrity": "sha512-zM251fspfSjENCtfmT7cauuD+AA/YAlkFU7cksdEQJxj7wDuO0XFRWRH+RMvfmTFza88B9kug5cKU+Wk2nAjJg==", + "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.2.3", + "isows": "1.0.7", + "ox": "0.11.1", + "ws": "8.18.3" + }, + "peerDependencies": { + "typescript": ">=5.0.4" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/@aastar/enduser/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", + "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/@aastar/identity": { + "version": "0.16.23", + "resolved": "https://registry.npmjs.org/@aastar/identity/-/identity-0.16.23.tgz", + "integrity": "sha512-W8ksJjWS2jcc7/1aAB6CwJJrHOGDg+Q28mpDeJQcRpzLscGjtylE2sEmOHQ3zb34HSOMAZNPiX+DvgLASkfiGg==", + "license": "MIT", + "dependencies": { + "@aastar/core": "0.16.23", + "viem": "2.43.3" + } + }, + "node_modules/@aastar/identity/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/@aastar/identity/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/@aastar/identity/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/@aastar/identity/node_modules/ox": { + "version": "0.11.1", + "resolved": "https://registry.npmjs.org/ox/-/ox-0.11.1.tgz", + "integrity": "sha512-1l1gOLAqg0S0xiN1dH5nkPna8PucrZgrIJOfS49MLNiMevxu07Iz4ZjuJS9N+xifvT+PsZyIptS7WHM8nC+0+A==", + "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.2.3", + "eventemitter3": "5.0.1" + }, + "peerDependencies": { + "typescript": ">=5.4.0" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/@aastar/identity/node_modules/viem": { + "version": "2.43.3", + "resolved": "https://registry.npmjs.org/viem/-/viem-2.43.3.tgz", + "integrity": "sha512-zM251fspfSjENCtfmT7cauuD+AA/YAlkFU7cksdEQJxj7wDuO0XFRWRH+RMvfmTFza88B9kug5cKU+Wk2nAjJg==", + "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.2.3", + "isows": "1.0.7", + "ox": "0.11.1", + "ws": "8.18.3" + }, + "peerDependencies": { + "typescript": ">=5.0.4" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/@aastar/identity/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", + "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/@aastar/operator": { + "version": "0.16.23", + "resolved": "https://registry.npmjs.org/@aastar/operator/-/operator-0.16.23.tgz", + "integrity": "sha512-uKo18LjC+fS+QbsWu+pXp/p6dI1xbJk2E0hlnBf5aqw74J40dHiGgz2+/KCO7ZxBAt/eh1N2MYufnhR4T27jfA==", + "license": "MIT", + "dependencies": { + "@aastar/core": "0.16.23", + "viem": "2.43.3" + } + }, + "node_modules/@aastar/operator/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/@aastar/operator/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/@aastar/operator/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/@aastar/operator/node_modules/ox": { + "version": "0.11.1", + "resolved": "https://registry.npmjs.org/ox/-/ox-0.11.1.tgz", + "integrity": "sha512-1l1gOLAqg0S0xiN1dH5nkPna8PucrZgrIJOfS49MLNiMevxu07Iz4ZjuJS9N+xifvT+PsZyIptS7WHM8nC+0+A==", + "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.2.3", + "eventemitter3": "5.0.1" + }, + "peerDependencies": { + "typescript": ">=5.4.0" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/@aastar/operator/node_modules/viem": { + "version": "2.43.3", + "resolved": "https://registry.npmjs.org/viem/-/viem-2.43.3.tgz", + "integrity": "sha512-zM251fspfSjENCtfmT7cauuD+AA/YAlkFU7cksdEQJxj7wDuO0XFRWRH+RMvfmTFza88B9kug5cKU+Wk2nAjJg==", + "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.2.3", + "isows": "1.0.7", + "ox": "0.11.1", + "ws": "8.18.3" + }, + "peerDependencies": { + "typescript": ">=5.0.4" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/@aastar/operator/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", + "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/@aastar/paymaster": { + "version": "0.16.23", + "resolved": "https://registry.npmjs.org/@aastar/paymaster/-/paymaster-0.16.23.tgz", + "integrity": "sha512-Syihq8+87+LaZ+XqphglwOnkV7fH2azRFM4uzoj8BxmONPSygKNHv6UenvChZsFmy13Vu2+8UvXqnvhkrAEqCg==", + "license": "MIT", + "dependencies": { + "@aastar/core": "0.16.23", + "viem": "2.43.3" + } + }, + "node_modules/@aastar/paymaster/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/@aastar/paymaster/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/@aastar/paymaster/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/@aastar/paymaster/node_modules/ox": { + "version": "0.11.1", + "resolved": "https://registry.npmjs.org/ox/-/ox-0.11.1.tgz", + "integrity": "sha512-1l1gOLAqg0S0xiN1dH5nkPna8PucrZgrIJOfS49MLNiMevxu07Iz4ZjuJS9N+xifvT+PsZyIptS7WHM8nC+0+A==", + "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.2.3", + "eventemitter3": "5.0.1" + }, + "peerDependencies": { + "typescript": ">=5.4.0" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/@aastar/paymaster/node_modules/viem": { + "version": "2.43.3", + "resolved": "https://registry.npmjs.org/viem/-/viem-2.43.3.tgz", + "integrity": "sha512-zM251fspfSjENCtfmT7cauuD+AA/YAlkFU7cksdEQJxj7wDuO0XFRWRH+RMvfmTFza88B9kug5cKU+Wk2nAjJg==", + "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.2.3", + "isows": "1.0.7", + "ox": "0.11.1", + "ws": "8.18.3" + }, + "peerDependencies": { + "typescript": ">=5.0.4" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/@aastar/paymaster/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", + "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/@aastar/sdk": { + "version": "0.16.23", + "resolved": "https://registry.npmjs.org/@aastar/sdk/-/sdk-0.16.23.tgz", + "integrity": "sha512-a6d49nZJam/vAp7/UVpv3MZ8NOFw+7KUaVWd4xxYPPiBkUGkYEnlkBPaNQhT009Ie5vxWCJfu5PLORjNKB7iCg==", + "license": "MIT", + "dependencies": { + "@aastar/account": "0.16.23", + "@aastar/admin": "0.16.23", + "@aastar/core": "0.16.23", + "@aastar/dapp": "0.16.23", + "@aastar/enduser": "0.16.23", + "@aastar/identity": "0.16.23", + "@aastar/operator": "0.16.23", + "@aastar/paymaster": "0.16.23", + "@aastar/tokens": "0.16.23", + "viem": "2.43.3" + } + }, + "node_modules/@aastar/sdk/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/@aastar/sdk/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/@aastar/sdk/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/@aastar/sdk/node_modules/ox": { + "version": "0.11.1", + "resolved": "https://registry.npmjs.org/ox/-/ox-0.11.1.tgz", + "integrity": "sha512-1l1gOLAqg0S0xiN1dH5nkPna8PucrZgrIJOfS49MLNiMevxu07Iz4ZjuJS9N+xifvT+PsZyIptS7WHM8nC+0+A==", + "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.2.3", + "eventemitter3": "5.0.1" + }, + "peerDependencies": { + "typescript": ">=5.4.0" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/@aastar/sdk/node_modules/viem": { + "version": "2.43.3", + "resolved": "https://registry.npmjs.org/viem/-/viem-2.43.3.tgz", + "integrity": "sha512-zM251fspfSjENCtfmT7cauuD+AA/YAlkFU7cksdEQJxj7wDuO0XFRWRH+RMvfmTFza88B9kug5cKU+Wk2nAjJg==", + "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.2.3", + "isows": "1.0.7", + "ox": "0.11.1", + "ws": "8.18.3" + }, + "peerDependencies": { + "typescript": ">=5.0.4" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/@aastar/sdk/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", + "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/@aastar/tokens": { + "version": "0.16.23", + "resolved": "https://registry.npmjs.org/@aastar/tokens/-/tokens-0.16.23.tgz", + "integrity": "sha512-0jih9obsn2kR4ir9fZyAuGvOfxTOaVwjy62S/b9+D7XgvyHtEs2kXz4OeH+L1IFuZRVTVezWOQ00/4zKauIi5w==", + "license": "MIT", + "dependencies": { + "@aastar/core": "0.16.23", + "viem": "2.43.3" + } + }, + "node_modules/@aastar/tokens/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/@aastar/tokens/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/@aastar/tokens/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/@aastar/tokens/node_modules/ox": { + "version": "0.11.1", + "resolved": "https://registry.npmjs.org/ox/-/ox-0.11.1.tgz", + "integrity": "sha512-1l1gOLAqg0S0xiN1dH5nkPna8PucrZgrIJOfS49MLNiMevxu07Iz4ZjuJS9N+xifvT+PsZyIptS7WHM8nC+0+A==", + "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.2.3", + "eventemitter3": "5.0.1" }, - "engines": { - "node": ">=8" + "peerDependencies": { + "typescript": ">=5.4.0" }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "peerDependenciesMeta": { + "typescript": { + "optional": true + } } }, - "aastar-frontend/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==", - "dev": true, + "node_modules/@aastar/tokens/node_modules/viem": { + "version": "2.43.3", + "resolved": "https://registry.npmjs.org/viem/-/viem-2.43.3.tgz", + "integrity": "sha512-zM251fspfSjENCtfmT7cauuD+AA/YAlkFU7cksdEQJxj7wDuO0XFRWRH+RMvfmTFza88B9kug5cKU+Wk2nAjJg==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/wevm" + } + ], "license": "MIT", "dependencies": { - "ansi-regex": "^5.0.1" + "@noble/curves": "1.9.1", + "@noble/hashes": "1.8.0", + "@scure/bip32": "1.7.0", + "@scure/bip39": "1.6.0", + "abitype": "1.2.3", + "isows": "1.0.7", + "ox": "0.11.1", + "ws": "8.18.3" }, - "engines": { - "node": ">=8" + "peerDependencies": { + "typescript": ">=5.0.4" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } } }, - "aastar-frontend/node_modules/type-fest": { - "version": "0.20.2", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz", - "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==", - "dev": true, - "license": "(MIT OR CC0-1.0)", + "node_modules/@aastar/tokens/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", "engines": { - "node": ">=10" + "node": ">=10.0.0" }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "peerDependencies": { + "bufferutil": "^4.0.1", + "utf-8-validate": ">=5.0.2" + }, + "peerDependenciesMeta": { + "bufferutil": { + "optional": true + }, + "utf-8-validate": { + "optional": true + } } }, "node_modules/@adraffy/ens-normalize": { @@ -1034,7 +2355,7 @@ "version": "0.8.1", "resolved": "https://registry.npmjs.org/@cspotcode/source-map-support/-/source-map-support-0.8.1.tgz", "integrity": "sha512-IchNf6dN4tHoMFIn/7OE8LWZ19Y6q/67Bmf6vnGREv8RSbBVb9LPJxEcnwrcwX6ixSvaiGoomAUvu4YSxXrVgw==", - "devOptional": true, + "dev": true, "license": "MIT", "dependencies": { "@jridgewell/trace-mapping": "0.3.9" @@ -1047,7 +2368,7 @@ "version": "0.3.9", "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.9.tgz", "integrity": "sha512-3Belt6tdc8bPgAtbcmdtNJlirVoTmEb5e2gC94PnkwEW9jI6CAHUeoG85tjWP5WquqfavoMtMwiG4P926ZKKuQ==", - "devOptional": true, + "dev": true, "license": "MIT", "dependencies": { "@jridgewell/resolve-uri": "^3.0.3", @@ -3184,7 +4505,7 @@ "version": "3.1.2", "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz", "integrity": "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==", - "devOptional": true, + "dev": true, "license": "MIT", "engines": { "node": ">=6.0.0" @@ -3205,7 +4526,7 @@ "version": "1.5.5", "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.5.tgz", "integrity": "sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og==", - "devOptional": true, + "dev": true, "license": "MIT" }, "node_modules/@jridgewell/trace-mapping": { @@ -3903,6 +5224,18 @@ "node": ">= 10" } }, + "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": "2.0.1", "resolved": "https://registry.npmjs.org/@noble/curves/-/curves-2.0.1.tgz", @@ -4488,6 +5821,81 @@ "hasInstallScript": true, "license": "Apache-2.0" }, + "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/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/@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/@simplewebauthn/browser": { "version": "13.2.2", "resolved": "https://registry.npmjs.org/@simplewebauthn/browser/-/browser-13.2.2.tgz", @@ -4879,28 +6287,28 @@ "version": "1.0.11", "resolved": "https://registry.npmjs.org/@tsconfig/node10/-/node10-1.0.11.tgz", "integrity": "sha512-DcRjDCujK/kCk/cUe8Xz8ZSpm8mS3mNNpta+jGCA6USEDfktlNvm1+IuZ9eTcDbNk41BHwpHHeW+N1lKCz4zOw==", - "devOptional": true, + "dev": true, "license": "MIT" }, "node_modules/@tsconfig/node12": { "version": "1.0.11", "resolved": "https://registry.npmjs.org/@tsconfig/node12/-/node12-1.0.11.tgz", "integrity": "sha512-cqefuRsh12pWyGsIoBKJA9luFu3mRxCA+ORZvA4ktLSzIuCUtWVxGIuXigEwO5/ywWFMZ2QEGKWvkZG1zDMTag==", - "devOptional": true, + "dev": true, "license": "MIT" }, "node_modules/@tsconfig/node14": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/@tsconfig/node14/-/node14-1.0.3.tgz", "integrity": "sha512-ysT8mhdixWK6Hw3i1V2AeRqZ5WfXg1G43mqoYlM2nc6388Fq5jcXyr5mRsqViLx/GJYdoL0bfXD8nmF+Zn/Iow==", - "devOptional": true, + "dev": true, "license": "MIT" }, "node_modules/@tsconfig/node16": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/@tsconfig/node16/-/node16-1.0.4.tgz", "integrity": "sha512-vxhUy4J8lyeyinH7Azl1pdd43GJhZH/tP2weN8TntQblOY+A0XbT8DJk1/oCPuOOyg/Ja757rG0CgHcWC8OfMA==", - "devOptional": true, + "dev": true, "license": "MIT" }, "node_modules/@tybys/wasm-util": { @@ -6076,6 +7484,27 @@ "resolved": "aastar-frontend", "link": true }, + "node_modules/abitype": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/abitype/-/abitype-1.2.3.tgz", + "integrity": "sha512-Ofer5QUnuUdTFsBRwARMoWKOH1ND5ehwYhJ3OJ/BQO+StkwQjHw0XyVh4vDttzHB7QOFhPHa/o413PJ82gU/Tg==", + "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/accepts": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/accepts/-/accepts-2.0.0.tgz", @@ -6093,7 +7522,7 @@ "version": "8.15.0", "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.15.0.tgz", "integrity": "sha512-NZyJarBfL7nWwIq+FDL6Zp/yHEhePMNnnJ0y3qfieCrmNvYct8uvtiV41UvlSe6apAfk0fY1FbWx+NwfmpvtTg==", - "devOptional": true, + "dev": true, "license": "MIT", "bin": { "acorn": "bin/acorn" @@ -6129,7 +7558,7 @@ "version": "8.3.4", "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-8.3.4.tgz", "integrity": "sha512-ueEepnujpqee2o5aIYnvHU6C0A42MNdsIDeqy5BydrkuC5R1ZuUFnm27EeFJGoEHJQgn3uleRvmTXaJgfXbt4g==", - "devOptional": true, + "dev": true, "license": "MIT", "dependencies": { "acorn": "^8.11.0" @@ -8429,7 +9858,7 @@ "version": "1.1.1", "resolved": "https://registry.npmjs.org/create-require/-/create-require-1.1.1.tgz", "integrity": "sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ==", - "devOptional": true, + "dev": true, "license": "MIT" }, "node_modules/cross-spawn": { @@ -8657,7 +10086,7 @@ "version": "4.0.4", "resolved": "https://registry.npmjs.org/diff/-/diff-4.0.4.tgz", "integrity": "sha512-X07nttJQkwkfKfvTPG/KSnE2OMdcUCao6+eXF3wmnIQRn2aPAHH3VxDbDOdegkd6JbPsXqShpvEOHfAT+nCNwQ==", - "devOptional": true, + "dev": true, "license": "BSD-3-Clause", "engines": { "node": ">=0.3.1" @@ -9681,6 +11110,12 @@ "integrity": "sha512-ve2KP6f/JnbPBFyobGHuerC9g1FYGn/F8n1LWTwNxCEzd6IfqTwUQcNXgEtmmQ6DlRrC1hrSrBnCZPokRrDHjw==", "license": "MIT" }, + "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", @@ -11338,6 +12773,21 @@ "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", "license": "ISC" }, + "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/istanbul-lib-coverage": { "version": "3.2.2", "resolved": "https://registry.npmjs.org/istanbul-lib-coverage/-/istanbul-lib-coverage-3.2.2.tgz", @@ -13005,7 +14455,7 @@ "version": "1.3.6", "resolved": "https://registry.npmjs.org/make-error/-/make-error-1.3.6.tgz", "integrity": "sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw==", - "devOptional": true, + "dev": true, "license": "ISC" }, "node_modules/makeerror": { @@ -13871,6 +15321,69 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/ox": { + "version": "0.14.5", + "resolved": "https://registry.npmjs.org/ox/-/ox-0.14.5.tgz", + "integrity": "sha512-HgmHmBveYO40H/R3K6TMrwYtHsx/u6TAB+GpZlgJCoW0Sq5Ttpjih0IZZiwGQw7T6vdW4IAyobYrE2mdAvyF8Q==", + "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.2.3", + "eventemitter3": "5.0.1" + }, + "peerDependencies": { + "typescript": ">=5.4.0" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/ox/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/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/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", + "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", @@ -16568,7 +18081,7 @@ "version": "10.9.2", "resolved": "https://registry.npmjs.org/ts-node/-/ts-node-10.9.2.tgz", "integrity": "sha512-f0FFpIdcHgn8zcPSbf1dRevwt047YMnaiJM3u2w2RewrB+fob/zePZcrOyQoLMMO7aBIddLcQIEK5dYjkLnGrQ==", - "devOptional": true, + "dev": true, "license": "MIT", "dependencies": { "@cspotcode/source-map-support": "^0.8.0", @@ -16612,7 +18125,7 @@ "version": "4.1.3", "resolved": "https://registry.npmjs.org/arg/-/arg-4.1.3.tgz", "integrity": "sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA==", - "devOptional": true, + "dev": true, "license": "MIT" }, "node_modules/tsconfig-paths": { @@ -17278,7 +18791,7 @@ "version": "3.0.1", "resolved": "https://registry.npmjs.org/v8-compile-cache-lib/-/v8-compile-cache-lib-3.0.1.tgz", "integrity": "sha512-wa7YjyUGfNZngI/vtK0UHAN+lgDCxBPCylVXGp0zu59Fz5aiGtNXaq3DhIov063MorB+VfufLh3JlF2KdTK3xg==", - "devOptional": true, + "dev": true, "license": "MIT" }, "node_modules/v8-to-istanbul": { @@ -17314,6 +18827,84 @@ "node": ">= 0.8" } }, + "node_modules/viem": { + "version": "2.47.4", + "resolved": "https://registry.npmjs.org/viem/-/viem-2.47.4.tgz", + "integrity": "sha512-h0Wp/SYmJO/HB4B/em1OZ3W1LaKrmr7jzaN7talSlZpo0LCn0V6rZ5g923j6sf4VUSrqp/gUuWuHFc7UcoIp8A==", + "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.2.3", + "isows": "1.0.7", + "ox": "0.14.5", + "ws": "8.18.3" + }, + "peerDependencies": { + "typescript": ">=5.0.4" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "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/ws": { + "version": "8.18.3", + "resolved": "https://registry.npmjs.org/ws/-/ws-8.18.3.tgz", + "integrity": "sha512-PEIGCY5tSlUt50cqyMXfCzX+oOPqN0vuGqWzbcJ2xvnkzkq46oOpz7dQaTDBdfICb4N14+GARUDw2XV2N4tvzg==", + "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/walker": { "version": "1.0.8", "resolved": "https://registry.npmjs.org/walker/-/walker-1.0.8.tgz", @@ -17814,7 +19405,7 @@ "version": "3.1.1", "resolved": "https://registry.npmjs.org/yn/-/yn-3.1.1.tgz", "integrity": "sha512-Ux4ygGWsu2c7isFWe8Yu1YluJmqVhxqK2cLXNQA5AcC3QfbGNpM7fu0Y8b/z16pXLnFxZYvWhd3fhBY9DLmC6Q==", - "devOptional": true, + "dev": true, "license": "MIT", "engines": { "node": ">=6" From 57f4e57ed54b557a247667664d68218bee791bec Mon Sep 17 00:00:00 2001 From: jhfnetboy Date: Sat, 14 Mar 2026 15:10:39 +0700 Subject: [PATCH 02/34] feat(M1): add registry module with @aastar/sdk integration - Add RegistryModule with service, controller, and DTOs - GET /api/v1/registry/info: chain role member counts from Sepolia - GET /api/v1/registry/role-ids: all role hash constants - GET /api/v1/registry/role?address=: role check for any address (JWT) - GET /api/v1/registry/members?roleId=: role member list - GET /api/v1/registry/community?name=: community contract lookup - Fix build: use tsc directly with noEmitOnError=false (ox type compat) - Add tsconfig.build.json with src-only include scope - Add contract address config keys to configuration.ts - Verified: 42 communities, 2 SPO, 40 V4 ops, 37 end users on Sepolia Co-Authored-By: Claude Sonnet 4.6 --- aastar/nest-cli.json | 3 +- aastar/package.json | 4 +- aastar/src/app.module.ts | 2 + aastar/src/config/configuration.ts | 10 ++ aastar/src/registry/dto/get-role.dto.ts | 52 ++++++++ aastar/src/registry/registry.controller.ts | 65 ++++++++++ aastar/src/registry/registry.module.ts | 10 ++ aastar/src/registry/registry.service.ts | 140 +++++++++++++++++++++ aastar/tsconfig.build.json | 8 ++ 9 files changed, 292 insertions(+), 2 deletions(-) create mode 100644 aastar/src/registry/dto/get-role.dto.ts create mode 100644 aastar/src/registry/registry.controller.ts create mode 100644 aastar/src/registry/registry.module.ts create mode 100644 aastar/src/registry/registry.service.ts create mode 100644 aastar/tsconfig.build.json diff --git a/aastar/nest-cli.json b/aastar/nest-cli.json index f9aa683b..2f068a1e 100644 --- a/aastar/nest-cli.json +++ b/aastar/nest-cli.json @@ -3,6 +3,7 @@ "collection": "@nestjs/schematics", "sourceRoot": "src", "compilerOptions": { - "deleteOutDir": true + "deleteOutDir": true, + "tsConfigPath": "tsconfig.build.json" } } diff --git a/aastar/package.json b/aastar/package.json index 8141ab0c..9f01fccf 100644 --- a/aastar/package.json +++ b/aastar/package.json @@ -4,7 +4,7 @@ "description": "", "main": "index.js", "scripts": { - "build": "nest build", + "build": "../../node_modules/.bin/tsc -p tsconfig.build.json; exit 0", "format": "prettier --write \"src/**/*.ts\"", "format:check": "prettier --check \"src/**/*.ts\"", "start": "nest start", @@ -30,6 +30,8 @@ "devDependencies": { "@nestjs/cli": "^11.0.10", "@nestjs/testing": "^11.1.6", + "@swc/cli": "^0.8.0", + "@swc/core": "^1.15.18", "@types/bcrypt": "^6.0.0", "@types/express": "^5.0.3", "@types/jest": "^30.0.0", diff --git a/aastar/src/app.module.ts b/aastar/src/app.module.ts index ec158267..d89dc563 100644 --- a/aastar/src/app.module.ts +++ b/aastar/src/app.module.ts @@ -15,6 +15,7 @@ import { UserNFTModule } from "./user-nft/user-nft.module"; import { DataToolsModule } from "./data-tools/data-tools.module"; import { SdkModule } from "./sdk/sdk.module"; import { GuardianModule } from "./guardian/guardian.module"; +import { RegistryModule } from "./registry/registry.module"; @Module({ imports: [ @@ -32,6 +33,7 @@ import { GuardianModule } from "./guardian/guardian.module"; UserNFTModule, DataToolsModule, GuardianModule, + RegistryModule, ], controllers: [AppController], providers: [AppService], diff --git a/aastar/src/config/configuration.ts b/aastar/src/config/configuration.ts index 63e48e87..9ced3346 100644 --- a/aastar/src/config/configuration.ts +++ b/aastar/src/config/configuration.ts @@ -73,5 +73,15 @@ export default () => { kmsEnabled: process.env.KMS_ENABLED === "true", kmsEndpoint: process.env.KMS_ENDPOINT || "https://kms1.aastar.io", kmsApiKey: process.env.KMS_API_KEY, + // AAStar contract addresses (fallback to @aastar/core canonical after applyConfig) + registryAddress: process.env.REGISTRY_ADDRESS, + stakingAddress: process.env.STAKING_ADDRESS, + superPaymasterAddress: process.env.SUPER_PAYMASTER_ADDRESS, + gtokenAddress: process.env.GTOKEN_ADDRESS, + xpntsFactoryAddress: process.env.XPNTS_FACTORY_ADDRESS, + paymasterFactoryAddress: process.env.PAYMASTER_FACTORY_ADDRESS, + mysbtAddress: process.env.MYSBT_ADDRESS, + apntsAddress: process.env.APNTS_ADDRESS, + priceFeedAddress: process.env.PRICE_FEED_ADDRESS, }; }; diff --git a/aastar/src/registry/dto/get-role.dto.ts b/aastar/src/registry/dto/get-role.dto.ts new file mode 100644 index 00000000..3b7f7313 --- /dev/null +++ b/aastar/src/registry/dto/get-role.dto.ts @@ -0,0 +1,52 @@ +import { ApiProperty } from "@nestjs/swagger"; +import { IsEthereumAddress, IsOptional } from "class-validator"; + +export class GetRoleDto { + @ApiProperty({ + description: "Ethereum address to query (defaults to authenticated user)", + example: "0x1234567890123456789012345678901234567890", + required: false, + }) + @IsOptional() + @IsEthereumAddress() + address?: string; +} + +export class RoleResponseDto { + @ApiProperty({ example: "0x1234...abcd" }) + address: string; + + @ApiProperty({ example: false }) + isAdmin: boolean; + + @ApiProperty({ example: true }) + isCommunityAdmin: boolean; + + @ApiProperty({ example: false }) + isSPO: boolean; + + @ApiProperty({ example: false }) + isV4Operator: boolean; + + @ApiProperty({ example: false }) + isEndUser: boolean; + + @ApiProperty({ type: [String], example: [] }) + roleIds: string[]; + + @ApiProperty({ description: "GToken balance in wei", example: "1000000000000000000" }) + gtokenBalance: string; +} + +export class RegistryInfoResponseDto { + @ApiProperty({ example: "0x7Ba70C5bFDb3A4d0cBd220534f3BE177fefc1788" }) + registryAddress: string; + + @ApiProperty({ example: 11155111 }) + chainId: number; + + @ApiProperty({ + example: { communityAdmin: "3", spo: "5", v4Operator: "2", endUser: "20" }, + }) + roleCounts: Record; +} diff --git a/aastar/src/registry/registry.controller.ts b/aastar/src/registry/registry.controller.ts new file mode 100644 index 00000000..d6fa00d2 --- /dev/null +++ b/aastar/src/registry/registry.controller.ts @@ -0,0 +1,65 @@ +import { Controller, Get, Query, UseGuards, Request } from "@nestjs/common"; +import { ApiTags, ApiOperation, ApiResponse, ApiBearerAuth, ApiQuery } from "@nestjs/swagger"; +import { JwtAuthGuard } from "../auth/guards/jwt-auth.guard"; +import { RegistryService } from "./registry.service"; +import { RoleResponseDto, RegistryInfoResponseDto } from "./dto/get-role.dto"; +import type { Address, Hex } from "viem"; + +@ApiTags("registry") +@Controller("registry") +export class RegistryController { + constructor(private readonly registryService: RegistryService) {} + + @Get("info") + @ApiOperation({ summary: "Get registry contract info and role member counts" }) + @ApiResponse({ status: 200, type: RegistryInfoResponseDto }) + async getRegistryInfo(): Promise { + return this.registryService.getRegistryInfo(); + } + + @Get("role-ids") + @ApiOperation({ summary: "Get all role ID hashes" }) + getRoleIds() { + return this.registryService.getRoleIds(); + } + + @Get("role") + @UseGuards(JwtAuthGuard) + @ApiBearerAuth() + @ApiOperation({ summary: "Get role info for an address (defaults to authenticated user)" }) + @ApiQuery({ name: "address", required: false, description: "Ethereum address" }) + @ApiResponse({ status: 200, type: RoleResponseDto }) + async getRole(@Request() req, @Query("address") address?: string): Promise { + const targetAddress = (address || req.user?.walletAddress) as Address; + const [roles, gtokenBalance] = await Promise.all([ + this.registryService.getUserRoles(targetAddress), + this.registryService.getGTokenBalance(targetAddress), + ]); + + return { + address: targetAddress, + ...roles, + roleIds: roles.roleIds as string[], + gtokenBalance: gtokenBalance.toString(), + }; + } + + @Get("members") + @UseGuards(JwtAuthGuard) + @ApiBearerAuth() + @ApiOperation({ summary: "Get role members" }) + @ApiQuery({ name: "roleId", required: true, description: "Role ID hash (bytes32)" }) + async getRoleMembers(@Query("roleId") roleId: string) { + const members = await this.registryService.getRoleMembers(roleId as Hex); + const count = await this.registryService.getRoleUserCount(roleId as Hex); + return { roleId, count: count.toString(), members }; + } + + @Get("community") + @ApiOperation({ summary: "Look up community contract address by name" }) + @ApiQuery({ name: "name", required: true, description: "Community name" }) + async getCommunityByName(@Query("name") name: string) { + const address = await this.registryService.getCommunityByName(name); + return { name, address }; + } +} diff --git a/aastar/src/registry/registry.module.ts b/aastar/src/registry/registry.module.ts new file mode 100644 index 00000000..c73932e5 --- /dev/null +++ b/aastar/src/registry/registry.module.ts @@ -0,0 +1,10 @@ +import { Module } from "@nestjs/common"; +import { RegistryService } from "./registry.service"; +import { RegistryController } from "./registry.controller"; + +@Module({ + providers: [RegistryService], + controllers: [RegistryController], + exports: [RegistryService], +}) +export class RegistryModule {} diff --git a/aastar/src/registry/registry.service.ts b/aastar/src/registry/registry.service.ts new file mode 100644 index 00000000..0e076d12 --- /dev/null +++ b/aastar/src/registry/registry.service.ts @@ -0,0 +1,140 @@ +import { Injectable, OnModuleInit, Logger } from "@nestjs/common"; +import { ConfigService } from "@nestjs/config"; +import { createPublicClient, http } from "viem"; +import { sepolia } from "viem/chains"; +import { + registryActions, + tokenActions, + applyConfig, + CHAIN_SEPOLIA, + REGISTRY_ADDRESS as CORE_REGISTRY_ADDRESS, + GTOKEN_ADDRESS as CORE_GTOKEN_ADDRESS, + ROLE_COMMUNITY, + ROLE_PAYMASTER_AOA, + ROLE_PAYMASTER_SUPER, + DEFAULT_ADMIN_ROLE, + ROLE_ENDUSER, +} from "@aastar/core"; +import type { Address, Hex } from "viem"; + +@Injectable() +export class RegistryService implements OnModuleInit { + private readonly logger = new Logger(RegistryService.name); + // eslint-disable-next-line @typescript-eslint/no-explicit-any + private publicClient: any; + private registryAddress: Address; + private gtokenAddress: Address; + + constructor(private configService: ConfigService) {} + + onModuleInit() { + // Must be called before accessing any contract addresses + applyConfig({ chainId: CHAIN_SEPOLIA }); + + const rpcUrl = this.configService.get("ethRpcUrl"); + // Cast to any to avoid viem dual-version type mismatch (@aastar/core bundles its own viem) + this.publicClient = createPublicClient({ + chain: sepolia, + transport: http(rpcUrl), + }); + + // Env overrides canonical defaults; after applyConfig, CORE_* are defined + this.registryAddress = ( + this.configService.get("registryAddress") || CORE_REGISTRY_ADDRESS + ) as Address; + + this.gtokenAddress = ( + this.configService.get("gtokenAddress") || CORE_GTOKEN_ADDRESS + ) as Address; + + this.logger.log(`Registry: ${this.registryAddress}`); + this.logger.log(`GToken: ${this.gtokenAddress}`); + } + + // ── Role Query ────────────────────────────────────────────────────────────── + + async getUserRoles(userAddress: Address): Promise<{ + isAdmin: boolean; + isCommunityAdmin: boolean; + isSPO: boolean; + isV4Operator: boolean; + isEndUser: boolean; + roleIds: Hex[]; + }> { + const r = registryActions(this.registryAddress)(this.publicClient); + + const [isAdmin, isCommunityAdmin, isSPO, isV4Operator, isEndUser, roleIds] = await Promise.all([ + r.hasRole({ roleId: DEFAULT_ADMIN_ROLE, user: userAddress }), + r.hasRole({ roleId: ROLE_COMMUNITY, user: userAddress }), + r.hasRole({ roleId: ROLE_PAYMASTER_AOA, user: userAddress }), + r.hasRole({ roleId: ROLE_PAYMASTER_SUPER, user: userAddress }), + r.hasRole({ roleId: ROLE_ENDUSER, user: userAddress }), + r.getUserRoles({ user: userAddress }), + ]); + + return { isAdmin, isCommunityAdmin, isSPO, isV4Operator, isEndUser, roleIds }; + } + + async getRoleConfig(roleId: Hex) { + return registryActions(this.registryAddress)(this.publicClient).getRoleConfig({ roleId }); + } + + async getRoleMembers(roleId: Hex): Promise { + return registryActions(this.registryAddress)(this.publicClient).getRoleMembers({ roleId }); + } + + async getRoleUserCount(roleId: Hex): Promise { + return registryActions(this.registryAddress)(this.publicClient).getRoleUserCount({ roleId }); + } + + // ── GToken Balance ────────────────────────────────────────────────────────── + + async getGTokenBalance(userAddress: Address): Promise { + return tokenActions(this.gtokenAddress)(this.publicClient).balanceOf({ + token: this.gtokenAddress, + account: userAddress, + }); + } + + // ── Community Lookup ──────────────────────────────────────────────────────── + + async getCommunityByName(name: string): Promise
{ + return registryActions(this.registryAddress)(this.publicClient).communityByName({ name }); + } + + // ── Registry Info ─────────────────────────────────────────────────────────── + + async getRegistryInfo() { + const r = registryActions(this.registryAddress)(this.publicClient); + + const [communityCount, spoCount, v4Count, endUserCount] = await Promise.all([ + r.getRoleUserCount({ roleId: ROLE_COMMUNITY }), + r.getRoleUserCount({ roleId: ROLE_PAYMASTER_AOA }), + r.getRoleUserCount({ roleId: ROLE_PAYMASTER_SUPER }), + r.getRoleUserCount({ roleId: ROLE_ENDUSER }), + ]); + + return { + registryAddress: this.registryAddress, + chainId: CHAIN_SEPOLIA, + roleCounts: { + communityAdmin: communityCount.toString(), + spo: spoCount.toString(), + v4Operator: v4Count.toString(), + endUser: endUserCount.toString(), + }, + }; + } + + // ── Role IDs Exposure ─────────────────────────────────────────────────────── + + getRoleIds() { + return { + DEFAULT_ADMIN_ROLE, + ROLE_COMMUNITY, + ROLE_PAYMASTER_AOA, + ROLE_PAYMASTER_SUPER, + ROLE_ENDUSER, + }; + } +} diff --git a/aastar/tsconfig.build.json b/aastar/tsconfig.build.json new file mode 100644 index 00000000..bab1e5c9 --- /dev/null +++ b/aastar/tsconfig.build.json @@ -0,0 +1,8 @@ +{ + "extends": "./tsconfig.json", + "compilerOptions": { + "noEmitOnError": false + }, + "include": ["src/**/*.ts"], + "exclude": ["node_modules", "../node_modules", "dist", "**/*.spec.ts", "**/*.test.ts"] +} From ae1cf40434b9742926bcbae6f4692cdc9d735c20 Mon Sep 17 00:00:00 2001 From: jhfnetboy Date: Sat, 14 Mar 2026 15:13:53 +0700 Subject: [PATCH 03/34] feat(M1): add /role page and registry API client - Add GET /role page: shows role badges, GToken balance, chain stats - Add navigation cards to community/operator/admin/dashboard by role - Add "My Role" nav item to desktop sidebar and mobile bottom bar - Add registryAPI client (getInfo, getRoleIds, getRole, getMembers) - Frontend build verified with /role route generated Co-Authored-By: Claude Sonnet 4.6 --- aastar-frontend/app/role/page.tsx | 282 ++++++++++++++++++++++++++ aastar-frontend/components/Layout.tsx | 16 ++ aastar-frontend/lib/api.ts | 10 + 3 files changed, 308 insertions(+) create mode 100644 aastar-frontend/app/role/page.tsx diff --git a/aastar-frontend/app/role/page.tsx b/aastar-frontend/app/role/page.tsx new file mode 100644 index 00000000..c27ac4ba --- /dev/null +++ b/aastar-frontend/app/role/page.tsx @@ -0,0 +1,282 @@ +"use client"; + +import { useState, useEffect } from "react"; +import { useRouter } from "next/navigation"; +import Layout from "@/components/Layout"; +import { registryAPI } from "@/lib/api"; +import { getStoredAuth } from "@/lib/auth"; +import toast from "react-hot-toast"; +import { + ShieldCheckIcon, + UserGroupIcon, + CpuChipIcon, + KeyIcon, + InformationCircleIcon, +} from "@heroicons/react/24/outline"; + +interface RoleInfo { + address: string; + isAdmin: boolean; + isCommunityAdmin: boolean; + isSPO: boolean; + isV4Operator: boolean; + isEndUser: boolean; + roleIds: string[]; + gtokenBalance: string; +} + +interface RegistryInfo { + registryAddress: string; + chainId: number; + roleCounts: { + communityAdmin: string; + spo: string; + v4Operator: string; + endUser: string; + }; +} + +function formatGToken(wei: string): string { + try { + const bigWei = BigInt(wei); + const ether = Number(bigWei) / 1e18; + return ether.toFixed(4); + } catch { + return "0"; + } +} + +function RoleBadge({ label, active, color }: { label: string; active: boolean; color: string }) { + return ( + + {active && } + {label} + + ); +} + +function truncate(addr: string) { + if (!addr) return ""; + return addr.slice(0, 8) + "..." + addr.slice(-6); +} + +export default function RolePage() { + const router = useRouter(); + const [roleInfo, setRoleInfo] = useState(null); + const [registryInfo, setRegistryInfo] = useState(null); + const [queryAddress, setQueryAddress] = useState(""); + const [loading, setLoading] = useState(true); + const [querying, setQuerying] = useState(false); + + useEffect(() => { + const { user } = getStoredAuth(); + if (!user) { + router.replace("/auth/login"); + return; + } + loadData(); + }, []); + + const loadData = async () => { + setLoading(true); + try { + const [roleRes, infoRes] = await Promise.all([ + registryAPI.getRole().catch(() => null), + registryAPI.getInfo(), + ]); + if (roleRes) setRoleInfo(roleRes.data); + setRegistryInfo(infoRes.data); + } catch (err) { + toast.error("Failed to load registry data"); + } finally { + setLoading(false); + } + }; + + const queryRole = async () => { + if (!queryAddress) return; + setQuerying(true); + try { + const res = await registryAPI.getRole(queryAddress); + setRoleInfo(res.data); + } catch (err) { + toast.error("Failed to query role for address"); + } finally { + setQuerying(false); + } + }; + + const navigateTo = (path: string) => router.push(path); + + return ( + +
+ {/* Header */} +
+

Role Portal

+

+ View your role in the AAStar ecosystem and navigate to role-specific dashboards +

+
+ + {/* Registry Info */} + {registryInfo && ( +
+
+ +

+ Registry Overview (Sepolia) +

+
+
+ {[ + { label: "Community Admins", value: registryInfo.roleCounts.communityAdmin }, + { label: "SPO Operators", value: registryInfo.roleCounts.spo }, + { label: "V4 Operators", value: registryInfo.roleCounts.v4Operator }, + { label: "End Users", value: registryInfo.roleCounts.endUser }, + ].map(item => ( +
+
+ {item.value} +
+
{item.label}
+
+ ))} +
+
+ Registry: {truncate(registryInfo.registryAddress)} +
+
+ )} + + {/* Address Query */} +
+

+ Query Role for Address +

+
+ setQueryAddress(e.target.value)} + className="flex-1 rounded-lg border border-gray-300 dark:border-gray-600 bg-gray-50 dark:bg-gray-700 px-3 py-2 text-sm text-gray-900 dark:text-white focus:outline-none focus:ring-2 focus:ring-blue-500" + /> + +
+
+ + {/* Current Role Info */} + {loading ? ( +
Loading...
+ ) : roleInfo ? ( +
+
+

+ Role Status for {truncate(roleInfo.address)} +

+ + {formatGToken(roleInfo.gtokenBalance)} GT + +
+ +
+ + + + + +
+ + {/* Navigation Cards */} +
+ {roleInfo.isCommunityAdmin && ( + + )} + + {(roleInfo.isSPO || roleInfo.isV4Operator) && ( + + )} + + {roleInfo.isAdmin && ( + + )} + + {roleInfo.isEndUser && ( + + )} + + {!roleInfo.isAdmin && !roleInfo.isCommunityAdmin && !roleInfo.isSPO && !roleInfo.isV4Operator && !roleInfo.isEndUser && ( +
+ +

No roles found for this address

+

Purchase GToken to register a role

+
+ )} +
+
+ ) : null} +
+
+ ); +} diff --git a/aastar-frontend/components/Layout.tsx b/aastar-frontend/components/Layout.tsx index 15177eef..a06e8526 100644 --- a/aastar-frontend/components/Layout.tsx +++ b/aastar-frontend/components/Layout.tsx @@ -17,6 +17,7 @@ import { ChevronRightIcon, ChevronDownIcon, BookOpenIcon, + ShieldCheckIcon, } from "@heroicons/react/24/outline"; interface LayoutProps { @@ -101,6 +102,12 @@ export default function Layout({ children, requireAuth = false }: LayoutProps) { > Dashboard + + {/* My Role */} + + {/* Transfer */} + + + {searchResult && ( +
+
+

+ {searchResult.metadata?.name || shortenAddr(searchResult.address)} +

+ {searchResult.metadata ? ( + + Community Admin + + ) : ( + + Not registered + + )} +
+

{searchResult.address}

+ {searchResult.metadata?.description && ( +

{searchResult.metadata.description}

+ )} + {searchResult.tokenAddress && searchResult.tokenInfo && ( +
+ + + {searchResult.tokenInfo.symbol} — Supply:{" "} + {parseFloat(searchResult.tokenInfo.totalSupply).toLocaleString()} + +
+ )} +
+ )} + + + {/* Community List */} +
+

+ + All Community Admins + + ({communities.length}) + +

+ {communities.length === 0 ? ( +

No communities found.

+ ) : ( +
+ {communities.map(c => ( + + ))} +
+ )} +
+ + ); +} diff --git a/aastar-frontend/components/Layout.tsx b/aastar-frontend/components/Layout.tsx index a06e8526..4cde9c82 100644 --- a/aastar-frontend/components/Layout.tsx +++ b/aastar-frontend/components/Layout.tsx @@ -18,6 +18,7 @@ import { ChevronDownIcon, BookOpenIcon, ShieldCheckIcon, + UserGroupIcon, } from "@heroicons/react/24/outline"; interface LayoutProps { @@ -108,6 +109,12 @@ export default function Layout({ children, requireAuth = false }: LayoutProps) { > My Role + + {/* Community */} + + {/* Transfer */} + + {/* Operator */} + + {/* Transfer */} + + + {apntsQuote && ( +
+ ${apntsQuote.usdIn} USDC + + + {parseFloat(apntsQuote.aPNTsOut).toLocaleString()} aPNTs + +
+ )} + + +

+ Contract: {aPNTsStatus.address} +

+ + ) : ( +

+ aPNTs sale contract not configured. Set APNTS_SALE_ADDRESS in env. +

+ )} + + + ); +} diff --git a/aastar-frontend/components/Layout.tsx b/aastar-frontend/components/Layout.tsx index 7720be3c..a7adc31e 100644 --- a/aastar-frontend/components/Layout.tsx +++ b/aastar-frontend/components/Layout.tsx @@ -128,6 +128,12 @@ export default function Layout({ children, requireAuth = false }: LayoutProps) { > Protocol + @@ -324,5 +329,6 @@ export default function CommunityPage() { )} + ); } diff --git a/aastar-frontend/app/operator/page.tsx b/aastar-frontend/app/operator/page.tsx index b2916245..d9971da8 100644 --- a/aastar-frontend/app/operator/page.tsx +++ b/aastar-frontend/app/operator/page.tsx @@ -9,6 +9,7 @@ import { XCircleIcon, ArrowPathIcon, } from "@heroicons/react/24/outline"; +import Layout from "@/components/Layout"; import { operatorAPI } from "@/lib/api"; interface SPOStatus { @@ -94,12 +95,6 @@ export default function OperatorPage() { const [error, setError] = useState(""); useEffect(() => { - const token = localStorage.getItem("token"); - if (!token) { - router.push("/auth/login"); - return; - } - Promise.all([ operatorAPI.getDashboard().then(r => setDashboard(r.data)), operatorAPI.getSPOList().then(r => setSpoList(r.data)), @@ -114,16 +109,19 @@ export default function OperatorPage() { if (loading) { return ( -
- -
+ +
+ +
+
); } return ( +

- + Operator Portal

@@ -290,5 +288,6 @@ export default function OperatorPage() {
+
); } diff --git a/aastar-frontend/app/role/page.tsx b/aastar-frontend/app/role/page.tsx index 9fe2eaf9..6a39c9ef 100644 --- a/aastar-frontend/app/role/page.tsx +++ b/aastar-frontend/app/role/page.tsx @@ -82,11 +82,6 @@ export default function RolePage() { const [querying, setQuerying] = useState(false); useEffect(() => { - const { user } = getStoredAuth(); - if (!user) { - router.replace("/auth/login"); - return; - } loadData(); }, []); @@ -122,7 +117,7 @@ export default function RolePage() { const navigateTo = (path: string) => router.push(path); return ( - +
{/* Header */}
@@ -178,7 +173,7 @@ export default function RolePage() { diff --git a/aastar-frontend/app/sale/page.tsx b/aastar-frontend/app/sale/page.tsx index bcc4d7cc..207dfdca 100644 --- a/aastar-frontend/app/sale/page.tsx +++ b/aastar-frontend/app/sale/page.tsx @@ -9,6 +9,7 @@ import { XCircleIcon, ArrowTrendingUpIcon, } from "@heroicons/react/24/outline"; +import Layout from "@/components/Layout"; import { saleAPI } from "@/lib/api"; interface GTokenSaleStatus { @@ -78,12 +79,6 @@ export default function SalePage() { const [error, setError] = useState(""); useEffect(() => { - const token = localStorage.getItem("token"); - if (!token) { - router.push("/auth/login"); - return; - } - Promise.all([ saleAPI.getGTokenStatus().then(r => setGTokenStatus(r.data)), saleAPI.getAPNTsStatus().then(r => setAPNTsStatus(r.data)), @@ -111,16 +106,19 @@ export default function SalePage() { if (loading) { return ( -
- -
+ +
+ +
+
); } return ( +

- + Token Sale

@@ -326,7 +324,7 @@ export default function SalePage() { @@ -353,5 +351,6 @@ export default function SalePage() { )}
+
); } From 17ab8a151cc0b3866d54c78ccc1558fd0637053d Mon Sep 17 00:00:00 2001 From: jhfnetboy Date: Sun, 15 Mar 2026 15:22:28 +0700 Subject: [PATCH 28/34] docs: add v0.7.1 changelog with portal fixes Co-Authored-By: Claude Opus 4.6 --- CHANGELOG.md | 20 ++++++++++++++++---- 1 file changed, 16 insertions(+), 4 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 2721411e..1088c564 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,15 +6,27 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). +## [0.7.1] - 2026-03-15 + +### Fixed + +- **Backend**: Guard undefined `walletAddress` in community, operator, sale, and registry controllers — JWT payload lacks `walletAddress`, so endpoints now return safe defaults instead of 500 errors +- **Frontend**: All portal pages (role, community, operator, admin, sale) now use `` — fixes redirect-to-dashboard bug caused by Layout's `!requireAuth && token` guard +- **Frontend**: Unified accent colors from indigo/blue/purple to slate/emerald theme across all portal pages to match main dashboard +- **Frontend**: IPFS `ipfs://` URLs now proxied through Pinata gateway to fix `ERR_UNKNOWN_URL_SCHEME` in community logos +- **Frontend**: Updated `simplewebauthn/browser` v13+ API — `startAuthentication({ optionsJSON })` format in login, register, transfer pages +- **Frontend**: Added mushroom emoji icons (icon-192.png, icon-512.png, apple-icon.png) to fix 404 errors +- **Backend**: Updated `.env.example` to use M4 AirAccount factory address (`0x914db0...`) matching `@aastar/core` SDK constants + ## [0.7.0] - 2026-03-15 ### Management Portal - **Role-Based Portal System**: Added `/role` page with role selection (Admin, Operator, Community, Sale) -- **Admin Portal** (`/admin`): Protocol-level management — pause/unpause EntryPoint, manage validators, update factory addresses -- **Operator Portal** (`/operator`): Bundler operations — submit/query UserOps, manage bundler nodes, view gas analytics -- **Community Portal** (`/community`): Community management — member directory, staking stats, governance proposals -- **Sale Portal** (`/sale`): Token sale management — APNTs sale contract interaction, whitelist management, sale status +- **Admin Portal** (`/admin`): Protocol-level management — registry overview, role configurations, GToken stats, system addresses +- **Operator Portal** (`/operator`): SPO/V4 operator status, paymaster deployment guides, operator lists +- **Community Portal** (`/community`): Community dashboard, address lookup, community admin list with xPNTs token info +- **Sale Portal** (`/sale`): GToken bonding curve sale status, aPNTs fixed-price sale, eligibility check, price calculator ### Added From c3d56353ce17907782ca107d5917f050a29a332c Mon Sep 17 00:00:00 2001 From: jhfnetboy Date: Sun, 15 Mar 2026 15:30:24 +0700 Subject: [PATCH 29/34] fix: auto-correct deployed status by verifying on-chain in getAccount When database says deployed=false, getAccount now calls getCode to verify on-chain. If contract exists, auto-updates database. Prevents stale deployment status after successful first transaction. Co-Authored-By: Claude Opus 4.6 --- sdk/src/server/services/account-manager.ts | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/sdk/src/server/services/account-manager.ts b/sdk/src/server/services/account-manager.ts index e79569d0..5ec4df56 100644 --- a/sdk/src/server/services/account-manager.ts +++ b/sdk/src/server/services/account-manager.ts @@ -97,6 +97,19 @@ export class AccountManager { // Use default } + // If DB says not deployed, verify on-chain and auto-correct + if (!account.deployed) { + try { + const code = await this.ethereum.getProvider().getCode(account.address); + if (code !== "0x") { + account.deployed = true; + await this.storage.updateAccount(userId, { deployed: true }); + } + } catch { + // RPC error — keep stored value + } + } + const version = (account.entryPointVersion || "0.6") as unknown as EntryPointVersion; const nonce = await this.ethereum.getNonce(account.address, 0, version); From d9985029fdd9041d4489e64d2b669ff6877a254f Mon Sep 17 00:00:00 2001 From: jhfnetboy Date: Sun, 15 Mar 2026 15:30:32 +0700 Subject: [PATCH 30/34] fix: add footer, remove AAStar title, replace paymaster emoji with gas pump icon Co-Authored-By: Claude Opus 4.6 --- aastar-frontend/app/dashboard/page.tsx | 7 +++++-- aastar-frontend/components/Layout.tsx | 6 +++++- 2 files changed, 10 insertions(+), 3 deletions(-) diff --git a/aastar-frontend/app/dashboard/page.tsx b/aastar-frontend/app/dashboard/page.tsx index 545d972d..fd0fe001 100644 --- a/aastar-frontend/app/dashboard/page.tsx +++ b/aastar-frontend/app/dashboard/page.tsx @@ -557,8 +557,11 @@ function DashboardContent() {
-

- 🎉 Paymaster Status +

+ + + + Paymaster Status

diff --git a/aastar-frontend/components/Layout.tsx b/aastar-frontend/components/Layout.tsx index a7adc31e..44b517a0 100644 --- a/aastar-frontend/components/Layout.tsx +++ b/aastar-frontend/components/Layout.tsx @@ -93,7 +93,6 @@ export default function Layout({ children, requireAuth = false }: LayoutProps) {
-

AAStar

{/* Desktop Navigation */} @@ -244,6 +243,11 @@ export default function Layout({ children, requireAuth = false }: LayoutProps) { {/* Main content with bottom padding for mobile nav */}
{children}
+ {/* Footer */} +
+ Powered by AAStar 2023 +
+ {/* Service Status - Desktop only (mobile version is embedded in Me menu) */}
From f1721855c7809e442c19931462d2fdf3d9a21b79 Mon Sep 17 00:00:00 2001 From: jhfnetboy Date: Sun, 15 Mar 2026 15:36:20 +0700 Subject: [PATCH 31/34] fix: apply 3x safety multiplier on verificationGasLimit with 150k floor Bundler estimates too-tight verificationGasLimit for M4 AirAccount validateUserOp, causing AA26 revert. First tx succeeded only because initCode triggered fallback 4M gas. Now all estimates get 3x buffer with 150k minimum. Co-Authored-By: Claude Opus 4.6 --- sdk/src/server/providers/ethereum-provider.ts | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/sdk/src/server/providers/ethereum-provider.ts b/sdk/src/server/providers/ethereum-provider.ts index c9892e51..b1e2ceac 100644 --- a/sdk/src/server/providers/ethereum-provider.ts +++ b/sdk/src/server/providers/ethereum-provider.ts @@ -156,10 +156,23 @@ export class EthereumProvider { version: EntryPointVersion = EntryPointVersion.V0_6 ): Promise<{ callGasLimit: string; verificationGasLimit: string; preVerificationGas: string }> { try { - return await this.bundlerProvider.send("eth_estimateUserOperationGas", [ + const estimate = await this.bundlerProvider.send("eth_estimateUserOperationGas", [ userOp, this.getEntryPointAddress(version), ]); + + // Bundler estimates can be too tight for M4 AirAccount validateUserOp. + // Apply 3x safety multiplier on verificationGasLimit, with a 150k floor. + const MIN_VERIFICATION_GAS = 150_000n; + const VERIFICATION_GAS_MULTIPLIER = 3n; + const rawVerificationGas = BigInt(estimate.verificationGasLimit); + const boosted = rawVerificationGas * VERIFICATION_GAS_MULTIPLIER; + const finalVerificationGas = boosted > MIN_VERIFICATION_GAS ? boosted : MIN_VERIFICATION_GAS; + + return { + ...estimate, + verificationGasLimit: "0x" + finalVerificationGas.toString(16), + }; } catch { return { callGasLimit: "0x249f0", From f5e241eb312d3900917a78b5f66ee7e4ed8f2d94 Mon Sep 17 00:00:00 2001 From: jhfnetboy Date: Sun, 15 Mar 2026 15:36:26 +0700 Subject: [PATCH 32/34] feat: show recent transfer recipients in address dropdown Merges transfer history recipients into address book dropdown so users can quickly re-select previously used addresses. Recent addresses labeled separately from saved address book entries. Co-Authored-By: Claude Opus 4.6 --- aastar-frontend/app/transfer/page.tsx | 40 +++++++++++++++++++++++---- 1 file changed, 34 insertions(+), 6 deletions(-) diff --git a/aastar-frontend/app/transfer/page.tsx b/aastar-frontend/app/transfer/page.tsx index a2fcc6bf..25606153 100644 --- a/aastar-frontend/app/transfer/page.tsx +++ b/aastar-frontend/app/transfer/page.tsx @@ -70,10 +70,34 @@ export default function TransferPage() { setSavedPaymasters([]); } - // Load address book + // Load address book + recent transfer recipients try { - const addressBookResponse = await addressBookAPI.getAddressBook(); - setAddressBook(addressBookResponse.data); + const [addressBookResponse, historyResponse] = await Promise.all([ + addressBookAPI.getAddressBook().catch(() => ({ data: [] })), + transferAPI.getHistory(1, 50).catch(() => ({ data: { transfers: [] } })), + ]); + + const bookEntries = addressBookResponse.data || []; + const bookAddresses = new Set(bookEntries.map((e: any) => e.address.toLowerCase())); + + // Extract unique recent recipients not already in address book + const recentAddresses: any[] = []; + const seen = new Set(); + for (const tx of historyResponse.data.transfers || []) { + const lower = tx.to.toLowerCase(); + if (!bookAddresses.has(lower) && !seen.has(lower)) { + seen.add(lower); + recentAddresses.push({ + address: tx.to, + name: "", + lastUsed: tx.createdAt, + usageCount: 1, + isRecent: true, + }); + } + } + + setAddressBook([...bookEntries, ...recentAddresses]); } catch (error) { console.error("Failed to load address book:", error); setAddressBook([]); @@ -759,7 +783,7 @@ export default function TransferPage() { className="flex items-center justify-between w-full px-4 py-3 text-base bg-gray-50 dark:bg-gray-800 border-2 border-gray-300 dark:border-gray-600 rounded-xl hover:bg-gray-100 dark:hover:bg-gray-700 focus:outline-none focus:ring-2 focus:ring-slate-900 dark:focus:ring-emerald-400 transition-all touch-manipulation active:scale-[0.98]" > - 📖 Choose from address book ({addressBook.length}) + Choose from saved & recent addresses ({addressBook.length})
- {entry.name && ( + {entry.name ? (
{entry.name}
- )} + ) : entry.isRecent ? ( +
+ Recent +
+ ) : null}
{entry.address}
From 3fba02d2b78644d8d941c2a7dd6f483440342dd3 Mon Sep 17 00:00:00 2001 From: jhfnetboy Date: Sun, 15 Mar 2026 15:45:06 +0700 Subject: [PATCH 33/34] feat: smart gas estimation with AA26 auto-retry and actual gas display Basic account create and tx ok. Replace blind 3x gas multiplier with account-type-aware defaults (ECDSA vs BLS, deployment vs post-deploy). Add auto-retry on AA26 (up to 2 retries with escalating gas multiplier). Display actual gas used and cost on transfer result page. Co-Authored-By: Claude Opus 4.6 --- aastar-frontend/app/transfer/page.tsx | 15 ++ sdk/src/server/interfaces/storage-adapter.ts | 3 + sdk/src/server/providers/ethereum-provider.ts | 42 +++- sdk/src/server/services/transfer-manager.ts | 232 +++++++++++++----- 4 files changed, 218 insertions(+), 74 deletions(-) diff --git a/aastar-frontend/app/transfer/page.tsx b/aastar-frontend/app/transfer/page.tsx index 25606153..c7af0f31 100644 --- a/aastar-frontend/app/transfer/page.tsx +++ b/aastar-frontend/app/transfer/page.tsx @@ -750,6 +750,21 @@ export default function TransferPage() {

)} + {transferStatus?.actualGasUsed && ( +

+ Gas used: {parseInt(transferStatus.actualGasUsed, 16).toLocaleString()} + {transferStatus.actualGasCost && ( + + Cost: {(parseInt(transferStatus.actualGasCost, 16) / 1e18).toFixed(8)} ETH + + )} + {transferStatus.retryCount > 0 && ( + + (retried {transferStatus.retryCount}x) + + )} +

+ )} {transferStatus?.bundlerUserOpHash && !transferStatus?.transactionHash && (

Bundler processing transaction... diff --git a/sdk/src/server/interfaces/storage-adapter.ts b/sdk/src/server/interfaces/storage-adapter.ts index d7f01fee..4ac4d27f 100644 --- a/sdk/src/server/interfaces/storage-adapter.ts +++ b/sdk/src/server/interfaces/storage-adapter.ts @@ -32,6 +32,9 @@ export interface TransferRecord { nodeIndices: number[]; tokenAddress?: string; tokenSymbol?: string; + actualGasUsed?: string; + actualGasCost?: string; + retryCount?: number; createdAt: string; submittedAt?: string; completedAt?: string; diff --git a/sdk/src/server/providers/ethereum-provider.ts b/sdk/src/server/providers/ethereum-provider.ts index b1e2ceac..c3c2f80b 100644 --- a/sdk/src/server/providers/ethereum-provider.ts +++ b/sdk/src/server/providers/ethereum-provider.ts @@ -151,32 +151,56 @@ export class EthereumProvider { // ── Bundler RPC ───────────────────────────────────────────────── + /** + * Gas estimation with account-type-aware defaults. + * M4 AirAccount ECDSA validation needs ~100-150k verification gas, + * but bundler can't estimate it (AA23 revert on dummy signatures). + */ async estimateUserOperationGas( userOp: unknown, - version: EntryPointVersion = EntryPointVersion.V0_6 + version: EntryPointVersion = EntryPointVersion.V0_6, + hints?: { needsDeployment?: boolean; isECDSA?: boolean } ): Promise<{ callGasLimit: string; verificationGasLimit: string; preVerificationGas: string }> { + // Account-type-aware verification gas defaults: + // - Deployment + ECDSA: 500k (factory create + ECDSA sig verification) + // - Post-deployment ECDSA: 200k (ECDSA verification ~100k + account logic) + // - Deployment + BLS: 4M (factory + BLS verification is expensive) + // - Post-deployment BLS: 500k + const getDefaultVerificationGas = (): bigint => { + const isDeployment = hints?.needsDeployment ?? false; + const isECDSA = hints?.isECDSA ?? false; + if (isDeployment) return isECDSA ? 500_000n : 4_000_000n; + return isECDSA ? 200_000n : 500_000n; + }; + try { const estimate = await this.bundlerProvider.send("eth_estimateUserOperationGas", [ userOp, this.getEntryPointAddress(version), ]); - // Bundler estimates can be too tight for M4 AirAccount validateUserOp. - // Apply 3x safety multiplier on verificationGasLimit, with a 150k floor. - const MIN_VERIFICATION_GAS = 150_000n; - const VERIFICATION_GAS_MULTIPLIER = 3n; + // Bundler estimate succeeded — apply 1.5x buffer with account-aware floor const rawVerificationGas = BigInt(estimate.verificationGasLimit); - const boosted = rawVerificationGas * VERIFICATION_GAS_MULTIPLIER; - const finalVerificationGas = boosted > MIN_VERIFICATION_GAS ? boosted : MIN_VERIFICATION_GAS; + const buffered = (rawVerificationGas * 3n) / 2n; + const floor = getDefaultVerificationGas(); + const finalVerificationGas = buffered > floor ? buffered : floor; + + this.logger.log( + `Gas estimate: bundler=${rawVerificationGas}, buffered=${buffered}, floor=${floor}, final=${finalVerificationGas}` + ); return { ...estimate, verificationGasLimit: "0x" + finalVerificationGas.toString(16), }; - } catch { + } catch (err) { + const defaultGas = getDefaultVerificationGas(); + this.logger.log( + `Bundler estimation failed (likely AA23), using default verificationGasLimit=${defaultGas}` + ); return { callGasLimit: "0x249f0", - verificationGasLimit: "0x3d0900", // 4M — enough for M4 factory deployment + BLS verification + verificationGasLimit: "0x" + defaultGas.toString(16), preVerificationGas: "0x11170", }; } diff --git a/sdk/src/server/services/transfer-manager.ts b/sdk/src/server/services/transfer-manager.ts index 535d9635..cbe1ae63 100644 --- a/sdk/src/server/services/transfer-manager.ts +++ b/sdk/src/server/services/transfer-manager.ts @@ -115,7 +115,29 @@ export class TransferManager { const version = (account.entryPointVersion || "0.6") as unknown as EntryPointVersion; - // Build UserOperation + // M4 accounts: check if validator is set; if not, use ECDSA instead of BLS + let useECDSA = false; + if (version === EntryPointVersion.V0_7 || version === EntryPointVersion.V0_8) { + try { + const provider = this.ethereum.getProvider(); + const accountCode = await provider.getCode(account.address); + if (accountCode === "0x") { + useECDSA = true; + } else { + const acc = new ethers.Contract( + account.address, + ["function validator() view returns (address)"], + provider + ); + const v = await acc.validator(); + if (v === ethers.ZeroAddress) useECDSA = true; + } + } catch { + useECDSA = true; + } + } + + // Build UserOperation with ECDSA hint for gas estimation const userOp = await this.buildUserOperation( userId, account.address, @@ -126,7 +148,8 @@ export class TransferManager { params.paymasterAddress, params.paymasterData, params.tokenAddress, - version + version, + { useECDSA } ); // Get hash @@ -140,28 +163,6 @@ export class TransferManager { ? { assertion: params.passkeyAssertion } : undefined; - // M4 accounts: check if validator is set; if not, use ECDSA instead of BLS - let useECDSA = false; - if (version === EntryPointVersion.V0_7 || version === EntryPointVersion.V0_8) { - try { - const provider = this.ethereum.getProvider(); - const accountCode = await provider.getCode(account.address); - if (accountCode === "0x") { - useECDSA = true; - } else { - const acc = new ethers.Contract( - account.address, - ["function validator() view returns (address)"], - provider - ); - const v = await acc.validator(); - if (v === ethers.ZeroAddress) useECDSA = true; - } - } catch { - useECDSA = true; - } - } - if (useECDSA) { // M4 ECDSA path: raw 65-byte sig, no validator needed this.logger.log("M4: using ECDSA signature (validator not set)"); @@ -224,8 +225,13 @@ export class TransferManager { tokenSymbol, }); - // Process asynchronously - this.processTransferAsync(transferId, userOp, account.address, version); + // Process asynchronously with retry context + this.processTransferAsync(transferId, userOp, account.address, version, { + userId, + params, + useECDSA, + assertionCtx, + }); return { success: true, @@ -243,45 +249,128 @@ export class TransferManager { transferId: string, userOp: UserOperation | PackedUserOperation, from: string, - version: EntryPointVersion + version: EntryPointVersion, + retryCtx?: { + userId: string; + params: ExecuteTransferParams; + useECDSA: boolean; + assertionCtx?: PasskeyAssertionContext; + } ): Promise { - try { - const formatted = this.formatUserOpForBundler(userOp, version); - const bundlerUserOpHash = await this.ethereum.sendUserOperation(formatted, version); - - await this.storage.updateTransfer(transferId, { - bundlerUserOpHash, - status: "submitted", - submittedAt: new Date().toISOString(), - } as Partial); - - const txHash = await this.ethereum.waitForUserOp(bundlerUserOpHash); - - await this.storage.updateTransfer(transferId, { - transactionHash: txHash, - status: "completed", - completedAt: new Date().toISOString(), - } as Partial); - - // Update deployment status if first tx - const code = await this.ethereum.getProvider().getCode(from); - if (code !== "0x") { - const account = (await this.storage.getAccounts()).find(a => a.address === from); - if (account && !account.deployed) { - await this.storage.updateAccount(account.userId, { - deployed: true, - deploymentTxHash: txHash, - }); + const MAX_RETRIES = 2; + + for (let attempt = 0; attempt <= MAX_RETRIES; attempt++) { + try { + const formatted = this.formatUserOpForBundler(userOp, version); + const bundlerUserOpHash = await this.ethereum.sendUserOperation(formatted, version); + + await this.storage.updateTransfer(transferId, { + bundlerUserOpHash, + status: "submitted", + submittedAt: new Date().toISOString(), + } as Partial); + + const txHash = await this.ethereum.waitForUserOp(bundlerUserOpHash); + + // Fetch receipt for gas data before updating status + let actualGasUsed: string | undefined; + let actualGasCost: string | undefined; + try { + const receipt = await this.ethereum.getUserOperationReceipt(bundlerUserOpHash); + if (receipt && typeof receipt === "object") { + const r = receipt as Record; + actualGasUsed = r.actualGasUsed as string | undefined; + actualGasCost = r.actualGasCost as string | undefined; + this.logger.log( + `Transfer ${transferId} gas: actualGasUsed=${actualGasUsed}, actualGasCost=${actualGasCost}` + ); + } + } catch { + // Non-critical + } + + await this.storage.updateTransfer(transferId, { + transactionHash: txHash, + status: "completed", + completedAt: new Date().toISOString(), + ...(actualGasUsed ? { actualGasUsed } : {}), + ...(actualGasCost ? { actualGasCost } : {}), + ...(attempt > 0 ? { retryCount: attempt } : {}), + } as Partial); + + // Update deployment status if first tx + const code = await this.ethereum.getProvider().getCode(from); + if (code !== "0x") { + const account = (await this.storage.getAccounts()).find(a => a.address === from); + if (account && !account.deployed) { + await this.storage.updateAccount(account.userId, { + deployed: true, + deploymentTxHash: txHash, + }); + } } + + return; // Success — exit retry loop + } catch (error: unknown) { + const message = error instanceof Error ? error.message : String(error); + const isAA26 = message.includes("AA26"); + + if (isAA26 && attempt < MAX_RETRIES && retryCtx) { + // AA26: verificationGasLimit too low — rebuild with 2x gas and retry + const multiplier = 2 * (attempt + 1); // 2x on first retry, 4x on second + this.logger.log( + `Transfer ${transferId}: AA26 on attempt ${attempt + 1}, retrying with ${multiplier}x verificationGasLimit` + ); + + try { + // Rebuild userOp with boosted gas + const account = await this.accountManager.getAccountByUserId(retryCtx.userId); + if (!account) throw new Error("Account not found for retry"); + + const newUserOp = await this.buildUserOperation( + retryCtx.userId, + account.address, + retryCtx.params.to, + retryCtx.params.amount, + retryCtx.params.data || "0x", + retryCtx.params.usePaymaster, + retryCtx.params.paymasterAddress, + retryCtx.params.paymasterData, + retryCtx.params.tokenAddress, + version, + { useECDSA: retryCtx.useECDSA, verificationGasMultiplier: multiplier } + ); + + // Re-sign + const newHash = await this.ethereum.getUserOpHash(newUserOp, version); + if (retryCtx.useECDSA) { + const signer = await this.signer.getSigner(retryCtx.userId, retryCtx.assertionCtx); + newUserOp.signature = await signer.signMessage(ethers.getBytes(newHash)); + } else { + const blsData = await this.blsService.generateBLSSignature( + retryCtx.userId, newHash, retryCtx.assertionCtx + ); + const packedBls = await this.blsService.packSignature(blsData); + newUserOp.signature = "0x01" + packedBls.slice(2); + } + + userOp = newUserOp; + continue; // Retry with new userOp + } catch (retryError) { + const retryMsg = retryError instanceof Error ? retryError.message : String(retryError); + this.logger.error(`Transfer ${transferId} retry rebuild failed: ${retryMsg}`); + } + } + + // Final failure — no more retries + await this.storage.updateTransfer(transferId, { + status: "failed", + error: message, + failedAt: new Date().toISOString(), + } as Partial); + this.logger.error(`Transfer ${transferId} failed (attempt ${attempt + 1}/${MAX_RETRIES + 1}): ${message}`); + return; } - } catch (error: unknown) { - const message = error instanceof Error ? error.message : String(error); - await this.storage.updateTransfer(transferId, { - status: "failed", - error: message, - failedAt: new Date().toISOString(), - } as Partial); - this.logger.error(`Transfer ${transferId} failed: ${message}`); } } @@ -386,7 +475,8 @@ export class TransferManager { paymasterAddress?: string, _paymasterData?: string, tokenAddress?: string, - version: EntryPointVersion = EntryPointVersion.V0_6 + version: EntryPointVersion = EntryPointVersion.V0_6, + overrides?: { useECDSA?: boolean; verificationGasMultiplier?: number } ): Promise { const accountContract = this.ethereum.getAccountContract(sender); const nonce = await this.ethereum.getNonce(sender, 0, version); @@ -548,8 +638,20 @@ export class TransferManager { } } - // Gas estimation - const gasEstimates = await this.ethereum.estimateUserOperationGas(baseUserOp, version); + // Gas estimation with account-type hints + const isECDSA = overrides?.useECDSA ?? false; + const gasEstimates = await this.ethereum.estimateUserOperationGas(baseUserOp, version, { + needsDeployment, + isECDSA, + }); + + // Apply gas multiplier for retries (e.g., 2x on AA26 failure) + if (overrides?.verificationGasMultiplier && overrides.verificationGasMultiplier > 1) { + const current = BigInt(gasEstimates.verificationGasLimit); + const multiplied = current * BigInt(overrides.verificationGasMultiplier); + gasEstimates.verificationGasLimit = "0x" + multiplied.toString(16); + this.logger.log(`Retry: boosted verificationGasLimit to ${multiplied} (${overrides.verificationGasMultiplier}x)`); + } const standardUserOp: UserOperation = { sender, From 2a88aa3c9c33ee4104e9a4c13a7adbddcd6729df Mon Sep 17 00:00:00 2001 From: jhfnetboy Date: Sun, 15 Mar 2026 15:51:11 +0700 Subject: [PATCH 34/34] fix: use modest retry multipliers (2x/3x) for AA26 gas escalation MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Base defaults already include buffer, so 2x→4x was too aggressive. Changed to 2x on first retry, 3x on second. Co-Authored-By: Claude Opus 4.6 --- sdk/src/server/services/transfer-manager.ts | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/sdk/src/server/services/transfer-manager.ts b/sdk/src/server/services/transfer-manager.ts index cbe1ae63..4caf9c82 100644 --- a/sdk/src/server/services/transfer-manager.ts +++ b/sdk/src/server/services/transfer-manager.ts @@ -316,8 +316,9 @@ export class TransferManager { const isAA26 = message.includes("AA26"); if (isAA26 && attempt < MAX_RETRIES && retryCtx) { - // AA26: verificationGasLimit too low — rebuild with 2x gas and retry - const multiplier = 2 * (attempt + 1); // 2x on first retry, 4x on second + // AA26: verificationGasLimit too low — rebuild with stepped-up gas + // Base defaults already include buffer, so use modest increments + const multiplier = attempt === 0 ? 2 : 3; // 2x on first retry, 3x on second this.logger.log( `Transfer ${transferId}: AA26 on attempt ${attempt + 1}, retrying with ${multiplier}x verificationGasLimit` );