@satora/swap 1.3.2 → 1.4.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.d.cts CHANGED
@@ -161,6 +161,16 @@ type SwapActionInput = {
161
161
  * `false`, `pending` resolves to `wait` (not `fund`) and no refund is offered.
162
162
  */
163
163
  clientFunds?: boolean;
164
+ /**
165
+ * Whether the server's leg is an on-chain HTLC the client claims (the
166
+ * default). `false` for receive-on-Lightning swaps (`*_to_lightning`): there
167
+ * the server "funds" by paying the client's invoice off-chain, so there is
168
+ * nothing to claim and no claim window — {@link serverRefundLocktime} is
169
+ * meaningless. When `false`, `serverfunded` (the payment is in flight)
170
+ * resolves to `wait`, with the unilateral refund listed but blocked until
171
+ * the client's own timelock, exactly like `clientfunded`.
172
+ */
173
+ serverFunds?: boolean;
164
174
  };
165
175
  /** On-chain state of one HTLC in a swap. */
166
176
  type HtlcObservation = "absent" | "mempool" | "confirmed" | "invalid" | "spent_claim" | "spent_refund";
@@ -682,6 +692,8 @@ declare class Client {
682
692
  /** Delegated to the legacy client (migration checkpoint). */
683
693
  createArkadeToLightningSwap(...args: Parameters<Client$1["createArkadeToLightningSwap"]>): ReturnType<Client$1["createArkadeToLightningSwap"]>;
684
694
  /** Delegated to the legacy client (migration checkpoint). */
695
+ createEvmToLightningSwap(...args: Parameters<Client$1["createEvmToLightningSwap"]>): ReturnType<Client$1["createEvmToLightningSwap"]>;
696
+ /** Delegated to the legacy client (migration checkpoint). */
685
697
  createEvmToArkadeSwapGeneric(...args: Parameters<Client$1["createEvmToArkadeSwapGeneric"]>): ReturnType<Client$1["createEvmToArkadeSwapGeneric"]>;
686
698
  /** Delegated to the legacy client (migration checkpoint). */
687
699
  createEvmToBitcoinSwap(...args: Parameters<Client$1["createEvmToBitcoinSwap"]>): ReturnType<Client$1["createEvmToBitcoinSwap"]>;
package/dist/index.d.ts CHANGED
@@ -161,6 +161,16 @@ type SwapActionInput = {
161
161
  * `false`, `pending` resolves to `wait` (not `fund`) and no refund is offered.
162
162
  */
163
163
  clientFunds?: boolean;
164
+ /**
165
+ * Whether the server's leg is an on-chain HTLC the client claims (the
166
+ * default). `false` for receive-on-Lightning swaps (`*_to_lightning`): there
167
+ * the server "funds" by paying the client's invoice off-chain, so there is
168
+ * nothing to claim and no claim window — {@link serverRefundLocktime} is
169
+ * meaningless. When `false`, `serverfunded` (the payment is in flight)
170
+ * resolves to `wait`, with the unilateral refund listed but blocked until
171
+ * the client's own timelock, exactly like `clientfunded`.
172
+ */
173
+ serverFunds?: boolean;
164
174
  };
165
175
  /** On-chain state of one HTLC in a swap. */
166
176
  type HtlcObservation = "absent" | "mempool" | "confirmed" | "invalid" | "spent_claim" | "spent_refund";
@@ -682,6 +692,8 @@ declare class Client {
682
692
  /** Delegated to the legacy client (migration checkpoint). */
683
693
  createArkadeToLightningSwap(...args: Parameters<Client$1["createArkadeToLightningSwap"]>): ReturnType<Client$1["createArkadeToLightningSwap"]>;
684
694
  /** Delegated to the legacy client (migration checkpoint). */
695
+ createEvmToLightningSwap(...args: Parameters<Client$1["createEvmToLightningSwap"]>): ReturnType<Client$1["createEvmToLightningSwap"]>;
696
+ /** Delegated to the legacy client (migration checkpoint). */
685
697
  createEvmToArkadeSwapGeneric(...args: Parameters<Client$1["createEvmToArkadeSwapGeneric"]>): ReturnType<Client$1["createEvmToArkadeSwapGeneric"]>;
686
698
  /** Delegated to the legacy client (migration checkpoint). */
687
699
  createEvmToBitcoinSwap(...args: Parameters<Client$1["createEvmToBitcoinSwap"]>): ReturnType<Client$1["createEvmToBitcoinSwap"]>;
package/dist/index.js CHANGED
@@ -19,7 +19,8 @@ function deriveSwapActions(input) {
19
19
  serverChainNow,
20
20
  clientRefundLocktime,
21
21
  serverRefundLocktime,
22
- clientFunds = true
22
+ clientFunds = true,
23
+ serverFunds = true
23
24
  } = input;
24
25
  switch (status) {
25
26
  case "pending": {
@@ -104,6 +105,36 @@ function deriveSwapActions(input) {
104
105
  return { recommended: "wait", actions: [wait, refund] };
105
106
  }
106
107
  case "serverfunded": {
108
+ if (!serverFunds) {
109
+ const refundUnlocked2 = clientChainNow >= clientRefundLocktime;
110
+ if (refundUnlocked2) {
111
+ const refund3 = {
112
+ id: "refund_unilateral",
113
+ recommended: true,
114
+ automation: "confirm",
115
+ reason: "Reclaim your deposit."
116
+ };
117
+ return { recommended: "refund_unilateral", actions: [refund3] };
118
+ }
119
+ const wait2 = {
120
+ id: "wait",
121
+ waitingOn: "server_funding",
122
+ recommended: true,
123
+ automation: "auto",
124
+ reason: "Waiting for the Lightning payment to settle."
125
+ };
126
+ const refund2 = {
127
+ id: "refund_unilateral",
128
+ recommended: false,
129
+ automation: "confirm",
130
+ reason: "Refund becomes available once the timelock passes.",
131
+ blockedBy: {
132
+ kind: "timelock_not_expired",
133
+ message: "The refund timelock has not passed yet."
134
+ }
135
+ };
136
+ return { recommended: "wait", actions: [wait2, refund2] };
137
+ }
107
138
  const claimWindowClosed = serverChainNow >= serverRefundLocktime;
108
139
  if (!claimWindowClosed) {
109
140
  const claim = {
@@ -1328,8 +1359,10 @@ var HintTracker = class {
1328
1359
  serverChainNow: now,
1329
1360
  clientRefundLocktime: swap.clientRefundLocktime,
1330
1361
  serverRefundLocktime: swap.serverRefundLocktime,
1331
- // Pay-on-Lightning swaps have no client-funded on-chain leg.
1332
- clientFunds: swap.clientHtlc !== void 0
1362
+ // Pay-on-Lightning swaps have no client-funded on-chain leg;
1363
+ // receive-on-Lightning swaps have no server-funded one.
1364
+ clientFunds: swap.clientHtlc !== void 0,
1365
+ serverFunds: swap.serverHtlc !== void 0
1333
1366
  });
1334
1367
  const previous = this.#lastActions.get(swap.swapId);
1335
1368
  if (!force && previous && JSON.stringify(previous) === JSON.stringify(actions))
@@ -1955,6 +1988,29 @@ function swapToTracked(stored) {
1955
1988
  // no on-chain client leg
1956
1989
  serverRefundLocktime: ms(r.vhtlc_refund_locktime)
1957
1990
  };
1991
+ // Client funds the EVM HTLC (evm_expected_sats of the BTC-pegged token);
1992
+ // the server pays the Lightning invoice off-chain and claims the HTLC —
1993
+ // no server leg to watch.
1994
+ case "evm_to_lightning":
1995
+ return {
1996
+ swapId: r.id,
1997
+ clientHtlc: evmLeg({
1998
+ chainId: r.evm_chain_id,
1999
+ htlc: r.evm_htlc_address,
2000
+ hashLock: r.hash_lock,
2001
+ claimAddress: r.server_evm_address,
2002
+ // the server claims the client's EVM HTLC
2003
+ expectedSats: r.evm_expected_sats,
2004
+ token: r.wbtc_address,
2005
+ sender: r.evm_coordinator_address,
2006
+ // the coordinator locks on the client's behalf
2007
+ timelockSec: r.evm_refund_locktime,
2008
+ createdAt: r.created_at
2009
+ }),
2010
+ clientRefundLocktime: ms(r.evm_refund_locktime),
2011
+ serverRefundLocktime: 0
2012
+ // no on-chain server leg
2013
+ };
1958
2014
  // Client funds the Arkade VHTLC (source_amount); the server pays the
1959
2015
  // Lightning invoice off-chain and claims the VHTLC — no server leg to
1960
2016
  // watch.
@@ -2217,8 +2273,10 @@ var SwapTracker = class {
2217
2273
  serverChainNow,
2218
2274
  clientRefundLocktime: swap.clientRefundLocktime,
2219
2275
  serverRefundLocktime: swap.serverRefundLocktime,
2220
- // Pay-on-Lightning swaps have no client-funded on-chain leg.
2221
- clientFunds: swap.clientHtlc !== void 0
2276
+ // Pay-on-Lightning swaps have no client-funded on-chain leg;
2277
+ // receive-on-Lightning swaps have no server-funded one.
2278
+ clientFunds: swap.clientHtlc !== void 0,
2279
+ serverFunds: swap.serverHtlc !== void 0
2222
2280
  }),
2223
2281
  // Expose the raw observations so consumers can render progress from
2224
2282
  // chain facts (which leg is funded/spent) even when the server is
@@ -2510,6 +2568,12 @@ var Client = class {
2510
2568
  );
2511
2569
  }
2512
2570
  /** Delegated to the legacy client (migration checkpoint). */
2571
+ createEvmToLightningSwap(...args) {
2572
+ return this.#trackAfterCreate(
2573
+ this.#legacy.createEvmToLightningSwap(...args)
2574
+ );
2575
+ }
2576
+ /** Delegated to the legacy client (migration checkpoint). */
2513
2577
  createEvmToArkadeSwapGeneric(...args) {
2514
2578
  return this.#trackAfterCreate(
2515
2579
  this.#legacy.createEvmToArkadeSwapGeneric(...args)