@arkade-os/swap 0.0.10 → 0.0.12

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
@@ -1,9 +1,9 @@
1
- import { ProvisionedKey, ProvisionedClaimSecret, asset, IWallet, arkade, RestIndexerProvider, Transaction, IContractManager, VHTLC, Identity, ActivityResolver } from '@arkade-os/sdk';
2
- import { S as SwapSecretsProjection, R as RfqSwapRecord, A as AssetSwapRepository, a as AssetSwap, M as MarketsCacheEntry, b as RefundArkProvider, c as RefundIndexer, L as LockupVtxo, d as RfqSwap, e as ArkadeRefundResult, f as LockupSpendIndexer, g as RfqSwapState } from './repository-C8FXlmHY.cjs';
3
- export { h as AssetSwapStatus, i as AvailableRfqSwapManagerCallbacks, B as BTC_ASSET_ID, I as InMemoryAssetSwapRepository, j as LightningReceiveSwap, k as LightningSendSwap, l as LockupFate, m as LockupNeedsRecoveryError, n as LockupParams, o as LockupSpend, O as OnchainSendAction, p as OnchainSendSwap, P as PersistableRfqSwap, q as PreimageBlockedReason, r as PreimageNotRecoverableError, s as REFUND_MTP_LAG_SECONDS, t as RFQ_RESOLVED_STATES, u as RFQ_SWAP_RETENTION_SECONDS, v as RFQ_SWAP_TERMINAL_STATES, w as RefundOutcome, x as RfqRestoreFailure, y as RfqRestoreOptions, z as RfqRestoreResult, C as RfqSwapActionName, D as RfqSwapLockup, E as RfqSwapManager, F as RfqSwapManagerCallbacks, G as RfqSwapManagerConfig, H as RfqSwapManagerDeps, J as RfqSwapManagerEvents, K as RfqSwapOrigin, N as RfqSwapOriginRequired, Q as RfqSwapOutcome, T as RfqSwapRecordStore, U as SwapContractRegistry, V as addAssetSwap, W as awaitRfqResolution, X as createRfqSwapRecord, Y as findLockupVtxos, Z as getAssetSwaps, _ as getAssetSwapsOrThrow, $ as isRfqSwapTerminal, a0 as isRfqTerminal, a1 as nextOnchainAction, a2 as preimageForSwapRecord, a3 as pushRefundWithoutReceiver, a4 as readLockupFate, a5 as rebuildRfqSwap, a6 as refundIfUnresolved, a7 as rfqSwapOriginOf, a8 as shouldRetainRfqSwap, a9 as swapSecretsToRecord, aa as updateAssetSwap, ab as updateAssetSwapBestEffort, ac as updateRfqSwapRecord } from './repository-C8FXlmHY.cjs';
1
+ import { ProvisionedKey, ProvisionedClaimSecret, asset, RelativeTimelock, IWallet, arkade, RestIndexerProvider, Transaction, IContractManager, OnchainProvider, PaymentRail, VHTLC, Identity, ActivityResolver } from '@arkade-os/sdk';
2
+ import { S as SwapSecretsProjection, R as RfqSwapRecord, A as AssetSwapRepository, a as AssetSwap, M as MarketsCacheEntry, b as RefundArkProvider, c as RefundIndexer, L as LockupVtxo, d as RfqSwap, e as ArkadeRefundResult, f as LockupSpendIndexer, g as RfqSwapState } from './repository-DaK1RzRq.cjs';
3
+ export { h as AssetSwapStatus, i as AvailableRfqSwapManagerCallbacks, B as BTC_ASSET_ID, I as InMemoryAssetSwapRepository, j as LightningReceiveSwap, k as LightningSendSwap, l as LockupFate, m as LockupNeedsRecoveryError, n as LockupParams, o as LockupSpend, O as OnchainSendAction, p as OnchainSendSwap, P as PersistableRfqSwap, q as PreimageBlockedReason, r as PreimageNotRecoverableError, s as REFUND_MTP_LAG_SECONDS, t as RFQ_RESOLVED_STATES, u as RFQ_SWAP_RETENTION_SECONDS, v as RFQ_SWAP_TERMINAL_STATES, w as RefundOutcome, x as RfqRestoreFailure, y as RfqRestoreOptions, z as RfqRestoreResult, C as RfqSwapActionName, D as RfqSwapLockup, E as RfqSwapManager, F as RfqSwapManagerCallbacks, G as RfqSwapManagerConfig, H as RfqSwapManagerDeps, J as RfqSwapManagerEvents, K as RfqSwapOrigin, N as RfqSwapOriginRequired, Q as RfqSwapOutcome, T as RfqSwapRecordStore, U as SwapContractRegistry, V as addAssetSwap, W as awaitRfqResolution, X as createRfqSwapRecord, Y as findLockupVtxos, Z as getAssetSwaps, _ as getAssetSwapsOrThrow, $ as isRfqSwapTerminal, a0 as isRfqTerminal, a1 as nextOnchainAction, a2 as preimageForSwapRecord, a3 as pushRefundWithoutReceiver, a4 as readLockupFate, a5 as rebuildRfqSwap, a6 as refundIfUnresolved, a7 as rfqSwapOriginOf, a8 as shouldRetainRfqSwap, a9 as swapSecretsToRecord, aa as updateAssetSwap, ab as updateAssetSwapBestEffort, ac as updateRfqSwapRecord } from './repository-DaK1RzRq.cjs';
4
4
  import { Network, LocalCardInput, DiscoveredMarket, Side, OfferPlan } from '@arkade-os/solver-discovery';
