@arkade-os/swap 0.0.12 → 0.0.13

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
@@ -34,6 +34,8 @@ __export(index_exports, {
34
34
  ARKADE_BTC: () => ARKADE_BTC,
35
35
  AddressMismatch: () => AddressMismatch,
36
36
  BTC_ASSET_ID: () => BTC_ASSET_ID,
37
+ CROSS_ASSET_RAIL: () => CROSS_ASSET_RAIL,
38
+ CovclaimdRevealError: () => CovclaimdRevealError,
37
39
  InMemoryAssetSwapRepository: () => InMemoryAssetSwapRepository,
38
40
  IndexedDbAssetSwapRepository: () => IndexedDbAssetSwapRepository,
39
41
  LIGHTNING_BTC: () => LIGHTNING_BTC,
@@ -90,8 +92,10 @@ __export(index_exports, {
90
92
  classifyDepositSpend: () => classifyDepositSpend,
91
93
  classifyOnchainHtlc: () => classifyOnchainHtlc,
92
94
  classifySpend: () => classifySpend,
95
+ covclaimdClient: () => covclaimdClient,
93
96
  createOffer: () => createOffer,
94
97
  createRfqSwapRecord: () => createRfqSwapRecord,
98
+ crossAssetRail: () => crossAssetRail,
95
99
  decodeOffer: () => decodeOffer,
96
100
  deriveLightningReceive: () => deriveLightningReceive,
97
101
  deriveOnchainReceive: () => deriveOnchainReceive,
@@ -137,6 +141,8 @@ __export(index_exports, {
137
141
  requestOnchainSend: () => requestOnchainSend,
138
142
  restoreAssetSwaps: () => restoreAssetSwaps,
139
143
  retireSettledOfferContracts: () => retireSettledOfferContracts,
144
+ revealClaimPacket: () => revealClaimPacket,
145
+ revealFieldsFromScript: () => revealFieldsFromScript,
140
146
  rfqClaimSecretOf: () => rfqClaimSecretOf,
141
147
  rfqPair: () => rfqPair,
142
148
  rfqSecretsProfile: () => rfqSecretsProfile,
@@ -2403,7 +2409,7 @@ var lightningReceiveRequest = (input) => ({
2403
2409
  payment_hash: input.paymentHash,
2404
2410
  payout_address: input.payoutAddress,
2405
2411
  payout_pubkey: import_base10.hex.encode(input.payoutPubkey),
2406
- claim_packet: input.claimPacket
2412
+ ...input.claimPacket === void 0 ? {} : { claim_packet: input.claimPacket }
2407
2413
  }
2408
2414
  });
2409
2415
  var onchainReceiveRequest = (input) => ({
@@ -2415,7 +2421,7 @@ var onchainReceiveRequest = (input) => ({
2415
2421
  amount: input.amount,
2416
2422
  profile: {
2417
2423
  payment_hash: input.paymentHash,
2418
- claim_packet: input.claimPacket,
2424
+ ...input.claimPacket === void 0 ? {} : { claim_packet: input.claimPacket },
2419
2425
  refund_pubkey: import_base10.hex.encode(input.refundPubkey),
2420
2426
  payout_address: input.payoutAddress,
2421
2427
  payout_pubkey: import_base10.hex.encode(input.payoutPubkey)
@@ -2686,17 +2692,17 @@ async function requestLightningReceive(wallet, arkServerUrl, transport, params)
2686
2692
  new import_sdk9.RestArkProvider(arkServerUrl).getInfo(),
2687
2693
  wallet.getAddress()
2688
2694
  ]);
2689
- const claimPacket = await sealClaimPacket({
2695
+ const claimPacket = params.covclaimdPubkey ? await sealClaimPacket({
2690
2696
  preimage,
2691
2697
  covclaimdPubkey: params.covclaimdPubkey
2692
- });
2698
+ }) : void 0;
2693
2699
  const quote = await transport.requestQuote(
2694
2700
  lightningReceiveRequest({
2695
2701
  rfqId,
2696
2702
  paymentHash,
2697
2703
  payoutAddress,
2698
2704
  payoutPubkey,
2699
- claimPacket: claimPacket.ciphertext,
2705
+ claimPacket: claimPacket?.ciphertext,
2700
2706
  amount: params.amount,
2701
2707
  amountSide: params.amountSide
2702
2708
  })
@@ -2809,10 +2815,10 @@ async function requestOnchainReceive(wallet, arkServerUrl, transport, params) {
2809
2815
  new import_sdk9.RestArkProvider(arkServerUrl).getInfo(),
2810
2816
  wallet.getAddress()
2811
2817
  ]);
2812
- const claimPacket = await sealClaimPacket({
2818
+ const claimPacket = params.covclaimdPubkey ? await sealClaimPacket({
2813
2819
  preimage,
2814
2820
  covclaimdPubkey: params.covclaimdPubkey
2815
- });
2821
+ }) : void 0;
2816
2822
  const quote = await transport.requestQuote(
2817
2823
  onchainReceiveRequest({
2818
2824
  rfqId,
@@ -2820,7 +2826,7 @@ async function requestOnchainReceive(wallet, arkServerUrl, transport, params) {
2820
2826
  payoutAddress,
2821
2827
  payoutPubkey,
2822
2828
  refundPubkey: params.refundPubkey,
2823
- claimPacket: claimPacket.ciphertext,
2829
+ claimPacket: claimPacket?.ciphertext,
2824
2830
  amount: params.amount,
2825
2831
  amountSide: params.amountSide
2826
2832
  })
@@ -2968,6 +2974,7 @@ function solverOnchainRail(deps) {
2968
2974
  id: SOLVER_ONCHAIN_RAIL,
2969
2975
  match: (req) => (0, import_sdk11.btcTarget)(req.raw) !== void 0,
2970
2976
  available: async (req) => {
2977
+ if ((0, import_sdk11.assetsOf)(req).length > 0) return false;
2971
2978
  const address = (0, import_sdk11.btcTarget)(req.raw);
2972
2979
  if (!address) return false;
2973
2980
  try {
@@ -2981,6 +2988,7 @@ function solverOnchainRail(deps) {
2981
2988
  },
2982
2989
  quote: async (req, ctx) => {
2983
2990
  const address = (0, import_sdk11.btcTarget)(req.raw);
2991
+ (0, import_sdk11.assertNoAssets)(SOLVER_ONCHAIN_RAIL, req);
2984
2992
  const amount = (0, import_sdk11.resolveSendAmount)(SOLVER_ONCHAIN_RAIL, req.raw, req.amount);
2985
2993
  const payoutPkScript = l1ScriptForAddress(address, deps.l1Network);
2986
2994
  const rendezvous = await rendezvousFor(amount);
@@ -3079,12 +3087,14 @@ function solverLightningRail(deps) {
3079
3087
  id: SOLVER_LIGHTNING_RAIL,
3080
3088
  match: (req) => (0, import_sdk12.invoiceTarget)(req.raw) !== void 0,
3081
3089
  available: async (req) => {
3090
+ if ((0, import_sdk12.assetsOf)(req).length > 0) return false;
3082
3091
  const facts = factsOf(req.raw, deps.decodeInvoice, Math.floor(Date.now() / 1e3));
3083
3092
  if (!facts) return false;
3084
3093
  if (req.amount !== void 0 && req.amount !== facts.amountSats) return false;
3085
3094
  return await rendezvousFor(facts.amountSats) !== void 0;
3086
3095
  },
3087
3096
  quote: async (req, ctx) => {
3097
+ (0, import_sdk12.assertNoAssets)(SOLVER_LIGHTNING_RAIL, req);
3088
3098
  const facts = factsOf(req.raw, deps.decodeInvoice, Math.floor(Date.now() / 1e3));
3089
3099
  if (!facts) {
3090
3100
  throw new Error(
@@ -3157,16 +3167,260 @@ function solverLightningRail(deps) {
3157
3167
  };
3158
3168
  }
3159
3169
 
3160
- // src/claim.ts
3161
- var import_base14 = require("@scure/base");
3170
+ // src/payment/crossAsset.ts
3171
+ var import_sdk13 = require("@arkade-os/sdk");
3172
+ var CROSS_ASSET_RAIL = "cross-asset";
3173
+ var DEFAULT_CARRIER_SATS = 330;
3174
+ var parseAssetId = (assetId) => {
3175
+ try {
3176
+ return import_sdk13.asset.AssetId.fromString(assetId);
3177
+ } catch {
3178
+ return void 0;
3179
+ }
3180
+ };
3181
+ function crossAssetRail(deps) {
3182
+ const planFor = async (asset3) => {
3183
+ const markets = await deps.discover();
3184
+ const found = findMarket(markets, BTC_ASSET_ID, asset3.assetId);
3185
+ const market = found?.market;
3186
+ if (!market) return void 0;
3187
+ const plan = await deps.quote(market, found.give, asset3.amount);
3188
+ const [balance, dust] = await Promise.all([deps.btcBalance(), deps.dust()]);
3189
+ return { plan, error: validatePlan(plan, balance, dust) };
3190
+ };
3191
+ return {
3192
+ id: CROSS_ASSET_RAIL,
3193
+ match: (req) => (0, import_sdk13.arkTarget)(req.raw) !== void 0,
3194
+ available: async (req) => {
3195
+ const assets = (0, import_sdk13.assetsOf)(req);
3196
+ if (assets.length !== 1) return false;
3197
+ const [asset3] = assets;
3198
+ if (asset3.assetId === BTC_ASSET_ID) return false;
3199
+ if (typeof asset3.amount !== "bigint" || asset3.amount <= 0n) return false;
3200
+ if (!parseAssetId(asset3.assetId)) return false;
3201
+ const planned = await planFor(asset3);
3202
+ return planned !== void 0 && planned.error === void 0;
3203
+ },
3204
+ quote: async (req, ctx) => {
3205
+ const payTo = (0, import_sdk13.arkTarget)(req.raw);
3206
+ const asset3 = (0, import_sdk13.resolveAssetAmount)(CROSS_ASSET_RAIL, req);
3207
+ const wantAsset = parseAssetId(asset3.assetId);
3208
+ if (!wantAsset) {
3209
+ throw new Error(
3210
+ `${CROSS_ASSET_RAIL}: ${asset3.assetId} is not an asset id (expected 34 bytes of hex)`
3211
+ );
3212
+ }
3213
+ const planned = await planFor(asset3);
3214
+ if (!planned) {
3215
+ throw new Error(`${CROSS_ASSET_RAIL}: no market swaps BTC into ${asset3.assetId}`);
3216
+ }
3217
+ if (planned.error) {
3218
+ throw new Error(
3219
+ `${CROSS_ASSET_RAIL}: cannot swap into ${asset3.assetId} \u2014 ${planned.error}`
3220
+ );
3221
+ }
3222
+ const { plan } = planned;
3223
+ if (!Number.isSafeInteger(Number(plan.deposit.atomic))) {
3224
+ throw new Error(
3225
+ `${CROSS_ASSET_RAIL}: deposit of ${plan.deposit.atomic} does not fit a JS number`
3226
+ );
3227
+ }
3228
+ const depositSats = Number(plan.deposit.atomic);
3229
+ const carrier = deps.carrierSats ?? DEFAULT_CARRIER_SATS;
3230
+ return {
3231
+ railId: CROSS_ASSET_RAIL,
3232
+ // OPEN QUESTION for review: `total = amount + fee` forces the
3233
+ // purchase price into `fee`, which reads as a service charge.
3234
+ // A third field instead? `assets.spent` labels it correctly.
3235
+ amount: carrier,
3236
+ fee: depositSats,
3237
+ total: depositSats + carrier,
3238
+ assets: {
3239
+ delivered: asset3,
3240
+ spent: { assetId: BTC_ASSET_ID, amount: plan.deposit.atomic }
3241
+ },
3242
+ meta: {
3243
+ market: plan.market.pair,
3244
+ priceDisplay: plan.priceDisplay,
3245
+ give: plan.give
3246
+ },
3247
+ send: async () => (0, import_sdk13.makeHandle)(CROSS_ASSET_RAIL, async (emit) => {
3248
+ const offer = await createOffer(ctx.wallet, deps.arkServerUrl, {
3249
+ wantAmount: asset3.amount,
3250
+ wantAsset,
3251
+ ...deps.emulatorPubkey ? { emulatorPubkey: deps.emulatorPubkey } : {}
3252
+ });
3253
+ const swap = {
3254
+ phase: "quoted",
3255
+ offerHex: offer.offerHex,
3256
+ address: offer.address,
3257
+ swapPkScript: offer.swapPkScript,
3258
+ depositSats,
3259
+ asset: asset3,
3260
+ payTo,
3261
+ plan
3262
+ };
3263
+ await deps.persist(swap);
3264
+ await ctx.wallet.send({
3265
+ address: offer.address,
3266
+ amount: depositSats,
3267
+ extensions: [offer.extension]
3268
+ });
3269
+ emit({ status: "sent" });
3270
+ await deps.awaitFill(swap);
3271
+ await deps.persist({ ...swap, phase: "filled" });
3272
+ await deps.persist({ ...swap, phase: "paying" });
3273
+ const txid = await ctx.wallet.send({
3274
+ address: payTo,
3275
+ amount: carrier,
3276
+ assets: [asset3]
3277
+ });
3278
+ await deps.persist({ ...swap, phase: "settled", txid });
3279
+ const result = {
3280
+ railId: CROSS_ASSET_RAIL,
3281
+ txid,
3282
+ swapId: offer.offerHex
3283
+ };
3284
+ emit({ status: "settled", result });
3285
+ return result;
3286
+ })
3287
+ };
3288
+ }
3289
+ };
3290
+ }
3291
+
3292
+ // src/reveal.ts
3293
+ var import_base13 = require("@scure/base");
3162
3294
  var import_legacy3 = require("@noble/hashes/legacy.js");
3163
- var import_sha25 = require("@noble/hashes/sha2.js");
3295
+ var import_sha24 = require("@noble/hashes/sha2.js");
3164
3296
  var import_sdk14 = require("@arkade-os/sdk");
3297
+ var CovclaimdRevealError = class extends Error {
3298
+ name = "CovclaimdRevealError";
3299
+ status;
3300
+ detail;
3301
+ retryable;
3302
+ constructor(what, status, detail) {
3303
+ super(`covclaimd ${what} failed: ${status || "no response"} ${detail}`.trimEnd());
3304
+ this.status = status;
3305
+ this.detail = detail;
3306
+ this.retryable = status === 0 || status === 429 || status >= 500;
3307
+ }
3308
+ };
3309
+ var decodeKey = (value, field) => {
3310
+ if (typeof value !== "string") throw new Error(`covclaimd info: ${field} is not a string`);
3311
+ let bytes;
3312
+ try {
3313
+ bytes = import_base13.hex.decode(value);
3314
+ } catch {
3315
+ throw new Error(`covclaimd info: ${field} is not hex`);
3316
+ }
3317
+ if (bytes.length !== 33) {
3318
+ throw new Error(`covclaimd info: ${field} must be 33-byte compressed, got ${bytes.length}`);
3319
+ }
3320
+ return bytes;
3321
+ };
3322
+ var LOOPBACK = /* @__PURE__ */ new Set(["localhost", "127.0.0.1", "[::1]"]);
3323
+ var assertTransportSecure = (baseUrl, allowInsecureHttp) => {
3324
+ const { protocol, hostname } = new URL(baseUrl);
3325
+ if (protocol === "https:" || allowInsecureHttp) return;
3326
+ if (protocol === "http:" && LOOPBACK.has(hostname)) return;
3327
+ throw new Error(
3328
+ `covclaimd URL must be https (got ${protocol}//${hostname}): the key it serves is the one the preimage gets sealed to. Pass allowInsecureHttp to override.`
3329
+ );
3330
+ };
3331
+ var covclaimdClient = (baseUrl, options = {}) => {
3332
+ assertTransportSecure(baseUrl, options.allowInsecureHttp === true);
3333
+ const url = baseUrl.replace(/\/+$/, "");
3334
+ const fetchImpl = options.fetchImpl ?? fetch;
3335
+ const timeoutMs = options.timeoutMs ?? 3e4;
3336
+ const send = async (what, path, init) => {
3337
+ let response;
3338
+ try {
3339
+ response = await fetchImpl(`${url}${path}`, {
3340
+ ...init,
3341
+ // a redirect would move the key fetch off the vetted origin
3342
+ redirect: "error",
3343
+ signal: AbortSignal.timeout(timeoutMs)
3344
+ });
3345
+ } catch (error) {
3346
+ throw new CovclaimdRevealError(what, 0, String(error));
3347
+ }
3348
+ if (!response.ok) {
3349
+ throw new CovclaimdRevealError(what, response.status, await response.text());
3350
+ }
3351
+ return response;
3352
+ };
3353
+ const readJson = async (what, response) => {
3354
+ const body = await response.text();
3355
+ try {
3356
+ return JSON.parse(body);
3357
+ } catch {
3358
+ throw new CovclaimdRevealError(
3359
+ what,
3360
+ response.status,
3361
+ `non-JSON body: ${body.slice(0, 200)}`
3362
+ );
3363
+ }
3364
+ };
3365
+ return {
3366
+ async info() {
3367
+ const response = await send("info", "/v1/preimage/covclaimd-pubkey", {
3368
+ method: "GET"
3369
+ });
3370
+ const body = await readJson("info", response);
3371
+ return {
3372
+ covclaimdPubkey: decodeKey(body?.covclaimd_pub_key, "covclaimd_pub_key"),
3373
+ emulatorPubkey: import_base13.hex.encode(decodeKey(body?.emulator_pub_key, "emulator_pub_key"))
3374
+ };
3375
+ },
3376
+ async reveal(params) {
3377
+ await send("reveal", "/v1/reveal", {
3378
+ method: "POST",
3379
+ headers: { "content-type": "application/json" },
3380
+ body: JSON.stringify({
3381
+ swap_address: params.swapAddress,
3382
+ packet: { ciphertext: params.ciphertext, arkade_script: params.arkadeScript },
3383
+ taptree: params.taptree
3384
+ })
3385
+ });
3386
+ }
3387
+ };
3388
+ };
3389
+ function revealFieldsFromScript(script) {
3390
+ if (!script.nonInteractiveClaimArkadeScript) {
3391
+ throw new Error("this covenant has no non-interactive claim leaf to reveal against");
3392
+ }
3393
+ return {
3394
+ arkadeScript: import_base13.base64.encode(script.nonInteractiveClaimArkadeScript),
3395
+ taptree: import_base13.hex.encode(script.encode())
3396
+ };
3397
+ }
3398
+ async function revealClaimPacket(client, input) {
3399
+ const fields = revealFieldsFromScript(input.script);
3400
+ if (import_base13.hex.encode(import_sdk14.ArkAddress.decode(input.address).pkScript) !== import_base13.hex.encode(input.script.pkScript)) {
3401
+ throw new Error("address does not belong to this covenant");
3402
+ }
3403
+ if (import_base13.hex.encode((0, import_legacy3.ripemd160)((0, import_sha24.sha256)(input.preimage))) !== import_base13.hex.encode(input.script.options.preimageHash)) {
3404
+ throw new Error("preimage does not match the covenant's payment hash");
3405
+ }
3406
+ const { ciphertext } = await sealClaimPacket({
3407
+ preimage: input.preimage,
3408
+ covclaimdPubkey: (await client.info()).covclaimdPubkey
3409
+ });
3410
+ await client.reveal({ swapAddress: input.address, ciphertext, ...fields });
3411
+ return { ciphertext };
3412
+ }
3413
+
3414
+ // src/claim.ts
3415
+ var import_base15 = require("@scure/base");
3416
+ var import_legacy4 = require("@noble/hashes/legacy.js");
3417
+ var import_sha26 = require("@noble/hashes/sha2.js");
3418
+ var import_sdk16 = require("@arkade-os/sdk");
3165
3419
 
3166
3420
  // src/refund.ts
3167
- var import_base13 = require("@scure/base");
3168
- var import_sha24 = require("@noble/hashes/sha2.js");
3169
- var import_sdk13 = require("@arkade-os/sdk");
3421
+ var import_base14 = require("@scure/base");
3422
+ var import_sha25 = require("@noble/hashes/sha2.js");
3423
+ var import_sdk15 = require("@arkade-os/sdk");
3170
3424
  var sleep2 = (ms) => new Promise((resolve) => setTimeout(resolve, ms));
3171
3425
  var isRfqTerminal = (state) => RFQ_TERMINAL_STATES.includes(state);
3172
3426
  var RFQ_RESOLVED_STATES = ["settled", "refunded"];
@@ -3213,7 +3467,7 @@ var LockupNeedsRecoveryError = class extends Error {
3213
3467
  }
3214
3468
  };
3215
3469
  async function findLockupVtxos(indexer, swapPkScript) {
3216
- const scripts = [import_base13.hex.encode(swapPkScript)];
3470
+ const scripts = [import_base14.hex.encode(swapPkScript)];
3217
3471
  const [spendable, recoverable] = await Promise.all([
3218
3472
  indexer.getVtxos({ scripts, spendableOnly: true }),
3219
3473
  indexer.getVtxos({ scripts, recoverableOnly: true })
@@ -3239,16 +3493,16 @@ async function findLockupVtxos(indexer, swapPkScript) {
3239
3493
  }
3240
3494
  return out;
3241
3495
  }
3242
- var hashesTo = (candidate, paymentHash) => import_base13.hex.encode((0, import_sha24.sha256)(candidate)) === paymentHash;
3496
+ var hashesTo = (candidate, paymentHash) => import_base14.hex.encode((0, import_sha25.sha256)(candidate)) === paymentHash;
3243
3497
  var candidateWitnessItems = (tx, inputIndex) => [
3244
- ...(0, import_sdk13.getArkPsbtFields)(tx, inputIndex, import_sdk13.ConditionWitness).flat(),
3498
+ ...(0, import_sdk15.getArkPsbtFields)(tx, inputIndex, import_sdk15.ConditionWitness).flat(),
3245
3499
  ...tx.getInput(inputIndex).finalScriptWitness ?? []
3246
3500
  ];
3247
3501
  async function readLockupFate(indexer, input) {
3248
- const { vtxos } = await indexer.getVtxos({ scripts: [import_base13.hex.encode(input.swapPkScript)] });
3502
+ const { vtxos } = await indexer.getVtxos({ scripts: [import_base14.hex.encode(input.swapPkScript)] });
3249
3503
  const all = vtxos ?? [];
3250
3504
  if (all.length === 0) return { fate: "unknown" };
3251
- const exited = all.filter((vtxo) => vtxo.isUnrolled && !(0, import_sdk13.hasTerminalSpend)(vtxo));
3505
+ const exited = all.filter((vtxo) => vtxo.isUnrolled && !(0, import_sdk15.hasTerminalSpend)(vtxo));
3252
3506
  if (exited.length > 0) {
3253
3507
  return {
3254
3508
  fate: "exited",
@@ -3258,7 +3512,7 @@ async function readLockupFate(indexer, input) {
3258
3512
  const spentBy = /* @__PURE__ */ new Map();
3259
3513
  let everySpendNamed = true;
3260
3514
  for (const vtxo of all) {
3261
- if (!(0, import_sdk13.hasTerminalSpend)(vtxo)) return { fate: "open" };
3515
+ if (!(0, import_sdk15.hasTerminalSpend)(vtxo)) return { fate: "open" };
3262
3516
  if (vtxo.spentBy)
3263
3517
  spentBy.set(vtxo.spentBy, {
3264
3518
  checkpointTxid: vtxo.spentBy,
@@ -3272,7 +3526,7 @@ async function readLockupFate(indexer, input) {
3272
3526
  for (const raw of txs) {
3273
3527
  let tx;
3274
3528
  try {
3275
- tx = import_sdk13.Transaction.fromPSBT(import_base13.base64.decode(raw));
3529
+ tx = import_sdk15.Transaction.fromPSBT(import_base14.base64.decode(raw));
3276
3530
  } catch {
3277
3531
  continue;
3278
3532
  }
@@ -3280,7 +3534,7 @@ async function readLockupFate(indexer, input) {
3280
3534
  for (let i = 0; i < tx.inputsLength; i++) {
3281
3535
  const spent = tx.getInput(i);
3282
3536
  if (!spent.txid) continue;
3283
- const txid = import_base13.hex.encode(spent.txid);
3537
+ const txid = import_base14.hex.encode(spent.txid);
3284
3538
  if (!all.some((vtxo) => vtxo.txid === txid && vtxo.vout === spent.index)) continue;
3285
3539
  for (const candidate of candidateWitnessItems(tx, i)) {
3286
3540
  if (hashesTo(candidate, input.paymentHash)) {
@@ -3309,14 +3563,14 @@ async function pushRefundWithoutReceiver(ark, input) {
3309
3563
  const info = await ark.getInfo();
3310
3564
  let serverUnrollScript;
3311
3565
  try {
3312
- serverUnrollScript = import_sdk13.CSVMultisigTapscript.decode(import_base13.hex.decode(info.checkpointTapscript));
3566
+ serverUnrollScript = import_sdk15.CSVMultisigTapscript.decode(import_base14.hex.decode(info.checkpointTapscript));
3313
3567
  } catch {
3314
3568
  throw new Error("invalid checkpointTapscript from the Arkade server");
3315
3569
  }
3316
3570
  const leaf = input.script.refundWithoutReceiver();
3317
3571
  const tapTree = input.script.encode();
3318
3572
  const amount = input.vtxos.reduce((sum, vtxo) => sum + vtxo.value, 0);
3319
- const { arkTx, checkpoints } = (0, import_sdk13.buildOffchainTx)(
3573
+ const { arkTx, checkpoints } = (0, import_sdk15.buildOffchainTx)(
3320
3574
  input.vtxos.map((vtxo) => ({
3321
3575
  txid: vtxo.txid,
3322
3576
  vout: vtxo.vout,
@@ -3329,18 +3583,18 @@ async function pushRefundWithoutReceiver(ark, input) {
3329
3583
  );
3330
3584
  const signedArkTx = await input.sender.sign(arkTx);
3331
3585
  const submitted = await ark.submitTx(
3332
- import_base13.base64.encode(signedArkTx.toPSBT()),
3333
- checkpoints.map((c) => import_base13.base64.encode(c.toPSBT()))
3586
+ import_base14.base64.encode(signedArkTx.toPSBT()),
3587
+ checkpoints.map((c) => import_base14.base64.encode(c.toPSBT()))
3334
3588
  );
3335
- (0, import_sdk13.assertSubmittedArkTxid)(submitted, signedArkTx, "refundWithoutReceiver");
3336
- const matched = (0, import_sdk13.matchServerCheckpoints)(
3589
+ (0, import_sdk15.assertSubmittedArkTxid)(submitted, signedArkTx, "refundWithoutReceiver");
3590
+ const matched = (0, import_sdk15.matchServerCheckpoints)(
3337
3591
  submitted.signedCheckpointTxs,
3338
3592
  checkpoints,
3339
3593
  "refundWithoutReceiver"
3340
3594
  );
3341
3595
  const finalCheckpoints = await Promise.all(
3342
3596
  matched.map(
3343
- async ({ server }) => import_base13.base64.encode((await input.sender.sign(server, [0])).toPSBT())
3597
+ async ({ server }) => import_base14.base64.encode((await input.sender.sign(server, [0])).toPSBT())
3344
3598
  )
3345
3599
  );
3346
3600
  await ark.finalizeTx(submitted.arkTxid, finalCheckpoints);
@@ -3435,20 +3689,20 @@ async function pushClaim(ark, input) {
3435
3689
  }
3436
3690
  }
3437
3691
  const committed = input.script.options.preimageHash;
3438
- if (import_base14.hex.encode((0, import_legacy3.ripemd160)((0, import_sha25.sha256)(input.preimage))) !== import_base14.hex.encode(committed)) {
3692
+ if (import_base15.hex.encode((0, import_legacy4.ripemd160)((0, import_sha26.sha256)(input.preimage))) !== import_base15.hex.encode(committed)) {
3439
3693
  throw new Error("preimage does not match the covenant's payment hash");
3440
3694
  }
3441
3695
  const info = await ark.getInfo();
3442
3696
  let serverUnrollScript;
3443
3697
  try {
3444
- serverUnrollScript = import_sdk14.CSVMultisigTapscript.decode(import_base14.hex.decode(info.checkpointTapscript));
3698
+ serverUnrollScript = import_sdk16.CSVMultisigTapscript.decode(import_base15.hex.decode(info.checkpointTapscript));
3445
3699
  } catch {
3446
3700
  throw new Error("invalid checkpointTapscript from the Arkade server");
3447
3701
  }
3448
3702
  const leaf = input.script.claim();
3449
3703
  const tapTree = input.script.encode();
3450
- const arkTxid = await (0, import_sdk14.signAndSubmitOffchainTx)({
3451
- identity: (0, import_sdk14.claimWithPreimageIdentity)(input.receiver, input.preimage),
3704
+ const arkTxid = await (0, import_sdk16.signAndSubmitOffchainTx)({
3705
+ identity: (0, import_sdk16.claimWithPreimageIdentity)(input.receiver, input.preimage),
3452
3706
  provider: ark,
3453
3707
  inputs: input.vtxos.map((vtxo) => ({
3454
3708
  txid: vtxo.txid,
@@ -3495,7 +3749,7 @@ async function claimReceiveLockup(indexer, ark, input) {
3495
3749
  }
3496
3750
 
3497
3751
  // src/refundBlocked.ts
3498
- var import_sdk15 = require("@arkade-os/sdk");
3752
+ var import_sdk17 = require("@arkade-os/sdk");
3499
3753
  var RefundNotLocallyPossibleError = class extends Error {
3500
3754
  constructor(reason, message, options) {
3501
3755
  super(message, options);
@@ -3512,16 +3766,16 @@ async function senderIdentityForSwapRecord(wallet, record) {
3512
3766
  );
3513
3767
  }
3514
3768
  try {
3515
- return await (0, import_sdk15.contractSigner)(wallet, record.signingDescriptor);
3769
+ return await (0, import_sdk17.contractSigner)(wallet, record.signingDescriptor);
3516
3770
  } catch (cause) {
3517
- if (cause instanceof import_sdk15.WalletCannotSignError) {
3771
+ if (cause instanceof import_sdk17.WalletCannotSignError) {
3518
3772
  throw new RefundNotLocallyPossibleError(
3519
3773
  "unsignable-wallet",
3520
3774
  `this wallet holds ${record.signingDescriptor} but cannot sign with it; attach its signer`,
3521
3775
  { cause }
3522
3776
  );
3523
3777
  }
3524
- if (cause instanceof import_sdk15.ForeignDescriptorError) {
3778
+ if (cause instanceof import_sdk17.ForeignDescriptorError) {
3525
3779
  throw new RefundNotLocallyPossibleError(
3526
3780
  "foreign-descriptor",
3527
3781
  `this wallet cannot derive ${record.signingDescriptor}; the swap was created on another wallet`,
@@ -3556,7 +3810,7 @@ function arkadeRefunder(deps) {
3556
3810
  }
3557
3811
 
3558
3812
  // src/swapManager.ts
3559
- var import_base15 = require("@scure/base");
3813
+ var import_base16 = require("@scure/base");
3560
3814
  function nextOnchainAction(input) {
3561
3815
  switch (input.phase.phase) {
3562
3816
  case "unfunded":
@@ -4004,7 +4258,7 @@ var RfqSwapManager = class {
4004
4258
  // ── internals ────────────────────────────────────────────────────────────
4005
4259
  track(swap) {
4006
4260
  this.monitored.set(swap.rfqId, swap);
4007
- this.byLockupScript.set(import_base15.hex.encode(swap.lockupPkScript), swap);
4261
+ this.byLockupScript.set(import_base16.hex.encode(swap.lockupPkScript), swap);
4008
4262
  }
4009
4263
  /** Drops the swap from BOTH indexes. The event index is the one that stops
4010
4264
  * a late event finding a swap that is gone; `pollSwap`'s own
@@ -4013,7 +4267,7 @@ var RfqSwapManager = class {
4013
4267
  * them from silently re-driving a cancelled swap. */
4014
4268
  untrack(rfqId) {
4015
4269
  const swap = this.monitored.get(rfqId);
4016
- if (swap) this.byLockupScript.delete(import_base15.hex.encode(swap.lockupPkScript));
4270
+ if (swap) this.byLockupScript.delete(import_base16.hex.encode(swap.lockupPkScript));
4017
4271
  this.monitored.delete(rfqId);
4018
4272
  this.refundRefused.delete(rfqId);
4019
4273
  this.lastClaimError.delete(rfqId);
@@ -4075,7 +4329,7 @@ var RfqSwapManager = class {
4075
4329
  if (!lockup) {
4076
4330
  try {
4077
4331
  const [existing] = await contracts.getContracts({
4078
- script: import_base15.hex.encode(swap.lockupPkScript)
4332
+ script: import_base16.hex.encode(swap.lockupPkScript)
4079
4333
  });
4080
4334
  if (existing) {
4081
4335
  this.registered.set(swap.rfqId, true);
@@ -4094,13 +4348,13 @@ var RfqSwapManager = class {
4094
4348
  );
4095
4349
  return;
4096
4350
  }
4097
- const script = import_base15.hex.encode(lockup.script.pkScript);
4098
- if (script !== import_base15.hex.encode(swap.lockupPkScript)) {
4351
+ const script = import_base16.hex.encode(lockup.script.pkScript);
4352
+ if (script !== import_base16.hex.encode(swap.lockupPkScript)) {
4099
4353
  this.registered.set(swap.rfqId, false);
4100
4354
  this.emitFailed(
4101
4355
  swap,
4102
4356
  new Error(
4103
- `swap ${swap.rfqId} lockup script ${script} does not match its lockupPkScript ${import_base15.hex.encode(swap.lockupPkScript)}`
4357
+ `swap ${swap.rfqId} lockup script ${script} does not match its lockupPkScript ${import_base16.hex.encode(swap.lockupPkScript)}`
4104
4358
  )
4105
4359
  );
4106
4360
  return;
@@ -4119,7 +4373,7 @@ var RfqSwapManager = class {
4119
4373
  * script for its whole life. Best-effort — the swap is over either way. */
4120
4374
  retireContract(swap) {
4121
4375
  if (!this.deps.contracts || !this.registered.get(swap.rfqId)) return;
4122
- void this.deps.contracts.setContractWatchState(import_base15.hex.encode(swap.lockupPkScript), "retained").catch((error) => this.emitFailed(swap, error));
4376
+ void this.deps.contracts.setContractWatchState(import_base16.hex.encode(swap.lockupPkScript), "retained").catch((error) => this.emitFailed(swap, error));
4123
4377
  }
4124
4378
  arm() {
4125
4379
  if (!this.running) return;
@@ -4592,8 +4846,8 @@ var errorMessage = (error) => error instanceof Error ? error.message : String(er
4592
4846
  var outpointKey = (vtxo) => `${vtxo.txid}:${vtxo.vout}`;
4593
4847
 
4594
4848
  // src/activity.ts
4595
- var import_sdk16 = require("@arkade-os/sdk");
4596
- var import_base16 = require("@scure/base");
4849
+ var import_sdk18 = require("@arkade-os/sdk");
4850
+ var import_base17 = require("@scure/base");
4597
4851
  var LABELS = {
4598
4852
  lightning_send: "Lightning send",
4599
4853
  lightning_receive: "Lightning receive",
@@ -4668,7 +4922,7 @@ async function activityInputOf(record, indexer) {
4668
4922
  async function lockupTxids(indexer, record, wantFunding) {
4669
4923
  let script;
4670
4924
  try {
4671
- script = import_base16.hex.encode(import_sdk16.ArkAddress.decode(record.lockupAddress).pkScript);
4925
+ script = import_base17.hex.encode(import_sdk18.ArkAddress.decode(record.lockupAddress).pkScript);
4672
4926
  } catch {
4673
4927
  return [];
4674
4928
  }
@@ -4690,6 +4944,8 @@ async function lockupTxids(indexer, record, wantFunding) {
4690
4944
  ARKADE_BTC,
4691
4945
  AddressMismatch,
4692
4946
  BTC_ASSET_ID,
4947
+ CROSS_ASSET_RAIL,
4948
+ CovclaimdRevealError,
4693
4949
  InMemoryAssetSwapRepository,
4694
4950
  IndexedDbAssetSwapRepository,
4695
4951
  LIGHTNING_BTC,
@@ -4746,8 +5002,10 @@ async function lockupTxids(indexer, record, wantFunding) {
4746
5002
  classifyDepositSpend,
4747
5003
  classifyOnchainHtlc,
4748
5004
  classifySpend,
5005
+ covclaimdClient,
4749
5006
  createOffer,
4750
5007
  createRfqSwapRecord,
5008
+ crossAssetRail,
4751
5009
  decodeOffer,
4752
5010
  deriveLightningReceive,
4753
5011
  deriveOnchainReceive,
@@ -4793,6 +5051,8 @@ async function lockupTxids(indexer, record, wantFunding) {
4793
5051
  requestOnchainSend,
4794
5052
  restoreAssetSwaps,
4795
5053
  retireSettledOfferContracts,
5054
+ revealClaimPacket,
5055
+ revealFieldsFromScript,
4796
5056
  rfqClaimSecretOf,
4797
5057
  rfqPair,
4798
5058
  rfqSecretsProfile,