@arkade-os/swap 0.0.3 → 0.0.5

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.
@@ -204,176 +204,11 @@ async function classifyOnchainHtlc(chain, input) {
204
204
  return { phase: "claimable", utxo: best };
205
205
  }
206
206
 
207
- // src/secrets.ts
208
- import { hex as hex2 } from "@scure/base";
209
- import { sha256 as sha2562 } from "@noble/hashes/sha2.js";
210
- import { randomBytes } from "@noble/hashes/utils.js";
211
- import { schnorr } from "@noble/curves/secp256k1.js";
212
- import {
213
- SingleKey,
214
- isHDAllocationCapable,
215
- isHDWalletCapable
216
- } from "@arkade-os/sdk";
217
- var RFQ_PREIMAGE_TAG = "Arkade-RFQ-Preimage-v1";
218
- function buildPreimageMessage(xonly, index) {
219
- if (xonly.length !== 32) {
220
- throw new Error(`x-only pubkey must be 32 bytes, got ${xonly.length}`);
221
- }
222
- if (!Number.isInteger(index) || index < 0 || index > 4294967295) {
223
- throw new Error(`index must be a u32, got ${index}`);
224
- }
225
- const tag = new TextEncoder().encode(RFQ_PREIMAGE_TAG);
226
- const message = new Uint8Array(tag.length + 32 + 4);
227
- message.set(tag, 0);
228
- message.set(xonly, tag.length);
229
- new DataView(message.buffer).setUint32(tag.length + 32, index, true);
230
- return message;
231
- }
232
- var PREIMAGE_INDEX = 0;
233
- async function deriveSwapSecrets(wallet) {
234
- if (!isHDAllocationCapable(wallet)) return void 0;
235
- const signingDescriptor = await wallet.getNextSigningDescriptor();
236
- if (!signingDescriptor) return void 0;
237
- return { derivable: true, signingDescriptor };
238
- }
239
- function randomSwapSecrets(opts = {}) {
240
- if (opts.preimage instanceof Uint8Array && opts.preimage.length !== 32) {
241
- throw new Error(`preimage must be 32 bytes, got ${opts.preimage.length}`);
242
- }
243
- const preimage = opts.preimage instanceof Uint8Array ? opts.preimage : opts.preimage ? randomBytes(32) : void 0;
244
- return {
245
- derivable: false,
246
- senderPrivateKey: schnorr.utils.randomSecretKey(),
247
- ...preimage ? { preimage } : {}
248
- };
249
- }
250
- function rfqSecretsToRecord(secrets) {
251
- if (secrets.derivable) {
252
- return {
253
- signingDescriptor: secrets.signingDescriptor,
254
- ...secrets.preimage ? { preimageHex: hex2.encode(secrets.preimage) } : {}
255
- };
256
- }
257
- return {
258
- fallbackSecrets: {
259
- version: 1,
260
- type: "stored",
261
- senderPrivateKeyHex: hex2.encode(secrets.senderPrivateKey),
262
- ...secrets.preimage ? { preimageHex: hex2.encode(secrets.preimage) } : {}
263
- }
264
- };
265
- }
266
- function rfqSecretsOfRecord(record) {
267
- if (record.signingDescriptor) {
268
- return {
269
- derivable: true,
270
- signingDescriptor: record.signingDescriptor,
271
- ...record.preimageHex ? { preimage: decodeHex32(record.preimageHex, "preimageHex") } : {}
272
- };
273
- }
274
- const fallback = record.fallbackSecrets;
275
- if (!fallback) return void 0;
276
- if (fallback.version !== 1 || fallback.type !== "stored") {
277
- throw new Error("unsupported RFQ fallback secrets record");
278
- }
279
- return {
280
- derivable: false,
281
- senderPrivateKey: decodeHex32(fallback.senderPrivateKeyHex, "senderPrivateKeyHex"),
282
- ...fallback.preimageHex ? { preimage: decodeHex32(fallback.preimageHex, "preimageHex") } : {}
283
- };
284
- }
285
- function decodeHex32(value, label) {
286
- const bytes = hex2.decode(value);
287
- if (bytes.length !== 32) {
288
- throw new Error(label + " must be 32 bytes, got " + bytes.length);
289
- }
290
- return bytes;
291
- }
292
- async function adoptSwapDescriptor(wallet, signingDescriptor) {
293
- if (!isHDAllocationCapable(wallet)) return;
294
- await wallet.advanceSigningDescriptorWatermark(signingDescriptor);
295
- }
296
- var RefundNotLocallyPossibleError = class extends Error {
297
- constructor(reason, message, options) {
298
- super(message, options);
299
- this.reason = reason;
300
- }
301
- reason;
302
- name = "RefundNotLocallyPossibleError";
303
- };
304
- async function senderIdentityForRfqSecrets(wallet, secrets) {
305
- if (!secrets.derivable) return SingleKey.fromPrivateKey(secrets.senderPrivateKey);
306
- const signer = isHDWalletCapable(wallet) ? await wallet.signerForDescriptor(secrets.signingDescriptor) : void 0;
307
- if (!signer || !isDeterministicSigner(signer)) {
308
- throw new RefundNotLocallyPossibleError(
309
- "foreign-descriptor",
310
- `this wallet cannot derive ${secrets.signingDescriptor}; the swap was created on another wallet`
311
- );
312
- }
313
- return signer;
314
- }
315
- async function senderIdentityForSwapRecord(wallet, record) {
316
- let secrets;
317
- try {
318
- secrets = rfqSecretsOfRecord(record);
319
- } catch (error) {
320
- throw new RefundNotLocallyPossibleError(
321
- "unreadable-secrets",
322
- error instanceof Error ? error.message : String(error),
323
- // the record's own diagnosis, kept for a caller that wants more
324
- // than the message
325
- { cause: error }
326
- );
327
- }
328
- if (!secrets) {
329
- throw new RefundNotLocallyPossibleError(
330
- "no-secrets",
331
- "this swap record carries no signing descriptor and no fallback secrets"
332
- );
333
- }
334
- return senderIdentityForRfqSecrets(wallet, secrets);
335
- }
336
- async function senderPubkeyForRfqSecrets(wallet, secrets) {
337
- if (!secrets.derivable) return schnorr.getPublicKey(secrets.senderPrivateKey);
338
- return (await senderIdentityForRfqSecrets(wallet, secrets)).xOnlyPublicKey();
339
- }
340
- function isDeterministicSigner(value) {
341
- if (typeof value !== "object" || value === null) return false;
342
- const v = value;
343
- return typeof v.signSchnorrDeterministic === "function" && typeof v.xOnlyPublicKey === "function";
344
- }
345
- async function derivePreimage(signer) {
346
- const xonly = await signer.xOnlyPublicKey();
347
- const message = buildPreimageMessage(xonly, PREIMAGE_INDEX);
348
- return sha2562(await signer.signSchnorrDeterministic(sha2562(message)));
349
- }
350
- async function preimageForRfqSecrets(wallet, secrets) {
351
- if (!secrets.derivable) {
352
- if (!secrets.preimage) throw new Error("this swap carries no stored preimage");
353
- return secrets.preimage;
354
- }
355
- if (secrets.preimage) return secrets.preimage;
356
- const signer = await senderIdentityForRfqSecrets(wallet, secrets);
357
- if (!isDeterministicSigner(signer)) {
358
- throw new Error(
359
- `wallet cannot sign deterministically for ${secrets.signingDescriptor}; its preimage is not derivable`
360
- );
361
- }
362
- try {
363
- return await derivePreimage(signer);
364
- } catch (cause) {
365
- throw new Error(
366
- `wallet cannot sign deterministically for ${secrets.signingDescriptor}; its preimage is not derivable`,
367
- { cause }
368
- );
369
- }
370
- }
371
-
372
207
  // src/claimPacket.ts