5
- import { O as OnchainNetwork, a as OnchainHtlc, b as OnchainHtlcParams } from './rfq-DglvHMNC.cjs';
6
- export { A as ARKADE_ASSET, c as ARKADE_BTC, d as AddressMismatch, C as ChainSource, e as ChainUtxo, H as HtlcUtxo, I as InvoiceFacts, L as LIGHTNING_BTC, f as LIGHTNING_RECEIVE_PAIR, g as LIGHTNING_SEND_PAIR, h as LOCKTIME_THRESHOLD, i as LightningReceiveTreeParams, j as LightningSendTreeParams, M as MAX_MIN_CONFIRMATIONS, k as MIN_CLAIM_WINDOW_SECONDS, l as MIN_HEADROOM_SECONDS, m as ONCHAIN_BTC, n as ONCHAIN_CLAIM_MARGIN_SECONDS, o as ONCHAIN_DUST_SATS, p as ONCHAIN_ORDER_MARGIN_SECONDS, q as ONCHAIN_RECEIVE_PAIR, r as ONCHAIN_SECONDS_PER_BLOCK, s as ONCHAIN_SEND_PAIR, t as OnchainHtlcPhase, R as RFQ_TERMINAL_STATES, u as RelaySocket, v as RfqQuote, w as RfqRefusalReason, x as RfqStatus, y as RfqTransport, S as SOLO_REFUND_HEADROOM_SECONDS, z as SwapRefusal, B as arkadeAssetLeg, D as arkadeSwapRequest, E as assertFundable, F as assertReceivable, G as awaitOnchainFill, J as buildHtlcClaim, K as buildHtlcRefund, N as claimOnchainFill, P as classifyOnchainHtlc, Q as deriveLightningReceive, T as deriveOnchainReceive, U as deriveOnchainSend, V as extractPreimage, W as httpTransport, X as lightningReceiveRequest, Y as lightningSendRequest, Z as lightningSendVtxoScript, _ as newPreimage, $ as newRfqId, a0 as offerTermsFromQuote, a1 as onchainHtlcScript, a2 as onchainReceiveRequest, a3 as onchainSendRequest, a4 as paymentHashOf, a5 as receiveVtxoScript, a6 as relayTransport, a7 as requestLightningReceive, a8 as requestLightningSend, a9 as requestOnchainReceive, aa as requestOnchainSend, ab as rfqPair, ac as unilateralClaimDelay, ad as unilateralRefundDelay, ae as unilateralRefundWithoutReceiverDelay, af as verifyLockupAddress, ag as verifyReceiveInvoice } from './rfq-DglvHMNC.cjs';
5
+ import { O as OnchainNetwork, a as OnchainHtlc, b as OnchainHtlcParams, C as ChainSource, R as RfqTransport, r as requestOnchainSend, I as InvoiceFacts, c as requestLightningSend } from './rfq-DzsmhXX3.cjs';
6
+ export { A as ARKADE_ASSET, d as ARKADE_BTC, e as AddressMismatch, f as ChainUtxo, H as HtlcUtxo, L as LIGHTNING_BTC, g as LIGHTNING_RECEIVE_PAIR, h as LIGHTNING_SEND_PAIR, i as LOCKTIME_THRESHOLD, j as LightningReceiveTreeParams, k as LightningSendTreeParams, M as MAX_MIN_CONFIRMATIONS, l as MIN_CLAIM_WINDOW_SECONDS, m as MIN_HEADROOM_SECONDS, n as ONCHAIN_BTC, o as ONCHAIN_CLAIM_MARGIN_SECONDS, p as ONCHAIN_DUST_SATS, q as ONCHAIN_ORDER_MARGIN_SECONDS, s as ONCHAIN_RECEIVE_PAIR, t as ONCHAIN_SECONDS_PER_BLOCK, u as ONCHAIN_SEND_PAIR, v as OnchainHtlcPhase, w as RFQ_TERMINAL_STATES, x as RelaySocket, y as RfqQuote, z as RfqRefusalReason, B as RfqStatus, S as SOLO_REFUND_HEADROOM_SECONDS, D as SwapRefusal, E as arkadeAssetLeg, F as arkadeSwapRequest, G as assertFundable, J as assertReceivable, K as awaitOnchainFill, N as buildHtlcClaim, P as buildHtlcRefund, Q as claimOnchainFill, T as classifyOnchainHtlc, U as deriveLightningReceive, V as deriveOnchainReceive, W as deriveOnchainSend, X as extractPreimage, Y as httpTransport, Z as l1ScriptForAddress, _ as lightningReceiveRequest, $ as lightningSendRequest, a0 as lightningSendVtxoScript, a1 as newPreimage, a2 as newRfqId, a3 as offerTermsFromQuote, a4 as onchainHtlcScript, a5 as onchainReceiveRequest, a6 as onchainSendRequest, a7 as paymentHashOf, a8 as receiveVtxoScript, a9 as relayTransport, aa as requestLightningReceive, ab as requestOnchainReceive, ac as rfqPair, ad as unilateralClaimDelay, ae as unilateralRefundDelay, af as unilateralRefundWithoutReceiverDelay, ag as verifyLockupAddress, ah as verifyReceiveInvoice } from './rfq-DzsmhXX3.cjs';
7
7
 
8
8
  /**
9
9
  * Which wallet key signs this leg. Stored at `profile.signer`.
@@ -141,6 +141,9 @@ interface OnchainSendProfile extends Record<string, unknown> {
141
141
  htlcAddress: string;
142
142
  /** `profile.min_confirmations`; gates when the fill is claimable. */
143
143
  minConfirmations: number;
144
+ /** Where the claim PAYS, hex. The spender's own choice, so nothing else
145
+ * gives it back — and `buildHtlcClaim` needs it. */
146
+ payoutPkScript: string;
144
147
  /** The fill's outpoint, learned on first sighting. Without it a SPENT htlc
145
148
  * reads as never funded — see `classifyOnchainHtlc`. */
146
149
  funding?: {
@@ -180,9 +183,21 @@ declare function onchainSendProfile(result: {
180
183
  htlcParams: OnchainHtlcParams;
181
184
  l1Network: OnchainNetwork;
182
185
  minConfirmations: number;
186
+ payoutPkScript: Uint8Array;
183
187
  }): Omit<OnchainSendProfile, "signer" | "hashlock">;
184
188
 
185
- /** The contracts — pure data, shared verbatim with any other implementation. */
189
+ /**
190
+ * The contracts, one per WANT side — pure data, shared verbatim with any other
191
+ * implementation.
192
+ *
193
+ * **These are the base: an offer carrying an exit delay compiles to a third
194
+ * closure that is not in either file.** The tree is not fixed-shape — the
195
+ * protocol defines the exit as `iff ExitDelay`, and solverd appends it the same
196
+ * way (`pkg/swap/contract/offer.go`, `VtxoScript`) — so it cannot be a function
197
+ * in a static artifact without splitting these into one file per exit variant.
198
+ * {@link withExitClosure} owns that step, and the golden in `offer.test.ts`
199
+ * pins the artifact it produces so the whole contract is still readable as data.
200
+ */
186
201
  declare const swapPrograms: Record<"wantAsset" | "wantBtc", ReturnType<typeof arkade.parseArtifact>>;
187
202
  /** A full-fill offer. Exactly one field names an asset: `wantAsset` set = the
188
203
  * fill must deliver that asset (the deposit may be BTC or another asset,
@@ -203,6 +218,14 @@ interface Offer {
203
218
  makerPublicKey: Uint8Array;
204
219
  /** Covenant co-signer (emulator) x-only key (32 bytes). */
205
220
  emulatorPubkey: Uint8Array;
221
+ /** Partial-fill numerator. Reserved wire space in V1: carried through the
222
+ * codec so an offer that sets it decodes, never interpreted here. */
223
+ ratioNum?: bigint;
224
+ /** Partial-fill denominator. Set with {@link Offer.ratioNum} or not at all. */
225
+ ratioDen?: bigint;
226
+ /** The maker's unilateral exit path. Present adds a third closure to the
227
+ * taproot tree, so it changes `swapPkScript` — see {@link offerVtxoScript}. */
228
+ exitDelay?: RelativeTimelock;
206
229
  }
207
230
  /** Compile the offer's contract: program + args -> taproot tree. */
208
231
  declare function offerVtxoScript(offer: Omit<Offer, "swapPkScript">, serverPubkey: Uint8Array): InstanceType<typeof arkade.ArkadeProgramScript>;
@@ -233,6 +256,14 @@ declare function decodeOffer(data: Uint8Array): Offer;
233
256
  * funding rather than after: nothing is at stake yet, so a failure can throw
234
257
  * and be retried, where the same failure after `wallet.send` would leave a
235
258
  * funded deposit unwatched with no way to notice.
259
+ *
260
+ * **The maker's unilateral exit closure is built by default**, at the server's
261
+ * own `unilateralExitDelay` — the same thing solverd does. Without it `cancel`
262
+ * is the only way back out, and `cancel` needs the server's signature: a server
263
+ * that will not co-sign leaves the deposit stuck at the swap address until the
264
+ * VTXO expires and the operator sweeps it. An offer has no expiry of its own,
265
+ * so that exposure has no end. `noExit` opts out for a caller who wants the
266
+ * smaller tree and accepts the dependency.
236
267
  */
