@babylonlabs-io/ts-sdk 0.33.4 → 0.33.6

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (54) hide show
  1. package/dist/buildAndBroadcastRefund-B332dykQ.cjs +2 -0
  2. package/dist/buildAndBroadcastRefund-B332dykQ.cjs.map +1 -0
  3. package/dist/{buildAndBroadcastRefund-D_QlvCsw.js → buildAndBroadcastRefund-CPjXNaMi.js} +126 -121
  4. package/dist/buildAndBroadcastRefund-CPjXNaMi.js.map +1 -0
  5. package/dist/index.cjs +1 -1
  6. package/dist/index.js +89 -87
  7. package/dist/tbv/core/clients/index.cjs +1 -1
  8. package/dist/tbv/core/clients/index.js +23 -21
  9. package/dist/tbv/core/clients/vault-provider/__tests__/batchAttribution.test.d.ts +2 -0
  10. package/dist/tbv/core/clients/vault-provider/__tests__/batchAttribution.test.d.ts.map +1 -0
  11. package/dist/tbv/core/clients/vault-provider/__tests__/batchPoll.test.d.ts +2 -0
  12. package/dist/tbv/core/clients/vault-provider/__tests__/batchPoll.test.d.ts.map +1 -0
  13. package/dist/tbv/core/clients/vault-provider/api.d.ts +13 -4
  14. package/dist/tbv/core/clients/vault-provider/api.d.ts.map +1 -1
  15. package/dist/tbv/core/clients/vault-provider/auth/serverIdentity.d.ts +12 -3
  16. package/dist/tbv/core/clients/vault-provider/auth/serverIdentity.d.ts.map +1 -1
  17. package/dist/tbv/core/clients/vault-provider/batchAttribution.d.ts +45 -0
  18. package/dist/tbv/core/clients/vault-provider/batchAttribution.d.ts.map +1 -0
  19. package/dist/tbv/core/clients/vault-provider/batchPoll.d.ts +55 -0
  20. package/dist/tbv/core/clients/vault-provider/batchPoll.d.ts.map +1 -0
  21. package/dist/tbv/core/clients/vault-provider/index.d.ts +2 -0
  22. package/dist/tbv/core/clients/vault-provider/index.d.ts.map +1 -1
  23. package/dist/tbv/core/clients/vault-provider/json-rpc-client.d.ts +3 -3
  24. package/dist/tbv/core/clients/vault-provider/json-rpc-client.d.ts.map +1 -1
  25. package/dist/tbv/core/clients/vault-provider/types.d.ts +68 -24
  26. package/dist/tbv/core/clients/vault-provider/types.d.ts.map +1 -1
  27. package/dist/tbv/core/clients/vault-provider/validators.d.ts +12 -2
  28. package/dist/tbv/core/clients/vault-provider/validators.d.ts.map +1 -1
  29. package/dist/tbv/core/index.cjs +1 -1
  30. package/dist/tbv/core/index.js +73 -71
  31. package/dist/tbv/core/services/deposit/waitForPeginStatus.d.ts.map +1 -1
  32. package/dist/tbv/core/services/index.cjs +1 -1
  33. package/dist/tbv/core/services/index.js +1 -1
  34. package/dist/tbv/core/services/pegout/state.d.ts +1 -1
  35. package/dist/tbv/index.cjs +1 -1
  36. package/dist/tbv/index.js +73 -71
  37. package/dist/types-DnyyBNcC.cjs +2 -0
  38. package/dist/types-DnyyBNcC.cjs.map +1 -0
  39. package/dist/{types-ByW6nSLj.js → types-TiIjyo2b.js} +32 -30
  40. package/dist/types-TiIjyo2b.js.map +1 -0
  41. package/dist/vault-registry-reader-DNiXOSYM.cjs +2 -0
  42. package/dist/vault-registry-reader-DNiXOSYM.cjs.map +1 -0
  43. package/dist/{vault-registry-reader-WiNVOsnD.js → vault-registry-reader-PsSxB0JZ.js} +439 -267
  44. package/dist/vault-registry-reader-PsSxB0JZ.js.map +1 -0
  45. package/package.json +1 -1
  46. package/dist/buildAndBroadcastRefund-CIPPpchL.cjs +0 -2
  47. package/dist/buildAndBroadcastRefund-CIPPpchL.cjs.map +0 -1
  48. package/dist/buildAndBroadcastRefund-D_QlvCsw.js.map +0 -1
  49. package/dist/types-ByW6nSLj.js.map +0 -1
  50. package/dist/types-CfCZyfid.cjs +0 -2
  51. package/dist/types-CfCZyfid.cjs.map +0 -1
  52. package/dist/vault-registry-reader-OK2V08tk.cjs +0 -2
  53. package/dist/vault-registry-reader-OK2V08tk.cjs.map +0 -1
  54. package/dist/vault-registry-reader-WiNVOsnD.js.map +0 -1
