@arkade-os/swap 0.0.20 → 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.
package/dist/index.cjs CHANGED
@@ -4204,30 +4204,26 @@ var LockupNeedsRecoveryError = class extends Error {
4204
4204
  this.recoverableAfter = recoverableAfter;
4205
4205
  }
4206
4206
  };
4207
- async function findLockupVtxos(indexer, swapPkScript) {
4208
- const scripts = [import_base14.hex.encode(swapPkScript)];
4209
- const [spendable, recoverable] = await Promise.all([
4210
- indexer.getVtxos({ scripts, spendableOnly: true }),
4211
- indexer.getVtxos({ scripts, recoverableOnly: true })
4212
- ]);
4207
+ async function findLockupVtxos(contracts, swapPkScript) {
4208
+ const [row] = await contracts.getContractsWithVtxos({
4209
+ script: import_base14.hex.encode(swapPkScript)
4210
+ });
4213
4211
  const seen = /* @__PURE__ */ new Set();
4214
4212
  const out = [];
4215
- for (const [vtxos, isRecoverable] of [
4216
- [spendable.vtxos ?? [], false],
4217
- [recoverable.vtxos ?? [], true]
4218
- ]) {
4219
- for (const vtxo of vtxos) {
4220
- if (vtxo.isUnrolled) continue;
4221
- const key = `${vtxo.txid}:${vtxo.vout}`;
4222
- if (seen.has(key)) continue;
4223
- seen.add(key);
4224
- out.push({
4225
- txid: vtxo.txid,
4226
- vout: vtxo.vout,
4227
- value: Number(vtxo.value),
4228
- recoverable: isRecoverable
4229
- });
4230
- }
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
+ });
4231
4227
  }
4232
4228
  return out;
4233
4229
  }
@@ -4339,7 +4335,7 @@ async function pushRefundWithoutReceiver(ark, input) {
4339
4335
  return { arkTxid: submitted.arkTxid, amount };
4340
4336
  }
4341
4337
  var REFUND_MTP_LAG_SECONDS = 2 * 60 * 60;
