@arkade-os/swap 0.0.7 → 0.0.9

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.
@@ -1,4 +1,4 @@
1
- import { asset, VHTLC, IWallet, ProvisionedClaimSecret, ProvisionedKey } from '@arkade-os/sdk';
1
+ import { VHTLC, asset, IWallet, ProvisionedClaimSecret, ProvisionedKey } from '@arkade-os/sdk';
2
2
 
3
3
  /** L1 confirmation-depth and reorg margin between dependent timelocks. */
4
4
  declare const ONCHAIN_ORDER_MARGIN_SECONDS: number;
@@ -9,6 +9,13 @@ declare const ONCHAIN_ORDER_MARGIN_SECONDS: number;
9
9
  declare const ONCHAIN_CLAIM_MARGIN_SECONDS: number;
10
10
  /** Bounds on the confirmation depth a quote may demand. */
11
11
  declare const MAX_MIN_CONFIRMATIONS = 6;
12
+ /**
13
+ * BIP65's boundary between the two things an absolute locktime can mean.
14
+ * Below it consensus reads the value as a block height; at or above it, as a
15
+ * unix timestamp. 500,000,000 itself is 1985-07-05 and is a timestamp, so the
16
+ * comparison against it is strict.
17
+ */
18
+ declare const LOCKTIME_THRESHOLD = 500000000;
12
19
  /** Conservative block interval for converting depths into wall-clock time. */
13
20
  declare const ONCHAIN_SECONDS_PER_BLOCK = 600;
14
21
  /**
@@ -239,7 +246,7 @@ declare const ONCHAIN_SEND_PAIR: string;
239
246
  /** On-board: a Bitcoin-L1 HTLC in, Arkade sats out. */
240
247
  declare const ONCHAIN_RECEIVE_PAIR: string;
241
248
  /** The closed refusal set. Treat any unknown reason as a generic decline. */
242
- type RfqRefusalReason = "unsupported_pair" | "unsupported_payload" | "amount_out_of_range" | "exposure_cap" | "invoice_expired" | "quote_conflict" | "pricing_unavailable";
249
+ type RfqRefusalReason = "unsupported_pair" | "unsupported_payload" | "amount_out_of_range" | "exposure_cap" | "invoice_expired" | "quote_conflict" | "pricing_unavailable" | "rate_limited";
243
250
  /** Lifecycle vocabulary; states after which nothing more will happen. */
244
251
  declare const RFQ_TERMINAL_STATES: readonly ["settled", "refused", "expired", "refunded", "stuck"];
245
252
  /** A refusal from the solver, carrying its closed-set reason. */
@@ -444,6 +451,9 @@ declare function lightningSendVtxoScript(params: {
444
451
  * this value. P2TR pkScript, 34 bytes. */
445
452
  receiverPkScript: Uint8Array;
446
453
  }): InstanceType<typeof VHTLC.ScriptV2>;
454
+ /** Every input {@link lightningSendVtxoScript} builds from. Derived from the
455
+ * builder rather than restated, so the two cannot drift. */
456
+ type LightningSendTreeParams = Parameters<typeof lightningSendVtxoScript>[0];
447
457
  /** The BOLT11 facts the trader read from its OWN decode — this module takes
448
458
  * the facts, not the decoder, so any wallet's existing decoder serves. */
