@arkade-os/swap 0.0.10 → 0.1.0-rc.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
@@ -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, 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 RefundIndexer, L as LockupVtxo, c as SwapOperator, d as RfqSwap, e as ArkadeRefundResult, f as LockupSpendIndexer, g as RfqSwapState, h as RfqSwapManager, i as RfqSwapManagerCallbacks } from './repository-BWP1UstE.cjs';
3
+ export { j as AssetSwapStatus, k as AvailableRfqSwapManagerCallbacks, B as BTC_ASSET_ID, I as InMemoryAssetSwapRepository, l as LightningReceiveSwap, m as LightningSendSwap, n as LockupFate, o as LockupNeedsRecoveryError, p as LockupParams, q as LockupSpend, O as OnchainSendAction, r as OnchainSendSwap, P as PersistableRfqSwap, s as PreimageBlockedReason, t as PreimageNotRecoverableError, u as REFUND_MTP_LAG_SECONDS, v as RFQ_RESOLVED_STATES, w as RFQ_SWAP_RETENTION_SECONDS, x as RFQ_SWAP_TERMINAL_STATES, y as RefundOutcome, z as RfqRestoreFailure, C as RfqRestoreOptions, D as RfqRestoreResult, E as RfqSwapActionName, F as RfqSwapLockup, 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 normalizeRfqSwapRecord, a3 as preimageForSwapRecord, a4 as pushRefundWithoutReceiver, a5 as readLockupFate, a6 as rebuildRfqSwap, a7 as refundIfUnresolved, a8 as rfqSwapOriginOf, a9 as shouldRetainRfqSwap, aa as swapSecretsToRecord, ab as updateAssetSwap, ac as updateAssetSwapBestEffort, ad as updateRfqSwapRecord } from './repository-BWP1UstE.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, r as requestLightningReceive, c as requestLightningSend, d as requestOnchainSend, I as InvoiceFacts, R as RfqTransport, C as ChainSource } from './rfq-CzCGjICq.cjs';
6
+ export { A as ARKADE_ASSET, e as ARKADE_BTC, f as AddressMismatch, g as ChainUtxo, H as HtlcUtxo, L as LIGHTNING_BTC, h as LIGHTNING_RECEIVE_PAIR, i as LIGHTNING_SEND_PAIR, j as LOCKTIME_THRESHOLD, k as LightningReceiveContractParams, l as LightningSendContractParams, M as MAX_MIN_CONFIRMATIONS, m as MIN_CLAIM_WINDOW_SECONDS, n as MIN_HEADROOM_SECONDS, o as ONCHAIN_BTC, p as ONCHAIN_CLAIM_MARGIN_SECONDS, q as ONCHAIN_DUST_SATS, s as ONCHAIN_ORDER_MARGIN_SECONDS, t as ONCHAIN_RECEIVE_PAIR, u as ONCHAIN_SECONDS_PER_BLOCK, v as ONCHAIN_SEND_PAIR, w as OnchainHtlcPhase, x as RFQ_TERMINAL_STATES, y as RelaySocket, z as RfqQuote, B as RfqRefusalReason, D as RfqStatus, S as SOLO_REFUND_HEADROOM_SECONDS, E as SwapRefusal, F as arkadeAssetLeg, G as arkadeSwapRequest, J as assertFundable, K as assertReceivable, N as awaitOnchainFill, P as buildHtlcClaim, Q as buildHtlcRefund, T as claimOnchainFill, U as classifyOnchainHtlc, V as deriveLightningReceive, W as deriveOnchainReceive, X as deriveOnchainSend, Y as extractPreimage, Z as httpTransport, _ as lightningReceiveContract, $ as lightningReceiveRequest, a0 as lightningSendContract, a1 as lightningSendRequest, a2 as newPreimage, a3 as newRfqId, a4 as offerTermsFromQuote, a5 as onchainHtlcScript, a6 as onchainReceiveRequest, a7 as onchainSendRequest, a8 as paymentHashOf, a9 as relayTransport, aa as requestOnchainReceive, ab as rfqPair, ac as unilateralClaimDelay, ad as unilateralRefundDelay, ae as unilateralRefundWithoutReceiverDelay, af as verifyLockupAddress, ag as verifyReceiveInvoice } from './rfq-CzCGjICq.cjs';
7
7
 