@@ -1 +0,0 @@
1
- {"version":3,"file":"buildAndBroadcastRefund-D_QlvCsw.js","sources":["../src/tbv/core/services/activation/activateVault.ts","../src/tbv/core/services/deposit/waitForPeginStatus.ts","../src/tbv/core/services/deposit/submitWotsPublicKey.ts","../src/tbv/core/services/deposit/signDepositorGraph.ts","../src/tbv/core/services/deposit/runDepositorPresignFlow.ts","../src/tbv/core/services/deposit/validation.ts","../src/tbv/core/services/pegout/state.ts","../src/tbv/core/services/refund/errors.ts","../src/tbv/core/services/refund/buildAndBroadcastRefund.ts"],"sourcesContent":["/**\n * Vault activation — reveal HTLC secret on Ethereum to move the vault from\n * Verified to Active. The on-chain contract validates `sha256(s) == hashlock`\n * and the activation deadline; this function pre-validates inputs (including\n * an optional hashlock check) and delegates the actual contract write to an\n * injected callback so the SDK stays transport-agnostic.\n *\n * @module services/activation\n */\n\nimport type { Abi, Address, Hash, Hex } from \"viem\";\n\nimport { BTCVaultRegistryABI } from \"../../contracts/abis/BTCVaultRegistry.abi\";\nimport { ensureHexPrefix } from \"../../primitives/utils/bitcoin\";\nimport { validateSecretAgainstHashlock } from \"../htlc\";\n\nconst BYTES32_HEX_RE = /^0x[0-9a-fA-F]{64}$/;\nconst ADDRESS_HEX_RE = /^0x[0-9a-fA-F]{40}$/;\n// ETH calldata convention: 0x prefix REQUIRED, even number of hex chars, may\n// be empty (\"0x\"). Named distinctly from the BTC-hex regex in\n// buildAndBroadcastRefund.ts (which allows an optional prefix and requires\n// non-empty) to make the convention explicit at the call site.\nconst ETH_HEX_BYTES_RE = /^0x([0-9a-fA-F]{2})*$/;\n\nfunction assertBytes32(value: string, label: string): void {\n if (value.length !== 66) {\n throw new Error(\n `${label} must be 32 bytes (66 hex chars with 0x prefix), got length ${value.length}`,\n );\n }\n if (!BYTES32_HEX_RE.test(value)) {\n throw new Error(\n `${label} must contain only hex characters after the 0x prefix`,\n );\n }\n}\n\nfunction assertAddress(value: string, label: string): void {\n if (!ADDRESS_HEX_RE.test(value)) {\n throw new Error(\n `${label} must be a 20-byte 0x-prefixed hex address (42 chars)`,\n );\n }\n}\n\nfunction assertHexBytes(value: string, label: string): void {\n if (!ETH_HEX_BYTES_RE.test(value)) {\n throw new Error(\n `${label} must be a 0x-prefixed hex string with an even number of hex chars`,\n );\n }\n}\n\n/**\n * A single ETH contract-write call. The SDK assembles these; the caller\n * executes them via viem, wagmi, a wallet provider, or any other transport.\n */\nexport interface EthContractWriteCall {\n address: Address;\n abi: Abi;\n functionName: string;\n args: readonly unknown[];\n}\n\n/**\n * Minimum shape the SDK requires from any contract-write result. Callers may\n * return richer objects (e.g. including the receipt) — the SDK propagates\n * them unchanged via the generic parameter on {@link EthContractWriter}.\n */\nexport interface EthContractWriteResult {\n transactionHash: Hash;\n}\n\n/**\n * Caller-provided contract writer. The generic `R` lets callers return any\n * transport-specific result shape (e.g. `{ transactionHash, receipt }`);\n * the SDK forwards that shape back through `activateVault`.\n */\nexport type EthContractWriter<R extends EthContractWriteResult = EthContractWriteResult> = (\n call: EthContractWriteCall,\n) => Promise<R>;\n\nexport interface ActivateVaultInput<\n R extends EthContractWriteResult = EthContractWriteResult,\n> {\n /** BTCVaultRegistry contract address (env-specific). */\n btcVaultRegistryAddress: Address;\n /** Vault ID (bytes32, 0x-prefixed). */\n vaultId: Hex;\n /**\n * HTLC secret preimage (bytes32). A missing `0x` prefix or an uppercase\n * `0X` prefix is normalised before validation.\n */\n secret: string;\n /**\n * Optional hashlock for client-side pre-validation. When provided, the SDK\n * rejects before calling `writeContract` if `sha256(secret) != hashlock`.\n */\n hashlock?: Hex;\n /**\n * Activation metadata passed through to the contract. Required to keep\n * the \"empty metadata\" convention explicit at the call site — pass `\"0x\"`\n * (empty bytes) when no metadata is needed. Must be a 0x-prefixed hex\n * string with an even number of hex chars.\n */\n activationMetadata: Hex;\n /** Caller-provided write callback — see {@link EthContractWriter}. */\n writeContract: EthContractWriter<R>;\n /**\n * Optional abort signal. Checked before validation runs; since validation\n * is fully synchronous, cancellation between validation and the write is\n * not observable and callers should rely on the transport's own\n * cancellation support for that window.\n */\n signal?: AbortSignal;\n}\n\n/**\n * Reveal the HTLC secret on Ethereum and activate the vault.\n *\n * Validates inputs, optionally pre-checks the secret against the expected\n * hashlock, and delegates the contract write to `writeContract`. Returns\n * whatever the writer returns so callers can keep richer transport-specific\n * metadata (e.g. viem receipts) end-to-end.\n *\n * @throws `Error` if `btcVaultRegistryAddress` is not a valid 20-byte address\n * @throws `Error` if `vaultId` or `secret` is not a valid 32-byte hex\n * @throws `Error` if `hashlock` is provided and is not a valid 32-byte hex,\n * or if `sha256(secret) != hashlock`\n * @throws `Error` if `activationMetadata` is not a 0x-prefixed hex byte\n * string (must have an even number of hex chars). Pass `\"0x\"` for\n * empty metadata.\n * @throws whatever the injected `writeContract` throws\n * @throws `AbortError` / caller-provided abort reason if `signal` aborts\n */\nexport async function activateVault<\n R extends EthContractWriteResult = EthContractWriteResult,\n>(input: ActivateVaultInput<R>): Promise<R> {\n const {\n btcVaultRegistryAddress,\n vaultId,\n hashlock,\n activationMetadata,\n writeContract,\n signal,\n } = input;\n\n signal?.throwIfAborted();\n\n assertAddress(btcVaultRegistryAddress, \"btcVaultRegistryAddress\");\n assertBytes32(vaultId, \"vaultId\");\n\n const normalizedSecret = ensureHexPrefix(input.secret);\n assertBytes32(normalizedSecret, \"secret\");\n\n if (hashlock !== undefined) {\n assertBytes32(hashlock, \"hashlock\");\n if (!validateSecretAgainstHashlock(normalizedSecret, hashlock)) {\n throw new Error(\n \"Invalid secret: SHA256(secret) does not match the provided hashlock\",\n );\n }\n }\n\n assertHexBytes(activationMetadata, \"activationMetadata\");\n\n return writeContract({\n address: btcVaultRegistryAddress,\n abi: BTCVaultRegistryABI,\n functionName: \"activateVaultWithSecret\",\n args: [vaultId, normalizedSecret, activationMetadata],\n });\n}\n","/**\n * Poll `getPeginStatus` until the VP reaches one of the target statuses.\n *\n * Pure polling utility with no framework dependencies (no localStorage, no React).\n * Handles \"PegIn not found\" as transient (VP hasn't ingested yet).\n */\n\nimport { JsonRpcError } from \"../../clients/vault-provider/json-rpc-client\";\nimport {\n RpcErrorCode,\n VP_TERMINAL_STATUSES,\n type DaemonStatus,\n} from \"../../clients/vault-provider/types\";\nimport type { PeginStatusReader } from \"./interfaces\";\n\n/** Default polling interval (10 seconds). */\nconst DEFAULT_POLL_INTERVAL_MS = 10_000;\n\nexport interface WaitForPeginStatusParams {\n /** VP client implementing the status reader interface */\n statusReader: PeginStatusReader;\n /** BTC pegin transaction ID (unprefixed hex, 64 chars) */\n peginTxid: string;\n /** Set of acceptable statuses — polling stops when the VP reports one of these */\n targetStatuses: ReadonlySet<DaemonStatus>;\n /** Maximum time to wait in milliseconds */\n timeoutMs: number;\n /** Polling interval in milliseconds (default: 10s) */\n pollIntervalMs?: number;\n /** AbortSignal for cancellation */\n signal?: AbortSignal;\n}\n\n/**\n * Poll `getPeginStatus` until the VP reaches one of the target statuses.\n *\n * @returns The DaemonStatus string that matched one of the targets\n * @throws Error on timeout, abort, or non-transient RPC error\n */\nexport async function waitForPeginStatus(\n params: WaitForPeginStatusParams,\n): Promise<DaemonStatus> {\n const {\n statusReader,\n peginTxid,\n targetStatuses,\n timeoutMs,\n pollIntervalMs = DEFAULT_POLL_INTERVAL_MS,\n signal,\n } = params;\n\n const startTime = Date.now();\n\n while (true) {\n if (signal?.aborted) {\n throw new Error(\n `Polling aborted for pegin ${peginTxid.slice(0, 8)}… (target: ${[...targetStatuses].join(\", \")})`,\n );\n }\n\n if (Date.now() - startTime >= timeoutMs) {\n throw new Error(\n `Polling timeout after ${timeoutMs}ms for pegin ${peginTxid.slice(0, 8)}… (target: ${[...targetStatuses].join(\", \")})`,\n );\n }\n\n try {\n const response = await statusReader.getPeginStatus(\n { pegin_txid: peginTxid },\n signal,\n );\n\n const status = response.status as DaemonStatus;\n if (targetStatuses.has(status)) {\n return status;\n }\n // Fail fast on terminal statuses to avoid waiting for timeout\n if (VP_TERMINAL_STATUSES.has(status) && !targetStatuses.has(status)) {\n throw new Error(\n `Pegin ${peginTxid.slice(0, 8)}… reached terminal status \"${status}\" while waiting for ${[...targetStatuses].join(\", \")}`,\n );\n }\n } catch (error) {\n // \"PegIn not found\" is transient — VP hasn't ingested the pegin yet.\n // Check structured error code first, fall back to message matching.\n const isNotFound =\n (error instanceof JsonRpcError &&\n error.code === RpcErrorCode.NOT_FOUND) ||\n (error instanceof Error && error.message.includes(\"PegIn not found\"));\n if (!isNotFound) {\n throw error;\n }\n }\n\n // Wait before next poll, with abort support\n await new Promise<void>((resolve, reject) => {\n const onAbort = () => {\n clearTimeout(timeoutId);\n reject(\n new Error(\n `Polling aborted for pegin ${peginTxid.slice(0, 8)}… (target: ${[...targetStatuses].join(\", \")})`,\n ),\n );\n };\n const timeoutId = setTimeout(() => {\n signal?.removeEventListener(\"abort\", onAbort);\n resolve();\n }, pollIntervalMs);\n signal?.addEventListener(\"abort\", onAbort, { once: true });\n });\n }\n}\n","/**\n * Submit pre-derived WOTS public keys to the vault provider.\n *\n * Polls `getPeginStatus` until the VP reaches `PendingDepositorWotsPK`,\n * then submits the keys. If the VP has already moved past WOTS step\n * (e.g., resume flow), submission is skipped.\n *\n * The caller is responsible for deriving WOTS keys externally using\n * `expandWotsSeed` + `deriveWotsBlocksFromSeed` from the SDK's\n * `tbv/core/vault-secrets` and `tbv/core/wots` modules respectively.\n */\n\nimport {\n DaemonStatus,\n POST_WOTS_STATUSES,\n type WotsBlockPublicKey,\n} from \"../../clients/vault-provider/types\";\nimport type { PeginStatusReader, WotsKeySubmitter } from \"./interfaces\";\nimport { waitForPeginStatus } from \"./waitForPeginStatus\";\n\n/** Maximum time to wait for VP to reach PendingDepositorWotsPK (5 min). */\nconst STATUS_POLL_TIMEOUT_MS = 5 * 60 * 1000;\n\n/** All statuses we accept — either ready for submission or already past it. */\nconst TARGET_STATUSES: ReadonlySet<DaemonStatus> = new Set([\n DaemonStatus.PENDING_DEPOSITOR_WOTS_PK,\n ...POST_WOTS_STATUSES,\n]);\n\nexport interface SubmitWotsPublicKeyParams {\n /** VP client implementing the status reader interface */\n statusReader: PeginStatusReader;\n /** VP client implementing the WOTS key submission interface */\n wotsSubmitter: WotsKeySubmitter;\n /** BTC pegin transaction ID (unprefixed hex, 64 chars) */\n peginTxid: string;\n /** Depositor's x-only BTC public key (unprefixed hex, 64 chars) */\n depositorPk: string;\n /** Pre-derived WOTS block public keys (one per assert block) */\n wotsPublicKeys: WotsBlockPublicKey[];\n /** Maximum time to wait for VP to be ready (default: 5 min) */\n timeoutMs?: number;\n /** AbortSignal for cancellation */\n signal?: AbortSignal;\n}\n\n/**\n * Submit WOTS public keys to the vault provider.\n *\n * @throws Error on timeout, abort, or RPC error\n */\nexport async function submitWotsPublicKey(\n params: SubmitWotsPublicKeyParams,\n): Promise<void> {\n const {\n statusReader,\n wotsSubmitter,\n peginTxid,\n depositorPk,\n wotsPublicKeys,\n timeoutMs = STATUS_POLL_TIMEOUT_MS,\n signal,\n } = params;\n\n signal?.throwIfAborted();\n\n // Wait until VP has ingested the pegin and is ready for the WOTS key.\n const status = await waitForPeginStatus({\n statusReader,\n peginTxid,\n targetStatuses: TARGET_STATUSES,\n timeoutMs,\n signal,\n });\n\n // Key was already submitted in a previous session (e.g. resume flow)\n if (POST_WOTS_STATUSES.has(status)) {\n return;\n }\n\n signal?.throwIfAborted();\n\n await wotsSubmitter.submitDepositorWotsKey(\n {\n pegin_txid: peginTxid,\n depositor_pk: depositorPk,\n wots_public_keys: wotsPublicKeys,\n },\n signal,\n );\n}\n","/**\n * Depositor Graph Signing Service\n *\n * Signs the depositor's own graph transactions (Payout, NoPayout per challenger)\n * for the depositor-as-claimer flow.\n *\n * Both PSBTs are constructed locally from authoritative on-chain connector\n * parameters and the VP-advertised transaction hexes (which are themselves\n * cross-checked against on-chain or protocol-defined sinks). Building PSBTs\n * locally is essential: every field that enters the Taproot sighash\n * (witnessUtxo, tapLeafScript, controlBlock, tapInternalKey) must come from\n * trusted sources, otherwise a malicious VP could substitute metadata that\n * makes the depositor's signature valid for a different spend.\n *\n * Transaction counts: 1 Payout + N NoPayout = 1 + N total PSBTs.\n *\n * @see btc-vault docs/pegin.md - \"Automatic Graph Creation & Presigning\"\n * @see btc-vault crates/vault/src/transactions/nopayout.rs - NoPayout structure\n */\n\nimport { type Network } from \"@babylonlabs-io/babylon-tbv-rust-wasm\";\nimport { Transaction } from \"bitcoinjs-lib\";\n\nimport type { BitcoinWallet, SignPsbtOptions } from \"../../../../shared/wallets/interfaces\";\nimport type {\n DepositorAsClaimerPresignatures,\n DepositorGraphTransactions,\n DepositorPreSigsPerChallenger,\n PresignDataPerChallenger,\n} from \"../../clients/vault-provider/types\";\nimport {\n assertNoPayoutOutputMatchesChallenger,\n buildNoPayoutPsbt,\n} from \"../../primitives/psbt/noPayout\";\nimport {\n assertPayoutOutputMatchesRegistered,\n buildPayoutPsbt,\n extractPayoutSignature,\n} from \"../../primitives/psbt/payout\";\nimport {\n stripHexPrefix,\n uint8ArrayToHex,\n} from \"../../primitives/utils/bitcoin\";\nimport { createTaprootScriptPathSignOptions } from \"../../utils/signing\";\n\n/**\n * The depositor signs exactly one input (index 0) per payout/nopayout PSBT.\n * Used to construct SignPsbtOptions for wallet.signPsbt(). PSBTs may carry\n * additional inputs (the payout PSBT includes the assert prevout; the nopayout\n * PSBT includes the two ChallengeAssert prevouts) so the Taproot SIGHASH_DEFAULT\n * sighash commits to all prevouts, but those inputs are not signed by the\n * depositor.\n */\nconst DEPOSITOR_SIGNED_INPUT_COUNT = 1;\n\n/** Tracks which indices in the flat PSBT array belong to which challenger */\ninterface ChallengerEntry {\n challengerPubkey: string;\n noPayoutIdx: number;\n}\n\n/** Result of the collect phase - flat PSBT array with index mapping */\ninterface CollectedDepositorGraphPsbts {\n psbtHexes: string[];\n signOptions: SignPsbtOptions[];\n challengerEntries: ChallengerEntry[];\n}\n\n// ============================================================================\n// Helpers\n// ============================================================================\n\n/**\n * Compute the local-challenger set for the depositor-as-claimer flow.\n *\n * Per the protocol (see btc-vault crates/vault/src/lib.rs - `LocalChallengers`):\n * localChallengers = {VaultProvider, VaultKeepers} \\ {Claimer}\n *\n * For the depositor-as-claimer flow the claimer is the depositor, so this\n * removes the depositor from the union if present (it usually isn't).\n * The protocol guarantees the result is non-empty by construction.\n */\nfunction deriveLocalChallengers(\n vaultProviderBtcPubkey: string,\n vaultKeeperBtcPubkeys: string[],\n depositorBtcPubkey: string,\n): string[] {\n const depositor = stripHexPrefix(depositorBtcPubkey).toLowerCase();\n const all = [vaultProviderBtcPubkey, ...vaultKeeperBtcPubkeys].map((k) =>\n stripHexPrefix(k).toLowerCase(),\n );\n const filtered = all.filter((k) => k !== depositor);\n if (filtered.length === 0) {\n throw new Error(\n \"Cannot derive localChallengers: removing depositor from {vaultProvider, vaultKeepers} left an empty set\",\n );\n }\n return filtered;\n}\n\n/**\n * Read the txid that the given input references in the unsigned tx, in display\n * (big-endian) hex order. bitcoinjs-lib stores `input.hash` in internal\n * little-endian byte order, which is the reverse of how txids are normally\n * displayed.\n */\nfunction readInputTxid(tx: Transaction, inputIndex: number): string {\n const input = tx.ins[inputIndex];\n return uint8ArrayToHex(new Uint8Array(input.hash).slice().reverse());\n}\n\n/**\n * Verify the noPayout transaction's input at `inputIndex` references the\n * given parent transaction at vout 0 (per nopayout.rs the layout is fixed:\n * Assert:0, ChallengeAssertX:0, ChallengeAssertY:0).\n */\nfunction assertInputReferencesParent(\n noPayoutTx: Transaction,\n inputIndex: number,\n parentTx: Transaction,\n parentLabel: string,\n challengerPubkey: string,\n): void {\n const input = noPayoutTx.ins[inputIndex];\n if (input.index !== 0) {\n throw new Error(\n `NoPayout (challenger ${challengerPubkey}) input ${inputIndex} expected to spend ${parentLabel} vout 0, got vout ${input.index}`,\n );\n }\n const parentTxid = parentTx.getId();\n const inputTxid = readInputTxid(noPayoutTx, inputIndex);\n if (inputTxid !== parentTxid) {\n throw new Error(\n `NoPayout (challenger ${challengerPubkey}) input ${inputIndex} does not reference ${parentLabel} (expected txid ${parentTxid}, got ${inputTxid})`,\n );\n }\n}\n\n// ============================================================================\n// Collect phase\n// ============================================================================\n\n/**\n * Build the depositor's payout PSBT and per-challenger NoPayout PSBTs locally\n * from authoritative connector params.\n *\n * Layout of returned arrays: [Payout, NoPayout_0, NoPayout_1, ...]\n */\nasync function collectDepositorGraphPsbts(\n depositorGraph: DepositorGraphTransactions,\n walletPublicKey: string,\n ctx: DepositorGraphSigningContext,\n): Promise<CollectedDepositorGraphPsbts> {\n const psbtHexes: string[] = [];\n const signOptions: SignPsbtOptions[] = [];\n const challengerEntries: ChallengerEntry[] = [];\n\n // 1. Validate the payout transaction's largest output pays to the\n // depositor's on-chain registered payout scriptPubKey. The payout tx\n // hex is supplied by the VP and otherwise unconstrained; this assertion\n // pins the destination of the funds.\n assertPayoutOutputMatchesRegistered(\n depositorGraph.payout_tx.tx_hex,\n ctx.registeredPayoutScriptPubKey,\n );\n\n // 2. Build the payout PSBT locally. Every sighash-relevant field\n // (witnessUtxo, tapLeafScript, controlBlock, tapInternalKey) is derived\n // from on-chain trusted connector params, not from the VP. The VP-\n // supplied assert tx hex is implicitly pinned by buildPayoutPsbt's\n // input-1 txid check against payoutTx.ins[1].hash.\n const builtPayout = await buildPayoutPsbt({\n payoutTxHex: depositorGraph.payout_tx.tx_hex,\n peginTxHex: ctx.peginTxHex,\n assertTxHex: depositorGraph.assert_tx.tx_hex,\n depositorBtcPubkey: ctx.depositorBtcPubkey,\n vaultProviderBtcPubkey: ctx.vaultProviderBtcPubkey,\n vaultKeeperBtcPubkeys: ctx.vaultKeeperBtcPubkeys,\n universalChallengerBtcPubkeys: ctx.universalChallengerBtcPubkeys,\n timelockPegin: ctx.timelockPegin,\n network: ctx.network,\n });\n psbtHexes.push(builtPayout.psbtHex);\n signOptions.push(\n createTaprootScriptPathSignOptions(\n walletPublicKey,\n DEPOSITOR_SIGNED_INPUT_COUNT,\n ),\n );\n\n // 3. Per-challenger: build the NoPayout PSBT locally too.\n const localChallengers = deriveLocalChallengers(\n ctx.vaultProviderBtcPubkey,\n ctx.vaultKeeperBtcPubkeys,\n ctx.depositorBtcPubkey,\n );\n const claimerPubkey = stripHexPrefix(ctx.depositorBtcPubkey);\n const assertTxParsed = Transaction.fromHex(\n stripHexPrefix(depositorGraph.assert_tx.tx_hex),\n );\n\n for (const challenger of depositorGraph.challenger_presign_data) {\n const challengerPubkey = stripHexPrefix(challenger.challenger_pubkey);\n\n const noPayoutIdx = psbtHexes.length;\n const noPayoutHex = await buildLocalNoPayoutPsbt({\n challenger,\n challengerPubkey,\n claimerPubkey,\n localChallengers,\n assertTxParsed,\n ctx,\n });\n psbtHexes.push(noPayoutHex);\n signOptions.push(\n createTaprootScriptPathSignOptions(\n walletPublicKey,\n DEPOSITOR_SIGNED_INPUT_COUNT,\n ),\n );\n\n challengerEntries.push({\n challengerPubkey,\n noPayoutIdx,\n });\n }\n\n return { psbtHexes, signOptions, challengerEntries };\n}\n\ninterface BuildLocalNoPayoutPsbtParams {\n challenger: PresignDataPerChallenger;\n challengerPubkey: string;\n claimerPubkey: string;\n localChallengers: string[];\n assertTxParsed: Transaction;\n ctx: DepositorGraphSigningContext;\n}\n\n/**\n * Build a single NoPayout PSBT for one challenger from authoritative\n * inputs. Validates the VP-supplied parent transactions match what the\n * NoPayout transaction commits to via input txids, and asserts the output\n * pays to the protocol-defined challenger sink before returning.\n *\n * NoPayout transaction layout (per\n * btc-vault crates/vault/src/transactions/nopayout.rs):\n * - 3 inputs (fixed order):\n * - Input 0: Assert tx output 0 (depositor signs - NoPayout path)\n * - Input 1: ChallengeAssertX tx output 0 (with timelock)\n * - Input 2: ChallengeAssertY tx output 0 (with timelock)\n * - 1 output: BIP-86 P2TR to the challenger\n */\nasync function buildLocalNoPayoutPsbt(\n params: BuildLocalNoPayoutPsbtParams,\n): Promise<string> {\n const {\n challenger,\n challengerPubkey,\n claimerPubkey,\n localChallengers,\n assertTxParsed,\n ctx,\n } = params;\n\n // Pin the output sink before doing any sighash-relevant work.\n assertNoPayoutOutputMatchesChallenger(\n challenger.nopayout_tx.tx_hex,\n challengerPubkey,\n ctx.network,\n );\n\n // Parse the NoPayout tx and the two ChallengeAssert parents.\n const noPayoutTx = Transaction.fromHex(\n stripHexPrefix(challenger.nopayout_tx.tx_hex),\n );\n const challengeAssertXTx = Transaction.fromHex(\n stripHexPrefix(challenger.challenge_assert_x_tx.tx_hex),\n );\n const challengeAssertYTx = Transaction.fromHex(\n stripHexPrefix(challenger.challenge_assert_y_tx.tx_hex),\n );\n\n if (noPayoutTx.ins.length !== 3) {\n throw new Error(\n `NoPayout (challenger ${challengerPubkey}) must have exactly 3 inputs, got ${noPayoutTx.ins.length}`,\n );\n }\n\n // Pin every input's parent. Each parent's outs[0] is the authoritative\n // prevout - because we verified the parent's txid matches what the NoPayout\n // tx commits to, the parent cannot be substituted without changing the\n // NoPayout txid.\n assertInputReferencesParent(\n noPayoutTx,\n 0,\n assertTxParsed,\n \"Assert\",\n challengerPubkey,\n );\n assertInputReferencesParent(\n noPayoutTx,\n 1,\n challengeAssertXTx,\n \"ChallengeAssertX\",\n challengerPubkey,\n );\n assertInputReferencesParent(\n noPayoutTx,\n 2,\n challengeAssertYTx,\n \"ChallengeAssertY\",\n challengerPubkey,\n );\n\n const prevouts = [\n assertTxParsed.outs[0],\n challengeAssertXTx.outs[0],\n challengeAssertYTx.outs[0],\n ].map((out) => ({\n script_pubkey: uint8ArrayToHex(new Uint8Array(out.script)),\n value: out.value,\n }));\n\n return buildNoPayoutPsbt({\n noPayoutTxHex: challenger.nopayout_tx.tx_hex,\n challengerPubkey,\n prevouts,\n connectorParams: {\n claimer: claimerPubkey,\n localChallengers,\n universalChallengers: ctx.universalChallengerBtcPubkeys,\n timelockAssert: ctx.timelockAssert,\n councilMembers: ctx.councilMembers,\n councilQuorum: ctx.councilQuorum,\n },\n });\n}\n\n// ============================================================================\n// Extract phase\n// ============================================================================\n\n/**\n * Extract all signatures from signed PSBTs and assemble into presignatures.\n */\nfunction extractDepositorGraphSignatures(\n signedPsbtHexes: string[],\n challengerEntries: ChallengerEntry[],\n depositorPubkey: string,\n): DepositorAsClaimerPresignatures {\n const payoutSignature = extractPayoutSignature(\n signedPsbtHexes[0],\n depositorPubkey,\n );\n\n const perChallenger: Record<string, DepositorPreSigsPerChallenger> = {};\n for (const entry of challengerEntries) {\n perChallenger[entry.challengerPubkey] = {\n nopayout_signature: extractPayoutSignature(\n signedPsbtHexes[entry.noPayoutIdx],\n depositorPubkey,\n ),\n };\n }\n\n return {\n payout_signatures: {\n payout_signature: payoutSignature,\n },\n per_challenger: perChallenger,\n };\n}\n\n/**\n * Sign multiple PSBTs, using batch signing when the wallet supports it.\n * Falls back to sequential `signPsbt` calls for wallets without `signPsbts`.\n */\nasync function signPsbtsWithFallback(\n wallet: BitcoinWallet,\n psbtHexes: string[],\n options?: SignPsbtOptions[],\n): Promise<string[]> {\n if (typeof wallet.signPsbts === \"function\") {\n return wallet.signPsbts(psbtHexes, options);\n }\n\n const signed: string[] = [];\n for (let i = 0; i < psbtHexes.length; i++) {\n signed.push(await wallet.signPsbt(psbtHexes[i], options?.[i]));\n }\n return signed;\n}\n\n// ============================================================================\n// Main entry point\n// ============================================================================\n\n/**\n * Authoritative inputs required to construct the depositor's Payout AND every\n * per-challenger NoPayout PSBT locally. Every field here must come from\n * trusted on-chain sources, not from the vault provider response. They feed\n * directly into the Taproot sighash.\n */\nexport interface DepositorGraphSigningContext {\n /** Raw pegin BTC transaction hex (provides the depositor's signed prevout) */\n peginTxHex: string;\n /** Depositor's BTC public key (x-only, 64-char hex, no 0x prefix) */\n depositorBtcPubkey: string;\n /** Vault provider's BTC public key (x-only hex, no prefix) */\n vaultProviderBtcPubkey: string;\n /** Sorted vault keeper BTC public keys (x-only hex, no prefix) */\n vaultKeeperBtcPubkeys: string[];\n /** Sorted universal challenger BTC public keys (x-only hex, no prefix) */\n universalChallengerBtcPubkeys: string[];\n /** Pegin CSV timelock from the locked offchain params version (blocks) */\n timelockPegin: number;\n /**\n * Assert CSV timelock from the locked offchain params version (blocks).\n * Sourced from the on-chain ProtocolParams contract via\n * `ViemProtocolParamsReader.getOffchainParamsByVersion(...).timelockAssert`.\n */\n timelockAssert: number;\n /**\n * Security council member x-only public keys (hex, no prefix). Sourced from\n * the on-chain ProtocolParams contract via\n * `ViemProtocolParamsReader.getOffchainParamsByVersion(...).securityCouncilKeys`.\n */\n councilMembers: string[];\n /**\n * M-of-N council quorum threshold. Sourced from the on-chain ProtocolParams\n * contract via `ViemProtocolParamsReader.getOffchainParamsByVersion(...).councilQuorum`.\n */\n councilQuorum: number;\n /** BTC network (Mainnet, Testnet, etc.) */\n network: Network;\n /**\n * On-chain registered depositor payout scriptPubKey (hex, with or without\n * 0x prefix). Used to assert the VP-advertised payout transaction pays to\n * the depositor's registered address before the wallet produces a signature.\n */\n registeredPayoutScriptPubKey: string;\n}\n\nexport interface SignDepositorGraphParams {\n /** The depositor graph from VP response */\n depositorGraph: DepositorGraphTransactions;\n /** Bitcoin wallet for signing */\n btcWallet: BitcoinWallet;\n /** Authoritative inputs used to rebuild every PSBT locally */\n signingContext: DepositorGraphSigningContext;\n}\n\n/**\n * Sign all depositor graph transactions and assemble into presignatures.\n *\n * Flow:\n * 1. Build payout + per-challenger nopayout PSBTs locally\n * 2. Batch sign via wallet.signPsbts() if available, else sequential signPsbt()\n * 3. Extract Schnorr signatures from each signed PSBT\n * 4. Assemble into DepositorAsClaimerPresignatures\n */\nexport async function signDepositorGraph(\n params: SignDepositorGraphParams,\n): Promise<DepositorAsClaimerPresignatures> {\n const { depositorGraph, btcWallet, signingContext } = params;\n\n const depositorPubkey = stripHexPrefix(signingContext.depositorBtcPubkey);\n const walletPublicKey = await btcWallet.getPublicKeyHex();\n\n // 1. Build all PSBTs locally\n const { psbtHexes, signOptions, challengerEntries } =\n await collectDepositorGraphPsbts(\n depositorGraph,\n walletPublicKey,\n signingContext,\n );\n\n // 2. Sign all PSBTs (batch when supported, sequential fallback for mobile)\n const signedPsbtHexes = await signPsbtsWithFallback(\n btcWallet,\n psbtHexes,\n signOptions,\n );\n\n if (signedPsbtHexes.length !== psbtHexes.length) {\n throw new Error(\n `Wallet returned ${signedPsbtHexes.length} signed PSBTs, expected ${psbtHexes.length}`,\n );\n }\n\n // 3. Extract signatures and assemble presignatures\n return extractDepositorGraphSignatures(\n signedPsbtHexes,\n challengerEntries,\n depositorPubkey,\n );\n}\n","/**\n * Payout Signing Orchestration\n *\n * Polls VP for `PendingDepositorSignatures`, fetches presign transactions,\n * signs payouts via PayoutManager, signs the depositor graph, and submits\n * all signatures back to the VP.\n *\n * This is the main deposit protocol step between registration and activation.\n */\n\nimport type { Network } from \"@babylonlabs-io/babylon-tbv-rust-wasm\";\nimport * as bitcoin from \"bitcoinjs-lib\";\nimport { Buffer } from \"buffer\";\n\nimport type { BitcoinWallet } from \"../../../../shared/wallets/interfaces\";\nimport { DaemonStatus } from \"../../clients/vault-provider/types\";\nimport type {\n ClaimerSignatures,\n ClaimerTransactions,\n} from \"../../clients/vault-provider/types\";\nimport { PayoutManager } from \"../../managers/PayoutManager\";\nimport {\n processPublicKeyToXOnly,\n stripHexPrefix,\n} from \"../../primitives/utils/bitcoin\";\nimport type { PeginStatusReader, PresignClient } from \"./interfaces\";\nimport { signDepositorGraph } from \"./signDepositorGraph\";\nimport { waitForPeginStatus } from \"./waitForPeginStatus\";\n\n// ============================================================================\n// Types\n// ============================================================================\n\n/**\n * Context required for signing payout transactions.\n * Caller builds this from on-chain data (contract queries, GraphQL, config).\n */\nexport interface PayoutSigningContext {\n /** Raw pegin BTC transaction hex (for PSBT construction) */\n peginTxHex: string;\n /** Vault provider's BTC public key (x-only hex, no prefix) */\n vaultProviderBtcPubkey: string;\n /** Sorted vault keeper BTC public keys (x-only hex, no prefix) */\n vaultKeeperBtcPubkeys: string[];\n /** Sorted universal challenger BTC public keys (x-only hex, no prefix) */\n universalChallengerBtcPubkeys: string[];\n /** Depositor's BTC public key (x-only hex, no prefix) */\n depositorBtcPubkey: string;\n /** Pegin timelock from the locked offchain params version */\n timelockPegin: number;\n /**\n * Assert CSV timelock from the locked offchain params version (blocks).\n * Source: ProtocolParams contract via\n * `ViemProtocolParamsReader.getOffchainParamsByVersion(...).timelockAssert`.\n * Required for the depositor-graph NoPayout local rebuild.\n */\n timelockAssert: number;\n /**\n * Security council member x-only public keys (hex, no prefix).\n * Source: ProtocolParams contract via\n * `getOffchainParamsByVersion(...).securityCouncilKeys`.\n * Required for the depositor-graph NoPayout local rebuild.\n */\n councilMembers: string[];\n /**\n * M-of-N council quorum threshold.\n * Source: ProtocolParams contract via\n * `getOffchainParamsByVersion(...).councilQuorum`.\n * Required for the depositor-graph NoPayout local rebuild.\n */\n councilQuorum: number;\n /** BTC network (Mainnet, Testnet, etc.) */\n network: Network;\n /** On-chain registered depositor payout scriptPubKey (hex) */\n registeredPayoutScriptPubKey: string;\n}\n\nexport interface RunDepositorPresignFlowParams {\n /** VP client implementing the status reader interface */\n statusReader: PeginStatusReader;\n /** VP client implementing the presign transaction flow interface */\n presignClient: PresignClient;\n /** Bitcoin wallet for signing */\n btcWallet: BitcoinWallet;\n /** BTC pegin transaction ID (unprefixed hex, 64 chars) */\n peginTxid: string;\n /** Depositor's x-only BTC public key (unprefixed hex, 64 chars) */\n depositorPk: string;\n /** Signing context built from on-chain data */\n signingContext: PayoutSigningContext;\n /** Maximum polling timeout in milliseconds (default: 20 min) */\n timeoutMs?: number;\n /** AbortSignal for cancellation */\n signal?: AbortSignal;\n /** Optional progress callback (completed claimers, total claimers) */\n onProgress?: (completed: number, total: number) => void;\n}\n\n// ============================================================================\n// Constants\n// ============================================================================\n\n/** Maximum polling timeout (20 minutes) — VP may take 15-20 min to prepare. */\nconst MAX_POLLING_TIMEOUT_MS = 20 * 60 * 1000;\n\n/** Statuses after payout signatures are submitted — if VP is already here, skip. */\nconst POST_PAYOUT_STATUSES: ReadonlySet<DaemonStatus> = new Set([\n DaemonStatus.PENDING_ACKS,\n DaemonStatus.PENDING_ACTIVATION,\n DaemonStatus.ACTIVATED,\n]);\n\nconst TARGET_STATUS: ReadonlySet<DaemonStatus> = new Set([\n DaemonStatus.PENDING_DEPOSITOR_SIGNATURES,\n ...POST_PAYOUT_STATUSES,\n]);\n\n// ============================================================================\n// Internal helpers\n// ============================================================================\n\ninterface PreparedTransaction {\n claimerPubkeyXOnly: string;\n payoutTxHex: string;\n assertTxHex: string;\n}\n\nfunction prepareTransactionsForSigning(\n claimerTransactions: ClaimerTransactions[],\n): PreparedTransaction[] {\n return claimerTransactions.map((tx) => ({\n claimerPubkeyXOnly: processPublicKeyToXOnly(tx.claimer_pubkey),\n payoutTxHex: tx.payout_tx.tx_hex,\n assertTxHex: tx.assert_tx.tx_hex,\n }));\n}\n\n/**\n * Derive BIP-86 P2TR scriptPubKey hex from an x-only public key.\n * Requires bitcoinjs-lib ECC to be initialized by the caller.\n */\nfunction deriveBip86ScriptPubKey(xOnlyPubkeyHex: string): string {\n const { output } = bitcoin.payments.p2tr({\n internalPubkey: Buffer.from(xOnlyPubkeyHex, \"hex\"),\n });\n if (!output) {\n throw new Error(\"Failed to derive BIP-86 P2TR scriptPubKey\");\n }\n return output.toString(\"hex\");\n}\n\n/**\n * Resolve the expected payout scriptPubKey for a given claimer.\n *\n * - VP/Depositor claimer: payout goes to the depositor's registered payout address\n * - VK claimer: payout goes to a BIP-86 P2TR address derived from the VK's pubkey\n *\n * Note: BIP-86 derivation for VK claimers requires bitcoinjs-lib's ECC to be initialized.\n */\nfunction resolvePayoutScriptPubKey(\n claimerPubkeyXOnly: string,\n context: PayoutSigningContext,\n): string {\n const claimer = stripHexPrefix(claimerPubkeyXOnly).toLowerCase();\n const vpPubkey = stripHexPrefix(\n context.vaultProviderBtcPubkey,\n ).toLowerCase();\n const depositorPubkey = stripHexPrefix(\n context.depositorBtcPubkey,\n ).toLowerCase();\n\n if (claimer === vpPubkey || claimer === depositorPubkey) {\n return context.registeredPayoutScriptPubKey;\n }\n\n // Verify claimer is a known vault keeper\n const isVaultKeeper = context.vaultKeeperBtcPubkeys.some(\n (vk) => stripHexPrefix(vk).toLowerCase() === claimer,\n );\n if (!isVaultKeeper) {\n throw new Error(\n `Unknown claimer pubkey ${claimer}: not VP, depositor, or a registered vault keeper`,\n );\n }\n\n // VK claimer: derive BIP-86 P2TR scriptPubKey from the VK's x-only pubkey\n const scriptPubKey = deriveBip86ScriptPubKey(claimer);\n return `0x${scriptPubKey}`;\n}\n\nfunction buildPayoutSigningInput(\n tx: PreparedTransaction,\n context: PayoutSigningContext,\n) {\n return {\n payoutTxHex: tx.payoutTxHex,\n peginTxHex: context.peginTxHex,\n assertTxHex: tx.assertTxHex,\n vaultProviderBtcPubkey: context.vaultProviderBtcPubkey,\n vaultKeeperBtcPubkeys: context.vaultKeeperBtcPubkeys,\n universalChallengerBtcPubkeys: context.universalChallengerBtcPubkeys,\n depositorBtcPubkey: context.depositorBtcPubkey,\n timelockPegin: context.timelockPegin,\n registeredPayoutScriptPubKey: resolvePayoutScriptPubKey(\n tx.claimerPubkeyXOnly,\n context,\n ),\n };\n}\n\n/**\n * Sign all payout transactions using PayoutManager.\n * Uses batch signing when wallet supports it, sequential otherwise.\n */\nasync function signPayoutTransactions(\n btcWallet: BitcoinWallet,\n context: PayoutSigningContext,\n transactions: PreparedTransaction[],\n onProgress?: (completed: number, total: number) => void,\n): Promise<Record<string, ClaimerSignatures>> {\n const payoutManager = new PayoutManager({\n network: context.network,\n btcWallet,\n });\n\n const totalClaimers = transactions.length;\n onProgress?.(0, totalClaimers);\n\n let payoutSignatures: string[];\n\n if (payoutManager.supportsBatchSigning()) {\n const results = await payoutManager.signPayoutTransactionsBatch(\n transactions.map((tx) => buildPayoutSigningInput(tx, context)),\n );\n payoutSignatures = results.map((r) => r.payoutSignature);\n } else {\n payoutSignatures = [];\n for (let i = 0; i < transactions.length; i++) {\n onProgress?.(i, totalClaimers);\n const result = await payoutManager.signPayoutTransaction(\n buildPayoutSigningInput(transactions[i], context),\n );\n payoutSignatures.push(result.signature);\n }\n }\n\n const signatures: Record<string, ClaimerSignatures> = {};\n for (let i = 0; i < transactions.length; i++) {\n signatures[transactions[i].claimerPubkeyXOnly] = {\n payout_signature: payoutSignatures[i],\n };\n }\n\n onProgress?.(totalClaimers, totalClaimers);\n return signatures;\n}\n\n// ============================================================================\n// Main entry point\n// ============================================================================\n\n/**\n * Poll for payout transactions, sign them, sign the depositor graph,\n * and submit all signatures to the vault provider.\n *\n * This is the main deposit protocol step between registration and activation.\n *\n * @throws Error on timeout, abort, signing failure, or RPC error\n */\nexport async function runDepositorPresignFlow(\n params: RunDepositorPresignFlowParams,\n): Promise<void> {\n const {\n statusReader,\n presignClient,\n btcWallet,\n peginTxid,\n depositorPk,\n signingContext,\n timeoutMs = MAX_POLLING_TIMEOUT_MS,\n signal,\n onProgress,\n } = params;\n\n // Phase 1: Poll until VP is ready for depositor signatures (or already past)\n const status = await waitForPeginStatus({\n statusReader,\n peginTxid,\n targetStatuses: TARGET_STATUS,\n timeoutMs,\n signal,\n });\n\n // Resume-safe: if VP already moved past payout signing, nothing to do\n if (POST_PAYOUT_STATUSES.has(status)) {\n return;\n }\n\n signal?.throwIfAborted();\n\n // Phase 2: Fetch presign transactions\n const response = await presignClient.requestDepositorPresignTransactions(\n {\n pegin_txid: peginTxid,\n depositor_pk: depositorPk,\n },\n signal,\n );\n\n signal?.throwIfAborted();\n\n // Phase 3: Sign VP/VK claimer payout transactions\n // Filter out the depositor's own claimer entry — its payout is signed\n // separately via signDepositorGraph (Phase 4) using VP-provided PSBTs.\n // Including it here would cause a redundant wallet signing prompt whose\n // result is discarded when the depositor graph signature overwrites it.\n const depositorPkNormalized = processPublicKeyToXOnly(depositorPk);\n const nonDepositorTxs = response.txs.filter(\n (tx) => processPublicKeyToXOnly(tx.claimer_pubkey) !== depositorPkNormalized,\n );\n const preparedTransactions = prepareTransactionsForSigning(nonDepositorTxs);\n const claimerSignatures = await signPayoutTransactions(\n btcWallet,\n signingContext,\n preparedTransactions,\n onProgress,\n );\n\n signal?.throwIfAborted();\n\n // Phase 4: Sign depositor-as-claimer graph. Both Payout and per-challenger\n // NoPayout PSBTs are rebuilt locally inside signDepositorGraph from these\n // authoritative connector params and the on-chain protocol parameters.\n const depositorClaimerPresignatures = await signDepositorGraph({\n depositorGraph: response.depositor_graph,\n btcWallet,\n signingContext: {\n peginTxHex: signingContext.peginTxHex,\n depositorBtcPubkey: depositorPk,\n vaultProviderBtcPubkey: signingContext.vaultProviderBtcPubkey,\n vaultKeeperBtcPubkeys: signingContext.vaultKeeperBtcPubkeys,\n universalChallengerBtcPubkeys:\n signingContext.universalChallengerBtcPubkeys,\n timelockPegin: signingContext.timelockPegin,\n timelockAssert: signingContext.timelockAssert,\n councilMembers: signingContext.councilMembers,\n councilQuorum: signingContext.councilQuorum,\n network: signingContext.network,\n registeredPayoutScriptPubKey: signingContext.registeredPayoutScriptPubKey,\n },\n });\n\n signal?.throwIfAborted();\n\n // Phase 5: Submit all signatures to VP\n // Include depositor's own payout signature in the signatures map\n const allSignatures = { ...claimerSignatures };\n allSignatures[stripHexPrefix(depositorPk)] =\n depositorClaimerPresignatures.payout_signatures;\n\n await presignClient.submitDepositorPresignatures(\n {\n pegin_txid: peginTxid,\n depositor_pk: depositorPk,\n signatures: allSignatures,\n depositor_claimer_presignatures: depositorClaimerPresignatures,\n },\n signal,\n );\n}\n","/**\n * Pure validation functions for deposit operations.\n *\n * All validations return a consistent {@link ValidationResult} format or throw\n * on critical failures (e.g. missing protocol participants).\n *\n * Business rules (single-provider limit, max vault count) and form-flow\n * checks (wallet connected) belong in the consumer layer.\n *\n * @module tbv/core/services/deposit/validation\n */\n\nimport {\n formatSatoshisToBtc,\n stripHexPrefix,\n} from \"../../primitives/utils/bitcoin\";\n\n// ---------------------------------------------------------------------------\n// Types\n// ---------------------------------------------------------------------------\n\nexport interface ValidationResult {\n valid: boolean;\n error?: string;\n warnings?: string[];\n}\n\n/**\n * Parameters for checking if a deposit form is valid.\n */\nexport interface DepositFormValidityParams {\n /** Deposit amount in satoshis */\n amountSats: bigint;\n /** Minimum deposit from protocol params */\n minDeposit: bigint;\n /** Maximum deposit from protocol params (optional) */\n maxDeposit?: bigint;\n /** User's available BTC balance in satoshis */\n btcBalance: bigint;\n /** Estimated transaction fee in satoshis */\n estimatedFeeSats?: bigint;\n /** Depositor claim value in satoshis (required output for challenge transactions) */\n depositorClaimValue?: bigint;\n}\n\nexport interface RemainingCapacityParams {\n /** Requested deposit amount in satoshis */\n amount: bigint;\n /**\n * Effective remaining capacity in satoshis (min of protocol-total and\n * per-address remaining). `null` means no cap applies.\n */\n effectiveRemaining: bigint | null;\n}\n\n/** Narrow structural type for UTXO — avoids importing vault-specific types. */\ninterface UtxoLike {\n txid: string;\n vout: number;\n value: number;\n}\n\n/**\n * Parameters for validating multi-vault deposit flow inputs.\n *\n * Callers must resolve any async loading states before calling — the SDK\n * validates resolved data, not React hook state.\n *\n * Form-flow checks (wallet connected, provider selected) are the caller's\n * responsibility and are NOT performed here.\n */\nexport interface MultiVaultDepositFlowInputs {\n vaultAmounts: bigint[];\n confirmedUTXOs: UtxoLike[];\n vaultProviderBtcPubkey: string;\n vaultKeeperBtcPubkeys: string[];\n universalChallengerBtcPubkeys: string[];\n /** Protocol minimum deposit per vault (satoshis) */\n minDeposit: bigint;\n /** Protocol maximum deposit per vault (satoshis) */\n maxDeposit?: bigint;\n}\n\n// ---------------------------------------------------------------------------\n// Private helpers\n// ---------------------------------------------------------------------------\n\nfunction isValidXOnlyHex(hex: string): boolean {\n return /^[0-9a-fA-F]{64}$/.test(hex);\n}\n\n// ---------------------------------------------------------------------------\n// Validation functions\n// ---------------------------------------------------------------------------\n\n/**\n * Check if deposit amount is within valid range and affordable.\n *\n * Returns false when fees/claim value are not yet known (still loading),\n * and includes them in the balance check once available.\n */\nexport function isDepositAmountValid(\n params: DepositFormValidityParams,\n): boolean {\n const {\n amountSats,\n minDeposit,\n maxDeposit,\n btcBalance,\n estimatedFeeSats,\n depositorClaimValue,\n } = params;\n\n if (amountSats <= 0n) return false;\n if (amountSats < minDeposit) return false;\n if (maxDeposit && maxDeposit > 0n && amountSats > maxDeposit) return false;\n\n if (estimatedFeeSats == null || depositorClaimValue == null) return false;\n\n const totalRequired = amountSats + estimatedFeeSats + depositorClaimValue;\n if (totalRequired > btcBalance) return false;\n\n return true;\n}\n\n/**\n * Validate deposit amount against minimum and maximum constraints.\n */\nexport function validateDepositAmount(\n amount: bigint,\n minDeposit: bigint,\n maxDeposit?: bigint,\n): ValidationResult {\n if (amount <= 0n) {\n return {\n valid: false,\n error: \"Deposit amount must be greater than zero\",\n };\n }\n\n if (amount < minDeposit) {\n return {\n valid: false,\n error: `Minimum deposit is ${formatSatoshisToBtc(minDeposit)} BTC`,\n };\n }\n\n if (maxDeposit && maxDeposit > 0n && amount > maxDeposit) {\n return {\n valid: false,\n error: `Maximum deposit is ${formatSatoshisToBtc(maxDeposit)} BTC`,\n };\n }\n\n return { valid: true };\n}\n\n/**\n * Validate that the requested deposit fits within the effective remaining cap.\n */\nexport function validateRemainingCapacity(\n params: RemainingCapacityParams,\n): ValidationResult {\n const { amount, effectiveRemaining } = params;\n if (effectiveRemaining === null) return { valid: true };\n\n if (effectiveRemaining === 0n) {\n return {\n valid: false,\n error: \"Supply cap reached — deposits temporarily paused\",\n };\n }\n\n if (amount > effectiveRemaining) {\n return {\n valid: false,\n error: `Vault size exceeds remaining capacity (${formatSatoshisToBtc(effectiveRemaining)} BTC)`,\n };\n }\n\n return { valid: true };\n}\n\n/**\n * Validate that selected providers exist in the available set.\n *\n * Business rules (e.g. single-provider limit) are the caller's responsibility.\n */\nexport function validateProviderSelection(\n selectedProviders: string[],\n availableProviders: string[],\n): ValidationResult {\n if (!selectedProviders || selectedProviders.length === 0) {\n return {\n valid: false,\n error: \"At least one vault provider must be selected\",\n };\n }\n\n const availableProvidersLower = availableProviders.map((p) =>\n p.toLowerCase(),\n );\n const invalidProviders = selectedProviders.filter(\n (p) => !availableProvidersLower.includes(p.toLowerCase()),\n );\n\n if (invalidProviders.length > 0) {\n return {\n valid: false,\n error: \"Invalid vault provider selected\",\n };\n }\n\n return { valid: true };\n}\n\n/**\n * Validate vault amounts array for multi-vault deposits.\n * Checks count, positivity, and per-vault min/max protocol limits.\n *\n * Max vault count limits are the caller's responsibility.\n */\nexport function validateVaultAmounts(\n amounts: bigint[],\n minDeposit?: bigint,\n maxDeposit?: bigint,\n): ValidationResult {\n if (!amounts || amounts.length === 0) {\n return {\n valid: false,\n error: \"At least one vault amount required\",\n };\n }\n\n for (let i = 0; i < amounts.length; i++) {\n const amount = amounts[i];\n if (amount <= 0n) {\n return {\n valid: false,\n error: `Vault ${i + 1} amount must be positive`,\n };\n }\n if (minDeposit && amount < minDeposit) {\n return {\n valid: false,\n error: `Vault ${i + 1} amount ${formatSatoshisToBtc(amount)} BTC is below minimum deposit ${formatSatoshisToBtc(minDeposit)} BTC`,\n };\n }\n if (maxDeposit && amount > maxDeposit) {\n return {\n valid: false,\n error: `Vault ${i + 1} amount ${formatSatoshisToBtc(amount)} BTC exceeds maximum deposit ${formatSatoshisToBtc(maxDeposit)} BTC`,\n };\n }\n }\n\n return { valid: true };\n}\n\n/**\n * Validate vault provider BTC public key format.\n */\nexport function validateVaultProviderPubkey(pubkey: string): ValidationResult {\n const stripped = stripHexPrefix(pubkey);\n if (!isValidXOnlyHex(stripped)) {\n return {\n valid: false,\n error:\n \"Invalid pubkey format: must be 64 hex characters (32-byte x-only public key, no 0x prefix)\",\n };\n }\n return { valid: true };\n}\n\n// ---------------------------------------------------------------------------\n// Private helpers for multi-vault validation\n// ---------------------------------------------------------------------------\n\nfunction validateVaultKeepers(vaultKeeperBtcPubkeys: string[]): void {\n if (!vaultKeeperBtcPubkeys || vaultKeeperBtcPubkeys.length === 0) {\n throw new Error(\n \"No vault keepers available. The system requires at least one vault keeper to create a deposit.\",\n );\n }\n}\n\nfunction validateUniversalChallengers(\n universalChallengerBtcPubkeys: string[],\n): void {\n if (\n !universalChallengerBtcPubkeys ||\n universalChallengerBtcPubkeys.length === 0\n ) {\n throw new Error(\n \"No universal challengers available. The system requires at least one universal challenger to create a deposit.\",\n );\n }\n}\n\nfunction validateUTXOState(confirmedUTXOs: UtxoLike[]): void {\n if (confirmedUTXOs.length === 0) {\n throw new Error(\"No spendable UTXOs available\");\n }\n}\n\n// ---------------------------------------------------------------------------\n// Multi-vault composite validation\n// ---------------------------------------------------------------------------\n\n/**\n * Validate protocol-level multi-vault deposit inputs.\n * Throws an error if any validation fails.\n *\n * Form-flow checks (wallet connections, provider selection) must be\n * performed by the caller before invoking this function.\n */\nexport function validateMultiVaultDepositInputs(\n params: MultiVaultDepositFlowInputs,\n): void {\n const {\n vaultAmounts,\n confirmedUTXOs,\n vaultProviderBtcPubkey,\n vaultKeeperBtcPubkeys,\n universalChallengerBtcPubkeys,\n minDeposit,\n maxDeposit,\n } = params;\n\n const amountsValidation = validateVaultAmounts(\n vaultAmounts,\n minDeposit,\n maxDeposit,\n );\n if (!amountsValidation.valid) {\n throw new Error(amountsValidation.error);\n }\n\n // Vault provider pubkey\n const pubkeyValidation = validateVaultProviderPubkey(vaultProviderBtcPubkey);\n if (!pubkeyValidation.valid) {\n throw new Error(pubkeyValidation.error);\n }\n\n validateVaultKeepers(vaultKeeperBtcPubkeys);\n validateUniversalChallengers(universalChallengerBtcPubkeys);\n validateUTXOState(confirmedUTXOs);\n}\n","/**\n * Pegout state definitions and protocol-level terminal checks.\n *\n * Maps VP-reported pegout statuses from `vaultProvider_getPegoutStatus`\n * to protocol lifecycle states.\n *\n * Lifecycle:\n * ClaimEventReceived -> ClaimBroadcast -> AssertBroadcast -> PayoutBroadcast (success)\n * > ChallengeAssertObserved -> WronglyChallengedBroadcast -> PayoutBroadcast\n * > ChallengeAssertObserved -> Failed (challenger won)\n */\n\n/** Claimer-side pegout statuses reported by the VP. */\nexport enum ClaimerPegoutStatusValue {\n CLAIM_EVENT_RECEIVED = \"ClaimEventReceived\",\n CLAIM_BROADCAST = \"ClaimBroadcast\",\n ASSERT_BROADCAST = \"AssertBroadcast\",\n CHALLENGE_ASSERT_OBSERVED = \"ChallengeAssertObserved\",\n WRONGLY_CHALLENGED_BROADCAST = \"WronglyChallengedBroadcast\",\n PAYOUT_BROADCAST = \"PayoutBroadcast\",\n FAILED = \"Failed\",\n}\n\nconst PEGOUT_TERMINAL_STATUSES = new Set<string>([\n ClaimerPegoutStatusValue.PAYOUT_BROADCAST,\n ClaimerPegoutStatusValue.FAILED,\n]);\n\n/** Whether a claimer status string maps to a known pegout state. */\nexport function isRecognizedPegoutStatus(status: string): boolean {\n return Object.values(ClaimerPegoutStatusValue).includes(\n status as ClaimerPegoutStatusValue,\n );\n}\n\n/**\n * Whether a claimer status is a hard-terminal pegout status\n * (PayoutBroadcast or Failed). Soft-terminal conditions (polling\n * thresholds) are a consumer-side concern.\n */\nexport function isPegoutTerminalStatus(\n claimerStatus: string | undefined,\n): boolean {\n return !!claimerStatus && PEGOUT_TERMINAL_STATUSES.has(claimerStatus);\n}\n","/**\n * Domain errors thrown by the refund service.\n *\n * @module services/refund/errors\n */\n\nimport type { Hex } from \"viem\";\n\n/**\n * Thrown when the broadcast transport rejects the refund tx because the CSV\n * timelock has not yet matured (BIP68 non-final). Callers can surface a\n * friendly \"wait until block N\" message; the original transport error is\n * available via {@link cause}.\n */\nexport class BIP68NotMatureError extends Error {\n public readonly vaultId: Hex;\n public override readonly cause: Error;\n\n constructor(vaultId: Hex, cause: Error) {\n super(`Refund not yet mature (BIP68 not final): ${cause.message}`);\n this.name = \"BIP68NotMatureError\";\n this.vaultId = vaultId;\n this.cause = cause;\n }\n}\n","/**\n * Vault refund orchestration — reclaim BTC from an expired Pre-PegIn HTLC via\n * the CSV-timelocked refund script (leaf 1). SDK owns the sequence of:\n * fetch → fee calc → PSBT build → sign → finalize → broadcast. Pre-fetched\n * data (fee rate) is passed by value; the data-flow-dependent reads\n * (`readVault`, `readPrePeginContext(vault)`) and the interactive transports\n * (`signPsbt`, `broadcastTx`) stay as injected callbacks so the caller keeps\n * its transport choice (viem, wagmi, mempool client, etc.) and error decoding.\n *\n * @module services/refund\n */\n\nimport type { Network } from \"@babylonlabs-io/babylon-tbv-rust-wasm\";\nimport { Psbt } from \"bitcoinjs-lib\";\nimport type { Address, Hex } from \"viem\";\n\nimport type { SignPsbtOptions } from \"../../../../shared/wallets/interfaces/BitcoinWallet\";\nimport { buildRefundPsbt } from \"../../primitives/psbt/refund\";\nimport {\n processPublicKeyToXOnly,\n stripHexPrefix,\n} from \"../../primitives/utils/bitcoin\";\nimport { createTaprootScriptPathSignOptions } from \"../../utils/signing\";\n\nimport { BIP68NotMatureError } from \"./errors\";\n\nconst BYTES32_HEX_RE = /^0x[0-9a-fA-F]{64}$/;\n// BTC raw-hex convention: 0x prefix optional, even number of hex chars, must\n// be non-empty. Named distinctly from the ETH-hex regex in activateVault.ts\n// (which requires a 0x prefix and allows empty \"0x\") to make the convention\n// explicit at the call site.\nconst BTC_HEX_BYTES_RE = /^(?:0x)?(?:[0-9a-fA-F]{2})+$/;\n// Pubkeys are either 32 bytes (x-only, 64 hex chars) or 33 bytes (compressed,\n// 66 hex chars). 65 hex chars is not a valid byte length — reject it here\n// rather than letting the malformed value surface as an opaque PSBT/signing\n// failure later.\nconst PUBKEY_HEX_RE = /^(?:0x)?(?:[0-9a-fA-F]{64}|[0-9a-fA-F]{66})$/;\n// Conservative upper bound for the fixed-shape refund tx (1 P2TR script-path\n// input spending the HTLC refund leaf → 1 P2TR/P2WPKH output). Taproot\n// script-path witness: 64-byte Schnorr sig + refund script + control block.\n// This is protocol-owned knowledge; callers don't parameterise it.\nexport const REFUND_VSIZE = 160;\n\n/**\n * Network fee (sats) the SDK will charge for a refund tx at the given\n * sat/vB rate. Mirrors the internal computation in\n * {@link buildAndBroadcastRefund} so callers (e.g. UI fee previews) don't\n * have to duplicate the constant.\n */\nexport function estimateRefundFeeSats(feeRateSatsVb: number): bigint {\n if (!Number.isFinite(feeRateSatsVb) || feeRateSatsVb <= 0) {\n throw new Error(\n `feeRateSatsVb must be a positive finite number, got ${feeRateSatsVb}`,\n );\n }\n return BigInt(Math.ceil(feeRateSatsVb * REFUND_VSIZE));\n}\n// Refund tx has exactly one input — the HTLC output at htlcVout from the\n// Pre-PegIn tx. Used to tell the signer how many sign entries to generate.\n// (Not the taproot leaf index; the leaf is encoded into the PSBT by the\n// WASM PSBT builder based on the refund script path.)\nconst REFUND_INPUT_COUNT = 1;\nconst MAX_VOUT = 0xffff;\nconst BIP68_ERROR_RE = /non-BIP68-final/i;\n\nfunction assertBytes32(value: string, label: string): void {\n if (value.length !== 66) {\n throw new Error(\n `${label} must be 32 bytes (66 hex chars with 0x prefix), got length ${value.length}`,\n );\n }\n if (!BYTES32_HEX_RE.test(value)) {\n throw new Error(\n `${label} must contain only hex characters after the 0x prefix`,\n );\n }\n}\n\n/**\n * Authoritative vault fields needed to build a refund. Versioning fields,\n * the hashlock, and htlcVout must come from the on-chain contract (never the\n * indexer). The amount + `unsignedPrePeginTxHex` + `depositorBtcPubkey` can\n * come from the indexer since they are not security-critical for signing\n * (the PSBT builder re-derives the HTLC script from on-chain params).\n */\nexport interface VaultRefundData {\n hashlock: Hex;\n htlcVout: number;\n offchainParamsVersion: number;\n appVaultKeepersVersion: number;\n universalChallengersVersion: number;\n vaultProvider: Address;\n applicationEntryPoint: Address;\n /** Pre-PegIn HTLC output value in satoshis. */\n amount: bigint;\n /**\n * Funded, pre-witness Pre-PegIn transaction hex. 0x prefix optional.\n * The name mirrors the contract/indexer schema; the bytes are the\n * funded form (refund construction needs real outpoints).\n */\n unsignedPrePeginTxHex: string;\n /** Depositor's BTC public key (x-only or compressed hex; 0x prefix optional). */\n depositorBtcPubkey: string;\n}\n\n/**\n * Version-resolved protocol context that parameterises the HTLC's taproot\n * scripts. The *signer-set* fields (`vaultKeeperPubkeys`,\n * `universalChallengerPubkeys`) and the version-locked numeric protocol\n * params **must** be sourced from the on-chain contract at the version\n * pinned in {@link VaultRefundData} — this is the trust boundary.\n * `vaultProviderPubkey` today is sourced from the GraphQL indexer via\n * `fetchVaultProviderById`; the caller is responsible for any additional\n * cross-check it requires. Keeper and challenger pubkey arrays must be\n * pre-sorted the same way the Rust protocol sorts them (canonical for\n * script derivation).\n */\nexport interface RefundPrePeginContext {\n vaultProviderPubkey: string;\n vaultKeeperPubkeys: readonly string[];\n universalChallengerPubkeys: readonly string[];\n timelockRefund: number;\n feeRate: bigint;\n numLocalChallengers: number;\n councilQuorum: number;\n councilSize: number;\n network: Network;\n}\n\n/** Minimum shape required from a broadcast result. */\nexport interface BtcBroadcastResult {\n txId: string;\n}\n\nexport type BtcBroadcaster<\n R extends BtcBroadcastResult = BtcBroadcastResult,\n> = (signedTxHex: string) => Promise<R>;\n\nexport type RefundPsbtSigner = (\n psbtHex: string,\n opts: SignPsbtOptions,\n) => Promise<string>;\n\nexport interface RefundInput<\n R extends BtcBroadcastResult = BtcBroadcastResult,\n> {\n vaultId: Hex;\n /**\n * Fetch authoritative on-chain + indexer vault data. The SDK passes no\n * arguments — the caller closes over `vaultId` (or any other context it\n * needs).\n */\n readVault: () => Promise<VaultRefundData>;\n /**\n * Fetch the version-pinned refund context (sorted pubkeys, timelock, etc.)\n * derived from the vault's locked versions.\n */\n readPrePeginContext: (\n vault: VaultRefundData,\n ) => Promise<RefundPrePeginContext>;\n /**\n * Mempool-derived sat/vB fee rate to use for the refund tx (positive\n * number). Caller fetches this before invoking — it does not depend on\n * any value the SDK computes, and folding it into the call keeps the\n * orchestration honest.\n */\n feeRate: number;\n /** BTC wallet signer; receives a PSBT hex + taproot script-path options. */\n signPsbt: RefundPsbtSigner;\n /** Broadcast callback — returns whatever shape the caller needs. */\n broadcastTx: BtcBroadcaster<R>;\n /** Checked at every async boundary. */\n signal?: AbortSignal;\n}\n\nfunction assertNonNegativeInteger(value: number, label: string): void {\n if (!Number.isInteger(value) || value < 0) {\n throw new Error(`${label} must be a non-negative integer, got ${value}`);\n }\n}\n\nfunction validateVaultRefundData(v: VaultRefundData): void {\n assertBytes32(v.hashlock, \"hashlock\");\n if (\n !Number.isInteger(v.htlcVout) ||\n v.htlcVout < 0 ||\n v.htlcVout > MAX_VOUT\n ) {\n throw new Error(\n `htlcVout must be an integer 0-${MAX_VOUT}, got ${v.htlcVout}`,\n );\n }\n // Version fields flow directly into on-chain script derivation via\n // `readPrePeginContext` — NaN, negative, or non-integer values would\n // silently produce wrong scripts. Guard here as defence in depth even\n // though the caller sources these from bigint on-chain reads.\n assertNonNegativeInteger(v.offchainParamsVersion, \"offchainParamsVersion\");\n assertNonNegativeInteger(v.appVaultKeepersVersion, \"appVaultKeepersVersion\");\n assertNonNegativeInteger(\n v.universalChallengersVersion,\n \"universalChallengersVersion\",\n );\n if (typeof v.unsignedPrePeginTxHex !== \"string\" || v.unsignedPrePeginTxHex.length === 0) {\n throw new Error(\"unsignedPrePeginTxHex must be a non-empty hex string\");\n }\n if (!BTC_HEX_BYTES_RE.test(v.unsignedPrePeginTxHex)) {\n throw new Error(\n \"unsignedPrePeginTxHex must be a hex byte string (optional 0x prefix, even length)\",\n );\n }\n if (!v.depositorBtcPubkey || !PUBKEY_HEX_RE.test(v.depositorBtcPubkey)) {\n throw new Error(\n \"depositorBtcPubkey must be 32 or 33 bytes of hex (optional 0x prefix)\",\n );\n }\n if (typeof v.amount !== \"bigint\" || v.amount <= 0n) {\n throw new Error(`amount must be a positive bigint, got ${v.amount}`);\n }\n}\n\nfunction validateRefundPrePeginContext(c: RefundPrePeginContext): void {\n if (!c.vaultProviderPubkey || !PUBKEY_HEX_RE.test(c.vaultProviderPubkey)) {\n throw new Error(\"vaultProviderPubkey must be 32 or 33 bytes of hex\");\n }\n if (c.vaultKeeperPubkeys.length === 0) {\n throw new Error(\"vaultKeeperPubkeys must be non-empty\");\n }\n if (c.universalChallengerPubkeys.length === 0) {\n throw new Error(\"universalChallengerPubkeys must be non-empty\");\n }\n if (!Number.isInteger(c.timelockRefund) || c.timelockRefund <= 0) {\n throw new Error(\n `timelockRefund must be a positive integer, got ${c.timelockRefund}`,\n );\n }\n if (typeof c.feeRate !== \"bigint\" || c.feeRate <= 0n) {\n throw new Error(\n `protocol feeRate must be a positive bigint, got ${c.feeRate}`,\n );\n }\n if (\n !Number.isInteger(c.numLocalChallengers) ||\n c.numLocalChallengers < 0\n ) {\n throw new Error(\"numLocalChallengers must be a non-negative integer\");\n }\n if (\n !Number.isInteger(c.councilQuorum) ||\n !Number.isInteger(c.councilSize) ||\n c.councilQuorum <= 0 ||\n c.councilSize <= 0 ||\n c.councilQuorum > c.councilSize\n ) {\n throw new Error(\n `councilQuorum (${c.councilQuorum}) must be in [1, councilSize=${c.councilSize}]`,\n );\n }\n}\n\nfunction finalizeAndExtract(signedPsbtHex: string): string {\n const psbt = Psbt.fromHex(signedPsbtHex);\n try {\n psbt.finalizeAllInputs();\n } catch (e: unknown) {\n // Some wallets (e.g. Keystone) finalize during signPsbt; bitcoinjs then\n // throws \"Input is already finalized\". Treat that case as a no-op.\n const message = e instanceof Error ? e.message : String(e);\n if (!message.includes(\"already finalized\")) {\n throw new Error(`Failed to finalize refund PSBT: ${message}`);\n }\n }\n return psbt.extractTransaction().toHex();\n}\n\n/**\n * Build, sign, and broadcast a refund transaction for an expired vault.\n *\n * Trust boundary: `readVault` must source the hashlock, htlcVout, and\n * versioning fields from the on-chain contract — an indexer-only path\n * leaves the refund flow open to signer-set substitution. The SDK does\n * not enforce this; it is the caller's responsibility.\n *\n * The broadcast transport is expected to surface Bitcoin's `non-BIP68-final`\n * policy rejection as an `Error` whose message contains that string; when\n * it does, the SDK wraps it in {@link BIP68NotMatureError}. All other\n * transport errors propagate unchanged.\n *\n * @returns whatever the injected `broadcastTx` returns (generic pass-through)\n * @throws `Error` if any validation fails\n * @throws {@link BIP68NotMatureError} if the broadcast is rejected because\n * the refund CSV timelock has not yet matured\n * @throws anything `readVault`, `readPrePeginContext`,\n * `signPsbt`, or `broadcastTx` throws\n */\nexport async function buildAndBroadcastRefund<\n R extends BtcBroadcastResult = BtcBroadcastResult,\n>(input: RefundInput<R>): Promise<R> {\n const {\n vaultId,\n readVault,\n readPrePeginContext,\n feeRate,\n signPsbt,\n broadcastTx,\n signal,\n } = input;\n\n signal?.throwIfAborted();\n assertBytes32(vaultId, \"vaultId\");\n\n const vault = await readVault();\n validateVaultRefundData(vault);\n signal?.throwIfAborted();\n\n const ctx = await readPrePeginContext(vault);\n validateRefundPrePeginContext(ctx);\n signal?.throwIfAborted();\n\n if (!Number.isFinite(feeRate) || feeRate <= 0) {\n throw new Error(`feeRate must be a positive number, got ${feeRate}`);\n }\n const refundFee = BigInt(Math.ceil(feeRate * REFUND_VSIZE));\n signal?.throwIfAborted();\n\n // `vault.depositorBtcPubkey` may arrive as wallet-native compressed sec1\n // (33 bytes) because the caller fetches it live from the wallet for\n // signing. WASM script derivation wants x-only (32 bytes), so normalize\n // here; the raw form is kept for the wallet sign call below.\n const xOnlyDepositorPubkey = processPublicKeyToXOnly(\n vault.depositorBtcPubkey,\n );\n const { psbtHex } = await buildRefundPsbt({\n prePeginParams: {\n depositorPubkey: xOnlyDepositorPubkey,\n vaultProviderPubkey: stripHexPrefix(ctx.vaultProviderPubkey),\n vaultKeeperPubkeys: ctx.vaultKeeperPubkeys.map(stripHexPrefix),\n universalChallengerPubkeys:\n ctx.universalChallengerPubkeys.map(stripHexPrefix),\n hashlocks: [stripHexPrefix(vault.hashlock)],\n timelockRefund: ctx.timelockRefund,\n pegInAmounts: [vault.amount],\n feeRate: ctx.feeRate,\n numLocalChallengers: ctx.numLocalChallengers,\n councilQuorum: ctx.councilQuorum,\n councilSize: ctx.councilSize,\n network: ctx.network,\n },\n fundedPrePeginTxHex: stripHexPrefix(vault.unsignedPrePeginTxHex),\n htlcVout: vault.htlcVout,\n refundFee,\n // buildRefundPsbt's top-level `hashlock` param is documented as \"no 0x\n // prefix\" and flows into the WASM HTLC connector derivation; a prefixed\n // value would derive the wrong refund script leaf and yield an\n // unspendable PSBT. Match the `hashlocks` array handling above.\n hashlock: stripHexPrefix(vault.hashlock),\n });\n signal?.throwIfAborted();\n\n const signOptions = createTaprootScriptPathSignOptions(\n vault.depositorBtcPubkey,\n REFUND_INPUT_COUNT,\n );\n const signedPsbtHex = await signPsbt(psbtHex, signOptions);\n const signedTxHex = finalizeAndExtract(signedPsbtHex);\n signal?.throwIfAborted();\n\n try {\n return await broadcastTx(signedTxHex);\n } catch (error) {\n if (error instanceof Error && BIP68_ERROR_RE.test(error.message)) {\n throw new BIP68NotMatureError(vaultId, error);\n }\n throw error;\n }\n}\n"],"names":["BYTES32_HEX_RE","ADDRESS_HEX_RE","ETH_HEX_BYTES_RE","assertBytes32","value","label","assertAddress","assertHexBytes","activateVault","input","btcVaultRegistryAddress","vaultId","hashlock","activationMetadata","writeContract","signal","normalizedSecret","ensureHexPrefix","validateSecretAgainstHashlock","BTCVaultRegistryABI","DEFAULT_POLL_INTERVAL_MS","waitForPeginStatus","params","statusReader","peginTxid","targetStatuses","timeoutMs","pollIntervalMs","startTime","status","VP_TERMINAL_STATUSES","error","JsonRpcError","RpcErrorCode","resolve","reject","onAbort","timeoutId","STATUS_POLL_TIMEOUT_MS","TARGET_STATUSES","DaemonStatus","POST_WOTS_STATUSES","submitWotsPublicKey","wotsSubmitter","depositorPk","wotsPublicKeys","DEPOSITOR_SIGNED_INPUT_COUNT","deriveLocalChallengers","vaultProviderBtcPubkey","vaultKeeperBtcPubkeys","depositorBtcPubkey","depositor","stripHexPrefix","filtered","k","readInputTxid","tx","inputIndex","uint8ArrayToHex","assertInputReferencesParent","noPayoutTx","parentTx","parentLabel","challengerPubkey","parentTxid","inputTxid","collectDepositorGraphPsbts","depositorGraph","walletPublicKey","ctx","psbtHexes","signOptions","challengerEntries","assertPayoutOutputMatchesRegistered","builtPayout","buildPayoutPsbt","createTaprootScriptPathSignOptions","localChallengers","claimerPubkey","assertTxParsed","Transaction","challenger","noPayoutIdx","noPayoutHex","buildLocalNoPayoutPsbt","assertNoPayoutOutputMatchesChallenger","challengeAssertXTx","challengeAssertYTx","prevouts","out","buildNoPayoutPsbt","extractDepositorGraphSignatures","signedPsbtHexes","depositorPubkey","payoutSignature","extractPayoutSignature","perChallenger","entry","signPsbtsWithFallback","wallet","options","signed","i","signDepositorGraph","btcWallet","signingContext","MAX_POLLING_TIMEOUT_MS","POST_PAYOUT_STATUSES","TARGET_STATUS","prepareTransactionsForSigning","claimerTransactions","processPublicKeyToXOnly","deriveBip86ScriptPubKey","xOnlyPubkeyHex","output","bitcoin","Buffer","resolvePayoutScriptPubKey","claimerPubkeyXOnly","context","claimer","vpPubkey","vk","buildPayoutSigningInput","signPayoutTransactions","transactions","onProgress","payoutManager","PayoutManager","totalClaimers","payoutSignatures","r","result","signatures","runDepositorPresignFlow","presignClient","response","depositorPkNormalized","nonDepositorTxs","preparedTransactions","claimerSignatures","depositorClaimerPresignatures","allSignatures","isValidXOnlyHex","hex","isDepositAmountValid","amountSats","minDeposit","maxDeposit","btcBalance","estimatedFeeSats","depositorClaimValue","validateDepositAmount","amount","formatSatoshisToBtc","validateRemainingCapacity","effectiveRemaining","validateProviderSelection","selectedProviders","availableProviders","availableProvidersLower","p","validateVaultAmounts","amounts","validateVaultProviderPubkey","pubkey","stripped","validateVaultKeepers","validateUniversalChallengers","universalChallengerBtcPubkeys","validateUTXOState","confirmedUTXOs","validateMultiVaultDepositInputs","vaultAmounts","amountsValidation","pubkeyValidation","ClaimerPegoutStatusValue","PEGOUT_TERMINAL_STATUSES","isRecognizedPegoutStatus","isPegoutTerminalStatus","claimerStatus","BIP68NotMatureError","cause","__publicField","BTC_HEX_BYTES_RE","PUBKEY_HEX_RE","REFUND_VSIZE","estimateRefundFeeSats","feeRateSatsVb","REFUND_INPUT_COUNT","MAX_VOUT","BIP68_ERROR_RE","assertNonNegativeInteger","validateVaultRefundData","v","validateRefundPrePeginContext","c","finalizeAndExtract","signedPsbtHex","psbt","Psbt","e","message","buildAndBroadcastRefund","readVault","readPrePeginContext","feeRate","signPsbt","broadcastTx","vault","refundFee","xOnlyDepositorPubkey","psbtHex","buildRefundPsbt","signedTxHex"],"mappings":"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"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"types-ByW6nSLj.js","sources":["../src/tbv/core/clients/vault-provider/json-rpc-client.ts","../src/tbv/core/clients/vault-provider/types.ts"],"sourcesContent":["/**\n * Generic JSON-RPC 2.0 HTTP Client\n *\n * Framework-agnostic client using `fetch()` — works in browsers and Node.js 18+.\n * Includes configurable retry policy and AbortSignal passthrough.\n */\n\nexport interface JsonRpcRequest<T = unknown> {\n jsonrpc: \"2.0\";\n method: string;\n params: T;\n id: number | string;\n}\n\nexport interface JsonRpcSuccessResponse<T = unknown> {\n jsonrpc: \"2.0\";\n result: T;\n id: number | string;\n}\n\nexport interface JsonRpcErrorResponse {\n jsonrpc: \"2.0\";\n error: {\n code: number;\n message: string;\n data?: unknown;\n };\n id: number | string;\n}\n\nexport type JsonRpcResponse<T = unknown> =\n | JsonRpcSuccessResponse<T>\n | JsonRpcErrorResponse;\n\n/**\n * Injects bearer tokens into requests for auth-gated methods, and is\n * notified on auth-expired responses so it can invalidate its cache.\n *\n * The `JsonRpcClient` is agnostic to which methods are auth-gated —\n * the provider's `getToken(method)` decides. Returning `null` means\n * \"no auth required for this method\"; the client then sends the\n * request with no `Authorization` header.\n */\nexport interface BearerTokenProvider {\n /**\n * Return the bearer token to inject for `method`, or `null` if the\n * method does not require auth.\n */\n getToken(method: string): Promise<string | null>;\n /**\n * Drop the cached token. Next call to `getToken` must re-acquire.\n * Called by the client on reactive-refresh-trigger responses.\n */\n invalidate(): void;\n}\n\nexport interface JsonRpcClientConfig {\n /** Base URL of the RPC service */\n baseUrl: string;\n /** Timeout in milliseconds per request attempt */\n timeout: number;\n /** Optional custom headers */\n headers?: Record<string, string>;\n /** Number of retry attempts for transient errors (default: 3) */\n retries?: number;\n /** Initial retry delay in milliseconds (default: 1000) */\n retryDelay?: number;\n /**\n * Maximum response body size, in bytes, for typed JSON-RPC calls.\n * `callRaw` intentionally returns the unparsed Response and is not capped here.\n * Default: 2 MiB.\n */\n maxResponseBytes?: number;\n /**\n * Predicate that decides which methods retry on transient errors.\n * Default retries only `getPeginStatus`, `getPegoutStatus`, and\n * `requestDepositorPresignTransactions`. Write methods are not\n * retried by default.\n */\n retryableFor?: (method: string) => boolean;\n /**\n * Per-request bearer-token source. A non-null return attaches\n * `Authorization: Bearer <token>`; `null` skips auth. `call`\n * additionally retries once on wire `auth_expired` (invalidate +\n * refetch + retry). `callRaw` skips reactive refresh.\n */\n tokenProvider?: BearerTokenProvider;\n}\n\n/**\n * Identifies whether an error was produced locally (timeout, network\n * failure, malformed response) or parsed from a wire-format JSON-RPC\n * error envelope returned by the server.\n *\n * This matters for anyone inspecting the shared `-32001` code: the SDK\n * uses it internally for network failures AND the server uses it for\n * auth-middleware rejections. The `source` field disambiguates.\n */\nexport type JsonRpcErrorSource = \"wire\" | \"local\";\n\nexport class JsonRpcError extends Error {\n constructor(\n public code: number,\n message: string,\n /** \"wire\" for server-returned envelopes; \"local\" for SDK-side failures. */\n public source: JsonRpcErrorSource = \"local\",\n /** Structured data from the server `error.data` field, if any. */\n public data?: unknown,\n ) {\n super(message);\n this.name = \"JsonRpcError\";\n }\n}\n\nexport const JSON_RPC_ERROR_CODES = {\n TIMEOUT: -32000,\n NETWORK: -32001,\n /** VP proxy: request timed out at proxy level */\n PROXY_TIMEOUT: -32002,\n /** VP proxy: VP unreachable / DNS failure / response too large */\n PROXY_UNAVAILABLE: -32003,\n /** SDK client: response missing \"result\" field (malformed JSON-RPC) */\n INVALID_RESPONSE: -32700,\n /** SDK client: response body exceeded the configured byte limit */\n RESPONSE_TOO_LARGE: -32701,\n} as const;\n\n/** JSON-RPC protocol version */\nconst JSON_RPC_VERSION = \"2.0\" as const;\n\n/** Default number of retry attempts for transient errors */\nconst DEFAULT_RETRY_ATTEMPTS = 3;\n\n/** Default initial retry delay in milliseconds */\nconst DEFAULT_RETRY_DELAY_MS = 1000;\n\n/** Default maximum JSON-RPC response size for typed calls (2 MiB) */\nconst DEFAULT_MAX_RESPONSE_BYTES = 2 * 1024 * 1024;\n\n/**\n * TODO: Temporary typed-call exceptions for methods that currently return large\n * artifact payloads as JSON-RPC results.\n */\nconst UNCAPPED_TYPED_RESPONSE_METHODS: ReadonlySet<string> = new Set([\n \"vaultProvider_requestDepositorClaimerArtifacts\",\n]);\n\n/** HTTP status codes that indicate transient server errors and are safe to retry */\nconst RETRYABLE_HTTP_STATUS_CODES: ReadonlySet<number> = new Set([\n 408, // Request Timeout\n 429, // Too Many Requests\n 500, // Internal Server Error\n 502, // Bad Gateway\n 503, // Service Unavailable\n 504, // Gateway Timeout\n]);\n\n/** Default retry predicate: only retry read-only / idempotent methods */\nconst DEFAULT_RETRYABLE_METHODS: ReadonlySet<string> = new Set([\n \"vaultProvider_getPeginStatus\",\n \"vaultProvider_getPegoutStatus\",\n \"vaultProvider_requestDepositorPresignTransactions\",\n]);\n\nfunction defaultRetryableFor(method: string): boolean {\n return DEFAULT_RETRYABLE_METHODS.has(method);\n}\n\n/**\n * Token-expired marker the server emits in `error.data.kind`. When\n * present on a wire-origin error, the client invalidates its cached\n * token and retries the request once with a freshly-acquired bearer.\n *\n * Kept in sync with btc-vault's auth middleware. Absence of the marker\n * means the server does not support reactive refresh yet; we fall back\n * to proactive-only refresh via `BearerTokenProvider.getToken()` TTL\n * checks.\n */\nconst AUTH_EXPIRED_DATA_KIND = \"auth_expired\";\n\nfunction isAuthExpiredError(error: unknown): boolean {\n if (!(error instanceof JsonRpcError)) return false;\n if (error.source !== \"wire\") return false;\n const data = error.data;\n if (data === null || typeof data !== \"object\") return false;\n const kind = (data as { kind?: unknown }).kind;\n return kind === AUTH_EXPIRED_DATA_KIND;\n}\n\n/**\n * Generic JSON-RPC 2.0 HTTP client with safe retry policy.\n */\nexport class JsonRpcClient {\n private baseUrl: string;\n private timeout: number;\n private headers: Record<string, string>;\n private requestId = 0;\n private retries: number;\n private retryDelay: number;\n private maxResponseBytes: number;\n private retryableFor: (method: string) => boolean;\n private tokenProvider?: BearerTokenProvider;\n\n constructor(config: JsonRpcClientConfig) {\n this.baseUrl = config.baseUrl.replace(/\\/$/, \"\");\n this.timeout = config.timeout;\n this.headers = {\n \"Content-Type\": \"application/json\",\n ...config.headers,\n };\n this.retries = config.retries ?? DEFAULT_RETRY_ATTEMPTS;\n this.retryDelay = config.retryDelay ?? DEFAULT_RETRY_DELAY_MS;\n this.maxResponseBytes =\n config.maxResponseBytes ?? DEFAULT_MAX_RESPONSE_BYTES;\n if (!Number.isFinite(this.maxResponseBytes) || this.maxResponseBytes <= 0) {\n throw new Error(\"maxResponseBytes must be a positive finite number\");\n }\n this.retryableFor = config.retryableFor ?? defaultRetryableFor;\n this.tokenProvider = config.tokenProvider;\n }\n\n private async buildHeaders(method: string): Promise<Record<string, string>> {\n const headers: Record<string, string> = { ...this.headers };\n if (this.tokenProvider) {\n const token = await this.tokenProvider.getToken(method);\n if (token) {\n headers.Authorization = `Bearer ${token}`;\n }\n }\n return headers;\n }\n\n /**\n * Make a JSON-RPC request with optional retry for safe methods.\n *\n * If the request fails with a wire-origin `auth_expired` error and a\n * `tokenProvider` is configured, the client invalidates its cached\n * token and retries the request once with a freshly-acquired bearer.\n *\n * @param method - The RPC method name\n * @param params - The method parameters\n * @param signal - Optional AbortSignal for caller-controlled cancellation\n * @returns The result from the RPC method\n * @throws JsonRpcError if the RPC call fails\n */\n async call<TParams, TResult>(\n method: string,\n params: TParams,\n signal?: AbortSignal,\n ): Promise<TResult> {\n try {\n return await this.callOnce<TParams, TResult>(method, params, signal);\n } catch (error) {\n // The auth-expired retry fires for ALL methods, including mutating\n // ones. This is intentional and safe: the server's auth middleware\n // validates the bearer token BEFORE dispatching to the method\n // handler, so an `auth_expired` error means the handler never ran\n // and no state was mutated. Confirmed against btc-vault at\n // `crates/btc-auth/src/middleware/jsonrpc.rs` — token validation\n // is pre-handler only. The `retryableFor` guard on\n // HTTP-transient-error retries doesn't apply here because that\n // guard is about retrying after a request the server may have\n // started processing; auth_expired is categorically different.\n if (this.tokenProvider && isAuthExpiredError(error)) {\n this.tokenProvider.invalidate();\n return await this.callOnce<TParams, TResult>(method, params, signal);\n }\n throw error;\n }\n }\n\n private async callOnce<TParams, TResult>(\n method: string,\n params: TParams,\n signal: AbortSignal | undefined,\n ): Promise<TResult> {\n const response = await this.fetchWithRetry(method, params, signal);\n\n let jsonResponse: unknown;\n try {\n const responseText = UNCAPPED_TYPED_RESPONSE_METHODS.has(method)\n ? await response.text()\n : await readResponseTextWithLimit(response, this.maxResponseBytes);\n jsonResponse = JSON.parse(responseText);\n } catch (error) {\n if (error instanceof JsonRpcError) {\n throw error;\n }\n throw new JsonRpcError(\n JSON_RPC_ERROR_CODES.INVALID_RESPONSE,\n \"Invalid JSON-RPC response: body is not valid JSON\",\n \"local\",\n );\n }\n\n if (\n jsonResponse === null ||\n typeof jsonResponse !== \"object\" ||\n Array.isArray(jsonResponse)\n ) {\n throw new JsonRpcError(\n JSON_RPC_ERROR_CODES.INVALID_RESPONSE,\n `Invalid JSON-RPC response: expected an object, got ${typeof jsonResponse}`,\n \"local\",\n );\n }\n\n const rpcResponse = jsonResponse as Record<string, unknown>;\n\n if (\"error\" in rpcResponse && rpcResponse.error != null) {\n const err = rpcResponse.error as {\n code?: number;\n message?: string;\n data?: unknown;\n };\n throw new JsonRpcError(\n err.code ?? JSON_RPC_ERROR_CODES.INVALID_RESPONSE,\n err.message ?? \"Unknown RPC error\",\n \"wire\",\n err.data,\n );\n }\n\n if (!(\"result\" in rpcResponse)) {\n throw new JsonRpcError(\n JSON_RPC_ERROR_CODES.INVALID_RESPONSE,\n `Invalid JSON-RPC response: missing \"result\" field`,\n \"local\",\n );\n }\n\n return rpcResponse.result as TResult;\n }\n\n /**\n * Make a JSON-RPC request returning the raw Response (unparsed body).\n *\n * Bearer tokens are injected identically to `call`. **Reactive refresh\n * is NOT performed here** — the response body may be unbounded (e.g.\n * claimer-artifact downloads), so the client refuses to parse it to\n * detect auth errors. Callers relying on token-expired retries for\n * large downloads must read the body themselves and re-invoke\n * `callRaw` after `tokenProvider.invalidate()`.\n */\n async callRaw<TParams>(\n method: string,\n params: TParams,\n signal?: AbortSignal,\n ): Promise<Response> {\n return this.fetchWithRetry(method, params, signal);\n }\n\n private async fetchWithRetry<TParams>(\n method: string,\n params: TParams,\n callerSignal?: AbortSignal,\n ): Promise<Response> {\n const requestId = ++this.requestId;\n const maxRetries = this.retryableFor(method) ? this.retries : 0;\n\n // jsonrpsee (Rust backend) expects params as an array (positional parameters)\n const request: JsonRpcRequest<TParams[]> = {\n jsonrpc: JSON_RPC_VERSION,\n method,\n params: [params],\n id: requestId,\n };\n\n const body = JSON.stringify(request);\n let lastError: Error | null = null;\n\n for (let attempt = 0; attempt <= maxRetries; attempt++) {\n // Merge caller signal with per-request timeout signal\n const timeoutController = new AbortController();\n const timeoutId = setTimeout(\n () => timeoutController.abort(),\n this.timeout,\n );\n\n const merged = callerSignal\n ? mergeAbortSignals(callerSignal, timeoutController.signal)\n : null;\n const signal = merged ? merged.signal : timeoutController.signal;\n\n try {\n // Build headers per-attempt so the token provider can return a\n // freshly-acquired bearer after a prior invalidate() on this\n // request (retry loop path) without plumbing state through.\n const headers = await this.buildHeaders(method);\n\n const response = await fetch(this.baseUrl, {\n method: \"POST\",\n headers,\n body,\n signal,\n });\n\n clearTimeout(timeoutId);\n merged?.cleanup();\n\n if (!response.ok) {\n const shouldRetry =\n attempt < maxRetries &&\n RETRYABLE_HTTP_STATUS_CODES.has(response.status);\n\n if (shouldRetry) {\n const delay = this.retryDelay * Math.pow(2, attempt);\n await this.sleep(delay, callerSignal);\n continue;\n }\n\n throw new Error(\n `HTTP error: ${response.status} ${response.statusText}`,\n );\n }\n\n return response;\n } catch (error) {\n clearTimeout(timeoutId);\n merged?.cleanup();\n lastError = error instanceof Error ? error : new Error(String(error));\n\n // Check if caller aborted (not our timeout)\n if (callerSignal?.aborted) {\n throw new Error(\"Request aborted\");\n }\n\n if (error instanceof Error && error.name === \"AbortError\") {\n if (attempt < maxRetries) {\n const delay = this.retryDelay * Math.pow(2, attempt);\n await this.sleep(delay, callerSignal);\n continue;\n }\n throw new JsonRpcError(\n JSON_RPC_ERROR_CODES.TIMEOUT,\n `Request timeout after ${this.timeout}ms (${maxRetries + 1} attempts)`,\n \"local\",\n );\n }\n\n // Handle network errors (CORS, connection refused, etc.)\n if (error instanceof TypeError) {\n if (attempt < maxRetries) {\n const delay = this.retryDelay * Math.pow(2, attempt);\n await this.sleep(delay, callerSignal);\n continue;\n }\n throw new JsonRpcError(\n JSON_RPC_ERROR_CODES.NETWORK,\n `Network error: ${error.message} (${maxRetries + 1} attempts)`,\n \"local\",\n );\n }\n\n // Don't retry JSON-RPC errors (business logic errors)\n throw error;\n }\n }\n\n throw lastError || new Error(\"Unknown error after retries\");\n }\n\n private sleep(ms: number, signal?: AbortSignal): Promise<void> {\n return new Promise((resolve, reject) => {\n if (signal?.aborted) {\n reject(new Error(\"Request aborted\"));\n return;\n }\n const timeoutId = setTimeout(() => {\n signal?.removeEventListener(\"abort\", onAbort);\n resolve();\n }, ms);\n const onAbort = () => {\n clearTimeout(timeoutId);\n reject(new Error(\"Request aborted\"));\n };\n signal?.addEventListener(\"abort\", onAbort, { once: true });\n });\n }\n\n getBaseUrl(): string {\n return this.baseUrl;\n }\n}\n\ninterface MergedSignal {\n signal: AbortSignal;\n /** Remove listeners from the source signals. Call after the request completes. */\n cleanup: () => void;\n}\n\n/**\n * Merge two AbortSignals — the returned signal aborts if either input aborts.\n * Returns a cleanup function to remove listeners when the request completes\n * normally, preventing listener accumulation in long-lived polling flows.\n */\nfunction mergeAbortSignals(a: AbortSignal, b: AbortSignal): MergedSignal {\n if (a.aborted) return { signal: a, cleanup: () => {} };\n if (b.aborted) return { signal: b, cleanup: () => {} };\n\n const controller = new AbortController();\n const onAbortA = () => {\n b.removeEventListener(\"abort\", onAbortB);\n controller.abort();\n };\n const onAbortB = () => {\n a.removeEventListener(\"abort\", onAbortA);\n controller.abort();\n };\n a.addEventListener(\"abort\", onAbortA, { once: true });\n b.addEventListener(\"abort\", onAbortB, { once: true });\n\n const cleanup = () => {\n a.removeEventListener(\"abort\", onAbortA);\n b.removeEventListener(\"abort\", onAbortB);\n };\n\n return { signal: controller.signal, cleanup };\n}\n\nasync function readResponseTextWithLimit(\n response: Response,\n maxBytes: number,\n): Promise<string> {\n const contentLength = response.headers.get(\"content-length\");\n if (contentLength !== null) {\n const parsedContentLength = Number(contentLength);\n if (\n Number.isFinite(parsedContentLength) &&\n parsedContentLength > maxBytes\n ) {\n throw responseTooLargeError(maxBytes);\n }\n }\n\n if (!response.body) {\n return \"\";\n }\n\n const reader = response.body.getReader();\n const decoder = new TextDecoder();\n let totalBytes = 0;\n let responseText = \"\";\n\n try {\n for (;;) {\n const { done, value } = await reader.read();\n if (done) break;\n if (!value) continue;\n\n totalBytes += value.byteLength;\n if (totalBytes > maxBytes) {\n await reader.cancel();\n throw responseTooLargeError(maxBytes);\n }\n responseText += decoder.decode(value, { stream: true });\n }\n } finally {\n reader.releaseLock();\n }\n\n return responseText + decoder.decode();\n}\n\nfunction responseTooLargeError(maxBytes: number): JsonRpcError {\n return new JsonRpcError(\n JSON_RPC_ERROR_CODES.RESPONSE_TOO_LARGE,\n `JSON-RPC response exceeds maximum size of ${maxBytes} bytes`,\n \"local\",\n );\n}\n","/**\n * Type definitions for Vault Provider JSON-RPC API.\n *\n * These types match the `vaultProvider_*` RPC namespace defined by the\n * btc-vault daemon. They are the SDK's canonical copy of the VP protocol\n * contract, independent of any frontend framework.\n *\n * @see https://github.com/babylonlabs-io/btc-vault/blob/main/docs/pegin.md\n */\n\n// ============================================================================\n// Daemon Status\n// ============================================================================\n\n/**\n * Backend daemon status (vault provider database).\n * Source: btc-vault crates/vaultd/src/workers/claimer/mod.rs PegInStatus enum\n *\n * State flow (happy path):\n * PendingIngestion -> PendingDepositorWotsPK -> PendingBabeSetup -> PendingChallengerPresigning\n * -> PendingPeginSigsAvailability -> PendingPrePegInConfirmations\n * -> PendingDepositorSignatures -> PendingACKs -> PendingActivation -> Activated\n *\n * Terminal / branching states:\n * - Expired: vault timed out before activation\n * - ClaimPosted: claim transaction posted on-chain\n * - PeggedOut: BTC has been returned to the depositor\n */\nexport enum DaemonStatus {\n PENDING_INGESTION = \"PendingIngestion\",\n PENDING_DEPOSITOR_WOTS_PK = \"PendingDepositorWotsPK\",\n PENDING_BABE_SETUP = \"PendingBabeSetup\",\n PENDING_CHALLENGER_PRESIGNING = \"PendingChallengerPresigning\",\n PENDING_PEGIN_SIGS_AVAILABILITY = \"PendingPeginSigsAvailability\",\n PENDING_PRE_PEGIN_CONFIRMATIONS = \"PendingPrePegInConfirmations\",\n PENDING_DEPOSITOR_SIGNATURES = \"PendingDepositorSignatures\",\n PENDING_ACKS = \"PendingACKs\",\n PENDING_ACTIVATION = \"PendingActivation\",\n ACTIVATED = \"Activated\",\n EXPIRED = \"Expired\",\n CLAIM_POSTED = \"ClaimPosted\",\n PEGGED_OUT = \"PeggedOut\",\n}\n\n// ============================================================================\n// Status Groups\n// ============================================================================\n\n/**\n * States where the VP is still processing (no depositor action needed).\n * Excludes PENDING_DEPOSITOR_WOTS_PK (requires depositor action).\n */\nexport const PRE_DEPOSITOR_SIGNATURES_STATES: readonly DaemonStatus[] = [\n DaemonStatus.PENDING_INGESTION,\n DaemonStatus.PENDING_BABE_SETUP,\n DaemonStatus.PENDING_CHALLENGER_PRESIGNING,\n DaemonStatus.PENDING_PEGIN_SIGS_AVAILABILITY,\n DaemonStatus.PENDING_PRE_PEGIN_CONFIRMATIONS,\n];\n\n/** States after PendingDepositorSignatures where the depositor has no action. */\nconst POST_PAYOUT_SIGNATURE_STATUSES: readonly DaemonStatus[] = [\n DaemonStatus.PENDING_ACKS,\n DaemonStatus.PENDING_ACTIVATION,\n DaemonStatus.ACTIVATED,\n];\n\n/**\n * Statuses where no depositor action is needed (VP processing or already past\n * depositor interaction). Excludes PENDING_INGESTION and PENDING_DEPOSITOR_WOTS_PK.\n */\nexport const VP_TRANSIENT_STATUSES: ReadonlySet<DaemonStatus> = new Set([\n DaemonStatus.PENDING_BABE_SETUP,\n DaemonStatus.PENDING_CHALLENGER_PRESIGNING,\n DaemonStatus.PENDING_PEGIN_SIGS_AVAILABILITY,\n DaemonStatus.PENDING_PRE_PEGIN_CONFIRMATIONS,\n ...POST_PAYOUT_SIGNATURE_STATUSES,\n]);\n\n/**\n * Terminal VP statuses where no further progress is possible.\n * If the VP reaches one of these states while polling, polling should\n * stop immediately with an error rather than waiting for timeout.\n */\nexport const VP_TERMINAL_STATUSES: ReadonlySet<DaemonStatus> = new Set([\n DaemonStatus.EXPIRED,\n DaemonStatus.CLAIM_POSTED,\n DaemonStatus.PEGGED_OUT,\n]);\n\n/**\n * Statuses that come after WOTS key submission.\n * If the VP is already in one of these states, the WOTS key was already\n * submitted and we can skip.\n */\nexport const POST_WOTS_STATUSES: ReadonlySet<DaemonStatus> = new Set([\n ...VP_TRANSIENT_STATUSES,\n DaemonStatus.PENDING_DEPOSITOR_SIGNATURES,\n]);\n\n// ============================================================================\n// WOTS Types (needed by SubmitDepositorWotsKeyParams)\n// ============================================================================\n\n/**\n * WOTS configuration for a single block.\n * Matches Rust `babe::wots::Config` serde format.\n */\nexport interface WotsConfig {\n /** Digit bit-width (e.g. 4 → base-16 digits). */\n d: number;\n /** Number of message digits in this block. */\n n: number;\n /** Radix used for the checksum computation. */\n checksum_radix: number;\n}\n\n/**\n * A single block of WOTS public keys.\n * Chain values are arrays of byte values (matching Rust `[u8; 20]`).\n */\nexport interface WotsBlockPublicKey {\n config: WotsConfig;\n message_terminals: number[][];\n checksum_major_terminal: number[];\n checksum_minor_terminal: number[];\n}\n\n// ============================================================================\n// Request Parameter Types\n// ============================================================================\n\n/** Params for requesting the payout/claim/assert transactions to pre-sign. */\nexport interface RequestDepositorPresignTransactionsParams {\n pegin_txid: string;\n depositor_pk: string;\n}\n\n/** Params for submitting the depositor's WOTS public key to the VP. */\nexport interface SubmitDepositorWotsKeyParams {\n pegin_txid: string;\n depositor_pk: string;\n wots_public_keys: WotsBlockPublicKey[];\n}\n\n/** Per-challenger signatures for the depositor-as-claimer flow. */\nexport interface DepositorPreSigsPerChallenger {\n nopayout_signature: string;\n}\n\n/** Depositor-as-claimer pre-signatures (payout + per-challenger). */\nexport interface DepositorAsClaimerPresignatures {\n payout_signatures: ClaimerSignatures;\n per_challenger: Record<string, DepositorPreSigsPerChallenger>;\n}\n\n/** Params for submitting depositor pre-signatures including claimer presignatures. */\nexport interface SubmitDepositorPresignaturesParams {\n pegin_txid: string;\n depositor_pk: string;\n signatures: Record<string, ClaimerSignatures>;\n depositor_claimer_presignatures: DepositorAsClaimerPresignatures;\n}\n\n/** Payout signatures per claimer. */\nexport interface ClaimerSignatures {\n payout_signature: string;\n}\n\n/** Params for requesting BaBe DecryptorArtifacts from the VP. */\nexport interface RequestDepositorClaimerArtifactsParams {\n pegin_txid: string;\n depositor_pk: string;\n}\n\n/** Params for querying pegin status. Either pegin_txid or vault_id must be provided. */\nexport type GetPeginStatusParams =\n | { pegin_txid: string; vault_id?: never }\n | { vault_id: string; pegin_txid?: never };\n\n// ============================================================================\n// Response Types\n// ============================================================================\n\n/** A raw Bitcoin transaction with its hex encoding. */\nexport interface TransactionData {\n tx_hex: string;\n}\n\n/** Set of transactions the depositor must pre-sign for a single claimer. */\nexport interface ClaimerTransactions {\n claimer_pubkey: string;\n claim_tx: TransactionData;\n assert_tx: TransactionData;\n payout_tx: TransactionData;\n payout_psbt: string;\n}\n\n/** Per-segment connector data for ChallengeAssert inputs. */\nexport interface ChallengeAssertConnectorData {\n wots_pks_json: string;\n gc_wots_keys_json: string;\n}\n\n/** Challenger-specific transactions and signing data for the depositor graph. */\nexport interface PresignDataPerChallenger {\n challenger_pubkey: string;\n challenge_assert_x_tx: TransactionData;\n challenge_assert_y_tx: TransactionData;\n nopayout_tx: TransactionData;\n nopayout_psbt: string;\n challenge_assert_connectors: ChallengeAssertConnectorData[];\n output_label_hashes: string[];\n}\n\n/** Depositor-as-claimer TxGraph transactions. */\nexport interface DepositorGraphTransactions {\n claim_tx: TransactionData;\n assert_tx: TransactionData;\n payout_tx: TransactionData;\n payout_psbt: string;\n challenger_presign_data: PresignDataPerChallenger[];\n offchain_params_version: number;\n}\n\n/** Response from `requestDepositorPresignTransactions`. */\nexport interface RequestDepositorPresignTransactionsResponse {\n txs: ClaimerTransactions[];\n depositor_graph: DepositorGraphTransactions;\n}\n\n/** BaBe garbled-circuit session data for a single challenger. */\nexport interface BaBeSessionData {\n decryptor_artifacts_hex: string;\n}\n\n/** Response from `requestDepositorClaimerArtifacts`. */\nexport interface RequestDepositorClaimerArtifactsResponse {\n tx_graph_json: string;\n verifying_key_hex: string;\n babe_sessions: Record<string, BaBeSessionData>;\n}\n\n/** Progress tracker for a multi-challenger operation. */\nexport interface ChallengerProgress {\n total_challengers: number;\n completed_challengers: number;\n completed_challenger_pubkeys: string[];\n pending_challenger_pubkeys: string[];\n}\n\nexport type GcDataProgress = ChallengerProgress;\nexport type AckCollectionProgress = ChallengerProgress;\n\n/** Extended presigning progress with all 3 concurrent phases. */\nexport interface PresigningProgress extends ChallengerProgress {\n depositor_graph_created?: boolean;\n vk_challenger_presigning_completed?: number;\n vk_challenger_presigning_total?: number;\n}\n\n/** Detailed progress breakdown for an in-progress pegin. */\nexport interface PeginProgressDetails {\n gc_data?: GcDataProgress;\n presigning?: PresigningProgress;\n ack_collection?: AckCollectionProgress;\n claimer_graphs?: ClaimerGraphStatus[];\n}\n\n/** Per-claimer graph status (challenger perspective). */\nexport interface ClaimerGraphStatus {\n claimer_pubkey: string;\n presigned: boolean;\n}\n\n/** Response from `getPeginStatus`. */\nexport interface GetPeginStatusResponse {\n pegin_txid: string;\n status: string;\n progress: PeginProgressDetails;\n health_info: string;\n last_error?: string;\n}\n\n// ============================================================================\n// Pegout Types\n// ============================================================================\n\n/** Params for querying pegout status from the VP daemon. */\nexport interface GetPegoutStatusParams {\n pegin_txid: string;\n}\n\n/** Claimer-side pegout progress. */\nexport interface ClaimerPegoutStatus {\n status: string;\n failed: boolean;\n claim_txid?: string;\n claimer_pubkey?: string;\n challenger_pubkey?: string;\n created_at?: string;\n updated_at?: string;\n}\n\n/** Challenger-side pegout progress. */\nexport interface ChallengerPegoutStatus {\n status: string;\n claim_txid?: string;\n claimer_pubkey?: string;\n assert_txid?: string;\n challenge_assert_txid?: string;\n nopayout_txid?: string;\n created_at?: string;\n updated_at?: string;\n}\n\n/** Response from `getPegoutStatus`. */\nexport interface GetPegoutStatusResponse {\n pegin_txid: string;\n found: boolean;\n claimer?: ClaimerPegoutStatus;\n challenger?: ChallengerPegoutStatus;\n}\n\n// ============================================================================\n// Error Codes\n// ============================================================================\n\n/** JSON-RPC error codes returned by the vault provider. */\nexport enum RpcErrorCode {\n DATABASE_ERROR = -32005,\n PRESIGN_ERROR = -32006,\n JSON_SERIALIZATION_ERROR = -32007,\n TX_GRAPH_ERROR = -32008,\n INVALID_GRAPH = -32009,\n VALIDATION_ERROR = -32010,\n NOT_FOUND = -32011,\n INTERNAL_ERROR = -32603,\n}\n"],"names":["JsonRpcError","code","message","source","data","JSON_RPC_ERROR_CODES","JSON_RPC_VERSION","DEFAULT_RETRY_ATTEMPTS","DEFAULT_RETRY_DELAY_MS","DEFAULT_MAX_RESPONSE_BYTES","UNCAPPED_TYPED_RESPONSE_METHODS","RETRYABLE_HTTP_STATUS_CODES","DEFAULT_RETRYABLE_METHODS","defaultRetryableFor","method","AUTH_EXPIRED_DATA_KIND","isAuthExpiredError","error","JsonRpcClient","config","__publicField","headers","token","params","signal","response","jsonResponse","responseText","readResponseTextWithLimit","rpcResponse","err","callerSignal","requestId","maxRetries","body","lastError","attempt","timeoutController","timeoutId","merged","mergeAbortSignals","delay","ms","resolve","reject","onAbort","a","b","controller","onAbortA","onAbortB","cleanup","maxBytes","contentLength","parsedContentLength","responseTooLargeError","reader","decoder","totalBytes","done","value","DaemonStatus","PRE_DEPOSITOR_SIGNATURES_STATES","POST_PAYOUT_SIGNATURE_STATUSES","VP_TRANSIENT_STATUSES","VP_TERMINAL_STATUSES","POST_WOTS_STATUSES","RpcErrorCode"],"mappings":";;;AAoGO,MAAMA,UAAqB,MAAM;AAAA,EACtC,YACSC,GACPC,GAEOC,IAA6B,SAE7BC,GACP;AACA,UAAMF,CAAO,GAPN,KAAA,OAAAD,GAGA,KAAA,SAAAE,GAEA,KAAA,OAAAC,GAGP,KAAK,OAAO;AAAA,EACd;AACF;AAEO,MAAMC,IAAuB;AAAA,EAClC,SAAS;AAAA,EACT,SAAS;AAAA;AAAA,EAET,eAAe;AAAA;AAAA,EAEf,mBAAmB;AAAA;AAAA,EAEnB,kBAAkB;AAAA;AAAA,EAElB,oBAAoB;AACtB,GAGMC,IAAmB,OAGnBC,IAAyB,GAGzBC,IAAyB,KAGzBC,IAA6B,IAAI,OAAO,MAMxCC,wBAA2D,IAAI;AAAA,EACnE;AACF,CAAC,GAGKC,wBAAuD,IAAI;AAAA,EAC/D;AAAA;AAAA,EACA;AAAA;AAAA,EACA;AAAA;AAAA,EACA;AAAA;AAAA,EACA;AAAA;AAAA,EACA;AAAA;AACF,CAAC,GAGKC,wBAAqD,IAAI;AAAA,EAC7D;AAAA,EACA;AAAA,EACA;AACF,CAAC;AAED,SAASC,EAAoBC,GAAyB;AACpD,SAAOF,EAA0B,IAAIE,CAAM;AAC7C;AAYA,MAAMC,IAAyB;AAE/B,SAASC,EAAmBC,GAAyB;AAEnD,MADI,EAAEA,aAAiBjB,MACnBiB,EAAM,WAAW,OAAQ,QAAO;AACpC,QAAMb,IAAOa,EAAM;AACnB,SAAIb,MAAS,QAAQ,OAAOA,KAAS,WAAiB,KACxCA,EAA4B,SAC1BW;AAClB;AAKO,MAAMG,EAAc;AAAA,EAWzB,YAAYC,GAA6B;AAVjC,IAAAC,EAAA;AACA,IAAAA,EAAA;AACA,IAAAA,EAAA;AACA,IAAAA,EAAA,mBAAY;AACZ,IAAAA,EAAA;AACA,IAAAA,EAAA;AACA,IAAAA,EAAA;AACA,IAAAA,EAAA;AACA,IAAAA,EAAA;AAaN,QAVA,KAAK,UAAUD,EAAO,QAAQ,QAAQ,OAAO,EAAE,GAC/C,KAAK,UAAUA,EAAO,SACtB,KAAK,UAAU;AAAA,MACb,gBAAgB;AAAA,MAChB,GAAGA,EAAO;AAAA,IAAA,GAEZ,KAAK,UAAUA,EAAO,WAAWZ,GACjC,KAAK,aAAaY,EAAO,cAAcX,GACvC,KAAK,mBACHW,EAAO,oBAAoBV,GACzB,CAAC,OAAO,SAAS,KAAK,gBAAgB,KAAK,KAAK,oBAAoB;AACtE,YAAM,IAAI,MAAM,mDAAmD;AAErE,SAAK,eAAeU,EAAO,gBAAgBN,GAC3C,KAAK,gBAAgBM,EAAO;AAAA,EAC9B;AAAA,EAEA,MAAc,aAAaL,GAAiD;AAC1E,UAAMO,IAAkC,EAAE,GAAG,KAAK,QAAA;AAClD,QAAI,KAAK,eAAe;AACtB,YAAMC,IAAQ,MAAM,KAAK,cAAc,SAASR,CAAM;AACtD,MAAIQ,MACFD,EAAQ,gBAAgB,UAAUC,CAAK;AAAA,IAE3C;AACA,WAAOD;AAAA,EACT;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAeA,MAAM,KACJP,GACAS,GACAC,GACkB;AAClB,QAAI;AACF,aAAO,MAAM,KAAK,SAA2BV,GAAQS,GAAQC,CAAM;AAAA,IACrE,SAASP,GAAO;AAWd,UAAI,KAAK,iBAAiBD,EAAmBC,CAAK;AAChD,oBAAK,cAAc,WAAA,GACZ,MAAM,KAAK,SAA2BH,GAAQS,GAAQC,CAAM;AAErE,YAAMP;AAAA,IACR;AAAA,EACF;AAAA,EAEA,MAAc,SACZH,GACAS,GACAC,GACkB;AAClB,UAAMC,IAAW,MAAM,KAAK,eAAeX,GAAQS,GAAQC,CAAM;AAEjE,QAAIE;AACJ,QAAI;AACF,YAAMC,IAAejB,EAAgC,IAAII,CAAM,IAC3D,MAAMW,EAAS,KAAA,IACf,MAAMG,EAA0BH,GAAU,KAAK,gBAAgB;AACnE,MAAAC,IAAe,KAAK,MAAMC,CAAY;AAAA,IACxC,SAASV,GAAO;AACd,YAAIA,aAAiBjB,IACbiB,IAEF,IAAIjB;AAAA,QACRK,EAAqB;AAAA,QACrB;AAAA,QACA;AAAA,MAAA;AAAA,IAEJ;AAEA,QACEqB,MAAiB,QACjB,OAAOA,KAAiB,YACxB,MAAM,QAAQA,CAAY;AAE1B,YAAM,IAAI1B;AAAA,QACRK,EAAqB;AAAA,QACrB,sDAAsD,OAAOqB,CAAY;AAAA,QACzE;AAAA,MAAA;AAIJ,UAAMG,IAAcH;AAEpB,QAAI,WAAWG,KAAeA,EAAY,SAAS,MAAM;AACvD,YAAMC,IAAMD,EAAY;AAKxB,YAAM,IAAI7B;AAAA,QACR8B,EAAI,QAAQzB,EAAqB;AAAA,QACjCyB,EAAI,WAAW;AAAA,QACf;AAAA,QACAA,EAAI;AAAA,MAAA;AAAA,IAER;AAEA,QAAI,EAAE,YAAYD;AAChB,YAAM,IAAI7B;AAAA,QACRK,EAAqB;AAAA,QACrB;AAAA,QACA;AAAA,MAAA;AAIJ,WAAOwB,EAAY;AAAA,EACrB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAYA,MAAM,QACJf,GACAS,GACAC,GACmB;AACnB,WAAO,KAAK,eAAeV,GAAQS,GAAQC,CAAM;AAAA,EACnD;AAAA,EAEA,MAAc,eACZV,GACAS,GACAQ,GACmB;AACnB,UAAMC,IAAY,EAAE,KAAK,WACnBC,IAAa,KAAK,aAAanB,CAAM,IAAI,KAAK,UAAU,GAUxDoB,IAAO,KAAK,UAPyB;AAAA,MACzC,SAAS5B;AAAA,MACT,QAAAQ;AAAA,MACA,QAAQ,CAACS,CAAM;AAAA,MACf,IAAIS;AAAA,IAAA,CAG6B;AACnC,QAAIG,IAA0B;AAE9B,aAASC,IAAU,GAAGA,KAAWH,GAAYG,KAAW;AAEtD,YAAMC,IAAoB,IAAI,gBAAA,GACxBC,IAAY;AAAA,QAChB,MAAMD,EAAkB,MAAA;AAAA,QACxB,KAAK;AAAA,MAAA,GAGDE,IAASR,IACXS,EAAkBT,GAAcM,EAAkB,MAAM,IACxD,MACEb,IAASe,IAASA,EAAO,SAASF,EAAkB;AAE1D,UAAI;AAIF,cAAMhB,IAAU,MAAM,KAAK,aAAaP,CAAM,GAExCW,IAAW,MAAM,MAAM,KAAK,SAAS;AAAA,UACzC,QAAQ;AAAA,UACR,SAAAJ;AAAA,UACA,MAAAa;AAAA,UACA,QAAAV;AAAA,QAAA,CACD;AAKD,YAHA,aAAac,CAAS,GACtBC,KAAA,QAAAA,EAAQ,WAEJ,CAACd,EAAS,IAAI;AAKhB,cAHEW,IAAUH,KACVtB,EAA4B,IAAIc,EAAS,MAAM,GAEhC;AACf,kBAAMgB,IAAQ,KAAK,aAAa,KAAK,IAAI,GAAGL,CAAO;AACnD,kBAAM,KAAK,MAAMK,GAAOV,CAAY;AACpC;AAAA,UACF;AAEA,gBAAM,IAAI;AAAA,YACR,eAAeN,EAAS,MAAM,IAAIA,EAAS,UAAU;AAAA,UAAA;AAAA,QAEzD;AAEA,eAAOA;AAAA,MACT,SAASR,GAAO;AAMd,YALA,aAAaqB,CAAS,GACtBC,KAAA,QAAAA,EAAQ,WACRJ,IAAYlB,aAAiB,QAAQA,IAAQ,IAAI,MAAM,OAAOA,CAAK,CAAC,GAGhEc,KAAA,QAAAA,EAAc;AAChB,gBAAM,IAAI,MAAM,iBAAiB;AAGnC,YAAId,aAAiB,SAASA,EAAM,SAAS,cAAc;AACzD,cAAImB,IAAUH,GAAY;AACxB,kBAAMQ,IAAQ,KAAK,aAAa,KAAK,IAAI,GAAGL,CAAO;AACnD,kBAAM,KAAK,MAAMK,GAAOV,CAAY;AACpC;AAAA,UACF;AACA,gBAAM,IAAI/B;AAAA,YACRK,EAAqB;AAAA,YACrB,yBAAyB,KAAK,OAAO,OAAO4B,IAAa,CAAC;AAAA,YAC1D;AAAA,UAAA;AAAA,QAEJ;AAGA,YAAIhB,aAAiB,WAAW;AAC9B,cAAImB,IAAUH,GAAY;AACxB,kBAAMQ,IAAQ,KAAK,aAAa,KAAK,IAAI,GAAGL,CAAO;AACnD,kBAAM,KAAK,MAAMK,GAAOV,CAAY;AACpC;AAAA,UACF;AACA,gBAAM,IAAI/B;AAAA,YACRK,EAAqB;AAAA,YACrB,kBAAkBY,EAAM,OAAO,KAAKgB,IAAa,CAAC;AAAA,YAClD;AAAA,UAAA;AAAA,QAEJ;AAGA,cAAMhB;AAAA,MACR;AAAA,IACF;AAEA,UAAMkB,KAAa,IAAI,MAAM,6BAA6B;AAAA,EAC5D;AAAA,EAEQ,MAAMO,GAAYlB,GAAqC;AAC7D,WAAO,IAAI,QAAQ,CAACmB,GAASC,MAAW;AACtC,UAAIpB,KAAA,QAAAA,EAAQ,SAAS;AACnB,QAAAoB,EAAO,IAAI,MAAM,iBAAiB,CAAC;AACnC;AAAA,MACF;AACA,YAAMN,IAAY,WAAW,MAAM;AACjC,QAAAd,KAAA,QAAAA,EAAQ,oBAAoB,SAASqB,IACrCF,EAAA;AAAA,MACF,GAAGD,CAAE,GACCG,IAAU,MAAM;AACpB,qBAAaP,CAAS,GACtBM,EAAO,IAAI,MAAM,iBAAiB,CAAC;AAAA,MACrC;AACA,MAAApB,KAAA,QAAAA,EAAQ,iBAAiB,SAASqB,GAAS,EAAE,MAAM;IACrD,CAAC;AAAA,EACH;AAAA,EAEA,aAAqB;AACnB,WAAO,KAAK;AAAA,EACd;AACF;AAaA,SAASL,EAAkBM,GAAgBC,GAA8B;AACvE,MAAID,EAAE,QAAS,QAAO,EAAE,QAAQA,GAAG,SAAS,MAAM;AAAA,EAAC,EAAA;AACnD,MAAIC,EAAE,QAAS,QAAO,EAAE,QAAQA,GAAG,SAAS,MAAM;AAAA,EAAC,EAAA;AAEnD,QAAMC,IAAa,IAAI,gBAAA,GACjBC,IAAW,MAAM;AACrB,IAAAF,EAAE,oBAAoB,SAASG,CAAQ,GACvCF,EAAW,MAAA;AAAA,EACb,GACME,IAAW,MAAM;AACrB,IAAAJ,EAAE,oBAAoB,SAASG,CAAQ,GACvCD,EAAW,MAAA;AAAA,EACb;AACA,EAAAF,EAAE,iBAAiB,SAASG,GAAU,EAAE,MAAM,IAAM,GACpDF,EAAE,iBAAiB,SAASG,GAAU,EAAE,MAAM,IAAM;AAEpD,QAAMC,IAAU,MAAM;AACpB,IAAAL,EAAE,oBAAoB,SAASG,CAAQ,GACvCF,EAAE,oBAAoB,SAASG,CAAQ;AAAA,EACzC;AAEA,SAAO,EAAE,QAAQF,EAAW,QAAQ,SAAAG,EAAA;AACtC;AAEA,eAAevB,EACbH,GACA2B,GACiB;AACjB,QAAMC,IAAgB5B,EAAS,QAAQ,IAAI,gBAAgB;AAC3D,MAAI4B,MAAkB,MAAM;AAC1B,UAAMC,IAAsB,OAAOD,CAAa;AAChD,QACE,OAAO,SAASC,CAAmB,KACnCA,IAAsBF;AAEtB,YAAMG,EAAsBH,CAAQ;AAAA,EAExC;AAEA,MAAI,CAAC3B,EAAS;AACZ,WAAO;AAGT,QAAM+B,IAAS/B,EAAS,KAAK,UAAA,GACvBgC,IAAU,IAAI,YAAA;AACpB,MAAIC,IAAa,GACb/B,IAAe;AAEnB,MAAI;AACF,eAAS;AACP,YAAM,EAAE,MAAAgC,GAAM,OAAAC,EAAA,IAAU,MAAMJ,EAAO,KAAA;AACrC,UAAIG,EAAM;AACV,UAAKC,GAGL;AAAA,YADAF,KAAcE,EAAM,YAChBF,IAAaN;AACf,sBAAMI,EAAO,OAAA,GACPD,EAAsBH,CAAQ;AAEtC,QAAAzB,KAAgB8B,EAAQ,OAAOG,GAAO,EAAE,QAAQ,IAAM;AAAA;AAAA,IACxD;AAAA,EACF,UAAA;AACE,IAAAJ,EAAO,YAAA;AAAA,EACT;AAEA,SAAO7B,IAAe8B,EAAQ,OAAA;AAChC;AAEA,SAASF,EAAsBH,GAAgC;AAC7D,SAAO,IAAIpD;AAAA,IACTK,EAAqB;AAAA,IACrB,6CAA6C+C,CAAQ;AAAA,IACrD;AAAA,EAAA;AAEJ;AC9hBO,IAAKS,sBAAAA,OACVA,EAAA,oBAAoB,oBACpBA,EAAA,4BAA4B,0BAC5BA,EAAA,qBAAqB,oBACrBA,EAAA,gCAAgC,+BAChCA,EAAA,kCAAkC,gCAClCA,EAAA,kCAAkC,gCAClCA,EAAA,+BAA+B,8BAC/BA,EAAA,eAAe,eACfA,EAAA,qBAAqB,qBACrBA,EAAA,YAAY,aACZA,EAAA,UAAU,WACVA,EAAA,eAAe,eACfA,EAAA,aAAa,aAbHA,IAAAA,KAAA,CAAA,CAAA;AAwBL,MAAMC,IAA2D;AAAA,EACtE;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA;AACF,GAGMC,IAA0D;AAAA,EAC9D;AAAA,EACA;AAAA,EACA;AAAA;AACF,GAMaC,wBAAuD,IAAI;AAAA,EACtE;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA,GAAGD;AACL,CAAC,GAOYE,wBAAsD,IAAI;AAAA,EACrE;AAAA,EACA;AAAA,EACA;AAAA;AACF,CAAC,GAOYC,wBAAoD,IAAI;AAAA,EACnE,GAAGF;AAAA,EACH;AAAA;AACF,CAAC;AAuOM,IAAKG,sBAAAA,OACVA,EAAAA,EAAA,iBAAiB,MAAA,IAAjB,kBACAA,EAAAA,EAAA,gBAAgB,MAAA,IAAhB,iBACAA,EAAAA,EAAA,2BAA2B,MAAA,IAA3B,4BACAA,EAAAA,EAAA,iBAAiB,MAAA,IAAjB,kBACAA,EAAAA,EAAA,gBAAgB,MAAA,IAAhB,iBACAA,EAAAA,EAAA,mBAAmB,MAAA,IAAnB,oBACAA,EAAAA,EAAA,YAAY,MAAA,IAAZ,aACAA,EAAAA,EAAA,iBAAiB,MAAA,IAAjB,kBARUA,IAAAA,KAAA,CAAA,CAAA;"}
@@ -1,2 +0,0 @@
1
- "use strict";var y=Object.defineProperty;var b=(e,t,r)=>t in e?y(e,t,{enumerable:!0,configurable:!0,writable:!0,value:r}):e[t]=r;var P=(e,t,r)=>b(e,typeof t!="symbol"?t+"":t,r);class R extends Error{constructor(t,r,n="local",o){super(r),this.code=t,this.source=n,this.data=o,this.name="JsonRpcError"}}const u={TIMEOUT:-32e3,NETWORK:-32001,PROXY_TIMEOUT:-32002,PROXY_UNAVAILABLE:-32003,INVALID_RESPONSE:-32700,RESPONSE_TOO_LARGE:-32701},f="2.0",p=3,D=1e3,L=2*1024*1024,v=new Set(["vaultProvider_requestDepositorClaimerArtifacts"]),g=new Set([408,429,500,502,503,504]),U=new Set(["vaultProvider_getPeginStatus","vaultProvider_getPegoutStatus","vaultProvider_requestDepositorPresignTransactions"]);function m(e){return U.has(e)}const G="auth_expired";function C(e){if(!(e instanceof R)||e.source!=="wire")return!1;const t=e.data;return t===null||typeof t!="object"?!1:t.kind===G}class B{constructor(t){P(this,"baseUrl");P(this,"timeout");P(this,"headers");P(this,"requestId",0);P(this,"retries");P(this,"retryDelay");P(this,"maxResponseBytes");P(this,"retryableFor");P(this,"tokenProvider");if(this.baseUrl=t.baseUrl.replace(/\/$/,""),this.timeout=t.timeout,this.headers={"Content-Type":"application/json",...t.headers},this.retries=t.retries??p,this.retryDelay=t.retryDelay??D,this.maxResponseBytes=t.maxResponseBytes??L,!Number.isFinite(this.maxResponseBytes)||this.maxResponseBytes<=0)throw new Error("maxResponseBytes must be a positive finite number");this.retryableFor=t.retryableFor??m,this.tokenProvider=t.tokenProvider}async buildHeaders(t){const r={...this.headers};if(this.tokenProvider){const n=await this.tokenProvider.getToken(t);n&&(r.Authorization=`Bearer ${n}`)}return r}async call(t,r,n){try{return await this.callOnce(t,r,n)}catch(o){if(this.tokenProvider&&C(o))return this.tokenProvider.invalidate(),await this.callOnce(t,r,n);throw o}}async callOnce(t,r,n){const o=await this.fetchWithRetry(t,r,n);let s;try{const i=v.has(t)?await o.text():await k(o,this.maxResponseBytes);s=JSON.parse(i)}catch(i){throw i instanceof R?i:new R(u.INVALID_RESPONSE,"Invalid JSON-RPC response: body is not valid JSON","local")}if(s===null||typeof s!="object"||Array.isArray(s))throw new R(u.INVALID_RESPONSE,`Invalid JSON-RPC response: expected an object, got ${typeof s}`,"local");const a=s;if("error"in a&&a.error!=null){const i=a.error;throw new R(i.code??u.INVALID_RESPONSE,i.message??"Unknown RPC error","wire",i.data)}if(!("result"in a))throw new R(u.INVALID_RESPONSE,'Invalid JSON-RPC response: missing "result" field',"local");return a.result}async callRaw(t,r,n){return this.fetchWithRetry(t,r,n)}async fetchWithRetry(t,r,n){const o=++this.requestId,s=this.retryableFor(t)?this.retries:0,i=JSON.stringify({jsonrpc:f,method:t,params:[r],id:o});let l=null;for(let T=0;T<=s;T++){const A=new AbortController,S=setTimeout(()=>A.abort(),this.timeout),_=n?x(n,A.signal):null,I=_?_.signal:A.signal;try{const E=await this.buildHeaders(t),c=await fetch(this.baseUrl,{method:"POST",headers:E,body:i,signal:I});if(clearTimeout(S),_==null||_.cleanup(),!c.ok){if(T<s&&g.has(c.status)){const w=this.retryDelay*Math.pow(2,T);await this.sleep(w,n);continue}throw new Error(`HTTP error: ${c.status} ${c.statusText}`)}return c}catch(E){if(clearTimeout(S),_==null||_.cleanup(),l=E instanceof Error?E:new Error(String(E)),n!=null&&n.aborted)throw new Error("Request aborted");if(E instanceof Error&&E.name==="AbortError"){if(T<s){const c=this.retryDelay*Math.pow(2,T);await this.sleep(c,n);continue}throw new R(u.TIMEOUT,`Request timeout after ${this.timeout}ms (${s+1} attempts)`,"local")}if(E instanceof TypeError){if(T<s){const c=this.retryDelay*Math.pow(2,T);await this.sleep(c,n);continue}throw new R(u.NETWORK,`Network error: ${E.message} (${s+1} attempts)`,"local")}throw E}}throw l||new Error("Unknown error after retries")}sleep(t,r){return new Promise((n,o)=>{if(r!=null&&r.aborted){o(new Error("Request aborted"));return}const s=setTimeout(()=>{r==null||r.removeEventListener("abort",a),n()},t),a=()=>{clearTimeout(s),o(new Error("Request aborted"))};r==null||r.addEventListener("abort",a,{once:!0})})}getBaseUrl(){return this.baseUrl}}function x(e,t){if(e.aborted)return{signal:e,cleanup:()=>{}};if(t.aborted)return{signal:t,cleanup:()=>{}};const r=new AbortController,n=()=>{t.removeEventListener("abort",o),r.abort()},o=()=>{e.removeEventListener("abort",n),r.abort()};e.addEventListener("abort",n,{once:!0}),t.addEventListener("abort",o,{once:!0});const s=()=>{e.removeEventListener("abort",n),t.removeEventListener("abort",o)};return{signal:r.signal,cleanup:s}}async function k(e,t){const r=e.headers.get("content-length");if(r!==null){const i=Number(r);if(Number.isFinite(i)&&i>t)throw d(t)}if(!e.body)return"";const n=e.body.getReader(),o=new TextDecoder;let s=0,a="";try{for(;;){const{done:i,value:l}=await n.read();if(i)break;if(l){if(s+=l.byteLength,s>t)throw await n.cancel(),d(t);a+=o.decode(l,{stream:!0})}}}finally{n.releaseLock()}return a+o.decode()}function d(e){return new R(u.RESPONSE_TOO_LARGE,`JSON-RPC response exceeds maximum size of ${e} bytes`,"local")}var N=(e=>(e.PENDING_INGESTION="PendingIngestion",e.PENDING_DEPOSITOR_WOTS_PK="PendingDepositorWotsPK",e.PENDING_BABE_SETUP="PendingBabeSetup",e.PENDING_CHALLENGER_PRESIGNING="PendingChallengerPresigning",e.PENDING_PEGIN_SIGS_AVAILABILITY="PendingPeginSigsAvailability",e.PENDING_PRE_PEGIN_CONFIRMATIONS="PendingPrePegInConfirmations",e.PENDING_DEPOSITOR_SIGNATURES="PendingDepositorSignatures",e.PENDING_ACKS="PendingACKs",e.PENDING_ACTIVATION="PendingActivation",e.ACTIVATED="Activated",e.EXPIRED="Expired",e.CLAIM_POSTED="ClaimPosted",e.PEGGED_OUT="PeggedOut",e))(N||{});const V=["PendingIngestion","PendingBabeSetup","PendingChallengerPresigning","PendingPeginSigsAvailability","PendingPrePegInConfirmations"],J=["PendingACKs","PendingActivation","Activated"],O=new Set(["PendingBabeSetup","PendingChallengerPresigning","PendingPeginSigsAvailability","PendingPrePegInConfirmations",...J]),M=new Set(["Expired","ClaimPosted","PeggedOut"]),F=new Set([...O,"PendingDepositorSignatures"]);var h=(e=>(e[e.DATABASE_ERROR=-32005]="DATABASE_ERROR",e[e.PRESIGN_ERROR=-32006]="PRESIGN_ERROR",e[e.JSON_SERIALIZATION_ERROR=-32007]="JSON_SERIALIZATION_ERROR",e[e.TX_GRAPH_ERROR=-32008]="TX_GRAPH_ERROR",e[e.INVALID_GRAPH=-32009]="INVALID_GRAPH",e[e.VALIDATION_ERROR=-32010]="VALIDATION_ERROR",e[e.NOT_FOUND=-32011]="NOT_FOUND",e[e.INTERNAL_ERROR=-32603]="INTERNAL_ERROR",e))(h||{});exports.DaemonStatus=N;exports.JSON_RPC_ERROR_CODES=u;exports.JsonRpcClient=B;exports.JsonRpcError=R;exports.POST_WOTS_STATUSES=F;exports.PRE_DEPOSITOR_SIGNATURES_STATES=V;exports.RpcErrorCode=h;exports.VP_TERMINAL_STATUSES=M;exports.VP_TRANSIENT_STATUSES=O;
2
- //# sourceMappingURL=types-CfCZyfid.cjs.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"types-CfCZyfid.cjs","sources":["../src/tbv/core/clients/vault-provider/json-rpc-client.ts","../src/tbv/core/clients/vault-provider/types.ts"],"sourcesContent":["/**\n * Generic JSON-RPC 2.0 HTTP Client\n *\n * Framework-agnostic client using `fetch()` — works in browsers and Node.js 18+.\n * Includes configurable retry policy and AbortSignal passthrough.\n */\n\nexport interface JsonRpcRequest<T = unknown> {\n jsonrpc: \"2.0\";\n method: string;\n params: T;\n id: number | string;\n}\n\nexport interface JsonRpcSuccessResponse<T = unknown> {\n jsonrpc: \"2.0\";\n result: T;\n id: number | string;\n}\n\nexport interface JsonRpcErrorResponse {\n jsonrpc: \"2.0\";\n error: {\n code: number;\n message: string;\n data?: unknown;\n };\n id: number | string;\n}\n\nexport type JsonRpcResponse<T = unknown> =\n | JsonRpcSuccessResponse<T>\n | JsonRpcErrorResponse;\n\n/**\n * Injects bearer tokens into requests for auth-gated methods, and is\n * notified on auth-expired responses so it can invalidate its cache.\n *\n * The `JsonRpcClient` is agnostic to which methods are auth-gated —\n * the provider's `getToken(method)` decides. Returning `null` means\n * \"no auth required for this method\"; the client then sends the\n * request with no `Authorization` header.\n */\nexport interface BearerTokenProvider {\n /**\n * Return the bearer token to inject for `method`, or `null` if the\n * method does not require auth.\n */\n getToken(method: string): Promise<string | null>;\n /**\n * Drop the cached token. Next call to `getToken` must re-acquire.\n * Called by the client on reactive-refresh-trigger responses.\n */\n invalidate(): void;\n}\n\nexport interface JsonRpcClientConfig {\n /** Base URL of the RPC service */\n baseUrl: string;\n /** Timeout in milliseconds per request attempt */\n timeout: number;\n /** Optional custom headers */\n headers?: Record<string, string>;\n /** Number of retry attempts for transient errors (default: 3) */\n retries?: number;\n /** Initial retry delay in milliseconds (default: 1000) */\n retryDelay?: number;\n /**\n * Maximum response body size, in bytes, for typed JSON-RPC calls.\n * `callRaw` intentionally returns the unparsed Response and is not capped here.\n * Default: 2 MiB.\n */\n maxResponseBytes?: number;\n /**\n * Predicate that decides which methods retry on transient errors.\n * Default retries only `getPeginStatus`, `getPegoutStatus`, and\n * `requestDepositorPresignTransactions`. Write methods are not\n * retried by default.\n */\n retryableFor?: (method: string) => boolean;\n /**\n * Per-request bearer-token source. A non-null return attaches\n * `Authorization: Bearer <token>`; `null` skips auth. `call`\n * additionally retries once on wire `auth_expired` (invalidate +\n * refetch + retry). `callRaw` skips reactive refresh.\n */\n tokenProvider?: BearerTokenProvider;\n}\n\n/**\n * Identifies whether an error was produced locally (timeout, network\n * failure, malformed response) or parsed from a wire-format JSON-RPC\n * error envelope returned by the server.\n *\n * This matters for anyone inspecting the shared `-32001` code: the SDK\n * uses it internally for network failures AND the server uses it for\n * auth-middleware rejections. The `source` field disambiguates.\n */\nexport type JsonRpcErrorSource = \"wire\" | \"local\";\n\nexport class JsonRpcError extends Error {\n constructor(\n public code: number,\n message: string,\n /** \"wire\" for server-returned envelopes; \"local\" for SDK-side failures. */\n public source: JsonRpcErrorSource = \"local\",\n /** Structured data from the server `error.data` field, if any. */\n public data?: unknown,\n ) {\n super(message);\n this.name = \"JsonRpcError\";\n }\n}\n\nexport const JSON_RPC_ERROR_CODES = {\n TIMEOUT: -32000,\n NETWORK: -32001,\n /** VP proxy: request timed out at proxy level */\n PROXY_TIMEOUT: -32002,\n /** VP proxy: VP unreachable / DNS failure / response too large */\n PROXY_UNAVAILABLE: -32003,\n /** SDK client: response missing \"result\" field (malformed JSON-RPC) */\n INVALID_RESPONSE: -32700,\n /** SDK client: response body exceeded the configured byte limit */\n RESPONSE_TOO_LARGE: -32701,\n} as const;\n\n/** JSON-RPC protocol version */\nconst JSON_RPC_VERSION = \"2.0\" as const;\n\n/** Default number of retry attempts for transient errors */\nconst DEFAULT_RETRY_ATTEMPTS = 3;\n\n/** Default initial retry delay in milliseconds */\nconst DEFAULT_RETRY_DELAY_MS = 1000;\n\n/** Default maximum JSON-RPC response size for typed calls (2 MiB) */\nconst DEFAULT_MAX_RESPONSE_BYTES = 2 * 1024 * 1024;\n\n/**\n * TODO: Temporary typed-call exceptions for methods that currently return large\n * artifact payloads as JSON-RPC results.\n */\nconst UNCAPPED_TYPED_RESPONSE_METHODS: ReadonlySet<string> = new Set([\n \"vaultProvider_requestDepositorClaimerArtifacts\",\n]);\n\n/** HTTP status codes that indicate transient server errors and are safe to retry */\nconst RETRYABLE_HTTP_STATUS_CODES: ReadonlySet<number> = new Set([\n 408, // Request Timeout\n 429, // Too Many Requests\n 500, // Internal Server Error\n 502, // Bad Gateway\n 503, // Service Unavailable\n 504, // Gateway Timeout\n]);\n\n/** Default retry predicate: only retry read-only / idempotent methods */\nconst DEFAULT_RETRYABLE_METHODS: ReadonlySet<string> = new Set([\n \"vaultProvider_getPeginStatus\",\n \"vaultProvider_getPegoutStatus\",\n \"vaultProvider_requestDepositorPresignTransactions\",\n]);\n\nfunction defaultRetryableFor(method: string): boolean {\n return DEFAULT_RETRYABLE_METHODS.has(method);\n}\n\n/**\n * Token-expired marker the server emits in `error.data.kind`. When\n * present on a wire-origin error, the client invalidates its cached\n * token and retries the request once with a freshly-acquired bearer.\n *\n * Kept in sync with btc-vault's auth middleware. Absence of the marker\n * means the server does not support reactive refresh yet; we fall back\n * to proactive-only refresh via `BearerTokenProvider.getToken()` TTL\n * checks.\n */\nconst AUTH_EXPIRED_DATA_KIND = \"auth_expired\";\n\nfunction isAuthExpiredError(error: unknown): boolean {\n if (!(error instanceof JsonRpcError)) return false;\n if (error.source !== \"wire\") return false;\n const data = error.data;\n if (data === null || typeof data !== \"object\") return false;\n const kind = (data as { kind?: unknown }).kind;\n return kind === AUTH_EXPIRED_DATA_KIND;\n}\n\n/**\n * Generic JSON-RPC 2.0 HTTP client with safe retry policy.\n */\nexport class JsonRpcClient {\n private baseUrl: string;\n private timeout: number;\n private headers: Record<string, string>;\n private requestId = 0;\n private retries: number;\n private retryDelay: number;\n private maxResponseBytes: number;\n private retryableFor: (method: string) => boolean;\n private tokenProvider?: BearerTokenProvider;\n\n constructor(config: JsonRpcClientConfig) {\n this.baseUrl = config.baseUrl.replace(/\\/$/, \"\");\n this.timeout = config.timeout;\n this.headers = {\n \"Content-Type\": \"application/json\",\n ...config.headers,\n };\n this.retries = config.retries ?? DEFAULT_RETRY_ATTEMPTS;\n this.retryDelay = config.retryDelay ?? DEFAULT_RETRY_DELAY_MS;\n this.maxResponseBytes =\n config.maxResponseBytes ?? DEFAULT_MAX_RESPONSE_BYTES;\n if (!Number.isFinite(this.maxResponseBytes) || this.maxResponseBytes <= 0) {\n throw new Error(\"maxResponseBytes must be a positive finite number\");\n }\n this.retryableFor = config.retryableFor ?? defaultRetryableFor;\n this.tokenProvider = config.tokenProvider;\n }\n\n private async buildHeaders(method: string): Promise<Record<string, string>> {\n const headers: Record<string, string> = { ...this.headers };\n if (this.tokenProvider) {\n const token = await this.tokenProvider.getToken(method);\n if (token) {\n headers.Authorization = `Bearer ${token}`;\n }\n }\n return headers;\n }\n\n /**\n * Make a JSON-RPC request with optional retry for safe methods.\n *\n * If the request fails with a wire-origin `auth_expired` error and a\n * `tokenProvider` is configured, the client invalidates its cached\n * token and retries the request once with a freshly-acquired bearer.\n *\n * @param method - The RPC method name\n * @param params - The method parameters\n * @param signal - Optional AbortSignal for caller-controlled cancellation\n * @returns The result from the RPC method\n * @throws JsonRpcError if the RPC call fails\n */\n async call<TParams, TResult>(\n method: string,\n params: TParams,\n signal?: AbortSignal,\n ): Promise<TResult> {\n try {\n return await this.callOnce<TParams, TResult>(method, params, signal);\n } catch (error) {\n // The auth-expired retry fires for ALL methods, including mutating\n // ones. This is intentional and safe: the server's auth middleware\n // validates the bearer token BEFORE dispatching to the method\n // handler, so an `auth_expired` error means the handler never ran\n // and no state was mutated. Confirmed against btc-vault at\n // `crates/btc-auth/src/middleware/jsonrpc.rs` — token validation\n // is pre-handler only. The `retryableFor` guard on\n // HTTP-transient-error retries doesn't apply here because that\n // guard is about retrying after a request the server may have\n // started processing; auth_expired is categorically different.\n if (this.tokenProvider && isAuthExpiredError(error)) {\n this.tokenProvider.invalidate();\n return await this.callOnce<TParams, TResult>(method, params, signal);\n }\n throw error;\n }\n }\n\n private async callOnce<TParams, TResult>(\n method: string,\n params: TParams,\n signal: AbortSignal | undefined,\n ): Promise<TResult> {\n const response = await this.fetchWithRetry(method, params, signal);\n\n let jsonResponse: unknown;\n try {\n const responseText = UNCAPPED_TYPED_RESPONSE_METHODS.has(method)\n ? await response.text()\n : await readResponseTextWithLimit(response, this.maxResponseBytes);\n jsonResponse = JSON.parse(responseText);\n } catch (error) {\n if (error instanceof JsonRpcError) {\n throw error;\n }\n throw new JsonRpcError(\n JSON_RPC_ERROR_CODES.INVALID_RESPONSE,\n \"Invalid JSON-RPC response: body is not valid JSON\",\n \"local\",\n );\n }\n\n if (\n jsonResponse === null ||\n typeof jsonResponse !== \"object\" ||\n Array.isArray(jsonResponse)\n ) {\n throw new JsonRpcError(\n JSON_RPC_ERROR_CODES.INVALID_RESPONSE,\n `Invalid JSON-RPC response: expected an object, got ${typeof jsonResponse}`,\n \"local\",\n );\n }\n\n const rpcResponse = jsonResponse as Record<string, unknown>;\n\n if (\"error\" in rpcResponse && rpcResponse.error != null) {\n const err = rpcResponse.error as {\n code?: number;\n message?: string;\n data?: unknown;\n };\n throw new JsonRpcError(\n err.code ?? JSON_RPC_ERROR_CODES.INVALID_RESPONSE,\n err.message ?? \"Unknown RPC error\",\n \"wire\",\n err.data,\n );\n }\n\n if (!(\"result\" in rpcResponse)) {\n throw new JsonRpcError(\n JSON_RPC_ERROR_CODES.INVALID_RESPONSE,\n `Invalid JSON-RPC response: missing \"result\" field`,\n \"local\",\n );\n }\n\n return rpcResponse.result as TResult;\n }\n\n /**\n * Make a JSON-RPC request returning the raw Response (unparsed body).\n *\n * Bearer tokens are injected identically to `call`. **Reactive refresh\n * is NOT performed here** — the response body may be unbounded (e.g.\n * claimer-artifact downloads), so the client refuses to parse it to\n * detect auth errors. Callers relying on token-expired retries for\n * large downloads must read the body themselves and re-invoke\n * `callRaw` after `tokenProvider.invalidate()`.\n */\n async callRaw<TParams>(\n method: string,\n params: TParams,\n signal?: AbortSignal,\n ): Promise<Response> {\n return this.fetchWithRetry(method, params, signal);\n }\n\n private async fetchWithRetry<TParams>(\n method: string,\n params: TParams,\n callerSignal?: AbortSignal,\n ): Promise<Response> {\n const requestId = ++this.requestId;\n const maxRetries = this.retryableFor(method) ? this.retries : 0;\n\n // jsonrpsee (Rust backend) expects params as an array (positional parameters)\n const request: JsonRpcRequest<TParams[]> = {\n jsonrpc: JSON_RPC_VERSION,\n method,\n params: [params],\n id: requestId,\n };\n\n const body = JSON.stringify(request);\n let lastError: Error | null = null;\n\n for (let attempt = 0; attempt <= maxRetries; attempt++) {\n // Merge caller signal with per-request timeout signal\n const timeoutController = new AbortController();\n const timeoutId = setTimeout(\n () => timeoutController.abort(),\n this.timeout,\n );\n\n const merged = callerSignal\n ? mergeAbortSignals(callerSignal, timeoutController.signal)\n : null;\n const signal = merged ? merged.signal : timeoutController.signal;\n\n try {\n // Build headers per-attempt so the token provider can return a\n // freshly-acquired bearer after a prior invalidate() on this\n // request (retry loop path) without plumbing state through.\n const headers = await this.buildHeaders(method);\n\n const response = await fetch(this.baseUrl, {\n method: \"POST\",\n headers,\n body,\n signal,\n });\n\n clearTimeout(timeoutId);\n merged?.cleanup();\n\n if (!response.ok) {\n const shouldRetry =\n attempt < maxRetries &&\n RETRYABLE_HTTP_STATUS_CODES.has(response.status);\n\n if (shouldRetry) {\n const delay = this.retryDelay * Math.pow(2, attempt);\n await this.sleep(delay, callerSignal);\n continue;\n }\n\n throw new Error(\n `HTTP error: ${response.status} ${response.statusText}`,\n );\n }\n\n return response;\n } catch (error) {\n clearTimeout(timeoutId);\n merged?.cleanup();\n lastError = error instanceof Error ? error : new Error(String(error));\n\n // Check if caller aborted (not our timeout)\n if (callerSignal?.aborted) {\n throw new Error(\"Request aborted\");\n }\n\n if (error instanceof Error && error.name === \"AbortError\") {\n if (attempt < maxRetries) {\n const delay = this.retryDelay * Math.pow(2, attempt);\n await this.sleep(delay, callerSignal);\n continue;\n }\n throw new JsonRpcError(\n JSON_RPC_ERROR_CODES.TIMEOUT,\n `Request timeout after ${this.timeout}ms (${maxRetries + 1} attempts)`,\n \"local\",\n );\n }\n\n // Handle network errors (CORS, connection refused, etc.)\n if (error instanceof TypeError) {\n if (attempt < maxRetries) {\n const delay = this.retryDelay * Math.pow(2, attempt);\n await this.sleep(delay, callerSignal);\n continue;\n }\n throw new JsonRpcError(\n JSON_RPC_ERROR_CODES.NETWORK,\n `Network error: ${error.message} (${maxRetries + 1} attempts)`,\n \"local\",\n );\n }\n\n // Don't retry JSON-RPC errors (business logic errors)\n throw error;\n }\n }\n\n throw lastError || new Error(\"Unknown error after retries\");\n }\n\n private sleep(ms: number, signal?: AbortSignal): Promise<void> {\n return new Promise((resolve, reject) => {\n if (signal?.aborted) {\n reject(new Error(\"Request aborted\"));\n return;\n }\n const timeoutId = setTimeout(() => {\n signal?.removeEventListener(\"abort\", onAbort);\n resolve();\n }, ms);\n const onAbort = () => {\n clearTimeout(timeoutId);\n reject(new Error(\"Request aborted\"));\n };\n signal?.addEventListener(\"abort\", onAbort, { once: true });\n });\n }\n\n getBaseUrl(): string {\n return this.baseUrl;\n }\n}\n\ninterface MergedSignal {\n signal: AbortSignal;\n /** Remove listeners from the source signals. Call after the request completes. */\n cleanup: () => void;\n}\n\n/**\n * Merge two AbortSignals — the returned signal aborts if either input aborts.\n * Returns a cleanup function to remove listeners when the request completes\n * normally, preventing listener accumulation in long-lived polling flows.\n */\nfunction mergeAbortSignals(a: AbortSignal, b: AbortSignal): MergedSignal {\n if (a.aborted) return { signal: a, cleanup: () => {} };\n if (b.aborted) return { signal: b, cleanup: () => {} };\n\n const controller = new AbortController();\n const onAbortA = () => {\n b.removeEventListener(\"abort\", onAbortB);\n controller.abort();\n };\n const onAbortB = () => {\n a.removeEventListener(\"abort\", onAbortA);\n controller.abort();\n };\n a.addEventListener(\"abort\", onAbortA, { once: true });\n b.addEventListener(\"abort\", onAbortB, { once: true });\n\n const cleanup = () => {\n a.removeEventListener(\"abort\", onAbortA);\n b.removeEventListener(\"abort\", onAbortB);\n };\n\n return { signal: controller.signal, cleanup };\n}\n\nasync function readResponseTextWithLimit(\n response: Response,\n maxBytes: number,\n): Promise<string> {\n const contentLength = response.headers.get(\"content-length\");\n if (contentLength !== null) {\n const parsedContentLength = Number(contentLength);\n if (\n Number.isFinite(parsedContentLength) &&\n parsedContentLength > maxBytes\n ) {\n throw responseTooLargeError(maxBytes);\n }\n }\n\n if (!response.body) {\n return \"\";\n }\n\n const reader = response.body.getReader();\n const decoder = new TextDecoder();\n let totalBytes = 0;\n let responseText = \"\";\n\n try {\n for (;;) {\n const { done, value } = await reader.read();\n if (done) break;\n if (!value) continue;\n\n totalBytes += value.byteLength;\n if (totalBytes > maxBytes) {\n await reader.cancel();\n throw responseTooLargeError(maxBytes);\n }\n responseText += decoder.decode(value, { stream: true });\n }\n } finally {\n reader.releaseLock();\n }\n\n return responseText + decoder.decode();\n}\n\nfunction responseTooLargeError(maxBytes: number): JsonRpcError {\n return new JsonRpcError(\n JSON_RPC_ERROR_CODES.RESPONSE_TOO_LARGE,\n `JSON-RPC response exceeds maximum size of ${maxBytes} bytes`,\n \"local\",\n );\n}\n","/**\n * Type definitions for Vault Provider JSON-RPC API.\n *\n * These types match the `vaultProvider_*` RPC namespace defined by the\n * btc-vault daemon. They are the SDK's canonical copy of the VP protocol\n * contract, independent of any frontend framework.\n *\n * @see https://github.com/babylonlabs-io/btc-vault/blob/main/docs/pegin.md\n */\n\n// ============================================================================\n// Daemon Status\n// ============================================================================\n\n/**\n * Backend daemon status (vault provider database).\n * Source: btc-vault crates/vaultd/src/workers/claimer/mod.rs PegInStatus enum\n *\n * State flow (happy path):\n * PendingIngestion -> PendingDepositorWotsPK -> PendingBabeSetup -> PendingChallengerPresigning\n * -> PendingPeginSigsAvailability -> PendingPrePegInConfirmations\n * -> PendingDepositorSignatures -> PendingACKs -> PendingActivation -> Activated\n *\n * Terminal / branching states:\n * - Expired: vault timed out before activation\n * - ClaimPosted: claim transaction posted on-chain\n * - PeggedOut: BTC has been returned to the depositor\n */\nexport enum DaemonStatus {\n PENDING_INGESTION = \"PendingIngestion\",\n PENDING_DEPOSITOR_WOTS_PK = \"PendingDepositorWotsPK\",\n PENDING_BABE_SETUP = \"PendingBabeSetup\",\n PENDING_CHALLENGER_PRESIGNING = \"PendingChallengerPresigning\",\n PENDING_PEGIN_SIGS_AVAILABILITY = \"PendingPeginSigsAvailability\",\n PENDING_PRE_PEGIN_CONFIRMATIONS = \"PendingPrePegInConfirmations\",\n PENDING_DEPOSITOR_SIGNATURES = \"PendingDepositorSignatures\",\n PENDING_ACKS = \"PendingACKs\",\n PENDING_ACTIVATION = \"PendingActivation\",\n ACTIVATED = \"Activated\",\n EXPIRED = \"Expired\",\n CLAIM_POSTED = \"ClaimPosted\",\n PEGGED_OUT = \"PeggedOut\",\n}\n\n// ============================================================================\n// Status Groups\n// ============================================================================\n\n/**\n * States where the VP is still processing (no depositor action needed).\n * Excludes PENDING_DEPOSITOR_WOTS_PK (requires depositor action).\n */\nexport const PRE_DEPOSITOR_SIGNATURES_STATES: readonly DaemonStatus[] = [\n DaemonStatus.PENDING_INGESTION,\n DaemonStatus.PENDING_BABE_SETUP,\n DaemonStatus.PENDING_CHALLENGER_PRESIGNING,\n DaemonStatus.PENDING_PEGIN_SIGS_AVAILABILITY,\n DaemonStatus.PENDING_PRE_PEGIN_CONFIRMATIONS,\n];\n\n/** States after PendingDepositorSignatures where the depositor has no action. */\nconst POST_PAYOUT_SIGNATURE_STATUSES: readonly DaemonStatus[] = [\n DaemonStatus.PENDING_ACKS,\n DaemonStatus.PENDING_ACTIVATION,\n DaemonStatus.ACTIVATED,\n];\n\n/**\n * Statuses where no depositor action is needed (VP processing or already past\n * depositor interaction). Excludes PENDING_INGESTION and PENDING_DEPOSITOR_WOTS_PK.\n */\nexport const VP_TRANSIENT_STATUSES: ReadonlySet<DaemonStatus> = new Set([\n DaemonStatus.PENDING_BABE_SETUP,\n DaemonStatus.PENDING_CHALLENGER_PRESIGNING,\n DaemonStatus.PENDING_PEGIN_SIGS_AVAILABILITY,\n DaemonStatus.PENDING_PRE_PEGIN_CONFIRMATIONS,\n ...POST_PAYOUT_SIGNATURE_STATUSES,\n]);\n\n/**\n * Terminal VP statuses where no further progress is possible.\n * If the VP reaches one of these states while polling, polling should\n * stop immediately with an error rather than waiting for timeout.\n */\nexport const VP_TERMINAL_STATUSES: ReadonlySet<DaemonStatus> = new Set([\n DaemonStatus.EXPIRED,\n DaemonStatus.CLAIM_POSTED,\n DaemonStatus.PEGGED_OUT,\n]);\n\n/**\n * Statuses that come after WOTS key submission.\n * If the VP is already in one of these states, the WOTS key was already\n * submitted and we can skip.\n */\nexport const POST_WOTS_STATUSES: ReadonlySet<DaemonStatus> = new Set([\n ...VP_TRANSIENT_STATUSES,\n DaemonStatus.PENDING_DEPOSITOR_SIGNATURES,\n]);\n\n// ============================================================================\n// WOTS Types (needed by SubmitDepositorWotsKeyParams)\n// ============================================================================\n\n/**\n * WOTS configuration for a single block.\n * Matches Rust `babe::wots::Config` serde format.\n */\nexport interface WotsConfig {\n /** Digit bit-width (e.g. 4 → base-16 digits). */\n d: number;\n /** Number of message digits in this block. */\n n: number;\n /** Radix used for the checksum computation. */\n checksum_radix: number;\n}\n\n/**\n * A single block of WOTS public keys.\n * Chain values are arrays of byte values (matching Rust `[u8; 20]`).\n */\nexport interface WotsBlockPublicKey {\n config: WotsConfig;\n message_terminals: number[][];\n checksum_major_terminal: number[];\n checksum_minor_terminal: number[];\n}\n\n// ============================================================================\n// Request Parameter Types\n// ============================================================================\n\n/** Params for requesting the payout/claim/assert transactions to pre-sign. */\nexport interface RequestDepositorPresignTransactionsParams {\n pegin_txid: string;\n depositor_pk: string;\n}\n\n/** Params for submitting the depositor's WOTS public key to the VP. */\nexport interface SubmitDepositorWotsKeyParams {\n pegin_txid: string;\n depositor_pk: string;\n wots_public_keys: WotsBlockPublicKey[];\n}\n\n/** Per-challenger signatures for the depositor-as-claimer flow. */\nexport interface DepositorPreSigsPerChallenger {\n nopayout_signature: string;\n}\n\n/** Depositor-as-claimer pre-signatures (payout + per-challenger). */\nexport interface DepositorAsClaimerPresignatures {\n payout_signatures: ClaimerSignatures;\n per_challenger: Record<string, DepositorPreSigsPerChallenger>;\n}\n\n/** Params for submitting depositor pre-signatures including claimer presignatures. */\nexport interface SubmitDepositorPresignaturesParams {\n pegin_txid: string;\n depositor_pk: string;\n signatures: Record<string, ClaimerSignatures>;\n depositor_claimer_presignatures: DepositorAsClaimerPresignatures;\n}\n\n/** Payout signatures per claimer. */\nexport interface ClaimerSignatures {\n payout_signature: string;\n}\n\n/** Params for requesting BaBe DecryptorArtifacts from the VP. */\nexport interface RequestDepositorClaimerArtifactsParams {\n pegin_txid: string;\n depositor_pk: string;\n}\n\n/** Params for querying pegin status. Either pegin_txid or vault_id must be provided. */\nexport type GetPeginStatusParams =\n | { pegin_txid: string; vault_id?: never }\n | { vault_id: string; pegin_txid?: never };\n\n// ============================================================================\n// Response Types\n// ============================================================================\n\n/** A raw Bitcoin transaction with its hex encoding. */\nexport interface TransactionData {\n tx_hex: string;\n}\n\n/** Set of transactions the depositor must pre-sign for a single claimer. */\nexport interface ClaimerTransactions {\n claimer_pubkey: string;\n claim_tx: TransactionData;\n assert_tx: TransactionData;\n payout_tx: TransactionData;\n payout_psbt: string;\n}\n\n/** Per-segment connector data for ChallengeAssert inputs. */\nexport interface ChallengeAssertConnectorData {\n wots_pks_json: string;\n gc_wots_keys_json: string;\n}\n\n/** Challenger-specific transactions and signing data for the depositor graph. */\nexport interface PresignDataPerChallenger {\n challenger_pubkey: string;\n challenge_assert_x_tx: TransactionData;\n challenge_assert_y_tx: TransactionData;\n nopayout_tx: TransactionData;\n nopayout_psbt: string;\n challenge_assert_connectors: ChallengeAssertConnectorData[];\n output_label_hashes: string[];\n}\n\n/** Depositor-as-claimer TxGraph transactions. */\nexport interface DepositorGraphTransactions {\n claim_tx: TransactionData;\n assert_tx: TransactionData;\n payout_tx: TransactionData;\n payout_psbt: string;\n challenger_presign_data: PresignDataPerChallenger[];\n offchain_params_version: number;\n}\n\n/** Response from `requestDepositorPresignTransactions`. */\nexport interface RequestDepositorPresignTransactionsResponse {\n txs: ClaimerTransactions[];\n depositor_graph: DepositorGraphTransactions;\n}\n\n/** BaBe garbled-circuit session data for a single challenger. */\nexport interface BaBeSessionData {\n decryptor_artifacts_hex: string;\n}\n\n/** Response from `requestDepositorClaimerArtifacts`. */\nexport interface RequestDepositorClaimerArtifactsResponse {\n tx_graph_json: string;\n verifying_key_hex: string;\n babe_sessions: Record<string, BaBeSessionData>;\n}\n\n/** Progress tracker for a multi-challenger operation. */\nexport interface ChallengerProgress {\n total_challengers: number;\n completed_challengers: number;\n completed_challenger_pubkeys: string[];\n pending_challenger_pubkeys: string[];\n}\n\nexport type GcDataProgress = ChallengerProgress;\nexport type AckCollectionProgress = ChallengerProgress;\n\n/** Extended presigning progress with all 3 concurrent phases. */\nexport interface PresigningProgress extends ChallengerProgress {\n depositor_graph_created?: boolean;\n vk_challenger_presigning_completed?: number;\n vk_challenger_presigning_total?: number;\n}\n\n/** Detailed progress breakdown for an in-progress pegin. */\nexport interface PeginProgressDetails {\n gc_data?: GcDataProgress;\n presigning?: PresigningProgress;\n ack_collection?: AckCollectionProgress;\n claimer_graphs?: ClaimerGraphStatus[];\n}\n\n/** Per-claimer graph status (challenger perspective). */\nexport interface ClaimerGraphStatus {\n claimer_pubkey: string;\n presigned: boolean;\n}\n\n/** Response from `getPeginStatus`. */\nexport interface GetPeginStatusResponse {\n pegin_txid: string;\n status: string;\n progress: PeginProgressDetails;\n health_info: string;\n last_error?: string;\n}\n\n// ============================================================================\n// Pegout Types\n// ============================================================================\n\n/** Params for querying pegout status from the VP daemon. */\nexport interface GetPegoutStatusParams {\n pegin_txid: string;\n}\n\n/** Claimer-side pegout progress. */\nexport interface ClaimerPegoutStatus {\n status: string;\n failed: boolean;\n claim_txid?: string;\n claimer_pubkey?: string;\n challenger_pubkey?: string;\n created_at?: string;\n updated_at?: string;\n}\n\n/** Challenger-side pegout progress. */\nexport interface ChallengerPegoutStatus {\n status: string;\n claim_txid?: string;\n claimer_pubkey?: string;\n assert_txid?: string;\n challenge_assert_txid?: string;\n nopayout_txid?: string;\n created_at?: string;\n updated_at?: string;\n}\n\n/** Response from `getPegoutStatus`. */\nexport interface GetPegoutStatusResponse {\n pegin_txid: string;\n found: boolean;\n claimer?: ClaimerPegoutStatus;\n challenger?: ChallengerPegoutStatus;\n}\n\n// ============================================================================\n// Error Codes\n// ============================================================================\n\n/** JSON-RPC error codes returned by the vault provider. */\nexport enum RpcErrorCode {\n DATABASE_ERROR = -32005,\n PRESIGN_ERROR = -32006,\n JSON_SERIALIZATION_ERROR = -32007,\n TX_GRAPH_ERROR = -32008,\n INVALID_GRAPH = -32009,\n VALIDATION_ERROR = -32010,\n NOT_FOUND = -32011,\n INTERNAL_ERROR = -32603,\n}\n"],"names":["JsonRpcError","code","message","source","data","JSON_RPC_ERROR_CODES","JSON_RPC_VERSION","DEFAULT_RETRY_ATTEMPTS","DEFAULT_RETRY_DELAY_MS","DEFAULT_MAX_RESPONSE_BYTES","UNCAPPED_TYPED_RESPONSE_METHODS","RETRYABLE_HTTP_STATUS_CODES","DEFAULT_RETRYABLE_METHODS","defaultRetryableFor","method","AUTH_EXPIRED_DATA_KIND","isAuthExpiredError","error","JsonRpcClient","config","__publicField","headers","token","params","signal","response","jsonResponse","responseText","readResponseTextWithLimit","rpcResponse","err","callerSignal","requestId","maxRetries","body","lastError","attempt","timeoutController","timeoutId","merged","mergeAbortSignals","delay","ms","resolve","reject","onAbort","a","b","controller","onAbortA","onAbortB","cleanup","maxBytes","contentLength","parsedContentLength","responseTooLargeError","reader","decoder","totalBytes","done","value","DaemonStatus","PRE_DEPOSITOR_SIGNATURES_STATES","POST_PAYOUT_SIGNATURE_STATUSES","VP_TRANSIENT_STATUSES","VP_TERMINAL_STATUSES","POST_WOTS_STATUSES","RpcErrorCode"],"mappings":"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"}
@@ -1,2 +0,0 @@
1
- "use strict";var Q=Object.defineProperty;var ee=(r,e,t)=>e in r?Q(r,e,{enumerable:!0,configurable:!0,writable:!0,value:t}):r[e]=t;var c=(r,e,t)=>ee(r,typeof e!="symbol"?e+"":e,t);const B=require("./types-CfCZyfid.cjs"),l=require("./bitcoin-B3aqjuMP.cjs"),y=require("./validation-u8W7Lp2x.cjs"),te=require("@bitcoin-js/tiny-secp256k1-asmjs"),w=require("bitcoinjs-lib"),_=require("buffer"),H=require("./sha2-CsTynrfJ.cjs"),b=require("./BTCVaultRegistry.abi-ZdPpION2.cjs"),p=require("./ProtocolParams.abi-BmvHwQJV.cjs");function re(r){const e=Object.create(null,{[Symbol.toStringTag]:{value:"Module"}});if(r){for(const t in r)if(t!=="default"){const n=Object.getOwnPropertyDescriptor(r,t);Object.defineProperty(e,t,n.get?n:{enumerable:!0,get:()=>r[t]})}}return e.default=r,Object.freeze(e)}const k=re(te),N=new Set(Object.values(B.DaemonStatus)),ne=200;function o(r){var e;return((e=JSON.stringify(r))==null?void 0:e.slice(0,ne))??"undefined"}const se="The vault provider returned an unexpected response. Please try again or contact support.";class s extends Error{constructor(t){super(se);c(this,"detail");this.name="VpResponseValidationError",this.detail=t}}const x=64;function m(r){return typeof r=="string"&&r.length>0&&y.HEX_RE.test(r)}function L(r){return typeof r=="string"&&r.length>0}function X(r,e){if(!m(r))throw new s(`VP response validation failed: "${e}" must be a non-empty hex string, got ${o(r)}`)}function P(r,e){if(!L(r))throw new s(`VP response validation failed: "${e}" must be a non-empty string, got ${o(r)}`)}function q(r,e){if(!m(r)||r.length!==l.X_ONLY_PUBKEY_HEX_LEN&&r.length!==l.COMPRESSED_PUBKEY_HEX_LEN)throw new s(`VP response validation failed: "${e}" must be a ${l.X_ONLY_PUBKEY_HEX_LEN} or ${l.COMPRESSED_PUBKEY_HEX_LEN}-char hex string (BTC pubkey), got ${o(r)}`)}function ie(r){const e=r.presigning;if(e==null)return;if(typeof e!="object"||Array.isArray(e))throw new s('VP response validation failed: "progress.presigning" must be an object if present');const t=e;if(t.depositor_graph_created!==void 0&&typeof t.depositor_graph_created!="boolean")throw new s(`VP response validation failed: "progress.presigning.depositor_graph_created" must be a boolean if present, got ${o(t.depositor_graph_created)}`);if(t.vk_challenger_presigning_completed!==void 0&&typeof t.vk_challenger_presigning_completed!="number")throw new s(`VP response validation failed: "progress.presigning.vk_challenger_presigning_completed" must be a number if present, got ${o(t.vk_challenger_presigning_completed)}`);if(t.vk_challenger_presigning_total!==void 0&&typeof t.vk_challenger_presigning_total!="number")throw new s(`VP response validation failed: "progress.presigning.vk_challenger_presigning_total" must be a number if present, got ${o(t.vk_challenger_presigning_total)}`)}function ae(r){if(r===null||typeof r!="object")throw new s("VP response validation failed: getPeginStatus response is not an object");const e=r;if(!m(e.pegin_txid)||e.pegin_txid.length!==x)throw new s(`VP response validation failed: "pegin_txid" must be a ${x}-char hex string (txid), got ${o(e.pegin_txid)}`);if(typeof e.status!="string")throw new s('VP response validation failed: "status" must be a string');if(!N.has(e.status))throw new s(`VP response validation failed: unrecognized status "${e.status}". Expected one of: ${[...N].join(", ")}`);if(e.progress===null||typeof e.progress!="object"||Array.isArray(e.progress))throw new s('VP response validation failed: "progress" must be an object');if(ie(e.progress),typeof e.health_info!="string")throw new s('VP response validation failed: "health_info" must be a string');if(e.last_error!==void 0&&typeof e.last_error!="string")throw new s(`VP response validation failed: "last_error" must be a string if present, got ${o(e.last_error)}`)}function oe(r){if(r===null||typeof r!="object")throw new s("VP response validation failed: requestDepositorPresignTransactions response is not an object");const e=r;if(!Array.isArray(e.txs))throw new s('VP response validation failed: "txs" must be an array');for(let t=0;t<e.txs.length;t++)ce(e.txs[t],`txs[${t}]`);if(e.depositor_graph===null||typeof e.depositor_graph!="object")throw new s('VP response validation failed: "depositor_graph" must be an object');pe(e.depositor_graph)}function f(r,e){if(r===null||typeof r!="object")throw new s(`VP response validation failed: "${e}" must be an object`);X(r.tx_hex,`${e}.tx_hex`)}function ce(r,e){if(r===null||typeof r!="object")throw new s(`VP response validation failed: "${e}" must be an object`);const t=r;q(t.claimer_pubkey,`${e}.claimer_pubkey`),f(t.claim_tx,`${e}.claim_tx`),f(t.assert_tx,`${e}.assert_tx`),f(t.payout_tx,`${e}.payout_tx`),P(t.payout_psbt,`${e}.payout_psbt`)}function le(r,e){if(r===null||typeof r!="object")throw new s(`VP response validation failed: "${e}" must be an object`);const t=r;P(t.wots_pks_json,`${e}.wots_pks_json`),P(t.gc_wots_keys_json,`${e}.gc_wots_keys_json`)}function ue(r,e){if(r===null||typeof r!="object")throw new s(`VP response validation failed: "${e}" must be an object`);const t=r;if(q(t.challenger_pubkey,`${e}.challenger_pubkey`),f(t.challenge_assert_x_tx,`${e}.challenge_assert_x_tx`),f(t.challenge_assert_y_tx,`${e}.challenge_assert_y_tx`),f(t.nopayout_tx,`${e}.nopayout_tx`),P(t.nopayout_psbt,`${e}.nopayout_psbt`),!Array.isArray(t.challenge_assert_connectors))throw new s(`VP response validation failed: "${e}.challenge_assert_connectors" must be an array`);for(let n=0;n<t.challenge_assert_connectors.length;n++)le(t.challenge_assert_connectors[n],`${e}.challenge_assert_connectors[${n}]`);if(!Array.isArray(t.output_label_hashes))throw new s(`VP response validation failed: "${e}.output_label_hashes" must be an array`);for(let n=0;n<t.output_label_hashes.length;n++)X(t.output_label_hashes[n],`${e}.output_label_hashes[${n}]`)}function M(r){if(r===null||typeof r!="object")throw new s("VP response validation failed: requestDepositorClaimerArtifacts response is not an object");const e=r;if(!L(e.tx_graph_json))throw new s(`VP response validation failed: "tx_graph_json" must be a non-empty string, got ${o(e.tx_graph_json)}`);if(!m(e.verifying_key_hex))throw new s(`VP response validation failed: "verifying_key_hex" must be a non-empty hex string, got ${o(e.verifying_key_hex)}`);if(e.babe_sessions===null||typeof e.babe_sessions!="object")throw new s('VP response validation failed: "babe_sessions" must be an object');for(const[t,n]of Object.entries(e.babe_sessions)){if(n===null||typeof n!="object")throw new s(`VP response validation failed: "babe_sessions.${t}" must be an object`);const i=n;if(!m(i.decryptor_artifacts_hex))throw new s(`VP response validation failed: "babe_sessions.${t}.decryptor_artifacts_hex" must be a non-empty hex string, got ${o(i.decryptor_artifacts_hex)}`)}}function de(r){if(r===null||typeof r!="object")throw new s("VP response validation failed: getPegoutStatus response is not an object");const e=r;if(!m(e.pegin_txid)||e.pegin_txid.length!==x)throw new s(`VP response validation failed: "pegin_txid" must be a ${x}-char hex string (txid), got ${o(e.pegin_txid)}`);if(typeof e.found!="boolean")throw new s(`VP response validation failed: "found" must be a boolean, got ${o(e.found)}`);if(e.claimer!==void 0){if(e.claimer===null||typeof e.claimer!="object")throw new s('VP response validation failed: "claimer" must be an object if present');const t=e.claimer;if(typeof t.status!="string")throw new s(`VP response validation failed: "claimer.status" must be a string, got ${o(t.status)}`);if(typeof t.failed!="boolean")throw new s(`VP response validation failed: "claimer.failed" must be a boolean, got ${o(t.failed)}`)}if(e.challenger!==void 0){if(e.challenger===null||typeof e.challenger!="object")throw new s('VP response validation failed: "challenger" must be an object if present');const t=e.challenger;if(typeof t.status!="string")throw new s(`VP response validation failed: "challenger.status" must be a string, got ${o(t.status)}`)}}function pe(r){if(f(r.claim_tx,"depositor_graph.claim_tx"),f(r.assert_tx,"depositor_graph.assert_tx"),f(r.payout_tx,"depositor_graph.payout_tx"),P(r.payout_psbt,"depositor_graph.payout_psbt"),!Array.isArray(r.challenger_presign_data))throw new s('VP response validation failed: "depositor_graph.challenger_presign_data" must be an array');for(let e=0;e<r.challenger_presign_data.length;e++)ue(r.challenger_presign_data[e],`depositor_graph.challenger_presign_data[${e}]`);if(typeof r.offchain_params_version!="number")throw new s('VP response validation failed: "depositor_graph.offchain_params_version" must be a number')}const he=6e4;class F{constructor(e,t){c(this,"client");const n={baseUrl:e,timeout:(t==null?void 0:t.timeout)??he,retries:t==null?void 0:t.retries,retryDelay:t==null?void 0:t.retryDelay,retryableFor:t==null?void 0:t.retryableFor,headers:t==null?void 0:t.headers,tokenProvider:t==null?void 0:t.tokenProvider,maxResponseBytes:t==null?void 0:t.maxResponseBytes};this.client=new B.JsonRpcClient(n)}async requestDepositorPresignTransactions(e,t){const n=await this.client.call("vaultProvider_requestDepositorPresignTransactions",e,t);return oe(n),n}async submitDepositorPresignatures(e,t){return this.client.call("vaultProvider_submitDepositorPresignatures",e,t)}async submitDepositorWotsKey(e,t){return this.client.call("vaultProvider_submitDepositorWotsKey",e,t)}async requestDepositorClaimerArtifacts(e,t){const n=await this.client.call("vaultProvider_requestDepositorClaimerArtifacts",e,t);return M(n),n}async getPeginStatus(e,t){const n=await this.client.call("vaultProvider_getPeginStatus",e,t);return ae(n),n}async getPegoutStatus(e,t){const n=await this.client.call("vaultProvider_getPegoutStatus",e,t);return de(n),n}}const ge="BIP0322-signed-message",fe="TapTweak",G=32,_e=64;function Y(r,e){const t=new TextEncoder().encode(r),n=H.sha256(t),i=new Uint8Array(n.length*2+e.length);return i.set(n,0),i.set(n,n.length),i.set(e,n.length*2),H.sha256(i)}function me(r){if(r.length!==G)return null;const e=Y(fe,r),t=k.xOnlyPointAddTweak(r,e);return t?t.xOnlyPubkey:null}function ye(r,e,t){if(e.length!==G||t.length!==_e)return!1;try{const n=Y(ge,r),i=w.payments.p2tr({internalPubkey:_.Buffer.from(e)});if(!i.output)return!1;const a=i.output,u=0,g=new w.Transaction;g.version=0,g.locktime=0;const T=_.Buffer.concat([_.Buffer.from([0,32]),_.Buffer.from(n)]);g.addInput(_.Buffer.alloc(32,0),4294967295,0,T),g.addOutput(a,u);const h=new w.Transaction;h.version=0,h.locktime=0;const S=g.getHash();h.addInput(S,0,0),h.addOutput(_.Buffer.from([106]),u);const I=h.hashForWitnessV1(0,[a],[u],w.Transaction.SIGHASH_DEFAULT),R=me(e);return R?k.verifySchnorr(I,R,t):!1}catch{return!1}}function A(r,e){const t=(r&7)<<5,n=typeof e=="bigint"?e:BigInt(e);if(n<0n)throw new Error("cborHead: negative argument");if(n<24n)return new Uint8Array([t|Number(n)]);if(n<0x100n)return new Uint8Array([t|24,Number(n)]);if(n<0x10000n){const a=Number(n);return new Uint8Array([t|25,a>>>8&255,a&255])}if(n<0x100000000n){const a=Number(n);return new Uint8Array([t|26,a>>>24&255,a>>>16&255,a>>>8&255,a&255])}const i=new Uint8Array(9);i[0]=t|27;for(let a=7;a>=0;a--)i[1+a]=Number(n>>BigInt((7-a)*8))&255;return i}function W(...r){const e=r.reduce((i,a)=>i+a.length,0),t=new Uint8Array(e);let n=0;for(const i of r)t.set(i,n),n+=i.length;return t}function O(r){const t=[A(4,r.length)];for(const n of r)t.push(A(0,n));return W(...t)}function be(r,e,t){if(!Number.isSafeInteger(t)||t<0)throw new Error(`encodeServerIdentityPayload: expires_at must be a non-negative safe integer, got ${t}`);const n=A(4,3),i=O(r),a=O(e),u=A(0,t);return W(n,i,a,u)}const Pe=new TextEncoder().encode("btc-auth.server-identity.v1");class d extends Error{constructor(e,t){super(e),this.reason=t,this.name="ServerIdentityError"}}function v(r){const e=new Uint8Array(r.length/2);for(let t=0;t<e.length;t++)e[t]=parseInt(r.slice(t*2,t*2+2),16);return e}function z(r){const{proof:e,pinnedServerPubkey:t,now:n}=r,i=l.stripHexPrefix(t).toLowerCase();if(i.length!==l.X_ONLY_PUBKEY_HEX_LEN||!y.HEX_RE.test(i))throw new d(`pinnedServerPubkey must be 32-byte hex; got ${i.length} chars`,"invalid_pubkey_encoding");const a=l.stripHexPrefix(e.server_pubkey).toLowerCase();if(a.length!==l.X_ONLY_PUBKEY_HEX_LEN||!y.HEX_RE.test(a))throw new d(`server_pubkey must be 32-byte hex; got ${a.length} chars`,"invalid_pubkey_encoding");if(a!==i)throw new d(`server_pubkey does not match pinned value: expected ${i}, got ${a}`,"pinned_pubkey_mismatch");if(!Number.isSafeInteger(e.expires_at))throw new d(`expires_at must be a finite integer; got ${JSON.stringify(e.expires_at)}`,"invalid_expires_at");if(!Number.isSafeInteger(n))throw new d(`now must be a finite integer; got ${JSON.stringify(n)}`,"invalid_expires_at");if(e.expires_at<=n)throw new d(`server identity proof expired at ${e.expires_at}, now ${n}`,"expired");const u=l.stripHexPrefix(e.ephemeral_pubkey).toLowerCase();if(u.length!==l.COMPRESSED_PUBKEY_HEX_LEN||!y.HEX_RE.test(u))throw new d(`ephemeral_pubkey must be 33-byte compressed hex; got ${u.length} chars`,"invalid_ephemeral_pubkey");const g=u.slice(0,2);if(g!=="02"&&g!=="03")throw new d(`ephemeral_pubkey must be compressed (prefix 02/03); got ${g}`,"invalid_ephemeral_pubkey");const T=v(u);if(!k.isPoint(T))throw new d("ephemeral_pubkey is not a valid secp256k1 point","invalid_ephemeral_pubkey");const h=l.stripHexPrefix(e.signature).toLowerCase();if(h.length!==l.SCHNORR_SIG_HEX_LEN||!y.HEX_RE.test(h))throw new d(`signature must be 64-byte Schnorr hex; got ${h.length} chars`,"invalid_signature_encoding");const S=be(Pe,v(u),e.expires_at);if(!ye(S,v(a),v(h)))throw new d("BIP-322 signature verification failed — ephemeral key is not attested by pinned server pubkey","signature_verification_failed")}const we=new Set(["vaultProvider_submitDepositorWotsKey","vaultProvider_submitDepositorPresignatures","vaultProvider_requestDepositorPresignTransactions"]),ve=6e4,E="auth_createDepositorToken";function J(r,e){return new B.JsonRpcClient({baseUrl:r,timeout:ve,headers:e,retryableFor:t=>t===E})}const j=4102444800,xe=30;class Ae{constructor(e){c(this,"client");c(this,"peginTxid");c(this,"authAnchorHex");c(this,"pinnedServerPubkey");c(this,"authGatedMethods");c(this,"refreshSkewSecs");c(this,"now");c(this,"cached",null);c(this,"inFlight",null);this.client=e.client,this.peginTxid=e.peginTxid,this.authAnchorHex=e.authAnchorHex,this.pinnedServerPubkey=e.pinnedServerPubkey,this.authGatedMethods=e.authGatedMethods,this.refreshSkewSecs=e.refreshSkewSecs??xe,this.now=e.now??(()=>Math.floor(Date.now()/1e3))}async getToken(e){if(e===E||!this.authGatedMethods.has(e))return null;const t=this.cached;return t&&this.now()+this.refreshSkewSecs<t.expiresAt?t.token:(await this.acquireSingleFlight()).token}invalidate(){this.cached=null}setClient(e){this.client=e}acquireSingleFlight(){const e=this.inFlight;if(e)return e;const t=(async()=>{try{const n=await this.client.call(E,{pegin_txid:this.peginTxid,auth_anchor:this.authAnchorHex});if(z({proof:n.server_identity,pinnedServerPubkey:this.pinnedServerPubkey,now:this.now()}),typeof n.token!="string"||n.token.length===0)throw new Error(`VpTokenProvider: invalid token in acquire response (expected non-empty string, got ${typeof n.token})`);const i=this.now();if(!Number.isSafeInteger(n.expires_at)||n.expires_at<=i||n.expires_at>j)throw new Error(`VpTokenProvider: invalid expires_at in acquire response (got ${JSON.stringify(n.expires_at)}; must be a safe integer in (${i}, ${j}])`);const a={token:n.token,expiresAt:n.expires_at};return this.cached=a,a}finally{this.inFlight=null}})();return this.inFlight=t,t}}class Z{constructor(){c(this,"entries",new Map)}getOrCreate(e){const t=this.entries.get(e.peginTxid);if(t){if(t.authAnchorHex!==e.authAnchorHex)throw new Error(`VpTokenRegistry: peginTxid ${e.peginTxid} already bound to authAnchorHex ${t.authAnchorHex.slice(0,8)}…; got ${e.authAnchorHex.slice(0,8)}…`);if(t.pinnedServerPubkey!==e.pinnedServerPubkey)throw new Error(`VpTokenRegistry: peginTxid ${e.peginTxid} already bound to pinnedServerPubkey ${t.pinnedServerPubkey.slice(0,8)}…; got ${e.pinnedServerPubkey.slice(0,8)}…`);return t.provider.setClient(e.client),t.provider}const n=new Ae({client:e.client,peginTxid:e.peginTxid,authAnchorHex:e.authAnchorHex,pinnedServerPubkey:e.pinnedServerPubkey,authGatedMethods:we});return this.entries.set(e.peginTxid,{provider:n,authAnchorHex:e.authAnchorHex,pinnedServerPubkey:e.pinnedServerPubkey}),n}peek(e){var t;return(t=this.entries.get(e))==null?void 0:t.provider}release(e){this.entries.delete(e)}clear(){this.entries.clear()}get size(){return this.entries.size}}const $=new Z;function Ve(r){var n;const e=J(r.baseUrl,(n=r.options)==null?void 0:n.headers),t=$.getOrCreate({client:e,peginTxid:r.peginTxid,authAnchorHex:r.authAnchorHex,pinnedServerPubkey:r.pinnedServerPubkey});return new F(r.baseUrl,{...r.options,tokenProvider:t})}function ke(r){$.getOrCreate({client:J(r.baseUrl,r.headers),peginTxid:r.peginTxid,authAnchorHex:r.authAnchorHex,pinnedServerPubkey:r.pinnedServerPubkey})}async function Te(r,e){const[t,n]=await r.multicall({contracts:[{address:e,abi:b.BTCVaultRegistryABI,functionName:"protocolParams"},{address:e,abi:b.BTCVaultRegistryABI,functionName:"applicationRegistry"}],allowFailure:!1});return{protocolParams:t,applicationRegistry:n}}const D=65535;function C(r){return{timelockAssert:r.timelockAssert,timelockChallengeAssert:r.timelockChallengeAssert,securityCouncilKeys:[...r.securityCouncilKeys],councilQuorum:r.councilQuorum,feeRate:r.feeRate,babeTotalInstances:r.babeTotalInstances,babeInstancesToFinalize:r.babeInstancesToFinalize,minVpCommissionBps:r.minVpCommissionBps,tRefund:r.tRefund,tStale:r.tStale,minPeginFeeRate:r.minPeginFeeRate,proverProgramVersion:r.proverProgramVersion,minPrepeginDepth:r.minPrepeginDepth}}function U(r){return{minimumPegInAmount:r.minimumPegInAmount,maxPegInAmount:r.maxPegInAmount,pegInAckTimeout:r.pegInAckTimeout,pegInActivationTimeout:r.pegInActivationTimeout,maxHtlcOutputCount:r.maxHtlcOutputCount}}function K(r){if(r>BigInt(D))throw new Error(`timelockAssert value ${r} exceeds uint16 max (${D})`);return Number(r)}class Se{constructor(e,t){this.publicClient=e,this.contractAddress=t}async getTBVProtocolParams(){const e=await this.publicClient.readContract({address:this.contractAddress,abi:p.ProtocolParamsABI,functionName:"getTBVProtocolParams"});return U(e)}async getLatestOffchainParams(){const e=await this.publicClient.readContract({address:this.contractAddress,abi:p.ProtocolParamsABI,functionName:"getLatestOffchainParams"});return C(e)}async getOffchainParamsByVersion(e){const t=await this.publicClient.readContract({address:this.contractAddress,abi:p.ProtocolParamsABI,functionName:"getOffchainParamsByVersion",args:[e]});return C(t)}async getLatestOffchainParamsVersion(){return await this.publicClient.readContract({address:this.contractAddress,abi:p.ProtocolParamsABI,functionName:"latestOffchainParamsVersion"})}async getTimelockPeginByVersion(e){const t=await this.getOffchainParamsByVersion(e);return K(t.timelockAssert)}async getPegInConfiguration(){const e=await this.publicClient.multicall({contracts:[{address:this.contractAddress,abi:p.ProtocolParamsABI,functionName:"getTBVProtocolParams"},{address:this.contractAddress,abi:p.ProtocolParamsABI,functionName:"getLatestOffchainParams"}],allowFailure:!1}),t=U(e[0]),n=C(e[1]);return{minimumPegInAmount:t.minimumPegInAmount,maxPegInAmount:t.maxPegInAmount,pegInAckTimeout:t.pegInAckTimeout,pegInActivationTimeout:t.pegInActivationTimeout,maxHtlcOutputCount:t.maxHtlcOutputCount,timelockPegin:K(n.timelockAssert),timelockRefund:n.tRefund,minVpCommissionBps:n.minVpCommissionBps,offchainParams:n}}}function V(r){return r.map(e=>({ethAddress:e.ethAddress,btcPubKey:e.btcPubKey}))}class Ce{constructor(e,t){this.publicClient=e,this.contractAddress=t}async getVaultKeepersByVersion(e,t){const n=await this.publicClient.readContract({address:this.contractAddress,abi:p.ApplicationRegistryABI,functionName:"getVaultKeepersByVersion",args:[e,t]});return V(n)}async getCurrentVaultKeepers(e){const t=await this.publicClient.readContract({address:this.contractAddress,abi:p.ApplicationRegistryABI,functionName:"getCurrentVaultKeepers",args:[e]});return V(t)}async getCurrentVaultKeepersVersion(e){return await this.publicClient.readContract({address:this.contractAddress,abi:p.ApplicationRegistryABI,functionName:"getCurrentVaultKeepersVersion",args:[e]})}}class Ee{constructor(e,t){this.publicClient=e,this.contractAddress=t}async getUniversalChallengersByVersion(e){const t=await this.publicClient.readContract({address:this.contractAddress,abi:p.ProtocolParamsABI,functionName:"getUniversalChallengersByVersion",args:[e]});return V(t)}async getCurrentUniversalChallengers(){const e=await this.publicClient.readContract({address:this.contractAddress,abi:p.ProtocolParamsABI,functionName:"getCurrentUniversalChallengers"});return V(e)}async getLatestUniversalChallengersVersion(){return await this.publicClient.readContract({address:this.contractAddress,abi:p.ProtocolParamsABI,functionName:"latestUniversalChallengersVersion"})}}class Be{constructor(e,t){this.publicClient=e,this.contractAddress=t}async getVaultProviderBtcPubKey(e){const n=(await this.publicClient.readContract({address:this.contractAddress,abi:b.BTCVaultRegistryABI,functionName:"getVaultProviderBTCKey",args:[e]})).toLowerCase();if(!/^0x[0-9a-f]{64}$/.test(n))throw new Error(`getVaultProviderBTCKey returned an unexpected value (vp=${e}, length ${n.length}, prefix "${n.slice(0,2)}")`);const i=n.slice(2);if(!k.isXOnlyPoint(l.hexToUint8Array(i)))throw new Error(`getVaultProviderBTCKey returned a value that is not on the secp256k1 curve (vp=${e})`);return i}async getVaultBasicInfo(e){const t=await this.publicClient.readContract({address:this.contractAddress,abi:b.BTCVaultRegistryABI,functionName:"getBtcVaultBasicInfo",args:[e]});return{depositor:t.depositor,depositorBtcPubKey:t.depositorBtcPubKey,amount:t.amount,vaultProvider:t.vaultProvider,status:t.status,applicationEntryPoint:t.applicationEntryPoint,createdAt:t.createdAt}}async getVaultProtocolInfo(e){const t=await this.publicClient.readContract({address:this.contractAddress,abi:b.BTCVaultRegistryABI,functionName:"getBtcVaultProtocolInfo",args:[e]});return{depositorSignedPeginTx:t.depositorSignedPeginTx,universalChallengersVersion:t.universalChallengersVersion,appVaultKeepersVersion:t.appVaultKeepersVersion,offchainParamsVersion:t.offchainParamsVersion,verifiedAt:t.verifiedAt,depositorWotsPkHash:t.depositorWotsPkHash,hashlock:t.hashlock,htlcVout:t.htlcVout,depositorPopSignature:t.depositorPopSignature,prePeginTxHash:t.prePeginTxHash,vaultProviderCommissionBps:t.vaultProviderCommissionBps}}async getVaultData(e){const[t,n]=await Promise.all([this.getVaultBasicInfo(e),this.getVaultProtocolInfo(e)]);if(!n.depositorSignedPeginTx||n.depositorSignedPeginTx==="0x")throw new Error(`Vault ${e} not found on-chain or has no pegin transaction`);return{basic:t,protocol:n}}}exports.ServerIdentityError=d;exports.VaultProviderRpcClient=F;exports.ViemProtocolParamsReader=Se;exports.ViemUniversalChallengerReader=Ee;exports.ViemVaultKeeperReader=Ce;exports.ViemVaultRegistryReader=Be;exports.VpResponseValidationError=s;exports.VpTokenRegistry=Z;exports.createAuthenticatedVpClient=Ve;exports.primeVpTokenRegistry=ke;exports.resolveProtocolAddresses=Te;exports.validateRequestDepositorClaimerArtifactsResponse=M;exports.verifyServerIdentity=z;exports.vpTokenRegistry=$;
2
- //# sourceMappingURL=vault-registry-reader-OK2V08tk.cjs.map