{"version":3,"file":"peginState-eaQ4IO_R.cjs","sources":["../src/tbv/core/services/deposit/peginState.ts"],"sourcesContent":["// ============================================================================\n// State Definitions\n// ============================================================================\n\n/**\n * Vault status — combines on-chain contract status (0-4) with indexer-derived\n * statuses (5-7). The contract enum (BTCVaultRegistry.sol BTCVaultStatus) only\n * has: Pending(0), Verified(1), Active(2), Redeemed(3), Expired(4).\n * The indexer maps these and adds extra statuses for UI display.\n *\n * IMPORTANT: With the new contract architecture:\n * - Core vault status (BTCVaultRegistry) does NOT change when used by applications\n * - Vaults remain at ACTIVE status even when used in DeFi positions\n * - Application usage status is tracked separately by each integration controller\n */\nexport enum ContractStatus {\n  /** Status 0: Request submitted, waiting for ACKs */\n  PENDING = 0,\n  /** Status 1: All ACKs collected, ready for secret activation */\n  VERIFIED = 1,\n  /** Status 2: HTLC secret revealed, vault is active and usable (stays here even when used by apps) */\n  ACTIVE = 2,\n  /** Status 3: Vault has been redeemed, BTC is claimable */\n  REDEEMED = 3,\n  /** Status 4 (indexer-only): Vault was liquidated (collateral seized due to unpaid debt) */\n  LIQUIDATED = 4,\n  /** Status 5 (indexer-only): Vault is invalid — BTC UTXOs were spent in a different transaction */\n  INVALID = 5,\n  /** Status 6 (indexer-only): Depositor has withdrawn their BTC (redemption complete) */\n  DEPOSITOR_WITHDRAWN = 6,\n  /** Status 7 (indexer-only): Vault expired due to AckTimeout or ActivationTimeout */\n  EXPIRED = 7,\n}\n\n/** Reason why a vault expired */\nexport type ExpirationReason =\n  | \"ack_timeout\"\n  | \"proof_timeout\"\n  | \"activation_timeout\";\n\n// ============================================================================\n// Protocol State Model\n// ============================================================================\n\n/**\n * Available actions user can take\n */\nexport enum PeginAction {\n  /** Submit WOTS key (re-derives via wallet `deriveContextHash`) */\n  SUBMIT_WOTS_KEY = \"SUBMIT_WOTS_KEY\",\n  /** Sign payout transactions */\n  SIGN_PAYOUT_TRANSACTIONS = \"SIGN_PAYOUT_TRANSACTIONS\",\n  /** Sign and broadcast peg-in transaction to Bitcoin */\n  SIGN_AND_BROADCAST_TO_BITCOIN = \"SIGN_AND_BROADCAST_TO_BITCOIN\",\n  /** Reveal HTLC secret on Ethereum to activate vault */\n  ACTIVATE_VAULT = \"ACTIVATE_VAULT\",\n  /**\n   * Escape hatch: reveal the HTLC secret and immediately redeem the vault for\n   * the depositor (`activateVaultWithSecretAndRedeem`), skipping application\n   * activation. Recovery path when the peg-in was swept on Bitcoin but the\n   * vault could not be activated (application paused / activation revert).\n   */\n  ACTIVATE_AND_REDEEM = \"ACTIVATE_AND_REDEEM\",\n  /** Sign and broadcast HTLC refund transaction for an expired vault */\n  REFUND_HTLC = \"REFUND_HTLC\",\n}\n\n/**\n * Protocol-level peg-in state (framework-agnostic)\n */\nexport interface PeginProtocolState {\n  /** Smart contract status (source of truth for on-chain state) */\n  contractStatus: ContractStatus;\n  /** Available user actions (empty array when no action is available) */\n  availableActions: PeginAction[];\n}\n\n/**\n * Options for getPeginProtocolState function.\n *\n * All fields represent protocol-level state from the vault provider or\n * on-chain contracts. Client-side tracking (localStorage, polling state)\n * is NOT included — consumers handle that in their own layer.\n */\nexport interface GetPeginProtocolStateOptions {\n  /** Whether claim/payout transactions are ready from VP */\n  transactionsReady?: boolean;\n  /** Whether the vault provider is waiting for the depositor's WOTS public key */\n  needsWotsKey?: boolean;\n  /** Whether the vault provider hasn't ingested this peg-in yet */\n  pendingIngestion?: boolean;\n  /** Whether the depositor can refund the HTLC (Pre-PegIn tx available) */\n  canRefund?: boolean;\n  /** Whether the vault provider reported a terminal failure */\n  hasProviderTerminalFailure?: boolean;\n  /**\n   * VERIFIED only: the Pre-PegIn HTLC outpoint has been spent on Bitcoin BY\n   * THE PEGIN TRANSACTION while the vault is still Verified on Ethereum. The\n   * secret was revealed (e.g. in the calldata of a reverted activation) and\n   * the peg-in swept without the vault activating, so the normal activation\n   * no longer returns value to the depositor and the CSV refund can never\n   * broadcast. The remaining recovery is the activate-and-redeem escape\n   * hatch.\n   *\n   * The caller MUST prove the spender by comparing the outspend's\n   * `spendingTxid` against the vault's PegIn txid before setting this. A\n   * bare \"spent\" observation is not sufficient: the spend may be the\n   * depositor's own CSV refund, and offering the secret-revealing hatch\n   * against a refund burns the secret for a vault whose funds already\n   * returned.\n   */\n  htlcSpentByPeginTx?: boolean;\n}\n\n// ============================================================================\n// State Machine Logic\n// ============================================================================\n\n/**\n * Determine the current protocol state and available actions based on contract\n * status and vault provider state. Framework-agnostic: returns only\n * protocol-level data with no display labels, messages, or UI concerns.\n *\n * Client-side tracking overrides (e.g. suppressing actions after the user\n * has already acted but on-chain state hasn't caught up) are the caller's\n * responsibility.\n *\n * @param contractStatus - On-chain contract status (source of truth)\n * @param options - Vault provider state\n * @returns Protocol state with available actions\n */\nexport function getPeginProtocolState(\n  contractStatus: ContractStatus,\n  options: GetPeginProtocolStateOptions = {},\n): PeginProtocolState {\n  const {\n    transactionsReady,\n    needsWotsKey,\n    pendingIngestion,\n    canRefund,\n    hasProviderTerminalFailure,\n    htlcSpentByPeginTx,\n  } = options;\n\n  if (contractStatus === ContractStatus.PENDING) {\n    if (hasProviderTerminalFailure) {\n      return { contractStatus, availableActions: [] };\n    }\n\n    if (needsWotsKey) {\n      return {\n        contractStatus,\n        availableActions: [PeginAction.SUBMIT_WOTS_KEY],\n      };\n    }\n\n    if (pendingIngestion === true && !transactionsReady) {\n      return {\n        contractStatus,\n        availableActions: [PeginAction.SIGN_AND_BROADCAST_TO_BITCOIN],\n      };\n    }\n\n    if (pendingIngestion === undefined && !transactionsReady) {\n      return { contractStatus, availableActions: [] };\n    }\n\n    if (!transactionsReady) {\n      return { contractStatus, availableActions: [] };\n    }\n\n    return {\n      contractStatus,\n      availableActions: [PeginAction.SIGN_PAYOUT_TRANSACTIONS],\n    };\n  }\n\n  if (contractStatus === ContractStatus.VERIFIED) {\n    // A spent HTLC while still Verified means the peg-in was swept without\n    // activation: activating normally would hand the collateral to an\n    // application flow that already failed once, and refunding is impossible\n    // (the outpoint is gone). Surface only the escape hatch.\n    if (htlcSpentByPeginTx) {\n      return {\n        contractStatus,\n        availableActions: [PeginAction.ACTIVATE_AND_REDEEM],\n      };\n    }\n    return {\n      contractStatus,\n      availableActions: [PeginAction.ACTIVATE_VAULT],\n    };\n  }\n\n  if (contractStatus === ContractStatus.ACTIVE) {\n    return { contractStatus, availableActions: [] };\n  }\n\n  if (contractStatus === ContractStatus.REDEEMED) {\n    return { contractStatus, availableActions: [] };\n  }\n\n  if (contractStatus === ContractStatus.LIQUIDATED) {\n    return { contractStatus, availableActions: [] };\n  }\n\n  if (contractStatus === ContractStatus.EXPIRED) {\n    return {\n      contractStatus,\n      availableActions: canRefund ? [PeginAction.REFUND_HTLC] : [],\n    };\n  }\n\n  if (contractStatus === ContractStatus.INVALID) {\n    return { contractStatus, availableActions: [] };\n  }\n\n  if (contractStatus === ContractStatus.DEPOSITOR_WITHDRAWN) {\n    return { contractStatus, availableActions: [] };\n  }\n\n  return { contractStatus, availableActions: [] };\n}\n\n/**\n * Check if a specific action is available in the current state\n */\nexport function canPerformAction(\n  state: PeginProtocolState,\n  action: PeginAction,\n): boolean {\n  return state.availableActions.includes(action);\n}\n\n// ============================================================================\n// Activation deadline\n// ============================================================================\n\n/**\n * Whether a vault's on-chain activation window has closed. Mirrors the\n * BTCVaultRegistry check that reverts `ActivationDeadlineExpired`:\n * `block.number > createdAt + pegInActivationTimeout` — strict `>`, so a\n * boundary-equal block is NOT expired. All values are Ethereum block numbers.\n */\nexport function isActivationDeadlinePassedOnChain(params: {\n  currentBlock: bigint;\n  createdAtBlock: bigint;\n  pegInActivationTimeout: bigint;\n}): boolean {\n  const { currentBlock, createdAtBlock, pegInActivationTimeout } = params;\n  return currentBlock > createdAtBlock + pegInActivationTimeout;\n}\n"],"names":["ContractStatus","PeginAction","getPeginProtocolState","contractStatus","options","transactionsReady","needsWotsKey","pendingIngestion","canRefund","hasProviderTerminalFailure","htlcSpentByPeginTx","canPerformAction","state","action","isActivationDeadlinePassedOnChain","params","currentBlock","createdAtBlock","pegInActivationTimeout"],"mappings":"aAeO,IAAKA,GAAAA,IAEVA,EAAAA,EAAA,QAAU,CAAA,EAAV,UAEAA,EAAAA,EAAA,SAAW,CAAA,EAAX,WAEAA,EAAAA,EAAA,OAAS,CAAA,EAAT,SAEAA,EAAAA,EAAA,SAAW,CAAA,EAAX,WAEAA,EAAAA,EAAA,WAAa,CAAA,EAAb,aAEAA,EAAAA,EAAA,QAAU,CAAA,EAAV,UAEAA,EAAAA,EAAA,oBAAsB,CAAA,EAAtB,sBAEAA,EAAAA,EAAA,QAAU,CAAA,EAAV,UAhBUA,IAAAA,GAAA,CAAA,CAAA,EAgCAC,GAAAA,IAEVA,EAAA,gBAAkB,kBAElBA,EAAA,yBAA2B,2BAE3BA,EAAA,8BAAgC,gCAEhCA,EAAA,eAAiB,iBAOjBA,EAAA,oBAAsB,sBAEtBA,EAAA,YAAc,cAjBJA,IAAAA,GAAA,CAAA,CAAA,EAoFL,SAASC,EACdC,EACAC,EAAwC,GACpB,CACpB,KAAM,CACJ,kBAAAC,EACA,aAAAC,EACA,iBAAAC,EACA,UAAAC,EACA,2BAAAC,EACA,mBAAAC,CAAA,EACEN,EAEJ,OAAID,IAAmB,EACjBM,EACK,CAAE,eAAAN,EAAgB,iBAAkB,EAAC,EAG1CG,EACK,CACL,eAAAH,EACA,iBAAkB,CAAC,iBAAA,CAA2B,EAI9CI,IAAqB,IAAQ,CAACF,EACzB,CACL,eAAAF,EACA,iBAAkB,CAAC,+BAAA,CAAyC,EAI5DI,IAAqB,QAAa,CAACF,EAC9B,CAAE,eAAAF,EAAgB,iBAAkB,EAAC,EAGzCE,EAIE,CACL,eAAAF,EACA,iBAAkB,CAAC,0BAAA,CAAoC,EALhD,CAAE,eAAAA,EAAgB,iBAAkB,EAAC,EAS5CA,IAAmB,EAKjBO,EACK,CACL,eAAAP,EACA,iBAAkB,CAAC,qBAAA,CAA+B,EAG/C,CACL,eAAAA,EACA,iBAAkB,CAAC,gBAAA,CAA0B,EAI7CA,IAAmB,EACd,CAAE,eAAAA,EAAgB,iBAAkB,EAAC,EAG1CA,IAAmB,EACd,CAAE,eAAAA,EAAgB,iBAAkB,EAAC,EAG1CA,IAAmB,EACd,CAAE,eAAAA,EAAgB,iBAAkB,EAAC,EAG1CA,IAAmB,EACd,CACL,eAAAA,EACA,iBAAkBK,EAAY,CAAC,eAA2B,CAAA,CAAC,EAI3DL,IAAmB,EACd,CAAE,eAAAA,EAAgB,iBAAkB,EAAC,EAG1CA,IAAmB,EACd,CAAE,eAAAA,EAAgB,iBAAkB,EAAC,EAGvC,CAAE,eAAAA,EAAgB,iBAAkB,EAAC,CAC9C,CAKO,SAASQ,EACdC,EACAC,EACS,CACT,OAAOD,EAAM,iBAAiB,SAASC,CAAM,CAC/C,CAYO,SAASC,EAAkCC,EAItC,CACV,KAAM,CAAE,aAAAC,EAAc,eAAAC,EAAgB,uBAAAC,CAAA,EAA2BH,EACjE,OAAOC,EAAeC,EAAiBC,CACzC"}