@satora/swap 1.4.0 → 1.6.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
@@ -313,6 +313,13 @@ type HtlcRef = {
313
313
  * → `invalid`, so the client never claims a short-funded leg.
314
314
  */
315
315
  expectedAmount: bigint;
316
+ /**
317
+ * Overrides {@link expectedAmount} as the `invalid` threshold, leaving the
318
+ * `isActive` tuple on the expected amount. For the client's own
319
+ * coordinator-locked leg, whose amount is DEX output: the server decides
320
+ * whether a short lock is acceptable, so the client doesn't second-guess it.
321
+ */
322
+ minAmount?: bigint;
316
323
  /** Expected token address; the funding is `invalid` if it locks another token. */
317
324
  expectedToken?: `0x${string}`;
318
325
  /**
@@ -436,9 +443,10 @@ type SwapTrackerOptions = {
436
443
  * leg holds funds on-chain (≥ clientfunded, unresolved), where refund safety
437
444
  * must not depend on the server. Everything else advances on server hints
438
445
  * only ({@link applyHint}); a swap with nothing at stake costs zero chain
439
- * reads. Default 60s.
446
+ * reads. A getter is read on every tick, so the cadence can follow a
447
+ * setting that changes on a live client. Default 60s.
440
448
  */
441
- atRiskReconcileIntervalMs?: number;
449
+ atRiskReconcileIntervalMs?: number | (() => number);
442
450
  };
