@arkade-os/swap 0.0.6 → 0.0.7

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/README.md CHANGED
@@ -290,7 +290,9 @@ message anywhere: **acceptance is funding**.
290
290
  offline. The solver observes the funding on-chain, pays the invoice, and claims with the
291
291
  preimage — which lands publicly in the claim witness as the receipt. A failed swap refunds by
292
292
  covenant to the trader's address, pushable by anyone, no trader keys or state.
293
- - **Arkade ↔ arkade** (BTC↔asset, asset↔asset): the trader accepts a quote by creating and funding
293
+ - **Arkade ↔ arkade** (BTC↔asset, asset↔asset): an arkade asset leg names the asset id itself —
294
+ `arkade:<68-hex>`, built with `arkadeAssetLeg` (the deprecated coarse `ARKADE_ASSET` is served by
295
+ no solver). The trader accepts a quote by creating and funding
294
296
  an **offer** (layer 1) bound to the quoted terms before `valid_until`. The offer covenant only
295
297
  releases the deposit to a fill that delivers the quoted amount, so the solver fills or nothing
296
298
  moves; an unfilled offer is cancelled cooperatively. The quote wire shape ships here; the
@@ -311,9 +311,10 @@ var solverHex = (value, field) => {
311
311
  }
312
312
  };
313
313
  var ARKADE_BTC = "arkade:BTC";
314
- var ARKADE_ASSET = "arkade:ASSET";
315
314
  var LIGHTNING_BTC = "lightning:BTC";
316
315
  var ONCHAIN_BTC = "onchain:BTC";
316
+ var arkadeAssetLeg = (id) => `arkade:${id.toString()}`;
317
+ var ARKADE_ASSET = "arkade:ASSET";
317
318
  var rfqPair = (from, to) => `${from}->${to}`;
318
319
  var LIGHTNING_SEND_PAIR = rfqPair(ARKADE_BTC, LIGHTNING_BTC);
319
320
  var LIGHTNING_RECEIVE_PAIR = rfqPair(LIGHTNING_BTC, ARKADE_BTC);
@@ -354,23 +355,34 @@ var lightningSendRequest = (input) => ({
354
355
  }
355
356
  });
356
357
  var arkadeSwapRequest = (input) => {
357
- if (Boolean(input.wantAsset) === Boolean(input.offerAsset)) {
358
- throw new Error("set exactly one of wantAsset (BTC->asset) or offerAsset (asset->BTC)");
358
+ if (!input.wantAsset && !input.offerAsset) {
359
+ throw new Error(
360
+ "set exactly one of wantAsset (BTC->asset) or offerAsset (asset->BTC) \u2014 with neither set both legs are BTC, which is not a swap"
361
+ );
359
362
  }
363
+ if (input.wantAsset && input.offerAsset) {
364
+ throw new Error(
365
+ "set exactly one of wantAsset (BTC->asset) or offerAsset (asset->BTC) \u2014 asset->asset is nameable on the wire but no solver quotes it yet"
366
+ );
367
+ }
368
+ const pair = rfqPair(
369
+ input.offerAsset ? arkadeAssetLeg(input.offerAsset) : ARKADE_BTC,
370
+ input.wantAsset ? arkadeAssetLeg(input.wantAsset) : ARKADE_BTC
371
+ );
372
+ assertPairLength(pair);
360
373
  return {
361
374
  v: 1,
362
375
  type: "rfq_request",
363
376
  rfq_id: input.rfqId,
364
- pair: rfqPair(
365
- input.offerAsset ? ARKADE_ASSET : ARKADE_BTC,
366
- input.wantAsset ? ARKADE_ASSET : ARKADE_BTC
367
- ),
377
+ pair,
368
378
  amount_side: input.amountSide,
369
379
  amount: input.amount,
370
- profile: {
371
- ...input.offerAsset && { offer_asset: hex3.encode(input.offerAsset.serialize()) },
372
- ...input.wantAsset && { want_asset: hex3.encode(input.wantAsset.serialize()) }
373
- }
380
+ // The pair is the only place the asset ids appear. Repeating them here
381
+ // would be a key the solver's `.strict()` profile schema does not
382
+ // declare, and an undeclared key is `unsupported_payload` — a refusal,
383
+ // not an ignored extra. Empty, not absent: `profile` is required on
384
+ // every other request shape this wire carries.
385
+ profile: {}
374
386
  };
375
387
  };
376
388
  var MIN_HEADROOM_SECONDS = 90 * 60;
@@ -384,6 +396,14 @@ var assertFinite = (value, reason, label) => {
384
396
  throw gateError(reason, `${label} is not a finite number (${String(value)})`);
385
397
  }
386
398
  };
399
+ var MAX_PAIR_LENGTH = 158;
400
+ var assertPairLength = (pair) => {
401
+ if (pair.length > MAX_PAIR_LENGTH) {
402
+ throw new Error(
403
+ `pair is ${pair.length} characters, over the wire's ${MAX_PAIR_LENGTH}-character limit`
404
+ );
405
+ }
406
+ };
387
407
  var verifyLockupAddress = (quote, derivedAddress) => {
388
408
  const quoted = quote.profile?.lockup_address;
389
409
  if (derivedAddress !== quoted) throw new AddressMismatch(derivedAddress, quoted);
@@ -423,14 +443,20 @@ var assertFundable = (input) => {
423
443
  }
424
444
  }
425
445
  };
