@veridex/sdk 1.0.0-beta.10 → 1.0.0-beta.12

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.
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../src/chains/sui/SuiClient.ts","../../../src/payload.ts","../../../src/constants.ts"],"sourcesContent":["/**\n * Veridex Protocol SDK - Sui Chain Client\n *\n * Production-grade implementation of ChainClient interface for Sui.\n * Supports session management, query-based execution, and vault operations.\n *\n * Security:\n * - Native sui::ecdsa_k1::secp256k1_verify for signature validation\n * - CCQ-based session validation with 60s staleness window\n * - Replay protection via nonce verification\n *\n * Note: Sui is a spoke chain. Session registration/revocation happens on Hub.\n */\n\nimport { SuiClient as MystenSuiClient } from '@mysten/sui/client';\nimport { createHash } from 'crypto';\nimport type { SessionKey } from '../../sessions/types.js';\nimport type {\n ChainClient,\n ChainConfig,\n TransferParams,\n ExecuteParams,\n BridgeParams,\n DispatchResult,\n WebAuthnSignature,\n VaultCreationResult,\n RegisterSessionParams,\n RevokeSessionParams,\n SessionValidationResult,\n} from '../../core/types.js';\nimport { encodeTransferAction, encodeExecuteAction, encodeBridgeAction } from '../../payload.js';\n\n// ============================================================================\n// Types\n// ============================================================================\n\nexport interface SuiClientConfig {\n wormholeChainId: number;\n rpcUrl: string;\n packageId: string; // Veridex Spoke package ID\n wormholeCoreBridge: string;\n tokenBridge?: string;\n network?: 'mainnet' | 'testnet' | 'devnet';\n hubRpcUrl?: string; // Hub chain RPC for session management\n hubContractAddress?: string; // Hub contract for session management\n}\n\n// ============================================================================\n// SuiClient\n// ============================================================================\n\nexport class SuiClient implements ChainClient {\n private config: ChainConfig;\n private client: MystenSuiClient;\n private packageId: string;\n private hubRpcUrl?: string;\n private hubContractAddress?: string;\n\n constructor(config: SuiClientConfig) {\n this.config = {\n name: `Sui ${config.network || 'mainnet'}`,\n chainId: 0,\n wormholeChainId: config.wormholeChainId,\n rpcUrl: config.rpcUrl,\n explorerUrl: config.network === 'testnet'\n ? 'https://suiscan.xyz/testnet'\n : config.network === 'devnet'\n ? 'https://suiscan.xyz/devnet'\n : 'https://suiscan.xyz/mainnet',\n isEvm: false,\n contracts: {\n hub: config.packageId,\n wormholeCoreBridge: config.wormholeCoreBridge,\n tokenBridge: config.tokenBridge,\n },\n };\n\n this.client = new MystenSuiClient({ url: config.rpcUrl });\n this.packageId = config.packageId;\n this.hubRpcUrl = config.hubRpcUrl;\n this.hubContractAddress = config.hubContractAddress;\n }\n\n getConfig(): ChainConfig {\n return this.config;\n }\n\n async getNonce(_userKeyHash: string): Promise<bigint> {\n // Nonce is managed on the Hub for cross-chain actions.\n return 0n;\n }\n\n async getMessageFee(): Promise<bigint> {\n // Wormhole fees for Sui are generally handled by relayer submission.\n return 0n;\n }\n\n async buildTransferPayload(params: TransferParams): Promise<string> {\n return encodeTransferAction(params.token, params.recipient, params.amount);\n }\n\n async buildExecutePayload(params: ExecuteParams): Promise<string> {\n return encodeExecuteAction(params.target, params.value, params.data);\n }\n\n async buildBridgePayload(params: BridgeParams): Promise<string> {\n return encodeBridgeAction(params.token, params.amount, params.destinationChain, params.recipient);\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\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 Sui spoke chains. ' +\n 'Actions must be dispatched from the Hub (EVM) chain. '\n );\n }\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 const keyHash = this.computeKeyHash(publicKeyX, publicKeyY);\n const messageHash = this.buildMessageHash(keyHash, targetChain, actionPayload, nonce);\n\n const request = {\n messageHash,\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 const response = await fetch(`${relayerUrl}/api/v1/submit`, {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify(request),\n });\n\n if (!response.ok) {\n throw new Error(`Relayer submission failed: ${response.status} ${response.statusText}`);\n }\n\n const result = await response.json();\n\n return {\n transactionHash: result.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 // Sui vaults may be represented as shared objects on-chain; without registry object IDs,\n // we return the deterministic address used by the SDK for receiving and balance display.\n return this.computeVaultAddress(userKeyHash);\n }\n\n computeVaultAddress(userKeyHash: string): string {\n // SDK convention: Sui addresses are 32-byte hex with 0x prefix.\n const clean = userKeyHash.replace(/^0x/, '').padStart(64, '0');\n return '0x' + clean;\n }\n\n async vaultExists(_userKeyHash: string): Promise<boolean> {\n // Account addresses on Sui are implicit; treat as existing.\n return true;\n }\n\n async createVault(userKeyHash: string, signer: any): Promise<VaultCreationResult> {\n void signer;\n throw new Error(\n 'Vault creation on Sui must be done via cross-chain message from Hub. ' +\n `Use the Hub client to dispatch a vault creation action targeting Sui (chain ${this.config.wormholeChainId}). KeyHash=${userKeyHash}`\n );\n }\n\n async createVaultSponsored?(userKeyHash: string, sponsorPrivateKey: string, rpcUrl?: string): Promise<VaultCreationResult> {\n void userKeyHash;\n void sponsorPrivateKey;\n void rpcUrl;\n throw new Error(\n 'Vault creation on Sui must be done via cross-chain message from Hub. ' +\n 'Use relayer gasless submission to create vault.'\n );\n }\n\n /**\n * Create a vault via the relayer (sponsored/gasless)\n * This is the recommended way to create Sui vaults\n * \n * The relayer will dispatch a vault creation action from Hub to Sui spoke\n */\n async createVaultViaRelayer(\n userKeyHash: string,\n relayerUrl: string\n ): Promise<VaultCreationResult> {\n const response = await fetch(`${relayerUrl}/api/v1/sui/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,\n gasUsed: 0n,\n alreadyExisted: result.alreadyExists || false,\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/sui/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 // Best-effort placeholder.\n return 5_000n;\n }\n\n getFactoryAddress(): string | undefined {\n return undefined;\n }\n\n getImplementationAddress(): string | undefined {\n return undefined;\n }\n\n // ========================================================================\n // Balance utilities (used by VeridexSDK multichain)\n // ========================================================================\n\n async getNativeBalance(address: string): Promise<bigint> {\n const balance = await this.client.getBalance({ owner: address });\n return BigInt(balance.totalBalance);\n }\n\n async getTokenBalance(coinType: string, ownerAddress: string): Promise<bigint> {\n const balance = await this.client.getBalance({ owner: ownerAddress, coinType });\n return BigInt(balance.totalBalance);\n }\n\n getClient(): MystenSuiClient {\n return this.client;\n }\n\n getPackageId(): string {\n return this.packageId;\n }\n\n // ========================================================================\n // Session Management (Issue #13)\n // ========================================================================\n\n /**\n * Register a session key on the Hub (must be called via Hub client)\n * Sui spokes validate sessions via CCQ, but registration happens on Hub\n * \n * @throws Error - Session management must be done via Hub chain\n */\n async registerSession(_params: RegisterSessionParams): Promise<void> {\n throw new Error(\n 'Session registration must be performed on the Hub chain (Base). ' +\n 'Use EVMClient connected to the Hub to call registerSession().'\n );\n }\n\n /**\n * Revoke a session key on the Hub (must be called via Hub client)\n * \n * @throws Error - Session management must be done via Hub chain\n */\n async revokeSession(_params: RevokeSessionParams): Promise<void> {\n throw new Error(\n 'Session revocation must be performed on the Hub chain (Base). ' +\n 'Use EVMClient connected to the Hub to call revokeSession().'\n );\n }\n\n /**\n * Check if a session is active by querying the Hub\n * This method queries the Hub contract directly for session validation\n * \n * @param userKeyHash - Hash of user's Passkey public key\n * @param sessionKeyHash - Hash of session key to validate\n * @returns Session validation result with expiry and limits\n */\n async isSessionActive(\n _userKeyHash: string,\n _sessionKeyHash: string\n ): Promise<SessionValidationResult> {\n if (!this.hubRpcUrl || !this.hubContractAddress) {\n throw new Error(\n 'Hub configuration required for session validation. ' +\n 'Provide hubRpcUrl and hubContractAddress in SuiClientConfig.'\n );\n }\n\n // Query Hub contract for session status\n // This would normally use ethers.js to query the Hub contract\n // For production, import ethers dynamically or pass Hub client\n throw new Error(\n 'isSessionActive requires Hub client integration. ' +\n 'Use EVMClient.isSessionActive() on the Hub chain, ' +\n 'then pass the result to session execution on Sui.'\n );\n }\n\n /**\n * Get all sessions for a user from the Hub\n * \n * @param userKeyHash - Hash of user's Passkey public key\n * @returns Array of all sessions (active and expired/revoked)\n */\n async getUserSessions(userKeyHash: string): Promise<SessionKey[]> {\n if (!this.hubRpcUrl || !this.hubContractAddress) {\n throw new Error(\n 'Hub configuration required for session queries. ' +\n 'Provide hubRpcUrl and hubContractAddress in SuiClientConfig.'\n );\n }\n\n // Query Hub contract for user sessions\n throw new Error(\n 'getUserSessions requires Hub client integration. ' +\n 'Use EVMClient.getUserSessions() on the Hub chain. ' +\n `User: ${userKeyHash}`\n );\n }\n\n // ========================================================================\n // Query-Based Execution (Issue #9/#10)\n // ========================================================================\n\n /**\n * Get user state from Hub (comprehensive state query)\n * Returns key hash, nonce, and last action hash for CCQ validation\n * \n * @param userKeyHash - Hash of user's Passkey public key\n * @returns User state with nonce and last action hash\n */\n async getUserState(userKeyHash: string): Promise<{\n keyHash: string;\n nonce: bigint;\n lastActionHash: string;\n }> {\n if (!this.hubRpcUrl || !this.hubContractAddress) {\n throw new Error(\n 'Hub configuration required for state queries. ' +\n 'Provide hubRpcUrl and hubContractAddress in SuiClientConfig.'\n );\n }\n\n // Query Hub contract for user state\n // This enables query-based execution with CCQ validation\n throw new Error(\n 'getUserState requires Hub client integration. ' +\n 'Use EVMClient.getUserState() on the Hub chain. ' +\n `User: ${userKeyHash}`\n );\n }\n\n /**\n * Get user's last action hash from Hub\n * Used for optimistic execution and nonce validation\n * \n * @param userKeyHash - Hash of user's Passkey public key\n * @returns Last action hash (zero hash if no actions)\n */\n async getUserLastActionHash(userKeyHash: string): Promise<string> {\n if (!this.hubRpcUrl || !this.hubContractAddress) {\n throw new Error(\n 'Hub configuration required for action hash queries. ' +\n 'Provide hubRpcUrl and hubContractAddress in SuiClientConfig.'\n );\n }\n\n // Query Hub contract for last action hash\n throw new Error(\n 'getUserLastActionHash requires Hub client integration. ' +\n 'Use EVMClient.getUserLastActionHash() on the Hub chain. ' +\n `User: ${userKeyHash}`\n );\n }\n\n /**\n * Execute with query-based validation (faster than VAA, ~23s vs 60-90s)\n * Uses Wormhole CCQ to validate Hub state, then executes on Sui\n * \n * @param params Query execution parameters with CCQ response\n * @returns Dispatch result with transaction hash\n * \n * @remarks\n * Query-based execution flow:\n * 1. Query Hub state via Wormhole CCQ\n * 2. Validate Guardian signatures on query response\n * 3. Execute on Sui with validated state\n * 4. Hub state must be < 60s stale (enforced by QueryVerifier)\n */\n async executeWithQuery(\n _params: {\n userKeyHash: string;\n queryResponse: Uint8Array; // CCQ Guardian response\n actionType: number;\n actionPayload: Uint8Array;\n relayerUrl?: string;\n }\n ): Promise<DispatchResult> {\n throw new Error(\n 'Query-based execution on Sui requires relayer integration. ' +\n 'Use relayer API to submit query-validated transactions. ' +\n 'Relayer will call veridex_spoke::execute_with_query on Sui.'\n );\n }\n\n // ========================================================================\n // Internal helpers\n // ========================================================================\n\n private computeKeyHash(publicKeyX: bigint, publicKeyY: bigint): string {\n const xHex = publicKeyX.toString(16).padStart(64, '0');\n const yHex = publicKeyY.toString(16).padStart(64, '0');\n const combined = Buffer.from(xHex + yHex, 'hex');\n const hash = createHash('sha256').update(combined).digest('hex');\n return '0x' + hash;\n }\n\n private buildMessageHash(keyHash: string, targetChain: number, actionPayload: string, nonce: bigint): string {\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 nonceHex = nonce.toString(16).padStart(64, '0');\n const nonceBuffer = Buffer.from(nonceHex, 'hex');\n\n const combined = Buffer.concat([keyHashBuffer, targetChainBuffer, payloadBuffer, nonceBuffer]);\n const hash = createHash('sha256').update(combined).digest('hex');\n return '0x' + hash;\n }\n\n // ============================================================================\n // Social Recovery Methods (Issue #23)\n // ============================================================================\n // \n // Note: Social recovery is managed on the Hub chain (EVM).\n // Sui spokes receive and execute recovery VAAs broadcast from the Hub.\n // The relayer service handles submitting recovery transactions to Sui.\n //\n // SDK users should use EVMClient methods for guardian management and\n // recovery initiation on the Hub chain.\n // ============================================================================\n\n /**\n * Get vault object ID by owner key hash\n * \n * @param ownerKeyHash - Owner's passkey hash (32 bytes as hex)\n * @param configObjectId - Shared Config object ID\n * @param registryObjectId - Shared VaultRegistry object ID\n * @returns Vault object ID or null if not found\n */\n async getVaultId(\n ownerKeyHash: string,\n registryObjectId: string\n ): Promise<string | null> {\n try {\n // Query the VaultRegistry table for the owner_key_hash\n // The registry maps owner_key_hash -> vault ID\n const registryObject = await this.client.getObject({\n id: registryObjectId,\n options: { showContent: true },\n });\n\n if (!registryObject.data?.content) {\n return null;\n }\n\n // For a proper implementation, we'd need to query dynamic fields\n // or use a Move view function. This is a placeholder showing the pattern.\n console.warn('getVaultId requires dynamic field query - use Move view function');\n return null;\n } catch (error) {\n console.error('Error getting vault ID:', error);\n return null;\n }\n }\n\n /**\n * Get vault owner key hash from vault object\n * \n * @param vaultObjectId - Vault object ID\n * @returns Owner key hash as hex string\n */\n async getVaultOwner(vaultObjectId: string): Promise<string | null> {\n try {\n const vaultObject = await this.client.getObject({\n id: vaultObjectId,\n options: { showContent: true },\n });\n\n if (!vaultObject.data?.content || vaultObject.data.content.dataType !== 'moveObject') {\n return null;\n }\n\n const fields = vaultObject.data.content.fields as Record<string, unknown>;\n const ownerKeyHash = fields['owner_key_hash'] as number[] | undefined;\n\n if (!ownerKeyHash) {\n return null;\n }\n\n // Convert byte array to hex string\n return '0x' + Buffer.from(ownerKeyHash).toString('hex');\n } catch (error) {\n console.error('Error getting vault owner:', error);\n return null;\n }\n }\n\n /**\n * Get authorized signers for a vault\n * \n * @param vaultObjectId - Vault object ID\n * @returns Array of authorized signer key hashes\n */\n async getAuthorizedSigners(vaultObjectId: string): Promise<string[]> {\n try {\n const vaultObject = await this.client.getObject({\n id: vaultObjectId,\n options: { showContent: true },\n });\n\n if (!vaultObject.data?.content || vaultObject.data.content.dataType !== 'moveObject') {\n return [];\n }\n\n const fields = vaultObject.data.content.fields as Record<string, unknown>;\n const authorizedSigners = fields['authorized_signers'] as number[][] | undefined;\n\n if (!authorizedSigners) {\n return [];\n }\n\n // Convert each byte array to hex string\n return authorizedSigners.map(signer => \n '0x' + Buffer.from(signer).toString('hex')\n );\n } catch (error) {\n console.error('Error getting authorized signers:', error);\n return [];\n }\n }\n\n /**\n * Check if a VAA has been processed (for replay protection)\n * \n * @param vaaHash - VAA hash as hex string\n * @param processedVaasObjectId - ProcessedVAAs shared object ID\n * @returns Whether the VAA has been processed\n */\n async isVaaProcessed(\n vaaHash: string,\n processedVaasObjectId: string\n ): Promise<boolean> {\n try {\n const processedObject = await this.client.getObject({\n id: processedVaasObjectId,\n options: { showContent: true },\n });\n\n if (!processedObject.data?.content) {\n return false;\n }\n\n // Would need to query dynamic field for vaaHash key\n console.warn('isVaaProcessed requires dynamic field query');\n return false;\n } catch (error) {\n console.error('Error checking VAA status:', error);\n return false;\n }\n }\n\n /**\n * Check if protocol is paused\n * \n * @param configObjectId - Config shared object ID\n * @returns Whether the protocol is paused\n */\n async isProtocolPaused(configObjectId: string): Promise<boolean> {\n try {\n const configObject = await this.client.getObject({\n id: configObjectId,\n options: { showContent: true },\n });\n\n if (!configObject.data?.content || configObject.data.content.dataType !== 'moveObject') {\n return false;\n }\n\n const fields = configObject.data.content.fields as Record<string, unknown>;\n return fields['paused'] === true;\n } catch (error) {\n console.error('Error checking pause status:', error);\n return false;\n }\n }\n}\n","/**\n * Veridex Protocol SDK - Payload Encoding/Decoding Utilities\n */\n\nimport { ethers } from 'ethers';\nimport {\n ACTION_TRANSFER,\n ACTION_EXECUTE,\n ACTION_CONFIG,\n ACTION_BRIDGE,\n PROTOCOL_VERSION,\n} from './constants.js';\nimport type { TransferAction, BridgeAction, ExecuteAction, ActionPayload } from './types.js';\n\n// ============================================================================\n// Action Encoding\n// ============================================================================\n\n/**\n * Encode a transfer action payload\n * Format: [actionType(1)] [token(32)] [recipient(32)] [amount(32)]\n */\nexport function encodeTransferAction(\n token: string,\n recipient: string,\n amount: bigint\n): string {\n const tokenPadded = padTo32Bytes(token);\n const recipientPadded = padTo32Bytes(recipient);\n const amountBytes = ethers.zeroPadValue(ethers.toBeHex(amount), 32);\n\n return ethers.concat([\n ethers.toBeHex(ACTION_TRANSFER, 1),\n tokenPadded,\n recipientPadded,\n amountBytes,\n ]);\n}\n\n/**\n * Encode a bridge action payload\n * Format: [actionType(1)] [token(32)] [amount(32)] [targetChain(2)] [recipient(32)]\n */\nexport function encodeBridgeAction(\n token: string,\n amount: bigint,\n targetChain: number,\n recipient: string\n): string {\n const tokenPadded = padTo32Bytes(token);\n const amountBytes = ethers.zeroPadValue(ethers.toBeHex(amount), 32);\n const targetChainBytes = ethers.toBeHex(targetChain, 2);\n const recipientPadded = padTo32Bytes(recipient);\n\n return ethers.concat([\n ethers.toBeHex(ACTION_BRIDGE, 1),\n tokenPadded,\n amountBytes,\n targetChainBytes,\n recipientPadded,\n ]);\n}\n\n/**\n * Encode an execute action payload (arbitrary contract call)\n * Format: [actionType(1)] [target(32)] [value(32)] [dataLength(2)] [data(variable)]\n */\nexport function encodeExecuteAction(\n target: string,\n value: bigint,\n data: string\n): string {\n const targetPadded = padTo32Bytes(target);\n const valueBytes = ethers.zeroPadValue(ethers.toBeHex(value), 32);\n const dataBytes = ethers.getBytes(data);\n const dataLengthBytes = ethers.toBeHex(dataBytes.length, 2);\n\n return ethers.concat([\n ethers.toBeHex(ACTION_EXECUTE, 1),\n targetPadded,\n valueBytes,\n dataLengthBytes,\n data,\n ]);\n}\n\n/**\n * Encode a config action payload\n * Format: [actionType(1)] [configType(1)] [configData(variable)]\n */\nexport function encodeConfigAction(configType: number, configData: string): string {\n return ethers.concat([\n ethers.toBeHex(ACTION_CONFIG, 1),\n ethers.toBeHex(configType, 1),\n configData,\n ]);\n}\n\n// ============================================================================\n// Veridex Payload Encoding\n// ============================================================================\n\n/**\n * Encode the full Veridex message payload that gets published via Wormhole\n * Format: [version(1)] [userKeyHash(32)] [targetChain(2)] [nonce(32)] [pubKeyX(32)] [pubKeyY(32)] [actionPayload]\n */\nexport function encodeVeridexPayload(\n userKeyHash: string,\n targetChain: number,\n nonce: bigint,\n publicKeyX: bigint,\n publicKeyY: bigint,\n actionPayload: string\n): string {\n return ethers.concat([\n ethers.toBeHex(PROTOCOL_VERSION, 1),\n userKeyHash,\n ethers.toBeHex(targetChain, 2),\n ethers.zeroPadValue(ethers.toBeHex(nonce), 32),\n ethers.zeroPadValue(ethers.toBeHex(publicKeyX), 32),\n ethers.zeroPadValue(ethers.toBeHex(publicKeyY), 32),\n actionPayload,\n ]);\n}\n\n// ============================================================================\n// Action Decoding\n// ============================================================================\n\n/**\n * Decode an action payload to determine its type and contents\n */\nexport function decodeActionPayload(payload: string): ActionPayload {\n const data = ethers.getBytes(payload);\n const actionType = data[0];\n\n switch (actionType) {\n case ACTION_TRANSFER:\n return decodeTransferAction(payload);\n case ACTION_BRIDGE:\n return decodeBridgeAction(payload);\n case ACTION_EXECUTE:\n return decodeExecuteAction(payload);\n default:\n return { type: `unknown_${actionType}`, raw: payload };\n }\n}\n\n/**\n * Decode a transfer action payload\n */\nexport function decodeTransferAction(payload: string): TransferAction {\n const data = ethers.getBytes(payload);\n\n const tokenBytes = data.slice(1, 33);\n const recipientBytes = data.slice(33, 65);\n const amountBytes = data.slice(65, 97);\n\n return {\n type: 'transfer',\n token: trimTo20Bytes(ethers.hexlify(tokenBytes)),\n recipient: trimTo20Bytes(ethers.hexlify(recipientBytes)),\n amount: BigInt(ethers.hexlify(amountBytes)),\n };\n}\n\n/**\n * Decode a bridge action payload\n */\nexport function decodeBridgeAction(payload: string): BridgeAction {\n const data = ethers.getBytes(payload);\n\n const tokenBytes = data.slice(1, 33);\n const amountBytes = data.slice(33, 65);\n const targetChainByte0 = data[65];\n const targetChainByte1 = data[66];\n const recipientBytes = data.slice(67, 99);\n\n const targetChain = ((targetChainByte0 ?? 0) << 8) | (targetChainByte1 ?? 0);\n\n return {\n type: 'bridge',\n token: trimTo20Bytes(ethers.hexlify(tokenBytes)),\n amount: BigInt(ethers.hexlify(amountBytes)),\n targetChain,\n recipient: ethers.hexlify(recipientBytes),\n };\n}\n\n/**\n * Decode an execute action payload\n */\nexport function decodeExecuteAction(payload: string): ExecuteAction {\n const data = ethers.getBytes(payload);\n\n const targetBytes = data.slice(1, 33);\n const valueBytes = data.slice(33, 65);\n const dataLengthByte0 = data[65];\n const dataLengthByte1 = data[66];\n const dataLength = ((dataLengthByte0 ?? 0) << 8) | (dataLengthByte1 ?? 0);\n const callData = data.slice(67, 67 + dataLength);\n\n return {\n type: 'execute',\n target: trimTo20Bytes(ethers.hexlify(targetBytes)),\n value: BigInt(ethers.hexlify(valueBytes)),\n data: ethers.hexlify(callData),\n };\n}\n\n// ============================================================================\n// Chain-Specific Encodings\n// ============================================================================\n\n/**\n * Encode a Solana-compatible transfer action\n * Solana uses: [actionType(1)] [amount(8 LE)] [recipient(32)]\n */\nexport function encodeSolanaTransferAction(\n amount: bigint,\n recipient: string\n): string {\n const amountBytes = Buffer.alloc(8);\n amountBytes.writeBigUInt64LE(amount);\n\n const recipientBytes = ethers.getBytes(recipient);\n\n return ethers.hexlify(\n Buffer.concat([\n Buffer.from([ACTION_TRANSFER]),\n amountBytes,\n Buffer.from(recipientBytes),\n ])\n );\n}\n\n/**\n * Encode an Aptos-compatible transfer action\n * Aptos uses: [actionType(1)] [amount(8 LE)] [recipient(32)]\n */\nexport function encodeAptosTransferAction(\n amount: bigint,\n recipient: string\n): string {\n const amountBytes = Buffer.alloc(8);\n amountBytes.writeBigUInt64LE(amount);\n\n const recipientPadded = padTo32Bytes(recipient);\n\n return ethers.hexlify(\n Buffer.concat([\n Buffer.from([ACTION_TRANSFER]),\n amountBytes,\n Buffer.from(ethers.getBytes(recipientPadded)),\n ])\n );\n}\n\n/**\n * Encode a Sui-compatible transfer action\n * Sui uses: [actionType(1)] [amount(8 LE)] [recipient(32)]\n */\nexport function encodeSuiTransferAction(\n amount: bigint,\n recipient: string\n): string {\n const amountBytes = Buffer.alloc(8);\n amountBytes.writeBigUInt64LE(amount);\n\n const recipientPadded = padTo32Bytes(recipient);\n\n return ethers.hexlify(\n Buffer.concat([\n Buffer.from([ACTION_TRANSFER]),\n amountBytes,\n Buffer.from(ethers.getBytes(recipientPadded)),\n ])\n );\n}\n\n// ============================================================================\n// Address Utilities\n// ============================================================================\n\n/**\n * Pad an address to 32 bytes (Wormhole standard)\n * Supports both EVM addresses (0x...) and Solana addresses (base58)\n */\nexport function padTo32Bytes(address: string): string {\n // Handle native token - convert to zero address\n if (address.toLowerCase() === 'native') {\n return '0x' + '0'.repeat(64);\n }\n \n // If it starts with 0x, treat as hex\n if (address.startsWith('0x')) {\n const hex = address.replace('0x', '');\n // Validate that hex only contains valid hex characters\n if (!/^[0-9a-fA-F]*$/.test(hex)) {\n throw new Error(`Invalid address: ${address}. Expected hex string or 'native'.`);\n }\n return '0x' + hex.padStart(64, '0');\n }\n \n // Otherwise, assume base58 Solana address and decode it\n // Base58 character set (Bitcoin/Solana style - no 0, O, I, l)\n const base58Chars = '123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz';\n \n // Validate base58 characters\n for (const char of address) {\n if (!base58Chars.includes(char)) {\n throw new Error(`Invalid address: ${address}. Contains invalid base58 character '${char}'.`);\n }\n }\n \n // Decode base58 to bytes\n let value = BigInt(0);\n for (const char of address) {\n value = value * 58n + BigInt(base58Chars.indexOf(char));\n }\n \n // Convert to 32-byte hex\n let hex = value.toString(16);\n // Ensure it's not longer than 64 chars (32 bytes)\n if (hex.length > 64) {\n throw new Error(`Invalid address: ${address}. Decoded value too large for 32 bytes.`);\n }\n \n return '0x' + hex.padStart(64, '0');\n}\n\n/**\n * Trim a 32-byte hex to a 20-byte EVM address\n */\nexport function trimTo20Bytes(hex32: string): string {\n const clean = hex32.replace('0x', '');\n return '0x' + clean.slice(-40);\n}\n\n/**\n * Convert a Solana public key (base58) to bytes32\n * @deprecated Use padTo32Bytes instead, which now handles both EVM and Solana addresses\n */\nexport function solanaAddressToBytes32(base58Address: string): string {\n return padTo32Bytes(base58Address);\n}\n\n// ============================================================================\n// Amount Utilities\n// ============================================================================\n\n/**\n * Format an amount with decimals for display\n */\nexport function formatAmount(amount: bigint, decimals = 18): string {\n const divisor = 10n ** BigInt(decimals);\n const whole = amount / divisor;\n const fraction = amount % divisor;\n\n if (fraction === 0n) {\n return whole.toString();\n }\n\n const fractionStr = fraction.toString().padStart(decimals, '0');\n const trimmedFraction = fractionStr.replace(/0+$/, '');\n\n return `${whole}.${trimmedFraction}`;\n}\n\n/**\n * Parse an amount string with decimals to bigint\n */\nexport function parseAmount(amountStr: string, decimals = 18): bigint {\n const parts = amountStr.split('.');\n const whole = BigInt(parts[0] ?? '0');\n\n if (parts.length === 1 || !parts[1]) {\n return whole * (10n ** BigInt(decimals));\n }\n\n const fractionStr = parts[1].slice(0, decimals).padEnd(decimals, '0');\n const fraction = BigInt(fractionStr);\n\n return whole * (10n ** BigInt(decimals)) + fraction;\n}\n\n// ============================================================================\n// Nonce Utilities\n// ============================================================================\n\n/**\n * Generate a unique nonce for a transaction\n */\nexport function generateNonce(): bigint {\n const timestamp = BigInt(Date.now());\n const random = BigInt(Math.floor(Math.random() * 1000000));\n return (timestamp << 20n) | random;\n}\n\n/**\n * Create a message hash for signing (used in authenticateRawAndDispatch)\n */\nexport function createMessageHash(\n targetChain: number,\n actionPayload: string,\n nonce: bigint\n): string {\n return ethers.keccak256(\n ethers.solidityPacked(\n ['uint16', 'bytes', 'uint256'],\n [targetChain, actionPayload, nonce]\n )\n );\n}\n\n/**\n * Create the challenge bytes for gasless dispatch (matches Hub's authenticateAndDispatch)\n * \n * The Hub contract passes raw packed bytes to WebAuthn.verify():\n * abi.encodePacked(targetChain, actionPayload, userNonce, hubChainId)\n * \n * The WebAuthn library then base64url-encodes these bytes to match against clientDataJSON.\n * We do NOT hash here - the challenge is the raw packed bytes.\n * \n * @param targetChain - Wormhole chain ID of the destination\n * @param actionPayload - The action payload (hex string)\n * @param nonce - User's current nonce\n * @param hubChainId - Wormhole chain ID of the Hub (e.g., 30 for Base)\n * @returns The packed bytes as hex string (NOT hashed)\n */\nexport function createGaslessMessageHash(\n targetChain: number,\n actionPayload: string,\n nonce: bigint,\n hubChainId: number\n): string {\n // Return raw packed bytes - NO sha256 hash\n // The contract passes these bytes directly to WebAuthn.verify()\n return ethers.solidityPacked(\n ['uint16', 'bytes', 'uint256', 'uint16'],\n [targetChain, actionPayload, nonce, hubChainId]\n );\n}\n\n/**\n * Build the challenge bytes for WebAuthn signing (gasless flow)\n * Returns raw packed bytes that match what the Hub contract expects\n * \n * @param targetChain - Wormhole chain ID of the destination\n * @param actionPayload - The action payload (hex string)\n * @param nonce - User's current nonce\n * @param hubChainId - Wormhole chain ID of the Hub\n * @returns Challenge bytes for WebAuthn signing (raw packed, not hashed)\n */\nexport function buildGaslessChallenge(\n targetChain: number,\n actionPayload: string,\n nonce: bigint,\n hubChainId: number\n): Uint8Array {\n const packed = createGaslessMessageHash(targetChain, actionPayload, nonce, hubChainId);\n return ethers.getBytes(packed);\n}\n\n/**\n * Build the challenge bytes for WebAuthn signing\n */\nexport function buildChallenge(\n userKeyHash: string,\n targetChain: number,\n nonce: bigint,\n actionPayload: string\n): Uint8Array {\n const encoded = ethers.solidityPacked(\n ['bytes32', 'uint16', 'uint256', 'bytes'],\n [userKeyHash, targetChain, nonce, actionPayload]\n );\n return ethers.getBytes(ethers.keccak256(encoded));\n}\n","/**\n * Veridex Protocol SDK - Constants and Chain Configurations\n */\n\nimport type { ChainConfig } from './types.js';\n\n// ============================================================================\n// Action Type Constants\n// ============================================================================\n\nexport const ACTION_TYPES = {\n TRANSFER: 1,\n EXECUTE: 2,\n CONFIG: 3,\n BRIDGE: 4,\n} as const;\n\nexport const ACTION_TRANSFER = 1;\nexport const ACTION_EXECUTE = 2;\nexport const ACTION_CONFIG = 3;\nexport const ACTION_BRIDGE = 4;\n\n// Protocol version\nexport const PROTOCOL_VERSION = 1;\n\n// ============================================================================\n// Wormhole Chain IDs\n// ============================================================================\n\n/**\n * Wormhole Chain IDs organized by network\n * @see https://docs.wormhole.com/wormhole/reference/constants\n */\nexport const WORMHOLE_CHAIN_IDS = {\n MAINNET: {\n SOLANA: 1,\n ETHEREUM: 2,\n TERRA: 3,\n BSC: 4,\n POLYGON: 5,\n AVALANCHE: 6,\n OASIS: 7,\n ALGORAND: 8,\n AURORA: 9,\n FANTOM: 10,\n KARURA: 11,\n ACALA: 12,\n KLAYTN: 13,\n CELO: 14,\n NEAR: 15,\n MOONBEAM: 16,\n NEON: 17,\n TERRA2: 18,\n INJECTIVE: 19,\n OSMOSIS: 20,\n SUI: 21,\n APTOS: 22,\n ARBITRUM: 23,\n OPTIMISM: 24,\n GNOSIS: 25,\n PYTHNET: 26,\n XPLA: 28,\n BASE: 30,\n SEI: 32,\n ROOTSTOCK: 33,\n SCROLL: 34,\n MANTLE: 35,\n BLAST: 36,\n XLAYER: 37,\n LINEA: 38,\n BERACHAIN: 39,\n SEIEVM: 40,\n },\n TESTNET: {\n SOLANA_DEVNET: 1,\n GOERLI: 2,\n BSC_TESTNET: 4,\n POLYGON_MUMBAI: 5,\n AVALANCHE_FUJI: 6,\n FANTOM_TESTNET: 10,\n CELO_ALFAJORES: 14,\n MOONBASE_ALPHA: 16,\n SUI_TESTNET: 21,\n APTOS_TESTNET: 22,\n SEPOLIA: 10002,\n ARBITRUM_SEPOLIA: 10003,\n BASE_SEPOLIA: 10004,\n OPTIMISM_SEPOLIA: 10005,\n HOLESKY: 10006,\n POLYGON_SEPOLIA: 10007,\n SEI_ATLANTIC_2: 10066, // Sei Arctic-1 testnet (EVM)\n STARKNET_SEPOLIA: 50001, // Custom bridge (non-Wormhole, relayer-attested)\n },\n} as const;\n\n// Legacy flat exports for backward compatibility\nexport const WORMHOLE_CHAIN_IDS_FLAT = {\n // Mainnets\n SOLANA: 1,\n ETHEREUM: 2,\n TERRA: 3,\n BSC: 4,\n POLYGON: 5,\n AVALANCHE: 6,\n OASIS: 7,\n ALGORAND: 8,\n AURORA: 9,\n FANTOM: 10,\n KARURA: 11,\n ACALA: 12,\n KLAYTN: 13,\n CELO: 14,\n NEAR: 15,\n MOONBEAM: 16,\n NEON: 17,\n TERRA2: 18,\n INJECTIVE: 19,\n OSMOSIS: 20,\n SUI: 21,\n APTOS: 22,\n ARBITRUM: 23,\n OPTIMISM: 24,\n GNOSIS: 25,\n PYTHNET: 26,\n XPLA: 28,\n BASE: 30,\n SEI: 32,\n ROOTSTOCK: 33,\n SCROLL: 34,\n MANTLE: 35,\n BLAST: 36,\n XLAYER: 37,\n LINEA: 38,\n BERACHAIN: 39,\n SEIEVM: 40,\n\n // Testnets\n SOLANA_DEVNET: 1,\n GOERLI: 2,\n BSC_TESTNET: 4,\n POLYGON_MUMBAI: 5,\n AVALANCHE_FUJI: 6,\n FANTOM_TESTNET: 10,\n CELO_ALFAJORES: 14,\n MOONBASE_ALPHA: 16,\n SUI_TESTNET: 21,\n APTOS_TESTNET: 22,\n ARBITRUM_SEPOLIA: 10003,\n BASE_SEPOLIA: 10004,\n OPTIMISM_SEPOLIA: 10005,\n POLYGON_SEPOLIA: 10007,\n HOLESKY: 10006,\n STARKNET_SEPOLIA: 50001, // Custom bridge (non-Wormhole)\n} as const;\n\n// ============================================================================\n// Testnet Chain Configurations\n// ============================================================================\n\nexport const TESTNET_CHAINS: Record<string, ChainConfig> = {\n baseSepolia: {\n name: 'Base Sepolia',\n chainId: 84532,\n wormholeChainId: 10004,\n rpcUrl: 'https://sepolia.base.org', // Public CORS-friendly RPC\n explorerUrl: 'https://sepolia.basescan.org',\n isEvm: true,\n contracts: {\n hub: '0x66D87dE68327f48A099c5B9bE97020Feab9a7c82',\n vaultFactory: '0xCFaEb5652aa2Ee60b2229dC8895B4159749C7e53',\n vaultImplementation: '0x0d13367C16c6f0B24eD275CC67C7D9f42878285c',\n wormholeCoreBridge: '0x79A1027a6A159502049F10906D333EC57E95F083',\n tokenBridge: '0x86F55A04690fd7815A3D802bD587e83eA888B239',\n },\n },\n optimismSepolia: {\n name: 'Optimism Sepolia',\n chainId: 11155420,\n wormholeChainId: 10005,\n rpcUrl: 'https://sepolia.optimism.io',\n explorerUrl: 'https://sepolia-optimism.etherscan.io',\n isEvm: true,\n contracts: {\n vaultFactory: '0xA5653d54079ABeCe780F8d9597B2bc4B09fe464A',\n vaultImplementation: '0x8099b1406485d2255ff89Ce5Ea18520802AFC150',\n wormholeCoreBridge: '0x31377888146f3253211EFEf5c676D41ECe7D58Fe',\n tokenBridge: '0x99737Ec4B815d816c49A385943baf0380e75c0Ac',\n },\n },\n arbitrumSepolia: {\n name: 'Arbitrum Sepolia',\n chainId: 421614,\n wormholeChainId: 10003,\n rpcUrl: 'https://sepolia-rollup.arbitrum.io/rpc',\n explorerUrl: 'https://sepolia.arbiscan.io',\n isEvm: true,\n contracts: {\n vaultFactory: '0xd36D3D5DB59d78f1E33813490F72DABC15C9B07c',\n vaultImplementation: '0xB10ACf39eBF17fc33F722cBD955b7aeCB0611bc4',\n wormholeCoreBridge: '0x6b9C8671cdDC8dEab9c719bB87cBd3e782bA6a35',\n tokenBridge: '0xC7A204bDBFe983FCD8d8E61D02b475D4073fF97e',\n },\n },\n seiTestnet: {\n name: 'Sei Atlantic-2',\n chainId: 1328,\n wormholeChainId: 40,\n rpcUrl: 'https://evm-rpc-testnet.sei-apis.com',\n explorerUrl: 'https://seitrace.com/?chain=atlantic-2',\n isEvm: true,\n contracts: {\n vaultFactory: '0x07F608AFf6d63b68029488b726d895c4Bb593038',\n vaultImplementation: '0xD66153fccFB6731fB6c4944FbD607ba86A76a1f6',\n wormholeCoreBridge: '0x0000000000000000000000000000000000000000', // Mock - not yet deployed\n },\n },\n solanaDevnet: {\n name: 'Solana Devnet',\n chainId: 0,\n wormholeChainId: 1,\n rpcUrl: 'https://api.devnet.solana.com',\n explorerUrl: 'https://explorer.solana.com',\n isEvm: false,\n contracts: {\n hub: 'AnyXHsqq9c2BiW4WgBcj6Aye7Ua7a7L7iSuwpfJxECJM',\n wormholeCoreBridge: '3u8hJUVTA4jH1wYAyUur7FFZVQ8H635K3tSHHF4ssjQ5',\n tokenBridge: 'DZnkkTmCiFWfYTfT41X3Rd1kDgozqzxWaHqsw6W4x2oe',\n },\n },\n aptosTestnet: {\n name: 'Aptos Testnet',\n chainId: 0,\n wormholeChainId: 22,\n rpcUrl: 'https://fullnode.testnet.aptoslabs.com/v1',\n explorerUrl: 'https://explorer.aptoslabs.com',\n isEvm: false,\n contracts: {\n hub: '0x0237e04f74b991b5b6030a793779663033f4ff4a1682a9e66c1f41fc1ec3e2a4',\n wormholeCoreBridge: '0x5bc11445584a763c1fa7ed39081f1b920954da14e04b32440cba863d03e19625',\n tokenBridge: '0x576410486a2da45eee6c949c995670112ddf2fbeedab20350d506328eefc9d4f',\n },\n },\n suiTestnet: {\n name: 'Sui Testnet',\n chainId: 0,\n wormholeChainId: 21,\n rpcUrl: 'https://fullnode.testnet.sui.io:443',\n explorerUrl: 'https://suiscan.xyz/testnet',\n isEvm: false,\n contracts: {\n hub: '0x35e99fdbbc1cde7e093da6f9e758ba2c4a077904bd64caee2fa6db5e6c4e9e37',\n wormholeCoreBridge: '0x31358d198147da50db32eda2562951d53973a0c0ad5ed738e9b17d88b213d790',\n },\n },\n starknetSepolia: {\n name: 'Starknet Sepolia',\n chainId: 0, // Native Starknet chain ID (SN_SEPOLIA = 0x534e5f5345504f4c4941)\n wormholeChainId: 50001, // Custom chain ID (50000+ reserved for non-Wormhole chains)\n rpcUrl: 'https://starknet-sepolia.g.alchemy.com/starknet/version/rpc/v0_7/tsOnfTBZDKMXcUA26OED-',\n explorerUrl: 'https://sepolia.starkscan.co',\n isEvm: false,\n contracts: {\n // Starknet spoke contract\n hub: '0x68adcc730ed6c355200d00f763825448497b9cdf7936ca121711e078c88e811',\n // Custom bridge contract (NOT Wormhole)\n wormholeCoreBridge: '0x2c458c1ae64556482b05cc2d3ee5b032ed114d68429dda2062c9849a5a725f8',\n },\n // Hub chain ID that Starknet bridge validates (Base Sepolia = 10004)\n hubChainId: 10004,\n },\n};\n\n// ============================================================================\n// Mainnet Chain Configurations\n// ============================================================================\n\nexport const MAINNET_CHAINS: Record<string, ChainConfig> = {\n ethereum: {\n name: 'Ethereum',\n chainId: 1,\n wormholeChainId: 2,\n rpcUrl: 'https://eth.llamarpc.com',\n explorerUrl: 'https://etherscan.io',\n isEvm: true,\n contracts: {\n wormholeCoreBridge: '0x98f3c9e6E3fAce36bAAd05FE09d375Ef1464288B',\n tokenBridge: '0x3ee18B2214AFF97000D974cf647E7C347E8fa585',\n },\n },\n base: {\n name: 'Base',\n chainId: 8453,\n wormholeChainId: 30,\n rpcUrl: 'https://mainnet.base.org',\n explorerUrl: 'https://basescan.org',\n isEvm: true,\n contracts: {\n wormholeCoreBridge: '0xbebdb6C8ddC678FfA9f8748f85C815C556Dd8ac6',\n tokenBridge: '0x8d2de8d2f73F1F4cAB472AC9A881C9b123C79627',\n },\n },\n optimism: {\n name: 'Optimism',\n chainId: 10,\n wormholeChainId: 24,\n rpcUrl: 'https://mainnet.optimism.io',\n explorerUrl: 'https://optimistic.etherscan.io',\n isEvm: true,\n contracts: {\n wormholeCoreBridge: '0xEe91C335eab126dF5fDB3797EA9d6aD93aeC9722',\n tokenBridge: '0x1D68124e65faFC907325e3EDbF8c4d84499DAa8b',\n },\n },\n arbitrum: {\n name: 'Arbitrum',\n chainId: 42161,\n wormholeChainId: 23,\n rpcUrl: 'https://arb1.arbitrum.io/rpc',\n explorerUrl: 'https://arbiscan.io',\n isEvm: true,\n contracts: {\n wormholeCoreBridge: '0xa5f208e072434bC67592E4C49C1B991BA79BCA46',\n tokenBridge: '0x0b2402144Bb366A632D14B83F244D2e0e21bD39c',\n },\n },\n polygon: {\n name: 'Polygon',\n chainId: 137,\n wormholeChainId: 5,\n rpcUrl: 'https://polygon-rpc.com',\n explorerUrl: 'https://polygonscan.com',\n isEvm: true,\n contracts: {\n wormholeCoreBridge: '0x7A4B5a56256163F07b2C80A7cA55aBE66c4ec4d7',\n tokenBridge: '0x5a58505a96D1dbf8dF91cB21B54419FC36e93fdE',\n },\n },\n solana: {\n name: 'Solana',\n chainId: 0,\n wormholeChainId: 1,\n rpcUrl: 'https://api.mainnet-beta.solana.com',\n explorerUrl: 'https://explorer.solana.com',\n isEvm: false,\n contracts: {\n wormholeCoreBridge: 'worm2ZoG2kUd4vFXhvjh93UUH596ayRfgQ2MgjNMTth',\n tokenBridge: 'wormDTUJ6AWPNvk59vGQbDvGJmqbDTdgWgAqcLBCgUb',\n },\n },\n aptos: {\n name: 'Aptos',\n chainId: 0,\n wormholeChainId: 22,\n rpcUrl: 'https://fullnode.mainnet.aptoslabs.com/v1',\n explorerUrl: 'https://explorer.aptoslabs.com',\n isEvm: false,\n contracts: {\n wormholeCoreBridge: '0x5bc11445584a763c1fa7ed39081f1b920954da14e04b32440cba863d03e19625',\n tokenBridge: '0x576410486a2da45eee6c949c995670112ddf2fbeedab20350d506328eefc9d4f',\n },\n },\n sui: {\n name: 'Sui',\n chainId: 0,\n wormholeChainId: 21,\n rpcUrl: 'https://fullnode.mainnet.sui.io:443',\n explorerUrl: 'https://suiscan.xyz/mainnet',\n isEvm: false,\n contracts: {\n wormholeCoreBridge: '0xaeab97f96cf9877fee2883315d459552b2b921edc16d7ceac6eab944dd88919c',\n },\n },\n};\n\n// ============================================================================\n// Wormhole API Endpoints\n// ============================================================================\n\nexport const WORMHOLE_API = {\n MAINNET: 'https://api.wormholescan.io',\n TESTNET: 'https://api.testnet.wormholescan.io',\n GUARDIAN_RPC_MAINNET: 'https://wormhole-v2-mainnet-api.certus.one',\n GUARDIAN_RPC_TESTNET: 'https://wormhole-v2-testnet-api.certus.one',\n} as const;\n\n// ============================================================================\n// Hub Contract ABI (minimal)\n// ============================================================================\n\nexport const HUB_ABI = [\n 'function authenticateAndDispatch((bytes authenticatorData, string clientDataJSON, uint256 challengeIndex, uint256 typeIndex, uint256 r, uint256 s) auth, uint256 publicKeyX, uint256 publicKeyY, uint16 targetChain, bytes actionPayload) external payable returns (uint64 sequence)',\n 'function authenticateRawAndDispatch(uint256 r, uint256 s, bytes32 messageHash, uint256 publicKeyX, uint256 publicKeyY, uint16 targetChain, bytes actionPayload, uint256 nonce) external payable returns (uint64 sequence)',\n 'function getNonce(bytes32 userKeyHash) external view returns (uint256)',\n 'function encodeTransferAction(address token, address recipient, uint256 amount) external pure returns (bytes)',\n 'function encodeExecuteAction(address target, uint256 value, bytes data) external pure returns (bytes)',\n 'function encodeBridgeAction(bytes32 token, uint256 amount, uint16 targetChain, bytes32 recipient) external pure returns (bytes)',\n 'function messageFee() external view returns (uint256)',\n 'event Dispatched(bytes32 indexed userKeyHash, uint16 targetChain, uint256 nonce, uint64 sequence, bytes actionPayload)',\n] as const;\n\n// ============================================================================\n// Vault Factory ABI (minimal)\n// ============================================================================\n\nexport const VAULT_FACTORY_ABI = [\n 'function createVault(bytes32 userKeyHash) external returns (address)',\n 'function getVault(bytes32 userKeyHash) external view returns (address)',\n 'function vaultExists(bytes32 userKeyHash) external view returns (bool)',\n 'event VaultCreated(bytes32 indexed userKeyHash, address vault)',\n] as const;\n\n// ============================================================================\n// Vault ABI (minimal)\n// ============================================================================\n\nexport const VAULT_ABI = [\n 'function execute(address target, uint256 value, bytes data) external returns (bytes)',\n 'function executeFromHub(bytes32 vaaHash, uint16 emitterChain, bytes32 emitterAddress, bytes payload) external',\n 'function owner() external view returns (bytes32)',\n 'function hub() external view returns (address)',\n 'receive() external payable',\n] as const;\n"],"mappings":"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","names":["hex"]}
1
+ {"version":3,"sources":["../../../src/chains/sui/SuiClient.ts","../../../src/payload.ts","../../../src/constants.ts"],"sourcesContent":["/**\n * Veridex Protocol SDK - Sui Chain Client\n *\n * Production-grade implementation of ChainClient interface for Sui.\n * Supports session management, query-based execution, and vault operations.\n *\n * Security:\n * - Native sui::ecdsa_k1::secp256k1_verify for signature validation\n * - CCQ-based session validation with 60s staleness window\n * - Replay protection via nonce verification\n *\n * Note: Sui is a spoke chain. Session registration/revocation happens on Hub.\n */\n\nimport { SuiClient as MystenSuiClient } from '@mysten/sui/client';\nimport { createHash } from 'crypto';\nimport type { SessionKey } from '../../sessions/types.js';\nimport type {\n ChainClient,\n ChainConfig,\n TransferParams,\n ExecuteParams,\n BridgeParams,\n DispatchResult,\n WebAuthnSignature,\n VaultCreationResult,\n RegisterSessionParams,\n RevokeSessionParams,\n SessionValidationResult,\n} from '../../core/types.js';\nimport { encodeTransferAction, encodeExecuteAction, encodeBridgeAction } from '../../payload.js';\n\n// ============================================================================\n// Types\n// ============================================================================\n\nexport interface SuiClientConfig {\n wormholeChainId: number;\n rpcUrl: string;\n packageId: string; // Veridex Spoke package ID\n wormholeCoreBridge: string;\n tokenBridge?: string;\n network?: 'mainnet' | 'testnet' | 'devnet';\n hubRpcUrl?: string; // Hub chain RPC for session management\n hubContractAddress?: string; // Hub contract for session management\n}\n\n// ============================================================================\n// SuiClient\n// ============================================================================\n\nexport class SuiClient implements ChainClient {\n private config: ChainConfig;\n private client: MystenSuiClient;\n private packageId: string;\n private hubRpcUrl?: string;\n private hubContractAddress?: string;\n\n constructor(config: SuiClientConfig) {\n this.config = {\n name: `Sui ${config.network || 'mainnet'}`,\n chainId: 0,\n wormholeChainId: config.wormholeChainId,\n rpcUrl: config.rpcUrl,\n explorerUrl: config.network === 'testnet'\n ? 'https://suiscan.xyz/testnet'\n : config.network === 'devnet'\n ? 'https://suiscan.xyz/devnet'\n : 'https://suiscan.xyz/mainnet',\n isEvm: false,\n contracts: {\n hub: config.packageId,\n wormholeCoreBridge: config.wormholeCoreBridge,\n tokenBridge: config.tokenBridge,\n },\n };\n\n this.client = new MystenSuiClient({ url: config.rpcUrl });\n this.packageId = config.packageId;\n this.hubRpcUrl = config.hubRpcUrl;\n this.hubContractAddress = config.hubContractAddress;\n }\n\n getConfig(): ChainConfig {\n return this.config;\n }\n\n async getNonce(_userKeyHash: string): Promise<bigint> {\n // Nonce is managed on the Hub for cross-chain actions.\n return 0n;\n }\n\n async getMessageFee(): Promise<bigint> {\n // Wormhole fees for Sui are generally handled by relayer submission.\n return 0n;\n }\n\n async buildTransferPayload(params: TransferParams): Promise<string> {\n return encodeTransferAction(params.token, params.recipient, params.amount);\n }\n\n async buildExecutePayload(params: ExecuteParams): Promise<string> {\n return encodeExecuteAction(params.target, params.value, params.data);\n }\n\n async buildBridgePayload(params: BridgeParams): Promise<string> {\n return encodeBridgeAction(params.token, params.amount, params.destinationChain, params.recipient);\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\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 Sui spoke chains. ' +\n 'Actions must be dispatched from the Hub (EVM) chain. '\n );\n }\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 const keyHash = this.computeKeyHash(publicKeyX, publicKeyY);\n const messageHash = this.buildMessageHash(keyHash, targetChain, actionPayload, nonce);\n\n const request = {\n messageHash,\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 const response = await fetch(`${relayerUrl}/api/v1/submit`, {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify(request),\n });\n\n if (!response.ok) {\n throw new Error(`Relayer submission failed: ${response.status} ${response.statusText}`);\n }\n\n const result = await response.json();\n\n return {\n transactionHash: result.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 // Sui vaults may be represented as shared objects on-chain; without registry object IDs,\n // we return the deterministic address used by the SDK for receiving and balance display.\n return this.computeVaultAddress(userKeyHash);\n }\n\n computeVaultAddress(userKeyHash: string): string {\n // SDK convention: Sui addresses are 32-byte hex with 0x prefix.\n const clean = userKeyHash.replace(/^0x/, '').padStart(64, '0');\n return '0x' + clean;\n }\n\n async vaultExists(_userKeyHash: string): Promise<boolean> {\n // Account addresses on Sui are implicit; treat as existing.\n return true;\n }\n\n async createVault(userKeyHash: string, signer: any): Promise<VaultCreationResult> {\n void signer;\n throw new Error(\n 'Vault creation on Sui must be done via cross-chain message from Hub. ' +\n `Use the Hub client to dispatch a vault creation action targeting Sui (chain ${this.config.wormholeChainId}). KeyHash=${userKeyHash}`\n );\n }\n\n async createVaultSponsored?(userKeyHash: string, sponsorPrivateKey: string, rpcUrl?: string): Promise<VaultCreationResult> {\n void userKeyHash;\n void sponsorPrivateKey;\n void rpcUrl;\n throw new Error(\n 'Vault creation on Sui must be done via cross-chain message from Hub. ' +\n 'Use relayer gasless submission to create vault.'\n );\n }\n\n /**\n * Create a vault via the relayer (sponsored/gasless)\n * This is the recommended way to create Sui vaults\n * \n * The relayer will dispatch a vault creation action from Hub to Sui spoke\n */\n async createVaultViaRelayer(\n userKeyHash: string,\n relayerUrl: string\n ): Promise<VaultCreationResult> {\n const response = await fetch(`${relayerUrl}/api/v1/sui/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,\n gasUsed: 0n,\n alreadyExisted: result.alreadyExists || false,\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/sui/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 // Best-effort placeholder.\n return 5_000n;\n }\n\n getFactoryAddress(): string | undefined {\n return undefined;\n }\n\n getImplementationAddress(): string | undefined {\n return undefined;\n }\n\n // ========================================================================\n // Balance utilities (used by VeridexSDK multichain)\n // ========================================================================\n\n async getNativeBalance(address: string): Promise<bigint> {\n const balance = await this.client.getBalance({ owner: address });\n return BigInt(balance.totalBalance);\n }\n\n async getTokenBalance(coinType: string, ownerAddress: string): Promise<bigint> {\n const balance = await this.client.getBalance({ owner: ownerAddress, coinType });\n return BigInt(balance.totalBalance);\n }\n\n getClient(): MystenSuiClient {\n return this.client;\n }\n\n getPackageId(): string {\n return this.packageId;\n }\n\n // ========================================================================\n // Session Management (Issue #13)\n // ========================================================================\n\n /**\n * Register a session key on the Hub (must be called via Hub client)\n * Sui spokes validate sessions via CCQ, but registration happens on Hub\n * \n * @throws Error - Session management must be done via Hub chain\n */\n async registerSession(_params: RegisterSessionParams): Promise<void> {\n throw new Error(\n 'Session registration must be performed on the Hub chain (Base). ' +\n 'Use EVMClient connected to the Hub to call registerSession().'\n );\n }\n\n /**\n * Revoke a session key on the Hub (must be called via Hub client)\n * \n * @throws Error - Session management must be done via Hub chain\n */\n async revokeSession(_params: RevokeSessionParams): Promise<void> {\n throw new Error(\n 'Session revocation must be performed on the Hub chain (Base). ' +\n 'Use EVMClient connected to the Hub to call revokeSession().'\n );\n }\n\n /**\n * Check if a session is active by querying the Hub\n * This method queries the Hub contract directly for session validation\n * \n * @param userKeyHash - Hash of user's Passkey public key\n * @param sessionKeyHash - Hash of session key to validate\n * @returns Session validation result with expiry and limits\n */\n async isSessionActive(\n _userKeyHash: string,\n _sessionKeyHash: string\n ): Promise<SessionValidationResult> {\n if (!this.hubRpcUrl || !this.hubContractAddress) {\n throw new Error(\n 'Hub configuration required for session validation. ' +\n 'Provide hubRpcUrl and hubContractAddress in SuiClientConfig.'\n );\n }\n\n // Query Hub contract for session status\n // This would normally use ethers.js to query the Hub contract\n // For production, import ethers dynamically or pass Hub client\n throw new Error(\n 'isSessionActive requires Hub client integration. ' +\n 'Use EVMClient.isSessionActive() on the Hub chain, ' +\n 'then pass the result to session execution on Sui.'\n );\n }\n\n /**\n * Get all sessions for a user from the Hub\n * \n * @param userKeyHash - Hash of user's Passkey public key\n * @returns Array of all sessions (active and expired/revoked)\n */\n async getUserSessions(userKeyHash: string): Promise<SessionKey[]> {\n if (!this.hubRpcUrl || !this.hubContractAddress) {\n throw new Error(\n 'Hub configuration required for session queries. ' +\n 'Provide hubRpcUrl and hubContractAddress in SuiClientConfig.'\n );\n }\n\n // Query Hub contract for user sessions\n throw new Error(\n 'getUserSessions requires Hub client integration. ' +\n 'Use EVMClient.getUserSessions() on the Hub chain. ' +\n `User: ${userKeyHash}`\n );\n }\n\n // ========================================================================\n // Query-Based Execution (Issue #9/#10)\n // ========================================================================\n\n /**\n * Get user state from Hub (comprehensive state query)\n * Returns key hash, nonce, and last action hash for CCQ validation\n * \n * @param userKeyHash - Hash of user's Passkey public key\n * @returns User state with nonce and last action hash\n */\n async getUserState(userKeyHash: string): Promise<{\n keyHash: string;\n nonce: bigint;\n lastActionHash: string;\n }> {\n if (!this.hubRpcUrl || !this.hubContractAddress) {\n throw new Error(\n 'Hub configuration required for state queries. ' +\n 'Provide hubRpcUrl and hubContractAddress in SuiClientConfig.'\n );\n }\n\n // Query Hub contract for user state\n // This enables query-based execution with CCQ validation\n throw new Error(\n 'getUserState requires Hub client integration. ' +\n 'Use EVMClient.getUserState() on the Hub chain. ' +\n `User: ${userKeyHash}`\n );\n }\n\n /**\n * Get user's last action hash from Hub\n * Used for optimistic execution and nonce validation\n * \n * @param userKeyHash - Hash of user's Passkey public key\n * @returns Last action hash (zero hash if no actions)\n */\n async getUserLastActionHash(userKeyHash: string): Promise<string> {\n if (!this.hubRpcUrl || !this.hubContractAddress) {\n throw new Error(\n 'Hub configuration required for action hash queries. ' +\n 'Provide hubRpcUrl and hubContractAddress in SuiClientConfig.'\n );\n }\n\n // Query Hub contract for last action hash\n throw new Error(\n 'getUserLastActionHash requires Hub client integration. ' +\n 'Use EVMClient.getUserLastActionHash() on the Hub chain. ' +\n `User: ${userKeyHash}`\n );\n }\n\n /**\n * Execute with query-based validation (faster than VAA, ~23s vs 60-90s)\n * Uses Wormhole CCQ to validate Hub state, then executes on Sui\n * \n * @param params Query execution parameters with CCQ response\n * @returns Dispatch result with transaction hash\n * \n * @remarks\n * Query-based execution flow:\n * 1. Query Hub state via Wormhole CCQ\n * 2. Validate Guardian signatures on query response\n * 3. Execute on Sui with validated state\n * 4. Hub state must be < 60s stale (enforced by QueryVerifier)\n */\n async executeWithQuery(\n _params: {\n userKeyHash: string;\n queryResponse: Uint8Array; // CCQ Guardian response\n actionType: number;\n actionPayload: Uint8Array;\n relayerUrl?: string;\n }\n ): Promise<DispatchResult> {\n throw new Error(\n 'Query-based execution on Sui requires relayer integration. ' +\n 'Use relayer API to submit query-validated transactions. ' +\n 'Relayer will call veridex_spoke::execute_with_query on Sui.'\n );\n }\n\n // ========================================================================\n // Internal helpers\n // ========================================================================\n\n private computeKeyHash(publicKeyX: bigint, publicKeyY: bigint): string {\n const xHex = publicKeyX.toString(16).padStart(64, '0');\n const yHex = publicKeyY.toString(16).padStart(64, '0');\n const combined = Buffer.from(xHex + yHex, 'hex');\n const hash = createHash('sha256').update(combined).digest('hex');\n return '0x' + hash;\n }\n\n private buildMessageHash(keyHash: string, targetChain: number, actionPayload: string, nonce: bigint): string {\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 nonceHex = nonce.toString(16).padStart(64, '0');\n const nonceBuffer = Buffer.from(nonceHex, 'hex');\n\n const combined = Buffer.concat([keyHashBuffer, targetChainBuffer, payloadBuffer, nonceBuffer]);\n const hash = createHash('sha256').update(combined).digest('hex');\n return '0x' + hash;\n }\n\n // ============================================================================\n // Social Recovery Methods (Issue #23)\n // ============================================================================\n // \n // Note: Social recovery is managed on the Hub chain (EVM).\n // Sui spokes receive and execute recovery VAAs broadcast from the Hub.\n // The relayer service handles submitting recovery transactions to Sui.\n //\n // SDK users should use EVMClient methods for guardian management and\n // recovery initiation on the Hub chain.\n // ============================================================================\n\n /**\n * Get vault object ID by owner key hash\n * \n * @param ownerKeyHash - Owner's passkey hash (32 bytes as hex)\n * @param configObjectId - Shared Config object ID\n * @param registryObjectId - Shared VaultRegistry object ID\n * @returns Vault object ID or null if not found\n */\n async getVaultId(\n ownerKeyHash: string,\n registryObjectId: string\n ): Promise<string | null> {\n try {\n // Query the VaultRegistry table for the owner_key_hash\n // The registry maps owner_key_hash -> vault ID\n const registryObject = await this.client.getObject({\n id: registryObjectId,\n options: { showContent: true },\n });\n\n if (!registryObject.data?.content) {\n return null;\n }\n\n // For a proper implementation, we'd need to query dynamic fields\n // or use a Move view function. This is a placeholder showing the pattern.\n console.warn('getVaultId requires dynamic field query - use Move view function');\n return null;\n } catch (error) {\n console.error('Error getting vault ID:', error);\n return null;\n }\n }\n\n /**\n * Get vault owner key hash from vault object\n * \n * @param vaultObjectId - Vault object ID\n * @returns Owner key hash as hex string\n */\n async getVaultOwner(vaultObjectId: string): Promise<string | null> {\n try {\n const vaultObject = await this.client.getObject({\n id: vaultObjectId,\n options: { showContent: true },\n });\n\n if (!vaultObject.data?.content || vaultObject.data.content.dataType !== 'moveObject') {\n return null;\n }\n\n const fields = vaultObject.data.content.fields as Record<string, unknown>;\n const ownerKeyHash = fields['owner_key_hash'] as number[] | undefined;\n\n if (!ownerKeyHash) {\n return null;\n }\n\n // Convert byte array to hex string\n return '0x' + Buffer.from(ownerKeyHash).toString('hex');\n } catch (error) {\n console.error('Error getting vault owner:', error);\n return null;\n }\n }\n\n /**\n * Get authorized signers for a vault\n * \n * @param vaultObjectId - Vault object ID\n * @returns Array of authorized signer key hashes\n */\n async getAuthorizedSigners(vaultObjectId: string): Promise<string[]> {\n try {\n const vaultObject = await this.client.getObject({\n id: vaultObjectId,\n options: { showContent: true },\n });\n\n if (!vaultObject.data?.content || vaultObject.data.content.dataType !== 'moveObject') {\n return [];\n }\n\n const fields = vaultObject.data.content.fields as Record<string, unknown>;\n const authorizedSigners = fields['authorized_signers'] as number[][] | undefined;\n\n if (!authorizedSigners) {\n return [];\n }\n\n // Convert each byte array to hex string\n return authorizedSigners.map(signer => \n '0x' + Buffer.from(signer).toString('hex')\n );\n } catch (error) {\n console.error('Error getting authorized signers:', error);\n return [];\n }\n }\n\n /**\n * Check if a VAA has been processed (for replay protection)\n * \n * @param vaaHash - VAA hash as hex string\n * @param processedVaasObjectId - ProcessedVAAs shared object ID\n * @returns Whether the VAA has been processed\n */\n async isVaaProcessed(\n vaaHash: string,\n processedVaasObjectId: string\n ): Promise<boolean> {\n try {\n const processedObject = await this.client.getObject({\n id: processedVaasObjectId,\n options: { showContent: true },\n });\n\n if (!processedObject.data?.content) {\n return false;\n }\n\n // Would need to query dynamic field for vaaHash key\n console.warn('isVaaProcessed requires dynamic field query');\n return false;\n } catch (error) {\n console.error('Error checking VAA status:', error);\n return false;\n }\n }\n\n /**\n * Check if protocol is paused\n * \n * @param configObjectId - Config shared object ID\n * @returns Whether the protocol is paused\n */\n async isProtocolPaused(configObjectId: string): Promise<boolean> {\n try {\n const configObject = await this.client.getObject({\n id: configObjectId,\n options: { showContent: true },\n });\n\n if (!configObject.data?.content || configObject.data.content.dataType !== 'moveObject') {\n return false;\n }\n\n const fields = configObject.data.content.fields as Record<string, unknown>;\n return fields['paused'] === true;\n } catch (error) {\n console.error('Error checking pause status:', error);\n return false;\n }\n }\n}\n","/**\n * Veridex Protocol SDK - Payload Encoding/Decoding Utilities\n */\n\nimport { ethers } from 'ethers';\nimport {\n ACTION_TRANSFER,\n ACTION_EXECUTE,\n ACTION_CONFIG,\n ACTION_BRIDGE,\n PROTOCOL_VERSION,\n} from './constants.js';\nimport type { TransferAction, BridgeAction, ExecuteAction, ActionPayload } from './types.js';\n\n// ============================================================================\n// Action Encoding\n// ============================================================================\n\n/**\n * Encode a transfer action payload\n * Format: [actionType(1)] [token(32)] [recipient(32)] [amount(32)]\n */\nexport function encodeTransferAction(\n token: string,\n recipient: string,\n amount: bigint\n): string {\n const tokenPadded = padTo32Bytes(token);\n const recipientPadded = padTo32Bytes(recipient);\n const amountBytes = ethers.zeroPadValue(ethers.toBeHex(amount), 32);\n\n return ethers.concat([\n ethers.toBeHex(ACTION_TRANSFER, 1),\n tokenPadded,\n recipientPadded,\n amountBytes,\n ]);\n}\n\n/**\n * Encode a bridge action payload\n * Format: [actionType(1)] [token(32)] [amount(32)] [targetChain(2)] [recipient(32)]\n */\nexport function encodeBridgeAction(\n token: string,\n amount: bigint,\n targetChain: number,\n recipient: string\n): string {\n const tokenPadded = padTo32Bytes(token);\n const amountBytes = ethers.zeroPadValue(ethers.toBeHex(amount), 32);\n const targetChainBytes = ethers.toBeHex(targetChain, 2);\n const recipientPadded = padTo32Bytes(recipient);\n\n return ethers.concat([\n ethers.toBeHex(ACTION_BRIDGE, 1),\n tokenPadded,\n amountBytes,\n targetChainBytes,\n recipientPadded,\n ]);\n}\n\n/**\n * Encode an execute action payload (arbitrary contract call)\n * Format: [actionType(1)] [target(32)] [value(32)] [dataLength(2)] [data(variable)]\n */\nexport function encodeExecuteAction(\n target: string,\n value: bigint,\n data: string\n): string {\n const targetPadded = padTo32Bytes(target);\n const valueBytes = ethers.zeroPadValue(ethers.toBeHex(value), 32);\n const dataBytes = ethers.getBytes(data);\n const dataLengthBytes = ethers.toBeHex(dataBytes.length, 2);\n\n return ethers.concat([\n ethers.toBeHex(ACTION_EXECUTE, 1),\n targetPadded,\n valueBytes,\n dataLengthBytes,\n data,\n ]);\n}\n\n/**\n * Encode a config action payload\n * Format: [actionType(1)] [configType(1)] [configData(variable)]\n */\nexport function encodeConfigAction(configType: number, configData: string): string {\n return ethers.concat([\n ethers.toBeHex(ACTION_CONFIG, 1),\n ethers.toBeHex(configType, 1),\n configData,\n ]);\n}\n\n// ============================================================================\n// Veridex Payload Encoding\n// ============================================================================\n\n/**\n * Encode the full Veridex message payload that gets published via Wormhole\n * Format: [version(1)] [userKeyHash(32)] [targetChain(2)] [nonce(32)] [pubKeyX(32)] [pubKeyY(32)] [actionPayload]\n */\nexport function encodeVeridexPayload(\n userKeyHash: string,\n targetChain: number,\n nonce: bigint,\n publicKeyX: bigint,\n publicKeyY: bigint,\n actionPayload: string\n): string {\n return ethers.concat([\n ethers.toBeHex(PROTOCOL_VERSION, 1),\n userKeyHash,\n ethers.toBeHex(targetChain, 2),\n ethers.zeroPadValue(ethers.toBeHex(nonce), 32),\n ethers.zeroPadValue(ethers.toBeHex(publicKeyX), 32),\n ethers.zeroPadValue(ethers.toBeHex(publicKeyY), 32),\n actionPayload,\n ]);\n}\n\n// ============================================================================\n// Action Decoding\n// ============================================================================\n\n/**\n * Decode an action payload to determine its type and contents\n */\nexport function decodeActionPayload(payload: string): ActionPayload {\n const data = ethers.getBytes(payload);\n const actionType = data[0];\n\n switch (actionType) {\n case ACTION_TRANSFER:\n return decodeTransferAction(payload);\n case ACTION_BRIDGE:\n return decodeBridgeAction(payload);\n case ACTION_EXECUTE:\n return decodeExecuteAction(payload);\n default:\n return { type: `unknown_${actionType}`, raw: payload };\n }\n}\n\n/**\n * Decode a transfer action payload\n */\nexport function decodeTransferAction(payload: string): TransferAction {\n const data = ethers.getBytes(payload);\n\n const tokenBytes = data.slice(1, 33);\n const recipientBytes = data.slice(33, 65);\n const amountBytes = data.slice(65, 97);\n\n return {\n type: 'transfer',\n token: trimTo20Bytes(ethers.hexlify(tokenBytes)),\n recipient: trimTo20Bytes(ethers.hexlify(recipientBytes)),\n amount: BigInt(ethers.hexlify(amountBytes)),\n };\n}\n\n/**\n * Decode a bridge action payload\n */\nexport function decodeBridgeAction(payload: string): BridgeAction {\n const data = ethers.getBytes(payload);\n\n const tokenBytes = data.slice(1, 33);\n const amountBytes = data.slice(33, 65);\n const targetChainByte0 = data[65];\n const targetChainByte1 = data[66];\n const recipientBytes = data.slice(67, 99);\n\n const targetChain = ((targetChainByte0 ?? 0) << 8) | (targetChainByte1 ?? 0);\n\n return {\n type: 'bridge',\n token: trimTo20Bytes(ethers.hexlify(tokenBytes)),\n amount: BigInt(ethers.hexlify(amountBytes)),\n targetChain,\n recipient: ethers.hexlify(recipientBytes),\n };\n}\n\n/**\n * Decode an execute action payload\n */\nexport function decodeExecuteAction(payload: string): ExecuteAction {\n const data = ethers.getBytes(payload);\n\n const targetBytes = data.slice(1, 33);\n const valueBytes = data.slice(33, 65);\n const dataLengthByte0 = data[65];\n const dataLengthByte1 = data[66];\n const dataLength = ((dataLengthByte0 ?? 0) << 8) | (dataLengthByte1 ?? 0);\n const callData = data.slice(67, 67 + dataLength);\n\n return {\n type: 'execute',\n target: trimTo20Bytes(ethers.hexlify(targetBytes)),\n value: BigInt(ethers.hexlify(valueBytes)),\n data: ethers.hexlify(callData),\n };\n}\n\n// ============================================================================\n// Chain-Specific Encodings\n// ============================================================================\n\n/**\n * Encode a Solana-compatible transfer action\n * Solana uses: [actionType(1)] [amount(8 LE)] [recipient(32)]\n */\nexport function encodeSolanaTransferAction(\n amount: bigint,\n recipient: string\n): string {\n const amountBytes = Buffer.alloc(8);\n amountBytes.writeBigUInt64LE(amount);\n\n const recipientBytes = ethers.getBytes(recipient);\n\n return ethers.hexlify(\n Buffer.concat([\n Buffer.from([ACTION_TRANSFER]),\n amountBytes,\n Buffer.from(recipientBytes),\n ])\n );\n}\n\n/**\n * Encode an Aptos-compatible transfer action\n * Aptos uses: [actionType(1)] [amount(8 LE)] [recipient(32)]\n */\nexport function encodeAptosTransferAction(\n amount: bigint,\n recipient: string\n): string {\n const amountBytes = Buffer.alloc(8);\n amountBytes.writeBigUInt64LE(amount);\n\n const recipientPadded = padTo32Bytes(recipient);\n\n return ethers.hexlify(\n Buffer.concat([\n Buffer.from([ACTION_TRANSFER]),\n amountBytes,\n Buffer.from(ethers.getBytes(recipientPadded)),\n ])\n );\n}\n\n/**\n * Encode a Sui-compatible transfer action\n * Sui uses: [actionType(1)] [amount(8 LE)] [recipient(32)]\n */\nexport function encodeSuiTransferAction(\n amount: bigint,\n recipient: string\n): string {\n const amountBytes = Buffer.alloc(8);\n amountBytes.writeBigUInt64LE(amount);\n\n const recipientPadded = padTo32Bytes(recipient);\n\n return ethers.hexlify(\n Buffer.concat([\n Buffer.from([ACTION_TRANSFER]),\n amountBytes,\n Buffer.from(ethers.getBytes(recipientPadded)),\n ])\n );\n}\n\n// ============================================================================\n// Address Utilities\n// ============================================================================\n\n/**\n * Pad an address to 32 bytes (Wormhole standard)\n * Supports both EVM addresses (0x...) and Solana addresses (base58)\n */\nexport function padTo32Bytes(address: string): string {\n // Handle native token - convert to zero address\n if (address.toLowerCase() === 'native') {\n return '0x' + '0'.repeat(64);\n }\n \n // If it starts with 0x, treat as hex\n if (address.startsWith('0x')) {\n const hex = address.replace('0x', '');\n // Validate that hex only contains valid hex characters\n if (!/^[0-9a-fA-F]*$/.test(hex)) {\n throw new Error(`Invalid address: ${address}. Expected hex string or 'native'.`);\n }\n return '0x' + hex.padStart(64, '0');\n }\n \n // Otherwise, assume base58 Solana address and decode it\n // Base58 character set (Bitcoin/Solana style - no 0, O, I, l)\n const base58Chars = '123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz';\n \n // Validate base58 characters\n for (const char of address) {\n if (!base58Chars.includes(char)) {\n throw new Error(`Invalid address: ${address}. Contains invalid base58 character '${char}'.`);\n }\n }\n \n // Decode base58 to bytes\n let value = BigInt(0);\n for (const char of address) {\n value = value * 58n + BigInt(base58Chars.indexOf(char));\n }\n \n // Convert to 32-byte hex\n let hex = value.toString(16);\n // Ensure it's not longer than 64 chars (32 bytes)\n if (hex.length > 64) {\n throw new Error(`Invalid address: ${address}. Decoded value too large for 32 bytes.`);\n }\n \n return '0x' + hex.padStart(64, '0');\n}\n\n/**\n * Trim a 32-byte hex to a 20-byte EVM address\n */\nexport function trimTo20Bytes(hex32: string): string {\n const clean = hex32.replace('0x', '');\n return '0x' + clean.slice(-40);\n}\n\n/**\n * Convert a Solana public key (base58) to bytes32\n * @deprecated Use padTo32Bytes instead, which now handles both EVM and Solana addresses\n */\nexport function solanaAddressToBytes32(base58Address: string): string {\n return padTo32Bytes(base58Address);\n}\n\n// ============================================================================\n// Amount Utilities\n// ============================================================================\n\n/**\n * Format an amount with decimals for display\n */\nexport function formatAmount(amount: bigint, decimals = 18): string {\n const divisor = 10n ** BigInt(decimals);\n const whole = amount / divisor;\n const fraction = amount % divisor;\n\n if (fraction === 0n) {\n return whole.toString();\n }\n\n const fractionStr = fraction.toString().padStart(decimals, '0');\n const trimmedFraction = fractionStr.replace(/0+$/, '');\n\n return `${whole}.${trimmedFraction}`;\n}\n\n/**\n * Parse an amount string with decimals to bigint\n */\nexport function parseAmount(amountStr: string, decimals = 18): bigint {\n const parts = amountStr.split('.');\n const whole = BigInt(parts[0] ?? '0');\n\n if (parts.length === 1 || !parts[1]) {\n return whole * (10n ** BigInt(decimals));\n }\n\n const fractionStr = parts[1].slice(0, decimals).padEnd(decimals, '0');\n const fraction = BigInt(fractionStr);\n\n return whole * (10n ** BigInt(decimals)) + fraction;\n}\n\n// ============================================================================\n// Nonce Utilities\n// ============================================================================\n\n/**\n * Generate a unique nonce for a transaction\n */\nexport function generateNonce(): bigint {\n const timestamp = BigInt(Date.now());\n const random = BigInt(Math.floor(Math.random() * 1000000));\n return (timestamp << 20n) | random;\n}\n\n/**\n * Create a message hash for signing (used in authenticateRawAndDispatch)\n */\nexport function createMessageHash(\n targetChain: number,\n actionPayload: string,\n nonce: bigint\n): string {\n return ethers.keccak256(\n ethers.solidityPacked(\n ['uint16', 'bytes', 'uint256'],\n [targetChain, actionPayload, nonce]\n )\n );\n}\n\n/**\n * Create the challenge bytes for gasless dispatch (matches Hub's authenticateAndDispatch)\n * \n * The Hub contract passes raw packed bytes to WebAuthn.verify():\n * abi.encodePacked(targetChain, actionPayload, userNonce, hubChainId)\n * \n * The WebAuthn library then base64url-encodes these bytes to match against clientDataJSON.\n * We do NOT hash here - the challenge is the raw packed bytes.\n * \n * @param targetChain - Wormhole chain ID of the destination\n * @param actionPayload - The action payload (hex string)\n * @param nonce - User's current nonce\n * @param hubChainId - Wormhole chain ID of the Hub (e.g., 30 for Base)\n * @returns The packed bytes as hex string (NOT hashed)\n */\nexport function createGaslessMessageHash(\n targetChain: number,\n actionPayload: string,\n nonce: bigint,\n hubChainId: number\n): string {\n // Return raw packed bytes - NO sha256 hash\n // The contract passes these bytes directly to WebAuthn.verify()\n return ethers.solidityPacked(\n ['uint16', 'bytes', 'uint256', 'uint16'],\n [targetChain, actionPayload, nonce, hubChainId]\n );\n}\n\n/**\n * Build the challenge bytes for WebAuthn signing (gasless flow)\n * Returns raw packed bytes that match what the Hub contract expects\n * \n * @param targetChain - Wormhole chain ID of the destination\n * @param actionPayload - The action payload (hex string)\n * @param nonce - User's current nonce\n * @param hubChainId - Wormhole chain ID of the Hub\n * @returns Challenge bytes for WebAuthn signing (raw packed, not hashed)\n */\nexport function buildGaslessChallenge(\n targetChain: number,\n actionPayload: string,\n nonce: bigint,\n hubChainId: number\n): Uint8Array {\n const packed = createGaslessMessageHash(targetChain, actionPayload, nonce, hubChainId);\n return ethers.getBytes(packed);\n}\n\n/**\n * Build the challenge bytes for WebAuthn signing\n */\nexport function buildChallenge(\n userKeyHash: string,\n targetChain: number,\n nonce: bigint,\n actionPayload: string\n): Uint8Array {\n const encoded = ethers.solidityPacked(\n ['bytes32', 'uint16', 'uint256', 'bytes'],\n [userKeyHash, targetChain, nonce, actionPayload]\n );\n return ethers.getBytes(ethers.keccak256(encoded));\n}\n","/**\n * Veridex Protocol SDK - Constants and Chain Configurations\n */\n\nimport type { ChainConfig } from './types.js';\n\n// ============================================================================\n// Action Type Constants\n// ============================================================================\n\nexport const ACTION_TYPES = {\n TRANSFER: 1,\n EXECUTE: 2,\n CONFIG: 3,\n BRIDGE: 4,\n} as const;\n\nexport const ACTION_TRANSFER = 1;\nexport const ACTION_EXECUTE = 2;\nexport const ACTION_CONFIG = 3;\nexport const ACTION_BRIDGE = 4;\n\n// Protocol version\nexport const PROTOCOL_VERSION = 1;\n\n// ============================================================================\n// Wormhole Chain IDs\n// ============================================================================\n\n/**\n * Wormhole Chain IDs organized by network\n * @see https://docs.wormhole.com/wormhole/reference/constants\n */\nexport const WORMHOLE_CHAIN_IDS = {\n MAINNET: {\n SOLANA: 1,\n ETHEREUM: 2,\n TERRA: 3,\n BSC: 4,\n POLYGON: 5,\n AVALANCHE: 6,\n OASIS: 7,\n ALGORAND: 8,\n AURORA: 9,\n FANTOM: 10,\n KARURA: 11,\n ACALA: 12,\n KLAYTN: 13,\n CELO: 14,\n NEAR: 15,\n MOONBEAM: 16,\n NEON: 17,\n TERRA2: 18,\n INJECTIVE: 19,\n OSMOSIS: 20,\n SUI: 21,\n APTOS: 22,\n ARBITRUM: 23,\n OPTIMISM: 24,\n GNOSIS: 25,\n PYTHNET: 26,\n XPLA: 28,\n BASE: 30,\n SEI: 32,\n ROOTSTOCK: 33,\n SCROLL: 34,\n MANTLE: 35,\n BLAST: 36,\n XLAYER: 37,\n LINEA: 38,\n BERACHAIN: 39,\n SEIEVM: 40,\n },\n TESTNET: {\n SOLANA_DEVNET: 1,\n GOERLI: 2,\n BSC_TESTNET: 4,\n POLYGON_MUMBAI: 5,\n AVALANCHE_FUJI: 6,\n FANTOM_TESTNET: 10,\n CELO_ALFAJORES: 14,\n MOONBASE_ALPHA: 16,\n SUI_TESTNET: 21,\n APTOS_TESTNET: 22,\n SEPOLIA: 10002,\n ARBITRUM_SEPOLIA: 10003,\n BASE_SEPOLIA: 10004,\n OPTIMISM_SEPOLIA: 10005,\n HOLESKY: 10006,\n POLYGON_SEPOLIA: 10007,\n SEI_ATLANTIC_2: 10066, // Sei Arctic-1 testnet (EVM)\n STARKNET_SEPOLIA: 50001, // Custom bridge (non-Wormhole, relayer-attested)\n },\n} as const;\n\n// Legacy flat exports for backward compatibility\nexport const WORMHOLE_CHAIN_IDS_FLAT = {\n // Mainnets\n SOLANA: 1,\n ETHEREUM: 2,\n TERRA: 3,\n BSC: 4,\n POLYGON: 5,\n AVALANCHE: 6,\n OASIS: 7,\n ALGORAND: 8,\n AURORA: 9,\n FANTOM: 10,\n KARURA: 11,\n ACALA: 12,\n KLAYTN: 13,\n CELO: 14,\n NEAR: 15,\n MOONBEAM: 16,\n NEON: 17,\n TERRA2: 18,\n INJECTIVE: 19,\n OSMOSIS: 20,\n SUI: 21,\n APTOS: 22,\n ARBITRUM: 23,\n OPTIMISM: 24,\n GNOSIS: 25,\n PYTHNET: 26,\n XPLA: 28,\n BASE: 30,\n SEI: 32,\n ROOTSTOCK: 33,\n SCROLL: 34,\n MANTLE: 35,\n BLAST: 36,\n XLAYER: 37,\n LINEA: 38,\n BERACHAIN: 39,\n SEIEVM: 40,\n\n // Testnets\n SOLANA_DEVNET: 1,\n GOERLI: 2,\n BSC_TESTNET: 4,\n POLYGON_MUMBAI: 5,\n AVALANCHE_FUJI: 6,\n FANTOM_TESTNET: 10,\n CELO_ALFAJORES: 14,\n MOONBASE_ALPHA: 16,\n SUI_TESTNET: 21,\n APTOS_TESTNET: 22,\n ARBITRUM_SEPOLIA: 10003,\n BASE_SEPOLIA: 10004,\n OPTIMISM_SEPOLIA: 10005,\n POLYGON_SEPOLIA: 10007,\n HOLESKY: 10006,\n STARKNET_SEPOLIA: 50001, // Custom bridge (non-Wormhole)\n} as const;\n\n// ============================================================================\n// Testnet Chain Configurations\n// ============================================================================\n\nexport const TESTNET_CHAINS: Record<string, ChainConfig> = {\n baseSepolia: {\n name: 'Base Sepolia',\n chainId: 84532,\n wormholeChainId: 10004,\n rpcUrl: 'https://sepolia.base.org', // Public CORS-friendly RPC\n explorerUrl: 'https://sepolia.basescan.org',\n isEvm: true,\n contracts: {\n hub: '0x66D87dE68327f48A099c5B9bE97020Feab9a7c82',\n vaultFactory: '0xCFaEb5652aa2Ee60b2229dC8895B4159749C7e53',\n vaultImplementation: '0x0d13367C16c6f0B24eD275CC67C7D9f42878285c',\n wormholeCoreBridge: '0x79A1027a6A159502049F10906D333EC57E95F083',\n tokenBridge: '0x86F55A04690fd7815A3D802bD587e83eA888B239',\n },\n },\n optimismSepolia: {\n name: 'Optimism Sepolia',\n chainId: 11155420,\n wormholeChainId: 10005,\n rpcUrl: 'https://sepolia.optimism.io',\n explorerUrl: 'https://sepolia-optimism.etherscan.io',\n isEvm: true,\n contracts: {\n vaultFactory: '0xA5653d54079ABeCe780F8d9597B2bc4B09fe464A',\n vaultImplementation: '0x8099b1406485d2255ff89Ce5Ea18520802AFC150',\n wormholeCoreBridge: '0x31377888146f3253211EFEf5c676D41ECe7D58Fe',\n tokenBridge: '0x99737Ec4B815d816c49A385943baf0380e75c0Ac',\n },\n },\n arbitrumSepolia: {\n name: 'Arbitrum Sepolia',\n chainId: 421614,\n wormholeChainId: 10003,\n rpcUrl: 'https://sepolia-rollup.arbitrum.io/rpc',\n explorerUrl: 'https://sepolia.arbiscan.io',\n isEvm: true,\n contracts: {\n vaultFactory: '0xd36D3D5DB59d78f1E33813490F72DABC15C9B07c',\n vaultImplementation: '0xB10ACf39eBF17fc33F722cBD955b7aeCB0611bc4',\n wormholeCoreBridge: '0x6b9C8671cdDC8dEab9c719bB87cBd3e782bA6a35',\n tokenBridge: '0xC7A204bDBFe983FCD8d8E61D02b475D4073fF97e',\n },\n },\n seiTestnet: {\n name: 'Sei Atlantic-2',\n chainId: 1328,\n wormholeChainId: 40,\n rpcUrl: 'https://evm-rpc-testnet.sei-apis.com',\n explorerUrl: 'https://seitrace.com/?chain=atlantic-2',\n isEvm: true,\n contracts: {\n vaultFactory: '0x07F608AFf6d63b68029488b726d895c4Bb593038',\n vaultImplementation: '0xD66153fccFB6731fB6c4944FbD607ba86A76a1f6',\n wormholeCoreBridge: '0x0000000000000000000000000000000000000000', // Mock - not yet deployed\n },\n },\n solanaDevnet: {\n name: 'Solana Devnet',\n chainId: 0,\n wormholeChainId: 1,\n rpcUrl: 'https://api.devnet.solana.com',\n explorerUrl: 'https://explorer.solana.com',\n isEvm: false,\n contracts: {\n hub: 'AnyXHsqq9c2BiW4WgBcj6Aye7Ua7a7L7iSuwpfJxECJM',\n wormholeCoreBridge: '3u8hJUVTA4jH1wYAyUur7FFZVQ8H635K3tSHHF4ssjQ5',\n tokenBridge: 'DZnkkTmCiFWfYTfT41X3Rd1kDgozqzxWaHqsw6W4x2oe',\n },\n },\n aptosTestnet: {\n name: 'Aptos Testnet',\n chainId: 0,\n wormholeChainId: 22,\n rpcUrl: 'https://fullnode.testnet.aptoslabs.com/v1',\n explorerUrl: 'https://explorer.aptoslabs.com',\n isEvm: false,\n contracts: {\n hub: '0x0237e04f74b991b5b6030a793779663033f4ff4a1682a9e66c1f41fc1ec3e2a4',\n wormholeCoreBridge: '0x5bc11445584a763c1fa7ed39081f1b920954da14e04b32440cba863d03e19625',\n tokenBridge: '0x576410486a2da45eee6c949c995670112ddf2fbeedab20350d506328eefc9d4f',\n },\n },\n suiTestnet: {\n name: 'Sui Testnet',\n chainId: 0,\n wormholeChainId: 21,\n rpcUrl: 'https://fullnode.testnet.sui.io:443',\n explorerUrl: 'https://suiscan.xyz/testnet',\n isEvm: false,\n contracts: {\n hub: '0x35e99fdbbc1cde7e093da6f9e758ba2c4a077904bd64caee2fa6db5e6c4e9e37',\n wormholeCoreBridge: '0x31358d198147da50db32eda2562951d53973a0c0ad5ed738e9b17d88b213d790',\n },\n },\n starknetSepolia: {\n name: 'Starknet Sepolia',\n chainId: 0, // Native Starknet chain ID (SN_SEPOLIA = 0x534e5f5345504f4c4941)\n wormholeChainId: 50001, // Custom chain ID (50000+ reserved for non-Wormhole chains)\n rpcUrl: 'https://starknet-sepolia.g.alchemy.com/starknet/version/rpc/v0_7/tsOnfTBZDKMXcUA26OED-',\n explorerUrl: 'https://sepolia.starkscan.co',\n isEvm: false,\n contracts: {\n // Starknet spoke contract\n hub: '0x68adcc730ed6c355200d00f763825448497b9cdf7936ca121711e078c88e811',\n // Custom bridge contract (NOT Wormhole)\n wormholeCoreBridge: '0x2c458c1ae64556482b05cc2d3ee5b032ed114d68429dda2062c9849a5a725f8',\n },\n // Hub chain ID that Starknet bridge validates (Base Sepolia = 10004)\n hubChainId: 10004,\n },\n};\n\n// ============================================================================\n// Mainnet Chain Configurations\n// ============================================================================\n\nexport const MAINNET_CHAINS: Record<string, ChainConfig> = {\n ethereum: {\n name: 'Ethereum',\n chainId: 1,\n wormholeChainId: 2,\n rpcUrl: 'https://eth.llamarpc.com',\n explorerUrl: 'https://etherscan.io',\n isEvm: true,\n contracts: {\n wormholeCoreBridge: '0x98f3c9e6E3fAce36bAAd05FE09d375Ef1464288B',\n tokenBridge: '0x3ee18B2214AFF97000D974cf647E7C347E8fa585',\n },\n },\n base: {\n name: 'Base',\n chainId: 8453,\n wormholeChainId: 30,\n rpcUrl: 'https://mainnet.base.org',\n explorerUrl: 'https://basescan.org',\n isEvm: true,\n contracts: {\n wormholeCoreBridge: '0xbebdb6C8ddC678FfA9f8748f85C815C556Dd8ac6',\n tokenBridge: '0x8d2de8d2f73F1F4cAB472AC9A881C9b123C79627',\n },\n },\n optimism: {\n name: 'Optimism',\n chainId: 10,\n wormholeChainId: 24,\n rpcUrl: 'https://mainnet.optimism.io',\n explorerUrl: 'https://optimistic.etherscan.io',\n isEvm: true,\n contracts: {\n wormholeCoreBridge: '0xEe91C335eab126dF5fDB3797EA9d6aD93aeC9722',\n tokenBridge: '0x1D68124e65faFC907325e3EDbF8c4d84499DAa8b',\n },\n },\n arbitrum: {\n name: 'Arbitrum',\n chainId: 42161,\n wormholeChainId: 23,\n rpcUrl: 'https://arb1.arbitrum.io/rpc',\n explorerUrl: 'https://arbiscan.io',\n isEvm: true,\n contracts: {\n wormholeCoreBridge: '0xa5f208e072434bC67592E4C49C1B991BA79BCA46',\n tokenBridge: '0x0b2402144Bb366A632D14B83F244D2e0e21bD39c',\n },\n },\n polygon: {\n name: 'Polygon',\n chainId: 137,\n wormholeChainId: 5,\n rpcUrl: 'https://polygon-rpc.com',\n explorerUrl: 'https://polygonscan.com',\n isEvm: true,\n contracts: {\n wormholeCoreBridge: '0x7A4B5a56256163F07b2C80A7cA55aBE66c4ec4d7',\n tokenBridge: '0x5a58505a96D1dbf8dF91cB21B54419FC36e93fdE',\n },\n },\n solana: {\n name: 'Solana',\n chainId: 0,\n wormholeChainId: 1,\n rpcUrl: 'https://api.mainnet-beta.solana.com',\n explorerUrl: 'https://explorer.solana.com',\n isEvm: false,\n contracts: {\n wormholeCoreBridge: 'worm2ZoG2kUd4vFXhvjh93UUH596ayRfgQ2MgjNMTth',\n tokenBridge: 'wormDTUJ6AWPNvk59vGQbDvGJmqbDTdgWgAqcLBCgUb',\n },\n },\n aptos: {\n name: 'Aptos',\n chainId: 0,\n wormholeChainId: 22,\n rpcUrl: 'https://fullnode.mainnet.aptoslabs.com/v1',\n explorerUrl: 'https://explorer.aptoslabs.com',\n isEvm: false,\n contracts: {\n wormholeCoreBridge: '0x5bc11445584a763c1fa7ed39081f1b920954da14e04b32440cba863d03e19625',\n tokenBridge: '0x576410486a2da45eee6c949c995670112ddf2fbeedab20350d506328eefc9d4f',\n },\n },\n sui: {\n name: 'Sui',\n chainId: 0,\n wormholeChainId: 21,\n rpcUrl: 'https://fullnode.mainnet.sui.io:443',\n explorerUrl: 'https://suiscan.xyz/mainnet',\n isEvm: false,\n contracts: {\n wormholeCoreBridge: '0xaeab97f96cf9877fee2883315d459552b2b921edc16d7ceac6eab944dd88919c',\n },\n },\n};\n\n// ============================================================================\n// Wormhole API Endpoints\n// ============================================================================\n\nexport const WORMHOLE_API = {\n MAINNET: 'https://api.wormholescan.io',\n TESTNET: 'https://api.testnet.wormholescan.io',\n GUARDIAN_RPC_MAINNET: 'https://wormhole-v2-mainnet-api.certus.one',\n GUARDIAN_RPC_TESTNET: 'https://wormhole-v2-testnet-api.certus.one',\n} as const;\n\n// ============================================================================\n// Hub Contract ABI (minimal)\n// ============================================================================\n\nexport const HUB_ABI = [\n 'function authenticateAndDispatch((bytes authenticatorData, string clientDataJSON, uint256 challengeIndex, uint256 typeIndex, uint256 r, uint256 s) auth, uint256 publicKeyX, uint256 publicKeyY, uint16 targetChain, bytes actionPayload) external payable returns (uint64 sequence)',\n 'function authenticateRawAndDispatch(uint256 r, uint256 s, bytes32 messageHash, uint256 publicKeyX, uint256 publicKeyY, uint16 targetChain, bytes actionPayload, uint256 nonce) external payable returns (uint64 sequence)',\n 'function userNonces(bytes32 userKeyHash) external view returns (uint256)',\n 'function encodeTransferAction(address token, address recipient, uint256 amount) external pure returns (bytes)',\n 'function encodeExecuteAction(address target, uint256 value, bytes data) external pure returns (bytes)',\n 'function encodeBridgeAction(bytes32 token, uint256 amount, uint16 targetChain, bytes32 recipient) external pure returns (bytes)',\n 'function messageFee() external view returns (uint256)',\n 'event Dispatched(bytes32 indexed userKeyHash, uint16 targetChain, uint256 nonce, uint64 sequence, bytes actionPayload)',\n] as const;\n\n// ============================================================================\n// Vault Factory ABI (minimal)\n// ============================================================================\n\nexport const VAULT_FACTORY_ABI = [\n 'function createVault(bytes32 userKeyHash) external returns (address)',\n 'function getVault(bytes32 userKeyHash) external view returns (address)',\n 'function vaultExists(bytes32 userKeyHash) external view returns (bool)',\n 'event VaultCreated(bytes32 indexed userKeyHash, address vault)',\n] as const;\n\n// ============================================================================\n// Vault ABI (minimal)\n// ============================================================================\n\nexport const VAULT_ABI = [\n 'function execute(address target, uint256 value, bytes data) external returns (bytes)',\n 'function executeFromHub(bytes32 vaaHash, uint16 emitterChain, bytes32 emitterAddress, bytes payload) external',\n 'function owner() external view returns (bytes32)',\n 'function hub() external view returns (address)',\n 'receive() external payable',\n] as const;\n"],"mappings":";AAcA,SAAS,aAAa,uBAAuB;AAC7C,SAAS,kBAAkB;;;ACX3B,SAAS,cAAc;;;ACahB,IAAM,kBAAkB;AACxB,IAAM,iBAAiB;AAEvB,IAAM,gBAAgB;;;ADEtB,SAAS,qBACd,OACA,WACA,QACQ;AACR,QAAM,cAAc,aAAa,KAAK;AACtC,QAAM,kBAAkB,aAAa,SAAS;AAC9C,QAAM,cAAc,OAAO,aAAa,OAAO,QAAQ,MAAM,GAAG,EAAE;AAElE,SAAO,OAAO,OAAO;AAAA,IACnB,OAAO,QAAQ,iBAAiB,CAAC;AAAA,IACjC;AAAA,IACA;AAAA,IACA;AAAA,EACF,CAAC;AACH;AAMO,SAAS,mBACd,OACA,QACA,aACA,WACQ;AACR,QAAM,cAAc,aAAa,KAAK;AACtC,QAAM,cAAc,OAAO,aAAa,OAAO,QAAQ,MAAM,GAAG,EAAE;AAClE,QAAM,mBAAmB,OAAO,QAAQ,aAAa,CAAC;AACtD,QAAM,kBAAkB,aAAa,SAAS;AAE9C,SAAO,OAAO,OAAO;AAAA,IACnB,OAAO,QAAQ,eAAe,CAAC;AAAA,IAC/B;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF,CAAC;AACH;AAMO,SAAS,oBACd,QACA,OACA,MACQ;AACR,QAAM,eAAe,aAAa,MAAM;AACxC,QAAM,aAAa,OAAO,aAAa,OAAO,QAAQ,KAAK,GAAG,EAAE;AAChE,QAAM,YAAY,OAAO,SAAS,IAAI;AACtC,QAAM,kBAAkB,OAAO,QAAQ,UAAU,QAAQ,CAAC;AAE1D,SAAO,OAAO,OAAO;AAAA,IACnB,OAAO,QAAQ,gBAAgB,CAAC;AAAA,IAChC;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF,CAAC;AACH;AA4MO,SAAS,aAAa,SAAyB;AAEpD,MAAI,QAAQ,YAAY,MAAM,UAAU;AACtC,WAAO,OAAO,IAAI,OAAO,EAAE;AAAA,EAC7B;AAGA,MAAI,QAAQ,WAAW,IAAI,GAAG;AAC5B,UAAMA,OAAM,QAAQ,QAAQ,MAAM,EAAE;AAEpC,QAAI,CAAC,iBAAiB,KAAKA,IAAG,GAAG;AAC/B,YAAM,IAAI,MAAM,oBAAoB,OAAO,oCAAoC;AAAA,IACjF;AACA,WAAO,OAAOA,KAAI,SAAS,IAAI,GAAG;AAAA,EACpC;AAIA,QAAM,cAAc;AAGpB,aAAW,QAAQ,SAAS;AAC1B,QAAI,CAAC,YAAY,SAAS,IAAI,GAAG;AAC/B,YAAM,IAAI,MAAM,oBAAoB,OAAO,wCAAwC,IAAI,IAAI;AAAA,IAC7F;AAAA,EACF;AAGA,MAAI,QAAQ,OAAO,CAAC;AACpB,aAAW,QAAQ,SAAS;AAC1B,YAAQ,QAAQ,MAAM,OAAO,YAAY,QAAQ,IAAI,CAAC;AAAA,EACxD;AAGA,MAAI,MAAM,MAAM,SAAS,EAAE;AAE3B,MAAI,IAAI,SAAS,IAAI;AACnB,UAAM,IAAI,MAAM,oBAAoB,OAAO,yCAAyC;AAAA,EACtF;AAEA,SAAO,OAAO,IAAI,SAAS,IAAI,GAAG;AACpC;;;ADtRO,IAAM,YAAN,MAAuC;AAAA,EAClC;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EAER,YAAY,QAAyB;AACjC,SAAK,SAAS;AAAA,MACV,MAAM,OAAO,OAAO,WAAW,SAAS;AAAA,MACxC,SAAS;AAAA,MACT,iBAAiB,OAAO;AAAA,MACxB,QAAQ,OAAO;AAAA,MACf,aAAa,OAAO,YAAY,YAC1B,gCACA,OAAO,YAAY,WACf,+BACA;AAAA,MACV,OAAO;AAAA,MACP,WAAW;AAAA,QACP,KAAK,OAAO;AAAA,QACZ,oBAAoB,OAAO;AAAA,QAC3B,aAAa,OAAO;AAAA,MACxB;AAAA,IACJ;AAEA,SAAK,SAAS,IAAI,gBAAgB,EAAE,KAAK,OAAO,OAAO,CAAC;AACxD,SAAK,YAAY,OAAO;AACxB,SAAK,YAAY,OAAO;AACxB,SAAK,qBAAqB,OAAO;AAAA,EACrC;AAAA,EAEA,YAAyB;AACrB,WAAO,KAAK;AAAA,EAChB;AAAA,EAEA,MAAM,SAAS,cAAuC;AAElD,WAAO;AAAA,EACX;AAAA,EAEA,MAAM,gBAAiC;AAEnC,WAAO;AAAA,EACX;AAAA,EAEA,MAAM,qBAAqB,QAAyC;AAChE,WAAO,qBAAqB,OAAO,OAAO,OAAO,WAAW,OAAO,MAAM;AAAA,EAC7E;AAAA,EAEA,MAAM,oBAAoB,QAAwC;AAC9D,WAAO,oBAAoB,OAAO,QAAQ,OAAO,OAAO,OAAO,IAAI;AAAA,EACvE;AAAA,EAEA,MAAM,mBAAmB,QAAuC;AAC5D,WAAO,mBAAmB,OAAO,OAAO,OAAO,QAAQ,OAAO,kBAAkB,OAAO,SAAS;AAAA,EACpG;AAAA,EAEA,MAAM,SACF,WACA,YACA,YACA,aACA,eACA,OACA,QACuB;AACvB,SAAK;AACL,SAAK;AACL,SAAK;AACL,SAAK;AACL,SAAK;AACL,SAAK;AACL,SAAK;AACL,UAAM,IAAI;AAAA,MACN;AAAA,IAEJ;AAAA,EACJ;AAAA,EAEA,MAAM,gBACF,WACA,YACA,YACA,aACA,eACA,OACA,YACuB;AACvB,UAAM,UAAU,KAAK,eAAe,YAAY,UAAU;AAC1D,UAAM,cAAc,KAAK,iBAAiB,SAAS,aAAa,eAAe,KAAK;AAEpF,UAAM,UAAU;AAAA,MACZ;AAAA,MACA,GAAG,OAAO,UAAU,EAAE,SAAS,EAAE,EAAE,SAAS,IAAI,GAAG;AAAA,MACnD,GAAG,OAAO,UAAU,EAAE,SAAS,EAAE,EAAE,SAAS,IAAI,GAAG;AAAA,MACnD,YAAY,OAAO,WAAW,SAAS,EAAE,EAAE,SAAS,IAAI,GAAG;AAAA,MAC3D,YAAY,OAAO,WAAW,SAAS,EAAE,EAAE,SAAS,IAAI,GAAG;AAAA,MAC3D;AAAA,MACA;AAAA,MACA,OAAO,OAAO,KAAK;AAAA,IACvB;AAEA,UAAM,WAAW,MAAM,MAAM,GAAG,UAAU,kBAAkB;AAAA,MACxD,QAAQ;AAAA,MACR,SAAS,EAAE,gBAAgB,mBAAmB;AAAA,MAC9C,MAAM,KAAK,UAAU,OAAO;AAAA,IAChC,CAAC;AAED,QAAI,CAAC,SAAS,IAAI;AACd,YAAM,IAAI,MAAM,8BAA8B,SAAS,MAAM,IAAI,SAAS,UAAU,EAAE;AAAA,IAC1F;AAEA,UAAM,SAAS,MAAM,SAAS,KAAK;AAEnC,WAAO;AAAA,MACH,iBAAiB,OAAO,mBAAmB,OAAO;AAAA,MAClD,UAAU,OAAO,OAAO,YAAY,CAAC;AAAA,MACrC,aAAa;AAAA,MACb;AAAA,IACJ;AAAA,EACJ;AAAA,EAEA,MAAM,gBAAgB,aAA6C;AAG/D,WAAO,KAAK,oBAAoB,WAAW;AAAA,EAC/C;AAAA,EAEA,oBAAoB,aAA6B;AAE7C,UAAM,QAAQ,YAAY,QAAQ,OAAO,EAAE,EAAE,SAAS,IAAI,GAAG;AAC7D,WAAO,OAAO;AAAA,EAClB;AAAA,EAEA,MAAM,YAAY,cAAwC;AAEtD,WAAO;AAAA,EACX;AAAA,EAEA,MAAM,YAAY,aAAqB,QAA2C;AAC9E,SAAK;AACL,UAAM,IAAI;AAAA,MACN,oJAC+E,KAAK,OAAO,eAAe,cAAc,WAAW;AAAA,IACvI;AAAA,EACJ;AAAA,EAEA,MAAM,qBAAsB,aAAqB,mBAA2B,QAA+C;AACvH,SAAK;AACL,SAAK;AACL,SAAK;AACL,UAAM,IAAI;AAAA,MACN;AAAA,IAEJ;AAAA,EACJ;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,MAAM,sBACF,aACA,YAC4B;AAC5B,UAAM,WAAW,MAAM,MAAM,GAAG,UAAU,qBAAqB;AAAA,MAC3D,QAAQ;AAAA,MACR,SAAS;AAAA,QACL,gBAAgB;AAAA,MACpB;AAAA,MACA,MAAM,KAAK,UAAU;AAAA,QACjB;AAAA,QACA,SAAS,KAAK,OAAO;AAAA,MACzB,CAAC;AAAA,IACL,CAAC;AAED,UAAM,SAAS,MAAM,SAAS,KAAK;AAEnC,QAAI,CAAC,SAAS,MAAM,CAAC,OAAO,SAAS;AACjC,YAAM,IAAI,MAAM,OAAO,SAAS,oCAAoC;AAAA,IACxE;AAEA,WAAO;AAAA,MACH,SAAS,OAAO;AAAA,MAChB,iBAAiB,OAAO,mBAAmB;AAAA,MAC3C,aAAa;AAAA,MACb,SAAS;AAAA,MACT,gBAAgB,OAAO,iBAAiB;AAAA,MACxC,aAAa;AAAA,IACjB;AAAA,EACJ;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,mBACF,aACA,YACkD;AAClD,UAAM,WAAW,MAAM;AAAA,MACnB,GAAG,UAAU,qBAAqB,WAAW,YAAY,KAAK,OAAO,eAAe;AAAA,IACxF;AAEA,QAAI,CAAC,SAAS,IAAI;AACd,YAAM,IAAI,MAAM,uCAAuC;AAAA,IAC3D;AAEA,UAAM,SAAS,MAAM,SAAS,KAAK;AACnC,WAAO;AAAA,MACH,cAAc,OAAO;AAAA,MACrB,QAAQ,OAAO;AAAA,IACnB;AAAA,EACJ;AAAA,EAEA,MAAM,yBAAyB,cAAuC;AAElE,WAAO;AAAA,EACX;AAAA,EAEA,oBAAwC;AACpC,WAAO;AAAA,EACX;AAAA,EAEA,2BAA+C;AAC3C,WAAO;AAAA,EACX;AAAA;AAAA;AAAA;AAAA,EAMA,MAAM,iBAAiB,SAAkC;AACrD,UAAM,UAAU,MAAM,KAAK,OAAO,WAAW,EAAE,OAAO,QAAQ,CAAC;AAC/D,WAAO,OAAO,QAAQ,YAAY;AAAA,EACtC;AAAA,EAEA,MAAM,gBAAgB,UAAkB,cAAuC;AAC3E,UAAM,UAAU,MAAM,KAAK,OAAO,WAAW,EAAE,OAAO,cAAc,SAAS,CAAC;AAC9E,WAAO,OAAO,QAAQ,YAAY;AAAA,EACtC;AAAA,EAEA,YAA6B;AACzB,WAAO,KAAK;AAAA,EAChB;AAAA,EAEA,eAAuB;AACnB,WAAO,KAAK;AAAA,EAChB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAYA,MAAM,gBAAgB,SAA+C;AACjE,UAAM,IAAI;AAAA,MACN;AAAA,IAEJ;AAAA,EACJ;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,MAAM,cAAc,SAA6C;AAC7D,UAAM,IAAI;AAAA,MACN;AAAA,IAEJ;AAAA,EACJ;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAUA,MAAM,gBACF,cACA,iBACgC;AAChC,QAAI,CAAC,KAAK,aAAa,CAAC,KAAK,oBAAoB;AAC7C,YAAM,IAAI;AAAA,QACN;AAAA,MAEJ;AAAA,IACJ;AAKA,UAAM,IAAI;AAAA,MACN;AAAA,IAGJ;AAAA,EACJ;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,MAAM,gBAAgB,aAA4C;AAC9D,QAAI,CAAC,KAAK,aAAa,CAAC,KAAK,oBAAoB;AAC7C,YAAM,IAAI;AAAA,QACN;AAAA,MAEJ;AAAA,IACJ;AAGA,UAAM,IAAI;AAAA,MACN,4GAES,WAAW;AAAA,IACxB;AAAA,EACJ;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAaA,MAAM,aAAa,aAIhB;AACC,QAAI,CAAC,KAAK,aAAa,CAAC,KAAK,oBAAoB;AAC7C,YAAM,IAAI;AAAA,QACN;AAAA,MAEJ;AAAA,IACJ;AAIA,UAAM,IAAI;AAAA,MACN,sGAES,WAAW;AAAA,IACxB;AAAA,EACJ;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASA,MAAM,sBAAsB,aAAsC;AAC9D,QAAI,CAAC,KAAK,aAAa,CAAC,KAAK,oBAAoB;AAC7C,YAAM,IAAI;AAAA,QACN;AAAA,MAEJ;AAAA,IACJ;AAGA,UAAM,IAAI;AAAA,MACN,wHAES,WAAW;AAAA,IACxB;AAAA,EACJ;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAgBA,MAAM,iBACF,SAOuB;AACvB,UAAM,IAAI;AAAA,MACN;AAAA,IAGJ;AAAA,EACJ;AAAA;AAAA;AAAA;AAAA,EAMQ,eAAe,YAAoB,YAA4B;AACnE,UAAM,OAAO,WAAW,SAAS,EAAE,EAAE,SAAS,IAAI,GAAG;AACrD,UAAM,OAAO,WAAW,SAAS,EAAE,EAAE,SAAS,IAAI,GAAG;AACrD,UAAM,WAAW,OAAO,KAAK,OAAO,MAAM,KAAK;AAC/C,UAAM,OAAO,WAAW,QAAQ,EAAE,OAAO,QAAQ,EAAE,OAAO,KAAK;AAC/D,WAAO,OAAO;AAAA,EAClB;AAAA,EAEQ,iBAAiB,SAAiB,aAAqB,eAAuB,OAAuB;AACzG,UAAM,gBAAgB,OAAO,KAAK,QAAQ,QAAQ,OAAO,EAAE,GAAG,KAAK;AACnE,UAAM,oBAAoB,OAAO,MAAM,CAAC;AACxC,sBAAkB,cAAc,WAAW;AAC3C,UAAM,gBAAgB,OAAO,KAAK,cAAc,QAAQ,OAAO,EAAE,GAAG,KAAK;AACzE,UAAM,WAAW,MAAM,SAAS,EAAE,EAAE,SAAS,IAAI,GAAG;AACpD,UAAM,cAAc,OAAO,KAAK,UAAU,KAAK;AAE/C,UAAM,WAAW,OAAO,OAAO,CAAC,eAAe,mBAAmB,eAAe,WAAW,CAAC;AAC7F,UAAM,OAAO,WAAW,QAAQ,EAAE,OAAO,QAAQ,EAAE,OAAO,KAAK;AAC/D,WAAO,OAAO;AAAA,EAClB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAsBA,MAAM,WACF,cACA,kBACsB;AACtB,QAAI;AAGA,YAAM,iBAAiB,MAAM,KAAK,OAAO,UAAU;AAAA,QAC/C,IAAI;AAAA,QACJ,SAAS,EAAE,aAAa,KAAK;AAAA,MACjC,CAAC;AAED,UAAI,CAAC,eAAe,MAAM,SAAS;AAC/B,eAAO;AAAA,MACX;AAIA,cAAQ,KAAK,kEAAkE;AAC/E,aAAO;AAAA,IACX,SAAS,OAAO;AACZ,cAAQ,MAAM,2BAA2B,KAAK;AAC9C,aAAO;AAAA,IACX;AAAA,EACJ;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,MAAM,cAAc,eAA+C;AAC/D,QAAI;AACA,YAAM,cAAc,MAAM,KAAK,OAAO,UAAU;AAAA,QAC5C,IAAI;AAAA,QACJ,SAAS,EAAE,aAAa,KAAK;AAAA,MACjC,CAAC;AAED,UAAI,CAAC,YAAY,MAAM,WAAW,YAAY,KAAK,QAAQ,aAAa,cAAc;AAClF,eAAO;AAAA,MACX;AAEA,YAAM,SAAS,YAAY,KAAK,QAAQ;AACxC,YAAM,eAAe,OAAO,gBAAgB;AAE5C,UAAI,CAAC,cAAc;AACf,eAAO;AAAA,MACX;AAGA,aAAO,OAAO,OAAO,KAAK,YAAY,EAAE,SAAS,KAAK;AAAA,IAC1D,SAAS,OAAO;AACZ,cAAQ,MAAM,8BAA8B,KAAK;AACjD,aAAO;AAAA,IACX;AAAA,EACJ;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,MAAM,qBAAqB,eAA0C;AACjE,QAAI;AACA,YAAM,cAAc,MAAM,KAAK,OAAO,UAAU;AAAA,QAC5C,IAAI;AAAA,QACJ,SAAS,EAAE,aAAa,KAAK;AAAA,MACjC,CAAC;AAED,UAAI,CAAC,YAAY,MAAM,WAAW,YAAY,KAAK,QAAQ,aAAa,cAAc;AAClF,eAAO,CAAC;AAAA,MACZ;AAEA,YAAM,SAAS,YAAY,KAAK,QAAQ;AACxC,YAAM,oBAAoB,OAAO,oBAAoB;AAErD,UAAI,CAAC,mBAAmB;AACpB,eAAO,CAAC;AAAA,MACZ;AAGA,aAAO,kBAAkB;AAAA,QAAI,YACzB,OAAO,OAAO,KAAK,MAAM,EAAE,SAAS,KAAK;AAAA,MAC7C;AAAA,IACJ,SAAS,OAAO;AACZ,cAAQ,MAAM,qCAAqC,KAAK;AACxD,aAAO,CAAC;AAAA,IACZ;AAAA,EACJ;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASA,MAAM,eACF,SACA,uBACgB;AAChB,QAAI;AACA,YAAM,kBAAkB,MAAM,KAAK,OAAO,UAAU;AAAA,QAChD,IAAI;AAAA,QACJ,SAAS,EAAE,aAAa,KAAK;AAAA,MACjC,CAAC;AAED,UAAI,CAAC,gBAAgB,MAAM,SAAS;AAChC,eAAO;AAAA,MACX;AAGA,cAAQ,KAAK,6CAA6C;AAC1D,aAAO;AAAA,IACX,SAAS,OAAO;AACZ,cAAQ,MAAM,8BAA8B,KAAK;AACjD,aAAO;AAAA,IACX;AAAA,EACJ;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,MAAM,iBAAiB,gBAA0C;AAC7D,QAAI;AACA,YAAM,eAAe,MAAM,KAAK,OAAO,UAAU;AAAA,QAC7C,IAAI;AAAA,QACJ,SAAS,EAAE,aAAa,KAAK;AAAA,MACjC,CAAC;AAED,UAAI,CAAC,aAAa,MAAM,WAAW,aAAa,KAAK,QAAQ,aAAa,cAAc;AACpF,eAAO;AAAA,MACX;AAEA,YAAM,SAAS,aAAa,KAAK,QAAQ;AACzC,aAAO,OAAO,QAAQ,MAAM;AAAA,IAChC,SAAS,OAAO;AACZ,cAAQ,MAAM,gCAAgC,KAAK;AACnD,aAAO;AAAA,IACX;AAAA,EACJ;AACJ;","names":["hex"]}
@@ -143,7 +143,7 @@ declare const WORMHOLE_API: {
143
143
  readonly GUARDIAN_RPC_MAINNET: "https://wormhole-v2-mainnet-api.certus.one";
144
144
  readonly GUARDIAN_RPC_TESTNET: "https://wormhole-v2-testnet-api.certus.one";
145
145
  };