443
451
  declare class SwapTracker {
444
452
  #private;
@@ -472,6 +480,7 @@ declare class SwapTracker {
472
480
  */
473
481
  applyHint(swapId: string, opts?: {
474
482
  force?: boolean;
483
+ status?: SwapStatus;
475
484
  }): Promise<void>;
476
485
  /** Notify `cb` of the current action for each tracked swap, then on every change. */
477
486
  subscribeToActions(cb: ActionSubscriber): () => void;
@@ -664,6 +673,8 @@ declare class Client {
664
673
  /** Delegated to the legacy client (migration checkpoint). */
665
674
  claim(...args: Parameters<Client$1["claim"]>): ReturnType<Client$1["claim"]>;
666
675
  /** Delegated to the legacy client (migration checkpoint). */
676
+ claimEvmWithSigner(...args: Parameters<Client$1["claimEvmWithSigner"]>): ReturnType<Client$1["claimEvmWithSigner"]>;
677
+ /** Delegated to the legacy client (migration checkpoint). */
667
678
  claimViaGasless(...args: Parameters<Client$1["claimViaGasless"]>): ReturnType<Client$1["claimViaGasless"]>;
668
679
  /** Delegated to the legacy client (migration checkpoint). */
669
680
  claimArkade(...args: Parameters<Client$1["claimArkade"]>): ReturnType<Client$1["claimArkade"]>;
@@ -721,6 +732,17 @@ declare class Client {
721
732
  recoverGaslessFunds(...args: Parameters<Client$1["recoverGaslessFunds"]>): ReturnType<Client$1["recoverGaslessFunds"]>;
722
733
  /** Delegated to the legacy client (migration checkpoint). */
723
734
  hasReceivedVtxo(...args: Parameters<Client$1["hasReceivedVtxo"]>): ReturnType<Client$1["hasReceivedVtxo"]>;
735
+ /** Confirmations a server-funded Bitcoin HTLC needs before it is claimable. */
736
+ getBitcoinMinConfirmations(): number | undefined;
737
+ /**
738
+ * At `0` the claim goes out against a mempool funding, trusting the funder
739
+ * not to replace it once the claim reveals the preimage.
740
+ *
741
+ * Only the chain monitors read a depth, so this does nothing unless the
742
+ * client was built with {@link ClientBuilder.withChainVerifiedTracking}.
743
+ * Takes effect on subsequent reads, including swaps already tracked.
744
+ */
745
+ setBitcoinMinConfirmations(minConfirmations: number | undefined): void;
724
746
  /**
725
747
  * Start observing the user's active swaps and deriving each one's next action.
726
748
  *
@@ -811,7 +833,8 @@ declare class ClientBuilder {
811
833
  * funding hits the mempool, which TRUSTS the funder not to double-spend it
812
834
  * (claiming publishes the preimage, so a funder that then replaced its
813
835
  * 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.
836
+ * that doesn't rely on the funder's good behaviour. Read only by the chain
837
+ * monitors, so it needs {@link withChainVerifiedTracking} to have any effect.
815
838
  */
816
839
  withBitcoinMinConfirmations(minConfirmations: number): this;
817
840
  /**
@@ -974,67 +997,6 @@ type BitcoinHtlcFacts = {
974
997
  spendWitness?: string[];
975
998
  };
976
999
 
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
1000
  /**
1039
1001
  * A esplora-backed {@link BitcoinChainReader} — the concrete chain source the
1040
1002
  * {@link BitcoinContractManager} uses in production.
@@ -1062,6 +1024,12 @@ type EsploraTx = {
1062
1024
  block_height?: number;
1063
1025
  };
1064
1026
  };
1027
+ /** A depth already resolved to a number, for the pure classifier below. */
1028
+ type BitcoinConfirmationPolicy = {
1029
+ minConfirmations?: number;
1030
+ };
1031
+ /** A depth, or a getter resolved per read so it can change without a rebuild. */
1032
+ type MinConfirmationsSource = number | (() => number | undefined);
1065
1033
  /**
1066
1034
  * When a funding tx counts as `confirmed` for observation purposes.
1067
1035
  *
@@ -1074,9 +1042,10 @@ type EsploraTx = {
1074
1042
  * `1` (or more) for a policy that doesn't rely on the funder's good behaviour;
1075
1043
  * values above 1 make the reader fetch the tip height to compute depth.
1076
1044
  */
1077
- type BitcoinConfirmationPolicy = {
1078
- minConfirmations?: number;
1045
+ type BitcoinReaderPolicy = {
1046
+ minConfirmations?: MinConfirmationsSource;
1079
1047
  };
1048
+ declare function resolveMinConfirmations(source: MinConfirmationsSource | undefined): number;
1080
1049
  /**
1081
1050
  * Reduce an address's esplora tx history to HTLC facts. If a tx spends an output
1082
1051
  * at the address, that's the resolving spend (its witness classifies claim vs
@@ -1098,7 +1067,69 @@ declare const DEFAULT_ESPLORA_URLS: string[];
1098
1067
  * providers) and fails over to the rest on error — so a throttled or failing
1099
1068
  * provider doesn't stall tracking.
1100
1069
  */
1101
- declare function esploraReader(esploraUrls: string | string[], fetchImpl?: typeof fetch, policy?: BitcoinConfirmationPolicy): BitcoinChainReader;
1070
+ declare function esploraReader(esploraUrls: string | string[], fetchImpl?: typeof fetch, policy?: BitcoinReaderPolicy): BitcoinChainReader;
1071
+
1072
+ /** The chain surface the observer needs (the esplora and electrum readers satisfy it). */
1073
+ type BitcoinChainReader = {
1074
+ /**
1075
+ * Funding + spend facts for an HTLC witness-script address. `minConfirmations`
1076
+ * overrides the reader's default for this address alone — the two legs of a
1077
+ * swap do not share one rule.
1078
+ */
1079
+ getHtlcFacts(address: string, minConfirmations?: number): Promise<BitcoinHtlcFacts>;
1080
+ /**
1081
+ * Optional push capability: invoke `onChange` whenever the address's tx
1082
+ * history changes (e.g. an Electrum scripthash subscription). Returns an
1083
+ * unsubscribe function. When present, the manager reconciles on push
1084
+ * instead of relying solely on the tracker's poll cadence.
1085
+ */
1086
+ subscribe?(address: string, onChange: () => void): () => void;
1087
+ };
1088
+ type BitcoinCreateConfig = {
1089
+ /** One or more esplora REST base URLs; several are tried in rotation with failover. */
1090
+ esploraUrl: string | string[];
1091
+ /**
1092
+ * Optional Electrum WebSocket URL (Fulcrum `ws`/`wss` port). When set, the
1093
+ * manager reads via Electrum (fresher than public explorers) and gets push
1094
+ * reconciles via scripthash subscriptions; the esplora reader remains the
1095
+ * fallback on Electrum errors.
1096
+ */
1097
+ electrumWsUrl?: string;
1098
+ /** Network the HTLC addresses live on (for Electrum scripthashes); default mainnet. */
1099
+ network?: "mainnet" | "testnet" | "signet" | "regtest";
1100
+ /** The current Bitcoin MTP (ms); typically `async () => (await client.getMtp()).mtp * 1000`. */
1101
+ chainTime?: () => Promise<number>;
1102
+ /**
1103
+ * Confirmations a funding tx needs before it observes as `confirmed`.
1104
+ * Default `0`: accept an unconfirmed funding, trusting the funder not to
1105
+ * double-spend it (the claim reveals the preimage against it). `1` = wait
1106
+ * for a block. Only the server-funded leg reads it; `swapToTracked` pins the
1107
+ * client-funded leg to 1.
1108
+ */
1109
+ minConfirmations?: MinConfirmationsSource;
1110
+ };
1111
+ type BitcoinContractManagerDeps = {
1112
+ reader: BitcoinChainReader;
1113
+ chainTime?: () => Promise<number>;
1114
+ };
1115
+ declare class BitcoinContractManager implements ContractManager {
1116
+ #private;
1117
+ readonly ledger: Ledger;
1118
+ private constructor();
1119
+ static fromDeps(deps: BitcoinContractManagerDeps): BitcoinContractManager;
1120
+ static create(config: BitcoinCreateConfig): Promise<BitcoinContractManager>;
1121
+ canObserve(ref: HtlcRef): boolean;
1122
+ register(ref: HtlcRef): Promise<void>;
1123
+ unregister(ref: HtlcRef): Promise<void>;
1124
+ getState(ref: HtlcRef): HtlcObservation | undefined;
1125
+ chainNow(_ref: HtlcRef): number | undefined;
1126
+ onEvent(cb: (ref: HtlcRef, state: HtlcObservation) => void): () => void;
1127
+ refresh(): Promise<void>;
1128
+ reconcile(ref: HtlcRef): Promise<void>;
1129
+ dispose(): void;
1130
+ /** The preimage a claim revealed on this HTLC, if one was seen. */
1131
+ getPreimage(ref: HtlcRef): Uint8Array | undefined;
1132
+ }
1102
1133
 
1103
1134
  /**
1104
1135
  * An Electrum-backed {@link BitcoinChainReader} — reads HTLC facts from our own
@@ -1133,7 +1164,7 @@ type ElectrumReaderNetwork = "mainnet" | "testnet" | "signet" | "regtest";
1133
1164
  * Build a {@link BitcoinChainReader} over an Electrum connection, with push
1134
1165
  * support and an optional fallback reader for outages.
1135
1166
  */
1136
- declare function electrumReader(client: ElectrumRpc, opts?: BitcoinConfirmationPolicy & {
1167
+ declare function electrumReader(client: ElectrumRpc, opts?: BitcoinReaderPolicy & {
1137
1168
  /** Network the HTLC addresses live on; defaults to mainnet. */
1138
1169
  network?: ElectrumReaderNetwork;
1139
1170
  /** Reader consulted when the Electrum server errors (e.g. esplora). */
@@ -1317,6 +1348,8 @@ type EvmLogClient = {
1317
1348
  address: `0x${string}`[];
1318
1349
  topics: (`0x${string}`[] | null)[];
1319
1350
  fromBlock: `0x${string}`;
1351
+ /** Set only when the read is chunked (see `maxBlockRange`). */
1352
+ toBlock?: `0x${string}`;
1320
1353
  }
1321
1354
  ];
1322
1355
  }): Promise<RawLog[]>;
@@ -1329,8 +1362,16 @@ type EvmLogClient = {
1329
1362
  }>;
1330
1363
  getBlock(): Promise<Pick<Block, "timestamp" | "number">>;
1331
1364
  };
1365
+ type EvmReaderOptions = {
1366
+ /**
1367
+ * Largest block span one `eth_getLogs` may cover. Some providers cap it
1368
+ * (rpc.rootstock.io: 2000 blocks); a read past the cap is split into
1369
+ * consecutive chunks up to the latest block. Unset means one unbounded call.
1370
+ */
1371
+ maxBlockRange?: bigint;
1372
+ };
1332
1373
  /** Build an {@link EvmChainReader} over an existing viem-like client. */
1333
- declare function evmReaderFromClient(client: EvmLogClient): EvmChainReader;
1374
+ declare function evmReaderFromClient(client: EvmLogClient, options?: EvmReaderOptions): EvmChainReader;
1334
1375
  /**
1335
1376
  * Build an {@link EvmChainReader} over one or more EVM JSON-RPC endpoints. With
1336
1377
  * several, viem's `fallback` tries them in order and fails over on error.
@@ -1339,7 +1380,7 @@ declare function evmReaderFromClient(client: EvmLogClient): EvmChainReader;
1339
1380
  * public RPCs rate-limiting us (publicnode 403s) — and it contradicts this
1340
1381
  * package's near-zero-RPC design.
1341
1382
  */
1342
- declare function createEvmRpcReader(rpcUrls: string | string[]): EvmChainReader;
1383
+ declare function createEvmRpcReader(rpcUrls: string | string[], options?: EvmReaderOptions): EvmChainReader;
1343
1384
  /**
1344
1385
  * Resolve the per-chain readers used for tracking: the tested {@link
1345
1386
  * DEFAULT_EVM_RPCS} by default, with any `overrides` taking priority for their
@@ -1591,4 +1632,4 @@ declare class WsStatusSource {
1591
1632
 
1592
1633
  declare function swapToTracked(stored: StoredSwap): TrackedSwap | undefined;
1593
1634
 
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 };
1635
+ 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
@@ -313,6 +313,13 @@ type HtlcRef = {
313
313
  * → `invalid`, so the client never claims a short-funded leg.
314
314
  */
315
315
  expectedAmount: bigint;
316
+ /**
317
+ * Overrides {@link expectedAmount} as the `invalid` threshold, leaving the
318
+ * `isActive` tuple on the expected amount. For the client's own
319
+ * coordinator-locked leg, whose amount is DEX output: the server decides
320
+ * whether a short lock is acceptable, so the client doesn't second-guess it.
321
+ */
322
+ minAmount?: bigint;
316
323
  /** Expected token address; the funding is `invalid` if it locks another token. */
317
324
  expectedToken?: `0x${string}`;
318
325
  /**
@@ -436,9 +443,10 @@ type SwapTrackerOptions = {
436
443
  * leg holds funds on-chain (≥ clientfunded, unresolved), where refund safety
437
444
  * must not depend on the server. Everything else advances on server hints
438
445
  * only ({@link applyHint}); a swap with nothing at stake costs zero chain
439
- * reads. Default 60s.
446
+ * reads. A getter is read on every tick, so the cadence can follow a
447
+ * setting that changes on a live client. Default 60s.
440
448
  */
441
- atRiskReconcileIntervalMs?: number;
449
+ atRiskReconcileIntervalMs?: number | (() => number);
442
450
  };
443
451
  declare class SwapTracker {
444
452
  #private;
@@ -472,6 +480,7 @@ declare class SwapTracker {
472
480
  */
473
481
  applyHint(swapId: string, opts?: {
474
482
  force?: boolean;
483
+ status?: SwapStatus;
475
484
  }): Promise<void>;
476
485
  /** Notify `cb` of the current action for each tracked swap, then on every change. */
477
486
  subscribeToActions(cb: ActionSubscriber): () => void;
@@ -664,6 +673,8 @@ declare class Client {
664
673
  /** Delegated to the legacy client (migration checkpoint). */
665
674
  claim(...args: Parameters<Client$1["claim"]>): ReturnType<Client$1["claim"]>;
666
675
  /** Delegated to the legacy client (migration checkpoint). */
676
+ claimEvmWithSigner(...args: Parameters<Client$1["claimEvmWithSigner"]>): ReturnType<Client$1["claimEvmWithSigner"]>;
677
+ /** Delegated to the legacy client (migration checkpoint). */
667
678
  claimViaGasless(...args: Parameters<Client$1["claimViaGasless"]>): ReturnType<Client$1["claimViaGasless"]>;
668
679
  /** Delegated to the legacy client (migration checkpoint). */
669
680
  claimArkade(...args: Parameters<Client$1["claimArkade"]>): ReturnType<Client$1["claimArkade"]>;
@@ -721,6 +732,17 @@ declare class Client {
721
732
  recoverGaslessFunds(...args: Parameters<Client$1["recoverGaslessFunds"]>): ReturnType<Client$1["recoverGaslessFunds"]>;
722
733
  /** Delegated to the legacy client (migration checkpoint). */
723
734
  hasReceivedVtxo(...args: Parameters<Client$1["hasReceivedVtxo"]>): ReturnType<Client$1["hasReceivedVtxo"]>;
735
+ /** Confirmations a server-funded Bitcoin HTLC needs before it is claimable. */
736
+ getBitcoinMinConfirmations(): number | undefined;
737
+ /**
738
+ * At `0` the claim goes out against a mempool funding, trusting the funder
739
+ * not to replace it once the claim reveals the preimage.
740
+ *
741
+ * Only the chain monitors read a depth, so this does nothing unless the
742
+ * client was built with {@link ClientBuilder.withChainVerifiedTracking}.
743
+ * Takes effect on subsequent reads, including swaps already tracked.
744
+ */
745
+ setBitcoinMinConfirmations(minConfirmations: number | undefined): void;
724
746
  /**
725
747
  * Start observing the user's active swaps and deriving each one's next action.
726
748
  *
@@ -811,7 +833,8 @@ declare class ClientBuilder {
811
833
  * funding hits the mempool, which TRUSTS the funder not to double-spend it
812
834
  * (claiming publishes the preimage, so a funder that then replaced its
813
835
  * 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.
836
+ * that doesn't rely on the funder's good behaviour. Read only by the chain
837
+ * monitors, so it needs {@link withChainVerifiedTracking} to have any effect.
815
838
  */
816
839
  withBitcoinMinConfirmations(minConfirmations: number): this;
817
840
  /**
@@ -974,67 +997,6 @@ type BitcoinHtlcFacts = {
974
997
  spendWitness?: string[];
975
998
  };
976
999
 
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
1000
  /**
1039
1001
  * A esplora-backed {@link BitcoinChainReader} — the concrete chain source the
1040
1002
  * {@link BitcoinContractManager} uses in production.
@@ -1062,6 +1024,12 @@ type EsploraTx = {
1062
1024
  block_height?: number;
1063
1025
  };
1064
1026
  };
1027
+ /** A depth already resolved to a number, for the pure classifier below. */
1028
+ type BitcoinConfirmationPolicy = {
1029
+ minConfirmations?: number;
1030
+ };
1031
+ /** A depth, or a getter resolved per read so it can change without a rebuild. */
1032
+ type MinConfirmationsSource = number | (() => number | undefined);
1065
1033
  /**
1066
1034
  * When a funding tx counts as `confirmed` for observation purposes.
1067
1035
  *
@@ -1074,9 +1042,10 @@ type EsploraTx = {
1074
1042
  * `1` (or more) for a policy that doesn't rely on the funder's good behaviour;
1075
1043
  * values above 1 make the reader fetch the tip height to compute depth.
1076
1044
  */
1077
- type BitcoinConfirmationPolicy = {
1078
- minConfirmations?: number;
1045
+ type BitcoinReaderPolicy = {
1046
+ minConfirmations?: MinConfirmationsSource;
1079
1047
  };
1048
+ declare function resolveMinConfirmations(source: MinConfirmationsSource | undefined): number;
1080
1049
  /**
1081
1050
  * Reduce an address's esplora tx history to HTLC facts. If a tx spends an output
1082
1051
  * at the address, that's the resolving spend (its witness classifies claim vs
@@ -1098,7 +1067,69 @@ declare const DEFAULT_ESPLORA_URLS: string[];
1098
1067
  * providers) and fails over to the rest on error — so a throttled or failing
1099
1068
  * provider doesn't stall tracking.
1100
1069
  */
1101
- declare function esploraReader(esploraUrls: string | string[], fetchImpl?: typeof fetch, policy?: BitcoinConfirmationPolicy): BitcoinChainReader;
1070
+ declare function esploraReader(esploraUrls: string | string[], fetchImpl?: typeof fetch, policy?: BitcoinReaderPolicy): BitcoinChainReader;
1071
+
1072
+ /** The chain surface the observer needs (the esplora and electrum readers satisfy it). */
1073
+ type BitcoinChainReader = {
1074
+ /**
1075
+ * Funding + spend facts for an HTLC witness-script address. `minConfirmations`
1076
+ * overrides the reader's default for this address alone — the two legs of a
1077
+ * swap do not share one rule.
1078
+ */
1079
+ getHtlcFacts(address: string, minConfirmations?: number): Promise<BitcoinHtlcFacts>;
1080
+ /**
1081
+ * Optional push capability: invoke `onChange` whenever the address's tx
1082
+ * history changes (e.g. an Electrum scripthash subscription). Returns an
1083
+ * unsubscribe function. When present, the manager reconciles on push
1084
+ * instead of relying solely on the tracker's poll cadence.
1085
+ */
1086
+ subscribe?(address: string, onChange: () => void): () => void;
1087
+ };
1088
+ type BitcoinCreateConfig = {
1089
+ /** One or more esplora REST base URLs; several are tried in rotation with failover. */
1090
+ esploraUrl: string | string[];
1091
+ /**
1092
+ * Optional Electrum WebSocket URL (Fulcrum `ws`/`wss` port). When set, the
1093
+ * manager reads via Electrum (fresher than public explorers) and gets push
1094
+ * reconciles via scripthash subscriptions; the esplora reader remains the
1095
+ * fallback on Electrum errors.
1096
+ */
1097
+ electrumWsUrl?: string;
1098
+ /** Network the HTLC addresses live on (for Electrum scripthashes); default mainnet. */
1099
+ network?: "mainnet" | "testnet" | "signet" | "regtest";
1100
+ /** The current Bitcoin MTP (ms); typically `async () => (await client.getMtp()).mtp * 1000`. */
1101
+ chainTime?: () => Promise<number>;
1102
+ /**
1103
+ * Confirmations a funding tx needs before it observes as `confirmed`.
1104
+ * Default `0`: accept an unconfirmed funding, trusting the funder not to
1105
+ * double-spend it (the claim reveals the preimage against it). `1` = wait
1106
+ * for a block. Only the server-funded leg reads it; `swapToTracked` pins the
1107
+ * client-funded leg to 1.
1108
+ */
1109
+ minConfirmations?: MinConfirmationsSource;
1110
+ };
1111
+ type BitcoinContractManagerDeps = {
1112
+ reader: BitcoinChainReader;
1113
+ chainTime?: () => Promise<number>;
1114
+ };
1115
+ declare class BitcoinContractManager implements ContractManager {
1116
+ #private;
1117
+ readonly ledger: Ledger;
1118
+ private constructor();
1119
+ static fromDeps(deps: BitcoinContractManagerDeps): BitcoinContractManager;
1120
+ static create(config: BitcoinCreateConfig): Promise<BitcoinContractManager>;
1121
+ canObserve(ref: HtlcRef): boolean;
1122
+ register(ref: HtlcRef): Promise<void>;
1123
+ unregister(ref: HtlcRef): Promise<void>;
1124
+ getState(ref: HtlcRef): HtlcObservation | undefined;
1125
+ chainNow(_ref: HtlcRef): number | undefined;
1126
+ onEvent(cb: (ref: HtlcRef, state: HtlcObservation) => void): () => void;
1127
+ refresh(): Promise<void>;
1128
+ reconcile(ref: HtlcRef): Promise<void>;
1129
+ dispose(): void;
1130
+ /** The preimage a claim revealed on this HTLC, if one was seen. */
1131
+ getPreimage(ref: HtlcRef): Uint8Array | undefined;
1132
+ }
1102
1133
 
1103
1134
  /**
1104
1135
  * An Electrum-backed {@link BitcoinChainReader} — reads HTLC facts from our own
@@ -1133,7 +1164,7 @@ type ElectrumReaderNetwork = "mainnet" | "testnet" | "signet" | "regtest";
1133
1164
  * Build a {@link BitcoinChainReader} over an Electrum connection, with push
1134
1165
  * support and an optional fallback reader for outages.
1135
1166
  */
1136
- declare function electrumReader(client: ElectrumRpc, opts?: BitcoinConfirmationPolicy & {
1167
+ declare function electrumReader(client: ElectrumRpc, opts?: BitcoinReaderPolicy & {
1137
1168
  /** Network the HTLC addresses live on; defaults to mainnet. */
1138
1169
  network?: ElectrumReaderNetwork;
1139
1170
  /** Reader consulted when the Electrum server errors (e.g. esplora). */
@@ -1317,6 +1348,8 @@ type EvmLogClient = {
1317
1348
  address: `0x${string}`[];
1318
1349
  topics: (`0x${string}`[] | null)[];
1319
1350
  fromBlock: `0x${string}`;
1351
+ /** Set only when the read is chunked (see `maxBlockRange`). */
1352
+ toBlock?: `0x${string}`;
1320
1353
  }
1321
1354
  ];
1322
1355
  }): Promise<RawLog[]>;
@@ -1329,8 +1362,16 @@ type EvmLogClient = {
1329
1362
  }>;
1330
1363
  getBlock(): Promise<Pick<Block, "timestamp" | "number">>;
1331
1364
  };
1365
+ type EvmReaderOptions = {
1366
+ /**
1367
+ * Largest block span one `eth_getLogs` may cover. Some providers cap it
1368
+ * (rpc.rootstock.io: 2000 blocks); a read past the cap is split into
1369
+ * consecutive chunks up to the latest block. Unset means one unbounded call.
1370
+ */
1371
+ maxBlockRange?: bigint;
1372
+ };
1332
1373
  /** Build an {@link EvmChainReader} over an existing viem-like client. */
1333
- declare function evmReaderFromClient(client: EvmLogClient): EvmChainReader;
1374
+ declare function evmReaderFromClient(client: EvmLogClient, options?: EvmReaderOptions): EvmChainReader;
1334
1375
  /**
1335
1376
  * Build an {@link EvmChainReader} over one or more EVM JSON-RPC endpoints. With
1336
1377
  * several, viem's `fallback` tries them in order and fails over on error.
@@ -1339,7 +1380,7 @@ declare function evmReaderFromClient(client: EvmLogClient): EvmChainReader;
1339
1380
  * public RPCs rate-limiting us (publicnode 403s) — and it contradicts this
1340
1381
  * package's near-zero-RPC design.
1341
1382
  */
1342
- declare function createEvmRpcReader(rpcUrls: string | string[]): EvmChainReader;
1383
+ declare function createEvmRpcReader(rpcUrls: string | string[], options?: EvmReaderOptions): EvmChainReader;
1343
1384
  /**
1344
1385
  * Resolve the per-chain readers used for tracking: the tested {@link
1345
1386
  * DEFAULT_EVM_RPCS} by default, with any `overrides` taking priority for their
@@ -1591,4 +1632,4 @@ declare class WsStatusSource {
1591
1632
 
1592
1633
  declare function swapToTracked(stored: StoredSwap): TrackedSwap | undefined;
1593
1634
 
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 };
1635
+ 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 };