@veridex/sdk 1.0.0-beta.5 → 1.0.0-beta.6

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/utils.js CHANGED
@@ -52,8 +52,8 @@ var TESTNET_CHAINS = {
52
52
  isEvm: true,
53
53
  contracts: {
54
54
  hub: "0x66D87dE68327f48A099c5B9bE97020Feab9a7c82",
55
- vaultFactory: "0x40D9B16094808Fa48e73598E31AB964Cf15b475f",
56
- vaultImplementation: "0xcBEb49b0109E61c1C69C51D5D9483A3aD6D18258",
55
+ vaultFactory: "0xCFaEb5652aa2Ee60b2229dC8895B4159749C7e53",
56
+ vaultImplementation: "0x0d13367C16c6f0B24eD275CC67C7D9f42878285c",
57
57
  wormholeCoreBridge: "0x79A1027a6A159502049F10906D333EC57E95F083",
58
58
  tokenBridge: "0x86F55A04690fd7815A3D802bD587e83eA888B239"
59
59
  }
@@ -66,8 +66,8 @@ var TESTNET_CHAINS = {
66
66
  explorerUrl: "https://sepolia-optimism.etherscan.io",
67
67
  isEvm: true,
68
68
  contracts: {
69
- vaultFactory: "0xAbB421166E648953CDBE93c0078a0A794c56Fb84",
70
- vaultImplementation: "0xDCD7daEf1AC06f4a8392957cca4834F7a16c058D",
69
+ vaultFactory: "0xA5653d54079ABeCe780F8d9597B2bc4B09fe464A",
70
+ vaultImplementation: "0x8099b1406485d2255ff89Ce5Ea18520802AFC150",
71
71
  wormholeCoreBridge: "0x31377888146f3253211EFEf5c676D41ECe7D58Fe",
72
72
  tokenBridge: "0x99737Ec4B815d816c49A385943baf0380e75c0Ac"
73
73
  }
package/dist/utils.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/utils.ts","../src/constants.ts"],"sourcesContent":["/**\n * Veridex Protocol SDK - Utility Functions\n */\n\nimport { ethers } from 'ethers';\nimport type { ChainConfig } from './types.js';\nimport { TESTNET_CHAINS, MAINNET_CHAINS } from './constants.js';\n\n// ============================================================================\n// Base64URL Encoding/Decoding (WebAuthn compatible)\n// ============================================================================\n\n/**\n * Base64URL encode a buffer\n */\nexport function base64URLEncode(buffer: Uint8Array): string {\n // Convert Uint8Array to base64 using browser APIs\n const bytes = Array.from(buffer);\n const binary = String.fromCharCode(...bytes);\n const base64 = btoa(binary);\n return base64.replace(/\\+/g, '-').replace(/\\//g, '_').replace(/=/g, '');\n}\n\n/**\n * Base64URL decode a string\n */\nexport function base64URLDecode(str: string): Uint8Array {\n const base64 = str.replace(/-/g, '+').replace(/_/g, '/');\n const padded = base64 + '='.repeat((4 - (base64.length % 4)) % 4);\n // Use browser's atob for base64 decoding\n const binary = atob(padded);\n const bytes = new Uint8Array(binary.length);\n for (let i = 0; i < binary.length; i++) {\n bytes[i] = binary.charCodeAt(i);\n }\n return bytes;\n}\n\n// ============================================================================\n// Signature Utilities\n// ============================================================================\n\n/**\n * Parse DER-encoded ECDSA signature to r and s values\n */\nexport function parseDERSignature(signature: Uint8Array): { r: Uint8Array; s: Uint8Array } {\n let offset = 0;\n\n if (signature[offset++] !== 0x30) {\n throw new Error('Invalid signature format');\n }\n\n // Skip total length\n offset++;\n\n if (signature[offset++] !== 0x02) {\n throw new Error('Invalid signature format');\n }\n\n const rLength = signature[offset++];\n if (rLength === undefined) {\n throw new Error('Invalid signature format: missing r length');\n }\n let r = signature.slice(offset, offset + rLength);\n offset += rLength;\n\n // Remove leading zero if present (for positive number representation)\n if (r[0] === 0x00 && r.length > 32) {\n r = r.slice(1);\n }\n // Pad to 32 bytes if needed\n if (r.length < 32) {\n const padded = new Uint8Array(32);\n padded.set(r, 32 - r.length);\n r = padded;\n }\n\n if (signature[offset++] !== 0x02) {\n throw new Error('Invalid signature format');\n }\n\n const sLength = signature[offset++];\n if (sLength === undefined) {\n throw new Error('Invalid signature format: missing s length');\n }\n let s = signature.slice(offset, offset + sLength);\n\n // Remove leading zero if present\n if (s[0] === 0x00 && s.length > 32) {\n s = s.slice(1);\n }\n // Pad to 32 bytes if needed\n if (s.length < 32) {\n const padded = new Uint8Array(32);\n padded.set(s, 32 - s.length);\n s = padded;\n }\n\n return { r, s };\n}\n\n/**\n * Encode signature for Solidity verification\n */\nexport function encodeSignatureForSolidity(r: bigint, s: bigint): string {\n return ethers.solidityPacked(['uint256', 'uint256'], [r, s]);\n}\n\n// ============================================================================\n// Key Hash Utilities\n// ============================================================================\n\n/**\n * Compute key hash from public key coordinates\n */\nexport function computeKeyHash(publicKeyX: bigint, publicKeyY: bigint): string {\n return ethers.keccak256(\n ethers.solidityPacked(['uint256', 'uint256'], [publicKeyX, publicKeyY])\n );\n}\n\n// ============================================================================\n// Chain Utilities\n// ============================================================================\n\n/**\n * Get chain config by name\n */\nexport function getChainConfig(chainName: string, testnet = true): ChainConfig | undefined {\n const chains = testnet ? TESTNET_CHAINS : MAINNET_CHAINS;\n return chains[chainName];\n}\n\n/**\n * Get chain config by Wormhole chain ID\n */\nexport function getChainByWormholeId(wormholeChainId: number, testnet = true): ChainConfig | undefined {\n const chains = testnet ? TESTNET_CHAINS : MAINNET_CHAINS;\n return Object.values(chains).find(chain => chain.wormholeChainId === wormholeChainId);\n}\n\n/**\n * Get chain config by EVM chain ID\n */\nexport function getChainByEvmId(evmChainId: number, testnet = true): ChainConfig | undefined {\n const chains = testnet ? TESTNET_CHAINS : MAINNET_CHAINS;\n return Object.values(chains).find(chain => chain.chainId === evmChainId);\n}\n\n/**\n * Check if a chain is EVM-compatible\n */\nexport function isEvmChain(wormholeChainId: number): boolean {\n // Non-EVM chains\n const nonEvmChains = new Set([1, 8, 15, 21, 22]); // Solana, Algorand, NEAR, Sui, Aptos\n return !nonEvmChains.has(wormholeChainId);\n}\n\n/**\n * Get all supported chains\n */\nexport function getSupportedChains(testnet = true): ChainConfig[] {\n const chains = testnet ? TESTNET_CHAINS : MAINNET_CHAINS;\n return Object.values(chains);\n}\n\n// ============================================================================\n// Explorer URL Utilities\n// ============================================================================\n\n/**\n * Get transaction explorer URL\n */\nexport function getTxExplorerUrl(chain: ChainConfig, txHash: string): string {\n if (chain.isEvm) {\n return `${chain.explorerUrl}/tx/${txHash}`;\n }\n\n // Non-EVM chains have different URL patterns\n switch (chain.wormholeChainId) {\n case 1: // Solana\n return `${chain.explorerUrl}/tx/${txHash}?cluster=devnet`;\n case 21: // Sui\n return `${chain.explorerUrl}/tx/${txHash}`;\n case 22: // Aptos\n return `${chain.explorerUrl}/txn/${txHash}?network=testnet`;\n default:\n return `${chain.explorerUrl}/tx/${txHash}`;\n }\n}\n\n/**\n * Get address explorer URL\n */\nexport function getAddressExplorerUrl(chain: ChainConfig, address: string): string {\n if (chain.isEvm) {\n return `${chain.explorerUrl}/address/${address}`;\n }\n\n switch (chain.wormholeChainId) {\n case 1: // Solana\n return `${chain.explorerUrl}/address/${address}?cluster=devnet`;\n case 21: // Sui\n return `${chain.explorerUrl}/account/${address}`;\n case 22: // Aptos\n return `${chain.explorerUrl}/account/${address}?network=testnet`;\n default:\n return `${chain.explorerUrl}/address/${address}`;\n }\n}\n\n// ============================================================================\n// Validation Utilities\n// ============================================================================\n\n/**\n * Validate an EVM address\n */\nexport function isValidEvmAddress(address: string): boolean {\n return ethers.isAddress(address);\n}\n\n/**\n * Validate a bytes32 hex string\n */\nexport function isValidBytes32(hex: string): boolean {\n const clean = hex.replace('0x', '');\n return /^[0-9a-fA-F]{64}$/.test(clean);\n}\n\n/**\n * Validate a Wormhole chain ID\n */\nexport function isValidWormholeChainId(chainId: number): boolean {\n // Valid Wormhole chain IDs range from 1 to ~10007 (testnets)\n return chainId >= 1 && chainId <= 50000;\n}\n\n// ============================================================================\n// Retry Utilities\n// ============================================================================\n\n/**\n * Retry a function with exponential backoff\n */\nexport async function retryWithBackoff<T>(\n fn: () => Promise<T>,\n options: {\n maxRetries?: number;\n initialDelayMs?: number;\n maxDelayMs?: number;\n backoffMultiplier?: number;\n onRetry?: (attempt: number, error: Error) => void;\n } = {}\n): Promise<T> {\n const {\n maxRetries = 5,\n initialDelayMs = 1000,\n maxDelayMs = 30000,\n backoffMultiplier = 2,\n onRetry,\n } = options;\n\n let lastError: Error | undefined;\n let delay = initialDelayMs;\n\n for (let attempt = 1; attempt <= maxRetries; attempt++) {\n try {\n return await fn();\n } catch (error) {\n lastError = error as Error;\n\n if (attempt < maxRetries) {\n onRetry?.(attempt, lastError);\n await sleep(delay);\n delay = Math.min(delay * backoffMultiplier, maxDelayMs);\n }\n }\n }\n\n throw lastError ?? new Error('Retry failed');\n}\n\n// ============================================================================\n// Helpers\n// ============================================================================\n\nfunction sleep(ms: number): Promise<void> {\n return new Promise(resolve => setTimeout(resolve, ms));\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: '0x40D9B16094808Fa48e73598E31AB964Cf15b475f',\n vaultImplementation: '0xcBEb49b0109E61c1C69C51D5D9483A3aD6D18258',\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: '0xAbB421166E648953CDBE93c0078a0A794c56Fb84',\n vaultImplementation: '0xDCD7daEf1AC06f4a8392957cca4834F7a16c058D',\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: '0x1a89da9e9f8f0bc90d8d492890bd55fb261c6277d2a95dfcac70c268d0c23dcc',\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/utils.ts","../src/constants.ts"],"sourcesContent":["/**\n * Veridex Protocol SDK - Utility Functions\n */\n\nimport { ethers } from 'ethers';\nimport type { ChainConfig } from './types.js';\nimport { TESTNET_CHAINS, MAINNET_CHAINS } from './constants.js';\n\n// ============================================================================\n// Base64URL Encoding/Decoding (WebAuthn compatible)\n// ============================================================================\n\n/**\n * Base64URL encode a buffer\n */\nexport function base64URLEncode(buffer: Uint8Array): string {\n // Convert Uint8Array to base64 using browser APIs\n const bytes = Array.from(buffer);\n const binary = String.fromCharCode(...bytes);\n const base64 = btoa(binary);\n return base64.replace(/\\+/g, '-').replace(/\\//g, '_').replace(/=/g, '');\n}\n\n/**\n * Base64URL decode a string\n */\nexport function base64URLDecode(str: string): Uint8Array {\n const base64 = str.replace(/-/g, '+').replace(/_/g, '/');\n const padded = base64 + '='.repeat((4 - (base64.length % 4)) % 4);\n // Use browser's atob for base64 decoding\n const binary = atob(padded);\n const bytes = new Uint8Array(binary.length);\n for (let i = 0; i < binary.length; i++) {\n bytes[i] = binary.charCodeAt(i);\n }\n return bytes;\n}\n\n// ============================================================================\n// Signature Utilities\n// ============================================================================\n\n/**\n * Parse DER-encoded ECDSA signature to r and s values\n */\nexport function parseDERSignature(signature: Uint8Array): { r: Uint8Array; s: Uint8Array } {\n let offset = 0;\n\n if (signature[offset++] !== 0x30) {\n throw new Error('Invalid signature format');\n }\n\n // Skip total length\n offset++;\n\n if (signature[offset++] !== 0x02) {\n throw new Error('Invalid signature format');\n }\n\n const rLength = signature[offset++];\n if (rLength === undefined) {\n throw new Error('Invalid signature format: missing r length');\n }\n let r = signature.slice(offset, offset + rLength);\n offset += rLength;\n\n // Remove leading zero if present (for positive number representation)\n if (r[0] === 0x00 && r.length > 32) {\n r = r.slice(1);\n }\n // Pad to 32 bytes if needed\n if (r.length < 32) {\n const padded = new Uint8Array(32);\n padded.set(r, 32 - r.length);\n r = padded;\n }\n\n if (signature[offset++] !== 0x02) {\n throw new Error('Invalid signature format');\n }\n\n const sLength = signature[offset++];\n if (sLength === undefined) {\n throw new Error('Invalid signature format: missing s length');\n }\n let s = signature.slice(offset, offset + sLength);\n\n // Remove leading zero if present\n if (s[0] === 0x00 && s.length > 32) {\n s = s.slice(1);\n }\n // Pad to 32 bytes if needed\n if (s.length < 32) {\n const padded = new Uint8Array(32);\n padded.set(s, 32 - s.length);\n s = padded;\n }\n\n return { r, s };\n}\n\n/**\n * Encode signature for Solidity verification\n */\nexport function encodeSignatureForSolidity(r: bigint, s: bigint): string {\n return ethers.solidityPacked(['uint256', 'uint256'], [r, s]);\n}\n\n// ============================================================================\n// Key Hash Utilities\n// ============================================================================\n\n/**\n * Compute key hash from public key coordinates\n */\nexport function computeKeyHash(publicKeyX: bigint, publicKeyY: bigint): string {\n return ethers.keccak256(\n ethers.solidityPacked(['uint256', 'uint256'], [publicKeyX, publicKeyY])\n );\n}\n\n// ============================================================================\n// Chain Utilities\n// ============================================================================\n\n/**\n * Get chain config by name\n */\nexport function getChainConfig(chainName: string, testnet = true): ChainConfig | undefined {\n const chains = testnet ? TESTNET_CHAINS : MAINNET_CHAINS;\n return chains[chainName];\n}\n\n/**\n * Get chain config by Wormhole chain ID\n */\nexport function getChainByWormholeId(wormholeChainId: number, testnet = true): ChainConfig | undefined {\n const chains = testnet ? TESTNET_CHAINS : MAINNET_CHAINS;\n return Object.values(chains).find(chain => chain.wormholeChainId === wormholeChainId);\n}\n\n/**\n * Get chain config by EVM chain ID\n */\nexport function getChainByEvmId(evmChainId: number, testnet = true): ChainConfig | undefined {\n const chains = testnet ? TESTNET_CHAINS : MAINNET_CHAINS;\n return Object.values(chains).find(chain => chain.chainId === evmChainId);\n}\n\n/**\n * Check if a chain is EVM-compatible\n */\nexport function isEvmChain(wormholeChainId: number): boolean {\n // Non-EVM chains\n const nonEvmChains = new Set([1, 8, 15, 21, 22]); // Solana, Algorand, NEAR, Sui, Aptos\n return !nonEvmChains.has(wormholeChainId);\n}\n\n/**\n * Get all supported chains\n */\nexport function getSupportedChains(testnet = true): ChainConfig[] {\n const chains = testnet ? TESTNET_CHAINS : MAINNET_CHAINS;\n return Object.values(chains);\n}\n\n// ============================================================================\n// Explorer URL Utilities\n// ============================================================================\n\n/**\n * Get transaction explorer URL\n */\nexport function getTxExplorerUrl(chain: ChainConfig, txHash: string): string {\n if (chain.isEvm) {\n return `${chain.explorerUrl}/tx/${txHash}`;\n }\n\n // Non-EVM chains have different URL patterns\n switch (chain.wormholeChainId) {\n case 1: // Solana\n return `${chain.explorerUrl}/tx/${txHash}?cluster=devnet`;\n case 21: // Sui\n return `${chain.explorerUrl}/tx/${txHash}`;\n case 22: // Aptos\n return `${chain.explorerUrl}/txn/${txHash}?network=testnet`;\n default:\n return `${chain.explorerUrl}/tx/${txHash}`;\n }\n}\n\n/**\n * Get address explorer URL\n */\nexport function getAddressExplorerUrl(chain: ChainConfig, address: string): string {\n if (chain.isEvm) {\n return `${chain.explorerUrl}/address/${address}`;\n }\n\n switch (chain.wormholeChainId) {\n case 1: // Solana\n return `${chain.explorerUrl}/address/${address}?cluster=devnet`;\n case 21: // Sui\n return `${chain.explorerUrl}/account/${address}`;\n case 22: // Aptos\n return `${chain.explorerUrl}/account/${address}?network=testnet`;\n default:\n return `${chain.explorerUrl}/address/${address}`;\n }\n}\n\n// ============================================================================\n// Validation Utilities\n// ============================================================================\n\n/**\n * Validate an EVM address\n */\nexport function isValidEvmAddress(address: string): boolean {\n return ethers.isAddress(address);\n}\n\n/**\n * Validate a bytes32 hex string\n */\nexport function isValidBytes32(hex: string): boolean {\n const clean = hex.replace('0x', '');\n return /^[0-9a-fA-F]{64}$/.test(clean);\n}\n\n/**\n * Validate a Wormhole chain ID\n */\nexport function isValidWormholeChainId(chainId: number): boolean {\n // Valid Wormhole chain IDs range from 1 to ~10007 (testnets)\n return chainId >= 1 && chainId <= 50000;\n}\n\n// ============================================================================\n// Retry Utilities\n// ============================================================================\n\n/**\n * Retry a function with exponential backoff\n */\nexport async function retryWithBackoff<T>(\n fn: () => Promise<T>,\n options: {\n maxRetries?: number;\n initialDelayMs?: number;\n maxDelayMs?: number;\n backoffMultiplier?: number;\n onRetry?: (attempt: number, error: Error) => void;\n } = {}\n): Promise<T> {\n const {\n maxRetries = 5,\n initialDelayMs = 1000,\n maxDelayMs = 30000,\n backoffMultiplier = 2,\n onRetry,\n } = options;\n\n let lastError: Error | undefined;\n let delay = initialDelayMs;\n\n for (let attempt = 1; attempt <= maxRetries; attempt++) {\n try {\n return await fn();\n } catch (error) {\n lastError = error as Error;\n\n if (attempt < maxRetries) {\n onRetry?.(attempt, lastError);\n await sleep(delay);\n delay = Math.min(delay * backoffMultiplier, maxDelayMs);\n }\n }\n }\n\n throw lastError ?? new Error('Retry failed');\n}\n\n// ============================================================================\n// Helpers\n// ============================================================================\n\nfunction sleep(ms: number): Promise<void> {\n return new Promise(resolve => setTimeout(resolve, ms));\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: '0x1a89da9e9f8f0bc90d8d492890bd55fb261c6277d2a95dfcac70c268d0c23dcc',\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":[]}
package/dist/utils.mjs CHANGED
@@ -13,8 +13,8 @@ var TESTNET_CHAINS = {
13
13
  isEvm: true,
14
14
  contracts: {
15
15
  hub: "0x66D87dE68327f48A099c5B9bE97020Feab9a7c82",
16
- vaultFactory: "0x40D9B16094808Fa48e73598E31AB964Cf15b475f",
17
- vaultImplementation: "0xcBEb49b0109E61c1C69C51D5D9483A3aD6D18258",
16
+ vaultFactory: "0xCFaEb5652aa2Ee60b2229dC8895B4159749C7e53",
17
+ vaultImplementation: "0x0d13367C16c6f0B24eD275CC67C7D9f42878285c",
18
18
  wormholeCoreBridge: "0x79A1027a6A159502049F10906D333EC57E95F083",
19
19
  tokenBridge: "0x86F55A04690fd7815A3D802bD587e83eA888B239"
20
20
  }
@@ -27,8 +27,8 @@ var TESTNET_CHAINS = {
27
27
  explorerUrl: "https://sepolia-optimism.etherscan.io",
28
28
  isEvm: true,
29
29
  contracts: {
30
- vaultFactory: "0xAbB421166E648953CDBE93c0078a0A794c56Fb84",
31
- vaultImplementation: "0xDCD7daEf1AC06f4a8392957cca4834F7a16c058D",
30
+ vaultFactory: "0xA5653d54079ABeCe780F8d9597B2bc4B09fe464A",
31
+ vaultImplementation: "0x8099b1406485d2255ff89Ce5Ea18520802AFC150",
32
32
  wormholeCoreBridge: "0x31377888146f3253211EFEf5c676D41ECe7D58Fe",
33
33
  tokenBridge: "0x99737Ec4B815d816c49A385943baf0380e75c0Ac"
34
34
  }
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/utils.ts","../src/constants.ts"],"sourcesContent":["/**\n * Veridex Protocol SDK - Utility Functions\n */\n\nimport { ethers } from 'ethers';\nimport type { ChainConfig } from './types.js';\nimport { TESTNET_CHAINS, MAINNET_CHAINS } from './constants.js';\n\n// ============================================================================\n// Base64URL Encoding/Decoding (WebAuthn compatible)\n// ============================================================================\n\n/**\n * Base64URL encode a buffer\n */\nexport function base64URLEncode(buffer: Uint8Array): string {\n // Convert Uint8Array to base64 using browser APIs\n const bytes = Array.from(buffer);\n const binary = String.fromCharCode(...bytes);\n const base64 = btoa(binary);\n return base64.replace(/\\+/g, '-').replace(/\\//g, '_').replace(/=/g, '');\n}\n\n/**\n * Base64URL decode a string\n */\nexport function base64URLDecode(str: string): Uint8Array {\n const base64 = str.replace(/-/g, '+').replace(/_/g, '/');\n const padded = base64 + '='.repeat((4 - (base64.length % 4)) % 4);\n // Use browser's atob for base64 decoding\n const binary = atob(padded);\n const bytes = new Uint8Array(binary.length);\n for (let i = 0; i < binary.length; i++) {\n bytes[i] = binary.charCodeAt(i);\n }\n return bytes;\n}\n\n// ============================================================================\n// Signature Utilities\n// ============================================================================\n\n/**\n * Parse DER-encoded ECDSA signature to r and s values\n */\nexport function parseDERSignature(signature: Uint8Array): { r: Uint8Array; s: Uint8Array } {\n let offset = 0;\n\n if (signature[offset++] !== 0x30) {\n throw new Error('Invalid signature format');\n }\n\n // Skip total length\n offset++;\n\n if (signature[offset++] !== 0x02) {\n throw new Error('Invalid signature format');\n }\n\n const rLength = signature[offset++];\n if (rLength === undefined) {\n throw new Error('Invalid signature format: missing r length');\n }\n let r = signature.slice(offset, offset + rLength);\n offset += rLength;\n\n // Remove leading zero if present (for positive number representation)\n if (r[0] === 0x00 && r.length > 32) {\n r = r.slice(1);\n }\n // Pad to 32 bytes if needed\n if (r.length < 32) {\n const padded = new Uint8Array(32);\n padded.set(r, 32 - r.length);\n r = padded;\n }\n\n if (signature[offset++] !== 0x02) {\n throw new Error('Invalid signature format');\n }\n\n const sLength = signature[offset++];\n if (sLength === undefined) {\n throw new Error('Invalid signature format: missing s length');\n }\n let s = signature.slice(offset, offset + sLength);\n\n // Remove leading zero if present\n if (s[0] === 0x00 && s.length > 32) {\n s = s.slice(1);\n }\n // Pad to 32 bytes if needed\n if (s.length < 32) {\n const padded = new Uint8Array(32);\n padded.set(s, 32 - s.length);\n s = padded;\n }\n\n return { r, s };\n}\n\n/**\n * Encode signature for Solidity verification\n */\nexport function encodeSignatureForSolidity(r: bigint, s: bigint): string {\n return ethers.solidityPacked(['uint256', 'uint256'], [r, s]);\n}\n\n// ============================================================================\n// Key Hash Utilities\n// ============================================================================\n\n/**\n * Compute key hash from public key coordinates\n */\nexport function computeKeyHash(publicKeyX: bigint, publicKeyY: bigint): string {\n return ethers.keccak256(\n ethers.solidityPacked(['uint256', 'uint256'], [publicKeyX, publicKeyY])\n );\n}\n\n// ============================================================================\n// Chain Utilities\n// ============================================================================\n\n/**\n * Get chain config by name\n */\nexport function getChainConfig(chainName: string, testnet = true): ChainConfig | undefined {\n const chains = testnet ? TESTNET_CHAINS : MAINNET_CHAINS;\n return chains[chainName];\n}\n\n/**\n * Get chain config by Wormhole chain ID\n */\nexport function getChainByWormholeId(wormholeChainId: number, testnet = true): ChainConfig | undefined {\n const chains = testnet ? TESTNET_CHAINS : MAINNET_CHAINS;\n return Object.values(chains).find(chain => chain.wormholeChainId === wormholeChainId);\n}\n\n/**\n * Get chain config by EVM chain ID\n */\nexport function getChainByEvmId(evmChainId: number, testnet = true): ChainConfig | undefined {\n const chains = testnet ? TESTNET_CHAINS : MAINNET_CHAINS;\n return Object.values(chains).find(chain => chain.chainId === evmChainId);\n}\n\n/**\n * Check if a chain is EVM-compatible\n */\nexport function isEvmChain(wormholeChainId: number): boolean {\n // Non-EVM chains\n const nonEvmChains = new Set([1, 8, 15, 21, 22]); // Solana, Algorand, NEAR, Sui, Aptos\n return !nonEvmChains.has(wormholeChainId);\n}\n\n/**\n * Get all supported chains\n */\nexport function getSupportedChains(testnet = true): ChainConfig[] {\n const chains = testnet ? TESTNET_CHAINS : MAINNET_CHAINS;\n return Object.values(chains);\n}\n\n// ============================================================================\n// Explorer URL Utilities\n// ============================================================================\n\n/**\n * Get transaction explorer URL\n */\nexport function getTxExplorerUrl(chain: ChainConfig, txHash: string): string {\n if (chain.isEvm) {\n return `${chain.explorerUrl}/tx/${txHash}`;\n }\n\n // Non-EVM chains have different URL patterns\n switch (chain.wormholeChainId) {\n case 1: // Solana\n return `${chain.explorerUrl}/tx/${txHash}?cluster=devnet`;\n case 21: // Sui\n return `${chain.explorerUrl}/tx/${txHash}`;\n case 22: // Aptos\n return `${chain.explorerUrl}/txn/${txHash}?network=testnet`;\n default:\n return `${chain.explorerUrl}/tx/${txHash}`;\n }\n}\n\n/**\n * Get address explorer URL\n */\nexport function getAddressExplorerUrl(chain: ChainConfig, address: string): string {\n if (chain.isEvm) {\n return `${chain.explorerUrl}/address/${address}`;\n }\n\n switch (chain.wormholeChainId) {\n case 1: // Solana\n return `${chain.explorerUrl}/address/${address}?cluster=devnet`;\n case 21: // Sui\n return `${chain.explorerUrl}/account/${address}`;\n case 22: // Aptos\n return `${chain.explorerUrl}/account/${address}?network=testnet`;\n default:\n return `${chain.explorerUrl}/address/${address}`;\n }\n}\n\n// ============================================================================\n// Validation Utilities\n// ============================================================================\n\n/**\n * Validate an EVM address\n */\nexport function isValidEvmAddress(address: string): boolean {\n return ethers.isAddress(address);\n}\n\n/**\n * Validate a bytes32 hex string\n */\nexport function isValidBytes32(hex: string): boolean {\n const clean = hex.replace('0x', '');\n return /^[0-9a-fA-F]{64}$/.test(clean);\n}\n\n/**\n * Validate a Wormhole chain ID\n */\nexport function isValidWormholeChainId(chainId: number): boolean {\n // Valid Wormhole chain IDs range from 1 to ~10007 (testnets)\n return chainId >= 1 && chainId <= 50000;\n}\n\n// ============================================================================\n// Retry Utilities\n// ============================================================================\n\n/**\n * Retry a function with exponential backoff\n */\nexport async function retryWithBackoff<T>(\n fn: () => Promise<T>,\n options: {\n maxRetries?: number;\n initialDelayMs?: number;\n maxDelayMs?: number;\n backoffMultiplier?: number;\n onRetry?: (attempt: number, error: Error) => void;\n } = {}\n): Promise<T> {\n const {\n maxRetries = 5,\n initialDelayMs = 1000,\n maxDelayMs = 30000,\n backoffMultiplier = 2,\n onRetry,\n } = options;\n\n let lastError: Error | undefined;\n let delay = initialDelayMs;\n\n for (let attempt = 1; attempt <= maxRetries; attempt++) {\n try {\n return await fn();\n } catch (error) {\n lastError = error as Error;\n\n if (attempt < maxRetries) {\n onRetry?.(attempt, lastError);\n await sleep(delay);\n delay = Math.min(delay * backoffMultiplier, maxDelayMs);\n }\n }\n }\n\n throw lastError ?? new Error('Retry failed');\n}\n\n// ============================================================================\n// Helpers\n// ============================================================================\n\nfunction sleep(ms: number): Promise<void> {\n return new Promise(resolve => setTimeout(resolve, ms));\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: '0x40D9B16094808Fa48e73598E31AB964Cf15b475f',\n vaultImplementation: '0xcBEb49b0109E61c1C69C51D5D9483A3aD6D18258',\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: '0xAbB421166E648953CDBE93c0078a0A794c56Fb84',\n vaultImplementation: '0xDCD7daEf1AC06f4a8392957cca4834F7a16c058D',\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: '0x1a89da9e9f8f0bc90d8d492890bd55fb261c6277d2a95dfcac70c268d0c23dcc',\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/utils.ts","../src/constants.ts"],"sourcesContent":["/**\n * Veridex Protocol SDK - Utility Functions\n */\n\nimport { ethers } from 'ethers';\nimport type { ChainConfig } from './types.js';\nimport { TESTNET_CHAINS, MAINNET_CHAINS } from './constants.js';\n\n// ============================================================================\n// Base64URL Encoding/Decoding (WebAuthn compatible)\n// ============================================================================\n\n/**\n * Base64URL encode a buffer\n */\nexport function base64URLEncode(buffer: Uint8Array): string {\n // Convert Uint8Array to base64 using browser APIs\n const bytes = Array.from(buffer);\n const binary = String.fromCharCode(...bytes);\n const base64 = btoa(binary);\n return base64.replace(/\\+/g, '-').replace(/\\//g, '_').replace(/=/g, '');\n}\n\n/**\n * Base64URL decode a string\n */\nexport function base64URLDecode(str: string): Uint8Array {\n const base64 = str.replace(/-/g, '+').replace(/_/g, '/');\n const padded = base64 + '='.repeat((4 - (base64.length % 4)) % 4);\n // Use browser's atob for base64 decoding\n const binary = atob(padded);\n const bytes = new Uint8Array(binary.length);\n for (let i = 0; i < binary.length; i++) {\n bytes[i] = binary.charCodeAt(i);\n }\n return bytes;\n}\n\n// ============================================================================\n// Signature Utilities\n// ============================================================================\n\n/**\n * Parse DER-encoded ECDSA signature to r and s values\n */\nexport function parseDERSignature(signature: Uint8Array): { r: Uint8Array; s: Uint8Array } {\n let offset = 0;\n\n if (signature[offset++] !== 0x30) {\n throw new Error('Invalid signature format');\n }\n\n // Skip total length\n offset++;\n\n if (signature[offset++] !== 0x02) {\n throw new Error('Invalid signature format');\n }\n\n const rLength = signature[offset++];\n if (rLength === undefined) {\n throw new Error('Invalid signature format: missing r length');\n }\n let r = signature.slice(offset, offset + rLength);\n offset += rLength;\n\n // Remove leading zero if present (for positive number representation)\n if (r[0] === 0x00 && r.length > 32) {\n r = r.slice(1);\n }\n // Pad to 32 bytes if needed\n if (r.length < 32) {\n const padded = new Uint8Array(32);\n padded.set(r, 32 - r.length);\n r = padded;\n }\n\n if (signature[offset++] !== 0x02) {\n throw new Error('Invalid signature format');\n }\n\n const sLength = signature[offset++];\n if (sLength === undefined) {\n throw new Error('Invalid signature format: missing s length');\n }\n let s = signature.slice(offset, offset + sLength);\n\n // Remove leading zero if present\n if (s[0] === 0x00 && s.length > 32) {\n s = s.slice(1);\n }\n // Pad to 32 bytes if needed\n if (s.length < 32) {\n const padded = new Uint8Array(32);\n padded.set(s, 32 - s.length);\n s = padded;\n }\n\n return { r, s };\n}\n\n/**\n * Encode signature for Solidity verification\n */\nexport function encodeSignatureForSolidity(r: bigint, s: bigint): string {\n return ethers.solidityPacked(['uint256', 'uint256'], [r, s]);\n}\n\n// ============================================================================\n// Key Hash Utilities\n// ============================================================================\n\n/**\n * Compute key hash from public key coordinates\n */\nexport function computeKeyHash(publicKeyX: bigint, publicKeyY: bigint): string {\n return ethers.keccak256(\n ethers.solidityPacked(['uint256', 'uint256'], [publicKeyX, publicKeyY])\n );\n}\n\n// ============================================================================\n// Chain Utilities\n// ============================================================================\n\n/**\n * Get chain config by name\n */\nexport function getChainConfig(chainName: string, testnet = true): ChainConfig | undefined {\n const chains = testnet ? TESTNET_CHAINS : MAINNET_CHAINS;\n return chains[chainName];\n}\n\n/**\n * Get chain config by Wormhole chain ID\n */\nexport function getChainByWormholeId(wormholeChainId: number, testnet = true): ChainConfig | undefined {\n const chains = testnet ? TESTNET_CHAINS : MAINNET_CHAINS;\n return Object.values(chains).find(chain => chain.wormholeChainId === wormholeChainId);\n}\n\n/**\n * Get chain config by EVM chain ID\n */\nexport function getChainByEvmId(evmChainId: number, testnet = true): ChainConfig | undefined {\n const chains = testnet ? TESTNET_CHAINS : MAINNET_CHAINS;\n return Object.values(chains).find(chain => chain.chainId === evmChainId);\n}\n\n/**\n * Check if a chain is EVM-compatible\n */\nexport function isEvmChain(wormholeChainId: number): boolean {\n // Non-EVM chains\n const nonEvmChains = new Set([1, 8, 15, 21, 22]); // Solana, Algorand, NEAR, Sui, Aptos\n return !nonEvmChains.has(wormholeChainId);\n}\n\n/**\n * Get all supported chains\n */\nexport function getSupportedChains(testnet = true): ChainConfig[] {\n const chains = testnet ? TESTNET_CHAINS : MAINNET_CHAINS;\n return Object.values(chains);\n}\n\n// ============================================================================\n// Explorer URL Utilities\n// ============================================================================\n\n/**\n * Get transaction explorer URL\n */\nexport function getTxExplorerUrl(chain: ChainConfig, txHash: string): string {\n if (chain.isEvm) {\n return `${chain.explorerUrl}/tx/${txHash}`;\n }\n\n // Non-EVM chains have different URL patterns\n switch (chain.wormholeChainId) {\n case 1: // Solana\n return `${chain.explorerUrl}/tx/${txHash}?cluster=devnet`;\n case 21: // Sui\n return `${chain.explorerUrl}/tx/${txHash}`;\n case 22: // Aptos\n return `${chain.explorerUrl}/txn/${txHash}?network=testnet`;\n default:\n return `${chain.explorerUrl}/tx/${txHash}`;\n }\n}\n\n/**\n * Get address explorer URL\n */\nexport function getAddressExplorerUrl(chain: ChainConfig, address: string): string {\n if (chain.isEvm) {\n return `${chain.explorerUrl}/address/${address}`;\n }\n\n switch (chain.wormholeChainId) {\n case 1: // Solana\n return `${chain.explorerUrl}/address/${address}?cluster=devnet`;\n case 21: // Sui\n return `${chain.explorerUrl}/account/${address}`;\n case 22: // Aptos\n return `${chain.explorerUrl}/account/${address}?network=testnet`;\n default:\n return `${chain.explorerUrl}/address/${address}`;\n }\n}\n\n// ============================================================================\n// Validation Utilities\n// ============================================================================\n\n/**\n * Validate an EVM address\n */\nexport function isValidEvmAddress(address: string): boolean {\n return ethers.isAddress(address);\n}\n\n/**\n * Validate a bytes32 hex string\n */\nexport function isValidBytes32(hex: string): boolean {\n const clean = hex.replace('0x', '');\n return /^[0-9a-fA-F]{64}$/.test(clean);\n}\n\n/**\n * Validate a Wormhole chain ID\n */\nexport function isValidWormholeChainId(chainId: number): boolean {\n // Valid Wormhole chain IDs range from 1 to ~10007 (testnets)\n return chainId >= 1 && chainId <= 50000;\n}\n\n// ============================================================================\n// Retry Utilities\n// ============================================================================\n\n/**\n * Retry a function with exponential backoff\n */\nexport async function retryWithBackoff<T>(\n fn: () => Promise<T>,\n options: {\n maxRetries?: number;\n initialDelayMs?: number;\n maxDelayMs?: number;\n backoffMultiplier?: number;\n onRetry?: (attempt: number, error: Error) => void;\n } = {}\n): Promise<T> {\n const {\n maxRetries = 5,\n initialDelayMs = 1000,\n maxDelayMs = 30000,\n backoffMultiplier = 2,\n onRetry,\n } = options;\n\n let lastError: Error | undefined;\n let delay = initialDelayMs;\n\n for (let attempt = 1; attempt <= maxRetries; attempt++) {\n try {\n return await fn();\n } catch (error) {\n lastError = error as Error;\n\n if (attempt < maxRetries) {\n onRetry?.(attempt, lastError);\n await sleep(delay);\n delay = Math.min(delay * backoffMultiplier, maxDelayMs);\n }\n }\n }\n\n throw lastError ?? new Error('Retry failed');\n}\n\n// ============================================================================\n// Helpers\n// ============================================================================\n\nfunction sleep(ms: number): Promise<void> {\n return new Promise(resolve => setTimeout(resolve, ms));\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: '0x1a89da9e9f8f0bc90d8d492890bd55fb261c6277d2a95dfcac70c268d0c23dcc',\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 +1 @@
1
- {"version":3,"sources":["../src/wormhole.ts","../src/constants.ts"],"sourcesContent":["/**\n * Veridex Protocol SDK - Wormhole Utilities\n * \n * Functions for fetching VAAs, parsing messages, and interacting with Wormhole\n * \n * This module integrates with the official @wormhole-foundation/sdk patterns for\n * better chain abstraction and reliability, while providing Veridex-specific\n * utilities for payload handling and VAA management.\n */\n\nimport { ethers } from 'ethers';\nimport type { VAA, VAASignature, VeridexPayload } from './types.js';\nimport { WORMHOLE_API } from './constants.js';\n\n// ============================================================================\n// Constants\n// ============================================================================\n\n/**\n * Wormhole Consistency Levels\n * @see https://docs.wormhole.com/wormhole/reference/glossary#consistency-level\n */\nexport const CONSISTENCY_LEVELS = {\n /** Finalized - Wait for block finality (most secure) */\n FINALIZED: 200,\n /** Instant - No wait for finality (fastest, less secure) */\n INSTANT: 201,\n /** Safe - Standard finality (deprecated, use FINALIZED) */\n SAFE: 200,\n} as const;\n\n/**\n * Guardian network configuration\n */\nexport const GUARDIAN_CONFIG = {\n /** Total number of guardians in mainnet */\n MAINNET_GUARDIAN_COUNT: 19,\n /** Required signatures for mainnet quorum (13/19) */\n MAINNET_QUORUM: 13,\n /** Total number of guardians in testnet */\n TESTNET_GUARDIAN_COUNT: 1,\n /** Required signatures for testnet quorum */\n TESTNET_QUORUM: 1,\n} as const;\n\n// ============================================================================\n// Types\n// ============================================================================\n\nexport interface FetchVAAOptions {\n testnet?: boolean;\n maxRetries?: number;\n retryDelayMs?: number;\n onRetry?: (attempt: number, maxRetries: number) => void;\n}\n\nexport interface WaitForSignaturesOptions {\n testnet?: boolean;\n requiredSignatures?: number;\n maxWaitMs?: number;\n checkIntervalMs?: number;\n onProgress?: (currentSignatures: number, required: number) => void;\n}\n\n// ============================================================================\n// VAA Fetching\n// ============================================================================\n\n/**\n * Fetch a VAA from Wormhole guardians by sequence number\n * \n * @example\n * ```ts\n * const vaa = await fetchVAA(\n * WORMHOLE_CHAIN_IDS.TESTNET.BASE_SEPOLIA,\n * '0x000...hubAddress',\n * 97n,\n * { testnet: true }\n * );\n * ```\n */\nexport async function fetchVAA(\n emitterChain: number,\n emitterAddress: string,\n sequence: bigint,\n options: FetchVAAOptions = {}\n): Promise<string> {\n const {\n testnet = true,\n maxRetries = 30,\n retryDelayMs = 2000,\n onRetry,\n } = options;\n\n const apiBase = testnet ? WORMHOLE_API.TESTNET : WORMHOLE_API.MAINNET;\n const normalizedEmitter = normalizeEmitterAddress(emitterAddress);\n const url = `${apiBase}/api/v1/vaas/${emitterChain}/${normalizedEmitter}/${sequence.toString()}`;\n\n for (let i = 0; i < maxRetries; i++) {\n try {\n const response = await fetch(url);\n\n if (response.ok) {\n const data = await response.json() as { data?: { vaa?: string } };\n if (data.data?.vaa) {\n return data.data.vaa;\n }\n }\n\n if (i < maxRetries - 1) {\n onRetry?.(i + 1, maxRetries);\n await sleep(retryDelayMs);\n }\n } catch {\n if (i < maxRetries - 1) {\n onRetry?.(i + 1, maxRetries);\n await sleep(retryDelayMs);\n }\n }\n }\n\n throw new Error(`Failed to fetch VAA after ${maxRetries} attempts`);\n}\n\n/**\n * Fetch VAA by transaction hash using operations API\n * This is more reliable than the transactions API when sequence numbers don't match\n */\nexport async function fetchVAAByTxHash(\n txHash: string,\n options: {\n testnet?: boolean;\n maxRetries?: number;\n retryDelayMs?: number;\n onRetry?: (attempt: number, maxRetries: number) => void;\n } = {}\n): Promise<string> {\n const {\n testnet = true,\n maxRetries = 60,\n retryDelayMs = 3000,\n onRetry,\n } = options;\n\n const apiBase = testnet ? WORMHOLE_API.TESTNET : WORMHOLE_API.MAINNET;\n // Remove 0x prefix if present for the API\n const cleanTxHash = txHash.replace(/^0x/, '');\n const url = `${apiBase}/api/v1/operations?txHash=${cleanTxHash}`;\n\n for (let i = 0; i < maxRetries; i++) {\n try {\n const response = await fetch(url);\n\n if (response.ok) {\n const data = await response.json() as { \n operations?: Array<{ \n vaa?: { raw?: string }; \n sequence?: string;\n }>;\n };\n if (data.operations && data.operations.length > 0) {\n const operation = data.operations[0];\n if (operation.vaa?.raw) {\n return operation.vaa.raw;\n }\n }\n }\n\n if (i < maxRetries - 1) {\n onRetry?.(i + 1, maxRetries);\n await sleep(retryDelayMs);\n }\n } catch {\n if (i < maxRetries - 1) {\n onRetry?.(i + 1, maxRetries);\n await sleep(retryDelayMs);\n }\n }\n }\n\n throw new Error(`Failed to fetch VAA after ${maxRetries} attempts`);\n}\n\n/**\n * Fetch VAA by transaction hash using transactions API (fallback)\n */\nexport async function fetchVAAByTxHashFallback(\n txHash: string,\n options: {\n testnet?: boolean;\n maxRetries?: number;\n retryDelayMs?: number;\n onRetry?: (attempt: number, maxRetries: number) => void;\n } = {}\n): Promise<string> {\n const {\n testnet = true,\n maxRetries = 30,\n retryDelayMs = 2000,\n onRetry,\n } = options;\n\n const apiBase = testnet ? WORMHOLE_API.TESTNET : WORMHOLE_API.MAINNET;\n const url = `${apiBase}/api/v1/transactions/${txHash}`;\n\n for (let i = 0; i < maxRetries; i++) {\n try {\n const response = await fetch(url);\n\n if (response.ok) {\n const data = await response.json() as { data?: { globalTx?: { originTx?: { vaaId?: string } } } };\n if (data.data?.globalTx?.originTx?.vaaId) {\n const vaaId = data.data.globalTx.originTx.vaaId;\n const vaaUrl = `${apiBase}/api/v1/vaas/${vaaId}`;\n const vaaResponse = await fetch(vaaUrl);\n\n if (vaaResponse.ok) {\n const vaaData = await vaaResponse.json() as { data?: { vaa?: string } };\n if (vaaData.data?.vaa) {\n return vaaData.data.vaa;\n }\n }\n }\n }\n\n if (i < maxRetries - 1) {\n onRetry?.(i + 1, maxRetries);\n await sleep(retryDelayMs);\n }\n } catch {\n if (i < maxRetries - 1) {\n onRetry?.(i + 1, maxRetries);\n await sleep(retryDelayMs);\n }\n }\n }\n\n throw new Error(`Failed to fetch VAA after ${maxRetries} attempts`);\n}\n\n// ============================================================================\n// VAA Parsing\n// ============================================================================\n\n/**\n * Parse a base64-encoded VAA into its components\n */\nexport function parseVAA(vaaBase64: string): VAA {\n const vaaBytes = Buffer.from(vaaBase64, 'base64');\n return parseVAABytes(vaaBytes);\n}\n\n/**\n * Parse raw VAA bytes into its components\n */\nexport function parseVAABytes(vaaBytes: Buffer): VAA {\n let offset = 0;\n\n // Version (1 byte)\n const version = vaaBytes.readUInt8(offset);\n offset += 1;\n\n // Guardian set index (4 bytes)\n const guardianSetIndex = vaaBytes.readUInt32BE(offset);\n offset += 4;\n\n // Number of signatures (1 byte)\n const numSignatures = vaaBytes.readUInt8(offset);\n offset += 1;\n\n // Parse signatures (66 bytes each: 1 guardian index + 65 signature)\n const signatures: VAASignature[] = [];\n for (let i = 0; i < numSignatures; i++) {\n const guardianIndex = vaaBytes.readUInt8(offset);\n offset += 1;\n const signature = '0x' + vaaBytes.subarray(offset, offset + 65).toString('hex');\n offset += 65;\n signatures.push({ guardianIndex, signature });\n }\n\n // Mark the start of the body (for hash calculation)\n const bodyOffset = offset;\n\n // Timestamp (4 bytes)\n const timestamp = vaaBytes.readUInt32BE(offset);\n offset += 4;\n\n // Nonce (4 bytes)\n const nonce = vaaBytes.readUInt32BE(offset);\n offset += 4;\n\n // Emitter chain (2 bytes)\n const emitterChain = vaaBytes.readUInt16BE(offset);\n offset += 2;\n\n // Emitter address (32 bytes)\n const emitterAddress = '0x' + vaaBytes.subarray(offset, offset + 32).toString('hex');\n offset += 32;\n\n // Sequence (8 bytes)\n const sequence = vaaBytes.readBigUInt64BE(offset);\n offset += 8;\n\n // Consistency level (1 byte)\n const consistencyLevel = vaaBytes.readUInt8(offset);\n offset += 1;\n\n // Payload (remaining bytes)\n const payload = '0x' + vaaBytes.subarray(offset).toString('hex');\n\n // Calculate VAA body hash (used for verification on destination chains)\n const body = vaaBytes.subarray(bodyOffset);\n const hash = ethers.keccak256(ethers.keccak256(body));\n\n return {\n version,\n guardianSetIndex,\n signatures,\n timestamp,\n nonce,\n emitterChain,\n emitterAddress,\n sequence,\n consistencyLevel,\n payload,\n hash,\n };\n}\n\n/**\n * Parse a Veridex-specific payload from a VAA\n */\nexport function parseVeridexPayload(payloadHex: string): VeridexPayload {\n const payload = Buffer.from(payloadHex.replace('0x', ''), 'hex');\n let offset = 0;\n\n // Version (1 byte)\n const version = payload.readUInt8(offset);\n offset += 1;\n\n // User key hash (32 bytes)\n const userKeyHash = '0x' + payload.subarray(offset, offset + 32).toString('hex');\n offset += 32;\n\n // Target chain (2 bytes)\n const targetChain = payload.readUInt16BE(offset);\n offset += 2;\n\n // Nonce (32 bytes)\n const nonce = BigInt('0x' + payload.subarray(offset, offset + 32).toString('hex'));\n offset += 32;\n\n // Public key X (32 bytes)\n const publicKeyX = BigInt('0x' + payload.subarray(offset, offset + 32).toString('hex'));\n offset += 32;\n\n // Public key Y (32 bytes)\n const publicKeyY = BigInt('0x' + payload.subarray(offset, offset + 32).toString('hex'));\n offset += 32;\n\n // Action payload (remaining bytes)\n const actionPayload = '0x' + payload.subarray(offset).toString('hex');\n\n return {\n version,\n userKeyHash,\n targetChain,\n nonce,\n publicKeyX,\n publicKeyY,\n actionPayload,\n };\n}\n\n// ============================================================================\n// VAA Encoding\n// ============================================================================\n\n/**\n * Encode a VAA back to bytes for on-chain submission\n */\nexport function encodeVAAToBytes(vaaBase64: string): string {\n const vaaBytes = Buffer.from(vaaBase64, 'base64');\n return '0x' + vaaBytes.toString('hex');\n}\n\n/**\n * Encode VAA to bytes for Solana (returns Uint8Array)\n */\nexport function encodeVAAForSolana(vaaBase64: string): Uint8Array {\n return new Uint8Array(Buffer.from(vaaBase64, 'base64'));\n}\n\n// ============================================================================\n// Address Utilities\n// ============================================================================\n\n/**\n * Normalize an address to a 32-byte Wormhole emitter address format\n */\nexport function normalizeEmitterAddress(address: string): string {\n let hex = address.replace('0x', '');\n while (hex.length < 64) {\n hex = '0' + hex;\n }\n return hex;\n}\n\n/**\n * Convert a 32-byte emitter address back to a 20-byte EVM address\n */\nexport function emitterToEvmAddress(emitterHex: string): string {\n const hex = emitterHex.replace('0x', '');\n return '0x' + hex.slice(-40);\n}\n\n// ============================================================================\n// Transaction Utilities\n// ============================================================================\n\n/**\n * Extract the VAA sequence from a transaction receipt\n */\nexport async function getSequenceFromTxReceipt(\n provider: ethers.Provider,\n txHash: string,\n wormholeCoreBridge: string\n): Promise<bigint> {\n const receipt = await provider.getTransactionReceipt(txHash);\n if (!receipt) {\n throw new Error(`Transaction receipt not found: ${txHash}`);\n }\n\n const LOG_MESSAGE_PUBLISHED_TOPIC = ethers.id(\n 'LogMessagePublished(address,uint64,uint32,bytes,uint8)'\n );\n\n for (const log of receipt.logs) {\n if (log.address.toLowerCase() === wormholeCoreBridge.toLowerCase()) {\n if (log.topics[0] === LOG_MESSAGE_PUBLISHED_TOPIC && log.topics[1]) {\n const sequence = BigInt(log.topics[1]);\n return sequence;\n }\n }\n }\n\n throw new Error('LogMessagePublished event not found in transaction');\n}\n\n/**\n * Wait for a Wormhole message to be signed by guardians\n * \n * @example\n * ```ts\n * const vaa = await waitForGuardianSignatures(\n * WORMHOLE_CHAIN_IDS.TESTNET.BASE_SEPOLIA,\n * hubEmitter,\n * 97n,\n * {\n * testnet: true,\n * onProgress: (current, required) => console.log(`${current}/${required} signatures`)\n * }\n * );\n * ```\n */\nexport async function waitForGuardianSignatures(\n emitterChain: number,\n emitterAddress: string,\n sequence: bigint,\n options: WaitForSignaturesOptions = {}\n): Promise<VAA> {\n const {\n testnet = true,\n requiredSignatures = testnet ? GUARDIAN_CONFIG.TESTNET_QUORUM : GUARDIAN_CONFIG.MAINNET_QUORUM,\n maxWaitMs = 120000,\n checkIntervalMs = 5000,\n onProgress,\n } = options;\n\n const startTime = Date.now();\n\n while (Date.now() - startTime < maxWaitMs) {\n try {\n const vaaBase64 = await fetchVAA(emitterChain, emitterAddress, sequence, {\n testnet,\n maxRetries: 1,\n retryDelayMs: 0,\n });\n const vaa = parseVAA(vaaBase64);\n\n onProgress?.(vaa.signatures.length, requiredSignatures);\n\n if (vaa.signatures.length >= requiredSignatures) {\n return vaa;\n }\n } catch {\n // VAA not available yet, continue waiting\n }\n\n await sleep(checkIntervalMs);\n }\n\n throw new Error(`Timeout waiting for guardian signatures after ${maxWaitMs / 1000}s`);\n}\n\n// ============================================================================\n// Wormhole Core Bridge Addresses\n// ============================================================================\n\n/**\n * Get the Wormhole Core Bridge contract address for a chain\n */\nexport function getWormholeCoreBridge(wormholeChainId: number, testnet = true): string {\n const testnetBridges: Record<number, string> = {\n 10004: '0x79A1027a6A159502049F10906D333EC57E95F083', // Base Sepolia\n 10005: '0x31377888146f3253211EFEf5c676D41ECe7D58Fe', // Optimism Sepolia\n 10003: '0x6b9C8671cdDC8dEab9c719bB87cBd3e782bA6a35', // Arbitrum Sepolia\n 1: '3u8hJUVTA4jH1wYAyUur7FFZVQ8H635K3tSHHF4ssjQ5', // Solana Devnet\n 22: '0x5bc11445584a763c1fa7ed39081f1b920954da14e04b32440cba863d03e19625', // Aptos Testnet\n 21: '0x31358d198147da50db32eda2562951d53973a0c0ad5ed738e9b17d88b213d790', // Sui Testnet\n };\n\n const mainnetBridges: Record<number, string> = {\n 2: '0x98f3c9e6E3fAce36bAAd05FE09d375Ef1464288B', // Ethereum\n 30: '0xbebdb6C8ddC678FfA9f8748f85C815C556Dd8ac6', // Base\n 24: '0xEe91C335eab126dF5fDB3797EA9d6aD93aeC9722', // Optimism\n 23: '0xa5f208e072434bC67592E4C49C1B991BA79BCA46', // Arbitrum\n 5: '0x7A4B5a56256163F07b2C80A7cA55aBE66c4ec4d7', // Polygon\n 1: 'worm2ZoG2kUd4vFXhvjh93UUH596ayRfgQ2MgjNMTth', // Solana\n 22: '0x5bc11445584a763c1fa7ed39081f1b920954da14e04b32440cba863d03e19625', // Aptos\n 21: '0xaeab97f96cf9877fee2883315d459552b2b921edc16d7ceac6eab944dd88919c', // Sui\n };\n\n const bridges = testnet ? testnetBridges : mainnetBridges;\n return bridges[wormholeChainId] ?? '';\n}\n\n/**\n * Get the Wormhole Token Bridge contract address for a chain\n */\nexport function getWormholeTokenBridge(wormholeChainId: number, testnet = true): string {\n const testnetBridges: Record<number, string> = {\n 10004: '0x86F55A04690fd7815A3D802bD587e83eA888B239', // Base Sepolia\n 10005: '0x99737Ec4B815d816c49A385943baf0380e75c0Ac', // Optimism Sepolia\n 10003: '0xC7A204bDBFe983FCD8d8E61D02b475D4073fF97e', // Arbitrum Sepolia\n };\n\n const mainnetBridges: Record<number, string> = {\n 2: '0x3ee18B2214AFF97000D974cf647E7C347E8fa585', // Ethereum\n 30: '0x8d2de8d2f73F1F4cAB472AC9A881C9b123C79627', // Base\n 24: '0x1D68124e65faFC907325e3EDbF8c4d84499DAa8b', // Optimism\n 23: '0x0b2402144Bb366A632D14B83F244D2e0e21bD39c', // Arbitrum\n 5: '0x5a58505a96D1dbf8dF91cB21B54419FC36e93fdE', // Polygon\n };\n\n const bridges = testnet ? testnetBridges : mainnetBridges;\n return bridges[wormholeChainId] ?? '';\n}\n\n/**\n * Get the Wormhole Relayer contract address for a chain\n */\nexport function getWormholeRelayer(wormholeChainId: number, testnet = true): string {\n const testnetRelayers: Record<number, string> = {\n 10004: '0x93BAD53DDfB6132b0aC8E37f6029163E63372cEE', // Base Sepolia\n 10005: '0x93BAD53DDfB6132b0aC8E37f6029163E63372cEE', // Optimism Sepolia\n 10003: '0x7B1bD7a6b4E61c2a123AC6BC2cbfC614437D0470', // Arbitrum Sepolia\n };\n\n const mainnetRelayers: Record<number, string> = {\n 2: '0x27428DD2d3DD32A4D7f7C497eAaa23130d894911', // Ethereum\n 30: '0x706F82e9bb5b0813501714Ab5974216704980e31', // Base\n 24: '0x27428DD2d3DD32A4D7f7C497eAaa23130d894911', // Optimism\n 23: '0x27428DD2d3DD32A4D7f7C497eAaa23130d894911', // Arbitrum\n 5: '0x27428DD2d3DD32A4D7f7C497eAaa23130d894911', // Polygon\n };\n\n const relayers = testnet ? testnetRelayers : mainnetRelayers;\n return relayers[wormholeChainId] ?? '';\n}\n\n/**\n * Check if a chain supports Wormhole Relayer\n */\nexport function supportsRelayer(wormholeChainId: number, testnet = true): boolean {\n return getWormholeRelayer(wormholeChainId, testnet) !== '';\n}\n\n/**\n * Get chain name from Wormhole chain ID\n */\nexport function getChainName(wormholeChainId: number): string {\n const names: Record<number, string> = {\n 1: 'Solana',\n 2: 'Ethereum',\n 4: 'BSC',\n 5: 'Polygon',\n 6: 'Avalanche',\n 10: 'Fantom',\n 21: 'Sui',\n 22: 'Aptos',\n 23: 'Arbitrum',\n 24: 'Optimism',\n 30: 'Base',\n 10002: 'Sepolia',\n 10003: 'Arbitrum Sepolia',\n 10004: 'Base Sepolia',\n 10005: 'Optimism Sepolia',\n };\n return names[wormholeChainId] ?? `Chain ${wormholeChainId}`;\n}\n\n// ============================================================================\n// VAA Validation\n// ============================================================================\n\n/**\n * Validate that a VAA has sufficient signatures for the given network\n */\nexport function hasQuorum(vaa: VAA, testnet = true): boolean {\n const required = testnet ? GUARDIAN_CONFIG.TESTNET_QUORUM : GUARDIAN_CONFIG.MAINNET_QUORUM;\n return vaa.signatures.length >= required;\n}\n\n/**\n * Validate VAA emitter matches expected source\n */\nexport function validateEmitter(\n vaa: VAA,\n expectedChain: number,\n expectedAddress: string\n): boolean {\n const normalizedExpected = '0x' + normalizeEmitterAddress(expectedAddress);\n return (\n vaa.emitterChain === expectedChain &&\n vaa.emitterAddress.toLowerCase() === normalizedExpected.toLowerCase()\n );\n}\n\n/**\n * Convert an EVM address to bytes32 format (for Wormhole)\n */\nexport function evmAddressToBytes32(address: string): string {\n const hex = address.replace('0x', '').toLowerCase();\n return '0x' + hex.padStart(64, '0');\n}\n\n// ============================================================================\n// Helpers\n// ============================================================================\n\nfunction sleep(ms: number): Promise<void> {\n return new Promise(resolve => setTimeout(resolve, ms));\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: '0x40D9B16094808Fa48e73598E31AB964Cf15b475f',\n vaultImplementation: '0xcBEb49b0109E61c1C69C51D5D9483A3aD6D18258',\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: '0xAbB421166E648953CDBE93c0078a0A794c56Fb84',\n vaultImplementation: '0xDCD7daEf1AC06f4a8392957cca4834F7a16c058D',\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: '0x1a89da9e9f8f0bc90d8d492890bd55fb261c6277d2a95dfcac70c268d0c23dcc',\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/wormhole.ts","../src/constants.ts"],"sourcesContent":["/**\n * Veridex Protocol SDK - Wormhole Utilities\n * \n * Functions for fetching VAAs, parsing messages, and interacting with Wormhole\n * \n * This module integrates with the official @wormhole-foundation/sdk patterns for\n * better chain abstraction and reliability, while providing Veridex-specific\n * utilities for payload handling and VAA management.\n */\n\nimport { ethers } from 'ethers';\nimport type { VAA, VAASignature, VeridexPayload } from './types.js';\nimport { WORMHOLE_API } from './constants.js';\n\n// ============================================================================\n// Constants\n// ============================================================================\n\n/**\n * Wormhole Consistency Levels\n * @see https://docs.wormhole.com/wormhole/reference/glossary#consistency-level\n */\nexport const CONSISTENCY_LEVELS = {\n /** Finalized - Wait for block finality (most secure) */\n FINALIZED: 200,\n /** Instant - No wait for finality (fastest, less secure) */\n INSTANT: 201,\n /** Safe - Standard finality (deprecated, use FINALIZED) */\n SAFE: 200,\n} as const;\n\n/**\n * Guardian network configuration\n */\nexport const GUARDIAN_CONFIG = {\n /** Total number of guardians in mainnet */\n MAINNET_GUARDIAN_COUNT: 19,\n /** Required signatures for mainnet quorum (13/19) */\n MAINNET_QUORUM: 13,\n /** Total number of guardians in testnet */\n TESTNET_GUARDIAN_COUNT: 1,\n /** Required signatures for testnet quorum */\n TESTNET_QUORUM: 1,\n} as const;\n\n// ============================================================================\n// Types\n// ============================================================================\n\nexport interface FetchVAAOptions {\n testnet?: boolean;\n maxRetries?: number;\n retryDelayMs?: number;\n onRetry?: (attempt: number, maxRetries: number) => void;\n}\n\nexport interface WaitForSignaturesOptions {\n testnet?: boolean;\n requiredSignatures?: number;\n maxWaitMs?: number;\n checkIntervalMs?: number;\n onProgress?: (currentSignatures: number, required: number) => void;\n}\n\n// ============================================================================\n// VAA Fetching\n// ============================================================================\n\n/**\n * Fetch a VAA from Wormhole guardians by sequence number\n * \n * @example\n * ```ts\n * const vaa = await fetchVAA(\n * WORMHOLE_CHAIN_IDS.TESTNET.BASE_SEPOLIA,\n * '0x000...hubAddress',\n * 97n,\n * { testnet: true }\n * );\n * ```\n */\nexport async function fetchVAA(\n emitterChain: number,\n emitterAddress: string,\n sequence: bigint,\n options: FetchVAAOptions = {}\n): Promise<string> {\n const {\n testnet = true,\n maxRetries = 30,\n retryDelayMs = 2000,\n onRetry,\n } = options;\n\n const apiBase = testnet ? WORMHOLE_API.TESTNET : WORMHOLE_API.MAINNET;\n const normalizedEmitter = normalizeEmitterAddress(emitterAddress);\n const url = `${apiBase}/api/v1/vaas/${emitterChain}/${normalizedEmitter}/${sequence.toString()}`;\n\n for (let i = 0; i < maxRetries; i++) {\n try {\n const response = await fetch(url);\n\n if (response.ok) {\n const data = await response.json() as { data?: { vaa?: string } };\n if (data.data?.vaa) {\n return data.data.vaa;\n }\n }\n\n if (i < maxRetries - 1) {\n onRetry?.(i + 1, maxRetries);\n await sleep(retryDelayMs);\n }\n } catch {\n if (i < maxRetries - 1) {\n onRetry?.(i + 1, maxRetries);\n await sleep(retryDelayMs);\n }\n }\n }\n\n throw new Error(`Failed to fetch VAA after ${maxRetries} attempts`);\n}\n\n/**\n * Fetch VAA by transaction hash using operations API\n * This is more reliable than the transactions API when sequence numbers don't match\n */\nexport async function fetchVAAByTxHash(\n txHash: string,\n options: {\n testnet?: boolean;\n maxRetries?: number;\n retryDelayMs?: number;\n onRetry?: (attempt: number, maxRetries: number) => void;\n } = {}\n): Promise<string> {\n const {\n testnet = true,\n maxRetries = 60,\n retryDelayMs = 3000,\n onRetry,\n } = options;\n\n const apiBase = testnet ? WORMHOLE_API.TESTNET : WORMHOLE_API.MAINNET;\n // Remove 0x prefix if present for the API\n const cleanTxHash = txHash.replace(/^0x/, '');\n const url = `${apiBase}/api/v1/operations?txHash=${cleanTxHash}`;\n\n for (let i = 0; i < maxRetries; i++) {\n try {\n const response = await fetch(url);\n\n if (response.ok) {\n const data = await response.json() as { \n operations?: Array<{ \n vaa?: { raw?: string }; \n sequence?: string;\n }>;\n };\n if (data.operations && data.operations.length > 0) {\n const operation = data.operations[0];\n if (operation.vaa?.raw) {\n return operation.vaa.raw;\n }\n }\n }\n\n if (i < maxRetries - 1) {\n onRetry?.(i + 1, maxRetries);\n await sleep(retryDelayMs);\n }\n } catch {\n if (i < maxRetries - 1) {\n onRetry?.(i + 1, maxRetries);\n await sleep(retryDelayMs);\n }\n }\n }\n\n throw new Error(`Failed to fetch VAA after ${maxRetries} attempts`);\n}\n\n/**\n * Fetch VAA by transaction hash using transactions API (fallback)\n */\nexport async function fetchVAAByTxHashFallback(\n txHash: string,\n options: {\n testnet?: boolean;\n maxRetries?: number;\n retryDelayMs?: number;\n onRetry?: (attempt: number, maxRetries: number) => void;\n } = {}\n): Promise<string> {\n const {\n testnet = true,\n maxRetries = 30,\n retryDelayMs = 2000,\n onRetry,\n } = options;\n\n const apiBase = testnet ? WORMHOLE_API.TESTNET : WORMHOLE_API.MAINNET;\n const url = `${apiBase}/api/v1/transactions/${txHash}`;\n\n for (let i = 0; i < maxRetries; i++) {\n try {\n const response = await fetch(url);\n\n if (response.ok) {\n const data = await response.json() as { data?: { globalTx?: { originTx?: { vaaId?: string } } } };\n if (data.data?.globalTx?.originTx?.vaaId) {\n const vaaId = data.data.globalTx.originTx.vaaId;\n const vaaUrl = `${apiBase}/api/v1/vaas/${vaaId}`;\n const vaaResponse = await fetch(vaaUrl);\n\n if (vaaResponse.ok) {\n const vaaData = await vaaResponse.json() as { data?: { vaa?: string } };\n if (vaaData.data?.vaa) {\n return vaaData.data.vaa;\n }\n }\n }\n }\n\n if (i < maxRetries - 1) {\n onRetry?.(i + 1, maxRetries);\n await sleep(retryDelayMs);\n }\n } catch {\n if (i < maxRetries - 1) {\n onRetry?.(i + 1, maxRetries);\n await sleep(retryDelayMs);\n }\n }\n }\n\n throw new Error(`Failed to fetch VAA after ${maxRetries} attempts`);\n}\n\n// ============================================================================\n// VAA Parsing\n// ============================================================================\n\n/**\n * Parse a base64-encoded VAA into its components\n */\nexport function parseVAA(vaaBase64: string): VAA {\n const vaaBytes = Buffer.from(vaaBase64, 'base64');\n return parseVAABytes(vaaBytes);\n}\n\n/**\n * Parse raw VAA bytes into its components\n */\nexport function parseVAABytes(vaaBytes: Buffer): VAA {\n let offset = 0;\n\n // Version (1 byte)\n const version = vaaBytes.readUInt8(offset);\n offset += 1;\n\n // Guardian set index (4 bytes)\n const guardianSetIndex = vaaBytes.readUInt32BE(offset);\n offset += 4;\n\n // Number of signatures (1 byte)\n const numSignatures = vaaBytes.readUInt8(offset);\n offset += 1;\n\n // Parse signatures (66 bytes each: 1 guardian index + 65 signature)\n const signatures: VAASignature[] = [];\n for (let i = 0; i < numSignatures; i++) {\n const guardianIndex = vaaBytes.readUInt8(offset);\n offset += 1;\n const signature = '0x' + vaaBytes.subarray(offset, offset + 65).toString('hex');\n offset += 65;\n signatures.push({ guardianIndex, signature });\n }\n\n // Mark the start of the body (for hash calculation)\n const bodyOffset = offset;\n\n // Timestamp (4 bytes)\n const timestamp = vaaBytes.readUInt32BE(offset);\n offset += 4;\n\n // Nonce (4 bytes)\n const nonce = vaaBytes.readUInt32BE(offset);\n offset += 4;\n\n // Emitter chain (2 bytes)\n const emitterChain = vaaBytes.readUInt16BE(offset);\n offset += 2;\n\n // Emitter address (32 bytes)\n const emitterAddress = '0x' + vaaBytes.subarray(offset, offset + 32).toString('hex');\n offset += 32;\n\n // Sequence (8 bytes)\n const sequence = vaaBytes.readBigUInt64BE(offset);\n offset += 8;\n\n // Consistency level (1 byte)\n const consistencyLevel = vaaBytes.readUInt8(offset);\n offset += 1;\n\n // Payload (remaining bytes)\n const payload = '0x' + vaaBytes.subarray(offset).toString('hex');\n\n // Calculate VAA body hash (used for verification on destination chains)\n const body = vaaBytes.subarray(bodyOffset);\n const hash = ethers.keccak256(ethers.keccak256(body));\n\n return {\n version,\n guardianSetIndex,\n signatures,\n timestamp,\n nonce,\n emitterChain,\n emitterAddress,\n sequence,\n consistencyLevel,\n payload,\n hash,\n };\n}\n\n/**\n * Parse a Veridex-specific payload from a VAA\n */\nexport function parseVeridexPayload(payloadHex: string): VeridexPayload {\n const payload = Buffer.from(payloadHex.replace('0x', ''), 'hex');\n let offset = 0;\n\n // Version (1 byte)\n const version = payload.readUInt8(offset);\n offset += 1;\n\n // User key hash (32 bytes)\n const userKeyHash = '0x' + payload.subarray(offset, offset + 32).toString('hex');\n offset += 32;\n\n // Target chain (2 bytes)\n const targetChain = payload.readUInt16BE(offset);\n offset += 2;\n\n // Nonce (32 bytes)\n const nonce = BigInt('0x' + payload.subarray(offset, offset + 32).toString('hex'));\n offset += 32;\n\n // Public key X (32 bytes)\n const publicKeyX = BigInt('0x' + payload.subarray(offset, offset + 32).toString('hex'));\n offset += 32;\n\n // Public key Y (32 bytes)\n const publicKeyY = BigInt('0x' + payload.subarray(offset, offset + 32).toString('hex'));\n offset += 32;\n\n // Action payload (remaining bytes)\n const actionPayload = '0x' + payload.subarray(offset).toString('hex');\n\n return {\n version,\n userKeyHash,\n targetChain,\n nonce,\n publicKeyX,\n publicKeyY,\n actionPayload,\n };\n}\n\n// ============================================================================\n// VAA Encoding\n// ============================================================================\n\n/**\n * Encode a VAA back to bytes for on-chain submission\n */\nexport function encodeVAAToBytes(vaaBase64: string): string {\n const vaaBytes = Buffer.from(vaaBase64, 'base64');\n return '0x' + vaaBytes.toString('hex');\n}\n\n/**\n * Encode VAA to bytes for Solana (returns Uint8Array)\n */\nexport function encodeVAAForSolana(vaaBase64: string): Uint8Array {\n return new Uint8Array(Buffer.from(vaaBase64, 'base64'));\n}\n\n// ============================================================================\n// Address Utilities\n// ============================================================================\n\n/**\n * Normalize an address to a 32-byte Wormhole emitter address format\n */\nexport function normalizeEmitterAddress(address: string): string {\n let hex = address.replace('0x', '');\n while (hex.length < 64) {\n hex = '0' + hex;\n }\n return hex;\n}\n\n/**\n * Convert a 32-byte emitter address back to a 20-byte EVM address\n */\nexport function emitterToEvmAddress(emitterHex: string): string {\n const hex = emitterHex.replace('0x', '');\n return '0x' + hex.slice(-40);\n}\n\n// ============================================================================\n// Transaction Utilities\n// ============================================================================\n\n/**\n * Extract the VAA sequence from a transaction receipt\n */\nexport async function getSequenceFromTxReceipt(\n provider: ethers.Provider,\n txHash: string,\n wormholeCoreBridge: string\n): Promise<bigint> {\n const receipt = await provider.getTransactionReceipt(txHash);\n if (!receipt) {\n throw new Error(`Transaction receipt not found: ${txHash}`);\n }\n\n const LOG_MESSAGE_PUBLISHED_TOPIC = ethers.id(\n 'LogMessagePublished(address,uint64,uint32,bytes,uint8)'\n );\n\n for (const log of receipt.logs) {\n if (log.address.toLowerCase() === wormholeCoreBridge.toLowerCase()) {\n if (log.topics[0] === LOG_MESSAGE_PUBLISHED_TOPIC && log.topics[1]) {\n const sequence = BigInt(log.topics[1]);\n return sequence;\n }\n }\n }\n\n throw new Error('LogMessagePublished event not found in transaction');\n}\n\n/**\n * Wait for a Wormhole message to be signed by guardians\n * \n * @example\n * ```ts\n * const vaa = await waitForGuardianSignatures(\n * WORMHOLE_CHAIN_IDS.TESTNET.BASE_SEPOLIA,\n * hubEmitter,\n * 97n,\n * {\n * testnet: true,\n * onProgress: (current, required) => console.log(`${current}/${required} signatures`)\n * }\n * );\n * ```\n */\nexport async function waitForGuardianSignatures(\n emitterChain: number,\n emitterAddress: string,\n sequence: bigint,\n options: WaitForSignaturesOptions = {}\n): Promise<VAA> {\n const {\n testnet = true,\n requiredSignatures = testnet ? GUARDIAN_CONFIG.TESTNET_QUORUM : GUARDIAN_CONFIG.MAINNET_QUORUM,\n maxWaitMs = 120000,\n checkIntervalMs = 5000,\n onProgress,\n } = options;\n\n const startTime = Date.now();\n\n while (Date.now() - startTime < maxWaitMs) {\n try {\n const vaaBase64 = await fetchVAA(emitterChain, emitterAddress, sequence, {\n testnet,\n maxRetries: 1,\n retryDelayMs: 0,\n });\n const vaa = parseVAA(vaaBase64);\n\n onProgress?.(vaa.signatures.length, requiredSignatures);\n\n if (vaa.signatures.length >= requiredSignatures) {\n return vaa;\n }\n } catch {\n // VAA not available yet, continue waiting\n }\n\n await sleep(checkIntervalMs);\n }\n\n throw new Error(`Timeout waiting for guardian signatures after ${maxWaitMs / 1000}s`);\n}\n\n// ============================================================================\n// Wormhole Core Bridge Addresses\n// ============================================================================\n\n/**\n * Get the Wormhole Core Bridge contract address for a chain\n */\nexport function getWormholeCoreBridge(wormholeChainId: number, testnet = true): string {\n const testnetBridges: Record<number, string> = {\n 10004: '0x79A1027a6A159502049F10906D333EC57E95F083', // Base Sepolia\n 10005: '0x31377888146f3253211EFEf5c676D41ECe7D58Fe', // Optimism Sepolia\n 10003: '0x6b9C8671cdDC8dEab9c719bB87cBd3e782bA6a35', // Arbitrum Sepolia\n 1: '3u8hJUVTA4jH1wYAyUur7FFZVQ8H635K3tSHHF4ssjQ5', // Solana Devnet\n 22: '0x5bc11445584a763c1fa7ed39081f1b920954da14e04b32440cba863d03e19625', // Aptos Testnet\n 21: '0x31358d198147da50db32eda2562951d53973a0c0ad5ed738e9b17d88b213d790', // Sui Testnet\n };\n\n const mainnetBridges: Record<number, string> = {\n 2: '0x98f3c9e6E3fAce36bAAd05FE09d375Ef1464288B', // Ethereum\n 30: '0xbebdb6C8ddC678FfA9f8748f85C815C556Dd8ac6', // Base\n 24: '0xEe91C335eab126dF5fDB3797EA9d6aD93aeC9722', // Optimism\n 23: '0xa5f208e072434bC67592E4C49C1B991BA79BCA46', // Arbitrum\n 5: '0x7A4B5a56256163F07b2C80A7cA55aBE66c4ec4d7', // Polygon\n 1: 'worm2ZoG2kUd4vFXhvjh93UUH596ayRfgQ2MgjNMTth', // Solana\n 22: '0x5bc11445584a763c1fa7ed39081f1b920954da14e04b32440cba863d03e19625', // Aptos\n 21: '0xaeab97f96cf9877fee2883315d459552b2b921edc16d7ceac6eab944dd88919c', // Sui\n };\n\n const bridges = testnet ? testnetBridges : mainnetBridges;\n return bridges[wormholeChainId] ?? '';\n}\n\n/**\n * Get the Wormhole Token Bridge contract address for a chain\n */\nexport function getWormholeTokenBridge(wormholeChainId: number, testnet = true): string {\n const testnetBridges: Record<number, string> = {\n 10004: '0x86F55A04690fd7815A3D802bD587e83eA888B239', // Base Sepolia\n 10005: '0x99737Ec4B815d816c49A385943baf0380e75c0Ac', // Optimism Sepolia\n 10003: '0xC7A204bDBFe983FCD8d8E61D02b475D4073fF97e', // Arbitrum Sepolia\n };\n\n const mainnetBridges: Record<number, string> = {\n 2: '0x3ee18B2214AFF97000D974cf647E7C347E8fa585', // Ethereum\n 30: '0x8d2de8d2f73F1F4cAB472AC9A881C9b123C79627', // Base\n 24: '0x1D68124e65faFC907325e3EDbF8c4d84499DAa8b', // Optimism\n 23: '0x0b2402144Bb366A632D14B83F244D2e0e21bD39c', // Arbitrum\n 5: '0x5a58505a96D1dbf8dF91cB21B54419FC36e93fdE', // Polygon\n };\n\n const bridges = testnet ? testnetBridges : mainnetBridges;\n return bridges[wormholeChainId] ?? '';\n}\n\n/**\n * Get the Wormhole Relayer contract address for a chain\n */\nexport function getWormholeRelayer(wormholeChainId: number, testnet = true): string {\n const testnetRelayers: Record<number, string> = {\n 10004: '0x93BAD53DDfB6132b0aC8E37f6029163E63372cEE', // Base Sepolia\n 10005: '0x93BAD53DDfB6132b0aC8E37f6029163E63372cEE', // Optimism Sepolia\n 10003: '0x7B1bD7a6b4E61c2a123AC6BC2cbfC614437D0470', // Arbitrum Sepolia\n };\n\n const mainnetRelayers: Record<number, string> = {\n 2: '0x27428DD2d3DD32A4D7f7C497eAaa23130d894911', // Ethereum\n 30: '0x706F82e9bb5b0813501714Ab5974216704980e31', // Base\n 24: '0x27428DD2d3DD32A4D7f7C497eAaa23130d894911', // Optimism\n 23: '0x27428DD2d3DD32A4D7f7C497eAaa23130d894911', // Arbitrum\n 5: '0x27428DD2d3DD32A4D7f7C497eAaa23130d894911', // Polygon\n };\n\n const relayers = testnet ? testnetRelayers : mainnetRelayers;\n return relayers[wormholeChainId] ?? '';\n}\n\n/**\n * Check if a chain supports Wormhole Relayer\n */\nexport function supportsRelayer(wormholeChainId: number, testnet = true): boolean {\n return getWormholeRelayer(wormholeChainId, testnet) !== '';\n}\n\n/**\n * Get chain name from Wormhole chain ID\n */\nexport function getChainName(wormholeChainId: number): string {\n const names: Record<number, string> = {\n 1: 'Solana',\n 2: 'Ethereum',\n 4: 'BSC',\n 5: 'Polygon',\n 6: 'Avalanche',\n 10: 'Fantom',\n 21: 'Sui',\n 22: 'Aptos',\n 23: 'Arbitrum',\n 24: 'Optimism',\n 30: 'Base',\n 10002: 'Sepolia',\n 10003: 'Arbitrum Sepolia',\n 10004: 'Base Sepolia',\n 10005: 'Optimism Sepolia',\n };\n return names[wormholeChainId] ?? `Chain ${wormholeChainId}`;\n}\n\n// ============================================================================\n// VAA Validation\n// ============================================================================\n\n/**\n * Validate that a VAA has sufficient signatures for the given network\n */\nexport function hasQuorum(vaa: VAA, testnet = true): boolean {\n const required = testnet ? GUARDIAN_CONFIG.TESTNET_QUORUM : GUARDIAN_CONFIG.MAINNET_QUORUM;\n return vaa.signatures.length >= required;\n}\n\n/**\n * Validate VAA emitter matches expected source\n */\nexport function validateEmitter(\n vaa: VAA,\n expectedChain: number,\n expectedAddress: string\n): boolean {\n const normalizedExpected = '0x' + normalizeEmitterAddress(expectedAddress);\n return (\n vaa.emitterChain === expectedChain &&\n vaa.emitterAddress.toLowerCase() === normalizedExpected.toLowerCase()\n );\n}\n\n/**\n * Convert an EVM address to bytes32 format (for Wormhole)\n */\nexport function evmAddressToBytes32(address: string): string {\n const hex = address.replace('0x', '').toLowerCase();\n return '0x' + hex.padStart(64, '0');\n}\n\n// ============================================================================\n// Helpers\n// ============================================================================\n\nfunction sleep(ms: number): Promise<void> {\n return new Promise(resolve => setTimeout(resolve, ms));\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: '0x1a89da9e9f8f0bc90d8d492890bd55fb261c6277d2a95dfcac70c268d0c23dcc',\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":";;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAUA,oBAAuB;;;ACgXhB,IAAM,eAAe;AAAA,EAC1B,SAAS;AAAA,EACT,SAAS;AAAA,EACT,sBAAsB;AAAA,EACtB,sBAAsB;AACxB;;;ADzWO,IAAM,qBAAqB;AAAA;AAAA,EAEhC,WAAW;AAAA;AAAA,EAEX,SAAS;AAAA;AAAA,EAET,MAAM;AACR;AAKO,IAAM,kBAAkB;AAAA;AAAA,EAE7B,wBAAwB;AAAA;AAAA,EAExB,gBAAgB;AAAA;AAAA,EAEhB,wBAAwB;AAAA;AAAA,EAExB,gBAAgB;AAClB;AAsCA,eAAsB,SACpB,cACA,gBACA,UACA,UAA2B,CAAC,GACX;AACjB,QAAM;AAAA,IACJ,UAAU;AAAA,IACV,aAAa;AAAA,IACb,eAAe;AAAA,IACf;AAAA,EACF,IAAI;AAEJ,QAAM,UAAU,UAAU,aAAa,UAAU,aAAa;AAC9D,QAAM,oBAAoB,wBAAwB,cAAc;AAChE,QAAM,MAAM,GAAG,OAAO,gBAAgB,YAAY,IAAI,iBAAiB,IAAI,SAAS,SAAS,CAAC;AAE9F,WAAS,IAAI,GAAG,IAAI,YAAY,KAAK;AACnC,QAAI;AACF,YAAM,WAAW,MAAM,MAAM,GAAG;AAEhC,UAAI,SAAS,IAAI;AACf,cAAM,OAAO,MAAM,SAAS,KAAK;AACjC,YAAI,KAAK,MAAM,KAAK;AAClB,iBAAO,KAAK,KAAK;AAAA,QACnB;AAAA,MACF;AAEA,UAAI,IAAI,aAAa,GAAG;AACtB,kBAAU,IAAI,GAAG,UAAU;AAC3B,cAAM,MAAM,YAAY;AAAA,MAC1B;AAAA,IACF,QAAQ;AACN,UAAI,IAAI,aAAa,GAAG;AACtB,kBAAU,IAAI,GAAG,UAAU;AAC3B,cAAM,MAAM,YAAY;AAAA,MAC1B;AAAA,IACF;AAAA,EACF;AAEA,QAAM,IAAI,MAAM,6BAA6B,UAAU,WAAW;AACpE;AAMA,eAAsB,iBACpB,QACA,UAKI,CAAC,GACY;AACjB,QAAM;AAAA,IACJ,UAAU;AAAA,IACV,aAAa;AAAA,IACb,eAAe;AAAA,IACf;AAAA,EACF,IAAI;AAEJ,QAAM,UAAU,UAAU,aAAa,UAAU,aAAa;AAE9D,QAAM,cAAc,OAAO,QAAQ,OAAO,EAAE;AAC5C,QAAM,MAAM,GAAG,OAAO,6BAA6B,WAAW;AAE9D,WAAS,IAAI,GAAG,IAAI,YAAY,KAAK;AACnC,QAAI;AACF,YAAM,WAAW,MAAM,MAAM,GAAG;AAEhC,UAAI,SAAS,IAAI;AACf,cAAM,OAAO,MAAM,SAAS,KAAK;AAMjC,YAAI,KAAK,cAAc,KAAK,WAAW,SAAS,GAAG;AACjD,gBAAM,YAAY,KAAK,WAAW,CAAC;AACnC,cAAI,UAAU,KAAK,KAAK;AACtB,mBAAO,UAAU,IAAI;AAAA,UACvB;AAAA,QACF;AAAA,MACF;AAEA,UAAI,IAAI,aAAa,GAAG;AACtB,kBAAU,IAAI,GAAG,UAAU;AAC3B,cAAM,MAAM,YAAY;AAAA,MAC1B;AAAA,IACF,QAAQ;AACN,UAAI,IAAI,aAAa,GAAG;AACtB,kBAAU,IAAI,GAAG,UAAU;AAC3B,cAAM,MAAM,YAAY;AAAA,MAC1B;AAAA,IACF;AAAA,EACF;AAEA,QAAM,IAAI,MAAM,6BAA6B,UAAU,WAAW;AACpE;AAKA,eAAsB,yBACpB,QACA,UAKI,CAAC,GACY;AACjB,QAAM;AAAA,IACJ,UAAU;AAAA,IACV,aAAa;AAAA,IACb,eAAe;AAAA,IACf;AAAA,EACF,IAAI;AAEJ,QAAM,UAAU,UAAU,aAAa,UAAU,aAAa;AAC9D,QAAM,MAAM,GAAG,OAAO,wBAAwB,MAAM;AAEpD,WAAS,IAAI,GAAG,IAAI,YAAY,KAAK;AACnC,QAAI;AACF,YAAM,WAAW,MAAM,MAAM,GAAG;AAEhC,UAAI,SAAS,IAAI;AACf,cAAM,OAAO,MAAM,SAAS,KAAK;AACjC,YAAI,KAAK,MAAM,UAAU,UAAU,OAAO;AACxC,gBAAM,QAAQ,KAAK,KAAK,SAAS,SAAS;AAC1C,gBAAM,SAAS,GAAG,OAAO,gBAAgB,KAAK;AAC9C,gBAAM,cAAc,MAAM,MAAM,MAAM;AAEtC,cAAI,YAAY,IAAI;AAClB,kBAAM,UAAU,MAAM,YAAY,KAAK;AACvC,gBAAI,QAAQ,MAAM,KAAK;AACrB,qBAAO,QAAQ,KAAK;AAAA,YACtB;AAAA,UACF;AAAA,QACF;AAAA,MACF;AAEA,UAAI,IAAI,aAAa,GAAG;AACtB,kBAAU,IAAI,GAAG,UAAU;AAC3B,cAAM,MAAM,YAAY;AAAA,MAC1B;AAAA,IACF,QAAQ;AACN,UAAI,IAAI,aAAa,GAAG;AACtB,kBAAU,IAAI,GAAG,UAAU;AAC3B,cAAM,MAAM,YAAY;AAAA,MAC1B;AAAA,IACF;AAAA,EACF;AAEA,QAAM,IAAI,MAAM,6BAA6B,UAAU,WAAW;AACpE;AASO,SAAS,SAAS,WAAwB;AAC/C,QAAM,WAAW,OAAO,KAAK,WAAW,QAAQ;AAChD,SAAO,cAAc,QAAQ;AAC/B;AAKO,SAAS,cAAc,UAAuB;AACnD,MAAI,SAAS;AAGb,QAAM,UAAU,SAAS,UAAU,MAAM;AACzC,YAAU;AAGV,QAAM,mBAAmB,SAAS,aAAa,MAAM;AACrD,YAAU;AAGV,QAAM,gBAAgB,SAAS,UAAU,MAAM;AAC/C,YAAU;AAGV,QAAM,aAA6B,CAAC;AACpC,WAAS,IAAI,GAAG,IAAI,eAAe,KAAK;AACtC,UAAM,gBAAgB,SAAS,UAAU,MAAM;AAC/C,cAAU;AACV,UAAM,YAAY,OAAO,SAAS,SAAS,QAAQ,SAAS,EAAE,EAAE,SAAS,KAAK;AAC9E,cAAU;AACV,eAAW,KAAK,EAAE,eAAe,UAAU,CAAC;AAAA,EAC9C;AAGA,QAAM,aAAa;AAGnB,QAAM,YAAY,SAAS,aAAa,MAAM;AAC9C,YAAU;AAGV,QAAM,QAAQ,SAAS,aAAa,MAAM;AAC1C,YAAU;AAGV,QAAM,eAAe,SAAS,aAAa,MAAM;AACjD,YAAU;AAGV,QAAM,iBAAiB,OAAO,SAAS,SAAS,QAAQ,SAAS,EAAE,EAAE,SAAS,KAAK;AACnF,YAAU;AAGV,QAAM,WAAW,SAAS,gBAAgB,MAAM;AAChD,YAAU;AAGV,QAAM,mBAAmB,SAAS,UAAU,MAAM;AAClD,YAAU;AAGV,QAAM,UAAU,OAAO,SAAS,SAAS,MAAM,EAAE,SAAS,KAAK;AAG/D,QAAM,OAAO,SAAS,SAAS,UAAU;AACzC,QAAM,OAAO,qBAAO,UAAU,qBAAO,UAAU,IAAI,CAAC;AAEpD,SAAO;AAAA,IACL;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF;AACF;AAKO,SAAS,oBAAoB,YAAoC;AACtE,QAAM,UAAU,OAAO,KAAK,WAAW,QAAQ,MAAM,EAAE,GAAG,KAAK;AAC/D,MAAI,SAAS;AAGb,QAAM,UAAU,QAAQ,UAAU,MAAM;AACxC,YAAU;AAGV,QAAM,cAAc,OAAO,QAAQ,SAAS,QAAQ,SAAS,EAAE,EAAE,SAAS,KAAK;AAC/E,YAAU;AAGV,QAAM,cAAc,QAAQ,aAAa,MAAM;AAC/C,YAAU;AAGV,QAAM,QAAQ,OAAO,OAAO,QAAQ,SAAS,QAAQ,SAAS,EAAE,EAAE,SAAS,KAAK,CAAC;AACjF,YAAU;AAGV,QAAM,aAAa,OAAO,OAAO,QAAQ,SAAS,QAAQ,SAAS,EAAE,EAAE,SAAS,KAAK,CAAC;AACtF,YAAU;AAGV,QAAM,aAAa,OAAO,OAAO,QAAQ,SAAS,QAAQ,SAAS,EAAE,EAAE,SAAS,KAAK,CAAC;AACtF,YAAU;AAGV,QAAM,gBAAgB,OAAO,QAAQ,SAAS,MAAM,EAAE,SAAS,KAAK;AAEpE,SAAO;AAAA,IACL;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF;AACF;AASO,SAAS,iBAAiB,WAA2B;AAC1D,QAAM,WAAW,OAAO,KAAK,WAAW,QAAQ;AAChD,SAAO,OAAO,SAAS,SAAS,KAAK;AACvC;AAKO,SAAS,mBAAmB,WAA+B;AAChE,SAAO,IAAI,WAAW,OAAO,KAAK,WAAW,QAAQ,CAAC;AACxD;AASO,SAAS,wBAAwB,SAAyB;AAC/D,MAAI,MAAM,QAAQ,QAAQ,MAAM,EAAE;AAClC,SAAO,IAAI,SAAS,IAAI;AACtB,UAAM,MAAM;AAAA,EACd;AACA,SAAO;AACT;AAKO,SAAS,oBAAoB,YAA4B;AAC9D,QAAM,MAAM,WAAW,QAAQ,MAAM,EAAE;AACvC,SAAO,OAAO,IAAI,MAAM,GAAG;AAC7B;AASA,eAAsB,yBACpB,UACA,QACA,oBACiB;AACjB,QAAM,UAAU,MAAM,SAAS,sBAAsB,MAAM;AAC3D,MAAI,CAAC,SAAS;AACZ,UAAM,IAAI,MAAM,kCAAkC,MAAM,EAAE;AAAA,EAC5D;AAEA,QAAM,8BAA8B,qBAAO;AAAA,IACzC;AAAA,EACF;AAEA,aAAW,OAAO,QAAQ,MAAM;AAC9B,QAAI,IAAI,QAAQ,YAAY,MAAM,mBAAmB,YAAY,GAAG;AAClE,UAAI,IAAI,OAAO,CAAC,MAAM,+BAA+B,IAAI,OAAO,CAAC,GAAG;AAClE,cAAM,WAAW,OAAO,IAAI,OAAO,CAAC,CAAC;AACrC,eAAO;AAAA,MACT;AAAA,IACF;AAAA,EACF;AAEA,QAAM,IAAI,MAAM,oDAAoD;AACtE;AAkBA,eAAsB,0BACpB,cACA,gBACA,UACA,UAAoC,CAAC,GACvB;AACd,QAAM;AAAA,IACJ,UAAU;AAAA,IACV,qBAAqB,UAAU,gBAAgB,iBAAiB,gBAAgB;AAAA,IAChF,YAAY;AAAA,IACZ,kBAAkB;AAAA,IAClB;AAAA,EACF,IAAI;AAEJ,QAAM,YAAY,KAAK,IAAI;AAE3B,SAAO,KAAK,IAAI,IAAI,YAAY,WAAW;AACzC,QAAI;AACF,YAAM,YAAY,MAAM,SAAS,cAAc,gBAAgB,UAAU;AAAA,QACvE;AAAA,QACA,YAAY;AAAA,QACZ,cAAc;AAAA,MAChB,CAAC;AACD,YAAM,MAAM,SAAS,SAAS;AAE9B,mBAAa,IAAI,WAAW,QAAQ,kBAAkB;AAEtD,UAAI,IAAI,WAAW,UAAU,oBAAoB;AAC/C,eAAO;AAAA,MACT;AAAA,IACF,QAAQ;AAAA,IAER;AAEA,UAAM,MAAM,eAAe;AAAA,EAC7B;AAEA,QAAM,IAAI,MAAM,iDAAiD,YAAY,GAAI,GAAG;AACtF;AASO,SAAS,sBAAsB,iBAAyB,UAAU,MAAc;AACrF,QAAM,iBAAyC;AAAA,IAC7C,OAAO;AAAA;AAAA,IACP,OAAO;AAAA;AAAA,IACP,OAAO;AAAA;AAAA,IACP,GAAG;AAAA;AAAA,IACH,IAAI;AAAA;AAAA,IACJ,IAAI;AAAA;AAAA,EACN;AAEA,QAAM,iBAAyC;AAAA,IAC7C,GAAG;AAAA;AAAA,IACH,IAAI;AAAA;AAAA,IACJ,IAAI;AAAA;AAAA,IACJ,IAAI;AAAA;AAAA,IACJ,GAAG;AAAA;AAAA,IACH,GAAG;AAAA;AAAA,IACH,IAAI;AAAA;AAAA,IACJ,IAAI;AAAA;AAAA,EACN;AAEA,QAAM,UAAU,UAAU,iBAAiB;AAC3C,SAAO,QAAQ,eAAe,KAAK;AACrC;AAKO,SAAS,uBAAuB,iBAAyB,UAAU,MAAc;AACtF,QAAM,iBAAyC;AAAA,IAC7C,OAAO;AAAA;AAAA,IACP,OAAO;AAAA;AAAA,IACP,OAAO;AAAA;AAAA,EACT;AAEA,QAAM,iBAAyC;AAAA,IAC7C,GAAG;AAAA;AAAA,IACH,IAAI;AAAA;AAAA,IACJ,IAAI;AAAA;AAAA,IACJ,IAAI;AAAA;AAAA,IACJ,GAAG;AAAA;AAAA,EACL;AAEA,QAAM,UAAU,UAAU,iBAAiB;AAC3C,SAAO,QAAQ,eAAe,KAAK;AACrC;AAKO,SAAS,mBAAmB,iBAAyB,UAAU,MAAc;AAClF,QAAM,kBAA0C;AAAA,IAC9C,OAAO;AAAA;AAAA,IACP,OAAO;AAAA;AAAA,IACP,OAAO;AAAA;AAAA,EACT;AAEA,QAAM,kBAA0C;AAAA,IAC9C,GAAG;AAAA;AAAA,IACH,IAAI;AAAA;AAAA,IACJ,IAAI;AAAA;AAAA,IACJ,IAAI;AAAA;AAAA,IACJ,GAAG;AAAA;AAAA,EACL;AAEA,QAAM,WAAW,UAAU,kBAAkB;AAC7C,SAAO,SAAS,eAAe,KAAK;AACtC;AAKO,SAAS,gBAAgB,iBAAyB,UAAU,MAAe;AAChF,SAAO,mBAAmB,iBAAiB,OAAO,MAAM;AAC1D;AAKO,SAAS,aAAa,iBAAiC;AAC5D,QAAM,QAAgC;AAAA,IACpC,GAAG;AAAA,IACH,GAAG;AAAA,IACH,GAAG;AAAA,IACH,GAAG;AAAA,IACH,GAAG;AAAA,IACH,IAAI;AAAA,IACJ,IAAI;AAAA,IACJ,IAAI;AAAA,IACJ,IAAI;AAAA,IACJ,IAAI;AAAA,IACJ,IAAI;AAAA,IACJ,OAAO;AAAA,IACP,OAAO;AAAA,IACP,OAAO;AAAA,IACP,OAAO;AAAA,EACT;AACA,SAAO,MAAM,eAAe,KAAK,SAAS,eAAe;AAC3D;AASO,SAAS,UAAU,KAAU,UAAU,MAAe;AAC3D,QAAM,WAAW,UAAU,gBAAgB,iBAAiB,gBAAgB;AAC5E,SAAO,IAAI,WAAW,UAAU;AAClC;AAKO,SAAS,gBACd,KACA,eACA,iBACS;AACT,QAAM,qBAAqB,OAAO,wBAAwB,eAAe;AACzE,SACE,IAAI,iBAAiB,iBACrB,IAAI,eAAe,YAAY,MAAM,mBAAmB,YAAY;AAExE;AAKO,SAAS,oBAAoB,SAAyB;AAC3D,QAAM,MAAM,QAAQ,QAAQ,MAAM,EAAE,EAAE,YAAY;AAClD,SAAO,OAAO,IAAI,SAAS,IAAI,GAAG;AACpC;AAMA,SAAS,MAAM,IAA2B;AACxC,SAAO,IAAI,QAAQ,aAAW,WAAW,SAAS,EAAE,CAAC;AACvD;","names":[]}