146
- declare const HUB_ABI: readonly ["function authenticateAndDispatch((bytes authenticatorData, string clientDataJSON, uint256 challengeIndex, uint256 typeIndex, uint256 r, uint256 s) auth, uint256 publicKeyX, uint256 publicKeyY, uint16 targetChain, bytes actionPayload) external payable returns (uint64 sequence)", "function authenticateRawAndDispatch(uint256 r, uint256 s, bytes32 messageHash, uint256 publicKeyX, uint256 publicKeyY, uint16 targetChain, bytes actionPayload, uint256 nonce) external payable returns (uint64 sequence)", "function getNonce(bytes32 userKeyHash) external view returns (uint256)", "function encodeTransferAction(address token, address recipient, uint256 amount) external pure returns (bytes)", "function encodeExecuteAction(address target, uint256 value, bytes data) external pure returns (bytes)", "function encodeBridgeAction(bytes32 token, uint256 amount, uint16 targetChain, bytes32 recipient) external pure returns (bytes)", "function messageFee() external view returns (uint256)", "event Dispatched(bytes32 indexed userKeyHash, uint16 targetChain, uint256 nonce, uint64 sequence, bytes actionPayload)"];
146
+ declare const HUB_ABI: readonly ["function authenticateAndDispatch((bytes authenticatorData, string clientDataJSON, uint256 challengeIndex, uint256 typeIndex, uint256 r, uint256 s) auth, uint256 publicKeyX, uint256 publicKeyY, uint16 targetChain, bytes actionPayload) external payable returns (uint64 sequence)", "function authenticateRawAndDispatch(uint256 r, uint256 s, bytes32 messageHash, uint256 publicKeyX, uint256 publicKeyY, uint16 targetChain, bytes actionPayload, uint256 nonce) external payable returns (uint64 sequence)", "function userNonces(bytes32 userKeyHash) external view returns (uint256)", "function encodeTransferAction(address token, address recipient, uint256 amount) external pure returns (bytes)", "function encodeExecuteAction(address target, uint256 value, bytes data) external pure returns (bytes)", "function encodeBridgeAction(bytes32 token, uint256 amount, uint16 targetChain, bytes32 recipient) external pure returns (bytes)", "function messageFee() external view returns (uint256)", "event Dispatched(bytes32 indexed userKeyHash, uint16 targetChain, uint256 nonce, uint64 sequence, bytes actionPayload)"];
147
147
  declare const VAULT_FACTORY_ABI: readonly ["function createVault(bytes32 userKeyHash) external returns (address)", "function getVault(bytes32 userKeyHash) external view returns (address)", "function vaultExists(bytes32 userKeyHash) external view returns (bool)", "event VaultCreated(bytes32 indexed userKeyHash, address vault)"];