449
459
  interface InvoiceFacts {
@@ -512,6 +522,22 @@ declare function requestLightningSend(wallet: IWallet, arkServerUrl: string, tra
512
522
  /** How the `sender` key is recovered later. Persist it with the record;
513
523
  * it holds nothing secret. */
514
524
  secrets: ProvisionedKey;
525
+ /**
526
+ * Every input the covenant was built from, as it was AT REQUEST TIME.
527
+ *
528
+ * Returned so a consumer can persist the swap without re-deriving any of
529
+ * it. Half of these are not on the quote: `serverPubkey` and `claimDelay`
530
+ * come from this wallet's own `getInfo()`, `emulatorPubkey` from a
531
+ * per-network pin, `refundPkScript` from decoding an address.
532
+ *
533
+ * All public. Persisting them is optional: this call also registers the
534
+ * lockup as a contract, and that row is where `rebuildRfqSwap` takes its
535
+ * covenant from — see `rfqRecord.ts`. Keep a copy only to hold a record
536
+ * that rebuilds without the wallet's contract store, and keep it as
537
+ * `VHTLCV2ContractHandler.serializeParams(script.options)`, the shape the
538
+ * rebuild accepts.
539
+ */
540
+ treeParams: LightningSendTreeParams;
515
541
  }>;
516
542
  /**
517
543
  * Map an arkade↔arkade quote onto `createOffer` terms. The trader takes the
@@ -610,6 +636,15 @@ declare function deriveOnchainSend(input: {
610
636
  * so the row can never key on a script other than the derived one. */
611
637
  script: InstanceType<typeof VHTLC.ScriptV2>;
612
638
  htlc: OnchainHtlc;
639
+ /** The inputs {@link htlc} was built from. Returned because nothing else
640
+ * can give them back: `OnchainHtlc` exposes only derived values, and this
641
+ * contract is Bitcoin L1 — there is no Arkade contract row for it, so a
642
+ * consumer persisting the swap has no other route to rebuilding it. */
643
+ htlcParams: OnchainHtlcParams;
644
+ /** Echoed from the input, so a result is a complete description of the L1
645
+ * half rather than one a caller has to re-assemble from what it passed in.
646
+ * {@link onchainSendProfile} reads it from here. */
647
+ l1Network: OnchainNetwork;
613
648
  refundLocktime: number;
614
649
  htlcLocktime: number;
615
650
  minConfirmations: number;
@@ -660,6 +695,30 @@ declare function requestOnchainSend(wallet: IWallet, arkServerUrl: string, trans
660
695
  refundAddress: string;
661
696
  /** The EXPECTED L1 fill, derived locally — watch and claim against this. */
662
697
  htlc: OnchainHtlc;
698
+ /** The inputs {@link htlc} was built from — persist these to rebuild it
699
+ * after a restart. Nothing else gives them back: `OnchainHtlc` exposes only
700
+ * derived values, and this contract is Bitcoin L1, so unlike the arkade
701
+ * lockup there is no contract row holding its parameters. Persist
702
+ * `htlc.address` alongside them (`OnchainSendProfile.htlcAddress`): the
703
+ * rebuild checks the two against each other, which is the only check
704
+ * available on a leg with no second copy of its covenant.
705
+ *
706
+ * `onchainSendProfile(result)` does all of that mapping for you; prefer it
707
+ * to reading these fields across by hand. */
708
+ htlcParams: OnchainHtlcParams;
709
+ /**
710
+ * Which bitcoin network the L1 HTLC was derived for.
711
+ *
712
+ * Returned because it is NOT the ark network name and cannot be recovered
713
+ * from one by inspection: this call maps `info.network` through a private
714
+ * narrowing where signet, mutinynet and testnet4 all become `"testnet"`.
715
+ * A caller reconstructing it from context would be re-deriving a mapping
716
+ * it cannot see, and a value the profile needs verbatim.
717
+ */
718
+ l1Network: OnchainNetwork;
719
+ /** `profile.min_confirmations`; gates when the L1 fill becomes claimable,
720
+ * and part of what a restored swap needs to drive its own claim. */
721
+ minConfirmations: number;
663
722
  /** The VHTLC `sender` x-only key, bound into the covenant. Public. */
664
723
  senderPubkey: Uint8Array;
665
724
  /** How the preimage and the `sender` key are recovered later — map it
@@ -757,6 +816,9 @@ declare function receiveVtxoScript(params: {
757
816
  * address) — `nonInteractiveClaim`'s pinned destination. */
758
817
  payoutPkScript: Uint8Array;
759
818
  }): InstanceType<typeof VHTLC.ScriptV2>;
819
+ /** Every input {@link receiveVtxoScript} builds from; see
820
+ * {@link LightningSendTreeParams}. */
821
+ type LightningReceiveTreeParams = Parameters<typeof receiveVtxoScript>[0];
760
822
  /**
761
823
  * The pure core of {@link requestLightningReceive}: derive the solver-funded
762
824
  * covenant locally from the quote's binding fields plus the trader's own data
@@ -781,6 +843,9 @@ declare function deriveLightningReceive(input: {
781
843
  /** The solver's hold invoice on `H` — what the trader pays to arm the swap. */
782
844
  invoice: string;
783
845
  refundLocktime: number;
846
+ /** Every input the covenant was built from — see the same field on
847
+ * `requestLightningSend`'s result for why a consumer needs them. */
848
+ treeParams: LightningReceiveTreeParams;
784
849
  };
785
850
  /**
786
851
  * The `lightning:BTC->arkade:BTC` user flow: quote → derive the covenant
@@ -856,6 +921,9 @@ declare function requestLightningReceive(wallet: IWallet, arkServerUrl: string,
856
921
  * through `swapSecretsToRecord` and persist BEFORE paying the invoice.
857
922
  * Public unless `mustPersistPreimage` says the wallet could not derive P. */
858
923
  secrets: ProvisionedClaimSecret;
924
+ /** Every input the covenant was built from; see the same field on
925
+ * `requestLightningSend`'s result. */
926
+ treeParams: LightningReceiveTreeParams;
859
927
  }>;
