@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/chains/aptos/index.js.map +1 -1
- package/dist/chains/aptos/index.mjs.map +1 -1
- package/dist/chains/evm/index.js.map +1 -1
- package/dist/chains/evm/index.mjs.map +1 -1
- package/dist/chains/solana/index.js.map +1 -1
- package/dist/chains/solana/index.mjs.map +1 -1
- package/dist/chains/starknet/index.js.map +1 -1
- package/dist/chains/starknet/index.mjs.map +1 -1
- package/dist/chains/sui/index.js.map +1 -1
- package/dist/chains/sui/index.mjs.map +1 -1
- package/dist/constants.js +4 -4
- package/dist/constants.js.map +1 -1
- package/dist/constants.mjs +4 -4
- package/dist/constants.mjs.map +1 -1
- package/dist/index.js +8 -8
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +8 -8
- package/dist/index.mjs.map +1 -1
- package/dist/payload.js.map +1 -1
- package/dist/payload.mjs.map +1 -1
- package/dist/queries/index.js +4 -4
- package/dist/queries/index.js.map +1 -1
- package/dist/queries/index.mjs +4 -4
- package/dist/queries/index.mjs.map +1 -1
- package/dist/utils.js +4 -4
- package/dist/utils.js.map +1 -1
- package/dist/utils.mjs +4 -4
- package/dist/utils.mjs.map +1 -1
- package/dist/wormhole.js.map +1 -1
- package/dist/wormhole.mjs.map +1 -1
- package/package.json +1 -1
package/dist/index.mjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/core/PasskeyManager.ts","../src/utils.ts","../src/constants.ts","../src/core/WalletManager.ts","../src/core/BalanceManager.ts","../src/constants/tokens.ts","../src/core/TransactionTracker.ts","../src/core/CrossChainManager.ts","../src/wormhole.ts","../src/core/RelayerClient.ts","../src/chains/solana/SolanaClient.ts","../src/payload.ts","../src/chains/aptos/AptosClient.ts","../src/chains/sui/SuiClient.ts","../src/chains/starknet/StarknetClient.ts","../src/core/ChainDetector.ts","../src/core/TransactionParser.ts","../src/core/TransactionSummary.types.ts","../src/core/SpendingLimitsManager.ts","../src/core/SpendingLimits.types.ts","../src/core/VeridexSDK.ts","../src/auth/prepareAuth.ts","../src/queries/hubState.ts","../src/queries/constants.ts","../src/queries/portfolio.ts","../src/core/GasSponsor.ts","../src/chains/evm/EVMClient.ts","../src/presets.ts","../src/factory.ts","../src/sessions/index.ts","../src/sessions/types.ts","../src/sessions/crypto.ts","../src/sessions/storage.ts","../src/chains/evm/EVMHubClientAdapter.ts","../src/constants/errors.ts"],"sourcesContent":["/**\n * Veridex Protocol SDK - Passkey Manager\n * \n * Chain-agnostic WebAuthn/Passkey credential management\n */\n\nimport {\n startRegistration,\n startAuthentication,\n browserSupportsWebAuthn,\n} from '@simplewebauthn/browser';\nimport type {\n PublicKeyCredentialCreationOptionsJSON,\n PublicKeyCredentialRequestOptionsJSON,\n RegistrationResponseJSON,\n AuthenticationResponseJSON,\n} from '@simplewebauthn/types';\nimport { ethers } from 'ethers';\nimport { base64URLEncode, base64URLDecode, parseDERSignature, computeKeyHash } from '../utils.js';\n\n// ============================================================================\n// Types\n// ============================================================================\n\nexport interface PasskeyCredential {\n credentialId: string;\n publicKeyX: bigint;\n publicKeyY: bigint;\n keyHash: string;\n}\n\nexport interface WebAuthnSignature {\n authenticatorData: string;\n clientDataJSON: string;\n challengeIndex: number;\n typeIndex: number;\n r: bigint;\n s: bigint;\n}\n\nexport interface PasskeyManagerConfig {\n rpName?: string;\n rpId?: string;\n timeout?: number;\n userVerification?: 'required' | 'preferred' | 'discouraged';\n authenticatorAttachment?: 'platform' | 'cross-platform';\n /** Relayer API URL for cross-device credential recovery */\n relayerUrl?: string;\n}\n\n// ============================================================================\n// PasskeyManager Class\n// ============================================================================\n\n/**\n * Manages WebAuthn passkey credentials for Veridex Protocol\n */\nexport class PasskeyManager {\n private config: Required<PasskeyManagerConfig>;\n private credential: PasskeyCredential | null = null;\n\n constructor(config: PasskeyManagerConfig = {}) {\n this.config = {\n rpName: config.rpName ?? 'Veridex Protocol',\n rpId: config.rpId ?? (typeof window !== 'undefined' ? window.location.hostname : 'localhost'),\n timeout: config.timeout ?? 60000,\n userVerification: config.userVerification ?? 'required',\n authenticatorAttachment: config.authenticatorAttachment ?? 'platform',\n relayerUrl: config.relayerUrl ?? '',\n };\n }\n\n static isSupported(): boolean {\n return browserSupportsWebAuthn();\n }\n\n static async isPlatformAuthenticatorAvailable(): Promise<boolean> {\n if (typeof window === 'undefined' || !window.PublicKeyCredential) {\n return false;\n }\n return await window.PublicKeyCredential.isUserVerifyingPlatformAuthenticatorAvailable();\n }\n\n async register(username: string, displayName: string): Promise<PasskeyCredential> {\n if (!PasskeyManager.isSupported()) {\n throw new Error('WebAuthn is not supported in this browser');\n }\n\n const challenge = ethers.randomBytes(32);\n const challengeBase64 = base64URLEncode(challenge);\n\n const options: PublicKeyCredentialCreationOptionsJSON = {\n challenge: challengeBase64,\n rp: {\n name: this.config.rpName,\n id: this.config.rpId,\n },\n user: {\n id: base64URLEncode(ethers.toUtf8Bytes(username)),\n name: username,\n displayName: displayName,\n },\n pubKeyCredParams: [\n { alg: -7, type: 'public-key' }, // ES256 (P-256) - WebAuthn default\n { alg: -257, type: 'public-key' }, // RS256 - Widely supported\n { alg: -8, type: 'public-key' }, // EdDSA - Modern, efficient\n { alg: -35, type: 'public-key' }, // ES384 (P-384)\n { alg: -36, type: 'public-key' }, // ES512 (P-521)\n { alg: -37, type: 'public-key' }, // PS256 - RSA PSS\n ],\n authenticatorSelection: {\n authenticatorAttachment: this.config.authenticatorAttachment,\n userVerification: this.config.userVerification,\n residentKey: 'required',\n requireResidentKey: true,\n },\n timeout: this.config.timeout,\n attestation: 'none',\n };\n\n const response = await startRegistration(options);\n const publicKey = this.extractPublicKeyFromAttestation(response);\n const keyHash = computeKeyHash(publicKey.x, publicKey.y);\n\n this.credential = {\n credentialId: response.id,\n publicKeyX: publicKey.x,\n publicKeyY: publicKey.y,\n keyHash,\n };\n\n return this.credential;\n }\n\n async sign(challenge: Uint8Array): Promise<WebAuthnSignature> {\n if (!this.credential) {\n throw new Error('No credential set. Call register() or setCredential() first.');\n }\n\n const challengeBase64 = base64URLEncode(challenge);\n\n const options: PublicKeyCredentialRequestOptionsJSON = {\n challenge: challengeBase64,\n rpId: this.config.rpId,\n allowCredentials: [\n {\n id: this.credential.credentialId,\n type: 'public-key',\n transports: ['internal'],\n },\n ],\n userVerification: this.config.userVerification,\n timeout: this.config.timeout,\n };\n\n const response = await startAuthentication(options);\n return this.parseAuthenticationResponse(response);\n }\n\n /**\n * Authenticate using a discoverable credential (passkey)\n * This allows sign-in without knowing the credential ID ahead of time.\n * The authenticator will show all available passkeys for this RP.\n * \n * @param challenge - Optional challenge bytes. If not provided, a random challenge is used.\n * @returns The credential that was used to authenticate, along with the signature\n */\n async authenticate(challenge?: Uint8Array): Promise<{\n credential: PasskeyCredential;\n signature: WebAuthnSignature;\n }> {\n if (!PasskeyManager.isSupported()) {\n throw new Error('WebAuthn is not supported in this browser');\n }\n\n const actualChallenge = challenge ?? ethers.randomBytes(32);\n const challengeBase64 = base64URLEncode(actualChallenge);\n\n // Use discoverable credentials - no allowCredentials means the authenticator\n // will show all available passkeys for this RP\n const options: PublicKeyCredentialRequestOptionsJSON = {\n challenge: challengeBase64,\n rpId: this.config.rpId,\n // No allowCredentials = discoverable credential flow\n userVerification: this.config.userVerification,\n timeout: this.config.timeout,\n };\n\n const response = await startAuthentication(options);\n \n // Extract the credential ID that was used\n const credentialId = response.id;\n \n // Parse the signature\n const signature = this.parseAuthenticationResponse(response);\n \n // For discoverable credentials, we need to recover the public key from the response\n // or require it to be stored. Since WebAuthn doesn't return the public key on auth,\n // we need to check if we have it stored, or use a different approach.\n \n // Try to load from localStorage first (might have been stored during registration)\n let storedCredential = this.loadCredentialById(credentialId);\n \n if (storedCredential) {\n this.credential = storedCredential;\n return { credential: storedCredential, signature };\n }\n \n // If not in localStorage, try to fetch from relayer (cross-device recovery)\n if (this.config.relayerUrl) {\n storedCredential = await this.loadCredentialFromRelayer(credentialId);\n if (storedCredential) {\n this.credential = storedCredential;\n // Cache locally for future use\n this.saveToLocalStorage();\n return { credential: storedCredential, signature };\n }\n }\n \n // If we don't have the public key stored anywhere, we need to throw an error\n // because we can't derive the keyHash without the public key\n throw new Error(\n 'Credential not found. ' +\n 'This passkey was registered on a different device or the data was cleared. ' +\n 'Please register a new passkey or ensure the relayer URL is configured.'\n );\n }\n\n /**\n * Load a credential by its ID from localStorage\n * Used for discoverable credential authentication\n */\n private loadCredentialById(credentialId: string, key = 'veridex_credential'): PasskeyCredential | null {\n if (typeof window === 'undefined') {\n return null;\n }\n\n const stored = localStorage.getItem(key);\n if (!stored) {\n return null;\n }\n\n try {\n const data = JSON.parse(stored);\n // Check if this is the right credential\n if (data.credentialId === credentialId) {\n return {\n credentialId: data.credentialId,\n publicKeyX: BigInt(data.publicKeyX),\n publicKeyY: BigInt(data.publicKeyY),\n keyHash: data.keyHash,\n };\n }\n return null;\n } catch (error) {\n console.error('Failed to load credential:', error);\n return null;\n }\n }\n\n /**\n * Check if there's a stored credential for this RP\n */\n hasStoredCredential(key = 'veridex_credential'): boolean {\n if (typeof window === 'undefined') {\n return false;\n }\n return localStorage.getItem(key) !== null;\n }\n\n getCredential(): PasskeyCredential | null {\n return this.credential;\n }\n\n setCredential(credential: PasskeyCredential): void {\n this.credential = credential;\n }\n\n createCredentialFromPublicKey(\n credentialId: string,\n publicKeyX: bigint,\n publicKeyY: bigint\n ): PasskeyCredential {\n const keyHash = computeKeyHash(publicKeyX, publicKeyY);\n this.credential = {\n credentialId,\n publicKeyX,\n publicKeyY,\n keyHash,\n };\n return this.credential;\n }\n\n clearCredential(): void {\n this.credential = null;\n }\n\n saveToLocalStorage(key = 'veridex_credential'): void {\n if (!this.credential) {\n throw new Error('No credential to save');\n }\n if (typeof window === 'undefined') {\n throw new Error('localStorage is not available');\n }\n\n const data = {\n credentialId: this.credential.credentialId,\n publicKeyX: this.credential.publicKeyX.toString(),\n publicKeyY: this.credential.publicKeyY.toString(),\n keyHash: this.credential.keyHash,\n };\n\n localStorage.setItem(key, JSON.stringify(data));\n }\n\n loadFromLocalStorage(key = 'veridex_credential'): PasskeyCredential | null {\n if (typeof window === 'undefined') {\n return null;\n }\n\n const stored = localStorage.getItem(key);\n if (!stored) {\n return null;\n }\n\n try {\n const data = JSON.parse(stored);\n this.credential = {\n credentialId: data.credentialId,\n publicKeyX: BigInt(data.publicKeyX),\n publicKeyY: BigInt(data.publicKeyY),\n keyHash: data.keyHash,\n };\n return this.credential;\n } catch (error) {\n console.error('Failed to load credential from localStorage:', error);\n return null;\n }\n }\n\n removeFromLocalStorage(key = 'veridex_credential'): void {\n if (typeof window !== 'undefined') {\n localStorage.removeItem(key);\n }\n }\n\n // =========================================================================\n // Relayer-based Credential Storage (Cross-Device Recovery)\n // =========================================================================\n\n /**\n * Save the current credential to the relayer for cross-device recovery.\n * This should be called after registration.\n */\n async saveCredentialToRelayer(): Promise<boolean> {\n if (!this.credential) {\n throw new Error('No credential to save');\n }\n if (!this.config.relayerUrl) {\n console.warn('Relayer URL not configured; skipping remote credential storage');\n return false;\n }\n\n try {\n const response = await fetch(`${this.config.relayerUrl}/api/v1/credential`, {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({\n keyHash: this.credential.keyHash,\n credentialId: this.credential.credentialId,\n publicKeyX: this.credential.publicKeyX.toString(),\n publicKeyY: this.credential.publicKeyY.toString(),\n }),\n });\n\n if (!response.ok) {\n const errorData = await response.json().catch(() => ({}));\n console.error('Failed to save credential to relayer:', errorData);\n return false;\n }\n\n console.log('Credential saved to relayer for cross-device recovery');\n return true;\n } catch (error) {\n console.error('Failed to save credential to relayer:', error);\n return false;\n }\n }\n\n /**\n * Load a credential from the relayer by credential ID.\n * Used during discoverable credential authentication when localStorage is empty.\n */\n async loadCredentialFromRelayer(credentialId: string): Promise<PasskeyCredential | null> {\n if (!this.config.relayerUrl) {\n return null;\n }\n\n try {\n const response = await fetch(\n `${this.config.relayerUrl}/api/v1/credential/by-id/${encodeURIComponent(credentialId)}`\n );\n\n if (!response.ok) {\n return null;\n }\n\n const data = await response.json();\n if (!data.exists) {\n return null;\n }\n\n return {\n credentialId: data.credentialId,\n publicKeyX: BigInt(data.publicKeyX),\n publicKeyY: BigInt(data.publicKeyY),\n keyHash: data.keyHash,\n };\n } catch (error) {\n console.error('Failed to load credential from relayer:', error);\n return null;\n }\n }\n\n /**\n * Load a credential from the relayer by keyHash.\n * Useful when you know the user's keyHash but not their credential ID.\n */\n async loadCredentialFromRelayerByKeyHash(keyHash: string): Promise<PasskeyCredential | null> {\n if (!this.config.relayerUrl) {\n return null;\n }\n\n try {\n const response = await fetch(\n `${this.config.relayerUrl}/api/v1/credential/${encodeURIComponent(keyHash)}`\n );\n\n if (!response.ok) {\n return null;\n }\n\n const data = await response.json();\n if (!data.exists) {\n return null;\n }\n\n return {\n credentialId: data.credentialId,\n publicKeyX: BigInt(data.publicKeyX),\n publicKeyY: BigInt(data.publicKeyY),\n keyHash: data.keyHash,\n };\n } catch (error) {\n console.error('Failed to load credential from relayer:', error);\n return null;\n }\n }\n\n private extractPublicKeyFromAttestation(\n response: RegistrationResponseJSON\n ): { x: bigint; y: bigint } {\n const attestationObject = base64URLDecode(response.response.attestationObject);\n\n // Parse CBOR attestation object\n // The attestation object is a CBOR map with keys: fmt, authData, attStmt\n // We need to extract the authData which contains the credential public key\n\n let offset = 0;\n\n // Skip the CBOR map header (usually 0xa3 for 3-item map or 0xa2 for 2-item map)\n if (attestationObject[offset] >= 0xa0 && attestationObject[offset] <= 0xbf) {\n offset++;\n }\n\n // Find the authData field in the CBOR map\n // Look for the text string \"authData\" (0x68 followed by \"authData\")\n while (offset < attestationObject.length - 37) {\n if (attestationObject[offset] === 0x68 && // text string, 8 bytes\n attestationObject[offset + 1] === 0x61 && // 'a'\n attestationObject[offset + 2] === 0x75 && // 'u'\n attestationObject[offset + 3] === 0x74 && // 't'\n attestationObject[offset + 4] === 0x68 && // 'h'\n attestationObject[offset + 5] === 0x44 && // 'D'\n attestationObject[offset + 6] === 0x61 && // 'a'\n attestationObject[offset + 7] === 0x74 && // 't'\n attestationObject[offset + 8] === 0x61) { // 'a'\n offset += 9;\n break;\n }\n offset++;\n }\n\n // Skip the byte string header for authData\n if (attestationObject[offset] === 0x58 || attestationObject[offset] === 0x59) {\n // 0x58 = 1-byte length, 0x59 = 2-byte length\n const lengthBytes = attestationObject[offset] === 0x58 ? 1 : 2;\n offset += 1 + lengthBytes;\n }\n\n // Now we're at the start of authData\n // authData structure:\n // - rpIdHash: 32 bytes\n // - flags: 1 byte\n // - signCount: 4 bytes\n // - attestedCredentialData (if AT flag is set):\n // - aaguid: 16 bytes\n // - credentialIdLength: 2 bytes\n // - credentialId: credentialIdLength bytes\n // - credentialPublicKey: CBOR-encoded COSE_Key\n\n offset += 32; // Skip rpIdHash\n offset += 1; // Skip flags\n offset += 4; // Skip signCount\n offset += 16; // Skip aaguid\n\n // Read credential ID length\n const credIdLen = (attestationObject[offset] << 8) | attestationObject[offset + 1];\n offset += 2;\n offset += credIdLen; // Skip credential ID\n\n // Now we're at the COSE public key\n const coseKey = attestationObject.slice(offset);\n\n console.log('COSE key length:', coseKey.length);\n console.log('COSE key hex:', this.bytesToHex(coseKey.slice(0, Math.min(100, coseKey.length))));\n\n const { x, y } = this.parseCOSEKey(coseKey);\n return { x, y };\n }\n\n private parseCOSEKey(coseKey: Uint8Array): { x: bigint; y: bigint } {\n console.log('COSE key length:', coseKey.length);\n console.log('COSE key hex:', this.bytesToHex(coseKey));\n\n // Try multiple parsing strategies\n const parsed = this.tryParseCOSEKeyStrategies(coseKey);\n if (parsed) {\n return parsed;\n }\n\n // If all strategies fail, try using a CBOR parser approach\n return this.parseCOSEKeyWithCBORStructure(coseKey);\n }\n\n private tryParseCOSEKeyStrategies(coseKey: Uint8Array): { x: bigint; y: bigint } | null {\n // Strategy 1: Look for the specific pattern of EC2 keys\n const keyBytes = new Uint8Array(coseKey);\n\n // Common pattern for EC2 keys with P-256 curve\n for (let i = 0; i < keyBytes.length - 40; i++) {\n // Check for potential x coordinate (32 bytes preceded by key marker)\n if (keyBytes[i] === 0x58 && keyBytes[i + 1] === 0x20) {\n const potentialX = keyBytes.slice(i + 2, i + 34);\n\n // Look for y coordinate after x\n for (let j = i + 34; j < keyBytes.length - 34; j++) {\n if (keyBytes[j] === 0x58 && keyBytes[j + 1] === 0x20) {\n const potentialY = keyBytes.slice(j + 2, j + 34);\n\n // Verify these look like valid coordinates\n if (this.isValidCoordinate(potentialX) && this.isValidCoordinate(potentialY)) {\n console.log('Found coordinates via pattern matching');\n return {\n x: this.bytesToBigInt(potentialX),\n y: this.bytesToBigInt(potentialY)\n };\n }\n }\n }\n }\n }\n\n // Strategy 2: Look for ASN.1 structure\n return this.tryParseASN1Structure(keyBytes);\n }\n\n private parseCOSEKeyWithCBORStructure(coseKey: Uint8Array): { x: bigint; y: bigint } {\n // More flexible parsing that handles different CBOR structures\n const bytes = new Uint8Array(coseKey);\n let xBytes: Uint8Array | null = null;\n let yBytes: Uint8Array | null = null;\n\n // Look for x and y coordinates by scanning for byte strings\n let i = 0;\n while (i < bytes.length) {\n // Check for byte string markers\n if (bytes[i] === 0x58) { // Byte string with length byte\n const length = bytes[i + 1];\n if (length === 0x20) { // 32 bytes - likely a coordinate\n const start = i + 2;\n const end = start + 32;\n\n if (end <= bytes.length) {\n const coordinate = bytes.slice(start, end);\n\n // Assign to x or y based on position or previous assignments\n if (!xBytes) {\n xBytes = coordinate;\n console.log('Found x at offset', i);\n } else if (!yBytes) {\n yBytes = coordinate;\n console.log('Found y at offset', i);\n break; // Found both, exit loop\n }\n }\n i = end;\n } else {\n i += length + 2;\n }\n } else if (bytes[i] === 0x42) { // Byte string with 2-byte length\n if (i + 3 < bytes.length) {\n const length = (bytes[i + 1] << 8) | bytes[i + 2];\n if (length === 32) {\n const start = i + 3;\n const end = start + 32;\n\n if (end <= bytes.length) {\n const coordinate = bytes.slice(start, end);\n\n if (!xBytes) {\n xBytes = coordinate;\n console.log('Found x at offset', i);\n } else if (!yBytes) {\n yBytes = coordinate;\n console.log('Found y at offset', i);\n break;\n }\n }\n i = end;\n } else {\n i += length + 3;\n }\n } else {\n i++;\n }\n } else if (bytes[i] === 0x40) { // Byte string with indefinite length\n // Skip indefinite length marker\n i++;\n // Look for 0x04 marker (uncompressed point) or direct coordinates\n while (i < bytes.length && bytes[i] !== 0xFF) { // 0xFF is break marker\n if (bytes[i] === 0x04 && i + 65 <= bytes.length) {\n // Uncompressed EC point format\n const x = bytes.slice(i + 1, i + 33);\n const y = bytes.slice(i + 33, i + 65);\n\n if (this.isValidCoordinate(x) && this.isValidCoordinate(y)) {\n xBytes = x;\n yBytes = y;\n console.log('Found coordinates in uncompressed point format');\n break;\n }\n }\n i++;\n }\n if (xBytes && yBytes) break;\n } else {\n i++;\n }\n }\n\n if (!xBytes || !yBytes) {\n // Fallback: Try to find any 32-byte sequences\n const potentialCoords = this.find32ByteSequences(bytes);\n if (potentialCoords.length >= 2) {\n xBytes = potentialCoords[0];\n yBytes = potentialCoords[1];\n console.log('Fallback: Using first two 32-byte sequences as coordinates');\n }\n }\n\n if (!xBytes || !yBytes) {\n console.error('Failed to find coordinates in COSE key. Full dump:');\n console.error('Hex:', this.bytesToHex(bytes));\n console.error('Structure analysis:');\n this.analyzeCOSEStructure(bytes);\n throw new Error('Failed to extract public key coordinates from COSE key. Check console for details.');\n }\n\n return {\n x: this.bytesToBigInt(xBytes),\n y: this.bytesToBigInt(yBytes)\n };\n }\n\n private tryParseASN1Structure(bytes: Uint8Array): { x: bigint; y: bigint } | null {\n // ASN.1 SEQUENCE for EC public key\n if (bytes[0] === 0x30) { // SEQUENCE tag\n let offset = 2; // Skip tag and length\n\n // Look for BIT STRING (0x03)\n if (bytes[offset] === 0x03) {\n offset += 2; // Skip BIT STRING tag and unused bits\n\n // Look for another SEQUENCE\n if (bytes[offset] === 0x30) {\n offset += 2;\n\n // Should now have OID for P-256: 1.2.840.10045.3.1.7\n // Skip OID (usually 10 bytes: 06 08 2A 86 48 CE 3D 03 01 07)\n offset += 12;\n\n // BIT STRING containing the raw public key\n if (bytes[offset] === 0x03 && bytes[offset + 2] === 0x04) {\n offset += 3; // Skip to uncompressed point (0x04)\n\n const x = bytes.slice(offset, offset + 32);\n const y = bytes.slice(offset + 32, offset + 64);\n\n if (x.length === 32 && y.length === 32) {\n console.log('Found coordinates via ASN.1 parsing');\n return {\n x: this.bytesToBigInt(x),\n y: this.bytesToBigInt(y)\n };\n }\n }\n }\n }\n }\n return null;\n }\n\n private find32ByteSequences(bytes: Uint8Array): Uint8Array[] {\n const sequences: Uint8Array[] = [];\n\n for (let i = 0; i <= bytes.length - 32; i++) {\n // Check if this 32-byte sequence looks like a valid coordinate\n const sequence = bytes.slice(i, i + 32);\n if (this.isValidCoordinate(sequence)) {\n sequences.push(sequence);\n }\n }\n\n return sequences;\n }\n\n private isValidCoordinate(bytes: Uint8Array): boolean {\n if (bytes.length !== 32) return false;\n\n // Basic validation: not all zeros, not all FF\n let allZeros = true;\n let allOnes = true;\n\n for (const byte of bytes) {\n if (byte !== 0) allZeros = false;\n if (byte !== 0xFF) allOnes = false;\n }\n\n return !allZeros && !allOnes;\n }\n\n private bytesToBigInt(bytes: Uint8Array): bigint {\n return BigInt('0x' + this.bytesToHex(bytes));\n }\n\n private bytesToHex(bytes: Uint8Array): string {\n return Array.from(bytes)\n .map(b => b.toString(16).padStart(2, '0'))\n .join('');\n }\n\n private analyzeCOSEStructure(bytes: Uint8Array): void {\n console.log('COSE Structure Analysis:');\n console.log('First 20 bytes:', this.bytesToHex(bytes.slice(0, 20)));\n\n // Check for known COSE key structure markers\n const firstByte = bytes[0];\n console.log('First byte (0x' + firstByte.toString(16) + '):');\n\n if (firstByte >= 0xa0 && firstByte <= 0xbf) {\n console.log('- Definite length map with', (firstByte & 0x1f), 'pairs');\n } else if (firstByte === 0xbf) {\n console.log('- Indefinite length map');\n } else if (firstByte === 0x04) {\n console.log('- Byte string');\n } else if (firstByte === 0x02) {\n console.log('- Negative integer');\n }\n\n // Count occurrences of 32-byte sequences\n let count32 = 0;\n for (let i = 0; i <= bytes.length - 32; i++) {\n const chunk = bytes.slice(i, i + 32);\n if (this.isValidCoordinate(chunk)) {\n console.log(`Found valid 32-byte sequence at offset ${i}:`,\n this.bytesToHex(chunk.slice(0, 8)) + '...');\n count32++;\n }\n }\n console.log(`Total valid 32-byte sequences: ${count32}`);\n\n // Look for specific markers\n console.log('Looking for known markers:');\n const markers = [\n { byte: 0x04, name: 'Uncompressed point marker' },\n { byte: 0x03, name: 'BIT STRING' },\n { byte: 0x30, name: 'SEQUENCE' },\n { byte: 0x02, name: 'INTEGER' },\n { byte: 0x06, name: 'OBJECT IDENTIFIER' },\n { byte: 0x58, name: 'Byte string with length byte' },\n { byte: 0x42, name: 'Byte string with 2-byte length' },\n { byte: 0x40, name: 'Byte string indefinite length' },\n { byte: 0xA0, name: 'Map start' },\n { byte: 0xBF, name: 'Indefinite map start' },\n ];\n\n for (const marker of markers) {\n const indices = [];\n for (let i = 0; i < bytes.length; i++) {\n if (bytes[i] === marker.byte) {\n indices.push(i);\n }\n }\n if (indices.length > 0) {\n console.log(` ${marker.name} (0x${marker.byte.toString(16)}) at positions:`, indices.slice(0, 5).join(', '));\n }\n }\n }\n\n private parseAuthenticationResponse(response: AuthenticationResponseJSON): WebAuthnSignature {\n const authenticatorData = base64URLDecode(response.response.authenticatorData);\n const clientDataJSON = response.response.clientDataJSON;\n const signature = base64URLDecode(response.response.signature);\n\n const { r, s } = parseDERSignature(signature);\n\n // Normalize signature to low-S form.\n // The on-chain WebAuthn verifier rejects signatures with s > n/2.\n // WebAuthn authenticators are not guaranteed to produce low-S signatures,\n // so without this normalization, valid signatures can intermittently fail.\n const P256_N = BigInt('0xFFFFFFFF00000000FFFFFFFFFFFFFFFFBCE6FAADA7179E84F3B9CAC2FC632551');\n const P256_N_DIV_2 = BigInt(\n '0x7FFFFFFF800000007FFFFFFFFFFFFFFFDE737D56D38BCF4279DCE5617E3192A8'\n );\n\n const clientDataStr = new TextDecoder().decode(base64URLDecode(clientDataJSON));\n const challengeIndex = clientDataStr.indexOf('\"challenge\"');\n const typeIndex = clientDataStr.indexOf('\"type\"');\n\n if (challengeIndex === -1 || typeIndex === -1) {\n throw new Error('Invalid clientDataJSON format');\n }\n\n return {\n authenticatorData: ethers.hexlify(authenticatorData),\n clientDataJSON: clientDataStr,\n challengeIndex,\n typeIndex,\n r: this.bytesToBigInt(r),\n s: (() => {\n const sBig = this.bytesToBigInt(s);\n return sBig > P256_N_DIV_2 ? P256_N - sBig : sBig;\n })(),\n };\n }\n}","/**\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","/**\n * Veridex Protocol SDK - Wallet Manager\n * \n * Manages deterministic wallet addresses across multiple chains.\n * Vault addresses are computed using CREATE2 on EVM chains and chain-specific\n * derivation on non-EVM chains, all based on the user's passkey public key.\n */\n\nimport { ethers } from 'ethers';\nimport type { \n PasskeyCredential,\n UnifiedIdentity,\n ChainAddress,\n WalletManagerConfig,\n} from './types.js';\nimport { computeKeyHash } from '../utils.js';\n\n// ============================================================================\n// Constants\n// ============================================================================\n\n/**\n * EIP-1167 minimal proxy bytecode prefix (before implementation address)\n * 3d602d80600a3d3981f3363d3d373d3d3d363d73\n */\nconst PROXY_BYTECODE_PREFIX = '0x3d602d80600a3d3981f3363d3d373d3d3d363d73';\n\n/**\n * EIP-1167 minimal proxy bytecode suffix (after implementation address)\n * 5af43d82803e903d91602b57fd5bf3\n */\nconst PROXY_BYTECODE_SUFFIX = '5af43d82803e903d91602b57fd5bf3';\n\n// ============================================================================\n// WalletManager Class\n// ============================================================================\n\n/**\n * Manages wallet address derivation and storage for Veridex Protocol\n * \n * @example\n * ```typescript\n * const manager = new WalletManager();\n * \n * // Compute vault address for a credential\n * const address = await manager.computeVaultAddress(\n * credential.keyHash,\n * factoryAddress,\n * implementationAddress\n * );\n * \n * // Get unified identity with addresses on all chains\n * const identity = await manager.getUnifiedIdentity(credential, chainConfigs);\n * ```\n */\nexport class WalletManager {\n private config: WalletManagerConfig;\n private addressCache: Map<string, ChainAddress[]> = new Map();\n\n constructor(config: WalletManagerConfig = {}) {\n this.config = {\n cacheAddresses: config.cacheAddresses ?? true,\n persistToStorage: config.persistToStorage ?? false,\n storageKey: config.storageKey ?? 'veridex_wallet_addresses',\n };\n\n // Load cached addresses from storage if enabled\n if (this.config.persistToStorage && typeof window !== 'undefined') {\n this.loadFromStorage();\n }\n }\n\n // ========================================================================\n // Address Computation\n // ========================================================================\n\n /**\n * Compute the deterministic vault address for an EVM chain\n * \n * Uses CREATE2 with EIP-1167 minimal proxy pattern:\n * - Salt = keccak256(factoryAddress, ownerKeyHash)\n * - InitCode = EIP-1167 proxy bytecode with implementation address\n * \n * @param keyHash - The owner's key hash (keccak256 of public key coordinates)\n * @param factoryAddress - The vault factory contract address\n * @param implementationAddress - The vault implementation contract address\n * @returns The deterministic vault address\n */\n computeVaultAddress(\n keyHash: string,\n factoryAddress: string,\n implementationAddress: string\n ): string {\n // Compute salt: keccak256(abi.encodePacked(factory, keyHash))\n const salt = ethers.keccak256(\n ethers.solidityPacked(\n ['address', 'bytes32'],\n [factoryAddress, keyHash]\n )\n );\n\n // Build EIP-1167 initcode\n const initCode = this.buildProxyInitCode(implementationAddress);\n const initCodeHash = ethers.keccak256(initCode);\n\n // CREATE2 address computation:\n // address = keccak256(0xff ++ factory ++ salt ++ initCodeHash)[12:]\n const create2Data = ethers.solidityPacked(\n ['bytes1', 'address', 'bytes32', 'bytes32'],\n ['0xff', factoryAddress, salt, initCodeHash]\n );\n\n const hash = ethers.keccak256(create2Data);\n // Take last 20 bytes as address\n return ethers.getAddress('0x' + hash.slice(26));\n }\n\n /**\n * Compute vault address from public key coordinates\n * \n * @param publicKeyX - P-256 public key X coordinate\n * @param publicKeyY - P-256 public key Y coordinate\n * @param factoryAddress - The vault factory contract address\n * @param implementationAddress - The vault implementation contract address\n * @returns The deterministic vault address\n */\n computeVaultAddressFromPublicKey(\n publicKeyX: bigint,\n publicKeyY: bigint,\n factoryAddress: string,\n implementationAddress: string\n ): string {\n const keyHash = computeKeyHash(publicKeyX, publicKeyY);\n return this.computeVaultAddress(keyHash, factoryAddress, implementationAddress);\n }\n\n /**\n * Build EIP-1167 minimal proxy initcode\n */\n private buildProxyInitCode(implementationAddress: string): string {\n // Remove 0x prefix if present and lowercase\n const impl = implementationAddress.toLowerCase().replace('0x', '');\n \n // EIP-1167 bytecode format\n return PROXY_BYTECODE_PREFIX + impl + PROXY_BYTECODE_SUFFIX;\n }\n\n // ========================================================================\n // Unified Identity\n // ========================================================================\n\n /**\n * Get unified identity with addresses across all configured chains\n * \n * @param credential - The passkey credential\n * @param chainConfigs - Map of chain configurations with factory/implementation addresses\n * @returns Unified identity with addresses on each chain\n */\n async getUnifiedIdentity(\n credential: PasskeyCredential,\n chainConfigs: Map<number, ChainAddressConfig>\n ): Promise<UnifiedIdentity> {\n const addresses: ChainAddress[] = [];\n\n for (const [wormholeChainId, config] of chainConfigs) {\n const address = await this.deriveAddressForChain(\n credential,\n wormholeChainId,\n config\n );\n \n if (address) {\n addresses.push(address);\n }\n }\n\n const identity: UnifiedIdentity = {\n keyHash: credential.keyHash,\n publicKeyX: credential.publicKeyX,\n publicKeyY: credential.publicKeyY,\n credentialId: credential.credentialId,\n addresses,\n createdAt: Date.now(),\n updatedAt: Date.now(),\n };\n\n // Cache the identity\n if (this.config.cacheAddresses) {\n this.addressCache.set(credential.keyHash, addresses);\n }\n\n // Persist to storage if enabled\n if (this.config.persistToStorage) {\n this.saveToStorage(identity);\n }\n\n return identity;\n }\n\n /**\n * Derive address for a specific chain\n */\n private async deriveAddressForChain(\n credential: PasskeyCredential,\n wormholeChainId: number,\n config: ChainAddressConfig\n ): Promise<ChainAddress | null> {\n if (config.isEvm) {\n // EVM chains use CREATE2\n if (!config.factoryAddress || !config.implementationAddress) {\n return null;\n }\n\n const address = this.computeVaultAddress(\n credential.keyHash,\n config.factoryAddress,\n config.implementationAddress\n );\n\n return {\n wormholeChainId,\n chainName: config.chainName,\n address,\n isEvm: true,\n deployed: false, // Will be checked separately\n };\n } else {\n // Non-EVM chains have chain-specific address derivation\n return this.deriveNonEvmAddress(credential, wormholeChainId, config);\n }\n }\n\n /**\n * Derive address for non-EVM chains\n * \n * Each chain has its own address format:\n * - Solana: Base58 encoded public key hash\n * - Aptos: 32-byte hex address\n * - Sui: 32-byte hex address with 0x prefix\n */\n private deriveNonEvmAddress(\n credential: PasskeyCredential,\n wormholeChainId: number,\n _config: ChainAddressConfig\n ): ChainAddress | null {\n switch (wormholeChainId) {\n case 1: // Solana\n // Solana uses the key hash directly as a seed for PDA derivation\n // The actual address depends on the program ID\n return {\n wormholeChainId: 1,\n chainName: 'Solana',\n address: credential.keyHash, // PDA will be derived from this\n isEvm: false,\n derivationType: 'pda',\n deployed: false,\n };\n\n case 22: // Aptos\n // Aptos uses the key hash as the resource account address\n return {\n wormholeChainId: 22,\n chainName: 'Aptos',\n address: credential.keyHash,\n isEvm: false,\n derivationType: 'resource_account',\n deployed: false,\n };\n\n case 21: // Sui\n // Sui uses the key hash with 0x prefix\n return {\n wormholeChainId: 21,\n chainName: 'Sui',\n address: credential.keyHash,\n isEvm: false,\n derivationType: 'object',\n deployed: false,\n };\n\n default:\n // Unknown chain\n return null;\n }\n }\n\n // ========================================================================\n // Address Lookup\n // ========================================================================\n\n /**\n * Get cached address for a chain\n */\n getAddressForChain(keyHash: string, wormholeChainId: number): ChainAddress | undefined {\n const addresses = this.addressCache.get(keyHash);\n return addresses?.find(a => a.wormholeChainId === wormholeChainId);\n }\n\n /**\n * Get all cached addresses for a key hash\n */\n getAddresses(keyHash: string): ChainAddress[] {\n return this.addressCache.get(keyHash) ?? [];\n }\n\n /**\n * Update deployment status for an address\n */\n updateDeploymentStatus(\n keyHash: string,\n wormholeChainId: number,\n deployed: boolean,\n deploymentTxHash?: string\n ): void {\n const addresses = this.addressCache.get(keyHash);\n if (!addresses) return;\n\n const address = addresses.find(a => a.wormholeChainId === wormholeChainId);\n if (address) {\n address.deployed = deployed;\n address.deploymentTxHash = deploymentTxHash;\n }\n\n // Persist update if enabled\n if (this.config.persistToStorage) {\n this.saveAddressesToStorage(keyHash, addresses);\n }\n }\n\n // ========================================================================\n // Storage\n // ========================================================================\n\n /**\n * Load addresses from localStorage\n */\n private loadFromStorage(): void {\n if (typeof window === 'undefined') return;\n\n try {\n const stored = localStorage.getItem(this.config.storageKey!);\n if (!stored) return;\n\n const data = JSON.parse(stored) as StoredWalletData;\n \n for (const [keyHash, addresses] of Object.entries(data.addresses)) {\n this.addressCache.set(keyHash, addresses);\n }\n } catch (error) {\n console.warn('Failed to load wallet addresses from storage:', error);\n }\n }\n\n /**\n * Save identity to localStorage\n */\n private saveToStorage(identity: UnifiedIdentity): void {\n if (typeof window === 'undefined') return;\n\n try {\n const stored = localStorage.getItem(this.config.storageKey!) ?? '{}';\n const data = JSON.parse(stored) as StoredWalletData;\n\n if (!data.addresses) {\n data.addresses = {};\n }\n\n // Store identity with serialized bigints\n data.addresses[identity.keyHash] = identity.addresses;\n data.identities = data.identities ?? {};\n data.identities[identity.keyHash] = {\n keyHash: identity.keyHash,\n publicKeyX: identity.publicKeyX.toString(),\n publicKeyY: identity.publicKeyY.toString(),\n credentialId: identity.credentialId,\n createdAt: identity.createdAt,\n updatedAt: identity.updatedAt,\n };\n\n localStorage.setItem(this.config.storageKey!, JSON.stringify(data));\n } catch (error) {\n console.warn('Failed to save wallet addresses to storage:', error);\n }\n }\n\n /**\n * Save addresses to localStorage\n */\n private saveAddressesToStorage(keyHash: string, addresses: ChainAddress[]): void {\n if (typeof window === 'undefined') return;\n\n try {\n const stored = localStorage.getItem(this.config.storageKey!) ?? '{}';\n const data = JSON.parse(stored) as StoredWalletData;\n\n if (!data.addresses) {\n data.addresses = {};\n }\n\n data.addresses[keyHash] = addresses;\n localStorage.setItem(this.config.storageKey!, JSON.stringify(data));\n } catch (error) {\n console.warn('Failed to save wallet addresses to storage:', error);\n }\n }\n\n /**\n * Clear all cached data\n */\n clearCache(): void {\n this.addressCache.clear();\n \n if (this.config.persistToStorage && typeof window !== 'undefined') {\n localStorage.removeItem(this.config.storageKey!);\n }\n }\n\n /**\n * Load identity from storage\n */\n loadIdentityFromStorage(keyHash: string): UnifiedIdentity | null {\n if (typeof window === 'undefined') return null;\n\n try {\n const stored = localStorage.getItem(this.config.storageKey!);\n if (!stored) return null;\n\n const data = JSON.parse(stored) as StoredWalletData;\n const storedIdentity = data.identities?.[keyHash];\n const addresses = data.addresses?.[keyHash];\n\n if (!storedIdentity || !addresses) return null;\n\n return {\n keyHash: storedIdentity.keyHash,\n publicKeyX: BigInt(storedIdentity.publicKeyX),\n publicKeyY: BigInt(storedIdentity.publicKeyY),\n credentialId: storedIdentity.credentialId,\n addresses,\n createdAt: storedIdentity.createdAt,\n updatedAt: storedIdentity.updatedAt,\n };\n } catch (error) {\n console.warn('Failed to load identity from storage:', error);\n return null;\n }\n }\n}\n\n// ============================================================================\n// Helper Types (Internal)\n// ============================================================================\n\ninterface ChainAddressConfig {\n chainName: string;\n isEvm: boolean;\n factoryAddress?: string;\n implementationAddress?: string;\n}\n\ninterface StoredWalletData {\n addresses: Record<string, ChainAddress[]>;\n identities?: Record<string, {\n keyHash: string;\n publicKeyX: string;\n publicKeyY: string;\n credentialId: string;\n createdAt: number;\n updatedAt: number;\n }>;\n}\n\n// Export the helper type for external use\nexport type { ChainAddressConfig };\n","/**\n * Veridex Protocol SDK - Balance Manager\n * \n * Manages balance fetching for native tokens and ERC20s across chains\n */\n\nimport { ethers } from 'ethers';\nimport { \n TokenInfo, \n getTokenList, \n getAllTokens, \n isNativeToken, \n NATIVE_TOKEN_ADDRESS \n} from '../constants/tokens.js';\n\n// ============================================================================\n// Types\n// ============================================================================\n\nexport interface TokenBalance {\n /** Token information */\n token: TokenInfo;\n /** Raw balance in smallest units */\n balance: bigint;\n /** Formatted balance with decimals */\n formatted: string;\n /** USD value (if price available) */\n usdValue?: number;\n}\n\nexport interface PortfolioBalance {\n /** Wormhole chain ID */\n wormholeChainId: number;\n /** Chain name */\n chainName: string;\n /** Address being queried */\n address: string;\n /** Individual token balances */\n tokens: TokenBalance[];\n /** Total USD value (if prices available) */\n totalUsdValue?: number;\n /** Timestamp of last update */\n lastUpdated: number;\n}\n\nexport interface BalanceManagerConfig {\n /** Whether to cache balances */\n cacheBalances?: boolean;\n /** Cache TTL in milliseconds */\n cacheTtl?: number;\n /** Custom RPC URLs by chain ID */\n customRpcUrls?: Record<number, string>;\n}\n\n// ============================================================================\n// Constants\n// ============================================================================\n\n/**\n * Default RPC URLs for testnet chains\n */\nconst DEFAULT_RPC_URLS: Record<number, string> = {\n 10004: 'https://sepolia.base.org',\n 10005: 'https://sepolia.optimism.io',\n 10003: 'https://sepolia-rollup.arbitrum.io/rpc',\n};\n\n/**\n * Testnet token prices (USD) for development/testing\n * These are static estimates since testnet tokens have no real value\n */\nconst TESTNET_TOKEN_PRICES: Record<string, number> = {\n ETH: 2500,\n WETH: 2500,\n USDC: 1,\n USDT: 1,\n DAI: 1,\n WBTC: 60000,\n LINK: 15,\n UNI: 8,\n};\n\n/**\n * ERC20 ABI for balance checking\n */\nconst ERC20_ABI = [\n 'function balanceOf(address owner) view returns (uint256)',\n 'function decimals() view returns (uint8)',\n 'function symbol() view returns (string)',\n 'function name() view returns (string)',\n];\n\n/**\n * Default cache TTL: 30 seconds\n */\nconst DEFAULT_CACHE_TTL = 30_000;\n\n// ============================================================================\n// Balance Cache\n// ============================================================================\n\ninterface CachedBalance {\n balance: PortfolioBalance;\n expiresAt: number;\n}\n\n// ============================================================================\n// Balance Manager Class\n// ============================================================================\n\nexport class BalanceManager {\n private config: Required<BalanceManagerConfig>;\n private providers: Map<number, ethers.JsonRpcProvider> = new Map();\n private cache: Map<string, CachedBalance> = new Map();\n\n constructor(config: BalanceManagerConfig = {}) {\n this.config = {\n cacheBalances: config.cacheBalances ?? true,\n cacheTtl: config.cacheTtl ?? DEFAULT_CACHE_TTL,\n customRpcUrls: config.customRpcUrls ?? {},\n };\n }\n\n // ========================================================================\n // Public Methods\n // ========================================================================\n\n /**\n * Get balance for a specific token on a chain\n * \n * @param wormholeChainId - The Wormhole chain ID\n * @param address - The address to check balance for\n * @param tokenAddress - Token address or 'native' for native token\n * @returns TokenBalance with raw and formatted amounts\n */\n async getBalance(\n wormholeChainId: number,\n address: string,\n tokenAddress: string\n ): Promise<TokenBalance> {\n const provider = this.getProvider(wormholeChainId);\n const tokenList = getTokenList(wormholeChainId);\n \n if (!tokenList) {\n throw new Error(`Chain ${wormholeChainId} not supported`);\n }\n\n const tokens = getAllTokens(wormholeChainId);\n let tokenInfo = tokens.find(\n t => t.address.toLowerCase() === tokenAddress.toLowerCase()\n );\n\n // Handle native token variations\n if (!tokenInfo && isNativeToken(tokenAddress)) {\n tokenInfo = tokenList.nativeToken;\n }\n\n // If still no token info, create a generic one\n if (!tokenInfo) {\n tokenInfo = await this.fetchTokenInfo(provider, tokenAddress);\n }\n\n const balance = await this.fetchBalance(provider, address, tokenAddress, tokenInfo);\n const formatted = ethers.formatUnits(balance, tokenInfo.decimals);\n // Calculate USD value using testnet prices\n const price = TESTNET_TOKEN_PRICES[tokenInfo.symbol.toUpperCase()];\n const usdValue = price ? parseFloat(formatted) * price : undefined;\n\n return {\n token: tokenInfo,\n balance,\n formatted,\n usdValue,\n };\n }\n\n /**\n * Get all token balances for an address on a chain\n * \n * @param wormholeChainId - The Wormhole chain ID\n * @param address - The address to check balances for\n * @param includeZeroBalances - Whether to include tokens with 0 balance\n * @returns PortfolioBalance with all token balances\n */\n async getPortfolioBalance(\n wormholeChainId: number,\n address: string,\n includeZeroBalances: boolean = false\n ): Promise<PortfolioBalance> {\n // Check cache first\n const cacheKey = `${wormholeChainId}:${address.toLowerCase()}`;\n if (this.config.cacheBalances) {\n const cached = this.cache.get(cacheKey);\n if (cached && cached.expiresAt > Date.now()) {\n return cached.balance;\n }\n }\n\n const tokenList = getTokenList(wormholeChainId);\n if (!tokenList) {\n throw new Error(`Chain ${wormholeChainId} not supported`);\n }\n\n const provider = this.getProvider(wormholeChainId);\n const tokens = getAllTokens(wormholeChainId);\n const balances: TokenBalance[] = [];\n\n // Fetch all balances in parallel\n const balancePromises = tokens.map(async (token) => {\n try {\n const balance = await this.fetchBalance(\n provider,\n address,\n token.address,\n token\n );\n const formatted = ethers.formatUnits(balance, token.decimals);\n // Calculate USD value using testnet prices\n const price = TESTNET_TOKEN_PRICES[token.symbol.toUpperCase()];\n const usdValue = price ? parseFloat(formatted) * price : undefined;\n return { token, balance, formatted, usdValue };\n } catch (error) {\n console.warn(`Failed to fetch ${token.symbol} balance:`, error);\n return { token, balance: 0n, formatted: '0', usdValue: undefined };\n }\n });\n\n const results = await Promise.all(balancePromises);\n\n for (const result of results) {\n if (includeZeroBalances || result.balance > 0n) {\n balances.push(result);\n }\n }\n\n // Calculate total USD value\n const totalUsdValue = balances.reduce((sum, b) => sum + (b.usdValue ?? 0), 0);\n\n const portfolio: PortfolioBalance = {\n wormholeChainId,\n chainName: tokenList.chainName,\n address,\n tokens: balances,\n totalUsdValue: totalUsdValue > 0 ? totalUsdValue : undefined,\n lastUpdated: Date.now(),\n };\n\n // Cache the result\n if (this.config.cacheBalances) {\n this.cache.set(cacheKey, {\n balance: portfolio,\n expiresAt: Date.now() + this.config.cacheTtl,\n });\n }\n\n return portfolio;\n }\n\n /**\n * Get native token balance\n * \n * @param wormholeChainId - The Wormhole chain ID\n * @param address - The address to check\n * @returns TokenBalance for native token\n */\n async getNativeBalance(\n wormholeChainId: number,\n address: string\n ): Promise<TokenBalance> {\n return this.getBalance(wormholeChainId, address, NATIVE_TOKEN_ADDRESS);\n }\n\n /**\n * Get balances across multiple chains for an address\n * \n * @param address - The address to check\n * @param chainIds - Array of Wormhole chain IDs to check\n * @returns Array of PortfolioBalance for each chain\n */\n async getMultiChainBalances(\n address: string,\n chainIds: number[]\n ): Promise<PortfolioBalance[]> {\n const promises = chainIds.map(chainId =>\n this.getPortfolioBalance(chainId, address).catch(error => {\n console.warn(`Failed to fetch balances for chain ${chainId}:`, error);\n return null;\n })\n );\n\n const results = await Promise.all(promises);\n return results.filter((r): r is PortfolioBalance => r !== null);\n }\n\n /**\n * Clear the balance cache\n */\n clearCache(): void {\n this.cache.clear();\n }\n\n /**\n * Invalidate cache for a specific address\n */\n invalidateCache(wormholeChainId: number, address: string): void {\n const cacheKey = `${wormholeChainId}:${address.toLowerCase()}`;\n this.cache.delete(cacheKey);\n }\n\n /**\n * Add or update RPC URL for a chain\n */\n setRpcUrl(wormholeChainId: number, rpcUrl: string): void {\n this.config.customRpcUrls[wormholeChainId] = rpcUrl;\n // Clear existing provider to force recreation\n this.providers.delete(wormholeChainId);\n }\n\n // ========================================================================\n // Private Methods\n // ========================================================================\n\n /**\n * Get or create a provider for a chain\n */\n private getProvider(wormholeChainId: number): ethers.JsonRpcProvider {\n let provider = this.providers.get(wormholeChainId);\n if (provider) {\n return provider;\n }\n\n const rpcUrl = this.config.customRpcUrls[wormholeChainId] ?? \n DEFAULT_RPC_URLS[wormholeChainId];\n \n if (!rpcUrl) {\n throw new Error(`No RPC URL configured for chain ${wormholeChainId}`);\n }\n\n provider = new ethers.JsonRpcProvider(rpcUrl);\n this.providers.set(wormholeChainId, provider);\n return provider;\n }\n\n /**\n * Fetch balance for a token\n */\n private async fetchBalance(\n provider: ethers.JsonRpcProvider,\n address: string,\n tokenAddress: string,\n _tokenInfo: TokenInfo\n ): Promise<bigint> {\n if (isNativeToken(tokenAddress)) {\n return await provider.getBalance(address);\n }\n\n const contract = new ethers.Contract(tokenAddress, ERC20_ABI, provider);\n return await contract.balanceOf(address);\n }\n\n /**\n * Fetch token info from contract\n */\n private async fetchTokenInfo(\n provider: ethers.JsonRpcProvider,\n tokenAddress: string\n ): Promise<TokenInfo> {\n const contract = new ethers.Contract(tokenAddress, ERC20_ABI, provider);\n \n const [symbol, name, decimals] = await Promise.all([\n contract.symbol().catch(() => 'UNKNOWN'),\n contract.name().catch(() => 'Unknown Token'),\n contract.decimals().catch(() => 18),\n ]);\n\n return {\n symbol,\n name,\n address: tokenAddress,\n decimals: Number(decimals),\n isNative: false,\n };\n }\n}\n","/**\n * Veridex Protocol SDK - Token Constants\n * \n * Known tokens per chain for balance fetching and transfers\n */\n\n// ============================================================================\n// Types\n// ============================================================================\n\nexport interface TokenInfo {\n /** Token symbol (e.g., 'USDC', 'ETH') */\n symbol: string;\n /** Token name (e.g., 'USD Coin') */\n name: string;\n /** Token address (use 'native' for native token) */\n address: string;\n /** Number of decimals */\n decimals: number;\n /** Optional logo URL */\n logoUrl?: string;\n /** Whether this is the native token */\n isNative: boolean;\n /** Wormhole-wrapped token address on other chains (by wormhole chain ID) */\n wrappedAddresses?: Record<number, string>;\n}\n\nexport interface ChainTokenList {\n /** Wormhole chain ID */\n wormholeChainId: number;\n /** Chain name */\n chainName: string;\n /** Native token info */\n nativeToken: TokenInfo;\n /** ERC20/SPL/etc tokens */\n tokens: TokenInfo[];\n}\n\n// ============================================================================\n// Constants\n// ============================================================================\n\n/**\n * Native token address constant\n */\nexport const NATIVE_TOKEN_ADDRESS = 'native';\n\n/**\n * Zero address for EVM chains\n */\nexport const EVM_ZERO_ADDRESS = '0x0000000000000000000000000000000000000000';\n\n// ============================================================================\n// Base Sepolia (Hub Chain) - Wormhole Chain ID 10004\n// ============================================================================\n\nexport const BASE_SEPOLIA_TOKENS: ChainTokenList = {\n wormholeChainId: 10004,\n chainName: 'Base Sepolia',\n nativeToken: {\n symbol: 'ETH',\n name: 'Ether',\n address: NATIVE_TOKEN_ADDRESS,\n decimals: 18,\n isNative: true,\n },\n tokens: [\n {\n symbol: 'USDC',\n name: 'USD Coin (Test)',\n address: '0x036CbD53842c5426634e7929541eC2318f3dCF7e', // Circle test USDC\n decimals: 6,\n isNative: false,\n },\n {\n symbol: 'WETH',\n name: 'Wrapped Ether',\n address: '0x4200000000000000000000000000000000000006',\n decimals: 18,\n isNative: false,\n },\n ],\n};\n\n// ============================================================================\n// Optimism Sepolia (Spoke Chain) - Wormhole Chain ID 10005\n// ============================================================================\n\nexport const OPTIMISM_SEPOLIA_TOKENS: ChainTokenList = {\n wormholeChainId: 10005,\n chainName: 'Optimism Sepolia',\n nativeToken: {\n symbol: 'ETH',\n name: 'Ether',\n address: NATIVE_TOKEN_ADDRESS,\n decimals: 18,\n isNative: true,\n },\n tokens: [\n {\n symbol: 'USDC',\n name: 'USD Coin (Test)',\n address: '0x5fd84259d66Cd46123540766Be93DFE6D43130D7', // Test USDC\n decimals: 6,\n isNative: false,\n },\n {\n symbol: 'WETH',\n name: 'Wrapped Ether',\n address: '0x4200000000000000000000000000000000000006',\n decimals: 18,\n isNative: false,\n },\n ],\n};\n\n// ============================================================================\n// Arbitrum Sepolia (Spoke Chain) - Wormhole Chain ID 10003\n// ============================================================================\n\nexport const ARBITRUM_SEPOLIA_TOKENS: ChainTokenList = {\n wormholeChainId: 10003,\n chainName: 'Arbitrum Sepolia',\n nativeToken: {\n symbol: 'ETH',\n name: 'Ether',\n address: NATIVE_TOKEN_ADDRESS,\n decimals: 18,\n isNative: true,\n },\n tokens: [\n {\n symbol: 'USDC',\n name: 'USD Coin (Test)',\n address: '0x75faf114eafb1BDbe2F0316DF893fd58CE46AA4d', // Circle USDC Arbitrum Sepolia\n decimals: 6,\n isNative: false,\n },\n {\n symbol: 'WETH',\n name: 'Wrapped Ether',\n address: '0x980B62Da83eFf3D4576C647993b0c1D7faf17c73',\n decimals: 18,\n isNative: false,\n },\n ],\n};\n\n// ============================================================================\n// Token Registry\n// ============================================================================\n\n/**\n * All token lists indexed by Wormhole chain ID\n */\nexport const TOKEN_REGISTRY: Record<number, ChainTokenList> = {\n 10004: BASE_SEPOLIA_TOKENS,\n 10005: OPTIMISM_SEPOLIA_TOKENS,\n 10003: ARBITRUM_SEPOLIA_TOKENS,\n};\n\n// ============================================================================\n// Helper Functions\n// ============================================================================\n\n/**\n * Get token list for a chain\n */\nexport function getTokenList(wormholeChainId: number): ChainTokenList | null {\n return TOKEN_REGISTRY[wormholeChainId] ?? null;\n}\n\n/**\n * Get all tokens for a chain (native + ERC20)\n */\nexport function getAllTokens(wormholeChainId: number): TokenInfo[] {\n const list = getTokenList(wormholeChainId);\n if (!list) return [];\n return [list.nativeToken, ...list.tokens];\n}\n\n/**\n * Get token info by symbol\n */\nexport function getTokenBySymbol(wormholeChainId: number, symbol: string): TokenInfo | null {\n const tokens = getAllTokens(wormholeChainId);\n return tokens.find(t => t.symbol.toLowerCase() === symbol.toLowerCase()) ?? null;\n}\n\n/**\n * Get token info by address\n */\nexport function getTokenByAddress(wormholeChainId: number, address: string): TokenInfo | null {\n const tokens = getAllTokens(wormholeChainId);\n const normalizedAddress = address.toLowerCase();\n return tokens.find(t => t.address.toLowerCase() === normalizedAddress) ?? null;\n}\n\n/**\n * Check if an address is the native token\n */\nexport function isNativeToken(address: string): boolean {\n return address.toLowerCase() === NATIVE_TOKEN_ADDRESS || \n address === EVM_ZERO_ADDRESS;\n}\n\n/**\n * Get supported chain IDs\n */\nexport function getSupportedChainIds(): number[] {\n return Object.keys(TOKEN_REGISTRY).map(Number);\n}\n\n/**\n * Get chain name by Wormhole chain ID\n */\nexport function getChainName(wormholeChainId: number): string | null {\n return TOKEN_REGISTRY[wormholeChainId]?.chainName ?? null;\n}\n","/**\n * Veridex Protocol SDK - Transaction Tracker\n * \n * Tracks transaction status from pending to confirmed\n */\n\nimport { ethers } from 'ethers';\n\n// ============================================================================\n// Types\n// ============================================================================\n\nexport type TransactionStatus = \n | 'pending'\n | 'submitted'\n | 'confirming'\n | 'confirmed'\n | 'failed'\n | 'dropped';\n\nexport interface TransactionState {\n /** Transaction hash */\n hash: string;\n /** Current status */\n status: TransactionStatus;\n /** Wormhole chain ID where transaction was sent */\n wormholeChainId: number;\n /** Block number when confirmed */\n blockNumber?: number;\n /** Number of confirmations */\n confirmations: number;\n /** Required confirmations for finality */\n requiredConfirmations: number;\n /** Gas used (after confirmation) */\n gasUsed?: bigint;\n /** Effective gas price */\n effectiveGasPrice?: bigint;\n /** Error message if failed */\n error?: string;\n /** Timestamp when transaction was submitted */\n submittedAt: number;\n /** Timestamp when transaction was confirmed */\n confirmedAt?: number;\n /** VAA sequence number (for cross-chain txs) */\n vaaSequence?: bigint;\n}\n\nexport interface TrackerConfig {\n /** Polling interval in ms (default: 2000) */\n pollingInterval?: number;\n /** Required confirmations for finality (default: 1) */\n requiredConfirmations?: number;\n /** Timeout in ms before marking as dropped (default: 300000 - 5 min) */\n timeout?: number;\n /** Custom RPC URLs by chain ID */\n customRpcUrls?: Record<number, string>;\n}\n\nexport type TransactionCallback = (state: TransactionState) => void;\n\n// ============================================================================\n// Constants\n// ============================================================================\n\nconst DEFAULT_POLLING_INTERVAL = 2000;\nconst DEFAULT_REQUIRED_CONFIRMATIONS = 1;\nconst DEFAULT_TIMEOUT = 300_000; // 5 minutes\n\nconst DEFAULT_RPC_URLS: Record<number, string> = {\n 10004: 'https://sepolia.base.org',\n 10005: 'https://sepolia.optimism.io',\n 10003: 'https://sepolia-rollup.arbitrum.io/rpc',\n};\n\n// ============================================================================\n// Transaction Tracker Class\n// ============================================================================\n\nexport class TransactionTracker {\n private config: Required<TrackerConfig>;\n private providers: Map<number, ethers.JsonRpcProvider> = new Map();\n private trackedTransactions: Map<string, TransactionState> = new Map();\n private callbacks: Map<string, TransactionCallback[]> = new Map();\n private pollingIntervals: Map<string, NodeJS.Timeout> = new Map();\n\n constructor(config: TrackerConfig = {}) {\n this.config = {\n pollingInterval: config.pollingInterval ?? DEFAULT_POLLING_INTERVAL,\n requiredConfirmations: config.requiredConfirmations ?? DEFAULT_REQUIRED_CONFIRMATIONS,\n timeout: config.timeout ?? DEFAULT_TIMEOUT,\n customRpcUrls: config.customRpcUrls ?? {},\n };\n }\n\n // ========================================================================\n // Public Methods\n // ========================================================================\n\n /**\n * Track a transaction and receive status updates\n * \n * @param hash - Transaction hash\n * @param wormholeChainId - Chain where transaction was sent\n * @param callback - Optional callback for status updates\n * @param vaaSequence - Optional VAA sequence for cross-chain transactions\n * @returns Initial transaction state\n */\n track(\n hash: string,\n wormholeChainId: number,\n callback?: TransactionCallback,\n vaaSequence?: bigint\n ): TransactionState {\n // Create initial state\n const state: TransactionState = {\n hash,\n status: 'pending',\n wormholeChainId,\n confirmations: 0,\n requiredConfirmations: this.config.requiredConfirmations,\n submittedAt: Date.now(),\n vaaSequence,\n };\n\n this.trackedTransactions.set(hash, state);\n \n if (callback) {\n this.addCallback(hash, callback);\n }\n\n // Start polling\n this.startPolling(hash, wormholeChainId);\n\n return state;\n }\n\n /**\n * Add a callback for transaction updates\n */\n addCallback(hash: string, callback: TransactionCallback): void {\n const existing = this.callbacks.get(hash) ?? [];\n existing.push(callback);\n this.callbacks.set(hash, existing);\n }\n\n /**\n * Remove a callback\n */\n removeCallback(hash: string, callback: TransactionCallback): void {\n const existing = this.callbacks.get(hash) ?? [];\n const filtered = existing.filter(cb => cb !== callback);\n if (filtered.length > 0) {\n this.callbacks.set(hash, filtered);\n } else {\n this.callbacks.delete(hash);\n }\n }\n\n /**\n * Get current state of a tracked transaction\n */\n getState(hash: string): TransactionState | null {\n return this.trackedTransactions.get(hash) ?? null;\n }\n\n /**\n * Wait for a transaction to reach confirmed status\n * \n * @param hash - Transaction hash\n * @param wormholeChainId - Chain where transaction was sent\n * @returns Promise that resolves when confirmed or rejects on failure\n */\n async waitForConfirmation(\n hash: string,\n wormholeChainId: number\n ): Promise<TransactionState> {\n // Check if already tracked\n let state = this.trackedTransactions.get(hash);\n \n if (!state) {\n state = this.track(hash, wormholeChainId);\n }\n\n // If already confirmed or failed, return immediately\n if (state.status === 'confirmed' || state.status === 'failed' || state.status === 'dropped') {\n return state;\n }\n\n // Wait for confirmation\n return new Promise((resolve, reject) => {\n const callback: TransactionCallback = (newState) => {\n if (newState.status === 'confirmed') {\n this.removeCallback(hash, callback);\n resolve(newState);\n } else if (newState.status === 'failed' || newState.status === 'dropped') {\n this.removeCallback(hash, callback);\n reject(new Error(newState.error ?? `Transaction ${newState.status}`));\n }\n };\n\n this.addCallback(hash, callback);\n });\n }\n\n /**\n * Stop tracking a transaction\n */\n stopTracking(hash: string): void {\n const interval = this.pollingIntervals.get(hash);\n if (interval) {\n clearInterval(interval);\n this.pollingIntervals.delete(hash);\n }\n this.trackedTransactions.delete(hash);\n this.callbacks.delete(hash);\n }\n\n /**\n * Stop tracking all transactions\n */\n stopAll(): void {\n for (const hash of this.pollingIntervals.keys()) {\n this.stopTracking(hash);\n }\n }\n\n /**\n * Get all tracked transactions\n */\n getAllTracked(): TransactionState[] {\n return Array.from(this.trackedTransactions.values());\n }\n\n /**\n * Get pending transactions\n */\n getPending(): TransactionState[] {\n return this.getAllTracked().filter(\n tx => tx.status === 'pending' || tx.status === 'submitted' || tx.status === 'confirming'\n );\n }\n\n // ========================================================================\n // Private Methods\n // ========================================================================\n\n /**\n * Get or create provider for a chain\n */\n private getProvider(wormholeChainId: number): ethers.JsonRpcProvider {\n let provider = this.providers.get(wormholeChainId);\n if (provider) {\n return provider;\n }\n\n const rpcUrl = this.config.customRpcUrls[wormholeChainId] ?? \n DEFAULT_RPC_URLS[wormholeChainId];\n \n if (!rpcUrl) {\n throw new Error(`No RPC URL configured for chain ${wormholeChainId}`);\n }\n\n provider = new ethers.JsonRpcProvider(rpcUrl);\n this.providers.set(wormholeChainId, provider);\n return provider;\n }\n\n /**\n * Start polling for transaction status\n */\n private startPolling(hash: string, wormholeChainId: number): void {\n // Initial check\n this.checkTransaction(hash, wormholeChainId);\n\n // Set up interval\n const interval = setInterval(() => {\n this.checkTransaction(hash, wormholeChainId);\n }, this.config.pollingInterval);\n\n this.pollingIntervals.set(hash, interval);\n }\n\n /**\n * Check transaction status\n */\n private async checkTransaction(hash: string, wormholeChainId: number): Promise<void> {\n const state = this.trackedTransactions.get(hash);\n if (!state) {\n this.stopTracking(hash);\n return;\n }\n\n // Check timeout\n if (Date.now() - state.submittedAt > this.config.timeout) {\n this.updateState(hash, {\n status: 'dropped',\n error: 'Transaction timeout - possibly dropped from mempool',\n });\n this.stopTracking(hash);\n return;\n }\n\n try {\n const provider = this.getProvider(wormholeChainId);\n const receipt = await provider.getTransactionReceipt(hash);\n\n if (!receipt) {\n // Transaction not yet mined\n if (state.status === 'pending') {\n this.updateState(hash, { status: 'submitted' });\n }\n return;\n }\n\n // Transaction is mined\n const currentBlock = await provider.getBlockNumber();\n const confirmations = currentBlock - receipt.blockNumber + 1;\n\n if (receipt.status === 0) {\n // Transaction failed\n this.updateState(hash, {\n status: 'failed',\n blockNumber: receipt.blockNumber,\n confirmations,\n gasUsed: receipt.gasUsed,\n effectiveGasPrice: receipt.gasPrice,\n error: 'Transaction reverted',\n });\n this.stopTracking(hash);\n return;\n }\n\n if (confirmations >= this.config.requiredConfirmations) {\n // Fully confirmed\n this.updateState(hash, {\n status: 'confirmed',\n blockNumber: receipt.blockNumber,\n confirmations,\n gasUsed: receipt.gasUsed,\n effectiveGasPrice: receipt.gasPrice,\n confirmedAt: Date.now(),\n });\n this.stopTracking(hash);\n } else {\n // Still confirming\n this.updateState(hash, {\n status: 'confirming',\n blockNumber: receipt.blockNumber,\n confirmations,\n gasUsed: receipt.gasUsed,\n effectiveGasPrice: receipt.gasPrice,\n });\n }\n } catch (error) {\n console.warn(`Error checking transaction ${hash}:`, error);\n // Don't update state on transient errors\n }\n }\n\n /**\n * Update transaction state and notify callbacks\n */\n private updateState(hash: string, updates: Partial<TransactionState>): void {\n const current = this.trackedTransactions.get(hash);\n if (!current) return;\n\n const newState: TransactionState = { ...current, ...updates };\n this.trackedTransactions.set(hash, newState);\n\n // Notify callbacks\n const callbacks = this.callbacks.get(hash) ?? [];\n for (const callback of callbacks) {\n try {\n callback(newState);\n } catch (error) {\n console.error('Error in transaction callback:', error);\n }\n }\n }\n}\n\n// ============================================================================\n// Helper Functions\n// ============================================================================\n\n/**\n * Create a formatted transaction explorer URL\n */\nexport function getExplorerUrl(\n wormholeChainId: number,\n hash: string\n): string | null {\n const explorers: Record<number, string> = {\n 10004: 'https://sepolia.basescan.org/tx/',\n 10005: 'https://sepolia-optimism.etherscan.io/tx/',\n 10003: 'https://sepolia.arbiscan.io/tx/',\n };\n\n const baseUrl = explorers[wormholeChainId];\n return baseUrl ? `${baseUrl}${hash}` : null;\n}\n\n/**\n * Format transaction state for display\n */\nexport function formatTransactionState(state: TransactionState): string {\n switch (state.status) {\n case 'pending':\n return 'Transaction pending...';\n case 'submitted':\n return 'Transaction submitted, waiting for confirmation...';\n case 'confirming':\n return `Confirming (${state.confirmations}/${state.requiredConfirmations})...`;\n case 'confirmed':\n return 'Transaction confirmed!';\n case 'failed':\n return `Transaction failed: ${state.error ?? 'Unknown error'}`;\n case 'dropped':\n return 'Transaction dropped from mempool';\n default:\n return 'Unknown status';\n }\n}\n","/**\n * Veridex Protocol SDK - Cross-Chain Manager\n * \n * Orchestrates cross-chain transfers including:\n * - VAA fetching and parsing\n * - Fee estimation (message + relayer fees)\n * - Transaction status tracking across chains\n * - Lifecycle callbacks for UI updates\n */\n\nimport { ethers } from 'ethers';\nimport {\n fetchVAA,\n fetchVAAByTxHash,\n parseVAA,\n parseVeridexPayload,\n encodeVAAToBytes,\n getSequenceFromTxReceipt,\n waitForGuardianSignatures,\n normalizeEmitterAddress,\n GUARDIAN_CONFIG,\n} from '../wormhole.js';\nimport type {\n BridgeParams,\n VAA,\n VeridexPayload,\n ChainConfig,\n} from './types.js';\n\n// ============================================================================\n// Types\n// ============================================================================\n\n/**\n * Cross-chain transfer lifecycle states\n */\nexport type CrossChainStatus =\n | 'preparing'\n | 'signing'\n | 'dispatching'\n | 'waiting_confirmations'\n | 'waiting_guardians'\n | 'vaa_ready'\n | 'relaying'\n | 'executing'\n | 'completed'\n | 'failed';\n\n/**\n * Progress callback for cross-chain operations\n */\nexport interface CrossChainProgress {\n status: CrossChainStatus;\n step: number;\n totalSteps: number;\n message: string;\n details?: {\n txHash?: string;\n sequence?: bigint;\n guardianSignatures?: number;\n requiredSignatures?: number;\n vaaReady?: boolean;\n destinationTxHash?: string;\n };\n}\n\n/**\n * Cross-chain transfer result\n */\nexport interface CrossChainResult {\n /** Source chain transaction hash */\n sourceTxHash: string;\n /** Wormhole message sequence number */\n sequence: bigint;\n /** Emitter address (Hub contract) */\n emitterAddress: string;\n /** Source chain Wormhole ID */\n sourceChain: number;\n /** Destination chain Wormhole ID */\n destinationChain: number;\n /** VAA base64 (once ready) */\n vaa?: string;\n /** Parsed VAA */\n parsedVaa?: VAA;\n /** Destination chain transaction hash */\n destinationTxHash?: string;\n /** Total time taken in ms */\n duration: number;\n /** Final status */\n status: CrossChainStatus;\n /** Error message if failed */\n error?: string;\n}\n\n/**\n * Fee breakdown for cross-chain transfers\n */\nexport interface CrossChainFees {\n /** Gas cost on source chain */\n sourceGas: bigint;\n /** Wormhole message fee */\n messageFee: bigint;\n /** Relayer fee (if using automatic relay) */\n relayerFee: bigint;\n /** Total estimated cost in source chain native token */\n totalCost: bigint;\n /** Formatted total cost */\n formattedTotal: string;\n /** Currency symbol */\n currency: string;\n}\n\n/**\n * Configuration for CrossChainManager\n */\nexport interface CrossChainConfig {\n /** Use testnet APIs (default: true) */\n testnet?: boolean;\n /** Relayer service URL (optional) */\n relayerUrl?: string;\n /** Max time to wait for VAA (ms) */\n vaaTimeoutMs?: number;\n /** Interval to poll for VAA (ms) */\n vaaPollingIntervalMs?: number;\n /** Required block confirmations before fetching VAA */\n confirmationsRequired?: number;\n /** Auto-relay VAA to destination (requires relayer) */\n autoRelay?: boolean;\n}\n\n/**\n * Callback type for progress updates\n */\nexport type CrossChainProgressCallback = (progress: CrossChainProgress) => void;\n\n// ============================================================================\n// Default Configuration\n// ============================================================================\n\nconst DEFAULT_CONFIG: Required<CrossChainConfig> = {\n testnet: true,\n relayerUrl: '',\n vaaTimeoutMs: 120_000, // 2 minutes\n vaaPollingIntervalMs: 3_000, // 3 seconds\n confirmationsRequired: 1,\n autoRelay: false,\n};\n\n// ============================================================================\n// CrossChainManager Class\n// ============================================================================\n\n/**\n * Manages cross-chain transfer lifecycle\n */\nexport class CrossChainManager {\n private config: Required<CrossChainConfig>;\n private pendingTransfers: Map<string, CrossChainResult> = new Map();\n\n constructor(config: CrossChainConfig = {}) {\n this.config = { ...DEFAULT_CONFIG, ...config };\n }\n\n // ========================================================================\n // Configuration\n // ========================================================================\n\n /**\n * Update configuration\n */\n setConfig(config: Partial<CrossChainConfig>): void {\n this.config = { ...this.config, ...config };\n }\n\n /**\n * Get current configuration\n */\n getConfig(): CrossChainConfig {\n return { ...this.config };\n }\n\n // ========================================================================\n // Fee Estimation\n // ========================================================================\n\n /**\n * Estimate fees for a cross-chain transfer\n */\n async estimateFees(\n params: BridgeParams,\n sourceChainConfig: ChainConfig,\n provider: ethers.Provider\n ): Promise<CrossChainFees> {\n // Get current gas price\n const feeData = await provider.getFeeData();\n const gasPrice = feeData.gasPrice ?? 0n;\n \n // Estimate gas for dispatch (Hub chain)\n // This is an approximation - actual gas depends on payload size\n const estimatedGas = 300_000n;\n const sourceGas = estimatedGas * gasPrice;\n\n // Get Wormhole message fee\n let messageFee = 0n;\n try {\n const wormholeAbi = ['function messageFee() view returns (uint256)'];\n const wormhole = new ethers.Contract(\n sourceChainConfig.contracts.wormholeCoreBridge,\n wormholeAbi,\n provider\n );\n messageFee = await wormhole.messageFee();\n } catch {\n // Default to 0 if bridge doesn't have messageFee\n }\n\n // Get relayer fee if using automatic relay\n let relayerFee = 0n;\n if (this.config.autoRelay && this.config.relayerUrl) {\n try {\n relayerFee = await this.fetchRelayerFee(\n params.destinationChain,\n sourceChainConfig.wormholeChainId\n );\n } catch {\n // Relayer fee fetch failed, continue with 0\n }\n }\n\n const totalCost = sourceGas + messageFee + relayerFee;\n\n return {\n sourceGas,\n messageFee,\n relayerFee,\n totalCost,\n formattedTotal: this.formatWei(totalCost),\n currency: 'ETH',\n };\n }\n\n /**\n * Fetch relayer fee from relayer service\n */\n private async fetchRelayerFee(\n destinationChain: number,\n _sourceChain: number\n ): Promise<bigint> {\n if (!this.config.relayerUrl) {\n return 0n;\n }\n\n // The current Veridex relayer exposes a simplified fee endpoint.\n // Source chain is accepted here for future-proofing but not required by the API today.\n const response = await fetch(\n `${this.config.relayerUrl}/api/v1/fee?targetChain=${destinationChain}`\n );\n\n if (!response.ok) {\n throw new Error('Failed to fetch relayer fee');\n }\n\n const data = await response.json() as {\n fees?: {\n wormhole?: string;\n relayer?: string;\n total?: string;\n };\n };\n\n return BigInt(data.fees?.relayer ?? '0');\n }\n\n // ========================================================================\n // VAA Operations\n // ========================================================================\n\n /**\n * Fetch VAA by sequence number\n */\n async fetchVAA(\n emitterChain: number,\n emitterAddress: string,\n sequence: bigint,\n onProgress?: CrossChainProgressCallback\n ): Promise<string> {\n onProgress?.({\n status: 'waiting_guardians',\n step: 4,\n totalSteps: 6,\n message: 'Waiting for Wormhole guardians to sign...',\n details: { sequence },\n });\n\n const vaaBase64 = await fetchVAA(emitterChain, emitterAddress, sequence, {\n testnet: this.config.testnet,\n maxRetries: Math.ceil(this.config.vaaTimeoutMs / this.config.vaaPollingIntervalMs),\n retryDelayMs: this.config.vaaPollingIntervalMs,\n onRetry: (attempt, max) => {\n onProgress?.({\n status: 'waiting_guardians',\n step: 4,\n totalSteps: 6,\n message: `Waiting for guardians (attempt ${attempt}/${max})...`,\n details: { sequence },\n });\n },\n });\n\n onProgress?.({\n status: 'vaa_ready',\n step: 5,\n totalSteps: 6,\n message: 'VAA signed and ready!',\n details: { sequence, vaaReady: true },\n });\n\n return vaaBase64;\n }\n\n /**\n * Fetch VAA by transaction hash (more reliable)\n */\n async fetchVAAByTxHash(\n txHash: string,\n onProgress?: CrossChainProgressCallback\n ): Promise<string> {\n onProgress?.({\n status: 'waiting_guardians',\n step: 4,\n totalSteps: 6,\n message: 'Waiting for Wormhole guardians to sign...',\n details: { txHash },\n });\n\n const vaaBase64 = await fetchVAAByTxHash(txHash, {\n testnet: this.config.testnet,\n maxRetries: Math.ceil(this.config.vaaTimeoutMs / this.config.vaaPollingIntervalMs),\n retryDelayMs: this.config.vaaPollingIntervalMs,\n onRetry: (attempt, max) => {\n onProgress?.({\n status: 'waiting_guardians',\n step: 4,\n totalSteps: 6,\n message: `Waiting for guardians (attempt ${attempt}/${max})...`,\n details: { txHash },\n });\n },\n });\n\n onProgress?.({\n status: 'vaa_ready',\n step: 5,\n totalSteps: 6,\n message: 'VAA signed and ready!',\n details: { txHash, vaaReady: true },\n });\n\n return vaaBase64;\n }\n\n /**\n * Wait for guardians to sign a message with progress tracking\n */\n async waitForGuardians(\n emitterChain: number,\n emitterAddress: string,\n sequence: bigint,\n onProgress?: CrossChainProgressCallback\n ): Promise<VAA> {\n const requiredSignatures = this.config.testnet\n ? GUARDIAN_CONFIG.TESTNET_QUORUM\n : GUARDIAN_CONFIG.MAINNET_QUORUM;\n\n return await waitForGuardianSignatures(\n emitterChain,\n emitterAddress,\n sequence,\n {\n testnet: this.config.testnet,\n requiredSignatures,\n maxWaitMs: this.config.vaaTimeoutMs,\n checkIntervalMs: this.config.vaaPollingIntervalMs,\n onProgress: (current, required) => {\n onProgress?.({\n status: 'waiting_guardians',\n step: 4,\n totalSteps: 6,\n message: `Collecting signatures (${current}/${required})...`,\n details: {\n sequence,\n guardianSignatures: current,\n requiredSignatures: required,\n },\n });\n },\n }\n );\n }\n\n /**\n * Parse a VAA and extract Veridex payload\n */\n parseVAA(vaaBase64: string): { vaa: VAA; payload: VeridexPayload } {\n const vaa = parseVAA(vaaBase64);\n const payload = parseVeridexPayload(vaa.payload);\n return { vaa, payload };\n }\n\n /**\n * Encode VAA for on-chain submission\n */\n encodeVAAForSubmission(vaaBase64: string): string {\n return encodeVAAToBytes(vaaBase64);\n }\n\n // ========================================================================\n // Transfer Lifecycle\n // ========================================================================\n\n /**\n * Track a cross-chain transfer\n */\n trackTransfer(\n sourceTxHash: string,\n sourceChain: number,\n destinationChain: number,\n sequence: bigint,\n emitterAddress: string\n ): CrossChainResult {\n const result: CrossChainResult = {\n sourceTxHash,\n sequence,\n emitterAddress,\n sourceChain,\n destinationChain,\n duration: 0,\n status: 'waiting_guardians',\n };\n\n this.pendingTransfers.set(sourceTxHash, result);\n return result;\n }\n\n /**\n * Get pending transfer by source tx hash\n */\n getPendingTransfer(sourceTxHash: string): CrossChainResult | undefined {\n return this.pendingTransfers.get(sourceTxHash);\n }\n\n /**\n * Get all pending transfers\n */\n getAllPendingTransfers(): CrossChainResult[] {\n return Array.from(this.pendingTransfers.values()).filter(\n t => t.status !== 'completed' && t.status !== 'failed'\n );\n }\n\n /**\n * Update transfer status\n */\n updateTransfer(\n sourceTxHash: string,\n updates: Partial<CrossChainResult>\n ): CrossChainResult | undefined {\n const transfer = this.pendingTransfers.get(sourceTxHash);\n if (!transfer) return undefined;\n\n Object.assign(transfer, updates);\n return transfer;\n }\n\n /**\n * Complete transfer with VAA\n */\n completeTransfer(\n sourceTxHash: string,\n vaa: string,\n destinationTxHash?: string\n ): CrossChainResult | undefined {\n const transfer = this.pendingTransfers.get(sourceTxHash);\n if (!transfer) return undefined;\n\n transfer.vaa = vaa;\n transfer.parsedVaa = parseVAA(vaa);\n transfer.destinationTxHash = destinationTxHash;\n transfer.status = 'completed';\n\n return transfer;\n }\n\n /**\n * Mark transfer as failed\n */\n failTransfer(sourceTxHash: string, error: string): CrossChainResult | undefined {\n const transfer = this.pendingTransfers.get(sourceTxHash);\n if (!transfer) return undefined;\n\n transfer.status = 'failed';\n transfer.error = error;\n\n return transfer;\n }\n\n /**\n * Clear completed/failed transfers\n */\n clearFinishedTransfers(): void {\n for (const [hash, transfer] of this.pendingTransfers.entries()) {\n if (transfer.status === 'completed' || transfer.status === 'failed') {\n this.pendingTransfers.delete(hash);\n }\n }\n }\n\n // ========================================================================\n // Utilities\n // ========================================================================\n\n /**\n * Extract sequence from transaction receipt\n */\n async getSequenceFromTx(\n provider: ethers.Provider,\n txHash: string,\n wormholeCoreBridge: string\n ): Promise<bigint> {\n return await getSequenceFromTxReceipt(provider, txHash, wormholeCoreBridge);\n }\n\n /**\n * Normalize address to emitter format\n */\n normalizeAddress(address: string): string {\n return normalizeEmitterAddress(address);\n }\n\n /**\n * Get explorer URL for a cross-chain transfer\n */\n getExplorerUrl(\n txHash: string,\n _chain: 'source' | 'destination',\n explorerBaseUrl: string\n ): string {\n return `${explorerBaseUrl}/tx/${txHash}`;\n }\n\n /**\n * Get Wormholescan URL for VAA\n */\n getWormholeExplorerUrl(\n emitterChain: number,\n emitterAddress: string,\n sequence: bigint\n ): string {\n const base = this.config.testnet\n ? 'https://wormholescan.io/#/tx'\n : 'https://wormholescan.io/#/tx';\n \n const normalizedEmitter = normalizeEmitterAddress(emitterAddress);\n return `${base}/${emitterChain}/${normalizedEmitter}/${sequence.toString()}`;\n }\n\n /**\n * Format wei to human-readable string\n */\n private formatWei(wei: bigint): string {\n const eth = Number(wei) / 1e18;\n if (eth < 0.0001) {\n return `${(Number(wei) / 1e9).toFixed(4)} gwei`;\n }\n return `${eth.toFixed(6)} ETH`;\n }\n}\n\n// ============================================================================\n// Export singleton for convenience\n// ============================================================================\n\nexport const crossChainManager = new CrossChainManager();\n","/**\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 - Relayer Client\n * \n * Client for interacting with the Veridex relayer service.\n * The relayer automatically submits VAAs to destination chains.\n * \n * Features:\n * - Submit VAA for relay\n * - Check relay status\n * - Get supported routes\n * - Fee estimation\n */\n\n// ============================================================================\n// Types\n// ============================================================================\n\n/**\n * Relay request status\n */\nexport type RelayStatus =\n | 'pending'\n | 'processing'\n | 'submitted'\n | 'confirmed'\n | 'failed';\n\n/**\n * Relay request result\n */\nexport interface RelayRequest {\n /** Unique relay request ID */\n id: string;\n /** VAA sequence number */\n sequence: bigint;\n /** Source chain Wormhole ID */\n sourceChain: number;\n /** Destination chain Wormhole ID */\n destinationChain: number;\n /** Relay status */\n status: RelayStatus;\n /** Source transaction hash */\n sourceTxHash: string;\n /** Destination transaction hash (when completed) */\n destinationTxHash?: string;\n /** Timestamp when request was created */\n createdAt: number;\n /** Timestamp when request was last updated */\n updatedAt: number;\n /** Error message if failed */\n error?: string;\n /** Gas used on destination chain */\n gasUsed?: bigint;\n /** Fee paid */\n feePaid?: bigint;\n}\n\n/**\n * Supported route information\n */\nexport interface RelayRoute {\n /** Source chain Wormhole ID */\n sourceChain: number;\n /** Destination chain Wormhole ID */\n destinationChain: number;\n /** Whether the route is active */\n active: boolean;\n /** Estimated relay time in seconds */\n estimatedTimeSeconds: number;\n /** Base fee in destination chain native token */\n baseFee: bigint;\n /** Fee per gas unit */\n gasPrice: bigint;\n /** Maximum gas limit */\n maxGas: bigint;\n}\n\n/**\n * Relayer service info\n */\nexport interface RelayerInfo {\n /** Relayer name/identifier */\n name: string;\n /** Relayer version */\n version: string;\n /** Supported chains */\n supportedChains: number[];\n /** Available routes */\n routes: RelayRoute[];\n /** Whether the relayer is online */\n online: boolean;\n /** Current queue depth */\n queueDepth: number;\n}\n\n/**\n * Request body for submitting a signed action to the relayer (gasless)\n * Uses full WebAuthn data for authenticateAndDispatch\n */\nexport interface SubmitSignedActionRequest {\n /** WebAuthn authenticatorData (hex) */\n authenticatorData: string;\n /** WebAuthn clientDataJSON (raw string) */\n clientDataJSON: string;\n /** Index of \"challenge\":\"...\" in clientDataJSON */\n challengeIndex: number;\n /** Index of \"type\":\"...\" in clientDataJSON */\n typeIndex: number;\n /** P-256 signature r component (hex) */\n r: string;\n /** P-256 signature s component (hex) */\n s: string;\n /** P-256 public key X coordinate (hex) */\n publicKeyX: string;\n /** P-256 public key Y coordinate (hex) */\n publicKeyY: string;\n /** Target chain Wormhole ID */\n targetChain: number;\n /** Action payload (hex) */\n actionPayload: string;\n /** User nonce */\n nonce: number;\n}\n\n/**\n * Response from submitting a signed action\n */\nexport interface SubmitActionResult {\n /** Whether the submission was successful */\n success: boolean;\n /** Transaction hash on Hub chain */\n txHash?: string;\n /** Wormhole sequence number */\n sequence?: string;\n /** Error message if failed */\n error?: string;\n /** Human-readable message */\n message?: string;\n}\n\n/**\n * Query submission request (Issue #11/#12)\n * For optimistic execution via Wormhole Query proofs (~5-7s vs ~120s)\n */\nexport interface SubmitQueryRequest {\n /** Target spoke chain Wormhole ID */\n targetChain: number;\n /** User's key hash */\n userKeyHash: string;\n /** Serialized transaction for spoke chain */\n serializedTx: string; // hex\n /** Query proof with Guardian signatures */\n queryProof: {\n /** Raw query response bytes */\n queryResponse: string; // hex\n /** Guardian signatures */\n signatures: string; // hex\n };\n /** Whether to fallback to VAA if Query fails */\n fallbackToVaa?: boolean;\n /** Optional metadata */\n metadata?: {\n /** User's preferred execution path */\n preferredPath?: 'query' | 'vaa';\n /** Transaction value in USD (for routing decisions) */\n estimatedValueUSD?: number;\n };\n}\n\n/**\n * Query submission result (Issue #11/#12)\n */\nexport interface SubmitQueryResult {\n /** Whether submission succeeded */\n success: boolean;\n /** Transaction hash on spoke chain */\n txHash?: string;\n /** Execution path used */\n path: 'query' | 'vaa';\n /** Latency in milliseconds */\n latencyMs?: number;\n /** Error message if failed */\n error?: string;\n /** Whether fallback to VAA occurred */\n fellBack?: boolean;\n}\n\n/**\n * Fee quote for a relay\n */\nexport interface RelayFeeQuote {\n /** Source chain Wormhole ID */\n sourceChain: number;\n /** Destination chain Wormhole ID */\n destinationChain: number;\n /** Estimated fee in source chain native token */\n feeInSourceToken: bigint;\n /** Estimated fee in destination chain native token */\n feeInDestinationToken: bigint;\n /** Estimated gas on destination */\n estimatedGas: bigint;\n /** Quote expiration timestamp */\n expiresAt: number;\n /** Quote ID for submission */\n quoteId: string;\n}\n\n/**\n * Configuration for RelayerClient\n */\nexport interface RelayerClientConfig {\n /** Base URL of the relayer service */\n baseUrl: string;\n /** API key for authentication (optional) */\n apiKey?: string;\n /** Timeout for requests in ms */\n timeoutMs?: number;\n /** Max retries for failed requests */\n maxRetries?: number;\n}\n\n// ============================================================================\n// Default Configuration\n// ============================================================================\n\nconst DEFAULT_CONFIG: Required<Omit<RelayerClientConfig, 'baseUrl'>> = {\n apiKey: '',\n timeoutMs: 30_000,\n maxRetries: 3,\n};\n\n// ============================================================================\n// RelayerClient Class\n// ============================================================================\n\n/**\n * Client for the Veridex relayer service\n */\nexport class RelayerClient {\n private baseUrl: string;\n private config: Required<Omit<RelayerClientConfig, 'baseUrl'>>;\n\n constructor(config: RelayerClientConfig) {\n this.baseUrl = config.baseUrl.replace(/\\/+$/, ''); // Remove trailing slashes\n this.config = { ...DEFAULT_CONFIG, ...config };\n }\n\n // ========================================================================\n // Relay Operations\n // ========================================================================\n\n /**\n * Submit a VAA for relay to destination chain\n */\n async submitRelay(\n vaaBase64: string,\n sourceChain: number,\n destinationChain: number,\n sourceTxHash: string,\n sequence: bigint,\n feeQuoteId?: string\n ): Promise<RelayRequest> {\n void vaaBase64;\n void sourceChain;\n void destinationChain;\n void sourceTxHash;\n void sequence;\n void feeQuoteId;\n throw new Error(\n 'submitRelay() is not supported by the current Veridex relayer API. ' +\n 'Use submitSignedAction() and let the relayer observe hub events to relay automatically.'\n );\n }\n\n /**\n * Submit a signed action to the relayer for gasless execution\n * \n * This allows users to execute transfers without paying gas themselves.\n * The relayer will submit the transaction to the Hub chain and pay the gas.\n * The relayer then automatically relays the VAA to the destination spoke chain.\n * \n * @param request - The signed action request with passkey signature\n * @returns Result including Hub tx hash and Wormhole sequence\n */\n async submitSignedAction(request: SubmitSignedActionRequest): Promise<SubmitActionResult> {\n try {\n const response = await this.fetch('/api/v1/submit', {\n method: 'POST',\n body: JSON.stringify(request),\n });\n\n return {\n success: response.success,\n txHash: response.transactionHash ?? response.txHash,\n sequence: response.sequence,\n error: response.error,\n message: response.message,\n };\n } catch (err: any) {\n // Handle 400 errors gracefully - the relayer returns error details in the body\n if (err.status === 400 && err.body) {\n return {\n success: false,\n error: err.body.error ?? 'Relayer returned 400 Bad Request',\n message: err.body.message,\n };\n }\n // Re-throw other errors\n throw err;\n }\n }\n\n /**\n * Submit a Query-based transaction for optimistic execution (Issue #11/#12)\n * \n * Uses Wormhole Cross-Chain Queries (CCQ) to achieve ~5-7 second latency\n * vs ~120+ seconds for traditional VAA flow.\n * \n * Flow:\n * 1. Client fetches Hub state via queryHubState() from SDK\n * 2. Client constructs and signs transaction\n * 3. Client submits Query proof + tx to this endpoint\n * 4. Relayer validates format and submits to spoke chain\n * 5. Spoke chain verifies Guardian signatures on-chain\n * \n * @param request - Query submission with Guardian-signed proof\n * @returns Result including spoke tx hash and execution path\n */\n async submitQuery(request: SubmitQueryRequest): Promise<SubmitQueryResult> {\n try {\n const response = await this.fetch('/api/v1/submit-query', {\n method: 'POST',\n body: JSON.stringify(request),\n });\n\n return {\n success: response.success ?? false,\n txHash: response.txHash,\n path: response.path ?? 'query',\n latencyMs: response.latencyMs,\n error: response.error,\n fellBack: response.fellBack ?? false,\n };\n } catch (err: any) {\n // Handle errors gracefully\n if (err.status === 400 && err.body) {\n return {\n success: false,\n path: 'query',\n error: err.body.error ?? 'Relayer returned 400 Bad Request',\n };\n }\n throw err;\n }\n }\n\n /**\n * Get relay request status\n */\n async getRelayStatus(requestId: string): Promise<RelayRequest> {\n void requestId;\n throw new Error('getRelayStatus() is not supported by the current Veridex relayer API.');\n }\n\n /**\n * Get relay status by source transaction hash\n */\n async getRelayBySourceTx(sourceTxHash: string): Promise<RelayRequest | null> {\n void sourceTxHash;\n return null;\n }\n\n /**\n * Get relay status by sequence number\n */\n async getRelayBySequence(\n sourceChain: number,\n sequence: bigint\n ): Promise<RelayRequest | null> {\n void sourceChain;\n void sequence;\n return null;\n }\n\n /**\n * Cancel a pending relay request\n */\n async cancelRelay(requestId: string): Promise<boolean> {\n void requestId;\n return false;\n }\n\n /**\n * Poll for relay completion\n */\n async waitForRelay(\n requestId: string,\n timeoutMs: number = 120_000,\n pollingIntervalMs: number = 3_000,\n onProgress?: (status: RelayStatus) => void\n ): Promise<RelayRequest> {\n void requestId;\n void timeoutMs;\n void pollingIntervalMs;\n void onProgress;\n throw new Error('waitForRelay() is not supported by the current Veridex relayer API.');\n }\n\n // ========================================================================\n // Fee Estimation\n // ========================================================================\n\n /**\n * Get fee quote for a relay\n */\n async getFeeQuote(\n sourceChain: number,\n destinationChain: number,\n estimatedGas?: bigint\n ): Promise<RelayFeeQuote> {\n void sourceChain;\n void estimatedGas;\n\n // The relayer currently returns a simple fee breakdown; we map it into the\n // existing RelayFeeQuote shape with best-effort defaults.\n const response = await this.fetch(`/api/v1/fee?targetChain=${destinationChain}`);\n const relayerFee = BigInt(response?.fees?.relayer ?? '0');\n const total = BigInt(response?.fees?.total ?? relayerFee.toString());\n\n return {\n sourceChain: sourceChain,\n destinationChain,\n feeInSourceToken: total,\n feeInDestinationToken: relayerFee,\n estimatedGas: 0n,\n expiresAt: Date.now() + 60_000,\n quoteId: '',\n };\n }\n\n // ========================================================================\n // Service Info\n // ========================================================================\n\n /**\n * Get relayer service info\n */\n async getInfo(): Promise<RelayerInfo> {\n const response = await this.fetch('/api/v1/info');\n\n return {\n name: 'veridex-relayer',\n version: response?.relayer?.version ?? response?.version ?? 'unknown',\n supportedChains: (response?.supportedChains || []).map((c: any) => c.wormholeChainId ?? c),\n routes: [],\n online: true,\n queueDepth: 0,\n };\n }\n\n /**\n * Get supported routes\n */\n async getRoutes(): Promise<RelayRoute[]> {\n throw new Error('getRoutes() is not supported by the current Veridex relayer API.');\n }\n\n /**\n * Check if a route is supported\n */\n async isRouteSupported(\n sourceChain: number,\n destinationChain: number\n ): Promise<boolean> {\n void sourceChain;\n void destinationChain;\n return false;\n }\n\n /**\n * Check relayer health\n */\n async healthCheck(): Promise<boolean> {\n try {\n const response = await this.fetch('/health');\n return response.status === 'healthy' || response.status === 'degraded' || response.healthy === true;\n } catch {\n return false;\n }\n }\n\n // ========================================================================\n // Pending Relays\n // ========================================================================\n\n /**\n * Get all pending relay requests for a user\n */\n async getPendingRelays(userKeyHash: string): Promise<RelayRequest[]> {\n void userKeyHash;\n return [];\n }\n\n /**\n * Get relay history for a user\n */\n async getRelayHistory(\n userKeyHash: string,\n limit: number = 50,\n offset: number = 0\n ): Promise<RelayRequest[]> {\n void userKeyHash;\n void limit;\n void offset;\n return [];\n }\n\n // ========================================================================\n // Internal Helpers\n // ========================================================================\n\n /**\n * SDK version for telemetry\n */\n private static readonly SDK_VERSION = '1.0.0-beta.1';\n\n /**\n * Make an HTTP request to the relayer\n */\n private async fetch(\n path: string,\n options: RequestInit = {}\n ): Promise<any> {\n const headers: HeadersInit = {\n 'Content-Type': 'application/json',\n 'User-Agent': `@veridex/sdk/${RelayerClient.SDK_VERSION}`,\n ...(options.headers || {}),\n };\n\n if (this.config.apiKey) {\n (headers as Record<string, string>)['X-API-Key'] = this.config.apiKey;\n }\n\n const controller = new AbortController();\n const timeout = setTimeout(() => controller.abort(), this.config.timeoutMs);\n\n let lastError: Error | null = null;\n\n for (let attempt = 0; attempt <= this.config.maxRetries; attempt++) {\n try {\n const response = await fetch(`${this.baseUrl}${path}`, {\n ...options,\n headers,\n signal: controller.signal,\n });\n\n clearTimeout(timeout);\n\n if (!response.ok) {\n const error: any = new Error(\n `Relayer request failed: ${response.status} ${response.statusText}`\n );\n error.status = response.status;\n try {\n error.body = await response.json();\n } catch {\n // Ignore JSON parse errors\n }\n throw error;\n }\n\n return await response.json();\n } catch (error: any) {\n lastError = error;\n\n // Don't retry on client errors (4xx)\n if (error.status && error.status >= 400 && error.status < 500) {\n throw error;\n }\n\n // Don't retry on abort\n if (error.name === 'AbortError') {\n throw new Error('Request timeout');\n }\n\n // Wait before retry\n if (attempt < this.config.maxRetries) {\n await this.sleep(1000 * (attempt + 1));\n }\n }\n }\n\n throw lastError || new Error('Request failed after all retries');\n }\n\n /**\n * Sleep helper\n */\n private sleep(ms: number): Promise<void> {\n return new Promise(resolve => setTimeout(resolve, ms));\n }\n}\n\n// ============================================================================\n// Factory function\n// ============================================================================\n\n/**\n * Create a RelayerClient instance\n */\nexport function createRelayerClient(config: RelayerClientConfig): RelayerClient {\n return new RelayerClient(config);\n}\n","/**\n * Veridex Protocol SDK - Solana Chain Client\n * \n * Implementation of ChainClient interface for Solana blockchain\n */\n\nimport {\n Connection,\n PublicKey,\n} from '@solana/web3.js';\nimport {\n getAssociatedTokenAddressSync,\n} from '@solana/spl-token';\nimport { createHash } from 'crypto';\nimport type {\n ChainClient,\n ChainConfig,\n TransferParams,\n ExecuteParams,\n BridgeParams,\n DispatchResult,\n WebAuthnSignature,\n VaultCreationResult,\n} from '../../core/types.js';\nimport { encodeTransferAction, encodeExecuteAction, encodeBridgeAction } from '../../payload.js';\n\n// ============================================================================\n// Types\n// ============================================================================\n\nexport interface SolanaClientConfig {\n wormholeChainId: number;\n rpcUrl: string;\n programId: string; // Veridex Spoke program\n wormholeCoreBridge: string;\n tokenBridge: string;\n network?: 'mainnet' | 'devnet' | 'testnet';\n commitment?: 'processed' | 'confirmed' | 'finalized';\n}\n\n// ============================================================================\n// Constants\n// ============================================================================\n\n// ============================================================================\n// SolanaClient Class\n// ============================================================================\n\n/**\n * Solana implementation of the ChainClient interface\n */\nexport class SolanaClient implements ChainClient {\n private config: ChainConfig;\n private connection: Connection;\n private programId: PublicKey;\n\n constructor(config: SolanaClientConfig) {\n this.config = {\n name: `Solana ${config.network || 'mainnet'}`,\n chainId: config.wormholeChainId,\n wormholeChainId: config.wormholeChainId,\n rpcUrl: config.rpcUrl,\n explorerUrl: config.network === 'devnet'\n ? 'https://explorer.solana.com?cluster=devnet'\n : 'https://explorer.solana.com',\n isEvm: false,\n contracts: {\n hub: undefined, // Solana is a spoke only\n wormholeCoreBridge: config.wormholeCoreBridge,\n tokenBridge: config.tokenBridge,\n },\n };\n\n this.connection = new Connection(\n config.rpcUrl,\n config.commitment || 'confirmed'\n );\n this.programId = new PublicKey(config.programId);\n }\n\n getConfig(): ChainConfig {\n return this.config;\n }\n\n async getNonce(userKeyHash: string): Promise<bigint> {\n try {\n const vaultAddress = this.computeVaultAddressFromHash(userKeyHash);\n const accountInfo = await this.connection.getAccountInfo(new PublicKey(vaultAddress));\n\n if (!accountInfo || accountInfo.data.length < 40) {\n return 0n;\n }\n\n // Nonce is stored at offset 8 (after discriminator)\n // Read as u64 little-endian\n const nonce = accountInfo.data.readBigUInt64LE(8);\n return nonce;\n } catch (error) {\n console.error('Error getting nonce:', error);\n return 0n;\n }\n }\n\n async getMessageFee(): Promise<bigint> {\n try {\n // Query Wormhole bridge for message fee\n // For now, return a default estimate\n // TODO: Query on-chain Wormhole config account\n return 0n; // Solana doesn't charge a Wormhole fee in the same way\n } catch (error) {\n console.error('Error getting message fee:', error);\n return 0n;\n }\n }\n\n async buildTransferPayload(params: TransferParams): Promise<string> {\n return encodeTransferAction(\n params.token,\n params.recipient,\n params.amount\n );\n }\n\n async buildExecutePayload(params: ExecuteParams): Promise<string> {\n return encodeExecuteAction(\n params.target,\n params.value,\n params.data\n );\n }\n\n async buildBridgePayload(params: BridgeParams): Promise<string> {\n return encodeBridgeAction(\n params.token,\n params.amount,\n params.destinationChain,\n params.recipient\n );\n }\n\n async dispatch(\n signature: WebAuthnSignature,\n publicKeyX: bigint,\n publicKeyY: bigint,\n targetChain: number,\n actionPayload: string,\n nonce: bigint,\n signer: any // Solana Keypair or similar\n ): Promise<DispatchResult> {\n void signature;\n void publicKeyX;\n void publicKeyY;\n void targetChain;\n void actionPayload;\n void nonce;\n void signer;\n throw new Error(\n 'Direct dispatch not supported on Solana spoke chains. ' +\n 'Actions must be dispatched from the Hub (EVM) chain. ' +\n 'This client is for receiving cross-chain messages only.'\n );\n }\n\n /**\n * Dispatch an action via relayer (gasless)\n * Note: On Solana, this still goes through the Hub chain\n * Solana is a spoke-only chain in Veridex architecture\n */\n async dispatchGasless(\n signature: WebAuthnSignature,\n publicKeyX: bigint,\n publicKeyY: bigint,\n targetChain: number,\n actionPayload: string,\n nonce: bigint,\n relayerUrl: string\n ): Promise<DispatchResult> {\n // Compute key hash\n const keyHash = this.computeKeyHash(publicKeyX, publicKeyY);\n\n // Build the message that was signed (matches Hub chain format)\n const message = this.buildMessage(keyHash, targetChain, actionPayload, nonce);\n\n // Prepare request for relayer\n const request = {\n messageHash: message,\n r: '0x' + signature.r.toString(16).padStart(64, '0'),\n s: '0x' + signature.s.toString(16).padStart(64, '0'),\n publicKeyX: '0x' + publicKeyX.toString(16).padStart(64, '0'),\n publicKeyY: '0x' + publicKeyY.toString(16).padStart(64, '0'),\n targetChain,\n actionPayload,\n nonce: Number(nonce),\n };\n\n // Submit to relayer\n const response = await fetch(`${relayerUrl}/api/v1/submit`, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n },\n body: JSON.stringify(request),\n });\n\n if (!response.ok) {\n const error = await response.json().catch(() => ({ error: response.statusText }));\n throw new Error(`Relayer submission failed: ${error.error || response.statusText}`);\n }\n\n const result = await response.json();\n\n if (!result.success) {\n throw new Error(`Relayer submission failed: ${result.error}`);\n }\n\n return {\n transactionHash: result.txHash,\n sequence: BigInt(result.sequence || '0'),\n userKeyHash: keyHash,\n targetChain,\n };\n }\n\n async getVaultAddress(userKeyHash: string): Promise<string | null> {\n try {\n const vaultAddress = this.computeVaultAddressFromHash(userKeyHash);\n const accountInfo = await this.connection.getAccountInfo(new PublicKey(vaultAddress));\n\n if (!accountInfo) {\n return null;\n }\n\n return vaultAddress;\n } catch (error) {\n console.error('Error getting vault address:', error);\n return null;\n }\n }\n\n /**\n * Compute vault address using PDA (Program Derived Address)\n * Seeds: [\"vault\", userKeyHash]\n */\n computeVaultAddress(userKeyHash: string): string {\n return this.computeVaultAddressFromHash(userKeyHash);\n }\n\n private computeVaultAddressFromHash(userKeyHash: string): string {\n const userKeyHashBuffer = Buffer.from(userKeyHash.replace('0x', ''), 'hex');\n const [vaultPda] = PublicKey.findProgramAddressSync(\n [Buffer.from('vault'), userKeyHashBuffer],\n this.programId\n );\n return vaultPda.toBase58();\n }\n\n async vaultExists(userKeyHash: string): Promise<boolean> {\n const address = await this.getVaultAddress(userKeyHash);\n return address !== null;\n }\n\n async createVault(userKeyHash: string, signer: any): Promise<VaultCreationResult> {\n void userKeyHash;\n void signer;\n throw new Error(\n 'Vault creation on Solana must be done via relayer. ' +\n 'Use createVaultViaRelayer() instead.'\n );\n }\n\n async createVaultSponsored?(\n userKeyHash: string,\n sponsorPrivateKey: string,\n rpcUrl?: string\n ): Promise<VaultCreationResult> {\n void userKeyHash;\n void sponsorPrivateKey;\n void rpcUrl;\n throw new Error(\n 'Vault creation on Solana must be done via relayer. ' +\n 'Use createVaultViaRelayer() instead.'\n );\n }\n\n /**\n * Create a vault via the relayer (sponsored/gasless)\n * This is the recommended way to create Solana vaults\n */\n async createVaultViaRelayer(\n userKeyHash: string,\n relayerUrl: string\n ): Promise<VaultCreationResult> {\n const response = await fetch(`${relayerUrl}/api/v1/solana/vault`, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n },\n body: JSON.stringify({\n userKeyHash,\n chainId: this.config.wormholeChainId,\n }),\n });\n\n const result = await response.json();\n\n if (!response.ok || !result.success) {\n throw new Error(result.error || 'Failed to create vault via relayer');\n }\n\n return {\n address: result.vaultAddress,\n transactionHash: result.transactionHash || '',\n blockNumber: 0, // Solana doesn't have block numbers like EVM\n gasUsed: 0n, // Solana uses compute units, not gas\n alreadyExisted: !result.transactionHash,\n sponsoredBy: 'relayer',\n };\n }\n\n /**\n * Get vault info via relayer (includes existence check)\n */\n async getVaultViaRelayer(\n userKeyHash: string,\n relayerUrl: string\n ): Promise<{ vaultAddress: string; exists: boolean }> {\n const response = await fetch(\n `${relayerUrl}/api/v1/solana/vault/${userKeyHash}?chainId=${this.config.wormholeChainId}`\n );\n\n if (!response.ok) {\n throw new Error('Failed to get vault info from relayer');\n }\n\n const result = await response.json();\n return {\n vaultAddress: result.vaultAddress,\n exists: result.exists,\n };\n }\n\n async estimateVaultCreationGas(userKeyHash: string): Promise<bigint> {\n void userKeyHash;\n // Return SOL estimate for vault creation (rent + compute)\n // ~0.002 SOL for rent-exempt account + compute units\n return 2_000_000n; // 0.002 SOL in lamports\n }\n\n getFactoryAddress(): string | undefined {\n // Solana uses program addresses, not factory pattern\n return undefined;\n }\n\n getImplementationAddress(): string | undefined {\n // Solana uses program addresses, not implementation pattern\n return undefined;\n }\n\n // ========================================================================\n // Balance Methods\n // ========================================================================\n\n /**\n * Get native SOL balance\n */\n async getNativeBalance(address: string): Promise<bigint> {\n const balance = await this.connection.getBalance(new PublicKey(address));\n return BigInt(balance);\n }\n\n /**\n * Get SPL token balance\n */\n async getTokenBalance(tokenAddress: string, ownerAddress: string): Promise<bigint> {\n try {\n const mint = new PublicKey(tokenAddress);\n const owner = new PublicKey(ownerAddress);\n const ata = getAssociatedTokenAddressSync(mint, owner);\n\n const balance = await this.connection.getTokenAccountBalance(ata);\n return BigInt(balance.value.amount);\n } catch (error) {\n console.error('Error getting token balance:', error);\n return 0n;\n }\n }\n\n // ========================================================================\n // Utility Methods\n // ========================================================================\n\n /**\n * Compute key hash from public key coordinates\n * Matches EVM keccak256(abi.encode(publicKeyX, publicKeyY))\n */\n private computeKeyHash(publicKeyX: bigint, publicKeyY: bigint): string {\n // Use SHA-256 for Solana (Solana doesn't have keccak256 built-in)\n // The relayer will convert this to match EVM format\n const xBuffer = Buffer.alloc(32);\n const yBuffer = Buffer.alloc(32);\n\n // Write as big-endian to match EVM encoding\n const xHex = publicKeyX.toString(16).padStart(64, '0');\n const yHex = publicKeyY.toString(16).padStart(64, '0');\n\n Buffer.from(xHex, 'hex').copy(xBuffer);\n Buffer.from(yHex, 'hex').copy(yBuffer);\n\n // For cross-chain compatibility, we need to match the EVM hash\n // This should be keccak256, but we'll return a format the relayer expects\n const combined = Buffer.concat([xBuffer, yBuffer]);\n const hash = createHash('sha256').update(combined).digest();\n\n return '0x' + hash.toString('hex');\n }\n\n /**\n * Build message for signing (matches Hub chain format)\n */\n private buildMessage(\n keyHash: string,\n targetChain: number,\n actionPayload: string,\n nonce: bigint\n ): string {\n // This should match the EVM message format for cross-chain compatibility\n const keyHashBuffer = Buffer.from(keyHash.replace('0x', ''), 'hex');\n const targetChainBuffer = Buffer.alloc(2);\n targetChainBuffer.writeUInt16BE(targetChain);\n const payloadBuffer = Buffer.from(actionPayload.replace('0x', ''), 'hex');\n const nonceBuffer = Buffer.alloc(32);\n const nonceHex = nonce.toString(16).padStart(64, '0');\n Buffer.from(nonceHex, 'hex').copy(nonceBuffer);\n\n const combined = Buffer.concat([\n keyHashBuffer,\n targetChainBuffer,\n payloadBuffer,\n nonceBuffer,\n ]);\n\n const hash = createHash('sha256').update(combined).digest();\n return '0x' + hash.toString('hex');\n }\n\n /**\n * Get connection instance for advanced usage\n */\n getConnection(): Connection {\n return this.connection;\n }\n\n /**\n * Get program ID\n */\n getProgramId(): PublicKey {\n return this.programId;\n }\n\n /**\n * Get current slot\n */\n async getSlot(): Promise<number> {\n return await this.connection.getSlot();\n }\n\n /**\n * Get transaction status\n */\n async getTransaction(signature: string, commitment?: 'confirmed' | 'finalized') {\n return await this.connection.getTransaction(signature, {\n commitment: commitment || 'confirmed',\n maxSupportedTransactionVersion: 0,\n });\n }\n\n // ============================================================================\n // Social Recovery Methods (Issue #23)\n // ============================================================================\n // \n // Note: Social recovery is managed on the Hub chain (EVM).\n // Solana spokes receive and execute recovery VAAs broadcast from the Hub.\n // These methods are placeholders that indicate spoke-only chains don't\n // initiate recovery - they only execute recovery instructions from Hub VAAs.\n //\n // The relayer service handles:\n // 1. Fetching recovery VAAs from Wormhole guardians\n // 2. Submitting execute_recovery instruction to Solana spoke\n // 3. Processing OwnerRecovered events\n //\n // SDK users should use EVMClient methods for guardian management and\n // recovery initiation on the Hub chain.\n // ============================================================================\n\n /**\n * Check if a recovery VAA has been executed on this spoke\n * \n * @param vaaHash - Hash of the recovery VAA\n * @returns Whether the VAA has been processed\n */\n async isRecoveryExecuted(vaaHash: string): Promise<boolean> {\n try {\n // Derive VAA record PDA\n const vaaHashBuffer = Buffer.from(vaaHash.replace('0x', ''), 'hex');\n const [vaaRecordPda] = PublicKey.findProgramAddressSync(\n [Buffer.from('vaa_record'), vaaHashBuffer],\n this.programId\n );\n\n const accountInfo = await this.connection.getAccountInfo(vaaRecordPda);\n if (!accountInfo || accountInfo.data.length < 9) {\n return false;\n }\n\n // First byte after discriminator is 'processed' bool\n return accountInfo.data[8] === 1;\n } catch (error) {\n console.error('Error checking recovery execution:', error);\n return false;\n }\n }\n\n /**\n * Get vault owner after potential recovery\n * \n * @param vaultAddress - Vault address to check\n * @returns Current owner key hash\n */\n async getVaultOwner(vaultAddress: string): Promise<string> {\n try {\n const accountInfo = await this.connection.getAccountInfo(new PublicKey(vaultAddress));\n if (!accountInfo || accountInfo.data.length < 40) {\n throw new Error('Vault not found');\n }\n\n // Owner key hash is stored after discriminator (8 bytes) at offset 8-40\n const ownerKeyHash = accountInfo.data.slice(8, 40);\n return '0x' + ownerKeyHash.toString('hex');\n } catch (error) {\n console.error('Error getting vault owner:', error);\n throw error;\n }\n }\n\n /**\n * Get authorized signers for a vault\n * \n * @param vaultAddress - Vault address to check\n * @returns Array of authorized signer key hashes\n */\n async getAuthorizedSigners(vaultAddress: string): Promise<string[]> {\n try {\n const accountInfo = await this.connection.getAccountInfo(new PublicKey(vaultAddress));\n if (!accountInfo || accountInfo.data.length < 235) {\n throw new Error('Vault not found');\n }\n\n // Vault layout:\n // 8 bytes discriminator\n // 32 bytes owner_key_hash\n // 8 bytes nonce\n // 1 byte paused\n // 8 bytes daily_limit\n // 8 bytes daily_spent\n // 8 bytes day_start\n // 1 byte bump\n // 1 byte authorized_signer_count\n // 5 * 32 bytes authorized_signers\n\n const signerCount = accountInfo.data[66]; // offset 8+32+8+1+8+8+1 = 66\n const signers: string[] = [];\n\n for (let i = 0; i < signerCount; i++) {\n const offset = 67 + (i * 32); // Start of authorized_signers array\n const keyHash = accountInfo.data.slice(offset, offset + 32);\n signers.push('0x' + keyHash.toString('hex'));\n }\n\n return signers;\n } catch (error) {\n console.error('Error getting authorized signers:', error);\n throw error;\n }\n }\n}\n","/**\n * Veridex Protocol SDK - Payload Encoding/Decoding Utilities\n */\n\nimport { ethers } from 'ethers';\nimport {\n ACTION_TRANSFER,\n ACTION_EXECUTE,\n ACTION_CONFIG,\n ACTION_BRIDGE,\n PROTOCOL_VERSION,\n} from './constants.js';\nimport type { TransferAction, BridgeAction, ExecuteAction, ActionPayload } from './types.js';\n\n// ============================================================================\n// Action Encoding\n// ============================================================================\n\n/**\n * Encode a transfer action payload\n * Format: [actionType(1)] [token(32)] [recipient(32)] [amount(32)]\n */\nexport function encodeTransferAction(\n token: string,\n recipient: string,\n amount: bigint\n): string {\n const tokenPadded = padTo32Bytes(token);\n const recipientPadded = padTo32Bytes(recipient);\n const amountBytes = ethers.zeroPadValue(ethers.toBeHex(amount), 32);\n\n return ethers.concat([\n ethers.toBeHex(ACTION_TRANSFER, 1),\n tokenPadded,\n recipientPadded,\n amountBytes,\n ]);\n}\n\n/**\n * Encode a bridge action payload\n * Format: [actionType(1)] [token(32)] [amount(32)] [targetChain(2)] [recipient(32)]\n */\nexport function encodeBridgeAction(\n token: string,\n amount: bigint,\n targetChain: number,\n recipient: string\n): string {\n const tokenPadded = padTo32Bytes(token);\n const amountBytes = ethers.zeroPadValue(ethers.toBeHex(amount), 32);\n const targetChainBytes = ethers.toBeHex(targetChain, 2);\n const recipientPadded = padTo32Bytes(recipient);\n\n return ethers.concat([\n ethers.toBeHex(ACTION_BRIDGE, 1),\n tokenPadded,\n amountBytes,\n targetChainBytes,\n recipientPadded,\n ]);\n}\n\n/**\n * Encode an execute action payload (arbitrary contract call)\n * Format: [actionType(1)] [target(32)] [value(32)] [dataLength(2)] [data(variable)]\n */\nexport function encodeExecuteAction(\n target: string,\n value: bigint,\n data: string\n): string {\n const targetPadded = padTo32Bytes(target);\n const valueBytes = ethers.zeroPadValue(ethers.toBeHex(value), 32);\n const dataBytes = ethers.getBytes(data);\n const dataLengthBytes = ethers.toBeHex(dataBytes.length, 2);\n\n return ethers.concat([\n ethers.toBeHex(ACTION_EXECUTE, 1),\n targetPadded,\n valueBytes,\n dataLengthBytes,\n data,\n ]);\n}\n\n/**\n * Encode a config action payload\n * Format: [actionType(1)] [configType(1)] [configData(variable)]\n */\nexport function encodeConfigAction(configType: number, configData: string): string {\n return ethers.concat([\n ethers.toBeHex(ACTION_CONFIG, 1),\n ethers.toBeHex(configType, 1),\n configData,\n ]);\n}\n\n// ============================================================================\n// Veridex Payload Encoding\n// ============================================================================\n\n/**\n * Encode the full Veridex message payload that gets published via Wormhole\n * Format: [version(1)] [userKeyHash(32)] [targetChain(2)] [nonce(32)] [pubKeyX(32)] [pubKeyY(32)] [actionPayload]\n */\nexport function encodeVeridexPayload(\n userKeyHash: string,\n targetChain: number,\n nonce: bigint,\n publicKeyX: bigint,\n publicKeyY: bigint,\n actionPayload: string\n): string {\n return ethers.concat([\n ethers.toBeHex(PROTOCOL_VERSION, 1),\n userKeyHash,\n ethers.toBeHex(targetChain, 2),\n ethers.zeroPadValue(ethers.toBeHex(nonce), 32),\n ethers.zeroPadValue(ethers.toBeHex(publicKeyX), 32),\n ethers.zeroPadValue(ethers.toBeHex(publicKeyY), 32),\n actionPayload,\n ]);\n}\n\n// ============================================================================\n// Action Decoding\n// ============================================================================\n\n/**\n * Decode an action payload to determine its type and contents\n */\nexport function decodeActionPayload(payload: string): ActionPayload {\n const data = ethers.getBytes(payload);\n const actionType = data[0];\n\n switch (actionType) {\n case ACTION_TRANSFER:\n return decodeTransferAction(payload);\n case ACTION_BRIDGE:\n return decodeBridgeAction(payload);\n case ACTION_EXECUTE:\n return decodeExecuteAction(payload);\n default:\n return { type: `unknown_${actionType}`, raw: payload };\n }\n}\n\n/**\n * Decode a transfer action payload\n */\nexport function decodeTransferAction(payload: string): TransferAction {\n const data = ethers.getBytes(payload);\n\n const tokenBytes = data.slice(1, 33);\n const recipientBytes = data.slice(33, 65);\n const amountBytes = data.slice(65, 97);\n\n return {\n type: 'transfer',\n token: trimTo20Bytes(ethers.hexlify(tokenBytes)),\n recipient: trimTo20Bytes(ethers.hexlify(recipientBytes)),\n amount: BigInt(ethers.hexlify(amountBytes)),\n };\n}\n\n/**\n * Decode a bridge action payload\n */\nexport function decodeBridgeAction(payload: string): BridgeAction {\n const data = ethers.getBytes(payload);\n\n const tokenBytes = data.slice(1, 33);\n const amountBytes = data.slice(33, 65);\n const targetChainByte0 = data[65];\n const targetChainByte1 = data[66];\n const recipientBytes = data.slice(67, 99);\n\n const targetChain = ((targetChainByte0 ?? 0) << 8) | (targetChainByte1 ?? 0);\n\n return {\n type: 'bridge',\n token: trimTo20Bytes(ethers.hexlify(tokenBytes)),\n amount: BigInt(ethers.hexlify(amountBytes)),\n targetChain,\n recipient: ethers.hexlify(recipientBytes),\n };\n}\n\n/**\n * Decode an execute action payload\n */\nexport function decodeExecuteAction(payload: string): ExecuteAction {\n const data = ethers.getBytes(payload);\n\n const targetBytes = data.slice(1, 33);\n const valueBytes = data.slice(33, 65);\n const dataLengthByte0 = data[65];\n const dataLengthByte1 = data[66];\n const dataLength = ((dataLengthByte0 ?? 0) << 8) | (dataLengthByte1 ?? 0);\n const callData = data.slice(67, 67 + dataLength);\n\n return {\n type: 'execute',\n target: trimTo20Bytes(ethers.hexlify(targetBytes)),\n value: BigInt(ethers.hexlify(valueBytes)),\n data: ethers.hexlify(callData),\n };\n}\n\n// ============================================================================\n// Chain-Specific Encodings\n// ============================================================================\n\n/**\n * Encode a Solana-compatible transfer action\n * Solana uses: [actionType(1)] [amount(8 LE)] [recipient(32)]\n */\nexport function encodeSolanaTransferAction(\n amount: bigint,\n recipient: string\n): string {\n const amountBytes = Buffer.alloc(8);\n amountBytes.writeBigUInt64LE(amount);\n\n const recipientBytes = ethers.getBytes(recipient);\n\n return ethers.hexlify(\n Buffer.concat([\n Buffer.from([ACTION_TRANSFER]),\n amountBytes,\n Buffer.from(recipientBytes),\n ])\n );\n}\n\n/**\n * Encode an Aptos-compatible transfer action\n * Aptos uses: [actionType(1)] [amount(8 LE)] [recipient(32)]\n */\nexport function encodeAptosTransferAction(\n amount: bigint,\n recipient: string\n): string {\n const amountBytes = Buffer.alloc(8);\n amountBytes.writeBigUInt64LE(amount);\n\n const recipientPadded = padTo32Bytes(recipient);\n\n return ethers.hexlify(\n Buffer.concat([\n Buffer.from([ACTION_TRANSFER]),\n amountBytes,\n Buffer.from(ethers.getBytes(recipientPadded)),\n ])\n );\n}\n\n/**\n * Encode a Sui-compatible transfer action\n * Sui uses: [actionType(1)] [amount(8 LE)] [recipient(32)]\n */\nexport function encodeSuiTransferAction(\n amount: bigint,\n recipient: string\n): string {\n const amountBytes = Buffer.alloc(8);\n amountBytes.writeBigUInt64LE(amount);\n\n const recipientPadded = padTo32Bytes(recipient);\n\n return ethers.hexlify(\n Buffer.concat([\n Buffer.from([ACTION_TRANSFER]),\n amountBytes,\n Buffer.from(ethers.getBytes(recipientPadded)),\n ])\n );\n}\n\n// ============================================================================\n// Address Utilities\n// ============================================================================\n\n/**\n * Pad an address to 32 bytes (Wormhole standard)\n * Supports both EVM addresses (0x...) and Solana addresses (base58)\n */\nexport function padTo32Bytes(address: string): string {\n // Handle native token - convert to zero address\n if (address.toLowerCase() === 'native') {\n return '0x' + '0'.repeat(64);\n }\n \n // If it starts with 0x, treat as hex\n if (address.startsWith('0x')) {\n const hex = address.replace('0x', '');\n // Validate that hex only contains valid hex characters\n if (!/^[0-9a-fA-F]*$/.test(hex)) {\n throw new Error(`Invalid address: ${address}. Expected hex string or 'native'.`);\n }\n return '0x' + hex.padStart(64, '0');\n }\n \n // Otherwise, assume base58 Solana address and decode it\n // Base58 character set (Bitcoin/Solana style - no 0, O, I, l)\n const base58Chars = '123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz';\n \n // Validate base58 characters\n for (const char of address) {\n if (!base58Chars.includes(char)) {\n throw new Error(`Invalid address: ${address}. Contains invalid base58 character '${char}'.`);\n }\n }\n \n // Decode base58 to bytes\n let value = BigInt(0);\n for (const char of address) {\n value = value * 58n + BigInt(base58Chars.indexOf(char));\n }\n \n // Convert to 32-byte hex\n let hex = value.toString(16);\n // Ensure it's not longer than 64 chars (32 bytes)\n if (hex.length > 64) {\n throw new Error(`Invalid address: ${address}. Decoded value too large for 32 bytes.`);\n }\n \n return '0x' + hex.padStart(64, '0');\n}\n\n/**\n * Trim a 32-byte hex to a 20-byte EVM address\n */\nexport function trimTo20Bytes(hex32: string): string {\n const clean = hex32.replace('0x', '');\n return '0x' + clean.slice(-40);\n}\n\n/**\n * Convert a Solana public key (base58) to bytes32\n * @deprecated Use padTo32Bytes instead, which now handles both EVM and Solana addresses\n */\nexport function solanaAddressToBytes32(base58Address: string): string {\n return padTo32Bytes(base58Address);\n}\n\n// ============================================================================\n// Amount Utilities\n// ============================================================================\n\n/**\n * Format an amount with decimals for display\n */\nexport function formatAmount(amount: bigint, decimals = 18): string {\n const divisor = 10n ** BigInt(decimals);\n const whole = amount / divisor;\n const fraction = amount % divisor;\n\n if (fraction === 0n) {\n return whole.toString();\n }\n\n const fractionStr = fraction.toString().padStart(decimals, '0');\n const trimmedFraction = fractionStr.replace(/0+$/, '');\n\n return `${whole}.${trimmedFraction}`;\n}\n\n/**\n * Parse an amount string with decimals to bigint\n */\nexport function parseAmount(amountStr: string, decimals = 18): bigint {\n const parts = amountStr.split('.');\n const whole = BigInt(parts[0] ?? '0');\n\n if (parts.length === 1 || !parts[1]) {\n return whole * (10n ** BigInt(decimals));\n }\n\n const fractionStr = parts[1].slice(0, decimals).padEnd(decimals, '0');\n const fraction = BigInt(fractionStr);\n\n return whole * (10n ** BigInt(decimals)) + fraction;\n}\n\n// ============================================================================\n// Nonce Utilities\n// ============================================================================\n\n/**\n * Generate a unique nonce for a transaction\n */\nexport function generateNonce(): bigint {\n const timestamp = BigInt(Date.now());\n const random = BigInt(Math.floor(Math.random() * 1000000));\n return (timestamp << 20n) | random;\n}\n\n/**\n * Create a message hash for signing (used in authenticateRawAndDispatch)\n */\nexport function createMessageHash(\n targetChain: number,\n actionPayload: string,\n nonce: bigint\n): string {\n return ethers.keccak256(\n ethers.solidityPacked(\n ['uint16', 'bytes', 'uint256'],\n [targetChain, actionPayload, nonce]\n )\n );\n}\n\n/**\n * Create the challenge bytes for gasless dispatch (matches Hub's authenticateAndDispatch)\n * \n * The Hub contract passes raw packed bytes to WebAuthn.verify():\n * abi.encodePacked(targetChain, actionPayload, userNonce, hubChainId)\n * \n * The WebAuthn library then base64url-encodes these bytes to match against clientDataJSON.\n * We do NOT hash here - the challenge is the raw packed bytes.\n * \n * @param targetChain - Wormhole chain ID of the destination\n * @param actionPayload - The action payload (hex string)\n * @param nonce - User's current nonce\n * @param hubChainId - Wormhole chain ID of the Hub (e.g., 30 for Base)\n * @returns The packed bytes as hex string (NOT hashed)\n */\nexport function createGaslessMessageHash(\n targetChain: number,\n actionPayload: string,\n nonce: bigint,\n hubChainId: number\n): string {\n // Return raw packed bytes - NO sha256 hash\n // The contract passes these bytes directly to WebAuthn.verify()\n return ethers.solidityPacked(\n ['uint16', 'bytes', 'uint256', 'uint16'],\n [targetChain, actionPayload, nonce, hubChainId]\n );\n}\n\n/**\n * Build the challenge bytes for WebAuthn signing (gasless flow)\n * Returns raw packed bytes that match what the Hub contract expects\n * \n * @param targetChain - Wormhole chain ID of the destination\n * @param actionPayload - The action payload (hex string)\n * @param nonce - User's current nonce\n * @param hubChainId - Wormhole chain ID of the Hub\n * @returns Challenge bytes for WebAuthn signing (raw packed, not hashed)\n */\nexport function buildGaslessChallenge(\n targetChain: number,\n actionPayload: string,\n nonce: bigint,\n hubChainId: number\n): Uint8Array {\n const packed = createGaslessMessageHash(targetChain, actionPayload, nonce, hubChainId);\n return ethers.getBytes(packed);\n}\n\n/**\n * Build the challenge bytes for WebAuthn signing\n */\nexport function buildChallenge(\n userKeyHash: string,\n targetChain: number,\n nonce: bigint,\n actionPayload: string\n): Uint8Array {\n const encoded = ethers.solidityPacked(\n ['bytes32', 'uint16', 'uint256', 'bytes'],\n [userKeyHash, targetChain, nonce, actionPayload]\n );\n return ethers.getBytes(ethers.keccak256(encoded));\n}\n","/**\n * Veridex Protocol SDK - Aptos Chain Client\n * \n * Implementation of ChainClient interface for Aptos blockchain\n */\n\nimport { AptosClient as AptosSDK, Types } from 'aptos';\nimport { sha3_256 } from 'js-sha3';\nimport type {\n ChainClient,\n ChainConfig,\n TransferParams,\n ExecuteParams,\n BridgeParams,\n DispatchResult,\n WebAuthnSignature,\n VaultCreationResult,\n} from '../../core/types.js';\nimport { encodeTransferAction, encodeExecuteAction, encodeBridgeAction } from '../../payload.js';\n\n// ============================================================================\n// Types\n// ============================================================================\n\nexport interface AptosClientConfig {\n wormholeChainId: number;\n rpcUrl: string;\n moduleAddress: string; // Veridex Spoke module address\n wormholeCoreBridge: string;\n tokenBridge: string;\n network?: 'mainnet' | 'testnet' | 'devnet';\n}\n\n// ============================================================================\n// Constants\n// ============================================================================\n\n// ============================================================================\n// AptosClient Class\n// ============================================================================\n\n/**\n * Aptos implementation of the ChainClient interface\n */\nexport class AptosClient implements ChainClient {\n private config: ChainConfig;\n private client: AptosSDK;\n private moduleAddress: string;\n\n constructor(config: AptosClientConfig) {\n this.config = {\n name: `Aptos ${config.network || 'mainnet'}`,\n chainId: config.wormholeChainId,\n wormholeChainId: config.wormholeChainId,\n rpcUrl: config.rpcUrl,\n explorerUrl: config.network === 'testnet'\n ? 'https://explorer.aptoslabs.com?network=testnet'\n : 'https://explorer.aptoslabs.com',\n isEvm: false,\n contracts: {\n hub: undefined, // Aptos is a spoke only\n wormholeCoreBridge: config.wormholeCoreBridge,\n tokenBridge: config.tokenBridge,\n },\n };\n\n this.client = new AptosSDK(config.rpcUrl);\n this.moduleAddress = config.moduleAddress;\n }\n\n getConfig(): ChainConfig {\n return this.config;\n }\n\n async getNonce(userKeyHash: string): Promise<bigint> {\n try {\n const vaultAddress = this.computeVaultAddressFromHash(userKeyHash);\n\n // Query vault resource\n const resource = await this.client.getAccountResource(\n vaultAddress,\n `${this.moduleAddress}::vault::Vault`\n );\n\n if (resource && resource.data) {\n const data = resource.data as any;\n return BigInt(data.nonce || 0);\n }\n\n return 0n;\n } catch (error) {\n console.error('Error getting nonce:', error);\n return 0n;\n }\n }\n\n async getMessageFee(): Promise<bigint> {\n try {\n // Query Wormhole bridge for message fee\n // For now, return a default estimate\n // TODO: Query on-chain Wormhole config\n return 0n; // Aptos doesn't charge a Wormhole fee in the same way\n } catch (error) {\n console.error('Error getting message fee:', error);\n return 0n;\n }\n }\n\n async buildTransferPayload(params: TransferParams): Promise<string> {\n return encodeTransferAction(\n params.token,\n params.recipient,\n params.amount\n );\n }\n\n async buildExecutePayload(params: ExecuteParams): Promise<string> {\n return encodeExecuteAction(\n params.target,\n params.value,\n params.data\n );\n }\n\n async buildBridgePayload(params: BridgeParams): Promise<string> {\n return encodeBridgeAction(\n params.token,\n params.amount,\n params.destinationChain,\n params.recipient\n );\n }\n\n async dispatch(\n signature: WebAuthnSignature,\n publicKeyX: bigint,\n publicKeyY: bigint,\n targetChain: number,\n actionPayload: string,\n nonce: bigint,\n signer: any // Aptos AptosAccount\n ): Promise<DispatchResult> {\n void signature;\n void publicKeyX;\n void publicKeyY;\n void targetChain;\n void actionPayload;\n void nonce;\n void signer;\n throw new Error(\n 'Direct dispatch not supported on Aptos spoke chains. ' +\n 'Actions must be dispatched from the Hub (EVM) chain. ' +\n 'This client is for receiving cross-chain messages only.'\n );\n }\n\n /**\n * Dispatch an action via relayer (gasless)\n * Note: On Aptos, this still goes through the Hub chain\n * Aptos is a spoke-only chain in Veridex architecture\n */\n async dispatchGasless(\n signature: WebAuthnSignature,\n publicKeyX: bigint,\n publicKeyY: bigint,\n targetChain: number,\n actionPayload: string,\n nonce: bigint,\n relayerUrl: string\n ): Promise<DispatchResult> {\n // Compute key hash\n const keyHash = this.computeKeyHash(publicKeyX, publicKeyY);\n\n // Build the message that was signed (matches Hub chain format)\n const message = this.buildMessage(keyHash, targetChain, actionPayload, nonce);\n\n // Prepare request for relayer\n const request = {\n messageHash: message,\n r: '0x' + signature.r.toString(16).padStart(64, '0'),\n s: '0x' + signature.s.toString(16).padStart(64, '0'),\n publicKeyX: '0x' + publicKeyX.toString(16).padStart(64, '0'),\n publicKeyY: '0x' + publicKeyY.toString(16).padStart(64, '0'),\n targetChain,\n actionPayload,\n nonce: Number(nonce),\n };\n\n // Submit to relayer\n const response = await fetch(`${relayerUrl}/api/v1/submit`, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n },\n body: JSON.stringify(request),\n });\n\n if (!response.ok) {\n const error = await response.json().catch(() => ({ error: response.statusText }));\n throw new Error(`Relayer submission failed: ${error.error || response.statusText}`);\n }\n\n const result = await response.json();\n\n if (!result.success) {\n throw new Error(`Relayer submission failed: ${result.error}`);\n }\n\n return {\n transactionHash: result.txHash,\n sequence: BigInt(result.sequence || '0'),\n userKeyHash: keyHash,\n targetChain,\n };\n }\n\n /**\n * Get vault address from on-chain VaultRegistry.\n * Queries the get_vault_address view function which looks up the vault in the registry.\n */\n async getVaultAddress(userKeyHash: string): Promise<string | null> {\n try {\n // Query the on-chain VaultRegistry via view function\n // Module is veridex::spoke (not veridex_spoke)\n // Normalize keyHash to 0x-prefixed 64-char hex string\n const normalizedKeyHash = '0x' + userKeyHash.replace('0x', '').padStart(64, '0');\n \n const payload = {\n function: `${this.moduleAddress}::spoke::get_vault_address`,\n type_arguments: [],\n arguments: [normalizedKeyHash], // Pass as hex string, not byte array\n };\n\n const response = await this.client.view(payload);\n \n if (response && response.length > 0) {\n const vaultAddress = response[0] as string;\n return vaultAddress;\n }\n\n return null;\n } catch (error: any) {\n // E_VAULT_NOT_FOUND (error code 6) means vault doesn't exist in registry\n if (error?.message?.includes('E_VAULT_NOT_FOUND') || \n error?.message?.includes('error code 6') ||\n error?.status === 404) {\n return null;\n }\n console.error('Error getting vault address from registry:', error);\n return null;\n }\n }\n\n /**\n * @deprecated Use getVaultAddress() instead - this method uses incorrect address derivation.\n * On Aptos, vaults are created as named objects by the relayer, not resource accounts.\n * The vault address depends on which relayer created it, so must be queried on-chain.\n */\n computeVaultAddress(userKeyHash: string): string {\n console.warn(\n 'computeVaultAddress() is deprecated for Aptos. ' +\n 'Use getVaultAddress() to query the on-chain VaultRegistry instead.'\n );\n return this.computeVaultAddressFromHash(userKeyHash);\n }\n\n private computeVaultAddressFromHash(userKeyHash: string): string {\n // NOTE: This is kept for backward compatibility but produces INCORRECT addresses!\n // Aptos spoke uses object::create_named_object(creator, key_hash) where:\n // - creator = relayer address (not module address)\n // - scheme = 0xFD (named object, not 0xFE resource account)\n // The correct approach is to query the VaultRegistry on-chain.\n\n const sourceAddress = this.hexToBytes(this.moduleAddress.replace('0x', ''));\n const seed = this.hexToBytes(userKeyHash.replace('0x', ''));\n const scheme = new Uint8Array([0xFE]); // INCORRECT - kept for backward compat\n\n const combined = new Uint8Array([...sourceAddress, ...seed, ...scheme]);\n const hash = sha3_256(combined);\n\n return '0x' + hash;\n }\n\n /**\n * Convert hex string to Uint8Array (browser-compatible)\n */\n private hexToBytes(hex: string): Uint8Array {\n const bytes = new Uint8Array(hex.length / 2);\n for (let i = 0; i < hex.length; i += 2) {\n bytes[i / 2] = parseInt(hex.substr(i, 2), 16);\n }\n return bytes;\n }\n\n async vaultExists(userKeyHash: string): Promise<boolean> {\n const address = await this.getVaultAddress(userKeyHash);\n return address !== null;\n }\n\n async createVault(userKeyHash: string, signer: any): Promise<VaultCreationResult> {\n void userKeyHash;\n void signer;\n throw new Error(\n 'Vault creation on Aptos must be done via cross-chain message from Hub. ' +\n 'Use the Hub chain client to dispatch a vault creation action targeting Aptos.'\n );\n }\n\n async createVaultSponsored?(\n userKeyHash: string,\n sponsorPrivateKey: string,\n rpcUrl?: string\n ): Promise<VaultCreationResult> {\n void userKeyHash;\n void sponsorPrivateKey;\n void rpcUrl;\n throw new Error(\n 'Vault creation on Aptos must be done via cross-chain message from Hub. ' +\n 'Use relayer gasless submission to create vault.'\n );\n }\n\n /**\n * Create a vault via the relayer (sponsored/gasless)\n * This is the recommended way to create Aptos vaults\n * \n * The relayer will dispatch a vault creation action from Hub to Aptos spoke\n */\n async createVaultViaRelayer(\n userKeyHash: string,\n relayerUrl: string\n ): Promise<VaultCreationResult> {\n const response = await fetch(`${relayerUrl}/api/v1/aptos/vault`, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n },\n body: JSON.stringify({\n userKeyHash,\n chainId: this.config.wormholeChainId,\n }),\n });\n\n const result = await response.json();\n\n if (!response.ok || !result.success) {\n throw new Error(result.error || 'Failed to create vault via relayer');\n }\n\n return {\n address: result.vaultAddress,\n transactionHash: result.transactionHash || '',\n blockNumber: 0,\n gasUsed: 0n,\n alreadyExisted: result.alreadyExists || false,\n sponsoredBy: 'relayer',\n };\n }\n\n /**\n * Get vault info via relayer (includes existence check)\n */\n async getVaultViaRelayer(\n userKeyHash: string,\n relayerUrl: string\n ): Promise<{ vaultAddress: string; exists: boolean }> {\n const response = await fetch(\n `${relayerUrl}/api/v1/aptos/vault/${userKeyHash}?chainId=${this.config.wormholeChainId}`\n );\n\n if (!response.ok) {\n throw new Error('Failed to get vault info from relayer');\n }\n\n const result = await response.json();\n return {\n vaultAddress: result.vaultAddress,\n exists: result.exists,\n };\n }\n\n async estimateVaultCreationGas(userKeyHash: string): Promise<bigint> {\n void userKeyHash;\n // Return APT estimate for vault creation\n // ~0.001 APT for account creation + gas\n return 100_000n; // 0.001 APT in octas (1 APT = 100M octas)\n }\n\n getFactoryAddress(): string | undefined {\n // Aptos uses module addresses, not factory pattern\n return undefined;\n }\n\n getImplementationAddress(): string | undefined {\n // Aptos uses module addresses, not implementation pattern\n return undefined;\n }\n\n // ========================================================================\n // Balance Methods\n // ========================================================================\n\n /**\n * Get native APT balance\n */\n async getNativeBalance(address: string): Promise<bigint> {\n try {\n const resource = await this.client.getAccountResource(\n address,\n '0x1::coin::CoinStore<0x1::aptos_coin::AptosCoin>'\n );\n\n if (resource && resource.data) {\n const data = resource.data as any;\n return BigInt(data.coin?.value || 0);\n }\n\n return 0n;\n } catch (error) {\n console.error('Error getting native balance:', error);\n return 0n;\n }\n }\n\n /**\n * Get fungible asset (FA) or coin balance\n */\n async getTokenBalance(tokenAddress: string, ownerAddress: string): Promise<bigint> {\n try {\n // Try as Coin type first\n const coinType = tokenAddress.includes('::')\n ? tokenAddress\n : `${tokenAddress}::coin::Coin`;\n\n const resource = await this.client.getAccountResource(\n ownerAddress,\n `0x1::coin::CoinStore<${coinType}>`\n );\n\n if (resource && resource.data) {\n const data = resource.data as any;\n return BigInt(data.coin?.value || 0);\n }\n\n return 0n;\n } catch (error) {\n // If Coin query fails, try Fungible Asset (FA) format\n try {\n // FA balances are stored differently\n // Would need to query the FA resource\n console.warn('FA balance query not fully implemented yet');\n return 0n;\n } catch (faError) {\n console.error('Error getting token balance:', error);\n return 0n;\n }\n }\n }\n\n // ========================================================================\n // Utility Methods\n // ========================================================================\n\n /**\n * Compute key hash from public key coordinates\n * Matches EVM keccak256(abi.encode(publicKeyX, publicKeyY))\n */\n private computeKeyHash(publicKeyX: bigint, publicKeyY: bigint): string {\n // Write as big-endian to match EVM encoding\n const xHex = publicKeyX.toString(16).padStart(64, '0');\n const yHex = publicKeyY.toString(16).padStart(64, '0');\n\n const xBytes = this.hexToBytes(xHex);\n const yBytes = this.hexToBytes(yHex);\n\n // Use SHA3-256 for Aptos (which is what Aptos uses natively)\n // For cross-chain compatibility, this should match the EVM hash\n const combined = new Uint8Array([...xBytes, ...yBytes]);\n const hash = sha3_256(combined);\n\n return '0x' + hash;\n }\n\n /**\n * Build message for signing (matches Hub chain format)\n */\n private buildMessage(\n keyHash: string,\n targetChain: number,\n actionPayload: string,\n nonce: bigint\n ): string {\n const keyHashBytes = this.hexToBytes(keyHash.replace('0x', ''));\n const targetChainBytes = new Uint8Array(2);\n targetChainBytes[0] = (targetChain >> 8) & 0xFF;\n targetChainBytes[1] = targetChain & 0xFF;\n const payloadBytes = this.hexToBytes(actionPayload.replace('0x', ''));\n const nonceHex = nonce.toString(16).padStart(64, '0');\n const nonceBytes = this.hexToBytes(nonceHex);\n\n const combined = new Uint8Array([\n ...keyHashBytes,\n ...targetChainBytes,\n ...payloadBytes,\n ...nonceBytes,\n ]);\n\n const hash = sha3_256(combined);\n return '0x' + hash;\n }\n\n /**\n * Get Aptos client instance for advanced usage\n */\n getClient(): AptosSDK {\n return this.client;\n }\n\n /**\n * Get module address\n */\n getModuleAddress(): string {\n return this.moduleAddress;\n }\n\n /**\n * Get current ledger version\n */\n async getLedgerVersion(): Promise<bigint> {\n const ledgerInfo = await this.client.getLedgerInfo();\n return BigInt(ledgerInfo.ledger_version);\n }\n\n /**\n * Get transaction by hash\n */\n async getTransaction(txHash: string): Promise<Types.Transaction> {\n return await this.client.getTransactionByHash(txHash);\n }\n\n /**\n * Wait for transaction confirmation\n */\n async waitForTransaction(txHash: string, timeoutSecs: number = 30): Promise<Types.Transaction> {\n return await this.client.waitForTransactionWithResult(txHash, {\n timeoutSecs,\n checkSuccess: true,\n });\n }\n\n // ============================================================================\n // Social Recovery Methods (Issue #23)\n // ============================================================================\n // \n // Note: Social recovery is managed on the Hub chain (EVM).\n // Aptos spokes receive and execute recovery VAAs broadcast from the Hub.\n // The relayer service handles submitting recovery transactions to Aptos.\n //\n // SDK users should use EVMClient methods for guardian management and\n // recovery initiation on the Hub chain.\n // ============================================================================\n\n /**\n * Get vault resource for an owner\n * \n * @param ownerKeyHash - Owner's passkey hash (32 bytes as hex)\n * @returns Vault resource data or null if not found\n */\n async getVaultResource(ownerKeyHash: string): Promise<{\n ownerKeyHash: string;\n authorizedSigners: string[];\n nonce: bigint;\n } | null> {\n try {\n const vaultAddress = this.computeVaultAddressFromHash(ownerKeyHash);\n\n const resource = await this.client.getAccountResource(\n vaultAddress,\n `${this.moduleAddress}::vault::Vault`\n );\n\n if (!resource || !resource.data) {\n return null;\n }\n\n const data = resource.data as any;\n return {\n ownerKeyHash: data.owner_key_hash || ownerKeyHash,\n authorizedSigners: data.authorized_signers || [],\n nonce: BigInt(data.nonce || 0),\n };\n } catch (error) {\n console.error('Error getting vault resource:', error);\n return null;\n }\n }\n\n /**\n * Get authorized signers for a vault\n * \n * @param ownerKeyHash - Owner's passkey hash (32 bytes as hex)\n * @returns Array of authorized signer key hashes\n */\n async getAuthorizedSigners(ownerKeyHash: string): Promise<string[]> {\n const vaultResource = await this.getVaultResource(ownerKeyHash);\n return vaultResource?.authorizedSigners || [];\n }\n\n /**\n * Check if a VAA has been processed (for replay protection)\n * \n * @param vaaHash - VAA hash as hex string\n * @returns Whether the VAA has been processed\n */\n async isVaaProcessed(vaaHash: string): Promise<boolean> {\n try {\n const resource = await this.client.getAccountResource(\n this.moduleAddress,\n `${this.moduleAddress}::spoke::ProcessedVAAs`\n );\n\n if (!resource || !resource.data) {\n return false;\n }\n\n const data = resource.data as any;\n const processedVaas = data.processed || [];\n\n // Check if vaaHash is in the processed list\n const normalizedHash = vaaHash.toLowerCase().replace('0x', '');\n return processedVaas.some((hash: string) => \n hash.toLowerCase().replace('0x', '') === normalizedHash\n );\n } catch (error) {\n console.error('Error checking VAA status:', error);\n return false;\n }\n }\n\n /**\n * Check if protocol is paused\n * \n * @returns Whether the protocol is paused\n */\n async isProtocolPaused(): Promise<boolean> {\n try {\n const resource = await this.client.getAccountResource(\n this.moduleAddress,\n `${this.moduleAddress}::spoke::Config`\n );\n\n if (!resource || !resource.data) {\n return false;\n }\n\n const data = resource.data as any;\n return data.paused === true;\n } catch (error) {\n console.error('Error checking pause status:', error);\n return false;\n }\n }\n}\n","/**\n * Veridex Protocol SDK - Sui Chain Client\n *\n * Production-grade implementation of ChainClient interface for Sui.\n * Supports session management, query-based execution, and vault operations.\n *\n * Security:\n * - Native sui::ecdsa_k1::secp256k1_verify for signature validation\n * - CCQ-based session validation with 60s staleness window\n * - Replay protection via nonce verification\n *\n * Note: Sui is a spoke chain. Session registration/revocation happens on Hub.\n */\n\nimport { SuiClient as MystenSuiClient } from '@mysten/sui/client';\nimport { createHash } from 'crypto';\nimport type { SessionKey } from '../../sessions/types.js';\nimport type {\n ChainClient,\n ChainConfig,\n TransferParams,\n ExecuteParams,\n BridgeParams,\n DispatchResult,\n WebAuthnSignature,\n VaultCreationResult,\n RegisterSessionParams,\n RevokeSessionParams,\n SessionValidationResult,\n} from '../../core/types.js';\nimport { encodeTransferAction, encodeExecuteAction, encodeBridgeAction } from '../../payload.js';\n\n// ============================================================================\n// Types\n// ============================================================================\n\nexport interface SuiClientConfig {\n wormholeChainId: number;\n rpcUrl: string;\n packageId: string; // Veridex Spoke package ID\n wormholeCoreBridge: string;\n tokenBridge?: string;\n network?: 'mainnet' | 'testnet' | 'devnet';\n hubRpcUrl?: string; // Hub chain RPC for session management\n hubContractAddress?: string; // Hub contract for session management\n}\n\n// ============================================================================\n// SuiClient\n// ============================================================================\n\nexport class SuiClient implements ChainClient {\n private config: ChainConfig;\n private client: MystenSuiClient;\n private packageId: string;\n private hubRpcUrl?: string;\n private hubContractAddress?: string;\n\n constructor(config: SuiClientConfig) {\n this.config = {\n name: `Sui ${config.network || 'mainnet'}`,\n chainId: 0,\n wormholeChainId: config.wormholeChainId,\n rpcUrl: config.rpcUrl,\n explorerUrl: config.network === 'testnet'\n ? 'https://suiscan.xyz/testnet'\n : config.network === 'devnet'\n ? 'https://suiscan.xyz/devnet'\n : 'https://suiscan.xyz/mainnet',\n isEvm: false,\n contracts: {\n hub: config.packageId,\n wormholeCoreBridge: config.wormholeCoreBridge,\n tokenBridge: config.tokenBridge,\n },\n };\n\n this.client = new MystenSuiClient({ url: config.rpcUrl });\n this.packageId = config.packageId;\n this.hubRpcUrl = config.hubRpcUrl;\n this.hubContractAddress = config.hubContractAddress;\n }\n\n getConfig(): ChainConfig {\n return this.config;\n }\n\n async getNonce(_userKeyHash: string): Promise<bigint> {\n // Nonce is managed on the Hub for cross-chain actions.\n return 0n;\n }\n\n async getMessageFee(): Promise<bigint> {\n // Wormhole fees for Sui are generally handled by relayer submission.\n return 0n;\n }\n\n async buildTransferPayload(params: TransferParams): Promise<string> {\n return encodeTransferAction(params.token, params.recipient, params.amount);\n }\n\n async buildExecutePayload(params: ExecuteParams): Promise<string> {\n return encodeExecuteAction(params.target, params.value, params.data);\n }\n\n async buildBridgePayload(params: BridgeParams): Promise<string> {\n return encodeBridgeAction(params.token, params.amount, params.destinationChain, params.recipient);\n }\n\n async dispatch(\n signature: WebAuthnSignature,\n publicKeyX: bigint,\n publicKeyY: bigint,\n targetChain: number,\n actionPayload: string,\n nonce: bigint,\n signer: any\n ): Promise<DispatchResult> {\n void signature;\n void publicKeyX;\n void publicKeyY;\n void targetChain;\n void actionPayload;\n void nonce;\n void signer;\n throw new Error(\n 'Direct dispatch not supported on Sui spoke chains. ' +\n 'Actions must be dispatched from the Hub (EVM) chain. '\n );\n }\n\n async dispatchGasless(\n signature: WebAuthnSignature,\n publicKeyX: bigint,\n publicKeyY: bigint,\n targetChain: number,\n actionPayload: string,\n nonce: bigint,\n relayerUrl: string\n ): Promise<DispatchResult> {\n const keyHash = this.computeKeyHash(publicKeyX, publicKeyY);\n const messageHash = this.buildMessageHash(keyHash, targetChain, actionPayload, nonce);\n\n const request = {\n messageHash,\n r: '0x' + signature.r.toString(16).padStart(64, '0'),\n s: '0x' + signature.s.toString(16).padStart(64, '0'),\n publicKeyX: '0x' + publicKeyX.toString(16).padStart(64, '0'),\n publicKeyY: '0x' + publicKeyY.toString(16).padStart(64, '0'),\n targetChain,\n actionPayload,\n nonce: Number(nonce),\n };\n\n const response = await fetch(`${relayerUrl}/api/v1/submit`, {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify(request),\n });\n\n if (!response.ok) {\n throw new Error(`Relayer submission failed: ${response.status} ${response.statusText}`);\n }\n\n const result = await response.json();\n\n return {\n transactionHash: result.transactionHash ?? result.txHash,\n sequence: BigInt(result.sequence || 0),\n userKeyHash: keyHash,\n targetChain,\n };\n }\n\n async getVaultAddress(userKeyHash: string): Promise<string | null> {\n // Sui vaults may be represented as shared objects on-chain; without registry object IDs,\n // we return the deterministic address used by the SDK for receiving and balance display.\n return this.computeVaultAddress(userKeyHash);\n }\n\n computeVaultAddress(userKeyHash: string): string {\n // SDK convention: Sui addresses are 32-byte hex with 0x prefix.\n const clean = userKeyHash.replace(/^0x/, '').padStart(64, '0');\n return '0x' + clean;\n }\n\n async vaultExists(_userKeyHash: string): Promise<boolean> {\n // Account addresses on Sui are implicit; treat as existing.\n return true;\n }\n\n async createVault(userKeyHash: string, signer: any): Promise<VaultCreationResult> {\n void signer;\n throw new Error(\n 'Vault creation on Sui must be done via cross-chain message from Hub. ' +\n `Use the Hub client to dispatch a vault creation action targeting Sui (chain ${this.config.wormholeChainId}). KeyHash=${userKeyHash}`\n );\n }\n\n async createVaultSponsored?(userKeyHash: string, sponsorPrivateKey: string, rpcUrl?: string): Promise<VaultCreationResult> {\n void userKeyHash;\n void sponsorPrivateKey;\n void rpcUrl;\n throw new Error(\n 'Vault creation on Sui must be done via cross-chain message from Hub. ' +\n 'Use relayer gasless submission to create vault.'\n );\n }\n\n /**\n * Create a vault via the relayer (sponsored/gasless)\n * This is the recommended way to create Sui vaults\n * \n * The relayer will dispatch a vault creation action from Hub to Sui spoke\n */\n async createVaultViaRelayer(\n userKeyHash: string,\n relayerUrl: string\n ): Promise<VaultCreationResult> {\n const response = await fetch(`${relayerUrl}/api/v1/sui/vault`, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n },\n body: JSON.stringify({\n userKeyHash,\n chainId: this.config.wormholeChainId,\n }),\n });\n\n const result = await response.json();\n\n if (!response.ok || !result.success) {\n throw new Error(result.error || 'Failed to create vault via relayer');\n }\n\n return {\n address: result.vaultAddress,\n transactionHash: result.transactionHash || '',\n blockNumber: 0,\n gasUsed: 0n,\n alreadyExisted: result.alreadyExists || false,\n sponsoredBy: 'relayer',\n };\n }\n\n /**\n * Get vault info via relayer (includes existence check)\n */\n async getVaultViaRelayer(\n userKeyHash: string,\n relayerUrl: string\n ): Promise<{ vaultAddress: string; exists: boolean }> {\n const response = await fetch(\n `${relayerUrl}/api/v1/sui/vault/${userKeyHash}?chainId=${this.config.wormholeChainId}`\n );\n\n if (!response.ok) {\n throw new Error('Failed to get vault info from relayer');\n }\n\n const result = await response.json();\n return {\n vaultAddress: result.vaultAddress,\n exists: result.exists,\n };\n }\n\n async estimateVaultCreationGas(_userKeyHash: string): Promise<bigint> {\n // Best-effort placeholder.\n return 5_000n;\n }\n\n getFactoryAddress(): string | undefined {\n return undefined;\n }\n\n getImplementationAddress(): string | undefined {\n return undefined;\n }\n\n // ========================================================================\n // Balance utilities (used by VeridexSDK multichain)\n // ========================================================================\n\n async getNativeBalance(address: string): Promise<bigint> {\n const balance = await this.client.getBalance({ owner: address });\n return BigInt(balance.totalBalance);\n }\n\n async getTokenBalance(coinType: string, ownerAddress: string): Promise<bigint> {\n const balance = await this.client.getBalance({ owner: ownerAddress, coinType });\n return BigInt(balance.totalBalance);\n }\n\n getClient(): MystenSuiClient {\n return this.client;\n }\n\n getPackageId(): string {\n return this.packageId;\n }\n\n // ========================================================================\n // Session Management (Issue #13)\n // ========================================================================\n\n /**\n * Register a session key on the Hub (must be called via Hub client)\n * Sui spokes validate sessions via CCQ, but registration happens on Hub\n * \n * @throws Error - Session management must be done via Hub chain\n */\n async registerSession(_params: RegisterSessionParams): Promise<void> {\n throw new Error(\n 'Session registration must be performed on the Hub chain (Base). ' +\n 'Use EVMClient connected to the Hub to call registerSession().'\n );\n }\n\n /**\n * Revoke a session key on the Hub (must be called via Hub client)\n * \n * @throws Error - Session management must be done via Hub chain\n */\n async revokeSession(_params: RevokeSessionParams): Promise<void> {\n throw new Error(\n 'Session revocation must be performed on the Hub chain (Base). ' +\n 'Use EVMClient connected to the Hub to call revokeSession().'\n );\n }\n\n /**\n * Check if a session is active by querying the Hub\n * This method queries the Hub contract directly for session validation\n * \n * @param userKeyHash - Hash of user's Passkey public key\n * @param sessionKeyHash - Hash of session key to validate\n * @returns Session validation result with expiry and limits\n */\n async isSessionActive(\n _userKeyHash: string,\n _sessionKeyHash: string\n ): Promise<SessionValidationResult> {\n if (!this.hubRpcUrl || !this.hubContractAddress) {\n throw new Error(\n 'Hub configuration required for session validation. ' +\n 'Provide hubRpcUrl and hubContractAddress in SuiClientConfig.'\n );\n }\n\n // Query Hub contract for session status\n // This would normally use ethers.js to query the Hub contract\n // For production, import ethers dynamically or pass Hub client\n throw new Error(\n 'isSessionActive requires Hub client integration. ' +\n 'Use EVMClient.isSessionActive() on the Hub chain, ' +\n 'then pass the result to session execution on Sui.'\n );\n }\n\n /**\n * Get all sessions for a user from the Hub\n * \n * @param userKeyHash - Hash of user's Passkey public key\n * @returns Array of all sessions (active and expired/revoked)\n */\n async getUserSessions(userKeyHash: string): Promise<SessionKey[]> {\n if (!this.hubRpcUrl || !this.hubContractAddress) {\n throw new Error(\n 'Hub configuration required for session queries. ' +\n 'Provide hubRpcUrl and hubContractAddress in SuiClientConfig.'\n );\n }\n\n // Query Hub contract for user sessions\n throw new Error(\n 'getUserSessions requires Hub client integration. ' +\n 'Use EVMClient.getUserSessions() on the Hub chain. ' +\n `User: ${userKeyHash}`\n );\n }\n\n // ========================================================================\n // Query-Based Execution (Issue #9/#10)\n // ========================================================================\n\n /**\n * Get user state from Hub (comprehensive state query)\n * Returns key hash, nonce, and last action hash for CCQ validation\n * \n * @param userKeyHash - Hash of user's Passkey public key\n * @returns User state with nonce and last action hash\n */\n async getUserState(userKeyHash: string): Promise<{\n keyHash: string;\n nonce: bigint;\n lastActionHash: string;\n }> {\n if (!this.hubRpcUrl || !this.hubContractAddress) {\n throw new Error(\n 'Hub configuration required for state queries. ' +\n 'Provide hubRpcUrl and hubContractAddress in SuiClientConfig.'\n );\n }\n\n // Query Hub contract for user state\n // This enables query-based execution with CCQ validation\n throw new Error(\n 'getUserState requires Hub client integration. ' +\n 'Use EVMClient.getUserState() on the Hub chain. ' +\n `User: ${userKeyHash}`\n );\n }\n\n /**\n * Get user's last action hash from Hub\n * Used for optimistic execution and nonce validation\n * \n * @param userKeyHash - Hash of user's Passkey public key\n * @returns Last action hash (zero hash if no actions)\n */\n async getUserLastActionHash(userKeyHash: string): Promise<string> {\n if (!this.hubRpcUrl || !this.hubContractAddress) {\n throw new Error(\n 'Hub configuration required for action hash queries. ' +\n 'Provide hubRpcUrl and hubContractAddress in SuiClientConfig.'\n );\n }\n\n // Query Hub contract for last action hash\n throw new Error(\n 'getUserLastActionHash requires Hub client integration. ' +\n 'Use EVMClient.getUserLastActionHash() on the Hub chain. ' +\n `User: ${userKeyHash}`\n );\n }\n\n /**\n * Execute with query-based validation (faster than VAA, ~23s vs 60-90s)\n * Uses Wormhole CCQ to validate Hub state, then executes on Sui\n * \n * @param params Query execution parameters with CCQ response\n * @returns Dispatch result with transaction hash\n * \n * @remarks\n * Query-based execution flow:\n * 1. Query Hub state via Wormhole CCQ\n * 2. Validate Guardian signatures on query response\n * 3. Execute on Sui with validated state\n * 4. Hub state must be < 60s stale (enforced by QueryVerifier)\n */\n async executeWithQuery(\n _params: {\n userKeyHash: string;\n queryResponse: Uint8Array; // CCQ Guardian response\n actionType: number;\n actionPayload: Uint8Array;\n relayerUrl?: string;\n }\n ): Promise<DispatchResult> {\n throw new Error(\n 'Query-based execution on Sui requires relayer integration. ' +\n 'Use relayer API to submit query-validated transactions. ' +\n 'Relayer will call veridex_spoke::execute_with_query on Sui.'\n );\n }\n\n // ========================================================================\n // Internal helpers\n // ========================================================================\n\n private computeKeyHash(publicKeyX: bigint, publicKeyY: bigint): string {\n const xHex = publicKeyX.toString(16).padStart(64, '0');\n const yHex = publicKeyY.toString(16).padStart(64, '0');\n const combined = Buffer.from(xHex + yHex, 'hex');\n const hash = createHash('sha256').update(combined).digest('hex');\n return '0x' + hash;\n }\n\n private buildMessageHash(keyHash: string, targetChain: number, actionPayload: string, nonce: bigint): string {\n const keyHashBuffer = Buffer.from(keyHash.replace(/^0x/, ''), 'hex');\n const targetChainBuffer = Buffer.alloc(2);\n targetChainBuffer.writeUInt16BE(targetChain);\n const payloadBuffer = Buffer.from(actionPayload.replace(/^0x/, ''), 'hex');\n const nonceHex = nonce.toString(16).padStart(64, '0');\n const nonceBuffer = Buffer.from(nonceHex, 'hex');\n\n const combined = Buffer.concat([keyHashBuffer, targetChainBuffer, payloadBuffer, nonceBuffer]);\n const hash = createHash('sha256').update(combined).digest('hex');\n return '0x' + hash;\n }\n\n // ============================================================================\n // Social Recovery Methods (Issue #23)\n // ============================================================================\n // \n // Note: Social recovery is managed on the Hub chain (EVM).\n // Sui spokes receive and execute recovery VAAs broadcast from the Hub.\n // The relayer service handles submitting recovery transactions to Sui.\n //\n // SDK users should use EVMClient methods for guardian management and\n // recovery initiation on the Hub chain.\n // ============================================================================\n\n /**\n * Get vault object ID by owner key hash\n * \n * @param ownerKeyHash - Owner's passkey hash (32 bytes as hex)\n * @param configObjectId - Shared Config object ID\n * @param registryObjectId - Shared VaultRegistry object ID\n * @returns Vault object ID or null if not found\n */\n async getVaultId(\n ownerKeyHash: string,\n registryObjectId: string\n ): Promise<string | null> {\n try {\n // Query the VaultRegistry table for the owner_key_hash\n // The registry maps owner_key_hash -> vault ID\n const registryObject = await this.client.getObject({\n id: registryObjectId,\n options: { showContent: true },\n });\n\n if (!registryObject.data?.content) {\n return null;\n }\n\n // For a proper implementation, we'd need to query dynamic fields\n // or use a Move view function. This is a placeholder showing the pattern.\n console.warn('getVaultId requires dynamic field query - use Move view function');\n return null;\n } catch (error) {\n console.error('Error getting vault ID:', error);\n return null;\n }\n }\n\n /**\n * Get vault owner key hash from vault object\n * \n * @param vaultObjectId - Vault object ID\n * @returns Owner key hash as hex string\n */\n async getVaultOwner(vaultObjectId: string): Promise<string | null> {\n try {\n const vaultObject = await this.client.getObject({\n id: vaultObjectId,\n options: { showContent: true },\n });\n\n if (!vaultObject.data?.content || vaultObject.data.content.dataType !== 'moveObject') {\n return null;\n }\n\n const fields = vaultObject.data.content.fields as Record<string, unknown>;\n const ownerKeyHash = fields['owner_key_hash'] as number[] | undefined;\n\n if (!ownerKeyHash) {\n return null;\n }\n\n // Convert byte array to hex string\n return '0x' + Buffer.from(ownerKeyHash).toString('hex');\n } catch (error) {\n console.error('Error getting vault owner:', error);\n return null;\n }\n }\n\n /**\n * Get authorized signers for a vault\n * \n * @param vaultObjectId - Vault object ID\n * @returns Array of authorized signer key hashes\n */\n async getAuthorizedSigners(vaultObjectId: string): Promise<string[]> {\n try {\n const vaultObject = await this.client.getObject({\n id: vaultObjectId,\n options: { showContent: true },\n });\n\n if (!vaultObject.data?.content || vaultObject.data.content.dataType !== 'moveObject') {\n return [];\n }\n\n const fields = vaultObject.data.content.fields as Record<string, unknown>;\n const authorizedSigners = fields['authorized_signers'] as number[][] | undefined;\n\n if (!authorizedSigners) {\n return [];\n }\n\n // Convert each byte array to hex string\n return authorizedSigners.map(signer => \n '0x' + Buffer.from(signer).toString('hex')\n );\n } catch (error) {\n console.error('Error getting authorized signers:', error);\n return [];\n }\n }\n\n /**\n * Check if a VAA has been processed (for replay protection)\n * \n * @param vaaHash - VAA hash as hex string\n * @param processedVaasObjectId - ProcessedVAAs shared object ID\n * @returns Whether the VAA has been processed\n */\n async isVaaProcessed(\n vaaHash: string,\n processedVaasObjectId: string\n ): Promise<boolean> {\n try {\n const processedObject = await this.client.getObject({\n id: processedVaasObjectId,\n options: { showContent: true },\n });\n\n if (!processedObject.data?.content) {\n return false;\n }\n\n // Would need to query dynamic field for vaaHash key\n console.warn('isVaaProcessed requires dynamic field query');\n return false;\n } catch (error) {\n console.error('Error checking VAA status:', error);\n return false;\n }\n }\n\n /**\n * Check if protocol is paused\n * \n * @param configObjectId - Config shared object ID\n * @returns Whether the protocol is paused\n */\n async isProtocolPaused(configObjectId: string): Promise<boolean> {\n try {\n const configObject = await this.client.getObject({\n id: configObjectId,\n options: { showContent: true },\n });\n\n if (!configObject.data?.content || configObject.data.content.dataType !== 'moveObject') {\n return false;\n }\n\n const fields = configObject.data.content.fields as Record<string, unknown>;\n return fields['paused'] === true;\n } catch (error) {\n console.error('Error checking pause status:', error);\n return false;\n }\n }\n}\n","/**\n * Veridex Protocol SDK - Starknet Chain Client\n *\n * Production-grade implementation of ChainClient interface for Starknet.\n * Supports custom bridge attestation, gasless execution via Hub dispatch.\n *\n * Security:\n * - Native starknet::eth_signature::verify_eth_signature for validation\n * - Custom bridge with multi-relayer threshold attestations\n * - Replay protection via nonce verification on Hub\n * - Bridge validates source_chain == hub_chain_id (10004 = Base Sepolia)\n *\n * Architecture:\n * - Starknet actions MUST be dispatched via Hub (Base Sepolia)\n * - Hub publishes Wormhole message → relayer monitors → relayer submits attestation\n * - Bridge accumulates attestations → threshold reached → spoke executes\n * - Spoke validates source_chain == hubChainId (NOT targetChain)\n * \n * Custom Bridge:\n * - Bridge address: 0x2c458c1ae64556482b05cc2d3ee5b032ed114d68429dda2062c9849a5a725f8\n * - Chain ID: 50001 (custom range 50000+, reserved for non-Wormhole chains)\n * - Hub Chain ID: 10004 (Base Sepolia - what bridge validates as source)\n */\n\nimport type { SessionKey } from '../../sessions/types.js';\nimport type {\n ChainClient,\n ChainConfig,\n TransferParams,\n ExecuteParams,\n BridgeParams,\n DispatchResult,\n WebAuthnSignature,\n VaultCreationResult,\n RegisterSessionParams,\n RevokeSessionParams,\n SessionValidationResult,\n} from '../../core/types.js';\nimport { createHash } from 'crypto';\nimport { RpcProvider } from 'starknet';\nimport { encodeTransferAction, encodeExecuteAction, encodeBridgeAction } from '../../payload.js';\n\n// ============================================================================\n// Constants\n// ============================================================================\n\n// Starknet felt252 max value is 2^252 - 1\nconst FELT252_MAX = BigInt('0x0800000000000000000000000000000000000000000000000000000000000000') - 1n;\n\n// 2^128 for splitting u256 into low/high\nconst U128_MAX = BigInt('0x100000000000000000000000000000000');\n\n/**\n * Convert a 256-bit keyHash to Starknet u256 format (low, high felt252 pair).\n * Starknet u256 is represented as two felt252 values: (low_128_bits, high_128_bits)\n * \n * @param keyHash - 256-bit hex string (with or without 0x prefix)\n * @returns Array of two hex strings [low, high] for Starknet calldata\n */\nfunction toStarknetU256(keyHash: string): [string, string] {\n const cleanHash = keyHash.replace('0x', '').padStart(64, '0');\n const value = BigInt('0x' + cleanHash);\n \n // Split into low 128 bits and high 128 bits\n const low = value % U128_MAX;\n const high = value / U128_MAX;\n \n return [\n '0x' + low.toString(16),\n '0x' + high.toString(16)\n ];\n}\n\n/**\n * Truncate a 256-bit keyHash to fit within Starknet's felt252 (252-bit) field.\n * Clears the top 4 bits to ensure the value is < 2^252.\n * \n * @param keyHash - 256-bit hex string (with or without 0x prefix)\n * @returns felt252-compatible hex string with 0x prefix\n */\nfunction toStarknetFelt(keyHash: string): string {\n const cleanHash = keyHash.replace('0x', '');\n const value = BigInt('0x' + cleanHash);\n // Mask to felt252 range (clear top 4 bits)\n const masked = value & FELT252_MAX;\n return '0x' + masked.toString(16);\n}\n\n// ============================================================================\n// Types\n// ============================================================================\n\nexport interface StarknetClientConfig {\n wormholeChainId: number;\n rpcUrl: string;\n spokeContractAddress?: string;\n bridgeContractAddress?: string;\n network?: 'mainnet' | 'sepolia' | 'testnet';\n hubRpcUrl?: string; // Hub chain RPC for session management\n hubContractAddress?: string; // Hub contract for session management\n}\n\n// ============================================================================\n// StarknetClient\n// ============================================================================\n\nexport class StarknetClient implements ChainClient {\n private config: ChainConfig;\n private provider: RpcProvider;\n private hubRpcUrl?: string;\n private hubContractAddress?: string;\n\n constructor(config: StarknetClientConfig) {\n this.config = {\n name: `Starknet ${config.network || 'mainnet'}`,\n chainId: 0,\n wormholeChainId: config.wormholeChainId,\n rpcUrl: config.rpcUrl,\n explorerUrl: config.network === 'sepolia'\n ? 'https://sepolia.starkscan.co'\n : 'https://starkscan.co',\n isEvm: false,\n contracts: {\n hub: config.spokeContractAddress,\n wormholeCoreBridge: config.bridgeContractAddress ?? '',\n },\n };\n\n this.hubRpcUrl = config.hubRpcUrl;\n this.hubContractAddress = config.hubContractAddress;\n\n this.provider = new RpcProvider({ nodeUrl: config.rpcUrl });\n }\n\n getConfig(): ChainConfig {\n return this.config;\n }\n\n async getNonce(_userKeyHash: string): Promise<bigint> {\n return 0n;\n }\n\n async getMessageFee(): Promise<bigint> {\n return 0n;\n }\n\n async buildTransferPayload(params: TransferParams): Promise<string> {\n return encodeTransferAction(params.token, params.recipient, params.amount);\n }\n\n async buildExecutePayload(params: ExecuteParams): Promise<string> {\n return encodeExecuteAction(params.target, params.value, params.data);\n }\n\n async buildBridgePayload(params: BridgeParams): Promise<string> {\n return encodeBridgeAction(params.token, params.amount, params.destinationChain, params.recipient);\n }\n\n async dispatch(\n signature: WebAuthnSignature,\n publicKeyX: bigint,\n publicKeyY: bigint,\n targetChain: number,\n actionPayload: string,\n nonce: bigint,\n signer: any\n ): Promise<DispatchResult> {\n void signature;\n void publicKeyX;\n void publicKeyY;\n void targetChain;\n void actionPayload;\n void nonce;\n void signer;\n throw new Error(\n 'Direct dispatch not supported on Starknet. ' +\n 'Starknet actions are executed via the Veridex Hub (Base Sepolia) + custom bridge. ' +\n 'Use dispatchGasless() to route through relayer, which will submit attestations to the bridge.'\n );\n }\n\n async dispatchGasless(\n signature: WebAuthnSignature,\n publicKeyX: bigint,\n publicKeyY: bigint,\n targetChain: number,\n actionPayload: string,\n nonce: bigint,\n relayerUrl: string\n ): Promise<DispatchResult> {\n /**\n * Starknet gasless execution flow:\n * 1. User signs action with passkey (on client)\n * 2. SDK submits to relayer with targetChain=50001 (Starknet)\n * 3. Relayer dispatches to Hub (Base Sepolia) with targetChain=50001\n * 4. Hub publishes Wormhole message\n * 5. Relayer monitors Hub Dispatch event\n * 6. Relayer submits attestation to Starknet Bridge\n * 7. Bridge accumulates attestations from multiple relayers\n * 8. When threshold reached, Bridge calls spoke.execute()\n * 9. Spoke validates source_chain == hubChainId (10004)\n * 10. Spoke executes action on user's vault\n * \n * Result: Completely gasless for user - relayer pays all fees\n */\n const keyHash = this.computeKeyHash(publicKeyX, publicKeyY);\n\n // Submit to relayer for Hub dispatch + bridge attestation\n const request = {\n signature: {\n r: '0x' + signature.r.toString(16).padStart(64, '0'),\n s: '0x' + signature.s.toString(16).padStart(64, '0'),\n authenticatorData: signature.authenticatorData,\n clientDataJSON: signature.clientDataJSON,\n challengeIndex: signature.challengeIndex,\n typeIndex: signature.typeIndex,\n },\n publicKeyX: '0x' + publicKeyX.toString(16).padStart(64, '0'),\n publicKeyY: '0x' + publicKeyY.toString(16).padStart(64, '0'),\n targetChain, // 50001 for Starknet\n actionPayload,\n userNonce: Number(nonce),\n };\n\n const response = await fetch(`${relayerUrl}/api/v1/submit`, {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify(request),\n });\n\n if (!response.ok) {\n const errorText = await response.text().catch(() => 'Unknown error');\n throw new Error(\n `Relayer submission failed: ${response.status} ${response.statusText}. ` +\n `Error: ${errorText}`\n );\n }\n\n const result = await response.json();\n\n return {\n transactionHash: result.transactionHash ?? result.txHash ?? result.hubTxHash,\n sequence: BigInt(result.sequence || 0),\n userKeyHash: keyHash,\n targetChain,\n };\n }\n\n // Note: getVaultAddress is now defined in the Social Recovery section below\n // with enhanced spoke contract querying support.\n\n computeVaultAddress(userKeyHash: string): string {\n /**\n * Starknet vault derivation:\n * - Vaults are created via spoke contract\n * - Address is deterministic from userKeyHash\n * - Uses keyHash directly as vault identifier (felt252)\n * \n * Note: Actual vault address on Starknet may differ based on\n * spoke implementation. This is a best-effort derivation.\n */\n const clean = userKeyHash.replace(/^0x/, '');\n return '0x' + clean;\n }\n\n async vaultExists(userKeyHash: string): Promise<boolean> {\n /**\n * Check if vault exists on Starknet spoke\n * Best-effort: queries spoke contract if available\n */\n if (!this.config.contracts.hub) {\n return false;\n }\n\n try {\n const vaultAddress = await this.getVaultAddress(userKeyHash);\n if (!vaultAddress) {\n return false;\n }\n\n // Query Starknet RPC for contract code at vault address\n const anyProvider = this.provider as any;\n if (typeof anyProvider.getClassHashAt === 'function') {\n await anyProvider.getClassHashAt(vaultAddress);\n return true;\n }\n } catch {\n // Vault doesn't exist or RPC doesn't support query\n }\n\n return false;\n }\n\n async createVault(userKeyHash: string, signer: any): Promise<VaultCreationResult> {\n void signer;\n throw new Error(\n 'Vault creation on Starknet must be done via Hub dispatch + custom bridge attestation. ' +\n 'Use Hub client (Base Sepolia) to dispatch a CREATE_VAULT action with targetChain=50001. ' +\n `KeyHash=${userKeyHash}`\n );\n }\n\n async createVaultSponsored?(userKeyHash: string, sponsorPrivateKey: string, rpcUrl?: string): Promise<VaultCreationResult> {\n void userKeyHash;\n void sponsorPrivateKey;\n void rpcUrl;\n throw new Error(\n 'Vault creation on Starknet must be done via Hub dispatch + custom bridge attestation. ' +\n 'Use Hub client (Base Sepolia) with sponsor key to dispatch CREATE_VAULT action.'\n );\n }\n\n /**\n * Create a vault via the relayer (sponsored/gasless)\n * This is the recommended way to create Starknet vaults\n * \n * The relayer will dispatch a vault creation action from Hub via custom bridge to Starknet spoke\n */\n async createVaultViaRelayer(\n userKeyHash: string,\n relayerUrl: string\n ): Promise<VaultCreationResult> {\n const response = await fetch(`${relayerUrl}/api/v1/starknet/vault`, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n },\n body: JSON.stringify({\n userKeyHash,\n chainId: this.config.wormholeChainId,\n }),\n });\n\n const result = await response.json();\n\n if (!response.ok || !result.success) {\n throw new Error(result.error || 'Failed to create vault via relayer');\n }\n\n return {\n address: result.vaultAddress,\n transactionHash: result.transactionHash || '',\n blockNumber: 0,\n gasUsed: 0n,\n alreadyExisted: result.alreadyExists || false,\n sponsoredBy: 'relayer',\n };\n }\n\n /**\n * Get vault info via relayer (includes existence check)\n */\n async getVaultViaRelayer(\n userKeyHash: string,\n relayerUrl: string\n ): Promise<{ vaultAddress: string; exists: boolean }> {\n const response = await fetch(\n `${relayerUrl}/api/v1/starknet/vault/${userKeyHash}?chainId=${this.config.wormholeChainId}`\n );\n\n if (!response.ok) {\n throw new Error('Failed to get vault info from relayer');\n }\n\n const result = await response.json();\n return {\n vaultAddress: result.vaultAddress,\n exists: result.exists,\n };\n }\n\n async estimateVaultCreationGas(_userKeyHash: string): Promise<bigint> {\n return 0n;\n }\n\n getFactoryAddress(): string | undefined {\n return undefined;\n }\n\n getImplementationAddress(): string | undefined {\n return undefined;\n }\n\n // ========================================================================\n // Balance utility (best-effort)\n // ========================================================================\n\n async getNativeBalance(address: string): Promise<bigint> {\n // Best-effort: some Starknet RPCs support getBalance, but it is not universal.\n try {\n const anyProvider = this.provider as any;\n if (typeof anyProvider.getBalance === 'function') {\n const res = await anyProvider.getBalance(address);\n return BigInt(res);\n }\n } catch {\n // ignore\n }\n return 0n;\n }\n\n getProvider(): RpcProvider {\n return this.provider;\n }\n\n // ========================================================================\n // Session Management (Issue #13)\n // ========================================================================\n\n /**\n * Register a session key on the Hub (must be called via Hub client)\n * Starknet spokes validate sessions via CCQ, but registration happens on Hub\n * \n * @throws Error - Session management must be done via Hub chain\n */\n async registerSession(_params: RegisterSessionParams): Promise<void> {\n throw new Error(\n 'Session registration must be performed on the Hub chain (Base). ' +\n 'Use EVMClient connected to the Hub to call registerSession().'\n );\n }\n\n /**\n * Revoke a session key on the Hub (must be called via Hub client)\n * \n * @throws Error - Session management must be done via Hub chain\n */\n async revokeSession(_params: RevokeSessionParams): Promise<void> {\n throw new Error(\n 'Session revocation must be performed on the Hub chain (Base). ' +\n 'Use EVMClient connected to the Hub to call revokeSession().'\n );\n }\n\n /**\n * Check if a session is active by querying the Hub\n * This method queries the Hub contract directly for session validation\n * \n * @param userKeyHash - Hash of user's Passkey public key\n * @param sessionKeyHash - Hash of session key to validate\n * @returns Session validation result with expiry and limits\n */\n async isSessionActive(\n userKeyHash: string,\n sessionKeyHash: string\n ): Promise<SessionValidationResult> {\n if (!this.hubRpcUrl || !this.hubContractAddress) {\n throw new Error(\n 'Hub configuration required for session validation. ' +\n 'Provide hubRpcUrl and hubContractAddress in StarknetClientConfig.'\n );\n }\n\n // Query Hub contract for session status\n throw new Error(\n 'isSessionActive requires Hub client integration. ' +\n 'Use EVMClient.isSessionActive() on the Hub chain, ' +\n 'then pass the result to session execution on Starknet.'\n );\n }\n\n /**\n * Get all sessions for a user from the Hub\n * \n * @param userKeyHash - Hash of user's Passkey public key\n * @returns Array of all sessions (active and expired/revoked)\n */\n async getUserSessions(userKeyHash: string): Promise<SessionKey[]> {\n if (!this.hubRpcUrl || !this.hubContractAddress) {\n throw new Error(\n 'Hub configuration required for session queries. ' +\n 'Provide hubRpcUrl and hubContractAddress in StarknetClientConfig.'\n );\n }\n\n // Query Hub contract for user sessions\n throw new Error(\n 'getUserSessions requires Hub client integration. ' +\n 'Use EVMClient.getUserSessions() on the Hub chain. ' +\n `User: ${userKeyHash}`\n );\n }\n\n // ========================================================================\n // Query-Based Execution (Issue #9/#10)\n // ========================================================================\n\n /**\n * Get user state from Hub (comprehensive state query)\n * Returns key hash, nonce, and last action hash for CCQ validation\n * \n * @param userKeyHash - Hash of user's Passkey public key\n * @returns User state with nonce and last action hash\n */\n async getUserState(userKeyHash: string): Promise<{\n keyHash: string;\n nonce: bigint;\n lastActionHash: string;\n }> {\n if (!this.hubRpcUrl || !this.hubContractAddress) {\n throw new Error(\n 'Hub configuration required for state queries. ' +\n 'Provide hubRpcUrl and hubContractAddress in StarknetClientConfig.'\n );\n }\n\n // Query Hub contract for user state\n throw new Error(\n 'getUserState requires Hub client integration. ' +\n 'Use EVMClient.getUserState() on the Hub chain. ' +\n `User: ${userKeyHash}`\n );\n }\n\n /**\n * Get user's last action hash from Hub\n * Used for optimistic execution and nonce validation\n * \n * @param userKeyHash - Hash of user's Passkey public key\n * @returns Last action hash (zero hash if no actions)\n */\n async getUserLastActionHash(userKeyHash: string): Promise<string> {\n if (!this.hubRpcUrl || !this.hubContractAddress) {\n throw new Error(\n 'Hub configuration required for action hash queries. ' +\n 'Provide hubRpcUrl and hubContractAddress in StarknetClientConfig.'\n );\n }\n\n // Query Hub contract for last action hash\n throw new Error(\n 'getUserLastActionHash requires Hub client integration. ' +\n 'Use EVMClient.getUserLastActionHash() on the Hub chain. ' +\n `User: ${userKeyHash}`\n );\n }\n\n /**\n * Execute with query-based validation (faster than VAA, ~23s vs 60-90s)\n * Uses Wormhole CCQ to validate Hub state, then executes on Starknet\n * \n * @param params Query execution parameters with CCQ response\n * @returns Dispatch result with transaction hash\n * \n * @remarks\n * Query-based execution flow:\n * 1. Query Hub state via Wormhole CCQ\n * 2. Validate Guardian signatures on query response\n * 3. Execute on Starknet with validated state\n * 4. Hub state must be < 60s stale (enforced by QueryVerifier)\n */\n async executeWithQuery(\n _params: {\n userKeyHash: string;\n queryResponse: Uint8Array; // CCQ Guardian response\n actionType: number;\n actionPayload: Uint8Array;\n relayerUrl?: string;\n }\n ): Promise<DispatchResult> {\n throw new Error(\n 'Query-based execution on Starknet requires relayer integration. ' +\n 'Use relayer API to submit query-validated transactions. ' +\n 'Relayer will call veridex_spoke::execute_with_query on Starknet.'\n );\n }\n\n // ========================================================================\n // Internal helpers\n // ========================================================================\n\n private computeKeyHash(publicKeyX: bigint, publicKeyY: bigint): string {\n const xHex = publicKeyX.toString(16).padStart(64, '0');\n const yHex = publicKeyY.toString(16).padStart(64, '0');\n const combined = Buffer.from(xHex + yHex, 'hex');\n const hash = createHash('sha256').update(combined).digest('hex');\n return '0x' + hash;\n }\n\n private buildMessageHash(keyHash: string, targetChain: number, actionPayload: string, nonce: bigint): string {\n const keyHashBuffer = Buffer.from(keyHash.replace(/^0x/, ''), 'hex');\n const targetChainBuffer = Buffer.alloc(2);\n targetChainBuffer.writeUInt16BE(targetChain);\n const payloadBuffer = Buffer.from(actionPayload.replace(/^0x/, ''), 'hex');\n const nonceHex = nonce.toString(16).padStart(64, '0');\n const nonceBuffer = Buffer.from(nonceHex, 'hex');\n\n const combined = Buffer.concat([keyHashBuffer, targetChainBuffer, payloadBuffer, nonceBuffer]);\n const hash = createHash('sha256').update(combined).digest('hex');\n return '0x' + hash;\n }\n\n // ============================================================================\n // Social Recovery Methods (Issue #23)\n // ============================================================================\n // \n // Note: Social recovery is managed on the Hub chain (EVM).\n // Starknet spokes receive and execute recovery VAAs broadcast from the Hub.\n // The relayer service handles submitting recovery transactions to Starknet.\n //\n // SDK users should use EVMClient methods for guardian management and\n // recovery initiation on the Hub chain.\n // ============================================================================\n\n /**\n * Get vault address by owner key hash\n * \n * @param ownerKeyHash - Owner's passkey hash\n * @returns Vault address on Starknet (felt252 as hex string)\n */\n async getVaultAddress(ownerKeyHash: string): Promise<string | null> {\n try {\n const spokeAddress = this.config.contracts.hub;\n if (!spokeAddress) {\n throw new Error('Spoke contract address not configured');\n }\n\n // Starknet spoke expects u256 (low, high) format for keyHash\n const [low, high] = toStarknetU256(ownerKeyHash);\n\n // Call get_vault on spoke contract with u256 split into [low, high]\n const result = await this.provider.callContract({\n contractAddress: spokeAddress,\n entrypoint: 'get_vault',\n calldata: [low, high],\n });\n\n // result[0] is the vault address (0 if not found)\n const vaultAddress = result[0];\n if (vaultAddress === '0x0' || vaultAddress === '0') {\n return null;\n }\n\n return vaultAddress;\n } catch (error) {\n console.error('Error getting vault address:', error);\n return null;\n }\n }\n\n /**\n * Check if vault exists and get basic info\n * \n * @param ownerKeyHash - Owner's passkey hash \n * @returns Vault info or null if not found\n */\n async getVaultInfo(ownerKeyHash: string): Promise<{\n address: string;\n ownerKeyHash: string;\n } | null> {\n const vaultAddress = await this.getVaultAddress(ownerKeyHash);\n if (!vaultAddress) {\n return null;\n }\n\n return {\n address: vaultAddress,\n ownerKeyHash,\n };\n }\n\n /**\n * Check if spoke contract is paused\n * \n * @returns Whether the protocol is paused\n */\n async isProtocolPaused(): Promise<boolean> {\n try {\n const spokeAddress = this.config.contracts.hub;\n if (!spokeAddress) {\n throw new Error('Spoke contract address not configured');\n }\n\n const result = await this.provider.callContract({\n contractAddress: spokeAddress,\n entrypoint: 'is_paused',\n calldata: [],\n });\n\n return result[0] === '0x1' || result[0] === '1';\n } catch (error) {\n console.error('Error checking pause status:', error);\n return false;\n }\n }\n}\n","/**\n * Veridex Protocol SDK - Chain Detector\n *\n * Phase 4: Multi-chain client support helper.\n *\n * Provides:\n * - Chain config lookup (testnet/mainnet)\n * - Auto-configuration for non-EVM ChainClient instances\n */\n\nimport type { ChainClient, ChainConfig, PasskeyCredential, ChainAddress } from './types.js';\nimport { TESTNET_CHAINS, MAINNET_CHAINS } from '../constants.js';\nimport { WalletManager } from './WalletManager.js';\nimport { SolanaClient } from '../chains/solana/SolanaClient.js';\nimport { AptosClient } from '../chains/aptos/AptosClient.js';\nimport { SuiClient } from '../chains/sui/SuiClient.js';\nimport { StarknetClient } from '../chains/starknet/StarknetClient.js';\n\nexport interface ChainDetectorConfig {\n testnet?: boolean;\n rpcUrls?: Record<number, string>;\n}\n\nexport interface NativeBalanceCapable {\n getNativeBalance(address: string): Promise<bigint>;\n}\n\nconst NON_EVM_NATIVE_META: Record<number, { symbol: string; name: string; decimals: number }> = {\n 1: { symbol: 'SOL', name: 'Solana', decimals: 9 },\n 21: { symbol: 'SUI', name: 'Sui', decimals: 9 },\n 22: { symbol: 'APT', name: 'Aptos', decimals: 8 },\n};\n\nexport class ChainDetector {\n private readonly testnet: boolean;\n private readonly rpcUrls: Record<number, string>;\n private readonly walletManager: WalletManager;\n\n constructor(config: ChainDetectorConfig = {}) {\n this.testnet = config.testnet ?? true;\n this.rpcUrls = config.rpcUrls ?? {};\n this.walletManager = new WalletManager({ cacheAddresses: true, persistToStorage: false });\n }\n\n getChainConfig(wormholeChainId: number): ChainConfig | undefined {\n const chains = this.testnet ? TESTNET_CHAINS : MAINNET_CHAINS;\n return Object.values(chains).find(c => c.wormholeChainId === wormholeChainId);\n }\n\n /**\n * Create a chain client for non-EVM chains using repo constants.\n * For EVM, callers should instantiate EVMClient directly (Hub-driven).\n */\n createClient(wormholeChainId: number): ChainClient {\n const chain = this.getChainConfig(wormholeChainId);\n if (!chain) {\n throw new Error(`Unknown chain (wormholeChainId=${wormholeChainId})`);\n }\n\n const rpcUrl = this.rpcUrls[wormholeChainId] ?? chain.rpcUrl;\n\n if (chain.isEvm) {\n throw new Error(\n `EVM chain auto-detection is not supported here (wormholeChainId=${wormholeChainId}). ` +\n 'Instantiate EVMClient with hubContractAddress/vaultFactory/vaultImplementation explicitly.'\n );\n }\n\n switch (wormholeChainId) {\n case 1: {\n const programId = chain.contracts.hub;\n if (!programId || !chain.contracts.tokenBridge) {\n throw new Error('Solana config missing programId/tokenBridge in constants');\n }\n return new SolanaClient({\n wormholeChainId,\n rpcUrl,\n programId,\n wormholeCoreBridge: chain.contracts.wormholeCoreBridge,\n tokenBridge: chain.contracts.tokenBridge,\n network: this.testnet ? 'devnet' : 'mainnet',\n });\n }\n case 22: {\n const moduleAddress = chain.contracts.hub;\n if (!moduleAddress || !chain.contracts.tokenBridge) {\n throw new Error('Aptos config missing moduleAddress/tokenBridge in constants');\n }\n return new AptosClient({\n wormholeChainId,\n rpcUrl,\n moduleAddress,\n wormholeCoreBridge: chain.contracts.wormholeCoreBridge,\n tokenBridge: chain.contracts.tokenBridge,\n network: this.testnet ? 'testnet' : 'mainnet',\n });\n }\n case 21: {\n const packageId = chain.contracts.hub;\n return new SuiClient({\n wormholeChainId,\n rpcUrl,\n packageId: packageId ?? '',\n wormholeCoreBridge: chain.contracts.wormholeCoreBridge,\n tokenBridge: chain.contracts.tokenBridge,\n network: this.testnet ? 'testnet' : 'mainnet',\n });\n }\n case 50001: {\n // Starknet Sepolia with custom bridge\n const spokeAddress = chain.contracts.hub;\n const bridgeAddress = chain.contracts.wormholeCoreBridge;\n if (!spokeAddress || !bridgeAddress) {\n throw new Error('Starknet config missing spoke/bridge addresses in constants');\n }\n return new StarknetClient({\n wormholeChainId,\n rpcUrl,\n spokeContractAddress: spokeAddress,\n bridgeContractAddress: bridgeAddress,\n network: this.testnet ? 'sepolia' : 'mainnet',\n });\n }\n default:\n throw new Error(\n `Unsupported non-EVM chain (wormholeChainId=${wormholeChainId}). ` +\n 'Add configuration in ChainDetector.createClient().'\n );\n }\n }\n\n /**\n * Derive a best-effort vault address for a chain from the passkey credential.\n *\n * - EVM chains: requires vaultFactory/vaultImplementation in constants.\n * - Non-EVM chains: uses WalletManager chain-specific derivation.\n */\n deriveVaultAddress(credential: PasskeyCredential, wormholeChainId: number): ChainAddress | null {\n const chain = this.getChainConfig(wormholeChainId);\n if (!chain) {\n return null;\n }\n\n if (chain.isEvm) {\n const factory = chain.contracts.vaultFactory;\n const implementation = chain.contracts.vaultImplementation;\n if (!factory || !implementation) {\n return null;\n }\n\n const address = this.walletManager.computeVaultAddress(credential.keyHash, factory, implementation);\n return {\n wormholeChainId,\n chainName: chain.name,\n address,\n isEvm: true,\n deployed: false,\n derivationType: 'create2',\n };\n }\n\n // Non-EVM: WalletManager derives using keyHash conventions.\n return {\n wormholeChainId,\n chainName: chain.name,\n address: wormholeChainId === 21 \n ? this.normalizeSuiAddress(credential.keyHash)\n : wormholeChainId === 50001\n ? credential.keyHash // Starknet uses keyHash directly (felt252)\n : credential.keyHash,\n isEvm: false,\n deployed: false,\n derivationType: wormholeChainId === 1 \n ? 'pda' \n : wormholeChainId === 22 \n ? 'resource_account' \n : wormholeChainId === 50001\n ? 'keyHash'\n : 'object',\n };\n }\n\n getNonEvmNativeTokenMeta(wormholeChainId: number): { symbol: string; name: string; decimals: number } | null {\n return NON_EVM_NATIVE_META[wormholeChainId] ?? null;\n }\n\n private normalizeSuiAddress(value: string): string {\n const clean = value.replace(/^0x/, '').padStart(64, '0');\n return '0x' + clean;\n }\n}\n\nexport function createChainDetector(config: ChainDetectorConfig = {}): ChainDetector {\n return new ChainDetector(config);\n}\n","/**\n * Veridex Protocol SDK - Transaction Parser\n * \n * Parses transaction payloads into human-readable summaries (Issue #26)\n * \n * Security-critical: This module MUST accurately represent what users are signing.\n * Any mismatch between displayed information and actual transaction is a security vulnerability.\n */\n\nimport { ethers } from 'ethers';\nimport {\n ACTION_TRANSFER,\n ACTION_EXECUTE,\n ACTION_CONFIG,\n ACTION_BRIDGE,\n} from '../constants.js';\nimport {\n decodeTransferAction,\n decodeBridgeAction,\n} from '../payload.js';\nimport type { PreparedTransfer, PreparedBridge } from './types.js';\nimport type { BridgeParams, TransferParams } from '../types.js';\nimport type {\n TransactionSummary,\n TransactionParserConfig,\n TokenDisplay,\n RecipientDisplay,\n ChainDisplay,\n RiskWarning,\n TransferDetails,\n BridgeDetails,\n ExecuteDetails,\n ConfigDetails,\n TokenInfo,\n} from './TransactionSummary.types.js';\nimport { getChainDisplay, getConfigTypeName } from './TransactionSummary.types.js';\n\n// ============================================================================\n// Default Token Registry\n// ============================================================================\n\nconst DEFAULT_TOKENS: Map<string, TokenInfo> = new Map([\n // Native token placeholder\n ['0x0000000000000000000000000000000000000000', {\n symbol: 'ETH',\n name: 'Ether',\n decimals: 18,\n verified: true,\n }],\n ['native', {\n symbol: 'ETH',\n name: 'Ether',\n decimals: 18,\n verified: true,\n }],\n // Common stablecoins (Base Sepolia)\n ['0x036cbd53842c5426634e7929541ec2318f3dcf7e', {\n symbol: 'USDC',\n name: 'USD Coin',\n decimals: 6,\n verified: true,\n }],\n]);\n\n// ============================================================================\n// Utility Functions\n// ============================================================================\n\n/**\n * Format a bigint amount to human-readable string\n */\nexport function formatAmount(amount: bigint, decimals: number): string {\n if (amount === 0n) return '0';\n \n const divisor = 10n ** BigInt(decimals);\n const whole = amount / divisor;\n const remainder = amount % divisor;\n \n if (remainder === 0n) {\n return whole.toString();\n }\n \n // Format with decimal places\n const remainderStr = remainder.toString().padStart(decimals, '0');\n // Trim trailing zeros\n const trimmed = remainderStr.replace(/0+$/, '');\n \n return `${whole}.${trimmed}`;\n}\n\n/**\n * Truncate an address for display\n */\nexport function truncateAddress(address: string, startChars = 6, endChars = 4): string {\n if (address.length <= startChars + endChars + 3) {\n return address;\n }\n return `${address.slice(0, startChars)}...${address.slice(-endChars)}`;\n}\n\n/**\n * Format time remaining until expiration\n */\nexport function formatTimeRemaining(expiresAt: number): string {\n const now = Date.now();\n const remaining = expiresAt - now;\n \n if (remaining <= 0) return 'Expired';\n \n const seconds = Math.floor(remaining / 1000);\n if (seconds < 60) return `${seconds} seconds`;\n \n const minutes = Math.floor(seconds / 60);\n if (minutes < 60) return `${minutes} minute${minutes === 1 ? '' : 's'}`;\n \n const hours = Math.floor(minutes / 60);\n return `${hours} hour${hours === 1 ? '' : 's'}`;\n}\n\n/**\n * Check if address is the zero address (native token)\n */\nexport function isNativeToken(address: string): boolean {\n return address === '0x0000000000000000000000000000000000000000' ||\n address === 'native' ||\n address === ethers.ZeroAddress;\n}\n\n// ============================================================================\n// Transaction Parser Class\n// ============================================================================\n\n/**\n * Parses prepared transactions into human-readable summaries\n */\nexport class TransactionParser {\n private config: TransactionParserConfig;\n private tokenRegistry: Map<string, TokenInfo>;\n\n constructor(config: TransactionParserConfig = {}) {\n this.config = config;\n this.tokenRegistry = config.knownTokens ?? new Map(DEFAULT_TOKENS);\n }\n\n /**\n * Main entry point: parse a prepared transfer into a human-readable summary\n * \n * This method determines the action type from the payload and delegates\n * to the appropriate specialized parser.\n * \n * @param prepared - PreparedTransfer or PreparedBridge object from SDK\n * @param vaultAddress - Optional vault address (uses default if not provided)\n * @param vaultChainId - Optional vault chain ID (uses config default if not provided)\n */\n async parse(\n prepared: PreparedTransfer | PreparedBridge,\n vaultAddress?: string,\n vaultChainId?: number\n ): Promise<TransactionSummary> {\n const effectiveVaultAddress = vaultAddress ?? '0x0000000000000000000000000000000000000000';\n \n // Determine chain ID based on type - PreparedBridge uses destinationChain, PreparedTransfer uses params.targetChain\n const isBridgePrepared = 'destinationChain' in prepared;\n const defaultChainId = isBridgePrepared \n ? (prepared as PreparedBridge).destinationChain \n : (prepared as PreparedTransfer).params.targetChain;\n const effectiveChainId = vaultChainId ?? this.config.defaultChainId ?? defaultChainId;\n \n // Normalize to PreparedTransfer with defaults for missing fields\n // For PreparedBridge, we construct params from the bridge-specific fields\n const normalizedParams: TransferParams = isBridgePrepared \n ? {\n targetChain: (prepared as PreparedBridge).destinationChain,\n token: (prepared as PreparedBridge).params.token,\n recipient: (prepared as PreparedBridge).params.recipient,\n amount: (prepared as PreparedBridge).params.amount,\n }\n : (prepared as PreparedTransfer).params;\n\n const normalized: PreparedTransfer = {\n params: normalizedParams,\n actionPayload: prepared.actionPayload,\n nonce: prepared.nonce,\n challenge: prepared.challenge,\n estimatedGas: (prepared as PreparedTransfer).estimatedGas ?? 0n,\n gasPrice: (prepared as PreparedTransfer).gasPrice ?? 0n,\n messageFee: (prepared as PreparedTransfer).messageFee ?? (isBridgePrepared ? (prepared as PreparedBridge).fees?.relayerFee ?? 0n : 0n),\n totalCost: (prepared as PreparedTransfer).totalCost ?? 0n,\n formattedCost: (prepared as PreparedTransfer).formattedCost ?? '0',\n preparedAt: prepared.preparedAt ?? Date.now(),\n expiresAt: prepared.expiresAt,\n };\n\n // Determine action type from payload\n const actionType = this.detectActionType(normalized.actionPayload);\n\n switch (actionType) {\n case ACTION_TRANSFER:\n return this.parseTransfer(normalized, effectiveVaultAddress, effectiveChainId);\n case ACTION_BRIDGE:\n return this.parseBridgeFromPrepared(normalized, effectiveVaultAddress, effectiveChainId);\n case ACTION_EXECUTE:\n return this.parseExecuteFromPayload(\n normalized.actionPayload,\n normalized.nonce,\n normalized.challenge,\n effectiveVaultAddress,\n effectiveChainId,\n normalized.expiresAt,\n normalized.formattedCost\n );\n case ACTION_CONFIG:\n return this.parseConfigFromPayload(\n normalized.actionPayload,\n normalized.nonce,\n normalized.challenge,\n effectiveVaultAddress,\n effectiveChainId,\n normalized.expiresAt,\n normalized.formattedCost\n );\n default:\n // Fallback for unknown action types\n return this.createUnknownActionSummary(normalized, effectiveVaultAddress, effectiveChainId);\n }\n }\n\n /**\n * Detect action type from payload\n */\n private detectActionType(payload: string): number {\n if (!payload || payload.length < 4) return 0;\n // Action type is typically first byte after 0x\n const typeHex = payload.slice(2, 4);\n return parseInt(typeHex, 16);\n }\n\n /**\n * Parse bridge action from PreparedTransfer\n */\n private async parseBridgeFromPrepared(\n prepared: PreparedTransfer,\n vaultAddress: string,\n vaultChainId: number\n ): Promise<TransactionSummary> {\n const { params, actionPayload, nonce, challenge, expiresAt, formattedCost } = prepared;\n const decoded = decodeBridgeAction(actionPayload);\n\n const token = await this.resolveToken(decoded.token, decoded.amount);\n const sourceChain = getChainDisplay(vaultChainId);\n const destinationChain = getChainDisplay(params.targetChain);\n const recipient = await this.resolveRecipient(decoded.recipient);\n\n const details: BridgeDetails = {\n token,\n sourceChain,\n destinationChain,\n recipient,\n estimatedTime: this.estimateBridgeTime(sourceChain.id, destinationChain.id),\n };\n\n const warnings = await this.assessBridgeRisks({\n sourceChain: vaultChainId,\n destinationChain: params.targetChain,\n token: decoded.token,\n recipient: decoded.recipient,\n amount: decoded.amount,\n }, token, sourceChain, destinationChain);\n\n return {\n action: 'bridge',\n title: `Bridge ${token.symbol}`,\n description: `Bridge ${token.amount} ${token.symbol} from ${sourceChain.name} to ${destinationChain.name}`,\n details,\n vault: {\n address: vaultAddress,\n truncated: truncateAddress(vaultAddress),\n chain: sourceChain,\n },\n fee: {\n gas: formattedCost,\n paidByRelayer: false,\n total: formattedCost,\n },\n warnings,\n raw: {\n actionType: ACTION_BRIDGE,\n actionPayload,\n nonce,\n challenge: ethers.hexlify(challenge),\n chainId: params.targetChain,\n expiresAt,\n expiresIn: formatTimeRemaining(expiresAt),\n },\n generatedAt: Date.now(),\n };\n }\n\n /**\n * Parse execute action from payload\n */\n private async parseExecuteFromPayload(\n actionPayload: string,\n nonce: bigint,\n challenge: Uint8Array,\n vaultAddress: string,\n chainId: number,\n expiresAt: number,\n formattedCost: string\n ): Promise<TransactionSummary> {\n // Decode execute action - basic structure\n const target = '0x' + actionPayload.slice(4, 44);\n const value = BigInt('0x' + actionPayload.slice(44, 108));\n const calldata = '0x' + actionPayload.slice(108);\n\n const targetDisplay = await this.resolveRecipient(target);\n const chain = getChainDisplay(chainId);\n const functionInfo = this.decodeFunctionCall(calldata);\n\n const details: ExecuteDetails = {\n target: targetDisplay,\n value: await this.resolveToken(ethers.ZeroAddress, value),\n chain,\n functionName: functionInfo?.name,\n decodedArgs: functionInfo?.args,\n calldata,\n };\n\n const warnings = await this.assessExecuteRisks(target, value, calldata, targetDisplay);\n\n return {\n action: 'execute',\n title: 'Contract Call',\n description: `Call ${functionInfo?.name ?? 'function'} on ${targetDisplay.ens ?? targetDisplay.truncated}`,\n details,\n vault: {\n address: vaultAddress,\n truncated: truncateAddress(vaultAddress),\n chain,\n },\n fee: {\n gas: formattedCost,\n paidByRelayer: false,\n total: formattedCost,\n },\n warnings,\n raw: {\n actionType: ACTION_EXECUTE,\n actionPayload,\n nonce,\n challenge: ethers.hexlify(challenge),\n chainId,\n expiresAt,\n expiresIn: formatTimeRemaining(expiresAt),\n },\n generatedAt: Date.now(),\n };\n }\n\n /**\n * Parse config action from payload\n */\n private async parseConfigFromPayload(\n actionPayload: string,\n nonce: bigint,\n challenge: Uint8Array,\n vaultAddress: string,\n chainId: number,\n expiresAt: number,\n formattedCost: string\n ): Promise<TransactionSummary> {\n // Decode config action - basic structure\n const configType = parseInt(actionPayload.slice(2, 4), 16);\n const configData = '0x' + actionPayload.slice(4);\n\n const chain = getChainDisplay(chainId);\n const configTypeName = getConfigTypeName(configType);\n\n const details: ConfigDetails = {\n configType,\n configTypeName,\n description: this.describeConfigChange(configType, configData),\n changes: this.parseConfigChanges(configType, configData),\n };\n\n const warnings: RiskWarning[] = [{\n level: 'high',\n type: 'config_change',\n message: 'This transaction will modify your vault settings',\n details: `Changing: ${configTypeName}`,\n }];\n\n return {\n action: 'config',\n title: 'Configuration Change',\n description: `Update vault configuration: ${configTypeName}`,\n details,\n vault: {\n address: vaultAddress,\n truncated: truncateAddress(vaultAddress),\n chain,\n },\n fee: {\n gas: formattedCost,\n paidByRelayer: false,\n total: formattedCost,\n },\n warnings,\n raw: {\n actionType: ACTION_CONFIG,\n actionPayload,\n nonce,\n challenge: ethers.hexlify(challenge),\n chainId,\n expiresAt,\n expiresIn: formatTimeRemaining(expiresAt),\n },\n generatedAt: Date.now(),\n };\n }\n\n /**\n * Create a fallback summary for unknown action types\n */\n private createUnknownActionSummary(\n prepared: PreparedTransfer,\n vaultAddress: string,\n chainId: number\n ): TransactionSummary {\n const chain = getChainDisplay(chainId);\n\n return {\n action: 'execute',\n title: 'Unknown Action',\n description: 'This transaction contains an unrecognized action type',\n details: null,\n vault: {\n address: vaultAddress,\n truncated: truncateAddress(vaultAddress),\n chain,\n },\n fee: {\n gas: prepared.formattedCost,\n paidByRelayer: false,\n total: prepared.formattedCost,\n },\n warnings: [{\n level: 'critical',\n type: 'unknown_token',\n message: 'Unknown action type - proceed with extreme caution',\n details: `Action type: ${this.detectActionType(prepared.actionPayload)}`,\n }],\n raw: {\n actionType: this.detectActionType(prepared.actionPayload),\n actionPayload: prepared.actionPayload,\n nonce: prepared.nonce,\n challenge: ethers.hexlify(prepared.challenge),\n chainId,\n expiresAt: prepared.expiresAt,\n expiresIn: formatTimeRemaining(prepared.expiresAt),\n },\n generatedAt: Date.now(),\n };\n }\n\n /**\n * Parse a prepared transfer into a human-readable summary\n */\n async parseTransfer(\n prepared: PreparedTransfer,\n vaultAddress: string,\n vaultChainId: number\n ): Promise<TransactionSummary> {\n const { params, actionPayload, nonce, challenge, expiresAt } = prepared;\n const decoded = decodeTransferAction(actionPayload);\n\n const token = await this.resolveToken(decoded.token, decoded.amount);\n const recipient = await this.resolveRecipient(decoded.recipient);\n const chain = getChainDisplay(params.targetChain);\n\n const details: TransferDetails = {\n token,\n recipient,\n chain,\n };\n\n const warnings = await this.assessTransferRisks(params, token, recipient);\n\n return {\n action: 'transfer',\n title: `Send ${token.symbol}`,\n description: `Send ${token.amount} ${token.symbol} to ${recipient.ens ?? recipient.truncated}`,\n details,\n vault: {\n address: vaultAddress,\n truncated: truncateAddress(vaultAddress),\n chain: getChainDisplay(vaultChainId),\n },\n fee: {\n gas: prepared.formattedCost,\n paidByRelayer: false, // Will be updated by caller if gasless\n total: prepared.formattedCost,\n },\n warnings,\n raw: {\n actionType: ACTION_TRANSFER,\n actionPayload,\n nonce,\n challenge: ethers.hexlify(challenge),\n chainId: params.targetChain,\n expiresAt,\n expiresIn: formatTimeRemaining(expiresAt),\n },\n generatedAt: Date.now(),\n };\n }\n\n /**\n * Parse a bridge operation into a human-readable summary\n */\n async parseBridge(\n params: BridgeParams,\n actionPayload: string,\n nonce: bigint,\n challenge: Uint8Array,\n vaultAddress: string,\n vaultChainId: number,\n expiresAt: number,\n formattedCost: string\n ): Promise<TransactionSummary> {\n const decoded = decodeBridgeAction(actionPayload);\n\n const token = await this.resolveToken(decoded.token, decoded.amount);\n const sourceChain = getChainDisplay(params.sourceChain);\n const destinationChain = getChainDisplay(params.destinationChain);\n const recipient = await this.resolveRecipient(decoded.recipient);\n\n const details: BridgeDetails = {\n token,\n sourceChain,\n destinationChain,\n recipient,\n estimatedTime: this.estimateBridgeTime(sourceChain.id, destinationChain.id),\n };\n\n const warnings = await this.assessBridgeRisks(params, token, sourceChain, destinationChain);\n\n return {\n action: 'bridge',\n title: `Bridge ${token.symbol}`,\n description: `Bridge ${token.amount} ${token.symbol} from ${sourceChain.name} to ${destinationChain.name}`,\n details,\n vault: {\n address: vaultAddress,\n truncated: truncateAddress(vaultAddress),\n chain: getChainDisplay(vaultChainId),\n },\n fee: {\n gas: formattedCost,\n paidByRelayer: false,\n total: formattedCost,\n },\n warnings,\n raw: {\n actionType: ACTION_BRIDGE,\n actionPayload,\n nonce,\n challenge: ethers.hexlify(challenge),\n chainId: params.sourceChain,\n expiresAt,\n expiresIn: formatTimeRemaining(expiresAt),\n },\n generatedAt: Date.now(),\n };\n }\n\n /**\n * Parse an execute (contract call) operation into a human-readable summary\n */\n async parseExecute(\n target: string,\n value: bigint,\n calldata: string,\n chainId: number,\n nonce: bigint,\n challenge: Uint8Array,\n vaultAddress: string,\n expiresAt: number,\n formattedCost: string\n ): Promise<TransactionSummary> {\n const targetRecipient = await this.resolveRecipient(target);\n const chain = getChainDisplay(chainId);\n const valueToken = await this.resolveToken(ethers.ZeroAddress, value);\n\n // Try to decode function signature\n const functionInfo = this.decodeFunctionCall(calldata);\n\n const details: ExecuteDetails = {\n target: targetRecipient,\n value: valueToken,\n chain,\n functionName: functionInfo?.name,\n decodedArgs: functionInfo?.args,\n calldata,\n };\n\n const warnings = await this.assessExecuteRisks(target, value, calldata, targetRecipient);\n\n const title = functionInfo?.name\n ? `Call ${functionInfo.name}`\n : 'Contract Interaction';\n\n return {\n action: 'execute',\n title,\n description: `Execute contract call on ${targetRecipient.ens ?? targetRecipient.truncated}`,\n details,\n vault: {\n address: vaultAddress,\n truncated: truncateAddress(vaultAddress),\n chain,\n },\n fee: {\n gas: formattedCost,\n paidByRelayer: false,\n total: formattedCost,\n },\n warnings,\n raw: {\n actionType: ACTION_EXECUTE,\n actionPayload: calldata,\n nonce,\n challenge: ethers.hexlify(challenge),\n chainId,\n expiresAt,\n expiresIn: formatTimeRemaining(expiresAt),\n },\n generatedAt: Date.now(),\n };\n }\n\n /**\n * Parse a config change operation\n */\n async parseConfig(\n configType: number,\n configData: string,\n chainId: number,\n nonce: bigint,\n challenge: Uint8Array,\n vaultAddress: string,\n expiresAt: number,\n formattedCost: string\n ): Promise<TransactionSummary> {\n const chain = getChainDisplay(chainId);\n const configTypeName = getConfigTypeName(configType);\n\n const details: ConfigDetails = {\n configType,\n configTypeName,\n description: this.describeConfigChange(configType, configData),\n changes: this.parseConfigChanges(configType, configData),\n };\n\n const warnings: RiskWarning[] = [{\n level: 'warning',\n type: 'config_change',\n message: 'This transaction will modify your vault settings',\n }];\n\n return {\n action: 'config',\n title: configTypeName,\n description: `Update vault configuration: ${configTypeName}`,\n details,\n vault: {\n address: vaultAddress,\n truncated: truncateAddress(vaultAddress),\n chain,\n },\n fee: {\n gas: formattedCost,\n paidByRelayer: false,\n total: formattedCost,\n },\n warnings,\n raw: {\n actionType: ACTION_CONFIG,\n actionPayload: configData,\n nonce,\n challenge: ethers.hexlify(challenge),\n chainId,\n expiresAt,\n expiresIn: formatTimeRemaining(expiresAt),\n },\n generatedAt: Date.now(),\n };\n }\n\n // ============================================================================\n // Resolution Methods\n // ============================================================================\n\n /**\n * Resolve token address to display info\n */\n private async resolveToken(address: string, amount: bigint): Promise<TokenDisplay> {\n const normalizedAddress = address.toLowerCase();\n const isNative = isNativeToken(address);\n\n // Check registry\n let tokenInfo = this.tokenRegistry.get(normalizedAddress);\n if (!tokenInfo && isNative) {\n tokenInfo = this.tokenRegistry.get('native');\n }\n\n const decimals = tokenInfo?.decimals ?? 18;\n const symbol = tokenInfo?.symbol ?? (isNative ? 'ETH' : 'UNKNOWN');\n const formattedAmount = formatAmount(amount, decimals);\n\n // Try to get USD value\n let usdValue: string | undefined;\n if (this.config.priceOracle) {\n try {\n const price = await this.config.priceOracle(address);\n if (price !== null) {\n const amountNum = parseFloat(formattedAmount);\n usdValue = `$${(amountNum * price).toFixed(2)}`;\n }\n } catch {\n // Price oracle failed, continue without USD value\n }\n }\n\n return {\n symbol,\n amount: formattedAmount,\n rawAmount: amount,\n address: isNative ? ethers.ZeroAddress : address,\n decimals,\n usdValue,\n isNative,\n };\n }\n\n /**\n * Resolve recipient address to display info\n */\n private async resolveRecipient(address: string): Promise<RecipientDisplay> {\n const truncated = truncateAddress(address);\n let ens: string | undefined;\n let isContract: boolean | undefined;\n let isNewRecipient: boolean | undefined;\n let label: string | undefined;\n\n // Check known recipients\n if (this.config.knownRecipients) {\n label = this.config.knownRecipients.get(address.toLowerCase());\n }\n\n // Try ENS resolution\n if (this.config.ensResolver) {\n try {\n const resolved = await this.config.ensResolver(address);\n if (resolved) {\n ens = resolved;\n }\n } catch {\n // ENS resolution failed, continue without\n }\n }\n\n // Check if contract\n if (this.config.contractDetector) {\n try {\n isContract = await this.config.contractDetector(address);\n } catch {\n // Contract detection failed\n }\n }\n\n // Check transaction history\n if (this.config.transactionHistory) {\n isNewRecipient = !this.config.transactionHistory.has(address.toLowerCase());\n }\n\n return {\n address,\n ens,\n truncated,\n isContract,\n isNewRecipient,\n label,\n };\n }\n\n // ============================================================================\n // Risk Assessment Methods\n // ============================================================================\n\n /**\n * Assess risks for a transfer transaction\n */\n private async assessTransferRisks(\n _params: TransferParams,\n token: TokenDisplay,\n recipient: RecipientDisplay\n ): Promise<RiskWarning[]> {\n const warnings: RiskWarning[] = [];\n\n // New recipient warning\n if (recipient.isNewRecipient) {\n warnings.push({\n level: 'warning',\n type: 'new_recipient',\n message: \"You've never sent to this address before\",\n details: 'Double-check the recipient address is correct',\n });\n }\n\n // Large transaction warning\n if (this.config.averageTransactionValue) {\n const threshold = this.config.averageTransactionValue * 10n; // 10x average\n if (token.rawAmount > threshold) {\n warnings.push({\n level: 'warning',\n type: 'large_transaction',\n message: 'This transaction is larger than your usual activity',\n details: `Amount: ${token.amount} ${token.symbol}`,\n });\n }\n }\n\n // Contract interaction warning\n if (recipient.isContract) {\n warnings.push({\n level: 'info',\n type: 'contract_interaction',\n message: 'Recipient is a smart contract',\n });\n }\n\n // Unknown token warning\n const tokenInfo = this.tokenRegistry.get(token.address.toLowerCase());\n if (!tokenInfo?.verified) {\n warnings.push({\n level: 'warning',\n type: 'unknown_token',\n message: 'This token is not in our verified list',\n details: 'Verify the token address is correct',\n });\n }\n\n return warnings;\n }\n\n /**\n * Assess risks for a bridge transaction\n */\n private async assessBridgeRisks(\n _params: BridgeParams,\n token: TokenDisplay,\n sourceChain: ChainDisplay,\n destinationChain: ChainDisplay\n ): Promise<RiskWarning[]> {\n const warnings: RiskWarning[] = [];\n\n // Cross-chain operation info\n warnings.push({\n level: 'info',\n type: 'cross_chain',\n message: `This is a cross-chain transfer from ${sourceChain.name} to ${destinationChain.name}`,\n details: 'Funds will be locked on the source chain and released on the destination',\n });\n\n // Large transaction warning\n if (this.config.averageTransactionValue) {\n const threshold = this.config.averageTransactionValue * 10n;\n if (token.rawAmount > threshold) {\n warnings.push({\n level: 'warning',\n type: 'large_transaction',\n message: 'This transaction is larger than your usual activity',\n });\n }\n }\n\n return warnings;\n }\n\n /**\n * Assess risks for an execute transaction\n */\n private async assessExecuteRisks(\n _target: string,\n value: bigint,\n _calldata: string,\n recipient: RecipientDisplay\n ): Promise<RiskWarning[]> {\n const warnings: RiskWarning[] = [];\n\n // Contract interaction is inherently risky\n warnings.push({\n level: 'warning',\n type: 'contract_interaction',\n message: 'This transaction calls an external contract',\n details: 'Review the contract and function being called',\n });\n\n // New recipient warning\n if (recipient.isNewRecipient) {\n warnings.push({\n level: 'warning',\n type: 'new_recipient',\n message: \"You've never interacted with this contract before\",\n });\n }\n\n // Value transfer with contract call\n if (value > 0n) {\n warnings.push({\n level: 'info',\n type: 'large_transaction',\n message: `This transaction sends ${formatAmount(value, 18)} ETH along with the contract call`,\n });\n }\n\n return warnings;\n }\n\n // ============================================================================\n // Helper Methods\n // ============================================================================\n\n /**\n * Estimate bridge completion time\n */\n private estimateBridgeTime(_sourceChain: number, _destChain: number): string {\n // Wormhole typically takes 2-15 minutes depending on chains\n // Query-based is faster (~5-7 seconds), VAA-based is slower (~2+ minutes)\n return '~2-5 minutes';\n }\n\n /**\n * Try to decode a function call from calldata\n */\n private decodeFunctionCall(calldata: string): { name: string; args: Record<string, unknown> } | null {\n if (calldata.length < 10) return null;\n\n // Common function selectors\n const KNOWN_SELECTORS: Record<string, string> = {\n '0xa9059cbb': 'transfer',\n '0x23b872dd': 'transferFrom',\n '0x095ea7b3': 'approve',\n '0x70a08231': 'balanceOf',\n '0x18160ddd': 'totalSupply',\n '0x313ce567': 'decimals',\n '0x06fdde03': 'name',\n '0x95d89b41': 'symbol',\n };\n\n const selector = calldata.slice(0, 10).toLowerCase();\n const name = KNOWN_SELECTORS[selector];\n\n if (name) {\n return { name, args: {} }; // Would need ABI to decode args\n }\n\n return null;\n }\n\n /**\n * Describe a config change in human-readable terms\n */\n private describeConfigChange(configType: number, _configData: string): string {\n const name = getConfigTypeName(configType);\n return `This will update your vault's ${name.toLowerCase()}`;\n }\n\n /**\n * Parse config changes into structured format\n */\n private parseConfigChanges(configType: number, configData: string): Array<{ field: string; newValue: string }> {\n // Basic parsing - would need more context for full implementation\n return [{\n field: getConfigTypeName(configType),\n newValue: configData.length > 66 ? `${configData.slice(0, 66)}...` : configData,\n }];\n }\n\n /**\n * Update parser configuration\n */\n updateConfig(config: Partial<TransactionParserConfig>): void {\n this.config = { ...this.config, ...config };\n if (config.knownTokens) {\n this.tokenRegistry = config.knownTokens;\n }\n }\n\n /**\n * Add a known token to the registry\n */\n addKnownToken(address: string, info: TokenInfo): void {\n this.tokenRegistry.set(address.toLowerCase(), info);\n }\n\n /**\n * Add a known recipient label\n */\n addKnownRecipient(address: string, label: string): void {\n if (!this.config.knownRecipients) {\n this.config.knownRecipients = new Map();\n }\n this.config.knownRecipients.set(address.toLowerCase(), label);\n }\n}\n\n// ============================================================================\n// Audit Logging Types and Functions\n// ============================================================================\n\n/**\n * Audit log entry for transaction summaries\n * Used for security audits and debugging\n */\nexport interface TransactionAuditEntry {\n /** Unique identifier matching the TransactionSummary.id */\n summaryId: string;\n /** ISO timestamp when summary was generated */\n timestamp: string;\n /** Action type that was parsed */\n actionType: string;\n /** Human-readable title shown to user */\n titleDisplayed: string;\n /** Human-readable description shown to user */\n descriptionDisplayed: string;\n /** Number of risk warnings shown */\n riskWarningCount: number;\n /** Highest risk level in warnings */\n highestRiskLevel: string | null;\n /** Whether technical details were available */\n hasTechnicalDetails: boolean;\n /** Hash of the raw payload for verification */\n payloadHash: string;\n /** Expiration time shown */\n expiresAt: number;\n /** Chain ID of the transaction */\n targetChain: number;\n /** Gas cost formatted as shown to user */\n gasCostDisplayed: string;\n}\n\n/**\n * Create an audit log entry from a transaction summary\n * \n * @param summary - The transaction summary that was displayed\n * @returns Audit entry for logging\n */\nexport function createAuditEntry(summary: TransactionSummary): TransactionAuditEntry {\n const highestRisk = summary.warnings.reduce<string | null>((acc, r) => {\n const order: Record<string, number> = { critical: 0, high: 1, warning: 2, info: 3 };\n if (acc === null) return r.level;\n if (order[r.level] < order[acc]) {\n return r.level;\n }\n return acc;\n }, null);\n\n return {\n summaryId: `${summary.generatedAt}-${summary.action}`,\n timestamp: new Date().toISOString(),\n actionType: summary.action,\n titleDisplayed: summary.title,\n descriptionDisplayed: summary.description,\n riskWarningCount: summary.warnings.length,\n highestRiskLevel: highestRisk,\n hasTechnicalDetails: !!summary.raw,\n payloadHash: summary.raw?.actionPayload ? ethers.keccak256(summary.raw.actionPayload) : '',\n expiresAt: summary.raw?.expiresAt ?? 0,\n targetChain: summary.raw?.chainId ?? 0,\n gasCostDisplayed: summary.fee.total,\n };\n}\n\n/**\n * Log a transaction summary for audit purposes\n * \n * @param summary - The transaction summary to log\n * @param logger - Optional custom logger (defaults to console.info)\n */\nexport function logTransactionSummary(\n summary: TransactionSummary,\n logger: (entry: TransactionAuditEntry) => void = (entry) => {\n // Default: structured console logging\n console.info('[VERIDEX_TX_AUDIT]', JSON.stringify(entry));\n }\n): TransactionAuditEntry {\n const entry = createAuditEntry(summary);\n logger(entry);\n return entry;\n}\n\n// ============================================================================\n// Factory Function\n// ============================================================================\n\n/**\n * Create a transaction parser with optional configuration\n */\nexport function createTransactionParser(config?: TransactionParserConfig): TransactionParser {\n return new TransactionParser(config);\n}\n","/**\n * Veridex Protocol SDK - Transaction Summary Types\n * \n * Human-readable transaction summary types for security and UX (Issue #26)\n * \n * These types enable users to understand what they're signing before\n * providing biometric authentication, preventing phishing and social engineering.\n */\n\n// ============================================================================\n// Action Display Types\n// ============================================================================\n\n/**\n * Human-readable action type\n */\nexport type ActionDisplayType = 'transfer' | 'bridge' | 'config' | 'execute' | 'unknown';\n\n/**\n * Token display information\n */\nexport interface TokenDisplay {\n /** Token symbol (e.g., \"ETH\", \"USDC\") */\n symbol: string;\n /** Human-readable amount (e.g., \"1.5\") */\n amount: string;\n /** Raw amount in smallest unit */\n rawAmount: bigint;\n /** Token contract address */\n address: string;\n /** Number of decimals */\n decimals: number;\n /** Estimated USD value (if available) */\n usdValue?: string;\n /** Whether this is the native token */\n isNative: boolean;\n}\n\n/**\n * Recipient display information\n */\nexport interface RecipientDisplay {\n /** Raw address (hex) */\n address: string;\n /** ENS name (if resolved) */\n ens?: string;\n /** Truncated address for display (e.g., \"0x1234...5678\") */\n truncated: string;\n /** Whether this is a contract address */\n isContract?: boolean;\n /** Whether this is a new recipient (never sent to before) */\n isNewRecipient?: boolean;\n /** Label if known (e.g., \"My Wallet\", \"Exchange\") */\n label?: string;\n}\n\n/**\n * Chain display information\n */\nexport interface ChainDisplay {\n /** Wormhole chain ID */\n id: number;\n /** Human-readable chain name */\n name: string;\n /** Chain icon URL (optional) */\n iconUrl?: string;\n /** Whether this is a testnet */\n isTestnet: boolean;\n}\n\n// ============================================================================\n// Risk Warning Types\n// ============================================================================\n\n/**\n * Risk level for warnings\n */\nexport type RiskLevel = 'info' | 'warning' | 'high' | 'critical';\n\n/**\n * Risk warning with message and metadata\n */\nexport interface RiskWarning {\n /** Severity level */\n level: RiskLevel;\n /** Human-readable warning message */\n message: string;\n /** Warning type for programmatic handling */\n type: RiskWarningType;\n /** Additional context/details */\n details?: string;\n}\n\n/**\n * Types of risk warnings\n */\nexport type RiskWarningType =\n | 'large_transaction' // Amount exceeds usual activity\n | 'new_recipient' // First time sending to this address\n | 'contract_interaction' // Calling an external contract\n | 'full_balance' // Transferring all assets\n | 'high_gas' // Gas cost is unusually high\n | 'unknown_token' // Token not in verified list\n | 'cross_chain' // Cross-chain operation\n | 'config_change' // Vault configuration change\n | 'all_tokens' // Affects all tokens in vault\n | 'irreversible'; // Action cannot be undone\n\n// ============================================================================\n// Transaction Summary Types\n// ============================================================================\n\n/**\n * Transfer-specific details\n */\nexport interface TransferDetails {\n token: TokenDisplay;\n recipient: RecipientDisplay;\n chain: ChainDisplay;\n}\n\n/**\n * Bridge-specific details\n */\nexport interface BridgeDetails {\n token: TokenDisplay;\n sourceChain: ChainDisplay;\n destinationChain: ChainDisplay;\n recipient: RecipientDisplay;\n /** Estimated bridge fee */\n bridgeFee?: string;\n /** Estimated arrival time */\n estimatedTime?: string;\n}\n\n/**\n * Execute (contract call) details\n */\nexport interface ExecuteDetails {\n target: RecipientDisplay;\n value: TokenDisplay;\n chain: ChainDisplay;\n /** Function signature if decodable */\n functionName?: string;\n /** Decoded function arguments if available */\n decodedArgs?: Record<string, unknown>;\n /** Raw calldata (hex) */\n calldata: string;\n}\n\n/**\n * Config change details\n */\nexport interface ConfigDetails {\n configType: number;\n configTypeName: string;\n description: string;\n changes: Array<{\n field: string;\n oldValue?: string;\n newValue: string;\n }>;\n}\n\n/**\n * Union type for all action-specific details\n */\nexport type ActionDetails = TransferDetails | BridgeDetails | ExecuteDetails | ConfigDetails;\n\n/**\n * Complete transaction summary for display\n */\nexport interface TransactionSummary {\n /** Action type for display */\n action: ActionDisplayType;\n \n /** Human-readable title (e.g., \"Send ETH\", \"Bridge USDC\") */\n title: string;\n \n /** Human-readable description */\n description: string;\n\n /** Action-specific details */\n details: TransferDetails | BridgeDetails | ExecuteDetails | ConfigDetails | null;\n \n /** Source vault information */\n vault: {\n address: string;\n truncated: string;\n chain: ChainDisplay;\n };\n\n /** Fee information */\n fee: {\n /** Estimated gas fee */\n gas: string;\n /** Gas in USD (if available) */\n gasUsd?: string;\n /** Whether fee is paid by relayer */\n paidByRelayer: boolean;\n /** Relayer fee (if applicable) */\n relayerFee?: string;\n /** Total fee */\n total: string;\n };\n\n /** Risk warnings */\n warnings: RiskWarning[];\n \n /** Raw technical details for advanced users */\n raw: {\n actionType: number;\n actionPayload: string;\n nonce: bigint;\n challenge: string;\n chainId: number;\n /** Expiration timestamp */\n expiresAt: number;\n /** Time until expiration in human readable form */\n expiresIn: string;\n };\n\n /** Timestamp when summary was generated */\n generatedAt: number;\n}\n\n// ============================================================================\n// Parser Configuration\n// ============================================================================\n\n/**\n * Configuration for the transaction parser\n */\nexport interface TransactionParserConfig {\n /** Default chain ID for vault operations */\n defaultChainId?: number;\n /** Known token registry (address -> info) */\n knownTokens?: Map<string, TokenInfo>;\n /** Known recipient labels (address -> label) */\n knownRecipients?: Map<string, string>;\n /** ENS resolver function */\n ensResolver?: (address: string) => Promise<string | null>;\n /** Contract detector function */\n contractDetector?: (address: string) => Promise<boolean>;\n /** Price oracle for USD values */\n priceOracle?: (tokenAddress: string) => Promise<number | null>;\n /** User's transaction history for new recipient detection */\n transactionHistory?: Set<string>;\n /** User's average transaction value for large tx detection */\n averageTransactionValue?: bigint;\n}\n\n/**\n * Token info for registry\n */\nexport interface TokenInfo {\n symbol: string;\n name: string;\n decimals: number;\n logoUrl?: string;\n verified: boolean;\n}\n\n// ============================================================================\n// Chain Name Mapping\n// ============================================================================\n\n/**\n * Get chain display info from Wormhole chain ID\n */\nexport const CHAIN_DISPLAY_INFO: Record<number, Omit<ChainDisplay, 'id'>> = {\n // Mainnets\n 1: { name: 'Solana', isTestnet: false },\n 2: { name: 'Ethereum', isTestnet: false },\n 4: { name: 'BSC', isTestnet: false },\n 5: { name: 'Polygon', isTestnet: false },\n 6: { name: 'Avalanche', isTestnet: false },\n 21: { name: 'Sui', isTestnet: false },\n 22: { name: 'Aptos', isTestnet: false },\n 23: { name: 'Arbitrum', isTestnet: false },\n 24: { name: 'Optimism', isTestnet: false },\n 30: { name: 'Base', isTestnet: false },\n\n // Testnets\n 10002: { name: 'Sepolia', isTestnet: true },\n 10003: { name: 'Arbitrum Sepolia', isTestnet: true },\n 10004: { name: 'Base Sepolia', isTestnet: true },\n 10005: { name: 'Optimism Sepolia', isTestnet: true },\n 50001: { name: 'Starknet Sepolia', isTestnet: true },\n};\n\n/**\n * Get chain display info with fallback\n */\nexport function getChainDisplay(chainId: number): ChainDisplay {\n const info = CHAIN_DISPLAY_INFO[chainId];\n if (info) {\n return { id: chainId, ...info };\n }\n return {\n id: chainId,\n name: `Chain ${chainId}`,\n isTestnet: chainId >= 10000,\n };\n}\n\n// ============================================================================\n// Config Type Names\n// ============================================================================\n\nexport const CONFIG_TYPE_NAMES: Record<number, string> = {\n 1: 'Update Spending Limits',\n 2: 'Add Guardian',\n 3: 'Remove Guardian',\n 4: 'Update Recovery Threshold',\n 5: 'Add Session Key',\n 6: 'Revoke Session Key',\n 7: 'Update Emergency Contact',\n};\n\n/**\n * Get config type name with fallback\n */\nexport function getConfigTypeName(configType: number): string {\n return CONFIG_TYPE_NAMES[configType] ?? `Config Update (Type ${configType})`;\n}\n","/**\n * Veridex Protocol SDK - Spending Limits Manager (Issue #27)\n * \n * Manages vault spending limits including:\n * - Reading current limits and usage from on-chain state\n * - Preparing limit update transactions (requires passkey signature)\n * - Checking transactions against limits before signing\n * - Formatting limits for UI display\n * \n * Security Considerations:\n * - All limit changes require Hub authentication (passkey signature)\n * - Changes are propagated via VAA to spoke chains\n * - Local checks are advisory; on-chain enforcement is authoritative\n */\n\nimport { ethers } from 'ethers';\nimport {\n type SpendingLimits,\n type FormattedSpendingLimits,\n type LimitCheckResult,\n type LimitViolationSuggestion,\n type SpendingTransaction,\n type DailySpendingSummary,\n type DurationDisplay,\n type SpendingLimitConfig,\n type SpendingLimitChangedEvent,\n type SpendingLimitEventCallback,\n CONFIG_TYPE,\n formatDuration,\n calculatePercentage,\n formatLargeAmount,\n} from './SpendingLimits.types.js';\nimport { encodeConfigAction } from '../payload.js';\n\n// ============================================================================\n// Vault ABI Fragment (spending limit related functions)\n// ============================================================================\n\nconst VAULT_ABI = [\n 'function dailyLimit() view returns (uint256)',\n 'function dailyWithdrawn() view returns (uint256)',\n 'function dayStart() view returns (uint256)',\n 'function paused() view returns (bool)',\n 'function getRemainingDailyLimit() view returns (uint256)',\n 'event Paused(bool paused)',\n 'event DailyLimitUpdated(uint256 newLimit)',\n];\n\n// ============================================================================\n// Constants\n// ============================================================================\n\n/** One day in seconds */\nconst DAY_SECONDS = 86400;\n\n/** One day in milliseconds */\nconst DAY_MS = DAY_SECONDS * 1000;\n\n// ============================================================================\n// Configuration\n// ============================================================================\n\nexport interface SpendingLimitsManagerConfig {\n /** Default token decimals for formatting */\n defaultDecimals?: number;\n \n /** Default token symbol for formatting */\n defaultSymbol?: string;\n \n /** Custom RPC URLs by chain ID */\n rpcUrls?: Record<number, string>;\n \n /** Cache TTL in milliseconds */\n cacheTtl?: number;\n \n /** Event callback for limit changes */\n onLimitChange?: SpendingLimitEventCallback;\n}\n\n// ============================================================================\n// Main Class\n// ============================================================================\n\nexport class SpendingLimitsManager {\n private config: Required<SpendingLimitsManagerConfig>;\n private cache: Map<string, { data: SpendingLimits; expiry: number }> = new Map();\n private eventListeners: SpendingLimitEventCallback[] = [];\n \n constructor(config: SpendingLimitsManagerConfig = {}) {\n this.config = {\n defaultDecimals: config.defaultDecimals ?? 18,\n defaultSymbol: config.defaultSymbol ?? 'ETH',\n rpcUrls: config.rpcUrls ?? {},\n cacheTtl: config.cacheTtl ?? 10000, // 10 seconds\n onLimitChange: config.onLimitChange ?? (() => {}),\n };\n \n if (config.onLimitChange) {\n this.eventListeners.push(config.onLimitChange);\n }\n }\n \n // ============================================================================\n // Read Spending Limits\n // ============================================================================\n \n /**\n * Get current spending limits for a vault\n * @param vaultAddress - Vault contract address\n * @param chainId - Chain ID where the vault is deployed\n * @param rpcUrl - Optional RPC URL override\n */\n async getSpendingLimits(\n vaultAddress: string,\n chainId: number,\n rpcUrl?: string\n ): Promise<SpendingLimits> {\n // Check cache first\n const cacheKey = `${chainId}:${vaultAddress.toLowerCase()}`;\n const cached = this.cache.get(cacheKey);\n if (cached && Date.now() < cached.expiry) {\n return cached.data;\n }\n \n const provider = this.getProvider(chainId, rpcUrl);\n const vault = new ethers.Contract(vaultAddress, VAULT_ABI, provider);\n \n // Fetch all values in parallel\n const [dailyLimit, dailyWithdrawn, dayStart, paused] = await Promise.all([\n vault.dailyLimit() as Promise<bigint>,\n vault.dailyWithdrawn() as Promise<bigint>,\n vault.dayStart() as Promise<bigint>,\n vault.paused() as Promise<boolean>,\n ]);\n \n const now = Date.now();\n const dayStartMs = Number(dayStart) * 1000;\n const dayEndMs = dayStartMs + DAY_MS;\n \n // Calculate effective values (handle day rollover)\n let effectiveSpent = dailyWithdrawn;\n let effectiveResetTime = new Date(dayEndMs);\n let timeUntilReset = dayEndMs - now;\n \n if (now >= dayEndMs) {\n // New day has started, spent resets to 0\n effectiveSpent = 0n;\n // Calculate next reset time\n const daysSinceStart = Math.floor((now - dayStartMs) / DAY_MS);\n const nextDayStart = dayStartMs + (daysSinceStart + 1) * DAY_MS;\n effectiveResetTime = new Date(nextDayStart);\n timeUntilReset = nextDayStart - now;\n }\n \n const dailyRemaining = dailyLimit === 0n \n ? BigInt('0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff') // max uint256\n : dailyLimit > effectiveSpent \n ? dailyLimit - effectiveSpent \n : 0n;\n \n const limits: SpendingLimits = {\n dailyLimit,\n dailySpent: effectiveSpent,\n dailyRemaining,\n dayResetTime: effectiveResetTime,\n timeUntilReset: Math.max(0, timeUntilReset),\n transactionLimit: 0n, // Per-tx limits are in SpendingLimitModule, not base vault\n isPaused: paused,\n lastUpdated: new Date(),\n chainId,\n };\n \n // Cache the result\n this.cache.set(cacheKey, {\n data: limits,\n expiry: now + this.config.cacheTtl,\n });\n \n return limits;\n }\n \n /**\n * Get spending limits formatted for UI display\n */\n async getFormattedSpendingLimits(\n vaultAddress: string,\n chainId: number,\n options?: {\n rpcUrl?: string;\n decimals?: number;\n symbol?: string;\n }\n ): Promise<FormattedSpendingLimits> {\n const limits = await this.getSpendingLimits(vaultAddress, chainId, options?.rpcUrl);\n const decimals = options?.decimals ?? this.config.defaultDecimals;\n const symbol = options?.symbol ?? this.config.defaultSymbol;\n \n return this.formatLimits(limits, decimals, symbol);\n }\n \n /**\n * Format raw limits for display\n */\n formatLimits(\n limits: SpendingLimits,\n decimals: number = 18,\n symbol: string = 'ETH'\n ): FormattedSpendingLimits {\n const hasDailyLimit = limits.dailyLimit > 0n;\n \n // Convert to number for display (safe for typical amounts)\n const toNumber = (val: bigint): number => {\n const divisor = 10n ** BigInt(decimals);\n return Number(val * 10000n / divisor) / 10000;\n };\n \n return {\n dailyLimit: hasDailyLimit \n ? formatLargeAmount(limits.dailyLimit, decimals, symbol)\n : 'Unlimited',\n dailyLimitValue: toNumber(limits.dailyLimit),\n dailySpent: formatLargeAmount(limits.dailySpent, decimals, symbol),\n dailySpentValue: toNumber(limits.dailySpent),\n dailyRemaining: hasDailyLimit \n ? formatLargeAmount(limits.dailyRemaining, decimals, symbol)\n : 'Unlimited',\n dailyRemainingValue: toNumber(limits.dailyRemaining),\n dailyUsedPercentage: hasDailyLimit \n ? calculatePercentage(limits.dailySpent, limits.dailyLimit)\n : 0,\n timeUntilReset: formatDuration(limits.timeUntilReset).formatted,\n transactionLimit: limits.transactionLimit > 0n\n ? formatLargeAmount(limits.transactionLimit, decimals, symbol)\n : 'Unlimited',\n transactionLimitValue: toNumber(limits.transactionLimit),\n isPaused: limits.isPaused,\n hasDailyLimit,\n hasTransactionLimit: limits.transactionLimit > 0n,\n };\n }\n \n // ============================================================================\n // Limit Checks\n // ============================================================================\n \n /**\n * Check if a transaction amount is within limits\n * @param vaultAddress - Vault to check\n * @param chainId - Chain ID\n * @param amount - Amount to transfer (in base units)\n * @returns Result indicating if transfer is allowed\n */\n async checkTransactionLimit(\n vaultAddress: string,\n chainId: number,\n amount: bigint,\n options?: { rpcUrl?: string }\n ): Promise<LimitCheckResult> {\n const limits = await this.getSpendingLimits(vaultAddress, chainId, options?.rpcUrl);\n \n // Check if paused first\n if (limits.isPaused) {\n return {\n allowed: false,\n reason: 'vault_paused',\n message: 'Vault is paused. Unpause to continue.',\n suggestions: [\n {\n action: 'unpause_vault',\n label: 'Unpause Vault',\n },\n ],\n };\n }\n \n // Check per-transaction limit\n if (limits.transactionLimit > 0n && amount > limits.transactionLimit) {\n return {\n allowed: false,\n reason: 'transaction_limit_exceeded',\n message: `Transaction exceeds per-transaction limit of ${formatLargeAmount(limits.transactionLimit, this.config.defaultDecimals, this.config.defaultSymbol)}`,\n allowedAmount: limits.transactionLimit,\n excessAmount: amount - limits.transactionLimit,\n suggestions: [\n {\n action: 'send_partial',\n label: `Send ${formatLargeAmount(limits.transactionLimit, this.config.defaultDecimals, this.config.defaultSymbol)} (within limit)`,\n data: { amount: limits.transactionLimit },\n },\n {\n action: 'increase_limit',\n label: 'Increase Transaction Limit',\n },\n ],\n };\n }\n \n // Check daily limit\n if (limits.dailyLimit > 0n) {\n const wouldSpend = limits.dailySpent + amount;\n \n if (wouldSpend > limits.dailyLimit) {\n const excessAmount = wouldSpend - limits.dailyLimit;\n const suggestions: LimitViolationSuggestion[] = [];\n \n // Suggest partial transfer if some amount is available\n if (limits.dailyRemaining > 0n) {\n suggestions.push({\n action: 'send_partial',\n label: `Send ${formatLargeAmount(limits.dailyRemaining, this.config.defaultDecimals, this.config.defaultSymbol)} (within limit)`,\n data: { amount: limits.dailyRemaining },\n });\n }\n \n suggestions.push({\n action: 'increase_limit',\n label: 'Increase Daily Limit',\n data: { newLimit: wouldSpend },\n });\n \n suggestions.push({\n action: 'wait_for_reset',\n label: `Wait ${formatDuration(limits.timeUntilReset).formatted} for limit reset`,\n data: { waitTimeMs: limits.timeUntilReset },\n });\n \n return {\n allowed: false,\n reason: 'daily_limit_exceeded',\n message: `Transaction would exceed daily limit. Already spent ${formatLargeAmount(limits.dailySpent, this.config.defaultDecimals, this.config.defaultSymbol)} of ${formatLargeAmount(limits.dailyLimit, this.config.defaultDecimals, this.config.defaultSymbol)} today.`,\n allowedAmount: limits.dailyRemaining,\n excessAmount,\n waitTime: limits.timeUntilReset,\n suggestions,\n };\n }\n }\n \n return {\n allowed: true,\n message: 'Transaction is within limits',\n };\n }\n \n // ============================================================================\n // Limit Configuration (Prepare for Signing)\n // ============================================================================\n \n /**\n * Prepare a transaction to update the daily spending limit\n * Returns the config action payload that needs to be signed via passkey\n * \n * @param newLimit - New daily limit in base units (0 = unlimited)\n * @returns Config action payload for signing\n */\n prepareDailyLimitUpdate(newLimit: bigint): string {\n // Config type 1 = daily limit update\n // Config data format: [limit(32)]\n const limitBytes = ethers.zeroPadValue(ethers.toBeHex(newLimit), 32);\n return encodeConfigAction(CONFIG_TYPE.DAILY_LIMIT, limitBytes);\n }\n \n /**\n * Prepare a transaction to pause the vault\n * @returns Config action payload for signing\n */\n preparePauseVault(): string {\n // Config type 2 = pause, config data: [paused(1)] where 1 = paused\n const pausedByte = ethers.toBeHex(1, 1);\n return encodeConfigAction(CONFIG_TYPE.PAUSE, pausedByte);\n }\n \n /**\n * Prepare a transaction to unpause the vault\n * @returns Config action payload for signing\n */\n prepareUnpauseVault(): string {\n // Config type 2 = pause, config data: [paused(1)] where 0 = unpaused\n const unpausedByte = ethers.toBeHex(0, 1);\n return encodeConfigAction(CONFIG_TYPE.PAUSE, unpausedByte);\n }\n \n /**\n * Get the full spending limit configuration encoded as config payload\n * Used during vault creation to set initial limits\n */\n encodeInitialLimits(config: SpendingLimitConfig): string {\n if (!config.dailyLimit || config.dailyLimit === 0n) {\n // No limit configuration needed\n return '';\n }\n return this.prepareDailyLimitUpdate(config.dailyLimit);\n }\n \n // ============================================================================\n // Transaction History\n // ============================================================================\n \n /**\n * Get recent spending transactions for a vault\n * Note: This requires indexer integration for full history\n * @param vaultAddress - Vault to query\n * @param chainId - Chain ID\n * @param limit - Maximum number of transactions to return\n */\n async getRecentTransactions(\n vaultAddress: string,\n chainId: number,\n limit: number = 10\n ): Promise<SpendingTransaction[]> {\n // Note: Full implementation requires indexer/subgraph integration\n // For now, return empty array - UI should handle gracefully\n // In production, this would query a subgraph or indexer API\n console.log(`[SpendingLimitsManager] getRecentTransactions not fully implemented. Vault: ${vaultAddress}, Chain: ${chainId}, Limit: ${limit}`);\n return [];\n }\n \n /**\n * Get daily spending summary\n */\n async getDailySpendingSummary(\n vaultAddress: string,\n chainId: number,\n date?: Date\n ): Promise<DailySpendingSummary> {\n const targetDate = date ?? new Date();\n const transactions = await this.getRecentTransactions(vaultAddress, chainId, 100);\n \n // Filter transactions from the target date\n const startOfDay = new Date(targetDate);\n startOfDay.setHours(0, 0, 0, 0);\n const endOfDay = new Date(startOfDay);\n endOfDay.setDate(endOfDay.getDate() + 1);\n \n const dayTransactions = transactions.filter(\n tx => tx.timestamp >= startOfDay && tx.timestamp < endOfDay\n );\n \n const totalSpent = dayTransactions.reduce(\n (sum, tx) => sum + tx.amount,\n 0n\n );\n \n return {\n date: targetDate,\n totalSpent,\n formattedTotal: formatLargeAmount(totalSpent, this.config.defaultDecimals, this.config.defaultSymbol),\n transactionCount: dayTransactions.length,\n transactions: dayTransactions,\n };\n }\n \n // ============================================================================\n // Event Subscription\n // ============================================================================\n \n /**\n * Subscribe to spending limit change events\n */\n onLimitChange(callback: SpendingLimitEventCallback): () => void {\n this.eventListeners.push(callback);\n return () => {\n const index = this.eventListeners.indexOf(callback);\n if (index >= 0) {\n this.eventListeners.splice(index, 1);\n }\n };\n }\n \n /**\n * Notify listeners of a limit change event\n * Call this after a successful limit update transaction\n */\n notifyLimitChange(event: SpendingLimitChangedEvent): void {\n for (const listener of this.eventListeners) {\n try {\n listener(event);\n } catch (error) {\n console.error('[SpendingLimitsManager] Event listener error:', error);\n }\n }\n }\n \n // ============================================================================\n // Countdown Timer\n // ============================================================================\n \n /**\n * Get a live countdown to daily limit reset\n * Returns an object with current time remaining that updates\n */\n async getResetCountdown(\n vaultAddress: string,\n chainId: number,\n options?: { rpcUrl?: string }\n ): Promise<{\n getCurrentTimeRemaining: () => DurationDisplay;\n timeUntilResetMs: number;\n resetTime: Date;\n }> {\n const limits = await this.getSpendingLimits(vaultAddress, chainId, options?.rpcUrl);\n const fetchTime = Date.now();\n \n return {\n getCurrentTimeRemaining: () => {\n const elapsed = Date.now() - fetchTime;\n const remaining = Math.max(0, limits.timeUntilReset - elapsed);\n return formatDuration(remaining);\n },\n timeUntilResetMs: limits.timeUntilReset,\n resetTime: limits.dayResetTime,\n };\n }\n \n // ============================================================================\n // Cache Management\n // ============================================================================\n \n /**\n * Clear the cache for a specific vault or all vaults\n */\n clearCache(vaultAddress?: string, chainId?: number): void {\n if (vaultAddress && chainId) {\n this.cache.delete(`${chainId}:${vaultAddress.toLowerCase()}`);\n } else {\n this.cache.clear();\n }\n }\n \n /**\n * Invalidate cache after a limit change\n */\n invalidateCacheAfterChange(vaultAddress: string, chainId: number): void {\n this.clearCache(vaultAddress, chainId);\n }\n \n // ============================================================================\n // Helpers\n // ============================================================================\n \n /**\n * Get a provider for the specified chain\n */\n private getProvider(chainId: number, rpcUrl?: string): ethers.Provider {\n const url = rpcUrl ?? this.config.rpcUrls[chainId];\n if (!url) {\n throw new Error(`No RPC URL configured for chain ${chainId}`);\n }\n return new ethers.JsonRpcProvider(url);\n }\n}\n\n// ============================================================================\n// Factory Function\n// ============================================================================\n\n/**\n * Create a SpendingLimitsManager instance\n */\nexport function createSpendingLimitsManager(\n config?: SpendingLimitsManagerConfig\n): SpendingLimitsManager {\n return new SpendingLimitsManager(config);\n}\n","/**\n * Veridex Protocol SDK - Spending Limits Type Definitions (Issue #27)\n * \n * Types for configuring, viewing, and enforcing spending limits on vaults.\n * Spending limits provide an additional security layer against:\n * - Compromised passkeys draining entire vault\n * - Accidental large transactions\n * - Malicious session key abuse\n * \n * Security Model:\n * - Limits are enforced on-chain by the vault contract\n * - Limit changes require passkey signature (Hub authentication)\n * - Circuit breaker auto-pauses vault on limit violation\n * - Daily limits reset 24 hours from first spend\n */\n\n// ============================================================================\n// Core Types\n// ============================================================================\n\n/**\n * Current spending limits and usage for a vault\n */\nexport interface SpendingLimits {\n /** Daily spending limit (0 = unlimited) */\n dailyLimit: bigint;\n \n /** Amount spent in current 24-hour period */\n dailySpent: bigint;\n \n /** Remaining daily allowance */\n dailyRemaining: bigint;\n \n /** When the daily counter resets (UTC timestamp) */\n dayResetTime: Date;\n \n /** Time remaining until daily reset (milliseconds) */\n timeUntilReset: number;\n \n /** Per-transaction limit (0 = unlimited) */\n transactionLimit: bigint;\n \n /** Whether the vault is currently paused */\n isPaused: boolean;\n \n /** Last updated timestamp */\n lastUpdated: Date;\n \n /** Chain where these limits are enforced */\n chainId: number;\n}\n\n/**\n * Formatted spending limits for UI display\n */\nexport interface FormattedSpendingLimits {\n /** Daily limit as human-readable string (e.g., \"1,000 USDC\") */\n dailyLimit: string;\n \n /** Daily limit as raw number for calculations */\n dailyLimitValue: number;\n \n /** Amount spent today as human-readable string */\n dailySpent: string;\n \n /** Amount spent as raw number */\n dailySpentValue: number;\n \n /** Remaining daily allowance as human-readable string */\n dailyRemaining: string;\n \n /** Remaining as raw number */\n dailyRemainingValue: number;\n \n /** Percentage of daily limit used (0-100) */\n dailyUsedPercentage: number;\n \n /** Time until reset as human-readable string (e.g., \"6h 23m\") */\n timeUntilReset: string;\n \n /** Transaction limit as human-readable string */\n transactionLimit: string;\n \n /** Transaction limit as raw number */\n transactionLimitValue: number;\n \n /** Whether the vault is paused */\n isPaused: boolean;\n \n /** Whether daily limit is set (false = unlimited) */\n hasDailyLimit: boolean;\n \n /** Whether transaction limit is set (false = unlimited) */\n hasTransactionLimit: boolean;\n}\n\n/**\n * Spending limit configuration during vault creation\n */\nexport interface SpendingLimitConfig {\n /** Daily spending limit (optional, 0 = unlimited) */\n dailyLimit?: bigint;\n \n /** Per-transaction limit (optional, 0 = unlimited) */\n transactionLimit?: bigint;\n \n /** Whether to require 2FA for transactions above threshold */\n requireMultiSigAbove?: bigint;\n \n /** Whitelisted recipients (unlimited transfers allowed) */\n whitelistedRecipients?: string[];\n}\n\n/**\n * Parameters for setting daily limit\n */\nexport interface SetDailyLimitParams {\n /** New daily limit in wei/lamports/base units */\n limit: bigint;\n \n /** Optional chain to configure (defaults to current chain) */\n chainId?: number;\n}\n\n/**\n * Parameters for setting transaction limit\n */\nexport interface SetTransactionLimitParams {\n /** New transaction limit in wei/lamports/base units */\n limit: bigint;\n \n /** Optional chain to configure (defaults to current chain) */\n chainId?: number;\n}\n\n// ============================================================================\n// Limit Enforcement Types\n// ============================================================================\n\n/**\n * Result of checking if a transaction is within limits\n */\nexport interface LimitCheckResult {\n /** Whether the transaction is allowed */\n allowed: boolean;\n \n /** Reason code if not allowed */\n reason?: LimitViolationType;\n \n /** Human-readable message */\n message: string;\n \n /** Amount that would be allowed (if partially allowed) */\n allowedAmount?: bigint;\n \n /** Amount that exceeds limit */\n excessAmount?: bigint;\n \n /** Time to wait if daily limit reached */\n waitTime?: number;\n \n /** Suggested actions for the user */\n suggestions?: LimitViolationSuggestion[];\n}\n\n/**\n * Types of limit violations\n */\nexport type LimitViolationType =\n | 'daily_limit_exceeded'\n | 'transaction_limit_exceeded'\n | 'vault_paused'\n | 'insufficient_balance'\n | 'daily_limit_would_exceed';\n\n/**\n * Suggestion for resolving a limit violation\n */\nexport interface LimitViolationSuggestion {\n /** Action type */\n action: 'send_partial' | 'increase_limit' | 'wait_for_reset' | 'unpause_vault';\n \n /** Human-readable label */\n label: string;\n \n /** Additional data for the action */\n data?: {\n amount?: bigint;\n waitTimeMs?: number;\n newLimit?: bigint;\n };\n}\n\n// ============================================================================\n// Transaction History Types\n// ============================================================================\n\n/**\n * A spending transaction in the history\n */\nexport interface SpendingTransaction {\n /** Transaction hash */\n hash: string;\n \n /** Amount spent (in wei/lamports) */\n amount: bigint;\n \n /** Human-readable amount */\n formattedAmount: string;\n \n /** Token symbol */\n tokenSymbol: string;\n \n /** Recipient address */\n recipient: string;\n \n /** Recipient display name (ENS, label, or truncated) */\n recipientDisplay: string;\n \n /** When the transaction occurred */\n timestamp: Date;\n \n /** Relative time (e.g., \"2h ago\") */\n relativeTime: string;\n \n /** Transaction type */\n type: 'transfer' | 'bridge' | 'execute';\n \n /** Whether this counted against daily limit */\n countedAgainstLimit: boolean;\n}\n\n/**\n * Daily spending summary\n */\nexport interface DailySpendingSummary {\n /** Date for this summary */\n date: Date;\n \n /** Total amount spent */\n totalSpent: bigint;\n \n /** Formatted total */\n formattedTotal: string;\n \n /** Number of transactions */\n transactionCount: number;\n \n /** Individual transactions */\n transactions: SpendingTransaction[];\n}\n\n// ============================================================================\n// Config Action Encoding\n// ============================================================================\n\n/**\n * Config types matching VeridexVault.sol\n */\nexport const CONFIG_TYPE = {\n /** Update daily limit */\n DAILY_LIMIT: 1,\n /** Pause/unpause vault */\n PAUSE: 2,\n /** Update guardians */\n GUARDIANS: 3,\n /** Register sender */\n REGISTER_SENDER: 4,\n /** Allow source chain */\n ALLOW_CHAIN: 5,\n /** Set query verifier */\n QUERY_VERIFIER: 6,\n} as const;\n\nexport type ConfigType = (typeof CONFIG_TYPE)[keyof typeof CONFIG_TYPE];\n\n// ============================================================================\n// Event Types\n// ============================================================================\n\n/**\n * Event emitted when spending limits change\n */\nexport interface SpendingLimitChangedEvent {\n /** Event type */\n type: 'daily_limit_changed' | 'transaction_limit_changed' | 'vault_paused' | 'vault_unpaused';\n \n /** Previous value */\n previousValue: bigint | boolean;\n \n /** New value */\n newValue: bigint | boolean;\n \n /** Transaction hash */\n txHash: string;\n \n /** Block timestamp */\n timestamp: Date;\n}\n\n/**\n * Callback for spending limit events\n */\nexport type SpendingLimitEventCallback = (event: SpendingLimitChangedEvent) => void;\n\n// ============================================================================\n// Preset Configurations\n// ============================================================================\n\n/**\n * Predefined spending limit configurations\n */\nexport interface LimitPreset {\n /** Preset identifier */\n id: string;\n \n /** Display name */\n name: string;\n \n /** Description */\n description: string;\n \n /** Daily limit suggestion (in USD equivalent) */\n dailyLimitUsd: number;\n \n /** Transaction limit suggestion (in USD equivalent) */\n transactionLimitUsd: number;\n \n /** Icon for UI */\n icon: string;\n \n /** Recommended for user type */\n recommendedFor: string;\n}\n\n/**\n * Standard limit presets\n */\nexport const LIMIT_PRESETS: LimitPreset[] = [\n {\n id: 'conservative',\n name: 'Conservative',\n description: 'Low limits for maximum security',\n dailyLimitUsd: 500,\n transactionLimitUsd: 100,\n icon: '🔒',\n recommendedFor: 'New users or high-value vaults',\n },\n {\n id: 'balanced',\n name: 'Balanced',\n description: 'Moderate limits for everyday use',\n dailyLimitUsd: 2500,\n transactionLimitUsd: 500,\n icon: '⚖️',\n recommendedFor: 'Regular users',\n },\n {\n id: 'generous',\n name: 'Generous',\n description: 'Higher limits for active traders',\n dailyLimitUsd: 10000,\n transactionLimitUsd: 2500,\n icon: '🚀',\n recommendedFor: 'Active traders and power users',\n },\n {\n id: 'unlimited',\n name: 'No Limits',\n description: 'No spending restrictions (not recommended)',\n dailyLimitUsd: 0, // 0 = unlimited\n transactionLimitUsd: 0,\n icon: '⚠️',\n recommendedFor: 'Advanced users who accept full risk',\n },\n];\n\n// ============================================================================\n// Utility Types\n// ============================================================================\n\n/**\n * Duration display for reset countdown\n */\nexport interface DurationDisplay {\n hours: number;\n minutes: number;\n seconds: number;\n formatted: string; // e.g., \"6h 23m\"\n}\n\n/**\n * Calculate duration display from milliseconds\n */\nexport function formatDuration(ms: number): DurationDisplay {\n const totalSeconds = Math.max(0, Math.floor(ms / 1000));\n const hours = Math.floor(totalSeconds / 3600);\n const minutes = Math.floor((totalSeconds % 3600) / 60);\n const seconds = totalSeconds % 60;\n \n let formatted: string;\n if (hours > 0) {\n formatted = `${hours}h ${minutes}m`;\n } else if (minutes > 0) {\n formatted = `${minutes}m ${seconds}s`;\n } else {\n formatted = `${seconds}s`;\n }\n \n return { hours, minutes, seconds, formatted };\n}\n\n/**\n * Calculate percentage safely (handles zero division)\n */\nexport function calculatePercentage(spent: bigint, limit: bigint): number {\n if (limit === 0n) return 0;\n // Use fixed-point math to avoid precision loss\n const percentage = Number((spent * 10000n) / limit) / 100;\n return Math.min(100, Math.max(0, percentage));\n}\n\n/**\n * Format large numbers with appropriate units\n */\nexport function formatLargeAmount(\n amount: bigint,\n decimals: number = 18,\n symbol: string = 'ETH'\n): string {\n const divisor = 10n ** BigInt(decimals);\n const whole = amount / divisor;\n const fraction = amount % divisor;\n \n // Format with up to 4 decimal places\n const fractionStr = fraction.toString().padStart(decimals, '0').slice(0, 4);\n const trimmedFraction = fractionStr.replace(/0+$/, '');\n \n const numStr = trimmedFraction \n ? `${whole.toLocaleString()}.${trimmedFraction}`\n : whole.toLocaleString();\n \n return `${numStr} ${symbol}`;\n}\n","/**\n * Veridex Protocol SDK - Main SDK Class\n */\n\nimport { PasskeyManager } from './PasskeyManager.js';\nimport { WalletManager } from './WalletManager.js';\nimport { BalanceManager, type TokenBalance, type PortfolioBalance } from './BalanceManager.js';\nimport { TransactionTracker, type TransactionState, type TransactionCallback } from './TransactionTracker.js';\nimport { \n CrossChainManager, \n type CrossChainResult,\n type CrossChainFees,\n type CrossChainProgressCallback,\n} from './CrossChainManager.js';\nimport { RelayerClient, type SubmitSignedActionRequest } from './RelayerClient.js';\nimport { ChainDetector } from './ChainDetector.js';\nimport { TransactionParser } from './TransactionParser.js';\nimport type { TransactionSummary } from './TransactionSummary.types.js';\nimport { SpendingLimitsManager } from './SpendingLimitsManager.js';\nimport type { SpendingLimits, FormattedSpendingLimits, LimitCheckResult } from './SpendingLimits.types.js';\nimport { ethers } from 'ethers';\nimport { authenticateAndPrepare } from '../auth/prepareAuth.js';\nimport { queryPortfolio } from '../queries/portfolio.js';\nimport { \n GasSponsor, \n type SponsoredVaultResult, \n type MultiChainVaultResult,\n type ChainDeploymentConfig,\n} from './GasSponsor.js';\nimport { buildChallenge, buildGaslessChallenge } from '../payload.js';\nimport { normalizeEmitterAddress } from '../wormhole.js';\nimport { \n getAllTokens, \n getTokenBySymbol, \n isNativeToken,\n type TokenInfo \n} from '../constants/tokens.js';\nimport type {\n VeridexConfig,\n ChainClient,\n PasskeyCredential,\n TransferParams,\n ExecuteParams,\n BridgeParams,\n DispatchResult,\n VaultInfo,\n UnifiedIdentity,\n ChainAddress,\n VaultCreationResult,\n PreparedTransfer,\n TransferResult,\n ReceiveAddress,\n BridgeResult,\n PreparedBridge,\n IdentityState,\n AddBackupKeyResult,\n RemoveKeyResult,\n AuthorizedKey,\n} from './types.js';\n\n/** Expiration time for prepared transfers (5 minutes) */\nconst PREPARED_TRANSFER_TTL = 5 * 60 * 1000;\n\nexport class VeridexSDK {\n public readonly passkey: PasskeyManager;\n public readonly wallet: WalletManager;\n public readonly balance: BalanceManager;\n public readonly transactions: TransactionTracker;\n public readonly crossChain: CrossChainManager;\n public readonly sponsor: GasSponsor;\n public readonly transactionParser: TransactionParser;\n public readonly spendingLimits: SpendingLimitsManager;\n private readonly chain: ChainClient;\n private readonly relayer?: RelayerClient;\n // TODO: Use relayerApiKey when relayer integration is complete (Issue #8)\n // private readonly relayerApiKey?: string;\n private readonly queryApiKey?: string;\n private readonly testnet: boolean;\n private readonly sponsorPrivateKey?: string;\n private readonly chainRpcUrls?: Record<number, string>;\n private readonly chainDetector: ChainDetector;\n private unifiedIdentity: UnifiedIdentity | null = null;\n\n constructor(config: VeridexConfig) {\n this.chain = config.chain;\n this.testnet = config.testnet ?? true;\n this.sponsorPrivateKey = config.sponsorPrivateKey;\n this.chainRpcUrls = config.chainRpcUrls;\n // TODO: Uncomment when relayerApiKey is used (Issue #8)\n // this.relayerApiKey = config.relayerApiKey;\n this.queryApiKey = config.queryApiKey ?? config.relayerApiKey;\n this.passkey = new PasskeyManager({\n relayerUrl: config.relayerUrl,\n });\n this.wallet = new WalletManager({\n cacheAddresses: true,\n persistToStorage: config.persistWallet ?? true,\n });\n this.balance = new BalanceManager({\n cacheBalances: true,\n cacheTtl: 30_000, // 30 seconds\n customRpcUrls: config.chainRpcUrls ?? {},\n });\n this.transactions = new TransactionTracker({\n pollingInterval: 2000,\n requiredConfirmations: 1,\n });\n\n this.chainDetector = new ChainDetector({\n testnet: this.testnet,\n rpcUrls: config.chainRpcUrls ?? {},\n });\n this.crossChain = new CrossChainManager({\n testnet: this.testnet,\n relayerUrl: config.relayerUrl,\n autoRelay: !!config.relayerUrl,\n });\n this.sponsor = new GasSponsor({\n // Veridex fallback sponsorship\n sponsorPrivateKey: config.sponsorPrivateKey,\n // Integrator-provided sponsorship (takes priority over Veridex)\n integratorSponsorKey: config.integratorSponsorKey,\n // Relayer for remote sponsorship (future primary method)\n relayerUrl: config.relayerUrl,\n relayerApiKey: config.relayerApiKey,\n // Chain configuration\n testnet: this.testnet,\n customRpcUrls: config.chainRpcUrls,\n });\n\n // Initialize relayer client if URL provided\n if (config.relayerUrl) {\n this.relayer = new RelayerClient({\n baseUrl: config.relayerUrl,\n apiKey: config.relayerApiKey,\n });\n }\n\n // Initialize transaction parser for human-readable summaries (Issue #26)\n this.transactionParser = new TransactionParser({\n defaultChainId: this.chain.getConfig().wormholeChainId,\n // TODO: Integrate ENS resolution via relayer when available\n // resolveEnsName: async (address) => { ... }\n // TODO: Integrate price oracle when available\n // getTokenPrice: async (token, chainId) => { ... }\n });\n\n // Initialize spending limits manager (Issue #27)\n this.spendingLimits = new SpendingLimitsManager({\n defaultDecimals: 18,\n defaultSymbol: this.chain.getConfig().name.includes('Solana') ? 'SOL' : 'ETH',\n rpcUrls: config.chainRpcUrls ?? {},\n cacheTtl: 10000, // 10 seconds\n });\n }\n\n getChainConfig() {\n return this.chain.getConfig();\n }\n\n getChainClient(): ChainClient {\n return this.chain;\n }\n\n async getNonce(): Promise<bigint> {\n const credential = this.passkey.getCredential();\n if (!credential) {\n throw new Error('No credential set. Call passkey.register() or passkey.setCredential() first.');\n }\n return await this.chain.getNonce(credential.keyHash);\n }\n\n async getMessageFee(): Promise<bigint> {\n return await this.chain.getMessageFee();\n }\n\n async buildTransferPayload(params: TransferParams): Promise<string> {\n return await this.chain.buildTransferPayload(params);\n }\n\n async buildExecutePayload(params: ExecuteParams): Promise<string> {\n return await this.chain.buildExecutePayload(params);\n }\n\n async buildBridgePayload(params: BridgeParams): Promise<string> {\n return await this.chain.buildBridgePayload(params);\n }\n\n async transfer(params: TransferParams, signer: any): Promise<DispatchResult> {\n const credential = this.passkey.getCredential();\n if (!credential) {\n throw new Error('No credential set. Call passkey.register() or passkey.setCredential() first.');\n }\n\n const actionPayload = await this.buildTransferPayload(params);\n const nonce = await this.getNonce();\n const challenge = buildChallenge(\n credential.keyHash,\n params.targetChain,\n nonce,\n actionPayload\n );\n\n const signature = await this.passkey.sign(challenge);\n\n return await this.chain.dispatch(\n signature,\n credential.publicKeyX,\n credential.publicKeyY,\n params.targetChain,\n actionPayload,\n nonce,\n signer\n );\n }\n\n async execute(params: ExecuteParams, signer: any): Promise<DispatchResult> {\n const credential = this.passkey.getCredential();\n if (!credential) {\n throw new Error('No credential set');\n }\n\n const actionPayload = await this.buildExecutePayload(params);\n const nonce = await this.getNonce();\n const challenge = buildChallenge(\n credential.keyHash,\n params.targetChain,\n nonce,\n actionPayload\n );\n\n const signature = await this.passkey.sign(challenge);\n\n return await this.chain.dispatch(\n signature,\n credential.publicKeyX,\n credential.publicKeyY,\n params.targetChain,\n actionPayload,\n nonce,\n signer\n );\n }\n\n async bridge(params: BridgeParams, signer: any): Promise<DispatchResult> {\n const credential = this.passkey.getCredential();\n if (!credential) {\n throw new Error('No credential set');\n }\n\n const actionPayload = await this.buildBridgePayload(params);\n const nonce = await this.getNonce();\n\n const challenge = buildChallenge(\n credential.keyHash,\n params.sourceChain,\n nonce,\n actionPayload\n );\n\n const signature = await this.passkey.sign(challenge);\n\n return await this.chain.dispatch(\n signature,\n credential.publicKeyX,\n credential.publicKeyY,\n params.sourceChain,\n actionPayload,\n nonce,\n signer\n );\n }\n\n // ========================================================================\n // Phase 3: Cross-Chain Transfers\n // ========================================================================\n\n /**\n * Prepare a bridge/cross-chain transfer with fee estimation\n * \n * @param params - Bridge parameters\n * @returns PreparedBridge with fee estimates\n */\n async prepareBridge(params: BridgeParams): Promise<PreparedBridge> {\n const credential = this.passkey.getCredential();\n if (!credential) {\n throw new Error('No credential set. Call passkey.register() or passkey.setCredential() first.');\n }\n\n // Build payload and get nonce\n const actionPayload = await this.buildBridgePayload(params);\n const nonce = await this.getNonce();\n \n // Build challenge\n const challenge = buildChallenge(\n credential.keyHash,\n params.sourceChain,\n nonce,\n actionPayload\n );\n\n // Get chain config\n const chainConfig = this.chain.getConfig();\n\n // Estimate fees using CrossChainManager\n const evmClient = this.chain as any;\n const provider = evmClient.provider ?? evmClient.getProvider?.();\n \n let fees: CrossChainFees = {\n sourceGas: 300_000n * 1_000_000_000n, // Default estimate\n messageFee: 0n,\n relayerFee: 0n,\n totalCost: 300_000n * 1_000_000_000n,\n formattedTotal: '0.0003 ETH',\n currency: 'ETH',\n };\n\n if (provider) {\n try {\n fees = await this.crossChain.estimateFees(params, chainConfig, provider);\n } catch (e) {\n console.warn('Fee estimation failed, using defaults:', e);\n }\n }\n\n return {\n params,\n actionPayload,\n nonce,\n challenge,\n fees,\n sourceChain: params.sourceChain,\n destinationChain: params.destinationChain,\n preparedAt: Date.now(),\n expiresAt: Date.now() + PREPARED_TRANSFER_TTL,\n };\n }\n\n /**\n * Execute a prepared bridge with full cross-chain tracking\n * \n * @param prepared - PreparedBridge from prepareBridge()\n * @param signer - Signer to pay for gas\n * @param onProgress - Optional callback for progress updates\n * @returns BridgeResult with cross-chain tracking info\n */\n async executeBridge(\n prepared: PreparedBridge,\n signer: any,\n onProgress?: CrossChainProgressCallback\n ): Promise<BridgeResult> {\n const credential = this.passkey.getCredential();\n if (!credential) {\n throw new Error('No credential set');\n }\n\n // Check expiration\n if (Date.now() > prepared.expiresAt) {\n throw new Error('Prepared bridge has expired. Please call prepareBridge() again.');\n }\n\n const startTime = Date.now();\n const chainConfig = this.chain.getConfig();\n const hubEmitter = normalizeEmitterAddress(chainConfig.contracts.hub ?? '');\n\n // Step 1: Sign with passkey\n onProgress?.({\n status: 'signing',\n step: 1,\n totalSteps: 6,\n message: 'Sign with your passkey...',\n });\n\n const signature = await this.passkey.sign(prepared.challenge);\n\n // Step 2: Dispatch transaction\n onProgress?.({\n status: 'dispatching',\n step: 2,\n totalSteps: 6,\n message: 'Submitting transaction to blockchain...',\n });\n\n const dispatchResult = await this.chain.dispatch(\n signature,\n credential.publicKeyX,\n credential.publicKeyY,\n prepared.params.sourceChain,\n prepared.actionPayload,\n prepared.nonce,\n signer\n );\n\n // Step 3: Wait for confirmations\n onProgress?.({\n status: 'waiting_confirmations',\n step: 3,\n totalSteps: 6,\n message: 'Waiting for block confirmations...',\n details: { txHash: dispatchResult.transactionHash },\n });\n\n // Track the cross-chain transfer\n this.crossChain.trackTransfer(\n dispatchResult.transactionHash,\n prepared.sourceChain,\n prepared.destinationChain,\n dispatchResult.sequence,\n hubEmitter\n );\n\n // Track in transaction tracker too\n this.transactions.track(\n dispatchResult.transactionHash,\n chainConfig.wormholeChainId,\n undefined,\n dispatchResult.sequence\n );\n\n // Step 4-5: Fetch VAA (CrossChainManager handles this)\n let vaa: string | undefined;\n try {\n vaa = await this.crossChain.fetchVAAByTxHash(\n dispatchResult.transactionHash,\n onProgress\n );\n \n this.crossChain.completeTransfer(\n dispatchResult.transactionHash,\n vaa\n );\n } catch (error) {\n // VAA fetch failed, but transaction was successful\n // User can retry VAA fetch later\n console.warn('VAA fetch failed:', error);\n }\n\n // Step 6: Submit to relayer (if configured)\n // The relayer auto-relays by observing hub Dispatch events; there is\n // currently no relay-job API to poll for destination tx hashes.\n let destinationTxHash: string | undefined;\n if (vaa && this.relayer) {\n onProgress?.({\n status: 'relaying',\n step: 6,\n totalSteps: 6,\n message: 'Relayer will submit to destination chain automatically...',\n });\n }\n\n onProgress?.({\n status: 'completed',\n step: 6,\n totalSteps: 6,\n message: 'Cross-chain transfer complete!',\n details: {\n txHash: dispatchResult.transactionHash,\n sequence: dispatchResult.sequence,\n vaaReady: !!vaa,\n destinationTxHash,\n },\n });\n\n // Invalidate balance cache\n const vaultAddress = this.getVaultAddress();\n this.balance.invalidateCache(chainConfig.wormholeChainId, vaultAddress);\n\n return {\n ...dispatchResult,\n params: prepared.params,\n sourceChain: prepared.sourceChain,\n destinationChain: prepared.destinationChain,\n vaa,\n destinationTxHash,\n duration: Date.now() - startTime,\n timestamp: Date.now(),\n };\n }\n\n /**\n * Execute a gasless bridge using the relayer\n *\n * The relayer pays for the Hub transaction (and Wormhole fee), then observes\n * the resulting Dispatch event and relays the VAA to the destination spoke.\n */\n async bridgeViaRelayer(\n params: BridgeParams,\n onProgress?: CrossChainProgressCallback\n ): Promise<BridgeResult> {\n const credential = this.passkey.getCredential();\n if (!credential) {\n throw new Error('No credential set. Call passkey.register() or passkey.setCredential() first.');\n }\n\n if (!this.relayer) {\n throw new Error('Relayer not configured. Please provide relayerUrl in SDK config.');\n }\n\n const startTime = Date.now();\n\n onProgress?.({\n status: 'preparing',\n step: 0,\n totalSteps: 6,\n message: 'Preparing gasless bridge...',\n });\n\n // Bridge actions target the *sourceChain* (where the vault holds funds)\n const actionPayload = await this.buildBridgePayload(params);\n const nonce = await this.getNonce();\n const chainConfig = this.chain.getConfig();\n const hubChainId = chainConfig.hubChainId ?? chainConfig.wormholeChainId;\n\n onProgress?.({\n status: 'signing',\n step: 1,\n totalSteps: 6,\n message: 'Sign with your passkey...',\n });\n\n const challenge = buildGaslessChallenge(\n params.sourceChain,\n actionPayload,\n nonce,\n hubChainId\n );\n const signature = await this.passkey.sign(challenge);\n\n onProgress?.({\n status: 'dispatching',\n step: 2,\n totalSteps: 6,\n message: 'Submitting gasless bridge to relayer...',\n });\n\n // Use full WebAuthn data for authenticateAndDispatch\n const submitRequest: SubmitSignedActionRequest = {\n authenticatorData: signature.authenticatorData,\n clientDataJSON: signature.clientDataJSON,\n challengeIndex: signature.challengeIndex,\n typeIndex: signature.typeIndex,\n r: '0x' + signature.r.toString(16).padStart(64, '0'),\n s: '0x' + signature.s.toString(16).padStart(64, '0'),\n publicKeyX: '0x' + credential.publicKeyX.toString(16).padStart(64, '0'),\n publicKeyY: '0x' + credential.publicKeyY.toString(16).padStart(64, '0'),\n targetChain: params.sourceChain,\n actionPayload,\n nonce: Number(nonce),\n };\n\n const relayerResult = await this.relayer.submitSignedAction(submitRequest);\n if (!relayerResult.success) {\n throw new Error(`Relayer submission failed: ${relayerResult.error}`);\n }\n\n const txHash = relayerResult.txHash ?? '';\n const sequence = relayerResult.sequence ? BigInt(relayerResult.sequence) : 0n;\n\n if (txHash) {\n this.transactions.track(txHash, hubChainId, undefined, sequence || undefined);\n }\n\n // Try to fetch VAA for UI feedback (relayer will still execute even if this fails)\n let vaa: string | undefined;\n try {\n vaa = await this.crossChain.fetchVAAByTxHash(txHash, onProgress);\n } catch {\n // ignore: user can retry fetch later\n }\n\n onProgress?.({\n status: 'completed',\n step: 6,\n totalSteps: 6,\n message: 'Gasless bridge submitted. Relayer will complete execution.',\n details: {\n txHash,\n sequence,\n vaaReady: !!vaa,\n },\n });\n\n return {\n transactionHash: txHash,\n sequence,\n userKeyHash: credential.keyHash,\n targetChain: params.sourceChain,\n blockNumber: 0,\n params,\n sourceChain: params.sourceChain,\n destinationChain: params.destinationChain,\n vaa,\n destinationTxHash: undefined,\n duration: Date.now() - startTime,\n timestamp: Date.now(),\n };\n }\n\n /**\n * Execute a full bridge with automatic preparation\n * \n * @param params - Bridge parameters\n * @param signer - Signer to pay for gas\n * @param onProgress - Optional callback for progress updates\n * @returns BridgeResult with cross-chain tracking info\n */\n async bridgeWithTracking(\n params: BridgeParams,\n signer: any,\n onProgress?: CrossChainProgressCallback\n ): Promise<BridgeResult> {\n onProgress?.({\n status: 'preparing',\n step: 0,\n totalSteps: 6,\n message: 'Preparing cross-chain transfer...',\n });\n\n const prepared = await this.prepareBridge(params);\n return await this.executeBridge(prepared, signer, onProgress);\n }\n\n /**\n * Fetch VAA for a completed transaction\n * Use this if VAA fetch failed during bridge execution\n * \n * @param txHash - Source chain transaction hash\n * @returns VAA base64 string\n */\n async fetchVAAForTransaction(txHash: string): Promise<string> {\n return await this.crossChain.fetchVAAByTxHash(txHash);\n }\n\n /**\n * Get cross-chain transfer fees\n * \n * @param params - Bridge parameters\n * @returns CrossChainFees with breakdown\n */\n async getBridgeFees(params: BridgeParams): Promise<CrossChainFees> {\n const chainConfig = this.chain.getConfig();\n const evmClient = this.chain as any;\n const provider = evmClient.provider ?? evmClient.getProvider?.();\n\n if (!provider) {\n throw new Error('Provider not available');\n }\n\n return await this.crossChain.estimateFees(params, chainConfig, provider);\n }\n\n /**\n * Get all pending cross-chain transfers\n */\n getPendingBridges(): CrossChainResult[] {\n return this.crossChain.getAllPendingTransfers();\n }\n\n /**\n * Get Wormholescan explorer URL for a cross-chain transfer\n */\n getWormholeExplorerUrl(sequence: bigint): string {\n const chainConfig = this.chain.getConfig();\n const hubEmitter = chainConfig.contracts.hub ?? '';\n return this.crossChain.getWormholeExplorerUrl(\n chainConfig.wormholeChainId,\n hubEmitter,\n sequence\n );\n }\n\n // ========================================================================\n // Phase 2: Send & Receive Funds\n // ========================================================================\n\n /**\n * Prepare a transfer with gas estimation\n * Call this before transfer() to show user the cost\n * \n * @param params - Transfer parameters\n * @returns PreparedTransfer with gas estimates and challenge\n */\n async prepareTransfer(params: TransferParams): Promise<PreparedTransfer> {\n const credential = this.passkey.getCredential();\n if (!credential) {\n throw new Error('No credential set. Call passkey.register() or passkey.setCredential() first.');\n }\n\n // Build payload and get nonce\n const actionPayload = await this.buildTransferPayload(params);\n const nonce = await this.getNonce();\n \n // Build challenge\n const challenge = buildChallenge(\n credential.keyHash,\n params.targetChain,\n nonce,\n actionPayload\n );\n\n // Get gas estimates - need to type cast for EVM-specific methods\n const evmClient = this.chain as any;\n let estimatedGas = 500000n; // Default\n let gasPrice = 0n;\n \n if (typeof evmClient.getGasPrice === 'function') {\n gasPrice = await evmClient.getGasPrice();\n }\n\n // Get message fee\n const messageFee = await this.getMessageFee();\n\n // Calculate total cost\n const gasCost = estimatedGas * gasPrice;\n const totalCost = gasCost + messageFee;\n const formattedCost = this.formatWei(totalCost);\n\n return {\n params,\n actionPayload,\n nonce,\n challenge,\n estimatedGas,\n gasPrice,\n messageFee,\n totalCost,\n formattedCost,\n preparedAt: Date.now(),\n expiresAt: Date.now() + PREPARED_TRANSFER_TTL,\n };\n }\n\n /**\n * Get a human-readable summary of a prepared transfer (Issue #26)\n * \n * Use this to show users what they're signing before biometric authentication.\n * The summary includes:\n * - Action type (transfer, bridge, execute, config)\n * - Human-readable amounts (not wei)\n * - Recipient display (truncated address, ENS if available)\n * - Chain information\n * - Risk warnings for unusual transactions\n * - Gas cost breakdown\n * - Expiration countdown\n * \n * @example\n * ```typescript\n * const prepared = await sdk.prepareTransfer({\n * recipient: '0x123...',\n * amount: '1000000000000000000', // 1 ETH in wei\n * tokenAddress: NATIVE_TOKEN_ADDRESS,\n * targetChain: 10004, // Base Sepolia\n * });\n * \n * const summary = await sdk.getTransactionSummary(prepared);\n * console.log(summary.title); // \"Transfer\"\n * console.log(summary.description); // \"Send 1.0 ETH to 0x123...abc\"\n * console.log(summary.details.formattedAmount); // \"1.0\"\n * console.log(summary.risks); // [{ type: 'large_transaction', level: 'high', ... }]\n * ```\n * \n * @param prepared - PreparedTransfer or PreparedBridge from prepare methods\n * @returns Promise<TransactionSummary> with human-readable details\n */\n async getTransactionSummary(prepared: PreparedTransfer | PreparedBridge): Promise<TransactionSummary> {\n return this.transactionParser.parse(prepared);\n }\n\n // ============================================================================\n // Spending Limits (Issue #27)\n // ============================================================================\n\n /**\n * Get current spending limits for your vault\n * \n * @example\n * ```typescript\n * const limits = await sdk.getSpendingLimits();\n * console.log(`Daily remaining: ${limits.dailyRemaining}`);\n * console.log(`Resets in: ${limits.timeUntilReset}ms`);\n * ```\n * \n * @param chainId - Optional chain ID (defaults to current chain)\n * @returns Promise<SpendingLimits> with current limits and usage\n */\n async getSpendingLimits(chainId?: number): Promise<SpendingLimits> {\n const vaultAddress = this.getVaultAddress();\n const effectiveChainId = chainId ?? this.chain.getConfig().wormholeChainId;\n const rpcUrl = this.chainRpcUrls?.[effectiveChainId] ?? this.chain.getConfig().rpcUrl;\n \n return this.spendingLimits.getSpendingLimits(vaultAddress, effectiveChainId, rpcUrl);\n }\n\n /**\n * Get spending limits formatted for UI display\n * \n * @example\n * ```typescript\n * const formatted = await sdk.getFormattedSpendingLimits();\n * console.log(`${formatted.dailyUsedPercentage}% of daily limit used`);\n * console.log(`Resets in: ${formatted.timeUntilReset}`);\n * ```\n */\n async getFormattedSpendingLimits(chainId?: number): Promise<FormattedSpendingLimits> {\n const vaultAddress = this.getVaultAddress();\n const effectiveChainId = chainId ?? this.chain.getConfig().wormholeChainId;\n const rpcUrl = this.chainRpcUrls?.[effectiveChainId] ?? this.chain.getConfig().rpcUrl;\n \n return this.spendingLimits.getFormattedSpendingLimits(vaultAddress, effectiveChainId, { rpcUrl });\n }\n\n /**\n * Check if a transaction amount is within spending limits\n * \n * @example\n * ```typescript\n * const check = await sdk.checkSpendingLimit(ethers.parseEther(\"1.0\"));\n * if (!check.allowed) {\n * console.log(check.message);\n * console.log('Suggestions:', check.suggestions);\n * }\n * ```\n * \n * @param amount - Amount to check (in wei/base units)\n * @param chainId - Optional chain ID\n * @returns LimitCheckResult with allowed status and suggestions\n */\n async checkSpendingLimit(amount: bigint, chainId?: number): Promise<LimitCheckResult> {\n const vaultAddress = this.getVaultAddress();\n const effectiveChainId = chainId ?? this.chain.getConfig().wormholeChainId;\n const rpcUrl = this.chainRpcUrls?.[effectiveChainId] ?? this.chain.getConfig().rpcUrl;\n \n return this.spendingLimits.checkTransactionLimit(vaultAddress, effectiveChainId, amount, { rpcUrl });\n }\n\n /**\n * Prepare a transaction to update the daily spending limit\n * Returns a PreparedTransfer that can be signed and executed\n * \n * @example\n * ```typescript\n * // Set daily limit to 5 ETH\n * const prepared = await sdk.prepareSetDailyLimit(ethers.parseEther(\"5.0\"));\n * const result = await sdk.executeTransfer(prepared, signer);\n * ```\n * \n * @param newLimit - New daily limit (0 = unlimited)\n * @returns PreparedTransfer for signing\n */\n async prepareSetDailyLimit(newLimit: bigint): Promise<PreparedTransfer> {\n const credential = this.passkey.getCredential();\n if (!credential) {\n throw new Error('No credential set');\n }\n\n const actionPayload = this.spendingLimits.prepareDailyLimitUpdate(newLimit);\n const nonce = await this.getNonce();\n const targetChain = this.chain.getConfig().wormholeChainId;\n const challenge = buildChallenge(credential.keyHash, targetChain, nonce, actionPayload);\n const messageFee = await this.getMessageFee();\n \n return {\n params: {\n targetChain,\n token: 'native',\n recipient: this.getVaultAddress(),\n amount: 0n,\n },\n actionPayload,\n nonce,\n challenge,\n estimatedGas: 0n,\n gasPrice: 0n,\n messageFee,\n totalCost: messageFee,\n formattedCost: '0',\n preparedAt: Date.now(),\n expiresAt: Date.now() + PREPARED_TRANSFER_TTL,\n };\n }\n\n /**\n * Prepare a transaction to pause the vault (emergency stop)\n * Pausing prevents all withdrawals until unpaused\n * \n * @example\n * ```typescript\n * const prepared = await sdk.preparePauseVault();\n * const result = await sdk.executeTransfer(prepared, signer);\n * ```\n */\n async preparePauseVault(): Promise<PreparedTransfer> {\n const credential = this.passkey.getCredential();\n if (!credential) {\n throw new Error('No credential set');\n }\n\n const actionPayload = this.spendingLimits.preparePauseVault();\n const nonce = await this.getNonce();\n const targetChain = this.chain.getConfig().wormholeChainId;\n const challenge = buildChallenge(credential.keyHash, targetChain, nonce, actionPayload);\n const messageFee = await this.getMessageFee();\n \n return {\n params: {\n targetChain,\n token: 'native',\n recipient: this.getVaultAddress(),\n amount: 0n,\n },\n actionPayload,\n nonce,\n challenge,\n estimatedGas: 0n,\n gasPrice: 0n,\n messageFee,\n totalCost: messageFee,\n formattedCost: '0',\n preparedAt: Date.now(),\n expiresAt: Date.now() + PREPARED_TRANSFER_TTL,\n };\n }\n\n /**\n * Prepare a transaction to unpause the vault\n * \n * @example\n * ```typescript\n * const prepared = await sdk.prepareUnpauseVault();\n * const result = await sdk.executeTransfer(prepared, signer);\n * ```\n */\n async prepareUnpauseVault(): Promise<PreparedTransfer> {\n const credential = this.passkey.getCredential();\n if (!credential) {\n throw new Error('No credential set');\n }\n\n const actionPayload = this.spendingLimits.prepareUnpauseVault();\n const nonce = await this.getNonce();\n const targetChain = this.chain.getConfig().wormholeChainId;\n const challenge = buildChallenge(credential.keyHash, targetChain, nonce, actionPayload);\n const messageFee = await this.getMessageFee();\n \n return {\n params: {\n targetChain,\n token: 'native',\n recipient: this.getVaultAddress(),\n amount: 0n,\n },\n actionPayload,\n nonce,\n challenge,\n estimatedGas: 0n,\n gasPrice: 0n,\n messageFee,\n totalCost: messageFee,\n formattedCost: '0',\n preparedAt: Date.now(),\n expiresAt: Date.now() + PREPARED_TRANSFER_TTL,\n };\n }\n\n /**\n * Execute a prepared transfer\n * Use this after prepareTransfer() for better UX\n * \n * @param prepared - PreparedTransfer from prepareTransfer()\n * @param signer - Signer to pay for gas\n * @returns TransferResult with tracking info\n */\n async executeTransfer(\n prepared: PreparedTransfer, \n signer: any\n ): Promise<TransferResult> {\n const credential = this.passkey.getCredential();\n if (!credential) {\n throw new Error('No credential set');\n }\n\n // Check if prepared transfer has expired\n if (Date.now() > prepared.expiresAt) {\n throw new Error('Prepared transfer has expired. Please call prepareTransfer() again.');\n }\n\n // Sign with passkey\n const signature = await this.passkey.sign(prepared.challenge);\n\n // Dispatch the transaction\n const result = await this.chain.dispatch(\n signature,\n credential.publicKeyX,\n credential.publicKeyY,\n prepared.params.targetChain,\n prepared.actionPayload,\n prepared.nonce,\n signer\n );\n\n // Track the transaction\n if (result.transactionHash) {\n const chainConfig = this.chain.getConfig();\n this.transactions.track(\n result.transactionHash,\n chainConfig.wormholeChainId,\n undefined,\n result.sequence\n );\n }\n\n // Invalidate balance cache for sender\n const vaultAddress = this.getVaultAddress();\n const chainConfig = this.chain.getConfig();\n this.balance.invalidateCache(chainConfig.wormholeChainId, vaultAddress);\n\n return {\n ...result,\n params: prepared.params,\n timestamp: Date.now(),\n };\n }\n\n /**\n * Enhanced transfer with automatic tracking\n * \n * @param params - Transfer parameters\n * @param signer - Signer to pay for gas\n * @param onStatusChange - Optional callback for transaction status updates\n * @returns TransferResult with tracking info\n */\n async transferWithTracking(\n params: TransferParams,\n signer: any,\n onStatusChange?: TransactionCallback\n ): Promise<TransferResult> {\n const credential = this.passkey.getCredential();\n if (!credential) {\n throw new Error('No credential set');\n }\n\n // Execute the transfer\n const actionPayload = await this.buildTransferPayload(params);\n const nonce = await this.getNonce();\n const challenge = buildChallenge(\n credential.keyHash,\n params.targetChain,\n nonce,\n actionPayload\n );\n\n const signature = await this.passkey.sign(challenge);\n\n const result = await this.chain.dispatch(\n signature,\n credential.publicKeyX,\n credential.publicKeyY,\n params.targetChain,\n actionPayload,\n nonce,\n signer\n );\n\n // Track the transaction\n if (result.transactionHash) {\n const chainConfig = this.chain.getConfig();\n this.transactions.track(\n result.transactionHash,\n chainConfig.wormholeChainId,\n onStatusChange,\n result.sequence\n );\n }\n\n // Invalidate balance cache\n const vaultAddress = this.getVaultAddress();\n const chainConfig = this.chain.getConfig();\n this.balance.invalidateCache(chainConfig.wormholeChainId, vaultAddress);\n\n return {\n ...result,\n params,\n timestamp: Date.now(),\n };\n }\n\n /**\n * Execute a gasless transfer using the relayer\n * \n * This method allows users to send funds without paying gas themselves.\n * The relayer service submits the transaction to the Hub and pays the gas.\n * The relayer then automatically relays the VAA to the destination spoke chain.\n * \n * @param params - Transfer parameters (to, amount, token, targetChain)\n * @param onStatusChange - Optional callback for transaction status updates\n * @returns TransferResult with Hub tx hash and tracking info\n */\n async transferViaRelayer(\n params: TransferParams,\n onStatusChange?: TransactionCallback\n ): Promise<TransferResult> {\n const credential = this.passkey.getCredential();\n if (!credential) {\n throw new Error('No credential set. Call passkey.register() or passkey.setCredential() first.');\n }\n\n // Ensure relayer is available\n if (!this.relayer) {\n throw new Error('Relayer not configured. Please provide relayerUrl in SDK config.');\n }\n\n const chainConfig = this.chain.getConfig();\n\n // Build the action payload (canonical encoding from the active chain client)\n const actionPayload = await this.buildTransferPayload(params);\n\n // Client-first preparation:\n // - fetch Guardian-attested nonce via Wormhole Queries when possible\n // - fall back to hub RPC nonce lookup\n // - prompt user to sign once\n const prepared = await authenticateAndPrepare(\n {\n credential,\n targetChain: params.targetChain,\n actionPayload,\n },\n this.queryApiKey ?? ''\n );\n\n const submitRequest = JSON.parse(new TextDecoder().decode(prepared.serializedTx)) as SubmitSignedActionRequest;\n\n // Ensure the request body uses our canonical payload (defensive)\n (submitRequest as any).actionPayload = actionPayload;\n\n const relayerResult = await this.relayer.submitSignedAction(submitRequest);\n\n if (!relayerResult.success) {\n throw new Error(`Relayer submission failed: ${relayerResult.error}`);\n }\n\n // Track the Hub transaction\n if (relayerResult.txHash) {\n const hubChainId = chainConfig.hubChainId ?? chainConfig.wormholeChainId;\n this.transactions.track(\n relayerResult.txHash,\n hubChainId,\n onStatusChange,\n relayerResult.sequence ? BigInt(relayerResult.sequence) : undefined\n );\n }\n\n // Invalidate balance cache for sender\n const vaultAddress = this.getVaultAddress();\n this.balance.invalidateCache(chainConfig.wormholeChainId, vaultAddress);\n\n return {\n transactionHash: relayerResult.txHash ?? '',\n sequence: relayerResult.sequence ? BigInt(relayerResult.sequence) : 0n,\n userKeyHash: credential.keyHash,\n targetChain: params.targetChain,\n blockNumber: 0, // Hub tx block number not returned by relayer\n params,\n timestamp: Date.now(),\n };\n }\n\n /**\n * Wait for a transaction to confirm\n * \n * @param hash - Transaction hash\n * @returns TransactionState when confirmed\n */\n async waitForTransaction(hash: string): Promise<TransactionState> {\n const chainConfig = this.chain.getConfig();\n return await this.transactions.waitForConfirmation(hash, chainConfig.wormholeChainId);\n }\n\n // ========================================================================\n // Balance Methods\n // ========================================================================\n\n /**\n * Get native token balance for the current vault\n * \n * @returns TokenBalance with native token balance\n */\n async getVaultNativeBalance(): Promise<TokenBalance> {\n const vaultAddress = this.getVaultAddress();\n const chainConfig = this.chain.getConfig();\n return await this.balance.getNativeBalance(chainConfig.wormholeChainId, vaultAddress);\n }\n\n /**\n * Get all token balances for the current vault\n * \n * @param includeZeroBalances - Whether to include tokens with 0 balance\n * @returns PortfolioBalance with all token balances\n */\n async getVaultBalances(includeZeroBalances: boolean = false): Promise<PortfolioBalance> {\n const vaultAddress = this.getVaultAddress();\n const chainConfig = this.chain.getConfig();\n\n // Prefer Wormhole Queries when possible (faster, Guardian-attested), but preserve\n // existing behavior as a fallback.\n const credential = this.passkey.getCredential();\n if (credential && this.queryApiKey) {\n try {\n const wormholeChainId = chainConfig.wormholeChainId;\n const tokenList = getAllTokens(wormholeChainId);\n const erc20Tokens = tokenList\n .filter((t) => !isNativeToken(t.address))\n .map((t) => t.address);\n\n const result = await queryPortfolio(credential.keyHash, this.queryApiKey, {\n network: this.testnet ? 'testnet' : 'mainnet',\n vaultAddresses: { [wormholeChainId]: vaultAddress },\n evmTokenAddresses: { [wormholeChainId]: erc20Tokens },\n rpcUrls: { [wormholeChainId]: chainConfig.rpcUrl },\n maxAge: 60,\n // Testnet Query Proxy can be slow; use a more forgiving timeout.\n timeout: this.testnet ? 15_000 : 10_000,\n maxAttempts: this.testnet ? 3 : 2,\n });\n\n const chain = result.chains.find((c) => c.wormholeChainId === wormholeChainId);\n if (chain && !chain.error) {\n const byAssetId = new Map(chain.balances.map((b) => [b.assetId.toLowerCase(), b] as const));\n const tokens = tokenList.map((t) => {\n if (isNativeToken(t.address)) {\n return null;\n }\n const found = byAssetId.get(t.address.toLowerCase());\n const amount = found?.amount ?? 0n;\n const formatted = ethers.formatUnits(amount, t.decimals);\n return {\n token: t,\n balance: amount,\n formatted,\n usdValue: found?.usdValue,\n };\n }).filter((t): t is NonNullable<typeof t> => !!t);\n\n // Add native token via RPC (Queries don't support native ETH balance).\n const native = await this.balance.getNativeBalance(wormholeChainId, vaultAddress);\n const merged = [native, ...tokens];\n\n const filtered = includeZeroBalances ? merged : merged.filter((t) => t.balance > 0n);\n const totalUsdValue = filtered.reduce((sum, t) => sum + (t.usdValue ?? 0), 0);\n\n return {\n wormholeChainId,\n chainName: chainConfig.name,\n address: vaultAddress,\n tokens: filtered,\n totalUsdValue: totalUsdValue || undefined,\n lastUpdated: Date.now(),\n };\n }\n } catch {\n // Fall back to the existing RPC-based balance logic.\n }\n }\n\n return await this.balance.getPortfolioBalance(chainConfig.wormholeChainId, vaultAddress, includeZeroBalances);\n }\n\n /**\n * Get token balance for a specific token\n * \n * @param tokenAddress - Token contract address or 'native'\n * @returns TokenBalance for the specified token\n */\n async getVaultTokenBalance(tokenAddress: string): Promise<TokenBalance> {\n const vaultAddress = this.getVaultAddress();\n const chainConfig = this.chain.getConfig();\n return await this.balance.getBalance(\n chainConfig.wormholeChainId,\n vaultAddress,\n tokenAddress\n );\n }\n\n /**\n * Get balances across multiple chains\n * \n * @param chainIds - Array of Wormhole chain IDs to check\n * @returns Array of PortfolioBalance for each chain\n */\n async getMultiChainBalances(chainIds: number[]): Promise<PortfolioBalance[]> {\n const credential = this.passkey.getCredential();\n if (!credential) {\n throw new Error('No credential set');\n }\n\n // Derive an address per chain and query balances accordingly.\n const results: PortfolioBalance[] = [];\n\n for (const wormholeChainId of chainIds) {\n const chainConfig = this.chainDetector.getChainConfig(wormholeChainId);\n\n // If unknown, skip with a warning.\n if (!chainConfig) {\n // eslint-disable-next-line no-console\n console.warn(`Unknown chainId for balances: ${wormholeChainId}`);\n continue;\n }\n\n // Resolve vault address\n const derived = this.chainDetector.deriveVaultAddress(credential, wormholeChainId);\n const address = derived?.address ?? (wormholeChainId === this.chain.getConfig().wormholeChainId\n ? this.getVaultAddress()\n : credential.keyHash);\n\n if (chainConfig.isEvm) {\n try {\n const portfolio = await this.balance.getPortfolioBalance(wormholeChainId, address, false);\n results.push(portfolio);\n } catch (error) {\n // eslint-disable-next-line no-console\n console.warn(`Failed to fetch EVM balances for chain ${wormholeChainId}:`, error);\n }\n continue;\n }\n\n // Non-EVM: fetch native balance via chain-specific client\n try {\n const client: any = this.chainDetector.createClient(wormholeChainId);\n if (typeof client.getNativeBalance !== 'function') {\n // eslint-disable-next-line no-console\n console.warn(`No native balance support for chain ${wormholeChainId}`);\n continue;\n }\n\n const native = await client.getNativeBalance(address);\n const meta = this.chainDetector.getNonEvmNativeTokenMeta(wormholeChainId);\n\n const decimals = meta?.decimals ?? 0;\n const formatted = decimals > 0 ? ethers.formatUnits(native, decimals) : native.toString();\n\n results.push({\n wormholeChainId,\n chainName: chainConfig.name,\n address,\n tokens: [\n {\n token: {\n symbol: meta?.symbol ?? 'NATIVE',\n name: meta?.name ?? 'Native Token',\n address: 'native',\n decimals,\n isNative: true,\n },\n balance: native,\n formatted,\n },\n ],\n lastUpdated: Date.now(),\n });\n } catch (error) {\n // eslint-disable-next-line no-console\n console.warn(`Failed to fetch non-EVM balances for chain ${wormholeChainId}:`, error);\n }\n }\n\n return results;\n }\n\n /**\n * Get token list for a chain\n */\n getTokenList(wormholeChainId?: number): TokenInfo[] {\n const chainId = wormholeChainId ?? this.chain.getConfig().wormholeChainId;\n return getAllTokens(chainId);\n }\n\n /**\n * Get token by symbol\n */\n getTokenBySymbol(symbol: string, wormholeChainId?: number): TokenInfo | null {\n const chainId = wormholeChainId ?? this.chain.getConfig().wormholeChainId;\n return getTokenBySymbol(chainId, symbol);\n }\n\n // ========================================================================\n // Receive Address Methods\n // ========================================================================\n\n /**\n * Get receive address information for sharing\n * Use this to generate QR codes or share your vault address\n * \n * @returns ReceiveAddress with address and sharing info\n */\n getReceiveAddress(): ReceiveAddress {\n const vaultAddress = this.getVaultAddress();\n const chainConfig = this.chain.getConfig();\n \n // Create a deep link for wallet apps (EIP-681 format for EVM)\n const deepLink = chainConfig.isEvm \n ? `ethereum:${vaultAddress}@${chainConfig.chainId}`\n : undefined;\n\n // Create copy-friendly text\n const copyText = `${vaultAddress}`;\n\n return {\n address: vaultAddress,\n chainName: chainConfig.name,\n wormholeChainId: chainConfig.wormholeChainId,\n deepLink,\n copyText,\n };\n }\n\n /**\n * Generate receive address with amount (for payment requests)\n * \n * @param amount - Amount to request\n * @param tokenAddress - Token address or 'native'\n * @param tokenDecimals - Token decimals\n * @returns ReceiveAddress with payment request info\n */\n getPaymentRequest(\n amount: bigint,\n tokenAddress: string = 'native',\n tokenDecimals: number = 18\n ): ReceiveAddress {\n const vaultAddress = this.getVaultAddress();\n const chainConfig = this.chain.getConfig();\n \n // Format amount\n const formattedAmount = this.formatUnits(amount, tokenDecimals);\n \n // Create EIP-681 payment request for EVM\n let deepLink: string | undefined;\n if (chainConfig.isEvm) {\n if (isNativeToken(tokenAddress)) {\n deepLink = `ethereum:${vaultAddress}@${chainConfig.chainId}?value=${amount.toString()}`;\n } else {\n // ERC20 transfer\n deepLink = `ethereum:${tokenAddress}@${chainConfig.chainId}/transfer?address=${vaultAddress}&uint256=${amount.toString()}`;\n }\n }\n\n return {\n address: vaultAddress,\n chainName: chainConfig.name,\n wormholeChainId: chainConfig.wormholeChainId,\n deepLink,\n copyText: `${vaultAddress} (${formattedAmount})`,\n };\n }\n\n // ========================================================================\n // Utility Methods\n // ========================================================================\n\n /**\n * Format wei to ether string\n */\n private formatWei(wei: bigint): string {\n // Simple formatter - 18 decimals\n const ether = Number(wei) / 1e18;\n return `${ether.toFixed(6)} ETH`;\n }\n\n /**\n * Format units based on decimals\n */\n private formatUnits(amount: bigint, decimals: number): string {\n const divisor = BigInt(10 ** decimals);\n const whole = amount / divisor;\n const remainder = amount % divisor;\n const remainderStr = remainder.toString().padStart(decimals, '0');\n const trimmed = remainderStr.slice(0, 4).replace(/0+$/, '') || '0';\n return `${whole}.${trimmed}`;\n }\n\n\n async getVaultInfo(targetChainId?: number): Promise<VaultInfo | null> {\n const credential = this.passkey.getCredential();\n if (!credential) {\n throw new Error('No credential set');\n }\n\n const chainConfig = this.chain.getConfig();\n const checkChainId = targetChainId ?? chainConfig.wormholeChainId;\n\n if (checkChainId !== chainConfig.wormholeChainId) {\n throw new Error('Cross-chain vault queries not yet supported. Please create a client for the target chain.');\n }\n\n const vaultAddress = await this.chain.getVaultAddress(credential.keyHash);\n const exists = await this.chain.vaultExists(credential.keyHash);\n\n if (!vaultAddress || !exists) {\n return null;\n }\n\n return {\n address: vaultAddress,\n ownerKeyHash: credential.keyHash,\n chain: chainConfig.name,\n wormholeChainId: chainConfig.wormholeChainId,\n exists,\n };\n }\n\n // ========================================================================\n // Wallet & Identity Methods\n // ========================================================================\n\n /**\n * Get the deterministic vault address for the current credential\n * This computes the address off-chain without requiring the vault to exist\n * \n * @returns The vault address that will be used when vault is created\n */\n getVaultAddress(): string {\n const credential = this.passkey.getCredential();\n if (!credential) {\n throw new Error('No credential set. Call passkey.register() or passkey.setCredential() first.');\n }\n\n return this.chain.computeVaultAddress(credential.keyHash);\n }\n\n /**\n * Get the vault address for a specific key hash\n * \n * @param keyHash - The user's key hash\n * @returns The deterministic vault address\n */\n getVaultAddressForKeyHash(keyHash: string): string {\n return this.chain.computeVaultAddress(keyHash);\n }\n\n /**\n * Get the vault address for a specific chain\n * Each EVM chain has its own factory contract, so vault addresses are chain-specific.\n * \n * @param wormholeChainId - The Wormhole chain ID\n * @param keyHash - Optional key hash (defaults to current credential)\n * @returns The deterministic vault address for that chain, or null if chain not supported\n */\n getVaultAddressForChain(wormholeChainId: number, keyHash?: string): string | null {\n const hash = keyHash ?? this.passkey.getCredential()?.keyHash;\n if (!hash) {\n throw new Error('No credential set and no keyHash provided');\n }\n\n const credential = { keyHash: hash } as PasskeyCredential;\n const derived = this.chainDetector.deriveVaultAddress(credential, wormholeChainId);\n return derived?.address ?? null;\n }\n\n /**\n * Get vault balances for a specific chain\n * Unlike getVaultBalances() which uses the hub chain, this fetches for any EVM chain.\n * \n * @param wormholeChainId - The Wormhole chain ID\n * @param includeZeroBalances - Whether to include tokens with 0 balance\n * @returns PortfolioBalance with all token balances for that chain\n */\n async getVaultBalancesForChain(\n wormholeChainId: number,\n includeZeroBalances: boolean = false\n ): Promise<PortfolioBalance> {\n const credential = this.passkey.getCredential();\n if (!credential) {\n throw new Error('No credential set');\n }\n\n // Get the correct vault address for this chain\n const vaultAddress = this.getVaultAddressForChain(wormholeChainId, credential.keyHash);\n if (!vaultAddress) {\n throw new Error(`Cannot derive vault address for chain ${wormholeChainId}`);\n }\n\n const chainConfig = this.chainDetector.getChainConfig(wormholeChainId);\n if (!chainConfig) {\n throw new Error(`Unknown chain ${wormholeChainId}`);\n }\n\n // Try Wormhole Queries first for faster, attested results\n if (this.queryApiKey) {\n try {\n const tokenList = getAllTokens(wormholeChainId);\n const erc20Tokens = tokenList\n .filter((t) => !isNativeToken(t.address))\n .map((t) => t.address);\n\n const rpcUrl = this.chainRpcUrls?.[wormholeChainId] ?? chainConfig.rpcUrl;\n \n const result = await queryPortfolio(credential.keyHash, this.queryApiKey, {\n network: this.testnet ? 'testnet' : 'mainnet',\n vaultAddresses: { [wormholeChainId]: vaultAddress },\n evmTokenAddresses: { [wormholeChainId]: erc20Tokens },\n rpcUrls: { [wormholeChainId]: rpcUrl },\n maxAge: 60,\n timeout: this.testnet ? 15_000 : 10_000,\n maxAttempts: this.testnet ? 3 : 2,\n });\n\n const chain = result.chains.find((c) => c.wormholeChainId === wormholeChainId);\n if (chain && !chain.error) {\n const byAssetId = new Map(chain.balances.map((b) => [b.assetId.toLowerCase(), b] as const));\n const tokens = tokenList.map((t) => {\n if (isNativeToken(t.address)) {\n return null;\n }\n const found = byAssetId.get(t.address.toLowerCase());\n const amount = found?.amount ?? 0n;\n const formatted = ethers.formatUnits(amount, t.decimals);\n return {\n token: t,\n balance: amount,\n formatted,\n usdValue: found?.usdValue,\n };\n }).filter((t): t is NonNullable<typeof t> => !!t);\n\n // Add native token via RPC\n const native = await this.balance.getNativeBalance(wormholeChainId, vaultAddress);\n const merged = [native, ...tokens];\n\n const filtered = includeZeroBalances ? merged : merged.filter((t) => t.balance > 0n);\n const totalUsdValue = filtered.reduce((sum, t) => sum + (t.usdValue ?? 0), 0);\n\n return {\n wormholeChainId,\n chainName: chainConfig.name,\n address: vaultAddress,\n tokens: filtered,\n totalUsdValue: totalUsdValue || undefined,\n lastUpdated: Date.now(),\n };\n }\n } catch {\n // Fall back to RPC-based balance fetching\n }\n }\n\n // Fallback to RPC-based balance fetching\n return await this.balance.getPortfolioBalance(wormholeChainId, vaultAddress, includeZeroBalances);\n }\n\n /**\n * Get unified identity with addresses across chains\n * \n * @returns UnifiedIdentity containing credential info and chain addresses\n */\n async getUnifiedIdentity(): Promise<UnifiedIdentity> {\n const credential = this.passkey.getCredential();\n if (!credential) {\n throw new Error('No credential set. Call passkey.register() or passkey.setCredential() first.');\n }\n\n // Check if we have cached identity\n if (this.unifiedIdentity && this.unifiedIdentity.keyHash === credential.keyHash) {\n return this.unifiedIdentity;\n }\n\n // Try to load from storage first\n const storedIdentity = this.wallet.loadIdentityFromStorage(credential.keyHash);\n if (storedIdentity) {\n this.unifiedIdentity = storedIdentity;\n // Update deployment status from chain\n await this.updateDeploymentStatus();\n return this.unifiedIdentity;\n }\n\n // Build new identity\n const chainConfig = this.chain.getConfig();\n const addresses: ChainAddress[] = [];\n\n // Compute address for current chain\n try {\n const address = this.chain.computeVaultAddress(credential.keyHash);\n const deployed = await this.chain.vaultExists(credential.keyHash);\n \n addresses.push({\n wormholeChainId: chainConfig.wormholeChainId,\n chainName: chainConfig.name,\n address,\n isEvm: chainConfig.isEvm,\n deployed,\n derivationType: 'create2',\n });\n } catch (error) {\n console.warn('Could not compute vault address for current chain:', error);\n }\n\n this.unifiedIdentity = {\n keyHash: credential.keyHash,\n publicKeyX: credential.publicKeyX,\n publicKeyY: credential.publicKeyY,\n credentialId: credential.credentialId,\n addresses,\n createdAt: Date.now(),\n updatedAt: Date.now(),\n };\n\n return this.unifiedIdentity;\n }\n\n /**\n * Get the current chain address from unified identity\n */\n async getCurrentChainAddress(): Promise<ChainAddress | null> {\n const identity = await this.getUnifiedIdentity();\n const chainConfig = this.chain.getConfig();\n \n return identity.addresses.find(\n a => a.wormholeChainId === chainConfig.wormholeChainId\n ) ?? null;\n }\n\n /**\n * Update deployment status for cached identity\n */\n private async updateDeploymentStatus(): Promise<void> {\n if (!this.unifiedIdentity) return;\n\n const chainConfig = this.chain.getConfig();\n const address = this.unifiedIdentity.addresses.find(\n a => a.wormholeChainId === chainConfig.wormholeChainId\n );\n\n if (address) {\n try {\n const deployed = await this.chain.vaultExists(this.unifiedIdentity.keyHash);\n address.deployed = deployed;\n this.unifiedIdentity.updatedAt = Date.now();\n } catch (error) {\n console.warn('Could not update deployment status:', error);\n }\n }\n }\n\n /**\n * Add a chain address to the unified identity\n * Used when configuring multiple chains\n */\n addChainAddress(address: ChainAddress): void {\n if (!this.unifiedIdentity) {\n throw new Error('No identity loaded. Call getUnifiedIdentity() first.');\n }\n\n const existing = this.unifiedIdentity.addresses.findIndex(\n a => a.wormholeChainId === address.wormholeChainId\n );\n\n if (existing >= 0) {\n this.unifiedIdentity.addresses[existing] = address;\n } else {\n this.unifiedIdentity.addresses.push(address);\n }\n\n this.unifiedIdentity.updatedAt = Date.now();\n }\n\n // ========================================================================\n // Vault Creation Methods\n // ========================================================================\n\n /**\n * Create a vault for the current credential\n * \n * @param signer - The signer to pay for gas\n * @returns VaultCreationResult with address and transaction details\n */\n async createVault(signer: any): Promise<VaultCreationResult> {\n const credential = this.passkey.getCredential();\n if (!credential) {\n throw new Error('No credential set');\n }\n\n const result = await this.chain.createVault(credential.keyHash, signer);\n\n // Update cached identity if available\n if (this.unifiedIdentity) {\n const chainConfig = this.chain.getConfig();\n const address = this.unifiedIdentity.addresses.find(\n a => a.wormholeChainId === chainConfig.wormholeChainId\n );\n\n if (address) {\n address.deployed = true;\n address.deploymentTxHash = result.transactionHash;\n } else {\n this.unifiedIdentity.addresses.push({\n wormholeChainId: chainConfig.wormholeChainId,\n chainName: chainConfig.name,\n address: result.address,\n isEvm: chainConfig.isEvm,\n deployed: true,\n deploymentTxHash: result.transactionHash,\n derivationType: 'create2',\n });\n }\n\n this.unifiedIdentity.updatedAt = Date.now();\n }\n\n return result;\n }\n\n /**\n * Create a vault with sponsored gas (Veridex pays for gas)\n * \n * Uses the sponsor wallet configured in SDK initialization.\n * If no sponsor is configured, throws an error.\n * \n * @param wormholeChainId - Optional chain ID for multi-chain creation\n * @returns VaultCreationResult with address and transaction details\n */\n async createVaultSponsored(wormholeChainId?: number): Promise<VaultCreationResult> {\n const credential = this.passkey.getCredential();\n if (!credential) {\n throw new Error('No credential set');\n }\n\n if (!this.sponsorPrivateKey) {\n throw new Error('No sponsor wallet configured. Set sponsorPrivateKey in SDK config.');\n }\n\n // Check if chain client supports sponsored creation\n if (!this.chain.createVaultSponsored) {\n throw new Error('Current chain client does not support sponsored vault creation');\n }\n\n // Get the appropriate RPC URL for the chain\n const chainConfig = this.chain.getConfig();\n const targetChainId = wormholeChainId ?? chainConfig.wormholeChainId;\n const rpcUrl = this.chainRpcUrls?.[targetChainId] ?? chainConfig.rpcUrl;\n\n const result = await this.chain.createVaultSponsored(\n credential.keyHash,\n this.sponsorPrivateKey,\n rpcUrl\n );\n\n // Update cached identity if available\n if (this.unifiedIdentity) {\n const address = this.unifiedIdentity.addresses.find(\n a => a.wormholeChainId === targetChainId\n );\n\n if (address) {\n address.deployed = true;\n address.deploymentTxHash = result.transactionHash;\n } else {\n this.unifiedIdentity.addresses.push({\n wormholeChainId: targetChainId,\n chainName: chainConfig.name,\n address: result.address,\n isEvm: chainConfig.isEvm,\n deployed: true,\n deploymentTxHash: result.transactionHash,\n derivationType: 'create2',\n });\n }\n\n this.unifiedIdentity.updatedAt = Date.now();\n }\n\n return result;\n }\n\n /**\n * Check if sponsored vault creation is available\n */\n hasSponsoredVaultCreation(): boolean {\n return !!this.sponsorPrivateKey && !!this.chain.createVaultSponsored;\n }\n\n /**\n * Ensure vault exists, creating with sponsor if available\n * Falls back to requiring a signer if no sponsor configured\n * \n * @param signer - Optional signer (only required if no sponsor configured)\n * @returns The vault address\n */\n async ensureVaultAuto(signer?: any): Promise<string> {\n const credential = this.passkey.getCredential();\n if (!credential) {\n throw new Error('No credential set');\n }\n\n const exists = await this.chain.vaultExists(credential.keyHash);\n if (exists) {\n return this.getVaultAddress();\n }\n\n // Try sponsored creation first\n if (this.hasSponsoredVaultCreation()) {\n const result = await this.createVaultSponsored();\n return result.address;\n }\n\n // Fall back to signer-based creation\n if (!signer) {\n throw new Error('No sponsor configured and no signer provided for vault creation');\n }\n\n const result = await this.createVault(signer);\n return result.address;\n }\n\n /**\n * Ensure vault exists, creating if necessary\n * \n * @param signer - The signer to pay for gas (only used if creation needed)\n * @returns The vault address\n */\n async ensureVault(signer: any): Promise<string> {\n const credential = this.passkey.getCredential();\n if (!credential) {\n throw new Error('No credential set');\n }\n\n const exists = await this.chain.vaultExists(credential.keyHash);\n if (exists) {\n return this.getVaultAddress();\n }\n\n const result = await this.createVault(signer);\n return result.address;\n }\n\n /**\n * Estimate gas for vault creation\n */\n async estimateVaultCreationGas(): Promise<bigint> {\n const credential = this.passkey.getCredential();\n if (!credential) {\n throw new Error('No credential set');\n }\n\n return await this.chain.estimateVaultCreationGas(credential.keyHash);\n }\n\n async vaultExists(): Promise<boolean> {\n const credential = this.passkey.getCredential();\n if (!credential) {\n throw new Error('No credential set');\n }\n\n return await this.chain.vaultExists(credential.keyHash);\n }\n\n // ========================================================================\n // Sponsored Vault Creation (Gasless)\n // ========================================================================\n\n /**\n * Check if gas sponsorship is configured\n * \n * @returns true if a sponsor is configured (relayer, integrator, or Veridex)\n */\n isSponsorshipAvailable(): boolean {\n return this.sponsor.isConfigured();\n }\n\n /**\n * Get the active sponsorship source\n * \n * Priority order:\n * 1. 'relayer' - Remote relayer service (future primary)\n * 2. 'integrator' - Platform-provided sponsor key\n * 3. 'veridex' - Veridex default sponsor (fallback)\n * 4. 'none' - No sponsorship available\n * \n * @returns The active sponsorship source\n */\n getSponsorshipSource(): 'relayer' | 'integrator' | 'veridex' | 'none' {\n return this.sponsor.getSponsorshipSource();\n }\n\n /**\n * Get supported chains for sponsored vault creation\n * \n * @returns Array of chain configurations\n */\n getSponsoredChains(): ChainDeploymentConfig[] {\n return this.sponsor.getSupportedChains();\n }\n\n /**\n * Create a vault on a specific chain using gas sponsorship\n * User doesn't need to pay gas - Veridex pays\n * \n * @param wormholeChainId - The Wormhole chain ID to create vault on\n * @returns Result with vault address\n */\n async createSponsoredVault(wormholeChainId: number): Promise<SponsoredVaultResult> {\n const credential = this.passkey.getCredential();\n if (!credential) {\n throw new Error('No credential set. Call passkey.register() or passkey.setCredential() first.');\n }\n\n if (!this.sponsor.isConfigured()) {\n throw new Error('Gas sponsorship not configured. Set sponsorPrivateKey in SDK config.');\n }\n\n const result = await this.sponsor.createVaultOnChain(credential.keyHash, wormholeChainId);\n\n // Update cached identity if successful\n if (result.success && result.vaultAddress && this.unifiedIdentity) {\n const existingAddress = this.unifiedIdentity.addresses.find(\n a => a.wormholeChainId === wormholeChainId\n );\n\n if (existingAddress) {\n existingAddress.deployed = true;\n existingAddress.deploymentTxHash = result.transactionHash;\n existingAddress.address = result.vaultAddress;\n } else {\n this.unifiedIdentity.addresses.push({\n wormholeChainId,\n chainName: result.chain,\n address: result.vaultAddress,\n isEvm: true,\n deployed: true,\n deploymentTxHash: result.transactionHash,\n derivationType: 'create2',\n });\n }\n\n this.unifiedIdentity.updatedAt = Date.now();\n }\n\n return result;\n }\n\n /**\n * Create vaults on all supported chains using gas sponsorship\n * User doesn't need to pay gas - Veridex pays\n * \n * @returns Multi-chain result with all vault addresses\n */\n async createSponsoredVaultsOnAllChains(): Promise<MultiChainVaultResult> {\n const credential = this.passkey.getCredential();\n if (!credential) {\n throw new Error('No credential set. Call passkey.register() or passkey.setCredential() first.');\n }\n\n if (!this.sponsor.isConfigured()) {\n throw new Error('Gas sponsorship not configured. Set sponsorPrivateKey in SDK config.');\n }\n\n const result = await this.sponsor.createVaultsOnAllChains(credential.keyHash);\n\n // Update cached identity with all successful vaults\n if (this.unifiedIdentity) {\n for (const vaultResult of result.results) {\n if (vaultResult.success && vaultResult.vaultAddress) {\n const existingAddress = this.unifiedIdentity.addresses.find(\n a => a.wormholeChainId === vaultResult.wormholeChainId\n );\n\n if (existingAddress) {\n existingAddress.deployed = true;\n existingAddress.deploymentTxHash = vaultResult.transactionHash;\n existingAddress.address = vaultResult.vaultAddress;\n } else {\n this.unifiedIdentity.addresses.push({\n wormholeChainId: vaultResult.wormholeChainId,\n chainName: vaultResult.chain,\n address: vaultResult.vaultAddress,\n isEvm: true,\n deployed: true,\n deploymentTxHash: vaultResult.transactionHash,\n derivationType: 'create2',\n });\n }\n }\n }\n\n this.unifiedIdentity.updatedAt = Date.now();\n }\n\n return result;\n }\n\n /**\n * Check if vaults exist on all supported chains\n * \n * @returns Map of chain ID to vault status\n */\n async checkVaultsOnAllChains(): Promise<Record<number, { exists: boolean; address: string }>> {\n const credential = this.passkey.getCredential();\n if (!credential) {\n throw new Error('No credential set');\n }\n\n return await this.sponsor.checkVaultsOnAllChains(credential.keyHash);\n }\n\n /**\n * Ensure vaults exist on all chains, creating if necessary (sponsored)\n * \n * @returns Result with all vault addresses\n */\n async ensureSponsoredVaultsOnAllChains(): Promise<MultiChainVaultResult> {\n const credential = this.passkey.getCredential();\n if (!credential) {\n throw new Error('No credential set');\n }\n\n // First check which vaults exist\n const existing = await this.checkVaultsOnAllChains();\n \n // Find chains that need vault creation\n const supportedChains = this.sponsor.getSupportedChains();\n const needsCreation = supportedChains.filter(\n chain => !existing[chain.wormholeChainId]?.exists\n );\n\n if (needsCreation.length === 0) {\n // All vaults exist\n const vaultAddresses: Record<number, string> = {};\n const results: SponsoredVaultResult[] = [];\n\n for (const chain of supportedChains) {\n const status = existing[chain.wormholeChainId];\n vaultAddresses[chain.wormholeChainId] = status?.address || '';\n results.push({\n success: true,\n chain: chain.name,\n wormholeChainId: chain.wormholeChainId,\n vaultAddress: status?.address,\n alreadyExists: true,\n });\n }\n\n return {\n keyHash: credential.keyHash,\n results,\n allSuccessful: true,\n vaultAddresses,\n };\n }\n\n // Create missing vaults\n return await this.createSponsoredVaultsOnAllChains();\n }\n\n // ==========================================================================\n // Backup Passkey / Multi-Key Identity Methods (Issue #22)\n // ==========================================================================\n\n /**\n * Get the identity state for the current passkey\n * Returns information about the identity including key count and root status\n * \n * @returns Identity state or null if no credential set\n */\n async getIdentityState(): Promise<IdentityState | null> {\n const credential = this.passkey.getCredential();\n if (!credential) {\n return null;\n }\n\n const evmClient = this.chain as any;\n if (typeof evmClient.getIdentityState !== 'function') {\n throw new Error('Identity management not supported on this chain client');\n }\n\n return await evmClient.getIdentityState(credential.keyHash);\n }\n\n /**\n * Get all authorized passkeys for the current identity\n * \n * @returns Array of authorized keys with root status, or null if no credential\n */\n async listAuthorizedPasskeys(): Promise<AuthorizedKey[] | null> {\n const credential = this.passkey.getCredential();\n if (!credential) {\n return null;\n }\n\n const evmClient = this.chain as any;\n if (typeof evmClient.getIdentityState !== 'function') {\n throw new Error('Identity management not supported on this chain client');\n }\n\n // Get the identity for this key\n const state = await evmClient.getIdentityState(credential.keyHash);\n if (!state.identity || state.identity === ethers.ZeroHash) {\n // Key not registered, return just this key as pending\n return [];\n }\n\n // Get all authorized keys for this identity\n const keyHashes: string[] = await evmClient.getAuthorizedKeys(state.identity);\n \n // Map to AuthorizedKey with root status\n return keyHashes.map(keyHash => ({\n keyHash,\n isRoot: keyHash === state.identity,\n }));\n }\n\n /**\n * Check if the current identity has backup passkeys registered\n * Returns false if only one passkey (the root) is registered\n * \n * @returns True if backup passkeys exist, false otherwise\n */\n async hasBackupPasskeys(): Promise<boolean> {\n const state = await this.getIdentityState();\n if (!state || state.keyCount === 0) {\n return false;\n }\n return state.keyCount > 1;\n }\n\n /**\n * Register a backup passkey for the current identity\n * The backup passkey can be used to recover access if the primary is lost\n * \n * @param newCredential The new passkey credential to add as backup\n * @param signer Ethereum signer to pay gas (optional, uses relayer if not provided)\n * @returns Result with transaction hash and sequence for cross-chain sync\n */\n async addBackupPasskey(\n newCredential: PasskeyCredential,\n signer?: any\n ): Promise<AddBackupKeyResult> {\n const credential = this.passkey.getCredential();\n if (!credential) {\n throw new Error('No credential set. Call passkey.register() or passkey.setCredential() first.');\n }\n\n const evmClient = this.chain as any;\n if (typeof evmClient.addBackupKey !== 'function') {\n throw new Error('Backup passkey management not supported on this chain client');\n }\n\n // Get identity state to ensure we're within limits\n const state = await evmClient.getIdentityState(credential.keyHash);\n if (state.keyCount >= state.maxKeys) {\n throw new Error(`Maximum keys (${state.maxKeys}) already registered for this identity`);\n }\n\n // Check if the new key is already authorized\n const isAlreadyAuthorized = await evmClient.isAuthorizedForIdentity(\n state.identity,\n newCredential.keyHash\n );\n if (isAlreadyAuthorized) {\n throw new Error('This passkey is already authorized for this identity');\n }\n\n if (!state.identity || state.identity === ethers.ZeroHash) {\n throw new Error('Identity not registered. Call registerIdentity() first.');\n }\n\n // Nonce for key-management is stored on the *identity* (not necessarily the signing key)\n const nonce = await this.chain.getNonce(state.identity);\n\n // Challenge = abi.encodePacked(\"VERIDEX_ADD_KEY\", identityKeyHash, newKeyHash, nonce)\n const packedChallenge = ethers.solidityPacked(\n ['string', 'bytes32', 'bytes32', 'uint256'],\n ['VERIDEX_ADD_KEY', state.identity, newCredential.keyHash, nonce]\n );\n\n const signature = await this.passkey.sign(ethers.getBytes(packedChallenge));\n\n if (!signer) {\n throw new Error('Signer required for backup key registration');\n }\n\n // Call Hub contract to add backup key\n const { receipt, sequence } = await evmClient.addBackupKey(\n signature,\n credential.publicKeyX,\n credential.publicKeyY,\n newCredential.publicKeyX,\n newCredential.publicKeyY,\n nonce,\n signer\n );\n\n // Get updated key count\n const updatedState = await evmClient.getIdentityState(credential.keyHash);\n\n return {\n transactionHash: receipt.hash,\n sequence,\n identity: state.identity,\n newKeyHash: newCredential.keyHash,\n keyCount: updatedState.keyCount,\n };\n }\n\n /**\n * Remove a passkey from the current identity\n * Cannot remove the last remaining passkey\n * \n * @param keyToRemove Hash of the passkey to remove\n * @param signer Ethereum signer to pay gas\n * @returns Result with transaction hash and sequence for cross-chain sync\n */\n async removePasskey(\n keyToRemove: string,\n signer: any\n ): Promise<RemoveKeyResult> {\n const credential = this.passkey.getCredential();\n if (!credential) {\n throw new Error('No credential set. Call passkey.register() or passkey.setCredential() first.');\n }\n\n const evmClient = this.chain as any;\n if (typeof evmClient.removeKey !== 'function') {\n throw new Error('Backup passkey management not supported on this chain client');\n }\n\n // Get identity state\n const state = await evmClient.getIdentityState(credential.keyHash);\n if (state.keyCount <= 1) {\n throw new Error('Cannot remove the last passkey. At least one must remain.');\n }\n\n // Check if the key to remove is actually authorized\n const isAuthorized = await evmClient.isAuthorizedForIdentity(\n state.identity,\n keyToRemove\n );\n if (!isAuthorized) {\n throw new Error('The specified passkey is not authorized for this identity');\n }\n\n if (!state.identity || state.identity === ethers.ZeroHash) {\n throw new Error('Identity not registered. Call registerIdentity() first.');\n }\n\n // Nonce for key-management is stored on the *identity*\n const nonce = await this.chain.getNonce(state.identity);\n\n // Challenge = abi.encodePacked(\"VERIDEX_REMOVE_KEY\", identityKeyHash, keyToRemove, nonce)\n const packedChallenge = ethers.solidityPacked(\n ['string', 'bytes32', 'bytes32', 'uint256'],\n ['VERIDEX_REMOVE_KEY', state.identity, keyToRemove, nonce]\n );\n\n const signature = await this.passkey.sign(ethers.getBytes(packedChallenge));\n\n // Call Hub contract to remove key\n const { receipt, sequence } = await evmClient.removeKey(\n signature,\n credential.publicKeyX,\n credential.publicKeyY,\n keyToRemove,\n nonce,\n signer\n );\n\n // Get updated key count\n const updatedState = await evmClient.getIdentityState(credential.keyHash);\n\n return {\n transactionHash: receipt.hash,\n sequence,\n identity: state.identity,\n removedKeyHash: keyToRemove,\n keyCount: updatedState.keyCount,\n };\n }\n\n /**\n * Check if a specific passkey is authorized for the current identity\n * \n * @param keyHash Hash of the passkey to check\n * @returns True if authorized, false otherwise\n */\n async isPasskeyAuthorized(keyHash: string): Promise<boolean> {\n const credential = this.passkey.getCredential();\n if (!credential) {\n return false;\n }\n\n const evmClient = this.chain as any;\n if (typeof evmClient.getIdentityState !== 'function') {\n throw new Error('Identity management not supported on this chain client');\n }\n\n const state = await evmClient.getIdentityState(credential.keyHash);\n if (!state.identity || state.identity === ethers.ZeroHash) {\n return false;\n }\n\n return await evmClient.isAuthorizedForIdentity(state.identity, keyHash);\n }\n\n /**\n * Get the identity hash for the current passkey\n * This is the keyHash of the first/root passkey registered\n * \n * @returns Identity hash or null if no credential/identity\n */\n async getIdentity(): Promise<string | null> {\n const credential = this.passkey.getCredential();\n if (!credential) {\n return null;\n }\n\n const evmClient = this.chain as any;\n if (typeof evmClient.getIdentityForKey !== 'function') {\n // Fallback: return keyHash as identity (single-key mode)\n return credential.keyHash;\n }\n\n const identity = await evmClient.getIdentityForKey(credential.keyHash);\n if (identity === ethers.ZeroHash) {\n // Not registered yet, return current keyHash\n return credential.keyHash;\n }\n\n return identity;\n }\n\n getCredential(): PasskeyCredential | null {\n return this.passkey.getCredential();\n }\n\n setCredential(credential: PasskeyCredential): void {\n this.passkey.setCredential(credential);\n }\n\n hasCredential(): boolean {\n return this.passkey.getCredential() !== null;\n }\n\n clearCredential(): void {\n this.passkey.clearCredential();\n }\n}\n","import { ethers } from 'ethers';\n\nimport type { PasskeyCredential, TransferParams, ExecuteParams, BridgeParams } from '../core/types.js';\nimport { PasskeyManager } from '../core/PasskeyManager.js';\nimport { MAINNET_CHAINS, TESTNET_CHAINS } from '../constants.js';\nimport { buildGaslessChallenge, encodeBridgeAction, encodeExecuteAction, encodeTransferAction } from '../payload.js';\nimport { queryHubState } from '../queries/hubState.js';\n\nexport type AuthenticateAndPrepareParams = {\n credential: PasskeyCredential;\n action?: TransferParams | ExecuteParams | BridgeParams;\n /** Pre-encoded Hub action payload (hex string). If provided, `action` is ignored. */\n actionPayload?: string;\n targetChain: number;\n};\n\nexport type AuthenticateAndPrepareResult = {\n serializedTx: Uint8Array;\n queryProof: Uint8Array<ArrayBufferLike>;\n estimatedLatency: number;\n fallbackAvailable: boolean;\n};\n\nfunction resolveNetwork(): 'testnet' | 'mainnet' {\n const envCandidates = [\n (globalThis as any)?.process?.env?.NEXT_PUBLIC_VERIDEX_NETWORK,\n (globalThis as any)?.process?.env?.VERIDEX_NETWORK,\n (globalThis as any)?.process?.env?.NEXT_PUBLIC_WORMHOLE_NETWORK,\n (globalThis as any)?.process?.env?.WORMHOLE_NETWORK,\n ].filter(Boolean);\n\n const env = (envCandidates[0] as string | undefined)?.toLowerCase();\n if (env === 'mainnet' || env === 'testnet') return env;\n return 'testnet';\n}\n\nfunction getHubChainId(network: 'testnet' | 'mainnet'): number {\n return network === 'testnet' ? TESTNET_CHAINS.baseSepolia.wormholeChainId : MAINNET_CHAINS.base.wormholeChainId;\n}\n\nfunction getHubRpcUrl(network: 'testnet' | 'mainnet'): string {\n return network === 'testnet' ? TESTNET_CHAINS.baseSepolia.rpcUrl : MAINNET_CHAINS.base.rpcUrl;\n}\n\nfunction getHubAddress(network: 'testnet' | 'mainnet'): string {\n const hub = network === 'testnet'\n ? TESTNET_CHAINS.baseSepolia.contracts.hub\n : (MAINNET_CHAINS.base.contracts as any)?.hub;\n if (!hub) {\n throw new Error('Hub address missing in SDK constants');\n }\n return hub;\n}\n\nfunction encodeActionPayload(action: TransferParams | ExecuteParams | BridgeParams, targetChain: number): string {\n if ((action as TransferParams).token !== undefined && (action as TransferParams).recipient !== undefined) {\n const a = action as TransferParams;\n return encodeTransferAction(a.token, a.recipient, a.amount);\n }\n\n if ((action as ExecuteParams).target !== undefined && (action as ExecuteParams).data !== undefined) {\n const a = action as ExecuteParams;\n return encodeExecuteAction(a.target, a.value, a.data);\n }\n\n const a = action as BridgeParams;\n return encodeBridgeAction(a.token, a.amount, targetChain, a.recipient);\n}\n\nasync function fetchNonceViaRpc(userKeyHash: string, network: 'testnet' | 'mainnet'): Promise<bigint> {\n const rpcUrl = getHubRpcUrl(network);\n const hubAddress = getHubAddress(network);\n\n const provider = new ethers.JsonRpcProvider(rpcUrl);\n const hubIface = new ethers.Interface([\n 'function getNonce(bytes32 userKeyHash) external view returns (uint256)',\n 'function userNonces(bytes32 userKeyHash) external view returns (uint256)',\n ]);\n\n const calls: Array<() => Promise<bigint>> = [\n async () => {\n const data = hubIface.encodeFunctionData('getNonce', [userKeyHash]);\n const res = await provider.call({ to: hubAddress, data });\n const decoded = hubIface.decodeFunctionResult('getNonce', res);\n return decoded[0] as bigint;\n },\n async () => {\n const data = hubIface.encodeFunctionData('userNonces', [userKeyHash]);\n const res = await provider.call({ to: hubAddress, data });\n const decoded = hubIface.decodeFunctionResult('userNonces', res);\n return decoded[0] as bigint;\n },\n ];\n\n let lastErr: unknown;\n for (const fn of calls) {\n try {\n return await fn();\n } catch (e) {\n lastErr = e;\n }\n }\n\n throw lastErr instanceof Error ? lastErr : new Error(String(lastErr));\n}\n\nfunction toHex32(value: bigint): string {\n return '0x' + value.toString(16).padStart(64, '0');\n}\n\n/**\n * Client-first authentication preparation:\n * - user signs locally (FaceID/TouchID)\n * - client queries Wormhole Query Proxy for Guardian-attested nonce/state\n * - client returns a ready-to-submit relayer payload (JSON bytes)\n * - falls back to RPC nonce if Queries fails\n */\nexport async function authenticateAndPrepare(\n userParams: AuthenticateAndPrepareParams,\n apiKey: string\n): Promise<AuthenticateAndPrepareResult> {\n const network = resolveNetwork();\n const hubChainId = getHubChainId(network);\n\n const actionPayload = userParams.actionPayload ?? (userParams.action\n ? encodeActionPayload(userParams.action, userParams.targetChain)\n : undefined);\n\n if (!actionPayload) {\n throw new Error('Missing action payload: provide either actionPayload or action');\n }\n\n let nonce: bigint;\n let queryProof: Uint8Array<ArrayBufferLike> = new Uint8Array();\n let fallbackAvailable = true;\n\n const queryStart = Date.now();\n try {\n if (!apiKey) {\n throw new Error('Missing Query Proxy apiKey');\n }\n\n const state = await queryHubState(userParams.credential.keyHash, apiKey, { network, maxAge: 60 });\n\n if (!state.isRegistered) {\n // This is a hard failure: signing won’t help if the key isn’t registered.\n throw new Error('Passkey is not registered on Hub');\n }\n\n nonce = state.nonce;\n queryProof = state.proof;\n } catch {\n // Fallback: fetch nonce directly from hub RPC.\n nonce = await fetchNonceViaRpc(userParams.credential.keyHash, network);\n queryProof = new Uint8Array();\n }\n const queryLatencyMs = Date.now() - queryStart;\n\n const challenge = buildGaslessChallenge(userParams.targetChain, actionPayload, nonce, hubChainId);\n const passkey = new PasskeyManager();\n passkey.setCredential(userParams.credential);\n const signature = await passkey.sign(challenge);\n\n // Relayer request body (matches packages/relayer POST /api/v1/submit requirements)\n // Uses full WebAuthn data for authenticateAndDispatch\n const requestBody: any = {\n authenticatorData: signature.authenticatorData,\n clientDataJSON: signature.clientDataJSON,\n challengeIndex: signature.challengeIndex,\n typeIndex: signature.typeIndex,\n r: toHex32(signature.r),\n s: toHex32(signature.s),\n publicKeyX: toHex32(userParams.credential.publicKeyX),\n publicKeyY: toHex32(userParams.credential.publicKeyY),\n targetChain: userParams.targetChain,\n actionPayload,\n nonce: Number(nonce),\n };\n\n // Include proof as an optional field for callers to forward/store (relayer ignores extra fields).\n if (queryProof.length) {\n requestBody.queryProof = ethers.hexlify(queryProof);\n }\n\n const serializedTx = new TextEncoder().encode(JSON.stringify(requestBody));\n\n // Heuristic: Queries is sub-second; RPC nonce lookup is slower.\n const estimatedLatency = queryProof.length ? Math.max(250, queryLatencyMs) : Math.max(800, queryLatencyMs);\n\n return {\n serializedTx,\n queryProof,\n estimatedLatency,\n fallbackAvailable,\n };\n}\n","import axios, { AxiosError } from 'axios';\nimport { Buffer } from 'buffer';\nimport { ethers } from 'ethers';\nimport {\n EthCallQueryRequest,\n EthCallQueryResponse,\n PerChainQueryRequest,\n QueryRequest,\n QueryResponse,\n hexToUint8Array,\n isValidHexString,\n} from '@wormhole-foundation/wormhole-query-sdk';\n\nimport { MAINNET_CHAINS, TESTNET_CHAINS } from '../constants.js';\nimport { WORMHOLE_QUERY_PROXY_URLS } from './constants.js';\n\nexport type QueryHubStateNetwork = 'testnet' | 'mainnet';\n\nexport type QueryHubStateOptions = {\n /** Max response age in seconds (default: 60). */\n maxAge?: number;\n network?: QueryHubStateNetwork;\n /** Maximum attempts including the first try (default: 4). */\n maxAttempts?: number;\n};\n\nexport type HubStateResult = {\n nonce: bigint;\n isRegistered: boolean;\n blockTime: number;\n proof: Uint8Array;\n /** Last action hash (Issue #9/#10 - for action-hash binding) */\n lastActionHash?: string;\n};\n\nexport type QueryHubStateErrorCode =\n | 'INVALID_ARGUMENT'\n | 'UNSUPPORTED_NETWORK'\n | 'MISSING_HUB_ADDRESS'\n | 'PROXY_HTTP_ERROR'\n | 'PROXY_RESPONSE_INVALID'\n | 'ATTESTATION_STALE'\n | 'QUERY_RESPONSE_INVALID';\n\nexport class QueryHubStateError extends Error {\n code: QueryHubStateErrorCode;\n cause?: unknown;\n\n constructor(code: QueryHubStateErrorCode, message: string, cause?: unknown) {\n super(message);\n this.name = 'QueryHubStateError';\n this.code = code;\n this.cause = cause;\n }\n}\n\nfunction resolveNetwork(options?: QueryHubStateOptions): QueryHubStateNetwork {\n if (options?.network) return options.network;\n\n const envCandidates = [\n (globalThis as any)?.process?.env?.NEXT_PUBLIC_VERIDEX_NETWORK,\n (globalThis as any)?.process?.env?.VERIDEX_NETWORK,\n (globalThis as any)?.process?.env?.NEXT_PUBLIC_WORMHOLE_NETWORK,\n (globalThis as any)?.process?.env?.WORMHOLE_NETWORK,\n ].filter(Boolean);\n\n const env = (envCandidates[0] as string | undefined)?.toLowerCase();\n if (env === 'mainnet' || env === 'testnet') return env;\n\n // Default to testnet to support Base Sepolia out-of-the-box.\n return 'testnet';\n}\n\nfunction concatBytes(parts: Uint8Array[]): Uint8Array {\n const total = parts.reduce((sum, p) => sum + p.length, 0);\n const out = new Uint8Array(total);\n let offset = 0;\n for (const p of parts) {\n out.set(p, offset);\n offset += p.length;\n }\n return out;\n}\n\nfunction signaturesToProofBytes(signatures: string[]): Uint8Array {\n const chunks: Uint8Array[] = [];\n\n for (const sig of signatures) {\n if (typeof sig !== 'string' || sig.length !== 132 || !/^[0-9a-fA-F]+$/.test(sig)) {\n throw new QueryHubStateError(\n 'PROXY_RESPONSE_INVALID',\n `Invalid guardian signature format (expected 132 hex chars): ${String(sig)}`\n );\n }\n // Avoid Node Buffer-backed Uint8Array (can surface as SharedArrayBuffer in DTS types).\n chunks.push(hexToUint8Array(`0x${sig}`));\n }\n\n return concatBytes(chunks);\n}\n\nfunction decodeQueryBytes(bytes: string): Uint8Array {\n if (typeof bytes !== 'string' || bytes.length === 0) {\n throw new QueryHubStateError('PROXY_RESPONSE_INVALID', 'Missing query response bytes');\n }\n\n // Query Proxy commonly returns a 0x-prefixed hex string.\n if (isValidHexString(bytes)) {\n return hexToUint8Array(bytes);\n }\n\n // Fallback: attempt base64 decoding.\n try {\n if (typeof atob === 'function') {\n const raw = atob(bytes);\n const arr = new Uint8Array(raw.length);\n for (let i = 0; i < raw.length; i++) arr[i] = raw.charCodeAt(i);\n return arr;\n }\n } catch {\n // ignore\n }\n\n try {\n return new Uint8Array(Buffer.from(bytes, 'base64'));\n } catch (cause) {\n throw new QueryHubStateError('PROXY_RESPONSE_INVALID', 'Unrecognized query response bytes encoding', cause);\n }\n}\n\nfunction sleep(ms: number): Promise<void> {\n return new Promise((resolve) => setTimeout(resolve, ms));\n}\n\nasync function withExponentialBackoff<T>(\n fn: () => Promise<T>,\n maxAttempts: number\n): Promise<T> {\n let attempt = 0;\n let lastError: unknown;\n\n while (attempt < maxAttempts) {\n try {\n return await fn();\n } catch (err) {\n lastError = err;\n attempt += 1;\n if (attempt >= maxAttempts) break;\n\n const baseMs = 250;\n const backoffMs = Math.min(5_000, baseMs * 2 ** (attempt - 1));\n const jitterMs = Math.floor(Math.random() * 100);\n await sleep(backoffMs + jitterMs);\n }\n }\n\n throw lastError;\n}\n\nfunction getHubConfig(network: QueryHubStateNetwork): {\n wormholeChainId: number;\n hubAddress: string;\n endpoint: string;\n rpcUrl: string;\n} {\n if (network === 'testnet') {\n const baseSepolia = TESTNET_CHAINS.baseSepolia;\n if (!baseSepolia?.contracts?.hub) {\n throw new QueryHubStateError('MISSING_HUB_ADDRESS', 'Missing Base Sepolia hub address in SDK constants');\n }\n\n return {\n wormholeChainId: baseSepolia.wormholeChainId,\n hubAddress: baseSepolia.contracts.hub,\n endpoint: WORMHOLE_QUERY_PROXY_URLS.testnet,\n rpcUrl: baseSepolia.rpcUrl,\n };\n }\n\n if (network === 'mainnet') {\n const base = MAINNET_CHAINS.base;\n const hubAddress = (base?.contracts as any)?.hub as string | undefined;\n\n if (!hubAddress) {\n throw new QueryHubStateError(\n 'MISSING_HUB_ADDRESS',\n 'Missing mainnet hub address in SDK constants (MAINNET_CHAINS.base.contracts.hub)'\n );\n }\n\n return {\n wormholeChainId: base.wormholeChainId,\n hubAddress,\n endpoint: WORMHOLE_QUERY_PROXY_URLS.mainnet,\n rpcUrl: base.rpcUrl,\n };\n }\n\n throw new QueryHubStateError('UNSUPPORTED_NETWORK', `Unsupported network: ${network}`);\n}\n\nfunction encodeHubCalls(hubAddress: string, userKeyHash: string): { to: string; data: string }[] {\n // Support both the spec name and known on-chain variants.\n const nonceAbiCandidates = [\n 'function getUserNonce(bytes32 userKeyHash) view returns (uint256)',\n 'function userNonces(bytes32 userKeyHash) view returns (uint256)',\n 'function getNonceByHash(bytes32 userKeyHash) view returns (uint256)',\n ];\n\n const registeredAbiCandidates = [\n 'function registeredKeys(bytes32 userKeyHash) view returns (bool)',\n 'function isKeyRegisteredByHash(bytes32 userKeyHash) view returns (bool)',\n ];\n\n // Issue #9/#10: Add getUserLastActionHash for action-hash binding\n const actionHashAbiCandidates = [\n 'function getUserLastActionHash(bytes32 userKeyHash) view returns (bytes32)',\n 'function userLastActionHash(bytes32 userKeyHash) view returns (bytes32)',\n ];\n\n // We encode *all* candidates; the proxy will execute each call, and we decode the first successful one.\n // This makes the client resilient to Hub ABI differences across deployments.\n const iface = new ethers.Interface([\n ...nonceAbiCandidates,\n ...registeredAbiCandidates,\n ...actionHashAbiCandidates,\n ]);\n\n const nonceFnNames = ['getUserNonce', 'userNonces', 'getNonceByHash'] as const;\n const regFnNames = ['registeredKeys', 'isKeyRegisteredByHash'] as const;\n const actionHashFnNames = ['getUserLastActionHash', 'userLastActionHash'] as const;\n\n return [\n ...nonceFnNames.map((fn) => ({\n to: hubAddress,\n data: iface.encodeFunctionData(fn, [userKeyHash]),\n })),\n ...regFnNames.map((fn) => ({\n to: hubAddress,\n data: iface.encodeFunctionData(fn, [userKeyHash]),\n })),\n ...actionHashFnNames.map((fn) => ({\n to: hubAddress,\n data: iface.encodeFunctionData(fn, [userKeyHash]),\n })),\n ];\n}\n\nfunction decodeFirstNonce(results: string[]): bigint {\n const candidates = [\n 'function getUserNonce(bytes32 userKeyHash) view returns (uint256)',\n 'function userNonces(bytes32 userKeyHash) view returns (uint256)',\n 'function getNonceByHash(bytes32 userKeyHash) view returns (uint256)',\n ];\n const iface = new ethers.Interface(candidates);\n const fnNames = ['getUserNonce', 'userNonces', 'getNonceByHash'] as const;\n\n for (let idx = 0; idx < fnNames.length; idx++) {\n const fnName = fnNames[idx];\n try {\n const data = results[idx];\n if (!data || data === '0x') continue;\n const decoded = iface.decodeFunctionResult(fnName, data);\n return decoded[0] as bigint;\n } catch {\n // keep trying\n }\n }\n\n throw new QueryHubStateError('QUERY_RESPONSE_INVALID', 'Unable to decode user nonce from query response');\n}\n\nfunction decodeFirstIsRegistered(results: string[]): boolean {\n const nonceCandidateCount = 3;\n const candidates = [\n 'function registeredKeys(bytes32 userKeyHash) view returns (bool)',\n 'function isKeyRegisteredByHash(bytes32 userKeyHash) view returns (bool)',\n ];\n const iface = new ethers.Interface(candidates);\n const fnNames = ['registeredKeys', 'isKeyRegisteredByHash'] as const;\n\n for (let i = 0; i < fnNames.length; i++) {\n const fnName = fnNames[i];\n try {\n const data = results[nonceCandidateCount + i];\n if (!data || data === '0x') continue;\n const decoded = iface.decodeFunctionResult(fnName, data);\n return Boolean(decoded[0]);\n } catch {\n // keep trying\n }\n }\n\n // If the hub deployment doesn’t support registration, treat as false.\n return false;\n}\n\n/** * Decode last action hash from query results (Issue #9/#10)\n * Returns zero hash if not available (backwards compatibility)\n */\nfunction decodeLastActionHash(results: string[]): string {\n const nonceCandidateCount = 3;\n const registeredCandidateCount = 2;\n const actionHashOffset = nonceCandidateCount + registeredCandidateCount;\n\n const candidates = [\n 'function getUserLastActionHash(bytes32 userKeyHash) view returns (bytes32)',\n 'function userLastActionHash(bytes32 userKeyHash) view returns (bytes32)',\n ];\n const iface = new ethers.Interface(candidates);\n const fnNames = ['getUserLastActionHash', 'userLastActionHash'] as const;\n\n for (let i = 0; i < fnNames.length; i++) {\n const fnName = fnNames[i];\n try {\n const data = results[actionHashOffset + i];\n if (!data || data === '0x') continue;\n const decoded = iface.decodeFunctionResult(fnName, data);\n return decoded[0] as string;\n } catch {\n // keep trying\n }\n }\n\n // Backwards compatibility: return zero hash if not available\n return ethers.ZeroHash;\n}\n\n/** * Fetch Guardian-attested Hub state directly from the Wormhole Query Proxy.\n *\n * Client-side only: this avoids relayer API costs and produces a Guardian-signed proof\n * that can be forwarded to the relayer for on-chain verification/submission.\n */\nexport async function queryHubState(\n userKeyHash: string,\n apiKey: string,\n options?: QueryHubStateOptions\n): Promise<HubStateResult> {\n if (typeof userKeyHash !== 'string' || userKeyHash.length === 0) {\n throw new QueryHubStateError('INVALID_ARGUMENT', 'userKeyHash is required');\n }\n if (!isValidHexString(userKeyHash) || hexToUint8Array(userKeyHash).length !== 32) {\n throw new QueryHubStateError('INVALID_ARGUMENT', 'userKeyHash must be a 32-byte hex string');\n }\n if (typeof apiKey !== 'string' || apiKey.length === 0) {\n throw new QueryHubStateError('INVALID_ARGUMENT', 'apiKey is required');\n }\n\n const network = resolveNetwork(options);\n const maxAgeSeconds = options?.maxAge ?? 60;\n const maxAttempts = options?.maxAttempts ?? 4;\n\n const { wormholeChainId, hubAddress, endpoint, rpcUrl } = getHubConfig(network);\n\n const provider = new ethers.JsonRpcProvider(rpcUrl);\n\n const callData = encodeHubCalls(hubAddress, userKeyHash);\n\n const doFetch = async () => {\n try {\n const latestBlock = await provider.getBlockNumber();\n const blockTag = Math.max(0, latestBlock - 2);\n\n const request = new QueryRequest(Date.now() & 0xffffffff, [\n new PerChainQueryRequest(wormholeChainId, new EthCallQueryRequest(blockTag, callData)),\n ]);\n\n // Wormhole Query Proxy expects raw hex WITHOUT 0x prefix\n const requestHex = Buffer.from(request.serialize()).toString('hex');\n\n const response = await axios.post(\n endpoint,\n { bytes: requestHex },\n {\n headers: {\n 'X-API-Key': apiKey,\n 'Content-Type': 'application/json',\n },\n timeout: 10_000,\n }\n );\n\n const data = response.data as any;\n const signatures = data?.signatures as string[] | undefined;\n const bytes = data?.bytes as string | undefined;\n\n if (!Array.isArray(signatures) || typeof bytes !== 'string') {\n throw new QueryHubStateError('PROXY_RESPONSE_INVALID', 'Query Proxy response missing signatures/bytes');\n }\n\n const proof = signaturesToProofBytes(signatures);\n const queryBytes = decodeQueryBytes(bytes);\n const parsed = QueryResponse.from(queryBytes);\n\n const perChain = parsed.responses.find((r) => r.chainId === wormholeChainId);\n if (!perChain) {\n throw new QueryHubStateError('QUERY_RESPONSE_INVALID', 'Missing per-chain response for hub chain');\n }\n\n // The SDK provides a parser for the chain-specific response.\n const chainResp = EthCallQueryResponse.from(perChain.response.serialize());\n const blockTime = Number(chainResp.blockTime);\n\n const nowSeconds = Math.floor(Date.now() / 1000);\n if (nowSeconds - blockTime > maxAgeSeconds) {\n throw new QueryHubStateError(\n 'ATTESTATION_STALE',\n `Guardian attestation is stale (blockTime=${blockTime}, now=${nowSeconds}, maxAge=${maxAgeSeconds}s)`\n );\n }\n\n const nonce = decodeFirstNonce(chainResp.results);\n const isRegistered = decodeFirstIsRegistered(chainResp.results);\n const lastActionHash = decodeLastActionHash(chainResp.results);\n\n return {\n nonce,\n isRegistered,\n blockTime,\n proof,\n lastActionHash,\n } satisfies HubStateResult;\n } catch (err) {\n if (err instanceof QueryHubStateError) throw err;\n if (axios.isAxiosError(err)) {\n const ax = err as AxiosError;\n const status = ax.response?.status;\n const statusText = ax.response?.statusText;\n const details = typeof ax.response?.data === 'string' ? ax.response?.data : undefined;\n\n throw new QueryHubStateError(\n 'PROXY_HTTP_ERROR',\n `Query Proxy request failed${status ? ` (${status} ${statusText ?? ''})` : ''}${details ? `: ${details}` : ''}`,\n err\n );\n }\n\n throw new QueryHubStateError('PROXY_HTTP_ERROR', 'Query Proxy request failed', err);\n }\n };\n\n return await withExponentialBackoff(doFetch, maxAttempts);\n}\n","export const WORMHOLE_QUERY_PROXY_URLS = {\n mainnet: 'https://query.wormhole.com/v1/query',\n testnet: 'https://testnet.query.wormhole.com/v1/query',\n} as const;\n\n/**\n * Wormhole Query Proxy rate limit: 6 queries per second.\n * SDK callers should throttle requests accordingly.\n */\nexport const WORMHOLE_QUERY_RATE_LIMIT_PER_SECOND = 6;\n\n/**\n * Convenience set of Wormhole chain IDs commonly supported by Queries.\n * This is not an exhaustive list of all Wormhole chains.\n */\nexport const WORMHOLE_QUERY_CHAIN_IDS = {\n ETHEREUM: 2,\n POLYGON: 5,\n ARBITRUM: 23,\n OPTIMISM: 24,\n BASE: 30,\n} as const;\n","import axios, { AxiosError } from 'axios';\nimport { Buffer } from 'buffer';\nimport { ethers } from 'ethers';\nimport { PublicKey } from '@solana/web3.js';\nimport {\n EthCallQueryRequest,\n EthCallQueryResponse,\n PerChainQueryRequest,\n QueryRequest,\n QueryResponse,\n SolanaAccountQueryRequest,\n SolanaAccountQueryResponse,\n hexToUint8Array,\n isValidHexString,\n} from '@wormhole-foundation/wormhole-query-sdk';\n\nimport { MAINNET_CHAINS, TESTNET_CHAINS } from '../constants.js';\nimport { WalletManager } from '../core/WalletManager.js';\nimport { getAllTokens, isNativeToken } from '../constants/tokens.js';\nimport { WORMHOLE_QUERY_PROXY_URLS } from './constants.js';\n\nexport type QueryPortfolioNetwork = 'testnet' | 'mainnet';\n\nexport type QueryPortfolioOptions = {\n /** Max response age in seconds (default: 60). */\n maxAge?: number;\n network?: QueryPortfolioNetwork;\n /** Maximum attempts including the first try (default: 4). */\n maxAttempts?: number;\n /** Cache TTL in ms (default: 30_000). */\n cacheTtlMs?: number;\n /** Request timeout in ms (default: 15_000 for testnet, 10_000 for mainnet). */\n timeout?: number;\n /** Override Query Proxy endpoint. */\n endpoint?: string;\n /** Override per-chain RPC URLs used for block tag lookups. */\n rpcUrls?: Record<number, string>;\n /** Override derived vault addresses for specific Wormhole chain IDs. */\n vaultAddresses?: Record<number, string>;\n /** Override token lists (ERC20 only) for specific Wormhole chain IDs. */\n evmTokenAddresses?: Record<number, string[]>;\n /** Additional Solana accounts to include in the Solana account query (base58). */\n solanaAccounts?: string[];\n /** Optional USD prices by symbol/address for aggregation (e.g. { USDC: 1 }). */\n pricesUsd?: Record<string, number>;\n};\n\nexport type PortfolioBalance = {\n assetId: string;\n amount: bigint;\n decimals?: number;\n symbol?: string;\n usdValue?: number;\n};\n\nexport type PortfolioChainErrorCode =\n | 'UNSUPPORTED_CHAIN'\n | 'MISSING_VAULT'\n | 'MISSING_TOKENS'\n | 'ATTESTATION_STALE'\n | 'DECODE_ERROR';\n\nexport type PortfolioChainResult = {\n wormholeChainId: number;\n chainName?: string;\n vaultAddress?: string;\n blockTime?: number;\n balances: PortfolioBalance[];\n error?: {\n code: PortfolioChainErrorCode;\n message: string;\n };\n};\n\nexport type PortfolioResult = {\n proof: Uint8Array;\n totalUsd?: number;\n chains: PortfolioChainResult[];\n};\n\nexport type QueryPortfolioErrorCode =\n | 'INVALID_ARGUMENT'\n | 'NETWORK_ERROR'\n | 'PROXY_HTTP_ERROR'\n | 'PROXY_RESPONSE_INVALID'\n | 'QUERY_RESPONSE_INVALID';\n\nexport class QueryPortfolioError extends Error {\n code: QueryPortfolioErrorCode;\n cause?: unknown;\n\n constructor(code: QueryPortfolioErrorCode, message: string, cause?: unknown) {\n super(message);\n this.name = 'QueryPortfolioError';\n this.code = code;\n this.cause = cause;\n }\n}\n\ntype CacheEntry = { expiresAt: number; value: PortfolioResult };\nconst PORTFOLIO_CACHE = new Map<string, CacheEntry>();\n\nfunction resolveNetwork(options?: QueryPortfolioOptions): QueryPortfolioNetwork {\n if (options?.network) return options.network;\n\n const envCandidates = [\n (globalThis as any)?.process?.env?.NEXT_PUBLIC_VERIDEX_NETWORK,\n (globalThis as any)?.process?.env?.VERIDEX_NETWORK,\n (globalThis as any)?.process?.env?.NEXT_PUBLIC_WORMHOLE_NETWORK,\n (globalThis as any)?.process?.env?.WORMHOLE_NETWORK,\n ].filter(Boolean);\n\n const env = (envCandidates[0] as string | undefined)?.toLowerCase();\n if (env === 'mainnet' || env === 'testnet') return env;\n\n return 'testnet';\n}\n\nfunction concatBytes(parts: Uint8Array[]): Uint8Array {\n const total = parts.reduce((sum, p) => sum + p.length, 0);\n const out = new Uint8Array(total);\n let offset = 0;\n for (const p of parts) {\n out.set(p, offset);\n offset += p.length;\n }\n return out;\n}\n\nfunction signaturesToProofBytes(signatures: string[]): Uint8Array {\n const chunks: Uint8Array[] = [];\n\n for (const sig of signatures) {\n if (typeof sig !== 'string' || sig.length !== 132 || !/^[0-9a-fA-F]+$/.test(sig)) {\n throw new QueryPortfolioError(\n 'PROXY_RESPONSE_INVALID',\n `Invalid guardian signature format (expected 132 hex chars): ${String(sig)}`\n );\n }\n // Avoid Node Buffer-backed Uint8Array (can surface as SharedArrayBuffer in DTS types).\n chunks.push(hexToUint8Array(`0x${sig}`));\n }\n\n return concatBytes(chunks);\n}\n\nfunction decodeQueryBytes(bytes: string): Uint8Array {\n if (typeof bytes !== 'string' || bytes.length === 0) {\n throw new QueryPortfolioError('PROXY_RESPONSE_INVALID', 'Missing query response bytes');\n }\n\n if (isValidHexString(bytes)) {\n return hexToUint8Array(bytes);\n }\n\n try {\n if (typeof atob === 'function') {\n const raw = atob(bytes);\n const arr = new Uint8Array(raw.length);\n for (let i = 0; i < raw.length; i++) arr[i] = raw.charCodeAt(i);\n return arr;\n }\n } catch {\n // ignore\n }\n\n try {\n return new Uint8Array(Buffer.from(bytes, 'base64'));\n } catch (cause) {\n throw new QueryPortfolioError('PROXY_RESPONSE_INVALID', 'Unrecognized query response bytes encoding', cause);\n }\n}\n\nfunction sleep(ms: number): Promise<void> {\n return new Promise((resolve) => setTimeout(resolve, ms));\n}\n\n/**\n * Simple rate limiter for Wormhole Query Proxy (6 requests/second limit).\n * Queues requests and releases them at the allowed rate.\n */\nconst rateLimiter = {\n queue: [] as Array<() => void>,\n lastRequest: 0,\n minInterval: 170, // ~6 req/s with buffer\n \n async acquire(): Promise<void> {\n return new Promise((resolve) => {\n const tryAcquire = () => {\n const now = Date.now();\n const elapsed = now - rateLimiter.lastRequest;\n if (elapsed >= rateLimiter.minInterval) {\n rateLimiter.lastRequest = now;\n resolve();\n } else {\n setTimeout(tryAcquire, rateLimiter.minInterval - elapsed);\n }\n };\n tryAcquire();\n });\n }\n};\n\nasync function withExponentialBackoff<T>(fn: () => Promise<T>, maxAttempts: number): Promise<T> {\n let attempt = 0;\n let lastError: unknown;\n\n while (attempt < maxAttempts) {\n try {\n return await fn();\n } catch (err) {\n lastError = err;\n attempt += 1;\n if (attempt >= maxAttempts) break;\n\n const baseMs = 250;\n const backoffMs = Math.min(5_000, baseMs * 2 ** (attempt - 1));\n const jitterMs = Math.floor(Math.random() * 100);\n await sleep(backoffMs + jitterMs);\n }\n }\n\n throw lastError;\n}\n\nfunction getChainConfigs(network: QueryPortfolioNetwork) {\n return network === 'testnet' ? TESTNET_CHAINS : MAINNET_CHAINS;\n}\n\nfunction getProxyEndpoint(network: QueryPortfolioNetwork, options?: QueryPortfolioOptions): string {\n if (options?.endpoint) return options.endpoint;\n return network === 'testnet' ? WORMHOLE_QUERY_PROXY_URLS.testnet : WORMHOLE_QUERY_PROXY_URLS.mainnet;\n}\n\nfunction getDefaultPortfolioChains(network: QueryPortfolioNetwork): number[] {\n // Include hub (Base Sepolia 10004) and spoke chains\n return network === 'testnet' ? [10004, 10005, 10003, 1] : [30, 24, 23, 1];\n}\n\nfunction normalizeHex32(hex: string): Uint8Array {\n if (typeof hex !== 'string' || !/^0x[0-9a-fA-F]{64}$/.test(hex)) {\n throw new QueryPortfolioError('INVALID_ARGUMENT', `Invalid userKeyHash (expected 0x + 32 bytes hex): ${hex}`);\n }\n return new Uint8Array(Buffer.from(hex.slice(2), 'hex'));\n}\n\nfunction deriveSolanaVaultAddress(programIdBase58: string, userKeyHash: string): string {\n const programId = new PublicKey(programIdBase58);\n const keyHashBytes = normalizeHex32(userKeyHash);\n const [vaultPda] = PublicKey.findProgramAddressSync([Buffer.from('vault'), Buffer.from(keyHashBytes)], programId);\n return vaultPda.toBase58();\n}\n\nfunction makeCacheKey(userKeyHash: string, apiKey: string, options: QueryPortfolioOptions | undefined, chainIds: number[]) {\n // Do not include apiKey in the cache key; it should not affect the data.\n const payload = {\n userKeyHash,\n network: resolveNetwork(options),\n chainIds: [...chainIds].sort((a, b) => a - b),\n vaultAddresses: options?.vaultAddresses ?? null,\n evmTokenAddresses: options?.evmTokenAddresses ?? null,\n solanaAccounts: options?.solanaAccounts ?? null,\n endpoint: options?.endpoint ?? null,\n };\n\n void apiKey;\n return JSON.stringify(payload);\n}\n\nfunction safeNumberFromBigint(b: bigint): number {\n const n = Number(b);\n return Number.isFinite(n) ? n : 0;\n}\n\nfunction priceLookup(pricesUsd: Record<string, number> | undefined, symbol?: string, assetId?: string): number | undefined {\n if (!pricesUsd) return undefined;\n if (symbol && pricesUsd[symbol] != null) return pricesUsd[symbol];\n if (assetId && pricesUsd[assetId] != null) return pricesUsd[assetId];\n return undefined;\n}\n\nfunction sumUsd(balances: PortfolioBalance[], pricesUsd?: Record<string, number>): number | undefined {\n let total = 0;\n let any = false;\n\n for (const b of balances) {\n const p = priceLookup(pricesUsd, b.symbol, b.assetId);\n if (p == null) continue;\n if (b.decimals == null) continue;\n\n const denom = 10 ** b.decimals;\n const amount = Number(b.amount) / denom;\n if (!Number.isFinite(amount)) continue;\n total += amount * p;\n any = true;\n }\n\n return any ? total : undefined;\n}\n\nasync function getRecentBlockTag(rpcUrl: string): Promise<number> {\n const provider = new ethers.JsonRpcProvider(rpcUrl);\n const latest = await provider.getBlockNumber();\n return Math.max(0, latest - 2);\n}\n\nfunction encodeErc20BalanceCalls(vaultAddress: string, tokenAddresses: string[]): { to: string; data: string }[] {\n const iface = new ethers.Interface(['function balanceOf(address owner) view returns (uint256)']);\n return tokenAddresses.map((token) => ({\n to: token,\n data: iface.encodeFunctionData('balanceOf', [vaultAddress]),\n }));\n}\n\nfunction decodeErc20Balances(results: string[], tokenAddresses: string[]): bigint[] {\n const iface = new ethers.Interface(['function balanceOf(address owner) view returns (uint256)']);\n const out: bigint[] = [];\n for (let i = 0; i < tokenAddresses.length; i++) {\n const data = results[i];\n if (!data || data === '0x') {\n out.push(0n);\n continue;\n }\n const decoded = iface.decodeFunctionResult('balanceOf', data);\n out.push(decoded[0] as bigint);\n }\n return out;\n}\n\n/**\n * Fetch Guardian-attested vault balances across multiple chains in one Query Proxy request.\n *\n * Notes:\n * - EVM balances are ERC20-only via `eth_call` (native ETH is not queryable via this query type).\n * - Solana balance uses lamports of the Veridex vault PDA (plus optional extra accounts).\n * - Aptos is included only if/when Wormhole Queries adds Aptos query types (currently returned as unsupported).\n */\nexport async function queryPortfolio(\n userKeyHash: string,\n apiKey: string,\n options?: QueryPortfolioOptions\n): Promise<PortfolioResult> {\n const network = resolveNetwork(options);\n const maxAgeSeconds = options?.maxAge ?? 60;\n const maxAttempts = options?.maxAttempts ?? 4;\n const cacheTtlMs = options?.cacheTtlMs ?? 30_000;\n const endpoint = getProxyEndpoint(network, options);\n\n const chainIds = options?.rpcUrls ? Object.keys(options.rpcUrls).map(Number) : undefined;\n void chainIds;\n\n const requestedChains = options?.vaultAddresses\n ? Object.keys(options.vaultAddresses).map(Number)\n : undefined;\n\n const defaultChains = getDefaultPortfolioChains(network);\n const wormholeChainIds = options?.evmTokenAddresses\n ? Array.from(new Set([...defaultChains, ...Object.keys(options.evmTokenAddresses).map(Number)]))\n : defaultChains;\n\n // If the caller provided explicit vault overrides, include those chain IDs even if not in defaults.\n const finalChainIds = requestedChains\n ? Array.from(new Set([...wormholeChainIds, ...requestedChains]))\n : wormholeChainIds;\n\n if (!apiKey || typeof apiKey !== 'string') {\n throw new QueryPortfolioError('INVALID_ARGUMENT', 'Missing Query Proxy apiKey');\n }\n\n const cacheKey = makeCacheKey(userKeyHash, apiKey, options, finalChainIds);\n const cached = PORTFOLIO_CACHE.get(cacheKey);\n if (cached && cached.expiresAt > Date.now()) {\n return cached.value;\n }\n\n const chains = getChainConfigs(network);\n const walletManager = new WalletManager({ cacheAddresses: true, persistToStorage: false });\n\n const pricesUsd: Record<string, number> | undefined = {\n USDC: 1,\n ...(options?.pricesUsd ?? {}),\n };\n\n const doFetch = async (): Promise<PortfolioResult> => {\n try {\n const perChainRequests: PerChainQueryRequest[] = [];\n const chainMeta: Record<number, { vaultAddress?: string; chainName?: string; kind: 'evm' | 'solana' | 'unsupported' }> = {};\n\n // Precompute any EVM block tags in parallel to keep total latency down.\n const evmChainIds = finalChainIds.filter((id) => {\n const cfg = Object.values(chains).find((c) => c.wormholeChainId === id);\n return cfg?.isEvm;\n });\n\n const blockTagsByChainId = new Map<number, number>();\n await Promise.all(\n evmChainIds.map(async (wormholeChainId) => {\n const cfg = Object.values(chains).find((c) => c.wormholeChainId === wormholeChainId);\n if (!cfg) return;\n const rpcUrl = options?.rpcUrls?.[wormholeChainId] ?? cfg.rpcUrl;\n const blockTag = await getRecentBlockTag(rpcUrl);\n blockTagsByChainId.set(wormholeChainId, blockTag);\n })\n );\n\n for (const wormholeChainId of finalChainIds) {\n const cfg = Object.values(chains).find((c) => c.wormholeChainId === wormholeChainId);\n\n if (wormholeChainId === 22) {\n chainMeta[wormholeChainId] = { kind: 'unsupported', chainName: cfg?.name };\n continue;\n }\n\n if (!cfg) {\n chainMeta[wormholeChainId] = { kind: 'unsupported' };\n continue;\n }\n\n if (cfg.isEvm) {\n const vaultAddress = options?.vaultAddresses?.[wormholeChainId]\n ?? (cfg.contracts.vaultFactory && cfg.contracts.vaultImplementation\n ? walletManager.computeVaultAddress(userKeyHash, cfg.contracts.vaultFactory, cfg.contracts.vaultImplementation)\n : undefined);\n\n chainMeta[wormholeChainId] = { kind: 'evm', vaultAddress, chainName: cfg.name };\n\n if (!vaultAddress) {\n continue;\n }\n\n const tokenAddresses = options?.evmTokenAddresses?.[wormholeChainId]\n ?? getAllTokens(wormholeChainId).filter((t) => !isNativeToken(t.address)).map((t) => t.address);\n\n if (!tokenAddresses.length) {\n continue;\n }\n\n const blockTag = blockTagsByChainId.get(wormholeChainId);\n if (blockTag == null) {\n continue;\n }\n\n const calls = encodeErc20BalanceCalls(vaultAddress, tokenAddresses);\n perChainRequests.push(new PerChainQueryRequest(wormholeChainId, new EthCallQueryRequest(blockTag, calls)));\n continue;\n }\n\n // Solana\n if (wormholeChainId === 1) {\n const programId = options?.vaultAddresses?.[wormholeChainId] ?? cfg.contracts.hub;\n chainMeta[wormholeChainId] = { kind: 'solana', chainName: cfg.name };\n\n if (!programId) {\n continue;\n }\n\n const vaultAddress = deriveSolanaVaultAddress(programId, userKeyHash);\n chainMeta[wormholeChainId] = { kind: 'solana', chainName: cfg.name, vaultAddress };\n\n const accounts = [vaultAddress, ...(options?.solanaAccounts ?? [])];\n perChainRequests.push(\n new PerChainQueryRequest(\n wormholeChainId,\n new SolanaAccountQueryRequest('finalized', accounts, undefined, 0n, 0n)\n )\n );\n continue;\n }\n\n chainMeta[wormholeChainId] = { kind: 'unsupported', chainName: cfg.name };\n }\n\n if (perChainRequests.length > 255) {\n throw new QueryPortfolioError(\n 'INVALID_ARGUMENT',\n `Too many per-chain requests (${perChainRequests.length}); max is 255 per Query Proxy request`\n );\n }\n\n // If no per-chain requests were built (e.g., missing vaults or tokens), return early with empty results\n if (perChainRequests.length === 0) {\n const chainsOut: PortfolioChainResult[] = finalChainIds.map((wormholeChainId) => {\n const meta = chainMeta[wormholeChainId] ?? { kind: 'unsupported' as const };\n return {\n wormholeChainId,\n chainName: meta.chainName,\n vaultAddress: meta.vaultAddress,\n balances: [],\n error: { \n code: 'MISSING_VAULT' as const, \n message: 'Unable to build query: missing vault address or no tokens configured' \n },\n };\n });\n return { proof: new Uint8Array(), totalUsd: 0, chains: chainsOut };\n }\n\n const request = new QueryRequest(Date.now() & 0xffffffff, perChainRequests);\n // Wormhole Query Proxy expects raw hex WITHOUT 0x prefix\n const requestHex = Buffer.from(request.serialize()).toString('hex');\n\n // Respect rate limit before making request\n await rateLimiter.acquire();\n\n let response;\n try {\n console.log('[queryPortfolio] Sending request to:', endpoint);\n console.log('[queryPortfolio] Request bytes length:', requestHex.length);\n \n // Use provided timeout, or default to 15s for testnet (slower), 10s for mainnet\n const defaultTimeout = network === 'testnet' ? 15_000 : 10_000;\n const requestTimeout = options?.timeout ?? defaultTimeout;\n \n response = await axios.post(\n endpoint,\n { bytes: requestHex },\n {\n headers: {\n 'X-API-Key': apiKey,\n 'Content-Type': 'application/json',\n },\n timeout: requestTimeout,\n }\n );\n } catch (axiosErr) {\n const err = axiosErr as AxiosError;\n // Network errors (CORS, timeout, no connection) have no response\n if (!err.response) {\n console.error('[queryPortfolio] Network error:', {\n message: err.message,\n code: err.code,\n name: err.name,\n });\n throw new QueryPortfolioError(\n 'NETWORK_ERROR',\n `Network error: ${err.message} (code: ${err.code})`\n );\n }\n const status = err.response.status;\n const errData = err.response.data;\n console.error('[queryPortfolio] Wormhole Query Proxy error:', { status, data: errData });\n throw new QueryPortfolioError(\n 'PROXY_RESPONSE_INVALID',\n `Query Proxy returned ${status}: ${JSON.stringify(errData)}`\n );\n }\n\n const data = response.data as any;\n const signatures = data?.signatures as string[] | undefined;\n const bytes = data?.bytes as string | undefined;\n\n if (!Array.isArray(signatures) || typeof bytes !== 'string') {\n throw new QueryPortfolioError('PROXY_RESPONSE_INVALID', 'Query Proxy response missing signatures/bytes');\n }\n\n const proof = signaturesToProofBytes(signatures);\n const queryBytes = decodeQueryBytes(bytes);\n const parsed = QueryResponse.from(queryBytes);\n\n const nowSeconds = Math.floor(Date.now() / 1000);\n const chainsOut: PortfolioChainResult[] = [];\n\n for (const wormholeChainId of finalChainIds) {\n const meta = chainMeta[wormholeChainId] ?? { kind: 'unsupported' as const };\n\n if (meta.kind === 'unsupported') {\n const msg = wormholeChainId === 22\n ? 'Aptos Queries are not supported by the Wormhole Query SDK yet'\n : 'Chain is not supported by this portfolio query implementation';\n chainsOut.push({\n wormholeChainId,\n chainName: meta.chainName,\n balances: [],\n error: { code: 'UNSUPPORTED_CHAIN', message: msg },\n });\n continue;\n }\n\n if (!meta.vaultAddress) {\n chainsOut.push({\n wormholeChainId,\n chainName: meta.chainName,\n balances: [],\n error: { code: 'MISSING_VAULT', message: 'Unable to derive vault address for chain' },\n });\n continue;\n }\n\n const perChain = parsed.responses.find((r) => r.chainId === wormholeChainId);\n if (!perChain) {\n chainsOut.push({\n wormholeChainId,\n chainName: meta.chainName,\n vaultAddress: meta.vaultAddress,\n balances: [],\n error: { code: 'DECODE_ERROR', message: 'Missing per-chain response from Query Proxy' },\n });\n continue;\n }\n\n try {\n if (meta.kind === 'evm') {\n const cfg = Object.values(chains).find((c) => c.wormholeChainId === wormholeChainId);\n const tokenAddresses = options?.evmTokenAddresses?.[wormholeChainId]\n ?? getAllTokens(wormholeChainId).filter((t) => !isNativeToken(t.address)).map((t) => t.address);\n\n if (!tokenAddresses.length) {\n chainsOut.push({\n wormholeChainId,\n chainName: meta.chainName,\n vaultAddress: meta.vaultAddress,\n balances: [],\n error: { code: 'MISSING_TOKENS', message: 'No ERC20 tokens configured for EVM portfolio query' },\n });\n continue;\n }\n\n const chainResp = EthCallQueryResponse.from(perChain.response.serialize());\n const blockTime = Number(chainResp.blockTime);\n const age = nowSeconds - blockTime;\n if (age > maxAgeSeconds) {\n chainsOut.push({\n wormholeChainId,\n chainName: meta.chainName,\n vaultAddress: meta.vaultAddress,\n blockTime,\n balances: [],\n error: { code: 'ATTESTATION_STALE', message: `Attestation stale by ${age}s (maxAge=${maxAgeSeconds}s)` },\n });\n continue;\n }\n\n const amounts = decodeErc20Balances(chainResp.results, tokenAddresses);\n const tokenInfos = getAllTokens(wormholeChainId).filter((t) => !isNativeToken(t.address));\n\n const balances: PortfolioBalance[] = tokenAddresses.map((addr, i) => {\n const info = tokenInfos.find((t) => t.address.toLowerCase() === addr.toLowerCase());\n const symbol = info?.symbol;\n const decimals = info?.decimals;\n const usdPrice = priceLookup(pricesUsd, symbol, addr);\n const usdValue = usdPrice != null && decimals != null\n ? (Number(amounts[i]) / 10 ** decimals) * usdPrice\n : undefined;\n\n return {\n assetId: addr,\n amount: amounts[i],\n symbol,\n decimals,\n usdValue: Number.isFinite(usdValue ?? NaN) ? usdValue : undefined,\n };\n });\n\n void cfg;\n chainsOut.push({\n wormholeChainId,\n chainName: meta.chainName,\n vaultAddress: meta.vaultAddress,\n blockTime,\n balances,\n });\n continue;\n }\n\n // Solana\n const chainResp = SolanaAccountQueryResponse.from(perChain.response.serialize());\n const blockTime = safeNumberFromBigint(chainResp.blockTime);\n const age = nowSeconds - blockTime;\n if (age > maxAgeSeconds) {\n chainsOut.push({\n wormholeChainId,\n chainName: meta.chainName,\n vaultAddress: meta.vaultAddress,\n blockTime,\n balances: [],\n error: { code: 'ATTESTATION_STALE', message: `Attestation stale by ${age}s (maxAge=${maxAgeSeconds}s)` },\n });\n continue;\n }\n\n const vaultResult = chainResp.results[0];\n const lamports = vaultResult?.lamports ?? 0n;\n\n const balances: PortfolioBalance[] = [\n {\n assetId: 'SOL',\n amount: lamports,\n decimals: 9,\n symbol: 'SOL',\n usdValue: priceLookup(pricesUsd, 'SOL', 'SOL') != null\n ? (Number(lamports) / 1e9) * (priceLookup(pricesUsd, 'SOL', 'SOL') as number)\n : undefined,\n },\n ];\n\n chainsOut.push({\n wormholeChainId,\n chainName: meta.chainName,\n vaultAddress: meta.vaultAddress,\n blockTime,\n balances,\n });\n } catch (cause) {\n chainsOut.push({\n wormholeChainId,\n chainName: meta.chainName,\n vaultAddress: meta.vaultAddress,\n balances: [],\n error: { code: 'DECODE_ERROR', message: `Failed to decode chain response: ${String((cause as any)?.message ?? cause)}` },\n });\n }\n }\n\n const allBalances = chainsOut.flatMap((c) => c.balances);\n const totalUsd = sumUsd(allBalances, pricesUsd);\n\n const result: PortfolioResult = { proof, totalUsd, chains: chainsOut };\n\n PORTFOLIO_CACHE.set(cacheKey, { expiresAt: Date.now() + cacheTtlMs, value: result });\n return result;\n } catch (err) {\n if (err instanceof QueryPortfolioError) throw err;\n if (axios.isAxiosError(err)) {\n const ax = err as AxiosError;\n const status = ax.response?.status;\n const statusText = ax.response?.statusText;\n const details = typeof ax.response?.data === 'string' ? ax.response?.data : undefined;\n\n throw new QueryPortfolioError(\n 'PROXY_HTTP_ERROR',\n `Query Proxy request failed${status ? ` (${status} ${statusText ?? ''})` : ''}${details ? `: ${details}` : ''}`,\n err\n );\n }\n\n throw new QueryPortfolioError('PROXY_HTTP_ERROR', 'Query Proxy request failed', err);\n }\n };\n\n const result = await withExponentialBackoff(doFetch, maxAttempts);\n PORTFOLIO_CACHE.set(cacheKey, { expiresAt: Date.now() + cacheTtlMs, value: result });\n return result;\n}\n","/**\n * Gas Sponsor Module\n * \n * Handles sponsored (gasless) vault creation for Veridex users.\n * Uses a Veridex-owned wallet to pay gas fees on behalf of users.\n * \n * This is a temporary solution until the full relayer is built.\n * In the future, this will be handled by:\n * - ERC-4337 Account Abstraction with Paymasters\n * - Dedicated Relayer service\n */\n\nimport { ethers } from 'ethers';\n\n// ============================================================================\n// Types\n// ============================================================================\n\nexport interface ChainDeploymentConfig {\n name: string;\n chainId: number;\n wormholeChainId: number;\n rpcUrl: string;\n vaultFactory?: string;\n hubAddress?: string;\n isHub?: boolean;\n}\n\nexport interface SponsoredVaultResult {\n success: boolean;\n chain: string;\n wormholeChainId: number;\n vaultAddress?: string;\n transactionHash?: string;\n error?: string;\n alreadyExists?: boolean;\n}\n\nexport interface MultiChainVaultResult {\n keyHash: string;\n results: SponsoredVaultResult[];\n allSuccessful: boolean;\n vaultAddresses: Record<number, string>; // wormholeChainId -> address\n}\n\nexport interface GasSponsorConfig {\n /** \n * Private key for the sponsor wallet (from env or secure storage)\n * This is the fallback when relayer is not available\n */\n sponsorPrivateKey?: string;\n \n /**\n * Integrator-provided sponsor key (for platforms using Veridex SDK)\n * Takes priority over Veridex default sponsorship\n */\n integratorSponsorKey?: string;\n \n /** \n * Relayer API endpoint for remote sponsorship (primary method)\n * When available, this takes priority over local wallet sponsorship\n */\n relayerUrl?: string;\n \n /** API key for relayer service authentication */\n relayerApiKey?: string;\n \n /** @deprecated Use relayerUrl instead */\n sponsorApiUrl?: string;\n /** @deprecated Use relayerApiKey instead */\n sponsorApiKey?: string;\n \n /** Whether to use testnet configurations */\n testnet?: boolean;\n /** Custom RPC URLs by wormhole chain ID */\n customRpcUrls?: Record<number, string>;\n}\n\n/** Sponsorship source type */\nexport type SponsorshipSource = 'relayer' | 'integrator' | 'veridex' | 'none';\n\n// ============================================================================\n// Constants\n// ============================================================================\n\n// Vault Factory ABI (minimal)\nconst VAULT_FACTORY_ABI = [\n 'function createVault(bytes32 ownerKeyHash) external returns (address)',\n 'function getVault(bytes32 ownerKeyHash) external view returns (address)',\n 'function vaultExists(bytes32 ownerKeyHash) external view returns (bool)',\n 'function computeVaultAddress(bytes32 ownerKeyHash) external view returns (address)',\n 'event VaultCreated(address indexed vault, bytes32 indexed ownerKeyHash, address creator)',\n];\n\n// Testnet chain configurations\nconst TESTNET_CHAINS: ChainDeploymentConfig[] = [\n {\n name: 'Base Sepolia',\n chainId: 84532,\n wormholeChainId: 10004,\n rpcUrl: 'https://sepolia.base.org',\n hubAddress: '0xf189b649ecb44708165f36619ED24ff917eF1f94',\n isHub: true,\n },\n {\n name: 'Optimism Sepolia',\n chainId: 11155420,\n wormholeChainId: 10005,\n rpcUrl: 'https://sepolia.optimism.io',\n vaultFactory: '0x677bA5C2f9c7377860c7aeB00037E1a5D12B3515',\n },\n {\n name: 'Arbitrum Sepolia',\n chainId: 421614,\n wormholeChainId: 10003,\n rpcUrl: 'https://sepolia-rollup.arbitrum.io/rpc',\n vaultFactory: '0xbE9B9c39956448DA75Ac97E5e3dE17e34171660A',\n },\n];\n\n// Mainnet chain configurations (for future use)\nconst MAINNET_CHAINS: ChainDeploymentConfig[] = [\n // Will be populated when mainnet is ready\n];\n\n// ============================================================================\n// GasSponsor Class\n// ============================================================================\n\n/**\n * Gas Sponsorship with layered fallback:\n * 1. Relayer (primary) - Remote relayer service handles gas\n * 2. Integrator wallet - Platform using SDK provides their own sponsor key\n * 3. Veridex wallet (fallback) - Veridex's default sponsor wallet\n */\nexport class GasSponsor {\n private config: GasSponsorConfig;\n private sponsorWallet?: ethers.Wallet;\n private integratorWallet?: ethers.Wallet;\n private chains: ChainDeploymentConfig[];\n\n constructor(config: GasSponsorConfig = {}) {\n this.config = config;\n this.chains = config.testnet !== false ? TESTNET_CHAINS : MAINNET_CHAINS;\n\n // Initialize integrator wallet if provided (takes priority)\n if (config.integratorSponsorKey) {\n this.integratorWallet = new ethers.Wallet(config.integratorSponsorKey);\n }\n\n // Initialize Veridex sponsor wallet as fallback\n if (config.sponsorPrivateKey) {\n this.sponsorWallet = new ethers.Wallet(config.sponsorPrivateKey);\n }\n }\n\n /**\n * Determine which sponsorship source is available\n * Priority: Relayer > Integrator > Veridex > None\n */\n getSponsorshipSource(): SponsorshipSource {\n // 1. Check relayer first (future primary method)\n if (this.config.relayerUrl || this.config.sponsorApiUrl) {\n return 'relayer';\n }\n \n // 2. Check integrator-provided wallet\n if (this.integratorWallet) {\n return 'integrator';\n }\n \n // 3. Check Veridex fallback wallet\n if (this.sponsorWallet) {\n return 'veridex';\n }\n \n return 'none';\n }\n\n /**\n * Get the active sponsor wallet (integrator takes priority)\n */\n private getActiveWallet(): ethers.Wallet | undefined {\n return this.integratorWallet || this.sponsorWallet;\n }\n\n /**\n * Get supported chains for vault deployment\n */\n getSupportedChains(): ChainDeploymentConfig[] {\n return this.chains.filter(c => c.vaultFactory);\n }\n\n /**\n * Get the hub chain configuration\n */\n getHubChain(): ChainDeploymentConfig | undefined {\n return this.chains.find(c => c.isHub);\n }\n\n /**\n * Check if sponsor is configured (has relayer, integrator key, or Veridex key)\n */\n isConfigured(): boolean {\n return this.getSponsorshipSource() !== 'none';\n }\n\n /**\n * Get sponsor wallet balance on a specific chain\n */\n async getSponsorBalance(wormholeChainId: number): Promise<bigint> {\n const chain = this.chains.find(c => c.wormholeChainId === wormholeChainId);\n const wallet = this.getActiveWallet();\n if (!chain || !wallet) {\n return BigInt(0);\n }\n\n const rpcUrl = this.config.customRpcUrls?.[wormholeChainId] || chain.rpcUrl;\n const provider = new ethers.JsonRpcProvider(rpcUrl);\n return await provider.getBalance(wallet.address);\n }\n\n /**\n * Check if a vault exists for a given key hash on a chain\n */\n async checkVaultExists(\n keyHash: string,\n wormholeChainId: number\n ): Promise<{ exists: boolean; address: string }> {\n const chain = this.chains.find(c => c.wormholeChainId === wormholeChainId);\n if (!chain || !chain.vaultFactory) {\n return { exists: false, address: ethers.ZeroAddress };\n }\n\n const rpcUrl = this.config.customRpcUrls?.[wormholeChainId] || chain.rpcUrl;\n const provider = new ethers.JsonRpcProvider(rpcUrl);\n const factory = new ethers.Contract(chain.vaultFactory, VAULT_FACTORY_ABI, provider);\n\n try {\n const address = await factory.getVault(keyHash);\n const exists = address !== ethers.ZeroAddress;\n return { exists, address };\n } catch (error) {\n console.error(`Error checking vault on ${chain.name}:`, error);\n return { exists: false, address: ethers.ZeroAddress };\n }\n }\n\n /**\n * Get predicted vault address for a key hash on a chain\n */\n async computeVaultAddress(\n keyHash: string,\n wormholeChainId: number\n ): Promise<string | null> {\n const chain = this.chains.find(c => c.wormholeChainId === wormholeChainId);\n if (!chain || !chain.vaultFactory) {\n return null;\n }\n\n const rpcUrl = this.config.customRpcUrls?.[wormholeChainId] || chain.rpcUrl;\n const provider = new ethers.JsonRpcProvider(rpcUrl);\n const factory = new ethers.Contract(chain.vaultFactory, VAULT_FACTORY_ABI, provider);\n\n try {\n return await factory.computeVaultAddress(keyHash);\n } catch (error) {\n console.error(`Error computing vault address on ${chain.name}:`, error);\n return null;\n }\n }\n\n /**\n * Create a vault on a specific chain (sponsored)\n * \n * Sponsorship priority:\n * 1. Relayer API (future - not yet implemented)\n * 2. Integrator wallet (if provided)\n * 3. Veridex sponsor wallet (fallback)\n */\n async createVaultOnChain(\n keyHash: string,\n wormholeChainId: number\n ): Promise<SponsoredVaultResult> {\n const chain = this.chains.find(c => c.wormholeChainId === wormholeChainId);\n \n if (!chain) {\n return {\n success: false,\n chain: 'Unknown',\n wormholeChainId,\n error: `Chain ${wormholeChainId} not found`,\n };\n }\n\n if (!chain.vaultFactory) {\n return {\n success: false,\n chain: chain.name,\n wormholeChainId,\n error: `No vault factory configured for ${chain.name}`,\n };\n }\n\n const source = this.getSponsorshipSource();\n\n // 1. Check if using relayer API (future primary method)\n if (source === 'relayer') {\n const relayerUrl = this.config.relayerUrl || this.config.sponsorApiUrl;\n if (relayerUrl) {\n return await this.createVaultViaRelayer(keyHash, chain, relayerUrl);\n }\n }\n\n // 2. Use local wallet (integrator or Veridex)\n const wallet = this.getActiveWallet();\n if (!wallet) {\n return {\n success: false,\n chain: chain.name,\n wormholeChainId,\n error: 'No sponsor configured. Set VERIDEX_SPONSOR_KEY or provide integratorSponsorKey.',\n };\n }\n\n const sponsorType = source === 'integrator' ? 'Integrator' : 'Veridex';\n\n try {\n const rpcUrl = this.config.customRpcUrls?.[wormholeChainId] || chain.rpcUrl;\n const provider = new ethers.JsonRpcProvider(rpcUrl);\n const signer = wallet.connect(provider);\n const factory = new ethers.Contract(chain.vaultFactory, VAULT_FACTORY_ABI, signer);\n\n // Check if vault already exists\n const existingVault = await factory.getVault(keyHash);\n if (existingVault !== ethers.ZeroAddress) {\n return {\n success: true,\n chain: chain.name,\n wormholeChainId,\n vaultAddress: existingVault,\n alreadyExists: true,\n };\n }\n\n // Check sponsor balance\n const balance = await provider.getBalance(signer.address);\n if (balance < ethers.parseEther('0.001')) {\n return {\n success: false,\n chain: chain.name,\n wormholeChainId,\n error: `Insufficient ${sponsorType} sponsor balance on ${chain.name}`,\n };\n }\n\n // Create vault\n console.log(`[GasSponsor] Creating vault on ${chain.name} (${sponsorType} sponsored)...`);\n const tx = await factory.createVault(keyHash);\n const receipt = await tx.wait();\n\n // Get vault address from event or direct query\n const vaultAddress = await factory.getVault(keyHash);\n\n console.log(`[GasSponsor] OK Vault created on ${chain.name}: ${vaultAddress}`);\n\n return {\n success: true,\n chain: chain.name,\n wormholeChainId,\n vaultAddress,\n transactionHash: receipt.hash,\n };\n } catch (error: any) {\n console.error(`[GasSponsor] Error creating vault on ${chain.name}:`, error);\n return {\n success: false,\n chain: chain.name,\n wormholeChainId,\n error: error.message || 'Unknown error',\n };\n }\n }\n\n /**\n * Create vault via relayer service (future primary method)\n * \n * The relayer handles:\n * - Gas payment on behalf of users\n * - Transaction submission and monitoring\n * - Rate limiting and abuse prevention\n */\n private async createVaultViaRelayer(\n keyHash: string,\n chain: ChainDeploymentConfig,\n relayerUrl: string\n ): Promise<SponsoredVaultResult> {\n try {\n const apiKey = this.config.relayerApiKey || this.config.sponsorApiKey;\n \n const response = await fetch(`${relayerUrl}/create-vault`, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n ...(apiKey && {\n 'Authorization': `Bearer ${apiKey}`,\n }),\n },\n body: JSON.stringify({\n keyHash,\n wormholeChainId: chain.wormholeChainId,\n }),\n });\n\n if (!response.ok) {\n const error = await response.text();\n \n // If relayer fails, try fallback to local wallet\n console.warn(`[GasSponsor] Relayer failed, trying local wallet fallback...`);\n const wallet = this.getActiveWallet();\n if (wallet) {\n return await this.createVaultWithWallet(keyHash, chain, wallet);\n }\n \n throw new Error(`Relayer error: ${error}`);\n }\n\n const result = await response.json();\n return {\n success: true,\n chain: chain.name,\n wormholeChainId: chain.wormholeChainId,\n vaultAddress: result.vaultAddress,\n transactionHash: result.transactionHash,\n alreadyExists: result.alreadyExists,\n };\n } catch (error: any) {\n // Fallback to local wallet if relayer fails\n console.warn(`[GasSponsor] Relayer unavailable: ${error.message}`);\n const wallet = this.getActiveWallet();\n if (wallet) {\n console.log(`[GasSponsor] Falling back to local wallet sponsorship...`);\n return await this.createVaultWithWallet(keyHash, chain, wallet);\n }\n \n return {\n success: false,\n chain: chain.name,\n wormholeChainId: chain.wormholeChainId,\n error: error.message || 'Relayer request failed and no fallback available',\n };\n }\n }\n\n /**\n * Create vault with a specific wallet (internal helper)\n */\n private async createVaultWithWallet(\n keyHash: string,\n chain: ChainDeploymentConfig,\n wallet: ethers.Wallet\n ): Promise<SponsoredVaultResult> {\n if (!chain.vaultFactory) {\n return {\n success: false,\n chain: chain.name,\n wormholeChainId: chain.wormholeChainId,\n error: `No vault factory for ${chain.name}`,\n };\n }\n\n try {\n const rpcUrl = this.config.customRpcUrls?.[chain.wormholeChainId] || chain.rpcUrl;\n const provider = new ethers.JsonRpcProvider(rpcUrl);\n const signer = wallet.connect(provider);\n const factory = new ethers.Contract(chain.vaultFactory, VAULT_FACTORY_ABI, signer);\n\n // Check if vault already exists\n const existingVault = await factory.getVault(keyHash);\n if (existingVault !== ethers.ZeroAddress) {\n return {\n success: true,\n chain: chain.name,\n wormholeChainId: chain.wormholeChainId,\n vaultAddress: existingVault,\n alreadyExists: true,\n };\n }\n\n // Check balance\n const balance = await provider.getBalance(signer.address);\n if (balance < ethers.parseEther('0.001')) {\n return {\n success: false,\n chain: chain.name,\n wormholeChainId: chain.wormholeChainId,\n error: `Insufficient sponsor balance on ${chain.name}`,\n };\n }\n\n // Create vault\n const tx = await factory.createVault(keyHash);\n const receipt = await tx.wait();\n const vaultAddress = await factory.getVault(keyHash);\n\n return {\n success: true,\n chain: chain.name,\n wormholeChainId: chain.wormholeChainId,\n vaultAddress,\n transactionHash: receipt.hash,\n };\n } catch (error: any) {\n return {\n success: false,\n chain: chain.name,\n wormholeChainId: chain.wormholeChainId,\n error: error.message || 'Wallet creation failed',\n };\n }\n }\n\n /**\n * Create vaults on all supported chains (sponsored)\n */\n async createVaultsOnAllChains(keyHash: string): Promise<MultiChainVaultResult> {\n const supportedChains = this.getSupportedChains();\n const results: SponsoredVaultResult[] = [];\n const vaultAddresses: Record<number, string> = {};\n\n console.log(`[GasSponsor] Creating vaults on ${supportedChains.length} chains...`);\n\n // Create vaults in parallel (or sequentially for rate limiting)\n for (const chain of supportedChains) {\n const result = await this.createVaultOnChain(keyHash, chain.wormholeChainId);\n results.push(result);\n\n if (result.success && result.vaultAddress) {\n vaultAddresses[chain.wormholeChainId] = result.vaultAddress;\n }\n }\n\n const allSuccessful = results.every(r => r.success);\n\n return {\n keyHash,\n results,\n allSuccessful,\n vaultAddresses,\n };\n }\n\n /**\n * Check vault status on all chains\n */\n async checkVaultsOnAllChains(keyHash: string): Promise<Record<number, { exists: boolean; address: string }>> {\n const supportedChains = this.getSupportedChains();\n const results: Record<number, { exists: boolean; address: string }> = {};\n\n for (const chain of supportedChains) {\n results[chain.wormholeChainId] = await this.checkVaultExists(keyHash, chain.wormholeChainId);\n }\n\n return results;\n }\n}\n\n// ============================================================================\n// Factory Function\n// ============================================================================\n\n/**\n * Create a GasSponsor instance\n * \n * @example\n * ```ts\n * // With environment variable\n * const sponsor = createGasSponsor({\n * sponsorPrivateKey: process.env.VERIDEX_SPONSOR_KEY,\n * testnet: true,\n * });\n * \n * // Create vaults for a user\n * const result = await sponsor.createVaultsOnAllChains(userKeyHash);\n * ```\n */\nexport function createGasSponsor(config: GasSponsorConfig = {}): GasSponsor {\n return new GasSponsor(config);\n}\n\n// ============================================================================\n// Convenience Functions\n// ============================================================================\n\n/**\n * Quick check if gas sponsorship is available\n */\nexport function isSponsorshipAvailable(): boolean {\n return !!(\n typeof process !== 'undefined' &&\n (process.env?.VERIDEX_SPONSOR_KEY || process.env?.NEXT_PUBLIC_SPONSOR_API_URL)\n );\n}\n\n/**\n * Get chain configurations for display\n */\nexport function getSupportedChainConfigs(testnet: boolean = true): ChainDeploymentConfig[] {\n return (testnet ? TESTNET_CHAINS : MAINNET_CHAINS).filter(c => c.vaultFactory);\n}\n","/**\n * Veridex Protocol SDK - EVM Chain Client\n * \n * Implementation of ChainClient interface for EVM-compatible chains\n */\n\nimport { ethers } from 'ethers';\nimport type {\n ChainClient,\n ChainConfig,\n TransferParams,\n ExecuteParams,\n BridgeParams,\n DispatchResult,\n WebAuthnSignature,\n VaultCreationResult,\n} from '../../core/types.js';\nimport { encodeTransferAction, encodeExecuteAction, encodeBridgeAction } from '../../payload.js';\n\n// ============================================================================\n// Types\n// ============================================================================\n\nexport interface EVMClientConfig {\n chainId: number;\n wormholeChainId: number;\n rpcUrl: string;\n hubContractAddress: string;\n wormholeCoreBridge: string;\n name?: string;\n explorerUrl?: string;\n vaultFactory?: string;\n vaultImplementation?: string;\n tokenBridge?: string;\n}\n\n// ============================================================================\n// Constants\n// ============================================================================\n\n/**\n * EIP-1167 minimal proxy bytecode prefix (before implementation address)\n */\nconst PROXY_BYTECODE_PREFIX = '0x3d602d80600a3d3981f3363d3d373d3d3d363d73';\n\n/**\n * EIP-1167 minimal proxy bytecode suffix (after implementation address)\n */\nconst PROXY_BYTECODE_SUFFIX = '5af43d82803e903d91602b57fd5bf3';\n\n/**\n * ERC20 ABI for balance and transfer operations\n */\nconst ERC20_ABI = [\n 'function balanceOf(address owner) view returns (uint256)',\n 'function decimals() view returns (uint8)',\n 'function symbol() view returns (string)',\n 'function name() view returns (string)',\n 'function allowance(address owner, address spender) view returns (uint256)',\n 'function transfer(address to, uint256 amount) returns (bool)',\n 'function approve(address spender, uint256 amount) returns (bool)',\n];\n\n// ============================================================================\n// Hub Contract ABI (minimal)\n// ============================================================================\n\nconst HUB_ABI = [\n 'function dispatch(tuple(bytes authenticatorData, string clientDataJSON, uint256 challengeIndex, uint256 typeIndex, uint256 r, uint256 s) signature, uint256 publicKeyX, uint256 publicKeyY, uint16 targetChain, bytes actionPayload, uint256 nonce) payable returns (uint64 sequence)',\n 'function getNonce(bytes32 userKeyHash) view returns (uint256)',\n 'function getMessageFee() view returns (uint256)',\n 'function getVaultAddress(bytes32 userKeyHash) view returns (address)',\n 'function vaultExists(bytes32 userKeyHash) view returns (bool)',\n 'function createVault(bytes32 userKeyHash) returns (address)',\n // Issue #9/#10: New Hub methods for Query-based execution\n 'function getUserState(bytes32 userKeyHash) view returns (bytes32 keyHash, uint256 nonce, bytes32 lastActionHash)',\n 'function getUserLastActionHash(bytes32 userKeyHash) view returns (bytes32)',\n // Issue #13: Session key management\n 'function registerSession(tuple(bytes authenticatorData, string clientDataJSON, uint256 challengeIndex, uint256 typeIndex, uint256 r, uint256 s) auth, uint256 publicKeyX, uint256 publicKeyY, bytes32 sessionKeyHash, uint256 duration, uint256 maxValue, bool requireUV) external',\n 'function isSessionActive(bytes32 userKeyHash, bytes32 sessionKeyHash) view returns (bool active, uint256 expiry, uint256 maxValue, uint256 sessionIndex)',\n 'function revokeSession(tuple(bytes authenticatorData, string clientDataJSON, uint256 challengeIndex, uint256 typeIndex, uint256 r, uint256 s) auth, uint256 publicKeyX, uint256 publicKeyY, bytes32 sessionKeyHash, bool requireUV) external',\n 'function getUserSessions(bytes32 userKeyHash) view returns (tuple(bytes32 sessionKeyHash, uint256 expiry, uint256 maxValue, bool revoked)[])',\n 'function getUserSessionCount(bytes32 userKeyHash) view returns (uint256)',\n // Issue #22: Backup Passkey / Multi-Key Identity management\n 'function registerIdentity(tuple(bytes authenticatorData, string clientDataJSON, uint256 challengeIndex, uint256 typeIndex, uint256 r, uint256 s) auth, uint256 publicKeyX, uint256 publicKeyY) external',\n 'function addBackupKey(tuple(bytes authenticatorData, string clientDataJSON, uint256 challengeIndex, uint256 typeIndex, uint256 r, uint256 s) auth, uint256 publicKeyX, uint256 publicKeyY, uint256 newPublicKeyX, uint256 newPublicKeyY, uint256 nonce) external payable returns (uint64 sequence)',\n 'function removeKey(tuple(bytes authenticatorData, string clientDataJSON, uint256 challengeIndex, uint256 typeIndex, uint256 r, uint256 s) auth, uint256 publicKeyX, uint256 publicKeyY, bytes32 keyToRemove, uint256 nonce) external payable returns (uint64 sequence)',\n 'function getIdentityForKey(bytes32 keyHash) view returns (bytes32)',\n 'function getAuthorizedKeys(bytes32 identity) view returns (bytes32[])',\n 'function getAuthorizedKeyCount(bytes32 identity) view returns (uint256)',\n 'function isAuthorizedForIdentity(bytes32 identity, bytes32 keyHash) view returns (bool)',\n 'function isIdentityRoot(bytes32 keyHash) view returns (bool)',\n 'function getIdentityState(bytes32 keyHash) view returns (bytes32 identity, uint256 keyCount, uint256 maxKeys, bool isRoot)',\n \n // Issue #23: Social Recovery / Guardian Management\n 'function setupGuardians(tuple(bytes authenticatorData, string clientDataJSON, uint256 challengeIndex, uint256 typeIndex, uint256 r, uint256 s) auth, uint256 publicKeyX, uint256 publicKeyY, bytes32[] guardians, uint256 threshold) external payable returns (uint64 sequence)',\n 'function addGuardian(tuple(bytes authenticatorData, string clientDataJSON, uint256 challengeIndex, uint256 typeIndex, uint256 r, uint256 s) auth, uint256 publicKeyX, uint256 publicKeyY, bytes32 guardianKeyHash) external payable returns (uint64 sequence)',\n 'function removeGuardian(tuple(bytes authenticatorData, string clientDataJSON, uint256 challengeIndex, uint256 typeIndex, uint256 r, uint256 s) auth, uint256 publicKeyX, uint256 publicKeyY, bytes32 guardianKeyHash) external payable returns (uint64 sequence)',\n 'function initiateRecovery(tuple(bytes authenticatorData, string clientDataJSON, uint256 challengeIndex, uint256 typeIndex, uint256 r, uint256 s) auth, uint256 publicKeyX, uint256 publicKeyY, bytes32 identityToRecover, bytes32 newOwnerKeyHash) external payable returns (uint64 sequence)',\n 'function approveRecovery(tuple(bytes authenticatorData, string clientDataJSON, uint256 challengeIndex, uint256 typeIndex, uint256 r, uint256 s) auth, uint256 publicKeyX, uint256 publicKeyY, bytes32 identityToRecover) external payable returns (uint64 sequence)',\n 'function executeRecovery(bytes32 identityToRecover, uint256 newPublicKeyX, uint256 newPublicKeyY) external payable returns (uint64 sequence)',\n 'function cancelRecovery(tuple(bytes authenticatorData, string clientDataJSON, uint256 challengeIndex, uint256 typeIndex, uint256 r, uint256 s) auth, uint256 publicKeyX, uint256 publicKeyY) external payable returns (uint64 sequence)',\n 'function getGuardians(bytes32 identityKeyHash) view returns (bytes32[] guardians, uint256 threshold, bool isConfigured)',\n 'function getRecoveryStatus(bytes32 identityKeyHash) view returns (bool isActive, bytes32 newOwnerKeyHash, uint256 initiatedAt, uint256 approvalCount, uint256 threshold, uint256 canExecuteAt, uint256 expiresAt)',\n 'function hasGuardianApproved(bytes32 identityKeyHash, bytes32 guardianKeyHash) view returns (bool hasApproved)',\n];\n\n// ============================================================================\n// Factory Contract ABI (minimal)\n// ============================================================================\n\nconst FACTORY_ABI = [\n 'function createVault(bytes32 ownerKeyHash) returns (address vault)',\n 'function getVault(bytes32 ownerKeyHash) view returns (address)',\n 'function computeVaultAddress(bytes32 ownerKeyHash) view returns (address vault)',\n 'function vaultExists(bytes32 ownerKeyHash) view returns (bool)',\n 'function implementation() view returns (address)',\n];\n\n// ============================================================================\n// EVMClient Class\n// ============================================================================\n\n/**\n * EVM implementation of the ChainClient interface\n */\nexport class EVMClient implements ChainClient {\n private config: ChainConfig;\n private provider: ethers.JsonRpcProvider;\n private hubContract: ethers.Contract;\n private factoryContract: ethers.Contract | null = null;\n private cachedImplementation: string | null = null;\n\n constructor(config: EVMClientConfig) {\n this.config = {\n name: config.name ?? `EVM Chain ${config.chainId}`,\n chainId: config.chainId,\n wormholeChainId: config.wormholeChainId,\n rpcUrl: config.rpcUrl,\n explorerUrl: config.explorerUrl ?? '',\n isEvm: true,\n contracts: {\n hub: config.hubContractAddress,\n vaultFactory: config.vaultFactory,\n vaultImplementation: config.vaultImplementation,\n wormholeCoreBridge: config.wormholeCoreBridge,\n tokenBridge: config.tokenBridge,\n },\n };\n\n this.provider = new ethers.JsonRpcProvider(config.rpcUrl);\n this.hubContract = new ethers.Contract(\n config.hubContractAddress,\n HUB_ABI,\n this.provider\n );\n\n // Initialize factory contract if address is provided\n if (config.vaultFactory) {\n this.factoryContract = new ethers.Contract(\n config.vaultFactory,\n FACTORY_ABI,\n this.provider\n );\n }\n\n // Cache implementation address if provided\n if (config.vaultImplementation) {\n this.cachedImplementation = config.vaultImplementation;\n }\n }\n\n getConfig(): ChainConfig {\n return this.config;\n }\n\n async getNonce(userKeyHash: string): Promise<bigint> {\n const nonce = await this.hubContract.getNonce(userKeyHash);\n return BigInt(nonce.toString());\n }\n\n /**\n * Get user state from Hub (Issue #9/#10)\n * Returns comprehensive state including last action hash\n */\n async getUserState(userKeyHash: string): Promise<{\n keyHash: string;\n nonce: bigint;\n lastActionHash: string;\n }> {\n try {\n const result = await this.hubContract.getUserState(userKeyHash);\n return {\n keyHash: result[0],\n nonce: BigInt(result[1].toString()),\n lastActionHash: result[2],\n };\n } catch (error) {\n // Fallback for older Hub deployments without getUserState\n const nonce = await this.getNonce(userKeyHash);\n return {\n keyHash: userKeyHash,\n nonce,\n lastActionHash: ethers.ZeroHash,\n };\n }\n }\n\n /**\n * Get user's last action hash from Hub (Issue #9/#10)\n * Returns zero hash if user has no actions yet\n */\n async getUserLastActionHash(userKeyHash: string): Promise<string> {\n try {\n return await this.hubContract.getUserLastActionHash(userKeyHash);\n } catch (error) {\n // Fallback for older Hub deployments\n return ethers.ZeroHash;\n }\n }\n\n // ==========================================================================\n // Session Management Methods (Issue #13)\n // ==========================================================================\n\n /**\n * Register a new session key for temporary authentication\n * Enables native L1 speed for repeat transactions without biometric auth\n * \n * @param params Session registration parameters\n * @param signer Ethereum signer to pay gas\n * @returns Transaction receipt\n */\n async registerSession(\n params: import('../../types.js').RegisterSessionParams,\n signer: ethers.Signer\n ): Promise<ethers.TransactionReceipt> {\n const hubWithSigner = this.hubContract.connect(signer) as any;\n\n const authTuple = {\n authenticatorData: params.signature.authenticatorData,\n clientDataJSON: params.signature.clientDataJSON,\n challengeIndex: params.signature.challengeIndex,\n typeIndex: params.signature.typeIndex,\n r: params.signature.r,\n s: params.signature.s,\n };\n\n const tx = await hubWithSigner.registerSession(\n authTuple,\n params.publicKeyX,\n params.publicKeyY,\n params.sessionKeyHash,\n params.duration,\n params.maxValue,\n params.requireUV\n );\n\n return await tx.wait();\n }\n\n /**\n * Check if a session is currently active (queryable via Wormhole CCQ)\n * \n * @param userKeyHash Hash of the user's Passkey public key\n * @param sessionKeyHash Hash of the session key to check\n * @returns Session validation result\n */\n async isSessionActive(\n userKeyHash: string,\n sessionKeyHash: string\n ): Promise<import('../../types.js').SessionValidationResult> {\n const result = await this.hubContract.isSessionActive(userKeyHash, sessionKeyHash);\n \n return {\n active: result[0],\n expiry: Number(result[1]),\n maxValue: BigInt(result[2].toString()),\n sessionIndex: Number(result[3]),\n };\n }\n\n /**\n * Revoke a session key immediately\n * \n * @param params Session revocation parameters\n * @param signer Ethereum signer to pay gas\n * @returns Transaction receipt\n */\n async revokeSession(\n params: import('../../types.js').RevokeSessionParams,\n signer: ethers.Signer\n ): Promise<ethers.TransactionReceipt> {\n const hubWithSigner = this.hubContract.connect(signer) as any;\n\n const authTuple = {\n authenticatorData: params.signature.authenticatorData,\n clientDataJSON: params.signature.clientDataJSON,\n challengeIndex: params.signature.challengeIndex,\n typeIndex: params.signature.typeIndex,\n r: params.signature.r,\n s: params.signature.s,\n };\n\n const tx = await hubWithSigner.revokeSession(\n authTuple,\n params.publicKeyX,\n params.publicKeyY,\n params.sessionKeyHash,\n params.requireUV\n );\n\n return await tx.wait();\n }\n\n /**\n * Get all sessions for a user\n * \n * @param userKeyHash Hash of the user's Passkey public key\n * @returns Array of all sessions (active and expired/revoked)\n */\n async getUserSessions(userKeyHash: string): Promise<import('../../types.js').SessionKey[]> {\n const sessions = await this.hubContract.getUserSessions(userKeyHash);\n \n return sessions.map((s: any) => ({\n sessionKeyHash: s.sessionKeyHash,\n expiry: Number(s.expiry),\n maxValue: BigInt(s.maxValue.toString()),\n revoked: s.revoked,\n }));\n }\n\n /**\n * Get the number of sessions for a user\n * \n * @param userKeyHash Hash of the user's Passkey public key\n * @returns Number of sessions\n */\n async getUserSessionCount(userKeyHash: string): Promise<number> {\n const count = await this.hubContract.getUserSessionCount(userKeyHash);\n return Number(count);\n }\n\n async getMessageFee(): Promise<bigint> {\n const fee = await this.hubContract.getMessageFee();\n return BigInt(fee.toString());\n }\n\n async buildTransferPayload(params: TransferParams): Promise<string> {\n return encodeTransferAction(\n params.token,\n params.recipient,\n params.amount\n );\n }\n\n async buildExecutePayload(params: ExecuteParams): Promise<string> {\n return encodeExecuteAction(\n params.target,\n params.value,\n params.data\n );\n }\n\n async buildBridgePayload(params: BridgeParams): Promise<string> {\n return encodeBridgeAction(\n params.token,\n params.amount,\n params.destinationChain,\n params.recipient\n );\n }\n\n async dispatch(\n signature: WebAuthnSignature,\n publicKeyX: bigint,\n publicKeyY: bigint,\n targetChain: number,\n actionPayload: string,\n nonce: bigint,\n signer: ethers.Signer\n ): Promise<DispatchResult> {\n const hubWithSigner = this.hubContract.connect(signer) as any;\n\n const signatureTuple = {\n authenticatorData: signature.authenticatorData,\n clientDataJSON: signature.clientDataJSON,\n challengeIndex: signature.challengeIndex,\n typeIndex: signature.typeIndex,\n r: signature.r,\n s: signature.s,\n };\n\n const messageFee = await this.getMessageFee();\n\n const tx = await hubWithSigner.dispatch(\n signatureTuple,\n publicKeyX,\n publicKeyY,\n targetChain,\n actionPayload,\n nonce,\n { value: messageFee }\n );\n\n const receipt = await tx.wait();\n\n // Extract sequence from event logs\n const dispatchEvent = receipt.logs.find((log: any) => {\n try {\n const parsed = hubWithSigner.interface.parseLog(log);\n return parsed?.name === 'ActionDispatched';\n } catch {\n return false;\n }\n });\n\n let sequence = 0n;\n if (dispatchEvent) {\n const parsed = hubWithSigner.interface.parseLog(dispatchEvent);\n sequence = BigInt(parsed?.args?.sequence?.toString() ?? '0');\n }\n\n const keyHash = ethers.keccak256(\n ethers.AbiCoder.defaultAbiCoder().encode(\n ['uint256', 'uint256'],\n [publicKeyX, publicKeyY]\n )\n );\n\n return {\n transactionHash: receipt.hash,\n sequence,\n userKeyHash: keyHash,\n targetChain,\n blockNumber: receipt.blockNumber,\n };\n }\n\n /**\n * Dispatch an action to the Hub via relayer (gasless)\n * The relayer pays for gas and submits the transaction on behalf of the user\n */\n async dispatchGasless(\n signature: WebAuthnSignature,\n publicKeyX: bigint,\n publicKeyY: bigint,\n targetChain: number,\n actionPayload: string,\n nonce: bigint,\n relayerUrl: string\n ): Promise<DispatchResult> {\n // Compute message hash that was signed\n // This should match how the WebAuthn signature was generated\n const keyHash = ethers.keccak256(\n ethers.AbiCoder.defaultAbiCoder().encode(\n ['uint256', 'uint256'],\n [publicKeyX, publicKeyY]\n )\n );\n\n // Build the message that was signed\n const message = ethers.keccak256(\n ethers.AbiCoder.defaultAbiCoder().encode(\n ['bytes32', 'uint16', 'bytes', 'uint256'],\n [keyHash, targetChain, actionPayload, nonce]\n )\n );\n\n // Prepare request for relayer\n const request = {\n messageHash: message,\n r: '0x' + signature.r.toString(16).padStart(64, '0'),\n s: '0x' + signature.s.toString(16).padStart(64, '0'),\n publicKeyX: '0x' + publicKeyX.toString(16).padStart(64, '0'),\n publicKeyY: '0x' + publicKeyY.toString(16).padStart(64, '0'),\n targetChain,\n actionPayload,\n nonce: Number(nonce),\n };\n\n // Submit to relayer\n const response = await fetch(`${relayerUrl}/api/v1/submit`, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n },\n body: JSON.stringify(request),\n });\n\n if (!response.ok) {\n const error = await response.json().catch(() => ({ error: response.statusText }));\n throw new Error(`Relayer submission failed: ${error.error || response.statusText}`);\n }\n\n const result = await response.json();\n\n if (!result.success) {\n throw new Error(`Relayer submission failed: ${result.error}`);\n }\n\n return {\n transactionHash: result.txHash,\n sequence: BigInt(result.sequence || '0'),\n userKeyHash: keyHash,\n targetChain,\n };\n }\n\n async getVaultAddress(userKeyHash: string): Promise<string | null> {\n try {\n // Try factory first if available\n if (this.factoryContract) {\n const address = await this.factoryContract.getVault(userKeyHash);\n if (address !== ethers.ZeroAddress) {\n return address;\n }\n }\n\n // Fallback to hub contract\n const address = await this.hubContract.getVaultAddress(userKeyHash);\n if (address === ethers.ZeroAddress) {\n return null;\n }\n return address;\n } catch (error) {\n console.error('Error getting vault address:', error);\n return null;\n }\n }\n\n /**\n * Compute vault address deterministically without querying the chain\n * Uses CREATE2 with EIP-1167 minimal proxy pattern\n */\n computeVaultAddress(userKeyHash: string): string {\n const factoryAddress = this.getFactoryAddress();\n const implementationAddress = this.getImplementationAddress();\n\n if (!factoryAddress || !implementationAddress) {\n throw new Error('Factory and implementation addresses required for address computation');\n }\n\n // Compute salt: keccak256(abi.encodePacked(factory, keyHash))\n const salt = ethers.keccak256(\n ethers.solidityPacked(\n ['address', 'bytes32'],\n [factoryAddress, userKeyHash]\n )\n );\n\n // Build EIP-1167 initcode\n const initCode = this.buildProxyInitCode(implementationAddress);\n const initCodeHash = ethers.keccak256(initCode);\n\n // CREATE2 address computation:\n // address = keccak256(0xff ++ factory ++ salt ++ initCodeHash)[12:]\n const create2Data = ethers.solidityPacked(\n ['bytes1', 'address', 'bytes32', 'bytes32'],\n ['0xff', factoryAddress, salt, initCodeHash]\n );\n\n const hash = ethers.keccak256(create2Data);\n // Take last 20 bytes as address\n return ethers.getAddress('0x' + hash.slice(26));\n }\n\n /**\n * Build EIP-1167 minimal proxy initcode\n */\n private buildProxyInitCode(implementationAddress: string): string {\n const impl = implementationAddress.toLowerCase().replace('0x', '');\n return PROXY_BYTECODE_PREFIX + impl + PROXY_BYTECODE_SUFFIX;\n }\n\n async vaultExists(userKeyHash: string): Promise<boolean> {\n try {\n // Try factory first if available\n if (this.factoryContract) {\n return await this.factoryContract.vaultExists(userKeyHash);\n }\n // Hub chains may not have vaultExists, silently return false\n if (this.hubContract.vaultExists) {\n try {\n return await this.hubContract.vaultExists(userKeyHash);\n } catch {\n // Hub contract doesn't have vaultExists - this is expected on hub-only chains\n return false;\n }\n }\n return false;\n } catch {\n // Silently return false - vault existence check is non-critical\n return false;\n }\n }\n\n async createVault(userKeyHash: string, signer: ethers.Signer): Promise<VaultCreationResult> {\n // Check if vault already exists\n const exists = await this.vaultExists(userKeyHash);\n if (exists) {\n const address = await this.getVaultAddress(userKeyHash);\n if (address) {\n return {\n address,\n transactionHash: '',\n blockNumber: 0,\n gasUsed: 0n,\n alreadyExisted: true,\n };\n }\n }\n\n // Create vault using factory or hub\n let tx: ethers.TransactionResponse;\n\n if (this.factoryContract) {\n const factoryWithSigner = this.factoryContract.connect(signer) as ethers.Contract;\n tx = await factoryWithSigner.createVault(userKeyHash);\n } else {\n const hubWithSigner = this.hubContract.connect(signer) as ethers.Contract;\n tx = await hubWithSigner.createVault(userKeyHash);\n }\n\n const receipt = await tx.wait();\n if (!receipt) {\n throw new Error('Transaction failed - no receipt');\n }\n\n const vaultAddress = await this.getVaultAddress(userKeyHash);\n if (!vaultAddress) {\n throw new Error('Failed to create vault - address not found after creation');\n }\n\n return {\n address: vaultAddress,\n transactionHash: receipt.hash,\n blockNumber: receipt.blockNumber,\n gasUsed: receipt.gasUsed,\n alreadyExisted: false,\n };\n }\n\n /**\n * Create a vault with a sponsor wallet paying for gas\n * \n * @param userKeyHash - The user's passkey hash\n * @param sponsorPrivateKey - Private key of the wallet that will pay gas\n * @param rpcUrl - Optional RPC URL to use (defaults to client's RPC)\n * @returns VaultCreationResult with address and transaction details\n */\n async createVaultSponsored(\n userKeyHash: string,\n sponsorPrivateKey: string,\n rpcUrl?: string\n ): Promise<VaultCreationResult> {\n // Check if vault already exists\n const exists = await this.vaultExists(userKeyHash);\n if (exists) {\n const address = await this.getVaultAddress(userKeyHash);\n if (address) {\n return {\n address,\n transactionHash: '',\n blockNumber: 0,\n gasUsed: 0n,\n alreadyExisted: true,\n };\n }\n }\n\n // Create sponsor signer\n const provider = rpcUrl\n ? new ethers.JsonRpcProvider(rpcUrl)\n : this.provider;\n const sponsorWallet = new ethers.Wallet(sponsorPrivateKey, provider);\n\n // Check sponsor balance\n const sponsorBalance = await provider.getBalance(sponsorWallet.address);\n const estimatedGas = await this.estimateVaultCreationGas(userKeyHash);\n const feeData = await provider.getFeeData();\n const estimatedCost = estimatedGas * (feeData.gasPrice ?? 1000000000n);\n\n if (sponsorBalance < estimatedCost) {\n throw new Error(\n `Sponsor wallet has insufficient funds. ` +\n `Balance: ${ethers.formatEther(sponsorBalance)} ETH, ` +\n `Estimated cost: ${ethers.formatEther(estimatedCost)} ETH`\n );\n }\n\n // Create vault using factory or hub with sponsor wallet\n let tx: ethers.TransactionResponse;\n\n if (this.factoryContract) {\n const factoryWithSponsor = this.factoryContract.connect(sponsorWallet) as ethers.Contract;\n tx = await factoryWithSponsor.createVault(userKeyHash);\n } else {\n const hubWithSponsor = this.hubContract.connect(sponsorWallet) as ethers.Contract;\n tx = await hubWithSponsor.createVault(userKeyHash);\n }\n\n const receipt = await tx.wait();\n if (!receipt) {\n throw new Error('Transaction failed - no receipt');\n }\n\n const vaultAddress = await this.getVaultAddress(userKeyHash);\n if (!vaultAddress) {\n throw new Error('Failed to create vault - address not found after creation');\n }\n\n return {\n address: vaultAddress,\n transactionHash: receipt.hash,\n blockNumber: receipt.blockNumber,\n gasUsed: receipt.gasUsed,\n alreadyExisted: false,\n sponsoredBy: sponsorWallet.address,\n };\n }\n\n async estimateVaultCreationGas(userKeyHash: string): Promise<bigint> {\n try {\n if (this.factoryContract) {\n return await this.factoryContract.createVault.estimateGas(userKeyHash);\n }\n return await this.hubContract.createVault.estimateGas(userKeyHash);\n } catch (error) {\n // Return a default estimate if estimation fails (vault might already exist)\n console.warn('Gas estimation failed, returning default:', error);\n return 150000n; // Default estimate for vault creation\n }\n }\n\n getFactoryAddress(): string | undefined {\n return this.config.contracts.vaultFactory;\n }\n\n getImplementationAddress(): string | undefined {\n return this.config.contracts.vaultImplementation ?? this.cachedImplementation ?? undefined;\n }\n\n /**\n * Fetch implementation address from factory contract\n */\n async fetchImplementationAddress(): Promise<string | null> {\n if (this.cachedImplementation) {\n return this.cachedImplementation;\n }\n\n if (!this.factoryContract) {\n return null;\n }\n\n try {\n this.cachedImplementation = await this.factoryContract.implementation();\n return this.cachedImplementation;\n } catch (error) {\n console.error('Error fetching implementation address:', error);\n return null;\n }\n }\n\n /**\n * Get the provider instance\n */\n getProvider(): ethers.JsonRpcProvider {\n return this.provider;\n }\n\n // ========================================================================\n // Balance Methods (Phase 2)\n // ========================================================================\n\n /**\n * Get native token balance for an address\n */\n async getNativeBalance(address: string): Promise<bigint> {\n return await this.provider.getBalance(address);\n }\n\n /**\n * Get ERC20 token balance for an address\n */\n async getTokenBalance(tokenAddress: string, ownerAddress: string): Promise<bigint> {\n const contract = new ethers.Contract(tokenAddress, ERC20_ABI, this.provider);\n return await contract.balanceOf(ownerAddress);\n }\n\n /**\n * Get token allowance\n */\n async getTokenAllowance(\n tokenAddress: string,\n ownerAddress: string,\n spenderAddress: string\n ): Promise<bigint> {\n const contract = new ethers.Contract(tokenAddress, ERC20_ABI, this.provider);\n return await contract.allowance(ownerAddress, spenderAddress);\n }\n\n /**\n * Estimate gas for a dispatch transaction\n */\n async estimateDispatchGas(\n signature: WebAuthnSignature,\n publicKeyX: bigint,\n publicKeyY: bigint,\n targetChain: number,\n actionPayload: string,\n nonce: bigint\n ): Promise<bigint> {\n const signatureTuple = {\n authenticatorData: signature.authenticatorData,\n clientDataJSON: signature.clientDataJSON,\n challengeIndex: signature.challengeIndex,\n typeIndex: signature.typeIndex,\n r: signature.r,\n s: signature.s,\n };\n\n const messageFee = await this.getMessageFee();\n\n try {\n const gasEstimate = await this.hubContract.dispatch.estimateGas(\n signatureTuple,\n publicKeyX,\n publicKeyY,\n targetChain,\n actionPayload,\n nonce,\n { value: messageFee }\n );\n return gasEstimate;\n } catch (error) {\n console.warn('Gas estimation failed, using default:', error);\n return 500000n; // Default estimate for dispatch\n }\n }\n\n /**\n * Get current gas price\n */\n async getGasPrice(): Promise<bigint> {\n const feeData = await this.provider.getFeeData();\n return feeData.gasPrice ?? feeData.maxFeePerGas ?? 0n;\n }\n\n /**\n * Get current block number\n */\n async getBlockNumber(): Promise<number> {\n return await this.provider.getBlockNumber();\n }\n\n /**\n * Get transaction receipt\n */\n async getTransactionReceipt(hash: string): Promise<ethers.TransactionReceipt | null> {\n return await this.provider.getTransactionReceipt(hash);\n }\n\n /**\n * Wait for transaction confirmation\n */\n async waitForTransaction(\n hash: string,\n confirmations: number = 1\n ): Promise<ethers.TransactionReceipt | null> {\n return await this.provider.waitForTransaction(hash, confirmations);\n }\n\n // ==========================================================================\n // Backup Passkey / Multi-Key Identity Methods (Issue #22)\n // ==========================================================================\n\n /**\n * Get the identity for a given key hash\n * Returns zero hash if key is not registered to any identity\n * \n * @param keyHash Hash of the passkey to look up\n * @returns Identity (first passkey's keyHash) or zero hash\n */\n async getIdentityForKey(keyHash: string): Promise<string> {\n try {\n return await this.hubContract.getIdentityForKey(keyHash);\n } catch (error) {\n return ethers.ZeroHash;\n }\n }\n\n /**\n * Get all authorized keys for an identity\n * \n * @param identity The identity key hash (first passkey's keyHash)\n * @returns Array of authorized key hashes\n */\n async getAuthorizedKeys(identity: string): Promise<string[]> {\n try {\n return await this.hubContract.getAuthorizedKeys(identity);\n } catch (error) {\n return [];\n }\n }\n\n /**\n * Get count of authorized keys for an identity\n * \n * @param identity The identity key hash\n * @returns Number of authorized keys\n */\n async getAuthorizedKeyCount(identity: string): Promise<number> {\n try {\n const count = await this.hubContract.getAuthorizedKeyCount(identity);\n return Number(count);\n } catch (error) {\n return 0;\n }\n }\n\n /**\n * Check if a key is authorized for an identity\n * \n * @param identity The identity key hash\n * @param keyHash The key hash to check\n * @returns Whether the key is authorized\n */\n async isAuthorizedForIdentity(identity: string, keyHash: string): Promise<boolean> {\n try {\n return await this.hubContract.isAuthorizedForIdentity(identity, keyHash);\n } catch (error) {\n return false;\n }\n }\n\n /**\n * Check if a key is the root identity key\n * \n * @param keyHash The key hash to check\n * @returns Whether the key is a root identity\n */\n async isIdentityRootKey(keyHash: string): Promise<boolean> {\n try {\n return await this.hubContract.isIdentityRoot(keyHash);\n } catch (error) {\n return false;\n }\n }\n\n /**\n * Get comprehensive identity state for a key\n * \n * @param keyHash Hash of any key in the identity\n * @returns Identity state including count, max, and root status\n */\n async getIdentityState(keyHash: string): Promise<import('../../types.js').IdentityState> {\n try {\n const result = await this.hubContract.getIdentityState(keyHash);\n return {\n identity: result[0],\n keyCount: Number(result[1]),\n maxKeys: Number(result[2]),\n isRoot: result[3],\n };\n } catch (error) {\n // Fallback for keys not registered\n return {\n identity: ethers.ZeroHash,\n keyCount: 0,\n maxKeys: 5,\n isRoot: false,\n };\n }\n }\n\n /**\n * Register a new identity with the first passkey\n * This makes the passkey the root identity key\n * \n * @param signature WebAuthn signature\n * @param publicKeyX Passkey public key X coordinate\n * @param publicKeyY Passkey public key Y coordinate\n * @param signer Ethereum signer to pay gas\n * @returns Transaction receipt and identity hash\n */\n async registerIdentity(\n signature: WebAuthnSignature,\n publicKeyX: bigint,\n publicKeyY: bigint,\n signer: ethers.Signer\n ): Promise<{ receipt: ethers.TransactionReceipt; identity: string }> {\n const hubWithSigner = this.hubContract.connect(signer) as any;\n\n const authTuple = {\n authenticatorData: signature.authenticatorData,\n clientDataJSON: signature.clientDataJSON,\n challengeIndex: signature.challengeIndex,\n typeIndex: signature.typeIndex,\n r: signature.r,\n s: signature.s,\n };\n\n const tx = await hubWithSigner.registerIdentity(\n authTuple,\n publicKeyX,\n publicKeyY\n );\n\n const receipt = await tx.wait();\n \n // Compute identity (keyHash of the registered key)\n const keyHash = ethers.keccak256(\n ethers.solidityPacked(['uint256', 'uint256'], [publicKeyX, publicKeyY])\n );\n\n return { receipt, identity: keyHash };\n }\n\n /**\n * Add a backup passkey to an existing identity\n * Requires WebAuthn signature from an authorized key\n * \n * @param signature WebAuthn signature from existing authorized key\n * @param publicKeyX Existing key's X coordinate\n * @param publicKeyY Existing key's Y coordinate\n * @param newPublicKeyX New backup key's X coordinate\n * @param newPublicKeyY New backup key's Y coordinate\n * @param nonce Current nonce for the signing key\n * @param signer Ethereum signer to pay gas\n * @returns Transaction receipt and sequence number\n */\n async addBackupKey(\n signature: WebAuthnSignature,\n publicKeyX: bigint,\n publicKeyY: bigint,\n newPublicKeyX: bigint,\n newPublicKeyY: bigint,\n nonce: bigint,\n signer: ethers.Signer\n ): Promise<{ receipt: ethers.TransactionReceipt; sequence: bigint }> {\n const hubWithSigner = this.hubContract.connect(signer) as any;\n\n const authTuple = {\n authenticatorData: signature.authenticatorData,\n clientDataJSON: signature.clientDataJSON,\n challengeIndex: signature.challengeIndex,\n typeIndex: signature.typeIndex,\n r: signature.r,\n s: signature.s,\n };\n\n const messageFee = await this.getMessageFee();\n\n const tx = await hubWithSigner.addBackupKey(\n authTuple,\n publicKeyX,\n publicKeyY,\n newPublicKeyX,\n newPublicKeyY,\n nonce,\n { value: messageFee }\n );\n\n const receipt = await tx.wait();\n\n // Extract sequence from Dispatch event\n let sequence = 0n;\n for (const log of receipt.logs) {\n try {\n const parsed = this.hubContract.interface.parseLog({\n topics: log.topics as string[],\n data: log.data,\n });\n if (parsed?.name === 'Dispatched') {\n sequence = BigInt(parsed.args[3]); // sequence is 4th arg\n break;\n }\n } catch {\n // Not a Hub event, skip\n }\n }\n\n return { receipt, sequence };\n }\n\n /**\n * Remove a passkey from an identity\n * Cannot remove the last remaining key\n * \n * @param signature WebAuthn signature from an authorized key\n * @param publicKeyX Signing key's X coordinate\n * @param publicKeyY Signing key's Y coordinate\n * @param keyToRemove Hash of the key to remove\n * @param nonce Current nonce for the signing key\n * @param signer Ethereum signer to pay gas\n * @returns Transaction receipt and sequence number\n */\n async removeKey(\n signature: WebAuthnSignature,\n publicKeyX: bigint,\n publicKeyY: bigint,\n keyToRemove: string,\n nonce: bigint,\n signer: ethers.Signer\n ): Promise<{ receipt: ethers.TransactionReceipt; sequence: bigint }> {\n const hubWithSigner = this.hubContract.connect(signer) as any;\n\n const authTuple = {\n authenticatorData: signature.authenticatorData,\n clientDataJSON: signature.clientDataJSON,\n challengeIndex: signature.challengeIndex,\n typeIndex: signature.typeIndex,\n r: signature.r,\n s: signature.s,\n };\n\n const messageFee = await this.getMessageFee();\n\n const tx = await hubWithSigner.removeKey(\n authTuple,\n publicKeyX,\n publicKeyY,\n keyToRemove,\n nonce,\n { value: messageFee }\n );\n\n const receipt = await tx.wait();\n\n // Extract sequence from Dispatch event\n let sequence = 0n;\n for (const log of receipt.logs) {\n try {\n const parsed = this.hubContract.interface.parseLog({\n topics: log.topics as string[],\n data: log.data,\n });\n if (parsed?.name === 'Dispatched') {\n sequence = BigInt(parsed.args[3]);\n break;\n }\n } catch {\n // Not a Hub event, skip\n }\n }\n\n return { receipt, sequence };\n }\n\n // =========================================================================\n // SOCIAL RECOVERY METHODS (Issue #23)\n // =========================================================================\n\n /**\n * Setup guardians for an identity\n * @param signature WebAuthn signature from owner\n * @param publicKeyX Owner's public key X coordinate\n * @param publicKeyY Owner's public key Y coordinate\n * @param guardians Array of guardian key hashes\n * @param threshold Required approvals for recovery\n * @param signer Ethers signer for transaction\n */\n async setupGuardians(\n signature: WebAuthnSignature,\n publicKeyX: bigint,\n publicKeyY: bigint,\n guardians: string[],\n threshold: bigint,\n signer: ethers.Signer\n ): Promise<{ receipt: ethers.TransactionReceipt; sequence: bigint }> {\n const hubWithSigner = this.hubContract.connect(signer) as any;\n\n const authTuple = {\n authenticatorData: signature.authenticatorData,\n clientDataJSON: signature.clientDataJSON,\n challengeIndex: signature.challengeIndex,\n typeIndex: signature.typeIndex,\n r: signature.r,\n s: signature.s,\n };\n\n const messageFee = await this.getMessageFee();\n\n const tx = await hubWithSigner.setupGuardians(\n authTuple,\n publicKeyX,\n publicKeyY,\n guardians,\n threshold,\n { value: messageFee }\n );\n\n const receipt = await tx.wait();\n const sequence = this._extractSequenceFromReceipt(receipt);\n\n return { receipt, sequence };\n }\n\n /**\n * Add a guardian to an identity\n */\n async addGuardian(\n signature: WebAuthnSignature,\n publicKeyX: bigint,\n publicKeyY: bigint,\n guardianKeyHash: string,\n signer: ethers.Signer\n ): Promise<{ receipt: ethers.TransactionReceipt; sequence: bigint }> {\n const hubWithSigner = this.hubContract.connect(signer) as any;\n\n const authTuple = {\n authenticatorData: signature.authenticatorData,\n clientDataJSON: signature.clientDataJSON,\n challengeIndex: signature.challengeIndex,\n typeIndex: signature.typeIndex,\n r: signature.r,\n s: signature.s,\n };\n\n const messageFee = await this.getMessageFee();\n\n const tx = await hubWithSigner.addGuardian(\n authTuple,\n publicKeyX,\n publicKeyY,\n guardianKeyHash,\n { value: messageFee }\n );\n\n const receipt = await tx.wait();\n const sequence = this._extractSequenceFromReceipt(receipt);\n\n return { receipt, sequence };\n }\n\n /**\n * Remove a guardian from an identity\n */\n async removeGuardian(\n signature: WebAuthnSignature,\n publicKeyX: bigint,\n publicKeyY: bigint,\n guardianKeyHash: string,\n signer: ethers.Signer\n ): Promise<{ receipt: ethers.TransactionReceipt; sequence: bigint }> {\n const hubWithSigner = this.hubContract.connect(signer) as any;\n\n const authTuple = {\n authenticatorData: signature.authenticatorData,\n clientDataJSON: signature.clientDataJSON,\n challengeIndex: signature.challengeIndex,\n typeIndex: signature.typeIndex,\n r: signature.r,\n s: signature.s,\n };\n\n const messageFee = await this.getMessageFee();\n\n const tx = await hubWithSigner.removeGuardian(\n authTuple,\n publicKeyX,\n publicKeyY,\n guardianKeyHash,\n { value: messageFee }\n );\n\n const receipt = await tx.wait();\n const sequence = this._extractSequenceFromReceipt(receipt);\n\n return { receipt, sequence };\n }\n\n /**\n * Initiate recovery as a guardian\n */\n async initiateRecovery(\n signature: WebAuthnSignature,\n publicKeyX: bigint,\n publicKeyY: bigint,\n identityToRecover: string,\n newOwnerKeyHash: string,\n signer: ethers.Signer\n ): Promise<{ receipt: ethers.TransactionReceipt; sequence: bigint }> {\n const hubWithSigner = this.hubContract.connect(signer) as any;\n\n const authTuple = {\n authenticatorData: signature.authenticatorData,\n clientDataJSON: signature.clientDataJSON,\n challengeIndex: signature.challengeIndex,\n typeIndex: signature.typeIndex,\n r: signature.r,\n s: signature.s,\n };\n\n const messageFee = await this.getMessageFee();\n\n const tx = await hubWithSigner.initiateRecovery(\n authTuple,\n publicKeyX,\n publicKeyY,\n identityToRecover,\n newOwnerKeyHash,\n { value: messageFee }\n );\n\n const receipt = await tx.wait();\n const sequence = this._extractSequenceFromReceipt(receipt);\n\n return { receipt, sequence };\n }\n\n /**\n * Approve recovery as a guardian\n */\n async approveRecovery(\n signature: WebAuthnSignature,\n publicKeyX: bigint,\n publicKeyY: bigint,\n identityToRecover: string,\n signer: ethers.Signer\n ): Promise<{ receipt: ethers.TransactionReceipt; sequence: bigint }> {\n const hubWithSigner = this.hubContract.connect(signer) as any;\n\n const authTuple = {\n authenticatorData: signature.authenticatorData,\n clientDataJSON: signature.clientDataJSON,\n challengeIndex: signature.challengeIndex,\n typeIndex: signature.typeIndex,\n r: signature.r,\n s: signature.s,\n };\n\n const messageFee = await this.getMessageFee();\n\n const tx = await hubWithSigner.approveRecovery(\n authTuple,\n publicKeyX,\n publicKeyY,\n identityToRecover,\n { value: messageFee }\n );\n\n const receipt = await tx.wait();\n const sequence = this._extractSequenceFromReceipt(receipt);\n\n return { receipt, sequence };\n }\n\n /**\n * Execute recovery after timelock (anyone can call)\n */\n async executeRecovery(\n identityToRecover: string,\n newPublicKeyX: bigint,\n newPublicKeyY: bigint,\n signer: ethers.Signer\n ): Promise<{ receipt: ethers.TransactionReceipt; sequence: bigint }> {\n const hubWithSigner = this.hubContract.connect(signer) as any;\n\n const messageFee = await this.getMessageFee();\n\n const tx = await hubWithSigner.executeRecovery(\n identityToRecover,\n newPublicKeyX,\n newPublicKeyY,\n { value: messageFee }\n );\n\n const receipt = await tx.wait();\n const sequence = this._extractSequenceFromReceipt(receipt);\n\n return { receipt, sequence };\n }\n\n /**\n * Cancel recovery as owner\n */\n async cancelRecovery(\n signature: WebAuthnSignature,\n publicKeyX: bigint,\n publicKeyY: bigint,\n signer: ethers.Signer\n ): Promise<{ receipt: ethers.TransactionReceipt; sequence: bigint }> {\n const hubWithSigner = this.hubContract.connect(signer) as any;\n\n const authTuple = {\n authenticatorData: signature.authenticatorData,\n clientDataJSON: signature.clientDataJSON,\n challengeIndex: signature.challengeIndex,\n typeIndex: signature.typeIndex,\n r: signature.r,\n s: signature.s,\n };\n\n const messageFee = await this.getMessageFee();\n\n const tx = await hubWithSigner.cancelRecovery(\n authTuple,\n publicKeyX,\n publicKeyY,\n { value: messageFee }\n );\n\n const receipt = await tx.wait();\n const sequence = this._extractSequenceFromReceipt(receipt);\n\n return { receipt, sequence };\n }\n\n /**\n * Get guardians for an identity\n */\n async getGuardians(identityKeyHash: string): Promise<{\n guardians: string[];\n threshold: bigint;\n isConfigured: boolean;\n }> {\n const result = await this.hubContract.getGuardians(identityKeyHash);\n return {\n guardians: result.guardians,\n threshold: result.threshold,\n isConfigured: result.isConfigured,\n };\n }\n\n /**\n * Get recovery status for an identity\n */\n async getRecoveryStatus(identityKeyHash: string): Promise<{\n isActive: boolean;\n newOwnerKeyHash: string;\n initiatedAt: bigint;\n approvalCount: bigint;\n threshold: bigint;\n canExecuteAt: bigint;\n expiresAt: bigint;\n }> {\n const result = await this.hubContract.getRecoveryStatus(identityKeyHash);\n return {\n isActive: result.isActive,\n newOwnerKeyHash: result.newOwnerKeyHash,\n initiatedAt: result.initiatedAt,\n approvalCount: result.approvalCount,\n threshold: result.threshold,\n canExecuteAt: result.canExecuteAt,\n expiresAt: result.expiresAt,\n };\n }\n\n /**\n * Check if a guardian has approved recovery\n */\n async hasGuardianApproved(\n identityKeyHash: string,\n guardianKeyHash: string\n ): Promise<boolean> {\n return this.hubContract.hasGuardianApproved(identityKeyHash, guardianKeyHash);\n }\n\n /**\n * Helper to extract sequence from transaction receipt\n */\n private _extractSequenceFromReceipt(receipt: ethers.TransactionReceipt): bigint {\n for (const log of receipt.logs) {\n try {\n const parsed = this.hubContract.interface.parseLog({\n topics: log.topics as string[],\n data: log.data,\n });\n if (parsed?.name === 'Dispatch') {\n return BigInt(parsed.args.sequence);\n }\n } catch {\n // Not a Hub event, skip\n }\n }\n return 0n;\n }\n}\n","/**\n * Veridex Protocol SDK - Chain Presets\n * \n * Pre-configured chain settings for easy SDK initialization.\n * Developers only need to specify chain name and network type.\n * \n * @example\n * ```typescript\n * import { createSDK } from '@veridex/sdk';\n * \n * // Simple initialization - testnet by default\n * const sdk = await createSDK('base');\n * \n * // Or specify mainnet\n * const mainnetSdk = await createSDK('base', { network: 'mainnet' });\n * ```\n */\n\nimport type { ChainConfig } from './types.js';\n\n// ============================================================================\n// Supported Chain Names\n// ============================================================================\n\n/**\n * All supported chain names for easy reference\n */\nexport const CHAIN_NAMES = {\n // EVM L2s (Hub-capable)\n BASE: 'base',\n OPTIMISM: 'optimism',\n ARBITRUM: 'arbitrum',\n SCROLL: 'scroll',\n BLAST: 'blast',\n MANTLE: 'mantle',\n \n // EVM L1s\n ETHEREUM: 'ethereum',\n POLYGON: 'polygon',\n BSC: 'bsc',\n AVALANCHE: 'avalanche',\n FANTOM: 'fantom',\n CELO: 'celo',\n MOONBEAM: 'moonbeam',\n \n // Non-EVM\n SOLANA: 'solana',\n APTOS: 'aptos',\n SUI: 'sui',\n STARKNET: 'starknet',\n NEAR: 'near',\n SEI: 'sei',\n} as const;\n\nexport type ChainName = typeof CHAIN_NAMES[keyof typeof CHAIN_NAMES];\nexport type NetworkType = 'mainnet' | 'testnet';\n\n// ============================================================================\n// Chain Preset Interface\n// ============================================================================\n\nexport interface ChainPreset {\n /** Human-readable chain name */\n displayName: string;\n /** Chain type for client selection */\n type: 'evm' | 'solana' | 'aptos' | 'sui' | 'starknet' | 'near' | 'cosmos';\n /** Whether this chain can be a hub */\n canBeHub: boolean;\n /** Testnet configuration */\n testnet: ChainConfig;\n /** Mainnet configuration */\n mainnet: ChainConfig;\n}\n\n// ============================================================================\n// EVM Chain Presets\n// ============================================================================\n\nexport const CHAIN_PRESETS: Record<ChainName, ChainPreset> = {\n // ────────────────────────────────────────────────────────────────────────\n // BASE - Primary Hub Chain\n // ────────────────────────────────────────────────────────────────────────\n base: {\n displayName: 'Base',\n type: 'evm',\n canBeHub: true,\n testnet: {\n name: 'Base Sepolia',\n chainId: 84532,\n wormholeChainId: 10004,\n rpcUrl: 'https://sepolia.base.org',\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 mainnet: {\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 // TODO: Deploy mainnet contracts\n wormholeCoreBridge: '0xbebdb6C8ddC678FfA9f8748f85C815C556Dd8ac6',\n tokenBridge: '0x8d2de8d2f73F1F4cAB472AC9A881C9b123C79627',\n },\n },\n },\n\n // ────────────────────────────────────────────────────────────────────────\n // OPTIMISM - Secondary Hub / Spoke\n // ────────────────────────────────────────────────────────────────────────\n optimism: {\n displayName: 'Optimism',\n type: 'evm',\n canBeHub: true,\n testnet: {\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 mainnet: {\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 },\n\n // ────────────────────────────────────────────────────────────────────────\n // ARBITRUM\n // ────────────────────────────────────────────────────────────────────────\n arbitrum: {\n displayName: 'Arbitrum',\n type: 'evm',\n canBeHub: true,\n testnet: {\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 mainnet: {\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 },\n\n // ────────────────────────────────────────────────────────────────────────\n // ETHEREUM\n // ────────────────────────────────────────────────────────────────────────\n ethereum: {\n displayName: 'Ethereum',\n type: 'evm',\n canBeHub: false,\n testnet: {\n name: 'Sepolia',\n chainId: 11155111,\n wormholeChainId: 10002,\n rpcUrl: 'https://rpc.sepolia.org',\n explorerUrl: 'https://sepolia.etherscan.io',\n isEvm: true,\n contracts: {\n wormholeCoreBridge: '0x4a8bc80Ed5a4067f1CCf107057b8270E0cC11A78',\n tokenBridge: '0xDB5492265f6038831E89f495670FF909aDe94bd9',\n },\n },\n mainnet: {\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 },\n\n // ────────────────────────────────────────────────────────────────────────\n // POLYGON\n // ────────────────────────────────────────────────────────────────────────\n polygon: {\n displayName: 'Polygon',\n type: 'evm',\n canBeHub: false,\n testnet: {\n name: 'Polygon Amoy',\n chainId: 80002,\n wormholeChainId: 10007,\n rpcUrl: 'https://rpc-amoy.polygon.technology',\n explorerUrl: 'https://amoy.polygonscan.com',\n isEvm: true,\n contracts: {\n wormholeCoreBridge: '0x0CBE91CF822c73C2315FB05100C2F714765d5c20',\n tokenBridge: '0x0290FB167208Af455bB137780163b7B7a9a10C16',\n },\n },\n mainnet: {\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 },\n\n // ────────────────────────────────────────────────────────────────────────\n // BSC\n // ────────────────────────────────────────────────────────────────────────\n bsc: {\n displayName: 'BNB Chain',\n type: 'evm',\n canBeHub: false,\n testnet: {\n name: 'BSC Testnet',\n chainId: 97,\n wormholeChainId: 4,\n rpcUrl: 'https://data-seed-prebsc-1-s1.binance.org:8545',\n explorerUrl: 'https://testnet.bscscan.com',\n isEvm: true,\n contracts: {\n wormholeCoreBridge: '0x68605AD7b15c732a30b1BbC62BE8F2A509D74b4D',\n tokenBridge: '0x9dcF9D205C9De35334D646BeE44b2D2859712A09',\n },\n },\n mainnet: {\n name: 'BNB Chain',\n chainId: 56,\n wormholeChainId: 4,\n rpcUrl: 'https://bsc-dataseed.binance.org',\n explorerUrl: 'https://bscscan.com',\n isEvm: true,\n contracts: {\n wormholeCoreBridge: '0x98f3c9e6E3fAce36bAAd05FE09d375Ef1464288B',\n tokenBridge: '0xB6F6D86a8f9879A9c87f643768d9efc38c1Da6E7',\n },\n },\n },\n\n // ────────────────────────────────────────────────────────────────────────\n // AVALANCHE\n // ────────────────────────────────────────────────────────────────────────\n avalanche: {\n displayName: 'Avalanche',\n type: 'evm',\n canBeHub: false,\n testnet: {\n name: 'Avalanche Fuji',\n chainId: 43113,\n wormholeChainId: 6,\n rpcUrl: 'https://api.avax-test.network/ext/bc/C/rpc',\n explorerUrl: 'https://testnet.snowtrace.io',\n isEvm: true,\n contracts: {\n wormholeCoreBridge: '0x7bbcE28e64B3F8b84d876Ab298393c38ad7aac4C',\n tokenBridge: '0x61E44E506Ca5659E6c0bba9b678586fA2d729756',\n },\n },\n mainnet: {\n name: 'Avalanche',\n chainId: 43114,\n wormholeChainId: 6,\n rpcUrl: 'https://api.avax.network/ext/bc/C/rpc',\n explorerUrl: 'https://snowtrace.io',\n isEvm: true,\n contracts: {\n wormholeCoreBridge: '0x54a8e5f9c4CbA08F9943965859F6c34eAF03E26c',\n tokenBridge: '0x0e082F06FF657D94310cB8cE8B0D9a04541d8052',\n },\n },\n },\n\n // ────────────────────────────────────────────────────────────────────────\n // SCROLL\n // ────────────────────────────────────────────────────────────────────────\n scroll: {\n displayName: 'Scroll',\n type: 'evm',\n canBeHub: false,\n testnet: {\n name: 'Scroll Sepolia',\n chainId: 534351,\n wormholeChainId: 34,\n rpcUrl: 'https://sepolia-rpc.scroll.io',\n explorerUrl: 'https://sepolia.scrollscan.com',\n isEvm: true,\n contracts: {\n wormholeCoreBridge: '0x055F47F1250012C6B20c436570a76e52c17Af2D5',\n tokenBridge: '0x22427d90B7dA3fA4642F7025A854c7254E4e45BF',\n },\n },\n mainnet: {\n name: 'Scroll',\n chainId: 534352,\n wormholeChainId: 34,\n rpcUrl: 'https://rpc.scroll.io',\n explorerUrl: 'https://scrollscan.com',\n isEvm: true,\n contracts: {\n wormholeCoreBridge: '0xbebdb6C8ddC678FfA9f8748f85C815C556Dd8ac6',\n tokenBridge: '0x24850c6f61C438823F01B7A3BF2B89B72174Fa9d',\n },\n },\n },\n\n // ────────────────────────────────────────────────────────────────────────\n // BLAST\n // ────────────────────────────────────────────────────────────────────────\n blast: {\n displayName: 'Blast',\n type: 'evm',\n canBeHub: false,\n testnet: {\n name: 'Blast Sepolia',\n chainId: 168587773,\n wormholeChainId: 36,\n rpcUrl: 'https://sepolia.blast.io',\n explorerUrl: 'https://sepolia.blastscan.io',\n isEvm: true,\n contracts: {\n wormholeCoreBridge: '0x473e002D7add6fB67a4964F13bFd61280Ca46886',\n tokenBridge: '0x430855B4D43b8AEB9D2B9869B74d58dda79C0dB2',\n },\n },\n mainnet: {\n name: 'Blast',\n chainId: 81457,\n wormholeChainId: 36,\n rpcUrl: 'https://rpc.blast.io',\n explorerUrl: 'https://blastscan.io',\n isEvm: true,\n contracts: {\n wormholeCoreBridge: '0xbebdb6C8ddC678FfA9f8748f85C815C556Dd8ac6',\n tokenBridge: '0x24850c6f61C438823F01B7A3BF2B89B72174Fa9d',\n },\n },\n },\n\n // ────────────────────────────────────────────────────────────────────────\n // MANTLE\n // ────────────────────────────────────────────────────────────────────────\n mantle: {\n displayName: 'Mantle',\n type: 'evm',\n canBeHub: false,\n testnet: {\n name: 'Mantle Sepolia',\n chainId: 5003,\n wormholeChainId: 35,\n rpcUrl: 'https://rpc.sepolia.mantle.xyz',\n explorerUrl: 'https://sepolia.mantlescan.xyz',\n isEvm: true,\n contracts: {\n wormholeCoreBridge: '0x376428e7f26D5867e69201b275553C45B09EE090',\n tokenBridge: '0x75Bfa155a9D7A3714b0861c8a8aF0C4633c45b5D',\n },\n },\n mainnet: {\n name: 'Mantle',\n chainId: 5000,\n wormholeChainId: 35,\n rpcUrl: 'https://rpc.mantle.xyz',\n explorerUrl: 'https://mantlescan.xyz',\n isEvm: true,\n contracts: {\n wormholeCoreBridge: '0xbebdb6C8ddC678FfA9f8748f85C815C556Dd8ac6',\n tokenBridge: '0x24850c6f61C438823F01B7A3BF2B89B72174Fa9d',\n },\n },\n },\n\n // ────────────────────────────────────────────────────────────────────────\n // FANTOM\n // ────────────────────────────────────────────────────────────────────────\n fantom: {\n displayName: 'Fantom',\n type: 'evm',\n canBeHub: false,\n testnet: {\n name: 'Fantom Testnet',\n chainId: 4002,\n wormholeChainId: 10,\n rpcUrl: 'https://rpc.testnet.fantom.network',\n explorerUrl: 'https://testnet.ftmscan.com',\n isEvm: true,\n contracts: {\n wormholeCoreBridge: '0x1BB3B4119b7BA9dfad76B0545fb3F531383c3bB7',\n tokenBridge: '0x599CEa2204B4FaECd584Ab1F2b6aCA137a0afbE8',\n },\n },\n mainnet: {\n name: 'Fantom',\n chainId: 250,\n wormholeChainId: 10,\n rpcUrl: 'https://rpcapi.fantom.network',\n explorerUrl: 'https://ftmscan.com',\n isEvm: true,\n contracts: {\n wormholeCoreBridge: '0x126783A6Cb203a3E35344528B26ca3a0489a1485',\n tokenBridge: '0x7C9Fc5741288cDFdD83CeB07f3ea7e22618D79D2',\n },\n },\n },\n\n // ────────────────────────────────────────────────────────────────────────\n // CELO\n // ────────────────────────────────────────────────────────────────────────\n celo: {\n displayName: 'Celo',\n type: 'evm',\n canBeHub: false,\n testnet: {\n name: 'Celo Alfajores',\n chainId: 44787,\n wormholeChainId: 14,\n rpcUrl: 'https://alfajores-forno.celo-testnet.org',\n explorerUrl: 'https://alfajores.celoscan.io',\n isEvm: true,\n contracts: {\n wormholeCoreBridge: '0x88505117CA88e7dd2eC6EA1E13f0948db2D50D56',\n tokenBridge: '0x05ca6037eC51F8b712eD2E6Fa72219FEaE74E153',\n },\n },\n mainnet: {\n name: 'Celo',\n chainId: 42220,\n wormholeChainId: 14,\n rpcUrl: 'https://forno.celo.org',\n explorerUrl: 'https://celoscan.io',\n isEvm: true,\n contracts: {\n wormholeCoreBridge: '0xa321448d90d4e5b0A732867c18eA198e75CAC48E',\n tokenBridge: '0x796Dff6D74F3E27060B71255Fe517BFb23C93eed',\n },\n },\n },\n\n // ────────────────────────────────────────────────────────────────────────\n // MOONBEAM\n // ────────────────────────────────────────────────────────────────────────\n moonbeam: {\n displayName: 'Moonbeam',\n type: 'evm',\n canBeHub: false,\n testnet: {\n name: 'Moonbase Alpha',\n chainId: 1287,\n wormholeChainId: 16,\n rpcUrl: 'https://rpc.api.moonbase.moonbeam.network',\n explorerUrl: 'https://moonbase.moonscan.io',\n isEvm: true,\n contracts: {\n wormholeCoreBridge: '0xa5B7D85a8f27dd7907dc8FdC21FA5657D5E2F901',\n tokenBridge: '0xbc976D4b9D57E57c3cA52e1Fd136C45FF7955A96',\n },\n },\n mainnet: {\n name: 'Moonbeam',\n chainId: 1284,\n wormholeChainId: 16,\n rpcUrl: 'https://rpc.api.moonbeam.network',\n explorerUrl: 'https://moonscan.io',\n isEvm: true,\n contracts: {\n wormholeCoreBridge: '0xC8e2b0cD52Cf01b0Ce87d389Daa3d414d4cE29f3',\n tokenBridge: '0xb1731c586ca89a23809861c6103F0b96B3F57D92',\n },\n },\n },\n\n // ────────────────────────────────────────────────────────────────────────\n // SEI\n // ────────────────────────────────────────────────────────────────────────\n sei: {\n displayName: 'Sei',\n type: 'evm',\n canBeHub: false,\n testnet: {\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',\n },\n },\n mainnet: {\n name: 'Sei',\n chainId: 1329,\n wormholeChainId: 32,\n rpcUrl: 'https://evm-rpc.sei-apis.com',\n explorerUrl: 'https://seitrace.com',\n isEvm: true,\n contracts: {\n wormholeCoreBridge: '0x0000000000000000000000000000000000000000',\n },\n },\n },\n\n // ────────────────────────────────────────────────────────────────────────\n // SOLANA\n // ────────────────────────────────────────────────────────────────────────\n solana: {\n displayName: 'Solana',\n type: 'solana',\n canBeHub: false,\n testnet: {\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 mainnet: {\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 },\n\n // ────────────────────────────────────────────────────────────────────────\n // APTOS\n // ────────────────────────────────────────────────────────────────────────\n aptos: {\n displayName: 'Aptos',\n type: 'aptos',\n canBeHub: false,\n testnet: {\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 mainnet: {\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 },\n\n // ────────────────────────────────────────────────────────────────────────\n // SUI\n // ────────────────────────────────────────────────────────────────────────\n sui: {\n displayName: 'Sui',\n type: 'sui',\n canBeHub: false,\n testnet: {\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 mainnet: {\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 // STARKNET\n // ────────────────────────────────────────────────────────────────────────\n starknet: {\n displayName: 'Starknet',\n type: 'starknet',\n canBeHub: false,\n testnet: {\n name: 'Starknet Sepolia',\n chainId: 0,\n wormholeChainId: 50001, // Custom bridge (non-Wormhole)\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 hub: '0x68adcc730ed6c355200d00f763825448497b9cdf7936ca121711e078c88e811',\n wormholeCoreBridge: '0x2c458c1ae64556482b05cc2d3ee5b032ed114d68429dda2062c9849a5a725f8',\n },\n hubChainId: 10004, // Base Sepolia\n },\n mainnet: {\n name: 'Starknet',\n chainId: 0,\n wormholeChainId: 50001,\n rpcUrl: 'https://starknet-mainnet.public.blastapi.io/rpc/v0_7',\n explorerUrl: 'https://starkscan.co',\n isEvm: false,\n contracts: {\n // TODO: Deploy mainnet contracts\n wormholeCoreBridge: '',\n },\n },\n },\n\n // ────────────────────────────────────────────────────────────────────────\n // NEAR\n // ────────────────────────────────────────────────────────────────────────\n near: {\n displayName: 'Near',\n type: 'near',\n canBeHub: false,\n testnet: {\n name: 'Near Testnet',\n chainId: 0,\n wormholeChainId: 15,\n rpcUrl: 'https://rpc.testnet.near.org',\n explorerUrl: 'https://explorer.testnet.near.org',\n isEvm: false,\n contracts: {\n wormholeCoreBridge: 'wormhole.wormhole.testnet',\n tokenBridge: 'token.wormhole.testnet',\n },\n },\n mainnet: {\n name: 'Near',\n chainId: 0,\n wormholeChainId: 15,\n rpcUrl: 'https://rpc.mainnet.near.org',\n explorerUrl: 'https://explorer.near.org',\n isEvm: false,\n contracts: {\n wormholeCoreBridge: 'contract.wormhole_crypto.near',\n tokenBridge: 'contract.portalbridge.near',\n },\n },\n },\n};\n\n// ============================================================================\n// Helper Functions\n// ============================================================================\n\n/**\n * Get chain configuration by name and network\n */\nexport function getChainConfig(\n chain: ChainName,\n network: NetworkType = 'testnet'\n): ChainConfig {\n const preset = CHAIN_PRESETS[chain];\n if (!preset) {\n throw new Error(\n `Unknown chain: \"${chain}\". Supported chains: ${Object.keys(CHAIN_PRESETS).join(', ')}`\n );\n }\n return preset[network];\n}\n\n/**\n * Get chain preset by name\n */\nexport function getChainPreset(chain: ChainName): ChainPreset {\n const preset = CHAIN_PRESETS[chain];\n if (!preset) {\n throw new Error(\n `Unknown chain: \"${chain}\". Supported chains: ${Object.keys(CHAIN_PRESETS).join(', ')}`\n );\n }\n return preset;\n}\n\n/**\n * Get all supported chain names\n */\nexport function getSupportedChains(): ChainName[] {\n return Object.keys(CHAIN_PRESETS) as ChainName[];\n}\n\n/**\n * Get hub-capable chains\n */\nexport function getHubChains(): ChainName[] {\n return Object.entries(CHAIN_PRESETS)\n .filter(([_, preset]) => preset.canBeHub)\n .map(([name]) => name as ChainName);\n}\n\n/**\n * Check if chain is supported\n */\nexport function isChainSupported(chain: string): chain is ChainName {\n return chain in CHAIN_PRESETS;\n}\n\n/**\n * Get default hub chain\n */\nexport function getDefaultHub(network: NetworkType = 'testnet'): ChainConfig {\n return CHAIN_PRESETS.base[network];\n}\n","/**\n * Veridex Protocol SDK - Simplified Initialization\n * \n * Factory functions for easy SDK creation with minimal configuration.\n * \n * @example\n * ```typescript\n * import { createSDK } from '@veridex/sdk';\n * \n * // Simplest usage - testnet by default\n * const sdk = await createSDK('base');\n * \n * // Register passkey and start using\n * await sdk.passkey.register('user@example.com', 'My Wallet');\n * const vault = await sdk.getVaultAddress();\n * ```\n */\n\nimport { VeridexSDK } from './core/VeridexSDK.js';\nimport { EVMClient } from './chains/evm/EVMClient.js';\nimport { SolanaClient } from './chains/solana/SolanaClient.js';\nimport { AptosClient } from './chains/aptos/AptosClient.js';\nimport { SuiClient } from './chains/sui/SuiClient.js';\nimport { StarknetClient } from './chains/starknet/StarknetClient.js';\nimport { \n CHAIN_PRESETS,\n getChainConfig,\n getChainPreset,\n type ChainName,\n type NetworkType,\n} from './presets.js';\nimport type { ChainClient } from './core/types.js';\n\n// ============================================================================\n// Simple Configuration Interface\n// ============================================================================\n\n/**\n * Simplified SDK configuration\n * Only specify what you need - everything else has sensible defaults\n */\nexport interface SimpleSDKConfig {\n /**\n * Network to connect to\n * @default 'testnet'\n */\n network?: NetworkType;\n \n /**\n * Custom RPC URL (optional - defaults to public endpoints)\n */\n rpcUrl?: string;\n \n /**\n * Relayer URL for gasless transactions (optional)\n */\n relayerUrl?: string;\n \n /**\n * Relayer API key (optional)\n */\n relayerApiKey?: string;\n \n /**\n * Sponsor private key for gasless vault creation (optional)\n * If not provided, users pay their own gas\n */\n sponsorPrivateKey?: string;\n \n /**\n * Integrator sponsor key (optional)\n * Allows platforms to pay for their users' transactions\n */\n integratorSponsorKey?: string;\n \n /**\n * Additional RPC URLs for multi-chain operations\n * Maps chain name to RPC URL\n */\n rpcUrls?: Partial<Record<ChainName, string>>;\n}\n\n/**\n * Session-specific configuration\n */\nexport interface SessionConfig {\n /**\n * Chain to use for sessions\n */\n chain: ChainName;\n \n /**\n * Network to connect to\n * @default 'testnet'\n */\n network?: NetworkType;\n \n /**\n * Session duration in seconds\n * @default 3600 (1 hour)\n */\n duration?: number;\n \n /**\n * Maximum value per transaction\n * @default BigInt(1e18) (1 token)\n */\n maxValue?: bigint;\n \n /**\n * Require user verification for session creation\n * @default true\n */\n requireUV?: boolean;\n}\n\n// ============================================================================\n// Chain Client Factory\n// ============================================================================\n\n/**\n * Create the appropriate chain client based on chain type\n */\nfunction createChainClient(\n chain: ChainName,\n network: NetworkType,\n customRpcUrl?: string\n): ChainClient {\n const preset = getChainPreset(chain);\n const config = preset[network];\n const rpcUrl = customRpcUrl || config.rpcUrl;\n\n const requireString = (value: string | undefined, label: string): string => {\n if (!value) {\n throw new Error(`Missing ${label} for chain \"${chain}\" on network \"${network}\"`);\n }\n return value;\n };\n \n switch (preset.type) {\n case 'evm':\n return new EVMClient({\n chainId: config.chainId,\n wormholeChainId: config.wormholeChainId,\n rpcUrl,\n hubContractAddress: requireString(config.contracts.hub, 'hub contract address'),\n wormholeCoreBridge: requireString(config.contracts.wormholeCoreBridge, 'Wormhole core bridge address'),\n vaultFactory: config.contracts.vaultFactory,\n vaultImplementation: config.contracts.vaultImplementation,\n tokenBridge: config.contracts.tokenBridge,\n name: config.name,\n explorerUrl: config.explorerUrl,\n });\n \n case 'solana':\n return new SolanaClient({\n rpcUrl,\n programId: requireString(config.contracts.hub, 'programId'),\n wormholeCoreBridge: requireString(config.contracts.wormholeCoreBridge, 'Wormhole core bridge address'),\n tokenBridge: requireString(config.contracts.tokenBridge, 'token bridge address'),\n wormholeChainId: config.wormholeChainId,\n network: network === 'testnet' ? 'devnet' : 'mainnet',\n });\n \n case 'aptos':\n return new AptosClient({\n rpcUrl,\n moduleAddress: requireString(config.contracts.hub, 'moduleAddress'),\n wormholeCoreBridge: requireString(config.contracts.wormholeCoreBridge, 'Wormhole core bridge address'),\n tokenBridge: requireString(config.contracts.tokenBridge, 'token bridge address'),\n wormholeChainId: config.wormholeChainId,\n network: network,\n });\n \n case 'sui':\n return new SuiClient({\n rpcUrl,\n packageId: requireString(config.contracts.hub, 'packageId'),\n wormholeCoreBridge: requireString(config.contracts.wormholeCoreBridge, 'Wormhole core bridge address'),\n wormholeChainId: config.wormholeChainId,\n network: network,\n });\n \n case 'starknet':\n return new StarknetClient({\n rpcUrl,\n spokeContractAddress: config.contracts.hub,\n bridgeContractAddress: config.contracts.wormholeCoreBridge,\n wormholeChainId: config.wormholeChainId,\n network: network === 'testnet' ? 'sepolia' : 'mainnet',\n });\n \n case 'near':\n case 'cosmos':\n throw new Error(`Chain type \"${preset.type}\" is not yet supported. Coming soon!`);\n \n default:\n throw new Error(`Unknown chain type: ${preset.type}`);\n }\n}\n\n// ============================================================================\n// SDK Factory Functions\n// ============================================================================\n\n/**\n * Create a Veridex SDK instance with minimal configuration\n * \n * @param chain - Chain name (e.g., 'base', 'optimism', 'solana')\n * @param config - Optional configuration overrides\n * @returns Configured VeridexSDK instance\n * \n * @example\n * ```typescript\n * // Simplest usage - testnet by default\n * const sdk = await createSDK('base');\n * \n * // Use mainnet\n * const mainnetSdk = await createSDK('base', { network: 'mainnet' });\n * \n * // With custom RPC\n * const customSdk = await createSDK('base', { \n * rpcUrl: 'https://my-rpc.example.com' \n * });\n * \n * // With relayer for gasless transactions\n * const gaslessSdk = await createSDK('base', {\n * relayerUrl: 'https://relayer.veridex.io',\n * relayerApiKey: 'your-api-key',\n * });\n * ```\n */\nexport function createSDK(\n chain: ChainName,\n config: SimpleSDKConfig = {}\n): VeridexSDK {\n const network = config.network ?? 'testnet';\n \n // Validate chain exists\n if (!CHAIN_PRESETS[chain]) {\n const supportedChains = Object.keys(CHAIN_PRESETS).join(', ');\n throw new Error(\n `Unknown chain: \"${chain}\". Supported chains: ${supportedChains}`\n );\n }\n \n // Create chain client\n const chainClient = createChainClient(chain, network, config.rpcUrl);\n \n // Build RPC URLs map for multi-chain operations\n const chainRpcUrls: Record<number, string> = {};\n if (config.rpcUrls) {\n for (const [chainName, rpcUrl] of Object.entries(config.rpcUrls)) {\n if (rpcUrl && CHAIN_PRESETS[chainName as ChainName]) {\n const chainConfig = getChainConfig(chainName as ChainName, network);\n chainRpcUrls[chainConfig.wormholeChainId] = rpcUrl;\n }\n }\n }\n \n // Create SDK\n return new VeridexSDK({\n chain: chainClient,\n testnet: network === 'testnet',\n relayerUrl: config.relayerUrl,\n relayerApiKey: config.relayerApiKey,\n sponsorPrivateKey: config.sponsorPrivateKey,\n integratorSponsorKey: config.integratorSponsorKey,\n chainRpcUrls: Object.keys(chainRpcUrls).length > 0 ? chainRpcUrls : undefined,\n });\n}\n\n/**\n * Create SDK for the default hub chain (Base)\n * \n * @param config - Optional configuration\n * @returns SDK configured for Base hub chain\n * \n * @example\n * ```typescript\n * const sdk = createHubSDK();\n * await sdk.passkey.register('user', 'My Wallet');\n * ```\n */\nexport function createHubSDK(config: SimpleSDKConfig = {}): VeridexSDK {\n return createSDK('base', config);\n}\n\n/**\n * Create SDK for testnet (convenience function)\n * \n * @param chain - Chain name\n * @param config - Optional configuration (network is forced to testnet)\n * @returns SDK configured for testnet\n */\nexport function createTestnetSDK(\n chain: ChainName = 'base',\n config: Omit<SimpleSDKConfig, 'network'> = {}\n): VeridexSDK {\n return createSDK(chain, { ...config, network: 'testnet' });\n}\n\n/**\n * Create SDK for mainnet (convenience function)\n * \n * @param chain - Chain name\n * @param config - Optional configuration (network is forced to mainnet)\n * @returns SDK configured for mainnet\n */\nexport function createMainnetSDK(\n chain: ChainName = 'base',\n config: Omit<SimpleSDKConfig, 'network'> = {}\n): VeridexSDK {\n return createSDK(chain, { ...config, network: 'mainnet' });\n}\n\n// ============================================================================\n// Session Factory (for Session Keys)\n// ============================================================================\n\n/**\n * Create a session-enabled SDK\n * \n * @param chain - Chain name\n * @param config - Session configuration\n * @returns SDK configured for session key usage\n * \n * @example\n * ```typescript\n * import { createSessionSDK, SessionManager } from '@veridex/sdk';\n * \n * const sdk = createSessionSDK('base');\n * const sessionManager = new SessionManager({ sdk });\n * \n * // Create a session (one passkey auth)\n * const session = await sessionManager.createSession({\n * duration: 3600,\n * maxValue: BigInt(1e18),\n * });\n * \n * // Execute multiple transactions without prompts\n * await sessionManager.executeWithSession(params, session);\n * ```\n */\nexport function createSessionSDK(\n chain: ChainName = 'base',\n config: SimpleSDKConfig = {}\n): VeridexSDK {\n // Sessions require hub chain with session key support\n const preset = getChainPreset(chain);\n if (!preset.canBeHub) {\n console.warn(\n `Chain \"${chain}\" may have limited session support. ` +\n `Consider using a hub chain like \"base\" for full session capabilities.`\n );\n }\n \n return createSDK(chain, config);\n}\n\n// ============================================================================\n// Type Exports\n// ============================================================================\n\nexport type { ChainName, NetworkType } from './presets.js';\nexport { \n CHAIN_NAMES, \n CHAIN_PRESETS,\n getChainConfig,\n getChainPreset,\n getSupportedChains,\n getHubChains,\n isChainSupported,\n getDefaultHub,\n} from './presets.js';\n","/**\n * Veridex Protocol SDK - Session Manager\n * \n * Manages ephemeral session keys for fast, native L1-speed transactions\n * after initial biometric authentication.\n * \n * Key Features:\n * - One-time Passkey auth to create session\n * - Instant software-backed signing for subsequent transactions\n * - Query-based validation on Spokes (no VAA wait)\n * - ~400ms transactions after initial setup\n * - Secure encrypted storage (AES-GCM)\n * - Auto-refresh before expiry\n * - Per-session value limits\n */\n\nimport { ethers } from 'ethers';\nimport type {\n SessionKey,\n SessionConfig,\n SessionSignature,\n SessionManagerConfig,\n SessionStorage,\n SessionEvent,\n SessionEventCallback,\n ActionParams,\n SessionSignedAction,\n} from './types.js';\nimport { SessionError, SessionErrorCode } from './types.js';\nimport {\n generateSecp256k1KeyPair,\n computeSessionKeyHash,\n signWithSessionKey,\n hashAction,\n validateSessionConfig,\n DEFAULT_SESSION_DURATION,\n DEFAULT_REFRESH_BUFFER,\n} from './crypto.js';\nimport { createSessionStorage } from './storage.js';\nimport type { PasskeyCredential } from '../core/PasskeyManager.js';\nimport type { RegisterSessionParams, RevokeSessionParams } from '../types.js';\n\n// ============================================================================\n// Hub Client Interface\n// ============================================================================\n\n/**\n * Interface for Hub contract interactions\n * \n * This should be implemented by chain clients (e.g., EVMHubClientAdapter).\n */\ninterface HubClient {\n /**\n * Register a session on the Hub\n * \n * @param params Registration parameters with Passkey signature\n * @returns Promise that resolves when registration completes\n */\n registerSession(params: RegisterSessionParams): Promise<void>;\n \n /**\n * Revoke a session on the Hub\n * \n * @param params Revocation parameters with Passkey signature\n * @returns Promise that resolves when revocation completes\n */\n revokeSession(params: RevokeSessionParams): Promise<void>;\n}\n\n// ============================================================================\n// Session Manager Class\n// ============================================================================\n\n/**\n * Manages session key lifecycle and signing operations\n * \n * Usage:\n * ```typescript\n * const manager = new SessionManager(credential, hubClient, passkeySign, config);\n * \n * // Create session (requires biometric)\n * const session = await manager.createSession();\n * \n * // Sign actions instantly (no biometric)\n * const signature = await manager.signWithSession(action);\n * \n * // Revoke session (requires biometric)\n * await manager.revokeSession();\n * ```\n */\nclass SessionManager {\n private currentSession: SessionKey | null = null;\n private storage: SessionStorage;\n private config: Required<SessionConfig>;\n private refreshTimer: NodeJS.Timeout | null = null;\n private eventCallbacks: SessionEventCallback[] = [];\n private debug: boolean;\n \n /**\n * @param credential User's Passkey credential (for Hub interaction)\n * @param hubClient Hub client for on-chain session operations\n * @param passkeySign Function to sign challenges with Passkey\n * @param config Session configuration\n * @param managerConfig SessionManager configuration\n */\n constructor(\n private credential: PasskeyCredential,\n private hubClient: HubClient,\n private passkeySign: (challenge: Uint8Array) => Promise<any>,\n config: Partial<SessionConfig>,\n managerConfig?: SessionManagerConfig\n ) {\n // Validate and set configuration\n this.config = {\n duration: config.duration ?? DEFAULT_SESSION_DURATION,\n maxValue: config.maxValue ?? 0n,\n autoRefresh: config.autoRefresh ?? true,\n refreshBuffer: config.refreshBuffer ?? DEFAULT_REFRESH_BUFFER,\n chainScopes: config.chainScopes ?? [],\n };\n \n validateSessionConfig(this.config);\n \n this.debug = managerConfig?.debug ?? false;\n \n // Initialize storage\n this.storage = managerConfig?.encryptionKey\n ? createSessionStorage(credential.credentialId)\n : createSessionStorage(\n credential.credentialId,\n managerConfig?.storageBackend\n );\n }\n \n // ========================================================================\n // Session Lifecycle\n // ========================================================================\n \n /**\n * Create a new session (requires biometric authentication)\n * \n * Steps:\n * 1. Generate ephemeral secp256k1 key pair\n * 2. Sign session registration with Passkey\n * 3. Register session on Hub contract\n * 4. Store session securely (encrypted)\n * 5. Start auto-refresh timer (if enabled)\n * \n * @returns Created session key\n * @throws SessionError if registration fails\n */\n async createSession(): Promise<SessionKey> {\n try {\n this.log('Creating new session...');\n \n // 1. Generate ephemeral key pair\n const keyPair = generateSecp256k1KeyPair();\n const keyHash = computeSessionKeyHash(keyPair.publicKey);\n \n this.log('Generated session key:', keyHash);\n \n // 2. Prepare challenge for Passkey signing\n const challenge = ethers.solidityPacked(\n ['string', 'bytes32', 'uint256', 'uint256'],\n ['registerSession', keyHash, this.config.duration, this.config.maxValue]\n );\n \n this.log('Challenge prepared, requesting Passkey signature...');\n \n // 3. Sign with Passkey (this triggers biometric prompt)\n const signature = await this.passkeySign(ethers.getBytes(challenge));\n \n this.log('Passkey signature obtained, registering on Hub...');\n \n // 4. Register session on Hub\n const registerParams: RegisterSessionParams = {\n signature,\n publicKeyX: this.credential.publicKeyX,\n publicKeyY: this.credential.publicKeyY,\n sessionKeyHash: keyHash,\n duration: this.config.duration,\n maxValue: this.config.maxValue,\n requireUV: true,\n };\n \n await this.hubClient.registerSession(registerParams);\n \n this.log('Session registered on Hub');\n \n // 5. Create session object\n const expiry = Date.now() + this.config.duration * 1000;\n \n this.currentSession = {\n publicKey: keyPair.publicKey,\n privateKey: keyPair.privateKey,\n keyHash,\n expiry,\n maxValue: this.config.maxValue,\n chainScopes: this.config.chainScopes,\n userKeyHash: this.credential.keyHash,\n };\n \n // 6. Store securely\n await this.storage.save(this.currentSession);\n \n this.log('Session stored securely');\n \n // 7. Start auto-refresh\n if (this.config.autoRefresh) {\n this.scheduleRefresh();\n }\n \n // 8. Emit event\n this.emit({ type: 'session-created', session: this.currentSession });\n \n return this.currentSession;\n \n } catch (error) {\n const sessionError = error instanceof SessionError\n ? error\n : new SessionError(\n 'Failed to create session',\n SessionErrorCode.REGISTRATION_FAILED,\n error\n );\n \n this.emit({ type: 'session-error', error: sessionError });\n throw sessionError;\n }\n }\n \n /**\n * Load existing session from storage\n * \n * @returns Loaded session or null if no valid session exists\n */\n async loadSession(): Promise<SessionKey | null> {\n try {\n this.log('Loading session from storage...');\n \n const session = await this.storage.load();\n \n if (!session) {\n this.log('No session found in storage');\n return null;\n }\n \n // Verify session is not expired\n if (session.expiry <= Date.now()) {\n this.log('Session expired, clearing...');\n await this.storage.clear();\n return null;\n }\n \n this.currentSession = session;\n this.log('Session loaded:', session.keyHash);\n \n // Start auto-refresh if enabled\n if (this.config.autoRefresh) {\n this.scheduleRefresh();\n }\n \n this.emit({ type: 'session-loaded', session });\n \n return session;\n \n } catch (error) {\n this.log('Failed to load session:', error);\n await this.storage.clear();\n return null;\n }\n }\n \n /**\n * Revoke the current session (requires biometric authentication)\n * \n * @throws SessionError if no active session or revocation fails\n */\n async revokeSession(): Promise<void> {\n if (!this.currentSession) {\n throw new SessionError(\n 'No active session to revoke',\n SessionErrorCode.NO_ACTIVE_SESSION\n );\n }\n \n try {\n this.log('Revoking session:', this.currentSession.keyHash);\n \n // 1. Prepare challenge for revocation\n const challenge = ethers.solidityPacked(\n ['string', 'bytes32'],\n ['revokeSession', this.currentSession.keyHash]\n );\n \n // 2. Sign with Passkey (biometric prompt)\n const signature = await this.passkeySign(ethers.getBytes(challenge));\n \n this.log('Passkey signature obtained, revoking on Hub...');\n \n // 3. Revoke on Hub\n const revokeParams: RevokeSessionParams = {\n signature,\n publicKeyX: this.credential.publicKeyX,\n publicKeyY: this.credential.publicKeyY,\n sessionKeyHash: this.currentSession.keyHash,\n requireUV: true,\n };\n \n await this.hubClient.revokeSession(revokeParams);\n \n this.log('Session revoked on Hub');\n \n // 4. Clear local storage\n await this.storage.clear();\n \n // 5. Cancel refresh timer\n if (this.refreshTimer) {\n clearTimeout(this.refreshTimer);\n this.refreshTimer = null;\n }\n \n const revokedKeyHash = this.currentSession.keyHash;\n this.currentSession = null;\n \n // 6. Emit event\n this.emit({ type: 'session-revoked', keyHash: revokedKeyHash });\n \n this.log('Session revoked successfully');\n \n } catch (error) {\n const sessionError = error instanceof SessionError\n ? error\n : new SessionError(\n 'Failed to revoke session',\n SessionErrorCode.REVOCATION_FAILED,\n error\n );\n \n this.emit({ type: 'session-error', error: sessionError });\n throw sessionError;\n }\n }\n \n // ========================================================================\n // Session Signing\n // ========================================================================\n \n /**\n * Sign an action with the session key (instant, no biometric)\n * \n * @param action Action parameters to sign\n * @returns Session signature\n * @throws SessionError if no active session, expired, or value exceeds limit\n */\n async signWithSession(action: ActionParams): Promise<SessionSignature> {\n if (!this.currentSession) {\n throw new SessionError(\n 'No active session available',\n SessionErrorCode.NO_ACTIVE_SESSION\n );\n }\n \n const now = Date.now();\n if (now >= this.currentSession.expiry) {\n this.emit({ type: 'session-expired', keyHash: this.currentSession.keyHash });\n throw new SessionError(\n 'Session has expired',\n SessionErrorCode.SESSION_EXPIRED\n );\n }\n \n if (this.currentSession.maxValue > 0n && action.value > this.currentSession.maxValue) {\n throw new SessionError(\n `Transaction value (${action.value}) exceeds session limit (${this.currentSession.maxValue})`,\n SessionErrorCode.VALUE_EXCEEDS_LIMIT,\n { value: action.value, limit: this.currentSession.maxValue }\n );\n }\n \n if (\n this.currentSession.chainScopes.length > 0 &&\n !this.currentSession.chainScopes.includes(action.targetChain)\n ) {\n throw new SessionError(\n `Chain ${action.targetChain} not in session scope`,\n SessionErrorCode.CHAIN_NOT_ALLOWED,\n { chain: action.targetChain, allowedChains: this.currentSession.chainScopes }\n );\n }\n \n this.log('Signing action with session key...');\n \n const messageHash = hashAction(action);\n const { signature } = signWithSessionKey(\n this.currentSession.privateKey,\n messageHash\n );\n \n const sessionSignature: SessionSignature = {\n signature,\n sessionKeyHash: this.currentSession.keyHash,\n userKeyHash: this.currentSession.userKeyHash,\n timestamp: now,\n nonce: action.nonce,\n };\n \n this.log('Action signed successfully');\n \n return sessionSignature;\n }\n \n /**\n * Sign an action and prepare for submission\n * \n * @param action Action parameters\n * @returns Session-signed action ready for submission\n */\n async signAction(action: ActionParams): Promise<SessionSignedAction> {\n const signature = await this.signWithSession(action);\n \n return {\n action,\n signature,\n readyToSubmit: true,\n };\n }\n \n // ========================================================================\n // Session State\n // ========================================================================\n \n /**\n * Check if a session is currently active\n * \n * @returns True if an active, non-expired session exists\n */\n isActive(): boolean {\n if (!this.currentSession) {\n return false;\n }\n return Date.now() < this.currentSession.expiry;\n }\n \n /**\n * Get current session information (if active)\n * \n * @returns Current session or null\n */\n getSession(): SessionKey | null {\n if (!this.isActive()) {\n return null;\n }\n return this.currentSession;\n }\n \n /**\n * Get time remaining until session expiry (in seconds)\n * \n * @returns Seconds until expiry, or 0 if no active session\n */\n getTimeRemaining(): number {\n if (!this.currentSession) {\n return 0;\n }\n const remaining = Math.floor((this.currentSession.expiry - Date.now()) / 1000);\n return Math.max(0, remaining);\n }\n \n // ========================================================================\n // Auto-Refresh\n // ========================================================================\n \n /**\n * Schedule automatic session refresh\n */\n private scheduleRefresh(): void {\n if (!this.currentSession || !this.config.autoRefresh) {\n return;\n }\n \n if (this.refreshTimer) {\n clearTimeout(this.refreshTimer);\n }\n \n const timeUntilRefresh = this.currentSession.expiry - Date.now() - (this.config.refreshBuffer * 1000);\n \n if (timeUntilRefresh <= 0) {\n this.log('Session expiring soon, refreshing now...');\n this.refreshSession().catch(error => {\n this.log('Auto-refresh failed:', error);\n this.emit({ type: 'session-error', error });\n });\n return;\n }\n \n this.log(`Scheduling refresh in ${Math.floor(timeUntilRefresh / 1000)}s`);\n \n this.refreshTimer = setTimeout(() => {\n this.refreshSession().catch(error => {\n this.log('Auto-refresh failed:', error);\n this.emit({ type: 'session-error', error });\n });\n }, timeUntilRefresh);\n }\n \n /**\n * Refresh the current session (creates a new session)\n * \n * @returns New session key\n */\n async refreshSession(): Promise<SessionKey> {\n this.log('Refreshing session...');\n const newSession = await this.createSession();\n this.emit({ type: 'session-refreshed', session: newSession });\n return newSession;\n }\n \n // ========================================================================\n // Event Handling\n // ========================================================================\n \n /**\n * Register an event callback\n */\n on(callback: SessionEventCallback): void {\n this.eventCallbacks.push(callback);\n }\n \n /**\n * Unregister an event callback\n */\n off(callback: SessionEventCallback): void {\n this.eventCallbacks = this.eventCallbacks.filter(cb => cb !== callback);\n }\n \n /**\n * Emit a session event\n */\n private emit(event: SessionEvent): void {\n for (const callback of this.eventCallbacks) {\n try {\n callback(event);\n } catch (error) {\n console.error('Session event callback error:', error);\n }\n }\n }\n \n // ========================================================================\n // Utilities\n // ========================================================================\n \n /**\n * Log debug message (if debug enabled)\n */\n private log(...args: any[]): void {\n if (this.debug) {\n console.log('[SessionManager]', ...args);\n }\n }\n \n /**\n * Cleanup resources\n */\n dispose(): void {\n if (this.refreshTimer) {\n clearTimeout(this.refreshTimer);\n this.refreshTimer = null;\n }\n this.eventCallbacks = [];\n this.currentSession = null;\n }\n}\n\n// ============================================================================\n// Exports\n// ============================================================================\n\nexport { SessionManager };\nexport type { HubClient };\nexport * from './types.js';\nexport * from './crypto.js';\nexport * from './storage.js';","/**\n * Veridex Protocol SDK - Session Key Management Types\n * \n * Type definitions for ephemeral session keys that enable\n * native L1-speed transactions after initial biometric auth.\n */\n\n// ============================================================================\n// Core Session Types\n// ============================================================================\n\n/**\n * Ephemeral session key for fast software-backed signing\n * \n * Security model:\n * - Private key encrypted at rest (AES-GCM)\n * - Max 24-hour duration enforced on-chain\n * - Value limits prevent unlimited spending\n * - Chain scopes restrict cross-chain usage\n */\nexport interface SessionKey {\n /** Public key of the session (secp256k1) */\n publicKey: Uint8Array;\n \n /** Private key (MUST be encrypted before storage) */\n privateKey: Uint8Array;\n \n /** Keccak256 hash of public key (on-chain identifier) */\n keyHash: string;\n \n /** Unix timestamp when session expires (milliseconds) */\n expiry: number;\n \n /** Maximum transaction value allowed (in token's base units) */\n maxValue: bigint;\n \n /** Wormhole chain IDs where this session is valid */\n chainScopes: number[];\n \n /** User's Passkey key hash (binds session to user) */\n userKeyHash: string;\n}\n\n/**\n * Configuration for session creation and lifecycle\n */\nexport interface SessionConfig {\n /** Session duration in seconds (default: 3600 = 1 hour, max: 86400 = 24 hours) */\n duration: number;\n \n /** Maximum transaction value in base units (0 = unlimited, but NOT RECOMMENDED) */\n maxValue: bigint;\n \n /** Auto-refresh session before expiry (default: true) */\n autoRefresh: boolean;\n \n /** Refresh buffer time in seconds (refresh this many seconds before expiry, default: 300 = 5 min) */\n refreshBuffer?: number;\n \n /** Chain scopes - which Wormhole chain IDs can use this session (empty = all chains) */\n chainScopes?: number[];\n}\n\n/**\n * Signature produced by signing with a session key\n * \n * This is a lightweight software signature (secp256k1) that can be\n * validated on-chain via CCQ to Hub's isSessionActive() state.\n */\nexport interface SessionSignature {\n /** ECDSA signature (r, s, v) from session private key */\n signature: Uint8Array;\n \n /** Session key hash (links signature to registered session) */\n sessionKeyHash: string;\n \n /** User's Passkey key hash (for Hub state query) */\n userKeyHash: string;\n \n /** Timestamp when signature was created (for replay prevention) */\n timestamp: number;\n \n /** Optional nonce for additional replay protection */\n nonce?: number;\n}\n\n/**\n * Configuration for SessionManager initialization\n */\nexport interface SessionManagerConfig {\n /** Default session configuration */\n defaultSessionConfig: SessionConfig;\n \n /** Storage backend ('indexeddb' or 'localstorage', default: 'indexeddb') */\n storageBackend?: 'indexeddb' | 'localstorage';\n \n /** Enable debug logging */\n debug?: boolean;\n \n /** Custom encryption key derivation (for testing only) */\n encryptionKey?: CryptoKey;\n}\n\n// ============================================================================\n// Session Lifecycle Events\n// ============================================================================\n\n/**\n * Events emitted during session lifecycle\n */\nexport type SessionEvent = \n | { type: 'session-created'; session: SessionKey }\n | { type: 'session-loaded'; session: SessionKey }\n | { type: 'session-expired'; keyHash: string }\n | { type: 'session-refreshed'; session: SessionKey }\n | { type: 'session-revoked'; keyHash: string }\n | { type: 'session-error'; error: Error };\n\nexport type SessionEventCallback = (event: SessionEvent) => void;\n\n// ============================================================================\n// Storage Interface\n// ============================================================================\n\n/**\n * Interface for session storage implementations\n * \n * Implementations MUST:\n * - Encrypt private keys before storage\n * - Use secure key derivation (e.g., PBKDF2 or similar)\n * - Provide atomic read/write/delete operations\n */\nexport interface SessionStorage {\n /**\n * Save a session (private key will be encrypted)\n */\n save(session: SessionKey): Promise<void>;\n \n /**\n * Load the active session (private key will be decrypted)\n */\n load(): Promise<SessionKey | null>;\n \n /**\n * Clear all stored sessions\n */\n clear(): Promise<void>;\n \n /**\n * Check if a session exists\n */\n exists(): Promise<boolean>;\n}\n\n// ============================================================================\n// Action Signing Types\n// ============================================================================\n\n/**\n * Parameters for an action to be signed with a session key\n */\nexport interface ActionParams {\n /** Action type (transfer, execute, bridge, etc.) */\n action: string;\n \n /** Target chain (Wormhole chain ID) */\n targetChain: number;\n \n /** Transaction value in base units */\n value: bigint;\n \n /** Action-specific payload */\n payload: Uint8Array;\n \n /** Nonce for replay prevention */\n nonce: number;\n \n /** Optional deadline timestamp */\n deadline?: number;\n}\n\n/**\n * Result of session-signed action\n */\nexport interface SessionSignedAction {\n /** Original action parameters */\n action: ActionParams;\n \n /** Session signature */\n signature: SessionSignature;\n \n /** Ready to submit to relayer or on-chain */\n readyToSubmit: boolean;\n}\n\n// ============================================================================\n// Error Types\n// ============================================================================\n\nexport class SessionError extends Error {\n constructor(\n message: string,\n public code: SessionErrorCode,\n public details?: unknown\n ) {\n super(message);\n this.name = 'SessionError';\n }\n}\n\nexport enum SessionErrorCode {\n NO_ACTIVE_SESSION = 'NO_ACTIVE_SESSION',\n SESSION_EXPIRED = 'SESSION_EXPIRED',\n VALUE_EXCEEDS_LIMIT = 'VALUE_EXCEEDS_LIMIT',\n CHAIN_NOT_ALLOWED = 'CHAIN_NOT_ALLOWED',\n STORAGE_ERROR = 'STORAGE_ERROR',\n ENCRYPTION_ERROR = 'ENCRYPTION_ERROR',\n INVALID_CONFIG = 'INVALID_CONFIG',\n REGISTRATION_FAILED = 'REGISTRATION_FAILED',\n REVOCATION_FAILED = 'REVOCATION_FAILED',\n}\n","/**\n * Veridex Protocol SDK - Session Cryptography Utilities\n * \n * Provides cryptographic operations for session key management:\n * - secp256k1 key generation (NOT secp256r1 - sessions are software-backed)\n * - ECDSA signing with session keys\n * - Key hash derivation (keccak256)\n * - Secure random generation\n */\n\nimport { ethers } from 'ethers';\nimport { SessionError, SessionErrorCode } from './types.js';\n\n// ============================================================================\n// Constants\n// ============================================================================\n\n/** Maximum session duration enforced on-chain (24 hours) */\nexport const MAX_SESSION_DURATION = 86400; // 24 hours in seconds\n\n/** Minimum session duration (60 seconds) */\nexport const MIN_SESSION_DURATION = 60;\n\n/** Default session duration (1 hour) */\nexport const DEFAULT_SESSION_DURATION = 3600;\n\n/** Default refresh buffer (5 minutes before expiry) */\nexport const DEFAULT_REFRESH_BUFFER = 300;\n\n// ============================================================================\n// Key Generation\n// ============================================================================\n\n/**\n * Key pair for secp256k1 session keys\n */\nexport interface KeyPair {\n publicKey: Uint8Array;\n privateKey: Uint8Array;\n address: string; // Ethereum-style address for verification\n}\n\n/**\n * Generate a new secp256k1 key pair for session key\n * \n * Security:\n * - Uses cryptographically secure random (ethers.Wallet.createRandom)\n * - Returns uncompressed public key (65 bytes)\n * - Private key is 32 bytes\n * \n * @returns KeyPair with public/private keys and derived address\n */\nexport function generateSecp256k1KeyPair(): KeyPair {\n try {\n // Use ethers.js for secure key generation\n const wallet = ethers.Wallet.createRandom();\n \n // Extract raw private key (32 bytes)\n const privateKey = ethers.getBytes(wallet.privateKey);\n \n // ethers v6 returns COMPRESSED public key (33 bytes).\n // We need UNCOMPRESSED (65 bytes: 0x04 || x || y).\n // Use SigningKey to derive the uncompressed form.\n const signingKey = new ethers.SigningKey(wallet.privateKey);\n const publicKey = ethers.getBytes(signingKey.publicKey);\n \n return {\n publicKey,\n privateKey,\n address: wallet.address,\n };\n } catch (error) {\n throw new SessionError(\n 'Failed to generate secp256k1 key pair',\n SessionErrorCode.ENCRYPTION_ERROR,\n error\n );\n }\n}\n\n/**\n * Compute keccak256 hash of public key (session key identifier)\n * \n * This hash is used as the on-chain identifier for the session.\n * It matches the Solidity keccak256(publicKey) computation.\n * \n * @param publicKey Uncompressed public key (65 bytes)\n * @returns Hex string of keccak256 hash (0x...)\n */\nexport function computeSessionKeyHash(publicKey: Uint8Array): string {\n if (publicKey.length !== 65 || publicKey[0] !== 0x04) {\n throw new SessionError(\n 'Invalid public key format (expected 65-byte uncompressed key)',\n SessionErrorCode.INVALID_CONFIG\n );\n }\n \n // Hash the full uncompressed public key (including 0x04 prefix)\n return ethers.keccak256(publicKey);\n}\n\n// ============================================================================\n// Signing\n// ============================================================================\n\n/**\n * Sign a message hash with a session key (secp256k1 ECDSA)\n * \n * @param privateKey Session private key (32 bytes)\n * @param messageHash Message hash to sign (32 bytes)\n * @returns Signature with r, s, v components\n */\nexport function signWithSessionKey(\n privateKey: Uint8Array,\n messageHash: Uint8Array | string\n): { r: string; s: string; v: number; signature: Uint8Array } {\n try {\n if (privateKey.length !== 32) {\n throw new SessionError(\n 'Invalid private key length (expected 32 bytes)',\n SessionErrorCode.ENCRYPTION_ERROR\n );\n }\n \n // Create signing key from private key\n const signingKey = new ethers.SigningKey(privateKey);\n \n // Ensure message hash is bytes\n const hashBytes = typeof messageHash === 'string' \n ? ethers.getBytes(messageHash)\n : messageHash;\n \n if (hashBytes.length !== 32) {\n throw new SessionError(\n 'Invalid message hash length (expected 32 bytes)',\n SessionErrorCode.INVALID_CONFIG\n );\n }\n \n // Sign the hash\n const sig = signingKey.sign(hashBytes);\n \n // Extract r, s, v\n const r = sig.r;\n const s = sig.s;\n const v = sig.v;\n \n // Combine into 65-byte signature (r + s + v)\n const signature = ethers.getBytes(sig.serialized);\n \n return { r, s, v, signature };\n } catch (error) {\n throw new SessionError(\n 'Failed to sign with session key',\n SessionErrorCode.ENCRYPTION_ERROR,\n error\n );\n }\n}\n\n/**\n * Hash an action for signing\n * \n * Creates a deterministic hash of action parameters that can be\n * signed with a session key and verified on-chain.\n * \n * Hash format: keccak256(abi.encodePacked(\n * action, targetChain, value, keccak256(payload), nonce, deadline\n * ))\n * \n * @param params Action parameters\n * @returns Message hash (32 bytes)\n */\nexport function hashAction(params: {\n action: string;\n targetChain: number;\n value: bigint;\n payload: Uint8Array;\n nonce: number;\n deadline?: number;\n}): Uint8Array {\n try {\n // Hash the payload first\n const payloadHash = ethers.keccak256(params.payload);\n \n // Encode packed (matches Solidity abi.encodePacked)\n const encoded = ethers.solidityPacked(\n ['string', 'uint256', 'uint256', 'bytes32', 'uint256', 'uint256'],\n [\n params.action,\n params.targetChain,\n params.value,\n payloadHash,\n params.nonce,\n params.deadline ?? 0,\n ]\n );\n \n // Return keccak256 hash\n return ethers.getBytes(ethers.keccak256(encoded));\n } catch (error) {\n throw new SessionError(\n 'Failed to hash action',\n SessionErrorCode.INVALID_CONFIG,\n error\n );\n }\n}\n\n/**\n * Verify a session key signature\n * \n * Used for testing and client-side validation before submission.\n * On-chain verification is handled by Spoke contracts via CCQ.\n * \n * @param messageHash Message that was signed\n * @param signature Signature to verify\n * @param expectedPublicKey Expected public key of signer\n * @returns True if signature is valid\n */\nexport function verifySessionSignature(\n messageHash: Uint8Array | string,\n signature: Uint8Array,\n expectedPublicKey: Uint8Array\n): boolean {\n try {\n if (signature.length !== 65) {\n return false;\n }\n \n // Ensure hash is bytes\n const hashBytes = typeof messageHash === 'string'\n ? ethers.getBytes(messageHash)\n : messageHash;\n \n // Recover public key from signature\n const recovered = ethers.SigningKey.recoverPublicKey(\n hashBytes,\n ethers.hexlify(signature)\n );\n \n // Compare with expected public key\n const recoveredBytes = ethers.getBytes(recovered);\n \n if (recoveredBytes.length !== expectedPublicKey.length) {\n return false;\n }\n \n // Constant-time comparison\n return recoveredBytes.every((byte, i) => byte === expectedPublicKey[i]);\n } catch {\n return false;\n }\n}\n\n// ============================================================================\n// Encryption Key Derivation\n// ============================================================================\n\n/**\n * Derive an AES-GCM encryption key for session storage\n * \n * Uses PBKDF2 to derive a key from a user-specific seed.\n * The seed should be derived from the user's Passkey credential ID.\n * \n * Security considerations:\n * - Uses 100,000 iterations (OWASP minimum)\n * - Salt is derived from credential ID (unique per user)\n * - Key is bound to specific browser/device via extractable: false\n * \n * @param credentialId User's Passkey credential ID (unique identifier)\n * @returns AES-GCM encryption key\n */\nexport async function deriveEncryptionKey(credentialId: string): Promise<CryptoKey> {\n try {\n // Use credential ID as password material\n const passwordBytes = ethers.toUtf8Bytes(credentialId);\n \n // Import as key material\n const keyMaterial = await crypto.subtle.importKey(\n 'raw',\n passwordBytes as BufferSource,\n 'PBKDF2',\n false,\n ['deriveKey']\n );\n \n // Derive salt from credential ID (deterministic but unique per user)\n const saltBytes = ethers.getBytes(ethers.keccak256(passwordBytes));\n \n // Derive AES-GCM key\n const key = await crypto.subtle.deriveKey(\n {\n name: 'PBKDF2',\n salt: saltBytes as BufferSource,\n iterations: 100000, // OWASP minimum\n hash: 'SHA-256',\n },\n keyMaterial,\n {\n name: 'AES-GCM',\n length: 256,\n },\n false, // Not extractable (stays in browser)\n ['encrypt', 'decrypt']\n );\n \n return key;\n } catch (error) {\n throw new SessionError(\n 'Failed to derive encryption key',\n SessionErrorCode.ENCRYPTION_ERROR,\n error\n );\n }\n}\n\n/**\n * Generate a random initialization vector (IV) for AES-GCM\n * \n * @returns 12-byte IV (standard for AES-GCM)\n */\nexport function generateIv(): Uint8Array {\n return crypto.getRandomValues(new Uint8Array(12));\n}\n\n/**\n * Encrypt data with AES-GCM\n * \n * @param data Data to encrypt\n * @param key AES-GCM encryption key\n * @returns Encrypted data with IV prepended\n */\nexport async function encrypt(data: Uint8Array, key: CryptoKey): Promise<Uint8Array> {\n try {\n const iv = generateIv();\n \n const encrypted = await crypto.subtle.encrypt(\n {\n name: 'AES-GCM',\n iv: iv as BufferSource,\n },\n key,\n data as BufferSource\n );\n \n // Prepend IV to encrypted data (IV is not secret)\n const result = new Uint8Array(iv.length + encrypted.byteLength);\n result.set(iv, 0);\n result.set(new Uint8Array(encrypted), iv.length);\n \n return result;\n } catch (error) {\n throw new SessionError(\n 'Encryption failed',\n SessionErrorCode.ENCRYPTION_ERROR,\n error\n );\n }\n}\n\n/**\n * Decrypt data with AES-GCM\n * \n * @param encryptedData Data with IV prepended\n * @param key AES-GCM encryption key\n * @returns Decrypted data\n */\nexport async function decrypt(encryptedData: Uint8Array, key: CryptoKey): Promise<Uint8Array> {\n try {\n if (encryptedData.length < 12) {\n throw new Error('Invalid encrypted data (too short)');\n }\n \n // Extract IV (first 12 bytes)\n const iv = encryptedData.slice(0, 12);\n \n // Extract encrypted data (remaining bytes)\n const ciphertext = encryptedData.slice(12);\n \n const decrypted = await crypto.subtle.decrypt(\n {\n name: 'AES-GCM',\n iv,\n },\n key,\n ciphertext\n );\n \n return new Uint8Array(decrypted);\n } catch (error) {\n throw new SessionError(\n 'Decryption failed',\n SessionErrorCode.ENCRYPTION_ERROR,\n error\n );\n }\n}\n\n// ============================================================================\n// Validation\n// ============================================================================\n\n/**\n * Validate session configuration\n * \n * @param config Session configuration to validate\n * @throws SessionError if configuration is invalid\n */\nexport function validateSessionConfig(config: {\n duration: number;\n maxValue: bigint;\n}): void {\n if (config.duration < MIN_SESSION_DURATION) {\n throw new SessionError(\n `Session duration too short (minimum: ${MIN_SESSION_DURATION}s)`,\n SessionErrorCode.INVALID_CONFIG\n );\n }\n \n if (config.duration > MAX_SESSION_DURATION) {\n throw new SessionError(\n `Session duration too long (maximum: ${MAX_SESSION_DURATION}s = 24 hours)`,\n SessionErrorCode.INVALID_CONFIG\n );\n }\n \n if (config.maxValue < 0n) {\n throw new SessionError(\n 'Session maxValue cannot be negative',\n SessionErrorCode.INVALID_CONFIG\n );\n }\n}\n","/**\n * Veridex Protocol SDK - Secure Session Storage\n * \n * Provides encrypted storage for session keys using IndexedDB or LocalStorage.\n * Private keys are ALWAYS encrypted at rest using AES-GCM.\n * \n * Security guarantees:\n * - Private keys never stored in plaintext\n * - Encryption keys derived from Passkey credential ID (user-bound)\n * - Keys are non-extractable (remain in browser's crypto subsystem)\n * - Automatic cleanup on revocation or expiry\n */\n\nimport { ethers } from 'ethers';\nimport type { SessionKey, SessionStorage } from './types.js';\nimport { SessionError, SessionErrorCode } from './types.js';\nimport { encrypt, decrypt, deriveEncryptionKey } from './crypto.js';\n\n// ============================================================================\n// IndexedDB Session Storage (Preferred)\n// ============================================================================\n\n/** IndexedDB database name */\nconst DB_NAME = 'veridex-sessions';\n\n/** IndexedDB version */\nconst DB_VERSION = 1;\n\n/** Object store name */\nconst STORE_NAME = 'sessions';\n\n/**\n * IndexedDB-based session storage with encryption\n * \n * Preferred storage backend because:\n * - Larger storage quota (~50MB vs ~10MB)\n * - Structured storage (no serialization overhead)\n * - Better performance for binary data\n * - Non-blocking async API\n */\nexport class IndexedDBSessionStorage implements SessionStorage {\n private db: IDBDatabase | null = null;\n private encryptionKey: CryptoKey | null = null;\n private credentialId: string;\n \n /**\n * @param credentialId User's Passkey credential ID (for key derivation)\n */\n constructor(credentialId: string) {\n if (!credentialId) {\n throw new SessionError(\n 'Credential ID required for session storage',\n SessionErrorCode.INVALID_CONFIG\n );\n }\n this.credentialId = credentialId;\n }\n \n /**\n * Initialize database connection\n */\n private async initialize(): Promise<void> {\n if (this.db) return;\n \n return new Promise((resolve, reject) => {\n const request = indexedDB.open(DB_NAME, DB_VERSION);\n \n request.onerror = () => {\n reject(new SessionError(\n 'Failed to open IndexedDB',\n SessionErrorCode.STORAGE_ERROR,\n request.error\n ));\n };\n \n request.onsuccess = () => {\n this.db = request.result;\n resolve();\n };\n \n request.onupgradeneeded = (event) => {\n const db = (event.target as IDBOpenDBRequest).result;\n \n // Create object store if it doesn't exist\n if (!db.objectStoreNames.contains(STORE_NAME)) {\n const store = db.createObjectStore(STORE_NAME, { keyPath: 'keyHash' });\n \n // Create indexes for efficient queries\n store.createIndex('userKeyHash', 'userKeyHash', { unique: false });\n store.createIndex('expiry', 'expiry', { unique: false });\n }\n };\n });\n }\n \n /**\n * Get or derive encryption key\n */\n private async getEncryptionKey(): Promise<CryptoKey> {\n if (this.encryptionKey) {\n return this.encryptionKey;\n }\n \n this.encryptionKey = await deriveEncryptionKey(this.credentialId);\n return this.encryptionKey;\n }\n \n /**\n * Save a session (encrypts private key)\n */\n async save(session: SessionKey): Promise<void> {\n try {\n await this.initialize();\n \n if (!this.db) {\n throw new Error('Database not initialized');\n }\n \n // Get encryption key\n const key = await this.getEncryptionKey();\n \n // Encrypt private key\n const encryptedPrivateKey = await encrypt(session.privateKey, key);\n \n // Prepare storage object (private key encrypted)\n const storageObject = {\n keyHash: session.keyHash,\n publicKey: Array.from(session.publicKey), // Store as array for IndexedDB\n encryptedPrivateKey: Array.from(encryptedPrivateKey),\n expiry: session.expiry,\n maxValue: session.maxValue.toString(), // BigInt as string\n chainScopes: session.chainScopes,\n userKeyHash: session.userKeyHash,\n savedAt: Date.now(),\n };\n \n // Store in IndexedDB\n return new Promise((resolve, reject) => {\n const transaction = this.db!.transaction([STORE_NAME], 'readwrite');\n const store = transaction.objectStore(STORE_NAME);\n const request = store.put(storageObject);\n \n request.onsuccess = () => resolve();\n request.onerror = () => {\n reject(new SessionError(\n 'Failed to save session',\n SessionErrorCode.STORAGE_ERROR,\n request.error\n ));\n };\n });\n } catch (error) {\n if (error instanceof SessionError) {\n throw error;\n }\n throw new SessionError(\n 'Failed to save session',\n SessionErrorCode.STORAGE_ERROR,\n error\n );\n }\n }\n \n /**\n * Load the active session (decrypts private key)\n */\n async load(): Promise<SessionKey | null> {\n try {\n await this.initialize();\n \n if (!this.db) {\n throw new Error('Database not initialized');\n }\n \n // Get all sessions\n const allSessions = await this.getAllSessions();\n \n if (allSessions.length === 0) {\n return null;\n }\n \n // Find the most recent non-expired session\n const now = Date.now();\n const validSessions = allSessions\n .filter(s => s.expiry > now)\n .sort((a, b) => b.savedAt - a.savedAt);\n \n if (validSessions.length === 0) {\n // All sessions expired, clean up\n await this.clear();\n return null;\n }\n \n const stored = validSessions[0];\n \n // Get encryption key\n const key = await this.getEncryptionKey();\n \n // Decrypt private key\n const encryptedPrivateKey = new Uint8Array(stored.encryptedPrivateKey);\n const privateKey = await decrypt(encryptedPrivateKey, key);\n \n // Reconstruct session\n const session: SessionKey = {\n keyHash: stored.keyHash,\n publicKey: new Uint8Array(stored.publicKey),\n privateKey,\n expiry: stored.expiry,\n maxValue: BigInt(stored.maxValue),\n chainScopes: stored.chainScopes,\n userKeyHash: stored.userKeyHash,\n };\n \n return session;\n } catch (error) {\n if (error instanceof SessionError) {\n throw error;\n }\n throw new SessionError(\n 'Failed to load session',\n SessionErrorCode.STORAGE_ERROR,\n error\n );\n }\n }\n \n /**\n * Get all stored sessions (internal helper)\n */\n private async getAllSessions(): Promise<Array<any>> {\n if (!this.db) {\n return [];\n }\n \n return new Promise((resolve, reject) => {\n const transaction = this.db!.transaction([STORE_NAME], 'readonly');\n const store = transaction.objectStore(STORE_NAME);\n const request = store.getAll();\n \n request.onsuccess = () => resolve(request.result || []);\n request.onerror = () => {\n reject(new SessionError(\n 'Failed to get sessions',\n SessionErrorCode.STORAGE_ERROR,\n request.error\n ));\n };\n });\n }\n \n /**\n * Clear all sessions\n */\n async clear(): Promise<void> {\n try {\n await this.initialize();\n \n if (!this.db) {\n return;\n }\n \n return new Promise((resolve, reject) => {\n const transaction = this.db!.transaction([STORE_NAME], 'readwrite');\n const store = transaction.objectStore(STORE_NAME);\n const request = store.clear();\n \n request.onsuccess = () => resolve();\n request.onerror = () => {\n reject(new SessionError(\n 'Failed to clear sessions',\n SessionErrorCode.STORAGE_ERROR,\n request.error\n ));\n };\n });\n } catch (error) {\n if (error instanceof SessionError) {\n throw error;\n }\n throw new SessionError(\n 'Failed to clear sessions',\n SessionErrorCode.STORAGE_ERROR,\n error\n );\n }\n }\n \n /**\n * Check if any session exists\n */\n async exists(): Promise<boolean> {\n try {\n await this.initialize();\n \n if (!this.db) {\n return false;\n }\n \n const sessions = await this.getAllSessions();\n return sessions.length > 0;\n } catch {\n return false;\n }\n }\n \n /**\n * Close database connection\n */\n close(): void {\n if (this.db) {\n this.db.close();\n this.db = null;\n }\n }\n}\n\n// ============================================================================\n// LocalStorage Session Storage (Fallback)\n// ============================================================================\n\n/** LocalStorage key prefix */\nconst STORAGE_KEY_PREFIX = 'veridex-session-';\n\n/**\n * LocalStorage-based session storage with encryption\n * \n * Fallback storage backend when IndexedDB is unavailable.\n * \n * Limitations:\n * - Smaller storage quota (~10MB)\n * - Synchronous API (blocks main thread)\n * - String-based storage (requires serialization)\n */\nexport class LocalStorageSessionStorage implements SessionStorage {\n private encryptionKey: CryptoKey | null = null;\n private credentialId: string;\n private storageKey: string;\n \n /**\n * @param credentialId User's Passkey credential ID (for key derivation)\n */\n constructor(credentialId: string) {\n if (!credentialId) {\n throw new SessionError(\n 'Credential ID required for session storage',\n SessionErrorCode.INVALID_CONFIG\n );\n }\n this.credentialId = credentialId;\n this.storageKey = STORAGE_KEY_PREFIX + ethers.keccak256(ethers.toUtf8Bytes(credentialId));\n }\n \n /**\n * Get or derive encryption key\n */\n private async getEncryptionKey(): Promise<CryptoKey> {\n if (this.encryptionKey) {\n return this.encryptionKey;\n }\n \n this.encryptionKey = await deriveEncryptionKey(this.credentialId);\n return this.encryptionKey;\n }\n \n /**\n * Save a session (encrypts private key)\n */\n async save(session: SessionKey): Promise<void> {\n try {\n // Get encryption key\n const key = await this.getEncryptionKey();\n \n // Encrypt private key\n const encryptedPrivateKey = await encrypt(session.privateKey, key);\n \n // Prepare storage object\n const storageObject = {\n keyHash: session.keyHash,\n publicKey: ethers.hexlify(session.publicKey),\n encryptedPrivateKey: ethers.hexlify(encryptedPrivateKey),\n expiry: session.expiry,\n maxValue: session.maxValue.toString(),\n chainScopes: session.chainScopes,\n userKeyHash: session.userKeyHash,\n savedAt: Date.now(),\n };\n \n // Store as JSON\n localStorage.setItem(this.storageKey, JSON.stringify(storageObject));\n } catch (error) {\n if (error instanceof SessionError) {\n throw error;\n }\n throw new SessionError(\n 'Failed to save session',\n SessionErrorCode.STORAGE_ERROR,\n error\n );\n }\n }\n \n /**\n * Load the active session (decrypts private key)\n */\n async load(): Promise<SessionKey | null> {\n try {\n const data = localStorage.getItem(this.storageKey);\n \n if (!data) {\n return null;\n }\n \n const stored = JSON.parse(data);\n \n // Check if expired\n if (stored.expiry <= Date.now()) {\n await this.clear();\n return null;\n }\n \n // Get encryption key\n const key = await this.getEncryptionKey();\n \n // Decrypt private key\n const encryptedPrivateKey = ethers.getBytes(stored.encryptedPrivateKey);\n const privateKey = await decrypt(encryptedPrivateKey, key);\n \n // Reconstruct session\n const session: SessionKey = {\n keyHash: stored.keyHash,\n publicKey: ethers.getBytes(stored.publicKey),\n privateKey,\n expiry: stored.expiry,\n maxValue: BigInt(stored.maxValue),\n chainScopes: stored.chainScopes,\n userKeyHash: stored.userKeyHash,\n };\n \n return session;\n } catch (error) {\n // Clear corrupted data\n await this.clear();\n \n if (error instanceof SessionError) {\n throw error;\n }\n throw new SessionError(\n 'Failed to load session',\n SessionErrorCode.STORAGE_ERROR,\n error\n );\n }\n }\n \n /**\n * Clear all sessions\n */\n async clear(): Promise<void> {\n try {\n localStorage.removeItem(this.storageKey);\n } catch (error) {\n throw new SessionError(\n 'Failed to clear sessions',\n SessionErrorCode.STORAGE_ERROR,\n error\n );\n }\n }\n \n /**\n * Check if any session exists\n */\n async exists(): Promise<boolean> {\n try {\n return localStorage.getItem(this.storageKey) !== null;\n } catch {\n return false;\n }\n }\n}\n\n// ============================================================================\n// Storage Factory\n// ============================================================================\n\n/**\n * Create appropriate session storage based on environment\n * \n * @param credentialId User's Passkey credential ID\n * @param preferredBackend Preferred storage backend ('indexeddb' or 'localstorage')\n * @returns Session storage implementation\n */\nexport function createSessionStorage(\n credentialId: string,\n preferredBackend?: 'indexeddb' | 'localstorage'\n): SessionStorage {\n // Check if running in browser\n if (typeof window === 'undefined') {\n throw new SessionError(\n 'Session storage requires browser environment',\n SessionErrorCode.STORAGE_ERROR\n );\n }\n \n // Try IndexedDB first (if not explicitly requesting localStorage)\n if (preferredBackend !== 'localstorage' && typeof indexedDB !== 'undefined') {\n try {\n return new IndexedDBSessionStorage(credentialId);\n } catch (error) {\n console.warn('IndexedDB unavailable, falling back to LocalStorage:', error);\n }\n }\n \n // Fallback to LocalStorage\n if (typeof localStorage !== 'undefined') {\n return new LocalStorageSessionStorage(credentialId);\n }\n \n throw new SessionError(\n 'No storage backend available (requires IndexedDB or LocalStorage)',\n SessionErrorCode.STORAGE_ERROR\n );\n}\n","/**\n * Veridex Protocol SDK - EVM Hub Client Adapter\n * \n * Adapts EVMClient to work with SessionManager's HubClient interface.\n * Provides a clean integration layer between session management and chain clients.\n */\n\nimport type { HubClient } from '../../sessions/index.js';\nimport type { RegisterSessionParams, RevokeSessionParams } from '../../types.js';\nimport type { EVMClient } from './EVMClient.js';\nimport type { ethers } from 'ethers';\n\n/**\n * Adapter that makes EVMClient compatible with SessionManager's HubClient interface\n * \n * Usage:\n * ```typescript\n * const hubAdapter = new EVMHubClientAdapter(evmClient, signer);\n * const sessionManager = new SessionManager(\n * credential,\n * hubAdapter,\n * config\n * );\n * ```\n */\nexport class EVMHubClientAdapter implements HubClient {\n constructor(\n private evmClient: EVMClient,\n private signer: ethers.Signer\n ) {}\n \n /**\n * Register a session on the Hub\n * \n * @param params Registration parameters with Passkey signature\n * @returns Promise that resolves when registration completes\n */\n async registerSession(params: RegisterSessionParams): Promise<void> {\n // Call EVMClient's registerSession method\n await this.evmClient.registerSession(params, this.signer);\n }\n \n /**\n * Revoke a session on the Hub\n * \n * @param params Revocation parameters with Passkey signature\n * @returns Promise that resolves when revocation completes\n */\n async revokeSession(params: RevokeSessionParams): Promise<void> {\n // Call EVMClient's revokeSession method\n await this.evmClient.revokeSession(params, this.signer);\n }\n \n /**\n * Update the signer (e.g., when switching accounts)\n * \n * @param signer New Ethereum signer\n */\n updateSigner(signer: ethers.Signer): void {\n this.signer = signer;\n }\n}\n","/**\n * Veridex Solana Program Error Codes\n *\n * Error code constants for parsing and handling Veridex program errors.\n * These codes map directly to the Anchor error enum variants in the\n * Solana program.\n *\n * @packageDocumentation\n */\n\n// ============================================================================\n// Error Code Ranges\n// ============================================================================\n\n/**\n * Error code range boundaries.\n * Use these to categorize errors programmatically.\n */\nexport const ERROR_RANGES = {\n /** Core protocol errors (paused, unauthorized, limits, etc.) */\n CORE: { min: 6000, max: 6099 },\n /** Query execution errors */\n QUERY_EXECUTION: { min: 6100, max: 6149 },\n /** ABI decoding errors */\n ABI: { min: 6150, max: 6199 },\n /** Query parsing/validation errors */\n QUERY_PARSING: { min: 6200, max: 6299 },\n} as const;\n\n// ============================================================================\n// Core Protocol Error Codes (6000-6099)\n// ============================================================================\n\nexport const VERIDEX_ERRORS = {\n // Core Protocol Errors\n /** Protocol is globally paused */\n PROTOCOL_PAUSED: 6000,\n /** Vault is paused */\n VAULT_PAUSED: 6001,\n /** VAA already processed (replay protection) */\n VAA_ALREADY_PROCESSED: 6002,\n /** Invalid emitter chain */\n INVALID_EMITTER_CHAIN: 6003,\n /** Invalid emitter address */\n INVALID_EMITTER: 6004,\n /** Invalid owner */\n INVALID_OWNER: 6005,\n /** Invalid target chain */\n INVALID_TARGET_CHAIN: 6006,\n /** Invalid payload version */\n INVALID_PAYLOAD_VERSION: 6007,\n /** Invalid action payload */\n INVALID_ACTION_PAYLOAD: 6008,\n /** Invalid action type */\n INVALID_ACTION_TYPE: 6009,\n /** Daily limit exceeded */\n DAILY_LIMIT_EXCEEDED: 6010,\n /** Insufficient funds */\n INSUFFICIENT_FUNDS: 6011,\n /** Unauthorized */\n UNAUTHORIZED: 6012,\n /** Invalid VAA */\n INVALID_VAA: 6013,\n /** Token bridge not configured */\n TOKEN_BRIDGE_NOT_CONFIGURED: 6014,\n /** Invalid bridge parameters */\n INVALID_BRIDGE_PARAMS: 6015,\n\n // Query Execution Errors (6100-6149)\n /** Invalid query response format */\n INVALID_QUERY_RESPONSE: 6100,\n /** Query response expired (> 60 seconds old) */\n QUERY_EXPIRED: 6101,\n /** Query signature verification failed */\n QUERY_INVALID: 6102,\n /** Query result doesn't match expected state */\n QUERY_MISMATCH: 6103,\n /** Query block time is in the future */\n QUERY_FUTURE_BLOCK: 6104,\n /** Invalid nonce in query response */\n INVALID_QUERY_NONCE: 6105,\n /** Secp256k1 verification instruction missing */\n SECP256K1_INSTRUCTION_MISSING: 6106,\n /** Invalid secp256k1 instruction format */\n INVALID_SECP256K1_INSTRUCTION: 6107,\n /** Insufficient Guardian signatures on query */\n INSUFFICIENT_SIGNATURES: 6108,\n /** Chain ID mismatch in query response */\n CHAIN_ID_MISMATCH: 6109,\n /** Query result not found */\n QUERY_RESULT_NOT_FOUND: 6110,\n\n // ABI Decoding Errors (6150-6199)\n /** ABI decoding: insufficient data */\n ABI_INSUFFICIENT_DATA: 6150,\n /** ABI decoding: value overflow */\n ABI_OVERFLOW: 6151,\n /** ABI decoding: invalid encoding */\n ABI_INVALID_ENCODING: 6152,\n /** ABI decoding: general failure */\n ABI_DECODING_FAILED: 6153,\n\n // Query Parsing Errors (6200-6299)\n /** Invalid query response format (parsing) */\n QUERY_PARSE_INVALID_RESPONSE: 6200,\n /** Invalid query version */\n QUERY_PARSE_INVALID_VERSION: 6201,\n /** Unsupported query type */\n QUERY_PARSE_UNSUPPORTED_TYPE: 6202,\n /** Query response is stale (parsing) */\n QUERY_PARSE_STALE: 6203,\n /** Query block time is in the future (parsing) */\n QUERY_PARSE_FUTURE_BLOCK: 6204,\n /** Invalid Hub state data */\n QUERY_PARSE_INVALID_HUB_STATE: 6205,\n /** Invalid nonce (parsing) */\n QUERY_PARSE_INVALID_NONCE: 6206,\n /** Query result doesn't match expected (parsing) */\n QUERY_PARSE_MISMATCH: 6207,\n /** Secp256k1 instruction not found (parsing) */\n QUERY_PARSE_SECP256K1_MISSING: 6208,\n /** Invalid Secp256k1 instruction (parsing) */\n QUERY_PARSE_INVALID_SECP256K1: 6209,\n /** Insufficient Guardian signatures (parsing) */\n QUERY_PARSE_INSUFFICIENT_SIGS: 6210,\n /** Invalid Guardian signature (parsing) */\n QUERY_PARSE_INVALID_GUARDIAN_SIG: 6211,\n /** Chain ID mismatch (parsing) */\n QUERY_PARSE_CHAIN_ID_MISMATCH: 6212,\n /** Guardian index out of range */\n QUERY_PARSE_GUARDIAN_INDEX_OOB: 6213,\n /** Non-increasing Guardian index */\n QUERY_PARSE_NON_INCREASING_INDEX: 6214,\n /** Query signature verification failed (parsing) */\n QUERY_PARSE_INVALID_SIGNATURE: 6215,\n /** ABI decoding failed (parsing) */\n QUERY_PARSE_ABI_FAILED: 6216,\n} as const;\n\nexport type VeridexErrorCode = (typeof VERIDEX_ERRORS)[keyof typeof VERIDEX_ERRORS];\n\n// ============================================================================\n// Error Messages\n// ============================================================================\n\n/**\n * Human-readable error messages for each error code.\n */\nexport const ERROR_MESSAGES: Record<VeridexErrorCode, string> = {\n // Core Protocol Errors\n [VERIDEX_ERRORS.PROTOCOL_PAUSED]: \"Protocol is paused\",\n [VERIDEX_ERRORS.VAULT_PAUSED]: \"Vault is paused\",\n [VERIDEX_ERRORS.VAA_ALREADY_PROCESSED]:\n \"This transaction has already been processed\",\n [VERIDEX_ERRORS.INVALID_EMITTER_CHAIN]: \"Invalid emitter chain\",\n [VERIDEX_ERRORS.INVALID_EMITTER]: \"Invalid emitter address\",\n [VERIDEX_ERRORS.INVALID_OWNER]: \"Invalid owner\",\n [VERIDEX_ERRORS.INVALID_TARGET_CHAIN]: \"Invalid target chain\",\n [VERIDEX_ERRORS.INVALID_PAYLOAD_VERSION]: \"Unsupported payload version\",\n [VERIDEX_ERRORS.INVALID_ACTION_PAYLOAD]: \"Invalid action payload\",\n [VERIDEX_ERRORS.INVALID_ACTION_TYPE]: \"Unknown action type\",\n [VERIDEX_ERRORS.DAILY_LIMIT_EXCEEDED]: \"Daily spending limit exceeded\",\n [VERIDEX_ERRORS.INSUFFICIENT_FUNDS]: \"Insufficient funds in vault\",\n [VERIDEX_ERRORS.UNAUTHORIZED]: \"Unauthorized\",\n [VERIDEX_ERRORS.INVALID_VAA]: \"Invalid VAA\",\n [VERIDEX_ERRORS.TOKEN_BRIDGE_NOT_CONFIGURED]: \"Token bridge not configured\",\n [VERIDEX_ERRORS.INVALID_BRIDGE_PARAMS]: \"Invalid bridge parameters\",\n\n // Query Execution Errors\n [VERIDEX_ERRORS.INVALID_QUERY_RESPONSE]: \"Invalid query response format\",\n [VERIDEX_ERRORS.QUERY_EXPIRED]:\n \"Query has expired. Please refresh and try again.\",\n [VERIDEX_ERRORS.QUERY_INVALID]: \"Query signature verification failed\",\n [VERIDEX_ERRORS.QUERY_MISMATCH]: \"Query result does not match expected state\",\n [VERIDEX_ERRORS.QUERY_FUTURE_BLOCK]:\n \"Query block time is in the future. Possible clock skew.\",\n [VERIDEX_ERRORS.INVALID_QUERY_NONCE]: \"Invalid nonce in query response\",\n [VERIDEX_ERRORS.SECP256K1_INSTRUCTION_MISSING]:\n \"Secp256k1 verification instruction missing\",\n [VERIDEX_ERRORS.INVALID_SECP256K1_INSTRUCTION]:\n \"Invalid secp256k1 instruction format\",\n [VERIDEX_ERRORS.INSUFFICIENT_SIGNATURES]:\n \"Insufficient Guardian signatures on query\",\n [VERIDEX_ERRORS.CHAIN_ID_MISMATCH]: \"Chain ID mismatch in query response\",\n [VERIDEX_ERRORS.QUERY_RESULT_NOT_FOUND]: \"Query result not found\",\n\n // ABI Decoding Errors\n [VERIDEX_ERRORS.ABI_INSUFFICIENT_DATA]: \"ABI decoding failed: insufficient data\",\n [VERIDEX_ERRORS.ABI_OVERFLOW]: \"ABI decoding failed: value overflow\",\n [VERIDEX_ERRORS.ABI_INVALID_ENCODING]: \"ABI decoding failed: invalid encoding\",\n [VERIDEX_ERRORS.ABI_DECODING_FAILED]: \"Failed to decode data from Hub\",\n\n // Query Parsing Errors\n [VERIDEX_ERRORS.QUERY_PARSE_INVALID_RESPONSE]: \"Invalid query response format\",\n [VERIDEX_ERRORS.QUERY_PARSE_INVALID_VERSION]: \"Invalid query version\",\n [VERIDEX_ERRORS.QUERY_PARSE_UNSUPPORTED_TYPE]: \"Unsupported query type\",\n [VERIDEX_ERRORS.QUERY_PARSE_STALE]: \"Query response is stale\",\n [VERIDEX_ERRORS.QUERY_PARSE_FUTURE_BLOCK]: \"Query block time is in the future\",\n [VERIDEX_ERRORS.QUERY_PARSE_INVALID_HUB_STATE]: \"Invalid Hub state data\",\n [VERIDEX_ERRORS.QUERY_PARSE_INVALID_NONCE]: \"Invalid nonce in query\",\n [VERIDEX_ERRORS.QUERY_PARSE_MISMATCH]: \"Query result mismatch\",\n [VERIDEX_ERRORS.QUERY_PARSE_SECP256K1_MISSING]: \"Secp256k1 instruction not found\",\n [VERIDEX_ERRORS.QUERY_PARSE_INVALID_SECP256K1]: \"Invalid Secp256k1 instruction\",\n [VERIDEX_ERRORS.QUERY_PARSE_INSUFFICIENT_SIGS]:\n \"Insufficient Guardian signatures\",\n [VERIDEX_ERRORS.QUERY_PARSE_INVALID_GUARDIAN_SIG]: \"Invalid Guardian signature\",\n [VERIDEX_ERRORS.QUERY_PARSE_CHAIN_ID_MISMATCH]: \"Chain ID mismatch\",\n [VERIDEX_ERRORS.QUERY_PARSE_GUARDIAN_INDEX_OOB]: \"Guardian index out of range\",\n [VERIDEX_ERRORS.QUERY_PARSE_NON_INCREASING_INDEX]:\n \"Non-increasing Guardian index\",\n [VERIDEX_ERRORS.QUERY_PARSE_INVALID_SIGNATURE]:\n \"Query signature verification failed\",\n [VERIDEX_ERRORS.QUERY_PARSE_ABI_FAILED]: \"ABI decoding failed\",\n};\n\n// ============================================================================\n// Helper Functions\n// ============================================================================\n\n/**\n * Check if an error code is in the core protocol range.\n */\nexport function isCoreError(code: number): boolean {\n return code >= ERROR_RANGES.CORE.min && code <= ERROR_RANGES.CORE.max;\n}\n\n/**\n * Check if an error code is a query execution error.\n */\nexport function isQueryExecutionError(code: number): boolean {\n return (\n code >= ERROR_RANGES.QUERY_EXECUTION.min &&\n code <= ERROR_RANGES.QUERY_EXECUTION.max\n );\n}\n\n/**\n * Check if an error code is an ABI decoding error.\n */\nexport function isAbiError(code: number): boolean {\n return code >= ERROR_RANGES.ABI.min && code <= ERROR_RANGES.ABI.max;\n}\n\n/**\n * Check if an error code is a query parsing error.\n */\nexport function isQueryParsingError(code: number): boolean {\n return (\n code >= ERROR_RANGES.QUERY_PARSING.min &&\n code <= ERROR_RANGES.QUERY_PARSING.max\n );\n}\n\n/**\n * Check if an error is related to query operations (execution or parsing).\n */\nexport function isQueryError(code: number): boolean {\n return isQueryExecutionError(code) || isQueryParsingError(code);\n}\n\n/**\n * Get the error category as a human-readable string.\n */\nexport function getErrorCategory(code: number): string {\n if (isCoreError(code)) return \"Core Protocol\";\n if (isQueryExecutionError(code)) return \"Query Execution\";\n if (isAbiError(code)) return \"ABI Decoding\";\n if (isQueryParsingError(code)) return \"Query Parsing\";\n return \"Unknown\";\n}\n\n/**\n * Get the human-readable message for an error code.\n */\nexport function getErrorMessage(code: number): string {\n return ERROR_MESSAGES[code as VeridexErrorCode] ?? `Unknown error: ${code}`;\n}\n\n/**\n * Parse an Anchor program error to extract the Veridex error code.\n *\n * @param error - The error object from a failed transaction\n * @returns The error code if found, undefined otherwise\n */\nexport function parseVeridexError(error: unknown): VeridexErrorCode | undefined {\n if (!error || typeof error !== \"object\") return undefined;\n\n // Handle Anchor ProgramError\n const anchorError = error as {\n code?: number;\n error?: { errorCode?: { code?: string; number?: number } };\n };\n\n // Try direct code property\n if (typeof anchorError.code === \"number\") {\n if (anchorError.code in ERROR_MESSAGES) {\n return anchorError.code as VeridexErrorCode;\n }\n }\n\n // Try Anchor v0.30+ error format\n if (anchorError.error?.errorCode?.number !== undefined) {\n const code = anchorError.error.errorCode.number;\n if (code in ERROR_MESSAGES) {\n return code as VeridexErrorCode;\n }\n }\n\n return undefined;\n}\n\n/**\n * Check if the error is a retryable error (e.g., expired query can be refreshed).\n */\nexport function isRetryableError(code: number): boolean {\n const retryableCodes: number[] = [\n VERIDEX_ERRORS.QUERY_EXPIRED,\n VERIDEX_ERRORS.QUERY_PARSE_STALE,\n VERIDEX_ERRORS.QUERY_FUTURE_BLOCK,\n VERIDEX_ERRORS.QUERY_PARSE_FUTURE_BLOCK,\n VERIDEX_ERRORS.QUERY_MISMATCH,\n VERIDEX_ERRORS.QUERY_PARSE_MISMATCH,\n ];\n return retryableCodes.includes(code);\n}\n\n/**\n * Suggested user action for common errors.\n */\nexport function getSuggestedAction(code: number): string {\n switch (code) {\n case VERIDEX_ERRORS.QUERY_EXPIRED:\n case VERIDEX_ERRORS.QUERY_PARSE_STALE:\n return \"The query data has expired. Please refresh and try again.\";\n case VERIDEX_ERRORS.QUERY_FUTURE_BLOCK:\n case VERIDEX_ERRORS.QUERY_PARSE_FUTURE_BLOCK:\n return \"Clock synchronization issue detected. Please wait a moment and retry.\";\n case VERIDEX_ERRORS.INSUFFICIENT_FUNDS:\n return \"Add more funds to your vault before attempting this operation.\";\n case VERIDEX_ERRORS.DAILY_LIMIT_EXCEEDED:\n return \"Daily spending limit exceeded. Wait until tomorrow or increase your limit.\";\n case VERIDEX_ERRORS.PROTOCOL_PAUSED:\n return \"The protocol is temporarily paused. Please try again later.\";\n case VERIDEX_ERRORS.VAULT_PAUSED:\n return \"Your vault is paused. Contact support if this is unexpected.\";\n case VERIDEX_ERRORS.INSUFFICIENT_SIGNATURES:\n case VERIDEX_ERRORS.QUERY_PARSE_INSUFFICIENT_SIGS:\n return \"Waiting for Guardian consensus. Please try again in a few seconds.\";\n default:\n return \"An error occurred. Please try again or contact support.\";\n }\n}\n"],"mappings":";AAMA;AAAA,EACI;AAAA,EACA;AAAA,EACA;AAAA,OACG;AAOP,SAAS,UAAAA,eAAc;;;ACbvB,SAAS,cAAc;;;ACMhB,IAAM,eAAe;AAAA,EAC1B,UAAU;AAAA,EACV,SAAS;AAAA,EACT,QAAQ;AAAA,EACR,QAAQ;AACV;AAEO,IAAM,kBAAkB;AACxB,IAAM,iBAAiB;AACvB,IAAM,gBAAgB;AACtB,IAAM,gBAAgB;AAGtB,IAAM,mBAAmB;AAUzB,IAAM,qBAAqB;AAAA,EAChC,SAAS;AAAA,IACP,QAAQ;AAAA,IACR,UAAU;AAAA,IACV,OAAO;AAAA,IACP,KAAK;AAAA,IACL,SAAS;AAAA,IACT,WAAW;AAAA,IACX,OAAO;AAAA,IACP,UAAU;AAAA,IACV,QAAQ;AAAA,IACR,QAAQ;AAAA,IACR,QAAQ;AAAA,IACR,OAAO;AAAA,IACP,QAAQ;AAAA,IACR,MAAM;AAAA,IACN,MAAM;AAAA,IACN,UAAU;AAAA,IACV,MAAM;AAAA,IACN,QAAQ;AAAA,IACR,WAAW;AAAA,IACX,SAAS;AAAA,IACT,KAAK;AAAA,IACL,OAAO;AAAA,IACP,UAAU;AAAA,IACV,UAAU;AAAA,IACV,QAAQ;AAAA,IACR,SAAS;AAAA,IACT,MAAM;AAAA,IACN,MAAM;AAAA,IACN,KAAK;AAAA,IACL,WAAW;AAAA,IACX,QAAQ;AAAA,IACR,QAAQ;AAAA,IACR,OAAO;AAAA,IACP,QAAQ;AAAA,IACR,OAAO;AAAA,IACP,WAAW;AAAA,IACX,QAAQ;AAAA,EACV;AAAA,EACA,SAAS;AAAA,IACP,eAAe;AAAA,IACf,QAAQ;AAAA,IACR,aAAa;AAAA,IACb,gBAAgB;AAAA,IAChB,gBAAgB;AAAA,IAChB,gBAAgB;AAAA,IAChB,gBAAgB;AAAA,IAChB,gBAAgB;AAAA,IAChB,aAAa;AAAA,IACb,eAAe;AAAA,IACf,SAAS;AAAA,IACT,kBAAkB;AAAA,IAClB,cAAc;AAAA,IACd,kBAAkB;AAAA,IAClB,SAAS;AAAA,IACT,iBAAiB;AAAA,IACjB,gBAAgB;AAAA;AAAA,IAChB,kBAAkB;AAAA;AAAA,EACpB;AACF;AAGO,IAAM,0BAA0B;AAAA;AAAA,EAErC,QAAQ;AAAA,EACR,UAAU;AAAA,EACV,OAAO;AAAA,EACP,KAAK;AAAA,EACL,SAAS;AAAA,EACT,WAAW;AAAA,EACX,OAAO;AAAA,EACP,UAAU;AAAA,EACV,QAAQ;AAAA,EACR,QAAQ;AAAA,EACR,QAAQ;AAAA,EACR,OAAO;AAAA,EACP,QAAQ;AAAA,EACR,MAAM;AAAA,EACN,MAAM;AAAA,EACN,UAAU;AAAA,EACV,MAAM;AAAA,EACN,QAAQ;AAAA,EACR,WAAW;AAAA,EACX,SAAS;AAAA,EACT,KAAK;AAAA,EACL,OAAO;AAAA,EACP,UAAU;AAAA,EACV,UAAU;AAAA,EACV,QAAQ;AAAA,EACR,SAAS;AAAA,EACT,MAAM;AAAA,EACN,MAAM;AAAA,EACN,KAAK;AAAA,EACL,WAAW;AAAA,EACX,QAAQ;AAAA,EACR,QAAQ;AAAA,EACR,OAAO;AAAA,EACP,QAAQ;AAAA,EACR,OAAO;AAAA,EACP,WAAW;AAAA,EACX,QAAQ;AAAA;AAAA,EAGR,eAAe;AAAA,EACf,QAAQ;AAAA,EACR,aAAa;AAAA,EACb,gBAAgB;AAAA,EAChB,gBAAgB;AAAA,EAChB,gBAAgB;AAAA,EAChB,gBAAgB;AAAA,EAChB,gBAAgB;AAAA,EAChB,aAAa;AAAA,EACb,eAAe;AAAA,EACf,kBAAkB;AAAA,EAClB,cAAc;AAAA,EACd,kBAAkB;AAAA,EAClB,iBAAiB;AAAA,EACjB,SAAS;AAAA,EACT,kBAAkB;AAAA;AACpB;AAMO,IAAM,iBAA8C;AAAA,EACzD,aAAa;AAAA,IACX,MAAM;AAAA,IACN,SAAS;AAAA,IACT,iBAAiB;AAAA,IACjB,QAAQ;AAAA;AAAA,IACR,aAAa;AAAA,IACb,OAAO;AAAA,IACP,WAAW;AAAA,MACT,KAAK;AAAA,MACL,cAAc;AAAA,MACd,qBAAqB;AAAA,MACrB,oBAAoB;AAAA,MACpB,aAAa;AAAA,IACf;AAAA,EACF;AAAA,EACA,iBAAiB;AAAA,IACf,MAAM;AAAA,IACN,SAAS;AAAA,IACT,iBAAiB;AAAA,IACjB,QAAQ;AAAA,IACR,aAAa;AAAA,IACb,OAAO;AAAA,IACP,WAAW;AAAA,MACT,cAAc;AAAA,MACd,qBAAqB;AAAA,MACrB,oBAAoB;AAAA,MACpB,aAAa;AAAA,IACf;AAAA,EACF;AAAA,EACA,iBAAiB;AAAA,IACf,MAAM;AAAA,IACN,SAAS;AAAA,IACT,iBAAiB;AAAA,IACjB,QAAQ;AAAA,IACR,aAAa;AAAA,IACb,OAAO;AAAA,IACP,WAAW;AAAA,MACT,cAAc;AAAA,MACd,qBAAqB;AAAA,MACrB,oBAAoB;AAAA,MACpB,aAAa;AAAA,IACf;AAAA,EACF;AAAA,EACA,YAAY;AAAA,IACV,MAAM;AAAA,IACN,SAAS;AAAA,IACT,iBAAiB;AAAA,IACjB,QAAQ;AAAA,IACR,aAAa;AAAA,IACb,OAAO;AAAA,IACP,WAAW;AAAA,MACT,cAAc;AAAA,MACd,qBAAqB;AAAA,MACrB,oBAAoB;AAAA;AAAA,IACtB;AAAA,EACF;AAAA,EACA,cAAc;AAAA,IACZ,MAAM;AAAA,IACN,SAAS;AAAA,IACT,iBAAiB;AAAA,IACjB,QAAQ;AAAA,IACR,aAAa;AAAA,IACb,OAAO;AAAA,IACP,WAAW;AAAA,MACT,KAAK;AAAA,MACL,oBAAoB;AAAA,MACpB,aAAa;AAAA,IACf;AAAA,EACF;AAAA,EACA,cAAc;AAAA,IACZ,MAAM;AAAA,IACN,SAAS;AAAA,IACT,iBAAiB;AAAA,IACjB,QAAQ;AAAA,IACR,aAAa;AAAA,IACb,OAAO;AAAA,IACP,WAAW;AAAA,MACT,KAAK;AAAA,MACL,oBAAoB;AAAA,MACpB,aAAa;AAAA,IACf;AAAA,EACF;AAAA,EACA,YAAY;AAAA,IACV,MAAM;AAAA,IACN,SAAS;AAAA,IACT,iBAAiB;AAAA,IACjB,QAAQ;AAAA,IACR,aAAa;AAAA,IACb,OAAO;AAAA,IACP,WAAW;AAAA,MACT,KAAK;AAAA,MACL,oBAAoB;AAAA,IACtB;AAAA,EACF;AAAA,EACA,iBAAiB;AAAA,IACf,MAAM;AAAA,IACN,SAAS;AAAA;AAAA,IACT,iBAAiB;AAAA;AAAA,IACjB,QAAQ;AAAA,IACR,aAAa;AAAA,IACb,OAAO;AAAA,IACP,WAAW;AAAA;AAAA,MAET,KAAK;AAAA;AAAA,MAEL,oBAAoB;AAAA,IACtB;AAAA;AAAA,IAEA,YAAY;AAAA,EACd;AACF;AAMO,IAAM,iBAA8C;AAAA,EACzD,UAAU;AAAA,IACR,MAAM;AAAA,IACN,SAAS;AAAA,IACT,iBAAiB;AAAA,IACjB,QAAQ;AAAA,IACR,aAAa;AAAA,IACb,OAAO;AAAA,IACP,WAAW;AAAA,MACT,oBAAoB;AAAA,MACpB,aAAa;AAAA,IACf;AAAA,EACF;AAAA,EACA,MAAM;AAAA,IACJ,MAAM;AAAA,IACN,SAAS;AAAA,IACT,iBAAiB;AAAA,IACjB,QAAQ;AAAA,IACR,aAAa;AAAA,IACb,OAAO;AAAA,IACP,WAAW;AAAA,MACT,oBAAoB;AAAA,MACpB,aAAa;AAAA,IACf;AAAA,EACF;AAAA,EACA,UAAU;AAAA,IACR,MAAM;AAAA,IACN,SAAS;AAAA,IACT,iBAAiB;AAAA,IACjB,QAAQ;AAAA,IACR,aAAa;AAAA,IACb,OAAO;AAAA,IACP,WAAW;AAAA,MACT,oBAAoB;AAAA,MACpB,aAAa;AAAA,IACf;AAAA,EACF;AAAA,EACA,UAAU;AAAA,IACR,MAAM;AAAA,IACN,SAAS;AAAA,IACT,iBAAiB;AAAA,IACjB,QAAQ;AAAA,IACR,aAAa;AAAA,IACb,OAAO;AAAA,IACP,WAAW;AAAA,MACT,oBAAoB;AAAA,MACpB,aAAa;AAAA,IACf;AAAA,EACF;AAAA,EACA,SAAS;AAAA,IACP,MAAM;AAAA,IACN,SAAS;AAAA,IACT,iBAAiB;AAAA,IACjB,QAAQ;AAAA,IACR,aAAa;AAAA,IACb,OAAO;AAAA,IACP,WAAW;AAAA,MACT,oBAAoB;AAAA,MACpB,aAAa;AAAA,IACf;AAAA,EACF;AAAA,EACA,QAAQ;AAAA,IACN,MAAM;AAAA,IACN,SAAS;AAAA,IACT,iBAAiB;AAAA,IACjB,QAAQ;AAAA,IACR,aAAa;AAAA,IACb,OAAO;AAAA,IACP,WAAW;AAAA,MACT,oBAAoB;AAAA,MACpB,aAAa;AAAA,IACf;AAAA,EACF;AAAA,EACA,OAAO;AAAA,IACL,MAAM;AAAA,IACN,SAAS;AAAA,IACT,iBAAiB;AAAA,IACjB,QAAQ;AAAA,IACR,aAAa;AAAA,IACb,OAAO;AAAA,IACP,WAAW;AAAA,MACT,oBAAoB;AAAA,MACpB,aAAa;AAAA,IACf;AAAA,EACF;AAAA,EACA,KAAK;AAAA,IACH,MAAM;AAAA,IACN,SAAS;AAAA,IACT,iBAAiB;AAAA,IACjB,QAAQ;AAAA,IACR,aAAa;AAAA,IACb,OAAO;AAAA,IACP,WAAW;AAAA,MACT,oBAAoB;AAAA,IACtB;AAAA,EACF;AACF;AAMO,IAAM,eAAe;AAAA,EAC1B,SAAS;AAAA,EACT,SAAS;AAAA,EACT,sBAAsB;AAAA,EACtB,sBAAsB;AACxB;AAMO,IAAM,UAAU;AAAA,EACrB;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF;AAMO,IAAM,oBAAoB;AAAA,EAC/B;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF;AAMO,IAAM,YAAY;AAAA,EACvB;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF;;;ADtZO,SAAS,gBAAgB,QAA4B;AAE1D,QAAM,QAAQ,MAAM,KAAK,MAAM;AAC/B,QAAM,SAAS,OAAO,aAAa,GAAG,KAAK;AAC3C,QAAM,SAAS,KAAK,MAAM;AAC1B,SAAO,OAAO,QAAQ,OAAO,GAAG,EAAE,QAAQ,OAAO,GAAG,EAAE,QAAQ,MAAM,EAAE;AACxE;AAKO,SAAS,gBAAgB,KAAyB;AACvD,QAAM,SAAS,IAAI,QAAQ,MAAM,GAAG,EAAE,QAAQ,MAAM,GAAG;AACvD,QAAM,SAAS,SAAS,IAAI,QAAQ,IAAK,OAAO,SAAS,KAAM,CAAC;AAEhE,QAAM,SAAS,KAAK,MAAM;AAC1B,QAAM,QAAQ,IAAI,WAAW,OAAO,MAAM;AAC1C,WAAS,IAAI,GAAG,IAAI,OAAO,QAAQ,KAAK;AACtC,UAAM,CAAC,IAAI,OAAO,WAAW,CAAC;AAAA,EAChC;AACA,SAAO;AACT;AASO,SAAS,kBAAkB,WAAyD;AACzF,MAAI,SAAS;AAEb,MAAI,UAAU,QAAQ,MAAM,IAAM;AAChC,UAAM,IAAI,MAAM,0BAA0B;AAAA,EAC5C;AAGA;AAEA,MAAI,UAAU,QAAQ,MAAM,GAAM;AAChC,UAAM,IAAI,MAAM,0BAA0B;AAAA,EAC5C;AAEA,QAAM,UAAU,UAAU,QAAQ;AAClC,MAAI,YAAY,QAAW;AACzB,UAAM,IAAI,MAAM,4CAA4C;AAAA,EAC9D;AACA,MAAI,IAAI,UAAU,MAAM,QAAQ,SAAS,OAAO;AAChD,YAAU;AAGV,MAAI,EAAE,CAAC,MAAM,KAAQ,EAAE,SAAS,IAAI;AAClC,QAAI,EAAE,MAAM,CAAC;AAAA,EACf;AAEA,MAAI,EAAE,SAAS,IAAI;AACjB,UAAM,SAAS,IAAI,WAAW,EAAE;AAChC,WAAO,IAAI,GAAG,KAAK,EAAE,MAAM;AAC3B,QAAI;AAAA,EACN;AAEA,MAAI,UAAU,QAAQ,MAAM,GAAM;AAChC,UAAM,IAAI,MAAM,0BAA0B;AAAA,EAC5C;AAEA,QAAM,UAAU,UAAU,QAAQ;AAClC,MAAI,YAAY,QAAW;AACzB,UAAM,IAAI,MAAM,4CAA4C;AAAA,EAC9D;AACA,MAAI,IAAI,UAAU,MAAM,QAAQ,SAAS,OAAO;AAGhD,MAAI,EAAE,CAAC,MAAM,KAAQ,EAAE,SAAS,IAAI;AAClC,QAAI,EAAE,MAAM,CAAC;AAAA,EACf;AAEA,MAAI,EAAE,SAAS,IAAI;AACjB,UAAM,SAAS,IAAI,WAAW,EAAE;AAChC,WAAO,IAAI,GAAG,KAAK,EAAE,MAAM;AAC3B,QAAI;AAAA,EACN;AAEA,SAAO,EAAE,GAAG,EAAE;AAChB;AAKO,SAAS,2BAA2B,GAAW,GAAmB;AACvE,SAAO,OAAO,eAAe,CAAC,WAAW,SAAS,GAAG,CAAC,GAAG,CAAC,CAAC;AAC7D;AASO,SAAS,eAAe,YAAoB,YAA4B;AAC7E,SAAO,OAAO;AAAA,IACZ,OAAO,eAAe,CAAC,WAAW,SAAS,GAAG,CAAC,YAAY,UAAU,CAAC;AAAA,EACxE;AACF;AAiBO,SAAS,qBAAqB,iBAAyB,UAAU,MAA+B;AACrG,QAAM,SAAS,UAAU,iBAAiB;AAC1C,SAAO,OAAO,OAAO,MAAM,EAAE,KAAK,WAAS,MAAM,oBAAoB,eAAe;AACtF;AAKO,SAAS,gBAAgB,YAAoB,UAAU,MAA+B;AAC3F,QAAM,SAAS,UAAU,iBAAiB;AAC1C,SAAO,OAAO,OAAO,MAAM,EAAE,KAAK,WAAS,MAAM,YAAY,UAAU;AACzE;AAKO,SAAS,WAAW,iBAAkC;AAE3D,QAAM,eAAe,oBAAI,IAAI,CAAC,GAAG,GAAG,IAAI,IAAI,EAAE,CAAC;AAC/C,SAAO,CAAC,aAAa,IAAI,eAAe;AAC1C;AAiBO,SAAS,iBAAiB,OAAoB,QAAwB;AAC3E,MAAI,MAAM,OAAO;AACf,WAAO,GAAG,MAAM,WAAW,OAAO,MAAM;AAAA,EAC1C;AAGA,UAAQ,MAAM,iBAAiB;AAAA,IAC7B,KAAK;AACH,aAAO,GAAG,MAAM,WAAW,OAAO,MAAM;AAAA,IAC1C,KAAK;AACH,aAAO,GAAG,MAAM,WAAW,OAAO,MAAM;AAAA,IAC1C,KAAK;AACH,aAAO,GAAG,MAAM,WAAW,QAAQ,MAAM;AAAA,IAC3C;AACE,aAAO,GAAG,MAAM,WAAW,OAAO,MAAM;AAAA,EAC5C;AACF;AAKO,SAAS,sBAAsB,OAAoB,SAAyB;AACjF,MAAI,MAAM,OAAO;AACf,WAAO,GAAG,MAAM,WAAW,YAAY,OAAO;AAAA,EAChD;AAEA,UAAQ,MAAM,iBAAiB;AAAA,IAC7B,KAAK;AACH,aAAO,GAAG,MAAM,WAAW,YAAY,OAAO;AAAA,IAChD,KAAK;AACH,aAAO,GAAG,MAAM,WAAW,YAAY,OAAO;AAAA,IAChD,KAAK;AACH,aAAO,GAAG,MAAM,WAAW,YAAY,OAAO;AAAA,IAChD;AACE,aAAO,GAAG,MAAM,WAAW,YAAY,OAAO;AAAA,EAClD;AACF;AASO,SAAS,kBAAkB,SAA0B;AAC1D,SAAO,OAAO,UAAU,OAAO;AACjC;AAKO,SAAS,eAAe,KAAsB;AACnD,QAAM,QAAQ,IAAI,QAAQ,MAAM,EAAE;AAClC,SAAO,oBAAoB,KAAK,KAAK;AACvC;AAKO,SAAS,uBAAuB,SAA0B;AAE/D,SAAO,WAAW,KAAK,WAAW;AACpC;AASA,eAAsB,iBACpB,IACA,UAMI,CAAC,GACO;AACZ,QAAM;AAAA,IACJ,aAAa;AAAA,IACb,iBAAiB;AAAA,IACjB,aAAa;AAAA,IACb,oBAAoB;AAAA,IACpB;AAAA,EACF,IAAI;AAEJ,MAAI;AACJ,MAAI,QAAQ;AAEZ,WAAS,UAAU,GAAG,WAAW,YAAY,WAAW;AACtD,QAAI;AACF,aAAO,MAAM,GAAG;AAAA,IAClB,SAAS,OAAO;AACd,kBAAY;AAEZ,UAAI,UAAU,YAAY;AACxB,kBAAU,SAAS,SAAS;AAC5B,cAAM,MAAM,KAAK;AACjB,gBAAQ,KAAK,IAAI,QAAQ,mBAAmB,UAAU;AAAA,MACxD;AAAA,IACF;AAAA,EACF;AAEA,QAAM,aAAa,IAAI,MAAM,cAAc;AAC7C;AAMA,SAAS,MAAM,IAA2B;AACxC,SAAO,IAAI,QAAQ,aAAW,WAAW,SAAS,EAAE,CAAC;AACvD;;;ADxOO,IAAM,iBAAN,MAAM,gBAAe;AAAA,EAChB;AAAA,EACA,aAAuC;AAAA,EAE/C,YAAY,SAA+B,CAAC,GAAG;AAC3C,SAAK,SAAS;AAAA,MACV,QAAQ,OAAO,UAAU;AAAA,MACzB,MAAM,OAAO,SAAS,OAAO,WAAW,cAAc,OAAO,SAAS,WAAW;AAAA,MACjF,SAAS,OAAO,WAAW;AAAA,MAC3B,kBAAkB,OAAO,oBAAoB;AAAA,MAC7C,yBAAyB,OAAO,2BAA2B;AAAA,MAC3D,YAAY,OAAO,cAAc;AAAA,IACrC;AAAA,EACJ;AAAA,EAEA,OAAO,cAAuB;AAC1B,WAAO,wBAAwB;AAAA,EACnC;AAAA,EAEA,aAAa,mCAAqD;AAC9D,QAAI,OAAO,WAAW,eAAe,CAAC,OAAO,qBAAqB;AAC9D,aAAO;AAAA,IACX;AACA,WAAO,MAAM,OAAO,oBAAoB,8CAA8C;AAAA,EAC1F;AAAA,EAEA,MAAM,SAAS,UAAkB,aAAiD;AAC9E,QAAI,CAAC,gBAAe,YAAY,GAAG;AAC/B,YAAM,IAAI,MAAM,2CAA2C;AAAA,IAC/D;AAEA,UAAM,YAAYC,QAAO,YAAY,EAAE;AACvC,UAAM,kBAAkB,gBAAgB,SAAS;AAEjD,UAAM,UAAkD;AAAA,MACpD,WAAW;AAAA,MACX,IAAI;AAAA,QACA,MAAM,KAAK,OAAO;AAAA,QAClB,IAAI,KAAK,OAAO;AAAA,MACpB;AAAA,MACA,MAAM;AAAA,QACF,IAAI,gBAAgBA,QAAO,YAAY,QAAQ,CAAC;AAAA,QAChD,MAAM;AAAA,QACN;AAAA,MACJ;AAAA,MACA,kBAAkB;AAAA,QACd,EAAE,KAAK,IAAI,MAAM,aAAa;AAAA;AAAA,QAC9B,EAAE,KAAK,MAAM,MAAM,aAAa;AAAA;AAAA,QAChC,EAAE,KAAK,IAAI,MAAM,aAAa;AAAA;AAAA,QAC9B,EAAE,KAAK,KAAK,MAAM,aAAa;AAAA;AAAA,QAC/B,EAAE,KAAK,KAAK,MAAM,aAAa;AAAA;AAAA,QAC/B,EAAE,KAAK,KAAK,MAAM,aAAa;AAAA;AAAA,MACnC;AAAA,MACA,wBAAwB;AAAA,QACpB,yBAAyB,KAAK,OAAO;AAAA,QACrC,kBAAkB,KAAK,OAAO;AAAA,QAC9B,aAAa;AAAA,QACb,oBAAoB;AAAA,MACxB;AAAA,MACA,SAAS,KAAK,OAAO;AAAA,MACrB,aAAa;AAAA,IACjB;AAEA,UAAM,WAAW,MAAM,kBAAkB,OAAO;AAChD,UAAM,YAAY,KAAK,gCAAgC,QAAQ;AAC/D,UAAM,UAAU,eAAe,UAAU,GAAG,UAAU,CAAC;AAEvD,SAAK,aAAa;AAAA,MACd,cAAc,SAAS;AAAA,MACvB,YAAY,UAAU;AAAA,MACtB,YAAY,UAAU;AAAA,MACtB;AAAA,IACJ;AAEA,WAAO,KAAK;AAAA,EAChB;AAAA,EAEA,MAAM,KAAK,WAAmD;AAC1D,QAAI,CAAC,KAAK,YAAY;AAClB,YAAM,IAAI,MAAM,8DAA8D;AAAA,IAClF;AAEA,UAAM,kBAAkB,gBAAgB,SAAS;AAEjD,UAAM,UAAiD;AAAA,MACnD,WAAW;AAAA,MACX,MAAM,KAAK,OAAO;AAAA,MAClB,kBAAkB;AAAA,QACd;AAAA,UACI,IAAI,KAAK,WAAW;AAAA,UACpB,MAAM;AAAA,UACN,YAAY,CAAC,UAAU;AAAA,QAC3B;AAAA,MACJ;AAAA,MACA,kBAAkB,KAAK,OAAO;AAAA,MAC9B,SAAS,KAAK,OAAO;AAAA,IACzB;AAEA,UAAM,WAAW,MAAM,oBAAoB,OAAO;AAClD,WAAO,KAAK,4BAA4B,QAAQ;AAAA,EACpD;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAUA,MAAM,aAAa,WAGhB;AACC,QAAI,CAAC,gBAAe,YAAY,GAAG;AAC/B,YAAM,IAAI,MAAM,2CAA2C;AAAA,IAC/D;AAEA,UAAM,kBAAkB,aAAaA,QAAO,YAAY,EAAE;AAC1D,UAAM,kBAAkB,gBAAgB,eAAe;AAIvD,UAAM,UAAiD;AAAA,MACnD,WAAW;AAAA,MACX,MAAM,KAAK,OAAO;AAAA;AAAA,MAElB,kBAAkB,KAAK,OAAO;AAAA,MAC9B,SAAS,KAAK,OAAO;AAAA,IACzB;AAEA,UAAM,WAAW,MAAM,oBAAoB,OAAO;AAGlD,UAAM,eAAe,SAAS;AAG9B,UAAM,YAAY,KAAK,4BAA4B,QAAQ;AAO3D,QAAI,mBAAmB,KAAK,mBAAmB,YAAY;AAE3D,QAAI,kBAAkB;AAClB,WAAK,aAAa;AAClB,aAAO,EAAE,YAAY,kBAAkB,UAAU;AAAA,IACrD;AAGA,QAAI,KAAK,OAAO,YAAY;AACxB,yBAAmB,MAAM,KAAK,0BAA0B,YAAY;AACpE,UAAI,kBAAkB;AAClB,aAAK,aAAa;AAElB,aAAK,mBAAmB;AACxB,eAAO,EAAE,YAAY,kBAAkB,UAAU;AAAA,MACrD;AAAA,IACJ;AAIA,UAAM,IAAI;AAAA,MACN;AAAA,IAGJ;AAAA,EACJ;AAAA;AAAA;AAAA;AAAA;AAAA,EAMQ,mBAAmB,cAAsB,MAAM,sBAAgD;AACnG,QAAI,OAAO,WAAW,aAAa;AAC/B,aAAO;AAAA,IACX;AAEA,UAAM,SAAS,aAAa,QAAQ,GAAG;AACvC,QAAI,CAAC,QAAQ;AACT,aAAO;AAAA,IACX;AAEA,QAAI;AACA,YAAM,OAAO,KAAK,MAAM,MAAM;AAE9B,UAAI,KAAK,iBAAiB,cAAc;AACpC,eAAO;AAAA,UACH,cAAc,KAAK;AAAA,UACnB,YAAY,OAAO,KAAK,UAAU;AAAA,UAClC,YAAY,OAAO,KAAK,UAAU;AAAA,UAClC,SAAS,KAAK;AAAA,QAClB;AAAA,MACJ;AACA,aAAO;AAAA,IACX,SAAS,OAAO;AACZ,cAAQ,MAAM,8BAA8B,KAAK;AACjD,aAAO;AAAA,IACX;AAAA,EACJ;AAAA;AAAA;AAAA;AAAA,EAKA,oBAAoB,MAAM,sBAA+B;AACrD,QAAI,OAAO,WAAW,aAAa;AAC/B,aAAO;AAAA,IACX;AACA,WAAO,aAAa,QAAQ,GAAG,MAAM;AAAA,EACzC;AAAA,EAEA,gBAA0C;AACtC,WAAO,KAAK;AAAA,EAChB;AAAA,EAEA,cAAc,YAAqC;AAC/C,SAAK,aAAa;AAAA,EACtB;AAAA,EAEA,8BACI,cACA,YACA,YACiB;AACjB,UAAM,UAAU,eAAe,YAAY,UAAU;AACrD,SAAK,aAAa;AAAA,MACd;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,IACJ;AACA,WAAO,KAAK;AAAA,EAChB;AAAA,EAEA,kBAAwB;AACpB,SAAK,aAAa;AAAA,EACtB;AAAA,EAEA,mBAAmB,MAAM,sBAA4B;AACjD,QAAI,CAAC,KAAK,YAAY;AAClB,YAAM,IAAI,MAAM,uBAAuB;AAAA,IAC3C;AACA,QAAI,OAAO,WAAW,aAAa;AAC/B,YAAM,IAAI,MAAM,+BAA+B;AAAA,IACnD;AAEA,UAAM,OAAO;AAAA,MACT,cAAc,KAAK,WAAW;AAAA,MAC9B,YAAY,KAAK,WAAW,WAAW,SAAS;AAAA,MAChD,YAAY,KAAK,WAAW,WAAW,SAAS;AAAA,MAChD,SAAS,KAAK,WAAW;AAAA,IAC7B;AAEA,iBAAa,QAAQ,KAAK,KAAK,UAAU,IAAI,CAAC;AAAA,EAClD;AAAA,EAEA,qBAAqB,MAAM,sBAAgD;AACvE,QAAI,OAAO,WAAW,aAAa;AAC/B,aAAO;AAAA,IACX;AAEA,UAAM,SAAS,aAAa,QAAQ,GAAG;AACvC,QAAI,CAAC,QAAQ;AACT,aAAO;AAAA,IACX;AAEA,QAAI;AACA,YAAM,OAAO,KAAK,MAAM,MAAM;AAC9B,WAAK,aAAa;AAAA,QACd,cAAc,KAAK;AAAA,QACnB,YAAY,OAAO,KAAK,UAAU;AAAA,QAClC,YAAY,OAAO,KAAK,UAAU;AAAA,QAClC,SAAS,KAAK;AAAA,MAClB;AACA,aAAO,KAAK;AAAA,IAChB,SAAS,OAAO;AACZ,cAAQ,MAAM,gDAAgD,KAAK;AACnE,aAAO;AAAA,IACX;AAAA,EACJ;AAAA,EAEA,uBAAuB,MAAM,sBAA4B;AACrD,QAAI,OAAO,WAAW,aAAa;AAC/B,mBAAa,WAAW,GAAG;AAAA,IAC/B;AAAA,EACJ;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAUA,MAAM,0BAA4C;AAC9C,QAAI,CAAC,KAAK,YAAY;AAClB,YAAM,IAAI,MAAM,uBAAuB;AAAA,IAC3C;AACA,QAAI,CAAC,KAAK,OAAO,YAAY;AACzB,cAAQ,KAAK,gEAAgE;AAC7E,aAAO;AAAA,IACX;AAEA,QAAI;AACA,YAAM,WAAW,MAAM,MAAM,GAAG,KAAK,OAAO,UAAU,sBAAsB;AAAA,QACxE,QAAQ;AAAA,QACR,SAAS,EAAE,gBAAgB,mBAAmB;AAAA,QAC9C,MAAM,KAAK,UAAU;AAAA,UACjB,SAAS,KAAK,WAAW;AAAA,UACzB,cAAc,KAAK,WAAW;AAAA,UAC9B,YAAY,KAAK,WAAW,WAAW,SAAS;AAAA,UAChD,YAAY,KAAK,WAAW,WAAW,SAAS;AAAA,QACpD,CAAC;AAAA,MACL,CAAC;AAED,UAAI,CAAC,SAAS,IAAI;AACd,cAAM,YAAY,MAAM,SAAS,KAAK,EAAE,MAAM,OAAO,CAAC,EAAE;AACxD,gBAAQ,MAAM,yCAAyC,SAAS;AAChE,eAAO;AAAA,MACX;AAEA,cAAQ,IAAI,uDAAuD;AACnE,aAAO;AAAA,IACX,SAAS,OAAO;AACZ,cAAQ,MAAM,yCAAyC,KAAK;AAC5D,aAAO;AAAA,IACX;AAAA,EACJ;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,MAAM,0BAA0B,cAAyD;AACrF,QAAI,CAAC,KAAK,OAAO,YAAY;AACzB,aAAO;AAAA,IACX;AAEA,QAAI;AACA,YAAM,WAAW,MAAM;AAAA,QACnB,GAAG,KAAK,OAAO,UAAU,4BAA4B,mBAAmB,YAAY,CAAC;AAAA,MACzF;AAEA,UAAI,CAAC,SAAS,IAAI;AACd,eAAO;AAAA,MACX;AAEA,YAAM,OAAO,MAAM,SAAS,KAAK;AACjC,UAAI,CAAC,KAAK,QAAQ;AACd,eAAO;AAAA,MACX;AAEA,aAAO;AAAA,QACH,cAAc,KAAK;AAAA,QACnB,YAAY,OAAO,KAAK,UAAU;AAAA,QAClC,YAAY,OAAO,KAAK,UAAU;AAAA,QAClC,SAAS,KAAK;AAAA,MAClB;AAAA,IACJ,SAAS,OAAO;AACZ,cAAQ,MAAM,2CAA2C,KAAK;AAC9D,aAAO;AAAA,IACX;AAAA,EACJ;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,MAAM,mCAAmC,SAAoD;AACzF,QAAI,CAAC,KAAK,OAAO,YAAY;AACzB,aAAO;AAAA,IACX;AAEA,QAAI;AACA,YAAM,WAAW,MAAM;AAAA,QACnB,GAAG,KAAK,OAAO,UAAU,sBAAsB,mBAAmB,OAAO,CAAC;AAAA,MAC9E;AAEA,UAAI,CAAC,SAAS,IAAI;AACd,eAAO;AAAA,MACX;AAEA,YAAM,OAAO,MAAM,SAAS,KAAK;AACjC,UAAI,CAAC,KAAK,QAAQ;AACd,eAAO;AAAA,MACX;AAEA,aAAO;AAAA,QACH,cAAc,KAAK;AAAA,QACnB,YAAY,OAAO,KAAK,UAAU;AAAA,QAClC,YAAY,OAAO,KAAK,UAAU;AAAA,QAClC,SAAS,KAAK;AAAA,MAClB;AAAA,IACJ,SAAS,OAAO;AACZ,cAAQ,MAAM,2CAA2C,KAAK;AAC9D,aAAO;AAAA,IACX;AAAA,EACJ;AAAA,EAEQ,gCACJ,UACwB;AACxB,UAAM,oBAAoB,gBAAgB,SAAS,SAAS,iBAAiB;AAM7E,QAAI,SAAS;AAGb,QAAI,kBAAkB,MAAM,KAAK,OAAQ,kBAAkB,MAAM,KAAK,KAAM;AACxE;AAAA,IACJ;AAIA,WAAO,SAAS,kBAAkB,SAAS,IAAI;AAC3C,UAAI,kBAAkB,MAAM,MAAM;AAAA,MAC9B,kBAAkB,SAAS,CAAC,MAAM;AAAA,MAClC,kBAAkB,SAAS,CAAC,MAAM;AAAA,MAClC,kBAAkB,SAAS,CAAC,MAAM;AAAA,MAClC,kBAAkB,SAAS,CAAC,MAAM;AAAA,MAClC,kBAAkB,SAAS,CAAC,MAAM;AAAA,MAClC,kBAAkB,SAAS,CAAC,MAAM;AAAA,MAClC,kBAAkB,SAAS,CAAC,MAAM;AAAA,MAClC,kBAAkB,SAAS,CAAC,MAAM,IAAM;AACxC,kBAAU;AACV;AAAA,MACJ;AACA;AAAA,IACJ;AAGA,QAAI,kBAAkB,MAAM,MAAM,MAAQ,kBAAkB,MAAM,MAAM,IAAM;AAE1E,YAAM,cAAc,kBAAkB,MAAM,MAAM,KAAO,IAAI;AAC7D,gBAAU,IAAI;AAAA,IAClB;AAaA,cAAU;AACV,cAAU;AACV,cAAU;AACV,cAAU;AAGV,UAAM,YAAa,kBAAkB,MAAM,KAAK,IAAK,kBAAkB,SAAS,CAAC;AACjF,cAAU;AACV,cAAU;AAGV,UAAM,UAAU,kBAAkB,MAAM,MAAM;AAE9C,YAAQ,IAAI,oBAAoB,QAAQ,MAAM;AAC9C,YAAQ,IAAI,iBAAiB,KAAK,WAAW,QAAQ,MAAM,GAAG,KAAK,IAAI,KAAK,QAAQ,MAAM,CAAC,CAAC,CAAC;AAE7F,UAAM,EAAE,GAAG,EAAE,IAAI,KAAK,aAAa,OAAO;AAC1C,WAAO,EAAE,GAAG,EAAE;AAAA,EAClB;AAAA,EAEQ,aAAa,SAA+C;AAChE,YAAQ,IAAI,oBAAoB,QAAQ,MAAM;AAC9C,YAAQ,IAAI,iBAAiB,KAAK,WAAW,OAAO,CAAC;AAGrD,UAAM,SAAS,KAAK,0BAA0B,OAAO;AACrD,QAAI,QAAQ;AACR,aAAO;AAAA,IACX;AAGA,WAAO,KAAK,8BAA8B,OAAO;AAAA,EACrD;AAAA,EAEQ,0BAA0B,SAAsD;AAEpF,UAAM,WAAW,IAAI,WAAW,OAAO;AAGvC,aAAS,IAAI,GAAG,IAAI,SAAS,SAAS,IAAI,KAAK;AAE3C,UAAI,SAAS,CAAC,MAAM,MAAQ,SAAS,IAAI,CAAC,MAAM,IAAM;AAClD,cAAM,aAAa,SAAS,MAAM,IAAI,GAAG,IAAI,EAAE;AAG/C,iBAAS,IAAI,IAAI,IAAI,IAAI,SAAS,SAAS,IAAI,KAAK;AAChD,cAAI,SAAS,CAAC,MAAM,MAAQ,SAAS,IAAI,CAAC,MAAM,IAAM;AAClD,kBAAM,aAAa,SAAS,MAAM,IAAI,GAAG,IAAI,EAAE;AAG/C,gBAAI,KAAK,kBAAkB,UAAU,KAAK,KAAK,kBAAkB,UAAU,GAAG;AAC1E,sBAAQ,IAAI,wCAAwC;AACpD,qBAAO;AAAA,gBACH,GAAG,KAAK,cAAc,UAAU;AAAA,gBAChC,GAAG,KAAK,cAAc,UAAU;AAAA,cACpC;AAAA,YACJ;AAAA,UACJ;AAAA,QACJ;AAAA,MACJ;AAAA,IACJ;AAGA,WAAO,KAAK,sBAAsB,QAAQ;AAAA,EAC9C;AAAA,EAEQ,8BAA8B,SAA+C;AAEjF,UAAM,QAAQ,IAAI,WAAW,OAAO;AACpC,QAAI,SAA4B;AAChC,QAAI,SAA4B;AAGhC,QAAI,IAAI;AACR,WAAO,IAAI,MAAM,QAAQ;AAErB,UAAI,MAAM,CAAC,MAAM,IAAM;AACnB,cAAM,SAAS,MAAM,IAAI,CAAC;AAC1B,YAAI,WAAW,IAAM;AACjB,gBAAM,QAAQ,IAAI;AAClB,gBAAM,MAAM,QAAQ;AAEpB,cAAI,OAAO,MAAM,QAAQ;AACrB,kBAAM,aAAa,MAAM,MAAM,OAAO,GAAG;AAGzC,gBAAI,CAAC,QAAQ;AACT,uBAAS;AACT,sBAAQ,IAAI,qBAAqB,CAAC;AAAA,YACtC,WAAW,CAAC,QAAQ;AAChB,uBAAS;AACT,sBAAQ,IAAI,qBAAqB,CAAC;AAClC;AAAA,YACJ;AAAA,UACJ;AACA,cAAI;AAAA,QACR,OAAO;AACH,eAAK,SAAS;AAAA,QAClB;AAAA,MACJ,WAAW,MAAM,CAAC,MAAM,IAAM;AAC1B,YAAI,IAAI,IAAI,MAAM,QAAQ;AACtB,gBAAM,SAAU,MAAM,IAAI,CAAC,KAAK,IAAK,MAAM,IAAI,CAAC;AAChD,cAAI,WAAW,IAAI;AACf,kBAAM,QAAQ,IAAI;AAClB,kBAAM,MAAM,QAAQ;AAEpB,gBAAI,OAAO,MAAM,QAAQ;AACrB,oBAAM,aAAa,MAAM,MAAM,OAAO,GAAG;AAEzC,kBAAI,CAAC,QAAQ;AACT,yBAAS;AACT,wBAAQ,IAAI,qBAAqB,CAAC;AAAA,cACtC,WAAW,CAAC,QAAQ;AAChB,yBAAS;AACT,wBAAQ,IAAI,qBAAqB,CAAC;AAClC;AAAA,cACJ;AAAA,YACJ;AACA,gBAAI;AAAA,UACR,OAAO;AACH,iBAAK,SAAS;AAAA,UAClB;AAAA,QACJ,OAAO;AACH;AAAA,QACJ;AAAA,MACJ,WAAW,MAAM,CAAC,MAAM,IAAM;AAE1B;AAEA,eAAO,IAAI,MAAM,UAAU,MAAM,CAAC,MAAM,KAAM;AAC1C,cAAI,MAAM,CAAC,MAAM,KAAQ,IAAI,MAAM,MAAM,QAAQ;AAE7C,kBAAM,IAAI,MAAM,MAAM,IAAI,GAAG,IAAI,EAAE;AACnC,kBAAM,IAAI,MAAM,MAAM,IAAI,IAAI,IAAI,EAAE;AAEpC,gBAAI,KAAK,kBAAkB,CAAC,KAAK,KAAK,kBAAkB,CAAC,GAAG;AACxD,uBAAS;AACT,uBAAS;AACT,sBAAQ,IAAI,gDAAgD;AAC5D;AAAA,YACJ;AAAA,UACJ;AACA;AAAA,QACJ;AACA,YAAI,UAAU,OAAQ;AAAA,MAC1B,OAAO;AACH;AAAA,MACJ;AAAA,IACJ;AAEA,QAAI,CAAC,UAAU,CAAC,QAAQ;AAEpB,YAAM,kBAAkB,KAAK,oBAAoB,KAAK;AACtD,UAAI,gBAAgB,UAAU,GAAG;AAC7B,iBAAS,gBAAgB,CAAC;AAC1B,iBAAS,gBAAgB,CAAC;AAC1B,gBAAQ,IAAI,4DAA4D;AAAA,MAC5E;AAAA,IACJ;AAEA,QAAI,CAAC,UAAU,CAAC,QAAQ;AACpB,cAAQ,MAAM,oDAAoD;AAClE,cAAQ,MAAM,QAAQ,KAAK,WAAW,KAAK,CAAC;AAC5C,cAAQ,MAAM,qBAAqB;AACnC,WAAK,qBAAqB,KAAK;AAC/B,YAAM,IAAI,MAAM,oFAAoF;AAAA,IACxG;AAEA,WAAO;AAAA,MACH,GAAG,KAAK,cAAc,MAAM;AAAA,MAC5B,GAAG,KAAK,cAAc,MAAM;AAAA,IAChC;AAAA,EACJ;AAAA,EAEQ,sBAAsB,OAAoD;AAE9E,QAAI,MAAM,CAAC,MAAM,IAAM;AACnB,UAAI,SAAS;AAGb,UAAI,MAAM,MAAM,MAAM,GAAM;AACxB,kBAAU;AAGV,YAAI,MAAM,MAAM,MAAM,IAAM;AACxB,oBAAU;AAIV,oBAAU;AAGV,cAAI,MAAM,MAAM,MAAM,KAAQ,MAAM,SAAS,CAAC,MAAM,GAAM;AACtD,sBAAU;AAEV,kBAAM,IAAI,MAAM,MAAM,QAAQ,SAAS,EAAE;AACzC,kBAAM,IAAI,MAAM,MAAM,SAAS,IAAI,SAAS,EAAE;AAE9C,gBAAI,EAAE,WAAW,MAAM,EAAE,WAAW,IAAI;AACpC,sBAAQ,IAAI,qCAAqC;AACjD,qBAAO;AAAA,gBACH,GAAG,KAAK,cAAc,CAAC;AAAA,gBACvB,GAAG,KAAK,cAAc,CAAC;AAAA,cAC3B;AAAA,YACJ;AAAA,UACJ;AAAA,QACJ;AAAA,MACJ;AAAA,IACJ;AACA,WAAO;AAAA,EACX;AAAA,EAEQ,oBAAoB,OAAiC;AACzD,UAAM,YAA0B,CAAC;AAEjC,aAAS,IAAI,GAAG,KAAK,MAAM,SAAS,IAAI,KAAK;AAEzC,YAAM,WAAW,MAAM,MAAM,GAAG,IAAI,EAAE;AACtC,UAAI,KAAK,kBAAkB,QAAQ,GAAG;AAClC,kBAAU,KAAK,QAAQ;AAAA,MAC3B;AAAA,IACJ;AAEA,WAAO;AAAA,EACX;AAAA,EAEQ,kBAAkB,OAA4B;AAClD,QAAI,MAAM,WAAW,GAAI,QAAO;AAGhC,QAAI,WAAW;AACf,QAAI,UAAU;AAEd,eAAW,QAAQ,OAAO;AACtB,UAAI,SAAS,EAAG,YAAW;AAC3B,UAAI,SAAS,IAAM,WAAU;AAAA,IACjC;AAEA,WAAO,CAAC,YAAY,CAAC;AAAA,EACzB;AAAA,EAEQ,cAAc,OAA2B;AAC7C,WAAO,OAAO,OAAO,KAAK,WAAW,KAAK,CAAC;AAAA,EAC/C;AAAA,EAEQ,WAAW,OAA2B;AAC1C,WAAO,MAAM,KAAK,KAAK,EAClB,IAAI,OAAK,EAAE,SAAS,EAAE,EAAE,SAAS,GAAG,GAAG,CAAC,EACxC,KAAK,EAAE;AAAA,EAChB;AAAA,EAEQ,qBAAqB,OAAyB;AAClD,YAAQ,IAAI,0BAA0B;AACtC,YAAQ,IAAI,mBAAmB,KAAK,WAAW,MAAM,MAAM,GAAG,EAAE,CAAC,CAAC;AAGlE,UAAM,YAAY,MAAM,CAAC;AACzB,YAAQ,IAAI,mBAAmB,UAAU,SAAS,EAAE,IAAI,IAAI;AAE5D,QAAI,aAAa,OAAQ,aAAa,KAAM;AACxC,cAAQ,IAAI,8BAA+B,YAAY,IAAO,OAAO;AAAA,IACzE,WAAW,cAAc,KAAM;AAC3B,cAAQ,IAAI,yBAAyB;AAAA,IACzC,WAAW,cAAc,GAAM;AAC3B,cAAQ,IAAI,eAAe;AAAA,IAC/B,WAAW,cAAc,GAAM;AAC3B,cAAQ,IAAI,oBAAoB;AAAA,IACpC;AAGA,QAAI,UAAU;AACd,aAAS,IAAI,GAAG,KAAK,MAAM,SAAS,IAAI,KAAK;AACzC,YAAM,QAAQ,MAAM,MAAM,GAAG,IAAI,EAAE;AACnC,UAAI,KAAK,kBAAkB,KAAK,GAAG;AAC/B,gBAAQ;AAAA,UAAI,0CAA0C,CAAC;AAAA,UACnD,KAAK,WAAW,MAAM,MAAM,GAAG,CAAC,CAAC,IAAI;AAAA,QAAK;AAC9C;AAAA,MACJ;AAAA,IACJ;AACA,YAAQ,IAAI,kCAAkC,OAAO,EAAE;AAGvD,YAAQ,IAAI,4BAA4B;AACxC,UAAM,UAAU;AAAA,MACZ,EAAE,MAAM,GAAM,MAAM,4BAA4B;AAAA,MAChD,EAAE,MAAM,GAAM,MAAM,aAAa;AAAA,MACjC,EAAE,MAAM,IAAM,MAAM,WAAW;AAAA,MAC/B,EAAE,MAAM,GAAM,MAAM,UAAU;AAAA,MAC9B,EAAE,MAAM,GAAM,MAAM,oBAAoB;AAAA,MACxC,EAAE,MAAM,IAAM,MAAM,+BAA+B;AAAA,MACnD,EAAE,MAAM,IAAM,MAAM,iCAAiC;AAAA,MACrD,EAAE,MAAM,IAAM,MAAM,gCAAgC;AAAA,MACpD,EAAE,MAAM,KAAM,MAAM,YAAY;AAAA,MAChC,EAAE,MAAM,KAAM,MAAM,uBAAuB;AAAA,IAC/C;AAEA,eAAW,UAAU,SAAS;AAC1B,YAAM,UAAU,CAAC;AACjB,eAAS,IAAI,GAAG,IAAI,MAAM,QAAQ,KAAK;AACnC,YAAI,MAAM,CAAC,MAAM,OAAO,MAAM;AAC1B,kBAAQ,KAAK,CAAC;AAAA,QAClB;AAAA,MACJ;AACA,UAAI,QAAQ,SAAS,GAAG;AACpB,gBAAQ,IAAI,KAAK,OAAO,IAAI,OAAO,OAAO,KAAK,SAAS,EAAE,CAAC,mBAAmB,QAAQ,MAAM,GAAG,CAAC,EAAE,KAAK,IAAI,CAAC;AAAA,MAChH;AAAA,IACJ;AAAA,EACJ;AAAA,EAEQ,4BAA4B,UAAyD;AACzF,UAAM,oBAAoB,gBAAgB,SAAS,SAAS,iBAAiB;AAC7E,UAAM,iBAAiB,SAAS,SAAS;AACzC,UAAM,YAAY,gBAAgB,SAAS,SAAS,SAAS;AAE7D,UAAM,EAAE,GAAG,EAAE,IAAI,kBAAkB,SAAS;AAM5C,UAAM,SAAS,OAAO,oEAAoE;AAC1F,UAAM,eAAe;AAAA,MACjB;AAAA,IACJ;AAEA,UAAM,gBAAgB,IAAI,YAAY,EAAE,OAAO,gBAAgB,cAAc,CAAC;AAC9E,UAAM,iBAAiB,cAAc,QAAQ,aAAa;AAC1D,UAAM,YAAY,cAAc,QAAQ,QAAQ;AAEhD,QAAI,mBAAmB,MAAM,cAAc,IAAI;AAC3C,YAAM,IAAI,MAAM,+BAA+B;AAAA,IACnD;AAEA,WAAO;AAAA,MACH,mBAAmBA,QAAO,QAAQ,iBAAiB;AAAA,MACnD,gBAAgB;AAAA,MAChB;AAAA,MACA;AAAA,MACA,GAAG,KAAK,cAAc,CAAC;AAAA,MACvB,IAAI,MAAM;AACN,cAAM,OAAO,KAAK,cAAc,CAAC;AACjC,eAAO,OAAO,eAAe,SAAS,OAAO;AAAA,MACjD,GAAG;AAAA,IACP;AAAA,EACJ;AACJ;;;AGh1BA,SAAS,UAAAC,eAAc;AAiBvB,IAAM,wBAAwB;AAM9B,IAAM,wBAAwB;AAwBvB,IAAM,gBAAN,MAAoB;AAAA,EACf;AAAA,EACA,eAA4C,oBAAI,IAAI;AAAA,EAE5D,YAAY,SAA8B,CAAC,GAAG;AAC1C,SAAK,SAAS;AAAA,MACV,gBAAgB,OAAO,kBAAkB;AAAA,MACzC,kBAAkB,OAAO,oBAAoB;AAAA,MAC7C,YAAY,OAAO,cAAc;AAAA,IACrC;AAGA,QAAI,KAAK,OAAO,oBAAoB,OAAO,WAAW,aAAa;AAC/D,WAAK,gBAAgB;AAAA,IACzB;AAAA,EACJ;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAkBA,oBACI,SACA,gBACA,uBACM;AAEN,UAAM,OAAOC,QAAO;AAAA,MAChBA,QAAO;AAAA,QACH,CAAC,WAAW,SAAS;AAAA,QACrB,CAAC,gBAAgB,OAAO;AAAA,MAC5B;AAAA,IACJ;AAGA,UAAM,WAAW,KAAK,mBAAmB,qBAAqB;AAC9D,UAAM,eAAeA,QAAO,UAAU,QAAQ;AAI9C,UAAM,cAAcA,QAAO;AAAA,MACvB,CAAC,UAAU,WAAW,WAAW,SAAS;AAAA,MAC1C,CAAC,QAAQ,gBAAgB,MAAM,YAAY;AAAA,IAC/C;AAEA,UAAM,OAAOA,QAAO,UAAU,WAAW;AAEzC,WAAOA,QAAO,WAAW,OAAO,KAAK,MAAM,EAAE,CAAC;AAAA,EAClD;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAWA,iCACI,YACA,YACA,gBACA,uBACM;AACN,UAAM,UAAU,eAAe,YAAY,UAAU;AACrD,WAAO,KAAK,oBAAoB,SAAS,gBAAgB,qBAAqB;AAAA,EAClF;AAAA;AAAA;AAAA;AAAA,EAKQ,mBAAmB,uBAAuC;AAE9D,UAAM,OAAO,sBAAsB,YAAY,EAAE,QAAQ,MAAM,EAAE;AAGjE,WAAO,wBAAwB,OAAO;AAAA,EAC1C;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAaA,MAAM,mBACF,YACA,cACwB;AACxB,UAAM,YAA4B,CAAC;AAEnC,eAAW,CAAC,iBAAiB,MAAM,KAAK,cAAc;AAClD,YAAM,UAAU,MAAM,KAAK;AAAA,QACvB;AAAA,QACA;AAAA,QACA;AAAA,MACJ;AAEA,UAAI,SAAS;AACT,kBAAU,KAAK,OAAO;AAAA,MAC1B;AAAA,IACJ;AAEA,UAAM,WAA4B;AAAA,MAC9B,SAAS,WAAW;AAAA,MACpB,YAAY,WAAW;AAAA,MACvB,YAAY,WAAW;AAAA,MACvB,cAAc,WAAW;AAAA,MACzB;AAAA,MACA,WAAW,KAAK,IAAI;AAAA,MACpB,WAAW,KAAK,IAAI;AAAA,IACxB;AAGA,QAAI,KAAK,OAAO,gBAAgB;AAC5B,WAAK,aAAa,IAAI,WAAW,SAAS,SAAS;AAAA,IACvD;AAGA,QAAI,KAAK,OAAO,kBAAkB;AAC9B,WAAK,cAAc,QAAQ;AAAA,IAC/B;AAEA,WAAO;AAAA,EACX;AAAA;AAAA;AAAA;AAAA,EAKA,MAAc,sBACV,YACA,iBACA,QAC4B;AAC5B,QAAI,OAAO,OAAO;AAEd,UAAI,CAAC,OAAO,kBAAkB,CAAC,OAAO,uBAAuB;AACzD,eAAO;AAAA,MACX;AAEA,YAAM,UAAU,KAAK;AAAA,QACjB,WAAW;AAAA,QACX,OAAO;AAAA,QACP,OAAO;AAAA,MACX;AAEA,aAAO;AAAA,QACH;AAAA,QACA,WAAW,OAAO;AAAA,QAClB;AAAA,QACA,OAAO;AAAA,QACP,UAAU;AAAA;AAAA,MACd;AAAA,IACJ,OAAO;AAEH,aAAO,KAAK,oBAAoB,YAAY,iBAAiB,MAAM;AAAA,IACvE;AAAA,EACJ;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAUQ,oBACJ,YACA,iBACA,SACmB;AACnB,YAAQ,iBAAiB;AAAA,MACrB,KAAK;AAGD,eAAO;AAAA,UACH,iBAAiB;AAAA,UACjB,WAAW;AAAA,UACX,SAAS,WAAW;AAAA;AAAA,UACpB,OAAO;AAAA,UACP,gBAAgB;AAAA,UAChB,UAAU;AAAA,QACd;AAAA,MAEJ,KAAK;AAED,eAAO;AAAA,UACH,iBAAiB;AAAA,UACjB,WAAW;AAAA,UACX,SAAS,WAAW;AAAA,UACpB,OAAO;AAAA,UACP,gBAAgB;AAAA,UAChB,UAAU;AAAA,QACd;AAAA,MAEJ,KAAK;AAED,eAAO;AAAA,UACH,iBAAiB;AAAA,UACjB,WAAW;AAAA,UACX,SAAS,WAAW;AAAA,UACpB,OAAO;AAAA,UACP,gBAAgB;AAAA,UAChB,UAAU;AAAA,QACd;AAAA,MAEJ;AAEI,eAAO;AAAA,IACf;AAAA,EACJ;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASA,mBAAmB,SAAiB,iBAAmD;AACnF,UAAM,YAAY,KAAK,aAAa,IAAI,OAAO;AAC/C,WAAO,WAAW,KAAK,OAAK,EAAE,oBAAoB,eAAe;AAAA,EACrE;AAAA;AAAA;AAAA;AAAA,EAKA,aAAa,SAAiC;AAC1C,WAAO,KAAK,aAAa,IAAI,OAAO,KAAK,CAAC;AAAA,EAC9C;AAAA;AAAA;AAAA;AAAA,EAKA,uBACI,SACA,iBACA,UACA,kBACI;AACJ,UAAM,YAAY,KAAK,aAAa,IAAI,OAAO;AAC/C,QAAI,CAAC,UAAW;AAEhB,UAAM,UAAU,UAAU,KAAK,OAAK,EAAE,oBAAoB,eAAe;AACzE,QAAI,SAAS;AACT,cAAQ,WAAW;AACnB,cAAQ,mBAAmB;AAAA,IAC/B;AAGA,QAAI,KAAK,OAAO,kBAAkB;AAC9B,WAAK,uBAAuB,SAAS,SAAS;AAAA,IAClD;AAAA,EACJ;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASQ,kBAAwB;AAC5B,QAAI,OAAO,WAAW,YAAa;AAEnC,QAAI;AACA,YAAM,SAAS,aAAa,QAAQ,KAAK,OAAO,UAAW;AAC3D,UAAI,CAAC,OAAQ;AAEb,YAAM,OAAO,KAAK,MAAM,MAAM;AAE9B,iBAAW,CAAC,SAAS,SAAS,KAAK,OAAO,QAAQ,KAAK,SAAS,GAAG;AAC/D,aAAK,aAAa,IAAI,SAAS,SAAS;AAAA,MAC5C;AAAA,IACJ,SAAS,OAAO;AACZ,cAAQ,KAAK,iDAAiD,KAAK;AAAA,IACvE;AAAA,EACJ;AAAA;AAAA;AAAA;AAAA,EAKQ,cAAc,UAAiC;AACnD,QAAI,OAAO,WAAW,YAAa;AAEnC,QAAI;AACA,YAAM,SAAS,aAAa,QAAQ,KAAK,OAAO,UAAW,KAAK;AAChE,YAAM,OAAO,KAAK,MAAM,MAAM;AAE9B,UAAI,CAAC,KAAK,WAAW;AACjB,aAAK,YAAY,CAAC;AAAA,MACtB;AAGA,WAAK,UAAU,SAAS,OAAO,IAAI,SAAS;AAC5C,WAAK,aAAa,KAAK,cAAc,CAAC;AACtC,WAAK,WAAW,SAAS,OAAO,IAAI;AAAA,QAChC,SAAS,SAAS;AAAA,QAClB,YAAY,SAAS,WAAW,SAAS;AAAA,QACzC,YAAY,SAAS,WAAW,SAAS;AAAA,QACzC,cAAc,SAAS;AAAA,QACvB,WAAW,SAAS;AAAA,QACpB,WAAW,SAAS;AAAA,MACxB;AAEA,mBAAa,QAAQ,KAAK,OAAO,YAAa,KAAK,UAAU,IAAI,CAAC;AAAA,IACtE,SAAS,OAAO;AACZ,cAAQ,KAAK,+CAA+C,KAAK;AAAA,IACrE;AAAA,EACJ;AAAA;AAAA;AAAA;AAAA,EAKQ,uBAAuB,SAAiB,WAAiC;AAC7E,QAAI,OAAO,WAAW,YAAa;AAEnC,QAAI;AACA,YAAM,SAAS,aAAa,QAAQ,KAAK,OAAO,UAAW,KAAK;AAChE,YAAM,OAAO,KAAK,MAAM,MAAM;AAE9B,UAAI,CAAC,KAAK,WAAW;AACjB,aAAK,YAAY,CAAC;AAAA,MACtB;AAEA,WAAK,UAAU,OAAO,IAAI;AAC1B,mBAAa,QAAQ,KAAK,OAAO,YAAa,KAAK,UAAU,IAAI,CAAC;AAAA,IACtE,SAAS,OAAO;AACZ,cAAQ,KAAK,+CAA+C,KAAK;AAAA,IACrE;AAAA,EACJ;AAAA;AAAA;AAAA;AAAA,EAKA,aAAmB;AACf,SAAK,aAAa,MAAM;AAExB,QAAI,KAAK,OAAO,oBAAoB,OAAO,WAAW,aAAa;AAC/D,mBAAa,WAAW,KAAK,OAAO,UAAW;AAAA,IACnD;AAAA,EACJ;AAAA;AAAA;AAAA;AAAA,EAKA,wBAAwB,SAAyC;AAC7D,QAAI,OAAO,WAAW,YAAa,QAAO;AAE1C,QAAI;AACA,YAAM,SAAS,aAAa,QAAQ,KAAK,OAAO,UAAW;AAC3D,UAAI,CAAC,OAAQ,QAAO;AAEpB,YAAM,OAAO,KAAK,MAAM,MAAM;AAC9B,YAAM,iBAAiB,KAAK,aAAa,OAAO;AAChD,YAAM,YAAY,KAAK,YAAY,OAAO;AAE1C,UAAI,CAAC,kBAAkB,CAAC,UAAW,QAAO;AAE1C,aAAO;AAAA,QACH,SAAS,eAAe;AAAA,QACxB,YAAY,OAAO,eAAe,UAAU;AAAA,QAC5C,YAAY,OAAO,eAAe,UAAU;AAAA,QAC5C,cAAc,eAAe;AAAA,QAC7B;AAAA,QACA,WAAW,eAAe;AAAA,QAC1B,WAAW,eAAe;AAAA,MAC9B;AAAA,IACJ,SAAS,OAAO;AACZ,cAAQ,KAAK,yCAAyC,KAAK;AAC3D,aAAO;AAAA,IACX;AAAA,EACJ;AACJ;;;ACzbA,SAAS,UAAAC,eAAc;;;ACuChB,IAAM,uBAAuB;AAK7B,IAAM,mBAAmB;AAMzB,IAAM,sBAAsC;AAAA,EAC/C,iBAAiB;AAAA,EACjB,WAAW;AAAA,EACX,aAAa;AAAA,IACT,QAAQ;AAAA,IACR,MAAM;AAAA,IACN,SAAS;AAAA,IACT,UAAU;AAAA,IACV,UAAU;AAAA,EACd;AAAA,EACA,QAAQ;AAAA,IACJ;AAAA,MACI,QAAQ;AAAA,MACR,MAAM;AAAA,MACN,SAAS;AAAA;AAAA,MACT,UAAU;AAAA,MACV,UAAU;AAAA,IACd;AAAA,IACA;AAAA,MACI,QAAQ;AAAA,MACR,MAAM;AAAA,MACN,SAAS;AAAA,MACT,UAAU;AAAA,MACV,UAAU;AAAA,IACd;AAAA,EACJ;AACJ;AAMO,IAAM,0BAA0C;AAAA,EACnD,iBAAiB;AAAA,EACjB,WAAW;AAAA,EACX,aAAa;AAAA,IACT,QAAQ;AAAA,IACR,MAAM;AAAA,IACN,SAAS;AAAA,IACT,UAAU;AAAA,IACV,UAAU;AAAA,EACd;AAAA,EACA,QAAQ;AAAA,IACJ;AAAA,MACI,QAAQ;AAAA,MACR,MAAM;AAAA,MACN,SAAS;AAAA;AAAA,MACT,UAAU;AAAA,MACV,UAAU;AAAA,IACd;AAAA,IACA;AAAA,MACI,QAAQ;AAAA,MACR,MAAM;AAAA,MACN,SAAS;AAAA,MACT,UAAU;AAAA,MACV,UAAU;AAAA,IACd;AAAA,EACJ;AACJ;AAMO,IAAM,0BAA0C;AAAA,EACnD,iBAAiB;AAAA,EACjB,WAAW;AAAA,EACX,aAAa;AAAA,IACT,QAAQ;AAAA,IACR,MAAM;AAAA,IACN,SAAS;AAAA,IACT,UAAU;AAAA,IACV,UAAU;AAAA,EACd;AAAA,EACA,QAAQ;AAAA,IACJ;AAAA,MACI,QAAQ;AAAA,MACR,MAAM;AAAA,MACN,SAAS;AAAA;AAAA,MACT,UAAU;AAAA,MACV,UAAU;AAAA,IACd;AAAA,IACA;AAAA,MACI,QAAQ;AAAA,MACR,MAAM;AAAA,MACN,SAAS;AAAA,MACT,UAAU;AAAA,MACV,UAAU;AAAA,IACd;AAAA,EACJ;AACJ;AASO,IAAM,iBAAiD;AAAA,EAC1D,OAAO;AAAA,EACP,OAAO;AAAA,EACP,OAAO;AACX;AASO,SAAS,aAAa,iBAAgD;AACzE,SAAO,eAAe,eAAe,KAAK;AAC9C;AAKO,SAAS,aAAa,iBAAsC;AAC/D,QAAM,OAAO,aAAa,eAAe;AACzC,MAAI,CAAC,KAAM,QAAO,CAAC;AACnB,SAAO,CAAC,KAAK,aAAa,GAAG,KAAK,MAAM;AAC5C;AAKO,SAAS,iBAAiB,iBAAyB,QAAkC;AACxF,QAAM,SAAS,aAAa,eAAe;AAC3C,SAAO,OAAO,KAAK,OAAK,EAAE,OAAO,YAAY,MAAM,OAAO,YAAY,CAAC,KAAK;AAChF;AAKO,SAAS,kBAAkB,iBAAyB,SAAmC;AAC1F,QAAM,SAAS,aAAa,eAAe;AAC3C,QAAM,oBAAoB,QAAQ,YAAY;AAC9C,SAAO,OAAO,KAAK,OAAK,EAAE,QAAQ,YAAY,MAAM,iBAAiB,KAAK;AAC9E;AAKO,SAAS,cAAc,SAA0B;AACpD,SAAO,QAAQ,YAAY,MAAM,wBAC1B,YAAY;AACvB;AAKO,SAAS,uBAAiC;AAC7C,SAAO,OAAO,KAAK,cAAc,EAAE,IAAI,MAAM;AACjD;AAKO,SAAS,aAAa,iBAAwC;AACjE,SAAO,eAAe,eAAe,GAAG,aAAa;AACzD;;;AD7JA,IAAM,mBAA2C;AAAA,EAC7C,OAAO;AAAA,EACP,OAAO;AAAA,EACP,OAAO;AACX;AAMA,IAAM,uBAA+C;AAAA,EACjD,KAAK;AAAA,EACL,MAAM;AAAA,EACN,MAAM;AAAA,EACN,MAAM;AAAA,EACN,KAAK;AAAA,EACL,MAAM;AAAA,EACN,MAAM;AAAA,EACN,KAAK;AACT;AAKA,IAAM,YAAY;AAAA,EACd;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACJ;AAKA,IAAM,oBAAoB;AAenB,IAAM,iBAAN,MAAqB;AAAA,EAChB;AAAA,EACA,YAAiD,oBAAI,IAAI;AAAA,EACzD,QAAoC,oBAAI,IAAI;AAAA,EAEpD,YAAY,SAA+B,CAAC,GAAG;AAC3C,SAAK,SAAS;AAAA,MACV,eAAe,OAAO,iBAAiB;AAAA,MACvC,UAAU,OAAO,YAAY;AAAA,MAC7B,eAAe,OAAO,iBAAiB,CAAC;AAAA,IAC5C;AAAA,EACJ;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAcA,MAAM,WACF,iBACA,SACA,cACqB;AACrB,UAAM,WAAW,KAAK,YAAY,eAAe;AACjD,UAAM,YAAY,aAAa,eAAe;AAE9C,QAAI,CAAC,WAAW;AACZ,YAAM,IAAI,MAAM,SAAS,eAAe,gBAAgB;AAAA,IAC5D;AAEA,UAAM,SAAS,aAAa,eAAe;AAC3C,QAAI,YAAY,OAAO;AAAA,MACnB,OAAK,EAAE,QAAQ,YAAY,MAAM,aAAa,YAAY;AAAA,IAC9D;AAGA,QAAI,CAAC,aAAa,cAAc,YAAY,GAAG;AAC3C,kBAAY,UAAU;AAAA,IAC1B;AAGA,QAAI,CAAC,WAAW;AACZ,kBAAY,MAAM,KAAK,eAAe,UAAU,YAAY;AAAA,IAChE;AAEA,UAAM,UAAU,MAAM,KAAK,aAAa,UAAU,SAAS,cAAc,SAAS;AAClF,UAAM,YAAYC,QAAO,YAAY,SAAS,UAAU,QAAQ;AAEhE,UAAM,QAAQ,qBAAqB,UAAU,OAAO,YAAY,CAAC;AACjE,UAAM,WAAW,QAAQ,WAAW,SAAS,IAAI,QAAQ;AAEzD,WAAO;AAAA,MACH,OAAO;AAAA,MACP;AAAA,MACA;AAAA,MACA;AAAA,IACJ;AAAA,EACJ;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAUA,MAAM,oBACF,iBACA,SACA,sBAA+B,OACN;AAEzB,UAAM,WAAW,GAAG,eAAe,IAAI,QAAQ,YAAY,CAAC;AAC5D,QAAI,KAAK,OAAO,eAAe;AAC3B,YAAM,SAAS,KAAK,MAAM,IAAI,QAAQ;AACtC,UAAI,UAAU,OAAO,YAAY,KAAK,IAAI,GAAG;AACzC,eAAO,OAAO;AAAA,MAClB;AAAA,IACJ;AAEA,UAAM,YAAY,aAAa,eAAe;AAC9C,QAAI,CAAC,WAAW;AACZ,YAAM,IAAI,MAAM,SAAS,eAAe,gBAAgB;AAAA,IAC5D;AAEA,UAAM,WAAW,KAAK,YAAY,eAAe;AACjD,UAAM,SAAS,aAAa,eAAe;AAC3C,UAAM,WAA2B,CAAC;AAGlC,UAAM,kBAAkB,OAAO,IAAI,OAAO,UAAU;AAChD,UAAI;AACA,cAAM,UAAU,MAAM,KAAK;AAAA,UACvB;AAAA,UACA;AAAA,UACA,MAAM;AAAA,UACN;AAAA,QACJ;AACA,cAAM,YAAYA,QAAO,YAAY,SAAS,MAAM,QAAQ;AAE5D,cAAM,QAAQ,qBAAqB,MAAM,OAAO,YAAY,CAAC;AAC7D,cAAM,WAAW,QAAQ,WAAW,SAAS,IAAI,QAAQ;AACzD,eAAO,EAAE,OAAO,SAAS,WAAW,SAAS;AAAA,MACjD,SAAS,OAAO;AACZ,gBAAQ,KAAK,mBAAmB,MAAM,MAAM,aAAa,KAAK;AAC9D,eAAO,EAAE,OAAO,SAAS,IAAI,WAAW,KAAK,UAAU,OAAU;AAAA,MACrE;AAAA,IACJ,CAAC;AAED,UAAM,UAAU,MAAM,QAAQ,IAAI,eAAe;AAEjD,eAAW,UAAU,SAAS;AAC1B,UAAI,uBAAuB,OAAO,UAAU,IAAI;AAC5C,iBAAS,KAAK,MAAM;AAAA,MACxB;AAAA,IACJ;AAGA,UAAM,gBAAgB,SAAS,OAAO,CAAC,KAAK,MAAM,OAAO,EAAE,YAAY,IAAI,CAAC;AAE5E,UAAM,YAA8B;AAAA,MAChC;AAAA,MACA,WAAW,UAAU;AAAA,MACrB;AAAA,MACA,QAAQ;AAAA,MACR,eAAe,gBAAgB,IAAI,gBAAgB;AAAA,MACnD,aAAa,KAAK,IAAI;AAAA,IAC1B;AAGA,QAAI,KAAK,OAAO,eAAe;AAC3B,WAAK,MAAM,IAAI,UAAU;AAAA,QACrB,SAAS;AAAA,QACT,WAAW,KAAK,IAAI,IAAI,KAAK,OAAO;AAAA,MACxC,CAAC;AAAA,IACL;AAEA,WAAO;AAAA,EACX;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASA,MAAM,iBACF,iBACA,SACqB;AACrB,WAAO,KAAK,WAAW,iBAAiB,SAAS,oBAAoB;AAAA,EACzE;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASA,MAAM,sBACF,SACA,UAC2B;AAC3B,UAAM,WAAW,SAAS;AAAA,MAAI,aAC1B,KAAK,oBAAoB,SAAS,OAAO,EAAE,MAAM,WAAS;AACtD,gBAAQ,KAAK,sCAAsC,OAAO,KAAK,KAAK;AACpE,eAAO;AAAA,MACX,CAAC;AAAA,IACL;AAEA,UAAM,UAAU,MAAM,QAAQ,IAAI,QAAQ;AAC1C,WAAO,QAAQ,OAAO,CAAC,MAA6B,MAAM,IAAI;AAAA,EAClE;AAAA;AAAA;AAAA;AAAA,EAKA,aAAmB;AACf,SAAK,MAAM,MAAM;AAAA,EACrB;AAAA;AAAA;AAAA;AAAA,EAKA,gBAAgB,iBAAyB,SAAuB;AAC5D,UAAM,WAAW,GAAG,eAAe,IAAI,QAAQ,YAAY,CAAC;AAC5D,SAAK,MAAM,OAAO,QAAQ;AAAA,EAC9B;AAAA;AAAA;AAAA;AAAA,EAKA,UAAU,iBAAyB,QAAsB;AACrD,SAAK,OAAO,cAAc,eAAe,IAAI;AAE7C,SAAK,UAAU,OAAO,eAAe;AAAA,EACzC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASQ,YAAY,iBAAiD;AACjE,QAAI,WAAW,KAAK,UAAU,IAAI,eAAe;AACjD,QAAI,UAAU;AACV,aAAO;AAAA,IACX;AAEA,UAAM,SAAS,KAAK,OAAO,cAAc,eAAe,KACzC,iBAAiB,eAAe;AAE/C,QAAI,CAAC,QAAQ;AACT,YAAM,IAAI,MAAM,mCAAmC,eAAe,EAAE;AAAA,IACxE;AAEA,eAAW,IAAIA,QAAO,gBAAgB,MAAM;AAC5C,SAAK,UAAU,IAAI,iBAAiB,QAAQ;AAC5C,WAAO;AAAA,EACX;AAAA;AAAA;AAAA;AAAA,EAKA,MAAc,aACV,UACA,SACA,cACA,YACe;AACf,QAAI,cAAc,YAAY,GAAG;AAC7B,aAAO,MAAM,SAAS,WAAW,OAAO;AAAA,IAC5C;AAEA,UAAM,WAAW,IAAIA,QAAO,SAAS,cAAc,WAAW,QAAQ;AACtE,WAAO,MAAM,SAAS,UAAU,OAAO;AAAA,EAC3C;AAAA;AAAA;AAAA;AAAA,EAKA,MAAc,eACV,UACA,cACkB;AAClB,UAAM,WAAW,IAAIA,QAAO,SAAS,cAAc,WAAW,QAAQ;AAEtE,UAAM,CAAC,QAAQ,MAAM,QAAQ,IAAI,MAAM,QAAQ,IAAI;AAAA,MAC/C,SAAS,OAAO,EAAE,MAAM,MAAM,SAAS;AAAA,MACvC,SAAS,KAAK,EAAE,MAAM,MAAM,eAAe;AAAA,MAC3C,SAAS,SAAS,EAAE,MAAM,MAAM,EAAE;AAAA,IACtC,CAAC;AAED,WAAO;AAAA,MACH;AAAA,MACA;AAAA,MACA,SAAS;AAAA,MACT,UAAU,OAAO,QAAQ;AAAA,MACzB,UAAU;AAAA,IACd;AAAA,EACJ;AACJ;;;AEzXA,SAAS,UAAAC,eAAc;AA0DvB,IAAM,2BAA2B;AACjC,IAAM,iCAAiC;AACvC,IAAM,kBAAkB;AAExB,IAAMC,oBAA2C;AAAA,EAC7C,OAAO;AAAA,EACP,OAAO;AAAA,EACP,OAAO;AACX;AAMO,IAAM,qBAAN,MAAyB;AAAA,EACpB;AAAA,EACA,YAAiD,oBAAI,IAAI;AAAA,EACzD,sBAAqD,oBAAI,IAAI;AAAA,EAC7D,YAAgD,oBAAI,IAAI;AAAA,EACxD,mBAAgD,oBAAI,IAAI;AAAA,EAEhE,YAAY,SAAwB,CAAC,GAAG;AACpC,SAAK,SAAS;AAAA,MACV,iBAAiB,OAAO,mBAAmB;AAAA,MAC3C,uBAAuB,OAAO,yBAAyB;AAAA,MACvD,SAAS,OAAO,WAAW;AAAA,MAC3B,eAAe,OAAO,iBAAiB,CAAC;AAAA,IAC5C;AAAA,EACJ;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAeA,MACI,MACA,iBACA,UACA,aACgB;AAEhB,UAAM,QAA0B;AAAA,MAC5B;AAAA,MACA,QAAQ;AAAA,MACR;AAAA,MACA,eAAe;AAAA,MACf,uBAAuB,KAAK,OAAO;AAAA,MACnC,aAAa,KAAK,IAAI;AAAA,MACtB;AAAA,IACJ;AAEA,SAAK,oBAAoB,IAAI,MAAM,KAAK;AAExC,QAAI,UAAU;AACV,WAAK,YAAY,MAAM,QAAQ;AAAA,IACnC;AAGA,SAAK,aAAa,MAAM,eAAe;AAEvC,WAAO;AAAA,EACX;AAAA;AAAA;AAAA;AAAA,EAKA,YAAY,MAAc,UAAqC;AAC3D,UAAM,WAAW,KAAK,UAAU,IAAI,IAAI,KAAK,CAAC;AAC9C,aAAS,KAAK,QAAQ;AACtB,SAAK,UAAU,IAAI,MAAM,QAAQ;AAAA,EACrC;AAAA;AAAA;AAAA;AAAA,EAKA,eAAe,MAAc,UAAqC;AAC9D,UAAM,WAAW,KAAK,UAAU,IAAI,IAAI,KAAK,CAAC;AAC9C,UAAM,WAAW,SAAS,OAAO,QAAM,OAAO,QAAQ;AACtD,QAAI,SAAS,SAAS,GAAG;AACrB,WAAK,UAAU,IAAI,MAAM,QAAQ;AAAA,IACrC,OAAO;AACH,WAAK,UAAU,OAAO,IAAI;AAAA,IAC9B;AAAA,EACJ;AAAA;AAAA;AAAA;AAAA,EAKA,SAAS,MAAuC;AAC5C,WAAO,KAAK,oBAAoB,IAAI,IAAI,KAAK;AAAA,EACjD;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASA,MAAM,oBACF,MACA,iBACyB;AAEzB,QAAI,QAAQ,KAAK,oBAAoB,IAAI,IAAI;AAE7C,QAAI,CAAC,OAAO;AACR,cAAQ,KAAK,MAAM,MAAM,eAAe;AAAA,IAC5C;AAGA,QAAI,MAAM,WAAW,eAAe,MAAM,WAAW,YAAY,MAAM,WAAW,WAAW;AACzF,aAAO;AAAA,IACX;AAGA,WAAO,IAAI,QAAQ,CAAC,SAAS,WAAW;AACpC,YAAM,WAAgC,CAAC,aAAa;AAChD,YAAI,SAAS,WAAW,aAAa;AACjC,eAAK,eAAe,MAAM,QAAQ;AAClC,kBAAQ,QAAQ;AAAA,QACpB,WAAW,SAAS,WAAW,YAAY,SAAS,WAAW,WAAW;AACtE,eAAK,eAAe,MAAM,QAAQ;AAClC,iBAAO,IAAI,MAAM,SAAS,SAAS,eAAe,SAAS,MAAM,EAAE,CAAC;AAAA,QACxE;AAAA,MACJ;AAEA,WAAK,YAAY,MAAM,QAAQ;AAAA,IACnC,CAAC;AAAA,EACL;AAAA;AAAA;AAAA;AAAA,EAKA,aAAa,MAAoB;AAC7B,UAAM,WAAW,KAAK,iBAAiB,IAAI,IAAI;AAC/C,QAAI,UAAU;AACV,oBAAc,QAAQ;AACtB,WAAK,iBAAiB,OAAO,IAAI;AAAA,IACrC;AACA,SAAK,oBAAoB,OAAO,IAAI;AACpC,SAAK,UAAU,OAAO,IAAI;AAAA,EAC9B;AAAA;AAAA;AAAA;AAAA,EAKA,UAAgB;AACZ,eAAW,QAAQ,KAAK,iBAAiB,KAAK,GAAG;AAC7C,WAAK,aAAa,IAAI;AAAA,IAC1B;AAAA,EACJ;AAAA;AAAA;AAAA;AAAA,EAKA,gBAAoC;AAChC,WAAO,MAAM,KAAK,KAAK,oBAAoB,OAAO,CAAC;AAAA,EACvD;AAAA;AAAA;AAAA;AAAA,EAKA,aAAiC;AAC7B,WAAO,KAAK,cAAc,EAAE;AAAA,MACxB,QAAM,GAAG,WAAW,aAAa,GAAG,WAAW,eAAe,GAAG,WAAW;AAAA,IAChF;AAAA,EACJ;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASQ,YAAY,iBAAiD;AACjE,QAAI,WAAW,KAAK,UAAU,IAAI,eAAe;AACjD,QAAI,UAAU;AACV,aAAO;AAAA,IACX;AAEA,UAAM,SAAS,KAAK,OAAO,cAAc,eAAe,KACzCA,kBAAiB,eAAe;AAE/C,QAAI,CAAC,QAAQ;AACT,YAAM,IAAI,MAAM,mCAAmC,eAAe,EAAE;AAAA,IACxE;AAEA,eAAW,IAAID,QAAO,gBAAgB,MAAM;AAC5C,SAAK,UAAU,IAAI,iBAAiB,QAAQ;AAC5C,WAAO;AAAA,EACX;AAAA;AAAA;AAAA;AAAA,EAKQ,aAAa,MAAc,iBAA+B;AAE9D,SAAK,iBAAiB,MAAM,eAAe;AAG3C,UAAM,WAAW,YAAY,MAAM;AAC/B,WAAK,iBAAiB,MAAM,eAAe;AAAA,IAC/C,GAAG,KAAK,OAAO,eAAe;AAE9B,SAAK,iBAAiB,IAAI,MAAM,QAAQ;AAAA,EAC5C;AAAA;AAAA;AAAA;AAAA,EAKA,MAAc,iBAAiB,MAAc,iBAAwC;AACjF,UAAM,QAAQ,KAAK,oBAAoB,IAAI,IAAI;AAC/C,QAAI,CAAC,OAAO;AACR,WAAK,aAAa,IAAI;AACtB;AAAA,IACJ;AAGA,QAAI,KAAK,IAAI,IAAI,MAAM,cAAc,KAAK,OAAO,SAAS;AACtD,WAAK,YAAY,MAAM;AAAA,QACnB,QAAQ;AAAA,QACR,OAAO;AAAA,MACX,CAAC;AACD,WAAK,aAAa,IAAI;AACtB;AAAA,IACJ;AAEA,QAAI;AACA,YAAM,WAAW,KAAK,YAAY,eAAe;AACjD,YAAM,UAAU,MAAM,SAAS,sBAAsB,IAAI;AAEzD,UAAI,CAAC,SAAS;AAEV,YAAI,MAAM,WAAW,WAAW;AAC5B,eAAK,YAAY,MAAM,EAAE,QAAQ,YAAY,CAAC;AAAA,QAClD;AACA;AAAA,MACJ;AAGA,YAAM,eAAe,MAAM,SAAS,eAAe;AACnD,YAAM,gBAAgB,eAAe,QAAQ,cAAc;AAE3D,UAAI,QAAQ,WAAW,GAAG;AAEtB,aAAK,YAAY,MAAM;AAAA,UACnB,QAAQ;AAAA,UACR,aAAa,QAAQ;AAAA,UACrB;AAAA,UACA,SAAS,QAAQ;AAAA,UACjB,mBAAmB,QAAQ;AAAA,UAC3B,OAAO;AAAA,QACX,CAAC;AACD,aAAK,aAAa,IAAI;AACtB;AAAA,MACJ;AAEA,UAAI,iBAAiB,KAAK,OAAO,uBAAuB;AAEpD,aAAK,YAAY,MAAM;AAAA,UACnB,QAAQ;AAAA,UACR,aAAa,QAAQ;AAAA,UACrB;AAAA,UACA,SAAS,QAAQ;AAAA,UACjB,mBAAmB,QAAQ;AAAA,UAC3B,aAAa,KAAK,IAAI;AAAA,QAC1B,CAAC;AACD,aAAK,aAAa,IAAI;AAAA,MAC1B,OAAO;AAEH,aAAK,YAAY,MAAM;AAAA,UACnB,QAAQ;AAAA,UACR,aAAa,QAAQ;AAAA,UACrB;AAAA,UACA,SAAS,QAAQ;AAAA,UACjB,mBAAmB,QAAQ;AAAA,QAC/B,CAAC;AAAA,MACL;AAAA,IACJ,SAAS,OAAO;AACZ,cAAQ,KAAK,8BAA8B,IAAI,KAAK,KAAK;AAAA,IAE7D;AAAA,EACJ;AAAA;AAAA;AAAA;AAAA,EAKQ,YAAY,MAAc,SAA0C;AACxE,UAAM,UAAU,KAAK,oBAAoB,IAAI,IAAI;AACjD,QAAI,CAAC,QAAS;AAEd,UAAM,WAA6B,EAAE,GAAG,SAAS,GAAG,QAAQ;AAC5D,SAAK,oBAAoB,IAAI,MAAM,QAAQ;AAG3C,UAAM,YAAY,KAAK,UAAU,IAAI,IAAI,KAAK,CAAC;AAC/C,eAAW,YAAY,WAAW;AAC9B,UAAI;AACA,iBAAS,QAAQ;AAAA,MACrB,SAAS,OAAO;AACZ,gBAAQ,MAAM,kCAAkC,KAAK;AAAA,MACzD;AAAA,IACJ;AAAA,EACJ;AACJ;AASO,SAAS,eACZ,iBACA,MACa;AACb,QAAM,YAAoC;AAAA,IACtC,OAAO;AAAA,IACP,OAAO;AAAA,IACP,OAAO;AAAA,EACX;AAEA,QAAM,UAAU,UAAU,eAAe;AACzC,SAAO,UAAU,GAAG,OAAO,GAAG,IAAI,KAAK;AAC3C;AAKO,SAAS,uBAAuB,OAAiC;AACpE,UAAQ,MAAM,QAAQ;AAAA,IAClB,KAAK;AACD,aAAO;AAAA,IACX,KAAK;AACD,aAAO;AAAA,IACX,KAAK;AACD,aAAO,eAAe,MAAM,aAAa,IAAI,MAAM,qBAAqB;AAAA,IAC5E,KAAK;AACD,aAAO;AAAA,IACX,KAAK;AACD,aAAO,uBAAuB,MAAM,SAAS,eAAe;AAAA,IAChE,KAAK;AACD,aAAO;AAAA,IACX;AACI,aAAO;AAAA,EACf;AACJ;;;AC5ZA,SAAS,UAAAE,eAAc;;;ACAvB,SAAS,UAAAC,eAAc;AAYhB,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,cAAMC,OAAM,YAAY;AAAA,MAC1B;AAAA,IACF,QAAQ;AACN,UAAI,IAAI,aAAa,GAAG;AACtB,kBAAU,IAAI,GAAG,UAAU;AAC3B,cAAMA,OAAM,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,cAAMA,OAAM,YAAY;AAAA,MAC1B;AAAA,IACF,QAAQ;AACN,UAAI,IAAI,aAAa,GAAG;AACtB,kBAAU,IAAI,GAAG,UAAU;AAC3B,cAAMA,OAAM,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,cAAMA,OAAM,YAAY;AAAA,MAC1B;AAAA,IACF,QAAQ;AACN,UAAI,IAAI,aAAa,GAAG;AACtB,kBAAU,IAAI,GAAG,UAAU;AAC3B,cAAMA,OAAM,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,OAAOC,QAAO,UAAUA,QAAO,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,8BAA8BA,QAAO;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,UAAMD,OAAM,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;AAiCO,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,SAASE,OAAM,IAA2B;AACxC,SAAO,IAAI,QAAQ,aAAW,WAAW,SAAS,EAAE,CAAC;AACvD;;;ADlgBA,IAAM,iBAA6C;AAAA,EAC/C,SAAS;AAAA,EACT,YAAY;AAAA,EACZ,cAAc;AAAA;AAAA,EACd,sBAAsB;AAAA;AAAA,EACtB,uBAAuB;AAAA,EACvB,WAAW;AACf;AASO,IAAM,oBAAN,MAAwB;AAAA,EACnB;AAAA,EACA,mBAAkD,oBAAI,IAAI;AAAA,EAElE,YAAY,SAA2B,CAAC,GAAG;AACvC,SAAK,SAAS,EAAE,GAAG,gBAAgB,GAAG,OAAO;AAAA,EACjD;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASA,UAAU,QAAyC;AAC/C,SAAK,SAAS,EAAE,GAAG,KAAK,QAAQ,GAAG,OAAO;AAAA,EAC9C;AAAA;AAAA;AAAA;AAAA,EAKA,YAA8B;AAC1B,WAAO,EAAE,GAAG,KAAK,OAAO;AAAA,EAC5B;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASA,MAAM,aACF,QACA,mBACA,UACuB;AAEvB,UAAM,UAAU,MAAM,SAAS,WAAW;AAC1C,UAAM,WAAW,QAAQ,YAAY;AAIrC,UAAM,eAAe;AACrB,UAAM,YAAY,eAAe;AAGjC,QAAI,aAAa;AACjB,QAAI;AACA,YAAM,cAAc,CAAC,8CAA8C;AACnE,YAAM,WAAW,IAAIC,QAAO;AAAA,QACxB,kBAAkB,UAAU;AAAA,QAC5B;AAAA,QACA;AAAA,MACJ;AACA,mBAAa,MAAM,SAAS,WAAW;AAAA,IAC3C,QAAQ;AAAA,IAER;AAGA,QAAI,aAAa;AACjB,QAAI,KAAK,OAAO,aAAa,KAAK,OAAO,YAAY;AACjD,UAAI;AACA,qBAAa,MAAM,KAAK;AAAA,UACpB,OAAO;AAAA,UACP,kBAAkB;AAAA,QACtB;AAAA,MACJ,QAAQ;AAAA,MAER;AAAA,IACJ;AAEA,UAAM,YAAY,YAAY,aAAa;AAE3C,WAAO;AAAA,MACH;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA,gBAAgB,KAAK,UAAU,SAAS;AAAA,MACxC,UAAU;AAAA,IACd;AAAA,EACJ;AAAA;AAAA;AAAA;AAAA,EAKA,MAAc,gBACV,kBACA,cACe;AACf,QAAI,CAAC,KAAK,OAAO,YAAY;AACzB,aAAO;AAAA,IACX;AAIA,UAAM,WAAW,MAAM;AAAA,MACnB,GAAG,KAAK,OAAO,UAAU,2BAA2B,gBAAgB;AAAA,IACxE;AAEA,QAAI,CAAC,SAAS,IAAI;AACd,YAAM,IAAI,MAAM,6BAA6B;AAAA,IACjD;AAEA,UAAM,OAAO,MAAM,SAAS,KAAK;AAQjC,WAAO,OAAO,KAAK,MAAM,WAAW,GAAG;AAAA,EAC3C;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASA,MAAM,SACF,cACA,gBACA,UACA,YACe;AACf,iBAAa;AAAA,MACT,QAAQ;AAAA,MACR,MAAM;AAAA,MACN,YAAY;AAAA,MACZ,SAAS;AAAA,MACT,SAAS,EAAE,SAAS;AAAA,IACxB,CAAC;AAED,UAAM,YAAY,MAAM,SAAS,cAAc,gBAAgB,UAAU;AAAA,MACrE,SAAS,KAAK,OAAO;AAAA,MACrB,YAAY,KAAK,KAAK,KAAK,OAAO,eAAe,KAAK,OAAO,oBAAoB;AAAA,MACjF,cAAc,KAAK,OAAO;AAAA,MAC1B,SAAS,CAAC,SAAS,QAAQ;AACvB,qBAAa;AAAA,UACT,QAAQ;AAAA,UACR,MAAM;AAAA,UACN,YAAY;AAAA,UACZ,SAAS,kCAAkC,OAAO,IAAI,GAAG;AAAA,UACzD,SAAS,EAAE,SAAS;AAAA,QACxB,CAAC;AAAA,MACL;AAAA,IACJ,CAAC;AAED,iBAAa;AAAA,MACT,QAAQ;AAAA,MACR,MAAM;AAAA,MACN,YAAY;AAAA,MACZ,SAAS;AAAA,MACT,SAAS,EAAE,UAAU,UAAU,KAAK;AAAA,IACxC,CAAC;AAED,WAAO;AAAA,EACX;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,iBACF,QACA,YACe;AACf,iBAAa;AAAA,MACT,QAAQ;AAAA,MACR,MAAM;AAAA,MACN,YAAY;AAAA,MACZ,SAAS;AAAA,MACT,SAAS,EAAE,OAAO;AAAA,IACtB,CAAC;AAED,UAAM,YAAY,MAAM,iBAAiB,QAAQ;AAAA,MAC7C,SAAS,KAAK,OAAO;AAAA,MACrB,YAAY,KAAK,KAAK,KAAK,OAAO,eAAe,KAAK,OAAO,oBAAoB;AAAA,MACjF,cAAc,KAAK,OAAO;AAAA,MAC1B,SAAS,CAAC,SAAS,QAAQ;AACvB,qBAAa;AAAA,UACT,QAAQ;AAAA,UACR,MAAM;AAAA,UACN,YAAY;AAAA,UACZ,SAAS,kCAAkC,OAAO,IAAI,GAAG;AAAA,UACzD,SAAS,EAAE,OAAO;AAAA,QACtB,CAAC;AAAA,MACL;AAAA,IACJ,CAAC;AAED,iBAAa;AAAA,MACT,QAAQ;AAAA,MACR,MAAM;AAAA,MACN,YAAY;AAAA,MACZ,SAAS;AAAA,MACT,SAAS,EAAE,QAAQ,UAAU,KAAK;AAAA,IACtC,CAAC;AAED,WAAO;AAAA,EACX;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,iBACF,cACA,gBACA,UACA,YACY;AACZ,UAAM,qBAAqB,KAAK,OAAO,UACjC,gBAAgB,iBAChB,gBAAgB;AAEtB,WAAO,MAAM;AAAA,MACT;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,QACI,SAAS,KAAK,OAAO;AAAA,QACrB;AAAA,QACA,WAAW,KAAK,OAAO;AAAA,QACvB,iBAAiB,KAAK,OAAO;AAAA,QAC7B,YAAY,CAAC,SAAS,aAAa;AAC/B,uBAAa;AAAA,YACT,QAAQ;AAAA,YACR,MAAM;AAAA,YACN,YAAY;AAAA,YACZ,SAAS,0BAA0B,OAAO,IAAI,QAAQ;AAAA,YACtD,SAAS;AAAA,cACL;AAAA,cACA,oBAAoB;AAAA,cACpB,oBAAoB;AAAA,YACxB;AAAA,UACJ,CAAC;AAAA,QACL;AAAA,MACJ;AAAA,IACJ;AAAA,EACJ;AAAA;AAAA;AAAA;AAAA,EAKA,SAAS,WAA0D;AAC/D,UAAM,MAAM,SAAS,SAAS;AAC9B,UAAM,UAAU,oBAAoB,IAAI,OAAO;AAC/C,WAAO,EAAE,KAAK,QAAQ;AAAA,EAC1B;AAAA;AAAA;AAAA;AAAA,EAKA,uBAAuB,WAA2B;AAC9C,WAAO,iBAAiB,SAAS;AAAA,EACrC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASA,cACI,cACA,aACA,kBACA,UACA,gBACgB;AAChB,UAAM,SAA2B;AAAA,MAC7B;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA,UAAU;AAAA,MACV,QAAQ;AAAA,IACZ;AAEA,SAAK,iBAAiB,IAAI,cAAc,MAAM;AAC9C,WAAO;AAAA,EACX;AAAA;AAAA;AAAA;AAAA,EAKA,mBAAmB,cAAoD;AACnE,WAAO,KAAK,iBAAiB,IAAI,YAAY;AAAA,EACjD;AAAA;AAAA;AAAA;AAAA,EAKA,yBAA6C;AACzC,WAAO,MAAM,KAAK,KAAK,iBAAiB,OAAO,CAAC,EAAE;AAAA,MAC9C,OAAK,EAAE,WAAW,eAAe,EAAE,WAAW;AAAA,IAClD;AAAA,EACJ;AAAA;AAAA;AAAA;AAAA,EAKA,eACI,cACA,SAC4B;AAC5B,UAAM,WAAW,KAAK,iBAAiB,IAAI,YAAY;AACvD,QAAI,CAAC,SAAU,QAAO;AAEtB,WAAO,OAAO,UAAU,OAAO;AAC/B,WAAO;AAAA,EACX;AAAA;AAAA;AAAA;AAAA,EAKA,iBACI,cACA,KACA,mBAC4B;AAC5B,UAAM,WAAW,KAAK,iBAAiB,IAAI,YAAY;AACvD,QAAI,CAAC,SAAU,QAAO;AAEtB,aAAS,MAAM;AACf,aAAS,YAAY,SAAS,GAAG;AACjC,aAAS,oBAAoB;AAC7B,aAAS,SAAS;AAElB,WAAO;AAAA,EACX;AAAA;AAAA;AAAA;AAAA,EAKA,aAAa,cAAsB,OAA6C;AAC5E,UAAM,WAAW,KAAK,iBAAiB,IAAI,YAAY;AACvD,QAAI,CAAC,SAAU,QAAO;AAEtB,aAAS,SAAS;AAClB,aAAS,QAAQ;AAEjB,WAAO;AAAA,EACX;AAAA;AAAA;AAAA;AAAA,EAKA,yBAA+B;AAC3B,eAAW,CAAC,MAAM,QAAQ,KAAK,KAAK,iBAAiB,QAAQ,GAAG;AAC5D,UAAI,SAAS,WAAW,eAAe,SAAS,WAAW,UAAU;AACjE,aAAK,iBAAiB,OAAO,IAAI;AAAA,MACrC;AAAA,IACJ;AAAA,EACJ;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASA,MAAM,kBACF,UACA,QACA,oBACe;AACf,WAAO,MAAM,yBAAyB,UAAU,QAAQ,kBAAkB;AAAA,EAC9E;AAAA;AAAA;AAAA;AAAA,EAKA,iBAAiB,SAAyB;AACtC,WAAO,wBAAwB,OAAO;AAAA,EAC1C;AAAA;AAAA;AAAA;AAAA,EAKA,eACI,QACA,QACA,iBACM;AACN,WAAO,GAAG,eAAe,OAAO,MAAM;AAAA,EAC1C;AAAA;AAAA;AAAA;AAAA,EAKA,uBACI,cACA,gBACA,UACM;AACN,UAAM,OAAO,KAAK,OAAO,UACnB,iCACA;AAEN,UAAM,oBAAoB,wBAAwB,cAAc;AAChE,WAAO,GAAG,IAAI,IAAI,YAAY,IAAI,iBAAiB,IAAI,SAAS,SAAS,CAAC;AAAA,EAC9E;AAAA;AAAA;AAAA;AAAA,EAKQ,UAAU,KAAqB;AACnC,UAAM,MAAM,OAAO,GAAG,IAAI;AAC1B,QAAI,MAAM,MAAQ;AACd,aAAO,IAAI,OAAO,GAAG,IAAI,KAAK,QAAQ,CAAC,CAAC;AAAA,IAC5C;AACA,WAAO,GAAG,IAAI,QAAQ,CAAC,CAAC;AAAA,EAC5B;AACJ;AAMO,IAAM,oBAAoB,IAAI,kBAAkB;;;AErWvD,IAAMC,kBAAiE;AAAA,EACnE,QAAQ;AAAA,EACR,WAAW;AAAA,EACX,YAAY;AAChB;AASO,IAAM,gBAAN,MAAM,eAAc;AAAA,EACf;AAAA,EACA;AAAA,EAER,YAAY,QAA6B;AACrC,SAAK,UAAU,OAAO,QAAQ,QAAQ,QAAQ,EAAE;AAChD,SAAK,SAAS,EAAE,GAAGA,iBAAgB,GAAG,OAAO;AAAA,EACjD;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASA,MAAM,YACF,WACA,aACA,kBACA,cACA,UACA,YACqB;AACrB,SAAK;AACL,SAAK;AACL,SAAK;AACL,SAAK;AACL,SAAK;AACL,SAAK;AACL,UAAM,IAAI;AAAA,MACN;AAAA,IAEJ;AAAA,EACJ;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAYA,MAAM,mBAAmB,SAAiE;AACtF,QAAI;AACA,YAAM,WAAW,MAAM,KAAK,MAAM,kBAAkB;AAAA,QAChD,QAAQ;AAAA,QACR,MAAM,KAAK,UAAU,OAAO;AAAA,MAChC,CAAC;AAED,aAAO;AAAA,QACH,SAAS,SAAS;AAAA,QAClB,QAAQ,SAAS,mBAAmB,SAAS;AAAA,QAC7C,UAAU,SAAS;AAAA,QACnB,OAAO,SAAS;AAAA,QAChB,SAAS,SAAS;AAAA,MACtB;AAAA,IACJ,SAAS,KAAU;AAEf,UAAI,IAAI,WAAW,OAAO,IAAI,MAAM;AAChC,eAAO;AAAA,UACH,SAAS;AAAA,UACT,OAAO,IAAI,KAAK,SAAS;AAAA,UACzB,SAAS,IAAI,KAAK;AAAA,QACtB;AAAA,MACJ;AAEA,YAAM;AAAA,IACV;AAAA,EACJ;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAkBA,MAAM,YAAY,SAAyD;AACvE,QAAI;AACA,YAAM,WAAW,MAAM,KAAK,MAAM,wBAAwB;AAAA,QACtD,QAAQ;AAAA,QACR,MAAM,KAAK,UAAU,OAAO;AAAA,MAChC,CAAC;AAED,aAAO;AAAA,QACH,SAAS,SAAS,WAAW;AAAA,QAC7B,QAAQ,SAAS;AAAA,QACjB,MAAM,SAAS,QAAQ;AAAA,QACvB,WAAW,SAAS;AAAA,QACpB,OAAO,SAAS;AAAA,QAChB,UAAU,SAAS,YAAY;AAAA,MACnC;AAAA,IACJ,SAAS,KAAU;AAEf,UAAI,IAAI,WAAW,OAAO,IAAI,MAAM;AAChC,eAAO;AAAA,UACH,SAAS;AAAA,UACT,MAAM;AAAA,UACN,OAAO,IAAI,KAAK,SAAS;AAAA,QAC7B;AAAA,MACJ;AACA,YAAM;AAAA,IACV;AAAA,EACJ;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,eAAe,WAA0C;AAC3D,SAAK;AACL,UAAM,IAAI,MAAM,uEAAuE;AAAA,EAC3F;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,mBAAmB,cAAoD;AACzE,SAAK;AACL,WAAO;AAAA,EACX;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,mBACF,aACA,UAC4B;AAC5B,SAAK;AACL,SAAK;AACL,WAAO;AAAA,EACX;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,YAAY,WAAqC;AACnD,SAAK;AACL,WAAO;AAAA,EACX;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,aACF,WACA,YAAoB,MACpB,oBAA4B,KAC5B,YACqB;AACrB,SAAK;AACL,SAAK;AACL,SAAK;AACL,SAAK;AACL,UAAM,IAAI,MAAM,qEAAqE;AAAA,EACzF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASA,MAAM,YACF,aACA,kBACA,cACsB;AACtB,SAAK;AACL,SAAK;AAIL,UAAM,WAAW,MAAM,KAAK,MAAM,2BAA2B,gBAAgB,EAAE;AAC/E,UAAM,aAAa,OAAO,UAAU,MAAM,WAAW,GAAG;AACxD,UAAM,QAAQ,OAAO,UAAU,MAAM,SAAS,WAAW,SAAS,CAAC;AAEnE,WAAO;AAAA,MACH;AAAA,MACA;AAAA,MACA,kBAAkB;AAAA,MAClB,uBAAuB;AAAA,MACvB,cAAc;AAAA,MACd,WAAW,KAAK,IAAI,IAAI;AAAA,MACxB,SAAS;AAAA,IACb;AAAA,EACJ;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASA,MAAM,UAAgC;AAClC,UAAM,WAAW,MAAM,KAAK,MAAM,cAAc;AAEhD,WAAO;AAAA,MACH,MAAM;AAAA,MACN,SAAS,UAAU,SAAS,WAAW,UAAU,WAAW;AAAA,MAC5D,kBAAkB,UAAU,mBAAmB,CAAC,GAAG,IAAI,CAAC,MAAW,EAAE,mBAAmB,CAAC;AAAA,MACzF,QAAQ,CAAC;AAAA,MACT,QAAQ;AAAA,MACR,YAAY;AAAA,IAChB;AAAA,EACJ;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,YAAmC;AACrC,UAAM,IAAI,MAAM,kEAAkE;AAAA,EACtF;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,iBACF,aACA,kBACgB;AAChB,SAAK;AACL,SAAK;AACL,WAAO;AAAA,EACX;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,cAAgC;AAClC,QAAI;AACA,YAAM,WAAW,MAAM,KAAK,MAAM,SAAS;AAC3C,aAAO,SAAS,WAAW,aAAa,SAAS,WAAW,cAAc,SAAS,YAAY;AAAA,IACnG,QAAQ;AACJ,aAAO;AAAA,IACX;AAAA,EACJ;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASA,MAAM,iBAAiB,aAA8C;AACjE,SAAK;AACL,WAAO,CAAC;AAAA,EACZ;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,gBACF,aACA,QAAgB,IAChB,SAAiB,GACM;AACvB,SAAK;AACL,SAAK;AACL,SAAK;AACL,WAAO,CAAC;AAAA,EACZ;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASA,OAAwB,cAAc;AAAA;AAAA;AAAA;AAAA,EAKtC,MAAc,MACV,MACA,UAAuB,CAAC,GACZ;AACZ,UAAM,UAAuB;AAAA,MACzB,gBAAgB;AAAA,MAChB,cAAc,gBAAgB,eAAc,WAAW;AAAA,MACvD,GAAI,QAAQ,WAAW,CAAC;AAAA,IAC5B;AAEA,QAAI,KAAK,OAAO,QAAQ;AACpB,MAAC,QAAmC,WAAW,IAAI,KAAK,OAAO;AAAA,IACnE;AAEA,UAAM,aAAa,IAAI,gBAAgB;AACvC,UAAM,UAAU,WAAW,MAAM,WAAW,MAAM,GAAG,KAAK,OAAO,SAAS;AAE1E,QAAI,YAA0B;AAE9B,aAAS,UAAU,GAAG,WAAW,KAAK,OAAO,YAAY,WAAW;AAChE,UAAI;AACA,cAAM,WAAW,MAAM,MAAM,GAAG,KAAK,OAAO,GAAG,IAAI,IAAI;AAAA,UACnD,GAAG;AAAA,UACH;AAAA,UACA,QAAQ,WAAW;AAAA,QACvB,CAAC;AAED,qBAAa,OAAO;AAEpB,YAAI,CAAC,SAAS,IAAI;AACd,gBAAM,QAAa,IAAI;AAAA,YACnB,2BAA2B,SAAS,MAAM,IAAI,SAAS,UAAU;AAAA,UACrE;AACA,gBAAM,SAAS,SAAS;AACxB,cAAI;AACA,kBAAM,OAAO,MAAM,SAAS,KAAK;AAAA,UACrC,QAAQ;AAAA,UAER;AACA,gBAAM;AAAA,QACV;AAEA,eAAO,MAAM,SAAS,KAAK;AAAA,MAC/B,SAAS,OAAY;AACjB,oBAAY;AAGZ,YAAI,MAAM,UAAU,MAAM,UAAU,OAAO,MAAM,SAAS,KAAK;AAC3D,gBAAM;AAAA,QACV;AAGA,YAAI,MAAM,SAAS,cAAc;AAC7B,gBAAM,IAAI,MAAM,iBAAiB;AAAA,QACrC;AAGA,YAAI,UAAU,KAAK,OAAO,YAAY;AAClC,gBAAM,KAAK,MAAM,OAAQ,UAAU,EAAE;AAAA,QACzC;AAAA,MACJ;AAAA,IACJ;AAEA,UAAM,aAAa,IAAI,MAAM,kCAAkC;AAAA,EACnE;AAAA;AAAA;AAAA;AAAA,EAKQ,MAAM,IAA2B;AACrC,WAAO,IAAI,QAAQ,aAAW,WAAW,SAAS,EAAE,CAAC;AAAA,EACzD;AACJ;AASO,SAAS,oBAAoB,QAA4C;AAC5E,SAAO,IAAI,cAAc,MAAM;AACnC;;;AC9lBA;AAAA,EACI;AAAA,EACA;AAAA,OACG;AACP;AAAA,EACI;AAAA,OACG;AACP,SAAS,kBAAkB;;;ACT3B,SAAS,UAAAC,eAAc;AAkBhB,SAAS,qBACd,OACA,WACA,QACQ;AACR,QAAM,cAAc,aAAa,KAAK;AACtC,QAAM,kBAAkB,aAAa,SAAS;AAC9C,QAAM,cAAcC,QAAO,aAAaA,QAAO,QAAQ,MAAM,GAAG,EAAE;AAElE,SAAOA,QAAO,OAAO;AAAA,IACnBA,QAAO,QAAQ,iBAAiB,CAAC;AAAA,IACjC;AAAA,IACA;AAAA,IACA;AAAA,EACF,CAAC;AACH;AAMO,SAAS,mBACd,OACA,QACA,aACA,WACQ;AACR,QAAM,cAAc,aAAa,KAAK;AACtC,QAAM,cAAcA,QAAO,aAAaA,QAAO,QAAQ,MAAM,GAAG,EAAE;AAClE,QAAM,mBAAmBA,QAAO,QAAQ,aAAa,CAAC;AACtD,QAAM,kBAAkB,aAAa,SAAS;AAE9C,SAAOA,QAAO,OAAO;AAAA,IACnBA,QAAO,QAAQ,eAAe,CAAC;AAAA,IAC/B;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF,CAAC;AACH;AAMO,SAAS,oBACd,QACA,OACA,MACQ;AACR,QAAM,eAAe,aAAa,MAAM;AACxC,QAAM,aAAaA,QAAO,aAAaA,QAAO,QAAQ,KAAK,GAAG,EAAE;AAChE,QAAM,YAAYA,QAAO,SAAS,IAAI;AACtC,QAAM,kBAAkBA,QAAO,QAAQ,UAAU,QAAQ,CAAC;AAE1D,SAAOA,QAAO,OAAO;AAAA,IACnBA,QAAO,QAAQ,gBAAgB,CAAC;AAAA,IAChC;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF,CAAC;AACH;AAMO,SAAS,mBAAmB,YAAoB,YAA4B;AACjF,SAAOA,QAAO,OAAO;AAAA,IACnBA,QAAO,QAAQ,eAAe,CAAC;AAAA,IAC/BA,QAAO,QAAQ,YAAY,CAAC;AAAA,IAC5B;AAAA,EACF,CAAC;AACH;AAUO,SAAS,qBACd,aACA,aACA,OACA,YACA,YACA,eACQ;AACR,SAAOA,QAAO,OAAO;AAAA,IACnBA,QAAO,QAAQ,kBAAkB,CAAC;AAAA,IAClC;AAAA,IACAA,QAAO,QAAQ,aAAa,CAAC;AAAA,IAC7BA,QAAO,aAAaA,QAAO,QAAQ,KAAK,GAAG,EAAE;AAAA,IAC7CA,QAAO,aAAaA,QAAO,QAAQ,UAAU,GAAG,EAAE;AAAA,IAClDA,QAAO,aAAaA,QAAO,QAAQ,UAAU,GAAG,EAAE;AAAA,IAClD;AAAA,EACF,CAAC;AACH;AASO,SAAS,oBAAoB,SAAgC;AAClE,QAAM,OAAOA,QAAO,SAAS,OAAO;AACpC,QAAM,aAAa,KAAK,CAAC;AAEzB,UAAQ,YAAY;AAAA,IAClB,KAAK;AACH,aAAO,qBAAqB,OAAO;AAAA,IACrC,KAAK;AACH,aAAO,mBAAmB,OAAO;AAAA,IACnC,KAAK;AACH,aAAO,oBAAoB,OAAO;AAAA,IACpC;AACE,aAAO,EAAE,MAAM,WAAW,UAAU,IAAI,KAAK,QAAQ;AAAA,EACzD;AACF;AAKO,SAAS,qBAAqB,SAAiC;AACpE,QAAM,OAAOA,QAAO,SAAS,OAAO;AAEpC,QAAM,aAAa,KAAK,MAAM,GAAG,EAAE;AACnC,QAAM,iBAAiB,KAAK,MAAM,IAAI,EAAE;AACxC,QAAM,cAAc,KAAK,MAAM,IAAI,EAAE;AAErC,SAAO;AAAA,IACL,MAAM;AAAA,IACN,OAAO,cAAcA,QAAO,QAAQ,UAAU,CAAC;AAAA,IAC/C,WAAW,cAAcA,QAAO,QAAQ,cAAc,CAAC;AAAA,IACvD,QAAQ,OAAOA,QAAO,QAAQ,WAAW,CAAC;AAAA,EAC5C;AACF;AAKO,SAAS,mBAAmB,SAA+B;AAChE,QAAM,OAAOA,QAAO,SAAS,OAAO;AAEpC,QAAM,aAAa,KAAK,MAAM,GAAG,EAAE;AACnC,QAAM,cAAc,KAAK,MAAM,IAAI,EAAE;AACrC,QAAM,mBAAmB,KAAK,EAAE;AAChC,QAAM,mBAAmB,KAAK,EAAE;AAChC,QAAM,iBAAiB,KAAK,MAAM,IAAI,EAAE;AAExC,QAAM,eAAgB,oBAAoB,MAAM,KAAM,oBAAoB;AAE1E,SAAO;AAAA,IACL,MAAM;AAAA,IACN,OAAO,cAAcA,QAAO,QAAQ,UAAU,CAAC;AAAA,IAC/C,QAAQ,OAAOA,QAAO,QAAQ,WAAW,CAAC;AAAA,IAC1C;AAAA,IACA,WAAWA,QAAO,QAAQ,cAAc;AAAA,EAC1C;AACF;AAKO,SAAS,oBAAoB,SAAgC;AAClE,QAAM,OAAOA,QAAO,SAAS,OAAO;AAEpC,QAAM,cAAc,KAAK,MAAM,GAAG,EAAE;AACpC,QAAM,aAAa,KAAK,MAAM,IAAI,EAAE;AACpC,QAAM,kBAAkB,KAAK,EAAE;AAC/B,QAAM,kBAAkB,KAAK,EAAE;AAC/B,QAAM,cAAe,mBAAmB,MAAM,KAAM,mBAAmB;AACvE,QAAM,WAAW,KAAK,MAAM,IAAI,KAAK,UAAU;AAE/C,SAAO;AAAA,IACL,MAAM;AAAA,IACN,QAAQ,cAAcA,QAAO,QAAQ,WAAW,CAAC;AAAA,IACjD,OAAO,OAAOA,QAAO,QAAQ,UAAU,CAAC;AAAA,IACxC,MAAMA,QAAO,QAAQ,QAAQ;AAAA,EAC/B;AACF;AAUO,SAAS,2BACd,QACA,WACQ;AACR,QAAM,cAAc,OAAO,MAAM,CAAC;AAClC,cAAY,iBAAiB,MAAM;AAEnC,QAAM,iBAAiBA,QAAO,SAAS,SAAS;AAEhD,SAAOA,QAAO;AAAA,IACZ,OAAO,OAAO;AAAA,MACZ,OAAO,KAAK,CAAC,eAAe,CAAC;AAAA,MAC7B;AAAA,MACA,OAAO,KAAK,cAAc;AAAA,IAC5B,CAAC;AAAA,EACH;AACF;AAMO,SAAS,0BACd,QACA,WACQ;AACR,QAAM,cAAc,OAAO,MAAM,CAAC;AAClC,cAAY,iBAAiB,MAAM;AAEnC,QAAM,kBAAkB,aAAa,SAAS;AAE9C,SAAOA,QAAO;AAAA,IACZ,OAAO,OAAO;AAAA,MACZ,OAAO,KAAK,CAAC,eAAe,CAAC;AAAA,MAC7B;AAAA,MACA,OAAO,KAAKA,QAAO,SAAS,eAAe,CAAC;AAAA,IAC9C,CAAC;AAAA,EACH;AACF;AAMO,SAAS,wBACd,QACA,WACQ;AACR,QAAM,cAAc,OAAO,MAAM,CAAC;AAClC,cAAY,iBAAiB,MAAM;AAEnC,QAAM,kBAAkB,aAAa,SAAS;AAE9C,SAAOA,QAAO;AAAA,IACZ,OAAO,OAAO;AAAA,MACZ,OAAO,KAAK,CAAC,eAAe,CAAC;AAAA,MAC7B;AAAA,MACA,OAAO,KAAKA,QAAO,SAAS,eAAe,CAAC;AAAA,IAC9C,CAAC;AAAA,EACH;AACF;AAUO,SAAS,aAAa,SAAyB;AAEpD,MAAI,QAAQ,YAAY,MAAM,UAAU;AACtC,WAAO,OAAO,IAAI,OAAO,EAAE;AAAA,EAC7B;AAGA,MAAI,QAAQ,WAAW,IAAI,GAAG;AAC5B,UAAMC,OAAM,QAAQ,QAAQ,MAAM,EAAE;AAEpC,QAAI,CAAC,iBAAiB,KAAKA,IAAG,GAAG;AAC/B,YAAM,IAAI,MAAM,oBAAoB,OAAO,oCAAoC;AAAA,IACjF;AACA,WAAO,OAAOA,KAAI,SAAS,IAAI,GAAG;AAAA,EACpC;AAIA,QAAM,cAAc;AAGpB,aAAW,QAAQ,SAAS;AAC1B,QAAI,CAAC,YAAY,SAAS,IAAI,GAAG;AAC/B,YAAM,IAAI,MAAM,oBAAoB,OAAO,wCAAwC,IAAI,IAAI;AAAA,IAC7F;AAAA,EACF;AAGA,MAAI,QAAQ,OAAO,CAAC;AACpB,aAAW,QAAQ,SAAS;AAC1B,YAAQ,QAAQ,MAAM,OAAO,YAAY,QAAQ,IAAI,CAAC;AAAA,EACxD;AAGA,MAAI,MAAM,MAAM,SAAS,EAAE;AAE3B,MAAI,IAAI,SAAS,IAAI;AACnB,UAAM,IAAI,MAAM,oBAAoB,OAAO,yCAAyC;AAAA,EACtF;AAEA,SAAO,OAAO,IAAI,SAAS,IAAI,GAAG;AACpC;AAKO,SAAS,cAAc,OAAuB;AACnD,QAAM,QAAQ,MAAM,QAAQ,MAAM,EAAE;AACpC,SAAO,OAAO,MAAM,MAAM,GAAG;AAC/B;AAMO,SAAS,uBAAuB,eAA+B;AACpE,SAAO,aAAa,aAAa;AACnC;AASO,SAAS,aAAa,QAAgB,WAAW,IAAY;AAClE,QAAM,UAAU,OAAO,OAAO,QAAQ;AACtC,QAAM,QAAQ,SAAS;AACvB,QAAM,WAAW,SAAS;AAE1B,MAAI,aAAa,IAAI;AACnB,WAAO,MAAM,SAAS;AAAA,EACxB;AAEA,QAAM,cAAc,SAAS,SAAS,EAAE,SAAS,UAAU,GAAG;AAC9D,QAAM,kBAAkB,YAAY,QAAQ,OAAO,EAAE;AAErD,SAAO,GAAG,KAAK,IAAI,eAAe;AACpC;AAKO,SAAS,YAAY,WAAmB,WAAW,IAAY;AACpE,QAAM,QAAQ,UAAU,MAAM,GAAG;AACjC,QAAM,QAAQ,OAAO,MAAM,CAAC,KAAK,GAAG;AAEpC,MAAI,MAAM,WAAW,KAAK,CAAC,MAAM,CAAC,GAAG;AACnC,WAAO,QAAS,OAAO,OAAO,QAAQ;AAAA,EACxC;AAEA,QAAM,cAAc,MAAM,CAAC,EAAE,MAAM,GAAG,QAAQ,EAAE,OAAO,UAAU,GAAG;AACpE,QAAM,WAAW,OAAO,WAAW;AAEnC,SAAO,QAAS,OAAO,OAAO,QAAQ,IAAK;AAC7C;AASO,SAAS,gBAAwB;AACtC,QAAM,YAAY,OAAO,KAAK,IAAI,CAAC;AACnC,QAAM,SAAS,OAAO,KAAK,MAAM,KAAK,OAAO,IAAI,GAAO,CAAC;AACzD,SAAQ,aAAa,MAAO;AAC9B;AAKO,SAAS,kBACd,aACA,eACA,OACQ;AACR,SAAOD,QAAO;AAAA,IACZA,QAAO;AAAA,MACL,CAAC,UAAU,SAAS,SAAS;AAAA,MAC7B,CAAC,aAAa,eAAe,KAAK;AAAA,IACpC;AAAA,EACF;AACF;AAiBO,SAAS,yBACd,aACA,eACA,OACA,YACQ;AAGR,SAAOA,QAAO;AAAA,IACZ,CAAC,UAAU,SAAS,WAAW,QAAQ;AAAA,IACvC,CAAC,aAAa,eAAe,OAAO,UAAU;AAAA,EAChD;AACF;AAYO,SAAS,sBACd,aACA,eACA,OACA,YACY;AACZ,QAAM,SAAS,yBAAyB,aAAa,eAAe,OAAO,UAAU;AACrF,SAAOA,QAAO,SAAS,MAAM;AAC/B;AAKO,SAAS,eACd,aACA,aACA,OACA,eACY;AACZ,QAAM,UAAUA,QAAO;AAAA,IACrB,CAAC,WAAW,UAAU,WAAW,OAAO;AAAA,IACxC,CAAC,aAAa,aAAa,OAAO,aAAa;AAAA,EACjD;AACA,SAAOA,QAAO,SAASA,QAAO,UAAU,OAAO,CAAC;AAClD;;;AD3aO,IAAM,eAAN,MAA0C;AAAA,EACrC;AAAA,EACA;AAAA,EACA;AAAA,EAER,YAAY,QAA4B;AACpC,SAAK,SAAS;AAAA,MACV,MAAM,UAAU,OAAO,WAAW,SAAS;AAAA,MAC3C,SAAS,OAAO;AAAA,MAChB,iBAAiB,OAAO;AAAA,MACxB,QAAQ,OAAO;AAAA,MACf,aAAa,OAAO,YAAY,WAC1B,+CACA;AAAA,MACN,OAAO;AAAA,MACP,WAAW;AAAA,QACP,KAAK;AAAA;AAAA,QACL,oBAAoB,OAAO;AAAA,QAC3B,aAAa,OAAO;AAAA,MACxB;AAAA,IACJ;AAEA,SAAK,aAAa,IAAI;AAAA,MAClB,OAAO;AAAA,MACP,OAAO,cAAc;AAAA,IACzB;AACA,SAAK,YAAY,IAAI,UAAU,OAAO,SAAS;AAAA,EACnD;AAAA,EAEA,YAAyB;AACrB,WAAO,KAAK;AAAA,EAChB;AAAA,EAEA,MAAM,SAAS,aAAsC;AACjD,QAAI;AACA,YAAM,eAAe,KAAK,4BAA4B,WAAW;AACjE,YAAM,cAAc,MAAM,KAAK,WAAW,eAAe,IAAI,UAAU,YAAY,CAAC;AAEpF,UAAI,CAAC,eAAe,YAAY,KAAK,SAAS,IAAI;AAC9C,eAAO;AAAA,MACX;AAIA,YAAM,QAAQ,YAAY,KAAK,gBAAgB,CAAC;AAChD,aAAO;AAAA,IACX,SAAS,OAAO;AACZ,cAAQ,MAAM,wBAAwB,KAAK;AAC3C,aAAO;AAAA,IACX;AAAA,EACJ;AAAA,EAEA,MAAM,gBAAiC;AACnC,QAAI;AAIA,aAAO;AAAA,IACX,SAAS,OAAO;AACZ,cAAQ,MAAM,8BAA8B,KAAK;AACjD,aAAO;AAAA,IACX;AAAA,EACJ;AAAA,EAEA,MAAM,qBAAqB,QAAyC;AAChE,WAAO;AAAA,MACH,OAAO;AAAA,MACP,OAAO;AAAA,MACP,OAAO;AAAA,IACX;AAAA,EACJ;AAAA,EAEA,MAAM,oBAAoB,QAAwC;AAC9D,WAAO;AAAA,MACH,OAAO;AAAA,MACP,OAAO;AAAA,MACP,OAAO;AAAA,IACX;AAAA,EACJ;AAAA,EAEA,MAAM,mBAAmB,QAAuC;AAC5D,WAAO;AAAA,MACH,OAAO;AAAA,MACP,OAAO;AAAA,MACP,OAAO;AAAA,MACP,OAAO;AAAA,IACX;AAAA,EACJ;AAAA,EAEA,MAAM,SACF,WACA,YACA,YACA,aACA,eACA,OACA,QACuB;AACvB,SAAK;AACL,SAAK;AACL,SAAK;AACL,SAAK;AACL,SAAK;AACL,SAAK;AACL,SAAK;AACL,UAAM,IAAI;AAAA,MACN;AAAA,IAGJ;AAAA,EACJ;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,MAAM,gBACF,WACA,YACA,YACA,aACA,eACA,OACA,YACuB;AAEvB,UAAM,UAAU,KAAK,eAAe,YAAY,UAAU;AAG1D,UAAM,UAAU,KAAK,aAAa,SAAS,aAAa,eAAe,KAAK;AAG5E,UAAM,UAAU;AAAA,MACZ,aAAa;AAAA,MACb,GAAG,OAAO,UAAU,EAAE,SAAS,EAAE,EAAE,SAAS,IAAI,GAAG;AAAA,MACnD,GAAG,OAAO,UAAU,EAAE,SAAS,EAAE,EAAE,SAAS,IAAI,GAAG;AAAA,MACnD,YAAY,OAAO,WAAW,SAAS,EAAE,EAAE,SAAS,IAAI,GAAG;AAAA,MAC3D,YAAY,OAAO,WAAW,SAAS,EAAE,EAAE,SAAS,IAAI,GAAG;AAAA,MAC3D;AAAA,MACA;AAAA,MACA,OAAO,OAAO,KAAK;AAAA,IACvB;AAGA,UAAM,WAAW,MAAM,MAAM,GAAG,UAAU,kBAAkB;AAAA,MACxD,QAAQ;AAAA,MACR,SAAS;AAAA,QACL,gBAAgB;AAAA,MACpB;AAAA,MACA,MAAM,KAAK,UAAU,OAAO;AAAA,IAChC,CAAC;AAED,QAAI,CAAC,SAAS,IAAI;AACd,YAAM,QAAQ,MAAM,SAAS,KAAK,EAAE,MAAM,OAAO,EAAE,OAAO,SAAS,WAAW,EAAE;AAChF,YAAM,IAAI,MAAM,8BAA8B,MAAM,SAAS,SAAS,UAAU,EAAE;AAAA,IACtF;AAEA,UAAM,SAAS,MAAM,SAAS,KAAK;AAEnC,QAAI,CAAC,OAAO,SAAS;AACjB,YAAM,IAAI,MAAM,8BAA8B,OAAO,KAAK,EAAE;AAAA,IAChE;AAEA,WAAO;AAAA,MACH,iBAAiB,OAAO;AAAA,MACxB,UAAU,OAAO,OAAO,YAAY,GAAG;AAAA,MACvC,aAAa;AAAA,MACb;AAAA,IACJ;AAAA,EACJ;AAAA,EAEA,MAAM,gBAAgB,aAA6C;AAC/D,QAAI;AACA,YAAM,eAAe,KAAK,4BAA4B,WAAW;AACjE,YAAM,cAAc,MAAM,KAAK,WAAW,eAAe,IAAI,UAAU,YAAY,CAAC;AAEpF,UAAI,CAAC,aAAa;AACd,eAAO;AAAA,MACX;AAEA,aAAO;AAAA,IACX,SAAS,OAAO;AACZ,cAAQ,MAAM,gCAAgC,KAAK;AACnD,aAAO;AAAA,IACX;AAAA,EACJ;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,oBAAoB,aAA6B;AAC7C,WAAO,KAAK,4BAA4B,WAAW;AAAA,EACvD;AAAA,EAEQ,4BAA4B,aAA6B;AAC7D,UAAM,oBAAoB,OAAO,KAAK,YAAY,QAAQ,MAAM,EAAE,GAAG,KAAK;AAC1E,UAAM,CAAC,QAAQ,IAAI,UAAU;AAAA,MACzB,CAAC,OAAO,KAAK,OAAO,GAAG,iBAAiB;AAAA,MACxC,KAAK;AAAA,IACT;AACA,WAAO,SAAS,SAAS;AAAA,EAC7B;AAAA,EAEA,MAAM,YAAY,aAAuC;AACrD,UAAM,UAAU,MAAM,KAAK,gBAAgB,WAAW;AACtD,WAAO,YAAY;AAAA,EACvB;AAAA,EAEA,MAAM,YAAY,aAAqB,QAA2C;AAC9E,SAAK;AACL,SAAK;AACL,UAAM,IAAI;AAAA,MACN;AAAA,IAEJ;AAAA,EACJ;AAAA,EAEA,MAAM,qBACF,aACA,mBACA,QAC4B;AAC5B,SAAK;AACL,SAAK;AACL,SAAK;AACL,UAAM,IAAI;AAAA,MACN;AAAA,IAEJ;AAAA,EACJ;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,MAAM,sBACF,aACA,YAC4B;AAC5B,UAAM,WAAW,MAAM,MAAM,GAAG,UAAU,wBAAwB;AAAA,MAC9D,QAAQ;AAAA,MACR,SAAS;AAAA,QACL,gBAAgB;AAAA,MACpB;AAAA,MACA,MAAM,KAAK,UAAU;AAAA,QACjB;AAAA,QACA,SAAS,KAAK,OAAO;AAAA,MACzB,CAAC;AAAA,IACL,CAAC;AAED,UAAM,SAAS,MAAM,SAAS,KAAK;AAEnC,QAAI,CAAC,SAAS,MAAM,CAAC,OAAO,SAAS;AACjC,YAAM,IAAI,MAAM,OAAO,SAAS,oCAAoC;AAAA,IACxE;AAEA,WAAO;AAAA,MACH,SAAS,OAAO;AAAA,MAChB,iBAAiB,OAAO,mBAAmB;AAAA,MAC3C,aAAa;AAAA;AAAA,MACb,SAAS;AAAA;AAAA,MACT,gBAAgB,CAAC,OAAO;AAAA,MACxB,aAAa;AAAA,IACjB;AAAA,EACJ;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,mBACF,aACA,YACkD;AAClD,UAAM,WAAW,MAAM;AAAA,MACnB,GAAG,UAAU,wBAAwB,WAAW,YAAY,KAAK,OAAO,eAAe;AAAA,IAC3F;AAEA,QAAI,CAAC,SAAS,IAAI;AACd,YAAM,IAAI,MAAM,uCAAuC;AAAA,IAC3D;AAEA,UAAM,SAAS,MAAM,SAAS,KAAK;AACnC,WAAO;AAAA,MACH,cAAc,OAAO;AAAA,MACrB,QAAQ,OAAO;AAAA,IACnB;AAAA,EACJ;AAAA,EAEA,MAAM,yBAAyB,aAAsC;AACjE,SAAK;AAGL,WAAO;AAAA,EACX;AAAA,EAEA,oBAAwC;AAEpC,WAAO;AAAA,EACX;AAAA,EAEA,2BAA+C;AAE3C,WAAO;AAAA,EACX;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASA,MAAM,iBAAiB,SAAkC;AACrD,UAAM,UAAU,MAAM,KAAK,WAAW,WAAW,IAAI,UAAU,OAAO,CAAC;AACvE,WAAO,OAAO,OAAO;AAAA,EACzB;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,gBAAgB,cAAsB,cAAuC;AAC/E,QAAI;AACA,YAAM,OAAO,IAAI,UAAU,YAAY;AACvC,YAAM,QAAQ,IAAI,UAAU,YAAY;AACxC,YAAM,MAAM,8BAA8B,MAAM,KAAK;AAErD,YAAM,UAAU,MAAM,KAAK,WAAW,uBAAuB,GAAG;AAChE,aAAO,OAAO,QAAQ,MAAM,MAAM;AAAA,IACtC,SAAS,OAAO;AACZ,cAAQ,MAAM,gCAAgC,KAAK;AACnD,aAAO;AAAA,IACX;AAAA,EACJ;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAUQ,eAAe,YAAoB,YAA4B;AAGnE,UAAM,UAAU,OAAO,MAAM,EAAE;AAC/B,UAAM,UAAU,OAAO,MAAM,EAAE;AAG/B,UAAM,OAAO,WAAW,SAAS,EAAE,EAAE,SAAS,IAAI,GAAG;AACrD,UAAM,OAAO,WAAW,SAAS,EAAE,EAAE,SAAS,IAAI,GAAG;AAErD,WAAO,KAAK,MAAM,KAAK,EAAE,KAAK,OAAO;AACrC,WAAO,KAAK,MAAM,KAAK,EAAE,KAAK,OAAO;AAIrC,UAAM,WAAW,OAAO,OAAO,CAAC,SAAS,OAAO,CAAC;AACjD,UAAM,OAAO,WAAW,QAAQ,EAAE,OAAO,QAAQ,EAAE,OAAO;AAE1D,WAAO,OAAO,KAAK,SAAS,KAAK;AAAA,EACrC;AAAA;AAAA;AAAA;AAAA,EAKQ,aACJ,SACA,aACA,eACA,OACM;AAEN,UAAM,gBAAgB,OAAO,KAAK,QAAQ,QAAQ,MAAM,EAAE,GAAG,KAAK;AAClE,UAAM,oBAAoB,OAAO,MAAM,CAAC;AACxC,sBAAkB,cAAc,WAAW;AAC3C,UAAM,gBAAgB,OAAO,KAAK,cAAc,QAAQ,MAAM,EAAE,GAAG,KAAK;AACxE,UAAM,cAAc,OAAO,MAAM,EAAE;AACnC,UAAM,WAAW,MAAM,SAAS,EAAE,EAAE,SAAS,IAAI,GAAG;AACpD,WAAO,KAAK,UAAU,KAAK,EAAE,KAAK,WAAW;AAE7C,UAAM,WAAW,OAAO,OAAO;AAAA,MAC3B;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,IACJ,CAAC;AAED,UAAM,OAAO,WAAW,QAAQ,EAAE,OAAO,QAAQ,EAAE,OAAO;AAC1D,WAAO,OAAO,KAAK,SAAS,KAAK;AAAA,EACrC;AAAA;AAAA;AAAA;AAAA,EAKA,gBAA4B;AACxB,WAAO,KAAK;AAAA,EAChB;AAAA;AAAA;AAAA;AAAA,EAKA,eAA0B;AACtB,WAAO,KAAK;AAAA,EAChB;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,UAA2B;AAC7B,WAAO,MAAM,KAAK,WAAW,QAAQ;AAAA,EACzC;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,eAAe,WAAmB,YAAwC;AAC5E,WAAO,MAAM,KAAK,WAAW,eAAe,WAAW;AAAA,MACnD,YAAY,cAAc;AAAA,MAC1B,gCAAgC;AAAA,IACpC,CAAC;AAAA,EACL;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EA0BA,MAAM,mBAAmB,SAAmC;AACxD,QAAI;AAEA,YAAM,gBAAgB,OAAO,KAAK,QAAQ,QAAQ,MAAM,EAAE,GAAG,KAAK;AAClE,YAAM,CAAC,YAAY,IAAI,UAAU;AAAA,QAC7B,CAAC,OAAO,KAAK,YAAY,GAAG,aAAa;AAAA,QACzC,KAAK;AAAA,MACT;AAEA,YAAM,cAAc,MAAM,KAAK,WAAW,eAAe,YAAY;AACrE,UAAI,CAAC,eAAe,YAAY,KAAK,SAAS,GAAG;AAC7C,eAAO;AAAA,MACX;AAGA,aAAO,YAAY,KAAK,CAAC,MAAM;AAAA,IACnC,SAAS,OAAO;AACZ,cAAQ,MAAM,sCAAsC,KAAK;AACzD,aAAO;AAAA,IACX;AAAA,EACJ;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,MAAM,cAAc,cAAuC;AACvD,QAAI;AACA,YAAM,cAAc,MAAM,KAAK,WAAW,eAAe,IAAI,UAAU,YAAY,CAAC;AACpF,UAAI,CAAC,eAAe,YAAY,KAAK,SAAS,IAAI;AAC9C,cAAM,IAAI,MAAM,iBAAiB;AAAA,MACrC;AAGA,YAAM,eAAe,YAAY,KAAK,MAAM,GAAG,EAAE;AACjD,aAAO,OAAO,aAAa,SAAS,KAAK;AAAA,IAC7C,SAAS,OAAO;AACZ,cAAQ,MAAM,8BAA8B,KAAK;AACjD,YAAM;AAAA,IACV;AAAA,EACJ;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,MAAM,qBAAqB,cAAyC;AAChE,QAAI;AACA,YAAM,cAAc,MAAM,KAAK,WAAW,eAAe,IAAI,UAAU,YAAY,CAAC;AACpF,UAAI,CAAC,eAAe,YAAY,KAAK,SAAS,KAAK;AAC/C,cAAM,IAAI,MAAM,iBAAiB;AAAA,MACrC;AAcA,YAAM,cAAc,YAAY,KAAK,EAAE;AACvC,YAAM,UAAoB,CAAC;AAE3B,eAAS,IAAI,GAAG,IAAI,aAAa,KAAK;AAClC,cAAM,SAAS,KAAM,IAAI;AACzB,cAAM,UAAU,YAAY,KAAK,MAAM,QAAQ,SAAS,EAAE;AAC1D,gBAAQ,KAAK,OAAO,QAAQ,SAAS,KAAK,CAAC;AAAA,MAC/C;AAEA,aAAO;AAAA,IACX,SAAS,OAAO;AACZ,cAAQ,MAAM,qCAAqC,KAAK;AACxD,YAAM;AAAA,IACV;AAAA,EACJ;AACJ;;;AElkBA,SAAS,eAAe,gBAAuB;AAC/C,SAAS,gBAAgB;AAqClB,IAAM,cAAN,MAAyC;AAAA,EACpC;AAAA,EACA;AAAA,EACA;AAAA,EAER,YAAY,QAA2B;AACnC,SAAK,SAAS;AAAA,MACV,MAAM,SAAS,OAAO,WAAW,SAAS;AAAA,MAC1C,SAAS,OAAO;AAAA,MAChB,iBAAiB,OAAO;AAAA,MACxB,QAAQ,OAAO;AAAA,MACf,aAAa,OAAO,YAAY,YAC1B,mDACA;AAAA,MACN,OAAO;AAAA,MACP,WAAW;AAAA,QACP,KAAK;AAAA;AAAA,QACL,oBAAoB,OAAO;AAAA,QAC3B,aAAa,OAAO;AAAA,MACxB;AAAA,IACJ;AAEA,SAAK,SAAS,IAAI,SAAS,OAAO,MAAM;AACxC,SAAK,gBAAgB,OAAO;AAAA,EAChC;AAAA,EAEA,YAAyB;AACrB,WAAO,KAAK;AAAA,EAChB;AAAA,EAEA,MAAM,SAAS,aAAsC;AACjD,QAAI;AACA,YAAM,eAAe,KAAK,4BAA4B,WAAW;AAGjE,YAAM,WAAW,MAAM,KAAK,OAAO;AAAA,QAC/B;AAAA,QACA,GAAG,KAAK,aAAa;AAAA,MACzB;AAEA,UAAI,YAAY,SAAS,MAAM;AAC3B,cAAM,OAAO,SAAS;AACtB,eAAO,OAAO,KAAK,SAAS,CAAC;AAAA,MACjC;AAEA,aAAO;AAAA,IACX,SAAS,OAAO;AACZ,cAAQ,MAAM,wBAAwB,KAAK;AAC3C,aAAO;AAAA,IACX;AAAA,EACJ;AAAA,EAEA,MAAM,gBAAiC;AACnC,QAAI;AAIA,aAAO;AAAA,IACX,SAAS,OAAO;AACZ,cAAQ,MAAM,8BAA8B,KAAK;AACjD,aAAO;AAAA,IACX;AAAA,EACJ;AAAA,EAEA,MAAM,qBAAqB,QAAyC;AAChE,WAAO;AAAA,MACH,OAAO;AAAA,MACP,OAAO;AAAA,MACP,OAAO;AAAA,IACX;AAAA,EACJ;AAAA,EAEA,MAAM,oBAAoB,QAAwC;AAC9D,WAAO;AAAA,MACH,OAAO;AAAA,MACP,OAAO;AAAA,MACP,OAAO;AAAA,IACX;AAAA,EACJ;AAAA,EAEA,MAAM,mBAAmB,QAAuC;AAC5D,WAAO;AAAA,MACH,OAAO;AAAA,MACP,OAAO;AAAA,MACP,OAAO;AAAA,MACP,OAAO;AAAA,IACX;AAAA,EACJ;AAAA,EAEA,MAAM,SACF,WACA,YACA,YACA,aACA,eACA,OACA,QACuB;AACvB,SAAK;AACL,SAAK;AACL,SAAK;AACL,SAAK;AACL,SAAK;AACL,SAAK;AACL,SAAK;AACL,UAAM,IAAI;AAAA,MACN;AAAA,IAGJ;AAAA,EACJ;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,MAAM,gBACF,WACA,YACA,YACA,aACA,eACA,OACA,YACuB;AAEvB,UAAM,UAAU,KAAK,eAAe,YAAY,UAAU;AAG1D,UAAM,UAAU,KAAK,aAAa,SAAS,aAAa,eAAe,KAAK;AAG5E,UAAM,UAAU;AAAA,MACZ,aAAa;AAAA,MACb,GAAG,OAAO,UAAU,EAAE,SAAS,EAAE,EAAE,SAAS,IAAI,GAAG;AAAA,MACnD,GAAG,OAAO,UAAU,EAAE,SAAS,EAAE,EAAE,SAAS,IAAI,GAAG;AAAA,MACnD,YAAY,OAAO,WAAW,SAAS,EAAE,EAAE,SAAS,IAAI,GAAG;AAAA,MAC3D,YAAY,OAAO,WAAW,SAAS,EAAE,EAAE,SAAS,IAAI,GAAG;AAAA,MAC3D;AAAA,MACA;AAAA,MACA,OAAO,OAAO,KAAK;AAAA,IACvB;AAGA,UAAM,WAAW,MAAM,MAAM,GAAG,UAAU,kBAAkB;AAAA,MACxD,QAAQ;AAAA,MACR,SAAS;AAAA,QACL,gBAAgB;AAAA,MACpB;AAAA,MACA,MAAM,KAAK,UAAU,OAAO;AAAA,IAChC,CAAC;AAED,QAAI,CAAC,SAAS,IAAI;AACd,YAAM,QAAQ,MAAM,SAAS,KAAK,EAAE,MAAM,OAAO,EAAE,OAAO,SAAS,WAAW,EAAE;AAChF,YAAM,IAAI,MAAM,8BAA8B,MAAM,SAAS,SAAS,UAAU,EAAE;AAAA,IACtF;AAEA,UAAM,SAAS,MAAM,SAAS,KAAK;AAEnC,QAAI,CAAC,OAAO,SAAS;AACjB,YAAM,IAAI,MAAM,8BAA8B,OAAO,KAAK,EAAE;AAAA,IAChE;AAEA,WAAO;AAAA,MACH,iBAAiB,OAAO;AAAA,MACxB,UAAU,OAAO,OAAO,YAAY,GAAG;AAAA,MACvC,aAAa;AAAA,MACb;AAAA,IACJ;AAAA,EACJ;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,MAAM,gBAAgB,aAA6C;AAC/D,QAAI;AAIA,YAAM,oBAAoB,OAAO,YAAY,QAAQ,MAAM,EAAE,EAAE,SAAS,IAAI,GAAG;AAE/E,YAAM,UAAU;AAAA,QACZ,UAAU,GAAG,KAAK,aAAa;AAAA,QAC/B,gBAAgB,CAAC;AAAA,QACjB,WAAW,CAAC,iBAAiB;AAAA;AAAA,MACjC;AAEA,YAAM,WAAW,MAAM,KAAK,OAAO,KAAK,OAAO;AAE/C,UAAI,YAAY,SAAS,SAAS,GAAG;AACjC,cAAM,eAAe,SAAS,CAAC;AAC/B,eAAO;AAAA,MACX;AAEA,aAAO;AAAA,IACX,SAAS,OAAY;AAEjB,UAAI,OAAO,SAAS,SAAS,mBAAmB,KAC5C,OAAO,SAAS,SAAS,cAAc,KACvC,OAAO,WAAW,KAAK;AACvB,eAAO;AAAA,MACX;AACA,cAAQ,MAAM,8CAA8C,KAAK;AACjE,aAAO;AAAA,IACX;AAAA,EACJ;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,oBAAoB,aAA6B;AAC7C,YAAQ;AAAA,MACJ;AAAA,IAEJ;AACA,WAAO,KAAK,4BAA4B,WAAW;AAAA,EACvD;AAAA,EAEQ,4BAA4B,aAA6B;AAO7D,UAAM,gBAAgB,KAAK,WAAW,KAAK,cAAc,QAAQ,MAAM,EAAE,CAAC;AAC1E,UAAM,OAAO,KAAK,WAAW,YAAY,QAAQ,MAAM,EAAE,CAAC;AAC1D,UAAM,SAAS,IAAI,WAAW,CAAC,GAAI,CAAC;AAEpC,UAAM,WAAW,IAAI,WAAW,CAAC,GAAG,eAAe,GAAG,MAAM,GAAG,MAAM,CAAC;AACtE,UAAM,OAAO,SAAS,QAAQ;AAE9B,WAAO,OAAO;AAAA,EAClB;AAAA;AAAA;AAAA;AAAA,EAKQ,WAAW,KAAyB;AACxC,UAAM,QAAQ,IAAI,WAAW,IAAI,SAAS,CAAC;AAC3C,aAAS,IAAI,GAAG,IAAI,IAAI,QAAQ,KAAK,GAAG;AACpC,YAAM,IAAI,CAAC,IAAI,SAAS,IAAI,OAAO,GAAG,CAAC,GAAG,EAAE;AAAA,IAChD;AACA,WAAO;AAAA,EACX;AAAA,EAEA,MAAM,YAAY,aAAuC;AACrD,UAAM,UAAU,MAAM,KAAK,gBAAgB,WAAW;AACtD,WAAO,YAAY;AAAA,EACvB;AAAA,EAEA,MAAM,YAAY,aAAqB,QAA2C;AAC9E,SAAK;AACL,SAAK;AACL,UAAM,IAAI;AAAA,MACN;AAAA,IAEJ;AAAA,EACJ;AAAA,EAEA,MAAM,qBACF,aACA,mBACA,QAC4B;AAC5B,SAAK;AACL,SAAK;AACL,SAAK;AACL,UAAM,IAAI;AAAA,MACN;AAAA,IAEJ;AAAA,EACJ;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,MAAM,sBACF,aACA,YAC4B;AAC5B,UAAM,WAAW,MAAM,MAAM,GAAG,UAAU,uBAAuB;AAAA,MAC7D,QAAQ;AAAA,MACR,SAAS;AAAA,QACL,gBAAgB;AAAA,MACpB;AAAA,MACA,MAAM,KAAK,UAAU;AAAA,QACjB;AAAA,QACA,SAAS,KAAK,OAAO;AAAA,MACzB,CAAC;AAAA,IACL,CAAC;AAED,UAAM,SAAS,MAAM,SAAS,KAAK;AAEnC,QAAI,CAAC,SAAS,MAAM,CAAC,OAAO,SAAS;AACjC,YAAM,IAAI,MAAM,OAAO,SAAS,oCAAoC;AAAA,IACxE;AAEA,WAAO;AAAA,MACH,SAAS,OAAO;AAAA,MAChB,iBAAiB,OAAO,mBAAmB;AAAA,MAC3C,aAAa;AAAA,MACb,SAAS;AAAA,MACT,gBAAgB,OAAO,iBAAiB;AAAA,MACxC,aAAa;AAAA,IACjB;AAAA,EACJ;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,mBACF,aACA,YACkD;AAClD,UAAM,WAAW,MAAM;AAAA,MACnB,GAAG,UAAU,uBAAuB,WAAW,YAAY,KAAK,OAAO,eAAe;AAAA,IAC1F;AAEA,QAAI,CAAC,SAAS,IAAI;AACd,YAAM,IAAI,MAAM,uCAAuC;AAAA,IAC3D;AAEA,UAAM,SAAS,MAAM,SAAS,KAAK;AACnC,WAAO;AAAA,MACH,cAAc,OAAO;AAAA,MACrB,QAAQ,OAAO;AAAA,IACnB;AAAA,EACJ;AAAA,EAEA,MAAM,yBAAyB,aAAsC;AACjE,SAAK;AAGL,WAAO;AAAA,EACX;AAAA,EAEA,oBAAwC;AAEpC,WAAO;AAAA,EACX;AAAA,EAEA,2BAA+C;AAE3C,WAAO;AAAA,EACX;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASA,MAAM,iBAAiB,SAAkC;AACrD,QAAI;AACA,YAAM,WAAW,MAAM,KAAK,OAAO;AAAA,QAC/B;AAAA,QACA;AAAA,MACJ;AAEA,UAAI,YAAY,SAAS,MAAM;AAC3B,cAAM,OAAO,SAAS;AACtB,eAAO,OAAO,KAAK,MAAM,SAAS,CAAC;AAAA,MACvC;AAEA,aAAO;AAAA,IACX,SAAS,OAAO;AACZ,cAAQ,MAAM,iCAAiC,KAAK;AACpD,aAAO;AAAA,IACX;AAAA,EACJ;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,gBAAgB,cAAsB,cAAuC;AAC/E,QAAI;AAEA,YAAM,WAAW,aAAa,SAAS,IAAI,IACrC,eACA,GAAG,YAAY;AAErB,YAAM,WAAW,MAAM,KAAK,OAAO;AAAA,QAC/B;AAAA,QACA,wBAAwB,QAAQ;AAAA,MACpC;AAEA,UAAI,YAAY,SAAS,MAAM;AAC3B,cAAM,OAAO,SAAS;AACtB,eAAO,OAAO,KAAK,MAAM,SAAS,CAAC;AAAA,MACvC;AAEA,aAAO;AAAA,IACX,SAAS,OAAO;AAEZ,UAAI;AAGA,gBAAQ,KAAK,4CAA4C;AACzD,eAAO;AAAA,MACX,SAAS,SAAS;AACd,gBAAQ,MAAM,gCAAgC,KAAK;AACnD,eAAO;AAAA,MACX;AAAA,IACJ;AAAA,EACJ;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAUQ,eAAe,YAAoB,YAA4B;AAEnE,UAAM,OAAO,WAAW,SAAS,EAAE,EAAE,SAAS,IAAI,GAAG;AACrD,UAAM,OAAO,WAAW,SAAS,EAAE,EAAE,SAAS,IAAI,GAAG;AAErD,UAAM,SAAS,KAAK,WAAW,IAAI;AACnC,UAAM,SAAS,KAAK,WAAW,IAAI;AAInC,UAAM,WAAW,IAAI,WAAW,CAAC,GAAG,QAAQ,GAAG,MAAM,CAAC;AACtD,UAAM,OAAO,SAAS,QAAQ;AAE9B,WAAO,OAAO;AAAA,EAClB;AAAA;AAAA;AAAA;AAAA,EAKQ,aACJ,SACA,aACA,eACA,OACM;AACN,UAAM,eAAe,KAAK,WAAW,QAAQ,QAAQ,MAAM,EAAE,CAAC;AAC9D,UAAM,mBAAmB,IAAI,WAAW,CAAC;AACzC,qBAAiB,CAAC,IAAK,eAAe,IAAK;AAC3C,qBAAiB,CAAC,IAAI,cAAc;AACpC,UAAM,eAAe,KAAK,WAAW,cAAc,QAAQ,MAAM,EAAE,CAAC;AACpE,UAAM,WAAW,MAAM,SAAS,EAAE,EAAE,SAAS,IAAI,GAAG;AACpD,UAAM,aAAa,KAAK,WAAW,QAAQ;AAE3C,UAAM,WAAW,IAAI,WAAW;AAAA,MAC5B,GAAG;AAAA,MACH,GAAG;AAAA,MACH,GAAG;AAAA,MACH,GAAG;AAAA,IACP,CAAC;AAED,UAAM,OAAO,SAAS,QAAQ;AAC9B,WAAO,OAAO;AAAA,EAClB;AAAA;AAAA;AAAA;AAAA,EAKA,YAAsB;AAClB,WAAO,KAAK;AAAA,EAChB;AAAA;AAAA;AAAA;AAAA,EAKA,mBAA2B;AACvB,WAAO,KAAK;AAAA,EAChB;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,mBAAoC;AACtC,UAAM,aAAa,MAAM,KAAK,OAAO,cAAc;AACnD,WAAO,OAAO,WAAW,cAAc;AAAA,EAC3C;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,eAAe,QAA4C;AAC7D,WAAO,MAAM,KAAK,OAAO,qBAAqB,MAAM;AAAA,EACxD;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,mBAAmB,QAAgB,cAAsB,IAAgC;AAC3F,WAAO,MAAM,KAAK,OAAO,6BAA6B,QAAQ;AAAA,MAC1D;AAAA,MACA,cAAc;AAAA,IAClB,CAAC;AAAA,EACL;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAoBA,MAAM,iBAAiB,cAIb;AACN,QAAI;AACA,YAAM,eAAe,KAAK,4BAA4B,YAAY;AAElE,YAAM,WAAW,MAAM,KAAK,OAAO;AAAA,QAC/B;AAAA,QACA,GAAG,KAAK,aAAa;AAAA,MACzB;AAEA,UAAI,CAAC,YAAY,CAAC,SAAS,MAAM;AAC7B,eAAO;AAAA,MACX;AAEA,YAAM,OAAO,SAAS;AACtB,aAAO;AAAA,QACH,cAAc,KAAK,kBAAkB;AAAA,QACrC,mBAAmB,KAAK,sBAAsB,CAAC;AAAA,QAC/C,OAAO,OAAO,KAAK,SAAS,CAAC;AAAA,MACjC;AAAA,IACJ,SAAS,OAAO;AACZ,cAAQ,MAAM,iCAAiC,KAAK;AACpD,aAAO;AAAA,IACX;AAAA,EACJ;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,MAAM,qBAAqB,cAAyC;AAChE,UAAM,gBAAgB,MAAM,KAAK,iBAAiB,YAAY;AAC9D,WAAO,eAAe,qBAAqB,CAAC;AAAA,EAChD;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,MAAM,eAAe,SAAmC;AACpD,QAAI;AACA,YAAM,WAAW,MAAM,KAAK,OAAO;AAAA,QAC/B,KAAK;AAAA,QACL,GAAG,KAAK,aAAa;AAAA,MACzB;AAEA,UAAI,CAAC,YAAY,CAAC,SAAS,MAAM;AAC7B,eAAO;AAAA,MACX;AAEA,YAAM,OAAO,SAAS;AACtB,YAAM,gBAAgB,KAAK,aAAa,CAAC;AAGzC,YAAM,iBAAiB,QAAQ,YAAY,EAAE,QAAQ,MAAM,EAAE;AAC7D,aAAO,cAAc;AAAA,QAAK,CAAC,SACvB,KAAK,YAAY,EAAE,QAAQ,MAAM,EAAE,MAAM;AAAA,MAC7C;AAAA,IACJ,SAAS,OAAO;AACZ,cAAQ,MAAM,8BAA8B,KAAK;AACjD,aAAO;AAAA,IACX;AAAA,EACJ;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,MAAM,mBAAqC;AACvC,QAAI;AACA,YAAM,WAAW,MAAM,KAAK,OAAO;AAAA,QAC/B,KAAK;AAAA,QACL,GAAG,KAAK,aAAa;AAAA,MACzB;AAEA,UAAI,CAAC,YAAY,CAAC,SAAS,MAAM;AAC7B,eAAO;AAAA,MACX;AAEA,YAAM,OAAO,SAAS;AACtB,aAAO,KAAK,WAAW;AAAA,IAC3B,SAAS,OAAO;AACZ,cAAQ,MAAM,gCAAgC,KAAK;AACnD,aAAO;AAAA,IACX;AAAA,EACJ;AACJ;;;ACxoBA,SAAS,aAAa,uBAAuB;AAC7C,SAAS,cAAAE,mBAAkB;AAoCpB,IAAM,YAAN,MAAuC;AAAA,EAClC;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EAER,YAAY,QAAyB;AACjC,SAAK,SAAS;AAAA,MACV,MAAM,OAAO,OAAO,WAAW,SAAS;AAAA,MACxC,SAAS;AAAA,MACT,iBAAiB,OAAO;AAAA,MACxB,QAAQ,OAAO;AAAA,MACf,aAAa,OAAO,YAAY,YAC1B,gCACA,OAAO,YAAY,WACf,+BACA;AAAA,MACV,OAAO;AAAA,MACP,WAAW;AAAA,QACP,KAAK,OAAO;AAAA,QACZ,oBAAoB,OAAO;AAAA,QAC3B,aAAa,OAAO;AAAA,MACxB;AAAA,IACJ;AAEA,SAAK,SAAS,IAAI,gBAAgB,EAAE,KAAK,OAAO,OAAO,CAAC;AACxD,SAAK,YAAY,OAAO;AACxB,SAAK,YAAY,OAAO;AACxB,SAAK,qBAAqB,OAAO;AAAA,EACrC;AAAA,EAEA,YAAyB;AACrB,WAAO,KAAK;AAAA,EAChB;AAAA,EAEA,MAAM,SAAS,cAAuC;AAElD,WAAO;AAAA,EACX;AAAA,EAEA,MAAM,gBAAiC;AAEnC,WAAO;AAAA,EACX;AAAA,EAEA,MAAM,qBAAqB,QAAyC;AAChE,WAAO,qBAAqB,OAAO,OAAO,OAAO,WAAW,OAAO,MAAM;AAAA,EAC7E;AAAA,EAEA,MAAM,oBAAoB,QAAwC;AAC9D,WAAO,oBAAoB,OAAO,QAAQ,OAAO,OAAO,OAAO,IAAI;AAAA,EACvE;AAAA,EAEA,MAAM,mBAAmB,QAAuC;AAC5D,WAAO,mBAAmB,OAAO,OAAO,OAAO,QAAQ,OAAO,kBAAkB,OAAO,SAAS;AAAA,EACpG;AAAA,EAEA,MAAM,SACF,WACA,YACA,YACA,aACA,eACA,OACA,QACuB;AACvB,SAAK;AACL,SAAK;AACL,SAAK;AACL,SAAK;AACL,SAAK;AACL,SAAK;AACL,SAAK;AACL,UAAM,IAAI;AAAA,MACN;AAAA,IAEJ;AAAA,EACJ;AAAA,EAEA,MAAM,gBACF,WACA,YACA,YACA,aACA,eACA,OACA,YACuB;AACvB,UAAM,UAAU,KAAK,eAAe,YAAY,UAAU;AAC1D,UAAM,cAAc,KAAK,iBAAiB,SAAS,aAAa,eAAe,KAAK;AAEpF,UAAM,UAAU;AAAA,MACZ;AAAA,MACA,GAAG,OAAO,UAAU,EAAE,SAAS,EAAE,EAAE,SAAS,IAAI,GAAG;AAAA,MACnD,GAAG,OAAO,UAAU,EAAE,SAAS,EAAE,EAAE,SAAS,IAAI,GAAG;AAAA,MACnD,YAAY,OAAO,WAAW,SAAS,EAAE,EAAE,SAAS,IAAI,GAAG;AAAA,MAC3D,YAAY,OAAO,WAAW,SAAS,EAAE,EAAE,SAAS,IAAI,GAAG;AAAA,MAC3D;AAAA,MACA;AAAA,MACA,OAAO,OAAO,KAAK;AAAA,IACvB;AAEA,UAAM,WAAW,MAAM,MAAM,GAAG,UAAU,kBAAkB;AAAA,MACxD,QAAQ;AAAA,MACR,SAAS,EAAE,gBAAgB,mBAAmB;AAAA,MAC9C,MAAM,KAAK,UAAU,OAAO;AAAA,IAChC,CAAC;AAED,QAAI,CAAC,SAAS,IAAI;AACd,YAAM,IAAI,MAAM,8BAA8B,SAAS,MAAM,IAAI,SAAS,UAAU,EAAE;AAAA,IAC1F;AAEA,UAAM,SAAS,MAAM,SAAS,KAAK;AAEnC,WAAO;AAAA,MACH,iBAAiB,OAAO,mBAAmB,OAAO;AAAA,MAClD,UAAU,OAAO,OAAO,YAAY,CAAC;AAAA,MACrC,aAAa;AAAA,MACb;AAAA,IACJ;AAAA,EACJ;AAAA,EAEA,MAAM,gBAAgB,aAA6C;AAG/D,WAAO,KAAK,oBAAoB,WAAW;AAAA,EAC/C;AAAA,EAEA,oBAAoB,aAA6B;AAE7C,UAAM,QAAQ,YAAY,QAAQ,OAAO,EAAE,EAAE,SAAS,IAAI,GAAG;AAC7D,WAAO,OAAO;AAAA,EAClB;AAAA,EAEA,MAAM,YAAY,cAAwC;AAEtD,WAAO;AAAA,EACX;AAAA,EAEA,MAAM,YAAY,aAAqB,QAA2C;AAC9E,SAAK;AACL,UAAM,IAAI;AAAA,MACN,oJAC+E,KAAK,OAAO,eAAe,cAAc,WAAW;AAAA,IACvI;AAAA,EACJ;AAAA,EAEA,MAAM,qBAAsB,aAAqB,mBAA2B,QAA+C;AACvH,SAAK;AACL,SAAK;AACL,SAAK;AACL,UAAM,IAAI;AAAA,MACN;AAAA,IAEJ;AAAA,EACJ;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,MAAM,sBACF,aACA,YAC4B;AAC5B,UAAM,WAAW,MAAM,MAAM,GAAG,UAAU,qBAAqB;AAAA,MAC3D,QAAQ;AAAA,MACR,SAAS;AAAA,QACL,gBAAgB;AAAA,MACpB;AAAA,MACA,MAAM,KAAK,UAAU;AAAA,QACjB;AAAA,QACA,SAAS,KAAK,OAAO;AAAA,MACzB,CAAC;AAAA,IACL,CAAC;AAED,UAAM,SAAS,MAAM,SAAS,KAAK;AAEnC,QAAI,CAAC,SAAS,MAAM,CAAC,OAAO,SAAS;AACjC,YAAM,IAAI,MAAM,OAAO,SAAS,oCAAoC;AAAA,IACxE;AAEA,WAAO;AAAA,MACH,SAAS,OAAO;AAAA,MAChB,iBAAiB,OAAO,mBAAmB;AAAA,MAC3C,aAAa;AAAA,MACb,SAAS;AAAA,MACT,gBAAgB,OAAO,iBAAiB;AAAA,MACxC,aAAa;AAAA,IACjB;AAAA,EACJ;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,mBACF,aACA,YACkD;AAClD,UAAM,WAAW,MAAM;AAAA,MACnB,GAAG,UAAU,qBAAqB,WAAW,YAAY,KAAK,OAAO,eAAe;AAAA,IACxF;AAEA,QAAI,CAAC,SAAS,IAAI;AACd,YAAM,IAAI,MAAM,uCAAuC;AAAA,IAC3D;AAEA,UAAM,SAAS,MAAM,SAAS,KAAK;AACnC,WAAO;AAAA,MACH,cAAc,OAAO;AAAA,MACrB,QAAQ,OAAO;AAAA,IACnB;AAAA,EACJ;AAAA,EAEA,MAAM,yBAAyB,cAAuC;AAElE,WAAO;AAAA,EACX;AAAA,EAEA,oBAAwC;AACpC,WAAO;AAAA,EACX;AAAA,EAEA,2BAA+C;AAC3C,WAAO;AAAA,EACX;AAAA;AAAA;AAAA;AAAA,EAMA,MAAM,iBAAiB,SAAkC;AACrD,UAAM,UAAU,MAAM,KAAK,OAAO,WAAW,EAAE,OAAO,QAAQ,CAAC;AAC/D,WAAO,OAAO,QAAQ,YAAY;AAAA,EACtC;AAAA,EAEA,MAAM,gBAAgB,UAAkB,cAAuC;AAC3E,UAAM,UAAU,MAAM,KAAK,OAAO,WAAW,EAAE,OAAO,cAAc,SAAS,CAAC;AAC9E,WAAO,OAAO,QAAQ,YAAY;AAAA,EACtC;AAAA,EAEA,YAA6B;AACzB,WAAO,KAAK;AAAA,EAChB;AAAA,EAEA,eAAuB;AACnB,WAAO,KAAK;AAAA,EAChB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAYA,MAAM,gBAAgB,SAA+C;AACjE,UAAM,IAAI;AAAA,MACN;AAAA,IAEJ;AAAA,EACJ;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,MAAM,cAAc,SAA6C;AAC7D,UAAM,IAAI;AAAA,MACN;AAAA,IAEJ;AAAA,EACJ;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAUA,MAAM,gBACF,cACA,iBACgC;AAChC,QAAI,CAAC,KAAK,aAAa,CAAC,KAAK,oBAAoB;AAC7C,YAAM,IAAI;AAAA,QACN;AAAA,MAEJ;AAAA,IACJ;AAKA,UAAM,IAAI;AAAA,MACN;AAAA,IAGJ;AAAA,EACJ;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,MAAM,gBAAgB,aAA4C;AAC9D,QAAI,CAAC,KAAK,aAAa,CAAC,KAAK,oBAAoB;AAC7C,YAAM,IAAI;AAAA,QACN;AAAA,MAEJ;AAAA,IACJ;AAGA,UAAM,IAAI;AAAA,MACN,4GAES,WAAW;AAAA,IACxB;AAAA,EACJ;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAaA,MAAM,aAAa,aAIhB;AACC,QAAI,CAAC,KAAK,aAAa,CAAC,KAAK,oBAAoB;AAC7C,YAAM,IAAI;AAAA,QACN;AAAA,MAEJ;AAAA,IACJ;AAIA,UAAM,IAAI;AAAA,MACN,sGAES,WAAW;AAAA,IACxB;AAAA,EACJ;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASA,MAAM,sBAAsB,aAAsC;AAC9D,QAAI,CAAC,KAAK,aAAa,CAAC,KAAK,oBAAoB;AAC7C,YAAM,IAAI;AAAA,QACN;AAAA,MAEJ;AAAA,IACJ;AAGA,UAAM,IAAI;AAAA,MACN,wHAES,WAAW;AAAA,IACxB;AAAA,EACJ;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAgBA,MAAM,iBACF,SAOuB;AACvB,UAAM,IAAI;AAAA,MACN;AAAA,IAGJ;AAAA,EACJ;AAAA;AAAA;AAAA;AAAA,EAMQ,eAAe,YAAoB,YAA4B;AACnE,UAAM,OAAO,WAAW,SAAS,EAAE,EAAE,SAAS,IAAI,GAAG;AACrD,UAAM,OAAO,WAAW,SAAS,EAAE,EAAE,SAAS,IAAI,GAAG;AACrD,UAAM,WAAW,OAAO,KAAK,OAAO,MAAM,KAAK;AAC/C,UAAM,OAAOC,YAAW,QAAQ,EAAE,OAAO,QAAQ,EAAE,OAAO,KAAK;AAC/D,WAAO,OAAO;AAAA,EAClB;AAAA,EAEQ,iBAAiB,SAAiB,aAAqB,eAAuB,OAAuB;AACzG,UAAM,gBAAgB,OAAO,KAAK,QAAQ,QAAQ,OAAO,EAAE,GAAG,KAAK;AACnE,UAAM,oBAAoB,OAAO,MAAM,CAAC;AACxC,sBAAkB,cAAc,WAAW;AAC3C,UAAM,gBAAgB,OAAO,KAAK,cAAc,QAAQ,OAAO,EAAE,GAAG,KAAK;AACzE,UAAM,WAAW,MAAM,SAAS,EAAE,EAAE,SAAS,IAAI,GAAG;AACpD,UAAM,cAAc,OAAO,KAAK,UAAU,KAAK;AAE/C,UAAM,WAAW,OAAO,OAAO,CAAC,eAAe,mBAAmB,eAAe,WAAW,CAAC;AAC7F,UAAM,OAAOA,YAAW,QAAQ,EAAE,OAAO,QAAQ,EAAE,OAAO,KAAK;AAC/D,WAAO,OAAO;AAAA,EAClB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAsBA,MAAM,WACF,cACA,kBACsB;AACtB,QAAI;AAGA,YAAM,iBAAiB,MAAM,KAAK,OAAO,UAAU;AAAA,QAC/C,IAAI;AAAA,QACJ,SAAS,EAAE,aAAa,KAAK;AAAA,MACjC,CAAC;AAED,UAAI,CAAC,eAAe,MAAM,SAAS;AAC/B,eAAO;AAAA,MACX;AAIA,cAAQ,KAAK,kEAAkE;AAC/E,aAAO;AAAA,IACX,SAAS,OAAO;AACZ,cAAQ,MAAM,2BAA2B,KAAK;AAC9C,aAAO;AAAA,IACX;AAAA,EACJ;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,MAAM,cAAc,eAA+C;AAC/D,QAAI;AACA,YAAM,cAAc,MAAM,KAAK,OAAO,UAAU;AAAA,QAC5C,IAAI;AAAA,QACJ,SAAS,EAAE,aAAa,KAAK;AAAA,MACjC,CAAC;AAED,UAAI,CAAC,YAAY,MAAM,WAAW,YAAY,KAAK,QAAQ,aAAa,cAAc;AAClF,eAAO;AAAA,MACX;AAEA,YAAM,SAAS,YAAY,KAAK,QAAQ;AACxC,YAAM,eAAe,OAAO,gBAAgB;AAE5C,UAAI,CAAC,cAAc;AACf,eAAO;AAAA,MACX;AAGA,aAAO,OAAO,OAAO,KAAK,YAAY,EAAE,SAAS,KAAK;AAAA,IAC1D,SAAS,OAAO;AACZ,cAAQ,MAAM,8BAA8B,KAAK;AACjD,aAAO;AAAA,IACX;AAAA,EACJ;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,MAAM,qBAAqB,eAA0C;AACjE,QAAI;AACA,YAAM,cAAc,MAAM,KAAK,OAAO,UAAU;AAAA,QAC5C,IAAI;AAAA,QACJ,SAAS,EAAE,aAAa,KAAK;AAAA,MACjC,CAAC;AAED,UAAI,CAAC,YAAY,MAAM,WAAW,YAAY,KAAK,QAAQ,aAAa,cAAc;AAClF,eAAO,CAAC;AAAA,MACZ;AAEA,YAAM,SAAS,YAAY,KAAK,QAAQ;AACxC,YAAM,oBAAoB,OAAO,oBAAoB;AAErD,UAAI,CAAC,mBAAmB;AACpB,eAAO,CAAC;AAAA,MACZ;AAGA,aAAO,kBAAkB;AAAA,QAAI,YACzB,OAAO,OAAO,KAAK,MAAM,EAAE,SAAS,KAAK;AAAA,MAC7C;AAAA,IACJ,SAAS,OAAO;AACZ,cAAQ,MAAM,qCAAqC,KAAK;AACxD,aAAO,CAAC;AAAA,IACZ;AAAA,EACJ;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASA,MAAM,eACF,SACA,uBACgB;AAChB,QAAI;AACA,YAAM,kBAAkB,MAAM,KAAK,OAAO,UAAU;AAAA,QAChD,IAAI;AAAA,QACJ,SAAS,EAAE,aAAa,KAAK;AAAA,MACjC,CAAC;AAED,UAAI,CAAC,gBAAgB,MAAM,SAAS;AAChC,eAAO;AAAA,MACX;AAGA,cAAQ,KAAK,6CAA6C;AAC1D,aAAO;AAAA,IACX,SAAS,OAAO;AACZ,cAAQ,MAAM,8BAA8B,KAAK;AACjD,aAAO;AAAA,IACX;AAAA,EACJ;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,MAAM,iBAAiB,gBAA0C;AAC7D,QAAI;AACA,YAAM,eAAe,MAAM,KAAK,OAAO,UAAU;AAAA,QAC7C,IAAI;AAAA,QACJ,SAAS,EAAE,aAAa,KAAK;AAAA,MACjC,CAAC;AAED,UAAI,CAAC,aAAa,MAAM,WAAW,aAAa,KAAK,QAAQ,aAAa,cAAc;AACpF,eAAO;AAAA,MACX;AAEA,YAAM,SAAS,aAAa,KAAK,QAAQ;AACzC,aAAO,OAAO,QAAQ,MAAM;AAAA,IAChC,SAAS,OAAO;AACZ,cAAQ,MAAM,gCAAgC,KAAK;AACnD,aAAO;AAAA,IACX;AAAA,EACJ;AACJ;;;AC7mBA,SAAS,cAAAC,mBAAkB;AAC3B,SAAS,mBAAmB;AAQ5B,IAAM,cAAc,OAAO,oEAAoE,IAAI;AAGnG,IAAM,WAAW,OAAO,qCAAqC;AAS7D,SAAS,eAAe,SAAmC;AACvD,QAAM,YAAY,QAAQ,QAAQ,MAAM,EAAE,EAAE,SAAS,IAAI,GAAG;AAC5D,QAAM,QAAQ,OAAO,OAAO,SAAS;AAGrC,QAAM,MAAM,QAAQ;AACpB,QAAM,OAAO,QAAQ;AAErB,SAAO;AAAA,IACH,OAAO,IAAI,SAAS,EAAE;AAAA,IACtB,OAAO,KAAK,SAAS,EAAE;AAAA,EAC3B;AACJ;AAmCO,IAAM,iBAAN,MAA4C;AAAA,EACvC;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EAER,YAAY,QAA8B;AACtC,SAAK,SAAS;AAAA,MACV,MAAM,YAAY,OAAO,WAAW,SAAS;AAAA,MAC7C,SAAS;AAAA,MACT,iBAAiB,OAAO;AAAA,MACxB,QAAQ,OAAO;AAAA,MACf,aAAa,OAAO,YAAY,YAC1B,iCACA;AAAA,MACN,OAAO;AAAA,MACP,WAAW;AAAA,QACP,KAAK,OAAO;AAAA,QACZ,oBAAoB,OAAO,yBAAyB;AAAA,MACxD;AAAA,IACJ;AAEA,SAAK,YAAY,OAAO;AACxB,SAAK,qBAAqB,OAAO;AAEjC,SAAK,WAAW,IAAI,YAAY,EAAE,SAAS,OAAO,OAAO,CAAC;AAAA,EAC9D;AAAA,EAEA,YAAyB;AACrB,WAAO,KAAK;AAAA,EAChB;AAAA,EAEA,MAAM,SAAS,cAAuC;AAClD,WAAO;AAAA,EACX;AAAA,EAEA,MAAM,gBAAiC;AACnC,WAAO;AAAA,EACX;AAAA,EAEA,MAAM,qBAAqB,QAAyC;AAChE,WAAO,qBAAqB,OAAO,OAAO,OAAO,WAAW,OAAO,MAAM;AAAA,EAC7E;AAAA,EAEA,MAAM,oBAAoB,QAAwC;AAC9D,WAAO,oBAAoB,OAAO,QAAQ,OAAO,OAAO,OAAO,IAAI;AAAA,EACvE;AAAA,EAEA,MAAM,mBAAmB,QAAuC;AAC5D,WAAO,mBAAmB,OAAO,OAAO,OAAO,QAAQ,OAAO,kBAAkB,OAAO,SAAS;AAAA,EACpG;AAAA,EAEA,MAAM,SACF,WACA,YACA,YACA,aACA,eACA,OACA,QACuB;AACvB,SAAK;AACL,SAAK;AACL,SAAK;AACL,SAAK;AACL,SAAK;AACL,SAAK;AACL,SAAK;AACL,UAAM,IAAI;AAAA,MACN;AAAA,IAGJ;AAAA,EACJ;AAAA,EAEA,MAAM,gBACF,WACA,YACA,YACA,aACA,eACA,OACA,YACuB;AAgBvB,UAAM,UAAU,KAAK,eAAe,YAAY,UAAU;AAG1D,UAAM,UAAU;AAAA,MACZ,WAAW;AAAA,QACP,GAAG,OAAO,UAAU,EAAE,SAAS,EAAE,EAAE,SAAS,IAAI,GAAG;AAAA,QACnD,GAAG,OAAO,UAAU,EAAE,SAAS,EAAE,EAAE,SAAS,IAAI,GAAG;AAAA,QACnD,mBAAmB,UAAU;AAAA,QAC7B,gBAAgB,UAAU;AAAA,QAC1B,gBAAgB,UAAU;AAAA,QAC1B,WAAW,UAAU;AAAA,MACzB;AAAA,MACA,YAAY,OAAO,WAAW,SAAS,EAAE,EAAE,SAAS,IAAI,GAAG;AAAA,MAC3D,YAAY,OAAO,WAAW,SAAS,EAAE,EAAE,SAAS,IAAI,GAAG;AAAA,MAC3D;AAAA;AAAA,MACA;AAAA,MACA,WAAW,OAAO,KAAK;AAAA,IAC3B;AAEA,UAAM,WAAW,MAAM,MAAM,GAAG,UAAU,kBAAkB;AAAA,MACxD,QAAQ;AAAA,MACR,SAAS,EAAE,gBAAgB,mBAAmB;AAAA,MAC9C,MAAM,KAAK,UAAU,OAAO;AAAA,IAChC,CAAC;AAED,QAAI,CAAC,SAAS,IAAI;AACd,YAAM,YAAY,MAAM,SAAS,KAAK,EAAE,MAAM,MAAM,eAAe;AACnE,YAAM,IAAI;AAAA,QACN,8BAA8B,SAAS,MAAM,IAAI,SAAS,UAAU,YAC1D,SAAS;AAAA,MACvB;AAAA,IACJ;AAEA,UAAM,SAAS,MAAM,SAAS,KAAK;AAEnC,WAAO;AAAA,MACH,iBAAiB,OAAO,mBAAmB,OAAO,UAAU,OAAO;AAAA,MACnE,UAAU,OAAO,OAAO,YAAY,CAAC;AAAA,MACrC,aAAa;AAAA,MACb;AAAA,IACJ;AAAA,EACJ;AAAA;AAAA;AAAA,EAKA,oBAAoB,aAA6B;AAU7C,UAAM,QAAQ,YAAY,QAAQ,OAAO,EAAE;AAC3C,WAAO,OAAO;AAAA,EAClB;AAAA,EAEA,MAAM,YAAY,aAAuC;AAKrD,QAAI,CAAC,KAAK,OAAO,UAAU,KAAK;AAC5B,aAAO;AAAA,IACX;AAEA,QAAI;AACA,YAAM,eAAe,MAAM,KAAK,gBAAgB,WAAW;AAC3D,UAAI,CAAC,cAAc;AACf,eAAO;AAAA,MACX;AAGA,YAAM,cAAc,KAAK;AACzB,UAAI,OAAO,YAAY,mBAAmB,YAAY;AAClD,cAAM,YAAY,eAAe,YAAY;AAC7C,eAAO;AAAA,MACX;AAAA,IACJ,QAAQ;AAAA,IAER;AAEA,WAAO;AAAA,EACX;AAAA,EAEA,MAAM,YAAY,aAAqB,QAA2C;AAC9E,SAAK;AACL,UAAM,IAAI;AAAA,MACN,yLAEW,WAAW;AAAA,IAC1B;AAAA,EACJ;AAAA,EAEA,MAAM,qBAAsB,aAAqB,mBAA2B,QAA+C;AACvH,SAAK;AACL,SAAK;AACL,SAAK;AACL,UAAM,IAAI;AAAA,MACN;AAAA,IAEJ;AAAA,EACJ;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,MAAM,sBACF,aACA,YAC4B;AAC5B,UAAM,WAAW,MAAM,MAAM,GAAG,UAAU,0BAA0B;AAAA,MAChE,QAAQ;AAAA,MACR,SAAS;AAAA,QACL,gBAAgB;AAAA,MACpB;AAAA,MACA,MAAM,KAAK,UAAU;AAAA,QACjB;AAAA,QACA,SAAS,KAAK,OAAO;AAAA,MACzB,CAAC;AAAA,IACL,CAAC;AAED,UAAM,SAAS,MAAM,SAAS,KAAK;AAEnC,QAAI,CAAC,SAAS,MAAM,CAAC,OAAO,SAAS;AACjC,YAAM,IAAI,MAAM,OAAO,SAAS,oCAAoC;AAAA,IACxE;AAEA,WAAO;AAAA,MACH,SAAS,OAAO;AAAA,MAChB,iBAAiB,OAAO,mBAAmB;AAAA,MAC3C,aAAa;AAAA,MACb,SAAS;AAAA,MACT,gBAAgB,OAAO,iBAAiB;AAAA,MACxC,aAAa;AAAA,IACjB;AAAA,EACJ;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,mBACF,aACA,YACkD;AAClD,UAAM,WAAW,MAAM;AAAA,MACnB,GAAG,UAAU,0BAA0B,WAAW,YAAY,KAAK,OAAO,eAAe;AAAA,IAC7F;AAEA,QAAI,CAAC,SAAS,IAAI;AACd,YAAM,IAAI,MAAM,uCAAuC;AAAA,IAC3D;AAEA,UAAM,SAAS,MAAM,SAAS,KAAK;AACnC,WAAO;AAAA,MACH,cAAc,OAAO;AAAA,MACrB,QAAQ,OAAO;AAAA,IACnB;AAAA,EACJ;AAAA,EAEA,MAAM,yBAAyB,cAAuC;AAClE,WAAO;AAAA,EACX;AAAA,EAEA,oBAAwC;AACpC,WAAO;AAAA,EACX;AAAA,EAEA,2BAA+C;AAC3C,WAAO;AAAA,EACX;AAAA;AAAA;AAAA;AAAA,EAMA,MAAM,iBAAiB,SAAkC;AAErD,QAAI;AACA,YAAM,cAAc,KAAK;AACzB,UAAI,OAAO,YAAY,eAAe,YAAY;AAC9C,cAAM,MAAM,MAAM,YAAY,WAAW,OAAO;AAChD,eAAO,OAAO,GAAG;AAAA,MACrB;AAAA,IACJ,QAAQ;AAAA,IAER;AACA,WAAO;AAAA,EACX;AAAA,EAEA,cAA2B;AACvB,WAAO,KAAK;AAAA,EAChB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAYA,MAAM,gBAAgB,SAA+C;AACjE,UAAM,IAAI;AAAA,MACN;AAAA,IAEJ;AAAA,EACJ;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,MAAM,cAAc,SAA6C;AAC7D,UAAM,IAAI;AAAA,MACN;AAAA,IAEJ;AAAA,EACJ;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAUA,MAAM,gBACF,aACA,gBACgC;AAChC,QAAI,CAAC,KAAK,aAAa,CAAC,KAAK,oBAAoB;AAC7C,YAAM,IAAI;AAAA,QACN;AAAA,MAEJ;AAAA,IACJ;AAGA,UAAM,IAAI;AAAA,MACN;AAAA,IAGJ;AAAA,EACJ;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,MAAM,gBAAgB,aAA4C;AAC9D,QAAI,CAAC,KAAK,aAAa,CAAC,KAAK,oBAAoB;AAC7C,YAAM,IAAI;AAAA,QACN;AAAA,MAEJ;AAAA,IACJ;AAGA,UAAM,IAAI;AAAA,MACN,4GAES,WAAW;AAAA,IACxB;AAAA,EACJ;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAaA,MAAM,aAAa,aAIhB;AACC,QAAI,CAAC,KAAK,aAAa,CAAC,KAAK,oBAAoB;AAC7C,YAAM,IAAI;AAAA,QACN;AAAA,MAEJ;AAAA,IACJ;AAGA,UAAM,IAAI;AAAA,MACN,sGAES,WAAW;AAAA,IACxB;AAAA,EACJ;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASA,MAAM,sBAAsB,aAAsC;AAC9D,QAAI,CAAC,KAAK,aAAa,CAAC,KAAK,oBAAoB;AAC7C,YAAM,IAAI;AAAA,QACN;AAAA,MAEJ;AAAA,IACJ;AAGA,UAAM,IAAI;AAAA,MACN,wHAES,WAAW;AAAA,IACxB;AAAA,EACJ;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAgBA,MAAM,iBACF,SAOuB;AACvB,UAAM,IAAI;AAAA,MACN;AAAA,IAGJ;AAAA,EACJ;AAAA;AAAA;AAAA;AAAA,EAMQ,eAAe,YAAoB,YAA4B;AACnE,UAAM,OAAO,WAAW,SAAS,EAAE,EAAE,SAAS,IAAI,GAAG;AACrD,UAAM,OAAO,WAAW,SAAS,EAAE,EAAE,SAAS,IAAI,GAAG;AACrD,UAAM,WAAW,OAAO,KAAK,OAAO,MAAM,KAAK;AAC/C,UAAM,OAAOC,YAAW,QAAQ,EAAE,OAAO,QAAQ,EAAE,OAAO,KAAK;AAC/D,WAAO,OAAO;AAAA,EAClB;AAAA,EAEQ,iBAAiB,SAAiB,aAAqB,eAAuB,OAAuB;AACzG,UAAM,gBAAgB,OAAO,KAAK,QAAQ,QAAQ,OAAO,EAAE,GAAG,KAAK;AACnE,UAAM,oBAAoB,OAAO,MAAM,CAAC;AACxC,sBAAkB,cAAc,WAAW;AAC3C,UAAM,gBAAgB,OAAO,KAAK,cAAc,QAAQ,OAAO,EAAE,GAAG,KAAK;AACzE,UAAM,WAAW,MAAM,SAAS,EAAE,EAAE,SAAS,IAAI,GAAG;AACpD,UAAM,cAAc,OAAO,KAAK,UAAU,KAAK;AAE/C,UAAM,WAAW,OAAO,OAAO,CAAC,eAAe,mBAAmB,eAAe,WAAW,CAAC;AAC7F,UAAM,OAAOA,YAAW,QAAQ,EAAE,OAAO,QAAQ,EAAE,OAAO,KAAK;AAC/D,WAAO,OAAO;AAAA,EAClB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAoBA,MAAM,gBAAgB,cAA8C;AAChE,QAAI;AACA,YAAM,eAAe,KAAK,OAAO,UAAU;AAC3C,UAAI,CAAC,cAAc;AACf,cAAM,IAAI,MAAM,uCAAuC;AAAA,MAC3D;AAGA,YAAM,CAAC,KAAK,IAAI,IAAI,eAAe,YAAY;AAG/C,YAAM,SAAS,MAAM,KAAK,SAAS,aAAa;AAAA,QAC5C,iBAAiB;AAAA,QACjB,YAAY;AAAA,QACZ,UAAU,CAAC,KAAK,IAAI;AAAA,MACxB,CAAC;AAGD,YAAM,eAAe,OAAO,CAAC;AAC7B,UAAI,iBAAiB,SAAS,iBAAiB,KAAK;AAChD,eAAO;AAAA,MACX;AAEA,aAAO;AAAA,IACX,SAAS,OAAO;AACZ,cAAQ,MAAM,gCAAgC,KAAK;AACnD,aAAO;AAAA,IACX;AAAA,EACJ;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,MAAM,aAAa,cAGT;AACN,UAAM,eAAe,MAAM,KAAK,gBAAgB,YAAY;AAC5D,QAAI,CAAC,cAAc;AACf,aAAO;AAAA,IACX;AAEA,WAAO;AAAA,MACH,SAAS;AAAA,MACT;AAAA,IACJ;AAAA,EACJ;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,MAAM,mBAAqC;AACvC,QAAI;AACA,YAAM,eAAe,KAAK,OAAO,UAAU;AAC3C,UAAI,CAAC,cAAc;AACf,cAAM,IAAI,MAAM,uCAAuC;AAAA,MAC3D;AAEA,YAAM,SAAS,MAAM,KAAK,SAAS,aAAa;AAAA,QAC5C,iBAAiB;AAAA,QACjB,YAAY;AAAA,QACZ,UAAU,CAAC;AAAA,MACf,CAAC;AAED,aAAO,OAAO,CAAC,MAAM,SAAS,OAAO,CAAC,MAAM;AAAA,IAChD,SAAS,OAAO;AACZ,cAAQ,MAAM,gCAAgC,KAAK;AACnD,aAAO;AAAA,IACX;AAAA,EACJ;AACJ;;;AClpBA,IAAM,sBAA0F;AAAA,EAC5F,GAAG,EAAE,QAAQ,OAAO,MAAM,UAAU,UAAU,EAAE;AAAA,EAChD,IAAI,EAAE,QAAQ,OAAO,MAAM,OAAO,UAAU,EAAE;AAAA,EAC9C,IAAI,EAAE,QAAQ,OAAO,MAAM,SAAS,UAAU,EAAE;AACpD;AAEO,IAAM,gBAAN,MAAoB;AAAA,EACN;AAAA,EACA;AAAA,EACA;AAAA,EAEjB,YAAY,SAA8B,CAAC,GAAG;AAC1C,SAAK,UAAU,OAAO,WAAW;AACjC,SAAK,UAAU,OAAO,WAAW,CAAC;AAClC,SAAK,gBAAgB,IAAI,cAAc,EAAE,gBAAgB,MAAM,kBAAkB,MAAM,CAAC;AAAA,EAC5F;AAAA,EAEA,eAAe,iBAAkD;AAC7D,UAAM,SAAS,KAAK,UAAU,iBAAiB;AAC/C,WAAO,OAAO,OAAO,MAAM,EAAE,KAAK,OAAK,EAAE,oBAAoB,eAAe;AAAA,EAChF;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,aAAa,iBAAsC;AAC/C,UAAM,QAAQ,KAAK,eAAe,eAAe;AACjD,QAAI,CAAC,OAAO;AACR,YAAM,IAAI,MAAM,kCAAkC,eAAe,GAAG;AAAA,IACxE;AAEA,UAAM,SAAS,KAAK,QAAQ,eAAe,KAAK,MAAM;AAEtD,QAAI,MAAM,OAAO;AACb,YAAM,IAAI;AAAA,QACN,mEAAmE,eAAe;AAAA,MAEtF;AAAA,IACJ;AAEA,YAAQ,iBAAiB;AAAA,MACrB,KAAK,GAAG;AACJ,cAAM,YAAY,MAAM,UAAU;AAClC,YAAI,CAAC,aAAa,CAAC,MAAM,UAAU,aAAa;AAC5C,gBAAM,IAAI,MAAM,0DAA0D;AAAA,QAC9E;AACA,eAAO,IAAI,aAAa;AAAA,UACpB;AAAA,UACA;AAAA,UACA;AAAA,UACA,oBAAoB,MAAM,UAAU;AAAA,UACpC,aAAa,MAAM,UAAU;AAAA,UAC7B,SAAS,KAAK,UAAU,WAAW;AAAA,QACvC,CAAC;AAAA,MACL;AAAA,MACA,KAAK,IAAI;AACL,cAAM,gBAAgB,MAAM,UAAU;AACtC,YAAI,CAAC,iBAAiB,CAAC,MAAM,UAAU,aAAa;AAChD,gBAAM,IAAI,MAAM,6DAA6D;AAAA,QACjF;AACA,eAAO,IAAI,YAAY;AAAA,UACnB;AAAA,UACA;AAAA,UACA;AAAA,UACA,oBAAoB,MAAM,UAAU;AAAA,UACpC,aAAa,MAAM,UAAU;AAAA,UAC7B,SAAS,KAAK,UAAU,YAAY;AAAA,QACxC,CAAC;AAAA,MACL;AAAA,MACA,KAAK,IAAI;AACL,cAAM,YAAY,MAAM,UAAU;AAClC,eAAO,IAAI,UAAU;AAAA,UACjB;AAAA,UACA;AAAA,UACA,WAAW,aAAa;AAAA,UACxB,oBAAoB,MAAM,UAAU;AAAA,UACpC,aAAa,MAAM,UAAU;AAAA,UAC7B,SAAS,KAAK,UAAU,YAAY;AAAA,QACxC,CAAC;AAAA,MACL;AAAA,MACA,KAAK,OAAO;AAER,cAAM,eAAe,MAAM,UAAU;AACrC,cAAM,gBAAgB,MAAM,UAAU;AACtC,YAAI,CAAC,gBAAgB,CAAC,eAAe;AACjC,gBAAM,IAAI,MAAM,6DAA6D;AAAA,QACjF;AACA,eAAO,IAAI,eAAe;AAAA,UACtB;AAAA,UACA;AAAA,UACA,sBAAsB;AAAA,UACtB,uBAAuB;AAAA,UACvB,SAAS,KAAK,UAAU,YAAY;AAAA,QACxC,CAAC;AAAA,MACL;AAAA,MACA;AACI,cAAM,IAAI;AAAA,UACN,8CAA8C,eAAe;AAAA,QAEjE;AAAA,IACR;AAAA,EACJ;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,mBAAmB,YAA+B,iBAA8C;AAC5F,UAAM,QAAQ,KAAK,eAAe,eAAe;AACjD,QAAI,CAAC,OAAO;AACR,aAAO;AAAA,IACX;AAEA,QAAI,MAAM,OAAO;AACb,YAAM,UAAU,MAAM,UAAU;AAChC,YAAM,iBAAiB,MAAM,UAAU;AACvC,UAAI,CAAC,WAAW,CAAC,gBAAgB;AAC7B,eAAO;AAAA,MACX;AAEA,YAAM,UAAU,KAAK,cAAc,oBAAoB,WAAW,SAAS,SAAS,cAAc;AAClG,aAAO;AAAA,QACH;AAAA,QACA,WAAW,MAAM;AAAA,QACjB;AAAA,QACA,OAAO;AAAA,QACP,UAAU;AAAA,QACV,gBAAgB;AAAA,MACpB;AAAA,IACJ;AAGA,WAAO;AAAA,MACH;AAAA,MACA,WAAW,MAAM;AAAA,MACjB,SAAS,oBAAoB,KACvB,KAAK,oBAAoB,WAAW,OAAO,IAC3C,oBAAoB,QACpB,WAAW,UACX,WAAW;AAAA,MACjB,OAAO;AAAA,MACP,UAAU;AAAA,MACV,gBAAgB,oBAAoB,IAC9B,QACA,oBAAoB,KACpB,qBACA,oBAAoB,QACpB,YACA;AAAA,IACV;AAAA,EACJ;AAAA,EAEA,yBAAyB,iBAAoF;AACzG,WAAO,oBAAoB,eAAe,KAAK;AAAA,EACnD;AAAA,EAEQ,oBAAoB,OAAuB;AAC/C,UAAM,QAAQ,MAAM,QAAQ,OAAO,EAAE,EAAE,SAAS,IAAI,GAAG;AACvD,WAAO,OAAO;AAAA,EAClB;AACJ;AAEO,SAAS,oBAAoB,SAA8B,CAAC,GAAkB;AACjF,SAAO,IAAI,cAAc,MAAM;AACnC;;;ACzLA,SAAS,UAAAC,eAAc;;;ACqQhB,IAAM,qBAA+D;AAAA;AAAA,EAE1E,GAAG,EAAE,MAAM,UAAU,WAAW,MAAM;AAAA,EACtC,GAAG,EAAE,MAAM,YAAY,WAAW,MAAM;AAAA,EACxC,GAAG,EAAE,MAAM,OAAO,WAAW,MAAM;AAAA,EACnC,GAAG,EAAE,MAAM,WAAW,WAAW,MAAM;AAAA,EACvC,GAAG,EAAE,MAAM,aAAa,WAAW,MAAM;AAAA,EACzC,IAAI,EAAE,MAAM,OAAO,WAAW,MAAM;AAAA,EACpC,IAAI,EAAE,MAAM,SAAS,WAAW,MAAM;AAAA,EACtC,IAAI,EAAE,MAAM,YAAY,WAAW,MAAM;AAAA,EACzC,IAAI,EAAE,MAAM,YAAY,WAAW,MAAM;AAAA,EACzC,IAAI,EAAE,MAAM,QAAQ,WAAW,MAAM;AAAA;AAAA,EAGrC,OAAO,EAAE,MAAM,WAAW,WAAW,KAAK;AAAA,EAC1C,OAAO,EAAE,MAAM,oBAAoB,WAAW,KAAK;AAAA,EACnD,OAAO,EAAE,MAAM,gBAAgB,WAAW,KAAK;AAAA,EAC/C,OAAO,EAAE,MAAM,oBAAoB,WAAW,KAAK;AAAA,EACnD,OAAO,EAAE,MAAM,oBAAoB,WAAW,KAAK;AACrD;AAKO,SAAS,gBAAgB,SAA+B;AAC7D,QAAM,OAAO,mBAAmB,OAAO;AACvC,MAAI,MAAM;AACR,WAAO,EAAE,IAAI,SAAS,GAAG,KAAK;AAAA,EAChC;AACA,SAAO;AAAA,IACL,IAAI;AAAA,IACJ,MAAM,SAAS,OAAO;AAAA,IACtB,WAAW,WAAW;AAAA,EACxB;AACF;AAMO,IAAM,oBAA4C;AAAA,EACvD,GAAG;AAAA,EACH,GAAG;AAAA,EACH,GAAG;AAAA,EACH,GAAG;AAAA,EACH,GAAG;AAAA,EACH,GAAG;AAAA,EACH,GAAG;AACL;AAKO,SAAS,kBAAkB,YAA4B;AAC5D,SAAO,kBAAkB,UAAU,KAAK,uBAAuB,UAAU;AAC3E;;;AD5RA,IAAM,iBAAyC,oBAAI,IAAI;AAAA;AAAA,EAErD,CAAC,8CAA8C;AAAA,IAC7C,QAAQ;AAAA,IACR,MAAM;AAAA,IACN,UAAU;AAAA,IACV,UAAU;AAAA,EACZ,CAAC;AAAA,EACD,CAAC,UAAU;AAAA,IACT,QAAQ;AAAA,IACR,MAAM;AAAA,IACN,UAAU;AAAA,IACV,UAAU;AAAA,EACZ,CAAC;AAAA;AAAA,EAED,CAAC,8CAA8C;AAAA,IAC7C,QAAQ;AAAA,IACR,MAAM;AAAA,IACN,UAAU;AAAA,IACV,UAAU;AAAA,EACZ,CAAC;AACH,CAAC;AASM,SAASC,cAAa,QAAgB,UAA0B;AACrE,MAAI,WAAW,GAAI,QAAO;AAE1B,QAAM,UAAU,OAAO,OAAO,QAAQ;AACtC,QAAM,QAAQ,SAAS;AACvB,QAAM,YAAY,SAAS;AAE3B,MAAI,cAAc,IAAI;AACpB,WAAO,MAAM,SAAS;AAAA,EACxB;AAGA,QAAM,eAAe,UAAU,SAAS,EAAE,SAAS,UAAU,GAAG;AAEhE,QAAM,UAAU,aAAa,QAAQ,OAAO,EAAE;AAE9C,SAAO,GAAG,KAAK,IAAI,OAAO;AAC5B;AAKO,SAAS,gBAAgB,SAAiB,aAAa,GAAG,WAAW,GAAW;AACrF,MAAI,QAAQ,UAAU,aAAa,WAAW,GAAG;AAC/C,WAAO;AAAA,EACT;AACA,SAAO,GAAG,QAAQ,MAAM,GAAG,UAAU,CAAC,MAAM,QAAQ,MAAM,CAAC,QAAQ,CAAC;AACtE;AAKO,SAAS,oBAAoB,WAA2B;AAC7D,QAAM,MAAM,KAAK,IAAI;AACrB,QAAM,YAAY,YAAY;AAE9B,MAAI,aAAa,EAAG,QAAO;AAE3B,QAAM,UAAU,KAAK,MAAM,YAAY,GAAI;AAC3C,MAAI,UAAU,GAAI,QAAO,GAAG,OAAO;AAEnC,QAAM,UAAU,KAAK,MAAM,UAAU,EAAE;AACvC,MAAI,UAAU,GAAI,QAAO,GAAG,OAAO,UAAU,YAAY,IAAI,KAAK,GAAG;AAErE,QAAM,QAAQ,KAAK,MAAM,UAAU,EAAE;AACrC,SAAO,GAAG,KAAK,QAAQ,UAAU,IAAI,KAAK,GAAG;AAC/C;AAKO,SAASC,eAAc,SAA0B;AACtD,SAAO,YAAY,gDACZ,YAAY,YACZ,YAAYC,QAAO;AAC5B;AASO,IAAM,oBAAN,MAAwB;AAAA,EACrB;AAAA,EACA;AAAA,EAER,YAAY,SAAkC,CAAC,GAAG;AAChD,SAAK,SAAS;AACd,SAAK,gBAAgB,OAAO,eAAe,IAAI,IAAI,cAAc;AAAA,EACnE;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAYA,MAAM,MACJ,UACA,cACA,cAC6B;AAC7B,UAAM,wBAAwB,gBAAgB;AAG9C,UAAM,mBAAmB,sBAAsB;AAC/C,UAAM,iBAAiB,mBAClB,SAA4B,mBAC5B,SAA8B,OAAO;AAC1C,UAAM,mBAAmB,gBAAgB,KAAK,OAAO,kBAAkB;AAIvE,UAAM,mBAAmC,mBACrC;AAAA,MACE,aAAc,SAA4B;AAAA,MAC1C,OAAQ,SAA4B,OAAO;AAAA,MAC3C,WAAY,SAA4B,OAAO;AAAA,MAC/C,QAAS,SAA4B,OAAO;AAAA,IAC9C,IACC,SAA8B;AAEnC,UAAM,aAA+B;AAAA,MACnC,QAAQ;AAAA,MACR,eAAe,SAAS;AAAA,MACxB,OAAO,SAAS;AAAA,MAChB,WAAW,SAAS;AAAA,MACpB,cAAe,SAA8B,gBAAgB;AAAA,MAC7D,UAAW,SAA8B,YAAY;AAAA,MACrD,YAAa,SAA8B,eAAe,mBAAoB,SAA4B,MAAM,cAAc,KAAK;AAAA,MACnI,WAAY,SAA8B,aAAa;AAAA,MACvD,eAAgB,SAA8B,iBAAiB;AAAA,MAC/D,YAAY,SAAS,cAAc,KAAK,IAAI;AAAA,MAC5C,WAAW,SAAS;AAAA,IACtB;AAGA,UAAM,aAAa,KAAK,iBAAiB,WAAW,aAAa;AAEjE,YAAQ,YAAY;AAAA,MAClB,KAAK;AACH,eAAO,KAAK,cAAc,YAAY,uBAAuB,gBAAgB;AAAA,MAC/E,KAAK;AACH,eAAO,KAAK,wBAAwB,YAAY,uBAAuB,gBAAgB;AAAA,MACzF,KAAK;AACH,eAAO,KAAK;AAAA,UACV,WAAW;AAAA,UACX,WAAW;AAAA,UACX,WAAW;AAAA,UACX;AAAA,UACA;AAAA,UACA,WAAW;AAAA,UACX,WAAW;AAAA,QACb;AAAA,MACF,KAAK;AACH,eAAO,KAAK;AAAA,UACV,WAAW;AAAA,UACX,WAAW;AAAA,UACX,WAAW;AAAA,UACX;AAAA,UACA;AAAA,UACA,WAAW;AAAA,UACX,WAAW;AAAA,QACb;AAAA,MACF;AAEE,eAAO,KAAK,2BAA2B,YAAY,uBAAuB,gBAAgB;AAAA,IAC9F;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAKQ,iBAAiB,SAAyB;AAChD,QAAI,CAAC,WAAW,QAAQ,SAAS,EAAG,QAAO;AAE3C,UAAM,UAAU,QAAQ,MAAM,GAAG,CAAC;AAClC,WAAO,SAAS,SAAS,EAAE;AAAA,EAC7B;AAAA;AAAA;AAAA;AAAA,EAKA,MAAc,wBACZ,UACA,cACA,cAC6B;AAC7B,UAAM,EAAE,QAAQ,eAAe,OAAO,WAAW,WAAW,cAAc,IAAI;AAC9E,UAAM,UAAU,mBAAmB,aAAa;AAEhD,UAAM,QAAQ,MAAM,KAAK,aAAa,QAAQ,OAAO,QAAQ,MAAM;AACnE,UAAM,cAAc,gBAAgB,YAAY;AAChD,UAAM,mBAAmB,gBAAgB,OAAO,WAAW;AAC3D,UAAM,YAAY,MAAM,KAAK,iBAAiB,QAAQ,SAAS;AAE/D,UAAM,UAAyB;AAAA,MAC7B;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA,eAAe,KAAK,mBAAmB,YAAY,IAAI,iBAAiB,EAAE;AAAA,IAC5E;AAEA,UAAM,WAAW,MAAM,KAAK,kBAAkB;AAAA,MAC5C,aAAa;AAAA,MACb,kBAAkB,OAAO;AAAA,MACzB,OAAO,QAAQ;AAAA,MACf,WAAW,QAAQ;AAAA,MACnB,QAAQ,QAAQ;AAAA,IAClB,GAAG,OAAO,aAAa,gBAAgB;AAEvC,WAAO;AAAA,MACL,QAAQ;AAAA,MACR,OAAO,UAAU,MAAM,MAAM;AAAA,MAC7B,aAAa,UAAU,MAAM,MAAM,IAAI,MAAM,MAAM,SAAS,YAAY,IAAI,OAAO,iBAAiB,IAAI;AAAA,MACxG;AAAA,MACA,OAAO;AAAA,QACL,SAAS;AAAA,QACT,WAAW,gBAAgB,YAAY;AAAA,QACvC,OAAO;AAAA,MACT;AAAA,MACA,KAAK;AAAA,QACH,KAAK;AAAA,QACL,eAAe;AAAA,QACf,OAAO;AAAA,MACT;AAAA,MACA;AAAA,MACA,KAAK;AAAA,QACH,YAAY;AAAA,QACZ;AAAA,QACA;AAAA,QACA,WAAWA,QAAO,QAAQ,SAAS;AAAA,QACnC,SAAS,OAAO;AAAA,QAChB;AAAA,QACA,WAAW,oBAAoB,SAAS;AAAA,MAC1C;AAAA,MACA,aAAa,KAAK,IAAI;AAAA,IACxB;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAKA,MAAc,wBACZ,eACA,OACA,WACA,cACA,SACA,WACA,eAC6B;AAE7B,UAAM,SAAS,OAAO,cAAc,MAAM,GAAG,EAAE;AAC/C,UAAM,QAAQ,OAAO,OAAO,cAAc,MAAM,IAAI,GAAG,CAAC;AACxD,UAAM,WAAW,OAAO,cAAc,MAAM,GAAG;AAE/C,UAAM,gBAAgB,MAAM,KAAK,iBAAiB,MAAM;AACxD,UAAM,QAAQ,gBAAgB,OAAO;AACrC,UAAM,eAAe,KAAK,mBAAmB,QAAQ;AAErD,UAAM,UAA0B;AAAA,MAC9B,QAAQ;AAAA,MACR,OAAO,MAAM,KAAK,aAAaA,QAAO,aAAa,KAAK;AAAA,MACxD;AAAA,MACA,cAAc,cAAc;AAAA,MAC5B,aAAa,cAAc;AAAA,MAC3B;AAAA,IACF;AAEA,UAAM,WAAW,MAAM,KAAK,mBAAmB,QAAQ,OAAO,UAAU,aAAa;AAErF,WAAO;AAAA,MACL,QAAQ;AAAA,MACR,OAAO;AAAA,MACP,aAAa,QAAQ,cAAc,QAAQ,UAAU,OAAO,cAAc,OAAO,cAAc,SAAS;AAAA,MACxG;AAAA,MACA,OAAO;AAAA,QACL,SAAS;AAAA,QACT,WAAW,gBAAgB,YAAY;AAAA,QACvC;AAAA,MACF;AAAA,MACA,KAAK;AAAA,QACH,KAAK;AAAA,QACL,eAAe;AAAA,QACf,OAAO;AAAA,MACT;AAAA,MACA;AAAA,MACA,KAAK;AAAA,QACH,YAAY;AAAA,QACZ;AAAA,QACA;AAAA,QACA,WAAWA,QAAO,QAAQ,SAAS;AAAA,QACnC;AAAA,QACA;AAAA,QACA,WAAW,oBAAoB,SAAS;AAAA,MAC1C;AAAA,MACA,aAAa,KAAK,IAAI;AAAA,IACxB;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAKA,MAAc,uBACZ,eACA,OACA,WACA,cACA,SACA,WACA,eAC6B;AAE7B,UAAM,aAAa,SAAS,cAAc,MAAM,GAAG,CAAC,GAAG,EAAE;AACzD,UAAM,aAAa,OAAO,cAAc,MAAM,CAAC;AAE/C,UAAM,QAAQ,gBAAgB,OAAO;AACrC,UAAM,iBAAiB,kBAAkB,UAAU;AAEnD,UAAM,UAAyB;AAAA,MAC7B;AAAA,MACA;AAAA,MACA,aAAa,KAAK,qBAAqB,YAAY,UAAU;AAAA,MAC7D,SAAS,KAAK,mBAAmB,YAAY,UAAU;AAAA,IACzD;AAEA,UAAM,WAA0B,CAAC;AAAA,MAC/B,OAAO;AAAA,MACP,MAAM;AAAA,MACN,SAAS;AAAA,MACT,SAAS,aAAa,cAAc;AAAA,IACtC,CAAC;AAED,WAAO;AAAA,MACL,QAAQ;AAAA,MACR,OAAO;AAAA,MACP,aAAa,+BAA+B,cAAc;AAAA,MAC1D;AAAA,MACA,OAAO;AAAA,QACL,SAAS;AAAA,QACT,WAAW,gBAAgB,YAAY;AAAA,QACvC;AAAA,MACF;AAAA,MACA,KAAK;AAAA,QACH,KAAK;AAAA,QACL,eAAe;AAAA,QACf,OAAO;AAAA,MACT;AAAA,MACA;AAAA,MACA,KAAK;AAAA,QACH,YAAY;AAAA,QACZ;AAAA,QACA;AAAA,QACA,WAAWA,QAAO,QAAQ,SAAS;AAAA,QACnC;AAAA,QACA;AAAA,QACA,WAAW,oBAAoB,SAAS;AAAA,MAC1C;AAAA,MACA,aAAa,KAAK,IAAI;AAAA,IACxB;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAKQ,2BACN,UACA,cACA,SACoB;AACpB,UAAM,QAAQ,gBAAgB,OAAO;AAErC,WAAO;AAAA,MACL,QAAQ;AAAA,MACR,OAAO;AAAA,MACP,aAAa;AAAA,MACb,SAAS;AAAA,MACT,OAAO;AAAA,QACL,SAAS;AAAA,QACT,WAAW,gBAAgB,YAAY;AAAA,QACvC;AAAA,MACF;AAAA,MACA,KAAK;AAAA,QACH,KAAK,SAAS;AAAA,QACd,eAAe;AAAA,QACf,OAAO,SAAS;AAAA,MAClB;AAAA,MACA,UAAU,CAAC;AAAA,QACT,OAAO;AAAA,QACP,MAAM;AAAA,QACN,SAAS;AAAA,QACT,SAAS,gBAAgB,KAAK,iBAAiB,SAAS,aAAa,CAAC;AAAA,MACxE,CAAC;AAAA,MACD,KAAK;AAAA,QACH,YAAY,KAAK,iBAAiB,SAAS,aAAa;AAAA,QACxD,eAAe,SAAS;AAAA,QACxB,OAAO,SAAS;AAAA,QAChB,WAAWA,QAAO,QAAQ,SAAS,SAAS;AAAA,QAC5C;AAAA,QACA,WAAW,SAAS;AAAA,QACpB,WAAW,oBAAoB,SAAS,SAAS;AAAA,MACnD;AAAA,MACA,aAAa,KAAK,IAAI;AAAA,IACxB;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,cACJ,UACA,cACA,cAC6B;AAC7B,UAAM,EAAE,QAAQ,eAAe,OAAO,WAAW,UAAU,IAAI;AAC/D,UAAM,UAAU,qBAAqB,aAAa;AAElD,UAAM,QAAQ,MAAM,KAAK,aAAa,QAAQ,OAAO,QAAQ,MAAM;AACnE,UAAM,YAAY,MAAM,KAAK,iBAAiB,QAAQ,SAAS;AAC/D,UAAM,QAAQ,gBAAgB,OAAO,WAAW;AAEhD,UAAM,UAA2B;AAAA,MAC/B;AAAA,MACA;AAAA,MACA;AAAA,IACF;AAEA,UAAM,WAAW,MAAM,KAAK,oBAAoB,QAAQ,OAAO,SAAS;AAExE,WAAO;AAAA,MACL,QAAQ;AAAA,MACR,OAAO,QAAQ,MAAM,MAAM;AAAA,MAC3B,aAAa,QAAQ,MAAM,MAAM,IAAI,MAAM,MAAM,OAAO,UAAU,OAAO,UAAU,SAAS;AAAA,MAC5F;AAAA,MACA,OAAO;AAAA,QACL,SAAS;AAAA,QACT,WAAW,gBAAgB,YAAY;AAAA,QACvC,OAAO,gBAAgB,YAAY;AAAA,MACrC;AAAA,MACA,KAAK;AAAA,QACH,KAAK,SAAS;AAAA,QACd,eAAe;AAAA;AAAA,QACf,OAAO,SAAS;AAAA,MAClB;AAAA,MACA;AAAA,MACA,KAAK;AAAA,QACH,YAAY;AAAA,QACZ;AAAA,QACA;AAAA,QACA,WAAWA,QAAO,QAAQ,SAAS;AAAA,QACnC,SAAS,OAAO;AAAA,QAChB;AAAA,QACA,WAAW,oBAAoB,SAAS;AAAA,MAC1C;AAAA,MACA,aAAa,KAAK,IAAI;AAAA,IACxB;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,YACJ,QACA,eACA,OACA,WACA,cACA,cACA,WACA,eAC6B;AAC7B,UAAM,UAAU,mBAAmB,aAAa;AAEhD,UAAM,QAAQ,MAAM,KAAK,aAAa,QAAQ,OAAO,QAAQ,MAAM;AACnE,UAAM,cAAc,gBAAgB,OAAO,WAAW;AACtD,UAAM,mBAAmB,gBAAgB,OAAO,gBAAgB;AAChE,UAAM,YAAY,MAAM,KAAK,iBAAiB,QAAQ,SAAS;AAE/D,UAAM,UAAyB;AAAA,MAC7B;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA,eAAe,KAAK,mBAAmB,YAAY,IAAI,iBAAiB,EAAE;AAAA,IAC5E;AAEA,UAAM,WAAW,MAAM,KAAK,kBAAkB,QAAQ,OAAO,aAAa,gBAAgB;AAE1F,WAAO;AAAA,MACL,QAAQ;AAAA,MACR,OAAO,UAAU,MAAM,MAAM;AAAA,MAC7B,aAAa,UAAU,MAAM,MAAM,IAAI,MAAM,MAAM,SAAS,YAAY,IAAI,OAAO,iBAAiB,IAAI;AAAA,MACxG;AAAA,MACA,OAAO;AAAA,QACL,SAAS;AAAA,QACT,WAAW,gBAAgB,YAAY;AAAA,QACvC,OAAO,gBAAgB,YAAY;AAAA,MACrC;AAAA,MACA,KAAK;AAAA,QACH,KAAK;AAAA,QACL,eAAe;AAAA,QACf,OAAO;AAAA,MACT;AAAA,MACA;AAAA,MACA,KAAK;AAAA,QACH,YAAY;AAAA,QACZ;AAAA,QACA;AAAA,QACA,WAAWA,QAAO,QAAQ,SAAS;AAAA,QACnC,SAAS,OAAO;AAAA,QAChB;AAAA,QACA,WAAW,oBAAoB,SAAS;AAAA,MAC1C;AAAA,MACA,aAAa,KAAK,IAAI;AAAA,IACxB;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,aACJ,QACA,OACA,UACA,SACA,OACA,WACA,cACA,WACA,eAC6B;AAC7B,UAAM,kBAAkB,MAAM,KAAK,iBAAiB,MAAM;AAC1D,UAAM,QAAQ,gBAAgB,OAAO;AACrC,UAAM,aAAa,MAAM,KAAK,aAAaA,QAAO,aAAa,KAAK;AAGpE,UAAM,eAAe,KAAK,mBAAmB,QAAQ;AAErD,UAAM,UAA0B;AAAA,MAC9B,QAAQ;AAAA,MACR,OAAO;AAAA,MACP;AAAA,MACA,cAAc,cAAc;AAAA,MAC5B,aAAa,cAAc;AAAA,MAC3B;AAAA,IACF;AAEA,UAAM,WAAW,MAAM,KAAK,mBAAmB,QAAQ,OAAO,UAAU,eAAe;AAEvF,UAAM,QAAQ,cAAc,OACxB,QAAQ,aAAa,IAAI,KACzB;AAEJ,WAAO;AAAA,MACL,QAAQ;AAAA,MACR;AAAA,MACA,aAAa,4BAA4B,gBAAgB,OAAO,gBAAgB,SAAS;AAAA,MACzF;AAAA,MACA,OAAO;AAAA,QACL,SAAS;AAAA,QACT,WAAW,gBAAgB,YAAY;AAAA,QACvC;AAAA,MACF;AAAA,MACA,KAAK;AAAA,QACH,KAAK;AAAA,QACL,eAAe;AAAA,QACf,OAAO;AAAA,MACT;AAAA,MACA;AAAA,MACA,KAAK;AAAA,QACH,YAAY;AAAA,QACZ,eAAe;AAAA,QACf;AAAA,QACA,WAAWA,QAAO,QAAQ,SAAS;AAAA,QACnC;AAAA,QACA;AAAA,QACA,WAAW,oBAAoB,SAAS;AAAA,MAC1C;AAAA,MACA,aAAa,KAAK,IAAI;AAAA,IACxB;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,YACJ,YACA,YACA,SACA,OACA,WACA,cACA,WACA,eAC6B;AAC7B,UAAM,QAAQ,gBAAgB,OAAO;AACrC,UAAM,iBAAiB,kBAAkB,UAAU;AAEnD,UAAM,UAAyB;AAAA,MAC7B;AAAA,MACA;AAAA,MACA,aAAa,KAAK,qBAAqB,YAAY,UAAU;AAAA,MAC7D,SAAS,KAAK,mBAAmB,YAAY,UAAU;AAAA,IACzD;AAEA,UAAM,WAA0B,CAAC;AAAA,MAC/B,OAAO;AAAA,MACP,MAAM;AAAA,MACN,SAAS;AAAA,IACX,CAAC;AAED,WAAO;AAAA,MACL,QAAQ;AAAA,MACR,OAAO;AAAA,MACP,aAAa,+BAA+B,cAAc;AAAA,MAC1D;AAAA,MACA,OAAO;AAAA,QACL,SAAS;AAAA,QACT,WAAW,gBAAgB,YAAY;AAAA,QACvC;AAAA,MACF;AAAA,MACA,KAAK;AAAA,QACH,KAAK;AAAA,QACL,eAAe;AAAA,QACf,OAAO;AAAA,MACT;AAAA,MACA;AAAA,MACA,KAAK;AAAA,QACH,YAAY;AAAA,QACZ,eAAe;AAAA,QACf;AAAA,QACA,WAAWA,QAAO,QAAQ,SAAS;AAAA,QACnC;AAAA,QACA;AAAA,QACA,WAAW,oBAAoB,SAAS;AAAA,MAC1C;AAAA,MACA,aAAa,KAAK,IAAI;AAAA,IACxB;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASA,MAAc,aAAa,SAAiB,QAAuC;AACjF,UAAM,oBAAoB,QAAQ,YAAY;AAC9C,UAAM,WAAWD,eAAc,OAAO;AAGtC,QAAI,YAAY,KAAK,cAAc,IAAI,iBAAiB;AACxD,QAAI,CAAC,aAAa,UAAU;AAC1B,kBAAY,KAAK,cAAc,IAAI,QAAQ;AAAA,IAC7C;AAEA,UAAM,WAAW,WAAW,YAAY;AACxC,UAAM,SAAS,WAAW,WAAW,WAAW,QAAQ;AACxD,UAAM,kBAAkBD,cAAa,QAAQ,QAAQ;AAGrD,QAAI;AACJ,QAAI,KAAK,OAAO,aAAa;AAC3B,UAAI;AACF,cAAM,QAAQ,MAAM,KAAK,OAAO,YAAY,OAAO;AACnD,YAAI,UAAU,MAAM;AAClB,gBAAM,YAAY,WAAW,eAAe;AAC5C,qBAAW,KAAK,YAAY,OAAO,QAAQ,CAAC,CAAC;AAAA,QAC/C;AAAA,MACF,QAAQ;AAAA,MAER;AAAA,IACF;AAEA,WAAO;AAAA,MACL;AAAA,MACA,QAAQ;AAAA,MACR,WAAW;AAAA,MACX,SAAS,WAAWE,QAAO,cAAc;AAAA,MACzC;AAAA,MACA;AAAA,MACA;AAAA,IACF;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAKA,MAAc,iBAAiB,SAA4C;AACzE,UAAM,YAAY,gBAAgB,OAAO;AACzC,QAAI;AACJ,QAAI;AACJ,QAAI;AACJ,QAAI;AAGJ,QAAI,KAAK,OAAO,iBAAiB;AAC/B,cAAQ,KAAK,OAAO,gBAAgB,IAAI,QAAQ,YAAY,CAAC;AAAA,IAC/D;AAGA,QAAI,KAAK,OAAO,aAAa;AAC3B,UAAI;AACF,cAAM,WAAW,MAAM,KAAK,OAAO,YAAY,OAAO;AACtD,YAAI,UAAU;AACZ,gBAAM;AAAA,QACR;AAAA,MACF,QAAQ;AAAA,MAER;AAAA,IACF;AAGA,QAAI,KAAK,OAAO,kBAAkB;AAChC,UAAI;AACF,qBAAa,MAAM,KAAK,OAAO,iBAAiB,OAAO;AAAA,MACzD,QAAQ;AAAA,MAER;AAAA,IACF;AAGA,QAAI,KAAK,OAAO,oBAAoB;AAClC,uBAAiB,CAAC,KAAK,OAAO,mBAAmB,IAAI,QAAQ,YAAY,CAAC;AAAA,IAC5E;AAEA,WAAO;AAAA,MACL;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,IACF;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASA,MAAc,oBACZ,SACA,OACA,WACwB;AACxB,UAAM,WAA0B,CAAC;AAGjC,QAAI,UAAU,gBAAgB;AAC5B,eAAS,KAAK;AAAA,QACZ,OAAO;AAAA,QACP,MAAM;AAAA,QACN,SAAS;AAAA,QACT,SAAS;AAAA,MACX,CAAC;AAAA,IACH;AAGA,QAAI,KAAK,OAAO,yBAAyB;AACvC,YAAM,YAAY,KAAK,OAAO,0BAA0B;AACxD,UAAI,MAAM,YAAY,WAAW;AAC/B,iBAAS,KAAK;AAAA,UACZ,OAAO;AAAA,UACP,MAAM;AAAA,UACN,SAAS;AAAA,UACT,SAAS,WAAW,MAAM,MAAM,IAAI,MAAM,MAAM;AAAA,QAClD,CAAC;AAAA,MACH;AAAA,IACF;AAGA,QAAI,UAAU,YAAY;AACxB,eAAS,KAAK;AAAA,QACZ,OAAO;AAAA,QACP,MAAM;AAAA,QACN,SAAS;AAAA,MACX,CAAC;AAAA,IACH;AAGA,UAAM,YAAY,KAAK,cAAc,IAAI,MAAM,QAAQ,YAAY,CAAC;AACpE,QAAI,CAAC,WAAW,UAAU;AACxB,eAAS,KAAK;AAAA,QACZ,OAAO;AAAA,QACP,MAAM;AAAA,QACN,SAAS;AAAA,QACT,SAAS;AAAA,MACX,CAAC;AAAA,IACH;AAEA,WAAO;AAAA,EACT;AAAA;AAAA;AAAA;AAAA,EAKA,MAAc,kBACZ,SACA,OACA,aACA,kBACwB;AACxB,UAAM,WAA0B,CAAC;AAGjC,aAAS,KAAK;AAAA,MACZ,OAAO;AAAA,MACP,MAAM;AAAA,MACN,SAAS,uCAAuC,YAAY,IAAI,OAAO,iBAAiB,IAAI;AAAA,MAC5F,SAAS;AAAA,IACX,CAAC;AAGD,QAAI,KAAK,OAAO,yBAAyB;AACvC,YAAM,YAAY,KAAK,OAAO,0BAA0B;AACxD,UAAI,MAAM,YAAY,WAAW;AAC/B,iBAAS,KAAK;AAAA,UACZ,OAAO;AAAA,UACP,MAAM;AAAA,UACN,SAAS;AAAA,QACX,CAAC;AAAA,MACH;AAAA,IACF;AAEA,WAAO;AAAA,EACT;AAAA;AAAA;AAAA;AAAA,EAKA,MAAc,mBACZ,SACA,OACA,WACA,WACwB;AACxB,UAAM,WAA0B,CAAC;AAGjC,aAAS,KAAK;AAAA,MACZ,OAAO;AAAA,MACP,MAAM;AAAA,MACN,SAAS;AAAA,MACT,SAAS;AAAA,IACX,CAAC;AAGD,QAAI,UAAU,gBAAgB;AAC5B,eAAS,KAAK;AAAA,QACZ,OAAO;AAAA,QACP,MAAM;AAAA,QACN,SAAS;AAAA,MACX,CAAC;AAAA,IACH;AAGA,QAAI,QAAQ,IAAI;AACd,eAAS,KAAK;AAAA,QACZ,OAAO;AAAA,QACP,MAAM;AAAA,QACN,SAAS,0BAA0BF,cAAa,OAAO,EAAE,CAAC;AAAA,MAC5D,CAAC;AAAA,IACH;AAEA,WAAO;AAAA,EACT;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASQ,mBAAmB,cAAsB,YAA4B;AAG3E,WAAO;AAAA,EACT;AAAA;AAAA;AAAA;AAAA,EAKQ,mBAAmB,UAA0E;AACnG,QAAI,SAAS,SAAS,GAAI,QAAO;AAGjC,UAAM,kBAA0C;AAAA,MAC9C,cAAc;AAAA,MACd,cAAc;AAAA,MACd,cAAc;AAAA,MACd,cAAc;AAAA,MACd,cAAc;AAAA,MACd,cAAc;AAAA,MACd,cAAc;AAAA,MACd,cAAc;AAAA,IAChB;AAEA,UAAM,WAAW,SAAS,MAAM,GAAG,EAAE,EAAE,YAAY;AACnD,UAAM,OAAO,gBAAgB,QAAQ;AAErC,QAAI,MAAM;AACR,aAAO,EAAE,MAAM,MAAM,CAAC,EAAE;AAAA,IAC1B;AAEA,WAAO;AAAA,EACT;AAAA;AAAA;AAAA;AAAA,EAKQ,qBAAqB,YAAoB,aAA6B;AAC5E,UAAM,OAAO,kBAAkB,UAAU;AACzC,WAAO,iCAAiC,KAAK,YAAY,CAAC;AAAA,EAC5D;AAAA;AAAA;AAAA;AAAA,EAKQ,mBAAmB,YAAoB,YAAgE;AAE7G,WAAO,CAAC;AAAA,MACN,OAAO,kBAAkB,UAAU;AAAA,MACnC,UAAU,WAAW,SAAS,KAAK,GAAG,WAAW,MAAM,GAAG,EAAE,CAAC,QAAQ;AAAA,IACvE,CAAC;AAAA,EACH;AAAA;AAAA;AAAA;AAAA,EAKA,aAAa,QAAgD;AAC3D,SAAK,SAAS,EAAE,GAAG,KAAK,QAAQ,GAAG,OAAO;AAC1C,QAAI,OAAO,aAAa;AACtB,WAAK,gBAAgB,OAAO;AAAA,IAC9B;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAKA,cAAc,SAAiB,MAAuB;AACpD,SAAK,cAAc,IAAI,QAAQ,YAAY,GAAG,IAAI;AAAA,EACpD;AAAA;AAAA;AAAA;AAAA,EAKA,kBAAkB,SAAiB,OAAqB;AACtD,QAAI,CAAC,KAAK,OAAO,iBAAiB;AAChC,WAAK,OAAO,kBAAkB,oBAAI,IAAI;AAAA,IACxC;AACA,SAAK,OAAO,gBAAgB,IAAI,QAAQ,YAAY,GAAG,KAAK;AAAA,EAC9D;AACF;AA2CO,SAAS,iBAAiB,SAAoD;AACnF,QAAM,cAAc,QAAQ,SAAS,OAAsB,CAAC,KAAK,MAAM;AACrE,UAAM,QAAgC,EAAE,UAAU,GAAG,MAAM,GAAG,SAAS,GAAG,MAAM,EAAE;AAClF,QAAI,QAAQ,KAAM,QAAO,EAAE;AAC3B,QAAI,MAAM,EAAE,KAAK,IAAI,MAAM,GAAG,GAAG;AAC/B,aAAO,EAAE;AAAA,IACX;AACA,WAAO;AAAA,EACT,GAAG,IAAI;AAEP,SAAO;AAAA,IACL,WAAW,GAAG,QAAQ,WAAW,IAAI,QAAQ,MAAM;AAAA,IACnD,YAAW,oBAAI,KAAK,GAAE,YAAY;AAAA,IAClC,YAAY,QAAQ;AAAA,IACpB,gBAAgB,QAAQ;AAAA,IACxB,sBAAsB,QAAQ;AAAA,IAC9B,kBAAkB,QAAQ,SAAS;AAAA,IACnC,kBAAkB;AAAA,IAClB,qBAAqB,CAAC,CAAC,QAAQ;AAAA,IAC/B,aAAa,QAAQ,KAAK,gBAAgBE,QAAO,UAAU,QAAQ,IAAI,aAAa,IAAI;AAAA,IACxF,WAAW,QAAQ,KAAK,aAAa;AAAA,IACrC,aAAa,QAAQ,KAAK,WAAW;AAAA,IACrC,kBAAkB,QAAQ,IAAI;AAAA,EAChC;AACF;AAQO,SAAS,sBACd,SACA,SAAiD,CAAC,UAAU;AAE1D,UAAQ,KAAK,sBAAsB,KAAK,UAAU,KAAK,CAAC;AAC1D,GACuB;AACvB,QAAM,QAAQ,iBAAiB,OAAO;AACtC,SAAO,KAAK;AACZ,SAAO;AACT;AASO,SAAS,wBAAwB,QAAqD;AAC3F,SAAO,IAAI,kBAAkB,MAAM;AACrC;;;AEzkCA,SAAS,UAAAC,gBAAc;;;ACoPhB,IAAM,cAAc;AAAA;AAAA,EAEzB,aAAa;AAAA;AAAA,EAEb,OAAO;AAAA;AAAA,EAEP,WAAW;AAAA;AAAA,EAEX,iBAAiB;AAAA;AAAA,EAEjB,aAAa;AAAA;AAAA,EAEb,gBAAgB;AAClB;AAkEO,IAAM,gBAA+B;AAAA,EAC1C;AAAA,IACE,IAAI;AAAA,IACJ,MAAM;AAAA,IACN,aAAa;AAAA,IACb,eAAe;AAAA,IACf,qBAAqB;AAAA,IACrB,MAAM;AAAA,IACN,gBAAgB;AAAA,EAClB;AAAA,EACA;AAAA,IACE,IAAI;AAAA,IACJ,MAAM;AAAA,IACN,aAAa;AAAA,IACb,eAAe;AAAA,IACf,qBAAqB;AAAA,IACrB,MAAM;AAAA,IACN,gBAAgB;AAAA,EAClB;AAAA,EACA;AAAA,IACE,IAAI;AAAA,IACJ,MAAM;AAAA,IACN,aAAa;AAAA,IACb,eAAe;AAAA,IACf,qBAAqB;AAAA,IACrB,MAAM;AAAA,IACN,gBAAgB;AAAA,EAClB;AAAA,EACA;AAAA,IACE,IAAI;AAAA,IACJ,MAAM;AAAA,IACN,aAAa;AAAA,IACb,eAAe;AAAA;AAAA,IACf,qBAAqB;AAAA,IACrB,MAAM;AAAA,IACN,gBAAgB;AAAA,EAClB;AACF;AAmBO,SAAS,eAAe,IAA6B;AAC1D,QAAM,eAAe,KAAK,IAAI,GAAG,KAAK,MAAM,KAAK,GAAI,CAAC;AACtD,QAAM,QAAQ,KAAK,MAAM,eAAe,IAAI;AAC5C,QAAM,UAAU,KAAK,MAAO,eAAe,OAAQ,EAAE;AACrD,QAAM,UAAU,eAAe;AAE/B,MAAI;AACJ,MAAI,QAAQ,GAAG;AACb,gBAAY,GAAG,KAAK,KAAK,OAAO;AAAA,EAClC,WAAW,UAAU,GAAG;AACtB,gBAAY,GAAG,OAAO,KAAK,OAAO;AAAA,EACpC,OAAO;AACL,gBAAY,GAAG,OAAO;AAAA,EACxB;AAEA,SAAO,EAAE,OAAO,SAAS,SAAS,UAAU;AAC9C;AAKO,SAAS,oBAAoB,OAAe,OAAuB;AACxE,MAAI,UAAU,GAAI,QAAO;AAEzB,QAAM,aAAa,OAAQ,QAAQ,SAAU,KAAK,IAAI;AACtD,SAAO,KAAK,IAAI,KAAK,KAAK,IAAI,GAAG,UAAU,CAAC;AAC9C;AAKO,SAAS,kBACd,QACA,WAAmB,IACnB,SAAiB,OACT;AACR,QAAM,UAAU,OAAO,OAAO,QAAQ;AACtC,QAAM,QAAQ,SAAS;AACvB,QAAM,WAAW,SAAS;AAG1B,QAAM,cAAc,SAAS,SAAS,EAAE,SAAS,UAAU,GAAG,EAAE,MAAM,GAAG,CAAC;AAC1E,QAAM,kBAAkB,YAAY,QAAQ,OAAO,EAAE;AAErD,QAAM,SAAS,kBACX,GAAG,MAAM,eAAe,CAAC,IAAI,eAAe,KAC5C,MAAM,eAAe;AAEzB,SAAO,GAAG,MAAM,IAAI,MAAM;AAC5B;;;ADrZA,IAAMC,aAAY;AAAA,EAChB;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF;AAOA,IAAM,cAAc;AAGpB,IAAM,SAAS,cAAc;AA2BtB,IAAM,wBAAN,MAA4B;AAAA,EACzB;AAAA,EACA,QAA+D,oBAAI,IAAI;AAAA,EACvE,iBAA+C,CAAC;AAAA,EAExD,YAAY,SAAsC,CAAC,GAAG;AACpD,SAAK,SAAS;AAAA,MACZ,iBAAiB,OAAO,mBAAmB;AAAA,MAC3C,eAAe,OAAO,iBAAiB;AAAA,MACvC,SAAS,OAAO,WAAW,CAAC;AAAA,MAC5B,UAAU,OAAO,YAAY;AAAA;AAAA,MAC7B,eAAe,OAAO,kBAAkB,MAAM;AAAA,MAAC;AAAA,IACjD;AAEA,QAAI,OAAO,eAAe;AACxB,WAAK,eAAe,KAAK,OAAO,aAAa;AAAA,IAC/C;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAYA,MAAM,kBACJ,cACA,SACA,QACyB;AAEzB,UAAM,WAAW,GAAG,OAAO,IAAI,aAAa,YAAY,CAAC;AACzD,UAAM,SAAS,KAAK,MAAM,IAAI,QAAQ;AACtC,QAAI,UAAU,KAAK,IAAI,IAAI,OAAO,QAAQ;AACxC,aAAO,OAAO;AAAA,IAChB;AAEA,UAAM,WAAW,KAAK,YAAY,SAAS,MAAM;AACjD,UAAM,QAAQ,IAAIC,SAAO,SAAS,cAAcD,YAAW,QAAQ;AAGnE,UAAM,CAAC,YAAY,gBAAgB,UAAU,MAAM,IAAI,MAAM,QAAQ,IAAI;AAAA,MACvE,MAAM,WAAW;AAAA,MACjB,MAAM,eAAe;AAAA,MACrB,MAAM,SAAS;AAAA,MACf,MAAM,OAAO;AAAA,IACf,CAAC;AAED,UAAM,MAAM,KAAK,IAAI;AACrB,UAAM,aAAa,OAAO,QAAQ,IAAI;AACtC,UAAM,WAAW,aAAa;AAG9B,QAAI,iBAAiB;AACrB,QAAI,qBAAqB,IAAI,KAAK,QAAQ;AAC1C,QAAI,iBAAiB,WAAW;AAEhC,QAAI,OAAO,UAAU;AAEnB,uBAAiB;AAEjB,YAAM,iBAAiB,KAAK,OAAO,MAAM,cAAc,MAAM;AAC7D,YAAM,eAAe,cAAc,iBAAiB,KAAK;AACzD,2BAAqB,IAAI,KAAK,YAAY;AAC1C,uBAAiB,eAAe;AAAA,IAClC;AAEA,UAAM,iBAAiB,eAAe,KAClC,OAAO,oEAAoE,IAC3E,aAAa,iBACX,aAAa,iBACb;AAEN,UAAM,SAAyB;AAAA,MAC7B;AAAA,MACA,YAAY;AAAA,MACZ;AAAA,MACA,cAAc;AAAA,MACd,gBAAgB,KAAK,IAAI,GAAG,cAAc;AAAA,MAC1C,kBAAkB;AAAA;AAAA,MAClB,UAAU;AAAA,MACV,aAAa,oBAAI,KAAK;AAAA,MACtB;AAAA,IACF;AAGA,SAAK,MAAM,IAAI,UAAU;AAAA,MACvB,MAAM;AAAA,MACN,QAAQ,MAAM,KAAK,OAAO;AAAA,IAC5B,CAAC;AAED,WAAO;AAAA,EACT;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,2BACJ,cACA,SACA,SAKkC;AAClC,UAAM,SAAS,MAAM,KAAK,kBAAkB,cAAc,SAAS,SAAS,MAAM;AAClF,UAAM,WAAW,SAAS,YAAY,KAAK,OAAO;AAClD,UAAM,SAAS,SAAS,UAAU,KAAK,OAAO;AAE9C,WAAO,KAAK,aAAa,QAAQ,UAAU,MAAM;AAAA,EACnD;AAAA;AAAA;AAAA;AAAA,EAKA,aACE,QACA,WAAmB,IACnB,SAAiB,OACQ;AACzB,UAAM,gBAAgB,OAAO,aAAa;AAG1C,UAAM,WAAW,CAAC,QAAwB;AACxC,YAAM,UAAU,OAAO,OAAO,QAAQ;AACtC,aAAO,OAAO,MAAM,SAAS,OAAO,IAAI;AAAA,IAC1C;AAEA,WAAO;AAAA,MACL,YAAY,gBACR,kBAAkB,OAAO,YAAY,UAAU,MAAM,IACrD;AAAA,MACJ,iBAAiB,SAAS,OAAO,UAAU;AAAA,MAC3C,YAAY,kBAAkB,OAAO,YAAY,UAAU,MAAM;AAAA,MACjE,iBAAiB,SAAS,OAAO,UAAU;AAAA,MAC3C,gBAAgB,gBACZ,kBAAkB,OAAO,gBAAgB,UAAU,MAAM,IACzD;AAAA,MACJ,qBAAqB,SAAS,OAAO,cAAc;AAAA,MACnD,qBAAqB,gBACjB,oBAAoB,OAAO,YAAY,OAAO,UAAU,IACxD;AAAA,MACJ,gBAAgB,eAAe,OAAO,cAAc,EAAE;AAAA,MACtD,kBAAkB,OAAO,mBAAmB,KACxC,kBAAkB,OAAO,kBAAkB,UAAU,MAAM,IAC3D;AAAA,MACJ,uBAAuB,SAAS,OAAO,gBAAgB;AAAA,MACvD,UAAU,OAAO;AAAA,MACjB;AAAA,MACA,qBAAqB,OAAO,mBAAmB;AAAA,IACjD;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAaA,MAAM,sBACJ,cACA,SACA,QACA,SAC2B;AAC3B,UAAM,SAAS,MAAM,KAAK,kBAAkB,cAAc,SAAS,SAAS,MAAM;AAGlF,QAAI,OAAO,UAAU;AACnB,aAAO;AAAA,QACL,SAAS;AAAA,QACT,QAAQ;AAAA,QACR,SAAS;AAAA,QACT,aAAa;AAAA,UACX;AAAA,YACE,QAAQ;AAAA,YACR,OAAO;AAAA,UACT;AAAA,QACF;AAAA,MACF;AAAA,IACF;AAGA,QAAI,OAAO,mBAAmB,MAAM,SAAS,OAAO,kBAAkB;AACpE,aAAO;AAAA,QACL,SAAS;AAAA,QACT,QAAQ;AAAA,QACR,SAAS,gDAAgD,kBAAkB,OAAO,kBAAkB,KAAK,OAAO,iBAAiB,KAAK,OAAO,aAAa,CAAC;AAAA,QAC3J,eAAe,OAAO;AAAA,QACtB,cAAc,SAAS,OAAO;AAAA,QAC9B,aAAa;AAAA,UACX;AAAA,YACE,QAAQ;AAAA,YACR,OAAO,QAAQ,kBAAkB,OAAO,kBAAkB,KAAK,OAAO,iBAAiB,KAAK,OAAO,aAAa,CAAC;AAAA,YACjH,MAAM,EAAE,QAAQ,OAAO,iBAAiB;AAAA,UAC1C;AAAA,UACA;AAAA,YACE,QAAQ;AAAA,YACR,OAAO;AAAA,UACT;AAAA,QACF;AAAA,MACF;AAAA,IACF;AAGA,QAAI,OAAO,aAAa,IAAI;AAC1B,YAAM,aAAa,OAAO,aAAa;AAEvC,UAAI,aAAa,OAAO,YAAY;AAClC,cAAM,eAAe,aAAa,OAAO;AACzC,cAAM,cAA0C,CAAC;AAGjD,YAAI,OAAO,iBAAiB,IAAI;AAC9B,sBAAY,KAAK;AAAA,YACf,QAAQ;AAAA,YACR,OAAO,QAAQ,kBAAkB,OAAO,gBAAgB,KAAK,OAAO,iBAAiB,KAAK,OAAO,aAAa,CAAC;AAAA,YAC/G,MAAM,EAAE,QAAQ,OAAO,eAAe;AAAA,UACxC,CAAC;AAAA,QACH;AAEA,oBAAY,KAAK;AAAA,UACf,QAAQ;AAAA,UACR,OAAO;AAAA,UACP,MAAM,EAAE,UAAU,WAAW;AAAA,QAC/B,CAAC;AAED,oBAAY,KAAK;AAAA,UACf,QAAQ;AAAA,UACR,OAAO,QAAQ,eAAe,OAAO,cAAc,EAAE,SAAS;AAAA,UAC9D,MAAM,EAAE,YAAY,OAAO,eAAe;AAAA,QAC5C,CAAC;AAED,eAAO;AAAA,UACL,SAAS;AAAA,UACT,QAAQ;AAAA,UACR,SAAS,uDAAuD,kBAAkB,OAAO,YAAY,KAAK,OAAO,iBAAiB,KAAK,OAAO,aAAa,CAAC,OAAO,kBAAkB,OAAO,YAAY,KAAK,OAAO,iBAAiB,KAAK,OAAO,aAAa,CAAC;AAAA,UAC/P,eAAe,OAAO;AAAA,UACtB;AAAA,UACA,UAAU,OAAO;AAAA,UACjB;AAAA,QACF;AAAA,MACF;AAAA,IACF;AAEA,WAAO;AAAA,MACL,SAAS;AAAA,MACT,SAAS;AAAA,IACX;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAaA,wBAAwB,UAA0B;AAGhD,UAAM,aAAaC,SAAO,aAAaA,SAAO,QAAQ,QAAQ,GAAG,EAAE;AACnE,WAAO,mBAAmB,YAAY,aAAa,UAAU;AAAA,EAC/D;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,oBAA4B;AAE1B,UAAM,aAAaA,SAAO,QAAQ,GAAG,CAAC;AACtC,WAAO,mBAAmB,YAAY,OAAO,UAAU;AAAA,EACzD;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,sBAA8B;AAE5B,UAAM,eAAeA,SAAO,QAAQ,GAAG,CAAC;AACxC,WAAO,mBAAmB,YAAY,OAAO,YAAY;AAAA,EAC3D;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,oBAAoB,QAAqC;AACvD,QAAI,CAAC,OAAO,cAAc,OAAO,eAAe,IAAI;AAElD,aAAO;AAAA,IACT;AACA,WAAO,KAAK,wBAAwB,OAAO,UAAU;AAAA,EACvD;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAaA,MAAM,sBACJ,cACA,SACA,QAAgB,IACgB;AAIhC,YAAQ,IAAI,+EAA+E,YAAY,YAAY,OAAO,YAAY,KAAK,EAAE;AAC7I,WAAO,CAAC;AAAA,EACV;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,wBACJ,cACA,SACA,MAC+B;AAC/B,UAAM,aAAa,QAAQ,oBAAI,KAAK;AACpC,UAAM,eAAe,MAAM,KAAK,sBAAsB,cAAc,SAAS,GAAG;AAGhF,UAAM,aAAa,IAAI,KAAK,UAAU;AACtC,eAAW,SAAS,GAAG,GAAG,GAAG,CAAC;AAC9B,UAAM,WAAW,IAAI,KAAK,UAAU;AACpC,aAAS,QAAQ,SAAS,QAAQ,IAAI,CAAC;AAEvC,UAAM,kBAAkB,aAAa;AAAA,MACnC,QAAM,GAAG,aAAa,cAAc,GAAG,YAAY;AAAA,IACrD;AAEA,UAAM,aAAa,gBAAgB;AAAA,MACjC,CAAC,KAAK,OAAO,MAAM,GAAG;AAAA,MACtB;AAAA,IACF;AAEA,WAAO;AAAA,MACL,MAAM;AAAA,MACN;AAAA,MACA,gBAAgB,kBAAkB,YAAY,KAAK,OAAO,iBAAiB,KAAK,OAAO,aAAa;AAAA,MACpG,kBAAkB,gBAAgB;AAAA,MAClC,cAAc;AAAA,IAChB;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASA,cAAc,UAAkD;AAC9D,SAAK,eAAe,KAAK,QAAQ;AACjC,WAAO,MAAM;AACX,YAAM,QAAQ,KAAK,eAAe,QAAQ,QAAQ;AAClD,UAAI,SAAS,GAAG;AACd,aAAK,eAAe,OAAO,OAAO,CAAC;AAAA,MACrC;AAAA,IACF;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,kBAAkB,OAAwC;AACxD,eAAW,YAAY,KAAK,gBAAgB;AAC1C,UAAI;AACF,iBAAS,KAAK;AAAA,MAChB,SAAS,OAAO;AACd,gBAAQ,MAAM,iDAAiD,KAAK;AAAA,MACtE;AAAA,IACF;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAUA,MAAM,kBACJ,cACA,SACA,SAKC;AACD,UAAM,SAAS,MAAM,KAAK,kBAAkB,cAAc,SAAS,SAAS,MAAM;AAClF,UAAM,YAAY,KAAK,IAAI;AAE3B,WAAO;AAAA,MACL,yBAAyB,MAAM;AAC7B,cAAM,UAAU,KAAK,IAAI,IAAI;AAC7B,cAAM,YAAY,KAAK,IAAI,GAAG,OAAO,iBAAiB,OAAO;AAC7D,eAAO,eAAe,SAAS;AAAA,MACjC;AAAA,MACA,kBAAkB,OAAO;AAAA,MACzB,WAAW,OAAO;AAAA,IACpB;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASA,WAAW,cAAuB,SAAwB;AACxD,QAAI,gBAAgB,SAAS;AAC3B,WAAK,MAAM,OAAO,GAAG,OAAO,IAAI,aAAa,YAAY,CAAC,EAAE;AAAA,IAC9D,OAAO;AACL,WAAK,MAAM,MAAM;AAAA,IACnB;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAKA,2BAA2B,cAAsB,SAAuB;AACtE,SAAK,WAAW,cAAc,OAAO;AAAA,EACvC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASQ,YAAY,SAAiB,QAAkC;AACrE,UAAM,MAAM,UAAU,KAAK,OAAO,QAAQ,OAAO;AACjD,QAAI,CAAC,KAAK;AACR,YAAM,IAAI,MAAM,mCAAmC,OAAO,EAAE;AAAA,IAC9D;AACA,WAAO,IAAIA,SAAO,gBAAgB,GAAG;AAAA,EACvC;AACF;AASO,SAAS,4BACd,QACuB;AACvB,SAAO,IAAI,sBAAsB,MAAM;AACzC;;;AE/hBA,SAAS,UAAAC,gBAAc;;;ACpBvB,SAAS,UAAAC,gBAAc;;;ACAvB,OAAO,WAA2B;AAClC,SAAS,UAAAC,eAAc;AACvB,SAAS,UAAAC,gBAAc;AACvB;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,OACK;;;ACXA,IAAM,4BAA4B;AAAA,EACvC,SAAS;AAAA,EACT,SAAS;AACX;AAMO,IAAM,uCAAuC;AAM7C,IAAM,2BAA2B;AAAA,EACtC,UAAU;AAAA,EACV,SAAS;AAAA,EACT,UAAU;AAAA,EACV,UAAU;AAAA,EACV,MAAM;AACR;;;ADuBO,IAAM,qBAAN,cAAiC,MAAM;AAAA,EAC5C;AAAA,EACA;AAAA,EAEA,YAAY,MAA8B,SAAiB,OAAiB;AAC1E,UAAM,OAAO;AACb,SAAK,OAAO;AACZ,SAAK,OAAO;AACZ,SAAK,QAAQ;AAAA,EACf;AACF;AAEA,SAAS,eAAe,SAAsD;AAC5E,MAAI,SAAS,QAAS,QAAO,QAAQ;AAErC,QAAM,gBAAgB;AAAA,IACnB,YAAoB,SAAS,KAAK;AAAA,IAClC,YAAoB,SAAS,KAAK;AAAA,IAClC,YAAoB,SAAS,KAAK;AAAA,IAClC,YAAoB,SAAS,KAAK;AAAA,EACrC,EAAE,OAAO,OAAO;AAEhB,QAAM,MAAO,cAAc,CAAC,GAA0B,YAAY;AAClE,MAAI,QAAQ,aAAa,QAAQ,UAAW,QAAO;AAGnD,SAAO;AACT;AAEA,SAAS,YAAY,OAAiC;AACpD,QAAM,QAAQ,MAAM,OAAO,CAAC,KAAK,MAAM,MAAM,EAAE,QAAQ,CAAC;AACxD,QAAM,MAAM,IAAI,WAAW,KAAK;AAChC,MAAI,SAAS;AACb,aAAW,KAAK,OAAO;AACrB,QAAI,IAAI,GAAG,MAAM;AACjB,cAAU,EAAE;AAAA,EACd;AACA,SAAO;AACT;AAEA,SAAS,uBAAuB,YAAkC;AAChE,QAAM,SAAuB,CAAC;AAE9B,aAAW,OAAO,YAAY;AAC5B,QAAI,OAAO,QAAQ,YAAY,IAAI,WAAW,OAAO,CAAC,iBAAiB,KAAK,GAAG,GAAG;AAChF,YAAM,IAAI;AAAA,QACR;AAAA,QACA,+DAA+D,OAAO,GAAG,CAAC;AAAA,MAC5E;AAAA,IACF;AAEA,WAAO,KAAK,gBAAgB,KAAK,GAAG,EAAE,CAAC;AAAA,EACzC;AAEA,SAAO,YAAY,MAAM;AAC3B;AAEA,SAAS,iBAAiB,OAA2B;AACnD,MAAI,OAAO,UAAU,YAAY,MAAM,WAAW,GAAG;AACnD,UAAM,IAAI,mBAAmB,0BAA0B,8BAA8B;AAAA,EACvF;AAGA,MAAI,iBAAiB,KAAK,GAAG;AAC3B,WAAO,gBAAgB,KAAK;AAAA,EAC9B;AAGA,MAAI;AACF,QAAI,OAAO,SAAS,YAAY;AAC9B,YAAM,MAAM,KAAK,KAAK;AACtB,YAAM,MAAM,IAAI,WAAW,IAAI,MAAM;AACrC,eAAS,IAAI,GAAG,IAAI,IAAI,QAAQ,IAAK,KAAI,CAAC,IAAI,IAAI,WAAW,CAAC;AAC9D,aAAO;AAAA,IACT;AAAA,EACF,QAAQ;AAAA,EAER;AAEA,MAAI;AACF,WAAO,IAAI,WAAWC,QAAO,KAAK,OAAO,QAAQ,CAAC;AAAA,EACpD,SAAS,OAAO;AACd,UAAM,IAAI,mBAAmB,0BAA0B,8CAA8C,KAAK;AAAA,EAC5G;AACF;AAEA,SAASC,OAAM,IAA2B;AACxC,SAAO,IAAI,QAAQ,CAAC,YAAY,WAAW,SAAS,EAAE,CAAC;AACzD;AAEA,eAAe,uBACb,IACA,aACY;AACZ,MAAI,UAAU;AACd,MAAI;AAEJ,SAAO,UAAU,aAAa;AAC5B,QAAI;AACF,aAAO,MAAM,GAAG;AAAA,IAClB,SAAS,KAAK;AACZ,kBAAY;AACZ,iBAAW;AACX,UAAI,WAAW,YAAa;AAE5B,YAAM,SAAS;AACf,YAAM,YAAY,KAAK,IAAI,KAAO,SAAS,MAAM,UAAU,EAAE;AAC7D,YAAM,WAAW,KAAK,MAAM,KAAK,OAAO,IAAI,GAAG;AAC/C,YAAMA,OAAM,YAAY,QAAQ;AAAA,IAClC;AAAA,EACF;AAEA,QAAM;AACR;AAEA,SAAS,aAAa,SAKpB;AACA,MAAI,YAAY,WAAW;AACzB,UAAM,cAAc,eAAe;AACnC,QAAI,CAAC,aAAa,WAAW,KAAK;AAChC,YAAM,IAAI,mBAAmB,uBAAuB,mDAAmD;AAAA,IACzG;AAEA,WAAO;AAAA,MACL,iBAAiB,YAAY;AAAA,MAC7B,YAAY,YAAY,UAAU;AAAA,MAClC,UAAU,0BAA0B;AAAA,MACpC,QAAQ,YAAY;AAAA,IACtB;AAAA,EACF;AAEA,MAAI,YAAY,WAAW;AACzB,UAAM,OAAO,eAAe;AAC5B,UAAM,aAAc,MAAM,WAAmB;AAE7C,QAAI,CAAC,YAAY;AACf,YAAM,IAAI;AAAA,QACR;AAAA,QACA;AAAA,MACF;AAAA,IACF;AAEA,WAAO;AAAA,MACL,iBAAiB,KAAK;AAAA,MACtB;AAAA,MACA,UAAU,0BAA0B;AAAA,MACpC,QAAQ,KAAK;AAAA,IACf;AAAA,EACF;AAEA,QAAM,IAAI,mBAAmB,uBAAuB,wBAAwB,OAAO,EAAE;AACvF;AAEA,SAAS,eAAe,YAAoB,aAAqD;AAE/F,QAAM,qBAAqB;AAAA,IACzB;AAAA,IACA;AAAA,IACA;AAAA,EACF;AAEA,QAAM,0BAA0B;AAAA,IAC9B;AAAA,IACA;AAAA,EACF;AAGA,QAAM,0BAA0B;AAAA,IAC9B;AAAA,IACA;AAAA,EACF;AAIA,QAAM,QAAQ,IAAIC,SAAO,UAAU;AAAA,IACjC,GAAG;AAAA,IACH,GAAG;AAAA,IACH,GAAG;AAAA,EACL,CAAC;AAED,QAAM,eAAe,CAAC,gBAAgB,cAAc,gBAAgB;AACpE,QAAM,aAAa,CAAC,kBAAkB,uBAAuB;AAC7D,QAAM,oBAAoB,CAAC,yBAAyB,oBAAoB;AAExE,SAAO;AAAA,IACL,GAAG,aAAa,IAAI,CAAC,QAAQ;AAAA,MAC3B,IAAI;AAAA,MACJ,MAAM,MAAM,mBAAmB,IAAI,CAAC,WAAW,CAAC;AAAA,IAClD,EAAE;AAAA,IACF,GAAG,WAAW,IAAI,CAAC,QAAQ;AAAA,MACzB,IAAI;AAAA,MACJ,MAAM,MAAM,mBAAmB,IAAI,CAAC,WAAW,CAAC;AAAA,IAClD,EAAE;AAAA,IACF,GAAG,kBAAkB,IAAI,CAAC,QAAQ;AAAA,MAChC,IAAI;AAAA,MACJ,MAAM,MAAM,mBAAmB,IAAI,CAAC,WAAW,CAAC;AAAA,IAClD,EAAE;AAAA,EACJ;AACF;AAEA,SAAS,iBAAiB,SAA2B;AACnD,QAAM,aAAa;AAAA,IACjB;AAAA,IACA;AAAA,IACA;AAAA,EACF;AACA,QAAM,QAAQ,IAAIA,SAAO,UAAU,UAAU;AAC7C,QAAM,UAAU,CAAC,gBAAgB,cAAc,gBAAgB;AAE/D,WAAS,MAAM,GAAG,MAAM,QAAQ,QAAQ,OAAO;AAC7C,UAAM,SAAS,QAAQ,GAAG;AAC1B,QAAI;AACF,YAAM,OAAO,QAAQ,GAAG;AACxB,UAAI,CAAC,QAAQ,SAAS,KAAM;AAC5B,YAAM,UAAU,MAAM,qBAAqB,QAAQ,IAAI;AACvD,aAAO,QAAQ,CAAC;AAAA,IAClB,QAAQ;AAAA,IAER;AAAA,EACF;AAEA,QAAM,IAAI,mBAAmB,0BAA0B,iDAAiD;AAC1G;AAEA,SAAS,wBAAwB,SAA4B;AAC3D,QAAM,sBAAsB;AAC5B,QAAM,aAAa;AAAA,IACjB;AAAA,IACA;AAAA,EACF;AACA,QAAM,QAAQ,IAAIA,SAAO,UAAU,UAAU;AAC7C,QAAM,UAAU,CAAC,kBAAkB,uBAAuB;AAE1D,WAAS,IAAI,GAAG,IAAI,QAAQ,QAAQ,KAAK;AACvC,UAAM,SAAS,QAAQ,CAAC;AACxB,QAAI;AACF,YAAM,OAAO,QAAQ,sBAAsB,CAAC;AAC5C,UAAI,CAAC,QAAQ,SAAS,KAAM;AAC5B,YAAM,UAAU,MAAM,qBAAqB,QAAQ,IAAI;AACvD,aAAO,QAAQ,QAAQ,CAAC,CAAC;AAAA,IAC3B,QAAQ;AAAA,IAER;AAAA,EACF;AAGA,SAAO;AACT;AAKA,SAAS,qBAAqB,SAA2B;AACvD,QAAM,sBAAsB;AAC5B,QAAM,2BAA2B;AACjC,QAAM,mBAAmB,sBAAsB;AAE/C,QAAM,aAAa;AAAA,IACjB;AAAA,IACA;AAAA,EACF;AACA,QAAM,QAAQ,IAAIA,SAAO,UAAU,UAAU;AAC7C,QAAM,UAAU,CAAC,yBAAyB,oBAAoB;AAE9D,WAAS,IAAI,GAAG,IAAI,QAAQ,QAAQ,KAAK;AACvC,UAAM,SAAS,QAAQ,CAAC;AACxB,QAAI;AACF,YAAM,OAAO,QAAQ,mBAAmB,CAAC;AACzC,UAAI,CAAC,QAAQ,SAAS,KAAM;AAC5B,YAAM,UAAU,MAAM,qBAAqB,QAAQ,IAAI;AACvD,aAAO,QAAQ,CAAC;AAAA,IAClB,QAAQ;AAAA,IAER;AAAA,EACF;AAGA,SAAOA,SAAO;AAChB;AAOA,eAAsB,cACpB,aACA,QACA,SACyB;AACzB,MAAI,OAAO,gBAAgB,YAAY,YAAY,WAAW,GAAG;AAC/D,UAAM,IAAI,mBAAmB,oBAAoB,yBAAyB;AAAA,EAC5E;AACA,MAAI,CAAC,iBAAiB,WAAW,KAAK,gBAAgB,WAAW,EAAE,WAAW,IAAI;AAChF,UAAM,IAAI,mBAAmB,oBAAoB,0CAA0C;AAAA,EAC7F;AACA,MAAI,OAAO,WAAW,YAAY,OAAO,WAAW,GAAG;AACrD,UAAM,IAAI,mBAAmB,oBAAoB,oBAAoB;AAAA,EACvE;AAEA,QAAM,UAAU,eAAe,OAAO;AACtC,QAAM,gBAAgB,SAAS,UAAU;AACzC,QAAM,cAAc,SAAS,eAAe;AAE5C,QAAM,EAAE,iBAAiB,YAAY,UAAU,OAAO,IAAI,aAAa,OAAO;AAE9E,QAAM,WAAW,IAAIA,SAAO,gBAAgB,MAAM;AAElD,QAAM,WAAW,eAAe,YAAY,WAAW;AAEvD,QAAM,UAAU,YAAY;AAC1B,QAAI;AACF,YAAM,cAAc,MAAM,SAAS,eAAe;AAClD,YAAM,WAAW,KAAK,IAAI,GAAG,cAAc,CAAC;AAE5C,YAAM,UAAU,IAAI,aAAa,KAAK,IAAI,IAAI,YAAY;AAAA,QACxD,IAAI,qBAAqB,iBAAiB,IAAI,oBAAoB,UAAU,QAAQ,CAAC;AAAA,MACvF,CAAC;AAGD,YAAM,aAAaF,QAAO,KAAK,QAAQ,UAAU,CAAC,EAAE,SAAS,KAAK;AAElE,YAAM,WAAW,MAAM,MAAM;AAAA,QAC3B;AAAA,QACA,EAAE,OAAO,WAAW;AAAA,QACpB;AAAA,UACE,SAAS;AAAA,YACP,aAAa;AAAA,YACb,gBAAgB;AAAA,UAClB;AAAA,UACA,SAAS;AAAA,QACX;AAAA,MACF;AAEA,YAAM,OAAO,SAAS;AACtB,YAAM,aAAa,MAAM;AACzB,YAAM,QAAQ,MAAM;AAEpB,UAAI,CAAC,MAAM,QAAQ,UAAU,KAAK,OAAO,UAAU,UAAU;AAC3D,cAAM,IAAI,mBAAmB,0BAA0B,+CAA+C;AAAA,MACxG;AAEA,YAAM,QAAQ,uBAAuB,UAAU;AAC/C,YAAM,aAAa,iBAAiB,KAAK;AACzC,YAAM,SAAS,cAAc,KAAK,UAAU;AAE5C,YAAM,WAAW,OAAO,UAAU,KAAK,CAAC,MAAM,EAAE,YAAY,eAAe;AAC3E,UAAI,CAAC,UAAU;AACb,cAAM,IAAI,mBAAmB,0BAA0B,0CAA0C;AAAA,MACnG;AAGA,YAAM,YAAY,qBAAqB,KAAK,SAAS,SAAS,UAAU,CAAC;AACzE,YAAM,YAAY,OAAO,UAAU,SAAS;AAE5C,YAAM,aAAa,KAAK,MAAM,KAAK,IAAI,IAAI,GAAI;AAC/C,UAAI,aAAa,YAAY,eAAe;AAC1C,cAAM,IAAI;AAAA,UACR;AAAA,UACA,4CAA4C,SAAS,SAAS,UAAU,YAAY,aAAa;AAAA,QACnG;AAAA,MACF;AAEA,YAAM,QAAQ,iBAAiB,UAAU,OAAO;AAChD,YAAM,eAAe,wBAAwB,UAAU,OAAO;AAC9D,YAAM,iBAAiB,qBAAqB,UAAU,OAAO;AAE7D,aAAO;AAAA,QACL;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,MACF;AAAA,IACF,SAAS,KAAK;AACZ,UAAI,eAAe,mBAAoB,OAAM;AAC7C,UAAI,MAAM,aAAa,GAAG,GAAG;AAC3B,cAAM,KAAK;AACX,cAAM,SAAS,GAAG,UAAU;AAC5B,cAAM,aAAa,GAAG,UAAU;AAChC,cAAM,UAAU,OAAO,GAAG,UAAU,SAAS,WAAW,GAAG,UAAU,OAAO;AAE5E,cAAM,IAAI;AAAA,UACR;AAAA,UACA,6BAA6B,SAAS,KAAK,MAAM,IAAI,cAAc,EAAE,MAAM,EAAE,GAAG,UAAU,KAAK,OAAO,KAAK,EAAE;AAAA,UAC7G;AAAA,QACF;AAAA,MACF;AAEA,YAAM,IAAI,mBAAmB,oBAAoB,8BAA8B,GAAG;AAAA,IACpF;AAAA,EACF;AAEA,SAAO,MAAM,uBAAuB,SAAS,WAAW;AAC1D;;;ADnaA,SAASG,kBAAwC;AAC/C,QAAM,gBAAgB;AAAA,IACnB,YAAoB,SAAS,KAAK;AAAA,IAClC,YAAoB,SAAS,KAAK;AAAA,IAClC,YAAoB,SAAS,KAAK;AAAA,IAClC,YAAoB,SAAS,KAAK;AAAA,EACrC,EAAE,OAAO,OAAO;AAEhB,QAAM,MAAO,cAAc,CAAC,GAA0B,YAAY;AAClE,MAAI,QAAQ,aAAa,QAAQ,UAAW,QAAO;AACnD,SAAO;AACT;AAEA,SAAS,cAAc,SAAwC;AAC7D,SAAO,YAAY,YAAY,eAAe,YAAY,kBAAkB,eAAe,KAAK;AAClG;AAEA,SAAS,aAAa,SAAwC;AAC5D,SAAO,YAAY,YAAY,eAAe,YAAY,SAAS,eAAe,KAAK;AACzF;AAEA,SAAS,cAAc,SAAwC;AAC7D,QAAM,MAAM,YAAY,YACpB,eAAe,YAAY,UAAU,MACpC,eAAe,KAAK,WAAmB;AAC5C,MAAI,CAAC,KAAK;AACR,UAAM,IAAI,MAAM,sCAAsC;AAAA,EACxD;AACA,SAAO;AACT;AAEA,SAAS,oBAAoB,QAAuD,aAA6B;AAC/G,MAAK,OAA0B,UAAU,UAAc,OAA0B,cAAc,QAAW;AACxG,UAAMC,KAAI;AACV,WAAO,qBAAqBA,GAAE,OAAOA,GAAE,WAAWA,GAAE,MAAM;AAAA,EAC5D;AAEA,MAAK,OAAyB,WAAW,UAAc,OAAyB,SAAS,QAAW;AAClG,UAAMA,KAAI;AACV,WAAO,oBAAoBA,GAAE,QAAQA,GAAE,OAAOA,GAAE,IAAI;AAAA,EACtD;AAEA,QAAM,IAAI;AACV,SAAO,mBAAmB,EAAE,OAAO,EAAE,QAAQ,aAAa,EAAE,SAAS;AACvE;AAEA,eAAe,iBAAiB,aAAqB,SAAiD;AACpG,QAAM,SAAS,aAAa,OAAO;AACnC,QAAM,aAAa,cAAc,OAAO;AAExC,QAAM,WAAW,IAAIC,SAAO,gBAAgB,MAAM;AAClD,QAAM,WAAW,IAAIA,SAAO,UAAU;AAAA,IACpC;AAAA,IACA;AAAA,EACF,CAAC;AAED,QAAM,QAAsC;AAAA,IAC1C,YAAY;AACV,YAAM,OAAO,SAAS,mBAAmB,YAAY,CAAC,WAAW,CAAC;AAClE,YAAM,MAAM,MAAM,SAAS,KAAK,EAAE,IAAI,YAAY,KAAK,CAAC;AACxD,YAAM,UAAU,SAAS,qBAAqB,YAAY,GAAG;AAC7D,aAAO,QAAQ,CAAC;AAAA,IAClB;AAAA,IACA,YAAY;AACV,YAAM,OAAO,SAAS,mBAAmB,cAAc,CAAC,WAAW,CAAC;AACpE,YAAM,MAAM,MAAM,SAAS,KAAK,EAAE,IAAI,YAAY,KAAK,CAAC;AACxD,YAAM,UAAU,SAAS,qBAAqB,cAAc,GAAG;AAC/D,aAAO,QAAQ,CAAC;AAAA,IAClB;AAAA,EACF;AAEA,MAAI;AACJ,aAAW,MAAM,OAAO;AACtB,QAAI;AACF,aAAO,MAAM,GAAG;AAAA,IAClB,SAAS,GAAG;AACV,gBAAU;AAAA,IACZ;AAAA,EACF;AAEA,QAAM,mBAAmB,QAAQ,UAAU,IAAI,MAAM,OAAO,OAAO,CAAC;AACtE;AAEA,SAAS,QAAQ,OAAuB;AACtC,SAAO,OAAO,MAAM,SAAS,EAAE,EAAE,SAAS,IAAI,GAAG;AACnD;AASA,eAAsB,uBACpB,YACA,QACuC;AACvC,QAAM,UAAUF,gBAAe;AAC/B,QAAM,aAAa,cAAc,OAAO;AAExC,QAAM,gBAAgB,WAAW,kBAAkB,WAAW,SAC1D,oBAAoB,WAAW,QAAQ,WAAW,WAAW,IAC7D;AAEJ,MAAI,CAAC,eAAe;AAClB,UAAM,IAAI,MAAM,gEAAgE;AAAA,EAClF;AAEA,MAAI;AACJ,MAAI,aAA0C,IAAI,WAAW;AAC7D,MAAI,oBAAoB;AAExB,QAAM,aAAa,KAAK,IAAI;AAC5B,MAAI;AACF,QAAI,CAAC,QAAQ;AACX,YAAM,IAAI,MAAM,4BAA4B;AAAA,IAC9C;AAEA,UAAM,QAAQ,MAAM,cAAc,WAAW,WAAW,SAAS,QAAQ,EAAE,SAAS,QAAQ,GAAG,CAAC;AAEhG,QAAI,CAAC,MAAM,cAAc;AAEvB,YAAM,IAAI,MAAM,kCAAkC;AAAA,IACpD;AAEA,YAAQ,MAAM;AACd,iBAAa,MAAM;AAAA,EACrB,QAAQ;AAEN,YAAQ,MAAM,iBAAiB,WAAW,WAAW,SAAS,OAAO;AACrE,iBAAa,IAAI,WAAW;AAAA,EAC9B;AACA,QAAM,iBAAiB,KAAK,IAAI,IAAI;AAEpC,QAAM,YAAY,sBAAsB,WAAW,aAAa,eAAe,OAAO,UAAU;AAChG,QAAM,UAAU,IAAI,eAAe;AACnC,UAAQ,cAAc,WAAW,UAAU;AAC3C,QAAM,YAAY,MAAM,QAAQ,KAAK,SAAS;AAI9C,QAAM,cAAmB;AAAA,IACvB,mBAAmB,UAAU;AAAA,IAC7B,gBAAgB,UAAU;AAAA,IAC1B,gBAAgB,UAAU;AAAA,IAC1B,WAAW,UAAU;AAAA,IACrB,GAAG,QAAQ,UAAU,CAAC;AAAA,IACtB,GAAG,QAAQ,UAAU,CAAC;AAAA,IACtB,YAAY,QAAQ,WAAW,WAAW,UAAU;AAAA,IACpD,YAAY,QAAQ,WAAW,WAAW,UAAU;AAAA,IACpD,aAAa,WAAW;AAAA,IACxB;AAAA,IACA,OAAO,OAAO,KAAK;AAAA,EACrB;AAGA,MAAI,WAAW,QAAQ;AACrB,gBAAY,aAAaE,SAAO,QAAQ,UAAU;AAAA,EACpD;AAEA,QAAM,eAAe,IAAI,YAAY,EAAE,OAAO,KAAK,UAAU,WAAW,CAAC;AAGzE,QAAM,mBAAmB,WAAW,SAAS,KAAK,IAAI,KAAK,cAAc,IAAI,KAAK,IAAI,KAAK,cAAc;AAEzG,SAAO;AAAA,IACL;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF;AACF;;;AGnMA,OAAOC,YAA2B;AAClC,SAAS,UAAAC,eAAc;AACvB,SAAS,UAAAC,gBAAc;AACvB,SAAS,aAAAC,kBAAiB;AAC1B;AAAA,EACE,uBAAAC;AAAA,EACA,wBAAAC;AAAA,EACA,wBAAAC;AAAA,EACA,gBAAAC;AAAA,EACA,iBAAAC;AAAA,EACA;AAAA,EACA;AAAA,EACA,mBAAAC;AAAA,EACA,oBAAAC;AAAA,OACK;AAyEA,IAAM,sBAAN,cAAkC,MAAM;AAAA,EAC7C;AAAA,EACA;AAAA,EAEA,YAAY,MAA+B,SAAiB,OAAiB;AAC3E,UAAM,OAAO;AACb,SAAK,OAAO;AACZ,SAAK,OAAO;AACZ,SAAK,QAAQ;AAAA,EACf;AACF;AAGA,IAAM,kBAAkB,oBAAI,IAAwB;AAEpD,SAASC,gBAAe,SAAwD;AAC9E,MAAI,SAAS,QAAS,QAAO,QAAQ;AAErC,QAAM,gBAAgB;AAAA,IACnB,YAAoB,SAAS,KAAK;AAAA,IAClC,YAAoB,SAAS,KAAK;AAAA,IAClC,YAAoB,SAAS,KAAK;AAAA,IAClC,YAAoB,SAAS,KAAK;AAAA,EACrC,EAAE,OAAO,OAAO;AAEhB,QAAM,MAAO,cAAc,CAAC,GAA0B,YAAY;AAClE,MAAI,QAAQ,aAAa,QAAQ,UAAW,QAAO;AAEnD,SAAO;AACT;AAEA,SAASC,aAAY,OAAiC;AACpD,QAAM,QAAQ,MAAM,OAAO,CAAC,KAAK,MAAM,MAAM,EAAE,QAAQ,CAAC;AACxD,QAAM,MAAM,IAAI,WAAW,KAAK;AAChC,MAAI,SAAS;AACb,aAAW,KAAK,OAAO;AACrB,QAAI,IAAI,GAAG,MAAM;AACjB,cAAU,EAAE;AAAA,EACd;AACA,SAAO;AACT;AAEA,SAASC,wBAAuB,YAAkC;AAChE,QAAM,SAAuB,CAAC;AAE9B,aAAW,OAAO,YAAY;AAC5B,QAAI,OAAO,QAAQ,YAAY,IAAI,WAAW,OAAO,CAAC,iBAAiB,KAAK,GAAG,GAAG;AAChF,YAAM,IAAI;AAAA,QACR;AAAA,QACA,+DAA+D,OAAO,GAAG,CAAC;AAAA,MAC5E;AAAA,IACF;AAEA,WAAO,KAAKC,iBAAgB,KAAK,GAAG,EAAE,CAAC;AAAA,EACzC;AAEA,SAAOF,aAAY,MAAM;AAC3B;AAEA,SAASG,kBAAiB,OAA2B;AACnD,MAAI,OAAO,UAAU,YAAY,MAAM,WAAW,GAAG;AACnD,UAAM,IAAI,oBAAoB,0BAA0B,8BAA8B;AAAA,EACxF;AAEA,MAAIC,kBAAiB,KAAK,GAAG;AAC3B,WAAOF,iBAAgB,KAAK;AAAA,EAC9B;AAEA,MAAI;AACF,QAAI,OAAO,SAAS,YAAY;AAC9B,YAAM,MAAM,KAAK,KAAK;AACtB,YAAM,MAAM,IAAI,WAAW,IAAI,MAAM;AACrC,eAAS,IAAI,GAAG,IAAI,IAAI,QAAQ,IAAK,KAAI,CAAC,IAAI,IAAI,WAAW,CAAC;AAC9D,aAAO;AAAA,IACT;AAAA,EACF,QAAQ;AAAA,EAER;AAEA,MAAI;AACF,WAAO,IAAI,WAAWG,QAAO,KAAK,OAAO,QAAQ,CAAC;AAAA,EACpD,SAAS,OAAO;AACd,UAAM,IAAI,oBAAoB,0BAA0B,8CAA8C,KAAK;AAAA,EAC7G;AACF;AAEA,SAASC,OAAM,IAA2B;AACxC,SAAO,IAAI,QAAQ,CAAC,YAAY,WAAW,SAAS,EAAE,CAAC;AACzD;AAMA,IAAM,cAAc;AAAA,EAClB,OAAO,CAAC;AAAA,EACR,aAAa;AAAA,EACb,aAAa;AAAA;AAAA,EAEb,MAAM,UAAyB;AAC7B,WAAO,IAAI,QAAQ,CAAC,YAAY;AAC9B,YAAM,aAAa,MAAM;AACvB,cAAM,MAAM,KAAK,IAAI;AACrB,cAAM,UAAU,MAAM,YAAY;AAClC,YAAI,WAAW,YAAY,aAAa;AACtC,sBAAY,cAAc;AAC1B,kBAAQ;AAAA,QACV,OAAO;AACL,qBAAW,YAAY,YAAY,cAAc,OAAO;AAAA,QAC1D;AAAA,MACF;AACA,iBAAW;AAAA,IACb,CAAC;AAAA,EACH;AACF;AAEA,eAAeC,wBAA0B,IAAsB,aAAiC;AAC9F,MAAI,UAAU;AACd,MAAI;AAEJ,SAAO,UAAU,aAAa;AAC5B,QAAI;AACF,aAAO,MAAM,GAAG;AAAA,IAClB,SAAS,KAAK;AACZ,kBAAY;AACZ,iBAAW;AACX,UAAI,WAAW,YAAa;AAE5B,YAAM,SAAS;AACf,YAAM,YAAY,KAAK,IAAI,KAAO,SAAS,MAAM,UAAU,EAAE;AAC7D,YAAM,WAAW,KAAK,MAAM,KAAK,OAAO,IAAI,GAAG;AAC/C,YAAMD,OAAM,YAAY,QAAQ;AAAA,IAClC;AAAA,EACF;AAEA,QAAM;AACR;AAEA,SAAS,gBAAgB,SAAgC;AACvD,SAAO,YAAY,YAAY,iBAAiB;AAClD;AAEA,SAAS,iBAAiB,SAAgC,SAAyC;AACjG,MAAI,SAAS,SAAU,QAAO,QAAQ;AACtC,SAAO,YAAY,YAAY,0BAA0B,UAAU,0BAA0B;AAC/F;AAEA,SAAS,0BAA0B,SAA0C;AAE3E,SAAO,YAAY,YAAY,CAAC,OAAO,OAAO,OAAO,CAAC,IAAI,CAAC,IAAI,IAAI,IAAI,CAAC;AAC1E;AAEA,SAAS,eAAe,KAAyB;AAC/C,MAAI,OAAO,QAAQ,YAAY,CAAC,sBAAsB,KAAK,GAAG,GAAG;AAC/D,UAAM,IAAI,oBAAoB,oBAAoB,qDAAqD,GAAG,EAAE;AAAA,EAC9G;AACA,SAAO,IAAI,WAAWD,QAAO,KAAK,IAAI,MAAM,CAAC,GAAG,KAAK,CAAC;AACxD;AAEA,SAAS,yBAAyB,iBAAyB,aAA6B;AACtF,QAAM,YAAY,IAAIG,WAAU,eAAe;AAC/C,QAAM,eAAe,eAAe,WAAW;AAC/C,QAAM,CAAC,QAAQ,IAAIA,WAAU,uBAAuB,CAACH,QAAO,KAAK,OAAO,GAAGA,QAAO,KAAK,YAAY,CAAC,GAAG,SAAS;AAChH,SAAO,SAAS,SAAS;AAC3B;AAEA,SAAS,aAAa,aAAqB,QAAgB,SAA4C,UAAoB;AAEzH,QAAM,UAAU;AAAA,IACd;AAAA,IACA,SAASN,gBAAe,OAAO;AAAA,IAC/B,UAAU,CAAC,GAAG,QAAQ,EAAE,KAAK,CAAC,GAAG,MAAM,IAAI,CAAC;AAAA,IAC5C,gBAAgB,SAAS,kBAAkB;AAAA,IAC3C,mBAAmB,SAAS,qBAAqB;AAAA,IACjD,gBAAgB,SAAS,kBAAkB;AAAA,IAC3C,UAAU,SAAS,YAAY;AAAA,EACjC;AAEA,OAAK;AACL,SAAO,KAAK,UAAU,OAAO;AAC/B;AAEA,SAAS,qBAAqB,GAAmB;AAC/C,QAAM,IAAI,OAAO,CAAC;AAClB,SAAO,OAAO,SAAS,CAAC,IAAI,IAAI;AAClC;AAEA,SAAS,YAAY,WAA+C,QAAiB,SAAsC;AACzH,MAAI,CAAC,UAAW,QAAO;AACvB,MAAI,UAAU,UAAU,MAAM,KAAK,KAAM,QAAO,UAAU,MAAM;AAChE,MAAI,WAAW,UAAU,OAAO,KAAK,KAAM,QAAO,UAAU,OAAO;AACnE,SAAO;AACT;AAEA,SAAS,OAAO,UAA8B,WAAwD;AACpG,MAAI,QAAQ;AACZ,MAAI,MAAM;AAEV,aAAW,KAAK,UAAU;AACxB,UAAM,IAAI,YAAY,WAAW,EAAE,QAAQ,EAAE,OAAO;AACpD,QAAI,KAAK,KAAM;AACf,QAAI,EAAE,YAAY,KAAM;AAExB,UAAM,QAAQ,MAAM,EAAE;AACtB,UAAM,SAAS,OAAO,EAAE,MAAM,IAAI;AAClC,QAAI,CAAC,OAAO,SAAS,MAAM,EAAG;AAC9B,aAAS,SAAS;AAClB,UAAM;AAAA,EACR;AAEA,SAAO,MAAM,QAAQ;AACvB;AAEA,eAAe,kBAAkB,QAAiC;AAChE,QAAM,WAAW,IAAIU,SAAO,gBAAgB,MAAM;AAClD,QAAM,SAAS,MAAM,SAAS,eAAe;AAC7C,SAAO,KAAK,IAAI,GAAG,SAAS,CAAC;AAC/B;AAEA,SAAS,wBAAwB,cAAsB,gBAA0D;AAC/G,QAAM,QAAQ,IAAIA,SAAO,UAAU,CAAC,0DAA0D,CAAC;AAC/F,SAAO,eAAe,IAAI,CAAC,WAAW;AAAA,IACpC,IAAI;AAAA,IACJ,MAAM,MAAM,mBAAmB,aAAa,CAAC,YAAY,CAAC;AAAA,EAC5D,EAAE;AACJ;AAEA,SAAS,oBAAoB,SAAmB,gBAAoC;AAClF,QAAM,QAAQ,IAAIA,SAAO,UAAU,CAAC,0DAA0D,CAAC;AAC/F,QAAM,MAAgB,CAAC;AACvB,WAAS,IAAI,GAAG,IAAI,eAAe,QAAQ,KAAK;AAC9C,UAAM,OAAO,QAAQ,CAAC;AACtB,QAAI,CAAC,QAAQ,SAAS,MAAM;AAC1B,UAAI,KAAK,EAAE;AACX;AAAA,IACF;AACA,UAAM,UAAU,MAAM,qBAAqB,aAAa,IAAI;AAC5D,QAAI,KAAK,QAAQ,CAAC,CAAW;AAAA,EAC/B;AACA,SAAO;AACT;AAUA,eAAsB,eACpB,aACA,QACA,SAC0B;AAC1B,QAAM,UAAUV,gBAAe,OAAO;AACtC,QAAM,gBAAgB,SAAS,UAAU;AACzC,QAAM,cAAc,SAAS,eAAe;AAC5C,QAAM,aAAa,SAAS,cAAc;AAC1C,QAAM,WAAW,iBAAiB,SAAS,OAAO;AAElD,QAAM,WAAW,SAAS,UAAU,OAAO,KAAK,QAAQ,OAAO,EAAE,IAAI,MAAM,IAAI;AAC/E,OAAK;AAEL,QAAM,kBAAkB,SAAS,iBAC7B,OAAO,KAAK,QAAQ,cAAc,EAAE,IAAI,MAAM,IAC9C;AAEJ,QAAM,gBAAgB,0BAA0B,OAAO;AACvD,QAAM,mBAAmB,SAAS,oBAC9B,MAAM,KAAK,oBAAI,IAAI,CAAC,GAAG,eAAe,GAAG,OAAO,KAAK,QAAQ,iBAAiB,EAAE,IAAI,MAAM,CAAC,CAAC,CAAC,IAC7F;AAGJ,QAAM,gBAAgB,kBAClB,MAAM,KAAK,oBAAI,IAAI,CAAC,GAAG,kBAAkB,GAAG,eAAe,CAAC,CAAC,IAC7D;AAEJ,MAAI,CAAC,UAAU,OAAO,WAAW,UAAU;AACzC,UAAM,IAAI,oBAAoB,oBAAoB,4BAA4B;AAAA,EAChF;AAEA,QAAM,WAAW,aAAa,aAAa,QAAQ,SAAS,aAAa;AACzE,QAAM,SAAS,gBAAgB,IAAI,QAAQ;AAC3C,MAAI,UAAU,OAAO,YAAY,KAAK,IAAI,GAAG;AAC3C,WAAO,OAAO;AAAA,EAChB;AAEA,QAAM,SAAS,gBAAgB,OAAO;AACtC,QAAM,gBAAgB,IAAI,cAAc,EAAE,gBAAgB,MAAM,kBAAkB,MAAM,CAAC;AAEzF,QAAM,YAAgD;AAAA,IACpD,MAAM;AAAA,IACN,GAAI,SAAS,aAAa,CAAC;AAAA,EAC7B;AAEA,QAAM,UAAU,YAAsC;AACpD,QAAI;AACF,YAAM,mBAA2C,CAAC;AAClD,YAAM,YAAmH,CAAC;AAG1H,YAAM,cAAc,cAAc,OAAO,CAAC,OAAO;AAC/C,cAAM,MAAM,OAAO,OAAO,MAAM,EAAE,KAAK,CAAC,MAAM,EAAE,oBAAoB,EAAE;AACtE,eAAO,KAAK;AAAA,MACd,CAAC;AAED,YAAM,qBAAqB,oBAAI,IAAoB;AACnD,YAAM,QAAQ;AAAA,QACZ,YAAY,IAAI,OAAO,oBAAoB;AACzC,gBAAM,MAAM,OAAO,OAAO,MAAM,EAAE,KAAK,CAAC,MAAM,EAAE,oBAAoB,eAAe;AACnF,cAAI,CAAC,IAAK;AACV,gBAAM,SAAS,SAAS,UAAU,eAAe,KAAK,IAAI;AAC1D,gBAAM,WAAW,MAAM,kBAAkB,MAAM;AAC/C,6BAAmB,IAAI,iBAAiB,QAAQ;AAAA,QAClD,CAAC;AAAA,MACH;AAEA,iBAAW,mBAAmB,eAAe;AAC3C,cAAM,MAAM,OAAO,OAAO,MAAM,EAAE,KAAK,CAAC,MAAM,EAAE,oBAAoB,eAAe;AAEnF,YAAI,oBAAoB,IAAI;AAC1B,oBAAU,eAAe,IAAI,EAAE,MAAM,eAAe,WAAW,KAAK,KAAK;AACzE;AAAA,QACF;AAEA,YAAI,CAAC,KAAK;AACR,oBAAU,eAAe,IAAI,EAAE,MAAM,cAAc;AACnD;AAAA,QACF;AAEA,YAAI,IAAI,OAAO;AACb,gBAAM,eAAe,SAAS,iBAAiB,eAAe,MACxD,IAAI,UAAU,gBAAgB,IAAI,UAAU,sBAC5C,cAAc,oBAAoB,aAAa,IAAI,UAAU,cAAc,IAAI,UAAU,mBAAmB,IAC5G;AAEN,oBAAU,eAAe,IAAI,EAAE,MAAM,OAAO,cAAc,WAAW,IAAI,KAAK;AAE9E,cAAI,CAAC,cAAc;AACjB;AAAA,UACF;AAEA,gBAAM,iBAAiB,SAAS,oBAAoB,eAAe,KAC9D,aAAa,eAAe,EAAE,OAAO,CAAC,MAAM,CAAC,cAAc,EAAE,OAAO,CAAC,EAAE,IAAI,CAAC,MAAM,EAAE,OAAO;AAEhG,cAAI,CAAC,eAAe,QAAQ;AAC1B;AAAA,UACF;AAEA,gBAAM,WAAW,mBAAmB,IAAI,eAAe;AACvD,cAAI,YAAY,MAAM;AACpB;AAAA,UACF;AAEA,gBAAM,QAAQ,wBAAwB,cAAc,cAAc;AAClE,2BAAiB,KAAK,IAAIW,sBAAqB,iBAAiB,IAAIC,qBAAoB,UAAU,KAAK,CAAC,CAAC;AACzG;AAAA,QACF;AAGA,YAAI,oBAAoB,GAAG;AACzB,gBAAM,YAAY,SAAS,iBAAiB,eAAe,KAAK,IAAI,UAAU;AAC9E,oBAAU,eAAe,IAAI,EAAE,MAAM,UAAU,WAAW,IAAI,KAAK;AAEnE,cAAI,CAAC,WAAW;AACd;AAAA,UACF;AAEA,gBAAM,eAAe,yBAAyB,WAAW,WAAW;AACpE,oBAAU,eAAe,IAAI,EAAE,MAAM,UAAU,WAAW,IAAI,MAAM,aAAa;AAEjF,gBAAM,WAAW,CAAC,cAAc,GAAI,SAAS,kBAAkB,CAAC,CAAE;AAClE,2BAAiB;AAAA,YACf,IAAID;AAAA,cACF;AAAA,cACA,IAAI,0BAA0B,aAAa,UAAU,QAAW,IAAI,EAAE;AAAA,YACxE;AAAA,UACF;AACA;AAAA,QACF;AAEA,kBAAU,eAAe,IAAI,EAAE,MAAM,eAAe,WAAW,IAAI,KAAK;AAAA,MAC1E;AAEA,UAAI,iBAAiB,SAAS,KAAK;AACjC,cAAM,IAAI;AAAA,UACR;AAAA,UACA,gCAAgC,iBAAiB,MAAM;AAAA,QACzD;AAAA,MACF;AAGA,UAAI,iBAAiB,WAAW,GAAG;AACjC,cAAME,aAAoC,cAAc,IAAI,CAAC,oBAAoB;AAC/E,gBAAM,OAAO,UAAU,eAAe,KAAK,EAAE,MAAM,cAAuB;AAC1E,iBAAO;AAAA,YACL;AAAA,YACA,WAAW,KAAK;AAAA,YAChB,cAAc,KAAK;AAAA,YACnB,UAAU,CAAC;AAAA,YACX,OAAO;AAAA,cACL,MAAM;AAAA,cACN,SAAS;AAAA,YACX;AAAA,UACF;AAAA,QACF,CAAC;AACD,eAAO,EAAE,OAAO,IAAI,WAAW,GAAG,UAAU,GAAG,QAAQA,WAAU;AAAA,MACnE;AAEA,YAAM,UAAU,IAAIC,cAAa,KAAK,IAAI,IAAI,YAAY,gBAAgB;AAE1E,YAAM,aAAaR,QAAO,KAAK,QAAQ,UAAU,CAAC,EAAE,SAAS,KAAK;AAGlE,YAAM,YAAY,QAAQ;AAE1B,UAAI;AACJ,UAAI;AACF,gBAAQ,IAAI,wCAAwC,QAAQ;AAC5D,gBAAQ,IAAI,0CAA0C,WAAW,MAAM;AAGvE,cAAM,iBAAiB,YAAY,YAAY,OAAS;AACxD,cAAM,iBAAiB,SAAS,WAAW;AAE3C,mBAAW,MAAMS,OAAM;AAAA,UACrB;AAAA,UACA,EAAE,OAAO,WAAW;AAAA,UACpB;AAAA,YACE,SAAS;AAAA,cACP,aAAa;AAAA,cACb,gBAAgB;AAAA,YAClB;AAAA,YACA,SAAS;AAAA,UACX;AAAA,QACF;AAAA,MACF,SAAS,UAAU;AACjB,cAAM,MAAM;AAEZ,YAAI,CAAC,IAAI,UAAU;AACjB,kBAAQ,MAAM,mCAAmC;AAAA,YAC/C,SAAS,IAAI;AAAA,YACb,MAAM,IAAI;AAAA,YACV,MAAM,IAAI;AAAA,UACZ,CAAC;AACD,gBAAM,IAAI;AAAA,YACR;AAAA,YACA,kBAAkB,IAAI,OAAO,WAAW,IAAI,IAAI;AAAA,UAClD;AAAA,QACF;AACA,cAAM,SAAS,IAAI,SAAS;AAC5B,cAAM,UAAU,IAAI,SAAS;AAC7B,gBAAQ,MAAM,gDAAgD,EAAE,QAAQ,MAAM,QAAQ,CAAC;AACvF,cAAM,IAAI;AAAA,UACR;AAAA,UACA,wBAAwB,MAAM,KAAK,KAAK,UAAU,OAAO,CAAC;AAAA,QAC5D;AAAA,MACF;AAEA,YAAM,OAAO,SAAS;AACtB,YAAM,aAAa,MAAM;AACzB,YAAM,QAAQ,MAAM;AAEpB,UAAI,CAAC,MAAM,QAAQ,UAAU,KAAK,OAAO,UAAU,UAAU;AAC3D,cAAM,IAAI,oBAAoB,0BAA0B,+CAA+C;AAAA,MACzG;AAEA,YAAM,QAAQb,wBAAuB,UAAU;AAC/C,YAAM,aAAaE,kBAAiB,KAAK;AACzC,YAAM,SAASY,eAAc,KAAK,UAAU;AAE5C,YAAM,aAAa,KAAK,MAAM,KAAK,IAAI,IAAI,GAAI;AAC/C,YAAM,YAAoC,CAAC;AAE3C,iBAAW,mBAAmB,eAAe;AAC3C,cAAM,OAAO,UAAU,eAAe,KAAK,EAAE,MAAM,cAAuB;AAE1E,YAAI,KAAK,SAAS,eAAe;AAC/B,gBAAM,MAAM,oBAAoB,KAC5B,kEACA;AACJ,oBAAU,KAAK;AAAA,YACb;AAAA,YACA,WAAW,KAAK;AAAA,YAChB,UAAU,CAAC;AAAA,YACX,OAAO,EAAE,MAAM,qBAAqB,SAAS,IAAI;AAAA,UACnD,CAAC;AACD;AAAA,QACF;AAEA,YAAI,CAAC,KAAK,cAAc;AACtB,oBAAU,KAAK;AAAA,YACb;AAAA,YACA,WAAW,KAAK;AAAA,YAChB,UAAU,CAAC;AAAA,YACX,OAAO,EAAE,MAAM,iBAAiB,SAAS,2CAA2C;AAAA,UACtF,CAAC;AACD;AAAA,QACF;AAEA,cAAM,WAAW,OAAO,UAAU,KAAK,CAAC,MAAM,EAAE,YAAY,eAAe;AAC3E,YAAI,CAAC,UAAU;AACb,oBAAU,KAAK;AAAA,YACb;AAAA,YACA,WAAW,KAAK;AAAA,YAChB,cAAc,KAAK;AAAA,YACnB,UAAU,CAAC;AAAA,YACX,OAAO,EAAE,MAAM,gBAAgB,SAAS,8CAA8C;AAAA,UACxF,CAAC;AACD;AAAA,QACF;AAEA,YAAI;AACF,cAAI,KAAK,SAAS,OAAO;AACvB,kBAAM,MAAM,OAAO,OAAO,MAAM,EAAE,KAAK,CAAC,MAAM,EAAE,oBAAoB,eAAe;AACnF,kBAAM,iBAAiB,SAAS,oBAAoB,eAAe,KAC9D,aAAa,eAAe,EAAE,OAAO,CAAC,MAAM,CAAC,cAAc,EAAE,OAAO,CAAC,EAAE,IAAI,CAAC,MAAM,EAAE,OAAO;AAEhG,gBAAI,CAAC,eAAe,QAAQ;AAC1B,wBAAU,KAAK;AAAA,gBACb;AAAA,gBACA,WAAW,KAAK;AAAA,gBAChB,cAAc,KAAK;AAAA,gBACnB,UAAU,CAAC;AAAA,gBACX,OAAO,EAAE,MAAM,kBAAkB,SAAS,qDAAqD;AAAA,cACjG,CAAC;AACD;AAAA,YACF;AAEA,kBAAMC,aAAYC,sBAAqB,KAAK,SAAS,SAAS,UAAU,CAAC;AACzE,kBAAMC,aAAY,OAAOF,WAAU,SAAS;AAC5C,kBAAMG,OAAM,aAAaD;AACzB,gBAAIC,OAAM,eAAe;AACvB,wBAAU,KAAK;AAAA,gBACb;AAAA,gBACA,WAAW,KAAK;AAAA,gBAChB,cAAc,KAAK;AAAA,gBACnB,WAAAD;AAAA,gBACA,UAAU,CAAC;AAAA,gBACX,OAAO,EAAE,MAAM,qBAAqB,SAAS,wBAAwBC,IAAG,aAAa,aAAa,KAAK;AAAA,cACzG,CAAC;AACD;AAAA,YACF;AAEA,kBAAM,UAAU,oBAAoBH,WAAU,SAAS,cAAc;AACrE,kBAAM,aAAa,aAAa,eAAe,EAAE,OAAO,CAAC,MAAM,CAAC,cAAc,EAAE,OAAO,CAAC;AAExF,kBAAMI,YAA+B,eAAe,IAAI,CAAC,MAAM,MAAM;AACnE,oBAAM,OAAO,WAAW,KAAK,CAAC,MAAM,EAAE,QAAQ,YAAY,MAAM,KAAK,YAAY,CAAC;AAClF,oBAAM,SAAS,MAAM;AACrB,oBAAM,WAAW,MAAM;AACvB,oBAAM,WAAW,YAAY,WAAW,QAAQ,IAAI;AACpD,oBAAM,WAAW,YAAY,QAAQ,YAAY,OAC5C,OAAO,QAAQ,CAAC,CAAC,IAAI,MAAM,WAAY,WACxC;AAEJ,qBAAO;AAAA,gBACL,SAAS;AAAA,gBACT,QAAQ,QAAQ,CAAC;AAAA,gBACjB;AAAA,gBACA;AAAA,gBACA,UAAU,OAAO,SAAS,YAAY,GAAG,IAAI,WAAW;AAAA,cAC1D;AAAA,YACF,CAAC;AAED,iBAAK;AACL,sBAAU,KAAK;AAAA,cACb;AAAA,cACA,WAAW,KAAK;AAAA,cAChB,cAAc,KAAK;AAAA,cACnB,WAAAF;AAAA,cACA,UAAAE;AAAA,YACF,CAAC;AACD;AAAA,UACF;AAGA,gBAAM,YAAY,2BAA2B,KAAK,SAAS,SAAS,UAAU,CAAC;AAC/E,gBAAM,YAAY,qBAAqB,UAAU,SAAS;AAC1D,gBAAM,MAAM,aAAa;AACzB,cAAI,MAAM,eAAe;AACvB,sBAAU,KAAK;AAAA,cACb;AAAA,cACA,WAAW,KAAK;AAAA,cAChB,cAAc,KAAK;AAAA,cACnB;AAAA,cACA,UAAU,CAAC;AAAA,cACX,OAAO,EAAE,MAAM,qBAAqB,SAAS,wBAAwB,GAAG,aAAa,aAAa,KAAK;AAAA,YACzG,CAAC;AACD;AAAA,UACF;AAEA,gBAAM,cAAc,UAAU,QAAQ,CAAC;AACvC,gBAAM,WAAW,aAAa,YAAY;AAE1C,gBAAM,WAA+B;AAAA,YACnC;AAAA,cACE,SAAS;AAAA,cACT,QAAQ;AAAA,cACR,UAAU;AAAA,cACV,QAAQ;AAAA,cACR,UAAU,YAAY,WAAW,OAAO,KAAK,KAAK,OAC7C,OAAO,QAAQ,IAAI,MAAQ,YAAY,WAAW,OAAO,KAAK,IAC/D;AAAA,YACN;AAAA,UACF;AAEA,oBAAU,KAAK;AAAA,YACb;AAAA,YACA,WAAW,KAAK;AAAA,YAChB,cAAc,KAAK;AAAA,YACnB;AAAA,YACA;AAAA,UACF,CAAC;AAAA,QACH,SAAS,OAAO;AACd,oBAAU,KAAK;AAAA,YACb;AAAA,YACA,WAAW,KAAK;AAAA,YAChB,cAAc,KAAK;AAAA,YACnB,UAAU,CAAC;AAAA,YACX,OAAO,EAAE,MAAM,gBAAgB,SAAS,oCAAoC,OAAQ,OAAe,WAAW,KAAK,CAAC,GAAG;AAAA,UACzH,CAAC;AAAA,QACH;AAAA,MACF;AAEA,YAAM,cAAc,UAAU,QAAQ,CAAC,MAAM,EAAE,QAAQ;AACvD,YAAM,WAAW,OAAO,aAAa,SAAS;AAE9C,YAAMC,UAA0B,EAAE,OAAO,UAAU,QAAQ,UAAU;AAErE,sBAAgB,IAAI,UAAU,EAAE,WAAW,KAAK,IAAI,IAAI,YAAY,OAAOA,QAAO,CAAC;AACnF,aAAOA;AAAA,IACT,SAAS,KAAK;AACZ,UAAI,eAAe,oBAAqB,OAAM;AAC9C,UAAIP,OAAM,aAAa,GAAG,GAAG;AAC3B,cAAM,KAAK;AACX,cAAM,SAAS,GAAG,UAAU;AAC5B,cAAM,aAAa,GAAG,UAAU;AAChC,cAAM,UAAU,OAAO,GAAG,UAAU,SAAS,WAAW,GAAG,UAAU,OAAO;AAE5E,cAAM,IAAI;AAAA,UACR;AAAA,UACA,6BAA6B,SAAS,KAAK,MAAM,IAAI,cAAc,EAAE,MAAM,EAAE,GAAG,UAAU,KAAK,OAAO,KAAK,EAAE;AAAA,UAC7G;AAAA,QACF;AAAA,MACF;AAEA,YAAM,IAAI,oBAAoB,oBAAoB,8BAA8B,GAAG;AAAA,IACrF;AAAA,EACF;AAEA,QAAM,SAAS,MAAMP,wBAAuB,SAAS,WAAW;AAChE,kBAAgB,IAAI,UAAU,EAAE,WAAW,KAAK,IAAI,IAAI,YAAY,OAAO,OAAO,CAAC;AACnF,SAAO;AACT;;;AC1tBA,SAAS,UAAAe,gBAAc;AA0EvB,IAAMC,qBAAoB;AAAA,EACtB;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACJ;AAGA,IAAMC,kBAA0C;AAAA,EAC5C;AAAA,IACI,MAAM;AAAA,IACN,SAAS;AAAA,IACT,iBAAiB;AAAA,IACjB,QAAQ;AAAA,IACR,YAAY;AAAA,IACZ,OAAO;AAAA,EACX;AAAA,EACA;AAAA,IACI,MAAM;AAAA,IACN,SAAS;AAAA,IACT,iBAAiB;AAAA,IACjB,QAAQ;AAAA,IACR,cAAc;AAAA,EAClB;AAAA,EACA;AAAA,IACI,MAAM;AAAA,IACN,SAAS;AAAA,IACT,iBAAiB;AAAA,IACjB,QAAQ;AAAA,IACR,cAAc;AAAA,EAClB;AACJ;AAGA,IAAMC,kBAA0C;AAAA;AAEhD;AAYO,IAAM,aAAN,MAAiB;AAAA,EACZ;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EAER,YAAY,SAA2B,CAAC,GAAG;AACvC,SAAK,SAAS;AACd,SAAK,SAAS,OAAO,YAAY,QAAQD,kBAAiBC;AAG1D,QAAI,OAAO,sBAAsB;AAC7B,WAAK,mBAAmB,IAAIH,SAAO,OAAO,OAAO,oBAAoB;AAAA,IACzE;AAGA,QAAI,OAAO,mBAAmB;AAC1B,WAAK,gBAAgB,IAAIA,SAAO,OAAO,OAAO,iBAAiB;AAAA,IACnE;AAAA,EACJ;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,uBAA0C;AAEtC,QAAI,KAAK,OAAO,cAAc,KAAK,OAAO,eAAe;AACrD,aAAO;AAAA,IACX;AAGA,QAAI,KAAK,kBAAkB;AACvB,aAAO;AAAA,IACX;AAGA,QAAI,KAAK,eAAe;AACpB,aAAO;AAAA,IACX;AAEA,WAAO;AAAA,EACX;AAAA;AAAA;AAAA;AAAA,EAKQ,kBAA6C;AACjD,WAAO,KAAK,oBAAoB,KAAK;AAAA,EACzC;AAAA;AAAA;AAAA;AAAA,EAKA,qBAA8C;AAC1C,WAAO,KAAK,OAAO,OAAO,OAAK,EAAE,YAAY;AAAA,EACjD;AAAA;AAAA;AAAA;AAAA,EAKA,cAAiD;AAC7C,WAAO,KAAK,OAAO,KAAK,OAAK,EAAE,KAAK;AAAA,EACxC;AAAA;AAAA;AAAA;AAAA,EAKA,eAAwB;AACpB,WAAO,KAAK,qBAAqB,MAAM;AAAA,EAC3C;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,kBAAkB,iBAA0C;AAC9D,UAAM,QAAQ,KAAK,OAAO,KAAK,OAAK,EAAE,oBAAoB,eAAe;AACzE,UAAM,SAAS,KAAK,gBAAgB;AACpC,QAAI,CAAC,SAAS,CAAC,QAAQ;AACnB,aAAO,OAAO,CAAC;AAAA,IACnB;AAEA,UAAM,SAAS,KAAK,OAAO,gBAAgB,eAAe,KAAK,MAAM;AACrE,UAAM,WAAW,IAAIA,SAAO,gBAAgB,MAAM;AAClD,WAAO,MAAM,SAAS,WAAW,OAAO,OAAO;AAAA,EACnD;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,iBACF,SACA,iBAC6C;AAC7C,UAAM,QAAQ,KAAK,OAAO,KAAK,OAAK,EAAE,oBAAoB,eAAe;AACzE,QAAI,CAAC,SAAS,CAAC,MAAM,cAAc;AAC/B,aAAO,EAAE,QAAQ,OAAO,SAASA,SAAO,YAAY;AAAA,IACxD;AAEA,UAAM,SAAS,KAAK,OAAO,gBAAgB,eAAe,KAAK,MAAM;AACrE,UAAM,WAAW,IAAIA,SAAO,gBAAgB,MAAM;AAClD,UAAM,UAAU,IAAIA,SAAO,SAAS,MAAM,cAAcC,oBAAmB,QAAQ;AAEnF,QAAI;AACA,YAAM,UAAU,MAAM,QAAQ,SAAS,OAAO;AAC9C,YAAM,SAAS,YAAYD,SAAO;AAClC,aAAO,EAAE,QAAQ,QAAQ;AAAA,IAC7B,SAAS,OAAO;AACZ,cAAQ,MAAM,2BAA2B,MAAM,IAAI,KAAK,KAAK;AAC7D,aAAO,EAAE,QAAQ,OAAO,SAASA,SAAO,YAAY;AAAA,IACxD;AAAA,EACJ;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,oBACF,SACA,iBACsB;AACtB,UAAM,QAAQ,KAAK,OAAO,KAAK,OAAK,EAAE,oBAAoB,eAAe;AACzE,QAAI,CAAC,SAAS,CAAC,MAAM,cAAc;AAC/B,aAAO;AAAA,IACX;AAEA,UAAM,SAAS,KAAK,OAAO,gBAAgB,eAAe,KAAK,MAAM;AACrE,UAAM,WAAW,IAAIA,SAAO,gBAAgB,MAAM;AAClD,UAAM,UAAU,IAAIA,SAAO,SAAS,MAAM,cAAcC,oBAAmB,QAAQ;AAEnF,QAAI;AACA,aAAO,MAAM,QAAQ,oBAAoB,OAAO;AAAA,IACpD,SAAS,OAAO;AACZ,cAAQ,MAAM,oCAAoC,MAAM,IAAI,KAAK,KAAK;AACtE,aAAO;AAAA,IACX;AAAA,EACJ;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAUA,MAAM,mBACF,SACA,iBAC6B;AAC7B,UAAM,QAAQ,KAAK,OAAO,KAAK,OAAK,EAAE,oBAAoB,eAAe;AAEzE,QAAI,CAAC,OAAO;AACR,aAAO;AAAA,QACH,SAAS;AAAA,QACT,OAAO;AAAA,QACP;AAAA,QACA,OAAO,SAAS,eAAe;AAAA,MACnC;AAAA,IACJ;AAEA,QAAI,CAAC,MAAM,cAAc;AACrB,aAAO;AAAA,QACH,SAAS;AAAA,QACT,OAAO,MAAM;AAAA,QACb;AAAA,QACA,OAAO,mCAAmC,MAAM,IAAI;AAAA,MACxD;AAAA,IACJ;AAEA,UAAM,SAAS,KAAK,qBAAqB;AAGzC,QAAI,WAAW,WAAW;AACtB,YAAM,aAAa,KAAK,OAAO,cAAc,KAAK,OAAO;AACzD,UAAI,YAAY;AACZ,eAAO,MAAM,KAAK,sBAAsB,SAAS,OAAO,UAAU;AAAA,MACtE;AAAA,IACJ;AAGA,UAAM,SAAS,KAAK,gBAAgB;AACpC,QAAI,CAAC,QAAQ;AACT,aAAO;AAAA,QACH,SAAS;AAAA,QACT,OAAO,MAAM;AAAA,QACb;AAAA,QACA,OAAO;AAAA,MACX;AAAA,IACJ;AAEA,UAAM,cAAc,WAAW,eAAe,eAAe;AAE7D,QAAI;AACA,YAAM,SAAS,KAAK,OAAO,gBAAgB,eAAe,KAAK,MAAM;AACrE,YAAM,WAAW,IAAID,SAAO,gBAAgB,MAAM;AAClD,YAAM,SAAS,OAAO,QAAQ,QAAQ;AACtC,YAAM,UAAU,IAAIA,SAAO,SAAS,MAAM,cAAcC,oBAAmB,MAAM;AAGjF,YAAM,gBAAgB,MAAM,QAAQ,SAAS,OAAO;AACpD,UAAI,kBAAkBD,SAAO,aAAa;AACtC,eAAO;AAAA,UACH,SAAS;AAAA,UACT,OAAO,MAAM;AAAA,UACb;AAAA,UACA,cAAc;AAAA,UACd,eAAe;AAAA,QACnB;AAAA,MACJ;AAGA,YAAM,UAAU,MAAM,SAAS,WAAW,OAAO,OAAO;AACxD,UAAI,UAAUA,SAAO,WAAW,OAAO,GAAG;AACtC,eAAO;AAAA,UACH,SAAS;AAAA,UACT,OAAO,MAAM;AAAA,UACb;AAAA,UACA,OAAO,gBAAgB,WAAW,uBAAuB,MAAM,IAAI;AAAA,QACvE;AAAA,MACJ;AAGA,cAAQ,IAAI,kCAAkC,MAAM,IAAI,KAAK,WAAW,gBAAgB;AACxF,YAAM,KAAK,MAAM,QAAQ,YAAY,OAAO;AAC5C,YAAM,UAAU,MAAM,GAAG,KAAK;AAG9B,YAAM,eAAe,MAAM,QAAQ,SAAS,OAAO;AAEnD,cAAQ,IAAI,oCAAoC,MAAM,IAAI,KAAK,YAAY,EAAE;AAE7E,aAAO;AAAA,QACH,SAAS;AAAA,QACT,OAAO,MAAM;AAAA,QACb;AAAA,QACA;AAAA,QACA,iBAAiB,QAAQ;AAAA,MAC7B;AAAA,IACJ,SAAS,OAAY;AACjB,cAAQ,MAAM,wCAAwC,MAAM,IAAI,KAAK,KAAK;AAC1E,aAAO;AAAA,QACH,SAAS;AAAA,QACT,OAAO,MAAM;AAAA,QACb;AAAA,QACA,OAAO,MAAM,WAAW;AAAA,MAC5B;AAAA,IACJ;AAAA,EACJ;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAUA,MAAc,sBACV,SACA,OACA,YAC6B;AAC7B,QAAI;AACA,YAAM,SAAS,KAAK,OAAO,iBAAiB,KAAK,OAAO;AAExD,YAAM,WAAW,MAAM,MAAM,GAAG,UAAU,iBAAiB;AAAA,QACvD,QAAQ;AAAA,QACR,SAAS;AAAA,UACL,gBAAgB;AAAA,UAChB,GAAI,UAAU;AAAA,YACV,iBAAiB,UAAU,MAAM;AAAA,UACrC;AAAA,QACJ;AAAA,QACA,MAAM,KAAK,UAAU;AAAA,UACjB;AAAA,UACA,iBAAiB,MAAM;AAAA,QAC3B,CAAC;AAAA,MACL,CAAC;AAED,UAAI,CAAC,SAAS,IAAI;AACd,cAAM,QAAQ,MAAM,SAAS,KAAK;AAGlC,gBAAQ,KAAK,8DAA8D;AAC3E,cAAM,SAAS,KAAK,gBAAgB;AACpC,YAAI,QAAQ;AACR,iBAAO,MAAM,KAAK,sBAAsB,SAAS,OAAO,MAAM;AAAA,QAClE;AAEA,cAAM,IAAI,MAAM,kBAAkB,KAAK,EAAE;AAAA,MAC7C;AAEA,YAAM,SAAS,MAAM,SAAS,KAAK;AACnC,aAAO;AAAA,QACH,SAAS;AAAA,QACT,OAAO,MAAM;AAAA,QACb,iBAAiB,MAAM;AAAA,QACvB,cAAc,OAAO;AAAA,QACrB,iBAAiB,OAAO;AAAA,QACxB,eAAe,OAAO;AAAA,MAC1B;AAAA,IACJ,SAAS,OAAY;AAEjB,cAAQ,KAAK,qCAAqC,MAAM,OAAO,EAAE;AACjE,YAAM,SAAS,KAAK,gBAAgB;AACpC,UAAI,QAAQ;AACR,gBAAQ,IAAI,0DAA0D;AACtE,eAAO,MAAM,KAAK,sBAAsB,SAAS,OAAO,MAAM;AAAA,MAClE;AAEA,aAAO;AAAA,QACH,SAAS;AAAA,QACT,OAAO,MAAM;AAAA,QACb,iBAAiB,MAAM;AAAA,QACvB,OAAO,MAAM,WAAW;AAAA,MAC5B;AAAA,IACJ;AAAA,EACJ;AAAA;AAAA;AAAA;AAAA,EAKA,MAAc,sBACV,SACA,OACA,QAC6B;AAC7B,QAAI,CAAC,MAAM,cAAc;AACrB,aAAO;AAAA,QACH,SAAS;AAAA,QACT,OAAO,MAAM;AAAA,QACb,iBAAiB,MAAM;AAAA,QACvB,OAAO,wBAAwB,MAAM,IAAI;AAAA,MAC7C;AAAA,IACJ;AAEA,QAAI;AACA,YAAM,SAAS,KAAK,OAAO,gBAAgB,MAAM,eAAe,KAAK,MAAM;AAC3E,YAAM,WAAW,IAAIA,SAAO,gBAAgB,MAAM;AAClD,YAAM,SAAS,OAAO,QAAQ,QAAQ;AACtC,YAAM,UAAU,IAAIA,SAAO,SAAS,MAAM,cAAcC,oBAAmB,MAAM;AAGjF,YAAM,gBAAgB,MAAM,QAAQ,SAAS,OAAO;AACpD,UAAI,kBAAkBD,SAAO,aAAa;AACtC,eAAO;AAAA,UACH,SAAS;AAAA,UACT,OAAO,MAAM;AAAA,UACb,iBAAiB,MAAM;AAAA,UACvB,cAAc;AAAA,UACd,eAAe;AAAA,QACnB;AAAA,MACJ;AAGA,YAAM,UAAU,MAAM,SAAS,WAAW,OAAO,OAAO;AACxD,UAAI,UAAUA,SAAO,WAAW,OAAO,GAAG;AACtC,eAAO;AAAA,UACH,SAAS;AAAA,UACT,OAAO,MAAM;AAAA,UACb,iBAAiB,MAAM;AAAA,UACvB,OAAO,mCAAmC,MAAM,IAAI;AAAA,QACxD;AAAA,MACJ;AAGA,YAAM,KAAK,MAAM,QAAQ,YAAY,OAAO;AAC5C,YAAM,UAAU,MAAM,GAAG,KAAK;AAC9B,YAAM,eAAe,MAAM,QAAQ,SAAS,OAAO;AAEnD,aAAO;AAAA,QACH,SAAS;AAAA,QACT,OAAO,MAAM;AAAA,QACb,iBAAiB,MAAM;AAAA,QACvB;AAAA,QACA,iBAAiB,QAAQ;AAAA,MAC7B;AAAA,IACJ,SAAS,OAAY;AACjB,aAAO;AAAA,QACH,SAAS;AAAA,QACT,OAAO,MAAM;AAAA,QACb,iBAAiB,MAAM;AAAA,QACvB,OAAO,MAAM,WAAW;AAAA,MAC5B;AAAA,IACJ;AAAA,EACJ;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,wBAAwB,SAAiD;AAC3E,UAAM,kBAAkB,KAAK,mBAAmB;AAChD,UAAM,UAAkC,CAAC;AACzC,UAAM,iBAAyC,CAAC;AAEhD,YAAQ,IAAI,mCAAmC,gBAAgB,MAAM,YAAY;AAGjF,eAAW,SAAS,iBAAiB;AACjC,YAAM,SAAS,MAAM,KAAK,mBAAmB,SAAS,MAAM,eAAe;AAC3E,cAAQ,KAAK,MAAM;AAEnB,UAAI,OAAO,WAAW,OAAO,cAAc;AACvC,uBAAe,MAAM,eAAe,IAAI,OAAO;AAAA,MACnD;AAAA,IACJ;AAEA,UAAM,gBAAgB,QAAQ,MAAM,OAAK,EAAE,OAAO;AAElD,WAAO;AAAA,MACH;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,IACJ;AAAA,EACJ;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,uBAAuB,SAAgF;AACzG,UAAM,kBAAkB,KAAK,mBAAmB;AAChD,UAAM,UAAgE,CAAC;AAEvE,eAAW,SAAS,iBAAiB;AACjC,cAAQ,MAAM,eAAe,IAAI,MAAM,KAAK,iBAAiB,SAAS,MAAM,eAAe;AAAA,IAC/F;AAEA,WAAO;AAAA,EACX;AACJ;AAqBO,SAAS,iBAAiB,SAA2B,CAAC,GAAe;AACxE,SAAO,IAAI,WAAW,MAAM;AAChC;;;AL/gBA,IAAM,wBAAwB,IAAI,KAAK;AAEhC,IAAM,aAAN,MAAiB;AAAA,EACJ;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACC;AAAA,EACA;AAAA;AAAA;AAAA,EAGA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACT,kBAA0C;AAAA,EAElD,YAAY,QAAuB;AAC/B,SAAK,QAAQ,OAAO;AACpB,SAAK,UAAU,OAAO,WAAW;AACjC,SAAK,oBAAoB,OAAO;AAChC,SAAK,eAAe,OAAO;AAG3B,SAAK,cAAc,OAAO,eAAe,OAAO;AAChD,SAAK,UAAU,IAAI,eAAe;AAAA,MAC9B,YAAY,OAAO;AAAA,IACvB,CAAC;AACD,SAAK,SAAS,IAAI,cAAc;AAAA,MAC5B,gBAAgB;AAAA,MAChB,kBAAkB,OAAO,iBAAiB;AAAA,IAC9C,CAAC;AACD,SAAK,UAAU,IAAI,eAAe;AAAA,MAC9B,eAAe;AAAA,MACf,UAAU;AAAA;AAAA,MACV,eAAe,OAAO,gBAAgB,CAAC;AAAA,IAC3C,CAAC;AACD,SAAK,eAAe,IAAI,mBAAmB;AAAA,MACvC,iBAAiB;AAAA,MACjB,uBAAuB;AAAA,IAC3B,CAAC;AAED,SAAK,gBAAgB,IAAI,cAAc;AAAA,MACnC,SAAS,KAAK;AAAA,MACd,SAAS,OAAO,gBAAgB,CAAC;AAAA,IACrC,CAAC;AACD,SAAK,aAAa,IAAI,kBAAkB;AAAA,MACpC,SAAS,KAAK;AAAA,MACd,YAAY,OAAO;AAAA,MACnB,WAAW,CAAC,CAAC,OAAO;AAAA,IACxB,CAAC;AACD,SAAK,UAAU,IAAI,WAAW;AAAA;AAAA,MAE1B,mBAAmB,OAAO;AAAA;AAAA,MAE1B,sBAAsB,OAAO;AAAA;AAAA,MAE7B,YAAY,OAAO;AAAA,MACnB,eAAe,OAAO;AAAA;AAAA,MAEtB,SAAS,KAAK;AAAA,MACd,eAAe,OAAO;AAAA,IAC1B,CAAC;AAGD,QAAI,OAAO,YAAY;AACnB,WAAK,UAAU,IAAI,cAAc;AAAA,QAC7B,SAAS,OAAO;AAAA,QAChB,QAAQ,OAAO;AAAA,MACnB,CAAC;AAAA,IACL;AAGA,SAAK,oBAAoB,IAAI,kBAAkB;AAAA,MAC3C,gBAAgB,KAAK,MAAM,UAAU,EAAE;AAAA;AAAA;AAAA;AAAA;AAAA,IAK3C,CAAC;AAGD,SAAK,iBAAiB,IAAI,sBAAsB;AAAA,MAC5C,iBAAiB;AAAA,MACjB,eAAe,KAAK,MAAM,UAAU,EAAE,KAAK,SAAS,QAAQ,IAAI,QAAQ;AAAA,MACxE,SAAS,OAAO,gBAAgB,CAAC;AAAA,MACjC,UAAU;AAAA;AAAA,IACd,CAAC;AAAA,EACL;AAAA,EAEA,iBAAiB;AACb,WAAO,KAAK,MAAM,UAAU;AAAA,EAChC;AAAA,EAEA,iBAA8B;AAC1B,WAAO,KAAK;AAAA,EAChB;AAAA,EAEA,MAAM,WAA4B;AAC9B,UAAM,aAAa,KAAK,QAAQ,cAAc;AAC9C,QAAI,CAAC,YAAY;AACb,YAAM,IAAI,MAAM,8EAA8E;AAAA,IAClG;AACA,WAAO,MAAM,KAAK,MAAM,SAAS,WAAW,OAAO;AAAA,EACvD;AAAA,EAEA,MAAM,gBAAiC;AACnC,WAAO,MAAM,KAAK,MAAM,cAAc;AAAA,EAC1C;AAAA,EAEA,MAAM,qBAAqB,QAAyC;AAChE,WAAO,MAAM,KAAK,MAAM,qBAAqB,MAAM;AAAA,EACvD;AAAA,EAEA,MAAM,oBAAoB,QAAwC;AAC9D,WAAO,MAAM,KAAK,MAAM,oBAAoB,MAAM;AAAA,EACtD;AAAA,EAEA,MAAM,mBAAmB,QAAuC;AAC5D,WAAO,MAAM,KAAK,MAAM,mBAAmB,MAAM;AAAA,EACrD;AAAA,EAEA,MAAM,SAAS,QAAwB,QAAsC;AACzE,UAAM,aAAa,KAAK,QAAQ,cAAc;AAC9C,QAAI,CAAC,YAAY;AACb,YAAM,IAAI,MAAM,8EAA8E;AAAA,IAClG;AAEA,UAAM,gBAAgB,MAAM,KAAK,qBAAqB,MAAM;AAC5D,UAAM,QAAQ,MAAM,KAAK,SAAS;AAClC,UAAM,YAAY;AAAA,MACd,WAAW;AAAA,MACX,OAAO;AAAA,MACP;AAAA,MACA;AAAA,IACJ;AAEA,UAAM,YAAY,MAAM,KAAK,QAAQ,KAAK,SAAS;AAEnD,WAAO,MAAM,KAAK,MAAM;AAAA,MACpB;AAAA,MACA,WAAW;AAAA,MACX,WAAW;AAAA,MACX,OAAO;AAAA,MACP;AAAA,MACA;AAAA,MACA;AAAA,IACJ;AAAA,EACJ;AAAA,EAEA,MAAM,QAAQ,QAAuB,QAAsC;AACvE,UAAM,aAAa,KAAK,QAAQ,cAAc;AAC9C,QAAI,CAAC,YAAY;AACb,YAAM,IAAI,MAAM,mBAAmB;AAAA,IACvC;AAEA,UAAM,gBAAgB,MAAM,KAAK,oBAAoB,MAAM;AAC3D,UAAM,QAAQ,MAAM,KAAK,SAAS;AAClC,UAAM,YAAY;AAAA,MACd,WAAW;AAAA,MACX,OAAO;AAAA,MACP;AAAA,MACA;AAAA,IACJ;AAEA,UAAM,YAAY,MAAM,KAAK,QAAQ,KAAK,SAAS;AAEnD,WAAO,MAAM,KAAK,MAAM;AAAA,MACpB;AAAA,MACA,WAAW;AAAA,MACX,WAAW;AAAA,MACX,OAAO;AAAA,MACP;AAAA,MACA;AAAA,MACA;AAAA,IACJ;AAAA,EACJ;AAAA,EAEA,MAAM,OAAO,QAAsB,QAAsC;AACrE,UAAM,aAAa,KAAK,QAAQ,cAAc;AAC9C,QAAI,CAAC,YAAY;AACb,YAAM,IAAI,MAAM,mBAAmB;AAAA,IACvC;AAEA,UAAM,gBAAgB,MAAM,KAAK,mBAAmB,MAAM;AAC1D,UAAM,QAAQ,MAAM,KAAK,SAAS;AAElC,UAAM,YAAY;AAAA,MACd,WAAW;AAAA,MACX,OAAO;AAAA,MACP;AAAA,MACA;AAAA,IACJ;AAEA,UAAM,YAAY,MAAM,KAAK,QAAQ,KAAK,SAAS;AAEnD,WAAO,MAAM,KAAK,MAAM;AAAA,MACpB;AAAA,MACA,WAAW;AAAA,MACX,WAAW;AAAA,MACX,OAAO;AAAA,MACP;AAAA,MACA;AAAA,MACA;AAAA,IACJ;AAAA,EACJ;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAYA,MAAM,cAAc,QAA+C;AAC/D,UAAM,aAAa,KAAK,QAAQ,cAAc;AAC9C,QAAI,CAAC,YAAY;AACb,YAAM,IAAI,MAAM,8EAA8E;AAAA,IAClG;AAGA,UAAM,gBAAgB,MAAM,KAAK,mBAAmB,MAAM;AAC1D,UAAM,QAAQ,MAAM,KAAK,SAAS;AAGlC,UAAM,YAAY;AAAA,MACd,WAAW;AAAA,MACX,OAAO;AAAA,MACP;AAAA,MACA;AAAA,IACJ;AAGA,UAAM,cAAc,KAAK,MAAM,UAAU;AAGzC,UAAM,YAAY,KAAK;AACvB,UAAM,WAAW,UAAU,YAAY,UAAU,cAAc;AAE/D,QAAI,OAAuB;AAAA,MACvB,WAAW,UAAW;AAAA;AAAA,MACtB,YAAY;AAAA,MACZ,YAAY;AAAA,MACZ,WAAW,UAAW;AAAA,MACtB,gBAAgB;AAAA,MAChB,UAAU;AAAA,IACd;AAEA,QAAI,UAAU;AACV,UAAI;AACA,eAAO,MAAM,KAAK,WAAW,aAAa,QAAQ,aAAa,QAAQ;AAAA,MAC3E,SAAS,GAAG;AACR,gBAAQ,KAAK,0CAA0C,CAAC;AAAA,MAC5D;AAAA,IACJ;AAEA,WAAO;AAAA,MACH;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA,aAAa,OAAO;AAAA,MACpB,kBAAkB,OAAO;AAAA,MACzB,YAAY,KAAK,IAAI;AAAA,MACrB,WAAW,KAAK,IAAI,IAAI;AAAA,IAC5B;AAAA,EACJ;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAUA,MAAM,cACF,UACA,QACA,YACqB;AACrB,UAAM,aAAa,KAAK,QAAQ,cAAc;AAC9C,QAAI,CAAC,YAAY;AACb,YAAM,IAAI,MAAM,mBAAmB;AAAA,IACvC;AAGA,QAAI,KAAK,IAAI,IAAI,SAAS,WAAW;AACjC,YAAM,IAAI,MAAM,iEAAiE;AAAA,IACrF;AAEA,UAAM,YAAY,KAAK,IAAI;AAC3B,UAAM,cAAc,KAAK,MAAM,UAAU;AACzC,UAAM,aAAa,wBAAwB,YAAY,UAAU,OAAO,EAAE;AAG1E,iBAAa;AAAA,MACT,QAAQ;AAAA,MACR,MAAM;AAAA,MACN,YAAY;AAAA,MACZ,SAAS;AAAA,IACb,CAAC;AAED,UAAM,YAAY,MAAM,KAAK,QAAQ,KAAK,SAAS,SAAS;AAG5D,iBAAa;AAAA,MACT,QAAQ;AAAA,MACR,MAAM;AAAA,MACN,YAAY;AAAA,MACZ,SAAS;AAAA,IACb,CAAC;AAED,UAAM,iBAAiB,MAAM,KAAK,MAAM;AAAA,MACpC;AAAA,MACA,WAAW;AAAA,MACX,WAAW;AAAA,MACX,SAAS,OAAO;AAAA,MAChB,SAAS;AAAA,MACT,SAAS;AAAA,MACT;AAAA,IACJ;AAGA,iBAAa;AAAA,MACT,QAAQ;AAAA,MACR,MAAM;AAAA,MACN,YAAY;AAAA,MACZ,SAAS;AAAA,MACT,SAAS,EAAE,QAAQ,eAAe,gBAAgB;AAAA,IACtD,CAAC;AAGD,SAAK,WAAW;AAAA,MACZ,eAAe;AAAA,MACf,SAAS;AAAA,MACT,SAAS;AAAA,MACT,eAAe;AAAA,MACf;AAAA,IACJ;AAGA,SAAK,aAAa;AAAA,MACd,eAAe;AAAA,MACf,YAAY;AAAA,MACZ;AAAA,MACA,eAAe;AAAA,IACnB;AAGA,QAAI;AACJ,QAAI;AACA,YAAM,MAAM,KAAK,WAAW;AAAA,QACxB,eAAe;AAAA,QACf;AAAA,MACJ;AAEA,WAAK,WAAW;AAAA,QACZ,eAAe;AAAA,QACf;AAAA,MACJ;AAAA,IACJ,SAAS,OAAO;AAGZ,cAAQ,KAAK,qBAAqB,KAAK;AAAA,IAC3C;AAKA,QAAI;AACJ,QAAI,OAAO,KAAK,SAAS;AACrB,mBAAa;AAAA,QACT,QAAQ;AAAA,QACR,MAAM;AAAA,QACN,YAAY;AAAA,QACZ,SAAS;AAAA,MACb,CAAC;AAAA,IACL;AAEA,iBAAa;AAAA,MACT,QAAQ;AAAA,MACR,MAAM;AAAA,MACN,YAAY;AAAA,MACZ,SAAS;AAAA,MACT,SAAS;AAAA,QACL,QAAQ,eAAe;AAAA,QACvB,UAAU,eAAe;AAAA,QACzB,UAAU,CAAC,CAAC;AAAA,QACZ;AAAA,MACJ;AAAA,IACJ,CAAC;AAGD,UAAM,eAAe,KAAK,gBAAgB;AAC1C,SAAK,QAAQ,gBAAgB,YAAY,iBAAiB,YAAY;AAEtE,WAAO;AAAA,MACH,GAAG;AAAA,MACH,QAAQ,SAAS;AAAA,MACjB,aAAa,SAAS;AAAA,MACtB,kBAAkB,SAAS;AAAA,MAC3B;AAAA,MACA;AAAA,MACA,UAAU,KAAK,IAAI,IAAI;AAAA,MACvB,WAAW,KAAK,IAAI;AAAA,IACxB;AAAA,EACJ;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,MAAM,iBACF,QACA,YACqB;AACrB,UAAM,aAAa,KAAK,QAAQ,cAAc;AAC9C,QAAI,CAAC,YAAY;AACb,YAAM,IAAI,MAAM,8EAA8E;AAAA,IAClG;AAEA,QAAI,CAAC,KAAK,SAAS;AACf,YAAM,IAAI,MAAM,kEAAkE;AAAA,IACtF;AAEA,UAAM,YAAY,KAAK,IAAI;AAE3B,iBAAa;AAAA,MACT,QAAQ;AAAA,MACR,MAAM;AAAA,MACN,YAAY;AAAA,MACZ,SAAS;AAAA,IACb,CAAC;AAGD,UAAM,gBAAgB,MAAM,KAAK,mBAAmB,MAAM;AAC1D,UAAM,QAAQ,MAAM,KAAK,SAAS;AAClC,UAAM,cAAc,KAAK,MAAM,UAAU;AACzC,UAAM,aAAa,YAAY,cAAc,YAAY;AAEzD,iBAAa;AAAA,MACT,QAAQ;AAAA,MACR,MAAM;AAAA,MACN,YAAY;AAAA,MACZ,SAAS;AAAA,IACb,CAAC;AAED,UAAM,YAAY;AAAA,MACd,OAAO;AAAA,MACP;AAAA,MACA;AAAA,MACA;AAAA,IACJ;AACA,UAAM,YAAY,MAAM,KAAK,QAAQ,KAAK,SAAS;AAEnD,iBAAa;AAAA,MACT,QAAQ;AAAA,MACR,MAAM;AAAA,MACN,YAAY;AAAA,MACZ,SAAS;AAAA,IACb,CAAC;AAGD,UAAM,gBAA2C;AAAA,MAC7C,mBAAmB,UAAU;AAAA,MAC7B,gBAAgB,UAAU;AAAA,MAC1B,gBAAgB,UAAU;AAAA,MAC1B,WAAW,UAAU;AAAA,MACrB,GAAG,OAAO,UAAU,EAAE,SAAS,EAAE,EAAE,SAAS,IAAI,GAAG;AAAA,MACnD,GAAG,OAAO,UAAU,EAAE,SAAS,EAAE,EAAE,SAAS,IAAI,GAAG;AAAA,MACnD,YAAY,OAAO,WAAW,WAAW,SAAS,EAAE,EAAE,SAAS,IAAI,GAAG;AAAA,MACtE,YAAY,OAAO,WAAW,WAAW,SAAS,EAAE,EAAE,SAAS,IAAI,GAAG;AAAA,MACtE,aAAa,OAAO;AAAA,MACpB;AAAA,MACA,OAAO,OAAO,KAAK;AAAA,IACvB;AAEA,UAAM,gBAAgB,MAAM,KAAK,QAAQ,mBAAmB,aAAa;AACzE,QAAI,CAAC,cAAc,SAAS;AACxB,YAAM,IAAI,MAAM,8BAA8B,cAAc,KAAK,EAAE;AAAA,IACvE;AAEA,UAAM,SAAS,cAAc,UAAU;AACvC,UAAM,WAAW,cAAc,WAAW,OAAO,cAAc,QAAQ,IAAI;AAE3E,QAAI,QAAQ;AACR,WAAK,aAAa,MAAM,QAAQ,YAAY,QAAW,YAAY,MAAS;AAAA,IAChF;AAGA,QAAI;AACJ,QAAI;AACA,YAAM,MAAM,KAAK,WAAW,iBAAiB,QAAQ,UAAU;AAAA,IACnE,QAAQ;AAAA,IAER;AAEA,iBAAa;AAAA,MACT,QAAQ;AAAA,MACR,MAAM;AAAA,MACN,YAAY;AAAA,MACZ,SAAS;AAAA,MACT,SAAS;AAAA,QACL;AAAA,QACA;AAAA,QACA,UAAU,CAAC,CAAC;AAAA,MAChB;AAAA,IACJ,CAAC;AAED,WAAO;AAAA,MACH,iBAAiB;AAAA,MACjB;AAAA,MACA,aAAa,WAAW;AAAA,MACxB,aAAa,OAAO;AAAA,MACpB,aAAa;AAAA,MACb;AAAA,MACA,aAAa,OAAO;AAAA,MACpB,kBAAkB,OAAO;AAAA,MACzB;AAAA,MACA,mBAAmB;AAAA,MACnB,UAAU,KAAK,IAAI,IAAI;AAAA,MACvB,WAAW,KAAK,IAAI;AAAA,IACxB;AAAA,EACJ;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAUA,MAAM,mBACF,QACA,QACA,YACqB;AACrB,iBAAa;AAAA,MACT,QAAQ;AAAA,MACR,MAAM;AAAA,MACN,YAAY;AAAA,MACZ,SAAS;AAAA,IACb,CAAC;AAED,UAAM,WAAW,MAAM,KAAK,cAAc,MAAM;AAChD,WAAO,MAAM,KAAK,cAAc,UAAU,QAAQ,UAAU;AAAA,EAChE;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASA,MAAM,uBAAuB,QAAiC;AAC1D,WAAO,MAAM,KAAK,WAAW,iBAAiB,MAAM;AAAA,EACxD;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,MAAM,cAAc,QAA+C;AAC/D,UAAM,cAAc,KAAK,MAAM,UAAU;AACzC,UAAM,YAAY,KAAK;AACvB,UAAM,WAAW,UAAU,YAAY,UAAU,cAAc;AAE/D,QAAI,CAAC,UAAU;AACX,YAAM,IAAI,MAAM,wBAAwB;AAAA,IAC5C;AAEA,WAAO,MAAM,KAAK,WAAW,aAAa,QAAQ,aAAa,QAAQ;AAAA,EAC3E;AAAA;AAAA;AAAA;AAAA,EAKA,oBAAwC;AACpC,WAAO,KAAK,WAAW,uBAAuB;AAAA,EAClD;AAAA;AAAA;AAAA;AAAA,EAKA,uBAAuB,UAA0B;AAC7C,UAAM,cAAc,KAAK,MAAM,UAAU;AACzC,UAAM,aAAa,YAAY,UAAU,OAAO;AAChD,WAAO,KAAK,WAAW;AAAA,MACnB,YAAY;AAAA,MACZ;AAAA,MACA;AAAA,IACJ;AAAA,EACJ;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAaA,MAAM,gBAAgB,QAAmD;AACrE,UAAM,aAAa,KAAK,QAAQ,cAAc;AAC9C,QAAI,CAAC,YAAY;AACb,YAAM,IAAI,MAAM,8EAA8E;AAAA,IAClG;AAGA,UAAM,gBAAgB,MAAM,KAAK,qBAAqB,MAAM;AAC5D,UAAM,QAAQ,MAAM,KAAK,SAAS;AAGlC,UAAM,YAAY;AAAA,MACd,WAAW;AAAA,MACX,OAAO;AAAA,MACP;AAAA,MACA;AAAA,IACJ;AAGA,UAAM,YAAY,KAAK;AACvB,QAAI,eAAe;AACnB,QAAI,WAAW;AAEf,QAAI,OAAO,UAAU,gBAAgB,YAAY;AAC7C,iBAAW,MAAM,UAAU,YAAY;AAAA,IAC3C;AAGA,UAAM,aAAa,MAAM,KAAK,cAAc;AAG5C,UAAM,UAAU,eAAe;AAC/B,UAAM,YAAY,UAAU;AAC5B,UAAM,gBAAgB,KAAK,UAAU,SAAS;AAE9C,WAAO;AAAA,MACH;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA,YAAY,KAAK,IAAI;AAAA,MACrB,WAAW,KAAK,IAAI,IAAI;AAAA,IAC5B;AAAA,EACJ;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;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAkCA,MAAM,sBAAsB,UAA0E;AAClG,WAAO,KAAK,kBAAkB,MAAM,QAAQ;AAAA,EAChD;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAmBA,MAAM,kBAAkB,SAA2C;AAC/D,UAAM,eAAe,KAAK,gBAAgB;AAC1C,UAAM,mBAAmB,WAAW,KAAK,MAAM,UAAU,EAAE;AAC3D,UAAM,SAAS,KAAK,eAAe,gBAAgB,KAAK,KAAK,MAAM,UAAU,EAAE;AAE/E,WAAO,KAAK,eAAe,kBAAkB,cAAc,kBAAkB,MAAM;AAAA,EACvF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAYA,MAAM,2BAA2B,SAAoD;AACjF,UAAM,eAAe,KAAK,gBAAgB;AAC1C,UAAM,mBAAmB,WAAW,KAAK,MAAM,UAAU,EAAE;AAC3D,UAAM,SAAS,KAAK,eAAe,gBAAgB,KAAK,KAAK,MAAM,UAAU,EAAE;AAE/E,WAAO,KAAK,eAAe,2BAA2B,cAAc,kBAAkB,EAAE,OAAO,CAAC;AAAA,EACpG;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAkBA,MAAM,mBAAmB,QAAgB,SAA6C;AAClF,UAAM,eAAe,KAAK,gBAAgB;AAC1C,UAAM,mBAAmB,WAAW,KAAK,MAAM,UAAU,EAAE;AAC3D,UAAM,SAAS,KAAK,eAAe,gBAAgB,KAAK,KAAK,MAAM,UAAU,EAAE;AAE/E,WAAO,KAAK,eAAe,sBAAsB,cAAc,kBAAkB,QAAQ,EAAE,OAAO,CAAC;AAAA,EACvG;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAgBA,MAAM,qBAAqB,UAA6C;AACpE,UAAM,aAAa,KAAK,QAAQ,cAAc;AAC9C,QAAI,CAAC,YAAY;AACb,YAAM,IAAI,MAAM,mBAAmB;AAAA,IACvC;AAEA,UAAM,gBAAgB,KAAK,eAAe,wBAAwB,QAAQ;AAC1E,UAAM,QAAQ,MAAM,KAAK,SAAS;AAClC,UAAM,cAAc,KAAK,MAAM,UAAU,EAAE;AAC3C,UAAM,YAAY,eAAe,WAAW,SAAS,aAAa,OAAO,aAAa;AACtF,UAAM,aAAa,MAAM,KAAK,cAAc;AAE5C,WAAO;AAAA,MACH,QAAQ;AAAA,QACJ;AAAA,QACA,OAAO;AAAA,QACP,WAAW,KAAK,gBAAgB;AAAA,QAChC,QAAQ;AAAA,MACZ;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA,cAAc;AAAA,MACd,UAAU;AAAA,MACV;AAAA,MACA,WAAW;AAAA,MACX,eAAe;AAAA,MACf,YAAY,KAAK,IAAI;AAAA,MACrB,WAAW,KAAK,IAAI,IAAI;AAAA,IAC5B;AAAA,EACJ;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAYA,MAAM,oBAA+C;AACjD,UAAM,aAAa,KAAK,QAAQ,cAAc;AAC9C,QAAI,CAAC,YAAY;AACb,YAAM,IAAI,MAAM,mBAAmB;AAAA,IACvC;AAEA,UAAM,gBAAgB,KAAK,eAAe,kBAAkB;AAC5D,UAAM,QAAQ,MAAM,KAAK,SAAS;AAClC,UAAM,cAAc,KAAK,MAAM,UAAU,EAAE;AAC3C,UAAM,YAAY,eAAe,WAAW,SAAS,aAAa,OAAO,aAAa;AACtF,UAAM,aAAa,MAAM,KAAK,cAAc;AAE5C,WAAO;AAAA,MACH,QAAQ;AAAA,QACJ;AAAA,QACA,OAAO;AAAA,QACP,WAAW,KAAK,gBAAgB;AAAA,QAChC,QAAQ;AAAA,MACZ;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA,cAAc;AAAA,MACd,UAAU;AAAA,MACV;AAAA,MACA,WAAW;AAAA,MACX,eAAe;AAAA,MACf,YAAY,KAAK,IAAI;AAAA,MACrB,WAAW,KAAK,IAAI,IAAI;AAAA,IAC5B;AAAA,EACJ;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAWA,MAAM,sBAAiD;AACnD,UAAM,aAAa,KAAK,QAAQ,cAAc;AAC9C,QAAI,CAAC,YAAY;AACb,YAAM,IAAI,MAAM,mBAAmB;AAAA,IACvC;AAEA,UAAM,gBAAgB,KAAK,eAAe,oBAAoB;AAC9D,UAAM,QAAQ,MAAM,KAAK,SAAS;AAClC,UAAM,cAAc,KAAK,MAAM,UAAU,EAAE;AAC3C,UAAM,YAAY,eAAe,WAAW,SAAS,aAAa,OAAO,aAAa;AACtF,UAAM,aAAa,MAAM,KAAK,cAAc;AAE5C,WAAO;AAAA,MACH,QAAQ;AAAA,QACJ;AAAA,QACA,OAAO;AAAA,QACP,WAAW,KAAK,gBAAgB;AAAA,QAChC,QAAQ;AAAA,MACZ;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA,cAAc;AAAA,MACd,UAAU;AAAA,MACV;AAAA,MACA,WAAW;AAAA,MACX,eAAe;AAAA,MACf,YAAY,KAAK,IAAI;AAAA,MACrB,WAAW,KAAK,IAAI,IAAI;AAAA,IAC5B;AAAA,EACJ;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAUA,MAAM,gBACF,UACA,QACuB;AACvB,UAAM,aAAa,KAAK,QAAQ,cAAc;AAC9C,QAAI,CAAC,YAAY;AACb,YAAM,IAAI,MAAM,mBAAmB;AAAA,IACvC;AAGA,QAAI,KAAK,IAAI,IAAI,SAAS,WAAW;AACjC,YAAM,IAAI,MAAM,qEAAqE;AAAA,IACzF;AAGA,UAAM,YAAY,MAAM,KAAK,QAAQ,KAAK,SAAS,SAAS;AAG5D,UAAM,SAAS,MAAM,KAAK,MAAM;AAAA,MAC5B;AAAA,MACA,WAAW;AAAA,MACX,WAAW;AAAA,MACX,SAAS,OAAO;AAAA,MAChB,SAAS;AAAA,MACT,SAAS;AAAA,MACT;AAAA,IACJ;AAGA,QAAI,OAAO,iBAAiB;AACxB,YAAMI,eAAc,KAAK,MAAM,UAAU;AACzC,WAAK,aAAa;AAAA,QACd,OAAO;AAAA,QACPA,aAAY;AAAA,QACZ;AAAA,QACA,OAAO;AAAA,MACX;AAAA,IACJ;AAGA,UAAM,eAAe,KAAK,gBAAgB;AAC1C,UAAM,cAAc,KAAK,MAAM,UAAU;AACzC,SAAK,QAAQ,gBAAgB,YAAY,iBAAiB,YAAY;AAEtE,WAAO;AAAA,MACH,GAAG;AAAA,MACH,QAAQ,SAAS;AAAA,MACjB,WAAW,KAAK,IAAI;AAAA,IACxB;AAAA,EACJ;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAUA,MAAM,qBACF,QACA,QACA,gBACuB;AACvB,UAAM,aAAa,KAAK,QAAQ,cAAc;AAC9C,QAAI,CAAC,YAAY;AACb,YAAM,IAAI,MAAM,mBAAmB;AAAA,IACvC;AAGA,UAAM,gBAAgB,MAAM,KAAK,qBAAqB,MAAM;AAC5D,UAAM,QAAQ,MAAM,KAAK,SAAS;AAClC,UAAM,YAAY;AAAA,MACd,WAAW;AAAA,MACX,OAAO;AAAA,MACP;AAAA,MACA;AAAA,IACJ;AAEA,UAAM,YAAY,MAAM,KAAK,QAAQ,KAAK,SAAS;AAEnD,UAAM,SAAS,MAAM,KAAK,MAAM;AAAA,MAC5B;AAAA,MACA,WAAW;AAAA,MACX,WAAW;AAAA,MACX,OAAO;AAAA,MACP;AAAA,MACA;AAAA,MACA;AAAA,IACJ;AAGA,QAAI,OAAO,iBAAiB;AACxB,YAAMA,eAAc,KAAK,MAAM,UAAU;AACzC,WAAK,aAAa;AAAA,QACd,OAAO;AAAA,QACPA,aAAY;AAAA,QACZ;AAAA,QACA,OAAO;AAAA,MACX;AAAA,IACJ;AAGA,UAAM,eAAe,KAAK,gBAAgB;AAC1C,UAAM,cAAc,KAAK,MAAM,UAAU;AACzC,SAAK,QAAQ,gBAAgB,YAAY,iBAAiB,YAAY;AAEtE,WAAO;AAAA,MACH,GAAG;AAAA,MACH;AAAA,MACA,WAAW,KAAK,IAAI;AAAA,IACxB;AAAA,EACJ;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAaA,MAAM,mBACF,QACA,gBACuB;AACvB,UAAM,aAAa,KAAK,QAAQ,cAAc;AAC9C,QAAI,CAAC,YAAY;AACb,YAAM,IAAI,MAAM,8EAA8E;AAAA,IAClG;AAGA,QAAI,CAAC,KAAK,SAAS;AACf,YAAM,IAAI,MAAM,kEAAkE;AAAA,IACtF;AAEA,UAAM,cAAc,KAAK,MAAM,UAAU;AAGzC,UAAM,gBAAgB,MAAM,KAAK,qBAAqB,MAAM;AAM5D,UAAM,WAAW,MAAM;AAAA,MACnB;AAAA,QACI;AAAA,QACA,aAAa,OAAO;AAAA,QACpB;AAAA,MACJ;AAAA,MACA,KAAK,eAAe;AAAA,IACxB;AAEA,UAAM,gBAAgB,KAAK,MAAM,IAAI,YAAY,EAAE,OAAO,SAAS,YAAY,CAAC;AAGhF,IAAC,cAAsB,gBAAgB;AAEvC,UAAM,gBAAgB,MAAM,KAAK,QAAQ,mBAAmB,aAAa;AAEzE,QAAI,CAAC,cAAc,SAAS;AACxB,YAAM,IAAI,MAAM,8BAA8B,cAAc,KAAK,EAAE;AAAA,IACvE;AAGA,QAAI,cAAc,QAAQ;AACtB,YAAM,aAAa,YAAY,cAAc,YAAY;AACzD,WAAK,aAAa;AAAA,QACd,cAAc;AAAA,QACd;AAAA,QACA;AAAA,QACA,cAAc,WAAW,OAAO,cAAc,QAAQ,IAAI;AAAA,MAC9D;AAAA,IACJ;AAGA,UAAM,eAAe,KAAK,gBAAgB;AAC1C,SAAK,QAAQ,gBAAgB,YAAY,iBAAiB,YAAY;AAEtE,WAAO;AAAA,MACH,iBAAiB,cAAc,UAAU;AAAA,MACzC,UAAU,cAAc,WAAW,OAAO,cAAc,QAAQ,IAAI;AAAA,MACpE,aAAa,WAAW;AAAA,MACxB,aAAa,OAAO;AAAA,MACpB,aAAa;AAAA;AAAA,MACb;AAAA,MACA,WAAW,KAAK,IAAI;AAAA,IACxB;AAAA,EACJ;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,MAAM,mBAAmB,MAAyC;AAC9D,UAAM,cAAc,KAAK,MAAM,UAAU;AACzC,WAAO,MAAM,KAAK,aAAa,oBAAoB,MAAM,YAAY,eAAe;AAAA,EACxF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAWA,MAAM,wBAA+C;AACjD,UAAM,eAAe,KAAK,gBAAgB;AAC1C,UAAM,cAAc,KAAK,MAAM,UAAU;AACzC,WAAO,MAAM,KAAK,QAAQ,iBAAiB,YAAY,iBAAiB,YAAY;AAAA,EACxF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,MAAM,iBAAiB,sBAA+B,OAAkC;AACpF,UAAM,eAAe,KAAK,gBAAgB;AAC1C,UAAM,cAAc,KAAK,MAAM,UAAU;AAIzC,UAAM,aAAa,KAAK,QAAQ,cAAc;AAC9C,QAAI,cAAc,KAAK,aAAa;AAChC,UAAI;AACA,cAAM,kBAAkB,YAAY;AACpC,cAAM,YAAY,aAAa,eAAe;AAC9C,cAAM,cAAc,UACf,OAAO,CAAC,MAAM,CAAC,cAAc,EAAE,OAAO,CAAC,EACvC,IAAI,CAAC,MAAM,EAAE,OAAO;AAEzB,cAAM,SAAS,MAAM,eAAe,WAAW,SAAS,KAAK,aAAa;AAAA,UACtE,SAAS,KAAK,UAAU,YAAY;AAAA,UACpC,gBAAgB,EAAE,CAAC,eAAe,GAAG,aAAa;AAAA,UAClD,mBAAmB,EAAE,CAAC,eAAe,GAAG,YAAY;AAAA,UACpD,SAAS,EAAE,CAAC,eAAe,GAAG,YAAY,OAAO;AAAA,UACjD,QAAQ;AAAA;AAAA,UAER,SAAS,KAAK,UAAU,OAAS;AAAA,UACjC,aAAa,KAAK,UAAU,IAAI;AAAA,QACpC,CAAC;AAED,cAAM,QAAQ,OAAO,OAAO,KAAK,CAAC,MAAM,EAAE,oBAAoB,eAAe;AAC7E,YAAI,SAAS,CAAC,MAAM,OAAO;AACvB,gBAAM,YAAY,IAAI,IAAI,MAAM,SAAS,IAAI,CAAC,MAAM,CAAC,EAAE,QAAQ,YAAY,GAAG,CAAC,CAAU,CAAC;AAC1F,gBAAM,SAAS,UAAU,IAAI,CAAC,MAAM;AAChC,gBAAI,cAAc,EAAE,OAAO,GAAG;AAC1B,qBAAO;AAAA,YACX;AACA,kBAAM,QAAQ,UAAU,IAAI,EAAE,QAAQ,YAAY,CAAC;AACnD,kBAAM,SAAS,OAAO,UAAU;AAChC,kBAAM,YAAYC,SAAO,YAAY,QAAQ,EAAE,QAAQ;AACvD,mBAAO;AAAA,cACH,OAAO;AAAA,cACP,SAAS;AAAA,cACT;AAAA,cACA,UAAU,OAAO;AAAA,YACrB;AAAA,UACJ,CAAC,EAAE,OAAO,CAAC,MAAkC,CAAC,CAAC,CAAC;AAGhD,gBAAM,SAAS,MAAM,KAAK,QAAQ,iBAAiB,iBAAiB,YAAY;AAChF,gBAAM,SAAS,CAAC,QAAQ,GAAG,MAAM;AAEjC,gBAAM,WAAW,sBAAsB,SAAS,OAAO,OAAO,CAAC,MAAM,EAAE,UAAU,EAAE;AACnF,gBAAM,gBAAgB,SAAS,OAAO,CAAC,KAAK,MAAM,OAAO,EAAE,YAAY,IAAI,CAAC;AAE5E,iBAAO;AAAA,YACH;AAAA,YACA,WAAW,YAAY;AAAA,YACvB,SAAS;AAAA,YACT,QAAQ;AAAA,YACR,eAAe,iBAAiB;AAAA,YAChC,aAAa,KAAK,IAAI;AAAA,UAC1B;AAAA,QACJ;AAAA,MACJ,QAAQ;AAAA,MAER;AAAA,IACJ;AAEA,WAAO,MAAM,KAAK,QAAQ,oBAAoB,YAAY,iBAAiB,cAAc,mBAAmB;AAAA,EAChH;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,MAAM,qBAAqB,cAA6C;AACpE,UAAM,eAAe,KAAK,gBAAgB;AAC1C,UAAM,cAAc,KAAK,MAAM,UAAU;AACzC,WAAO,MAAM,KAAK,QAAQ;AAAA,MACtB,YAAY;AAAA,MACZ;AAAA,MACA;AAAA,IACJ;AAAA,EACJ;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,MAAM,sBAAsB,UAAiD;AACzE,UAAM,aAAa,KAAK,QAAQ,cAAc;AAC9C,QAAI,CAAC,YAAY;AACb,YAAM,IAAI,MAAM,mBAAmB;AAAA,IACvC;AAGA,UAAM,UAA8B,CAAC;AAErC,eAAW,mBAAmB,UAAU;AACpC,YAAM,cAAc,KAAK,cAAc,eAAe,eAAe;AAGrE,UAAI,CAAC,aAAa;AAEd,gBAAQ,KAAK,iCAAiC,eAAe,EAAE;AAC/D;AAAA,MACJ;AAGA,YAAM,UAAU,KAAK,cAAc,mBAAmB,YAAY,eAAe;AACjF,YAAM,UAAU,SAAS,YAAY,oBAAoB,KAAK,MAAM,UAAU,EAAE,kBAC1E,KAAK,gBAAgB,IACrB,WAAW;AAEjB,UAAI,YAAY,OAAO;AACnB,YAAI;AACA,gBAAM,YAAY,MAAM,KAAK,QAAQ,oBAAoB,iBAAiB,SAAS,KAAK;AACxF,kBAAQ,KAAK,SAAS;AAAA,QAC1B,SAAS,OAAO;AAEZ,kBAAQ,KAAK,0CAA0C,eAAe,KAAK,KAAK;AAAA,QACpF;AACA;AAAA,MACJ;AAGA,UAAI;AACA,cAAM,SAAc,KAAK,cAAc,aAAa,eAAe;AACnE,YAAI,OAAO,OAAO,qBAAqB,YAAY;AAE/C,kBAAQ,KAAK,uCAAuC,eAAe,EAAE;AACrE;AAAA,QACJ;AAEA,cAAM,SAAS,MAAM,OAAO,iBAAiB,OAAO;AACpD,cAAM,OAAO,KAAK,cAAc,yBAAyB,eAAe;AAExE,cAAM,WAAW,MAAM,YAAY;AACnC,cAAM,YAAY,WAAW,IAAIA,SAAO,YAAY,QAAQ,QAAQ,IAAI,OAAO,SAAS;AAExF,gBAAQ,KAAK;AAAA,UACT;AAAA,UACA,WAAW,YAAY;AAAA,UACvB;AAAA,UACA,QAAQ;AAAA,YACJ;AAAA,cACI,OAAO;AAAA,gBACH,QAAQ,MAAM,UAAU;AAAA,gBACxB,MAAM,MAAM,QAAQ;AAAA,gBACpB,SAAS;AAAA,gBACT;AAAA,gBACA,UAAU;AAAA,cACd;AAAA,cACA,SAAS;AAAA,cACT;AAAA,YACJ;AAAA,UACJ;AAAA,UACA,aAAa,KAAK,IAAI;AAAA,QAC1B,CAAC;AAAA,MACL,SAAS,OAAO;AAEZ,gBAAQ,KAAK,8CAA8C,eAAe,KAAK,KAAK;AAAA,MACxF;AAAA,IACJ;AAEA,WAAO;AAAA,EACX;AAAA;AAAA;AAAA;AAAA,EAKA,aAAa,iBAAuC;AAChD,UAAM,UAAU,mBAAmB,KAAK,MAAM,UAAU,EAAE;AAC1D,WAAO,aAAa,OAAO;AAAA,EAC/B;AAAA;AAAA;AAAA;AAAA,EAKA,iBAAiB,QAAgB,iBAA4C;AACzE,UAAM,UAAU,mBAAmB,KAAK,MAAM,UAAU,EAAE;AAC1D,WAAO,iBAAiB,SAAS,MAAM;AAAA,EAC3C;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAYA,oBAAoC;AAChC,UAAM,eAAe,KAAK,gBAAgB;AAC1C,UAAM,cAAc,KAAK,MAAM,UAAU;AAGzC,UAAM,WAAW,YAAY,QACvB,YAAY,YAAY,IAAI,YAAY,OAAO,KAC/C;AAGN,UAAM,WAAW,GAAG,YAAY;AAEhC,WAAO;AAAA,MACH,SAAS;AAAA,MACT,WAAW,YAAY;AAAA,MACvB,iBAAiB,YAAY;AAAA,MAC7B;AAAA,MACA;AAAA,IACJ;AAAA,EACJ;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAUA,kBACI,QACA,eAAuB,UACvB,gBAAwB,IACV;AACd,UAAM,eAAe,KAAK,gBAAgB;AAC1C,UAAM,cAAc,KAAK,MAAM,UAAU;AAGzC,UAAM,kBAAkB,KAAK,YAAY,QAAQ,aAAa;AAG9D,QAAI;AACJ,QAAI,YAAY,OAAO;AACnB,UAAI,cAAc,YAAY,GAAG;AAC7B,mBAAW,YAAY,YAAY,IAAI,YAAY,OAAO,UAAU,OAAO,SAAS,CAAC;AAAA,MACzF,OAAO;AAEH,mBAAW,YAAY,YAAY,IAAI,YAAY,OAAO,qBAAqB,YAAY,YAAY,OAAO,SAAS,CAAC;AAAA,MAC5H;AAAA,IACJ;AAEA,WAAO;AAAA,MACH,SAAS;AAAA,MACT,WAAW,YAAY;AAAA,MACvB,iBAAiB,YAAY;AAAA,MAC7B;AAAA,MACA,UAAU,GAAG,YAAY,KAAK,eAAe;AAAA,IACjD;AAAA,EACJ;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASQ,UAAU,KAAqB;AAEnC,UAAM,QAAQ,OAAO,GAAG,IAAI;AAC5B,WAAO,GAAG,MAAM,QAAQ,CAAC,CAAC;AAAA,EAC9B;AAAA;AAAA;AAAA;AAAA,EAKQ,YAAY,QAAgB,UAA0B;AAC1D,UAAM,UAAU,OAAO,MAAM,QAAQ;AACrC,UAAM,QAAQ,SAAS;AACvB,UAAM,YAAY,SAAS;AAC3B,UAAM,eAAe,UAAU,SAAS,EAAE,SAAS,UAAU,GAAG;AAChE,UAAM,UAAU,aAAa,MAAM,GAAG,CAAC,EAAE,QAAQ,OAAO,EAAE,KAAK;AAC/D,WAAO,GAAG,KAAK,IAAI,OAAO;AAAA,EAC9B;AAAA,EAGA,MAAM,aAAa,eAAmD;AAClE,UAAM,aAAa,KAAK,QAAQ,cAAc;AAC9C,QAAI,CAAC,YAAY;AACb,YAAM,IAAI,MAAM,mBAAmB;AAAA,IACvC;AAEA,UAAM,cAAc,KAAK,MAAM,UAAU;AACzC,UAAM,eAAe,iBAAiB,YAAY;AAElD,QAAI,iBAAiB,YAAY,iBAAiB;AAC9C,YAAM,IAAI,MAAM,2FAA2F;AAAA,IAC/G;AAEA,UAAM,eAAe,MAAM,KAAK,MAAM,gBAAgB,WAAW,OAAO;AACxE,UAAM,SAAS,MAAM,KAAK,MAAM,YAAY,WAAW,OAAO;AAE9D,QAAI,CAAC,gBAAgB,CAAC,QAAQ;AAC1B,aAAO;AAAA,IACX;AAEA,WAAO;AAAA,MACH,SAAS;AAAA,MACT,cAAc,WAAW;AAAA,MACzB,OAAO,YAAY;AAAA,MACnB,iBAAiB,YAAY;AAAA,MAC7B;AAAA,IACJ;AAAA,EACJ;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAYA,kBAA0B;AACtB,UAAM,aAAa,KAAK,QAAQ,cAAc;AAC9C,QAAI,CAAC,YAAY;AACb,YAAM,IAAI,MAAM,8EAA8E;AAAA,IAClG;AAEA,WAAO,KAAK,MAAM,oBAAoB,WAAW,OAAO;AAAA,EAC5D;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,0BAA0B,SAAyB;AAC/C,WAAO,KAAK,MAAM,oBAAoB,OAAO;AAAA,EACjD;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAUA,wBAAwB,iBAAyB,SAAiC;AAC9E,UAAM,OAAO,WAAW,KAAK,QAAQ,cAAc,GAAG;AACtD,QAAI,CAAC,MAAM;AACP,YAAM,IAAI,MAAM,2CAA2C;AAAA,IAC/D;AAEA,UAAM,aAAa,EAAE,SAAS,KAAK;AACnC,UAAM,UAAU,KAAK,cAAc,mBAAmB,YAAY,eAAe;AACjF,WAAO,SAAS,WAAW;AAAA,EAC/B;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAUA,MAAM,yBACF,iBACA,sBAA+B,OACN;AACzB,UAAM,aAAa,KAAK,QAAQ,cAAc;AAC9C,QAAI,CAAC,YAAY;AACb,YAAM,IAAI,MAAM,mBAAmB;AAAA,IACvC;AAGA,UAAM,eAAe,KAAK,wBAAwB,iBAAiB,WAAW,OAAO;AACrF,QAAI,CAAC,cAAc;AACf,YAAM,IAAI,MAAM,yCAAyC,eAAe,EAAE;AAAA,IAC9E;AAEA,UAAM,cAAc,KAAK,cAAc,eAAe,eAAe;AACrE,QAAI,CAAC,aAAa;AACd,YAAM,IAAI,MAAM,iBAAiB,eAAe,EAAE;AAAA,IACtD;AAGA,QAAI,KAAK,aAAa;AAClB,UAAI;AACA,cAAM,YAAY,aAAa,eAAe;AAC9C,cAAM,cAAc,UACf,OAAO,CAAC,MAAM,CAAC,cAAc,EAAE,OAAO,CAAC,EACvC,IAAI,CAAC,MAAM,EAAE,OAAO;AAEzB,cAAM,SAAS,KAAK,eAAe,eAAe,KAAK,YAAY;AAEnE,cAAM,SAAS,MAAM,eAAe,WAAW,SAAS,KAAK,aAAa;AAAA,UACtE,SAAS,KAAK,UAAU,YAAY;AAAA,UACpC,gBAAgB,EAAE,CAAC,eAAe,GAAG,aAAa;AAAA,UAClD,mBAAmB,EAAE,CAAC,eAAe,GAAG,YAAY;AAAA,UACpD,SAAS,EAAE,CAAC,eAAe,GAAG,OAAO;AAAA,UACrC,QAAQ;AAAA,UACR,SAAS,KAAK,UAAU,OAAS;AAAA,UACjC,aAAa,KAAK,UAAU,IAAI;AAAA,QACpC,CAAC;AAED,cAAM,QAAQ,OAAO,OAAO,KAAK,CAAC,MAAM,EAAE,oBAAoB,eAAe;AAC7E,YAAI,SAAS,CAAC,MAAM,OAAO;AACvB,gBAAM,YAAY,IAAI,IAAI,MAAM,SAAS,IAAI,CAAC,MAAM,CAAC,EAAE,QAAQ,YAAY,GAAG,CAAC,CAAU,CAAC;AAC1F,gBAAM,SAAS,UAAU,IAAI,CAAC,MAAM;AAChC,gBAAI,cAAc,EAAE,OAAO,GAAG;AAC1B,qBAAO;AAAA,YACX;AACA,kBAAM,QAAQ,UAAU,IAAI,EAAE,QAAQ,YAAY,CAAC;AACnD,kBAAM,SAAS,OAAO,UAAU;AAChC,kBAAM,YAAYA,SAAO,YAAY,QAAQ,EAAE,QAAQ;AACvD,mBAAO;AAAA,cACH,OAAO;AAAA,cACP,SAAS;AAAA,cACT;AAAA,cACA,UAAU,OAAO;AAAA,YACrB;AAAA,UACJ,CAAC,EAAE,OAAO,CAAC,MAAkC,CAAC,CAAC,CAAC;AAGhD,gBAAM,SAAS,MAAM,KAAK,QAAQ,iBAAiB,iBAAiB,YAAY;AAChF,gBAAM,SAAS,CAAC,QAAQ,GAAG,MAAM;AAEjC,gBAAM,WAAW,sBAAsB,SAAS,OAAO,OAAO,CAAC,MAAM,EAAE,UAAU,EAAE;AACnF,gBAAM,gBAAgB,SAAS,OAAO,CAAC,KAAK,MAAM,OAAO,EAAE,YAAY,IAAI,CAAC;AAE5E,iBAAO;AAAA,YACH;AAAA,YACA,WAAW,YAAY;AAAA,YACvB,SAAS;AAAA,YACT,QAAQ;AAAA,YACR,eAAe,iBAAiB;AAAA,YAChC,aAAa,KAAK,IAAI;AAAA,UAC1B;AAAA,QACJ;AAAA,MACJ,QAAQ;AAAA,MAER;AAAA,IACJ;AAGA,WAAO,MAAM,KAAK,QAAQ,oBAAoB,iBAAiB,cAAc,mBAAmB;AAAA,EACpG;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,MAAM,qBAA+C;AACjD,UAAM,aAAa,KAAK,QAAQ,cAAc;AAC9C,QAAI,CAAC,YAAY;AACb,YAAM,IAAI,MAAM,8EAA8E;AAAA,IAClG;AAGA,QAAI,KAAK,mBAAmB,KAAK,gBAAgB,YAAY,WAAW,SAAS;AAC7E,aAAO,KAAK;AAAA,IAChB;AAGA,UAAM,iBAAiB,KAAK,OAAO,wBAAwB,WAAW,OAAO;AAC7E,QAAI,gBAAgB;AAChB,WAAK,kBAAkB;AAEvB,YAAM,KAAK,uBAAuB;AAClC,aAAO,KAAK;AAAA,IAChB;AAGA,UAAM,cAAc,KAAK,MAAM,UAAU;AACzC,UAAM,YAA4B,CAAC;AAGnC,QAAI;AACA,YAAM,UAAU,KAAK,MAAM,oBAAoB,WAAW,OAAO;AACjE,YAAM,WAAW,MAAM,KAAK,MAAM,YAAY,WAAW,OAAO;AAEhE,gBAAU,KAAK;AAAA,QACX,iBAAiB,YAAY;AAAA,QAC7B,WAAW,YAAY;AAAA,QACvB;AAAA,QACA,OAAO,YAAY;AAAA,QACnB;AAAA,QACA,gBAAgB;AAAA,MACpB,CAAC;AAAA,IACL,SAAS,OAAO;AACZ,cAAQ,KAAK,sDAAsD,KAAK;AAAA,IAC5E;AAEA,SAAK,kBAAkB;AAAA,MACnB,SAAS,WAAW;AAAA,MACpB,YAAY,WAAW;AAAA,MACvB,YAAY,WAAW;AAAA,MACvB,cAAc,WAAW;AAAA,MACzB;AAAA,MACA,WAAW,KAAK,IAAI;AAAA,MACpB,WAAW,KAAK,IAAI;AAAA,IACxB;AAEA,WAAO,KAAK;AAAA,EAChB;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,yBAAuD;AACzD,UAAM,WAAW,MAAM,KAAK,mBAAmB;AAC/C,UAAM,cAAc,KAAK,MAAM,UAAU;AAEzC,WAAO,SAAS,UAAU;AAAA,MACtB,OAAK,EAAE,oBAAoB,YAAY;AAAA,IAC3C,KAAK;AAAA,EACT;AAAA;AAAA;AAAA;AAAA,EAKA,MAAc,yBAAwC;AAClD,QAAI,CAAC,KAAK,gBAAiB;AAE3B,UAAM,cAAc,KAAK,MAAM,UAAU;AACzC,UAAM,UAAU,KAAK,gBAAgB,UAAU;AAAA,MAC3C,OAAK,EAAE,oBAAoB,YAAY;AAAA,IAC3C;AAEA,QAAI,SAAS;AACT,UAAI;AACA,cAAM,WAAW,MAAM,KAAK,MAAM,YAAY,KAAK,gBAAgB,OAAO;AAC1E,gBAAQ,WAAW;AACnB,aAAK,gBAAgB,YAAY,KAAK,IAAI;AAAA,MAC9C,SAAS,OAAO;AACZ,gBAAQ,KAAK,uCAAuC,KAAK;AAAA,MAC7D;AAAA,IACJ;AAAA,EACJ;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,gBAAgB,SAA6B;AACzC,QAAI,CAAC,KAAK,iBAAiB;AACvB,YAAM,IAAI,MAAM,sDAAsD;AAAA,IAC1E;AAEA,UAAM,WAAW,KAAK,gBAAgB,UAAU;AAAA,MAC5C,OAAK,EAAE,oBAAoB,QAAQ;AAAA,IACvC;AAEA,QAAI,YAAY,GAAG;AACf,WAAK,gBAAgB,UAAU,QAAQ,IAAI;AAAA,IAC/C,OAAO;AACH,WAAK,gBAAgB,UAAU,KAAK,OAAO;AAAA,IAC/C;AAEA,SAAK,gBAAgB,YAAY,KAAK,IAAI;AAAA,EAC9C;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAYA,MAAM,YAAY,QAA2C;AACzD,UAAM,aAAa,KAAK,QAAQ,cAAc;AAC9C,QAAI,CAAC,YAAY;AACb,YAAM,IAAI,MAAM,mBAAmB;AAAA,IACvC;AAEA,UAAM,SAAS,MAAM,KAAK,MAAM,YAAY,WAAW,SAAS,MAAM;AAGtE,QAAI,KAAK,iBAAiB;AACtB,YAAM,cAAc,KAAK,MAAM,UAAU;AACzC,YAAM,UAAU,KAAK,gBAAgB,UAAU;AAAA,QAC3C,OAAK,EAAE,oBAAoB,YAAY;AAAA,MAC3C;AAEA,UAAI,SAAS;AACT,gBAAQ,WAAW;AACnB,gBAAQ,mBAAmB,OAAO;AAAA,MACtC,OAAO;AACH,aAAK,gBAAgB,UAAU,KAAK;AAAA,UAChC,iBAAiB,YAAY;AAAA,UAC7B,WAAW,YAAY;AAAA,UACvB,SAAS,OAAO;AAAA,UAChB,OAAO,YAAY;AAAA,UACnB,UAAU;AAAA,UACV,kBAAkB,OAAO;AAAA,UACzB,gBAAgB;AAAA,QACpB,CAAC;AAAA,MACL;AAEA,WAAK,gBAAgB,YAAY,KAAK,IAAI;AAAA,IAC9C;AAEA,WAAO;AAAA,EACX;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAWA,MAAM,qBAAqB,iBAAwD;AAC/E,UAAM,aAAa,KAAK,QAAQ,cAAc;AAC9C,QAAI,CAAC,YAAY;AACb,YAAM,IAAI,MAAM,mBAAmB;AAAA,IACvC;AAEA,QAAI,CAAC,KAAK,mBAAmB;AACzB,YAAM,IAAI,MAAM,oEAAoE;AAAA,IACxF;AAGA,QAAI,CAAC,KAAK,MAAM,sBAAsB;AAClC,YAAM,IAAI,MAAM,gEAAgE;AAAA,IACpF;AAGA,UAAM,cAAc,KAAK,MAAM,UAAU;AACzC,UAAM,gBAAgB,mBAAmB,YAAY;AACrD,UAAM,SAAS,KAAK,eAAe,aAAa,KAAK,YAAY;AAEjE,UAAM,SAAS,MAAM,KAAK,MAAM;AAAA,MAC5B,WAAW;AAAA,MACX,KAAK;AAAA,MACL;AAAA,IACJ;AAGA,QAAI,KAAK,iBAAiB;AACtB,YAAM,UAAU,KAAK,gBAAgB,UAAU;AAAA,QAC3C,OAAK,EAAE,oBAAoB;AAAA,MAC/B;AAEA,UAAI,SAAS;AACT,gBAAQ,WAAW;AACnB,gBAAQ,mBAAmB,OAAO;AAAA,MACtC,OAAO;AACH,aAAK,gBAAgB,UAAU,KAAK;AAAA,UAChC,iBAAiB;AAAA,UACjB,WAAW,YAAY;AAAA,UACvB,SAAS,OAAO;AAAA,UAChB,OAAO,YAAY;AAAA,UACnB,UAAU;AAAA,UACV,kBAAkB,OAAO;AAAA,UACzB,gBAAgB;AAAA,QACpB,CAAC;AAAA,MACL;AAEA,WAAK,gBAAgB,YAAY,KAAK,IAAI;AAAA,IAC9C;AAEA,WAAO;AAAA,EACX;AAAA;AAAA;AAAA;AAAA,EAKA,4BAAqC;AACjC,WAAO,CAAC,CAAC,KAAK,qBAAqB,CAAC,CAAC,KAAK,MAAM;AAAA,EACpD;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASA,MAAM,gBAAgB,QAA+B;AACjD,UAAM,aAAa,KAAK,QAAQ,cAAc;AAC9C,QAAI,CAAC,YAAY;AACb,YAAM,IAAI,MAAM,mBAAmB;AAAA,IACvC;AAEA,UAAM,SAAS,MAAM,KAAK,MAAM,YAAY,WAAW,OAAO;AAC9D,QAAI,QAAQ;AACR,aAAO,KAAK,gBAAgB;AAAA,IAChC;AAGA,QAAI,KAAK,0BAA0B,GAAG;AAClC,YAAMC,UAAS,MAAM,KAAK,qBAAqB;AAC/C,aAAOA,QAAO;AAAA,IAClB;AAGA,QAAI,CAAC,QAAQ;AACT,YAAM,IAAI,MAAM,iEAAiE;AAAA,IACrF;AAEA,UAAM,SAAS,MAAM,KAAK,YAAY,MAAM;AAC5C,WAAO,OAAO;AAAA,EAClB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,MAAM,YAAY,QAA8B;AAC5C,UAAM,aAAa,KAAK,QAAQ,cAAc;AAC9C,QAAI,CAAC,YAAY;AACb,YAAM,IAAI,MAAM,mBAAmB;AAAA,IACvC;AAEA,UAAM,SAAS,MAAM,KAAK,MAAM,YAAY,WAAW,OAAO;AAC9D,QAAI,QAAQ;AACR,aAAO,KAAK,gBAAgB;AAAA,IAChC;AAEA,UAAM,SAAS,MAAM,KAAK,YAAY,MAAM;AAC5C,WAAO,OAAO;AAAA,EAClB;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,2BAA4C;AAC9C,UAAM,aAAa,KAAK,QAAQ,cAAc;AAC9C,QAAI,CAAC,YAAY;AACb,YAAM,IAAI,MAAM,mBAAmB;AAAA,IACvC;AAEA,WAAO,MAAM,KAAK,MAAM,yBAAyB,WAAW,OAAO;AAAA,EACvE;AAAA,EAEA,MAAM,cAAgC;AAClC,UAAM,aAAa,KAAK,QAAQ,cAAc;AAC9C,QAAI,CAAC,YAAY;AACb,YAAM,IAAI,MAAM,mBAAmB;AAAA,IACvC;AAEA,WAAO,MAAM,KAAK,MAAM,YAAY,WAAW,OAAO;AAAA,EAC1D;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAWA,yBAAkC;AAC9B,WAAO,KAAK,QAAQ,aAAa;AAAA,EACrC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAaA,uBAAsE;AAClE,WAAO,KAAK,QAAQ,qBAAqB;AAAA,EAC7C;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,qBAA8C;AAC1C,WAAO,KAAK,QAAQ,mBAAmB;AAAA,EAC3C;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASA,MAAM,qBAAqB,iBAAwD;AAC/E,UAAM,aAAa,KAAK,QAAQ,cAAc;AAC9C,QAAI,CAAC,YAAY;AACb,YAAM,IAAI,MAAM,8EAA8E;AAAA,IAClG;AAEA,QAAI,CAAC,KAAK,QAAQ,aAAa,GAAG;AAC9B,YAAM,IAAI,MAAM,sEAAsE;AAAA,IAC1F;AAEA,UAAM,SAAS,MAAM,KAAK,QAAQ,mBAAmB,WAAW,SAAS,eAAe;AAGxF,QAAI,OAAO,WAAW,OAAO,gBAAgB,KAAK,iBAAiB;AAC/D,YAAM,kBAAkB,KAAK,gBAAgB,UAAU;AAAA,QACnD,OAAK,EAAE,oBAAoB;AAAA,MAC/B;AAEA,UAAI,iBAAiB;AACjB,wBAAgB,WAAW;AAC3B,wBAAgB,mBAAmB,OAAO;AAC1C,wBAAgB,UAAU,OAAO;AAAA,MACrC,OAAO;AACH,aAAK,gBAAgB,UAAU,KAAK;AAAA,UAChC;AAAA,UACA,WAAW,OAAO;AAAA,UAClB,SAAS,OAAO;AAAA,UAChB,OAAO;AAAA,UACP,UAAU;AAAA,UACV,kBAAkB,OAAO;AAAA,UACzB,gBAAgB;AAAA,QACpB,CAAC;AAAA,MACL;AAEA,WAAK,gBAAgB,YAAY,KAAK,IAAI;AAAA,IAC9C;AAEA,WAAO;AAAA,EACX;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,MAAM,mCAAmE;AACrE,UAAM,aAAa,KAAK,QAAQ,cAAc;AAC9C,QAAI,CAAC,YAAY;AACb,YAAM,IAAI,MAAM,8EAA8E;AAAA,IAClG;AAEA,QAAI,CAAC,KAAK,QAAQ,aAAa,GAAG;AAC9B,YAAM,IAAI,MAAM,sEAAsE;AAAA,IAC1F;AAEA,UAAM,SAAS,MAAM,KAAK,QAAQ,wBAAwB,WAAW,OAAO;AAG5E,QAAI,KAAK,iBAAiB;AACtB,iBAAW,eAAe,OAAO,SAAS;AACtC,YAAI,YAAY,WAAW,YAAY,cAAc;AACjD,gBAAM,kBAAkB,KAAK,gBAAgB,UAAU;AAAA,YACnD,OAAK,EAAE,oBAAoB,YAAY;AAAA,UAC3C;AAEA,cAAI,iBAAiB;AACjB,4BAAgB,WAAW;AAC3B,4BAAgB,mBAAmB,YAAY;AAC/C,4BAAgB,UAAU,YAAY;AAAA,UAC1C,OAAO;AACH,iBAAK,gBAAgB,UAAU,KAAK;AAAA,cAChC,iBAAiB,YAAY;AAAA,cAC7B,WAAW,YAAY;AAAA,cACvB,SAAS,YAAY;AAAA,cACrB,OAAO;AAAA,cACP,UAAU;AAAA,cACV,kBAAkB,YAAY;AAAA,cAC9B,gBAAgB;AAAA,YACpB,CAAC;AAAA,UACL;AAAA,QACJ;AAAA,MACJ;AAEA,WAAK,gBAAgB,YAAY,KAAK,IAAI;AAAA,IAC9C;AAEA,WAAO;AAAA,EACX;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,MAAM,yBAAwF;AAC1F,UAAM,aAAa,KAAK,QAAQ,cAAc;AAC9C,QAAI,CAAC,YAAY;AACb,YAAM,IAAI,MAAM,mBAAmB;AAAA,IACvC;AAEA,WAAO,MAAM,KAAK,QAAQ,uBAAuB,WAAW,OAAO;AAAA,EACvE;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,MAAM,mCAAmE;AACrE,UAAM,aAAa,KAAK,QAAQ,cAAc;AAC9C,QAAI,CAAC,YAAY;AACb,YAAM,IAAI,MAAM,mBAAmB;AAAA,IACvC;AAGA,UAAM,WAAW,MAAM,KAAK,uBAAuB;AAGnD,UAAM,kBAAkB,KAAK,QAAQ,mBAAmB;AACxD,UAAM,gBAAgB,gBAAgB;AAAA,MAClC,WAAS,CAAC,SAAS,MAAM,eAAe,GAAG;AAAA,IAC/C;AAEA,QAAI,cAAc,WAAW,GAAG;AAE5B,YAAM,iBAAyC,CAAC;AAChD,YAAM,UAAkC,CAAC;AAEzC,iBAAW,SAAS,iBAAiB;AACjC,cAAM,SAAS,SAAS,MAAM,eAAe;AAC7C,uBAAe,MAAM,eAAe,IAAI,QAAQ,WAAW;AAC3D,gBAAQ,KAAK;AAAA,UACT,SAAS;AAAA,UACT,OAAO,MAAM;AAAA,UACb,iBAAiB,MAAM;AAAA,UACvB,cAAc,QAAQ;AAAA,UACtB,eAAe;AAAA,QACnB,CAAC;AAAA,MACL;AAEA,aAAO;AAAA,QACH,SAAS,WAAW;AAAA,QACpB;AAAA,QACA,eAAe;AAAA,QACf;AAAA,MACJ;AAAA,IACJ;AAGA,WAAO,MAAM,KAAK,iCAAiC;AAAA,EACvD;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAYA,MAAM,mBAAkD;AACpD,UAAM,aAAa,KAAK,QAAQ,cAAc;AAC9C,QAAI,CAAC,YAAY;AACb,aAAO;AAAA,IACX;AAEA,UAAM,YAAY,KAAK;AACvB,QAAI,OAAO,UAAU,qBAAqB,YAAY;AAClD,YAAM,IAAI,MAAM,wDAAwD;AAAA,IAC5E;AAEA,WAAO,MAAM,UAAU,iBAAiB,WAAW,OAAO;AAAA,EAC9D;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,MAAM,yBAA0D;AAC5D,UAAM,aAAa,KAAK,QAAQ,cAAc;AAC9C,QAAI,CAAC,YAAY;AACb,aAAO;AAAA,IACX;AAEA,UAAM,YAAY,KAAK;AACvB,QAAI,OAAO,UAAU,qBAAqB,YAAY;AAClD,YAAM,IAAI,MAAM,wDAAwD;AAAA,IAC5E;AAGA,UAAM,QAAQ,MAAM,UAAU,iBAAiB,WAAW,OAAO;AACjE,QAAI,CAAC,MAAM,YAAY,MAAM,aAAaD,SAAO,UAAU;AAEvD,aAAO,CAAC;AAAA,IACZ;AAGA,UAAM,YAAsB,MAAM,UAAU,kBAAkB,MAAM,QAAQ;AAG5E,WAAO,UAAU,IAAI,cAAY;AAAA,MAC7B;AAAA,MACA,QAAQ,YAAY,MAAM;AAAA,IAC9B,EAAE;AAAA,EACN;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,MAAM,oBAAsC;AACxC,UAAM,QAAQ,MAAM,KAAK,iBAAiB;AAC1C,QAAI,CAAC,SAAS,MAAM,aAAa,GAAG;AAChC,aAAO;AAAA,IACX;AACA,WAAO,MAAM,WAAW;AAAA,EAC5B;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAUA,MAAM,iBACF,eACA,QAC2B;AAC3B,UAAM,aAAa,KAAK,QAAQ,cAAc;AAC9C,QAAI,CAAC,YAAY;AACb,YAAM,IAAI,MAAM,8EAA8E;AAAA,IAClG;AAEA,UAAM,YAAY,KAAK;AACvB,QAAI,OAAO,UAAU,iBAAiB,YAAY;AAC9C,YAAM,IAAI,MAAM,8DAA8D;AAAA,IAClF;AAGA,UAAM,QAAQ,MAAM,UAAU,iBAAiB,WAAW,OAAO;AACjE,QAAI,MAAM,YAAY,MAAM,SAAS;AACjC,YAAM,IAAI,MAAM,iBAAiB,MAAM,OAAO,wCAAwC;AAAA,IAC1F;AAGA,UAAM,sBAAsB,MAAM,UAAU;AAAA,MACxC,MAAM;AAAA,MACN,cAAc;AAAA,IAClB;AACA,QAAI,qBAAqB;AACrB,YAAM,IAAI,MAAM,sDAAsD;AAAA,IAC1E;AAEA,QAAI,CAAC,MAAM,YAAY,MAAM,aAAaA,SAAO,UAAU;AACvD,YAAM,IAAI,MAAM,yDAAyD;AAAA,IAC7E;AAGA,UAAM,QAAQ,MAAM,KAAK,MAAM,SAAS,MAAM,QAAQ;AAGtD,UAAM,kBAAkBA,SAAO;AAAA,MAC3B,CAAC,UAAU,WAAW,WAAW,SAAS;AAAA,MAC1C,CAAC,mBAAmB,MAAM,UAAU,cAAc,SAAS,KAAK;AAAA,IACpE;AAEA,UAAM,YAAY,MAAM,KAAK,QAAQ,KAAKA,SAAO,SAAS,eAAe,CAAC;AAE1E,QAAI,CAAC,QAAQ;AACT,YAAM,IAAI,MAAM,6CAA6C;AAAA,IACjE;AAGA,UAAM,EAAE,SAAS,SAAS,IAAI,MAAM,UAAU;AAAA,MAC1C;AAAA,MACA,WAAW;AAAA,MACX,WAAW;AAAA,MACX,cAAc;AAAA,MACd,cAAc;AAAA,MACd;AAAA,MACA;AAAA,IACJ;AAGA,UAAM,eAAe,MAAM,UAAU,iBAAiB,WAAW,OAAO;AAExE,WAAO;AAAA,MACH,iBAAiB,QAAQ;AAAA,MACzB;AAAA,MACA,UAAU,MAAM;AAAA,MAChB,YAAY,cAAc;AAAA,MAC1B,UAAU,aAAa;AAAA,IAC3B;AAAA,EACJ;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAUA,MAAM,cACF,aACA,QACwB;AACxB,UAAM,aAAa,KAAK,QAAQ,cAAc;AAC9C,QAAI,CAAC,YAAY;AACb,YAAM,IAAI,MAAM,8EAA8E;AAAA,IAClG;AAEA,UAAM,YAAY,KAAK;AACvB,QAAI,OAAO,UAAU,cAAc,YAAY;AAC3C,YAAM,IAAI,MAAM,8DAA8D;AAAA,IAClF;AAGA,UAAM,QAAQ,MAAM,UAAU,iBAAiB,WAAW,OAAO;AACjE,QAAI,MAAM,YAAY,GAAG;AACrB,YAAM,IAAI,MAAM,2DAA2D;AAAA,IAC/E;AAGA,UAAM,eAAe,MAAM,UAAU;AAAA,MACjC,MAAM;AAAA,MACN;AAAA,IACJ;AACA,QAAI,CAAC,cAAc;AACf,YAAM,IAAI,MAAM,2DAA2D;AAAA,IAC/E;AAEA,QAAI,CAAC,MAAM,YAAY,MAAM,aAAaA,SAAO,UAAU;AACvD,YAAM,IAAI,MAAM,yDAAyD;AAAA,IAC7E;AAGA,UAAM,QAAQ,MAAM,KAAK,MAAM,SAAS,MAAM,QAAQ;AAGtD,UAAM,kBAAkBA,SAAO;AAAA,MAC3B,CAAC,UAAU,WAAW,WAAW,SAAS;AAAA,MAC1C,CAAC,sBAAsB,MAAM,UAAU,aAAa,KAAK;AAAA,IAC7D;AAEA,UAAM,YAAY,MAAM,KAAK,QAAQ,KAAKA,SAAO,SAAS,eAAe,CAAC;AAG1E,UAAM,EAAE,SAAS,SAAS,IAAI,MAAM,UAAU;AAAA,MAC1C;AAAA,MACA,WAAW;AAAA,MACX,WAAW;AAAA,MACX;AAAA,MACA;AAAA,MACA;AAAA,IACJ;AAGA,UAAM,eAAe,MAAM,UAAU,iBAAiB,WAAW,OAAO;AAExE,WAAO;AAAA,MACH,iBAAiB,QAAQ;AAAA,MACzB;AAAA,MACA,UAAU,MAAM;AAAA,MAChB,gBAAgB;AAAA,MAChB,UAAU,aAAa;AAAA,IAC3B;AAAA,EACJ;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,MAAM,oBAAoB,SAAmC;AACzD,UAAM,aAAa,KAAK,QAAQ,cAAc;AAC9C,QAAI,CAAC,YAAY;AACb,aAAO;AAAA,IACX;AAEA,UAAM,YAAY,KAAK;AACvB,QAAI,OAAO,UAAU,qBAAqB,YAAY;AAClD,YAAM,IAAI,MAAM,wDAAwD;AAAA,IAC5E;AAEA,UAAM,QAAQ,MAAM,UAAU,iBAAiB,WAAW,OAAO;AACjE,QAAI,CAAC,MAAM,YAAY,MAAM,aAAaA,SAAO,UAAU;AACvD,aAAO;AAAA,IACX;AAEA,WAAO,MAAM,UAAU,wBAAwB,MAAM,UAAU,OAAO;AAAA,EAC1E;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,MAAM,cAAsC;AACxC,UAAM,aAAa,KAAK,QAAQ,cAAc;AAC9C,QAAI,CAAC,YAAY;AACb,aAAO;AAAA,IACX;AAEA,UAAM,YAAY,KAAK;AACvB,QAAI,OAAO,UAAU,sBAAsB,YAAY;AAEnD,aAAO,WAAW;AAAA,IACtB;AAEA,UAAM,WAAW,MAAM,UAAU,kBAAkB,WAAW,OAAO;AACrE,QAAI,aAAaA,SAAO,UAAU;AAE9B,aAAO,WAAW;AAAA,IACtB;AAEA,WAAO;AAAA,EACX;AAAA,EAEA,gBAA0C;AACtC,WAAO,KAAK,QAAQ,cAAc;AAAA,EACtC;AAAA,EAEA,cAAc,YAAqC;AAC/C,SAAK,QAAQ,cAAc,UAAU;AAAA,EACzC;AAAA,EAEA,gBAAyB;AACrB,WAAO,KAAK,QAAQ,cAAc,MAAM;AAAA,EAC5C;AAAA,EAEA,kBAAwB;AACpB,SAAK,QAAQ,gBAAgB;AAAA,EACjC;AACJ;;;AMl4EA,SAAS,UAAAE,gBAAc;AAqCvB,IAAMC,yBAAwB;AAK9B,IAAMC,yBAAwB;AAK9B,IAAMC,aAAY;AAAA,EACd;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACJ;AAMA,IAAMC,WAAU;AAAA,EACZ;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA;AAAA,EAEA;AAAA,EACA;AAAA;AAAA,EAEA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA;AAAA,EAEA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA;AAAA,EAGA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACJ;AAMA,IAAM,cAAc;AAAA,EAChB;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACJ;AASO,IAAM,YAAN,MAAuC;AAAA,EAClC;AAAA,EACA;AAAA,EACA;AAAA,EACA,kBAA0C;AAAA,EAC1C,uBAAsC;AAAA,EAE9C,YAAY,QAAyB;AACjC,SAAK,SAAS;AAAA,MACV,MAAM,OAAO,QAAQ,aAAa,OAAO,OAAO;AAAA,MAChD,SAAS,OAAO;AAAA,MAChB,iBAAiB,OAAO;AAAA,MACxB,QAAQ,OAAO;AAAA,MACf,aAAa,OAAO,eAAe;AAAA,MACnC,OAAO;AAAA,MACP,WAAW;AAAA,QACP,KAAK,OAAO;AAAA,QACZ,cAAc,OAAO;AAAA,QACrB,qBAAqB,OAAO;AAAA,QAC5B,oBAAoB,OAAO;AAAA,QAC3B,aAAa,OAAO;AAAA,MACxB;AAAA,IACJ;AAEA,SAAK,WAAW,IAAIC,SAAO,gBAAgB,OAAO,MAAM;AACxD,SAAK,cAAc,IAAIA,SAAO;AAAA,MAC1B,OAAO;AAAA,MACPD;AAAA,MACA,KAAK;AAAA,IACT;AAGA,QAAI,OAAO,cAAc;AACrB,WAAK,kBAAkB,IAAIC,SAAO;AAAA,QAC9B,OAAO;AAAA,QACP;AAAA,QACA,KAAK;AAAA,MACT;AAAA,IACJ;AAGA,QAAI,OAAO,qBAAqB;AAC5B,WAAK,uBAAuB,OAAO;AAAA,IACvC;AAAA,EACJ;AAAA,EAEA,YAAyB;AACrB,WAAO,KAAK;AAAA,EAChB;AAAA,EAEA,MAAM,SAAS,aAAsC;AACjD,UAAM,QAAQ,MAAM,KAAK,YAAY,SAAS,WAAW;AACzD,WAAO,OAAO,MAAM,SAAS,CAAC;AAAA,EAClC;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,MAAM,aAAa,aAIhB;AACC,QAAI;AACA,YAAM,SAAS,MAAM,KAAK,YAAY,aAAa,WAAW;AAC9D,aAAO;AAAA,QACH,SAAS,OAAO,CAAC;AAAA,QACjB,OAAO,OAAO,OAAO,CAAC,EAAE,SAAS,CAAC;AAAA,QAClC,gBAAgB,OAAO,CAAC;AAAA,MAC5B;AAAA,IACJ,SAAS,OAAO;AAEZ,YAAM,QAAQ,MAAM,KAAK,SAAS,WAAW;AAC7C,aAAO;AAAA,QACH,SAAS;AAAA,QACT;AAAA,QACA,gBAAgBA,SAAO;AAAA,MAC3B;AAAA,IACJ;AAAA,EACJ;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,MAAM,sBAAsB,aAAsC;AAC9D,QAAI;AACA,aAAO,MAAM,KAAK,YAAY,sBAAsB,WAAW;AAAA,IACnE,SAAS,OAAO;AAEZ,aAAOA,SAAO;AAAA,IAClB;AAAA,EACJ;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAcA,MAAM,gBACF,QACA,QACkC;AAClC,UAAM,gBAAgB,KAAK,YAAY,QAAQ,MAAM;AAErD,UAAM,YAAY;AAAA,MACd,mBAAmB,OAAO,UAAU;AAAA,MACpC,gBAAgB,OAAO,UAAU;AAAA,MACjC,gBAAgB,OAAO,UAAU;AAAA,MACjC,WAAW,OAAO,UAAU;AAAA,MAC5B,GAAG,OAAO,UAAU;AAAA,MACpB,GAAG,OAAO,UAAU;AAAA,IACxB;AAEA,UAAM,KAAK,MAAM,cAAc;AAAA,MAC3B;AAAA,MACA,OAAO;AAAA,MACP,OAAO;AAAA,MACP,OAAO;AAAA,MACP,OAAO;AAAA,MACP,OAAO;AAAA,MACP,OAAO;AAAA,IACX;AAEA,WAAO,MAAM,GAAG,KAAK;AAAA,EACzB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASA,MAAM,gBACF,aACA,gBACyD;AACzD,UAAM,SAAS,MAAM,KAAK,YAAY,gBAAgB,aAAa,cAAc;AAEjF,WAAO;AAAA,MACH,QAAQ,OAAO,CAAC;AAAA,MAChB,QAAQ,OAAO,OAAO,CAAC,CAAC;AAAA,MACxB,UAAU,OAAO,OAAO,CAAC,EAAE,SAAS,CAAC;AAAA,MACrC,cAAc,OAAO,OAAO,CAAC,CAAC;AAAA,IAClC;AAAA,EACJ;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASA,MAAM,cACF,QACA,QACkC;AAClC,UAAM,gBAAgB,KAAK,YAAY,QAAQ,MAAM;AAErD,UAAM,YAAY;AAAA,MACd,mBAAmB,OAAO,UAAU;AAAA,MACpC,gBAAgB,OAAO,UAAU;AAAA,MACjC,gBAAgB,OAAO,UAAU;AAAA,MACjC,WAAW,OAAO,UAAU;AAAA,MAC5B,GAAG,OAAO,UAAU;AAAA,MACpB,GAAG,OAAO,UAAU;AAAA,IACxB;AAEA,UAAM,KAAK,MAAM,cAAc;AAAA,MAC3B;AAAA,MACA,OAAO;AAAA,MACP,OAAO;AAAA,MACP,OAAO;AAAA,MACP,OAAO;AAAA,IACX;AAEA,WAAO,MAAM,GAAG,KAAK;AAAA,EACzB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,MAAM,gBAAgB,aAAqE;AACvF,UAAM,WAAW,MAAM,KAAK,YAAY,gBAAgB,WAAW;AAEnE,WAAO,SAAS,IAAI,CAAC,OAAY;AAAA,MAC7B,gBAAgB,EAAE;AAAA,MAClB,QAAQ,OAAO,EAAE,MAAM;AAAA,MACvB,UAAU,OAAO,EAAE,SAAS,SAAS,CAAC;AAAA,MACtC,SAAS,EAAE;AAAA,IACf,EAAE;AAAA,EACN;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,MAAM,oBAAoB,aAAsC;AAC5D,UAAM,QAAQ,MAAM,KAAK,YAAY,oBAAoB,WAAW;AACpE,WAAO,OAAO,KAAK;AAAA,EACvB;AAAA,EAEA,MAAM,gBAAiC;AACnC,UAAM,MAAM,MAAM,KAAK,YAAY,cAAc;AACjD,WAAO,OAAO,IAAI,SAAS,CAAC;AAAA,EAChC;AAAA,EAEA,MAAM,qBAAqB,QAAyC;AAChE,WAAO;AAAA,MACH,OAAO;AAAA,MACP,OAAO;AAAA,MACP,OAAO;AAAA,IACX;AAAA,EACJ;AAAA,EAEA,MAAM,oBAAoB,QAAwC;AAC9D,WAAO;AAAA,MACH,OAAO;AAAA,MACP,OAAO;AAAA,MACP,OAAO;AAAA,IACX;AAAA,EACJ;AAAA,EAEA,MAAM,mBAAmB,QAAuC;AAC5D,WAAO;AAAA,MACH,OAAO;AAAA,MACP,OAAO;AAAA,MACP,OAAO;AAAA,MACP,OAAO;AAAA,IACX;AAAA,EACJ;AAAA,EAEA,MAAM,SACF,WACA,YACA,YACA,aACA,eACA,OACA,QACuB;AACvB,UAAM,gBAAgB,KAAK,YAAY,QAAQ,MAAM;AAErD,UAAM,iBAAiB;AAAA,MACnB,mBAAmB,UAAU;AAAA,MAC7B,gBAAgB,UAAU;AAAA,MAC1B,gBAAgB,UAAU;AAAA,MAC1B,WAAW,UAAU;AAAA,MACrB,GAAG,UAAU;AAAA,MACb,GAAG,UAAU;AAAA,IACjB;AAEA,UAAM,aAAa,MAAM,KAAK,cAAc;AAE5C,UAAM,KAAK,MAAM,cAAc;AAAA,MAC3B;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA,EAAE,OAAO,WAAW;AAAA,IACxB;AAEA,UAAM,UAAU,MAAM,GAAG,KAAK;AAG9B,UAAM,gBAAgB,QAAQ,KAAK,KAAK,CAAC,QAAa;AAClD,UAAI;AACA,cAAM,SAAS,cAAc,UAAU,SAAS,GAAG;AACnD,eAAO,QAAQ,SAAS;AAAA,MAC5B,QAAQ;AACJ,eAAO;AAAA,MACX;AAAA,IACJ,CAAC;AAED,QAAI,WAAW;AACf,QAAI,eAAe;AACf,YAAM,SAAS,cAAc,UAAU,SAAS,aAAa;AAC7D,iBAAW,OAAO,QAAQ,MAAM,UAAU,SAAS,KAAK,GAAG;AAAA,IAC/D;AAEA,UAAM,UAAUA,SAAO;AAAA,MACnBA,SAAO,SAAS,gBAAgB,EAAE;AAAA,QAC9B,CAAC,WAAW,SAAS;AAAA,QACrB,CAAC,YAAY,UAAU;AAAA,MAC3B;AAAA,IACJ;AAEA,WAAO;AAAA,MACH,iBAAiB,QAAQ;AAAA,MACzB;AAAA,MACA,aAAa;AAAA,MACb;AAAA,MACA,aAAa,QAAQ;AAAA,IACzB;AAAA,EACJ;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,MAAM,gBACF,WACA,YACA,YACA,aACA,eACA,OACA,YACuB;AAGvB,UAAM,UAAUA,SAAO;AAAA,MACnBA,SAAO,SAAS,gBAAgB,EAAE;AAAA,QAC9B,CAAC,WAAW,SAAS;AAAA,QACrB,CAAC,YAAY,UAAU;AAAA,MAC3B;AAAA,IACJ;AAGA,UAAM,UAAUA,SAAO;AAAA,MACnBA,SAAO,SAAS,gBAAgB,EAAE;AAAA,QAC9B,CAAC,WAAW,UAAU,SAAS,SAAS;AAAA,QACxC,CAAC,SAAS,aAAa,eAAe,KAAK;AAAA,MAC/C;AAAA,IACJ;AAGA,UAAM,UAAU;AAAA,MACZ,aAAa;AAAA,MACb,GAAG,OAAO,UAAU,EAAE,SAAS,EAAE,EAAE,SAAS,IAAI,GAAG;AAAA,MACnD,GAAG,OAAO,UAAU,EAAE,SAAS,EAAE,EAAE,SAAS,IAAI,GAAG;AAAA,MACnD,YAAY,OAAO,WAAW,SAAS,EAAE,EAAE,SAAS,IAAI,GAAG;AAAA,MAC3D,YAAY,OAAO,WAAW,SAAS,EAAE,EAAE,SAAS,IAAI,GAAG;AAAA,MAC3D;AAAA,MACA;AAAA,MACA,OAAO,OAAO,KAAK;AAAA,IACvB;AAGA,UAAM,WAAW,MAAM,MAAM,GAAG,UAAU,kBAAkB;AAAA,MACxD,QAAQ;AAAA,MACR,SAAS;AAAA,QACL,gBAAgB;AAAA,MACpB;AAAA,MACA,MAAM,KAAK,UAAU,OAAO;AAAA,IAChC,CAAC;AAED,QAAI,CAAC,SAAS,IAAI;AACd,YAAM,QAAQ,MAAM,SAAS,KAAK,EAAE,MAAM,OAAO,EAAE,OAAO,SAAS,WAAW,EAAE;AAChF,YAAM,IAAI,MAAM,8BAA8B,MAAM,SAAS,SAAS,UAAU,EAAE;AAAA,IACtF;AAEA,UAAM,SAAS,MAAM,SAAS,KAAK;AAEnC,QAAI,CAAC,OAAO,SAAS;AACjB,YAAM,IAAI,MAAM,8BAA8B,OAAO,KAAK,EAAE;AAAA,IAChE;AAEA,WAAO;AAAA,MACH,iBAAiB,OAAO;AAAA,MACxB,UAAU,OAAO,OAAO,YAAY,GAAG;AAAA,MACvC,aAAa;AAAA,MACb;AAAA,IACJ;AAAA,EACJ;AAAA,EAEA,MAAM,gBAAgB,aAA6C;AAC/D,QAAI;AAEA,UAAI,KAAK,iBAAiB;AACtB,cAAMC,WAAU,MAAM,KAAK,gBAAgB,SAAS,WAAW;AAC/D,YAAIA,aAAYD,SAAO,aAAa;AAChC,iBAAOC;AAAA,QACX;AAAA,MACJ;AAGA,YAAM,UAAU,MAAM,KAAK,YAAY,gBAAgB,WAAW;AAClE,UAAI,YAAYD,SAAO,aAAa;AAChC,eAAO;AAAA,MACX;AACA,aAAO;AAAA,IACX,SAAS,OAAO;AACZ,cAAQ,MAAM,gCAAgC,KAAK;AACnD,aAAO;AAAA,IACX;AAAA,EACJ;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,oBAAoB,aAA6B;AAC7C,UAAM,iBAAiB,KAAK,kBAAkB;AAC9C,UAAM,wBAAwB,KAAK,yBAAyB;AAE5D,QAAI,CAAC,kBAAkB,CAAC,uBAAuB;AAC3C,YAAM,IAAI,MAAM,uEAAuE;AAAA,IAC3F;AAGA,UAAM,OAAOA,SAAO;AAAA,MAChBA,SAAO;AAAA,QACH,CAAC,WAAW,SAAS;AAAA,QACrB,CAAC,gBAAgB,WAAW;AAAA,MAChC;AAAA,IACJ;AAGA,UAAM,WAAW,KAAK,mBAAmB,qBAAqB;AAC9D,UAAM,eAAeA,SAAO,UAAU,QAAQ;AAI9C,UAAM,cAAcA,SAAO;AAAA,MACvB,CAAC,UAAU,WAAW,WAAW,SAAS;AAAA,MAC1C,CAAC,QAAQ,gBAAgB,MAAM,YAAY;AAAA,IAC/C;AAEA,UAAM,OAAOA,SAAO,UAAU,WAAW;AAEzC,WAAOA,SAAO,WAAW,OAAO,KAAK,MAAM,EAAE,CAAC;AAAA,EAClD;AAAA;AAAA;AAAA;AAAA,EAKQ,mBAAmB,uBAAuC;AAC9D,UAAM,OAAO,sBAAsB,YAAY,EAAE,QAAQ,MAAM,EAAE;AACjE,WAAOJ,yBAAwB,OAAOC;AAAA,EAC1C;AAAA,EAEA,MAAM,YAAY,aAAuC;AACrD,QAAI;AAEA,UAAI,KAAK,iBAAiB;AACtB,eAAO,MAAM,KAAK,gBAAgB,YAAY,WAAW;AAAA,MAC7D;AAEA,UAAI,KAAK,YAAY,aAAa;AAC9B,YAAI;AACA,iBAAO,MAAM,KAAK,YAAY,YAAY,WAAW;AAAA,QACzD,QAAQ;AAEJ,iBAAO;AAAA,QACX;AAAA,MACJ;AACA,aAAO;AAAA,IACX,QAAQ;AAEJ,aAAO;AAAA,IACX;AAAA,EACJ;AAAA,EAEA,MAAM,YAAY,aAAqB,QAAqD;AAExF,UAAM,SAAS,MAAM,KAAK,YAAY,WAAW;AACjD,QAAI,QAAQ;AACR,YAAM,UAAU,MAAM,KAAK,gBAAgB,WAAW;AACtD,UAAI,SAAS;AACT,eAAO;AAAA,UACH;AAAA,UACA,iBAAiB;AAAA,UACjB,aAAa;AAAA,UACb,SAAS;AAAA,UACT,gBAAgB;AAAA,QACpB;AAAA,MACJ;AAAA,IACJ;AAGA,QAAI;AAEJ,QAAI,KAAK,iBAAiB;AACtB,YAAM,oBAAoB,KAAK,gBAAgB,QAAQ,MAAM;AAC7D,WAAK,MAAM,kBAAkB,YAAY,WAAW;AAAA,IACxD,OAAO;AACH,YAAM,gBAAgB,KAAK,YAAY,QAAQ,MAAM;AACrD,WAAK,MAAM,cAAc,YAAY,WAAW;AAAA,IACpD;AAEA,UAAM,UAAU,MAAM,GAAG,KAAK;AAC9B,QAAI,CAAC,SAAS;AACV,YAAM,IAAI,MAAM,iCAAiC;AAAA,IACrD;AAEA,UAAM,eAAe,MAAM,KAAK,gBAAgB,WAAW;AAC3D,QAAI,CAAC,cAAc;AACf,YAAM,IAAI,MAAM,2DAA2D;AAAA,IAC/E;AAEA,WAAO;AAAA,MACH,SAAS;AAAA,MACT,iBAAiB,QAAQ;AAAA,MACzB,aAAa,QAAQ;AAAA,MACrB,SAAS,QAAQ;AAAA,MACjB,gBAAgB;AAAA,IACpB;AAAA,EACJ;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAUA,MAAM,qBACF,aACA,mBACA,QAC4B;AAE5B,UAAM,SAAS,MAAM,KAAK,YAAY,WAAW;AACjD,QAAI,QAAQ;AACR,YAAM,UAAU,MAAM,KAAK,gBAAgB,WAAW;AACtD,UAAI,SAAS;AACT,eAAO;AAAA,UACH;AAAA,UACA,iBAAiB;AAAA,UACjB,aAAa;AAAA,UACb,SAAS;AAAA,UACT,gBAAgB;AAAA,QACpB;AAAA,MACJ;AAAA,IACJ;AAGA,UAAM,WAAW,SACX,IAAIG,SAAO,gBAAgB,MAAM,IACjC,KAAK;AACX,UAAM,gBAAgB,IAAIA,SAAO,OAAO,mBAAmB,QAAQ;AAGnE,UAAM,iBAAiB,MAAM,SAAS,WAAW,cAAc,OAAO;AACtE,UAAM,eAAe,MAAM,KAAK,yBAAyB,WAAW;AACpE,UAAM,UAAU,MAAM,SAAS,WAAW;AAC1C,UAAM,gBAAgB,gBAAgB,QAAQ,YAAY;AAE1D,QAAI,iBAAiB,eAAe;AAChC,YAAM,IAAI;AAAA,QACN,mDACYA,SAAO,YAAY,cAAc,CAAC,yBAC3BA,SAAO,YAAY,aAAa,CAAC;AAAA,MACxD;AAAA,IACJ;AAGA,QAAI;AAEJ,QAAI,KAAK,iBAAiB;AACtB,YAAM,qBAAqB,KAAK,gBAAgB,QAAQ,aAAa;AACrE,WAAK,MAAM,mBAAmB,YAAY,WAAW;AAAA,IACzD,OAAO;AACH,YAAM,iBAAiB,KAAK,YAAY,QAAQ,aAAa;AAC7D,WAAK,MAAM,eAAe,YAAY,WAAW;AAAA,IACrD;AAEA,UAAM,UAAU,MAAM,GAAG,KAAK;AAC9B,QAAI,CAAC,SAAS;AACV,YAAM,IAAI,MAAM,iCAAiC;AAAA,IACrD;AAEA,UAAM,eAAe,MAAM,KAAK,gBAAgB,WAAW;AAC3D,QAAI,CAAC,cAAc;AACf,YAAM,IAAI,MAAM,2DAA2D;AAAA,IAC/E;AAEA,WAAO;AAAA,MACH,SAAS;AAAA,MACT,iBAAiB,QAAQ;AAAA,MACzB,aAAa,QAAQ;AAAA,MACrB,SAAS,QAAQ;AAAA,MACjB,gBAAgB;AAAA,MAChB,aAAa,cAAc;AAAA,IAC/B;AAAA,EACJ;AAAA,EAEA,MAAM,yBAAyB,aAAsC;AACjE,QAAI;AACA,UAAI,KAAK,iBAAiB;AACtB,eAAO,MAAM,KAAK,gBAAgB,YAAY,YAAY,WAAW;AAAA,MACzE;AACA,aAAO,MAAM,KAAK,YAAY,YAAY,YAAY,WAAW;AAAA,IACrE,SAAS,OAAO;AAEZ,cAAQ,KAAK,6CAA6C,KAAK;AAC/D,aAAO;AAAA,IACX;AAAA,EACJ;AAAA,EAEA,oBAAwC;AACpC,WAAO,KAAK,OAAO,UAAU;AAAA,EACjC;AAAA,EAEA,2BAA+C;AAC3C,WAAO,KAAK,OAAO,UAAU,uBAAuB,KAAK,wBAAwB;AAAA,EACrF;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,6BAAqD;AACvD,QAAI,KAAK,sBAAsB;AAC3B,aAAO,KAAK;AAAA,IAChB;AAEA,QAAI,CAAC,KAAK,iBAAiB;AACvB,aAAO;AAAA,IACX;AAEA,QAAI;AACA,WAAK,uBAAuB,MAAM,KAAK,gBAAgB,eAAe;AACtE,aAAO,KAAK;AAAA,IAChB,SAAS,OAAO;AACZ,cAAQ,MAAM,0CAA0C,KAAK;AAC7D,aAAO;AAAA,IACX;AAAA,EACJ;AAAA;AAAA;AAAA;AAAA,EAKA,cAAsC;AAClC,WAAO,KAAK;AAAA,EAChB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASA,MAAM,iBAAiB,SAAkC;AACrD,WAAO,MAAM,KAAK,SAAS,WAAW,OAAO;AAAA,EACjD;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,gBAAgB,cAAsB,cAAuC;AAC/E,UAAM,WAAW,IAAIA,SAAO,SAAS,cAAcF,YAAW,KAAK,QAAQ;AAC3E,WAAO,MAAM,SAAS,UAAU,YAAY;AAAA,EAChD;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,kBACF,cACA,cACA,gBACe;AACf,UAAM,WAAW,IAAIE,SAAO,SAAS,cAAcF,YAAW,KAAK,QAAQ;AAC3E,WAAO,MAAM,SAAS,UAAU,cAAc,cAAc;AAAA,EAChE;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,oBACF,WACA,YACA,YACA,aACA,eACA,OACe;AACf,UAAM,iBAAiB;AAAA,MACnB,mBAAmB,UAAU;AAAA,MAC7B,gBAAgB,UAAU;AAAA,MAC1B,gBAAgB,UAAU;AAAA,MAC1B,WAAW,UAAU;AAAA,MACrB,GAAG,UAAU;AAAA,MACb,GAAG,UAAU;AAAA,IACjB;AAEA,UAAM,aAAa,MAAM,KAAK,cAAc;AAE5C,QAAI;AACA,YAAM,cAAc,MAAM,KAAK,YAAY,SAAS;AAAA,QAChD;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA,EAAE,OAAO,WAAW;AAAA,MACxB;AACA,aAAO;AAAA,IACX,SAAS,OAAO;AACZ,cAAQ,KAAK,yCAAyC,KAAK;AAC3D,aAAO;AAAA,IACX;AAAA,EACJ;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,cAA+B;AACjC,UAAM,UAAU,MAAM,KAAK,SAAS,WAAW;AAC/C,WAAO,QAAQ,YAAY,QAAQ,gBAAgB;AAAA,EACvD;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,iBAAkC;AACpC,WAAO,MAAM,KAAK,SAAS,eAAe;AAAA,EAC9C;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,sBAAsB,MAAyD;AACjF,WAAO,MAAM,KAAK,SAAS,sBAAsB,IAAI;AAAA,EACzD;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,mBACF,MACA,gBAAwB,GACiB;AACzC,WAAO,MAAM,KAAK,SAAS,mBAAmB,MAAM,aAAa;AAAA,EACrE;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAaA,MAAM,kBAAkB,SAAkC;AACtD,QAAI;AACA,aAAO,MAAM,KAAK,YAAY,kBAAkB,OAAO;AAAA,IAC3D,SAAS,OAAO;AACZ,aAAOE,SAAO;AAAA,IAClB;AAAA,EACJ;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,MAAM,kBAAkB,UAAqC;AACzD,QAAI;AACA,aAAO,MAAM,KAAK,YAAY,kBAAkB,QAAQ;AAAA,IAC5D,SAAS,OAAO;AACZ,aAAO,CAAC;AAAA,IACZ;AAAA,EACJ;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,MAAM,sBAAsB,UAAmC;AAC3D,QAAI;AACA,YAAM,QAAQ,MAAM,KAAK,YAAY,sBAAsB,QAAQ;AACnE,aAAO,OAAO,KAAK;AAAA,IACvB,SAAS,OAAO;AACZ,aAAO;AAAA,IACX;AAAA,EACJ;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASA,MAAM,wBAAwB,UAAkB,SAAmC;AAC/E,QAAI;AACA,aAAO,MAAM,KAAK,YAAY,wBAAwB,UAAU,OAAO;AAAA,IAC3E,SAAS,OAAO;AACZ,aAAO;AAAA,IACX;AAAA,EACJ;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,MAAM,kBAAkB,SAAmC;AACvD,QAAI;AACA,aAAO,MAAM,KAAK,YAAY,eAAe,OAAO;AAAA,IACxD,SAAS,OAAO;AACZ,aAAO;AAAA,IACX;AAAA,EACJ;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,MAAM,iBAAiB,SAAkE;AACrF,QAAI;AACA,YAAM,SAAS,MAAM,KAAK,YAAY,iBAAiB,OAAO;AAC9D,aAAO;AAAA,QACH,UAAU,OAAO,CAAC;AAAA,QAClB,UAAU,OAAO,OAAO,CAAC,CAAC;AAAA,QAC1B,SAAS,OAAO,OAAO,CAAC,CAAC;AAAA,QACzB,QAAQ,OAAO,CAAC;AAAA,MACpB;AAAA,IACJ,SAAS,OAAO;AAEZ,aAAO;AAAA,QACH,UAAUA,SAAO;AAAA,QACjB,UAAU;AAAA,QACV,SAAS;AAAA,QACT,QAAQ;AAAA,MACZ;AAAA,IACJ;AAAA,EACJ;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAYA,MAAM,iBACF,WACA,YACA,YACA,QACiE;AACjE,UAAM,gBAAgB,KAAK,YAAY,QAAQ,MAAM;AAErD,UAAM,YAAY;AAAA,MACd,mBAAmB,UAAU;AAAA,MAC7B,gBAAgB,UAAU;AAAA,MAC1B,gBAAgB,UAAU;AAAA,MAC1B,WAAW,UAAU;AAAA,MACrB,GAAG,UAAU;AAAA,MACb,GAAG,UAAU;AAAA,IACjB;AAEA,UAAM,KAAK,MAAM,cAAc;AAAA,MAC3B;AAAA,MACA;AAAA,MACA;AAAA,IACJ;AAEA,UAAM,UAAU,MAAM,GAAG,KAAK;AAG9B,UAAM,UAAUA,SAAO;AAAA,MACnBA,SAAO,eAAe,CAAC,WAAW,SAAS,GAAG,CAAC,YAAY,UAAU,CAAC;AAAA,IAC1E;AAEA,WAAO,EAAE,SAAS,UAAU,QAAQ;AAAA,EACxC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAeA,MAAM,aACF,WACA,YACA,YACA,eACA,eACA,OACA,QACiE;AACjE,UAAM,gBAAgB,KAAK,YAAY,QAAQ,MAAM;AAErD,UAAM,YAAY;AAAA,MACd,mBAAmB,UAAU;AAAA,MAC7B,gBAAgB,UAAU;AAAA,MAC1B,gBAAgB,UAAU;AAAA,MAC1B,WAAW,UAAU;AAAA,MACrB,GAAG,UAAU;AAAA,MACb,GAAG,UAAU;AAAA,IACjB;AAEA,UAAM,aAAa,MAAM,KAAK,cAAc;AAE5C,UAAM,KAAK,MAAM,cAAc;AAAA,MAC3B;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA,EAAE,OAAO,WAAW;AAAA,IACxB;AAEA,UAAM,UAAU,MAAM,GAAG,KAAK;AAG9B,QAAI,WAAW;AACf,eAAW,OAAO,QAAQ,MAAM;AAC5B,UAAI;AACA,cAAM,SAAS,KAAK,YAAY,UAAU,SAAS;AAAA,UAC/C,QAAQ,IAAI;AAAA,UACZ,MAAM,IAAI;AAAA,QACd,CAAC;AACD,YAAI,QAAQ,SAAS,cAAc;AAC/B,qBAAW,OAAO,OAAO,KAAK,CAAC,CAAC;AAChC;AAAA,QACJ;AAAA,MACJ,QAAQ;AAAA,MAER;AAAA,IACJ;AAEA,WAAO,EAAE,SAAS,SAAS;AAAA,EAC/B;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAcA,MAAM,UACF,WACA,YACA,YACA,aACA,OACA,QACiE;AACjE,UAAM,gBAAgB,KAAK,YAAY,QAAQ,MAAM;AAErD,UAAM,YAAY;AAAA,MACd,mBAAmB,UAAU;AAAA,MAC7B,gBAAgB,UAAU;AAAA,MAC1B,gBAAgB,UAAU;AAAA,MAC1B,WAAW,UAAU;AAAA,MACrB,GAAG,UAAU;AAAA,MACb,GAAG,UAAU;AAAA,IACjB;AAEA,UAAM,aAAa,MAAM,KAAK,cAAc;AAE5C,UAAM,KAAK,MAAM,cAAc;AAAA,MAC3B;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA,EAAE,OAAO,WAAW;AAAA,IACxB;AAEA,UAAM,UAAU,MAAM,GAAG,KAAK;AAG9B,QAAI,WAAW;AACf,eAAW,OAAO,QAAQ,MAAM;AAC5B,UAAI;AACA,cAAM,SAAS,KAAK,YAAY,UAAU,SAAS;AAAA,UAC/C,QAAQ,IAAI;AAAA,UACZ,MAAM,IAAI;AAAA,QACd,CAAC;AACD,YAAI,QAAQ,SAAS,cAAc;AAC/B,qBAAW,OAAO,OAAO,KAAK,CAAC,CAAC;AAChC;AAAA,QACJ;AAAA,MACJ,QAAQ;AAAA,MAER;AAAA,IACJ;AAEA,WAAO,EAAE,SAAS,SAAS;AAAA,EAC/B;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAeA,MAAM,eACF,WACA,YACA,YACA,WACA,WACA,QACiE;AACjE,UAAM,gBAAgB,KAAK,YAAY,QAAQ,MAAM;AAErD,UAAM,YAAY;AAAA,MACd,mBAAmB,UAAU;AAAA,MAC7B,gBAAgB,UAAU;AAAA,MAC1B,gBAAgB,UAAU;AAAA,MAC1B,WAAW,UAAU;AAAA,MACrB,GAAG,UAAU;AAAA,MACb,GAAG,UAAU;AAAA,IACjB;AAEA,UAAM,aAAa,MAAM,KAAK,cAAc;AAE5C,UAAM,KAAK,MAAM,cAAc;AAAA,MAC3B;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA,EAAE,OAAO,WAAW;AAAA,IACxB;AAEA,UAAM,UAAU,MAAM,GAAG,KAAK;AAC9B,UAAM,WAAW,KAAK,4BAA4B,OAAO;AAEzD,WAAO,EAAE,SAAS,SAAS;AAAA,EAC/B;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,YACF,WACA,YACA,YACA,iBACA,QACiE;AACjE,UAAM,gBAAgB,KAAK,YAAY,QAAQ,MAAM;AAErD,UAAM,YAAY;AAAA,MACd,mBAAmB,UAAU;AAAA,MAC7B,gBAAgB,UAAU;AAAA,MAC1B,gBAAgB,UAAU;AAAA,MAC1B,WAAW,UAAU;AAAA,MACrB,GAAG,UAAU;AAAA,MACb,GAAG,UAAU;AAAA,IACjB;AAEA,UAAM,aAAa,MAAM,KAAK,cAAc;AAE5C,UAAM,KAAK,MAAM,cAAc;AAAA,MAC3B;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA,EAAE,OAAO,WAAW;AAAA,IACxB;AAEA,UAAM,UAAU,MAAM,GAAG,KAAK;AAC9B,UAAM,WAAW,KAAK,4BAA4B,OAAO;AAEzD,WAAO,EAAE,SAAS,SAAS;AAAA,EAC/B;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,eACF,WACA,YACA,YACA,iBACA,QACiE;AACjE,UAAM,gBAAgB,KAAK,YAAY,QAAQ,MAAM;AAErD,UAAM,YAAY;AAAA,MACd,mBAAmB,UAAU;AAAA,MAC7B,gBAAgB,UAAU;AAAA,MAC1B,gBAAgB,UAAU;AAAA,MAC1B,WAAW,UAAU;AAAA,MACrB,GAAG,UAAU;AAAA,MACb,GAAG,UAAU;AAAA,IACjB;AAEA,UAAM,aAAa,MAAM,KAAK,cAAc;AAE5C,UAAM,KAAK,MAAM,cAAc;AAAA,MAC3B;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA,EAAE,OAAO,WAAW;AAAA,IACxB;AAEA,UAAM,UAAU,MAAM,GAAG,KAAK;AAC9B,UAAM,WAAW,KAAK,4BAA4B,OAAO;AAEzD,WAAO,EAAE,SAAS,SAAS;AAAA,EAC/B;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,iBACF,WACA,YACA,YACA,mBACA,iBACA,QACiE;AACjE,UAAM,gBAAgB,KAAK,YAAY,QAAQ,MAAM;AAErD,UAAM,YAAY;AAAA,MACd,mBAAmB,UAAU;AAAA,MAC7B,gBAAgB,UAAU;AAAA,MAC1B,gBAAgB,UAAU;AAAA,MAC1B,WAAW,UAAU;AAAA,MACrB,GAAG,UAAU;AAAA,MACb,GAAG,UAAU;AAAA,IACjB;AAEA,UAAM,aAAa,MAAM,KAAK,cAAc;AAE5C,UAAM,KAAK,MAAM,cAAc;AAAA,MAC3B;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA,EAAE,OAAO,WAAW;AAAA,IACxB;AAEA,UAAM,UAAU,MAAM,GAAG,KAAK;AAC9B,UAAM,WAAW,KAAK,4BAA4B,OAAO;AAEzD,WAAO,EAAE,SAAS,SAAS;AAAA,EAC/B;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,gBACF,WACA,YACA,YACA,mBACA,QACiE;AACjE,UAAM,gBAAgB,KAAK,YAAY,QAAQ,MAAM;AAErD,UAAM,YAAY;AAAA,MACd,mBAAmB,UAAU;AAAA,MAC7B,gBAAgB,UAAU;AAAA,MAC1B,gBAAgB,UAAU;AAAA,MAC1B,WAAW,UAAU;AAAA,MACrB,GAAG,UAAU;AAAA,MACb,GAAG,UAAU;AAAA,IACjB;AAEA,UAAM,aAAa,MAAM,KAAK,cAAc;AAE5C,UAAM,KAAK,MAAM,cAAc;AAAA,MAC3B;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA,EAAE,OAAO,WAAW;AAAA,IACxB;AAEA,UAAM,UAAU,MAAM,GAAG,KAAK;AAC9B,UAAM,WAAW,KAAK,4BAA4B,OAAO;AAEzD,WAAO,EAAE,SAAS,SAAS;AAAA,EAC/B;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,gBACF,mBACA,eACA,eACA,QACiE;AACjE,UAAM,gBAAgB,KAAK,YAAY,QAAQ,MAAM;AAErD,UAAM,aAAa,MAAM,KAAK,cAAc;AAE5C,UAAM,KAAK,MAAM,cAAc;AAAA,MAC3B;AAAA,MACA;AAAA,MACA;AAAA,MACA,EAAE,OAAO,WAAW;AAAA,IACxB;AAEA,UAAM,UAAU,MAAM,GAAG,KAAK;AAC9B,UAAM,WAAW,KAAK,4BAA4B,OAAO;AAEzD,WAAO,EAAE,SAAS,SAAS;AAAA,EAC/B;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,eACF,WACA,YACA,YACA,QACiE;AACjE,UAAM,gBAAgB,KAAK,YAAY,QAAQ,MAAM;AAErD,UAAM,YAAY;AAAA,MACd,mBAAmB,UAAU;AAAA,MAC7B,gBAAgB,UAAU;AAAA,MAC1B,gBAAgB,UAAU;AAAA,MAC1B,WAAW,UAAU;AAAA,MACrB,GAAG,UAAU;AAAA,MACb,GAAG,UAAU;AAAA,IACjB;AAEA,UAAM,aAAa,MAAM,KAAK,cAAc;AAE5C,UAAM,KAAK,MAAM,cAAc;AAAA,MAC3B;AAAA,MACA;AAAA,MACA;AAAA,MACA,EAAE,OAAO,WAAW;AAAA,IACxB;AAEA,UAAM,UAAU,MAAM,GAAG,KAAK;AAC9B,UAAM,WAAW,KAAK,4BAA4B,OAAO;AAEzD,WAAO,EAAE,SAAS,SAAS;AAAA,EAC/B;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,aAAa,iBAIhB;AACC,UAAM,SAAS,MAAM,KAAK,YAAY,aAAa,eAAe;AAClE,WAAO;AAAA,MACH,WAAW,OAAO;AAAA,MAClB,WAAW,OAAO;AAAA,MAClB,cAAc,OAAO;AAAA,IACzB;AAAA,EACJ;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,kBAAkB,iBAQrB;AACC,UAAM,SAAS,MAAM,KAAK,YAAY,kBAAkB,eAAe;AACvE,WAAO;AAAA,MACH,UAAU,OAAO;AAAA,MACjB,iBAAiB,OAAO;AAAA,MACxB,aAAa,OAAO;AAAA,MACpB,eAAe,OAAO;AAAA,MACtB,WAAW,OAAO;AAAA,MAClB,cAAc,OAAO;AAAA,MACrB,WAAW,OAAO;AAAA,IACtB;AAAA,EACJ;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,oBACF,iBACA,iBACgB;AAChB,WAAO,KAAK,YAAY,oBAAoB,iBAAiB,eAAe;AAAA,EAChF;AAAA;AAAA;AAAA;AAAA,EAKQ,4BAA4B,SAA4C;AAC5E,eAAW,OAAO,QAAQ,MAAM;AAC5B,UAAI;AACA,cAAM,SAAS,KAAK,YAAY,UAAU,SAAS;AAAA,UAC/C,QAAQ,IAAI;AAAA,UACZ,MAAM,IAAI;AAAA,QACd,CAAC;AACD,YAAI,QAAQ,SAAS,YAAY;AAC7B,iBAAO,OAAO,OAAO,KAAK,QAAQ;AAAA,QACtC;AAAA,MACJ,QAAQ;AAAA,MAER;AAAA,IACJ;AACA,WAAO;AAAA,EACX;AACJ;;;AC56CO,IAAM,cAAc;AAAA;AAAA,EAEzB,MAAM;AAAA,EACN,UAAU;AAAA,EACV,UAAU;AAAA,EACV,QAAQ;AAAA,EACR,OAAO;AAAA,EACP,QAAQ;AAAA;AAAA,EAGR,UAAU;AAAA,EACV,SAAS;AAAA,EACT,KAAK;AAAA,EACL,WAAW;AAAA,EACX,QAAQ;AAAA,EACR,MAAM;AAAA,EACN,UAAU;AAAA;AAAA,EAGV,QAAQ;AAAA,EACR,OAAO;AAAA,EACP,KAAK;AAAA,EACL,UAAU;AAAA,EACV,MAAM;AAAA,EACN,KAAK;AACP;AA0BO,IAAM,gBAAgD;AAAA;AAAA;AAAA;AAAA,EAI3D,MAAM;AAAA,IACJ,aAAa;AAAA,IACb,MAAM;AAAA,IACN,UAAU;AAAA,IACV,SAAS;AAAA,MACP,MAAM;AAAA,MACN,SAAS;AAAA,MACT,iBAAiB;AAAA,MACjB,QAAQ;AAAA,MACR,aAAa;AAAA,MACb,OAAO;AAAA,MACP,WAAW;AAAA,QACT,KAAK;AAAA,QACL,cAAc;AAAA,QACd,qBAAqB;AAAA,QACrB,oBAAoB;AAAA,QACpB,aAAa;AAAA,MACf;AAAA,IACF;AAAA,IACA,SAAS;AAAA,MACP,MAAM;AAAA,MACN,SAAS;AAAA,MACT,iBAAiB;AAAA,MACjB,QAAQ;AAAA,MACR,aAAa;AAAA,MACb,OAAO;AAAA,MACP,WAAW;AAAA;AAAA,QAET,oBAAoB;AAAA,QACpB,aAAa;AAAA,MACf;AAAA,IACF;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAKA,UAAU;AAAA,IACR,aAAa;AAAA,IACb,MAAM;AAAA,IACN,UAAU;AAAA,IACV,SAAS;AAAA,MACP,MAAM;AAAA,MACN,SAAS;AAAA,MACT,iBAAiB;AAAA,MACjB,QAAQ;AAAA,MACR,aAAa;AAAA,MACb,OAAO;AAAA,MACP,WAAW;AAAA,QACT,cAAc;AAAA,QACd,qBAAqB;AAAA,QACrB,oBAAoB;AAAA,QACpB,aAAa;AAAA,MACf;AAAA,IACF;AAAA,IACA,SAAS;AAAA,MACP,MAAM;AAAA,MACN,SAAS;AAAA,MACT,iBAAiB;AAAA,MACjB,QAAQ;AAAA,MACR,aAAa;AAAA,MACb,OAAO;AAAA,MACP,WAAW;AAAA,QACT,oBAAoB;AAAA,QACpB,aAAa;AAAA,MACf;AAAA,IACF;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAKA,UAAU;AAAA,IACR,aAAa;AAAA,IACb,MAAM;AAAA,IACN,UAAU;AAAA,IACV,SAAS;AAAA,MACP,MAAM;AAAA,MACN,SAAS;AAAA,MACT,iBAAiB;AAAA,MACjB,QAAQ;AAAA,MACR,aAAa;AAAA,MACb,OAAO;AAAA,MACP,WAAW;AAAA,QACT,cAAc;AAAA,QACd,qBAAqB;AAAA,QACrB,oBAAoB;AAAA,QACpB,aAAa;AAAA,MACf;AAAA,IACF;AAAA,IACA,SAAS;AAAA,MACP,MAAM;AAAA,MACN,SAAS;AAAA,MACT,iBAAiB;AAAA,MACjB,QAAQ;AAAA,MACR,aAAa;AAAA,MACb,OAAO;AAAA,MACP,WAAW;AAAA,QACT,oBAAoB;AAAA,QACpB,aAAa;AAAA,MACf;AAAA,IACF;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAKA,UAAU;AAAA,IACR,aAAa;AAAA,IACb,MAAM;AAAA,IACN,UAAU;AAAA,IACV,SAAS;AAAA,MACP,MAAM;AAAA,MACN,SAAS;AAAA,MACT,iBAAiB;AAAA,MACjB,QAAQ;AAAA,MACR,aAAa;AAAA,MACb,OAAO;AAAA,MACP,WAAW;AAAA,QACT,oBAAoB;AAAA,QACpB,aAAa;AAAA,MACf;AAAA,IACF;AAAA,IACA,SAAS;AAAA,MACP,MAAM;AAAA,MACN,SAAS;AAAA,MACT,iBAAiB;AAAA,MACjB,QAAQ;AAAA,MACR,aAAa;AAAA,MACb,OAAO;AAAA,MACP,WAAW;AAAA,QACT,oBAAoB;AAAA,QACpB,aAAa;AAAA,MACf;AAAA,IACF;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAKA,SAAS;AAAA,IACP,aAAa;AAAA,IACb,MAAM;AAAA,IACN,UAAU;AAAA,IACV,SAAS;AAAA,MACP,MAAM;AAAA,MACN,SAAS;AAAA,MACT,iBAAiB;AAAA,MACjB,QAAQ;AAAA,MACR,aAAa;AAAA,MACb,OAAO;AAAA,MACP,WAAW;AAAA,QACT,oBAAoB;AAAA,QACpB,aAAa;AAAA,MACf;AAAA,IACF;AAAA,IACA,SAAS;AAAA,MACP,MAAM;AAAA,MACN,SAAS;AAAA,MACT,iBAAiB;AAAA,MACjB,QAAQ;AAAA,MACR,aAAa;AAAA,MACb,OAAO;AAAA,MACP,WAAW;AAAA,QACT,oBAAoB;AAAA,QACpB,aAAa;AAAA,MACf;AAAA,IACF;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAKA,KAAK;AAAA,IACH,aAAa;AAAA,IACb,MAAM;AAAA,IACN,UAAU;AAAA,IACV,SAAS;AAAA,MACP,MAAM;AAAA,MACN,SAAS;AAAA,MACT,iBAAiB;AAAA,MACjB,QAAQ;AAAA,MACR,aAAa;AAAA,MACb,OAAO;AAAA,MACP,WAAW;AAAA,QACT,oBAAoB;AAAA,QACpB,aAAa;AAAA,MACf;AAAA,IACF;AAAA,IACA,SAAS;AAAA,MACP,MAAM;AAAA,MACN,SAAS;AAAA,MACT,iBAAiB;AAAA,MACjB,QAAQ;AAAA,MACR,aAAa;AAAA,MACb,OAAO;AAAA,MACP,WAAW;AAAA,QACT,oBAAoB;AAAA,QACpB,aAAa;AAAA,MACf;AAAA,IACF;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAKA,WAAW;AAAA,IACT,aAAa;AAAA,IACb,MAAM;AAAA,IACN,UAAU;AAAA,IACV,SAAS;AAAA,MACP,MAAM;AAAA,MACN,SAAS;AAAA,MACT,iBAAiB;AAAA,MACjB,QAAQ;AAAA,MACR,aAAa;AAAA,MACb,OAAO;AAAA,MACP,WAAW;AAAA,QACT,oBAAoB;AAAA,QACpB,aAAa;AAAA,MACf;AAAA,IACF;AAAA,IACA,SAAS;AAAA,MACP,MAAM;AAAA,MACN,SAAS;AAAA,MACT,iBAAiB;AAAA,MACjB,QAAQ;AAAA,MACR,aAAa;AAAA,MACb,OAAO;AAAA,MACP,WAAW;AAAA,QACT,oBAAoB;AAAA,QACpB,aAAa;AAAA,MACf;AAAA,IACF;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAKA,QAAQ;AAAA,IACN,aAAa;AAAA,IACb,MAAM;AAAA,IACN,UAAU;AAAA,IACV,SAAS;AAAA,MACP,MAAM;AAAA,MACN,SAAS;AAAA,MACT,iBAAiB;AAAA,MACjB,QAAQ;AAAA,MACR,aAAa;AAAA,MACb,OAAO;AAAA,MACP,WAAW;AAAA,QACT,oBAAoB;AAAA,QACpB,aAAa;AAAA,MACf;AAAA,IACF;AAAA,IACA,SAAS;AAAA,MACP,MAAM;AAAA,MACN,SAAS;AAAA,MACT,iBAAiB;AAAA,MACjB,QAAQ;AAAA,MACR,aAAa;AAAA,MACb,OAAO;AAAA,MACP,WAAW;AAAA,QACT,oBAAoB;AAAA,QACpB,aAAa;AAAA,MACf;AAAA,IACF;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAKA,OAAO;AAAA,IACL,aAAa;AAAA,IACb,MAAM;AAAA,IACN,UAAU;AAAA,IACV,SAAS;AAAA,MACP,MAAM;AAAA,MACN,SAAS;AAAA,MACT,iBAAiB;AAAA,MACjB,QAAQ;AAAA,MACR,aAAa;AAAA,MACb,OAAO;AAAA,MACP,WAAW;AAAA,QACT,oBAAoB;AAAA,QACpB,aAAa;AAAA,MACf;AAAA,IACF;AAAA,IACA,SAAS;AAAA,MACP,MAAM;AAAA,MACN,SAAS;AAAA,MACT,iBAAiB;AAAA,MACjB,QAAQ;AAAA,MACR,aAAa;AAAA,MACb,OAAO;AAAA,MACP,WAAW;AAAA,QACT,oBAAoB;AAAA,QACpB,aAAa;AAAA,MACf;AAAA,IACF;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAKA,QAAQ;AAAA,IACN,aAAa;AAAA,IACb,MAAM;AAAA,IACN,UAAU;AAAA,IACV,SAAS;AAAA,MACP,MAAM;AAAA,MACN,SAAS;AAAA,MACT,iBAAiB;AAAA,MACjB,QAAQ;AAAA,MACR,aAAa;AAAA,MACb,OAAO;AAAA,MACP,WAAW;AAAA,QACT,oBAAoB;AAAA,QACpB,aAAa;AAAA,MACf;AAAA,IACF;AAAA,IACA,SAAS;AAAA,MACP,MAAM;AAAA,MACN,SAAS;AAAA,MACT,iBAAiB;AAAA,MACjB,QAAQ;AAAA,MACR,aAAa;AAAA,MACb,OAAO;AAAA,MACP,WAAW;AAAA,QACT,oBAAoB;AAAA,QACpB,aAAa;AAAA,MACf;AAAA,IACF;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAKA,QAAQ;AAAA,IACN,aAAa;AAAA,IACb,MAAM;AAAA,IACN,UAAU;AAAA,IACV,SAAS;AAAA,MACP,MAAM;AAAA,MACN,SAAS;AAAA,MACT,iBAAiB;AAAA,MACjB,QAAQ;AAAA,MACR,aAAa;AAAA,MACb,OAAO;AAAA,MACP,WAAW;AAAA,QACT,oBAAoB;AAAA,QACpB,aAAa;AAAA,MACf;AAAA,IACF;AAAA,IACA,SAAS;AAAA,MACP,MAAM;AAAA,MACN,SAAS;AAAA,MACT,iBAAiB;AAAA,MACjB,QAAQ;AAAA,MACR,aAAa;AAAA,MACb,OAAO;AAAA,MACP,WAAW;AAAA,QACT,oBAAoB;AAAA,QACpB,aAAa;AAAA,MACf;AAAA,IACF;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM;AAAA,IACJ,aAAa;AAAA,IACb,MAAM;AAAA,IACN,UAAU;AAAA,IACV,SAAS;AAAA,MACP,MAAM;AAAA,MACN,SAAS;AAAA,MACT,iBAAiB;AAAA,MACjB,QAAQ;AAAA,MACR,aAAa;AAAA,MACb,OAAO;AAAA,MACP,WAAW;AAAA,QACT,oBAAoB;AAAA,QACpB,aAAa;AAAA,MACf;AAAA,IACF;AAAA,IACA,SAAS;AAAA,MACP,MAAM;AAAA,MACN,SAAS;AAAA,MACT,iBAAiB;AAAA,MACjB,QAAQ;AAAA,MACR,aAAa;AAAA,MACb,OAAO;AAAA,MACP,WAAW;AAAA,QACT,oBAAoB;AAAA,QACpB,aAAa;AAAA,MACf;AAAA,IACF;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAKA,UAAU;AAAA,IACR,aAAa;AAAA,IACb,MAAM;AAAA,IACN,UAAU;AAAA,IACV,SAAS;AAAA,MACP,MAAM;AAAA,MACN,SAAS;AAAA,MACT,iBAAiB;AAAA,MACjB,QAAQ;AAAA,MACR,aAAa;AAAA,MACb,OAAO;AAAA,MACP,WAAW;AAAA,QACT,oBAAoB;AAAA,QACpB,aAAa;AAAA,MACf;AAAA,IACF;AAAA,IACA,SAAS;AAAA,MACP,MAAM;AAAA,MACN,SAAS;AAAA,MACT,iBAAiB;AAAA,MACjB,QAAQ;AAAA,MACR,aAAa;AAAA,MACb,OAAO;AAAA,MACP,WAAW;AAAA,QACT,oBAAoB;AAAA,QACpB,aAAa;AAAA,MACf;AAAA,IACF;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAKA,KAAK;AAAA,IACH,aAAa;AAAA,IACb,MAAM;AAAA,IACN,UAAU;AAAA,IACV,SAAS;AAAA,MACP,MAAM;AAAA,MACN,SAAS;AAAA,MACT,iBAAiB;AAAA,MACjB,QAAQ;AAAA,MACR,aAAa;AAAA,MACb,OAAO;AAAA,MACP,WAAW;AAAA,QACT,cAAc;AAAA,QACd,qBAAqB;AAAA,QACrB,oBAAoB;AAAA,MACtB;AAAA,IACF;AAAA,IACA,SAAS;AAAA,MACP,MAAM;AAAA,MACN,SAAS;AAAA,MACT,iBAAiB;AAAA,MACjB,QAAQ;AAAA,MACR,aAAa;AAAA,MACb,OAAO;AAAA,MACP,WAAW;AAAA,QACT,oBAAoB;AAAA,MACtB;AAAA,IACF;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAKA,QAAQ;AAAA,IACN,aAAa;AAAA,IACb,MAAM;AAAA,IACN,UAAU;AAAA,IACV,SAAS;AAAA,MACP,MAAM;AAAA,MACN,SAAS;AAAA,MACT,iBAAiB;AAAA,MACjB,QAAQ;AAAA,MACR,aAAa;AAAA,MACb,OAAO;AAAA,MACP,WAAW;AAAA,QACT,KAAK;AAAA,QACL,oBAAoB;AAAA,QACpB,aAAa;AAAA,MACf;AAAA,IACF;AAAA,IACA,SAAS;AAAA,MACP,MAAM;AAAA,MACN,SAAS;AAAA,MACT,iBAAiB;AAAA,MACjB,QAAQ;AAAA,MACR,aAAa;AAAA,MACb,OAAO;AAAA,MACP,WAAW;AAAA,QACT,oBAAoB;AAAA,QACpB,aAAa;AAAA,MACf;AAAA,IACF;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAKA,OAAO;AAAA,IACL,aAAa;AAAA,IACb,MAAM;AAAA,IACN,UAAU;AAAA,IACV,SAAS;AAAA,MACP,MAAM;AAAA,MACN,SAAS;AAAA,MACT,iBAAiB;AAAA,MACjB,QAAQ;AAAA,MACR,aAAa;AAAA,MACb,OAAO;AAAA,MACP,WAAW;AAAA,QACT,KAAK;AAAA,QACL,oBAAoB;AAAA,QACpB,aAAa;AAAA,MACf;AAAA,IACF;AAAA,IACA,SAAS;AAAA,MACP,MAAM;AAAA,MACN,SAAS;AAAA,MACT,iBAAiB;AAAA,MACjB,QAAQ;AAAA,MACR,aAAa;AAAA,MACb,OAAO;AAAA,MACP,WAAW;AAAA,QACT,oBAAoB;AAAA,QACpB,aAAa;AAAA,MACf;AAAA,IACF;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAKA,KAAK;AAAA,IACH,aAAa;AAAA,IACb,MAAM;AAAA,IACN,UAAU;AAAA,IACV,SAAS;AAAA,MACP,MAAM;AAAA,MACN,SAAS;AAAA,MACT,iBAAiB;AAAA,MACjB,QAAQ;AAAA,MACR,aAAa;AAAA,MACb,OAAO;AAAA,MACP,WAAW;AAAA,QACT,KAAK;AAAA,QACL,oBAAoB;AAAA,MACtB;AAAA,IACF;AAAA,IACA,SAAS;AAAA,MACP,MAAM;AAAA,MACN,SAAS;AAAA,MACT,iBAAiB;AAAA,MACjB,QAAQ;AAAA,MACR,aAAa;AAAA,MACb,OAAO;AAAA,MACP,WAAW;AAAA,QACT,oBAAoB;AAAA,MACtB;AAAA,IACF;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAKA,UAAU;AAAA,IACR,aAAa;AAAA,IACb,MAAM;AAAA,IACN,UAAU;AAAA,IACV,SAAS;AAAA,MACP,MAAM;AAAA,MACN,SAAS;AAAA,MACT,iBAAiB;AAAA;AAAA,MACjB,QAAQ;AAAA,MACR,aAAa;AAAA,MACb,OAAO;AAAA,MACP,WAAW;AAAA,QACT,KAAK;AAAA,QACL,oBAAoB;AAAA,MACtB;AAAA,MACA,YAAY;AAAA;AAAA,IACd;AAAA,IACA,SAAS;AAAA,MACP,MAAM;AAAA,MACN,SAAS;AAAA,MACT,iBAAiB;AAAA,MACjB,QAAQ;AAAA,MACR,aAAa;AAAA,MACb,OAAO;AAAA,MACP,WAAW;AAAA;AAAA,QAET,oBAAoB;AAAA,MACtB;AAAA,IACF;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM;AAAA,IACJ,aAAa;AAAA,IACb,MAAM;AAAA,IACN,UAAU;AAAA,IACV,SAAS;AAAA,MACP,MAAM;AAAA,MACN,SAAS;AAAA,MACT,iBAAiB;AAAA,MACjB,QAAQ;AAAA,MACR,aAAa;AAAA,MACb,OAAO;AAAA,MACP,WAAW;AAAA,QACT,oBAAoB;AAAA,QACpB,aAAa;AAAA,MACf;AAAA,IACF;AAAA,IACA,SAAS;AAAA,MACP,MAAM;AAAA,MACN,SAAS;AAAA,MACT,iBAAiB;AAAA,MACjB,QAAQ;AAAA,MACR,aAAa;AAAA,MACb,OAAO;AAAA,MACP,WAAW;AAAA,QACT,oBAAoB;AAAA,QACpB,aAAa;AAAA,MACf;AAAA,IACF;AAAA,EACF;AACF;AASO,SAAS,eACd,OACA,UAAuB,WACV;AACb,QAAM,SAAS,cAAc,KAAK;AAClC,MAAI,CAAC,QAAQ;AACX,UAAM,IAAI;AAAA,MACR,mBAAmB,KAAK,wBAAwB,OAAO,KAAK,aAAa,EAAE,KAAK,IAAI,CAAC;AAAA,IACvF;AAAA,EACF;AACA,SAAO,OAAO,OAAO;AACvB;AAKO,SAAS,eAAe,OAA+B;AAC5D,QAAM,SAAS,cAAc,KAAK;AAClC,MAAI,CAAC,QAAQ;AACX,UAAM,IAAI;AAAA,MACR,mBAAmB,KAAK,wBAAwB,OAAO,KAAK,aAAa,EAAE,KAAK,IAAI,CAAC;AAAA,IACvF;AAAA,EACF;AACA,SAAO;AACT;AAKO,SAAS,qBAAkC;AAChD,SAAO,OAAO,KAAK,aAAa;AAClC;AAKO,SAAS,eAA4B;AAC1C,SAAO,OAAO,QAAQ,aAAa,EAChC,OAAO,CAAC,CAAC,GAAG,MAAM,MAAM,OAAO,QAAQ,EACvC,IAAI,CAAC,CAAC,IAAI,MAAM,IAAiB;AACtC;AAKO,SAAS,iBAAiB,OAAmC;AAClE,SAAO,SAAS;AAClB;AAKO,SAAS,cAAc,UAAuB,WAAwB;AAC3E,SAAO,cAAc,KAAK,OAAO;AACnC;;;AC/oBA,SAAS,kBACP,OACA,SACA,cACa;AACb,QAAM,SAAS,eAAe,KAAK;AACnC,QAAM,SAAS,OAAO,OAAO;AAC7B,QAAM,SAAS,gBAAgB,OAAO;AAEtC,QAAM,gBAAgB,CAAC,OAA2B,UAA0B;AAC1E,QAAI,CAAC,OAAO;AACV,YAAM,IAAI,MAAM,WAAW,KAAK,eAAe,KAAK,iBAAiB,OAAO,GAAG;AAAA,IACjF;AACA,WAAO;AAAA,EACT;AAEA,UAAQ,OAAO,MAAM;AAAA,IACnB,KAAK;AACH,aAAO,IAAI,UAAU;AAAA,QACnB,SAAS,OAAO;AAAA,QAChB,iBAAiB,OAAO;AAAA,QACxB;AAAA,QACA,oBAAoB,cAAc,OAAO,UAAU,KAAK,sBAAsB;AAAA,QAC9E,oBAAoB,cAAc,OAAO,UAAU,oBAAoB,8BAA8B;AAAA,QACrG,cAAc,OAAO,UAAU;AAAA,QAC/B,qBAAqB,OAAO,UAAU;AAAA,QACtC,aAAa,OAAO,UAAU;AAAA,QAC9B,MAAM,OAAO;AAAA,QACb,aAAa,OAAO;AAAA,MACtB,CAAC;AAAA,IAEH,KAAK;AACH,aAAO,IAAI,aAAa;AAAA,QACtB;AAAA,QACA,WAAW,cAAc,OAAO,UAAU,KAAK,WAAW;AAAA,QAC1D,oBAAoB,cAAc,OAAO,UAAU,oBAAoB,8BAA8B;AAAA,QACrG,aAAa,cAAc,OAAO,UAAU,aAAa,sBAAsB;AAAA,QAC/E,iBAAiB,OAAO;AAAA,QACxB,SAAS,YAAY,YAAY,WAAW;AAAA,MAC9C,CAAC;AAAA,IAEH,KAAK;AACH,aAAO,IAAI,YAAY;AAAA,QACrB;AAAA,QACA,eAAe,cAAc,OAAO,UAAU,KAAK,eAAe;AAAA,QAClE,oBAAoB,cAAc,OAAO,UAAU,oBAAoB,8BAA8B;AAAA,QACrG,aAAa,cAAc,OAAO,UAAU,aAAa,sBAAsB;AAAA,QAC/E,iBAAiB,OAAO;AAAA,QACxB;AAAA,MACF,CAAC;AAAA,IAEH,KAAK;AACH,aAAO,IAAI,UAAU;AAAA,QACnB;AAAA,QACA,WAAW,cAAc,OAAO,UAAU,KAAK,WAAW;AAAA,QAC1D,oBAAoB,cAAc,OAAO,UAAU,oBAAoB,8BAA8B;AAAA,QACrG,iBAAiB,OAAO;AAAA,QACxB;AAAA,MACF,CAAC;AAAA,IAEH,KAAK;AACH,aAAO,IAAI,eAAe;AAAA,QACxB;AAAA,QACA,sBAAsB,OAAO,UAAU;AAAA,QACvC,uBAAuB,OAAO,UAAU;AAAA,QACxC,iBAAiB,OAAO;AAAA,QACxB,SAAS,YAAY,YAAY,YAAY;AAAA,MAC/C,CAAC;AAAA,IAEH,KAAK;AAAA,IACL,KAAK;AACH,YAAM,IAAI,MAAM,eAAe,OAAO,IAAI,sCAAsC;AAAA,IAElF;AACE,YAAM,IAAI,MAAM,uBAAuB,OAAO,IAAI,EAAE;AAAA,EACxD;AACF;AAiCO,SAAS,UACd,OACA,SAA0B,CAAC,GACf;AACZ,QAAM,UAAU,OAAO,WAAW;AAGlC,MAAI,CAAC,cAAc,KAAK,GAAG;AACzB,UAAM,kBAAkB,OAAO,KAAK,aAAa,EAAE,KAAK,IAAI;AAC5D,UAAM,IAAI;AAAA,MACR,mBAAmB,KAAK,wBAAwB,eAAe;AAAA,IACjE;AAAA,EACF;AAGA,QAAM,cAAc,kBAAkB,OAAO,SAAS,OAAO,MAAM;AAGnE,QAAM,eAAuC,CAAC;AAC9C,MAAI,OAAO,SAAS;AAClB,eAAW,CAAC,WAAW,MAAM,KAAK,OAAO,QAAQ,OAAO,OAAO,GAAG;AAChE,UAAI,UAAU,cAAc,SAAsB,GAAG;AACnD,cAAM,cAAc,eAAe,WAAwB,OAAO;AAClE,qBAAa,YAAY,eAAe,IAAI;AAAA,MAC9C;AAAA,IACF;AAAA,EACF;AAGA,SAAO,IAAI,WAAW;AAAA,IACpB,OAAO;AAAA,IACP,SAAS,YAAY;AAAA,IACrB,YAAY,OAAO;AAAA,IACnB,eAAe,OAAO;AAAA,IACtB,mBAAmB,OAAO;AAAA,IAC1B,sBAAsB,OAAO;AAAA,IAC7B,cAAc,OAAO,KAAK,YAAY,EAAE,SAAS,IAAI,eAAe;AAAA,EACtE,CAAC;AACH;AAcO,SAAS,aAAa,SAA0B,CAAC,GAAe;AACrE,SAAO,UAAU,QAAQ,MAAM;AACjC;AASO,SAAS,iBACd,QAAmB,QACnB,SAA2C,CAAC,GAChC;AACZ,SAAO,UAAU,OAAO,EAAE,GAAG,QAAQ,SAAS,UAAU,CAAC;AAC3D;AASO,SAAS,iBACd,QAAmB,QACnB,SAA2C,CAAC,GAChC;AACZ,SAAO,UAAU,OAAO,EAAE,GAAG,QAAQ,SAAS,UAAU,CAAC;AAC3D;AA8BO,SAAS,iBACd,QAAmB,QACnB,SAA0B,CAAC,GACf;AAEZ,QAAM,SAAS,eAAe,KAAK;AACnC,MAAI,CAAC,OAAO,UAAU;AACpB,YAAQ;AAAA,MACN,UAAU,KAAK;AAAA,IAEjB;AAAA,EACF;AAEA,SAAO,UAAU,OAAO,MAAM;AAChC;;;ACtVA,SAAS,UAAAE,gBAAc;;;ACuLhB,IAAM,eAAN,cAA2B,MAAM;AAAA,EACpC,YACI,SACO,MACA,SACT;AACE,UAAM,OAAO;AAHN;AACA;AAGP,SAAK,OAAO;AAAA,EAChB;AACJ;;;ACtMA,SAAS,UAAAC,gBAAc;AAQhB,IAAM,uBAAuB;AAG7B,IAAM,uBAAuB;AAG7B,IAAM,2BAA2B;AAGjC,IAAM,yBAAyB;AAyB/B,SAAS,2BAAoC;AAChD,MAAI;AAEA,UAAM,SAASC,SAAO,OAAO,aAAa;AAG1C,UAAM,aAAaA,SAAO,SAAS,OAAO,UAAU;AAKpD,UAAM,aAAa,IAAIA,SAAO,WAAW,OAAO,UAAU;AAC1D,UAAM,YAAYA,SAAO,SAAS,WAAW,SAAS;AAEtD,WAAO;AAAA,MACH;AAAA,MACA;AAAA,MACA,SAAS,OAAO;AAAA,IACpB;AAAA,EACJ,SAAS,OAAO;AACZ,UAAM,IAAI;AAAA,MACN;AAAA;AAAA,MAEA;AAAA,IACJ;AAAA,EACJ;AACJ;AAWO,SAAS,sBAAsB,WAA+B;AACjE,MAAI,UAAU,WAAW,MAAM,UAAU,CAAC,MAAM,GAAM;AAClD,UAAM,IAAI;AAAA,MACN;AAAA;AAAA,IAEJ;AAAA,EACJ;AAGA,SAAOA,SAAO,UAAU,SAAS;AACrC;AAaO,SAAS,mBACZ,YACA,aAC0D;AAC1D,MAAI;AACA,QAAI,WAAW,WAAW,IAAI;AAC1B,YAAM,IAAI;AAAA,QACN;AAAA;AAAA,MAEJ;AAAA,IACJ;AAGA,UAAM,aAAa,IAAIA,SAAO,WAAW,UAAU;AAGnD,UAAM,YAAY,OAAO,gBAAgB,WACnCA,SAAO,SAAS,WAAW,IAC3B;AAEN,QAAI,UAAU,WAAW,IAAI;AACzB,YAAM,IAAI;AAAA,QACN;AAAA;AAAA,MAEJ;AAAA,IACJ;AAGA,UAAM,MAAM,WAAW,KAAK,SAAS;AAGrC,UAAM,IAAI,IAAI;AACd,UAAM,IAAI,IAAI;AACd,UAAM,IAAI,IAAI;AAGd,UAAM,YAAYA,SAAO,SAAS,IAAI,UAAU;AAEhD,WAAO,EAAE,GAAG,GAAG,GAAG,UAAU;AAAA,EAChC,SAAS,OAAO;AACZ,UAAM,IAAI;AAAA,MACN;AAAA;AAAA,MAEA;AAAA,IACJ;AAAA,EACJ;AACJ;AAeO,SAAS,WAAW,QAOZ;AACX,MAAI;AAEA,UAAM,cAAcA,SAAO,UAAU,OAAO,OAAO;AAGnD,UAAM,UAAUA,SAAO;AAAA,MACnB,CAAC,UAAU,WAAW,WAAW,WAAW,WAAW,SAAS;AAAA,MAChE;AAAA,QACI,OAAO;AAAA,QACP,OAAO;AAAA,QACP,OAAO;AAAA,QACP;AAAA,QACA,OAAO;AAAA,QACP,OAAO,YAAY;AAAA,MACvB;AAAA,IACJ;AAGA,WAAOA,SAAO,SAASA,SAAO,UAAU,OAAO,CAAC;AAAA,EACpD,SAAS,OAAO;AACZ,UAAM,IAAI;AAAA,MACN;AAAA;AAAA,MAEA;AAAA,IACJ;AAAA,EACJ;AACJ;AAaO,SAAS,uBACZ,aACA,WACA,mBACO;AACP,MAAI;AACA,QAAI,UAAU,WAAW,IAAI;AACzB,aAAO;AAAA,IACX;AAGA,UAAM,YAAY,OAAO,gBAAgB,WACnCA,SAAO,SAAS,WAAW,IAC3B;AAGN,UAAM,YAAYA,SAAO,WAAW;AAAA,MAChC;AAAA,MACAA,SAAO,QAAQ,SAAS;AAAA,IAC5B;AAGA,UAAM,iBAAiBA,SAAO,SAAS,SAAS;AAEhD,QAAI,eAAe,WAAW,kBAAkB,QAAQ;AACpD,aAAO;AAAA,IACX;AAGA,WAAO,eAAe,MAAM,CAAC,MAAM,MAAM,SAAS,kBAAkB,CAAC,CAAC;AAAA,EAC1E,QAAQ;AACJ,WAAO;AAAA,EACX;AACJ;AAoBA,eAAsB,oBAAoB,cAA0C;AAChF,MAAI;AAEA,UAAM,gBAAgBA,SAAO,YAAY,YAAY;AAGrD,UAAM,cAAc,MAAM,OAAO,OAAO;AAAA,MACpC;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA,CAAC,WAAW;AAAA,IAChB;AAGA,UAAM,YAAYA,SAAO,SAASA,SAAO,UAAU,aAAa,CAAC;AAGjE,UAAM,MAAM,MAAM,OAAO,OAAO;AAAA,MAC5B;AAAA,QACI,MAAM;AAAA,QACN,MAAM;AAAA,QACN,YAAY;AAAA;AAAA,QACZ,MAAM;AAAA,MACV;AAAA,MACA;AAAA,MACA;AAAA,QACI,MAAM;AAAA,QACN,QAAQ;AAAA,MACZ;AAAA,MACA;AAAA;AAAA,MACA,CAAC,WAAW,SAAS;AAAA,IACzB;AAEA,WAAO;AAAA,EACX,SAAS,OAAO;AACZ,UAAM,IAAI;AAAA,MACN;AAAA;AAAA,MAEA;AAAA,IACJ;AAAA,EACJ;AACJ;AAOO,SAAS,aAAyB;AACrC,SAAO,OAAO,gBAAgB,IAAI,WAAW,EAAE,CAAC;AACpD;AASA,eAAsB,QAAQ,MAAkB,KAAqC;AACjF,MAAI;AACA,UAAM,KAAK,WAAW;AAEtB,UAAM,YAAY,MAAM,OAAO,OAAO;AAAA,MAClC;AAAA,QACI,MAAM;AAAA,QACN;AAAA,MACJ;AAAA,MACA;AAAA,MACA;AAAA,IACJ;AAGA,UAAM,SAAS,IAAI,WAAW,GAAG,SAAS,UAAU,UAAU;AAC9D,WAAO,IAAI,IAAI,CAAC;AAChB,WAAO,IAAI,IAAI,WAAW,SAAS,GAAG,GAAG,MAAM;AAE/C,WAAO;AAAA,EACX,SAAS,OAAO;AACZ,UAAM,IAAI;AAAA,MACN;AAAA;AAAA,MAEA;AAAA,IACJ;AAAA,EACJ;AACJ;AASA,eAAsB,QAAQ,eAA2B,KAAqC;AAC1F,MAAI;AACA,QAAI,cAAc,SAAS,IAAI;AAC3B,YAAM,IAAI,MAAM,oCAAoC;AAAA,IACxD;AAGA,UAAM,KAAK,cAAc,MAAM,GAAG,EAAE;AAGpC,UAAM,aAAa,cAAc,MAAM,EAAE;AAEzC,UAAM,YAAY,MAAM,OAAO,OAAO;AAAA,MAClC;AAAA,QACI,MAAM;AAAA,QACN;AAAA,MACJ;AAAA,MACA;AAAA,MACA;AAAA,IACJ;AAEA,WAAO,IAAI,WAAW,SAAS;AAAA,EACnC,SAAS,OAAO;AACZ,UAAM,IAAI;AAAA,MACN;AAAA;AAAA,MAEA;AAAA,IACJ;AAAA,EACJ;AACJ;AAYO,SAAS,sBAAsB,QAG7B;AACL,MAAI,OAAO,WAAW,sBAAsB;AACxC,UAAM,IAAI;AAAA,MACN,wCAAwC,oBAAoB;AAAA;AAAA,IAEhE;AAAA,EACJ;AAEA,MAAI,OAAO,WAAW,sBAAsB;AACxC,UAAM,IAAI;AAAA,MACN,uCAAuC,oBAAoB;AAAA;AAAA,IAE/D;AAAA,EACJ;AAEA,MAAI,OAAO,WAAW,IAAI;AACtB,UAAM,IAAI;AAAA,MACN;AAAA;AAAA,IAEJ;AAAA,EACJ;AACJ;;;ACpaA,SAAS,UAAAC,gBAAc;AAUvB,IAAM,UAAU;AAGhB,IAAM,aAAa;AAGnB,IAAM,aAAa;AAWZ,IAAM,0BAAN,MAAwD;AAAA,EACnD,KAAyB;AAAA,EACzB,gBAAkC;AAAA,EAClC;AAAA;AAAA;AAAA;AAAA,EAKR,YAAY,cAAsB;AAC9B,QAAI,CAAC,cAAc;AACf,YAAM,IAAI;AAAA,QACN;AAAA;AAAA,MAEJ;AAAA,IACJ;AACA,SAAK,eAAe;AAAA,EACxB;AAAA;AAAA;AAAA;AAAA,EAKA,MAAc,aAA4B;AACtC,QAAI,KAAK,GAAI;AAEb,WAAO,IAAI,QAAQ,CAAC,SAAS,WAAW;AACpC,YAAM,UAAU,UAAU,KAAK,SAAS,UAAU;AAElD,cAAQ,UAAU,MAAM;AACpB,eAAO,IAAI;AAAA,UACP;AAAA;AAAA,UAEA,QAAQ;AAAA,QACZ,CAAC;AAAA,MACL;AAEA,cAAQ,YAAY,MAAM;AACtB,aAAK,KAAK,QAAQ;AAClB,gBAAQ;AAAA,MACZ;AAEA,cAAQ,kBAAkB,CAAC,UAAU;AACjC,cAAM,KAAM,MAAM,OAA4B;AAG9C,YAAI,CAAC,GAAG,iBAAiB,SAAS,UAAU,GAAG;AAC3C,gBAAM,QAAQ,GAAG,kBAAkB,YAAY,EAAE,SAAS,UAAU,CAAC;AAGrE,gBAAM,YAAY,eAAe,eAAe,EAAE,QAAQ,MAAM,CAAC;AACjE,gBAAM,YAAY,UAAU,UAAU,EAAE,QAAQ,MAAM,CAAC;AAAA,QAC3D;AAAA,MACJ;AAAA,IACJ,CAAC;AAAA,EACL;AAAA;AAAA;AAAA;AAAA,EAKA,MAAc,mBAAuC;AACjD,QAAI,KAAK,eAAe;AACpB,aAAO,KAAK;AAAA,IAChB;AAEA,SAAK,gBAAgB,MAAM,oBAAoB,KAAK,YAAY;AAChE,WAAO,KAAK;AAAA,EAChB;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,KAAK,SAAoC;AAC3C,QAAI;AACA,YAAM,KAAK,WAAW;AAEtB,UAAI,CAAC,KAAK,IAAI;AACV,cAAM,IAAI,MAAM,0BAA0B;AAAA,MAC9C;AAGA,YAAM,MAAM,MAAM,KAAK,iBAAiB;AAGxC,YAAM,sBAAsB,MAAM,QAAQ,QAAQ,YAAY,GAAG;AAGjE,YAAM,gBAAgB;AAAA,QAClB,SAAS,QAAQ;AAAA,QACjB,WAAW,MAAM,KAAK,QAAQ,SAAS;AAAA;AAAA,QACvC,qBAAqB,MAAM,KAAK,mBAAmB;AAAA,QACnD,QAAQ,QAAQ;AAAA,QAChB,UAAU,QAAQ,SAAS,SAAS;AAAA;AAAA,QACpC,aAAa,QAAQ;AAAA,QACrB,aAAa,QAAQ;AAAA,QACrB,SAAS,KAAK,IAAI;AAAA,MACtB;AAGA,aAAO,IAAI,QAAQ,CAAC,SAAS,WAAW;AACpC,cAAM,cAAc,KAAK,GAAI,YAAY,CAAC,UAAU,GAAG,WAAW;AAClE,cAAM,QAAQ,YAAY,YAAY,UAAU;AAChD,cAAM,UAAU,MAAM,IAAI,aAAa;AAEvC,gBAAQ,YAAY,MAAM,QAAQ;AAClC,gBAAQ,UAAU,MAAM;AACpB,iBAAO,IAAI;AAAA,YACP;AAAA;AAAA,YAEA,QAAQ;AAAA,UACZ,CAAC;AAAA,QACL;AAAA,MACJ,CAAC;AAAA,IACL,SAAS,OAAO;AACZ,UAAI,iBAAiB,cAAc;AAC/B,cAAM;AAAA,MACV;AACA,YAAM,IAAI;AAAA,QACN;AAAA;AAAA,QAEA;AAAA,MACJ;AAAA,IACJ;AAAA,EACJ;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,OAAmC;AACrC,QAAI;AACA,YAAM,KAAK,WAAW;AAEtB,UAAI,CAAC,KAAK,IAAI;AACV,cAAM,IAAI,MAAM,0BAA0B;AAAA,MAC9C;AAGA,YAAM,cAAc,MAAM,KAAK,eAAe;AAE9C,UAAI,YAAY,WAAW,GAAG;AAC1B,eAAO;AAAA,MACX;AAGA,YAAM,MAAM,KAAK,IAAI;AACrB,YAAM,gBAAgB,YACjB,OAAO,OAAK,EAAE,SAAS,GAAG,EAC1B,KAAK,CAAC,GAAG,MAAM,EAAE,UAAU,EAAE,OAAO;AAEzC,UAAI,cAAc,WAAW,GAAG;AAE5B,cAAM,KAAK,MAAM;AACjB,eAAO;AAAA,MACX;AAEA,YAAM,SAAS,cAAc,CAAC;AAG9B,YAAM,MAAM,MAAM,KAAK,iBAAiB;AAGxC,YAAM,sBAAsB,IAAI,WAAW,OAAO,mBAAmB;AACrE,YAAM,aAAa,MAAM,QAAQ,qBAAqB,GAAG;AAGzD,YAAM,UAAsB;AAAA,QACxB,SAAS,OAAO;AAAA,QAChB,WAAW,IAAI,WAAW,OAAO,SAAS;AAAA,QAC1C;AAAA,QACA,QAAQ,OAAO;AAAA,QACf,UAAU,OAAO,OAAO,QAAQ;AAAA,QAChC,aAAa,OAAO;AAAA,QACpB,aAAa,OAAO;AAAA,MACxB;AAEA,aAAO;AAAA,IACX,SAAS,OAAO;AACZ,UAAI,iBAAiB,cAAc;AAC/B,cAAM;AAAA,MACV;AACA,YAAM,IAAI;AAAA,QACN;AAAA;AAAA,QAEA;AAAA,MACJ;AAAA,IACJ;AAAA,EACJ;AAAA;AAAA;AAAA;AAAA,EAKA,MAAc,iBAAsC;AAChD,QAAI,CAAC,KAAK,IAAI;AACV,aAAO,CAAC;AAAA,IACZ;AAEA,WAAO,IAAI,QAAQ,CAAC,SAAS,WAAW;AACpC,YAAM,cAAc,KAAK,GAAI,YAAY,CAAC,UAAU,GAAG,UAAU;AACjE,YAAM,QAAQ,YAAY,YAAY,UAAU;AAChD,YAAM,UAAU,MAAM,OAAO;AAE7B,cAAQ,YAAY,MAAM,QAAQ,QAAQ,UAAU,CAAC,CAAC;AACtD,cAAQ,UAAU,MAAM;AACpB,eAAO,IAAI;AAAA,UACP;AAAA;AAAA,UAEA,QAAQ;AAAA,QACZ,CAAC;AAAA,MACL;AAAA,IACJ,CAAC;AAAA,EACL;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,QAAuB;AACzB,QAAI;AACA,YAAM,KAAK,WAAW;AAEtB,UAAI,CAAC,KAAK,IAAI;AACV;AAAA,MACJ;AAEA,aAAO,IAAI,QAAQ,CAAC,SAAS,WAAW;AACpC,cAAM,cAAc,KAAK,GAAI,YAAY,CAAC,UAAU,GAAG,WAAW;AAClE,cAAM,QAAQ,YAAY,YAAY,UAAU;AAChD,cAAM,UAAU,MAAM,MAAM;AAE5B,gBAAQ,YAAY,MAAM,QAAQ;AAClC,gBAAQ,UAAU,MAAM;AACpB,iBAAO,IAAI;AAAA,YACP;AAAA;AAAA,YAEA,QAAQ;AAAA,UACZ,CAAC;AAAA,QACL;AAAA,MACJ,CAAC;AAAA,IACL,SAAS,OAAO;AACZ,UAAI,iBAAiB,cAAc;AAC/B,cAAM;AAAA,MACV;AACA,YAAM,IAAI;AAAA,QACN;AAAA;AAAA,QAEA;AAAA,MACJ;AAAA,IACJ;AAAA,EACJ;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,SAA2B;AAC7B,QAAI;AACA,YAAM,KAAK,WAAW;AAEtB,UAAI,CAAC,KAAK,IAAI;AACV,eAAO;AAAA,MACX;AAEA,YAAM,WAAW,MAAM,KAAK,eAAe;AAC3C,aAAO,SAAS,SAAS;AAAA,IAC7B,QAAQ;AACJ,aAAO;AAAA,IACX;AAAA,EACJ;AAAA;AAAA;AAAA;AAAA,EAKA,QAAc;AACV,QAAI,KAAK,IAAI;AACT,WAAK,GAAG,MAAM;AACd,WAAK,KAAK;AAAA,IACd;AAAA,EACJ;AACJ;AAOA,IAAM,qBAAqB;AAYpB,IAAM,6BAAN,MAA2D;AAAA,EACtD,gBAAkC;AAAA,EAClC;AAAA,EACA;AAAA;AAAA;AAAA;AAAA,EAKR,YAAY,cAAsB;AAC9B,QAAI,CAAC,cAAc;AACf,YAAM,IAAI;AAAA,QACN;AAAA;AAAA,MAEJ;AAAA,IACJ;AACA,SAAK,eAAe;AACpB,SAAK,aAAa,qBAAqBC,SAAO,UAAUA,SAAO,YAAY,YAAY,CAAC;AAAA,EAC5F;AAAA;AAAA;AAAA;AAAA,EAKA,MAAc,mBAAuC;AACjD,QAAI,KAAK,eAAe;AACpB,aAAO,KAAK;AAAA,IAChB;AAEA,SAAK,gBAAgB,MAAM,oBAAoB,KAAK,YAAY;AAChE,WAAO,KAAK;AAAA,EAChB;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,KAAK,SAAoC;AAC3C,QAAI;AAEA,YAAM,MAAM,MAAM,KAAK,iBAAiB;AAGxC,YAAM,sBAAsB,MAAM,QAAQ,QAAQ,YAAY,GAAG;AAGjE,YAAM,gBAAgB;AAAA,QAClB,SAAS,QAAQ;AAAA,QACjB,WAAWA,SAAO,QAAQ,QAAQ,SAAS;AAAA,QAC3C,qBAAqBA,SAAO,QAAQ,mBAAmB;AAAA,QACvD,QAAQ,QAAQ;AAAA,QAChB,UAAU,QAAQ,SAAS,SAAS;AAAA,QACpC,aAAa,QAAQ;AAAA,QACrB,aAAa,QAAQ;AAAA,QACrB,SAAS,KAAK,IAAI;AAAA,MACtB;AAGA,mBAAa,QAAQ,KAAK,YAAY,KAAK,UAAU,aAAa,CAAC;AAAA,IACvE,SAAS,OAAO;AACZ,UAAI,iBAAiB,cAAc;AAC/B,cAAM;AAAA,MACV;AACA,YAAM,IAAI;AAAA,QACN;AAAA;AAAA,QAEA;AAAA,MACJ;AAAA,IACJ;AAAA,EACJ;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,OAAmC;AACrC,QAAI;AACA,YAAM,OAAO,aAAa,QAAQ,KAAK,UAAU;AAEjD,UAAI,CAAC,MAAM;AACP,eAAO;AAAA,MACX;AAEA,YAAM,SAAS,KAAK,MAAM,IAAI;AAG9B,UAAI,OAAO,UAAU,KAAK,IAAI,GAAG;AAC7B,cAAM,KAAK,MAAM;AACjB,eAAO;AAAA,MACX;AAGA,YAAM,MAAM,MAAM,KAAK,iBAAiB;AAGxC,YAAM,sBAAsBA,SAAO,SAAS,OAAO,mBAAmB;AACtE,YAAM,aAAa,MAAM,QAAQ,qBAAqB,GAAG;AAGzD,YAAM,UAAsB;AAAA,QACxB,SAAS,OAAO;AAAA,QAChB,WAAWA,SAAO,SAAS,OAAO,SAAS;AAAA,QAC3C;AAAA,QACA,QAAQ,OAAO;AAAA,QACf,UAAU,OAAO,OAAO,QAAQ;AAAA,QAChC,aAAa,OAAO;AAAA,QACpB,aAAa,OAAO;AAAA,MACxB;AAEA,aAAO;AAAA,IACX,SAAS,OAAO;AAEZ,YAAM,KAAK,MAAM;AAEjB,UAAI,iBAAiB,cAAc;AAC/B,cAAM;AAAA,MACV;AACA,YAAM,IAAI;AAAA,QACN;AAAA;AAAA,QAEA;AAAA,MACJ;AAAA,IACJ;AAAA,EACJ;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,QAAuB;AACzB,QAAI;AACA,mBAAa,WAAW,KAAK,UAAU;AAAA,IAC3C,SAAS,OAAO;AACZ,YAAM,IAAI;AAAA,QACN;AAAA;AAAA,QAEA;AAAA,MACJ;AAAA,IACJ;AAAA,EACJ;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,SAA2B;AAC7B,QAAI;AACA,aAAO,aAAa,QAAQ,KAAK,UAAU,MAAM;AAAA,IACrD,QAAQ;AACJ,aAAO;AAAA,IACX;AAAA,EACJ;AACJ;AAaO,SAAS,qBACZ,cACA,kBACc;AAEd,MAAI,OAAO,WAAW,aAAa;AAC/B,UAAM,IAAI;AAAA,MACN;AAAA;AAAA,IAEJ;AAAA,EACJ;AAGA,MAAI,qBAAqB,kBAAkB,OAAO,cAAc,aAAa;AACzE,QAAI;AACA,aAAO,IAAI,wBAAwB,YAAY;AAAA,IACnD,SAAS,OAAO;AACZ,cAAQ,KAAK,wDAAwD,KAAK;AAAA,IAC9E;AAAA,EACJ;AAGA,MAAI,OAAO,iBAAiB,aAAa;AACrC,WAAO,IAAI,2BAA2B,YAAY;AAAA,EACtD;AAEA,QAAM,IAAI;AAAA,IACN;AAAA;AAAA,EAEJ;AACJ;;;AHhbA,IAAM,iBAAN,MAAqB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAejB,YACY,YACA,WACA,aACR,QACA,eACF;AALU;AACA;AACA;AAKR,SAAK,SAAS;AAAA,MACV,UAAU,OAAO,YAAY;AAAA,MAC7B,UAAU,OAAO,YAAY;AAAA,MAC7B,aAAa,OAAO,eAAe;AAAA,MACnC,eAAe,OAAO,iBAAiB;AAAA,MACvC,aAAa,OAAO,eAAe,CAAC;AAAA,IACxC;AAEA,0BAAsB,KAAK,MAAM;AAEjC,SAAK,QAAQ,eAAe,SAAS;AAGrC,SAAK,UAAU,eAAe,gBACxB,qBAAqB,WAAW,YAAY,IAC5C;AAAA,MACE,WAAW;AAAA,MACX,eAAe;AAAA,IACnB;AAAA,EACR;AAAA,EAzCQ,iBAAoC;AAAA,EACpC;AAAA,EACA;AAAA,EACA,eAAsC;AAAA,EACtC,iBAAyC,CAAC;AAAA,EAC1C;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAuDR,MAAM,gBAAqC;AACvC,QAAI;AACA,WAAK,IAAI,yBAAyB;AAGlC,YAAM,UAAU,yBAAyB;AACzC,YAAM,UAAU,sBAAsB,QAAQ,SAAS;AAEvD,WAAK,IAAI,0BAA0B,OAAO;AAG1C,YAAM,YAAYC,SAAO;AAAA,QACrB,CAAC,UAAU,WAAW,WAAW,SAAS;AAAA,QAC1C,CAAC,mBAAmB,SAAS,KAAK,OAAO,UAAU,KAAK,OAAO,QAAQ;AAAA,MAC3E;AAEA,WAAK,IAAI,qDAAqD;AAG9D,YAAM,YAAY,MAAM,KAAK,YAAYA,SAAO,SAAS,SAAS,CAAC;AAEnE,WAAK,IAAI,mDAAmD;AAG5D,YAAM,iBAAwC;AAAA,QAC1C;AAAA,QACA,YAAY,KAAK,WAAW;AAAA,QAC5B,YAAY,KAAK,WAAW;AAAA,QAC5B,gBAAgB;AAAA,QAChB,UAAU,KAAK,OAAO;AAAA,QACtB,UAAU,KAAK,OAAO;AAAA,QACtB,WAAW;AAAA,MACf;AAEA,YAAM,KAAK,UAAU,gBAAgB,cAAc;AAEnD,WAAK,IAAI,2BAA2B;AAGpC,YAAM,SAAS,KAAK,IAAI,IAAI,KAAK,OAAO,WAAW;AAEnD,WAAK,iBAAiB;AAAA,QAClB,WAAW,QAAQ;AAAA,QACnB,YAAY,QAAQ;AAAA,QACpB;AAAA,QACA;AAAA,QACA,UAAU,KAAK,OAAO;AAAA,QACtB,aAAa,KAAK,OAAO;AAAA,QACzB,aAAa,KAAK,WAAW;AAAA,MACjC;AAGA,YAAM,KAAK,QAAQ,KAAK,KAAK,cAAc;AAE3C,WAAK,IAAI,yBAAyB;AAGlC,UAAI,KAAK,OAAO,aAAa;AACzB,aAAK,gBAAgB;AAAA,MACzB;AAGA,WAAK,KAAK,EAAE,MAAM,mBAAmB,SAAS,KAAK,eAAe,CAAC;AAEnE,aAAO,KAAK;AAAA,IAEhB,SAAS,OAAO;AACZ,YAAM,eAAe,iBAAiB,eAChC,QACA,IAAI;AAAA,QACF;AAAA;AAAA,QAEA;AAAA,MACJ;AAEJ,WAAK,KAAK,EAAE,MAAM,iBAAiB,OAAO,aAAa,CAAC;AACxD,YAAM;AAAA,IACV;AAAA,EACJ;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,MAAM,cAA0C;AAC5C,QAAI;AACA,WAAK,IAAI,iCAAiC;AAE1C,YAAM,UAAU,MAAM,KAAK,QAAQ,KAAK;AAExC,UAAI,CAAC,SAAS;AACV,aAAK,IAAI,6BAA6B;AACtC,eAAO;AAAA,MACX;AAGA,UAAI,QAAQ,UAAU,KAAK,IAAI,GAAG;AAC9B,aAAK,IAAI,8BAA8B;AACvC,cAAM,KAAK,QAAQ,MAAM;AACzB,eAAO;AAAA,MACX;AAEA,WAAK,iBAAiB;AACtB,WAAK,IAAI,mBAAmB,QAAQ,OAAO;AAG3C,UAAI,KAAK,OAAO,aAAa;AACzB,aAAK,gBAAgB;AAAA,MACzB;AAEA,WAAK,KAAK,EAAE,MAAM,kBAAkB,QAAQ,CAAC;AAE7C,aAAO;AAAA,IAEX,SAAS,OAAO;AACZ,WAAK,IAAI,2BAA2B,KAAK;AACzC,YAAM,KAAK,QAAQ,MAAM;AACzB,aAAO;AAAA,IACX;AAAA,EACJ;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,MAAM,gBAA+B;AACjC,QAAI,CAAC,KAAK,gBAAgB;AACtB,YAAM,IAAI;AAAA,QACN;AAAA;AAAA,MAEJ;AAAA,IACJ;AAEA,QAAI;AACA,WAAK,IAAI,qBAAqB,KAAK,eAAe,OAAO;AAGzD,YAAM,YAAYA,SAAO;AAAA,QACrB,CAAC,UAAU,SAAS;AAAA,QACpB,CAAC,iBAAiB,KAAK,eAAe,OAAO;AAAA,MACjD;AAGA,YAAM,YAAY,MAAM,KAAK,YAAYA,SAAO,SAAS,SAAS,CAAC;AAEnE,WAAK,IAAI,gDAAgD;AAGzD,YAAM,eAAoC;AAAA,QACtC;AAAA,QACA,YAAY,KAAK,WAAW;AAAA,QAC5B,YAAY,KAAK,WAAW;AAAA,QAC5B,gBAAgB,KAAK,eAAe;AAAA,QACpC,WAAW;AAAA,MACf;AAEA,YAAM,KAAK,UAAU,cAAc,YAAY;AAE/C,WAAK,IAAI,wBAAwB;AAGjC,YAAM,KAAK,QAAQ,MAAM;AAGzB,UAAI,KAAK,cAAc;AACnB,qBAAa,KAAK,YAAY;AAC9B,aAAK,eAAe;AAAA,MACxB;AAEA,YAAM,iBAAiB,KAAK,eAAe;AAC3C,WAAK,iBAAiB;AAGtB,WAAK,KAAK,EAAE,MAAM,mBAAmB,SAAS,eAAe,CAAC;AAE9D,WAAK,IAAI,8BAA8B;AAAA,IAE3C,SAAS,OAAO;AACZ,YAAM,eAAe,iBAAiB,eAChC,QACA,IAAI;AAAA,QACF;AAAA;AAAA,QAEA;AAAA,MACJ;AAEJ,WAAK,KAAK,EAAE,MAAM,iBAAiB,OAAO,aAAa,CAAC;AACxD,YAAM;AAAA,IACV;AAAA,EACJ;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAaA,MAAM,gBAAgB,QAAiD;AACnE,QAAI,CAAC,KAAK,gBAAgB;AACtB,YAAM,IAAI;AAAA,QACN;AAAA;AAAA,MAEJ;AAAA,IACJ;AAEA,UAAM,MAAM,KAAK,IAAI;AACrB,QAAI,OAAO,KAAK,eAAe,QAAQ;AACnC,WAAK,KAAK,EAAE,MAAM,mBAAmB,SAAS,KAAK,eAAe,QAAQ,CAAC;AAC3E,YAAM,IAAI;AAAA,QACN;AAAA;AAAA,MAEJ;AAAA,IACJ;AAEA,QAAI,KAAK,eAAe,WAAW,MAAM,OAAO,QAAQ,KAAK,eAAe,UAAU;AAClF,YAAM,IAAI;AAAA,QACN,sBAAsB,OAAO,KAAK,4BAA4B,KAAK,eAAe,QAAQ;AAAA;AAAA,QAE1F,EAAE,OAAO,OAAO,OAAO,OAAO,KAAK,eAAe,SAAS;AAAA,MAC/D;AAAA,IACJ;AAEA,QACI,KAAK,eAAe,YAAY,SAAS,KACzC,CAAC,KAAK,eAAe,YAAY,SAAS,OAAO,WAAW,GAC9D;AACE,YAAM,IAAI;AAAA,QACN,SAAS,OAAO,WAAW;AAAA;AAAA,QAE3B,EAAE,OAAO,OAAO,aAAa,eAAe,KAAK,eAAe,YAAY;AAAA,MAChF;AAAA,IACJ;AAEA,SAAK,IAAI,oCAAoC;AAE7C,UAAM,cAAc,WAAW,MAAM;AACrC,UAAM,EAAE,UAAU,IAAI;AAAA,MAClB,KAAK,eAAe;AAAA,MACpB;AAAA,IACJ;AAEA,UAAM,mBAAqC;AAAA,MACvC;AAAA,MACA,gBAAgB,KAAK,eAAe;AAAA,MACpC,aAAa,KAAK,eAAe;AAAA,MACjC,WAAW;AAAA,MACX,OAAO,OAAO;AAAA,IAClB;AAEA,SAAK,IAAI,4BAA4B;AAErC,WAAO;AAAA,EACX;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,MAAM,WAAW,QAAoD;AACjE,UAAM,YAAY,MAAM,KAAK,gBAAgB,MAAM;AAEnD,WAAO;AAAA,MACH;AAAA,MACA;AAAA,MACA,eAAe;AAAA,IACnB;AAAA,EACJ;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAWA,WAAoB;AAChB,QAAI,CAAC,KAAK,gBAAgB;AACtB,aAAO;AAAA,IACX;AACA,WAAO,KAAK,IAAI,IAAI,KAAK,eAAe;AAAA,EAC5C;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,aAAgC;AAC5B,QAAI,CAAC,KAAK,SAAS,GAAG;AAClB,aAAO;AAAA,IACX;AACA,WAAO,KAAK;AAAA,EAChB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,mBAA2B;AACvB,QAAI,CAAC,KAAK,gBAAgB;AACtB,aAAO;AAAA,IACX;AACA,UAAM,YAAY,KAAK,OAAO,KAAK,eAAe,SAAS,KAAK,IAAI,KAAK,GAAI;AAC7E,WAAO,KAAK,IAAI,GAAG,SAAS;AAAA,EAChC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASQ,kBAAwB;AAC5B,QAAI,CAAC,KAAK,kBAAkB,CAAC,KAAK,OAAO,aAAa;AAClD;AAAA,IACJ;AAEA,QAAI,KAAK,cAAc;AACnB,mBAAa,KAAK,YAAY;AAAA,IAClC;AAEA,UAAM,mBAAmB,KAAK,eAAe,SAAS,KAAK,IAAI,IAAK,KAAK,OAAO,gBAAgB;AAEhG,QAAI,oBAAoB,GAAG;AACvB,WAAK,IAAI,0CAA0C;AACnD,WAAK,eAAe,EAAE,MAAM,WAAS;AACjC,aAAK,IAAI,wBAAwB,KAAK;AACtC,aAAK,KAAK,EAAE,MAAM,iBAAiB,MAAM,CAAC;AAAA,MAC9C,CAAC;AACD;AAAA,IACJ;AAEA,SAAK,IAAI,yBAAyB,KAAK,MAAM,mBAAmB,GAAI,CAAC,GAAG;AAExE,SAAK,eAAe,WAAW,MAAM;AACjC,WAAK,eAAe,EAAE,MAAM,WAAS;AACjC,aAAK,IAAI,wBAAwB,KAAK;AACtC,aAAK,KAAK,EAAE,MAAM,iBAAiB,MAAM,CAAC;AAAA,MAC9C,CAAC;AAAA,IACL,GAAG,gBAAgB;AAAA,EACvB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,MAAM,iBAAsC;AACxC,SAAK,IAAI,uBAAuB;AAChC,UAAM,aAAa,MAAM,KAAK,cAAc;AAC5C,SAAK,KAAK,EAAE,MAAM,qBAAqB,SAAS,WAAW,CAAC;AAC5D,WAAO;AAAA,EACX;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASA,GAAG,UAAsC;AACrC,SAAK,eAAe,KAAK,QAAQ;AAAA,EACrC;AAAA;AAAA;AAAA;AAAA,EAKA,IAAI,UAAsC;AACtC,SAAK,iBAAiB,KAAK,eAAe,OAAO,QAAM,OAAO,QAAQ;AAAA,EAC1E;AAAA;AAAA;AAAA;AAAA,EAKQ,KAAK,OAA2B;AACpC,eAAW,YAAY,KAAK,gBAAgB;AACxC,UAAI;AACA,iBAAS,KAAK;AAAA,MAClB,SAAS,OAAO;AACZ,gBAAQ,MAAM,iCAAiC,KAAK;AAAA,MACxD;AAAA,IACJ;AAAA,EACJ;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASQ,OAAO,MAAmB;AAC9B,QAAI,KAAK,OAAO;AACZ,cAAQ,IAAI,oBAAoB,GAAG,IAAI;AAAA,IAC3C;AAAA,EACJ;AAAA;AAAA;AAAA;AAAA,EAKA,UAAgB;AACZ,QAAI,KAAK,cAAc;AACnB,mBAAa,KAAK,YAAY;AAC9B,WAAK,eAAe;AAAA,IACxB;AACA,SAAK,iBAAiB,CAAC;AACvB,SAAK,iBAAiB;AAAA,EAC1B;AACJ;;;AIpiBO,IAAM,sBAAN,MAA+C;AAAA,EAClD,YACY,WACA,QACV;AAFU;AACA;AAAA,EACT;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQH,MAAM,gBAAgB,QAA8C;AAEhE,UAAM,KAAK,UAAU,gBAAgB,QAAQ,KAAK,MAAM;AAAA,EAC5D;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,MAAM,cAAc,QAA4C;AAE5D,UAAM,KAAK,UAAU,cAAc,QAAQ,KAAK,MAAM;AAAA,EAC1D;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,aAAa,QAA6B;AACtC,SAAK,SAAS;AAAA,EAClB;AACJ;;;AC3CO,IAAM,eAAe;AAAA;AAAA,EAE1B,MAAM,EAAE,KAAK,KAAM,KAAK,KAAK;AAAA;AAAA,EAE7B,iBAAiB,EAAE,KAAK,MAAM,KAAK,KAAK;AAAA;AAAA,EAExC,KAAK,EAAE,KAAK,MAAM,KAAK,KAAK;AAAA;AAAA,EAE5B,eAAe,EAAE,KAAK,MAAM,KAAK,KAAK;AACxC;AAMO,IAAM,iBAAiB;AAAA;AAAA;AAAA,EAG5B,iBAAiB;AAAA;AAAA,EAEjB,cAAc;AAAA;AAAA,EAEd,uBAAuB;AAAA;AAAA,EAEvB,uBAAuB;AAAA;AAAA,EAEvB,iBAAiB;AAAA;AAAA,EAEjB,eAAe;AAAA;AAAA,EAEf,sBAAsB;AAAA;AAAA,EAEtB,yBAAyB;AAAA;AAAA,EAEzB,wBAAwB;AAAA;AAAA,EAExB,qBAAqB;AAAA;AAAA,EAErB,sBAAsB;AAAA;AAAA,EAEtB,oBAAoB;AAAA;AAAA,EAEpB,cAAc;AAAA;AAAA,EAEd,aAAa;AAAA;AAAA,EAEb,6BAA6B;AAAA;AAAA,EAE7B,uBAAuB;AAAA;AAAA;AAAA,EAIvB,wBAAwB;AAAA;AAAA,EAExB,eAAe;AAAA;AAAA,EAEf,eAAe;AAAA;AAAA,EAEf,gBAAgB;AAAA;AAAA,EAEhB,oBAAoB;AAAA;AAAA,EAEpB,qBAAqB;AAAA;AAAA,EAErB,+BAA+B;AAAA;AAAA,EAE/B,+BAA+B;AAAA;AAAA,EAE/B,yBAAyB;AAAA;AAAA,EAEzB,mBAAmB;AAAA;AAAA,EAEnB,wBAAwB;AAAA;AAAA;AAAA,EAIxB,uBAAuB;AAAA;AAAA,EAEvB,cAAc;AAAA;AAAA,EAEd,sBAAsB;AAAA;AAAA,EAEtB,qBAAqB;AAAA;AAAA;AAAA,EAIrB,8BAA8B;AAAA;AAAA,EAE9B,6BAA6B;AAAA;AAAA,EAE7B,8BAA8B;AAAA;AAAA,EAE9B,mBAAmB;AAAA;AAAA,EAEnB,0BAA0B;AAAA;AAAA,EAE1B,+BAA+B;AAAA;AAAA,EAE/B,2BAA2B;AAAA;AAAA,EAE3B,sBAAsB;AAAA;AAAA,EAEtB,+BAA+B;AAAA;AAAA,EAE/B,+BAA+B;AAAA;AAAA,EAE/B,+BAA+B;AAAA;AAAA,EAE/B,kCAAkC;AAAA;AAAA,EAElC,+BAA+B;AAAA;AAAA,EAE/B,gCAAgC;AAAA;AAAA,EAEhC,kCAAkC;AAAA;AAAA,EAElC,+BAA+B;AAAA;AAAA,EAE/B,wBAAwB;AAC1B;AAWO,IAAM,iBAAmD;AAAA;AAAA,EAE9D,CAAC,eAAe,eAAe,GAAG;AAAA,EAClC,CAAC,eAAe,YAAY,GAAG;AAAA,EAC/B,CAAC,eAAe,qBAAqB,GACnC;AAAA,EACF,CAAC,eAAe,qBAAqB,GAAG;AAAA,EACxC,CAAC,eAAe,eAAe,GAAG;AAAA,EAClC,CAAC,eAAe,aAAa,GAAG;AAAA,EAChC,CAAC,eAAe,oBAAoB,GAAG;AAAA,EACvC,CAAC,eAAe,uBAAuB,GAAG;AAAA,EAC1C,CAAC,eAAe,sBAAsB,GAAG;AAAA,EACzC,CAAC,eAAe,mBAAmB,GAAG;AAAA,EACtC,CAAC,eAAe,oBAAoB,GAAG;AAAA,EACvC,CAAC,eAAe,kBAAkB,GAAG;AAAA,EACrC,CAAC,eAAe,YAAY,GAAG;AAAA,EAC/B,CAAC,eAAe,WAAW,GAAG;AAAA,EAC9B,CAAC,eAAe,2BAA2B,GAAG;AAAA,EAC9C,CAAC,eAAe,qBAAqB,GAAG;AAAA;AAAA,EAGxC,CAAC,eAAe,sBAAsB,GAAG;AAAA,EACzC,CAAC,eAAe,aAAa,GAC3B;AAAA,EACF,CAAC,eAAe,aAAa,GAAG;AAAA,EAChC,CAAC,eAAe,cAAc,GAAG;AAAA,EACjC,CAAC,eAAe,kBAAkB,GAChC;AAAA,EACF,CAAC,eAAe,mBAAmB,GAAG;AAAA,EACtC,CAAC,eAAe,6BAA6B,GAC3C;AAAA,EACF,CAAC,eAAe,6BAA6B,GAC3C;AAAA,EACF,CAAC,eAAe,uBAAuB,GACrC;AAAA,EACF,CAAC,eAAe,iBAAiB,GAAG;AAAA,EACpC,CAAC,eAAe,sBAAsB,GAAG;AAAA;AAAA,EAGzC,CAAC,eAAe,qBAAqB,GAAG;AAAA,EACxC,CAAC,eAAe,YAAY,GAAG;AAAA,EAC/B,CAAC,eAAe,oBAAoB,GAAG;AAAA,EACvC,CAAC,eAAe,mBAAmB,GAAG;AAAA;AAAA,EAGtC,CAAC,eAAe,4BAA4B,GAAG;AAAA,EAC/C,CAAC,eAAe,2BAA2B,GAAG;AAAA,EAC9C,CAAC,eAAe,4BAA4B,GAAG;AAAA,EAC/C,CAAC,eAAe,iBAAiB,GAAG;AAAA,EACpC,CAAC,eAAe,wBAAwB,GAAG;AAAA,EAC3C,CAAC,eAAe,6BAA6B,GAAG;AAAA,EAChD,CAAC,eAAe,yBAAyB,GAAG;AAAA,EAC5C,CAAC,eAAe,oBAAoB,GAAG;AAAA,EACvC,CAAC,eAAe,6BAA6B,GAAG;AAAA,EAChD,CAAC,eAAe,6BAA6B,GAAG;AAAA,EAChD,CAAC,eAAe,6BAA6B,GAC3C;AAAA,EACF,CAAC,eAAe,gCAAgC,GAAG;AAAA,EACnD,CAAC,eAAe,6BAA6B,GAAG;AAAA,EAChD,CAAC,eAAe,8BAA8B,GAAG;AAAA,EACjD,CAAC,eAAe,gCAAgC,GAC9C;AAAA,EACF,CAAC,eAAe,6BAA6B,GAC3C;AAAA,EACF,CAAC,eAAe,sBAAsB,GAAG;AAC3C;AASO,SAAS,YAAY,MAAuB;AACjD,SAAO,QAAQ,aAAa,KAAK,OAAO,QAAQ,aAAa,KAAK;AACpE;AAKO,SAAS,sBAAsB,MAAuB;AAC3D,SACE,QAAQ,aAAa,gBAAgB,OACrC,QAAQ,aAAa,gBAAgB;AAEzC;AAKO,SAAS,WAAW,MAAuB;AAChD,SAAO,QAAQ,aAAa,IAAI,OAAO,QAAQ,aAAa,IAAI;AAClE;AAKO,SAAS,oBAAoB,MAAuB;AACzD,SACE,QAAQ,aAAa,cAAc,OACnC,QAAQ,aAAa,cAAc;AAEvC;AAKO,SAAS,aAAa,MAAuB;AAClD,SAAO,sBAAsB,IAAI,KAAK,oBAAoB,IAAI;AAChE;AAKO,SAAS,iBAAiB,MAAsB;AACrD,MAAI,YAAY,IAAI,EAAG,QAAO;AAC9B,MAAI,sBAAsB,IAAI,EAAG,QAAO;AACxC,MAAI,WAAW,IAAI,EAAG,QAAO;AAC7B,MAAI,oBAAoB,IAAI,EAAG,QAAO;AACtC,SAAO;AACT;AAKO,SAAS,gBAAgB,MAAsB;AACpD,SAAO,eAAe,IAAwB,KAAK,kBAAkB,IAAI;AAC3E;AAQO,SAAS,kBAAkB,OAA8C;AAC9E,MAAI,CAAC,SAAS,OAAO,UAAU,SAAU,QAAO;AAGhD,QAAM,cAAc;AAMpB,MAAI,OAAO,YAAY,SAAS,UAAU;AACxC,QAAI,YAAY,QAAQ,gBAAgB;AACtC,aAAO,YAAY;AAAA,IACrB;AAAA,EACF;AAGA,MAAI,YAAY,OAAO,WAAW,WAAW,QAAW;AACtD,UAAM,OAAO,YAAY,MAAM,UAAU;AACzC,QAAI,QAAQ,gBAAgB;AAC1B,aAAO;AAAA,IACT;AAAA,EACF;AAEA,SAAO;AACT;AAKO,SAAS,iBAAiB,MAAuB;AACtD,QAAM,iBAA2B;AAAA,IAC/B,eAAe;AAAA,IACf,eAAe;AAAA,IACf,eAAe;AAAA,IACf,eAAe;AAAA,IACf,eAAe;AAAA,IACf,eAAe;AAAA,EACjB;AACA,SAAO,eAAe,SAAS,IAAI;AACrC;AAKO,SAAS,mBAAmB,MAAsB;AACvD,UAAQ,MAAM;AAAA,IACZ,KAAK,eAAe;AAAA,IACpB,KAAK,eAAe;AAClB,aAAO;AAAA,IACT,KAAK,eAAe;AAAA,IACpB,KAAK,eAAe;AAClB,aAAO;AAAA,IACT,KAAK,eAAe;AAClB,aAAO;AAAA,IACT,KAAK,eAAe;AAClB,aAAO;AAAA,IACT,KAAK,eAAe;AAClB,aAAO;AAAA,IACT,KAAK,eAAe;AAClB,aAAO;AAAA,IACT,KAAK,eAAe;AAAA,IACpB,KAAK,eAAe;AAClB,aAAO;AAAA,IACT;AACE,aAAO;AAAA,EACX;AACF;","names":["ethers","ethers","ethers","ethers","ethers","ethers","ethers","DEFAULT_RPC_URLS","ethers","ethers","sleep","ethers","sleep","ethers","DEFAULT_CONFIG","ethers","ethers","hex","createHash","createHash","createHash","createHash","ethers","formatAmount","isNativeToken","ethers","ethers","VAULT_ABI","ethers","ethers","ethers","Buffer","ethers","Buffer","sleep","ethers","resolveNetwork","a","ethers","axios","Buffer","ethers","PublicKey","EthCallQueryRequest","EthCallQueryResponse","PerChainQueryRequest","QueryRequest","QueryResponse","hexToUint8Array","isValidHexString","resolveNetwork","concatBytes","signaturesToProofBytes","hexToUint8Array","decodeQueryBytes","isValidHexString","Buffer","sleep","withExponentialBackoff","PublicKey","ethers","PerChainQueryRequest","EthCallQueryRequest","chainsOut","QueryRequest","axios","QueryResponse","chainResp","EthCallQueryResponse","blockTime","age","balances","result","ethers","VAULT_FACTORY_ABI","TESTNET_CHAINS","MAINNET_CHAINS","chainConfig","ethers","result","ethers","PROXY_BYTECODE_PREFIX","PROXY_BYTECODE_SUFFIX","ERC20_ABI","HUB_ABI","ethers","address","ethers","ethers","ethers","ethers","ethers","ethers"]}
|
|
1
|
+
{"version":3,"sources":["../src/core/PasskeyManager.ts","../src/utils.ts","../src/constants.ts","../src/core/WalletManager.ts","../src/core/BalanceManager.ts","../src/constants/tokens.ts","../src/core/TransactionTracker.ts","../src/core/CrossChainManager.ts","../src/wormhole.ts","../src/core/RelayerClient.ts","../src/chains/solana/SolanaClient.ts","../src/payload.ts","../src/chains/aptos/AptosClient.ts","../src/chains/sui/SuiClient.ts","../src/chains/starknet/StarknetClient.ts","../src/core/ChainDetector.ts","../src/core/TransactionParser.ts","../src/core/TransactionSummary.types.ts","../src/core/SpendingLimitsManager.ts","../src/core/SpendingLimits.types.ts","../src/core/VeridexSDK.ts","../src/auth/prepareAuth.ts","../src/queries/hubState.ts","../src/queries/constants.ts","../src/queries/portfolio.ts","../src/core/GasSponsor.ts","../src/chains/evm/EVMClient.ts","../src/presets.ts","../src/factory.ts","../src/sessions/index.ts","../src/sessions/types.ts","../src/sessions/crypto.ts","../src/sessions/storage.ts","../src/chains/evm/EVMHubClientAdapter.ts","../src/constants/errors.ts"],"sourcesContent":["/**\n * Veridex Protocol SDK - Passkey Manager\n * \n * Chain-agnostic WebAuthn/Passkey credential management\n */\n\nimport {\n startRegistration,\n startAuthentication,\n browserSupportsWebAuthn,\n} from '@simplewebauthn/browser';\nimport type {\n PublicKeyCredentialCreationOptionsJSON,\n PublicKeyCredentialRequestOptionsJSON,\n RegistrationResponseJSON,\n AuthenticationResponseJSON,\n} from '@simplewebauthn/types';\nimport { ethers } from 'ethers';\nimport { base64URLEncode, base64URLDecode, parseDERSignature, computeKeyHash } from '../utils.js';\n\n// ============================================================================\n// Types\n// ============================================================================\n\nexport interface PasskeyCredential {\n credentialId: string;\n publicKeyX: bigint;\n publicKeyY: bigint;\n keyHash: string;\n}\n\nexport interface WebAuthnSignature {\n authenticatorData: string;\n clientDataJSON: string;\n challengeIndex: number;\n typeIndex: number;\n r: bigint;\n s: bigint;\n}\n\nexport interface PasskeyManagerConfig {\n rpName?: string;\n rpId?: string;\n timeout?: number;\n userVerification?: 'required' | 'preferred' | 'discouraged';\n authenticatorAttachment?: 'platform' | 'cross-platform';\n /** Relayer API URL for cross-device credential recovery */\n relayerUrl?: string;\n}\n\n// ============================================================================\n// PasskeyManager Class\n// ============================================================================\n\n/**\n * Manages WebAuthn passkey credentials for Veridex Protocol\n */\nexport class PasskeyManager {\n private config: Required<PasskeyManagerConfig>;\n private credential: PasskeyCredential | null = null;\n\n constructor(config: PasskeyManagerConfig = {}) {\n this.config = {\n rpName: config.rpName ?? 'Veridex Protocol',\n rpId: config.rpId ?? (typeof window !== 'undefined' ? window.location.hostname : 'localhost'),\n timeout: config.timeout ?? 60000,\n userVerification: config.userVerification ?? 'required',\n authenticatorAttachment: config.authenticatorAttachment ?? 'platform',\n relayerUrl: config.relayerUrl ?? '',\n };\n }\n\n static isSupported(): boolean {\n return browserSupportsWebAuthn();\n }\n\n static async isPlatformAuthenticatorAvailable(): Promise<boolean> {\n if (typeof window === 'undefined' || !window.PublicKeyCredential) {\n return false;\n }\n return await window.PublicKeyCredential.isUserVerifyingPlatformAuthenticatorAvailable();\n }\n\n async register(username: string, displayName: string): Promise<PasskeyCredential> {\n if (!PasskeyManager.isSupported()) {\n throw new Error('WebAuthn is not supported in this browser');\n }\n\n const challenge = ethers.randomBytes(32);\n const challengeBase64 = base64URLEncode(challenge);\n\n const options: PublicKeyCredentialCreationOptionsJSON = {\n challenge: challengeBase64,\n rp: {\n name: this.config.rpName,\n id: this.config.rpId,\n },\n user: {\n id: base64URLEncode(ethers.toUtf8Bytes(username)),\n name: username,\n displayName: displayName,\n },\n pubKeyCredParams: [\n { alg: -7, type: 'public-key' }, // ES256 (P-256) - WebAuthn default\n { alg: -257, type: 'public-key' }, // RS256 - Widely supported\n { alg: -8, type: 'public-key' }, // EdDSA - Modern, efficient\n { alg: -35, type: 'public-key' }, // ES384 (P-384)\n { alg: -36, type: 'public-key' }, // ES512 (P-521)\n { alg: -37, type: 'public-key' }, // PS256 - RSA PSS\n ],\n authenticatorSelection: {\n authenticatorAttachment: this.config.authenticatorAttachment,\n userVerification: this.config.userVerification,\n residentKey: 'required',\n requireResidentKey: true,\n },\n timeout: this.config.timeout,\n attestation: 'none',\n };\n\n const response = await startRegistration(options);\n const publicKey = this.extractPublicKeyFromAttestation(response);\n const keyHash = computeKeyHash(publicKey.x, publicKey.y);\n\n this.credential = {\n credentialId: response.id,\n publicKeyX: publicKey.x,\n publicKeyY: publicKey.y,\n keyHash,\n };\n\n return this.credential;\n }\n\n async sign(challenge: Uint8Array): Promise<WebAuthnSignature> {\n if (!this.credential) {\n throw new Error('No credential set. Call register() or setCredential() first.');\n }\n\n const challengeBase64 = base64URLEncode(challenge);\n\n const options: PublicKeyCredentialRequestOptionsJSON = {\n challenge: challengeBase64,\n rpId: this.config.rpId,\n allowCredentials: [\n {\n id: this.credential.credentialId,\n type: 'public-key',\n transports: ['internal'],\n },\n ],\n userVerification: this.config.userVerification,\n timeout: this.config.timeout,\n };\n\n const response = await startAuthentication(options);\n return this.parseAuthenticationResponse(response);\n }\n\n /**\n * Authenticate using a discoverable credential (passkey)\n * This allows sign-in without knowing the credential ID ahead of time.\n * The authenticator will show all available passkeys for this RP.\n * \n * @param challenge - Optional challenge bytes. If not provided, a random challenge is used.\n * @returns The credential that was used to authenticate, along with the signature\n */\n async authenticate(challenge?: Uint8Array): Promise<{\n credential: PasskeyCredential;\n signature: WebAuthnSignature;\n }> {\n if (!PasskeyManager.isSupported()) {\n throw new Error('WebAuthn is not supported in this browser');\n }\n\n const actualChallenge = challenge ?? ethers.randomBytes(32);\n const challengeBase64 = base64URLEncode(actualChallenge);\n\n // Use discoverable credentials - no allowCredentials means the authenticator\n // will show all available passkeys for this RP\n const options: PublicKeyCredentialRequestOptionsJSON = {\n challenge: challengeBase64,\n rpId: this.config.rpId,\n // No allowCredentials = discoverable credential flow\n userVerification: this.config.userVerification,\n timeout: this.config.timeout,\n };\n\n const response = await startAuthentication(options);\n \n // Extract the credential ID that was used\n const credentialId = response.id;\n \n // Parse the signature\n const signature = this.parseAuthenticationResponse(response);\n \n // For discoverable credentials, we need to recover the public key from the response\n // or require it to be stored. Since WebAuthn doesn't return the public key on auth,\n // we need to check if we have it stored, or use a different approach.\n \n // Try to load from localStorage first (might have been stored during registration)\n let storedCredential = this.loadCredentialById(credentialId);\n \n if (storedCredential) {\n this.credential = storedCredential;\n return { credential: storedCredential, signature };\n }\n \n // If not in localStorage, try to fetch from relayer (cross-device recovery)\n if (this.config.relayerUrl) {\n storedCredential = await this.loadCredentialFromRelayer(credentialId);\n if (storedCredential) {\n this.credential = storedCredential;\n // Cache locally for future use\n this.saveToLocalStorage();\n return { credential: storedCredential, signature };\n }\n }\n \n // If we don't have the public key stored anywhere, we need to throw an error\n // because we can't derive the keyHash without the public key\n throw new Error(\n 'Credential not found. ' +\n 'This passkey was registered on a different device or the data was cleared. ' +\n 'Please register a new passkey or ensure the relayer URL is configured.'\n );\n }\n\n /**\n * Load a credential by its ID from localStorage\n * Used for discoverable credential authentication\n */\n private loadCredentialById(credentialId: string, key = 'veridex_credential'): PasskeyCredential | null {\n if (typeof window === 'undefined') {\n return null;\n }\n\n const stored = localStorage.getItem(key);\n if (!stored) {\n return null;\n }\n\n try {\n const data = JSON.parse(stored);\n // Check if this is the right credential\n if (data.credentialId === credentialId) {\n return {\n credentialId: data.credentialId,\n publicKeyX: BigInt(data.publicKeyX),\n publicKeyY: BigInt(data.publicKeyY),\n keyHash: data.keyHash,\n };\n }\n return null;\n } catch (error) {\n console.error('Failed to load credential:', error);\n return null;\n }\n }\n\n /**\n * Check if there's a stored credential for this RP\n */\n hasStoredCredential(key = 'veridex_credential'): boolean {\n if (typeof window === 'undefined') {\n return false;\n }\n return localStorage.getItem(key) !== null;\n }\n\n getCredential(): PasskeyCredential | null {\n return this.credential;\n }\n\n setCredential(credential: PasskeyCredential): void {\n this.credential = credential;\n }\n\n createCredentialFromPublicKey(\n credentialId: string,\n publicKeyX: bigint,\n publicKeyY: bigint\n ): PasskeyCredential {\n const keyHash = computeKeyHash(publicKeyX, publicKeyY);\n this.credential = {\n credentialId,\n publicKeyX,\n publicKeyY,\n keyHash,\n };\n return this.credential;\n }\n\n clearCredential(): void {\n this.credential = null;\n }\n\n saveToLocalStorage(key = 'veridex_credential'): void {\n if (!this.credential) {\n throw new Error('No credential to save');\n }\n if (typeof window === 'undefined') {\n throw new Error('localStorage is not available');\n }\n\n const data = {\n credentialId: this.credential.credentialId,\n publicKeyX: this.credential.publicKeyX.toString(),\n publicKeyY: this.credential.publicKeyY.toString(),\n keyHash: this.credential.keyHash,\n };\n\n localStorage.setItem(key, JSON.stringify(data));\n }\n\n loadFromLocalStorage(key = 'veridex_credential'): PasskeyCredential | null {\n if (typeof window === 'undefined') {\n return null;\n }\n\n const stored = localStorage.getItem(key);\n if (!stored) {\n return null;\n }\n\n try {\n const data = JSON.parse(stored);\n this.credential = {\n credentialId: data.credentialId,\n publicKeyX: BigInt(data.publicKeyX),\n publicKeyY: BigInt(data.publicKeyY),\n keyHash: data.keyHash,\n };\n return this.credential;\n } catch (error) {\n console.error('Failed to load credential from localStorage:', error);\n return null;\n }\n }\n\n removeFromLocalStorage(key = 'veridex_credential'): void {\n if (typeof window !== 'undefined') {\n localStorage.removeItem(key);\n }\n }\n\n // =========================================================================\n // Relayer-based Credential Storage (Cross-Device Recovery)\n // =========================================================================\n\n /**\n * Save the current credential to the relayer for cross-device recovery.\n * This should be called after registration.\n */\n async saveCredentialToRelayer(): Promise<boolean> {\n if (!this.credential) {\n throw new Error('No credential to save');\n }\n if (!this.config.relayerUrl) {\n console.warn('Relayer URL not configured; skipping remote credential storage');\n return false;\n }\n\n try {\n const response = await fetch(`${this.config.relayerUrl}/api/v1/credential`, {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({\n keyHash: this.credential.keyHash,\n credentialId: this.credential.credentialId,\n publicKeyX: this.credential.publicKeyX.toString(),\n publicKeyY: this.credential.publicKeyY.toString(),\n }),\n });\n\n if (!response.ok) {\n const errorData = await response.json().catch(() => ({}));\n console.error('Failed to save credential to relayer:', errorData);\n return false;\n }\n\n console.log('Credential saved to relayer for cross-device recovery');\n return true;\n } catch (error) {\n console.error('Failed to save credential to relayer:', error);\n return false;\n }\n }\n\n /**\n * Load a credential from the relayer by credential ID.\n * Used during discoverable credential authentication when localStorage is empty.\n */\n async loadCredentialFromRelayer(credentialId: string): Promise<PasskeyCredential | null> {\n if (!this.config.relayerUrl) {\n return null;\n }\n\n try {\n const response = await fetch(\n `${this.config.relayerUrl}/api/v1/credential/by-id/${encodeURIComponent(credentialId)}`\n );\n\n if (!response.ok) {\n return null;\n }\n\n const data = await response.json();\n if (!data.exists) {\n return null;\n }\n\n return {\n credentialId: data.credentialId,\n publicKeyX: BigInt(data.publicKeyX),\n publicKeyY: BigInt(data.publicKeyY),\n keyHash: data.keyHash,\n };\n } catch (error) {\n console.error('Failed to load credential from relayer:', error);\n return null;\n }\n }\n\n /**\n * Load a credential from the relayer by keyHash.\n * Useful when you know the user's keyHash but not their credential ID.\n */\n async loadCredentialFromRelayerByKeyHash(keyHash: string): Promise<PasskeyCredential | null> {\n if (!this.config.relayerUrl) {\n return null;\n }\n\n try {\n const response = await fetch(\n `${this.config.relayerUrl}/api/v1/credential/${encodeURIComponent(keyHash)}`\n );\n\n if (!response.ok) {\n return null;\n }\n\n const data = await response.json();\n if (!data.exists) {\n return null;\n }\n\n return {\n credentialId: data.credentialId,\n publicKeyX: BigInt(data.publicKeyX),\n publicKeyY: BigInt(data.publicKeyY),\n keyHash: data.keyHash,\n };\n } catch (error) {\n console.error('Failed to load credential from relayer:', error);\n return null;\n }\n }\n\n private extractPublicKeyFromAttestation(\n response: RegistrationResponseJSON\n ): { x: bigint; y: bigint } {\n const attestationObject = base64URLDecode(response.response.attestationObject);\n\n // Parse CBOR attestation object\n // The attestation object is a CBOR map with keys: fmt, authData, attStmt\n // We need to extract the authData which contains the credential public key\n\n let offset = 0;\n\n // Skip the CBOR map header (usually 0xa3 for 3-item map or 0xa2 for 2-item map)\n if (attestationObject[offset] >= 0xa0 && attestationObject[offset] <= 0xbf) {\n offset++;\n }\n\n // Find the authData field in the CBOR map\n // Look for the text string \"authData\" (0x68 followed by \"authData\")\n while (offset < attestationObject.length - 37) {\n if (attestationObject[offset] === 0x68 && // text string, 8 bytes\n attestationObject[offset + 1] === 0x61 && // 'a'\n attestationObject[offset + 2] === 0x75 && // 'u'\n attestationObject[offset + 3] === 0x74 && // 't'\n attestationObject[offset + 4] === 0x68 && // 'h'\n attestationObject[offset + 5] === 0x44 && // 'D'\n attestationObject[offset + 6] === 0x61 && // 'a'\n attestationObject[offset + 7] === 0x74 && // 't'\n attestationObject[offset + 8] === 0x61) { // 'a'\n offset += 9;\n break;\n }\n offset++;\n }\n\n // Skip the byte string header for authData\n if (attestationObject[offset] === 0x58 || attestationObject[offset] === 0x59) {\n // 0x58 = 1-byte length, 0x59 = 2-byte length\n const lengthBytes = attestationObject[offset] === 0x58 ? 1 : 2;\n offset += 1 + lengthBytes;\n }\n\n // Now we're at the start of authData\n // authData structure:\n // - rpIdHash: 32 bytes\n // - flags: 1 byte\n // - signCount: 4 bytes\n // - attestedCredentialData (if AT flag is set):\n // - aaguid: 16 bytes\n // - credentialIdLength: 2 bytes\n // - credentialId: credentialIdLength bytes\n // - credentialPublicKey: CBOR-encoded COSE_Key\n\n offset += 32; // Skip rpIdHash\n offset += 1; // Skip flags\n offset += 4; // Skip signCount\n offset += 16; // Skip aaguid\n\n // Read credential ID length\n const credIdLen = (attestationObject[offset] << 8) | attestationObject[offset + 1];\n offset += 2;\n offset += credIdLen; // Skip credential ID\n\n // Now we're at the COSE public key\n const coseKey = attestationObject.slice(offset);\n\n console.log('COSE key length:', coseKey.length);\n console.log('COSE key hex:', this.bytesToHex(coseKey.slice(0, Math.min(100, coseKey.length))));\n\n const { x, y } = this.parseCOSEKey(coseKey);\n return { x, y };\n }\n\n private parseCOSEKey(coseKey: Uint8Array): { x: bigint; y: bigint } {\n console.log('COSE key length:', coseKey.length);\n console.log('COSE key hex:', this.bytesToHex(coseKey));\n\n // Try multiple parsing strategies\n const parsed = this.tryParseCOSEKeyStrategies(coseKey);\n if (parsed) {\n return parsed;\n }\n\n // If all strategies fail, try using a CBOR parser approach\n return this.parseCOSEKeyWithCBORStructure(coseKey);\n }\n\n private tryParseCOSEKeyStrategies(coseKey: Uint8Array): { x: bigint; y: bigint } | null {\n // Strategy 1: Look for the specific pattern of EC2 keys\n const keyBytes = new Uint8Array(coseKey);\n\n // Common pattern for EC2 keys with P-256 curve\n for (let i = 0; i < keyBytes.length - 40; i++) {\n // Check for potential x coordinate (32 bytes preceded by key marker)\n if (keyBytes[i] === 0x58 && keyBytes[i + 1] === 0x20) {\n const potentialX = keyBytes.slice(i + 2, i + 34);\n\n // Look for y coordinate after x\n for (let j = i + 34; j < keyBytes.length - 34; j++) {\n if (keyBytes[j] === 0x58 && keyBytes[j + 1] === 0x20) {\n const potentialY = keyBytes.slice(j + 2, j + 34);\n\n // Verify these look like valid coordinates\n if (this.isValidCoordinate(potentialX) && this.isValidCoordinate(potentialY)) {\n console.log('Found coordinates via pattern matching');\n return {\n x: this.bytesToBigInt(potentialX),\n y: this.bytesToBigInt(potentialY)\n };\n }\n }\n }\n }\n }\n\n // Strategy 2: Look for ASN.1 structure\n return this.tryParseASN1Structure(keyBytes);\n }\n\n private parseCOSEKeyWithCBORStructure(coseKey: Uint8Array): { x: bigint; y: bigint } {\n // More flexible parsing that handles different CBOR structures\n const bytes = new Uint8Array(coseKey);\n let xBytes: Uint8Array | null = null;\n let yBytes: Uint8Array | null = null;\n\n // Look for x and y coordinates by scanning for byte strings\n let i = 0;\n while (i < bytes.length) {\n // Check for byte string markers\n if (bytes[i] === 0x58) { // Byte string with length byte\n const length = bytes[i + 1];\n if (length === 0x20) { // 32 bytes - likely a coordinate\n const start = i + 2;\n const end = start + 32;\n\n if (end <= bytes.length) {\n const coordinate = bytes.slice(start, end);\n\n // Assign to x or y based on position or previous assignments\n if (!xBytes) {\n xBytes = coordinate;\n console.log('Found x at offset', i);\n } else if (!yBytes) {\n yBytes = coordinate;\n console.log('Found y at offset', i);\n break; // Found both, exit loop\n }\n }\n i = end;\n } else {\n i += length + 2;\n }\n } else if (bytes[i] === 0x42) { // Byte string with 2-byte length\n if (i + 3 < bytes.length) {\n const length = (bytes[i + 1] << 8) | bytes[i + 2];\n if (length === 32) {\n const start = i + 3;\n const end = start + 32;\n\n if (end <= bytes.length) {\n const coordinate = bytes.slice(start, end);\n\n if (!xBytes) {\n xBytes = coordinate;\n console.log('Found x at offset', i);\n } else if (!yBytes) {\n yBytes = coordinate;\n console.log('Found y at offset', i);\n break;\n }\n }\n i = end;\n } else {\n i += length + 3;\n }\n } else {\n i++;\n }\n } else if (bytes[i] === 0x40) { // Byte string with indefinite length\n // Skip indefinite length marker\n i++;\n // Look for 0x04 marker (uncompressed point) or direct coordinates\n while (i < bytes.length && bytes[i] !== 0xFF) { // 0xFF is break marker\n if (bytes[i] === 0x04 && i + 65 <= bytes.length) {\n // Uncompressed EC point format\n const x = bytes.slice(i + 1, i + 33);\n const y = bytes.slice(i + 33, i + 65);\n\n if (this.isValidCoordinate(x) && this.isValidCoordinate(y)) {\n xBytes = x;\n yBytes = y;\n console.log('Found coordinates in uncompressed point format');\n break;\n }\n }\n i++;\n }\n if (xBytes && yBytes) break;\n } else {\n i++;\n }\n }\n\n if (!xBytes || !yBytes) {\n // Fallback: Try to find any 32-byte sequences\n const potentialCoords = this.find32ByteSequences(bytes);\n if (potentialCoords.length >= 2) {\n xBytes = potentialCoords[0];\n yBytes = potentialCoords[1];\n console.log('Fallback: Using first two 32-byte sequences as coordinates');\n }\n }\n\n if (!xBytes || !yBytes) {\n console.error('Failed to find coordinates in COSE key. Full dump:');\n console.error('Hex:', this.bytesToHex(bytes));\n console.error('Structure analysis:');\n this.analyzeCOSEStructure(bytes);\n throw new Error('Failed to extract public key coordinates from COSE key. Check console for details.');\n }\n\n return {\n x: this.bytesToBigInt(xBytes),\n y: this.bytesToBigInt(yBytes)\n };\n }\n\n private tryParseASN1Structure(bytes: Uint8Array): { x: bigint; y: bigint } | null {\n // ASN.1 SEQUENCE for EC public key\n if (bytes[0] === 0x30) { // SEQUENCE tag\n let offset = 2; // Skip tag and length\n\n // Look for BIT STRING (0x03)\n if (bytes[offset] === 0x03) {\n offset += 2; // Skip BIT STRING tag and unused bits\n\n // Look for another SEQUENCE\n if (bytes[offset] === 0x30) {\n offset += 2;\n\n // Should now have OID for P-256: 1.2.840.10045.3.1.7\n // Skip OID (usually 10 bytes: 06 08 2A 86 48 CE 3D 03 01 07)\n offset += 12;\n\n // BIT STRING containing the raw public key\n if (bytes[offset] === 0x03 && bytes[offset + 2] === 0x04) {\n offset += 3; // Skip to uncompressed point (0x04)\n\n const x = bytes.slice(offset, offset + 32);\n const y = bytes.slice(offset + 32, offset + 64);\n\n if (x.length === 32 && y.length === 32) {\n console.log('Found coordinates via ASN.1 parsing');\n return {\n x: this.bytesToBigInt(x),\n y: this.bytesToBigInt(y)\n };\n }\n }\n }\n }\n }\n return null;\n }\n\n private find32ByteSequences(bytes: Uint8Array): Uint8Array[] {\n const sequences: Uint8Array[] = [];\n\n for (let i = 0; i <= bytes.length - 32; i++) {\n // Check if this 32-byte sequence looks like a valid coordinate\n const sequence = bytes.slice(i, i + 32);\n if (this.isValidCoordinate(sequence)) {\n sequences.push(sequence);\n }\n }\n\n return sequences;\n }\n\n private isValidCoordinate(bytes: Uint8Array): boolean {\n if (bytes.length !== 32) return false;\n\n // Basic validation: not all zeros, not all FF\n let allZeros = true;\n let allOnes = true;\n\n for (const byte of bytes) {\n if (byte !== 0) allZeros = false;\n if (byte !== 0xFF) allOnes = false;\n }\n\n return !allZeros && !allOnes;\n }\n\n private bytesToBigInt(bytes: Uint8Array): bigint {\n return BigInt('0x' + this.bytesToHex(bytes));\n }\n\n private bytesToHex(bytes: Uint8Array): string {\n return Array.from(bytes)\n .map(b => b.toString(16).padStart(2, '0'))\n .join('');\n }\n\n private analyzeCOSEStructure(bytes: Uint8Array): void {\n console.log('COSE Structure Analysis:');\n console.log('First 20 bytes:', this.bytesToHex(bytes.slice(0, 20)));\n\n // Check for known COSE key structure markers\n const firstByte = bytes[0];\n console.log('First byte (0x' + firstByte.toString(16) + '):');\n\n if (firstByte >= 0xa0 && firstByte <= 0xbf) {\n console.log('- Definite length map with', (firstByte & 0x1f), 'pairs');\n } else if (firstByte === 0xbf) {\n console.log('- Indefinite length map');\n } else if (firstByte === 0x04) {\n console.log('- Byte string');\n } else if (firstByte === 0x02) {\n console.log('- Negative integer');\n }\n\n // Count occurrences of 32-byte sequences\n let count32 = 0;\n for (let i = 0; i <= bytes.length - 32; i++) {\n const chunk = bytes.slice(i, i + 32);\n if (this.isValidCoordinate(chunk)) {\n console.log(`Found valid 32-byte sequence at offset ${i}:`,\n this.bytesToHex(chunk.slice(0, 8)) + '...');\n count32++;\n }\n }\n console.log(`Total valid 32-byte sequences: ${count32}`);\n\n // Look for specific markers\n console.log('Looking for known markers:');\n const markers = [\n { byte: 0x04, name: 'Uncompressed point marker' },\n { byte: 0x03, name: 'BIT STRING' },\n { byte: 0x30, name: 'SEQUENCE' },\n { byte: 0x02, name: 'INTEGER' },\n { byte: 0x06, name: 'OBJECT IDENTIFIER' },\n { byte: 0x58, name: 'Byte string with length byte' },\n { byte: 0x42, name: 'Byte string with 2-byte length' },\n { byte: 0x40, name: 'Byte string indefinite length' },\n { byte: 0xA0, name: 'Map start' },\n { byte: 0xBF, name: 'Indefinite map start' },\n ];\n\n for (const marker of markers) {\n const indices = [];\n for (let i = 0; i < bytes.length; i++) {\n if (bytes[i] === marker.byte) {\n indices.push(i);\n }\n }\n if (indices.length > 0) {\n console.log(` ${marker.name} (0x${marker.byte.toString(16)}) at positions:`, indices.slice(0, 5).join(', '));\n }\n }\n }\n\n private parseAuthenticationResponse(response: AuthenticationResponseJSON): WebAuthnSignature {\n const authenticatorData = base64URLDecode(response.response.authenticatorData);\n const clientDataJSON = response.response.clientDataJSON;\n const signature = base64URLDecode(response.response.signature);\n\n const { r, s } = parseDERSignature(signature);\n\n // Normalize signature to low-S form.\n // The on-chain WebAuthn verifier rejects signatures with s > n/2.\n // WebAuthn authenticators are not guaranteed to produce low-S signatures,\n // so without this normalization, valid signatures can intermittently fail.\n const P256_N = BigInt('0xFFFFFFFF00000000FFFFFFFFFFFFFFFFBCE6FAADA7179E84F3B9CAC2FC632551');\n const P256_N_DIV_2 = BigInt(\n '0x7FFFFFFF800000007FFFFFFFFFFFFFFFDE737D56D38BCF4279DCE5617E3192A8'\n );\n\n const clientDataStr = new TextDecoder().decode(base64URLDecode(clientDataJSON));\n const challengeIndex = clientDataStr.indexOf('\"challenge\"');\n const typeIndex = clientDataStr.indexOf('\"type\"');\n\n if (challengeIndex === -1 || typeIndex === -1) {\n throw new Error('Invalid clientDataJSON format');\n }\n\n return {\n authenticatorData: ethers.hexlify(authenticatorData),\n clientDataJSON: clientDataStr,\n challengeIndex,\n typeIndex,\n r: this.bytesToBigInt(r),\n s: (() => {\n const sBig = this.bytesToBigInt(s);\n return sBig > P256_N_DIV_2 ? P256_N - sBig : sBig;\n })(),\n };\n }\n}","/**\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","/**\n * Veridex Protocol SDK - Wallet Manager\n * \n * Manages deterministic wallet addresses across multiple chains.\n * Vault addresses are computed using CREATE2 on EVM chains and chain-specific\n * derivation on non-EVM chains, all based on the user's passkey public key.\n */\n\nimport { ethers } from 'ethers';\nimport type { \n PasskeyCredential,\n UnifiedIdentity,\n ChainAddress,\n WalletManagerConfig,\n} from './types.js';\nimport { computeKeyHash } from '../utils.js';\n\n// ============================================================================\n// Constants\n// ============================================================================\n\n/**\n * EIP-1167 minimal proxy bytecode prefix (before implementation address)\n * 3d602d80600a3d3981f3363d3d373d3d3d363d73\n */\nconst PROXY_BYTECODE_PREFIX = '0x3d602d80600a3d3981f3363d3d373d3d3d363d73';\n\n/**\n * EIP-1167 minimal proxy bytecode suffix (after implementation address)\n * 5af43d82803e903d91602b57fd5bf3\n */\nconst PROXY_BYTECODE_SUFFIX = '5af43d82803e903d91602b57fd5bf3';\n\n// ============================================================================\n// WalletManager Class\n// ============================================================================\n\n/**\n * Manages wallet address derivation and storage for Veridex Protocol\n * \n * @example\n * ```typescript\n * const manager = new WalletManager();\n * \n * // Compute vault address for a credential\n * const address = await manager.computeVaultAddress(\n * credential.keyHash,\n * factoryAddress,\n * implementationAddress\n * );\n * \n * // Get unified identity with addresses on all chains\n * const identity = await manager.getUnifiedIdentity(credential, chainConfigs);\n * ```\n */\nexport class WalletManager {\n private config: WalletManagerConfig;\n private addressCache: Map<string, ChainAddress[]> = new Map();\n\n constructor(config: WalletManagerConfig = {}) {\n this.config = {\n cacheAddresses: config.cacheAddresses ?? true,\n persistToStorage: config.persistToStorage ?? false,\n storageKey: config.storageKey ?? 'veridex_wallet_addresses',\n };\n\n // Load cached addresses from storage if enabled\n if (this.config.persistToStorage && typeof window !== 'undefined') {\n this.loadFromStorage();\n }\n }\n\n // ========================================================================\n // Address Computation\n // ========================================================================\n\n /**\n * Compute the deterministic vault address for an EVM chain\n * \n * Uses CREATE2 with EIP-1167 minimal proxy pattern:\n * - Salt = keccak256(factoryAddress, ownerKeyHash)\n * - InitCode = EIP-1167 proxy bytecode with implementation address\n * \n * @param keyHash - The owner's key hash (keccak256 of public key coordinates)\n * @param factoryAddress - The vault factory contract address\n * @param implementationAddress - The vault implementation contract address\n * @returns The deterministic vault address\n */\n computeVaultAddress(\n keyHash: string,\n factoryAddress: string,\n implementationAddress: string\n ): string {\n // Compute salt: keccak256(abi.encodePacked(factory, keyHash))\n const salt = ethers.keccak256(\n ethers.solidityPacked(\n ['address', 'bytes32'],\n [factoryAddress, keyHash]\n )\n );\n\n // Build EIP-1167 initcode\n const initCode = this.buildProxyInitCode(implementationAddress);\n const initCodeHash = ethers.keccak256(initCode);\n\n // CREATE2 address computation:\n // address = keccak256(0xff ++ factory ++ salt ++ initCodeHash)[12:]\n const create2Data = ethers.solidityPacked(\n ['bytes1', 'address', 'bytes32', 'bytes32'],\n ['0xff', factoryAddress, salt, initCodeHash]\n );\n\n const hash = ethers.keccak256(create2Data);\n // Take last 20 bytes as address\n return ethers.getAddress('0x' + hash.slice(26));\n }\n\n /**\n * Compute vault address from public key coordinates\n * \n * @param publicKeyX - P-256 public key X coordinate\n * @param publicKeyY - P-256 public key Y coordinate\n * @param factoryAddress - The vault factory contract address\n * @param implementationAddress - The vault implementation contract address\n * @returns The deterministic vault address\n */\n computeVaultAddressFromPublicKey(\n publicKeyX: bigint,\n publicKeyY: bigint,\n factoryAddress: string,\n implementationAddress: string\n ): string {\n const keyHash = computeKeyHash(publicKeyX, publicKeyY);\n return this.computeVaultAddress(keyHash, factoryAddress, implementationAddress);\n }\n\n /**\n * Build EIP-1167 minimal proxy initcode\n */\n private buildProxyInitCode(implementationAddress: string): string {\n // Remove 0x prefix if present and lowercase\n const impl = implementationAddress.toLowerCase().replace('0x', '');\n \n // EIP-1167 bytecode format\n return PROXY_BYTECODE_PREFIX + impl + PROXY_BYTECODE_SUFFIX;\n }\n\n // ========================================================================\n // Unified Identity\n // ========================================================================\n\n /**\n * Get unified identity with addresses across all configured chains\n * \n * @param credential - The passkey credential\n * @param chainConfigs - Map of chain configurations with factory/implementation addresses\n * @returns Unified identity with addresses on each chain\n */\n async getUnifiedIdentity(\n credential: PasskeyCredential,\n chainConfigs: Map<number, ChainAddressConfig>\n ): Promise<UnifiedIdentity> {\n const addresses: ChainAddress[] = [];\n\n for (const [wormholeChainId, config] of chainConfigs) {\n const address = await this.deriveAddressForChain(\n credential,\n wormholeChainId,\n config\n );\n \n if (address) {\n addresses.push(address);\n }\n }\n\n const identity: UnifiedIdentity = {\n keyHash: credential.keyHash,\n publicKeyX: credential.publicKeyX,\n publicKeyY: credential.publicKeyY,\n credentialId: credential.credentialId,\n addresses,\n createdAt: Date.now(),\n updatedAt: Date.now(),\n };\n\n // Cache the identity\n if (this.config.cacheAddresses) {\n this.addressCache.set(credential.keyHash, addresses);\n }\n\n // Persist to storage if enabled\n if (this.config.persistToStorage) {\n this.saveToStorage(identity);\n }\n\n return identity;\n }\n\n /**\n * Derive address for a specific chain\n */\n private async deriveAddressForChain(\n credential: PasskeyCredential,\n wormholeChainId: number,\n config: ChainAddressConfig\n ): Promise<ChainAddress | null> {\n if (config.isEvm) {\n // EVM chains use CREATE2\n if (!config.factoryAddress || !config.implementationAddress) {\n return null;\n }\n\n const address = this.computeVaultAddress(\n credential.keyHash,\n config.factoryAddress,\n config.implementationAddress\n );\n\n return {\n wormholeChainId,\n chainName: config.chainName,\n address,\n isEvm: true,\n deployed: false, // Will be checked separately\n };\n } else {\n // Non-EVM chains have chain-specific address derivation\n return this.deriveNonEvmAddress(credential, wormholeChainId, config);\n }\n }\n\n /**\n * Derive address for non-EVM chains\n * \n * Each chain has its own address format:\n * - Solana: Base58 encoded public key hash\n * - Aptos: 32-byte hex address\n * - Sui: 32-byte hex address with 0x prefix\n */\n private deriveNonEvmAddress(\n credential: PasskeyCredential,\n wormholeChainId: number,\n _config: ChainAddressConfig\n ): ChainAddress | null {\n switch (wormholeChainId) {\n case 1: // Solana\n // Solana uses the key hash directly as a seed for PDA derivation\n // The actual address depends on the program ID\n return {\n wormholeChainId: 1,\n chainName: 'Solana',\n address: credential.keyHash, // PDA will be derived from this\n isEvm: false,\n derivationType: 'pda',\n deployed: false,\n };\n\n case 22: // Aptos\n // Aptos uses the key hash as the resource account address\n return {\n wormholeChainId: 22,\n chainName: 'Aptos',\n address: credential.keyHash,\n isEvm: false,\n derivationType: 'resource_account',\n deployed: false,\n };\n\n case 21: // Sui\n // Sui uses the key hash with 0x prefix\n return {\n wormholeChainId: 21,\n chainName: 'Sui',\n address: credential.keyHash,\n isEvm: false,\n derivationType: 'object',\n deployed: false,\n };\n\n default:\n // Unknown chain\n return null;\n }\n }\n\n // ========================================================================\n // Address Lookup\n // ========================================================================\n\n /**\n * Get cached address for a chain\n */\n getAddressForChain(keyHash: string, wormholeChainId: number): ChainAddress | undefined {\n const addresses = this.addressCache.get(keyHash);\n return addresses?.find(a => a.wormholeChainId === wormholeChainId);\n }\n\n /**\n * Get all cached addresses for a key hash\n */\n getAddresses(keyHash: string): ChainAddress[] {\n return this.addressCache.get(keyHash) ?? [];\n }\n\n /**\n * Update deployment status for an address\n */\n updateDeploymentStatus(\n keyHash: string,\n wormholeChainId: number,\n deployed: boolean,\n deploymentTxHash?: string\n ): void {\n const addresses = this.addressCache.get(keyHash);\n if (!addresses) return;\n\n const address = addresses.find(a => a.wormholeChainId === wormholeChainId);\n if (address) {\n address.deployed = deployed;\n address.deploymentTxHash = deploymentTxHash;\n }\n\n // Persist update if enabled\n if (this.config.persistToStorage) {\n this.saveAddressesToStorage(keyHash, addresses);\n }\n }\n\n // ========================================================================\n // Storage\n // ========================================================================\n\n /**\n * Load addresses from localStorage\n */\n private loadFromStorage(): void {\n if (typeof window === 'undefined') return;\n\n try {\n const stored = localStorage.getItem(this.config.storageKey!);\n if (!stored) return;\n\n const data = JSON.parse(stored) as StoredWalletData;\n \n for (const [keyHash, addresses] of Object.entries(data.addresses)) {\n this.addressCache.set(keyHash, addresses);\n }\n } catch (error) {\n console.warn('Failed to load wallet addresses from storage:', error);\n }\n }\n\n /**\n * Save identity to localStorage\n */\n private saveToStorage(identity: UnifiedIdentity): void {\n if (typeof window === 'undefined') return;\n\n try {\n const stored = localStorage.getItem(this.config.storageKey!) ?? '{}';\n const data = JSON.parse(stored) as StoredWalletData;\n\n if (!data.addresses) {\n data.addresses = {};\n }\n\n // Store identity with serialized bigints\n data.addresses[identity.keyHash] = identity.addresses;\n data.identities = data.identities ?? {};\n data.identities[identity.keyHash] = {\n keyHash: identity.keyHash,\n publicKeyX: identity.publicKeyX.toString(),\n publicKeyY: identity.publicKeyY.toString(),\n credentialId: identity.credentialId,\n createdAt: identity.createdAt,\n updatedAt: identity.updatedAt,\n };\n\n localStorage.setItem(this.config.storageKey!, JSON.stringify(data));\n } catch (error) {\n console.warn('Failed to save wallet addresses to storage:', error);\n }\n }\n\n /**\n * Save addresses to localStorage\n */\n private saveAddressesToStorage(keyHash: string, addresses: ChainAddress[]): void {\n if (typeof window === 'undefined') return;\n\n try {\n const stored = localStorage.getItem(this.config.storageKey!) ?? '{}';\n const data = JSON.parse(stored) as StoredWalletData;\n\n if (!data.addresses) {\n data.addresses = {};\n }\n\n data.addresses[keyHash] = addresses;\n localStorage.setItem(this.config.storageKey!, JSON.stringify(data));\n } catch (error) {\n console.warn('Failed to save wallet addresses to storage:', error);\n }\n }\n\n /**\n * Clear all cached data\n */\n clearCache(): void {\n this.addressCache.clear();\n \n if (this.config.persistToStorage && typeof window !== 'undefined') {\n localStorage.removeItem(this.config.storageKey!);\n }\n }\n\n /**\n * Load identity from storage\n */\n loadIdentityFromStorage(keyHash: string): UnifiedIdentity | null {\n if (typeof window === 'undefined') return null;\n\n try {\n const stored = localStorage.getItem(this.config.storageKey!);\n if (!stored) return null;\n\n const data = JSON.parse(stored) as StoredWalletData;\n const storedIdentity = data.identities?.[keyHash];\n const addresses = data.addresses?.[keyHash];\n\n if (!storedIdentity || !addresses) return null;\n\n return {\n keyHash: storedIdentity.keyHash,\n publicKeyX: BigInt(storedIdentity.publicKeyX),\n publicKeyY: BigInt(storedIdentity.publicKeyY),\n credentialId: storedIdentity.credentialId,\n addresses,\n createdAt: storedIdentity.createdAt,\n updatedAt: storedIdentity.updatedAt,\n };\n } catch (error) {\n console.warn('Failed to load identity from storage:', error);\n return null;\n }\n }\n}\n\n// ============================================================================\n// Helper Types (Internal)\n// ============================================================================\n\ninterface ChainAddressConfig {\n chainName: string;\n isEvm: boolean;\n factoryAddress?: string;\n implementationAddress?: string;\n}\n\ninterface StoredWalletData {\n addresses: Record<string, ChainAddress[]>;\n identities?: Record<string, {\n keyHash: string;\n publicKeyX: string;\n publicKeyY: string;\n credentialId: string;\n createdAt: number;\n updatedAt: number;\n }>;\n}\n\n// Export the helper type for external use\nexport type { ChainAddressConfig };\n","/**\n * Veridex Protocol SDK - Balance Manager\n * \n * Manages balance fetching for native tokens and ERC20s across chains\n */\n\nimport { ethers } from 'ethers';\nimport { \n TokenInfo, \n getTokenList, \n getAllTokens, \n isNativeToken, \n NATIVE_TOKEN_ADDRESS \n} from '../constants/tokens.js';\n\n// ============================================================================\n// Types\n// ============================================================================\n\nexport interface TokenBalance {\n /** Token information */\n token: TokenInfo;\n /** Raw balance in smallest units */\n balance: bigint;\n /** Formatted balance with decimals */\n formatted: string;\n /** USD value (if price available) */\n usdValue?: number;\n}\n\nexport interface PortfolioBalance {\n /** Wormhole chain ID */\n wormholeChainId: number;\n /** Chain name */\n chainName: string;\n /** Address being queried */\n address: string;\n /** Individual token balances */\n tokens: TokenBalance[];\n /** Total USD value (if prices available) */\n totalUsdValue?: number;\n /** Timestamp of last update */\n lastUpdated: number;\n}\n\nexport interface BalanceManagerConfig {\n /** Whether to cache balances */\n cacheBalances?: boolean;\n /** Cache TTL in milliseconds */\n cacheTtl?: number;\n /** Custom RPC URLs by chain ID */\n customRpcUrls?: Record<number, string>;\n}\n\n// ============================================================================\n// Constants\n// ============================================================================\n\n/**\n * Default RPC URLs for testnet chains\n */\nconst DEFAULT_RPC_URLS: Record<number, string> = {\n 10004: 'https://sepolia.base.org',\n 10005: 'https://sepolia.optimism.io',\n 10003: 'https://sepolia-rollup.arbitrum.io/rpc',\n};\n\n/**\n * Testnet token prices (USD) for development/testing\n * These are static estimates since testnet tokens have no real value\n */\nconst TESTNET_TOKEN_PRICES: Record<string, number> = {\n ETH: 2500,\n WETH: 2500,\n USDC: 1,\n USDT: 1,\n DAI: 1,\n WBTC: 60000,\n LINK: 15,\n UNI: 8,\n};\n\n/**\n * ERC20 ABI for balance checking\n */\nconst ERC20_ABI = [\n 'function balanceOf(address owner) view returns (uint256)',\n 'function decimals() view returns (uint8)',\n 'function symbol() view returns (string)',\n 'function name() view returns (string)',\n];\n\n/**\n * Default cache TTL: 30 seconds\n */\nconst DEFAULT_CACHE_TTL = 30_000;\n\n// ============================================================================\n// Balance Cache\n// ============================================================================\n\ninterface CachedBalance {\n balance: PortfolioBalance;\n expiresAt: number;\n}\n\n// ============================================================================\n// Balance Manager Class\n// ============================================================================\n\nexport class BalanceManager {\n private config: Required<BalanceManagerConfig>;\n private providers: Map<number, ethers.JsonRpcProvider> = new Map();\n private cache: Map<string, CachedBalance> = new Map();\n\n constructor(config: BalanceManagerConfig = {}) {\n this.config = {\n cacheBalances: config.cacheBalances ?? true,\n cacheTtl: config.cacheTtl ?? DEFAULT_CACHE_TTL,\n customRpcUrls: config.customRpcUrls ?? {},\n };\n }\n\n // ========================================================================\n // Public Methods\n // ========================================================================\n\n /**\n * Get balance for a specific token on a chain\n * \n * @param wormholeChainId - The Wormhole chain ID\n * @param address - The address to check balance for\n * @param tokenAddress - Token address or 'native' for native token\n * @returns TokenBalance with raw and formatted amounts\n */\n async getBalance(\n wormholeChainId: number,\n address: string,\n tokenAddress: string\n ): Promise<TokenBalance> {\n const provider = this.getProvider(wormholeChainId);\n const tokenList = getTokenList(wormholeChainId);\n \n if (!tokenList) {\n throw new Error(`Chain ${wormholeChainId} not supported`);\n }\n\n const tokens = getAllTokens(wormholeChainId);\n let tokenInfo = tokens.find(\n t => t.address.toLowerCase() === tokenAddress.toLowerCase()\n );\n\n // Handle native token variations\n if (!tokenInfo && isNativeToken(tokenAddress)) {\n tokenInfo = tokenList.nativeToken;\n }\n\n // If still no token info, create a generic one\n if (!tokenInfo) {\n tokenInfo = await this.fetchTokenInfo(provider, tokenAddress);\n }\n\n const balance = await this.fetchBalance(provider, address, tokenAddress, tokenInfo);\n const formatted = ethers.formatUnits(balance, tokenInfo.decimals);\n // Calculate USD value using testnet prices\n const price = TESTNET_TOKEN_PRICES[tokenInfo.symbol.toUpperCase()];\n const usdValue = price ? parseFloat(formatted) * price : undefined;\n\n return {\n token: tokenInfo,\n balance,\n formatted,\n usdValue,\n };\n }\n\n /**\n * Get all token balances for an address on a chain\n * \n * @param wormholeChainId - The Wormhole chain ID\n * @param address - The address to check balances for\n * @param includeZeroBalances - Whether to include tokens with 0 balance\n * @returns PortfolioBalance with all token balances\n */\n async getPortfolioBalance(\n wormholeChainId: number,\n address: string,\n includeZeroBalances: boolean = false\n ): Promise<PortfolioBalance> {\n // Check cache first\n const cacheKey = `${wormholeChainId}:${address.toLowerCase()}`;\n if (this.config.cacheBalances) {\n const cached = this.cache.get(cacheKey);\n if (cached && cached.expiresAt > Date.now()) {\n return cached.balance;\n }\n }\n\n const tokenList = getTokenList(wormholeChainId);\n if (!tokenList) {\n throw new Error(`Chain ${wormholeChainId} not supported`);\n }\n\n const provider = this.getProvider(wormholeChainId);\n const tokens = getAllTokens(wormholeChainId);\n const balances: TokenBalance[] = [];\n\n // Fetch all balances in parallel\n const balancePromises = tokens.map(async (token) => {\n try {\n const balance = await this.fetchBalance(\n provider,\n address,\n token.address,\n token\n );\n const formatted = ethers.formatUnits(balance, token.decimals);\n // Calculate USD value using testnet prices\n const price = TESTNET_TOKEN_PRICES[token.symbol.toUpperCase()];\n const usdValue = price ? parseFloat(formatted) * price : undefined;\n return { token, balance, formatted, usdValue };\n } catch (error) {\n console.warn(`Failed to fetch ${token.symbol} balance:`, error);\n return { token, balance: 0n, formatted: '0', usdValue: undefined };\n }\n });\n\n const results = await Promise.all(balancePromises);\n\n for (const result of results) {\n if (includeZeroBalances || result.balance > 0n) {\n balances.push(result);\n }\n }\n\n // Calculate total USD value\n const totalUsdValue = balances.reduce((sum, b) => sum + (b.usdValue ?? 0), 0);\n\n const portfolio: PortfolioBalance = {\n wormholeChainId,\n chainName: tokenList.chainName,\n address,\n tokens: balances,\n totalUsdValue: totalUsdValue > 0 ? totalUsdValue : undefined,\n lastUpdated: Date.now(),\n };\n\n // Cache the result\n if (this.config.cacheBalances) {\n this.cache.set(cacheKey, {\n balance: portfolio,\n expiresAt: Date.now() + this.config.cacheTtl,\n });\n }\n\n return portfolio;\n }\n\n /**\n * Get native token balance\n * \n * @param wormholeChainId - The Wormhole chain ID\n * @param address - The address to check\n * @returns TokenBalance for native token\n */\n async getNativeBalance(\n wormholeChainId: number,\n address: string\n ): Promise<TokenBalance> {\n return this.getBalance(wormholeChainId, address, NATIVE_TOKEN_ADDRESS);\n }\n\n /**\n * Get balances across multiple chains for an address\n * \n * @param address - The address to check\n * @param chainIds - Array of Wormhole chain IDs to check\n * @returns Array of PortfolioBalance for each chain\n */\n async getMultiChainBalances(\n address: string,\n chainIds: number[]\n ): Promise<PortfolioBalance[]> {\n const promises = chainIds.map(chainId =>\n this.getPortfolioBalance(chainId, address).catch(error => {\n console.warn(`Failed to fetch balances for chain ${chainId}:`, error);\n return null;\n })\n );\n\n const results = await Promise.all(promises);\n return results.filter((r): r is PortfolioBalance => r !== null);\n }\n\n /**\n * Clear the balance cache\n */\n clearCache(): void {\n this.cache.clear();\n }\n\n /**\n * Invalidate cache for a specific address\n */\n invalidateCache(wormholeChainId: number, address: string): void {\n const cacheKey = `${wormholeChainId}:${address.toLowerCase()}`;\n this.cache.delete(cacheKey);\n }\n\n /**\n * Add or update RPC URL for a chain\n */\n setRpcUrl(wormholeChainId: number, rpcUrl: string): void {\n this.config.customRpcUrls[wormholeChainId] = rpcUrl;\n // Clear existing provider to force recreation\n this.providers.delete(wormholeChainId);\n }\n\n // ========================================================================\n // Private Methods\n // ========================================================================\n\n /**\n * Get or create a provider for a chain\n */\n private getProvider(wormholeChainId: number): ethers.JsonRpcProvider {\n let provider = this.providers.get(wormholeChainId);\n if (provider) {\n return provider;\n }\n\n const rpcUrl = this.config.customRpcUrls[wormholeChainId] ?? \n DEFAULT_RPC_URLS[wormholeChainId];\n \n if (!rpcUrl) {\n throw new Error(`No RPC URL configured for chain ${wormholeChainId}`);\n }\n\n provider = new ethers.JsonRpcProvider(rpcUrl);\n this.providers.set(wormholeChainId, provider);\n return provider;\n }\n\n /**\n * Fetch balance for a token\n */\n private async fetchBalance(\n provider: ethers.JsonRpcProvider,\n address: string,\n tokenAddress: string,\n _tokenInfo: TokenInfo\n ): Promise<bigint> {\n if (isNativeToken(tokenAddress)) {\n return await provider.getBalance(address);\n }\n\n const contract = new ethers.Contract(tokenAddress, ERC20_ABI, provider);\n return await contract.balanceOf(address);\n }\n\n /**\n * Fetch token info from contract\n */\n private async fetchTokenInfo(\n provider: ethers.JsonRpcProvider,\n tokenAddress: string\n ): Promise<TokenInfo> {\n const contract = new ethers.Contract(tokenAddress, ERC20_ABI, provider);\n \n const [symbol, name, decimals] = await Promise.all([\n contract.symbol().catch(() => 'UNKNOWN'),\n contract.name().catch(() => 'Unknown Token'),\n contract.decimals().catch(() => 18),\n ]);\n\n return {\n symbol,\n name,\n address: tokenAddress,\n decimals: Number(decimals),\n isNative: false,\n };\n }\n}\n","/**\n * Veridex Protocol SDK - Token Constants\n * \n * Known tokens per chain for balance fetching and transfers\n */\n\n// ============================================================================\n// Types\n// ============================================================================\n\nexport interface TokenInfo {\n /** Token symbol (e.g., 'USDC', 'ETH') */\n symbol: string;\n /** Token name (e.g., 'USD Coin') */\n name: string;\n /** Token address (use 'native' for native token) */\n address: string;\n /** Number of decimals */\n decimals: number;\n /** Optional logo URL */\n logoUrl?: string;\n /** Whether this is the native token */\n isNative: boolean;\n /** Wormhole-wrapped token address on other chains (by wormhole chain ID) */\n wrappedAddresses?: Record<number, string>;\n}\n\nexport interface ChainTokenList {\n /** Wormhole chain ID */\n wormholeChainId: number;\n /** Chain name */\n chainName: string;\n /** Native token info */\n nativeToken: TokenInfo;\n /** ERC20/SPL/etc tokens */\n tokens: TokenInfo[];\n}\n\n// ============================================================================\n// Constants\n// ============================================================================\n\n/**\n * Native token address constant\n */\nexport const NATIVE_TOKEN_ADDRESS = 'native';\n\n/**\n * Zero address for EVM chains\n */\nexport const EVM_ZERO_ADDRESS = '0x0000000000000000000000000000000000000000';\n\n// ============================================================================\n// Base Sepolia (Hub Chain) - Wormhole Chain ID 10004\n// ============================================================================\n\nexport const BASE_SEPOLIA_TOKENS: ChainTokenList = {\n wormholeChainId: 10004,\n chainName: 'Base Sepolia',\n nativeToken: {\n symbol: 'ETH',\n name: 'Ether',\n address: NATIVE_TOKEN_ADDRESS,\n decimals: 18,\n isNative: true,\n },\n tokens: [\n {\n symbol: 'USDC',\n name: 'USD Coin (Test)',\n address: '0x036CbD53842c5426634e7929541eC2318f3dCF7e', // Circle test USDC\n decimals: 6,\n isNative: false,\n },\n {\n symbol: 'WETH',\n name: 'Wrapped Ether',\n address: '0x4200000000000000000000000000000000000006',\n decimals: 18,\n isNative: false,\n },\n ],\n};\n\n// ============================================================================\n// Optimism Sepolia (Spoke Chain) - Wormhole Chain ID 10005\n// ============================================================================\n\nexport const OPTIMISM_SEPOLIA_TOKENS: ChainTokenList = {\n wormholeChainId: 10005,\n chainName: 'Optimism Sepolia',\n nativeToken: {\n symbol: 'ETH',\n name: 'Ether',\n address: NATIVE_TOKEN_ADDRESS,\n decimals: 18,\n isNative: true,\n },\n tokens: [\n {\n symbol: 'USDC',\n name: 'USD Coin (Test)',\n address: '0x5fd84259d66Cd46123540766Be93DFE6D43130D7', // Test USDC\n decimals: 6,\n isNative: false,\n },\n {\n symbol: 'WETH',\n name: 'Wrapped Ether',\n address: '0x4200000000000000000000000000000000000006',\n decimals: 18,\n isNative: false,\n },\n ],\n};\n\n// ============================================================================\n// Arbitrum Sepolia (Spoke Chain) - Wormhole Chain ID 10003\n// ============================================================================\n\nexport const ARBITRUM_SEPOLIA_TOKENS: ChainTokenList = {\n wormholeChainId: 10003,\n chainName: 'Arbitrum Sepolia',\n nativeToken: {\n symbol: 'ETH',\n name: 'Ether',\n address: NATIVE_TOKEN_ADDRESS,\n decimals: 18,\n isNative: true,\n },\n tokens: [\n {\n symbol: 'USDC',\n name: 'USD Coin (Test)',\n address: '0x75faf114eafb1BDbe2F0316DF893fd58CE46AA4d', // Circle USDC Arbitrum Sepolia\n decimals: 6,\n isNative: false,\n },\n {\n symbol: 'WETH',\n name: 'Wrapped Ether',\n address: '0x980B62Da83eFf3D4576C647993b0c1D7faf17c73',\n decimals: 18,\n isNative: false,\n },\n ],\n};\n\n// ============================================================================\n// Token Registry\n// ============================================================================\n\n/**\n * All token lists indexed by Wormhole chain ID\n */\nexport const TOKEN_REGISTRY: Record<number, ChainTokenList> = {\n 10004: BASE_SEPOLIA_TOKENS,\n 10005: OPTIMISM_SEPOLIA_TOKENS,\n 10003: ARBITRUM_SEPOLIA_TOKENS,\n};\n\n// ============================================================================\n// Helper Functions\n// ============================================================================\n\n/**\n * Get token list for a chain\n */\nexport function getTokenList(wormholeChainId: number): ChainTokenList | null {\n return TOKEN_REGISTRY[wormholeChainId] ?? null;\n}\n\n/**\n * Get all tokens for a chain (native + ERC20)\n */\nexport function getAllTokens(wormholeChainId: number): TokenInfo[] {\n const list = getTokenList(wormholeChainId);\n if (!list) return [];\n return [list.nativeToken, ...list.tokens];\n}\n\n/**\n * Get token info by symbol\n */\nexport function getTokenBySymbol(wormholeChainId: number, symbol: string): TokenInfo | null {\n const tokens = getAllTokens(wormholeChainId);\n return tokens.find(t => t.symbol.toLowerCase() === symbol.toLowerCase()) ?? null;\n}\n\n/**\n * Get token info by address\n */\nexport function getTokenByAddress(wormholeChainId: number, address: string): TokenInfo | null {\n const tokens = getAllTokens(wormholeChainId);\n const normalizedAddress = address.toLowerCase();\n return tokens.find(t => t.address.toLowerCase() === normalizedAddress) ?? null;\n}\n\n/**\n * Check if an address is the native token\n */\nexport function isNativeToken(address: string): boolean {\n return address.toLowerCase() === NATIVE_TOKEN_ADDRESS || \n address === EVM_ZERO_ADDRESS;\n}\n\n/**\n * Get supported chain IDs\n */\nexport function getSupportedChainIds(): number[] {\n return Object.keys(TOKEN_REGISTRY).map(Number);\n}\n\n/**\n * Get chain name by Wormhole chain ID\n */\nexport function getChainName(wormholeChainId: number): string | null {\n return TOKEN_REGISTRY[wormholeChainId]?.chainName ?? null;\n}\n","/**\n * Veridex Protocol SDK - Transaction Tracker\n * \n * Tracks transaction status from pending to confirmed\n */\n\nimport { ethers } from 'ethers';\n\n// ============================================================================\n// Types\n// ============================================================================\n\nexport type TransactionStatus = \n | 'pending'\n | 'submitted'\n | 'confirming'\n | 'confirmed'\n | 'failed'\n | 'dropped';\n\nexport interface TransactionState {\n /** Transaction hash */\n hash: string;\n /** Current status */\n status: TransactionStatus;\n /** Wormhole chain ID where transaction was sent */\n wormholeChainId: number;\n /** Block number when confirmed */\n blockNumber?: number;\n /** Number of confirmations */\n confirmations: number;\n /** Required confirmations for finality */\n requiredConfirmations: number;\n /** Gas used (after confirmation) */\n gasUsed?: bigint;\n /** Effective gas price */\n effectiveGasPrice?: bigint;\n /** Error message if failed */\n error?: string;\n /** Timestamp when transaction was submitted */\n submittedAt: number;\n /** Timestamp when transaction was confirmed */\n confirmedAt?: number;\n /** VAA sequence number (for cross-chain txs) */\n vaaSequence?: bigint;\n}\n\nexport interface TrackerConfig {\n /** Polling interval in ms (default: 2000) */\n pollingInterval?: number;\n /** Required confirmations for finality (default: 1) */\n requiredConfirmations?: number;\n /** Timeout in ms before marking as dropped (default: 300000 - 5 min) */\n timeout?: number;\n /** Custom RPC URLs by chain ID */\n customRpcUrls?: Record<number, string>;\n}\n\nexport type TransactionCallback = (state: TransactionState) => void;\n\n// ============================================================================\n// Constants\n// ============================================================================\n\nconst DEFAULT_POLLING_INTERVAL = 2000;\nconst DEFAULT_REQUIRED_CONFIRMATIONS = 1;\nconst DEFAULT_TIMEOUT = 300_000; // 5 minutes\n\nconst DEFAULT_RPC_URLS: Record<number, string> = {\n 10004: 'https://sepolia.base.org',\n 10005: 'https://sepolia.optimism.io',\n 10003: 'https://sepolia-rollup.arbitrum.io/rpc',\n};\n\n// ============================================================================\n// Transaction Tracker Class\n// ============================================================================\n\nexport class TransactionTracker {\n private config: Required<TrackerConfig>;\n private providers: Map<number, ethers.JsonRpcProvider> = new Map();\n private trackedTransactions: Map<string, TransactionState> = new Map();\n private callbacks: Map<string, TransactionCallback[]> = new Map();\n private pollingIntervals: Map<string, NodeJS.Timeout> = new Map();\n\n constructor(config: TrackerConfig = {}) {\n this.config = {\n pollingInterval: config.pollingInterval ?? DEFAULT_POLLING_INTERVAL,\n requiredConfirmations: config.requiredConfirmations ?? DEFAULT_REQUIRED_CONFIRMATIONS,\n timeout: config.timeout ?? DEFAULT_TIMEOUT,\n customRpcUrls: config.customRpcUrls ?? {},\n };\n }\n\n // ========================================================================\n // Public Methods\n // ========================================================================\n\n /**\n * Track a transaction and receive status updates\n * \n * @param hash - Transaction hash\n * @param wormholeChainId - Chain where transaction was sent\n * @param callback - Optional callback for status updates\n * @param vaaSequence - Optional VAA sequence for cross-chain transactions\n * @returns Initial transaction state\n */\n track(\n hash: string,\n wormholeChainId: number,\n callback?: TransactionCallback,\n vaaSequence?: bigint\n ): TransactionState {\n // Create initial state\n const state: TransactionState = {\n hash,\n status: 'pending',\n wormholeChainId,\n confirmations: 0,\n requiredConfirmations: this.config.requiredConfirmations,\n submittedAt: Date.now(),\n vaaSequence,\n };\n\n this.trackedTransactions.set(hash, state);\n \n if (callback) {\n this.addCallback(hash, callback);\n }\n\n // Start polling\n this.startPolling(hash, wormholeChainId);\n\n return state;\n }\n\n /**\n * Add a callback for transaction updates\n */\n addCallback(hash: string, callback: TransactionCallback): void {\n const existing = this.callbacks.get(hash) ?? [];\n existing.push(callback);\n this.callbacks.set(hash, existing);\n }\n\n /**\n * Remove a callback\n */\n removeCallback(hash: string, callback: TransactionCallback): void {\n const existing = this.callbacks.get(hash) ?? [];\n const filtered = existing.filter(cb => cb !== callback);\n if (filtered.length > 0) {\n this.callbacks.set(hash, filtered);\n } else {\n this.callbacks.delete(hash);\n }\n }\n\n /**\n * Get current state of a tracked transaction\n */\n getState(hash: string): TransactionState | null {\n return this.trackedTransactions.get(hash) ?? null;\n }\n\n /**\n * Wait for a transaction to reach confirmed status\n * \n * @param hash - Transaction hash\n * @param wormholeChainId - Chain where transaction was sent\n * @returns Promise that resolves when confirmed or rejects on failure\n */\n async waitForConfirmation(\n hash: string,\n wormholeChainId: number\n ): Promise<TransactionState> {\n // Check if already tracked\n let state = this.trackedTransactions.get(hash);\n \n if (!state) {\n state = this.track(hash, wormholeChainId);\n }\n\n // If already confirmed or failed, return immediately\n if (state.status === 'confirmed' || state.status === 'failed' || state.status === 'dropped') {\n return state;\n }\n\n // Wait for confirmation\n return new Promise((resolve, reject) => {\n const callback: TransactionCallback = (newState) => {\n if (newState.status === 'confirmed') {\n this.removeCallback(hash, callback);\n resolve(newState);\n } else if (newState.status === 'failed' || newState.status === 'dropped') {\n this.removeCallback(hash, callback);\n reject(new Error(newState.error ?? `Transaction ${newState.status}`));\n }\n };\n\n this.addCallback(hash, callback);\n });\n }\n\n /**\n * Stop tracking a transaction\n */\n stopTracking(hash: string): void {\n const interval = this.pollingIntervals.get(hash);\n if (interval) {\n clearInterval(interval);\n this.pollingIntervals.delete(hash);\n }\n this.trackedTransactions.delete(hash);\n this.callbacks.delete(hash);\n }\n\n /**\n * Stop tracking all transactions\n */\n stopAll(): void {\n for (const hash of this.pollingIntervals.keys()) {\n this.stopTracking(hash);\n }\n }\n\n /**\n * Get all tracked transactions\n */\n getAllTracked(): TransactionState[] {\n return Array.from(this.trackedTransactions.values());\n }\n\n /**\n * Get pending transactions\n */\n getPending(): TransactionState[] {\n return this.getAllTracked().filter(\n tx => tx.status === 'pending' || tx.status === 'submitted' || tx.status === 'confirming'\n );\n }\n\n // ========================================================================\n // Private Methods\n // ========================================================================\n\n /**\n * Get or create provider for a chain\n */\n private getProvider(wormholeChainId: number): ethers.JsonRpcProvider {\n let provider = this.providers.get(wormholeChainId);\n if (provider) {\n return provider;\n }\n\n const rpcUrl = this.config.customRpcUrls[wormholeChainId] ?? \n DEFAULT_RPC_URLS[wormholeChainId];\n \n if (!rpcUrl) {\n throw new Error(`No RPC URL configured for chain ${wormholeChainId}`);\n }\n\n provider = new ethers.JsonRpcProvider(rpcUrl);\n this.providers.set(wormholeChainId, provider);\n return provider;\n }\n\n /**\n * Start polling for transaction status\n */\n private startPolling(hash: string, wormholeChainId: number): void {\n // Initial check\n this.checkTransaction(hash, wormholeChainId);\n\n // Set up interval\n const interval = setInterval(() => {\n this.checkTransaction(hash, wormholeChainId);\n }, this.config.pollingInterval);\n\n this.pollingIntervals.set(hash, interval);\n }\n\n /**\n * Check transaction status\n */\n private async checkTransaction(hash: string, wormholeChainId: number): Promise<void> {\n const state = this.trackedTransactions.get(hash);\n if (!state) {\n this.stopTracking(hash);\n return;\n }\n\n // Check timeout\n if (Date.now() - state.submittedAt > this.config.timeout) {\n this.updateState(hash, {\n status: 'dropped',\n error: 'Transaction timeout - possibly dropped from mempool',\n });\n this.stopTracking(hash);\n return;\n }\n\n try {\n const provider = this.getProvider(wormholeChainId);\n const receipt = await provider.getTransactionReceipt(hash);\n\n if (!receipt) {\n // Transaction not yet mined\n if (state.status === 'pending') {\n this.updateState(hash, { status: 'submitted' });\n }\n return;\n }\n\n // Transaction is mined\n const currentBlock = await provider.getBlockNumber();\n const confirmations = currentBlock - receipt.blockNumber + 1;\n\n if (receipt.status === 0) {\n // Transaction failed\n this.updateState(hash, {\n status: 'failed',\n blockNumber: receipt.blockNumber,\n confirmations,\n gasUsed: receipt.gasUsed,\n effectiveGasPrice: receipt.gasPrice,\n error: 'Transaction reverted',\n });\n this.stopTracking(hash);\n return;\n }\n\n if (confirmations >= this.config.requiredConfirmations) {\n // Fully confirmed\n this.updateState(hash, {\n status: 'confirmed',\n blockNumber: receipt.blockNumber,\n confirmations,\n gasUsed: receipt.gasUsed,\n effectiveGasPrice: receipt.gasPrice,\n confirmedAt: Date.now(),\n });\n this.stopTracking(hash);\n } else {\n // Still confirming\n this.updateState(hash, {\n status: 'confirming',\n blockNumber: receipt.blockNumber,\n confirmations,\n gasUsed: receipt.gasUsed,\n effectiveGasPrice: receipt.gasPrice,\n });\n }\n } catch (error) {\n console.warn(`Error checking transaction ${hash}:`, error);\n // Don't update state on transient errors\n }\n }\n\n /**\n * Update transaction state and notify callbacks\n */\n private updateState(hash: string, updates: Partial<TransactionState>): void {\n const current = this.trackedTransactions.get(hash);\n if (!current) return;\n\n const newState: TransactionState = { ...current, ...updates };\n this.trackedTransactions.set(hash, newState);\n\n // Notify callbacks\n const callbacks = this.callbacks.get(hash) ?? [];\n for (const callback of callbacks) {\n try {\n callback(newState);\n } catch (error) {\n console.error('Error in transaction callback:', error);\n }\n }\n }\n}\n\n// ============================================================================\n// Helper Functions\n// ============================================================================\n\n/**\n * Create a formatted transaction explorer URL\n */\nexport function getExplorerUrl(\n wormholeChainId: number,\n hash: string\n): string | null {\n const explorers: Record<number, string> = {\n 10004: 'https://sepolia.basescan.org/tx/',\n 10005: 'https://sepolia-optimism.etherscan.io/tx/',\n 10003: 'https://sepolia.arbiscan.io/tx/',\n };\n\n const baseUrl = explorers[wormholeChainId];\n return baseUrl ? `${baseUrl}${hash}` : null;\n}\n\n/**\n * Format transaction state for display\n */\nexport function formatTransactionState(state: TransactionState): string {\n switch (state.status) {\n case 'pending':\n return 'Transaction pending...';\n case 'submitted':\n return 'Transaction submitted, waiting for confirmation...';\n case 'confirming':\n return `Confirming (${state.confirmations}/${state.requiredConfirmations})...`;\n case 'confirmed':\n return 'Transaction confirmed!';\n case 'failed':\n return `Transaction failed: ${state.error ?? 'Unknown error'}`;\n case 'dropped':\n return 'Transaction dropped from mempool';\n default:\n return 'Unknown status';\n }\n}\n","/**\n * Veridex Protocol SDK - Cross-Chain Manager\n * \n * Orchestrates cross-chain transfers including:\n * - VAA fetching and parsing\n * - Fee estimation (message + relayer fees)\n * - Transaction status tracking across chains\n * - Lifecycle callbacks for UI updates\n */\n\nimport { ethers } from 'ethers';\nimport {\n fetchVAA,\n fetchVAAByTxHash,\n parseVAA,\n parseVeridexPayload,\n encodeVAAToBytes,\n getSequenceFromTxReceipt,\n waitForGuardianSignatures,\n normalizeEmitterAddress,\n GUARDIAN_CONFIG,\n} from '../wormhole.js';\nimport type {\n BridgeParams,\n VAA,\n VeridexPayload,\n ChainConfig,\n} from './types.js';\n\n// ============================================================================\n// Types\n// ============================================================================\n\n/**\n * Cross-chain transfer lifecycle states\n */\nexport type CrossChainStatus =\n | 'preparing'\n | 'signing'\n | 'dispatching'\n | 'waiting_confirmations'\n | 'waiting_guardians'\n | 'vaa_ready'\n | 'relaying'\n | 'executing'\n | 'completed'\n | 'failed';\n\n/**\n * Progress callback for cross-chain operations\n */\nexport interface CrossChainProgress {\n status: CrossChainStatus;\n step: number;\n totalSteps: number;\n message: string;\n details?: {\n txHash?: string;\n sequence?: bigint;\n guardianSignatures?: number;\n requiredSignatures?: number;\n vaaReady?: boolean;\n destinationTxHash?: string;\n };\n}\n\n/**\n * Cross-chain transfer result\n */\nexport interface CrossChainResult {\n /** Source chain transaction hash */\n sourceTxHash: string;\n /** Wormhole message sequence number */\n sequence: bigint;\n /** Emitter address (Hub contract) */\n emitterAddress: string;\n /** Source chain Wormhole ID */\n sourceChain: number;\n /** Destination chain Wormhole ID */\n destinationChain: number;\n /** VAA base64 (once ready) */\n vaa?: string;\n /** Parsed VAA */\n parsedVaa?: VAA;\n /** Destination chain transaction hash */\n destinationTxHash?: string;\n /** Total time taken in ms */\n duration: number;\n /** Final status */\n status: CrossChainStatus;\n /** Error message if failed */\n error?: string;\n}\n\n/**\n * Fee breakdown for cross-chain transfers\n */\nexport interface CrossChainFees {\n /** Gas cost on source chain */\n sourceGas: bigint;\n /** Wormhole message fee */\n messageFee: bigint;\n /** Relayer fee (if using automatic relay) */\n relayerFee: bigint;\n /** Total estimated cost in source chain native token */\n totalCost: bigint;\n /** Formatted total cost */\n formattedTotal: string;\n /** Currency symbol */\n currency: string;\n}\n\n/**\n * Configuration for CrossChainManager\n */\nexport interface CrossChainConfig {\n /** Use testnet APIs (default: true) */\n testnet?: boolean;\n /** Relayer service URL (optional) */\n relayerUrl?: string;\n /** Max time to wait for VAA (ms) */\n vaaTimeoutMs?: number;\n /** Interval to poll for VAA (ms) */\n vaaPollingIntervalMs?: number;\n /** Required block confirmations before fetching VAA */\n confirmationsRequired?: number;\n /** Auto-relay VAA to destination (requires relayer) */\n autoRelay?: boolean;\n}\n\n/**\n * Callback type for progress updates\n */\nexport type CrossChainProgressCallback = (progress: CrossChainProgress) => void;\n\n// ============================================================================\n// Default Configuration\n// ============================================================================\n\nconst DEFAULT_CONFIG: Required<CrossChainConfig> = {\n testnet: true,\n relayerUrl: '',\n vaaTimeoutMs: 120_000, // 2 minutes\n vaaPollingIntervalMs: 3_000, // 3 seconds\n confirmationsRequired: 1,\n autoRelay: false,\n};\n\n// ============================================================================\n// CrossChainManager Class\n// ============================================================================\n\n/**\n * Manages cross-chain transfer lifecycle\n */\nexport class CrossChainManager {\n private config: Required<CrossChainConfig>;\n private pendingTransfers: Map<string, CrossChainResult> = new Map();\n\n constructor(config: CrossChainConfig = {}) {\n this.config = { ...DEFAULT_CONFIG, ...config };\n }\n\n // ========================================================================\n // Configuration\n // ========================================================================\n\n /**\n * Update configuration\n */\n setConfig(config: Partial<CrossChainConfig>): void {\n this.config = { ...this.config, ...config };\n }\n\n /**\n * Get current configuration\n */\n getConfig(): CrossChainConfig {\n return { ...this.config };\n }\n\n // ========================================================================\n // Fee Estimation\n // ========================================================================\n\n /**\n * Estimate fees for a cross-chain transfer\n */\n async estimateFees(\n params: BridgeParams,\n sourceChainConfig: ChainConfig,\n provider: ethers.Provider\n ): Promise<CrossChainFees> {\n // Get current gas price\n const feeData = await provider.getFeeData();\n const gasPrice = feeData.gasPrice ?? 0n;\n \n // Estimate gas for dispatch (Hub chain)\n // This is an approximation - actual gas depends on payload size\n const estimatedGas = 300_000n;\n const sourceGas = estimatedGas * gasPrice;\n\n // Get Wormhole message fee\n let messageFee = 0n;\n try {\n const wormholeAbi = ['function messageFee() view returns (uint256)'];\n const wormhole = new ethers.Contract(\n sourceChainConfig.contracts.wormholeCoreBridge,\n wormholeAbi,\n provider\n );\n messageFee = await wormhole.messageFee();\n } catch {\n // Default to 0 if bridge doesn't have messageFee\n }\n\n // Get relayer fee if using automatic relay\n let relayerFee = 0n;\n if (this.config.autoRelay && this.config.relayerUrl) {\n try {\n relayerFee = await this.fetchRelayerFee(\n params.destinationChain,\n sourceChainConfig.wormholeChainId\n );\n } catch {\n // Relayer fee fetch failed, continue with 0\n }\n }\n\n const totalCost = sourceGas + messageFee + relayerFee;\n\n return {\n sourceGas,\n messageFee,\n relayerFee,\n totalCost,\n formattedTotal: this.formatWei(totalCost),\n currency: 'ETH',\n };\n }\n\n /**\n * Fetch relayer fee from relayer service\n */\n private async fetchRelayerFee(\n destinationChain: number,\n _sourceChain: number\n ): Promise<bigint> {\n if (!this.config.relayerUrl) {\n return 0n;\n }\n\n // The current Veridex relayer exposes a simplified fee endpoint.\n // Source chain is accepted here for future-proofing but not required by the API today.\n const response = await fetch(\n `${this.config.relayerUrl}/api/v1/fee?targetChain=${destinationChain}`\n );\n\n if (!response.ok) {\n throw new Error('Failed to fetch relayer fee');\n }\n\n const data = await response.json() as {\n fees?: {\n wormhole?: string;\n relayer?: string;\n total?: string;\n };\n };\n\n return BigInt(data.fees?.relayer ?? '0');\n }\n\n // ========================================================================\n // VAA Operations\n // ========================================================================\n\n /**\n * Fetch VAA by sequence number\n */\n async fetchVAA(\n emitterChain: number,\n emitterAddress: string,\n sequence: bigint,\n onProgress?: CrossChainProgressCallback\n ): Promise<string> {\n onProgress?.({\n status: 'waiting_guardians',\n step: 4,\n totalSteps: 6,\n message: 'Waiting for Wormhole guardians to sign...',\n details: { sequence },\n });\n\n const vaaBase64 = await fetchVAA(emitterChain, emitterAddress, sequence, {\n testnet: this.config.testnet,\n maxRetries: Math.ceil(this.config.vaaTimeoutMs / this.config.vaaPollingIntervalMs),\n retryDelayMs: this.config.vaaPollingIntervalMs,\n onRetry: (attempt, max) => {\n onProgress?.({\n status: 'waiting_guardians',\n step: 4,\n totalSteps: 6,\n message: `Waiting for guardians (attempt ${attempt}/${max})...`,\n details: { sequence },\n });\n },\n });\n\n onProgress?.({\n status: 'vaa_ready',\n step: 5,\n totalSteps: 6,\n message: 'VAA signed and ready!',\n details: { sequence, vaaReady: true },\n });\n\n return vaaBase64;\n }\n\n /**\n * Fetch VAA by transaction hash (more reliable)\n */\n async fetchVAAByTxHash(\n txHash: string,\n onProgress?: CrossChainProgressCallback\n ): Promise<string> {\n onProgress?.({\n status: 'waiting_guardians',\n step: 4,\n totalSteps: 6,\n message: 'Waiting for Wormhole guardians to sign...',\n details: { txHash },\n });\n\n const vaaBase64 = await fetchVAAByTxHash(txHash, {\n testnet: this.config.testnet,\n maxRetries: Math.ceil(this.config.vaaTimeoutMs / this.config.vaaPollingIntervalMs),\n retryDelayMs: this.config.vaaPollingIntervalMs,\n onRetry: (attempt, max) => {\n onProgress?.({\n status: 'waiting_guardians',\n step: 4,\n totalSteps: 6,\n message: `Waiting for guardians (attempt ${attempt}/${max})...`,\n details: { txHash },\n });\n },\n });\n\n onProgress?.({\n status: 'vaa_ready',\n step: 5,\n totalSteps: 6,\n message: 'VAA signed and ready!',\n details: { txHash, vaaReady: true },\n });\n\n return vaaBase64;\n }\n\n /**\n * Wait for guardians to sign a message with progress tracking\n */\n async waitForGuardians(\n emitterChain: number,\n emitterAddress: string,\n sequence: bigint,\n onProgress?: CrossChainProgressCallback\n ): Promise<VAA> {\n const requiredSignatures = this.config.testnet\n ? GUARDIAN_CONFIG.TESTNET_QUORUM\n : GUARDIAN_CONFIG.MAINNET_QUORUM;\n\n return await waitForGuardianSignatures(\n emitterChain,\n emitterAddress,\n sequence,\n {\n testnet: this.config.testnet,\n requiredSignatures,\n maxWaitMs: this.config.vaaTimeoutMs,\n checkIntervalMs: this.config.vaaPollingIntervalMs,\n onProgress: (current, required) => {\n onProgress?.({\n status: 'waiting_guardians',\n step: 4,\n totalSteps: 6,\n message: `Collecting signatures (${current}/${required})...`,\n details: {\n sequence,\n guardianSignatures: current,\n requiredSignatures: required,\n },\n });\n },\n }\n );\n }\n\n /**\n * Parse a VAA and extract Veridex payload\n */\n parseVAA(vaaBase64: string): { vaa: VAA; payload: VeridexPayload } {\n const vaa = parseVAA(vaaBase64);\n const payload = parseVeridexPayload(vaa.payload);\n return { vaa, payload };\n }\n\n /**\n * Encode VAA for on-chain submission\n */\n encodeVAAForSubmission(vaaBase64: string): string {\n return encodeVAAToBytes(vaaBase64);\n }\n\n // ========================================================================\n // Transfer Lifecycle\n // ========================================================================\n\n /**\n * Track a cross-chain transfer\n */\n trackTransfer(\n sourceTxHash: string,\n sourceChain: number,\n destinationChain: number,\n sequence: bigint,\n emitterAddress: string\n ): CrossChainResult {\n const result: CrossChainResult = {\n sourceTxHash,\n sequence,\n emitterAddress,\n sourceChain,\n destinationChain,\n duration: 0,\n status: 'waiting_guardians',\n };\n\n this.pendingTransfers.set(sourceTxHash, result);\n return result;\n }\n\n /**\n * Get pending transfer by source tx hash\n */\n getPendingTransfer(sourceTxHash: string): CrossChainResult | undefined {\n return this.pendingTransfers.get(sourceTxHash);\n }\n\n /**\n * Get all pending transfers\n */\n getAllPendingTransfers(): CrossChainResult[] {\n return Array.from(this.pendingTransfers.values()).filter(\n t => t.status !== 'completed' && t.status !== 'failed'\n );\n }\n\n /**\n * Update transfer status\n */\n updateTransfer(\n sourceTxHash: string,\n updates: Partial<CrossChainResult>\n ): CrossChainResult | undefined {\n const transfer = this.pendingTransfers.get(sourceTxHash);\n if (!transfer) return undefined;\n\n Object.assign(transfer, updates);\n return transfer;\n }\n\n /**\n * Complete transfer with VAA\n */\n completeTransfer(\n sourceTxHash: string,\n vaa: string,\n destinationTxHash?: string\n ): CrossChainResult | undefined {\n const transfer = this.pendingTransfers.get(sourceTxHash);\n if (!transfer) return undefined;\n\n transfer.vaa = vaa;\n transfer.parsedVaa = parseVAA(vaa);\n transfer.destinationTxHash = destinationTxHash;\n transfer.status = 'completed';\n\n return transfer;\n }\n\n /**\n * Mark transfer as failed\n */\n failTransfer(sourceTxHash: string, error: string): CrossChainResult | undefined {\n const transfer = this.pendingTransfers.get(sourceTxHash);\n if (!transfer) return undefined;\n\n transfer.status = 'failed';\n transfer.error = error;\n\n return transfer;\n }\n\n /**\n * Clear completed/failed transfers\n */\n clearFinishedTransfers(): void {\n for (const [hash, transfer] of this.pendingTransfers.entries()) {\n if (transfer.status === 'completed' || transfer.status === 'failed') {\n this.pendingTransfers.delete(hash);\n }\n }\n }\n\n // ========================================================================\n // Utilities\n // ========================================================================\n\n /**\n * Extract sequence from transaction receipt\n */\n async getSequenceFromTx(\n provider: ethers.Provider,\n txHash: string,\n wormholeCoreBridge: string\n ): Promise<bigint> {\n return await getSequenceFromTxReceipt(provider, txHash, wormholeCoreBridge);\n }\n\n /**\n * Normalize address to emitter format\n */\n normalizeAddress(address: string): string {\n return normalizeEmitterAddress(address);\n }\n\n /**\n * Get explorer URL for a cross-chain transfer\n */\n getExplorerUrl(\n txHash: string,\n _chain: 'source' | 'destination',\n explorerBaseUrl: string\n ): string {\n return `${explorerBaseUrl}/tx/${txHash}`;\n }\n\n /**\n * Get Wormholescan URL for VAA\n */\n getWormholeExplorerUrl(\n emitterChain: number,\n emitterAddress: string,\n sequence: bigint\n ): string {\n const base = this.config.testnet\n ? 'https://wormholescan.io/#/tx'\n : 'https://wormholescan.io/#/tx';\n \n const normalizedEmitter = normalizeEmitterAddress(emitterAddress);\n return `${base}/${emitterChain}/${normalizedEmitter}/${sequence.toString()}`;\n }\n\n /**\n * Format wei to human-readable string\n */\n private formatWei(wei: bigint): string {\n const eth = Number(wei) / 1e18;\n if (eth < 0.0001) {\n return `${(Number(wei) / 1e9).toFixed(4)} gwei`;\n }\n return `${eth.toFixed(6)} ETH`;\n }\n}\n\n// ============================================================================\n// Export singleton for convenience\n// ============================================================================\n\nexport const crossChainManager = new CrossChainManager();\n","/**\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 - Relayer Client\n * \n * Client for interacting with the Veridex relayer service.\n * The relayer automatically submits VAAs to destination chains.\n * \n * Features:\n * - Submit VAA for relay\n * - Check relay status\n * - Get supported routes\n * - Fee estimation\n */\n\n// ============================================================================\n// Types\n// ============================================================================\n\n/**\n * Relay request status\n */\nexport type RelayStatus =\n | 'pending'\n | 'processing'\n | 'submitted'\n | 'confirmed'\n | 'failed';\n\n/**\n * Relay request result\n */\nexport interface RelayRequest {\n /** Unique relay request ID */\n id: string;\n /** VAA sequence number */\n sequence: bigint;\n /** Source chain Wormhole ID */\n sourceChain: number;\n /** Destination chain Wormhole ID */\n destinationChain: number;\n /** Relay status */\n status: RelayStatus;\n /** Source transaction hash */\n sourceTxHash: string;\n /** Destination transaction hash (when completed) */\n destinationTxHash?: string;\n /** Timestamp when request was created */\n createdAt: number;\n /** Timestamp when request was last updated */\n updatedAt: number;\n /** Error message if failed */\n error?: string;\n /** Gas used on destination chain */\n gasUsed?: bigint;\n /** Fee paid */\n feePaid?: bigint;\n}\n\n/**\n * Supported route information\n */\nexport interface RelayRoute {\n /** Source chain Wormhole ID */\n sourceChain: number;\n /** Destination chain Wormhole ID */\n destinationChain: number;\n /** Whether the route is active */\n active: boolean;\n /** Estimated relay time in seconds */\n estimatedTimeSeconds: number;\n /** Base fee in destination chain native token */\n baseFee: bigint;\n /** Fee per gas unit */\n gasPrice: bigint;\n /** Maximum gas limit */\n maxGas: bigint;\n}\n\n/**\n * Relayer service info\n */\nexport interface RelayerInfo {\n /** Relayer name/identifier */\n name: string;\n /** Relayer version */\n version: string;\n /** Supported chains */\n supportedChains: number[];\n /** Available routes */\n routes: RelayRoute[];\n /** Whether the relayer is online */\n online: boolean;\n /** Current queue depth */\n queueDepth: number;\n}\n\n/**\n * Request body for submitting a signed action to the relayer (gasless)\n * Uses full WebAuthn data for authenticateAndDispatch\n */\nexport interface SubmitSignedActionRequest {\n /** WebAuthn authenticatorData (hex) */\n authenticatorData: string;\n /** WebAuthn clientDataJSON (raw string) */\n clientDataJSON: string;\n /** Index of \"challenge\":\"...\" in clientDataJSON */\n challengeIndex: number;\n /** Index of \"type\":\"...\" in clientDataJSON */\n typeIndex: number;\n /** P-256 signature r component (hex) */\n r: string;\n /** P-256 signature s component (hex) */\n s: string;\n /** P-256 public key X coordinate (hex) */\n publicKeyX: string;\n /** P-256 public key Y coordinate (hex) */\n publicKeyY: string;\n /** Target chain Wormhole ID */\n targetChain: number;\n /** Action payload (hex) */\n actionPayload: string;\n /** User nonce */\n nonce: number;\n}\n\n/**\n * Response from submitting a signed action\n */\nexport interface SubmitActionResult {\n /** Whether the submission was successful */\n success: boolean;\n /** Transaction hash on Hub chain */\n txHash?: string;\n /** Wormhole sequence number */\n sequence?: string;\n /** Error message if failed */\n error?: string;\n /** Human-readable message */\n message?: string;\n}\n\n/**\n * Query submission request (Issue #11/#12)\n * For optimistic execution via Wormhole Query proofs (~5-7s vs ~120s)\n */\nexport interface SubmitQueryRequest {\n /** Target spoke chain Wormhole ID */\n targetChain: number;\n /** User's key hash */\n userKeyHash: string;\n /** Serialized transaction for spoke chain */\n serializedTx: string; // hex\n /** Query proof with Guardian signatures */\n queryProof: {\n /** Raw query response bytes */\n queryResponse: string; // hex\n /** Guardian signatures */\n signatures: string; // hex\n };\n /** Whether to fallback to VAA if Query fails */\n fallbackToVaa?: boolean;\n /** Optional metadata */\n metadata?: {\n /** User's preferred execution path */\n preferredPath?: 'query' | 'vaa';\n /** Transaction value in USD (for routing decisions) */\n estimatedValueUSD?: number;\n };\n}\n\n/**\n * Query submission result (Issue #11/#12)\n */\nexport interface SubmitQueryResult {\n /** Whether submission succeeded */\n success: boolean;\n /** Transaction hash on spoke chain */\n txHash?: string;\n /** Execution path used */\n path: 'query' | 'vaa';\n /** Latency in milliseconds */\n latencyMs?: number;\n /** Error message if failed */\n error?: string;\n /** Whether fallback to VAA occurred */\n fellBack?: boolean;\n}\n\n/**\n * Fee quote for a relay\n */\nexport interface RelayFeeQuote {\n /** Source chain Wormhole ID */\n sourceChain: number;\n /** Destination chain Wormhole ID */\n destinationChain: number;\n /** Estimated fee in source chain native token */\n feeInSourceToken: bigint;\n /** Estimated fee in destination chain native token */\n feeInDestinationToken: bigint;\n /** Estimated gas on destination */\n estimatedGas: bigint;\n /** Quote expiration timestamp */\n expiresAt: number;\n /** Quote ID for submission */\n quoteId: string;\n}\n\n/**\n * Configuration for RelayerClient\n */\nexport interface RelayerClientConfig {\n /** Base URL of the relayer service */\n baseUrl: string;\n /** API key for authentication (optional) */\n apiKey?: string;\n /** Timeout for requests in ms */\n timeoutMs?: number;\n /** Max retries for failed requests */\n maxRetries?: number;\n}\n\n// ============================================================================\n// Default Configuration\n// ============================================================================\n\nconst DEFAULT_CONFIG: Required<Omit<RelayerClientConfig, 'baseUrl'>> = {\n apiKey: '',\n timeoutMs: 30_000,\n maxRetries: 3,\n};\n\n// ============================================================================\n// RelayerClient Class\n// ============================================================================\n\n/**\n * Client for the Veridex relayer service\n */\nexport class RelayerClient {\n private baseUrl: string;\n private config: Required<Omit<RelayerClientConfig, 'baseUrl'>>;\n\n constructor(config: RelayerClientConfig) {\n this.baseUrl = config.baseUrl.replace(/\\/+$/, ''); // Remove trailing slashes\n this.config = { ...DEFAULT_CONFIG, ...config };\n }\n\n // ========================================================================\n // Relay Operations\n // ========================================================================\n\n /**\n * Submit a VAA for relay to destination chain\n */\n async submitRelay(\n vaaBase64: string,\n sourceChain: number,\n destinationChain: number,\n sourceTxHash: string,\n sequence: bigint,\n feeQuoteId?: string\n ): Promise<RelayRequest> {\n void vaaBase64;\n void sourceChain;\n void destinationChain;\n void sourceTxHash;\n void sequence;\n void feeQuoteId;\n throw new Error(\n 'submitRelay() is not supported by the current Veridex relayer API. ' +\n 'Use submitSignedAction() and let the relayer observe hub events to relay automatically.'\n );\n }\n\n /**\n * Submit a signed action to the relayer for gasless execution\n * \n * This allows users to execute transfers without paying gas themselves.\n * The relayer will submit the transaction to the Hub chain and pay the gas.\n * The relayer then automatically relays the VAA to the destination spoke chain.\n * \n * @param request - The signed action request with passkey signature\n * @returns Result including Hub tx hash and Wormhole sequence\n */\n async submitSignedAction(request: SubmitSignedActionRequest): Promise<SubmitActionResult> {\n try {\n const response = await this.fetch('/api/v1/submit', {\n method: 'POST',\n body: JSON.stringify(request),\n });\n\n return {\n success: response.success,\n txHash: response.transactionHash ?? response.txHash,\n sequence: response.sequence,\n error: response.error,\n message: response.message,\n };\n } catch (err: any) {\n // Handle 400 errors gracefully - the relayer returns error details in the body\n if (err.status === 400 && err.body) {\n return {\n success: false,\n error: err.body.error ?? 'Relayer returned 400 Bad Request',\n message: err.body.message,\n };\n }\n // Re-throw other errors\n throw err;\n }\n }\n\n /**\n * Submit a Query-based transaction for optimistic execution (Issue #11/#12)\n * \n * Uses Wormhole Cross-Chain Queries (CCQ) to achieve ~5-7 second latency\n * vs ~120+ seconds for traditional VAA flow.\n * \n * Flow:\n * 1. Client fetches Hub state via queryHubState() from SDK\n * 2. Client constructs and signs transaction\n * 3. Client submits Query proof + tx to this endpoint\n * 4. Relayer validates format and submits to spoke chain\n * 5. Spoke chain verifies Guardian signatures on-chain\n * \n * @param request - Query submission with Guardian-signed proof\n * @returns Result including spoke tx hash and execution path\n */\n async submitQuery(request: SubmitQueryRequest): Promise<SubmitQueryResult> {\n try {\n const response = await this.fetch('/api/v1/submit-query', {\n method: 'POST',\n body: JSON.stringify(request),\n });\n\n return {\n success: response.success ?? false,\n txHash: response.txHash,\n path: response.path ?? 'query',\n latencyMs: response.latencyMs,\n error: response.error,\n fellBack: response.fellBack ?? false,\n };\n } catch (err: any) {\n // Handle errors gracefully\n if (err.status === 400 && err.body) {\n return {\n success: false,\n path: 'query',\n error: err.body.error ?? 'Relayer returned 400 Bad Request',\n };\n }\n throw err;\n }\n }\n\n /**\n * Get relay request status\n */\n async getRelayStatus(requestId: string): Promise<RelayRequest> {\n void requestId;\n throw new Error('getRelayStatus() is not supported by the current Veridex relayer API.');\n }\n\n /**\n * Get relay status by source transaction hash\n */\n async getRelayBySourceTx(sourceTxHash: string): Promise<RelayRequest | null> {\n void sourceTxHash;\n return null;\n }\n\n /**\n * Get relay status by sequence number\n */\n async getRelayBySequence(\n sourceChain: number,\n sequence: bigint\n ): Promise<RelayRequest | null> {\n void sourceChain;\n void sequence;\n return null;\n }\n\n /**\n * Cancel a pending relay request\n */\n async cancelRelay(requestId: string): Promise<boolean> {\n void requestId;\n return false;\n }\n\n /**\n * Poll for relay completion\n */\n async waitForRelay(\n requestId: string,\n timeoutMs: number = 120_000,\n pollingIntervalMs: number = 3_000,\n onProgress?: (status: RelayStatus) => void\n ): Promise<RelayRequest> {\n void requestId;\n void timeoutMs;\n void pollingIntervalMs;\n void onProgress;\n throw new Error('waitForRelay() is not supported by the current Veridex relayer API.');\n }\n\n // ========================================================================\n // Fee Estimation\n // ========================================================================\n\n /**\n * Get fee quote for a relay\n */\n async getFeeQuote(\n sourceChain: number,\n destinationChain: number,\n estimatedGas?: bigint\n ): Promise<RelayFeeQuote> {\n void sourceChain;\n void estimatedGas;\n\n // The relayer currently returns a simple fee breakdown; we map it into the\n // existing RelayFeeQuote shape with best-effort defaults.\n const response = await this.fetch(`/api/v1/fee?targetChain=${destinationChain}`);\n const relayerFee = BigInt(response?.fees?.relayer ?? '0');\n const total = BigInt(response?.fees?.total ?? relayerFee.toString());\n\n return {\n sourceChain: sourceChain,\n destinationChain,\n feeInSourceToken: total,\n feeInDestinationToken: relayerFee,\n estimatedGas: 0n,\n expiresAt: Date.now() + 60_000,\n quoteId: '',\n };\n }\n\n // ========================================================================\n // Service Info\n // ========================================================================\n\n /**\n * Get relayer service info\n */\n async getInfo(): Promise<RelayerInfo> {\n const response = await this.fetch('/api/v1/info');\n\n return {\n name: 'veridex-relayer',\n version: response?.relayer?.version ?? response?.version ?? 'unknown',\n supportedChains: (response?.supportedChains || []).map((c: any) => c.wormholeChainId ?? c),\n routes: [],\n online: true,\n queueDepth: 0,\n };\n }\n\n /**\n * Get supported routes\n */\n async getRoutes(): Promise<RelayRoute[]> {\n throw new Error('getRoutes() is not supported by the current Veridex relayer API.');\n }\n\n /**\n * Check if a route is supported\n */\n async isRouteSupported(\n sourceChain: number,\n destinationChain: number\n ): Promise<boolean> {\n void sourceChain;\n void destinationChain;\n return false;\n }\n\n /**\n * Check relayer health\n */\n async healthCheck(): Promise<boolean> {\n try {\n const response = await this.fetch('/health');\n return response.status === 'healthy' || response.status === 'degraded' || response.healthy === true;\n } catch {\n return false;\n }\n }\n\n // ========================================================================\n // Pending Relays\n // ========================================================================\n\n /**\n * Get all pending relay requests for a user\n */\n async getPendingRelays(userKeyHash: string): Promise<RelayRequest[]> {\n void userKeyHash;\n return [];\n }\n\n /**\n * Get relay history for a user\n */\n async getRelayHistory(\n userKeyHash: string,\n limit: number = 50,\n offset: number = 0\n ): Promise<RelayRequest[]> {\n void userKeyHash;\n void limit;\n void offset;\n return [];\n }\n\n // ========================================================================\n // Internal Helpers\n // ========================================================================\n\n /**\n * SDK version for telemetry\n */\n private static readonly SDK_VERSION = '1.0.0-beta.1';\n\n /**\n * Make an HTTP request to the relayer\n */\n private async fetch(\n path: string,\n options: RequestInit = {}\n ): Promise<any> {\n const headers: HeadersInit = {\n 'Content-Type': 'application/json',\n 'User-Agent': `@veridex/sdk/${RelayerClient.SDK_VERSION}`,\n ...(options.headers || {}),\n };\n\n if (this.config.apiKey) {\n (headers as Record<string, string>)['X-API-Key'] = this.config.apiKey;\n }\n\n const controller = new AbortController();\n const timeout = setTimeout(() => controller.abort(), this.config.timeoutMs);\n\n let lastError: Error | null = null;\n\n for (let attempt = 0; attempt <= this.config.maxRetries; attempt++) {\n try {\n const response = await fetch(`${this.baseUrl}${path}`, {\n ...options,\n headers,\n signal: controller.signal,\n });\n\n clearTimeout(timeout);\n\n if (!response.ok) {\n const error: any = new Error(\n `Relayer request failed: ${response.status} ${response.statusText}`\n );\n error.status = response.status;\n try {\n error.body = await response.json();\n } catch {\n // Ignore JSON parse errors\n }\n throw error;\n }\n\n return await response.json();\n } catch (error: any) {\n lastError = error;\n\n // Don't retry on client errors (4xx)\n if (error.status && error.status >= 400 && error.status < 500) {\n throw error;\n }\n\n // Don't retry on abort\n if (error.name === 'AbortError') {\n throw new Error('Request timeout');\n }\n\n // Wait before retry\n if (attempt < this.config.maxRetries) {\n await this.sleep(1000 * (attempt + 1));\n }\n }\n }\n\n throw lastError || new Error('Request failed after all retries');\n }\n\n /**\n * Sleep helper\n */\n private sleep(ms: number): Promise<void> {\n return new Promise(resolve => setTimeout(resolve, ms));\n }\n}\n\n// ============================================================================\n// Factory function\n// ============================================================================\n\n/**\n * Create a RelayerClient instance\n */\nexport function createRelayerClient(config: RelayerClientConfig): RelayerClient {\n return new RelayerClient(config);\n}\n","/**\n * Veridex Protocol SDK - Solana Chain Client\n * \n * Implementation of ChainClient interface for Solana blockchain\n */\n\nimport {\n Connection,\n PublicKey,\n} from '@solana/web3.js';\nimport {\n getAssociatedTokenAddressSync,\n} from '@solana/spl-token';\nimport { createHash } from 'crypto';\nimport type {\n ChainClient,\n ChainConfig,\n TransferParams,\n ExecuteParams,\n BridgeParams,\n DispatchResult,\n WebAuthnSignature,\n VaultCreationResult,\n} from '../../core/types.js';\nimport { encodeTransferAction, encodeExecuteAction, encodeBridgeAction } from '../../payload.js';\n\n// ============================================================================\n// Types\n// ============================================================================\n\nexport interface SolanaClientConfig {\n wormholeChainId: number;\n rpcUrl: string;\n programId: string; // Veridex Spoke program\n wormholeCoreBridge: string;\n tokenBridge: string;\n network?: 'mainnet' | 'devnet' | 'testnet';\n commitment?: 'processed' | 'confirmed' | 'finalized';\n}\n\n// ============================================================================\n// Constants\n// ============================================================================\n\n// ============================================================================\n// SolanaClient Class\n// ============================================================================\n\n/**\n * Solana implementation of the ChainClient interface\n */\nexport class SolanaClient implements ChainClient {\n private config: ChainConfig;\n private connection: Connection;\n private programId: PublicKey;\n\n constructor(config: SolanaClientConfig) {\n this.config = {\n name: `Solana ${config.network || 'mainnet'}`,\n chainId: config.wormholeChainId,\n wormholeChainId: config.wormholeChainId,\n rpcUrl: config.rpcUrl,\n explorerUrl: config.network === 'devnet'\n ? 'https://explorer.solana.com?cluster=devnet'\n : 'https://explorer.solana.com',\n isEvm: false,\n contracts: {\n hub: undefined, // Solana is a spoke only\n wormholeCoreBridge: config.wormholeCoreBridge,\n tokenBridge: config.tokenBridge,\n },\n };\n\n this.connection = new Connection(\n config.rpcUrl,\n config.commitment || 'confirmed'\n );\n this.programId = new PublicKey(config.programId);\n }\n\n getConfig(): ChainConfig {\n return this.config;\n }\n\n async getNonce(userKeyHash: string): Promise<bigint> {\n try {\n const vaultAddress = this.computeVaultAddressFromHash(userKeyHash);\n const accountInfo = await this.connection.getAccountInfo(new PublicKey(vaultAddress));\n\n if (!accountInfo || accountInfo.data.length < 40) {\n return 0n;\n }\n\n // Nonce is stored at offset 8 (after discriminator)\n // Read as u64 little-endian\n const nonce = accountInfo.data.readBigUInt64LE(8);\n return nonce;\n } catch (error) {\n console.error('Error getting nonce:', error);\n return 0n;\n }\n }\n\n async getMessageFee(): Promise<bigint> {\n try {\n // Query Wormhole bridge for message fee\n // For now, return a default estimate\n // TODO: Query on-chain Wormhole config account\n return 0n; // Solana doesn't charge a Wormhole fee in the same way\n } catch (error) {\n console.error('Error getting message fee:', error);\n return 0n;\n }\n }\n\n async buildTransferPayload(params: TransferParams): Promise<string> {\n return encodeTransferAction(\n params.token,\n params.recipient,\n params.amount\n );\n }\n\n async buildExecutePayload(params: ExecuteParams): Promise<string> {\n return encodeExecuteAction(\n params.target,\n params.value,\n params.data\n );\n }\n\n async buildBridgePayload(params: BridgeParams): Promise<string> {\n return encodeBridgeAction(\n params.token,\n params.amount,\n params.destinationChain,\n params.recipient\n );\n }\n\n async dispatch(\n signature: WebAuthnSignature,\n publicKeyX: bigint,\n publicKeyY: bigint,\n targetChain: number,\n actionPayload: string,\n nonce: bigint,\n signer: any // Solana Keypair or similar\n ): Promise<DispatchResult> {\n void signature;\n void publicKeyX;\n void publicKeyY;\n void targetChain;\n void actionPayload;\n void nonce;\n void signer;\n throw new Error(\n 'Direct dispatch not supported on Solana spoke chains. ' +\n 'Actions must be dispatched from the Hub (EVM) chain. ' +\n 'This client is for receiving cross-chain messages only.'\n );\n }\n\n /**\n * Dispatch an action via relayer (gasless)\n * Note: On Solana, this still goes through the Hub chain\n * Solana is a spoke-only chain in Veridex architecture\n */\n async dispatchGasless(\n signature: WebAuthnSignature,\n publicKeyX: bigint,\n publicKeyY: bigint,\n targetChain: number,\n actionPayload: string,\n nonce: bigint,\n relayerUrl: string\n ): Promise<DispatchResult> {\n // Compute key hash\n const keyHash = this.computeKeyHash(publicKeyX, publicKeyY);\n\n // Build the message that was signed (matches Hub chain format)\n const message = this.buildMessage(keyHash, targetChain, actionPayload, nonce);\n\n // Prepare request for relayer\n const request = {\n messageHash: message,\n r: '0x' + signature.r.toString(16).padStart(64, '0'),\n s: '0x' + signature.s.toString(16).padStart(64, '0'),\n publicKeyX: '0x' + publicKeyX.toString(16).padStart(64, '0'),\n publicKeyY: '0x' + publicKeyY.toString(16).padStart(64, '0'),\n targetChain,\n actionPayload,\n nonce: Number(nonce),\n };\n\n // Submit to relayer\n const response = await fetch(`${relayerUrl}/api/v1/submit`, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n },\n body: JSON.stringify(request),\n });\n\n if (!response.ok) {\n const error = await response.json().catch(() => ({ error: response.statusText }));\n throw new Error(`Relayer submission failed: ${error.error || response.statusText}`);\n }\n\n const result = await response.json();\n\n if (!result.success) {\n throw new Error(`Relayer submission failed: ${result.error}`);\n }\n\n return {\n transactionHash: result.txHash,\n sequence: BigInt(result.sequence || '0'),\n userKeyHash: keyHash,\n targetChain,\n };\n }\n\n async getVaultAddress(userKeyHash: string): Promise<string | null> {\n try {\n const vaultAddress = this.computeVaultAddressFromHash(userKeyHash);\n const accountInfo = await this.connection.getAccountInfo(new PublicKey(vaultAddress));\n\n if (!accountInfo) {\n return null;\n }\n\n return vaultAddress;\n } catch (error) {\n console.error('Error getting vault address:', error);\n return null;\n }\n }\n\n /**\n * Compute vault address using PDA (Program Derived Address)\n * Seeds: [\"vault\", userKeyHash]\n */\n computeVaultAddress(userKeyHash: string): string {\n return this.computeVaultAddressFromHash(userKeyHash);\n }\n\n private computeVaultAddressFromHash(userKeyHash: string): string {\n const userKeyHashBuffer = Buffer.from(userKeyHash.replace('0x', ''), 'hex');\n const [vaultPda] = PublicKey.findProgramAddressSync(\n [Buffer.from('vault'), userKeyHashBuffer],\n this.programId\n );\n return vaultPda.toBase58();\n }\n\n async vaultExists(userKeyHash: string): Promise<boolean> {\n const address = await this.getVaultAddress(userKeyHash);\n return address !== null;\n }\n\n async createVault(userKeyHash: string, signer: any): Promise<VaultCreationResult> {\n void userKeyHash;\n void signer;\n throw new Error(\n 'Vault creation on Solana must be done via relayer. ' +\n 'Use createVaultViaRelayer() instead.'\n );\n }\n\n async createVaultSponsored?(\n userKeyHash: string,\n sponsorPrivateKey: string,\n rpcUrl?: string\n ): Promise<VaultCreationResult> {\n void userKeyHash;\n void sponsorPrivateKey;\n void rpcUrl;\n throw new Error(\n 'Vault creation on Solana must be done via relayer. ' +\n 'Use createVaultViaRelayer() instead.'\n );\n }\n\n /**\n * Create a vault via the relayer (sponsored/gasless)\n * This is the recommended way to create Solana vaults\n */\n async createVaultViaRelayer(\n userKeyHash: string,\n relayerUrl: string\n ): Promise<VaultCreationResult> {\n const response = await fetch(`${relayerUrl}/api/v1/solana/vault`, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n },\n body: JSON.stringify({\n userKeyHash,\n chainId: this.config.wormholeChainId,\n }),\n });\n\n const result = await response.json();\n\n if (!response.ok || !result.success) {\n throw new Error(result.error || 'Failed to create vault via relayer');\n }\n\n return {\n address: result.vaultAddress,\n transactionHash: result.transactionHash || '',\n blockNumber: 0, // Solana doesn't have block numbers like EVM\n gasUsed: 0n, // Solana uses compute units, not gas\n alreadyExisted: !result.transactionHash,\n sponsoredBy: 'relayer',\n };\n }\n\n /**\n * Get vault info via relayer (includes existence check)\n */\n async getVaultViaRelayer(\n userKeyHash: string,\n relayerUrl: string\n ): Promise<{ vaultAddress: string; exists: boolean }> {\n const response = await fetch(\n `${relayerUrl}/api/v1/solana/vault/${userKeyHash}?chainId=${this.config.wormholeChainId}`\n );\n\n if (!response.ok) {\n throw new Error('Failed to get vault info from relayer');\n }\n\n const result = await response.json();\n return {\n vaultAddress: result.vaultAddress,\n exists: result.exists,\n };\n }\n\n async estimateVaultCreationGas(userKeyHash: string): Promise<bigint> {\n void userKeyHash;\n // Return SOL estimate for vault creation (rent + compute)\n // ~0.002 SOL for rent-exempt account + compute units\n return 2_000_000n; // 0.002 SOL in lamports\n }\n\n getFactoryAddress(): string | undefined {\n // Solana uses program addresses, not factory pattern\n return undefined;\n }\n\n getImplementationAddress(): string | undefined {\n // Solana uses program addresses, not implementation pattern\n return undefined;\n }\n\n // ========================================================================\n // Balance Methods\n // ========================================================================\n\n /**\n * Get native SOL balance\n */\n async getNativeBalance(address: string): Promise<bigint> {\n const balance = await this.connection.getBalance(new PublicKey(address));\n return BigInt(balance);\n }\n\n /**\n * Get SPL token balance\n */\n async getTokenBalance(tokenAddress: string, ownerAddress: string): Promise<bigint> {\n try {\n const mint = new PublicKey(tokenAddress);\n const owner = new PublicKey(ownerAddress);\n const ata = getAssociatedTokenAddressSync(mint, owner);\n\n const balance = await this.connection.getTokenAccountBalance(ata);\n return BigInt(balance.value.amount);\n } catch (error) {\n console.error('Error getting token balance:', error);\n return 0n;\n }\n }\n\n // ========================================================================\n // Utility Methods\n // ========================================================================\n\n /**\n * Compute key hash from public key coordinates\n * Matches EVM keccak256(abi.encode(publicKeyX, publicKeyY))\n */\n private computeKeyHash(publicKeyX: bigint, publicKeyY: bigint): string {\n // Use SHA-256 for Solana (Solana doesn't have keccak256 built-in)\n // The relayer will convert this to match EVM format\n const xBuffer = Buffer.alloc(32);\n const yBuffer = Buffer.alloc(32);\n\n // Write as big-endian to match EVM encoding\n const xHex = publicKeyX.toString(16).padStart(64, '0');\n const yHex = publicKeyY.toString(16).padStart(64, '0');\n\n Buffer.from(xHex, 'hex').copy(xBuffer);\n Buffer.from(yHex, 'hex').copy(yBuffer);\n\n // For cross-chain compatibility, we need to match the EVM hash\n // This should be keccak256, but we'll return a format the relayer expects\n const combined = Buffer.concat([xBuffer, yBuffer]);\n const hash = createHash('sha256').update(combined).digest();\n\n return '0x' + hash.toString('hex');\n }\n\n /**\n * Build message for signing (matches Hub chain format)\n */\n private buildMessage(\n keyHash: string,\n targetChain: number,\n actionPayload: string,\n nonce: bigint\n ): string {\n // This should match the EVM message format for cross-chain compatibility\n const keyHashBuffer = Buffer.from(keyHash.replace('0x', ''), 'hex');\n const targetChainBuffer = Buffer.alloc(2);\n targetChainBuffer.writeUInt16BE(targetChain);\n const payloadBuffer = Buffer.from(actionPayload.replace('0x', ''), 'hex');\n const nonceBuffer = Buffer.alloc(32);\n const nonceHex = nonce.toString(16).padStart(64, '0');\n Buffer.from(nonceHex, 'hex').copy(nonceBuffer);\n\n const combined = Buffer.concat([\n keyHashBuffer,\n targetChainBuffer,\n payloadBuffer,\n nonceBuffer,\n ]);\n\n const hash = createHash('sha256').update(combined).digest();\n return '0x' + hash.toString('hex');\n }\n\n /**\n * Get connection instance for advanced usage\n */\n getConnection(): Connection {\n return this.connection;\n }\n\n /**\n * Get program ID\n */\n getProgramId(): PublicKey {\n return this.programId;\n }\n\n /**\n * Get current slot\n */\n async getSlot(): Promise<number> {\n return await this.connection.getSlot();\n }\n\n /**\n * Get transaction status\n */\n async getTransaction(signature: string, commitment?: 'confirmed' | 'finalized') {\n return await this.connection.getTransaction(signature, {\n commitment: commitment || 'confirmed',\n maxSupportedTransactionVersion: 0,\n });\n }\n\n // ============================================================================\n // Social Recovery Methods (Issue #23)\n // ============================================================================\n // \n // Note: Social recovery is managed on the Hub chain (EVM).\n // Solana spokes receive and execute recovery VAAs broadcast from the Hub.\n // These methods are placeholders that indicate spoke-only chains don't\n // initiate recovery - they only execute recovery instructions from Hub VAAs.\n //\n // The relayer service handles:\n // 1. Fetching recovery VAAs from Wormhole guardians\n // 2. Submitting execute_recovery instruction to Solana spoke\n // 3. Processing OwnerRecovered events\n //\n // SDK users should use EVMClient methods for guardian management and\n // recovery initiation on the Hub chain.\n // ============================================================================\n\n /**\n * Check if a recovery VAA has been executed on this spoke\n * \n * @param vaaHash - Hash of the recovery VAA\n * @returns Whether the VAA has been processed\n */\n async isRecoveryExecuted(vaaHash: string): Promise<boolean> {\n try {\n // Derive VAA record PDA\n const vaaHashBuffer = Buffer.from(vaaHash.replace('0x', ''), 'hex');\n const [vaaRecordPda] = PublicKey.findProgramAddressSync(\n [Buffer.from('vaa_record'), vaaHashBuffer],\n this.programId\n );\n\n const accountInfo = await this.connection.getAccountInfo(vaaRecordPda);\n if (!accountInfo || accountInfo.data.length < 9) {\n return false;\n }\n\n // First byte after discriminator is 'processed' bool\n return accountInfo.data[8] === 1;\n } catch (error) {\n console.error('Error checking recovery execution:', error);\n return false;\n }\n }\n\n /**\n * Get vault owner after potential recovery\n * \n * @param vaultAddress - Vault address to check\n * @returns Current owner key hash\n */\n async getVaultOwner(vaultAddress: string): Promise<string> {\n try {\n const accountInfo = await this.connection.getAccountInfo(new PublicKey(vaultAddress));\n if (!accountInfo || accountInfo.data.length < 40) {\n throw new Error('Vault not found');\n }\n\n // Owner key hash is stored after discriminator (8 bytes) at offset 8-40\n const ownerKeyHash = accountInfo.data.slice(8, 40);\n return '0x' + ownerKeyHash.toString('hex');\n } catch (error) {\n console.error('Error getting vault owner:', error);\n throw error;\n }\n }\n\n /**\n * Get authorized signers for a vault\n * \n * @param vaultAddress - Vault address to check\n * @returns Array of authorized signer key hashes\n */\n async getAuthorizedSigners(vaultAddress: string): Promise<string[]> {\n try {\n const accountInfo = await this.connection.getAccountInfo(new PublicKey(vaultAddress));\n if (!accountInfo || accountInfo.data.length < 235) {\n throw new Error('Vault not found');\n }\n\n // Vault layout:\n // 8 bytes discriminator\n // 32 bytes owner_key_hash\n // 8 bytes nonce\n // 1 byte paused\n // 8 bytes daily_limit\n // 8 bytes daily_spent\n // 8 bytes day_start\n // 1 byte bump\n // 1 byte authorized_signer_count\n // 5 * 32 bytes authorized_signers\n\n const signerCount = accountInfo.data[66]; // offset 8+32+8+1+8+8+1 = 66\n const signers: string[] = [];\n\n for (let i = 0; i < signerCount; i++) {\n const offset = 67 + (i * 32); // Start of authorized_signers array\n const keyHash = accountInfo.data.slice(offset, offset + 32);\n signers.push('0x' + keyHash.toString('hex'));\n }\n\n return signers;\n } catch (error) {\n console.error('Error getting authorized signers:', error);\n throw error;\n }\n }\n}\n","/**\n * Veridex Protocol SDK - Payload Encoding/Decoding Utilities\n */\n\nimport { ethers } from 'ethers';\nimport {\n ACTION_TRANSFER,\n ACTION_EXECUTE,\n ACTION_CONFIG,\n ACTION_BRIDGE,\n PROTOCOL_VERSION,\n} from './constants.js';\nimport type { TransferAction, BridgeAction, ExecuteAction, ActionPayload } from './types.js';\n\n// ============================================================================\n// Action Encoding\n// ============================================================================\n\n/**\n * Encode a transfer action payload\n * Format: [actionType(1)] [token(32)] [recipient(32)] [amount(32)]\n */\nexport function encodeTransferAction(\n token: string,\n recipient: string,\n amount: bigint\n): string {\n const tokenPadded = padTo32Bytes(token);\n const recipientPadded = padTo32Bytes(recipient);\n const amountBytes = ethers.zeroPadValue(ethers.toBeHex(amount), 32);\n\n return ethers.concat([\n ethers.toBeHex(ACTION_TRANSFER, 1),\n tokenPadded,\n recipientPadded,\n amountBytes,\n ]);\n}\n\n/**\n * Encode a bridge action payload\n * Format: [actionType(1)] [token(32)] [amount(32)] [targetChain(2)] [recipient(32)]\n */\nexport function encodeBridgeAction(\n token: string,\n amount: bigint,\n targetChain: number,\n recipient: string\n): string {\n const tokenPadded = padTo32Bytes(token);\n const amountBytes = ethers.zeroPadValue(ethers.toBeHex(amount), 32);\n const targetChainBytes = ethers.toBeHex(targetChain, 2);\n const recipientPadded = padTo32Bytes(recipient);\n\n return ethers.concat([\n ethers.toBeHex(ACTION_BRIDGE, 1),\n tokenPadded,\n amountBytes,\n targetChainBytes,\n recipientPadded,\n ]);\n}\n\n/**\n * Encode an execute action payload (arbitrary contract call)\n * Format: [actionType(1)] [target(32)] [value(32)] [dataLength(2)] [data(variable)]\n */\nexport function encodeExecuteAction(\n target: string,\n value: bigint,\n data: string\n): string {\n const targetPadded = padTo32Bytes(target);\n const valueBytes = ethers.zeroPadValue(ethers.toBeHex(value), 32);\n const dataBytes = ethers.getBytes(data);\n const dataLengthBytes = ethers.toBeHex(dataBytes.length, 2);\n\n return ethers.concat([\n ethers.toBeHex(ACTION_EXECUTE, 1),\n targetPadded,\n valueBytes,\n dataLengthBytes,\n data,\n ]);\n}\n\n/**\n * Encode a config action payload\n * Format: [actionType(1)] [configType(1)] [configData(variable)]\n */\nexport function encodeConfigAction(configType: number, configData: string): string {\n return ethers.concat([\n ethers.toBeHex(ACTION_CONFIG, 1),\n ethers.toBeHex(configType, 1),\n configData,\n ]);\n}\n\n// ============================================================================\n// Veridex Payload Encoding\n// ============================================================================\n\n/**\n * Encode the full Veridex message payload that gets published via Wormhole\n * Format: [version(1)] [userKeyHash(32)] [targetChain(2)] [nonce(32)] [pubKeyX(32)] [pubKeyY(32)] [actionPayload]\n */\nexport function encodeVeridexPayload(\n userKeyHash: string,\n targetChain: number,\n nonce: bigint,\n publicKeyX: bigint,\n publicKeyY: bigint,\n actionPayload: string\n): string {\n return ethers.concat([\n ethers.toBeHex(PROTOCOL_VERSION, 1),\n userKeyHash,\n ethers.toBeHex(targetChain, 2),\n ethers.zeroPadValue(ethers.toBeHex(nonce), 32),\n ethers.zeroPadValue(ethers.toBeHex(publicKeyX), 32),\n ethers.zeroPadValue(ethers.toBeHex(publicKeyY), 32),\n actionPayload,\n ]);\n}\n\n// ============================================================================\n// Action Decoding\n// ============================================================================\n\n/**\n * Decode an action payload to determine its type and contents\n */\nexport function decodeActionPayload(payload: string): ActionPayload {\n const data = ethers.getBytes(payload);\n const actionType = data[0];\n\n switch (actionType) {\n case ACTION_TRANSFER:\n return decodeTransferAction(payload);\n case ACTION_BRIDGE:\n return decodeBridgeAction(payload);\n case ACTION_EXECUTE:\n return decodeExecuteAction(payload);\n default:\n return { type: `unknown_${actionType}`, raw: payload };\n }\n}\n\n/**\n * Decode a transfer action payload\n */\nexport function decodeTransferAction(payload: string): TransferAction {\n const data = ethers.getBytes(payload);\n\n const tokenBytes = data.slice(1, 33);\n const recipientBytes = data.slice(33, 65);\n const amountBytes = data.slice(65, 97);\n\n return {\n type: 'transfer',\n token: trimTo20Bytes(ethers.hexlify(tokenBytes)),\n recipient: trimTo20Bytes(ethers.hexlify(recipientBytes)),\n amount: BigInt(ethers.hexlify(amountBytes)),\n };\n}\n\n/**\n * Decode a bridge action payload\n */\nexport function decodeBridgeAction(payload: string): BridgeAction {\n const data = ethers.getBytes(payload);\n\n const tokenBytes = data.slice(1, 33);\n const amountBytes = data.slice(33, 65);\n const targetChainByte0 = data[65];\n const targetChainByte1 = data[66];\n const recipientBytes = data.slice(67, 99);\n\n const targetChain = ((targetChainByte0 ?? 0) << 8) | (targetChainByte1 ?? 0);\n\n return {\n type: 'bridge',\n token: trimTo20Bytes(ethers.hexlify(tokenBytes)),\n amount: BigInt(ethers.hexlify(amountBytes)),\n targetChain,\n recipient: ethers.hexlify(recipientBytes),\n };\n}\n\n/**\n * Decode an execute action payload\n */\nexport function decodeExecuteAction(payload: string): ExecuteAction {\n const data = ethers.getBytes(payload);\n\n const targetBytes = data.slice(1, 33);\n const valueBytes = data.slice(33, 65);\n const dataLengthByte0 = data[65];\n const dataLengthByte1 = data[66];\n const dataLength = ((dataLengthByte0 ?? 0) << 8) | (dataLengthByte1 ?? 0);\n const callData = data.slice(67, 67 + dataLength);\n\n return {\n type: 'execute',\n target: trimTo20Bytes(ethers.hexlify(targetBytes)),\n value: BigInt(ethers.hexlify(valueBytes)),\n data: ethers.hexlify(callData),\n };\n}\n\n// ============================================================================\n// Chain-Specific Encodings\n// ============================================================================\n\n/**\n * Encode a Solana-compatible transfer action\n * Solana uses: [actionType(1)] [amount(8 LE)] [recipient(32)]\n */\nexport function encodeSolanaTransferAction(\n amount: bigint,\n recipient: string\n): string {\n const amountBytes = Buffer.alloc(8);\n amountBytes.writeBigUInt64LE(amount);\n\n const recipientBytes = ethers.getBytes(recipient);\n\n return ethers.hexlify(\n Buffer.concat([\n Buffer.from([ACTION_TRANSFER]),\n amountBytes,\n Buffer.from(recipientBytes),\n ])\n );\n}\n\n/**\n * Encode an Aptos-compatible transfer action\n * Aptos uses: [actionType(1)] [amount(8 LE)] [recipient(32)]\n */\nexport function encodeAptosTransferAction(\n amount: bigint,\n recipient: string\n): string {\n const amountBytes = Buffer.alloc(8);\n amountBytes.writeBigUInt64LE(amount);\n\n const recipientPadded = padTo32Bytes(recipient);\n\n return ethers.hexlify(\n Buffer.concat([\n Buffer.from([ACTION_TRANSFER]),\n amountBytes,\n Buffer.from(ethers.getBytes(recipientPadded)),\n ])\n );\n}\n\n/**\n * Encode a Sui-compatible transfer action\n * Sui uses: [actionType(1)] [amount(8 LE)] [recipient(32)]\n */\nexport function encodeSuiTransferAction(\n amount: bigint,\n recipient: string\n): string {\n const amountBytes = Buffer.alloc(8);\n amountBytes.writeBigUInt64LE(amount);\n\n const recipientPadded = padTo32Bytes(recipient);\n\n return ethers.hexlify(\n Buffer.concat([\n Buffer.from([ACTION_TRANSFER]),\n amountBytes,\n Buffer.from(ethers.getBytes(recipientPadded)),\n ])\n );\n}\n\n// ============================================================================\n// Address Utilities\n// ============================================================================\n\n/**\n * Pad an address to 32 bytes (Wormhole standard)\n * Supports both EVM addresses (0x...) and Solana addresses (base58)\n */\nexport function padTo32Bytes(address: string): string {\n // Handle native token - convert to zero address\n if (address.toLowerCase() === 'native') {\n return '0x' + '0'.repeat(64);\n }\n \n // If it starts with 0x, treat as hex\n if (address.startsWith('0x')) {\n const hex = address.replace('0x', '');\n // Validate that hex only contains valid hex characters\n if (!/^[0-9a-fA-F]*$/.test(hex)) {\n throw new Error(`Invalid address: ${address}. Expected hex string or 'native'.`);\n }\n return '0x' + hex.padStart(64, '0');\n }\n \n // Otherwise, assume base58 Solana address and decode it\n // Base58 character set (Bitcoin/Solana style - no 0, O, I, l)\n const base58Chars = '123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz';\n \n // Validate base58 characters\n for (const char of address) {\n if (!base58Chars.includes(char)) {\n throw new Error(`Invalid address: ${address}. Contains invalid base58 character '${char}'.`);\n }\n }\n \n // Decode base58 to bytes\n let value = BigInt(0);\n for (const char of address) {\n value = value * 58n + BigInt(base58Chars.indexOf(char));\n }\n \n // Convert to 32-byte hex\n let hex = value.toString(16);\n // Ensure it's not longer than 64 chars (32 bytes)\n if (hex.length > 64) {\n throw new Error(`Invalid address: ${address}. Decoded value too large for 32 bytes.`);\n }\n \n return '0x' + hex.padStart(64, '0');\n}\n\n/**\n * Trim a 32-byte hex to a 20-byte EVM address\n */\nexport function trimTo20Bytes(hex32: string): string {\n const clean = hex32.replace('0x', '');\n return '0x' + clean.slice(-40);\n}\n\n/**\n * Convert a Solana public key (base58) to bytes32\n * @deprecated Use padTo32Bytes instead, which now handles both EVM and Solana addresses\n */\nexport function solanaAddressToBytes32(base58Address: string): string {\n return padTo32Bytes(base58Address);\n}\n\n// ============================================================================\n// Amount Utilities\n// ============================================================================\n\n/**\n * Format an amount with decimals for display\n */\nexport function formatAmount(amount: bigint, decimals = 18): string {\n const divisor = 10n ** BigInt(decimals);\n const whole = amount / divisor;\n const fraction = amount % divisor;\n\n if (fraction === 0n) {\n return whole.toString();\n }\n\n const fractionStr = fraction.toString().padStart(decimals, '0');\n const trimmedFraction = fractionStr.replace(/0+$/, '');\n\n return `${whole}.${trimmedFraction}`;\n}\n\n/**\n * Parse an amount string with decimals to bigint\n */\nexport function parseAmount(amountStr: string, decimals = 18): bigint {\n const parts = amountStr.split('.');\n const whole = BigInt(parts[0] ?? '0');\n\n if (parts.length === 1 || !parts[1]) {\n return whole * (10n ** BigInt(decimals));\n }\n\n const fractionStr = parts[1].slice(0, decimals).padEnd(decimals, '0');\n const fraction = BigInt(fractionStr);\n\n return whole * (10n ** BigInt(decimals)) + fraction;\n}\n\n// ============================================================================\n// Nonce Utilities\n// ============================================================================\n\n/**\n * Generate a unique nonce for a transaction\n */\nexport function generateNonce(): bigint {\n const timestamp = BigInt(Date.now());\n const random = BigInt(Math.floor(Math.random() * 1000000));\n return (timestamp << 20n) | random;\n}\n\n/**\n * Create a message hash for signing (used in authenticateRawAndDispatch)\n */\nexport function createMessageHash(\n targetChain: number,\n actionPayload: string,\n nonce: bigint\n): string {\n return ethers.keccak256(\n ethers.solidityPacked(\n ['uint16', 'bytes', 'uint256'],\n [targetChain, actionPayload, nonce]\n )\n );\n}\n\n/**\n * Create the challenge bytes for gasless dispatch (matches Hub's authenticateAndDispatch)\n * \n * The Hub contract passes raw packed bytes to WebAuthn.verify():\n * abi.encodePacked(targetChain, actionPayload, userNonce, hubChainId)\n * \n * The WebAuthn library then base64url-encodes these bytes to match against clientDataJSON.\n * We do NOT hash here - the challenge is the raw packed bytes.\n * \n * @param targetChain - Wormhole chain ID of the destination\n * @param actionPayload - The action payload (hex string)\n * @param nonce - User's current nonce\n * @param hubChainId - Wormhole chain ID of the Hub (e.g., 30 for Base)\n * @returns The packed bytes as hex string (NOT hashed)\n */\nexport function createGaslessMessageHash(\n targetChain: number,\n actionPayload: string,\n nonce: bigint,\n hubChainId: number\n): string {\n // Return raw packed bytes - NO sha256 hash\n // The contract passes these bytes directly to WebAuthn.verify()\n return ethers.solidityPacked(\n ['uint16', 'bytes', 'uint256', 'uint16'],\n [targetChain, actionPayload, nonce, hubChainId]\n );\n}\n\n/**\n * Build the challenge bytes for WebAuthn signing (gasless flow)\n * Returns raw packed bytes that match what the Hub contract expects\n * \n * @param targetChain - Wormhole chain ID of the destination\n * @param actionPayload - The action payload (hex string)\n * @param nonce - User's current nonce\n * @param hubChainId - Wormhole chain ID of the Hub\n * @returns Challenge bytes for WebAuthn signing (raw packed, not hashed)\n */\nexport function buildGaslessChallenge(\n targetChain: number,\n actionPayload: string,\n nonce: bigint,\n hubChainId: number\n): Uint8Array {\n const packed = createGaslessMessageHash(targetChain, actionPayload, nonce, hubChainId);\n return ethers.getBytes(packed);\n}\n\n/**\n * Build the challenge bytes for WebAuthn signing\n */\nexport function buildChallenge(\n userKeyHash: string,\n targetChain: number,\n nonce: bigint,\n actionPayload: string\n): Uint8Array {\n const encoded = ethers.solidityPacked(\n ['bytes32', 'uint16', 'uint256', 'bytes'],\n [userKeyHash, targetChain, nonce, actionPayload]\n );\n return ethers.getBytes(ethers.keccak256(encoded));\n}\n","/**\n * Veridex Protocol SDK - Aptos Chain Client\n * \n * Implementation of ChainClient interface for Aptos blockchain\n */\n\nimport { AptosClient as AptosSDK, Types } from 'aptos';\nimport { sha3_256 } from 'js-sha3';\nimport type {\n ChainClient,\n ChainConfig,\n TransferParams,\n ExecuteParams,\n BridgeParams,\n DispatchResult,\n WebAuthnSignature,\n VaultCreationResult,\n} from '../../core/types.js';\nimport { encodeTransferAction, encodeExecuteAction, encodeBridgeAction } from '../../payload.js';\n\n// ============================================================================\n// Types\n// ============================================================================\n\nexport interface AptosClientConfig {\n wormholeChainId: number;\n rpcUrl: string;\n moduleAddress: string; // Veridex Spoke module address\n wormholeCoreBridge: string;\n tokenBridge: string;\n network?: 'mainnet' | 'testnet' | 'devnet';\n}\n\n// ============================================================================\n// Constants\n// ============================================================================\n\n// ============================================================================\n// AptosClient Class\n// ============================================================================\n\n/**\n * Aptos implementation of the ChainClient interface\n */\nexport class AptosClient implements ChainClient {\n private config: ChainConfig;\n private client: AptosSDK;\n private moduleAddress: string;\n\n constructor(config: AptosClientConfig) {\n this.config = {\n name: `Aptos ${config.network || 'mainnet'}`,\n chainId: config.wormholeChainId,\n wormholeChainId: config.wormholeChainId,\n rpcUrl: config.rpcUrl,\n explorerUrl: config.network === 'testnet'\n ? 'https://explorer.aptoslabs.com?network=testnet'\n : 'https://explorer.aptoslabs.com',\n isEvm: false,\n contracts: {\n hub: undefined, // Aptos is a spoke only\n wormholeCoreBridge: config.wormholeCoreBridge,\n tokenBridge: config.tokenBridge,\n },\n };\n\n this.client = new AptosSDK(config.rpcUrl);\n this.moduleAddress = config.moduleAddress;\n }\n\n getConfig(): ChainConfig {\n return this.config;\n }\n\n async getNonce(userKeyHash: string): Promise<bigint> {\n try {\n const vaultAddress = this.computeVaultAddressFromHash(userKeyHash);\n\n // Query vault resource\n const resource = await this.client.getAccountResource(\n vaultAddress,\n `${this.moduleAddress}::vault::Vault`\n );\n\n if (resource && resource.data) {\n const data = resource.data as any;\n return BigInt(data.nonce || 0);\n }\n\n return 0n;\n } catch (error) {\n console.error('Error getting nonce:', error);\n return 0n;\n }\n }\n\n async getMessageFee(): Promise<bigint> {\n try {\n // Query Wormhole bridge for message fee\n // For now, return a default estimate\n // TODO: Query on-chain Wormhole config\n return 0n; // Aptos doesn't charge a Wormhole fee in the same way\n } catch (error) {\n console.error('Error getting message fee:', error);\n return 0n;\n }\n }\n\n async buildTransferPayload(params: TransferParams): Promise<string> {\n return encodeTransferAction(\n params.token,\n params.recipient,\n params.amount\n );\n }\n\n async buildExecutePayload(params: ExecuteParams): Promise<string> {\n return encodeExecuteAction(\n params.target,\n params.value,\n params.data\n );\n }\n\n async buildBridgePayload(params: BridgeParams): Promise<string> {\n return encodeBridgeAction(\n params.token,\n params.amount,\n params.destinationChain,\n params.recipient\n );\n }\n\n async dispatch(\n signature: WebAuthnSignature,\n publicKeyX: bigint,\n publicKeyY: bigint,\n targetChain: number,\n actionPayload: string,\n nonce: bigint,\n signer: any // Aptos AptosAccount\n ): Promise<DispatchResult> {\n void signature;\n void publicKeyX;\n void publicKeyY;\n void targetChain;\n void actionPayload;\n void nonce;\n void signer;\n throw new Error(\n 'Direct dispatch not supported on Aptos spoke chains. ' +\n 'Actions must be dispatched from the Hub (EVM) chain. ' +\n 'This client is for receiving cross-chain messages only.'\n );\n }\n\n /**\n * Dispatch an action via relayer (gasless)\n * Note: On Aptos, this still goes through the Hub chain\n * Aptos is a spoke-only chain in Veridex architecture\n */\n async dispatchGasless(\n signature: WebAuthnSignature,\n publicKeyX: bigint,\n publicKeyY: bigint,\n targetChain: number,\n actionPayload: string,\n nonce: bigint,\n relayerUrl: string\n ): Promise<DispatchResult> {\n // Compute key hash\n const keyHash = this.computeKeyHash(publicKeyX, publicKeyY);\n\n // Build the message that was signed (matches Hub chain format)\n const message = this.buildMessage(keyHash, targetChain, actionPayload, nonce);\n\n // Prepare request for relayer\n const request = {\n messageHash: message,\n r: '0x' + signature.r.toString(16).padStart(64, '0'),\n s: '0x' + signature.s.toString(16).padStart(64, '0'),\n publicKeyX: '0x' + publicKeyX.toString(16).padStart(64, '0'),\n publicKeyY: '0x' + publicKeyY.toString(16).padStart(64, '0'),\n targetChain,\n actionPayload,\n nonce: Number(nonce),\n };\n\n // Submit to relayer\n const response = await fetch(`${relayerUrl}/api/v1/submit`, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n },\n body: JSON.stringify(request),\n });\n\n if (!response.ok) {\n const error = await response.json().catch(() => ({ error: response.statusText }));\n throw new Error(`Relayer submission failed: ${error.error || response.statusText}`);\n }\n\n const result = await response.json();\n\n if (!result.success) {\n throw new Error(`Relayer submission failed: ${result.error}`);\n }\n\n return {\n transactionHash: result.txHash,\n sequence: BigInt(result.sequence || '0'),\n userKeyHash: keyHash,\n targetChain,\n };\n }\n\n /**\n * Get vault address from on-chain VaultRegistry.\n * Queries the get_vault_address view function which looks up the vault in the registry.\n */\n async getVaultAddress(userKeyHash: string): Promise<string | null> {\n try {\n // Query the on-chain VaultRegistry via view function\n // Module is veridex::spoke (not veridex_spoke)\n // Normalize keyHash to 0x-prefixed 64-char hex string\n const normalizedKeyHash = '0x' + userKeyHash.replace('0x', '').padStart(64, '0');\n \n const payload = {\n function: `${this.moduleAddress}::spoke::get_vault_address`,\n type_arguments: [],\n arguments: [normalizedKeyHash], // Pass as hex string, not byte array\n };\n\n const response = await this.client.view(payload);\n \n if (response && response.length > 0) {\n const vaultAddress = response[0] as string;\n return vaultAddress;\n }\n\n return null;\n } catch (error: any) {\n // E_VAULT_NOT_FOUND (error code 6) means vault doesn't exist in registry\n if (error?.message?.includes('E_VAULT_NOT_FOUND') || \n error?.message?.includes('error code 6') ||\n error?.status === 404) {\n return null;\n }\n console.error('Error getting vault address from registry:', error);\n return null;\n }\n }\n\n /**\n * @deprecated Use getVaultAddress() instead - this method uses incorrect address derivation.\n * On Aptos, vaults are created as named objects by the relayer, not resource accounts.\n * The vault address depends on which relayer created it, so must be queried on-chain.\n */\n computeVaultAddress(userKeyHash: string): string {\n console.warn(\n 'computeVaultAddress() is deprecated for Aptos. ' +\n 'Use getVaultAddress() to query the on-chain VaultRegistry instead.'\n );\n return this.computeVaultAddressFromHash(userKeyHash);\n }\n\n private computeVaultAddressFromHash(userKeyHash: string): string {\n // NOTE: This is kept for backward compatibility but produces INCORRECT addresses!\n // Aptos spoke uses object::create_named_object(creator, key_hash) where:\n // - creator = relayer address (not module address)\n // - scheme = 0xFD (named object, not 0xFE resource account)\n // The correct approach is to query the VaultRegistry on-chain.\n\n const sourceAddress = this.hexToBytes(this.moduleAddress.replace('0x', ''));\n const seed = this.hexToBytes(userKeyHash.replace('0x', ''));\n const scheme = new Uint8Array([0xFE]); // INCORRECT - kept for backward compat\n\n const combined = new Uint8Array([...sourceAddress, ...seed, ...scheme]);\n const hash = sha3_256(combined);\n\n return '0x' + hash;\n }\n\n /**\n * Convert hex string to Uint8Array (browser-compatible)\n */\n private hexToBytes(hex: string): Uint8Array {\n const bytes = new Uint8Array(hex.length / 2);\n for (let i = 0; i < hex.length; i += 2) {\n bytes[i / 2] = parseInt(hex.substr(i, 2), 16);\n }\n return bytes;\n }\n\n async vaultExists(userKeyHash: string): Promise<boolean> {\n const address = await this.getVaultAddress(userKeyHash);\n return address !== null;\n }\n\n async createVault(userKeyHash: string, signer: any): Promise<VaultCreationResult> {\n void userKeyHash;\n void signer;\n throw new Error(\n 'Vault creation on Aptos must be done via cross-chain message from Hub. ' +\n 'Use the Hub chain client to dispatch a vault creation action targeting Aptos.'\n );\n }\n\n async createVaultSponsored?(\n userKeyHash: string,\n sponsorPrivateKey: string,\n rpcUrl?: string\n ): Promise<VaultCreationResult> {\n void userKeyHash;\n void sponsorPrivateKey;\n void rpcUrl;\n throw new Error(\n 'Vault creation on Aptos must be done via cross-chain message from Hub. ' +\n 'Use relayer gasless submission to create vault.'\n );\n }\n\n /**\n * Create a vault via the relayer (sponsored/gasless)\n * This is the recommended way to create Aptos vaults\n * \n * The relayer will dispatch a vault creation action from Hub to Aptos spoke\n */\n async createVaultViaRelayer(\n userKeyHash: string,\n relayerUrl: string\n ): Promise<VaultCreationResult> {\n const response = await fetch(`${relayerUrl}/api/v1/aptos/vault`, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n },\n body: JSON.stringify({\n userKeyHash,\n chainId: this.config.wormholeChainId,\n }),\n });\n\n const result = await response.json();\n\n if (!response.ok || !result.success) {\n throw new Error(result.error || 'Failed to create vault via relayer');\n }\n\n return {\n address: result.vaultAddress,\n transactionHash: result.transactionHash || '',\n blockNumber: 0,\n gasUsed: 0n,\n alreadyExisted: result.alreadyExists || false,\n sponsoredBy: 'relayer',\n };\n }\n\n /**\n * Get vault info via relayer (includes existence check)\n */\n async getVaultViaRelayer(\n userKeyHash: string,\n relayerUrl: string\n ): Promise<{ vaultAddress: string; exists: boolean }> {\n const response = await fetch(\n `${relayerUrl}/api/v1/aptos/vault/${userKeyHash}?chainId=${this.config.wormholeChainId}`\n );\n\n if (!response.ok) {\n throw new Error('Failed to get vault info from relayer');\n }\n\n const result = await response.json();\n return {\n vaultAddress: result.vaultAddress,\n exists: result.exists,\n };\n }\n\n async estimateVaultCreationGas(userKeyHash: string): Promise<bigint> {\n void userKeyHash;\n // Return APT estimate for vault creation\n // ~0.001 APT for account creation + gas\n return 100_000n; // 0.001 APT in octas (1 APT = 100M octas)\n }\n\n getFactoryAddress(): string | undefined {\n // Aptos uses module addresses, not factory pattern\n return undefined;\n }\n\n getImplementationAddress(): string | undefined {\n // Aptos uses module addresses, not implementation pattern\n return undefined;\n }\n\n // ========================================================================\n // Balance Methods\n // ========================================================================\n\n /**\n * Get native APT balance\n */\n async getNativeBalance(address: string): Promise<bigint> {\n try {\n const resource = await this.client.getAccountResource(\n address,\n '0x1::coin::CoinStore<0x1::aptos_coin::AptosCoin>'\n );\n\n if (resource && resource.data) {\n const data = resource.data as any;\n return BigInt(data.coin?.value || 0);\n }\n\n return 0n;\n } catch (error) {\n console.error('Error getting native balance:', error);\n return 0n;\n }\n }\n\n /**\n * Get fungible asset (FA) or coin balance\n */\n async getTokenBalance(tokenAddress: string, ownerAddress: string): Promise<bigint> {\n try {\n // Try as Coin type first\n const coinType = tokenAddress.includes('::')\n ? tokenAddress\n : `${tokenAddress}::coin::Coin`;\n\n const resource = await this.client.getAccountResource(\n ownerAddress,\n `0x1::coin::CoinStore<${coinType}>`\n );\n\n if (resource && resource.data) {\n const data = resource.data as any;\n return BigInt(data.coin?.value || 0);\n }\n\n return 0n;\n } catch (error) {\n // If Coin query fails, try Fungible Asset (FA) format\n try {\n // FA balances are stored differently\n // Would need to query the FA resource\n console.warn('FA balance query not fully implemented yet');\n return 0n;\n } catch (faError) {\n console.error('Error getting token balance:', error);\n return 0n;\n }\n }\n }\n\n // ========================================================================\n // Utility Methods\n // ========================================================================\n\n /**\n * Compute key hash from public key coordinates\n * Matches EVM keccak256(abi.encode(publicKeyX, publicKeyY))\n */\n private computeKeyHash(publicKeyX: bigint, publicKeyY: bigint): string {\n // Write as big-endian to match EVM encoding\n const xHex = publicKeyX.toString(16).padStart(64, '0');\n const yHex = publicKeyY.toString(16).padStart(64, '0');\n\n const xBytes = this.hexToBytes(xHex);\n const yBytes = this.hexToBytes(yHex);\n\n // Use SHA3-256 for Aptos (which is what Aptos uses natively)\n // For cross-chain compatibility, this should match the EVM hash\n const combined = new Uint8Array([...xBytes, ...yBytes]);\n const hash = sha3_256(combined);\n\n return '0x' + hash;\n }\n\n /**\n * Build message for signing (matches Hub chain format)\n */\n private buildMessage(\n keyHash: string,\n targetChain: number,\n actionPayload: string,\n nonce: bigint\n ): string {\n const keyHashBytes = this.hexToBytes(keyHash.replace('0x', ''));\n const targetChainBytes = new Uint8Array(2);\n targetChainBytes[0] = (targetChain >> 8) & 0xFF;\n targetChainBytes[1] = targetChain & 0xFF;\n const payloadBytes = this.hexToBytes(actionPayload.replace('0x', ''));\n const nonceHex = nonce.toString(16).padStart(64, '0');\n const nonceBytes = this.hexToBytes(nonceHex);\n\n const combined = new Uint8Array([\n ...keyHashBytes,\n ...targetChainBytes,\n ...payloadBytes,\n ...nonceBytes,\n ]);\n\n const hash = sha3_256(combined);\n return '0x' + hash;\n }\n\n /**\n * Get Aptos client instance for advanced usage\n */\n getClient(): AptosSDK {\n return this.client;\n }\n\n /**\n * Get module address\n */\n getModuleAddress(): string {\n return this.moduleAddress;\n }\n\n /**\n * Get current ledger version\n */\n async getLedgerVersion(): Promise<bigint> {\n const ledgerInfo = await this.client.getLedgerInfo();\n return BigInt(ledgerInfo.ledger_version);\n }\n\n /**\n * Get transaction by hash\n */\n async getTransaction(txHash: string): Promise<Types.Transaction> {\n return await this.client.getTransactionByHash(txHash);\n }\n\n /**\n * Wait for transaction confirmation\n */\n async waitForTransaction(txHash: string, timeoutSecs: number = 30): Promise<Types.Transaction> {\n return await this.client.waitForTransactionWithResult(txHash, {\n timeoutSecs,\n checkSuccess: true,\n });\n }\n\n // ============================================================================\n // Social Recovery Methods (Issue #23)\n // ============================================================================\n // \n // Note: Social recovery is managed on the Hub chain (EVM).\n // Aptos spokes receive and execute recovery VAAs broadcast from the Hub.\n // The relayer service handles submitting recovery transactions to Aptos.\n //\n // SDK users should use EVMClient methods for guardian management and\n // recovery initiation on the Hub chain.\n // ============================================================================\n\n /**\n * Get vault resource for an owner\n * \n * @param ownerKeyHash - Owner's passkey hash (32 bytes as hex)\n * @returns Vault resource data or null if not found\n */\n async getVaultResource(ownerKeyHash: string): Promise<{\n ownerKeyHash: string;\n authorizedSigners: string[];\n nonce: bigint;\n } | null> {\n try {\n const vaultAddress = this.computeVaultAddressFromHash(ownerKeyHash);\n\n const resource = await this.client.getAccountResource(\n vaultAddress,\n `${this.moduleAddress}::vault::Vault`\n );\n\n if (!resource || !resource.data) {\n return null;\n }\n\n const data = resource.data as any;\n return {\n ownerKeyHash: data.owner_key_hash || ownerKeyHash,\n authorizedSigners: data.authorized_signers || [],\n nonce: BigInt(data.nonce || 0),\n };\n } catch (error) {\n console.error('Error getting vault resource:', error);\n return null;\n }\n }\n\n /**\n * Get authorized signers for a vault\n * \n * @param ownerKeyHash - Owner's passkey hash (32 bytes as hex)\n * @returns Array of authorized signer key hashes\n */\n async getAuthorizedSigners(ownerKeyHash: string): Promise<string[]> {\n const vaultResource = await this.getVaultResource(ownerKeyHash);\n return vaultResource?.authorizedSigners || [];\n }\n\n /**\n * Check if a VAA has been processed (for replay protection)\n * \n * @param vaaHash - VAA hash as hex string\n * @returns Whether the VAA has been processed\n */\n async isVaaProcessed(vaaHash: string): Promise<boolean> {\n try {\n const resource = await this.client.getAccountResource(\n this.moduleAddress,\n `${this.moduleAddress}::spoke::ProcessedVAAs`\n );\n\n if (!resource || !resource.data) {\n return false;\n }\n\n const data = resource.data as any;\n const processedVaas = data.processed || [];\n\n // Check if vaaHash is in the processed list\n const normalizedHash = vaaHash.toLowerCase().replace('0x', '');\n return processedVaas.some((hash: string) => \n hash.toLowerCase().replace('0x', '') === normalizedHash\n );\n } catch (error) {\n console.error('Error checking VAA status:', error);\n return false;\n }\n }\n\n /**\n * Check if protocol is paused\n * \n * @returns Whether the protocol is paused\n */\n async isProtocolPaused(): Promise<boolean> {\n try {\n const resource = await this.client.getAccountResource(\n this.moduleAddress,\n `${this.moduleAddress}::spoke::Config`\n );\n\n if (!resource || !resource.data) {\n return false;\n }\n\n const data = resource.data as any;\n return data.paused === true;\n } catch (error) {\n console.error('Error checking pause status:', error);\n return false;\n }\n }\n}\n","/**\n * Veridex Protocol SDK - Sui Chain Client\n *\n * Production-grade implementation of ChainClient interface for Sui.\n * Supports session management, query-based execution, and vault operations.\n *\n * Security:\n * - Native sui::ecdsa_k1::secp256k1_verify for signature validation\n * - CCQ-based session validation with 60s staleness window\n * - Replay protection via nonce verification\n *\n * Note: Sui is a spoke chain. Session registration/revocation happens on Hub.\n */\n\nimport { SuiClient as MystenSuiClient } from '@mysten/sui/client';\nimport { createHash } from 'crypto';\nimport type { SessionKey } from '../../sessions/types.js';\nimport type {\n ChainClient,\n ChainConfig,\n TransferParams,\n ExecuteParams,\n BridgeParams,\n DispatchResult,\n WebAuthnSignature,\n VaultCreationResult,\n RegisterSessionParams,\n RevokeSessionParams,\n SessionValidationResult,\n} from '../../core/types.js';\nimport { encodeTransferAction, encodeExecuteAction, encodeBridgeAction } from '../../payload.js';\n\n// ============================================================================\n// Types\n// ============================================================================\n\nexport interface SuiClientConfig {\n wormholeChainId: number;\n rpcUrl: string;\n packageId: string; // Veridex Spoke package ID\n wormholeCoreBridge: string;\n tokenBridge?: string;\n network?: 'mainnet' | 'testnet' | 'devnet';\n hubRpcUrl?: string; // Hub chain RPC for session management\n hubContractAddress?: string; // Hub contract for session management\n}\n\n// ============================================================================\n// SuiClient\n// ============================================================================\n\nexport class SuiClient implements ChainClient {\n private config: ChainConfig;\n private client: MystenSuiClient;\n private packageId: string;\n private hubRpcUrl?: string;\n private hubContractAddress?: string;\n\n constructor(config: SuiClientConfig) {\n this.config = {\n name: `Sui ${config.network || 'mainnet'}`,\n chainId: 0,\n wormholeChainId: config.wormholeChainId,\n rpcUrl: config.rpcUrl,\n explorerUrl: config.network === 'testnet'\n ? 'https://suiscan.xyz/testnet'\n : config.network === 'devnet'\n ? 'https://suiscan.xyz/devnet'\n : 'https://suiscan.xyz/mainnet',\n isEvm: false,\n contracts: {\n hub: config.packageId,\n wormholeCoreBridge: config.wormholeCoreBridge,\n tokenBridge: config.tokenBridge,\n },\n };\n\n this.client = new MystenSuiClient({ url: config.rpcUrl });\n this.packageId = config.packageId;\n this.hubRpcUrl = config.hubRpcUrl;\n this.hubContractAddress = config.hubContractAddress;\n }\n\n getConfig(): ChainConfig {\n return this.config;\n }\n\n async getNonce(_userKeyHash: string): Promise<bigint> {\n // Nonce is managed on the Hub for cross-chain actions.\n return 0n;\n }\n\n async getMessageFee(): Promise<bigint> {\n // Wormhole fees for Sui are generally handled by relayer submission.\n return 0n;\n }\n\n async buildTransferPayload(params: TransferParams): Promise<string> {\n return encodeTransferAction(params.token, params.recipient, params.amount);\n }\n\n async buildExecutePayload(params: ExecuteParams): Promise<string> {\n return encodeExecuteAction(params.target, params.value, params.data);\n }\n\n async buildBridgePayload(params: BridgeParams): Promise<string> {\n return encodeBridgeAction(params.token, params.amount, params.destinationChain, params.recipient);\n }\n\n async dispatch(\n signature: WebAuthnSignature,\n publicKeyX: bigint,\n publicKeyY: bigint,\n targetChain: number,\n actionPayload: string,\n nonce: bigint,\n signer: any\n ): Promise<DispatchResult> {\n void signature;\n void publicKeyX;\n void publicKeyY;\n void targetChain;\n void actionPayload;\n void nonce;\n void signer;\n throw new Error(\n 'Direct dispatch not supported on Sui spoke chains. ' +\n 'Actions must be dispatched from the Hub (EVM) chain. '\n );\n }\n\n async dispatchGasless(\n signature: WebAuthnSignature,\n publicKeyX: bigint,\n publicKeyY: bigint,\n targetChain: number,\n actionPayload: string,\n nonce: bigint,\n relayerUrl: string\n ): Promise<DispatchResult> {\n const keyHash = this.computeKeyHash(publicKeyX, publicKeyY);\n const messageHash = this.buildMessageHash(keyHash, targetChain, actionPayload, nonce);\n\n const request = {\n messageHash,\n r: '0x' + signature.r.toString(16).padStart(64, '0'),\n s: '0x' + signature.s.toString(16).padStart(64, '0'),\n publicKeyX: '0x' + publicKeyX.toString(16).padStart(64, '0'),\n publicKeyY: '0x' + publicKeyY.toString(16).padStart(64, '0'),\n targetChain,\n actionPayload,\n nonce: Number(nonce),\n };\n\n const response = await fetch(`${relayerUrl}/api/v1/submit`, {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify(request),\n });\n\n if (!response.ok) {\n throw new Error(`Relayer submission failed: ${response.status} ${response.statusText}`);\n }\n\n const result = await response.json();\n\n return {\n transactionHash: result.transactionHash ?? result.txHash,\n sequence: BigInt(result.sequence || 0),\n userKeyHash: keyHash,\n targetChain,\n };\n }\n\n async getVaultAddress(userKeyHash: string): Promise<string | null> {\n // Sui vaults may be represented as shared objects on-chain; without registry object IDs,\n // we return the deterministic address used by the SDK for receiving and balance display.\n return this.computeVaultAddress(userKeyHash);\n }\n\n computeVaultAddress(userKeyHash: string): string {\n // SDK convention: Sui addresses are 32-byte hex with 0x prefix.\n const clean = userKeyHash.replace(/^0x/, '').padStart(64, '0');\n return '0x' + clean;\n }\n\n async vaultExists(_userKeyHash: string): Promise<boolean> {\n // Account addresses on Sui are implicit; treat as existing.\n return true;\n }\n\n async createVault(userKeyHash: string, signer: any): Promise<VaultCreationResult> {\n void signer;\n throw new Error(\n 'Vault creation on Sui must be done via cross-chain message from Hub. ' +\n `Use the Hub client to dispatch a vault creation action targeting Sui (chain ${this.config.wormholeChainId}). KeyHash=${userKeyHash}`\n );\n }\n\n async createVaultSponsored?(userKeyHash: string, sponsorPrivateKey: string, rpcUrl?: string): Promise<VaultCreationResult> {\n void userKeyHash;\n void sponsorPrivateKey;\n void rpcUrl;\n throw new Error(\n 'Vault creation on Sui must be done via cross-chain message from Hub. ' +\n 'Use relayer gasless submission to create vault.'\n );\n }\n\n /**\n * Create a vault via the relayer (sponsored/gasless)\n * This is the recommended way to create Sui vaults\n * \n * The relayer will dispatch a vault creation action from Hub to Sui spoke\n */\n async createVaultViaRelayer(\n userKeyHash: string,\n relayerUrl: string\n ): Promise<VaultCreationResult> {\n const response = await fetch(`${relayerUrl}/api/v1/sui/vault`, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n },\n body: JSON.stringify({\n userKeyHash,\n chainId: this.config.wormholeChainId,\n }),\n });\n\n const result = await response.json();\n\n if (!response.ok || !result.success) {\n throw new Error(result.error || 'Failed to create vault via relayer');\n }\n\n return {\n address: result.vaultAddress,\n transactionHash: result.transactionHash || '',\n blockNumber: 0,\n gasUsed: 0n,\n alreadyExisted: result.alreadyExists || false,\n sponsoredBy: 'relayer',\n };\n }\n\n /**\n * Get vault info via relayer (includes existence check)\n */\n async getVaultViaRelayer(\n userKeyHash: string,\n relayerUrl: string\n ): Promise<{ vaultAddress: string; exists: boolean }> {\n const response = await fetch(\n `${relayerUrl}/api/v1/sui/vault/${userKeyHash}?chainId=${this.config.wormholeChainId}`\n );\n\n if (!response.ok) {\n throw new Error('Failed to get vault info from relayer');\n }\n\n const result = await response.json();\n return {\n vaultAddress: result.vaultAddress,\n exists: result.exists,\n };\n }\n\n async estimateVaultCreationGas(_userKeyHash: string): Promise<bigint> {\n // Best-effort placeholder.\n return 5_000n;\n }\n\n getFactoryAddress(): string | undefined {\n return undefined;\n }\n\n getImplementationAddress(): string | undefined {\n return undefined;\n }\n\n // ========================================================================\n // Balance utilities (used by VeridexSDK multichain)\n // ========================================================================\n\n async getNativeBalance(address: string): Promise<bigint> {\n const balance = await this.client.getBalance({ owner: address });\n return BigInt(balance.totalBalance);\n }\n\n async getTokenBalance(coinType: string, ownerAddress: string): Promise<bigint> {\n const balance = await this.client.getBalance({ owner: ownerAddress, coinType });\n return BigInt(balance.totalBalance);\n }\n\n getClient(): MystenSuiClient {\n return this.client;\n }\n\n getPackageId(): string {\n return this.packageId;\n }\n\n // ========================================================================\n // Session Management (Issue #13)\n // ========================================================================\n\n /**\n * Register a session key on the Hub (must be called via Hub client)\n * Sui spokes validate sessions via CCQ, but registration happens on Hub\n * \n * @throws Error - Session management must be done via Hub chain\n */\n async registerSession(_params: RegisterSessionParams): Promise<void> {\n throw new Error(\n 'Session registration must be performed on the Hub chain (Base). ' +\n 'Use EVMClient connected to the Hub to call registerSession().'\n );\n }\n\n /**\n * Revoke a session key on the Hub (must be called via Hub client)\n * \n * @throws Error - Session management must be done via Hub chain\n */\n async revokeSession(_params: RevokeSessionParams): Promise<void> {\n throw new Error(\n 'Session revocation must be performed on the Hub chain (Base). ' +\n 'Use EVMClient connected to the Hub to call revokeSession().'\n );\n }\n\n /**\n * Check if a session is active by querying the Hub\n * This method queries the Hub contract directly for session validation\n * \n * @param userKeyHash - Hash of user's Passkey public key\n * @param sessionKeyHash - Hash of session key to validate\n * @returns Session validation result with expiry and limits\n */\n async isSessionActive(\n _userKeyHash: string,\n _sessionKeyHash: string\n ): Promise<SessionValidationResult> {\n if (!this.hubRpcUrl || !this.hubContractAddress) {\n throw new Error(\n 'Hub configuration required for session validation. ' +\n 'Provide hubRpcUrl and hubContractAddress in SuiClientConfig.'\n );\n }\n\n // Query Hub contract for session status\n // This would normally use ethers.js to query the Hub contract\n // For production, import ethers dynamically or pass Hub client\n throw new Error(\n 'isSessionActive requires Hub client integration. ' +\n 'Use EVMClient.isSessionActive() on the Hub chain, ' +\n 'then pass the result to session execution on Sui.'\n );\n }\n\n /**\n * Get all sessions for a user from the Hub\n * \n * @param userKeyHash - Hash of user's Passkey public key\n * @returns Array of all sessions (active and expired/revoked)\n */\n async getUserSessions(userKeyHash: string): Promise<SessionKey[]> {\n if (!this.hubRpcUrl || !this.hubContractAddress) {\n throw new Error(\n 'Hub configuration required for session queries. ' +\n 'Provide hubRpcUrl and hubContractAddress in SuiClientConfig.'\n );\n }\n\n // Query Hub contract for user sessions\n throw new Error(\n 'getUserSessions requires Hub client integration. ' +\n 'Use EVMClient.getUserSessions() on the Hub chain. ' +\n `User: ${userKeyHash}`\n );\n }\n\n // ========================================================================\n // Query-Based Execution (Issue #9/#10)\n // ========================================================================\n\n /**\n * Get user state from Hub (comprehensive state query)\n * Returns key hash, nonce, and last action hash for CCQ validation\n * \n * @param userKeyHash - Hash of user's Passkey public key\n * @returns User state with nonce and last action hash\n */\n async getUserState(userKeyHash: string): Promise<{\n keyHash: string;\n nonce: bigint;\n lastActionHash: string;\n }> {\n if (!this.hubRpcUrl || !this.hubContractAddress) {\n throw new Error(\n 'Hub configuration required for state queries. ' +\n 'Provide hubRpcUrl and hubContractAddress in SuiClientConfig.'\n );\n }\n\n // Query Hub contract for user state\n // This enables query-based execution with CCQ validation\n throw new Error(\n 'getUserState requires Hub client integration. ' +\n 'Use EVMClient.getUserState() on the Hub chain. ' +\n `User: ${userKeyHash}`\n );\n }\n\n /**\n * Get user's last action hash from Hub\n * Used for optimistic execution and nonce validation\n * \n * @param userKeyHash - Hash of user's Passkey public key\n * @returns Last action hash (zero hash if no actions)\n */\n async getUserLastActionHash(userKeyHash: string): Promise<string> {\n if (!this.hubRpcUrl || !this.hubContractAddress) {\n throw new Error(\n 'Hub configuration required for action hash queries. ' +\n 'Provide hubRpcUrl and hubContractAddress in SuiClientConfig.'\n );\n }\n\n // Query Hub contract for last action hash\n throw new Error(\n 'getUserLastActionHash requires Hub client integration. ' +\n 'Use EVMClient.getUserLastActionHash() on the Hub chain. ' +\n `User: ${userKeyHash}`\n );\n }\n\n /**\n * Execute with query-based validation (faster than VAA, ~23s vs 60-90s)\n * Uses Wormhole CCQ to validate Hub state, then executes on Sui\n * \n * @param params Query execution parameters with CCQ response\n * @returns Dispatch result with transaction hash\n * \n * @remarks\n * Query-based execution flow:\n * 1. Query Hub state via Wormhole CCQ\n * 2. Validate Guardian signatures on query response\n * 3. Execute on Sui with validated state\n * 4. Hub state must be < 60s stale (enforced by QueryVerifier)\n */\n async executeWithQuery(\n _params: {\n userKeyHash: string;\n queryResponse: Uint8Array; // CCQ Guardian response\n actionType: number;\n actionPayload: Uint8Array;\n relayerUrl?: string;\n }\n ): Promise<DispatchResult> {\n throw new Error(\n 'Query-based execution on Sui requires relayer integration. ' +\n 'Use relayer API to submit query-validated transactions. ' +\n 'Relayer will call veridex_spoke::execute_with_query on Sui.'\n );\n }\n\n // ========================================================================\n // Internal helpers\n // ========================================================================\n\n private computeKeyHash(publicKeyX: bigint, publicKeyY: bigint): string {\n const xHex = publicKeyX.toString(16).padStart(64, '0');\n const yHex = publicKeyY.toString(16).padStart(64, '0');\n const combined = Buffer.from(xHex + yHex, 'hex');\n const hash = createHash('sha256').update(combined).digest('hex');\n return '0x' + hash;\n }\n\n private buildMessageHash(keyHash: string, targetChain: number, actionPayload: string, nonce: bigint): string {\n const keyHashBuffer = Buffer.from(keyHash.replace(/^0x/, ''), 'hex');\n const targetChainBuffer = Buffer.alloc(2);\n targetChainBuffer.writeUInt16BE(targetChain);\n const payloadBuffer = Buffer.from(actionPayload.replace(/^0x/, ''), 'hex');\n const nonceHex = nonce.toString(16).padStart(64, '0');\n const nonceBuffer = Buffer.from(nonceHex, 'hex');\n\n const combined = Buffer.concat([keyHashBuffer, targetChainBuffer, payloadBuffer, nonceBuffer]);\n const hash = createHash('sha256').update(combined).digest('hex');\n return '0x' + hash;\n }\n\n // ============================================================================\n // Social Recovery Methods (Issue #23)\n // ============================================================================\n // \n // Note: Social recovery is managed on the Hub chain (EVM).\n // Sui spokes receive and execute recovery VAAs broadcast from the Hub.\n // The relayer service handles submitting recovery transactions to Sui.\n //\n // SDK users should use EVMClient methods for guardian management and\n // recovery initiation on the Hub chain.\n // ============================================================================\n\n /**\n * Get vault object ID by owner key hash\n * \n * @param ownerKeyHash - Owner's passkey hash (32 bytes as hex)\n * @param configObjectId - Shared Config object ID\n * @param registryObjectId - Shared VaultRegistry object ID\n * @returns Vault object ID or null if not found\n */\n async getVaultId(\n ownerKeyHash: string,\n registryObjectId: string\n ): Promise<string | null> {\n try {\n // Query the VaultRegistry table for the owner_key_hash\n // The registry maps owner_key_hash -> vault ID\n const registryObject = await this.client.getObject({\n id: registryObjectId,\n options: { showContent: true },\n });\n\n if (!registryObject.data?.content) {\n return null;\n }\n\n // For a proper implementation, we'd need to query dynamic fields\n // or use a Move view function. This is a placeholder showing the pattern.\n console.warn('getVaultId requires dynamic field query - use Move view function');\n return null;\n } catch (error) {\n console.error('Error getting vault ID:', error);\n return null;\n }\n }\n\n /**\n * Get vault owner key hash from vault object\n * \n * @param vaultObjectId - Vault object ID\n * @returns Owner key hash as hex string\n */\n async getVaultOwner(vaultObjectId: string): Promise<string | null> {\n try {\n const vaultObject = await this.client.getObject({\n id: vaultObjectId,\n options: { showContent: true },\n });\n\n if (!vaultObject.data?.content || vaultObject.data.content.dataType !== 'moveObject') {\n return null;\n }\n\n const fields = vaultObject.data.content.fields as Record<string, unknown>;\n const ownerKeyHash = fields['owner_key_hash'] as number[] | undefined;\n\n if (!ownerKeyHash) {\n return null;\n }\n\n // Convert byte array to hex string\n return '0x' + Buffer.from(ownerKeyHash).toString('hex');\n } catch (error) {\n console.error('Error getting vault owner:', error);\n return null;\n }\n }\n\n /**\n * Get authorized signers for a vault\n * \n * @param vaultObjectId - Vault object ID\n * @returns Array of authorized signer key hashes\n */\n async getAuthorizedSigners(vaultObjectId: string): Promise<string[]> {\n try {\n const vaultObject = await this.client.getObject({\n id: vaultObjectId,\n options: { showContent: true },\n });\n\n if (!vaultObject.data?.content || vaultObject.data.content.dataType !== 'moveObject') {\n return [];\n }\n\n const fields = vaultObject.data.content.fields as Record<string, unknown>;\n const authorizedSigners = fields['authorized_signers'] as number[][] | undefined;\n\n if (!authorizedSigners) {\n return [];\n }\n\n // Convert each byte array to hex string\n return authorizedSigners.map(signer => \n '0x' + Buffer.from(signer).toString('hex')\n );\n } catch (error) {\n console.error('Error getting authorized signers:', error);\n return [];\n }\n }\n\n /**\n * Check if a VAA has been processed (for replay protection)\n * \n * @param vaaHash - VAA hash as hex string\n * @param processedVaasObjectId - ProcessedVAAs shared object ID\n * @returns Whether the VAA has been processed\n */\n async isVaaProcessed(\n vaaHash: string,\n processedVaasObjectId: string\n ): Promise<boolean> {\n try {\n const processedObject = await this.client.getObject({\n id: processedVaasObjectId,\n options: { showContent: true },\n });\n\n if (!processedObject.data?.content) {\n return false;\n }\n\n // Would need to query dynamic field for vaaHash key\n console.warn('isVaaProcessed requires dynamic field query');\n return false;\n } catch (error) {\n console.error('Error checking VAA status:', error);\n return false;\n }\n }\n\n /**\n * Check if protocol is paused\n * \n * @param configObjectId - Config shared object ID\n * @returns Whether the protocol is paused\n */\n async isProtocolPaused(configObjectId: string): Promise<boolean> {\n try {\n const configObject = await this.client.getObject({\n id: configObjectId,\n options: { showContent: true },\n });\n\n if (!configObject.data?.content || configObject.data.content.dataType !== 'moveObject') {\n return false;\n }\n\n const fields = configObject.data.content.fields as Record<string, unknown>;\n return fields['paused'] === true;\n } catch (error) {\n console.error('Error checking pause status:', error);\n return false;\n }\n }\n}\n","/**\n * Veridex Protocol SDK - Starknet Chain Client\n *\n * Production-grade implementation of ChainClient interface for Starknet.\n * Supports custom bridge attestation, gasless execution via Hub dispatch.\n *\n * Security:\n * - Native starknet::eth_signature::verify_eth_signature for validation\n * - Custom bridge with multi-relayer threshold attestations\n * - Replay protection via nonce verification on Hub\n * - Bridge validates source_chain == hub_chain_id (10004 = Base Sepolia)\n *\n * Architecture:\n * - Starknet actions MUST be dispatched via Hub (Base Sepolia)\n * - Hub publishes Wormhole message → relayer monitors → relayer submits attestation\n * - Bridge accumulates attestations → threshold reached → spoke executes\n * - Spoke validates source_chain == hubChainId (NOT targetChain)\n * \n * Custom Bridge:\n * - Bridge address: 0x2c458c1ae64556482b05cc2d3ee5b032ed114d68429dda2062c9849a5a725f8\n * - Chain ID: 50001 (custom range 50000+, reserved for non-Wormhole chains)\n * - Hub Chain ID: 10004 (Base Sepolia - what bridge validates as source)\n */\n\nimport type { SessionKey } from '../../sessions/types.js';\nimport type {\n ChainClient,\n ChainConfig,\n TransferParams,\n ExecuteParams,\n BridgeParams,\n DispatchResult,\n WebAuthnSignature,\n VaultCreationResult,\n RegisterSessionParams,\n RevokeSessionParams,\n SessionValidationResult,\n} from '../../core/types.js';\nimport { createHash } from 'crypto';\nimport { RpcProvider } from 'starknet';\nimport { encodeTransferAction, encodeExecuteAction, encodeBridgeAction } from '../../payload.js';\n\n// ============================================================================\n// Constants\n// ============================================================================\n\n// Starknet felt252 max value is 2^252 - 1\nconst FELT252_MAX = BigInt('0x0800000000000000000000000000000000000000000000000000000000000000') - 1n;\n\n// 2^128 for splitting u256 into low/high\nconst U128_MAX = BigInt('0x100000000000000000000000000000000');\n\n/**\n * Convert a 256-bit keyHash to Starknet u256 format (low, high felt252 pair).\n * Starknet u256 is represented as two felt252 values: (low_128_bits, high_128_bits)\n * \n * @param keyHash - 256-bit hex string (with or without 0x prefix)\n * @returns Array of two hex strings [low, high] for Starknet calldata\n */\nfunction toStarknetU256(keyHash: string): [string, string] {\n const cleanHash = keyHash.replace('0x', '').padStart(64, '0');\n const value = BigInt('0x' + cleanHash);\n \n // Split into low 128 bits and high 128 bits\n const low = value % U128_MAX;\n const high = value / U128_MAX;\n \n return [\n '0x' + low.toString(16),\n '0x' + high.toString(16)\n ];\n}\n\n/**\n * Truncate a 256-bit keyHash to fit within Starknet's felt252 (252-bit) field.\n * Clears the top 4 bits to ensure the value is < 2^252.\n * \n * @param keyHash - 256-bit hex string (with or without 0x prefix)\n * @returns felt252-compatible hex string with 0x prefix\n */\nfunction toStarknetFelt(keyHash: string): string {\n const cleanHash = keyHash.replace('0x', '');\n const value = BigInt('0x' + cleanHash);\n // Mask to felt252 range (clear top 4 bits)\n const masked = value & FELT252_MAX;\n return '0x' + masked.toString(16);\n}\n\n// ============================================================================\n// Types\n// ============================================================================\n\nexport interface StarknetClientConfig {\n wormholeChainId: number;\n rpcUrl: string;\n spokeContractAddress?: string;\n bridgeContractAddress?: string;\n network?: 'mainnet' | 'sepolia' | 'testnet';\n hubRpcUrl?: string; // Hub chain RPC for session management\n hubContractAddress?: string; // Hub contract for session management\n}\n\n// ============================================================================\n// StarknetClient\n// ============================================================================\n\nexport class StarknetClient implements ChainClient {\n private config: ChainConfig;\n private provider: RpcProvider;\n private hubRpcUrl?: string;\n private hubContractAddress?: string;\n\n constructor(config: StarknetClientConfig) {\n this.config = {\n name: `Starknet ${config.network || 'mainnet'}`,\n chainId: 0,\n wormholeChainId: config.wormholeChainId,\n rpcUrl: config.rpcUrl,\n explorerUrl: config.network === 'sepolia'\n ? 'https://sepolia.starkscan.co'\n : 'https://starkscan.co',\n isEvm: false,\n contracts: {\n hub: config.spokeContractAddress,\n wormholeCoreBridge: config.bridgeContractAddress ?? '',\n },\n };\n\n this.hubRpcUrl = config.hubRpcUrl;\n this.hubContractAddress = config.hubContractAddress;\n\n this.provider = new RpcProvider({ nodeUrl: config.rpcUrl });\n }\n\n getConfig(): ChainConfig {\n return this.config;\n }\n\n async getNonce(_userKeyHash: string): Promise<bigint> {\n return 0n;\n }\n\n async getMessageFee(): Promise<bigint> {\n return 0n;\n }\n\n async buildTransferPayload(params: TransferParams): Promise<string> {\n return encodeTransferAction(params.token, params.recipient, params.amount);\n }\n\n async buildExecutePayload(params: ExecuteParams): Promise<string> {\n return encodeExecuteAction(params.target, params.value, params.data);\n }\n\n async buildBridgePayload(params: BridgeParams): Promise<string> {\n return encodeBridgeAction(params.token, params.amount, params.destinationChain, params.recipient);\n }\n\n async dispatch(\n signature: WebAuthnSignature,\n publicKeyX: bigint,\n publicKeyY: bigint,\n targetChain: number,\n actionPayload: string,\n nonce: bigint,\n signer: any\n ): Promise<DispatchResult> {\n void signature;\n void publicKeyX;\n void publicKeyY;\n void targetChain;\n void actionPayload;\n void nonce;\n void signer;\n throw new Error(\n 'Direct dispatch not supported on Starknet. ' +\n 'Starknet actions are executed via the Veridex Hub (Base Sepolia) + custom bridge. ' +\n 'Use dispatchGasless() to route through relayer, which will submit attestations to the bridge.'\n );\n }\n\n async dispatchGasless(\n signature: WebAuthnSignature,\n publicKeyX: bigint,\n publicKeyY: bigint,\n targetChain: number,\n actionPayload: string,\n nonce: bigint,\n relayerUrl: string\n ): Promise<DispatchResult> {\n /**\n * Starknet gasless execution flow:\n * 1. User signs action with passkey (on client)\n * 2. SDK submits to relayer with targetChain=50001 (Starknet)\n * 3. Relayer dispatches to Hub (Base Sepolia) with targetChain=50001\n * 4. Hub publishes Wormhole message\n * 5. Relayer monitors Hub Dispatch event\n * 6. Relayer submits attestation to Starknet Bridge\n * 7. Bridge accumulates attestations from multiple relayers\n * 8. When threshold reached, Bridge calls spoke.execute()\n * 9. Spoke validates source_chain == hubChainId (10004)\n * 10. Spoke executes action on user's vault\n * \n * Result: Completely gasless for user - relayer pays all fees\n */\n const keyHash = this.computeKeyHash(publicKeyX, publicKeyY);\n\n // Submit to relayer for Hub dispatch + bridge attestation\n const request = {\n signature: {\n r: '0x' + signature.r.toString(16).padStart(64, '0'),\n s: '0x' + signature.s.toString(16).padStart(64, '0'),\n authenticatorData: signature.authenticatorData,\n clientDataJSON: signature.clientDataJSON,\n challengeIndex: signature.challengeIndex,\n typeIndex: signature.typeIndex,\n },\n publicKeyX: '0x' + publicKeyX.toString(16).padStart(64, '0'),\n publicKeyY: '0x' + publicKeyY.toString(16).padStart(64, '0'),\n targetChain, // 50001 for Starknet\n actionPayload,\n userNonce: Number(nonce),\n };\n\n const response = await fetch(`${relayerUrl}/api/v1/submit`, {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify(request),\n });\n\n if (!response.ok) {\n const errorText = await response.text().catch(() => 'Unknown error');\n throw new Error(\n `Relayer submission failed: ${response.status} ${response.statusText}. ` +\n `Error: ${errorText}`\n );\n }\n\n const result = await response.json();\n\n return {\n transactionHash: result.transactionHash ?? result.txHash ?? result.hubTxHash,\n sequence: BigInt(result.sequence || 0),\n userKeyHash: keyHash,\n targetChain,\n };\n }\n\n // Note: getVaultAddress is now defined in the Social Recovery section below\n // with enhanced spoke contract querying support.\n\n computeVaultAddress(userKeyHash: string): string {\n /**\n * Starknet vault derivation:\n * - Vaults are created via spoke contract\n * - Address is deterministic from userKeyHash\n * - Uses keyHash directly as vault identifier (felt252)\n * \n * Note: Actual vault address on Starknet may differ based on\n * spoke implementation. This is a best-effort derivation.\n */\n const clean = userKeyHash.replace(/^0x/, '');\n return '0x' + clean;\n }\n\n async vaultExists(userKeyHash: string): Promise<boolean> {\n /**\n * Check if vault exists on Starknet spoke\n * Best-effort: queries spoke contract if available\n */\n if (!this.config.contracts.hub) {\n return false;\n }\n\n try {\n const vaultAddress = await this.getVaultAddress(userKeyHash);\n if (!vaultAddress) {\n return false;\n }\n\n // Query Starknet RPC for contract code at vault address\n const anyProvider = this.provider as any;\n if (typeof anyProvider.getClassHashAt === 'function') {\n await anyProvider.getClassHashAt(vaultAddress);\n return true;\n }\n } catch {\n // Vault doesn't exist or RPC doesn't support query\n }\n\n return false;\n }\n\n async createVault(userKeyHash: string, signer: any): Promise<VaultCreationResult> {\n void signer;\n throw new Error(\n 'Vault creation on Starknet must be done via Hub dispatch + custom bridge attestation. ' +\n 'Use Hub client (Base Sepolia) to dispatch a CREATE_VAULT action with targetChain=50001. ' +\n `KeyHash=${userKeyHash}`\n );\n }\n\n async createVaultSponsored?(userKeyHash: string, sponsorPrivateKey: string, rpcUrl?: string): Promise<VaultCreationResult> {\n void userKeyHash;\n void sponsorPrivateKey;\n void rpcUrl;\n throw new Error(\n 'Vault creation on Starknet must be done via Hub dispatch + custom bridge attestation. ' +\n 'Use Hub client (Base Sepolia) with sponsor key to dispatch CREATE_VAULT action.'\n );\n }\n\n /**\n * Create a vault via the relayer (sponsored/gasless)\n * This is the recommended way to create Starknet vaults\n * \n * The relayer will dispatch a vault creation action from Hub via custom bridge to Starknet spoke\n */\n async createVaultViaRelayer(\n userKeyHash: string,\n relayerUrl: string\n ): Promise<VaultCreationResult> {\n const response = await fetch(`${relayerUrl}/api/v1/starknet/vault`, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n },\n body: JSON.stringify({\n userKeyHash,\n chainId: this.config.wormholeChainId,\n }),\n });\n\n const result = await response.json();\n\n if (!response.ok || !result.success) {\n throw new Error(result.error || 'Failed to create vault via relayer');\n }\n\n return {\n address: result.vaultAddress,\n transactionHash: result.transactionHash || '',\n blockNumber: 0,\n gasUsed: 0n,\n alreadyExisted: result.alreadyExists || false,\n sponsoredBy: 'relayer',\n };\n }\n\n /**\n * Get vault info via relayer (includes existence check)\n */\n async getVaultViaRelayer(\n userKeyHash: string,\n relayerUrl: string\n ): Promise<{ vaultAddress: string; exists: boolean }> {\n const response = await fetch(\n `${relayerUrl}/api/v1/starknet/vault/${userKeyHash}?chainId=${this.config.wormholeChainId}`\n );\n\n if (!response.ok) {\n throw new Error('Failed to get vault info from relayer');\n }\n\n const result = await response.json();\n return {\n vaultAddress: result.vaultAddress,\n exists: result.exists,\n };\n }\n\n async estimateVaultCreationGas(_userKeyHash: string): Promise<bigint> {\n return 0n;\n }\n\n getFactoryAddress(): string | undefined {\n return undefined;\n }\n\n getImplementationAddress(): string | undefined {\n return undefined;\n }\n\n // ========================================================================\n // Balance utility (best-effort)\n // ========================================================================\n\n async getNativeBalance(address: string): Promise<bigint> {\n // Best-effort: some Starknet RPCs support getBalance, but it is not universal.\n try {\n const anyProvider = this.provider as any;\n if (typeof anyProvider.getBalance === 'function') {\n const res = await anyProvider.getBalance(address);\n return BigInt(res);\n }\n } catch {\n // ignore\n }\n return 0n;\n }\n\n getProvider(): RpcProvider {\n return this.provider;\n }\n\n // ========================================================================\n // Session Management (Issue #13)\n // ========================================================================\n\n /**\n * Register a session key on the Hub (must be called via Hub client)\n * Starknet spokes validate sessions via CCQ, but registration happens on Hub\n * \n * @throws Error - Session management must be done via Hub chain\n */\n async registerSession(_params: RegisterSessionParams): Promise<void> {\n throw new Error(\n 'Session registration must be performed on the Hub chain (Base). ' +\n 'Use EVMClient connected to the Hub to call registerSession().'\n );\n }\n\n /**\n * Revoke a session key on the Hub (must be called via Hub client)\n * \n * @throws Error - Session management must be done via Hub chain\n */\n async revokeSession(_params: RevokeSessionParams): Promise<void> {\n throw new Error(\n 'Session revocation must be performed on the Hub chain (Base). ' +\n 'Use EVMClient connected to the Hub to call revokeSession().'\n );\n }\n\n /**\n * Check if a session is active by querying the Hub\n * This method queries the Hub contract directly for session validation\n * \n * @param userKeyHash - Hash of user's Passkey public key\n * @param sessionKeyHash - Hash of session key to validate\n * @returns Session validation result with expiry and limits\n */\n async isSessionActive(\n userKeyHash: string,\n sessionKeyHash: string\n ): Promise<SessionValidationResult> {\n if (!this.hubRpcUrl || !this.hubContractAddress) {\n throw new Error(\n 'Hub configuration required for session validation. ' +\n 'Provide hubRpcUrl and hubContractAddress in StarknetClientConfig.'\n );\n }\n\n // Query Hub contract for session status\n throw new Error(\n 'isSessionActive requires Hub client integration. ' +\n 'Use EVMClient.isSessionActive() on the Hub chain, ' +\n 'then pass the result to session execution on Starknet.'\n );\n }\n\n /**\n * Get all sessions for a user from the Hub\n * \n * @param userKeyHash - Hash of user's Passkey public key\n * @returns Array of all sessions (active and expired/revoked)\n */\n async getUserSessions(userKeyHash: string): Promise<SessionKey[]> {\n if (!this.hubRpcUrl || !this.hubContractAddress) {\n throw new Error(\n 'Hub configuration required for session queries. ' +\n 'Provide hubRpcUrl and hubContractAddress in StarknetClientConfig.'\n );\n }\n\n // Query Hub contract for user sessions\n throw new Error(\n 'getUserSessions requires Hub client integration. ' +\n 'Use EVMClient.getUserSessions() on the Hub chain. ' +\n `User: ${userKeyHash}`\n );\n }\n\n // ========================================================================\n // Query-Based Execution (Issue #9/#10)\n // ========================================================================\n\n /**\n * Get user state from Hub (comprehensive state query)\n * Returns key hash, nonce, and last action hash for CCQ validation\n * \n * @param userKeyHash - Hash of user's Passkey public key\n * @returns User state with nonce and last action hash\n */\n async getUserState(userKeyHash: string): Promise<{\n keyHash: string;\n nonce: bigint;\n lastActionHash: string;\n }> {\n if (!this.hubRpcUrl || !this.hubContractAddress) {\n throw new Error(\n 'Hub configuration required for state queries. ' +\n 'Provide hubRpcUrl and hubContractAddress in StarknetClientConfig.'\n );\n }\n\n // Query Hub contract for user state\n throw new Error(\n 'getUserState requires Hub client integration. ' +\n 'Use EVMClient.getUserState() on the Hub chain. ' +\n `User: ${userKeyHash}`\n );\n }\n\n /**\n * Get user's last action hash from Hub\n * Used for optimistic execution and nonce validation\n * \n * @param userKeyHash - Hash of user's Passkey public key\n * @returns Last action hash (zero hash if no actions)\n */\n async getUserLastActionHash(userKeyHash: string): Promise<string> {\n if (!this.hubRpcUrl || !this.hubContractAddress) {\n throw new Error(\n 'Hub configuration required for action hash queries. ' +\n 'Provide hubRpcUrl and hubContractAddress in StarknetClientConfig.'\n );\n }\n\n // Query Hub contract for last action hash\n throw new Error(\n 'getUserLastActionHash requires Hub client integration. ' +\n 'Use EVMClient.getUserLastActionHash() on the Hub chain. ' +\n `User: ${userKeyHash}`\n );\n }\n\n /**\n * Execute with query-based validation (faster than VAA, ~23s vs 60-90s)\n * Uses Wormhole CCQ to validate Hub state, then executes on Starknet\n * \n * @param params Query execution parameters with CCQ response\n * @returns Dispatch result with transaction hash\n * \n * @remarks\n * Query-based execution flow:\n * 1. Query Hub state via Wormhole CCQ\n * 2. Validate Guardian signatures on query response\n * 3. Execute on Starknet with validated state\n * 4. Hub state must be < 60s stale (enforced by QueryVerifier)\n */\n async executeWithQuery(\n _params: {\n userKeyHash: string;\n queryResponse: Uint8Array; // CCQ Guardian response\n actionType: number;\n actionPayload: Uint8Array;\n relayerUrl?: string;\n }\n ): Promise<DispatchResult> {\n throw new Error(\n 'Query-based execution on Starknet requires relayer integration. ' +\n 'Use relayer API to submit query-validated transactions. ' +\n 'Relayer will call veridex_spoke::execute_with_query on Starknet.'\n );\n }\n\n // ========================================================================\n // Internal helpers\n // ========================================================================\n\n private computeKeyHash(publicKeyX: bigint, publicKeyY: bigint): string {\n const xHex = publicKeyX.toString(16).padStart(64, '0');\n const yHex = publicKeyY.toString(16).padStart(64, '0');\n const combined = Buffer.from(xHex + yHex, 'hex');\n const hash = createHash('sha256').update(combined).digest('hex');\n return '0x' + hash;\n }\n\n private buildMessageHash(keyHash: string, targetChain: number, actionPayload: string, nonce: bigint): string {\n const keyHashBuffer = Buffer.from(keyHash.replace(/^0x/, ''), 'hex');\n const targetChainBuffer = Buffer.alloc(2);\n targetChainBuffer.writeUInt16BE(targetChain);\n const payloadBuffer = Buffer.from(actionPayload.replace(/^0x/, ''), 'hex');\n const nonceHex = nonce.toString(16).padStart(64, '0');\n const nonceBuffer = Buffer.from(nonceHex, 'hex');\n\n const combined = Buffer.concat([keyHashBuffer, targetChainBuffer, payloadBuffer, nonceBuffer]);\n const hash = createHash('sha256').update(combined).digest('hex');\n return '0x' + hash;\n }\n\n // ============================================================================\n // Social Recovery Methods (Issue #23)\n // ============================================================================\n // \n // Note: Social recovery is managed on the Hub chain (EVM).\n // Starknet spokes receive and execute recovery VAAs broadcast from the Hub.\n // The relayer service handles submitting recovery transactions to Starknet.\n //\n // SDK users should use EVMClient methods for guardian management and\n // recovery initiation on the Hub chain.\n // ============================================================================\n\n /**\n * Get vault address by owner key hash\n * \n * @param ownerKeyHash - Owner's passkey hash\n * @returns Vault address on Starknet (felt252 as hex string)\n */\n async getVaultAddress(ownerKeyHash: string): Promise<string | null> {\n try {\n const spokeAddress = this.config.contracts.hub;\n if (!spokeAddress) {\n throw new Error('Spoke contract address not configured');\n }\n\n // Starknet spoke expects u256 (low, high) format for keyHash\n const [low, high] = toStarknetU256(ownerKeyHash);\n\n // Call get_vault on spoke contract with u256 split into [low, high]\n const result = await this.provider.callContract({\n contractAddress: spokeAddress,\n entrypoint: 'get_vault',\n calldata: [low, high],\n });\n\n // result[0] is the vault address (0 if not found)\n const vaultAddress = result[0];\n if (vaultAddress === '0x0' || vaultAddress === '0') {\n return null;\n }\n\n return vaultAddress;\n } catch (error) {\n console.error('Error getting vault address:', error);\n return null;\n }\n }\n\n /**\n * Check if vault exists and get basic info\n * \n * @param ownerKeyHash - Owner's passkey hash \n * @returns Vault info or null if not found\n */\n async getVaultInfo(ownerKeyHash: string): Promise<{\n address: string;\n ownerKeyHash: string;\n } | null> {\n const vaultAddress = await this.getVaultAddress(ownerKeyHash);\n if (!vaultAddress) {\n return null;\n }\n\n return {\n address: vaultAddress,\n ownerKeyHash,\n };\n }\n\n /**\n * Check if spoke contract is paused\n * \n * @returns Whether the protocol is paused\n */\n async isProtocolPaused(): Promise<boolean> {\n try {\n const spokeAddress = this.config.contracts.hub;\n if (!spokeAddress) {\n throw new Error('Spoke contract address not configured');\n }\n\n const result = await this.provider.callContract({\n contractAddress: spokeAddress,\n entrypoint: 'is_paused',\n calldata: [],\n });\n\n return result[0] === '0x1' || result[0] === '1';\n } catch (error) {\n console.error('Error checking pause status:', error);\n return false;\n }\n }\n}\n","/**\n * Veridex Protocol SDK - Chain Detector\n *\n * Phase 4: Multi-chain client support helper.\n *\n * Provides:\n * - Chain config lookup (testnet/mainnet)\n * - Auto-configuration for non-EVM ChainClient instances\n */\n\nimport type { ChainClient, ChainConfig, PasskeyCredential, ChainAddress } from './types.js';\nimport { TESTNET_CHAINS, MAINNET_CHAINS } from '../constants.js';\nimport { WalletManager } from './WalletManager.js';\nimport { SolanaClient } from '../chains/solana/SolanaClient.js';\nimport { AptosClient } from '../chains/aptos/AptosClient.js';\nimport { SuiClient } from '../chains/sui/SuiClient.js';\nimport { StarknetClient } from '../chains/starknet/StarknetClient.js';\n\nexport interface ChainDetectorConfig {\n testnet?: boolean;\n rpcUrls?: Record<number, string>;\n}\n\nexport interface NativeBalanceCapable {\n getNativeBalance(address: string): Promise<bigint>;\n}\n\nconst NON_EVM_NATIVE_META: Record<number, { symbol: string; name: string; decimals: number }> = {\n 1: { symbol: 'SOL', name: 'Solana', decimals: 9 },\n 21: { symbol: 'SUI', name: 'Sui', decimals: 9 },\n 22: { symbol: 'APT', name: 'Aptos', decimals: 8 },\n};\n\nexport class ChainDetector {\n private readonly testnet: boolean;\n private readonly rpcUrls: Record<number, string>;\n private readonly walletManager: WalletManager;\n\n constructor(config: ChainDetectorConfig = {}) {\n this.testnet = config.testnet ?? true;\n this.rpcUrls = config.rpcUrls ?? {};\n this.walletManager = new WalletManager({ cacheAddresses: true, persistToStorage: false });\n }\n\n getChainConfig(wormholeChainId: number): ChainConfig | undefined {\n const chains = this.testnet ? TESTNET_CHAINS : MAINNET_CHAINS;\n return Object.values(chains).find(c => c.wormholeChainId === wormholeChainId);\n }\n\n /**\n * Create a chain client for non-EVM chains using repo constants.\n * For EVM, callers should instantiate EVMClient directly (Hub-driven).\n */\n createClient(wormholeChainId: number): ChainClient {\n const chain = this.getChainConfig(wormholeChainId);\n if (!chain) {\n throw new Error(`Unknown chain (wormholeChainId=${wormholeChainId})`);\n }\n\n const rpcUrl = this.rpcUrls[wormholeChainId] ?? chain.rpcUrl;\n\n if (chain.isEvm) {\n throw new Error(\n `EVM chain auto-detection is not supported here (wormholeChainId=${wormholeChainId}). ` +\n 'Instantiate EVMClient with hubContractAddress/vaultFactory/vaultImplementation explicitly.'\n );\n }\n\n switch (wormholeChainId) {\n case 1: {\n const programId = chain.contracts.hub;\n if (!programId || !chain.contracts.tokenBridge) {\n throw new Error('Solana config missing programId/tokenBridge in constants');\n }\n return new SolanaClient({\n wormholeChainId,\n rpcUrl,\n programId,\n wormholeCoreBridge: chain.contracts.wormholeCoreBridge,\n tokenBridge: chain.contracts.tokenBridge,\n network: this.testnet ? 'devnet' : 'mainnet',\n });\n }\n case 22: {\n const moduleAddress = chain.contracts.hub;\n if (!moduleAddress || !chain.contracts.tokenBridge) {\n throw new Error('Aptos config missing moduleAddress/tokenBridge in constants');\n }\n return new AptosClient({\n wormholeChainId,\n rpcUrl,\n moduleAddress,\n wormholeCoreBridge: chain.contracts.wormholeCoreBridge,\n tokenBridge: chain.contracts.tokenBridge,\n network: this.testnet ? 'testnet' : 'mainnet',\n });\n }\n case 21: {\n const packageId = chain.contracts.hub;\n return new SuiClient({\n wormholeChainId,\n rpcUrl,\n packageId: packageId ?? '',\n wormholeCoreBridge: chain.contracts.wormholeCoreBridge,\n tokenBridge: chain.contracts.tokenBridge,\n network: this.testnet ? 'testnet' : 'mainnet',\n });\n }\n case 50001: {\n // Starknet Sepolia with custom bridge\n const spokeAddress = chain.contracts.hub;\n const bridgeAddress = chain.contracts.wormholeCoreBridge;\n if (!spokeAddress || !bridgeAddress) {\n throw new Error('Starknet config missing spoke/bridge addresses in constants');\n }\n return new StarknetClient({\n wormholeChainId,\n rpcUrl,\n spokeContractAddress: spokeAddress,\n bridgeContractAddress: bridgeAddress,\n network: this.testnet ? 'sepolia' : 'mainnet',\n });\n }\n default:\n throw new Error(\n `Unsupported non-EVM chain (wormholeChainId=${wormholeChainId}). ` +\n 'Add configuration in ChainDetector.createClient().'\n );\n }\n }\n\n /**\n * Derive a best-effort vault address for a chain from the passkey credential.\n *\n * - EVM chains: requires vaultFactory/vaultImplementation in constants.\n * - Non-EVM chains: uses WalletManager chain-specific derivation.\n */\n deriveVaultAddress(credential: PasskeyCredential, wormholeChainId: number): ChainAddress | null {\n const chain = this.getChainConfig(wormholeChainId);\n if (!chain) {\n return null;\n }\n\n if (chain.isEvm) {\n const factory = chain.contracts.vaultFactory;\n const implementation = chain.contracts.vaultImplementation;\n if (!factory || !implementation) {\n return null;\n }\n\n const address = this.walletManager.computeVaultAddress(credential.keyHash, factory, implementation);\n return {\n wormholeChainId,\n chainName: chain.name,\n address,\n isEvm: true,\n deployed: false,\n derivationType: 'create2',\n };\n }\n\n // Non-EVM: WalletManager derives using keyHash conventions.\n return {\n wormholeChainId,\n chainName: chain.name,\n address: wormholeChainId === 21 \n ? this.normalizeSuiAddress(credential.keyHash)\n : wormholeChainId === 50001\n ? credential.keyHash // Starknet uses keyHash directly (felt252)\n : credential.keyHash,\n isEvm: false,\n deployed: false,\n derivationType: wormholeChainId === 1 \n ? 'pda' \n : wormholeChainId === 22 \n ? 'resource_account' \n : wormholeChainId === 50001\n ? 'keyHash'\n : 'object',\n };\n }\n\n getNonEvmNativeTokenMeta(wormholeChainId: number): { symbol: string; name: string; decimals: number } | null {\n return NON_EVM_NATIVE_META[wormholeChainId] ?? null;\n }\n\n private normalizeSuiAddress(value: string): string {\n const clean = value.replace(/^0x/, '').padStart(64, '0');\n return '0x' + clean;\n }\n}\n\nexport function createChainDetector(config: ChainDetectorConfig = {}): ChainDetector {\n return new ChainDetector(config);\n}\n","/**\n * Veridex Protocol SDK - Transaction Parser\n * \n * Parses transaction payloads into human-readable summaries (Issue #26)\n * \n * Security-critical: This module MUST accurately represent what users are signing.\n * Any mismatch between displayed information and actual transaction is a security vulnerability.\n */\n\nimport { ethers } from 'ethers';\nimport {\n ACTION_TRANSFER,\n ACTION_EXECUTE,\n ACTION_CONFIG,\n ACTION_BRIDGE,\n} from '../constants.js';\nimport {\n decodeTransferAction,\n decodeBridgeAction,\n} from '../payload.js';\nimport type { PreparedTransfer, PreparedBridge } from './types.js';\nimport type { BridgeParams, TransferParams } from '../types.js';\nimport type {\n TransactionSummary,\n TransactionParserConfig,\n TokenDisplay,\n RecipientDisplay,\n ChainDisplay,\n RiskWarning,\n TransferDetails,\n BridgeDetails,\n ExecuteDetails,\n ConfigDetails,\n TokenInfo,\n} from './TransactionSummary.types.js';\nimport { getChainDisplay, getConfigTypeName } from './TransactionSummary.types.js';\n\n// ============================================================================\n// Default Token Registry\n// ============================================================================\n\nconst DEFAULT_TOKENS: Map<string, TokenInfo> = new Map([\n // Native token placeholder\n ['0x0000000000000000000000000000000000000000', {\n symbol: 'ETH',\n name: 'Ether',\n decimals: 18,\n verified: true,\n }],\n ['native', {\n symbol: 'ETH',\n name: 'Ether',\n decimals: 18,\n verified: true,\n }],\n // Common stablecoins (Base Sepolia)\n ['0x036cbd53842c5426634e7929541ec2318f3dcf7e', {\n symbol: 'USDC',\n name: 'USD Coin',\n decimals: 6,\n verified: true,\n }],\n]);\n\n// ============================================================================\n// Utility Functions\n// ============================================================================\n\n/**\n * Format a bigint amount to human-readable string\n */\nexport function formatAmount(amount: bigint, decimals: number): string {\n if (amount === 0n) return '0';\n \n const divisor = 10n ** BigInt(decimals);\n const whole = amount / divisor;\n const remainder = amount % divisor;\n \n if (remainder === 0n) {\n return whole.toString();\n }\n \n // Format with decimal places\n const remainderStr = remainder.toString().padStart(decimals, '0');\n // Trim trailing zeros\n const trimmed = remainderStr.replace(/0+$/, '');\n \n return `${whole}.${trimmed}`;\n}\n\n/**\n * Truncate an address for display\n */\nexport function truncateAddress(address: string, startChars = 6, endChars = 4): string {\n if (address.length <= startChars + endChars + 3) {\n return address;\n }\n return `${address.slice(0, startChars)}...${address.slice(-endChars)}`;\n}\n\n/**\n * Format time remaining until expiration\n */\nexport function formatTimeRemaining(expiresAt: number): string {\n const now = Date.now();\n const remaining = expiresAt - now;\n \n if (remaining <= 0) return 'Expired';\n \n const seconds = Math.floor(remaining / 1000);\n if (seconds < 60) return `${seconds} seconds`;\n \n const minutes = Math.floor(seconds / 60);\n if (minutes < 60) return `${minutes} minute${minutes === 1 ? '' : 's'}`;\n \n const hours = Math.floor(minutes / 60);\n return `${hours} hour${hours === 1 ? '' : 's'}`;\n}\n\n/**\n * Check if address is the zero address (native token)\n */\nexport function isNativeToken(address: string): boolean {\n return address === '0x0000000000000000000000000000000000000000' ||\n address === 'native' ||\n address === ethers.ZeroAddress;\n}\n\n// ============================================================================\n// Transaction Parser Class\n// ============================================================================\n\n/**\n * Parses prepared transactions into human-readable summaries\n */\nexport class TransactionParser {\n private config: TransactionParserConfig;\n private tokenRegistry: Map<string, TokenInfo>;\n\n constructor(config: TransactionParserConfig = {}) {\n this.config = config;\n this.tokenRegistry = config.knownTokens ?? new Map(DEFAULT_TOKENS);\n }\n\n /**\n * Main entry point: parse a prepared transfer into a human-readable summary\n * \n * This method determines the action type from the payload and delegates\n * to the appropriate specialized parser.\n * \n * @param prepared - PreparedTransfer or PreparedBridge object from SDK\n * @param vaultAddress - Optional vault address (uses default if not provided)\n * @param vaultChainId - Optional vault chain ID (uses config default if not provided)\n */\n async parse(\n prepared: PreparedTransfer | PreparedBridge,\n vaultAddress?: string,\n vaultChainId?: number\n ): Promise<TransactionSummary> {\n const effectiveVaultAddress = vaultAddress ?? '0x0000000000000000000000000000000000000000';\n \n // Determine chain ID based on type - PreparedBridge uses destinationChain, PreparedTransfer uses params.targetChain\n const isBridgePrepared = 'destinationChain' in prepared;\n const defaultChainId = isBridgePrepared \n ? (prepared as PreparedBridge).destinationChain \n : (prepared as PreparedTransfer).params.targetChain;\n const effectiveChainId = vaultChainId ?? this.config.defaultChainId ?? defaultChainId;\n \n // Normalize to PreparedTransfer with defaults for missing fields\n // For PreparedBridge, we construct params from the bridge-specific fields\n const normalizedParams: TransferParams = isBridgePrepared \n ? {\n targetChain: (prepared as PreparedBridge).destinationChain,\n token: (prepared as PreparedBridge).params.token,\n recipient: (prepared as PreparedBridge).params.recipient,\n amount: (prepared as PreparedBridge).params.amount,\n }\n : (prepared as PreparedTransfer).params;\n\n const normalized: PreparedTransfer = {\n params: normalizedParams,\n actionPayload: prepared.actionPayload,\n nonce: prepared.nonce,\n challenge: prepared.challenge,\n estimatedGas: (prepared as PreparedTransfer).estimatedGas ?? 0n,\n gasPrice: (prepared as PreparedTransfer).gasPrice ?? 0n,\n messageFee: (prepared as PreparedTransfer).messageFee ?? (isBridgePrepared ? (prepared as PreparedBridge).fees?.relayerFee ?? 0n : 0n),\n totalCost: (prepared as PreparedTransfer).totalCost ?? 0n,\n formattedCost: (prepared as PreparedTransfer).formattedCost ?? '0',\n preparedAt: prepared.preparedAt ?? Date.now(),\n expiresAt: prepared.expiresAt,\n };\n\n // Determine action type from payload\n const actionType = this.detectActionType(normalized.actionPayload);\n\n switch (actionType) {\n case ACTION_TRANSFER:\n return this.parseTransfer(normalized, effectiveVaultAddress, effectiveChainId);\n case ACTION_BRIDGE:\n return this.parseBridgeFromPrepared(normalized, effectiveVaultAddress, effectiveChainId);\n case ACTION_EXECUTE:\n return this.parseExecuteFromPayload(\n normalized.actionPayload,\n normalized.nonce,\n normalized.challenge,\n effectiveVaultAddress,\n effectiveChainId,\n normalized.expiresAt,\n normalized.formattedCost\n );\n case ACTION_CONFIG:\n return this.parseConfigFromPayload(\n normalized.actionPayload,\n normalized.nonce,\n normalized.challenge,\n effectiveVaultAddress,\n effectiveChainId,\n normalized.expiresAt,\n normalized.formattedCost\n );\n default:\n // Fallback for unknown action types\n return this.createUnknownActionSummary(normalized, effectiveVaultAddress, effectiveChainId);\n }\n }\n\n /**\n * Detect action type from payload\n */\n private detectActionType(payload: string): number {\n if (!payload || payload.length < 4) return 0;\n // Action type is typically first byte after 0x\n const typeHex = payload.slice(2, 4);\n return parseInt(typeHex, 16);\n }\n\n /**\n * Parse bridge action from PreparedTransfer\n */\n private async parseBridgeFromPrepared(\n prepared: PreparedTransfer,\n vaultAddress: string,\n vaultChainId: number\n ): Promise<TransactionSummary> {\n const { params, actionPayload, nonce, challenge, expiresAt, formattedCost } = prepared;\n const decoded = decodeBridgeAction(actionPayload);\n\n const token = await this.resolveToken(decoded.token, decoded.amount);\n const sourceChain = getChainDisplay(vaultChainId);\n const destinationChain = getChainDisplay(params.targetChain);\n const recipient = await this.resolveRecipient(decoded.recipient);\n\n const details: BridgeDetails = {\n token,\n sourceChain,\n destinationChain,\n recipient,\n estimatedTime: this.estimateBridgeTime(sourceChain.id, destinationChain.id),\n };\n\n const warnings = await this.assessBridgeRisks({\n sourceChain: vaultChainId,\n destinationChain: params.targetChain,\n token: decoded.token,\n recipient: decoded.recipient,\n amount: decoded.amount,\n }, token, sourceChain, destinationChain);\n\n return {\n action: 'bridge',\n title: `Bridge ${token.symbol}`,\n description: `Bridge ${token.amount} ${token.symbol} from ${sourceChain.name} to ${destinationChain.name}`,\n details,\n vault: {\n address: vaultAddress,\n truncated: truncateAddress(vaultAddress),\n chain: sourceChain,\n },\n fee: {\n gas: formattedCost,\n paidByRelayer: false,\n total: formattedCost,\n },\n warnings,\n raw: {\n actionType: ACTION_BRIDGE,\n actionPayload,\n nonce,\n challenge: ethers.hexlify(challenge),\n chainId: params.targetChain,\n expiresAt,\n expiresIn: formatTimeRemaining(expiresAt),\n },\n generatedAt: Date.now(),\n };\n }\n\n /**\n * Parse execute action from payload\n */\n private async parseExecuteFromPayload(\n actionPayload: string,\n nonce: bigint,\n challenge: Uint8Array,\n vaultAddress: string,\n chainId: number,\n expiresAt: number,\n formattedCost: string\n ): Promise<TransactionSummary> {\n // Decode execute action - basic structure\n const target = '0x' + actionPayload.slice(4, 44);\n const value = BigInt('0x' + actionPayload.slice(44, 108));\n const calldata = '0x' + actionPayload.slice(108);\n\n const targetDisplay = await this.resolveRecipient(target);\n const chain = getChainDisplay(chainId);\n const functionInfo = this.decodeFunctionCall(calldata);\n\n const details: ExecuteDetails = {\n target: targetDisplay,\n value: await this.resolveToken(ethers.ZeroAddress, value),\n chain,\n functionName: functionInfo?.name,\n decodedArgs: functionInfo?.args,\n calldata,\n };\n\n const warnings = await this.assessExecuteRisks(target, value, calldata, targetDisplay);\n\n return {\n action: 'execute',\n title: 'Contract Call',\n description: `Call ${functionInfo?.name ?? 'function'} on ${targetDisplay.ens ?? targetDisplay.truncated}`,\n details,\n vault: {\n address: vaultAddress,\n truncated: truncateAddress(vaultAddress),\n chain,\n },\n fee: {\n gas: formattedCost,\n paidByRelayer: false,\n total: formattedCost,\n },\n warnings,\n raw: {\n actionType: ACTION_EXECUTE,\n actionPayload,\n nonce,\n challenge: ethers.hexlify(challenge),\n chainId,\n expiresAt,\n expiresIn: formatTimeRemaining(expiresAt),\n },\n generatedAt: Date.now(),\n };\n }\n\n /**\n * Parse config action from payload\n */\n private async parseConfigFromPayload(\n actionPayload: string,\n nonce: bigint,\n challenge: Uint8Array,\n vaultAddress: string,\n chainId: number,\n expiresAt: number,\n formattedCost: string\n ): Promise<TransactionSummary> {\n // Decode config action - basic structure\n const configType = parseInt(actionPayload.slice(2, 4), 16);\n const configData = '0x' + actionPayload.slice(4);\n\n const chain = getChainDisplay(chainId);\n const configTypeName = getConfigTypeName(configType);\n\n const details: ConfigDetails = {\n configType,\n configTypeName,\n description: this.describeConfigChange(configType, configData),\n changes: this.parseConfigChanges(configType, configData),\n };\n\n const warnings: RiskWarning[] = [{\n level: 'high',\n type: 'config_change',\n message: 'This transaction will modify your vault settings',\n details: `Changing: ${configTypeName}`,\n }];\n\n return {\n action: 'config',\n title: 'Configuration Change',\n description: `Update vault configuration: ${configTypeName}`,\n details,\n vault: {\n address: vaultAddress,\n truncated: truncateAddress(vaultAddress),\n chain,\n },\n fee: {\n gas: formattedCost,\n paidByRelayer: false,\n total: formattedCost,\n },\n warnings,\n raw: {\n actionType: ACTION_CONFIG,\n actionPayload,\n nonce,\n challenge: ethers.hexlify(challenge),\n chainId,\n expiresAt,\n expiresIn: formatTimeRemaining(expiresAt),\n },\n generatedAt: Date.now(),\n };\n }\n\n /**\n * Create a fallback summary for unknown action types\n */\n private createUnknownActionSummary(\n prepared: PreparedTransfer,\n vaultAddress: string,\n chainId: number\n ): TransactionSummary {\n const chain = getChainDisplay(chainId);\n\n return {\n action: 'execute',\n title: 'Unknown Action',\n description: 'This transaction contains an unrecognized action type',\n details: null,\n vault: {\n address: vaultAddress,\n truncated: truncateAddress(vaultAddress),\n chain,\n },\n fee: {\n gas: prepared.formattedCost,\n paidByRelayer: false,\n total: prepared.formattedCost,\n },\n warnings: [{\n level: 'critical',\n type: 'unknown_token',\n message: 'Unknown action type - proceed with extreme caution',\n details: `Action type: ${this.detectActionType(prepared.actionPayload)}`,\n }],\n raw: {\n actionType: this.detectActionType(prepared.actionPayload),\n actionPayload: prepared.actionPayload,\n nonce: prepared.nonce,\n challenge: ethers.hexlify(prepared.challenge),\n chainId,\n expiresAt: prepared.expiresAt,\n expiresIn: formatTimeRemaining(prepared.expiresAt),\n },\n generatedAt: Date.now(),\n };\n }\n\n /**\n * Parse a prepared transfer into a human-readable summary\n */\n async parseTransfer(\n prepared: PreparedTransfer,\n vaultAddress: string,\n vaultChainId: number\n ): Promise<TransactionSummary> {\n const { params, actionPayload, nonce, challenge, expiresAt } = prepared;\n const decoded = decodeTransferAction(actionPayload);\n\n const token = await this.resolveToken(decoded.token, decoded.amount);\n const recipient = await this.resolveRecipient(decoded.recipient);\n const chain = getChainDisplay(params.targetChain);\n\n const details: TransferDetails = {\n token,\n recipient,\n chain,\n };\n\n const warnings = await this.assessTransferRisks(params, token, recipient);\n\n return {\n action: 'transfer',\n title: `Send ${token.symbol}`,\n description: `Send ${token.amount} ${token.symbol} to ${recipient.ens ?? recipient.truncated}`,\n details,\n vault: {\n address: vaultAddress,\n truncated: truncateAddress(vaultAddress),\n chain: getChainDisplay(vaultChainId),\n },\n fee: {\n gas: prepared.formattedCost,\n paidByRelayer: false, // Will be updated by caller if gasless\n total: prepared.formattedCost,\n },\n warnings,\n raw: {\n actionType: ACTION_TRANSFER,\n actionPayload,\n nonce,\n challenge: ethers.hexlify(challenge),\n chainId: params.targetChain,\n expiresAt,\n expiresIn: formatTimeRemaining(expiresAt),\n },\n generatedAt: Date.now(),\n };\n }\n\n /**\n * Parse a bridge operation into a human-readable summary\n */\n async parseBridge(\n params: BridgeParams,\n actionPayload: string,\n nonce: bigint,\n challenge: Uint8Array,\n vaultAddress: string,\n vaultChainId: number,\n expiresAt: number,\n formattedCost: string\n ): Promise<TransactionSummary> {\n const decoded = decodeBridgeAction(actionPayload);\n\n const token = await this.resolveToken(decoded.token, decoded.amount);\n const sourceChain = getChainDisplay(params.sourceChain);\n const destinationChain = getChainDisplay(params.destinationChain);\n const recipient = await this.resolveRecipient(decoded.recipient);\n\n const details: BridgeDetails = {\n token,\n sourceChain,\n destinationChain,\n recipient,\n estimatedTime: this.estimateBridgeTime(sourceChain.id, destinationChain.id),\n };\n\n const warnings = await this.assessBridgeRisks(params, token, sourceChain, destinationChain);\n\n return {\n action: 'bridge',\n title: `Bridge ${token.symbol}`,\n description: `Bridge ${token.amount} ${token.symbol} from ${sourceChain.name} to ${destinationChain.name}`,\n details,\n vault: {\n address: vaultAddress,\n truncated: truncateAddress(vaultAddress),\n chain: getChainDisplay(vaultChainId),\n },\n fee: {\n gas: formattedCost,\n paidByRelayer: false,\n total: formattedCost,\n },\n warnings,\n raw: {\n actionType: ACTION_BRIDGE,\n actionPayload,\n nonce,\n challenge: ethers.hexlify(challenge),\n chainId: params.sourceChain,\n expiresAt,\n expiresIn: formatTimeRemaining(expiresAt),\n },\n generatedAt: Date.now(),\n };\n }\n\n /**\n * Parse an execute (contract call) operation into a human-readable summary\n */\n async parseExecute(\n target: string,\n value: bigint,\n calldata: string,\n chainId: number,\n nonce: bigint,\n challenge: Uint8Array,\n vaultAddress: string,\n expiresAt: number,\n formattedCost: string\n ): Promise<TransactionSummary> {\n const targetRecipient = await this.resolveRecipient(target);\n const chain = getChainDisplay(chainId);\n const valueToken = await this.resolveToken(ethers.ZeroAddress, value);\n\n // Try to decode function signature\n const functionInfo = this.decodeFunctionCall(calldata);\n\n const details: ExecuteDetails = {\n target: targetRecipient,\n value: valueToken,\n chain,\n functionName: functionInfo?.name,\n decodedArgs: functionInfo?.args,\n calldata,\n };\n\n const warnings = await this.assessExecuteRisks(target, value, calldata, targetRecipient);\n\n const title = functionInfo?.name\n ? `Call ${functionInfo.name}`\n : 'Contract Interaction';\n\n return {\n action: 'execute',\n title,\n description: `Execute contract call on ${targetRecipient.ens ?? targetRecipient.truncated}`,\n details,\n vault: {\n address: vaultAddress,\n truncated: truncateAddress(vaultAddress),\n chain,\n },\n fee: {\n gas: formattedCost,\n paidByRelayer: false,\n total: formattedCost,\n },\n warnings,\n raw: {\n actionType: ACTION_EXECUTE,\n actionPayload: calldata,\n nonce,\n challenge: ethers.hexlify(challenge),\n chainId,\n expiresAt,\n expiresIn: formatTimeRemaining(expiresAt),\n },\n generatedAt: Date.now(),\n };\n }\n\n /**\n * Parse a config change operation\n */\n async parseConfig(\n configType: number,\n configData: string,\n chainId: number,\n nonce: bigint,\n challenge: Uint8Array,\n vaultAddress: string,\n expiresAt: number,\n formattedCost: string\n ): Promise<TransactionSummary> {\n const chain = getChainDisplay(chainId);\n const configTypeName = getConfigTypeName(configType);\n\n const details: ConfigDetails = {\n configType,\n configTypeName,\n description: this.describeConfigChange(configType, configData),\n changes: this.parseConfigChanges(configType, configData),\n };\n\n const warnings: RiskWarning[] = [{\n level: 'warning',\n type: 'config_change',\n message: 'This transaction will modify your vault settings',\n }];\n\n return {\n action: 'config',\n title: configTypeName,\n description: `Update vault configuration: ${configTypeName}`,\n details,\n vault: {\n address: vaultAddress,\n truncated: truncateAddress(vaultAddress),\n chain,\n },\n fee: {\n gas: formattedCost,\n paidByRelayer: false,\n total: formattedCost,\n },\n warnings,\n raw: {\n actionType: ACTION_CONFIG,\n actionPayload: configData,\n nonce,\n challenge: ethers.hexlify(challenge),\n chainId,\n expiresAt,\n expiresIn: formatTimeRemaining(expiresAt),\n },\n generatedAt: Date.now(),\n };\n }\n\n // ============================================================================\n // Resolution Methods\n // ============================================================================\n\n /**\n * Resolve token address to display info\n */\n private async resolveToken(address: string, amount: bigint): Promise<TokenDisplay> {\n const normalizedAddress = address.toLowerCase();\n const isNative = isNativeToken(address);\n\n // Check registry\n let tokenInfo = this.tokenRegistry.get(normalizedAddress);\n if (!tokenInfo && isNative) {\n tokenInfo = this.tokenRegistry.get('native');\n }\n\n const decimals = tokenInfo?.decimals ?? 18;\n const symbol = tokenInfo?.symbol ?? (isNative ? 'ETH' : 'UNKNOWN');\n const formattedAmount = formatAmount(amount, decimals);\n\n // Try to get USD value\n let usdValue: string | undefined;\n if (this.config.priceOracle) {\n try {\n const price = await this.config.priceOracle(address);\n if (price !== null) {\n const amountNum = parseFloat(formattedAmount);\n usdValue = `$${(amountNum * price).toFixed(2)}`;\n }\n } catch {\n // Price oracle failed, continue without USD value\n }\n }\n\n return {\n symbol,\n amount: formattedAmount,\n rawAmount: amount,\n address: isNative ? ethers.ZeroAddress : address,\n decimals,\n usdValue,\n isNative,\n };\n }\n\n /**\n * Resolve recipient address to display info\n */\n private async resolveRecipient(address: string): Promise<RecipientDisplay> {\n const truncated = truncateAddress(address);\n let ens: string | undefined;\n let isContract: boolean | undefined;\n let isNewRecipient: boolean | undefined;\n let label: string | undefined;\n\n // Check known recipients\n if (this.config.knownRecipients) {\n label = this.config.knownRecipients.get(address.toLowerCase());\n }\n\n // Try ENS resolution\n if (this.config.ensResolver) {\n try {\n const resolved = await this.config.ensResolver(address);\n if (resolved) {\n ens = resolved;\n }\n } catch {\n // ENS resolution failed, continue without\n }\n }\n\n // Check if contract\n if (this.config.contractDetector) {\n try {\n isContract = await this.config.contractDetector(address);\n } catch {\n // Contract detection failed\n }\n }\n\n // Check transaction history\n if (this.config.transactionHistory) {\n isNewRecipient = !this.config.transactionHistory.has(address.toLowerCase());\n }\n\n return {\n address,\n ens,\n truncated,\n isContract,\n isNewRecipient,\n label,\n };\n }\n\n // ============================================================================\n // Risk Assessment Methods\n // ============================================================================\n\n /**\n * Assess risks for a transfer transaction\n */\n private async assessTransferRisks(\n _params: TransferParams,\n token: TokenDisplay,\n recipient: RecipientDisplay\n ): Promise<RiskWarning[]> {\n const warnings: RiskWarning[] = [];\n\n // New recipient warning\n if (recipient.isNewRecipient) {\n warnings.push({\n level: 'warning',\n type: 'new_recipient',\n message: \"You've never sent to this address before\",\n details: 'Double-check the recipient address is correct',\n });\n }\n\n // Large transaction warning\n if (this.config.averageTransactionValue) {\n const threshold = this.config.averageTransactionValue * 10n; // 10x average\n if (token.rawAmount > threshold) {\n warnings.push({\n level: 'warning',\n type: 'large_transaction',\n message: 'This transaction is larger than your usual activity',\n details: `Amount: ${token.amount} ${token.symbol}`,\n });\n }\n }\n\n // Contract interaction warning\n if (recipient.isContract) {\n warnings.push({\n level: 'info',\n type: 'contract_interaction',\n message: 'Recipient is a smart contract',\n });\n }\n\n // Unknown token warning\n const tokenInfo = this.tokenRegistry.get(token.address.toLowerCase());\n if (!tokenInfo?.verified) {\n warnings.push({\n level: 'warning',\n type: 'unknown_token',\n message: 'This token is not in our verified list',\n details: 'Verify the token address is correct',\n });\n }\n\n return warnings;\n }\n\n /**\n * Assess risks for a bridge transaction\n */\n private async assessBridgeRisks(\n _params: BridgeParams,\n token: TokenDisplay,\n sourceChain: ChainDisplay,\n destinationChain: ChainDisplay\n ): Promise<RiskWarning[]> {\n const warnings: RiskWarning[] = [];\n\n // Cross-chain operation info\n warnings.push({\n level: 'info',\n type: 'cross_chain',\n message: `This is a cross-chain transfer from ${sourceChain.name} to ${destinationChain.name}`,\n details: 'Funds will be locked on the source chain and released on the destination',\n });\n\n // Large transaction warning\n if (this.config.averageTransactionValue) {\n const threshold = this.config.averageTransactionValue * 10n;\n if (token.rawAmount > threshold) {\n warnings.push({\n level: 'warning',\n type: 'large_transaction',\n message: 'This transaction is larger than your usual activity',\n });\n }\n }\n\n return warnings;\n }\n\n /**\n * Assess risks for an execute transaction\n */\n private async assessExecuteRisks(\n _target: string,\n value: bigint,\n _calldata: string,\n recipient: RecipientDisplay\n ): Promise<RiskWarning[]> {\n const warnings: RiskWarning[] = [];\n\n // Contract interaction is inherently risky\n warnings.push({\n level: 'warning',\n type: 'contract_interaction',\n message: 'This transaction calls an external contract',\n details: 'Review the contract and function being called',\n });\n\n // New recipient warning\n if (recipient.isNewRecipient) {\n warnings.push({\n level: 'warning',\n type: 'new_recipient',\n message: \"You've never interacted with this contract before\",\n });\n }\n\n // Value transfer with contract call\n if (value > 0n) {\n warnings.push({\n level: 'info',\n type: 'large_transaction',\n message: `This transaction sends ${formatAmount(value, 18)} ETH along with the contract call`,\n });\n }\n\n return warnings;\n }\n\n // ============================================================================\n // Helper Methods\n // ============================================================================\n\n /**\n * Estimate bridge completion time\n */\n private estimateBridgeTime(_sourceChain: number, _destChain: number): string {\n // Wormhole typically takes 2-15 minutes depending on chains\n // Query-based is faster (~5-7 seconds), VAA-based is slower (~2+ minutes)\n return '~2-5 minutes';\n }\n\n /**\n * Try to decode a function call from calldata\n */\n private decodeFunctionCall(calldata: string): { name: string; args: Record<string, unknown> } | null {\n if (calldata.length < 10) return null;\n\n // Common function selectors\n const KNOWN_SELECTORS: Record<string, string> = {\n '0xa9059cbb': 'transfer',\n '0x23b872dd': 'transferFrom',\n '0x095ea7b3': 'approve',\n '0x70a08231': 'balanceOf',\n '0x18160ddd': 'totalSupply',\n '0x313ce567': 'decimals',\n '0x06fdde03': 'name',\n '0x95d89b41': 'symbol',\n };\n\n const selector = calldata.slice(0, 10).toLowerCase();\n const name = KNOWN_SELECTORS[selector];\n\n if (name) {\n return { name, args: {} }; // Would need ABI to decode args\n }\n\n return null;\n }\n\n /**\n * Describe a config change in human-readable terms\n */\n private describeConfigChange(configType: number, _configData: string): string {\n const name = getConfigTypeName(configType);\n return `This will update your vault's ${name.toLowerCase()}`;\n }\n\n /**\n * Parse config changes into structured format\n */\n private parseConfigChanges(configType: number, configData: string): Array<{ field: string; newValue: string }> {\n // Basic parsing - would need more context for full implementation\n return [{\n field: getConfigTypeName(configType),\n newValue: configData.length > 66 ? `${configData.slice(0, 66)}...` : configData,\n }];\n }\n\n /**\n * Update parser configuration\n */\n updateConfig(config: Partial<TransactionParserConfig>): void {\n this.config = { ...this.config, ...config };\n if (config.knownTokens) {\n this.tokenRegistry = config.knownTokens;\n }\n }\n\n /**\n * Add a known token to the registry\n */\n addKnownToken(address: string, info: TokenInfo): void {\n this.tokenRegistry.set(address.toLowerCase(), info);\n }\n\n /**\n * Add a known recipient label\n */\n addKnownRecipient(address: string, label: string): void {\n if (!this.config.knownRecipients) {\n this.config.knownRecipients = new Map();\n }\n this.config.knownRecipients.set(address.toLowerCase(), label);\n }\n}\n\n// ============================================================================\n// Audit Logging Types and Functions\n// ============================================================================\n\n/**\n * Audit log entry for transaction summaries\n * Used for security audits and debugging\n */\nexport interface TransactionAuditEntry {\n /** Unique identifier matching the TransactionSummary.id */\n summaryId: string;\n /** ISO timestamp when summary was generated */\n timestamp: string;\n /** Action type that was parsed */\n actionType: string;\n /** Human-readable title shown to user */\n titleDisplayed: string;\n /** Human-readable description shown to user */\n descriptionDisplayed: string;\n /** Number of risk warnings shown */\n riskWarningCount: number;\n /** Highest risk level in warnings */\n highestRiskLevel: string | null;\n /** Whether technical details were available */\n hasTechnicalDetails: boolean;\n /** Hash of the raw payload for verification */\n payloadHash: string;\n /** Expiration time shown */\n expiresAt: number;\n /** Chain ID of the transaction */\n targetChain: number;\n /** Gas cost formatted as shown to user */\n gasCostDisplayed: string;\n}\n\n/**\n * Create an audit log entry from a transaction summary\n * \n * @param summary - The transaction summary that was displayed\n * @returns Audit entry for logging\n */\nexport function createAuditEntry(summary: TransactionSummary): TransactionAuditEntry {\n const highestRisk = summary.warnings.reduce<string | null>((acc, r) => {\n const order: Record<string, number> = { critical: 0, high: 1, warning: 2, info: 3 };\n if (acc === null) return r.level;\n if (order[r.level] < order[acc]) {\n return r.level;\n }\n return acc;\n }, null);\n\n return {\n summaryId: `${summary.generatedAt}-${summary.action}`,\n timestamp: new Date().toISOString(),\n actionType: summary.action,\n titleDisplayed: summary.title,\n descriptionDisplayed: summary.description,\n riskWarningCount: summary.warnings.length,\n highestRiskLevel: highestRisk,\n hasTechnicalDetails: !!summary.raw,\n payloadHash: summary.raw?.actionPayload ? ethers.keccak256(summary.raw.actionPayload) : '',\n expiresAt: summary.raw?.expiresAt ?? 0,\n targetChain: summary.raw?.chainId ?? 0,\n gasCostDisplayed: summary.fee.total,\n };\n}\n\n/**\n * Log a transaction summary for audit purposes\n * \n * @param summary - The transaction summary to log\n * @param logger - Optional custom logger (defaults to console.info)\n */\nexport function logTransactionSummary(\n summary: TransactionSummary,\n logger: (entry: TransactionAuditEntry) => void = (entry) => {\n // Default: structured console logging\n console.info('[VERIDEX_TX_AUDIT]', JSON.stringify(entry));\n }\n): TransactionAuditEntry {\n const entry = createAuditEntry(summary);\n logger(entry);\n return entry;\n}\n\n// ============================================================================\n// Factory Function\n// ============================================================================\n\n/**\n * Create a transaction parser with optional configuration\n */\nexport function createTransactionParser(config?: TransactionParserConfig): TransactionParser {\n return new TransactionParser(config);\n}\n","/**\n * Veridex Protocol SDK - Transaction Summary Types\n * \n * Human-readable transaction summary types for security and UX (Issue #26)\n * \n * These types enable users to understand what they're signing before\n * providing biometric authentication, preventing phishing and social engineering.\n */\n\n// ============================================================================\n// Action Display Types\n// ============================================================================\n\n/**\n * Human-readable action type\n */\nexport type ActionDisplayType = 'transfer' | 'bridge' | 'config' | 'execute' | 'unknown';\n\n/**\n * Token display information\n */\nexport interface TokenDisplay {\n /** Token symbol (e.g., \"ETH\", \"USDC\") */\n symbol: string;\n /** Human-readable amount (e.g., \"1.5\") */\n amount: string;\n /** Raw amount in smallest unit */\n rawAmount: bigint;\n /** Token contract address */\n address: string;\n /** Number of decimals */\n decimals: number;\n /** Estimated USD value (if available) */\n usdValue?: string;\n /** Whether this is the native token */\n isNative: boolean;\n}\n\n/**\n * Recipient display information\n */\nexport interface RecipientDisplay {\n /** Raw address (hex) */\n address: string;\n /** ENS name (if resolved) */\n ens?: string;\n /** Truncated address for display (e.g., \"0x1234...5678\") */\n truncated: string;\n /** Whether this is a contract address */\n isContract?: boolean;\n /** Whether this is a new recipient (never sent to before) */\n isNewRecipient?: boolean;\n /** Label if known (e.g., \"My Wallet\", \"Exchange\") */\n label?: string;\n}\n\n/**\n * Chain display information\n */\nexport interface ChainDisplay {\n /** Wormhole chain ID */\n id: number;\n /** Human-readable chain name */\n name: string;\n /** Chain icon URL (optional) */\n iconUrl?: string;\n /** Whether this is a testnet */\n isTestnet: boolean;\n}\n\n// ============================================================================\n// Risk Warning Types\n// ============================================================================\n\n/**\n * Risk level for warnings\n */\nexport type RiskLevel = 'info' | 'warning' | 'high' | 'critical';\n\n/**\n * Risk warning with message and metadata\n */\nexport interface RiskWarning {\n /** Severity level */\n level: RiskLevel;\n /** Human-readable warning message */\n message: string;\n /** Warning type for programmatic handling */\n type: RiskWarningType;\n /** Additional context/details */\n details?: string;\n}\n\n/**\n * Types of risk warnings\n */\nexport type RiskWarningType =\n | 'large_transaction' // Amount exceeds usual activity\n | 'new_recipient' // First time sending to this address\n | 'contract_interaction' // Calling an external contract\n | 'full_balance' // Transferring all assets\n | 'high_gas' // Gas cost is unusually high\n | 'unknown_token' // Token not in verified list\n | 'cross_chain' // Cross-chain operation\n | 'config_change' // Vault configuration change\n | 'all_tokens' // Affects all tokens in vault\n | 'irreversible'; // Action cannot be undone\n\n// ============================================================================\n// Transaction Summary Types\n// ============================================================================\n\n/**\n * Transfer-specific details\n */\nexport interface TransferDetails {\n token: TokenDisplay;\n recipient: RecipientDisplay;\n chain: ChainDisplay;\n}\n\n/**\n * Bridge-specific details\n */\nexport interface BridgeDetails {\n token: TokenDisplay;\n sourceChain: ChainDisplay;\n destinationChain: ChainDisplay;\n recipient: RecipientDisplay;\n /** Estimated bridge fee */\n bridgeFee?: string;\n /** Estimated arrival time */\n estimatedTime?: string;\n}\n\n/**\n * Execute (contract call) details\n */\nexport interface ExecuteDetails {\n target: RecipientDisplay;\n value: TokenDisplay;\n chain: ChainDisplay;\n /** Function signature if decodable */\n functionName?: string;\n /** Decoded function arguments if available */\n decodedArgs?: Record<string, unknown>;\n /** Raw calldata (hex) */\n calldata: string;\n}\n\n/**\n * Config change details\n */\nexport interface ConfigDetails {\n configType: number;\n configTypeName: string;\n description: string;\n changes: Array<{\n field: string;\n oldValue?: string;\n newValue: string;\n }>;\n}\n\n/**\n * Union type for all action-specific details\n */\nexport type ActionDetails = TransferDetails | BridgeDetails | ExecuteDetails | ConfigDetails;\n\n/**\n * Complete transaction summary for display\n */\nexport interface TransactionSummary {\n /** Action type for display */\n action: ActionDisplayType;\n \n /** Human-readable title (e.g., \"Send ETH\", \"Bridge USDC\") */\n title: string;\n \n /** Human-readable description */\n description: string;\n\n /** Action-specific details */\n details: TransferDetails | BridgeDetails | ExecuteDetails | ConfigDetails | null;\n \n /** Source vault information */\n vault: {\n address: string;\n truncated: string;\n chain: ChainDisplay;\n };\n\n /** Fee information */\n fee: {\n /** Estimated gas fee */\n gas: string;\n /** Gas in USD (if available) */\n gasUsd?: string;\n /** Whether fee is paid by relayer */\n paidByRelayer: boolean;\n /** Relayer fee (if applicable) */\n relayerFee?: string;\n /** Total fee */\n total: string;\n };\n\n /** Risk warnings */\n warnings: RiskWarning[];\n \n /** Raw technical details for advanced users */\n raw: {\n actionType: number;\n actionPayload: string;\n nonce: bigint;\n challenge: string;\n chainId: number;\n /** Expiration timestamp */\n expiresAt: number;\n /** Time until expiration in human readable form */\n expiresIn: string;\n };\n\n /** Timestamp when summary was generated */\n generatedAt: number;\n}\n\n// ============================================================================\n// Parser Configuration\n// ============================================================================\n\n/**\n * Configuration for the transaction parser\n */\nexport interface TransactionParserConfig {\n /** Default chain ID for vault operations */\n defaultChainId?: number;\n /** Known token registry (address -> info) */\n knownTokens?: Map<string, TokenInfo>;\n /** Known recipient labels (address -> label) */\n knownRecipients?: Map<string, string>;\n /** ENS resolver function */\n ensResolver?: (address: string) => Promise<string | null>;\n /** Contract detector function */\n contractDetector?: (address: string) => Promise<boolean>;\n /** Price oracle for USD values */\n priceOracle?: (tokenAddress: string) => Promise<number | null>;\n /** User's transaction history for new recipient detection */\n transactionHistory?: Set<string>;\n /** User's average transaction value for large tx detection */\n averageTransactionValue?: bigint;\n}\n\n/**\n * Token info for registry\n */\nexport interface TokenInfo {\n symbol: string;\n name: string;\n decimals: number;\n logoUrl?: string;\n verified: boolean;\n}\n\n// ============================================================================\n// Chain Name Mapping\n// ============================================================================\n\n/**\n * Get chain display info from Wormhole chain ID\n */\nexport const CHAIN_DISPLAY_INFO: Record<number, Omit<ChainDisplay, 'id'>> = {\n // Mainnets\n 1: { name: 'Solana', isTestnet: false },\n 2: { name: 'Ethereum', isTestnet: false },\n 4: { name: 'BSC', isTestnet: false },\n 5: { name: 'Polygon', isTestnet: false },\n 6: { name: 'Avalanche', isTestnet: false },\n 21: { name: 'Sui', isTestnet: false },\n 22: { name: 'Aptos', isTestnet: false },\n 23: { name: 'Arbitrum', isTestnet: false },\n 24: { name: 'Optimism', isTestnet: false },\n 30: { name: 'Base', isTestnet: false },\n\n // Testnets\n 10002: { name: 'Sepolia', isTestnet: true },\n 10003: { name: 'Arbitrum Sepolia', isTestnet: true },\n 10004: { name: 'Base Sepolia', isTestnet: true },\n 10005: { name: 'Optimism Sepolia', isTestnet: true },\n 50001: { name: 'Starknet Sepolia', isTestnet: true },\n};\n\n/**\n * Get chain display info with fallback\n */\nexport function getChainDisplay(chainId: number): ChainDisplay {\n const info = CHAIN_DISPLAY_INFO[chainId];\n if (info) {\n return { id: chainId, ...info };\n }\n return {\n id: chainId,\n name: `Chain ${chainId}`,\n isTestnet: chainId >= 10000,\n };\n}\n\n// ============================================================================\n// Config Type Names\n// ============================================================================\n\nexport const CONFIG_TYPE_NAMES: Record<number, string> = {\n 1: 'Update Spending Limits',\n 2: 'Add Guardian',\n 3: 'Remove Guardian',\n 4: 'Update Recovery Threshold',\n 5: 'Add Session Key',\n 6: 'Revoke Session Key',\n 7: 'Update Emergency Contact',\n};\n\n/**\n * Get config type name with fallback\n */\nexport function getConfigTypeName(configType: number): string {\n return CONFIG_TYPE_NAMES[configType] ?? `Config Update (Type ${configType})`;\n}\n","/**\n * Veridex Protocol SDK - Spending Limits Manager (Issue #27)\n * \n * Manages vault spending limits including:\n * - Reading current limits and usage from on-chain state\n * - Preparing limit update transactions (requires passkey signature)\n * - Checking transactions against limits before signing\n * - Formatting limits for UI display\n * \n * Security Considerations:\n * - All limit changes require Hub authentication (passkey signature)\n * - Changes are propagated via VAA to spoke chains\n * - Local checks are advisory; on-chain enforcement is authoritative\n */\n\nimport { ethers } from 'ethers';\nimport {\n type SpendingLimits,\n type FormattedSpendingLimits,\n type LimitCheckResult,\n type LimitViolationSuggestion,\n type SpendingTransaction,\n type DailySpendingSummary,\n type DurationDisplay,\n type SpendingLimitConfig,\n type SpendingLimitChangedEvent,\n type SpendingLimitEventCallback,\n CONFIG_TYPE,\n formatDuration,\n calculatePercentage,\n formatLargeAmount,\n} from './SpendingLimits.types.js';\nimport { encodeConfigAction } from '../payload.js';\n\n// ============================================================================\n// Vault ABI Fragment (spending limit related functions)\n// ============================================================================\n\nconst VAULT_ABI = [\n 'function dailyLimit() view returns (uint256)',\n 'function dailyWithdrawn() view returns (uint256)',\n 'function dayStart() view returns (uint256)',\n 'function paused() view returns (bool)',\n 'function getRemainingDailyLimit() view returns (uint256)',\n 'event Paused(bool paused)',\n 'event DailyLimitUpdated(uint256 newLimit)',\n];\n\n// ============================================================================\n// Constants\n// ============================================================================\n\n/** One day in seconds */\nconst DAY_SECONDS = 86400;\n\n/** One day in milliseconds */\nconst DAY_MS = DAY_SECONDS * 1000;\n\n// ============================================================================\n// Configuration\n// ============================================================================\n\nexport interface SpendingLimitsManagerConfig {\n /** Default token decimals for formatting */\n defaultDecimals?: number;\n \n /** Default token symbol for formatting */\n defaultSymbol?: string;\n \n /** Custom RPC URLs by chain ID */\n rpcUrls?: Record<number, string>;\n \n /** Cache TTL in milliseconds */\n cacheTtl?: number;\n \n /** Event callback for limit changes */\n onLimitChange?: SpendingLimitEventCallback;\n}\n\n// ============================================================================\n// Main Class\n// ============================================================================\n\nexport class SpendingLimitsManager {\n private config: Required<SpendingLimitsManagerConfig>;\n private cache: Map<string, { data: SpendingLimits; expiry: number }> = new Map();\n private eventListeners: SpendingLimitEventCallback[] = [];\n \n constructor(config: SpendingLimitsManagerConfig = {}) {\n this.config = {\n defaultDecimals: config.defaultDecimals ?? 18,\n defaultSymbol: config.defaultSymbol ?? 'ETH',\n rpcUrls: config.rpcUrls ?? {},\n cacheTtl: config.cacheTtl ?? 10000, // 10 seconds\n onLimitChange: config.onLimitChange ?? (() => {}),\n };\n \n if (config.onLimitChange) {\n this.eventListeners.push(config.onLimitChange);\n }\n }\n \n // ============================================================================\n // Read Spending Limits\n // ============================================================================\n \n /**\n * Get current spending limits for a vault\n * @param vaultAddress - Vault contract address\n * @param chainId - Chain ID where the vault is deployed\n * @param rpcUrl - Optional RPC URL override\n */\n async getSpendingLimits(\n vaultAddress: string,\n chainId: number,\n rpcUrl?: string\n ): Promise<SpendingLimits> {\n // Check cache first\n const cacheKey = `${chainId}:${vaultAddress.toLowerCase()}`;\n const cached = this.cache.get(cacheKey);\n if (cached && Date.now() < cached.expiry) {\n return cached.data;\n }\n \n const provider = this.getProvider(chainId, rpcUrl);\n const vault = new ethers.Contract(vaultAddress, VAULT_ABI, provider);\n \n // Fetch all values in parallel\n const [dailyLimit, dailyWithdrawn, dayStart, paused] = await Promise.all([\n vault.dailyLimit() as Promise<bigint>,\n vault.dailyWithdrawn() as Promise<bigint>,\n vault.dayStart() as Promise<bigint>,\n vault.paused() as Promise<boolean>,\n ]);\n \n const now = Date.now();\n const dayStartMs = Number(dayStart) * 1000;\n const dayEndMs = dayStartMs + DAY_MS;\n \n // Calculate effective values (handle day rollover)\n let effectiveSpent = dailyWithdrawn;\n let effectiveResetTime = new Date(dayEndMs);\n let timeUntilReset = dayEndMs - now;\n \n if (now >= dayEndMs) {\n // New day has started, spent resets to 0\n effectiveSpent = 0n;\n // Calculate next reset time\n const daysSinceStart = Math.floor((now - dayStartMs) / DAY_MS);\n const nextDayStart = dayStartMs + (daysSinceStart + 1) * DAY_MS;\n effectiveResetTime = new Date(nextDayStart);\n timeUntilReset = nextDayStart - now;\n }\n \n const dailyRemaining = dailyLimit === 0n \n ? BigInt('0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff') // max uint256\n : dailyLimit > effectiveSpent \n ? dailyLimit - effectiveSpent \n : 0n;\n \n const limits: SpendingLimits = {\n dailyLimit,\n dailySpent: effectiveSpent,\n dailyRemaining,\n dayResetTime: effectiveResetTime,\n timeUntilReset: Math.max(0, timeUntilReset),\n transactionLimit: 0n, // Per-tx limits are in SpendingLimitModule, not base vault\n isPaused: paused,\n lastUpdated: new Date(),\n chainId,\n };\n \n // Cache the result\n this.cache.set(cacheKey, {\n data: limits,\n expiry: now + this.config.cacheTtl,\n });\n \n return limits;\n }\n \n /**\n * Get spending limits formatted for UI display\n */\n async getFormattedSpendingLimits(\n vaultAddress: string,\n chainId: number,\n options?: {\n rpcUrl?: string;\n decimals?: number;\n symbol?: string;\n }\n ): Promise<FormattedSpendingLimits> {\n const limits = await this.getSpendingLimits(vaultAddress, chainId, options?.rpcUrl);\n const decimals = options?.decimals ?? this.config.defaultDecimals;\n const symbol = options?.symbol ?? this.config.defaultSymbol;\n \n return this.formatLimits(limits, decimals, symbol);\n }\n \n /**\n * Format raw limits for display\n */\n formatLimits(\n limits: SpendingLimits,\n decimals: number = 18,\n symbol: string = 'ETH'\n ): FormattedSpendingLimits {\n const hasDailyLimit = limits.dailyLimit > 0n;\n \n // Convert to number for display (safe for typical amounts)\n const toNumber = (val: bigint): number => {\n const divisor = 10n ** BigInt(decimals);\n return Number(val * 10000n / divisor) / 10000;\n };\n \n return {\n dailyLimit: hasDailyLimit \n ? formatLargeAmount(limits.dailyLimit, decimals, symbol)\n : 'Unlimited',\n dailyLimitValue: toNumber(limits.dailyLimit),\n dailySpent: formatLargeAmount(limits.dailySpent, decimals, symbol),\n dailySpentValue: toNumber(limits.dailySpent),\n dailyRemaining: hasDailyLimit \n ? formatLargeAmount(limits.dailyRemaining, decimals, symbol)\n : 'Unlimited',\n dailyRemainingValue: toNumber(limits.dailyRemaining),\n dailyUsedPercentage: hasDailyLimit \n ? calculatePercentage(limits.dailySpent, limits.dailyLimit)\n : 0,\n timeUntilReset: formatDuration(limits.timeUntilReset).formatted,\n transactionLimit: limits.transactionLimit > 0n\n ? formatLargeAmount(limits.transactionLimit, decimals, symbol)\n : 'Unlimited',\n transactionLimitValue: toNumber(limits.transactionLimit),\n isPaused: limits.isPaused,\n hasDailyLimit,\n hasTransactionLimit: limits.transactionLimit > 0n,\n };\n }\n \n // ============================================================================\n // Limit Checks\n // ============================================================================\n \n /**\n * Check if a transaction amount is within limits\n * @param vaultAddress - Vault to check\n * @param chainId - Chain ID\n * @param amount - Amount to transfer (in base units)\n * @returns Result indicating if transfer is allowed\n */\n async checkTransactionLimit(\n vaultAddress: string,\n chainId: number,\n amount: bigint,\n options?: { rpcUrl?: string }\n ): Promise<LimitCheckResult> {\n const limits = await this.getSpendingLimits(vaultAddress, chainId, options?.rpcUrl);\n \n // Check if paused first\n if (limits.isPaused) {\n return {\n allowed: false,\n reason: 'vault_paused',\n message: 'Vault is paused. Unpause to continue.',\n suggestions: [\n {\n action: 'unpause_vault',\n label: 'Unpause Vault',\n },\n ],\n };\n }\n \n // Check per-transaction limit\n if (limits.transactionLimit > 0n && amount > limits.transactionLimit) {\n return {\n allowed: false,\n reason: 'transaction_limit_exceeded',\n message: `Transaction exceeds per-transaction limit of ${formatLargeAmount(limits.transactionLimit, this.config.defaultDecimals, this.config.defaultSymbol)}`,\n allowedAmount: limits.transactionLimit,\n excessAmount: amount - limits.transactionLimit,\n suggestions: [\n {\n action: 'send_partial',\n label: `Send ${formatLargeAmount(limits.transactionLimit, this.config.defaultDecimals, this.config.defaultSymbol)} (within limit)`,\n data: { amount: limits.transactionLimit },\n },\n {\n action: 'increase_limit',\n label: 'Increase Transaction Limit',\n },\n ],\n };\n }\n \n // Check daily limit\n if (limits.dailyLimit > 0n) {\n const wouldSpend = limits.dailySpent + amount;\n \n if (wouldSpend > limits.dailyLimit) {\n const excessAmount = wouldSpend - limits.dailyLimit;\n const suggestions: LimitViolationSuggestion[] = [];\n \n // Suggest partial transfer if some amount is available\n if (limits.dailyRemaining > 0n) {\n suggestions.push({\n action: 'send_partial',\n label: `Send ${formatLargeAmount(limits.dailyRemaining, this.config.defaultDecimals, this.config.defaultSymbol)} (within limit)`,\n data: { amount: limits.dailyRemaining },\n });\n }\n \n suggestions.push({\n action: 'increase_limit',\n label: 'Increase Daily Limit',\n data: { newLimit: wouldSpend },\n });\n \n suggestions.push({\n action: 'wait_for_reset',\n label: `Wait ${formatDuration(limits.timeUntilReset).formatted} for limit reset`,\n data: { waitTimeMs: limits.timeUntilReset },\n });\n \n return {\n allowed: false,\n reason: 'daily_limit_exceeded',\n message: `Transaction would exceed daily limit. Already spent ${formatLargeAmount(limits.dailySpent, this.config.defaultDecimals, this.config.defaultSymbol)} of ${formatLargeAmount(limits.dailyLimit, this.config.defaultDecimals, this.config.defaultSymbol)} today.`,\n allowedAmount: limits.dailyRemaining,\n excessAmount,\n waitTime: limits.timeUntilReset,\n suggestions,\n };\n }\n }\n \n return {\n allowed: true,\n message: 'Transaction is within limits',\n };\n }\n \n // ============================================================================\n // Limit Configuration (Prepare for Signing)\n // ============================================================================\n \n /**\n * Prepare a transaction to update the daily spending limit\n * Returns the config action payload that needs to be signed via passkey\n * \n * @param newLimit - New daily limit in base units (0 = unlimited)\n * @returns Config action payload for signing\n */\n prepareDailyLimitUpdate(newLimit: bigint): string {\n // Config type 1 = daily limit update\n // Config data format: [limit(32)]\n const limitBytes = ethers.zeroPadValue(ethers.toBeHex(newLimit), 32);\n return encodeConfigAction(CONFIG_TYPE.DAILY_LIMIT, limitBytes);\n }\n \n /**\n * Prepare a transaction to pause the vault\n * @returns Config action payload for signing\n */\n preparePauseVault(): string {\n // Config type 2 = pause, config data: [paused(1)] where 1 = paused\n const pausedByte = ethers.toBeHex(1, 1);\n return encodeConfigAction(CONFIG_TYPE.PAUSE, pausedByte);\n }\n \n /**\n * Prepare a transaction to unpause the vault\n * @returns Config action payload for signing\n */\n prepareUnpauseVault(): string {\n // Config type 2 = pause, config data: [paused(1)] where 0 = unpaused\n const unpausedByte = ethers.toBeHex(0, 1);\n return encodeConfigAction(CONFIG_TYPE.PAUSE, unpausedByte);\n }\n \n /**\n * Get the full spending limit configuration encoded as config payload\n * Used during vault creation to set initial limits\n */\n encodeInitialLimits(config: SpendingLimitConfig): string {\n if (!config.dailyLimit || config.dailyLimit === 0n) {\n // No limit configuration needed\n return '';\n }\n return this.prepareDailyLimitUpdate(config.dailyLimit);\n }\n \n // ============================================================================\n // Transaction History\n // ============================================================================\n \n /**\n * Get recent spending transactions for a vault\n * Note: This requires indexer integration for full history\n * @param vaultAddress - Vault to query\n * @param chainId - Chain ID\n * @param limit - Maximum number of transactions to return\n */\n async getRecentTransactions(\n vaultAddress: string,\n chainId: number,\n limit: number = 10\n ): Promise<SpendingTransaction[]> {\n // Note: Full implementation requires indexer/subgraph integration\n // For now, return empty array - UI should handle gracefully\n // In production, this would query a subgraph or indexer API\n console.log(`[SpendingLimitsManager] getRecentTransactions not fully implemented. Vault: ${vaultAddress}, Chain: ${chainId}, Limit: ${limit}`);\n return [];\n }\n \n /**\n * Get daily spending summary\n */\n async getDailySpendingSummary(\n vaultAddress: string,\n chainId: number,\n date?: Date\n ): Promise<DailySpendingSummary> {\n const targetDate = date ?? new Date();\n const transactions = await this.getRecentTransactions(vaultAddress, chainId, 100);\n \n // Filter transactions from the target date\n const startOfDay = new Date(targetDate);\n startOfDay.setHours(0, 0, 0, 0);\n const endOfDay = new Date(startOfDay);\n endOfDay.setDate(endOfDay.getDate() + 1);\n \n const dayTransactions = transactions.filter(\n tx => tx.timestamp >= startOfDay && tx.timestamp < endOfDay\n );\n \n const totalSpent = dayTransactions.reduce(\n (sum, tx) => sum + tx.amount,\n 0n\n );\n \n return {\n date: targetDate,\n totalSpent,\n formattedTotal: formatLargeAmount(totalSpent, this.config.defaultDecimals, this.config.defaultSymbol),\n transactionCount: dayTransactions.length,\n transactions: dayTransactions,\n };\n }\n \n // ============================================================================\n // Event Subscription\n // ============================================================================\n \n /**\n * Subscribe to spending limit change events\n */\n onLimitChange(callback: SpendingLimitEventCallback): () => void {\n this.eventListeners.push(callback);\n return () => {\n const index = this.eventListeners.indexOf(callback);\n if (index >= 0) {\n this.eventListeners.splice(index, 1);\n }\n };\n }\n \n /**\n * Notify listeners of a limit change event\n * Call this after a successful limit update transaction\n */\n notifyLimitChange(event: SpendingLimitChangedEvent): void {\n for (const listener of this.eventListeners) {\n try {\n listener(event);\n } catch (error) {\n console.error('[SpendingLimitsManager] Event listener error:', error);\n }\n }\n }\n \n // ============================================================================\n // Countdown Timer\n // ============================================================================\n \n /**\n * Get a live countdown to daily limit reset\n * Returns an object with current time remaining that updates\n */\n async getResetCountdown(\n vaultAddress: string,\n chainId: number,\n options?: { rpcUrl?: string }\n ): Promise<{\n getCurrentTimeRemaining: () => DurationDisplay;\n timeUntilResetMs: number;\n resetTime: Date;\n }> {\n const limits = await this.getSpendingLimits(vaultAddress, chainId, options?.rpcUrl);\n const fetchTime = Date.now();\n \n return {\n getCurrentTimeRemaining: () => {\n const elapsed = Date.now() - fetchTime;\n const remaining = Math.max(0, limits.timeUntilReset - elapsed);\n return formatDuration(remaining);\n },\n timeUntilResetMs: limits.timeUntilReset,\n resetTime: limits.dayResetTime,\n };\n }\n \n // ============================================================================\n // Cache Management\n // ============================================================================\n \n /**\n * Clear the cache for a specific vault or all vaults\n */\n clearCache(vaultAddress?: string, chainId?: number): void {\n if (vaultAddress && chainId) {\n this.cache.delete(`${chainId}:${vaultAddress.toLowerCase()}`);\n } else {\n this.cache.clear();\n }\n }\n \n /**\n * Invalidate cache after a limit change\n */\n invalidateCacheAfterChange(vaultAddress: string, chainId: number): void {\n this.clearCache(vaultAddress, chainId);\n }\n \n // ============================================================================\n // Helpers\n // ============================================================================\n \n /**\n * Get a provider for the specified chain\n */\n private getProvider(chainId: number, rpcUrl?: string): ethers.Provider {\n const url = rpcUrl ?? this.config.rpcUrls[chainId];\n if (!url) {\n throw new Error(`No RPC URL configured for chain ${chainId}`);\n }\n return new ethers.JsonRpcProvider(url);\n }\n}\n\n// ============================================================================\n// Factory Function\n// ============================================================================\n\n/**\n * Create a SpendingLimitsManager instance\n */\nexport function createSpendingLimitsManager(\n config?: SpendingLimitsManagerConfig\n): SpendingLimitsManager {\n return new SpendingLimitsManager(config);\n}\n","/**\n * Veridex Protocol SDK - Spending Limits Type Definitions (Issue #27)\n * \n * Types for configuring, viewing, and enforcing spending limits on vaults.\n * Spending limits provide an additional security layer against:\n * - Compromised passkeys draining entire vault\n * - Accidental large transactions\n * - Malicious session key abuse\n * \n * Security Model:\n * - Limits are enforced on-chain by the vault contract\n * - Limit changes require passkey signature (Hub authentication)\n * - Circuit breaker auto-pauses vault on limit violation\n * - Daily limits reset 24 hours from first spend\n */\n\n// ============================================================================\n// Core Types\n// ============================================================================\n\n/**\n * Current spending limits and usage for a vault\n */\nexport interface SpendingLimits {\n /** Daily spending limit (0 = unlimited) */\n dailyLimit: bigint;\n \n /** Amount spent in current 24-hour period */\n dailySpent: bigint;\n \n /** Remaining daily allowance */\n dailyRemaining: bigint;\n \n /** When the daily counter resets (UTC timestamp) */\n dayResetTime: Date;\n \n /** Time remaining until daily reset (milliseconds) */\n timeUntilReset: number;\n \n /** Per-transaction limit (0 = unlimited) */\n transactionLimit: bigint;\n \n /** Whether the vault is currently paused */\n isPaused: boolean;\n \n /** Last updated timestamp */\n lastUpdated: Date;\n \n /** Chain where these limits are enforced */\n chainId: number;\n}\n\n/**\n * Formatted spending limits for UI display\n */\nexport interface FormattedSpendingLimits {\n /** Daily limit as human-readable string (e.g., \"1,000 USDC\") */\n dailyLimit: string;\n \n /** Daily limit as raw number for calculations */\n dailyLimitValue: number;\n \n /** Amount spent today as human-readable string */\n dailySpent: string;\n \n /** Amount spent as raw number */\n dailySpentValue: number;\n \n /** Remaining daily allowance as human-readable string */\n dailyRemaining: string;\n \n /** Remaining as raw number */\n dailyRemainingValue: number;\n \n /** Percentage of daily limit used (0-100) */\n dailyUsedPercentage: number;\n \n /** Time until reset as human-readable string (e.g., \"6h 23m\") */\n timeUntilReset: string;\n \n /** Transaction limit as human-readable string */\n transactionLimit: string;\n \n /** Transaction limit as raw number */\n transactionLimitValue: number;\n \n /** Whether the vault is paused */\n isPaused: boolean;\n \n /** Whether daily limit is set (false = unlimited) */\n hasDailyLimit: boolean;\n \n /** Whether transaction limit is set (false = unlimited) */\n hasTransactionLimit: boolean;\n}\n\n/**\n * Spending limit configuration during vault creation\n */\nexport interface SpendingLimitConfig {\n /** Daily spending limit (optional, 0 = unlimited) */\n dailyLimit?: bigint;\n \n /** Per-transaction limit (optional, 0 = unlimited) */\n transactionLimit?: bigint;\n \n /** Whether to require 2FA for transactions above threshold */\n requireMultiSigAbove?: bigint;\n \n /** Whitelisted recipients (unlimited transfers allowed) */\n whitelistedRecipients?: string[];\n}\n\n/**\n * Parameters for setting daily limit\n */\nexport interface SetDailyLimitParams {\n /** New daily limit in wei/lamports/base units */\n limit: bigint;\n \n /** Optional chain to configure (defaults to current chain) */\n chainId?: number;\n}\n\n/**\n * Parameters for setting transaction limit\n */\nexport interface SetTransactionLimitParams {\n /** New transaction limit in wei/lamports/base units */\n limit: bigint;\n \n /** Optional chain to configure (defaults to current chain) */\n chainId?: number;\n}\n\n// ============================================================================\n// Limit Enforcement Types\n// ============================================================================\n\n/**\n * Result of checking if a transaction is within limits\n */\nexport interface LimitCheckResult {\n /** Whether the transaction is allowed */\n allowed: boolean;\n \n /** Reason code if not allowed */\n reason?: LimitViolationType;\n \n /** Human-readable message */\n message: string;\n \n /** Amount that would be allowed (if partially allowed) */\n allowedAmount?: bigint;\n \n /** Amount that exceeds limit */\n excessAmount?: bigint;\n \n /** Time to wait if daily limit reached */\n waitTime?: number;\n \n /** Suggested actions for the user */\n suggestions?: LimitViolationSuggestion[];\n}\n\n/**\n * Types of limit violations\n */\nexport type LimitViolationType =\n | 'daily_limit_exceeded'\n | 'transaction_limit_exceeded'\n | 'vault_paused'\n | 'insufficient_balance'\n | 'daily_limit_would_exceed';\n\n/**\n * Suggestion for resolving a limit violation\n */\nexport interface LimitViolationSuggestion {\n /** Action type */\n action: 'send_partial' | 'increase_limit' | 'wait_for_reset' | 'unpause_vault';\n \n /** Human-readable label */\n label: string;\n \n /** Additional data for the action */\n data?: {\n amount?: bigint;\n waitTimeMs?: number;\n newLimit?: bigint;\n };\n}\n\n// ============================================================================\n// Transaction History Types\n// ============================================================================\n\n/**\n * A spending transaction in the history\n */\nexport interface SpendingTransaction {\n /** Transaction hash */\n hash: string;\n \n /** Amount spent (in wei/lamports) */\n amount: bigint;\n \n /** Human-readable amount */\n formattedAmount: string;\n \n /** Token symbol */\n tokenSymbol: string;\n \n /** Recipient address */\n recipient: string;\n \n /** Recipient display name (ENS, label, or truncated) */\n recipientDisplay: string;\n \n /** When the transaction occurred */\n timestamp: Date;\n \n /** Relative time (e.g., \"2h ago\") */\n relativeTime: string;\n \n /** Transaction type */\n type: 'transfer' | 'bridge' | 'execute';\n \n /** Whether this counted against daily limit */\n countedAgainstLimit: boolean;\n}\n\n/**\n * Daily spending summary\n */\nexport interface DailySpendingSummary {\n /** Date for this summary */\n date: Date;\n \n /** Total amount spent */\n totalSpent: bigint;\n \n /** Formatted total */\n formattedTotal: string;\n \n /** Number of transactions */\n transactionCount: number;\n \n /** Individual transactions */\n transactions: SpendingTransaction[];\n}\n\n// ============================================================================\n// Config Action Encoding\n// ============================================================================\n\n/**\n * Config types matching VeridexVault.sol\n */\nexport const CONFIG_TYPE = {\n /** Update daily limit */\n DAILY_LIMIT: 1,\n /** Pause/unpause vault */\n PAUSE: 2,\n /** Update guardians */\n GUARDIANS: 3,\n /** Register sender */\n REGISTER_SENDER: 4,\n /** Allow source chain */\n ALLOW_CHAIN: 5,\n /** Set query verifier */\n QUERY_VERIFIER: 6,\n} as const;\n\nexport type ConfigType = (typeof CONFIG_TYPE)[keyof typeof CONFIG_TYPE];\n\n// ============================================================================\n// Event Types\n// ============================================================================\n\n/**\n * Event emitted when spending limits change\n */\nexport interface SpendingLimitChangedEvent {\n /** Event type */\n type: 'daily_limit_changed' | 'transaction_limit_changed' | 'vault_paused' | 'vault_unpaused';\n \n /** Previous value */\n previousValue: bigint | boolean;\n \n /** New value */\n newValue: bigint | boolean;\n \n /** Transaction hash */\n txHash: string;\n \n /** Block timestamp */\n timestamp: Date;\n}\n\n/**\n * Callback for spending limit events\n */\nexport type SpendingLimitEventCallback = (event: SpendingLimitChangedEvent) => void;\n\n// ============================================================================\n// Preset Configurations\n// ============================================================================\n\n/**\n * Predefined spending limit configurations\n */\nexport interface LimitPreset {\n /** Preset identifier */\n id: string;\n \n /** Display name */\n name: string;\n \n /** Description */\n description: string;\n \n /** Daily limit suggestion (in USD equivalent) */\n dailyLimitUsd: number;\n \n /** Transaction limit suggestion (in USD equivalent) */\n transactionLimitUsd: number;\n \n /** Icon for UI */\n icon: string;\n \n /** Recommended for user type */\n recommendedFor: string;\n}\n\n/**\n * Standard limit presets\n */\nexport const LIMIT_PRESETS: LimitPreset[] = [\n {\n id: 'conservative',\n name: 'Conservative',\n description: 'Low limits for maximum security',\n dailyLimitUsd: 500,\n transactionLimitUsd: 100,\n icon: '🔒',\n recommendedFor: 'New users or high-value vaults',\n },\n {\n id: 'balanced',\n name: 'Balanced',\n description: 'Moderate limits for everyday use',\n dailyLimitUsd: 2500,\n transactionLimitUsd: 500,\n icon: '⚖️',\n recommendedFor: 'Regular users',\n },\n {\n id: 'generous',\n name: 'Generous',\n description: 'Higher limits for active traders',\n dailyLimitUsd: 10000,\n transactionLimitUsd: 2500,\n icon: '🚀',\n recommendedFor: 'Active traders and power users',\n },\n {\n id: 'unlimited',\n name: 'No Limits',\n description: 'No spending restrictions (not recommended)',\n dailyLimitUsd: 0, // 0 = unlimited\n transactionLimitUsd: 0,\n icon: '⚠️',\n recommendedFor: 'Advanced users who accept full risk',\n },\n];\n\n// ============================================================================\n// Utility Types\n// ============================================================================\n\n/**\n * Duration display for reset countdown\n */\nexport interface DurationDisplay {\n hours: number;\n minutes: number;\n seconds: number;\n formatted: string; // e.g., \"6h 23m\"\n}\n\n/**\n * Calculate duration display from milliseconds\n */\nexport function formatDuration(ms: number): DurationDisplay {\n const totalSeconds = Math.max(0, Math.floor(ms / 1000));\n const hours = Math.floor(totalSeconds / 3600);\n const minutes = Math.floor((totalSeconds % 3600) / 60);\n const seconds = totalSeconds % 60;\n \n let formatted: string;\n if (hours > 0) {\n formatted = `${hours}h ${minutes}m`;\n } else if (minutes > 0) {\n formatted = `${minutes}m ${seconds}s`;\n } else {\n formatted = `${seconds}s`;\n }\n \n return { hours, minutes, seconds, formatted };\n}\n\n/**\n * Calculate percentage safely (handles zero division)\n */\nexport function calculatePercentage(spent: bigint, limit: bigint): number {\n if (limit === 0n) return 0;\n // Use fixed-point math to avoid precision loss\n const percentage = Number((spent * 10000n) / limit) / 100;\n return Math.min(100, Math.max(0, percentage));\n}\n\n/**\n * Format large numbers with appropriate units\n */\nexport function formatLargeAmount(\n amount: bigint,\n decimals: number = 18,\n symbol: string = 'ETH'\n): string {\n const divisor = 10n ** BigInt(decimals);\n const whole = amount / divisor;\n const fraction = amount % divisor;\n \n // Format with up to 4 decimal places\n const fractionStr = fraction.toString().padStart(decimals, '0').slice(0, 4);\n const trimmedFraction = fractionStr.replace(/0+$/, '');\n \n const numStr = trimmedFraction \n ? `${whole.toLocaleString()}.${trimmedFraction}`\n : whole.toLocaleString();\n \n return `${numStr} ${symbol}`;\n}\n","/**\n * Veridex Protocol SDK - Main SDK Class\n */\n\nimport { PasskeyManager } from './PasskeyManager.js';\nimport { WalletManager } from './WalletManager.js';\nimport { BalanceManager, type TokenBalance, type PortfolioBalance } from './BalanceManager.js';\nimport { TransactionTracker, type TransactionState, type TransactionCallback } from './TransactionTracker.js';\nimport { \n CrossChainManager, \n type CrossChainResult,\n type CrossChainFees,\n type CrossChainProgressCallback,\n} from './CrossChainManager.js';\nimport { RelayerClient, type SubmitSignedActionRequest } from './RelayerClient.js';\nimport { ChainDetector } from './ChainDetector.js';\nimport { TransactionParser } from './TransactionParser.js';\nimport type { TransactionSummary } from './TransactionSummary.types.js';\nimport { SpendingLimitsManager } from './SpendingLimitsManager.js';\nimport type { SpendingLimits, FormattedSpendingLimits, LimitCheckResult } from './SpendingLimits.types.js';\nimport { ethers } from 'ethers';\nimport { authenticateAndPrepare } from '../auth/prepareAuth.js';\nimport { queryPortfolio } from '../queries/portfolio.js';\nimport { \n GasSponsor, \n type SponsoredVaultResult, \n type MultiChainVaultResult,\n type ChainDeploymentConfig,\n} from './GasSponsor.js';\nimport { buildChallenge, buildGaslessChallenge } from '../payload.js';\nimport { normalizeEmitterAddress } from '../wormhole.js';\nimport { \n getAllTokens, \n getTokenBySymbol, \n isNativeToken,\n type TokenInfo \n} from '../constants/tokens.js';\nimport type {\n VeridexConfig,\n ChainClient,\n PasskeyCredential,\n TransferParams,\n ExecuteParams,\n BridgeParams,\n DispatchResult,\n VaultInfo,\n UnifiedIdentity,\n ChainAddress,\n VaultCreationResult,\n PreparedTransfer,\n TransferResult,\n ReceiveAddress,\n BridgeResult,\n PreparedBridge,\n IdentityState,\n AddBackupKeyResult,\n RemoveKeyResult,\n AuthorizedKey,\n} from './types.js';\n\n/** Expiration time for prepared transfers (5 minutes) */\nconst PREPARED_TRANSFER_TTL = 5 * 60 * 1000;\n\nexport class VeridexSDK {\n public readonly passkey: PasskeyManager;\n public readonly wallet: WalletManager;\n public readonly balance: BalanceManager;\n public readonly transactions: TransactionTracker;\n public readonly crossChain: CrossChainManager;\n public readonly sponsor: GasSponsor;\n public readonly transactionParser: TransactionParser;\n public readonly spendingLimits: SpendingLimitsManager;\n private readonly chain: ChainClient;\n private readonly relayer?: RelayerClient;\n // TODO: Use relayerApiKey when relayer integration is complete (Issue #8)\n // private readonly relayerApiKey?: string;\n private readonly queryApiKey?: string;\n private readonly testnet: boolean;\n private readonly sponsorPrivateKey?: string;\n private readonly chainRpcUrls?: Record<number, string>;\n private readonly chainDetector: ChainDetector;\n private unifiedIdentity: UnifiedIdentity | null = null;\n\n constructor(config: VeridexConfig) {\n this.chain = config.chain;\n this.testnet = config.testnet ?? true;\n this.sponsorPrivateKey = config.sponsorPrivateKey;\n this.chainRpcUrls = config.chainRpcUrls;\n // TODO: Uncomment when relayerApiKey is used (Issue #8)\n // this.relayerApiKey = config.relayerApiKey;\n this.queryApiKey = config.queryApiKey ?? config.relayerApiKey;\n this.passkey = new PasskeyManager({\n relayerUrl: config.relayerUrl,\n });\n this.wallet = new WalletManager({\n cacheAddresses: true,\n persistToStorage: config.persistWallet ?? true,\n });\n this.balance = new BalanceManager({\n cacheBalances: true,\n cacheTtl: 30_000, // 30 seconds\n customRpcUrls: config.chainRpcUrls ?? {},\n });\n this.transactions = new TransactionTracker({\n pollingInterval: 2000,\n requiredConfirmations: 1,\n });\n\n this.chainDetector = new ChainDetector({\n testnet: this.testnet,\n rpcUrls: config.chainRpcUrls ?? {},\n });\n this.crossChain = new CrossChainManager({\n testnet: this.testnet,\n relayerUrl: config.relayerUrl,\n autoRelay: !!config.relayerUrl,\n });\n this.sponsor = new GasSponsor({\n // Veridex fallback sponsorship\n sponsorPrivateKey: config.sponsorPrivateKey,\n // Integrator-provided sponsorship (takes priority over Veridex)\n integratorSponsorKey: config.integratorSponsorKey,\n // Relayer for remote sponsorship (future primary method)\n relayerUrl: config.relayerUrl,\n relayerApiKey: config.relayerApiKey,\n // Chain configuration\n testnet: this.testnet,\n customRpcUrls: config.chainRpcUrls,\n });\n\n // Initialize relayer client if URL provided\n if (config.relayerUrl) {\n this.relayer = new RelayerClient({\n baseUrl: config.relayerUrl,\n apiKey: config.relayerApiKey,\n });\n }\n\n // Initialize transaction parser for human-readable summaries (Issue #26)\n this.transactionParser = new TransactionParser({\n defaultChainId: this.chain.getConfig().wormholeChainId,\n // TODO: Integrate ENS resolution via relayer when available\n // resolveEnsName: async (address) => { ... }\n // TODO: Integrate price oracle when available\n // getTokenPrice: async (token, chainId) => { ... }\n });\n\n // Initialize spending limits manager (Issue #27)\n this.spendingLimits = new SpendingLimitsManager({\n defaultDecimals: 18,\n defaultSymbol: this.chain.getConfig().name.includes('Solana') ? 'SOL' : 'ETH',\n rpcUrls: config.chainRpcUrls ?? {},\n cacheTtl: 10000, // 10 seconds\n });\n }\n\n getChainConfig() {\n return this.chain.getConfig();\n }\n\n getChainClient(): ChainClient {\n return this.chain;\n }\n\n async getNonce(): Promise<bigint> {\n const credential = this.passkey.getCredential();\n if (!credential) {\n throw new Error('No credential set. Call passkey.register() or passkey.setCredential() first.');\n }\n return await this.chain.getNonce(credential.keyHash);\n }\n\n async getMessageFee(): Promise<bigint> {\n return await this.chain.getMessageFee();\n }\n\n async buildTransferPayload(params: TransferParams): Promise<string> {\n return await this.chain.buildTransferPayload(params);\n }\n\n async buildExecutePayload(params: ExecuteParams): Promise<string> {\n return await this.chain.buildExecutePayload(params);\n }\n\n async buildBridgePayload(params: BridgeParams): Promise<string> {\n return await this.chain.buildBridgePayload(params);\n }\n\n async transfer(params: TransferParams, signer: any): Promise<DispatchResult> {\n const credential = this.passkey.getCredential();\n if (!credential) {\n throw new Error('No credential set. Call passkey.register() or passkey.setCredential() first.');\n }\n\n const actionPayload = await this.buildTransferPayload(params);\n const nonce = await this.getNonce();\n const challenge = buildChallenge(\n credential.keyHash,\n params.targetChain,\n nonce,\n actionPayload\n );\n\n const signature = await this.passkey.sign(challenge);\n\n return await this.chain.dispatch(\n signature,\n credential.publicKeyX,\n credential.publicKeyY,\n params.targetChain,\n actionPayload,\n nonce,\n signer\n );\n }\n\n async execute(params: ExecuteParams, signer: any): Promise<DispatchResult> {\n const credential = this.passkey.getCredential();\n if (!credential) {\n throw new Error('No credential set');\n }\n\n const actionPayload = await this.buildExecutePayload(params);\n const nonce = await this.getNonce();\n const challenge = buildChallenge(\n credential.keyHash,\n params.targetChain,\n nonce,\n actionPayload\n );\n\n const signature = await this.passkey.sign(challenge);\n\n return await this.chain.dispatch(\n signature,\n credential.publicKeyX,\n credential.publicKeyY,\n params.targetChain,\n actionPayload,\n nonce,\n signer\n );\n }\n\n async bridge(params: BridgeParams, signer: any): Promise<DispatchResult> {\n const credential = this.passkey.getCredential();\n if (!credential) {\n throw new Error('No credential set');\n }\n\n const actionPayload = await this.buildBridgePayload(params);\n const nonce = await this.getNonce();\n\n const challenge = buildChallenge(\n credential.keyHash,\n params.sourceChain,\n nonce,\n actionPayload\n );\n\n const signature = await this.passkey.sign(challenge);\n\n return await this.chain.dispatch(\n signature,\n credential.publicKeyX,\n credential.publicKeyY,\n params.sourceChain,\n actionPayload,\n nonce,\n signer\n );\n }\n\n // ========================================================================\n // Phase 3: Cross-Chain Transfers\n // ========================================================================\n\n /**\n * Prepare a bridge/cross-chain transfer with fee estimation\n * \n * @param params - Bridge parameters\n * @returns PreparedBridge with fee estimates\n */\n async prepareBridge(params: BridgeParams): Promise<PreparedBridge> {\n const credential = this.passkey.getCredential();\n if (!credential) {\n throw new Error('No credential set. Call passkey.register() or passkey.setCredential() first.');\n }\n\n // Build payload and get nonce\n const actionPayload = await this.buildBridgePayload(params);\n const nonce = await this.getNonce();\n \n // Build challenge\n const challenge = buildChallenge(\n credential.keyHash,\n params.sourceChain,\n nonce,\n actionPayload\n );\n\n // Get chain config\n const chainConfig = this.chain.getConfig();\n\n // Estimate fees using CrossChainManager\n const evmClient = this.chain as any;\n const provider = evmClient.provider ?? evmClient.getProvider?.();\n \n let fees: CrossChainFees = {\n sourceGas: 300_000n * 1_000_000_000n, // Default estimate\n messageFee: 0n,\n relayerFee: 0n,\n totalCost: 300_000n * 1_000_000_000n,\n formattedTotal: '0.0003 ETH',\n currency: 'ETH',\n };\n\n if (provider) {\n try {\n fees = await this.crossChain.estimateFees(params, chainConfig, provider);\n } catch (e) {\n console.warn('Fee estimation failed, using defaults:', e);\n }\n }\n\n return {\n params,\n actionPayload,\n nonce,\n challenge,\n fees,\n sourceChain: params.sourceChain,\n destinationChain: params.destinationChain,\n preparedAt: Date.now(),\n expiresAt: Date.now() + PREPARED_TRANSFER_TTL,\n };\n }\n\n /**\n * Execute a prepared bridge with full cross-chain tracking\n * \n * @param prepared - PreparedBridge from prepareBridge()\n * @param signer - Signer to pay for gas\n * @param onProgress - Optional callback for progress updates\n * @returns BridgeResult with cross-chain tracking info\n */\n async executeBridge(\n prepared: PreparedBridge,\n signer: any,\n onProgress?: CrossChainProgressCallback\n ): Promise<BridgeResult> {\n const credential = this.passkey.getCredential();\n if (!credential) {\n throw new Error('No credential set');\n }\n\n // Check expiration\n if (Date.now() > prepared.expiresAt) {\n throw new Error('Prepared bridge has expired. Please call prepareBridge() again.');\n }\n\n const startTime = Date.now();\n const chainConfig = this.chain.getConfig();\n const hubEmitter = normalizeEmitterAddress(chainConfig.contracts.hub ?? '');\n\n // Step 1: Sign with passkey\n onProgress?.({\n status: 'signing',\n step: 1,\n totalSteps: 6,\n message: 'Sign with your passkey...',\n });\n\n const signature = await this.passkey.sign(prepared.challenge);\n\n // Step 2: Dispatch transaction\n onProgress?.({\n status: 'dispatching',\n step: 2,\n totalSteps: 6,\n message: 'Submitting transaction to blockchain...',\n });\n\n const dispatchResult = await this.chain.dispatch(\n signature,\n credential.publicKeyX,\n credential.publicKeyY,\n prepared.params.sourceChain,\n prepared.actionPayload,\n prepared.nonce,\n signer\n );\n\n // Step 3: Wait for confirmations\n onProgress?.({\n status: 'waiting_confirmations',\n step: 3,\n totalSteps: 6,\n message: 'Waiting for block confirmations...',\n details: { txHash: dispatchResult.transactionHash },\n });\n\n // Track the cross-chain transfer\n this.crossChain.trackTransfer(\n dispatchResult.transactionHash,\n prepared.sourceChain,\n prepared.destinationChain,\n dispatchResult.sequence,\n hubEmitter\n );\n\n // Track in transaction tracker too\n this.transactions.track(\n dispatchResult.transactionHash,\n chainConfig.wormholeChainId,\n undefined,\n dispatchResult.sequence\n );\n\n // Step 4-5: Fetch VAA (CrossChainManager handles this)\n let vaa: string | undefined;\n try {\n vaa = await this.crossChain.fetchVAAByTxHash(\n dispatchResult.transactionHash,\n onProgress\n );\n \n this.crossChain.completeTransfer(\n dispatchResult.transactionHash,\n vaa\n );\n } catch (error) {\n // VAA fetch failed, but transaction was successful\n // User can retry VAA fetch later\n console.warn('VAA fetch failed:', error);\n }\n\n // Step 6: Submit to relayer (if configured)\n // The relayer auto-relays by observing hub Dispatch events; there is\n // currently no relay-job API to poll for destination tx hashes.\n let destinationTxHash: string | undefined;\n if (vaa && this.relayer) {\n onProgress?.({\n status: 'relaying',\n step: 6,\n totalSteps: 6,\n message: 'Relayer will submit to destination chain automatically...',\n });\n }\n\n onProgress?.({\n status: 'completed',\n step: 6,\n totalSteps: 6,\n message: 'Cross-chain transfer complete!',\n details: {\n txHash: dispatchResult.transactionHash,\n sequence: dispatchResult.sequence,\n vaaReady: !!vaa,\n destinationTxHash,\n },\n });\n\n // Invalidate balance cache\n const vaultAddress = this.getVaultAddress();\n this.balance.invalidateCache(chainConfig.wormholeChainId, vaultAddress);\n\n return {\n ...dispatchResult,\n params: prepared.params,\n sourceChain: prepared.sourceChain,\n destinationChain: prepared.destinationChain,\n vaa,\n destinationTxHash,\n duration: Date.now() - startTime,\n timestamp: Date.now(),\n };\n }\n\n /**\n * Execute a gasless bridge using the relayer\n *\n * The relayer pays for the Hub transaction (and Wormhole fee), then observes\n * the resulting Dispatch event and relays the VAA to the destination spoke.\n */\n async bridgeViaRelayer(\n params: BridgeParams,\n onProgress?: CrossChainProgressCallback\n ): Promise<BridgeResult> {\n const credential = this.passkey.getCredential();\n if (!credential) {\n throw new Error('No credential set. Call passkey.register() or passkey.setCredential() first.');\n }\n\n if (!this.relayer) {\n throw new Error('Relayer not configured. Please provide relayerUrl in SDK config.');\n }\n\n const startTime = Date.now();\n\n onProgress?.({\n status: 'preparing',\n step: 0,\n totalSteps: 6,\n message: 'Preparing gasless bridge...',\n });\n\n // Bridge actions target the *sourceChain* (where the vault holds funds)\n const actionPayload = await this.buildBridgePayload(params);\n const nonce = await this.getNonce();\n const chainConfig = this.chain.getConfig();\n const hubChainId = chainConfig.hubChainId ?? chainConfig.wormholeChainId;\n\n onProgress?.({\n status: 'signing',\n step: 1,\n totalSteps: 6,\n message: 'Sign with your passkey...',\n });\n\n const challenge = buildGaslessChallenge(\n params.sourceChain,\n actionPayload,\n nonce,\n hubChainId\n );\n const signature = await this.passkey.sign(challenge);\n\n onProgress?.({\n status: 'dispatching',\n step: 2,\n totalSteps: 6,\n message: 'Submitting gasless bridge to relayer...',\n });\n\n // Use full WebAuthn data for authenticateAndDispatch\n const submitRequest: SubmitSignedActionRequest = {\n authenticatorData: signature.authenticatorData,\n clientDataJSON: signature.clientDataJSON,\n challengeIndex: signature.challengeIndex,\n typeIndex: signature.typeIndex,\n r: '0x' + signature.r.toString(16).padStart(64, '0'),\n s: '0x' + signature.s.toString(16).padStart(64, '0'),\n publicKeyX: '0x' + credential.publicKeyX.toString(16).padStart(64, '0'),\n publicKeyY: '0x' + credential.publicKeyY.toString(16).padStart(64, '0'),\n targetChain: params.sourceChain,\n actionPayload,\n nonce: Number(nonce),\n };\n\n const relayerResult = await this.relayer.submitSignedAction(submitRequest);\n if (!relayerResult.success) {\n throw new Error(`Relayer submission failed: ${relayerResult.error}`);\n }\n\n const txHash = relayerResult.txHash ?? '';\n const sequence = relayerResult.sequence ? BigInt(relayerResult.sequence) : 0n;\n\n if (txHash) {\n this.transactions.track(txHash, hubChainId, undefined, sequence || undefined);\n }\n\n // Try to fetch VAA for UI feedback (relayer will still execute even if this fails)\n let vaa: string | undefined;\n try {\n vaa = await this.crossChain.fetchVAAByTxHash(txHash, onProgress);\n } catch {\n // ignore: user can retry fetch later\n }\n\n onProgress?.({\n status: 'completed',\n step: 6,\n totalSteps: 6,\n message: 'Gasless bridge submitted. Relayer will complete execution.',\n details: {\n txHash,\n sequence,\n vaaReady: !!vaa,\n },\n });\n\n return {\n transactionHash: txHash,\n sequence,\n userKeyHash: credential.keyHash,\n targetChain: params.sourceChain,\n blockNumber: 0,\n params,\n sourceChain: params.sourceChain,\n destinationChain: params.destinationChain,\n vaa,\n destinationTxHash: undefined,\n duration: Date.now() - startTime,\n timestamp: Date.now(),\n };\n }\n\n /**\n * Execute a full bridge with automatic preparation\n * \n * @param params - Bridge parameters\n * @param signer - Signer to pay for gas\n * @param onProgress - Optional callback for progress updates\n * @returns BridgeResult with cross-chain tracking info\n */\n async bridgeWithTracking(\n params: BridgeParams,\n signer: any,\n onProgress?: CrossChainProgressCallback\n ): Promise<BridgeResult> {\n onProgress?.({\n status: 'preparing',\n step: 0,\n totalSteps: 6,\n message: 'Preparing cross-chain transfer...',\n });\n\n const prepared = await this.prepareBridge(params);\n return await this.executeBridge(prepared, signer, onProgress);\n }\n\n /**\n * Fetch VAA for a completed transaction\n * Use this if VAA fetch failed during bridge execution\n * \n * @param txHash - Source chain transaction hash\n * @returns VAA base64 string\n */\n async fetchVAAForTransaction(txHash: string): Promise<string> {\n return await this.crossChain.fetchVAAByTxHash(txHash);\n }\n\n /**\n * Get cross-chain transfer fees\n * \n * @param params - Bridge parameters\n * @returns CrossChainFees with breakdown\n */\n async getBridgeFees(params: BridgeParams): Promise<CrossChainFees> {\n const chainConfig = this.chain.getConfig();\n const evmClient = this.chain as any;\n const provider = evmClient.provider ?? evmClient.getProvider?.();\n\n if (!provider) {\n throw new Error('Provider not available');\n }\n\n return await this.crossChain.estimateFees(params, chainConfig, provider);\n }\n\n /**\n * Get all pending cross-chain transfers\n */\n getPendingBridges(): CrossChainResult[] {\n return this.crossChain.getAllPendingTransfers();\n }\n\n /**\n * Get Wormholescan explorer URL for a cross-chain transfer\n */\n getWormholeExplorerUrl(sequence: bigint): string {\n const chainConfig = this.chain.getConfig();\n const hubEmitter = chainConfig.contracts.hub ?? '';\n return this.crossChain.getWormholeExplorerUrl(\n chainConfig.wormholeChainId,\n hubEmitter,\n sequence\n );\n }\n\n // ========================================================================\n // Phase 2: Send & Receive Funds\n // ========================================================================\n\n /**\n * Prepare a transfer with gas estimation\n * Call this before transfer() to show user the cost\n * \n * @param params - Transfer parameters\n * @returns PreparedTransfer with gas estimates and challenge\n */\n async prepareTransfer(params: TransferParams): Promise<PreparedTransfer> {\n const credential = this.passkey.getCredential();\n if (!credential) {\n throw new Error('No credential set. Call passkey.register() or passkey.setCredential() first.');\n }\n\n // Build payload and get nonce\n const actionPayload = await this.buildTransferPayload(params);\n const nonce = await this.getNonce();\n \n // Build challenge\n const challenge = buildChallenge(\n credential.keyHash,\n params.targetChain,\n nonce,\n actionPayload\n );\n\n // Get gas estimates - need to type cast for EVM-specific methods\n const evmClient = this.chain as any;\n let estimatedGas = 500000n; // Default\n let gasPrice = 0n;\n \n if (typeof evmClient.getGasPrice === 'function') {\n gasPrice = await evmClient.getGasPrice();\n }\n\n // Get message fee\n const messageFee = await this.getMessageFee();\n\n // Calculate total cost\n const gasCost = estimatedGas * gasPrice;\n const totalCost = gasCost + messageFee;\n const formattedCost = this.formatWei(totalCost);\n\n return {\n params,\n actionPayload,\n nonce,\n challenge,\n estimatedGas,\n gasPrice,\n messageFee,\n totalCost,\n formattedCost,\n preparedAt: Date.now(),\n expiresAt: Date.now() + PREPARED_TRANSFER_TTL,\n };\n }\n\n /**\n * Get a human-readable summary of a prepared transfer (Issue #26)\n * \n * Use this to show users what they're signing before biometric authentication.\n * The summary includes:\n * - Action type (transfer, bridge, execute, config)\n * - Human-readable amounts (not wei)\n * - Recipient display (truncated address, ENS if available)\n * - Chain information\n * - Risk warnings for unusual transactions\n * - Gas cost breakdown\n * - Expiration countdown\n * \n * @example\n * ```typescript\n * const prepared = await sdk.prepareTransfer({\n * recipient: '0x123...',\n * amount: '1000000000000000000', // 1 ETH in wei\n * tokenAddress: NATIVE_TOKEN_ADDRESS,\n * targetChain: 10004, // Base Sepolia\n * });\n * \n * const summary = await sdk.getTransactionSummary(prepared);\n * console.log(summary.title); // \"Transfer\"\n * console.log(summary.description); // \"Send 1.0 ETH to 0x123...abc\"\n * console.log(summary.details.formattedAmount); // \"1.0\"\n * console.log(summary.risks); // [{ type: 'large_transaction', level: 'high', ... }]\n * ```\n * \n * @param prepared - PreparedTransfer or PreparedBridge from prepare methods\n * @returns Promise<TransactionSummary> with human-readable details\n */\n async getTransactionSummary(prepared: PreparedTransfer | PreparedBridge): Promise<TransactionSummary> {\n return this.transactionParser.parse(prepared);\n }\n\n // ============================================================================\n // Spending Limits (Issue #27)\n // ============================================================================\n\n /**\n * Get current spending limits for your vault\n * \n * @example\n * ```typescript\n * const limits = await sdk.getSpendingLimits();\n * console.log(`Daily remaining: ${limits.dailyRemaining}`);\n * console.log(`Resets in: ${limits.timeUntilReset}ms`);\n * ```\n * \n * @param chainId - Optional chain ID (defaults to current chain)\n * @returns Promise<SpendingLimits> with current limits and usage\n */\n async getSpendingLimits(chainId?: number): Promise<SpendingLimits> {\n const vaultAddress = this.getVaultAddress();\n const effectiveChainId = chainId ?? this.chain.getConfig().wormholeChainId;\n const rpcUrl = this.chainRpcUrls?.[effectiveChainId] ?? this.chain.getConfig().rpcUrl;\n \n return this.spendingLimits.getSpendingLimits(vaultAddress, effectiveChainId, rpcUrl);\n }\n\n /**\n * Get spending limits formatted for UI display\n * \n * @example\n * ```typescript\n * const formatted = await sdk.getFormattedSpendingLimits();\n * console.log(`${formatted.dailyUsedPercentage}% of daily limit used`);\n * console.log(`Resets in: ${formatted.timeUntilReset}`);\n * ```\n */\n async getFormattedSpendingLimits(chainId?: number): Promise<FormattedSpendingLimits> {\n const vaultAddress = this.getVaultAddress();\n const effectiveChainId = chainId ?? this.chain.getConfig().wormholeChainId;\n const rpcUrl = this.chainRpcUrls?.[effectiveChainId] ?? this.chain.getConfig().rpcUrl;\n \n return this.spendingLimits.getFormattedSpendingLimits(vaultAddress, effectiveChainId, { rpcUrl });\n }\n\n /**\n * Check if a transaction amount is within spending limits\n * \n * @example\n * ```typescript\n * const check = await sdk.checkSpendingLimit(ethers.parseEther(\"1.0\"));\n * if (!check.allowed) {\n * console.log(check.message);\n * console.log('Suggestions:', check.suggestions);\n * }\n * ```\n * \n * @param amount - Amount to check (in wei/base units)\n * @param chainId - Optional chain ID\n * @returns LimitCheckResult with allowed status and suggestions\n */\n async checkSpendingLimit(amount: bigint, chainId?: number): Promise<LimitCheckResult> {\n const vaultAddress = this.getVaultAddress();\n const effectiveChainId = chainId ?? this.chain.getConfig().wormholeChainId;\n const rpcUrl = this.chainRpcUrls?.[effectiveChainId] ?? this.chain.getConfig().rpcUrl;\n \n return this.spendingLimits.checkTransactionLimit(vaultAddress, effectiveChainId, amount, { rpcUrl });\n }\n\n /**\n * Prepare a transaction to update the daily spending limit\n * Returns a PreparedTransfer that can be signed and executed\n * \n * @example\n * ```typescript\n * // Set daily limit to 5 ETH\n * const prepared = await sdk.prepareSetDailyLimit(ethers.parseEther(\"5.0\"));\n * const result = await sdk.executeTransfer(prepared, signer);\n * ```\n * \n * @param newLimit - New daily limit (0 = unlimited)\n * @returns PreparedTransfer for signing\n */\n async prepareSetDailyLimit(newLimit: bigint): Promise<PreparedTransfer> {\n const credential = this.passkey.getCredential();\n if (!credential) {\n throw new Error('No credential set');\n }\n\n const actionPayload = this.spendingLimits.prepareDailyLimitUpdate(newLimit);\n const nonce = await this.getNonce();\n const targetChain = this.chain.getConfig().wormholeChainId;\n const challenge = buildChallenge(credential.keyHash, targetChain, nonce, actionPayload);\n const messageFee = await this.getMessageFee();\n \n return {\n params: {\n targetChain,\n token: 'native',\n recipient: this.getVaultAddress(),\n amount: 0n,\n },\n actionPayload,\n nonce,\n challenge,\n estimatedGas: 0n,\n gasPrice: 0n,\n messageFee,\n totalCost: messageFee,\n formattedCost: '0',\n preparedAt: Date.now(),\n expiresAt: Date.now() + PREPARED_TRANSFER_TTL,\n };\n }\n\n /**\n * Prepare a transaction to pause the vault (emergency stop)\n * Pausing prevents all withdrawals until unpaused\n * \n * @example\n * ```typescript\n * const prepared = await sdk.preparePauseVault();\n * const result = await sdk.executeTransfer(prepared, signer);\n * ```\n */\n async preparePauseVault(): Promise<PreparedTransfer> {\n const credential = this.passkey.getCredential();\n if (!credential) {\n throw new Error('No credential set');\n }\n\n const actionPayload = this.spendingLimits.preparePauseVault();\n const nonce = await this.getNonce();\n const targetChain = this.chain.getConfig().wormholeChainId;\n const challenge = buildChallenge(credential.keyHash, targetChain, nonce, actionPayload);\n const messageFee = await this.getMessageFee();\n \n return {\n params: {\n targetChain,\n token: 'native',\n recipient: this.getVaultAddress(),\n amount: 0n,\n },\n actionPayload,\n nonce,\n challenge,\n estimatedGas: 0n,\n gasPrice: 0n,\n messageFee,\n totalCost: messageFee,\n formattedCost: '0',\n preparedAt: Date.now(),\n expiresAt: Date.now() + PREPARED_TRANSFER_TTL,\n };\n }\n\n /**\n * Prepare a transaction to unpause the vault\n * \n * @example\n * ```typescript\n * const prepared = await sdk.prepareUnpauseVault();\n * const result = await sdk.executeTransfer(prepared, signer);\n * ```\n */\n async prepareUnpauseVault(): Promise<PreparedTransfer> {\n const credential = this.passkey.getCredential();\n if (!credential) {\n throw new Error('No credential set');\n }\n\n const actionPayload = this.spendingLimits.prepareUnpauseVault();\n const nonce = await this.getNonce();\n const targetChain = this.chain.getConfig().wormholeChainId;\n const challenge = buildChallenge(credential.keyHash, targetChain, nonce, actionPayload);\n const messageFee = await this.getMessageFee();\n \n return {\n params: {\n targetChain,\n token: 'native',\n recipient: this.getVaultAddress(),\n amount: 0n,\n },\n actionPayload,\n nonce,\n challenge,\n estimatedGas: 0n,\n gasPrice: 0n,\n messageFee,\n totalCost: messageFee,\n formattedCost: '0',\n preparedAt: Date.now(),\n expiresAt: Date.now() + PREPARED_TRANSFER_TTL,\n };\n }\n\n /**\n * Execute a prepared transfer\n * Use this after prepareTransfer() for better UX\n * \n * @param prepared - PreparedTransfer from prepareTransfer()\n * @param signer - Signer to pay for gas\n * @returns TransferResult with tracking info\n */\n async executeTransfer(\n prepared: PreparedTransfer, \n signer: any\n ): Promise<TransferResult> {\n const credential = this.passkey.getCredential();\n if (!credential) {\n throw new Error('No credential set');\n }\n\n // Check if prepared transfer has expired\n if (Date.now() > prepared.expiresAt) {\n throw new Error('Prepared transfer has expired. Please call prepareTransfer() again.');\n }\n\n // Sign with passkey\n const signature = await this.passkey.sign(prepared.challenge);\n\n // Dispatch the transaction\n const result = await this.chain.dispatch(\n signature,\n credential.publicKeyX,\n credential.publicKeyY,\n prepared.params.targetChain,\n prepared.actionPayload,\n prepared.nonce,\n signer\n );\n\n // Track the transaction\n if (result.transactionHash) {\n const chainConfig = this.chain.getConfig();\n this.transactions.track(\n result.transactionHash,\n chainConfig.wormholeChainId,\n undefined,\n result.sequence\n );\n }\n\n // Invalidate balance cache for sender\n const vaultAddress = this.getVaultAddress();\n const chainConfig = this.chain.getConfig();\n this.balance.invalidateCache(chainConfig.wormholeChainId, vaultAddress);\n\n return {\n ...result,\n params: prepared.params,\n timestamp: Date.now(),\n };\n }\n\n /**\n * Enhanced transfer with automatic tracking\n * \n * @param params - Transfer parameters\n * @param signer - Signer to pay for gas\n * @param onStatusChange - Optional callback for transaction status updates\n * @returns TransferResult with tracking info\n */\n async transferWithTracking(\n params: TransferParams,\n signer: any,\n onStatusChange?: TransactionCallback\n ): Promise<TransferResult> {\n const credential = this.passkey.getCredential();\n if (!credential) {\n throw new Error('No credential set');\n }\n\n // Execute the transfer\n const actionPayload = await this.buildTransferPayload(params);\n const nonce = await this.getNonce();\n const challenge = buildChallenge(\n credential.keyHash,\n params.targetChain,\n nonce,\n actionPayload\n );\n\n const signature = await this.passkey.sign(challenge);\n\n const result = await this.chain.dispatch(\n signature,\n credential.publicKeyX,\n credential.publicKeyY,\n params.targetChain,\n actionPayload,\n nonce,\n signer\n );\n\n // Track the transaction\n if (result.transactionHash) {\n const chainConfig = this.chain.getConfig();\n this.transactions.track(\n result.transactionHash,\n chainConfig.wormholeChainId,\n onStatusChange,\n result.sequence\n );\n }\n\n // Invalidate balance cache\n const vaultAddress = this.getVaultAddress();\n const chainConfig = this.chain.getConfig();\n this.balance.invalidateCache(chainConfig.wormholeChainId, vaultAddress);\n\n return {\n ...result,\n params,\n timestamp: Date.now(),\n };\n }\n\n /**\n * Execute a gasless transfer using the relayer\n * \n * This method allows users to send funds without paying gas themselves.\n * The relayer service submits the transaction to the Hub and pays the gas.\n * The relayer then automatically relays the VAA to the destination spoke chain.\n * \n * @param params - Transfer parameters (to, amount, token, targetChain)\n * @param onStatusChange - Optional callback for transaction status updates\n * @returns TransferResult with Hub tx hash and tracking info\n */\n async transferViaRelayer(\n params: TransferParams,\n onStatusChange?: TransactionCallback\n ): Promise<TransferResult> {\n const credential = this.passkey.getCredential();\n if (!credential) {\n throw new Error('No credential set. Call passkey.register() or passkey.setCredential() first.');\n }\n\n // Ensure relayer is available\n if (!this.relayer) {\n throw new Error('Relayer not configured. Please provide relayerUrl in SDK config.');\n }\n\n const chainConfig = this.chain.getConfig();\n\n // Build the action payload (canonical encoding from the active chain client)\n const actionPayload = await this.buildTransferPayload(params);\n\n // Client-first preparation:\n // - fetch Guardian-attested nonce via Wormhole Queries when possible\n // - fall back to hub RPC nonce lookup\n // - prompt user to sign once\n const prepared = await authenticateAndPrepare(\n {\n credential,\n targetChain: params.targetChain,\n actionPayload,\n },\n this.queryApiKey ?? ''\n );\n\n const submitRequest = JSON.parse(new TextDecoder().decode(prepared.serializedTx)) as SubmitSignedActionRequest;\n\n // Ensure the request body uses our canonical payload (defensive)\n (submitRequest as any).actionPayload = actionPayload;\n\n const relayerResult = await this.relayer.submitSignedAction(submitRequest);\n\n if (!relayerResult.success) {\n throw new Error(`Relayer submission failed: ${relayerResult.error}`);\n }\n\n // Track the Hub transaction\n if (relayerResult.txHash) {\n const hubChainId = chainConfig.hubChainId ?? chainConfig.wormholeChainId;\n this.transactions.track(\n relayerResult.txHash,\n hubChainId,\n onStatusChange,\n relayerResult.sequence ? BigInt(relayerResult.sequence) : undefined\n );\n }\n\n // Invalidate balance cache for sender\n const vaultAddress = this.getVaultAddress();\n this.balance.invalidateCache(chainConfig.wormholeChainId, vaultAddress);\n\n return {\n transactionHash: relayerResult.txHash ?? '',\n sequence: relayerResult.sequence ? BigInt(relayerResult.sequence) : 0n,\n userKeyHash: credential.keyHash,\n targetChain: params.targetChain,\n blockNumber: 0, // Hub tx block number not returned by relayer\n params,\n timestamp: Date.now(),\n };\n }\n\n /**\n * Wait for a transaction to confirm\n * \n * @param hash - Transaction hash\n * @returns TransactionState when confirmed\n */\n async waitForTransaction(hash: string): Promise<TransactionState> {\n const chainConfig = this.chain.getConfig();\n return await this.transactions.waitForConfirmation(hash, chainConfig.wormholeChainId);\n }\n\n // ========================================================================\n // Balance Methods\n // ========================================================================\n\n /**\n * Get native token balance for the current vault\n * \n * @returns TokenBalance with native token balance\n */\n async getVaultNativeBalance(): Promise<TokenBalance> {\n const vaultAddress = this.getVaultAddress();\n const chainConfig = this.chain.getConfig();\n return await this.balance.getNativeBalance(chainConfig.wormholeChainId, vaultAddress);\n }\n\n /**\n * Get all token balances for the current vault\n * \n * @param includeZeroBalances - Whether to include tokens with 0 balance\n * @returns PortfolioBalance with all token balances\n */\n async getVaultBalances(includeZeroBalances: boolean = false): Promise<PortfolioBalance> {\n const vaultAddress = this.getVaultAddress();\n const chainConfig = this.chain.getConfig();\n\n // Prefer Wormhole Queries when possible (faster, Guardian-attested), but preserve\n // existing behavior as a fallback.\n const credential = this.passkey.getCredential();\n if (credential && this.queryApiKey) {\n try {\n const wormholeChainId = chainConfig.wormholeChainId;\n const tokenList = getAllTokens(wormholeChainId);\n const erc20Tokens = tokenList\n .filter((t) => !isNativeToken(t.address))\n .map((t) => t.address);\n\n const result = await queryPortfolio(credential.keyHash, this.queryApiKey, {\n network: this.testnet ? 'testnet' : 'mainnet',\n vaultAddresses: { [wormholeChainId]: vaultAddress },\n evmTokenAddresses: { [wormholeChainId]: erc20Tokens },\n rpcUrls: { [wormholeChainId]: chainConfig.rpcUrl },\n maxAge: 60,\n // Testnet Query Proxy can be slow; use a more forgiving timeout.\n timeout: this.testnet ? 15_000 : 10_000,\n maxAttempts: this.testnet ? 3 : 2,\n });\n\n const chain = result.chains.find((c) => c.wormholeChainId === wormholeChainId);\n if (chain && !chain.error) {\n const byAssetId = new Map(chain.balances.map((b) => [b.assetId.toLowerCase(), b] as const));\n const tokens = tokenList.map((t) => {\n if (isNativeToken(t.address)) {\n return null;\n }\n const found = byAssetId.get(t.address.toLowerCase());\n const amount = found?.amount ?? 0n;\n const formatted = ethers.formatUnits(amount, t.decimals);\n return {\n token: t,\n balance: amount,\n formatted,\n usdValue: found?.usdValue,\n };\n }).filter((t): t is NonNullable<typeof t> => !!t);\n\n // Add native token via RPC (Queries don't support native ETH balance).\n const native = await this.balance.getNativeBalance(wormholeChainId, vaultAddress);\n const merged = [native, ...tokens];\n\n const filtered = includeZeroBalances ? merged : merged.filter((t) => t.balance > 0n);\n const totalUsdValue = filtered.reduce((sum, t) => sum + (t.usdValue ?? 0), 0);\n\n return {\n wormholeChainId,\n chainName: chainConfig.name,\n address: vaultAddress,\n tokens: filtered,\n totalUsdValue: totalUsdValue || undefined,\n lastUpdated: Date.now(),\n };\n }\n } catch {\n // Fall back to the existing RPC-based balance logic.\n }\n }\n\n return await this.balance.getPortfolioBalance(chainConfig.wormholeChainId, vaultAddress, includeZeroBalances);\n }\n\n /**\n * Get token balance for a specific token\n * \n * @param tokenAddress - Token contract address or 'native'\n * @returns TokenBalance for the specified token\n */\n async getVaultTokenBalance(tokenAddress: string): Promise<TokenBalance> {\n const vaultAddress = this.getVaultAddress();\n const chainConfig = this.chain.getConfig();\n return await this.balance.getBalance(\n chainConfig.wormholeChainId,\n vaultAddress,\n tokenAddress\n );\n }\n\n /**\n * Get balances across multiple chains\n * \n * @param chainIds - Array of Wormhole chain IDs to check\n * @returns Array of PortfolioBalance for each chain\n */\n async getMultiChainBalances(chainIds: number[]): Promise<PortfolioBalance[]> {\n const credential = this.passkey.getCredential();\n if (!credential) {\n throw new Error('No credential set');\n }\n\n // Derive an address per chain and query balances accordingly.\n const results: PortfolioBalance[] = [];\n\n for (const wormholeChainId of chainIds) {\n const chainConfig = this.chainDetector.getChainConfig(wormholeChainId);\n\n // If unknown, skip with a warning.\n if (!chainConfig) {\n // eslint-disable-next-line no-console\n console.warn(`Unknown chainId for balances: ${wormholeChainId}`);\n continue;\n }\n\n // Resolve vault address\n const derived = this.chainDetector.deriveVaultAddress(credential, wormholeChainId);\n const address = derived?.address ?? (wormholeChainId === this.chain.getConfig().wormholeChainId\n ? this.getVaultAddress()\n : credential.keyHash);\n\n if (chainConfig.isEvm) {\n try {\n const portfolio = await this.balance.getPortfolioBalance(wormholeChainId, address, false);\n results.push(portfolio);\n } catch (error) {\n // eslint-disable-next-line no-console\n console.warn(`Failed to fetch EVM balances for chain ${wormholeChainId}:`, error);\n }\n continue;\n }\n\n // Non-EVM: fetch native balance via chain-specific client\n try {\n const client: any = this.chainDetector.createClient(wormholeChainId);\n if (typeof client.getNativeBalance !== 'function') {\n // eslint-disable-next-line no-console\n console.warn(`No native balance support for chain ${wormholeChainId}`);\n continue;\n }\n\n const native = await client.getNativeBalance(address);\n const meta = this.chainDetector.getNonEvmNativeTokenMeta(wormholeChainId);\n\n const decimals = meta?.decimals ?? 0;\n const formatted = decimals > 0 ? ethers.formatUnits(native, decimals) : native.toString();\n\n results.push({\n wormholeChainId,\n chainName: chainConfig.name,\n address,\n tokens: [\n {\n token: {\n symbol: meta?.symbol ?? 'NATIVE',\n name: meta?.name ?? 'Native Token',\n address: 'native',\n decimals,\n isNative: true,\n },\n balance: native,\n formatted,\n },\n ],\n lastUpdated: Date.now(),\n });\n } catch (error) {\n // eslint-disable-next-line no-console\n console.warn(`Failed to fetch non-EVM balances for chain ${wormholeChainId}:`, error);\n }\n }\n\n return results;\n }\n\n /**\n * Get token list for a chain\n */\n getTokenList(wormholeChainId?: number): TokenInfo[] {\n const chainId = wormholeChainId ?? this.chain.getConfig().wormholeChainId;\n return getAllTokens(chainId);\n }\n\n /**\n * Get token by symbol\n */\n getTokenBySymbol(symbol: string, wormholeChainId?: number): TokenInfo | null {\n const chainId = wormholeChainId ?? this.chain.getConfig().wormholeChainId;\n return getTokenBySymbol(chainId, symbol);\n }\n\n // ========================================================================\n // Receive Address Methods\n // ========================================================================\n\n /**\n * Get receive address information for sharing\n * Use this to generate QR codes or share your vault address\n * \n * @returns ReceiveAddress with address and sharing info\n */\n getReceiveAddress(): ReceiveAddress {\n const vaultAddress = this.getVaultAddress();\n const chainConfig = this.chain.getConfig();\n \n // Create a deep link for wallet apps (EIP-681 format for EVM)\n const deepLink = chainConfig.isEvm \n ? `ethereum:${vaultAddress}@${chainConfig.chainId}`\n : undefined;\n\n // Create copy-friendly text\n const copyText = `${vaultAddress}`;\n\n return {\n address: vaultAddress,\n chainName: chainConfig.name,\n wormholeChainId: chainConfig.wormholeChainId,\n deepLink,\n copyText,\n };\n }\n\n /**\n * Generate receive address with amount (for payment requests)\n * \n * @param amount - Amount to request\n * @param tokenAddress - Token address or 'native'\n * @param tokenDecimals - Token decimals\n * @returns ReceiveAddress with payment request info\n */\n getPaymentRequest(\n amount: bigint,\n tokenAddress: string = 'native',\n tokenDecimals: number = 18\n ): ReceiveAddress {\n const vaultAddress = this.getVaultAddress();\n const chainConfig = this.chain.getConfig();\n \n // Format amount\n const formattedAmount = this.formatUnits(amount, tokenDecimals);\n \n // Create EIP-681 payment request for EVM\n let deepLink: string | undefined;\n if (chainConfig.isEvm) {\n if (isNativeToken(tokenAddress)) {\n deepLink = `ethereum:${vaultAddress}@${chainConfig.chainId}?value=${amount.toString()}`;\n } else {\n // ERC20 transfer\n deepLink = `ethereum:${tokenAddress}@${chainConfig.chainId}/transfer?address=${vaultAddress}&uint256=${amount.toString()}`;\n }\n }\n\n return {\n address: vaultAddress,\n chainName: chainConfig.name,\n wormholeChainId: chainConfig.wormholeChainId,\n deepLink,\n copyText: `${vaultAddress} (${formattedAmount})`,\n };\n }\n\n // ========================================================================\n // Utility Methods\n // ========================================================================\n\n /**\n * Format wei to ether string\n */\n private formatWei(wei: bigint): string {\n // Simple formatter - 18 decimals\n const ether = Number(wei) / 1e18;\n return `${ether.toFixed(6)} ETH`;\n }\n\n /**\n * Format units based on decimals\n */\n private formatUnits(amount: bigint, decimals: number): string {\n const divisor = BigInt(10 ** decimals);\n const whole = amount / divisor;\n const remainder = amount % divisor;\n const remainderStr = remainder.toString().padStart(decimals, '0');\n const trimmed = remainderStr.slice(0, 4).replace(/0+$/, '') || '0';\n return `${whole}.${trimmed}`;\n }\n\n\n async getVaultInfo(targetChainId?: number): Promise<VaultInfo | null> {\n const credential = this.passkey.getCredential();\n if (!credential) {\n throw new Error('No credential set');\n }\n\n const chainConfig = this.chain.getConfig();\n const checkChainId = targetChainId ?? chainConfig.wormholeChainId;\n\n if (checkChainId !== chainConfig.wormholeChainId) {\n throw new Error('Cross-chain vault queries not yet supported. Please create a client for the target chain.');\n }\n\n const vaultAddress = await this.chain.getVaultAddress(credential.keyHash);\n const exists = await this.chain.vaultExists(credential.keyHash);\n\n if (!vaultAddress || !exists) {\n return null;\n }\n\n return {\n address: vaultAddress,\n ownerKeyHash: credential.keyHash,\n chain: chainConfig.name,\n wormholeChainId: chainConfig.wormholeChainId,\n exists,\n };\n }\n\n // ========================================================================\n // Wallet & Identity Methods\n // ========================================================================\n\n /**\n * Get the deterministic vault address for the current credential\n * This computes the address off-chain without requiring the vault to exist\n * \n * @returns The vault address that will be used when vault is created\n */\n getVaultAddress(): string {\n const credential = this.passkey.getCredential();\n if (!credential) {\n throw new Error('No credential set. Call passkey.register() or passkey.setCredential() first.');\n }\n\n return this.chain.computeVaultAddress(credential.keyHash);\n }\n\n /**\n * Get the vault address for a specific key hash\n * \n * @param keyHash - The user's key hash\n * @returns The deterministic vault address\n */\n getVaultAddressForKeyHash(keyHash: string): string {\n return this.chain.computeVaultAddress(keyHash);\n }\n\n /**\n * Get the vault address for a specific chain\n * Each EVM chain has its own factory contract, so vault addresses are chain-specific.\n * \n * @param wormholeChainId - The Wormhole chain ID\n * @param keyHash - Optional key hash (defaults to current credential)\n * @returns The deterministic vault address for that chain, or null if chain not supported\n */\n getVaultAddressForChain(wormholeChainId: number, keyHash?: string): string | null {\n const hash = keyHash ?? this.passkey.getCredential()?.keyHash;\n if (!hash) {\n throw new Error('No credential set and no keyHash provided');\n }\n\n const credential = { keyHash: hash } as PasskeyCredential;\n const derived = this.chainDetector.deriveVaultAddress(credential, wormholeChainId);\n return derived?.address ?? null;\n }\n\n /**\n * Get vault balances for a specific chain\n * Unlike getVaultBalances() which uses the hub chain, this fetches for any EVM chain.\n * \n * @param wormholeChainId - The Wormhole chain ID\n * @param includeZeroBalances - Whether to include tokens with 0 balance\n * @returns PortfolioBalance with all token balances for that chain\n */\n async getVaultBalancesForChain(\n wormholeChainId: number,\n includeZeroBalances: boolean = false\n ): Promise<PortfolioBalance> {\n const credential = this.passkey.getCredential();\n if (!credential) {\n throw new Error('No credential set');\n }\n\n // Get the correct vault address for this chain\n const vaultAddress = this.getVaultAddressForChain(wormholeChainId, credential.keyHash);\n if (!vaultAddress) {\n throw new Error(`Cannot derive vault address for chain ${wormholeChainId}`);\n }\n\n const chainConfig = this.chainDetector.getChainConfig(wormholeChainId);\n if (!chainConfig) {\n throw new Error(`Unknown chain ${wormholeChainId}`);\n }\n\n // Try Wormhole Queries first for faster, attested results\n if (this.queryApiKey) {\n try {\n const tokenList = getAllTokens(wormholeChainId);\n const erc20Tokens = tokenList\n .filter((t) => !isNativeToken(t.address))\n .map((t) => t.address);\n\n const rpcUrl = this.chainRpcUrls?.[wormholeChainId] ?? chainConfig.rpcUrl;\n \n const result = await queryPortfolio(credential.keyHash, this.queryApiKey, {\n network: this.testnet ? 'testnet' : 'mainnet',\n vaultAddresses: { [wormholeChainId]: vaultAddress },\n evmTokenAddresses: { [wormholeChainId]: erc20Tokens },\n rpcUrls: { [wormholeChainId]: rpcUrl },\n maxAge: 60,\n timeout: this.testnet ? 15_000 : 10_000,\n maxAttempts: this.testnet ? 3 : 2,\n });\n\n const chain = result.chains.find((c) => c.wormholeChainId === wormholeChainId);\n if (chain && !chain.error) {\n const byAssetId = new Map(chain.balances.map((b) => [b.assetId.toLowerCase(), b] as const));\n const tokens = tokenList.map((t) => {\n if (isNativeToken(t.address)) {\n return null;\n }\n const found = byAssetId.get(t.address.toLowerCase());\n const amount = found?.amount ?? 0n;\n const formatted = ethers.formatUnits(amount, t.decimals);\n return {\n token: t,\n balance: amount,\n formatted,\n usdValue: found?.usdValue,\n };\n }).filter((t): t is NonNullable<typeof t> => !!t);\n\n // Add native token via RPC\n const native = await this.balance.getNativeBalance(wormholeChainId, vaultAddress);\n const merged = [native, ...tokens];\n\n const filtered = includeZeroBalances ? merged : merged.filter((t) => t.balance > 0n);\n const totalUsdValue = filtered.reduce((sum, t) => sum + (t.usdValue ?? 0), 0);\n\n return {\n wormholeChainId,\n chainName: chainConfig.name,\n address: vaultAddress,\n tokens: filtered,\n totalUsdValue: totalUsdValue || undefined,\n lastUpdated: Date.now(),\n };\n }\n } catch {\n // Fall back to RPC-based balance fetching\n }\n }\n\n // Fallback to RPC-based balance fetching\n return await this.balance.getPortfolioBalance(wormholeChainId, vaultAddress, includeZeroBalances);\n }\n\n /**\n * Get unified identity with addresses across chains\n * \n * @returns UnifiedIdentity containing credential info and chain addresses\n */\n async getUnifiedIdentity(): Promise<UnifiedIdentity> {\n const credential = this.passkey.getCredential();\n if (!credential) {\n throw new Error('No credential set. Call passkey.register() or passkey.setCredential() first.');\n }\n\n // Check if we have cached identity\n if (this.unifiedIdentity && this.unifiedIdentity.keyHash === credential.keyHash) {\n return this.unifiedIdentity;\n }\n\n // Try to load from storage first\n const storedIdentity = this.wallet.loadIdentityFromStorage(credential.keyHash);\n if (storedIdentity) {\n this.unifiedIdentity = storedIdentity;\n // Update deployment status from chain\n await this.updateDeploymentStatus();\n return this.unifiedIdentity;\n }\n\n // Build new identity\n const chainConfig = this.chain.getConfig();\n const addresses: ChainAddress[] = [];\n\n // Compute address for current chain\n try {\n const address = this.chain.computeVaultAddress(credential.keyHash);\n const deployed = await this.chain.vaultExists(credential.keyHash);\n \n addresses.push({\n wormholeChainId: chainConfig.wormholeChainId,\n chainName: chainConfig.name,\n address,\n isEvm: chainConfig.isEvm,\n deployed,\n derivationType: 'create2',\n });\n } catch (error) {\n console.warn('Could not compute vault address for current chain:', error);\n }\n\n this.unifiedIdentity = {\n keyHash: credential.keyHash,\n publicKeyX: credential.publicKeyX,\n publicKeyY: credential.publicKeyY,\n credentialId: credential.credentialId,\n addresses,\n createdAt: Date.now(),\n updatedAt: Date.now(),\n };\n\n return this.unifiedIdentity;\n }\n\n /**\n * Get the current chain address from unified identity\n */\n async getCurrentChainAddress(): Promise<ChainAddress | null> {\n const identity = await this.getUnifiedIdentity();\n const chainConfig = this.chain.getConfig();\n \n return identity.addresses.find(\n a => a.wormholeChainId === chainConfig.wormholeChainId\n ) ?? null;\n }\n\n /**\n * Update deployment status for cached identity\n */\n private async updateDeploymentStatus(): Promise<void> {\n if (!this.unifiedIdentity) return;\n\n const chainConfig = this.chain.getConfig();\n const address = this.unifiedIdentity.addresses.find(\n a => a.wormholeChainId === chainConfig.wormholeChainId\n );\n\n if (address) {\n try {\n const deployed = await this.chain.vaultExists(this.unifiedIdentity.keyHash);\n address.deployed = deployed;\n this.unifiedIdentity.updatedAt = Date.now();\n } catch (error) {\n console.warn('Could not update deployment status:', error);\n }\n }\n }\n\n /**\n * Add a chain address to the unified identity\n * Used when configuring multiple chains\n */\n addChainAddress(address: ChainAddress): void {\n if (!this.unifiedIdentity) {\n throw new Error('No identity loaded. Call getUnifiedIdentity() first.');\n }\n\n const existing = this.unifiedIdentity.addresses.findIndex(\n a => a.wormholeChainId === address.wormholeChainId\n );\n\n if (existing >= 0) {\n this.unifiedIdentity.addresses[existing] = address;\n } else {\n this.unifiedIdentity.addresses.push(address);\n }\n\n this.unifiedIdentity.updatedAt = Date.now();\n }\n\n // ========================================================================\n // Vault Creation Methods\n // ========================================================================\n\n /**\n * Create a vault for the current credential\n * \n * @param signer - The signer to pay for gas\n * @returns VaultCreationResult with address and transaction details\n */\n async createVault(signer: any): Promise<VaultCreationResult> {\n const credential = this.passkey.getCredential();\n if (!credential) {\n throw new Error('No credential set');\n }\n\n const result = await this.chain.createVault(credential.keyHash, signer);\n\n // Update cached identity if available\n if (this.unifiedIdentity) {\n const chainConfig = this.chain.getConfig();\n const address = this.unifiedIdentity.addresses.find(\n a => a.wormholeChainId === chainConfig.wormholeChainId\n );\n\n if (address) {\n address.deployed = true;\n address.deploymentTxHash = result.transactionHash;\n } else {\n this.unifiedIdentity.addresses.push({\n wormholeChainId: chainConfig.wormholeChainId,\n chainName: chainConfig.name,\n address: result.address,\n isEvm: chainConfig.isEvm,\n deployed: true,\n deploymentTxHash: result.transactionHash,\n derivationType: 'create2',\n });\n }\n\n this.unifiedIdentity.updatedAt = Date.now();\n }\n\n return result;\n }\n\n /**\n * Create a vault with sponsored gas (Veridex pays for gas)\n * \n * Uses the sponsor wallet configured in SDK initialization.\n * If no sponsor is configured, throws an error.\n * \n * @param wormholeChainId - Optional chain ID for multi-chain creation\n * @returns VaultCreationResult with address and transaction details\n */\n async createVaultSponsored(wormholeChainId?: number): Promise<VaultCreationResult> {\n const credential = this.passkey.getCredential();\n if (!credential) {\n throw new Error('No credential set');\n }\n\n if (!this.sponsorPrivateKey) {\n throw new Error('No sponsor wallet configured. Set sponsorPrivateKey in SDK config.');\n }\n\n // Check if chain client supports sponsored creation\n if (!this.chain.createVaultSponsored) {\n throw new Error('Current chain client does not support sponsored vault creation');\n }\n\n // Get the appropriate RPC URL for the chain\n const chainConfig = this.chain.getConfig();\n const targetChainId = wormholeChainId ?? chainConfig.wormholeChainId;\n const rpcUrl = this.chainRpcUrls?.[targetChainId] ?? chainConfig.rpcUrl;\n\n const result = await this.chain.createVaultSponsored(\n credential.keyHash,\n this.sponsorPrivateKey,\n rpcUrl\n );\n\n // Update cached identity if available\n if (this.unifiedIdentity) {\n const address = this.unifiedIdentity.addresses.find(\n a => a.wormholeChainId === targetChainId\n );\n\n if (address) {\n address.deployed = true;\n address.deploymentTxHash = result.transactionHash;\n } else {\n this.unifiedIdentity.addresses.push({\n wormholeChainId: targetChainId,\n chainName: chainConfig.name,\n address: result.address,\n isEvm: chainConfig.isEvm,\n deployed: true,\n deploymentTxHash: result.transactionHash,\n derivationType: 'create2',\n });\n }\n\n this.unifiedIdentity.updatedAt = Date.now();\n }\n\n return result;\n }\n\n /**\n * Check if sponsored vault creation is available\n */\n hasSponsoredVaultCreation(): boolean {\n return !!this.sponsorPrivateKey && !!this.chain.createVaultSponsored;\n }\n\n /**\n * Ensure vault exists, creating with sponsor if available\n * Falls back to requiring a signer if no sponsor configured\n * \n * @param signer - Optional signer (only required if no sponsor configured)\n * @returns The vault address\n */\n async ensureVaultAuto(signer?: any): Promise<string> {\n const credential = this.passkey.getCredential();\n if (!credential) {\n throw new Error('No credential set');\n }\n\n const exists = await this.chain.vaultExists(credential.keyHash);\n if (exists) {\n return this.getVaultAddress();\n }\n\n // Try sponsored creation first\n if (this.hasSponsoredVaultCreation()) {\n const result = await this.createVaultSponsored();\n return result.address;\n }\n\n // Fall back to signer-based creation\n if (!signer) {\n throw new Error('No sponsor configured and no signer provided for vault creation');\n }\n\n const result = await this.createVault(signer);\n return result.address;\n }\n\n /**\n * Ensure vault exists, creating if necessary\n * \n * @param signer - The signer to pay for gas (only used if creation needed)\n * @returns The vault address\n */\n async ensureVault(signer: any): Promise<string> {\n const credential = this.passkey.getCredential();\n if (!credential) {\n throw new Error('No credential set');\n }\n\n const exists = await this.chain.vaultExists(credential.keyHash);\n if (exists) {\n return this.getVaultAddress();\n }\n\n const result = await this.createVault(signer);\n return result.address;\n }\n\n /**\n * Estimate gas for vault creation\n */\n async estimateVaultCreationGas(): Promise<bigint> {\n const credential = this.passkey.getCredential();\n if (!credential) {\n throw new Error('No credential set');\n }\n\n return await this.chain.estimateVaultCreationGas(credential.keyHash);\n }\n\n async vaultExists(): Promise<boolean> {\n const credential = this.passkey.getCredential();\n if (!credential) {\n throw new Error('No credential set');\n }\n\n return await this.chain.vaultExists(credential.keyHash);\n }\n\n // ========================================================================\n // Sponsored Vault Creation (Gasless)\n // ========================================================================\n\n /**\n * Check if gas sponsorship is configured\n * \n * @returns true if a sponsor is configured (relayer, integrator, or Veridex)\n */\n isSponsorshipAvailable(): boolean {\n return this.sponsor.isConfigured();\n }\n\n /**\n * Get the active sponsorship source\n * \n * Priority order:\n * 1. 'relayer' - Remote relayer service (future primary)\n * 2. 'integrator' - Platform-provided sponsor key\n * 3. 'veridex' - Veridex default sponsor (fallback)\n * 4. 'none' - No sponsorship available\n * \n * @returns The active sponsorship source\n */\n getSponsorshipSource(): 'relayer' | 'integrator' | 'veridex' | 'none' {\n return this.sponsor.getSponsorshipSource();\n }\n\n /**\n * Get supported chains for sponsored vault creation\n * \n * @returns Array of chain configurations\n */\n getSponsoredChains(): ChainDeploymentConfig[] {\n return this.sponsor.getSupportedChains();\n }\n\n /**\n * Create a vault on a specific chain using gas sponsorship\n * User doesn't need to pay gas - Veridex pays\n * \n * @param wormholeChainId - The Wormhole chain ID to create vault on\n * @returns Result with vault address\n */\n async createSponsoredVault(wormholeChainId: number): Promise<SponsoredVaultResult> {\n const credential = this.passkey.getCredential();\n if (!credential) {\n throw new Error('No credential set. Call passkey.register() or passkey.setCredential() first.');\n }\n\n if (!this.sponsor.isConfigured()) {\n throw new Error('Gas sponsorship not configured. Set sponsorPrivateKey in SDK config.');\n }\n\n const result = await this.sponsor.createVaultOnChain(credential.keyHash, wormholeChainId);\n\n // Update cached identity if successful\n if (result.success && result.vaultAddress && this.unifiedIdentity) {\n const existingAddress = this.unifiedIdentity.addresses.find(\n a => a.wormholeChainId === wormholeChainId\n );\n\n if (existingAddress) {\n existingAddress.deployed = true;\n existingAddress.deploymentTxHash = result.transactionHash;\n existingAddress.address = result.vaultAddress;\n } else {\n this.unifiedIdentity.addresses.push({\n wormholeChainId,\n chainName: result.chain,\n address: result.vaultAddress,\n isEvm: true,\n deployed: true,\n deploymentTxHash: result.transactionHash,\n derivationType: 'create2',\n });\n }\n\n this.unifiedIdentity.updatedAt = Date.now();\n }\n\n return result;\n }\n\n /**\n * Create vaults on all supported chains using gas sponsorship\n * User doesn't need to pay gas - Veridex pays\n * \n * @returns Multi-chain result with all vault addresses\n */\n async createSponsoredVaultsOnAllChains(): Promise<MultiChainVaultResult> {\n const credential = this.passkey.getCredential();\n if (!credential) {\n throw new Error('No credential set. Call passkey.register() or passkey.setCredential() first.');\n }\n\n if (!this.sponsor.isConfigured()) {\n throw new Error('Gas sponsorship not configured. Set sponsorPrivateKey in SDK config.');\n }\n\n const result = await this.sponsor.createVaultsOnAllChains(credential.keyHash);\n\n // Update cached identity with all successful vaults\n if (this.unifiedIdentity) {\n for (const vaultResult of result.results) {\n if (vaultResult.success && vaultResult.vaultAddress) {\n const existingAddress = this.unifiedIdentity.addresses.find(\n a => a.wormholeChainId === vaultResult.wormholeChainId\n );\n\n if (existingAddress) {\n existingAddress.deployed = true;\n existingAddress.deploymentTxHash = vaultResult.transactionHash;\n existingAddress.address = vaultResult.vaultAddress;\n } else {\n this.unifiedIdentity.addresses.push({\n wormholeChainId: vaultResult.wormholeChainId,\n chainName: vaultResult.chain,\n address: vaultResult.vaultAddress,\n isEvm: true,\n deployed: true,\n deploymentTxHash: vaultResult.transactionHash,\n derivationType: 'create2',\n });\n }\n }\n }\n\n this.unifiedIdentity.updatedAt = Date.now();\n }\n\n return result;\n }\n\n /**\n * Check if vaults exist on all supported chains\n * \n * @returns Map of chain ID to vault status\n */\n async checkVaultsOnAllChains(): Promise<Record<number, { exists: boolean; address: string }>> {\n const credential = this.passkey.getCredential();\n if (!credential) {\n throw new Error('No credential set');\n }\n\n return await this.sponsor.checkVaultsOnAllChains(credential.keyHash);\n }\n\n /**\n * Ensure vaults exist on all chains, creating if necessary (sponsored)\n * \n * @returns Result with all vault addresses\n */\n async ensureSponsoredVaultsOnAllChains(): Promise<MultiChainVaultResult> {\n const credential = this.passkey.getCredential();\n if (!credential) {\n throw new Error('No credential set');\n }\n\n // First check which vaults exist\n const existing = await this.checkVaultsOnAllChains();\n \n // Find chains that need vault creation\n const supportedChains = this.sponsor.getSupportedChains();\n const needsCreation = supportedChains.filter(\n chain => !existing[chain.wormholeChainId]?.exists\n );\n\n if (needsCreation.length === 0) {\n // All vaults exist\n const vaultAddresses: Record<number, string> = {};\n const results: SponsoredVaultResult[] = [];\n\n for (const chain of supportedChains) {\n const status = existing[chain.wormholeChainId];\n vaultAddresses[chain.wormholeChainId] = status?.address || '';\n results.push({\n success: true,\n chain: chain.name,\n wormholeChainId: chain.wormholeChainId,\n vaultAddress: status?.address,\n alreadyExists: true,\n });\n }\n\n return {\n keyHash: credential.keyHash,\n results,\n allSuccessful: true,\n vaultAddresses,\n };\n }\n\n // Create missing vaults\n return await this.createSponsoredVaultsOnAllChains();\n }\n\n // ==========================================================================\n // Backup Passkey / Multi-Key Identity Methods (Issue #22)\n // ==========================================================================\n\n /**\n * Get the identity state for the current passkey\n * Returns information about the identity including key count and root status\n * \n * @returns Identity state or null if no credential set\n */\n async getIdentityState(): Promise<IdentityState | null> {\n const credential = this.passkey.getCredential();\n if (!credential) {\n return null;\n }\n\n const evmClient = this.chain as any;\n if (typeof evmClient.getIdentityState !== 'function') {\n throw new Error('Identity management not supported on this chain client');\n }\n\n return await evmClient.getIdentityState(credential.keyHash);\n }\n\n /**\n * Get all authorized passkeys for the current identity\n * \n * @returns Array of authorized keys with root status, or null if no credential\n */\n async listAuthorizedPasskeys(): Promise<AuthorizedKey[] | null> {\n const credential = this.passkey.getCredential();\n if (!credential) {\n return null;\n }\n\n const evmClient = this.chain as any;\n if (typeof evmClient.getIdentityState !== 'function') {\n throw new Error('Identity management not supported on this chain client');\n }\n\n // Get the identity for this key\n const state = await evmClient.getIdentityState(credential.keyHash);\n if (!state.identity || state.identity === ethers.ZeroHash) {\n // Key not registered, return just this key as pending\n return [];\n }\n\n // Get all authorized keys for this identity\n const keyHashes: string[] = await evmClient.getAuthorizedKeys(state.identity);\n \n // Map to AuthorizedKey with root status\n return keyHashes.map(keyHash => ({\n keyHash,\n isRoot: keyHash === state.identity,\n }));\n }\n\n /**\n * Check if the current identity has backup passkeys registered\n * Returns false if only one passkey (the root) is registered\n * \n * @returns True if backup passkeys exist, false otherwise\n */\n async hasBackupPasskeys(): Promise<boolean> {\n const state = await this.getIdentityState();\n if (!state || state.keyCount === 0) {\n return false;\n }\n return state.keyCount > 1;\n }\n\n /**\n * Register a backup passkey for the current identity\n * The backup passkey can be used to recover access if the primary is lost\n * \n * @param newCredential The new passkey credential to add as backup\n * @param signer Ethereum signer to pay gas (optional, uses relayer if not provided)\n * @returns Result with transaction hash and sequence for cross-chain sync\n */\n async addBackupPasskey(\n newCredential: PasskeyCredential,\n signer?: any\n ): Promise<AddBackupKeyResult> {\n const credential = this.passkey.getCredential();\n if (!credential) {\n throw new Error('No credential set. Call passkey.register() or passkey.setCredential() first.');\n }\n\n const evmClient = this.chain as any;\n if (typeof evmClient.addBackupKey !== 'function') {\n throw new Error('Backup passkey management not supported on this chain client');\n }\n\n // Get identity state to ensure we're within limits\n const state = await evmClient.getIdentityState(credential.keyHash);\n if (state.keyCount >= state.maxKeys) {\n throw new Error(`Maximum keys (${state.maxKeys}) already registered for this identity`);\n }\n\n // Check if the new key is already authorized\n const isAlreadyAuthorized = await evmClient.isAuthorizedForIdentity(\n state.identity,\n newCredential.keyHash\n );\n if (isAlreadyAuthorized) {\n throw new Error('This passkey is already authorized for this identity');\n }\n\n if (!state.identity || state.identity === ethers.ZeroHash) {\n throw new Error('Identity not registered. Call registerIdentity() first.');\n }\n\n // Nonce for key-management is stored on the *identity* (not necessarily the signing key)\n const nonce = await this.chain.getNonce(state.identity);\n\n // Challenge = abi.encodePacked(\"VERIDEX_ADD_KEY\", identityKeyHash, newKeyHash, nonce)\n const packedChallenge = ethers.solidityPacked(\n ['string', 'bytes32', 'bytes32', 'uint256'],\n ['VERIDEX_ADD_KEY', state.identity, newCredential.keyHash, nonce]\n );\n\n const signature = await this.passkey.sign(ethers.getBytes(packedChallenge));\n\n if (!signer) {\n throw new Error('Signer required for backup key registration');\n }\n\n // Call Hub contract to add backup key\n const { receipt, sequence } = await evmClient.addBackupKey(\n signature,\n credential.publicKeyX,\n credential.publicKeyY,\n newCredential.publicKeyX,\n newCredential.publicKeyY,\n nonce,\n signer\n );\n\n // Get updated key count\n const updatedState = await evmClient.getIdentityState(credential.keyHash);\n\n return {\n transactionHash: receipt.hash,\n sequence,\n identity: state.identity,\n newKeyHash: newCredential.keyHash,\n keyCount: updatedState.keyCount,\n };\n }\n\n /**\n * Remove a passkey from the current identity\n * Cannot remove the last remaining passkey\n * \n * @param keyToRemove Hash of the passkey to remove\n * @param signer Ethereum signer to pay gas\n * @returns Result with transaction hash and sequence for cross-chain sync\n */\n async removePasskey(\n keyToRemove: string,\n signer: any\n ): Promise<RemoveKeyResult> {\n const credential = this.passkey.getCredential();\n if (!credential) {\n throw new Error('No credential set. Call passkey.register() or passkey.setCredential() first.');\n }\n\n const evmClient = this.chain as any;\n if (typeof evmClient.removeKey !== 'function') {\n throw new Error('Backup passkey management not supported on this chain client');\n }\n\n // Get identity state\n const state = await evmClient.getIdentityState(credential.keyHash);\n if (state.keyCount <= 1) {\n throw new Error('Cannot remove the last passkey. At least one must remain.');\n }\n\n // Check if the key to remove is actually authorized\n const isAuthorized = await evmClient.isAuthorizedForIdentity(\n state.identity,\n keyToRemove\n );\n if (!isAuthorized) {\n throw new Error('The specified passkey is not authorized for this identity');\n }\n\n if (!state.identity || state.identity === ethers.ZeroHash) {\n throw new Error('Identity not registered. Call registerIdentity() first.');\n }\n\n // Nonce for key-management is stored on the *identity*\n const nonce = await this.chain.getNonce(state.identity);\n\n // Challenge = abi.encodePacked(\"VERIDEX_REMOVE_KEY\", identityKeyHash, keyToRemove, nonce)\n const packedChallenge = ethers.solidityPacked(\n ['string', 'bytes32', 'bytes32', 'uint256'],\n ['VERIDEX_REMOVE_KEY', state.identity, keyToRemove, nonce]\n );\n\n const signature = await this.passkey.sign(ethers.getBytes(packedChallenge));\n\n // Call Hub contract to remove key\n const { receipt, sequence } = await evmClient.removeKey(\n signature,\n credential.publicKeyX,\n credential.publicKeyY,\n keyToRemove,\n nonce,\n signer\n );\n\n // Get updated key count\n const updatedState = await evmClient.getIdentityState(credential.keyHash);\n\n return {\n transactionHash: receipt.hash,\n sequence,\n identity: state.identity,\n removedKeyHash: keyToRemove,\n keyCount: updatedState.keyCount,\n };\n }\n\n /**\n * Check if a specific passkey is authorized for the current identity\n * \n * @param keyHash Hash of the passkey to check\n * @returns True if authorized, false otherwise\n */\n async isPasskeyAuthorized(keyHash: string): Promise<boolean> {\n const credential = this.passkey.getCredential();\n if (!credential) {\n return false;\n }\n\n const evmClient = this.chain as any;\n if (typeof evmClient.getIdentityState !== 'function') {\n throw new Error('Identity management not supported on this chain client');\n }\n\n const state = await evmClient.getIdentityState(credential.keyHash);\n if (!state.identity || state.identity === ethers.ZeroHash) {\n return false;\n }\n\n return await evmClient.isAuthorizedForIdentity(state.identity, keyHash);\n }\n\n /**\n * Get the identity hash for the current passkey\n * This is the keyHash of the first/root passkey registered\n * \n * @returns Identity hash or null if no credential/identity\n */\n async getIdentity(): Promise<string | null> {\n const credential = this.passkey.getCredential();\n if (!credential) {\n return null;\n }\n\n const evmClient = this.chain as any;\n if (typeof evmClient.getIdentityForKey !== 'function') {\n // Fallback: return keyHash as identity (single-key mode)\n return credential.keyHash;\n }\n\n const identity = await evmClient.getIdentityForKey(credential.keyHash);\n if (identity === ethers.ZeroHash) {\n // Not registered yet, return current keyHash\n return credential.keyHash;\n }\n\n return identity;\n }\n\n getCredential(): PasskeyCredential | null {\n return this.passkey.getCredential();\n }\n\n setCredential(credential: PasskeyCredential): void {\n this.passkey.setCredential(credential);\n }\n\n hasCredential(): boolean {\n return this.passkey.getCredential() !== null;\n }\n\n clearCredential(): void {\n this.passkey.clearCredential();\n }\n}\n","import { ethers } from 'ethers';\n\nimport type { PasskeyCredential, TransferParams, ExecuteParams, BridgeParams } from '../core/types.js';\nimport { PasskeyManager } from '../core/PasskeyManager.js';\nimport { MAINNET_CHAINS, TESTNET_CHAINS } from '../constants.js';\nimport { buildGaslessChallenge, encodeBridgeAction, encodeExecuteAction, encodeTransferAction } from '../payload.js';\nimport { queryHubState } from '../queries/hubState.js';\n\nexport type AuthenticateAndPrepareParams = {\n credential: PasskeyCredential;\n action?: TransferParams | ExecuteParams | BridgeParams;\n /** Pre-encoded Hub action payload (hex string). If provided, `action` is ignored. */\n actionPayload?: string;\n targetChain: number;\n};\n\nexport type AuthenticateAndPrepareResult = {\n serializedTx: Uint8Array;\n queryProof: Uint8Array<ArrayBufferLike>;\n estimatedLatency: number;\n fallbackAvailable: boolean;\n};\n\nfunction resolveNetwork(): 'testnet' | 'mainnet' {\n const envCandidates = [\n (globalThis as any)?.process?.env?.NEXT_PUBLIC_VERIDEX_NETWORK,\n (globalThis as any)?.process?.env?.VERIDEX_NETWORK,\n (globalThis as any)?.process?.env?.NEXT_PUBLIC_WORMHOLE_NETWORK,\n (globalThis as any)?.process?.env?.WORMHOLE_NETWORK,\n ].filter(Boolean);\n\n const env = (envCandidates[0] as string | undefined)?.toLowerCase();\n if (env === 'mainnet' || env === 'testnet') return env;\n return 'testnet';\n}\n\nfunction getHubChainId(network: 'testnet' | 'mainnet'): number {\n return network === 'testnet' ? TESTNET_CHAINS.baseSepolia.wormholeChainId : MAINNET_CHAINS.base.wormholeChainId;\n}\n\nfunction getHubRpcUrl(network: 'testnet' | 'mainnet'): string {\n return network === 'testnet' ? TESTNET_CHAINS.baseSepolia.rpcUrl : MAINNET_CHAINS.base.rpcUrl;\n}\n\nfunction getHubAddress(network: 'testnet' | 'mainnet'): string {\n const hub = network === 'testnet'\n ? TESTNET_CHAINS.baseSepolia.contracts.hub\n : (MAINNET_CHAINS.base.contracts as any)?.hub;\n if (!hub) {\n throw new Error('Hub address missing in SDK constants');\n }\n return hub;\n}\n\nfunction encodeActionPayload(action: TransferParams | ExecuteParams | BridgeParams, targetChain: number): string {\n if ((action as TransferParams).token !== undefined && (action as TransferParams).recipient !== undefined) {\n const a = action as TransferParams;\n return encodeTransferAction(a.token, a.recipient, a.amount);\n }\n\n if ((action as ExecuteParams).target !== undefined && (action as ExecuteParams).data !== undefined) {\n const a = action as ExecuteParams;\n return encodeExecuteAction(a.target, a.value, a.data);\n }\n\n const a = action as BridgeParams;\n return encodeBridgeAction(a.token, a.amount, targetChain, a.recipient);\n}\n\nasync function fetchNonceViaRpc(userKeyHash: string, network: 'testnet' | 'mainnet'): Promise<bigint> {\n const rpcUrl = getHubRpcUrl(network);\n const hubAddress = getHubAddress(network);\n\n const provider = new ethers.JsonRpcProvider(rpcUrl);\n const hubIface = new ethers.Interface([\n 'function getNonce(bytes32 userKeyHash) external view returns (uint256)',\n 'function userNonces(bytes32 userKeyHash) external view returns (uint256)',\n ]);\n\n const calls: Array<() => Promise<bigint>> = [\n async () => {\n const data = hubIface.encodeFunctionData('getNonce', [userKeyHash]);\n const res = await provider.call({ to: hubAddress, data });\n const decoded = hubIface.decodeFunctionResult('getNonce', res);\n return decoded[0] as bigint;\n },\n async () => {\n const data = hubIface.encodeFunctionData('userNonces', [userKeyHash]);\n const res = await provider.call({ to: hubAddress, data });\n const decoded = hubIface.decodeFunctionResult('userNonces', res);\n return decoded[0] as bigint;\n },\n ];\n\n let lastErr: unknown;\n for (const fn of calls) {\n try {\n return await fn();\n } catch (e) {\n lastErr = e;\n }\n }\n\n throw lastErr instanceof Error ? lastErr : new Error(String(lastErr));\n}\n\nfunction toHex32(value: bigint): string {\n return '0x' + value.toString(16).padStart(64, '0');\n}\n\n/**\n * Client-first authentication preparation:\n * - user signs locally (FaceID/TouchID)\n * - client queries Wormhole Query Proxy for Guardian-attested nonce/state\n * - client returns a ready-to-submit relayer payload (JSON bytes)\n * - falls back to RPC nonce if Queries fails\n */\nexport async function authenticateAndPrepare(\n userParams: AuthenticateAndPrepareParams,\n apiKey: string\n): Promise<AuthenticateAndPrepareResult> {\n const network = resolveNetwork();\n const hubChainId = getHubChainId(network);\n\n const actionPayload = userParams.actionPayload ?? (userParams.action\n ? encodeActionPayload(userParams.action, userParams.targetChain)\n : undefined);\n\n if (!actionPayload) {\n throw new Error('Missing action payload: provide either actionPayload or action');\n }\n\n let nonce: bigint;\n let queryProof: Uint8Array<ArrayBufferLike> = new Uint8Array();\n let fallbackAvailable = true;\n\n const queryStart = Date.now();\n try {\n if (!apiKey) {\n throw new Error('Missing Query Proxy apiKey');\n }\n\n const state = await queryHubState(userParams.credential.keyHash, apiKey, { network, maxAge: 60 });\n\n if (!state.isRegistered) {\n // This is a hard failure: signing won’t help if the key isn’t registered.\n throw new Error('Passkey is not registered on Hub');\n }\n\n nonce = state.nonce;\n queryProof = state.proof;\n } catch {\n // Fallback: fetch nonce directly from hub RPC.\n nonce = await fetchNonceViaRpc(userParams.credential.keyHash, network);\n queryProof = new Uint8Array();\n }\n const queryLatencyMs = Date.now() - queryStart;\n\n const challenge = buildGaslessChallenge(userParams.targetChain, actionPayload, nonce, hubChainId);\n const passkey = new PasskeyManager();\n passkey.setCredential(userParams.credential);\n const signature = await passkey.sign(challenge);\n\n // Relayer request body (matches packages/relayer POST /api/v1/submit requirements)\n // Uses full WebAuthn data for authenticateAndDispatch\n const requestBody: any = {\n authenticatorData: signature.authenticatorData,\n clientDataJSON: signature.clientDataJSON,\n challengeIndex: signature.challengeIndex,\n typeIndex: signature.typeIndex,\n r: toHex32(signature.r),\n s: toHex32(signature.s),\n publicKeyX: toHex32(userParams.credential.publicKeyX),\n publicKeyY: toHex32(userParams.credential.publicKeyY),\n targetChain: userParams.targetChain,\n actionPayload,\n nonce: Number(nonce),\n };\n\n // Include proof as an optional field for callers to forward/store (relayer ignores extra fields).\n if (queryProof.length) {\n requestBody.queryProof = ethers.hexlify(queryProof);\n }\n\n const serializedTx = new TextEncoder().encode(JSON.stringify(requestBody));\n\n // Heuristic: Queries is sub-second; RPC nonce lookup is slower.\n const estimatedLatency = queryProof.length ? Math.max(250, queryLatencyMs) : Math.max(800, queryLatencyMs);\n\n return {\n serializedTx,\n queryProof,\n estimatedLatency,\n fallbackAvailable,\n };\n}\n","import axios, { AxiosError } from 'axios';\nimport { Buffer } from 'buffer';\nimport { ethers } from 'ethers';\nimport {\n EthCallQueryRequest,\n EthCallQueryResponse,\n PerChainQueryRequest,\n QueryRequest,\n QueryResponse,\n hexToUint8Array,\n isValidHexString,\n} from '@wormhole-foundation/wormhole-query-sdk';\n\nimport { MAINNET_CHAINS, TESTNET_CHAINS } from '../constants.js';\nimport { WORMHOLE_QUERY_PROXY_URLS } from './constants.js';\n\nexport type QueryHubStateNetwork = 'testnet' | 'mainnet';\n\nexport type QueryHubStateOptions = {\n /** Max response age in seconds (default: 60). */\n maxAge?: number;\n network?: QueryHubStateNetwork;\n /** Maximum attempts including the first try (default: 4). */\n maxAttempts?: number;\n};\n\nexport type HubStateResult = {\n nonce: bigint;\n isRegistered: boolean;\n blockTime: number;\n proof: Uint8Array;\n /** Last action hash (Issue #9/#10 - for action-hash binding) */\n lastActionHash?: string;\n};\n\nexport type QueryHubStateErrorCode =\n | 'INVALID_ARGUMENT'\n | 'UNSUPPORTED_NETWORK'\n | 'MISSING_HUB_ADDRESS'\n | 'PROXY_HTTP_ERROR'\n | 'PROXY_RESPONSE_INVALID'\n | 'ATTESTATION_STALE'\n | 'QUERY_RESPONSE_INVALID';\n\nexport class QueryHubStateError extends Error {\n code: QueryHubStateErrorCode;\n cause?: unknown;\n\n constructor(code: QueryHubStateErrorCode, message: string, cause?: unknown) {\n super(message);\n this.name = 'QueryHubStateError';\n this.code = code;\n this.cause = cause;\n }\n}\n\nfunction resolveNetwork(options?: QueryHubStateOptions): QueryHubStateNetwork {\n if (options?.network) return options.network;\n\n const envCandidates = [\n (globalThis as any)?.process?.env?.NEXT_PUBLIC_VERIDEX_NETWORK,\n (globalThis as any)?.process?.env?.VERIDEX_NETWORK,\n (globalThis as any)?.process?.env?.NEXT_PUBLIC_WORMHOLE_NETWORK,\n (globalThis as any)?.process?.env?.WORMHOLE_NETWORK,\n ].filter(Boolean);\n\n const env = (envCandidates[0] as string | undefined)?.toLowerCase();\n if (env === 'mainnet' || env === 'testnet') return env;\n\n // Default to testnet to support Base Sepolia out-of-the-box.\n return 'testnet';\n}\n\nfunction concatBytes(parts: Uint8Array[]): Uint8Array {\n const total = parts.reduce((sum, p) => sum + p.length, 0);\n const out = new Uint8Array(total);\n let offset = 0;\n for (const p of parts) {\n out.set(p, offset);\n offset += p.length;\n }\n return out;\n}\n\nfunction signaturesToProofBytes(signatures: string[]): Uint8Array {\n const chunks: Uint8Array[] = [];\n\n for (const sig of signatures) {\n if (typeof sig !== 'string' || sig.length !== 132 || !/^[0-9a-fA-F]+$/.test(sig)) {\n throw new QueryHubStateError(\n 'PROXY_RESPONSE_INVALID',\n `Invalid guardian signature format (expected 132 hex chars): ${String(sig)}`\n );\n }\n // Avoid Node Buffer-backed Uint8Array (can surface as SharedArrayBuffer in DTS types).\n chunks.push(hexToUint8Array(`0x${sig}`));\n }\n\n return concatBytes(chunks);\n}\n\nfunction decodeQueryBytes(bytes: string): Uint8Array {\n if (typeof bytes !== 'string' || bytes.length === 0) {\n throw new QueryHubStateError('PROXY_RESPONSE_INVALID', 'Missing query response bytes');\n }\n\n // Query Proxy commonly returns a 0x-prefixed hex string.\n if (isValidHexString(bytes)) {\n return hexToUint8Array(bytes);\n }\n\n // Fallback: attempt base64 decoding.\n try {\n if (typeof atob === 'function') {\n const raw = atob(bytes);\n const arr = new Uint8Array(raw.length);\n for (let i = 0; i < raw.length; i++) arr[i] = raw.charCodeAt(i);\n return arr;\n }\n } catch {\n // ignore\n }\n\n try {\n return new Uint8Array(Buffer.from(bytes, 'base64'));\n } catch (cause) {\n throw new QueryHubStateError('PROXY_RESPONSE_INVALID', 'Unrecognized query response bytes encoding', cause);\n }\n}\n\nfunction sleep(ms: number): Promise<void> {\n return new Promise((resolve) => setTimeout(resolve, ms));\n}\n\nasync function withExponentialBackoff<T>(\n fn: () => Promise<T>,\n maxAttempts: number\n): Promise<T> {\n let attempt = 0;\n let lastError: unknown;\n\n while (attempt < maxAttempts) {\n try {\n return await fn();\n } catch (err) {\n lastError = err;\n attempt += 1;\n if (attempt >= maxAttempts) break;\n\n const baseMs = 250;\n const backoffMs = Math.min(5_000, baseMs * 2 ** (attempt - 1));\n const jitterMs = Math.floor(Math.random() * 100);\n await sleep(backoffMs + jitterMs);\n }\n }\n\n throw lastError;\n}\n\nfunction getHubConfig(network: QueryHubStateNetwork): {\n wormholeChainId: number;\n hubAddress: string;\n endpoint: string;\n rpcUrl: string;\n} {\n if (network === 'testnet') {\n const baseSepolia = TESTNET_CHAINS.baseSepolia;\n if (!baseSepolia?.contracts?.hub) {\n throw new QueryHubStateError('MISSING_HUB_ADDRESS', 'Missing Base Sepolia hub address in SDK constants');\n }\n\n return {\n wormholeChainId: baseSepolia.wormholeChainId,\n hubAddress: baseSepolia.contracts.hub,\n endpoint: WORMHOLE_QUERY_PROXY_URLS.testnet,\n rpcUrl: baseSepolia.rpcUrl,\n };\n }\n\n if (network === 'mainnet') {\n const base = MAINNET_CHAINS.base;\n const hubAddress = (base?.contracts as any)?.hub as string | undefined;\n\n if (!hubAddress) {\n throw new QueryHubStateError(\n 'MISSING_HUB_ADDRESS',\n 'Missing mainnet hub address in SDK constants (MAINNET_CHAINS.base.contracts.hub)'\n );\n }\n\n return {\n wormholeChainId: base.wormholeChainId,\n hubAddress,\n endpoint: WORMHOLE_QUERY_PROXY_URLS.mainnet,\n rpcUrl: base.rpcUrl,\n };\n }\n\n throw new QueryHubStateError('UNSUPPORTED_NETWORK', `Unsupported network: ${network}`);\n}\n\nfunction encodeHubCalls(hubAddress: string, userKeyHash: string): { to: string; data: string }[] {\n // Support both the spec name and known on-chain variants.\n const nonceAbiCandidates = [\n 'function getUserNonce(bytes32 userKeyHash) view returns (uint256)',\n 'function userNonces(bytes32 userKeyHash) view returns (uint256)',\n 'function getNonceByHash(bytes32 userKeyHash) view returns (uint256)',\n ];\n\n const registeredAbiCandidates = [\n 'function registeredKeys(bytes32 userKeyHash) view returns (bool)',\n 'function isKeyRegisteredByHash(bytes32 userKeyHash) view returns (bool)',\n ];\n\n // Issue #9/#10: Add getUserLastActionHash for action-hash binding\n const actionHashAbiCandidates = [\n 'function getUserLastActionHash(bytes32 userKeyHash) view returns (bytes32)',\n 'function userLastActionHash(bytes32 userKeyHash) view returns (bytes32)',\n ];\n\n // We encode *all* candidates; the proxy will execute each call, and we decode the first successful one.\n // This makes the client resilient to Hub ABI differences across deployments.\n const iface = new ethers.Interface([\n ...nonceAbiCandidates,\n ...registeredAbiCandidates,\n ...actionHashAbiCandidates,\n ]);\n\n const nonceFnNames = ['getUserNonce', 'userNonces', 'getNonceByHash'] as const;\n const regFnNames = ['registeredKeys', 'isKeyRegisteredByHash'] as const;\n const actionHashFnNames = ['getUserLastActionHash', 'userLastActionHash'] as const;\n\n return [\n ...nonceFnNames.map((fn) => ({\n to: hubAddress,\n data: iface.encodeFunctionData(fn, [userKeyHash]),\n })),\n ...regFnNames.map((fn) => ({\n to: hubAddress,\n data: iface.encodeFunctionData(fn, [userKeyHash]),\n })),\n ...actionHashFnNames.map((fn) => ({\n to: hubAddress,\n data: iface.encodeFunctionData(fn, [userKeyHash]),\n })),\n ];\n}\n\nfunction decodeFirstNonce(results: string[]): bigint {\n const candidates = [\n 'function getUserNonce(bytes32 userKeyHash) view returns (uint256)',\n 'function userNonces(bytes32 userKeyHash) view returns (uint256)',\n 'function getNonceByHash(bytes32 userKeyHash) view returns (uint256)',\n ];\n const iface = new ethers.Interface(candidates);\n const fnNames = ['getUserNonce', 'userNonces', 'getNonceByHash'] as const;\n\n for (let idx = 0; idx < fnNames.length; idx++) {\n const fnName = fnNames[idx];\n try {\n const data = results[idx];\n if (!data || data === '0x') continue;\n const decoded = iface.decodeFunctionResult(fnName, data);\n return decoded[0] as bigint;\n } catch {\n // keep trying\n }\n }\n\n throw new QueryHubStateError('QUERY_RESPONSE_INVALID', 'Unable to decode user nonce from query response');\n}\n\nfunction decodeFirstIsRegistered(results: string[]): boolean {\n const nonceCandidateCount = 3;\n const candidates = [\n 'function registeredKeys(bytes32 userKeyHash) view returns (bool)',\n 'function isKeyRegisteredByHash(bytes32 userKeyHash) view returns (bool)',\n ];\n const iface = new ethers.Interface(candidates);\n const fnNames = ['registeredKeys', 'isKeyRegisteredByHash'] as const;\n\n for (let i = 0; i < fnNames.length; i++) {\n const fnName = fnNames[i];\n try {\n const data = results[nonceCandidateCount + i];\n if (!data || data === '0x') continue;\n const decoded = iface.decodeFunctionResult(fnName, data);\n return Boolean(decoded[0]);\n } catch {\n // keep trying\n }\n }\n\n // If the hub deployment doesn’t support registration, treat as false.\n return false;\n}\n\n/** * Decode last action hash from query results (Issue #9/#10)\n * Returns zero hash if not available (backwards compatibility)\n */\nfunction decodeLastActionHash(results: string[]): string {\n const nonceCandidateCount = 3;\n const registeredCandidateCount = 2;\n const actionHashOffset = nonceCandidateCount + registeredCandidateCount;\n\n const candidates = [\n 'function getUserLastActionHash(bytes32 userKeyHash) view returns (bytes32)',\n 'function userLastActionHash(bytes32 userKeyHash) view returns (bytes32)',\n ];\n const iface = new ethers.Interface(candidates);\n const fnNames = ['getUserLastActionHash', 'userLastActionHash'] as const;\n\n for (let i = 0; i < fnNames.length; i++) {\n const fnName = fnNames[i];\n try {\n const data = results[actionHashOffset + i];\n if (!data || data === '0x') continue;\n const decoded = iface.decodeFunctionResult(fnName, data);\n return decoded[0] as string;\n } catch {\n // keep trying\n }\n }\n\n // Backwards compatibility: return zero hash if not available\n return ethers.ZeroHash;\n}\n\n/** * Fetch Guardian-attested Hub state directly from the Wormhole Query Proxy.\n *\n * Client-side only: this avoids relayer API costs and produces a Guardian-signed proof\n * that can be forwarded to the relayer for on-chain verification/submission.\n */\nexport async function queryHubState(\n userKeyHash: string,\n apiKey: string,\n options?: QueryHubStateOptions\n): Promise<HubStateResult> {\n if (typeof userKeyHash !== 'string' || userKeyHash.length === 0) {\n throw new QueryHubStateError('INVALID_ARGUMENT', 'userKeyHash is required');\n }\n if (!isValidHexString(userKeyHash) || hexToUint8Array(userKeyHash).length !== 32) {\n throw new QueryHubStateError('INVALID_ARGUMENT', 'userKeyHash must be a 32-byte hex string');\n }\n if (typeof apiKey !== 'string' || apiKey.length === 0) {\n throw new QueryHubStateError('INVALID_ARGUMENT', 'apiKey is required');\n }\n\n const network = resolveNetwork(options);\n const maxAgeSeconds = options?.maxAge ?? 60;\n const maxAttempts = options?.maxAttempts ?? 4;\n\n const { wormholeChainId, hubAddress, endpoint, rpcUrl } = getHubConfig(network);\n\n const provider = new ethers.JsonRpcProvider(rpcUrl);\n\n const callData = encodeHubCalls(hubAddress, userKeyHash);\n\n const doFetch = async () => {\n try {\n const latestBlock = await provider.getBlockNumber();\n const blockTag = Math.max(0, latestBlock - 2);\n\n const request = new QueryRequest(Date.now() & 0xffffffff, [\n new PerChainQueryRequest(wormholeChainId, new EthCallQueryRequest(blockTag, callData)),\n ]);\n\n // Wormhole Query Proxy expects raw hex WITHOUT 0x prefix\n const requestHex = Buffer.from(request.serialize()).toString('hex');\n\n const response = await axios.post(\n endpoint,\n { bytes: requestHex },\n {\n headers: {\n 'X-API-Key': apiKey,\n 'Content-Type': 'application/json',\n },\n timeout: 10_000,\n }\n );\n\n const data = response.data as any;\n const signatures = data?.signatures as string[] | undefined;\n const bytes = data?.bytes as string | undefined;\n\n if (!Array.isArray(signatures) || typeof bytes !== 'string') {\n throw new QueryHubStateError('PROXY_RESPONSE_INVALID', 'Query Proxy response missing signatures/bytes');\n }\n\n const proof = signaturesToProofBytes(signatures);\n const queryBytes = decodeQueryBytes(bytes);\n const parsed = QueryResponse.from(queryBytes);\n\n const perChain = parsed.responses.find((r) => r.chainId === wormholeChainId);\n if (!perChain) {\n throw new QueryHubStateError('QUERY_RESPONSE_INVALID', 'Missing per-chain response for hub chain');\n }\n\n // The SDK provides a parser for the chain-specific response.\n const chainResp = EthCallQueryResponse.from(perChain.response.serialize());\n const blockTime = Number(chainResp.blockTime);\n\n const nowSeconds = Math.floor(Date.now() / 1000);\n if (nowSeconds - blockTime > maxAgeSeconds) {\n throw new QueryHubStateError(\n 'ATTESTATION_STALE',\n `Guardian attestation is stale (blockTime=${blockTime}, now=${nowSeconds}, maxAge=${maxAgeSeconds}s)`\n );\n }\n\n const nonce = decodeFirstNonce(chainResp.results);\n const isRegistered = decodeFirstIsRegistered(chainResp.results);\n const lastActionHash = decodeLastActionHash(chainResp.results);\n\n return {\n nonce,\n isRegistered,\n blockTime,\n proof,\n lastActionHash,\n } satisfies HubStateResult;\n } catch (err) {\n if (err instanceof QueryHubStateError) throw err;\n if (axios.isAxiosError(err)) {\n const ax = err as AxiosError;\n const status = ax.response?.status;\n const statusText = ax.response?.statusText;\n const details = typeof ax.response?.data === 'string' ? ax.response?.data : undefined;\n\n throw new QueryHubStateError(\n 'PROXY_HTTP_ERROR',\n `Query Proxy request failed${status ? ` (${status} ${statusText ?? ''})` : ''}${details ? `: ${details}` : ''}`,\n err\n );\n }\n\n throw new QueryHubStateError('PROXY_HTTP_ERROR', 'Query Proxy request failed', err);\n }\n };\n\n return await withExponentialBackoff(doFetch, maxAttempts);\n}\n","export const WORMHOLE_QUERY_PROXY_URLS = {\n mainnet: 'https://query.wormhole.com/v1/query',\n testnet: 'https://testnet.query.wormhole.com/v1/query',\n} as const;\n\n/**\n * Wormhole Query Proxy rate limit: 6 queries per second.\n * SDK callers should throttle requests accordingly.\n */\nexport const WORMHOLE_QUERY_RATE_LIMIT_PER_SECOND = 6;\n\n/**\n * Convenience set of Wormhole chain IDs commonly supported by Queries.\n * This is not an exhaustive list of all Wormhole chains.\n */\nexport const WORMHOLE_QUERY_CHAIN_IDS = {\n ETHEREUM: 2,\n POLYGON: 5,\n ARBITRUM: 23,\n OPTIMISM: 24,\n BASE: 30,\n} as const;\n","import axios, { AxiosError } from 'axios';\nimport { Buffer } from 'buffer';\nimport { ethers } from 'ethers';\nimport { PublicKey } from '@solana/web3.js';\nimport {\n EthCallQueryRequest,\n EthCallQueryResponse,\n PerChainQueryRequest,\n QueryRequest,\n QueryResponse,\n SolanaAccountQueryRequest,\n SolanaAccountQueryResponse,\n hexToUint8Array,\n isValidHexString,\n} from '@wormhole-foundation/wormhole-query-sdk';\n\nimport { MAINNET_CHAINS, TESTNET_CHAINS } from '../constants.js';\nimport { WalletManager } from '../core/WalletManager.js';\nimport { getAllTokens, isNativeToken } from '../constants/tokens.js';\nimport { WORMHOLE_QUERY_PROXY_URLS } from './constants.js';\n\nexport type QueryPortfolioNetwork = 'testnet' | 'mainnet';\n\nexport type QueryPortfolioOptions = {\n /** Max response age in seconds (default: 60). */\n maxAge?: number;\n network?: QueryPortfolioNetwork;\n /** Maximum attempts including the first try (default: 4). */\n maxAttempts?: number;\n /** Cache TTL in ms (default: 30_000). */\n cacheTtlMs?: number;\n /** Request timeout in ms (default: 15_000 for testnet, 10_000 for mainnet). */\n timeout?: number;\n /** Override Query Proxy endpoint. */\n endpoint?: string;\n /** Override per-chain RPC URLs used for block tag lookups. */\n rpcUrls?: Record<number, string>;\n /** Override derived vault addresses for specific Wormhole chain IDs. */\n vaultAddresses?: Record<number, string>;\n /** Override token lists (ERC20 only) for specific Wormhole chain IDs. */\n evmTokenAddresses?: Record<number, string[]>;\n /** Additional Solana accounts to include in the Solana account query (base58). */\n solanaAccounts?: string[];\n /** Optional USD prices by symbol/address for aggregation (e.g. { USDC: 1 }). */\n pricesUsd?: Record<string, number>;\n};\n\nexport type PortfolioBalance = {\n assetId: string;\n amount: bigint;\n decimals?: number;\n symbol?: string;\n usdValue?: number;\n};\n\nexport type PortfolioChainErrorCode =\n | 'UNSUPPORTED_CHAIN'\n | 'MISSING_VAULT'\n | 'MISSING_TOKENS'\n | 'ATTESTATION_STALE'\n | 'DECODE_ERROR';\n\nexport type PortfolioChainResult = {\n wormholeChainId: number;\n chainName?: string;\n vaultAddress?: string;\n blockTime?: number;\n balances: PortfolioBalance[];\n error?: {\n code: PortfolioChainErrorCode;\n message: string;\n };\n};\n\nexport type PortfolioResult = {\n proof: Uint8Array;\n totalUsd?: number;\n chains: PortfolioChainResult[];\n};\n\nexport type QueryPortfolioErrorCode =\n | 'INVALID_ARGUMENT'\n | 'NETWORK_ERROR'\n | 'PROXY_HTTP_ERROR'\n | 'PROXY_RESPONSE_INVALID'\n | 'QUERY_RESPONSE_INVALID';\n\nexport class QueryPortfolioError extends Error {\n code: QueryPortfolioErrorCode;\n cause?: unknown;\n\n constructor(code: QueryPortfolioErrorCode, message: string, cause?: unknown) {\n super(message);\n this.name = 'QueryPortfolioError';\n this.code = code;\n this.cause = cause;\n }\n}\n\ntype CacheEntry = { expiresAt: number; value: PortfolioResult };\nconst PORTFOLIO_CACHE = new Map<string, CacheEntry>();\n\nfunction resolveNetwork(options?: QueryPortfolioOptions): QueryPortfolioNetwork {\n if (options?.network) return options.network;\n\n const envCandidates = [\n (globalThis as any)?.process?.env?.NEXT_PUBLIC_VERIDEX_NETWORK,\n (globalThis as any)?.process?.env?.VERIDEX_NETWORK,\n (globalThis as any)?.process?.env?.NEXT_PUBLIC_WORMHOLE_NETWORK,\n (globalThis as any)?.process?.env?.WORMHOLE_NETWORK,\n ].filter(Boolean);\n\n const env = (envCandidates[0] as string | undefined)?.toLowerCase();\n if (env === 'mainnet' || env === 'testnet') return env;\n\n return 'testnet';\n}\n\nfunction concatBytes(parts: Uint8Array[]): Uint8Array {\n const total = parts.reduce((sum, p) => sum + p.length, 0);\n const out = new Uint8Array(total);\n let offset = 0;\n for (const p of parts) {\n out.set(p, offset);\n offset += p.length;\n }\n return out;\n}\n\nfunction signaturesToProofBytes(signatures: string[]): Uint8Array {\n const chunks: Uint8Array[] = [];\n\n for (const sig of signatures) {\n if (typeof sig !== 'string' || sig.length !== 132 || !/^[0-9a-fA-F]+$/.test(sig)) {\n throw new QueryPortfolioError(\n 'PROXY_RESPONSE_INVALID',\n `Invalid guardian signature format (expected 132 hex chars): ${String(sig)}`\n );\n }\n // Avoid Node Buffer-backed Uint8Array (can surface as SharedArrayBuffer in DTS types).\n chunks.push(hexToUint8Array(`0x${sig}`));\n }\n\n return concatBytes(chunks);\n}\n\nfunction decodeQueryBytes(bytes: string): Uint8Array {\n if (typeof bytes !== 'string' || bytes.length === 0) {\n throw new QueryPortfolioError('PROXY_RESPONSE_INVALID', 'Missing query response bytes');\n }\n\n if (isValidHexString(bytes)) {\n return hexToUint8Array(bytes);\n }\n\n try {\n if (typeof atob === 'function') {\n const raw = atob(bytes);\n const arr = new Uint8Array(raw.length);\n for (let i = 0; i < raw.length; i++) arr[i] = raw.charCodeAt(i);\n return arr;\n }\n } catch {\n // ignore\n }\n\n try {\n return new Uint8Array(Buffer.from(bytes, 'base64'));\n } catch (cause) {\n throw new QueryPortfolioError('PROXY_RESPONSE_INVALID', 'Unrecognized query response bytes encoding', cause);\n }\n}\n\nfunction sleep(ms: number): Promise<void> {\n return new Promise((resolve) => setTimeout(resolve, ms));\n}\n\n/**\n * Simple rate limiter for Wormhole Query Proxy (6 requests/second limit).\n * Queues requests and releases them at the allowed rate.\n */\nconst rateLimiter = {\n queue: [] as Array<() => void>,\n lastRequest: 0,\n minInterval: 170, // ~6 req/s with buffer\n \n async acquire(): Promise<void> {\n return new Promise((resolve) => {\n const tryAcquire = () => {\n const now = Date.now();\n const elapsed = now - rateLimiter.lastRequest;\n if (elapsed >= rateLimiter.minInterval) {\n rateLimiter.lastRequest = now;\n resolve();\n } else {\n setTimeout(tryAcquire, rateLimiter.minInterval - elapsed);\n }\n };\n tryAcquire();\n });\n }\n};\n\nasync function withExponentialBackoff<T>(fn: () => Promise<T>, maxAttempts: number): Promise<T> {\n let attempt = 0;\n let lastError: unknown;\n\n while (attempt < maxAttempts) {\n try {\n return await fn();\n } catch (err) {\n lastError = err;\n attempt += 1;\n if (attempt >= maxAttempts) break;\n\n const baseMs = 250;\n const backoffMs = Math.min(5_000, baseMs * 2 ** (attempt - 1));\n const jitterMs = Math.floor(Math.random() * 100);\n await sleep(backoffMs + jitterMs);\n }\n }\n\n throw lastError;\n}\n\nfunction getChainConfigs(network: QueryPortfolioNetwork) {\n return network === 'testnet' ? TESTNET_CHAINS : MAINNET_CHAINS;\n}\n\nfunction getProxyEndpoint(network: QueryPortfolioNetwork, options?: QueryPortfolioOptions): string {\n if (options?.endpoint) return options.endpoint;\n return network === 'testnet' ? WORMHOLE_QUERY_PROXY_URLS.testnet : WORMHOLE_QUERY_PROXY_URLS.mainnet;\n}\n\nfunction getDefaultPortfolioChains(network: QueryPortfolioNetwork): number[] {\n // Include hub (Base Sepolia 10004) and spoke chains\n return network === 'testnet' ? [10004, 10005, 10003, 1] : [30, 24, 23, 1];\n}\n\nfunction normalizeHex32(hex: string): Uint8Array {\n if (typeof hex !== 'string' || !/^0x[0-9a-fA-F]{64}$/.test(hex)) {\n throw new QueryPortfolioError('INVALID_ARGUMENT', `Invalid userKeyHash (expected 0x + 32 bytes hex): ${hex}`);\n }\n return new Uint8Array(Buffer.from(hex.slice(2), 'hex'));\n}\n\nfunction deriveSolanaVaultAddress(programIdBase58: string, userKeyHash: string): string {\n const programId = new PublicKey(programIdBase58);\n const keyHashBytes = normalizeHex32(userKeyHash);\n const [vaultPda] = PublicKey.findProgramAddressSync([Buffer.from('vault'), Buffer.from(keyHashBytes)], programId);\n return vaultPda.toBase58();\n}\n\nfunction makeCacheKey(userKeyHash: string, apiKey: string, options: QueryPortfolioOptions | undefined, chainIds: number[]) {\n // Do not include apiKey in the cache key; it should not affect the data.\n const payload = {\n userKeyHash,\n network: resolveNetwork(options),\n chainIds: [...chainIds].sort((a, b) => a - b),\n vaultAddresses: options?.vaultAddresses ?? null,\n evmTokenAddresses: options?.evmTokenAddresses ?? null,\n solanaAccounts: options?.solanaAccounts ?? null,\n endpoint: options?.endpoint ?? null,\n };\n\n void apiKey;\n return JSON.stringify(payload);\n}\n\nfunction safeNumberFromBigint(b: bigint): number {\n const n = Number(b);\n return Number.isFinite(n) ? n : 0;\n}\n\nfunction priceLookup(pricesUsd: Record<string, number> | undefined, symbol?: string, assetId?: string): number | undefined {\n if (!pricesUsd) return undefined;\n if (symbol && pricesUsd[symbol] != null) return pricesUsd[symbol];\n if (assetId && pricesUsd[assetId] != null) return pricesUsd[assetId];\n return undefined;\n}\n\nfunction sumUsd(balances: PortfolioBalance[], pricesUsd?: Record<string, number>): number | undefined {\n let total = 0;\n let any = false;\n\n for (const b of balances) {\n const p = priceLookup(pricesUsd, b.symbol, b.assetId);\n if (p == null) continue;\n if (b.decimals == null) continue;\n\n const denom = 10 ** b.decimals;\n const amount = Number(b.amount) / denom;\n if (!Number.isFinite(amount)) continue;\n total += amount * p;\n any = true;\n }\n\n return any ? total : undefined;\n}\n\nasync function getRecentBlockTag(rpcUrl: string): Promise<number> {\n const provider = new ethers.JsonRpcProvider(rpcUrl);\n const latest = await provider.getBlockNumber();\n return Math.max(0, latest - 2);\n}\n\nfunction encodeErc20BalanceCalls(vaultAddress: string, tokenAddresses: string[]): { to: string; data: string }[] {\n const iface = new ethers.Interface(['function balanceOf(address owner) view returns (uint256)']);\n return tokenAddresses.map((token) => ({\n to: token,\n data: iface.encodeFunctionData('balanceOf', [vaultAddress]),\n }));\n}\n\nfunction decodeErc20Balances(results: string[], tokenAddresses: string[]): bigint[] {\n const iface = new ethers.Interface(['function balanceOf(address owner) view returns (uint256)']);\n const out: bigint[] = [];\n for (let i = 0; i < tokenAddresses.length; i++) {\n const data = results[i];\n if (!data || data === '0x') {\n out.push(0n);\n continue;\n }\n const decoded = iface.decodeFunctionResult('balanceOf', data);\n out.push(decoded[0] as bigint);\n }\n return out;\n}\n\n/**\n * Fetch Guardian-attested vault balances across multiple chains in one Query Proxy request.\n *\n * Notes:\n * - EVM balances are ERC20-only via `eth_call` (native ETH is not queryable via this query type).\n * - Solana balance uses lamports of the Veridex vault PDA (plus optional extra accounts).\n * - Aptos is included only if/when Wormhole Queries adds Aptos query types (currently returned as unsupported).\n */\nexport async function queryPortfolio(\n userKeyHash: string,\n apiKey: string,\n options?: QueryPortfolioOptions\n): Promise<PortfolioResult> {\n const network = resolveNetwork(options);\n const maxAgeSeconds = options?.maxAge ?? 60;\n const maxAttempts = options?.maxAttempts ?? 4;\n const cacheTtlMs = options?.cacheTtlMs ?? 30_000;\n const endpoint = getProxyEndpoint(network, options);\n\n const chainIds = options?.rpcUrls ? Object.keys(options.rpcUrls).map(Number) : undefined;\n void chainIds;\n\n const requestedChains = options?.vaultAddresses\n ? Object.keys(options.vaultAddresses).map(Number)\n : undefined;\n\n const defaultChains = getDefaultPortfolioChains(network);\n const wormholeChainIds = options?.evmTokenAddresses\n ? Array.from(new Set([...defaultChains, ...Object.keys(options.evmTokenAddresses).map(Number)]))\n : defaultChains;\n\n // If the caller provided explicit vault overrides, include those chain IDs even if not in defaults.\n const finalChainIds = requestedChains\n ? Array.from(new Set([...wormholeChainIds, ...requestedChains]))\n : wormholeChainIds;\n\n if (!apiKey || typeof apiKey !== 'string') {\n throw new QueryPortfolioError('INVALID_ARGUMENT', 'Missing Query Proxy apiKey');\n }\n\n const cacheKey = makeCacheKey(userKeyHash, apiKey, options, finalChainIds);\n const cached = PORTFOLIO_CACHE.get(cacheKey);\n if (cached && cached.expiresAt > Date.now()) {\n return cached.value;\n }\n\n const chains = getChainConfigs(network);\n const walletManager = new WalletManager({ cacheAddresses: true, persistToStorage: false });\n\n const pricesUsd: Record<string, number> | undefined = {\n USDC: 1,\n ...(options?.pricesUsd ?? {}),\n };\n\n const doFetch = async (): Promise<PortfolioResult> => {\n try {\n const perChainRequests: PerChainQueryRequest[] = [];\n const chainMeta: Record<number, { vaultAddress?: string; chainName?: string; kind: 'evm' | 'solana' | 'unsupported' }> = {};\n\n // Precompute any EVM block tags in parallel to keep total latency down.\n const evmChainIds = finalChainIds.filter((id) => {\n const cfg = Object.values(chains).find((c) => c.wormholeChainId === id);\n return cfg?.isEvm;\n });\n\n const blockTagsByChainId = new Map<number, number>();\n await Promise.all(\n evmChainIds.map(async (wormholeChainId) => {\n const cfg = Object.values(chains).find((c) => c.wormholeChainId === wormholeChainId);\n if (!cfg) return;\n const rpcUrl = options?.rpcUrls?.[wormholeChainId] ?? cfg.rpcUrl;\n const blockTag = await getRecentBlockTag(rpcUrl);\n blockTagsByChainId.set(wormholeChainId, blockTag);\n })\n );\n\n for (const wormholeChainId of finalChainIds) {\n const cfg = Object.values(chains).find((c) => c.wormholeChainId === wormholeChainId);\n\n if (wormholeChainId === 22) {\n chainMeta[wormholeChainId] = { kind: 'unsupported', chainName: cfg?.name };\n continue;\n }\n\n if (!cfg) {\n chainMeta[wormholeChainId] = { kind: 'unsupported' };\n continue;\n }\n\n if (cfg.isEvm) {\n const vaultAddress = options?.vaultAddresses?.[wormholeChainId]\n ?? (cfg.contracts.vaultFactory && cfg.contracts.vaultImplementation\n ? walletManager.computeVaultAddress(userKeyHash, cfg.contracts.vaultFactory, cfg.contracts.vaultImplementation)\n : undefined);\n\n chainMeta[wormholeChainId] = { kind: 'evm', vaultAddress, chainName: cfg.name };\n\n if (!vaultAddress) {\n continue;\n }\n\n const tokenAddresses = options?.evmTokenAddresses?.[wormholeChainId]\n ?? getAllTokens(wormholeChainId).filter((t) => !isNativeToken(t.address)).map((t) => t.address);\n\n if (!tokenAddresses.length) {\n continue;\n }\n\n const blockTag = blockTagsByChainId.get(wormholeChainId);\n if (blockTag == null) {\n continue;\n }\n\n const calls = encodeErc20BalanceCalls(vaultAddress, tokenAddresses);\n perChainRequests.push(new PerChainQueryRequest(wormholeChainId, new EthCallQueryRequest(blockTag, calls)));\n continue;\n }\n\n // Solana\n if (wormholeChainId === 1) {\n const programId = options?.vaultAddresses?.[wormholeChainId] ?? cfg.contracts.hub;\n chainMeta[wormholeChainId] = { kind: 'solana', chainName: cfg.name };\n\n if (!programId) {\n continue;\n }\n\n const vaultAddress = deriveSolanaVaultAddress(programId, userKeyHash);\n chainMeta[wormholeChainId] = { kind: 'solana', chainName: cfg.name, vaultAddress };\n\n const accounts = [vaultAddress, ...(options?.solanaAccounts ?? [])];\n perChainRequests.push(\n new PerChainQueryRequest(\n wormholeChainId,\n new SolanaAccountQueryRequest('finalized', accounts, undefined, 0n, 0n)\n )\n );\n continue;\n }\n\n chainMeta[wormholeChainId] = { kind: 'unsupported', chainName: cfg.name };\n }\n\n if (perChainRequests.length > 255) {\n throw new QueryPortfolioError(\n 'INVALID_ARGUMENT',\n `Too many per-chain requests (${perChainRequests.length}); max is 255 per Query Proxy request`\n );\n }\n\n // If no per-chain requests were built (e.g., missing vaults or tokens), return early with empty results\n if (perChainRequests.length === 0) {\n const chainsOut: PortfolioChainResult[] = finalChainIds.map((wormholeChainId) => {\n const meta = chainMeta[wormholeChainId] ?? { kind: 'unsupported' as const };\n return {\n wormholeChainId,\n chainName: meta.chainName,\n vaultAddress: meta.vaultAddress,\n balances: [],\n error: { \n code: 'MISSING_VAULT' as const, \n message: 'Unable to build query: missing vault address or no tokens configured' \n },\n };\n });\n return { proof: new Uint8Array(), totalUsd: 0, chains: chainsOut };\n }\n\n const request = new QueryRequest(Date.now() & 0xffffffff, perChainRequests);\n // Wormhole Query Proxy expects raw hex WITHOUT 0x prefix\n const requestHex = Buffer.from(request.serialize()).toString('hex');\n\n // Respect rate limit before making request\n await rateLimiter.acquire();\n\n let response;\n try {\n console.log('[queryPortfolio] Sending request to:', endpoint);\n console.log('[queryPortfolio] Request bytes length:', requestHex.length);\n \n // Use provided timeout, or default to 15s for testnet (slower), 10s for mainnet\n const defaultTimeout = network === 'testnet' ? 15_000 : 10_000;\n const requestTimeout = options?.timeout ?? defaultTimeout;\n \n response = await axios.post(\n endpoint,\n { bytes: requestHex },\n {\n headers: {\n 'X-API-Key': apiKey,\n 'Content-Type': 'application/json',\n },\n timeout: requestTimeout,\n }\n );\n } catch (axiosErr) {\n const err = axiosErr as AxiosError;\n // Network errors (CORS, timeout, no connection) have no response\n if (!err.response) {\n console.error('[queryPortfolio] Network error:', {\n message: err.message,\n code: err.code,\n name: err.name,\n });\n throw new QueryPortfolioError(\n 'NETWORK_ERROR',\n `Network error: ${err.message} (code: ${err.code})`\n );\n }\n const status = err.response.status;\n const errData = err.response.data;\n console.error('[queryPortfolio] Wormhole Query Proxy error:', { status, data: errData });\n throw new QueryPortfolioError(\n 'PROXY_RESPONSE_INVALID',\n `Query Proxy returned ${status}: ${JSON.stringify(errData)}`\n );\n }\n\n const data = response.data as any;\n const signatures = data?.signatures as string[] | undefined;\n const bytes = data?.bytes as string | undefined;\n\n if (!Array.isArray(signatures) || typeof bytes !== 'string') {\n throw new QueryPortfolioError('PROXY_RESPONSE_INVALID', 'Query Proxy response missing signatures/bytes');\n }\n\n const proof = signaturesToProofBytes(signatures);\n const queryBytes = decodeQueryBytes(bytes);\n const parsed = QueryResponse.from(queryBytes);\n\n const nowSeconds = Math.floor(Date.now() / 1000);\n const chainsOut: PortfolioChainResult[] = [];\n\n for (const wormholeChainId of finalChainIds) {\n const meta = chainMeta[wormholeChainId] ?? { kind: 'unsupported' as const };\n\n if (meta.kind === 'unsupported') {\n const msg = wormholeChainId === 22\n ? 'Aptos Queries are not supported by the Wormhole Query SDK yet'\n : 'Chain is not supported by this portfolio query implementation';\n chainsOut.push({\n wormholeChainId,\n chainName: meta.chainName,\n balances: [],\n error: { code: 'UNSUPPORTED_CHAIN', message: msg },\n });\n continue;\n }\n\n if (!meta.vaultAddress) {\n chainsOut.push({\n wormholeChainId,\n chainName: meta.chainName,\n balances: [],\n error: { code: 'MISSING_VAULT', message: 'Unable to derive vault address for chain' },\n });\n continue;\n }\n\n const perChain = parsed.responses.find((r) => r.chainId === wormholeChainId);\n if (!perChain) {\n chainsOut.push({\n wormholeChainId,\n chainName: meta.chainName,\n vaultAddress: meta.vaultAddress,\n balances: [],\n error: { code: 'DECODE_ERROR', message: 'Missing per-chain response from Query Proxy' },\n });\n continue;\n }\n\n try {\n if (meta.kind === 'evm') {\n const cfg = Object.values(chains).find((c) => c.wormholeChainId === wormholeChainId);\n const tokenAddresses = options?.evmTokenAddresses?.[wormholeChainId]\n ?? getAllTokens(wormholeChainId).filter((t) => !isNativeToken(t.address)).map((t) => t.address);\n\n if (!tokenAddresses.length) {\n chainsOut.push({\n wormholeChainId,\n chainName: meta.chainName,\n vaultAddress: meta.vaultAddress,\n balances: [],\n error: { code: 'MISSING_TOKENS', message: 'No ERC20 tokens configured for EVM portfolio query' },\n });\n continue;\n }\n\n const chainResp = EthCallQueryResponse.from(perChain.response.serialize());\n const blockTime = Number(chainResp.blockTime);\n const age = nowSeconds - blockTime;\n if (age > maxAgeSeconds) {\n chainsOut.push({\n wormholeChainId,\n chainName: meta.chainName,\n vaultAddress: meta.vaultAddress,\n blockTime,\n balances: [],\n error: { code: 'ATTESTATION_STALE', message: `Attestation stale by ${age}s (maxAge=${maxAgeSeconds}s)` },\n });\n continue;\n }\n\n const amounts = decodeErc20Balances(chainResp.results, tokenAddresses);\n const tokenInfos = getAllTokens(wormholeChainId).filter((t) => !isNativeToken(t.address));\n\n const balances: PortfolioBalance[] = tokenAddresses.map((addr, i) => {\n const info = tokenInfos.find((t) => t.address.toLowerCase() === addr.toLowerCase());\n const symbol = info?.symbol;\n const decimals = info?.decimals;\n const usdPrice = priceLookup(pricesUsd, symbol, addr);\n const usdValue = usdPrice != null && decimals != null\n ? (Number(amounts[i]) / 10 ** decimals) * usdPrice\n : undefined;\n\n return {\n assetId: addr,\n amount: amounts[i],\n symbol,\n decimals,\n usdValue: Number.isFinite(usdValue ?? NaN) ? usdValue : undefined,\n };\n });\n\n void cfg;\n chainsOut.push({\n wormholeChainId,\n chainName: meta.chainName,\n vaultAddress: meta.vaultAddress,\n blockTime,\n balances,\n });\n continue;\n }\n\n // Solana\n const chainResp = SolanaAccountQueryResponse.from(perChain.response.serialize());\n const blockTime = safeNumberFromBigint(chainResp.blockTime);\n const age = nowSeconds - blockTime;\n if (age > maxAgeSeconds) {\n chainsOut.push({\n wormholeChainId,\n chainName: meta.chainName,\n vaultAddress: meta.vaultAddress,\n blockTime,\n balances: [],\n error: { code: 'ATTESTATION_STALE', message: `Attestation stale by ${age}s (maxAge=${maxAgeSeconds}s)` },\n });\n continue;\n }\n\n const vaultResult = chainResp.results[0];\n const lamports = vaultResult?.lamports ?? 0n;\n\n const balances: PortfolioBalance[] = [\n {\n assetId: 'SOL',\n amount: lamports,\n decimals: 9,\n symbol: 'SOL',\n usdValue: priceLookup(pricesUsd, 'SOL', 'SOL') != null\n ? (Number(lamports) / 1e9) * (priceLookup(pricesUsd, 'SOL', 'SOL') as number)\n : undefined,\n },\n ];\n\n chainsOut.push({\n wormholeChainId,\n chainName: meta.chainName,\n vaultAddress: meta.vaultAddress,\n blockTime,\n balances,\n });\n } catch (cause) {\n chainsOut.push({\n wormholeChainId,\n chainName: meta.chainName,\n vaultAddress: meta.vaultAddress,\n balances: [],\n error: { code: 'DECODE_ERROR', message: `Failed to decode chain response: ${String((cause as any)?.message ?? cause)}` },\n });\n }\n }\n\n const allBalances = chainsOut.flatMap((c) => c.balances);\n const totalUsd = sumUsd(allBalances, pricesUsd);\n\n const result: PortfolioResult = { proof, totalUsd, chains: chainsOut };\n\n PORTFOLIO_CACHE.set(cacheKey, { expiresAt: Date.now() + cacheTtlMs, value: result });\n return result;\n } catch (err) {\n if (err instanceof QueryPortfolioError) throw err;\n if (axios.isAxiosError(err)) {\n const ax = err as AxiosError;\n const status = ax.response?.status;\n const statusText = ax.response?.statusText;\n const details = typeof ax.response?.data === 'string' ? ax.response?.data : undefined;\n\n throw new QueryPortfolioError(\n 'PROXY_HTTP_ERROR',\n `Query Proxy request failed${status ? ` (${status} ${statusText ?? ''})` : ''}${details ? `: ${details}` : ''}`,\n err\n );\n }\n\n throw new QueryPortfolioError('PROXY_HTTP_ERROR', 'Query Proxy request failed', err);\n }\n };\n\n const result = await withExponentialBackoff(doFetch, maxAttempts);\n PORTFOLIO_CACHE.set(cacheKey, { expiresAt: Date.now() + cacheTtlMs, value: result });\n return result;\n}\n","/**\n * Gas Sponsor Module\n * \n * Handles sponsored (gasless) vault creation for Veridex users.\n * Uses a Veridex-owned wallet to pay gas fees on behalf of users.\n * \n * This is a temporary solution until the full relayer is built.\n * In the future, this will be handled by:\n * - ERC-4337 Account Abstraction with Paymasters\n * - Dedicated Relayer service\n */\n\nimport { ethers } from 'ethers';\n\n// ============================================================================\n// Types\n// ============================================================================\n\nexport interface ChainDeploymentConfig {\n name: string;\n chainId: number;\n wormholeChainId: number;\n rpcUrl: string;\n vaultFactory?: string;\n hubAddress?: string;\n isHub?: boolean;\n}\n\nexport interface SponsoredVaultResult {\n success: boolean;\n chain: string;\n wormholeChainId: number;\n vaultAddress?: string;\n transactionHash?: string;\n error?: string;\n alreadyExists?: boolean;\n}\n\nexport interface MultiChainVaultResult {\n keyHash: string;\n results: SponsoredVaultResult[];\n allSuccessful: boolean;\n vaultAddresses: Record<number, string>; // wormholeChainId -> address\n}\n\nexport interface GasSponsorConfig {\n /** \n * Private key for the sponsor wallet (from env or secure storage)\n * This is the fallback when relayer is not available\n */\n sponsorPrivateKey?: string;\n \n /**\n * Integrator-provided sponsor key (for platforms using Veridex SDK)\n * Takes priority over Veridex default sponsorship\n */\n integratorSponsorKey?: string;\n \n /** \n * Relayer API endpoint for remote sponsorship (primary method)\n * When available, this takes priority over local wallet sponsorship\n */\n relayerUrl?: string;\n \n /** API key for relayer service authentication */\n relayerApiKey?: string;\n \n /** @deprecated Use relayerUrl instead */\n sponsorApiUrl?: string;\n /** @deprecated Use relayerApiKey instead */\n sponsorApiKey?: string;\n \n /** Whether to use testnet configurations */\n testnet?: boolean;\n /** Custom RPC URLs by wormhole chain ID */\n customRpcUrls?: Record<number, string>;\n}\n\n/** Sponsorship source type */\nexport type SponsorshipSource = 'relayer' | 'integrator' | 'veridex' | 'none';\n\n// ============================================================================\n// Constants\n// ============================================================================\n\n// Vault Factory ABI (minimal)\nconst VAULT_FACTORY_ABI = [\n 'function createVault(bytes32 ownerKeyHash) external returns (address)',\n 'function getVault(bytes32 ownerKeyHash) external view returns (address)',\n 'function vaultExists(bytes32 ownerKeyHash) external view returns (bool)',\n 'function computeVaultAddress(bytes32 ownerKeyHash) external view returns (address)',\n 'event VaultCreated(address indexed vault, bytes32 indexed ownerKeyHash, address creator)',\n];\n\n// Testnet chain configurations\nconst TESTNET_CHAINS: ChainDeploymentConfig[] = [\n {\n name: 'Base Sepolia',\n chainId: 84532,\n wormholeChainId: 10004,\n rpcUrl: 'https://sepolia.base.org',\n hubAddress: '0xf189b649ecb44708165f36619ED24ff917eF1f94',\n isHub: true,\n },\n {\n name: 'Optimism Sepolia',\n chainId: 11155420,\n wormholeChainId: 10005,\n rpcUrl: 'https://sepolia.optimism.io',\n vaultFactory: '0x677bA5C2f9c7377860c7aeB00037E1a5D12B3515',\n },\n {\n name: 'Arbitrum Sepolia',\n chainId: 421614,\n wormholeChainId: 10003,\n rpcUrl: 'https://sepolia-rollup.arbitrum.io/rpc',\n vaultFactory: '0xbE9B9c39956448DA75Ac97E5e3dE17e34171660A',\n },\n];\n\n// Mainnet chain configurations (for future use)\nconst MAINNET_CHAINS: ChainDeploymentConfig[] = [\n // Will be populated when mainnet is ready\n];\n\n// ============================================================================\n// GasSponsor Class\n// ============================================================================\n\n/**\n * Gas Sponsorship with layered fallback:\n * 1. Relayer (primary) - Remote relayer service handles gas\n * 2. Integrator wallet - Platform using SDK provides their own sponsor key\n * 3. Veridex wallet (fallback) - Veridex's default sponsor wallet\n */\nexport class GasSponsor {\n private config: GasSponsorConfig;\n private sponsorWallet?: ethers.Wallet;\n private integratorWallet?: ethers.Wallet;\n private chains: ChainDeploymentConfig[];\n\n constructor(config: GasSponsorConfig = {}) {\n this.config = config;\n this.chains = config.testnet !== false ? TESTNET_CHAINS : MAINNET_CHAINS;\n\n // Initialize integrator wallet if provided (takes priority)\n if (config.integratorSponsorKey) {\n this.integratorWallet = new ethers.Wallet(config.integratorSponsorKey);\n }\n\n // Initialize Veridex sponsor wallet as fallback\n if (config.sponsorPrivateKey) {\n this.sponsorWallet = new ethers.Wallet(config.sponsorPrivateKey);\n }\n }\n\n /**\n * Determine which sponsorship source is available\n * Priority: Relayer > Integrator > Veridex > None\n */\n getSponsorshipSource(): SponsorshipSource {\n // 1. Check relayer first (future primary method)\n if (this.config.relayerUrl || this.config.sponsorApiUrl) {\n return 'relayer';\n }\n \n // 2. Check integrator-provided wallet\n if (this.integratorWallet) {\n return 'integrator';\n }\n \n // 3. Check Veridex fallback wallet\n if (this.sponsorWallet) {\n return 'veridex';\n }\n \n return 'none';\n }\n\n /**\n * Get the active sponsor wallet (integrator takes priority)\n */\n private getActiveWallet(): ethers.Wallet | undefined {\n return this.integratorWallet || this.sponsorWallet;\n }\n\n /**\n * Get supported chains for vault deployment\n */\n getSupportedChains(): ChainDeploymentConfig[] {\n return this.chains.filter(c => c.vaultFactory);\n }\n\n /**\n * Get the hub chain configuration\n */\n getHubChain(): ChainDeploymentConfig | undefined {\n return this.chains.find(c => c.isHub);\n }\n\n /**\n * Check if sponsor is configured (has relayer, integrator key, or Veridex key)\n */\n isConfigured(): boolean {\n return this.getSponsorshipSource() !== 'none';\n }\n\n /**\n * Get sponsor wallet balance on a specific chain\n */\n async getSponsorBalance(wormholeChainId: number): Promise<bigint> {\n const chain = this.chains.find(c => c.wormholeChainId === wormholeChainId);\n const wallet = this.getActiveWallet();\n if (!chain || !wallet) {\n return BigInt(0);\n }\n\n const rpcUrl = this.config.customRpcUrls?.[wormholeChainId] || chain.rpcUrl;\n const provider = new ethers.JsonRpcProvider(rpcUrl);\n return await provider.getBalance(wallet.address);\n }\n\n /**\n * Check if a vault exists for a given key hash on a chain\n */\n async checkVaultExists(\n keyHash: string,\n wormholeChainId: number\n ): Promise<{ exists: boolean; address: string }> {\n const chain = this.chains.find(c => c.wormholeChainId === wormholeChainId);\n if (!chain || !chain.vaultFactory) {\n return { exists: false, address: ethers.ZeroAddress };\n }\n\n const rpcUrl = this.config.customRpcUrls?.[wormholeChainId] || chain.rpcUrl;\n const provider = new ethers.JsonRpcProvider(rpcUrl);\n const factory = new ethers.Contract(chain.vaultFactory, VAULT_FACTORY_ABI, provider);\n\n try {\n const address = await factory.getVault(keyHash);\n const exists = address !== ethers.ZeroAddress;\n return { exists, address };\n } catch (error) {\n console.error(`Error checking vault on ${chain.name}:`, error);\n return { exists: false, address: ethers.ZeroAddress };\n }\n }\n\n /**\n * Get predicted vault address for a key hash on a chain\n */\n async computeVaultAddress(\n keyHash: string,\n wormholeChainId: number\n ): Promise<string | null> {\n const chain = this.chains.find(c => c.wormholeChainId === wormholeChainId);\n if (!chain || !chain.vaultFactory) {\n return null;\n }\n\n const rpcUrl = this.config.customRpcUrls?.[wormholeChainId] || chain.rpcUrl;\n const provider = new ethers.JsonRpcProvider(rpcUrl);\n const factory = new ethers.Contract(chain.vaultFactory, VAULT_FACTORY_ABI, provider);\n\n try {\n return await factory.computeVaultAddress(keyHash);\n } catch (error) {\n console.error(`Error computing vault address on ${chain.name}:`, error);\n return null;\n }\n }\n\n /**\n * Create a vault on a specific chain (sponsored)\n * \n * Sponsorship priority:\n * 1. Relayer API (future - not yet implemented)\n * 2. Integrator wallet (if provided)\n * 3. Veridex sponsor wallet (fallback)\n */\n async createVaultOnChain(\n keyHash: string,\n wormholeChainId: number\n ): Promise<SponsoredVaultResult> {\n const chain = this.chains.find(c => c.wormholeChainId === wormholeChainId);\n \n if (!chain) {\n return {\n success: false,\n chain: 'Unknown',\n wormholeChainId,\n error: `Chain ${wormholeChainId} not found`,\n };\n }\n\n if (!chain.vaultFactory) {\n return {\n success: false,\n chain: chain.name,\n wormholeChainId,\n error: `No vault factory configured for ${chain.name}`,\n };\n }\n\n const source = this.getSponsorshipSource();\n\n // 1. Check if using relayer API (future primary method)\n if (source === 'relayer') {\n const relayerUrl = this.config.relayerUrl || this.config.sponsorApiUrl;\n if (relayerUrl) {\n return await this.createVaultViaRelayer(keyHash, chain, relayerUrl);\n }\n }\n\n // 2. Use local wallet (integrator or Veridex)\n const wallet = this.getActiveWallet();\n if (!wallet) {\n return {\n success: false,\n chain: chain.name,\n wormholeChainId,\n error: 'No sponsor configured. Set VERIDEX_SPONSOR_KEY or provide integratorSponsorKey.',\n };\n }\n\n const sponsorType = source === 'integrator' ? 'Integrator' : 'Veridex';\n\n try {\n const rpcUrl = this.config.customRpcUrls?.[wormholeChainId] || chain.rpcUrl;\n const provider = new ethers.JsonRpcProvider(rpcUrl);\n const signer = wallet.connect(provider);\n const factory = new ethers.Contract(chain.vaultFactory, VAULT_FACTORY_ABI, signer);\n\n // Check if vault already exists\n const existingVault = await factory.getVault(keyHash);\n if (existingVault !== ethers.ZeroAddress) {\n return {\n success: true,\n chain: chain.name,\n wormholeChainId,\n vaultAddress: existingVault,\n alreadyExists: true,\n };\n }\n\n // Check sponsor balance\n const balance = await provider.getBalance(signer.address);\n if (balance < ethers.parseEther('0.001')) {\n return {\n success: false,\n chain: chain.name,\n wormholeChainId,\n error: `Insufficient ${sponsorType} sponsor balance on ${chain.name}`,\n };\n }\n\n // Create vault\n console.log(`[GasSponsor] Creating vault on ${chain.name} (${sponsorType} sponsored)...`);\n const tx = await factory.createVault(keyHash);\n const receipt = await tx.wait();\n\n // Get vault address from event or direct query\n const vaultAddress = await factory.getVault(keyHash);\n\n console.log(`[GasSponsor] OK Vault created on ${chain.name}: ${vaultAddress}`);\n\n return {\n success: true,\n chain: chain.name,\n wormholeChainId,\n vaultAddress,\n transactionHash: receipt.hash,\n };\n } catch (error: any) {\n console.error(`[GasSponsor] Error creating vault on ${chain.name}:`, error);\n return {\n success: false,\n chain: chain.name,\n wormholeChainId,\n error: error.message || 'Unknown error',\n };\n }\n }\n\n /**\n * Create vault via relayer service (future primary method)\n * \n * The relayer handles:\n * - Gas payment on behalf of users\n * - Transaction submission and monitoring\n * - Rate limiting and abuse prevention\n */\n private async createVaultViaRelayer(\n keyHash: string,\n chain: ChainDeploymentConfig,\n relayerUrl: string\n ): Promise<SponsoredVaultResult> {\n try {\n const apiKey = this.config.relayerApiKey || this.config.sponsorApiKey;\n \n const response = await fetch(`${relayerUrl}/create-vault`, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n ...(apiKey && {\n 'Authorization': `Bearer ${apiKey}`,\n }),\n },\n body: JSON.stringify({\n keyHash,\n wormholeChainId: chain.wormholeChainId,\n }),\n });\n\n if (!response.ok) {\n const error = await response.text();\n \n // If relayer fails, try fallback to local wallet\n console.warn(`[GasSponsor] Relayer failed, trying local wallet fallback...`);\n const wallet = this.getActiveWallet();\n if (wallet) {\n return await this.createVaultWithWallet(keyHash, chain, wallet);\n }\n \n throw new Error(`Relayer error: ${error}`);\n }\n\n const result = await response.json();\n return {\n success: true,\n chain: chain.name,\n wormholeChainId: chain.wormholeChainId,\n vaultAddress: result.vaultAddress,\n transactionHash: result.transactionHash,\n alreadyExists: result.alreadyExists,\n };\n } catch (error: any) {\n // Fallback to local wallet if relayer fails\n console.warn(`[GasSponsor] Relayer unavailable: ${error.message}`);\n const wallet = this.getActiveWallet();\n if (wallet) {\n console.log(`[GasSponsor] Falling back to local wallet sponsorship...`);\n return await this.createVaultWithWallet(keyHash, chain, wallet);\n }\n \n return {\n success: false,\n chain: chain.name,\n wormholeChainId: chain.wormholeChainId,\n error: error.message || 'Relayer request failed and no fallback available',\n };\n }\n }\n\n /**\n * Create vault with a specific wallet (internal helper)\n */\n private async createVaultWithWallet(\n keyHash: string,\n chain: ChainDeploymentConfig,\n wallet: ethers.Wallet\n ): Promise<SponsoredVaultResult> {\n if (!chain.vaultFactory) {\n return {\n success: false,\n chain: chain.name,\n wormholeChainId: chain.wormholeChainId,\n error: `No vault factory for ${chain.name}`,\n };\n }\n\n try {\n const rpcUrl = this.config.customRpcUrls?.[chain.wormholeChainId] || chain.rpcUrl;\n const provider = new ethers.JsonRpcProvider(rpcUrl);\n const signer = wallet.connect(provider);\n const factory = new ethers.Contract(chain.vaultFactory, VAULT_FACTORY_ABI, signer);\n\n // Check if vault already exists\n const existingVault = await factory.getVault(keyHash);\n if (existingVault !== ethers.ZeroAddress) {\n return {\n success: true,\n chain: chain.name,\n wormholeChainId: chain.wormholeChainId,\n vaultAddress: existingVault,\n alreadyExists: true,\n };\n }\n\n // Check balance\n const balance = await provider.getBalance(signer.address);\n if (balance < ethers.parseEther('0.001')) {\n return {\n success: false,\n chain: chain.name,\n wormholeChainId: chain.wormholeChainId,\n error: `Insufficient sponsor balance on ${chain.name}`,\n };\n }\n\n // Create vault\n const tx = await factory.createVault(keyHash);\n const receipt = await tx.wait();\n const vaultAddress = await factory.getVault(keyHash);\n\n return {\n success: true,\n chain: chain.name,\n wormholeChainId: chain.wormholeChainId,\n vaultAddress,\n transactionHash: receipt.hash,\n };\n } catch (error: any) {\n return {\n success: false,\n chain: chain.name,\n wormholeChainId: chain.wormholeChainId,\n error: error.message || 'Wallet creation failed',\n };\n }\n }\n\n /**\n * Create vaults on all supported chains (sponsored)\n */\n async createVaultsOnAllChains(keyHash: string): Promise<MultiChainVaultResult> {\n const supportedChains = this.getSupportedChains();\n const results: SponsoredVaultResult[] = [];\n const vaultAddresses: Record<number, string> = {};\n\n console.log(`[GasSponsor] Creating vaults on ${supportedChains.length} chains...`);\n\n // Create vaults in parallel (or sequentially for rate limiting)\n for (const chain of supportedChains) {\n const result = await this.createVaultOnChain(keyHash, chain.wormholeChainId);\n results.push(result);\n\n if (result.success && result.vaultAddress) {\n vaultAddresses[chain.wormholeChainId] = result.vaultAddress;\n }\n }\n\n const allSuccessful = results.every(r => r.success);\n\n return {\n keyHash,\n results,\n allSuccessful,\n vaultAddresses,\n };\n }\n\n /**\n * Check vault status on all chains\n */\n async checkVaultsOnAllChains(keyHash: string): Promise<Record<number, { exists: boolean; address: string }>> {\n const supportedChains = this.getSupportedChains();\n const results: Record<number, { exists: boolean; address: string }> = {};\n\n for (const chain of supportedChains) {\n results[chain.wormholeChainId] = await this.checkVaultExists(keyHash, chain.wormholeChainId);\n }\n\n return results;\n }\n}\n\n// ============================================================================\n// Factory Function\n// ============================================================================\n\n/**\n * Create a GasSponsor instance\n * \n * @example\n * ```ts\n * // With environment variable\n * const sponsor = createGasSponsor({\n * sponsorPrivateKey: process.env.VERIDEX_SPONSOR_KEY,\n * testnet: true,\n * });\n * \n * // Create vaults for a user\n * const result = await sponsor.createVaultsOnAllChains(userKeyHash);\n * ```\n */\nexport function createGasSponsor(config: GasSponsorConfig = {}): GasSponsor {\n return new GasSponsor(config);\n}\n\n// ============================================================================\n// Convenience Functions\n// ============================================================================\n\n/**\n * Quick check if gas sponsorship is available\n */\nexport function isSponsorshipAvailable(): boolean {\n return !!(\n typeof process !== 'undefined' &&\n (process.env?.VERIDEX_SPONSOR_KEY || process.env?.NEXT_PUBLIC_SPONSOR_API_URL)\n );\n}\n\n/**\n * Get chain configurations for display\n */\nexport function getSupportedChainConfigs(testnet: boolean = true): ChainDeploymentConfig[] {\n return (testnet ? TESTNET_CHAINS : MAINNET_CHAINS).filter(c => c.vaultFactory);\n}\n","/**\n * Veridex Protocol SDK - EVM Chain Client\n * \n * Implementation of ChainClient interface for EVM-compatible chains\n */\n\nimport { ethers } from 'ethers';\nimport type {\n ChainClient,\n ChainConfig,\n TransferParams,\n ExecuteParams,\n BridgeParams,\n DispatchResult,\n WebAuthnSignature,\n VaultCreationResult,\n} from '../../core/types.js';\nimport { encodeTransferAction, encodeExecuteAction, encodeBridgeAction } from '../../payload.js';\n\n// ============================================================================\n// Types\n// ============================================================================\n\nexport interface EVMClientConfig {\n chainId: number;\n wormholeChainId: number;\n rpcUrl: string;\n hubContractAddress: string;\n wormholeCoreBridge: string;\n name?: string;\n explorerUrl?: string;\n vaultFactory?: string;\n vaultImplementation?: string;\n tokenBridge?: string;\n}\n\n// ============================================================================\n// Constants\n// ============================================================================\n\n/**\n * EIP-1167 minimal proxy bytecode prefix (before implementation address)\n */\nconst PROXY_BYTECODE_PREFIX = '0x3d602d80600a3d3981f3363d3d373d3d3d363d73';\n\n/**\n * EIP-1167 minimal proxy bytecode suffix (after implementation address)\n */\nconst PROXY_BYTECODE_SUFFIX = '5af43d82803e903d91602b57fd5bf3';\n\n/**\n * ERC20 ABI for balance and transfer operations\n */\nconst ERC20_ABI = [\n 'function balanceOf(address owner) view returns (uint256)',\n 'function decimals() view returns (uint8)',\n 'function symbol() view returns (string)',\n 'function name() view returns (string)',\n 'function allowance(address owner, address spender) view returns (uint256)',\n 'function transfer(address to, uint256 amount) returns (bool)',\n 'function approve(address spender, uint256 amount) returns (bool)',\n];\n\n// ============================================================================\n// Hub Contract ABI (minimal)\n// ============================================================================\n\nconst HUB_ABI = [\n 'function dispatch(tuple(bytes authenticatorData, string clientDataJSON, uint256 challengeIndex, uint256 typeIndex, uint256 r, uint256 s) signature, uint256 publicKeyX, uint256 publicKeyY, uint16 targetChain, bytes actionPayload, uint256 nonce) payable returns (uint64 sequence)',\n 'function getNonce(bytes32 userKeyHash) view returns (uint256)',\n 'function getMessageFee() view returns (uint256)',\n 'function getVaultAddress(bytes32 userKeyHash) view returns (address)',\n 'function vaultExists(bytes32 userKeyHash) view returns (bool)',\n 'function createVault(bytes32 userKeyHash) returns (address)',\n // Issue #9/#10: New Hub methods for Query-based execution\n 'function getUserState(bytes32 userKeyHash) view returns (bytes32 keyHash, uint256 nonce, bytes32 lastActionHash)',\n 'function getUserLastActionHash(bytes32 userKeyHash) view returns (bytes32)',\n // Issue #13: Session key management\n 'function registerSession(tuple(bytes authenticatorData, string clientDataJSON, uint256 challengeIndex, uint256 typeIndex, uint256 r, uint256 s) auth, uint256 publicKeyX, uint256 publicKeyY, bytes32 sessionKeyHash, uint256 duration, uint256 maxValue, bool requireUV) external',\n 'function isSessionActive(bytes32 userKeyHash, bytes32 sessionKeyHash) view returns (bool active, uint256 expiry, uint256 maxValue, uint256 sessionIndex)',\n 'function revokeSession(tuple(bytes authenticatorData, string clientDataJSON, uint256 challengeIndex, uint256 typeIndex, uint256 r, uint256 s) auth, uint256 publicKeyX, uint256 publicKeyY, bytes32 sessionKeyHash, bool requireUV) external',\n 'function getUserSessions(bytes32 userKeyHash) view returns (tuple(bytes32 sessionKeyHash, uint256 expiry, uint256 maxValue, bool revoked)[])',\n 'function getUserSessionCount(bytes32 userKeyHash) view returns (uint256)',\n // Issue #22: Backup Passkey / Multi-Key Identity management\n 'function registerIdentity(tuple(bytes authenticatorData, string clientDataJSON, uint256 challengeIndex, uint256 typeIndex, uint256 r, uint256 s) auth, uint256 publicKeyX, uint256 publicKeyY) external',\n 'function addBackupKey(tuple(bytes authenticatorData, string clientDataJSON, uint256 challengeIndex, uint256 typeIndex, uint256 r, uint256 s) auth, uint256 publicKeyX, uint256 publicKeyY, uint256 newPublicKeyX, uint256 newPublicKeyY, uint256 nonce) external payable returns (uint64 sequence)',\n 'function removeKey(tuple(bytes authenticatorData, string clientDataJSON, uint256 challengeIndex, uint256 typeIndex, uint256 r, uint256 s) auth, uint256 publicKeyX, uint256 publicKeyY, bytes32 keyToRemove, uint256 nonce) external payable returns (uint64 sequence)',\n 'function getIdentityForKey(bytes32 keyHash) view returns (bytes32)',\n 'function getAuthorizedKeys(bytes32 identity) view returns (bytes32[])',\n 'function getAuthorizedKeyCount(bytes32 identity) view returns (uint256)',\n 'function isAuthorizedForIdentity(bytes32 identity, bytes32 keyHash) view returns (bool)',\n 'function isIdentityRoot(bytes32 keyHash) view returns (bool)',\n 'function getIdentityState(bytes32 keyHash) view returns (bytes32 identity, uint256 keyCount, uint256 maxKeys, bool isRoot)',\n \n // Issue #23: Social Recovery / Guardian Management\n 'function setupGuardians(tuple(bytes authenticatorData, string clientDataJSON, uint256 challengeIndex, uint256 typeIndex, uint256 r, uint256 s) auth, uint256 publicKeyX, uint256 publicKeyY, bytes32[] guardians, uint256 threshold) external payable returns (uint64 sequence)',\n 'function addGuardian(tuple(bytes authenticatorData, string clientDataJSON, uint256 challengeIndex, uint256 typeIndex, uint256 r, uint256 s) auth, uint256 publicKeyX, uint256 publicKeyY, bytes32 guardianKeyHash) external payable returns (uint64 sequence)',\n 'function removeGuardian(tuple(bytes authenticatorData, string clientDataJSON, uint256 challengeIndex, uint256 typeIndex, uint256 r, uint256 s) auth, uint256 publicKeyX, uint256 publicKeyY, bytes32 guardianKeyHash) external payable returns (uint64 sequence)',\n 'function initiateRecovery(tuple(bytes authenticatorData, string clientDataJSON, uint256 challengeIndex, uint256 typeIndex, uint256 r, uint256 s) auth, uint256 publicKeyX, uint256 publicKeyY, bytes32 identityToRecover, bytes32 newOwnerKeyHash) external payable returns (uint64 sequence)',\n 'function approveRecovery(tuple(bytes authenticatorData, string clientDataJSON, uint256 challengeIndex, uint256 typeIndex, uint256 r, uint256 s) auth, uint256 publicKeyX, uint256 publicKeyY, bytes32 identityToRecover) external payable returns (uint64 sequence)',\n 'function executeRecovery(bytes32 identityToRecover, uint256 newPublicKeyX, uint256 newPublicKeyY) external payable returns (uint64 sequence)',\n 'function cancelRecovery(tuple(bytes authenticatorData, string clientDataJSON, uint256 challengeIndex, uint256 typeIndex, uint256 r, uint256 s) auth, uint256 publicKeyX, uint256 publicKeyY) external payable returns (uint64 sequence)',\n 'function getGuardians(bytes32 identityKeyHash) view returns (bytes32[] guardians, uint256 threshold, bool isConfigured)',\n 'function getRecoveryStatus(bytes32 identityKeyHash) view returns (bool isActive, bytes32 newOwnerKeyHash, uint256 initiatedAt, uint256 approvalCount, uint256 threshold, uint256 canExecuteAt, uint256 expiresAt)',\n 'function hasGuardianApproved(bytes32 identityKeyHash, bytes32 guardianKeyHash) view returns (bool hasApproved)',\n];\n\n// ============================================================================\n// Factory Contract ABI (minimal)\n// ============================================================================\n\nconst FACTORY_ABI = [\n 'function createVault(bytes32 ownerKeyHash) returns (address vault)',\n 'function getVault(bytes32 ownerKeyHash) view returns (address)',\n 'function computeVaultAddress(bytes32 ownerKeyHash) view returns (address vault)',\n 'function vaultExists(bytes32 ownerKeyHash) view returns (bool)',\n 'function implementation() view returns (address)',\n];\n\n// ============================================================================\n// EVMClient Class\n// ============================================================================\n\n/**\n * EVM implementation of the ChainClient interface\n */\nexport class EVMClient implements ChainClient {\n private config: ChainConfig;\n private provider: ethers.JsonRpcProvider;\n private hubContract: ethers.Contract;\n private factoryContract: ethers.Contract | null = null;\n private cachedImplementation: string | null = null;\n\n constructor(config: EVMClientConfig) {\n this.config = {\n name: config.name ?? `EVM Chain ${config.chainId}`,\n chainId: config.chainId,\n wormholeChainId: config.wormholeChainId,\n rpcUrl: config.rpcUrl,\n explorerUrl: config.explorerUrl ?? '',\n isEvm: true,\n contracts: {\n hub: config.hubContractAddress,\n vaultFactory: config.vaultFactory,\n vaultImplementation: config.vaultImplementation,\n wormholeCoreBridge: config.wormholeCoreBridge,\n tokenBridge: config.tokenBridge,\n },\n };\n\n this.provider = new ethers.JsonRpcProvider(config.rpcUrl);\n this.hubContract = new ethers.Contract(\n config.hubContractAddress,\n HUB_ABI,\n this.provider\n );\n\n // Initialize factory contract if address is provided\n if (config.vaultFactory) {\n this.factoryContract = new ethers.Contract(\n config.vaultFactory,\n FACTORY_ABI,\n this.provider\n );\n }\n\n // Cache implementation address if provided\n if (config.vaultImplementation) {\n this.cachedImplementation = config.vaultImplementation;\n }\n }\n\n getConfig(): ChainConfig {\n return this.config;\n }\n\n async getNonce(userKeyHash: string): Promise<bigint> {\n const nonce = await this.hubContract.getNonce(userKeyHash);\n return BigInt(nonce.toString());\n }\n\n /**\n * Get user state from Hub (Issue #9/#10)\n * Returns comprehensive state including last action hash\n */\n async getUserState(userKeyHash: string): Promise<{\n keyHash: string;\n nonce: bigint;\n lastActionHash: string;\n }> {\n try {\n const result = await this.hubContract.getUserState(userKeyHash);\n return {\n keyHash: result[0],\n nonce: BigInt(result[1].toString()),\n lastActionHash: result[2],\n };\n } catch (error) {\n // Fallback for older Hub deployments without getUserState\n const nonce = await this.getNonce(userKeyHash);\n return {\n keyHash: userKeyHash,\n nonce,\n lastActionHash: ethers.ZeroHash,\n };\n }\n }\n\n /**\n * Get user's last action hash from Hub (Issue #9/#10)\n * Returns zero hash if user has no actions yet\n */\n async getUserLastActionHash(userKeyHash: string): Promise<string> {\n try {\n return await this.hubContract.getUserLastActionHash(userKeyHash);\n } catch (error) {\n // Fallback for older Hub deployments\n return ethers.ZeroHash;\n }\n }\n\n // ==========================================================================\n // Session Management Methods (Issue #13)\n // ==========================================================================\n\n /**\n * Register a new session key for temporary authentication\n * Enables native L1 speed for repeat transactions without biometric auth\n * \n * @param params Session registration parameters\n * @param signer Ethereum signer to pay gas\n * @returns Transaction receipt\n */\n async registerSession(\n params: import('../../types.js').RegisterSessionParams,\n signer: ethers.Signer\n ): Promise<ethers.TransactionReceipt> {\n const hubWithSigner = this.hubContract.connect(signer) as any;\n\n const authTuple = {\n authenticatorData: params.signature.authenticatorData,\n clientDataJSON: params.signature.clientDataJSON,\n challengeIndex: params.signature.challengeIndex,\n typeIndex: params.signature.typeIndex,\n r: params.signature.r,\n s: params.signature.s,\n };\n\n const tx = await hubWithSigner.registerSession(\n authTuple,\n params.publicKeyX,\n params.publicKeyY,\n params.sessionKeyHash,\n params.duration,\n params.maxValue,\n params.requireUV\n );\n\n return await tx.wait();\n }\n\n /**\n * Check if a session is currently active (queryable via Wormhole CCQ)\n * \n * @param userKeyHash Hash of the user's Passkey public key\n * @param sessionKeyHash Hash of the session key to check\n * @returns Session validation result\n */\n async isSessionActive(\n userKeyHash: string,\n sessionKeyHash: string\n ): Promise<import('../../types.js').SessionValidationResult> {\n const result = await this.hubContract.isSessionActive(userKeyHash, sessionKeyHash);\n \n return {\n active: result[0],\n expiry: Number(result[1]),\n maxValue: BigInt(result[2].toString()),\n sessionIndex: Number(result[3]),\n };\n }\n\n /**\n * Revoke a session key immediately\n * \n * @param params Session revocation parameters\n * @param signer Ethereum signer to pay gas\n * @returns Transaction receipt\n */\n async revokeSession(\n params: import('../../types.js').RevokeSessionParams,\n signer: ethers.Signer\n ): Promise<ethers.TransactionReceipt> {\n const hubWithSigner = this.hubContract.connect(signer) as any;\n\n const authTuple = {\n authenticatorData: params.signature.authenticatorData,\n clientDataJSON: params.signature.clientDataJSON,\n challengeIndex: params.signature.challengeIndex,\n typeIndex: params.signature.typeIndex,\n r: params.signature.r,\n s: params.signature.s,\n };\n\n const tx = await hubWithSigner.revokeSession(\n authTuple,\n params.publicKeyX,\n params.publicKeyY,\n params.sessionKeyHash,\n params.requireUV\n );\n\n return await tx.wait();\n }\n\n /**\n * Get all sessions for a user\n * \n * @param userKeyHash Hash of the user's Passkey public key\n * @returns Array of all sessions (active and expired/revoked)\n */\n async getUserSessions(userKeyHash: string): Promise<import('../../types.js').SessionKey[]> {\n const sessions = await this.hubContract.getUserSessions(userKeyHash);\n \n return sessions.map((s: any) => ({\n sessionKeyHash: s.sessionKeyHash,\n expiry: Number(s.expiry),\n maxValue: BigInt(s.maxValue.toString()),\n revoked: s.revoked,\n }));\n }\n\n /**\n * Get the number of sessions for a user\n * \n * @param userKeyHash Hash of the user's Passkey public key\n * @returns Number of sessions\n */\n async getUserSessionCount(userKeyHash: string): Promise<number> {\n const count = await this.hubContract.getUserSessionCount(userKeyHash);\n return Number(count);\n }\n\n async getMessageFee(): Promise<bigint> {\n const fee = await this.hubContract.getMessageFee();\n return BigInt(fee.toString());\n }\n\n async buildTransferPayload(params: TransferParams): Promise<string> {\n return encodeTransferAction(\n params.token,\n params.recipient,\n params.amount\n );\n }\n\n async buildExecutePayload(params: ExecuteParams): Promise<string> {\n return encodeExecuteAction(\n params.target,\n params.value,\n params.data\n );\n }\n\n async buildBridgePayload(params: BridgeParams): Promise<string> {\n return encodeBridgeAction(\n params.token,\n params.amount,\n params.destinationChain,\n params.recipient\n );\n }\n\n async dispatch(\n signature: WebAuthnSignature,\n publicKeyX: bigint,\n publicKeyY: bigint,\n targetChain: number,\n actionPayload: string,\n nonce: bigint,\n signer: ethers.Signer\n ): Promise<DispatchResult> {\n const hubWithSigner = this.hubContract.connect(signer) as any;\n\n const signatureTuple = {\n authenticatorData: signature.authenticatorData,\n clientDataJSON: signature.clientDataJSON,\n challengeIndex: signature.challengeIndex,\n typeIndex: signature.typeIndex,\n r: signature.r,\n s: signature.s,\n };\n\n const messageFee = await this.getMessageFee();\n\n const tx = await hubWithSigner.dispatch(\n signatureTuple,\n publicKeyX,\n publicKeyY,\n targetChain,\n actionPayload,\n nonce,\n { value: messageFee }\n );\n\n const receipt = await tx.wait();\n\n // Extract sequence from event logs\n const dispatchEvent = receipt.logs.find((log: any) => {\n try {\n const parsed = hubWithSigner.interface.parseLog(log);\n return parsed?.name === 'ActionDispatched';\n } catch {\n return false;\n }\n });\n\n let sequence = 0n;\n if (dispatchEvent) {\n const parsed = hubWithSigner.interface.parseLog(dispatchEvent);\n sequence = BigInt(parsed?.args?.sequence?.toString() ?? '0');\n }\n\n const keyHash = ethers.keccak256(\n ethers.AbiCoder.defaultAbiCoder().encode(\n ['uint256', 'uint256'],\n [publicKeyX, publicKeyY]\n )\n );\n\n return {\n transactionHash: receipt.hash,\n sequence,\n userKeyHash: keyHash,\n targetChain,\n blockNumber: receipt.blockNumber,\n };\n }\n\n /**\n * Dispatch an action to the Hub via relayer (gasless)\n * The relayer pays for gas and submits the transaction on behalf of the user\n */\n async dispatchGasless(\n signature: WebAuthnSignature,\n publicKeyX: bigint,\n publicKeyY: bigint,\n targetChain: number,\n actionPayload: string,\n nonce: bigint,\n relayerUrl: string\n ): Promise<DispatchResult> {\n // Compute message hash that was signed\n // This should match how the WebAuthn signature was generated\n const keyHash = ethers.keccak256(\n ethers.AbiCoder.defaultAbiCoder().encode(\n ['uint256', 'uint256'],\n [publicKeyX, publicKeyY]\n )\n );\n\n // Build the message that was signed\n const message = ethers.keccak256(\n ethers.AbiCoder.defaultAbiCoder().encode(\n ['bytes32', 'uint16', 'bytes', 'uint256'],\n [keyHash, targetChain, actionPayload, nonce]\n )\n );\n\n // Prepare request for relayer\n const request = {\n messageHash: message,\n r: '0x' + signature.r.toString(16).padStart(64, '0'),\n s: '0x' + signature.s.toString(16).padStart(64, '0'),\n publicKeyX: '0x' + publicKeyX.toString(16).padStart(64, '0'),\n publicKeyY: '0x' + publicKeyY.toString(16).padStart(64, '0'),\n targetChain,\n actionPayload,\n nonce: Number(nonce),\n };\n\n // Submit to relayer\n const response = await fetch(`${relayerUrl}/api/v1/submit`, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n },\n body: JSON.stringify(request),\n });\n\n if (!response.ok) {\n const error = await response.json().catch(() => ({ error: response.statusText }));\n throw new Error(`Relayer submission failed: ${error.error || response.statusText}`);\n }\n\n const result = await response.json();\n\n if (!result.success) {\n throw new Error(`Relayer submission failed: ${result.error}`);\n }\n\n return {\n transactionHash: result.txHash,\n sequence: BigInt(result.sequence || '0'),\n userKeyHash: keyHash,\n targetChain,\n };\n }\n\n async getVaultAddress(userKeyHash: string): Promise<string | null> {\n try {\n // Try factory first if available\n if (this.factoryContract) {\n const address = await this.factoryContract.getVault(userKeyHash);\n if (address !== ethers.ZeroAddress) {\n return address;\n }\n }\n\n // Fallback to hub contract\n const address = await this.hubContract.getVaultAddress(userKeyHash);\n if (address === ethers.ZeroAddress) {\n return null;\n }\n return address;\n } catch (error) {\n console.error('Error getting vault address:', error);\n return null;\n }\n }\n\n /**\n * Compute vault address deterministically without querying the chain\n * Uses CREATE2 with EIP-1167 minimal proxy pattern\n */\n computeVaultAddress(userKeyHash: string): string {\n const factoryAddress = this.getFactoryAddress();\n const implementationAddress = this.getImplementationAddress();\n\n if (!factoryAddress || !implementationAddress) {\n throw new Error('Factory and implementation addresses required for address computation');\n }\n\n // Compute salt: keccak256(abi.encodePacked(factory, keyHash))\n const salt = ethers.keccak256(\n ethers.solidityPacked(\n ['address', 'bytes32'],\n [factoryAddress, userKeyHash]\n )\n );\n\n // Build EIP-1167 initcode\n const initCode = this.buildProxyInitCode(implementationAddress);\n const initCodeHash = ethers.keccak256(initCode);\n\n // CREATE2 address computation:\n // address = keccak256(0xff ++ factory ++ salt ++ initCodeHash)[12:]\n const create2Data = ethers.solidityPacked(\n ['bytes1', 'address', 'bytes32', 'bytes32'],\n ['0xff', factoryAddress, salt, initCodeHash]\n );\n\n const hash = ethers.keccak256(create2Data);\n // Take last 20 bytes as address\n return ethers.getAddress('0x' + hash.slice(26));\n }\n\n /**\n * Build EIP-1167 minimal proxy initcode\n */\n private buildProxyInitCode(implementationAddress: string): string {\n const impl = implementationAddress.toLowerCase().replace('0x', '');\n return PROXY_BYTECODE_PREFIX + impl + PROXY_BYTECODE_SUFFIX;\n }\n\n async vaultExists(userKeyHash: string): Promise<boolean> {\n try {\n // Try factory first if available\n if (this.factoryContract) {\n return await this.factoryContract.vaultExists(userKeyHash);\n }\n // Hub chains may not have vaultExists, silently return false\n if (this.hubContract.vaultExists) {\n try {\n return await this.hubContract.vaultExists(userKeyHash);\n } catch {\n // Hub contract doesn't have vaultExists - this is expected on hub-only chains\n return false;\n }\n }\n return false;\n } catch {\n // Silently return false - vault existence check is non-critical\n return false;\n }\n }\n\n async createVault(userKeyHash: string, signer: ethers.Signer): Promise<VaultCreationResult> {\n // Check if vault already exists\n const exists = await this.vaultExists(userKeyHash);\n if (exists) {\n const address = await this.getVaultAddress(userKeyHash);\n if (address) {\n return {\n address,\n transactionHash: '',\n blockNumber: 0,\n gasUsed: 0n,\n alreadyExisted: true,\n };\n }\n }\n\n // Create vault using factory or hub\n let tx: ethers.TransactionResponse;\n\n if (this.factoryContract) {\n const factoryWithSigner = this.factoryContract.connect(signer) as ethers.Contract;\n tx = await factoryWithSigner.createVault(userKeyHash);\n } else {\n const hubWithSigner = this.hubContract.connect(signer) as ethers.Contract;\n tx = await hubWithSigner.createVault(userKeyHash);\n }\n\n const receipt = await tx.wait();\n if (!receipt) {\n throw new Error('Transaction failed - no receipt');\n }\n\n const vaultAddress = await this.getVaultAddress(userKeyHash);\n if (!vaultAddress) {\n throw new Error('Failed to create vault - address not found after creation');\n }\n\n return {\n address: vaultAddress,\n transactionHash: receipt.hash,\n blockNumber: receipt.blockNumber,\n gasUsed: receipt.gasUsed,\n alreadyExisted: false,\n };\n }\n\n /**\n * Create a vault with a sponsor wallet paying for gas\n * \n * @param userKeyHash - The user's passkey hash\n * @param sponsorPrivateKey - Private key of the wallet that will pay gas\n * @param rpcUrl - Optional RPC URL to use (defaults to client's RPC)\n * @returns VaultCreationResult with address and transaction details\n */\n async createVaultSponsored(\n userKeyHash: string,\n sponsorPrivateKey: string,\n rpcUrl?: string\n ): Promise<VaultCreationResult> {\n // Check if vault already exists\n const exists = await this.vaultExists(userKeyHash);\n if (exists) {\n const address = await this.getVaultAddress(userKeyHash);\n if (address) {\n return {\n address,\n transactionHash: '',\n blockNumber: 0,\n gasUsed: 0n,\n alreadyExisted: true,\n };\n }\n }\n\n // Create sponsor signer\n const provider = rpcUrl\n ? new ethers.JsonRpcProvider(rpcUrl)\n : this.provider;\n const sponsorWallet = new ethers.Wallet(sponsorPrivateKey, provider);\n\n // Check sponsor balance\n const sponsorBalance = await provider.getBalance(sponsorWallet.address);\n const estimatedGas = await this.estimateVaultCreationGas(userKeyHash);\n const feeData = await provider.getFeeData();\n const estimatedCost = estimatedGas * (feeData.gasPrice ?? 1000000000n);\n\n if (sponsorBalance < estimatedCost) {\n throw new Error(\n `Sponsor wallet has insufficient funds. ` +\n `Balance: ${ethers.formatEther(sponsorBalance)} ETH, ` +\n `Estimated cost: ${ethers.formatEther(estimatedCost)} ETH`\n );\n }\n\n // Create vault using factory or hub with sponsor wallet\n let tx: ethers.TransactionResponse;\n\n if (this.factoryContract) {\n const factoryWithSponsor = this.factoryContract.connect(sponsorWallet) as ethers.Contract;\n tx = await factoryWithSponsor.createVault(userKeyHash);\n } else {\n const hubWithSponsor = this.hubContract.connect(sponsorWallet) as ethers.Contract;\n tx = await hubWithSponsor.createVault(userKeyHash);\n }\n\n const receipt = await tx.wait();\n if (!receipt) {\n throw new Error('Transaction failed - no receipt');\n }\n\n const vaultAddress = await this.getVaultAddress(userKeyHash);\n if (!vaultAddress) {\n throw new Error('Failed to create vault - address not found after creation');\n }\n\n return {\n address: vaultAddress,\n transactionHash: receipt.hash,\n blockNumber: receipt.blockNumber,\n gasUsed: receipt.gasUsed,\n alreadyExisted: false,\n sponsoredBy: sponsorWallet.address,\n };\n }\n\n async estimateVaultCreationGas(userKeyHash: string): Promise<bigint> {\n try {\n if (this.factoryContract) {\n return await this.factoryContract.createVault.estimateGas(userKeyHash);\n }\n return await this.hubContract.createVault.estimateGas(userKeyHash);\n } catch (error) {\n // Return a default estimate if estimation fails (vault might already exist)\n console.warn('Gas estimation failed, returning default:', error);\n return 150000n; // Default estimate for vault creation\n }\n }\n\n getFactoryAddress(): string | undefined {\n return this.config.contracts.vaultFactory;\n }\n\n getImplementationAddress(): string | undefined {\n return this.config.contracts.vaultImplementation ?? this.cachedImplementation ?? undefined;\n }\n\n /**\n * Fetch implementation address from factory contract\n */\n async fetchImplementationAddress(): Promise<string | null> {\n if (this.cachedImplementation) {\n return this.cachedImplementation;\n }\n\n if (!this.factoryContract) {\n return null;\n }\n\n try {\n this.cachedImplementation = await this.factoryContract.implementation();\n return this.cachedImplementation;\n } catch (error) {\n console.error('Error fetching implementation address:', error);\n return null;\n }\n }\n\n /**\n * Get the provider instance\n */\n getProvider(): ethers.JsonRpcProvider {\n return this.provider;\n }\n\n // ========================================================================\n // Balance Methods (Phase 2)\n // ========================================================================\n\n /**\n * Get native token balance for an address\n */\n async getNativeBalance(address: string): Promise<bigint> {\n return await this.provider.getBalance(address);\n }\n\n /**\n * Get ERC20 token balance for an address\n */\n async getTokenBalance(tokenAddress: string, ownerAddress: string): Promise<bigint> {\n const contract = new ethers.Contract(tokenAddress, ERC20_ABI, this.provider);\n return await contract.balanceOf(ownerAddress);\n }\n\n /**\n * Get token allowance\n */\n async getTokenAllowance(\n tokenAddress: string,\n ownerAddress: string,\n spenderAddress: string\n ): Promise<bigint> {\n const contract = new ethers.Contract(tokenAddress, ERC20_ABI, this.provider);\n return await contract.allowance(ownerAddress, spenderAddress);\n }\n\n /**\n * Estimate gas for a dispatch transaction\n */\n async estimateDispatchGas(\n signature: WebAuthnSignature,\n publicKeyX: bigint,\n publicKeyY: bigint,\n targetChain: number,\n actionPayload: string,\n nonce: bigint\n ): Promise<bigint> {\n const signatureTuple = {\n authenticatorData: signature.authenticatorData,\n clientDataJSON: signature.clientDataJSON,\n challengeIndex: signature.challengeIndex,\n typeIndex: signature.typeIndex,\n r: signature.r,\n s: signature.s,\n };\n\n const messageFee = await this.getMessageFee();\n\n try {\n const gasEstimate = await this.hubContract.dispatch.estimateGas(\n signatureTuple,\n publicKeyX,\n publicKeyY,\n targetChain,\n actionPayload,\n nonce,\n { value: messageFee }\n );\n return gasEstimate;\n } catch (error) {\n console.warn('Gas estimation failed, using default:', error);\n return 500000n; // Default estimate for dispatch\n }\n }\n\n /**\n * Get current gas price\n */\n async getGasPrice(): Promise<bigint> {\n const feeData = await this.provider.getFeeData();\n return feeData.gasPrice ?? feeData.maxFeePerGas ?? 0n;\n }\n\n /**\n * Get current block number\n */\n async getBlockNumber(): Promise<number> {\n return await this.provider.getBlockNumber();\n }\n\n /**\n * Get transaction receipt\n */\n async getTransactionReceipt(hash: string): Promise<ethers.TransactionReceipt | null> {\n return await this.provider.getTransactionReceipt(hash);\n }\n\n /**\n * Wait for transaction confirmation\n */\n async waitForTransaction(\n hash: string,\n confirmations: number = 1\n ): Promise<ethers.TransactionReceipt | null> {\n return await this.provider.waitForTransaction(hash, confirmations);\n }\n\n // ==========================================================================\n // Backup Passkey / Multi-Key Identity Methods (Issue #22)\n // ==========================================================================\n\n /**\n * Get the identity for a given key hash\n * Returns zero hash if key is not registered to any identity\n * \n * @param keyHash Hash of the passkey to look up\n * @returns Identity (first passkey's keyHash) or zero hash\n */\n async getIdentityForKey(keyHash: string): Promise<string> {\n try {\n return await this.hubContract.getIdentityForKey(keyHash);\n } catch (error) {\n return ethers.ZeroHash;\n }\n }\n\n /**\n * Get all authorized keys for an identity\n * \n * @param identity The identity key hash (first passkey's keyHash)\n * @returns Array of authorized key hashes\n */\n async getAuthorizedKeys(identity: string): Promise<string[]> {\n try {\n return await this.hubContract.getAuthorizedKeys(identity);\n } catch (error) {\n return [];\n }\n }\n\n /**\n * Get count of authorized keys for an identity\n * \n * @param identity The identity key hash\n * @returns Number of authorized keys\n */\n async getAuthorizedKeyCount(identity: string): Promise<number> {\n try {\n const count = await this.hubContract.getAuthorizedKeyCount(identity);\n return Number(count);\n } catch (error) {\n return 0;\n }\n }\n\n /**\n * Check if a key is authorized for an identity\n * \n * @param identity The identity key hash\n * @param keyHash The key hash to check\n * @returns Whether the key is authorized\n */\n async isAuthorizedForIdentity(identity: string, keyHash: string): Promise<boolean> {\n try {\n return await this.hubContract.isAuthorizedForIdentity(identity, keyHash);\n } catch (error) {\n return false;\n }\n }\n\n /**\n * Check if a key is the root identity key\n * \n * @param keyHash The key hash to check\n * @returns Whether the key is a root identity\n */\n async isIdentityRootKey(keyHash: string): Promise<boolean> {\n try {\n return await this.hubContract.isIdentityRoot(keyHash);\n } catch (error) {\n return false;\n }\n }\n\n /**\n * Get comprehensive identity state for a key\n * \n * @param keyHash Hash of any key in the identity\n * @returns Identity state including count, max, and root status\n */\n async getIdentityState(keyHash: string): Promise<import('../../types.js').IdentityState> {\n try {\n const result = await this.hubContract.getIdentityState(keyHash);\n return {\n identity: result[0],\n keyCount: Number(result[1]),\n maxKeys: Number(result[2]),\n isRoot: result[3],\n };\n } catch (error) {\n // Fallback for keys not registered\n return {\n identity: ethers.ZeroHash,\n keyCount: 0,\n maxKeys: 5,\n isRoot: false,\n };\n }\n }\n\n /**\n * Register a new identity with the first passkey\n * This makes the passkey the root identity key\n * \n * @param signature WebAuthn signature\n * @param publicKeyX Passkey public key X coordinate\n * @param publicKeyY Passkey public key Y coordinate\n * @param signer Ethereum signer to pay gas\n * @returns Transaction receipt and identity hash\n */\n async registerIdentity(\n signature: WebAuthnSignature,\n publicKeyX: bigint,\n publicKeyY: bigint,\n signer: ethers.Signer\n ): Promise<{ receipt: ethers.TransactionReceipt; identity: string }> {\n const hubWithSigner = this.hubContract.connect(signer) as any;\n\n const authTuple = {\n authenticatorData: signature.authenticatorData,\n clientDataJSON: signature.clientDataJSON,\n challengeIndex: signature.challengeIndex,\n typeIndex: signature.typeIndex,\n r: signature.r,\n s: signature.s,\n };\n\n const tx = await hubWithSigner.registerIdentity(\n authTuple,\n publicKeyX,\n publicKeyY\n );\n\n const receipt = await tx.wait();\n \n // Compute identity (keyHash of the registered key)\n const keyHash = ethers.keccak256(\n ethers.solidityPacked(['uint256', 'uint256'], [publicKeyX, publicKeyY])\n );\n\n return { receipt, identity: keyHash };\n }\n\n /**\n * Add a backup passkey to an existing identity\n * Requires WebAuthn signature from an authorized key\n * \n * @param signature WebAuthn signature from existing authorized key\n * @param publicKeyX Existing key's X coordinate\n * @param publicKeyY Existing key's Y coordinate\n * @param newPublicKeyX New backup key's X coordinate\n * @param newPublicKeyY New backup key's Y coordinate\n * @param nonce Current nonce for the signing key\n * @param signer Ethereum signer to pay gas\n * @returns Transaction receipt and sequence number\n */\n async addBackupKey(\n signature: WebAuthnSignature,\n publicKeyX: bigint,\n publicKeyY: bigint,\n newPublicKeyX: bigint,\n newPublicKeyY: bigint,\n nonce: bigint,\n signer: ethers.Signer\n ): Promise<{ receipt: ethers.TransactionReceipt; sequence: bigint }> {\n const hubWithSigner = this.hubContract.connect(signer) as any;\n\n const authTuple = {\n authenticatorData: signature.authenticatorData,\n clientDataJSON: signature.clientDataJSON,\n challengeIndex: signature.challengeIndex,\n typeIndex: signature.typeIndex,\n r: signature.r,\n s: signature.s,\n };\n\n const messageFee = await this.getMessageFee();\n\n const tx = await hubWithSigner.addBackupKey(\n authTuple,\n publicKeyX,\n publicKeyY,\n newPublicKeyX,\n newPublicKeyY,\n nonce,\n { value: messageFee }\n );\n\n const receipt = await tx.wait();\n\n // Extract sequence from Dispatch event\n let sequence = 0n;\n for (const log of receipt.logs) {\n try {\n const parsed = this.hubContract.interface.parseLog({\n topics: log.topics as string[],\n data: log.data,\n });\n if (parsed?.name === 'Dispatched') {\n sequence = BigInt(parsed.args[3]); // sequence is 4th arg\n break;\n }\n } catch {\n // Not a Hub event, skip\n }\n }\n\n return { receipt, sequence };\n }\n\n /**\n * Remove a passkey from an identity\n * Cannot remove the last remaining key\n * \n * @param signature WebAuthn signature from an authorized key\n * @param publicKeyX Signing key's X coordinate\n * @param publicKeyY Signing key's Y coordinate\n * @param keyToRemove Hash of the key to remove\n * @param nonce Current nonce for the signing key\n * @param signer Ethereum signer to pay gas\n * @returns Transaction receipt and sequence number\n */\n async removeKey(\n signature: WebAuthnSignature,\n publicKeyX: bigint,\n publicKeyY: bigint,\n keyToRemove: string,\n nonce: bigint,\n signer: ethers.Signer\n ): Promise<{ receipt: ethers.TransactionReceipt; sequence: bigint }> {\n const hubWithSigner = this.hubContract.connect(signer) as any;\n\n const authTuple = {\n authenticatorData: signature.authenticatorData,\n clientDataJSON: signature.clientDataJSON,\n challengeIndex: signature.challengeIndex,\n typeIndex: signature.typeIndex,\n r: signature.r,\n s: signature.s,\n };\n\n const messageFee = await this.getMessageFee();\n\n const tx = await hubWithSigner.removeKey(\n authTuple,\n publicKeyX,\n publicKeyY,\n keyToRemove,\n nonce,\n { value: messageFee }\n );\n\n const receipt = await tx.wait();\n\n // Extract sequence from Dispatch event\n let sequence = 0n;\n for (const log of receipt.logs) {\n try {\n const parsed = this.hubContract.interface.parseLog({\n topics: log.topics as string[],\n data: log.data,\n });\n if (parsed?.name === 'Dispatched') {\n sequence = BigInt(parsed.args[3]);\n break;\n }\n } catch {\n // Not a Hub event, skip\n }\n }\n\n return { receipt, sequence };\n }\n\n // =========================================================================\n // SOCIAL RECOVERY METHODS (Issue #23)\n // =========================================================================\n\n /**\n * Setup guardians for an identity\n * @param signature WebAuthn signature from owner\n * @param publicKeyX Owner's public key X coordinate\n * @param publicKeyY Owner's public key Y coordinate\n * @param guardians Array of guardian key hashes\n * @param threshold Required approvals for recovery\n * @param signer Ethers signer for transaction\n */\n async setupGuardians(\n signature: WebAuthnSignature,\n publicKeyX: bigint,\n publicKeyY: bigint,\n guardians: string[],\n threshold: bigint,\n signer: ethers.Signer\n ): Promise<{ receipt: ethers.TransactionReceipt; sequence: bigint }> {\n const hubWithSigner = this.hubContract.connect(signer) as any;\n\n const authTuple = {\n authenticatorData: signature.authenticatorData,\n clientDataJSON: signature.clientDataJSON,\n challengeIndex: signature.challengeIndex,\n typeIndex: signature.typeIndex,\n r: signature.r,\n s: signature.s,\n };\n\n const messageFee = await this.getMessageFee();\n\n const tx = await hubWithSigner.setupGuardians(\n authTuple,\n publicKeyX,\n publicKeyY,\n guardians,\n threshold,\n { value: messageFee }\n );\n\n const receipt = await tx.wait();\n const sequence = this._extractSequenceFromReceipt(receipt);\n\n return { receipt, sequence };\n }\n\n /**\n * Add a guardian to an identity\n */\n async addGuardian(\n signature: WebAuthnSignature,\n publicKeyX: bigint,\n publicKeyY: bigint,\n guardianKeyHash: string,\n signer: ethers.Signer\n ): Promise<{ receipt: ethers.TransactionReceipt; sequence: bigint }> {\n const hubWithSigner = this.hubContract.connect(signer) as any;\n\n const authTuple = {\n authenticatorData: signature.authenticatorData,\n clientDataJSON: signature.clientDataJSON,\n challengeIndex: signature.challengeIndex,\n typeIndex: signature.typeIndex,\n r: signature.r,\n s: signature.s,\n };\n\n const messageFee = await this.getMessageFee();\n\n const tx = await hubWithSigner.addGuardian(\n authTuple,\n publicKeyX,\n publicKeyY,\n guardianKeyHash,\n { value: messageFee }\n );\n\n const receipt = await tx.wait();\n const sequence = this._extractSequenceFromReceipt(receipt);\n\n return { receipt, sequence };\n }\n\n /**\n * Remove a guardian from an identity\n */\n async removeGuardian(\n signature: WebAuthnSignature,\n publicKeyX: bigint,\n publicKeyY: bigint,\n guardianKeyHash: string,\n signer: ethers.Signer\n ): Promise<{ receipt: ethers.TransactionReceipt; sequence: bigint }> {\n const hubWithSigner = this.hubContract.connect(signer) as any;\n\n const authTuple = {\n authenticatorData: signature.authenticatorData,\n clientDataJSON: signature.clientDataJSON,\n challengeIndex: signature.challengeIndex,\n typeIndex: signature.typeIndex,\n r: signature.r,\n s: signature.s,\n };\n\n const messageFee = await this.getMessageFee();\n\n const tx = await hubWithSigner.removeGuardian(\n authTuple,\n publicKeyX,\n publicKeyY,\n guardianKeyHash,\n { value: messageFee }\n );\n\n const receipt = await tx.wait();\n const sequence = this._extractSequenceFromReceipt(receipt);\n\n return { receipt, sequence };\n }\n\n /**\n * Initiate recovery as a guardian\n */\n async initiateRecovery(\n signature: WebAuthnSignature,\n publicKeyX: bigint,\n publicKeyY: bigint,\n identityToRecover: string,\n newOwnerKeyHash: string,\n signer: ethers.Signer\n ): Promise<{ receipt: ethers.TransactionReceipt; sequence: bigint }> {\n const hubWithSigner = this.hubContract.connect(signer) as any;\n\n const authTuple = {\n authenticatorData: signature.authenticatorData,\n clientDataJSON: signature.clientDataJSON,\n challengeIndex: signature.challengeIndex,\n typeIndex: signature.typeIndex,\n r: signature.r,\n s: signature.s,\n };\n\n const messageFee = await this.getMessageFee();\n\n const tx = await hubWithSigner.initiateRecovery(\n authTuple,\n publicKeyX,\n publicKeyY,\n identityToRecover,\n newOwnerKeyHash,\n { value: messageFee }\n );\n\n const receipt = await tx.wait();\n const sequence = this._extractSequenceFromReceipt(receipt);\n\n return { receipt, sequence };\n }\n\n /**\n * Approve recovery as a guardian\n */\n async approveRecovery(\n signature: WebAuthnSignature,\n publicKeyX: bigint,\n publicKeyY: bigint,\n identityToRecover: string,\n signer: ethers.Signer\n ): Promise<{ receipt: ethers.TransactionReceipt; sequence: bigint }> {\n const hubWithSigner = this.hubContract.connect(signer) as any;\n\n const authTuple = {\n authenticatorData: signature.authenticatorData,\n clientDataJSON: signature.clientDataJSON,\n challengeIndex: signature.challengeIndex,\n typeIndex: signature.typeIndex,\n r: signature.r,\n s: signature.s,\n };\n\n const messageFee = await this.getMessageFee();\n\n const tx = await hubWithSigner.approveRecovery(\n authTuple,\n publicKeyX,\n publicKeyY,\n identityToRecover,\n { value: messageFee }\n );\n\n const receipt = await tx.wait();\n const sequence = this._extractSequenceFromReceipt(receipt);\n\n return { receipt, sequence };\n }\n\n /**\n * Execute recovery after timelock (anyone can call)\n */\n async executeRecovery(\n identityToRecover: string,\n newPublicKeyX: bigint,\n newPublicKeyY: bigint,\n signer: ethers.Signer\n ): Promise<{ receipt: ethers.TransactionReceipt; sequence: bigint }> {\n const hubWithSigner = this.hubContract.connect(signer) as any;\n\n const messageFee = await this.getMessageFee();\n\n const tx = await hubWithSigner.executeRecovery(\n identityToRecover,\n newPublicKeyX,\n newPublicKeyY,\n { value: messageFee }\n );\n\n const receipt = await tx.wait();\n const sequence = this._extractSequenceFromReceipt(receipt);\n\n return { receipt, sequence };\n }\n\n /**\n * Cancel recovery as owner\n */\n async cancelRecovery(\n signature: WebAuthnSignature,\n publicKeyX: bigint,\n publicKeyY: bigint,\n signer: ethers.Signer\n ): Promise<{ receipt: ethers.TransactionReceipt; sequence: bigint }> {\n const hubWithSigner = this.hubContract.connect(signer) as any;\n\n const authTuple = {\n authenticatorData: signature.authenticatorData,\n clientDataJSON: signature.clientDataJSON,\n challengeIndex: signature.challengeIndex,\n typeIndex: signature.typeIndex,\n r: signature.r,\n s: signature.s,\n };\n\n const messageFee = await this.getMessageFee();\n\n const tx = await hubWithSigner.cancelRecovery(\n authTuple,\n publicKeyX,\n publicKeyY,\n { value: messageFee }\n );\n\n const receipt = await tx.wait();\n const sequence = this._extractSequenceFromReceipt(receipt);\n\n return { receipt, sequence };\n }\n\n /**\n * Get guardians for an identity\n */\n async getGuardians(identityKeyHash: string): Promise<{\n guardians: string[];\n threshold: bigint;\n isConfigured: boolean;\n }> {\n const result = await this.hubContract.getGuardians(identityKeyHash);\n return {\n guardians: result.guardians,\n threshold: result.threshold,\n isConfigured: result.isConfigured,\n };\n }\n\n /**\n * Get recovery status for an identity\n */\n async getRecoveryStatus(identityKeyHash: string): Promise<{\n isActive: boolean;\n newOwnerKeyHash: string;\n initiatedAt: bigint;\n approvalCount: bigint;\n threshold: bigint;\n canExecuteAt: bigint;\n expiresAt: bigint;\n }> {\n const result = await this.hubContract.getRecoveryStatus(identityKeyHash);\n return {\n isActive: result.isActive,\n newOwnerKeyHash: result.newOwnerKeyHash,\n initiatedAt: result.initiatedAt,\n approvalCount: result.approvalCount,\n threshold: result.threshold,\n canExecuteAt: result.canExecuteAt,\n expiresAt: result.expiresAt,\n };\n }\n\n /**\n * Check if a guardian has approved recovery\n */\n async hasGuardianApproved(\n identityKeyHash: string,\n guardianKeyHash: string\n ): Promise<boolean> {\n return this.hubContract.hasGuardianApproved(identityKeyHash, guardianKeyHash);\n }\n\n /**\n * Helper to extract sequence from transaction receipt\n */\n private _extractSequenceFromReceipt(receipt: ethers.TransactionReceipt): bigint {\n for (const log of receipt.logs) {\n try {\n const parsed = this.hubContract.interface.parseLog({\n topics: log.topics as string[],\n data: log.data,\n });\n if (parsed?.name === 'Dispatch') {\n return BigInt(parsed.args.sequence);\n }\n } catch {\n // Not a Hub event, skip\n }\n }\n return 0n;\n }\n}\n","/**\n * Veridex Protocol SDK - Chain Presets\n * \n * Pre-configured chain settings for easy SDK initialization.\n * Developers only need to specify chain name and network type.\n * \n * @example\n * ```typescript\n * import { createSDK } from '@veridex/sdk';\n * \n * // Simple initialization - testnet by default\n * const sdk = await createSDK('base');\n * \n * // Or specify mainnet\n * const mainnetSdk = await createSDK('base', { network: 'mainnet' });\n * ```\n */\n\nimport type { ChainConfig } from './types.js';\n\n// ============================================================================\n// Supported Chain Names\n// ============================================================================\n\n/**\n * All supported chain names for easy reference\n */\nexport const CHAIN_NAMES = {\n // EVM L2s (Hub-capable)\n BASE: 'base',\n OPTIMISM: 'optimism',\n ARBITRUM: 'arbitrum',\n SCROLL: 'scroll',\n BLAST: 'blast',\n MANTLE: 'mantle',\n \n // EVM L1s\n ETHEREUM: 'ethereum',\n POLYGON: 'polygon',\n BSC: 'bsc',\n AVALANCHE: 'avalanche',\n FANTOM: 'fantom',\n CELO: 'celo',\n MOONBEAM: 'moonbeam',\n \n // Non-EVM\n SOLANA: 'solana',\n APTOS: 'aptos',\n SUI: 'sui',\n STARKNET: 'starknet',\n NEAR: 'near',\n SEI: 'sei',\n} as const;\n\nexport type ChainName = typeof CHAIN_NAMES[keyof typeof CHAIN_NAMES];\nexport type NetworkType = 'mainnet' | 'testnet';\n\n// ============================================================================\n// Chain Preset Interface\n// ============================================================================\n\nexport interface ChainPreset {\n /** Human-readable chain name */\n displayName: string;\n /** Chain type for client selection */\n type: 'evm' | 'solana' | 'aptos' | 'sui' | 'starknet' | 'near' | 'cosmos';\n /** Whether this chain can be a hub */\n canBeHub: boolean;\n /** Testnet configuration */\n testnet: ChainConfig;\n /** Mainnet configuration */\n mainnet: ChainConfig;\n}\n\n// ============================================================================\n// EVM Chain Presets\n// ============================================================================\n\nexport const CHAIN_PRESETS: Record<ChainName, ChainPreset> = {\n // ────────────────────────────────────────────────────────────────────────\n // BASE - Primary Hub Chain\n // ────────────────────────────────────────────────────────────────────────\n base: {\n displayName: 'Base',\n type: 'evm',\n canBeHub: true,\n testnet: {\n name: 'Base Sepolia',\n chainId: 84532,\n wormholeChainId: 10004,\n rpcUrl: 'https://sepolia.base.org',\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 mainnet: {\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 // TODO: Deploy mainnet contracts\n wormholeCoreBridge: '0xbebdb6C8ddC678FfA9f8748f85C815C556Dd8ac6',\n tokenBridge: '0x8d2de8d2f73F1F4cAB472AC9A881C9b123C79627',\n },\n },\n },\n\n // ────────────────────────────────────────────────────────────────────────\n // OPTIMISM - Secondary Hub / Spoke\n // ────────────────────────────────────────────────────────────────────────\n optimism: {\n displayName: 'Optimism',\n type: 'evm',\n canBeHub: true,\n testnet: {\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 mainnet: {\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 },\n\n // ────────────────────────────────────────────────────────────────────────\n // ARBITRUM\n // ────────────────────────────────────────────────────────────────────────\n arbitrum: {\n displayName: 'Arbitrum',\n type: 'evm',\n canBeHub: true,\n testnet: {\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 mainnet: {\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 },\n\n // ────────────────────────────────────────────────────────────────────────\n // ETHEREUM\n // ────────────────────────────────────────────────────────────────────────\n ethereum: {\n displayName: 'Ethereum',\n type: 'evm',\n canBeHub: false,\n testnet: {\n name: 'Sepolia',\n chainId: 11155111,\n wormholeChainId: 10002,\n rpcUrl: 'https://rpc.sepolia.org',\n explorerUrl: 'https://sepolia.etherscan.io',\n isEvm: true,\n contracts: {\n wormholeCoreBridge: '0x4a8bc80Ed5a4067f1CCf107057b8270E0cC11A78',\n tokenBridge: '0xDB5492265f6038831E89f495670FF909aDe94bd9',\n },\n },\n mainnet: {\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 },\n\n // ────────────────────────────────────────────────────────────────────────\n // POLYGON\n // ────────────────────────────────────────────────────────────────────────\n polygon: {\n displayName: 'Polygon',\n type: 'evm',\n canBeHub: false,\n testnet: {\n name: 'Polygon Amoy',\n chainId: 80002,\n wormholeChainId: 10007,\n rpcUrl: 'https://rpc-amoy.polygon.technology',\n explorerUrl: 'https://amoy.polygonscan.com',\n isEvm: true,\n contracts: {\n wormholeCoreBridge: '0x0CBE91CF822c73C2315FB05100C2F714765d5c20',\n tokenBridge: '0x0290FB167208Af455bB137780163b7B7a9a10C16',\n },\n },\n mainnet: {\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 },\n\n // ────────────────────────────────────────────────────────────────────────\n // BSC\n // ────────────────────────────────────────────────────────────────────────\n bsc: {\n displayName: 'BNB Chain',\n type: 'evm',\n canBeHub: false,\n testnet: {\n name: 'BSC Testnet',\n chainId: 97,\n wormholeChainId: 4,\n rpcUrl: 'https://data-seed-prebsc-1-s1.binance.org:8545',\n explorerUrl: 'https://testnet.bscscan.com',\n isEvm: true,\n contracts: {\n wormholeCoreBridge: '0x68605AD7b15c732a30b1BbC62BE8F2A509D74b4D',\n tokenBridge: '0x9dcF9D205C9De35334D646BeE44b2D2859712A09',\n },\n },\n mainnet: {\n name: 'BNB Chain',\n chainId: 56,\n wormholeChainId: 4,\n rpcUrl: 'https://bsc-dataseed.binance.org',\n explorerUrl: 'https://bscscan.com',\n isEvm: true,\n contracts: {\n wormholeCoreBridge: '0x98f3c9e6E3fAce36bAAd05FE09d375Ef1464288B',\n tokenBridge: '0xB6F6D86a8f9879A9c87f643768d9efc38c1Da6E7',\n },\n },\n },\n\n // ────────────────────────────────────────────────────────────────────────\n // AVALANCHE\n // ────────────────────────────────────────────────────────────────────────\n avalanche: {\n displayName: 'Avalanche',\n type: 'evm',\n canBeHub: false,\n testnet: {\n name: 'Avalanche Fuji',\n chainId: 43113,\n wormholeChainId: 6,\n rpcUrl: 'https://api.avax-test.network/ext/bc/C/rpc',\n explorerUrl: 'https://testnet.snowtrace.io',\n isEvm: true,\n contracts: {\n wormholeCoreBridge: '0x7bbcE28e64B3F8b84d876Ab298393c38ad7aac4C',\n tokenBridge: '0x61E44E506Ca5659E6c0bba9b678586fA2d729756',\n },\n },\n mainnet: {\n name: 'Avalanche',\n chainId: 43114,\n wormholeChainId: 6,\n rpcUrl: 'https://api.avax.network/ext/bc/C/rpc',\n explorerUrl: 'https://snowtrace.io',\n isEvm: true,\n contracts: {\n wormholeCoreBridge: '0x54a8e5f9c4CbA08F9943965859F6c34eAF03E26c',\n tokenBridge: '0x0e082F06FF657D94310cB8cE8B0D9a04541d8052',\n },\n },\n },\n\n // ────────────────────────────────────────────────────────────────────────\n // SCROLL\n // ────────────────────────────────────────────────────────────────────────\n scroll: {\n displayName: 'Scroll',\n type: 'evm',\n canBeHub: false,\n testnet: {\n name: 'Scroll Sepolia',\n chainId: 534351,\n wormholeChainId: 34,\n rpcUrl: 'https://sepolia-rpc.scroll.io',\n explorerUrl: 'https://sepolia.scrollscan.com',\n isEvm: true,\n contracts: {\n wormholeCoreBridge: '0x055F47F1250012C6B20c436570a76e52c17Af2D5',\n tokenBridge: '0x22427d90B7dA3fA4642F7025A854c7254E4e45BF',\n },\n },\n mainnet: {\n name: 'Scroll',\n chainId: 534352,\n wormholeChainId: 34,\n rpcUrl: 'https://rpc.scroll.io',\n explorerUrl: 'https://scrollscan.com',\n isEvm: true,\n contracts: {\n wormholeCoreBridge: '0xbebdb6C8ddC678FfA9f8748f85C815C556Dd8ac6',\n tokenBridge: '0x24850c6f61C438823F01B7A3BF2B89B72174Fa9d',\n },\n },\n },\n\n // ────────────────────────────────────────────────────────────────────────\n // BLAST\n // ────────────────────────────────────────────────────────────────────────\n blast: {\n displayName: 'Blast',\n type: 'evm',\n canBeHub: false,\n testnet: {\n name: 'Blast Sepolia',\n chainId: 168587773,\n wormholeChainId: 36,\n rpcUrl: 'https://sepolia.blast.io',\n explorerUrl: 'https://sepolia.blastscan.io',\n isEvm: true,\n contracts: {\n wormholeCoreBridge: '0x473e002D7add6fB67a4964F13bFd61280Ca46886',\n tokenBridge: '0x430855B4D43b8AEB9D2B9869B74d58dda79C0dB2',\n },\n },\n mainnet: {\n name: 'Blast',\n chainId: 81457,\n wormholeChainId: 36,\n rpcUrl: 'https://rpc.blast.io',\n explorerUrl: 'https://blastscan.io',\n isEvm: true,\n contracts: {\n wormholeCoreBridge: '0xbebdb6C8ddC678FfA9f8748f85C815C556Dd8ac6',\n tokenBridge: '0x24850c6f61C438823F01B7A3BF2B89B72174Fa9d',\n },\n },\n },\n\n // ────────────────────────────────────────────────────────────────────────\n // MANTLE\n // ────────────────────────────────────────────────────────────────────────\n mantle: {\n displayName: 'Mantle',\n type: 'evm',\n canBeHub: false,\n testnet: {\n name: 'Mantle Sepolia',\n chainId: 5003,\n wormholeChainId: 35,\n rpcUrl: 'https://rpc.sepolia.mantle.xyz',\n explorerUrl: 'https://sepolia.mantlescan.xyz',\n isEvm: true,\n contracts: {\n wormholeCoreBridge: '0x376428e7f26D5867e69201b275553C45B09EE090',\n tokenBridge: '0x75Bfa155a9D7A3714b0861c8a8aF0C4633c45b5D',\n },\n },\n mainnet: {\n name: 'Mantle',\n chainId: 5000,\n wormholeChainId: 35,\n rpcUrl: 'https://rpc.mantle.xyz',\n explorerUrl: 'https://mantlescan.xyz',\n isEvm: true,\n contracts: {\n wormholeCoreBridge: '0xbebdb6C8ddC678FfA9f8748f85C815C556Dd8ac6',\n tokenBridge: '0x24850c6f61C438823F01B7A3BF2B89B72174Fa9d',\n },\n },\n },\n\n // ────────────────────────────────────────────────────────────────────────\n // FANTOM\n // ────────────────────────────────────────────────────────────────────────\n fantom: {\n displayName: 'Fantom',\n type: 'evm',\n canBeHub: false,\n testnet: {\n name: 'Fantom Testnet',\n chainId: 4002,\n wormholeChainId: 10,\n rpcUrl: 'https://rpc.testnet.fantom.network',\n explorerUrl: 'https://testnet.ftmscan.com',\n isEvm: true,\n contracts: {\n wormholeCoreBridge: '0x1BB3B4119b7BA9dfad76B0545fb3F531383c3bB7',\n tokenBridge: '0x599CEa2204B4FaECd584Ab1F2b6aCA137a0afbE8',\n },\n },\n mainnet: {\n name: 'Fantom',\n chainId: 250,\n wormholeChainId: 10,\n rpcUrl: 'https://rpcapi.fantom.network',\n explorerUrl: 'https://ftmscan.com',\n isEvm: true,\n contracts: {\n wormholeCoreBridge: '0x126783A6Cb203a3E35344528B26ca3a0489a1485',\n tokenBridge: '0x7C9Fc5741288cDFdD83CeB07f3ea7e22618D79D2',\n },\n },\n },\n\n // ────────────────────────────────────────────────────────────────────────\n // CELO\n // ────────────────────────────────────────────────────────────────────────\n celo: {\n displayName: 'Celo',\n type: 'evm',\n canBeHub: false,\n testnet: {\n name: 'Celo Alfajores',\n chainId: 44787,\n wormholeChainId: 14,\n rpcUrl: 'https://alfajores-forno.celo-testnet.org',\n explorerUrl: 'https://alfajores.celoscan.io',\n isEvm: true,\n contracts: {\n wormholeCoreBridge: '0x88505117CA88e7dd2eC6EA1E13f0948db2D50D56',\n tokenBridge: '0x05ca6037eC51F8b712eD2E6Fa72219FEaE74E153',\n },\n },\n mainnet: {\n name: 'Celo',\n chainId: 42220,\n wormholeChainId: 14,\n rpcUrl: 'https://forno.celo.org',\n explorerUrl: 'https://celoscan.io',\n isEvm: true,\n contracts: {\n wormholeCoreBridge: '0xa321448d90d4e5b0A732867c18eA198e75CAC48E',\n tokenBridge: '0x796Dff6D74F3E27060B71255Fe517BFb23C93eed',\n },\n },\n },\n\n // ────────────────────────────────────────────────────────────────────────\n // MOONBEAM\n // ────────────────────────────────────────────────────────────────────────\n moonbeam: {\n displayName: 'Moonbeam',\n type: 'evm',\n canBeHub: false,\n testnet: {\n name: 'Moonbase Alpha',\n chainId: 1287,\n wormholeChainId: 16,\n rpcUrl: 'https://rpc.api.moonbase.moonbeam.network',\n explorerUrl: 'https://moonbase.moonscan.io',\n isEvm: true,\n contracts: {\n wormholeCoreBridge: '0xa5B7D85a8f27dd7907dc8FdC21FA5657D5E2F901',\n tokenBridge: '0xbc976D4b9D57E57c3cA52e1Fd136C45FF7955A96',\n },\n },\n mainnet: {\n name: 'Moonbeam',\n chainId: 1284,\n wormholeChainId: 16,\n rpcUrl: 'https://rpc.api.moonbeam.network',\n explorerUrl: 'https://moonscan.io',\n isEvm: true,\n contracts: {\n wormholeCoreBridge: '0xC8e2b0cD52Cf01b0Ce87d389Daa3d414d4cE29f3',\n tokenBridge: '0xb1731c586ca89a23809861c6103F0b96B3F57D92',\n },\n },\n },\n\n // ────────────────────────────────────────────────────────────────────────\n // SEI\n // ────────────────────────────────────────────────────────────────────────\n sei: {\n displayName: 'Sei',\n type: 'evm',\n canBeHub: false,\n testnet: {\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',\n },\n },\n mainnet: {\n name: 'Sei',\n chainId: 1329,\n wormholeChainId: 32,\n rpcUrl: 'https://evm-rpc.sei-apis.com',\n explorerUrl: 'https://seitrace.com',\n isEvm: true,\n contracts: {\n wormholeCoreBridge: '0x0000000000000000000000000000000000000000',\n },\n },\n },\n\n // ────────────────────────────────────────────────────────────────────────\n // SOLANA\n // ────────────────────────────────────────────────────────────────────────\n solana: {\n displayName: 'Solana',\n type: 'solana',\n canBeHub: false,\n testnet: {\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 mainnet: {\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 },\n\n // ────────────────────────────────────────────────────────────────────────\n // APTOS\n // ────────────────────────────────────────────────────────────────────────\n aptos: {\n displayName: 'Aptos',\n type: 'aptos',\n canBeHub: false,\n testnet: {\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 mainnet: {\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 },\n\n // ────────────────────────────────────────────────────────────────────────\n // SUI\n // ────────────────────────────────────────────────────────────────────────\n sui: {\n displayName: 'Sui',\n type: 'sui',\n canBeHub: false,\n testnet: {\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 mainnet: {\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 // STARKNET\n // ────────────────────────────────────────────────────────────────────────\n starknet: {\n displayName: 'Starknet',\n type: 'starknet',\n canBeHub: false,\n testnet: {\n name: 'Starknet Sepolia',\n chainId: 0,\n wormholeChainId: 50001, // Custom bridge (non-Wormhole)\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 hub: '0x68adcc730ed6c355200d00f763825448497b9cdf7936ca121711e078c88e811',\n wormholeCoreBridge: '0x2c458c1ae64556482b05cc2d3ee5b032ed114d68429dda2062c9849a5a725f8',\n },\n hubChainId: 10004, // Base Sepolia\n },\n mainnet: {\n name: 'Starknet',\n chainId: 0,\n wormholeChainId: 50001,\n rpcUrl: 'https://starknet-mainnet.public.blastapi.io/rpc/v0_7',\n explorerUrl: 'https://starkscan.co',\n isEvm: false,\n contracts: {\n // TODO: Deploy mainnet contracts\n wormholeCoreBridge: '',\n },\n },\n },\n\n // ────────────────────────────────────────────────────────────────────────\n // NEAR\n // ────────────────────────────────────────────────────────────────────────\n near: {\n displayName: 'Near',\n type: 'near',\n canBeHub: false,\n testnet: {\n name: 'Near Testnet',\n chainId: 0,\n wormholeChainId: 15,\n rpcUrl: 'https://rpc.testnet.near.org',\n explorerUrl: 'https://explorer.testnet.near.org',\n isEvm: false,\n contracts: {\n wormholeCoreBridge: 'wormhole.wormhole.testnet',\n tokenBridge: 'token.wormhole.testnet',\n },\n },\n mainnet: {\n name: 'Near',\n chainId: 0,\n wormholeChainId: 15,\n rpcUrl: 'https://rpc.mainnet.near.org',\n explorerUrl: 'https://explorer.near.org',\n isEvm: false,\n contracts: {\n wormholeCoreBridge: 'contract.wormhole_crypto.near',\n tokenBridge: 'contract.portalbridge.near',\n },\n },\n },\n};\n\n// ============================================================================\n// Helper Functions\n// ============================================================================\n\n/**\n * Get chain configuration by name and network\n */\nexport function getChainConfig(\n chain: ChainName,\n network: NetworkType = 'testnet'\n): ChainConfig {\n const preset = CHAIN_PRESETS[chain];\n if (!preset) {\n throw new Error(\n `Unknown chain: \"${chain}\". Supported chains: ${Object.keys(CHAIN_PRESETS).join(', ')}`\n );\n }\n return preset[network];\n}\n\n/**\n * Get chain preset by name\n */\nexport function getChainPreset(chain: ChainName): ChainPreset {\n const preset = CHAIN_PRESETS[chain];\n if (!preset) {\n throw new Error(\n `Unknown chain: \"${chain}\". Supported chains: ${Object.keys(CHAIN_PRESETS).join(', ')}`\n );\n }\n return preset;\n}\n\n/**\n * Get all supported chain names\n */\nexport function getSupportedChains(): ChainName[] {\n return Object.keys(CHAIN_PRESETS) as ChainName[];\n}\n\n/**\n * Get hub-capable chains\n */\nexport function getHubChains(): ChainName[] {\n return Object.entries(CHAIN_PRESETS)\n .filter(([_, preset]) => preset.canBeHub)\n .map(([name]) => name as ChainName);\n}\n\n/**\n * Check if chain is supported\n */\nexport function isChainSupported(chain: string): chain is ChainName {\n return chain in CHAIN_PRESETS;\n}\n\n/**\n * Get default hub chain\n */\nexport function getDefaultHub(network: NetworkType = 'testnet'): ChainConfig {\n return CHAIN_PRESETS.base[network];\n}\n","/**\n * Veridex Protocol SDK - Simplified Initialization\n * \n * Factory functions for easy SDK creation with minimal configuration.\n * \n * @example\n * ```typescript\n * import { createSDK } from '@veridex/sdk';\n * \n * // Simplest usage - testnet by default\n * const sdk = await createSDK('base');\n * \n * // Register passkey and start using\n * await sdk.passkey.register('user@example.com', 'My Wallet');\n * const vault = await sdk.getVaultAddress();\n * ```\n */\n\nimport { VeridexSDK } from './core/VeridexSDK.js';\nimport { EVMClient } from './chains/evm/EVMClient.js';\nimport { SolanaClient } from './chains/solana/SolanaClient.js';\nimport { AptosClient } from './chains/aptos/AptosClient.js';\nimport { SuiClient } from './chains/sui/SuiClient.js';\nimport { StarknetClient } from './chains/starknet/StarknetClient.js';\nimport { \n CHAIN_PRESETS,\n getChainConfig,\n getChainPreset,\n type ChainName,\n type NetworkType,\n} from './presets.js';\nimport type { ChainClient } from './core/types.js';\n\n// ============================================================================\n// Simple Configuration Interface\n// ============================================================================\n\n/**\n * Simplified SDK configuration\n * Only specify what you need - everything else has sensible defaults\n */\nexport interface SimpleSDKConfig {\n /**\n * Network to connect to\n * @default 'testnet'\n */\n network?: NetworkType;\n \n /**\n * Custom RPC URL (optional - defaults to public endpoints)\n */\n rpcUrl?: string;\n \n /**\n * Relayer URL for gasless transactions (optional)\n */\n relayerUrl?: string;\n \n /**\n * Relayer API key (optional)\n */\n relayerApiKey?: string;\n \n /**\n * Sponsor private key for gasless vault creation (optional)\n * If not provided, users pay their own gas\n */\n sponsorPrivateKey?: string;\n \n /**\n * Integrator sponsor key (optional)\n * Allows platforms to pay for their users' transactions\n */\n integratorSponsorKey?: string;\n \n /**\n * Additional RPC URLs for multi-chain operations\n * Maps chain name to RPC URL\n */\n rpcUrls?: Partial<Record<ChainName, string>>;\n}\n\n/**\n * Session-specific configuration\n */\nexport interface SessionConfig {\n /**\n * Chain to use for sessions\n */\n chain: ChainName;\n \n /**\n * Network to connect to\n * @default 'testnet'\n */\n network?: NetworkType;\n \n /**\n * Session duration in seconds\n * @default 3600 (1 hour)\n */\n duration?: number;\n \n /**\n * Maximum value per transaction\n * @default BigInt(1e18) (1 token)\n */\n maxValue?: bigint;\n \n /**\n * Require user verification for session creation\n * @default true\n */\n requireUV?: boolean;\n}\n\n// ============================================================================\n// Chain Client Factory\n// ============================================================================\n\n/**\n * Create the appropriate chain client based on chain type\n */\nfunction createChainClient(\n chain: ChainName,\n network: NetworkType,\n customRpcUrl?: string\n): ChainClient {\n const preset = getChainPreset(chain);\n const config = preset[network];\n const rpcUrl = customRpcUrl || config.rpcUrl;\n\n const requireString = (value: string | undefined, label: string): string => {\n if (!value) {\n throw new Error(`Missing ${label} for chain \"${chain}\" on network \"${network}\"`);\n }\n return value;\n };\n \n switch (preset.type) {\n case 'evm':\n return new EVMClient({\n chainId: config.chainId,\n wormholeChainId: config.wormholeChainId,\n rpcUrl,\n hubContractAddress: requireString(config.contracts.hub, 'hub contract address'),\n wormholeCoreBridge: requireString(config.contracts.wormholeCoreBridge, 'Wormhole core bridge address'),\n vaultFactory: config.contracts.vaultFactory,\n vaultImplementation: config.contracts.vaultImplementation,\n tokenBridge: config.contracts.tokenBridge,\n name: config.name,\n explorerUrl: config.explorerUrl,\n });\n \n case 'solana':\n return new SolanaClient({\n rpcUrl,\n programId: requireString(config.contracts.hub, 'programId'),\n wormholeCoreBridge: requireString(config.contracts.wormholeCoreBridge, 'Wormhole core bridge address'),\n tokenBridge: requireString(config.contracts.tokenBridge, 'token bridge address'),\n wormholeChainId: config.wormholeChainId,\n network: network === 'testnet' ? 'devnet' : 'mainnet',\n });\n \n case 'aptos':\n return new AptosClient({\n rpcUrl,\n moduleAddress: requireString(config.contracts.hub, 'moduleAddress'),\n wormholeCoreBridge: requireString(config.contracts.wormholeCoreBridge, 'Wormhole core bridge address'),\n tokenBridge: requireString(config.contracts.tokenBridge, 'token bridge address'),\n wormholeChainId: config.wormholeChainId,\n network: network,\n });\n \n case 'sui':\n return new SuiClient({\n rpcUrl,\n packageId: requireString(config.contracts.hub, 'packageId'),\n wormholeCoreBridge: requireString(config.contracts.wormholeCoreBridge, 'Wormhole core bridge address'),\n wormholeChainId: config.wormholeChainId,\n network: network,\n });\n \n case 'starknet':\n return new StarknetClient({\n rpcUrl,\n spokeContractAddress: config.contracts.hub,\n bridgeContractAddress: config.contracts.wormholeCoreBridge,\n wormholeChainId: config.wormholeChainId,\n network: network === 'testnet' ? 'sepolia' : 'mainnet',\n });\n \n case 'near':\n case 'cosmos':\n throw new Error(`Chain type \"${preset.type}\" is not yet supported. Coming soon!`);\n \n default:\n throw new Error(`Unknown chain type: ${preset.type}`);\n }\n}\n\n// ============================================================================\n// SDK Factory Functions\n// ============================================================================\n\n/**\n * Create a Veridex SDK instance with minimal configuration\n * \n * @param chain - Chain name (e.g., 'base', 'optimism', 'solana')\n * @param config - Optional configuration overrides\n * @returns Configured VeridexSDK instance\n * \n * @example\n * ```typescript\n * // Simplest usage - testnet by default\n * const sdk = await createSDK('base');\n * \n * // Use mainnet\n * const mainnetSdk = await createSDK('base', { network: 'mainnet' });\n * \n * // With custom RPC\n * const customSdk = await createSDK('base', { \n * rpcUrl: 'https://my-rpc.example.com' \n * });\n * \n * // With relayer for gasless transactions\n * const gaslessSdk = await createSDK('base', {\n * relayerUrl: 'https://relayer.veridex.io',\n * relayerApiKey: 'your-api-key',\n * });\n * ```\n */\nexport function createSDK(\n chain: ChainName,\n config: SimpleSDKConfig = {}\n): VeridexSDK {\n const network = config.network ?? 'testnet';\n \n // Validate chain exists\n if (!CHAIN_PRESETS[chain]) {\n const supportedChains = Object.keys(CHAIN_PRESETS).join(', ');\n throw new Error(\n `Unknown chain: \"${chain}\". Supported chains: ${supportedChains}`\n );\n }\n \n // Create chain client\n const chainClient = createChainClient(chain, network, config.rpcUrl);\n \n // Build RPC URLs map for multi-chain operations\n const chainRpcUrls: Record<number, string> = {};\n if (config.rpcUrls) {\n for (const [chainName, rpcUrl] of Object.entries(config.rpcUrls)) {\n if (rpcUrl && CHAIN_PRESETS[chainName as ChainName]) {\n const chainConfig = getChainConfig(chainName as ChainName, network);\n chainRpcUrls[chainConfig.wormholeChainId] = rpcUrl;\n }\n }\n }\n \n // Create SDK\n return new VeridexSDK({\n chain: chainClient,\n testnet: network === 'testnet',\n relayerUrl: config.relayerUrl,\n relayerApiKey: config.relayerApiKey,\n sponsorPrivateKey: config.sponsorPrivateKey,\n integratorSponsorKey: config.integratorSponsorKey,\n chainRpcUrls: Object.keys(chainRpcUrls).length > 0 ? chainRpcUrls : undefined,\n });\n}\n\n/**\n * Create SDK for the default hub chain (Base)\n * \n * @param config - Optional configuration\n * @returns SDK configured for Base hub chain\n * \n * @example\n * ```typescript\n * const sdk = createHubSDK();\n * await sdk.passkey.register('user', 'My Wallet');\n * ```\n */\nexport function createHubSDK(config: SimpleSDKConfig = {}): VeridexSDK {\n return createSDK('base', config);\n}\n\n/**\n * Create SDK for testnet (convenience function)\n * \n * @param chain - Chain name\n * @param config - Optional configuration (network is forced to testnet)\n * @returns SDK configured for testnet\n */\nexport function createTestnetSDK(\n chain: ChainName = 'base',\n config: Omit<SimpleSDKConfig, 'network'> = {}\n): VeridexSDK {\n return createSDK(chain, { ...config, network: 'testnet' });\n}\n\n/**\n * Create SDK for mainnet (convenience function)\n * \n * @param chain - Chain name\n * @param config - Optional configuration (network is forced to mainnet)\n * @returns SDK configured for mainnet\n */\nexport function createMainnetSDK(\n chain: ChainName = 'base',\n config: Omit<SimpleSDKConfig, 'network'> = {}\n): VeridexSDK {\n return createSDK(chain, { ...config, network: 'mainnet' });\n}\n\n// ============================================================================\n// Session Factory (for Session Keys)\n// ============================================================================\n\n/**\n * Create a session-enabled SDK\n * \n * @param chain - Chain name\n * @param config - Session configuration\n * @returns SDK configured for session key usage\n * \n * @example\n * ```typescript\n * import { createSessionSDK, SessionManager } from '@veridex/sdk';\n * \n * const sdk = createSessionSDK('base');\n * const sessionManager = new SessionManager({ sdk });\n * \n * // Create a session (one passkey auth)\n * const session = await sessionManager.createSession({\n * duration: 3600,\n * maxValue: BigInt(1e18),\n * });\n * \n * // Execute multiple transactions without prompts\n * await sessionManager.executeWithSession(params, session);\n * ```\n */\nexport function createSessionSDK(\n chain: ChainName = 'base',\n config: SimpleSDKConfig = {}\n): VeridexSDK {\n // Sessions require hub chain with session key support\n const preset = getChainPreset(chain);\n if (!preset.canBeHub) {\n console.warn(\n `Chain \"${chain}\" may have limited session support. ` +\n `Consider using a hub chain like \"base\" for full session capabilities.`\n );\n }\n \n return createSDK(chain, config);\n}\n\n// ============================================================================\n// Type Exports\n// ============================================================================\n\nexport type { ChainName, NetworkType } from './presets.js';\nexport { \n CHAIN_NAMES, \n CHAIN_PRESETS,\n getChainConfig,\n getChainPreset,\n getSupportedChains,\n getHubChains,\n isChainSupported,\n getDefaultHub,\n} from './presets.js';\n","/**\n * Veridex Protocol SDK - Session Manager\n * \n * Manages ephemeral session keys for fast, native L1-speed transactions\n * after initial biometric authentication.\n * \n * Key Features:\n * - One-time Passkey auth to create session\n * - Instant software-backed signing for subsequent transactions\n * - Query-based validation on Spokes (no VAA wait)\n * - ~400ms transactions after initial setup\n * - Secure encrypted storage (AES-GCM)\n * - Auto-refresh before expiry\n * - Per-session value limits\n */\n\nimport { ethers } from 'ethers';\nimport type {\n SessionKey,\n SessionConfig,\n SessionSignature,\n SessionManagerConfig,\n SessionStorage,\n SessionEvent,\n SessionEventCallback,\n ActionParams,\n SessionSignedAction,\n} from './types.js';\nimport { SessionError, SessionErrorCode } from './types.js';\nimport {\n generateSecp256k1KeyPair,\n computeSessionKeyHash,\n signWithSessionKey,\n hashAction,\n validateSessionConfig,\n DEFAULT_SESSION_DURATION,\n DEFAULT_REFRESH_BUFFER,\n} from './crypto.js';\nimport { createSessionStorage } from './storage.js';\nimport type { PasskeyCredential } from '../core/PasskeyManager.js';\nimport type { RegisterSessionParams, RevokeSessionParams } from '../types.js';\n\n// ============================================================================\n// Hub Client Interface\n// ============================================================================\n\n/**\n * Interface for Hub contract interactions\n * \n * This should be implemented by chain clients (e.g., EVMHubClientAdapter).\n */\ninterface HubClient {\n /**\n * Register a session on the Hub\n * \n * @param params Registration parameters with Passkey signature\n * @returns Promise that resolves when registration completes\n */\n registerSession(params: RegisterSessionParams): Promise<void>;\n \n /**\n * Revoke a session on the Hub\n * \n * @param params Revocation parameters with Passkey signature\n * @returns Promise that resolves when revocation completes\n */\n revokeSession(params: RevokeSessionParams): Promise<void>;\n}\n\n// ============================================================================\n// Session Manager Class\n// ============================================================================\n\n/**\n * Manages session key lifecycle and signing operations\n * \n * Usage:\n * ```typescript\n * const manager = new SessionManager(credential, hubClient, passkeySign, config);\n * \n * // Create session (requires biometric)\n * const session = await manager.createSession();\n * \n * // Sign actions instantly (no biometric)\n * const signature = await manager.signWithSession(action);\n * \n * // Revoke session (requires biometric)\n * await manager.revokeSession();\n * ```\n */\nclass SessionManager {\n private currentSession: SessionKey | null = null;\n private storage: SessionStorage;\n private config: Required<SessionConfig>;\n private refreshTimer: NodeJS.Timeout | null = null;\n private eventCallbacks: SessionEventCallback[] = [];\n private debug: boolean;\n \n /**\n * @param credential User's Passkey credential (for Hub interaction)\n * @param hubClient Hub client for on-chain session operations\n * @param passkeySign Function to sign challenges with Passkey\n * @param config Session configuration\n * @param managerConfig SessionManager configuration\n */\n constructor(\n private credential: PasskeyCredential,\n private hubClient: HubClient,\n private passkeySign: (challenge: Uint8Array) => Promise<any>,\n config: Partial<SessionConfig>,\n managerConfig?: SessionManagerConfig\n ) {\n // Validate and set configuration\n this.config = {\n duration: config.duration ?? DEFAULT_SESSION_DURATION,\n maxValue: config.maxValue ?? 0n,\n autoRefresh: config.autoRefresh ?? true,\n refreshBuffer: config.refreshBuffer ?? DEFAULT_REFRESH_BUFFER,\n chainScopes: config.chainScopes ?? [],\n };\n \n validateSessionConfig(this.config);\n \n this.debug = managerConfig?.debug ?? false;\n \n // Initialize storage\n this.storage = managerConfig?.encryptionKey\n ? createSessionStorage(credential.credentialId)\n : createSessionStorage(\n credential.credentialId,\n managerConfig?.storageBackend\n );\n }\n \n // ========================================================================\n // Session Lifecycle\n // ========================================================================\n \n /**\n * Create a new session (requires biometric authentication)\n * \n * Steps:\n * 1. Generate ephemeral secp256k1 key pair\n * 2. Sign session registration with Passkey\n * 3. Register session on Hub contract\n * 4. Store session securely (encrypted)\n * 5. Start auto-refresh timer (if enabled)\n * \n * @returns Created session key\n * @throws SessionError if registration fails\n */\n async createSession(): Promise<SessionKey> {\n try {\n this.log('Creating new session...');\n \n // 1. Generate ephemeral key pair\n const keyPair = generateSecp256k1KeyPair();\n const keyHash = computeSessionKeyHash(keyPair.publicKey);\n \n this.log('Generated session key:', keyHash);\n \n // 2. Prepare challenge for Passkey signing\n const challenge = ethers.solidityPacked(\n ['string', 'bytes32', 'uint256', 'uint256'],\n ['registerSession', keyHash, this.config.duration, this.config.maxValue]\n );\n \n this.log('Challenge prepared, requesting Passkey signature...');\n \n // 3. Sign with Passkey (this triggers biometric prompt)\n const signature = await this.passkeySign(ethers.getBytes(challenge));\n \n this.log('Passkey signature obtained, registering on Hub...');\n \n // 4. Register session on Hub\n const registerParams: RegisterSessionParams = {\n signature,\n publicKeyX: this.credential.publicKeyX,\n publicKeyY: this.credential.publicKeyY,\n sessionKeyHash: keyHash,\n duration: this.config.duration,\n maxValue: this.config.maxValue,\n requireUV: true,\n };\n \n await this.hubClient.registerSession(registerParams);\n \n this.log('Session registered on Hub');\n \n // 5. Create session object\n const expiry = Date.now() + this.config.duration * 1000;\n \n this.currentSession = {\n publicKey: keyPair.publicKey,\n privateKey: keyPair.privateKey,\n keyHash,\n expiry,\n maxValue: this.config.maxValue,\n chainScopes: this.config.chainScopes,\n userKeyHash: this.credential.keyHash,\n };\n \n // 6. Store securely\n await this.storage.save(this.currentSession);\n \n this.log('Session stored securely');\n \n // 7. Start auto-refresh\n if (this.config.autoRefresh) {\n this.scheduleRefresh();\n }\n \n // 8. Emit event\n this.emit({ type: 'session-created', session: this.currentSession });\n \n return this.currentSession;\n \n } catch (error) {\n const sessionError = error instanceof SessionError\n ? error\n : new SessionError(\n 'Failed to create session',\n SessionErrorCode.REGISTRATION_FAILED,\n error\n );\n \n this.emit({ type: 'session-error', error: sessionError });\n throw sessionError;\n }\n }\n \n /**\n * Load existing session from storage\n * \n * @returns Loaded session or null if no valid session exists\n */\n async loadSession(): Promise<SessionKey | null> {\n try {\n this.log('Loading session from storage...');\n \n const session = await this.storage.load();\n \n if (!session) {\n this.log('No session found in storage');\n return null;\n }\n \n // Verify session is not expired\n if (session.expiry <= Date.now()) {\n this.log('Session expired, clearing...');\n await this.storage.clear();\n return null;\n }\n \n this.currentSession = session;\n this.log('Session loaded:', session.keyHash);\n \n // Start auto-refresh if enabled\n if (this.config.autoRefresh) {\n this.scheduleRefresh();\n }\n \n this.emit({ type: 'session-loaded', session });\n \n return session;\n \n } catch (error) {\n this.log('Failed to load session:', error);\n await this.storage.clear();\n return null;\n }\n }\n \n /**\n * Revoke the current session (requires biometric authentication)\n * \n * @throws SessionError if no active session or revocation fails\n */\n async revokeSession(): Promise<void> {\n if (!this.currentSession) {\n throw new SessionError(\n 'No active session to revoke',\n SessionErrorCode.NO_ACTIVE_SESSION\n );\n }\n \n try {\n this.log('Revoking session:', this.currentSession.keyHash);\n \n // 1. Prepare challenge for revocation\n const challenge = ethers.solidityPacked(\n ['string', 'bytes32'],\n ['revokeSession', this.currentSession.keyHash]\n );\n \n // 2. Sign with Passkey (biometric prompt)\n const signature = await this.passkeySign(ethers.getBytes(challenge));\n \n this.log('Passkey signature obtained, revoking on Hub...');\n \n // 3. Revoke on Hub\n const revokeParams: RevokeSessionParams = {\n signature,\n publicKeyX: this.credential.publicKeyX,\n publicKeyY: this.credential.publicKeyY,\n sessionKeyHash: this.currentSession.keyHash,\n requireUV: true,\n };\n \n await this.hubClient.revokeSession(revokeParams);\n \n this.log('Session revoked on Hub');\n \n // 4. Clear local storage\n await this.storage.clear();\n \n // 5. Cancel refresh timer\n if (this.refreshTimer) {\n clearTimeout(this.refreshTimer);\n this.refreshTimer = null;\n }\n \n const revokedKeyHash = this.currentSession.keyHash;\n this.currentSession = null;\n \n // 6. Emit event\n this.emit({ type: 'session-revoked', keyHash: revokedKeyHash });\n \n this.log('Session revoked successfully');\n \n } catch (error) {\n const sessionError = error instanceof SessionError\n ? error\n : new SessionError(\n 'Failed to revoke session',\n SessionErrorCode.REVOCATION_FAILED,\n error\n );\n \n this.emit({ type: 'session-error', error: sessionError });\n throw sessionError;\n }\n }\n \n // ========================================================================\n // Session Signing\n // ========================================================================\n \n /**\n * Sign an action with the session key (instant, no biometric)\n * \n * @param action Action parameters to sign\n * @returns Session signature\n * @throws SessionError if no active session, expired, or value exceeds limit\n */\n async signWithSession(action: ActionParams): Promise<SessionSignature> {\n if (!this.currentSession) {\n throw new SessionError(\n 'No active session available',\n SessionErrorCode.NO_ACTIVE_SESSION\n );\n }\n \n const now = Date.now();\n if (now >= this.currentSession.expiry) {\n this.emit({ type: 'session-expired', keyHash: this.currentSession.keyHash });\n throw new SessionError(\n 'Session has expired',\n SessionErrorCode.SESSION_EXPIRED\n );\n }\n \n if (this.currentSession.maxValue > 0n && action.value > this.currentSession.maxValue) {\n throw new SessionError(\n `Transaction value (${action.value}) exceeds session limit (${this.currentSession.maxValue})`,\n SessionErrorCode.VALUE_EXCEEDS_LIMIT,\n { value: action.value, limit: this.currentSession.maxValue }\n );\n }\n \n if (\n this.currentSession.chainScopes.length > 0 &&\n !this.currentSession.chainScopes.includes(action.targetChain)\n ) {\n throw new SessionError(\n `Chain ${action.targetChain} not in session scope`,\n SessionErrorCode.CHAIN_NOT_ALLOWED,\n { chain: action.targetChain, allowedChains: this.currentSession.chainScopes }\n );\n }\n \n this.log('Signing action with session key...');\n \n const messageHash = hashAction(action);\n const { signature } = signWithSessionKey(\n this.currentSession.privateKey,\n messageHash\n );\n \n const sessionSignature: SessionSignature = {\n signature,\n sessionKeyHash: this.currentSession.keyHash,\n userKeyHash: this.currentSession.userKeyHash,\n timestamp: now,\n nonce: action.nonce,\n };\n \n this.log('Action signed successfully');\n \n return sessionSignature;\n }\n \n /**\n * Sign an action and prepare for submission\n * \n * @param action Action parameters\n * @returns Session-signed action ready for submission\n */\n async signAction(action: ActionParams): Promise<SessionSignedAction> {\n const signature = await this.signWithSession(action);\n \n return {\n action,\n signature,\n readyToSubmit: true,\n };\n }\n \n // ========================================================================\n // Session State\n // ========================================================================\n \n /**\n * Check if a session is currently active\n * \n * @returns True if an active, non-expired session exists\n */\n isActive(): boolean {\n if (!this.currentSession) {\n return false;\n }\n return Date.now() < this.currentSession.expiry;\n }\n \n /**\n * Get current session information (if active)\n * \n * @returns Current session or null\n */\n getSession(): SessionKey | null {\n if (!this.isActive()) {\n return null;\n }\n return this.currentSession;\n }\n \n /**\n * Get time remaining until session expiry (in seconds)\n * \n * @returns Seconds until expiry, or 0 if no active session\n */\n getTimeRemaining(): number {\n if (!this.currentSession) {\n return 0;\n }\n const remaining = Math.floor((this.currentSession.expiry - Date.now()) / 1000);\n return Math.max(0, remaining);\n }\n \n // ========================================================================\n // Auto-Refresh\n // ========================================================================\n \n /**\n * Schedule automatic session refresh\n */\n private scheduleRefresh(): void {\n if (!this.currentSession || !this.config.autoRefresh) {\n return;\n }\n \n if (this.refreshTimer) {\n clearTimeout(this.refreshTimer);\n }\n \n const timeUntilRefresh = this.currentSession.expiry - Date.now() - (this.config.refreshBuffer * 1000);\n \n if (timeUntilRefresh <= 0) {\n this.log('Session expiring soon, refreshing now...');\n this.refreshSession().catch(error => {\n this.log('Auto-refresh failed:', error);\n this.emit({ type: 'session-error', error });\n });\n return;\n }\n \n this.log(`Scheduling refresh in ${Math.floor(timeUntilRefresh / 1000)}s`);\n \n this.refreshTimer = setTimeout(() => {\n this.refreshSession().catch(error => {\n this.log('Auto-refresh failed:', error);\n this.emit({ type: 'session-error', error });\n });\n }, timeUntilRefresh);\n }\n \n /**\n * Refresh the current session (creates a new session)\n * \n * @returns New session key\n */\n async refreshSession(): Promise<SessionKey> {\n this.log('Refreshing session...');\n const newSession = await this.createSession();\n this.emit({ type: 'session-refreshed', session: newSession });\n return newSession;\n }\n \n // ========================================================================\n // Event Handling\n // ========================================================================\n \n /**\n * Register an event callback\n */\n on(callback: SessionEventCallback): void {\n this.eventCallbacks.push(callback);\n }\n \n /**\n * Unregister an event callback\n */\n off(callback: SessionEventCallback): void {\n this.eventCallbacks = this.eventCallbacks.filter(cb => cb !== callback);\n }\n \n /**\n * Emit a session event\n */\n private emit(event: SessionEvent): void {\n for (const callback of this.eventCallbacks) {\n try {\n callback(event);\n } catch (error) {\n console.error('Session event callback error:', error);\n }\n }\n }\n \n // ========================================================================\n // Utilities\n // ========================================================================\n \n /**\n * Log debug message (if debug enabled)\n */\n private log(...args: any[]): void {\n if (this.debug) {\n console.log('[SessionManager]', ...args);\n }\n }\n \n /**\n * Cleanup resources\n */\n dispose(): void {\n if (this.refreshTimer) {\n clearTimeout(this.refreshTimer);\n this.refreshTimer = null;\n }\n this.eventCallbacks = [];\n this.currentSession = null;\n }\n}\n\n// ============================================================================\n// Exports\n// ============================================================================\n\nexport { SessionManager };\nexport type { HubClient };\nexport * from './types.js';\nexport * from './crypto.js';\nexport * from './storage.js';","/**\n * Veridex Protocol SDK - Session Key Management Types\n * \n * Type definitions for ephemeral session keys that enable\n * native L1-speed transactions after initial biometric auth.\n */\n\n// ============================================================================\n// Core Session Types\n// ============================================================================\n\n/**\n * Ephemeral session key for fast software-backed signing\n * \n * Security model:\n * - Private key encrypted at rest (AES-GCM)\n * - Max 24-hour duration enforced on-chain\n * - Value limits prevent unlimited spending\n * - Chain scopes restrict cross-chain usage\n */\nexport interface SessionKey {\n /** Public key of the session (secp256k1) */\n publicKey: Uint8Array;\n \n /** Private key (MUST be encrypted before storage) */\n privateKey: Uint8Array;\n \n /** Keccak256 hash of public key (on-chain identifier) */\n keyHash: string;\n \n /** Unix timestamp when session expires (milliseconds) */\n expiry: number;\n \n /** Maximum transaction value allowed (in token's base units) */\n maxValue: bigint;\n \n /** Wormhole chain IDs where this session is valid */\n chainScopes: number[];\n \n /** User's Passkey key hash (binds session to user) */\n userKeyHash: string;\n}\n\n/**\n * Configuration for session creation and lifecycle\n */\nexport interface SessionConfig {\n /** Session duration in seconds (default: 3600 = 1 hour, max: 86400 = 24 hours) */\n duration: number;\n \n /** Maximum transaction value in base units (0 = unlimited, but NOT RECOMMENDED) */\n maxValue: bigint;\n \n /** Auto-refresh session before expiry (default: true) */\n autoRefresh: boolean;\n \n /** Refresh buffer time in seconds (refresh this many seconds before expiry, default: 300 = 5 min) */\n refreshBuffer?: number;\n \n /** Chain scopes - which Wormhole chain IDs can use this session (empty = all chains) */\n chainScopes?: number[];\n}\n\n/**\n * Signature produced by signing with a session key\n * \n * This is a lightweight software signature (secp256k1) that can be\n * validated on-chain via CCQ to Hub's isSessionActive() state.\n */\nexport interface SessionSignature {\n /** ECDSA signature (r, s, v) from session private key */\n signature: Uint8Array;\n \n /** Session key hash (links signature to registered session) */\n sessionKeyHash: string;\n \n /** User's Passkey key hash (for Hub state query) */\n userKeyHash: string;\n \n /** Timestamp when signature was created (for replay prevention) */\n timestamp: number;\n \n /** Optional nonce for additional replay protection */\n nonce?: number;\n}\n\n/**\n * Configuration for SessionManager initialization\n */\nexport interface SessionManagerConfig {\n /** Default session configuration */\n defaultSessionConfig: SessionConfig;\n \n /** Storage backend ('indexeddb' or 'localstorage', default: 'indexeddb') */\n storageBackend?: 'indexeddb' | 'localstorage';\n \n /** Enable debug logging */\n debug?: boolean;\n \n /** Custom encryption key derivation (for testing only) */\n encryptionKey?: CryptoKey;\n}\n\n// ============================================================================\n// Session Lifecycle Events\n// ============================================================================\n\n/**\n * Events emitted during session lifecycle\n */\nexport type SessionEvent = \n | { type: 'session-created'; session: SessionKey }\n | { type: 'session-loaded'; session: SessionKey }\n | { type: 'session-expired'; keyHash: string }\n | { type: 'session-refreshed'; session: SessionKey }\n | { type: 'session-revoked'; keyHash: string }\n | { type: 'session-error'; error: Error };\n\nexport type SessionEventCallback = (event: SessionEvent) => void;\n\n// ============================================================================\n// Storage Interface\n// ============================================================================\n\n/**\n * Interface for session storage implementations\n * \n * Implementations MUST:\n * - Encrypt private keys before storage\n * - Use secure key derivation (e.g., PBKDF2 or similar)\n * - Provide atomic read/write/delete operations\n */\nexport interface SessionStorage {\n /**\n * Save a session (private key will be encrypted)\n */\n save(session: SessionKey): Promise<void>;\n \n /**\n * Load the active session (private key will be decrypted)\n */\n load(): Promise<SessionKey | null>;\n \n /**\n * Clear all stored sessions\n */\n clear(): Promise<void>;\n \n /**\n * Check if a session exists\n */\n exists(): Promise<boolean>;\n}\n\n// ============================================================================\n// Action Signing Types\n// ============================================================================\n\n/**\n * Parameters for an action to be signed with a session key\n */\nexport interface ActionParams {\n /** Action type (transfer, execute, bridge, etc.) */\n action: string;\n \n /** Target chain (Wormhole chain ID) */\n targetChain: number;\n \n /** Transaction value in base units */\n value: bigint;\n \n /** Action-specific payload */\n payload: Uint8Array;\n \n /** Nonce for replay prevention */\n nonce: number;\n \n /** Optional deadline timestamp */\n deadline?: number;\n}\n\n/**\n * Result of session-signed action\n */\nexport interface SessionSignedAction {\n /** Original action parameters */\n action: ActionParams;\n \n /** Session signature */\n signature: SessionSignature;\n \n /** Ready to submit to relayer or on-chain */\n readyToSubmit: boolean;\n}\n\n// ============================================================================\n// Error Types\n// ============================================================================\n\nexport class SessionError extends Error {\n constructor(\n message: string,\n public code: SessionErrorCode,\n public details?: unknown\n ) {\n super(message);\n this.name = 'SessionError';\n }\n}\n\nexport enum SessionErrorCode {\n NO_ACTIVE_SESSION = 'NO_ACTIVE_SESSION',\n SESSION_EXPIRED = 'SESSION_EXPIRED',\n VALUE_EXCEEDS_LIMIT = 'VALUE_EXCEEDS_LIMIT',\n CHAIN_NOT_ALLOWED = 'CHAIN_NOT_ALLOWED',\n STORAGE_ERROR = 'STORAGE_ERROR',\n ENCRYPTION_ERROR = 'ENCRYPTION_ERROR',\n INVALID_CONFIG = 'INVALID_CONFIG',\n REGISTRATION_FAILED = 'REGISTRATION_FAILED',\n REVOCATION_FAILED = 'REVOCATION_FAILED',\n}\n","/**\n * Veridex Protocol SDK - Session Cryptography Utilities\n * \n * Provides cryptographic operations for session key management:\n * - secp256k1 key generation (NOT secp256r1 - sessions are software-backed)\n * - ECDSA signing with session keys\n * - Key hash derivation (keccak256)\n * - Secure random generation\n */\n\nimport { ethers } from 'ethers';\nimport { SessionError, SessionErrorCode } from './types.js';\n\n// ============================================================================\n// Constants\n// ============================================================================\n\n/** Maximum session duration enforced on-chain (24 hours) */\nexport const MAX_SESSION_DURATION = 86400; // 24 hours in seconds\n\n/** Minimum session duration (60 seconds) */\nexport const MIN_SESSION_DURATION = 60;\n\n/** Default session duration (1 hour) */\nexport const DEFAULT_SESSION_DURATION = 3600;\n\n/** Default refresh buffer (5 minutes before expiry) */\nexport const DEFAULT_REFRESH_BUFFER = 300;\n\n// ============================================================================\n// Key Generation\n// ============================================================================\n\n/**\n * Key pair for secp256k1 session keys\n */\nexport interface KeyPair {\n publicKey: Uint8Array;\n privateKey: Uint8Array;\n address: string; // Ethereum-style address for verification\n}\n\n/**\n * Generate a new secp256k1 key pair for session key\n * \n * Security:\n * - Uses cryptographically secure random (ethers.Wallet.createRandom)\n * - Returns uncompressed public key (65 bytes)\n * - Private key is 32 bytes\n * \n * @returns KeyPair with public/private keys and derived address\n */\nexport function generateSecp256k1KeyPair(): KeyPair {\n try {\n // Use ethers.js for secure key generation\n const wallet = ethers.Wallet.createRandom();\n \n // Extract raw private key (32 bytes)\n const privateKey = ethers.getBytes(wallet.privateKey);\n \n // ethers v6 returns COMPRESSED public key (33 bytes).\n // We need UNCOMPRESSED (65 bytes: 0x04 || x || y).\n // Use SigningKey to derive the uncompressed form.\n const signingKey = new ethers.SigningKey(wallet.privateKey);\n const publicKey = ethers.getBytes(signingKey.publicKey);\n \n return {\n publicKey,\n privateKey,\n address: wallet.address,\n };\n } catch (error) {\n throw new SessionError(\n 'Failed to generate secp256k1 key pair',\n SessionErrorCode.ENCRYPTION_ERROR,\n error\n );\n }\n}\n\n/**\n * Compute keccak256 hash of public key (session key identifier)\n * \n * This hash is used as the on-chain identifier for the session.\n * It matches the Solidity keccak256(publicKey) computation.\n * \n * @param publicKey Uncompressed public key (65 bytes)\n * @returns Hex string of keccak256 hash (0x...)\n */\nexport function computeSessionKeyHash(publicKey: Uint8Array): string {\n if (publicKey.length !== 65 || publicKey[0] !== 0x04) {\n throw new SessionError(\n 'Invalid public key format (expected 65-byte uncompressed key)',\n SessionErrorCode.INVALID_CONFIG\n );\n }\n \n // Hash the full uncompressed public key (including 0x04 prefix)\n return ethers.keccak256(publicKey);\n}\n\n// ============================================================================\n// Signing\n// ============================================================================\n\n/**\n * Sign a message hash with a session key (secp256k1 ECDSA)\n * \n * @param privateKey Session private key (32 bytes)\n * @param messageHash Message hash to sign (32 bytes)\n * @returns Signature with r, s, v components\n */\nexport function signWithSessionKey(\n privateKey: Uint8Array,\n messageHash: Uint8Array | string\n): { r: string; s: string; v: number; signature: Uint8Array } {\n try {\n if (privateKey.length !== 32) {\n throw new SessionError(\n 'Invalid private key length (expected 32 bytes)',\n SessionErrorCode.ENCRYPTION_ERROR\n );\n }\n \n // Create signing key from private key\n const signingKey = new ethers.SigningKey(privateKey);\n \n // Ensure message hash is bytes\n const hashBytes = typeof messageHash === 'string' \n ? ethers.getBytes(messageHash)\n : messageHash;\n \n if (hashBytes.length !== 32) {\n throw new SessionError(\n 'Invalid message hash length (expected 32 bytes)',\n SessionErrorCode.INVALID_CONFIG\n );\n }\n \n // Sign the hash\n const sig = signingKey.sign(hashBytes);\n \n // Extract r, s, v\n const r = sig.r;\n const s = sig.s;\n const v = sig.v;\n \n // Combine into 65-byte signature (r + s + v)\n const signature = ethers.getBytes(sig.serialized);\n \n return { r, s, v, signature };\n } catch (error) {\n throw new SessionError(\n 'Failed to sign with session key',\n SessionErrorCode.ENCRYPTION_ERROR,\n error\n );\n }\n}\n\n/**\n * Hash an action for signing\n * \n * Creates a deterministic hash of action parameters that can be\n * signed with a session key and verified on-chain.\n * \n * Hash format: keccak256(abi.encodePacked(\n * action, targetChain, value, keccak256(payload), nonce, deadline\n * ))\n * \n * @param params Action parameters\n * @returns Message hash (32 bytes)\n */\nexport function hashAction(params: {\n action: string;\n targetChain: number;\n value: bigint;\n payload: Uint8Array;\n nonce: number;\n deadline?: number;\n}): Uint8Array {\n try {\n // Hash the payload first\n const payloadHash = ethers.keccak256(params.payload);\n \n // Encode packed (matches Solidity abi.encodePacked)\n const encoded = ethers.solidityPacked(\n ['string', 'uint256', 'uint256', 'bytes32', 'uint256', 'uint256'],\n [\n params.action,\n params.targetChain,\n params.value,\n payloadHash,\n params.nonce,\n params.deadline ?? 0,\n ]\n );\n \n // Return keccak256 hash\n return ethers.getBytes(ethers.keccak256(encoded));\n } catch (error) {\n throw new SessionError(\n 'Failed to hash action',\n SessionErrorCode.INVALID_CONFIG,\n error\n );\n }\n}\n\n/**\n * Verify a session key signature\n * \n * Used for testing and client-side validation before submission.\n * On-chain verification is handled by Spoke contracts via CCQ.\n * \n * @param messageHash Message that was signed\n * @param signature Signature to verify\n * @param expectedPublicKey Expected public key of signer\n * @returns True if signature is valid\n */\nexport function verifySessionSignature(\n messageHash: Uint8Array | string,\n signature: Uint8Array,\n expectedPublicKey: Uint8Array\n): boolean {\n try {\n if (signature.length !== 65) {\n return false;\n }\n \n // Ensure hash is bytes\n const hashBytes = typeof messageHash === 'string'\n ? ethers.getBytes(messageHash)\n : messageHash;\n \n // Recover public key from signature\n const recovered = ethers.SigningKey.recoverPublicKey(\n hashBytes,\n ethers.hexlify(signature)\n );\n \n // Compare with expected public key\n const recoveredBytes = ethers.getBytes(recovered);\n \n if (recoveredBytes.length !== expectedPublicKey.length) {\n return false;\n }\n \n // Constant-time comparison\n return recoveredBytes.every((byte, i) => byte === expectedPublicKey[i]);\n } catch {\n return false;\n }\n}\n\n// ============================================================================\n// Encryption Key Derivation\n// ============================================================================\n\n/**\n * Derive an AES-GCM encryption key for session storage\n * \n * Uses PBKDF2 to derive a key from a user-specific seed.\n * The seed should be derived from the user's Passkey credential ID.\n * \n * Security considerations:\n * - Uses 100,000 iterations (OWASP minimum)\n * - Salt is derived from credential ID (unique per user)\n * - Key is bound to specific browser/device via extractable: false\n * \n * @param credentialId User's Passkey credential ID (unique identifier)\n * @returns AES-GCM encryption key\n */\nexport async function deriveEncryptionKey(credentialId: string): Promise<CryptoKey> {\n try {\n // Use credential ID as password material\n const passwordBytes = ethers.toUtf8Bytes(credentialId);\n \n // Import as key material\n const keyMaterial = await crypto.subtle.importKey(\n 'raw',\n passwordBytes as BufferSource,\n 'PBKDF2',\n false,\n ['deriveKey']\n );\n \n // Derive salt from credential ID (deterministic but unique per user)\n const saltBytes = ethers.getBytes(ethers.keccak256(passwordBytes));\n \n // Derive AES-GCM key\n const key = await crypto.subtle.deriveKey(\n {\n name: 'PBKDF2',\n salt: saltBytes as BufferSource,\n iterations: 100000, // OWASP minimum\n hash: 'SHA-256',\n },\n keyMaterial,\n {\n name: 'AES-GCM',\n length: 256,\n },\n false, // Not extractable (stays in browser)\n ['encrypt', 'decrypt']\n );\n \n return key;\n } catch (error) {\n throw new SessionError(\n 'Failed to derive encryption key',\n SessionErrorCode.ENCRYPTION_ERROR,\n error\n );\n }\n}\n\n/**\n * Generate a random initialization vector (IV) for AES-GCM\n * \n * @returns 12-byte IV (standard for AES-GCM)\n */\nexport function generateIv(): Uint8Array {\n return crypto.getRandomValues(new Uint8Array(12));\n}\n\n/**\n * Encrypt data with AES-GCM\n * \n * @param data Data to encrypt\n * @param key AES-GCM encryption key\n * @returns Encrypted data with IV prepended\n */\nexport async function encrypt(data: Uint8Array, key: CryptoKey): Promise<Uint8Array> {\n try {\n const iv = generateIv();\n \n const encrypted = await crypto.subtle.encrypt(\n {\n name: 'AES-GCM',\n iv: iv as BufferSource,\n },\n key,\n data as BufferSource\n );\n \n // Prepend IV to encrypted data (IV is not secret)\n const result = new Uint8Array(iv.length + encrypted.byteLength);\n result.set(iv, 0);\n result.set(new Uint8Array(encrypted), iv.length);\n \n return result;\n } catch (error) {\n throw new SessionError(\n 'Encryption failed',\n SessionErrorCode.ENCRYPTION_ERROR,\n error\n );\n }\n}\n\n/**\n * Decrypt data with AES-GCM\n * \n * @param encryptedData Data with IV prepended\n * @param key AES-GCM encryption key\n * @returns Decrypted data\n */\nexport async function decrypt(encryptedData: Uint8Array, key: CryptoKey): Promise<Uint8Array> {\n try {\n if (encryptedData.length < 12) {\n throw new Error('Invalid encrypted data (too short)');\n }\n \n // Extract IV (first 12 bytes)\n const iv = encryptedData.slice(0, 12);\n \n // Extract encrypted data (remaining bytes)\n const ciphertext = encryptedData.slice(12);\n \n const decrypted = await crypto.subtle.decrypt(\n {\n name: 'AES-GCM',\n iv,\n },\n key,\n ciphertext\n );\n \n return new Uint8Array(decrypted);\n } catch (error) {\n throw new SessionError(\n 'Decryption failed',\n SessionErrorCode.ENCRYPTION_ERROR,\n error\n );\n }\n}\n\n// ============================================================================\n// Validation\n// ============================================================================\n\n/**\n * Validate session configuration\n * \n * @param config Session configuration to validate\n * @throws SessionError if configuration is invalid\n */\nexport function validateSessionConfig(config: {\n duration: number;\n maxValue: bigint;\n}): void {\n if (config.duration < MIN_SESSION_DURATION) {\n throw new SessionError(\n `Session duration too short (minimum: ${MIN_SESSION_DURATION}s)`,\n SessionErrorCode.INVALID_CONFIG\n );\n }\n \n if (config.duration > MAX_SESSION_DURATION) {\n throw new SessionError(\n `Session duration too long (maximum: ${MAX_SESSION_DURATION}s = 24 hours)`,\n SessionErrorCode.INVALID_CONFIG\n );\n }\n \n if (config.maxValue < 0n) {\n throw new SessionError(\n 'Session maxValue cannot be negative',\n SessionErrorCode.INVALID_CONFIG\n );\n }\n}\n","/**\n * Veridex Protocol SDK - Secure Session Storage\n * \n * Provides encrypted storage for session keys using IndexedDB or LocalStorage.\n * Private keys are ALWAYS encrypted at rest using AES-GCM.\n * \n * Security guarantees:\n * - Private keys never stored in plaintext\n * - Encryption keys derived from Passkey credential ID (user-bound)\n * - Keys are non-extractable (remain in browser's crypto subsystem)\n * - Automatic cleanup on revocation or expiry\n */\n\nimport { ethers } from 'ethers';\nimport type { SessionKey, SessionStorage } from './types.js';\nimport { SessionError, SessionErrorCode } from './types.js';\nimport { encrypt, decrypt, deriveEncryptionKey } from './crypto.js';\n\n// ============================================================================\n// IndexedDB Session Storage (Preferred)\n// ============================================================================\n\n/** IndexedDB database name */\nconst DB_NAME = 'veridex-sessions';\n\n/** IndexedDB version */\nconst DB_VERSION = 1;\n\n/** Object store name */\nconst STORE_NAME = 'sessions';\n\n/**\n * IndexedDB-based session storage with encryption\n * \n * Preferred storage backend because:\n * - Larger storage quota (~50MB vs ~10MB)\n * - Structured storage (no serialization overhead)\n * - Better performance for binary data\n * - Non-blocking async API\n */\nexport class IndexedDBSessionStorage implements SessionStorage {\n private db: IDBDatabase | null = null;\n private encryptionKey: CryptoKey | null = null;\n private credentialId: string;\n \n /**\n * @param credentialId User's Passkey credential ID (for key derivation)\n */\n constructor(credentialId: string) {\n if (!credentialId) {\n throw new SessionError(\n 'Credential ID required for session storage',\n SessionErrorCode.INVALID_CONFIG\n );\n }\n this.credentialId = credentialId;\n }\n \n /**\n * Initialize database connection\n */\n private async initialize(): Promise<void> {\n if (this.db) return;\n \n return new Promise((resolve, reject) => {\n const request = indexedDB.open(DB_NAME, DB_VERSION);\n \n request.onerror = () => {\n reject(new SessionError(\n 'Failed to open IndexedDB',\n SessionErrorCode.STORAGE_ERROR,\n request.error\n ));\n };\n \n request.onsuccess = () => {\n this.db = request.result;\n resolve();\n };\n \n request.onupgradeneeded = (event) => {\n const db = (event.target as IDBOpenDBRequest).result;\n \n // Create object store if it doesn't exist\n if (!db.objectStoreNames.contains(STORE_NAME)) {\n const store = db.createObjectStore(STORE_NAME, { keyPath: 'keyHash' });\n \n // Create indexes for efficient queries\n store.createIndex('userKeyHash', 'userKeyHash', { unique: false });\n store.createIndex('expiry', 'expiry', { unique: false });\n }\n };\n });\n }\n \n /**\n * Get or derive encryption key\n */\n private async getEncryptionKey(): Promise<CryptoKey> {\n if (this.encryptionKey) {\n return this.encryptionKey;\n }\n \n this.encryptionKey = await deriveEncryptionKey(this.credentialId);\n return this.encryptionKey;\n }\n \n /**\n * Save a session (encrypts private key)\n */\n async save(session: SessionKey): Promise<void> {\n try {\n await this.initialize();\n \n if (!this.db) {\n throw new Error('Database not initialized');\n }\n \n // Get encryption key\n const key = await this.getEncryptionKey();\n \n // Encrypt private key\n const encryptedPrivateKey = await encrypt(session.privateKey, key);\n \n // Prepare storage object (private key encrypted)\n const storageObject = {\n keyHash: session.keyHash,\n publicKey: Array.from(session.publicKey), // Store as array for IndexedDB\n encryptedPrivateKey: Array.from(encryptedPrivateKey),\n expiry: session.expiry,\n maxValue: session.maxValue.toString(), // BigInt as string\n chainScopes: session.chainScopes,\n userKeyHash: session.userKeyHash,\n savedAt: Date.now(),\n };\n \n // Store in IndexedDB\n return new Promise((resolve, reject) => {\n const transaction = this.db!.transaction([STORE_NAME], 'readwrite');\n const store = transaction.objectStore(STORE_NAME);\n const request = store.put(storageObject);\n \n request.onsuccess = () => resolve();\n request.onerror = () => {\n reject(new SessionError(\n 'Failed to save session',\n SessionErrorCode.STORAGE_ERROR,\n request.error\n ));\n };\n });\n } catch (error) {\n if (error instanceof SessionError) {\n throw error;\n }\n throw new SessionError(\n 'Failed to save session',\n SessionErrorCode.STORAGE_ERROR,\n error\n );\n }\n }\n \n /**\n * Load the active session (decrypts private key)\n */\n async load(): Promise<SessionKey | null> {\n try {\n await this.initialize();\n \n if (!this.db) {\n throw new Error('Database not initialized');\n }\n \n // Get all sessions\n const allSessions = await this.getAllSessions();\n \n if (allSessions.length === 0) {\n return null;\n }\n \n // Find the most recent non-expired session\n const now = Date.now();\n const validSessions = allSessions\n .filter(s => s.expiry > now)\n .sort((a, b) => b.savedAt - a.savedAt);\n \n if (validSessions.length === 0) {\n // All sessions expired, clean up\n await this.clear();\n return null;\n }\n \n const stored = validSessions[0];\n \n // Get encryption key\n const key = await this.getEncryptionKey();\n \n // Decrypt private key\n const encryptedPrivateKey = new Uint8Array(stored.encryptedPrivateKey);\n const privateKey = await decrypt(encryptedPrivateKey, key);\n \n // Reconstruct session\n const session: SessionKey = {\n keyHash: stored.keyHash,\n publicKey: new Uint8Array(stored.publicKey),\n privateKey,\n expiry: stored.expiry,\n maxValue: BigInt(stored.maxValue),\n chainScopes: stored.chainScopes,\n userKeyHash: stored.userKeyHash,\n };\n \n return session;\n } catch (error) {\n if (error instanceof SessionError) {\n throw error;\n }\n throw new SessionError(\n 'Failed to load session',\n SessionErrorCode.STORAGE_ERROR,\n error\n );\n }\n }\n \n /**\n * Get all stored sessions (internal helper)\n */\n private async getAllSessions(): Promise<Array<any>> {\n if (!this.db) {\n return [];\n }\n \n return new Promise((resolve, reject) => {\n const transaction = this.db!.transaction([STORE_NAME], 'readonly');\n const store = transaction.objectStore(STORE_NAME);\n const request = store.getAll();\n \n request.onsuccess = () => resolve(request.result || []);\n request.onerror = () => {\n reject(new SessionError(\n 'Failed to get sessions',\n SessionErrorCode.STORAGE_ERROR,\n request.error\n ));\n };\n });\n }\n \n /**\n * Clear all sessions\n */\n async clear(): Promise<void> {\n try {\n await this.initialize();\n \n if (!this.db) {\n return;\n }\n \n return new Promise((resolve, reject) => {\n const transaction = this.db!.transaction([STORE_NAME], 'readwrite');\n const store = transaction.objectStore(STORE_NAME);\n const request = store.clear();\n \n request.onsuccess = () => resolve();\n request.onerror = () => {\n reject(new SessionError(\n 'Failed to clear sessions',\n SessionErrorCode.STORAGE_ERROR,\n request.error\n ));\n };\n });\n } catch (error) {\n if (error instanceof SessionError) {\n throw error;\n }\n throw new SessionError(\n 'Failed to clear sessions',\n SessionErrorCode.STORAGE_ERROR,\n error\n );\n }\n }\n \n /**\n * Check if any session exists\n */\n async exists(): Promise<boolean> {\n try {\n await this.initialize();\n \n if (!this.db) {\n return false;\n }\n \n const sessions = await this.getAllSessions();\n return sessions.length > 0;\n } catch {\n return false;\n }\n }\n \n /**\n * Close database connection\n */\n close(): void {\n if (this.db) {\n this.db.close();\n this.db = null;\n }\n }\n}\n\n// ============================================================================\n// LocalStorage Session Storage (Fallback)\n// ============================================================================\n\n/** LocalStorage key prefix */\nconst STORAGE_KEY_PREFIX = 'veridex-session-';\n\n/**\n * LocalStorage-based session storage with encryption\n * \n * Fallback storage backend when IndexedDB is unavailable.\n * \n * Limitations:\n * - Smaller storage quota (~10MB)\n * - Synchronous API (blocks main thread)\n * - String-based storage (requires serialization)\n */\nexport class LocalStorageSessionStorage implements SessionStorage {\n private encryptionKey: CryptoKey | null = null;\n private credentialId: string;\n private storageKey: string;\n \n /**\n * @param credentialId User's Passkey credential ID (for key derivation)\n */\n constructor(credentialId: string) {\n if (!credentialId) {\n throw new SessionError(\n 'Credential ID required for session storage',\n SessionErrorCode.INVALID_CONFIG\n );\n }\n this.credentialId = credentialId;\n this.storageKey = STORAGE_KEY_PREFIX + ethers.keccak256(ethers.toUtf8Bytes(credentialId));\n }\n \n /**\n * Get or derive encryption key\n */\n private async getEncryptionKey(): Promise<CryptoKey> {\n if (this.encryptionKey) {\n return this.encryptionKey;\n }\n \n this.encryptionKey = await deriveEncryptionKey(this.credentialId);\n return this.encryptionKey;\n }\n \n /**\n * Save a session (encrypts private key)\n */\n async save(session: SessionKey): Promise<void> {\n try {\n // Get encryption key\n const key = await this.getEncryptionKey();\n \n // Encrypt private key\n const encryptedPrivateKey = await encrypt(session.privateKey, key);\n \n // Prepare storage object\n const storageObject = {\n keyHash: session.keyHash,\n publicKey: ethers.hexlify(session.publicKey),\n encryptedPrivateKey: ethers.hexlify(encryptedPrivateKey),\n expiry: session.expiry,\n maxValue: session.maxValue.toString(),\n chainScopes: session.chainScopes,\n userKeyHash: session.userKeyHash,\n savedAt: Date.now(),\n };\n \n // Store as JSON\n localStorage.setItem(this.storageKey, JSON.stringify(storageObject));\n } catch (error) {\n if (error instanceof SessionError) {\n throw error;\n }\n throw new SessionError(\n 'Failed to save session',\n SessionErrorCode.STORAGE_ERROR,\n error\n );\n }\n }\n \n /**\n * Load the active session (decrypts private key)\n */\n async load(): Promise<SessionKey | null> {\n try {\n const data = localStorage.getItem(this.storageKey);\n \n if (!data) {\n return null;\n }\n \n const stored = JSON.parse(data);\n \n // Check if expired\n if (stored.expiry <= Date.now()) {\n await this.clear();\n return null;\n }\n \n // Get encryption key\n const key = await this.getEncryptionKey();\n \n // Decrypt private key\n const encryptedPrivateKey = ethers.getBytes(stored.encryptedPrivateKey);\n const privateKey = await decrypt(encryptedPrivateKey, key);\n \n // Reconstruct session\n const session: SessionKey = {\n keyHash: stored.keyHash,\n publicKey: ethers.getBytes(stored.publicKey),\n privateKey,\n expiry: stored.expiry,\n maxValue: BigInt(stored.maxValue),\n chainScopes: stored.chainScopes,\n userKeyHash: stored.userKeyHash,\n };\n \n return session;\n } catch (error) {\n // Clear corrupted data\n await this.clear();\n \n if (error instanceof SessionError) {\n throw error;\n }\n throw new SessionError(\n 'Failed to load session',\n SessionErrorCode.STORAGE_ERROR,\n error\n );\n }\n }\n \n /**\n * Clear all sessions\n */\n async clear(): Promise<void> {\n try {\n localStorage.removeItem(this.storageKey);\n } catch (error) {\n throw new SessionError(\n 'Failed to clear sessions',\n SessionErrorCode.STORAGE_ERROR,\n error\n );\n }\n }\n \n /**\n * Check if any session exists\n */\n async exists(): Promise<boolean> {\n try {\n return localStorage.getItem(this.storageKey) !== null;\n } catch {\n return false;\n }\n }\n}\n\n// ============================================================================\n// Storage Factory\n// ============================================================================\n\n/**\n * Create appropriate session storage based on environment\n * \n * @param credentialId User's Passkey credential ID\n * @param preferredBackend Preferred storage backend ('indexeddb' or 'localstorage')\n * @returns Session storage implementation\n */\nexport function createSessionStorage(\n credentialId: string,\n preferredBackend?: 'indexeddb' | 'localstorage'\n): SessionStorage {\n // Check if running in browser\n if (typeof window === 'undefined') {\n throw new SessionError(\n 'Session storage requires browser environment',\n SessionErrorCode.STORAGE_ERROR\n );\n }\n \n // Try IndexedDB first (if not explicitly requesting localStorage)\n if (preferredBackend !== 'localstorage' && typeof indexedDB !== 'undefined') {\n try {\n return new IndexedDBSessionStorage(credentialId);\n } catch (error) {\n console.warn('IndexedDB unavailable, falling back to LocalStorage:', error);\n }\n }\n \n // Fallback to LocalStorage\n if (typeof localStorage !== 'undefined') {\n return new LocalStorageSessionStorage(credentialId);\n }\n \n throw new SessionError(\n 'No storage backend available (requires IndexedDB or LocalStorage)',\n SessionErrorCode.STORAGE_ERROR\n );\n}\n","/**\n * Veridex Protocol SDK - EVM Hub Client Adapter\n * \n * Adapts EVMClient to work with SessionManager's HubClient interface.\n * Provides a clean integration layer between session management and chain clients.\n */\n\nimport type { HubClient } from '../../sessions/index.js';\nimport type { RegisterSessionParams, RevokeSessionParams } from '../../types.js';\nimport type { EVMClient } from './EVMClient.js';\nimport type { ethers } from 'ethers';\n\n/**\n * Adapter that makes EVMClient compatible with SessionManager's HubClient interface\n * \n * Usage:\n * ```typescript\n * const hubAdapter = new EVMHubClientAdapter(evmClient, signer);\n * const sessionManager = new SessionManager(\n * credential,\n * hubAdapter,\n * config\n * );\n * ```\n */\nexport class EVMHubClientAdapter implements HubClient {\n constructor(\n private evmClient: EVMClient,\n private signer: ethers.Signer\n ) {}\n \n /**\n * Register a session on the Hub\n * \n * @param params Registration parameters with Passkey signature\n * @returns Promise that resolves when registration completes\n */\n async registerSession(params: RegisterSessionParams): Promise<void> {\n // Call EVMClient's registerSession method\n await this.evmClient.registerSession(params, this.signer);\n }\n \n /**\n * Revoke a session on the Hub\n * \n * @param params Revocation parameters with Passkey signature\n * @returns Promise that resolves when revocation completes\n */\n async revokeSession(params: RevokeSessionParams): Promise<void> {\n // Call EVMClient's revokeSession method\n await this.evmClient.revokeSession(params, this.signer);\n }\n \n /**\n * Update the signer (e.g., when switching accounts)\n * \n * @param signer New Ethereum signer\n */\n updateSigner(signer: ethers.Signer): void {\n this.signer = signer;\n }\n}\n","/**\n * Veridex Solana Program Error Codes\n *\n * Error code constants for parsing and handling Veridex program errors.\n * These codes map directly to the Anchor error enum variants in the\n * Solana program.\n *\n * @packageDocumentation\n */\n\n// ============================================================================\n// Error Code Ranges\n// ============================================================================\n\n/**\n * Error code range boundaries.\n * Use these to categorize errors programmatically.\n */\nexport const ERROR_RANGES = {\n /** Core protocol errors (paused, unauthorized, limits, etc.) */\n CORE: { min: 6000, max: 6099 },\n /** Query execution errors */\n QUERY_EXECUTION: { min: 6100, max: 6149 },\n /** ABI decoding errors */\n ABI: { min: 6150, max: 6199 },\n /** Query parsing/validation errors */\n QUERY_PARSING: { min: 6200, max: 6299 },\n} as const;\n\n// ============================================================================\n// Core Protocol Error Codes (6000-6099)\n// ============================================================================\n\nexport const VERIDEX_ERRORS = {\n // Core Protocol Errors\n /** Protocol is globally paused */\n PROTOCOL_PAUSED: 6000,\n /** Vault is paused */\n VAULT_PAUSED: 6001,\n /** VAA already processed (replay protection) */\n VAA_ALREADY_PROCESSED: 6002,\n /** Invalid emitter chain */\n INVALID_EMITTER_CHAIN: 6003,\n /** Invalid emitter address */\n INVALID_EMITTER: 6004,\n /** Invalid owner */\n INVALID_OWNER: 6005,\n /** Invalid target chain */\n INVALID_TARGET_CHAIN: 6006,\n /** Invalid payload version */\n INVALID_PAYLOAD_VERSION: 6007,\n /** Invalid action payload */\n INVALID_ACTION_PAYLOAD: 6008,\n /** Invalid action type */\n INVALID_ACTION_TYPE: 6009,\n /** Daily limit exceeded */\n DAILY_LIMIT_EXCEEDED: 6010,\n /** Insufficient funds */\n INSUFFICIENT_FUNDS: 6011,\n /** Unauthorized */\n UNAUTHORIZED: 6012,\n /** Invalid VAA */\n INVALID_VAA: 6013,\n /** Token bridge not configured */\n TOKEN_BRIDGE_NOT_CONFIGURED: 6014,\n /** Invalid bridge parameters */\n INVALID_BRIDGE_PARAMS: 6015,\n\n // Query Execution Errors (6100-6149)\n /** Invalid query response format */\n INVALID_QUERY_RESPONSE: 6100,\n /** Query response expired (> 60 seconds old) */\n QUERY_EXPIRED: 6101,\n /** Query signature verification failed */\n QUERY_INVALID: 6102,\n /** Query result doesn't match expected state */\n QUERY_MISMATCH: 6103,\n /** Query block time is in the future */\n QUERY_FUTURE_BLOCK: 6104,\n /** Invalid nonce in query response */\n INVALID_QUERY_NONCE: 6105,\n /** Secp256k1 verification instruction missing */\n SECP256K1_INSTRUCTION_MISSING: 6106,\n /** Invalid secp256k1 instruction format */\n INVALID_SECP256K1_INSTRUCTION: 6107,\n /** Insufficient Guardian signatures on query */\n INSUFFICIENT_SIGNATURES: 6108,\n /** Chain ID mismatch in query response */\n CHAIN_ID_MISMATCH: 6109,\n /** Query result not found */\n QUERY_RESULT_NOT_FOUND: 6110,\n\n // ABI Decoding Errors (6150-6199)\n /** ABI decoding: insufficient data */\n ABI_INSUFFICIENT_DATA: 6150,\n /** ABI decoding: value overflow */\n ABI_OVERFLOW: 6151,\n /** ABI decoding: invalid encoding */\n ABI_INVALID_ENCODING: 6152,\n /** ABI decoding: general failure */\n ABI_DECODING_FAILED: 6153,\n\n // Query Parsing Errors (6200-6299)\n /** Invalid query response format (parsing) */\n QUERY_PARSE_INVALID_RESPONSE: 6200,\n /** Invalid query version */\n QUERY_PARSE_INVALID_VERSION: 6201,\n /** Unsupported query type */\n QUERY_PARSE_UNSUPPORTED_TYPE: 6202,\n /** Query response is stale (parsing) */\n QUERY_PARSE_STALE: 6203,\n /** Query block time is in the future (parsing) */\n QUERY_PARSE_FUTURE_BLOCK: 6204,\n /** Invalid Hub state data */\n QUERY_PARSE_INVALID_HUB_STATE: 6205,\n /** Invalid nonce (parsing) */\n QUERY_PARSE_INVALID_NONCE: 6206,\n /** Query result doesn't match expected (parsing) */\n QUERY_PARSE_MISMATCH: 6207,\n /** Secp256k1 instruction not found (parsing) */\n QUERY_PARSE_SECP256K1_MISSING: 6208,\n /** Invalid Secp256k1 instruction (parsing) */\n QUERY_PARSE_INVALID_SECP256K1: 6209,\n /** Insufficient Guardian signatures (parsing) */\n QUERY_PARSE_INSUFFICIENT_SIGS: 6210,\n /** Invalid Guardian signature (parsing) */\n QUERY_PARSE_INVALID_GUARDIAN_SIG: 6211,\n /** Chain ID mismatch (parsing) */\n QUERY_PARSE_CHAIN_ID_MISMATCH: 6212,\n /** Guardian index out of range */\n QUERY_PARSE_GUARDIAN_INDEX_OOB: 6213,\n /** Non-increasing Guardian index */\n QUERY_PARSE_NON_INCREASING_INDEX: 6214,\n /** Query signature verification failed (parsing) */\n QUERY_PARSE_INVALID_SIGNATURE: 6215,\n /** ABI decoding failed (parsing) */\n QUERY_PARSE_ABI_FAILED: 6216,\n} as const;\n\nexport type VeridexErrorCode = (typeof VERIDEX_ERRORS)[keyof typeof VERIDEX_ERRORS];\n\n// ============================================================================\n// Error Messages\n// ============================================================================\n\n/**\n * Human-readable error messages for each error code.\n */\nexport const ERROR_MESSAGES: Record<VeridexErrorCode, string> = {\n // Core Protocol Errors\n [VERIDEX_ERRORS.PROTOCOL_PAUSED]: \"Protocol is paused\",\n [VERIDEX_ERRORS.VAULT_PAUSED]: \"Vault is paused\",\n [VERIDEX_ERRORS.VAA_ALREADY_PROCESSED]:\n \"This transaction has already been processed\",\n [VERIDEX_ERRORS.INVALID_EMITTER_CHAIN]: \"Invalid emitter chain\",\n [VERIDEX_ERRORS.INVALID_EMITTER]: \"Invalid emitter address\",\n [VERIDEX_ERRORS.INVALID_OWNER]: \"Invalid owner\",\n [VERIDEX_ERRORS.INVALID_TARGET_CHAIN]: \"Invalid target chain\",\n [VERIDEX_ERRORS.INVALID_PAYLOAD_VERSION]: \"Unsupported payload version\",\n [VERIDEX_ERRORS.INVALID_ACTION_PAYLOAD]: \"Invalid action payload\",\n [VERIDEX_ERRORS.INVALID_ACTION_TYPE]: \"Unknown action type\",\n [VERIDEX_ERRORS.DAILY_LIMIT_EXCEEDED]: \"Daily spending limit exceeded\",\n [VERIDEX_ERRORS.INSUFFICIENT_FUNDS]: \"Insufficient funds in vault\",\n [VERIDEX_ERRORS.UNAUTHORIZED]: \"Unauthorized\",\n [VERIDEX_ERRORS.INVALID_VAA]: \"Invalid VAA\",\n [VERIDEX_ERRORS.TOKEN_BRIDGE_NOT_CONFIGURED]: \"Token bridge not configured\",\n [VERIDEX_ERRORS.INVALID_BRIDGE_PARAMS]: \"Invalid bridge parameters\",\n\n // Query Execution Errors\n [VERIDEX_ERRORS.INVALID_QUERY_RESPONSE]: \"Invalid query response format\",\n [VERIDEX_ERRORS.QUERY_EXPIRED]:\n \"Query has expired. Please refresh and try again.\",\n [VERIDEX_ERRORS.QUERY_INVALID]: \"Query signature verification failed\",\n [VERIDEX_ERRORS.QUERY_MISMATCH]: \"Query result does not match expected state\",\n [VERIDEX_ERRORS.QUERY_FUTURE_BLOCK]:\n \"Query block time is in the future. Possible clock skew.\",\n [VERIDEX_ERRORS.INVALID_QUERY_NONCE]: \"Invalid nonce in query response\",\n [VERIDEX_ERRORS.SECP256K1_INSTRUCTION_MISSING]:\n \"Secp256k1 verification instruction missing\",\n [VERIDEX_ERRORS.INVALID_SECP256K1_INSTRUCTION]:\n \"Invalid secp256k1 instruction format\",\n [VERIDEX_ERRORS.INSUFFICIENT_SIGNATURES]:\n \"Insufficient Guardian signatures on query\",\n [VERIDEX_ERRORS.CHAIN_ID_MISMATCH]: \"Chain ID mismatch in query response\",\n [VERIDEX_ERRORS.QUERY_RESULT_NOT_FOUND]: \"Query result not found\",\n\n // ABI Decoding Errors\n [VERIDEX_ERRORS.ABI_INSUFFICIENT_DATA]: \"ABI decoding failed: insufficient data\",\n [VERIDEX_ERRORS.ABI_OVERFLOW]: \"ABI decoding failed: value overflow\",\n [VERIDEX_ERRORS.ABI_INVALID_ENCODING]: \"ABI decoding failed: invalid encoding\",\n [VERIDEX_ERRORS.ABI_DECODING_FAILED]: \"Failed to decode data from Hub\",\n\n // Query Parsing Errors\n [VERIDEX_ERRORS.QUERY_PARSE_INVALID_RESPONSE]: \"Invalid query response format\",\n [VERIDEX_ERRORS.QUERY_PARSE_INVALID_VERSION]: \"Invalid query version\",\n [VERIDEX_ERRORS.QUERY_PARSE_UNSUPPORTED_TYPE]: \"Unsupported query type\",\n [VERIDEX_ERRORS.QUERY_PARSE_STALE]: \"Query response is stale\",\n [VERIDEX_ERRORS.QUERY_PARSE_FUTURE_BLOCK]: \"Query block time is in the future\",\n [VERIDEX_ERRORS.QUERY_PARSE_INVALID_HUB_STATE]: \"Invalid Hub state data\",\n [VERIDEX_ERRORS.QUERY_PARSE_INVALID_NONCE]: \"Invalid nonce in query\",\n [VERIDEX_ERRORS.QUERY_PARSE_MISMATCH]: \"Query result mismatch\",\n [VERIDEX_ERRORS.QUERY_PARSE_SECP256K1_MISSING]: \"Secp256k1 instruction not found\",\n [VERIDEX_ERRORS.QUERY_PARSE_INVALID_SECP256K1]: \"Invalid Secp256k1 instruction\",\n [VERIDEX_ERRORS.QUERY_PARSE_INSUFFICIENT_SIGS]:\n \"Insufficient Guardian signatures\",\n [VERIDEX_ERRORS.QUERY_PARSE_INVALID_GUARDIAN_SIG]: \"Invalid Guardian signature\",\n [VERIDEX_ERRORS.QUERY_PARSE_CHAIN_ID_MISMATCH]: \"Chain ID mismatch\",\n [VERIDEX_ERRORS.QUERY_PARSE_GUARDIAN_INDEX_OOB]: \"Guardian index out of range\",\n [VERIDEX_ERRORS.QUERY_PARSE_NON_INCREASING_INDEX]:\n \"Non-increasing Guardian index\",\n [VERIDEX_ERRORS.QUERY_PARSE_INVALID_SIGNATURE]:\n \"Query signature verification failed\",\n [VERIDEX_ERRORS.QUERY_PARSE_ABI_FAILED]: \"ABI decoding failed\",\n};\n\n// ============================================================================\n// Helper Functions\n// ============================================================================\n\n/**\n * Check if an error code is in the core protocol range.\n */\nexport function isCoreError(code: number): boolean {\n return code >= ERROR_RANGES.CORE.min && code <= ERROR_RANGES.CORE.max;\n}\n\n/**\n * Check if an error code is a query execution error.\n */\nexport function isQueryExecutionError(code: number): boolean {\n return (\n code >= ERROR_RANGES.QUERY_EXECUTION.min &&\n code <= ERROR_RANGES.QUERY_EXECUTION.max\n );\n}\n\n/**\n * Check if an error code is an ABI decoding error.\n */\nexport function isAbiError(code: number): boolean {\n return code >= ERROR_RANGES.ABI.min && code <= ERROR_RANGES.ABI.max;\n}\n\n/**\n * Check if an error code is a query parsing error.\n */\nexport function isQueryParsingError(code: number): boolean {\n return (\n code >= ERROR_RANGES.QUERY_PARSING.min &&\n code <= ERROR_RANGES.QUERY_PARSING.max\n );\n}\n\n/**\n * Check if an error is related to query operations (execution or parsing).\n */\nexport function isQueryError(code: number): boolean {\n return isQueryExecutionError(code) || isQueryParsingError(code);\n}\n\n/**\n * Get the error category as a human-readable string.\n */\nexport function getErrorCategory(code: number): string {\n if (isCoreError(code)) return \"Core Protocol\";\n if (isQueryExecutionError(code)) return \"Query Execution\";\n if (isAbiError(code)) return \"ABI Decoding\";\n if (isQueryParsingError(code)) return \"Query Parsing\";\n return \"Unknown\";\n}\n\n/**\n * Get the human-readable message for an error code.\n */\nexport function getErrorMessage(code: number): string {\n return ERROR_MESSAGES[code as VeridexErrorCode] ?? `Unknown error: ${code}`;\n}\n\n/**\n * Parse an Anchor program error to extract the Veridex error code.\n *\n * @param error - The error object from a failed transaction\n * @returns The error code if found, undefined otherwise\n */\nexport function parseVeridexError(error: unknown): VeridexErrorCode | undefined {\n if (!error || typeof error !== \"object\") return undefined;\n\n // Handle Anchor ProgramError\n const anchorError = error as {\n code?: number;\n error?: { errorCode?: { code?: string; number?: number } };\n };\n\n // Try direct code property\n if (typeof anchorError.code === \"number\") {\n if (anchorError.code in ERROR_MESSAGES) {\n return anchorError.code as VeridexErrorCode;\n }\n }\n\n // Try Anchor v0.30+ error format\n if (anchorError.error?.errorCode?.number !== undefined) {\n const code = anchorError.error.errorCode.number;\n if (code in ERROR_MESSAGES) {\n return code as VeridexErrorCode;\n }\n }\n\n return undefined;\n}\n\n/**\n * Check if the error is a retryable error (e.g., expired query can be refreshed).\n */\nexport function isRetryableError(code: number): boolean {\n const retryableCodes: number[] = [\n VERIDEX_ERRORS.QUERY_EXPIRED,\n VERIDEX_ERRORS.QUERY_PARSE_STALE,\n VERIDEX_ERRORS.QUERY_FUTURE_BLOCK,\n VERIDEX_ERRORS.QUERY_PARSE_FUTURE_BLOCK,\n VERIDEX_ERRORS.QUERY_MISMATCH,\n VERIDEX_ERRORS.QUERY_PARSE_MISMATCH,\n ];\n return retryableCodes.includes(code);\n}\n\n/**\n * Suggested user action for common errors.\n */\nexport function getSuggestedAction(code: number): string {\n switch (code) {\n case VERIDEX_ERRORS.QUERY_EXPIRED:\n case VERIDEX_ERRORS.QUERY_PARSE_STALE:\n return \"The query data has expired. Please refresh and try again.\";\n case VERIDEX_ERRORS.QUERY_FUTURE_BLOCK:\n case VERIDEX_ERRORS.QUERY_PARSE_FUTURE_BLOCK:\n return \"Clock synchronization issue detected. Please wait a moment and retry.\";\n case VERIDEX_ERRORS.INSUFFICIENT_FUNDS:\n return \"Add more funds to your vault before attempting this operation.\";\n case VERIDEX_ERRORS.DAILY_LIMIT_EXCEEDED:\n return \"Daily spending limit exceeded. Wait until tomorrow or increase your limit.\";\n case VERIDEX_ERRORS.PROTOCOL_PAUSED:\n return \"The protocol is temporarily paused. Please try again later.\";\n case VERIDEX_ERRORS.VAULT_PAUSED:\n return \"Your vault is paused. Contact support if this is unexpected.\";\n case VERIDEX_ERRORS.INSUFFICIENT_SIGNATURES:\n case VERIDEX_ERRORS.QUERY_PARSE_INSUFFICIENT_SIGS:\n return \"Waiting for Guardian consensus. Please try again in a few seconds.\";\n default:\n return \"An error occurred. Please try again or contact support.\";\n }\n}\n"],"mappings":"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","names":["ethers","ethers","ethers","ethers","ethers","ethers","ethers","DEFAULT_RPC_URLS","ethers","ethers","sleep","ethers","sleep","ethers","DEFAULT_CONFIG","ethers","ethers","hex","createHash","createHash","createHash","createHash","ethers","formatAmount","isNativeToken","ethers","ethers","VAULT_ABI","ethers","ethers","ethers","Buffer","ethers","Buffer","sleep","ethers","resolveNetwork","a","ethers","axios","Buffer","ethers","PublicKey","EthCallQueryRequest","EthCallQueryResponse","PerChainQueryRequest","QueryRequest","QueryResponse","hexToUint8Array","isValidHexString","resolveNetwork","concatBytes","signaturesToProofBytes","hexToUint8Array","decodeQueryBytes","isValidHexString","Buffer","sleep","withExponentialBackoff","PublicKey","ethers","PerChainQueryRequest","EthCallQueryRequest","chainsOut","QueryRequest","axios","QueryResponse","chainResp","EthCallQueryResponse","blockTime","age","balances","result","ethers","VAULT_FACTORY_ABI","TESTNET_CHAINS","MAINNET_CHAINS","chainConfig","ethers","result","ethers","PROXY_BYTECODE_PREFIX","PROXY_BYTECODE_SUFFIX","ERC20_ABI","HUB_ABI","ethers","address","ethers","ethers","ethers","ethers","ethers","ethers"]}
|