237
268
  declare function createOffer(wallet: IWallet, arkServerUrl: string, params: {
238
269
  wantAmount: bigint;
@@ -241,6 +272,12 @@ declare function createOffer(wallet: IWallet, arkServerUrl: string, params: {
241
272
  /** Co-signer key override (33-byte compressed hex); see
242
273
  * {@link resolveEmulatorPubkey}. */
243
274
  emulatorPubkey?: string;
275
+ /** Override the exit closure's delay. Defaults to the server's own
276
+ * `unilateralExitDelay`, which is the delay solverd uses too. */
277
+ exitDelay?: RelativeTimelock;
278
+ /** Publish without the exit closure, leaving `cancel` — which needs the
279
+ * server — as the only way back out. See the note on this function. */
280
+ noExit?: boolean;
244
281
  }): Promise<{
245
282
  /** The encoded offer, hex. **Persist this** — it is the only input
246
283
  * `cancelOffer` needs to rebuild the covenant, and the restore scan reads
@@ -263,19 +300,23 @@ declare function createOffer(wallet: IWallet, arkServerUrl: string, params: {
263
300
  /**
264
301
  * Cancel an offer: spend the swap VTXO back to the user. Returns the ark txid.
265
302
  *
266
- * This is the refund path — how a user takes back a deposit no solver filled.
267
- * **Neither program carries a timelock**, so an unfilled deposit keeps its
268
- * place at the swap address rather than expiring: no deadline to miss and no
269
- * "expired" state to unwind, at the cost of the refund being something the
303
+ * This is the cooperative refund path — how a user takes back a deposit no
304
+ * solver filled. **No path here is on a deadline**, so an unfilled deposit
305
+ * keeps its place at the swap address rather than expiring: nothing to miss and
306
+ * no "expired" state to unwind, at the cost of the refund being something the
270
307
  * user asks for rather than something a clock delivers.
271
308
  *
272
- * Both paths out of the covenant are deliberately asymmetric:
309
+ * The routes out of the covenant are deliberately asymmetric:
273
310
  * - `fulfill` is signed by the **server alone**, but the covenant constrains
274
311
  * it to pay output 0 to `makerWP` for at least `wantAmount` — a solver
275
312
  * cannot take the deposit without delivering.
276
313
  * - `cancel` is a **2-of-2 of the user and the server**, so cancelling is
277
314
  * cooperative: the server co-signs. No solver signature is involved, so the
278
315
  * refund never depends on the counterparty being reachable.
316
+ * - `exit` is the user **alone** after a relative timelock, present unless the
317
+ * offer was created with `noExit`. It is the route that survives a server
318
+ * that will not co-sign this one, and it is reached by unrolling the VTXO
319
+ * onchain rather than through this function.
279
320
  *
280
321
  * Cancel therefore races a fill rather than pre-empting it. An offer the solver
281
322
  * is filling in the same moment may be spent by `fulfill` first, in which case
@@ -451,10 +492,19 @@ type SpendKind = "cancelled" | "fulfilled" | "indeterminate";
451
492
  /**
452
493
  * Classify a spend by the covenant leaf it took.
453
494
  *
454
- * The covenant's whole vocabulary is two leaves: `cancel` returns the deposit
455
- * to the user, `fulfill` is the solver paying for it. A submitted ark tx keeps
456
- * each input's `tapLeafScript`, so the spend *states* which one it used — this
457
- * reads an answer rather than inferring one.
495
+ * The vocabulary is what became of the deposit, not which key moved it:
496
+ * `fulfill` is the solver paying for it, and everything else returns it to the
497
+ * user. A submitted ark tx keeps each input's `tapLeafScript`, so the spend
498
+ * *states* which one it used — this reads an answer rather than inferring one.
499
+ *
500
+ * **`exit` reports `cancelled`, like `cancel` does.** The two differ in who had
501
+ * to agree — `cancel` is cooperative with the signer, `exit` is the maker alone
502
+ * after a delay — but not in outcome: the deposit went back unfilled either
503
+ * way, which is the question this answers. Reporting the exit leaf as
504
+ * `indeterminate` instead would be worse than imprecise: no status is written,
505
+ * so the swap stays `pending`, `restoreAssetSwaps` re-queues it on every scan,
506
+ * and `retireOfferContract` never runs — leaving a dead script in the
507
+ * subscription and the failsafe poll for the life of the wallet.
458
508
  *
459
509
  * **Hand it the transaction that actually spends the deposit outpoint, which is
460
510
  * the checkpoint, not the ark tx.** A spend is two linked transactions: the
@@ -621,6 +671,111 @@ type OfferContractRetirer = Pick<IContractManager, "setContractWatchState">;
621
671
  */
622
672
  declare function retireSettledOfferContracts(manager: OfferContractRetirer, swaps: AssetSwap[]): Promise<void>;
623
673
 
674
+ /** `network` is `requestOnchainSend`'s `l1Network`, and only decodes scripts to
675
+ * addresses — the provider decides which chain is read, so mismatching the two
676
+ * yields addresses it knows nothing about rather than an error. */
677
+ declare const chainSourceFrom: (provider: OnchainProvider, network: OnchainNetwork) => ChainSource;
678
+
679
+ /**
680
+ * Choosing which solver to negotiate with. Both send corridors pick a card the
681
+ * same way and differ only in the payout-side corridor they look for.
682
+ */
683
+
684
+ /** Where to reach a solver. Bounds are indicative — the quote binds.
685
+ *
686
+ * No `emulatorPubkey`: the card's key only FILTERS here — the covenant is
687
+ * built from `deps.emulatorPubkey` or the pinned default, never from it. */
688
+ interface SolverRendezvous {
689
+ solverPubkey: string;
690
+ transports: {
691
+ nostr: {
692
+ relays: string[];
693
+ };
694
+ };
695
+ minSats: number;
696
+ maxSats: number;
697
+ }
698
+ /** The size check is not a courtesy: quoting outside a card's advertised range
699
+ * burns a negotiation, tells a third party what the user is about to do, and
700
+ * is refused anyway. A card that serves the corridor but not the size is
701
+ * skipped, not fatal — another may take it. */
702
+ declare const solverRendezvous: (markets: DiscoveredMarket[], payoutCorridor: "onchain" | "lightning", amountSats: number, fallbackEmulatorPubkey?: Uint8Array) => SolverRendezvous | undefined;
703
+
704
+ /**
705
+ * `solver-onchain` — pay an L1 address out of an Arkade balance through a
706
+ * solver. Registered by the app: the SDK does not depend on this package, and
707
+ * `RouterContext.swaps` is boltz-swap's. Every refusal is `available()`
708
+ * returning false, so the router drops the rail and the collaborative exit
709
+ * `onchain` wins by ranking.
710
+ */
711
+
712
+ declare const SOLVER_ONCHAIN_RAIL = "solver-onchain";
713
+ /** What a record needs. Pass the whole object to `onchainSendProfile()`: only
714
+ * this carries `payoutPkScript`. */
715
+ type SolverOnchainSend = Awaited<ReturnType<typeof requestOnchainSend>> & {
716
+ rendezvous: SolverRendezvous;
717
+ /** Where the claim pays. Named nowhere else — the claim's output is the
718
+ * spender's choice. `onchainSendProfile()` hex-encodes it; a store fed
719
+ * these bytes raw returns an object with no `.length`. */
720
+ payoutPkScript: Uint8Array;
721
+ };
722
+ interface SolverOnchainRailDeps {
723
+ arkServerUrl: string;
724
+ l1Network: OnchainNetwork;
725
+ /** x-only L1 key that AUTHORISES the claim — not where it pays. */
726
+ payoutPubkey: Uint8Array;
727
+ /** Called by `available()` and again by `quote()` — pass the caching
728
+ * `discoverMarkets`, not a bare registry fetch. */
729
+ discover(): Promise<DiscoveredMarket[]>;
730
+ connect<T>(rendezvous: SolverRendezvous, fn: (transport: RfqTransport) => Promise<T>): Promise<T>;
731
+ /** Runs BEFORE funding, and a rejection cancels the send: a funded lockup
732
+ * with no record cannot be refunded. */
733
+ persist(swap: SolverOnchainSend): Promise<void>;
734
+ /** Resolve once the L1 fill is claimed. Optional: without it the handle
735
+ * stops at `"sent"`. `RfqSwapManager` drives the swap either way. */
736
+ awaitSettlement?(swap: SolverOnchainSend): Promise<{
737
+ txid: string;
738
+ }>;
739
+ emulatorPubkey?: string;
740
+ fallbackEmulatorPubkey?: Uint8Array;
741
+ }
742
+ declare const solverOnchainRendezvous: (markets: DiscoveredMarket[], amountSats: number, fallbackEmulatorPubkey?: Uint8Array) => SolverRendezvous | undefined;
743
+ /** Register alongside the core `onchain` rail, ranked first:
744
+ * `priority: ["ark", "solver-onchain", "onchain"]`. Both stay registered. */
745
+ declare function solverOnchainRail(deps: SolverOnchainRailDeps): PaymentRail;
746
+
747
+ /**
748
+ * `solver-lightning` — the sibling of `solver-onchain` on the BOLT11 corridor.
749
+ * Boltz's `lightning` rail matches the same invoices and both stay registered.
750
+ * The invoice fixes the amount, so a `req.amount` that disagrees is refused
751
+ * rather than ignored; `decodeInvoice` is injected because this package
752
+ * carries no bolt11 dependency.
753
+ */
754
+
755
+ declare const SOLVER_LIGHTNING_RAIL = "solver-lightning";
756
+ type SolverLightningSend = Awaited<ReturnType<typeof requestLightningSend>> & {
757
+ invoice: InvoiceFacts;
758
+ rendezvous: SolverRendezvous;
759
+ };
760
+ /** Mirrors {@link SolverOnchainRailDeps}; see there for the shared seams. */
761
+ interface SolverLightningRailDeps {
762
+ arkServerUrl: string;
763
+ /** A decoder that throws drops the rail rather than taking the router
764
+ * down — correct, since an undecodable invoice cannot be paid. */
765
+ decodeInvoice(bolt11: string): InvoiceFacts;
766
+ discover(): Promise<DiscoveredMarket[]>;
767
+ connect<T>(rendezvous: SolverRendezvous, fn: (transport: RfqTransport) => Promise<T>): Promise<T>;
768
+ persist(swap: SolverLightningSend): Promise<void>;
769
+ /** Optional; without it the handle stops at `"sent"`. */
770
+ awaitSettlement?(swap: SolverLightningSend): Promise<{
771
+ preimage?: string;
772
+ }>;
773
+ emulatorPubkey?: string;
774
+ fallbackEmulatorPubkey?: Uint8Array;
775
+ }
776
+ declare const solverLightningRendezvous: (markets: DiscoveredMarket[], amountSats: number, fallbackEmulatorPubkey?: Uint8Array) => SolverRendezvous | undefined;
777
+ declare function solverLightningRail(deps: SolverLightningRailDeps): PaymentRail;
778
+
624
779
  interface SealedClaimPacket {
625
780
  /** `ephPub(33) ‖ nonce(12) ‖ ciphertext`, base64 — wire-ready. This is
626
781
  * the whole packet: the RFQ request's `claim_packet` field carries
@@ -978,4 +1133,4 @@ interface RfqSwapActivityDeps {
978
1133
  */
979
1134
  declare function rfqSwapActivityInputs(deps: RfqSwapActivityDeps): Promise<SwapActivityInput[]>;
980
1135
 
981
- export { ArkadeRefundResult, type ArkadeRefunderDeps, AssetSwap, AssetSwapRepository, type ClaimArkProvider, type ClaimPacketInput, type DiscoverMarketsOptions, IndexedDbAssetSwapRepository, type LightningReceiveProfile, type LightningSendProfile, LockupAmountMismatchError, LockupContractMissing, type LockupContractReader, type LockupContractWriter, LockupRegistrationFailed, LockupSpendIndexer, LockupVtxo, MarketsCacheEntry, OFFER_PACKET_TYPE, type Offer, type OfferContractRetirer, type OfferSwapWatcher, OnchainHtlc, OnchainHtlcParams, OnchainNetwork, type OnchainSendProfile, type PlanError, QUOTE_OPTIONS, RefundArkProvider, type RefundBlockedReason, RefundIndexer, RefundNotLocallyPossibleError, type RestoreIndexer, type RfqClaimSecretProjection, type RfqHashlockProjection, type RfqSignerProjection, RfqSwap, type RfqSwapActivityDeps, RfqSwapRecord, RfqSwapState, SWAP_LOCKUP_CONTRACT_KIND, SWAP_LOCKUP_CONTRACT_LABEL, SWAP_LOCKUP_CONTRACT_TYPE, type SealedClaimPacket, type SpendKind, type SwapActivityInput, SwapSecretsProjection, type Tx, type WatchOfferSwapsParams, arkadeRefunder, awaitLockupFunding, cancelOffer, claimReceiveLockup, classifyDepositSpend, classifySpend, createOffer, decodeOffer, discoverMarkets, encodeOffer, findMarket, lockupContractParams, makeCachedFeedFetch, offerVtxoScript, onchainSendProfile, pushClaim, registerLockupContract, restoreAssetSwaps, retireSettledOfferContracts, rfqClaimSecretOf, rfqSecretsProfile, rfqSignerOf, rfqSwapActivityInputs, sealClaimPacket, senderIdentityForSwapRecord, spendTxidsOf, spendUpdate, swapActivityResolver, swapPrograms, validatePlan, watchOfferSwaps };
1136
+ export { ArkadeRefundResult, type ArkadeRefunderDeps, AssetSwap, AssetSwapRepository, ChainSource, type ClaimArkProvider, type ClaimPacketInput, type DiscoverMarketsOptions, IndexedDbAssetSwapRepository, InvoiceFacts, type LightningReceiveProfile, type LightningSendProfile, LockupAmountMismatchError, LockupContractMissing, type LockupContractReader, type LockupContractWriter, LockupRegistrationFailed, LockupSpendIndexer, LockupVtxo, MarketsCacheEntry, OFFER_PACKET_TYPE, type Offer, type OfferContractRetirer, type OfferSwapWatcher, OnchainHtlc, OnchainHtlcParams, OnchainNetwork, type OnchainSendProfile, type PlanError, QUOTE_OPTIONS, RefundArkProvider, type RefundBlockedReason, RefundIndexer, RefundNotLocallyPossibleError, type RestoreIndexer, type RfqClaimSecretProjection, type RfqHashlockProjection, type RfqSignerProjection, RfqSwap, type RfqSwapActivityDeps, RfqSwapRecord, RfqSwapState, RfqTransport, SOLVER_LIGHTNING_RAIL, SOLVER_ONCHAIN_RAIL, SWAP_LOCKUP_CONTRACT_KIND, SWAP_LOCKUP_CONTRACT_LABEL, SWAP_LOCKUP_CONTRACT_TYPE, type SealedClaimPacket, type SolverLightningRailDeps, type SolverLightningSend, type SolverOnchainRailDeps, type SolverOnchainSend, type SolverRendezvous, type SpendKind, type SwapActivityInput, SwapSecretsProjection, type Tx, type WatchOfferSwapsParams, arkadeRefunder, awaitLockupFunding, cancelOffer, chainSourceFrom, claimReceiveLockup, classifyDepositSpend, classifySpend, createOffer, decodeOffer, discoverMarkets, encodeOffer, findMarket, lockupContractParams, makeCachedFeedFetch, offerVtxoScript, onchainSendProfile, pushClaim, registerLockupContract, requestLightningSend, requestOnchainSend, restoreAssetSwaps, retireSettledOfferContracts, rfqClaimSecretOf, rfqSecretsProfile, rfqSignerOf, rfqSwapActivityInputs, sealClaimPacket, senderIdentityForSwapRecord, solverLightningRail, solverLightningRendezvous, solverOnchainRail, solverOnchainRendezvous, solverRendezvous, spendTxidsOf, spendUpdate, swapActivityResolver, swapPrograms, validatePlan, watchOfferSwaps };
package/dist/index.d.ts CHANGED
@@ -1,9 +1,9 @@
1
- import { ProvisionedKey, ProvisionedClaimSecret, asset, IWallet, arkade, RestIndexerProvider, Transaction, IContractManager, VHTLC, Identity, ActivityResolver } from '@arkade-os/sdk';
2
- import { S as SwapSecretsProjection, R as RfqSwapRecord, A as AssetSwapRepository, a as AssetSwap, M as MarketsCacheEntry, b as RefundArkProvider, c as RefundIndexer, L as LockupVtxo, d as RfqSwap, e as ArkadeRefundResult, f as LockupSpendIndexer, g as RfqSwapState } from './repository-Cw2EvvZG.js';
3
- export { h as AssetSwapStatus, i as AvailableRfqSwapManagerCallbacks, B as BTC_ASSET_ID, I as InMemoryAssetSwapRepository, j as LightningReceiveSwap, k as LightningSendSwap, l as LockupFate, m as LockupNeedsRecoveryError, n as LockupParams, o as LockupSpend, O as OnchainSendAction, p as OnchainSendSwap, P as PersistableRfqSwap, q as PreimageBlockedReason, r as PreimageNotRecoverableError, s as REFUND_MTP_LAG_SECONDS, t as RFQ_RESOLVED_STATES, u as RFQ_SWAP_RETENTION_SECONDS, v as RFQ_SWAP_TERMINAL_STATES, w as RefundOutcome, x as RfqRestoreFailure, y as RfqRestoreOptions, z as RfqRestoreResult, C as RfqSwapActionName, D as RfqSwapLockup, E as RfqSwapManager, F as RfqSwapManagerCallbacks, G as RfqSwapManagerConfig, H as RfqSwapManagerDeps, J as RfqSwapManagerEvents, K as RfqSwapOrigin, N as RfqSwapOriginRequired, Q as RfqSwapOutcome, T as RfqSwapRecordStore, U as SwapContractRegistry, V as addAssetSwap, W as awaitRfqResolution, X as createRfqSwapRecord, Y as findLockupVtxos, Z as getAssetSwaps, _ as getAssetSwapsOrThrow, $ as isRfqSwapTerminal, a0 as isRfqTerminal, a1 as nextOnchainAction, a2 as preimageForSwapRecord, a3 as pushRefundWithoutReceiver, a4 as readLockupFate, a5 as rebuildRfqSwap, a6 as refundIfUnresolved, a7 as rfqSwapOriginOf, a8 as shouldRetainRfqSwap, a9 as swapSecretsToRecord, aa as updateAssetSwap, ab as updateAssetSwapBestEffort, ac as updateRfqSwapRecord } from './repository-Cw2EvvZG.js';
1
+ import { ProvisionedKey, ProvisionedClaimSecret, asset, RelativeTimelock, IWallet, arkade, RestIndexerProvider, Transaction, IContractManager, OnchainProvider, PaymentRail, VHTLC, Identity, ActivityResolver } from '@arkade-os/sdk';
2
+ import { S as SwapSecretsProjection, R as RfqSwapRecord, A as AssetSwapRepository, a as AssetSwap, M as MarketsCacheEntry, b as RefundArkProvider, c as RefundIndexer, L as LockupVtxo, d as RfqSwap, e as ArkadeRefundResult, f as LockupSpendIndexer, g as RfqSwapState } from './repository-DlLvj_y6.js';
3
+ export { h as AssetSwapStatus, i as AvailableRfqSwapManagerCallbacks, B as BTC_ASSET_ID, I as InMemoryAssetSwapRepository, j as LightningReceiveSwap, k as LightningSendSwap, l as LockupFate, m as LockupNeedsRecoveryError, n as LockupParams, o as LockupSpend, O as OnchainSendAction, p as OnchainSendSwap, P as PersistableRfqSwap, q as PreimageBlockedReason, r as PreimageNotRecoverableError, s as REFUND_MTP_LAG_SECONDS, t as RFQ_RESOLVED_STATES, u as RFQ_SWAP_RETENTION_SECONDS, v as RFQ_SWAP_TERMINAL_STATES, w as RefundOutcome, x as RfqRestoreFailure, y as RfqRestoreOptions, z as RfqRestoreResult, C as RfqSwapActionName, D as RfqSwapLockup, E as RfqSwapManager, F as RfqSwapManagerCallbacks, G as RfqSwapManagerConfig, H as RfqSwapManagerDeps, J as RfqSwapManagerEvents, K as RfqSwapOrigin, N as RfqSwapOriginRequired, Q as RfqSwapOutcome, T as RfqSwapRecordStore, U as SwapContractRegistry, V as addAssetSwap, W as awaitRfqResolution, X as createRfqSwapRecord, Y as findLockupVtxos, Z as getAssetSwaps, _ as getAssetSwapsOrThrow, $ as isRfqSwapTerminal, a0 as isRfqTerminal, a1 as nextOnchainAction, a2 as preimageForSwapRecord, a3 as pushRefundWithoutReceiver, a4 as readLockupFate, a5 as rebuildRfqSwap, a6 as refundIfUnresolved, a7 as rfqSwapOriginOf, a8 as shouldRetainRfqSwap, a9 as swapSecretsToRecord, aa as updateAssetSwap, ab as updateAssetSwapBestEffort, ac as updateRfqSwapRecord } from './repository-DlLvj_y6.js';
4
4
  import { Network, LocalCardInput, DiscoveredMarket, Side, OfferPlan } from '@arkade-os/solver-discovery';
5
- import { O as OnchainNetwork, a as OnchainHtlc, b as OnchainHtlcParams } from './rfq-DglvHMNC.js';
6
- export { A as ARKADE_ASSET, c as ARKADE_BTC, d as AddressMismatch, C as ChainSource, e as ChainUtxo, H as HtlcUtxo, I as InvoiceFacts, L as LIGHTNING_BTC, f as LIGHTNING_RECEIVE_PAIR, g as LIGHTNING_SEND_PAIR, h as LOCKTIME_THRESHOLD, i as LightningReceiveTreeParams, j as LightningSendTreeParams, M as MAX_MIN_CONFIRMATIONS, k as MIN_CLAIM_WINDOW_SECONDS, l as MIN_HEADROOM_SECONDS, m as ONCHAIN_BTC, n as ONCHAIN_CLAIM_MARGIN_SECONDS, o as ONCHAIN_DUST_SATS, p as ONCHAIN_ORDER_MARGIN_SECONDS, q as ONCHAIN_RECEIVE_PAIR, r as ONCHAIN_SECONDS_PER_BLOCK, s as ONCHAIN_SEND_PAIR, t as OnchainHtlcPhase, R as RFQ_TERMINAL_STATES, u as RelaySocket, v as RfqQuote, w as RfqRefusalReason, x as RfqStatus, y as RfqTransport, S as SOLO_REFUND_HEADROOM_SECONDS, z as SwapRefusal, B as arkadeAssetLeg, D as arkadeSwapRequest, E as assertFundable, F as assertReceivable, G as awaitOnchainFill, J as buildHtlcClaim, K as buildHtlcRefund, N as claimOnchainFill, P as classifyOnchainHtlc, Q as deriveLightningReceive, T as deriveOnchainReceive, U as deriveOnchainSend, V as extractPreimage, W as httpTransport, X as lightningReceiveRequest, Y as lightningSendRequest, Z as lightningSendVtxoScript, _ as newPreimage, $ as newRfqId, a0 as offerTermsFromQuote, a1 as onchainHtlcScript, a2 as onchainReceiveRequest, a3 as onchainSendRequest, a4 as paymentHashOf, a5 as receiveVtxoScript, a6 as relayTransport, a7 as requestLightningReceive, a8 as requestLightningSend, a9 as requestOnchainReceive, aa as requestOnchainSend, ab as rfqPair, ac as unilateralClaimDelay, ad as unilateralRefundDelay, ae as unilateralRefundWithoutReceiverDelay, af as verifyLockupAddress, ag as verifyReceiveInvoice } from './rfq-DglvHMNC.js';
5
+ import { O as OnchainNetwork, a as OnchainHtlc, b as OnchainHtlcParams, C as ChainSource, R as RfqTransport, r as requestOnchainSend, I as InvoiceFacts, c as requestLightningSend } from './rfq-DzsmhXX3.js';
6
+ export { A as ARKADE_ASSET, d as ARKADE_BTC, e as AddressMismatch, f as ChainUtxo, H as HtlcUtxo, L as LIGHTNING_BTC, g as LIGHTNING_RECEIVE_PAIR, h as LIGHTNING_SEND_PAIR, i as LOCKTIME_THRESHOLD, j as LightningReceiveTreeParams, k as LightningSendTreeParams, M as MAX_MIN_CONFIRMATIONS, l as MIN_CLAIM_WINDOW_SECONDS, m as MIN_HEADROOM_SECONDS, n as ONCHAIN_BTC, o as ONCHAIN_CLAIM_MARGIN_SECONDS, p as ONCHAIN_DUST_SATS, q as ONCHAIN_ORDER_MARGIN_SECONDS, s as ONCHAIN_RECEIVE_PAIR, t as ONCHAIN_SECONDS_PER_BLOCK, u as ONCHAIN_SEND_PAIR, v as OnchainHtlcPhase, w as RFQ_TERMINAL_STATES, x as RelaySocket, y as RfqQuote, z as RfqRefusalReason, B as RfqStatus, S as SOLO_REFUND_HEADROOM_SECONDS, D as SwapRefusal, E as arkadeAssetLeg, F as arkadeSwapRequest, G as assertFundable, J as assertReceivable, K as awaitOnchainFill, N as buildHtlcClaim, P as buildHtlcRefund, Q as claimOnchainFill, T as classifyOnchainHtlc, U as deriveLightningReceive, V as deriveOnchainReceive, W as deriveOnchainSend, X as extractPreimage, Y as httpTransport, Z as l1ScriptForAddress, _ as lightningReceiveRequest, $ as lightningSendRequest, a0 as lightningSendVtxoScript, a1 as newPreimage, a2 as newRfqId, a3 as offerTermsFromQuote, a4 as onchainHtlcScript, a5 as onchainReceiveRequest, a6 as onchainSendRequest, a7 as paymentHashOf, a8 as receiveVtxoScript, a9 as relayTransport, aa as requestLightningReceive, ab as requestOnchainReceive, ac as rfqPair, ad as unilateralClaimDelay, ae as unilateralRefundDelay, af as unilateralRefundWithoutReceiverDelay, ag as verifyLockupAddress, ah as verifyReceiveInvoice } from './rfq-DzsmhXX3.js';
7
7
 
8
8
  /**
9
9
  * Which wallet key signs this leg. Stored at `profile.signer`.
@@ -141,6 +141,9 @@ interface OnchainSendProfile extends Record<string, unknown> {
141
141
  htlcAddress: string;
142
142
  /** `profile.min_confirmations`; gates when the fill is claimable. */
143
143
  minConfirmations: number;
144
+ /** Where the claim PAYS, hex. The spender's own choice, so nothing else
145
+ * gives it back — and `buildHtlcClaim` needs it. */
146
+ payoutPkScript: string;
144
147
  /** The fill's outpoint, learned on first sighting. Without it a SPENT htlc
145
148
  * reads as never funded — see `classifyOnchainHtlc`. */
146
149
  funding?: {
@@ -180,9 +183,21 @@ declare function onchainSendProfile(result: {
180
183
  htlcParams: OnchainHtlcParams;
181
184
  l1Network: OnchainNetwork;
182
185
  minConfirmations: number;
186
+ payoutPkScript: Uint8Array;
183
187
  }): Omit<OnchainSendProfile, "signer" | "hashlock">;
184
188
 
185
- /** The contracts — pure data, shared verbatim with any other implementation. */
189
+ /**
190
+ * The contracts, one per WANT side — pure data, shared verbatim with any other
191
+ * implementation.
192
+ *
193
+ * **These are the base: an offer carrying an exit delay compiles to a third
194
+ * closure that is not in either file.** The tree is not fixed-shape — the
195
+ * protocol defines the exit as `iff ExitDelay`, and solverd appends it the same
196
+ * way (`pkg/swap/contract/offer.go`, `VtxoScript`) — so it cannot be a function
197
+ * in a static artifact without splitting these into one file per exit variant.
198
+ * {@link withExitClosure} owns that step, and the golden in `offer.test.ts`
199
+ * pins the artifact it produces so the whole contract is still readable as data.
200
+ */
186
201
  declare const swapPrograms: Record<"wantAsset" | "wantBtc", ReturnType<typeof arkade.parseArtifact>>;
187
202
  /** A full-fill offer. Exactly one field names an asset: `wantAsset` set = the
188
203
  * fill must deliver that asset (the deposit may be BTC or another asset,
@@ -203,6 +218,14 @@ interface Offer {
203
218
  makerPublicKey: Uint8Array;
204
219
  /** Covenant co-signer (emulator) x-only key (32 bytes). */
205
220
  emulatorPubkey: Uint8Array;
221
+ /** Partial-fill numerator. Reserved wire space in V1: carried through the
222
+ * codec so an offer that sets it decodes, never interpreted here. */
223
+ ratioNum?: bigint;
224
+ /** Partial-fill denominator. Set with {@link Offer.ratioNum} or not at all. */
225
+ ratioDen?: bigint;
226
+ /** The maker's unilateral exit path. Present adds a third closure to the
227
+ * taproot tree, so it changes `swapPkScript` — see {@link offerVtxoScript}. */
228
+ exitDelay?: RelativeTimelock;
206
229
  }
207
230
  /** Compile the offer's contract: program + args -> taproot tree. */
208
231
  declare function offerVtxoScript(offer: Omit<Offer, "swapPkScript">, serverPubkey: Uint8Array): InstanceType<typeof arkade.ArkadeProgramScript>;
@@ -233,6 +256,14 @@ declare function decodeOffer(data: Uint8Array): Offer;
233
256
  * funding rather than after: nothing is at stake yet, so a failure can throw
234
257
  * and be retried, where the same failure after `wallet.send` would leave a
235
258
  * funded deposit unwatched with no way to notice.
259
+ *
260
+ * **The maker's unilateral exit closure is built by default**, at the server's
261
+ * own `unilateralExitDelay` — the same thing solverd does. Without it `cancel`
262
+ * is the only way back out, and `cancel` needs the server's signature: a server
263
+ * that will not co-sign leaves the deposit stuck at the swap address until the
264
+ * VTXO expires and the operator sweeps it. An offer has no expiry of its own,
265
+ * so that exposure has no end. `noExit` opts out for a caller who wants the
266
+ * smaller tree and accepts the dependency.
236
267
  */
237
268
  declare function createOffer(wallet: IWallet, arkServerUrl: string, params: {
238
269
  wantAmount: bigint;
@@ -241,6 +272,12 @@ declare function createOffer(wallet: IWallet, arkServerUrl: string, params: {
241
272
  /** Co-signer key override (33-byte compressed hex); see
242
273
  * {@link resolveEmulatorPubkey}. */
243
274
  emulatorPubkey?: string;
275
+ /** Override the exit closure's delay. Defaults to the server's own
276
+ * `unilateralExitDelay`, which is the delay solverd uses too. */
277
+ exitDelay?: RelativeTimelock;
278
+ /** Publish without the exit closure, leaving `cancel` — which needs the
279
+ * server — as the only way back out. See the note on this function. */
280
+ noExit?: boolean;
244
281
  }): Promise<{
245
282
  /** The encoded offer, hex. **Persist this** — it is the only input
246
283
  * `cancelOffer` needs to rebuild the covenant, and the restore scan reads
@@ -263,19 +300,23 @@ declare function createOffer(wallet: IWallet, arkServerUrl: string, params: {
263
300
  /**
264
301
  * Cancel an offer: spend the swap VTXO back to the user. Returns the ark txid.
265
302
  *
266
- * This is the refund path — how a user takes back a deposit no solver filled.
267
- * **Neither program carries a timelock**, so an unfilled deposit keeps its
268
- * place at the swap address rather than expiring: no deadline to miss and no
269
- * "expired" state to unwind, at the cost of the refund being something the
303
+ * This is the cooperative refund path — how a user takes back a deposit no
304
+ * solver filled. **No path here is on a deadline**, so an unfilled deposit
305
+ * keeps its place at the swap address rather than expiring: nothing to miss and
306
+ * no "expired" state to unwind, at the cost of the refund being something the
270
307
  * user asks for rather than something a clock delivers.
271
308
  *
272
- * Both paths out of the covenant are deliberately asymmetric:
309
+ * The routes out of the covenant are deliberately asymmetric:
273
310
  * - `fulfill` is signed by the **server alone**, but the covenant constrains
274
311
  * it to pay output 0 to `makerWP` for at least `wantAmount` — a solver
275
312
  * cannot take the deposit without delivering.
276
313
  * - `cancel` is a **2-of-2 of the user and the server**, so cancelling is
277
314
  * cooperative: the server co-signs. No solver signature is involved, so the
278
315
  * refund never depends on the counterparty being reachable.
316
+ * - `exit` is the user **alone** after a relative timelock, present unless the
317
+ * offer was created with `noExit`. It is the route that survives a server
318
+ * that will not co-sign this one, and it is reached by unrolling the VTXO
319
+ * onchain rather than through this function.
279
320
  *
280
321
  * Cancel therefore races a fill rather than pre-empting it. An offer the solver
281
322
  * is filling in the same moment may be spent by `fulfill` first, in which case
@@ -451,10 +492,19 @@ type SpendKind = "cancelled" | "fulfilled" | "indeterminate";
451
492
  /**
452
493
  * Classify a spend by the covenant leaf it took.
453
494
  *
454
- * The covenant's whole vocabulary is two leaves: `cancel` returns the deposit
455
- * to the user, `fulfill` is the solver paying for it. A submitted ark tx keeps
456
- * each input's `tapLeafScript`, so the spend *states* which one it used — this
457
- * reads an answer rather than inferring one.
495
+ * The vocabulary is what became of the deposit, not which key moved it:
496
+ * `fulfill` is the solver paying for it, and everything else returns it to the
497
+ * user. A submitted ark tx keeps each input's `tapLeafScript`, so the spend
498
+ * *states* which one it used — this reads an answer rather than inferring one.
499
+ *
500
+ * **`exit` reports `cancelled`, like `cancel` does.** The two differ in who had
501
+ * to agree — `cancel` is cooperative with the signer, `exit` is the maker alone
502
+ * after a delay — but not in outcome: the deposit went back unfilled either
503
+ * way, which is the question this answers. Reporting the exit leaf as
504
+ * `indeterminate` instead would be worse than imprecise: no status is written,
505
+ * so the swap stays `pending`, `restoreAssetSwaps` re-queues it on every scan,
506
+ * and `retireOfferContract` never runs — leaving a dead script in the
507
+ * subscription and the failsafe poll for the life of the wallet.
458
508
  *
459
509
  * **Hand it the transaction that actually spends the deposit outpoint, which is
460
510
  * the checkpoint, not the ark tx.** A spend is two linked transactions: the
@@ -621,6 +671,111 @@ type OfferContractRetirer = Pick<IContractManager, "setContractWatchState">;
621
671
  */
622
672
  declare function retireSettledOfferContracts(manager: OfferContractRetirer, swaps: AssetSwap[]): Promise<void>;
623
673
 
674
+ /** `network` is `requestOnchainSend`'s `l1Network`, and only decodes scripts to
675
+ * addresses — the provider decides which chain is read, so mismatching the two
676
+ * yields addresses it knows nothing about rather than an error. */
677
+ declare const chainSourceFrom: (provider: OnchainProvider, network: OnchainNetwork) => ChainSource;
678
+
679
+ /**
680
+ * Choosing which solver to negotiate with. Both send corridors pick a card the
681
+ * same way and differ only in the payout-side corridor they look for.
682
+ */
683
+
684
+ /** Where to reach a solver. Bounds are indicative — the quote binds.
685
+ *
686
+ * No `emulatorPubkey`: the card's key only FILTERS here — the covenant is
687
+ * built from `deps.emulatorPubkey` or the pinned default, never from it. */
688
+ interface SolverRendezvous {
689
+ solverPubkey: string;
690
+ transports: {
691
+ nostr: {
692
+ relays: string[];
693
+ };
694
+ };
695
+ minSats: number;
696
+ maxSats: number;
697
+ }
698
+ /** The size check is not a courtesy: quoting outside a card's advertised range
699
+ * burns a negotiation, tells a third party what the user is about to do, and
700
+ * is refused anyway. A card that serves the corridor but not the size is
701
+ * skipped, not fatal — another may take it. */
702
+ declare const solverRendezvous: (markets: DiscoveredMarket[], payoutCorridor: "onchain" | "lightning", amountSats: number, fallbackEmulatorPubkey?: Uint8Array) => SolverRendezvous | undefined;
703
+
704
+ /**
705
+ * `solver-onchain` — pay an L1 address out of an Arkade balance through a
706
+ * solver. Registered by the app: the SDK does not depend on this package, and
707
+ * `RouterContext.swaps` is boltz-swap's. Every refusal is `available()`
708
+ * returning false, so the router drops the rail and the collaborative exit
709
+ * `onchain` wins by ranking.
710
+ */
711
+
712
+ declare const SOLVER_ONCHAIN_RAIL = "solver-onchain";
713
+ /** What a record needs. Pass the whole object to `onchainSendProfile()`: only
714
+ * this carries `payoutPkScript`. */
715
+ type SolverOnchainSend = Awaited<ReturnType<typeof requestOnchainSend>> & {
716
+ rendezvous: SolverRendezvous;
717
+ /** Where the claim pays. Named nowhere else — the claim's output is the
718
+ * spender's choice. `onchainSendProfile()` hex-encodes it; a store fed
719
+ * these bytes raw returns an object with no `.length`. */
720
+ payoutPkScript: Uint8Array;
721
+ };
722
+ interface SolverOnchainRailDeps {
723
+ arkServerUrl: string;
724
+ l1Network: OnchainNetwork;
725
+ /** x-only L1 key that AUTHORISES the claim — not where it pays. */
726
+ payoutPubkey: Uint8Array;
727
+ /** Called by `available()` and again by `quote()` — pass the caching
728
+ * `discoverMarkets`, not a bare registry fetch. */
729
+ discover(): Promise<DiscoveredMarket[]>;
730
+ connect<T>(rendezvous: SolverRendezvous, fn: (transport: RfqTransport) => Promise<T>): Promise<T>;
731
+ /** Runs BEFORE funding, and a rejection cancels the send: a funded lockup
732
+ * with no record cannot be refunded. */
733
+ persist(swap: SolverOnchainSend): Promise<void>;
734
+ /** Resolve once the L1 fill is claimed. Optional: without it the handle
735
+ * stops at `"sent"`. `RfqSwapManager` drives the swap either way. */
736
+ awaitSettlement?(swap: SolverOnchainSend): Promise<{
737
+ txid: string;
738
+ }>;
739
+ emulatorPubkey?: string;
740
+ fallbackEmulatorPubkey?: Uint8Array;
741
+ }
742
+ declare const solverOnchainRendezvous: (markets: DiscoveredMarket[], amountSats: number, fallbackEmulatorPubkey?: Uint8Array) => SolverRendezvous | undefined;
743
+ /** Register alongside the core `onchain` rail, ranked first:
744
+ * `priority: ["ark", "solver-onchain", "onchain"]`. Both stay registered. */
745
+ declare function solverOnchainRail(deps: SolverOnchainRailDeps): PaymentRail;
746
+
747
+ /**
748
+ * `solver-lightning` — the sibling of `solver-onchain` on the BOLT11 corridor.
749
+ * Boltz's `lightning` rail matches the same invoices and both stay registered.
750
+ * The invoice fixes the amount, so a `req.amount` that disagrees is refused
751
+ * rather than ignored; `decodeInvoice` is injected because this package
752
+ * carries no bolt11 dependency.
753
+ */
754
+
755
+ declare const SOLVER_LIGHTNING_RAIL = "solver-lightning";
756
+ type SolverLightningSend = Awaited<ReturnType<typeof requestLightningSend>> & {
757
+ invoice: InvoiceFacts;
758
+ rendezvous: SolverRendezvous;
759
+ };
760
+ /** Mirrors {@link SolverOnchainRailDeps}; see there for the shared seams. */
761
+ interface SolverLightningRailDeps {
762
+ arkServerUrl: string;
763
+ /** A decoder that throws drops the rail rather than taking the router
764
+ * down — correct, since an undecodable invoice cannot be paid. */
765
+ decodeInvoice(bolt11: string): InvoiceFacts;
766
+ discover(): Promise<DiscoveredMarket[]>;
767
+ connect<T>(rendezvous: SolverRendezvous, fn: (transport: RfqTransport) => Promise<T>): Promise<T>;
768
+ persist(swap: SolverLightningSend): Promise<void>;
769
+ /** Optional; without it the handle stops at `"sent"`. */
770
+ awaitSettlement?(swap: SolverLightningSend): Promise<{
771
+ preimage?: string;
772
+ }>;
773
+ emulatorPubkey?: string;
774
+ fallbackEmulatorPubkey?: Uint8Array;
775
+ }
776
+ declare const solverLightningRendezvous: (markets: DiscoveredMarket[], amountSats: number, fallbackEmulatorPubkey?: Uint8Array) => SolverRendezvous | undefined;
777
+ declare function solverLightningRail(deps: SolverLightningRailDeps): PaymentRail;
778
+
624
779
  interface SealedClaimPacket {
625
780
  /** `ephPub(33) ‖ nonce(12) ‖ ciphertext`, base64 — wire-ready. This is
626
781
  * the whole packet: the RFQ request's `claim_packet` field carries
@@ -978,4 +1133,4 @@ interface RfqSwapActivityDeps {
978
1133
  */
979
1134
  declare function rfqSwapActivityInputs(deps: RfqSwapActivityDeps): Promise<SwapActivityInput[]>;
980
1135
 
981
- export { ArkadeRefundResult, type ArkadeRefunderDeps, AssetSwap, AssetSwapRepository, type ClaimArkProvider, type ClaimPacketInput, type DiscoverMarketsOptions, IndexedDbAssetSwapRepository, type LightningReceiveProfile, type LightningSendProfile, LockupAmountMismatchError, LockupContractMissing, type LockupContractReader, type LockupContractWriter, LockupRegistrationFailed, LockupSpendIndexer, LockupVtxo, MarketsCacheEntry, OFFER_PACKET_TYPE, type Offer, type OfferContractRetirer, type OfferSwapWatcher, OnchainHtlc, OnchainHtlcParams, OnchainNetwork, type OnchainSendProfile, type PlanError, QUOTE_OPTIONS, RefundArkProvider, type RefundBlockedReason, RefundIndexer, RefundNotLocallyPossibleError, type RestoreIndexer, type RfqClaimSecretProjection, type RfqHashlockProjection, type RfqSignerProjection, RfqSwap, type RfqSwapActivityDeps, RfqSwapRecord, RfqSwapState, SWAP_LOCKUP_CONTRACT_KIND, SWAP_LOCKUP_CONTRACT_LABEL, SWAP_LOCKUP_CONTRACT_TYPE, type SealedClaimPacket, type SpendKind, type SwapActivityInput, SwapSecretsProjection, type Tx, type WatchOfferSwapsParams, arkadeRefunder, awaitLockupFunding, cancelOffer, claimReceiveLockup, classifyDepositSpend, classifySpend, createOffer, decodeOffer, discoverMarkets, encodeOffer, findMarket, lockupContractParams, makeCachedFeedFetch, offerVtxoScript, onchainSendProfile, pushClaim, registerLockupContract, restoreAssetSwaps, retireSettledOfferContracts, rfqClaimSecretOf, rfqSecretsProfile, rfqSignerOf, rfqSwapActivityInputs, sealClaimPacket, senderIdentityForSwapRecord, spendTxidsOf, spendUpdate, swapActivityResolver, swapPrograms, validatePlan, watchOfferSwaps };
1136
+ export { ArkadeRefundResult, type ArkadeRefunderDeps, AssetSwap, AssetSwapRepository, ChainSource, type ClaimArkProvider, type ClaimPacketInput, type DiscoverMarketsOptions, IndexedDbAssetSwapRepository, InvoiceFacts, type LightningReceiveProfile, type LightningSendProfile, LockupAmountMismatchError, LockupContractMissing, type LockupContractReader, type LockupContractWriter, LockupRegistrationFailed, LockupSpendIndexer, LockupVtxo, MarketsCacheEntry, OFFER_PACKET_TYPE, type Offer, type OfferContractRetirer, type OfferSwapWatcher, OnchainHtlc, OnchainHtlcParams, OnchainNetwork, type OnchainSendProfile, type PlanError, QUOTE_OPTIONS, RefundArkProvider, type RefundBlockedReason, RefundIndexer, RefundNotLocallyPossibleError, type RestoreIndexer, type RfqClaimSecretProjection, type RfqHashlockProjection, type RfqSignerProjection, RfqSwap, type RfqSwapActivityDeps, RfqSwapRecord, RfqSwapState, RfqTransport, SOLVER_LIGHTNING_RAIL, SOLVER_ONCHAIN_RAIL, SWAP_LOCKUP_CONTRACT_KIND, SWAP_LOCKUP_CONTRACT_LABEL, SWAP_LOCKUP_CONTRACT_TYPE, type SealedClaimPacket, type SolverLightningRailDeps, type SolverLightningSend, type SolverOnchainRailDeps, type SolverOnchainSend, type SolverRendezvous, type SpendKind, type SwapActivityInput, SwapSecretsProjection, type Tx, type WatchOfferSwapsParams, arkadeRefunder, awaitLockupFunding, cancelOffer, chainSourceFrom, claimReceiveLockup, classifyDepositSpend, classifySpend, createOffer, decodeOffer, discoverMarkets, encodeOffer, findMarket, lockupContractParams, makeCachedFeedFetch, offerVtxoScript, onchainSendProfile, pushClaim, registerLockupContract, requestLightningSend, requestOnchainSend, restoreAssetSwaps, retireSettledOfferContracts, rfqClaimSecretOf, rfqSecretsProfile, rfqSignerOf, rfqSwapActivityInputs, sealClaimPacket, senderIdentityForSwapRecord, solverLightningRail, solverLightningRendezvous, solverOnchainRail, solverOnchainRendezvous, solverRendezvous, spendTxidsOf, spendUpdate, swapActivityResolver, swapPrograms, validatePlan, watchOfferSwaps };