860
928
  /**
861
929
  * The pure core of {@link requestOnchainReceive}: derive BOTH contracts
@@ -932,4 +1000,4 @@ declare function requestOnchainReceive(wallet: IWallet, arkServerUrl: string, tr
932
1000
  secrets: ProvisionedClaimSecret;
933
1001
  }>;
934
1002
 
935
- export { onchainReceiveRequest as $, ARKADE_ASSET as A, assertReceivable as B, type ChainSource as C, awaitOnchainFill as D, buildHtlcClaim as E, buildHtlcRefund as F, claimOnchainFill as G, type HtlcUtxo as H, type InvoiceFacts as I, classifyOnchainHtlc as J, deriveLightningReceive as K, LIGHTNING_BTC as L, MAX_MIN_CONFIRMATIONS as M, deriveOnchainReceive as N, type OnchainHtlc as O, deriveOnchainSend as P, extractPreimage as Q, type RfqStatus as R, SOLO_REFUND_HEADROOM_SECONDS as S, httpTransport as T, lightningReceiveRequest as U, lightningSendRequest as V, lightningSendVtxoScript as W, newPreimage as X, newRfqId as Y, offerTermsFromQuote as Z, onchainHtlcScript as _, type RfqTransport as a, onchainSendRequest as a0, paymentHashOf as a1, receiveVtxoScript as a2, relayTransport as a3, requestLightningReceive as a4, requestLightningSend as a5, requestOnchainReceive as a6, requestOnchainSend as a7, rfqPair as a8, unilateralClaimDelay as a9, unilateralRefundDelay as aa, unilateralRefundWithoutReceiverDelay as ab, verifyLockupAddress as ac, verifyReceiveInvoice as ad, type ChainUtxo as b, type OnchainHtlcPhase as c, ARKADE_BTC as d, AddressMismatch as e, LIGHTNING_RECEIVE_PAIR as f, LIGHTNING_SEND_PAIR as g, MIN_CLAIM_WINDOW_SECONDS as h, MIN_HEADROOM_SECONDS as i, ONCHAIN_BTC as j, ONCHAIN_CLAIM_MARGIN_SECONDS as k, ONCHAIN_DUST_SATS as l, ONCHAIN_ORDER_MARGIN_SECONDS as m, ONCHAIN_RECEIVE_PAIR as n, ONCHAIN_SECONDS_PER_BLOCK as o, ONCHAIN_SEND_PAIR as p, type OnchainHtlcParams as q, type OnchainNetwork as r, RFQ_TERMINAL_STATES as s, type RelaySocket as t, type RfqQuote as u, type RfqRefusalReason as v, SwapRefusal as w, arkadeAssetLeg as x, arkadeSwapRequest as y, assertFundable as z };
1003
+ export { newRfqId as $, ARKADE_ASSET as A, arkadeAssetLeg as B, type ChainSource as C, arkadeSwapRequest as D, assertFundable as E, assertReceivable as F, awaitOnchainFill as G, type HtlcUtxo as H, type InvoiceFacts as I, buildHtlcClaim as J, buildHtlcRefund as K, LIGHTNING_BTC as L, MAX_MIN_CONFIRMATIONS as M, claimOnchainFill as N, type OnchainNetwork as O, classifyOnchainHtlc as P, deriveLightningReceive as Q, RFQ_TERMINAL_STATES as R, SOLO_REFUND_HEADROOM_SECONDS as S, deriveOnchainReceive as T, deriveOnchainSend as U, extractPreimage as V, httpTransport as W, lightningReceiveRequest as X, lightningSendRequest as Y, lightningSendVtxoScript as Z, newPreimage as _, type OnchainHtlc as a, offerTermsFromQuote as a0, onchainHtlcScript as a1, onchainReceiveRequest as a2, onchainSendRequest as a3, paymentHashOf as a4, receiveVtxoScript as a5, relayTransport as a6, requestLightningReceive as a7, requestLightningSend as a8, requestOnchainReceive as a9, requestOnchainSend as aa, rfqPair as ab, unilateralClaimDelay as ac, unilateralRefundDelay as ad, unilateralRefundWithoutReceiverDelay as ae, verifyLockupAddress as af, verifyReceiveInvoice as ag, type OnchainHtlcParams as b, ARKADE_BTC as c, AddressMismatch as d, type ChainUtxo as e, LIGHTNING_RECEIVE_PAIR as f, LIGHTNING_SEND_PAIR as g, LOCKTIME_THRESHOLD as h, type LightningReceiveTreeParams as i, type LightningSendTreeParams as j, MIN_CLAIM_WINDOW_SECONDS as k, MIN_HEADROOM_SECONDS as l, ONCHAIN_BTC as m, ONCHAIN_CLAIM_MARGIN_SECONDS as n, ONCHAIN_DUST_SATS as o, ONCHAIN_ORDER_MARGIN_SECONDS as p, ONCHAIN_RECEIVE_PAIR as q, ONCHAIN_SECONDS_PER_BLOCK as r, ONCHAIN_SEND_PAIR as s, type OnchainHtlcPhase as t, type RelaySocket as u, type RfqQuote as v, type RfqRefusalReason as w, type RfqStatus as x, type RfqTransport as y, SwapRefusal as z };
@@ -1,4 +1,4 @@
1
- import { asset, VHTLC, IWallet, ProvisionedClaimSecret, ProvisionedKey } from '@arkade-os/sdk';
1
+ import { VHTLC, asset, IWallet, ProvisionedClaimSecret, ProvisionedKey } from '@arkade-os/sdk';
2
2
 
3
3
  /** L1 confirmation-depth and reorg margin between dependent timelocks. */
4
4
  declare const ONCHAIN_ORDER_MARGIN_SECONDS: number;
@@ -9,6 +9,13 @@ declare const ONCHAIN_ORDER_MARGIN_SECONDS: number;
9
9
  declare const ONCHAIN_CLAIM_MARGIN_SECONDS: number;
10
10
  /** Bounds on the confirmation depth a quote may demand. */
11
11
  declare const MAX_MIN_CONFIRMATIONS = 6;
12
+ /**
13
+ * BIP65's boundary between the two things an absolute locktime can mean.
14
+ * Below it consensus reads the value as a block height; at or above it, as a
15
+ * unix timestamp. 500,000,000 itself is 1985-07-05 and is a timestamp, so the
16
+ * comparison against it is strict.
17
+ */
18
+ declare const LOCKTIME_THRESHOLD = 500000000;
12
19
  /** Conservative block interval for converting depths into wall-clock time. */
13
20
  declare const ONCHAIN_SECONDS_PER_BLOCK = 600;
14
21
  /**
@@ -239,7 +246,7 @@ declare const ONCHAIN_SEND_PAIR: string;
239
246
  /** On-board: a Bitcoin-L1 HTLC in, Arkade sats out. */
240
247
  declare const ONCHAIN_RECEIVE_PAIR: string;
