@lendasat/lendaswap-sdk-pure 0.2.26 → 0.2.27

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.
Files changed (55) hide show
  1. package/dist/cctp-inbound/client.d.ts +5 -0
  2. package/dist/cctp-inbound/client.d.ts.map +1 -1
  3. package/dist/cctp-inbound/client.js +9 -1
  4. package/dist/cctp-inbound/client.js.map +1 -1
  5. package/dist/cctp-inbound/preflight.d.ts +5 -0
  6. package/dist/cctp-inbound/preflight.d.ts.map +1 -1
  7. package/dist/cctp-inbound/preflight.js +20 -3
  8. package/dist/cctp-inbound/preflight.js.map +1 -1
  9. package/dist/cctp-inbound/submit.d.ts +5 -0
  10. package/dist/cctp-inbound/submit.d.ts.map +1 -1
  11. package/dist/cctp-inbound/submit.js +2 -0
  12. package/dist/cctp-inbound/submit.js.map +1 -1
  13. package/dist/client.d.ts +20 -2
  14. package/dist/client.d.ts.map +1 -1
  15. package/dist/client.js +109 -23
  16. package/dist/client.js.map +1 -1
  17. package/dist/create/retry.d.ts.map +1 -1
  18. package/dist/create/retry.js +11 -1
  19. package/dist/create/retry.js.map +1 -1
  20. package/dist/create/types.d.ts +5 -0
  21. package/dist/create/types.d.ts.map +1 -1
  22. package/dist/delegate.d.ts +9 -0
  23. package/dist/delegate.d.ts.map +1 -1
  24. package/dist/delegate.js +16 -1
  25. package/dist/delegate.js.map +1 -1
  26. package/dist/evm/coordinator.d.ts.map +1 -1
  27. package/dist/evm/coordinator.js +0 -1
  28. package/dist/evm/coordinator.js.map +1 -1
  29. package/dist/index.d.ts +2 -1
  30. package/dist/index.d.ts.map +1 -1
  31. package/dist/index.js +1 -0
  32. package/dist/index.js.map +1 -1
  33. package/dist/logging.d.ts +44 -0
  34. package/dist/logging.d.ts.map +1 -0
  35. package/dist/logging.js +130 -0
  36. package/dist/logging.js.map +1 -0
  37. package/dist/redeem/arkade.d.ts +5 -0
  38. package/dist/redeem/arkade.d.ts.map +1 -1
  39. package/dist/redeem/arkade.js +84 -12
  40. package/dist/redeem/arkade.js.map +1 -1
  41. package/dist/refund/arkade.d.ts +5 -0
  42. package/dist/refund/arkade.d.ts.map +1 -1
  43. package/dist/refund/arkade.js +29 -5
  44. package/dist/refund/arkade.js.map +1 -1
  45. package/dist/refund/collab-arkade-lightning.d.ts +5 -0
  46. package/dist/refund/collab-arkade-lightning.d.ts.map +1 -1
  47. package/dist/refund/collab-arkade-lightning.js +64 -27
  48. package/dist/refund/collab-arkade-lightning.js.map +1 -1
  49. package/dist/usd-price.d.ts +8 -1
  50. package/dist/usd-price.d.ts.map +1 -1
  51. package/dist/usd-price.js +16 -3
  52. package/dist/usd-price.js.map +1 -1
  53. package/dist/version.d.ts +2 -2
  54. package/dist/version.js +1 -1
  55. package/package.json +1 -1
package/dist/client.js CHANGED
@@ -9,6 +9,7 @@ import { delegateClaim, delegateRefund } from "./delegate.js";
9
9
  import { broadcastTransaction, findOutputByAddress } from "./esplora.js";
10
10
  import { buildCollabRefundEvmDigest, buildCollabRefundEvmTypedData, buildEip2612PermitDigest, buildPermit2FundingDigest, buildPermit2TypedData, deriveEvmAddress, encodeApproveCallData, encodeExecuteAndCreateWithPermit2, encodeHtlcErc20RefundCallData, PERMIT2_ADDRESS, signEvmDigest, } from "./evm/index.js";