148
148
  declare const VAULT_ABI: readonly ["function execute(address target, uint256 value, bytes data) external returns (bytes)", "function executeFromHub(bytes32 vaaHash, uint16 emitterChain, bytes32 emitterAddress, bytes payload) external", "function owner() external view returns (bytes32)", "function hub() external view returns (address)", "receive() external payable"];
149
149
 
@@ -143,7 +143,7 @@ declare const WORMHOLE_API: {
143
143
  readonly GUARDIAN_RPC_MAINNET: "https://wormhole-v2-mainnet-api.certus.one";
144
144
  readonly GUARDIAN_RPC_TESTNET: "https://wormhole-v2-testnet-api.certus.one";
145
145
  };
146
- declare const HUB_ABI: readonly ["function authenticateAndDispatch((bytes authenticatorData, string clientDataJSON, uint256 challengeIndex, uint256 typeIndex, uint256 r, uint256 s) auth, uint256 publicKeyX, uint256 publicKeyY, uint16 targetChain, bytes actionPayload) external payable returns (uint64 sequence)", "function authenticateRawAndDispatch(uint256 r, uint256 s, bytes32 messageHash, uint256 publicKeyX, uint256 publicKeyY, uint16 targetChain, bytes actionPayload, uint256 nonce) external payable returns (uint64 sequence)", "function getNonce(bytes32 userKeyHash) external view returns (uint256)", "function encodeTransferAction(address token, address recipient, uint256 amount) external pure returns (bytes)", "function encodeExecuteAction(address target, uint256 value, bytes data) external pure returns (bytes)", "function encodeBridgeAction(bytes32 token, uint256 amount, uint16 targetChain, bytes32 recipient) external pure returns (bytes)", "function messageFee() external view returns (uint256)", "event Dispatched(bytes32 indexed userKeyHash, uint16 targetChain, uint256 nonce, uint64 sequence, bytes actionPayload)"];
146
+ declare const HUB_ABI: readonly ["function authenticateAndDispatch((bytes authenticatorData, string clientDataJSON, uint256 challengeIndex, uint256 typeIndex, uint256 r, uint256 s) auth, uint256 publicKeyX, uint256 publicKeyY, uint16 targetChain, bytes actionPayload) external payable returns (uint64 sequence)", "function authenticateRawAndDispatch(uint256 r, uint256 s, bytes32 messageHash, uint256 publicKeyX, uint256 publicKeyY, uint16 targetChain, bytes actionPayload, uint256 nonce) external payable returns (uint64 sequence)", "function userNonces(bytes32 userKeyHash) external view returns (uint256)", "function encodeTransferAction(address token, address recipient, uint256 amount) external pure returns (bytes)", "function encodeExecuteAction(address target, uint256 value, bytes data) external pure returns (bytes)", "function encodeBridgeAction(bytes32 token, uint256 amount, uint16 targetChain, bytes32 recipient) external pure returns (bytes)", "function messageFee() external view returns (uint256)", "event Dispatched(bytes32 indexed userKeyHash, uint16 targetChain, uint256 nonce, uint64 sequence, bytes actionPayload)"];
147
147
  declare const VAULT_FACTORY_ABI: readonly ["function createVault(bytes32 userKeyHash) external returns (address)", "function getVault(bytes32 userKeyHash) external view returns (address)", "function vaultExists(bytes32 userKeyHash) external view returns (bool)", "event VaultCreated(bytes32 indexed userKeyHash, address vault)"];
