@arkade-os/swap 0.0.2 → 0.0.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.cjs CHANGED
@@ -55,7 +55,6 @@ __export(index_exports, {
55
55
  ONCHAIN_SEND_PAIR: () => ONCHAIN_SEND_PAIR,
56
56
  QUOTE_OPTIONS: () => QUOTE_OPTIONS,
57
57
  REFUND_MTP_LAG_SECONDS: () => REFUND_MTP_LAG_SECONDS,
58
- RFQ_PREIMAGE_TAG: () => RFQ_PREIMAGE_TAG,
59
58
  RFQ_RESOLVED_STATES: () => RFQ_RESOLVED_STATES,
60
59
  RFQ_SWAP_TERMINAL_STATES: () => RFQ_SWAP_TERMINAL_STATES,
61
60
  RFQ_TERMINAL_STATES: () => RFQ_TERMINAL_STATES,
@@ -66,7 +65,6 @@ __export(index_exports, {
66
65
  SWAP_LOCKUP_CONTRACT_TYPE: () => SWAP_LOCKUP_CONTRACT_TYPE,
67
66
  SwapRefusal: () => SwapRefusal,
68
67
  addAssetSwap: () => addAssetSwap,
69
- adoptSwapDescriptor: () => adoptSwapDescriptor,
70
68
  arkadeSwapRequest: () => arkadeSwapRequest,
71
69
  assertFundable: () => assertFundable,
72
70
  assertReceivable: () => assertReceivable,
@@ -75,7 +73,6 @@ __export(index_exports, {
75
73
  awaitRfqResolution: () => awaitRfqResolution,
76
74
  buildHtlcClaim: () => buildHtlcClaim,
77
75
  buildHtlcRefund: () => buildHtlcRefund,
78
- buildPreimageMessage: () => buildPreimageMessage,
79
76
  cancelOffer: () => cancelOffer,
80
77
  claimOnchainFill: () => claimOnchainFill,
81
78
  claimReceiveLockup: () => claimReceiveLockup,
@@ -87,8 +84,6 @@ __export(index_exports, {
87
84
  deriveLightningReceive: () => deriveLightningReceive,
88
85
  deriveOnchainReceive: () => deriveOnchainReceive,
89
86
  deriveOnchainSend: () => deriveOnchainSend,
90
- derivePreimage: () => derivePreimage,
91
- deriveSwapSecrets: () => deriveSwapSecrets,
92
87
  discoverMarkets: () => discoverMarkets,
93
88
  encodeOffer: () => encodeOffer,
94
89
  extractPreimage: () => extractPreimage,
@@ -97,7 +92,6 @@ __export(index_exports, {
97
92
  getAssetSwaps: () => getAssetSwaps,
98
93
  getAssetSwapsOrThrow: () => getAssetSwapsOrThrow,
99
94
  httpTransport: () => httpTransport,
100
- isDeterministicSigner: () => isDeterministicSigner,
101
95
  isRfqSwapTerminal: () => isRfqSwapTerminal,
102
96
  isRfqTerminal: () => isRfqTerminal,
103
97
  lightningReceiveRequest: () => lightningReceiveRequest,
@@ -113,10 +107,8 @@ __export(index_exports, {
113
107
  onchainReceiveRequest: () => onchainReceiveRequest,
114
108
  onchainSendRequest: () => onchainSendRequest,
115
109
  paymentHashOf: () => paymentHashOf,
116
- preimageForRfqSecrets: () => preimageForRfqSecrets,
117
110
  pushClaim: () => pushClaim,
118
111
  pushRefundWithoutReceiver: () => pushRefundWithoutReceiver,
119
- randomSwapSecrets: () => randomSwapSecrets,
120
112
  readLockupFate: () => readLockupFate,
121
113
  receiveVtxoScript: () => receiveVtxoScript,
122
114
  refundIfUnresolved: () => refundIfUnresolved,
@@ -129,15 +121,12 @@ __export(index_exports, {
129
121
  restoreAssetSwaps: () => restoreAssetSwaps,
130
122
  retireSettledOfferContracts: () => retireSettledOfferContracts,
131
123
  rfqPair: () => rfqPair,
132
- rfqSecretsOfRecord: () => rfqSecretsOfRecord,
133
- rfqSecretsToRecord: () => rfqSecretsToRecord,
134
124
  sealClaimPacket: () => sealClaimPacket,
135
- senderIdentityForRfqSecrets: () => senderIdentityForRfqSecrets,
136
125
  senderIdentityForSwapRecord: () => senderIdentityForSwapRecord,
137
- senderPubkeyForRfqSecrets: () => senderPubkeyForRfqSecrets,
138
126
  spendTxidsOf: () => spendTxidsOf,
139
127
  spendUpdate: () => spendUpdate,
140
128
  swapPrograms: () => swapPrograms,
129
+ swapSecretsToRecord: () => swapSecretsToRecord,
141
130
  unilateralClaimDelay: () => unilateralClaimDelay,
142
131
  unilateralRefundDelay: () => unilateralRefundDelay,
143
132
  unilateralRefundWithoutReceiverDelay: () => unilateralRefundWithoutReceiverDelay,
@@ -151,7 +140,7 @@ __export(index_exports, {
151
140
  module.exports = __toCommonJS(index_exports);
152
141
 
153
142
  // src/offer.ts
154
- var import_base = require("@scure/base");
143
+ var import_base2 = require("@scure/base");
155
144
  var import_utils = require("@scure/btc-signer/utils.js");
156
145
  var import_sdk = require("@arkade-os/sdk");
157
146
 
@@ -283,6 +272,7 @@ async function retireSettledOfferContracts(manager, swaps) {
283
272
  }
284
273
 
285
274
  // src/store.ts
275
+ var import_base = require("@scure/base");
286
276
  var BTC_ASSET_ID = "btc";
287
277
  var byNewest = (a, b) => b.createdAt - a.createdAt;
288
278
  var getAssetSwapsOrThrow = async (repository) => {
@@ -335,6 +325,10 @@ var updateAssetSwapBestEffort = async (repository, id, changes) => {
335
325
  return { swaps, persisted: false };
336
326
  }
337
327
  };
328
+ var swapSecretsToRecord = (secrets) => ({
329
+ signingDescriptor: secrets.descriptor,
330
+ ..."mustPersistPreimage" in secrets && secrets.mustPersistPreimage ? { preimageHex: import_base.hex.encode(secrets.preimage) } : {}
331
+ });
338
332
 
339
333
  // src/offer.ts
340
334
  var swapPrograms = {
@@ -380,14 +374,6 @@ var FIELDS = {
380
374
  offerAsset: { tag: 11, width: void 0 }
381
375
  };
382
376
  var NAMES = Object.fromEntries(Object.entries(FIELDS).map(([k, f]) => [f.tag, k]));
383
- var XONLY_LEN = 32;
384
- var xOnly = (key, label) => {
385
- if (key.length === XONLY_LEN) return key;
386
- if (key.length !== 33 || key[0] !== 2 && key[0] !== 3) {
387
- throw new Error(`${label} is not a compressed or x-only public key`);
388
- }
389
- return key.slice(1);
390
- };
391
377
  function tlv(type, value) {
392
378
  if (value.length > 65535) throw new Error("TLV value exceeds the u16 length field");
393
379
  return (0, import_utils.concatBytes)(Uint8Array.of(type, value.length >> 8 & 255, value.length & 255), value);
@@ -480,16 +466,16 @@ async function registerOfferContract(wallet, arkServerUrl, network, binding, ser
480
466
  contractManager
481
467
  });
482
468
  const contract = new import_sdk.arkade.ArkadeContract(client, program, args, keys);
483
- if (import_base.hex.encode(contract.pkScript) !== import_base.hex.encode(expectedPkScript)) {
469
+ if (import_base2.hex.encode(contract.pkScript) !== import_base2.hex.encode(expectedPkScript)) {
484
470
  throw new Error("derived covenant does not match the offer's swapPkScript");
485
471
  }
486
472
  await contract.register({
487
473
  label: OFFER_CONTRACT_LABEL,
488
474
  metadata: { genericallySpendable: false, kind: OFFER_CONTRACT_KIND }
489
475
  });
490
- await promoteOfferContract(contractManager, import_base.hex.encode(expectedPkScript));
476
+ await promoteOfferContract(contractManager, import_base2.hex.encode(expectedPkScript));
491
477
  }
492
- async function createOffer(wallet, arkServerUrl, emulatorPubkey, params) {
478
+ async function createOffer(wallet, arkServerUrl, params) {
493
479
  if (Boolean(params.wantAsset) === Boolean(params.offerAsset)) {
494
480
  throw new Error("set exactly one of wantAsset (BTC->asset) or offerAsset (asset->BTC)");
495
481
  }
@@ -498,8 +484,11 @@ async function createOffer(wallet, arkServerUrl, emulatorPubkey, params) {
498
484
  wallet.getAddress(),
499
485
  wallet.identity.xOnlyPublicKey()
500
486
  ]);
501
- const serverPubKey = xOnly(import_base.hex.decode(info.signerPubkey), "ark signer key");
502
- const emuKey = xOnly(emulatorPubkey, "emulator pubkey");
487
+ const serverPubKey = import_base2.hex.decode((0, import_sdk.toXOnlySignerHex)(info.signerPubkey));
488
+ const network = (0, import_sdk.getNetwork)(info.network);
489
+ const emuKey = import_base2.hex.decode(
490
+ (0, import_sdk.toXOnlySignerHex)((0, import_sdk.resolveEmulatorPubkey)(network, params.emulatorPubkey))
491
+ );
503
492
  const binding = {
504
493
  wantAmount: params.wantAmount,
505
494
  wantAsset: params.wantAsset,
@@ -520,17 +509,17 @@ async function createOffer(wallet, arkServerUrl, emulatorPubkey, params) {
520
509
  );
521
510
  const payload = encodeOffer(offer);
522
511
  return {
523
- offerHex: import_base.hex.encode(payload),
512
+ offerHex: import_base2.hex.encode(payload),
524
513
  extension: { type: OFFER_PACKET_TYPE, payload },
525
514
  // VtxoScript.address owns address construction; assembling an ArkAddress
526
515
  // from tweakedPublicKey here would silently miss any future step it gains
527
- address: script.address((0, import_sdk.getNetwork)(info.network).hrp, serverPubKey).encode(),
516
+ address: script.address(network.hrp, serverPubKey).encode(),
528
517
  swapPkScript: script.pkScript
529
518
  };
530
519
  }
531
520
  async function cancelOffer(wallet, arkServerUrl, offerHex, opts) {
532
521
  const { repository, fundingTxid, swapAddress } = opts;
533
- const offer = decodeOffer(import_base.hex.decode(offerHex));
522
+ const offer = decodeOffer(import_base2.hex.decode(offerHex));
534
523
  const contractManager = await wallet.getContractManager();
535
524
  const client = await import_sdk.arkade.Arkade.connect({
536
525
  arkade: new import_sdk.RestArkProvider(arkServerUrl),
@@ -547,7 +536,7 @@ async function cancelOffer(wallet, arkServerUrl, offerHex, opts) {
547
536
  const serverKey = swapAddress ? import_sdk.ArkAddress.decode(swapAddress).serverPubKey : client.serverKey;
548
537
  const { program, args, keys } = swapProgramBinding(offer, serverKey);
549
538
  const rebuilt = new import_sdk.arkade.ArkadeProgramScript(program, args, keys);
550
- if (import_base.hex.encode(rebuilt.pkScript) !== import_base.hex.encode(offer.swapPkScript)) {
539
+ if (import_base2.hex.encode(rebuilt.pkScript) !== import_base2.hex.encode(offer.swapPkScript)) {
551
540
  throw new Error(
552
541
  "rebuilt covenant does not match the offer's swapPkScript \u2014 the server signing key has likely rotated since funding; pass swapAddress (the funded address) to pin the original key"
553
542
  );
@@ -580,7 +569,7 @@ async function cancelOffer(wallet, arkServerUrl, offerHex, opts) {
580
569
  spentTxid: txid
581
570
  });
582
571
  if (persisted) {
583
- await retireOfferContract(contractManager, swaps, import_base.hex.encode(offer.swapPkScript));
572
+ await retireOfferContract(contractManager, swaps, import_base2.hex.encode(offer.swapPkScript));
584
573
  }
585
574
  }
586
575
  return txid;
@@ -846,7 +835,7 @@ var IndexedDbAssetSwapRepository = class {
846
835
  };
847
836
 
848
837
  // src/restore.ts
849
- var import_base2 = require("@scure/base");
838
+ var import_base3 = require("@scure/base");
850
839
  var import_sdk4 = require("@arkade-os/sdk");
851
840
  var TXS_PER_REQUEST = 50;
852
841
  async function fetchParsedTxs(indexer, txids) {
@@ -863,7 +852,7 @@ async function fetchParsedTxs(indexer, txids) {
863
852
  if (result.status !== "fulfilled") continue;
864
853
  for (const psbt of result.value) {
865
854
  try {
866
- const parsed = import_sdk4.Transaction.fromPSBT(import_base2.base64.decode(psbt));
855
+ const parsed = import_sdk4.Transaction.fromPSBT(import_base3.base64.decode(psbt));
867
856
  parsedByTxid.set(parsed.id, parsed);
868
857
  } catch {
869
858
  }
@@ -878,7 +867,7 @@ function classifySpend(offer, serverPubkey, spendTx, deposit) {
878
867
  let leaves;
879
868
  try {
880
869
  const script = offerVtxoScript(offer, serverPubkey);
881
- if (import_base2.hex.encode(script.pkScript) !== import_base2.hex.encode(offer.swapPkScript)) return "indeterminate";
870
+ if (import_base3.hex.encode(script.pkScript) !== import_base3.hex.encode(offer.swapPkScript)) return "indeterminate";
882
871
  leaves = {
883
872
  cancel: script.functionByName("cancel")?.leafScript,
884
873
  fulfill: script.functionByName("fulfill")?.leafScript
@@ -889,11 +878,11 @@ function classifySpend(offer, serverPubkey, spendTx, deposit) {
889
878
  for (let i = 0; i < spendTx.inputsLength; i++) {
890
879
  const input = spendTx.getInput(i);
891
880
  if (!input.txid || input.index !== deposit.vout) continue;
892
- if (import_base2.hex.encode(input.txid) !== deposit.txid) continue;
881
+ if (import_base3.hex.encode(input.txid) !== deposit.txid) continue;
893
882
  for (const leaf of input.tapLeafScript ?? []) {
894
- const spent = import_base2.hex.encode((0, import_sdk4.scriptFromTapLeafScript)(leaf));
895
- if (leaves.cancel && spent === import_base2.hex.encode(leaves.cancel)) return "cancelled";
896
- if (leaves.fulfill && spent === import_base2.hex.encode(leaves.fulfill)) return "fulfilled";
883
+ const spent = import_base3.hex.encode((0, import_sdk4.scriptFromTapLeafScript)(leaf));
884
+ if (leaves.cancel && spent === import_base3.hex.encode(leaves.cancel)) return "cancelled";
885
+ if (leaves.fulfill && spent === import_base3.hex.encode(leaves.fulfill)) return "fulfilled";
897
886
  }
898
887
  }
899
888
  return "indeterminate";
@@ -928,13 +917,13 @@ async function restoreAssetSwaps(indexer, txs, existingIds, opts) {
928
917
  found.push({
929
918
  fundingTx,
930
919
  offer: decodeOffer(payload),
931
- offerHex: import_base2.hex.encode(payload)
920
+ offerHex: import_base3.hex.encode(payload)
932
921
  });
933
922
  } catch {
934
923
  }
935
924
  }
936
925
  if (found.length === 0) return { restored: [], scannedTxids: fetchedTxids };
937
- const scripts = [...new Set(found.map((f) => import_base2.hex.encode(f.offer.swapPkScript)))];
926
+ const scripts = [...new Set(found.map((f) => import_base3.hex.encode(f.offer.swapPkScript)))];
938
927
  const { vtxos } = await indexer.getVtxos({ scripts });
939
928
  const vtxoByScriptAndTxid = new Map(vtxos.map((v) => [`${v.script}:${v.txid}`, v]));
940
929
  const txByAnyId = /* @__PURE__ */ new Map();
@@ -946,7 +935,7 @@ async function restoreAssetSwaps(indexer, txs, existingIds, opts) {
946
935
  const spendTxids = /* @__PURE__ */ new Set();
947
936
  for (const { fundingTx, offer } of found) {
948
937
  const vtxo = vtxoByScriptAndTxid.get(
949
- `${import_base2.hex.encode(offer.swapPkScript)}:${fundingTx.redeemTxid}`
938
+ `${import_base3.hex.encode(offer.swapPkScript)}:${fundingTx.redeemTxid}`
950
939
  );
951
940
  if (vtxo?.virtualStatus.state !== "spent") continue;
952
941
  for (const txid of spendTxidsOf(vtxo)) spendTxids.add(txid);
@@ -955,7 +944,7 @@ async function restoreAssetSwaps(indexer, txs, existingIds, opts) {
955
944
  const restored = [];
956
945
  const unresolved = /* @__PURE__ */ new Set();
957
946
  for (const { fundingTx, offer, offerHex } of found) {
958
- const swapPkScript = import_base2.hex.encode(offer.swapPkScript);
947
+ const swapPkScript = import_base3.hex.encode(offer.swapPkScript);
959
948
  const vtxo = vtxoByScriptAndTxid.get(`${swapPkScript}:${fundingTx.redeemTxid}`);
960
949
  if (!vtxo) {
961
950
  unresolved.add(fundingTx.redeemTxid);
@@ -1012,7 +1001,7 @@ async function restoreAssetSwaps(indexer, txs, existingIds, opts) {
1012
1001
  }
1013
1002
 
1014
1003
  // src/watch.ts
1015
- var import_base3 = require("@scure/base");
1004
+ var import_base4 = require("@scure/base");
1016
1005
  var import_sdk5 = require("@arkade-os/sdk");
1017
1006
  var TERMINAL = ["fulfilled", "cancelled", "recoverable"];
1018
1007
  function spendUpdate(swap, spend) {
@@ -1047,9 +1036,9 @@ async function watchOfferSwaps({
1047
1036
  if (candidates.length === 0) return "indeterminate";
1048
1037
  const { txs } = await indexer.getVirtualTxs(candidates);
1049
1038
  return classifyDepositSpend(
1050
- decodeOffer(import_base3.hex.decode(swap.offerHex)),
1039
+ decodeOffer(import_base4.hex.decode(swap.offerHex)),
1051
1040
  serverPubkey,
1052
- txs.map((psbt) => import_sdk5.Transaction.fromPSBT(import_base3.base64.decode(psbt))),
1041
+ txs.map((psbt) => import_sdk5.Transaction.fromPSBT(import_base4.base64.decode(psbt))),
1053
1042
  { txid: vtxo.txid, vout: vtxo.vout }
1054
1043
  );
1055
1044
  } catch {
@@ -1093,10 +1082,10 @@ async function watchOfferSwaps({
1093
1082
  // src/rfq.ts
1094
1083
  var import_base8 = require("@scure/base");
1095
1084
  var import_legacy2 = require("@noble/hashes/legacy.js");
1096
- var import_sdk8 = require("@arkade-os/sdk");
1085
+ var import_sdk7 = require("@arkade-os/sdk");
1097
1086
 
1098
1087
  // src/onchainHtlc.ts
1099
- var import_base4 = require("@scure/base");
1088
+ var import_base5 = require("@scure/base");
1100
1089
  var import_sha2 = require("@noble/hashes/sha2.js");
1101
1090
  var import_legacy = require("@noble/hashes/legacy.js");
1102
1091
  var btc = __toESM(require("@scure/btc-signer"), 1);
@@ -1106,8 +1095,8 @@ var MAX_MIN_CONFIRMATIONS = 6;
1106
1095
  var ONCHAIN_SECONDS_PER_BLOCK = 600;
1107
1096
  var ONCHAIN_DUST_SATS = BigInt(330);
1108
1097
  var newPreimage = () => crypto.getRandomValues(new Uint8Array(32));
1109
- var paymentHashOf = (preimage) => import_base4.hex.encode((0, import_sha2.sha256)(preimage));
1110
- var h160FromPaymentHash = (paymentHash) => (0, import_legacy.ripemd160)(import_base4.hex.decode(paymentHash));
1098
+ var paymentHashOf = (preimage) => import_base5.hex.encode((0, import_sha2.sha256)(preimage));
1099
+ var h160FromPaymentHash = (paymentHash) => (0, import_legacy.ripemd160)(import_base5.hex.decode(paymentHash));
1111
1100
  var L1_NETWORKS = {
1112
1101
  bitcoin: btc.NETWORK,
1113
1102
  testnet: btc.TEST_NETWORK,
@@ -1148,7 +1137,7 @@ function onchainHtlcScript(params, network) {
1148
1137
  );
1149
1138
  const controlBlockFor = (leaf) => {
1150
1139
  for (const [block, script] of payment.tapLeafScript ?? []) {
1151
- if (script.length - 1 === leaf.length && import_base4.hex.encode(script.subarray(0, leaf.length)) === import_base4.hex.encode(leaf)) {
1140
+ if (script.length - 1 === leaf.length && import_base5.hex.encode(script.subarray(0, leaf.length)) === import_base5.hex.encode(leaf)) {
1152
1141
  return btc.TaprootControlBlock.encode(block);
1153
1142
  }
1154
1143
  }
@@ -1241,13 +1230,13 @@ var buildHtlcRefund = (input) => buildLeafSpend({
1241
1230
  function extractPreimage(txHex, paymentHash) {
1242
1231
  let raw;
1243
1232
  try {
1244
- raw = btc.RawTx.decode(import_base4.hex.decode(txHex));
1233
+ raw = btc.RawTx.decode(import_base5.hex.decode(txHex));
1245
1234
  } catch {
1246
1235
  return null;
1247
1236
  }
1248
1237
  for (const stack of raw.witnesses ?? []) {
1249
1238
  for (const item of stack) {
1250
- if (item.length === 32 && import_base4.hex.encode((0, import_sha2.sha256)(item)) === paymentHash) return item;
1239
+ if (item.length === 32 && import_base5.hex.encode((0, import_sha2.sha256)(item)) === paymentHash) return item;
1251
1240
  }
1252
1241
  }
1253
1242
  return null;
@@ -1288,7 +1277,7 @@ async function classifyOnchainHtlc(chain, input) {
1288
1277
  const spend = await chain.getSpendingTx(input.funding.txid, input.funding.vout);
1289
1278
  if (!spend) return { phase: "unfunded" };
1290
1279
  const preimage = extractPreimage(spend.txHex, input.htlc.paymentHash);
1291
- const txid = btc.Transaction.fromRaw(import_base4.hex.decode(spend.txHex), {
1280
+ const txid = btc.Transaction.fromRaw(import_base5.hex.decode(spend.txHex), {
1292
1281
  allowUnknownInputs: true,
1293
1282
  allowUnknownOutputs: true
1294
1283
  }).id;
@@ -1301,177 +1290,19 @@ async function classifyOnchainHtlc(chain, input) {
1301
1290
  return { phase: "claimable", utxo: best };
1302
1291
  }
1303
1292
 
1304
- // src/secrets.ts
1305
- var import_base5 = require("@scure/base");
1306
- var import_sha22 = require("@noble/hashes/sha2.js");
1307
- var import_utils2 = require("@noble/hashes/utils.js");
1308
- var import_secp256k1 = require("@noble/curves/secp256k1.js");
1309
- var import_sdk6 = require("@arkade-os/sdk");
1310
- var RFQ_PREIMAGE_TAG = "Arkade-RFQ-Preimage-v1";
1311
- function buildPreimageMessage(xonly, index) {
1312
- if (xonly.length !== 32) {
1313
- throw new Error(`x-only pubkey must be 32 bytes, got ${xonly.length}`);
1314
- }
1315
- if (!Number.isInteger(index) || index < 0 || index > 4294967295) {
1316
- throw new Error(`index must be a u32, got ${index}`);
1317
- }
1318
- const tag = new TextEncoder().encode(RFQ_PREIMAGE_TAG);
1319
- const message = new Uint8Array(tag.length + 32 + 4);
1320
- message.set(tag, 0);
1321
- message.set(xonly, tag.length);
1322
- new DataView(message.buffer).setUint32(tag.length + 32, index, true);
1323
- return message;
1324
- }
1325
- var PREIMAGE_INDEX = 0;
1326
- async function deriveSwapSecrets(wallet) {
1327
- if (!(0, import_sdk6.isHDAllocationCapable)(wallet)) return void 0;
1328
- const signingDescriptor = await wallet.getNextSigningDescriptor();
1329
- if (!signingDescriptor) return void 0;
1330
- return { derivable: true, signingDescriptor };
1331
- }
1332
- function randomSwapSecrets(opts = {}) {
1333
- if (opts.preimage instanceof Uint8Array && opts.preimage.length !== 32) {
1334
- throw new Error(`preimage must be 32 bytes, got ${opts.preimage.length}`);
1335
- }
1336
- const preimage = opts.preimage instanceof Uint8Array ? opts.preimage : opts.preimage ? (0, import_utils2.randomBytes)(32) : void 0;
1337
- return {
1338
- derivable: false,
1339
- senderPrivateKey: import_secp256k1.schnorr.utils.randomSecretKey(),
1340
- ...preimage ? { preimage } : {}
1341
- };
1342
- }
1343
- function rfqSecretsToRecord(secrets) {
1344
- if (secrets.derivable) {
1345
- return {
1346
- signingDescriptor: secrets.signingDescriptor,
1347
- ...secrets.preimage ? { preimageHex: import_base5.hex.encode(secrets.preimage) } : {}
1348
- };
1349
- }
1350
- return {
1351
- fallbackSecrets: {
1352
- version: 1,
1353
- type: "stored",
1354
- senderPrivateKeyHex: import_base5.hex.encode(secrets.senderPrivateKey),
1355
- ...secrets.preimage ? { preimageHex: import_base5.hex.encode(secrets.preimage) } : {}
1356
- }
1357
- };
1358
- }
1359
- function rfqSecretsOfRecord(record) {
1360
- if (record.signingDescriptor) {
1361
- return {
1362
- derivable: true,
1363
- signingDescriptor: record.signingDescriptor,
1364
- ...record.preimageHex ? { preimage: decodeHex32(record.preimageHex, "preimageHex") } : {}
1365
- };
1366
- }
1367
- const fallback = record.fallbackSecrets;
1368
- if (!fallback) return void 0;
1369
- if (fallback.version !== 1 || fallback.type !== "stored") {
1370
- throw new Error("unsupported RFQ fallback secrets record");
1371
- }
1372
- return {
1373
- derivable: false,
1374
- senderPrivateKey: decodeHex32(fallback.senderPrivateKeyHex, "senderPrivateKeyHex"),
1375
- ...fallback.preimageHex ? { preimage: decodeHex32(fallback.preimageHex, "preimageHex") } : {}
1376
- };
1377
- }
1378
- function decodeHex32(value, label) {
1379
- const bytes = import_base5.hex.decode(value);
1380
- if (bytes.length !== 32) {
1381
- throw new Error(label + " must be 32 bytes, got " + bytes.length);
1382
- }
1383
- return bytes;
1384
- }
1385
- async function adoptSwapDescriptor(wallet, signingDescriptor) {
1386
- if (!(0, import_sdk6.isHDAllocationCapable)(wallet)) return;
1387
- await wallet.advanceSigningDescriptorWatermark(signingDescriptor);
1388
- }
1389
- var RefundNotLocallyPossibleError = class extends Error {
1390
- constructor(reason, message, options) {
1391
- super(message, options);
1392
- this.reason = reason;
1393
- }
1394
- reason;
1395
- name = "RefundNotLocallyPossibleError";
1396
- };
1397
- async function senderIdentityForRfqSecrets(wallet, secrets) {
1398
- if (!secrets.derivable) return import_sdk6.SingleKey.fromPrivateKey(secrets.senderPrivateKey);
1399
- const signer = (0, import_sdk6.isHDWalletCapable)(wallet) ? await wallet.signerForDescriptor(secrets.signingDescriptor) : void 0;
1400
- if (!signer || !isDeterministicSigner(signer)) {
1401
- throw new RefundNotLocallyPossibleError(
1402
- "foreign-descriptor",
1403
- `this wallet cannot derive ${secrets.signingDescriptor}; the swap was created on another wallet`
1404
- );
1405
- }
1406
- return signer;
1407
- }
1408
- async function senderIdentityForSwapRecord(wallet, record) {
1409
- let secrets;
1410
- try {
1411
- secrets = rfqSecretsOfRecord(record);
1412
- } catch (error) {
1413
- throw new RefundNotLocallyPossibleError(
1414
- "unreadable-secrets",
1415
- error instanceof Error ? error.message : String(error),
1416
- // the record's own diagnosis, kept for a caller that wants more
1417
- // than the message
1418
- { cause: error }
1419
- );
1420
- }
1421
- if (!secrets) {
1422
- throw new RefundNotLocallyPossibleError(
1423
- "no-secrets",
1424
- "this swap record carries no signing descriptor and no fallback secrets"
1425
- );
1426
- }
1427
- return senderIdentityForRfqSecrets(wallet, secrets);
1428
- }
1429
- async function senderPubkeyForRfqSecrets(wallet, secrets) {
1430
- if (!secrets.derivable) return import_secp256k1.schnorr.getPublicKey(secrets.senderPrivateKey);
1431
- return (await senderIdentityForRfqSecrets(wallet, secrets)).xOnlyPublicKey();
1432
- }
1433
- function isDeterministicSigner(value) {
1434
- if (typeof value !== "object" || value === null) return false;
1435
- const v = value;
1436
- return typeof v.signSchnorrDeterministic === "function" && typeof v.xOnlyPublicKey === "function";
1437
- }
1438
- async function derivePreimage(signer) {
1439
- const xonly = await signer.xOnlyPublicKey();
1440
- const message = buildPreimageMessage(xonly, PREIMAGE_INDEX);
1441
- return (0, import_sha22.sha256)(await signer.signSchnorrDeterministic((0, import_sha22.sha256)(message)));
1442
- }
1443
- async function preimageForRfqSecrets(wallet, secrets) {
1444
- if (!secrets.derivable) {
1445
- if (!secrets.preimage) throw new Error("this swap carries no stored preimage");
1446
- return secrets.preimage;
1447
- }
1448
- if (secrets.preimage) return secrets.preimage;
1449
- const signer = await senderIdentityForRfqSecrets(wallet, secrets);
1450
- if (!isDeterministicSigner(signer)) {
1451
- throw new Error(
1452
- `wallet cannot sign deterministically for ${secrets.signingDescriptor}; its preimage is not derivable`
1453
- );
1454
- }
1455
- try {
1456
- return await derivePreimage(signer);
1457
- } catch (cause) {
1458
- throw new Error(
1459
- `wallet cannot sign deterministically for ${secrets.signingDescriptor}; its preimage is not derivable`,
1460
- { cause }
1461
- );
1462
- }
1463
- }
1293
+ // src/rfq.ts
1294
+ var import_sdk8 = require("@arkade-os/sdk");
1464
1295
 
1465
1296
  // src/claimPacket.ts
1466
1297
  var import_base6 = require("@scure/base");
1467
- var import_secp256k12 = require("@noble/curves/secp256k1.js");
1298
+ var import_secp256k1 = require("@noble/curves/secp256k1.js");
1468
1299
  var import_hkdf = require("@noble/hashes/hkdf.js");
1469
- var import_sha23 = require("@noble/hashes/sha2.js");
1300
+ var import_sha22 = require("@noble/hashes/sha2.js");
1470
1301
  var HKDF_INFO = new TextEncoder().encode("covclaimd/preimage/v1");
1471
1302
  async function sealClaimPacket(input) {
1472
1303
  return sealWithEntropy(
1473
1304
  input,
1474
- import_secp256k12.secp256k1.utils.randomSecretKey(),
1305
+ import_secp256k1.secp256k1.utils.randomSecretKey(),
1475
1306
  crypto.getRandomValues(new Uint8Array(12))
1476
1307
  );
1477
1308
  }
@@ -1480,9 +1311,9 @@ async function sealWithEntropy(input, ephemeralKey, nonce) {
1480
1311
  if (input.covclaimdPubkey.length !== 33) {
1481
1312
  throw new Error("covclaimd pubkey must be 33-byte compressed");
1482
1313
  }
1483
- const ephemeralPub = import_secp256k12.secp256k1.getPublicKey(ephemeralKey, true);
1484
- const sharedX = import_secp256k12.secp256k1.getSharedSecret(ephemeralKey, input.covclaimdPubkey, true).subarray(1);
1485
- const key = (0, import_hkdf.hkdf)(import_sha23.sha256, sharedX, ephemeralPub, HKDF_INFO, 32);
1314
+ const ephemeralPub = import_secp256k1.secp256k1.getPublicKey(ephemeralKey, true);
1315
+ const sharedX = import_secp256k1.secp256k1.getSharedSecret(ephemeralKey, input.covclaimdPubkey, true).subarray(1);
1316
+ const key = (0, import_hkdf.hkdf)(import_sha22.sha256, sharedX, ephemeralPub, HKDF_INFO, 32);
1486
1317
  if (nonce.length !== 12) throw new Error("nonce must be 12 bytes");
1487
1318
  const aesKey = await crypto.subtle.importKey("raw", key, "AES-GCM", false, [
1488
1319
  "encrypt"
@@ -1507,7 +1338,7 @@ async function sealWithEntropy(input, ephemeralKey, nonce) {
1507
1338
 
1508
1339
  // src/lockupContract.ts
1509
1340
  var import_base7 = require("@scure/base");
1510
- var import_sdk7 = require("@arkade-os/sdk");
1341
+ var import_sdk6 = require("@arkade-os/sdk");
1511
1342
  var SWAP_LOCKUP_CONTRACT_TYPE = "vhtlc-v2";
1512
1343
  var SWAP_LOCKUP_CONTRACT_LABEL = "Arkade RFQ swap lockup";
1513
1344
  var SWAP_LOCKUP_CONTRACT_KIND = "rfq-swap-lockup";
@@ -1529,7 +1360,7 @@ async function registerLockupContract(contracts, script, address) {
1529
1360
  try {
1530
1361
  await contracts.createContract({
1531
1362
  type: SWAP_LOCKUP_CONTRACT_TYPE,
1532
- params: import_sdk7.VHTLCV2ContractHandler.serializeParams(script.options),
1363
+ params: import_sdk6.VHTLCV2ContractHandler.serializeParams(script.options),
1533
1364
  script: import_base7.hex.encode(script.pkScript),
1534
1365
  address,
1535
1366
  label: SWAP_LOCKUP_CONTRACT_LABEL,
@@ -1541,7 +1372,7 @@ async function registerLockupContract(contracts, script, address) {
1541
1372
  }
1542
1373
 
1543
1374
  // src/rfq.ts
1544
- var xOnly2 = (key, label) => {
1375
+ var xOnly = (key, label) => {
1545
1376
  if (key.length === 32) return key;
1546
1377
  if (key.length !== 33 || key[0] !== 2 && key[0] !== 3) {
1547
1378
  throw new Error(`${label} is not a compressed or x-only public key`);
@@ -1811,7 +1642,7 @@ function lightningSendVtxoScript(params) {
1811
1642
  type: "seconds",
1812
1643
  value: BigInt(value)
1813
1644
  });
1814
- return new import_sdk8.VHTLC.ScriptV2({
1645
+ return new import_sdk7.VHTLC.ScriptV2({
1815
1646
  sender: params.senderPubkey,
1816
1647
  receiver: params.solverPubkey,
1817
1648
  server: params.serverPubkey,
@@ -1832,17 +1663,12 @@ function lightningSendVtxoScript(params) {
1832
1663
  }
1833
1664
  });
1834
1665
  }
1835
- async function requestLightningSend(wallet, arkServerUrl, emulatorPubkey, transport, params) {
1666
+ async function requestLightningSend(wallet, arkServerUrl, transport, params) {
1836
1667
  const rfqId = params.rfqId ?? newRfqId();
1837
- const secrets = await deriveSwapSecrets(wallet) ?? randomSwapSecrets();
1838
- if (!secrets.derivable) {
1839
- console.warn(
1840
- "[swap] wallet cannot allocate an HD descriptor: the sender key is random and MUST be persisted before funding"
1841
- );
1842
- }
1843
- const senderPubkey = await senderPubkeyForRfqSecrets(wallet, secrets);
1668
+ const secrets = await (0, import_sdk8.provisionRefundKey)(wallet);
1669
+ const senderPubkey = secrets.pubkey;
1844
1670
  const [info, refundAddress] = await Promise.all([
1845
- new import_sdk8.RestArkProvider(arkServerUrl).getInfo(),
1671
+ new import_sdk7.RestArkProvider(arkServerUrl).getInfo(),
1846
1672
  wallet.getAddress()
1847
1673
  ]);
1848
1674
  const quote = await transport.requestQuote(
@@ -1865,19 +1691,23 @@ async function requestLightningSend(wallet, arkServerUrl, emulatorPubkey, transp
1865
1691
  `quote from_amount ${quote.from_amount} is below the invoice amount \u2014 a negative spread is not a quote`
1866
1692
  );
1867
1693
  }
1868
- const serverPubkey = xOnly2(import_base8.hex.decode(info.signerPubkey), "ark signer key");
1694
+ const serverPubkey = xOnly(import_base8.hex.decode(info.signerPubkey), "ark signer key");
1695
+ const network = (0, import_sdk7.getNetwork)(info.network);
1869
1696
  const script = lightningSendVtxoScript({
1870
- solverPubkey: xOnly2(import_base8.hex.decode(quote.solver_pubkey), "solver key"),
1697
+ solverPubkey: xOnly(import_base8.hex.decode(quote.solver_pubkey), "solver key"),
1871
1698
  refundLocktime: quote.refund_locktime,
1872
1699
  serverPubkey,
1873
1700
  paymentHash: params.invoice.paymentHash,
1874
1701
  claimDelay: unilateralClaimDelay(Number(info.unilateralExitDelay)),
1875
- emulatorPubkey: xOnly2(emulatorPubkey, "emulator pubkey"),
1702
+ emulatorPubkey: xOnly(
1703
+ import_base8.hex.decode((0, import_sdk7.resolveEmulatorPubkey)(network, params.emulatorPubkey)),
1704
+ "emulator signer key"
1705
+ ),
1876
1706
  senderPubkey,
1877
1707
  receiverPkScript: solverHex(receiverPkScriptHex, "profile.receiver_pk_script"),
1878
- refundPkScript: import_sdk8.ArkAddress.decode(refundAddress).pkScript
1708
+ refundPkScript: import_sdk7.ArkAddress.decode(refundAddress).pkScript
1879
1709
  });
1880
- const address = script.address((0, import_sdk8.getNetwork)(info.network).hrp, serverPubkey).encode();
1710
+ const address = script.address(network.hrp, serverPubkey).encode();
1881
1711
  verifyLockupAddress(quote, address);
1882
1712
  assertFundable({
1883
1713
  quote,
@@ -1962,7 +1792,7 @@ function deriveOnchainSend(input) {
1962
1792
  throw new Error("onchain-send quote is missing a binding field");
1963
1793
  }
1964
1794
  const script = lightningSendVtxoScript({
1965
- solverPubkey: xOnly2(import_base8.hex.decode(quote.solver_pubkey), "solver key"),
1795
+ solverPubkey: xOnly(import_base8.hex.decode(quote.solver_pubkey), "solver key"),
1966
1796
  refundLocktime,
1967
1797
  serverPubkey: input.serverPubkey,
1968
1798
  paymentHash: input.paymentHash,
@@ -1970,7 +1800,7 @@ function deriveOnchainSend(input) {
1970
1800
  emulatorPubkey: input.emulatorPubkey,
1971
1801
  senderPubkey: input.senderPubkey,
1972
1802
  receiverPkScript: solverHex(receiverPkScriptHex, "profile.receiver_pk_script"),
1973
- refundPkScript: import_sdk8.ArkAddress.decode(input.refundAddress).pkScript
1803
+ refundPkScript: import_sdk7.ArkAddress.decode(input.refundAddress).pkScript
1974
1804
  });
1975
1805
  const address = script.address(input.hrp, input.serverPubkey).encode();
1976
1806
  verifyLockupAddress(quote, address);
@@ -1978,7 +1808,7 @@ function deriveOnchainSend(input) {
1978
1808
  {
1979
1809
  paymentHash: input.paymentHash,
1980
1810
  claimKey: input.payoutPubkey,
1981
- refundKey: xOnly2(import_base8.hex.decode(htlcPubkey), "solver L1 htlc key"),
1811
+ refundKey: xOnly(import_base8.hex.decode(htlcPubkey), "solver L1 htlc key"),
1982
1812
  refundLocktime: htlcLocktime
1983
1813
  },
1984
1814
  input.l1Network
@@ -1994,27 +1824,18 @@ function deriveOnchainSend(input) {
1994
1824
  minConfirmations
1995
1825
  };
1996
1826
  }
1997
- async function requestOnchainSend(wallet, arkServerUrl, emulatorPubkey, transport, params) {
1827
+ async function requestOnchainSend(wallet, arkServerUrl, transport, params) {
1998
1828
  const rfqId = params.rfqId ?? newRfqId();
1999
- if (params.preimage && params.preimage.length !== 32) {
2000
- throw new Error(`preimage must be 32 bytes, got ${params.preimage.length}`);
2001
- }
2002
- const derivedSecrets = await deriveSwapSecrets(wallet);
2003
- const secrets = derivedSecrets ? params.preimage ? { ...derivedSecrets, preimage: params.preimage } : derivedSecrets : randomSwapSecrets({ preimage: params.preimage ?? true });
2004
- if (!secrets.derivable) {
2005
- console.warn(
2006
- params.preimage ? "[swap] this swap's sender key is random; the supplied preimage and sender key MUST be persisted before funding" : "[swap] this swap's preimage and sender key are random and MUST be persisted before funding"
2007
- );
2008
- } else if (params.preimage) {
1829
+ const secrets = await (0, import_sdk8.provisionClaimSecret)(wallet, { preimage: params.preimage });
1830
+ if (secrets.mustPersistPreimage) {
2009
1831
  console.warn(
2010
- "[swap] this swap's preimage was supplied by the caller and MUST be persisted with the signing descriptor before funding"
1832
+ "[swap] this swap's preimage cannot be re-derived from the seed and MUST be persisted with the record before funding"
2011
1833
  );
2012
1834
  }
2013
- const preimage = await preimageForRfqSecrets(wallet, secrets);
2014
- const paymentHash = paymentHashOf(preimage);
2015
- const senderPubkey = await senderPubkeyForRfqSecrets(wallet, secrets);
1835
+ const paymentHash = import_base8.hex.encode(secrets.paymentHash);
1836
+ const senderPubkey = secrets.pubkey;
2016
1837
  const [info, refundAddress] = await Promise.all([
2017
- new import_sdk8.RestArkProvider(arkServerUrl).getInfo(),
1838
+ new import_sdk7.RestArkProvider(arkServerUrl).getInfo(),
2018
1839
  wallet.getAddress()
2019
1840
  ]);
2020
1841
  const quote = await transport.requestQuote(
@@ -2028,14 +1849,18 @@ async function requestOnchainSend(wallet, arkServerUrl, emulatorPubkey, transpor
2028
1849
  amountSide: params.amountSide
2029
1850
  })
2030
1851
  );
1852
+ const network = (0, import_sdk7.getNetwork)(info.network);
2031
1853
  const derived = deriveOnchainSend({
2032
1854
  quote,
2033
1855
  paymentHash,
2034
1856
  payoutPubkey: params.payoutPubkey,
2035
- serverPubkey: xOnly2(import_base8.hex.decode(info.signerPubkey), "ark signer key"),
2036
- emulatorPubkey: xOnly2(emulatorPubkey, "emulator pubkey"),
1857
+ serverPubkey: xOnly(import_base8.hex.decode(info.signerPubkey), "ark signer key"),
1858
+ emulatorPubkey: xOnly(
1859
+ import_base8.hex.decode((0, import_sdk7.resolveEmulatorPubkey)(network, params.emulatorPubkey)),
1860
+ "emulator signer key"
1861
+ ),
2037
1862
  claimDelay: unilateralClaimDelay(Number(info.unilateralExitDelay)),
2038
- hrp: (0, import_sdk8.getNetwork)(info.network).hrp,
1863
+ hrp: network.hrp,
2039
1864
  l1Network: l1NetworkFromArk(info.network),
2040
1865
  refundAddress,
2041
1866
  senderPubkey
@@ -2139,7 +1964,7 @@ function receiveVtxoScript(params) {
2139
1964
  type: "seconds",
2140
1965
  value: BigInt(value)
2141
1966
  });
2142
- return new import_sdk8.VHTLC.ScriptV2({
1967
+ return new import_sdk7.VHTLC.ScriptV2({
2143
1968
  sender: params.solverPubkey,
2144
1969
  receiver: params.payoutPubkey,
2145
1970
  server: params.serverPubkey,
@@ -2170,7 +1995,7 @@ function deriveLightningReceive(input) {
2170
1995
  throw new Error("lightning-receive quote is missing a binding field");
2171
1996
  }
2172
1997
  const script = receiveVtxoScript({
2173
- solverPubkey: xOnly2(import_base8.hex.decode(quote.solver_pubkey), "solver key"),
1998
+ solverPubkey: xOnly(import_base8.hex.decode(quote.solver_pubkey), "solver key"),
2174
1999
  refundLocktime,
2175
2000
  serverPubkey: input.serverPubkey,
2176
2001
  paymentHash: input.paymentHash,
@@ -2178,25 +2003,25 @@ function deriveLightningReceive(input) {
2178
2003
  emulatorPubkey: input.emulatorPubkey,
2179
2004
  solverRefundPkScript: solverHex(solverRefundPkScriptHex, "profile.solver_refund_pk_script"),
2180
2005
  payoutPubkey: input.payoutPubkey,
2181
- payoutPkScript: import_sdk8.ArkAddress.decode(input.payoutAddress).pkScript
2006
+ payoutPkScript: import_sdk7.ArkAddress.decode(input.payoutAddress).pkScript
2182
2007
  });
2183
2008
  const address = script.address(input.hrp, input.serverPubkey).encode();
2184
2009
  verifyLockupAddress(quote, address);
2185
2010
  return { address, swapPkScript: script.pkScript, script, invoice, refundLocktime };
2186
2011
  }
2187
- async function requestLightningReceive(wallet, arkServerUrl, emulatorPubkey, transport, params) {
2012
+ async function requestLightningReceive(wallet, arkServerUrl, transport, params) {
2188
2013
  const rfqId = params.rfqId ?? newRfqId();
2189
- const secrets = await deriveSwapSecrets(wallet) ?? randomSwapSecrets({ preimage: true });
2190
- if (!secrets.derivable) {
2014
+ const secrets = await (0, import_sdk8.provisionClaimSecret)(wallet);
2015
+ if (secrets.mustPersistPreimage) {
2191
2016
  console.warn(
2192
- "[swap] this swap's preimage and payout key are random and MUST be persisted before paying"
2017
+ "[swap] this swap's preimage cannot be re-derived from the seed and MUST be persisted with the record before paying"
2193
2018
  );
2194
2019
  }
2195
- const preimage = await preimageForRfqSecrets(wallet, secrets);
2196
- const paymentHash = paymentHashOf(preimage);
2197
- const payoutPubkey = await senderPubkeyForRfqSecrets(wallet, secrets);
2020
+ const preimage = secrets.preimage;
2021
+ const paymentHash = import_base8.hex.encode(secrets.paymentHash);
2022
+ const payoutPubkey = secrets.pubkey;
2198
2023
  const [info, payoutAddress] = await Promise.all([
2199
- new import_sdk8.RestArkProvider(arkServerUrl).getInfo(),
2024
+ new import_sdk7.RestArkProvider(arkServerUrl).getInfo(),
2200
2025
  wallet.getAddress()
2201
2026
  ]);
2202
2027
  const claimPacket = await sealClaimPacket({
@@ -2215,15 +2040,19 @@ async function requestLightningReceive(wallet, arkServerUrl, emulatorPubkey, tra
2215
2040
  })
2216
2041
  );
2217
2042
  assertQuotedAmount(quote, params.amountSide, params.amount);
2043
+ const network = (0, import_sdk7.getNetwork)(info.network);
2218
2044
  const derived = deriveLightningReceive({
2219
2045
  quote,
2220
2046
  paymentHash,
2221
2047
  payoutPubkey,
2222
2048
  payoutAddress,
2223
- serverPubkey: xOnly2(import_base8.hex.decode(info.signerPubkey), "ark signer key"),
2224
- emulatorPubkey: xOnly2(emulatorPubkey, "emulator pubkey"),
2049
+ serverPubkey: xOnly(import_base8.hex.decode(info.signerPubkey), "ark signer key"),
2050
+ emulatorPubkey: xOnly(
2051
+ import_base8.hex.decode((0, import_sdk7.resolveEmulatorPubkey)(network, params.emulatorPubkey)),
2052
+ "emulator signer key"
2053
+ ),
2225
2054
  claimDelay: unilateralClaimDelay(Number(info.unilateralExitDelay)),
2226
- hrp: (0, import_sdk8.getNetwork)(info.network).hrp
2055
+ hrp: network.hrp
2227
2056
  });
2228
2057
  const now = Math.floor(Date.now() / 1e3);
2229
2058
  const { payDeadline } = verifyReceiveInvoice({
@@ -2266,7 +2095,7 @@ function deriveOnchainReceive(input) {
2266
2095
  throw new Error("onchain-receive quote is missing a binding field");
2267
2096
  }
2268
2097
  const script = receiveVtxoScript({
2269
- solverPubkey: xOnly2(import_base8.hex.decode(quote.solver_pubkey), "solver key"),
2098
+ solverPubkey: xOnly(import_base8.hex.decode(quote.solver_pubkey), "solver key"),
2270
2099
  refundLocktime,
2271
2100
  serverPubkey: input.serverPubkey,
2272
2101
  paymentHash: input.paymentHash,
@@ -2274,14 +2103,14 @@ function deriveOnchainReceive(input) {
2274
2103
  emulatorPubkey: input.emulatorPubkey,
2275
2104
  solverRefundPkScript: solverHex(solverRefundPkScriptHex, "profile.solver_refund_pk_script"),
2276
2105
  payoutPubkey: input.payoutPubkey,
2277
- payoutPkScript: import_sdk8.ArkAddress.decode(input.payoutAddress).pkScript
2106
+ payoutPkScript: import_sdk7.ArkAddress.decode(input.payoutAddress).pkScript
2278
2107
  });
2279
2108
  const address = script.address(input.hrp, input.serverPubkey).encode();
2280
2109
  verifyLockupAddress(quote, address);
2281
2110
  const htlc = onchainHtlcScript(
2282
2111
  {
2283
2112
  paymentHash: input.paymentHash,
2284
- claimKey: xOnly2(import_base8.hex.decode(claimPubkey), "solver L1 claim key"),
2113
+ claimKey: xOnly(import_base8.hex.decode(claimPubkey), "solver L1 claim key"),
2285
2114
  refundKey: input.refundPubkey,
2286
2115
  refundLocktime: htlcLocktime
2287
2116
  },
@@ -2298,19 +2127,19 @@ function deriveOnchainReceive(input) {
2298
2127
  minConfirmations
2299
2128
  };
2300
2129
  }
2301
- async function requestOnchainReceive(wallet, arkServerUrl, emulatorPubkey, transport, params) {
2130
+ async function requestOnchainReceive(wallet, arkServerUrl, transport, params) {
2302
2131
  const rfqId = params.rfqId ?? newRfqId();
2303
- const secrets = await deriveSwapSecrets(wallet) ?? randomSwapSecrets({ preimage: true });
2304
- if (!secrets.derivable) {
2132
+ const secrets = await (0, import_sdk8.provisionClaimSecret)(wallet);
2133
+ if (secrets.mustPersistPreimage) {
2305
2134
  console.warn(
2306
- "[swap] this swap's preimage and payout key are random and MUST be persisted before funding"
2135
+ "[swap] this swap's preimage cannot be re-derived from the seed and MUST be persisted with the record before funding"
2307
2136
  );
2308
2137
  }
2309
- const preimage = await preimageForRfqSecrets(wallet, secrets);
2310
- const paymentHash = paymentHashOf(preimage);
2311
- const payoutPubkey = await senderPubkeyForRfqSecrets(wallet, secrets);
2138
+ const preimage = secrets.preimage;
2139
+ const paymentHash = import_base8.hex.encode(secrets.paymentHash);
2140
+ const payoutPubkey = secrets.pubkey;
2312
2141
  const [info, payoutAddress] = await Promise.all([
2313
- new import_sdk8.RestArkProvider(arkServerUrl).getInfo(),
2142
+ new import_sdk7.RestArkProvider(arkServerUrl).getInfo(),
2314
2143
  wallet.getAddress()
2315
2144
  ]);
2316
2145
  const claimPacket = await sealClaimPacket({
@@ -2330,16 +2159,20 @@ async function requestOnchainReceive(wallet, arkServerUrl, emulatorPubkey, trans
2330
2159
  })
2331
2160
  );
2332
2161
  assertQuotedAmount(quote, params.amountSide, params.amount);
2162
+ const network = (0, import_sdk7.getNetwork)(info.network);
2333
2163
  const derived = deriveOnchainReceive({
2334
2164
  quote,
2335
2165
  paymentHash,
2336
2166
  payoutPubkey,
2337
2167
  payoutAddress,
2338
2168
  refundPubkey: params.refundPubkey,
2339
- serverPubkey: xOnly2(import_base8.hex.decode(info.signerPubkey), "ark signer key"),
2340
- emulatorPubkey: xOnly2(emulatorPubkey, "emulator pubkey"),
2169
+ serverPubkey: xOnly(import_base8.hex.decode(info.signerPubkey), "ark signer key"),
2170
+ emulatorPubkey: xOnly(
2171
+ import_base8.hex.decode((0, import_sdk7.resolveEmulatorPubkey)(network, params.emulatorPubkey)),
2172
+ "emulator signer key"
2173
+ ),
2341
2174
  claimDelay: unilateralClaimDelay(Number(info.unilateralExitDelay)),
2342
- hrp: (0, import_sdk8.getNetwork)(info.network).hrp,
2175
+ hrp: network.hrp,
2343
2176
  l1Network: l1NetworkFromArk(info.network)
2344
2177
  });
2345
2178
  assertFundable({
@@ -2374,12 +2207,12 @@ async function requestOnchainReceive(wallet, arkServerUrl, emulatorPubkey, trans
2374
2207
  // src/claim.ts
2375
2208
  var import_base10 = require("@scure/base");
2376
2209
  var import_legacy3 = require("@noble/hashes/legacy.js");
2377
- var import_sha25 = require("@noble/hashes/sha2.js");
2210
+ var import_sha24 = require("@noble/hashes/sha2.js");
2378
2211
  var import_sdk10 = require("@arkade-os/sdk");
2379
2212
 
2380
2213
  // src/refund.ts
2381
2214
  var import_base9 = require("@scure/base");
2382
- var import_sha24 = require("@noble/hashes/sha2.js");
2215
+ var import_sha23 = require("@noble/hashes/sha2.js");
2383
2216
  var import_sdk9 = require("@arkade-os/sdk");
2384
2217
  var sleep2 = (ms) => new Promise((resolve) => setTimeout(resolve, ms));
2385
2218
  var isRfqTerminal = (state) => RFQ_TERMINAL_STATES.includes(state);
@@ -2452,7 +2285,7 @@ async function findLockupVtxos(indexer, swapPkScript) {
2452
2285
  }
2453
2286
  return out;
2454
2287
  }
2455
- var hashesTo = (candidate, paymentHash) => import_base9.hex.encode((0, import_sha24.sha256)(candidate)) === paymentHash;
2288
+ var hashesTo = (candidate, paymentHash) => import_base9.hex.encode((0, import_sha23.sha256)(candidate)) === paymentHash;
2456
2289
  var candidateWitnessItems = (tx, inputIndex) => [
2457
2290
  ...(0, import_sdk9.getArkPsbtFields)(tx, inputIndex, import_sdk9.ConditionWitness).flat(),
2458
2291
  ...tx.getInput(inputIndex).finalScriptWitness ?? []
@@ -2621,7 +2454,7 @@ async function pushClaim(ark, input) {
2621
2454
  }
2622
2455
  }
2623
2456
  const committed = input.script.options.preimageHash;
2624
- if (import_base10.hex.encode((0, import_legacy3.ripemd160)((0, import_sha25.sha256)(input.preimage))) !== import_base10.hex.encode(committed)) {
2457
+ if (import_base10.hex.encode((0, import_legacy3.ripemd160)((0, import_sha24.sha256)(input.preimage))) !== import_base10.hex.encode(committed)) {
2625
2458
  throw new Error("preimage does not match the covenant's payment hash");
2626
2459
  }
2627
2460
  const info = await ark.getInfo();
@@ -2680,6 +2513,44 @@ async function claimReceiveLockup(indexer, ark, input) {
2680
2513
  });
2681
2514
  }
2682
2515
 
2516
+ // src/refundBlocked.ts
2517
+ var import_sdk11 = require("@arkade-os/sdk");
2518
+ var RefundNotLocallyPossibleError = class extends Error {
2519
+ constructor(reason, message, options) {
2520
+ super(message, options);
2521
+ this.reason = reason;
2522
+ }
2523
+ reason;
2524
+ name = "RefundNotLocallyPossibleError";
2525
+ };
2526
+ async function senderIdentityForSwapRecord(wallet, record) {
2527
+ if (!record.signingDescriptor) {
2528
+ throw new RefundNotLocallyPossibleError(
2529
+ "no-secrets",
2530
+ "this swap record carries no signing descriptor"
2531
+ );
2532
+ }
2533
+ try {
2534
+ return await (0, import_sdk11.contractSigner)(wallet, record.signingDescriptor);
2535
+ } catch (cause) {
2536
+ if (cause instanceof import_sdk11.WalletCannotSignError) {
2537
+ throw new RefundNotLocallyPossibleError(
2538
+ "unsignable-wallet",
2539
+ `this wallet holds ${record.signingDescriptor} but cannot sign with it; attach its signer`,
2540
+ { cause }
2541
+ );
2542
+ }
2543
+ if (cause instanceof import_sdk11.ForeignDescriptorError) {
2544
+ throw new RefundNotLocallyPossibleError(
2545
+ "foreign-descriptor",
2546
+ `this wallet cannot derive ${record.signingDescriptor}; the swap was created on another wallet`,
2547
+ { cause }
2548
+ );
2549
+ }
2550
+ throw cause;
2551
+ }
2552
+ }
2553
+
2683
2554
  // src/swapManager.ts
2684
2555
  var import_base11 = require("@scure/base");
2685
2556
  var RFQ_SWAP_TERMINAL_STATES = ["settled", "refunded", "failed"];
@@ -3473,7 +3344,6 @@ var outpointKey = (vtxo) => `${vtxo.txid}:${vtxo.vout}`;
3473
3344
  ONCHAIN_SEND_PAIR,
3474
3345
  QUOTE_OPTIONS,
3475
3346
  REFUND_MTP_LAG_SECONDS,
3476
- RFQ_PREIMAGE_TAG,
3477
3347
  RFQ_RESOLVED_STATES,
3478
3348
  RFQ_SWAP_TERMINAL_STATES,
3479
3349
  RFQ_TERMINAL_STATES,
@@ -3484,7 +3354,6 @@ var outpointKey = (vtxo) => `${vtxo.txid}:${vtxo.vout}`;
3484
3354
  SWAP_LOCKUP_CONTRACT_TYPE,
3485
3355
  SwapRefusal,
3486
3356
  addAssetSwap,
3487
- adoptSwapDescriptor,
3488
3357
  arkadeSwapRequest,
3489
3358
  assertFundable,
3490
3359
  assertReceivable,
@@ -3493,7 +3362,6 @@ var outpointKey = (vtxo) => `${vtxo.txid}:${vtxo.vout}`;
3493
3362
  awaitRfqResolution,
3494
3363
  buildHtlcClaim,
3495
3364
  buildHtlcRefund,
3496
- buildPreimageMessage,
3497
3365
  cancelOffer,
3498
3366
  claimOnchainFill,
3499
3367
  claimReceiveLockup,
@@ -3505,8 +3373,6 @@ var outpointKey = (vtxo) => `${vtxo.txid}:${vtxo.vout}`;
3505
3373
  deriveLightningReceive,
3506
3374
  deriveOnchainReceive,
3507
3375
  deriveOnchainSend,
3508
- derivePreimage,
3509
- deriveSwapSecrets,
3510
3376
  discoverMarkets,
3511
3377
  encodeOffer,
3512
3378
  extractPreimage,
@@ -3515,7 +3381,6 @@ var outpointKey = (vtxo) => `${vtxo.txid}:${vtxo.vout}`;
3515
3381
  getAssetSwaps,
3516
3382
  getAssetSwapsOrThrow,
3517
3383
  httpTransport,
3518
- isDeterministicSigner,
3519
3384
  isRfqSwapTerminal,
3520
3385
  isRfqTerminal,
3521
3386
  lightningReceiveRequest,
@@ -3531,10 +3396,8 @@ var outpointKey = (vtxo) => `${vtxo.txid}:${vtxo.vout}`;
3531
3396
  onchainReceiveRequest,
3532
3397
  onchainSendRequest,
3533
3398
  paymentHashOf,
3534
- preimageForRfqSecrets,
3535
3399
  pushClaim,
3536
3400
  pushRefundWithoutReceiver,
3537
- randomSwapSecrets,
3538
3401
  readLockupFate,
3539
3402
  receiveVtxoScript,
3540
3403
  refundIfUnresolved,
@@ -3547,15 +3410,12 @@ var outpointKey = (vtxo) => `${vtxo.txid}:${vtxo.vout}`;
3547
3410
  restoreAssetSwaps,
3548
3411
  retireSettledOfferContracts,
3549
3412
  rfqPair,
3550
- rfqSecretsOfRecord,
3551
- rfqSecretsToRecord,
3552
3413
  sealClaimPacket,
3553
- senderIdentityForRfqSecrets,
3554
3414
  senderIdentityForSwapRecord,
3555
- senderPubkeyForRfqSecrets,
3556
3415
  spendTxidsOf,
3557
3416
  spendUpdate,
3558
3417
  swapPrograms,
3418
+ swapSecretsToRecord,
3559
3419
  unilateralClaimDelay,
3560
3420
  unilateralRefundDelay,
3561
3421
  unilateralRefundWithoutReceiverDelay,