@satora/swap 1.7.2 → 1.8.0

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
@@ -720,13 +720,10 @@ async function fetchArkadeSpend(source, spentByTxid, paymentHash) {
720
720
 
721
721
  // src/contracts/arkade-manager.ts
722
722
  function isFunded(vtxo) {
723
- const { state } = vtxo.virtualStatus;
724
- return state === "preconfirmed" || state === "settled";
723
+ return !vtxo.isSpent && !vtxo.isSwept;
725
724
  }
726
725
  function spendTxid(vtxos) {
727
- const spent = vtxos.find(
728
- (v) => v.arkTxId || v.spentBy || v.isSpent || v.virtualStatus.state === "spent"
729
- );
726
+ const spent = vtxos.find((v) => v.arkTxId || v.spentBy || v.isSpent);
730
727
  return spent?.arkTxId ?? spent?.spentBy;
731
728
  }
732
729
  var ArkadeContractManager = class _ArkadeContractManager {
@@ -1772,6 +1769,17 @@ var SwapWorker = class {
1772
1769
  )
1773
1770
  );
1774
1771
  }
1772
+ /**
1773
+ * Put swaps on the hint feed as soon as they are tracked. {@link #onActions}
1774
+ * subscribes a swap when its first action is emitted, but a swap whose leg
1775
+ * cannot be classified yet (an unfunded lock on a chain without `eth_getLogs`)
1776
+ * emits nothing, and without this it would never receive the server hint
1777
+ * that its funding landed.
1778
+ */
1779
+ subscribe(swapIds) {
1780
+ if (swapIds.length === 0) return;
1781
+ this.#hintSource.subscribe(swapIds);
1782
+ }
1775
1783
  /** Stop reacting, cancel pending retries, and close the hint feed. */