241
248
  /** The closed refusal set. Treat any unknown reason as a generic decline. */
242
- type RfqRefusalReason = "unsupported_pair" | "unsupported_payload" | "amount_out_of_range" | "exposure_cap" | "invoice_expired" | "quote_conflict" | "pricing_unavailable";
249
+ type RfqRefusalReason = "unsupported_pair" | "unsupported_payload" | "amount_out_of_range" | "exposure_cap" | "invoice_expired" | "quote_conflict" | "pricing_unavailable" | "rate_limited";
243
250
  /** Lifecycle vocabulary; states after which nothing more will happen. */
244
251
  declare const RFQ_TERMINAL_STATES: readonly ["settled", "refused", "expired", "refunded", "stuck"];
245
252
  /** A refusal from the solver, carrying its closed-set reason. */
@@ -444,6 +451,9 @@ declare function lightningSendVtxoScript(params: {
444
451
  * this value. P2TR pkScript, 34 bytes. */
445
452
  receiverPkScript: Uint8Array;
446
453
  }): InstanceType<typeof VHTLC.ScriptV2>;
454
+ /** Every input {@link lightningSendVtxoScript} builds from. Derived from the
455
+ * builder rather than restated, so the two cannot drift. */
456
+ type LightningSendTreeParams = Parameters<typeof lightningSendVtxoScript>[0];
447
457
  /** The BOLT11 facts the trader read from its OWN decode — this module takes
448
458
  * the facts, not the decoder, so any wallet's existing decoder serves. */
449
459
  interface InvoiceFacts {
@@ -512,6 +522,22 @@ declare function requestLightningSend(wallet: IWallet, arkServerUrl: string, tra
512
522
  /** How the `sender` key is recovered later. Persist it with the record;
513
523
  * it holds nothing secret. */
514
524
  secrets: ProvisionedKey;
525
+ /**
526
+ * Every input the covenant was built from, as it was AT REQUEST TIME.
527
+ *
528
+ * Returned so a consumer can persist the swap without re-deriving any of
529
+ * it. Half of these are not on the quote: `serverPubkey` and `claimDelay`
530
+ * come from this wallet's own `getInfo()`, `emulatorPubkey` from a
531
+ * per-network pin, `refundPkScript` from decoding an address.
532
+ *
533
+ * All public. Persisting them is optional: this call also registers the
534
+ * lockup as a contract, and that row is where `rebuildRfqSwap` takes its
535
+ * covenant from — see `rfqRecord.ts`. Keep a copy only to hold a record
536
+ * that rebuilds without the wallet's contract store, and keep it as
537
+ * `VHTLCV2ContractHandler.serializeParams(script.options)`, the shape the
538
+ * rebuild accepts.
539
+ */
540
+ treeParams: LightningSendTreeParams;
515
541
  }>;
516
542
  /**
517
543
  * Map an arkade↔arkade quote onto `createOffer` terms. The trader takes the
@@ -610,6 +636,15 @@ declare function deriveOnchainSend(input: {
610
636
  * so the row can never key on a script other than the derived one. */
611
637
  script: InstanceType<typeof VHTLC.ScriptV2>;
612
638
  htlc: OnchainHtlc;
639
+ /** The inputs {@link htlc} was built from. Returned because nothing else
640
+ * can give them back: `OnchainHtlc` exposes only derived values, and this
641
+ * contract is Bitcoin L1 — there is no Arkade contract row for it, so a
642
+ * consumer persisting the swap has no other route to rebuilding it. */
643
+ htlcParams: OnchainHtlcParams;
644
+ /** Echoed from the input, so a result is a complete description of the L1
645
+ * half rather than one a caller has to re-assemble from what it passed in.
646
+ * {@link onchainSendProfile} reads it from here. */
647
+ l1Network: OnchainNetwork;
613
648
  refundLocktime: number;
614
649
  htlcLocktime: number;
615
650
  minConfirmations: number;
@@ -660,6 +695,30 @@ declare function requestOnchainSend(wallet: IWallet, arkServerUrl: string, trans
660
695
  refundAddress: string;
661
696
  /** The EXPECTED L1 fill, derived locally — watch and claim against this. */
662
697
  htlc: OnchainHtlc;
698
+ /** The inputs {@link htlc} was built from — persist these to rebuild it
699
+ * after a restart. Nothing else gives them back: `OnchainHtlc` exposes only
700
+ * derived values, and this contract is Bitcoin L1, so unlike the arkade
701
+ * lockup there is no contract row holding its parameters. Persist
702
+ * `htlc.address` alongside them (`OnchainSendProfile.htlcAddress`): the
703
+ * rebuild checks the two against each other, which is the only check
704
+ * available on a leg with no second copy of its covenant.
705
+ *
706
+ * `onchainSendProfile(result)` does all of that mapping for you; prefer it
707
+ * to reading these fields across by hand. */
708
+ htlcParams: OnchainHtlcParams;
709
+ /**
710
+ * Which bitcoin network the L1 HTLC was derived for.
711
+ *
712
+ * Returned because it is NOT the ark network name and cannot be recovered
713
+ * from one by inspection: this call maps `info.network` through a private
714
+ * narrowing where signet, mutinynet and testnet4 all become `"testnet"`.
715
+ * A caller reconstructing it from context would be re-deriving a mapping
716
+ * it cannot see, and a value the profile needs verbatim.
717
+ */
718
+ l1Network: OnchainNetwork;
719
+ /** `profile.min_confirmations`; gates when the L1 fill becomes claimable,
720
+ * and part of what a restored swap needs to drive its own claim. */
721
+ minConfirmations: number;
663
722
  /** The VHTLC `sender` x-only key, bound into the covenant. Public. */
664
723
  senderPubkey: Uint8Array;
665
724
  /** How the preimage and the `sender` key are recovered later — map it
@@ -757,6 +816,9 @@ declare function receiveVtxoScript(params: {
757
816
  * address) — `nonInteractiveClaim`'s pinned destination. */
758
817
  payoutPkScript: Uint8Array;
759
818
  }): InstanceType<typeof VHTLC.ScriptV2>;