11
11
  import { decodeUint256, encodeAllowanceCall, encodeBalanceOfCall, encodeMaxApproveData, getRevertReason, parseSignature, simulateTransaction, } from "./evm/wallet.js";
12
+ import { createSdkLogger, } from "./logging.js";
12
13
  import { buildArkadeClaim, continueArkadeClaim, claimViaGasless as gaslessClaim, claim as redeemClaim, } from "./redeem/index.js";
13
14
  import { buildArkadeRefund, buildOnchainClaimTransaction, buildOnchainRefundTransaction, collabRefundArkadeToEvmDelegate, collabRefundArkadeToEvmOffchain, collabRefundArkadeToLightningOffchain, verifyHtlcAddress, } from "./refund/index.js";
14
15
  import { bytesToHex, hexToBytes, Signer, } from "./signer/index.js";
@@ -64,6 +65,8 @@ export class ClientBuilder {
64
65
  #mnemonic;
65
66
  #xprv;
66
67
  #aa;
68
+ #logger;
69
+ #logLevel;
67
70
  /**
68
71
  * Sets the base URL for the API.
69
72
  * @param baseUrl - The base URL of the Lendaswap API.
@@ -197,6 +200,25 @@ export class ClientBuilder {
197
200
  this.#aa = aa;
198
201
  return this;
199
202
  }
203
+ /**
204
+ * Sets the logger sink used by the SDK.
205
+ *
206
+ * The SDK is silent by default. Pair this with `withLogLevel()` to opt in
207
+ * to runtime logs.
208
+ */
209
+ withLogger(logger) {
210
+ this.#logger = logger;
211
+ return this;
212
+ }
213
+ /**
214
+ * Sets the minimum log level emitted by the SDK.
215
+ *
216
+ * Defaults to `silent`.
217
+ */
218
+ withLogLevel(logLevel) {
219
+ this.#logLevel = logLevel;
220
+ return this;
221
+ }
200
222
  /**
201
223
  * Builds and returns a fully initialized Client instance.
202
224
  *
@@ -253,6 +275,8 @@ export class ClientBuilder {
253
275
  esploraUrl: this.#esploraUrl?.replace(/\/+$/, ""),
254
276
  arkadeServerUrl: this.#arkadeServerUrl?.replace(/\/+$/, ""),
255
277
  aa: this.#aa,
278
+ logger: this.#logger,
279
+ logLevel: this.#logLevel,
256
280
  }, signer, this.#signerStorage, this.#swapStorage);
257
281
  }
258
282
  }
@@ -288,6 +312,7 @@ export class Client {
288
312
  #swapStorage;
289
313
  #statusWatcher = null;
290
314
  #cctpInbound = null;
315
+ #logger;
291
316
  /**
292
317
  * Creates a new Client instance.
293
318
  *
@@ -305,6 +330,10 @@ export class Client {
305
330
  this.#signer = signer;
306
331
  this.#signerStorage = signerStorage;
307
332
  this.#swapStorage = swapStorage;
333
+ this.#logger = createSdkLogger({
334
+ logger: config.logger,
335
+ logLevel: config.logLevel,
336
+ });
308
337
  }
309
338
  /**
310
339
  * Subscribe to status updates for one or more swaps over a shared WebSocket.
@@ -366,6 +395,8 @@ export class Client {
366
395
  this.#cctpInbound = new CctpInboundClient({
367
396
  apiClient: this.#apiClient,
368
397
  aa: this.#config.aa,
398
+ logger: this.#config.logger,
399
+ logLevel: this.#config.logLevel,
369
400
  });
370
401
  }
371
402
  return this.#cctpInbound;
@@ -749,9 +780,12 @@ export class Client {
749
780
  * @returns The recovered swaps stored locally.
750
781
  */
751
782
  async recoverSwaps() {
752
- console.log(`Recovering ...`);
753
783
  const xpub = this.getUserIdXpub();
754
- console.log(`Recovering ${xpub}`);
784
+ this.#logger.info({
785
+ event: "client.recover.start",
786
+ message: "Recovering swaps for wallet",
787
+ data: { xpub },
788
+ });
755
789
  const { data, error } = await this.#apiClient.POST("/swap/recover", {
