@unicitylabs/sphere-sdk 0.1.0
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/LICENSE +21 -0
- package/README.md +1112 -0
- package/dist/core/index.cjs +7042 -0
- package/dist/core/index.cjs.map +1 -0
- package/dist/core/index.d.cts +2548 -0
- package/dist/core/index.d.ts +2548 -0
- package/dist/core/index.js +6946 -0
- package/dist/core/index.js.map +1 -0
- package/dist/impl/browser/index.cjs +7853 -0
- package/dist/impl/browser/index.cjs.map +1 -0
- package/dist/impl/browser/index.d.cts +3016 -0
- package/dist/impl/browser/index.d.ts +3016 -0
- package/dist/impl/browser/index.js +7841 -0
- package/dist/impl/browser/index.js.map +1 -0
- package/dist/impl/nodejs/index.cjs +1767 -0
- package/dist/impl/nodejs/index.cjs.map +1 -0
- package/dist/impl/nodejs/index.d.cts +1091 -0
- package/dist/impl/nodejs/index.d.ts +1091 -0
- package/dist/impl/nodejs/index.js +1722 -0
- package/dist/impl/nodejs/index.js.map +1 -0
- package/dist/index.cjs +7647 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.cts +10533 -0
- package/dist/index.d.ts +10533 -0
- package/dist/index.js +7523 -0
- package/dist/index.js.map +1 -0
- package/dist/l1/index.cjs +1545 -0
- package/dist/l1/index.cjs.map +1 -0
- package/dist/l1/index.d.cts +705 -0
- package/dist/l1/index.d.ts +705 -0
- package/dist/l1/index.js +1455 -0
- package/dist/l1/index.js.map +1 -0
- package/package.json +140 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../l1/index.ts","../../l1/types.ts","../../core/bech32.ts","../../l1/addressToScriptHash.ts","../../core/crypto.ts","../../l1/crypto.ts","../../l1/address.ts","../../l1/network.ts","../../l1/tx.ts","../../l1/vesting.ts","../../l1/vestingState.ts","../../l1/addressHelpers.ts"],"sourcesContent":["/**\n * L1 SDK - ALPHA blockchain operations\n */\n\n// Types\nexport * from './types';\n\n// Bech32 encoding (from core)\nexport {\n createBech32,\n encodeBech32,\n decodeBech32,\n convertBits,\n CHARSET,\n} from '../core/bech32';\n\n// Address utilities\nexport { addressToScriptHash } from './addressToScriptHash';\n\n// Crypto utilities (from core)\nexport {\n computeHash160,\n hash160,\n hash160ToBytes,\n publicKeyToAddress,\n privateKeyToAddressInfo,\n generateAddressInfo,\n ec,\n} from '../core/crypto';\n\n// Encryption and WIF\nexport {\n encrypt,\n decrypt,\n encryptWallet,\n decryptWallet,\n generatePrivateKey,\n hexToWIF,\n} from './crypto';\n\n// Address derivation\nexport {\n deriveChildKeyBIP32,\n deriveKeyAtPath,\n generateMasterKeyFromSeed,\n generateHDAddressBIP32,\n generateAddressFromMasterKey,\n deriveChildKey,\n generateHDAddress,\n} from './address';\n\n// Network (Fulcrum WebSocket)\nexport {\n connect,\n disconnect,\n rpc,\n isWebSocketConnected,\n waitForConnection,\n getUtxo,\n getBalance,\n broadcast,\n subscribeBlocks,\n getTransactionHistory,\n getTransaction,\n getBlockHeader,\n getCurrentBlockHeight,\n} from './network';\nexport type { BlockHeader, TransactionHistoryItem, TransactionDetail } from './network';\n\n// Transaction building\nexport {\n createScriptPubKey,\n buildSegWitTransaction,\n createAndSignTransaction,\n collectUtxosForAmount,\n createTransactionPlan,\n sendAlpha,\n} from './tx';\n\n// Vesting classification\nexport { vestingClassifier, VESTING_THRESHOLD } from './vesting';\nexport { vestingState } from './vestingState';\n\n// Address helpers\nexport { WalletAddressHelper } from './addressHelpers';\n","export interface Wallet {\n masterPrivateKey: string;\n chainCode?: string;\n addresses: WalletAddress[];\n createdAt?: number;\n isEncrypted?: boolean;\n encryptedMasterKey?: string;\n childPrivateKey?: string | null;\n isImportedAlphaWallet?: boolean;\n masterChainCode?: string | null;\n isBIP32?: boolean;\n descriptorPath?: string | null;\n}\n\nexport interface WalletAddress {\n address: string;\n publicKey?: string;\n privateKey?: string;\n path: string | null;\n index: number;\n createdAt?: string;\n isChange?: boolean; // true for change addresses (BIP32 chain 1)\n}\n\nexport interface StoredWallet {\n key: string;\n data: Wallet;\n}\n\nexport interface TransactionInput {\n txid: string;\n vout: number;\n value: number;\n address: string;\n}\n\nexport interface TransactionOutput {\n value: number;\n address: string;\n}\n\nexport interface Transaction {\n input: TransactionInput;\n outputs: TransactionOutput[];\n fee: number;\n changeAmount: number;\n changeAddress: string;\n}\n\nexport interface TransactionPlan {\n success: boolean;\n transactions: Transaction[];\n error?: string;\n}\n\nexport interface UTXO {\n txid?: string;\n tx_hash?: string;\n vout?: number;\n tx_pos?: number;\n value: number;\n height?: number;\n address?: string;\n}\n\nexport interface RestoreWalletResult {\n success: boolean;\n wallet: Wallet;\n message?: string;\n error?: string;\n /** Indicates that the wallet.dat file is encrypted and requires a password */\n isEncryptedDat?: boolean;\n}\n\nexport interface ExportOptions {\n password?: string;\n filename?: string;\n}\n\n/**\n * JSON Wallet Export Format v1.0\n *\n * Supports multiple wallet sources:\n * - \"mnemonic\": Created from BIP39 mnemonic phrase (new standard)\n * - \"file_bip32\": Imported from file with chain code (BIP32 HD wallet)\n * - \"file_standard\": Imported from file without chain code (HMAC-based)\n * - \"dat_descriptor\": Imported from wallet.dat descriptor wallet\n * - \"dat_hd\": Imported from wallet.dat HD wallet\n * - \"dat_legacy\": Imported from wallet.dat legacy wallet\n */\nexport type WalletJSONSource =\n | \"mnemonic\" // New standard - has mnemonic phrase\n | \"file_bip32\" // Imported from txt with chain code\n | \"file_standard\" // Imported from txt without chain code (HMAC)\n | \"dat_descriptor\" // Imported from wallet.dat (descriptor format)\n | \"dat_hd\" // Imported from wallet.dat (HD format)\n | \"dat_legacy\"; // Imported from wallet.dat (legacy format)\n\nexport type WalletJSONDerivationMode = \"bip32\" | \"wif_hmac\" | \"legacy_hmac\";\n\nexport interface WalletJSONAddress {\n address: string;\n publicKey: string;\n path: string;\n index?: number;\n isChange?: boolean;\n}\n\n/**\n * JSON Wallet Export structure\n */\nexport interface WalletJSON {\n /** Format version */\n version: \"1.0\";\n\n /** Generation timestamp ISO 8601 */\n generated: string;\n\n /** Security warning */\n warning: string;\n\n /** Master private key (hex, 64 chars) */\n masterPrivateKey: string;\n\n /** Master chain code for BIP32 (hex, 64 chars) - optional for HMAC wallets */\n chainCode?: string;\n\n /** BIP39 mnemonic phrase - only present if source is \"mnemonic\" */\n mnemonic?: string;\n\n /** Derivation mode used */\n derivationMode: WalletJSONDerivationMode;\n\n /** Source of the wallet */\n source: WalletJSONSource;\n\n /** First address for verification */\n firstAddress: WalletJSONAddress;\n\n /** Descriptor path for BIP32 wallets (e.g., \"84'/0'/0'\") */\n descriptorPath?: string;\n\n /** Encrypted fields (when password protected) */\n encrypted?: {\n /** Encrypted master private key (AES-256) */\n masterPrivateKey: string;\n /** Encrypted mnemonic (AES-256) - only if source is \"mnemonic\" */\n mnemonic?: string;\n /** Salt used for key derivation */\n salt: string;\n /** Number of PBKDF2 iterations */\n iterations: number;\n };\n\n /** Additional addresses beyond first (optional) */\n addresses?: WalletJSONAddress[];\n}\n\nexport interface WalletJSONExportOptions {\n /** Password for encryption (optional) */\n password?: string;\n /** Include all addresses (default: only first address) */\n includeAllAddresses?: boolean;\n /** Number of addresses to include (if includeAllAddresses is false) */\n addressCount?: number;\n}\n\nexport interface WalletJSONImportResult {\n success: boolean;\n wallet?: Wallet;\n source?: WalletJSONSource;\n derivationMode?: WalletJSONDerivationMode;\n /** Indicates if mnemonic was found in the JSON */\n hasMnemonic?: boolean;\n /** The decrypted mnemonic phrase (if available) */\n mnemonic?: string;\n message?: string;\n error?: string;\n}\n\n// Vesting types\nexport type VestingMode = \"all\" | \"vested\" | \"unvested\";\n\nexport interface ClassifiedUTXO extends UTXO {\n vestingStatus?: \"vested\" | \"unvested\" | \"error\";\n coinbaseHeight?: number | null;\n}\n\nexport interface VestingBalances {\n vested: bigint;\n unvested: bigint;\n all: bigint;\n}\n\nexport interface ClassificationResult {\n isVested: boolean;\n coinbaseHeight: number | null;\n error?: string;\n}\n\n// ==========================================\n// Path-based address utilities\n// ==========================================\n\n/**\n * Parse BIP32 path components from a derivation path string\n * @param path - Full path like \"m/84'/1'/0'/0/5\" or \"m/44'/0'/0'/1/3\"\n * @returns { chain: number, index: number } where chain=0 is external, chain=1 is change\n * Returns null if path is invalid\n *\n * Examples:\n * \"m/84'/1'/0'/0/5\" -> { chain: 0, index: 5 } (external address 5)\n * \"m/84'/1'/0'/1/3\" -> { chain: 1, index: 3 } (change address 3)\n */\nexport function parsePathComponents(path: string): { chain: number; index: number } | null {\n // Match paths like m/84'/1'/0'/0/5 or m/44'/0'/0'/1/3\n const match = path.match(/m\\/\\d+'\\/\\d+'\\/\\d+'\\/(\\d+)\\/(\\d+)/);\n if (!match) return null;\n return { chain: parseInt(match[1], 10), index: parseInt(match[2], 10) };\n}\n\n/**\n * Check if a BIP32 path represents a change address (chain=1)\n * @param path - Full BIP32 path string\n * @returns true if this is a change address path\n */\nexport function isChangePath(path: string): boolean {\n const parsed = parsePathComponents(path);\n return parsed?.chain === 1;\n}\n\n/**\n * Get display-friendly index from path (for UI display only)\n * @param path - Full BIP32 path string\n * @returns The address index number, or 0 if invalid\n */\nexport function getIndexFromPath(path: string): number {\n const parsed = parsePathComponents(path);\n return parsed?.index ?? 0;\n}\n\n/**\n * Convert a BIP32 path to a DOM-safe ID string\n * Replaces characters that are invalid in DOM IDs:\n * - ' (apostrophe) -> 'h' (hardened marker)\n * - / (forward slash) -> '-' (dash)\n *\n * @param path - Full BIP32 path like \"m/84'/1'/0'/0/5\"\n * @returns DOM-safe ID like \"m-84h-1h-0h-0-5\"\n *\n * Examples:\n * \"m/84'/1'/0'/0/5\" -> \"m-84h-1h-0h-0-5\"\n * \"m/44'/0'/0'/1/3\" -> \"m-44h-0h-0h-1-3\"\n */\nexport function pathToDOMId(path: string): string {\n return path.replace(/'/g, \"h\").replace(/\\//g, \"-\");\n}\n\n/**\n * Convert a DOM-safe ID back to a BIP32 path string\n * Reverses the transformation done by pathToDOMId:\n * - 'h' -> ' (apostrophe for hardened)\n * - '-' -> / (forward slash)\n *\n * @param encoded - DOM-safe ID like \"m-84h-1h-0h-0-5\"\n * @returns BIP32 path like \"m/84'/1'/0'/0/5\"\n *\n * Examples:\n * \"m-84h-1h-0h-0-5\" -> \"m/84'/1'/0'/0/5\"\n * \"m-44h-0h-0h-1-3\" -> \"m/44'/0'/0'/1/3\"\n */\nexport function domIdToPath(encoded: string): string {\n // Split by dash, then restore path format\n const parts = encoded.split(\"-\");\n return parts\n .map((part, idx) => {\n if (idx === 0) return part; // 'm' stays as-is\n // Restore hardened marker: ends with 'h' -> ends with \"'\"\n return part.endsWith(\"h\") ? `${part.slice(0, -1)}'` : part;\n })\n .join(\"/\");\n}\n","/**\n * Bech32 Encoding/Decoding\n * BIP-173 implementation for address encoding\n */\n\n// =============================================================================\n// Constants\n// =============================================================================\n\n/** Bech32 character set from BIP-173 */\nexport const CHARSET = 'qpzry9x8gf2tvdw0s3jn54khce6mua7l';\n\n/** Generator polynomial for checksum */\nconst GENERATOR = [0x3b6a57b2, 0x26508e6d, 0x1ea119fa, 0x3d4233dd, 0x2a1462b3];\n\n// =============================================================================\n// Bit Conversion\n// =============================================================================\n\n/**\n * Convert between bit arrays (8→5 or 5→8)\n */\nexport function convertBits(\n data: number[],\n fromBits: number,\n toBits: number,\n pad: boolean\n): number[] | null {\n let acc = 0;\n let bits = 0;\n const ret: number[] = [];\n const maxv = (1 << toBits) - 1;\n\n for (let i = 0; i < data.length; i++) {\n const value = data[i];\n if (value < 0 || value >> fromBits !== 0) return null;\n acc = (acc << fromBits) | value;\n bits += fromBits;\n while (bits >= toBits) {\n bits -= toBits;\n ret.push((acc >> bits) & maxv);\n }\n }\n\n if (pad) {\n if (bits > 0) {\n ret.push((acc << (toBits - bits)) & maxv);\n }\n } else if (bits >= fromBits || (acc << (toBits - bits)) & maxv) {\n return null;\n }\n\n return ret;\n}\n\n// =============================================================================\n// Internal Functions\n// =============================================================================\n\n/**\n * Expand HRP for checksum calculation\n */\nfunction hrpExpand(hrp: string): number[] {\n const ret: number[] = [];\n for (let i = 0; i < hrp.length; i++) ret.push(hrp.charCodeAt(i) >> 5);\n ret.push(0);\n for (let i = 0; i < hrp.length; i++) ret.push(hrp.charCodeAt(i) & 31);\n return ret;\n}\n\n/**\n * Calculate polymod checksum\n */\nfunction bech32Polymod(values: number[]): number {\n let chk = 1;\n for (let p = 0; p < values.length; p++) {\n const top = chk >> 25;\n chk = ((chk & 0x1ffffff) << 5) ^ values[p];\n for (let i = 0; i < 5; i++) {\n if ((top >> i) & 1) chk ^= GENERATOR[i];\n }\n }\n return chk;\n}\n\n/**\n * Create checksum for bech32\n */\nfunction bech32Checksum(hrp: string, data: number[]): number[] {\n const values = hrpExpand(hrp).concat(data).concat([0, 0, 0, 0, 0, 0]);\n const mod = bech32Polymod(values) ^ 1;\n\n const ret: number[] = [];\n for (let p = 0; p < 6; p++) {\n ret.push((mod >> (5 * (5 - p))) & 31);\n }\n return ret;\n}\n\n// =============================================================================\n// Public API\n// =============================================================================\n\n/**\n * Encode data to bech32 address\n *\n * @example\n * ```ts\n * const address = encodeBech32('alpha', 1, pubkeyHash);\n * // 'alpha1qw...'\n * ```\n */\nexport function encodeBech32(\n hrp: string,\n version: number,\n program: Uint8Array\n): string {\n if (version < 0 || version > 16) {\n throw new Error('Invalid witness version');\n }\n\n const converted = convertBits(Array.from(program), 8, 5, true);\n if (!converted) {\n throw new Error('Failed to convert bits');\n }\n\n const data = [version].concat(converted);\n const checksum = bech32Checksum(hrp, data);\n const combined = data.concat(checksum);\n\n let out = hrp + '1';\n for (let i = 0; i < combined.length; i++) {\n out += CHARSET[combined[i]];\n }\n\n return out;\n}\n\n/**\n * Decode bech32 address\n *\n * @example\n * ```ts\n * const result = decodeBech32('alpha1qw...');\n * // { hrp: 'alpha', witnessVersion: 1, data: Uint8Array }\n * ```\n */\nexport function decodeBech32(\n addr: string\n): { hrp: string; witnessVersion: number; data: Uint8Array } | null {\n addr = addr.toLowerCase();\n\n const pos = addr.lastIndexOf('1');\n if (pos < 1) return null;\n\n const hrp = addr.substring(0, pos);\n const dataStr = addr.substring(pos + 1);\n\n const data: number[] = [];\n for (let i = 0; i < dataStr.length; i++) {\n const val = CHARSET.indexOf(dataStr[i]);\n if (val === -1) return null;\n data.push(val);\n }\n\n // Validate checksum\n const checksum = bech32Checksum(hrp, data.slice(0, -6));\n for (let i = 0; i < 6; i++) {\n if (checksum[i] !== data[data.length - 6 + i]) {\n return null;\n }\n }\n\n const version = data[0];\n const program = convertBits(data.slice(1, -6), 5, 8, false);\n if (!program) return null;\n\n return {\n hrp,\n witnessVersion: version,\n data: Uint8Array.from(program),\n };\n}\n\n/**\n * Create address from public key hash\n *\n * @example\n * ```ts\n * const address = createAddress('alpha', pubkeyHash);\n * // 'alpha1...'\n * ```\n */\nexport function createAddress(hrp: string, pubkeyHash: Uint8Array | string): string {\n const hashBytes = typeof pubkeyHash === 'string'\n ? Uint8Array.from(Buffer.from(pubkeyHash, 'hex'))\n : pubkeyHash;\n\n return encodeBech32(hrp, 1, hashBytes);\n}\n\n/**\n * Validate bech32 address\n */\nexport function isValidBech32(addr: string): boolean {\n return decodeBech32(addr) !== null;\n}\n\n/**\n * Get HRP from address\n */\nexport function getAddressHrp(addr: string): string | null {\n const result = decodeBech32(addr);\n return result?.hrp ?? null;\n}\n\n// =============================================================================\n// Aliases for L1 SDK compatibility\n// =============================================================================\n\n/**\n * Alias for encodeBech32 (L1 SDK compatibility)\n */\nexport const createBech32 = encodeBech32;\n","import { decodeBech32 } from \"../core/bech32\";\nimport CryptoJS from \"crypto-js\";\n\n/** Convert bytes to hex */\nfunction bytesToHex(buf: Uint8Array) {\n return Array.from(buf)\n .map((b) => b.toString(16).padStart(2, \"0\"))\n .join(\"\");\n}\n\n/**\n * Convert \"alpha1xxxx\" Bech32 → Electrum script hash\n * Required for:\n * - blockchain.scripthash.get_history\n * - blockchain.scripthash.listunspent\n */\nexport function addressToScriptHash(address: string): string {\n const decoded = decodeBech32(address);\n if (!decoded) throw new Error(\"Invalid bech32 address: \" + address);\n\n // witness program always starts with OP_0 + PUSH20 (for P2WPKH)\n const scriptHex = \"0014\" + bytesToHex(decoded.data);\n\n // SHA256\n const sha = CryptoJS.SHA256(CryptoJS.enc.Hex.parse(scriptHex)).toString();\n\n // Electrum requires reversed byte order\n return sha.match(/../g)!.reverse().join(\"\");\n}\n","/**\n * Cryptographic utilities for SDK2\n *\n * Provides BIP39 mnemonic and BIP32 key derivation functions.\n * Platform-independent - no browser-specific APIs.\n */\n\nimport * as bip39 from 'bip39';\nimport CryptoJS from 'crypto-js';\nimport elliptic from 'elliptic';\nimport { encodeBech32 } from './bech32';\n\n// =============================================================================\n// Constants\n// =============================================================================\n\nconst ec = new elliptic.ec('secp256k1');\n\n/** secp256k1 curve order */\nconst CURVE_ORDER = BigInt(\n '0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141'\n);\n\n/** Default derivation path for Unicity (BIP44) */\nexport const DEFAULT_DERIVATION_PATH = \"m/44'/0'/0'\";\n\n// =============================================================================\n// Types\n// =============================================================================\n\nexport interface MasterKey {\n privateKey: string;\n chainCode: string;\n}\n\nexport interface DerivedKey {\n privateKey: string;\n chainCode: string;\n}\n\nexport interface KeyPair {\n privateKey: string;\n publicKey: string;\n}\n\nexport interface AddressInfo extends KeyPair {\n address: string;\n path: string;\n index: number;\n}\n\n// =============================================================================\n// BIP39 Mnemonic Functions\n// =============================================================================\n\n/**\n * Generate a new BIP39 mnemonic phrase\n * @param strength - Entropy bits (128 = 12 words, 256 = 24 words)\n */\nexport function generateMnemonic(strength: 128 | 256 = 128): string {\n return bip39.generateMnemonic(strength);\n}\n\n/**\n * Validate a BIP39 mnemonic phrase\n */\nexport function validateMnemonic(mnemonic: string): boolean {\n return bip39.validateMnemonic(mnemonic);\n}\n\n/**\n * Convert mnemonic to seed (64-byte hex string)\n * @param mnemonic - BIP39 mnemonic phrase\n * @param passphrase - Optional passphrase for additional security\n */\nexport async function mnemonicToSeed(\n mnemonic: string,\n passphrase: string = ''\n): Promise<string> {\n const seedBuffer = await bip39.mnemonicToSeed(mnemonic, passphrase);\n return Buffer.from(seedBuffer).toString('hex');\n}\n\n/**\n * Synchronous version of mnemonicToSeed\n */\nexport function mnemonicToSeedSync(\n mnemonic: string,\n passphrase: string = ''\n): string {\n const seedBuffer = bip39.mnemonicToSeedSync(mnemonic, passphrase);\n return Buffer.from(seedBuffer).toString('hex');\n}\n\n/**\n * Convert mnemonic to entropy (for recovery purposes)\n */\nexport function mnemonicToEntropy(mnemonic: string): string {\n return bip39.mnemonicToEntropy(mnemonic);\n}\n\n/**\n * Convert entropy to mnemonic\n */\nexport function entropyToMnemonic(entropy: string): string {\n return bip39.entropyToMnemonic(entropy);\n}\n\n// =============================================================================\n// BIP32 Key Derivation\n// =============================================================================\n\n/**\n * Generate master key from seed (BIP32 standard)\n * Uses HMAC-SHA512 with key \"Bitcoin seed\"\n */\nexport function generateMasterKey(seedHex: string): MasterKey {\n const I = CryptoJS.HmacSHA512(\n CryptoJS.enc.Hex.parse(seedHex),\n CryptoJS.enc.Utf8.parse('Bitcoin seed')\n ).toString();\n\n const IL = I.substring(0, 64); // Left 32 bytes - master private key\n const IR = I.substring(64); // Right 32 bytes - master chain code\n\n // Validate master key\n const masterKeyBigInt = BigInt('0x' + IL);\n if (masterKeyBigInt === 0n || masterKeyBigInt >= CURVE_ORDER) {\n throw new Error('Invalid master key generated');\n }\n\n return {\n privateKey: IL,\n chainCode: IR,\n };\n}\n\n/**\n * Derive child key using BIP32 standard\n * @param parentPrivKey - Parent private key (64 hex chars)\n * @param parentChainCode - Parent chain code (64 hex chars)\n * @param index - Child index (>= 0x80000000 for hardened)\n */\nexport function deriveChildKey(\n parentPrivKey: string,\n parentChainCode: string,\n index: number\n): DerivedKey {\n const isHardened = index >= 0x80000000;\n let data: string;\n\n if (isHardened) {\n // Hardened derivation: 0x00 || parentPrivKey || index\n const indexHex = index.toString(16).padStart(8, '0');\n data = '00' + parentPrivKey + indexHex;\n } else {\n // Non-hardened derivation: compressedPubKey || index\n const keyPair = ec.keyFromPrivate(parentPrivKey, 'hex');\n const compressedPubKey = keyPair.getPublic(true, 'hex');\n const indexHex = index.toString(16).padStart(8, '0');\n data = compressedPubKey + indexHex;\n }\n\n // HMAC-SHA512 with chain code as key\n const I = CryptoJS.HmacSHA512(\n CryptoJS.enc.Hex.parse(data),\n CryptoJS.enc.Hex.parse(parentChainCode)\n ).toString();\n\n const IL = I.substring(0, 64); // Left 32 bytes\n const IR = I.substring(64); // Right 32 bytes (new chain code)\n\n // Add IL to parent key mod n (curve order)\n const ilBigInt = BigInt('0x' + IL);\n const parentKeyBigInt = BigInt('0x' + parentPrivKey);\n\n // Check IL is valid (less than curve order)\n if (ilBigInt >= CURVE_ORDER) {\n throw new Error('Invalid key: IL >= curve order');\n }\n\n const childKeyBigInt = (ilBigInt + parentKeyBigInt) % CURVE_ORDER;\n\n // Check child key is valid (not zero)\n if (childKeyBigInt === 0n) {\n throw new Error('Invalid key: child key is zero');\n }\n\n const childPrivKey = childKeyBigInt.toString(16).padStart(64, '0');\n\n return {\n privateKey: childPrivKey,\n chainCode: IR,\n };\n}\n\n/**\n * Derive key at a full BIP32/BIP44 path\n * @param masterPrivKey - Master private key\n * @param masterChainCode - Master chain code\n * @param path - BIP44 path like \"m/44'/0'/0'/0/0\"\n */\nexport function deriveKeyAtPath(\n masterPrivKey: string,\n masterChainCode: string,\n path: string\n): DerivedKey {\n const pathParts = path.replace('m/', '').split('/');\n\n let currentKey = masterPrivKey;\n let currentChainCode = masterChainCode;\n\n for (const part of pathParts) {\n const isHardened = part.endsWith(\"'\") || part.endsWith('h');\n const indexStr = part.replace(/['h]$/, '');\n let index = parseInt(indexStr, 10);\n\n if (isHardened) {\n index += 0x80000000; // Add hardened offset\n }\n\n const derived = deriveChildKey(currentKey, currentChainCode, index);\n currentKey = derived.privateKey;\n currentChainCode = derived.chainCode;\n }\n\n return {\n privateKey: currentKey,\n chainCode: currentChainCode,\n };\n}\n\n// =============================================================================\n// Key Pair Operations\n// =============================================================================\n\n/**\n * Get public key from private key\n * @param privateKey - Private key as hex string\n * @param compressed - Return compressed public key (default: true)\n */\nexport function getPublicKey(privateKey: string, compressed: boolean = true): string {\n const keyPair = ec.keyFromPrivate(privateKey, 'hex');\n return keyPair.getPublic(compressed, 'hex');\n}\n\n/**\n * Create key pair from private key\n */\nexport function createKeyPair(privateKey: string): KeyPair {\n return {\n privateKey,\n publicKey: getPublicKey(privateKey),\n };\n}\n\n// =============================================================================\n// Hash Functions\n// =============================================================================\n\n/**\n * Compute SHA256 hash\n */\nexport function sha256(data: string, inputEncoding: 'hex' | 'utf8' = 'hex'): string {\n const parsed =\n inputEncoding === 'hex'\n ? CryptoJS.enc.Hex.parse(data)\n : CryptoJS.enc.Utf8.parse(data);\n return CryptoJS.SHA256(parsed).toString();\n}\n\n/**\n * Compute RIPEMD160 hash\n */\nexport function ripemd160(data: string, inputEncoding: 'hex' | 'utf8' = 'hex'): string {\n const parsed =\n inputEncoding === 'hex'\n ? CryptoJS.enc.Hex.parse(data)\n : CryptoJS.enc.Utf8.parse(data);\n return CryptoJS.RIPEMD160(parsed).toString();\n}\n\n/**\n * Compute HASH160 (SHA256 -> RIPEMD160)\n */\nexport function hash160(data: string): string {\n const sha = sha256(data, 'hex');\n return ripemd160(sha, 'hex');\n}\n\n/**\n * Compute double SHA256\n */\nexport function doubleSha256(data: string, inputEncoding: 'hex' | 'utf8' = 'hex'): string {\n const first = sha256(data, inputEncoding);\n return sha256(first, 'hex');\n}\n\n/**\n * Alias for hash160 (L1 SDK compatibility)\n */\nexport const computeHash160 = hash160;\n\n/**\n * Convert hex string to Uint8Array for witness program\n */\nexport function hash160ToBytes(hash160Hex: string): Uint8Array {\n const matches = hash160Hex.match(/../g);\n if (!matches) return new Uint8Array(0);\n return Uint8Array.from(matches.map((x) => parseInt(x, 16)));\n}\n\n/**\n * Generate bech32 address from public key\n * @param publicKey - Compressed public key as hex string\n * @param prefix - Address prefix (default: \"alpha\")\n * @param witnessVersion - Witness version (default: 0 for P2WPKH)\n * @returns Bech32 encoded address\n */\nexport function publicKeyToAddress(\n publicKey: string,\n prefix: string = 'alpha',\n witnessVersion: number = 0\n): string {\n const pubKeyHash = hash160(publicKey);\n const programBytes = hash160ToBytes(pubKeyHash);\n return encodeBech32(prefix, witnessVersion, programBytes);\n}\n\n/**\n * Get address info from private key\n */\nexport function privateKeyToAddressInfo(\n privateKey: string,\n prefix: string = 'alpha'\n): { address: string; publicKey: string } {\n const publicKey = getPublicKey(privateKey);\n const address = publicKeyToAddress(publicKey, prefix);\n return { address, publicKey };\n}\n\n// =============================================================================\n// Utility Functions\n// =============================================================================\n\n/**\n * Convert hex string to Uint8Array\n */\nexport function hexToBytes(hex: string): Uint8Array {\n const matches = hex.match(/../g);\n if (!matches) {\n return new Uint8Array(0);\n }\n return Uint8Array.from(matches.map((x) => parseInt(x, 16)));\n}\n\n/**\n * Convert Uint8Array to hex string\n */\nexport function bytesToHex(bytes: Uint8Array): string {\n return Array.from(bytes)\n .map((b) => b.toString(16).padStart(2, '0'))\n .join('');\n}\n\n/**\n * Generate random bytes as hex string\n */\nexport function randomBytes(length: number): string {\n const words = CryptoJS.lib.WordArray.random(length);\n return words.toString(CryptoJS.enc.Hex);\n}\n\n// =============================================================================\n// High-Level Functions\n// =============================================================================\n\n/**\n * Generate identity from mnemonic\n * Returns master key derived from mnemonic seed\n */\nexport async function identityFromMnemonic(\n mnemonic: string,\n passphrase: string = ''\n): Promise<MasterKey> {\n if (!validateMnemonic(mnemonic)) {\n throw new Error('Invalid mnemonic phrase');\n }\n const seedHex = await mnemonicToSeed(mnemonic, passphrase);\n return generateMasterKey(seedHex);\n}\n\n/**\n * Synchronous version of identityFromMnemonic\n */\nexport function identityFromMnemonicSync(\n mnemonic: string,\n passphrase: string = ''\n): MasterKey {\n if (!validateMnemonic(mnemonic)) {\n throw new Error('Invalid mnemonic phrase');\n }\n const seedHex = mnemonicToSeedSync(mnemonic, passphrase);\n return generateMasterKey(seedHex);\n}\n\n/**\n * Derive address info at a specific path\n * @param masterKey - Master key with privateKey and chainCode\n * @param basePath - Base derivation path (e.g., \"m/44'/0'/0'\")\n * @param index - Address index\n * @param isChange - Whether this is a change address (chain 1 vs 0)\n * @param prefix - Address prefix (default: \"alpha\")\n */\nexport function deriveAddressInfo(\n masterKey: MasterKey,\n basePath: string,\n index: number,\n isChange: boolean = false,\n prefix: string = 'alpha'\n): AddressInfo {\n const chain = isChange ? 1 : 0;\n const fullPath = `${basePath}/${chain}/${index}`;\n\n const derived = deriveKeyAtPath(masterKey.privateKey, masterKey.chainCode, fullPath);\n const publicKey = getPublicKey(derived.privateKey);\n const address = publicKeyToAddress(publicKey, prefix);\n\n return {\n privateKey: derived.privateKey,\n publicKey,\n address,\n path: fullPath,\n index,\n };\n}\n\n/**\n * Generate full address info from private key with index and path\n * (L1 SDK compatibility)\n */\nexport function generateAddressInfo(\n privateKey: string,\n index: number,\n path: string,\n prefix: string = 'alpha'\n): AddressInfo {\n const { address, publicKey } = privateKeyToAddressInfo(privateKey, prefix);\n return {\n privateKey,\n publicKey,\n address,\n path,\n index,\n };\n}\n\n// Re-export elliptic instance for advanced use cases\nexport { ec };\n","import CryptoJS from \"crypto-js\";\n\nconst SALT = \"alpha_wallet_salt\";\nconst PBKDF2_ITERATIONS = 100000;\n\nexport function encrypt(text: string, password: string): string {\n return CryptoJS.AES.encrypt(text, password).toString();\n}\n\nexport function decrypt(encrypted: string, password: string): string {\n const bytes = CryptoJS.AES.decrypt(encrypted, password);\n return bytes.toString(CryptoJS.enc.Utf8);\n}\n\nexport function generatePrivateKey(): string {\n return CryptoJS.lib.WordArray.random(32).toString();\n}\n\n/**\n * Encrypt wallet master key with password using PBKDF2 + AES\n */\nexport function encryptWallet(\n masterPrivateKey: string,\n password: string\n): string {\n const passwordKey = CryptoJS.PBKDF2(password, SALT, {\n keySize: 256 / 32,\n iterations: PBKDF2_ITERATIONS,\n }).toString();\n\n const encrypted = CryptoJS.AES.encrypt(\n masterPrivateKey,\n passwordKey\n ).toString();\n\n return encrypted;\n}\n\n/**\n * Decrypt wallet master key with password\n */\nexport function decryptWallet(\n encryptedData: string,\n password: string\n): string {\n const passwordKey = CryptoJS.PBKDF2(password, SALT, {\n keySize: 256 / 32,\n iterations: PBKDF2_ITERATIONS,\n }).toString();\n\n const decrypted = CryptoJS.AES.decrypt(encryptedData, passwordKey);\n return decrypted.toString(CryptoJS.enc.Utf8);\n}\n\n/**\n * Convert hex private key to WIF format\n */\nexport function hexToWIF(hexKey: string): string {\n // Alpha mainnet version byte is 0x80\n const versionByte = \"80\";\n const extendedKey = versionByte + hexKey;\n\n // Calculate checksum\n const hash1 = CryptoJS.SHA256(CryptoJS.enc.Hex.parse(extendedKey)).toString();\n const hash2 = CryptoJS.SHA256(CryptoJS.enc.Hex.parse(hash1)).toString();\n const checksum = hash2.substring(0, 8);\n\n // Combine and encode\n const finalHex = extendedKey + checksum;\n\n // Convert to Base58\n return base58Encode(finalHex);\n}\n\n/**\n * Base58 encoding\n */\nfunction base58Encode(hex: string): string {\n const ALPHABET = \"123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz\";\n\n // Convert hex to big integer\n let num = BigInt(\"0x\" + hex);\n let encoded = \"\";\n\n while (num > 0n) {\n const remainder = Number(num % 58n);\n num = num / 58n;\n encoded = ALPHABET[remainder] + encoded;\n }\n\n // Add leading 1s for leading 0s in hex\n for (let i = 0; i < hex.length && hex.substring(i, i + 2) === \"00\"; i += 2) {\n encoded = \"1\" + encoded;\n }\n\n return encoded;\n}\n","/**\n * L1 Address Derivation\n *\n * Uses core crypto functions for standard BIP32 derivation,\n * plus legacy functions for backward compatibility with old wallets.\n */\n\nimport CryptoJS from 'crypto-js';\nimport {\n deriveChildKey as coreDeriveChildKey,\n deriveKeyAtPath as coreDeriveKeyAtPath,\n generateMasterKey,\n generateAddressInfo,\n ec,\n} from '../core/crypto';\n\n// Re-export core functions with L1 naming conventions\nexport { ec };\n\n/**\n * Standard BIP32 child key derivation\n * Re-export from core with L1 naming convention\n */\nexport const deriveChildKeyBIP32 = coreDeriveChildKey;\n\n/**\n * Derive key at a full BIP44 path\n * Re-export from core\n */\nexport const deriveKeyAtPath = coreDeriveKeyAtPath;\n\n/**\n * Generate master key and chain code from seed (BIP32 standard)\n * Wrapper around core function with L1 return type naming\n */\nexport function generateMasterKeyFromSeed(seedHex: string): {\n masterPrivateKey: string;\n masterChainCode: string;\n} {\n const result = generateMasterKey(seedHex);\n return {\n masterPrivateKey: result.privateKey,\n masterChainCode: result.chainCode,\n };\n}\n\n/**\n * Generate HD address using standard BIP32\n * Standard path: m/44'/0'/0'/0/{index} (external chain, non-hardened)\n * For change addresses, use isChange = true to get m/44'/0'/0'/1/{index}\n */\nexport function generateHDAddressBIP32(\n masterPriv: string,\n chainCode: string,\n index: number,\n basePath: string = \"m/44'/0'/0'\",\n isChange: boolean = false\n) {\n // Chain: 0 = external (receiving), 1 = internal (change)\n const chain = isChange ? 1 : 0;\n const fullPath = `${basePath}/${chain}/${index}`;\n\n const derived = coreDeriveKeyAtPath(masterPriv, chainCode, fullPath);\n\n return generateAddressInfo(derived.privateKey, index, fullPath);\n}\n\n// ============================================\n// Original index.html compatible derivation\n// ============================================\n\n/**\n * Generate address from master private key using HMAC-SHA512 derivation\n * This matches exactly the original index.html implementation\n * NOTE: This is NON-STANDARD derivation for legacy wallet compatibility\n *\n * @param masterPrivateKey - 32-byte hex private key (64 chars)\n * @param index - Address index\n */\nexport function generateAddressFromMasterKey(\n masterPrivateKey: string,\n index: number\n) {\n const derivationPath = `m/44'/0'/${index}'`;\n\n // HMAC-SHA512 with path as key (matching index.html exactly)\n const hmacInput = CryptoJS.enc.Hex.parse(masterPrivateKey);\n const hmacKey = CryptoJS.enc.Utf8.parse(derivationPath);\n const hmacOutput = CryptoJS.HmacSHA512(hmacInput, hmacKey).toString();\n\n // Use left 32 bytes for private key\n const childPrivateKey = hmacOutput.substring(0, 64);\n\n return generateAddressInfo(childPrivateKey, index, derivationPath);\n}\n\n// ============================================\n// Legacy functions for backward compatibility\n// ============================================\n\n/**\n * @deprecated Use deriveChildKeyBIP32 for new wallets\n * Legacy HMAC-SHA512 derivation (non-standard)\n * Kept for backward compatibility with old wallets\n */\nexport function deriveChildKey(\n masterPriv: string,\n chainCode: string,\n index: number\n) {\n const data = masterPriv + index.toString(16).padStart(8, '0');\n\n const I = CryptoJS.HmacSHA512(\n CryptoJS.enc.Hex.parse(data),\n CryptoJS.enc.Hex.parse(chainCode)\n ).toString();\n\n return {\n privateKey: I.substring(0, 64),\n nextChainCode: I.substring(64),\n };\n}\n\n/**\n * @deprecated Use generateHDAddressBIP32 for new wallets\n * Legacy HD address generation (non-standard derivation)\n */\nexport function generateHDAddress(\n masterPriv: string,\n chainCode: string,\n index: number\n) {\n const child = deriveChildKey(masterPriv, chainCode, index);\n const path = `m/44'/0'/0'/${index}`;\n\n return generateAddressInfo(child.privateKey, index, path);\n}\n","// L1 Network - Fulcrum WebSocket client\n\nimport { addressToScriptHash } from './addressToScriptHash';\nimport type { UTXO } from './types';\n\nconst DEFAULT_ENDPOINT = 'wss://fulcrum.unicity.network:50004';\n\ninterface PendingRequest {\n resolve: (result: unknown) => void;\n reject: (err: unknown) => void;\n}\n\nexport interface BlockHeader {\n height: number;\n hex: string;\n [key: string]: unknown;\n}\n\ninterface BalanceResult {\n confirmed: number;\n unconfirmed: number;\n}\n\nlet ws: WebSocket | null = null;\nlet isConnected = false;\nlet isConnecting = false;\nlet requestId = 0;\nlet intentionalClose = false;\nlet reconnectAttempts = 0;\nlet isBlockSubscribed = false;\nlet lastBlockHeader: BlockHeader | null = null;\n\n// Store timeout IDs for pending requests\ninterface PendingRequestWithTimeout extends PendingRequest {\n timeoutId?: ReturnType<typeof setTimeout>;\n}\n\nconst pending: Record<number, PendingRequestWithTimeout> = {};\nconst blockSubscribers: ((header: BlockHeader) => void)[] = [];\n\n// Connection state callbacks with cleanup support\ninterface ConnectionCallback {\n resolve: () => void;\n reject: (err: Error) => void;\n timeoutId?: ReturnType<typeof setTimeout>;\n}\nconst connectionCallbacks: ConnectionCallback[] = [];\n\n// Reconnect configuration\nconst MAX_RECONNECT_ATTEMPTS = 10;\nconst BASE_DELAY = 2000;\nconst MAX_DELAY = 60000; // 1 minute\n\n// Timeout configuration\nconst RPC_TIMEOUT = 30000; // 30 seconds\nconst CONNECTION_TIMEOUT = 30000; // 30 seconds\n\n// ----------------------------------------\n// CONNECTION STATE\n// ----------------------------------------\nexport function isWebSocketConnected(): boolean {\n return isConnected && ws !== null && ws.readyState === WebSocket.OPEN;\n}\n\nexport function waitForConnection(): Promise<void> {\n if (isWebSocketConnected()) {\n return Promise.resolve();\n }\n\n return new Promise((resolve, reject) => {\n const callback: ConnectionCallback = {\n resolve: () => {\n if (callback.timeoutId) clearTimeout(callback.timeoutId);\n resolve();\n },\n reject: (err: Error) => {\n if (callback.timeoutId) clearTimeout(callback.timeoutId);\n reject(err);\n },\n };\n\n callback.timeoutId = setTimeout(() => {\n // Remove from callbacks array\n const idx = connectionCallbacks.indexOf(callback);\n if (idx > -1) connectionCallbacks.splice(idx, 1);\n reject(new Error('Connection timeout'));\n }, CONNECTION_TIMEOUT);\n\n connectionCallbacks.push(callback);\n });\n}\n\n// ----------------------------------------\n// SINGLETON CONNECT — prevents double connect\n// ----------------------------------------\nexport function connect(endpoint: string = DEFAULT_ENDPOINT): Promise<void> {\n if (isConnected) {\n return Promise.resolve();\n }\n\n if (isConnecting) {\n return waitForConnection();\n }\n\n isConnecting = true;\n\n return new Promise((resolve, reject) => {\n let hasResolved = false;\n\n try {\n ws = new WebSocket(endpoint);\n } catch (err) {\n console.error('[L1] WebSocket constructor threw exception:', err);\n isConnecting = false;\n reject(err);\n return;\n }\n\n ws.onopen = () => {\n isConnected = true;\n isConnecting = false;\n reconnectAttempts = 0; // Reset reconnect counter on successful connection\n hasResolved = true;\n resolve();\n\n // Notify all waiting callbacks (clear their timeouts first)\n connectionCallbacks.forEach((cb) => {\n if (cb.timeoutId) clearTimeout(cb.timeoutId);\n cb.resolve();\n });\n connectionCallbacks.length = 0;\n };\n\n ws.onclose = () => {\n isConnected = false;\n isBlockSubscribed = false; // Reset block subscription on disconnect\n\n // Reject all pending requests and clear their timeouts\n Object.values(pending).forEach((req) => {\n if (req.timeoutId) clearTimeout(req.timeoutId);\n req.reject(new Error('WebSocket connection closed'));\n });\n Object.keys(pending).forEach((key) => delete pending[Number(key)]);\n\n // Don't reconnect if this was an intentional close\n if (intentionalClose) {\n intentionalClose = false;\n isConnecting = false;\n reconnectAttempts = 0;\n\n // Reject if we haven't resolved yet\n if (!hasResolved) {\n hasResolved = true;\n reject(new Error('WebSocket connection closed intentionally'));\n }\n return;\n }\n\n // Check if we've exceeded max reconnect attempts\n if (reconnectAttempts >= MAX_RECONNECT_ATTEMPTS) {\n console.error('[L1] Max reconnect attempts reached. Giving up.');\n isConnecting = false;\n\n // Reject all waiting callbacks\n const error = new Error('Max reconnect attempts reached');\n connectionCallbacks.forEach((cb) => {\n if (cb.timeoutId) clearTimeout(cb.timeoutId);\n cb.reject(error);\n });\n connectionCallbacks.length = 0;\n\n // Reject if we haven't resolved yet\n if (!hasResolved) {\n hasResolved = true;\n reject(error);\n }\n return;\n }\n\n // Calculate exponential backoff delay\n const delay = Math.min(BASE_DELAY * Math.pow(2, reconnectAttempts), MAX_DELAY);\n\n reconnectAttempts++;\n console.warn(\n `[L1] WebSocket closed unexpectedly. Reconnecting in ${delay}ms (attempt ${reconnectAttempts}/${MAX_RECONNECT_ATTEMPTS})...`\n );\n\n // Keep isConnecting true so callers know reconnection is in progress\n // The resolve/reject will happen when reconnection succeeds or fails\n setTimeout(() => {\n connect(endpoint)\n .then(() => {\n if (!hasResolved) {\n hasResolved = true;\n resolve();\n }\n })\n .catch((err) => {\n if (!hasResolved) {\n hasResolved = true;\n reject(err);\n }\n });\n }, delay);\n };\n\n ws.onerror = (err: Event) => {\n console.error('[L1] WebSocket error:', err);\n // Note: Browser WebSocket errors don't provide detailed error info for security reasons\n // The actual connection error details are only visible in browser DevTools Network tab\n // Error alone doesn't mean connection failed - onclose will be called\n };\n\n ws.onmessage = (msg) => handleMessage(msg);\n });\n}\n\nfunction handleMessage(event: MessageEvent) {\n const data = JSON.parse(event.data);\n\n if (data.id && pending[data.id]) {\n const request = pending[data.id];\n delete pending[data.id];\n if (data.error) {\n request.reject(data.error);\n } else {\n request.resolve(data.result);\n }\n }\n\n if (data.method === 'blockchain.headers.subscribe') {\n const header = data.params[0] as BlockHeader;\n lastBlockHeader = header; // Cache for late subscribers\n blockSubscribers.forEach((cb) => cb(header));\n }\n}\n\n// ----------------------------------------\n// SAFE RPC - Auto-connects and waits if needed\n// ----------------------------------------\nexport async function rpc(method: string, params: unknown[] = []): Promise<unknown> {\n // Auto-connect if not connected\n if (!isConnected && !isConnecting) {\n await connect();\n }\n\n // Wait for connection if connecting\n if (!isWebSocketConnected()) {\n await waitForConnection();\n }\n\n return new Promise((resolve, reject) => {\n if (!ws || ws.readyState !== WebSocket.OPEN) {\n return reject(new Error('WebSocket not connected (OPEN)'));\n }\n\n const id = ++requestId;\n\n // Set up timeout for this request\n const timeoutId = setTimeout(() => {\n if (pending[id]) {\n delete pending[id];\n reject(new Error(`RPC timeout: ${method}`));\n }\n }, RPC_TIMEOUT);\n\n pending[id] = {\n resolve: (result) => {\n clearTimeout(timeoutId);\n resolve(result);\n },\n reject: (err) => {\n clearTimeout(timeoutId);\n reject(err);\n },\n timeoutId,\n };\n\n ws.send(JSON.stringify({ jsonrpc: '2.0', id, method, params }));\n });\n}\n\n// ----------------------------------------\n// API METHODS\n// ----------------------------------------\n\nexport async function getUtxo(address: string) {\n const scripthash = addressToScriptHash(address);\n\n const result = await rpc('blockchain.scripthash.listunspent', [scripthash]);\n\n if (!Array.isArray(result)) {\n console.warn('listunspent returned non-array:', result);\n return [];\n }\n\n return result.map((u: UTXO) => ({\n tx_hash: u.tx_hash,\n tx_pos: u.tx_pos,\n value: u.value,\n height: u.height,\n address,\n }));\n}\n\nexport async function getBalance(address: string) {\n const scriptHash = addressToScriptHash(address);\n const result = (await rpc('blockchain.scripthash.get_balance', [scriptHash])) as BalanceResult;\n\n const confirmed = result.confirmed || 0;\n const unconfirmed = result.unconfirmed || 0;\n\n const totalSats = confirmed + unconfirmed;\n\n // Convert sats → ALPHA\n const alpha = totalSats / 100_000_000;\n\n return alpha;\n}\n\nexport async function broadcast(rawHex: string) {\n return await rpc('blockchain.transaction.broadcast', [rawHex]);\n}\n\nexport async function subscribeBlocks(cb: (header: BlockHeader) => void): Promise<() => void> {\n // Auto-connect if not connected (same as rpc())\n if (!isConnected && !isConnecting) {\n await connect();\n }\n\n // Wait for connection to be established\n if (!isWebSocketConnected()) {\n await waitForConnection();\n }\n\n blockSubscribers.push(cb);\n\n // Only send RPC subscription if not already subscribed\n // This prevents duplicate server-side subscriptions\n if (!isBlockSubscribed) {\n isBlockSubscribed = true;\n const header = (await rpc('blockchain.headers.subscribe', [])) as BlockHeader;\n if (header) {\n lastBlockHeader = header;\n // Notify ALL current subscribers with the initial header\n blockSubscribers.forEach((subscriber) => subscriber(header));\n }\n } else if (lastBlockHeader) {\n // For late subscribers, immediately notify with cached header\n cb(lastBlockHeader);\n }\n\n // Return unsubscribe function\n return () => {\n const index = blockSubscribers.indexOf(cb);\n if (index > -1) {\n blockSubscribers.splice(index, 1);\n }\n };\n}\n\nexport interface TransactionHistoryItem {\n tx_hash: string;\n height: number;\n fee?: number;\n}\n\nexport interface TransactionDetail {\n txid: string;\n version: number;\n locktime: number;\n vin: Array<{\n txid: string;\n vout: number;\n scriptSig?: {\n hex: string;\n };\n sequence: number;\n }>;\n vout: Array<{\n value: number;\n n: number;\n scriptPubKey: {\n hex: string;\n type: string;\n addresses?: string[];\n address?: string;\n };\n }>;\n blockhash?: string;\n confirmations?: number;\n time?: number;\n blocktime?: number;\n}\n\nexport async function getTransactionHistory(address: string): Promise<TransactionHistoryItem[]> {\n const scriptHash = addressToScriptHash(address);\n const result = await rpc('blockchain.scripthash.get_history', [scriptHash]);\n\n if (!Array.isArray(result)) {\n console.warn('get_history returned non-array:', result);\n return [];\n }\n\n return result as TransactionHistoryItem[];\n}\n\nexport async function getTransaction(txid: string) {\n return await rpc('blockchain.transaction.get', [txid, true]);\n}\n\nexport async function getBlockHeader(height: number) {\n return await rpc('blockchain.block.header', [height, height]);\n}\n\nexport async function getCurrentBlockHeight(): Promise<number> {\n try {\n const header = (await rpc('blockchain.headers.subscribe', [])) as BlockHeader;\n return header?.height || 0;\n } catch (err) {\n console.error('Error getting current block height:', err);\n return 0;\n }\n}\n\nexport function disconnect() {\n if (ws) {\n intentionalClose = true;\n ws.close();\n ws = null;\n }\n isConnected = false;\n isConnecting = false;\n reconnectAttempts = 0;\n isBlockSubscribed = false;\n\n // Clear all pending request timeouts\n Object.values(pending).forEach((req) => {\n if (req.timeoutId) clearTimeout(req.timeoutId);\n });\n Object.keys(pending).forEach((key) => delete pending[Number(key)]);\n\n // Clear connection callback timeouts\n connectionCallbacks.forEach((cb) => {\n if (cb.timeoutId) clearTimeout(cb.timeoutId);\n });\n connectionCallbacks.length = 0;\n}\n","/**\n * Transaction handling - Strict copy of index.html logic\n */\nimport { getUtxo, broadcast } from \"./network\";\nimport { decodeBech32 } from \"../core/bech32\";\nimport CryptoJS from \"crypto-js\";\nimport elliptic from \"elliptic\";\nimport type { Wallet, TransactionPlan, Transaction, UTXO } from \"./types\";\nimport { vestingState } from \"./vestingState\";\nimport { WalletAddressHelper } from \"./addressHelpers\";\n\nconst ec = new elliptic.ec(\"secp256k1\");\n\n// Constants\nconst FEE = 10_000; // sats per transaction\nconst DUST = 546; // dust threshold\nconst SAT = 100_000_000; // sats in 1 ALPHA\n\n/**\n * Create scriptPubKey for address (P2WPKH for bech32)\n * Exact copy from index.html\n */\nexport function createScriptPubKey(address: string): string {\n if (!address || typeof address !== \"string\") {\n throw new Error(\"Invalid address: must be a string\");\n }\n\n const decoded = decodeBech32(address);\n if (!decoded) {\n throw new Error(\"Invalid bech32 address: \" + address);\n }\n\n // Convert data array to hex string\n const dataHex = Array.from(decoded.data)\n .map((byte) => byte.toString(16).padStart(2, \"0\"))\n .join(\"\");\n\n // P2WPKH scriptPubKey: OP_0 <20-byte-key-hash>\n return \"0014\" + dataHex;\n}\n\n/**\n * Create signature hash for SegWit (BIP143)\n * Exact copy from index.html createSignatureHash()\n */\nfunction createSignatureHash(\n txPlan: { input: { tx_hash: string; tx_pos: number; value: number }; outputs: Array<{ value: number; address: string }> },\n publicKey: string\n): string {\n let preimage = \"\";\n\n // 1. nVersion (4 bytes, little-endian)\n preimage += \"02000000\";\n\n // 2. hashPrevouts (32 bytes)\n const txidBytes = txPlan.input.tx_hash.match(/../g)!.reverse().join(\"\");\n const voutBytes = (\"00000000\" + txPlan.input.tx_pos.toString(16)).slice(-8).match(/../g)!.reverse().join(\"\");\n const prevouts = txidBytes + voutBytes;\n const hashPrevouts = CryptoJS.SHA256(CryptoJS.SHA256(CryptoJS.enc.Hex.parse(prevouts))).toString();\n preimage += hashPrevouts;\n\n // 3. hashSequence (32 bytes)\n const sequence = \"feffffff\";\n const hashSequence = CryptoJS.SHA256(CryptoJS.SHA256(CryptoJS.enc.Hex.parse(sequence))).toString();\n preimage += hashSequence;\n\n // 4. outpoint (36 bytes)\n preimage += txPlan.input.tx_hash.match(/../g)!.reverse().join(\"\");\n preimage += (\"00000000\" + txPlan.input.tx_pos.toString(16)).slice(-8).match(/../g)!.reverse().join(\"\");\n\n // 5. scriptCode for P2WPKH (includes length prefix)\n const pubKeyHash = CryptoJS.RIPEMD160(CryptoJS.SHA256(CryptoJS.enc.Hex.parse(publicKey))).toString();\n const scriptCode = \"1976a914\" + pubKeyHash + \"88ac\";\n preimage += scriptCode;\n\n // 6. amount (8 bytes, little-endian)\n const amountHex = txPlan.input.value.toString(16).padStart(16, \"0\");\n preimage += amountHex.match(/../g)!.reverse().join(\"\");\n\n // 7. nSequence (4 bytes, little-endian)\n preimage += sequence;\n\n // 8. hashOutputs (32 bytes)\n let outputs = \"\";\n for (const output of txPlan.outputs) {\n const outAmountHex = output.value.toString(16).padStart(16, \"0\");\n outputs += outAmountHex.match(/../g)!.reverse().join(\"\");\n const scriptPubKey = createScriptPubKey(output.address);\n const scriptLength = (scriptPubKey.length / 2).toString(16).padStart(2, \"0\");\n outputs += scriptLength;\n outputs += scriptPubKey;\n }\n const hashOutputs = CryptoJS.SHA256(CryptoJS.SHA256(CryptoJS.enc.Hex.parse(outputs))).toString();\n preimage += hashOutputs;\n\n // 9. nLocktime (4 bytes, little-endian)\n preimage += \"00000000\";\n\n // 10. sighash type (4 bytes, little-endian)\n preimage += \"01000000\"; // SIGHASH_ALL\n\n // Double SHA256\n const hash1 = CryptoJS.SHA256(CryptoJS.enc.Hex.parse(preimage));\n const hash2 = CryptoJS.SHA256(hash1);\n return hash2.toString();\n}\n\n/**\n * Create witness data for the transaction\n * Exact copy from index.html createWitnessData()\n */\nfunction createWitnessData(\n txPlan: { input: { tx_hash: string; tx_pos: number; value: number }; outputs: Array<{ value: number; address: string }> },\n keyPair: elliptic.ec.KeyPair,\n publicKey: string\n): string {\n // Create signature hash for witness\n const sigHash = createSignatureHash(txPlan, publicKey);\n\n // Sign the hash\n const signature = keyPair.sign(sigHash);\n\n // Ensure low-S canonical signature (BIP62)\n const halfOrder = ec.curve.n!.shrn(1);\n if (signature.s.cmp(halfOrder) > 0) {\n signature.s = ec.curve.n!.sub(signature.s);\n }\n\n const derSig = signature.toDER(\"hex\") + \"01\"; // SIGHASH_ALL\n\n // Build witness\n let witness = \"\";\n witness += \"02\"; // 2 stack items\n\n // Signature\n const sigLen = (derSig.length / 2).toString(16).padStart(2, \"0\");\n witness += sigLen;\n witness += derSig;\n\n // Public key\n const pubKeyLen = (publicKey.length / 2).toString(16).padStart(2, \"0\");\n witness += pubKeyLen;\n witness += publicKey;\n\n return witness;\n}\n\n/**\n * Build a proper SegWit transaction\n * Exact copy from index.html buildSegWitTransaction()\n */\nexport function buildSegWitTransaction(\n txPlan: { input: { tx_hash: string; tx_pos: number; value: number }; outputs: Array<{ value: number; address: string }> },\n keyPair: elliptic.ec.KeyPair,\n publicKey: string\n): { hex: string; txid: string } {\n let txHex = \"\";\n\n // Version (4 bytes, little-endian)\n txHex += \"02000000\"; // version 2\n\n // Marker and flag for SegWit\n txHex += \"00\"; // marker\n txHex += \"01\"; // flag\n\n // Number of inputs (varint)\n txHex += \"01\"; // 1 input\n\n // Input - Previous tx hash (32 bytes, reversed for little-endian)\n const prevTxHash = txPlan.input.tx_hash;\n const reversedHash = prevTxHash.match(/../g)!.reverse().join(\"\");\n txHex += reversedHash;\n\n // Previous output index (4 bytes, little-endian)\n const vout = txPlan.input.tx_pos;\n txHex += (\"00000000\" + vout.toString(16)).slice(-8).match(/../g)!.reverse().join(\"\");\n\n // Script length (varint) - 0 for witness transactions\n txHex += \"00\";\n\n // Sequence (4 bytes)\n txHex += \"feffffff\";\n\n // Number of outputs (varint)\n const outputCount = txPlan.outputs.length;\n txHex += (\"0\" + outputCount.toString(16)).slice(-2);\n\n // Outputs\n for (const output of txPlan.outputs) {\n // Amount (8 bytes, little-endian)\n const amountHex = output.value.toString(16).padStart(16, \"0\");\n txHex += amountHex.match(/../g)!.reverse().join(\"\");\n\n // Script pubkey\n const scriptPubKey = createScriptPubKey(output.address);\n const scriptLength = (scriptPubKey.length / 2).toString(16).padStart(2, \"0\");\n txHex += scriptLength;\n txHex += scriptPubKey;\n }\n\n // Witness data\n const witnessData = createWitnessData(txPlan, keyPair, publicKey);\n txHex += witnessData;\n\n // Locktime (4 bytes)\n txHex += \"00000000\";\n\n // Calculate transaction ID (double SHA256 of tx without witness data)\n let txForId = \"\";\n\n // Version (4 bytes)\n txForId += \"02000000\";\n\n // Input count (1 byte)\n txForId += \"01\";\n\n // Input: txid (32 bytes reversed) + vout (4 bytes)\n const inputTxidBytes = txPlan.input.tx_hash.match(/../g)!.reverse().join(\"\");\n txForId += inputTxidBytes;\n txForId += (\"00000000\" + txPlan.input.tx_pos.toString(16)).slice(-8).match(/../g)!.reverse().join(\"\");\n\n // Script sig (empty for P2WPKH)\n txForId += \"00\";\n\n // Sequence (4 bytes)\n txForId += \"feffffff\";\n\n // Output count\n txForId += (\"0\" + txPlan.outputs.length.toString(16)).slice(-2);\n\n // Add all outputs\n for (const output of txPlan.outputs) {\n const amountHex = (\"0000000000000000\" + output.value.toString(16)).slice(-16);\n const amountLittleEndian = amountHex.match(/../g)!.reverse().join(\"\");\n txForId += amountLittleEndian;\n\n const scriptPubKey = createScriptPubKey(output.address);\n const scriptLength = (\"0\" + (scriptPubKey.length / 2).toString(16)).slice(-2);\n txForId += scriptLength;\n txForId += scriptPubKey;\n }\n\n // Locktime (4 bytes)\n txForId += \"00000000\";\n\n // Calculate the correct txid\n const hash1 = CryptoJS.SHA256(CryptoJS.enc.Hex.parse(txForId));\n const hash2 = CryptoJS.SHA256(hash1);\n const txid = hash2.toString().match(/../g)!.reverse().join(\"\");\n\n return {\n hex: txHex,\n txid: txid,\n };\n}\n\n/**\n * Create and sign a transaction\n * Uses the private key for the specific address being spent from\n */\nexport function createAndSignTransaction(\n wallet: Wallet,\n txPlan: Transaction\n): { raw: string; txid: string } {\n // Find the address entry that matches the input address\n const fromAddress = txPlan.input.address;\n const addressEntry = wallet.addresses.find(a => a.address === fromAddress);\n\n // Use the private key from the address entry, or fall back to childPrivateKey/masterPrivateKey\n let privateKeyHex: string | undefined;\n\n if (addressEntry?.privateKey) {\n // Use the specific private key for this address\n privateKeyHex = addressEntry.privateKey;\n } else if (wallet.childPrivateKey) {\n // Fall back to childPrivateKey (first address)\n privateKeyHex = wallet.childPrivateKey;\n } else {\n // Last resort: use master key\n privateKeyHex = wallet.masterPrivateKey;\n }\n\n if (!privateKeyHex) {\n throw new Error(\"No private key available for address: \" + fromAddress);\n }\n\n const keyPair = ec.keyFromPrivate(privateKeyHex, \"hex\");\n const publicKey = keyPair.getPublic(true, \"hex\"); // compressed\n\n // Convert Transaction to the format expected by buildSegWitTransaction\n const txPlanForBuild = {\n input: {\n tx_hash: txPlan.input.txid,\n tx_pos: txPlan.input.vout,\n value: txPlan.input.value,\n },\n outputs: txPlan.outputs,\n };\n\n const tx = buildSegWitTransaction(txPlanForBuild, keyPair, publicKey);\n\n return {\n raw: tx.hex,\n txid: tx.txid,\n };\n}\n\n/**\n * Collect UTXOs for required amount\n * Based on index.html collectUtxosForAmount()\n *\n * Strategy: First try to find a single UTXO that can cover amount + fee.\n * If not found, fall back to combining multiple UTXOs.\n */\nexport function collectUtxosForAmount(\n utxoList: UTXO[],\n amountSats: number,\n recipientAddress: string,\n senderAddress: string\n): TransactionPlan {\n const totalAvailable = utxoList.reduce((sum, u) => sum + u.value, 0);\n\n if (totalAvailable < amountSats + FEE) {\n return {\n success: false,\n transactions: [],\n error: `Insufficient funds. Available: ${totalAvailable / SAT} ALPHA, Required: ${(amountSats + FEE) / SAT} ALPHA (including fee)`,\n };\n }\n\n // Strategy 1: Find a single UTXO that covers amount + fee\n // Sort by value ascending to find the smallest sufficient UTXO\n const sortedByValue = [...utxoList].sort((a, b) => a.value - b.value);\n const sufficientUtxo = sortedByValue.find(u => u.value >= amountSats + FEE);\n\n if (sufficientUtxo) {\n const changeAmount = sufficientUtxo.value - amountSats - FEE;\n const tx: Transaction = {\n input: {\n txid: sufficientUtxo.txid ?? sufficientUtxo.tx_hash ?? \"\",\n vout: sufficientUtxo.vout ?? sufficientUtxo.tx_pos ?? 0,\n value: sufficientUtxo.value,\n address: sufficientUtxo.address ?? senderAddress,\n },\n outputs: [{ address: recipientAddress, value: amountSats }],\n fee: FEE,\n changeAmount: changeAmount,\n changeAddress: senderAddress,\n };\n\n // Add change output if above dust\n if (changeAmount > DUST) {\n tx.outputs.push({ value: changeAmount, address: senderAddress });\n }\n\n return {\n success: true,\n transactions: [tx],\n };\n }\n\n // Strategy 2: No single UTXO is sufficient, combine multiple UTXOs\n // Sort descending to use larger UTXOs first (fewer transactions)\n const sortedDescending = [...utxoList].sort((a, b) => b.value - a.value);\n\n const transactions: Transaction[] = [];\n let remainingAmount = amountSats;\n\n for (const utxo of sortedDescending) {\n if (remainingAmount <= 0) break;\n\n const utxoValue = utxo.value;\n let txAmount = 0;\n let changeAmount = 0;\n\n if (utxoValue >= remainingAmount + FEE) {\n // This UTXO covers the remaining amount plus fee\n txAmount = remainingAmount;\n changeAmount = utxoValue - remainingAmount - FEE;\n remainingAmount = 0;\n } else {\n // Use entire UTXO minus fee\n txAmount = utxoValue - FEE;\n if (txAmount <= 0) continue; // Skip UTXOs too small to cover fee\n remainingAmount -= txAmount;\n }\n\n const tx: Transaction = {\n input: {\n txid: utxo.txid ?? utxo.tx_hash ?? \"\",\n vout: utxo.vout ?? utxo.tx_pos ?? 0,\n value: utxo.value,\n address: utxo.address ?? senderAddress,\n },\n outputs: [{ address: recipientAddress, value: txAmount }],\n fee: FEE,\n changeAmount: changeAmount,\n changeAddress: senderAddress,\n };\n\n // Add change output if above dust\n if (changeAmount > DUST) {\n tx.outputs.push({ value: changeAmount, address: senderAddress });\n }\n\n transactions.push(tx);\n }\n\n if (remainingAmount > 0) {\n return {\n success: false,\n transactions: [],\n error: `Unable to collect enough UTXOs. Short by ${remainingAmount / SAT} ALPHA after fees.`,\n };\n }\n\n return {\n success: true,\n transactions,\n };\n}\n\n/**\n * Create transaction plan from wallet\n * @param wallet - The wallet\n * @param toAddress - Recipient address\n * @param amountAlpha - Amount in ALPHA\n * @param fromAddress - Optional: specific address to send from (defaults to first address)\n */\nexport async function createTransactionPlan(\n wallet: Wallet,\n toAddress: string,\n amountAlpha: number,\n fromAddress?: string\n): Promise<TransactionPlan> {\n if (!decodeBech32(toAddress)) {\n throw new Error(\"Invalid recipient address\");\n }\n\n // Use specified fromAddress or default to first external address\n const defaultAddr = WalletAddressHelper.getDefault(wallet);\n const senderAddress = fromAddress || defaultAddr.address;\n const amountSats = Math.floor(amountAlpha * SAT);\n\n // Get UTXOs filtered by current vesting mode (set in SendModal)\n let utxos: UTXO[];\n const currentMode = vestingState.getMode();\n\n if (vestingState.hasClassifiedData(senderAddress)) {\n // Use vesting-filtered UTXOs based on selected mode\n utxos = vestingState.getFilteredUtxos(senderAddress);\n console.log(`Using ${utxos.length} ${currentMode} UTXOs`);\n } else {\n // Fall back to all UTXOs if not yet classified\n utxos = await getUtxo(senderAddress);\n console.log(`Using ${utxos.length} UTXOs (vesting not classified yet)`);\n }\n\n if (!Array.isArray(utxos) || utxos.length === 0) {\n const modeText = currentMode !== 'all' ? ` (${currentMode} coins)` : '';\n throw new Error(`No UTXOs available${modeText} for address: ` + senderAddress);\n }\n\n return collectUtxosForAmount(utxos, amountSats, toAddress, senderAddress);\n}\n\n/**\n * Send ALPHA to address\n * @param wallet - The wallet\n * @param toAddress - Recipient address\n * @param amountAlpha - Amount in ALPHA\n * @param fromAddress - Optional: specific address to send from\n */\nexport async function sendAlpha(\n wallet: Wallet,\n toAddress: string,\n amountAlpha: number,\n fromAddress?: string\n) {\n const plan = await createTransactionPlan(wallet, toAddress, amountAlpha, fromAddress);\n\n if (!plan.success) {\n throw new Error(plan.error || \"Transaction planning failed\");\n }\n\n const results = [];\n\n for (const tx of plan.transactions) {\n const signed = createAndSignTransaction(wallet, tx);\n const result = await broadcast(signed.raw);\n results.push({\n txid: signed.txid,\n raw: signed.raw,\n broadcastResult: result,\n });\n }\n\n return results;\n}\n","/**\n * VestingClassifier - Traces UTXOs to their coinbase origin to determine vesting status\n * VESTED: Coins from coinbase transactions in blocks <= VESTING_THRESHOLD (280000)\n * UNVESTED: Coins from coinbase transactions in blocks > VESTING_THRESHOLD\n *\n * Direct port from index.html VestingClassifier\n */\nimport { getTransaction, getCurrentBlockHeight } from \"./network\";\nimport type { UTXO, ClassifiedUTXO, ClassificationResult } from \"./types\";\n\nexport const VESTING_THRESHOLD = 280000;\n\n// Current block height - updated during classification\nlet currentBlockHeight: number | null = null;\n\ninterface CacheEntry {\n blockHeight: number | null; // null means \"not computed yet\"\n isCoinbase: boolean;\n inputTxId: string | null;\n}\n\ninterface TransactionData {\n txid: string;\n confirmations?: number;\n height?: number;\n vin?: Array<{\n txid?: string;\n coinbase?: string;\n }>;\n}\n\nclass VestingClassifier {\n private memoryCache = new Map<string, CacheEntry>();\n private dbName = \"SphereVestingCacheV5\"; // V5 - new cache with proper null handling\n private storeName = \"vestingCache\";\n private db: IDBDatabase | null = null;\n\n /**\n * Initialize IndexedDB for persistent caching\n */\n async initDB(): Promise<void> {\n return new Promise((resolve, reject) => {\n const request = indexedDB.open(this.dbName, 1);\n\n request.onupgradeneeded = (event) => {\n const db = (event.target as IDBOpenDBRequest).result;\n if (!db.objectStoreNames.contains(this.storeName)) {\n db.createObjectStore(this.storeName, { keyPath: \"txHash\" });\n }\n };\n\n request.onsuccess = (event) => {\n this.db = (event.target as IDBOpenDBRequest).result;\n resolve();\n };\n\n request.onerror = () => reject(request.error);\n });\n }\n\n /**\n * Check if transaction is coinbase\n */\n private isCoinbaseTransaction(txData: TransactionData): boolean {\n if (txData.vin && txData.vin.length === 1) {\n const vin = txData.vin[0];\n // Check for coinbase field or missing txid\n if (vin.coinbase || (!vin.txid && vin.coinbase !== undefined)) {\n return true;\n }\n // Some formats use empty txid for coinbase\n if (vin.txid === \"0000000000000000000000000000000000000000000000000000000000000000\") {\n return true;\n }\n }\n return false;\n }\n\n /**\n * Load from IndexedDB cache\n */\n private async loadFromDB(txHash: string): Promise<CacheEntry | null> {\n if (!this.db) return null;\n\n return new Promise((resolve) => {\n const tx = this.db!.transaction(this.storeName, \"readonly\");\n const store = tx.objectStore(this.storeName);\n const request = store.get(txHash);\n\n request.onsuccess = () => {\n if (request.result) {\n resolve({\n blockHeight: request.result.blockHeight,\n isCoinbase: request.result.isCoinbase,\n inputTxId: request.result.inputTxId,\n });\n } else {\n resolve(null);\n }\n };\n request.onerror = () => resolve(null);\n });\n }\n\n /**\n * Save to IndexedDB cache\n */\n private async saveToDB(txHash: string, entry: CacheEntry): Promise<void> {\n if (!this.db) return;\n\n return new Promise((resolve) => {\n const tx = this.db!.transaction(this.storeName, \"readwrite\");\n const store = tx.objectStore(this.storeName);\n store.put({ txHash, ...entry });\n tx.oncomplete = () => resolve();\n tx.onerror = () => resolve();\n });\n }\n\n /**\n * Trace a transaction to its coinbase origin\n * Alpha blockchain has single-input transactions, making this a linear trace\n */\n async traceToOrigin(txHash: string): Promise<{ coinbaseHeight: number | null; error?: string }> {\n let currentTxHash = txHash;\n let iterations = 0;\n const MAX_ITERATIONS = 10000;\n\n while (iterations < MAX_ITERATIONS) {\n iterations++;\n\n // Check memory cache first\n const cached = this.memoryCache.get(currentTxHash);\n if (cached) {\n if (cached.isCoinbase) {\n // Skip cache if blockHeight is null - needs re-fetch\n if (cached.blockHeight !== null && cached.blockHeight !== undefined) {\n return { coinbaseHeight: cached.blockHeight };\n }\n // Fall through to re-fetch\n } else if (cached.inputTxId) {\n // Follow the input chain\n currentTxHash = cached.inputTxId;\n continue;\n }\n }\n\n // Check IndexedDB cache\n const dbCached = await this.loadFromDB(currentTxHash);\n if (dbCached) {\n // Also store in memory cache\n this.memoryCache.set(currentTxHash, dbCached);\n if (dbCached.isCoinbase) {\n // Skip cache if blockHeight is null - needs re-fetch\n if (dbCached.blockHeight !== null && dbCached.blockHeight !== undefined) {\n return { coinbaseHeight: dbCached.blockHeight };\n }\n // Fall through to re-fetch\n } else if (dbCached.inputTxId) {\n currentTxHash = dbCached.inputTxId;\n continue;\n }\n }\n\n // Fetch from network\n const txData = await getTransaction(currentTxHash) as TransactionData;\n if (!txData || !txData.txid) {\n return { coinbaseHeight: null, error: `Failed to fetch tx ${currentTxHash}` };\n }\n\n // Determine if this is a coinbase transaction\n const isCoinbase = this.isCoinbaseTransaction(txData);\n\n // Calculate block height from confirmations (like index.html does)\n let blockHeight: number | null = null;\n if (txData.confirmations && currentBlockHeight !== null && currentBlockHeight !== undefined) {\n blockHeight = currentBlockHeight - txData.confirmations + 1;\n }\n\n // Get input transaction ID (if not coinbase)\n let inputTxId: string | null = null;\n if (!isCoinbase && txData.vin && txData.vin.length > 0 && txData.vin[0].txid) {\n inputTxId = txData.vin[0].txid;\n }\n\n // Cache the result\n const cacheEntry: CacheEntry = {\n blockHeight, // Can be null if confirmations not available\n isCoinbase,\n inputTxId,\n };\n this.memoryCache.set(currentTxHash, cacheEntry);\n await this.saveToDB(currentTxHash, cacheEntry);\n\n if (isCoinbase) {\n return { coinbaseHeight: blockHeight };\n }\n\n if (!inputTxId) {\n return { coinbaseHeight: null, error: \"Could not find input transaction\" };\n }\n\n currentTxHash = inputTxId;\n }\n\n return { coinbaseHeight: null, error: \"Max iterations exceeded\" };\n }\n\n /**\n * Classify a single UTXO\n */\n async classifyUtxo(utxo: UTXO): Promise<ClassificationResult> {\n const txHash = utxo.tx_hash || utxo.txid;\n if (!txHash) {\n return { isVested: false, coinbaseHeight: null, error: \"No transaction hash\" };\n }\n\n try {\n const result = await this.traceToOrigin(txHash);\n if (result.error || result.coinbaseHeight === null) {\n return { isVested: false, coinbaseHeight: null, error: result.error || \"Could not trace to origin\" };\n }\n return {\n isVested: result.coinbaseHeight <= VESTING_THRESHOLD,\n coinbaseHeight: result.coinbaseHeight,\n };\n } catch (err) {\n return {\n isVested: false,\n coinbaseHeight: null,\n error: err instanceof Error ? err.message : String(err),\n };\n }\n }\n\n /**\n * Classify multiple UTXOs with progress callback\n */\n async classifyUtxos(\n utxos: UTXO[],\n onProgress?: (current: number, total: number) => void\n ): Promise<{\n vested: ClassifiedUTXO[];\n unvested: ClassifiedUTXO[];\n errors: Array<{ utxo: UTXO; error: string }>;\n }> {\n // Get current block height before classification\n currentBlockHeight = await getCurrentBlockHeight();\n\n // Clear memory cache to force re-fetch with current block height\n this.memoryCache.clear();\n\n const vested: ClassifiedUTXO[] = [];\n const unvested: ClassifiedUTXO[] = [];\n const errors: Array<{ utxo: UTXO; error: string }> = [];\n\n for (let i = 0; i < utxos.length; i++) {\n const utxo = utxos[i];\n const result = await this.classifyUtxo(utxo);\n\n if (result.error) {\n errors.push({ utxo, error: result.error });\n // Default to unvested on error for safety\n unvested.push({\n ...utxo,\n vestingStatus: \"error\",\n coinbaseHeight: null,\n });\n } else if (result.isVested) {\n vested.push({\n ...utxo,\n vestingStatus: \"vested\",\n coinbaseHeight: result.coinbaseHeight,\n });\n } else {\n unvested.push({\n ...utxo,\n vestingStatus: \"unvested\",\n coinbaseHeight: result.coinbaseHeight,\n });\n }\n\n // Report progress\n if (onProgress) {\n onProgress(i + 1, utxos.length);\n }\n\n // Yield every 5 UTXOs\n if (i % 5 === 0) {\n await new Promise((resolve) => setTimeout(resolve, 0));\n }\n }\n\n return { vested, unvested, errors };\n }\n\n /**\n * Clear all caches\n */\n clearCaches(): void {\n this.memoryCache.clear();\n if (this.db) {\n const tx = this.db.transaction(this.storeName, \"readwrite\");\n tx.objectStore(this.storeName).clear();\n }\n }\n}\n\nexport const vestingClassifier = new VestingClassifier();\n","import { vestingClassifier } from \"./vesting\";\nimport type {\n UTXO,\n ClassifiedUTXO,\n VestingMode,\n VestingBalances,\n} from \"./types\";\n\ninterface AddressVestingCache {\n classifiedUtxos: {\n vested: ClassifiedUTXO[];\n unvested: ClassifiedUTXO[];\n all: ClassifiedUTXO[];\n };\n vestingBalances: VestingBalances;\n}\n\nclass VestingStateManager {\n private currentMode: VestingMode = \"all\";\n private addressCache = new Map<string, AddressVestingCache>();\n private classificationInProgress = false;\n\n /**\n * Set the current vesting mode\n */\n setMode(mode: VestingMode): void {\n if (![\"all\", \"vested\", \"unvested\"].includes(mode)) {\n throw new Error(`Invalid vesting mode: ${mode}`);\n }\n this.currentMode = mode;\n }\n\n getMode(): VestingMode {\n return this.currentMode;\n }\n\n /**\n * Classify all UTXOs for an address\n */\n async classifyAddressUtxos(\n address: string,\n utxos: UTXO[],\n onProgress?: (current: number, total: number) => void\n ): Promise<void> {\n if (this.classificationInProgress) return;\n\n this.classificationInProgress = true;\n\n try {\n await vestingClassifier.initDB();\n\n const result = await vestingClassifier.classifyUtxos(utxos, onProgress);\n\n // Calculate balances\n const vestedBalance = result.vested.reduce(\n (sum, utxo) => sum + BigInt(utxo.value),\n 0n\n );\n const unvestedBalance = result.unvested.reduce(\n (sum, utxo) => sum + BigInt(utxo.value),\n 0n\n );\n\n // Store in cache\n this.addressCache.set(address, {\n classifiedUtxos: {\n vested: result.vested,\n unvested: result.unvested,\n all: [...result.vested, ...result.unvested],\n },\n vestingBalances: {\n vested: vestedBalance,\n unvested: unvestedBalance,\n all: vestedBalance + unvestedBalance,\n },\n });\n\n // Log any errors\n if (result.errors.length > 0) {\n console.warn(`Vesting classification errors: ${result.errors.length}`);\n result.errors.slice(0, 5).forEach((err) => {\n const txHash = err.utxo.tx_hash || err.utxo.txid;\n console.warn(` ${txHash}: ${err.error}`);\n });\n }\n } finally {\n this.classificationInProgress = false;\n }\n }\n\n /**\n * Get filtered UTXOs based on current vesting mode\n */\n getFilteredUtxos(address: string): ClassifiedUTXO[] {\n const cache = this.addressCache.get(address);\n if (!cache) return [];\n\n switch (this.currentMode) {\n case \"vested\":\n return cache.classifiedUtxos.vested;\n case \"unvested\":\n return cache.classifiedUtxos.unvested;\n default:\n return cache.classifiedUtxos.all;\n }\n }\n\n /**\n * Get all UTXOs regardless of vesting mode (for transactions)\n */\n getAllUtxos(address: string): ClassifiedUTXO[] {\n const cache = this.addressCache.get(address);\n if (!cache) return [];\n return cache.classifiedUtxos.all;\n }\n\n /**\n * Get balance for current vesting mode (in satoshis)\n */\n getBalance(address: string): bigint {\n const cache = this.addressCache.get(address);\n if (!cache) return 0n;\n\n return cache.vestingBalances[this.currentMode];\n }\n\n /**\n * Get all balances for display\n */\n getAllBalances(address: string): VestingBalances {\n const cache = this.addressCache.get(address);\n if (!cache) {\n return { vested: 0n, unvested: 0n, all: 0n };\n }\n return cache.vestingBalances;\n }\n\n /**\n * Check if address has been classified\n */\n hasClassifiedData(address: string): boolean {\n return this.addressCache.has(address);\n }\n\n /**\n * Check if classification is in progress\n */\n isClassifying(): boolean {\n return this.classificationInProgress;\n }\n\n /**\n * Clear cache for an address\n */\n clearAddressCache(address: string): void {\n this.addressCache.delete(address);\n }\n\n /**\n * Clear all caches\n */\n clearAllCaches(): void {\n this.addressCache.clear();\n vestingClassifier.clearCaches();\n }\n}\n\nexport const vestingState = new VestingStateManager();\n","/**\n * WalletAddressHelper - Path-based address lookup and mutation utilities\n *\n * Key principle: A BIP32 path ALWAYS derives the same address from a given master key.\n * - If we try to add a different address for an existing path → FATAL ERROR\n * - This indicates corruption, wrong derivation, or data integrity issue\n *\n * Performance: O(n) lookup is negligible for typical wallet sizes (5-100 addresses)\n */\n\nimport type { Wallet, WalletAddress } from \"./types\";\n\nexport class WalletAddressHelper {\n /**\n * Find address by BIP32 derivation path\n * @param wallet - The wallet to search\n * @param path - Full BIP32 path like \"m/84'/1'/0'/0/5\"\n * @returns The address if found, undefined otherwise\n */\n static findByPath(wallet: Wallet, path: string): WalletAddress | undefined {\n return wallet.addresses.find((a) => a.path === path);\n }\n\n /**\n * Get the default address (first external/non-change address)\n * This replaces `wallet.addresses[0]` pattern for safer access\n *\n * @param wallet - The wallet\n * @returns First non-change address, or first address if all are change\n */\n static getDefault(wallet: Wallet): WalletAddress {\n return wallet.addresses.find((a) => !a.isChange) ?? wallet.addresses[0];\n }\n\n /**\n * Get the default address, or undefined if wallet has no addresses\n * Safe version that doesn't throw on empty wallet\n */\n static getDefaultOrNull(wallet: Wallet): WalletAddress | undefined {\n if (!wallet.addresses || wallet.addresses.length === 0) {\n return undefined;\n }\n return wallet.addresses.find((a) => !a.isChange) ?? wallet.addresses[0];\n }\n\n /**\n * Add new address to wallet (immutable operation)\n *\n * THROWS if address with same path but different address string already exists.\n * This indicates a serious derivation or data corruption issue.\n *\n * If the same path+address already exists, returns wallet unchanged (idempotent).\n *\n * @param wallet - The wallet to add to\n * @param newAddress - The address to add\n * @returns New wallet object with address added\n * @throws Error if path exists with different address (corruption indicator)\n */\n static add(wallet: Wallet, newAddress: WalletAddress): Wallet {\n if (!newAddress.path) {\n throw new Error(\"Cannot add address without a path\");\n }\n\n const existing = this.findByPath(wallet, newAddress.path);\n\n if (existing) {\n // Path exists - verify it's the SAME address\n if (existing.address !== newAddress.address) {\n throw new Error(\n `CRITICAL: Attempted to overwrite address for path ${newAddress.path}\\n` +\n `Existing: ${existing.address}\\n` +\n `New: ${newAddress.address}\\n` +\n `This indicates master key corruption or derivation logic error.`\n );\n }\n\n // Same path + same address = idempotent, return unchanged\n return wallet;\n }\n\n // New path - add to array\n return {\n ...wallet,\n addresses: [...wallet.addresses, newAddress],\n };\n }\n\n /**\n * Remove address by path (immutable operation)\n * @param wallet - The wallet to modify\n * @param path - The path of the address to remove\n * @returns New wallet object with address removed\n */\n static removeByPath(wallet: Wallet, path: string): Wallet {\n return {\n ...wallet,\n addresses: wallet.addresses.filter((a) => a.path !== path),\n };\n }\n\n /**\n * Get all external (non-change) addresses\n * @param wallet - The wallet\n * @returns Array of external addresses\n */\n static getExternal(wallet: Wallet): WalletAddress[] {\n return wallet.addresses.filter((a) => !a.isChange);\n }\n\n /**\n * Get all change addresses\n * @param wallet - The wallet\n * @returns Array of change addresses\n */\n static getChange(wallet: Wallet): WalletAddress[] {\n return wallet.addresses.filter((a) => a.isChange);\n }\n\n /**\n * Check if wallet has an address with the given path\n * @param wallet - The wallet to check\n * @param path - The path to look for\n * @returns true if path exists\n */\n static hasPath(wallet: Wallet, path: string): boolean {\n return wallet.addresses.some((a) => a.path === path);\n }\n\n /**\n * Validate wallet address array integrity\n * Checks for duplicate paths which indicate data corruption\n *\n * @param wallet - The wallet to validate\n * @throws Error if duplicate paths found\n */\n static validate(wallet: Wallet): void {\n const paths = wallet.addresses.map((a) => a.path).filter(Boolean);\n const uniquePaths = new Set(paths);\n\n if (paths.length !== uniquePaths.size) {\n // Find duplicates for error message\n const duplicates = paths.filter((p, i) => paths.indexOf(p) !== i);\n throw new Error(\n `CRITICAL: Wallet has duplicate paths: ${duplicates.join(\", \")}\\n` +\n `This indicates data corruption. Please restore from backup.`\n );\n }\n }\n\n /**\n * Sort addresses with external first, then change, each sorted by index\n * Useful for display purposes\n *\n * @param wallet - The wallet\n * @returns New wallet with sorted addresses\n */\n static sortAddresses(wallet: Wallet): Wallet {\n const sorted = [...wallet.addresses].sort((a, b) => {\n // External addresses first (isChange = false/undefined)\n const aIsChange = a.isChange ? 1 : 0;\n const bIsChange = b.isChange ? 1 : 0;\n if (aIsChange !== bIsChange) return aIsChange - bIsChange;\n // Then by index\n return a.index - b.index;\n });\n\n return {\n ...wallet,\n addresses: sorted,\n };\n }\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,wBAAAA;AAAA,EAAA;AAAA,yBAAAC;AAAA,EAAA;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;AAAA;AAAA;;;ACsNO,SAAS,oBAAoB,MAAuD;AAEzF,QAAM,QAAQ,KAAK,MAAM,mCAAmC;AAC5D,MAAI,CAAC,MAAO,QAAO;AACnB,SAAO,EAAE,OAAO,SAAS,MAAM,CAAC,GAAG,EAAE,GAAG,OAAO,SAAS,MAAM,CAAC,GAAG,EAAE,EAAE;AACxE;AAOO,SAAS,aAAa,MAAuB;AAClD,QAAM,SAAS,oBAAoB,IAAI;AACvC,SAAO,QAAQ,UAAU;AAC3B;AAOO,SAAS,iBAAiB,MAAsB;AACrD,QAAM,SAAS,oBAAoB,IAAI;AACvC,SAAO,QAAQ,SAAS;AAC1B;AAeO,SAAS,YAAY,MAAsB;AAChD,SAAO,KAAK,QAAQ,MAAM,GAAG,EAAE,QAAQ,OAAO,GAAG;AACnD;AAeO,SAAS,YAAY,SAAyB;AAEnD,QAAM,QAAQ,QAAQ,MAAM,GAAG;AAC/B,SAAO,MACJ,IAAI,CAAC,MAAM,QAAQ;AAClB,QAAI,QAAQ,EAAG,QAAO;AAEtB,WAAO,KAAK,SAAS,GAAG,IAAI,GAAG,KAAK,MAAM,GAAG,EAAE,CAAC,MAAM;AAAA,EACxD,CAAC,EACA,KAAK,GAAG;AACb;;;AC/QO,IAAM,UAAU;AAGvB,IAAM,YAAY,CAAC,WAAY,WAAY,WAAY,YAAY,SAAU;AAStE,SAAS,YACd,MACA,UACA,QACA,KACiB;AACjB,MAAI,MAAM;AACV,MAAI,OAAO;AACX,QAAM,MAAgB,CAAC;AACvB,QAAM,QAAQ,KAAK,UAAU;AAE7B,WAAS,IAAI,GAAG,IAAI,KAAK,QAAQ,KAAK;AACpC,UAAM,QAAQ,KAAK,CAAC;AACpB,QAAI,QAAQ,KAAK,SAAS,aAAa,EAAG,QAAO;AACjD,UAAO,OAAO,WAAY;AAC1B,YAAQ;AACR,WAAO,QAAQ,QAAQ;AACrB,cAAQ;AACR,UAAI,KAAM,OAAO,OAAQ,IAAI;AAAA,IAC/B;AAAA,EACF;AAEA,MAAI,KAAK;AACP,QAAI,OAAO,GAAG;AACZ,UAAI,KAAM,OAAQ,SAAS,OAAS,IAAI;AAAA,IAC1C;AAAA,EACF,WAAW,QAAQ,YAAa,OAAQ,SAAS,OAAS,MAAM;AAC9D,WAAO;AAAA,EACT;AAEA,SAAO;AACT;AASA,SAAS,UAAU,KAAuB;AACxC,QAAM,MAAgB,CAAC;AACvB,WAAS,IAAI,GAAG,IAAI,IAAI,QAAQ,IAAK,KAAI,KAAK,IAAI,WAAW,CAAC,KAAK,CAAC;AACpE,MAAI,KAAK,CAAC;AACV,WAAS,IAAI,GAAG,IAAI,IAAI,QAAQ,IAAK,KAAI,KAAK,IAAI,WAAW,CAAC,IAAI,EAAE;AACpE,SAAO;AACT;AAKA,SAAS,cAAc,QAA0B;AAC/C,MAAI,MAAM;AACV,WAAS,IAAI,GAAG,IAAI,OAAO,QAAQ,KAAK;AACtC,UAAM,MAAM,OAAO;AACnB,WAAQ,MAAM,aAAc,IAAK,OAAO,CAAC;AACzC,aAAS,IAAI,GAAG,IAAI,GAAG,KAAK;AAC1B,UAAK,OAAO,IAAK,EAAG,QAAO,UAAU,CAAC;AAAA,IACxC;AAAA,EACF;AACA,SAAO;AACT;AAKA,SAAS,eAAe,KAAa,MAA0B;AAC7D,QAAM,SAAS,UAAU,GAAG,EAAE,OAAO,IAAI,EAAE,OAAO,CAAC,GAAG,GAAG,GAAG,GAAG,GAAG,CAAC,CAAC;AACpE,QAAM,MAAM,cAAc,MAAM,IAAI;AAEpC,QAAM,MAAgB,CAAC;AACvB,WAAS,IAAI,GAAG,IAAI,GAAG,KAAK;AAC1B,QAAI,KAAM,OAAQ,KAAK,IAAI,KAAO,EAAE;AAAA,EACtC;AACA,SAAO;AACT;AAeO,SAAS,aACd,KACA,SACA,SACQ;AACR,MAAI,UAAU,KAAK,UAAU,IAAI;AAC/B,UAAM,IAAI,MAAM,yBAAyB;AAAA,EAC3C;AAEA,QAAM,YAAY,YAAY,MAAM,KAAK,OAAO,GAAG,GAAG,GAAG,IAAI;AAC7D,MAAI,CAAC,WAAW;AACd,UAAM,IAAI,MAAM,wBAAwB;AAAA,EAC1C;AAEA,QAAM,OAAO,CAAC,OAAO,EAAE,OAAO,SAAS;AACvC,QAAM,WAAW,eAAe,KAAK,IAAI;AACzC,QAAM,WAAW,KAAK,OAAO,QAAQ;AAErC,MAAI,MAAM,MAAM;AAChB,WAAS,IAAI,GAAG,IAAI,SAAS,QAAQ,KAAK;AACxC,WAAO,QAAQ,SAAS,CAAC,CAAC;AAAA,EAC5B;AAEA,SAAO;AACT;AAWO,SAAS,aACd,MACkE;AAClE,SAAO,KAAK,YAAY;AAExB,QAAM,MAAM,KAAK,YAAY,GAAG;AAChC,MAAI,MAAM,EAAG,QAAO;AAEpB,QAAM,MAAM,KAAK,UAAU,GAAG,GAAG;AACjC,QAAM,UAAU,KAAK,UAAU,MAAM,CAAC;AAEtC,QAAM,OAAiB,CAAC;AACxB,WAAS,IAAI,GAAG,IAAI,QAAQ,QAAQ,KAAK;AACvC,UAAM,MAAM,QAAQ,QAAQ,QAAQ,CAAC,CAAC;AACtC,QAAI,QAAQ,GAAI,QAAO;AACvB,SAAK,KAAK,GAAG;AAAA,EACf;AAGA,QAAM,WAAW,eAAe,KAAK,KAAK,MAAM,GAAG,EAAE,CAAC;AACtD,WAAS,IAAI,GAAG,IAAI,GAAG,KAAK;AAC1B,QAAI,SAAS,CAAC,MAAM,KAAK,KAAK,SAAS,IAAI,CAAC,GAAG;AAC7C,aAAO;AAAA,IACT;AAAA,EACF;AAEA,QAAM,UAAU,KAAK,CAAC;AACtB,QAAM,UAAU,YAAY,KAAK,MAAM,GAAG,EAAE,GAAG,GAAG,GAAG,KAAK;AAC1D,MAAI,CAAC,QAAS,QAAO;AAErB,SAAO;AAAA,IACL;AAAA,IACA,gBAAgB;AAAA,IAChB,MAAM,WAAW,KAAK,OAAO;AAAA,EAC/B;AACF;AAyCO,IAAM,eAAe;;;AC9N5B,uBAAqB;AAGrB,SAAS,WAAW,KAAiB;AACnC,SAAO,MAAM,KAAK,GAAG,EAClB,IAAI,CAAC,MAAM,EAAE,SAAS,EAAE,EAAE,SAAS,GAAG,GAAG,CAAC,EAC1C,KAAK,EAAE;AACZ;AAQO,SAAS,oBAAoB,SAAyB;AAC3D,QAAM,UAAU,aAAa,OAAO;AACpC,MAAI,CAAC,QAAS,OAAM,IAAI,MAAM,6BAA6B,OAAO;AAGlE,QAAM,YAAY,SAAS,WAAW,QAAQ,IAAI;AAGlD,QAAM,MAAM,iBAAAC,QAAS,OAAO,iBAAAA,QAAS,IAAI,IAAI,MAAM,SAAS,CAAC,EAAE,SAAS;AAGxE,SAAO,IAAI,MAAM,KAAK,EAAG,QAAQ,EAAE,KAAK,EAAE;AAC5C;;;ACrBA,YAAuB;AACvB,IAAAC,oBAAqB;AACrB,sBAAqB;AAOrB,IAAM,KAAK,IAAI,gBAAAC,QAAS,GAAG,WAAW;AAGtC,IAAM,cAAc;AAAA,EAClB;AACF;AA+FO,SAAS,kBAAkB,SAA4B;AAC5D,QAAM,IAAI,kBAAAC,QAAS;AAAA,IACjB,kBAAAA,QAAS,IAAI,IAAI,MAAM,OAAO;AAAA,IAC9B,kBAAAA,QAAS,IAAI,KAAK,MAAM,cAAc;AAAA,EACxC,EAAE,SAAS;AAEX,QAAM,KAAK,EAAE,UAAU,GAAG,EAAE;AAC5B,QAAM,KAAK,EAAE,UAAU,EAAE;AAGzB,QAAM,kBAAkB,OAAO,OAAO,EAAE;AACxC,MAAI,oBAAoB,MAAM,mBAAmB,aAAa;AAC5D,UAAM,IAAI,MAAM,8BAA8B;AAAA,EAChD;AAEA,SAAO;AAAA,IACL,YAAY;AAAA,IACZ,WAAW;AAAA,EACb;AACF;AAQO,SAAS,eACd,eACA,iBACA,OACY;AACZ,QAAM,aAAa,SAAS;AAC5B,MAAI;AAEJ,MAAI,YAAY;AAEd,UAAM,WAAW,MAAM,SAAS,EAAE,EAAE,SAAS,GAAG,GAAG;AACnD,WAAO,OAAO,gBAAgB;AAAA,EAChC,OAAO;AAEL,UAAM,UAAU,GAAG,eAAe,eAAe,KAAK;AACtD,UAAM,mBAAmB,QAAQ,UAAU,MAAM,KAAK;AACtD,UAAM,WAAW,MAAM,SAAS,EAAE,EAAE,SAAS,GAAG,GAAG;AACnD,WAAO,mBAAmB;AAAA,EAC5B;AAGA,QAAM,IAAI,kBAAAA,QAAS;AAAA,IACjB,kBAAAA,QAAS,IAAI,IAAI,MAAM,IAAI;AAAA,IAC3B,kBAAAA,QAAS,IAAI,IAAI,MAAM,eAAe;AAAA,EACxC,EAAE,SAAS;AAEX,QAAM,KAAK,EAAE,UAAU,GAAG,EAAE;AAC5B,QAAM,KAAK,EAAE,UAAU,EAAE;AAGzB,QAAM,WAAW,OAAO,OAAO,EAAE;AACjC,QAAM,kBAAkB,OAAO,OAAO,aAAa;AAGnD,MAAI,YAAY,aAAa;AAC3B,UAAM,IAAI,MAAM,gCAAgC;AAAA,EAClD;AAEA,QAAM,kBAAkB,WAAW,mBAAmB;AAGtD,MAAI,mBAAmB,IAAI;AACzB,UAAM,IAAI,MAAM,gCAAgC;AAAA,EAClD;AAEA,QAAM,eAAe,eAAe,SAAS,EAAE,EAAE,SAAS,IAAI,GAAG;AAEjE,SAAO;AAAA,IACL,YAAY;AAAA,IACZ,WAAW;AAAA,EACb;AACF;AAQO,SAAS,gBACd,eACA,iBACA,MACY;AACZ,QAAM,YAAY,KAAK,QAAQ,MAAM,EAAE,EAAE,MAAM,GAAG;AAElD,MAAI,aAAa;AACjB,MAAI,mBAAmB;AAEvB,aAAW,QAAQ,WAAW;AAC5B,UAAM,aAAa,KAAK,SAAS,GAAG,KAAK,KAAK,SAAS,GAAG;AAC1D,UAAM,WAAW,KAAK,QAAQ,SAAS,EAAE;AACzC,QAAI,QAAQ,SAAS,UAAU,EAAE;AAEjC,QAAI,YAAY;AACd,eAAS;AAAA,IACX;AAEA,UAAM,UAAU,eAAe,YAAY,kBAAkB,KAAK;AAClE,iBAAa,QAAQ;AACrB,uBAAmB,QAAQ;AAAA,EAC7B;AAEA,SAAO;AAAA,IACL,YAAY;AAAA,IACZ,WAAW;AAAA,EACb;AACF;AAWO,SAAS,aAAa,YAAoB,aAAsB,MAAc;AACnF,QAAM,UAAU,GAAG,eAAe,YAAY,KAAK;AACnD,SAAO,QAAQ,UAAU,YAAY,KAAK;AAC5C;AAmBO,SAAS,OAAO,MAAc,gBAAgC,OAAe;AAClF,QAAM,SACJ,kBAAkB,QACd,kBAAAC,QAAS,IAAI,IAAI,MAAM,IAAI,IAC3B,kBAAAA,QAAS,IAAI,KAAK,MAAM,IAAI;AAClC,SAAO,kBAAAA,QAAS,OAAO,MAAM,EAAE,SAAS;AAC1C;AAKO,SAAS,UAAU,MAAc,gBAAgC,OAAe;AACrF,QAAM,SACJ,kBAAkB,QACd,kBAAAA,QAAS,IAAI,IAAI,MAAM,IAAI,IAC3B,kBAAAA,QAAS,IAAI,KAAK,MAAM,IAAI;AAClC,SAAO,kBAAAA,QAAS,UAAU,MAAM,EAAE,SAAS;AAC7C;AAKO,SAAS,QAAQ,MAAsB;AAC5C,QAAM,MAAM,OAAO,MAAM,KAAK;AAC9B,SAAO,UAAU,KAAK,KAAK;AAC7B;AAaO,IAAM,iBAAiB;AAKvB,SAAS,eAAe,YAAgC;AAC7D,QAAM,UAAU,WAAW,MAAM,KAAK;AACtC,MAAI,CAAC,QAAS,QAAO,IAAI,WAAW,CAAC;AACrC,SAAO,WAAW,KAAK,QAAQ,IAAI,CAAC,MAAM,SAAS,GAAG,EAAE,CAAC,CAAC;AAC5D;AASO,SAAS,mBACd,WACA,SAAiB,SACjB,iBAAyB,GACjB;AACR,QAAM,aAAa,QAAQ,SAAS;AACpC,QAAM,eAAe,eAAe,UAAU;AAC9C,SAAO,aAAa,QAAQ,gBAAgB,YAAY;AAC1D;AAKO,SAAS,wBACd,YACA,SAAiB,SACuB;AACxC,QAAM,YAAY,aAAa,UAAU;AACzC,QAAM,UAAU,mBAAmB,WAAW,MAAM;AACpD,SAAO,EAAE,SAAS,UAAU;AAC9B;AAsGO,SAAS,oBACd,YACA,OACA,MACA,SAAiB,SACJ;AACb,QAAM,EAAE,SAAS,UAAU,IAAI,wBAAwB,YAAY,MAAM;AACzE,SAAO;AAAA,IACL;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF;AACF;;;ACvcA,IAAAC,oBAAqB;AAErB,IAAM,OAAO;AACb,IAAM,oBAAoB;AAEnB,SAAS,QAAQ,MAAc,UAA0B;AAC9D,SAAO,kBAAAC,QAAS,IAAI,QAAQ,MAAM,QAAQ,EAAE,SAAS;AACvD;AAEO,SAAS,QAAQ,WAAmB,UAA0B;AACnE,QAAM,QAAQ,kBAAAA,QAAS,IAAI,QAAQ,WAAW,QAAQ;AACtD,SAAO,MAAM,SAAS,kBAAAA,QAAS,IAAI,IAAI;AACzC;AAEO,SAAS,qBAA6B;AAC3C,SAAO,kBAAAA,QAAS,IAAI,UAAU,OAAO,EAAE,EAAE,SAAS;AACpD;AAKO,SAAS,cACd,kBACA,UACQ;AACR,QAAM,cAAc,kBAAAA,QAAS,OAAO,UAAU,MAAM;AAAA,IAClD,SAAS,MAAM;AAAA,IACf,YAAY;AAAA,EACd,CAAC,EAAE,SAAS;AAEZ,QAAM,YAAY,kBAAAA,QAAS,IAAI;AAAA,IAC7B;AAAA,IACA;AAAA,EACF,EAAE,SAAS;AAEX,SAAO;AACT;AAKO,SAAS,cACd,eACA,UACQ;AACR,QAAM,cAAc,kBAAAA,QAAS,OAAO,UAAU,MAAM;AAAA,IAClD,SAAS,MAAM;AAAA,IACf,YAAY;AAAA,EACd,CAAC,EAAE,SAAS;AAEZ,QAAM,YAAY,kBAAAA,QAAS,IAAI,QAAQ,eAAe,WAAW;AACjE,SAAO,UAAU,SAAS,kBAAAA,QAAS,IAAI,IAAI;AAC7C;AAKO,SAAS,SAAS,QAAwB;AAE/C,QAAM,cAAc;AACpB,QAAM,cAAc,cAAc;AAGlC,QAAM,QAAQ,kBAAAA,QAAS,OAAO,kBAAAA,QAAS,IAAI,IAAI,MAAM,WAAW,CAAC,EAAE,SAAS;AAC5E,QAAM,QAAQ,kBAAAA,QAAS,OAAO,kBAAAA,QAAS,IAAI,IAAI,MAAM,KAAK,CAAC,EAAE,SAAS;AACtE,QAAM,WAAW,MAAM,UAAU,GAAG,CAAC;AAGrC,QAAM,WAAW,cAAc;AAG/B,SAAO,aAAa,QAAQ;AAC9B;AAKA,SAAS,aAAa,KAAqB;AACzC,QAAM,WAAW;AAGjB,MAAI,MAAM,OAAO,OAAO,GAAG;AAC3B,MAAI,UAAU;AAEd,SAAO,MAAM,IAAI;AACf,UAAM,YAAY,OAAO,MAAM,GAAG;AAClC,UAAM,MAAM;AACZ,cAAU,SAAS,SAAS,IAAI;AAAA,EAClC;AAGA,WAAS,IAAI,GAAG,IAAI,IAAI,UAAU,IAAI,UAAU,GAAG,IAAI,CAAC,MAAM,MAAM,KAAK,GAAG;AAC1E,cAAU,MAAM;AAAA,EAClB;AAEA,SAAO;AACT;;;ACzFA,IAAAC,oBAAqB;AAgBd,IAAM,sBAAsB;AAM5B,IAAMC,mBAAkB;AAMxB,SAAS,0BAA0B,SAGxC;AACA,QAAM,SAAS,kBAAkB,OAAO;AACxC,SAAO;AAAA,IACL,kBAAkB,OAAO;AAAA,IACzB,iBAAiB,OAAO;AAAA,EAC1B;AACF;AAOO,SAAS,uBACd,YACA,WACA,OACA,WAAmB,eACnB,WAAoB,OACpB;AAEA,QAAM,QAAQ,WAAW,IAAI;AAC7B,QAAM,WAAW,GAAG,QAAQ,IAAI,KAAK,IAAI,KAAK;AAE9C,QAAM,UAAU,gBAAoB,YAAY,WAAW,QAAQ;AAEnE,SAAO,oBAAoB,QAAQ,YAAY,OAAO,QAAQ;AAChE;AAcO,SAAS,6BACd,kBACA,OACA;AACA,QAAM,iBAAiB,YAAY,KAAK;AAGxC,QAAM,YAAY,kBAAAC,QAAS,IAAI,IAAI,MAAM,gBAAgB;AACzD,QAAM,UAAU,kBAAAA,QAAS,IAAI,KAAK,MAAM,cAAc;AACtD,QAAM,aAAa,kBAAAA,QAAS,WAAW,WAAW,OAAO,EAAE,SAAS;AAGpE,QAAM,kBAAkB,WAAW,UAAU,GAAG,EAAE;AAElD,SAAO,oBAAoB,iBAAiB,OAAO,cAAc;AACnE;AAWO,SAASC,gBACd,YACA,WACA,OACA;AACA,QAAM,OAAO,aAAa,MAAM,SAAS,EAAE,EAAE,SAAS,GAAG,GAAG;AAE5D,QAAM,IAAI,kBAAAD,QAAS;AAAA,IACjB,kBAAAA,QAAS,IAAI,IAAI,MAAM,IAAI;AAAA,IAC3B,kBAAAA,QAAS,IAAI,IAAI,MAAM,SAAS;AAAA,EAClC,EAAE,SAAS;AAEX,SAAO;AAAA,IACL,YAAY,EAAE,UAAU,GAAG,EAAE;AAAA,IAC7B,eAAe,EAAE,UAAU,EAAE;AAAA,EAC/B;AACF;AAMO,SAAS,kBACd,YACA,WACA,OACA;AACA,QAAM,QAAQC,gBAAe,YAAY,WAAW,KAAK;AACzD,QAAM,OAAO,eAAe,KAAK;AAEjC,SAAO,oBAAoB,MAAM,YAAY,OAAO,IAAI;AAC1D;;;ACnIA,IAAM,mBAAmB;AAkBzB,IAAI,KAAuB;AAC3B,IAAI,cAAc;AAClB,IAAI,eAAe;AACnB,IAAI,YAAY;AAChB,IAAI,mBAAmB;AACvB,IAAI,oBAAoB;AACxB,IAAI,oBAAoB;AACxB,IAAI,kBAAsC;AAO1C,IAAM,UAAqD,CAAC;AAC5D,IAAM,mBAAsD,CAAC;AAQ7D,IAAM,sBAA4C,CAAC;AAGnD,IAAM,yBAAyB;AAC/B,IAAM,aAAa;AACnB,IAAM,YAAY;AAGlB,IAAM,cAAc;AACpB,IAAM,qBAAqB;AAKpB,SAAS,uBAAgC;AAC9C,SAAO,eAAe,OAAO,QAAQ,GAAG,eAAe,UAAU;AACnE;AAEO,SAAS,oBAAmC;AACjD,MAAI,qBAAqB,GAAG;AAC1B,WAAO,QAAQ,QAAQ;AAAA,EACzB;AAEA,SAAO,IAAI,QAAQ,CAAC,SAAS,WAAW;AACtC,UAAM,WAA+B;AAAA,MACnC,SAAS,MAAM;AACb,YAAI,SAAS,UAAW,cAAa,SAAS,SAAS;AACvD,gBAAQ;AAAA,MACV;AAAA,MACA,QAAQ,CAAC,QAAe;AACtB,YAAI,SAAS,UAAW,cAAa,SAAS,SAAS;AACvD,eAAO,GAAG;AAAA,MACZ;AAAA,IACF;AAEA,aAAS,YAAY,WAAW,MAAM;AAEpC,YAAM,MAAM,oBAAoB,QAAQ,QAAQ;AAChD,UAAI,MAAM,GAAI,qBAAoB,OAAO,KAAK,CAAC;AAC/C,aAAO,IAAI,MAAM,oBAAoB,CAAC;AAAA,IACxC,GAAG,kBAAkB;AAErB,wBAAoB,KAAK,QAAQ;AAAA,EACnC,CAAC;AACH;AAKO,SAAS,QAAQ,WAAmB,kBAAiC;AAC1E,MAAI,aAAa;AACf,WAAO,QAAQ,QAAQ;AAAA,EACzB;AAEA,MAAI,cAAc;AAChB,WAAO,kBAAkB;AAAA,EAC3B;AAEA,iBAAe;AAEf,SAAO,IAAI,QAAQ,CAAC,SAAS,WAAW;AACtC,QAAI,cAAc;AAElB,QAAI;AACF,WAAK,IAAI,UAAU,QAAQ;AAAA,IAC7B,SAAS,KAAK;AACZ,cAAQ,MAAM,+CAA+C,GAAG;AAChE,qBAAe;AACf,aAAO,GAAG;AACV;AAAA,IACF;AAEA,OAAG,SAAS,MAAM;AAChB,oBAAc;AACd,qBAAe;AACf,0BAAoB;AACpB,oBAAc;AACd,cAAQ;AAGR,0BAAoB,QAAQ,CAAC,OAAO;AAClC,YAAI,GAAG,UAAW,cAAa,GAAG,SAAS;AAC3C,WAAG,QAAQ;AAAA,MACb,CAAC;AACD,0BAAoB,SAAS;AAAA,IAC/B;AAEA,OAAG,UAAU,MAAM;AACjB,oBAAc;AACd,0BAAoB;AAGpB,aAAO,OAAO,OAAO,EAAE,QAAQ,CAAC,QAAQ;AACtC,YAAI,IAAI,UAAW,cAAa,IAAI,SAAS;AAC7C,YAAI,OAAO,IAAI,MAAM,6BAA6B,CAAC;AAAA,MACrD,CAAC;AACD,aAAO,KAAK,OAAO,EAAE,QAAQ,CAAC,QAAQ,OAAO,QAAQ,OAAO,GAAG,CAAC,CAAC;AAGjE,UAAI,kBAAkB;AACpB,2BAAmB;AACnB,uBAAe;AACf,4BAAoB;AAGpB,YAAI,CAAC,aAAa;AAChB,wBAAc;AACd,iBAAO,IAAI,MAAM,2CAA2C,CAAC;AAAA,QAC/D;AACA;AAAA,MACF;AAGA,UAAI,qBAAqB,wBAAwB;AAC/C,gBAAQ,MAAM,iDAAiD;AAC/D,uBAAe;AAGf,cAAM,QAAQ,IAAI,MAAM,gCAAgC;AACxD,4BAAoB,QAAQ,CAAC,OAAO;AAClC,cAAI,GAAG,UAAW,cAAa,GAAG,SAAS;AAC3C,aAAG,OAAO,KAAK;AAAA,QACjB,CAAC;AACD,4BAAoB,SAAS;AAG7B,YAAI,CAAC,aAAa;AAChB,wBAAc;AACd,iBAAO,KAAK;AAAA,QACd;AACA;AAAA,MACF;AAGA,YAAM,QAAQ,KAAK,IAAI,aAAa,KAAK,IAAI,GAAG,iBAAiB,GAAG,SAAS;AAE7E;AACA,cAAQ;AAAA,QACN,uDAAuD,KAAK,eAAe,iBAAiB,IAAI,sBAAsB;AAAA,MACxH;AAIA,iBAAW,MAAM;AACf,gBAAQ,QAAQ,EACb,KAAK,MAAM;AACV,cAAI,CAAC,aAAa;AAChB,0BAAc;AACd,oBAAQ;AAAA,UACV;AAAA,QACF,CAAC,EACA,MAAM,CAAC,QAAQ;AACd,cAAI,CAAC,aAAa;AAChB,0BAAc;AACd,mBAAO,GAAG;AAAA,UACZ;AAAA,QACF,CAAC;AAAA,MACL,GAAG,KAAK;AAAA,IACV;AAEA,OAAG,UAAU,CAAC,QAAe;AAC3B,cAAQ,MAAM,yBAAyB,GAAG;AAAA,IAI5C;AAEA,OAAG,YAAY,CAAC,QAAQ,cAAc,GAAG;AAAA,EAC3C,CAAC;AACH;AAEA,SAAS,cAAc,OAAqB;AAC1C,QAAM,OAAO,KAAK,MAAM,MAAM,IAAI;AAElC,MAAI,KAAK,MAAM,QAAQ,KAAK,EAAE,GAAG;AAC/B,UAAM,UAAU,QAAQ,KAAK,EAAE;AAC/B,WAAO,QAAQ,KAAK,EAAE;AACtB,QAAI,KAAK,OAAO;AACd,cAAQ,OAAO,KAAK,KAAK;AAAA,IAC3B,OAAO;AACL,cAAQ,QAAQ,KAAK,MAAM;AAAA,IAC7B;AAAA,EACF;AAEA,MAAI,KAAK,WAAW,gCAAgC;AAClD,UAAM,SAAS,KAAK,OAAO,CAAC;AAC5B,sBAAkB;AAClB,qBAAiB,QAAQ,CAAC,OAAO,GAAG,MAAM,CAAC;AAAA,EAC7C;AACF;AAKA,eAAsB,IAAI,QAAgB,SAAoB,CAAC,GAAqB;AAElF,MAAI,CAAC,eAAe,CAAC,cAAc;AACjC,UAAM,QAAQ;AAAA,EAChB;AAGA,MAAI,CAAC,qBAAqB,GAAG;AAC3B,UAAM,kBAAkB;AAAA,EAC1B;AAEA,SAAO,IAAI,QAAQ,CAAC,SAAS,WAAW;AACtC,QAAI,CAAC,MAAM,GAAG,eAAe,UAAU,MAAM;AAC3C,aAAO,OAAO,IAAI,MAAM,gCAAgC,CAAC;AAAA,IAC3D;AAEA,UAAM,KAAK,EAAE;AAGb,UAAM,YAAY,WAAW,MAAM;AACjC,UAAI,QAAQ,EAAE,GAAG;AACf,eAAO,QAAQ,EAAE;AACjB,eAAO,IAAI,MAAM,gBAAgB,MAAM,EAAE,CAAC;AAAA,MAC5C;AAAA,IACF,GAAG,WAAW;AAEd,YAAQ,EAAE,IAAI;AAAA,MACZ,SAAS,CAAC,WAAW;AACnB,qBAAa,SAAS;AACtB,gBAAQ,MAAM;AAAA,MAChB;AAAA,MACA,QAAQ,CAAC,QAAQ;AACf,qBAAa,SAAS;AACtB,eAAO,GAAG;AAAA,MACZ;AAAA,MACA;AAAA,IACF;AAEA,OAAG,KAAK,KAAK,UAAU,EAAE,SAAS,OAAO,IAAI,QAAQ,OAAO,CAAC,CAAC;AAAA,EAChE,CAAC;AACH;AAMA,eAAsB,QAAQ,SAAiB;AAC7C,QAAM,aAAa,oBAAoB,OAAO;AAE9C,QAAM,SAAS,MAAM,IAAI,qCAAqC,CAAC,UAAU,CAAC;AAE1E,MAAI,CAAC,MAAM,QAAQ,MAAM,GAAG;AAC1B,YAAQ,KAAK,mCAAmC,MAAM;AACtD,WAAO,CAAC;AAAA,EACV;AAEA,SAAO,OAAO,IAAI,CAAC,OAAa;AAAA,IAC9B,SAAS,EAAE;AAAA,IACX,QAAQ,EAAE;AAAA,IACV,OAAO,EAAE;AAAA,IACT,QAAQ,EAAE;AAAA,IACV;AAAA,EACF,EAAE;AACJ;AAEA,eAAsB,WAAW,SAAiB;AAChD,QAAM,aAAa,oBAAoB,OAAO;AAC9C,QAAM,SAAU,MAAM,IAAI,qCAAqC,CAAC,UAAU,CAAC;AAE3E,QAAM,YAAY,OAAO,aAAa;AACtC,QAAM,cAAc,OAAO,eAAe;AAE1C,QAAM,YAAY,YAAY;AAG9B,QAAM,QAAQ,YAAY;AAE1B,SAAO;AACT;AAEA,eAAsB,UAAU,QAAgB;AAC9C,SAAO,MAAM,IAAI,oCAAoC,CAAC,MAAM,CAAC;AAC/D;AAEA,eAAsB,gBAAgB,IAAwD;AAE5F,MAAI,CAAC,eAAe,CAAC,cAAc;AACjC,UAAM,QAAQ;AAAA,EAChB;AAGA,MAAI,CAAC,qBAAqB,GAAG;AAC3B,UAAM,kBAAkB;AAAA,EAC1B;AAEA,mBAAiB,KAAK,EAAE;AAIxB,MAAI,CAAC,mBAAmB;AACtB,wBAAoB;AACpB,UAAM,SAAU,MAAM,IAAI,gCAAgC,CAAC,CAAC;AAC5D,QAAI,QAAQ;AACV,wBAAkB;AAElB,uBAAiB,QAAQ,CAAC,eAAe,WAAW,MAAM,CAAC;AAAA,IAC7D;AAAA,EACF,WAAW,iBAAiB;AAE1B,OAAG,eAAe;AAAA,EACpB;AAGA,SAAO,MAAM;AACX,UAAM,QAAQ,iBAAiB,QAAQ,EAAE;AACzC,QAAI,QAAQ,IAAI;AACd,uBAAiB,OAAO,OAAO,CAAC;AAAA,IAClC;AAAA,EACF;AACF;AAoCA,eAAsB,sBAAsB,SAAoD;AAC9F,QAAM,aAAa,oBAAoB,OAAO;AAC9C,QAAM,SAAS,MAAM,IAAI,qCAAqC,CAAC,UAAU,CAAC;AAE1E,MAAI,CAAC,MAAM,QAAQ,MAAM,GAAG;AAC1B,YAAQ,KAAK,mCAAmC,MAAM;AACtD,WAAO,CAAC;AAAA,EACV;AAEA,SAAO;AACT;AAEA,eAAsB,eAAe,MAAc;AACjD,SAAO,MAAM,IAAI,8BAA8B,CAAC,MAAM,IAAI,CAAC;AAC7D;AAEA,eAAsB,eAAe,QAAgB;AACnD,SAAO,MAAM,IAAI,2BAA2B,CAAC,QAAQ,MAAM,CAAC;AAC9D;AAEA,eAAsB,wBAAyC;AAC7D,MAAI;AACF,UAAM,SAAU,MAAM,IAAI,gCAAgC,CAAC,CAAC;AAC5D,WAAO,QAAQ,UAAU;AAAA,EAC3B,SAAS,KAAK;AACZ,YAAQ,MAAM,uCAAuC,GAAG;AACxD,WAAO;AAAA,EACT;AACF;AAEO,SAAS,aAAa;AAC3B,MAAI,IAAI;AACN,uBAAmB;AACnB,OAAG,MAAM;AACT,SAAK;AAAA,EACP;AACA,gBAAc;AACd,iBAAe;AACf,sBAAoB;AACpB,sBAAoB;AAGpB,SAAO,OAAO,OAAO,EAAE,QAAQ,CAAC,QAAQ;AACtC,QAAI,IAAI,UAAW,cAAa,IAAI,SAAS;AAAA,EAC/C,CAAC;AACD,SAAO,KAAK,OAAO,EAAE,QAAQ,CAAC,QAAQ,OAAO,QAAQ,OAAO,GAAG,CAAC,CAAC;AAGjE,sBAAoB,QAAQ,CAAC,OAAO;AAClC,QAAI,GAAG,UAAW,cAAa,GAAG,SAAS;AAAA,EAC7C,CAAC;AACD,sBAAoB,SAAS;AAC/B;;;AC1bA,IAAAC,oBAAqB;AACrB,IAAAC,mBAAqB;;;ACId,IAAM,oBAAoB;AAGjC,IAAI,qBAAoC;AAkBxC,IAAM,oBAAN,MAAwB;AAAA,EACd,cAAc,oBAAI,IAAwB;AAAA,EAC1C,SAAS;AAAA;AAAA,EACT,YAAY;AAAA,EACZ,KAAyB;AAAA;AAAA;AAAA;AAAA,EAKjC,MAAM,SAAwB;AAC5B,WAAO,IAAI,QAAQ,CAAC,SAAS,WAAW;AACtC,YAAM,UAAU,UAAU,KAAK,KAAK,QAAQ,CAAC;AAE7C,cAAQ,kBAAkB,CAAC,UAAU;AACnC,cAAM,KAAM,MAAM,OAA4B;AAC9C,YAAI,CAAC,GAAG,iBAAiB,SAAS,KAAK,SAAS,GAAG;AACjD,aAAG,kBAAkB,KAAK,WAAW,EAAE,SAAS,SAAS,CAAC;AAAA,QAC5D;AAAA,MACF;AAEA,cAAQ,YAAY,CAAC,UAAU;AAC7B,aAAK,KAAM,MAAM,OAA4B;AAC7C,gBAAQ;AAAA,MACV;AAEA,cAAQ,UAAU,MAAM,OAAO,QAAQ,KAAK;AAAA,IAC9C,CAAC;AAAA,EACH;AAAA;AAAA;AAAA;AAAA,EAKQ,sBAAsB,QAAkC;AAC9D,QAAI,OAAO,OAAO,OAAO,IAAI,WAAW,GAAG;AACzC,YAAM,MAAM,OAAO,IAAI,CAAC;AAExB,UAAI,IAAI,YAAa,CAAC,IAAI,QAAQ,IAAI,aAAa,QAAY;AAC7D,eAAO;AAAA,MACT;AAEA,UAAI,IAAI,SAAS,oEAAoE;AACnF,eAAO;AAAA,MACT;AAAA,IACF;AACA,WAAO;AAAA,EACT;AAAA;AAAA;AAAA;AAAA,EAKA,MAAc,WAAW,QAA4C;AACnE,QAAI,CAAC,KAAK,GAAI,QAAO;AAErB,WAAO,IAAI,QAAQ,CAAC,YAAY;AAC9B,YAAM,KAAK,KAAK,GAAI,YAAY,KAAK,WAAW,UAAU;AAC1D,YAAM,QAAQ,GAAG,YAAY,KAAK,SAAS;AAC3C,YAAM,UAAU,MAAM,IAAI,MAAM;AAEhC,cAAQ,YAAY,MAAM;AACxB,YAAI,QAAQ,QAAQ;AAClB,kBAAQ;AAAA,YACN,aAAa,QAAQ,OAAO;AAAA,YAC5B,YAAY,QAAQ,OAAO;AAAA,YAC3B,WAAW,QAAQ,OAAO;AAAA,UAC5B,CAAC;AAAA,QACH,OAAO;AACL,kBAAQ,IAAI;AAAA,QACd;AAAA,MACF;AACA,cAAQ,UAAU,MAAM,QAAQ,IAAI;AAAA,IACtC,CAAC;AAAA,EACH;AAAA;AAAA;AAAA;AAAA,EAKA,MAAc,SAAS,QAAgB,OAAkC;AACvE,QAAI,CAAC,KAAK,GAAI;AAEd,WAAO,IAAI,QAAQ,CAAC,YAAY;AAC9B,YAAM,KAAK,KAAK,GAAI,YAAY,KAAK,WAAW,WAAW;AAC3D,YAAM,QAAQ,GAAG,YAAY,KAAK,SAAS;AAC3C,YAAM,IAAI,EAAE,QAAQ,GAAG,MAAM,CAAC;AAC9B,SAAG,aAAa,MAAM,QAAQ;AAC9B,SAAG,UAAU,MAAM,QAAQ;AAAA,IAC7B,CAAC;AAAA,EACH;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,MAAM,cAAc,QAA4E;AAC9F,QAAI,gBAAgB;AACpB,QAAI,aAAa;AACjB,UAAM,iBAAiB;AAEvB,WAAO,aAAa,gBAAgB;AAClC;AAGA,YAAM,SAAS,KAAK,YAAY,IAAI,aAAa;AACjD,UAAI,QAAQ;AACV,YAAI,OAAO,YAAY;AAErB,cAAI,OAAO,gBAAgB,QAAQ,OAAO,gBAAgB,QAAW;AACnE,mBAAO,EAAE,gBAAgB,OAAO,YAAY;AAAA,UAC9C;AAAA,QAEF,WAAW,OAAO,WAAW;AAE3B,0BAAgB,OAAO;AACvB;AAAA,QACF;AAAA,MACF;AAGA,YAAM,WAAW,MAAM,KAAK,WAAW,aAAa;AACpD,UAAI,UAAU;AAEZ,aAAK,YAAY,IAAI,eAAe,QAAQ;AAC5C,YAAI,SAAS,YAAY;AAEvB,cAAI,SAAS,gBAAgB,QAAQ,SAAS,gBAAgB,QAAW;AACvE,mBAAO,EAAE,gBAAgB,SAAS,YAAY;AAAA,UAChD;AAAA,QAEF,WAAW,SAAS,WAAW;AAC7B,0BAAgB,SAAS;AACzB;AAAA,QACF;AAAA,MACF;AAGA,YAAM,SAAS,MAAM,eAAe,aAAa;AACjD,UAAI,CAAC,UAAU,CAAC,OAAO,MAAM;AAC3B,eAAO,EAAE,gBAAgB,MAAM,OAAO,sBAAsB,aAAa,GAAG;AAAA,MAC9E;AAGA,YAAM,aAAa,KAAK,sBAAsB,MAAM;AAGpD,UAAI,cAA6B;AACjC,UAAI,OAAO,iBAAiB,uBAAuB,QAAQ,uBAAuB,QAAW;AAC3F,sBAAc,qBAAqB,OAAO,gBAAgB;AAAA,MAC5D;AAGA,UAAI,YAA2B;AAC/B,UAAI,CAAC,cAAc,OAAO,OAAO,OAAO,IAAI,SAAS,KAAK,OAAO,IAAI,CAAC,EAAE,MAAM;AAC5E,oBAAY,OAAO,IAAI,CAAC,EAAE;AAAA,MAC5B;AAGA,YAAM,aAAyB;AAAA,QAC7B;AAAA;AAAA,QACA;AAAA,QACA;AAAA,MACF;AACA,WAAK,YAAY,IAAI,eAAe,UAAU;AAC9C,YAAM,KAAK,SAAS,eAAe,UAAU;AAE7C,UAAI,YAAY;AACd,eAAO,EAAE,gBAAgB,YAAY;AAAA,MACvC;AAEA,UAAI,CAAC,WAAW;AACd,eAAO,EAAE,gBAAgB,MAAM,OAAO,mCAAmC;AAAA,MAC3E;AAEA,sBAAgB;AAAA,IAClB;AAEA,WAAO,EAAE,gBAAgB,MAAM,OAAO,0BAA0B;AAAA,EAClE;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,aAAa,MAA2C;AAC5D,UAAM,SAAS,KAAK,WAAW,KAAK;AACpC,QAAI,CAAC,QAAQ;AACX,aAAO,EAAE,UAAU,OAAO,gBAAgB,MAAM,OAAO,sBAAsB;AAAA,IAC/E;AAEA,QAAI;AACF,YAAM,SAAS,MAAM,KAAK,cAAc,MAAM;AAC9C,UAAI,OAAO,SAAS,OAAO,mBAAmB,MAAM;AAClD,eAAO,EAAE,UAAU,OAAO,gBAAgB,MAAM,OAAO,OAAO,SAAS,4BAA4B;AAAA,MACrG;AACA,aAAO;AAAA,QACL,UAAU,OAAO,kBAAkB;AAAA,QACnC,gBAAgB,OAAO;AAAA,MACzB;AAAA,IACF,SAAS,KAAK;AACZ,aAAO;AAAA,QACL,UAAU;AAAA,QACV,gBAAgB;AAAA,QAChB,OAAO,eAAe,QAAQ,IAAI,UAAU,OAAO,GAAG;AAAA,MACxD;AAAA,IACF;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,cACJ,OACA,YAKC;AAED,yBAAqB,MAAM,sBAAsB;AAGjD,SAAK,YAAY,MAAM;AAEvB,UAAM,SAA2B,CAAC;AAClC,UAAM,WAA6B,CAAC;AACpC,UAAM,SAA+C,CAAC;AAEtD,aAAS,IAAI,GAAG,IAAI,MAAM,QAAQ,KAAK;AACrC,YAAM,OAAO,MAAM,CAAC;AACpB,YAAM,SAAS,MAAM,KAAK,aAAa,IAAI;AAE3C,UAAI,OAAO,OAAO;AAChB,eAAO,KAAK,EAAE,MAAM,OAAO,OAAO,MAAM,CAAC;AAEzC,iBAAS,KAAK;AAAA,UACZ,GAAG;AAAA,UACH,eAAe;AAAA,UACf,gBAAgB;AAAA,QAClB,CAAC;AAAA,MACH,WAAW,OAAO,UAAU;AAC1B,eAAO,KAAK;AAAA,UACV,GAAG;AAAA,UACH,eAAe;AAAA,UACf,gBAAgB,OAAO;AAAA,QACzB,CAAC;AAAA,MACH,OAAO;AACL,iBAAS,KAAK;AAAA,UACZ,GAAG;AAAA,UACH,eAAe;AAAA,UACf,gBAAgB,OAAO;AAAA,QACzB,CAAC;AAAA,MACH;AAGA,UAAI,YAAY;AACd,mBAAW,IAAI,GAAG,MAAM,MAAM;AAAA,MAChC;AAGA,UAAI,IAAI,MAAM,GAAG;AACf,cAAM,IAAI,QAAQ,CAAC,YAAY,WAAW,SAAS,CAAC,CAAC;AAAA,MACvD;AAAA,IACF;AAEA,WAAO,EAAE,QAAQ,UAAU,OAAO;AAAA,EACpC;AAAA;AAAA;AAAA;AAAA,EAKA,cAAoB;AAClB,SAAK,YAAY,MAAM;AACvB,QAAI,KAAK,IAAI;AACX,YAAM,KAAK,KAAK,GAAG,YAAY,KAAK,WAAW,WAAW;AAC1D,SAAG,YAAY,KAAK,SAAS,EAAE,MAAM;AAAA,IACvC;AAAA,EACF;AACF;AAEO,IAAM,oBAAoB,IAAI,kBAAkB;;;ACnSvD,IAAM,sBAAN,MAA0B;AAAA,EAChB,cAA2B;AAAA,EAC3B,eAAe,oBAAI,IAAiC;AAAA,EACpD,2BAA2B;AAAA;AAAA;AAAA;AAAA,EAKnC,QAAQ,MAAyB;AAC/B,QAAI,CAAC,CAAC,OAAO,UAAU,UAAU,EAAE,SAAS,IAAI,GAAG;AACjD,YAAM,IAAI,MAAM,yBAAyB,IAAI,EAAE;AAAA,IACjD;AACA,SAAK,cAAc;AAAA,EACrB;AAAA,EAEA,UAAuB;AACrB,WAAO,KAAK;AAAA,EACd;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,qBACJ,SACA,OACA,YACe;AACf,QAAI,KAAK,yBAA0B;AAEnC,SAAK,2BAA2B;AAEhC,QAAI;AACF,YAAM,kBAAkB,OAAO;AAE/B,YAAM,SAAS,MAAM,kBAAkB,cAAc,OAAO,UAAU;AAGtE,YAAM,gBAAgB,OAAO,OAAO;AAAA,QAClC,CAAC,KAAK,SAAS,MAAM,OAAO,KAAK,KAAK;AAAA,QACtC;AAAA,MACF;AACA,YAAM,kBAAkB,OAAO,SAAS;AAAA,QACtC,CAAC,KAAK,SAAS,MAAM,OAAO,KAAK,KAAK;AAAA,QACtC;AAAA,MACF;AAGA,WAAK,aAAa,IAAI,SAAS;AAAA,QAC7B,iBAAiB;AAAA,UACf,QAAQ,OAAO;AAAA,UACf,UAAU,OAAO;AAAA,UACjB,KAAK,CAAC,GAAG,OAAO,QAAQ,GAAG,OAAO,QAAQ;AAAA,QAC5C;AAAA,QACA,iBAAiB;AAAA,UACf,QAAQ;AAAA,UACR,UAAU;AAAA,UACV,KAAK,gBAAgB;AAAA,QACvB;AAAA,MACF,CAAC;AAGD,UAAI,OAAO,OAAO,SAAS,GAAG;AAC5B,gBAAQ,KAAK,kCAAkC,OAAO,OAAO,MAAM,EAAE;AACrE,eAAO,OAAO,MAAM,GAAG,CAAC,EAAE,QAAQ,CAAC,QAAQ;AACzC,gBAAM,SAAS,IAAI,KAAK,WAAW,IAAI,KAAK;AAC5C,kBAAQ,KAAK,KAAK,MAAM,KAAK,IAAI,KAAK,EAAE;AAAA,QAC1C,CAAC;AAAA,MACH;AAAA,IACF,UAAE;AACA,WAAK,2BAA2B;AAAA,IAClC;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAKA,iBAAiB,SAAmC;AAClD,UAAM,QAAQ,KAAK,aAAa,IAAI,OAAO;AAC3C,QAAI,CAAC,MAAO,QAAO,CAAC;AAEpB,YAAQ,KAAK,aAAa;AAAA,MACxB,KAAK;AACH,eAAO,MAAM,gBAAgB;AAAA,MAC/B,KAAK;AACH,eAAO,MAAM,gBAAgB;AAAA,MAC/B;AACE,eAAO,MAAM,gBAAgB;AAAA,IACjC;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAKA,YAAY,SAAmC;AAC7C,UAAM,QAAQ,KAAK,aAAa,IAAI,OAAO;AAC3C,QAAI,CAAC,MAAO,QAAO,CAAC;AACpB,WAAO,MAAM,gBAAgB;AAAA,EAC/B;AAAA;AAAA;AAAA;AAAA,EAKA,WAAW,SAAyB;AAClC,UAAM,QAAQ,KAAK,aAAa,IAAI,OAAO;AAC3C,QAAI,CAAC,MAAO,QAAO;AAEnB,WAAO,MAAM,gBAAgB,KAAK,WAAW;AAAA,EAC/C;AAAA;AAAA;AAAA;AAAA,EAKA,eAAe,SAAkC;AAC/C,UAAM,QAAQ,KAAK,aAAa,IAAI,OAAO;AAC3C,QAAI,CAAC,OAAO;AACV,aAAO,EAAE,QAAQ,IAAI,UAAU,IAAI,KAAK,GAAG;AAAA,IAC7C;AACA,WAAO,MAAM;AAAA,EACf;AAAA;AAAA;AAAA;AAAA,EAKA,kBAAkB,SAA0B;AAC1C,WAAO,KAAK,aAAa,IAAI,OAAO;AAAA,EACtC;AAAA;AAAA;AAAA;AAAA,EAKA,gBAAyB;AACvB,WAAO,KAAK;AAAA,EACd;AAAA;AAAA;AAAA;AAAA,EAKA,kBAAkB,SAAuB;AACvC,SAAK,aAAa,OAAO,OAAO;AAAA,EAClC;AAAA;AAAA;AAAA;AAAA,EAKA,iBAAuB;AACrB,SAAK,aAAa,MAAM;AACxB,sBAAkB,YAAY;AAAA,EAChC;AACF;AAEO,IAAM,eAAe,IAAI,oBAAoB;;;AC3J7C,IAAM,sBAAN,MAA0B;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAO/B,OAAO,WAAW,QAAgB,MAAyC;AACzE,WAAO,OAAO,UAAU,KAAK,CAAC,MAAM,EAAE,SAAS,IAAI;AAAA,EACrD;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASA,OAAO,WAAW,QAA+B;AAC/C,WAAO,OAAO,UAAU,KAAK,CAAC,MAAM,CAAC,EAAE,QAAQ,KAAK,OAAO,UAAU,CAAC;AAAA,EACxE;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,OAAO,iBAAiB,QAA2C;AACjE,QAAI,CAAC,OAAO,aAAa,OAAO,UAAU,WAAW,GAAG;AACtD,aAAO;AAAA,IACT;AACA,WAAO,OAAO,UAAU,KAAK,CAAC,MAAM,CAAC,EAAE,QAAQ,KAAK,OAAO,UAAU,CAAC;AAAA,EACxE;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAeA,OAAO,IAAI,QAAgB,YAAmC;AAC5D,QAAI,CAAC,WAAW,MAAM;AACpB,YAAM,IAAI,MAAM,mCAAmC;AAAA,IACrD;AAEA,UAAM,WAAW,KAAK,WAAW,QAAQ,WAAW,IAAI;AAExD,QAAI,UAAU;AAEZ,UAAI,SAAS,YAAY,WAAW,SAAS;AAC3C,cAAM,IAAI;AAAA,UACR,qDAAqD,WAAW,IAAI;AAAA,YACrD,SAAS,OAAO;AAAA,OACrB,WAAW,OAAO;AAAA;AAAA,QAE9B;AAAA,MACF;AAGA,aAAO;AAAA,IACT;AAGA,WAAO;AAAA,MACL,GAAG;AAAA,MACH,WAAW,CAAC,GAAG,OAAO,WAAW,UAAU;AAAA,IAC7C;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,OAAO,aAAa,QAAgB,MAAsB;AACxD,WAAO;AAAA,MACL,GAAG;AAAA,MACH,WAAW,OAAO,UAAU,OAAO,CAAC,MAAM,EAAE,SAAS,IAAI;AAAA,IAC3D;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,OAAO,YAAY,QAAiC;AAClD,WAAO,OAAO,UAAU,OAAO,CAAC,MAAM,CAAC,EAAE,QAAQ;AAAA,EACnD;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,OAAO,UAAU,QAAiC;AAChD,WAAO,OAAO,UAAU,OAAO,CAAC,MAAM,EAAE,QAAQ;AAAA,EAClD;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,OAAO,QAAQ,QAAgB,MAAuB;AACpD,WAAO,OAAO,UAAU,KAAK,CAAC,MAAM,EAAE,SAAS,IAAI;AAAA,EACrD;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASA,OAAO,SAAS,QAAsB;AACpC,UAAM,QAAQ,OAAO,UAAU,IAAI,CAAC,MAAM,EAAE,IAAI,EAAE,OAAO,OAAO;AAChE,UAAM,cAAc,IAAI,IAAI,KAAK;AAEjC,QAAI,MAAM,WAAW,YAAY,MAAM;AAErC,YAAM,aAAa,MAAM,OAAO,CAAC,GAAG,MAAM,MAAM,QAAQ,CAAC,MAAM,CAAC;AAChE,YAAM,IAAI;AAAA,QACR,yCAAyC,WAAW,KAAK,IAAI,CAAC;AAAA;AAAA,MAEhE;AAAA,IACF;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASA,OAAO,cAAc,QAAwB;AAC3C,UAAM,SAAS,CAAC,GAAG,OAAO,SAAS,EAAE,KAAK,CAAC,GAAG,MAAM;AAElD,YAAM,YAAY,EAAE,WAAW,IAAI;AACnC,YAAM,YAAY,EAAE,WAAW,IAAI;AACnC,UAAI,cAAc,UAAW,QAAO,YAAY;AAEhD,aAAO,EAAE,QAAQ,EAAE;AAAA,IACrB,CAAC;AAED,WAAO;AAAA,MACL,GAAG;AAAA,MACH,WAAW;AAAA,IACb;AAAA,EACF;AACF;;;AHhKA,IAAMC,MAAK,IAAI,iBAAAC,QAAS,GAAG,WAAW;AAGtC,IAAM,MAAM;AACZ,IAAM,OAAO;AACb,IAAM,MAAM;AAML,SAAS,mBAAmB,SAAyB;AAC1D,MAAI,CAAC,WAAW,OAAO,YAAY,UAAU;AAC3C,UAAM,IAAI,MAAM,mCAAmC;AAAA,EACrD;AAEA,QAAM,UAAU,aAAa,OAAO;AACpC,MAAI,CAAC,SAAS;AACZ,UAAM,IAAI,MAAM,6BAA6B,OAAO;AAAA,EACtD;AAGA,QAAM,UAAU,MAAM,KAAK,QAAQ,IAAI,EACpC,IAAI,CAAC,SAAS,KAAK,SAAS,EAAE,EAAE,SAAS,GAAG,GAAG,CAAC,EAChD,KAAK,EAAE;AAGV,SAAO,SAAS;AAClB;AAMA,SAAS,oBACP,QACA,WACQ;AACR,MAAI,WAAW;AAGf,cAAY;AAGZ,QAAM,YAAY,OAAO,MAAM,QAAQ,MAAM,KAAK,EAAG,QAAQ,EAAE,KAAK,EAAE;AACtE,QAAM,aAAa,aAAa,OAAO,MAAM,OAAO,SAAS,EAAE,GAAG,MAAM,EAAE,EAAE,MAAM,KAAK,EAAG,QAAQ,EAAE,KAAK,EAAE;AAC3G,QAAM,WAAW,YAAY;AAC7B,QAAM,eAAe,kBAAAC,QAAS,OAAO,kBAAAA,QAAS,OAAO,kBAAAA,QAAS,IAAI,IAAI,MAAM,QAAQ,CAAC,CAAC,EAAE,SAAS;AACjG,cAAY;AAGZ,QAAM,WAAW;AACjB,QAAM,eAAe,kBAAAA,QAAS,OAAO,kBAAAA,QAAS,OAAO,kBAAAA,QAAS,IAAI,IAAI,MAAM,QAAQ,CAAC,CAAC,EAAE,SAAS;AACjG,cAAY;AAGZ,cAAY,OAAO,MAAM,QAAQ,MAAM,KAAK,EAAG,QAAQ,EAAE,KAAK,EAAE;AAChE,eAAa,aAAa,OAAO,MAAM,OAAO,SAAS,EAAE,GAAG,MAAM,EAAE,EAAE,MAAM,KAAK,EAAG,QAAQ,EAAE,KAAK,EAAE;AAGrG,QAAM,aAAa,kBAAAA,QAAS,UAAU,kBAAAA,QAAS,OAAO,kBAAAA,QAAS,IAAI,IAAI,MAAM,SAAS,CAAC,CAAC,EAAE,SAAS;AACnG,QAAM,aAAa,aAAa,aAAa;AAC7C,cAAY;AAGZ,QAAM,YAAY,OAAO,MAAM,MAAM,SAAS,EAAE,EAAE,SAAS,IAAI,GAAG;AAClE,cAAY,UAAU,MAAM,KAAK,EAAG,QAAQ,EAAE,KAAK,EAAE;AAGrD,cAAY;AAGZ,MAAI,UAAU;AACd,aAAW,UAAU,OAAO,SAAS;AACnC,UAAM,eAAe,OAAO,MAAM,SAAS,EAAE,EAAE,SAAS,IAAI,GAAG;AAC/D,eAAW,aAAa,MAAM,KAAK,EAAG,QAAQ,EAAE,KAAK,EAAE;AACvD,UAAM,eAAe,mBAAmB,OAAO,OAAO;AACtD,UAAM,gBAAgB,aAAa,SAAS,GAAG,SAAS,EAAE,EAAE,SAAS,GAAG,GAAG;AAC3E,eAAW;AACX,eAAW;AAAA,EACb;AACA,QAAM,cAAc,kBAAAA,QAAS,OAAO,kBAAAA,QAAS,OAAO,kBAAAA,QAAS,IAAI,IAAI,MAAM,OAAO,CAAC,CAAC,EAAE,SAAS;AAC/F,cAAY;AAGZ,cAAY;AAGZ,cAAY;AAGZ,QAAM,QAAQ,kBAAAA,QAAS,OAAO,kBAAAA,QAAS,IAAI,IAAI,MAAM,QAAQ,CAAC;AAC9D,QAAM,QAAQ,kBAAAA,QAAS,OAAO,KAAK;AACnC,SAAO,MAAM,SAAS;AACxB;AAMA,SAAS,kBACP,QACA,SACA,WACQ;AAER,QAAM,UAAU,oBAAoB,QAAQ,SAAS;AAGrD,QAAM,YAAY,QAAQ,KAAK,OAAO;AAGtC,QAAM,YAAYF,IAAG,MAAM,EAAG,KAAK,CAAC;AACpC,MAAI,UAAU,EAAE,IAAI,SAAS,IAAI,GAAG;AAClC,cAAU,IAAIA,IAAG,MAAM,EAAG,IAAI,UAAU,CAAC;AAAA,EAC3C;AAEA,QAAM,SAAS,UAAU,MAAM,KAAK,IAAI;AAGxC,MAAI,UAAU;AACd,aAAW;AAGX,QAAM,UAAU,OAAO,SAAS,GAAG,SAAS,EAAE,EAAE,SAAS,GAAG,GAAG;AAC/D,aAAW;AACX,aAAW;AAGX,QAAM,aAAa,UAAU,SAAS,GAAG,SAAS,EAAE,EAAE,SAAS,GAAG,GAAG;AACrE,aAAW;AACX,aAAW;AAEX,SAAO;AACT;AAMO,SAAS,uBACd,QACA,SACA,WAC+B;AAC/B,MAAI,QAAQ;AAGZ,WAAS;AAGT,WAAS;AACT,WAAS;AAGT,WAAS;AAGT,QAAM,aAAa,OAAO,MAAM;AAChC,QAAM,eAAe,WAAW,MAAM,KAAK,EAAG,QAAQ,EAAE,KAAK,EAAE;AAC/D,WAAS;AAGT,QAAM,OAAO,OAAO,MAAM;AAC1B,YAAU,aAAa,KAAK,SAAS,EAAE,GAAG,MAAM,EAAE,EAAE,MAAM,KAAK,EAAG,QAAQ,EAAE,KAAK,EAAE;AAGnF,WAAS;AAGT,WAAS;AAGT,QAAM,cAAc,OAAO,QAAQ;AACnC,YAAU,MAAM,YAAY,SAAS,EAAE,GAAG,MAAM,EAAE;AAGlD,aAAW,UAAU,OAAO,SAAS;AAEnC,UAAM,YAAY,OAAO,MAAM,SAAS,EAAE,EAAE,SAAS,IAAI,GAAG;AAC5D,aAAS,UAAU,MAAM,KAAK,EAAG,QAAQ,EAAE,KAAK,EAAE;AAGlD,UAAM,eAAe,mBAAmB,OAAO,OAAO;AACtD,UAAM,gBAAgB,aAAa,SAAS,GAAG,SAAS,EAAE,EAAE,SAAS,GAAG,GAAG;AAC3E,aAAS;AACT,aAAS;AAAA,EACX;AAGA,QAAM,cAAc,kBAAkB,QAAQ,SAAS,SAAS;AAChE,WAAS;AAGT,WAAS;AAGT,MAAI,UAAU;AAGd,aAAW;AAGX,aAAW;AAGX,QAAM,iBAAiB,OAAO,MAAM,QAAQ,MAAM,KAAK,EAAG,QAAQ,EAAE,KAAK,EAAE;AAC3E,aAAW;AACX,cAAY,aAAa,OAAO,MAAM,OAAO,SAAS,EAAE,GAAG,MAAM,EAAE,EAAE,MAAM,KAAK,EAAG,QAAQ,EAAE,KAAK,EAAE;AAGpG,aAAW;AAGX,aAAW;AAGX,cAAY,MAAM,OAAO,QAAQ,OAAO,SAAS,EAAE,GAAG,MAAM,EAAE;AAG9D,aAAW,UAAU,OAAO,SAAS;AACnC,UAAM,aAAa,qBAAqB,OAAO,MAAM,SAAS,EAAE,GAAG,MAAM,GAAG;AAC5E,UAAM,qBAAqB,UAAU,MAAM,KAAK,EAAG,QAAQ,EAAE,KAAK,EAAE;AACpE,eAAW;AAEX,UAAM,eAAe,mBAAmB,OAAO,OAAO;AACtD,UAAM,gBAAgB,OAAO,aAAa,SAAS,GAAG,SAAS,EAAE,GAAG,MAAM,EAAE;AAC5E,eAAW;AACX,eAAW;AAAA,EACb;AAGA,aAAW;AAGX,QAAM,QAAQ,kBAAAE,QAAS,OAAO,kBAAAA,QAAS,IAAI,IAAI,MAAM,OAAO,CAAC;AAC7D,QAAM,QAAQ,kBAAAA,QAAS,OAAO,KAAK;AACnC,QAAM,OAAO,MAAM,SAAS,EAAE,MAAM,KAAK,EAAG,QAAQ,EAAE,KAAK,EAAE;AAE7D,SAAO;AAAA,IACL,KAAK;AAAA,IACL;AAAA,EACF;AACF;AAMO,SAAS,yBACd,QACA,QAC+B;AAE/B,QAAM,cAAc,OAAO,MAAM;AACjC,QAAM,eAAe,OAAO,UAAU,KAAK,OAAK,EAAE,YAAY,WAAW;AAGzE,MAAI;AAEJ,MAAI,cAAc,YAAY;AAE5B,oBAAgB,aAAa;AAAA,EAC/B,WAAW,OAAO,iBAAiB;AAEjC,oBAAgB,OAAO;AAAA,EACzB,OAAO;AAEL,oBAAgB,OAAO;AAAA,EACzB;AAEA,MAAI,CAAC,eAAe;AAClB,UAAM,IAAI,MAAM,2CAA2C,WAAW;AAAA,EACxE;AAEA,QAAM,UAAUF,IAAG,eAAe,eAAe,KAAK;AACtD,QAAM,YAAY,QAAQ,UAAU,MAAM,KAAK;AAG/C,QAAM,iBAAiB;AAAA,IACrB,OAAO;AAAA,MACL,SAAS,OAAO,MAAM;AAAA,MACtB,QAAQ,OAAO,MAAM;AAAA,MACrB,OAAO,OAAO,MAAM;AAAA,IACtB;AAAA,IACA,SAAS,OAAO;AAAA,EAClB;AAEA,QAAM,KAAK,uBAAuB,gBAAgB,SAAS,SAAS;AAEpE,SAAO;AAAA,IACL,KAAK,GAAG;AAAA,IACR,MAAM,GAAG;AAAA,EACX;AACF;AASO,SAAS,sBACd,UACA,YACA,kBACA,eACiB;AACjB,QAAM,iBAAiB,SAAS,OAAO,CAAC,KAAK,MAAM,MAAM,EAAE,OAAO,CAAC;AAEnE,MAAI,iBAAiB,aAAa,KAAK;AACrC,WAAO;AAAA,MACL,SAAS;AAAA,MACT,cAAc,CAAC;AAAA,MACf,OAAO,kCAAkC,iBAAiB,GAAG,sBAAsB,aAAa,OAAO,GAAG;AAAA,IAC5G;AAAA,EACF;AAIA,QAAM,gBAAgB,CAAC,GAAG,QAAQ,EAAE,KAAK,CAAC,GAAG,MAAM,EAAE,QAAQ,EAAE,KAAK;AACpE,QAAM,iBAAiB,cAAc,KAAK,OAAK,EAAE,SAAS,aAAa,GAAG;AAE1E,MAAI,gBAAgB;AAClB,UAAM,eAAe,eAAe,QAAQ,aAAa;AACzD,UAAM,KAAkB;AAAA,MACtB,OAAO;AAAA,QACL,MAAM,eAAe,QAAQ,eAAe,WAAW;AAAA,QACvD,MAAM,eAAe,QAAQ,eAAe,UAAU;AAAA,QACtD,OAAO,eAAe;AAAA,QACtB,SAAS,eAAe,WAAW;AAAA,MACrC;AAAA,MACA,SAAS,CAAC,EAAE,SAAS,kBAAkB,OAAO,WAAW,CAAC;AAAA,MAC1D,KAAK;AAAA,MACL;AAAA,MACA,eAAe;AAAA,IACjB;AAGA,QAAI,eAAe,MAAM;AACvB,SAAG,QAAQ,KAAK,EAAE,OAAO,cAAc,SAAS,cAAc,CAAC;AAAA,IACjE;AAEA,WAAO;AAAA,MACL,SAAS;AAAA,MACT,cAAc,CAAC,EAAE;AAAA,IACnB;AAAA,EACF;AAIA,QAAM,mBAAmB,CAAC,GAAG,QAAQ,EAAE,KAAK,CAAC,GAAG,MAAM,EAAE,QAAQ,EAAE,KAAK;AAEvE,QAAM,eAA8B,CAAC;AACrC,MAAI,kBAAkB;AAEtB,aAAW,QAAQ,kBAAkB;AACnC,QAAI,mBAAmB,EAAG;AAE1B,UAAM,YAAY,KAAK;AACvB,QAAI,WAAW;AACf,QAAI,eAAe;AAEnB,QAAI,aAAa,kBAAkB,KAAK;AAEtC,iBAAW;AACX,qBAAe,YAAY,kBAAkB;AAC7C,wBAAkB;AAAA,IACpB,OAAO;AAEL,iBAAW,YAAY;AACvB,UAAI,YAAY,EAAG;AACnB,yBAAmB;AAAA,IACrB;AAEA,UAAM,KAAkB;AAAA,MACtB,OAAO;AAAA,QACL,MAAM,KAAK,QAAQ,KAAK,WAAW;AAAA,QACnC,MAAM,KAAK,QAAQ,KAAK,UAAU;AAAA,QAClC,OAAO,KAAK;AAAA,QACZ,SAAS,KAAK,WAAW;AAAA,MAC3B;AAAA,MACA,SAAS,CAAC,EAAE,SAAS,kBAAkB,OAAO,SAAS,CAAC;AAAA,MACxD,KAAK;AAAA,MACL;AAAA,MACA,eAAe;AAAA,IACjB;AAGA,QAAI,eAAe,MAAM;AACvB,SAAG,QAAQ,KAAK,EAAE,OAAO,cAAc,SAAS,cAAc,CAAC;AAAA,IACjE;AAEA,iBAAa,KAAK,EAAE;AAAA,EACtB;AAEA,MAAI,kBAAkB,GAAG;AACvB,WAAO;AAAA,MACL,SAAS;AAAA,MACT,cAAc,CAAC;AAAA,MACf,OAAO,4CAA4C,kBAAkB,GAAG;AAAA,IAC1E;AAAA,EACF;AAEA,SAAO;AAAA,IACL,SAAS;AAAA,IACT;AAAA,EACF;AACF;AASA,eAAsB,sBACpB,QACA,WACA,aACA,aAC0B;AAC1B,MAAI,CAAC,aAAa,SAAS,GAAG;AAC5B,UAAM,IAAI,MAAM,2BAA2B;AAAA,EAC7C;AAGA,QAAM,cAAc,oBAAoB,WAAW,MAAM;AACzD,QAAM,gBAAgB,eAAe,YAAY;AACjD,QAAM,aAAa,KAAK,MAAM,cAAc,GAAG;AAG/C,MAAI;AACJ,QAAM,cAAc,aAAa,QAAQ;AAEzC,MAAI,aAAa,kBAAkB,aAAa,GAAG;AAEjD,YAAQ,aAAa,iBAAiB,aAAa;AACnD,YAAQ,IAAI,SAAS,MAAM,MAAM,IAAI,WAAW,QAAQ;AAAA,EAC1D,OAAO;AAEL,YAAQ,MAAM,QAAQ,aAAa;AACnC,YAAQ,IAAI,SAAS,MAAM,MAAM,qCAAqC;AAAA,EACxE;AAEA,MAAI,CAAC,MAAM,QAAQ,KAAK,KAAK,MAAM,WAAW,GAAG;AAC/C,UAAM,WAAW,gBAAgB,QAAQ,KAAK,WAAW,YAAY;AACrE,UAAM,IAAI,MAAM,qBAAqB,QAAQ,mBAAmB,aAAa;AAAA,EAC/E;AAEA,SAAO,sBAAsB,OAAO,YAAY,WAAW,aAAa;AAC1E;AASA,eAAsB,UACpB,QACA,WACA,aACA,aACA;AACA,QAAM,OAAO,MAAM,sBAAsB,QAAQ,WAAW,aAAa,WAAW;AAEpF,MAAI,CAAC,KAAK,SAAS;AACjB,UAAM,IAAI,MAAM,KAAK,SAAS,6BAA6B;AAAA,EAC7D;AAEA,QAAM,UAAU,CAAC;AAEjB,aAAW,MAAM,KAAK,cAAc;AAClC,UAAM,SAAS,yBAAyB,QAAQ,EAAE;AAClD,UAAM,SAAS,MAAM,UAAU,OAAO,GAAG;AACzC,YAAQ,KAAK;AAAA,MACX,MAAM,OAAO;AAAA,MACb,KAAK,OAAO;AAAA,MACZ,iBAAiB;AAAA,IACnB,CAAC;AAAA,EACH;AAEA,SAAO;AACT;","names":["deriveChildKey","deriveKeyAtPath","CryptoJS","import_crypto_js","elliptic","CryptoJS","CryptoJS","import_crypto_js","CryptoJS","import_crypto_js","deriveKeyAtPath","CryptoJS","deriveChildKey","import_crypto_js","import_elliptic","ec","elliptic","CryptoJS"]}
|