373
208
  import { base64 } from "@scure/base";
374
209
  import { secp256k1 } from "@noble/curves/secp256k1.js";
375
210
  import { hkdf } from "@noble/hashes/hkdf.js";
376
- import { sha256 as sha2563 } from "@noble/hashes/sha2.js";
211
+ import { sha256 as sha2562 } from "@noble/hashes/sha2.js";
377
212
  var HKDF_INFO = new TextEncoder().encode("covclaimd/preimage/v1");
378
213
  async function sealClaimPacket(input) {
379
214
  return sealWithEntropy(
@@ -389,7 +224,7 @@ async function sealWithEntropy(input, ephemeralKey, nonce) {
389
224
  }
390
225
  const ephemeralPub = secp256k1.getPublicKey(ephemeralKey, true);
391
226
  const sharedX = secp256k1.getSharedSecret(ephemeralKey, input.covclaimdPubkey, true).subarray(1);
392
- const key = hkdf(sha2563, sharedX, ephemeralPub, HKDF_INFO, 32);
227
+ const key = hkdf(sha2562, sharedX, ephemeralPub, HKDF_INFO, 32);
393
228
  if (nonce.length !== 12) throw new Error("nonce must be 12 bytes");
394
229
  const aesKey = await crypto.subtle.importKey("raw", key, "AES-GCM", false, [
395
230
  "encrypt"
@@ -413,7 +248,7 @@ async function sealWithEntropy(input, ephemeralKey, nonce) {
413
248
  }
414
249
 
415
250
  // src/lockupContract.ts
416
- import { hex as hex3 } from "@scure/base";
251
+ import { hex as hex2 } from "@scure/base";
417
252
  import { VHTLCV2ContractHandler } from "@arkade-os/sdk";
418
253
  var SWAP_LOCKUP_CONTRACT_TYPE = "vhtlc-v2";
419
254
  var SWAP_LOCKUP_CONTRACT_LABEL = "Arkade RFQ swap lockup";
@@ -437,7 +272,7 @@ async function registerLockupContract(contracts, script, address) {
437
272
  await contracts.createContract({
438
273
  type: SWAP_LOCKUP_CONTRACT_TYPE,
439
274
  params: VHTLCV2ContractHandler.serializeParams(script.options),
440
- script: hex3.encode(script.pkScript),
275
+ script: hex2.encode(script.pkScript),
441
276
  address,
442
277
  label: SWAP_LOCKUP_CONTRACT_LABEL,
443
278
  metadata: { genericallySpendable: false, kind: SWAP_LOCKUP_CONTRACT_KIND }
@@ -448,7 +283,7 @@ async function registerLockupContract(contracts, script, address) {
448
283
  }
449
284
 
450
285
  // src/rfq.ts
451
- import { hex as hex4 } from "@scure/base";
286
+ import { hex as hex3 } from "@scure/base";
452
287
  import { ripemd160 as ripemd1602 } from "@noble/hashes/legacy.js";
453
288
  import {
454
289
  ArkAddress,
@@ -457,6 +292,10 @@ import {
457
292
  getNetwork,
458
293
  resolveEmulatorPubkey
459
294
  } from "@arkade-os/sdk";
295
+ import {
296
+ provisionClaimSecret,
297
+ provisionRefundKey
298
+ } from "@arkade-os/sdk";
460
299
  var xOnly = (key, label) => {
461
300
  if (key.length === 32) return key;
462
301
  if (key.length !== 33 || key[0] !== 2 && key[0] !== 3) {
@@ -466,7 +305,7 @@ var xOnly = (key, label) => {
466
305
  };
467
306
  var solverHex = (value, field) => {
468
307
  try {
469
- return hex4.decode(value);
308
+ return hex3.decode(value);
470
309
  } catch {
471
310
  throw new Error(`solver sent malformed hex for ${field}`);
472
311
  }
@@ -501,7 +340,7 @@ var AddressMismatch = class extends Error {
501
340
  this.quoted = quoted;
502
341
  }
503
342
  };
504
- var newRfqId = () => hex4.encode(crypto.getRandomValues(new Uint8Array(32)));
343
+ var newRfqId = () => hex3.encode(crypto.getRandomValues(new Uint8Array(32)));
505
344
  var lightningSendRequest = (input) => ({
506
345
  v: 1,
507
346
  type: "rfq_request",
@@ -511,7 +350,7 @@ var lightningSendRequest = (input) => ({
511
350
  profile: {
512
351
  invoice: input.invoice,
513
352
  refund_address: input.refundAddress,
514
- client_refund_pubkey: hex4.encode(input.senderPubkey)
353
+ client_refund_pubkey: hex3.encode(input.senderPubkey)
515
354
  }
516
355
  });
517
356
  var arkadeSwapRequest = (input) => {
@@ -529,8 +368,8 @@ var arkadeSwapRequest = (input) => {
529
368
  amount_side: input.amountSide,
530
369
  amount: input.amount,
531
370
  profile: {
532
- ...input.offerAsset && { offer_asset: hex4.encode(input.offerAsset.serialize()) },
533
- ...input.wantAsset && { want_asset: hex4.encode(input.wantAsset.serialize()) }
371
+ ...input.offerAsset && { offer_asset: hex3.encode(input.offerAsset.serialize()) },
372
+ ...input.wantAsset && { want_asset: hex3.encode(input.wantAsset.serialize()) }
534
373
  }
535
374
  };
536
375
  };
@@ -707,21 +546,22 @@ var relayTransport = (relayUrl, options) => {
707
546
  };
708
547
  };
709
548
  var SEQUENCE_GRANULARITY_SECONDS = 512;
549
+ var SOLO_REFUND_HEADROOM_SECONDS = 8 * SEQUENCE_GRANULARITY_SECONDS;
710
550
  var unilateralClaimDelay = (serverExitDelaySeconds) => {
711
551
  if (!Number.isFinite(serverExitDelaySeconds) || serverExitDelaySeconds < SEQUENCE_GRANULARITY_SECONDS) {
712
552
  throw new Error(
713
553
  `server exit delay must be at least ${SEQUENCE_GRANULARITY_SECONDS}s of seconds, got ${serverExitDelaySeconds}`
714
554
  );
715
555
  }
716
- if (serverExitDelaySeconds > (65535 - 2) * SEQUENCE_GRANULARITY_SECONDS) {
556
+ if (serverExitDelaySeconds > 65535 * SEQUENCE_GRANULARITY_SECONDS - SOLO_REFUND_HEADROOM_SECONDS) {
717
557
  throw new Error(
718
- `server exit delay ${serverExitDelaySeconds}s exceeds what BIP68 can encode once the two refund tiers are stacked above it`
558
+ `server exit delay ${serverExitDelaySeconds}s exceeds what BIP68 can encode once the solo refund's headroom is stacked above it`
719
559
  );
720
560
  }
721
561
  return Math.ceil(serverExitDelaySeconds / SEQUENCE_GRANULARITY_SECONDS) * SEQUENCE_GRANULARITY_SECONDS;
722
562
  };
723
- var unilateralRefundDelay = (claimDelay) => claimDelay + SEQUENCE_GRANULARITY_SECONDS;
724
- var unilateralRefundWithoutReceiverDelay = (claimDelay) => claimDelay + 2 * SEQUENCE_GRANULARITY_SECONDS;
563
+ var unilateralRefundDelay = (claimDelay) => claimDelay;
564
+ var unilateralRefundWithoutReceiverDelay = (claimDelay) => claimDelay + SOLO_REFUND_HEADROOM_SECONDS;
725
565
  function lightningSendVtxoScript(params) {
726
566
  const seconds = (value) => ({
727
567
  type: "seconds",
@@ -731,7 +571,7 @@ function lightningSendVtxoScript(params) {
731
571
  sender: params.senderPubkey,
732
572
  receiver: params.solverPubkey,
733
573
  server: params.serverPubkey,
734
- preimageHash: ripemd1602(hex4.decode(params.paymentHash)),
574
+ preimageHash: ripemd1602(hex3.decode(params.paymentHash)),
735
575
  refundLocktime: BigInt(params.refundLocktime),
736
576
  unilateralClaimDelay: seconds(params.claimDelay),
737
577
  unilateralRefundDelay: seconds(unilateralRefundDelay(params.claimDelay)),
@@ -750,13 +590,8 @@ function lightningSendVtxoScript(params) {
750
590
  }
751
591
  async function requestLightningSend(wallet, arkServerUrl, transport, params) {
752
592
  const rfqId = params.rfqId ?? newRfqId();
753
- const secrets = await deriveSwapSecrets(wallet) ?? randomSwapSecrets();
754
- if (!secrets.derivable) {
755
- console.warn(
756
- "[swap] wallet cannot allocate an HD descriptor: the sender key is random and MUST be persisted before funding"
757
- );
758
- }
759
- const senderPubkey = await senderPubkeyForRfqSecrets(wallet, secrets);
593
+ const secrets = await provisionRefundKey(wallet);
594
+ const senderPubkey = secrets.pubkey;
760
595
  const [info, refundAddress] = await Promise.all([
761
596
  new RestArkProvider(arkServerUrl).getInfo(),
762
597
  wallet.getAddress()
@@ -781,16 +616,16 @@ async function requestLightningSend(wallet, arkServerUrl, transport, params) {
781
616
  `quote from_amount ${quote.from_amount} is below the invoice amount \u2014 a negative spread is not a quote`
782
617
  );
783
618
  }
784
- const serverPubkey = xOnly(hex4.decode(info.signerPubkey), "ark signer key");
619
+ const serverPubkey = xOnly(hex3.decode(info.signerPubkey), "ark signer key");
785
620
  const network = getNetwork(info.network);
786
621
  const script = lightningSendVtxoScript({
787
- solverPubkey: xOnly(hex4.decode(quote.solver_pubkey), "solver key"),
622
+ solverPubkey: xOnly(hex3.decode(quote.solver_pubkey), "solver key"),
788
623
  refundLocktime: quote.refund_locktime,
789
624
  serverPubkey,
790
625
  paymentHash: params.invoice.paymentHash,
791
626
  claimDelay: unilateralClaimDelay(Number(info.unilateralExitDelay)),
792
627
  emulatorPubkey: xOnly(
793
- hex4.decode(resolveEmulatorPubkey(network, params.emulatorPubkey)),
628
+ hex3.decode(resolveEmulatorPubkey(network, params.emulatorPubkey)),
794
629
  "emulator signer key"
795
630
  ),
796
631
  senderPubkey,
@@ -835,9 +670,9 @@ var onchainSendRequest = (input) => ({
835
670
  amount: input.amount,
836
671
  profile: {
837
672
  payment_hash: input.paymentHash,
838
- payout_pubkey: hex4.encode(input.payoutPubkey),
673
+ payout_pubkey: hex3.encode(input.payoutPubkey),
839
674
  refund_address: input.refundAddress,
840
- client_refund_pubkey: hex4.encode(input.senderPubkey)
675
+ client_refund_pubkey: hex3.encode(input.senderPubkey)
841
676
  }
842
677
  });
843
678
  var lightningReceiveRequest = (input) => ({
@@ -850,7 +685,7 @@ var lightningReceiveRequest = (input) => ({
850
685
  profile: {
851
686
  payment_hash: input.paymentHash,
852
687
  payout_address: input.payoutAddress,
853
- payout_pubkey: hex4.encode(input.payoutPubkey),
688
+ payout_pubkey: hex3.encode(input.payoutPubkey),
854
689
  claim_packet: input.claimPacket
855
690
  }
856
691
  });
@@ -864,9 +699,9 @@ var onchainReceiveRequest = (input) => ({
864
699
  profile: {
865
700
  payment_hash: input.paymentHash,
866
701
  claim_packet: input.claimPacket,
867
- refund_pubkey: hex4.encode(input.refundPubkey),
702
+ refund_pubkey: hex3.encode(input.refundPubkey),
868
703
  payout_address: input.payoutAddress,
869
- payout_pubkey: hex4.encode(input.payoutPubkey)
704
+ payout_pubkey: hex3.encode(input.payoutPubkey)
870
705
  }
871
706
  });
872
707
  function deriveOnchainSend(input) {
@@ -882,7 +717,7 @@ function deriveOnchainSend(input) {
882
717
  throw new Error("onchain-send quote is missing a binding field");
883
718
  }
884
719
  const script = lightningSendVtxoScript({
885
- solverPubkey: xOnly(hex4.decode(quote.solver_pubkey), "solver key"),
720
+ solverPubkey: xOnly(hex3.decode(quote.solver_pubkey), "solver key"),
886
721
  refundLocktime,
887
722
  serverPubkey: input.serverPubkey,
888
723
  paymentHash: input.paymentHash,
@@ -898,7 +733,7 @@ function deriveOnchainSend(input) {
898
733
  {
899
734
  paymentHash: input.paymentHash,
900
735
  claimKey: input.payoutPubkey,
901
- refundKey: xOnly(hex4.decode(htlcPubkey), "solver L1 htlc key"),
736
+ refundKey: xOnly(hex3.decode(htlcPubkey), "solver L1 htlc key"),
902
737
  refundLocktime: htlcLocktime
903
738
  },
904
739
  input.l1Network
@@ -916,23 +751,14 @@ function deriveOnchainSend(input) {
916
751
  }
917
752
  async function requestOnchainSend(wallet, arkServerUrl, transport, params) {
918
753
  const rfqId = params.rfqId ?? newRfqId();
919
- if (params.preimage && params.preimage.length !== 32) {
920
- throw new Error(`preimage must be 32 bytes, got ${params.preimage.length}`);
921
- }
922
- const derivedSecrets = await deriveSwapSecrets(wallet);
923
- const secrets = derivedSecrets ? params.preimage ? { ...derivedSecrets, preimage: params.preimage } : derivedSecrets : randomSwapSecrets({ preimage: params.preimage ?? true });
924
- if (!secrets.derivable) {
925
- console.warn(
926
- 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"
927
- );
928
- } else if (params.preimage) {
754
+ const secrets = await provisionClaimSecret(wallet, { preimage: params.preimage });
755
+ if (secrets.mustPersistPreimage) {
929
756
  console.warn(
930
- "[swap] this swap's preimage was supplied by the caller and MUST be persisted with the signing descriptor before funding"
757
+ "[swap] this swap's preimage cannot be re-derived from the seed and MUST be persisted with the record before funding"
931
758
  );
932
759
  }
933
- const preimage = await preimageForRfqSecrets(wallet, secrets);
934
- const paymentHash = paymentHashOf(preimage);
935
- const senderPubkey = await senderPubkeyForRfqSecrets(wallet, secrets);
760
+ const paymentHash = hex3.encode(secrets.paymentHash);
761
+ const senderPubkey = secrets.pubkey;
936
762
  const [info, refundAddress] = await Promise.all([
937
763
  new RestArkProvider(arkServerUrl).getInfo(),
938
764
  wallet.getAddress()
@@ -953,9 +779,9 @@ async function requestOnchainSend(wallet, arkServerUrl, transport, params) {
953
779
  quote,
954
780
  paymentHash,
955
781
  payoutPubkey: params.payoutPubkey,
956
- serverPubkey: xOnly(hex4.decode(info.signerPubkey), "ark signer key"),
782
+ serverPubkey: xOnly(hex3.decode(info.signerPubkey), "ark signer key"),
957
783
  emulatorPubkey: xOnly(
958
- hex4.decode(resolveEmulatorPubkey(network, params.emulatorPubkey)),
784
+ hex3.decode(resolveEmulatorPubkey(network, params.emulatorPubkey)),
959
785
  "emulator signer key"
960
786
  ),
961
787
  claimDelay: unilateralClaimDelay(Number(info.unilateralExitDelay)),
@@ -1067,7 +893,7 @@ function receiveVtxoScript(params) {
1067
893
  sender: params.solverPubkey,
1068
894
  receiver: params.payoutPubkey,
1069
895
  server: params.serverPubkey,
1070
- preimageHash: ripemd1602(hex4.decode(params.paymentHash)),
896
+ preimageHash: ripemd1602(hex3.decode(params.paymentHash)),
1071
897
  refundLocktime: BigInt(params.refundLocktime),
1072
898
  unilateralClaimDelay: seconds(params.claimDelay),
1073
899
  unilateralRefundDelay: seconds(unilateralRefundDelay(params.claimDelay)),
@@ -1094,7 +920,7 @@ function deriveLightningReceive(input) {
1094
920
  throw new Error("lightning-receive quote is missing a binding field");
1095
921
  }
1096
922
  const script = receiveVtxoScript({
1097
- solverPubkey: xOnly(hex4.decode(quote.solver_pubkey), "solver key"),
923
+ solverPubkey: xOnly(hex3.decode(quote.solver_pubkey), "solver key"),
1098
924
  refundLocktime,
1099
925
  serverPubkey: input.serverPubkey,
1100
926
  paymentHash: input.paymentHash,
@@ -1110,15 +936,15 @@ function deriveLightningReceive(input) {
1110
936
  }
1111
937
  async function requestLightningReceive(wallet, arkServerUrl, transport, params) {
1112
938
  const rfqId = params.rfqId ?? newRfqId();
1113
- const secrets = await deriveSwapSecrets(wallet) ?? randomSwapSecrets({ preimage: true });
1114
- if (!secrets.derivable) {
939
+ const secrets = await provisionClaimSecret(wallet);
940
+ if (secrets.mustPersistPreimage) {
1115
941
  console.warn(
1116
- "[swap] this swap's preimage and payout key are random and MUST be persisted before paying"
942
+ "[swap] this swap's preimage cannot be re-derived from the seed and MUST be persisted with the record before paying"
1117
943
  );
1118
944
  }
1119
- const preimage = await preimageForRfqSecrets(wallet, secrets);
1120
- const paymentHash = paymentHashOf(preimage);
1121
- const payoutPubkey = await senderPubkeyForRfqSecrets(wallet, secrets);
945
+ const preimage = secrets.preimage;
946
+ const paymentHash = hex3.encode(secrets.paymentHash);
947
+ const payoutPubkey = secrets.pubkey;
1122
948
  const [info, payoutAddress] = await Promise.all([
1123
949
  new RestArkProvider(arkServerUrl).getInfo(),
1124
950
  wallet.getAddress()
@@ -1145,9 +971,9 @@ async function requestLightningReceive(wallet, arkServerUrl, transport, params)
1145
971
  paymentHash,
1146
972
  payoutPubkey,
1147
973
  payoutAddress,
1148
- serverPubkey: xOnly(hex4.decode(info.signerPubkey), "ark signer key"),
974
+ serverPubkey: xOnly(hex3.decode(info.signerPubkey), "ark signer key"),
1149
975
  emulatorPubkey: xOnly(
1150
- hex4.decode(resolveEmulatorPubkey(network, params.emulatorPubkey)),
976
+ hex3.decode(resolveEmulatorPubkey(network, params.emulatorPubkey)),
1151
977
  "emulator signer key"
1152
978
  ),
1153
979
  claimDelay: unilateralClaimDelay(Number(info.unilateralExitDelay)),
@@ -1194,7 +1020,7 @@ function deriveOnchainReceive(input) {
1194
1020
  throw new Error("onchain-receive quote is missing a binding field");
1195
1021
  }
1196
1022
  const script = receiveVtxoScript({
1197
- solverPubkey: xOnly(hex4.decode(quote.solver_pubkey), "solver key"),
1023
+ solverPubkey: xOnly(hex3.decode(quote.solver_pubkey), "solver key"),
1198
1024
  refundLocktime,
1199
1025
  serverPubkey: input.serverPubkey,
1200
1026
  paymentHash: input.paymentHash,
@@ -1209,7 +1035,7 @@ function deriveOnchainReceive(input) {
1209
1035
  const htlc = onchainHtlcScript(
1210
1036
  {
1211
1037
  paymentHash: input.paymentHash,
1212
- claimKey: xOnly(hex4.decode(claimPubkey), "solver L1 claim key"),
1038
+ claimKey: xOnly(hex3.decode(claimPubkey), "solver L1 claim key"),
1213
1039
  refundKey: input.refundPubkey,
1214
1040
  refundLocktime: htlcLocktime
1215
1041
  },
@@ -1228,15 +1054,15 @@ function deriveOnchainReceive(input) {
1228
1054
  }
1229
1055
  async function requestOnchainReceive(wallet, arkServerUrl, transport, params) {
1230
1056
  const rfqId = params.rfqId ?? newRfqId();
1231
- const secrets = await deriveSwapSecrets(wallet) ?? randomSwapSecrets({ preimage: true });
1232
- if (!secrets.derivable) {
1057
+ const secrets = await provisionClaimSecret(wallet);
1058
+ if (secrets.mustPersistPreimage) {
1233
1059
  console.warn(
1234
- "[swap] this swap's preimage and payout key are random and MUST be persisted before funding"
1060
+ "[swap] this swap's preimage cannot be re-derived from the seed and MUST be persisted with the record before funding"
1235
1061
  );
1236
1062
  }
1237
- const preimage = await preimageForRfqSecrets(wallet, secrets);
1238
- const paymentHash = paymentHashOf(preimage);
1239
- const payoutPubkey = await senderPubkeyForRfqSecrets(wallet, secrets);
1063
+ const preimage = secrets.preimage;
1064
+ const paymentHash = hex3.encode(secrets.paymentHash);
1065
+ const payoutPubkey = secrets.pubkey;
1240
1066
  const [info, payoutAddress] = await Promise.all([
1241
1067
  new RestArkProvider(arkServerUrl).getInfo(),
1242
1068
  wallet.getAddress()
@@ -1265,9 +1091,9 @@ async function requestOnchainReceive(wallet, arkServerUrl, transport, params) {
1265
1091
  payoutPubkey,
1266
1092
  payoutAddress,
1267
1093
  refundPubkey: params.refundPubkey,
1268
- serverPubkey: xOnly(hex4.decode(info.signerPubkey), "ark signer key"),
1094
+ serverPubkey: xOnly(hex3.decode(info.signerPubkey), "ark signer key"),
1269
1095
  emulatorPubkey: xOnly(
1270
- hex4.decode(resolveEmulatorPubkey(network, params.emulatorPubkey)),
1096
+ hex3.decode(resolveEmulatorPubkey(network, params.emulatorPubkey)),
1271
1097
  "emulator signer key"
1272
1098
  ),
1273
1099
  claimDelay: unilateralClaimDelay(Number(info.unilateralExitDelay)),
@@ -1318,20 +1144,6 @@ export {
1318
1144
  awaitOnchainFill,
1319
1145
  claimOnchainFill,
1320
1146
  classifyOnchainHtlc,
1321
- RFQ_PREIMAGE_TAG,
1322
- buildPreimageMessage,
1323
- deriveSwapSecrets,
1324
- randomSwapSecrets,
1325
- rfqSecretsToRecord,
1326
- rfqSecretsOfRecord,
1327
- adoptSwapDescriptor,
1328
- RefundNotLocallyPossibleError,
1329
- senderIdentityForRfqSecrets,
1330
- senderIdentityForSwapRecord,
1331
- senderPubkeyForRfqSecrets,
1332
- isDeterministicSigner,
1333
- derivePreimage,
1334
- preimageForRfqSecrets,
1335
1147
  sealClaimPacket,
1336
1148
  SWAP_LOCKUP_CONTRACT_TYPE,
1337
1149
  SWAP_LOCKUP_CONTRACT_LABEL,
@@ -1358,6 +1170,7 @@ export {
1358
1170
  assertFundable,
1359
1171
  httpTransport,
1360
1172
  relayTransport,
1173
+ SOLO_REFUND_HEADROOM_SECONDS,
1361
1174
  unilateralClaimDelay,
1362
1175
  unilateralRefundDelay,
1363
1176
  unilateralRefundWithoutReceiverDelay,