@satora/swap 1.4.0 → 1.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.d.cts CHANGED
@@ -436,9 +436,10 @@ type SwapTrackerOptions = {
436
436
  * leg holds funds on-chain (≥ clientfunded, unresolved), where refund safety
437
437
  * must not depend on the server. Everything else advances on server hints
438
438
  * only ({@link applyHint}); a swap with nothing at stake costs zero chain
439
- * reads. Default 60s.
439
+ * reads. A getter is read on every tick, so the cadence can follow a
440
+ * setting that changes on a live client. Default 60s.
440
441
  */
441
- atRiskReconcileIntervalMs?: number;
442
+ atRiskReconcileIntervalMs?: number | (() => number);
442
443
  };
443
444
  declare class SwapTracker {
444
445
  #private;
@@ -472,6 +473,7 @@ declare class SwapTracker {
472
473
  */
473
474
  applyHint(swapId: string, opts?: {
474
475
  force?: boolean;
476
+ status?: SwapStatus;
475
477
  }): Promise<void>;
476
478
  /** Notify `cb` of the current action for each tracked swap, then on every change. */
477
479
  subscribeToActions(cb: ActionSubscriber): () => void;
@@ -721,6 +723,17 @@ declare class Client {
721
723
  recoverGaslessFunds(...args: Parameters<Client$1["recoverGaslessFunds"]>): ReturnType<Client$1["recoverGaslessFunds"]>;
722
724
  /** Delegated to the legacy client (migration checkpoint). */
723
725
  hasReceivedVtxo(...args: Parameters<Client$1["hasReceivedVtxo"]>): ReturnType<Client$1["hasReceivedVtxo"]>;
726
+ /** Confirmations a server-funded Bitcoin HTLC needs before it is claimable. */
727
+ getBitcoinMinConfirmations(): number | undefined;
728
+ /**
729
+ * At `0` the claim goes out against a mempool funding, trusting the funder
730
+ * not to replace it once the claim reveals the preimage.
731
+ *
732
+ * Only the chain monitors read a depth, so this does nothing unless the
733
+ * client was built with {@link ClientBuilder.withChainVerifiedTracking}.
734
+ * Takes effect on subsequent reads, including swaps already tracked.
735
+ */
736
+ setBitcoinMinConfirmations(minConfirmations: number | undefined): void;
724
737
  /**
725
738
  * Start observing the user's active swaps and deriving each one's next action.
726
739
  *
@@ -811,7 +824,8 @@ declare class ClientBuilder {
811
824
  * funding hits the mempool, which TRUSTS the funder not to double-spend it
812
825
  * (claiming publishes the preimage, so a funder that then replaced its
813
826
  * funding could take both legs). Set `1` (or more) for a block-depth policy
814
- * that doesn't rely on the funder's good behaviour.
827
+ * that doesn't rely on the funder's good behaviour. Read only by the chain
828
+ * monitors, so it needs {@link withChainVerifiedTracking} to have any effect.
815
829
  */
816
830
  withBitcoinMinConfirmations(minConfirmations: number): this;
817
831
  /**
@@ -974,67 +988,6 @@ type BitcoinHtlcFacts = {
974
988
  spendWitness?: string[];
975
989
  };
976
990
 
977
- /** The chain surface the observer needs (the esplora and electrum readers satisfy it). */
978
- type BitcoinChainReader = {
979
- /**
980
- * Funding + spend facts for an HTLC witness-script address. `minConfirmations`
981
- * overrides the reader's default for this address alone — the two legs of a
982
- * swap do not share one rule.
983
- */
984
- getHtlcFacts(address: string, minConfirmations?: number): Promise<BitcoinHtlcFacts>;
985
- /**
986
- * Optional push capability: invoke `onChange` whenever the address's tx
987
- * history changes (e.g. an Electrum scripthash subscription). Returns an
988
- * unsubscribe function. When present, the manager reconciles on push
989
- * instead of relying solely on the tracker's poll cadence.
990
- */
991
- subscribe?(address: string, onChange: () => void): () => void;
992
- };
993
- type BitcoinCreateConfig = {
994
- /** One or more esplora REST base URLs; several are tried in rotation with failover. */
995
- esploraUrl: string | string[];
996
- /**
997
- * Optional Electrum WebSocket URL (Fulcrum `ws`/`wss` port). When set, the
998
- * manager reads via Electrum (fresher than public explorers) and gets push
999
- * reconciles via scripthash subscriptions; the esplora reader remains the
1000
- * fallback on Electrum errors.
1001
- */
1002
- electrumWsUrl?: string;
1003
- /** Network the HTLC addresses live on (for Electrum scripthashes); default mainnet. */
1004
- network?: "mainnet" | "testnet" | "signet" | "regtest";
1005
- /** The current Bitcoin MTP (ms); typically `async () => (await client.getMtp()).mtp * 1000`. */
1006
- chainTime?: () => Promise<number>;
1007
- /**
1008
- * Confirmations a funding tx needs before it observes as `confirmed`.
1009
- * Default `0`: accept an unconfirmed funding, trusting the funder not to
1010
- * double-spend it (the claim reveals the preimage against it). `1` = wait
1011
- * for a block.
1012
- */
1013
- minConfirmations?: number;
1014
- };
1015
- type BitcoinContractManagerDeps = {
1016
- reader: BitcoinChainReader;
1017
- chainTime?: () => Promise<number>;
1018
- };
1019
- declare class BitcoinContractManager implements ContractManager {
1020
- #private;
1021
- readonly ledger: Ledger;
1022
- private constructor();
1023
- static fromDeps(deps: BitcoinContractManagerDeps): BitcoinContractManager;
1024
- static create(config: BitcoinCreateConfig): Promise<BitcoinContractManager>;
1025
- canObserve(ref: HtlcRef): boolean;
1026
- register(ref: HtlcRef): Promise<void>;
1027
- unregister(ref: HtlcRef): Promise<void>;
1028
- getState(ref: HtlcRef): HtlcObservation | undefined;
1029
- chainNow(_ref: HtlcRef): number | undefined;
1030
- onEvent(cb: (ref: HtlcRef, state: HtlcObservation) => void): () => void;
1031
- refresh(): Promise<void>;
1032
- reconcile(ref: HtlcRef): Promise<void>;
1033
- dispose(): void;
1034
- /** The preimage a claim revealed on this HTLC, if one was seen. */
1035
- getPreimage(ref: HtlcRef): Uint8Array | undefined;
1036
- }
1037
-
1038
991
  /**
1039
992
  * A esplora-backed {@link BitcoinChainReader} — the concrete chain source the
1040
993
  * {@link BitcoinContractManager} uses in production.
@@ -1062,6 +1015,12 @@ type EsploraTx = {
1062
1015
  block_height?: number;
1063
1016
  };
1064
1017
  };
1018
+ /** A depth already resolved to a number, for the pure classifier below. */
1019
+ type BitcoinConfirmationPolicy = {
1020
+ minConfirmations?: number;
1021
+ };
1022
+ /** A depth, or a getter resolved per read so it can change without a rebuild. */
1023
+ type MinConfirmationsSource = number | (() => number | undefined);
1065
1024
  /**
1066
1025
  * When a funding tx counts as `confirmed` for observation purposes.
1067
1026
  *
@@ -1074,9 +1033,10 @@ type EsploraTx = {
1074
1033
  * `1` (or more) for a policy that doesn't rely on the funder's good behaviour;
1075
1034
  * values above 1 make the reader fetch the tip height to compute depth.
1076
1035
  */
1077
- type BitcoinConfirmationPolicy = {
1078
- minConfirmations?: number;
1036
+ type BitcoinReaderPolicy = {
1037
+ minConfirmations?: MinConfirmationsSource;
1079
1038
  };
1039
+ declare function resolveMinConfirmations(source: MinConfirmationsSource | undefined): number;
1080
1040
  /**
1081
1041
  * Reduce an address's esplora tx history to HTLC facts. If a tx spends an output
1082
1042
  * at the address, that's the resolving spend (its witness classifies claim vs
@@ -1098,7 +1058,69 @@ declare const DEFAULT_ESPLORA_URLS: string[];
1098
1058
  * providers) and fails over to the rest on error — so a throttled or failing
1099
1059
  * provider doesn't stall tracking.
1100
1060
  */
1101
- declare function esploraReader(esploraUrls: string | string[], fetchImpl?: typeof fetch, policy?: BitcoinConfirmationPolicy): BitcoinChainReader;
1061
+ declare function esploraReader(esploraUrls: string | string[], fetchImpl?: typeof fetch, policy?: BitcoinReaderPolicy): BitcoinChainReader;
1062
+
1063
+ /** The chain surface the observer needs (the esplora and electrum readers satisfy it). */
1064
+ type BitcoinChainReader = {
1065
+ /**
1066
+ * Funding + spend facts for an HTLC witness-script address. `minConfirmations`
1067
+ * overrides the reader's default for this address alone — the two legs of a
1068
+ * swap do not share one rule.
1069
+ */
1070
+ getHtlcFacts(address: string, minConfirmations?: number): Promise<BitcoinHtlcFacts>;
1071
+ /**
1072
+ * Optional push capability: invoke `onChange` whenever the address's tx
1073
+ * history changes (e.g. an Electrum scripthash subscription). Returns an
1074
+ * unsubscribe function. When present, the manager reconciles on push
1075
+ * instead of relying solely on the tracker's poll cadence.
1076
+ */
1077
+ subscribe?(address: string, onChange: () => void): () => void;
1078
+ };
1079
+ type BitcoinCreateConfig = {
1080
+ /** One or more esplora REST base URLs; several are tried in rotation with failover. */
1081
+ esploraUrl: string | string[];
1082
+ /**
1083
+ * Optional Electrum WebSocket URL (Fulcrum `ws`/`wss` port). When set, the
1084
+ * manager reads via Electrum (fresher than public explorers) and gets push
1085
+ * reconciles via scripthash subscriptions; the esplora reader remains the
1086
+ * fallback on Electrum errors.
1087
+ */
1088
+ electrumWsUrl?: string;
1089
+ /** Network the HTLC addresses live on (for Electrum scripthashes); default mainnet. */
1090
+ network?: "mainnet" | "testnet" | "signet" | "regtest";
1091
+ /** The current Bitcoin MTP (ms); typically `async () => (await client.getMtp()).mtp * 1000`. */
1092
+ chainTime?: () => Promise<number>;
1093
+ /**
1094
+ * Confirmations a funding tx needs before it observes as `confirmed`.
1095
+ * Default `0`: accept an unconfirmed funding, trusting the funder not to
1096
+ * double-spend it (the claim reveals the preimage against it). `1` = wait
1097
+ * for a block. Only the server-funded leg reads it; `swapToTracked` pins the
1098
+ * client-funded leg to 1.
1099
+ */
1100
+ minConfirmations?: MinConfirmationsSource;
1101
+ };
1102
+ type BitcoinContractManagerDeps = {
1103
+ reader: BitcoinChainReader;
1104
+ chainTime?: () => Promise<number>;
1105
+ };
1106
+ declare class BitcoinContractManager implements ContractManager {
1107
+ #private;
1108
+ readonly ledger: Ledger;
1109
+ private constructor();
1110
+ static fromDeps(deps: BitcoinContractManagerDeps): BitcoinContractManager;
1111
+ static create(config: BitcoinCreateConfig): Promise<BitcoinContractManager>;
1112
+ canObserve(ref: HtlcRef): boolean;
1113
+ register(ref: HtlcRef): Promise<void>;
1114
+ unregister(ref: HtlcRef): Promise<void>;
1115
+ getState(ref: HtlcRef): HtlcObservation | undefined;
1116
+ chainNow(_ref: HtlcRef): number | undefined;
1117
+ onEvent(cb: (ref: HtlcRef, state: HtlcObservation) => void): () => void;
1118
+ refresh(): Promise<void>;
1119
+ reconcile(ref: HtlcRef): Promise<void>;
1120
+ dispose(): void;
1121
+ /** The preimage a claim revealed on this HTLC, if one was seen. */
1122
+ getPreimage(ref: HtlcRef): Uint8Array | undefined;
1123
+ }
1102
1124
 
1103
1125
  /**
1104
1126
  * An Electrum-backed {@link BitcoinChainReader} — reads HTLC facts from our own
@@ -1133,7 +1155,7 @@ type ElectrumReaderNetwork = "mainnet" | "testnet" | "signet" | "regtest";
1133
1155
  * Build a {@link BitcoinChainReader} over an Electrum connection, with push
1134
1156
  * support and an optional fallback reader for outages.
1135
1157
  */
1136
- declare function electrumReader(client: ElectrumRpc, opts?: BitcoinConfirmationPolicy & {
1158
+ declare function electrumReader(client: ElectrumRpc, opts?: BitcoinReaderPolicy & {
1137
1159
  /** Network the HTLC addresses live on; defaults to mainnet. */
1138
1160
  network?: ElectrumReaderNetwork;
1139
1161
  /** Reader consulted when the Electrum server errors (e.g. esplora). */
@@ -1317,6 +1339,8 @@ type EvmLogClient = {
1317
1339
  address: `0x${string}`[];
1318
1340
  topics: (`0x${string}`[] | null)[];
1319
1341
  fromBlock: `0x${string}`;
1342
+ /** Set only when the read is chunked (see `maxBlockRange`). */
1343
+ toBlock?: `0x${string}`;
1320
1344
  }
1321
1345
  ];
1322
1346
  }): Promise<RawLog[]>;
@@ -1329,8 +1353,16 @@ type EvmLogClient = {
1329
1353
  }>;
1330
1354
  getBlock(): Promise<Pick<Block, "timestamp" | "number">>;
1331
1355
  };
1356
+ type EvmReaderOptions = {
1357
+ /**
1358
+ * Largest block span one `eth_getLogs` may cover. Some providers cap it
1359
+ * (rpc.rootstock.io: 2000 blocks); a read past the cap is split into
1360
+ * consecutive chunks up to the latest block. Unset means one unbounded call.
1361
+ */
1362
+ maxBlockRange?: bigint;
1363
+ };
1332
1364
  /** Build an {@link EvmChainReader} over an existing viem-like client. */
1333
- declare function evmReaderFromClient(client: EvmLogClient): EvmChainReader;
1365
+ declare function evmReaderFromClient(client: EvmLogClient, options?: EvmReaderOptions): EvmChainReader;
1334
1366
  /**
1335
1367
  * Build an {@link EvmChainReader} over one or more EVM JSON-RPC endpoints. With
1336
1368
  * several, viem's `fallback` tries them in order and fails over on error.
@@ -1339,7 +1371,7 @@ declare function evmReaderFromClient(client: EvmLogClient): EvmChainReader;
1339
1371
  * public RPCs rate-limiting us (publicnode 403s) — and it contradicts this
1340
1372
  * package's near-zero-RPC design.
1341
1373
  */
1342
- declare function createEvmRpcReader(rpcUrls: string | string[]): EvmChainReader;
1374
+ declare function createEvmRpcReader(rpcUrls: string | string[], options?: EvmReaderOptions): EvmChainReader;
1343
1375
  /**
1344
1376
  * Resolve the per-chain readers used for tracking: the tested {@link
1345
1377
  * DEFAULT_EVM_RPCS} by default, with any `overrides` taking priority for their
@@ -1591,4 +1623,4 @@ declare class WsStatusSource {
1591
1623
 
1592
1624
  declare function swapToTracked(stored: StoredSwap): TrackedSwap | undefined;
1593
1625
 
1594
- export { type ActionSubscriber, ArkadeContractManager, type ArkadeContractManagerDeps, type ArkadeCreateConfig, type ArkadeVhtlcInput, type BitcoinChainReader, type BitcoinConfirmationPolicy, BitcoinContractManager, type BitcoinContractManagerDeps, type BitcoinCreateConfig, type BlockedBy, type BlockedReason, type CctpClaimEvidence, type ClaimAction, Client, ClientBuilder, type ContractManager, DEFAULT_ESPLORA_URLS, DEFAULT_EVM_RPCS, type ElectrumReaderNetwork, type ElectrumRpc, type EvmChainReader, EvmContractManager, type EvmContractManagerDeps, type EvmHtlcQuery, type EvmLogClient, type FundAction, HintTracker, type HintTrackerOptions, type HtlcObservation, type HtlcRef, type Ledger, type NoneAction, type RawLog, type RecoverCctpClaimAction, type RefundCollaborativeAction, type RefundUnilateralAction, type SwapAction, type SwapActionAutomation, type SwapActionId, type SwapActionInput, type SwapActions, type SwapObservations, type SwapOutcome, type SwapStatusUpdate, SwapTracker, SwapWorker, type SwapWorkerOptions, type TrackedSwap, type WaitAction, type WaitingOn, type WebSocketLike, type WorkerHintSource, type WorkerTracker, WsStatusSource, type WsStatusSourceOptions, buildArkadeVhtlcRef, createEvmRpcReader, defaultArkadeServerUrl, defaultEvmReaders, deriveSwapActions, deriveSwapStatus, electrumReader, esploraReader, evmReaderFromClient, htlcFactsFromEsploraTxs, htlcKey, htlcQueryKey, swapToTracked };
1626
+ export { type ActionSubscriber, ArkadeContractManager, type ArkadeContractManagerDeps, type ArkadeCreateConfig, type ArkadeVhtlcInput, type BitcoinChainReader, type BitcoinConfirmationPolicy, BitcoinContractManager, type BitcoinContractManagerDeps, type BitcoinCreateConfig, type BitcoinReaderPolicy, type BlockedBy, type BlockedReason, type CctpClaimEvidence, type ClaimAction, Client, ClientBuilder, type ContractManager, DEFAULT_ESPLORA_URLS, DEFAULT_EVM_RPCS, type ElectrumReaderNetwork, type ElectrumRpc, type EvmChainReader, EvmContractManager, type EvmContractManagerDeps, type EvmHtlcQuery, type EvmLogClient, type FundAction, HintTracker, type HintTrackerOptions, type HtlcObservation, type HtlcRef, type Ledger, type MinConfirmationsSource, type NoneAction, type RawLog, type RecoverCctpClaimAction, type RefundCollaborativeAction, type RefundUnilateralAction, type SwapAction, type SwapActionAutomation, type SwapActionId, type SwapActionInput, type SwapActions, type SwapObservations, type SwapOutcome, type SwapStatusUpdate, SwapTracker, SwapWorker, type SwapWorkerOptions, type TrackedSwap, type WaitAction, type WaitingOn, type WebSocketLike, type WorkerHintSource, type WorkerTracker, WsStatusSource, type WsStatusSourceOptions, buildArkadeVhtlcRef, createEvmRpcReader, defaultArkadeServerUrl, defaultEvmReaders, deriveSwapActions, deriveSwapStatus, electrumReader, esploraReader, evmReaderFromClient, htlcFactsFromEsploraTxs, htlcKey, htlcQueryKey, resolveMinConfirmations, swapToTracked };
package/dist/index.d.ts CHANGED
@@ -436,9 +436,10 @@ type SwapTrackerOptions = {
436
436
  * leg holds funds on-chain (≥ clientfunded, unresolved), where refund safety
437
437
  * must not depend on the server. Everything else advances on server hints
438
438
  * only ({@link applyHint}); a swap with nothing at stake costs zero chain
439
- * reads. Default 60s.
439
+ * reads. A getter is read on every tick, so the cadence can follow a
440
+ * setting that changes on a live client. Default 60s.
440
441
  */
441
- atRiskReconcileIntervalMs?: number;
442
+ atRiskReconcileIntervalMs?: number | (() => number);
442
443
  };
443
444
  declare class SwapTracker {
444
445
  #private;
@@ -472,6 +473,7 @@ declare class SwapTracker {
472
473
  */
473
474
  applyHint(swapId: string, opts?: {
474
475
  force?: boolean;
476
+ status?: SwapStatus;
475
477
  }): Promise<void>;
476
478
  /** Notify `cb` of the current action for each tracked swap, then on every change. */
477
479
  subscribeToActions(cb: ActionSubscriber): () => void;
@@ -721,6 +723,17 @@ declare class Client {
721
723
  recoverGaslessFunds(...args: Parameters<Client$1["recoverGaslessFunds"]>): ReturnType<Client$1["recoverGaslessFunds"]>;
722
724
  /** Delegated to the legacy client (migration checkpoint). */
723
725
  hasReceivedVtxo(...args: Parameters<Client$1["hasReceivedVtxo"]>): ReturnType<Client$1["hasReceivedVtxo"]>;
726
+ /** Confirmations a server-funded Bitcoin HTLC needs before it is claimable. */
727
+ getBitcoinMinConfirmations(): number | undefined;
728
+ /**
729
+ * At `0` the claim goes out against a mempool funding, trusting the funder
730
+ * not to replace it once the claim reveals the preimage.
731
+ *
732
+ * Only the chain monitors read a depth, so this does nothing unless the
733
+ * client was built with {@link ClientBuilder.withChainVerifiedTracking}.
734
+ * Takes effect on subsequent reads, including swaps already tracked.
735
+ */
736
+ setBitcoinMinConfirmations(minConfirmations: number | undefined): void;
724
737
  /**
725
738
  * Start observing the user's active swaps and deriving each one's next action.
726
739
  *
@@ -811,7 +824,8 @@ declare class ClientBuilder {
811
824
  * funding hits the mempool, which TRUSTS the funder not to double-spend it
812
825
  * (claiming publishes the preimage, so a funder that then replaced its
813
826
  * funding could take both legs). Set `1` (or more) for a block-depth policy
814
- * that doesn't rely on the funder's good behaviour.
827
+ * that doesn't rely on the funder's good behaviour. Read only by the chain
828
+ * monitors, so it needs {@link withChainVerifiedTracking} to have any effect.
815
829
  */
816
830
  withBitcoinMinConfirmations(minConfirmations: number): this;
817
831
  /**
@@ -974,67 +988,6 @@ type BitcoinHtlcFacts = {
974
988
  spendWitness?: string[];
975
989
  };
976
990
 
977
- /** The chain surface the observer needs (the esplora and electrum readers satisfy it). */
978
- type BitcoinChainReader = {
979
- /**
980
- * Funding + spend facts for an HTLC witness-script address. `minConfirmations`
981
- * overrides the reader's default for this address alone — the two legs of a
982
- * swap do not share one rule.
983
- */
984
- getHtlcFacts(address: string, minConfirmations?: number): Promise<BitcoinHtlcFacts>;
985
- /**
986
- * Optional push capability: invoke `onChange` whenever the address's tx
987
- * history changes (e.g. an Electrum scripthash subscription). Returns an
988
- * unsubscribe function. When present, the manager reconciles on push
989
- * instead of relying solely on the tracker's poll cadence.
990
- */
991
- subscribe?(address: string, onChange: () => void): () => void;
992
- };
993
- type BitcoinCreateConfig = {
994
- /** One or more esplora REST base URLs; several are tried in rotation with failover. */
995
- esploraUrl: string | string[];
996
- /**
997
- * Optional Electrum WebSocket URL (Fulcrum `ws`/`wss` port). When set, the
998
- * manager reads via Electrum (fresher than public explorers) and gets push
999
- * reconciles via scripthash subscriptions; the esplora reader remains the
1000
- * fallback on Electrum errors.
1001
- */
1002
- electrumWsUrl?: string;
1003
- /** Network the HTLC addresses live on (for Electrum scripthashes); default mainnet. */
1004
- network?: "mainnet" | "testnet" | "signet" | "regtest";
1005
- /** The current Bitcoin MTP (ms); typically `async () => (await client.getMtp()).mtp * 1000`. */
1006
- chainTime?: () => Promise<number>;
1007
- /**
1008
- * Confirmations a funding tx needs before it observes as `confirmed`.
1009
- * Default `0`: accept an unconfirmed funding, trusting the funder not to
1010
- * double-spend it (the claim reveals the preimage against it). `1` = wait
1011
- * for a block.
1012
- */
1013
- minConfirmations?: number;
1014
- };
1015
- type BitcoinContractManagerDeps = {
1016
- reader: BitcoinChainReader;
1017
- chainTime?: () => Promise<number>;
1018
- };
1019
- declare class BitcoinContractManager implements ContractManager {
1020
- #private;
1021
- readonly ledger: Ledger;
1022
- private constructor();
1023
- static fromDeps(deps: BitcoinContractManagerDeps): BitcoinContractManager;
1024
- static create(config: BitcoinCreateConfig): Promise<BitcoinContractManager>;
1025
- canObserve(ref: HtlcRef): boolean;
1026
- register(ref: HtlcRef): Promise<void>;
1027
- unregister(ref: HtlcRef): Promise<void>;
1028
- getState(ref: HtlcRef): HtlcObservation | undefined;
1029
- chainNow(_ref: HtlcRef): number | undefined;
1030
- onEvent(cb: (ref: HtlcRef, state: HtlcObservation) => void): () => void;
1031
- refresh(): Promise<void>;
1032
- reconcile(ref: HtlcRef): Promise<void>;
1033
- dispose(): void;
1034
- /** The preimage a claim revealed on this HTLC, if one was seen. */
1035
- getPreimage(ref: HtlcRef): Uint8Array | undefined;
1036
- }
1037
-
1038
991
  /**
1039
992
  * A esplora-backed {@link BitcoinChainReader} — the concrete chain source the
1040
993
  * {@link BitcoinContractManager} uses in production.
@@ -1062,6 +1015,12 @@ type EsploraTx = {
1062
1015
  block_height?: number;
1063
1016
  };
1064
1017
  };
1018
+ /** A depth already resolved to a number, for the pure classifier below. */
1019
+ type BitcoinConfirmationPolicy = {
1020
+ minConfirmations?: number;
1021
+ };
1022
+ /** A depth, or a getter resolved per read so it can change without a rebuild. */
1023
+ type MinConfirmationsSource = number | (() => number | undefined);
1065
1024
  /**
1066
1025
  * When a funding tx counts as `confirmed` for observation purposes.
1067
1026
  *
@@ -1074,9 +1033,10 @@ type EsploraTx = {
1074
1033
  * `1` (or more) for a policy that doesn't rely on the funder's good behaviour;
1075
1034
  * values above 1 make the reader fetch the tip height to compute depth.
1076
1035
  */
1077
- type BitcoinConfirmationPolicy = {
1078
- minConfirmations?: number;
1036
+ type BitcoinReaderPolicy = {
1037
+ minConfirmations?: MinConfirmationsSource;
1079
1038
  };
1039
+ declare function resolveMinConfirmations(source: MinConfirmationsSource | undefined): number;
1080
1040
  /**
1081
1041
  * Reduce an address's esplora tx history to HTLC facts. If a tx spends an output
1082
1042
  * at the address, that's the resolving spend (its witness classifies claim vs
@@ -1098,7 +1058,69 @@ declare const DEFAULT_ESPLORA_URLS: string[];
1098
1058
  * providers) and fails over to the rest on error — so a throttled or failing
1099
1059
  * provider doesn't stall tracking.
1100
1060
  */
1101
- declare function esploraReader(esploraUrls: string | string[], fetchImpl?: typeof fetch, policy?: BitcoinConfirmationPolicy): BitcoinChainReader;
1061
+ declare function esploraReader(esploraUrls: string | string[], fetchImpl?: typeof fetch, policy?: BitcoinReaderPolicy): BitcoinChainReader;
1062
+
1063
+ /** The chain surface the observer needs (the esplora and electrum readers satisfy it). */
1064
+ type BitcoinChainReader = {
1065
+ /**
1066
+ * Funding + spend facts for an HTLC witness-script address. `minConfirmations`
1067
+ * overrides the reader's default for this address alone — the two legs of a
1068
+ * swap do not share one rule.
1069
+ */
1070
+ getHtlcFacts(address: string, minConfirmations?: number): Promise<BitcoinHtlcFacts>;
1071
+ /**
1072
+ * Optional push capability: invoke `onChange` whenever the address's tx
1073
+ * history changes (e.g. an Electrum scripthash subscription). Returns an
1074
+ * unsubscribe function. When present, the manager reconciles on push
1075
+ * instead of relying solely on the tracker's poll cadence.
1076
+ */
1077
+ subscribe?(address: string, onChange: () => void): () => void;
1078
+ };
1079
+ type BitcoinCreateConfig = {
1080
+ /** One or more esplora REST base URLs; several are tried in rotation with failover. */
1081
+ esploraUrl: string | string[];
1082
+ /**
1083
+ * Optional Electrum WebSocket URL (Fulcrum `ws`/`wss` port). When set, the
1084
+ * manager reads via Electrum (fresher than public explorers) and gets push
1085
+ * reconciles via scripthash subscriptions; the esplora reader remains the
1086
+ * fallback on Electrum errors.
1087
+ */
1088
+ electrumWsUrl?: string;
1089
+ /** Network the HTLC addresses live on (for Electrum scripthashes); default mainnet. */
1090
+ network?: "mainnet" | "testnet" | "signet" | "regtest";
1091
+ /** The current Bitcoin MTP (ms); typically `async () => (await client.getMtp()).mtp * 1000`. */
1092
+ chainTime?: () => Promise<number>;
1093
+ /**
1094
+ * Confirmations a funding tx needs before it observes as `confirmed`.
1095
+ * Default `0`: accept an unconfirmed funding, trusting the funder not to
1096
+ * double-spend it (the claim reveals the preimage against it). `1` = wait
1097
+ * for a block. Only the server-funded leg reads it; `swapToTracked` pins the
1098
+ * client-funded leg to 1.
1099
+ */
1100
+ minConfirmations?: MinConfirmationsSource;
1101
+ };
1102
+ type BitcoinContractManagerDeps = {
1103
+ reader: BitcoinChainReader;
1104
+ chainTime?: () => Promise<number>;
1105
+ };
1106
+ declare class BitcoinContractManager implements ContractManager {
1107
+ #private;
1108
+ readonly ledger: Ledger;
1109
+ private constructor();
1110
+ static fromDeps(deps: BitcoinContractManagerDeps): BitcoinContractManager;
1111
+ static create(config: BitcoinCreateConfig): Promise<BitcoinContractManager>;
1112
+ canObserve(ref: HtlcRef): boolean;
1113
+ register(ref: HtlcRef): Promise<void>;
1114
+ unregister(ref: HtlcRef): Promise<void>;
1115
+ getState(ref: HtlcRef): HtlcObservation | undefined;
1116
+ chainNow(_ref: HtlcRef): number | undefined;
1117
+ onEvent(cb: (ref: HtlcRef, state: HtlcObservation) => void): () => void;
1118
+ refresh(): Promise<void>;
1119
+ reconcile(ref: HtlcRef): Promise<void>;
1120
+ dispose(): void;
1121
+ /** The preimage a claim revealed on this HTLC, if one was seen. */
1122
+ getPreimage(ref: HtlcRef): Uint8Array | undefined;
1123
+ }
1102
1124
 
1103
1125
  /**
1104
1126
  * An Electrum-backed {@link BitcoinChainReader} — reads HTLC facts from our own
@@ -1133,7 +1155,7 @@ type ElectrumReaderNetwork = "mainnet" | "testnet" | "signet" | "regtest";
1133
1155
  * Build a {@link BitcoinChainReader} over an Electrum connection, with push
1134
1156
  * support and an optional fallback reader for outages.
1135
1157
  */
1136
- declare function electrumReader(client: ElectrumRpc, opts?: BitcoinConfirmationPolicy & {
1158
+ declare function electrumReader(client: ElectrumRpc, opts?: BitcoinReaderPolicy & {
1137
1159
  /** Network the HTLC addresses live on; defaults to mainnet. */
1138
1160
  network?: ElectrumReaderNetwork;
1139
1161
  /** Reader consulted when the Electrum server errors (e.g. esplora). */
@@ -1317,6 +1339,8 @@ type EvmLogClient = {
1317
1339
  address: `0x${string}`[];
1318
1340
  topics: (`0x${string}`[] | null)[];
1319
1341
  fromBlock: `0x${string}`;
1342
+ /** Set only when the read is chunked (see `maxBlockRange`). */
1343
+ toBlock?: `0x${string}`;
1320
1344
  }
1321
1345
  ];
1322
1346
  }): Promise<RawLog[]>;
@@ -1329,8 +1353,16 @@ type EvmLogClient = {
1329
1353
  }>;
1330
1354
  getBlock(): Promise<Pick<Block, "timestamp" | "number">>;
1331
1355
  };
1356
+ type EvmReaderOptions = {
1357
+ /**
1358
+ * Largest block span one `eth_getLogs` may cover. Some providers cap it
1359
+ * (rpc.rootstock.io: 2000 blocks); a read past the cap is split into
1360
+ * consecutive chunks up to the latest block. Unset means one unbounded call.
1361
+ */
1362
+ maxBlockRange?: bigint;
1363
+ };
1332
1364
  /** Build an {@link EvmChainReader} over an existing viem-like client. */
1333
- declare function evmReaderFromClient(client: EvmLogClient): EvmChainReader;
1365
+ declare function evmReaderFromClient(client: EvmLogClient, options?: EvmReaderOptions): EvmChainReader;
1334
1366
  /**
1335
1367
  * Build an {@link EvmChainReader} over one or more EVM JSON-RPC endpoints. With
1336
1368
  * several, viem's `fallback` tries them in order and fails over on error.
@@ -1339,7 +1371,7 @@ declare function evmReaderFromClient(client: EvmLogClient): EvmChainReader;
1339
1371
  * public RPCs rate-limiting us (publicnode 403s) — and it contradicts this
1340
1372
  * package's near-zero-RPC design.
1341
1373
  */
1342
- declare function createEvmRpcReader(rpcUrls: string | string[]): EvmChainReader;
1374
+ declare function createEvmRpcReader(rpcUrls: string | string[], options?: EvmReaderOptions): EvmChainReader;
1343
1375
  /**
1344
1376
  * Resolve the per-chain readers used for tracking: the tested {@link
1345
1377
  * DEFAULT_EVM_RPCS} by default, with any `overrides` taking priority for their
@@ -1591,4 +1623,4 @@ declare class WsStatusSource {
1591
1623
 
1592
1624
  declare function swapToTracked(stored: StoredSwap): TrackedSwap | undefined;
1593
1625
 
1594
- export { type ActionSubscriber, ArkadeContractManager, type ArkadeContractManagerDeps, type ArkadeCreateConfig, type ArkadeVhtlcInput, type BitcoinChainReader, type BitcoinConfirmationPolicy, BitcoinContractManager, type BitcoinContractManagerDeps, type BitcoinCreateConfig, type BlockedBy, type BlockedReason, type CctpClaimEvidence, type ClaimAction, Client, ClientBuilder, type ContractManager, DEFAULT_ESPLORA_URLS, DEFAULT_EVM_RPCS, type ElectrumReaderNetwork, type ElectrumRpc, type EvmChainReader, EvmContractManager, type EvmContractManagerDeps, type EvmHtlcQuery, type EvmLogClient, type FundAction, HintTracker, type HintTrackerOptions, type HtlcObservation, type HtlcRef, type Ledger, type NoneAction, type RawLog, type RecoverCctpClaimAction, type RefundCollaborativeAction, type RefundUnilateralAction, type SwapAction, type SwapActionAutomation, type SwapActionId, type SwapActionInput, type SwapActions, type SwapObservations, type SwapOutcome, type SwapStatusUpdate, SwapTracker, SwapWorker, type SwapWorkerOptions, type TrackedSwap, type WaitAction, type WaitingOn, type WebSocketLike, type WorkerHintSource, type WorkerTracker, WsStatusSource, type WsStatusSourceOptions, buildArkadeVhtlcRef, createEvmRpcReader, defaultArkadeServerUrl, defaultEvmReaders, deriveSwapActions, deriveSwapStatus, electrumReader, esploraReader, evmReaderFromClient, htlcFactsFromEsploraTxs, htlcKey, htlcQueryKey, swapToTracked };
1626
+ export { type ActionSubscriber, ArkadeContractManager, type ArkadeContractManagerDeps, type ArkadeCreateConfig, type ArkadeVhtlcInput, type BitcoinChainReader, type BitcoinConfirmationPolicy, BitcoinContractManager, type BitcoinContractManagerDeps, type BitcoinCreateConfig, type BitcoinReaderPolicy, type BlockedBy, type BlockedReason, type CctpClaimEvidence, type ClaimAction, Client, ClientBuilder, type ContractManager, DEFAULT_ESPLORA_URLS, DEFAULT_EVM_RPCS, type ElectrumReaderNetwork, type ElectrumRpc, type EvmChainReader, EvmContractManager, type EvmContractManagerDeps, type EvmHtlcQuery, type EvmLogClient, type FundAction, HintTracker, type HintTrackerOptions, type HtlcObservation, type HtlcRef, type Ledger, type MinConfirmationsSource, type NoneAction, type RawLog, type RecoverCctpClaimAction, type RefundCollaborativeAction, type RefundUnilateralAction, type SwapAction, type SwapActionAutomation, type SwapActionId, type SwapActionInput, type SwapActions, type SwapObservations, type SwapOutcome, type SwapStatusUpdate, SwapTracker, SwapWorker, type SwapWorkerOptions, type TrackedSwap, type WaitAction, type WaitingOn, type WebSocketLike, type WorkerHintSource, type WorkerTracker, WsStatusSource, type WsStatusSourceOptions, buildArkadeVhtlcRef, createEvmRpcReader, defaultArkadeServerUrl, defaultEvmReaders, deriveSwapActions, deriveSwapStatus, electrumReader, esploraReader, evmReaderFromClient, htlcFactsFromEsploraTxs, htlcKey, htlcQueryKey, resolveMinConfirmations, swapToTracked };