148
148
  declare const VAULT_ABI: readonly ["function execute(address target, uint256 value, bytes data) external returns (bytes)", "function executeFromHub(bytes32 vaaHash, uint16 emitterChain, bytes32 emitterAddress, bytes payload) external", "function owner() external view returns (bytes32)", "function hub() external view returns (address)", "receive() external payable"];
149
149
 
package/dist/constants.js CHANGED
@@ -390,7 +390,7 @@ var WORMHOLE_API = {
390
390
  var HUB_ABI = [
391
391
  "function authenticateAndDispatch((bytes authenticatorData, string clientDataJSON, uint256 challengeIndex, uint256 typeIndex, uint256 r, uint256 s) auth, uint256 publicKeyX, uint256 publicKeyY, uint16 targetChain, bytes actionPayload) external payable returns (uint64 sequence)",
392
392
  "function authenticateRawAndDispatch(uint256 r, uint256 s, bytes32 messageHash, uint256 publicKeyX, uint256 publicKeyY, uint16 targetChain, bytes actionPayload, uint256 nonce) external payable returns (uint64 sequence)",
393
- "function getNonce(bytes32 userKeyHash) external view returns (uint256)",
393
+ "function userNonces(bytes32 userKeyHash) external view returns (uint256)",
394
394
  "function encodeTransferAction(address token, address recipient, uint256 amount) external pure returns (bytes)",
395
395
  "function encodeExecuteAction(address target, uint256 value, bytes data) external pure returns (bytes)",
396
396
  "function encodeBridgeAction(bytes32 token, uint256 amount, uint16 targetChain, bytes32 recipient) external pure returns (bytes)",
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/constants.ts"],"sourcesContent":["/**\n * Veridex Protocol SDK - Constants and Chain Configurations\n */\n\nimport type { ChainConfig } from './types.js';\n\n// ============================================================================\n// Action Type Constants\n// ============================================================================\n\nexport const ACTION_TYPES = {\n TRANSFER: 1,\n EXECUTE: 2,\n CONFIG: 3,\n BRIDGE: 4,\n} as const;\n\nexport const ACTION_TRANSFER = 1;\nexport const ACTION_EXECUTE = 2;\nexport const ACTION_CONFIG = 3;\nexport const ACTION_BRIDGE = 4;\n\n// Protocol version\nexport const PROTOCOL_VERSION = 1;\n\n// ============================================================================\n// Wormhole Chain IDs\n// ============================================================================\n\n/**\n * Wormhole Chain IDs organized by network\n * @see https://docs.wormhole.com/wormhole/reference/constants\n */\nexport const WORMHOLE_CHAIN_IDS = {\n MAINNET: {\n SOLANA: 1,\n ETHEREUM: 2,\n TERRA: 3,\n BSC: 4,\n POLYGON: 5,\n AVALANCHE: 6,\n OASIS: 7,\n ALGORAND: 8,\n AURORA: 9,\n FANTOM: 10,\n KARURA: 11,\n ACALA: 12,\n KLAYTN: 13,\n CELO: 14,\n NEAR: 15,\n MOONBEAM: 16,\n NEON: 17,\n TERRA2: 18,\n INJECTIVE: 19,\n OSMOSIS: 20,\n SUI: 21,\n APTOS: 22,\n ARBITRUM: 23,\n OPTIMISM: 24,\n GNOSIS: 25,\n PYTHNET: 26,\n XPLA: 28,\n BASE: 30,\n SEI: 32,\n ROOTSTOCK: 33,\n SCROLL: 34,\n MANTLE: 35,\n BLAST: 36,\n XLAYER: 37,\n LINEA: 38,\n BERACHAIN: 39,\n SEIEVM: 40,\n },\n TESTNET: {\n SOLANA_DEVNET: 1,\n GOERLI: 2,\n BSC_TESTNET: 4,\n POLYGON_MUMBAI: 5,\n AVALANCHE_FUJI: 6,\n FANTOM_TESTNET: 10,\n CELO_ALFAJORES: 14,\n MOONBASE_ALPHA: 16,\n SUI_TESTNET: 21,\n APTOS_TESTNET: 22,\n SEPOLIA: 10002,\n ARBITRUM_SEPOLIA: 10003,\n BASE_SEPOLIA: 10004,\n OPTIMISM_SEPOLIA: 10005,\n HOLESKY: 10006,\n POLYGON_SEPOLIA: 10007,\n SEI_ATLANTIC_2: 10066, // Sei Arctic-1 testnet (EVM)\n STARKNET_SEPOLIA: 50001, // Custom bridge (non-Wormhole, relayer-attested)\n },\n} as const;\n\n// Legacy flat exports for backward compatibility\nexport const WORMHOLE_CHAIN_IDS_FLAT = {\n // Mainnets\n SOLANA: 1,\n ETHEREUM: 2,\n TERRA: 3,\n BSC: 4,\n POLYGON: 5,\n AVALANCHE: 6,\n OASIS: 7,\n ALGORAND: 8,\n AURORA: 9,\n FANTOM: 10,\n KARURA: 11,\n ACALA: 12,\n KLAYTN: 13,\n CELO: 14,\n NEAR: 15,\n MOONBEAM: 16,\n NEON: 17,\n TERRA2: 18,\n INJECTIVE: 19,\n OSMOSIS: 20,\n SUI: 21,\n APTOS: 22,\n ARBITRUM: 23,\n OPTIMISM: 24,\n GNOSIS: 25,\n PYTHNET: 26,\n XPLA: 28,\n BASE: 30,\n SEI: 32,\n ROOTSTOCK: 33,\n SCROLL: 34,\n MANTLE: 35,\n BLAST: 36,\n XLAYER: 37,\n LINEA: 38,\n BERACHAIN: 39,\n SEIEVM: 40,\n\n // Testnets\n SOLANA_DEVNET: 1,\n GOERLI: 2,\n BSC_TESTNET: 4,\n POLYGON_MUMBAI: 5,\n AVALANCHE_FUJI: 6,\n FANTOM_TESTNET: 10,\n CELO_ALFAJORES: 14,\n MOONBASE_ALPHA: 16,\n SUI_TESTNET: 21,\n APTOS_TESTNET: 22,\n ARBITRUM_SEPOLIA: 10003,\n BASE_SEPOLIA: 10004,\n OPTIMISM_SEPOLIA: 10005,\n POLYGON_SEPOLIA: 10007,\n HOLESKY: 10006,\n STARKNET_SEPOLIA: 50001, // Custom bridge (non-Wormhole)\n} as const;\n\n// ============================================================================\n// Testnet Chain Configurations\n// ============================================================================\n\nexport const TESTNET_CHAINS: Record<string, ChainConfig> = {\n baseSepolia: {\n name: 'Base Sepolia',\n chainId: 84532,\n wormholeChainId: 10004,\n rpcUrl: 'https://sepolia.base.org', // Public CORS-friendly RPC\n explorerUrl: 'https://sepolia.basescan.org',\n isEvm: true,\n contracts: {\n hub: '0x66D87dE68327f48A099c5B9bE97020Feab9a7c82',\n vaultFactory: '0xCFaEb5652aa2Ee60b2229dC8895B4159749C7e53',\n vaultImplementation: '0x0d13367C16c6f0B24eD275CC67C7D9f42878285c',\n wormholeCoreBridge: '0x79A1027a6A159502049F10906D333EC57E95F083',\n tokenBridge: '0x86F55A04690fd7815A3D802bD587e83eA888B239',\n },\n },\n optimismSepolia: {\n name: 'Optimism Sepolia',\n chainId: 11155420,\n wormholeChainId: 10005,\n rpcUrl: 'https://sepolia.optimism.io',\n explorerUrl: 'https://sepolia-optimism.etherscan.io',\n isEvm: true,\n contracts: {\n vaultFactory: '0xA5653d54079ABeCe780F8d9597B2bc4B09fe464A',\n vaultImplementation: '0x8099b1406485d2255ff89Ce5Ea18520802AFC150',\n wormholeCoreBridge: '0x31377888146f3253211EFEf5c676D41ECe7D58Fe',\n tokenBridge: '0x99737Ec4B815d816c49A385943baf0380e75c0Ac',\n },\n },\n arbitrumSepolia: {\n name: 'Arbitrum Sepolia',\n chainId: 421614,\n wormholeChainId: 10003,\n rpcUrl: 'https://sepolia-rollup.arbitrum.io/rpc',\n explorerUrl: 'https://sepolia.arbiscan.io',\n isEvm: true,\n contracts: {\n vaultFactory: '0xd36D3D5DB59d78f1E33813490F72DABC15C9B07c',\n vaultImplementation: '0xB10ACf39eBF17fc33F722cBD955b7aeCB0611bc4',\n wormholeCoreBridge: '0x6b9C8671cdDC8dEab9c719bB87cBd3e782bA6a35',\n tokenBridge: '0xC7A204bDBFe983FCD8d8E61D02b475D4073fF97e',\n },\n },\n seiTestnet: {\n name: 'Sei Atlantic-2',\n chainId: 1328,\n wormholeChainId: 40,\n rpcUrl: 'https://evm-rpc-testnet.sei-apis.com',\n explorerUrl: 'https://seitrace.com/?chain=atlantic-2',\n isEvm: true,\n contracts: {\n vaultFactory: '0x07F608AFf6d63b68029488b726d895c4Bb593038',\n vaultImplementation: '0xD66153fccFB6731fB6c4944FbD607ba86A76a1f6',\n wormholeCoreBridge: '0x0000000000000000000000000000000000000000', // Mock - not yet deployed\n },\n },\n solanaDevnet: {\n name: 'Solana Devnet',\n chainId: 0,\n wormholeChainId: 1,\n rpcUrl: 'https://api.devnet.solana.com',\n explorerUrl: 'https://explorer.solana.com',\n isEvm: false,\n contracts: {\n hub: 'AnyXHsqq9c2BiW4WgBcj6Aye7Ua7a7L7iSuwpfJxECJM',\n wormholeCoreBridge: '3u8hJUVTA4jH1wYAyUur7FFZVQ8H635K3tSHHF4ssjQ5',\n tokenBridge: 'DZnkkTmCiFWfYTfT41X3Rd1kDgozqzxWaHqsw6W4x2oe',\n },\n },\n aptosTestnet: {\n name: 'Aptos Testnet',\n chainId: 0,\n wormholeChainId: 22,\n rpcUrl: 'https://fullnode.testnet.aptoslabs.com/v1',\n explorerUrl: 'https://explorer.aptoslabs.com',\n isEvm: false,\n contracts: {\n hub: '0x0237e04f74b991b5b6030a793779663033f4ff4a1682a9e66c1f41fc1ec3e2a4',\n wormholeCoreBridge: '0x5bc11445584a763c1fa7ed39081f1b920954da14e04b32440cba863d03e19625',\n tokenBridge: '0x576410486a2da45eee6c949c995670112ddf2fbeedab20350d506328eefc9d4f',\n },\n },\n suiTestnet: {\n name: 'Sui Testnet',\n chainId: 0,\n wormholeChainId: 21,\n rpcUrl: 'https://fullnode.testnet.sui.io:443',\n explorerUrl: 'https://suiscan.xyz/testnet',\n isEvm: false,\n contracts: {\n hub: '0x35e99fdbbc1cde7e093da6f9e758ba2c4a077904bd64caee2fa6db5e6c4e9e37',\n wormholeCoreBridge: '0x31358d198147da50db32eda2562951d53973a0c0ad5ed738e9b17d88b213d790',\n },\n },\n starknetSepolia: {\n name: 'Starknet Sepolia',\n chainId: 0, // Native Starknet chain ID (SN_SEPOLIA = 0x534e5f5345504f4c4941)\n wormholeChainId: 50001, // Custom chain ID (50000+ reserved for non-Wormhole chains)\n rpcUrl: 'https://starknet-sepolia.g.alchemy.com/starknet/version/rpc/v0_7/tsOnfTBZDKMXcUA26OED-',\n explorerUrl: 'https://sepolia.starkscan.co',\n isEvm: false,\n contracts: {\n // Starknet spoke contract\n hub: '0x68adcc730ed6c355200d00f763825448497b9cdf7936ca121711e078c88e811',\n // Custom bridge contract (NOT Wormhole)\n wormholeCoreBridge: '0x2c458c1ae64556482b05cc2d3ee5b032ed114d68429dda2062c9849a5a725f8',\n },\n // Hub chain ID that Starknet bridge validates (Base Sepolia = 10004)\n hubChainId: 10004,\n },\n};\n\n// ============================================================================\n// Mainnet Chain Configurations\n// ============================================================================\n\nexport const MAINNET_CHAINS: Record<string, ChainConfig> = {\n ethereum: {\n name: 'Ethereum',\n chainId: 1,\n wormholeChainId: 2,\n rpcUrl: 'https://eth.llamarpc.com',\n explorerUrl: 'https://etherscan.io',\n isEvm: true,\n contracts: {\n wormholeCoreBridge: '0x98f3c9e6E3fAce36bAAd05FE09d375Ef1464288B',\n tokenBridge: '0x3ee18B2214AFF97000D974cf647E7C347E8fa585',\n },\n },\n base: {\n name: 'Base',\n chainId: 8453,\n wormholeChainId: 30,\n rpcUrl: 'https://mainnet.base.org',\n explorerUrl: 'https://basescan.org',\n isEvm: true,\n contracts: {\n wormholeCoreBridge: '0xbebdb6C8ddC678FfA9f8748f85C815C556Dd8ac6',\n tokenBridge: '0x8d2de8d2f73F1F4cAB472AC9A881C9b123C79627',\n },\n },\n optimism: {\n name: 'Optimism',\n chainId: 10,\n wormholeChainId: 24,\n rpcUrl: 'https://mainnet.optimism.io',\n explorerUrl: 'https://optimistic.etherscan.io',\n isEvm: true,\n contracts: {\n wormholeCoreBridge: '0xEe91C335eab126dF5fDB3797EA9d6aD93aeC9722',\n tokenBridge: '0x1D68124e65faFC907325e3EDbF8c4d84499DAa8b',\n },\n },\n arbitrum: {\n name: 'Arbitrum',\n chainId: 42161,\n wormholeChainId: 23,\n rpcUrl: 'https://arb1.arbitrum.io/rpc',\n explorerUrl: 'https://arbiscan.io',\n isEvm: true,\n contracts: {\n wormholeCoreBridge: '0xa5f208e072434bC67592E4C49C1B991BA79BCA46',\n tokenBridge: '0x0b2402144Bb366A632D14B83F244D2e0e21bD39c',\n },\n },\n polygon: {\n name: 'Polygon',\n chainId: 137,\n wormholeChainId: 5,\n rpcUrl: 'https://polygon-rpc.com',\n explorerUrl: 'https://polygonscan.com',\n isEvm: true,\n contracts: {\n wormholeCoreBridge: '0x7A4B5a56256163F07b2C80A7cA55aBE66c4ec4d7',\n tokenBridge: '0x5a58505a96D1dbf8dF91cB21B54419FC36e93fdE',\n },\n },\n solana: {\n name: 'Solana',\n chainId: 0,\n wormholeChainId: 1,\n rpcUrl: 'https://api.mainnet-beta.solana.com',\n explorerUrl: 'https://explorer.solana.com',\n isEvm: false,\n contracts: {\n wormholeCoreBridge: 'worm2ZoG2kUd4vFXhvjh93UUH596ayRfgQ2MgjNMTth',\n tokenBridge: 'wormDTUJ6AWPNvk59vGQbDvGJmqbDTdgWgAqcLBCgUb',\n },\n },\n aptos: {\n name: 'Aptos',\n chainId: 0,\n wormholeChainId: 22,\n rpcUrl: 'https://fullnode.mainnet.aptoslabs.com/v1',\n explorerUrl: 'https://explorer.aptoslabs.com',\n isEvm: false,\n contracts: {\n wormholeCoreBridge: '0x5bc11445584a763c1fa7ed39081f1b920954da14e04b32440cba863d03e19625',\n tokenBridge: '0x576410486a2da45eee6c949c995670112ddf2fbeedab20350d506328eefc9d4f',\n },\n },\n sui: {\n name: 'Sui',\n chainId: 0,\n wormholeChainId: 21,\n rpcUrl: 'https://fullnode.mainnet.sui.io:443',\n explorerUrl: 'https://suiscan.xyz/mainnet',\n isEvm: false,\n contracts: {\n wormholeCoreBridge: '0xaeab97f96cf9877fee2883315d459552b2b921edc16d7ceac6eab944dd88919c',\n },\n },\n};\n\n// ============================================================================\n// Wormhole API Endpoints\n// ============================================================================\n\nexport const WORMHOLE_API = {\n MAINNET: 'https://api.wormholescan.io',\n TESTNET: 'https://api.testnet.wormholescan.io',\n GUARDIAN_RPC_MAINNET: 'https://wormhole-v2-mainnet-api.certus.one',\n GUARDIAN_RPC_TESTNET: 'https://wormhole-v2-testnet-api.certus.one',\n} as const;\n\n// ============================================================================\n// Hub Contract ABI (minimal)\n// ============================================================================\n\nexport const HUB_ABI = [\n 'function authenticateAndDispatch((bytes authenticatorData, string clientDataJSON, uint256 challengeIndex, uint256 typeIndex, uint256 r, uint256 s) auth, uint256 publicKeyX, uint256 publicKeyY, uint16 targetChain, bytes actionPayload) external payable returns (uint64 sequence)',\n 'function authenticateRawAndDispatch(uint256 r, uint256 s, bytes32 messageHash, uint256 publicKeyX, uint256 publicKeyY, uint16 targetChain, bytes actionPayload, uint256 nonce) external payable returns (uint64 sequence)',\n 'function getNonce(bytes32 userKeyHash) external view returns (uint256)',\n 'function encodeTransferAction(address token, address recipient, uint256 amount) external pure returns (bytes)',\n 'function encodeExecuteAction(address target, uint256 value, bytes data) external pure returns (bytes)',\n 'function encodeBridgeAction(bytes32 token, uint256 amount, uint16 targetChain, bytes32 recipient) external pure returns (bytes)',\n 'function messageFee() external view returns (uint256)',\n 'event Dispatched(bytes32 indexed userKeyHash, uint16 targetChain, uint256 nonce, uint64 sequence, bytes actionPayload)',\n] as const;\n\n// ============================================================================\n// Vault Factory ABI (minimal)\n// ============================================================================\n\nexport const VAULT_FACTORY_ABI = [\n 'function createVault(bytes32 userKeyHash) external returns (address)',\n 'function getVault(bytes32 userKeyHash) external view returns (address)',\n 'function vaultExists(bytes32 userKeyHash) external view returns (bool)',\n 'event VaultCreated(bytes32 indexed userKeyHash, address vault)',\n] as const;\n\n// ============================================================================\n// Vault ABI (minimal)\n// ============================================================================\n\nexport const VAULT_ABI = [\n 'function execute(address target, uint256 value, bytes data) external returns (bytes)',\n 'function executeFromHub(bytes32 vaaHash, uint16 emitterChain, bytes32 emitterAddress, bytes payload) external',\n 'function owner() external view returns (bytes32)',\n 'function hub() external view returns (address)',\n 'receive() external payable',\n] as const;\n"],"mappings":"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","names":[]}
1
+ {"version":3,"sources":["../src/constants.ts"],"sourcesContent":["/**\n * Veridex Protocol SDK - Constants and Chain Configurations\n */\n\nimport type { ChainConfig } from './types.js';\n\n// ============================================================================\n// Action Type Constants\n// ============================================================================\n\nexport const ACTION_TYPES = {\n TRANSFER: 1,\n EXECUTE: 2,\n CONFIG: 3,\n BRIDGE: 4,\n} as const;\n\nexport const ACTION_TRANSFER = 1;\nexport const ACTION_EXECUTE = 2;\nexport const ACTION_CONFIG = 3;\nexport const ACTION_BRIDGE = 4;\n\n// Protocol version\nexport const PROTOCOL_VERSION = 1;\n\n// ============================================================================\n// Wormhole Chain IDs\n// ============================================================================\n\n/**\n * Wormhole Chain IDs organized by network\n * @see https://docs.wormhole.com/wormhole/reference/constants\n */\nexport const WORMHOLE_CHAIN_IDS = {\n MAINNET: {\n SOLANA: 1,\n ETHEREUM: 2,\n TERRA: 3,\n BSC: 4,\n POLYGON: 5,\n AVALANCHE: 6,\n OASIS: 7,\n ALGORAND: 8,\n AURORA: 9,\n FANTOM: 10,\n KARURA: 11,\n ACALA: 12,\n KLAYTN: 13,\n CELO: 14,\n NEAR: 15,\n MOONBEAM: 16,\n NEON: 17,\n TERRA2: 18,\n INJECTIVE: 19,\n OSMOSIS: 20,\n SUI: 21,\n APTOS: 22,\n ARBITRUM: 23,\n OPTIMISM: 24,\n GNOSIS: 25,\n PYTHNET: 26,\n XPLA: 28,\n BASE: 30,\n SEI: 32,\n ROOTSTOCK: 33,\n SCROLL: 34,\n MANTLE: 35,\n BLAST: 36,\n XLAYER: 37,\n LINEA: 38,\n BERACHAIN: 39,\n SEIEVM: 40,\n },\n TESTNET: {\n SOLANA_DEVNET: 1,\n GOERLI: 2,\n BSC_TESTNET: 4,\n POLYGON_MUMBAI: 5,\n AVALANCHE_FUJI: 6,\n FANTOM_TESTNET: 10,\n CELO_ALFAJORES: 14,\n MOONBASE_ALPHA: 16,\n SUI_TESTNET: 21,\n APTOS_TESTNET: 22,\n SEPOLIA: 10002,\n ARBITRUM_SEPOLIA: 10003,\n BASE_SEPOLIA: 10004,\n OPTIMISM_SEPOLIA: 10005,\n HOLESKY: 10006,\n POLYGON_SEPOLIA: 10007,\n SEI_ATLANTIC_2: 10066, // Sei Arctic-1 testnet (EVM)\n STARKNET_SEPOLIA: 50001, // Custom bridge (non-Wormhole, relayer-attested)\n },\n} as const;\n\n// Legacy flat exports for backward compatibility\nexport const WORMHOLE_CHAIN_IDS_FLAT = {\n // Mainnets\n SOLANA: 1,\n ETHEREUM: 2,\n TERRA: 3,\n BSC: 4,\n POLYGON: 5,\n AVALANCHE: 6,\n OASIS: 7,\n ALGORAND: 8,\n AURORA: 9,\n FANTOM: 10,\n KARURA: 11,\n ACALA: 12,\n KLAYTN: 13,\n CELO: 14,\n NEAR: 15,\n MOONBEAM: 16,\n NEON: 17,\n TERRA2: 18,\n INJECTIVE: 19,\n OSMOSIS: 20,\n SUI: 21,\n APTOS: 22,\n ARBITRUM: 23,\n OPTIMISM: 24,\n GNOSIS: 25,\n PYTHNET: 26,\n XPLA: 28,\n BASE: 30,\n SEI: 32,\n ROOTSTOCK: 33,\n SCROLL: 34,\n MANTLE: 35,\n BLAST: 36,\n XLAYER: 37,\n LINEA: 38,\n BERACHAIN: 39,\n SEIEVM: 40,\n\n // Testnets\n SOLANA_DEVNET: 1,\n GOERLI: 2,\n BSC_TESTNET: 4,\n POLYGON_MUMBAI: 5,\n AVALANCHE_FUJI: 6,\n FANTOM_TESTNET: 10,\n CELO_ALFAJORES: 14,\n MOONBASE_ALPHA: 16,\n SUI_TESTNET: 21,\n APTOS_TESTNET: 22,\n ARBITRUM_SEPOLIA: 10003,\n BASE_SEPOLIA: 10004,\n OPTIMISM_SEPOLIA: 10005,\n POLYGON_SEPOLIA: 10007,\n HOLESKY: 10006,\n STARKNET_SEPOLIA: 50001, // Custom bridge (non-Wormhole)\n} as const;\n\n// ============================================================================\n// Testnet Chain Configurations\n// ============================================================================\n\nexport const TESTNET_CHAINS: Record<string, ChainConfig> = {\n baseSepolia: {\n name: 'Base Sepolia',\n chainId: 84532,\n wormholeChainId: 10004,\n rpcUrl: 'https://sepolia.base.org', // Public CORS-friendly RPC\n explorerUrl: 'https://sepolia.basescan.org',\n isEvm: true,\n contracts: {\n hub: '0x66D87dE68327f48A099c5B9bE97020Feab9a7c82',\n vaultFactory: '0xCFaEb5652aa2Ee60b2229dC8895B4159749C7e53',\n vaultImplementation: '0x0d13367C16c6f0B24eD275CC67C7D9f42878285c',\n wormholeCoreBridge: '0x79A1027a6A159502049F10906D333EC57E95F083',\n tokenBridge: '0x86F55A04690fd7815A3D802bD587e83eA888B239',\n },\n },\n optimismSepolia: {\n name: 'Optimism Sepolia',\n chainId: 11155420,\n wormholeChainId: 10005,\n rpcUrl: 'https://sepolia.optimism.io',\n explorerUrl: 'https://sepolia-optimism.etherscan.io',\n isEvm: true,\n contracts: {\n vaultFactory: '0xA5653d54079ABeCe780F8d9597B2bc4B09fe464A',\n vaultImplementation: '0x8099b1406485d2255ff89Ce5Ea18520802AFC150',\n wormholeCoreBridge: '0x31377888146f3253211EFEf5c676D41ECe7D58Fe',\n tokenBridge: '0x99737Ec4B815d816c49A385943baf0380e75c0Ac',\n },\n },\n arbitrumSepolia: {\n name: 'Arbitrum Sepolia',\n chainId: 421614,\n wormholeChainId: 10003,\n rpcUrl: 'https://sepolia-rollup.arbitrum.io/rpc',\n explorerUrl: 'https://sepolia.arbiscan.io',\n isEvm: true,\n contracts: {\n vaultFactory: '0xd36D3D5DB59d78f1E33813490F72DABC15C9B07c',\n vaultImplementation: '0xB10ACf39eBF17fc33F722cBD955b7aeCB0611bc4',\n wormholeCoreBridge: '0x6b9C8671cdDC8dEab9c719bB87cBd3e782bA6a35',\n tokenBridge: '0xC7A204bDBFe983FCD8d8E61D02b475D4073fF97e',\n },\n },\n seiTestnet: {\n name: 'Sei Atlantic-2',\n chainId: 1328,\n wormholeChainId: 40,\n rpcUrl: 'https://evm-rpc-testnet.sei-apis.com',\n explorerUrl: 'https://seitrace.com/?chain=atlantic-2',\n isEvm: true,\n contracts: {\n vaultFactory: '0x07F608AFf6d63b68029488b726d895c4Bb593038',\n vaultImplementation: '0xD66153fccFB6731fB6c4944FbD607ba86A76a1f6',\n wormholeCoreBridge: '0x0000000000000000000000000000000000000000', // Mock - not yet deployed\n },\n },\n solanaDevnet: {\n name: 'Solana Devnet',\n chainId: 0,\n wormholeChainId: 1,\n rpcUrl: 'https://api.devnet.solana.com',\n explorerUrl: 'https://explorer.solana.com',\n isEvm: false,\n contracts: {\n hub: 'AnyXHsqq9c2BiW4WgBcj6Aye7Ua7a7L7iSuwpfJxECJM',\n wormholeCoreBridge: '3u8hJUVTA4jH1wYAyUur7FFZVQ8H635K3tSHHF4ssjQ5',\n tokenBridge: 'DZnkkTmCiFWfYTfT41X3Rd1kDgozqzxWaHqsw6W4x2oe',\n },\n },\n aptosTestnet: {\n name: 'Aptos Testnet',\n chainId: 0,\n wormholeChainId: 22,\n rpcUrl: 'https://fullnode.testnet.aptoslabs.com/v1',\n explorerUrl: 'https://explorer.aptoslabs.com',\n isEvm: false,\n contracts: {\n hub: '0x0237e04f74b991b5b6030a793779663033f4ff4a1682a9e66c1f41fc1ec3e2a4',\n wormholeCoreBridge: '0x5bc11445584a763c1fa7ed39081f1b920954da14e04b32440cba863d03e19625',\n tokenBridge: '0x576410486a2da45eee6c949c995670112ddf2fbeedab20350d506328eefc9d4f',\n },\n },\n suiTestnet: {\n name: 'Sui Testnet',\n chainId: 0,\n wormholeChainId: 21,\n rpcUrl: 'https://fullnode.testnet.sui.io:443',\n explorerUrl: 'https://suiscan.xyz/testnet',\n isEvm: false,\n contracts: {\n hub: '0x35e99fdbbc1cde7e093da6f9e758ba2c4a077904bd64caee2fa6db5e6c4e9e37',\n wormholeCoreBridge: '0x31358d198147da50db32eda2562951d53973a0c0ad5ed738e9b17d88b213d790',\n },\n },\n starknetSepolia: {\n name: 'Starknet Sepolia',\n chainId: 0, // Native Starknet chain ID (SN_SEPOLIA = 0x534e5f5345504f4c4941)\n wormholeChainId: 50001, // Custom chain ID (50000+ reserved for non-Wormhole chains)\n rpcUrl: 'https://starknet-sepolia.g.alchemy.com/starknet/version/rpc/v0_7/tsOnfTBZDKMXcUA26OED-',\n explorerUrl: 'https://sepolia.starkscan.co',\n isEvm: false,\n contracts: {\n // Starknet spoke contract\n hub: '0x68adcc730ed6c355200d00f763825448497b9cdf7936ca121711e078c88e811',\n // Custom bridge contract (NOT Wormhole)\n wormholeCoreBridge: '0x2c458c1ae64556482b05cc2d3ee5b032ed114d68429dda2062c9849a5a725f8',\n },\n // Hub chain ID that Starknet bridge validates (Base Sepolia = 10004)\n hubChainId: 10004,\n },\n};\n\n// ============================================================================\n// Mainnet Chain Configurations\n// ============================================================================\n\nexport const MAINNET_CHAINS: Record<string, ChainConfig> = {\n ethereum: {\n name: 'Ethereum',\n chainId: 1,\n wormholeChainId: 2,\n rpcUrl: 'https://eth.llamarpc.com',\n explorerUrl: 'https://etherscan.io',\n isEvm: true,\n contracts: {\n wormholeCoreBridge: '0x98f3c9e6E3fAce36bAAd05FE09d375Ef1464288B',\n tokenBridge: '0x3ee18B2214AFF97000D974cf647E7C347E8fa585',\n },\n },\n base: {\n name: 'Base',\n chainId: 8453,\n wormholeChainId: 30,\n rpcUrl: 'https://mainnet.base.org',\n explorerUrl: 'https://basescan.org',\n isEvm: true,\n contracts: {\n wormholeCoreBridge: '0xbebdb6C8ddC678FfA9f8748f85C815C556Dd8ac6',\n tokenBridge: '0x8d2de8d2f73F1F4cAB472AC9A881C9b123C79627',\n },\n },\n optimism: {\n name: 'Optimism',\n chainId: 10,\n wormholeChainId: 24,\n rpcUrl: 'https://mainnet.optimism.io',\n explorerUrl: 'https://optimistic.etherscan.io',\n isEvm: true,\n contracts: {\n wormholeCoreBridge: '0xEe91C335eab126dF5fDB3797EA9d6aD93aeC9722',\n tokenBridge: '0x1D68124e65faFC907325e3EDbF8c4d84499DAa8b',\n },\n },\n arbitrum: {\n name: 'Arbitrum',\n chainId: 42161,\n wormholeChainId: 23,\n rpcUrl: 'https://arb1.arbitrum.io/rpc',\n explorerUrl: 'https://arbiscan.io',\n isEvm: true,\n contracts: {\n wormholeCoreBridge: '0xa5f208e072434bC67592E4C49C1B991BA79BCA46',\n tokenBridge: '0x0b2402144Bb366A632D14B83F244D2e0e21bD39c',\n },\n },\n polygon: {\n name: 'Polygon',\n chainId: 137,\n wormholeChainId: 5,\n rpcUrl: 'https://polygon-rpc.com',\n explorerUrl: 'https://polygonscan.com',\n isEvm: true,\n contracts: {\n wormholeCoreBridge: '0x7A4B5a56256163F07b2C80A7cA55aBE66c4ec4d7',\n tokenBridge: '0x5a58505a96D1dbf8dF91cB21B54419FC36e93fdE',\n },\n },\n solana: {\n name: 'Solana',\n chainId: 0,\n wormholeChainId: 1,\n rpcUrl: 'https://api.mainnet-beta.solana.com',\n explorerUrl: 'https://explorer.solana.com',\n isEvm: false,\n contracts: {\n wormholeCoreBridge: 'worm2ZoG2kUd4vFXhvjh93UUH596ayRfgQ2MgjNMTth',\n tokenBridge: 'wormDTUJ6AWPNvk59vGQbDvGJmqbDTdgWgAqcLBCgUb',\n },\n },\n aptos: {\n name: 'Aptos',\n chainId: 0,\n wormholeChainId: 22,\n rpcUrl: 'https://fullnode.mainnet.aptoslabs.com/v1',\n explorerUrl: 'https://explorer.aptoslabs.com',\n isEvm: false,\n contracts: {\n wormholeCoreBridge: '0x5bc11445584a763c1fa7ed39081f1b920954da14e04b32440cba863d03e19625',\n tokenBridge: '0x576410486a2da45eee6c949c995670112ddf2fbeedab20350d506328eefc9d4f',\n },\n },\n sui: {\n name: 'Sui',\n chainId: 0,\n wormholeChainId: 21,\n rpcUrl: 'https://fullnode.mainnet.sui.io:443',\n explorerUrl: 'https://suiscan.xyz/mainnet',\n isEvm: false,\n contracts: {\n wormholeCoreBridge: '0xaeab97f96cf9877fee2883315d459552b2b921edc16d7ceac6eab944dd88919c',\n },\n },\n};\n\n// ============================================================================\n// Wormhole API Endpoints\n// ============================================================================\n\nexport const WORMHOLE_API = {\n MAINNET: 'https://api.wormholescan.io',\n TESTNET: 'https://api.testnet.wormholescan.io',\n GUARDIAN_RPC_MAINNET: 'https://wormhole-v2-mainnet-api.certus.one',\n GUARDIAN_RPC_TESTNET: 'https://wormhole-v2-testnet-api.certus.one',\n} as const;\n\n// ============================================================================\n// Hub Contract ABI (minimal)\n// ============================================================================\n\nexport const HUB_ABI = [\n 'function authenticateAndDispatch((bytes authenticatorData, string clientDataJSON, uint256 challengeIndex, uint256 typeIndex, uint256 r, uint256 s) auth, uint256 publicKeyX, uint256 publicKeyY, uint16 targetChain, bytes actionPayload) external payable returns (uint64 sequence)',\n 'function authenticateRawAndDispatch(uint256 r, uint256 s, bytes32 messageHash, uint256 publicKeyX, uint256 publicKeyY, uint16 targetChain, bytes actionPayload, uint256 nonce) external payable returns (uint64 sequence)',\n 'function userNonces(bytes32 userKeyHash) external view returns (uint256)',\n 'function encodeTransferAction(address token, address recipient, uint256 amount) external pure returns (bytes)',\n 'function encodeExecuteAction(address target, uint256 value, bytes data) external pure returns (bytes)',\n 'function encodeBridgeAction(bytes32 token, uint256 amount, uint16 targetChain, bytes32 recipient) external pure returns (bytes)',\n 'function messageFee() external view returns (uint256)',\n 'event Dispatched(bytes32 indexed userKeyHash, uint16 targetChain, uint256 nonce, uint64 sequence, bytes actionPayload)',\n] as const;\n\n// ============================================================================\n// Vault Factory ABI (minimal)\n// ============================================================================\n\nexport const VAULT_FACTORY_ABI = [\n 'function createVault(bytes32 userKeyHash) external returns (address)',\n 'function getVault(bytes32 userKeyHash) external view returns (address)',\n 'function vaultExists(bytes32 userKeyHash) external view returns (bool)',\n 'event VaultCreated(bytes32 indexed userKeyHash, address vault)',\n] as const;\n\n// ============================================================================\n// Vault ABI (minimal)\n// ============================================================================\n\nexport const VAULT_ABI = [\n 'function execute(address target, uint256 value, bytes data) external returns (bytes)',\n 'function executeFromHub(bytes32 vaaHash, uint16 emitterChain, bytes32 emitterAddress, bytes payload) external',\n 'function owner() external view returns (bytes32)',\n 'function hub() external view returns (address)',\n 'receive() external payable',\n] as const;\n"],"mappings":"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","names":[]}
@@ -353,7 +353,7 @@ var WORMHOLE_API = {
353
353
  var HUB_ABI = [
354
354
  "function authenticateAndDispatch((bytes authenticatorData, string clientDataJSON, uint256 challengeIndex, uint256 typeIndex, uint256 r, uint256 s) auth, uint256 publicKeyX, uint256 publicKeyY, uint16 targetChain, bytes actionPayload) external payable returns (uint64 sequence)",
355
355
  "function authenticateRawAndDispatch(uint256 r, uint256 s, bytes32 messageHash, uint256 publicKeyX, uint256 publicKeyY, uint16 targetChain, bytes actionPayload, uint256 nonce) external payable returns (uint64 sequence)",
356
- "function getNonce(bytes32 userKeyHash) external view returns (uint256)",
356
+ "function userNonces(bytes32 userKeyHash) external view returns (uint256)",
357
357
  "function encodeTransferAction(address token, address recipient, uint256 amount) external pure returns (bytes)",
358
358
  "function encodeExecuteAction(address target, uint256 value, bytes data) external pure returns (bytes)",
359
359
  "function encodeBridgeAction(bytes32 token, uint256 amount, uint16 targetChain, bytes32 recipient) external pure returns (bytes)",
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/constants.ts"],"sourcesContent":["/**\n * Veridex Protocol SDK - Constants and Chain Configurations\n */\n\nimport type { ChainConfig } from './types.js';\n\n// ============================================================================\n// Action Type Constants\n// ============================================================================\n\nexport const ACTION_TYPES = {\n TRANSFER: 1,\n EXECUTE: 2,\n CONFIG: 3,\n BRIDGE: 4,\n} as const;\n\nexport const ACTION_TRANSFER = 1;\nexport const ACTION_EXECUTE = 2;\nexport const ACTION_CONFIG = 3;\nexport const ACTION_BRIDGE = 4;\n\n// Protocol version\nexport const PROTOCOL_VERSION = 1;\n\n// ============================================================================\n// Wormhole Chain IDs\n// ============================================================================\n\n/**\n * Wormhole Chain IDs organized by network\n * @see https://docs.wormhole.com/wormhole/reference/constants\n */\nexport const WORMHOLE_CHAIN_IDS = {\n MAINNET: {\n SOLANA: 1,\n ETHEREUM: 2,\n TERRA: 3,\n BSC: 4,\n POLYGON: 5,\n AVALANCHE: 6,\n OASIS: 7,\n ALGORAND: 8,\n AURORA: 9,\n FANTOM: 10,\n KARURA: 11,\n ACALA: 12,\n KLAYTN: 13,\n CELO: 14,\n NEAR: 15,\n MOONBEAM: 16,\n NEON: 17,\n TERRA2: 18,\n INJECTIVE: 19,\n OSMOSIS: 20,\n SUI: 21,\n APTOS: 22,\n ARBITRUM: 23,\n OPTIMISM: 24,\n GNOSIS: 25,\n PYTHNET: 26,\n XPLA: 28,\n BASE: 30,\n SEI: 32,\n ROOTSTOCK: 33,\n SCROLL: 34,\n MANTLE: 35,\n BLAST: 36,\n XLAYER: 37,\n LINEA: 38,\n BERACHAIN: 39,\n SEIEVM: 40,\n },\n TESTNET: {\n SOLANA_DEVNET: 1,\n GOERLI: 2,\n BSC_TESTNET: 4,\n POLYGON_MUMBAI: 5,\n AVALANCHE_FUJI: 6,\n FANTOM_TESTNET: 10,\n CELO_ALFAJORES: 14,\n MOONBASE_ALPHA: 16,\n SUI_TESTNET: 21,\n APTOS_TESTNET: 22,\n SEPOLIA: 10002,\n ARBITRUM_SEPOLIA: 10003,\n BASE_SEPOLIA: 10004,\n OPTIMISM_SEPOLIA: 10005,\n HOLESKY: 10006,\n POLYGON_SEPOLIA: 10007,\n SEI_ATLANTIC_2: 10066, // Sei Arctic-1 testnet (EVM)\n STARKNET_SEPOLIA: 50001, // Custom bridge (non-Wormhole, relayer-attested)\n },\n} as const;\n\n// Legacy flat exports for backward compatibility\nexport const WORMHOLE_CHAIN_IDS_FLAT = {\n // Mainnets\n SOLANA: 1,\n ETHEREUM: 2,\n TERRA: 3,\n BSC: 4,\n POLYGON: 5,\n AVALANCHE: 6,\n OASIS: 7,\n ALGORAND: 8,\n AURORA: 9,\n FANTOM: 10,\n KARURA: 11,\n ACALA: 12,\n KLAYTN: 13,\n CELO: 14,\n NEAR: 15,\n MOONBEAM: 16,\n NEON: 17,\n TERRA2: 18,\n INJECTIVE: 19,\n OSMOSIS: 20,\n SUI: 21,\n APTOS: 22,\n ARBITRUM: 23,\n OPTIMISM: 24,\n GNOSIS: 25,\n PYTHNET: 26,\n XPLA: 28,\n BASE: 30,\n SEI: 32,\n ROOTSTOCK: 33,\n SCROLL: 34,\n MANTLE: 35,\n BLAST: 36,\n XLAYER: 37,\n LINEA: 38,\n BERACHAIN: 39,\n SEIEVM: 40,\n\n // Testnets\n SOLANA_DEVNET: 1,\n GOERLI: 2,\n BSC_TESTNET: 4,\n POLYGON_MUMBAI: 5,\n AVALANCHE_FUJI: 6,\n FANTOM_TESTNET: 10,\n CELO_ALFAJORES: 14,\n MOONBASE_ALPHA: 16,\n SUI_TESTNET: 21,\n APTOS_TESTNET: 22,\n ARBITRUM_SEPOLIA: 10003,\n BASE_SEPOLIA: 10004,\n OPTIMISM_SEPOLIA: 10005,\n POLYGON_SEPOLIA: 10007,\n HOLESKY: 10006,\n STARKNET_SEPOLIA: 50001, // Custom bridge (non-Wormhole)\n} as const;\n\n// ============================================================================\n// Testnet Chain Configurations\n// ============================================================================\n\nexport const TESTNET_CHAINS: Record<string, ChainConfig> = {\n baseSepolia: {\n name: 'Base Sepolia',\n chainId: 84532,\n wormholeChainId: 10004,\n rpcUrl: 'https://sepolia.base.org', // Public CORS-friendly RPC\n explorerUrl: 'https://sepolia.basescan.org',\n isEvm: true,\n contracts: {\n hub: '0x66D87dE68327f48A099c5B9bE97020Feab9a7c82',\n vaultFactory: '0xCFaEb5652aa2Ee60b2229dC8895B4159749C7e53',\n vaultImplementation: '0x0d13367C16c6f0B24eD275CC67C7D9f42878285c',\n wormholeCoreBridge: '0x79A1027a6A159502049F10906D333EC57E95F083',\n tokenBridge: '0x86F55A04690fd7815A3D802bD587e83eA888B239',\n },\n },\n optimismSepolia: {\n name: 'Optimism Sepolia',\n chainId: 11155420,\n wormholeChainId: 10005,\n rpcUrl: 'https://sepolia.optimism.io',\n explorerUrl: 'https://sepolia-optimism.etherscan.io',\n isEvm: true,\n contracts: {\n vaultFactory: '0xA5653d54079ABeCe780F8d9597B2bc4B09fe464A',\n vaultImplementation: '0x8099b1406485d2255ff89Ce5Ea18520802AFC150',\n wormholeCoreBridge: '0x31377888146f3253211EFEf5c676D41ECe7D58Fe',\n tokenBridge: '0x99737Ec4B815d816c49A385943baf0380e75c0Ac',\n },\n },\n arbitrumSepolia: {\n name: 'Arbitrum Sepolia',\n chainId: 421614,\n wormholeChainId: 10003,\n rpcUrl: 'https://sepolia-rollup.arbitrum.io/rpc',\n explorerUrl: 'https://sepolia.arbiscan.io',\n isEvm: true,\n contracts: {\n vaultFactory: '0xd36D3D5DB59d78f1E33813490F72DABC15C9B07c',\n vaultImplementation: '0xB10ACf39eBF17fc33F722cBD955b7aeCB0611bc4',\n wormholeCoreBridge: '0x6b9C8671cdDC8dEab9c719bB87cBd3e782bA6a35',\n tokenBridge: '0xC7A204bDBFe983FCD8d8E61D02b475D4073fF97e',\n },\n },\n seiTestnet: {\n name: 'Sei Atlantic-2',\n chainId: 1328,\n wormholeChainId: 40,\n rpcUrl: 'https://evm-rpc-testnet.sei-apis.com',\n explorerUrl: 'https://seitrace.com/?chain=atlantic-2',\n isEvm: true,\n contracts: {\n vaultFactory: '0x07F608AFf6d63b68029488b726d895c4Bb593038',\n vaultImplementation: '0xD66153fccFB6731fB6c4944FbD607ba86A76a1f6',\n wormholeCoreBridge: '0x0000000000000000000000000000000000000000', // Mock - not yet deployed\n },\n },\n solanaDevnet: {\n name: 'Solana Devnet',\n chainId: 0,\n wormholeChainId: 1,\n rpcUrl: 'https://api.devnet.solana.com',\n explorerUrl: 'https://explorer.solana.com',\n isEvm: false,\n contracts: {\n hub: 'AnyXHsqq9c2BiW4WgBcj6Aye7Ua7a7L7iSuwpfJxECJM',\n wormholeCoreBridge: '3u8hJUVTA4jH1wYAyUur7FFZVQ8H635K3tSHHF4ssjQ5',\n tokenBridge: 'DZnkkTmCiFWfYTfT41X3Rd1kDgozqzxWaHqsw6W4x2oe',\n },\n },\n aptosTestnet: {\n name: 'Aptos Testnet',\n chainId: 0,\n wormholeChainId: 22,\n rpcUrl: 'https://fullnode.testnet.aptoslabs.com/v1',\n explorerUrl: 'https://explorer.aptoslabs.com',\n isEvm: false,\n contracts: {\n hub: '0x0237e04f74b991b5b6030a793779663033f4ff4a1682a9e66c1f41fc1ec3e2a4',\n wormholeCoreBridge: '0x5bc11445584a763c1fa7ed39081f1b920954da14e04b32440cba863d03e19625',\n tokenBridge: '0x576410486a2da45eee6c949c995670112ddf2fbeedab20350d506328eefc9d4f',\n },\n },\n suiTestnet: {\n name: 'Sui Testnet',\n chainId: 0,\n wormholeChainId: 21,\n rpcUrl: 'https://fullnode.testnet.sui.io:443',\n explorerUrl: 'https://suiscan.xyz/testnet',\n isEvm: false,\n contracts: {\n hub: '0x35e99fdbbc1cde7e093da6f9e758ba2c4a077904bd64caee2fa6db5e6c4e9e37',\n wormholeCoreBridge: '0x31358d198147da50db32eda2562951d53973a0c0ad5ed738e9b17d88b213d790',\n },\n },\n starknetSepolia: {\n name: 'Starknet Sepolia',\n chainId: 0, // Native Starknet chain ID (SN_SEPOLIA = 0x534e5f5345504f4c4941)\n wormholeChainId: 50001, // Custom chain ID (50000+ reserved for non-Wormhole chains)\n rpcUrl: 'https://starknet-sepolia.g.alchemy.com/starknet/version/rpc/v0_7/tsOnfTBZDKMXcUA26OED-',\n explorerUrl: 'https://sepolia.starkscan.co',\n isEvm: false,\n contracts: {\n // Starknet spoke contract\n hub: '0x68adcc730ed6c355200d00f763825448497b9cdf7936ca121711e078c88e811',\n // Custom bridge contract (NOT Wormhole)\n wormholeCoreBridge: '0x2c458c1ae64556482b05cc2d3ee5b032ed114d68429dda2062c9849a5a725f8',\n },\n // Hub chain ID that Starknet bridge validates (Base Sepolia = 10004)\n hubChainId: 10004,\n },\n};\n\n// ============================================================================\n// Mainnet Chain Configurations\n// ============================================================================\n\nexport const MAINNET_CHAINS: Record<string, ChainConfig> = {\n ethereum: {\n name: 'Ethereum',\n chainId: 1,\n wormholeChainId: 2,\n rpcUrl: 'https://eth.llamarpc.com',\n explorerUrl: 'https://etherscan.io',\n isEvm: true,\n contracts: {\n wormholeCoreBridge: '0x98f3c9e6E3fAce36bAAd05FE09d375Ef1464288B',\n tokenBridge: '0x3ee18B2214AFF97000D974cf647E7C347E8fa585',\n },\n },\n base: {\n name: 'Base',\n chainId: 8453,\n wormholeChainId: 30,\n rpcUrl: 'https://mainnet.base.org',\n explorerUrl: 'https://basescan.org',\n isEvm: true,\n contracts: {\n wormholeCoreBridge: '0xbebdb6C8ddC678FfA9f8748f85C815C556Dd8ac6',\n tokenBridge: '0x8d2de8d2f73F1F4cAB472AC9A881C9b123C79627',\n },\n },\n optimism: {\n name: 'Optimism',\n chainId: 10,\n wormholeChainId: 24,\n rpcUrl: 'https://mainnet.optimism.io',\n explorerUrl: 'https://optimistic.etherscan.io',\n isEvm: true,\n contracts: {\n wormholeCoreBridge: '0xEe91C335eab126dF5fDB3797EA9d6aD93aeC9722',\n tokenBridge: '0x1D68124e65faFC907325e3EDbF8c4d84499DAa8b',\n },\n },\n arbitrum: {\n name: 'Arbitrum',\n chainId: 42161,\n wormholeChainId: 23,\n rpcUrl: 'https://arb1.arbitrum.io/rpc',\n explorerUrl: 'https://arbiscan.io',\n isEvm: true,\n contracts: {\n wormholeCoreBridge: '0xa5f208e072434bC67592E4C49C1B991BA79BCA46',\n tokenBridge: '0x0b2402144Bb366A632D14B83F244D2e0e21bD39c',\n },\n },\n polygon: {\n name: 'Polygon',\n chainId: 137,\n wormholeChainId: 5,\n rpcUrl: 'https://polygon-rpc.com',\n explorerUrl: 'https://polygonscan.com',\n isEvm: true,\n contracts: {\n wormholeCoreBridge: '0x7A4B5a56256163F07b2C80A7cA55aBE66c4ec4d7',\n tokenBridge: '0x5a58505a96D1dbf8dF91cB21B54419FC36e93fdE',\n },\n },\n solana: {\n name: 'Solana',\n chainId: 0,\n wormholeChainId: 1,\n rpcUrl: 'https://api.mainnet-beta.solana.com',\n explorerUrl: 'https://explorer.solana.com',\n isEvm: false,\n contracts: {\n wormholeCoreBridge: 'worm2ZoG2kUd4vFXhvjh93UUH596ayRfgQ2MgjNMTth',\n tokenBridge: 'wormDTUJ6AWPNvk59vGQbDvGJmqbDTdgWgAqcLBCgUb',\n },\n },\n aptos: {\n name: 'Aptos',\n chainId: 0,\n wormholeChainId: 22,\n rpcUrl: 'https://fullnode.mainnet.aptoslabs.com/v1',\n explorerUrl: 'https://explorer.aptoslabs.com',\n isEvm: false,\n contracts: {\n wormholeCoreBridge: '0x5bc11445584a763c1fa7ed39081f1b920954da14e04b32440cba863d03e19625',\n tokenBridge: '0x576410486a2da45eee6c949c995670112ddf2fbeedab20350d506328eefc9d4f',\n },\n },\n sui: {\n name: 'Sui',\n chainId: 0,\n wormholeChainId: 21,\n rpcUrl: 'https://fullnode.mainnet.sui.io:443',\n explorerUrl: 'https://suiscan.xyz/mainnet',\n isEvm: false,\n contracts: {\n wormholeCoreBridge: '0xaeab97f96cf9877fee2883315d459552b2b921edc16d7ceac6eab944dd88919c',\n },\n },\n};\n\n// ============================================================================\n// Wormhole API Endpoints\n// ============================================================================\n\nexport const WORMHOLE_API = {\n MAINNET: 'https://api.wormholescan.io',\n TESTNET: 'https://api.testnet.wormholescan.io',\n GUARDIAN_RPC_MAINNET: 'https://wormhole-v2-mainnet-api.certus.one',\n GUARDIAN_RPC_TESTNET: 'https://wormhole-v2-testnet-api.certus.one',\n} as const;\n\n// ============================================================================\n// Hub Contract ABI (minimal)\n// ============================================================================\n\nexport const HUB_ABI = [\n 'function authenticateAndDispatch((bytes authenticatorData, string clientDataJSON, uint256 challengeIndex, uint256 typeIndex, uint256 r, uint256 s) auth, uint256 publicKeyX, uint256 publicKeyY, uint16 targetChain, bytes actionPayload) external payable returns (uint64 sequence)',\n 'function authenticateRawAndDispatch(uint256 r, uint256 s, bytes32 messageHash, uint256 publicKeyX, uint256 publicKeyY, uint16 targetChain, bytes actionPayload, uint256 nonce) external payable returns (uint64 sequence)',\n 'function getNonce(bytes32 userKeyHash) external view returns (uint256)',\n 'function encodeTransferAction(address token, address recipient, uint256 amount) external pure returns (bytes)',\n 'function encodeExecuteAction(address target, uint256 value, bytes data) external pure returns (bytes)',\n 'function encodeBridgeAction(bytes32 token, uint256 amount, uint16 targetChain, bytes32 recipient) external pure returns (bytes)',\n 'function messageFee() external view returns (uint256)',\n 'event Dispatched(bytes32 indexed userKeyHash, uint16 targetChain, uint256 nonce, uint64 sequence, bytes actionPayload)',\n] as const;\n\n// ============================================================================\n// Vault Factory ABI (minimal)\n// ============================================================================\n\nexport const VAULT_FACTORY_ABI = [\n 'function createVault(bytes32 userKeyHash) external returns (address)',\n 'function getVault(bytes32 userKeyHash) external view returns (address)',\n 'function vaultExists(bytes32 userKeyHash) external view returns (bool)',\n 'event VaultCreated(bytes32 indexed userKeyHash, address vault)',\n] as const;\n\n// ============================================================================\n// Vault ABI (minimal)\n// ============================================================================\n\nexport const VAULT_ABI = [\n 'function execute(address target, uint256 value, bytes data) external returns (bytes)',\n 'function executeFromHub(bytes32 vaaHash, uint16 emitterChain, bytes32 emitterAddress, bytes payload) external',\n 'function owner() external view returns (bytes32)',\n 'function hub() external view returns (address)',\n 'receive() external payable',\n] as const;\n"],"mappings":"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","names":[]}
1
+ {"version":3,"sources":["../src/constants.ts"],"sourcesContent":["/**\n * Veridex Protocol SDK - Constants and Chain Configurations\n */\n\nimport type { ChainConfig } from './types.js';\n\n// ============================================================================\n// Action Type Constants\n// ============================================================================\n\nexport const ACTION_TYPES = {\n TRANSFER: 1,\n EXECUTE: 2,\n CONFIG: 3,\n BRIDGE: 4,\n} as const;\n\nexport const ACTION_TRANSFER = 1;\nexport const ACTION_EXECUTE = 2;\nexport const ACTION_CONFIG = 3;\nexport const ACTION_BRIDGE = 4;\n\n// Protocol version\nexport const PROTOCOL_VERSION = 1;\n\n// ============================================================================\n// Wormhole Chain IDs\n// ============================================================================\n\n/**\n * Wormhole Chain IDs organized by network\n * @see https://docs.wormhole.com/wormhole/reference/constants\n */\nexport const WORMHOLE_CHAIN_IDS = {\n MAINNET: {\n SOLANA: 1,\n ETHEREUM: 2,\n TERRA: 3,\n BSC: 4,\n POLYGON: 5,\n AVALANCHE: 6,\n OASIS: 7,\n ALGORAND: 8,\n AURORA: 9,\n FANTOM: 10,\n KARURA: 11,\n ACALA: 12,\n KLAYTN: 13,\n CELO: 14,\n NEAR: 15,\n MOONBEAM: 16,\n NEON: 17,\n TERRA2: 18,\n INJECTIVE: 19,\n OSMOSIS: 20,\n SUI: 21,\n APTOS: 22,\n ARBITRUM: 23,\n OPTIMISM: 24,\n GNOSIS: 25,\n PYTHNET: 26,\n XPLA: 28,\n BASE: 30,\n SEI: 32,\n ROOTSTOCK: 33,\n SCROLL: 34,\n MANTLE: 35,\n BLAST: 36,\n XLAYER: 37,\n LINEA: 38,\n BERACHAIN: 39,\n SEIEVM: 40,\n },\n TESTNET: {\n SOLANA_DEVNET: 1,\n GOERLI: 2,\n BSC_TESTNET: 4,\n POLYGON_MUMBAI: 5,\n AVALANCHE_FUJI: 6,\n FANTOM_TESTNET: 10,\n CELO_ALFAJORES: 14,\n MOONBASE_ALPHA: 16,\n SUI_TESTNET: 21,\n APTOS_TESTNET: 22,\n SEPOLIA: 10002,\n ARBITRUM_SEPOLIA: 10003,\n BASE_SEPOLIA: 10004,\n OPTIMISM_SEPOLIA: 10005,\n HOLESKY: 10006,\n POLYGON_SEPOLIA: 10007,\n SEI_ATLANTIC_2: 10066, // Sei Arctic-1 testnet (EVM)\n STARKNET_SEPOLIA: 50001, // Custom bridge (non-Wormhole, relayer-attested)\n },\n} as const;\n\n// Legacy flat exports for backward compatibility\nexport const WORMHOLE_CHAIN_IDS_FLAT = {\n // Mainnets\n SOLANA: 1,\n ETHEREUM: 2,\n TERRA: 3,\n BSC: 4,\n POLYGON: 5,\n AVALANCHE: 6,\n OASIS: 7,\n ALGORAND: 8,\n AURORA: 9,\n FANTOM: 10,\n KARURA: 11,\n ACALA: 12,\n KLAYTN: 13,\n CELO: 14,\n NEAR: 15,\n MOONBEAM: 16,\n NEON: 17,\n TERRA2: 18,\n INJECTIVE: 19,\n OSMOSIS: 20,\n SUI: 21,\n APTOS: 22,\n ARBITRUM: 23,\n OPTIMISM: 24,\n GNOSIS: 25,\n PYTHNET: 26,\n XPLA: 28,\n BASE: 30,\n SEI: 32,\n ROOTSTOCK: 33,\n SCROLL: 34,\n MANTLE: 35,\n BLAST: 36,\n XLAYER: 37,\n LINEA: 38,\n BERACHAIN: 39,\n SEIEVM: 40,\n\n // Testnets\n SOLANA_DEVNET: 1,\n GOERLI: 2,\n BSC_TESTNET: 4,\n POLYGON_MUMBAI: 5,\n AVALANCHE_FUJI: 6,\n FANTOM_TESTNET: 10,\n CELO_ALFAJORES: 14,\n MOONBASE_ALPHA: 16,\n SUI_TESTNET: 21,\n APTOS_TESTNET: 22,\n ARBITRUM_SEPOLIA: 10003,\n BASE_SEPOLIA: 10004,\n OPTIMISM_SEPOLIA: 10005,\n POLYGON_SEPOLIA: 10007,\n HOLESKY: 10006,\n STARKNET_SEPOLIA: 50001, // Custom bridge (non-Wormhole)\n} as const;\n\n// ============================================================================\n// Testnet Chain Configurations\n// ============================================================================\n\nexport const TESTNET_CHAINS: Record<string, ChainConfig> = {\n baseSepolia: {\n name: 'Base Sepolia',\n chainId: 84532,\n wormholeChainId: 10004,\n rpcUrl: 'https://sepolia.base.org', // Public CORS-friendly RPC\n explorerUrl: 'https://sepolia.basescan.org',\n isEvm: true,\n contracts: {\n hub: '0x66D87dE68327f48A099c5B9bE97020Feab9a7c82',\n vaultFactory: '0xCFaEb5652aa2Ee60b2229dC8895B4159749C7e53',\n vaultImplementation: '0x0d13367C16c6f0B24eD275CC67C7D9f42878285c',\n wormholeCoreBridge: '0x79A1027a6A159502049F10906D333EC57E95F083',\n tokenBridge: '0x86F55A04690fd7815A3D802bD587e83eA888B239',\n },\n },\n optimismSepolia: {\n name: 'Optimism Sepolia',\n chainId: 11155420,\n wormholeChainId: 10005,\n rpcUrl: 'https://sepolia.optimism.io',\n explorerUrl: 'https://sepolia-optimism.etherscan.io',\n isEvm: true,\n contracts: {\n vaultFactory: '0xA5653d54079ABeCe780F8d9597B2bc4B09fe464A',\n vaultImplementation: '0x8099b1406485d2255ff89Ce5Ea18520802AFC150',\n wormholeCoreBridge: '0x31377888146f3253211EFEf5c676D41ECe7D58Fe',\n tokenBridge: '0x99737Ec4B815d816c49A385943baf0380e75c0Ac',\n },\n },\n arbitrumSepolia: {\n name: 'Arbitrum Sepolia',\n chainId: 421614,\n wormholeChainId: 10003,\n rpcUrl: 'https://sepolia-rollup.arbitrum.io/rpc',\n explorerUrl: 'https://sepolia.arbiscan.io',\n isEvm: true,\n contracts: {\n vaultFactory: '0xd36D3D5DB59d78f1E33813490F72DABC15C9B07c',\n vaultImplementation: '0xB10ACf39eBF17fc33F722cBD955b7aeCB0611bc4',\n wormholeCoreBridge: '0x6b9C8671cdDC8dEab9c719bB87cBd3e782bA6a35',\n tokenBridge: '0xC7A204bDBFe983FCD8d8E61D02b475D4073fF97e',\n },\n },\n seiTestnet: {\n name: 'Sei Atlantic-2',\n chainId: 1328,\n wormholeChainId: 40,\n rpcUrl: 'https://evm-rpc-testnet.sei-apis.com',\n explorerUrl: 'https://seitrace.com/?chain=atlantic-2',\n isEvm: true,\n contracts: {\n vaultFactory: '0x07F608AFf6d63b68029488b726d895c4Bb593038',\n vaultImplementation: '0xD66153fccFB6731fB6c4944FbD607ba86A76a1f6',\n wormholeCoreBridge: '0x0000000000000000000000000000000000000000', // Mock - not yet deployed\n },\n },\n solanaDevnet: {\n name: 'Solana Devnet',\n chainId: 0,\n wormholeChainId: 1,\n rpcUrl: 'https://api.devnet.solana.com',\n explorerUrl: 'https://explorer.solana.com',\n isEvm: false,\n contracts: {\n hub: 'AnyXHsqq9c2BiW4WgBcj6Aye7Ua7a7L7iSuwpfJxECJM',\n wormholeCoreBridge: '3u8hJUVTA4jH1wYAyUur7FFZVQ8H635K3tSHHF4ssjQ5',\n tokenBridge: 'DZnkkTmCiFWfYTfT41X3Rd1kDgozqzxWaHqsw6W4x2oe',\n },\n },\n aptosTestnet: {\n name: 'Aptos Testnet',\n chainId: 0,\n wormholeChainId: 22,\n rpcUrl: 'https://fullnode.testnet.aptoslabs.com/v1',\n explorerUrl: 'https://explorer.aptoslabs.com',\n isEvm: false,\n contracts: {\n hub: '0x0237e04f74b991b5b6030a793779663033f4ff4a1682a9e66c1f41fc1ec3e2a4',\n wormholeCoreBridge: '0x5bc11445584a763c1fa7ed39081f1b920954da14e04b32440cba863d03e19625',\n tokenBridge: '0x576410486a2da45eee6c949c995670112ddf2fbeedab20350d506328eefc9d4f',\n },\n },\n suiTestnet: {\n name: 'Sui Testnet',\n chainId: 0,\n wormholeChainId: 21,\n rpcUrl: 'https://fullnode.testnet.sui.io:443',\n explorerUrl: 'https://suiscan.xyz/testnet',\n isEvm: false,\n contracts: {\n hub: '0x35e99fdbbc1cde7e093da6f9e758ba2c4a077904bd64caee2fa6db5e6c4e9e37',\n wormholeCoreBridge: '0x31358d198147da50db32eda2562951d53973a0c0ad5ed738e9b17d88b213d790',\n },\n },\n starknetSepolia: {\n name: 'Starknet Sepolia',\n chainId: 0, // Native Starknet chain ID (SN_SEPOLIA = 0x534e5f5345504f4c4941)\n wormholeChainId: 50001, // Custom chain ID (50000+ reserved for non-Wormhole chains)\n rpcUrl: 'https://starknet-sepolia.g.alchemy.com/starknet/version/rpc/v0_7/tsOnfTBZDKMXcUA26OED-',\n explorerUrl: 'https://sepolia.starkscan.co',\n isEvm: false,\n contracts: {\n // Starknet spoke contract\n hub: '0x68adcc730ed6c355200d00f763825448497b9cdf7936ca121711e078c88e811',\n // Custom bridge contract (NOT Wormhole)\n wormholeCoreBridge: '0x2c458c1ae64556482b05cc2d3ee5b032ed114d68429dda2062c9849a5a725f8',\n },\n // Hub chain ID that Starknet bridge validates (Base Sepolia = 10004)\n hubChainId: 10004,\n },\n};\n\n// ============================================================================\n// Mainnet Chain Configurations\n// ============================================================================\n\nexport const MAINNET_CHAINS: Record<string, ChainConfig> = {\n ethereum: {\n name: 'Ethereum',\n chainId: 1,\n wormholeChainId: 2,\n rpcUrl: 'https://eth.llamarpc.com',\n explorerUrl: 'https://etherscan.io',\n isEvm: true,\n contracts: {\n wormholeCoreBridge: '0x98f3c9e6E3fAce36bAAd05FE09d375Ef1464288B',\n tokenBridge: '0x3ee18B2214AFF97000D974cf647E7C347E8fa585',\n },\n },\n base: {\n name: 'Base',\n chainId: 8453,\n wormholeChainId: 30,\n rpcUrl: 'https://mainnet.base.org',\n explorerUrl: 'https://basescan.org',\n isEvm: true,\n contracts: {\n wormholeCoreBridge: '0xbebdb6C8ddC678FfA9f8748f85C815C556Dd8ac6',\n tokenBridge: '0x8d2de8d2f73F1F4cAB472AC9A881C9b123C79627',\n },\n },\n optimism: {\n name: 'Optimism',\n chainId: 10,\n wormholeChainId: 24,\n rpcUrl: 'https://mainnet.optimism.io',\n explorerUrl: 'https://optimistic.etherscan.io',\n isEvm: true,\n contracts: {\n wormholeCoreBridge: '0xEe91C335eab126dF5fDB3797EA9d6aD93aeC9722',\n tokenBridge: '0x1D68124e65faFC907325e3EDbF8c4d84499DAa8b',\n },\n },\n arbitrum: {\n name: 'Arbitrum',\n chainId: 42161,\n wormholeChainId: 23,\n rpcUrl: 'https://arb1.arbitrum.io/rpc',\n explorerUrl: 'https://arbiscan.io',\n isEvm: true,\n contracts: {\n wormholeCoreBridge: '0xa5f208e072434bC67592E4C49C1B991BA79BCA46',\n tokenBridge: '0x0b2402144Bb366A632D14B83F244D2e0e21bD39c',\n },\n },\n polygon: {\n name: 'Polygon',\n chainId: 137,\n wormholeChainId: 5,\n rpcUrl: 'https://polygon-rpc.com',\n explorerUrl: 'https://polygonscan.com',\n isEvm: true,\n contracts: {\n wormholeCoreBridge: '0x7A4B5a56256163F07b2C80A7cA55aBE66c4ec4d7',\n tokenBridge: '0x5a58505a96D1dbf8dF91cB21B54419FC36e93fdE',\n },\n },\n solana: {\n name: 'Solana',\n chainId: 0,\n wormholeChainId: 1,\n rpcUrl: 'https://api.mainnet-beta.solana.com',\n explorerUrl: 'https://explorer.solana.com',\n isEvm: false,\n contracts: {\n wormholeCoreBridge: 'worm2ZoG2kUd4vFXhvjh93UUH596ayRfgQ2MgjNMTth',\n tokenBridge: 'wormDTUJ6AWPNvk59vGQbDvGJmqbDTdgWgAqcLBCgUb',\n },\n },\n aptos: {\n name: 'Aptos',\n chainId: 0,\n wormholeChainId: 22,\n rpcUrl: 'https://fullnode.mainnet.aptoslabs.com/v1',\n explorerUrl: 'https://explorer.aptoslabs.com',\n isEvm: false,\n contracts: {\n wormholeCoreBridge: '0x5bc11445584a763c1fa7ed39081f1b920954da14e04b32440cba863d03e19625',\n tokenBridge: '0x576410486a2da45eee6c949c995670112ddf2fbeedab20350d506328eefc9d4f',\n },\n },\n sui: {\n name: 'Sui',\n chainId: 0,\n wormholeChainId: 21,\n rpcUrl: 'https://fullnode.mainnet.sui.io:443',\n explorerUrl: 'https://suiscan.xyz/mainnet',\n isEvm: false,\n contracts: {\n wormholeCoreBridge: '0xaeab97f96cf9877fee2883315d459552b2b921edc16d7ceac6eab944dd88919c',\n },\n },\n};\n\n// ============================================================================\n// Wormhole API Endpoints\n// ============================================================================\n\nexport const WORMHOLE_API = {\n MAINNET: 'https://api.wormholescan.io',\n TESTNET: 'https://api.testnet.wormholescan.io',\n GUARDIAN_RPC_MAINNET: 'https://wormhole-v2-mainnet-api.certus.one',\n GUARDIAN_RPC_TESTNET: 'https://wormhole-v2-testnet-api.certus.one',\n} as const;\n\n// ============================================================================\n// Hub Contract ABI (minimal)\n// ============================================================================\n\nexport const HUB_ABI = [\n 'function authenticateAndDispatch((bytes authenticatorData, string clientDataJSON, uint256 challengeIndex, uint256 typeIndex, uint256 r, uint256 s) auth, uint256 publicKeyX, uint256 publicKeyY, uint16 targetChain, bytes actionPayload) external payable returns (uint64 sequence)',\n 'function authenticateRawAndDispatch(uint256 r, uint256 s, bytes32 messageHash, uint256 publicKeyX, uint256 publicKeyY, uint16 targetChain, bytes actionPayload, uint256 nonce) external payable returns (uint64 sequence)',\n 'function userNonces(bytes32 userKeyHash) external view returns (uint256)',\n 'function encodeTransferAction(address token, address recipient, uint256 amount) external pure returns (bytes)',\n 'function encodeExecuteAction(address target, uint256 value, bytes data) external pure returns (bytes)',\n 'function encodeBridgeAction(bytes32 token, uint256 amount, uint16 targetChain, bytes32 recipient) external pure returns (bytes)',\n 'function messageFee() external view returns (uint256)',\n 'event Dispatched(bytes32 indexed userKeyHash, uint16 targetChain, uint256 nonce, uint64 sequence, bytes actionPayload)',\n] as const;\n\n// ============================================================================\n// Vault Factory ABI (minimal)\n// ============================================================================\n\nexport const VAULT_FACTORY_ABI = [\n 'function createVault(bytes32 userKeyHash) external returns (address)',\n 'function getVault(bytes32 userKeyHash) external view returns (address)',\n 'function vaultExists(bytes32 userKeyHash) external view returns (bool)',\n 'event VaultCreated(bytes32 indexed userKeyHash, address vault)',\n] as const;\n\n// ============================================================================\n// Vault ABI (minimal)\n// ============================================================================\n\nexport const VAULT_ABI = [\n 'function execute(address target, uint256 value, bytes data) external returns (bytes)',\n 'function executeFromHub(bytes32 vaaHash, uint16 emitterChain, bytes32 emitterAddress, bytes payload) external',\n 'function owner() external view returns (bytes32)',\n 'function hub() external view returns (address)',\n 'receive() external payable',\n] as const;\n"],"mappings":"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","names":[]}