756
790
  body: { xpub },
757
791
  });
@@ -762,7 +796,14 @@ export class Client {
762
796
  throw new Error("No recovery data returned");
763
797
  }
764
798
  const storedSwaps = [];
765
- console.log(`Recovered data ${JSON.stringify(data)}`);
799
+ this.#logger.debug({
800
+ event: "client.recover.response",
801
+ message: "Recovered swap data from server",
802
+ data: {
803
+ recoveredSwapCount: data.swaps.length,
804
+ highestIndex: data.highest_index,
805
+ },
806
+ });
766
807
  for (const recoveredSwap of data.swaps) {
767
808
  const { index, ...response } = recoveredSwap;
768
809
  const swapParams = this.deriveSwapParamsAtIndex(index);
@@ -1112,12 +1153,22 @@ export class Client {
1112
1153
  // Query VTXO status to determine claim method, polling briefly while
1113
1154
  // the Arkade indexer catches up if the funding tx hasn't been seen yet.
1114
1155
  const vtxoStatus = await this.#waitForVtxoStatus(id, options.waitForVtxoMs ?? 30_000);
1115
- if (vtxoStatus === "not_funded" || vtxoStatus === "spent") {
1156
+ if (vtxoStatus === "not_funded") {
1116
1157
  return {
1117
1158
  success: false,
1118
- message: vtxoStatus === "not_funded"
1119
- ? `No VTXOs found at the VHTLC address ${claimParams.vhtlcAddress}. The swap may not have been funded yet.`
1120
- : "All VTXOs have already been spent.",
1159
+ message: `No VTXOs found at the VHTLC address ${claimParams.vhtlcAddress}. The swap may not have been funded yet.`,
1160
+ };
1161
+ }
1162
+ if (vtxoStatus === "spent") {
1163
+ // A submitted-but-not-finalized Arkade offchain tx can make the original
1164
+ // VHTLC inputs look spent. Try to resume that pending tx before declaring
1165
+ // the claim already spent.
1166
+ const continued = await this.continueArkadeClaimSwap(id);
1167
+ if (continued.success)
1168
+ return continued;
1169
+ return {
1170
+ success: false,
1171
+ message: "All VTXOs have already been spent.",
1121
1172
  };
1122
1173
  }
1123
1174
  // Route based on VTXO status:
@@ -1195,6 +1246,8 @@ export class Client {
1195
1246
  ...claimParams,
1196
1247
  destinationAddress: "", // not needed for continue
1197
1248
  arkadeServerUrl: this.#config.arkadeServerUrl,
1249
+ logger: this.#config.logger,
1250
+ logLevel: this.#config.logLevel,
1198
1251
  });
1199
1252
  return {
1200
1253
  success: true,
@@ -1289,6 +1342,8 @@ export class Client {
1289
1342
  ...params,
1290
1343
  destinationAddress: options.destinationAddress,
1291
1344
  arkadeServerUrl: options.arkadeServerUrl ?? this.#config.arkadeServerUrl,
1345
+ logger: this.#config.logger,
1346
+ logLevel: this.#config.logLevel,
1292
1347
  });
1293
1348
  return {
1294
1349
  success: true,
@@ -1317,6 +1372,8 @@ export class Client {
1317
1372
  lendaswapApiUrl: this.#config.baseUrl,
1318
1373
  arkadeServerUrl: options.arkadeServerUrl ?? this.#config.arkadeServerUrl,
1319
1374
  swapId,
1375
+ logger: this.#config.logger,
1376
+ logLevel: this.#config.logLevel,
1320
1377
  });
1321
1378
  return {
1322
1379
  success: true,
@@ -1893,6 +1950,8 @@ export class Client {
1893
1950
  swapId: id,
1894
1951
  apiClient: this.#apiClient,
1895
1952
  arkadeServerUrl: options.arkadeServerUrl ?? this.#config.arkadeServerUrl,
1953
+ logger: this.#config.logger,
1954
+ logLevel: this.#config.logLevel,
1896
1955
  };
1897
1956
  try {
1898
1957
  if (vtxoStatus === "spendable") {
@@ -1918,7 +1977,13 @@ export class Client {
1918
1977
  const collabMsg = collabError instanceof Error
1919
1978
  ? collabError.message
1920
1979
  : String(collabError);
1921
- console.warn(`Collaborative refund failed (${collabMsg}), falling back to non-collab refund`);
1980
+ this.#logger.warn({
1981
+ event: "arkade.refund.collab_failed",
1982
+ message: "Collaborative refund failed, falling back to non-collaborative refund",
1983
+ swapId: id,
1984
+ data: { reason: collabMsg },
1985
+ error: collabError,
1986
+ });
1922
1987
  }
1923
1988
  // Fallback: non-collaborative refund (requires locktime to have expired)
1924
1989
  const now = Math.floor(Date.now() / 1000);
@@ -2000,6 +2065,8 @@ export class Client {
2000
2065
  arkadeServerUrl: options.arkadeServerUrl ?? this.#config.arkadeServerUrl,
2001
2066
  swapId: id,
2002
2067
  apiClient: this.#apiClient,
2068
+ logger: this.#config.logger,
2069
+ logLevel: this.#config.logLevel,
2003
2070
  });
2004
2071
  return {
2005
2072
  success: true,
@@ -2013,7 +2080,13 @@ export class Client {
2013
2080
  const collabMsg = collabError instanceof Error
2014
2081
  ? collabError.message
2015
2082
  : String(collabError);
2016
- console.warn(`collaborative refund failed (${collabMsg}), checking locktime fallback`);
2083
+ this.#logger.warn({
2084
+ event: "arkade_to_lightning.refund.collab_failed",
2085
+ message: "Collaborative refund failed, checking locktime fallback",
2086
+ swapId: id,
2087
+ data: { reason: collabMsg },
2088
+ error: collabError,
2089
+ });
2017
2090
  }
2018
2091
  // Fallback: non-collaborative refund (requires locktime to have expired)
2019
2092
  // TODO: Should use Bitcoin's MTP.
@@ -2073,6 +2146,8 @@ export class Client {
2073
2146
  const result = await buildArkadeRefund({
2074
2147
  ...params,
2075
2148
  arkadeServerUrl: options.arkadeServerUrl ?? this.#config.arkadeServerUrl,
2149
+ logger: this.#config.logger,
2150
+ logLevel: this.#config.logLevel,
2076
2151
  });
2077
2152
  return {
2078
2153
  success: true,
@@ -2100,6 +2175,8 @@ export class Client {
2100
2175
  ...params,
2101
2176
  lendaswapApiUrl: this.#config.baseUrl,
2102
2177
  arkadeServerUrl: options.arkadeServerUrl ?? this.#config.arkadeServerUrl,
2178
+ logger: this.#config.logger,
2179
+ logLevel: this.#config.logLevel,
2103
2180
  });
2104
2181
  return {
2105
2182
  success: true,
@@ -2504,6 +2581,8 @@ export class Client {
2504
2581
  baseUrl: this.#config.baseUrl,
2505
2582
  deriveSwapParams: () => this.deriveSwapParams(),
2506
2583
  evmAddress: this.getEvmAddress(),
2584
+ logger: this.#config.logger,
2585
+ logLevel: this.#config.logLevel,
2507
2586
  skipKeyIndices: async (n) => {
2508
2587
  if (this.#signerStorage) {
2509
2588
  const current = await this.#signerStorage.getKeyIndex();
@@ -3082,11 +3161,16 @@ export class Client {
3082
3161
  ? oldSwap.hash_lock.slice(2)
3083
3162
  : oldSwap.hash_lock;
3084
3163
  // Collaborative refund: old VHTLC → new VHTLC address
3085
- console.log("[retry] Starting collaborative refund", {
3086
- oldSwapId: swapId,
3087
- newSwapId: newSwap.id,
3088
- sourceAmount: sourceAmountSats,
3089
- network: oldSwap.network,
3164
+ this.#logger.info({
3165
+ event: "arkade_to_lightning.retry.collab_refund_start",
3166
+ message: "Starting collaborative refund before retry",
3167
+ swapId,
3168
+ data: {
3169
+ oldSwapId: swapId,
3170
+ newSwapId: newSwap.id,
3171
+ sourceAmount: sourceAmountSats,
3172
+ network: oldSwap.network,
3173
+ },
3090
3174
  });
3091
3175
  const refundResult = await collabRefundArkadeToLightningOffchain({
3092
3176
  userSecretKey: storedSwap.secretKey,
@@ -3104,6 +3188,8 @@ export class Client {
3104
3188
  arkadeServerUrl: this.#config.arkadeServerUrl,
3105
3189
  swapId,
3106
3190
  apiClient: this.#apiClient,
3191
+ logger: this.#config.logger,
3192
+ logLevel: this.#config.logLevel,
3107
3193
  });
3108
3194
  return {
3109
3195
  newSwap,
@@ -3863,39 +3949,39 @@ export class Client {
3863
3949
  *
3864
3950
  * For Arkade-destination swaps (EVM/Bitcoin/Lightning → Arkade), queries the
3865
3951
  * Arkade indexer for VTXOs at the `target_arkade_address` and checks if any
3866
- * VTXO's txid matches the swap's `btc_claim_txid`.
3952
+ * VTXO's txid matches the Arkade txid that paid the target address.
3867
3953
  *
3868
3954
  * @param swapId - The UUID of the swap
3869
- * @returns `true` if the VTXO matching `btc_claim_txid` was found
3955
+ * @returns `true` if the received Arkade VTXO was found
3870
3956
  */
3871
3957
  async hasReceivedVtxo(swapId) {
3872
3958
  const swap = await this.getSwap(swapId);
3873
- // Extract target_arkade_address and btc_claim_txid based on direction
3959
+ // Extract target_arkade_address and the Arkade-side txid that pays it.
3874
3960
  let targetArkadeAddress;
3875
- let btcClaimTxid;
3961
+ let receiveArkadeTxid;
3876
3962
  let network;
3877
3963
  if (swap.direction === "evm_to_arkade") {
3878
3964
  const s = swap;
3879
3965
  targetArkadeAddress = s.target_arkade_address;
3880
- btcClaimTxid = s.btc_claim_txid;
3966
+ receiveArkadeTxid = s.btc_claim_txid;
3881
3967
  network = s.network;
3882
3968
  }
3883
3969
  else if (swap.direction === "btc_to_arkade") {
3884
3970
  const s = swap;
3885
3971
  targetArkadeAddress = s.target_arkade_address;
3886
- btcClaimTxid = s.arkade_claim_txid;
3972
+ receiveArkadeTxid = s.arkade_claim_txid;
3887
3973
  network = s.network;
3888
3974
  }
3889
3975
  else if (swap.direction === "lightning_to_arkade") {
3890
3976
  const s = swap;
3891
3977
  targetArkadeAddress = s.target_arkade_address;
3892
- btcClaimTxid = s.btc_claim_txid;
3978
+ receiveArkadeTxid = s.arkade_claim_txid;
3893
3979
  network = s.network;
3894
3980
  }
3895
3981
  else {
3896
3982
  throw new Error(`hasReceivedVtxo only works for Arkade-destination swaps, got ${swap.direction}`);
3897
3983
  }
3898
- if (!btcClaimTxid) {
3984
+ if (!receiveArkadeTxid) {
3899
3985
  return false;
3900
3986
  }
3901
3987
  const { ArkAddress, RestIndexerProvider } = await import("@arkade-os/sdk");
@@ -3910,7 +3996,7 @@ export class Client {
3910
3996
  const { vtxos } = await indexer.getVtxos({
3911
3997
  scripts: [pkScript],
3912
3998
  });
3913
- return vtxos.some((v) => v.txid === btcClaimTxid);
3999
+ return vtxos.some((v) => v.txid === receiveArkadeTxid);
3914
4000
  }
3915
4001
  }
3916
4002
  //# sourceMappingURL=client.js.map