@arkade-os/swap 0.0.19 → 0.0.21

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.
@@ -1283,11 +1283,6 @@ var arkadeSwapRequest = (input) => {
1283
1283
  "set at least one of wantAsset or offerAsset \u2014 with neither set both legs are BTC, which is not a swap"
1284
1284
  );
1285
1285
  }
1286
- if (input.amountSide !== void 0 && input.amountSide !== "from") {
1287
- throw new Error(
1288
- 'arkade\u2194arkade quotes are exact-in only: use amountSide "from" with the deposit amount'
1289
- );
1290
- }
1291
1286
  const pair = rfqPair(
1292
1287
  input.offerAsset ? arkadeAssetLeg(input.offerAsset) : ARKADE_BTC,
1293
1288
  input.wantAsset ? arkadeAssetLeg(input.wantAsset) : ARKADE_BTC
@@ -1298,7 +1293,7 @@ var arkadeSwapRequest = (input) => {
1298
1293
  type: "rfq_request",
1299
1294
  rfq_id: input.rfqId,
1300
1295
  pair,
1301
- amount_side: "from",
1296
+ amount_side: input.amountSide ?? "from",
1302
1297
  amount: canonicalAssetAmount(input.amount),
1303
1298
  // The pair names the assets; the profile names the trader. Both are
1304
1299
  // covenant parameters, and the solver's `.strict()` schema refuses
@@ -1766,11 +1761,16 @@ var assertArkadeFundable = (input) => {
1766
1761
  throw gateError("quote_expired", "quote carries a non-positive amount");
1767
1762
  }
1768
1763
  };
1764
+ var quoteCarrierSats = (quote) => {
1765
+ const published = quote.carrier_sats === void 0 ? 0n : BigInt(quote.carrier_sats);
1766
+ return published > 0n ? published : ASSET_CARRIER_SATS;
1767
+ };
1769
1768
  async function requestArkadeSwap(wallet, arkServerUrl, transport, params) {
1770
1769
  if (!params.wantAsset && !params.offerAsset) {
1771
1770
  throw new Error("set at least one of wantAsset or offerAsset; BTC-to-BTC is not a swap");
1772
1771
  }
1773
1772
  const rfqId = params.rfqId ?? newRfqId();
1773
+ const amountSide = params.amountSide ?? "from";
1774
1774
  const [makerAddress, makerPublicKey] = await Promise.all([
1775
1775
  wallet.getAddress(),
1776
1776
  wallet.identity.xOnlyPublicKey()
@@ -1786,6 +1786,7 @@ async function requestArkadeSwap(wallet, arkServerUrl, transport, params) {
1786
1786
  ...params.offerAsset !== void 0 ? { offerAsset: params.offerAsset } : {},
1787
1787
  ...params.wantAsset !== void 0 ? { wantAsset: params.wantAsset } : {},
1788
1788
  amount: params.amount,
1789
+ amountSide,
1789
1790
  makerPkScript,
1790
1791
  makerPublicKey
1791
1792
  })
@@ -1798,11 +1799,30 @@ async function requestArkadeSwap(wallet, arkServerUrl, transport, params) {
1798
1799
  ...params.offerAsset !== void 0 ? { offerAsset: params.offerAsset } : {},
1799
1800
  ...params.wantAsset !== void 0 ? { wantAsset: params.wantAsset } : {}
1800
1801
  });
1801
- if (BigInt(quote.from_amount).toString() !== canonicalAssetAmount(params.amount)) {
1802
+ const quoted = amountSide === "from" ? quote.from_amount : quote.to_amount;
1803
+ if (BigInt(quoted).toString() !== canonicalAssetAmount(params.amount)) {
1802
1804
  throw new Error(
1803
- `quote from_amount ${quote.from_amount} does not match the requested ${canonicalAssetAmount(params.amount)}`
1805
+ `quote ${amountSide}_amount ${quoted} does not match the requested ${canonicalAssetAmount(params.amount)}`
1804
1806
  );
1805
1807
  }
1808
+ if (params.maxFromAmount !== void 0) {
1809
+ const cap = BigInt(canonicalAssetAmount(params.maxFromAmount));
1810
+ if (BigInt(quote.from_amount) > cap) {
1811
+ throw gateError(
1812
+ "quote_amount_rejected",
1813
+ `quote from_amount ${quote.from_amount} exceeds maxFromAmount ${cap}`
1814
+ );
1815
+ }
1816
+ }
1817
+ if (params.minToAmount !== void 0) {
1818
+ const floorAmount = BigInt(canonicalAssetAmount(params.minToAmount));
1819
+ if (BigInt(quote.to_amount) < floorAmount) {
1820
+ throw gateError(
1821
+ "quote_amount_rejected",
1822
+ `quote to_amount ${quote.to_amount} is under minToAmount ${floorAmount}`
1823
+ );
1824
+ }
1825
+ }
1806
1826
  const offer = await createOffer(wallet, arkServerUrl, {
1807
1827
  wantAmount: terms.wantAmount,
1808
1828
  ...terms.wantAsset !== void 0 ? { wantAsset: terms.wantAsset } : {},
@@ -1817,7 +1837,7 @@ async function requestArkadeSwap(wallet, arkServerUrl, transport, params) {
1817
1837
  pair,
1818
1838
  address: offer.address,
1819
1839
  fundAmount,
1820
- carrierSats: params.offerAsset !== void 0 ? ASSET_CARRIER_SATS : 0n,
1840
+ carrierSats: params.offerAsset !== void 0 ? quoteCarrierSats(quote) : 0n,
1821
1841
  swapPkScript: offer.swapPkScript,
1822
1842
  offerHex: offer.offerHex,
1823
1843
  extension: offer.extension
package/dist/index.cjs CHANGED
@@ -2555,11 +2555,6 @@ var arkadeSwapRequest = (input) => {
2555
2555
  "set at least one of wantAsset or offerAsset \u2014 with neither set both legs are BTC, which is not a swap"
2556
2556
  );
2557
2557
  }
2558
- if (input.amountSide !== void 0 && input.amountSide !== "from") {
2559
- throw new Error(
2560
- 'arkade\u2194arkade quotes are exact-in only: use amountSide "from" with the deposit amount'
2561
- );
2562
- }
2563
2558
  const pair = rfqPair(
2564
2559
  input.offerAsset ? arkadeAssetLeg(input.offerAsset) : ARKADE_BTC,
2565
2560
  input.wantAsset ? arkadeAssetLeg(input.wantAsset) : ARKADE_BTC
@@ -2570,7 +2565,7 @@ var arkadeSwapRequest = (input) => {
2570
2565
  type: "rfq_request",
2571
2566
  rfq_id: input.rfqId,
2572
2567
  pair,
2573
- amount_side: "from",
2568
+ amount_side: input.amountSide ?? "from",
2574
2569
  amount: canonicalAssetAmount(input.amount),
2575
2570
  // The pair names the assets; the profile names the trader. Both are
2576
2571
  // covenant parameters, and the solver's `.strict()` schema refuses
@@ -3038,11 +3033,16 @@ var assertArkadeFundable = (input) => {
3038
3033
  throw gateError("quote_expired", "quote carries a non-positive amount");
3039
3034
  }
3040
3035
  };
3036
+ var quoteCarrierSats = (quote) => {
3037
+ const published = quote.carrier_sats === void 0 ? 0n : BigInt(quote.carrier_sats);
3038
+ return published > 0n ? published : ASSET_CARRIER_SATS;
3039
+ };
3041
3040
  async function requestArkadeSwap(wallet, arkServerUrl, transport, params) {
3042
3041
  if (!params.wantAsset && !params.offerAsset) {
3043
3042
  throw new Error("set at least one of wantAsset or offerAsset; BTC-to-BTC is not a swap");
3044
3043
  }
3045
3044
  const rfqId = params.rfqId ?? newRfqId();
3045
+ const amountSide = params.amountSide ?? "from";
3046
3046
  const [makerAddress, makerPublicKey] = await Promise.all([
3047
3047
  wallet.getAddress(),
3048
3048
  wallet.identity.xOnlyPublicKey()
@@ -3058,6 +3058,7 @@ async function requestArkadeSwap(wallet, arkServerUrl, transport, params) {
3058
3058
  ...params.offerAsset !== void 0 ? { offerAsset: params.offerAsset } : {},
3059
3059
  ...params.wantAsset !== void 0 ? { wantAsset: params.wantAsset } : {},
3060
3060
  amount: params.amount,
3061
+ amountSide,
3061
3062
  makerPkScript,
3062
3063
  makerPublicKey
3063
3064
  })
@@ -3070,11 +3071,30 @@ async function requestArkadeSwap(wallet, arkServerUrl, transport, params) {
3070
3071
  ...params.offerAsset !== void 0 ? { offerAsset: params.offerAsset } : {},
3071
3072
  ...params.wantAsset !== void 0 ? { wantAsset: params.wantAsset } : {}
3072
3073
  });
3073
- if (BigInt(quote.from_amount).toString() !== canonicalAssetAmount(params.amount)) {
3074
+ const quoted = amountSide === "from" ? quote.from_amount : quote.to_amount;
3075
+ if (BigInt(quoted).toString() !== canonicalAssetAmount(params.amount)) {
3074
3076
  throw new Error(
3075
- `quote from_amount ${quote.from_amount} does not match the requested ${canonicalAssetAmount(params.amount)}`
3077
+ `quote ${amountSide}_amount ${quoted} does not match the requested ${canonicalAssetAmount(params.amount)}`
3076
3078
  );
3077
3079
  }
3080
+ if (params.maxFromAmount !== void 0) {
3081
+ const cap = BigInt(canonicalAssetAmount(params.maxFromAmount));
3082
+ if (BigInt(quote.from_amount) > cap) {
3083
+ throw gateError(
3084
+ "quote_amount_rejected",
3085
+ `quote from_amount ${quote.from_amount} exceeds maxFromAmount ${cap}`
3086
+ );
3087
+ }
3088
+ }
3089
+ if (params.minToAmount !== void 0) {
3090
+ const floorAmount = BigInt(canonicalAssetAmount(params.minToAmount));
3091
+ if (BigInt(quote.to_amount) < floorAmount) {
3092
+ throw gateError(
3093
+ "quote_amount_rejected",
3094
+ `quote to_amount ${quote.to_amount} is under minToAmount ${floorAmount}`
3095
+ );
3096
+ }
3097
+ }
3078
3098
  const offer = await createOffer(wallet, arkServerUrl, {
3079
3099
  wantAmount: terms.wantAmount,
3080
3100
  ...terms.wantAsset !== void 0 ? { wantAsset: terms.wantAsset } : {},
@@ -3089,7 +3109,7 @@ async function requestArkadeSwap(wallet, arkServerUrl, transport, params) {
3089
3109
  pair,
3090
3110
  address: offer.address,
3091
3111
  fundAmount,
3092
- carrierSats: params.offerAsset !== void 0 ? ASSET_CARRIER_SATS : 0n,
3112
+ carrierSats: params.offerAsset !== void 0 ? quoteCarrierSats(quote) : 0n,
3093
3113
  swapPkScript: offer.swapPkScript,
3094
3114
  offerHex: offer.offerHex,
3095
3115
  extension: offer.extension
@@ -4184,30 +4204,26 @@ var LockupNeedsRecoveryError = class extends Error {
4184
4204
  this.recoverableAfter = recoverableAfter;
4185
4205
  }
4186
4206
  };
4187
- async function findLockupVtxos(indexer, swapPkScript) {
4188
- const scripts = [import_base14.hex.encode(swapPkScript)];
4189
- const [spendable, recoverable] = await Promise.all([
4190
- indexer.getVtxos({ scripts, spendableOnly: true }),
4191
- indexer.getVtxos({ scripts, recoverableOnly: true })
4192
- ]);
4207
+ async function findLockupVtxos(contracts, swapPkScript) {
4208
+ const [row] = await contracts.getContractsWithVtxos({
4209
+ script: import_base14.hex.encode(swapPkScript)
4210
+ });
4193
4211
  const seen = /* @__PURE__ */ new Set();
4194
4212
  const out = [];
4195
- for (const [vtxos, isRecoverable] of [
4196
- [spendable.vtxos ?? [], false],
4197
- [recoverable.vtxos ?? [], true]
4198
- ]) {
4199
- for (const vtxo of vtxos) {
4200
- if (vtxo.isUnrolled) continue;
4201
- const key = `${vtxo.txid}:${vtxo.vout}`;
4202
- if (seen.has(key)) continue;
4203
- seen.add(key);
4204
- out.push({
4205
- txid: vtxo.txid,
4206
- vout: vtxo.vout,
4207
- value: Number(vtxo.value),
4208
- recoverable: isRecoverable
4209
- });
4210
- }
4213
+ for (const vtxo of row?.vtxos ?? []) {
4214
+ if (vtxo.isUnrolled) continue;
4215
+ if ((0, import_sdk16.hasTerminalSpend)(vtxo)) continue;
4216
+ const key = `${vtxo.txid}:${vtxo.vout}`;
4217
+ if (seen.has(key)) continue;
4218
+ seen.add(key);
4219
+ out.push({
4220
+ txid: vtxo.txid,
4221
+ vout: vtxo.vout,
4222
+ value: Number(vtxo.value),
4223
+ // The manager's canonical `isSwept` fact; no coercion, because the
4224
+ // normalized row guarantees a boolean.
4225
+ recoverable: vtxo.isSwept
4226
+ });
4211
4227
  }
4212
4228
  return out;
4213
4229
  }
@@ -4319,7 +4335,7 @@ async function pushRefundWithoutReceiver(ark, input) {
4319
4335
  return { arkTxid: submitted.arkTxid, amount };
4320
4336
  }
4321
4337
  var REFUND_MTP_LAG_SECONDS = 2 * 60 * 60;
4322
- async function refundIfUnresolved(transport, ark, indexer, input) {
4338
+ async function refundIfUnresolved(transport, ark, contracts, indexer, input) {
4323
4339
  const pollMs = input.pollMs ?? 5e3;
4324
4340
  const now = input.now ?? (() => Math.floor(Date.now() / 1e3));
4325
4341
  const attemptDeadline = input.attemptDeadline ?? input.refundLocktime + REFUND_MTP_LAG_SECONDS;
@@ -4342,7 +4358,7 @@ async function refundIfUnresolved(transport, ark, indexer, input) {
4342
4358
  status
4343
4359
  };
4344
4360
  }
4345
- const vtxos = await findLockupVtxos(indexer, input.script.pkScript);
4361
+ const vtxos = await findLockupVtxos(contracts, input.script.pkScript);
4346
4362
  if (vtxos.length === 0) return { outcome: "nothing_to_refund", status };
4347
4363
  try {
4348
4364
  const pushed = await pushRefundWithoutReceiver(ark, {
@@ -4437,10 +4453,10 @@ async function pushClaim(ark, input) {
4437
4453
  });
4438
4454
  return { arkTxid, amount: locked };
4439
4455
  }
4440
- async function awaitLockupFunding(indexer, swapPkScript, options = {}) {
4456
+ async function awaitLockupFunding(contracts, swapPkScript, options = {}) {
4441
4457
  const pollMs = options.pollMs ?? 5e3;
4442
4458
  for (; ; ) {
4443
- const vtxos = await findLockupVtxos(indexer, swapPkScript);
4459
+ const vtxos = await findLockupVtxos(contracts, swapPkScript);
4444
4460
  if (vtxos.length > 0) return vtxos;
4445
4461
  if (options.deadline !== void 0 && Date.now() / 1e3 >= options.deadline) {
4446
4462
  const error = new Error("the lockup never appeared at the covenant script");
@@ -4450,8 +4466,8 @@ async function awaitLockupFunding(indexer, swapPkScript, options = {}) {
4450
4466
  await sleep3(pollMs);
4451
4467
  }
4452
4468
  }
4453
- async function claimReceiveLockup(indexer, ark, input) {
4454
- const vtxos = await awaitLockupFunding(indexer, input.swapPkScript, {
4469
+ async function claimReceiveLockup(contracts, ark, input) {
4470
+ const vtxos = await awaitLockupFunding(contracts, input.swapPkScript, {
4455
4471
  pollMs: input.pollMs,
4456
4472
  deadline: input.deadline
4457
4473
  });
@@ -4513,7 +4529,7 @@ function arkadeRefunder(deps) {
4513
4529
  `swap ${swap.rfqId} carries no lockup covenant, so its refund cannot be built`
4514
4530
  );
4515
4531
  }
4516
- const vtxos = await findLockupVtxos(deps.indexer, swap.lockupPkScript);
4532
+ const vtxos = await findLockupVtxos(deps.contracts, swap.lockupPkScript);
4517
4533
  if (vtxos.length === 0) return null;
4518
4534
  const record = await deps.repository.getRfqSwap(swap.rfqId);
4519
4535
  if (!record) {
@@ -5136,7 +5152,10 @@ var RfqSwapManager = class {
5136
5152
  return;
5137
5153
  }
5138
5154
  if (swap.kind === "lightning_receive") {
5139
- return fate.fate === "exited" ? this.blockExitedLockup(swap, fate) : this.driveReceiveClaim(swap);
5155
+ if (fate.fate === "exited") return this.blockExitedLockup(swap, fate);
5156
+ if (fate.fate === "open") return this.driveReceiveClaim(swap);
5157
+ if (this.config.now() >= swap.refundLocktime) return this.driveReceiveClaim(swap);
5158
+ return;
5140
5159
  }
5141
5160
  if (swap.kind === "onchain_send" && swap.state !== "claimed") {
5142
5161
  if (await this.driveOnchain(swap) === "handled") return;
@@ -5191,7 +5210,7 @@ var RfqSwapManager = class {
5191
5210
  if (now < swap.refundLocktime) {
5192
5211
  let vtxos;
5193
5212
  try {
5194
- vtxos = await findLockupVtxos(this.deps.indexer, swap.lockupPkScript);
5213
+ vtxos = await findLockupVtxos(this.deps.contracts, swap.lockupPkScript);
5195
5214
  } catch (error) {
5196
5215
  this.emitFailed(swap, error);
5197
5216
  return;
package/dist/index.d.cts CHANGED
@@ -1,9 +1,9 @@
1
1
  import { ProvisionedKey, ProvisionedClaimSecret, ArkTxInput, asset, RelativeTimelock, IWallet, EmulatorProvider, arkade, RestIndexerProvider, Transaction, IContractManager, OnchainProvider, PaymentRail, Asset, VHTLC, Identity, ActivityResolver } from '@arkade-os/sdk';
2
- import { S as SwapSecretsProjection, R as RfqSwapRecord, A as AssetSwapRepository, a as AssetSwap, M as MarketsCacheEntry, b as RefundArkProvider, c as RefundIndexer, L as LockupVtxo, d as RfqSwap, e as ArkadeRefundResult, f as LockupSpendIndexer, g as RfqSwapState } from './repository-BXIcmIIC.cjs';
3
- export { h as AssetSwapStatus, i as AvailableRfqSwapManagerCallbacks, B as BTC_ASSET_ID, I as InMemoryAssetSwapRepository, j as LightningReceiveSwap, k as LightningSendSwap, l as LockupFate, m as LockupNeedsRecoveryError, n as LockupParams, o as LockupSpend, O as OnchainSendAction, p as OnchainSendSwap, P as PersistableRfqSwap, q as PreimageBlockedReason, r as PreimageNotRecoverableError, s as REFUND_MTP_LAG_SECONDS, t as RFQ_RESOLVED_STATES, u as RFQ_SWAP_RETENTION_SECONDS, v as RFQ_SWAP_TERMINAL_STATES, w as RefundOutcome, x as RfqRestoreFailure, y as RfqRestoreOptions, z as RfqRestoreResult, C as RfqSwapActionName, D as RfqSwapLockup, E as RfqSwapManager, F as RfqSwapManagerCallbacks, G as RfqSwapManagerConfig, H as RfqSwapManagerDeps, J as RfqSwapManagerEvents, K as RfqSwapOrigin, N as RfqSwapOriginRequired, Q as RfqSwapOutcome, T as RfqSwapRecordStore, U as SwapContractRegistry, V as addAssetSwap, W as awaitRfqResolution, X as createRfqSwapRecord, Y as findLockupVtxos, Z as getAssetSwaps, _ as getAssetSwapsOrThrow, $ as isRfqSwapTerminal, a0 as isRfqTerminal, a1 as nextOnchainAction, a2 as preimageForSwapRecord, a3 as pushRefundWithoutReceiver, a4 as readLockupFate, a5 as rebuildRfqSwap, a6 as refundIfUnresolved, a7 as rfqSwapOriginOf, a8 as shouldRetainRfqSwap, a9 as swapSecretsToRecord, aa as updateAssetSwap, ab as updateAssetSwapBestEffort, ac as updateRfqSwapRecord } from './repository-BXIcmIIC.cjs';
2
+ import { S as SwapSecretsProjection, R as RfqSwapRecord, A as AssetSwapRepository, a as AssetSwap, M as MarketsCacheEntry, b as RefundArkProvider, L as LockupContractSource, c as LockupVtxo, d as RfqSwap, e as ArkadeRefundResult, f as LockupSpendIndexer, g as RfqSwapState } from './repository-CZYc8Y38.cjs';
3
+ export { h as AssetSwapStatus, i as AvailableRfqSwapManagerCallbacks, B as BTC_ASSET_ID, I as InMemoryAssetSwapRepository, j as LightningReceiveSwap, k as LightningSendSwap, l as LockupFate, m as LockupNeedsRecoveryError, n as LockupParams, o as LockupSpend, O as OnchainSendAction, p as OnchainSendSwap, P as PersistableRfqSwap, q as PreimageBlockedReason, r as PreimageNotRecoverableError, s as REFUND_MTP_LAG_SECONDS, t as RFQ_RESOLVED_STATES, u as RFQ_SWAP_RETENTION_SECONDS, v as RFQ_SWAP_TERMINAL_STATES, w as RefundOutcome, x as RfqRestoreFailure, y as RfqRestoreOptions, z as RfqRestoreResult, C as RfqSwapActionName, D as RfqSwapLockup, E as RfqSwapManager, F as RfqSwapManagerCallbacks, G as RfqSwapManagerConfig, H as RfqSwapManagerDeps, J as RfqSwapManagerEvents, K as RfqSwapOrigin, N as RfqSwapOriginRequired, Q as RfqSwapOutcome, T as RfqSwapRecordStore, U as SwapContractRegistry, V as addAssetSwap, W as awaitRfqResolution, X as createRfqSwapRecord, Y as findLockupVtxos, Z as getAssetSwaps, _ as getAssetSwapsOrThrow, $ as isRfqSwapTerminal, a0 as isRfqTerminal, a1 as nextOnchainAction, a2 as preimageForSwapRecord, a3 as pushRefundWithoutReceiver, a4 as readLockupFate, a5 as rebuildRfqSwap, a6 as refundIfUnresolved, a7 as rfqSwapOriginOf, a8 as shouldRetainRfqSwap, a9 as swapSecretsToRecord, aa as updateAssetSwap, ab as updateAssetSwapBestEffort, ac as updateRfqSwapRecord } from './repository-CZYc8Y38.cjs';
4
4
  import { Network, LocalCardInput, DiscoveredMarket, Side, OfferPlan } from '@arkade-os/solver-discovery';
5
- import { O as OnchainNetwork, a as OnchainHtlc, b as OnchainHtlcParams, C as ChainSource, R as RfqTransport, r as requestOnchainSend, I as InvoiceFacts, c as requestLightningSend } from './rfq-D96aLvCA.cjs';
6
- export { A as ARKADE_ASSET, d as ARKADE_BTC, e as AddressMismatch, f as ChainUtxo, H as HtlcUtxo, L as LIGHTNING_BTC, g as LIGHTNING_RECEIVE_PAIR, h as LIGHTNING_SEND_PAIR, i as LOCKTIME_THRESHOLD, j as LightningReceiveTreeParams, k as LightningSendTreeParams, M as MAX_MIN_CONFIRMATIONS, l as MIN_CLAIM_WINDOW_SECONDS, m as MIN_HEADROOM_SECONDS, n as ONCHAIN_BTC, o as ONCHAIN_CLAIM_MARGIN_SECONDS, p as ONCHAIN_DUST_SATS, q as ONCHAIN_ORDER_MARGIN_SECONDS, s as ONCHAIN_RECEIVE_PAIR, t as ONCHAIN_SECONDS_PER_BLOCK, u as ONCHAIN_SEND_PAIR, v as OnchainHtlcPhase, w as RFQ_REFUSAL_ERROR_CODES, x as RFQ_TERMINAL_STATES, y as RelaySocket, z as RfqQuote, B as RfqRefusalDetail, D as RfqRefusalErrorCode, E as RfqRefusalReason, F as RfqRefusalUnit, G as RfqStatus, S as SOLO_REFUND_HEADROOM_SECONDS, J as SwapRefusal, K as arkadeAssetLeg, N as arkadeSwapRequest, P as assertArkadeFundable, Q as assertFundable, T as assertReceivable, U as awaitOnchainFill, V as buildHtlcClaim, W as buildHtlcRefund, X as canonicalAssetAmount, Y as claimOnchainFill, Z as classifyOnchainHtlc, _ as deriveLightningReceive, $ as deriveOnchainReceive, a0 as deriveOnchainSend, a1 as extractPreimage, a2 as httpTransport, a3 as isRfqRefusalErrorCode, a4 as l1ScriptForAddress, a5 as lightningReceiveRequest, a6 as lightningSendRequest, a7 as lightningSendVtxoScript, a8 as newPreimage, a9 as newRfqId, aa as normalizeMakerPkScript, ab as normalizeMakerPublicKey, ac as offerTermsFromQuote, ad as onchainHtlcScript, ae as onchainReceiveRequest, af as onchainSendRequest, ag as paymentHashOf, ah as receiveVtxoScript, ai as relayTransport, aj as requestArkadeSwap, ak as requestLightningReceive, al as requestOnchainReceive, am as rfqPair, an as unilateralClaimDelay, ao as unilateralRefundDelay, ap as unilateralRefundWithoutReceiverDelay, aq as verifyLockupAddress, ar as verifyOfferAddress, as as verifyReceiveInvoice } from './rfq-D96aLvCA.cjs';
5
+ import { O as OnchainNetwork, a as OnchainHtlc, b as OnchainHtlcParams, C as ChainSource, R as RfqTransport, r as requestOnchainSend, I as InvoiceFacts, c as requestLightningSend } from './rfq-B95nPfaa.cjs';
6
+ export { A as ARKADE_ASSET, d as ARKADE_BTC, e as AddressMismatch, f as ChainUtxo, H as HtlcUtxo, L as LIGHTNING_BTC, g as LIGHTNING_RECEIVE_PAIR, h as LIGHTNING_SEND_PAIR, i as LOCKTIME_THRESHOLD, j as LightningReceiveTreeParams, k as LightningSendTreeParams, M as MAX_MIN_CONFIRMATIONS, l as MIN_CLAIM_WINDOW_SECONDS, m as MIN_HEADROOM_SECONDS, n as ONCHAIN_BTC, o as ONCHAIN_CLAIM_MARGIN_SECONDS, p as ONCHAIN_DUST_SATS, q as ONCHAIN_ORDER_MARGIN_SECONDS, s as ONCHAIN_RECEIVE_PAIR, t as ONCHAIN_SECONDS_PER_BLOCK, u as ONCHAIN_SEND_PAIR, v as OnchainHtlcPhase, w as RFQ_REFUSAL_ERROR_CODES, x as RFQ_TERMINAL_STATES, y as RelaySocket, z as RfqQuote, B as RfqRefusalDetail, D as RfqRefusalErrorCode, E as RfqRefusalReason, F as RfqRefusalUnit, G as RfqStatus, S as SOLO_REFUND_HEADROOM_SECONDS, J as SwapRefusal, K as arkadeAssetLeg, N as arkadeSwapRequest, P as assertArkadeFundable, Q as assertFundable, T as assertReceivable, U as awaitOnchainFill, V as buildHtlcClaim, W as buildHtlcRefund, X as canonicalAssetAmount, Y as claimOnchainFill, Z as classifyOnchainHtlc, _ as deriveLightningReceive, $ as deriveOnchainReceive, a0 as deriveOnchainSend, a1 as extractPreimage, a2 as httpTransport, a3 as isRfqRefusalErrorCode, a4 as l1ScriptForAddress, a5 as lightningReceiveRequest, a6 as lightningSendRequest, a7 as lightningSendVtxoScript, a8 as newPreimage, a9 as newRfqId, aa as normalizeMakerPkScript, ab as normalizeMakerPublicKey, ac as offerTermsFromQuote, ad as onchainHtlcScript, ae as onchainReceiveRequest, af as onchainSendRequest, ag as paymentHashOf, ah as receiveVtxoScript, ai as relayTransport, aj as requestArkadeSwap, ak as requestLightningReceive, al as requestOnchainReceive, am as rfqPair, an as unilateralClaimDelay, ao as unilateralRefundDelay, ap as unilateralRefundWithoutReceiverDelay, aq as verifyLockupAddress, ar as verifyOfferAddress, as as verifyReceiveInvoice } from './rfq-B95nPfaa.cjs';
7
7
 
8
8
  /**
9
9
  * Which wallet key signs this leg. Stored at `profile.signer`.
@@ -1241,7 +1241,7 @@ declare function pushClaim(ark: ClaimArkProvider, input: {
1241
1241
  * unix-seconds `deadline`, and a thrown error carrying a stable `reason` when
1242
1242
  * the deadline passes.
1243
1243
  */
1244
- declare function awaitLockupFunding(indexer: RefundIndexer, swapPkScript: Uint8Array, options?: {
1244
+ declare function awaitLockupFunding(contracts: LockupContractSource, swapPkScript: Uint8Array, options?: {
1245
1245
  pollMs?: number;
1246
1246
  deadline?: number;
1247
1247
  }): Promise<readonly LockupVtxo[]>;
@@ -1258,7 +1258,7 @@ declare function awaitLockupFunding(indexer: RefundIndexer, swapPkScript: Uint8A
1258
1258
  * rest lands is safe — and that is also the answer to a genuinely underfunded
1259
1259
  * lockup, which never gets past the gate at all.
1260
1260
  */
1261
- declare function claimReceiveLockup(indexer: RefundIndexer, ark: ClaimArkProvider, input: Parameters<typeof pushClaim>[1] & {
1261
+ declare function claimReceiveLockup(contracts: LockupContractSource, ark: ClaimArkProvider, input: Parameters<typeof pushClaim>[1] & {
1262
1262
  /** The covenant's scriptPubKey, from the request flow's `swapPkScript`. */
1263
1263
  swapPkScript: Uint8Array;
1264
1264
  pollMs?: number;
@@ -1332,7 +1332,14 @@ declare function senderIdentityForSwapRecord(wallet: IWallet, record: {
1332
1332
 
1333
1333
  interface ArkadeRefunderDeps {
1334
1334
  ark: RefundArkProvider;
1335
- indexer: RefundIndexer;
1335
+ /**
1336
+ * The wallet's contract manager. The lockup's row must be registered in
1337
+ * it before this can see the funding — which is what
1338
+ * `RfqSwapManager.ensureRegistered` does per pass, and what
1339
+ * `requestLightningSend` / `requestOnchainSend` do up front. Prefer
1340
+ * `await wallet.getContractManager()`.
1341
+ */
1342
+ contracts: LockupContractSource;
1336
1343
  /** Asked for the descriptor's signer; never asked to mint a key. */
1337
1344
  wallet: IWallet;
1338
1345
  /**
@@ -1347,7 +1354,7 @@ interface ArkadeRefunderDeps {
1347
1354
  *
1348
1355
  * @example
1349
1356
  * manager.setCallbacks({
1350
- * refundArkade: arkadeRefunder({ ark, indexer, wallet, repository }),
1357
+ * refundArkade: arkadeRefunder({ ark, contracts, wallet, repository }),
1351
1358
  * saveSwap,
1352
1359
  * });
1353
1360
  */
@@ -1499,4 +1506,4 @@ interface RfqSwapActivityDeps {
1499
1506
  */
1500
1507
  declare function rfqSwapActivityInputs(deps: RfqSwapActivityDeps): Promise<SwapActivityInput[]>;
1501
1508
 
1502
- export { ASSET_CARRIER_SATS, ArkadeRefundResult, type ArkadeRefunderDeps, AssetSwap, AssetSwapRepository, type AssetSwapRestoreChange, CLAIM_PACKET_TYPE, CROSS_ASSET_RAIL, ChainSource, type ClaimArkProvider, type ClaimPacketInput, type ClaimPacketShape, type CovclaimdClient, type CovclaimdInfo, CovclaimdRevealError, type CrossAssetPhase, type CrossAssetRailDeps, type CrossAssetSwap, type DiscoverMarketsOptions, type FillFunding, IndexedDbAssetSwapRepository, InvoiceFacts, type LightningReceiveProfile, type LightningSendProfile, LockupAmountMismatchError, LockupContractMissing, type LockupContractReader, type LockupContractWriter, LockupRegistrationFailed, LockupSpendIndexer, LockupVtxo, MARKET_CORRIDORS, type MarketCorridor, type MarketLike, MarketsCacheEntry, OFFER_PACKET_TYPE, type Offer, type OfferContractRetirer, type OfferSwapWatcher, OnchainHtlc, OnchainHtlcParams, OnchainNetwork, type OnchainSendProfile, type PlanError, QUOTE_OPTIONS, RefundArkProvider, type RefundBlockedReason, RefundIndexer, RefundNotLocallyPossibleError, type RegisterAssetSwapRestoreOptions, type RestoreAssetSwapRepositoryOptions, type RestoreAssetSwapRepositoryResult, type RestoreIndexer, type RevealParams, type RfqClaimSecretProjection, type RfqHashlockProjection, type RfqSignerProjection, RfqSwap, type RfqSwapActivityDeps, RfqSwapRecord, RfqSwapState, RfqTransport, SEALED_CIPHERTEXT_LENGTH, SOLVER_LIGHTNING_RAIL, SOLVER_ONCHAIN_RAIL, SWAP_LOCKUP_CONTRACT_KIND, SWAP_LOCKUP_CONTRACT_LABEL, SWAP_LOCKUP_CONTRACT_TYPE, type SealedClaimPacket, type SolverLightningRailDeps, type SolverLightningSend, type SolverOnchainRailDeps, type SolverOnchainSend, type SolverRendezvous, type SpendKind, type SwapActivityInput, SwapSecretsProjection, type Tx, type WatchOfferSwapsParams, appendArkadeScript, arkadeRefunder, awaitLockupFunding, cancelOffer, chainSourceFrom, claimPacketShape, claimReceiveLockup, classifyDepositSpend, classifySpend, covclaimdClient, createOffer, crossAssetRail, decodeOffer, discoverMarkets, encodeOffer, fillOffer, findMarket, isRfqMarket, lockupContractParams, makeCachedFeedFetch, marketAssetId, marketCorridor, marketPairLabel, offerVtxoScript, onchainSendProfile, pushClaim, registerAssetSwapRestore, registerLockupContract, requestLightningSend, requestOnchainSend, restoreAssetSwapRepository, restoreAssetSwaps, restoreOfferCoverage, retireSettledOfferContracts, revealClaimPacket, revealFieldsFromScript, rfqClaimSecretOf, rfqSecretsProfile, rfqSignerOf, rfqSwapActivityInputs, sealClaimPacket, senderIdentityForSwapRecord, solverLightningRail, solverLightningRendezvous, solverOnchainRail, solverOnchainRendezvous, solverRendezvous, spendTxidsOf, spendUpdate, swapActivityResolver, swapPrograms, validatePlan, watchOfferSwaps };
1509
+ export { ASSET_CARRIER_SATS, ArkadeRefundResult, type ArkadeRefunderDeps, AssetSwap, AssetSwapRepository, type AssetSwapRestoreChange, CLAIM_PACKET_TYPE, CROSS_ASSET_RAIL, ChainSource, type ClaimArkProvider, type ClaimPacketInput, type ClaimPacketShape, type CovclaimdClient, type CovclaimdInfo, CovclaimdRevealError, type CrossAssetPhase, type CrossAssetRailDeps, type CrossAssetSwap, type DiscoverMarketsOptions, type FillFunding, IndexedDbAssetSwapRepository, InvoiceFacts, type LightningReceiveProfile, type LightningSendProfile, LockupAmountMismatchError, LockupContractMissing, type LockupContractReader, LockupContractSource, type LockupContractWriter, LockupRegistrationFailed, LockupSpendIndexer, LockupVtxo, MARKET_CORRIDORS, type MarketCorridor, type MarketLike, MarketsCacheEntry, OFFER_PACKET_TYPE, type Offer, type OfferContractRetirer, type OfferSwapWatcher, OnchainHtlc, OnchainHtlcParams, OnchainNetwork, type OnchainSendProfile, type PlanError, QUOTE_OPTIONS, RefundArkProvider, type RefundBlockedReason, RefundNotLocallyPossibleError, type RegisterAssetSwapRestoreOptions, type RestoreAssetSwapRepositoryOptions, type RestoreAssetSwapRepositoryResult, type RestoreIndexer, type RevealParams, type RfqClaimSecretProjection, type RfqHashlockProjection, type RfqSignerProjection, RfqSwap, type RfqSwapActivityDeps, RfqSwapRecord, RfqSwapState, RfqTransport, SEALED_CIPHERTEXT_LENGTH, SOLVER_LIGHTNING_RAIL, SOLVER_ONCHAIN_RAIL, SWAP_LOCKUP_CONTRACT_KIND, SWAP_LOCKUP_CONTRACT_LABEL, SWAP_LOCKUP_CONTRACT_TYPE, type SealedClaimPacket, type SolverLightningRailDeps, type SolverLightningSend, type SolverOnchainRailDeps, type SolverOnchainSend, type SolverRendezvous, type SpendKind, type SwapActivityInput, SwapSecretsProjection, type Tx, type WatchOfferSwapsParams, appendArkadeScript, arkadeRefunder, awaitLockupFunding, cancelOffer, chainSourceFrom, claimPacketShape, claimReceiveLockup, classifyDepositSpend, classifySpend, covclaimdClient, createOffer, crossAssetRail, decodeOffer, discoverMarkets, encodeOffer, fillOffer, findMarket, isRfqMarket, lockupContractParams, makeCachedFeedFetch, marketAssetId, marketCorridor, marketPairLabel, offerVtxoScript, onchainSendProfile, pushClaim, registerAssetSwapRestore, registerLockupContract, requestLightningSend, requestOnchainSend, restoreAssetSwapRepository, restoreAssetSwaps, restoreOfferCoverage, retireSettledOfferContracts, revealClaimPacket, revealFieldsFromScript, rfqClaimSecretOf, rfqSecretsProfile, rfqSignerOf, rfqSwapActivityInputs, sealClaimPacket, senderIdentityForSwapRecord, solverLightningRail, solverLightningRendezvous, solverOnchainRail, solverOnchainRendezvous, solverRendezvous, spendTxidsOf, spendUpdate, swapActivityResolver, swapPrograms, validatePlan, watchOfferSwaps };
package/dist/index.d.ts CHANGED
@@ -1,9 +1,9 @@
1
1
  import { ProvisionedKey, ProvisionedClaimSecret, ArkTxInput, asset, RelativeTimelock, IWallet, EmulatorProvider, arkade, RestIndexerProvider, Transaction, IContractManager, OnchainProvider, PaymentRail, Asset, VHTLC, Identity, ActivityResolver } from '@arkade-os/sdk';
2
- import { S as SwapSecretsProjection, R as RfqSwapRecord, A as AssetSwapRepository, a as AssetSwap, M as MarketsCacheEntry, b as RefundArkProvider, c as RefundIndexer, L as LockupVtxo, d as RfqSwap, e as ArkadeRefundResult, f as LockupSpendIndexer, g as RfqSwapState } from './repository-B6VPDGHC.js';
3
- export { h as AssetSwapStatus, i as AvailableRfqSwapManagerCallbacks, B as BTC_ASSET_ID, I as InMemoryAssetSwapRepository, j as LightningReceiveSwap, k as LightningSendSwap, l as LockupFate, m as LockupNeedsRecoveryError, n as LockupParams, o as LockupSpend, O as OnchainSendAction, p as OnchainSendSwap, P as PersistableRfqSwap, q as PreimageBlockedReason, r as PreimageNotRecoverableError, s as REFUND_MTP_LAG_SECONDS, t as RFQ_RESOLVED_STATES, u as RFQ_SWAP_RETENTION_SECONDS, v as RFQ_SWAP_TERMINAL_STATES, w as RefundOutcome, x as RfqRestoreFailure, y as RfqRestoreOptions, z as RfqRestoreResult, C as RfqSwapActionName, D as RfqSwapLockup, E as RfqSwapManager, F as RfqSwapManagerCallbacks, G as RfqSwapManagerConfig, H as RfqSwapManagerDeps, J as RfqSwapManagerEvents, K as RfqSwapOrigin, N as RfqSwapOriginRequired, Q as RfqSwapOutcome, T as RfqSwapRecordStore, U as SwapContractRegistry, V as addAssetSwap, W as awaitRfqResolution, X as createRfqSwapRecord, Y as findLockupVtxos, Z as getAssetSwaps, _ as getAssetSwapsOrThrow, $ as isRfqSwapTerminal, a0 as isRfqTerminal, a1 as nextOnchainAction, a2 as preimageForSwapRecord, a3 as pushRefundWithoutReceiver, a4 as readLockupFate, a5 as rebuildRfqSwap, a6 as refundIfUnresolved, a7 as rfqSwapOriginOf, a8 as shouldRetainRfqSwap, a9 as swapSecretsToRecord, aa as updateAssetSwap, ab as updateAssetSwapBestEffort, ac as updateRfqSwapRecord } from './repository-B6VPDGHC.js';
2
+ import { S as SwapSecretsProjection, R as RfqSwapRecord, A as AssetSwapRepository, a as AssetSwap, M as MarketsCacheEntry, b as RefundArkProvider, L as LockupContractSource, c as LockupVtxo, d as RfqSwap, e as ArkadeRefundResult, f as LockupSpendIndexer, g as RfqSwapState } from './repository-PNlTFdsj.js';
3
+ export { h as AssetSwapStatus, i as AvailableRfqSwapManagerCallbacks, B as BTC_ASSET_ID, I as InMemoryAssetSwapRepository, j as LightningReceiveSwap, k as LightningSendSwap, l as LockupFate, m as LockupNeedsRecoveryError, n as LockupParams, o as LockupSpend, O as OnchainSendAction, p as OnchainSendSwap, P as PersistableRfqSwap, q as PreimageBlockedReason, r as PreimageNotRecoverableError, s as REFUND_MTP_LAG_SECONDS, t as RFQ_RESOLVED_STATES, u as RFQ_SWAP_RETENTION_SECONDS, v as RFQ_SWAP_TERMINAL_STATES, w as RefundOutcome, x as RfqRestoreFailure, y as RfqRestoreOptions, z as RfqRestoreResult, C as RfqSwapActionName, D as RfqSwapLockup, E as RfqSwapManager, F as RfqSwapManagerCallbacks, G as RfqSwapManagerConfig, H as RfqSwapManagerDeps, J as RfqSwapManagerEvents, K as RfqSwapOrigin, N as RfqSwapOriginRequired, Q as RfqSwapOutcome, T as RfqSwapRecordStore, U as SwapContractRegistry, V as addAssetSwap, W as awaitRfqResolution, X as createRfqSwapRecord, Y as findLockupVtxos, Z as getAssetSwaps, _ as getAssetSwapsOrThrow, $ as isRfqSwapTerminal, a0 as isRfqTerminal, a1 as nextOnchainAction, a2 as preimageForSwapRecord, a3 as pushRefundWithoutReceiver, a4 as readLockupFate, a5 as rebuildRfqSwap, a6 as refundIfUnresolved, a7 as rfqSwapOriginOf, a8 as shouldRetainRfqSwap, a9 as swapSecretsToRecord, aa as updateAssetSwap, ab as updateAssetSwapBestEffort, ac as updateRfqSwapRecord } from './repository-PNlTFdsj.js';
4
4
  import { Network, LocalCardInput, DiscoveredMarket, Side, OfferPlan } from '@arkade-os/solver-discovery';
5
- import { O as OnchainNetwork, a as OnchainHtlc, b as OnchainHtlcParams, C as ChainSource, R as RfqTransport, r as requestOnchainSend, I as InvoiceFacts, c as requestLightningSend } from './rfq-D96aLvCA.js';
6
- export { A as ARKADE_ASSET, d as ARKADE_BTC, e as AddressMismatch, f as ChainUtxo, H as HtlcUtxo, L as LIGHTNING_BTC, g as LIGHTNING_RECEIVE_PAIR, h as LIGHTNING_SEND_PAIR, i as LOCKTIME_THRESHOLD, j as LightningReceiveTreeParams, k as LightningSendTreeParams, M as MAX_MIN_CONFIRMATIONS, l as MIN_CLAIM_WINDOW_SECONDS, m as MIN_HEADROOM_SECONDS, n as ONCHAIN_BTC, o as ONCHAIN_CLAIM_MARGIN_SECONDS, p as ONCHAIN_DUST_SATS, q as ONCHAIN_ORDER_MARGIN_SECONDS, s as ONCHAIN_RECEIVE_PAIR, t as ONCHAIN_SECONDS_PER_BLOCK, u as ONCHAIN_SEND_PAIR, v as OnchainHtlcPhase, w as RFQ_REFUSAL_ERROR_CODES, x as RFQ_TERMINAL_STATES, y as RelaySocket, z as RfqQuote, B as RfqRefusalDetail, D as RfqRefusalErrorCode, E as RfqRefusalReason, F as RfqRefusalUnit, G as RfqStatus, S as SOLO_REFUND_HEADROOM_SECONDS, J as SwapRefusal, K as arkadeAssetLeg, N as arkadeSwapRequest, P as assertArkadeFundable, Q as assertFundable, T as assertReceivable, U as awaitOnchainFill, V as buildHtlcClaim, W as buildHtlcRefund, X as canonicalAssetAmount, Y as claimOnchainFill, Z as classifyOnchainHtlc, _ as deriveLightningReceive, $ as deriveOnchainReceive, a0 as deriveOnchainSend, a1 as extractPreimage, a2 as httpTransport, a3 as isRfqRefusalErrorCode, a4 as l1ScriptForAddress, a5 as lightningReceiveRequest, a6 as lightningSendRequest, a7 as lightningSendVtxoScript, a8 as newPreimage, a9 as newRfqId, aa as normalizeMakerPkScript, ab as normalizeMakerPublicKey, ac as offerTermsFromQuote, ad as onchainHtlcScript, ae as onchainReceiveRequest, af as onchainSendRequest, ag as paymentHashOf, ah as receiveVtxoScript, ai as relayTransport, aj as requestArkadeSwap, ak as requestLightningReceive, al as requestOnchainReceive, am as rfqPair, an as unilateralClaimDelay, ao as unilateralRefundDelay, ap as unilateralRefundWithoutReceiverDelay, aq as verifyLockupAddress, ar as verifyOfferAddress, as as verifyReceiveInvoice } from './rfq-D96aLvCA.js';
5
+ import { O as OnchainNetwork, a as OnchainHtlc, b as OnchainHtlcParams, C as ChainSource, R as RfqTransport, r as requestOnchainSend, I as InvoiceFacts, c as requestLightningSend } from './rfq-B95nPfaa.js';
6
+ export { A as ARKADE_ASSET, d as ARKADE_BTC, e as AddressMismatch, f as ChainUtxo, H as HtlcUtxo, L as LIGHTNING_BTC, g as LIGHTNING_RECEIVE_PAIR, h as LIGHTNING_SEND_PAIR, i as LOCKTIME_THRESHOLD, j as LightningReceiveTreeParams, k as LightningSendTreeParams, M as MAX_MIN_CONFIRMATIONS, l as MIN_CLAIM_WINDOW_SECONDS, m as MIN_HEADROOM_SECONDS, n as ONCHAIN_BTC, o as ONCHAIN_CLAIM_MARGIN_SECONDS, p as ONCHAIN_DUST_SATS, q as ONCHAIN_ORDER_MARGIN_SECONDS, s as ONCHAIN_RECEIVE_PAIR, t as ONCHAIN_SECONDS_PER_BLOCK, u as ONCHAIN_SEND_PAIR, v as OnchainHtlcPhase, w as RFQ_REFUSAL_ERROR_CODES, x as RFQ_TERMINAL_STATES, y as RelaySocket, z as RfqQuote, B as RfqRefusalDetail, D as RfqRefusalErrorCode, E as RfqRefusalReason, F as RfqRefusalUnit, G as RfqStatus, S as SOLO_REFUND_HEADROOM_SECONDS, J as SwapRefusal, K as arkadeAssetLeg, N as arkadeSwapRequest, P as assertArkadeFundable, Q as assertFundable, T as assertReceivable, U as awaitOnchainFill, V as buildHtlcClaim, W as buildHtlcRefund, X as canonicalAssetAmount, Y as claimOnchainFill, Z as classifyOnchainHtlc, _ as deriveLightningReceive, $ as deriveOnchainReceive, a0 as deriveOnchainSend, a1 as extractPreimage, a2 as httpTransport, a3 as isRfqRefusalErrorCode, a4 as l1ScriptForAddress, a5 as lightningReceiveRequest, a6 as lightningSendRequest, a7 as lightningSendVtxoScript, a8 as newPreimage, a9 as newRfqId, aa as normalizeMakerPkScript, ab as normalizeMakerPublicKey, ac as offerTermsFromQuote, ad as onchainHtlcScript, ae as onchainReceiveRequest, af as onchainSendRequest, ag as paymentHashOf, ah as receiveVtxoScript, ai as relayTransport, aj as requestArkadeSwap, ak as requestLightningReceive, al as requestOnchainReceive, am as rfqPair, an as unilateralClaimDelay, ao as unilateralRefundDelay, ap as unilateralRefundWithoutReceiverDelay, aq as verifyLockupAddress, ar as verifyOfferAddress, as as verifyReceiveInvoice } from './rfq-B95nPfaa.js';
7
7
 
8
8
  /**
9
9
  * Which wallet key signs this leg. Stored at `profile.signer`.
@@ -1241,7 +1241,7 @@ declare function pushClaim(ark: ClaimArkProvider, input: {
1241
1241
  * unix-seconds `deadline`, and a thrown error carrying a stable `reason` when
1242
1242
  * the deadline passes.
1243
1243
  */
1244
- declare function awaitLockupFunding(indexer: RefundIndexer, swapPkScript: Uint8Array, options?: {
1244
+ declare function awaitLockupFunding(contracts: LockupContractSource, swapPkScript: Uint8Array, options?: {
1245
1245
  pollMs?: number;
1246
1246
  deadline?: number;
1247
1247
  }): Promise<readonly LockupVtxo[]>;
@@ -1258,7 +1258,7 @@ declare function awaitLockupFunding(indexer: RefundIndexer, swapPkScript: Uint8A
1258
1258
  * rest lands is safe — and that is also the answer to a genuinely underfunded
1259
1259
  * lockup, which never gets past the gate at all.
1260
1260
  */
1261
- declare function claimReceiveLockup(indexer: RefundIndexer, ark: ClaimArkProvider, input: Parameters<typeof pushClaim>[1] & {
1261
+ declare function claimReceiveLockup(contracts: LockupContractSource, ark: ClaimArkProvider, input: Parameters<typeof pushClaim>[1] & {
1262
1262
  /** The covenant's scriptPubKey, from the request flow's `swapPkScript`. */
1263
1263
  swapPkScript: Uint8Array;
1264
1264
  pollMs?: number;
@@ -1332,7 +1332,14 @@ declare function senderIdentityForSwapRecord(wallet: IWallet, record: {
1332
1332
 
1333
1333
  interface ArkadeRefunderDeps {
1334
1334
  ark: RefundArkProvider;
1335
- indexer: RefundIndexer;
1335
+ /**
1336
+ * The wallet's contract manager. The lockup's row must be registered in
1337
+ * it before this can see the funding — which is what
1338
+ * `RfqSwapManager.ensureRegistered` does per pass, and what
1339
+ * `requestLightningSend` / `requestOnchainSend` do up front. Prefer
1340
+ * `await wallet.getContractManager()`.
1341
+ */
1342
+ contracts: LockupContractSource;
1336
1343
  /** Asked for the descriptor's signer; never asked to mint a key. */
1337
1344
  wallet: IWallet;
1338
1345
  /**
@@ -1347,7 +1354,7 @@ interface ArkadeRefunderDeps {
1347
1354
  *
1348
1355
  * @example
1349
1356
  * manager.setCallbacks({
1350
- * refundArkade: arkadeRefunder({ ark, indexer, wallet, repository }),
1357
+ * refundArkade: arkadeRefunder({ ark, contracts, wallet, repository }),
1351
1358
  * saveSwap,
1352
1359
  * });
1353
1360
  */
@@ -1499,4 +1506,4 @@ interface RfqSwapActivityDeps {
1499
1506
  */
1500
1507
  declare function rfqSwapActivityInputs(deps: RfqSwapActivityDeps): Promise<SwapActivityInput[]>;
1501
1508
 
1502
- export { ASSET_CARRIER_SATS, ArkadeRefundResult, type ArkadeRefunderDeps, AssetSwap, AssetSwapRepository, type AssetSwapRestoreChange, CLAIM_PACKET_TYPE, CROSS_ASSET_RAIL, ChainSource, type ClaimArkProvider, type ClaimPacketInput, type ClaimPacketShape, type CovclaimdClient, type CovclaimdInfo, CovclaimdRevealError, type CrossAssetPhase, type CrossAssetRailDeps, type CrossAssetSwap, type DiscoverMarketsOptions, type FillFunding, IndexedDbAssetSwapRepository, InvoiceFacts, type LightningReceiveProfile, type LightningSendProfile, LockupAmountMismatchError, LockupContractMissing, type LockupContractReader, type LockupContractWriter, LockupRegistrationFailed, LockupSpendIndexer, LockupVtxo, MARKET_CORRIDORS, type MarketCorridor, type MarketLike, MarketsCacheEntry, OFFER_PACKET_TYPE, type Offer, type OfferContractRetirer, type OfferSwapWatcher, OnchainHtlc, OnchainHtlcParams, OnchainNetwork, type OnchainSendProfile, type PlanError, QUOTE_OPTIONS, RefundArkProvider, type RefundBlockedReason, RefundIndexer, RefundNotLocallyPossibleError, type RegisterAssetSwapRestoreOptions, type RestoreAssetSwapRepositoryOptions, type RestoreAssetSwapRepositoryResult, type RestoreIndexer, type RevealParams, type RfqClaimSecretProjection, type RfqHashlockProjection, type RfqSignerProjection, RfqSwap, type RfqSwapActivityDeps, RfqSwapRecord, RfqSwapState, RfqTransport, SEALED_CIPHERTEXT_LENGTH, SOLVER_LIGHTNING_RAIL, SOLVER_ONCHAIN_RAIL, SWAP_LOCKUP_CONTRACT_KIND, SWAP_LOCKUP_CONTRACT_LABEL, SWAP_LOCKUP_CONTRACT_TYPE, type SealedClaimPacket, type SolverLightningRailDeps, type SolverLightningSend, type SolverOnchainRailDeps, type SolverOnchainSend, type SolverRendezvous, type SpendKind, type SwapActivityInput, SwapSecretsProjection, type Tx, type WatchOfferSwapsParams, appendArkadeScript, arkadeRefunder, awaitLockupFunding, cancelOffer, chainSourceFrom, claimPacketShape, claimReceiveLockup, classifyDepositSpend, classifySpend, covclaimdClient, createOffer, crossAssetRail, decodeOffer, discoverMarkets, encodeOffer, fillOffer, findMarket, isRfqMarket, lockupContractParams, makeCachedFeedFetch, marketAssetId, marketCorridor, marketPairLabel, offerVtxoScript, onchainSendProfile, pushClaim, registerAssetSwapRestore, registerLockupContract, requestLightningSend, requestOnchainSend, restoreAssetSwapRepository, restoreAssetSwaps, restoreOfferCoverage, retireSettledOfferContracts, revealClaimPacket, revealFieldsFromScript, rfqClaimSecretOf, rfqSecretsProfile, rfqSignerOf, rfqSwapActivityInputs, sealClaimPacket, senderIdentityForSwapRecord, solverLightningRail, solverLightningRendezvous, solverOnchainRail, solverOnchainRendezvous, solverRendezvous, spendTxidsOf, spendUpdate, swapActivityResolver, swapPrograms, validatePlan, watchOfferSwaps };
1509
+ export { ASSET_CARRIER_SATS, ArkadeRefundResult, type ArkadeRefunderDeps, AssetSwap, AssetSwapRepository, type AssetSwapRestoreChange, CLAIM_PACKET_TYPE, CROSS_ASSET_RAIL, ChainSource, type ClaimArkProvider, type ClaimPacketInput, type ClaimPacketShape, type CovclaimdClient, type CovclaimdInfo, CovclaimdRevealError, type CrossAssetPhase, type CrossAssetRailDeps, type CrossAssetSwap, type DiscoverMarketsOptions, type FillFunding, IndexedDbAssetSwapRepository, InvoiceFacts, type LightningReceiveProfile, type LightningSendProfile, LockupAmountMismatchError, LockupContractMissing, type LockupContractReader, LockupContractSource, type LockupContractWriter, LockupRegistrationFailed, LockupSpendIndexer, LockupVtxo, MARKET_CORRIDORS, type MarketCorridor, type MarketLike, MarketsCacheEntry, OFFER_PACKET_TYPE, type Offer, type OfferContractRetirer, type OfferSwapWatcher, OnchainHtlc, OnchainHtlcParams, OnchainNetwork, type OnchainSendProfile, type PlanError, QUOTE_OPTIONS, RefundArkProvider, type RefundBlockedReason, RefundNotLocallyPossibleError, type RegisterAssetSwapRestoreOptions, type RestoreAssetSwapRepositoryOptions, type RestoreAssetSwapRepositoryResult, type RestoreIndexer, type RevealParams, type RfqClaimSecretProjection, type RfqHashlockProjection, type RfqSignerProjection, RfqSwap, type RfqSwapActivityDeps, RfqSwapRecord, RfqSwapState, RfqTransport, SEALED_CIPHERTEXT_LENGTH, SOLVER_LIGHTNING_RAIL, SOLVER_ONCHAIN_RAIL, SWAP_LOCKUP_CONTRACT_KIND, SWAP_LOCKUP_CONTRACT_LABEL, SWAP_LOCKUP_CONTRACT_TYPE, type SealedClaimPacket, type SolverLightningRailDeps, type SolverLightningSend, type SolverOnchainRailDeps, type SolverOnchainSend, type SolverRendezvous, type SpendKind, type SwapActivityInput, SwapSecretsProjection, type Tx, type WatchOfferSwapsParams, appendArkadeScript, arkadeRefunder, awaitLockupFunding, cancelOffer, chainSourceFrom, claimPacketShape, claimReceiveLockup, classifyDepositSpend, classifySpend, covclaimdClient, createOffer, crossAssetRail, decodeOffer, discoverMarkets, encodeOffer, fillOffer, findMarket, isRfqMarket, lockupContractParams, makeCachedFeedFetch, marketAssetId, marketCorridor, marketPairLabel, offerVtxoScript, onchainSendProfile, pushClaim, registerAssetSwapRestore, registerLockupContract, requestLightningSend, requestOnchainSend, restoreAssetSwapRepository, restoreAssetSwaps, restoreOfferCoverage, retireSettledOfferContracts, revealClaimPacket, revealFieldsFromScript, rfqClaimSecretOf, rfqSecretsProfile, rfqSignerOf, rfqSwapActivityInputs, sealClaimPacket, senderIdentityForSwapRecord, solverLightningRail, solverLightningRendezvous, solverOnchainRail, solverOnchainRendezvous, solverRendezvous, spendTxidsOf, spendUpdate, swapActivityResolver, swapPrograms, validatePlan, watchOfferSwaps };
package/dist/index.js CHANGED
@@ -100,7 +100,7 @@ import {
100
100
  verifyLockupAddress,
101
101
  verifyOfferAddress,
102
102
  verifyReceiveInvoice
103
- } from "./chunk-D7GDHZCG.js";
103
+ } from "./chunk-QJKMTPRQ.js";
104
104
  import {
105
105
  InMemoryAssetSwapRepository,
106
106
  marketsCacheKey
@@ -1792,30 +1792,26 @@ var LockupNeedsRecoveryError = class extends Error {
1792
1792
  this.recoverableAfter = recoverableAfter;
1793
1793
  }
1794
1794
  };
1795
- async function findLockupVtxos(indexer, swapPkScript) {
1796
- const scripts = [hex8.encode(swapPkScript)];
1797
- const [spendable, recoverable] = await Promise.all([
1798
- indexer.getVtxos({ scripts, spendableOnly: true }),
1799
- indexer.getVtxos({ scripts, recoverableOnly: true })
1800
- ]);
1795
+ async function findLockupVtxos(contracts, swapPkScript) {
1796
+ const [row] = await contracts.getContractsWithVtxos({
1797
+ script: hex8.encode(swapPkScript)
1798
+ });
1801
1799
  const seen = /* @__PURE__ */ new Set();
1802
1800
  const out = [];
1803
- for (const [vtxos, isRecoverable] of [
1804
- [spendable.vtxos ?? [], false],
1805
- [recoverable.vtxos ?? [], true]
1806
- ]) {
1807
- for (const vtxo of vtxos) {
1808
- if (vtxo.isUnrolled) continue;
1809
- const key = `${vtxo.txid}:${vtxo.vout}`;
1810
- if (seen.has(key)) continue;
1811
- seen.add(key);
1812
- out.push({
1813
- txid: vtxo.txid,
1814
- vout: vtxo.vout,
1815
- value: Number(vtxo.value),
1816
- recoverable: isRecoverable
1817
- });
1818
- }
1801
+ for (const vtxo of row?.vtxos ?? []) {
1802
+ if (vtxo.isUnrolled) continue;
1803
+ if (hasTerminalSpend(vtxo)) continue;
1804
+ const key = `${vtxo.txid}:${vtxo.vout}`;
1805
+ if (seen.has(key)) continue;
1806
+ seen.add(key);
1807
+ out.push({
1808
+ txid: vtxo.txid,
1809
+ vout: vtxo.vout,
1810
+ value: Number(vtxo.value),
1811
+ // The manager's canonical `isSwept` fact; no coercion, because the
1812
+ // normalized row guarantees a boolean.
1813
+ recoverable: vtxo.isSwept
1814
+ });
1819
1815
  }
1820
1816
  return out;
1821
1817
  }
@@ -1927,7 +1923,7 @@ async function pushRefundWithoutReceiver(ark, input) {
1927
1923
  return { arkTxid: submitted.arkTxid, amount };
1928
1924
  }
1929
1925
  var REFUND_MTP_LAG_SECONDS = 2 * 60 * 60;
1930
- async function refundIfUnresolved(transport, ark, indexer, input) {
1926
+ async function refundIfUnresolved(transport, ark, contracts, indexer, input) {
1931
1927
  const pollMs = input.pollMs ?? 5e3;
1932
1928
  const now = input.now ?? (() => Math.floor(Date.now() / 1e3));
1933
1929
  const attemptDeadline = input.attemptDeadline ?? input.refundLocktime + REFUND_MTP_LAG_SECONDS;
@@ -1950,7 +1946,7 @@ async function refundIfUnresolved(transport, ark, indexer, input) {
1950
1946
  status
1951
1947
  };
1952
1948
  }
1953
- const vtxos = await findLockupVtxos(indexer, input.script.pkScript);
1949
+ const vtxos = await findLockupVtxos(contracts, input.script.pkScript);
1954
1950
  if (vtxos.length === 0) return { outcome: "nothing_to_refund", status };
1955
1951
  try {
1956
1952
  const pushed = await pushRefundWithoutReceiver(ark, {
@@ -2045,10 +2041,10 @@ async function pushClaim(ark, input) {
2045
2041
  });
2046
2042
  return { arkTxid, amount: locked };
2047
2043
  }
2048
- async function awaitLockupFunding(indexer, swapPkScript, options = {}) {
2044
+ async function awaitLockupFunding(contracts, swapPkScript, options = {}) {
2049
2045
  const pollMs = options.pollMs ?? 5e3;
2050
2046
  for (; ; ) {
2051
- const vtxos = await findLockupVtxos(indexer, swapPkScript);
2047
+ const vtxos = await findLockupVtxos(contracts, swapPkScript);
2052
2048
  if (vtxos.length > 0) return vtxos;
2053
2049
  if (options.deadline !== void 0 && Date.now() / 1e3 >= options.deadline) {
2054
2050
  const error = new Error("the lockup never appeared at the covenant script");
@@ -2058,8 +2054,8 @@ async function awaitLockupFunding(indexer, swapPkScript, options = {}) {
2058
2054
  await sleep2(pollMs);
2059
2055
  }
2060
2056
  }
2061
- async function claimReceiveLockup(indexer, ark, input) {
2062
- const vtxos = await awaitLockupFunding(indexer, input.swapPkScript, {
2057
+ async function claimReceiveLockup(contracts, ark, input) {
2058
+ const vtxos = await awaitLockupFunding(contracts, input.swapPkScript, {
2063
2059
  pollMs: input.pollMs,
2064
2060
  deadline: input.deadline
2065
2061
  });
@@ -2125,7 +2121,7 @@ function arkadeRefunder(deps) {
2125
2121
  `swap ${swap.rfqId} carries no lockup covenant, so its refund cannot be built`
2126
2122
  );
2127
2123
  }
2128
- const vtxos = await findLockupVtxos(deps.indexer, swap.lockupPkScript);
2124
+ const vtxos = await findLockupVtxos(deps.contracts, swap.lockupPkScript);
2129
2125
  if (vtxos.length === 0) return null;
2130
2126
  const record = await deps.repository.getRfqSwap(swap.rfqId);
2131
2127
  if (!record) {
@@ -2750,7 +2746,10 @@ var RfqSwapManager = class {
2750
2746
  return;
2751
2747
  }
2752
2748
  if (swap.kind === "lightning_receive") {
2753
- return fate.fate === "exited" ? this.blockExitedLockup(swap, fate) : this.driveReceiveClaim(swap);
2749
+ if (fate.fate === "exited") return this.blockExitedLockup(swap, fate);
2750
+ if (fate.fate === "open") return this.driveReceiveClaim(swap);
2751
+ if (this.config.now() >= swap.refundLocktime) return this.driveReceiveClaim(swap);
2752
+ return;
2754
2753
  }
2755
2754
  if (swap.kind === "onchain_send" && swap.state !== "claimed") {
2756
2755
  if (await this.driveOnchain(swap) === "handled") return;
@@ -2805,7 +2804,7 @@ var RfqSwapManager = class {
2805
2804
  if (now < swap.refundLocktime) {
2806
2805
  let vtxos;
2807
2806
  try {
2808
- vtxos = await findLockupVtxos(this.deps.indexer, swap.lockupPkScript);
2807
+ vtxos = await findLockupVtxos(this.deps.contracts, swap.lockupPkScript);
2809
2808
  } catch (error) {
2810
2809
  this.emitFailed(swap, error);
2811
2810
  return;
package/dist/nostr.d.cts CHANGED
@@ -1,4 +1,4 @@
1
- import { R as RfqTransport } from './rfq-D96aLvCA.cjs';
1
+ import { R as RfqTransport } from './rfq-B95nPfaa.cjs';
2
2
  import { SimplePool } from 'nostr-tools';
3
3
  import '@arkade-os/sdk';
4
4
 
package/dist/nostr.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- import { R as RfqTransport } from './rfq-D96aLvCA.js';
1
+ import { R as RfqTransport } from './rfq-B95nPfaa.js';
2
2
  import { SimplePool } from 'nostr-tools';
3
3
  import '@arkade-os/sdk';
4
4
 
package/dist/nostr.js CHANGED
@@ -1,7 +1,7 @@
1
1
  import {
2
2
  expectQuote,
3
3
  pairOf
4
- } from "./chunk-D7GDHZCG.js";
4
+ } from "./chunk-QJKMTPRQ.js";
5
5
 
6
6
  // src/nostr.ts
7
7
  import {
@@ -1,8 +1,8 @@
1
1
  import { RealmLike } from '@arkade-os/sdk/repositories/realm';
2
- import { A as AssetSwapRepository, a as AssetSwap, R as RfqSwapRecord, M as MarketsCacheEntry } from '../../repository-BXIcmIIC.cjs';
2
+ import { A as AssetSwapRepository, a as AssetSwap, R as RfqSwapRecord, M as MarketsCacheEntry } from '../../repository-CZYc8Y38.cjs';
3
3
  import '@arkade-os/solver-discovery';
4
4
  import '@arkade-os/sdk';
5
- import '../../rfq-D96aLvCA.cjs';
5
+ import '../../rfq-B95nPfaa.cjs';
6
6
 
7
7
  /**
8
8
  * Realm backend for React Native.
@@ -1,8 +1,8 @@
1
1
  import { RealmLike } from '@arkade-os/sdk/repositories/realm';
2
- import { A as AssetSwapRepository, a as AssetSwap, R as RfqSwapRecord, M as MarketsCacheEntry } from '../../repository-B6VPDGHC.js';
2
+ import { A as AssetSwapRepository, a as AssetSwap, R as RfqSwapRecord, M as MarketsCacheEntry } from '../../repository-PNlTFdsj.js';
3
3
  import '@arkade-os/solver-discovery';
4
4
  import '@arkade-os/sdk';
5
- import '../../rfq-D96aLvCA.js';
5
+ import '../../rfq-B95nPfaa.js';
6
6
 
7
7
  /**
8
8
  * Realm backend for React Native.
@@ -1,8 +1,8 @@
1
1
  import { SQLExecutor } from '@arkade-os/sdk/repositories/sqlite';
2
- import { A as AssetSwapRepository, a as AssetSwap, R as RfqSwapRecord, M as MarketsCacheEntry } from '../../repository-BXIcmIIC.cjs';
2
+ import { A as AssetSwapRepository, a as AssetSwap, R as RfqSwapRecord, M as MarketsCacheEntry } from '../../repository-CZYc8Y38.cjs';
3
3
  import '@arkade-os/solver-discovery';
4
4
  import '@arkade-os/sdk';
5
- import '../../rfq-D96aLvCA.cjs';
5
+ import '../../rfq-B95nPfaa.cjs';
6
6
 
7
7
  /**
8
8
  * SQLite backend over the SDK's `SQLExecutor`, so any driver plugs in
@@ -1,8 +1,8 @@
1
1
  import { SQLExecutor } from '@arkade-os/sdk/repositories/sqlite';
2
- import { A as AssetSwapRepository, a as AssetSwap, R as RfqSwapRecord, M as MarketsCacheEntry } from '../../repository-B6VPDGHC.js';
2
+ import { A as AssetSwapRepository, a as AssetSwap, R as RfqSwapRecord, M as MarketsCacheEntry } from '../../repository-PNlTFdsj.js';
3
3
  import '@arkade-os/solver-discovery';
4
4
  import '@arkade-os/sdk';
5
- import '../../rfq-D96aLvCA.js';
5
+ import '../../rfq-B95nPfaa.js';
6
6
 
7
7
  /**
8
8
  * SQLite backend over the SDK's `SQLExecutor`, so any driver plugs in
@@ -1,6 +1,6 @@
1
1
  import { DiscoveredMarket } from '@arkade-os/solver-discovery';
2
- import { IWallet, ProvisionedKey, ProvisionedClaimSecret, RestArkProvider, RestIndexerProvider, VHTLC, Identity, IContractManager } from '@arkade-os/sdk';
3
- import { G as RfqStatus, R as RfqTransport, a as OnchainHtlc, f as ChainUtxo, C as ChainSource, v as OnchainHtlcPhase } from './rfq-D96aLvCA.cjs';
2
+ import { IWallet, ProvisionedKey, ProvisionedClaimSecret, RestArkProvider, IContractManager, RestIndexerProvider, VHTLC, Identity } from '@arkade-os/sdk';
3
+ import { G as RfqStatus, R as RfqTransport, a as OnchainHtlc, f as ChainUtxo, C as ChainSource, v as OnchainHtlcPhase } from './rfq-B95nPfaa.cjs';
4
4
 
5
5
  type AssetSwapStatus = "pending" | "cancelling" | "fulfilled" | "cancelled" | "recoverable" | "awaiting_fill" | "claimable" | "claimed" | "refunded_l1";
6
6
  /** The sentinel asset id for BTC itself, as opposed to a 68-hex asset id.
@@ -213,8 +213,17 @@ declare function awaitRfqResolution(transport: RfqTransport, rfqId: string, opti
213
213
  /** The Ark surface the refund push needs — narrower than a full provider, and
214
214
  * satisfied by {@link RestArkProvider}. Same seam style as `RestoreIndexer`. */
215
215
  type RefundArkProvider = Pick<RestArkProvider, "getInfo" | "submitTx" | "finalizeTx">;
216
- /** The indexer surface the lockup lookup needs. */
217
- type RefundIndexer = Pick<RestIndexerProvider, "getVtxos">;
216
+ /**
217
+ * The contract-manager surface the lockup lookup needs: the registered
218
+ * contract and its VTXOs, in one read.
219
+ *
220
+ * Satisfied structurally by a real `ContractManager`
221
+ * (`await wallet.getContractManager()`), whose `getContractsWithVtxos`
222
+ * performs a best-effort provider sync on every read and serves repository
223
+ * state only when that sync failed retryably — recorded in `getSyncState()`,
224
+ * never silently. {@link findLockupVtxos} trusts this read.
225
+ */
226
+ type LockupContractSource = Pick<IContractManager, "getContractsWithVtxos">;
218
227
  /** A still-refundable virtual output sitting at the swap lockup. */
219
228
  interface LockupVtxo {
220
229
  txid: string;
@@ -309,14 +318,9 @@ declare class LockupNeedsRecoveryError extends Error {
309
318
  * send, and refunding only `vtxos[0]` returns part of the money and strands
310
319
  * the rest at a script whose other refund paths are all longer.
311
320
  *
312
- * BOTH queries, because they are disjoint sets and `spendableOnly` alone goes
313
- * blind at exactly the wrong moment. A lockup whose batch expiry passed is
314
- * swept into the recoverable set, and this function exists to serve swaps that
315
- * sat unresolved — which are precisely the ones most likely to have got there.
316
- * Reading only the spendable set would report `nothing_to_refund` over money
317
- * that is still sitting at the script, which is worse than an error: it looks
318
- * like a resolved swap. `packages/boltz-swap` merges the same two queries for
319
- * the same reason (`arkade-swaps.ts`'s `refundableVtxos`).
321
+ * ONE read from the registered contract row (getContractsWithVtxos), not from the indexer by script.
322
+ * The row's isSwept flag is the authority on which outputs are swept-but-recoverable versus live-spendable,
323
+ * and hasTerminalSpend prunes already-consumed outputs before they reach the caller.
320
324
  *
321
325
  * **Visible is not the same as refundable.** A `recoverable` output cannot be
322
326
  * spent offchain at all — see {@link LockupVtxo.recoverable} — so this set is
@@ -324,12 +328,13 @@ declare class LockupNeedsRecoveryError extends Error {
324
328
  * That function refuses the recoverable ones by name rather than submitting a
325
329
  * spend the server must reject.
326
330
  *
327
- * **Unrolled outputs are the one exception, and are dropped.** A unilaterally
331
+ * **Unrolled and terminally spent outputs are dropped.** A unilaterally
328
332
  * exited output lives onchain behind its CSV; no offchain spend of any leaf can
329
333
  * reach it, and `LockupVtxo` carries no field to say so, so a caller could not
330
- * tell it apart from a live one. Whether arkd returns such an output under
331
- * `spendableOnly` is not determinable from here, so the exclusion is made
332
- * defensively rather than assumed. It costs the two waiting callers nothing
334
+ * tell it apart from a live one. The manager's rows carry the canonical facts
335
+ * (`isUnrolled`, `isSpent`, `spentBy`, `settledBy`), so both exclusions are
336
+ * exact rather than defensive — the same predicate (`hasTerminalSpend`) the
337
+ * wallet's own spend gate uses. It costs the two waiting callers nothing
333
338
  * they wanted: `awaitLockupFunding` keeps waiting for a claimable lockup
334
339
  * instead of publishing `P` into a spend that cannot land, and
335
340
  * `refundIfUnresolved` reports rather than grinding a doomed push to its
@@ -341,23 +346,33 @@ declare class LockupNeedsRecoveryError extends Error {
341
346
  * This read — not the RFQ's reported state — is the authority on whether
342
347
  * there is anything left at the lockup.
343
348
  *
344
- * **Not replaced by the contract manager's VTXO state, deliberately.** Once a
345
- * lockup is registered (see `RfqSwapManagerDeps.contracts`) the wallet tracks
346
- * these same outputs, and `getContractsWithVtxos` plus `canSpendOffchain` /
347
- * `canRecoverOnchain` would classify them. That is a WEAKER answer here on two
348
- * counts: it serves the wallet REPOSITORY, which a degraded sync will happily
349
- * hand back stale (`getSyncState()` reports `degraded` and returns cached rows
350
- * rather than failing), and its height-based expiry test needs a chain tip this
351
- * module does not have. The two queries below ask the indexer itself and need
352
- * neither. Ask-the-indexer, don't-trust-local-state — the same posture
353
- * {@link readLockupFate} takes, and for the same reason: this decides money.
349
+ * **Read from the contract manager, and trust it.** The lookup no longer asks
350
+ * the indexer by script: it reads the lockup's REGISTERED contract row
351
+ * (`getContractsWithVtxos`, see {@link LockupContractSource}) and trusts the
352
+ * answer. Two things make that safe, and both are the manager's to hold:
353
+ * the row must exist — registration writes it before the address can be
354
+ * funded (`requestLightningSend` / `requestOnchainSend` up front,
355
+ * `RfqSwapManager`'s `ensureRegistered` per pass for records made before that
356
+ * existed) — and the read must be fresh, which the manager's per-read
357
+ * best-effort sync provides; when only the repository answers, `getSyncState()`
358
+ * loudly says `degraded` instead of hiding it. An empty row for an
359
+ * unregistered or unfunded lockup is honored as-is: this module does not fall
360
+ * back to a script query behind the manager's back, so `RfqSwapManager` (which
361
+ * supplies the seam via `RfqSwapManagerDeps.contracts`) and standalone callers
362
+ * of {@link refundIfUnresolved} / {@link claimReceiveLockup} own the
363
+ * registration.
364
+ *
365
+ * {@link readLockupFate} is the mirror image, and deliberately so: the fate
366
+ * question needs the spending TRANSACTIONS' witnesses, which the manager does
367
+ * not expose — so it stays a direct indexer read while the money question
368
+ * (what is left here) is the manager's.
354
369
  */
355
- declare function findLockupVtxos(indexer: RefundIndexer, swapPkScript: Uint8Array): Promise<LockupVtxo[]>;
370
+ declare function findLockupVtxos(contracts: LockupContractSource, swapPkScript: Uint8Array): Promise<LockupVtxo[]>;
356
371
  /**
357
372
  * The indexer surface the lockup-spend read needs: the vtxo lookup, plus the
358
373
  * raw transactions those vtxos were spent by. Same narrow-seam style as
359
- * {@link RefundIndexer} and `restore.ts`'s `RestoreIndexer`, and satisfied by
360
- * {@link RestIndexerProvider}.
374
+ * a direct read of {@link RestIndexerProvider}, unlike
375
+ * {@link LockupContractSource}'s contract-manager read.
361
376
  */
362
377
  type LockupSpendIndexer = Pick<RestIndexerProvider, "getVtxos" | "getVirtualTxs">;
363
378
  /**
@@ -454,8 +469,10 @@ type LockupFate =
454
469
  * it is scanned across every output rather than in outpoint order, so which
455
470
  * output happens to come first cannot change the answer.
456
471
  *
457
- * Ask-the-indexer, don't-trust-local-state: read fresh on every poll, never
458
- * cached, the same posture {@link findLockupVtxos} already establishes.
472
+ * Read fresh on every poll, never cached. {@link findLockupVtxos} has since
473
+ * moved to the contract manager's read, but this question needs the spending
474
+ * transactions' witnesses, which the manager does not expose — so the indexer
475
+ * seam stays.
459
476
  */
460
477
  declare function readLockupFate(indexer: LockupSpendIndexer, input: {
461
478
  swapPkScript: Uint8Array;
@@ -619,7 +636,7 @@ type RefundOutcome =
619
636
  * well past the deadline skips straight to the push, and a lockup that is
620
637
  * already empty comes back as `nothing_to_refund` instead of an error.
621
638
  */
622
- declare function refundIfUnresolved(transport: RfqTransport, ark: RefundArkProvider, indexer: LockupSpendIndexer, input: {
639
+ declare function refundIfUnresolved(transport: RfqTransport, ark: RefundArkProvider, contracts: LockupContractSource, indexer: LockupSpendIndexer, input: {
623
640
  rfqId: string;
624
641
  script: InstanceType<typeof VHTLC.ScriptV2>;
625
642
  /** @see pushRefundWithoutReceiver */
@@ -1115,7 +1132,7 @@ interface RfqSwapManagerConfig {
1115
1132
  * seam style as {@link LockupSpendIndexer} and `refund.ts`'s
1116
1133
  * {@link RefundArkProvider}, and satisfied structurally by a real
1117
1134
  * `ContractManager` (`await wallet.getContractManager()`). */
1118
- type SwapContractRegistry = Pick<IContractManager, "createContract" | "getContracts" | "onContractEvent" | "setContractWatchState">;
1135
+ type SwapContractRegistry = Pick<IContractManager, "createContract" | "getContracts" | "getContractsWithVtxos" | "onContractEvent" | "setContractWatchState">;
1119
1136
  /**
1120
1137
  * The record store the manager writes to, narrowed to the four RFQ methods —
1121
1138
  * the same seam style as {@link LockupSpendIndexer} and
@@ -1216,22 +1233,16 @@ interface RfqSwapManagerDeps {
1216
1233
  */
1217
1234
  repository?: RfqSwapRecordStore;
1218
1235
  /**
1219
- * The wallet's contract manager, when there is one. Optional in the same
1220
- * way {@link chain} is: a caller with no wallet, or one that only wants the
1221
- * timer, still gets a fully working manager — the subscription is a
1222
- * LATENCY optimization and nothing depends on it.
1223
- *
1224
- * Supplying it buys two things. The lockup gets REGISTERED, which is what
1225
- * puts it in the wallet's own contract set at all — a prerequisite for
1226
- * anything that has to act on the lockup before its batch expires, since an
1227
- * expired lockup is swept and loses every cooperative path. And the indexer
1228
- * PUSHES its funding and its spend, so a settlement is noticed when it
1229
- * happens rather than up to `pollIntervalMs` later.
1236
+ * The wallet's contract manager. REQUIRED, because under contract-manager
1237
+ * sourcing it is no longer only registration and push: the lockup's own
1238
+ * VTXO state is read through `getContractsWithVtxos`, so the claim and
1239
+ * refund paths cannot work without it and its contract row. The manager
1240
+ * registers that row per pass (`ensureRegistered`).
1230
1241
  *
1231
- * Prefer `await wallet.getContractManager()` over constructing one, the way
1232
- * `createOffer` does.
1242
+ * Prefer `await wallet.getContractManager()` over constructing one, the
1243
+ * way `createOffer` does.
1233
1244
  */
1234
- contracts?: SwapContractRegistry;
1245
+ contracts: SwapContractRegistry;
1235
1246
  }
1236
1247
  /**
1237
1248
  * Watches a set of live RFQ swaps and drives each to its end.
@@ -1959,4 +1970,4 @@ declare class InMemoryAssetSwapRepository implements AssetSwapRepository {
1959
1970
  [Symbol.asyncDispose](): Promise<void>;
1960
1971
  }
1961
1972
 
1962
- export { isRfqSwapTerminal as $, type AssetSwapRepository as A, BTC_ASSET_ID as B, type RfqSwapActionName as C, type RfqSwapLockup as D, RfqSwapManager as E, type RfqSwapManagerCallbacks as F, type RfqSwapManagerConfig as G, type RfqSwapManagerDeps as H, InMemoryAssetSwapRepository as I, type RfqSwapManagerEvents as J, type RfqSwapOrigin as K, type LockupVtxo as L, type MarketsCacheEntry as M, RfqSwapOriginRequired as N, type OnchainSendAction as O, type PersistableRfqSwap as P, type RfqSwapOutcome as Q, type RfqSwapRecord as R, type SwapSecretsProjection as S, type RfqSwapRecordStore as T, type SwapContractRegistry as U, addAssetSwap as V, awaitRfqResolution as W, createRfqSwapRecord as X, findLockupVtxos as Y, getAssetSwaps as Z, getAssetSwapsOrThrow as _, type AssetSwap as a, isRfqTerminal as a0, nextOnchainAction as a1, preimageForSwapRecord as a2, pushRefundWithoutReceiver as a3, readLockupFate as a4, rebuildRfqSwap as a5, refundIfUnresolved as a6, rfqSwapOriginOf as a7, shouldRetainRfqSwap as a8, swapSecretsToRecord as a9, updateAssetSwap as aa, updateAssetSwapBestEffort as ab, updateRfqSwapRecord as ac, type RefundArkProvider as b, type RefundIndexer as c, type RfqSwap as d, type ArkadeRefundResult as e, type LockupSpendIndexer as f, type RfqSwapState as g, type AssetSwapStatus as h, type AvailableRfqSwapManagerCallbacks as i, type LightningReceiveSwap as j, type LightningSendSwap as k, type LockupFate as l, LockupNeedsRecoveryError as m, type LockupParams as n, type LockupSpend as o, type OnchainSendSwap as p, type PreimageBlockedReason as q, PreimageNotRecoverableError as r, REFUND_MTP_LAG_SECONDS as s, RFQ_RESOLVED_STATES as t, RFQ_SWAP_RETENTION_SECONDS as u, RFQ_SWAP_TERMINAL_STATES as v, type RefundOutcome as w, type RfqRestoreFailure as x, type RfqRestoreOptions as y, type RfqRestoreResult as z };
1973
+ export { isRfqSwapTerminal as $, type AssetSwapRepository as A, BTC_ASSET_ID as B, type RfqSwapActionName as C, type RfqSwapLockup as D, RfqSwapManager as E, type RfqSwapManagerCallbacks as F, type RfqSwapManagerConfig as G, type RfqSwapManagerDeps as H, InMemoryAssetSwapRepository as I, type RfqSwapManagerEvents as J, type RfqSwapOrigin as K, type LockupContractSource as L, type MarketsCacheEntry as M, RfqSwapOriginRequired as N, type OnchainSendAction as O, type PersistableRfqSwap as P, type RfqSwapOutcome as Q, type RfqSwapRecord as R, type SwapSecretsProjection as S, type RfqSwapRecordStore as T, type SwapContractRegistry as U, addAssetSwap as V, awaitRfqResolution as W, createRfqSwapRecord as X, findLockupVtxos as Y, getAssetSwaps as Z, getAssetSwapsOrThrow as _, type AssetSwap as a, isRfqTerminal as a0, nextOnchainAction as a1, preimageForSwapRecord as a2, pushRefundWithoutReceiver as a3, readLockupFate as a4, rebuildRfqSwap as a5, refundIfUnresolved as a6, rfqSwapOriginOf as a7, shouldRetainRfqSwap as a8, swapSecretsToRecord as a9, updateAssetSwap as aa, updateAssetSwapBestEffort as ab, updateRfqSwapRecord as ac, type RefundArkProvider as b, type LockupVtxo as c, type RfqSwap as d, type ArkadeRefundResult as e, type LockupSpendIndexer as f, type RfqSwapState as g, type AssetSwapStatus as h, type AvailableRfqSwapManagerCallbacks as i, type LightningReceiveSwap as j, type LightningSendSwap as k, type LockupFate as l, LockupNeedsRecoveryError as m, type LockupParams as n, type LockupSpend as o, type OnchainSendSwap as p, type PreimageBlockedReason as q, PreimageNotRecoverableError as r, REFUND_MTP_LAG_SECONDS as s, RFQ_RESOLVED_STATES as t, RFQ_SWAP_RETENTION_SECONDS as u, RFQ_SWAP_TERMINAL_STATES as v, type RefundOutcome as w, type RfqRestoreFailure as x, type RfqRestoreOptions as y, type RfqRestoreResult as z };
@@ -1,6 +1,6 @@
1
1
  import { DiscoveredMarket } from '@arkade-os/solver-discovery';
2
- import { IWallet, ProvisionedKey, ProvisionedClaimSecret, RestArkProvider, RestIndexerProvider, VHTLC, Identity, IContractManager } from '@arkade-os/sdk';
3
- import { G as RfqStatus, R as RfqTransport, a as OnchainHtlc, f as ChainUtxo, C as ChainSource, v as OnchainHtlcPhase } from './rfq-D96aLvCA.js';
2
+ import { IWallet, ProvisionedKey, ProvisionedClaimSecret, RestArkProvider, IContractManager, RestIndexerProvider, VHTLC, Identity } from '@arkade-os/sdk';
3
+ import { G as RfqStatus, R as RfqTransport, a as OnchainHtlc, f as ChainUtxo, C as ChainSource, v as OnchainHtlcPhase } from './rfq-B95nPfaa.js';
4
4
 
5
5
  type AssetSwapStatus = "pending" | "cancelling" | "fulfilled" | "cancelled" | "recoverable" | "awaiting_fill" | "claimable" | "claimed" | "refunded_l1";
6
6
  /** The sentinel asset id for BTC itself, as opposed to a 68-hex asset id.
@@ -213,8 +213,17 @@ declare function awaitRfqResolution(transport: RfqTransport, rfqId: string, opti
213
213
  /** The Ark surface the refund push needs — narrower than a full provider, and
214
214
  * satisfied by {@link RestArkProvider}. Same seam style as `RestoreIndexer`. */
215
215
  type RefundArkProvider = Pick<RestArkProvider, "getInfo" | "submitTx" | "finalizeTx">;
216
- /** The indexer surface the lockup lookup needs. */
217
- type RefundIndexer = Pick<RestIndexerProvider, "getVtxos">;
216
+ /**
217
+ * The contract-manager surface the lockup lookup needs: the registered
218
+ * contract and its VTXOs, in one read.
219
+ *
220
+ * Satisfied structurally by a real `ContractManager`
221
+ * (`await wallet.getContractManager()`), whose `getContractsWithVtxos`
222
+ * performs a best-effort provider sync on every read and serves repository
223
+ * state only when that sync failed retryably — recorded in `getSyncState()`,
224
+ * never silently. {@link findLockupVtxos} trusts this read.
225
+ */
226
+ type LockupContractSource = Pick<IContractManager, "getContractsWithVtxos">;
218
227
  /** A still-refundable virtual output sitting at the swap lockup. */
219
228
  interface LockupVtxo {
220
229
  txid: string;
@@ -309,14 +318,9 @@ declare class LockupNeedsRecoveryError extends Error {
309
318
  * send, and refunding only `vtxos[0]` returns part of the money and strands
310
319
  * the rest at a script whose other refund paths are all longer.
311
320
  *
312
- * BOTH queries, because they are disjoint sets and `spendableOnly` alone goes
313
- * blind at exactly the wrong moment. A lockup whose batch expiry passed is
314
- * swept into the recoverable set, and this function exists to serve swaps that
315
- * sat unresolved — which are precisely the ones most likely to have got there.
316
- * Reading only the spendable set would report `nothing_to_refund` over money
317
- * that is still sitting at the script, which is worse than an error: it looks
318
- * like a resolved swap. `packages/boltz-swap` merges the same two queries for
319
- * the same reason (`arkade-swaps.ts`'s `refundableVtxos`).
321
+ * ONE read from the registered contract row (getContractsWithVtxos), not from the indexer by script.
322
+ * The row's isSwept flag is the authority on which outputs are swept-but-recoverable versus live-spendable,
323
+ * and hasTerminalSpend prunes already-consumed outputs before they reach the caller.
320
324
  *
321
325
  * **Visible is not the same as refundable.** A `recoverable` output cannot be
322
326
  * spent offchain at all — see {@link LockupVtxo.recoverable} — so this set is
@@ -324,12 +328,13 @@ declare class LockupNeedsRecoveryError extends Error {
324
328
  * That function refuses the recoverable ones by name rather than submitting a
325
329
  * spend the server must reject.
326
330
  *
327
- * **Unrolled outputs are the one exception, and are dropped.** A unilaterally
331
+ * **Unrolled and terminally spent outputs are dropped.** A unilaterally
328
332
  * exited output lives onchain behind its CSV; no offchain spend of any leaf can
329
333
  * reach it, and `LockupVtxo` carries no field to say so, so a caller could not
330
- * tell it apart from a live one. Whether arkd returns such an output under
331
- * `spendableOnly` is not determinable from here, so the exclusion is made
332
- * defensively rather than assumed. It costs the two waiting callers nothing
334
+ * tell it apart from a live one. The manager's rows carry the canonical facts
335
+ * (`isUnrolled`, `isSpent`, `spentBy`, `settledBy`), so both exclusions are
336
+ * exact rather than defensive — the same predicate (`hasTerminalSpend`) the
337
+ * wallet's own spend gate uses. It costs the two waiting callers nothing
333
338
  * they wanted: `awaitLockupFunding` keeps waiting for a claimable lockup
334
339
  * instead of publishing `P` into a spend that cannot land, and
335
340
  * `refundIfUnresolved` reports rather than grinding a doomed push to its
@@ -341,23 +346,33 @@ declare class LockupNeedsRecoveryError extends Error {
341
346
  * This read — not the RFQ's reported state — is the authority on whether
342
347
  * there is anything left at the lockup.
343
348
  *
344
- * **Not replaced by the contract manager's VTXO state, deliberately.** Once a
345
- * lockup is registered (see `RfqSwapManagerDeps.contracts`) the wallet tracks
346
- * these same outputs, and `getContractsWithVtxos` plus `canSpendOffchain` /
347
- * `canRecoverOnchain` would classify them. That is a WEAKER answer here on two
348
- * counts: it serves the wallet REPOSITORY, which a degraded sync will happily
349
- * hand back stale (`getSyncState()` reports `degraded` and returns cached rows
350
- * rather than failing), and its height-based expiry test needs a chain tip this
351
- * module does not have. The two queries below ask the indexer itself and need
352
- * neither. Ask-the-indexer, don't-trust-local-state — the same posture
353
- * {@link readLockupFate} takes, and for the same reason: this decides money.
349
+ * **Read from the contract manager, and trust it.** The lookup no longer asks
350
+ * the indexer by script: it reads the lockup's REGISTERED contract row
351
+ * (`getContractsWithVtxos`, see {@link LockupContractSource}) and trusts the
352
+ * answer. Two things make that safe, and both are the manager's to hold:
353
+ * the row must exist — registration writes it before the address can be
354
+ * funded (`requestLightningSend` / `requestOnchainSend` up front,
355
+ * `RfqSwapManager`'s `ensureRegistered` per pass for records made before that
356
+ * existed) — and the read must be fresh, which the manager's per-read
357
+ * best-effort sync provides; when only the repository answers, `getSyncState()`
358
+ * loudly says `degraded` instead of hiding it. An empty row for an
359
+ * unregistered or unfunded lockup is honored as-is: this module does not fall
360
+ * back to a script query behind the manager's back, so `RfqSwapManager` (which
361
+ * supplies the seam via `RfqSwapManagerDeps.contracts`) and standalone callers
362
+ * of {@link refundIfUnresolved} / {@link claimReceiveLockup} own the
363
+ * registration.
364
+ *
365
+ * {@link readLockupFate} is the mirror image, and deliberately so: the fate
366
+ * question needs the spending TRANSACTIONS' witnesses, which the manager does
367
+ * not expose — so it stays a direct indexer read while the money question
368
+ * (what is left here) is the manager's.
354
369
  */
355
- declare function findLockupVtxos(indexer: RefundIndexer, swapPkScript: Uint8Array): Promise<LockupVtxo[]>;
370
+ declare function findLockupVtxos(contracts: LockupContractSource, swapPkScript: Uint8Array): Promise<LockupVtxo[]>;
356
371
  /**
357
372
  * The indexer surface the lockup-spend read needs: the vtxo lookup, plus the
358
373
  * raw transactions those vtxos were spent by. Same narrow-seam style as
359
- * {@link RefundIndexer} and `restore.ts`'s `RestoreIndexer`, and satisfied by
360
- * {@link RestIndexerProvider}.
374
+ * a direct read of {@link RestIndexerProvider}, unlike
375
+ * {@link LockupContractSource}'s contract-manager read.
361
376
  */
362
377
  type LockupSpendIndexer = Pick<RestIndexerProvider, "getVtxos" | "getVirtualTxs">;
363
378
  /**
@@ -454,8 +469,10 @@ type LockupFate =
454
469
  * it is scanned across every output rather than in outpoint order, so which
455
470
  * output happens to come first cannot change the answer.
456
471
  *
457
- * Ask-the-indexer, don't-trust-local-state: read fresh on every poll, never
458
- * cached, the same posture {@link findLockupVtxos} already establishes.
472
+ * Read fresh on every poll, never cached. {@link findLockupVtxos} has since
473
+ * moved to the contract manager's read, but this question needs the spending
474
+ * transactions' witnesses, which the manager does not expose — so the indexer
475
+ * seam stays.
459
476
  */
460
477
  declare function readLockupFate(indexer: LockupSpendIndexer, input: {
461
478
  swapPkScript: Uint8Array;
@@ -619,7 +636,7 @@ type RefundOutcome =
619
636
  * well past the deadline skips straight to the push, and a lockup that is
620
637
  * already empty comes back as `nothing_to_refund` instead of an error.
621
638
  */
622
- declare function refundIfUnresolved(transport: RfqTransport, ark: RefundArkProvider, indexer: LockupSpendIndexer, input: {
639
+ declare function refundIfUnresolved(transport: RfqTransport, ark: RefundArkProvider, contracts: LockupContractSource, indexer: LockupSpendIndexer, input: {
623
640
  rfqId: string;
624
641
  script: InstanceType<typeof VHTLC.ScriptV2>;
625
642
  /** @see pushRefundWithoutReceiver */
@@ -1115,7 +1132,7 @@ interface RfqSwapManagerConfig {
1115
1132
  * seam style as {@link LockupSpendIndexer} and `refund.ts`'s
1116
1133
  * {@link RefundArkProvider}, and satisfied structurally by a real
1117
1134
  * `ContractManager` (`await wallet.getContractManager()`). */
1118
- type SwapContractRegistry = Pick<IContractManager, "createContract" | "getContracts" | "onContractEvent" | "setContractWatchState">;
1135
+ type SwapContractRegistry = Pick<IContractManager, "createContract" | "getContracts" | "getContractsWithVtxos" | "onContractEvent" | "setContractWatchState">;
1119
1136
  /**
1120
1137
  * The record store the manager writes to, narrowed to the four RFQ methods —
1121
1138
  * the same seam style as {@link LockupSpendIndexer} and
@@ -1216,22 +1233,16 @@ interface RfqSwapManagerDeps {
1216
1233
  */
1217
1234
  repository?: RfqSwapRecordStore;
1218
1235
  /**
1219
- * The wallet's contract manager, when there is one. Optional in the same
1220
- * way {@link chain} is: a caller with no wallet, or one that only wants the
1221
- * timer, still gets a fully working manager — the subscription is a
1222
- * LATENCY optimization and nothing depends on it.
1223
- *
1224
- * Supplying it buys two things. The lockup gets REGISTERED, which is what
1225
- * puts it in the wallet's own contract set at all — a prerequisite for
1226
- * anything that has to act on the lockup before its batch expires, since an
1227
- * expired lockup is swept and loses every cooperative path. And the indexer
1228
- * PUSHES its funding and its spend, so a settlement is noticed when it
1229
- * happens rather than up to `pollIntervalMs` later.
1236
+ * The wallet's contract manager. REQUIRED, because under contract-manager
1237
+ * sourcing it is no longer only registration and push: the lockup's own
1238
+ * VTXO state is read through `getContractsWithVtxos`, so the claim and
1239
+ * refund paths cannot work without it and its contract row. The manager
1240
+ * registers that row per pass (`ensureRegistered`).
1230
1241
  *
1231
- * Prefer `await wallet.getContractManager()` over constructing one, the way
1232
- * `createOffer` does.
1242
+ * Prefer `await wallet.getContractManager()` over constructing one, the
1243
+ * way `createOffer` does.
1233
1244
  */
1234
- contracts?: SwapContractRegistry;
1245
+ contracts: SwapContractRegistry;
1235
1246
  }
1236
1247
  /**
1237
1248
  * Watches a set of live RFQ swaps and drives each to its end.
@@ -1959,4 +1970,4 @@ declare class InMemoryAssetSwapRepository implements AssetSwapRepository {
1959
1970
  [Symbol.asyncDispose](): Promise<void>;
1960
1971
  }
1961
1972
 
1962
- export { isRfqSwapTerminal as $, type AssetSwapRepository as A, BTC_ASSET_ID as B, type RfqSwapActionName as C, type RfqSwapLockup as D, RfqSwapManager as E, type RfqSwapManagerCallbacks as F, type RfqSwapManagerConfig as G, type RfqSwapManagerDeps as H, InMemoryAssetSwapRepository as I, type RfqSwapManagerEvents as J, type RfqSwapOrigin as K, type LockupVtxo as L, type MarketsCacheEntry as M, RfqSwapOriginRequired as N, type OnchainSendAction as O, type PersistableRfqSwap as P, type RfqSwapOutcome as Q, type RfqSwapRecord as R, type SwapSecretsProjection as S, type RfqSwapRecordStore as T, type SwapContractRegistry as U, addAssetSwap as V, awaitRfqResolution as W, createRfqSwapRecord as X, findLockupVtxos as Y, getAssetSwaps as Z, getAssetSwapsOrThrow as _, type AssetSwap as a, isRfqTerminal as a0, nextOnchainAction as a1, preimageForSwapRecord as a2, pushRefundWithoutReceiver as a3, readLockupFate as a4, rebuildRfqSwap as a5, refundIfUnresolved as a6, rfqSwapOriginOf as a7, shouldRetainRfqSwap as a8, swapSecretsToRecord as a9, updateAssetSwap as aa, updateAssetSwapBestEffort as ab, updateRfqSwapRecord as ac, type RefundArkProvider as b, type RefundIndexer as c, type RfqSwap as d, type ArkadeRefundResult as e, type LockupSpendIndexer as f, type RfqSwapState as g, type AssetSwapStatus as h, type AvailableRfqSwapManagerCallbacks as i, type LightningReceiveSwap as j, type LightningSendSwap as k, type LockupFate as l, LockupNeedsRecoveryError as m, type LockupParams as n, type LockupSpend as o, type OnchainSendSwap as p, type PreimageBlockedReason as q, PreimageNotRecoverableError as r, REFUND_MTP_LAG_SECONDS as s, RFQ_RESOLVED_STATES as t, RFQ_SWAP_RETENTION_SECONDS as u, RFQ_SWAP_TERMINAL_STATES as v, type RefundOutcome as w, type RfqRestoreFailure as x, type RfqRestoreOptions as y, type RfqRestoreResult as z };
1973
+ export { isRfqSwapTerminal as $, type AssetSwapRepository as A, BTC_ASSET_ID as B, type RfqSwapActionName as C, type RfqSwapLockup as D, RfqSwapManager as E, type RfqSwapManagerCallbacks as F, type RfqSwapManagerConfig as G, type RfqSwapManagerDeps as H, InMemoryAssetSwapRepository as I, type RfqSwapManagerEvents as J, type RfqSwapOrigin as K, type LockupContractSource as L, type MarketsCacheEntry as M, RfqSwapOriginRequired as N, type OnchainSendAction as O, type PersistableRfqSwap as P, type RfqSwapOutcome as Q, type RfqSwapRecord as R, type SwapSecretsProjection as S, type RfqSwapRecordStore as T, type SwapContractRegistry as U, addAssetSwap as V, awaitRfqResolution as W, createRfqSwapRecord as X, findLockupVtxos as Y, getAssetSwaps as Z, getAssetSwapsOrThrow as _, type AssetSwap as a, isRfqTerminal as a0, nextOnchainAction as a1, preimageForSwapRecord as a2, pushRefundWithoutReceiver as a3, readLockupFate as a4, rebuildRfqSwap as a5, refundIfUnresolved as a6, rfqSwapOriginOf as a7, shouldRetainRfqSwap as a8, swapSecretsToRecord as a9, updateAssetSwap as aa, updateAssetSwapBestEffort as ab, updateRfqSwapRecord as ac, type RefundArkProvider as b, type LockupVtxo as c, type RfqSwap as d, type ArkadeRefundResult as e, type LockupSpendIndexer as f, type RfqSwapState as g, type AssetSwapStatus as h, type AvailableRfqSwapManagerCallbacks as i, type LightningReceiveSwap as j, type LightningSendSwap as k, type LockupFate as l, LockupNeedsRecoveryError as m, type LockupParams as n, type LockupSpend as o, type OnchainSendSwap as p, type PreimageBlockedReason as q, PreimageNotRecoverableError as r, REFUND_MTP_LAG_SECONDS as s, RFQ_RESOLVED_STATES as t, RFQ_SWAP_RETENTION_SECONDS as u, RFQ_SWAP_TERMINAL_STATES as v, type RefundOutcome as w, type RfqRestoreFailure as x, type RfqRestoreOptions as y, type RfqRestoreResult as z };
@@ -303,6 +303,8 @@ interface RfqQuote {
303
303
  * solver). */
304
304
  from_amount: number | string;
305
305
  to_amount: number | string;
306
+ /** Dust an asset rides on. NOT a fee — already netted into the amounts above. */
307
+ carrier_sats?: number | string;
306
308
  solver_pubkey: string;
307
309
  valid_until: number;
308
310
  /** HTLC-class quotes only; absent for arkade↔arkade. */
@@ -348,8 +350,8 @@ declare const lightningSendRequest: (input: {
348
350
  * Wire-compatible with the reference solver (`AssetRfqRequest`, strict):
349
351
  * `amount` is a canonical decimal string of atomic units (never a JSON
350
352
  * number — an Arkade asset's precision is not knowable client-side, so the
351
- * losslessness carve-out cannot be checked), `amount_side` is exact-in only
352
- * (`"from"`), and `profile` carries the trader's own covenant position
353
+ * losslessness carve-out cannot be checked), `amount_side` is `"from"` or
354
+ * `"to"`, and `profile` carries the trader's own covenant position
353
355
  * (`maker_pk_script`, `maker_public_key`) — the fill pays that script, and
354
356
  * `cancel` is signed by that key. */
355
357
  declare const arkadeSwapRequest: (input: {
@@ -358,8 +360,6 @@ declare const arkadeSwapRequest: (input: {
358
360
  offerAsset?: asset.AssetId;
359
361
  /** Asset the trader wants; omit when wanting BTC. */
360
362
  wantAsset?: asset.AssetId;
361
- /** Exact-in only. `"to"` is refused client-side: the solver answers
362
- * `exact_out_unsupported`, since the two legs are different assets. */
363
363
  amountSide?: "from" | "to";
364
364
  /** Atomic units of the deposit (`from`) leg. bigint-safe: encoded as a
365
365
  * canonical decimal string on the wire. */
@@ -710,8 +710,13 @@ declare function requestArkadeSwap(wallet: IWallet, arkServerUrl: string, transp
710
710
  offerAsset?: asset.AssetId;
711
711
  /** Asset the trader wants; omit when wanting BTC. */
712
712
  wantAsset?: asset.AssetId;
713
- /** Deposit amount, in atomic units of the `from` leg. */
713
+ /** Atomic units of whichever leg `amountSide` names. */
714
714
  amount: bigint | number | string;
715
+ amountSide?: "from" | "to";
716
+ /** Bounds the side the SOLVER chose — the named side is echoed back verbatim,
717
+ * so asserting it proves nothing and an unbounded caller funds what it is asked. */
718
+ maxFromAmount?: bigint | number | string;
719
+ minToAmount?: bigint | number | string;
715
720
  rfqId?: string;
716
721
  /** Co-signer key override (33-byte compressed hex); see `createOffer`. */
717
722
  emulatorPubkey?: string;
@@ -725,7 +730,7 @@ declare function requestArkadeSwap(wallet: IWallet, arkServerUrl: string, transp
725
730
  /** What the deposit must carry: the quote's `from_amount`. Sats for a BTC
726
731
  * deposit, asset units for an asset deposit (plus a dust carrier). */
727
732
  fundAmount: bigint;
728
- /** Dust sats carrier for an asset deposit; 0n for a BTC deposit. */
733
+ /** Dust sats to attach to an asset deposit; 0n for a BTC deposit. */
729
734
  carrierSats: bigint;
730
735
  /** The covenant's scriptPubKey, for watching the deposit and its spend. */
731
736
  swapPkScript: Uint8Array;
@@ -303,6 +303,8 @@ interface RfqQuote {
303
303
  * solver). */
304
304
  from_amount: number | string;
305
305
  to_amount: number | string;
306
+ /** Dust an asset rides on. NOT a fee — already netted into the amounts above. */
307
+ carrier_sats?: number | string;
306
308
  solver_pubkey: string;
307
309
  valid_until: number;
308
310
  /** HTLC-class quotes only; absent for arkade↔arkade. */
@@ -348,8 +350,8 @@ declare const lightningSendRequest: (input: {
348
350
  * Wire-compatible with the reference solver (`AssetRfqRequest`, strict):
349
351
  * `amount` is a canonical decimal string of atomic units (never a JSON
350
352
  * number — an Arkade asset's precision is not knowable client-side, so the
351
- * losslessness carve-out cannot be checked), `amount_side` is exact-in only
352
- * (`"from"`), and `profile` carries the trader's own covenant position
353
+ * losslessness carve-out cannot be checked), `amount_side` is `"from"` or
354
+ * `"to"`, and `profile` carries the trader's own covenant position
353
355
  * (`maker_pk_script`, `maker_public_key`) — the fill pays that script, and
354
356
  * `cancel` is signed by that key. */
355
357
  declare const arkadeSwapRequest: (input: {
@@ -358,8 +360,6 @@ declare const arkadeSwapRequest: (input: {
358
360
  offerAsset?: asset.AssetId;
359
361
  /** Asset the trader wants; omit when wanting BTC. */
360
362
  wantAsset?: asset.AssetId;
361
- /** Exact-in only. `"to"` is refused client-side: the solver answers
362
- * `exact_out_unsupported`, since the two legs are different assets. */
363
363
  amountSide?: "from" | "to";
364
364
  /** Atomic units of the deposit (`from`) leg. bigint-safe: encoded as a
365
365
  * canonical decimal string on the wire. */
@@ -710,8 +710,13 @@ declare function requestArkadeSwap(wallet: IWallet, arkServerUrl: string, transp
710
710
  offerAsset?: asset.AssetId;
711
711
  /** Asset the trader wants; omit when wanting BTC. */
712
712
  wantAsset?: asset.AssetId;
713
- /** Deposit amount, in atomic units of the `from` leg. */
713
+ /** Atomic units of whichever leg `amountSide` names. */
714
714
  amount: bigint | number | string;
715
+ amountSide?: "from" | "to";
716
+ /** Bounds the side the SOLVER chose — the named side is echoed back verbatim,
717
+ * so asserting it proves nothing and an unbounded caller funds what it is asked. */
718
+ maxFromAmount?: bigint | number | string;
719
+ minToAmount?: bigint | number | string;
715
720
  rfqId?: string;
716
721
  /** Co-signer key override (33-byte compressed hex); see `createOffer`. */
717
722
  emulatorPubkey?: string;
@@ -725,7 +730,7 @@ declare function requestArkadeSwap(wallet: IWallet, arkServerUrl: string, transp
725
730
  /** What the deposit must carry: the quote's `from_amount`. Sats for a BTC
726
731
  * deposit, asset units for an asset deposit (plus a dust carrier). */
727
732
  fundAmount: bigint;
728
- /** Dust sats carrier for an asset deposit; 0n for a BTC deposit. */
733
+ /** Dust sats to attach to an asset deposit; 0n for a BTC deposit. */
729
734
  carrierSats: bigint;
730
735
  /** The covenant's scriptPubKey, for watching the deposit and its spend. */
731
736
  swapPkScript: Uint8Array;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@arkade-os/swap",
3
- "version": "0.0.19",
3
+ "version": "0.0.21",
4
4
  "type": "module",
5
5
  "description": "Client-side Arkade Intents asset swaps: discover markets, quote, create/track/cancel offers, restore from chain.",
6
6
  "repository": {
@@ -64,13 +64,13 @@
64
64
  "author": "Arkade-OS",
65
65
  "license": "MIT",
66
66
  "dependencies": {
67
- "@arkade-os/solver-discovery": "0.2.5",
67
+ "@arkade-os/solver-discovery": "0.2.7",
68
68
  "@noble/ciphers": "2.1.1",
69
69
  "@noble/curves": "2.0.1",
70
70
  "@noble/hashes": "2.0.1",
71
71
  "@scure/base": "2.0.0",
72
72
  "@scure/btc-signer": "2.0.1",
73
- "@arkade-os/sdk": "0.4.73"
73
+ "@arkade-os/sdk": "0.4.75"
74
74
  },
75
75
  "peerDependencies": {
76
76
  "nostr-tools": "^2.12.0"