426
- var expectQuote = (payload, rfqId) => {
446
+ var expectQuote = (payload, rfqId, requestedPair) => {
427
447
  const p = payload;
428
448
  if (p?.type === "rfq_refusal") throw new SwapRefusal(p.reason ?? "unknown", p.rfq_id ?? rfqId);
429
449
  if (p?.type !== "rfq_quote" || p.rfq_id !== rfqId) {
430
450
  throw new Error(`unexpected reply: ${p?.type ?? "no payload"}`);
431
451
  }
452
+ if (requestedPair !== void 0 && p.pair !== requestedPair) {
453
+ throw new Error(
454
+ `solver quoted ${JSON.stringify(p.pair)}, not the requested ${requestedPair}`
455
+ );
456
+ }
432
457
  return payload;
433
458
  };
459
+ var pairOf = (payload) => typeof payload.pair === "string" ? payload.pair : void 0;
434
460
  var httpTransport = (baseUrl, options = {}) => {
435
461
  const fetchImpl = options.fetchImpl ?? fetch;
436
462
  const readJson = async (response, what) => {
@@ -450,7 +476,11 @@ var httpTransport = (baseUrl, options = {}) => {
450
476
  headers: { "content-type": "application/json" },
451
477
  body: JSON.stringify(payload)
452
478
  });
453
- return expectQuote(await readJson(response, "quote request"), String(payload.rfq_id));
479
+ return expectQuote(
480
+ await readJson(response, "quote request"),
481
+ String(payload.rfq_id),
482
+ pairOf(payload)
483
+ );
454
484
  },
455
485
  async status(rfqId) {
456
486
  const response = await fetchImpl(`${baseUrl}/v1/rfq/${rfqId}`, { method: "GET" });
@@ -527,7 +557,8 @@ var relayTransport = (relayUrl, options) => {
527
557
  async requestQuote(payload) {
528
558
  return expectQuote(
529
559
  await roundTrip(payload, String(payload.rfq_id)),
530
- String(payload.rfq_id)
560
+ String(payload.rfq_id),
561
+ pairOf(payload)
531
562
  );
532
563
  },
533
564
  async status(rfqId) {
@@ -1151,9 +1182,10 @@ export {
1151
1182
  LockupRegistrationFailed,
1152
1183
  registerLockupContract,
1153
1184
  ARKADE_BTC,
1154
- ARKADE_ASSET,
1155
1185
  LIGHTNING_BTC,
1156
1186
  ONCHAIN_BTC,
1187
+ arkadeAssetLeg,
1188
+ ARKADE_ASSET,
1157
1189
  rfqPair,
1158
1190
  LIGHTNING_SEND_PAIR,
1159
1191
  LIGHTNING_RECEIVE_PAIR,
@@ -1168,6 +1200,8 @@ export {
1168
1200
  MIN_HEADROOM_SECONDS,
1169
1201
  verifyLockupAddress,
1170
1202
  assertFundable,
1203
+ expectQuote,
1204
+ pairOf,
1171
1205
  httpTransport,
1172
1206
  relayTransport,
1173
1207
  SOLO_REFUND_HEADROOM_SECONDS,
package/dist/index.cjs CHANGED
@@ -67,6 +67,7 @@ __export(index_exports, {
67
67
  SWAP_LOCKUP_CONTRACT_TYPE: () => SWAP_LOCKUP_CONTRACT_TYPE,
68
68
  SwapRefusal: () => SwapRefusal,
69
69
  addAssetSwap: () => addAssetSwap,
70
+ arkadeAssetLeg: () => arkadeAssetLeg,
70
71
  arkadeSwapRequest: () => arkadeSwapRequest,
71
72
  assertFundable: () => assertFundable,
72
73
  assertReceivable: () => assertReceivable,
@@ -1446,9 +1447,10 @@ var solverHex = (value, field) => {
1446
1447
  }
1447
1448
  };
1448
1449
  var ARKADE_BTC = "arkade:BTC";
1449
- var ARKADE_ASSET = "arkade:ASSET";
1450
1450
  var LIGHTNING_BTC = "lightning:BTC";
1451
1451
  var ONCHAIN_BTC = "onchain:BTC";
1452
+ var arkadeAssetLeg = (id) => `arkade:${id.toString()}`;
1453
+ var ARKADE_ASSET = "arkade:ASSET";
1452
1454
  var rfqPair = (from, to) => `${from}->${to}`;
1453
1455
  var LIGHTNING_SEND_PAIR = rfqPair(ARKADE_BTC, LIGHTNING_BTC);
1454
1456
  var LIGHTNING_RECEIVE_PAIR = rfqPair(LIGHTNING_BTC, ARKADE_BTC);
@@ -1489,23 +1491,34 @@ var lightningSendRequest = (input) => ({
1489
1491
  }
1490
1492
  });
1491
1493
  var arkadeSwapRequest = (input) => {
1492
- if (Boolean(input.wantAsset) === Boolean(input.offerAsset)) {
1493
- throw new Error("set exactly one of wantAsset (BTC->asset) or offerAsset (asset->BTC)");
1494
+ if (!input.wantAsset && !input.offerAsset) {
1495
+ throw new Error(
1496
+ "set exactly one of wantAsset (BTC->asset) or offerAsset (asset->BTC) \u2014 with neither set both legs are BTC, which is not a swap"
1497
+ );
1494
1498
  }
1499
+ if (input.wantAsset && input.offerAsset) {
1500
+ throw new Error(
1501
+ "set exactly one of wantAsset (BTC->asset) or offerAsset (asset->BTC) \u2014 asset->asset is nameable on the wire but no solver quotes it yet"
1502
+ );
1503
+ }
1504
+ const pair = rfqPair(
1505
+ input.offerAsset ? arkadeAssetLeg(input.offerAsset) : ARKADE_BTC,
1506
+ input.wantAsset ? arkadeAssetLeg(input.wantAsset) : ARKADE_BTC
1507
+ );
1508
+ assertPairLength(pair);
1495
1509
  return {
1496
1510
  v: 1,
1497
1511
  type: "rfq_request",
1498
1512
  rfq_id: input.rfqId,
1499
- pair: rfqPair(
1500
- input.offerAsset ? ARKADE_ASSET : ARKADE_BTC,
1501
- input.wantAsset ? ARKADE_ASSET : ARKADE_BTC
1502
- ),
1513
+ pair,
1503
1514
  amount_side: input.amountSide,
1504
1515
  amount: input.amount,
1505
- profile: {
1506
- ...input.offerAsset && { offer_asset: import_base8.hex.encode(input.offerAsset.serialize()) },
1507
- ...input.wantAsset && { want_asset: import_base8.hex.encode(input.wantAsset.serialize()) }
1508
- }
1516
+ // The pair is the only place the asset ids appear. Repeating them here
1517
+ // would be a key the solver's `.strict()` profile schema does not
1518
+ // declare, and an undeclared key is `unsupported_payload` — a refusal,
1519
+ // not an ignored extra. Empty, not absent: `profile` is required on
1520
+ // every other request shape this wire carries.
1521
+ profile: {}
1509
1522
  };
1510
1523
  };
1511
1524
  var MIN_HEADROOM_SECONDS = 90 * 60;
@@ -1519,6 +1532,14 @@ var assertFinite = (value, reason, label) => {
1519
1532
  throw gateError(reason, `${label} is not a finite number (${String(value)})`);
1520
1533
  }
1521
1534
  };
1535
+ var MAX_PAIR_LENGTH = 158;
1536
+ var assertPairLength = (pair) => {
1537
+ if (pair.length > MAX_PAIR_LENGTH) {
1538
+ throw new Error(
1539
+ `pair is ${pair.length} characters, over the wire's ${MAX_PAIR_LENGTH}-character limit`
1540
+ );
1541
+ }
1542
+ };
1522
1543
  var verifyLockupAddress = (quote, derivedAddress) => {
1523
1544
  const quoted = quote.profile?.lockup_address;
1524
1545
  if (derivedAddress !== quoted) throw new AddressMismatch(derivedAddress, quoted);
@@ -1558,14 +1579,20 @@ var assertFundable = (input) => {
1558
1579
  }
1559
1580
  }
1560
1581
  };
1561
- var expectQuote = (payload, rfqId) => {
1582
+ var expectQuote = (payload, rfqId, requestedPair) => {
1562
1583
  const p = payload;
1563
1584
  if (p?.type === "rfq_refusal") throw new SwapRefusal(p.reason ?? "unknown", p.rfq_id ?? rfqId);
1564
1585
  if (p?.type !== "rfq_quote" || p.rfq_id !== rfqId) {
1565
1586
  throw new Error(`unexpected reply: ${p?.type ?? "no payload"}`);
1566
1587
  }
1588
+ if (requestedPair !== void 0 && p.pair !== requestedPair) {
1589
+ throw new Error(
1590
+ `solver quoted ${JSON.stringify(p.pair)}, not the requested ${requestedPair}`
1591
+ );
1592
+ }
1567
1593
  return payload;
1568
1594
  };
1595
+ var pairOf = (payload) => typeof payload.pair === "string" ? payload.pair : void 0;
1569
1596
  var httpTransport = (baseUrl, options = {}) => {
1570
1597
  const fetchImpl = options.fetchImpl ?? fetch;
1571
1598
  const readJson = async (response, what) => {
@@ -1585,7 +1612,11 @@ var httpTransport = (baseUrl, options = {}) => {
1585
1612
  headers: { "content-type": "application/json" },
1586
1613
  body: JSON.stringify(payload)
1587
1614
  });
1588
- return expectQuote(await readJson(response, "quote request"), String(payload.rfq_id));
1615
+ return expectQuote(
1616
+ await readJson(response, "quote request"),
1617
+ String(payload.rfq_id),
1618
+ pairOf(payload)
1619
+ );
1589
1620
  },
1590
1621
  async status(rfqId) {
1591
1622
  const response = await fetchImpl(`${baseUrl}/v1/rfq/${rfqId}`, { method: "GET" });
@@ -1662,7 +1693,8 @@ var relayTransport = (relayUrl, options) => {
1662
1693
  async requestQuote(payload) {
1663
1694
  return expectQuote(
1664
1695
  await roundTrip(payload, String(payload.rfq_id)),
1665
- String(payload.rfq_id)
1696
+ String(payload.rfq_id),
1697
+ pairOf(payload)
1666
1698
  );
1667
1699
  },
1668
1700
  async status(rfqId) {
@@ -3470,6 +3502,7 @@ function swapActivityResolver(deps) {
3470
3502
  SWAP_LOCKUP_CONTRACT_TYPE,
3471
3503
  SwapRefusal,
3472
3504
  addAssetSwap,
3505
+ arkadeAssetLeg,
3473
3506
  arkadeSwapRequest,
3474
3507
  assertFundable,
3475
3508
  assertReceivable,
package/dist/index.d.cts CHANGED
@@ -2,8 +2,8 @@ import { asset, IWallet, arkade, RestIndexerProvider, Transaction, IContractMana
2
2
  import { A as AssetSwapRepository, a as AssetSwap, M as MarketsCacheEntry } from './repository-BwnZ8N62.cjs';
3
3
  export { b as AssetSwapStatus, B as BTC_ASSET_ID, I as InMemoryAssetSwapRepository, P as PreimageBlockedReason, c as PreimageNotRecoverableError, S as SwapSecretsProjection, d as addAssetSwap, g as getAssetSwaps, e as getAssetSwapsOrThrow, p as preimageForSwapRecord, s as swapSecretsToRecord, u as updateAssetSwap, f as updateAssetSwapBestEffort } from './repository-BwnZ8N62.cjs';
4
4
  import { Network, LocalCardInput, DiscoveredMarket, Side, OfferPlan } from '@arkade-os/solver-discovery';
5
- import { R as RfqStatus, a as RfqTransport, O as OnchainHtlc, C as ChainSource, b as ChainUtxo, c as OnchainHtlcPhase } from './rfq-3jWha5xA.cjs';
6
- export { A as ARKADE_ASSET, d as ARKADE_BTC, e as AddressMismatch, H as HtlcUtxo, I as InvoiceFacts, L as LIGHTNING_BTC, f as LIGHTNING_RECEIVE_PAIR, g as LIGHTNING_SEND_PAIR, M as MAX_MIN_CONFIRMATIONS, h as MIN_CLAIM_WINDOW_SECONDS, i as MIN_HEADROOM_SECONDS, j as ONCHAIN_BTC, k as ONCHAIN_CLAIM_MARGIN_SECONDS, l as ONCHAIN_DUST_SATS, m as ONCHAIN_ORDER_MARGIN_SECONDS, n as ONCHAIN_RECEIVE_PAIR, o as ONCHAIN_SECONDS_PER_BLOCK, p as ONCHAIN_SEND_PAIR, q as OnchainHtlcParams, r as OnchainNetwork, s as RFQ_TERMINAL_STATES, t as RelaySocket, u as RfqQuote, v as RfqRefusalReason, S as SOLO_REFUND_HEADROOM_SECONDS, w as SwapRefusal, x as arkadeSwapRequest, y as assertFundable, z as assertReceivable, B as awaitOnchainFill, D as buildHtlcClaim, E as buildHtlcRefund, F as claimOnchainFill, G as classifyOnchainHtlc, J as deriveLightningReceive, K as deriveOnchainReceive, N as deriveOnchainSend, P as extractPreimage, Q as httpTransport, T as lightningReceiveRequest, U as lightningSendRequest, V as lightningSendVtxoScript, W as newPreimage, X as newRfqId, Y as offerTermsFromQuote, Z as onchainHtlcScript, _ as onchainReceiveRequest, $ as onchainSendRequest, a0 as paymentHashOf, a1 as receiveVtxoScript, a2 as relayTransport, a3 as requestLightningReceive, a4 as requestLightningSend, a5 as requestOnchainReceive, a6 as requestOnchainSend, a7 as rfqPair, a8 as unilateralClaimDelay, a9 as unilateralRefundDelay, aa as unilateralRefundWithoutReceiverDelay, ab as verifyLockupAddress, ac as verifyReceiveInvoice } from './rfq-3jWha5xA.cjs';
5
+ import { R as RfqStatus, a as RfqTransport, O as OnchainHtlc, C as ChainSource, b as ChainUtxo, c as OnchainHtlcPhase } from './rfq-DfT9dAss.cjs';
6
+ export { A as ARKADE_ASSET, d as ARKADE_BTC, e as AddressMismatch, H as HtlcUtxo, I as InvoiceFacts, L as LIGHTNING_BTC, f as LIGHTNING_RECEIVE_PAIR, g as LIGHTNING_SEND_PAIR, M as MAX_MIN_CONFIRMATIONS, h as MIN_CLAIM_WINDOW_SECONDS, i as MIN_HEADROOM_SECONDS, j as ONCHAIN_BTC, k as ONCHAIN_CLAIM_MARGIN_SECONDS, l as ONCHAIN_DUST_SATS, m as ONCHAIN_ORDER_MARGIN_SECONDS, n as ONCHAIN_RECEIVE_PAIR, o as ONCHAIN_SECONDS_PER_BLOCK, p as ONCHAIN_SEND_PAIR, q as OnchainHtlcParams, r as OnchainNetwork, s as RFQ_TERMINAL_STATES, t as RelaySocket, u as RfqQuote, v as RfqRefusalReason, S as SOLO_REFUND_HEADROOM_SECONDS, w as SwapRefusal, x as arkadeAssetLeg, y as arkadeSwapRequest, z as assertFundable, B as assertReceivable, D as awaitOnchainFill, E as buildHtlcClaim, F as buildHtlcRefund, G as claimOnchainFill, J as classifyOnchainHtlc, K as deriveLightningReceive, N as deriveOnchainReceive, P as deriveOnchainSend, Q as extractPreimage, T as httpTransport, U as lightningReceiveRequest, V as lightningSendRequest, W as lightningSendVtxoScript, X as newPreimage, Y as newRfqId, Z as offerTermsFromQuote, _ as onchainHtlcScript, $ as onchainReceiveRequest, a0 as onchainSendRequest, a1 as paymentHashOf, a2 as receiveVtxoScript, a3 as relayTransport, a4 as requestLightningReceive, a5 as requestLightningSend, a6 as requestOnchainReceive, a7 as requestOnchainSend, a8 as rfqPair, a9 as unilateralClaimDelay, aa as unilateralRefundDelay, ab as unilateralRefundWithoutReceiverDelay, ac as verifyLockupAddress, ad as verifyReceiveInvoice } from './rfq-DfT9dAss.cjs';
7
7
 
8
8
  /** The contracts — pure data, shared verbatim with any other implementation. */
9
9
  declare const swapPrograms: Record<"wantAsset" | "wantBtc", ReturnType<typeof arkade.parseArtifact>>;
package/dist/index.d.ts CHANGED
@@ -2,8 +2,8 @@ import { asset, IWallet, arkade, RestIndexerProvider, Transaction, IContractMana
2
2
  import { A as AssetSwapRepository, a as AssetSwap, M as MarketsCacheEntry } from './repository-BwnZ8N62.js';
3
3
  export { b as AssetSwapStatus, B as BTC_ASSET_ID, I as InMemoryAssetSwapRepository, P as PreimageBlockedReason, c as PreimageNotRecoverableError, S as SwapSecretsProjection, d as addAssetSwap, g as getAssetSwaps, e as getAssetSwapsOrThrow, p as preimageForSwapRecord, s as swapSecretsToRecord, u as updateAssetSwap, f as updateAssetSwapBestEffort } from './repository-BwnZ8N62.js';
4
4
  import { Network, LocalCardInput, DiscoveredMarket, Side, OfferPlan } from '@arkade-os/solver-discovery';
5
- import { R as RfqStatus, a as RfqTransport, O as OnchainHtlc, C as ChainSource, b as ChainUtxo, c as OnchainHtlcPhase } from './rfq-3jWha5xA.js';
6
- export { A as ARKADE_ASSET, d as ARKADE_BTC, e as AddressMismatch, H as HtlcUtxo, I as InvoiceFacts, L as LIGHTNING_BTC, f as LIGHTNING_RECEIVE_PAIR, g as LIGHTNING_SEND_PAIR, M as MAX_MIN_CONFIRMATIONS, h as MIN_CLAIM_WINDOW_SECONDS, i as MIN_HEADROOM_SECONDS, j as ONCHAIN_BTC, k as ONCHAIN_CLAIM_MARGIN_SECONDS, l as ONCHAIN_DUST_SATS, m as ONCHAIN_ORDER_MARGIN_SECONDS, n as ONCHAIN_RECEIVE_PAIR, o as ONCHAIN_SECONDS_PER_BLOCK, p as ONCHAIN_SEND_PAIR, q as OnchainHtlcParams, r as OnchainNetwork, s as RFQ_TERMINAL_STATES, t as RelaySocket, u as RfqQuote, v as RfqRefusalReason, S as SOLO_REFUND_HEADROOM_SECONDS, w as SwapRefusal, x as arkadeSwapRequest, y as assertFundable, z as assertReceivable, B as awaitOnchainFill, D as buildHtlcClaim, E as buildHtlcRefund, F as claimOnchainFill, G as classifyOnchainHtlc, J as deriveLightningReceive, K as deriveOnchainReceive, N as deriveOnchainSend, P as extractPreimage, Q as httpTransport, T as lightningReceiveRequest, U as lightningSendRequest, V as lightningSendVtxoScript, W as newPreimage, X as newRfqId, Y as offerTermsFromQuote, Z as onchainHtlcScript, _ as onchainReceiveRequest, $ as onchainSendRequest, a0 as paymentHashOf, a1 as receiveVtxoScript, a2 as relayTransport, a3 as requestLightningReceive, a4 as requestLightningSend, a5 as requestOnchainReceive, a6 as requestOnchainSend, a7 as rfqPair, a8 as unilateralClaimDelay, a9 as unilateralRefundDelay, aa as unilateralRefundWithoutReceiverDelay, ab as verifyLockupAddress, ac as verifyReceiveInvoice } from './rfq-3jWha5xA.js';
5
+ import { R as RfqStatus, a as RfqTransport, O as OnchainHtlc, C as ChainSource, b as ChainUtxo, c as OnchainHtlcPhase } from './rfq-DfT9dAss.js';
6
+ export { A as ARKADE_ASSET, d as ARKADE_BTC, e as AddressMismatch, H as HtlcUtxo, I as InvoiceFacts, L as LIGHTNING_BTC, f as LIGHTNING_RECEIVE_PAIR, g as LIGHTNING_SEND_PAIR, M as MAX_MIN_CONFIRMATIONS, h as MIN_CLAIM_WINDOW_SECONDS, i as MIN_HEADROOM_SECONDS, j as ONCHAIN_BTC, k as ONCHAIN_CLAIM_MARGIN_SECONDS, l as ONCHAIN_DUST_SATS, m as ONCHAIN_ORDER_MARGIN_SECONDS, n as ONCHAIN_RECEIVE_PAIR, o as ONCHAIN_SECONDS_PER_BLOCK, p as ONCHAIN_SEND_PAIR, q as OnchainHtlcParams, r as OnchainNetwork, s as RFQ_TERMINAL_STATES, t as RelaySocket, u as RfqQuote, v as RfqRefusalReason, S as SOLO_REFUND_HEADROOM_SECONDS, w as SwapRefusal, x as arkadeAssetLeg, y as arkadeSwapRequest, z as assertFundable, B as assertReceivable, D as awaitOnchainFill, E as buildHtlcClaim, F as buildHtlcRefund, G as claimOnchainFill, J as classifyOnchainHtlc, K as deriveLightningReceive, N as deriveOnchainReceive, P as deriveOnchainSend, Q as extractPreimage, T as httpTransport, U as lightningReceiveRequest, V as lightningSendRequest, W as lightningSendVtxoScript, X as newPreimage, Y as newRfqId, Z as offerTermsFromQuote, _ as onchainHtlcScript, $ as onchainReceiveRequest, a0 as onchainSendRequest, a1 as paymentHashOf, a2 as receiveVtxoScript, a3 as relayTransport, a4 as requestLightningReceive, a5 as requestLightningSend, a6 as requestOnchainReceive, a7 as requestOnchainSend, a8 as rfqPair, a9 as unilateralClaimDelay, aa as unilateralRefundDelay, ab as unilateralRefundWithoutReceiverDelay, ac as verifyLockupAddress, ad as verifyReceiveInvoice } from './rfq-DfT9dAss.js';
7
7
 
8
8
  /** The contracts — pure data, shared verbatim with any other implementation. */
9
9
  declare const swapPrograms: Record<"wantAsset" | "wantBtc", ReturnType<typeof arkade.parseArtifact>>;
package/dist/index.js CHANGED
@@ -22,6 +22,7 @@ import {
22
22
  SWAP_LOCKUP_CONTRACT_LABEL,
23
23
  SWAP_LOCKUP_CONTRACT_TYPE,
24
24
  SwapRefusal,
25
+ arkadeAssetLeg,
25
26
  arkadeSwapRequest,
26
27
  assertFundable,
27
28
  assertReceivable,
@@ -59,7 +60,7 @@ import {
59
60
  unilateralRefundWithoutReceiverDelay,
60
61
  verifyLockupAddress,
61
62
  verifyReceiveInvoice
62
- } from "./chunk-Q4FAYBXS.js";
63
+ } from "./chunk-ZDTRQZE2.js";
63
64
  import {
64
65
  InMemoryAssetSwapRepository,
65
66
  marketsCacheKey
@@ -2269,6 +2270,7 @@ export {
2269
2270
  SWAP_LOCKUP_CONTRACT_TYPE,
2270
2271
  SwapRefusal,
2271
2272
  addAssetSwap,
2273
+ arkadeAssetLeg,
2272
2274
  arkadeSwapRequest,
2273
2275
  assertFundable,
2274
2276
  assertReceivable,
package/dist/nostr.cjs CHANGED
@@ -91,6 +91,20 @@ var SwapRefusal = class extends Error {
91
91
  }
92
92
  };
93
93
  var MIN_HEADROOM_SECONDS = 90 * 60;
94
+ var expectQuote = (payload, rfqId, requestedPair) => {
95
+ const p = payload;
96
+ if (p?.type === "rfq_refusal") throw new SwapRefusal(p.reason ?? "unknown", p.rfq_id ?? rfqId);
97
+ if (p?.type !== "rfq_quote" || p.rfq_id !== rfqId) {
98
+ throw new Error(`unexpected reply: ${p?.type ?? "no payload"}`);
99
+ }
100
+ if (requestedPair !== void 0 && p.pair !== requestedPair) {
101
+ throw new Error(
102
+ `solver quoted ${JSON.stringify(p.pair)}, not the requested ${requestedPair}`
103
+ );
104
+ }
105
+ return payload;
106
+ };
107
+ var pairOf = (payload) => typeof payload.pair === "string" ? payload.pair : void 0;
94
108
  var SEQUENCE_GRANULARITY_SECONDS = 512;
95
109
  var SOLO_REFUND_HEADROOM_SECONDS = 8 * SEQUENCE_GRANULARITY_SECONDS;
96
110
  var MIN_CLAIM_WINDOW_SECONDS = 30 * 60;
@@ -119,14 +133,6 @@ var closeReasons = (raw) => raw.map((entry) => {
119
133
  const { url, reason } = entry ?? {};
120
134
  return url ? `${url}: ${reason ?? "closed"}` : reason ?? "closed";
121
135
  });
122
- var asQuote = (payload, rfqId) => {
123
- const p = payload;
124
- if (p?.type === "rfq_refusal") throw new SwapRefusal(p.reason ?? "unknown", p.rfq_id ?? rfqId);
125
- if (p?.type !== "rfq_quote" || p.rfq_id !== rfqId) {
126
- throw new Error(`unexpected reply: ${p?.type ?? "no payload"}`);
127
- }
128
- return payload;
129
- };
130
136
  var nostrRfqTransport = (options) => {
131
137
  const relays = options.relays;
132
138
  const solverPubkey = options.solverPubkey;
@@ -202,7 +208,7 @@ var nostrRfqTransport = (options) => {
202
208
  const rfqId = String(payload.rfq_id);
203
209
  const reply = awaitReply(rfqId);
204
210
  await send(payload);
205
- return asQuote(await reply, rfqId);
211
+ return expectQuote(await reply, rfqId, pairOf(payload));
206
212
  },
207
213
  async status(rfqId) {
208
214
  const reply = awaitReply(rfqId);
package/dist/nostr.d.cts CHANGED
@@ -1,4 +1,4 @@
1
- import { a as RfqTransport } from './rfq-3jWha5xA.cjs';
1
+ import { a as RfqTransport } from './rfq-DfT9dAss.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 { a as RfqTransport } from './rfq-3jWha5xA.js';
1
+ import { a as RfqTransport } from './rfq-DfT9dAss.js';
2
2
  import { SimplePool } from 'nostr-tools';
3
3
  import '@arkade-os/sdk';
4
4
 
package/dist/nostr.js CHANGED
@@ -1,6 +1,7 @@
1
1
  import {
2
- SwapRefusal
3
- } from "./chunk-Q4FAYBXS.js";
2
+ expectQuote,
3
+ pairOf
4
+ } from "./chunk-ZDTRQZE2.js";
4
5
 
5
6
  // src/nostr.ts
6
7
  import {
@@ -32,14 +33,6 @@ var closeReasons = (raw) => raw.map((entry) => {
32
33
  const { url, reason } = entry ?? {};
33
34
  return url ? `${url}: ${reason ?? "closed"}` : reason ?? "closed";
34
35
  });
35
- var asQuote = (payload, rfqId) => {
36
- const p = payload;
37
- if (p?.type === "rfq_refusal") throw new SwapRefusal(p.reason ?? "unknown", p.rfq_id ?? rfqId);
38
- if (p?.type !== "rfq_quote" || p.rfq_id !== rfqId) {
39
- throw new Error(`unexpected reply: ${p?.type ?? "no payload"}`);
40
- }
41
- return payload;
42
- };
43
36
  var nostrRfqTransport = (options) => {
44
37
  const relays = options.relays;
45
38
  const solverPubkey = options.solverPubkey;
@@ -115,7 +108,7 @@ var nostrRfqTransport = (options) => {
115
108
  const rfqId = String(payload.rfq_id);
116
109
  const reply = awaitReply(rfqId);
117
110
  await send(payload);
118
- return asQuote(await reply, rfqId);
111
+ return expectQuote(await reply, rfqId, pairOf(payload));
119
112
  },
120
113
  async status(rfqId) {
121
114
  const reply = awaitReply(rfqId);
@@ -210,13 +210,25 @@ declare function classifyOnchainHtlc(chain: ChainSource, input: {
210
210
  };
211
211
  }): Promise<OnchainHtlcPhase>;
212
212
 
213
- /** Legs are `<corridor>:<asset>`; a pair is directional, `from->to`. Arkade
214
- * asset legs stay coarse (`arkade:ASSET`) — the exact asset ids ride the
215
- * request profile, mirroring how the offer TLV identifies assets. */
213
+ /** Legs are `<corridor>:<asset>`; a pair is directional, `from->to`. */
216
214
  declare const ARKADE_BTC = "arkade:BTC";
217
- declare const ARKADE_ASSET = "arkade:ASSET";
218
215
  declare const LIGHTNING_BTC = "lightning:BTC";
219
216
  declare const ONCHAIN_BTC = "onchain:BTC";
217
+ /** The arkade leg for an asset: the asset id itself, 68 lowercase hex. The id
218
+ * lives in the pair rather than the profile because the pair is the field both
219
+ * sides route and subscribe on, and a coarse leg cannot say which asset a
220
+ * market key is for.
221
+ *
222
+ * Taking an `AssetId` rather than a string is what enforces the case rule:
223
+ * `hex.decode` accepts uppercase while `hex.encode` only emits lowercase, so a
224
+ * value that reached us as `A1B2…` leaves here as `a1b2…`. Solvers compare pair
225
+ * strings byte for byte — a sender that normalised only in its key derivation
226
+ * would reach the right subscription and then be skipped as an unserved pair. */
227
+ declare const arkadeAssetLeg: (id: asset.AssetId) => string;
228
+ /** @deprecated The coarse asset leg. No solver serves it: `ASSET` is neither a
229
+ * registered ticker nor a 68-hex asset id, so a solver's market-key derivation
230
+ * throws on it. Use {@link arkadeAssetLeg}. Removed next major. */
231
+ declare const ARKADE_ASSET = "arkade:ASSET";
220
232
  declare const rfqPair: (from: string, to: string) => string;
221
233
  /** The implemented pair: pay a BOLT11 invoice out of an Arkade balance. */
222
234
  declare const LIGHTNING_SEND_PAIR: string;
@@ -287,9 +299,9 @@ declare const lightningSendRequest: (input: {
287
299
  senderPubkey: Uint8Array;
288
300
  }) => Record<string, unknown>;
289
301
  /** The rfq_request for an arkade↔arkade swap. Exactly one side may name an
290
- * asset id per direction (BTC has none); the pair string stays coarse and the
291
- * ids ride the profile, like the offer TLV. Forward-looking: the wire shape is
292
- * specified, the reference solver does not serve it yet. */
302
+ * asset id per direction (BTC has none), and the id is the leg itself — see
303
+ * {@link arkadeAssetLeg}. Forward-looking: the wire shape is specified, the
304
+ * reference solver does not serve it yet. */
293
305
  declare const arkadeSwapRequest: (input: {
294
306
  rfqId: string;
295
307
  /** Asset the trader deposits; omit when depositing BTC. */
@@ -920,4 +932,4 @@ declare function requestOnchainReceive(wallet: IWallet, arkServerUrl: string, tr
920
932
  secrets: ProvisionedClaimSecret;
921
933
  }>;
922
934
 
923
- export { onchainSendRequest as $, ARKADE_ASSET as A, awaitOnchainFill as B, type ChainSource as C, buildHtlcClaim as D, buildHtlcRefund as E, claimOnchainFill as F, classifyOnchainHtlc as G, type HtlcUtxo as H, type InvoiceFacts as I, deriveLightningReceive as J, deriveOnchainReceive as K, LIGHTNING_BTC as L, MAX_MIN_CONFIRMATIONS as M, deriveOnchainSend as N, type OnchainHtlc as O, extractPreimage as P, httpTransport as Q, type RfqStatus as R, SOLO_REFUND_HEADROOM_SECONDS as S, lightningReceiveRequest as T, lightningSendRequest as U, lightningSendVtxoScript as V, newPreimage as W, newRfqId as X, offerTermsFromQuote as Y, onchainHtlcScript as Z, onchainReceiveRequest as _, type RfqTransport as a, paymentHashOf as a0, receiveVtxoScript as a1, relayTransport as a2, requestLightningReceive as a3, requestLightningSend as a4, requestOnchainReceive as a5, requestOnchainSend as a6, rfqPair as a7, unilateralClaimDelay as a8, unilateralRefundDelay as a9, unilateralRefundWithoutReceiverDelay as aa, verifyLockupAddress as ab, verifyReceiveInvoice as ac, 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, arkadeSwapRequest as x, assertFundable as y, assertReceivable as z };
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 };
@@ -210,13 +210,25 @@ declare function classifyOnchainHtlc(chain: ChainSource, input: {
210
210
  };
211
211
  }): Promise<OnchainHtlcPhase>;
212
212
 
213
- /** Legs are `<corridor>:<asset>`; a pair is directional, `from->to`. Arkade
214
- * asset legs stay coarse (`arkade:ASSET`) — the exact asset ids ride the
215
- * request profile, mirroring how the offer TLV identifies assets. */
213
+ /** Legs are `<corridor>:<asset>`; a pair is directional, `from->to`. */
216
214
  declare const ARKADE_BTC = "arkade:BTC";
217
- declare const ARKADE_ASSET = "arkade:ASSET";
218
215
  declare const LIGHTNING_BTC = "lightning:BTC";
219
216
  declare const ONCHAIN_BTC = "onchain:BTC";
217
+ /** The arkade leg for an asset: the asset id itself, 68 lowercase hex. The id
218
+ * lives in the pair rather than the profile because the pair is the field both
219
+ * sides route and subscribe on, and a coarse leg cannot say which asset a
220
+ * market key is for.
221
+ *
222
+ * Taking an `AssetId` rather than a string is what enforces the case rule:
223
+ * `hex.decode` accepts uppercase while `hex.encode` only emits lowercase, so a
224
+ * value that reached us as `A1B2…` leaves here as `a1b2…`. Solvers compare pair
225
+ * strings byte for byte — a sender that normalised only in its key derivation
226
+ * would reach the right subscription and then be skipped as an unserved pair. */
227
+ declare const arkadeAssetLeg: (id: asset.AssetId) => string;
228
+ /** @deprecated The coarse asset leg. No solver serves it: `ASSET` is neither a
229
+ * registered ticker nor a 68-hex asset id, so a solver's market-key derivation
230
+ * throws on it. Use {@link arkadeAssetLeg}. Removed next major. */
231
+ declare const ARKADE_ASSET = "arkade:ASSET";
220
232
  declare const rfqPair: (from: string, to: string) => string;
221
233
  /** The implemented pair: pay a BOLT11 invoice out of an Arkade balance. */
222
234
  declare const LIGHTNING_SEND_PAIR: string;
@@ -287,9 +299,9 @@ declare const lightningSendRequest: (input: {
287
299
  senderPubkey: Uint8Array;
288
300
  }) => Record<string, unknown>;
289
301
  /** The rfq_request for an arkade↔arkade swap. Exactly one side may name an
290
- * asset id per direction (BTC has none); the pair string stays coarse and the
291
- * ids ride the profile, like the offer TLV. Forward-looking: the wire shape is
292
- * specified, the reference solver does not serve it yet. */
302
+ * asset id per direction (BTC has none), and the id is the leg itself — see
303
+ * {@link arkadeAssetLeg}. Forward-looking: the wire shape is specified, the
304
+ * reference solver does not serve it yet. */
293
305
  declare const arkadeSwapRequest: (input: {
294
306
  rfqId: string;
295
307
  /** Asset the trader deposits; omit when depositing BTC. */
@@ -920,4 +932,4 @@ declare function requestOnchainReceive(wallet: IWallet, arkServerUrl: string, tr
920
932
  secrets: ProvisionedClaimSecret;
921
933
  }>;
922
934
 
923
- export { onchainSendRequest as $, ARKADE_ASSET as A, awaitOnchainFill as B, type ChainSource as C, buildHtlcClaim as D, buildHtlcRefund as E, claimOnchainFill as F, classifyOnchainHtlc as G, type HtlcUtxo as H, type InvoiceFacts as I, deriveLightningReceive as J, deriveOnchainReceive as K, LIGHTNING_BTC as L, MAX_MIN_CONFIRMATIONS as M, deriveOnchainSend as N, type OnchainHtlc as O, extractPreimage as P, httpTransport as Q, type RfqStatus as R, SOLO_REFUND_HEADROOM_SECONDS as S, lightningReceiveRequest as T, lightningSendRequest as U, lightningSendVtxoScript as V, newPreimage as W, newRfqId as X, offerTermsFromQuote as Y, onchainHtlcScript as Z, onchainReceiveRequest as _, type RfqTransport as a, paymentHashOf as a0, receiveVtxoScript as a1, relayTransport as a2, requestLightningReceive as a3, requestLightningSend as a4, requestOnchainReceive as a5, requestOnchainSend as a6, rfqPair as a7, unilateralClaimDelay as a8, unilateralRefundDelay as a9, unilateralRefundWithoutReceiverDelay as aa, verifyLockupAddress as ab, verifyReceiveInvoice as ac, 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, arkadeSwapRequest as x, assertFundable as y, assertReceivable as z };
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 };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@arkade-os/swap",
3
- "version": "0.0.6",
3
+ "version": "0.0.7",
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": {
@@ -69,7 +69,7 @@
69
69
  "@noble/hashes": "2.0.1",
70
70
  "@scure/base": "2.0.0",
71
71
  "@scure/btc-signer": "2.0.1",
72
- "@arkade-os/sdk": "0.4.63"
72
+ "@arkade-os/sdk": "0.4.64"
73
73
  },
74
74
  "peerDependencies": {
75
75
  "nostr-tools": "^2.12.0"