8
8
  /**
9
9
  * Which wallet key signs this leg. Stored at `profile.signer`.
@@ -111,7 +111,7 @@ interface LightningReceiveProfile extends Record<string, unknown> {
111
111
  * preimage that is already public, and a swap that did claim is relabelled
112
112
  * `needs_counterparty` once its window shuts.
113
113
  */
114
- claimArkTxid?: string;
114
+ claimTxid?: string;
115
115
  }
116
116
  /** `arkade:BTC->onchain:BTC`. */
117
117
  interface OnchainSendProfile extends Record<string, unknown> {
@@ -182,7 +182,18 @@ declare function onchainSendProfile(result: {
182
182
  minConfirmations: number;
183
183
  }): Omit<OnchainSendProfile, "signer" | "hashlock">;
184
184
 
185
- /** The contracts — pure data, shared verbatim with any other implementation. */
185
+ /**
186
+ * The contracts, one per WANT side — pure data, shared verbatim with any other
187
+ * implementation.
188
+ *
189
+ * **These are the base: an offer carrying an exit delay compiles to a third
190
+ * closure that is not in either file.** The tree is not fixed-shape — the
191
+ * protocol defines the exit as `iff ExitDelay`, and solverd appends it the same
192
+ * way (`pkg/swap/contract/offer.go`, `VtxoScript`) — so it cannot be a function
193
+ * in a static artifact without splitting these into one file per exit variant.
194
+ * {@link withExitClosure} owns that step, and the golden in `offer.test.ts`
195
+ * pins the artifact it produces so the whole contract is still readable as data.
196
+ */
186
197
  declare const swapPrograms: Record<"wantAsset" | "wantBtc", ReturnType<typeof arkade.parseArtifact>>;
187
198
  /** A full-fill offer. Exactly one field names an asset: `wantAsset` set = the
188
199
  * fill must deliver that asset (the deposit may be BTC or another asset,
@@ -203,9 +214,17 @@ interface Offer {
203
214
  makerPublicKey: Uint8Array;
204
215
  /** Covenant co-signer (emulator) x-only key (32 bytes). */
205
216
  emulatorPubkey: Uint8Array;
217
+ /** Partial-fill numerator. Reserved wire space in V1: carried through the
218
+ * codec so an offer that sets it decodes, never interpreted here. */
219
+ ratioNum?: bigint;
220
+ /** Partial-fill denominator. Set with {@link Offer.ratioNum} or not at all. */
221
+ ratioDen?: bigint;
222
+ /** The maker's unilateral exit path. Present adds a third closure to the
223
+ * taproot tree, so it changes `swapPkScript` — see {@link offerVtxoScript}. */
224
+ exitDelay?: RelativeTimelock;
206
225
  }
207
226
  /** Compile the offer's contract: program + args -> taproot tree. */
208
- declare function offerVtxoScript(offer: Omit<Offer, "swapPkScript">, serverPubkey: Uint8Array): InstanceType<typeof arkade.ArkadeProgramScript>;
227
+ declare function offerContract(offer: Omit<Offer, "swapPkScript">, operatorPubkey: Uint8Array): InstanceType<typeof arkade.ArkadeProgramScript>;
209
228
  /** Extension packet type tag for Arkade Intents offers. */
210
229
  declare const OFFER_PACKET_TYPE = 3;
211
230
  /** Serialize an offer to TLV bytes (the packet payload). */
@@ -217,11 +236,11 @@ declare function decodeOffer(data: Uint8Array): Offer;
217
236
  * you deposit, embedding the returned extension, and the solver does the rest:
218
237
  *
219
238
  * // BTC -> asset
220
- * const o = await createOffer(wallet, ARK, { wantAmount: 1000n, wantAsset })
239
+ * const o = await createOffer(wallet, { wantAmount: 1000n, wantAsset })
221
240
  * await wallet.send({ address: o.address, amount: 1000, extensions: [o.extension] })
222
241
  *
223
242
  * // asset -> BTC (the sats are the VTXO carrier for the asset)
224
- * const o = await createOffer(wallet, ARK, { wantAmount: 1000n, offerAsset })
243
+ * const o = await createOffer(wallet, { wantAmount: 1000n, offerAsset })
225
244
  * await wallet.send({ address: o.address, amount: 500,
226
245
  * assets: [{ assetId, amount: 1000n }],
227
246
  * extensions: [o.extension] })