1776
1784
  stop() {
1777
1785
  this.#started = false;
@@ -1823,7 +1831,7 @@ var SwapWorker = class {
1823
1831
  const actionId = actions.recommended;
1824
1832
  if (!actionId) return;
1825
1833
  this.#executing.add(swapId);
1826
- void execute(swapId, actionId).then(() => this.#cancelRetry(swapId)).catch((error) => {
1834
+ void execute(swapId, actionId, actions).then(() => this.#cancelRetry(swapId)).catch((error) => {
1827
1835
  if (needsWallet(error)) {
1828
1836
  this.#cancelRetry(swapId);
1829
1837
  this.#needsUser.add(swapId);
@@ -2236,7 +2244,7 @@ function swapToTracked(stored) {
2236
2244
  token: r.evm_htlc_kind === "native" ? import_lendaswap_sdk_pure2.NATIVE_TOKEN_ADDRESS : lockedTokenFallback(r.evm_chain_id, r.network),
2237
2245
  // The coordinator created the HTLC on the client's behalf, so it
2238
2246
  // is the lock's sender (refund address), as on evm_to_lightning.
2239
- sender: r.evm_coordinator_address,
2247
+ sender: r.evm_htlc_kind === "native" && r.evm_coordinator_address.toLowerCase() === import_lendaswap_sdk_pure2.NATIVE_TOKEN_ADDRESS ? r.client_evm_address ?? void 0 : r.evm_coordinator_address,
2240
2248
  timelockSec: r.evm_refund_locktime,
2241
2249
  createdAt: r.created_at
2242
2250
  }),
@@ -2286,7 +2294,7 @@ function swapToTracked(stored) {
2286
2294
  token: r.wbtc_address,
2287
2295
  // The coordinator created the HTLC on the client's behalf, so it
2288
2296
  // is the lock's sender (refund address).
2289
- sender: r.evm_coordinator_address,
2297
+ sender: r.evm_htlc_kind === "native" && r.evm_coordinator_address.toLowerCase() === import_lendaswap_sdk_pure2.NATIVE_TOKEN_ADDRESS ? r.client_evm_address ?? void 0 : r.evm_coordinator_address,
2290
2298
  timelockSec: r.evm_refund_locktime,
2291
2299
  createdAt: r.created_at
2292
2300
  }),
@@ -2381,7 +2389,7 @@ function swapToTracked(stored) {
2381
2389
  // the server claims the client's EVM HTLC
2382
2390
  expectedSats: r.evm_expected_sats,
2383
2391
  token: r.wbtc_address,
2384
- sender: r.evm_coordinator_address,
2392
+ sender: r.evm_htlc_kind === "native" && r.evm_coordinator_address.toLowerCase() === import_lendaswap_sdk_pure2.NATIVE_TOKEN_ADDRESS ? r.client_evm_address ?? void 0 : r.evm_coordinator_address,
2385
2393
  // the coordinator locks on the client's behalf
2386
2394
  timelockSec: r.evm_refund_locktime,
2387
2395
  createdAt: r.created_at
@@ -3003,6 +3011,9 @@ var Client = class {
3003
3011
  return this.#legacy.claim(...args);
3004
3012
  }
3005
3013
  /** Delegated to the legacy client (migration checkpoint). */
3014
+ canSponsorClaim(...args) {
3015
+ return this.#legacy.canSponsorClaim(...args);
3016
+ }
3006
3017
  claimEvmWithSigner(...args) {
3007
3018
  return this.#legacy.claimEvmWithSigner(...args);
3008
3019
  }
@@ -3031,6 +3042,26 @@ var Client = class {
3031
3042
  return this.#legacy.buildCollabRefundEvmTypedData(...args);
3032
3043
  }
3033
3044
  /** Delegated to the legacy client (migration checkpoint). */
3045
+ getCollabRefundEvmSignature(...args) {
3046
+ return this.#legacy.getCollabRefundEvmSignature(...args);
3047
+ }
3048
+ /** Delegated to the legacy client (migration checkpoint). */
3049
+ getRehashEvmParams(...args) {
3050
+ return this.#legacy.getRehashEvmParams(...args);
3051
+ }
3052
+ /** Delegated to the legacy client (migration checkpoint). */
3053
+ signRehashEvm(...args) {
3054
+ return this.#legacy.signRehashEvm(...args);
3055
+ }
3056
+ /** Delegated to the legacy client (migration checkpoint). */
3057
+ retrySwapWithInvoice(...args) {
3058
+ return this.#legacy.retrySwapWithInvoice(...args);
3059
+ }
3060
+ /** Delegated to the legacy client (migration checkpoint). */
3061
+ retrySwapWithInvoiceWithSigner(...args) {
3062
+ return this.#legacy.retrySwapWithInvoiceWithSigner(...args);
3063
+ }
3064
+ /** Delegated to the legacy client (migration checkpoint). */
3034
3065
  collabRefundEvmSwap(...args) {
3035
3066
  return this.#legacy.collabRefundEvmSwap(...args);
3036
3067
  }
@@ -3106,9 +3137,14 @@ var Client = class {
3106
3137
  getPermit2FundingParamsUnsigned(...args) {
3107
3138
  return this.#legacy.getPermit2FundingParamsUnsigned(...args);
3108
3139
  }
3109
- /** Delegated to the legacy client (migration checkpoint). */
3110
- fundSwap(...args) {
3111
- return this.#legacy.fundSwap(...args);
3140
+ /**
3141
+ * Fund the swap, then re-verify it against the chain so the lock shows up
3142
+ * in the derived actions without waiting on a server hint.
3143
+ */
3144
+ async fundSwap(...args) {
3145
+ const result = await this.#legacy.fundSwap(...args);
3146
+ this.#reverifyAfterFunding(args[0]);
3147
+ return result;
3112
3148
  }
3113
3149
  /** Delegated to the legacy client (migration checkpoint). */
3114
3150
  fundSwapFromSolana(...args) {
@@ -3135,6 +3171,10 @@ var Client = class {
3135
3171
  return this.#legacy.fundSwapGasless(...args);
3136
3172
  }
3137
3173
  /** Delegated to the legacy client (migration checkpoint). */
3174
+ getEvmFundingExpectation(...args) {
3175
+ return this.#legacy.getEvmFundingExpectation(...args);
3176
+ }
3177
+ /** Delegated to the legacy client (migration checkpoint). */
3138
3178
  getSwapDepositorKey(...args) {
3139
3179
  return this.#legacy.getSwapDepositorKey(...args);
3140
3180
  }
@@ -3335,11 +3375,37 @@ var Client = class {
3335
3375
  for (const swap of swaps) {
3336
3376
  try {
3337
3377
  await tracker.track(swap);
3378
+ if (tracker.trackedSwapIds().includes(swap.swapId))
3379
+ this.#worker?.subscribe([swap.swapId]);
3338
3380
  } catch (error) {
3339
3381
  console.warn(`Client: tracking swap ${swap.swapId} failed:`, error);
3340
3382
  }
3341
3383
  }
3342
3384
  }
3385
+ /**
3386
+ * Re-verify a swap against the chain right after this client funded it.
3387
+ * The funding is mined when `fundSwap` resolves, but nothing else tells the
3388
+ * tracker so: a server hint arrives only after the server's own monitor
3389
+ * sees the lock (on Rootstock, a 30 s poll plus confirmations), and the
3390
+ * tracker's at-risk poll does not re-read an `absent` client leg. One
3391
+ * targeted read moves the swap to `clientfunded` at once. Fire-and-forget:
3392
+ * the funding succeeded whatever the re-verify does, and a swap that is not
3393
+ * tracked is a no-op.
3394
+ *
3395
+ * Chain-verified tracking only: a hints-only tracker has no chain to read,
3396
+ * its `applyHint` re-fetches the server's stored status, which lags the
3397
+ * lock by the same server-side delay this works around.
3398
+ */
3399
+ #reverifyAfterFunding(swapId) {
3400
+ if (typeof swapId !== "string" || !(this.#tracker instanceof SwapTracker))
3401
+ return;
3402
+ void this.#tracker.applyHint(swapId).catch((error) => {
3403
+ console.warn(
3404
+ `Client: re-verify after funding ${swapId} failed (the tracker's next read catches up):`,
3405
+ error
3406
+ );
3407
+ });
3408
+ }
3343
3409
  /**
3344
3410
  * Wire the server status WebSocket into a {@link SwapWorker} whenever a server
3345
3411
  * URL is configured: pushed status transitions trigger a targeted chain
@@ -3352,7 +3418,10 @@ var Client = class {
3352
3418
  const serverUrl = this.#tracking.serverUrl ?? legacyBaseUrl(this.#legacy);
3353
3419
  if (!serverUrl) return;
3354
3420
  const autoClaim = this.#tracking.autoClaim;
3355
- const hintSource = new WsStatusSource({ serverUrl });
3421
+ const hintSource = new WsStatusSource({
3422
+ serverUrl,
3423
+ webSocketFactory: this.#tracking.webSocketFactory
3424
+ });
3356
3425
  const worker = new SwapWorker({
3357
3426
  tracker,
3358
3427
  hintSource,