@arkade-os/swap 0.0.18 → 0.0.20

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/nostr.cjs CHANGED
@@ -39,9 +39,9 @@ __export(nostr_exports, {
39
39
  module.exports = __toCommonJS(nostr_exports);
40
40
 
41
41
  // src/rfq.ts
42
- var import_base4 = require("@scure/base");
42
+ var import_base6 = require("@scure/base");
43
43
  var import_legacy2 = require("@noble/hashes/legacy.js");
44
- var import_sdk2 = require("@arkade-os/sdk");
44
+ var import_sdk4 = require("@arkade-os/sdk");
45
45
 
46
46
  // src/onchainHtlc.ts
47
47
  var import_base = require("@scure/base");
@@ -58,7 +58,7 @@ var L1_NETWORKS = {
58
58
  };
59
59
 
60
60
  // src/rfq.ts
61
- var import_sdk3 = require("@arkade-os/sdk");
61
+ var import_sdk5 = require("@arkade-os/sdk");
62
62
 
63
63
  // src/claimPacket.ts
64
64
  var import_base2 = require("@scure/base");
@@ -73,6 +73,111 @@ var HKDF_INFO = new TextEncoder().encode("covclaimd/preimage/v1");
73
73
  var import_base3 = require("@scure/base");
74
74
  var import_sdk = require("@arkade-os/sdk");
75
75
 
76
+ // src/offer.ts
77
+ var import_base5 = require("@scure/base");
78
+ var import_utils2 = require("@scure/btc-signer/utils.js");
79
+ var import_sdk3 = require("@arkade-os/sdk");
80
+
81
+ // src/swap-want-asset.program.json
82
+ var swap_want_asset_program_default = {
83
+ version: 0,
84
+ name: "banco-btc-to-asset",
85
+ params: [
86
+ { name: "makerWP", type: "pubkey" },
87
+ { name: "wantAmount", type: "int" },
88
+ { name: "wantAssetTxid", type: "hash" },
89
+ { name: "wantAssetGroupIndex", type: "int" },
90
+ { name: "server", type: "pubkey" },
91
+ { name: "user", type: "pubkey" }
92
+ ],
93
+ functions: {
94
+ fulfill: {
95
+ tapscript: { signers: ["$server"] },
96
+ arkadeScript: {
97
+ asm: [
98
+ 0,
99
+ "$wantAssetTxid",
100
+ "$wantAssetGroupIndex",
101
+ "INSPECTOUTASSETLOOKUP",
102
+ "VERIFY",
103
+ "$wantAmount",
104
+ "GREATERTHANOREQUAL",
105
+ "VERIFY",
106
+ 0,
107
+ "INSPECTOUTPUTSCRIPTPUBKEY",
108
+ 1,
109
+ "EQUALVERIFY",
110
+ "$makerWP",
111
+ "EQUAL"
112
+ ]
113
+ }
114
+ },
115
+ cancel: {
116
+ tapscript: { signers: ["$user", "$server"] }
117
+ }
118
+ }
119
+ };
120
+
121
+ // src/swap-want-btc.program.json
122
+ var swap_want_btc_program_default = {
123
+ version: 0,
124
+ name: "banco-asset-to-btc",
125
+ params: [
126
+ { name: "makerWP", type: "pubkey" },
127
+ { name: "wantAmount", type: "int" },
128
+ { name: "server", type: "pubkey" },
129
+ { name: "user", type: "pubkey" }
130
+ ],
131
+ functions: {
132
+ fulfill: {
133
+ tapscript: { signers: ["$server"] },
134
+ arkadeScript: {
135
+ asm: [
136
+ 0,
137
+ "INSPECTOUTPUTVALUE",
138
+ "$wantAmount",
139
+ "GREATERTHANOREQUAL",
140
+ "VERIFY",
141
+ 0,
142
+ "INSPECTOUTPUTSCRIPTPUBKEY",
143
+ 1,
144
+ "EQUALVERIFY",
145
+ "$makerWP",
146
+ "EQUAL"
147
+ ]
148
+ }
149
+ },
150
+ cancel: {
151
+ tapscript: { signers: ["$user", "$server"] }
152
+ }
153
+ }
154
+ };
155
+
156
+ // src/store.ts
157
+ var import_base4 = require("@scure/base");
158
+ var import_sha23 = require("@noble/hashes/sha2.js");
159
+ var import_sdk2 = require("@arkade-os/sdk");
160
+
161
+ // src/offer.ts
162
+ var swapPrograms = {
163
+ wantAsset: import_sdk3.arkade.parseArtifact(swap_want_asset_program_default),
164
+ wantBtc: import_sdk3.arkade.parseArtifact(swap_want_btc_program_default)
165
+ };
166
+ var FIELDS = {
167
+ swapPkScript: { tag: 1, width: 34 },
168
+ wantAmount: { tag: 2, width: 8 },
169
+ wantAsset: { tag: 3, width: void 0 },
170
+ makerPkScript: { tag: 5, width: 34 },
171
+ makerPublicKey: { tag: 7, width: 32 },
172
+ emulatorPubkey: { tag: 8, width: 32 },
173
+ ratioNum: { tag: 9, width: 8 },
174
+ ratioDen: { tag: 10, width: 8 },
175
+ offerAsset: { tag: 11, width: void 0 },
176
+ exitTimelock: { tag: 12, width: 9 }
177
+ };
178
+ var NAMES = Object.fromEntries(Object.entries(FIELDS).map(([k, f]) => [f.tag, k]));
179
+ var ASSET_CARRIER_SATS = BigInt(import_sdk3.ASSET_CARRIER_SATS);
180
+
76
181
  // src/rfq.ts
77
182
  var ARKADE_BTC = "arkade:BTC";
78
183
  var LIGHTNING_BTC = "lightning:BTC";
package/dist/nostr.d.cts CHANGED
@@ -1,4 +1,4 @@
1
- import { R as RfqTransport } from './rfq-B_2hM0xk.cjs';
1
+ import { R as RfqTransport } from './rfq-B95nPfaa.cjs';
2
2
  import { SimplePool } from 'nostr-tools';
3
3
  import '@arkade-os/sdk';
4
4
 
package/dist/nostr.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- import { R as RfqTransport } from './rfq-B_2hM0xk.js';
1
+ import { R as RfqTransport } from './rfq-B95nPfaa.js';
2
2
  import { SimplePool } from 'nostr-tools';
3
3
  import '@arkade-os/sdk';
4
4
 
package/dist/nostr.js CHANGED
@@ -1,7 +1,7 @@
1
1
  import {
2
2
  expectQuote,
3
3
  pairOf
4
- } from "./chunk-N3W6LXH6.js";
4
+ } from "./chunk-QJKMTPRQ.js";
5
5
 
6
6
  // src/nostr.ts
7
7
  import {
@@ -1,8 +1,8 @@
1
1
  import { RealmLike } from '@arkade-os/sdk/repositories/realm';
2
- import { A as AssetSwapRepository, a as AssetSwap, R as RfqSwapRecord, M as MarketsCacheEntry } from '../../repository-BwasQwkR.cjs';
2
+ import { A as AssetSwapRepository, a as AssetSwap, R as RfqSwapRecord, M as MarketsCacheEntry } from '../../repository-Cop29z0c.cjs';
3
3
  import '@arkade-os/solver-discovery';
4
4
  import '@arkade-os/sdk';
5
- import '../../rfq-B_2hM0xk.cjs';
5
+ import '../../rfq-B95nPfaa.cjs';
6
6
 
7
7
  /**
8
8
  * Realm backend for React Native.
@@ -1,8 +1,8 @@
1
1
  import { RealmLike } from '@arkade-os/sdk/repositories/realm';
2
- import { A as AssetSwapRepository, a as AssetSwap, R as RfqSwapRecord, M as MarketsCacheEntry } from '../../repository-CucjFZN1.js';
2
+ import { A as AssetSwapRepository, a as AssetSwap, R as RfqSwapRecord, M as MarketsCacheEntry } from '../../repository-BrTpVPLy.js';
3
3
  import '@arkade-os/solver-discovery';
4
4
  import '@arkade-os/sdk';
5
- import '../../rfq-B_2hM0xk.js';
5
+ import '../../rfq-B95nPfaa.js';
6
6
 
7
7
  /**
8
8
  * Realm backend for React Native.
@@ -1,8 +1,8 @@
1
1
  import { SQLExecutor } from '@arkade-os/sdk/repositories/sqlite';
2
- import { A as AssetSwapRepository, a as AssetSwap, R as RfqSwapRecord, M as MarketsCacheEntry } from '../../repository-BwasQwkR.cjs';
2
+ import { A as AssetSwapRepository, a as AssetSwap, R as RfqSwapRecord, M as MarketsCacheEntry } from '../../repository-Cop29z0c.cjs';
3
3
  import '@arkade-os/solver-discovery';
4
4
  import '@arkade-os/sdk';
5
- import '../../rfq-B_2hM0xk.cjs';
5
+ import '../../rfq-B95nPfaa.cjs';
6
6
 
7
7
  /**
8
8
  * SQLite backend over the SDK's `SQLExecutor`, so any driver plugs in
@@ -1,8 +1,8 @@
1
1
  import { SQLExecutor } from '@arkade-os/sdk/repositories/sqlite';
2
- import { A as AssetSwapRepository, a as AssetSwap, R as RfqSwapRecord, M as MarketsCacheEntry } from '../../repository-CucjFZN1.js';
2
+ import { A as AssetSwapRepository, a as AssetSwap, R as RfqSwapRecord, M as MarketsCacheEntry } from '../../repository-BrTpVPLy.js';
3
3
  import '@arkade-os/solver-discovery';
4
4
  import '@arkade-os/sdk';
5
- import '../../rfq-B_2hM0xk.js';
5
+ import '../../rfq-B95nPfaa.js';
6
6
 
7
7
  /**
8
8
  * SQLite backend over the SDK's `SQLExecutor`, so any driver plugs in
@@ -1,6 +1,6 @@
1
1
  import { DiscoveredMarket } from '@arkade-os/solver-discovery';
2
2
  import { IWallet, ProvisionedKey, ProvisionedClaimSecret, RestArkProvider, RestIndexerProvider, VHTLC, Identity, IContractManager } from '@arkade-os/sdk';
3
- import { G as RfqStatus, R as RfqTransport, a as OnchainHtlc, f as ChainUtxo, C as ChainSource, v as OnchainHtlcPhase } from './rfq-B_2hM0xk.cjs';
3
+ import { G as RfqStatus, R as RfqTransport, a as OnchainHtlc, f as ChainUtxo, C as ChainSource, v as OnchainHtlcPhase } from './rfq-B95nPfaa.js';
4
4
 
5
5
  type AssetSwapStatus = "pending" | "cancelling" | "fulfilled" | "cancelled" | "recoverable" | "awaiting_fill" | "claimable" | "claimed" | "refunded_l1";
6
6
  /** The sentinel asset id for BTC itself, as opposed to a 68-hex asset id.
@@ -829,6 +829,9 @@ interface OnchainSendSwap extends RfqSwapCommon {
829
829
  htlc: OnchainHtlc;
830
830
  /** `profile.min_confirmations` from the quote. */
831
831
  minConfirmations: number;
832
+ /** The quote's `to_amount`, captured at REQUEST time: read at claim time it
833
+ * would be whatever the solver funded. */
834
+ expectedAmount: number;
832
835
  /** Where {@link RfqSwapManagerCallbacks.claimOnchain} pays; optional only
833
836
  * so records predating its profile slot still restore. */
834
837
  payoutPkScript?: Uint8Array;
@@ -1,6 +1,6 @@
1
1
  import { DiscoveredMarket } from '@arkade-os/solver-discovery';
2
2
  import { IWallet, ProvisionedKey, ProvisionedClaimSecret, RestArkProvider, RestIndexerProvider, VHTLC, Identity, IContractManager } from '@arkade-os/sdk';
3
- import { G as RfqStatus, R as RfqTransport, a as OnchainHtlc, f as ChainUtxo, C as ChainSource, v as OnchainHtlcPhase } from './rfq-B_2hM0xk.js';
3
+ import { G as RfqStatus, R as RfqTransport, a as OnchainHtlc, f as ChainUtxo, C as ChainSource, v as OnchainHtlcPhase } from './rfq-B95nPfaa.cjs';
4
4
 
5
5
  type AssetSwapStatus = "pending" | "cancelling" | "fulfilled" | "cancelled" | "recoverable" | "awaiting_fill" | "claimable" | "claimed" | "refunded_l1";
6
6
  /** The sentinel asset id for BTC itself, as opposed to a 68-hex asset id.
@@ -829,6 +829,9 @@ interface OnchainSendSwap extends RfqSwapCommon {
829
829
  htlc: OnchainHtlc;
830
830
  /** `profile.min_confirmations` from the quote. */
831
831
  minConfirmations: number;
832
+ /** The quote's `to_amount`, captured at REQUEST time: read at claim time it
833
+ * would be whatever the solver funded. */
834
+ expectedAmount: number;
832
835
  /** Where {@link RfqSwapManagerCallbacks.claimOnchain} pays; optional only
833
836
  * so records predating its profile slot still restore. */
834
837
  payoutPkScript?: Uint8Array;
@@ -298,8 +298,13 @@ interface RfqQuote {
298
298
  type: "rfq_quote";
299
299
  rfq_id: string;
300
300
  pair: string;
301
- from_amount: number;
302
- to_amount: number;
301
+ /** Sats on HTLC-class corridors (number); canonical decimal string on
302
+ * arkade↔arkade asset legs (bigint range, see WIRE_ASSET_AMOUNT on the
303
+ * solver). */
304
+ from_amount: number | string;
305
+ to_amount: number | string;
306
+ /** Dust an asset rides on. NOT a fee — already netted into the amounts above. */
307
+ carrier_sats?: number | string;
303
308
  solver_pubkey: string;
304
309
  valid_until: number;
305
310
  /** HTLC-class quotes only; absent for arkade↔arkade. */
@@ -309,6 +314,8 @@ interface RfqQuote {
309
314
  payment_hash?: string;
310
315
  lockup_address?: string;
311
316
  refund_without_receiver_delay?: number;
317
+ offer_address?: string;
318
+ offer_pk_script?: string;
312
319
  };
313
320
  [key: string]: unknown;
314
321
  }
@@ -336,20 +343,42 @@ declare const lightningSendRequest: (input: {
336
343
  refundAddress: string;
337
344
  senderPubkey: Uint8Array;
338
345
  }) => Record<string, unknown>;
339
- /** The rfq_request for an arkade↔arkade swap. Exactly one side may name an
340
- * asset id per direction (BTC has none), and the id is the leg itself — see
341
- * {@link arkadeAssetLeg}. Forward-looking: the wire shape is specified, the
342
- * reference solver does not serve it yet. */
346
+ /** The rfq_request for an arkade↔arkade swap. At least one side names an asset
347
+ * id (BTC has none), and the id is the leg itself — see
348
+ * {@link arkadeAssetLeg}.
349
+ *
350
+ * Wire-compatible with the reference solver (`AssetRfqRequest`, strict):
351
+ * `amount` is a canonical decimal string of atomic units (never a JSON
352
+ * number — an Arkade asset's precision is not knowable client-side, so the
353
+ * losslessness carve-out cannot be checked), `amount_side` is `"from"` or
354
+ * `"to"`, and `profile` carries the trader's own covenant position
355
+ * (`maker_pk_script`, `maker_public_key`) — the fill pays that script, and
356
+ * `cancel` is signed by that key. */
343
357
  declare const arkadeSwapRequest: (input: {
344
358
  rfqId: string;
345
359
  /** Asset the trader deposits; omit when depositing BTC. */
346
360
  offerAsset?: asset.AssetId;
347
361
  /** Asset the trader wants; omit when wanting BTC. */
348
362
  wantAsset?: asset.AssetId;
349
- amountSide: "from" | "to";
350
- /** Integer base units of the side named by `amountSide`. */
351
- amount: number;
363
+ amountSide?: "from" | "to";
364
+ /** Atomic units of the deposit (`from`) leg. bigint-safe: encoded as a
365
+ * canonical decimal string on the wire. */
366
+ amount: bigint | number | string;
367
+ /** Trader's own taproot scriptPubKey (34 bytes, `OP_1 <32-byte program>`),
368
+ * as bytes or lowercase hex. The covenant's `makerWP` minus its prefix. */
369
+ makerPkScript: Uint8Array | string;
370
+ /** Trader's own x-only key (32 bytes), as bytes or lowercase hex. The
371
+ * `cancel` path's `user` signer. */
372
+ makerPublicKey: Uint8Array | string;
352
373
  }) => Record<string, unknown>;
374
+ /** Canonical decimal string of atomic units: ASCII digits, no sign, point,
375
+ * exponent, or leading zero (unless the value is exactly "0"). bigint passes
376
+ * through; number must be a safe integer; string must already be canonical. */
377
+ declare const canonicalAssetAmount: (amount: bigint | number | string) => string;
378
+ /** 34-byte taproot scriptPubKey (`OP_1 <32-byte program>`), lowercase hex. */
379
+ declare const normalizeMakerPkScript: (value: Uint8Array | string) => string;
380
+ /** 32-byte x-only key, lowercase hex. Never a 33-byte compressed key. */
381
+ declare const normalizeMakerPublicKey: (value: Uint8Array | string) => string;
353
382
  /** Funding gate: refuse unless ≥90 min remain before the refund path opens.
354
383
  * 90 because the refund CLTV matures against median-time-past (BIP-113),
355
384
  * which lags wall clock by ~1h — a smaller wall-clock margin is no margin. */
@@ -622,6 +651,10 @@ declare function requestLightningSend(wallet: IWallet, arkServerUrl: string, tra
622
651
  * transaction that delivers the quoted want-amount to the trader, so the
623
652
  * solver fills or nothing moves. There is no rfq_fill message and no refund
624
653
  * timelock; an unfilled offer is cancelled cooperatively (`cancelOffer`).
654
+ *
655
+ * For asset-to-asset, the offer contract commits to the wanted asset only.
656
+ * The offered/deposit asset is carried by the funding VTXO and its asset
657
+ * packet; it is not part of the covenant derivation.
625
658
  */
626
659
  declare const offerTermsFromQuote: (quote: RfqQuote, assets: {
627
660
  wantAsset?: asset.AssetId;
@@ -631,6 +664,85 @@ declare const offerTermsFromQuote: (quote: RfqQuote, assets: {
631
664
  wantAsset?: asset.AssetId;
632
665
  offerAsset?: asset.AssetId;
633
666
  };
667
+ /** Compare-only check of the solver's offer address against YOUR OWN
668
+ * derivation — never extends trust, only narrows it. Funds only on an exact
669
+ * match of both the address (what the wallet sends to) and the script (what
670
+ * `offerVtxoScript` compiles to). Throws {@link AddressMismatch} otherwise. */
671
+ declare const verifyOfferAddress: (quote: RfqQuote, derived: {
672
+ address: string;
673
+ swapPkScript: Uint8Array;
674
+ }) => {
675
+ address: string;
676
+ swapPkScript: Uint8Array;
677
+ };
678
+ /** Gate an arkade↔arkade quote immediately before funding. No timelock exists
679
+ * on this class (neither `fulfill` nor `cancel` carries one), so the only
680
+ * clock is `valid_until`: funding after it is a deposit the solver will
681
+ * refuse to fill, reclaimable only via cooperative `cancelOffer`. */
682
+ declare const assertArkadeFundable: (input: {
683
+ quote: RfqQuote;
684
+ now?: number;
685
+ }) => void;
686
+ /**
687
+ * The arkade↔arkade user flow, mirroring `requestLightningSend`'s shape:
688
+ * quote → derive locally → verify → gate. Pure of funding on purpose — it
689
+ * returns the offer and the deposit it must carry, and the caller funds with
690
+ * its own wallet before `quote.valid_until`, after which the user may go
691
+ * offline: filling is non-interactive. An unfilled offer is cancelled
692
+ * cooperatively (`cancelOffer`); there is no timelock refund.
693
+ *
694
+ * Maker keys are the wallet's own (address script + identity x-only key), read
695
+ * here so the request profile and the local `createOffer` derivation cannot
696
+ * diverge. The quote's `offer_address`/`offer_pk_script` are compare-only:
697
+ * a mismatch throws {@link AddressMismatch} and must never be funded.
698
+ *
699
+ * Works over any {@link RfqTransport} — HTTP, dev relay, or Nostr — since the
700
+ * negotiation is one `rfq_request` round trip. Throws {@link SwapRefusal}
701
+ * (closed reason), {@link AddressMismatch} (never fund), or a gate error with
702
+ * a stable `reason`.
703
+ *
704
+ * Funding (caller's job, immediately after, before `valid_until`):
705
+ * - BTC->asset (`wantAsset`): `wallet.send({ address, amount: Number(fundAmount), extensions: [extension] })`
706
+ * - asset->BTC or asset->asset (`offerAsset`): `wallet.send({ address, amount: Number(carrierSats), assets: [{ assetId: offerAsset, amount: fundAmount }], extensions: [extension] })`
707
+ */
708
+ declare function requestArkadeSwap(wallet: IWallet, arkServerUrl: string, transport: RfqTransport, params: {
709
+ /** Asset the trader deposits; omit when depositing BTC. */
710
+ offerAsset?: asset.AssetId;
711
+ /** Asset the trader wants; omit when wanting BTC. */
712
+ wantAsset?: asset.AssetId;
713
+ /** Atomic units of whichever leg `amountSide` names. */
714
+ amount: bigint | number | string;
715
+ amountSide?: "from" | "to";
716
+ /** Bounds the side the SOLVER chose — the named side is echoed back verbatim,
717
+ * so asserting it proves nothing and an unbounded caller funds what it is asked. */
718
+ maxFromAmount?: bigint | number | string;
719
+ minToAmount?: bigint | number | string;
720
+ rfqId?: string;
721
+ /** Co-signer key override (33-byte compressed hex); see `createOffer`. */
722
+ emulatorPubkey?: string;
723
+ now?: number;
724
+ }): Promise<{
725
+ rfqId: string;
726
+ quote: RfqQuote;
727
+ pair: string;
728
+ /** The trader's OWN derivation — the only address to fund. */
729
+ address: string;
730
+ /** What the deposit must carry: the quote's `from_amount`. Sats for a BTC
731
+ * deposit, asset units for an asset deposit (plus a dust carrier). */
732
+ fundAmount: bigint;
733
+ /** Dust sats to attach to an asset deposit; 0n for a BTC deposit. */
734
+ carrierSats: bigint;
735
+ /** The covenant's scriptPubKey, for watching the deposit and its spend. */
736
+ swapPkScript: Uint8Array;
737
+ /** The encoded offer. Persist this — it is the only input `cancelOffer`
738
+ * needs, and the restore scan reads it back off the funding tx. */
739
+ offerHex: string;
740
+ /** Ready for `wallet.send`'s `extensions`. */
741
+ extension: {
742
+ type: number;
743
+ payload: Uint8Array;
744
+ };
745
+ }>;
634
746
  /** The rfq_request for `arkade:BTC->onchain:BTC`. Exact-out means "this much
635
747
  * lands in the L1 HTLC". `senderPubkey` is the user's own key for the
636
748
  * VHTLC's sender-side leaves — same role as in {@link lightningSendRequest}.
@@ -727,6 +839,7 @@ declare function deriveOnchainSend(input: {
727
839
  refundLocktime: number;
728
840
  htlcLocktime: number;
729
841
  minConfirmations: number;
842
+ expectedAmount: number;
730
843
  };
731
844
  /**
732
845
  * The `arkade:BTC->onchain:BTC` user flow, mirroring `requestLightningSend`:
@@ -767,6 +880,8 @@ declare function requestOnchainSend(wallet: IWallet, arkServerUrl: string, trans
767
880
  /** The user's OWN arkade lockup derivation — the only address to fund. */
768
881
  address: string;
769
882
  fundAmount: number;
883
+ /** What the solver's L1 fill must carry — persist it with the record. */
884
+ expectedAmount: number;
770
885
  swapPkScript: Uint8Array;
771
886
  /** The arkade covenant itself — the record's `lockup` for
772
887
  * `RfqSwapManager`, same role as {@link requestLightningSend}'s. */
@@ -1084,4 +1199,4 @@ declare function requestOnchainReceive(wallet: IWallet, arkServerUrl: string, tr
1084
1199
  secrets: ProvisionedClaimSecret;
1085
1200
  }>;
1086
1201
 
1087
- export { extractPreimage as $, ARKADE_ASSET as A, type RfqRefusalDetail as B, type ChainSource as C, type RfqRefusalErrorCode as D, type RfqRefusalReason as E, type RfqRefusalUnit as F, type RfqStatus as G, type HtlcUtxo as H, type InvoiceFacts as I, SwapRefusal as J, arkadeAssetLeg as K, LIGHTNING_BTC as L, MAX_MIN_CONFIRMATIONS as M, arkadeSwapRequest as N, type OnchainNetwork as O, assertFundable as P, assertReceivable as Q, type RfqTransport as R, SOLO_REFUND_HEADROOM_SECONDS as S, awaitOnchainFill as T, buildHtlcClaim as U, buildHtlcRefund as V, claimOnchainFill as W, classifyOnchainHtlc as X, deriveLightningReceive as Y, deriveOnchainReceive as Z, deriveOnchainSend as _, type OnchainHtlc as a, httpTransport as a0, isRfqRefusalErrorCode as a1, l1ScriptForAddress as a2, lightningReceiveRequest as a3, lightningSendRequest as a4, lightningSendVtxoScript as a5, newPreimage as a6, newRfqId as a7, offerTermsFromQuote as a8, onchainHtlcScript as a9, onchainReceiveRequest as aa, onchainSendRequest as ab, paymentHashOf as ac, receiveVtxoScript as ad, relayTransport as ae, requestLightningReceive as af, requestOnchainReceive as ag, rfqPair as ah, unilateralClaimDelay as ai, unilateralRefundDelay as aj, unilateralRefundWithoutReceiverDelay as ak, verifyLockupAddress as al, verifyReceiveInvoice as am, type OnchainHtlcParams as b, requestLightningSend as c, ARKADE_BTC as d, AddressMismatch as e, type ChainUtxo as f, LIGHTNING_RECEIVE_PAIR as g, LIGHTNING_SEND_PAIR as h, LOCKTIME_THRESHOLD as i, type LightningReceiveTreeParams as j, type LightningSendTreeParams as k, MIN_CLAIM_WINDOW_SECONDS as l, MIN_HEADROOM_SECONDS as m, ONCHAIN_BTC as n, ONCHAIN_CLAIM_MARGIN_SECONDS as o, ONCHAIN_DUST_SATS as p, ONCHAIN_ORDER_MARGIN_SECONDS as q, requestOnchainSend as r, ONCHAIN_RECEIVE_PAIR as s, ONCHAIN_SECONDS_PER_BLOCK as t, ONCHAIN_SEND_PAIR as u, type OnchainHtlcPhase as v, RFQ_REFUSAL_ERROR_CODES as w, RFQ_TERMINAL_STATES as x, type RelaySocket as y, type RfqQuote as z };
1202
+ export { deriveOnchainReceive as $, ARKADE_ASSET as A, type RfqRefusalDetail as B, type ChainSource as C, type RfqRefusalErrorCode as D, type RfqRefusalReason as E, type RfqRefusalUnit as F, type RfqStatus as G, type HtlcUtxo as H, type InvoiceFacts as I, SwapRefusal as J, arkadeAssetLeg as K, LIGHTNING_BTC as L, MAX_MIN_CONFIRMATIONS as M, arkadeSwapRequest as N, type OnchainNetwork as O, assertArkadeFundable as P, assertFundable as Q, type RfqTransport as R, SOLO_REFUND_HEADROOM_SECONDS as S, assertReceivable as T, awaitOnchainFill as U, buildHtlcClaim as V, buildHtlcRefund as W, canonicalAssetAmount as X, claimOnchainFill as Y, classifyOnchainHtlc as Z, deriveLightningReceive as _, type OnchainHtlc as a, deriveOnchainSend as a0, extractPreimage as a1, httpTransport as a2, isRfqRefusalErrorCode as a3, l1ScriptForAddress as a4, lightningReceiveRequest as a5, lightningSendRequest as a6, lightningSendVtxoScript as a7, newPreimage as a8, newRfqId as a9, normalizeMakerPkScript as aa, normalizeMakerPublicKey as ab, offerTermsFromQuote as ac, onchainHtlcScript as ad, onchainReceiveRequest as ae, onchainSendRequest as af, paymentHashOf as ag, receiveVtxoScript as ah, relayTransport as ai, requestArkadeSwap as aj, requestLightningReceive as ak, requestOnchainReceive as al, rfqPair as am, unilateralClaimDelay as an, unilateralRefundDelay as ao, unilateralRefundWithoutReceiverDelay as ap, verifyLockupAddress as aq, verifyOfferAddress as ar, verifyReceiveInvoice as as, type OnchainHtlcParams as b, requestLightningSend as c, ARKADE_BTC as d, AddressMismatch as e, type ChainUtxo as f, LIGHTNING_RECEIVE_PAIR as g, LIGHTNING_SEND_PAIR as h, LOCKTIME_THRESHOLD as i, type LightningReceiveTreeParams as j, type LightningSendTreeParams as k, MIN_CLAIM_WINDOW_SECONDS as l, MIN_HEADROOM_SECONDS as m, ONCHAIN_BTC as n, ONCHAIN_CLAIM_MARGIN_SECONDS as o, ONCHAIN_DUST_SATS as p, ONCHAIN_ORDER_MARGIN_SECONDS as q, requestOnchainSend as r, ONCHAIN_RECEIVE_PAIR as s, ONCHAIN_SECONDS_PER_BLOCK as t, ONCHAIN_SEND_PAIR as u, type OnchainHtlcPhase as v, RFQ_REFUSAL_ERROR_CODES as w, RFQ_TERMINAL_STATES as x, type RelaySocket as y, type RfqQuote as z };
@@ -298,8 +298,13 @@ interface RfqQuote {
298
298
  type: "rfq_quote";
299
299
  rfq_id: string;
300
300
  pair: string;
301
- from_amount: number;
302
- to_amount: number;
301
+ /** Sats on HTLC-class corridors (number); canonical decimal string on
302
+ * arkade↔arkade asset legs (bigint range, see WIRE_ASSET_AMOUNT on the
303
+ * solver). */
304
+ from_amount: number | string;
305
+ to_amount: number | string;
306
+ /** Dust an asset rides on. NOT a fee — already netted into the amounts above. */
307
+ carrier_sats?: number | string;
303
308
  solver_pubkey: string;
304
309
  valid_until: number;
305
310
  /** HTLC-class quotes only; absent for arkade↔arkade. */
@@ -309,6 +314,8 @@ interface RfqQuote {
309
314
  payment_hash?: string;
310
315
  lockup_address?: string;
311
316
  refund_without_receiver_delay?: number;
317
+ offer_address?: string;
318
+ offer_pk_script?: string;
312
319
  };
313
320
  [key: string]: unknown;
314
321
  }
@@ -336,20 +343,42 @@ declare const lightningSendRequest: (input: {
336
343
  refundAddress: string;
337
344
  senderPubkey: Uint8Array;
338
345
  }) => Record<string, unknown>;
339
- /** The rfq_request for an arkade↔arkade swap. Exactly one side may name an
340
- * asset id per direction (BTC has none), and the id is the leg itself — see
341
- * {@link arkadeAssetLeg}. Forward-looking: the wire shape is specified, the
342
- * reference solver does not serve it yet. */
346
+ /** The rfq_request for an arkade↔arkade swap. At least one side names an asset
347
+ * id (BTC has none), and the id is the leg itself — see
348
+ * {@link arkadeAssetLeg}.
349
+ *
350
+ * Wire-compatible with the reference solver (`AssetRfqRequest`, strict):
351
+ * `amount` is a canonical decimal string of atomic units (never a JSON
352
+ * number — an Arkade asset's precision is not knowable client-side, so the
353
+ * losslessness carve-out cannot be checked), `amount_side` is `"from"` or
354
+ * `"to"`, and `profile` carries the trader's own covenant position
355
+ * (`maker_pk_script`, `maker_public_key`) — the fill pays that script, and
356
+ * `cancel` is signed by that key. */
343
357
  declare const arkadeSwapRequest: (input: {
344
358
  rfqId: string;
345
359
  /** Asset the trader deposits; omit when depositing BTC. */
346
360
  offerAsset?: asset.AssetId;
347
361
  /** Asset the trader wants; omit when wanting BTC. */
348
362
  wantAsset?: asset.AssetId;
349
- amountSide: "from" | "to";
350
- /** Integer base units of the side named by `amountSide`. */
351
- amount: number;
363
+ amountSide?: "from" | "to";
364
+ /** Atomic units of the deposit (`from`) leg. bigint-safe: encoded as a
365
+ * canonical decimal string on the wire. */
366
+ amount: bigint | number | string;
367
+ /** Trader's own taproot scriptPubKey (34 bytes, `OP_1 <32-byte program>`),
368
+ * as bytes or lowercase hex. The covenant's `makerWP` minus its prefix. */
369
+ makerPkScript: Uint8Array | string;
370
+ /** Trader's own x-only key (32 bytes), as bytes or lowercase hex. The
371
+ * `cancel` path's `user` signer. */
372
+ makerPublicKey: Uint8Array | string;
352
373
  }) => Record<string, unknown>;
374
+ /** Canonical decimal string of atomic units: ASCII digits, no sign, point,
375
+ * exponent, or leading zero (unless the value is exactly "0"). bigint passes
376
+ * through; number must be a safe integer; string must already be canonical. */
377
+ declare const canonicalAssetAmount: (amount: bigint | number | string) => string;
378
+ /** 34-byte taproot scriptPubKey (`OP_1 <32-byte program>`), lowercase hex. */
379
+ declare const normalizeMakerPkScript: (value: Uint8Array | string) => string;
380
+ /** 32-byte x-only key, lowercase hex. Never a 33-byte compressed key. */
381
+ declare const normalizeMakerPublicKey: (value: Uint8Array | string) => string;
353
382
  /** Funding gate: refuse unless ≥90 min remain before the refund path opens.
354
383
  * 90 because the refund CLTV matures against median-time-past (BIP-113),
355
384
  * which lags wall clock by ~1h — a smaller wall-clock margin is no margin. */
@@ -622,6 +651,10 @@ declare function requestLightningSend(wallet: IWallet, arkServerUrl: string, tra
622
651
  * transaction that delivers the quoted want-amount to the trader, so the
623
652
  * solver fills or nothing moves. There is no rfq_fill message and no refund
624
653
  * timelock; an unfilled offer is cancelled cooperatively (`cancelOffer`).
654
+ *
655
+ * For asset-to-asset, the offer contract commits to the wanted asset only.
656
+ * The offered/deposit asset is carried by the funding VTXO and its asset
657
+ * packet; it is not part of the covenant derivation.
625
658
  */
626
659
  declare const offerTermsFromQuote: (quote: RfqQuote, assets: {
627
660
  wantAsset?: asset.AssetId;
@@ -631,6 +664,85 @@ declare const offerTermsFromQuote: (quote: RfqQuote, assets: {
631
664
  wantAsset?: asset.AssetId;
632
665
  offerAsset?: asset.AssetId;
633
666
  };
667
+ /** Compare-only check of the solver's offer address against YOUR OWN
668
+ * derivation — never extends trust, only narrows it. Funds only on an exact
669
+ * match of both the address (what the wallet sends to) and the script (what
670
+ * `offerVtxoScript` compiles to). Throws {@link AddressMismatch} otherwise. */
671
+ declare const verifyOfferAddress: (quote: RfqQuote, derived: {
672
+ address: string;
673
+ swapPkScript: Uint8Array;
674
+ }) => {
675
+ address: string;
676
+ swapPkScript: Uint8Array;
677
+ };
678
+ /** Gate an arkade↔arkade quote immediately before funding. No timelock exists
679
+ * on this class (neither `fulfill` nor `cancel` carries one), so the only
680
+ * clock is `valid_until`: funding after it is a deposit the solver will
681
+ * refuse to fill, reclaimable only via cooperative `cancelOffer`. */
682
+ declare const assertArkadeFundable: (input: {
683
+ quote: RfqQuote;
684
+ now?: number;
685
+ }) => void;
686
+ /**
687
+ * The arkade↔arkade user flow, mirroring `requestLightningSend`'s shape:
688
+ * quote → derive locally → verify → gate. Pure of funding on purpose — it
689
+ * returns the offer and the deposit it must carry, and the caller funds with
690
+ * its own wallet before `quote.valid_until`, after which the user may go
691
+ * offline: filling is non-interactive. An unfilled offer is cancelled
692
+ * cooperatively (`cancelOffer`); there is no timelock refund.
693
+ *
694
+ * Maker keys are the wallet's own (address script + identity x-only key), read
695
+ * here so the request profile and the local `createOffer` derivation cannot
696
+ * diverge. The quote's `offer_address`/`offer_pk_script` are compare-only:
697
+ * a mismatch throws {@link AddressMismatch} and must never be funded.
698
+ *
699
+ * Works over any {@link RfqTransport} — HTTP, dev relay, or Nostr — since the
700
+ * negotiation is one `rfq_request` round trip. Throws {@link SwapRefusal}
701
+ * (closed reason), {@link AddressMismatch} (never fund), or a gate error with
702
+ * a stable `reason`.
703
+ *
704
+ * Funding (caller's job, immediately after, before `valid_until`):
705
+ * - BTC->asset (`wantAsset`): `wallet.send({ address, amount: Number(fundAmount), extensions: [extension] })`
706
+ * - asset->BTC or asset->asset (`offerAsset`): `wallet.send({ address, amount: Number(carrierSats), assets: [{ assetId: offerAsset, amount: fundAmount }], extensions: [extension] })`
707
+ */
708
+ declare function requestArkadeSwap(wallet: IWallet, arkServerUrl: string, transport: RfqTransport, params: {
709
+ /** Asset the trader deposits; omit when depositing BTC. */
710
+ offerAsset?: asset.AssetId;
711
+ /** Asset the trader wants; omit when wanting BTC. */
712
+ wantAsset?: asset.AssetId;
713
+ /** Atomic units of whichever leg `amountSide` names. */
714
+ amount: bigint | number | string;
715
+ amountSide?: "from" | "to";
716
+ /** Bounds the side the SOLVER chose — the named side is echoed back verbatim,
717
+ * so asserting it proves nothing and an unbounded caller funds what it is asked. */
718
+ maxFromAmount?: bigint | number | string;
719
+ minToAmount?: bigint | number | string;
720
+ rfqId?: string;
721
+ /** Co-signer key override (33-byte compressed hex); see `createOffer`. */
722
+ emulatorPubkey?: string;
723
+ now?: number;
724
+ }): Promise<{
725
+ rfqId: string;
726
+ quote: RfqQuote;
727
+ pair: string;
728
+ /** The trader's OWN derivation — the only address to fund. */
729
+ address: string;
730
+ /** What the deposit must carry: the quote's `from_amount`. Sats for a BTC
731
+ * deposit, asset units for an asset deposit (plus a dust carrier). */
732
+ fundAmount: bigint;
733
+ /** Dust sats to attach to an asset deposit; 0n for a BTC deposit. */
734
+ carrierSats: bigint;
735
+ /** The covenant's scriptPubKey, for watching the deposit and its spend. */
736
+ swapPkScript: Uint8Array;
737
+ /** The encoded offer. Persist this — it is the only input `cancelOffer`
738
+ * needs, and the restore scan reads it back off the funding tx. */
739
+ offerHex: string;
740
+ /** Ready for `wallet.send`'s `extensions`. */
741
+ extension: {
742
+ type: number;
743
+ payload: Uint8Array;
744
+ };
745
+ }>;
634
746
  /** The rfq_request for `arkade:BTC->onchain:BTC`. Exact-out means "this much
635
747
  * lands in the L1 HTLC". `senderPubkey` is the user's own key for the
636
748
  * VHTLC's sender-side leaves — same role as in {@link lightningSendRequest}.
@@ -727,6 +839,7 @@ declare function deriveOnchainSend(input: {
727
839
  refundLocktime: number;
728
840
  htlcLocktime: number;
729
841
  minConfirmations: number;
842
+ expectedAmount: number;
730
843
  };
731
844
  /**
732
845
  * The `arkade:BTC->onchain:BTC` user flow, mirroring `requestLightningSend`:
@@ -767,6 +880,8 @@ declare function requestOnchainSend(wallet: IWallet, arkServerUrl: string, trans
767
880
  /** The user's OWN arkade lockup derivation — the only address to fund. */
768
881
  address: string;
769
882
  fundAmount: number;
883
+ /** What the solver's L1 fill must carry — persist it with the record. */
884
+ expectedAmount: number;
770
885
  swapPkScript: Uint8Array;
771
886
  /** The arkade covenant itself — the record's `lockup` for
772
887
  * `RfqSwapManager`, same role as {@link requestLightningSend}'s. */
@@ -1084,4 +1199,4 @@ declare function requestOnchainReceive(wallet: IWallet, arkServerUrl: string, tr
1084
1199
  secrets: ProvisionedClaimSecret;
1085
1200
  }>;
1086
1201
 
1087
- export { extractPreimage as $, ARKADE_ASSET as A, type RfqRefusalDetail as B, type ChainSource as C, type RfqRefusalErrorCode as D, type RfqRefusalReason as E, type RfqRefusalUnit as F, type RfqStatus as G, type HtlcUtxo as H, type InvoiceFacts as I, SwapRefusal as J, arkadeAssetLeg as K, LIGHTNING_BTC as L, MAX_MIN_CONFIRMATIONS as M, arkadeSwapRequest as N, type OnchainNetwork as O, assertFundable as P, assertReceivable as Q, type RfqTransport as R, SOLO_REFUND_HEADROOM_SECONDS as S, awaitOnchainFill as T, buildHtlcClaim as U, buildHtlcRefund as V, claimOnchainFill as W, classifyOnchainHtlc as X, deriveLightningReceive as Y, deriveOnchainReceive as Z, deriveOnchainSend as _, type OnchainHtlc as a, httpTransport as a0, isRfqRefusalErrorCode as a1, l1ScriptForAddress as a2, lightningReceiveRequest as a3, lightningSendRequest as a4, lightningSendVtxoScript as a5, newPreimage as a6, newRfqId as a7, offerTermsFromQuote as a8, onchainHtlcScript as a9, onchainReceiveRequest as aa, onchainSendRequest as ab, paymentHashOf as ac, receiveVtxoScript as ad, relayTransport as ae, requestLightningReceive as af, requestOnchainReceive as ag, rfqPair as ah, unilateralClaimDelay as ai, unilateralRefundDelay as aj, unilateralRefundWithoutReceiverDelay as ak, verifyLockupAddress as al, verifyReceiveInvoice as am, type OnchainHtlcParams as b, requestLightningSend as c, ARKADE_BTC as d, AddressMismatch as e, type ChainUtxo as f, LIGHTNING_RECEIVE_PAIR as g, LIGHTNING_SEND_PAIR as h, LOCKTIME_THRESHOLD as i, type LightningReceiveTreeParams as j, type LightningSendTreeParams as k, MIN_CLAIM_WINDOW_SECONDS as l, MIN_HEADROOM_SECONDS as m, ONCHAIN_BTC as n, ONCHAIN_CLAIM_MARGIN_SECONDS as o, ONCHAIN_DUST_SATS as p, ONCHAIN_ORDER_MARGIN_SECONDS as q, requestOnchainSend as r, ONCHAIN_RECEIVE_PAIR as s, ONCHAIN_SECONDS_PER_BLOCK as t, ONCHAIN_SEND_PAIR as u, type OnchainHtlcPhase as v, RFQ_REFUSAL_ERROR_CODES as w, RFQ_TERMINAL_STATES as x, type RelaySocket as y, type RfqQuote as z };
1202
+ export { deriveOnchainReceive as $, ARKADE_ASSET as A, type RfqRefusalDetail as B, type ChainSource as C, type RfqRefusalErrorCode as D, type RfqRefusalReason as E, type RfqRefusalUnit as F, type RfqStatus as G, type HtlcUtxo as H, type InvoiceFacts as I, SwapRefusal as J, arkadeAssetLeg as K, LIGHTNING_BTC as L, MAX_MIN_CONFIRMATIONS as M, arkadeSwapRequest as N, type OnchainNetwork as O, assertArkadeFundable as P, assertFundable as Q, type RfqTransport as R, SOLO_REFUND_HEADROOM_SECONDS as S, assertReceivable as T, awaitOnchainFill as U, buildHtlcClaim as V, buildHtlcRefund as W, canonicalAssetAmount as X, claimOnchainFill as Y, classifyOnchainHtlc as Z, deriveLightningReceive as _, type OnchainHtlc as a, deriveOnchainSend as a0, extractPreimage as a1, httpTransport as a2, isRfqRefusalErrorCode as a3, l1ScriptForAddress as a4, lightningReceiveRequest as a5, lightningSendRequest as a6, lightningSendVtxoScript as a7, newPreimage as a8, newRfqId as a9, normalizeMakerPkScript as aa, normalizeMakerPublicKey as ab, offerTermsFromQuote as ac, onchainHtlcScript as ad, onchainReceiveRequest as ae, onchainSendRequest as af, paymentHashOf as ag, receiveVtxoScript as ah, relayTransport as ai, requestArkadeSwap as aj, requestLightningReceive as ak, requestOnchainReceive as al, rfqPair as am, unilateralClaimDelay as an, unilateralRefundDelay as ao, unilateralRefundWithoutReceiverDelay as ap, verifyLockupAddress as aq, verifyOfferAddress as ar, verifyReceiveInvoice as as, type OnchainHtlcParams as b, requestLightningSend as c, ARKADE_BTC as d, AddressMismatch as e, type ChainUtxo as f, LIGHTNING_RECEIVE_PAIR as g, LIGHTNING_SEND_PAIR as h, LOCKTIME_THRESHOLD as i, type LightningReceiveTreeParams as j, type LightningSendTreeParams as k, MIN_CLAIM_WINDOW_SECONDS as l, MIN_HEADROOM_SECONDS as m, ONCHAIN_BTC as n, ONCHAIN_CLAIM_MARGIN_SECONDS as o, ONCHAIN_DUST_SATS as p, ONCHAIN_ORDER_MARGIN_SECONDS as q, requestOnchainSend as r, ONCHAIN_RECEIVE_PAIR as s, ONCHAIN_SECONDS_PER_BLOCK as t, ONCHAIN_SEND_PAIR as u, type OnchainHtlcPhase as v, RFQ_REFUSAL_ERROR_CODES as w, RFQ_TERMINAL_STATES as x, type RelaySocket as y, type RfqQuote as z };