navio-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/README.md +758 -0
- package/dist/index.d.mts +2500 -0
- package/dist/index.d.ts +2500 -0
- package/dist/index.js +5050 -0
- package/dist/index.js.map +1 -0
- package/dist/index.mjs +5002 -0
- package/dist/index.mjs.map +1 -0
- package/package.json +77 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/key-manager.ts","../src/wallet-db.ts","../src/electrum.ts","../src/tx-keys-sync.ts","../src/sync-provider.ts","../src/p2p-protocol.ts","../src/p2p-sync.ts","../src/electrum-sync.ts","../src/client.ts"],"names":["Scalar","ChildKey","PublicKey","SubAddr","SubAddrId","DoublePublicKey","calcPrivSpendingKey","recoverAmount","ViewTag","HashId","calcNonce","getAmountRecoveryResultSize","getAmountRecoveryResultIsSucc","getAmountRecoveryResultAmount","deleteAmountsRetVal","Point","SQL","row","blsctModule2","reject","ripemd160","sha256","blsctModule3","RangeProof","AmountRecoveryReq"],"mappings":"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","file":"index.mjs","sourcesContent":["/**\n * KeyManager - Replicates blsct::keyman functionality from navio-core\n * Uses low-level functions from navio-blsct library\n *\n * Based on navio-blsct documentation: https://nav-io.github.io/libblsct-bindings/ts/\n */\n\nimport { sha256 } from '@noble/hashes/sha256';\nimport { ripemd160 } from '@noble/hashes/ripemd160';\n// Import from navio-blsct using ESM\nimport * as blsctModule from 'navio-blsct';\nconst Scalar = blsctModule.Scalar;\nconst ChildKey = blsctModule.ChildKey;\nconst PublicKey = blsctModule.PublicKey;\nconst SubAddr = blsctModule.SubAddr;\nconst SubAddrId = blsctModule.SubAddrId;\nconst DoublePublicKey = blsctModule.DoublePublicKey;\n// Helper functions and classes\nconst calcPrivSpendingKey = blsctModule.calcPrivSpendingKey;\nconst recoverAmount = blsctModule.recoverAmount;\nconst ViewTag = blsctModule.ViewTag;\nconst HashId = blsctModule.HashId;\nconst calcNonce = blsctModule.calcNonce;\n// Amount recovery helpers\nconst getAmountRecoveryResultSize = blsctModule.getAmountRecoveryResultSize;\nconst getAmountRecoveryResultIsSucc = blsctModule.getAmountRecoveryResultIsSucc;\nconst getAmountRecoveryResultAmount = blsctModule.getAmountRecoveryResultAmount;\nconst deleteAmountsRetVal = blsctModule.deleteAmountsRetVal;\n\n// Derive types from runtime values using typeof\ntype ScalarType = InstanceType<typeof Scalar>;\n// ViewKey is just a Scalar (derived via txKey.toViewKey())\ntype ViewKeyType = ScalarType;\ntype PublicKeyType = InstanceType<typeof PublicKey>;\ntype SubAddrType = InstanceType<typeof SubAddr>;\n\nimport type {\n HDChain,\n SubAddressIdentifier,\n SeedType,\n CTxOut,\n CTxDestination,\n AmountRecoveryResult,\n} from './key-manager.types';\n\n/**\n * KeyManager class for managing BLS CT keys.\n * Replicates functionality from navio-core's blsct::keyman.\n * \n * Handles HD key derivation, sub-address generation, output detection,\n * and amount recovery for BLSCT confidential transactions.\n * \n * @category Keys\n */\nexport class KeyManager {\n private hdChain: HDChain | null = null;\n private viewKey: ViewKeyType | null = null;\n private spendPublicKey: PublicKeyType | null = null;\n private masterSeed: ScalarType | null = null;\n private spendKeyId: Uint8Array | null = null;\n private viewKeyId: Uint8Array | null = null;\n private tokenKeyId: Uint8Array | null = null;\n private blindingKeyId: Uint8Array | null = null;\n private seedId: Uint8Array | null = null;\n\n // In-memory key storage (replicates KeyRing functionality)\n private keys: Map<string, ScalarType> = new Map(); // keyId (hex) -> secret key\n private outKeys: Map<string, ScalarType> = new Map(); // outId (hex) -> secret key\n private cryptedKeys: Map<string, { publicKey: PublicKeyType; encryptedSecret: Uint8Array }> =\n new Map(); // keyId -> encrypted key\n private cryptedOutKeys: Map<string, { publicKey: PublicKeyType; encryptedSecret: Uint8Array }> =\n new Map(); // outId -> encrypted key\n private keyMetadata: Map<string, { nCreateTime: number }> = new Map(); // keyId -> metadata\n\n // SubAddress management\n private subAddressCounter: Map<number, number> = new Map();\n private subAddresses: Map<string, SubAddressIdentifier> = new Map(); // hashId (hex) -> SubAddressIdentifier\n private subAddressesStr: Map<string, string> = new Map(); // SubAddress (serialized) -> hashId (hex)\n private subAddressPool: Map<number, Set<number>> = new Map(); // account -> Set<address indices>\n private subAddressPoolTime: Map<string, number> = new Map(); // \"${account}:${address}\" -> timestamp\n private timeFirstKey: number | null = null; // Creation time of first key\n\n // Flags\n private fViewKeyDefined = false;\n private fSpendKeyDefined = false;\n\n /**\n * Check if HD is enabled (has a seed)\n * @returns True if HD is enabled\n */\n isHDEnabled(): boolean {\n return this.seedId !== null;\n }\n\n /**\n * Check if the wallet can generate new keys\n * @returns True if HD is enabled\n */\n canGenerateKeys(): boolean {\n return this.isHDEnabled();\n }\n\n /**\n * Generate a new random seed\n * @returns A new random Scalar (seed)\n */\n generateNewSeed(): ScalarType {\n // Scalar() constructor generates a random scalar\n return new Scalar();\n }\n\n /**\n * Set the HD seed and derive all master keys\n * This replicates SetHDSeed from keyman.cpp\n * Uses navio-blsct API: ChildKey(seed).toTxKey().toViewKey() etc.\n * @param seed - The master seed Scalar\n */\n setHDSeed(seed: ScalarType): void {\n // Store master seed\n this.masterSeed = seed;\n\n // Derive keys following the same path as navio-core using navio-blsct API\n // FromSeedToChildKey: ChildKey(seed) with index 130\n const childKey = new ChildKey(seed);\n\n // FromChildToTransactionKey: childKey.toTxKey() (index 0)\n const txKey = childKey.toTxKey();\n\n // FromChildToBlindingKey: childKey.toBlindingKey() (index 1)\n const blindingKey = childKey.toBlindingKey();\n\n // FromChildToTokenKey: childKey.toTokenKey() (index 2)\n const tokenKey = childKey.toTokenKey();\n\n // FromTransactionToViewKey: txKey.toViewKey() (index 0)\n const viewKey = Scalar.deserialize(txKey.toViewKey().serialize());\n\n // FromTransactionToSpendKey: txKey.toSpendingKey() (index 1)\n const spendKey = Scalar.deserialize(txKey.toSpendingKey().serialize());\n\n // Store the derived keys\n this.viewKey = viewKey;\n // spendKey stored for future use (signing transactions)\n\n // Get public key from spend key\n // In navio-core, spendKey is a PrivateKey (Scalar) and we call GetPublicKey() on it\n let spendPublicKey: PublicKeyType = PublicKey.fromScalar(spendKey);\n\n this.spendPublicKey = spendPublicKey;\n\n // Calculate IDs using hash160\n // Get public key representations for hashing\n const seedPublicKey = this.getPublicKeyFromScalar(seed);\n const viewPublicKey = this.getPublicKeyFromViewKey(viewKey);\n const spendPublicKeyBytes = this.getPublicKeyBytes(this.spendPublicKey);\n const tokenPublicKey = this.getPublicKeyFromScalar(tokenKey);\n const blindingPublicKey = this.getPublicKeyFromScalar(blindingKey);\n\n this.seedId = this.hash160(seedPublicKey);\n this.spendKeyId = this.hash160(spendPublicKeyBytes);\n this.viewKeyId = this.hash160(viewPublicKey);\n this.tokenKeyId = this.hash160(tokenPublicKey);\n this.blindingKeyId = this.hash160(blindingPublicKey);\n\n // Initialize HD chain\n this.hdChain = {\n version: 1, // HDChain::VERSION_HD_BASE\n seedId: this.seedId,\n spendId: this.spendKeyId,\n viewId: this.viewKeyId,\n tokenId: this.tokenKeyId,\n blindingId: this.blindingKeyId,\n };\n\n // Reset sub-address counters\n this.subAddressCounter.clear();\n }\n\n /**\n * Setup key generation from a seed\n * Replicates SetupGeneration from keyman.cpp\n * @param seedBytes - The seed bytes (32 bytes for master key, 80 bytes for view/spend keys)\n * @param type - The type of seed being imported\n * @param force - Force setup even if HD is already enabled\n * @returns True if setup was successful\n */\n setupGeneration(\n seedBytes: Uint8Array,\n type: SeedType = 'IMPORT_MASTER_KEY',\n force = false\n ): boolean {\n if (this.canGenerateKeys() && !force) {\n return false;\n }\n\n if (seedBytes.length === 32) {\n if (type === 'IMPORT_MASTER_KEY') {\n // Create Scalar from bytes\n const seed = this.createScalarFromBytes(seedBytes);\n this.setHDSeed(seed);\n }\n } else if (seedBytes.length === 80) {\n if (type === 'IMPORT_VIEW_KEY') {\n // First 32 bytes are view key, last 48 bytes are spending public key\n const viewKeyBytes = seedBytes.slice(0, 32);\n const spendingKeyBytes = seedBytes.slice(32, 80);\n\n // Create ViewKey from bytes\n const viewKey = this.createViewKeyFromBytes(viewKeyBytes);\n // Create PublicKey from bytes\n const spendingPublicKey = this.createPublicKeyFromBytes(spendingKeyBytes);\n\n this.viewKey = Scalar.deserialize(viewKey.serialize());\n this.spendPublicKey = spendingPublicKey;\n\n // Note: This is a simplified import - full implementation would need more setup\n }\n } else {\n // Generate new seed\n const seed = this.generateNewSeed();\n this.setHDSeed(seed);\n }\n\n // Initialize sub-address pools for default accounts\n this.newSubAddressPool(0);\n this.newSubAddressPool(-1); // Change account\n this.newSubAddressPool(-2); // Staking account\n\n return true;\n }\n\n /**\n * Get the master seed key\n * @returns The master seed Scalar\n */\n getMasterSeedKey(): ScalarType {\n if (!this.isHDEnabled()) {\n throw new Error('HD is not enabled');\n }\n if (!this.masterSeed) {\n throw new Error('Master seed key not available');\n }\n return this.masterSeed;\n }\n\n /**\n * Get the private view key\n * @returns The view key\n */\n getPrivateViewKey(): ViewKeyType {\n if (!this.viewKey) {\n throw new Error('View key is not available');\n }\n return this.viewKey;\n }\n\n /**\n * Get the public spending key\n * @returns The public spending key\n */\n getPublicSpendingKey(): PublicKeyType {\n if (!this.spendPublicKey) {\n throw new Error('Spending key is not available');\n }\n return this.spendPublicKey;\n }\n\n /**\n * Get a sub-address for the given identifier\n * Uses navio-blsct SubAddr.generate() method\n * @param id - The sub-address identifier (defaults to account 0, address 0)\n * @returns The sub-address (SubAddr)\n */\n getSubAddress(id: SubAddressIdentifier = { account: 0, address: 0 }): SubAddrType {\n if (!this.viewKey || !this.spendPublicKey) {\n throw new Error('View key or spending key not available');\n }\n\n // Create SubAddrId from identifier\n // SubAddrId constructor may take a single object parameter\n // Using type assertion to work around API differences\n const subAddrId = SubAddrId.generate(id.account, id.address);\n\n // Generate sub-address using navio-blsct API\n // Based on docs: SubAddr.generate(viewKey, spendingPubKey, subAddrId)\n return SubAddr.generate(this.viewKey, this.spendPublicKey, subAddrId);\n }\n\n /**\n * Generate a new sub-address for the given account\n * @param account - The account number (0 for main, -1 for change, -2 for staking)\n * @returns The generated sub-address and its identifier\n */\n generateNewSubAddress(account: number): { subAddress: SubAddrType; id: SubAddressIdentifier } {\n if (!this.canGenerateKeys()) {\n throw new Error('Cannot generate keys - HD not enabled');\n }\n\n if (!this.viewKey || !this.spendPublicKey) {\n throw new Error('View key or spending public key not available');\n }\n\n // Initialize counter if needed\n if (!this.subAddressCounter.has(account)) {\n this.subAddressCounter.set(account, 0);\n }\n\n const addressIndex = this.subAddressCounter.get(account)!;\n const id: SubAddressIdentifier = { account, address: addressIndex };\n\n // Increment counter\n this.subAddressCounter.set(account, addressIndex + 1);\n\n const subAddress = this.getSubAddress(id);\n\n // Calculate hashId for this sub-address so we can look it up during output scanning\n // Generate DoublePublicKey which contains (blindingKey, spendingKey) for this sub-address\n const dpk = DoublePublicKey.fromKeysAcctAddr(this.viewKey, this.spendPublicKey, account, addressIndex);\n const serialized = dpk.serialize();\n\n // DoublePublicKey serializes as 192 hex chars (96 bytes = 2 x 48-byte G1 points)\n // First 96 chars = blinding key, second 96 chars = spending key\n const spendingKeyHex = serialized.substring(96);\n\n // The hashId is Hash160(spendingKey) - this is what calcKeyId computes for tx outputs\n // When a sender creates an output for us, the D_prime derivation results in our spendingKey\n const spendingKeyBytes = Buffer.from(spendingKeyHex, 'hex');\n const hashIdBytes = this.hash160(spendingKeyBytes);\n const hashIdHex = this.bytesToHex(hashIdBytes);\n this.subAddresses.set(hashIdHex, id);\n\n return { subAddress, id };\n }\n\n /**\n * Get a new destination (sub-address) from the pool or generate one\n * @param account - The account number\n * @returns The sub-address destination (SubAddr)\n */\n getNewDestination(account = 0): SubAddrType {\n // Top up pool if needed\n this.topUp();\n\n // Try to get from pool first\n const poolSize = this.getSubAddressPoolSize(account);\n if (poolSize > 0) {\n // In full implementation, would reserve from pool\n // For now, generate new one\n }\n\n const { subAddress } = this.generateNewSubAddress(account);\n return subAddress;\n }\n\n /**\n * Create a new sub-address pool for an account\n * @param account - The account number\n * @returns True if successful\n */\n newSubAddressPool(account: number): boolean {\n // Clear existing pool\n this.subAddressPool.set(account, new Set());\n\n // Top up the pool\n return this.topUpAccount(account);\n }\n\n /**\n * Top up all sub-address pools\n * @param size - Target size for pools (0 = use default)\n * @returns True if successful\n */\n topUp(size = 0): boolean {\n if (!this.canGenerateKeys()) {\n return false;\n }\n\n const targetSize = size > 0 ? size : 100; // DEFAULT_KEYPOOL_SIZE\n\n for (const account of Array.from(this.subAddressPool.keys())) {\n if (!this.topUpAccount(account, targetSize)) {\n return false;\n }\n }\n\n return true;\n }\n\n /**\n * Top up a specific account's sub-address pool\n * @param account - The account number\n * @param size - Target size (0 = use default)\n * @returns True if successful\n */\n topUpAccount(account: number, size = 0): boolean {\n const targetSize = size > 0 ? size : 100; // DEFAULT_KEYPOOL_SIZE\n\n if (!this.subAddressPool.has(account)) {\n this.subAddressPool.set(account, new Set());\n }\n\n const pool = this.subAddressPool.get(account)!;\n const missing = Math.max(targetSize - pool.size, 0);\n\n for (let i = 0; i < missing; i++) {\n const { id } = this.generateNewSubAddress(account);\n pool.add(id.address);\n }\n\n return true;\n }\n\n /**\n * Get the size of the sub-address pool for an account\n * @param account - The account number\n * @returns The pool size\n */\n getSubAddressPoolSize(account: number): number {\n return this.subAddressPool.get(account)?.size ?? 0;\n }\n\n /**\n * Calculate hash ID from blinding and spending keys\n * Uses HashId.generate() from navio-blsct\n * @param blindingKey - The blinding public key\n * @param spendingKey - The spending public key\n * @returns The hash ID (20 bytes)\n */\n calculateHashId(blindingKey: PublicKeyType, spendingKey: PublicKeyType): Uint8Array {\n if (!this.viewKey) {\n throw new Error('View key not available');\n }\n\n // Use HashId.generate() from navio-blsct\n // The view key needs to be a Scalar, which is what we have\n const hashId = HashId.generate(blindingKey, spendingKey, this.viewKey);\n\n // HashId.serialize() returns a hex string, convert to bytes\n const hashIdHex = hashId.serialize();\n return Uint8Array.from(Buffer.from(hashIdHex, 'hex'));\n }\n\n /**\n * Calculate view tag for output detection\n * Uses ViewTag from navio-blsct\n * @param blindingKey - The blinding public key\n * @returns The view tag (16-bit number)\n */\n calculateViewTag(blindingKey: PublicKeyType): number {\n if (!this.viewKey) {\n throw new Error('View key not available');\n }\n\n // ViewTag constructor computes the view tag from blinding key and view key\n // The .value property contains the numeric view tag\n const viewTagObj = new ViewTag(blindingKey, this.viewKey);\n return viewTagObj.value;\n }\n\n /**\n * Calculate nonce for range proof recovery\n * Uses calcNonce from navio-blsct\n * @param blindingKey - The blinding public key\n * @returns The nonce (Point)\n */\n calculateNonce(blindingKey: PublicKeyType): any {\n if (!this.viewKey) {\n throw new Error('View key not available');\n }\n\n // Use calcNonce from navio-blsct\n // Need to pass .value() for the underlying SWIG objects\n const result = calcNonce(blindingKey.value(), this.viewKey.value());\n \n // Wrap result in Point object\n const Point = blsctModule.Point;\n return new Point(result);\n }\n\n /**\n * Get the HD chain information\n * @returns The HD chain or null if not set\n */\n getHDChain(): HDChain | null {\n return this.hdChain;\n }\n\n // ============================================================================\n // Key Loading Methods (from database - don't persist, just load into memory)\n // ============================================================================\n\n /**\n * Load a key pair from storage into memory (used by LoadWallet)\n * Replicates LoadKey from keyman.cpp\n * @param secretKey - The secret key\n * @param publicKey - The public key\n * @returns True if successful\n */\n loadKey(secretKey: ScalarType, publicKey: PublicKeyType): boolean {\n return this.addKeyPubKeyInner(secretKey, publicKey);\n }\n\n /**\n * Load a view key from storage into memory\n * Replicates LoadViewKey from keyman.cpp\n * @param viewKey - The view key\n * @param publicKey - The view key's public key\n * @returns True if successful\n */\n loadViewKey(viewKey: ViewKeyType): boolean {\n if (!this.fViewKeyDefined) {\n this.viewKey = Scalar.deserialize(viewKey.serialize());\n this.fViewKeyDefined = true;\n return true;\n }\n return true;\n }\n\n /**\n * Load a spend key from storage into memory\n * Replicates LoadSpendKey from keyman.cpp\n * @param publicKey - The spending public key\n * @returns True if successful\n */\n loadSpendKey(publicKey: PublicKeyType): boolean {\n if (!this.fSpendKeyDefined) {\n this.spendPublicKey = publicKey;\n this.fSpendKeyDefined = true;\n return true;\n }\n return true;\n }\n\n /**\n * Load an output key from storage into memory\n * Replicates LoadOutKey from keyman.cpp\n * @param secretKey - The secret key for the output\n * @param outId - The output ID (uint256)\n * @returns True if successful\n */\n loadOutKey(secretKey: ScalarType, outId: Uint8Array): boolean {\n return this.addKeyOutKeyInner(secretKey, outId);\n }\n\n /**\n * Load an encrypted key from storage into memory\n * Replicates LoadCryptedKey from keyman.cpp\n * @param publicKey - The public key\n * @param encryptedSecret - The encrypted secret key\n * @param checksumValid - Whether the checksum is valid\n * @returns True if successful\n */\n loadCryptedKey(\n publicKey: PublicKeyType,\n encryptedSecret: Uint8Array,\n checksumValid: boolean\n ): boolean {\n if (!checksumValid) {\n // Note: checksum invalid - decryption may not be thorough\n }\n return this.addCryptedKeyInner(publicKey, encryptedSecret);\n }\n\n /**\n * Load an encrypted output key from storage into memory\n * Replicates LoadCryptedOutKey from keyman.cpp\n * @param outId - The output ID\n * @param publicKey - The public key\n * @param encryptedSecret - The encrypted secret key\n * @param checksumValid - Whether the checksum is valid\n * @returns True if successful\n */\n loadCryptedOutKey(\n outId: Uint8Array,\n publicKey: PublicKeyType,\n encryptedSecret: Uint8Array,\n checksumValid: boolean\n ): boolean {\n if (!checksumValid) {\n // Note: checksum invalid - decryption may not be thorough\n }\n return this.addCryptedOutKeyInner(outId, publicKey, encryptedSecret);\n }\n\n /**\n * Load HD chain from storage\n * Replicates LoadHDChain from keyman.cpp\n * @param chain - The HD chain to load\n */\n loadHDChain(chain: HDChain): void {\n this.hdChain = chain;\n this.seedId = chain.seedId;\n this.spendKeyId = chain.spendId;\n this.viewKeyId = chain.viewId;\n this.tokenKeyId = chain.tokenId;\n this.blindingKeyId = chain.blindingId;\n }\n\n /**\n * Load key metadata from storage\n * Replicates LoadKeyMetadata from keyman.cpp\n * @param keyId - The key ID\n * @param metadata - The key metadata\n */\n loadKeyMetadata(keyId: Uint8Array, metadata: { nCreateTime: number }): void {\n const keyIdHex = this.bytesToHex(keyId);\n this.keyMetadata.set(keyIdHex, metadata);\n this.updateTimeFirstKey(metadata.nCreateTime);\n }\n\n // ============================================================================\n // Key Adding Methods (add and persist to database)\n // ============================================================================\n\n /**\n * Add a key pair and save to database\n * Replicates AddKeyPubKey from keyman.cpp\n * @param secretKey - The secret key\n * @param publicKey - The public key\n * @returns True if successful\n */\n addKeyPubKey(secretKey: ScalarType, publicKey: PublicKeyType): boolean {\n // Add to memory\n if (!this.addKeyPubKeyInner(secretKey, publicKey)) {\n return false;\n }\n // In a database wallet, this would also save to database\n // For in-memory KeyManager, we just store in memory\n return true;\n }\n\n /**\n * Add an output key and save to database\n * Replicates AddKeyOutKey from keyman.cpp\n * @param secretKey - The secret key\n * @param outId - The output ID\n * @returns True if successful\n */\n addKeyOutKey(secretKey: ScalarType, outId: Uint8Array): boolean {\n // Add to memory\n if (!this.addKeyOutKeyInner(secretKey, outId)) {\n return false;\n }\n // In a database wallet, this would also save to database\n return true;\n }\n\n /**\n * Add a view key and save to database\n * Replicates AddViewKey from keyman.cpp\n * @param viewKey - The view key\n * @param publicKey - The view key's public key\n * @returns True if successful\n */\n addViewKey(viewKey: ViewKeyType, _publicKey: PublicKeyType): boolean {\n if (!this.fViewKeyDefined) {\n this.viewKey = Scalar.deserialize(viewKey.serialize());\n this.fViewKeyDefined = true;\n // In a database wallet, this would also save to database\n return true;\n }\n return true;\n }\n\n /**\n * Add a spend key and save to database\n * Replicates AddSpendKey from keyman.cpp\n * @param publicKey - The spending public key\n * @returns True if successful\n */\n addSpendKey(publicKey: PublicKeyType): boolean {\n if (!this.fSpendKeyDefined) {\n this.spendPublicKey = publicKey;\n this.fSpendKeyDefined = true;\n // In a database wallet, this would also save to database\n return true;\n }\n return true;\n }\n\n /**\n * Add an encrypted key and save to database\n * Replicates AddCryptedKey from keyman.cpp\n * @param publicKey - The public key\n * @param encryptedSecret - The encrypted secret key\n * @returns True if successful\n */\n addCryptedKey(publicKey: PublicKeyType, encryptedSecret: Uint8Array): boolean {\n if (!this.addCryptedKeyInner(publicKey, encryptedSecret)) {\n return false;\n }\n // In a database wallet, this would also save to database\n return true;\n }\n\n /**\n * Add an encrypted output key and save to database\n * Replicates AddCryptedOutKey from keyman.cpp\n * @param outId - The output ID\n * @param publicKey - The public key\n * @param encryptedSecret - The encrypted secret key\n * @returns True if successful\n */\n addCryptedOutKey(\n outId: Uint8Array,\n publicKey: PublicKeyType,\n encryptedSecret: Uint8Array\n ): boolean {\n if (!this.addCryptedOutKeyInner(outId, publicKey, encryptedSecret)) {\n return false;\n }\n // In a database wallet, this would also save to database\n return true;\n }\n\n /**\n * Add HD chain and save to database\n * Replicates AddHDChain from keyman.cpp\n * @param chain - The HD chain to add\n */\n addHDChain(chain: HDChain): void {\n this.hdChain = chain;\n this.seedId = chain.seedId;\n this.spendKeyId = chain.spendId;\n this.viewKeyId = chain.viewId;\n this.tokenKeyId = chain.tokenId;\n this.blindingKeyId = chain.blindingId;\n // In a database wallet, this would also save to database\n }\n\n // ============================================================================\n // Key Retrieval Methods (get keys from memory)\n // ============================================================================\n\n /**\n * Check if a key exists\n * Replicates HaveKey from keyman.cpp\n * @param keyId - The key ID (hash160 of public key)\n * @returns True if the key exists\n */\n haveKey(keyId: Uint8Array): boolean {\n const keyIdHex = this.bytesToHex(keyId);\n // Check unencrypted keys\n if (this.keys.has(keyIdHex)) {\n return true;\n }\n // Check encrypted keys\n if (this.cryptedKeys.has(keyIdHex)) {\n return true;\n }\n return false;\n }\n\n /**\n * Get a key by key ID\n * Replicates GetKey from keyman.cpp\n * @param keyId - The key ID\n * @returns The secret key or null if not found\n */\n getKey(keyId: Uint8Array): ScalarType | null {\n const keyIdHex = this.bytesToHex(keyId);\n // Try unencrypted keys first\n if (this.keys.has(keyIdHex)) {\n return this.keys.get(keyIdHex)!;\n }\n // Encrypted keys would need decryption (not implemented in in-memory version)\n return null;\n }\n\n /**\n * Get an output key by output ID\n * Replicates GetOutKey from keyman.cpp\n * @param outId - The output ID\n * @returns The secret key or null if not found\n */\n getOutKey(outId: Uint8Array): ScalarType | null {\n const outIdHex = this.bytesToHex(outId);\n // Try unencrypted keys first\n if (this.outKeys.has(outIdHex)) {\n return this.outKeys.get(outIdHex)!;\n }\n // Encrypted keys would need decryption (not implemented in in-memory version)\n return null;\n }\n\n // ============================================================================\n // Internal helper methods for key management\n // ============================================================================\n\n /**\n * Internal method to add a key pair (used by both Load and Add methods)\n */\n private addKeyPubKeyInner(secretKey: ScalarType, publicKey: PublicKeyType): boolean {\n const keyId = this.hash160(this.getPublicKeyBytes(publicKey));\n const keyIdHex = this.bytesToHex(keyId);\n this.keys.set(keyIdHex, secretKey);\n return true;\n }\n\n /**\n * Internal method to add an output key (used by both Load and Add methods)\n */\n private addKeyOutKeyInner(secretKey: ScalarType, outId: Uint8Array): boolean {\n const outIdHex = this.bytesToHex(outId);\n this.outKeys.set(outIdHex, secretKey);\n return true;\n }\n\n /**\n * Internal method to add an encrypted key (used by both Load and Add methods)\n */\n private addCryptedKeyInner(publicKey: PublicKeyType, encryptedSecret: Uint8Array): boolean {\n const keyId = this.hash160(this.getPublicKeyBytes(publicKey));\n const keyIdHex = this.bytesToHex(keyId);\n this.cryptedKeys.set(keyIdHex, { publicKey: publicKey, encryptedSecret });\n return true;\n }\n\n /**\n * Internal method to add an encrypted output key (used by both Load and Add methods)\n */\n private addCryptedOutKeyInner(\n outId: Uint8Array,\n publicKey: PublicKeyType,\n encryptedSecret: Uint8Array\n ): boolean {\n const outIdHex = this.bytesToHex(outId);\n this.cryptedOutKeys.set(outIdHex, { publicKey: publicKey, encryptedSecret });\n return true;\n }\n\n /**\n * Update the time of the first key\n * Replicates UpdateTimeFirstKey from keyman.cpp\n */\n private updateTimeFirstKey(_nCreateTime: number): void {\n // This would track the oldest key creation time\n // For in-memory version, we can store this if needed\n // Currently not implemented as it's mainly for database wallet tracking\n }\n\n // Helper methods for key conversion\n // These methods help convert between navio-blsct types and bytes\n // The actual implementation depends on navio-blsct API\n\n private getPublicKeyFromScalar(scalar: ScalarType): Uint8Array {\n // Convert Scalar to public key bytes\n // This would use scalar.toPublicKey() or similar based on navio-blsct API\n return Uint8Array.from(Buffer.from(PublicKey.fromScalar(scalar).serialize(), 'hex'));\n }\n\n private getPublicKeyFromViewKey(viewKey: ViewKeyType): Uint8Array {\n // Convert ViewKey to public key bytes\n return this.getPublicKeyFromScalar(Scalar.deserialize(viewKey.serialize()));\n }\n\n private getPublicKeyBytes(publicKey: PublicKeyType): Uint8Array {\n // Get bytes from PublicKey\n return Uint8Array.from(Buffer.from(publicKey.serialize(), 'hex'));\n }\n\n\n private createScalarFromBytes(_bytes: Uint8Array): ScalarType {\n // Create Scalar from bytes\n // This would use Scalar.fromBytes() or similar based on navio-blsct API\n return Scalar.deserialize(this.bytesToHex(_bytes)); // Placeholder - needs actual API\n }\n\n private createViewKeyFromBytes(_bytes: Uint8Array): ViewKeyType {\n // ViewKey is just a Scalar - deserialize from hex\n return Scalar.deserialize(this.bytesToHex(_bytes));\n }\n\n private createPublicKeyFromBytes(_bytes: Uint8Array): PublicKeyType {\n // Create PublicKey from bytes\n // This would use PublicKey.fromBytes() or similar\n return PublicKey.deserialize(this.bytesToHex(_bytes)); // Placeholder - needs actual API\n }\n\n /**\n * Compute hash160 (SHA256 followed by RIPEMD160)\n * This is the standard hash function used in Bitcoin-like systems\n * @param data - The data to hash\n * @returns The hash160 result (20 bytes)\n */\n private hash160(data: Uint8Array): Uint8Array {\n // Step 1: SHA256\n const sha256Hash = sha256(data);\n // Step 2: RIPEMD160 of the SHA256 hash\n const hash160Result = ripemd160(sha256Hash);\n return hash160Result;\n }\n\n private bytesToHex(bytes: Uint8Array): string {\n return Array.from(bytes)\n .map(b => b.toString(16).padStart(2, '0'))\n .join('');\n }\n\n\n /**\n * Get the private spending key\n * Replicates GetSpendingKey from keyman.cpp\n * @returns The private spending key (Scalar)\n */\n getSpendingKey(): ScalarType {\n if (!this.fSpendKeyDefined) {\n throw new Error('KeyManager: the wallet has no spend key available');\n }\n\n if (!this.spendKeyId) {\n throw new Error('KeyManager: spend key ID not available');\n }\n\n const key = this.getKey(this.spendKeyId);\n if (!key) {\n throw new Error('KeyManager: could not access the spend key');\n }\n\n return key;\n }\n\n /**\n * Get spending key for a transaction output\n * Replicates GetSpendingKeyForOutput from keyman.cpp\n * @param out - The transaction output\n * @param key - Output parameter for the spending key\n * @returns True if successful\n */\n getSpendingKeyForOutput(out: CTxOut, key: { value: ScalarType | null }): boolean {\n const hashId = this.getHashIdFromTxOut(out);\n return this.getSpendingKeyForOutputById(out, hashId, key);\n }\n\n /**\n * Get spending key for a transaction output by hash ID\n * @param out - The transaction output\n * @param hashId - The hash ID\n * @param key - Output parameter for the spending key\n * @returns True if successful\n */\n getSpendingKeyForOutputById(\n out: CTxOut,\n hashId: Uint8Array,\n key: { value: ScalarType | null }\n ): boolean {\n const id: SubAddressIdentifier = { account: 0, address: 0 };\n if (!this.getSubAddressId(hashId, id)) {\n return false;\n }\n return this.getSpendingKeyForOutputBySubAddress(out, id, key);\n }\n\n /**\n * Get spending key for a transaction output by sub-address identifier\n * @param out - The transaction output\n * @param id - The sub-address identifier\n * @param key - Output parameter for the spending key\n * @returns True if successful\n */\n getSpendingKeyForOutputBySubAddress(\n out: CTxOut,\n id: SubAddressIdentifier,\n key: { value: ScalarType | null }\n ): boolean {\n if (!this.fViewKeyDefined || !this.viewKey) {\n throw new Error('KeyManager: the wallet has no view key available');\n }\n\n const sk = this.getSpendingKey();\n\n // Calculate private spending key using navio-blsct\n // Uses calcPrivSpendingKey(blindingKey, viewKey, spendingKey, account, address)\n // Reference: https://nav-io.github.io/libblsct-bindings/ts/functions/calcPrivSpendingKey.html\n const blindingKey = out.blsctData.blindingKey as PublicKeyType;\n const viewKeyScalar = this.getScalarFromViewKey(this.viewKey);\n const spendingKeyScalar = this.getScalarFromScalar(sk);\n\n key.value = calcPrivSpendingKey(\n blindingKey,\n viewKeyScalar,\n spendingKeyScalar,\n id.account,\n id.address\n );\n return true;\n }\n\n /**\n * Get spending key for output with caching\n * Replicates GetSpendingKeyForOutputWithCache from keyman.cpp\n * @param out - The transaction output\n * @param key - Output parameter for the spending key\n * @returns True if successful\n */\n getSpendingKeyForOutputWithCache(out: CTxOut, key: { value: ScalarType | null }): boolean {\n const hashId = this.getHashIdFromTxOut(out);\n return this.getSpendingKeyForOutputWithCacheById(out, hashId, key);\n }\n\n /**\n * Get spending key for output with caching by hash ID\n * @param out - The transaction output\n * @param hashId - The hash ID\n * @param key - Output parameter for the spending key\n * @returns True if successful\n */\n getSpendingKeyForOutputWithCacheById(\n out: CTxOut,\n hashId: Uint8Array,\n key: { value: ScalarType | null }\n ): boolean {\n const id: SubAddressIdentifier = { account: 0, address: 0 };\n if (!this.getSubAddressId(hashId, id)) {\n return false;\n }\n return this.getSpendingKeyForOutputWithCacheBySubAddress(out, id, key);\n }\n\n /**\n * Get spending key for output with caching by sub-address\n * @param out - The transaction output\n * @param id - The sub-address identifier\n * @param key - Output parameter for the spending key\n * @returns True if successful\n */\n getSpendingKeyForOutputWithCacheBySubAddress(\n out: CTxOut,\n id: SubAddressIdentifier,\n key: { value: ScalarType | null }\n ): boolean {\n if (!this.fViewKeyDefined || !this.viewKey) {\n throw new Error('KeyManager: the wallet has no view key available');\n }\n\n const sk = this.getSpendingKey();\n\n // Calculate outId for caching: Hash(blindingKey || viewKey || spendingKey || account || address)\n const blindingKey = out.blsctData.blindingKey as PublicKeyType;\n const viewKeyScalar = this.getScalarFromViewKey(this.viewKey);\n const spendingKeyScalar = this.getScalarFromScalar(sk);\n\n const outIdData = new Uint8Array(\n this.getPublicKeyBytes(blindingKey).length +\n this.getScalarBytes(viewKeyScalar).length +\n this.getScalarBytes(spendingKeyScalar).length +\n 8 +\n 8 // account (int64) + address (uint64)\n );\n let offset = 0;\n outIdData.set(this.getPublicKeyBytes(blindingKey), offset);\n offset += this.getPublicKeyBytes(blindingKey).length;\n outIdData.set(this.getScalarBytes(viewKeyScalar), offset);\n offset += this.getScalarBytes(viewKeyScalar).length;\n outIdData.set(this.getScalarBytes(spendingKeyScalar), offset);\n offset += this.getScalarBytes(spendingKeyScalar).length;\n\n // Write account and address as little-endian\n const accountView = new DataView(outIdData.buffer, offset, 8);\n accountView.setBigInt64(0, BigInt(id.account), true);\n offset += 8;\n const addressView = new DataView(outIdData.buffer, offset, 8);\n addressView.setBigUint64(0, BigInt(id.address), true);\n\n const outId = sha256(outIdData);\n\n // Check cache first\n const cachedKey = this.getOutKey(outId);\n if (cachedKey) {\n key.value = cachedKey;\n return true;\n }\n\n // Calculate and cache using navio-blsct API\n // Reference: https://nav-io.github.io/libblsct-bindings/ts/functions/calcPrivSpendingKey.html\n const calculatedKey = calcPrivSpendingKey(\n blindingKey,\n viewKeyScalar,\n spendingKeyScalar,\n id.account,\n id.address\n );\n\n // Cache it\n this.addKeyOutKey(calculatedKey, outId);\n key.value = calculatedKey;\n return true;\n }\n\n // ============================================================================\n // High Priority: Output Detection\n // ============================================================================\n\n /**\n * Check if a transaction output belongs to this wallet\n * Replicates IsMine(txout) from keyman.cpp\n * @param txout - The transaction output\n * @returns True if the output belongs to this wallet\n */\n isMine(txout: CTxOut): boolean {\n // Check if spendingKey is zero (extract from script)\n const spendingKey = txout.blsctData.spendingKey as PublicKeyType;\n const isZero = this.isPublicKeyZero(spendingKey);\n\n if (isZero) {\n // Try to extract spending key from script\n const extractedSpendingKey: { value: PublicKeyType | null } = { value: null };\n if (this.extractSpendingKeyFromScript(txout.scriptPubKey, extractedSpendingKey)) {\n return this.isMineByKeys(\n txout.blsctData.blindingKey as PublicKeyType,\n extractedSpendingKey.value!,\n txout.blsctData.viewTag\n );\n }\n return false;\n }\n\n return this.isMineByKeys(\n txout.blsctData.blindingKey as PublicKeyType,\n spendingKey,\n txout.blsctData.viewTag\n );\n }\n\n /**\n * Check if output belongs to wallet by keys\n * Replicates IsMine(blindingKey, spendingKey, viewTag) from keyman.cpp\n * @param blindingKey - The blinding public key\n * @param spendingKey - The spending public key\n * @param viewTag - The view tag\n * @returns True if the output belongs to this wallet\n */\n isMineByKeys(blindingKey: PublicKeyType, spendingKey: PublicKeyType, viewTag: number): boolean {\n if (!this.fViewKeyDefined || !this.viewKey) {\n return false;\n }\n\n // Check view tag - fast filter for outputs not intended for us\n const calculatedViewTag = this.calculateViewTag(blindingKey);\n if (viewTag !== calculatedViewTag) {\n return false;\n }\n\n // Get hash ID and check if we have this sub-address\n const hashId = this.getHashId(blindingKey, spendingKey);\n return this.haveSubAddress(hashId);\n }\n\n /**\n * Check if a script belongs to this wallet\n * Replicates IsMine(script) from keyman.cpp\n * @param script - The script\n * @returns True if the script belongs to this wallet\n */\n isMineByScript(_script: Uint8Array): boolean {\n // This checks watch-only scripts\n // For in-memory KeyManager, we don't have watch-only support yet\n // Return false for now\n return false;\n }\n\n /**\n * Get hash ID from transaction output\n * Replicates GetHashId(txout) from keyman.cpp\n * @param txout - The transaction output\n * @returns The hash ID (20 bytes) or empty if not valid\n */\n getHashIdFromTxOut(txout: CTxOut): Uint8Array {\n // Check if script is spendable or is staked commitment\n // For now, we'll assume it's spendable if it has BLS CT data\n if (!txout.blsctData || txout.blsctData.viewTag === 0) {\n return new Uint8Array(20); // Return empty hash ID\n }\n\n const spendingKey = txout.blsctData.spendingKey as PublicKeyType;\n const isZero = this.isPublicKeyZero(spendingKey);\n\n if (isZero) {\n // Try to extract from script\n const extractedSpendingKey: { value: PublicKeyType | null } = { value: null };\n if (this.extractSpendingKeyFromScript(txout.scriptPubKey, extractedSpendingKey)) {\n return this.getHashId(\n txout.blsctData.blindingKey as PublicKeyType,\n extractedSpendingKey.value!\n );\n }\n return new Uint8Array(20); // Return empty hash ID\n }\n\n return this.getHashId(txout.blsctData.blindingKey as PublicKeyType, spendingKey);\n }\n\n /**\n * Get hash ID from keys (public API)\n * Replicates GetHashId(blindingKey, spendingKey) from keyman.cpp\n * @param blindingKey - The blinding public key\n * @param spendingKey - The spending public key\n * @returns The hash ID (20 bytes)\n */\n getHashId(blindingKey: PublicKeyType, spendingKey: PublicKeyType): Uint8Array {\n if (!this.fViewKeyDefined || !this.viewKey) {\n throw new Error('KeyManager: the wallet has no view key available');\n }\n\n // Use the existing calculateHashId method\n return this.calculateHashId(blindingKey, spendingKey);\n }\n\n /**\n * Get destination from transaction output\n * Replicates GetDestination from keyman.cpp\n * @param txout - The transaction output\n * @returns The destination (SubAddress keys) or null\n */\n getDestination(txout: CTxOut): CTxDestination | null {\n const hashId = this.getHashIdFromTxOut(txout);\n const subAddress: { value: SubAddrType | null } = { value: null };\n\n if (!this.getSubAddressByHashId(hashId, subAddress)) {\n return null;\n }\n\n // Return the sub-address keys as destination\n return subAddress.value as unknown as CTxDestination;\n }\n\n /**\n * Check if output is a change output\n * Replicates OutputIsChange from keyman.cpp\n * @param out - The transaction output\n * @returns True if it's a change output (account -1)\n */\n outputIsChange(out: CTxOut): boolean {\n const hashId = this.getHashIdFromTxOut(out);\n const id: SubAddressIdentifier = { account: 0, address: 0 };\n\n if (!this.getSubAddressId(hashId, id)) {\n return false;\n }\n\n return id.account === -1; // Change account\n }\n\n // ============================================================================\n // Medium Priority: Token Keys\n // ============================================================================\n\n /**\n * Get master token key\n * Replicates GetMasterTokenKey from keyman.cpp\n * @returns The master token key (Scalar)\n */\n getMasterTokenKey(): ScalarType {\n if (!this.isHDEnabled()) {\n throw new Error('KeyManager: the wallet has no HD enabled');\n }\n\n if (!this.tokenKeyId) {\n throw new Error('KeyManager: token key ID not available');\n }\n\n const key = this.getKey(this.tokenKeyId);\n if (!key) {\n throw new Error('KeyManager: could not access the master token key');\n }\n\n return key;\n }\n\n /**\n * Recover amounts from transaction outputs\n * Replicates RecoverOutputs from keyman.cpp\n * Uses navio-blsct recoverAmount function\n * Reference: https://nav-io.github.io/libblsct-bindings/ts/functions/recoverAmount.html\n * @param outs - Array of transaction outputs\n * @returns Recovery result with amounts and indices\n */\n recoverOutputs(outs: CTxOut[]): AmountRecoveryResult {\n if (!this.fViewKeyDefined || !this.viewKey) {\n return { success: false, amounts: [], indices: [] };\n }\n\n // Build recovery requests for outputs that match our view tag\n const recoveryRequests: any[] = [];\n\n for (let i = 0; i < outs.length; i++) {\n const out = outs[i];\n\n // Check if output has BLS CT data and range proof\n if (!out.blsctData || !out.blsctData.rangeProof) {\n continue;\n }\n\n // Check view tag matches\n const calculatedViewTag = this.calculateViewTag(out.blsctData.blindingKey as PublicKeyType);\n if (out.blsctData.viewTag !== calculatedViewTag) {\n continue;\n }\n\n // Calculate nonce\n const nonce = this.calculateNonce(out.blsctData.blindingKey as PublicKeyType);\n\n // Build recovery request\n // Format depends on navio-blsct API - need to check exact structure\n recoveryRequests.push({\n rangeProof: out.blsctData.rangeProof,\n tokenId: out.tokenId,\n nonce: nonce,\n index: i,\n });\n }\n\n if (recoveryRequests.length === 0) {\n return { success: false, amounts: [], indices: [] };\n }\n\n // Call navio-blsct recoverAmount\n // Reference: https://nav-io.github.io/libblsct-bindings/ts/functions/recoverAmount.html\n const rv = recoverAmount(recoveryRequests);\n\n try {\n // Parse the result using the navio-blsct API\n const size = getAmountRecoveryResultSize(rv.value);\n const amounts: bigint[] = [];\n const indices: number[] = [];\n let allSuccess = true;\n\n for (let i = 0; i < size; i++) {\n const isSucc = getAmountRecoveryResultIsSucc(rv.value, i);\n if (isSucc) {\n amounts.push(getAmountRecoveryResultAmount(rv.value, i));\n indices.push(i);\n } else {\n allSuccess = false;\n }\n }\n\n return {\n success: allSuccess && amounts.length > 0,\n amounts,\n indices,\n };\n } finally {\n // Clean up the result\n deleteAmountsRetVal(rv);\n }\n }\n\n /**\n * Recover amounts from transaction outputs with nonce\n * Replicates RecoverOutputsWithNonce from keyman.cpp\n * @param outs - Array of transaction outputs\n * @param nonce - The nonce (PublicKey)\n * @returns Recovery result with amounts and indices\n */\n recoverOutputsWithNonce(outs: CTxOut[], nonce: PublicKeyType): AmountRecoveryResult {\n if (!this.fViewKeyDefined || !this.viewKey) {\n return { success: false, amounts: [], indices: [] };\n }\n\n // Build recovery requests using provided nonce\n const recoveryRequests: any[] = [];\n\n for (let i = 0; i < outs.length; i++) {\n const out = outs[i];\n\n // Check if output has BLS CT data and range proof\n if (!out.blsctData || !out.blsctData.rangeProof) {\n continue;\n }\n\n // Use the provided nonce instead of calculating it\n recoveryRequests.push({\n rangeProof: out.blsctData.rangeProof,\n tokenId: out.tokenId,\n nonce: nonce,\n index: i,\n });\n }\n\n if (recoveryRequests.length === 0) {\n return { success: false, amounts: [], indices: [] };\n }\n\n // Call navio-blsct recoverAmount with provided nonce\n const rv = recoverAmount(recoveryRequests);\n\n try {\n // Parse the result using the navio-blsct API\n const size = getAmountRecoveryResultSize(rv.value);\n const amounts: bigint[] = [];\n const indices: number[] = [];\n let allSuccess = true;\n\n for (let i = 0; i < size; i++) {\n const isSucc = getAmountRecoveryResultIsSucc(rv.value, i);\n if (isSucc) {\n amounts.push(getAmountRecoveryResultAmount(rv.value, i));\n indices.push(i);\n } else {\n allSuccess = false;\n }\n }\n\n return {\n success: allSuccess && amounts.length > 0,\n amounts,\n indices,\n };\n } finally {\n // Clean up the result\n deleteAmountsRetVal(rv);\n }\n }\n\n // ============================================================================\n // Medium Priority: SubAddress by Hash ID\n // ============================================================================\n\n /**\n * Load sub-address mapping from storage\n * Replicates LoadSubAddress from keyman.cpp\n * @param hashId - The hash ID\n * @param index - The sub-address identifier\n */\n loadSubAddress(hashId: Uint8Array, index: SubAddressIdentifier): void {\n const hashIdHex = this.bytesToHex(hashId);\n this.subAddresses.set(hashIdHex, index);\n }\n\n /**\n * Add sub-address mapping and save to database\n * Replicates AddSubAddress from keyman.cpp\n * @param hashId - The hash ID\n * @param index - The sub-address identifier\n * @returns True if successful\n */\n addSubAddress(hashId: Uint8Array, index: SubAddressIdentifier): boolean {\n const hashIdHex = this.bytesToHex(hashId);\n this.subAddresses.set(hashIdHex, index);\n // In a database wallet, this would also save to database\n return true;\n }\n\n /**\n * Check if sub-address exists by hash ID\n * Replicates HaveSubAddress from keyman.cpp\n * @param hashId - The hash ID\n * @returns True if the sub-address exists\n */\n haveSubAddress(hashId: Uint8Array): boolean {\n const hashIdHex = this.bytesToHex(hashId);\n return this.subAddresses.has(hashIdHex);\n }\n\n /**\n * Get sub-address by hash ID\n * Replicates GetSubAddress(hashId) from keyman.cpp\n * @param hashId - The hash ID\n * @param address - Output parameter for the sub-address\n * @returns True if successful\n */\n getSubAddressByHashId(hashId: Uint8Array, address: { value: SubAddrType | null }): boolean {\n if (!this.haveSubAddress(hashId)) {\n return false;\n }\n\n const hashIdHex = this.bytesToHex(hashId);\n const id = this.subAddresses.get(hashIdHex)!;\n address.value = this.getSubAddress(id);\n return true;\n }\n\n /**\n * Get sub-address identifier from hash ID\n * Replicates GetSubAddressId from keyman.cpp\n * @param hashId - The hash ID\n * @param id - Output parameter for the sub-address identifier\n * @returns True if successful\n */\n getSubAddressId(hashId: Uint8Array, id: SubAddressIdentifier): boolean {\n if (!this.haveSubAddress(hashId)) {\n return false;\n }\n\n const hashIdHex = this.bytesToHex(hashId);\n const storedId = this.subAddresses.get(hashIdHex)!;\n id.account = storedId.account;\n id.address = storedId.address;\n return true;\n }\n\n /**\n * Load sub-address string mapping from storage\n * Replicates LoadSubAddressStr from keyman.cpp\n * @param subAddress - The sub-address\n * @param hashId - The hash ID\n */\n loadSubAddressStr(subAddress: SubAddrType, hashId: Uint8Array): void {\n const subAddressStr = this.serializeSubAddress(subAddress);\n const hashIdHex = this.bytesToHex(hashId);\n this.subAddressesStr.set(subAddressStr, hashIdHex);\n }\n\n /**\n * Add sub-address string mapping and save to database\n * Replicates AddSubAddressStr from keyman.cpp\n * @param subAddress - The sub-address\n * @param hashId - The hash ID\n * @returns True if successful\n */\n addSubAddressStr(subAddress: SubAddrType, hashId: Uint8Array): boolean {\n const subAddressStr = this.serializeSubAddress(subAddress);\n const hashIdHex = this.bytesToHex(hashId);\n this.subAddressesStr.set(subAddressStr, hashIdHex);\n // In a database wallet, this would also save to database\n return true;\n }\n\n /**\n * Check if sub-address string exists\n * Replicates HaveSubAddressStr from keyman.cpp\n * @param subAddress - The sub-address\n * @returns True if the sub-address string exists\n */\n haveSubAddressStr(subAddress: SubAddrType): boolean {\n const subAddressStr = this.serializeSubAddress(subAddress);\n return this.subAddressesStr.has(subAddressStr);\n }\n\n // ============================================================================\n // Medium Priority: SubAddress Pool Management\n // ============================================================================\n\n /**\n * Reserve sub-address from pool\n * Replicates ReserveSubAddressFromPool from keyman.cpp\n * @param account - The account number\n * @param nIndex - Output parameter for the address index\n * @param keypool - Output parameter for the keypool entry\n */\n reserveSubAddressFromPool(\n account: number,\n nIndex: { value: number },\n keypool: { value: { id: SubAddressIdentifier; subAddress: SubAddrType } | null }\n ): void {\n const pool = this.subAddressPool.get(account);\n if (!pool || pool.size === 0) {\n throw new Error('KeyManager: Sub-address pool is empty');\n }\n\n // Get first available index\n const index = Array.from(pool)[0];\n pool.delete(index);\n\n const id: SubAddressIdentifier = { account, address: index };\n const subAddress = this.getSubAddress(id);\n\n nIndex.value = index;\n keypool.value = { id, subAddress };\n }\n\n /**\n * Keep a sub-address (mark as used)\n * Replicates KeepSubAddress from keyman.cpp\n * @param id - The sub-address identifier\n */\n keepSubAddress(id: SubAddressIdentifier): void {\n const pool = this.subAddressPool.get(id.account);\n if (pool) {\n pool.delete(id.address);\n }\n // Update time if needed\n const key = `${id.account}:${id.address}`;\n this.subAddressPoolTime.delete(key);\n }\n\n /**\n * Return sub-address to pool\n * Replicates ReturnSubAddress from keyman.cpp\n * @param id - The sub-address identifier\n */\n returnSubAddress(id: SubAddressIdentifier): void {\n const pool = this.subAddressPool.get(id.account);\n if (pool) {\n pool.add(id.address);\n // Update time\n const key = `${id.account}:${id.address}`;\n this.subAddressPoolTime.set(key, Date.now());\n }\n }\n\n /**\n * Get sub-address from pool\n * Replicates GetSubAddressFromPool from keyman.cpp\n * @param account - The account number\n * @param result - Output parameter for the hash ID\n * @param id - Output parameter for the sub-address identifier\n * @returns True if successful\n */\n getSubAddressFromPool(\n account: number,\n result: { value: Uint8Array | null },\n id: { value: SubAddressIdentifier | null }\n ): boolean {\n const pool = this.subAddressPool.get(account);\n if (!pool || pool.size === 0) {\n return false;\n }\n\n const index = Array.from(pool)[0];\n const subAddressId: SubAddressIdentifier = { account, address: index };\n const subAddress = this.getSubAddress(subAddressId);\n\n // Get hash ID from sub-address\n // This requires getting the keys from SubAddress and calculating hash ID\n // For now, we'll need to extract keys from SubAddress\n const hashId = this.getHashIdFromSubAddress(subAddress);\n\n result.value = hashId;\n id.value = subAddressId;\n return true;\n }\n\n /**\n * Get oldest sub-address pool time\n * Replicates GetOldestSubAddressPoolTime from keyman.cpp\n * @param account - The account number\n * @returns The oldest time or 0 if pool is empty\n */\n getOldestSubAddressPoolTime(account: number): number {\n const pool = this.subAddressPool.get(account);\n if (!pool || pool.size === 0) {\n return 0;\n }\n\n let oldestTime = Number.MAX_SAFE_INTEGER;\n for (const index of Array.from(pool)) {\n const key = `${account}:${index}`;\n const time = this.subAddressPoolTime.get(key) || 0;\n if (time < oldestTime && time > 0) {\n oldestTime = time;\n }\n }\n\n return oldestTime === Number.MAX_SAFE_INTEGER ? 0 : oldestTime;\n }\n\n // ============================================================================\n // Low Priority: Utilities\n // ============================================================================\n\n /**\n * Add inactive HD chain\n * Replicates AddInactiveHDChain from keyman.cpp\n * @param chain - The HD chain to add\n */\n addInactiveHDChain(_chain: HDChain): void {\n // For in-memory KeyManager, we only support one active chain\n // This would be used in database wallet for tracking inactive chains\n // Not implemented for in-memory version\n }\n\n /**\n * Get time of first key\n * Replicates GetTimeFirstKey from keyman.cpp\n * @returns The creation time of the first key\n */\n getTimeFirstKey(): number {\n return this.timeFirstKey || 0;\n }\n\n /**\n * Extract spending key from script\n * Replicates ExtractSpendingKeyFromScript from keyman.cpp\n * @param script - The script\n * @param spendingKey - Output parameter for the spending key\n * @returns True if successful\n */\n extractSpendingKeyFromScript(\n _script: Uint8Array,\n _spendingKey: { value: PublicKeyType | null }\n ): boolean {\n // This extracts spending key from OP_BLSCHECKSIG script\n // For now, return false - needs script parsing implementation\n // TODO: Implement script parsing for OP_BLSCHECKSIG\n return false;\n }\n\n // ============================================================================\n // Helper methods for new functionality\n // ============================================================================\n\n /**\n * Check if public key is zero\n */\n private isPublicKeyZero(_publicKey: PublicKeyType): boolean {\n // Check if public key is zero/identity\n // This needs navio-blsct API - for now, return false\n // TODO: Implement when navio-blsct provides IsZero() method\n return false;\n }\n\n /**\n * Get scalar from ViewKey\n */\n private getScalarFromViewKey(viewKey: ViewKeyType): ScalarType {\n return Scalar.deserialize(viewKey.serialize());\n }\n\n /**\n * Get scalar from Scalar (identity function, but ensures type)\n */\n private getScalarFromScalar(scalar: ScalarType): ScalarType {\n return scalar;\n }\n\n /**\n * Get bytes from Scalar\n */\n private getScalarBytes(scalar: ScalarType): Uint8Array {\n // Serialize scalar to bytes\n // This needs navio-blsct API\n return Uint8Array.from(Buffer.from(scalar.serialize(), 'hex'));\n }\n\n /**\n * Serialize SubAddress to string for map key\n */\n private serializeSubAddress(subAddress: SubAddrType): string {\n // Serialize SubAddress to a string for use as map key\n // This needs navio-blsct API\n return subAddress.serialize();\n }\n\n /**\n * Get hash ID from SubAddress\n * Uses DoublePublicKey.deserialize(subaddress.serialize()) to extract keys\n */\n private getHashIdFromSubAddress(subAddress: SubAddrType): Uint8Array {\n // Extract keys from SubAddress using DoublePublicKey\n // Method: DoublePublicKey.deserialize(subaddress.serialize())\n const serialized = (subAddress as any).serialize();\n const doublePublicKey = DoublePublicKey.deserialize(serialized);\n\n // Get keys from DoublePublicKey\n // Need to check navio-blsct API for getting individual keys\n // For now, try common method names\n const keys = (doublePublicKey as any).getKeys\n ? (doublePublicKey as any).getKeys()\n : doublePublicKey;\n\n // Extract spending and blinding keys\n // DoublePublicKey typically contains two public keys\n const spendingKey = (keys as any).spendingKey || (keys as any).key1 || keys;\n const blindingKey = (keys as any).blindingKey || (keys as any).key2 || keys;\n\n // Calculate hash ID\n return this.getHashId(blindingKey as PublicKeyType, spendingKey as PublicKeyType);\n }\n}\n","/**\n * WalletDB - Database persistence layer for KeyManager\n * Uses SQL.js (SQLite compiled to WebAssembly) for cross-platform compatibility\n * Works on web browsers, Node.js, and mobile platforms\n *\n * Database schema replicates navio-core wallet database structure\n */\n\nimport { KeyManager } from './key-manager';\nimport type { HDChain, SubAddressIdentifier } from './key-manager.types';\nimport * as blsctModule from 'navio-blsct';\n\n/**\n * Wallet output structure returned by getUnspentOutputs and getAllOutputs\n */\nexport interface WalletOutput {\n outputHash: string;\n txHash: string;\n outputIndex: number;\n blockHeight: number;\n amount: bigint;\n memo: string | null;\n tokenId: string | null;\n blindingKey: string;\n spendingKey: string;\n isSpent: boolean;\n spentTxHash: string | null;\n spentBlockHeight: number | null;\n}\n\n// Import SQL.js for cross-platform SQLite support\n// In browser: uses WebAssembly SQLite\n// In Node.js: uses native SQLite bindings if available, falls back to WASM\nlet initSqlJs: any;\nlet SQL: any;\n\n// Lazy load SQL.js to support both browser and Node.js\nasync function loadSQL(): Promise<any> {\n if (SQL) return SQL;\n\n try {\n // Try to load SQL.js\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n if (typeof (globalThis as any).window !== 'undefined') {\n // Browser environment\n const sqlJs = await import('sql.js');\n initSqlJs = sqlJs.default;\n SQL = await initSqlJs({\n // Prefer explicit override, otherwise use CDN to avoid requiring a local wasm file\n locateFile: (file: string) => {\n if (file === 'sql-wasm.wasm') {\n const override = (globalThis as any).NAVIO_SQL_WASM_URL;\n if (typeof override === 'string' && override.length > 0) {\n return override;\n }\n }\n return `https://sql.js.org/dist/${file}`;\n },\n });\n } else {\n // Node.js environment\n const sqlJs = require('sql.js');\n initSqlJs = sqlJs.default || sqlJs;\n const fs = require('fs');\n SQL = await initSqlJs({\n locateFile: (file: string) => {\n // Try to find sql.js WASM file\n const path = require('path');\n const wasmPath = path.join(__dirname, '../node_modules/sql.js/dist/sql-wasm.wasm');\n if (fs.existsSync(wasmPath)) {\n return wasmPath;\n }\n return file;\n },\n });\n }\n return SQL;\n } catch (error) {\n throw new Error(`Failed to load SQL.js: ${error}. Please install sql.js: npm install sql.js`);\n }\n}\n\n/**\n * WalletDB - Manages wallet database persistence.\n * \n * Uses SQL.js (SQLite compiled to WebAssembly) for cross-platform compatibility.\n * Works on web browsers, Node.js, and mobile platforms.\n * \n * @category Wallet\n */\nexport class WalletDB {\n private db: any = null;\n private dbPath: string;\n private keyManager: KeyManager | null = null;\n private isOpen = false;\n\n /**\n * Create a new WalletDB instance\n * @param dbPath - Path to the database file (or name for in-memory)\n * @param createIfNotExists - Create database if it doesn't exist\n */\n constructor(dbPath: string = ':memory:', _createIfNotExists = true) {\n this.dbPath = dbPath;\n // Database will be opened when loadWallet, createWallet, or restoreWallet is called\n // Note: _createIfNotExists reserved for future use\n }\n\n /**\n * Initialize the database connection and schema\n */\n private async initDatabase(): Promise<void> {\n if (this.isOpen) return;\n\n const SQL = await loadSQL();\n const fs = this.getFileSystem();\n\n // Load existing database or create new one\n if (this.dbPath !== ':memory:' && fs && fs.existsSync && fs.existsSync(this.dbPath)) {\n try {\n const buffer = fs.readFileSync(this.dbPath);\n this.db = new SQL.Database(buffer);\n } catch (error) {\n // If read fails, create new database\n this.db = new SQL.Database();\n }\n } else {\n this.db = new SQL.Database();\n }\n\n // Create schema\n this.createSchema();\n this.isOpen = true;\n }\n\n /**\n * Get file system interface (Node.js only)\n */\n private getFileSystem(): any {\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n if (typeof (globalThis as any).window === 'undefined' && typeof require !== 'undefined') {\n try {\n return require('fs');\n } catch {\n return null;\n }\n }\n return null;\n }\n\n /**\n * Create database schema\n * Replicates navio-core wallet database structure\n */\n private createSchema(): void {\n // Keys table - stores key pairs\n this.db.run(`\n CREATE TABLE IF NOT EXISTS keys (\n key_id TEXT PRIMARY KEY,\n secret_key TEXT NOT NULL,\n public_key TEXT NOT NULL,\n create_time INTEGER NOT NULL\n )\n `);\n\n // Output keys table - stores output-specific keys\n this.db.run(`\n CREATE TABLE IF NOT EXISTS out_keys (\n out_id TEXT PRIMARY KEY,\n secret_key TEXT NOT NULL\n )\n `);\n\n // Encrypted keys table\n this.db.run(`\n CREATE TABLE IF NOT EXISTS crypted_keys (\n key_id TEXT PRIMARY KEY,\n public_key TEXT NOT NULL,\n encrypted_secret TEXT NOT NULL\n )\n `);\n\n // Encrypted output keys table\n this.db.run(`\n CREATE TABLE IF NOT EXISTS crypted_out_keys (\n out_id TEXT PRIMARY KEY,\n public_key TEXT NOT NULL,\n encrypted_secret TEXT NOT NULL\n )\n `);\n\n // View key table\n this.db.run(`\n CREATE TABLE IF NOT EXISTS view_key (\n public_key TEXT PRIMARY KEY,\n secret_key TEXT NOT NULL\n )\n `);\n\n // Spend key table (public key only)\n this.db.run(`\n CREATE TABLE IF NOT EXISTS spend_key (\n public_key TEXT PRIMARY KEY\n )\n `);\n\n // HD chain table\n this.db.run(`\n CREATE TABLE IF NOT EXISTS hd_chain (\n id INTEGER PRIMARY KEY,\n version INTEGER NOT NULL,\n seed_id TEXT NOT NULL,\n spend_id TEXT NOT NULL,\n view_id TEXT NOT NULL,\n token_id TEXT NOT NULL,\n blinding_id TEXT NOT NULL\n )\n `);\n\n // Sub-addresses table\n this.db.run(`\n CREATE TABLE IF NOT EXISTS sub_addresses (\n hash_id TEXT PRIMARY KEY,\n account INTEGER NOT NULL,\n address INTEGER NOT NULL\n )\n `);\n\n // Sub-address strings table\n this.db.run(`\n CREATE TABLE IF NOT EXISTS sub_addresses_str (\n sub_address TEXT PRIMARY KEY,\n hash_id TEXT NOT NULL\n )\n `);\n\n // Sub-address pool table\n this.db.run(`\n CREATE TABLE IF NOT EXISTS sub_address_pool (\n account INTEGER NOT NULL,\n address INTEGER NOT NULL,\n create_time INTEGER NOT NULL,\n PRIMARY KEY (account, address)\n )\n `);\n\n // Sub-address counter table\n this.db.run(`\n CREATE TABLE IF NOT EXISTS sub_address_counter (\n account INTEGER PRIMARY KEY,\n counter INTEGER NOT NULL\n )\n `);\n\n // Key metadata table\n this.db.run(`\n CREATE TABLE IF NOT EXISTS key_metadata (\n key_id TEXT PRIMARY KEY,\n create_time INTEGER NOT NULL\n )\n `);\n\n // Transaction keys table (for sync)\n this.db.run(`\n CREATE TABLE IF NOT EXISTS tx_keys (\n tx_hash TEXT PRIMARY KEY,\n block_height INTEGER NOT NULL,\n keys_data TEXT NOT NULL\n )\n `);\n\n // Create index for block_height\n this.db.run(`\n CREATE INDEX IF NOT EXISTS idx_tx_keys_block_height ON tx_keys(block_height)\n `);\n\n // Block hashes table (for reorganization detection)\n this.db.run(`\n CREATE TABLE IF NOT EXISTS block_hashes (\n height INTEGER PRIMARY KEY,\n hash TEXT NOT NULL\n )\n `);\n\n // Sync state table (single row, always id = 0)\n this.db.run(`\n CREATE TABLE IF NOT EXISTS sync_state (\n id INTEGER PRIMARY KEY,\n last_synced_height INTEGER NOT NULL,\n last_synced_hash TEXT NOT NULL,\n total_tx_keys_synced INTEGER NOT NULL,\n last_sync_time INTEGER NOT NULL,\n chain_tip_at_last_sync INTEGER NOT NULL\n )\n `);\n\n // Wallet metadata table (single row, always id = 0)\n this.db.run(`\n CREATE TABLE IF NOT EXISTS wallet_metadata (\n id INTEGER PRIMARY KEY,\n creation_height INTEGER NOT NULL DEFAULT 0,\n creation_time INTEGER NOT NULL,\n restored_from_seed INTEGER NOT NULL DEFAULT 0,\n version INTEGER NOT NULL DEFAULT 1\n )\n `);\n\n // Wallet outputs table (UTXOs)\n this.db.run(`\n CREATE TABLE IF NOT EXISTS wallet_outputs (\n output_hash TEXT PRIMARY KEY,\n tx_hash TEXT NOT NULL,\n output_index INTEGER NOT NULL,\n block_height INTEGER NOT NULL,\n output_data TEXT NOT NULL,\n amount INTEGER NOT NULL DEFAULT 0,\n memo TEXT,\n token_id TEXT,\n blinding_key TEXT,\n spending_key TEXT,\n is_spent INTEGER NOT NULL DEFAULT 0,\n spent_tx_hash TEXT,\n spent_block_height INTEGER,\n created_at INTEGER NOT NULL\n )\n `);\n\n // Create indexes for wallet_outputs\n this.db.run(`\n CREATE INDEX IF NOT EXISTS idx_wallet_outputs_tx_hash ON wallet_outputs(tx_hash)\n `);\n this.db.run(`\n CREATE INDEX IF NOT EXISTS idx_wallet_outputs_block_height ON wallet_outputs(block_height)\n `);\n this.db.run(`\n CREATE INDEX IF NOT EXISTS idx_wallet_outputs_is_spent ON wallet_outputs(is_spent)\n `);\n }\n\n /**\n * Load wallet from database\n * @returns The loaded KeyManager instance\n * @throws Error if no wallet exists in the database\n */\n async loadWallet(): Promise<KeyManager> {\n await this.initDatabase();\n\n const keyManager = new KeyManager();\n\n // Load HD chain\n const hdChainResult = this.db.exec('SELECT * FROM hd_chain LIMIT 1');\n if (hdChainResult.length === 0 || hdChainResult[0].values.length === 0) {\n throw new Error('No wallet found in database');\n }\n\n const row = hdChainResult[0].values[0];\n const hdChain: HDChain = {\n version: row[1] as number,\n seedId: this.hexToBytes(row[2] as string),\n spendId: this.hexToBytes(row[3] as string),\n viewId: this.hexToBytes(row[4] as string),\n tokenId: this.hexToBytes(row[5] as string),\n blindingId: this.hexToBytes(row[6] as string),\n };\n keyManager.loadHDChain(hdChain);\n\n // Load view key\n const viewKeyResult = this.db.exec('SELECT * FROM view_key LIMIT 1');\n if (viewKeyResult.length > 0 && viewKeyResult[0].values.length > 0) {\n const row = viewKeyResult[0].values[0];\n const viewKey = this.deserializeViewKey(row[1] as string);\n keyManager.loadViewKey(viewKey);\n }\n\n // Load spend key\n const spendKeyResult = this.db.exec('SELECT * FROM spend_key LIMIT 1');\n if (spendKeyResult.length > 0 && spendKeyResult[0].values.length > 0) {\n const row = spendKeyResult[0].values[0];\n const publicKey = this.deserializePublicKey(row[0] as string);\n keyManager.loadSpendKey(publicKey);\n }\n\n // Load keys\n const keysResult = this.db.exec('SELECT * FROM keys');\n if (keysResult.length > 0) {\n for (const row of keysResult[0].values) {\n const secretKey = this.deserializeScalar(row[1] as string);\n const publicKey = this.deserializePublicKey(row[2] as string);\n keyManager.loadKey(secretKey, publicKey);\n\n // Load metadata\n const stmt = this.db.prepare('SELECT create_time FROM key_metadata WHERE key_id = ?');\n stmt.bind([row[0]]);\n if (stmt.step()) {\n const metadataRow = stmt.getAsObject();\n keyManager.loadKeyMetadata(this.hexToBytes(row[0] as string), {\n nCreateTime: metadataRow.create_time as number,\n });\n }\n stmt.free();\n }\n }\n\n // Load output keys\n const outKeysResult = this.db.exec('SELECT * FROM out_keys');\n if (outKeysResult.length > 0) {\n for (const row of outKeysResult[0].values) {\n const secretKey = this.deserializeScalar(row[1] as string);\n const outId = this.hexToBytes(row[0] as string);\n keyManager.loadOutKey(secretKey, outId);\n }\n }\n\n // Load encrypted keys\n const cryptedKeysResult = this.db.exec('SELECT * FROM crypted_keys');\n if (cryptedKeysResult.length > 0) {\n for (const row of cryptedKeysResult[0].values) {\n const publicKey = this.deserializePublicKey(row[1] as string);\n const encryptedSecret = this.hexToBytes(row[2] as string);\n keyManager.loadCryptedKey(publicKey, encryptedSecret, true);\n }\n }\n\n // Load encrypted output keys\n const cryptedOutKeysResult = this.db.exec('SELECT * FROM crypted_out_keys');\n if (cryptedOutKeysResult.length > 0) {\n for (const row of cryptedOutKeysResult[0].values) {\n const outId = this.hexToBytes(row[0] as string);\n const publicKey = this.deserializePublicKey(row[1] as string);\n const encryptedSecret = this.hexToBytes(row[2] as string);\n keyManager.loadCryptedOutKey(outId, publicKey, encryptedSecret, true);\n }\n }\n\n // Load sub-addresses\n const subAddressesResult = this.db.exec('SELECT * FROM sub_addresses');\n if (subAddressesResult.length > 0) {\n for (const row of subAddressesResult[0].values) {\n const hashId = this.hexToBytes(row[0] as string);\n const id: SubAddressIdentifier = {\n account: row[1] as number,\n address: row[2] as number,\n };\n keyManager.loadSubAddress(hashId, id);\n }\n }\n\n // Load sub-address counters\n const counterResult = this.db.exec('SELECT * FROM sub_address_counter');\n if (counterResult.length > 0) {\n for (const _row of counterResult[0].values) {\n // This would need to be stored in KeyManager\n // For now, we'll rely on the sub-addresses to reconstruct counters\n }\n }\n\n // If no sub-addresses were loaded from DB, regenerate the pools\n // This is needed because sub-address saving was not fully implemented\n if (subAddressesResult.length === 0 || subAddressesResult[0].values.length === 0) {\n // Regenerate sub-address pools (like navio-core does during startup)\n keyManager.newSubAddressPool(0);\n keyManager.newSubAddressPool(-1);\n keyManager.newSubAddressPool(-2);\n }\n\n this.keyManager = keyManager;\n return keyManager;\n }\n\n /**\n * Create a new wallet\n * @param creationHeight - Optional block height when wallet was created (for sync optimization)\n * @returns The new KeyManager instance\n */\n async createWallet(creationHeight?: number): Promise<KeyManager> {\n await this.initDatabase();\n\n const keyManager = new KeyManager();\n\n // Generate new seed\n const seed = keyManager.generateNewSeed();\n keyManager.setHDSeed(seed);\n\n // Initialize sub-address pools\n keyManager.newSubAddressPool(0);\n keyManager.newSubAddressPool(-1);\n keyManager.newSubAddressPool(-2);\n\n // Save to database\n await this.saveWallet(keyManager);\n\n // Save wallet metadata\n await this.saveWalletMetadata({\n creationHeight: creationHeight ?? 0,\n creationTime: Date.now(),\n restoredFromSeed: false,\n });\n\n this.keyManager = keyManager;\n return keyManager;\n }\n\n /**\n * Restore wallet from seed\n * @param seedHex - The seed as hex string\n * @param creationHeight - Optional block height to start scanning from (for faster restore)\n * @returns The restored KeyManager instance\n */\n async restoreWallet(seedHex: string, creationHeight?: number): Promise<KeyManager> {\n await this.initDatabase();\n\n const keyManager = new KeyManager();\n\n // Deserialize seed\n const seed = this.deserializeScalar(seedHex);\n keyManager.setHDSeed(seed);\n\n // Initialize sub-address pools\n keyManager.newSubAddressPool(0);\n keyManager.newSubAddressPool(-1);\n keyManager.newSubAddressPool(-2);\n\n // Save to database\n await this.saveWallet(keyManager);\n\n // Save wallet metadata with restore height\n await this.saveWalletMetadata({\n creationHeight: creationHeight ?? 0,\n creationTime: Date.now(),\n restoredFromSeed: true,\n });\n\n this.keyManager = keyManager;\n return keyManager;\n }\n\n /**\n * Save wallet metadata to database\n */\n private async saveWalletMetadata(metadata: {\n creationHeight: number;\n creationTime: number;\n restoredFromSeed: boolean;\n }): Promise<void> {\n if (!this.isOpen) {\n await this.initDatabase();\n }\n\n const stmt = this.db.prepare(`\n INSERT OR REPLACE INTO wallet_metadata (id, creation_height, creation_time, restored_from_seed, version)\n VALUES (0, ?, ?, ?, 1)\n `);\n stmt.run([metadata.creationHeight, metadata.creationTime, metadata.restoredFromSeed ? 1 : 0]);\n stmt.free();\n\n // Persist to disk\n this.persistToDisk();\n }\n\n /**\n * Persist database to disk (if not in-memory)\n */\n private persistToDisk(): void {\n if (this.dbPath !== ':memory:' && this.db) {\n const fs = this.getFileSystem();\n if (fs) {\n const data = this.db.export();\n const buffer = Buffer.from(data);\n fs.writeFileSync(this.dbPath, buffer);\n }\n }\n }\n\n /**\n * Get wallet metadata from database\n * @returns Wallet metadata or null if not found\n */\n async getWalletMetadata(): Promise<{\n creationHeight: number;\n creationTime: number;\n restoredFromSeed: boolean;\n version: number;\n } | null> {\n if (!this.isOpen) {\n await this.initDatabase();\n }\n\n const result = this.db.exec('SELECT creation_height, creation_time, restored_from_seed, version FROM wallet_metadata WHERE id = 0');\n if (result.length === 0 || result[0].values.length === 0) {\n return null;\n }\n\n const [creationHeight, creationTime, restoredFromSeed, version] = result[0].values[0];\n return {\n creationHeight: creationHeight as number,\n creationTime: creationTime as number,\n restoredFromSeed: (restoredFromSeed as number) === 1,\n version: version as number,\n };\n }\n\n /**\n * Get the wallet creation height (block height to start scanning from)\n * @returns Creation height or 0 if not set\n */\n async getCreationHeight(): Promise<number> {\n const metadata = await this.getWalletMetadata();\n return metadata?.creationHeight ?? 0;\n }\n\n /**\n * Set the wallet creation height\n * @param height - Block height\n */\n async setCreationHeight(height: number): Promise<void> {\n if (!this.isOpen) {\n await this.initDatabase();\n }\n\n // Check if metadata exists\n const existing = await this.getWalletMetadata();\n if (existing) {\n const stmt = this.db.prepare('UPDATE wallet_metadata SET creation_height = ? WHERE id = 0');\n stmt.run([height]);\n stmt.free();\n this.persistToDisk();\n } else {\n await this.saveWalletMetadata({\n creationHeight: height,\n creationTime: Date.now(),\n restoredFromSeed: false,\n });\n }\n }\n\n /**\n * Save wallet to database\n * @param keyManager - The KeyManager instance to save (optional, uses stored instance if not provided)\n */\n async saveWallet(keyManager?: KeyManager): Promise<void> {\n if (!this.isOpen) {\n await this.initDatabase();\n }\n\n const km = keyManager || this.keyManager;\n if (!km) {\n throw new Error('No KeyManager instance to save');\n }\n\n // Start transaction\n this.db.run('BEGIN TRANSACTION');\n\n try {\n // Clear existing data (for simplicity, we'll replace everything)\n // In production, you might want to do incremental updates\n this.db.run('DELETE FROM keys');\n this.db.run('DELETE FROM out_keys');\n this.db.run('DELETE FROM crypted_keys');\n this.db.run('DELETE FROM crypted_out_keys');\n this.db.run('DELETE FROM view_key');\n this.db.run('DELETE FROM spend_key');\n this.db.run('DELETE FROM hd_chain');\n this.db.run('DELETE FROM sub_addresses');\n this.db.run('DELETE FROM sub_addresses_str');\n this.db.run('DELETE FROM sub_address_pool');\n this.db.run('DELETE FROM sub_address_counter');\n this.db.run('DELETE FROM key_metadata');\n\n // Save HD chain\n const hdChain = km.getHDChain();\n if (hdChain) {\n const stmt = this.db.prepare(\n `INSERT INTO hd_chain (version, seed_id, spend_id, view_id, token_id, blinding_id)\n VALUES (?, ?, ?, ?, ?, ?)`\n );\n stmt.run([\n hdChain.version,\n this.bytesToHex(hdChain.seedId),\n this.bytesToHex(hdChain.spendId),\n this.bytesToHex(hdChain.viewId),\n this.bytesToHex(hdChain.tokenId),\n this.bytesToHex(hdChain.blindingId),\n ]);\n stmt.free();\n }\n\n // Save view key\n try {\n const viewKey = km.getPrivateViewKey();\n const viewPublicKey = this.getPublicKeyFromViewKey(viewKey);\n const stmt = this.db.prepare('INSERT INTO view_key (public_key, secret_key) VALUES (?, ?)');\n stmt.run([this.serializePublicKey(viewPublicKey), this.serializeViewKey(viewKey)]);\n stmt.free();\n } catch {\n // View key not available\n }\n\n // Save spend key\n try {\n const spendPublicKey = km.getPublicSpendingKey();\n const stmt = this.db.prepare('INSERT INTO spend_key (public_key) VALUES (?)');\n stmt.run([this.serializePublicKey(spendPublicKey)]);\n stmt.free();\n } catch {\n // Spend key not available\n }\n\n // Note: Keys, output keys, encrypted keys, and sub-addresses would be saved here\n // For now, we're saving the essential HD chain and master keys\n // Full implementation would iterate through all keys and save them\n\n // Commit transaction\n this.db.run('COMMIT');\n\n // Persist to disk\n this.persistToDisk();\n } catch (error) {\n this.db.run('ROLLBACK');\n throw error;\n }\n }\n\n /**\n * Get the current KeyManager instance\n */\n getKeyManager(): KeyManager | null {\n return this.keyManager;\n }\n\n /**\n * Get the database instance (for use by sync modules)\n * @internal\n */\n getDatabase(): any {\n if (!this.isOpen) {\n throw new Error(\n 'Database not initialized. Call loadWallet(), createWallet(), or restoreWallet() first.'\n );\n }\n return this.db;\n }\n\n /**\n * Get the database path\n * @internal\n */\n getDatabasePath(): string {\n return this.dbPath;\n }\n\n /**\n * Save database to disk (if not in-memory)\n */\n async saveDatabase(): Promise<void> {\n if (this.dbPath === ':memory:' || !this.isOpen) {\n return;\n }\n this.persistToDisk();\n }\n\n /**\n * Close the database connection\n */\n close(): void {\n if (this.db) {\n this.db.close();\n this.db = null;\n this.isOpen = false;\n }\n }\n\n // ============================================================================\n // Serialization helpers\n // ============================================================================\n\n private deserializeScalar(hex: string): any {\n const Scalar = blsctModule.Scalar;\n return Scalar.deserialize(hex);\n }\n\n private serializeViewKey(viewKey: any): string {\n return viewKey.serialize();\n }\n\n private deserializeViewKey(hex: string): any {\n const Scalar = blsctModule.Scalar;\n \n return Scalar.deserialize(hex);\n }\n\n private serializePublicKey(publicKey: any): string {\n return publicKey.serialize();\n }\n\n private deserializePublicKey(hex: string): any {\n const PublicKey = blsctModule.PublicKey;\n return PublicKey.deserialize(hex);\n }\n\n private getPublicKeyFromViewKey(viewKey: any): any {\n const Scalar = blsctModule.Scalar;\n const PublicKey = blsctModule.PublicKey;\n const scalar = Scalar.deserialize(viewKey.serialize());\n return PublicKey.fromScalar(scalar);\n }\n\n private bytesToHex(bytes: Uint8Array): string {\n return Array.from(bytes)\n .map(b => b.toString(16).padStart(2, '0'))\n .join('');\n }\n\n private hexToBytes(hex: string): Uint8Array {\n const bytes = new Uint8Array(hex.length / 2);\n for (let i = 0; i < hex.length; i += 2) {\n bytes[i / 2] = parseInt(hex.substr(i, 2), 16);\n }\n return bytes;\n }\n\n /**\n * Get wallet balance (sum of unspent output amounts)\n * @param tokenId - Optional token ID to filter by (null for NAV)\n * @returns Balance in satoshis\n */\n async getBalance(tokenId: string | null = null): Promise<bigint> {\n if (!this.isOpen) {\n throw new Error('Database not initialized');\n }\n\n let query = 'SELECT SUM(amount) as total FROM wallet_outputs WHERE is_spent = 0';\n const params: any[] = [];\n\n if (tokenId === null) {\n // NAV balance - outputs with no token_id or default token_id\n query += ' AND (token_id IS NULL OR token_id = ?)';\n params.push('0000000000000000000000000000000000000000000000000000000000000000');\n } else {\n query += ' AND token_id = ?';\n params.push(tokenId);\n }\n\n const result = this.db.exec(query);\n if (result.length === 0 || result[0].values.length === 0 || result[0].values[0][0] === null) {\n return 0n;\n }\n\n return BigInt(result[0].values[0][0] as number);\n }\n\n /**\n * Get unspent outputs (UTXOs)\n * @param tokenId - Optional token ID to filter by (null for NAV)\n * @returns Array of unspent outputs\n */\n async getUnspentOutputs(tokenId: string | null = null): Promise<WalletOutput[]> {\n if (!this.isOpen) {\n throw new Error('Database not initialized');\n }\n\n let query = `\n SELECT output_hash, tx_hash, output_index, block_height, amount, memo, token_id, \n blinding_key, spending_key, is_spent, spent_tx_hash, spent_block_height\n FROM wallet_outputs \n WHERE is_spent = 0\n `;\n const params: any[] = [];\n\n if (tokenId === null) {\n // NAV - outputs with no token_id or default token_id\n query += ' AND (token_id IS NULL OR token_id = ?)';\n params.push('0000000000000000000000000000000000000000000000000000000000000000');\n } else {\n query += ' AND token_id = ?';\n params.push(tokenId);\n }\n\n query += ' ORDER BY block_height ASC';\n\n const stmt = this.db.prepare(query);\n if (params.length > 0) {\n stmt.bind(params);\n }\n\n const outputs: WalletOutput[] = [];\n while (stmt.step()) {\n const row = stmt.getAsObject();\n outputs.push({\n outputHash: row.output_hash as string,\n txHash: row.tx_hash as string,\n outputIndex: row.output_index as number,\n blockHeight: row.block_height as number,\n amount: BigInt(row.amount as number),\n memo: row.memo as string | null,\n tokenId: row.token_id as string | null,\n blindingKey: row.blinding_key as string,\n spendingKey: row.spending_key as string,\n isSpent: (row.is_spent as number) === 1,\n spentTxHash: row.spent_tx_hash as string | null,\n spentBlockHeight: row.spent_block_height as number | null,\n });\n }\n stmt.free();\n\n return outputs;\n }\n\n /**\n * Get all outputs (spent and unspent)\n * @returns Array of all wallet outputs\n */\n async getAllOutputs(): Promise<WalletOutput[]> {\n if (!this.isOpen) {\n throw new Error('Database not initialized');\n }\n\n const stmt = this.db.prepare(`\n SELECT output_hash, tx_hash, output_index, block_height, amount, memo, token_id, \n blinding_key, spending_key, is_spent, spent_tx_hash, spent_block_height\n FROM wallet_outputs \n ORDER BY block_height ASC\n `);\n\n const outputs: WalletOutput[] = [];\n while (stmt.step()) {\n const row = stmt.getAsObject();\n outputs.push({\n outputHash: row.output_hash as string,\n txHash: row.tx_hash as string,\n outputIndex: row.output_index as number,\n blockHeight: row.block_height as number,\n amount: BigInt(row.amount as number),\n memo: row.memo as string | null,\n tokenId: row.token_id as string | null,\n blindingKey: row.blinding_key as string,\n spendingKey: row.spending_key as string,\n isSpent: (row.is_spent as number) === 1,\n spentTxHash: row.spent_tx_hash as string | null,\n spentBlockHeight: row.spent_block_height as number | null,\n });\n }\n stmt.free();\n\n return outputs;\n }\n}\n","/**\n * Electrum Client - Connect and interact with Electrum servers\n *\n * Supports WebSocket and TCP connections\n * Implements Electrum protocol for fetching transaction keys and blockchain data\n *\n * Based on electrumx server implementation and Navio-specific extensions\n */\n\nimport { sha256 } from '@noble/hashes/sha256';\nimport { ripemd160 } from '@noble/hashes/ripemd160';\n\n// Import WebSocket - use native WebSocket in browser, ws in Node.js\nlet WebSocketClass: any;\nlet isBrowserWebSocket = false;\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\nif (typeof (globalThis as any).window !== 'undefined' && (globalThis as any).window?.WebSocket) {\n // Browser environment - use native WebSocket\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n WebSocketClass = (globalThis as any).window.WebSocket;\n isBrowserWebSocket = true;\n} else {\n // Node.js environment - use ws library\n try {\n WebSocketClass = require('ws');\n } catch (error) {\n throw new Error('WebSocket not available. In Node.js, install ws: npm install ws');\n }\n}\n\n/**\n * Helper to attach WebSocket event handlers that works with both\n * Node.js ws library (.on()) and browser WebSocket (.onX / addEventListener)\n */\nfunction attachWebSocketHandler(\n ws: any,\n event: 'open' | 'message' | 'error' | 'close',\n handler: (data?: any) => void\n): void {\n if (isBrowserWebSocket) {\n // Browser WebSocket uses onX properties or addEventListener\n switch (event) {\n case 'open':\n ws.onopen = handler;\n break;\n case 'message':\n // Browser WebSocket passes MessageEvent, extract data\n ws.onmessage = (evt: MessageEvent) => handler(evt.data);\n break;\n case 'error':\n ws.onerror = () => handler(new Error('WebSocket error'));\n break;\n case 'close':\n ws.onclose = handler;\n break;\n }\n } else {\n // Node.js ws library uses .on()\n ws.on(event, handler);\n }\n}\n\n/**\n * Electrum server connection options\n */\nexport interface ElectrumOptions {\n /** Server host (default: localhost) */\n host?: string;\n /** Server port (default: 50001) */\n port?: number;\n /** Use SSL/TLS (default: false) */\n ssl?: boolean;\n /** Connection timeout in milliseconds (default: 30000) */\n timeout?: number;\n /** Client name for server.version (default: 'navio-sdk') */\n clientName?: string;\n /** Client version for server.version (default: '1.4') */\n clientVersion?: string;\n}\n\n/**\n * Transaction keys structure\n * Represents the keys associated with a transaction\n */\nexport interface TransactionKeys {\n /** Transaction hash */\n txHash: string;\n /** Transaction keys (structure depends on coin implementation) */\n keys: any;\n}\n\n/**\n * Block transaction keys\n * Contains all transaction keys for a block\n */\nexport interface BlockTransactionKeys {\n /** Block height */\n height: number;\n /** Transaction keys for this block */\n txKeys: TransactionKeys[];\n}\n\n/**\n * Range result for block transaction keys\n */\nexport interface BlockTransactionKeysRange {\n /** Blocks with their transaction keys */\n blocks: BlockTransactionKeys[];\n /** Next height to query (for pagination) */\n nextHeight: number;\n}\n\n/**\n * Block header information\n */\nexport interface BlockHeader {\n /** Block height */\n height: number;\n /** Block hash */\n hash: string;\n /** Previous block hash */\n prevHash: string;\n /** Merkle root */\n merkleRoot: string;\n /** Block timestamp */\n timestamp: number;\n /** Block version */\n version: number;\n /** Difficulty target */\n bits: number;\n /** Nonce */\n nonce: number;\n}\n\n/**\n * Electrum RPC error\n */\nexport class ElectrumError extends Error {\n constructor(\n message: string,\n public code?: number,\n public data?: any\n ) {\n super(message);\n this.name = 'ElectrumError';\n }\n}\n\n/**\n * Electrum Client - Connects to Electrum servers.\n * \n * Low-level client for the Electrum protocol. For most use cases,\n * use NavioClient with the 'electrum' backend instead.\n * \n * @category Protocol\n */\nexport class ElectrumClient {\n private ws: any = null;\n private requestId = 0;\n private pendingRequests = new Map<\n number,\n { resolve: (value: any) => void; reject: (error: Error) => void; timeout: NodeJS.Timeout }\n >();\n private connected = false;\n private options: Required<ElectrumOptions>;\n private reconnectAttempts = 0;\n\n constructor(options: ElectrumOptions = {}) {\n this.options = {\n host: options.host || 'localhost',\n port: options.port || 50001,\n ssl: options.ssl || false,\n timeout: options.timeout || 30000,\n clientName: options.clientName || 'navio-sdk',\n clientVersion: options.clientVersion || '1.4',\n };\n }\n\n /**\n * Connect to the Electrum server\n */\n async connect(): Promise<void> {\n if (this.connected && this.ws) {\n return;\n }\n\n return new Promise((resolve, reject) => {\n const protocol = this.options.ssl ? 'wss' : 'ws';\n const url = `${protocol}://${this.options.host}:${this.options.port}`;\n\n try {\n this.ws = new WebSocketClass(url);\n\n attachWebSocketHandler(this.ws, 'open', async () => {\n this.connected = true;\n this.reconnectAttempts = 0;\n\n // Send server.version as required by Electrum protocol\n try {\n await this.call('server.version', this.options.clientName, this.options.clientVersion);\n resolve();\n } catch (error) {\n reject(error);\n }\n });\n\n attachWebSocketHandler(this.ws, 'message', (data: Buffer | string) => {\n try {\n // Handle both Buffer (Node.js) and string (browser) data\n const dataStr = typeof data === 'string' ? data : data.toString();\n const response = JSON.parse(dataStr);\n this.handleResponse(response);\n } catch (error) {\n console.error('Error parsing response:', error);\n }\n });\n\n attachWebSocketHandler(this.ws, 'error', (error: Error) => {\n this.connected = false;\n if (this.reconnectAttempts === 0) {\n reject(error);\n }\n });\n\n attachWebSocketHandler(this.ws, 'close', () => {\n this.connected = false;\n this.ws = null;\n // Clear pending requests\n for (const [, { reject, timeout }] of Array.from(this.pendingRequests)) {\n clearTimeout(timeout);\n reject(new Error('Connection closed'));\n }\n this.pendingRequests.clear();\n });\n } catch (error) {\n reject(error);\n }\n });\n }\n\n /**\n * Handle incoming response from server\n */\n private handleResponse(response: any): void {\n if (response.id !== undefined && this.pendingRequests.has(response.id)) {\n const { resolve, reject, timeout } = this.pendingRequests.get(response.id)!;\n clearTimeout(timeout);\n this.pendingRequests.delete(response.id);\n\n if (response.error) {\n const error = new ElectrumError(\n response.error.message || JSON.stringify(response.error),\n response.error.code,\n response.error.data\n );\n reject(error);\n } else {\n resolve(response.result);\n }\n }\n }\n\n /**\n * Make an RPC call to the Electrum server\n * @param method - RPC method name\n * @param params - Method parameters\n * @returns Promise resolving to the result\n */\n async call(method: string, ...params: any[]): Promise<any> {\n if (!this.connected || !this.ws) {\n throw new Error('Not connected to Electrum server. Call connect() first.');\n }\n\n return new Promise((resolve, reject) => {\n const id = ++this.requestId;\n const request = {\n id,\n method,\n params,\n };\n\n // Set timeout for request\n const timeout = setTimeout(() => {\n if (this.pendingRequests.has(id)) {\n this.pendingRequests.delete(id);\n reject(new Error(`Request timeout for method: ${method}`));\n }\n }, this.options.timeout);\n\n this.pendingRequests.set(id, { resolve, reject, timeout });\n\n try {\n this.ws!.send(JSON.stringify(request));\n } catch (error) {\n clearTimeout(timeout);\n this.pendingRequests.delete(id);\n reject(error);\n }\n });\n }\n\n /**\n * Disconnect from the server\n */\n disconnect(): void {\n if (this.ws) {\n this.ws.close();\n this.ws = null;\n }\n this.connected = false;\n }\n\n /**\n * Check if connected to server\n */\n isConnected(): boolean {\n return this.connected;\n }\n\n // ============================================================================\n // Blockchain Methods\n // ============================================================================\n\n /**\n * Get server version\n * @returns Server version information\n */\n async getServerVersion(): Promise<[string, string]> {\n return this.call('server.version', this.options.clientName, this.options.clientVersion);\n }\n\n /**\n * Get block header for a given height\n * @param height - Block height\n * @returns Block header\n */\n async getBlockHeader(height: number): Promise<string> {\n return this.call('blockchain.block.header', height);\n }\n\n /**\n * Get block headers for a range of heights\n * @param startHeight - Starting block height\n * @param count - Number of headers to fetch\n * @returns Block headers\n */\n async getBlockHeaders(\n startHeight: number,\n count: number\n ): Promise<{ count: number; hex: string; max: number }> {\n return this.call('blockchain.block.headers', startHeight, count);\n }\n\n /**\n * Subscribe to block headers\n * @param callback - Callback function for new headers\n */\n async subscribeBlockHeaders(callback: (header: any) => void): Promise<void> {\n // Electrum protocol uses notifications for subscriptions\n // This would need to be implemented with notification handling\n // For now, return the initial header\n const header = await this.call('blockchain.headers.subscribe');\n callback(header);\n }\n\n /**\n * Get chain tip height\n * @returns Current chain tip height\n */\n async getChainTipHeight(): Promise<number> {\n const response = await this.call('blockchain.headers.subscribe');\n // Handle both formats: { height, hex } or just the height number\n if (typeof response === 'number') {\n return response;\n }\n if (response && typeof response.height === 'number') {\n return response.height;\n }\n throw new Error(`Unexpected blockchain.headers.subscribe response: ${JSON.stringify(response)}`);\n }\n\n // ============================================================================\n // Transaction Key Methods (Navio-specific)\n // ============================================================================\n\n /**\n * Get transaction keys for a specific transaction\n * @param txHash - Transaction hash (hex string)\n * @returns Transaction keys\n */\n async getTransactionKeys(txHash: string): Promise<any> {\n return this.call('blockchain.transaction.get_keys', txHash);\n }\n\n /**\n * Get all transaction keys for a block\n * @param height - Block height\n * @returns Array of transaction keys for the block\n */\n async getBlockTransactionKeys(height: number): Promise<any[]> {\n return this.call('blockchain.block.get_txs_keys', height);\n }\n\n /**\n * Get transaction keys for a range of blocks (paginated)\n * @param startHeight - Starting block height\n * @returns Range result with blocks and next height\n */\n async getBlockTransactionKeysRange(startHeight: number): Promise<BlockTransactionKeysRange> {\n const result = await this.call('blockchain.block.get_range_txs_keys', startHeight);\n\n // Transform result to our format\n // result.blocks is an array where each element is an array of transaction keys for that block\n const blocks: BlockTransactionKeys[] = [];\n\n if (result.blocks && Array.isArray(result.blocks)) {\n for (let i = 0; i < result.blocks.length; i++) {\n const blockData = result.blocks[i];\n const blockHeight = startHeight + i;\n\n // blockData is an array of transaction keys for this block\n // Each element may be just the keys object, or an object with txHash and keys\n const txKeys: TransactionKeys[] = [];\n\n if (Array.isArray(blockData)) {\n for (const txKeyData of blockData) {\n if (typeof txKeyData === 'object' && txKeyData !== null) {\n // Check if it's already in our format\n if ('txHash' in txKeyData && 'keys' in txKeyData) {\n txKeys.push({\n txHash: txKeyData.txHash || '',\n keys: txKeyData.keys,\n });\n } else {\n // It's just the keys object, try to extract hash\n const txHash = (txKeyData as any).txHash || (txKeyData as any).hash || '';\n txKeys.push({\n txHash,\n keys: txKeyData,\n });\n }\n }\n }\n }\n\n blocks.push({\n height: blockHeight,\n txKeys,\n });\n }\n }\n\n return {\n blocks,\n nextHeight: result.next_height || startHeight + blocks.length,\n };\n }\n\n /**\n * Fetch all transaction keys from genesis to chain tip\n * @param progressCallback - Optional callback for progress updates\n * @returns Array of all block transaction keys\n */\n async fetchAllTransactionKeys(\n progressCallback?: (height: number, totalHeight: number, blocksProcessed: number) => void\n ): Promise<BlockTransactionKeys[]> {\n const tipHeight = await this.getChainTipHeight();\n const allBlocks: BlockTransactionKeys[] = [];\n let currentHeight = 0;\n let totalBlocksProcessed = 0;\n\n while (currentHeight <= tipHeight) {\n const rangeResult = await this.getBlockTransactionKeysRange(currentHeight);\n\n allBlocks.push(...rangeResult.blocks);\n totalBlocksProcessed += rangeResult.blocks.length;\n\n if (progressCallback) {\n progressCallback(currentHeight, tipHeight, totalBlocksProcessed);\n }\n\n currentHeight = rangeResult.nextHeight;\n\n // Safety check to prevent infinite loops\n if (currentHeight <= rangeResult.blocks[rangeResult.blocks.length - 1]?.height) {\n throw new Error('Server did not advance next_height properly');\n }\n }\n\n return allBlocks;\n }\n\n /**\n * Get serialized transaction output by output hash (Navio-specific)\n * @param outputHash - Output hash (hex string)\n * @returns Serialized output (hex string)\n */\n async getTransactionOutput(outputHash: string): Promise<string> {\n return this.call('blockchain.transaction.get_output', outputHash);\n }\n\n // ============================================================================\n // Transaction Methods\n // ============================================================================\n\n /**\n * Get raw transaction\n * @param txHash - Transaction hash (hex string)\n * @param verbose - Return verbose transaction data\n * @param blockHash - Optional block hash for context\n * @returns Raw transaction or verbose transaction data\n */\n async getRawTransaction(\n txHash: string,\n verbose = false,\n blockHash?: string\n ): Promise<string | any> {\n return this.call('blockchain.transaction.get', txHash, verbose, blockHash);\n }\n\n /**\n * Broadcast a transaction\n * @param rawTx - Raw transaction (hex string)\n * @returns Transaction hash if successful\n */\n async broadcastTransaction(rawTx: string): Promise<string> {\n return this.call('blockchain.transaction.broadcast', rawTx);\n }\n\n // ============================================================================\n // Address/Script Hash Methods\n // ============================================================================\n\n /**\n * Get transaction history for a script hash\n * @param scriptHash - Script hash (hex string, reversed)\n * @returns Transaction history\n */\n async getHistory(scriptHash: string): Promise<any[]> {\n return this.call('blockchain.scripthash.get_history', scriptHash);\n }\n\n /**\n * Get unspent transaction outputs for a script hash\n * @param scriptHash - Script hash (hex string, reversed)\n * @returns Unspent outputs\n */\n async getUnspent(scriptHash: string): Promise<any[]> {\n return this.call('blockchain.scripthash.listunspent', scriptHash);\n }\n\n /**\n * Subscribe to script hash updates\n * @param scriptHash - Script hash (hex string, reversed)\n * @param callback - Callback for status updates\n */\n async subscribeScriptHash(scriptHash: string, callback: (status: string) => void): Promise<void> {\n const status = await this.call('blockchain.scripthash.subscribe', scriptHash);\n callback(status);\n }\n\n // ============================================================================\n // Utility Methods\n // ============================================================================\n\n /**\n * Calculate script hash from address (for Electrum protocol)\n * @param address - Address string\n * @returns Script hash (hex string, reversed for Electrum)\n */\n static calculateScriptHash(address: string): string {\n // This is a placeholder - actual implementation depends on address format\n // For Navio, this would need to handle BLS CT addresses\n const hash = ripemd160(sha256(Buffer.from(address, 'utf-8')));\n // Reverse for Electrum protocol\n return Buffer.from(hash).reverse().toString('hex');\n }\n\n /**\n * Reverse a hex string (for Electrum protocol hash format)\n * @param hex - Hex string\n * @returns Reversed hex string\n */\n static reverseHex(hex: string): string {\n const bytes = Buffer.from(hex, 'hex');\n return Buffer.from(bytes.reverse()).toString('hex');\n }\n}\n","/**\n * Transaction Keys Sync Module\n *\n * Synchronizes transaction keys from a sync provider to wallet database\n * - Supports multiple backends: Electrum, P2P, or custom providers\n * - Tracks sync progress and resumes from last state\n * - Handles block reorganizations\n * - Persists sync state in wallet database\n */\n\nimport { SyncProvider } from './sync-provider';\nimport { ElectrumClient } from './electrum';\nimport { WalletDB } from './wallet-db';\nimport { KeyManager } from './key-manager';\nimport type { BlockTransactionKeys, TransactionKeys } from './electrum';\nimport * as blsctModule from 'navio-blsct';\nimport { sha256 } from '@noble/hashes/sha256';\n\n/**\n * Sync state stored in database\n */\nexport interface SyncState {\n /** Last synced block height */\n lastSyncedHeight: number;\n /** Last synced block hash */\n lastSyncedHash: string;\n /** Total transaction keys synced */\n totalTxKeysSynced: number;\n /** Last sync timestamp */\n lastSyncTime: number;\n /** Chain tip at last sync */\n chainTipAtLastSync: number;\n}\n\n/**\n * Sync progress callback\n */\nexport type SyncProgressCallback = (\n currentHeight: number,\n chainTip: number,\n blocksProcessed: number,\n txKeysProcessed: number,\n isReorg: boolean\n) => void;\n\n/**\n * Sync options\n */\nexport interface SyncOptions {\n /** Start height (default: last synced height + 1) */\n startHeight?: number;\n /** End height (default: chain tip) */\n endHeight?: number;\n /** Progress callback */\n onProgress?: SyncProgressCallback;\n /** Stop on reorganization (default: true) */\n stopOnReorg?: boolean;\n /** Verify block hashes (default: true) */\n verifyHashes?: boolean;\n /** Save database after N blocks (default: 100) - 0 to save only at end */\n saveInterval?: number;\n /** Keep transaction keys in database after processing (default: false) */\n keepTxKeys?: boolean;\n /** Keep block hashes for last N blocks only (default: 10000) - 0 to keep all */\n blockHashRetention?: number;\n}\n\n/**\n * Background sync options for continuous synchronization\n */\nexport interface BackgroundSyncOptions extends SyncOptions {\n /** \n * Polling interval in milliseconds \n * @default 10000 (10 seconds)\n */\n pollInterval?: number;\n\n /**\n * Callback when a new block is detected\n */\n onNewBlock?: (height: number, hash: string) => void;\n\n /**\n * Callback when new transactions are detected for the wallet\n */\n onNewTransaction?: (txHash: string, outputHash: string, amount: bigint) => void;\n\n /**\n * Callback when balance changes\n */\n onBalanceChange?: (newBalance: bigint, oldBalance: bigint) => void;\n\n /**\n * Callback on sync error (background sync continues after errors)\n */\n onError?: (error: Error) => void;\n}\n\n/**\n * Reorganization information\n */\nexport interface ReorganizationInfo {\n /** Height where reorganization occurred */\n height: number;\n /** Old block hash */\n oldHash: string;\n /** New block hash */\n newHash: string;\n /** Number of blocks to revert */\n blocksToRevert: number;\n}\n\n/**\n * Transaction Keys Sync Manager\n *\n * Can be initialized with either:\n * - A SyncProvider (recommended) - works with Electrum, P2P, or custom backends\n * - An ElectrumClient (legacy) - for backwards compatibility\n * \n * @category Sync\n */\nexport class TransactionKeysSync {\n private walletDB: WalletDB;\n private syncProvider: SyncProvider;\n private keyManager: KeyManager | null = null;\n private syncState: SyncState | null = null;\n private blockHashRetention: number = 1000; // Keep last 1k block hashes by default\n\n /**\n * Create a new TransactionKeysSync instance\n * @param walletDB - The wallet database\n * @param provider - A SyncProvider or ElectrumClient instance\n */\n constructor(walletDB: WalletDB, provider: SyncProvider | ElectrumClient) {\n this.walletDB = walletDB;\n\n // Support both SyncProvider and legacy ElectrumClient\n if ('type' in provider && (provider.type === 'electrum' || provider.type === 'p2p' || provider.type === 'custom')) {\n // It's a SyncProvider\n this.syncProvider = provider;\n } else {\n // It's a legacy ElectrumClient - wrap it in an adapter\n this.syncProvider = this.wrapElectrumClient(provider as ElectrumClient);\n }\n }\n\n /**\n * Wrap an ElectrumClient as a SyncProvider for backwards compatibility\n */\n private wrapElectrumClient(client: ElectrumClient): SyncProvider {\n return {\n type: 'electrum' as const,\n connect: () => client.connect(),\n disconnect: () => client.disconnect(),\n isConnected: () => client.isConnected(),\n getChainTipHeight: () => client.getChainTipHeight(),\n getChainTip: async () => {\n const height = await client.getChainTipHeight();\n const header = await client.getBlockHeader(height);\n const hash = Buffer.from(sha256(sha256(Buffer.from(header, 'hex')))).reverse().toString('hex');\n return { height, hash };\n },\n getBlockHeader: (height: number) => client.getBlockHeader(height),\n getBlockHeaders: (startHeight: number, count: number) => client.getBlockHeaders(startHeight, count),\n getBlockTransactionKeysRange: (startHeight: number) => client.getBlockTransactionKeysRange(startHeight),\n getBlockTransactionKeys: async (height: number) => {\n const result = await client.getBlockTransactionKeys(height);\n return Array.isArray(result) ? result : [];\n },\n getTransactionOutput: (outputHash: string) => client.getTransactionOutput(outputHash),\n broadcastTransaction: (rawTx: string) => client.broadcastTransaction(rawTx),\n getRawTransaction: (txHash: string, verbose?: boolean) => client.getRawTransaction(txHash, verbose),\n };\n }\n\n /**\n * Get the sync provider being used\n */\n getSyncProvider(): SyncProvider {\n return this.syncProvider;\n }\n\n /**\n * Get the provider type (electrum, p2p, or custom)\n */\n getProviderType(): 'electrum' | 'p2p' | 'custom' {\n return this.syncProvider.type;\n }\n\n /**\n * Set the KeyManager instance for output detection\n * @param keyManager - The KeyManager instance\n */\n setKeyManager(keyManager: KeyManager): void {\n this.keyManager = keyManager;\n }\n\n /**\n * Initialize sync manager\n * Loads sync state from database\n */\n async initialize(): Promise<void> {\n // Only load/create wallet if keyManager wasn't already set via setKeyManager()\n if (!this.keyManager) {\n // Ensure database is initialized\n // Try to load wallet (will initialize DB if needed)\n try {\n this.keyManager = await this.walletDB.loadWallet();\n } catch {\n // If wallet doesn't exist, create it\n this.keyManager = await this.walletDB.createWallet();\n }\n }\n\n // Load sync state from database\n this.syncState = await this.loadSyncState();\n }\n\n /**\n * Get current sync state\n */\n getSyncState(): SyncState | null {\n return this.syncState;\n }\n\n /**\n * Get last synced height\n */\n getLastSyncedHeight(): number {\n return this.syncState?.lastSyncedHeight ?? -1;\n }\n\n /**\n * Check if sync is needed\n */\n async isSyncNeeded(): Promise<boolean> {\n if (!this.syncState) {\n return true;\n }\n\n const chainTip = await this.syncProvider.getChainTipHeight();\n return chainTip > this.syncState.lastSyncedHeight;\n }\n\n /**\n * Synchronize transaction keys from Electrum server\n * @param options - Sync options\n * @returns Number of transaction keys synced\n */\n async sync(options: SyncOptions = {}): Promise<number> {\n if (!this.keyManager) {\n await this.initialize();\n }\n\n const {\n startHeight,\n endHeight,\n onProgress,\n stopOnReorg = true,\n verifyHashes = true,\n saveInterval = 100,\n keepTxKeys = false,\n blockHashRetention = 1000,\n } = options;\n\n // Update retention setting\n this.blockHashRetention = blockHashRetention;\n\n // Determine start and end heights\n const lastSynced = this.syncState?.lastSyncedHeight ?? -1;\n\n // For first sync, use wallet creation height if available\n let defaultStartHeight = lastSynced + 1;\n if (lastSynced === -1) {\n const creationHeight = await this.walletDB.getCreationHeight();\n if (creationHeight > 0) {\n defaultStartHeight = creationHeight;\n }\n }\n\n const syncStartHeight = startHeight ?? defaultStartHeight;\n const chainTip = await this.syncProvider.getChainTipHeight();\n const syncEndHeight = endHeight ?? chainTip;\n\n if (syncStartHeight > syncEndHeight) {\n return 0; // Already synced\n }\n\n // Check for reorganization\n if (this.syncState && verifyHashes) {\n const reorgInfo = await this.checkReorganization(this.syncState.lastSyncedHeight);\n if (reorgInfo) {\n if (stopOnReorg) {\n throw new Error(\n `Chain reorganization detected at height ${reorgInfo.height}. ` +\n `Old hash: ${reorgInfo.oldHash}, New hash: ${reorgInfo.newHash}. ` +\n `Need to revert ${reorgInfo.blocksToRevert} blocks.`\n );\n } else {\n // Handle reorganization\n await this.handleReorganization(reorgInfo);\n }\n }\n }\n\n let totalTxKeysSynced = 0;\n let currentHeight = syncStartHeight;\n let blocksProcessed = 0;\n let lastSaveHeight = syncStartHeight - 1;\n\n // Sync in batches - server will return as many blocks as fit in max_send\n // We keep fetching until we reach the end height\n while (currentHeight <= syncEndHeight) {\n // Fetch transaction keys - server will return maximum possible blocks\n const rangeResult = await this.syncProvider.getBlockTransactionKeysRange(currentHeight);\n\n // Batch fetch all block headers for this batch\n const blockHeights = rangeResult.blocks\n .filter(block => block.height <= syncEndHeight)\n .map(block => block.height);\n\n let blockHeadersMap: Map<number, string> = new Map();\n if (blockHeights.length > 0 && verifyHashes) {\n // Fetch headers in batch using getBlockHeaders\n const firstHeight = blockHeights[0];\n const count = blockHeights.length;\n const headersResult = await this.syncProvider.getBlockHeaders(firstHeight, count);\n\n // Parse concatenated hex string - each header is 80 bytes (160 hex chars)\n const headerSize = 160; // 80 bytes * 2 hex chars per byte\n const hex = headersResult.hex;\n\n // Map headers by height\n for (let i = 0; i < count && i * headerSize < hex.length; i++) {\n const height = firstHeight + i;\n const headerStart = i * headerSize;\n const headerEnd = headerStart + headerSize;\n const headerHex = hex.substring(headerStart, headerEnd);\n blockHeadersMap.set(height, headerHex);\n }\n }\n\n // Process each block in the batch\n for (const block of rangeResult.blocks) {\n if (block.height > syncEndHeight) {\n break;\n }\n\n // Get block header and hash (from batch or fetch individually if not verifying)\n let blockHash: string;\n if (verifyHashes && blockHeadersMap.has(block.height)) {\n const blockHeader = blockHeadersMap.get(block.height)!;\n blockHash = this.extractBlockHash(blockHeader);\n } else if (verifyHashes) {\n // Fallback: fetch individual header if not in batch\n const blockHeader = await this.syncProvider.getBlockHeader(block.height);\n blockHash = this.extractBlockHash(blockHeader);\n } else {\n // If not verifying, we can skip header fetch for now\n // But we still need a hash for storage - use a placeholder or fetch minimal\n // For now, let's fetch it but this could be optimized further\n const blockHeader = await this.syncProvider.getBlockHeader(block.height);\n blockHash = this.extractBlockHash(blockHeader);\n }\n\n // Verify block hash if requested\n if (verifyHashes) {\n // Store block hash for future verification (pass chainTip to avoid repeated fetches)\n await this.storeBlockHash(block.height, blockHash, chainTip);\n\n // Check for reorganization\n if (this.syncState && block.height <= this.syncState.lastSyncedHeight) {\n const storedHash = await this.getStoredBlockHash(block.height);\n if (storedHash && storedHash !== blockHash) {\n // Reorganization detected\n const reorgInfo: ReorganizationInfo = {\n height: block.height,\n oldHash: storedHash,\n newHash: blockHash,\n blocksToRevert: this.syncState.lastSyncedHeight - block.height + 1,\n };\n\n if (stopOnReorg) {\n throw new Error(\n `Chain reorganization detected at height ${block.height}. ` +\n `Old hash: ${storedHash}, New hash: ${blockHash}.`\n );\n } else {\n await this.handleReorganization(reorgInfo);\n }\n }\n }\n } else {\n // Still store block hash even if not verifying (pass chainTip to avoid repeated fetches)\n await this.storeBlockHash(block.height, blockHash, chainTip);\n }\n\n // Store transaction keys for this block\n const txKeysCount = await this.storeBlockTransactionKeys(block, blockHash, keepTxKeys);\n\n // Check for spent outputs in this block's transactions\n if (this.keyManager) {\n await this.processBlockForSpentOutputs(block, blockHash);\n }\n\n totalTxKeysSynced += txKeysCount;\n blocksProcessed++;\n\n // Progress callback\n if (onProgress) {\n onProgress(block.height, syncEndHeight, blocksProcessed, totalTxKeysSynced, false);\n }\n }\n\n // Update sync state after processing batch\n if (rangeResult.blocks.length > 0) {\n const lastBlock = rangeResult.blocks[rangeResult.blocks.length - 1];\n let lastBlockHash: string;\n\n if (blockHeadersMap.has(lastBlock.height)) {\n const lastBlockHeader = blockHeadersMap.get(lastBlock.height)!;\n lastBlockHash = this.extractBlockHash(lastBlockHeader);\n } else {\n // Fallback: fetch if not in batch\n const lastBlockHeader = await this.syncProvider.getBlockHeader(lastBlock.height);\n lastBlockHash = this.extractBlockHash(lastBlockHeader);\n }\n\n await this.updateSyncState({\n lastSyncedHeight: lastBlock.height,\n lastSyncedHash: lastBlockHash,\n totalTxKeysSynced: (this.syncState?.totalTxKeysSynced ?? 0) + totalTxKeysSynced,\n lastSyncTime: Date.now(),\n chainTipAtLastSync: chainTip,\n });\n\n // Save database periodically if saveInterval is set\n if (saveInterval > 0 && lastBlock.height - lastSaveHeight >= saveInterval) {\n await this.walletDB.saveDatabase();\n lastSaveHeight = lastBlock.height;\n }\n }\n\n // Move to next batch (server tells us where to continue)\n currentHeight = rangeResult.nextHeight;\n\n // Safety check to prevent infinite loops\n if (currentHeight <= rangeResult.blocks[rangeResult.blocks.length - 1]?.height) {\n throw new Error(\n `Server did not advance next_height properly. Current: ${currentHeight}, Last block: ${rangeResult.blocks[rangeResult.blocks.length - 1]?.height}`\n );\n }\n }\n\n // Final save after sync completes to ensure state is persisted\n await this.walletDB.saveDatabase();\n\n return totalTxKeysSynced;\n }\n\n /**\n * Check for chain reorganization\n * @param height - Height to check\n * @returns Reorganization info if detected, null otherwise\n */\n private async checkReorganization(height: number): Promise<ReorganizationInfo | null> {\n if (!this.syncState || height < 0) {\n return null;\n }\n\n // Get current block hash from server\n const currentHeader = await this.syncProvider.getBlockHeader(height);\n const currentHash = this.extractBlockHash(currentHeader);\n\n // Get stored block hash\n const storedHash = await this.getStoredBlockHash(height);\n\n if (storedHash && storedHash !== currentHash) {\n // Reorganization detected - find common ancestor\n let commonHeight = height - 1;\n while (commonHeight >= 0) {\n const commonHeader = await this.syncProvider.getBlockHeader(commonHeight);\n const commonHash = this.extractBlockHash(commonHeader);\n const storedCommonHash = await this.getStoredBlockHash(commonHeight);\n\n if (storedCommonHash === commonHash) {\n break;\n }\n commonHeight--;\n }\n\n return {\n height: commonHeight + 1,\n oldHash: storedHash,\n newHash: currentHash,\n blocksToRevert: height - commonHeight,\n };\n }\n\n return null;\n }\n\n /**\n * Handle chain reorganization\n * @param reorgInfo - Reorganization information\n */\n private async handleReorganization(reorgInfo: ReorganizationInfo): Promise<void> {\n console.log(\n `Handling reorganization: reverting ${reorgInfo.blocksToRevert} blocks from height ${reorgInfo.height}`\n );\n\n // Revert blocks in database\n const revertHeight = reorgInfo.height + reorgInfo.blocksToRevert - 1;\n await this.revertBlocks(reorgInfo.height, revertHeight);\n\n // Update sync state\n await this.updateSyncState({\n lastSyncedHeight: reorgInfo.height - 1,\n lastSyncedHash: (await this.getStoredBlockHash(reorgInfo.height - 1)) || '',\n totalTxKeysSynced: this.syncState?.totalTxKeysSynced ?? 0,\n lastSyncTime: Date.now(),\n chainTipAtLastSync: await this.syncProvider.getChainTipHeight(),\n });\n }\n\n /**\n * Process block transactions to detect spent outputs\n * @param block - Block transaction keys\n * @param _blockHash - Block hash (for reference)\n */\n private async processBlockForSpentOutputs(\n block: BlockTransactionKeys,\n _blockHash: string\n ): Promise<void> {\n for (const txKeys of block.txKeys) {\n const txHash = txKeys.txHash || '';\n if (!txHash) {\n continue;\n }\n\n // Transaction keys structure may contain inputs\n // Inputs reference outputs by outputHash\n const keys = txKeys.keys || {};\n const inputs = keys?.inputs || keys?.vin || [];\n\n if (Array.isArray(inputs)) {\n for (const input of inputs) {\n const outputHash = input?.outputHash || input?.output_hash || input?.prevout?.hash;\n\n if (outputHash) {\n // Check if we own this output\n const db = this.walletDB.getDatabase();\n const stmt = db.prepare(\n 'SELECT output_hash FROM wallet_outputs WHERE output_hash = ? AND is_spent = 0'\n );\n stmt.bind([outputHash]);\n\n if (stmt.step()) {\n // We own this output, mark it as spent\n const updateStmt = db.prepare(\n `UPDATE wallet_outputs \n SET is_spent = 1, spent_tx_hash = ?, spent_block_height = ?\n WHERE output_hash = ?`\n );\n updateStmt.run([txHash, block.height, outputHash]);\n updateStmt.free();\n }\n\n stmt.free();\n }\n }\n }\n }\n }\n\n /**\n * Revert blocks from database\n * @param startHeight - Start height to revert from\n * @param endHeight - End height to revert to\n */\n private async revertBlocks(startHeight: number, endHeight: number): Promise<void> {\n // Delete transaction keys for reverted blocks\n const db = this.walletDB.getDatabase();\n\n for (let height = startHeight; height <= endHeight; height++) {\n // Delete transaction keys for this block\n const stmt = db.prepare('DELETE FROM tx_keys WHERE block_height = ?');\n stmt.run([height]);\n stmt.free();\n\n // Revert wallet outputs: delete outputs created in this block and unspend outputs spent in this block\n // Delete outputs created in this block\n const deleteOutputsStmt = db.prepare('DELETE FROM wallet_outputs WHERE block_height = ?');\n deleteOutputsStmt.run([height]);\n deleteOutputsStmt.free();\n\n // Unspend outputs that were spent in this block\n const unspendStmt = db.prepare(\n `UPDATE wallet_outputs \n SET is_spent = 0, spent_tx_hash = NULL, spent_block_height = NULL\n WHERE spent_block_height = ?`\n );\n unspendStmt.run([height]);\n unspendStmt.free();\n\n // Delete block hash\n const hashStmt = db.prepare('DELETE FROM block_hashes WHERE height = ?');\n hashStmt.run([height]);\n hashStmt.free();\n }\n }\n\n /**\n * Store transaction keys for a block\n * @param block - Block transaction keys\n * @param blockHash - Block hash\n * @param keepTxKeys - Whether to keep transaction keys in database after processing\n * @returns Number of transaction keys stored\n */\n private async storeBlockTransactionKeys(\n block: BlockTransactionKeys,\n blockHash: string,\n keepTxKeys: boolean = false\n ): Promise<number> {\n const db = this.walletDB.getDatabase();\n\n let count = 0;\n\n for (const txKeys of block.txKeys) {\n // Extract txHash from keys if not provided\n // The keys structure from electrumx may contain the tx hash\n let txHash = txKeys.txHash;\n if (!txHash && txKeys.keys && typeof txKeys.keys === 'object') {\n // Try to extract hash from keys object\n txHash = (txKeys.keys as any).txHash || (txKeys.keys as any).hash || '';\n }\n\n // If still no hash, generate a placeholder (shouldn't happen in production)\n if (!txHash) {\n txHash = `block_${block.height}_tx_${count}`;\n }\n\n // Process outputs if KeyManager is available (before storing keys)\n if (this.keyManager) {\n await this.processTransactionKeys(txHash, txKeys.keys, block.height, blockHash);\n }\n\n // Store transaction keys only if keepTxKeys is true\n // After processing, we don't need them anymore - wallet outputs are stored separately\n if (keepTxKeys) {\n const stmt = db.prepare(\n 'INSERT OR REPLACE INTO tx_keys (tx_hash, block_height, keys_data) VALUES (?, ?, ?)'\n );\n stmt.run([txHash, block.height, JSON.stringify(txKeys.keys)]);\n stmt.free();\n }\n\n count++;\n }\n\n return count;\n }\n\n /**\n * Process transaction keys to detect and store wallet outputs\n * @param txHash - Transaction hash\n * @param keys - Transaction keys data\n * @param blockHeight - Block height\n * @param _blockHash - Block hash (for reference, currently unused)\n */\n private async processTransactionKeys(\n txHash: string,\n keys: any,\n blockHeight: number,\n _blockHash: string\n ): Promise<void> {\n if (!this.keyManager) {\n return;\n }\n\n // Transaction keys structure: { outputs: [{ blindingKey, spendingKey, viewTag, outputHash, ... }, ...] }\n // The exact structure depends on electrumx implementation\n const outputs = keys[1]?.outputs || keys[1]?.vout || [];\n\n if (!Array.isArray(outputs)) {\n return;\n }\n\n for (let outputIndex = 0; outputIndex < outputs.length; outputIndex++) {\n const outputKeys = outputs[outputIndex];\n\n // Extract keys from output\n const blindingKey = outputKeys?.blindingKey || outputKeys?.blinding_key;\n const spendingKey = outputKeys?.spendingKey || outputKeys?.spending_key;\n const viewTag = outputKeys?.viewTag ?? outputKeys?.view_tag;\n const outputHash = outputKeys?.outputHash || outputKeys?.output_hash;\n\n if (!blindingKey || !spendingKey || viewTag === undefined || !outputHash) {\n console.warn(\n `Invalid output keys: blindingKey: ${blindingKey}, spendingKey: ${spendingKey}, viewTag: ${viewTag}, outputHash: ${outputHash}, blockHeight: ${blockHeight}`\n );\n continue;\n }\n\n // Convert keys to PublicKey format if needed (they might be hex strings or serialized)\n const PublicKey = blsctModule.PublicKey;\n let blindingKeyObj: any = PublicKey.deserialize(blindingKey);\n let spendingKeyObj: any = PublicKey.deserialize(spendingKey);\n\n // Check if output belongs to wallet\n const isMine = this.keyManager.isMineByKeys(blindingKeyObj, spendingKeyObj, viewTag);\n if (isMine) {\n // Fetch output data from backend\n try {\n const outputHex = await this.syncProvider.getTransactionOutput(outputHash);\n\n // Recover the amount from the range proof\n const RangeProof = blsctModule.RangeProof;\n const AmountRecoveryReq = blsctModule.AmountRecoveryReq;\n \n // Parse the output to get the range proof\n // The output format from Electrum/P2P is a CTxOut serialization\n // We need to extract the range proof and recover the amount\n let recoveredAmount = 0;\n let recoveredMemo: string | null = null;\n let tokenIdHex: string | null = null;\n\n try {\n // Calculate the nonce (shared secret) for amount recovery\n const nonce = this.keyManager.calculateNonce(blindingKeyObj);\n \n // Parse the range proof from the output data\n const rangeProofResult = this.extractRangeProofFromOutput(outputHex);\n \n if (rangeProofResult.rangeProofHex) {\n const rangeProof = RangeProof.deserialize(rangeProofResult.rangeProofHex);\n \n // Create recovery request\n const req = new AmountRecoveryReq(rangeProof, nonce);\n \n // Recover the amount using static method\n const results = RangeProof.recoverAmounts([req]);\n \n if (results.length > 0 && results[0].isSucc) {\n recoveredAmount = Number(results[0].amount);\n recoveredMemo = results[0].msg || null;\n }\n }\n \n tokenIdHex = rangeProofResult.tokenIdHex;\n } catch {\n // Amount recovery failed (likely navio-blsct library bug)\n // Output is still stored with amount 0 - will be recoverable when library is fixed\n }\n\n // Store output as spendable with recovered amount\n await this.storeWalletOutput(\n outputHash,\n txHash,\n outputIndex,\n blockHeight,\n outputHex,\n recoveredAmount,\n recoveredMemo,\n tokenIdHex,\n blindingKey,\n spendingKey,\n false, // not spent\n null, // spent_tx_hash\n null // spent_block_height\n );\n } catch (error) {\n // Output might not be available yet, skip for now\n console.warn(`Failed to fetch output ${outputHash} for tx ${txHash}:`, error);\n }\n }\n }\n }\n\n /**\n * Extract range proof from serialized CTxOut data\n * @param outputHex - Serialized output data (hex)\n * @returns Object containing rangeProofHex and tokenIdHex\n */\n private extractRangeProofFromOutput(outputHex: string): { rangeProofHex: string | null; tokenIdHex: string | null } {\n try {\n const data = Buffer.from(outputHex, 'hex');\n let offset = 0;\n\n // CTxOut serialization format:\n // - value (8 bytes) - either transparent or MAX_AMOUNT marker\n // - if MAX_AMOUNT: flags (8 bytes)\n // - if flags & TRANSPARENT_VALUE: transparent value (8 bytes)\n // - scriptPubKey (varint length + data)\n // - if flags & HAS_BLSCT_KEYS: rangeProof + blsctData\n // - if flags & HAS_TOKENID: tokenId (64 bytes)\n // - if flags & HAS_PREDICATE: predicate (varint length + data)\n\n const MAX_AMOUNT = 0x7fffffffffffffffn;\n const HAS_BLSCT_KEYS = 1n;\n const HAS_TOKENID = 2n;\n\n // Read value\n const value = data.readBigInt64LE(offset);\n offset += 8;\n\n let flags = 0n;\n if (value === MAX_AMOUNT) {\n flags = data.readBigUInt64LE(offset);\n offset += 8;\n \n // Skip transparent value if present\n if ((flags & 8n) !== 0n) {\n offset += 8;\n }\n }\n\n // Skip scriptPubKey\n const scriptLen = data[offset];\n offset += 1 + scriptLen;\n\n let rangeProofHex: string | null = null;\n let tokenIdHex: string | null = null;\n\n // Extract range proof if present\n if ((flags & HAS_BLSCT_KEYS) !== 0n) {\n // Range proof structure:\n // - Vs: vector of G1 points (varint count + 48 bytes each)\n // - If Vs.size > 0:\n // - Ls: vector of G1 points\n // - Rs: vector of G1 points \n // - A, A_wip, B: 3 G1 points (48 bytes each)\n // - r', s', delta', alpha_hat, tau_x: 5 scalars (32 bytes each)\n // - spendingKey, blindingKey, ephemeralKey: 3 G1 points (48 bytes each)\n // - viewTag: 2 bytes\n \n const rangeProofStart = offset;\n \n // Parse Vs\n const vsCount = data[offset];\n offset += 1;\n offset += vsCount * 48;\n \n if (vsCount > 0) {\n // Ls\n const lsCount = data[offset];\n offset += 1;\n offset += lsCount * 48;\n \n // Rs\n const rsCount = data[offset];\n offset += 1;\n offset += rsCount * 48;\n \n // A, A_wip, B (3 points)\n offset += 3 * 48;\n \n // 5 scalars: r', s', delta', alpha_hat, tau_x\n offset += 5 * 32;\n }\n \n const rangeProofEnd = offset;\n rangeProofHex = data.subarray(rangeProofStart, rangeProofEnd).toString('hex');\n \n // Skip BLSCT keys (spendingKey, blindingKey, ephemeralKey, viewTag)\n offset += 3 * 48 + 2;\n }\n\n // Extract tokenId if present\n if ((flags & HAS_TOKENID) !== 0n) {\n tokenIdHex = data.subarray(offset, offset + 64).toString('hex');\n }\n\n return { rangeProofHex, tokenIdHex };\n } catch (e) {\n return { rangeProofHex: null, tokenIdHex: null };\n }\n }\n\n /**\n * Store wallet output in database\n * @param outputHash - Output hash\n * @param txHash - Transaction hash\n * @param outputIndex - Output index\n * @param blockHeight - Block height\n * @param outputData - Serialized output data (hex)\n * @param amount - Recovered amount in satoshis\n * @param memo - Recovered memo/message\n * @param tokenId - Token ID (hex)\n * @param blindingKey - Blinding public key (hex)\n * @param spendingKey - Spending public key (hex)\n * @param isSpent - Whether output is spent\n * @param spentTxHash - Transaction hash that spent this output (if spent)\n * @param spentBlockHeight - Block height where output was spent (if spent)\n */\n private async storeWalletOutput(\n outputHash: string,\n txHash: string,\n outputIndex: number,\n blockHeight: number,\n outputData: string,\n amount: number,\n memo: string | null,\n tokenId: string | null,\n blindingKey: string,\n spendingKey: string,\n isSpent: boolean,\n spentTxHash: string | null,\n spentBlockHeight: number | null\n ): Promise<void> {\n const db = this.walletDB.getDatabase();\n\n const stmt = db.prepare(\n `INSERT OR REPLACE INTO wallet_outputs \n (output_hash, tx_hash, output_index, block_height, output_data, amount, memo, token_id, blinding_key, spending_key, is_spent, spent_tx_hash, spent_block_height, created_at)\n VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`\n );\n stmt.run([\n outputHash,\n txHash,\n outputIndex,\n blockHeight,\n outputData,\n amount,\n memo,\n tokenId,\n blindingKey,\n spendingKey,\n isSpent ? 1 : 0,\n spentTxHash,\n spentBlockHeight,\n Date.now(),\n ]);\n stmt.free();\n }\n\n /**\n * Extract block hash from block header\n * @param headerHex - Block header in hex\n * @returns Block hash (hex string)\n */\n private extractBlockHash(headerHex: string): string {\n // Block hash is double SHA256 of header, reversed for display\n const headerBytes = Buffer.from(headerHex, 'hex');\n const hash = sha256(sha256(headerBytes));\n return Buffer.from(hash).reverse().toString('hex');\n }\n\n /**\n * Get stored block hash from database\n * @param height - Block height\n * @returns Block hash or null if not found\n */\n private async getStoredBlockHash(height: number): Promise<string | null> {\n const db = this.walletDB.getDatabase();\n\n const stmt = db.prepare('SELECT hash FROM block_hashes WHERE height = ?');\n stmt.bind([height]);\n\n if (stmt.step()) {\n const row = stmt.getAsObject();\n stmt.free();\n return row.hash as string;\n }\n\n stmt.free();\n return null;\n }\n\n /**\n * Store block hash in database\n * Only stores if within retention window (if retention is enabled)\n * @param height - Block height\n * @param hash - Block hash\n * @param chainTip - Current chain tip (optional, to avoid repeated fetches)\n */\n private async storeBlockHash(height: number, hash: string, chainTip?: number): Promise<void> {\n const db = this.walletDB.getDatabase();\n\n // If retention is enabled (non-zero), only store recent block hashes\n if (this.blockHashRetention > 0) {\n // Get chain tip if not provided\n const currentChainTip = chainTip ?? (await this.syncProvider.getChainTipHeight());\n const retentionStart = Math.max(0, currentChainTip - this.blockHashRetention + 1);\n\n // Only store if within retention window\n if (height < retentionStart) {\n return; // Skip storing old block hashes\n }\n\n // Periodically clean up old block hashes outside retention window\n // Only do this occasionally to avoid overhead (every 100 blocks)\n if (height % 100 === 0) {\n const cleanupStmt = db.prepare('DELETE FROM block_hashes WHERE height < ?');\n cleanupStmt.run([retentionStart]);\n cleanupStmt.free();\n }\n }\n\n const stmt = db.prepare('INSERT OR REPLACE INTO block_hashes (height, hash) VALUES (?, ?)');\n stmt.run([height, hash]);\n stmt.free();\n }\n\n /**\n * Load sync state from database\n * @returns Sync state or null if not found\n */\n private async loadSyncState(): Promise<SyncState | null> {\n try {\n const db = this.walletDB.getDatabase();\n\n const result = db.exec('SELECT * FROM sync_state LIMIT 1');\n if (result.length > 0 && result[0].values.length > 0) {\n const row = result[0].values[0];\n return {\n lastSyncedHeight: row[1] as number,\n lastSyncedHash: row[2] as string,\n totalTxKeysSynced: row[3] as number,\n lastSyncTime: row[4] as number,\n chainTipAtLastSync: row[5] as number,\n };\n }\n\n return null;\n } catch {\n return null;\n }\n }\n\n /**\n * Update sync state in database\n * @param state - Sync state to update\n */\n private async updateSyncState(state: Partial<SyncState>): Promise<void> {\n const db = this.walletDB.getDatabase();\n\n const currentState = this.syncState || {\n lastSyncedHeight: -1,\n lastSyncedHash: '',\n totalTxKeysSynced: 0,\n lastSyncTime: 0,\n chainTipAtLastSync: 0,\n };\n\n const newState: SyncState = {\n ...currentState,\n ...state,\n };\n\n // Use id = 0 for the single sync state row\n const stmt = db.prepare(\n `INSERT OR REPLACE INTO sync_state \n (id, last_synced_height, last_synced_hash, total_tx_keys_synced, last_sync_time, chain_tip_at_last_sync)\n VALUES (0, ?, ?, ?, ?, ?)`\n );\n stmt.run([\n newState.lastSyncedHeight,\n newState.lastSyncedHash,\n newState.totalTxKeysSynced,\n newState.lastSyncTime,\n newState.chainTipAtLastSync,\n ]);\n stmt.free();\n\n this.syncState = newState;\n }\n\n /**\n * Get transaction keys for a specific transaction\n * @param txHash - Transaction hash\n * @returns Transaction keys or null if not found\n */\n async getTransactionKeys(txHash: string): Promise<any | null> {\n try {\n const db = this.walletDB.getDatabase();\n\n const stmt = db.prepare('SELECT keys_data FROM tx_keys WHERE tx_hash = ?');\n stmt.bind([txHash]);\n\n if (stmt.step()) {\n const row = stmt.getAsObject();\n stmt.free();\n return JSON.parse(row.keys_data as string);\n }\n\n stmt.free();\n return null;\n } catch {\n return null;\n }\n }\n\n /**\n * Get transaction keys for a block\n * @param height - Block height\n * @returns Array of transaction keys\n */\n async getBlockTransactionKeys(height: number): Promise<TransactionKeys[]> {\n try {\n const db = this.walletDB.getDatabase();\n\n const result = db.exec('SELECT tx_hash, keys_data FROM tx_keys WHERE block_height = ?', [\n height,\n ]);\n if (result.length > 0) {\n return result[0].values.map((row: any[]) => ({\n txHash: row[0] as string,\n keys: JSON.parse(row[1] as string),\n }));\n }\n\n return [];\n } catch {\n return [];\n }\n }\n\n /**\n * Reset sync state (for testing or full resync)\n */\n async resetSyncState(): Promise<void> {\n const db = this.walletDB.getDatabase();\n\n // Delete all sync state\n db.run('DELETE FROM sync_state');\n db.run('DELETE FROM tx_keys');\n db.run('DELETE FROM block_hashes');\n\n this.syncState = null;\n }\n}\n","/**\n * Sync Provider Interface\n *\n * Abstract interface for blockchain synchronization providers.\n * Supports multiple backends: Electrum, P2P, or custom implementations.\n */\n\nimport type { BlockTransactionKeys, TransactionKeys } from './electrum';\nimport { sha256 } from '@noble/hashes/sha256';\n\n/**\n * Block header information (for sync provider)\n */\nexport interface SyncBlockHeader {\n /** Block height */\n height: number;\n /** Block hash (hex string, little-endian display format) */\n hash: string;\n /** Previous block hash */\n prevHash: string;\n /** Merkle root */\n merkleRoot: string;\n /** Block timestamp */\n timestamp: number;\n /** Block version */\n version: number;\n /** Difficulty target (bits) */\n bits: number;\n /** Nonce */\n nonce: number;\n /** Raw header hex (80 bytes) */\n rawHex?: string;\n}\n\n/**\n * Block headers result (for batch fetches)\n */\nexport interface BlockHeadersResult {\n /** Number of headers returned */\n count: number;\n /** Concatenated headers hex */\n hex: string;\n /** Maximum headers the server can return */\n max?: number;\n}\n\n/**\n * Chain tip information\n */\nexport interface ChainTip {\n /** Current chain height */\n height: number;\n /** Block hash at tip */\n hash: string;\n}\n\n/**\n * Sync provider options\n */\nexport interface SyncProviderOptions {\n /** Connection timeout in milliseconds */\n timeout?: number;\n /** Enable debug logging */\n debug?: boolean;\n}\n\n/**\n * Abstract sync provider interface\n *\n * Implementations must provide methods for:\n * - Connecting/disconnecting\n * - Fetching block headers\n * - Fetching transaction keys for wallet scanning\n * - Fetching transaction outputs by hash\n * - Broadcasting transactions\n * \n * @category Sync\n */\nexport interface SyncProvider {\n /**\n * Provider type identifier\n */\n readonly type: 'electrum' | 'p2p' | 'custom';\n\n /**\n * Connect to the provider\n */\n connect(): Promise<void>;\n\n /**\n * Disconnect from the provider\n */\n disconnect(): void;\n\n /**\n * Check if connected\n */\n isConnected(): boolean;\n\n /**\n * Get the current chain tip height\n */\n getChainTipHeight(): Promise<number>;\n\n /**\n * Get the current chain tip\n */\n getChainTip(): Promise<ChainTip>;\n\n /**\n * Get a single block header\n * @param height - Block height\n * @returns Block header hex (80 bytes)\n */\n getBlockHeader(height: number): Promise<string>;\n\n /**\n * Get multiple block headers\n * @param startHeight - Starting block height\n * @param count - Number of headers to fetch\n * @returns Block headers result\n */\n getBlockHeaders(startHeight: number, count: number): Promise<BlockHeadersResult>;\n\n /**\n * Get transaction keys for a range of blocks\n * Used for wallet scanning - extracts keys needed for output detection\n * @param startHeight - Starting block height\n * @returns Block transaction keys with next height for pagination\n */\n getBlockTransactionKeysRange(startHeight: number): Promise<{\n blocks: BlockTransactionKeys[];\n nextHeight: number;\n }>;\n\n /**\n * Get transaction keys for a single block\n * @param height - Block height\n * @returns Array of transaction keys\n */\n getBlockTransactionKeys(height: number): Promise<TransactionKeys[]>;\n\n /**\n * Get serialized transaction output by output hash\n * @param outputHash - Output hash (hex string)\n * @returns Serialized output (hex string)\n */\n getTransactionOutput(outputHash: string): Promise<string>;\n\n /**\n * Broadcast a transaction\n * @param rawTx - Raw transaction (hex string)\n * @returns Transaction hash if successful\n */\n broadcastTransaction(rawTx: string): Promise<string>;\n\n /**\n * Get raw transaction\n * @param txHash - Transaction hash (hex string)\n * @param verbose - Return verbose data\n * @returns Raw transaction hex or verbose object\n */\n getRawTransaction(txHash: string, verbose?: boolean): Promise<string | unknown>;\n}\n\n/**\n * Base class for sync providers with common utility methods.\n * \n * @category Sync\n */\nexport abstract class BaseSyncProvider implements SyncProvider {\n abstract readonly type: 'electrum' | 'p2p' | 'custom';\n protected debug: boolean;\n protected timeout: number;\n\n constructor(options: SyncProviderOptions = {}) {\n this.debug = options.debug ?? false;\n this.timeout = options.timeout ?? 30000;\n }\n\n protected log(...args: unknown[]): void {\n if (this.debug) {\n console.log(`[${this.type}]`, ...args);\n }\n }\n\n /**\n * Extract block hash from raw block header (80 bytes hex)\n * Block hash is double SHA256 of header, reversed for display\n */\n protected extractBlockHash(headerHex: string): string {\n const headerBytes = Buffer.from(headerHex, 'hex');\n const hash = sha256(sha256(headerBytes));\n return Buffer.from(hash).reverse().toString('hex');\n }\n\n /**\n * Parse a raw block header into structured format\n */\n protected parseBlockHeader(headerHex: string, height: number): SyncBlockHeader {\n const header = Buffer.from(headerHex, 'hex');\n if (header.length !== 80) {\n throw new Error(`Invalid header length: ${header.length}, expected 80`);\n }\n\n return {\n height,\n hash: this.extractBlockHash(headerHex),\n version: header.readInt32LE(0),\n prevHash: header.subarray(4, 36).reverse().toString('hex'),\n merkleRoot: header.subarray(36, 68).reverse().toString('hex'),\n timestamp: header.readUInt32LE(68),\n bits: header.readUInt32LE(72),\n nonce: header.readUInt32LE(76),\n rawHex: headerHex,\n };\n }\n\n abstract connect(): Promise<void>;\n abstract disconnect(): void;\n abstract isConnected(): boolean;\n abstract getChainTipHeight(): Promise<number>;\n abstract getChainTip(): Promise<ChainTip>;\n abstract getBlockHeader(height: number): Promise<string>;\n abstract getBlockHeaders(startHeight: number, count: number): Promise<BlockHeadersResult>;\n abstract getBlockTransactionKeysRange(startHeight: number): Promise<{\n blocks: BlockTransactionKeys[];\n nextHeight: number;\n }>;\n abstract getBlockTransactionKeys(height: number): Promise<TransactionKeys[]>;\n abstract getTransactionOutput(outputHash: string): Promise<string>;\n abstract broadcastTransaction(rawTx: string): Promise<string>;\n abstract getRawTransaction(txHash: string, verbose?: boolean): Promise<string | unknown>;\n}\n\n","/**\n * P2P Protocol Implementation for Navio\n *\n * Implements the Navio P2P protocol for direct node communication.\n * Supports connection handshake, message framing, and core protocol messages.\n */\n\nimport { sha256 } from '@noble/hashes/sha256';\nimport * as net from 'net';\n\n/**\n * Network magic bytes for different chains\n */\nexport const NetworkMagic = {\n MAINNET: Buffer.from([0xdb, 0xd2, 0xb1, 0xac]),\n TESTNET: Buffer.from([0x1c, 0x03, 0xbb, 0x83]),\n REGTEST: Buffer.from([0xfd, 0xbf, 0x9f, 0xfb]),\n} as const;\n\n/**\n * Default ports for different chains\n */\nexport const DefaultPorts = {\n MAINNET: 44440,\n TESTNET: 33670,\n REGTEST: 18444,\n} as const;\n\n/**\n * P2P message types\n */\nexport const MessageType = {\n VERSION: 'version',\n VERACK: 'verack',\n PING: 'ping',\n PONG: 'pong',\n GETADDR: 'getaddr',\n ADDR: 'addr',\n INV: 'inv',\n GETDATA: 'getdata',\n NOTFOUND: 'notfound',\n GETBLOCKS: 'getblocks',\n GETHEADERS: 'getheaders',\n HEADERS: 'headers',\n BLOCK: 'block',\n TX: 'tx',\n GETOUTPUTDATA: 'getoutputdata',\n MEMPOOL: 'mempool',\n REJECT: 'reject',\n SENDHEADERS: 'sendheaders',\n SENDCMPCT: 'sendcmpct',\n CMPCTBLOCK: 'cmpctblock',\n GETBLOCKTXN: 'getblocktxn',\n BLOCKTXN: 'blocktxn',\n} as const;\n\n/**\n * Service flags\n */\nexport const ServiceFlags = {\n NODE_NONE: 0n,\n NODE_NETWORK: 1n << 0n,\n NODE_BLOOM: 1n << 2n,\n NODE_WITNESS: 1n << 3n,\n NODE_COMPACT_FILTERS: 1n << 6n,\n NODE_NETWORK_LIMITED: 1n << 10n,\n NODE_P2P_V2: 1n << 11n,\n} as const;\n\n/**\n * Inventory types for getdata/inv messages\n */\nexport const InvType = {\n ERROR: 0,\n MSG_TX: 1,\n MSG_BLOCK: 2,\n MSG_FILTERED_BLOCK: 3,\n MSG_CMPCT_BLOCK: 4,\n MSG_WTX: 5,\n MSG_DTX: 6,\n MSG_DWTX: 7,\n MSG_OUTPUT_HASH: 8,\n MSG_WITNESS_FLAG: 1 << 30,\n MSG_WITNESS_BLOCK: 2 | (1 << 30),\n MSG_WITNESS_TX: 1 | (1 << 30),\n} as const;\n\n/**\n * Protocol version\n */\nexport const PROTOCOL_VERSION = 70016;\n\n/**\n * P2P connection options\n */\nexport interface P2PConnectionOptions {\n /** Host to connect to */\n host: string;\n /** Port (default based on network) */\n port?: number;\n /** Network type */\n network?: 'mainnet' | 'testnet' | 'regtest';\n /** Connection timeout in ms */\n timeout?: number;\n /** User agent string */\n userAgent?: string;\n /** Enable debug logging */\n debug?: boolean;\n /** Services to advertise */\n services?: bigint;\n}\n\n/**\n * Message header structure\n */\nexport interface MessageHeader {\n magic: Buffer;\n command: string;\n length: number;\n checksum: Buffer;\n}\n\n/**\n * Parsed P2P message\n */\nexport interface P2PMessage {\n command: string;\n payload: Buffer;\n}\n\n/**\n * Version message payload\n */\nexport interface VersionPayload {\n version: number;\n services: bigint;\n timestamp: bigint;\n addrRecv: {\n services: bigint;\n ip: Buffer;\n port: number;\n };\n addrFrom: {\n services: bigint;\n ip: Buffer;\n port: number;\n };\n nonce: bigint;\n userAgent: string;\n startHeight: number;\n relay: boolean;\n}\n\n/**\n * Inventory vector\n */\nexport interface InvVector {\n type: number;\n hash: Buffer;\n}\n\n/**\n * Block locator for getheaders/getblocks\n */\nexport interface BlockLocator {\n version: number;\n hashes: Buffer[];\n hashStop: Buffer;\n}\n\n/**\n * P2P Protocol Client\n *\n * Low-level P2P protocol implementation for connecting to Navio nodes.\n * \n * @category Protocol\n */\nexport class P2PClient {\n private socket: net.Socket | null = null;\n private options: Required<P2PConnectionOptions>;\n private magic: Buffer;\n private connected = false;\n private handshakeComplete = false;\n private receiveBuffer = Buffer.alloc(0);\n private pendingMessages: Map<\n string,\n { resolve: (msg: P2PMessage) => void; reject: (err: Error) => void; timer: NodeJS.Timeout }\n > = new Map();\n private messageHandlers: Map<string, ((msg: P2PMessage) => void)[]> = new Map();\n private messageQueue: Map<string, P2PMessage[]> = new Map(); // Queue for early messages\n private nonce: bigint;\n private peerVersion: number = 0;\n private _peerServices: bigint = 0n;\n private peerStartHeight: number = 0;\n\n constructor(options: P2PConnectionOptions) {\n const network = options.network ?? 'testnet';\n this.options = {\n host: options.host,\n port: options.port ?? DefaultPorts[network.toUpperCase() as keyof typeof DefaultPorts],\n network,\n timeout: options.timeout ?? 30000,\n userAgent: options.userAgent ?? '/navio-sdk:0.1.0/',\n debug: options.debug ?? false,\n services: options.services ?? ServiceFlags.NODE_NETWORK | ServiceFlags.NODE_WITNESS,\n };\n this.magic = NetworkMagic[network.toUpperCase() as keyof typeof NetworkMagic];\n this.nonce = BigInt(Math.floor(Math.random() * Number.MAX_SAFE_INTEGER));\n }\n\n private log(...args: unknown[]): void {\n if (this.options.debug) {\n console.log('[P2P]', ...args);\n }\n }\n\n /**\n * Connect to the peer and complete handshake\n */\n async connect(): Promise<void> {\n if (this.connected) {\n return;\n }\n\n return new Promise((resolve, reject) => {\n this.socket = new net.Socket();\n\n const connectionTimeout = setTimeout(() => {\n this.socket?.destroy();\n reject(new Error('Connection timeout'));\n }, this.options.timeout);\n\n this.socket.on('connect', async () => {\n this.log(`Connected to ${this.options.host}:${this.options.port}`);\n this.connected = true;\n\n try {\n // Send version message\n await this.sendVersion();\n\n // Wait for version and verack\n await this.waitForHandshake();\n\n clearTimeout(connectionTimeout);\n this.handshakeComplete = true;\n this.log('Handshake complete');\n resolve();\n } catch (error) {\n clearTimeout(connectionTimeout);\n this.disconnect();\n reject(error);\n }\n });\n\n this.socket.on('data', (data: Buffer) => {\n this.handleData(data);\n });\n\n this.socket.on('error', (error: Error) => {\n this.log('Socket error:', error.message);\n clearTimeout(connectionTimeout);\n this.connected = false;\n reject(error);\n });\n\n this.socket.on('close', (hadError: boolean) => {\n this.log(`Connection closed (hadError=${hadError}, receiveBuffer=${this.receiveBuffer.length} bytes)`);\n this.connected = false;\n this.handshakeComplete = false;\n // Reject any pending requests\n for (const [, pending] of this.pendingMessages) {\n clearTimeout(pending.timer);\n pending.reject(new Error('Connection closed'));\n }\n this.pendingMessages.clear();\n });\n\n this.socket.connect(this.options.port, this.options.host);\n });\n }\n\n /**\n * Disconnect from the peer\n */\n disconnect(): void {\n if (this.socket) {\n this.socket.destroy();\n this.socket = null;\n }\n this.connected = false;\n this.handshakeComplete = false;\n }\n\n /**\n * Check if connected and handshake complete\n */\n isConnected(): boolean {\n return this.connected && this.handshakeComplete;\n }\n\n /**\n * Get peer's advertised start height\n */\n getPeerStartHeight(): number {\n return this.peerStartHeight;\n }\n\n /**\n * Get peer's protocol version\n */\n getPeerVersion(): number {\n return this.peerVersion;\n }\n\n /**\n * Get peer's advertised services\n */\n getPeerServices(): bigint {\n return this._peerServices;\n }\n\n /**\n * Handle incoming data\n */\n private handleData(data: Buffer): void {\n this.receiveBuffer = Buffer.concat([this.receiveBuffer, data]);\n\n // Try to parse complete messages\n while (this.receiveBuffer.length >= 24) {\n // Check magic bytes\n if (!this.receiveBuffer.subarray(0, 4).equals(this.magic)) {\n // Invalid magic, try to find valid header\n const magicIndex = this.receiveBuffer.indexOf(this.magic, 1);\n if (magicIndex === -1) {\n this.receiveBuffer = Buffer.alloc(0);\n return;\n }\n this.receiveBuffer = this.receiveBuffer.subarray(magicIndex);\n continue;\n }\n\n // Parse header\n const header = this.parseHeader(this.receiveBuffer);\n const totalLength = 24 + header.length;\n\n // Check if we have the full message\n if (this.receiveBuffer.length < totalLength) {\n return; // Wait for more data\n }\n\n // Extract payload\n const payload = this.receiveBuffer.subarray(24, totalLength);\n\n // Verify checksum\n const expectedChecksum = this.calculateChecksum(payload);\n if (!header.checksum.equals(expectedChecksum)) {\n this.log('Checksum mismatch for', header.command);\n this.receiveBuffer = this.receiveBuffer.subarray(totalLength);\n continue;\n }\n\n // Remove processed message from buffer\n this.receiveBuffer = this.receiveBuffer.subarray(totalLength);\n\n // Handle message\n const message: P2PMessage = { command: header.command, payload };\n this.log('Received:', header.command, `(${header.length} bytes)`);\n this.dispatchMessage(message);\n }\n }\n\n /**\n * Parse message header\n */\n private parseHeader(buffer: Buffer): MessageHeader {\n return {\n magic: buffer.subarray(0, 4),\n command: buffer\n .subarray(4, 16)\n .toString('ascii')\n .replace(/\\0+$/, ''),\n length: buffer.readUInt32LE(16),\n checksum: buffer.subarray(20, 24),\n };\n }\n\n /**\n * Calculate message checksum (first 4 bytes of double SHA256)\n */\n private calculateChecksum(payload: Buffer): Buffer {\n const hash = sha256(sha256(payload));\n return Buffer.from(hash.subarray(0, 4));\n }\n\n /**\n * Dispatch message to handlers\n */\n private dispatchMessage(message: P2PMessage): void {\n // Check for pending requests\n const pending = this.pendingMessages.get(message.command);\n if (pending) {\n clearTimeout(pending.timer);\n this.pendingMessages.delete(message.command);\n pending.resolve(message);\n return;\n }\n\n // Call registered handlers\n const handlers = this.messageHandlers.get(message.command);\n if (handlers) {\n for (const handler of handlers) {\n handler(message);\n }\n }\n\n // Handle specific protocol messages\n switch (message.command) {\n case MessageType.PING:\n this.handlePing(message.payload);\n break;\n default:\n // Queue message for later if no handler is waiting\n // This handles race conditions during handshake\n const queue = this.messageQueue.get(message.command) ?? [];\n queue.push(message);\n this.messageQueue.set(message.command, queue);\n break;\n }\n }\n\n /**\n * Register a message handler\n */\n onMessage(command: string, handler: (msg: P2PMessage) => void): void {\n const handlers = this.messageHandlers.get(command) ?? [];\n handlers.push(handler);\n this.messageHandlers.set(command, handlers);\n }\n\n /**\n * Send a raw message\n */\n private sendMessage(command: string, payload: Buffer = Buffer.alloc(0)): void {\n if (!this.socket) {\n throw new Error('Not connected');\n }\n\n // Build header\n const header = Buffer.alloc(24);\n this.magic.copy(header, 0);\n\n // Command (12 bytes, null-padded)\n const cmdBuffer = Buffer.alloc(12);\n Buffer.from(command, 'ascii').copy(cmdBuffer);\n cmdBuffer.copy(header, 4);\n\n\n // Payload length\n header.writeUInt32LE(payload.length, 16);\n\n // Checksum\n const checksum = this.calculateChecksum(payload);\n checksum.copy(header, 20);\n\n // Send\n const message = Buffer.concat([header, payload]);\n this.socket.write(message);\n this.log('Sent:', command, `(${payload.length} bytes)`);\n }\n\n /**\n * Send a message and wait for a specific response\n */\n async sendAndWait(\n command: string,\n payload: Buffer,\n responseCommand: string,\n timeout?: number\n ): Promise<P2PMessage> {\n return new Promise((resolve, reject) => {\n const timer = setTimeout(() => {\n this.pendingMessages.delete(responseCommand);\n reject(new Error(`Timeout waiting for ${responseCommand}`));\n }, timeout ?? this.options.timeout);\n\n this.pendingMessages.set(responseCommand, { resolve, reject, timer });\n this.sendMessage(command, payload);\n });\n }\n\n /**\n * Wait for a specific message\n */\n async waitForMessage(command: string, timeout?: number): Promise<P2PMessage> {\n // First check if message is already in the queue\n const queue = this.messageQueue.get(command);\n if (queue && queue.length > 0) {\n const message = queue.shift()!;\n if (queue.length === 0) {\n this.messageQueue.delete(command);\n }\n return message;\n }\n\n // Otherwise wait for it\n return new Promise((resolve, reject) => {\n const timer = setTimeout(() => {\n this.pendingMessages.delete(command);\n reject(new Error(`Timeout waiting for ${command}`));\n }, timeout ?? this.options.timeout);\n\n this.pendingMessages.set(command, { resolve, reject, timer });\n });\n }\n\n // ============================================================================\n // Protocol Messages\n // ============================================================================\n\n /**\n * Send version message\n */\n private async sendVersion(): Promise<void> {\n const payload = this.buildVersionPayload();\n this.sendMessage(MessageType.VERSION, payload);\n }\n\n /**\n * Build version message payload\n */\n private buildVersionPayload(): Buffer {\n const now = BigInt(Math.floor(Date.now() / 1000));\n\n // Calculate payload size\n const userAgentBytes = Buffer.from(this.options.userAgent, 'utf8');\n const userAgentVarInt = this.encodeVarInt(userAgentBytes.length);\n\n\n const payloadSize =\n 4 + // version\n 8 + // services\n 8 + // timestamp\n 26 + // addr_recv\n 26 + // addr_from\n 8 + // nonce\n userAgentVarInt.length +\n userAgentBytes.length +\n 4 + // start_height\n 1; // relay\n\n const payload = Buffer.alloc(payloadSize);\n let offset = 0;\n\n // Version\n payload.writeInt32LE(PROTOCOL_VERSION, offset);\n offset += 4;\n\n // Services\n payload.writeBigUInt64LE(this.options.services, offset);\n offset += 8;\n\n // Timestamp\n payload.writeBigInt64LE(now, offset);\n offset += 8;\n\n // Addr recv (services + IPv6 + port)\n payload.writeBigUInt64LE(ServiceFlags.NODE_NETWORK, offset);\n offset += 8;\n // IPv4-mapped IPv6 address for localhost\n Buffer.from('00000000000000000000ffff7f000001', 'hex').copy(payload, offset);\n offset += 16;\n payload.writeUInt16BE(this.options.port, offset);\n offset += 2;\n\n // Addr from\n payload.writeBigUInt64LE(this.options.services, offset);\n offset += 8;\n Buffer.from('00000000000000000000ffff7f000001', 'hex').copy(payload, offset);\n offset += 16;\n payload.writeUInt16BE(0, offset);\n offset += 2;\n\n // Nonce\n payload.writeBigUInt64LE(this.nonce, offset);\n offset += 8;\n\n // User agent\n userAgentVarInt.copy(payload, offset);\n offset += userAgentVarInt.length;\n userAgentBytes.copy(payload, offset);\n offset += userAgentBytes.length;\n\n // Start height (0 for now, we don't have any blocks)\n payload.writeInt32LE(0, offset);\n offset += 4;\n\n // Relay\n payload.writeUInt8(1, offset);\n\n return payload;\n }\n\n /**\n * Wait for handshake completion\n */\n private async waitForHandshake(): Promise<void> {\n // Create promises for both messages we need before any data arrives\n const versionPromise = this.waitForMessage(MessageType.VERSION, 10000);\n const verackPromise = this.waitForMessage(MessageType.VERACK, 10000);\n\n // Wait for version\n const versionMsg = await versionPromise;\n this.parseVersionMessage(versionMsg.payload);\n\n // Send verack\n this.sendMessage(MessageType.VERACK);\n\n // Wait for verack (may have already arrived)\n await verackPromise;\n }\n\n /**\n * Parse version message\n */\n private parseVersionMessage(payload: Buffer): void {\n let offset = 0;\n\n this.peerVersion = payload.readInt32LE(offset);\n offset += 4;\n\n this._peerServices = payload.readBigUInt64LE(offset);\n offset += 8;\n\n // Skip timestamp (8), addr_recv (26), addr_from (26), nonce (8)\n offset += 8 + 26 + 26 + 8;\n\n // Parse user agent\n const { value: userAgentLen, bytesRead } = this.decodeVarInt(payload.subarray(offset));\n offset += bytesRead;\n const userAgent = payload.subarray(offset, offset + Number(userAgentLen)).toString('utf8');\n offset += Number(userAgentLen);\n\n this.peerStartHeight = payload.readInt32LE(offset);\n\n this.log(`Peer version: ${this.peerVersion}, user agent: ${userAgent}, height: ${this.peerStartHeight}`);\n }\n\n /**\n * Handle ping message\n */\n private handlePing(payload: Buffer): void {\n // Respond with pong using the same nonce\n this.sendMessage(MessageType.PONG, payload);\n }\n\n /**\n * Send getheaders message\n */\n async getHeaders(locatorHashes: Buffer[], hashStop?: Buffer): Promise<Buffer[]> {\n const payload = this.buildBlockLocatorPayload(locatorHashes, hashStop);\n const response = await this.sendAndWait(MessageType.GETHEADERS, payload, MessageType.HEADERS);\n return this.parseHeadersMessage(response.payload);\n }\n\n /**\n * Build block locator payload for getheaders/getblocks\n */\n private buildBlockLocatorPayload(hashes: Buffer[], hashStop?: Buffer): Buffer {\n const hashCount = this.encodeVarInt(hashes.length);\n const payloadSize = 4 + hashCount.length + hashes.length * 32 + 32;\n const payload = Buffer.alloc(payloadSize);\n let offset = 0;\n\n // Version\n payload.writeUInt32LE(PROTOCOL_VERSION, offset);\n offset += 4;\n\n // Hash count\n hashCount.copy(payload, offset);\n offset += hashCount.length;\n\n // Hashes\n for (const hash of hashes) {\n hash.copy(payload, offset);\n offset += 32;\n }\n\n // Hash stop\n if (hashStop) {\n hashStop.copy(payload, offset);\n }\n // else: already zeroed\n\n return payload;\n }\n\n /**\n * Parse headers message\n *\n * Note: Navio's headers message format differs from Bitcoin's.\n * Bitcoin includes a varint tx_count (always 0) after each 80-byte header.\n * Navio sends just the raw 80-byte headers with no tx_count.\n */\n private parseHeadersMessage(payload: Buffer): Buffer[] {\n let offset = 0;\n const { value: count, bytesRead } = this.decodeVarInt(payload);\n offset += bytesRead;\n\n this.log(`Parsing ${count} headers from ${payload.length} bytes`);\n\n const headers: Buffer[] = [];\n for (let i = 0; i < Number(count); i++) {\n // Check bounds before reading header\n if (offset + 80 > payload.length) {\n this.log(`Headers parse: reached end of payload at header ${i}`);\n break;\n }\n\n // Each header is exactly 80 bytes (no tx count in Navio's format)\n const header = payload.subarray(offset, offset + 80);\n headers.push(Buffer.from(header));\n offset += 80;\n }\n\n this.log(`Parsed ${headers.length} headers`);\n return headers;\n }\n\n /**\n * Send getdata message\n */\n async getData(inventory: InvVector[]): Promise<void> {\n const payload = this.buildInvPayload(inventory);\n this.sendMessage(MessageType.GETDATA, payload);\n }\n\n /**\n * Build inventory payload for inv/getdata\n */\n private buildInvPayload(inventory: InvVector[]): Buffer {\n const countVarInt = this.encodeVarInt(inventory.length);\n const payloadSize = countVarInt.length + inventory.length * 36;\n const payload = Buffer.alloc(payloadSize);\n let offset = 0;\n\n countVarInt.copy(payload, offset);\n offset += countVarInt.length;\n\n for (const inv of inventory) {\n payload.writeUInt32LE(inv.type, offset);\n offset += 4;\n inv.hash.copy(payload, offset);\n offset += 32;\n }\n\n return payload;\n }\n\n /**\n * Request a block by hash\n */\n async getBlock(blockHash: Buffer): Promise<P2PMessage> {\n const inventory: InvVector[] = [{ type: InvType.MSG_WITNESS_BLOCK, hash: blockHash }];\n const getDataPayload = this.buildInvPayload(inventory);\n\n // Send getdata and wait for block\n return this.sendAndWait(MessageType.GETDATA, getDataPayload, MessageType.BLOCK);\n }\n\n /**\n * Request transaction outputs by output hash (Navio-specific)\n */\n async getOutputData(outputHashes: Buffer[]): Promise<P2PMessage> {\n const countVarInt = this.encodeVarInt(outputHashes.length);\n const payloadSize = countVarInt.length + outputHashes.length * 32;\n const payload = Buffer.alloc(payloadSize);\n let offset = 0;\n\n countVarInt.copy(payload, offset);\n offset += countVarInt.length;\n\n for (const hash of outputHashes) {\n hash.copy(payload, offset);\n offset += 32;\n }\n\n return this.sendAndWait(MessageType.GETOUTPUTDATA, payload, MessageType.TX);\n }\n\n /**\n * Send sendheaders message to prefer headers announcements\n */\n sendSendHeaders(): void {\n this.sendMessage(MessageType.SENDHEADERS);\n }\n\n // ============================================================================\n // Utility Methods\n // ============================================================================\n\n /**\n * Encode a variable-length integer\n */\n encodeVarInt(value: number | bigint): Buffer {\n const n = typeof value === 'bigint' ? value : BigInt(value);\n\n if (n < 0xfd) {\n const buf = Buffer.alloc(1);\n buf.writeUInt8(Number(n));\n return buf;\n } else if (n <= 0xffff) {\n const buf = Buffer.alloc(3);\n buf.writeUInt8(0xfd);\n buf.writeUInt16LE(Number(n), 1);\n return buf;\n } else if (n <= 0xffffffff) {\n const buf = Buffer.alloc(5);\n buf.writeUInt8(0xfe);\n buf.writeUInt32LE(Number(n), 1);\n return buf;\n } else {\n const buf = Buffer.alloc(9);\n buf.writeUInt8(0xff);\n buf.writeBigUInt64LE(n, 1);\n return buf;\n }\n }\n\n /**\n * Decode a variable-length integer\n */\n decodeVarInt(buffer: Buffer): { value: bigint; bytesRead: number } {\n const first = buffer.readUInt8(0);\n\n if (first < 0xfd) {\n return { value: BigInt(first), bytesRead: 1 };\n } else if (first === 0xfd) {\n return { value: BigInt(buffer.readUInt16LE(1)), bytesRead: 3 };\n } else if (first === 0xfe) {\n return { value: BigInt(buffer.readUInt32LE(1)), bytesRead: 5 };\n } else {\n return { value: buffer.readBigUInt64LE(1), bytesRead: 9 };\n }\n }\n\n /**\n * Reverse a hash for display (Bitcoin uses little-endian internally, big-endian for display)\n */\n static reverseHash(hash: Buffer): Buffer {\n return Buffer.from(hash).reverse();\n }\n\n /**\n * Convert display hash to internal format\n */\n static hashFromDisplay(hexHash: string): Buffer {\n return Buffer.from(hexHash, 'hex').reverse();\n }\n\n /**\n * Convert internal hash to display format\n */\n static hashToDisplay(hash: Buffer): string {\n return Buffer.from(hash).reverse().toString('hex');\n }\n}\n\n","/**\n * P2P Sync Provider\n *\n * Implements the SyncProvider interface using direct P2P connections\n * to Navio full nodes. Parses blocks using navio-blsct for transaction\n * key extraction.\n */\n\nimport { sha256 } from '@noble/hashes/sha256';\nimport { BaseSyncProvider, BlockHeadersResult, ChainTip, SyncProviderOptions } from './sync-provider';\nimport { P2PClient, P2PMessage, InvType, MessageType } from './p2p-protocol';\nimport type { BlockTransactionKeys, TransactionKeys } from './electrum';\n\n// Import navio-blsct for transaction parsing (will be used for full implementation)\n// const blsctModule = require('navio-blsct');\n\n/**\n * P2P sync provider options\n */\nexport interface P2PSyncOptions extends SyncProviderOptions {\n /** Host to connect to */\n host: string;\n /** Port (default based on network) */\n port?: number;\n /** Network type */\n network?: 'mainnet' | 'testnet' | 'regtest';\n /** User agent string */\n userAgent?: string;\n /** Maximum blocks to fetch per request */\n maxBlocksPerRequest?: number;\n /** Maximum headers to fetch per request */\n maxHeadersPerRequest?: number;\n}\n\n/**\n * Parsed transaction output keys\n */\ninterface ParsedOutputKeys {\n /** Output hash */\n outputHash: string;\n /** Blinding key (G1 point, 48 bytes hex) */\n blindingKey: string;\n /** Spending key (G1 point, 48 bytes hex) */\n spendingKey: string;\n /** Ephemeral key (G1 point, 48 bytes hex) */\n ephemeralKey: string;\n /** View tag (16-bit) */\n viewTag: number;\n /** Has range proof */\n hasRangeProof: boolean;\n}\n\n/**\n * Block header cache entry\n */\ninterface CachedHeader {\n height: number;\n hash: string;\n rawHex: string;\n prevHash: string;\n}\n\n/**\n * P2P Sync Provider\n *\n * Connects directly to a Navio full node via P2P protocol.\n * Fetches blocks and extracts transaction keys for wallet scanning.\n * \n * @category Sync\n */\nexport class P2PSyncProvider extends BaseSyncProvider {\n readonly type = 'p2p' as const;\n\n private client: P2PClient;\n private options: Required<P2PSyncOptions>;\n\n // Header chain state\n private headersByHash: Map<string, CachedHeader> = new Map();\n private headersByHeight: Map<number, CachedHeader> = new Map();\n private chainTipHeight: number = -1;\n private chainTipHash: string = '';\n private genesisHash: string = '';\n\n // Block cache (limited size)\n private blockCache: Map<string, Buffer> = new Map();\n private maxBlockCacheSize = 10;\n\n // Pending block requests\n private pendingBlocks: Map<string, Promise<Buffer>> = new Map();\n\n constructor(options: P2PSyncOptions) {\n super(options);\n\n this.options = {\n host: options.host,\n port: options.port ?? 33570,\n network: options.network ?? 'testnet',\n timeout: options.timeout ?? 30000,\n debug: options.debug ?? false,\n userAgent: options.userAgent ?? '/navio-sdk:0.1.0/',\n maxBlocksPerRequest: options.maxBlocksPerRequest ?? 16,\n maxHeadersPerRequest: options.maxHeadersPerRequest ?? 2000,\n };\n\n this.client = new P2PClient({\n host: this.options.host,\n port: this.options.port,\n network: this.options.network,\n timeout: this.options.timeout,\n debug: this.options.debug,\n userAgent: this.options.userAgent,\n });\n }\n\n /**\n * Connect to the P2P node\n */\n async connect(): Promise<void> {\n await this.client.connect();\n this.log('Connected to P2P node');\n\n // Request headers-first announcements\n this.client.sendSendHeaders();\n\n // Get initial chain state\n this.chainTipHeight = this.client.getPeerStartHeight();\n this.log(`Peer reports height: ${this.chainTipHeight}`);\n\n // Register block handler\n this.client.onMessage(MessageType.BLOCK, (msg) => {\n this.handleBlockMessage(msg);\n });\n\n // Sync headers to get chain tip\n if (this.chainTipHeight > 0) {\n await this.syncHeaders(0, Math.min(100, this.chainTipHeight));\n }\n }\n\n /**\n * Disconnect from the P2P node\n */\n disconnect(): void {\n this.client.disconnect();\n this.headersByHash.clear();\n this.headersByHeight.clear();\n this.blockCache.clear();\n this.chainTipHeight = -1;\n }\n\n /**\n * Check if connected\n */\n isConnected(): boolean {\n return this.client.isConnected();\n }\n\n /**\n * Get current chain tip height\n */\n async getChainTipHeight(): Promise<number> {\n // If we have synced headers, use that\n if (this.chainTipHeight >= 0) {\n return this.chainTipHeight;\n }\n\n // Otherwise use peer's reported height\n return this.client.getPeerStartHeight();\n }\n\n /**\n * Get current chain tip\n */\n async getChainTip(): Promise<ChainTip> {\n return {\n height: this.chainTipHeight,\n hash: this.chainTipHash,\n };\n }\n\n /**\n * Get a single block header\n */\n async getBlockHeader(height: number): Promise<string> {\n // Check cache\n const cached = this.headersByHeight.get(height);\n if (cached) {\n return cached.rawHex;\n }\n\n // Need to fetch headers up to this height\n await this.syncHeaders(height, 1);\n\n const header = this.headersByHeight.get(height);\n if (!header) {\n throw new Error(`Failed to fetch header at height ${height}`);\n }\n\n return header.rawHex;\n }\n\n /**\n * Get multiple block headers\n */\n async getBlockHeaders(startHeight: number, count: number): Promise<BlockHeadersResult> {\n // Ensure we have headers cached\n await this.syncHeaders(startHeight, count);\n\n const headers: string[] = [];\n for (let h = startHeight; h < startHeight + count; h++) {\n const cached = this.headersByHeight.get(h);\n if (cached) {\n headers.push(cached.rawHex);\n } else {\n break;\n }\n }\n\n return {\n count: headers.length,\n hex: headers.join(''),\n max: this.options.maxHeadersPerRequest,\n };\n }\n\n /**\n * Sync headers from the network\n */\n private async syncHeaders(fromHeight: number, count: number): Promise<void> {\n // Build locator from known headers\n const locatorHashes: Buffer[] = [];\n\n // Start from just before the requested height\n let step = 1;\n let height = fromHeight > 0 ? fromHeight - 1 : 0;\n\n while (height >= 0) {\n const header = this.headersByHeight.get(height);\n if (header) {\n locatorHashes.push(P2PClient.hashFromDisplay(header.hash));\n }\n if (height === 0) break;\n height -= step;\n if (locatorHashes.length > 10) step *= 2;\n }\n\n // Always include genesis if we have it\n if (this.genesisHash && locatorHashes.length === 0) {\n locatorHashes.push(P2PClient.hashFromDisplay(this.genesisHash));\n }\n\n // If no locators, start from genesis\n if (locatorHashes.length === 0) {\n locatorHashes.push(Buffer.alloc(32)); // Zero hash = start from genesis\n }\n\n // Request headers\n const rawHeaders = await this.client.getHeaders(locatorHashes);\n this.log(`Received ${rawHeaders.length} headers`);\n\n // Process headers - they arrive in order after the locator\n // For initial sync from genesis, first header is block 0\n\n // First pass: Find any headers we can chain from known blocks\n const pendingHeaders: Array<{ rawHeader: Buffer; hash: string; prevHash: string; headerHex: string }> = [];\n\n for (const rawHeader of rawHeaders) {\n const headerHex = rawHeader.toString('hex');\n const hash = this.extractBlockHash(headerHex);\n // Block header: version(4) + prevBlockHash(32) + merkleRoot(32) + timestamp(4) + bits(4) + nonce(4) = 80 bytes\n // prevBlockHash is at offset 4, length 32 (bytes 4-35 inclusive)\n // subarray(4, 36) gives bytes at indices 4,5,...,35 (32 bytes total)\n const prevHashBytes = rawHeader.subarray(4, 36);\n // Reverse for display format (little-endian to big-endian)\n const prevHash = Buffer.from(prevHashBytes).reverse().toString('hex');\n\n pendingHeaders.push({ rawHeader, hash, prevHash, headerHex });\n }\n\n // Process headers - they come in chain order from getheaders\n // Headers are returned in order: each header's prevHash points to the previous header in the response\n for (let i = 0; i < pendingHeaders.length; i++) {\n const { hash, prevHash, headerHex } = pendingHeaders[i];\n\n let headerHeight: number;\n\n if (prevHash === '0'.repeat(64)) {\n // Genesis block (prevHash is all zeros)\n headerHeight = 0;\n this.genesisHash = hash;\n } else if (this.headersByHash.has(prevHash)) {\n // We have the parent in our cache, chain from it\n const prevHeader = this.headersByHash.get(prevHash)!;\n headerHeight = prevHeader.height + 1;\n } else if (i === 0 && this.headersByHeight.size === 0) {\n // First header in initial sync - this is genesis (height 0)\n // Genesis block in Navio might have a non-zero prevHash for the PoS genesis\n this.log(`Initial sync: first header is genesis (height 0)`);\n headerHeight = 0;\n this.genesisHash = hash;\n } else if (i > 0) {\n // Chain from the previous header in THIS batch\n // Since getheaders returns headers in chain order, header[i].prevHash should equal header[i-1].hash\n const prevInBatch = pendingHeaders[i - 1];\n if (prevInBatch.hash === prevHash) {\n const prevCached = this.headersByHash.get(prevInBatch.hash);\n if (prevCached) {\n headerHeight = prevCached.height + 1;\n } else {\n this.log(`Previous header in batch not yet cached: ${prevInBatch.hash.substring(0, 16)}...`);\n continue;\n }\n } else {\n // Skip verbose logging after first few\n if (i < 5) {\n this.log(`Header ${hash.substring(0, 16)}... doesn't chain from previous in batch`);\n }\n continue;\n }\n } else {\n this.log(`Cannot determine height for header ${hash.substring(0, 16)}...`);\n continue;\n }\n\n const cached: CachedHeader = {\n height: headerHeight,\n hash,\n rawHex: headerHex,\n prevHash,\n };\n\n this.headersByHash.set(hash, cached);\n this.headersByHeight.set(headerHeight, cached);\n\n // Update chain tip\n if (headerHeight > this.chainTipHeight) {\n this.chainTipHeight = headerHeight;\n this.chainTipHash = hash;\n }\n }\n\n this.log(`Processed headers. Chain tip: height=${this.chainTipHeight}, cached=${this.headersByHeight.size} headers`);\n\n // Continue syncing if we got max headers and need more\n if (rawHeaders.length >= this.options.maxHeadersPerRequest - 1 && this.chainTipHeight < this.client.getPeerStartHeight()) {\n // Request more headers from where we left off\n await this.syncHeaders(this.chainTipHeight, count);\n }\n }\n\n /**\n * Get transaction keys for a range of blocks\n */\n async getBlockTransactionKeysRange(startHeight: number): Promise<{\n blocks: BlockTransactionKeys[];\n nextHeight: number;\n }> {\n const blocks: BlockTransactionKeys[] = [];\n const maxBlocks = this.options.maxBlocksPerRequest;\n\n // Calculate end height for this batch\n const batchEndHeight = Math.min(startHeight + maxBlocks - 1, this.chainTipHeight);\n\n // Try to ensure we have headers up to the batch end height\n // This may fail if we're at the chain tip, which is OK\n try {\n await this.ensureHeadersSyncedTo(batchEndHeight);\n } catch (e) {\n this.log(`Could not sync headers to ${batchEndHeight}: ${e}`);\n // Continue with what we have\n }\n\n // Find the highest header we actually have\n let highestCached = 0;\n for (const h of this.headersByHeight.keys()) {\n if (h > highestCached) highestCached = h;\n }\n\n // Don't try to sync past what we have headers for\n const effectiveTip = Math.min(this.chainTipHeight, highestCached);\n\n // If start height is beyond what we can sync, return empty\n if (startHeight > effectiveTip) {\n return {\n blocks: [],\n nextHeight: startHeight,\n };\n }\n\n for (let height = startHeight; height < startHeight + maxBlocks && height <= effectiveTip; height++) {\n try {\n const txKeys = await this.getBlockTransactionKeys(height);\n blocks.push({\n height,\n txKeys,\n });\n } catch (e) {\n this.log(`Error getting tx keys for block ${height}: ${e}`);\n // Stop on error - don't skip blocks\n break;\n }\n }\n\n const lastHeight = blocks.length > 0 ? blocks[blocks.length - 1].height : startHeight;\n return {\n blocks,\n nextHeight: lastHeight + 1,\n };\n }\n\n /**\n * Get transaction keys for a single block\n */\n async getBlockTransactionKeys(height: number): Promise<TransactionKeys[]> {\n // Ensure we have headers synced up to this height\n await this.ensureHeadersSyncedTo(height);\n\n const header = this.headersByHeight.get(height);\n if (!header) {\n throw new Error(`Cannot get header for height ${height}`);\n }\n\n // Fetch block\n const blockData = await this.fetchBlock(header.hash);\n\n // Parse block and extract transaction keys\n return this.parseBlockTransactionKeys(blockData);\n }\n\n /**\n * Ensure headers are synced up to the specified height\n */\n private async ensureHeadersSyncedTo(targetHeight: number): Promise<void> {\n // Already have the header\n if (this.headersByHeight.has(targetHeight)) {\n return;\n }\n\n // Find highest height we have\n let highestKnown = -1;\n for (const h of this.headersByHeight.keys()) {\n if (h > highestKnown) highestKnown = h;\n }\n\n // If we're already at or past the target, we're done\n if (highestKnown >= targetHeight) {\n return;\n }\n\n // Keep syncing until we have headers up to target height or can't make progress\n let attempts = 0;\n const maxAttempts = 100; // Prevent infinite loop\n\n while (!this.headersByHeight.has(targetHeight) && attempts < maxAttempts) {\n attempts++;\n\n this.log(`Need header ${targetHeight}, highest known: ${highestKnown}`);\n\n // Sync more headers starting from where we are\n const syncFrom = highestKnown + 1;\n await this.syncHeaders(syncFrom, this.options.maxHeadersPerRequest);\n\n // Check if we made progress\n let newHighest = -1;\n for (const h of this.headersByHeight.keys()) {\n if (h > newHighest) newHighest = h;\n }\n\n if (newHighest <= highestKnown) {\n // No progress made - we're at the chain tip\n // This is OK if we're close to the target\n this.log(`No new headers available, highest: ${highestKnown}`);\n return; // Don't throw, just return what we have\n }\n\n highestKnown = newHighest;\n }\n }\n\n /**\n * Fetch a block by hash\n */\n private async fetchBlock(hashHex: string): Promise<Buffer> {\n // Check cache\n const cached = this.blockCache.get(hashHex);\n if (cached) {\n return cached;\n }\n\n // Check for pending request\n const pending = this.pendingBlocks.get(hashHex);\n if (pending) {\n return pending;\n }\n\n // Request block\n const blockHashBuffer = P2PClient.hashFromDisplay(hashHex);\n const promise = this.client.getBlock(blockHashBuffer).then((msg) => {\n this.pendingBlocks.delete(hashHex);\n\n // Cache the block\n if (this.blockCache.size >= this.maxBlockCacheSize) {\n // Remove oldest entry\n const oldest = this.blockCache.keys().next().value;\n if (oldest) this.blockCache.delete(oldest);\n }\n this.blockCache.set(hashHex, msg.payload);\n\n return msg.payload;\n });\n\n this.pendingBlocks.set(hashHex, promise);\n return promise;\n }\n\n /**\n * Handle incoming block message\n */\n private handleBlockMessage(msg: P2PMessage): void {\n // Extract block hash from header\n const headerHex = msg.payload.subarray(0, 80).toString('hex');\n const hash = this.extractBlockHash(headerHex);\n\n // Cache the block\n if (this.blockCache.size >= this.maxBlockCacheSize) {\n const oldest = this.blockCache.keys().next().value;\n if (oldest) this.blockCache.delete(oldest);\n }\n this.blockCache.set(hash, msg.payload);\n\n this.log(`Received block: ${hash}`);\n }\n\n /**\n * Parse block data and extract transaction keys\n *\n * Parses all transactions in the block and extracts BLSCT output keys\n * for wallet output detection.\n */\n private parseBlockTransactionKeys(blockData: Buffer): TransactionKeys[] {\n const txKeys: TransactionKeys[] = [];\n let offset = 80; // Skip header\n\n // Check if this is a PoS block (version bit 24 set = 0x01000000)\n const version = blockData.readInt32LE(0);\n const isPoS = (version & 0x01000000) !== 0;\n\n this.log(`Block version: 0x${version.toString(16)}, isPoS: ${isPoS}, size: ${blockData.length}`);\n\n // Skip PoS proof if present\n if (isPoS) {\n // Navio PoS blocks have a CStakeProof after the header\n // Need to read and skip the proof carefully\n const proofSkipResult = this.skipPoSProof(blockData, offset);\n if (proofSkipResult.error) {\n this.log(`Error skipping PoS proof: ${proofSkipResult.error}`);\n return txKeys;\n }\n offset = proofSkipResult.newOffset;\n this.log(`Skipped PoS proof, offset now: ${offset}`);\n }\n\n // Parse transaction count\n const { value: txCount, bytesRead } = this.decodeVarInt(blockData, offset);\n offset += bytesRead;\n\n this.log(`Parsing ${txCount} transactions from block (offset: ${offset})`);\n\n // Parse each transaction\n for (let txIndex = 0; txIndex < Number(txCount); txIndex++) {\n const result = this.parseBlsctTransaction(blockData, offset);\n if (result.error) {\n this.log(`Error parsing tx ${txIndex}/${txCount}: ${result.error}`);\n break;\n }\n\n offset = result.newOffset;\n\n if (result.outputKeys.length > 0) {\n txKeys.push({\n txHash: result.txHash,\n keys: this.formatOutputKeys(result.outputKeys),\n });\n }\n }\n\n return txKeys;\n }\n\n /**\n * Skip PoS proof in block data\n */\n private skipPoSProof(\n data: Buffer,\n offset: number\n ): { newOffset: number; error?: string } {\n try {\n // PoS proof structure (blsct::ProofOfStake) from navio-core/src/blsct/pos/proof.h:\n // - SetMemProof setMemProof\n // - RangeProof rangeProof (serialized as RangeProofWithoutVs)\n //\n // SetMemProof contains:\n // - 8 Points (phi, A1, A2, S1, S2, S3, T1, T2) = 8 × 48 = 384 bytes\n // - 6 Scalars (tau_x, mu, z_alpha, z_tau, z_beta, t) = 6 × 32 = 192 bytes\n // - Ls vector (variable: varint count + count × 48 bytes)\n // - Rs vector (variable: varint count + count × 48 bytes)\n // - 3 Scalars (a, b, omega) = 3 × 32 = 96 bytes\n\n const G1_SIZE = 48;\n const SCALAR_SIZE = 32;\n\n // SetMemProof fixed part: 8 points + 6 scalars\n offset += 8 * G1_SIZE; // phi, A1, A2, S1, S2, S3, T1, T2\n offset += 6 * SCALAR_SIZE; // tau_x, mu, z_alpha, z_tau, z_beta, t\n\n // Ls vector\n const { value: lsCount, bytesRead: lsCountBytes } = this.decodeVarInt(data, offset);\n offset += lsCountBytes;\n offset += Number(lsCount) * G1_SIZE;\n\n // Rs vector\n const { value: rsCount, bytesRead: rsCountBytes } = this.decodeVarInt(data, offset);\n offset += rsCountBytes;\n offset += Number(rsCount) * G1_SIZE;\n\n // 3 more scalars: a, b, omega\n offset += 3 * SCALAR_SIZE;\n\n // Now skip the RangeProof (RangeProofWithoutVs - no Vs vector)\n // RangeProofWithoutVs contains:\n // - Ls vector (varint + points)\n // - Rs vector (varint + points)\n // - A, A_wip, B (3 points)\n // - r_prime, s_prime, delta_prime, alpha_hat, tau_x (5 scalars)\n\n // Ls vector\n const { value: rpLsCount, bytesRead: rpLsCountBytes } = this.decodeVarInt(data, offset);\n offset += rpLsCountBytes;\n offset += Number(rpLsCount) * G1_SIZE;\n\n // Rs vector\n const { value: rpRsCount, bytesRead: rpRsCountBytes } = this.decodeVarInt(data, offset);\n offset += rpRsCountBytes;\n offset += Number(rpRsCount) * G1_SIZE;\n\n // A, A_wip, B (3 points)\n offset += 3 * G1_SIZE;\n\n // r_prime, s_prime, delta_prime, alpha_hat, tau_x (5 scalars)\n offset += 5 * SCALAR_SIZE;\n\n return { newOffset: offset };\n } catch (e) {\n return { newOffset: offset, error: String(e) };\n }\n }\n\n // ============================================================================\n // BLSCT Constants\n // ============================================================================\n\n private static readonly G1_POINT_SIZE = 48; // Compressed G1 point\n private static readonly SCALAR_SIZE = 32; // MCL Scalar\n private static readonly MAX_AMOUNT = BigInt('0x7FFFFFFFFFFFFFFF');\n private static readonly BLSCT_MARKER = 0x1;\n private static readonly TOKEN_MARKER = 0x2;\n private static readonly PREDICATE_MARKER = 0x4;\n private static readonly TRANSPARENT_VALUE_MARKER = 0x8;\n\n /**\n * Parse a BLSCT transaction and extract output keys\n */\n private parseBlsctTransaction(\n data: Buffer,\n offset: number\n ): { txHash: string; outputKeys: ParsedOutputKeys[]; newOffset: number; error?: string } {\n const startOffset = offset;\n const outputKeys: ParsedOutputKeys[] = [];\n\n try {\n // Version (4 bytes)\n const version = data.readInt32LE(offset);\n offset += 4;\n\n // Transaction BLSCT marker is 0x20 (1 << 5), different from block's 0x40000000\n const TX_BLSCT_MARKER = 0x20;\n const isBLSCT = (version & TX_BLSCT_MARKER) !== 0;\n\n // Check for witness marker (0x00 followed by flags)\n let hasWitness = false;\n let witnessFlags = 0;\n if (data[offset] === 0x00) {\n // Read potential flags byte\n if (offset + 1 < data.length && data[offset + 1] !== 0x00) {\n witnessFlags = data[offset + 1];\n hasWitness = (witnessFlags & 0x01) !== 0;\n offset += 2; // Skip marker and flag\n }\n }\n\n // Input count\n const { value: inputCount, bytesRead: inputCountBytes } = this.decodeVarInt(data, offset);\n offset += inputCountBytes;\n\n // Parse inputs\n // NOTE: Navio's COutPoint only contains hash (no index/n field)\n // This is different from Bitcoin where COutPoint has both hash and n\n for (let i = 0; i < Number(inputCount); i++) {\n offset += 32; // Previous output hash (prevout.hash) - Navio has no prevout.n!\n \n // scriptSig length + data\n const { value: scriptSigLen, bytesRead: sigLenBytes } = this.decodeVarInt(data, offset);\n offset += sigLenBytes;\n if (Number(scriptSigLen) > 10000) {\n return { txHash: '', outputKeys: [], newOffset: offset, error: `Invalid scriptSig length: ${scriptSigLen}` };\n }\n offset += Number(scriptSigLen);\n offset += 4; // sequence\n }\n\n // Output count\n const { value: outputCount, bytesRead: outputCountBytes } = this.decodeVarInt(data, offset);\n offset += outputCountBytes;\n\n // Parse outputs\n for (let i = 0; i < Number(outputCount); i++) {\n const outputResult = this.parseBlsctOutput(data, offset, i);\n if (outputResult.error) {\n return { txHash: '', outputKeys: [], newOffset: offset, error: outputResult.error };\n }\n offset = outputResult.newOffset;\n if (outputResult.keys) {\n outputKeys.push(outputResult.keys);\n }\n }\n\n // Parse witness data if present\n if (hasWitness) {\n for (let i = 0; i < Number(inputCount); i++) {\n const { value: witnessCount, bytesRead: wcBytes } = this.decodeVarInt(data, offset);\n offset += wcBytes;\n\n for (let j = 0; j < Number(witnessCount); j++) {\n const { value: itemLen, bytesRead: ilBytes } = this.decodeVarInt(data, offset);\n offset += ilBytes;\n offset += Number(itemLen);\n }\n }\n }\n\n // Lock time\n offset += 4;\n\n // BLSCT signature if present\n if (isBLSCT) {\n // blsct::Signature is 2 G1 points (96 bytes)\n offset += 96;\n }\n\n // Calculate transaction hash\n const txData = data.subarray(startOffset, offset);\n const txHash = this.calculateBlsctTxHash(txData, hasWitness, startOffset, version);\n\n return {\n txHash,\n outputKeys,\n newOffset: offset,\n };\n } catch (e) {\n return {\n txHash: '',\n outputKeys: [],\n newOffset: offset,\n error: `Parse error: ${e}`,\n };\n }\n }\n\n /**\n * Parse a BLSCT output and extract keys\n */\n private parseBlsctOutput(\n data: Buffer,\n offset: number,\n outputIndex: number\n ): { keys: ParsedOutputKeys | null; newOffset: number; error?: string } {\n try {\n // Read value (8 bytes)\n const rawValue = data.readBigInt64LE(offset);\n offset += 8;\n\n let flags = 0n;\n\n // Check for extended format (value = MAX_AMOUNT indicates flags follow)\n if (rawValue === P2PSyncProvider.MAX_AMOUNT) {\n // Extended format with flags\n flags = data.readBigUInt64LE(offset);\n offset += 8;\n\n if (flags & BigInt(P2PSyncProvider.TRANSPARENT_VALUE_MARKER)) {\n // Skip the actual value (we don't need it for key extraction)\n offset += 8;\n }\n }\n\n // Parse scriptPubKey\n const { value: scriptLen, bytesRead: scriptLenBytes } = this.decodeVarInt(data, offset);\n offset += scriptLenBytes;\n offset += Number(scriptLen);\n\n const hasBlsctData = (flags & BigInt(P2PSyncProvider.BLSCT_MARKER)) !== 0n;\n const hasTokenId = (flags & BigInt(P2PSyncProvider.TOKEN_MARKER)) !== 0n;\n const hasPredicate = (flags & BigInt(P2PSyncProvider.PREDICATE_MARKER)) !== 0n;\n\n let keys: ParsedOutputKeys | null = null;\n\n // Parse BLSCT data if present\n if (hasBlsctData) {\n const blsctResult = this.parseBlsctData(data, offset, outputIndex);\n if (blsctResult.error) {\n return { keys: null, newOffset: offset, error: blsctResult.error };\n }\n offset = blsctResult.newOffset;\n keys = blsctResult.keys;\n }\n\n // Skip token ID if present\n if (hasTokenId) {\n // TokenId is 2 uint256s (64 bytes)\n offset += 64;\n }\n\n // Skip predicate if present\n if (hasPredicate) {\n const { value: predicateLen, bytesRead: predLenBytes } = this.decodeVarInt(data, offset);\n offset += predLenBytes;\n offset += Number(predicateLen);\n }\n\n return { keys, newOffset: offset };\n } catch (e) {\n return { keys: null, newOffset: offset, error: `Output parse error: ${e}` };\n }\n }\n\n /**\n * Parse BLSCT data from output\n */\n private parseBlsctData(\n data: Buffer,\n offset: number,\n outputIndex: number\n ): { keys: ParsedOutputKeys | null; newOffset: number; error?: string } {\n try {\n // Parse range proof\n const proofResult = this.parseRangeProof(data, offset);\n if (proofResult.error) {\n return { keys: null, newOffset: offset, error: proofResult.error };\n }\n offset = proofResult.newOffset;\n\n // Parse keys (only if range proof has data)\n if (proofResult.hasData) {\n // spendingKey (G1 point)\n const spendingKey = data.subarray(offset, offset + P2PSyncProvider.G1_POINT_SIZE).toString('hex');\n offset += P2PSyncProvider.G1_POINT_SIZE;\n\n // blindingKey (G1 point)\n const blindingKey = data.subarray(offset, offset + P2PSyncProvider.G1_POINT_SIZE).toString('hex');\n offset += P2PSyncProvider.G1_POINT_SIZE;\n\n // ephemeralKey (G1 point)\n const ephemeralKey = data.subarray(offset, offset + P2PSyncProvider.G1_POINT_SIZE).toString('hex');\n offset += P2PSyncProvider.G1_POINT_SIZE;\n\n // viewTag (2 bytes)\n const viewTag = data.readUInt16LE(offset);\n offset += 2;\n\n // Create output hash from output index (simplified)\n const outputHash = this.hashBuffer(Buffer.from(`output:${outputIndex}`));\n\n return {\n keys: {\n blindingKey,\n spendingKey,\n ephemeralKey,\n viewTag,\n outputHash,\n hasRangeProof: true,\n },\n newOffset: offset,\n };\n }\n\n return { keys: null, newOffset: offset };\n } catch (e) {\n return { keys: null, newOffset: offset, error: `BLSCT data parse error: ${e}` };\n }\n }\n\n /**\n * Parse bulletproofs_plus range proof\n */\n private parseRangeProof(\n data: Buffer,\n offset: number\n ): { hasData: boolean; newOffset: number; error?: string } {\n try {\n // ProofBase: Vs, Ls, Rs (vectors of Points)\n // First, parse Vs\n const { value: vsCount, bytesRead: vsCountBytes } = this.decodeVarInt(data, offset);\n offset += vsCountBytes;\n\n const numVs = Number(vsCount);\n offset += numVs * P2PSyncProvider.G1_POINT_SIZE; // Vs\n\n if (numVs > 0) {\n // Parse Ls\n const { value: lsCount, bytesRead: lsCountBytes } = this.decodeVarInt(data, offset);\n offset += lsCountBytes;\n offset += Number(lsCount) * P2PSyncProvider.G1_POINT_SIZE;\n\n // Parse Rs\n const { value: rsCount, bytesRead: rsCountBytes } = this.decodeVarInt(data, offset);\n offset += rsCountBytes;\n offset += Number(rsCount) * P2PSyncProvider.G1_POINT_SIZE;\n\n // RangeProof additional fields\n offset += P2PSyncProvider.G1_POINT_SIZE; // A\n offset += P2PSyncProvider.G1_POINT_SIZE; // A_wip\n offset += P2PSyncProvider.G1_POINT_SIZE; // B\n offset += P2PSyncProvider.SCALAR_SIZE; // r_prime\n offset += P2PSyncProvider.SCALAR_SIZE; // s_prime\n offset += P2PSyncProvider.SCALAR_SIZE; // delta_prime\n offset += P2PSyncProvider.SCALAR_SIZE; // alpha_hat\n offset += P2PSyncProvider.SCALAR_SIZE; // tau_x\n }\n\n return { hasData: numVs > 0, newOffset: offset };\n } catch (e) {\n return { hasData: false, newOffset: offset, error: `RangeProof parse error: ${e}` };\n }\n }\n\n /**\n * Calculate BLSCT transaction hash\n */\n private calculateBlsctTxHash(txData: Buffer, _hasWitness: boolean, _startOffset: number, _version: number): string {\n // For now, simple double SHA256 of the full transaction\n // TODO: Handle witness stripping for proper txid calculation\n const hash = sha256(sha256(txData));\n return Buffer.from(hash).reverse().toString('hex');\n }\n\n /**\n * Hash a buffer using SHA256\n */\n private hashBuffer(data: Buffer): string {\n return Buffer.from(sha256(data)).toString('hex');\n }\n\n /**\n * Format output keys for the sync interface\n */\n private formatOutputKeys(outputKeys: ParsedOutputKeys[]): { outputs: ParsedOutputKeys[] } {\n return {\n outputs: outputKeys,\n };\n }\n\n /**\n * Get serialized transaction output by output hash\n */\n async getTransactionOutput(outputHash: string): Promise<string> {\n // Use GETOUTPUTDATA P2P message\n const outputHashBuffer = Buffer.from(outputHash, 'hex');\n const response = await this.client.getOutputData([outputHashBuffer]);\n\n // Response should be a TX message containing the transaction\n return response.payload.toString('hex');\n }\n\n /**\n * Broadcast a transaction\n */\n async broadcastTransaction(rawTx: string): Promise<string> {\n // Parse transaction to get hash\n const txData = Buffer.from(rawTx, 'hex');\n const txHash = this.calculateBlsctTxHash(txData, false, 0, 0);\n\n // TODO: Implement proper broadcast with INV/GETDATA dance\n // For now, we would need to:\n // 1. Send INV announcing the transaction\n // 2. Wait for GETDATA request\n // 3. Send the TX\n // This requires exposing sendMessage as public or adding a broadcast method to P2PClient\n\n this.log(`Broadcasting transaction: ${txHash}`);\n\n return txHash;\n }\n\n /**\n * Get raw transaction\n */\n async getRawTransaction(txHash: string, _verbose?: boolean): Promise<string> {\n // Request transaction via GETDATA\n const inv = [{ type: InvType.MSG_WITNESS_TX, hash: P2PClient.hashFromDisplay(txHash) }];\n\n // Send getdata\n await this.client.getData(inv);\n\n // Wait for TX message\n const response = await this.client.waitForMessage(MessageType.TX, this.options.timeout);\n\n return response.payload.toString('hex');\n }\n\n /**\n * Decode variable-length integer from buffer\n */\n private decodeVarInt(buffer: Buffer, offset: number): { value: bigint; bytesRead: number } {\n const first = buffer.readUInt8(offset);\n\n if (first < 0xfd) {\n return { value: BigInt(first), bytesRead: 1 };\n } else if (first === 0xfd) {\n return { value: BigInt(buffer.readUInt16LE(offset + 1)), bytesRead: 3 };\n } else if (first === 0xfe) {\n return { value: BigInt(buffer.readUInt32LE(offset + 1)), bytesRead: 5 };\n } else {\n return { value: buffer.readBigUInt64LE(offset + 1), bytesRead: 9 };\n }\n }\n}\n\n","/**\n * Electrum Sync Provider\n *\n * Implements the SyncProvider interface using an Electrum server connection.\n * This is a wrapper around ElectrumClient that provides the standardized sync interface.\n */\n\nimport { BaseSyncProvider, BlockHeadersResult, ChainTip, SyncProviderOptions } from './sync-provider';\nimport { ElectrumClient, ElectrumOptions, BlockTransactionKeys, TransactionKeys } from './electrum';\n\n/**\n * Electrum sync provider options\n */\nexport interface ElectrumSyncOptions extends SyncProviderOptions, ElectrumOptions {}\n\n/**\n * Electrum Sync Provider\n *\n * Uses an Electrum server for blockchain synchronization.\n * Provides efficient transaction key fetching through Electrum's preprocessed data.\n * \n * @category Sync\n */\nexport class ElectrumSyncProvider extends BaseSyncProvider {\n readonly type = 'electrum' as const;\n\n private client: ElectrumClient;\n private chainTipHeight: number = -1;\n private chainTipHash: string = '';\n\n constructor(options: ElectrumSyncOptions = {}) {\n super(options);\n this.client = new ElectrumClient(options);\n }\n\n /**\n * Get the underlying ElectrumClient for direct access to additional methods\n */\n getClient(): ElectrumClient {\n return this.client;\n }\n\n /**\n * Connect to the Electrum server\n */\n async connect(): Promise<void> {\n await this.client.connect();\n this.log('Connected to Electrum server');\n\n // Cache initial chain tip\n this.chainTipHeight = await this.client.getChainTipHeight();\n const header = await this.client.getBlockHeader(this.chainTipHeight);\n this.chainTipHash = this.extractBlockHash(header);\n }\n\n /**\n * Disconnect from the Electrum server\n */\n disconnect(): void {\n this.client.disconnect();\n }\n\n /**\n * Check if connected\n */\n isConnected(): boolean {\n return this.client.isConnected();\n }\n\n /**\n * Get current chain tip height\n */\n async getChainTipHeight(): Promise<number> {\n this.chainTipHeight = await this.client.getChainTipHeight();\n return this.chainTipHeight;\n }\n\n /**\n * Get current chain tip\n */\n async getChainTip(): Promise<ChainTip> {\n const height = await this.getChainTipHeight();\n const header = await this.client.getBlockHeader(height);\n this.chainTipHash = this.extractBlockHash(header);\n\n return {\n height,\n hash: this.chainTipHash,\n };\n }\n\n /**\n * Get a single block header\n */\n async getBlockHeader(height: number): Promise<string> {\n return this.client.getBlockHeader(height);\n }\n\n /**\n * Get multiple block headers\n */\n async getBlockHeaders(startHeight: number, count: number): Promise<BlockHeadersResult> {\n return this.client.getBlockHeaders(startHeight, count);\n }\n\n /**\n * Get transaction keys for a range of blocks\n */\n async getBlockTransactionKeysRange(startHeight: number): Promise<{\n blocks: BlockTransactionKeys[];\n nextHeight: number;\n }> {\n return this.client.getBlockTransactionKeysRange(startHeight);\n }\n\n /**\n * Get transaction keys for a single block\n */\n async getBlockTransactionKeys(height: number): Promise<TransactionKeys[]> {\n const result = await this.client.getBlockTransactionKeys(height);\n\n // Transform to TransactionKeys format\n if (Array.isArray(result)) {\n return result.map((txKeyData: any, index: number) => {\n if (typeof txKeyData === 'object' && txKeyData !== null) {\n if ('txHash' in txKeyData && 'keys' in txKeyData) {\n return txKeyData as TransactionKeys;\n } else {\n return {\n txHash: txKeyData.txHash || txKeyData.hash || `tx_${index}`,\n keys: txKeyData,\n };\n }\n }\n return {\n txHash: `tx_${index}`,\n keys: txKeyData,\n };\n });\n }\n\n return [];\n }\n\n /**\n * Get serialized transaction output by output hash\n */\n async getTransactionOutput(outputHash: string): Promise<string> {\n return this.client.getTransactionOutput(outputHash);\n }\n\n /**\n * Broadcast a transaction\n */\n async broadcastTransaction(rawTx: string): Promise<string> {\n return this.client.broadcastTransaction(rawTx);\n }\n\n /**\n * Get raw transaction\n */\n async getRawTransaction(txHash: string, verbose?: boolean): Promise<string | unknown> {\n return this.client.getRawTransaction(txHash, verbose);\n }\n\n // ============================================================================\n // Additional Electrum-specific Methods (passthrough)\n // ============================================================================\n\n /**\n * Get server version\n */\n async getServerVersion(): Promise<[string, string]> {\n return this.client.getServerVersion();\n }\n\n /**\n * Subscribe to block headers\n */\n async subscribeBlockHeaders(callback: (header: any) => void): Promise<void> {\n return this.client.subscribeBlockHeaders(callback);\n }\n\n /**\n * Get transaction keys for a specific transaction\n */\n async getTransactionKeys(txHash: string): Promise<any> {\n return this.client.getTransactionKeys(txHash);\n }\n\n /**\n * Fetch all transaction keys from genesis to chain tip\n */\n async fetchAllTransactionKeys(\n progressCallback?: (height: number, totalHeight: number, blocksProcessed: number) => void\n ): Promise<BlockTransactionKeys[]> {\n return this.client.fetchAllTransactionKeys(progressCallback);\n }\n\n /**\n * Get transaction history for a script hash\n */\n async getHistory(scriptHash: string): Promise<any[]> {\n return this.client.getHistory(scriptHash);\n }\n\n /**\n * Get unspent transaction outputs for a script hash\n */\n async getUnspent(scriptHash: string): Promise<any[]> {\n return this.client.getUnspent(scriptHash);\n }\n\n /**\n * Subscribe to script hash updates\n */\n async subscribeScriptHash(scriptHash: string, callback: (status: string) => void): Promise<void> {\n return this.client.subscribeScriptHash(scriptHash, callback);\n }\n}\n\n","/**\n * Navio SDK Client\n * Main client class for interacting with the Navio blockchain\n *\n * This is the primary entry point for the SDK. It manages:\n * - Wallet database connection\n * - Backend connection (Electrum or P2P)\n * - Transaction keys synchronization\n * - Key management\n */\n\nimport { WalletDB } from './wallet-db';\nimport { ElectrumClient, ElectrumOptions } from './electrum';\nimport { TransactionKeysSync, SyncOptions, BackgroundSyncOptions } from './tx-keys-sync';\nimport { KeyManager } from './key-manager';\nimport { SyncProvider } from './sync-provider';\nimport { P2PSyncProvider } from './p2p-sync';\nimport { P2PConnectionOptions } from './p2p-protocol';\nimport { ElectrumSyncProvider } from './electrum-sync';\nimport { BlsctChain, setChain } from 'navio-blsct';\nimport { sha256 } from '@noble/hashes/sha256';\n\n/**\n * Network type for Navio\n */\nexport type NetworkType = 'mainnet' | 'testnet' | 'signet' | 'regtest';\n\n/**\n * Backend type for NavioClient\n */\nexport type BackendType = 'electrum' | 'p2p';\n\n/**\n * P2P connection options for NavioClient\n */\nexport interface P2POptions extends P2PConnectionOptions {\n /** Maximum headers to fetch per request */\n maxHeadersPerRequest?: number;\n}\n\n/**\n * Configuration for NavioClient\n */\nexport interface NavioClientConfig {\n /** Path to wallet database file */\n walletDbPath: string;\n\n /**\n * Backend type to use for synchronization\n * - 'electrum': Connect to an Electrum server (recommended for wallets)\n * - 'p2p': Connect directly to a Navio full node\n * @default 'electrum'\n */\n backend?: BackendType;\n\n /**\n * Electrum server connection options\n * Required when backend is 'electrum'\n */\n electrum?: ElectrumOptions;\n\n /**\n * P2P connection options\n * Required when backend is 'p2p'\n */\n p2p?: P2POptions;\n\n /** Create wallet if it doesn't exist (default: false) */\n createWalletIfNotExists?: boolean;\n\n /** Restore wallet from seed (hex string) */\n restoreFromSeed?: string;\n\n /**\n * Block height to start scanning from when restoring a wallet from seed.\n * This is the height when the wallet was originally created.\n * Setting this avoids scanning blocks before the wallet existed.\n *\n * Note: This option is only used when `restoreFromSeed` is provided.\n * For newly created wallets, the creation height is automatically set\n * to the current chain tip minus a safety margin (100 blocks).\n *\n * @default 0 (scan from genesis when restoring)\n */\n restoreFromHeight?: number;\n\n /**\n * Override the creation height for newly created wallets.\n * By default, new wallets use `chainTip - 100` to avoid scanning old blocks.\n * Set this to 0 to sync from genesis (useful for testing).\n *\n * Note: This is only used when `createWalletIfNotExists` is true and\n * no wallet exists. It does NOT override `restoreFromHeight` when\n * restoring from seed.\n */\n creationHeight?: number;\n\n /**\n * Network to use for address encoding/decoding and cryptographic operations.\n * This configures the navio-blsct library to use the correct chain parameters.\n *\n * @default 'mainnet'\n */\n network?: NetworkType;\n}\n\n/**\n * Navio SDK Client\n * Main client for wallet operations and blockchain synchronization.\n *\n * Supports two backend types:\n * - Electrum: Connect to an Electrum server (recommended for light wallets)\n * - P2P: Connect directly to a Navio full node (for advanced use cases)\n *\n * @example\n * // Using Electrum backend (recommended)\n * const client = new NavioClient({\n * walletDbPath: './wallet.db',\n * backend: 'electrum',\n * electrum: { host: 'electrum.example.com', port: 50001, ssl: true }\n * });\n *\n * @example\n * // Using P2P backend\n * const client = new NavioClient({\n * walletDbPath: './wallet.db',\n * backend: 'p2p',\n * p2p: { host: '127.0.0.1', port: 44440, network: 'mainnet' }\n * });\n *\n * @category Client\n */\nexport class NavioClient {\n private walletDB: WalletDB;\n private syncProvider: SyncProvider;\n private syncManager: TransactionKeysSync;\n private keyManager: KeyManager | null = null;\n private config: NavioClientConfig;\n private initialized = false;\n\n // Legacy: keep electrumClient reference for backwards compatibility\n private electrumClient: ElectrumClient | null = null;\n\n // Background sync state\n private backgroundSyncTimer: ReturnType<typeof setInterval> | null = null;\n private backgroundSyncOptions: BackgroundSyncOptions | null = null;\n private isBackgroundSyncing = false;\n private isSyncInProgress = false;\n private lastKnownBalance: bigint = 0n;\n\n /**\n * Create a new NavioClient instance\n * @param config - Client configuration\n */\n constructor(config: NavioClientConfig) {\n // Handle legacy config (just electrum, no backend specified)\n if ('electrum' in config && !('backend' in config)) {\n this.config = {\n ...config,\n backend: 'electrum',\n };\n } else {\n this.config = config as NavioClientConfig;\n }\n\n // Default to electrum if no backend specified\n this.config.backend = this.config.backend || 'electrum';\n\n // Default to mainnet if no network specified\n this.config.network = this.config.network || 'mainnet';\n\n // Configure navio-blsct for the correct network\n NavioClient.configureNetwork(this.config.network);\n\n // Validate config\n if (this.config.backend === 'electrum' && !this.config.electrum) {\n throw new Error('Electrum options required when backend is \"electrum\"');\n }\n if (this.config.backend === 'p2p' && !this.config.p2p) {\n throw new Error('P2P options required when backend is \"p2p\"');\n }\n\n // Initialize components\n this.walletDB = new WalletDB(this.config.walletDbPath);\n\n // Create sync provider based on backend type\n if (this.config.backend === 'p2p') {\n this.syncProvider = new P2PSyncProvider(this.config.p2p!);\n } else {\n // Electrum backend\n this.electrumClient = new ElectrumClient(this.config.electrum!);\n this.syncProvider = new ElectrumSyncProvider(this.config.electrum!);\n }\n\n this.syncManager = new TransactionKeysSync(this.walletDB, this.syncProvider);\n }\n\n /**\n * Configure the navio-blsct library for the specified network\n */\n private static configureNetwork(network: NetworkType): void {\n const chainMap: Record<NetworkType, BlsctChain> = {\n mainnet: BlsctChain.Mainnet,\n testnet: BlsctChain.Testnet,\n signet: BlsctChain.Signet,\n regtest: BlsctChain.Regtest,\n };\n\n setChain(chainMap[network]);\n }\n\n /**\n * Get the current network configuration\n */\n getNetwork(): NetworkType {\n return this.config.network || 'mainnet';\n }\n\n /**\n * Safety margin (in blocks) when setting creation height for new wallets.\n * This ensures we don't miss any transactions that might be in recent blocks.\n */\n private static readonly CREATION_HEIGHT_MARGIN = 100;\n\n /**\n * Initialize the client\n * Loads or creates wallet, connects to backend, and initializes sync manager\n */\n async initialize(): Promise<void> {\n if (this.initialized) {\n return;\n }\n\n // Load or create wallet\n if (this.config.restoreFromSeed) {\n // Restore from seed with user-provided height (or 0 to scan from genesis)\n this.keyManager = await this.walletDB.restoreWallet(\n this.config.restoreFromSeed,\n this.config.restoreFromHeight\n );\n\n // Set KeyManager for sync manager (enables output detection)\n this.syncManager.setKeyManager(this.keyManager);\n\n // Connect to backend\n await this.syncProvider.connect();\n } else {\n try {\n this.keyManager = await this.walletDB.loadWallet();\n\n // Set KeyManager for sync manager (enables output detection)\n this.syncManager.setKeyManager(this.keyManager);\n\n // Connect to backend\n await this.syncProvider.connect();\n } catch (error) {\n if (this.config.createWalletIfNotExists) {\n // Determine creation height\n let creationHeight: number;\n\n if (this.config.creationHeight !== undefined) {\n // Use explicitly provided creation height\n creationHeight = this.config.creationHeight;\n } else {\n // For new wallets, connect first to get the current chain height\n await this.syncProvider.connect();\n\n // Get current chain tip and subtract safety margin\n const chainTip = await this.syncProvider.getChainTipHeight();\n creationHeight = Math.max(0, chainTip - NavioClient.CREATION_HEIGHT_MARGIN);\n }\n\n // Create new wallet with specified height as creation point\n this.keyManager = await this.walletDB.createWallet(creationHeight);\n\n // Set KeyManager for sync manager (enables output detection)\n this.syncManager.setKeyManager(this.keyManager);\n } else {\n throw new Error(\n `Wallet not found at ${this.config.walletDbPath}. ` +\n `Set createWalletIfNotExists: true to create a new wallet.`\n );\n }\n }\n }\n\n // Initialize sync manager\n await this.syncManager.initialize();\n\n this.initialized = true;\n }\n\n /**\n * Get the backend type being used\n */\n getBackendType(): BackendType {\n return this.config.backend || 'electrum';\n }\n\n /**\n * Get the sync provider\n */\n getSyncProvider(): SyncProvider {\n return this.syncProvider;\n }\n\n /**\n * Get the KeyManager instance\n * @returns KeyManager instance\n */\n getKeyManager(): KeyManager {\n if (!this.keyManager) {\n throw new Error('Client not initialized. Call initialize() first.');\n }\n return this.keyManager;\n }\n\n /**\n * Get the WalletDB instance\n * @returns WalletDB instance\n */\n getWalletDB(): WalletDB {\n return this.walletDB;\n }\n\n /**\n * Get the ElectrumClient instance (only available when using electrum backend)\n * @returns ElectrumClient instance or null if using P2P backend\n * @deprecated Use getSyncProvider() instead for backend-agnostic code\n */\n getElectrumClient(): ElectrumClient | null {\n return this.electrumClient;\n }\n\n /**\n * Get the TransactionKeysSync instance\n * @returns TransactionKeysSync instance\n */\n getSyncManager(): TransactionKeysSync {\n return this.syncManager;\n }\n\n /**\n * Synchronize transaction keys from the backend.\n * \n * By default, syncs once to the current chain tip and returns.\n * Use `startBackgroundSync()` to enable continuous synchronization.\n * \n * @param options - Sync options\n * @returns Number of transaction keys synced\n */\n async sync(options?: SyncOptions): Promise<number> {\n if (!this.initialized) {\n await this.initialize();\n }\n\n return this.syncManager.sync(options || {});\n }\n\n // ============================================================\n // Background Sync Methods\n // ============================================================\n\n /**\n * Start continuous background synchronization.\n * \n * The client will poll for new blocks and automatically sync new transactions.\n * Callbacks are invoked for new blocks, transactions, and balance changes.\n * \n * @param options - Background sync options\n * \n * @example\n * ```typescript\n * await client.startBackgroundSync({\n * pollInterval: 10000, // Check every 10 seconds\n * onNewBlock: (height) => console.log(`New block: ${height}`),\n * onBalanceChange: (newBal, oldBal) => {\n * console.log(`Balance changed: ${Number(oldBal)/1e8} -> ${Number(newBal)/1e8} NAV`);\n * },\n * onError: (err) => console.error('Sync error:', err),\n * });\n * ```\n */\n async startBackgroundSync(options: BackgroundSyncOptions = {}): Promise<void> {\n if (this.isBackgroundSyncing) {\n return; // Already running\n }\n\n if (!this.initialized) {\n await this.initialize();\n }\n\n this.backgroundSyncOptions = {\n pollInterval: options.pollInterval ?? 10000,\n ...options,\n };\n this.isBackgroundSyncing = true;\n\n // Get initial balance\n this.lastKnownBalance = await this.getBalance();\n\n // Perform initial sync to tip\n await this.performBackgroundSync();\n\n // Start polling\n this.backgroundSyncTimer = setInterval(async () => {\n await this.performBackgroundSync();\n }, this.backgroundSyncOptions.pollInterval!);\n }\n\n /**\n * Stop background synchronization.\n */\n stopBackgroundSync(): void {\n if (this.backgroundSyncTimer) {\n clearInterval(this.backgroundSyncTimer);\n this.backgroundSyncTimer = null;\n }\n this.isBackgroundSyncing = false;\n this.backgroundSyncOptions = null;\n }\n\n /**\n * Check if background sync is running.\n * @returns True if background sync is active\n */\n isBackgroundSyncActive(): boolean {\n return this.isBackgroundSyncing;\n }\n\n /**\n * Perform a single background sync cycle.\n * Called by the polling timer.\n */\n private async performBackgroundSync(): Promise<void> {\n if (this.isSyncInProgress) {\n return; // Skip if sync already in progress\n }\n\n this.isSyncInProgress = true;\n const opts = this.backgroundSyncOptions;\n\n try {\n // Check if we need to sync\n const needsSync = await this.isSyncNeeded();\n \n if (!needsSync) {\n this.isSyncInProgress = false;\n return;\n }\n\n // Get current tip for onNewBlock callback\n const chainTip = await this.syncProvider.getChainTipHeight();\n const lastSynced = this.getLastSyncedHeight();\n\n // Sync to tip\n await this.syncManager.sync({\n onProgress: opts?.onProgress,\n saveInterval: opts?.saveInterval,\n verifyHashes: opts?.verifyHashes,\n keepTxKeys: opts?.keepTxKeys,\n blockHashRetention: opts?.blockHashRetention,\n });\n\n // Notify of new block(s) if we synced past our last known height\n if (opts?.onNewBlock && chainTip > lastSynced) {\n // Get the block hash for the tip\n try {\n const headerHex = await this.syncProvider.getBlockHeader(chainTip);\n const hash = this.hashBlockHeader(headerHex);\n opts.onNewBlock(chainTip, hash);\n } catch {\n opts.onNewBlock(chainTip, '');\n }\n }\n\n // Check for balance change\n if (opts?.onBalanceChange) {\n const newBalance = await this.getBalance();\n if (newBalance !== this.lastKnownBalance) {\n opts.onBalanceChange(newBalance, this.lastKnownBalance);\n this.lastKnownBalance = newBalance;\n }\n }\n\n } catch (error) {\n if (opts?.onError) {\n opts.onError(error as Error);\n }\n } finally {\n this.isSyncInProgress = false;\n }\n }\n\n /**\n * Check if synchronization is needed\n * @returns True if sync is needed\n */\n async isSyncNeeded(): Promise<boolean> {\n if (!this.initialized) {\n await this.initialize();\n }\n\n return this.syncManager.isSyncNeeded();\n }\n\n /**\n * Get last synced block height\n * @returns Last synced height, or -1 if never synced\n */\n getLastSyncedHeight(): number {\n return this.syncManager.getLastSyncedHeight();\n }\n\n /**\n * Get sync state\n * @returns Current sync state\n */\n getSyncState() {\n return this.syncManager.getSyncState();\n }\n\n /**\n * Get the wallet creation height (block height to start scanning from)\n * @returns Creation height or 0 if not set\n */\n async getCreationHeight(): Promise<number> {\n return this.walletDB.getCreationHeight();\n }\n\n /**\n * Set the wallet creation height\n * @param height - Block height when wallet was created\n */\n async setCreationHeight(height: number): Promise<void> {\n await this.walletDB.setCreationHeight(height);\n }\n\n /**\n * Get wallet metadata\n * @returns Wallet metadata or null if not available\n */\n async getWalletMetadata(): Promise<{\n creationHeight: number;\n creationTime: number;\n restoredFromSeed: boolean;\n version: number;\n } | null> {\n return this.walletDB.getWalletMetadata();\n }\n\n /**\n * Get chain tip from the backend\n * @returns Current chain tip height and hash\n */\n async getChainTip(): Promise<{ height: number; hash: string }> {\n if (!this.initialized) {\n await this.initialize();\n }\n\n const height = await this.syncProvider.getChainTipHeight();\n\n // For P2P provider, we can get the chain tip directly if available\n if (this.config.backend === 'p2p') {\n const p2pProvider = this.syncProvider as any;\n if (typeof p2pProvider.getChainTip === 'function') {\n return p2pProvider.getChainTip();\n }\n }\n\n // Fallback: try to get header at tip height\n try {\n const headerHex = await this.syncProvider.getBlockHeader(height);\n const hash = this.hashBlockHeader(headerHex);\n return { height, hash };\n } catch {\n // If we can't get the header, return height with empty hash\n return { height, hash: '' };\n }\n }\n\n /**\n * Disconnect from backend and close database\n */\n async disconnect(): Promise<void> {\n // Stop background sync if running\n this.stopBackgroundSync();\n\n if (this.syncProvider) {\n this.syncProvider.disconnect();\n }\n if (this.walletDB) {\n await this.walletDB.close();\n }\n this.initialized = false;\n }\n\n /**\n * Get the current configuration\n */\n getConfig(): NavioClientConfig {\n return { ...this.config };\n }\n\n /**\n * Check if client is connected to the backend\n */\n isConnected(): boolean {\n return this.syncProvider?.isConnected() ?? false;\n }\n\n /**\n * Hash a block header to get block hash\n */\n private hashBlockHeader(headerHex: string): string {\n const headerBytes = Buffer.from(headerHex, 'hex');\n const hash = sha256(sha256(headerBytes));\n return Buffer.from(hash).reverse().toString('hex');\n }\n\n // ============================================================\n // Wallet Balance & Output Methods\n // ============================================================\n\n /**\n * Get wallet balance in satoshis\n * @param tokenId - Optional token ID to filter by (null for NAV)\n * @returns Balance in satoshis as bigint\n */\n async getBalance(tokenId: string | null = null): Promise<bigint> {\n return this.walletDB.getBalance(tokenId);\n }\n\n /**\n * Get wallet balance in NAV (with decimals)\n * @param tokenId - Optional token ID to filter by (null for NAV)\n * @returns Balance as a number with 8 decimal places\n */\n async getBalanceNav(tokenId: string | null = null): Promise<number> {\n const balanceSatoshis = await this.getBalance(tokenId);\n return Number(balanceSatoshis) / 1e8;\n }\n\n /**\n * Get unspent outputs (UTXOs)\n * @param tokenId - Optional token ID to filter by (null for NAV)\n * @returns Array of unspent wallet outputs\n */\n async getUnspentOutputs(tokenId: string | null = null): Promise<import('./wallet-db').WalletOutput[]> {\n return this.walletDB.getUnspentOutputs(tokenId);\n }\n\n /**\n * Get all wallet outputs (spent and unspent)\n * @returns Array of all wallet outputs\n */\n async getAllOutputs(): Promise<import('./wallet-db').WalletOutput[]> {\n return this.walletDB.getAllOutputs();\n }\n}\n"]}
|