@veridex/sdk 1.1.5 → 1.1.7
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/{EVMClient-Bmy9czkE.d.mts → EVMClient-DqDiFak8.d.mts} +1 -1
- package/dist/auth/prepareAuth.d.mts +5 -4
- package/dist/auth/prepareAuth.js +143 -1422
- package/dist/auth/prepareAuth.js.map +1 -1
- package/dist/auth/prepareAuth.mjs +17 -96
- package/dist/auth/prepareAuth.mjs.map +1 -1
- package/dist/chains/aptos/index.d.mts +1 -1
- package/dist/chains/aptos/index.js +11 -33
- package/dist/chains/aptos/index.js.map +1 -1
- package/dist/chains/aptos/index.mjs +2 -2
- package/dist/chains/avalanche/index.d.mts +2 -2
- package/dist/chains/avalanche/index.js +19 -115
- package/dist/chains/avalanche/index.js.map +1 -1
- package/dist/chains/avalanche/index.mjs +3 -3
- package/dist/chains/evm/index.d.mts +5 -4
- package/dist/chains/evm/index.js +19 -115
- package/dist/chains/evm/index.js.map +1 -1
- package/dist/chains/evm/index.mjs +2 -2
- package/dist/chains/solana/index.d.mts +1 -1
- package/dist/chains/solana/index.js +11 -33
- package/dist/chains/solana/index.js.map +1 -1
- package/dist/chains/solana/index.mjs +2 -2
- package/dist/chains/stacks/index.d.mts +1 -1
- package/dist/chains/stacks/index.js +11 -38
- package/dist/chains/stacks/index.js.map +1 -1
- package/dist/chains/stacks/index.mjs +2 -2
- package/dist/chains/starknet/index.d.mts +36 -2
- package/dist/chains/starknet/index.js +208 -37
- package/dist/chains/starknet/index.js.map +1 -1
- package/dist/chains/starknet/index.mjs +9 -4
- package/dist/chains/stellar/index.d.mts +2 -1
- package/dist/chains/sui/index.d.mts +1 -1
- package/dist/chains/sui/index.js +11 -27
- package/dist/chains/sui/index.js.map +1 -1
- package/dist/chains/sui/index.mjs +2 -2
- package/dist/{chunk-ZNIVNPGF.mjs → chunk-3PCAVZUZ.mjs} +173 -37
- package/dist/chunk-3PCAVZUZ.mjs.map +1 -0
- package/dist/{chunk-DQOW3G7M.mjs → chunk-6BINP4RT.mjs} +48 -9
- package/dist/{chunk-DQOW3G7M.mjs.map → chunk-6BINP4RT.mjs.map} +1 -1
- package/dist/{chunk-7KN6Y4GX.mjs → chunk-AK5HWYX4.mjs} +12 -40
- package/dist/chunk-AK5HWYX4.mjs.map +1 -0
- package/dist/{chunk-QVTADARB.mjs → chunk-FPSCAGYS.mjs} +12 -35
- package/dist/chunk-FPSCAGYS.mjs.map +1 -0
- package/dist/{chunk-USVZH4QC.mjs → chunk-H3WRT6Y4.mjs} +20 -117
- package/dist/chunk-H3WRT6Y4.mjs.map +1 -0
- package/dist/{chunk-GXJUY2SC.mjs → chunk-MNH22BM2.mjs} +12 -35
- package/dist/chunk-MNH22BM2.mjs.map +1 -0
- package/dist/chunk-N42LPFPJ.mjs +177 -0
- package/dist/chunk-N42LPFPJ.mjs.map +1 -0
- package/dist/{chunk-D57UJ4L5.mjs → chunk-NKSRF45N.mjs} +12 -29
- package/dist/chunk-NKSRF45N.mjs.map +1 -0
- package/dist/{chunk-BJH5HJL5.mjs → chunk-SKZLZFE2.mjs} +91 -65
- package/dist/chunk-SKZLZFE2.mjs.map +1 -0
- package/dist/{chunk-NVRAQPSF.mjs → chunk-UF5NWMSQ.mjs} +20 -4
- package/dist/chunk-UF5NWMSQ.mjs.map +1 -0
- package/dist/chunk-WC4X3MAO.mjs +58 -0
- package/dist/chunk-WC4X3MAO.mjs.map +1 -0
- package/dist/{chunk-5FH67KLG.mjs → chunk-XHDOSV2F.mjs} +2 -2
- package/dist/{index-CKKUV4J7.d.mts → index-D1nb2JV9.d.mts} +2 -2
- package/dist/index-qyOqd8tx.d.mts +517 -0
- package/dist/index.d.mts +30 -366
- package/dist/index.js +2412 -2486
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +986 -55
- package/dist/index.mjs.map +1 -1
- package/dist/passkey-fh8bo2w-.d.mts +241 -0
- package/dist/passkey.d.mts +2 -182
- package/dist/passkey.js +86 -7
- package/dist/passkey.js.map +1 -1
- package/dist/passkey.mjs +2 -1
- package/dist/payload.d.mts +22 -28
- package/dist/payload.js +50 -9
- package/dist/payload.js.map +1 -1
- package/dist/payload.mjs +7 -3
- package/dist/platform/index.d.mts +3 -0
- package/dist/platform/index.js +216 -0
- package/dist/platform/index.js.map +1 -0
- package/dist/platform/index.mjs +21 -0
- package/dist/platform/index.mjs.map +1 -0
- package/dist/{portfolio-W2FQ2G3O.mjs → portfolio-MLP2JIFK.mjs} +2 -3
- package/dist/queries/index.mjs +324 -10
- package/dist/queries/index.mjs.map +1 -1
- package/dist/{types-DP2CQT8p.d.mts → types-CdlEbixV.d.mts} +12 -1
- package/dist/types.d.mts +1 -0
- package/dist/types.js.map +1 -1
- package/package.json +7 -1
- package/dist/chunk-72ZA3OYQ.mjs +0 -20
- package/dist/chunk-72ZA3OYQ.mjs.map +0 -1
- package/dist/chunk-7KN6Y4GX.mjs.map +0 -1
- package/dist/chunk-BJH5HJL5.mjs.map +0 -1
- package/dist/chunk-D57UJ4L5.mjs.map +0 -1
- package/dist/chunk-GXJUY2SC.mjs.map +0 -1
- package/dist/chunk-NVRAQPSF.mjs.map +0 -1
- package/dist/chunk-QVTADARB.mjs.map +0 -1
- package/dist/chunk-USVZH4QC.mjs.map +0 -1
- package/dist/chunk-XDIIFIW6.mjs +0 -330
- package/dist/chunk-XDIIFIW6.mjs.map +0 -1
- package/dist/chunk-ZNIVNPGF.mjs.map +0 -1
- package/dist/chunk-ZXMTPBSP.mjs +0 -857
- package/dist/chunk-ZXMTPBSP.mjs.map +0 -1
- /package/dist/{chunk-5FH67KLG.mjs.map → chunk-XHDOSV2F.mjs.map} +0 -0
- /package/dist/{portfolio-W2FQ2G3O.mjs.map → portfolio-MLP2JIFK.mjs.map} +0 -0
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/queries/portfolio.ts"],"sourcesContent":["import axios, { AxiosError } from 'axios';\nimport { Buffer } from 'buffer';\nimport { ethers } from 'ethers';\nimport { PublicKey } from '@solana/web3.js';\nimport {\n EthCallQueryRequest,\n EthCallQueryResponse,\n PerChainQueryRequest,\n QueryRequest,\n QueryResponse,\n SolanaAccountQueryRequest,\n SolanaAccountQueryResponse,\n hexToUint8Array,\n isValidHexString,\n} from '@wormhole-foundation/wormhole-query-sdk';\n\nimport { MAINNET_CHAINS, TESTNET_CHAINS } from '../constants.js';\nimport { WalletManager } from '../core/WalletManager.js';\nimport { getAllTokens, isNativeToken } from '../constants/tokens.js';\nimport { WORMHOLE_QUERY_PROXY_URLS } from './constants.js';\n\nexport type QueryPortfolioNetwork = 'testnet' | 'mainnet';\n\nexport type QueryPortfolioOptions = {\n /** Max response age in seconds (default: 60). */\n maxAge?: number;\n network?: QueryPortfolioNetwork;\n /** Maximum attempts including the first try (default: 4). */\n maxAttempts?: number;\n /** Cache TTL in ms (default: 30_000). */\n cacheTtlMs?: number;\n /** Request timeout in ms (default: 15_000 for testnet, 10_000 for mainnet). */\n timeout?: number;\n /** Override Query Proxy endpoint. */\n endpoint?: string;\n /** Override per-chain RPC URLs used for block tag lookups. */\n rpcUrls?: Record<number, string>;\n /** Override derived vault addresses for specific Wormhole chain IDs. */\n vaultAddresses?: Record<number, string>;\n /** Override token lists (ERC20 only) for specific Wormhole chain IDs. */\n evmTokenAddresses?: Record<number, string[]>;\n /** Additional Solana accounts to include in the Solana account query (base58). */\n solanaAccounts?: string[];\n /** Optional USD prices by symbol/address for aggregation (e.g. { USDC: 1 }). */\n pricesUsd?: Record<string, number>;\n};\n\nexport type PortfolioBalance = {\n assetId: string;\n amount: bigint;\n decimals?: number;\n symbol?: string;\n usdValue?: number;\n};\n\nexport type PortfolioChainErrorCode =\n | 'UNSUPPORTED_CHAIN'\n | 'MISSING_VAULT'\n | 'MISSING_TOKENS'\n | 'ATTESTATION_STALE'\n | 'DECODE_ERROR';\n\nexport type PortfolioChainResult = {\n wormholeChainId: number;\n chainName?: string;\n vaultAddress?: string;\n blockTime?: number;\n balances: PortfolioBalance[];\n error?: {\n code: PortfolioChainErrorCode;\n message: string;\n };\n};\n\nexport type PortfolioResult = {\n proof: Uint8Array;\n totalUsd?: number;\n chains: PortfolioChainResult[];\n};\n\nexport type QueryPortfolioErrorCode =\n | 'INVALID_ARGUMENT'\n | 'NETWORK_ERROR'\n | 'PROXY_HTTP_ERROR'\n | 'PROXY_RESPONSE_INVALID'\n | 'QUERY_RESPONSE_INVALID';\n\nexport class QueryPortfolioError extends Error {\n code: QueryPortfolioErrorCode;\n cause?: unknown;\n\n constructor(code: QueryPortfolioErrorCode, message: string, cause?: unknown) {\n super(message);\n this.name = 'QueryPortfolioError';\n this.code = code;\n this.cause = cause;\n }\n}\n\ntype CacheEntry = { expiresAt: number; value: PortfolioResult };\nconst PORTFOLIO_CACHE = new Map<string, CacheEntry>();\n\nfunction resolveNetwork(options?: QueryPortfolioOptions): QueryPortfolioNetwork {\n if (options?.network) return options.network;\n\n const envCandidates = [\n (globalThis as any)?.process?.env?.NEXT_PUBLIC_VERIDEX_NETWORK,\n (globalThis as any)?.process?.env?.VERIDEX_NETWORK,\n (globalThis as any)?.process?.env?.NEXT_PUBLIC_WORMHOLE_NETWORK,\n (globalThis as any)?.process?.env?.WORMHOLE_NETWORK,\n ].filter(Boolean);\n\n const env = (envCandidates[0] as string | undefined)?.toLowerCase();\n if (env === 'mainnet' || env === 'testnet') return env;\n\n return 'testnet';\n}\n\nfunction concatBytes(parts: Uint8Array[]): Uint8Array {\n const total = parts.reduce((sum, p) => sum + p.length, 0);\n const out = new Uint8Array(total);\n let offset = 0;\n for (const p of parts) {\n out.set(p, offset);\n offset += p.length;\n }\n return out;\n}\n\nfunction signaturesToProofBytes(signatures: string[]): Uint8Array {\n const chunks: Uint8Array[] = [];\n\n for (const sig of signatures) {\n if (typeof sig !== 'string' || sig.length !== 132 || !/^[0-9a-fA-F]+$/.test(sig)) {\n throw new QueryPortfolioError(\n 'PROXY_RESPONSE_INVALID',\n `Invalid guardian signature format (expected 132 hex chars): ${String(sig)}`\n );\n }\n // Avoid Node Buffer-backed Uint8Array (can surface as SharedArrayBuffer in DTS types).\n chunks.push(hexToUint8Array(`0x${sig}`));\n }\n\n return concatBytes(chunks);\n}\n\nfunction decodeQueryBytes(bytes: string): Uint8Array {\n if (typeof bytes !== 'string' || bytes.length === 0) {\n throw new QueryPortfolioError('PROXY_RESPONSE_INVALID', 'Missing query response bytes');\n }\n\n if (isValidHexString(bytes)) {\n return hexToUint8Array(bytes);\n }\n\n try {\n if (typeof atob === 'function') {\n const raw = atob(bytes);\n const arr = new Uint8Array(raw.length);\n for (let i = 0; i < raw.length; i++) arr[i] = raw.charCodeAt(i);\n return arr;\n }\n } catch {\n // ignore\n }\n\n try {\n return new Uint8Array(Buffer.from(bytes, 'base64'));\n } catch (cause) {\n throw new QueryPortfolioError('PROXY_RESPONSE_INVALID', 'Unrecognized query response bytes encoding', cause);\n }\n}\n\nfunction sleep(ms: number): Promise<void> {\n return new Promise((resolve) => setTimeout(resolve, ms));\n}\n\n/**\n * Simple rate limiter for Wormhole Query Proxy (6 requests/second limit).\n * Queues requests and releases them at the allowed rate.\n */\nconst rateLimiter = {\n queue: [] as Array<() => void>,\n lastRequest: 0,\n minInterval: 170, // ~6 req/s with buffer\n \n async acquire(): Promise<void> {\n return new Promise((resolve) => {\n const tryAcquire = () => {\n const now = Date.now();\n const elapsed = now - rateLimiter.lastRequest;\n if (elapsed >= rateLimiter.minInterval) {\n rateLimiter.lastRequest = now;\n resolve();\n } else {\n setTimeout(tryAcquire, rateLimiter.minInterval - elapsed);\n }\n };\n tryAcquire();\n });\n }\n};\n\nasync function withExponentialBackoff<T>(fn: () => Promise<T>, maxAttempts: number): Promise<T> {\n let attempt = 0;\n let lastError: unknown;\n\n while (attempt < maxAttempts) {\n try {\n return await fn();\n } catch (err) {\n lastError = err;\n attempt += 1;\n if (attempt >= maxAttempts) break;\n\n const baseMs = 250;\n const backoffMs = Math.min(5_000, baseMs * 2 ** (attempt - 1));\n const jitterMs = Math.floor(Math.random() * 100);\n await sleep(backoffMs + jitterMs);\n }\n }\n\n throw lastError;\n}\n\nfunction getChainConfigs(network: QueryPortfolioNetwork) {\n return network === 'testnet' ? TESTNET_CHAINS : MAINNET_CHAINS;\n}\n\nfunction getProxyEndpoint(network: QueryPortfolioNetwork, options?: QueryPortfolioOptions): string {\n if (options?.endpoint) return options.endpoint;\n return network === 'testnet' ? WORMHOLE_QUERY_PROXY_URLS.testnet : WORMHOLE_QUERY_PROXY_URLS.mainnet;\n}\n\nfunction getDefaultPortfolioChains(network: QueryPortfolioNetwork): number[] {\n // Include hub (Base Sepolia 10004) and spoke chains\n return network === 'testnet' ? [10004, 10005, 10003, 1] : [30, 24, 23, 1];\n}\n\nfunction normalizeHex32(hex: string): Uint8Array {\n if (typeof hex !== 'string' || !/^0x[0-9a-fA-F]{64}$/.test(hex)) {\n throw new QueryPortfolioError('INVALID_ARGUMENT', `Invalid userKeyHash (expected 0x + 32 bytes hex): ${hex}`);\n }\n return new Uint8Array(Buffer.from(hex.slice(2), 'hex'));\n}\n\nfunction deriveSolanaVaultAddress(programIdBase58: string, userKeyHash: string): string {\n const programId = new PublicKey(programIdBase58);\n const keyHashBytes = normalizeHex32(userKeyHash);\n const [vaultPda] = PublicKey.findProgramAddressSync([Buffer.from('vault'), Buffer.from(keyHashBytes)], programId);\n return vaultPda.toBase58();\n}\n\nfunction makeCacheKey(userKeyHash: string, apiKey: string, options: QueryPortfolioOptions | undefined, chainIds: number[]) {\n // Do not include apiKey in the cache key; it should not affect the data.\n const payload = {\n userKeyHash,\n network: resolveNetwork(options),\n chainIds: [...chainIds].sort((a, b) => a - b),\n vaultAddresses: options?.vaultAddresses ?? null,\n evmTokenAddresses: options?.evmTokenAddresses ?? null,\n solanaAccounts: options?.solanaAccounts ?? null,\n endpoint: options?.endpoint ?? null,\n };\n\n void apiKey;\n return JSON.stringify(payload);\n}\n\nfunction safeNumberFromBigint(b: bigint): number {\n const n = Number(b);\n return Number.isFinite(n) ? n : 0;\n}\n\nfunction priceLookup(pricesUsd: Record<string, number> | undefined, symbol?: string, assetId?: string): number | undefined {\n if (!pricesUsd) return undefined;\n if (symbol && pricesUsd[symbol] != null) return pricesUsd[symbol];\n if (assetId && pricesUsd[assetId] != null) return pricesUsd[assetId];\n return undefined;\n}\n\nfunction sumUsd(balances: PortfolioBalance[], pricesUsd?: Record<string, number>): number | undefined {\n let total = 0;\n let any = false;\n\n for (const b of balances) {\n const p = priceLookup(pricesUsd, b.symbol, b.assetId);\n if (p == null) continue;\n if (b.decimals == null) continue;\n\n const denom = 10 ** b.decimals;\n const amount = Number(b.amount) / denom;\n if (!Number.isFinite(amount)) continue;\n total += amount * p;\n any = true;\n }\n\n return any ? total : undefined;\n}\n\nasync function getRecentBlockTag(rpcUrl: string): Promise<number> {\n const provider = new ethers.JsonRpcProvider(rpcUrl);\n const latest = await provider.getBlockNumber();\n return Math.max(0, latest - 2);\n}\n\nfunction encodeErc20BalanceCalls(vaultAddress: string, tokenAddresses: string[]): { to: string; data: string }[] {\n const iface = new ethers.Interface(['function balanceOf(address owner) view returns (uint256)']);\n return tokenAddresses.map((token) => ({\n to: token,\n data: iface.encodeFunctionData('balanceOf', [vaultAddress]),\n }));\n}\n\nfunction decodeErc20Balances(results: string[], tokenAddresses: string[]): bigint[] {\n const iface = new ethers.Interface(['function balanceOf(address owner) view returns (uint256)']);\n const out: bigint[] = [];\n for (let i = 0; i < tokenAddresses.length; i++) {\n const data = results[i];\n if (!data || data === '0x') {\n out.push(0n);\n continue;\n }\n const decoded = iface.decodeFunctionResult('balanceOf', data);\n out.push(decoded[0] as bigint);\n }\n return out;\n}\n\n/**\n * Fetch Guardian-attested vault balances across multiple chains in one Query Proxy request.\n *\n * Notes:\n * - EVM balances are ERC20-only via `eth_call` (native ETH is not queryable via this query type).\n * - Solana balance uses lamports of the Veridex vault PDA (plus optional extra accounts).\n * - Aptos is included only if/when Wormhole Queries adds Aptos query types (currently returned as unsupported).\n */\nexport async function queryPortfolio(\n userKeyHash: string,\n apiKey: string,\n options?: QueryPortfolioOptions\n): Promise<PortfolioResult> {\n const network = resolveNetwork(options);\n const maxAgeSeconds = options?.maxAge ?? 60;\n const maxAttempts = options?.maxAttempts ?? 4;\n const cacheTtlMs = options?.cacheTtlMs ?? 30_000;\n const endpoint = getProxyEndpoint(network, options);\n\n const chainIds = options?.rpcUrls ? Object.keys(options.rpcUrls).map(Number) : undefined;\n void chainIds;\n\n const requestedChains = options?.vaultAddresses\n ? Object.keys(options.vaultAddresses).map(Number)\n : undefined;\n\n const defaultChains = getDefaultPortfolioChains(network);\n const wormholeChainIds = options?.evmTokenAddresses\n ? Array.from(new Set([...defaultChains, ...Object.keys(options.evmTokenAddresses).map(Number)]))\n : defaultChains;\n\n // If the caller provided explicit vault overrides, include those chain IDs even if not in defaults.\n const finalChainIds = requestedChains\n ? Array.from(new Set([...wormholeChainIds, ...requestedChains]))\n : wormholeChainIds;\n\n if (!apiKey || typeof apiKey !== 'string') {\n throw new QueryPortfolioError('INVALID_ARGUMENT', 'Missing Query Proxy apiKey');\n }\n\n const cacheKey = makeCacheKey(userKeyHash, apiKey, options, finalChainIds);\n const cached = PORTFOLIO_CACHE.get(cacheKey);\n if (cached && cached.expiresAt > Date.now()) {\n return cached.value;\n }\n\n const chains = getChainConfigs(network);\n const walletManager = new WalletManager({ cacheAddresses: true, persistToStorage: false });\n\n const pricesUsd: Record<string, number> | undefined = {\n USDC: 1,\n ...(options?.pricesUsd ?? {}),\n };\n\n const doFetch = async (): Promise<PortfolioResult> => {\n try {\n const perChainRequests: PerChainQueryRequest[] = [];\n const chainMeta: Record<number, { vaultAddress?: string; chainName?: string; kind: 'evm' | 'solana' | 'unsupported' }> = {};\n\n // Precompute any EVM block tags in parallel to keep total latency down.\n const evmChainIds = finalChainIds.filter((id) => {\n const cfg = Object.values(chains).find((c) => c.wormholeChainId === id);\n return cfg?.isEvm;\n });\n\n const blockTagsByChainId = new Map<number, number>();\n await Promise.all(\n evmChainIds.map(async (wormholeChainId) => {\n const cfg = Object.values(chains).find((c) => c.wormholeChainId === wormholeChainId);\n if (!cfg) return;\n const rpcUrl = options?.rpcUrls?.[wormholeChainId] ?? cfg.rpcUrl;\n const blockTag = await getRecentBlockTag(rpcUrl);\n blockTagsByChainId.set(wormholeChainId, blockTag);\n })\n );\n\n for (const wormholeChainId of finalChainIds) {\n const cfg = Object.values(chains).find((c) => c.wormholeChainId === wormholeChainId);\n\n if (wormholeChainId === 22) {\n chainMeta[wormholeChainId] = { kind: 'unsupported', chainName: cfg?.name };\n continue;\n }\n\n if (!cfg) {\n chainMeta[wormholeChainId] = { kind: 'unsupported' };\n continue;\n }\n\n if (cfg.isEvm) {\n const vaultAddress = options?.vaultAddresses?.[wormholeChainId]\n ?? (cfg.contracts.vaultFactory && cfg.contracts.vaultImplementation\n ? walletManager.computeVaultAddress(userKeyHash, cfg.contracts.vaultFactory, cfg.contracts.vaultImplementation)\n : undefined);\n\n chainMeta[wormholeChainId] = { kind: 'evm', vaultAddress, chainName: cfg.name };\n\n if (!vaultAddress) {\n continue;\n }\n\n const tokenAddresses = options?.evmTokenAddresses?.[wormholeChainId]\n ?? getAllTokens(wormholeChainId).filter((t) => !isNativeToken(t.address)).map((t) => t.address);\n\n if (!tokenAddresses.length) {\n continue;\n }\n\n const blockTag = blockTagsByChainId.get(wormholeChainId);\n if (blockTag == null) {\n continue;\n }\n\n const calls = encodeErc20BalanceCalls(vaultAddress, tokenAddresses);\n perChainRequests.push(new PerChainQueryRequest(wormholeChainId, new EthCallQueryRequest(blockTag, calls)));\n continue;\n }\n\n // Solana\n if (wormholeChainId === 1) {\n const programId = options?.vaultAddresses?.[wormholeChainId] ?? cfg.contracts.hub;\n chainMeta[wormholeChainId] = { kind: 'solana', chainName: cfg.name };\n\n if (!programId) {\n continue;\n }\n\n const vaultAddress = deriveSolanaVaultAddress(programId, userKeyHash);\n chainMeta[wormholeChainId] = { kind: 'solana', chainName: cfg.name, vaultAddress };\n\n const accounts = [vaultAddress, ...(options?.solanaAccounts ?? [])];\n perChainRequests.push(\n new PerChainQueryRequest(\n wormholeChainId,\n new SolanaAccountQueryRequest('finalized', accounts, undefined, 0n, 0n)\n )\n );\n continue;\n }\n\n chainMeta[wormholeChainId] = { kind: 'unsupported', chainName: cfg.name };\n }\n\n if (perChainRequests.length > 255) {\n throw new QueryPortfolioError(\n 'INVALID_ARGUMENT',\n `Too many per-chain requests (${perChainRequests.length}); max is 255 per Query Proxy request`\n );\n }\n\n // If no per-chain requests were built (e.g., missing vaults or tokens), return early with empty results\n if (perChainRequests.length === 0) {\n const chainsOut: PortfolioChainResult[] = finalChainIds.map((wormholeChainId) => {\n const meta = chainMeta[wormholeChainId] ?? { kind: 'unsupported' as const };\n return {\n wormholeChainId,\n chainName: meta.chainName,\n vaultAddress: meta.vaultAddress,\n balances: [],\n error: { \n code: 'MISSING_VAULT' as const, \n message: 'Unable to build query: missing vault address or no tokens configured' \n },\n };\n });\n return { proof: new Uint8Array(), totalUsd: 0, chains: chainsOut };\n }\n\n const request = new QueryRequest(Date.now() & 0xffffffff, perChainRequests);\n // Wormhole Query Proxy expects raw hex WITHOUT 0x prefix\n const requestHex = Buffer.from(request.serialize()).toString('hex');\n\n // Respect rate limit before making request\n await rateLimiter.acquire();\n\n let response;\n try {\n console.log('[queryPortfolio] Sending request to:', endpoint);\n console.log('[queryPortfolio] Request bytes length:', requestHex.length);\n \n // Use provided timeout, or default to 15s for testnet (slower), 10s for mainnet\n const defaultTimeout = network === 'testnet' ? 15_000 : 10_000;\n const requestTimeout = options?.timeout ?? defaultTimeout;\n \n response = await axios.post(\n endpoint,\n { bytes: requestHex },\n {\n headers: {\n 'X-API-Key': apiKey,\n 'Content-Type': 'application/json',\n },\n timeout: requestTimeout,\n }\n );\n } catch (axiosErr) {\n const err = axiosErr as AxiosError;\n // Network errors (CORS, timeout, no connection) have no response\n if (!err.response) {\n console.error('[queryPortfolio] Network error:', {\n message: err.message,\n code: err.code,\n name: err.name,\n });\n throw new QueryPortfolioError(\n 'NETWORK_ERROR',\n `Network error: ${err.message} (code: ${err.code})`\n );\n }\n const status = err.response.status;\n const errData = err.response.data;\n console.error('[queryPortfolio] Wormhole Query Proxy error:', { status, data: errData });\n throw new QueryPortfolioError(\n 'PROXY_RESPONSE_INVALID',\n `Query Proxy returned ${status}: ${JSON.stringify(errData)}`\n );\n }\n\n const data = response.data as any;\n const signatures = data?.signatures as string[] | undefined;\n const bytes = data?.bytes as string | undefined;\n\n if (!Array.isArray(signatures) || typeof bytes !== 'string') {\n throw new QueryPortfolioError('PROXY_RESPONSE_INVALID', 'Query Proxy response missing signatures/bytes');\n }\n\n const proof = signaturesToProofBytes(signatures);\n const queryBytes = decodeQueryBytes(bytes);\n const parsed = QueryResponse.from(queryBytes);\n\n const nowSeconds = Math.floor(Date.now() / 1000);\n const chainsOut: PortfolioChainResult[] = [];\n\n for (const wormholeChainId of finalChainIds) {\n const meta = chainMeta[wormholeChainId] ?? { kind: 'unsupported' as const };\n\n if (meta.kind === 'unsupported') {\n const msg = wormholeChainId === 22\n ? 'Aptos Queries are not supported by the Wormhole Query SDK yet'\n : 'Chain is not supported by this portfolio query implementation';\n chainsOut.push({\n wormholeChainId,\n chainName: meta.chainName,\n balances: [],\n error: { code: 'UNSUPPORTED_CHAIN', message: msg },\n });\n continue;\n }\n\n if (!meta.vaultAddress) {\n chainsOut.push({\n wormholeChainId,\n chainName: meta.chainName,\n balances: [],\n error: { code: 'MISSING_VAULT', message: 'Unable to derive vault address for chain' },\n });\n continue;\n }\n\n const perChain = parsed.responses.find((r) => r.chainId === wormholeChainId);\n if (!perChain) {\n chainsOut.push({\n wormholeChainId,\n chainName: meta.chainName,\n vaultAddress: meta.vaultAddress,\n balances: [],\n error: { code: 'DECODE_ERROR', message: 'Missing per-chain response from Query Proxy' },\n });\n continue;\n }\n\n try {\n if (meta.kind === 'evm') {\n const cfg = Object.values(chains).find((c) => c.wormholeChainId === wormholeChainId);\n const tokenAddresses = options?.evmTokenAddresses?.[wormholeChainId]\n ?? getAllTokens(wormholeChainId).filter((t) => !isNativeToken(t.address)).map((t) => t.address);\n\n if (!tokenAddresses.length) {\n chainsOut.push({\n wormholeChainId,\n chainName: meta.chainName,\n vaultAddress: meta.vaultAddress,\n balances: [],\n error: { code: 'MISSING_TOKENS', message: 'No ERC20 tokens configured for EVM portfolio query' },\n });\n continue;\n }\n\n const chainResp = EthCallQueryResponse.from(perChain.response.serialize());\n const blockTime = Number(chainResp.blockTime);\n const age = nowSeconds - blockTime;\n if (age > maxAgeSeconds) {\n chainsOut.push({\n wormholeChainId,\n chainName: meta.chainName,\n vaultAddress: meta.vaultAddress,\n blockTime,\n balances: [],\n error: { code: 'ATTESTATION_STALE', message: `Attestation stale by ${age}s (maxAge=${maxAgeSeconds}s)` },\n });\n continue;\n }\n\n const amounts = decodeErc20Balances(chainResp.results, tokenAddresses);\n const tokenInfos = getAllTokens(wormholeChainId).filter((t) => !isNativeToken(t.address));\n\n const balances: PortfolioBalance[] = tokenAddresses.map((addr, i) => {\n const info = tokenInfos.find((t) => t.address.toLowerCase() === addr.toLowerCase());\n const symbol = info?.symbol;\n const decimals = info?.decimals;\n const usdPrice = priceLookup(pricesUsd, symbol, addr);\n const usdValue = usdPrice != null && decimals != null\n ? (Number(amounts[i]) / 10 ** decimals) * usdPrice\n : undefined;\n\n return {\n assetId: addr,\n amount: amounts[i],\n symbol,\n decimals,\n usdValue: Number.isFinite(usdValue ?? NaN) ? usdValue : undefined,\n };\n });\n\n void cfg;\n chainsOut.push({\n wormholeChainId,\n chainName: meta.chainName,\n vaultAddress: meta.vaultAddress,\n blockTime,\n balances,\n });\n continue;\n }\n\n // Solana\n const chainResp = SolanaAccountQueryResponse.from(perChain.response.serialize());\n const blockTime = safeNumberFromBigint(chainResp.blockTime);\n const age = nowSeconds - blockTime;\n if (age > maxAgeSeconds) {\n chainsOut.push({\n wormholeChainId,\n chainName: meta.chainName,\n vaultAddress: meta.vaultAddress,\n blockTime,\n balances: [],\n error: { code: 'ATTESTATION_STALE', message: `Attestation stale by ${age}s (maxAge=${maxAgeSeconds}s)` },\n });\n continue;\n }\n\n const vaultResult = chainResp.results[0];\n const lamports = vaultResult?.lamports ?? 0n;\n\n const balances: PortfolioBalance[] = [\n {\n assetId: 'SOL',\n amount: lamports,\n decimals: 9,\n symbol: 'SOL',\n usdValue: priceLookup(pricesUsd, 'SOL', 'SOL') != null\n ? (Number(lamports) / 1e9) * (priceLookup(pricesUsd, 'SOL', 'SOL') as number)\n : undefined,\n },\n ];\n\n chainsOut.push({\n wormholeChainId,\n chainName: meta.chainName,\n vaultAddress: meta.vaultAddress,\n blockTime,\n balances,\n });\n } catch (cause) {\n chainsOut.push({\n wormholeChainId,\n chainName: meta.chainName,\n vaultAddress: meta.vaultAddress,\n balances: [],\n error: { code: 'DECODE_ERROR', message: `Failed to decode chain response: ${String((cause as any)?.message ?? cause)}` },\n });\n }\n }\n\n const allBalances = chainsOut.flatMap((c) => c.balances);\n const totalUsd = sumUsd(allBalances, pricesUsd);\n\n const result: PortfolioResult = { proof, totalUsd, chains: chainsOut };\n\n PORTFOLIO_CACHE.set(cacheKey, { expiresAt: Date.now() + cacheTtlMs, value: result });\n return result;\n } catch (err) {\n if (err instanceof QueryPortfolioError) throw err;\n if (axios.isAxiosError(err)) {\n const ax = err as AxiosError;\n const status = ax.response?.status;\n const statusText = ax.response?.statusText;\n const details = typeof ax.response?.data === 'string' ? ax.response?.data : undefined;\n\n throw new QueryPortfolioError(\n 'PROXY_HTTP_ERROR',\n `Query Proxy request failed${status ? ` (${status} ${statusText ?? ''})` : ''}${details ? `: ${details}` : ''}`,\n err\n );\n }\n\n throw new QueryPortfolioError('PROXY_HTTP_ERROR', 'Query Proxy request failed', err);\n }\n };\n\n const result = await withExponentialBackoff(doFetch, maxAttempts);\n PORTFOLIO_CACHE.set(cacheKey, { expiresAt: Date.now() + cacheTtlMs, value: result });\n return result;\n}\n"],"mappings":"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","names":["chainsOut","chainResp","blockTime","age","balances","result"]}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/chains/solana/SolanaClient.ts"],"sourcesContent":["/**\n * Veridex Protocol SDK - Solana Chain Client\n * \n * Implementation of ChainClient interface for Solana blockchain\n */\n\nimport {\n Connection,\n PublicKey,\n} from '@solana/web3.js';\nimport {\n getAssociatedTokenAddressSync,\n} from '@solana/spl-token';\nimport { createHash } from 'crypto';\nimport type {\n ChainClient,\n ChainConfig,\n TransferParams,\n ExecuteParams,\n BridgeParams,\n DispatchResult,\n WebAuthnSignature,\n VaultCreationResult,\n} from '../../core/types.js';\nimport { encodeTransferAction, encodeExecuteAction, encodeBridgeAction } from '../../payload.js';\n\n// ============================================================================\n// Types\n// ============================================================================\n\nexport interface SolanaClientConfig {\n wormholeChainId: number;\n rpcUrl: string;\n programId: string; // Veridex Spoke program\n wormholeCoreBridge: string;\n tokenBridge: string;\n network?: 'mainnet' | 'devnet' | 'testnet';\n commitment?: 'processed' | 'confirmed' | 'finalized';\n}\n\n// ============================================================================\n// Constants\n// ============================================================================\n\n// ============================================================================\n// SolanaClient Class\n// ============================================================================\n\n/**\n * Solana implementation of the ChainClient interface\n */\nexport class SolanaClient implements ChainClient {\n private config: ChainConfig;\n private connection: Connection;\n private programId: PublicKey;\n\n constructor(config: SolanaClientConfig) {\n this.config = {\n name: `Solana ${config.network || 'mainnet'}`,\n chainId: config.wormholeChainId,\n wormholeChainId: config.wormholeChainId,\n rpcUrl: config.rpcUrl,\n explorerUrl: config.network === 'devnet'\n ? 'https://explorer.solana.com?cluster=devnet'\n : 'https://explorer.solana.com',\n isEvm: false,\n contracts: {\n hub: undefined, // Solana is a spoke only\n wormholeCoreBridge: config.wormholeCoreBridge,\n tokenBridge: config.tokenBridge,\n },\n };\n\n this.connection = new Connection(\n config.rpcUrl,\n config.commitment || 'confirmed'\n );\n this.programId = new PublicKey(config.programId);\n }\n\n getConfig(): ChainConfig {\n return this.config;\n }\n\n async getNonce(userKeyHash: string): Promise<bigint> {\n try {\n const vaultAddress = this.computeVaultAddressFromHash(userKeyHash);\n const accountInfo = await this.connection.getAccountInfo(new PublicKey(vaultAddress));\n\n if (!accountInfo || accountInfo.data.length < 40) {\n return 0n;\n }\n\n // Nonce is stored at offset 8 (after discriminator)\n // Read as u64 little-endian\n const nonce = accountInfo.data.readBigUInt64LE(8);\n return nonce;\n } catch (error) {\n console.error('Error getting nonce:', error);\n return 0n;\n }\n }\n\n async getMessageFee(): Promise<bigint> {\n try {\n // Query Wormhole bridge for message fee\n // For now, return a default estimate\n // TODO: Query on-chain Wormhole config account\n return 0n; // Solana doesn't charge a Wormhole fee in the same way\n } catch (error) {\n console.error('Error getting message fee:', error);\n return 0n;\n }\n }\n\n async buildTransferPayload(params: TransferParams): Promise<string> {\n return encodeTransferAction(\n params.token,\n params.recipient,\n params.amount\n );\n }\n\n async buildExecutePayload(params: ExecuteParams): Promise<string> {\n return encodeExecuteAction(\n params.target,\n params.value,\n params.data\n );\n }\n\n async buildBridgePayload(params: BridgeParams): Promise<string> {\n return encodeBridgeAction(\n params.token,\n params.amount,\n params.destinationChain,\n params.recipient\n );\n }\n\n async dispatch(\n signature: WebAuthnSignature,\n publicKeyX: bigint,\n publicKeyY: bigint,\n targetChain: number,\n actionPayload: string,\n nonce: bigint,\n signer: any // Solana Keypair or similar\n ): Promise<DispatchResult> {\n void signature;\n void publicKeyX;\n void publicKeyY;\n void targetChain;\n void actionPayload;\n void nonce;\n void signer;\n throw new Error(\n 'Direct dispatch not supported on Solana spoke chains. ' +\n 'Actions must be dispatched from the Hub (EVM) chain. ' +\n 'This client is for receiving cross-chain messages only.'\n );\n }\n\n /**\n * Dispatch an action via relayer (gasless)\n * Note: On Solana, this still goes through the Hub chain\n * Solana is a spoke-only chain in Veridex architecture\n */\n async dispatchGasless(\n signature: WebAuthnSignature,\n publicKeyX: bigint,\n publicKeyY: bigint,\n targetChain: number,\n actionPayload: string,\n nonce: bigint,\n relayerUrl: string\n ): Promise<DispatchResult> {\n // Compute key hash\n const keyHash = this.computeKeyHash(publicKeyX, publicKeyY);\n\n // Build the message that was signed (matches Hub chain format)\n const message = this.buildMessage(keyHash, targetChain, actionPayload, nonce);\n\n // Prepare request for relayer\n const request = {\n messageHash: message,\n r: '0x' + signature.r.toString(16).padStart(64, '0'),\n s: '0x' + signature.s.toString(16).padStart(64, '0'),\n publicKeyX: '0x' + publicKeyX.toString(16).padStart(64, '0'),\n publicKeyY: '0x' + publicKeyY.toString(16).padStart(64, '0'),\n targetChain,\n actionPayload,\n nonce: Number(nonce),\n };\n\n // Submit to relayer\n const response = await fetch(`${relayerUrl}/api/v1/submit`, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n },\n body: JSON.stringify(request),\n });\n\n if (!response.ok) {\n const error = await response.json().catch(() => ({ error: response.statusText }));\n throw new Error(`Relayer submission failed: ${error.error || response.statusText}`);\n }\n\n const result = await response.json();\n\n if (!result.success) {\n throw new Error(`Relayer submission failed: ${result.error}`);\n }\n\n return {\n transactionHash: result.txHash,\n sequence: BigInt(result.sequence || '0'),\n userKeyHash: keyHash,\n targetChain,\n };\n }\n\n async getVaultAddress(userKeyHash: string): Promise<string | null> {\n try {\n const vaultAddress = this.computeVaultAddressFromHash(userKeyHash);\n const accountInfo = await this.connection.getAccountInfo(new PublicKey(vaultAddress));\n\n if (!accountInfo) {\n return null;\n }\n\n return vaultAddress;\n } catch (error) {\n console.error('Error getting vault address:', error);\n return null;\n }\n }\n\n /**\n * Compute vault address using PDA (Program Derived Address)\n * Seeds: [\"vault\", userKeyHash]\n */\n computeVaultAddress(userKeyHash: string): string {\n return this.computeVaultAddressFromHash(userKeyHash);\n }\n\n private computeVaultAddressFromHash(userKeyHash: string): string {\n const userKeyHashBuffer = Buffer.from(userKeyHash.replace('0x', ''), 'hex');\n const [vaultPda] = PublicKey.findProgramAddressSync(\n [Buffer.from('vault'), userKeyHashBuffer],\n this.programId\n );\n return vaultPda.toBase58();\n }\n\n async vaultExists(userKeyHash: string): Promise<boolean> {\n const address = await this.getVaultAddress(userKeyHash);\n return address !== null;\n }\n\n async createVault(userKeyHash: string, signer: any): Promise<VaultCreationResult> {\n void userKeyHash;\n void signer;\n throw new Error(\n 'Vault creation on Solana must be done via relayer. ' +\n 'Use createVaultViaRelayer() instead.'\n );\n }\n\n async createVaultSponsored?(\n userKeyHash: string,\n sponsorPrivateKey: string,\n rpcUrl?: string\n ): Promise<VaultCreationResult> {\n void userKeyHash;\n void sponsorPrivateKey;\n void rpcUrl;\n throw new Error(\n 'Vault creation on Solana must be done via relayer. ' +\n 'Use createVaultViaRelayer() instead.'\n );\n }\n\n /**\n * Create a vault via the relayer (sponsored/gasless)\n * This is the recommended way to create Solana vaults\n */\n async createVaultViaRelayer(\n userKeyHash: string,\n relayerUrl: string\n ): Promise<VaultCreationResult> {\n const response = await fetch(`${relayerUrl}/api/v1/solana/vault`, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n },\n body: JSON.stringify({\n userKeyHash,\n chainId: this.config.wormholeChainId,\n }),\n });\n\n const result = await response.json();\n\n if (!response.ok || !result.success) {\n throw new Error(result.error || 'Failed to create vault via relayer');\n }\n\n return {\n address: result.vaultAddress,\n transactionHash: result.transactionHash || '',\n blockNumber: 0, // Solana doesn't have block numbers like EVM\n gasUsed: 0n, // Solana uses compute units, not gas\n alreadyExisted: !result.transactionHash,\n sponsoredBy: 'relayer',\n };\n }\n\n /**\n * Get vault info via relayer (includes existence check)\n */\n async getVaultViaRelayer(\n userKeyHash: string,\n relayerUrl: string\n ): Promise<{ vaultAddress: string; exists: boolean }> {\n const response = await fetch(\n `${relayerUrl}/api/v1/solana/vault/${userKeyHash}?chainId=${this.config.wormholeChainId}`\n );\n\n if (!response.ok) {\n throw new Error('Failed to get vault info from relayer');\n }\n\n const result = await response.json();\n return {\n vaultAddress: result.vaultAddress,\n exists: result.exists,\n };\n }\n\n async estimateVaultCreationGas(userKeyHash: string): Promise<bigint> {\n void userKeyHash;\n // Return SOL estimate for vault creation (rent + compute)\n // ~0.002 SOL for rent-exempt account + compute units\n return 2_000_000n; // 0.002 SOL in lamports\n }\n\n getFactoryAddress(): string | undefined {\n // Solana uses program addresses, not factory pattern\n return undefined;\n }\n\n getImplementationAddress(): string | undefined {\n // Solana uses program addresses, not implementation pattern\n return undefined;\n }\n\n // ========================================================================\n // Balance Methods\n // ========================================================================\n\n /**\n * Get native SOL balance\n */\n async getNativeBalance(address: string): Promise<bigint> {\n const balance = await this.connection.getBalance(new PublicKey(address));\n return BigInt(balance);\n }\n\n /**\n * Get SPL token balance\n */\n async getTokenBalance(tokenAddress: string, ownerAddress: string): Promise<bigint> {\n try {\n const mint = new PublicKey(tokenAddress);\n const owner = new PublicKey(ownerAddress);\n const ata = getAssociatedTokenAddressSync(mint, owner);\n\n const balance = await this.connection.getTokenAccountBalance(ata);\n return BigInt(balance.value.amount);\n } catch (error) {\n console.error('Error getting token balance:', error);\n return 0n;\n }\n }\n\n // ========================================================================\n // Utility Methods\n // ========================================================================\n\n /**\n * Compute key hash from public key coordinates\n * Matches EVM keccak256(abi.encode(publicKeyX, publicKeyY))\n */\n private computeKeyHash(publicKeyX: bigint, publicKeyY: bigint): string {\n // Use SHA-256 for Solana (Solana doesn't have keccak256 built-in)\n // The relayer will convert this to match EVM format\n const xBuffer = Buffer.alloc(32);\n const yBuffer = Buffer.alloc(32);\n\n // Write as big-endian to match EVM encoding\n const xHex = publicKeyX.toString(16).padStart(64, '0');\n const yHex = publicKeyY.toString(16).padStart(64, '0');\n\n Buffer.from(xHex, 'hex').copy(xBuffer);\n Buffer.from(yHex, 'hex').copy(yBuffer);\n\n // For cross-chain compatibility, we need to match the EVM hash\n // This should be keccak256, but we'll return a format the relayer expects\n const combined = Buffer.concat([xBuffer, yBuffer]);\n const hash = createHash('sha256').update(combined).digest();\n\n return '0x' + hash.toString('hex');\n }\n\n /**\n * Build message for signing (matches Hub chain format)\n */\n private buildMessage(\n keyHash: string,\n targetChain: number,\n actionPayload: string,\n nonce: bigint\n ): string {\n // This should match the EVM message format for cross-chain compatibility\n const keyHashBuffer = Buffer.from(keyHash.replace('0x', ''), 'hex');\n const targetChainBuffer = Buffer.alloc(2);\n targetChainBuffer.writeUInt16BE(targetChain);\n const payloadBuffer = Buffer.from(actionPayload.replace('0x', ''), 'hex');\n const nonceBuffer = Buffer.alloc(32);\n const nonceHex = nonce.toString(16).padStart(64, '0');\n Buffer.from(nonceHex, 'hex').copy(nonceBuffer);\n\n const combined = Buffer.concat([\n keyHashBuffer,\n targetChainBuffer,\n payloadBuffer,\n nonceBuffer,\n ]);\n\n const hash = createHash('sha256').update(combined).digest();\n return '0x' + hash.toString('hex');\n }\n\n /**\n * Get connection instance for advanced usage\n */\n getConnection(): Connection {\n return this.connection;\n }\n\n /**\n * Get program ID\n */\n getProgramId(): PublicKey {\n return this.programId;\n }\n\n /**\n * Get current slot\n */\n async getSlot(): Promise<number> {\n return await this.connection.getSlot();\n }\n\n /**\n * Get transaction status\n */\n async getTransaction(signature: string, commitment?: 'confirmed' | 'finalized') {\n return await this.connection.getTransaction(signature, {\n commitment: commitment || 'confirmed',\n maxSupportedTransactionVersion: 0,\n });\n }\n\n // ============================================================================\n // Social Recovery Methods (Issue #23)\n // ============================================================================\n // \n // Note: Social recovery is managed on the Hub chain (EVM).\n // Solana spokes receive and execute recovery VAAs broadcast from the Hub.\n // These methods are placeholders that indicate spoke-only chains don't\n // initiate recovery - they only execute recovery instructions from Hub VAAs.\n //\n // The relayer service handles:\n // 1. Fetching recovery VAAs from Wormhole guardians\n // 2. Submitting execute_recovery instruction to Solana spoke\n // 3. Processing OwnerRecovered events\n //\n // SDK users should use EVMClient methods for guardian management and\n // recovery initiation on the Hub chain.\n // ============================================================================\n\n /**\n * Check if a recovery VAA has been executed on this spoke\n * \n * @param vaaHash - Hash of the recovery VAA\n * @returns Whether the VAA has been processed\n */\n async isRecoveryExecuted(vaaHash: string): Promise<boolean> {\n try {\n // Derive VAA record PDA\n const vaaHashBuffer = Buffer.from(vaaHash.replace('0x', ''), 'hex');\n const [vaaRecordPda] = PublicKey.findProgramAddressSync(\n [Buffer.from('vaa_record'), vaaHashBuffer],\n this.programId\n );\n\n const accountInfo = await this.connection.getAccountInfo(vaaRecordPda);\n if (!accountInfo || accountInfo.data.length < 9) {\n return false;\n }\n\n // First byte after discriminator is 'processed' bool\n return accountInfo.data[8] === 1;\n } catch (error) {\n console.error('Error checking recovery execution:', error);\n return false;\n }\n }\n\n /**\n * Get vault owner after potential recovery\n * \n * @param vaultAddress - Vault address to check\n * @returns Current owner key hash\n */\n async getVaultOwner(vaultAddress: string): Promise<string> {\n try {\n const accountInfo = await this.connection.getAccountInfo(new PublicKey(vaultAddress));\n if (!accountInfo || accountInfo.data.length < 40) {\n throw new Error('Vault not found');\n }\n\n // Owner key hash is stored after discriminator (8 bytes) at offset 8-40\n const ownerKeyHash = accountInfo.data.slice(8, 40);\n return '0x' + ownerKeyHash.toString('hex');\n } catch (error) {\n console.error('Error getting vault owner:', error);\n throw error;\n }\n }\n\n /**\n * Get authorized signers for a vault\n * \n * @param vaultAddress - Vault address to check\n * @returns Array of authorized signer key hashes\n */\n async getAuthorizedSigners(vaultAddress: string): Promise<string[]> {\n try {\n const accountInfo = await this.connection.getAccountInfo(new PublicKey(vaultAddress));\n if (!accountInfo || accountInfo.data.length < 235) {\n throw new Error('Vault not found');\n }\n\n // Vault layout:\n // 8 bytes discriminator\n // 32 bytes owner_key_hash\n // 8 bytes nonce\n // 1 byte paused\n // 8 bytes daily_limit\n // 8 bytes daily_spent\n // 8 bytes day_start\n // 1 byte bump\n // 1 byte authorized_signer_count\n // 5 * 32 bytes authorized_signers\n\n const signerCount = accountInfo.data[66]; // offset 8+32+8+1+8+8+1 = 66\n const signers: string[] = [];\n\n for (let i = 0; i < signerCount; i++) {\n const offset = 67 + (i * 32); // Start of authorized_signers array\n const keyHash = accountInfo.data.slice(offset, offset + 32);\n signers.push('0x' + keyHash.toString('hex'));\n }\n\n return signers;\n } catch (error) {\n console.error('Error getting authorized signers:', error);\n throw error;\n }\n }\n}\n"],"mappings":"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","names":[]}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/chains/evm/EVMClient.ts"],"sourcesContent":["/**\n * Veridex Protocol SDK - EVM Chain Client\n * \n * Implementation of ChainClient interface for EVM-compatible chains\n */\n\nimport { ethers } from 'ethers';\nimport type {\n ChainClient,\n ChainConfig,\n TransferParams,\n ExecuteParams,\n BridgeParams,\n DispatchResult,\n WebAuthnSignature,\n VaultCreationResult,\n} from '../../core/types.js';\nimport { encodeTransferAction, encodeExecuteAction, encodeBridgeAction } from '../../payload.js';\n\n// ============================================================================\n// Types\n// ============================================================================\n\nexport interface EVMClientConfig {\n chainId: number;\n wormholeChainId: number;\n rpcUrl: string;\n hubContractAddress: string;\n wormholeCoreBridge: string;\n name?: string;\n explorerUrl?: string;\n vaultFactory?: string;\n vaultImplementation?: string;\n tokenBridge?: string;\n}\n\n// ============================================================================\n// Constants\n// ============================================================================\n\n/**\n * EIP-1167 minimal proxy bytecode prefix (before implementation address)\n */\nconst PROXY_BYTECODE_PREFIX = '0x3d602d80600a3d3981f3363d3d373d3d3d363d73';\n\n/**\n * EIP-1167 minimal proxy bytecode suffix (after implementation address)\n */\nconst PROXY_BYTECODE_SUFFIX = '5af43d82803e903d91602b57fd5bf3';\n\n/**\n * ERC20 ABI for balance and transfer operations\n */\nconst ERC20_ABI = [\n 'function balanceOf(address owner) view returns (uint256)',\n 'function decimals() view returns (uint8)',\n 'function symbol() view returns (string)',\n 'function name() view returns (string)',\n 'function allowance(address owner, address spender) view returns (uint256)',\n 'function transfer(address to, uint256 amount) returns (bool)',\n 'function approve(address spender, uint256 amount) returns (bool)',\n];\n\n// ============================================================================\n// Hub Contract ABI (minimal)\n// ============================================================================\n\nconst HUB_ABI = [\n 'function dispatch(tuple(bytes authenticatorData, string clientDataJSON, uint256 challengeIndex, uint256 typeIndex, uint256 r, uint256 s) signature, uint256 publicKeyX, uint256 publicKeyY, uint16 targetChain, bytes actionPayload, uint256 nonce) payable returns (uint64 sequence)',\n 'function userNonces(bytes32 userKeyHash) view returns (uint256)',\n // Hub exposes the Wormhole core bridge address; message fee is read from the\n // bridge directly (getMessageFee() was removed from the Hub).\n 'function wormhole() view returns (address)',\n 'function getVaultAddress(bytes32 userKeyHash) view returns (address)',\n 'function vaultExists(bytes32 userKeyHash) view returns (bool)',\n 'function createVault(bytes32 userKeyHash) returns (address)',\n // Issue #9/#10: New Hub methods for Query-based execution\n 'function getUserState(bytes32 userKeyHash) view returns (bytes32 keyHash, uint256 nonce, bytes32 lastActionHash)',\n 'function getUserLastActionHash(bytes32 userKeyHash) view returns (bytes32)',\n // Issue #13: Session key management\n 'function registerSession(tuple(bytes authenticatorData, string clientDataJSON, uint256 challengeIndex, uint256 typeIndex, uint256 r, uint256 s) auth, uint256 publicKeyX, uint256 publicKeyY, bytes32 sessionKeyHash, uint256 duration, uint256 maxValue, bool requireUV) external',\n 'function isSessionActive(bytes32 userKeyHash, bytes32 sessionKeyHash) view returns (bool active, uint256 expiry, uint256 maxValue, uint256 sessionIndex)',\n 'function revokeSession(tuple(bytes authenticatorData, string clientDataJSON, uint256 challengeIndex, uint256 typeIndex, uint256 r, uint256 s) auth, uint256 publicKeyX, uint256 publicKeyY, bytes32 sessionKeyHash, bool requireUV) external',\n 'function getUserSessions(bytes32 userKeyHash) view returns (tuple(bytes32 sessionKeyHash, uint256 expiry, uint256 maxValue, bool revoked)[])',\n 'function getUserSessionCount(bytes32 userKeyHash) view returns (uint256)',\n // Issue #22: Backup Passkey / Multi-Key Identity management\n 'function registerIdentity(tuple(bytes authenticatorData, string clientDataJSON, uint256 challengeIndex, uint256 typeIndex, uint256 r, uint256 s) auth, uint256 publicKeyX, uint256 publicKeyY) external',\n 'function addBackupKey(tuple(bytes authenticatorData, string clientDataJSON, uint256 challengeIndex, uint256 typeIndex, uint256 r, uint256 s) auth, uint256 publicKeyX, uint256 publicKeyY, uint256 newPublicKeyX, uint256 newPublicKeyY, uint256 nonce) external payable returns (uint64 sequence)',\n 'function removeKey(tuple(bytes authenticatorData, string clientDataJSON, uint256 challengeIndex, uint256 typeIndex, uint256 r, uint256 s) auth, uint256 publicKeyX, uint256 publicKeyY, bytes32 keyToRemove, uint256 nonce) external payable returns (uint64 sequence)',\n 'function getIdentityForKey(bytes32 keyHash) view returns (bytes32)',\n 'function getAuthorizedKeys(bytes32 identity) view returns (bytes32[])',\n 'function getAuthorizedKeyCount(bytes32 identity) view returns (uint256)',\n 'function isAuthorizedForIdentity(bytes32 identity, bytes32 keyHash) view returns (bool)',\n 'function isIdentityRoot(bytes32 keyHash) view returns (bool)',\n 'function getIdentityState(bytes32 keyHash) view returns (bytes32 identity, uint256 keyCount, uint256 maxKeys, bool isRoot)',\n \n // Issue #23: Social Recovery / Guardian Management\n 'function setupGuardians(tuple(bytes authenticatorData, string clientDataJSON, uint256 challengeIndex, uint256 typeIndex, uint256 r, uint256 s) auth, uint256 publicKeyX, uint256 publicKeyY, bytes32[] guardians, uint256 threshold) external payable returns (uint64 sequence)',\n 'function addGuardian(tuple(bytes authenticatorData, string clientDataJSON, uint256 challengeIndex, uint256 typeIndex, uint256 r, uint256 s) auth, uint256 publicKeyX, uint256 publicKeyY, bytes32 guardianKeyHash) external payable returns (uint64 sequence)',\n 'function removeGuardian(tuple(bytes authenticatorData, string clientDataJSON, uint256 challengeIndex, uint256 typeIndex, uint256 r, uint256 s) auth, uint256 publicKeyX, uint256 publicKeyY, bytes32 guardianKeyHash) external payable returns (uint64 sequence)',\n 'function initiateRecovery(tuple(bytes authenticatorData, string clientDataJSON, uint256 challengeIndex, uint256 typeIndex, uint256 r, uint256 s) auth, uint256 publicKeyX, uint256 publicKeyY, bytes32 identityToRecover, bytes32 newOwnerKeyHash) external payable returns (uint64 sequence)',\n 'function approveRecovery(tuple(bytes authenticatorData, string clientDataJSON, uint256 challengeIndex, uint256 typeIndex, uint256 r, uint256 s) auth, uint256 publicKeyX, uint256 publicKeyY, bytes32 identityToRecover) external payable returns (uint64 sequence)',\n 'function executeRecovery(bytes32 identityToRecover, uint256 newPublicKeyX, uint256 newPublicKeyY) external payable returns (uint64 sequence)',\n 'function cancelRecovery(tuple(bytes authenticatorData, string clientDataJSON, uint256 challengeIndex, uint256 typeIndex, uint256 r, uint256 s) auth, uint256 publicKeyX, uint256 publicKeyY) external payable returns (uint64 sequence)',\n 'function getGuardians(bytes32 identityKeyHash) view returns (bytes32[] guardians, uint256 threshold, bool isConfigured)',\n 'function getRecoveryStatus(bytes32 identityKeyHash) view returns (bool isActive, bytes32 newOwnerKeyHash, uint256 initiatedAt, uint256 approvalCount, uint256 threshold, uint256 canExecuteAt, uint256 expiresAt)',\n 'function hasGuardianApproved(bytes32 identityKeyHash, bytes32 guardianKeyHash) view returns (bool hasApproved)',\n \n // ADR-0037: Threshold Multisig\n 'function configureTransactionPolicy(tuple(bytes authenticatorData, string clientDataJSON, uint256 challengeIndex, uint256 typeIndex, uint256 r, uint256 s) auth, uint256 publicKeyX, uint256 publicKeyY, uint256 threshold, uint256 protectedActionMask, uint256 proposalTtl, bool disableSessions) external',\n 'function createTransactionProposal(tuple(bytes authenticatorData, string clientDataJSON, uint256 challengeIndex, uint256 typeIndex, uint256 r, uint256 s) auth, uint256 publicKeyX, uint256 publicKeyY, uint16 targetChain, bytes actionPayload) external returns (bytes32 proposalId)',\n 'function approveTransactionProposal(tuple(bytes authenticatorData, string clientDataJSON, uint256 challengeIndex, uint256 typeIndex, uint256 r, uint256 s) auth, uint256 publicKeyX, uint256 publicKeyY, bytes32 proposalId) external returns (uint256 approvalCount, bool thresholdReached)',\n 'function cancelTransactionProposal(tuple(bytes authenticatorData, string clientDataJSON, uint256 challengeIndex, uint256 typeIndex, uint256 r, uint256 s) auth, uint256 publicKeyX, uint256 publicKeyY, bytes32 proposalId) external',\n 'function executeTransactionProposal(bytes32 proposalId) external payable returns (uint64 sequence)',\n 'function getTransactionPolicy(bytes32 identityKeyHash) view returns (bool enabled, uint256 threshold, uint256 protectedActionMask, uint256 proposalTtl, bool disableSessions)',\n 'function getTransactionProposal(bytes32 proposalId) view returns (bytes32 identityKeyHash, bytes32 proposerKeyHash, uint16 targetChain, uint8 actionType, bytes32 actionHash, uint256 createdAt, uint256 expiresAt, uint256 approvalCount, uint256 requiredThreshold, uint8 state)',\n 'function hasApprovedTransactionProposal(bytes32 proposalId, bytes32 keyHash) view returns (bool)',\n];\n\n// ============================================================================\n// Factory Contract ABI (minimal)\n// ============================================================================\n\nconst FACTORY_ABI = [\n 'function createVault(bytes32 ownerKeyHash) returns (address vault)',\n 'function getVault(bytes32 ownerKeyHash) view returns (address)',\n 'function computeVaultAddress(bytes32 ownerKeyHash) view returns (address vault)',\n 'function vaultExists(bytes32 ownerKeyHash) view returns (bool)',\n 'function implementation() view returns (address)',\n];\n\n// ============================================================================\n// EVMClient Class\n// ============================================================================\n\n/**\n * EVM implementation of the ChainClient interface\n */\nexport class EVMClient implements ChainClient {\n private config: ChainConfig;\n private provider: ethers.JsonRpcProvider;\n private hubContract: ethers.Contract;\n private factoryContract: ethers.Contract | null = null;\n private cachedImplementation: string | null = null;\n private cachedWormholeAddress: string | null = null;\n private cachedMessageFee: { value: bigint; expiresAt: number } | null = null;\n\n constructor(config: EVMClientConfig) {\n this.config = {\n name: config.name ?? `EVM Chain ${config.chainId}`,\n chainId: config.chainId,\n wormholeChainId: config.wormholeChainId,\n rpcUrl: config.rpcUrl,\n explorerUrl: config.explorerUrl ?? '',\n isEvm: true,\n contracts: {\n hub: config.hubContractAddress,\n vaultFactory: config.vaultFactory,\n vaultImplementation: config.vaultImplementation,\n wormholeCoreBridge: config.wormholeCoreBridge,\n tokenBridge: config.tokenBridge,\n },\n };\n\n this.provider = new ethers.JsonRpcProvider(config.rpcUrl);\n this.hubContract = new ethers.Contract(\n config.hubContractAddress,\n HUB_ABI,\n this.provider\n );\n\n // Initialize factory contract if address is provided\n if (config.vaultFactory) {\n this.factoryContract = new ethers.Contract(\n config.vaultFactory,\n FACTORY_ABI,\n this.provider\n );\n }\n\n // Cache implementation address if provided\n if (config.vaultImplementation) {\n this.cachedImplementation = config.vaultImplementation;\n }\n }\n\n getConfig(): ChainConfig {\n return this.config;\n }\n\n async getNonce(userKeyHash: string): Promise<bigint> {\n const nonce = await this.hubContract.userNonces(userKeyHash);\n return BigInt(nonce.toString());\n }\n\n /**\n * Get user state from Hub (Issue #9/#10)\n * Returns comprehensive state including last action hash\n */\n async getUserState(userKeyHash: string): Promise<{\n keyHash: string;\n nonce: bigint;\n lastActionHash: string;\n }> {\n try {\n const result = await this.hubContract.getUserState(userKeyHash);\n return {\n keyHash: result[0],\n nonce: BigInt(result[1].toString()),\n lastActionHash: result[2],\n };\n } catch (error) {\n // Fallback for older Hub deployments without getUserState\n const nonce = await this.getNonce(userKeyHash);\n return {\n keyHash: userKeyHash,\n nonce,\n lastActionHash: ethers.ZeroHash,\n };\n }\n }\n\n /**\n * Get user's last action hash from Hub (Issue #9/#10)\n * Returns zero hash if user has no actions yet\n */\n async getUserLastActionHash(userKeyHash: string): Promise<string> {\n try {\n return await this.hubContract.getUserLastActionHash(userKeyHash);\n } catch (error) {\n // Fallback for older Hub deployments\n return ethers.ZeroHash;\n }\n }\n\n // ==========================================================================\n // Session Management Methods (Issue #13)\n // ==========================================================================\n\n /**\n * Register a new session key for temporary authentication\n * Enables native L1 speed for repeat transactions without biometric auth\n * \n * @param params Session registration parameters\n * @param signer Ethereum signer to pay gas\n * @returns Transaction receipt\n */\n async registerSession(\n params: import('../../types.js').RegisterSessionParams,\n signer: ethers.Signer\n ): Promise<ethers.TransactionReceipt> {\n const hubWithSigner = this.hubContract.connect(signer) as any;\n\n const authTuple = {\n authenticatorData: params.signature.authenticatorData,\n clientDataJSON: params.signature.clientDataJSON,\n challengeIndex: params.signature.challengeIndex,\n typeIndex: params.signature.typeIndex,\n r: params.signature.r,\n s: params.signature.s,\n };\n\n const tx = await hubWithSigner.registerSession(\n authTuple,\n params.publicKeyX,\n params.publicKeyY,\n params.sessionKeyHash,\n params.duration,\n params.maxValue,\n params.requireUV\n );\n\n return await tx.wait();\n }\n\n /**\n * Check if a session is currently active (queryable via Wormhole CCQ)\n * \n * @param userKeyHash Hash of the user's Passkey public key\n * @param sessionKeyHash Hash of the session key to check\n * @returns Session validation result\n */\n async isSessionActive(\n userKeyHash: string,\n sessionKeyHash: string\n ): Promise<import('../../types.js').SessionValidationResult> {\n const result = await this.hubContract.isSessionActive(userKeyHash, sessionKeyHash);\n \n return {\n active: result[0],\n expiry: Number(result[1]),\n maxValue: BigInt(result[2].toString()),\n sessionIndex: Number(result[3]),\n };\n }\n\n /**\n * Revoke a session key immediately\n * \n * @param params Session revocation parameters\n * @param signer Ethereum signer to pay gas\n * @returns Transaction receipt\n */\n async revokeSession(\n params: import('../../types.js').RevokeSessionParams,\n signer: ethers.Signer\n ): Promise<ethers.TransactionReceipt> {\n const hubWithSigner = this.hubContract.connect(signer) as any;\n\n const authTuple = {\n authenticatorData: params.signature.authenticatorData,\n clientDataJSON: params.signature.clientDataJSON,\n challengeIndex: params.signature.challengeIndex,\n typeIndex: params.signature.typeIndex,\n r: params.signature.r,\n s: params.signature.s,\n };\n\n const tx = await hubWithSigner.revokeSession(\n authTuple,\n params.publicKeyX,\n params.publicKeyY,\n params.sessionKeyHash,\n params.requireUV\n );\n\n return await tx.wait();\n }\n\n /**\n * Get all sessions for a user\n * \n * @param userKeyHash Hash of the user's Passkey public key\n * @returns Array of all sessions (active and expired/revoked)\n */\n async getUserSessions(userKeyHash: string): Promise<import('../../types.js').SessionKey[]> {\n const sessions = await this.hubContract.getUserSessions(userKeyHash);\n \n return sessions.map((s: any) => ({\n sessionKeyHash: s.sessionKeyHash,\n expiry: Number(s.expiry),\n maxValue: BigInt(s.maxValue.toString()),\n revoked: s.revoked,\n }));\n }\n\n /**\n * Get the number of sessions for a user\n * \n * @param userKeyHash Hash of the user's Passkey public key\n * @returns Number of sessions\n */\n async getUserSessionCount(userKeyHash: string): Promise<number> {\n const count = await this.hubContract.getUserSessionCount(userKeyHash);\n return Number(count);\n }\n\n async getMessageFee(): Promise<bigint> {\n // Short cache to avoid hammering the RPC on every dispatch.\n const now = Date.now();\n if (this.cachedMessageFee && this.cachedMessageFee.expiresAt > now) {\n return this.cachedMessageFee.value;\n }\n\n // Resolve the Wormhole core bridge address. Prefer the value supplied\n // via config; otherwise read it from the Hub once and cache it.\n let wormholeAddress =\n this.config.contracts.wormholeCoreBridge ?? this.cachedWormholeAddress;\n if (!wormholeAddress) {\n wormholeAddress = await this.hubContract.wormhole();\n this.cachedWormholeAddress = wormholeAddress;\n }\n\n const wormhole = new ethers.Contract(\n wormholeAddress as string,\n ['function messageFee() view returns (uint256)'],\n this.provider,\n );\n const fee = await wormhole.messageFee();\n const value = BigInt(fee.toString());\n this.cachedMessageFee = { value, expiresAt: now + 30_000 };\n return value;\n }\n\n async buildTransferPayload(params: TransferParams): Promise<string> {\n return encodeTransferAction(\n params.token,\n params.recipient,\n params.amount\n );\n }\n\n async buildExecutePayload(params: ExecuteParams): Promise<string> {\n return encodeExecuteAction(\n params.target,\n params.value,\n params.data\n );\n }\n\n async buildBridgePayload(params: BridgeParams): Promise<string> {\n return encodeBridgeAction(\n params.token,\n params.amount,\n params.destinationChain,\n params.recipient\n );\n }\n\n async dispatch(\n signature: WebAuthnSignature,\n publicKeyX: bigint,\n publicKeyY: bigint,\n targetChain: number,\n actionPayload: string,\n nonce: bigint,\n signer: ethers.Signer\n ): Promise<DispatchResult> {\n const hubWithSigner = this.hubContract.connect(signer) as any;\n\n const signatureTuple = {\n authenticatorData: signature.authenticatorData,\n clientDataJSON: signature.clientDataJSON,\n challengeIndex: signature.challengeIndex,\n typeIndex: signature.typeIndex,\n r: signature.r,\n s: signature.s,\n };\n\n const messageFee = await this.getMessageFee();\n\n const tx = await hubWithSigner.dispatch(\n signatureTuple,\n publicKeyX,\n publicKeyY,\n targetChain,\n actionPayload,\n nonce,\n { value: messageFee }\n );\n\n const receipt = await tx.wait();\n\n // Extract sequence from event logs\n const dispatchEvent = receipt.logs.find((log: any) => {\n try {\n const parsed = hubWithSigner.interface.parseLog(log);\n return parsed?.name === 'ActionDispatched';\n } catch {\n return false;\n }\n });\n\n let sequence = 0n;\n if (dispatchEvent) {\n const parsed = hubWithSigner.interface.parseLog(dispatchEvent);\n sequence = BigInt(parsed?.args?.sequence?.toString() ?? '0');\n }\n\n const keyHash = ethers.keccak256(\n ethers.AbiCoder.defaultAbiCoder().encode(\n ['uint256', 'uint256'],\n [publicKeyX, publicKeyY]\n )\n );\n\n return {\n transactionHash: receipt.hash,\n sequence,\n userKeyHash: keyHash,\n targetChain,\n blockNumber: receipt.blockNumber,\n };\n }\n\n /**\n * Dispatch an action to the Hub via relayer (gasless)\n * The relayer pays for gas and submits the transaction on behalf of the user\n */\n async dispatchGasless(\n signature: WebAuthnSignature,\n publicKeyX: bigint,\n publicKeyY: bigint,\n targetChain: number,\n actionPayload: string,\n nonce: bigint,\n relayerUrl: string\n ): Promise<DispatchResult> {\n // Compute message hash that was signed\n // This should match how the WebAuthn signature was generated\n const keyHash = ethers.keccak256(\n ethers.AbiCoder.defaultAbiCoder().encode(\n ['uint256', 'uint256'],\n [publicKeyX, publicKeyY]\n )\n );\n\n // Build the message that was signed\n const message = ethers.keccak256(\n ethers.AbiCoder.defaultAbiCoder().encode(\n ['bytes32', 'uint16', 'bytes', 'uint256'],\n [keyHash, targetChain, actionPayload, nonce]\n )\n );\n\n // Prepare request for relayer\n const request = {\n messageHash: message,\n r: '0x' + signature.r.toString(16).padStart(64, '0'),\n s: '0x' + signature.s.toString(16).padStart(64, '0'),\n publicKeyX: '0x' + publicKeyX.toString(16).padStart(64, '0'),\n publicKeyY: '0x' + publicKeyY.toString(16).padStart(64, '0'),\n targetChain,\n actionPayload,\n nonce: Number(nonce),\n };\n\n // Submit to relayer with retries for transient failures.\n // Retry semantics:\n // - network errors (fetch throws) → retry up to 3 times\n // - HTTP 5xx → retry up to 3 times\n // - HTTP 408 / 429 → retry up to 3 times (respect Retry-After if present)\n // - HTTP 4xx (incl. 403 policy) → no retry, surface immediately\n // Backoff: 1s, 2s, 4s (with small jitter)\n const MAX_ATTEMPTS = 3;\n const baseDelayMs = 1000;\n const sleep = (ms: number) =>\n new Promise<void>((resolve) => setTimeout(resolve, ms));\n\n let response: Response | undefined;\n let lastError: unknown;\n for (let attempt = 1; attempt <= MAX_ATTEMPTS; attempt++) {\n try {\n response = await fetch(`${relayerUrl}/api/v1/submit`, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n },\n body: JSON.stringify(request),\n });\n\n const retryable =\n response.status >= 500 ||\n response.status === 408 ||\n response.status === 429;\n\n if (!retryable) {\n break; // success or deterministic failure\n }\n\n if (attempt === MAX_ATTEMPTS) break;\n\n const retryAfter = response.headers.get('retry-after');\n const explicitDelay = retryAfter ? parseInt(retryAfter, 10) * 1000 : 0;\n const backoff =\n explicitDelay > 0\n ? explicitDelay\n : baseDelayMs * 2 ** (attempt - 1) + Math.floor(Math.random() * 200);\n await sleep(backoff);\n } catch (err) {\n lastError = err;\n if (attempt === MAX_ATTEMPTS) break;\n const backoff = baseDelayMs * 2 ** (attempt - 1) + Math.floor(Math.random() * 200);\n await sleep(backoff);\n }\n }\n\n if (!response) {\n throw new Error(\n `Relayer submission failed after ${MAX_ATTEMPTS} attempts: ${\n lastError instanceof Error ? lastError.message : String(lastError)\n }`,\n );\n }\n\n if (!response.ok) {\n const error = await response.json().catch(() => ({ error: response!.statusText }));\n throw new Error(`Relayer submission failed: ${error.error || response.statusText}`);\n }\n\n const result = await response.json();\n\n if (!result.success) {\n throw new Error(`Relayer submission failed: ${result.error}`);\n }\n\n return {\n transactionHash: result.txHash,\n sequence: BigInt(result.sequence || '0'),\n userKeyHash: keyHash,\n targetChain,\n };\n }\n\n async getVaultAddress(userKeyHash: string): Promise<string | null> {\n try {\n // Try factory first if available\n if (this.factoryContract) {\n const address = await this.factoryContract.getVault(userKeyHash);\n if (address !== ethers.ZeroAddress) {\n return address;\n }\n }\n\n // Fallback to hub contract\n const address = await this.hubContract.getVaultAddress(userKeyHash);\n if (address === ethers.ZeroAddress) {\n return null;\n }\n return address;\n } catch (error) {\n console.error('Error getting vault address:', error);\n return null;\n }\n }\n\n /**\n * Compute vault address deterministically without querying the chain\n * Uses CREATE2 with EIP-1167 minimal proxy pattern\n */\n computeVaultAddress(userKeyHash: string): string {\n const factoryAddress = this.getFactoryAddress();\n const implementationAddress = this.getImplementationAddress();\n\n if (!factoryAddress || !implementationAddress) {\n throw new Error('Factory and implementation addresses required for address computation');\n }\n\n // Compute salt: keccak256(abi.encodePacked(factory, keyHash))\n const salt = ethers.keccak256(\n ethers.solidityPacked(\n ['address', 'bytes32'],\n [factoryAddress, userKeyHash]\n )\n );\n\n // Build EIP-1167 initcode\n const initCode = this.buildProxyInitCode(implementationAddress);\n const initCodeHash = ethers.keccak256(initCode);\n\n // CREATE2 address computation:\n // address = keccak256(0xff ++ factory ++ salt ++ initCodeHash)[12:]\n const create2Data = ethers.solidityPacked(\n ['bytes1', 'address', 'bytes32', 'bytes32'],\n ['0xff', factoryAddress, salt, initCodeHash]\n );\n\n const hash = ethers.keccak256(create2Data);\n // Take last 20 bytes as address\n return ethers.getAddress('0x' + hash.slice(26));\n }\n\n /**\n * Build EIP-1167 minimal proxy initcode\n */\n private buildProxyInitCode(implementationAddress: string): string {\n const impl = implementationAddress.toLowerCase().replace('0x', '');\n return PROXY_BYTECODE_PREFIX + impl + PROXY_BYTECODE_SUFFIX;\n }\n\n async vaultExists(userKeyHash: string): Promise<boolean> {\n try {\n // Try factory first if available\n if (this.factoryContract) {\n return await this.factoryContract.vaultExists(userKeyHash);\n }\n // Hub chains may not have vaultExists, silently return false\n if (this.hubContract.vaultExists) {\n try {\n return await this.hubContract.vaultExists(userKeyHash);\n } catch {\n // Hub contract doesn't have vaultExists - this is expected on hub-only chains\n return false;\n }\n }\n return false;\n } catch {\n // Silently return false - vault existence check is non-critical\n return false;\n }\n }\n\n async createVault(userKeyHash: string, signer: ethers.Signer): Promise<VaultCreationResult> {\n // Check if vault already exists\n const exists = await this.vaultExists(userKeyHash);\n if (exists) {\n const address = await this.getVaultAddress(userKeyHash);\n if (address) {\n return {\n address,\n transactionHash: '',\n blockNumber: 0,\n gasUsed: 0n,\n alreadyExisted: true,\n };\n }\n }\n\n // Create vault using factory or hub\n let tx: ethers.TransactionResponse;\n\n if (this.factoryContract) {\n const factoryWithSigner = this.factoryContract.connect(signer) as ethers.Contract;\n tx = await factoryWithSigner.createVault(userKeyHash);\n } else {\n const hubWithSigner = this.hubContract.connect(signer) as ethers.Contract;\n tx = await hubWithSigner.createVault(userKeyHash);\n }\n\n const receipt = await tx.wait();\n if (!receipt) {\n throw new Error('Transaction failed - no receipt');\n }\n\n const vaultAddress = await this.getVaultAddress(userKeyHash);\n if (!vaultAddress) {\n throw new Error('Failed to create vault - address not found after creation');\n }\n\n return {\n address: vaultAddress,\n transactionHash: receipt.hash,\n blockNumber: receipt.blockNumber,\n gasUsed: receipt.gasUsed,\n alreadyExisted: false,\n };\n }\n\n /**\n * Create a vault with a sponsor wallet paying for gas\n * \n * @param userKeyHash - The user's passkey hash\n * @param sponsorPrivateKey - Private key of the wallet that will pay gas\n * @param rpcUrl - Optional RPC URL to use (defaults to client's RPC)\n * @returns VaultCreationResult with address and transaction details\n */\n async createVaultSponsored(\n userKeyHash: string,\n sponsorPrivateKey: string,\n rpcUrl?: string\n ): Promise<VaultCreationResult> {\n // Check if vault already exists\n const exists = await this.vaultExists(userKeyHash);\n if (exists) {\n const address = await this.getVaultAddress(userKeyHash);\n if (address) {\n return {\n address,\n transactionHash: '',\n blockNumber: 0,\n gasUsed: 0n,\n alreadyExisted: true,\n };\n }\n }\n\n // Create sponsor signer\n const provider = rpcUrl\n ? new ethers.JsonRpcProvider(rpcUrl)\n : this.provider;\n const sponsorWallet = new ethers.Wallet(sponsorPrivateKey, provider);\n\n // Check sponsor balance\n const sponsorBalance = await provider.getBalance(sponsorWallet.address);\n const estimatedGas = await this.estimateVaultCreationGas(userKeyHash);\n const feeData = await provider.getFeeData();\n const estimatedCost = estimatedGas * (feeData.gasPrice ?? 1000000000n);\n\n if (sponsorBalance < estimatedCost) {\n throw new Error(\n `Sponsor wallet has insufficient funds. ` +\n `Balance: ${ethers.formatEther(sponsorBalance)} ETH, ` +\n `Estimated cost: ${ethers.formatEther(estimatedCost)} ETH`\n );\n }\n\n // Create vault using factory or hub with sponsor wallet\n let tx: ethers.TransactionResponse;\n\n if (this.factoryContract) {\n const factoryWithSponsor = this.factoryContract.connect(sponsorWallet) as ethers.Contract;\n tx = await factoryWithSponsor.createVault(userKeyHash);\n } else {\n const hubWithSponsor = this.hubContract.connect(sponsorWallet) as ethers.Contract;\n tx = await hubWithSponsor.createVault(userKeyHash);\n }\n\n const receipt = await tx.wait();\n if (!receipt) {\n throw new Error('Transaction failed - no receipt');\n }\n\n const vaultAddress = await this.getVaultAddress(userKeyHash);\n if (!vaultAddress) {\n throw new Error('Failed to create vault - address not found after creation');\n }\n\n return {\n address: vaultAddress,\n transactionHash: receipt.hash,\n blockNumber: receipt.blockNumber,\n gasUsed: receipt.gasUsed,\n alreadyExisted: false,\n sponsoredBy: sponsorWallet.address,\n };\n }\n\n async estimateVaultCreationGas(userKeyHash: string): Promise<bigint> {\n try {\n if (this.factoryContract) {\n return await this.factoryContract.createVault.estimateGas(userKeyHash);\n }\n return await this.hubContract.createVault.estimateGas(userKeyHash);\n } catch (error) {\n // Return a default estimate if estimation fails (vault might already exist)\n console.warn('Gas estimation failed, returning default:', error);\n return 150000n; // Default estimate for vault creation\n }\n }\n\n getFactoryAddress(): string | undefined {\n return this.config.contracts.vaultFactory;\n }\n\n getImplementationAddress(): string | undefined {\n return this.config.contracts.vaultImplementation ?? this.cachedImplementation ?? undefined;\n }\n\n /**\n * Fetch implementation address from factory contract\n */\n async fetchImplementationAddress(): Promise<string | null> {\n if (this.cachedImplementation) {\n return this.cachedImplementation;\n }\n\n if (!this.factoryContract) {\n return null;\n }\n\n try {\n this.cachedImplementation = await this.factoryContract.implementation();\n return this.cachedImplementation;\n } catch (error) {\n console.error('Error fetching implementation address:', error);\n return null;\n }\n }\n\n /**\n * Get the provider instance\n */\n getProvider(): ethers.JsonRpcProvider {\n return this.provider;\n }\n\n // ========================================================================\n // Balance Methods (Phase 2)\n // ========================================================================\n\n /**\n * Get native token balance for an address\n */\n async getNativeBalance(address: string): Promise<bigint> {\n return await this.provider.getBalance(address);\n }\n\n /**\n * Get ERC20 token balance for an address\n */\n async getTokenBalance(tokenAddress: string, ownerAddress: string): Promise<bigint> {\n const contract = new ethers.Contract(tokenAddress, ERC20_ABI, this.provider);\n return await contract.balanceOf(ownerAddress);\n }\n\n /**\n * Get token allowance\n */\n async getTokenAllowance(\n tokenAddress: string,\n ownerAddress: string,\n spenderAddress: string\n ): Promise<bigint> {\n const contract = new ethers.Contract(tokenAddress, ERC20_ABI, this.provider);\n return await contract.allowance(ownerAddress, spenderAddress);\n }\n\n /**\n * Estimate gas for a dispatch transaction\n */\n async estimateDispatchGas(\n signature: WebAuthnSignature,\n publicKeyX: bigint,\n publicKeyY: bigint,\n targetChain: number,\n actionPayload: string,\n nonce: bigint\n ): Promise<bigint> {\n const signatureTuple = {\n authenticatorData: signature.authenticatorData,\n clientDataJSON: signature.clientDataJSON,\n challengeIndex: signature.challengeIndex,\n typeIndex: signature.typeIndex,\n r: signature.r,\n s: signature.s,\n };\n\n const messageFee = await this.getMessageFee();\n\n try {\n const gasEstimate = await this.hubContract.dispatch.estimateGas(\n signatureTuple,\n publicKeyX,\n publicKeyY,\n targetChain,\n actionPayload,\n nonce,\n { value: messageFee }\n );\n return gasEstimate;\n } catch (error) {\n console.warn('Gas estimation failed, using default:', error);\n return 500000n; // Default estimate for dispatch\n }\n }\n\n /**\n * Get current gas price\n */\n async getGasPrice(): Promise<bigint> {\n const feeData = await this.provider.getFeeData();\n return feeData.gasPrice ?? feeData.maxFeePerGas ?? 0n;\n }\n\n /**\n * Get current block number\n */\n async getBlockNumber(): Promise<number> {\n return await this.provider.getBlockNumber();\n }\n\n /**\n * Get transaction receipt\n */\n async getTransactionReceipt(hash: string): Promise<ethers.TransactionReceipt | null> {\n return await this.provider.getTransactionReceipt(hash);\n }\n\n /**\n * Wait for transaction confirmation\n */\n async waitForTransaction(\n hash: string,\n confirmations: number = 1\n ): Promise<ethers.TransactionReceipt | null> {\n return await this.provider.waitForTransaction(hash, confirmations);\n }\n\n // ==========================================================================\n // Backup Passkey / Multi-Key Identity Methods (Issue #22)\n // ==========================================================================\n\n /**\n * Get the identity for a given key hash\n * Returns zero hash if key is not registered to any identity\n * \n * @param keyHash Hash of the passkey to look up\n * @returns Identity (first passkey's keyHash) or zero hash\n */\n async getIdentityForKey(keyHash: string): Promise<string> {\n try {\n return await this.hubContract.getIdentityForKey(keyHash);\n } catch (error) {\n return ethers.ZeroHash;\n }\n }\n\n /**\n * Get all authorized keys for an identity\n * \n * @param identity The identity key hash (first passkey's keyHash)\n * @returns Array of authorized key hashes\n */\n async getAuthorizedKeys(identity: string): Promise<string[]> {\n try {\n return await this.hubContract.getAuthorizedKeys(identity);\n } catch (error) {\n return [];\n }\n }\n\n /**\n * Get count of authorized keys for an identity\n * \n * @param identity The identity key hash\n * @returns Number of authorized keys\n */\n async getAuthorizedKeyCount(identity: string): Promise<number> {\n try {\n const count = await this.hubContract.getAuthorizedKeyCount(identity);\n return Number(count);\n } catch (error) {\n return 0;\n }\n }\n\n /**\n * Check if a key is authorized for an identity\n * \n * @param identity The identity key hash\n * @param keyHash The key hash to check\n * @returns Whether the key is authorized\n */\n async isAuthorizedForIdentity(identity: string, keyHash: string): Promise<boolean> {\n try {\n return await this.hubContract.isAuthorizedForIdentity(identity, keyHash);\n } catch (error) {\n return false;\n }\n }\n\n /**\n * Check if a key is the root identity key\n * \n * @param keyHash The key hash to check\n * @returns Whether the key is a root identity\n */\n async isIdentityRootKey(keyHash: string): Promise<boolean> {\n try {\n return await this.hubContract.isIdentityRoot(keyHash);\n } catch (error) {\n return false;\n }\n }\n\n /**\n * Get comprehensive identity state for a key\n * \n * @param keyHash Hash of any key in the identity\n * @returns Identity state including count, max, and root status\n */\n async getIdentityState(keyHash: string): Promise<import('../../types.js').IdentityState> {\n try {\n const result = await this.hubContract.getIdentityState(keyHash);\n return {\n identity: result[0],\n keyCount: Number(result[1]),\n maxKeys: Number(result[2]),\n isRoot: result[3],\n };\n } catch (error) {\n // Fallback for keys not registered\n return {\n identity: ethers.ZeroHash,\n keyCount: 0,\n maxKeys: 5,\n isRoot: false,\n };\n }\n }\n\n /**\n * Register a new identity with the first passkey\n * This makes the passkey the root identity key\n * \n * @param signature WebAuthn signature\n * @param publicKeyX Passkey public key X coordinate\n * @param publicKeyY Passkey public key Y coordinate\n * @param signer Ethereum signer to pay gas\n * @returns Transaction receipt and identity hash\n */\n async registerIdentity(\n signature: WebAuthnSignature,\n publicKeyX: bigint,\n publicKeyY: bigint,\n signer: ethers.Signer\n ): Promise<{ receipt: ethers.TransactionReceipt; identity: string }> {\n const hubWithSigner = this.hubContract.connect(signer) as any;\n\n const authTuple = {\n authenticatorData: signature.authenticatorData,\n clientDataJSON: signature.clientDataJSON,\n challengeIndex: signature.challengeIndex,\n typeIndex: signature.typeIndex,\n r: signature.r,\n s: signature.s,\n };\n\n const tx = await hubWithSigner.registerIdentity(\n authTuple,\n publicKeyX,\n publicKeyY\n );\n\n const receipt = await tx.wait();\n \n // Compute identity (keyHash of the registered key)\n const keyHash = ethers.keccak256(\n ethers.solidityPacked(['uint256', 'uint256'], [publicKeyX, publicKeyY])\n );\n\n return { receipt, identity: keyHash };\n }\n\n /**\n * Add a backup passkey to an existing identity\n * Requires WebAuthn signature from an authorized key\n * \n * @param signature WebAuthn signature from existing authorized key\n * @param publicKeyX Existing key's X coordinate\n * @param publicKeyY Existing key's Y coordinate\n * @param newPublicKeyX New backup key's X coordinate\n * @param newPublicKeyY New backup key's Y coordinate\n * @param nonce Current nonce for the signing key\n * @param signer Ethereum signer to pay gas\n * @returns Transaction receipt and sequence number\n */\n async addBackupKey(\n signature: WebAuthnSignature,\n publicKeyX: bigint,\n publicKeyY: bigint,\n newPublicKeyX: bigint,\n newPublicKeyY: bigint,\n nonce: bigint,\n signer: ethers.Signer\n ): Promise<{ receipt: ethers.TransactionReceipt; sequence: bigint }> {\n const hubWithSigner = this.hubContract.connect(signer) as any;\n\n const authTuple = {\n authenticatorData: signature.authenticatorData,\n clientDataJSON: signature.clientDataJSON,\n challengeIndex: signature.challengeIndex,\n typeIndex: signature.typeIndex,\n r: signature.r,\n s: signature.s,\n };\n\n const messageFee = await this.getMessageFee();\n\n const tx = await hubWithSigner.addBackupKey(\n authTuple,\n publicKeyX,\n publicKeyY,\n newPublicKeyX,\n newPublicKeyY,\n nonce,\n { value: messageFee }\n );\n\n const receipt = await tx.wait();\n\n // Extract sequence from Dispatch event\n let sequence = 0n;\n for (const log of receipt.logs) {\n try {\n const parsed = this.hubContract.interface.parseLog({\n topics: log.topics as string[],\n data: log.data,\n });\n if (parsed?.name === 'Dispatched') {\n sequence = BigInt(parsed.args[3]); // sequence is 4th arg\n break;\n }\n } catch {\n // Not a Hub event, skip\n }\n }\n\n return { receipt, sequence };\n }\n\n /**\n * Remove a passkey from an identity\n * Cannot remove the last remaining key\n * \n * @param signature WebAuthn signature from an authorized key\n * @param publicKeyX Signing key's X coordinate\n * @param publicKeyY Signing key's Y coordinate\n * @param keyToRemove Hash of the key to remove\n * @param nonce Current nonce for the signing key\n * @param signer Ethereum signer to pay gas\n * @returns Transaction receipt and sequence number\n */\n async removeKey(\n signature: WebAuthnSignature,\n publicKeyX: bigint,\n publicKeyY: bigint,\n keyToRemove: string,\n nonce: bigint,\n signer: ethers.Signer\n ): Promise<{ receipt: ethers.TransactionReceipt; sequence: bigint }> {\n const hubWithSigner = this.hubContract.connect(signer) as any;\n\n const authTuple = {\n authenticatorData: signature.authenticatorData,\n clientDataJSON: signature.clientDataJSON,\n challengeIndex: signature.challengeIndex,\n typeIndex: signature.typeIndex,\n r: signature.r,\n s: signature.s,\n };\n\n const messageFee = await this.getMessageFee();\n\n const tx = await hubWithSigner.removeKey(\n authTuple,\n publicKeyX,\n publicKeyY,\n keyToRemove,\n nonce,\n { value: messageFee }\n );\n\n const receipt = await tx.wait();\n\n // Extract sequence from Dispatch event\n let sequence = 0n;\n for (const log of receipt.logs) {\n try {\n const parsed = this.hubContract.interface.parseLog({\n topics: log.topics as string[],\n data: log.data,\n });\n if (parsed?.name === 'Dispatched') {\n sequence = BigInt(parsed.args[3]);\n break;\n }\n } catch {\n // Not a Hub event, skip\n }\n }\n\n return { receipt, sequence };\n }\n\n // =========================================================================\n // SOCIAL RECOVERY METHODS (Issue #23)\n // =========================================================================\n\n /**\n * Setup guardians for an identity\n * @param signature WebAuthn signature from owner\n * @param publicKeyX Owner's public key X coordinate\n * @param publicKeyY Owner's public key Y coordinate\n * @param guardians Array of guardian key hashes\n * @param threshold Required approvals for recovery\n * @param signer Ethers signer for transaction\n */\n async setupGuardians(\n signature: WebAuthnSignature,\n publicKeyX: bigint,\n publicKeyY: bigint,\n guardians: string[],\n threshold: bigint,\n signer: ethers.Signer\n ): Promise<{ receipt: ethers.TransactionReceipt; sequence: bigint }> {\n const hubWithSigner = this.hubContract.connect(signer) as any;\n\n const authTuple = {\n authenticatorData: signature.authenticatorData,\n clientDataJSON: signature.clientDataJSON,\n challengeIndex: signature.challengeIndex,\n typeIndex: signature.typeIndex,\n r: signature.r,\n s: signature.s,\n };\n\n const messageFee = await this.getMessageFee();\n\n const tx = await hubWithSigner.setupGuardians(\n authTuple,\n publicKeyX,\n publicKeyY,\n guardians,\n threshold,\n { value: messageFee }\n );\n\n const receipt = await tx.wait();\n const sequence = this._extractSequenceFromReceipt(receipt);\n\n return { receipt, sequence };\n }\n\n /**\n * Add a guardian to an identity\n */\n async addGuardian(\n signature: WebAuthnSignature,\n publicKeyX: bigint,\n publicKeyY: bigint,\n guardianKeyHash: string,\n signer: ethers.Signer\n ): Promise<{ receipt: ethers.TransactionReceipt; sequence: bigint }> {\n const hubWithSigner = this.hubContract.connect(signer) as any;\n\n const authTuple = {\n authenticatorData: signature.authenticatorData,\n clientDataJSON: signature.clientDataJSON,\n challengeIndex: signature.challengeIndex,\n typeIndex: signature.typeIndex,\n r: signature.r,\n s: signature.s,\n };\n\n const messageFee = await this.getMessageFee();\n\n const tx = await hubWithSigner.addGuardian(\n authTuple,\n publicKeyX,\n publicKeyY,\n guardianKeyHash,\n { value: messageFee }\n );\n\n const receipt = await tx.wait();\n const sequence = this._extractSequenceFromReceipt(receipt);\n\n return { receipt, sequence };\n }\n\n /**\n * Remove a guardian from an identity\n */\n async removeGuardian(\n signature: WebAuthnSignature,\n publicKeyX: bigint,\n publicKeyY: bigint,\n guardianKeyHash: string,\n signer: ethers.Signer\n ): Promise<{ receipt: ethers.TransactionReceipt; sequence: bigint }> {\n const hubWithSigner = this.hubContract.connect(signer) as any;\n\n const authTuple = {\n authenticatorData: signature.authenticatorData,\n clientDataJSON: signature.clientDataJSON,\n challengeIndex: signature.challengeIndex,\n typeIndex: signature.typeIndex,\n r: signature.r,\n s: signature.s,\n };\n\n const messageFee = await this.getMessageFee();\n\n const tx = await hubWithSigner.removeGuardian(\n authTuple,\n publicKeyX,\n publicKeyY,\n guardianKeyHash,\n { value: messageFee }\n );\n\n const receipt = await tx.wait();\n const sequence = this._extractSequenceFromReceipt(receipt);\n\n return { receipt, sequence };\n }\n\n /**\n * Initiate recovery as a guardian\n */\n async initiateRecovery(\n signature: WebAuthnSignature,\n publicKeyX: bigint,\n publicKeyY: bigint,\n identityToRecover: string,\n newOwnerKeyHash: string,\n signer: ethers.Signer\n ): Promise<{ receipt: ethers.TransactionReceipt; sequence: bigint }> {\n const hubWithSigner = this.hubContract.connect(signer) as any;\n\n const authTuple = {\n authenticatorData: signature.authenticatorData,\n clientDataJSON: signature.clientDataJSON,\n challengeIndex: signature.challengeIndex,\n typeIndex: signature.typeIndex,\n r: signature.r,\n s: signature.s,\n };\n\n const messageFee = await this.getMessageFee();\n\n const tx = await hubWithSigner.initiateRecovery(\n authTuple,\n publicKeyX,\n publicKeyY,\n identityToRecover,\n newOwnerKeyHash,\n { value: messageFee }\n );\n\n const receipt = await tx.wait();\n const sequence = this._extractSequenceFromReceipt(receipt);\n\n return { receipt, sequence };\n }\n\n /**\n * Approve recovery as a guardian\n */\n async approveRecovery(\n signature: WebAuthnSignature,\n publicKeyX: bigint,\n publicKeyY: bigint,\n identityToRecover: string,\n signer: ethers.Signer\n ): Promise<{ receipt: ethers.TransactionReceipt; sequence: bigint }> {\n const hubWithSigner = this.hubContract.connect(signer) as any;\n\n const authTuple = {\n authenticatorData: signature.authenticatorData,\n clientDataJSON: signature.clientDataJSON,\n challengeIndex: signature.challengeIndex,\n typeIndex: signature.typeIndex,\n r: signature.r,\n s: signature.s,\n };\n\n const messageFee = await this.getMessageFee();\n\n const tx = await hubWithSigner.approveRecovery(\n authTuple,\n publicKeyX,\n publicKeyY,\n identityToRecover,\n { value: messageFee }\n );\n\n const receipt = await tx.wait();\n const sequence = this._extractSequenceFromReceipt(receipt);\n\n return { receipt, sequence };\n }\n\n /**\n * Execute recovery after timelock (anyone can call)\n */\n async executeRecovery(\n identityToRecover: string,\n newPublicKeyX: bigint,\n newPublicKeyY: bigint,\n signer: ethers.Signer\n ): Promise<{ receipt: ethers.TransactionReceipt; sequence: bigint }> {\n const hubWithSigner = this.hubContract.connect(signer) as any;\n\n const messageFee = await this.getMessageFee();\n\n const tx = await hubWithSigner.executeRecovery(\n identityToRecover,\n newPublicKeyX,\n newPublicKeyY,\n { value: messageFee }\n );\n\n const receipt = await tx.wait();\n const sequence = this._extractSequenceFromReceipt(receipt);\n\n return { receipt, sequence };\n }\n\n /**\n * Cancel recovery as owner\n */\n async cancelRecovery(\n signature: WebAuthnSignature,\n publicKeyX: bigint,\n publicKeyY: bigint,\n signer: ethers.Signer\n ): Promise<{ receipt: ethers.TransactionReceipt; sequence: bigint }> {\n const hubWithSigner = this.hubContract.connect(signer) as any;\n\n const authTuple = {\n authenticatorData: signature.authenticatorData,\n clientDataJSON: signature.clientDataJSON,\n challengeIndex: signature.challengeIndex,\n typeIndex: signature.typeIndex,\n r: signature.r,\n s: signature.s,\n };\n\n const messageFee = await this.getMessageFee();\n\n const tx = await hubWithSigner.cancelRecovery(\n authTuple,\n publicKeyX,\n publicKeyY,\n { value: messageFee }\n );\n\n const receipt = await tx.wait();\n const sequence = this._extractSequenceFromReceipt(receipt);\n\n return { receipt, sequence };\n }\n\n /**\n * Get guardians for an identity\n */\n async getGuardians(identityKeyHash: string): Promise<{\n guardians: string[];\n threshold: bigint;\n isConfigured: boolean;\n }> {\n const result = await this.hubContract.getGuardians(identityKeyHash);\n return {\n guardians: result.guardians,\n threshold: result.threshold,\n isConfigured: result.isConfigured,\n };\n }\n\n /**\n * Get recovery status for an identity\n */\n async getRecoveryStatus(identityKeyHash: string): Promise<{\n isActive: boolean;\n newOwnerKeyHash: string;\n initiatedAt: bigint;\n approvalCount: bigint;\n threshold: bigint;\n canExecuteAt: bigint;\n expiresAt: bigint;\n }> {\n const result = await this.hubContract.getRecoveryStatus(identityKeyHash);\n return {\n isActive: result.isActive,\n newOwnerKeyHash: result.newOwnerKeyHash,\n initiatedAt: result.initiatedAt,\n approvalCount: result.approvalCount,\n threshold: result.threshold,\n canExecuteAt: result.canExecuteAt,\n expiresAt: result.expiresAt,\n };\n }\n\n /**\n * Check if a guardian has approved recovery\n */\n async hasGuardianApproved(\n identityKeyHash: string,\n guardianKeyHash: string\n ): Promise<boolean> {\n return this.hubContract.hasGuardianApproved(identityKeyHash, guardianKeyHash);\n }\n\n // ========================================================================\n // Threshold Multisig (ADR-0037)\n // ========================================================================\n\n async configureTransactionPolicy(\n signature: WebAuthnSignature,\n publicKeyX: bigint,\n publicKeyY: bigint,\n threshold: number,\n protectedActionMask: number,\n proposalTtl: number,\n disableSessions: boolean,\n signer: unknown,\n ): Promise<{ receipt: unknown }> {\n const s = signer as ethers.Signer;\n const hub = this.hubContract.connect(s) as ethers.Contract;\n const authTuple = this._toAuthTuple(signature);\n const tx = await hub.configureTransactionPolicy(\n authTuple,\n publicKeyX,\n publicKeyY,\n threshold,\n protectedActionMask,\n proposalTtl,\n disableSessions,\n );\n const receipt = await tx.wait();\n return { receipt };\n }\n\n async getTransactionPolicy(identityKeyHash: string): Promise<{\n enabled: boolean;\n threshold: number;\n protectedActionMask: number;\n proposalTtl: number;\n disableSessions: boolean;\n }> {\n try {\n const result = await this.hubContract.getTransactionPolicy(identityKeyHash);\n return {\n enabled: result.enabled,\n threshold: Number(result.threshold),\n protectedActionMask: Number(result.protectedActionMask),\n proposalTtl: Number(result.proposalTtl),\n disableSessions: result.disableSessions,\n };\n } catch (error) {\n // Hub deployments without ADR-0037 multisig support revert with no\n // data on this selector. Treat that as \"no policy configured\" so\n // direct dispatch is allowed. Re-throw unexpected errors.\n const code = (error as { code?: string } | null)?.code;\n if (code === 'CALL_EXCEPTION' || code === 'BAD_DATA') {\n return {\n enabled: false,\n threshold: 0,\n protectedActionMask: 0,\n proposalTtl: 0,\n disableSessions: false,\n };\n }\n throw error;\n }\n }\n\n async createTransactionProposal(\n signature: WebAuthnSignature,\n publicKeyX: bigint,\n publicKeyY: bigint,\n targetChain: number,\n actionPayload: string,\n signer: unknown,\n ): Promise<{ proposalId: string; receipt: unknown; sequence: bigint }> {\n const s = signer as ethers.Signer;\n const hub = this.hubContract.connect(s) as ethers.Contract;\n const authTuple = this._toAuthTuple(signature);\n const tx = await hub.createTransactionProposal(\n authTuple,\n publicKeyX,\n publicKeyY,\n targetChain,\n actionPayload,\n );\n const receipt = await tx.wait();\n\n // Extract proposalId from logs\n let proposalId = ethers.ZeroHash;\n for (const log of receipt.logs) {\n try {\n const parsed = this.hubContract.interface.parseLog({\n topics: log.topics as string[],\n data: log.data,\n });\n if (parsed?.name === 'ProposalCreated') {\n proposalId = parsed.args.proposalId;\n break;\n }\n } catch {\n // Not our event\n }\n }\n\n return { proposalId, receipt, sequence: 0n };\n }\n\n async approveTransactionProposal(\n signature: WebAuthnSignature,\n publicKeyX: bigint,\n publicKeyY: bigint,\n proposalId: string,\n signer: unknown,\n ): Promise<{ receipt: unknown; approvalCount: number; thresholdReached: boolean }> {\n const s = signer as ethers.Signer;\n const hub = this.hubContract.connect(s) as ethers.Contract;\n const authTuple = this._toAuthTuple(signature);\n const tx = await hub.approveTransactionProposal(\n authTuple,\n publicKeyX,\n publicKeyY,\n proposalId,\n );\n const receipt = await tx.wait();\n\n // Extract approval info from logs\n let approvalCount = 0;\n let thresholdReached = false;\n for (const log of receipt.logs) {\n try {\n const parsed = this.hubContract.interface.parseLog({\n topics: log.topics as string[],\n data: log.data,\n });\n if (parsed?.name === 'ProposalApproved') {\n approvalCount = Number(parsed.args.currentApprovals);\n thresholdReached = Number(parsed.args.currentApprovals) >= Number(parsed.args.requiredThreshold);\n break;\n }\n } catch {\n // Not our event\n }\n }\n\n return { receipt, approvalCount, thresholdReached };\n }\n\n async cancelTransactionProposal(\n signature: WebAuthnSignature,\n publicKeyX: bigint,\n publicKeyY: bigint,\n proposalId: string,\n signer: unknown,\n ): Promise<{ receipt: unknown }> {\n const s = signer as ethers.Signer;\n const hub = this.hubContract.connect(s) as ethers.Contract;\n const authTuple = this._toAuthTuple(signature);\n const tx = await hub.cancelTransactionProposal(\n authTuple,\n publicKeyX,\n publicKeyY,\n proposalId,\n );\n const receipt = await tx.wait();\n return { receipt };\n }\n\n async executeTransactionProposal(\n proposalId: string,\n signer: unknown,\n ): Promise<{ receipt: unknown; sequence: bigint }> {\n const s = signer as ethers.Signer;\n const hub = this.hubContract.connect(s) as ethers.Contract;\n const fee = await this.getMessageFee();\n const tx = await hub.executeTransactionProposal(proposalId, { value: fee });\n const receipt = await tx.wait();\n const sequence = this._extractSequenceFromReceipt(receipt);\n return { receipt, sequence };\n }\n\n async getTransactionProposal(proposalId: string): Promise<{\n identityKeyHash: string;\n proposerKeyHash: string;\n targetChain: number;\n actionType: number;\n actionHash: string;\n createdAt: bigint;\n expiresAt: bigint;\n approvalCount: number;\n requiredThreshold: number;\n state: number;\n }> {\n const result = await this.hubContract.getTransactionProposal(proposalId);\n return {\n identityKeyHash: result.identityKeyHash,\n proposerKeyHash: result.proposerKeyHash,\n targetChain: Number(result.targetChain),\n actionType: Number(result.actionType),\n actionHash: result.actionHash,\n createdAt: result.createdAt,\n expiresAt: result.expiresAt,\n approvalCount: Number(result.approvalCount),\n requiredThreshold: Number(result.requiredThreshold),\n state: Number(result.state),\n };\n }\n\n async hasApprovedTransactionProposal(\n proposalId: string,\n keyHash: string,\n ): Promise<boolean> {\n return this.hubContract.hasApprovedTransactionProposal(proposalId, keyHash);\n }\n\n /**\n * Convert a WebAuthnSignature to the struct tuple expected by the Hub contract\n */\n private _toAuthTuple(sig: WebAuthnSignature) {\n return {\n authenticatorData: sig.authenticatorData,\n clientDataJSON: sig.clientDataJSON,\n challengeIndex: sig.challengeIndex,\n typeIndex: sig.typeIndex,\n r: sig.r,\n s: sig.s,\n };\n }\n\n /**\n * Helper to extract sequence from transaction receipt\n */\n private _extractSequenceFromReceipt(receipt: ethers.TransactionReceipt): bigint {\n for (const log of receipt.logs) {\n try {\n const parsed = this.hubContract.interface.parseLog({\n topics: log.topics as string[],\n data: log.data,\n });\n if (parsed?.name === 'Dispatch') {\n return BigInt(parsed.args.sequence);\n }\n } catch {\n // Not a Hub event, skip\n }\n }\n return 0n;\n }\n}\n"],"mappings":"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","names":["address"]}
|