4342
- async function refundIfUnresolved(transport, ark, indexer, input) {
4338
+ async function refundIfUnresolved(transport, ark, contracts, indexer, input) {
4343
4339
  const pollMs = input.pollMs ?? 5e3;
4344
4340
  const now = input.now ?? (() => Math.floor(Date.now() / 1e3));
4345
4341
  const attemptDeadline = input.attemptDeadline ?? input.refundLocktime + REFUND_MTP_LAG_SECONDS;
@@ -4362,7 +4358,7 @@ async function refundIfUnresolved(transport, ark, indexer, input) {
4362
4358
  status
4363
4359
  };
4364
4360
  }
4365
- const vtxos = await findLockupVtxos(indexer, input.script.pkScript);
4361
+ const vtxos = await findLockupVtxos(contracts, input.script.pkScript);
4366
4362
  if (vtxos.length === 0) return { outcome: "nothing_to_refund", status };
4367
4363
  try {
4368
4364
  const pushed = await pushRefundWithoutReceiver(ark, {
@@ -4457,10 +4453,10 @@ async function pushClaim(ark, input) {
4457
4453
  });
4458
4454
  return { arkTxid, amount: locked };
4459
4455
  }
4460
- async function awaitLockupFunding(indexer, swapPkScript, options = {}) {
4456
+ async function awaitLockupFunding(contracts, swapPkScript, options = {}) {
4461
4457
  const pollMs = options.pollMs ?? 5e3;
4462
4458
  for (; ; ) {
4463
- const vtxos = await findLockupVtxos(indexer, swapPkScript);
4459
+ const vtxos = await findLockupVtxos(contracts, swapPkScript);
4464
4460
  if (vtxos.length > 0) return vtxos;
4465
4461
  if (options.deadline !== void 0 && Date.now() / 1e3 >= options.deadline) {
4466
4462
  const error = new Error("the lockup never appeared at the covenant script");
@@ -4470,8 +4466,8 @@ async function awaitLockupFunding(indexer, swapPkScript, options = {}) {
4470
4466
  await sleep3(pollMs);
4471
4467
  }
4472
4468
  }
4473
- async function claimReceiveLockup(indexer, ark, input) {
4474
- const vtxos = await awaitLockupFunding(indexer, input.swapPkScript, {
4469
+ async function claimReceiveLockup(contracts, ark, input) {
4470
+ const vtxos = await awaitLockupFunding(contracts, input.swapPkScript, {
4475
4471
  pollMs: input.pollMs,
4476
4472
  deadline: input.deadline
4477
4473
  });
@@ -4533,7 +4529,7 @@ function arkadeRefunder(deps) {
4533
4529
  `swap ${swap.rfqId} carries no lockup covenant, so its refund cannot be built`
4534
4530
  );
4535
4531
  }
4536
- const vtxos = await findLockupVtxos(deps.indexer, swap.lockupPkScript);
4532
+ const vtxos = await findLockupVtxos(deps.contracts, swap.lockupPkScript);
4537
4533
  if (vtxos.length === 0) return null;
4538
4534
  const record = await deps.repository.getRfqSwap(swap.rfqId);
4539
4535
  if (!record) {
@@ -5156,7 +5152,10 @@ var RfqSwapManager = class {
5156
5152
  return;
5157
5153
  }
5158
5154
  if (swap.kind === "lightning_receive") {
5159
- 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;
5160
5159
  }
5161
5160
  if (swap.kind === "onchain_send" && swap.state !== "claimed") {
5162
5161
  if (await this.driveOnchain(swap) === "handled") return;
@@ -5211,7 +5210,7 @@ var RfqSwapManager = class {
5211
5210
  if (now < swap.refundLocktime) {
5212
5211
  let vtxos;
5213
5212
  try {
5214
- vtxos = await findLockupVtxos(this.deps.indexer, swap.lockupPkScript);
5213
+ vtxos = await findLockupVtxos(this.deps.contracts, swap.lockupPkScript);
5215
5214
  } catch (error) {
5216
5215
  this.emitFailed(swap, error);
5217
5216
  return;
package/dist/index.d.cts CHANGED
@@ -1,6 +1,6 @@
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-Cop29z0c.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-Cop29z0c.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
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
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';
@@ -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,6 +1,6 @@
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-BrTpVPLy.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-BrTpVPLy.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
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
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';
@@ -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
@@ -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;
@@ -1,5 +1,5 @@
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-Cop29z0c.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
5
  import '../../rfq-B95nPfaa.cjs';
@@ -1,5 +1,5 @@
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-BrTpVPLy.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
5
  import '../../rfq-B95nPfaa.js';
@@ -1,5 +1,5 @@
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-Cop29z0c.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
5
  import '../../rfq-B95nPfaa.cjs';
@@ -1,5 +1,5 @@
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-BrTpVPLy.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
5
  import '../../rfq-B95nPfaa.js';
@@ -1,5 +1,5 @@
1
1
  import { DiscoveredMarket } from '@arkade-os/solver-discovery';
2
- import { IWallet, ProvisionedKey, ProvisionedClaimSecret, RestArkProvider, RestIndexerProvider, VHTLC, Identity, IContractManager } from '@arkade-os/sdk';
2
+ import { IWallet, ProvisionedKey, ProvisionedClaimSecret, RestArkProvider, IContractManager, RestIndexerProvider, VHTLC, Identity } from '@arkade-os/sdk';
3
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";
@@ -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,5 +1,5 @@
1
1
  import { DiscoveredMarket } from '@arkade-os/solver-discovery';
2
- import { IWallet, ProvisionedKey, ProvisionedClaimSecret, RestArkProvider, RestIndexerProvider, VHTLC, Identity, IContractManager } from '@arkade-os/sdk';
2
+ import { IWallet, ProvisionedKey, ProvisionedClaimSecret, RestArkProvider, IContractManager, RestIndexerProvider, VHTLC, Identity } from '@arkade-os/sdk';
3
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";
@@ -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 };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@arkade-os/swap",
3
- "version": "0.0.20",
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": {
@@ -70,7 +70,7 @@
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.74"
73
+ "@arkade-os/sdk": "0.4.75"
74
74
  },
75
75
  "peerDependencies": {
76
76
  "nostr-tools": "^2.12.0"