819
+ /** Every input {@link receiveVtxoScript} builds from; see
820
+ * {@link LightningSendTreeParams}. */
821
+ type LightningReceiveTreeParams = Parameters<typeof receiveVtxoScript>[0];
760
822
  /**
761
823
  * The pure core of {@link requestLightningReceive}: derive the solver-funded
762
824
  * covenant locally from the quote's binding fields plus the trader's own data
@@ -781,6 +843,9 @@ declare function deriveLightningReceive(input: {
781
843
  /** The solver's hold invoice on `H` — what the trader pays to arm the swap. */
782
844
  invoice: string;
783
845
  refundLocktime: number;
846
+ /** Every input the covenant was built from — see the same field on
847
+ * `requestLightningSend`'s result for why a consumer needs them. */
848
+ treeParams: LightningReceiveTreeParams;
784
849
  };
785
850
  /**
786
851
  * The `lightning:BTC->arkade:BTC` user flow: quote → derive the covenant
@@ -856,6 +921,9 @@ declare function requestLightningReceive(wallet: IWallet, arkServerUrl: string,
856
921
  * through `swapSecretsToRecord` and persist BEFORE paying the invoice.
857
922
  * Public unless `mustPersistPreimage` says the wallet could not derive P. */
858
923
  secrets: ProvisionedClaimSecret;
924
+ /** Every input the covenant was built from; see the same field on
925
+ * `requestLightningSend`'s result. */
926
+ treeParams: LightningReceiveTreeParams;
859
927
  }>;