@@ -233,14 +252,28 @@ declare function decodeOffer(data: Uint8Array): Offer;
233
252
  * funding rather than after: nothing is at stake yet, so a failure can throw
234
253
  * and be retried, where the same failure after `wallet.send` would leave a
235
254
  * funded deposit unwatched with no way to notice.
255
+ *
256
+ * **The maker's unilateral exit closure is built by default**, at the server's
257
+ * own `unilateralExitDelay` — the same thing solverd does. Without it `cancel`
258
+ * is the only way back out, and `cancel` needs the server's signature: a server
259
+ * that will not co-sign leaves the deposit stuck at the swap address until the
260
+ * VTXO expires and the operator sweeps it. An offer has no expiry of its own,
261
+ * so that exposure has no end. `noExit` opts out for a caller who wants the
262
+ * smaller tree and accepts the dependency.
236
263
  */
237
- declare function createOffer(wallet: IWallet, arkServerUrl: string, params: {
264
+ declare function createOffer(wallet: IWallet, params: {
238
265
  wantAmount: bigint;
239
266
  wantAsset?: asset.AssetId;
240
267
  offerAsset?: asset.AssetId;
241
268
  /** Co-signer key override (33-byte compressed hex); see
242
269
  * {@link resolveEmulatorPubkey}. */
243
270
  emulatorPubkey?: string;
271
+ /** Override the exit closure's delay. Defaults to the server's own
272
+ * `unilateralExitDelay`, which is the delay solverd uses too. */
273
+ exitDelay?: RelativeTimelock;
274
+ /** Publish without the exit closure, leaving `cancel` — which needs the
275
+ * server — as the only way back out. See the note on this function. */
276
+ noExit?: boolean;
244
277
  }): Promise<{
245
278
  /** The encoded offer, hex. **Persist this** — it is the only input
246
279
  * `cancelOffer` needs to rebuild the covenant, and the restore scan reads
@@ -263,19 +296,23 @@ declare function createOffer(wallet: IWallet, arkServerUrl: string, params: {
263
296
  /**
264
297
  * Cancel an offer: spend the swap VTXO back to the user. Returns the ark txid.
265
298
  *
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
299
+ * This is the cooperative refund path — how a user takes back a deposit no
300
+ * solver filled. **No path here is on a deadline**, so an unfilled deposit
301
+ * keeps its place at the swap address rather than expiring: nothing to miss and
302
+ * no "expired" state to unwind, at the cost of the refund being something the
270
303
  * user asks for rather than something a clock delivers.
271
304
  *
272
- * Both paths out of the covenant are deliberately asymmetric:
305
+ * The routes out of the covenant are deliberately asymmetric:
273
306
  * - `fulfill` is signed by the **server alone**, but the covenant constrains
274
307
  * it to pay output 0 to `makerWP` for at least `wantAmount` — a solver
275
308
  * cannot take the deposit without delivering.
276
309
  * - `cancel` is a **2-of-2 of the user and the server**, so cancelling is
277
310
  * cooperative: the server co-signs. No solver signature is involved, so the
278
311
  * refund never depends on the counterparty being reachable.
312
+ * - `exit` is the user **alone** after a relative timelock, present unless the
313
+ * offer was created with `noExit`. It is the route that survives a server
314
+ * that will not co-sign this one, and it is reached by unrolling the VTXO
315
+ * onchain rather than through this function.
279
316
  *
280
317
  * Cancel therefore races a fill rather than pre-empting it. An offer the solver
281
318
  * is filling in the same moment may be spent by `fulfill` first, in which case
@@ -291,8 +328,8 @@ declare function createOffer(wallet: IWallet, arkServerUrl: string, params: {
291
328
  * Identical offers derive the same address, so `fundingTxid` selects the exact
292
329
  * deposit; without it the address must hold exactly one spendable VTXO — with
293
330
  * several, cancel refuses to guess and throws.
294
- * `swapAddress` (the funded address) pins the server key the covenant was
295
- * built with, so cancel keeps working across a server signer rotation; without
331
+ * `swapAddress` (the funded address) pins the operator key the covenant was
332
+ * built with, so cancel keeps working across an operator signer rotation; without
296
333
  * it a rotated key is detected and reported rather than reading as a missing
297
334
  * VTXO.
298
335
  *
@@ -313,8 +350,13 @@ declare function createOffer(wallet: IWallet, arkServerUrl: string, params: {
313
350
  * returns, so a spend event that arrives in that window finds a `cancelling`
314
351
  * record and classifies the spend by its covenant leaf instead — the same
315
352
  * answer, one indexer read more.
353
+ *
354
+ * Takes no server URL, like every other entrypoint here: broadcast comes from
355
+ * `wallet.getArkadeBroadcaster()` and the indexer fallback from
356
+ * `wallet.getArkadeReader()`, so the wallet's own connection is the only one
357
+ * used (#734).
316
358
  */
317
- declare function cancelOffer(wallet: IWallet, arkServerUrl: string, offerHex: string, opts: {
359
+ declare function cancelOffer(wallet: IWallet, offerHex: string, opts: {
318
360
  repository: AssetSwapRepository;
319
361
  fundingTxid?: string;
320
362
  swapAddress?: string;
@@ -393,8 +435,7 @@ type PlanError = "insufficient-balance" | "side-disabled" | "below-min" | "above
393
435
  /** Validate a plan against the user's balance and the server dust limit. */
394
436
  declare const validatePlan: (plan: OfferPlan, giveBalance: bigint, dust: bigint) => PlanError | undefined;
395
437
 
396
- /** Browser backend over the SDK's shared IndexedDB manager — the same
397
- * infrastructure the wallet already uses for its Boltz swap repository. */
438
+ /** Browser backend over the SDK's shared IndexedDB manager. */
398
439
  declare class IndexedDbAssetSwapRepository implements AssetSwapRepository {
399
440
  readonly version: 4;
400
441
  private readonly connection;
@@ -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
@@ -474,12 +524,12 @@ type SpendKind = "cancelled" | "fulfilled" | "indeterminate";
474
524
  * and they also survive batching: a solver filling several offers in one tx
475
525
  * gives each input its own leaf.
476
526
  *
477
- * `serverPubkey` must be the key the covenant was *funded* against. If it has
527
+ * `operatorPubkey` must be the key the covenant was *funded* against. If it has
478
528
  * rotated since, the rebuilt script will not match the offer's own
479
529
  * `swapPkScript` and this returns `indeterminate` rather than guessing —
480
530
  * `cancelOffer` diagnoses the same mismatch the same way.
481
531
  */
482
- declare function classifySpend(offer: Offer, serverPubkey: Uint8Array, spendTx: Transaction, deposit: {
532
+ declare function classifySpend(offer: Offer, operatorPubkey: Uint8Array, spendTx: Transaction, deposit: {
483
533
  txid: string;
484
534
  vout: number;
485
535
  }): SpendKind;
@@ -500,7 +550,7 @@ declare const spendTxidsOf: (vtxo: {
500
550
  * settlement they may be the same id. Try each and take the first definite
501
551
  * answer, so the classification does not depend on that distinction.
502
552
  */
503
- declare function classifyDepositSpend(offer: Offer, serverPubkey: Uint8Array, spendTxs: Iterable<Transaction>, deposit: {
553
+ declare function classifyDepositSpend(offer: Offer, operatorPubkey: Uint8Array, spendTxs: Iterable<Transaction>, deposit: {
504
554
  txid: string;
505
555
  vout: number;
506
556
  }): SpendKind;
@@ -525,12 +575,12 @@ declare function classifyDepositSpend(offer: Offer, serverPubkey: Uint8Array, sp
525
575
  * does, so the `existingIds` escape hatch is no longer a correction mechanism
526
576
  * for a wrong label — it is only a skip list.
527
577
  *
528
- * `serverPubkey` must be the server key the covenants were funded against; a
578
+ * `operatorPubkey` must be the operator key the covenants were funded against; a
529
579
  * key that has rotated since makes every affected swap unclassifiable rather
530
580
  * than misclassified.
531
581
  */
532
582
  declare function restoreAssetSwaps(indexer: RestoreIndexer, txs: Tx[], existingIds: ReadonlySet<string>, opts: {
533
- serverPubkey: Uint8Array;
583
+ operatorPubkey: Uint8Array;
534
584
  scanned?: ReadonlySet<string>;
535
585
  }): Promise<{
536
586
  restored: AssetSwap[];
@@ -558,9 +608,6 @@ interface OfferSwapWatcher {
558
608
  }
559
609
  interface WatchOfferSwapsParams {
560
610
  wallet: IWallet;
561
- /** Same URL `createOffer`/`cancelOffer` take; used to read a spending tx
562
- * when the exact classifier cannot answer. */
563
- arkServerUrl: string;
564
611
  repository: AssetSwapRepository;
565
612
  /** Called after a change is persisted. A notification, not a store. */
566
613
  onUpdate?: (swap: AssetSwap) => void;
@@ -576,7 +623,7 @@ interface WatchOfferSwapsParams {
576
623
  * provide an `EventSource` implementation or use a runtime where it is enabled;
577
624
  * otherwise live updates do not arrive and restore remains the fallback.
578
625
  */
579
- declare function watchOfferSwaps({ wallet, arkServerUrl, repository, onUpdate, }: WatchOfferSwapsParams): Promise<OfferSwapWatcher>;
626
+ declare function watchOfferSwaps({ wallet, repository, onUpdate, }: WatchOfferSwapsParams): Promise<OfferSwapWatcher>;
580
627
 
581
628
  /**
582
629
  * Coverage: whether an offer's script is in the wallet's watched set.
@@ -644,8 +691,6 @@ interface ClaimPacketInput {
644
691
  */
645
692
  declare function sealClaimPacket(input: ClaimPacketInput): Promise<SealedClaimPacket>;
646
693
 
647
- /** The Ark surface the claim push needs — the same seam the refund push uses. */
648
- type ClaimArkProvider = RefundArkProvider;
649
694
  /**
650
695
  * The lockup is funded for less than the swap agreed.
651
696
  *
@@ -688,9 +733,9 @@ declare class LockupAmountMismatchError extends Error {
688
733
  * server at submit — but it turns "reported claimed, nothing landed, the
689
734
  * solver refunds hours later" into an immediate failure.
690
735
  */
691
- declare function pushClaim(ark: ClaimArkProvider, input: {
692
- /** The receive-direction covenant (see `receiveVtxoScript`). */
693
- script: InstanceType<typeof VHTLC.ScriptV2>;
736
+ declare function pushClaim(operator: SwapOperator, input: {
737
+ /** The receive-direction covenant (see `lightningReceiveContract`). */
738
+ contract: InstanceType<typeof VHTLC.ScriptV2>;
694
739
  /** The trader's `receiver` signer. Build it from the swap's `secrets`
695
740
  * with `contractSigner` — on an HD wallet that resolves
696
741
  * from the seed, with no stored key bytes anywhere. */
@@ -710,7 +755,7 @@ declare function pushClaim(ark: ClaimArkProvider, input: {
710
755
  * the remainder. */
711
756
  partiallyClaimed?: boolean;
712
757
  }): Promise<{
713
- arkTxid: string;
758
+ txid: string;
714
759
  amount: number;
715
760
  }>;
716
761
  /**
@@ -737,13 +782,13 @@ declare function awaitLockupFunding(indexer: RefundIndexer, swapPkScript: Uint8A
737
782
  * rest lands is safe — and that is also the answer to a genuinely underfunded
738
783
  * lockup, which never gets past the gate at all.
739
784
  */
740
- declare function claimReceiveLockup(indexer: RefundIndexer, ark: ClaimArkProvider, input: Parameters<typeof pushClaim>[1] & {
785
+ declare function claimReceiveLockup(indexer: RefundIndexer, operator: SwapOperator, input: Parameters<typeof pushClaim>[1] & {
741
786
  /** The covenant's scriptPubKey, from the request flow's `swapPkScript`. */
742
787
  swapPkScript: Uint8Array;
743
788
  pollMs?: number;
744
789
  deadline?: number;
745
790
  }): Promise<{
746
- arkTxid: string;
791
+ txid: string;
747
792
  amount: number;
748
793
  }>;
749
794
 
@@ -810,7 +855,7 @@ declare function senderIdentityForSwapRecord(wallet: IWallet, record: {
810
855
  */
811
856
 
812
857
  interface ArkadeRefunderDeps {
813
- ark: RefundArkProvider;
858
+ operator: SwapOperator;
814
859
  indexer: RefundIndexer;
815
860
  /** Asked for the descriptor's signer; never asked to mint a key. */
816
861
  wallet: IWallet;
@@ -826,7 +871,7 @@ interface ArkadeRefunderDeps {
826
871
  *
827
872
  * @example
828
873
  * manager.setCallbacks({
829
- * refundArkade: arkadeRefunder({ ark, indexer, wallet, repository }),
874
+ * refundArkade: arkadeRefunder({ operator, indexer, wallet, repository }),
830
875
  * saveSwap,
831
876
  * });
832
877
  */
@@ -954,7 +999,7 @@ interface RfqSwapActivityDeps {
954
999
  repository: Pick<AssetSwapRepository, "getAllRfqSwaps">;
955
1000
  /**
956
1001
  * Consulted only for what a record cannot answer: a record written before
957
- * `fundingArkTxid` existed, and the counterparty's spend on a swap that
1002
+ * `fundingTxid` existed, and the counterparty's spend on a swap that
958
1003
  * ended without a refund of ours.
959
1004
  *
960
1005
  * Optional because the stored fields are the primary source — cheaper, and
@@ -968,7 +1013,7 @@ interface RfqSwapActivityDeps {
968
1013
  * groups on.
969
1014
  *
970
1015
  * The txids come from four places, in order of preference: the record's own
971
- * `fundingArkTxid` and `refundArkTxid`, the corridor's `activityTxids` (the
1016
+ * `fundingTxid` and `refundTxid`, the corridor's `activityTxids` (the
972
1017
  * receive leg's Arkade claim, the onchain leg's L1 one), and — only when the
973
1018
  * first two cannot answer — one read of the lockup's VTXOs.
974
1019
  *
@@ -978,4 +1023,96 @@ interface RfqSwapActivityDeps {
978
1023
  */
979
1024
  declare function rfqSwapActivityInputs(deps: RfqSwapActivityDeps): Promise<SwapActivityInput[]>;
980
1025
 
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 };
1026
+ interface SwapQuoteInput {
1027
+ /** Which side of the market the trader deposits. */
1028
+ give: "base" | "quote";
1029
+ /** Size on the named side ("give" = exact-in, "receive" = exact-out).
1030
+ * Spot: display string or atomic bigint; corridors: sats. A lightning
1031
+ * send takes its amount from the invoice instead. */
1032
+ amount?: string | number | bigint;
1033
+ amountOn?: "give" | "receive";
1034
+ /** Required when the receive side is lightning. */
1035
+ invoice?: InvoiceFacts;
1036
+ /** Trader's x-only L1 claim key; required when the receive side is onchain. */
1037
+ payoutPubkey?: Uint8Array;
1038
+ preimage?: Uint8Array;
1039
+ maxPayAmount?: number;
1040
+ }
1041
+ interface SpotQuote {
1042
+ kind: "spot";
1043
+ market: DiscoveredMarket;
1044
+ plan: OfferPlan;
1045
+ }
1046
+ interface LightningSendQuote {
1047
+ kind: "ln_send";
1048
+ market: DiscoveredMarket;
1049
+ request: Awaited<ReturnType<typeof requestLightningSend>>;
1050
+ }
1051
+ interface LightningReceiveQuote {
1052
+ kind: "ln_receive";
1053
+ market: DiscoveredMarket;
1054
+ request: Awaited<ReturnType<typeof requestLightningReceive>>;
1055
+ /** The solver's hold invoice, for the payer. */
1056
+ invoice: string;
1057
+ }
1058
+ interface OnchainSendQuote {
1059
+ kind: "onchain_send";
1060
+ market: DiscoveredMarket;
1061
+ request: Awaited<ReturnType<typeof requestOnchainSend>>;
1062
+ }
1063
+ type SwapQuote = SpotQuote | LightningSendQuote | LightningReceiveQuote | OnchainSendQuote;
1064
+ type UnifiedSwap = {
1065
+ family: "offer";
1066
+ swap: AssetSwap;
1067
+ } | {
1068
+ family: "rfq";
1069
+ swap: RfqSwap;
1070
+ };
1071
+ interface SwapClientDeps {
1072
+ /** The server connection too: every provider below defaults to this
1073
+ * wallet's own, so no server URL is passed in (arkade-os/ts-sdk#734). */
1074
+ wallet: IWallet;
1075
+ repository: AssetSwapRepository;
1076
+ /** The rendezvous for a corridor market; never called for a spot one.
1077
+ *
1078
+ * The market's own `base_corridor`/`quote_corridor` are what route a swap
1079
+ * here rather than to the offer path, so whoever publishes the market
1080
+ * chooses which backend you are asked to open a transport to. Resolve one
1081
+ * only for markets from an index you trust — this client does not, and
1082
+ * cannot, check that a market named a corridor honestly. */
1083
+ transportFor: (market: DiscoveredMarket) => RfqTransport;
1084
+ discovery: Omit<DiscoverMarketsOptions, "repository">;
1085
+ /** BOLT11 decoder for the solver's hold invoice; required to quote lightning receives. */
1086
+ decodeInvoice?: (bolt11: string) => InvoiceFacts;
1087
+ /** covclaimd's 33-byte compressed pubkey — the lightning-receive claim
1088
+ * packet seals to it; required to quote lightning receives. */
1089
+ covclaimdPubkey?: Uint8Array;
1090
+ /** L1 access; required to quote onchain sends. */
1091
+ chain?: ChainSource;
1092
+ /** L1 claim callback (fee rate and signing are environment-specific);
1093
+ * without it the manager reports onchain claims as blocked. */
1094
+ claimOnchain?: RfqSwapManagerCallbacks["claimOnchain"];
1095
+ emulatorPubkey?: string;
1096
+ /** Overrides the wallet's own connection; for tests and for a caller that
1097
+ * must reach a different operator. */
1098
+ ark?: SwapOperator;
1099
+ indexer?: LockupSpendIndexer;
1100
+ }
1101
+ interface SwapClient {
1102
+ markets(useCache?: boolean): Promise<DiscoveredMarket[]>;
1103
+ quote(market: DiscoveredMarket, input: SwapQuoteInput): Promise<SwapQuote>;
1104
+ accept(quote: SwapQuote): Promise<UnifiedSwap>;
1105
+ /** Spot only: the covenant's cooperative reclaim. */
1106
+ cancel(fundingTxid: string): Promise<void>;
1107
+ /** Every swap this client knows of, both families and both live and ended
1108
+ * — not a live-only view. The RFQ half is bounded by what the manager has
1109
+ * loaded and by `RFQ_SWAP_RETENTION_SECONDS`. */
1110
+ swaps(): Promise<UnifiedSwap[]>;
1111
+ onUpdate(listener: (swap: UnifiedSwap) => void): () => void;
1112
+ start(): Promise<void>;
1113
+ stop(): Promise<void>;
1114
+ readonly manager: RfqSwapManager;
1115
+ }
1116
+ declare function createSwapClient(deps: SwapClientDeps): SwapClient;
1117
+
1118
+ export { ArkadeRefundResult, type ArkadeRefunderDeps, AssetSwap, AssetSwapRepository, ChainSource, type ClaimPacketInput, type DiscoverMarketsOptions, IndexedDbAssetSwapRepository, InvoiceFacts, type LightningReceiveProfile, type LightningReceiveQuote, type LightningSendProfile, type LightningSendQuote, 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 OnchainSendQuote, type PlanError, QUOTE_OPTIONS, type RefundBlockedReason, RefundIndexer, RefundNotLocallyPossibleError, type RestoreIndexer, type RfqClaimSecretProjection, type RfqHashlockProjection, type RfqSignerProjection, RfqSwap, type RfqSwapActivityDeps, RfqSwapManager, RfqSwapManagerCallbacks, RfqSwapRecord, RfqSwapState, RfqTransport, SWAP_LOCKUP_CONTRACT_KIND, SWAP_LOCKUP_CONTRACT_LABEL, SWAP_LOCKUP_CONTRACT_TYPE, type SealedClaimPacket, type SpendKind, type SpotQuote, type SwapActivityInput, type SwapClient, type SwapClientDeps, SwapOperator, type SwapQuote, type SwapQuoteInput, SwapSecretsProjection, type Tx, type UnifiedSwap, type WatchOfferSwapsParams, arkadeRefunder, awaitLockupFunding, cancelOffer, claimReceiveLockup, classifyDepositSpend, classifySpend, createOffer, createSwapClient, decodeOffer, discoverMarkets, encodeOffer, findMarket, lockupContractParams, makeCachedFeedFetch, offerContract, onchainSendProfile, pushClaim, registerLockupContract, requestLightningReceive, requestLightningSend, requestOnchainSend, restoreAssetSwaps, retireSettledOfferContracts, rfqClaimSecretOf, rfqSecretsProfile, rfqSignerOf, rfqSwapActivityInputs, sealClaimPacket, senderIdentityForSwapRecord, spendTxidsOf, spendUpdate, swapActivityResolver, swapPrograms, validatePlan, watchOfferSwaps };