860
928
  /**
861
929
  * The pure core of {@link requestOnchainReceive}: derive BOTH contracts
@@ -932,4 +1000,4 @@ declare function requestOnchainReceive(wallet: IWallet, arkServerUrl: string, tr
932
1000
  secrets: ProvisionedClaimSecret;
933
1001
  }>;
934
1002
 
935
- export { onchainReceiveRequest as $, ARKADE_ASSET as A, assertReceivable as B, type ChainSource as C, awaitOnchainFill as D, buildHtlcClaim as E, buildHtlcRefund as F, claimOnchainFill as G, type HtlcUtxo as H, type InvoiceFacts as I, classifyOnchainHtlc as J, deriveLightningReceive as K, LIGHTNING_BTC as L, MAX_MIN_CONFIRMATIONS as M, deriveOnchainReceive as N, type OnchainHtlc as O, deriveOnchainSend as P, extractPreimage as Q, type RfqStatus as R, SOLO_REFUND_HEADROOM_SECONDS as S, httpTransport as T, lightningReceiveRequest as U, lightningSendRequest as V, lightningSendVtxoScript as W, newPreimage as X, newRfqId as Y, offerTermsFromQuote as Z, onchainHtlcScript as _, type RfqTransport as a, onchainSendRequest as a0, paymentHashOf as a1, receiveVtxoScript as a2, relayTransport as a3, requestLightningReceive as a4, requestLightningSend as a5, requestOnchainReceive as a6, requestOnchainSend as a7, rfqPair as a8, unilateralClaimDelay as a9, unilateralRefundDelay as aa, unilateralRefundWithoutReceiverDelay as ab, verifyLockupAddress as ac, verifyReceiveInvoice as ad, type ChainUtxo as b, type OnchainHtlcPhase as c, ARKADE_BTC as d, AddressMismatch as e, LIGHTNING_RECEIVE_PAIR as f, LIGHTNING_SEND_PAIR as g, MIN_CLAIM_WINDOW_SECONDS as h, MIN_HEADROOM_SECONDS as i, ONCHAIN_BTC as j, ONCHAIN_CLAIM_MARGIN_SECONDS as k, ONCHAIN_DUST_SATS as l, ONCHAIN_ORDER_MARGIN_SECONDS as m, ONCHAIN_RECEIVE_PAIR as n, ONCHAIN_SECONDS_PER_BLOCK as o, ONCHAIN_SEND_PAIR as p, type OnchainHtlcParams as q, type OnchainNetwork as r, RFQ_TERMINAL_STATES as s, type RelaySocket as t, type RfqQuote as u, type RfqRefusalReason as v, SwapRefusal as w, arkadeAssetLeg as x, arkadeSwapRequest as y, assertFundable as z };
1003
+ export { newRfqId as $, ARKADE_ASSET as A, arkadeAssetLeg as B, type ChainSource as C, arkadeSwapRequest as D, assertFundable as E, assertReceivable as F, awaitOnchainFill as G, type HtlcUtxo as H, type InvoiceFacts as I, buildHtlcClaim as J, buildHtlcRefund as K, LIGHTNING_BTC as L, MAX_MIN_CONFIRMATIONS as M, claimOnchainFill as N, type OnchainNetwork as O, classifyOnchainHtlc as P, deriveLightningReceive as Q, RFQ_TERMINAL_STATES as R, SOLO_REFUND_HEADROOM_SECONDS as S, deriveOnchainReceive as T, deriveOnchainSend as U, extractPreimage as V, httpTransport as W, lightningReceiveRequest as X, lightningSendRequest as Y, lightningSendVtxoScript as Z, newPreimage as _, type OnchainHtlc as a, offerTermsFromQuote as a0, onchainHtlcScript as a1, onchainReceiveRequest as a2, onchainSendRequest as a3, paymentHashOf as a4, receiveVtxoScript as a5, relayTransport as a6, requestLightningReceive as a7, requestLightningSend as a8, requestOnchainReceive as a9, requestOnchainSend as aa, rfqPair as ab, unilateralClaimDelay as ac, unilateralRefundDelay as ad, unilateralRefundWithoutReceiverDelay as ae, verifyLockupAddress as af, verifyReceiveInvoice as ag, type OnchainHtlcParams as b, ARKADE_BTC as c, AddressMismatch as d, type ChainUtxo as e, LIGHTNING_RECEIVE_PAIR as f, LIGHTNING_SEND_PAIR as g, LOCKTIME_THRESHOLD as h, type LightningReceiveTreeParams as i, type LightningSendTreeParams as j, MIN_CLAIM_WINDOW_SECONDS as k, MIN_HEADROOM_SECONDS as l, ONCHAIN_BTC as m, ONCHAIN_CLAIM_MARGIN_SECONDS as n, ONCHAIN_DUST_SATS as o, ONCHAIN_ORDER_MARGIN_SECONDS as p, ONCHAIN_RECEIVE_PAIR as q, ONCHAIN_SECONDS_PER_BLOCK as r, ONCHAIN_SEND_PAIR as s, type OnchainHtlcPhase as t, type RelaySocket as u, type RfqQuote as v, type RfqRefusalReason as w, type RfqStatus as x, type RfqTransport as y, SwapRefusal as z };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@arkade-os/swap",
3
- "version": "0.0.7",
3
+ "version": "0.0.9",
4
4
  "type": "module",
5
5
  "description": "Client-side Arkade Intents asset swaps: discover markets, quote, create/track/cancel offers, restore from chain.",
6
6
  "repository": {
@@ -65,11 +65,12 @@
65
65
  "license": "MIT",
66
66
  "dependencies": {
67
67
  "@arkade-os/solver-discovery": "0.2.3",
68
+ "@noble/ciphers": "2.1.1",
68
69
  "@noble/curves": "2.0.1",
69
70
  "@noble/hashes": "2.0.1",
70
71
  "@scure/base": "2.0.0",
71
72
  "@scure/btc-signer": "2.0.1",
72
- "@arkade-os/sdk": "0.4.64"
73
+ "@arkade-os/sdk": "0.4.66"
73
74
  },
74
75
  "peerDependencies": {
75
76
  "nostr-tools": "^2.12.0"
@@ -1,236 +0,0 @@
1
- import { DiscoveredMarket } from '@arkade-os/solver-discovery';
2
- import { IWallet, ProvisionedKey, ProvisionedClaimSecret } from '@arkade-os/sdk';
3
-
4
- type AssetSwapStatus = "pending" | "cancelling" | "fulfilled" | "cancelled" | "recoverable" | "awaiting_fill" | "claimable" | "claimed" | "refunded_l1";
5
- /** The sentinel asset id for BTC itself, as opposed to a 68-hex asset id.
6
- * Lives here with the {@link AssetSwap} fields it describes so the market and
7
- * restore layers share one spelling instead of re-typing the literal. */
8
- declare const BTC_ASSET_ID = "btc";
9
- /**
10
- * The record fields a wallet-provisioned secret becomes — what
11
- * {@link swapSecretsToRecord} emits, and what every record type carrying swap
12
- * secrets embeds.
13
- *
14
- * A named type rather than four fields restated per record: the mapper and the
15
- * records it feeds must agree exactly, and a record that silently omits one of
16
- * these round-trips a swap whose preimage cannot be re-derived. Embedding makes
17
- * the omission a compile error instead.
18
- *
19
- * **Only `preimageHex` is secret.** `signingDescriptor` and `preimageSaltHex`
20
- * are public derivation inputs — they must survive a field-mapped backend, but
21
- * they leak nothing without the seed.
22
- */
23
- interface SwapSecretsProjection {
24
- /**
25
- * The wallet descriptor this swap's sender key comes from — a fresh HD
26
- * child, or a static wallet's `tr(pubkey)`. Public — the signer
27
- * re-derives from the wallet, so the record carries no key material.
28
- */
29
- signingDescriptor?: string;
30
- /** P, hex, when it cannot be re-derived from the seed at all: the user
31
- * supplied it, or the signer cannot sign deterministically. The swap's only
32
- * claim secret when present. */
33
- preimageHex?: string;
34
- /**
35
- * The salt P derives from, hex, on the salted arm — what a static wallet
36
- * gets instead of storing P. **Public**, and unlike every other field here
37
- * it is minted per swap: it is what stops one repeating key from handing
38
- * every swap the same preimage.
39
- */
40
- preimageSaltHex?: string;
41
- }
42
- interface AssetSwap extends SwapSecretsProjection {
43
- /** Funding txid — the swap's identity. */
44
- id: string;
45
- /** 'btc' or a 68-hex asset id. */
46
- fromAsset: string;
47
- toAsset: string;
48
- /** Atomic amounts as strings (bigint is not JSON-safe). */
49
- fromAmount: string;
50
- /** The covenant wantAmount — a floor, the fill pays >= this. */
51
- toAmount: string;
52
- swapAddress: string;
53
- /** Hex pkScript of the swap contract — the indexer monitoring key. */
54
- swapPkScript: string;
55
- /** TLV offer — needed to rebuild the contract for cancel. */
56
- offerHex: string;
57
- fundingTxid: string;
58
- spentTxid?: string;
59
- status: AssetSwapStatus;
60
- createdAt: number;
61
- completedAt?: number;
62
- /** RFQ pair string, e.g. `arkade:BTC->onchain:BTC`. */
63
- pair?: string;
64
- /** `sha256(P)`, hex. Public, and how a restore confirms a candidate
65
- * derivation is the right one. */
66
- paymentHash?: string;
67
- /** The L1 HTLC's pkScript, hex — the chain-watch key. */
68
- htlcPkScriptHex?: string;
69
- htlcLocktime?: number;
70
- /** The L1 funding txid, once observed. */
71
- l1Txid?: string;
72
- }
73
- /** All swaps, newest-first. Insertion order is not chronological — the restore
74
- * scan rebuilds records in tx-scan order — so sort at read to keep
75
- * newest-first canonical for every consumer. */
76
- declare const getAssetSwapsOrThrow: (repository: AssetSwapRepository) => Promise<AssetSwap[]>;
77
- /** The consumer read: a broken backend reads as no swaps rather than crashing
78
- * a history view. Mutations must use {@link getAssetSwapsOrThrow} instead —
79
- * swallowing the read there would let "the backend is gone" masquerade as "no
80
- * such swap" and skip the write silently. */
81
- declare const getAssetSwaps: (repository: AssetSwapRepository) => Promise<AssetSwap[]>;
82
- /** Add a swap; no-op if the id is already stored. Returns the updated list.
83
- * THROWS on a failed write — nothing irreversible may happen until this record
84
- * is durable, so the caller must not fund on a failure. */
85
- declare const addAssetSwap: (repository: AssetSwapRepository, swap: AssetSwap) => Promise<AssetSwap[]>;
86
- /** Merge changes into a swap by id. Returns the updated list.
87
- * THROWS on a failed read or write, like {@link addAssetSwap} — use this for a
88
- * write that gates something irreversible. Transitions written *after* the
89
- * irreversible act belong on {@link updateAssetSwapBestEffort}. */
90
- declare const updateAssetSwap: (repository: AssetSwapRepository, id: string, changes: Partial<Omit<AssetSwap, "id">>) => Promise<AssetSwap[]>;
91
- /**
92
- * {@link updateAssetSwap} for transitions that follow an irreversible action (a
93
- * broadcast claim, a spent lockup): failing the caller there would report as
94
- * failed a swap whose funds already moved, and a stale status is recoverable —
95
- * crash recovery re-derives the true state from the chain
96
- * (`classifyOnchainHtlc`).
97
- *
98
- * `persisted` is the part that must not be hidden: a caller that notifies on a
99
- * change, or treats one as terminal, has to know the store did not agree.
100
- */
101
- declare const updateAssetSwapBestEffort: (repository: AssetSwapRepository, id: string, changes: Partial<Omit<AssetSwap, "id">>) => Promise<{
102
- swaps: AssetSwap[];
103
- persisted: boolean;
104
- }>;
105
- /**
106
- * The record fields a wallet-provisioned secret becomes.
107
- *
108
- * `signingDescriptor` is public and always stored — it is what recovers the
109
- * signer. Then at most one of: `preimageHex`, when the wallet says it cannot
110
- * re-derive P and it becomes the swap's only claim secret; or
111
- * `preimageSaltHex`, the public input a derivable-but-repeating key needs.
112
- */
113
- declare const swapSecretsToRecord: (secrets: ProvisionedKey | ProvisionedClaimSecret) => SwapSecretsProjection & {
114
- signingDescriptor: string;
115
- };
116
- /** Why a wallet cannot produce a swap's preimage. */
117
- type PreimageBlockedReason =
118
- /** The record carries no `signingDescriptor`. */
119
- "no-secrets"
120
- /** `preimageHex` or `preimageSaltHex` is present but not 32 bytes of hex. */
121
- | "malformed-record"
122
- /**
123
- * Nothing to derive from: a descriptor that repeats across swaps, with
124
- * neither a stored preimage nor a salt — or one this wallet holds no key
125
- * for. Merged deliberately: `contractSigner` reports a key it does not
126
- * hold as a plain `Error` for static wallets and a `ForeignDescriptorError`
127
- * for HD ones, so splitting the two here would mean matching on message
128
- * text, which is the thing this type exists to avoid. The `cause` carries
129
- * whichever it was.
130
- */
131
- | "not-derivable"
132
- /** Derived, but it does not hash to the record's `paymentHash`. */
133
- | "hash-mismatch";
134
- /**
135
- * The wallet cannot produce this swap's preimage, and which of the four ways
136
- * is `reason`.
137
- *
138
- * Deliberately **not** {@link RefundNotLocallyPossibleError}: that one means
139
- * "no local refund is possible", and `RfqSwapManager` acts on it by reporting
140
- * `needs_counterparty`. A claim-path read failure is a different verdict, and
141
- * borrowing the refund error would have the manager announce one for the
142
- * other.
143
- */
144
- declare class PreimageNotRecoverableError extends Error {
145
- readonly reason: PreimageBlockedReason;
146
- readonly name = "PreimageNotRecoverableError";
147
- constructor(reason: PreimageBlockedReason, message: string, options?: {
148
- cause?: unknown;
149
- });
150
- }
151
- /**
152
- * The preimage a swap record claims with — stored, or re-derived from the
153
- * wallet.
154
- *
155
- * The record-shaped inverse of {@link swapSecretsToRecord}, and the one place
156
- * that knows which of a record's fields `contractPreimage` needs. Wire claim
157
- * paths here rather than composing it by hand: a caller that forgets to pass
158
- * `preimageSaltHex` gets a *wrong* preimage from a wallet that can derive,
159
- * not an error.
160
- *
161
- * Verifies the result against `paymentHash` when the record carries one. The
162
- * salted arm has two inputs that can be wrong — the key and the salt — where
163
- * the HD arm had one, and a wrong P otherwise surfaces as an opaque script
164
- * failure at claim time, long after the mistake.
165
- *
166
- * Every refusal is a {@link PreimageNotRecoverableError} carrying a `reason`,
167
- * so a caller can tell "this record predates the descriptor" from "the salt is
168
- * corrupt" without reading message text.
169
- */
170
- declare const preimageForSwapRecord: (wallet: IWallet, record: SwapSecretsProjection & {
171
- paymentHash?: string;
172
- }) => Promise<Uint8Array>;
173
-
174
- /** A registry discovery result held for reuse. Refetchable — unlike a swap
175
- * record, losing it costs one network round trip — but it must survive a cold
176
- * boot: serving it stale is what keeps quoting alive while a registry is down. */
177
- interface MarketsCacheEntry {
178
- markets: DiscoveredMarket[];
179
- fetchedAt: number;
180
- }
181
- /**
182
- * Everything the package persists, following the monorepo repository
183
- * convention (versioned interface, AsyncDisposable, one backend per
184
- * platform — see the Boltz plugin's SwapRepository). Consumers construct
185
- * exactly one of these; there is no second storage seam.
186
- *
187
- * Durable records (swaps) and rebuildable state (the restore scan's txid
188
- * cursor, the markets cache) live side by side because they share a
189
- * lifetime: all three belong to one wallet on one device, and a consumer
190
- * that wipes one wants all three gone.
191
- *
192
- * ponytail: no query filters — every consumer reads all swaps and filters
193
- * in memory; mirror the Boltz plugin's GetSwapsFilter when a consumer needs
194
- * subset queries.
195
- */
196
- interface AssetSwapRepository extends AsyncDisposable {
197
- readonly version: 2;
198
- /** Insert or replace a swap by id. Store the record whole: `preimageHex`
199
- * and `preimageSaltHex` both leave the swap unclaimable if a field-mapped
200
- * backend drops them — the first is the only claim secret of a swap whose
201
- * signer cannot derive, the second the public input every other static
202
- * wallet's preimage derives from.
203
- *
204
- * Records must be **JSON-safe**: the SQLite and Realm backends serialize
205
- * the record to JSON, so a `Date` in a consumer-added field comes back a
206
- * string, a `Set`/`Map` comes back empty, and a `bigint` throws here —
207
- * none of which happens on IndexedDB's structured clone. `AssetSwap` as
208
- * declared is JSON-safe; keep added fields that way. */
209
- saveSwap(swap: AssetSwap): Promise<void>;
210
- /** All stored swaps, in no particular order — `getAssetSwaps` is the
211
- * canonical newest-first read. */
212
- getAllSwaps(): Promise<AssetSwap[]>;
213
- /** Sent txids already checked for offer packets (see restore.ts). */
214
- getScannedTxids(): Promise<Set<string>>;
215
- markTxidsScanned(txids: Iterable<string>): Promise<void>;
216
- /** Cached registry markets, or undefined on a miss. */
217
- getCachedMarkets(network: string, registry: string): Promise<MarketsCacheEntry | undefined>;
218
- saveCachedMarkets(network: string, registry: string, entry: MarketsCacheEntry): Promise<void>;
219
- clear(): Promise<void>;
220
- }
221
- declare class InMemoryAssetSwapRepository implements AssetSwapRepository {
222
- readonly version: 2;
223
- private readonly swaps;
224
- private readonly scanned;
225
- private readonly markets;
226
- saveSwap(swap: AssetSwap): Promise<void>;
227
- getAllSwaps(): Promise<AssetSwap[]>;
228
- getScannedTxids(): Promise<Set<string>>;
229
- markTxidsScanned(txids: Iterable<string>): Promise<void>;
230
- getCachedMarkets(network: string, registry: string): Promise<MarketsCacheEntry | undefined>;
231
- saveCachedMarkets(network: string, registry: string, entry: MarketsCacheEntry): Promise<void>;
232
- clear(): Promise<void>;
233
- [Symbol.asyncDispose](): Promise<void>;
234
- }
235
-
236
- export { type AssetSwapRepository as A, BTC_ASSET_ID as B, InMemoryAssetSwapRepository as I, type MarketsCacheEntry as M, type PreimageBlockedReason as P, type SwapSecretsProjection as S, type AssetSwap as a, type AssetSwapStatus as b, PreimageNotRecoverableError as c, addAssetSwap as d, getAssetSwapsOrThrow as e, updateAssetSwapBestEffort as f, getAssetSwaps as g, preimageForSwapRecord as p, swapSecretsToRecord as s, updateAssetSwap as u };