@arkade-os/skill 0.1.2 → 0.1.4

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.
@@ -2,18 +2,15 @@
2
2
  /**
3
3
  * LendaSwapSkill - Swap USDC/USDT from/to Arkade via LendaSwap.
4
4
  *
5
- * This skill provides stablecoin swap capabilities for Arkade wallets
6
- * using the LendaSwap SDK for non-custodial BTC/stablecoin exchanges.
5
+ * Uses the @lendasat/lendaswap-sdk-pure SDK for non-custodial
6
+ * BTC/stablecoin atomic swaps via HTLCs.
7
7
  *
8
8
  * @module skills/lendaswap
9
9
  */
10
10
  Object.defineProperty(exports, "__esModule", { value: true });
11
11
  exports.LendaSwapSkill = void 0;
12
12
  exports.createLendaSwapSkill = createLendaSwapSkill;
13
- /**
14
- * Default LendaSwap API URL.
15
- */
16
- const DEFAULT_API_URL = "https://apilendaswap.lendasat.com/";
13
+ const lendaswap_sdk_pure_1 = require("@lendasat/lendaswap-sdk-pure");
17
14
  /**
18
15
  * Token decimals for stablecoins.
19
16
  */
@@ -25,389 +22,325 @@ const TOKEN_DECIMALS = {
25
22
  usdt_eth: 6,
26
23
  usdt_arb: 6,
27
24
  };
28
- function parseExpiry(raw, fallbackMs) {
29
- if (raw === null || raw === undefined) {
30
- return new Date(Date.now() + fallbackMs);
31
- }
32
- if (typeof raw === "string") {
33
- const parsed = new Date(raw);
34
- if (!Number.isNaN(parsed.getTime())) {
35
- return parsed;
36
- }
37
- }
38
- if (typeof raw === "number") {
39
- const ms = raw < 1000000000000 ? raw * 1000 : raw;
40
- return new Date(ms);
25
+ /**
26
+ * Map SDK swap status to our simplified status.
27
+ */
28
+ function mapSwapStatus(sdkStatus) {
29
+ switch (sdkStatus) {
30
+ case "pending":
31
+ return "pending";
32
+ case "clientfundingseen":
33
+ case "clientfunded":
34
+ return "funded";
35
+ case "serverfunded":
36
+ case "clientredeeming":
37
+ return "processing";
38
+ case "clientredeemed":
39
+ case "serverredeemed":
40
+ case "clientredeemedandclientrefunded":
41
+ return "completed";
42
+ case "expired":
43
+ case "clientfundedtoolate":
44
+ return "expired";
45
+ case "clientrefunded":
46
+ case "clientfundedserverrefunded":
47
+ case "clientrefundedserverfunded":
48
+ case "clientrefundedserverrefunded":
49
+ return "refunded";
50
+ case "clientinvalidfunded":
51
+ return "failed";
52
+ default:
53
+ return "pending";
41
54
  }
42
- return new Date(Date.now() + fallbackMs);
55
+ }
56
+ /**
57
+ * Check if a status is terminal (no longer active).
58
+ */
59
+ function isTerminalStatus(status) {
60
+ return (status === "completed" ||
61
+ status === "expired" ||
62
+ status === "refunded" ||
63
+ status === "failed");
43
64
  }
44
65
  /**
45
66
  * LendaSwapSkill provides stablecoin swap capabilities for Arkade wallets
46
- * using the LendaSwap SDK.
47
- *
48
- * This skill enables:
49
- * - Swapping BTC from Arkade to USDC/USDT on Polygon, Ethereum, or Arbitrum
50
- * - Receiving USDC/USDT and converting to BTC in your Arkade wallet
67
+ * using the LendaSwap SDK for non-custodial atomic swaps.
51
68
  *
52
69
  * @example
53
70
  * ```typescript
54
- * import { Wallet, SingleKey } from "@arkade-os/sdk";
55
- * import { LendaSwapSkill } from "@arkade-os/skill";
56
- *
57
- * // Create a wallet
58
- * const wallet = await Wallet.create({
59
- * identity: SingleKey.fromHex(privateKeyHex),
60
- * arkServerUrl: "https://arkade.computer",
61
- * });
62
- *
63
- * // Create the LendaSwap skill
64
71
  * const lendaswap = new LendaSwapSkill({ wallet });
65
72
  *
66
- * // Get a quote for BTC to USDC
73
+ * // Get a quote
67
74
  * const quote = await lendaswap.getQuoteBtcToStablecoin(100000, "usdc_pol");
68
- * console.log("You'll receive:", quote.targetAmount, "USDC");
69
75
  *
70
- * // Execute the swap
76
+ * // Create a swap (BTC → USDC)
71
77
  * const result = await lendaswap.swapBtcToStablecoin({
72
78
  * targetAddress: "0x...",
73
79
  * targetToken: "usdc_pol",
74
80
  * targetChain: "polygon",
75
81
  * sourceAmount: 100000,
76
82
  * });
77
- * console.log("Swap created:", result.swapId);
83
+ *
84
+ * // Fund the VHTLC address from your Arkade wallet, then claim
85
+ * const claim = await lendaswap.claimSwap(result.swapId);
78
86
  * ```
79
87
  */
80
88
  class LendaSwapSkill {
81
- /**
82
- * Creates a new LendaSwapSkill instance.
83
- *
84
- * @param config - Configuration options
85
- */
86
89
  constructor(config) {
87
90
  this.name = "lendaswap";
88
91
  this.description = "Swap USDC/USDT from/to Arkade via LendaSwap non-custodial exchange";
89
- this.version = "1.0.0";
90
- this.swapStorage = new Map();
92
+ this.version = "2.0.0";
93
+ this.client = null;
91
94
  this.wallet = config.wallet;
92
- this.apiUrl = config.apiUrl || DEFAULT_API_URL;
93
- this.apiKey = config.apiKey;
94
95
  this.referralCode = config.referralCode;
96
+ this.config = config;
95
97
  }
96
98
  /**
97
- * Check if the skill is available and properly configured.
99
+ * Get or create the LendaSwap SDK client (lazy initialization).
98
100
  */
101
+ async getClient() {
102
+ if (this.client)
103
+ return this.client;
104
+ const builder = lendaswap_sdk_pure_1.Client.builder()
105
+ .withSignerStorage(this.config.walletStorage || new lendaswap_sdk_pure_1.InMemoryWalletStorage())
106
+ .withSwapStorage(this.config.swapStorage || new lendaswap_sdk_pure_1.InMemorySwapStorage());
107
+ if (this.config.apiUrl) {
108
+ builder.withBaseUrl(this.config.apiUrl);
109
+ }
110
+ if (this.config.apiKey) {
111
+ builder.withApiKey(this.config.apiKey);
112
+ }
113
+ if (this.config.esploraUrl) {
114
+ builder.withEsploraUrl(this.config.esploraUrl);
115
+ }
116
+ if (this.config.arkadeServerUrl) {
117
+ builder.withArkadeServerUrl(this.config.arkadeServerUrl);
118
+ }
119
+ if (this.config.mnemonic) {
120
+ builder.withMnemonic(this.config.mnemonic);
121
+ }
122
+ this.client = await builder.build();
123
+ return this.client;
124
+ }
99
125
  async isAvailable() {
100
126
  try {
101
- const response = await this.fetchApi("/pairs");
102
- return response.ok;
127
+ const client = await this.getClient();
128
+ const result = await client.healthCheck();
129
+ return result === "ok";
103
130
  }
104
131
  catch {
105
132
  return false;
106
133
  }
107
134
  }
108
135
  /**
109
- * Get a quote for swapping BTC to stablecoins.
136
+ * Get the LendaSwap mnemonic for persistence across sessions.
137
+ */
138
+ async getMnemonic() {
139
+ const client = await this.getClient();
140
+ return client.getMnemonic();
141
+ }
142
+ /**
143
+ * Get the API version info.
110
144
  */
145
+ async getVersion() {
146
+ const client = await this.getClient();
147
+ return client.getVersion();
148
+ }
111
149
  async getQuoteBtcToStablecoin(sourceAmount, targetToken) {
112
- const response = await this.fetchApi("/quote", {
113
- method: "POST",
114
- body: JSON.stringify({
115
- from: "btc_arkade",
116
- to: targetToken,
117
- amount: sourceAmount,
118
- }),
119
- });
120
- if (!response.ok) {
121
- throw new Error(`Failed to get quote: ${response.statusText}`);
122
- }
123
- const data = (await response.json());
150
+ const client = await this.getClient();
151
+ const quote = await client.getQuote("btc_arkade", targetToken, sourceAmount);
152
+ const rate = parseFloat(quote.exchange_rate);
153
+ const netSats = sourceAmount - quote.protocol_fee - quote.network_fee;
154
+ const targetAmount = (netSats / 1e8) * rate;
124
155
  return {
125
156
  sourceToken: "btc_arkade",
126
157
  targetToken,
127
158
  sourceAmount,
128
- targetAmount: data.targetAmount,
129
- exchangeRate: data.exchangeRate,
159
+ targetAmount,
160
+ exchangeRate: rate,
130
161
  fee: {
131
- amount: data.fee?.amount || 0,
132
- percentage: data.fee?.percentage || 0,
162
+ amount: quote.protocol_fee + quote.network_fee,
163
+ percentage: quote.protocol_fee_rate * 100,
133
164
  },
134
- expiresAt: parseExpiry(data.expiresAt, 60000),
165
+ expiresAt: new Date(Date.now() + 60000),
135
166
  };
136
167
  }
137
- /**
138
- * Get a quote for swapping stablecoins to BTC.
139
- */
140
168
  async getQuoteStablecoinToBtc(sourceAmount, sourceToken) {
141
- const response = await this.fetchApi("/quote", {
142
- method: "POST",
143
- body: JSON.stringify({
144
- from: sourceToken,
145
- to: "btc_arkade",
146
- amount: sourceAmount,
147
- }),
148
- });
149
- if (!response.ok) {
150
- throw new Error(`Failed to get quote: ${response.statusText}`);
151
- }
152
- const data = (await response.json());
169
+ const client = await this.getClient();
170
+ const quote = await client.getQuote(sourceToken, "btc_arkade", sourceAmount);
171
+ const rate = parseFloat(quote.exchange_rate);
172
+ const grossSats = (sourceAmount / rate) * 1e8;
173
+ const targetAmount = grossSats - quote.protocol_fee - quote.network_fee;
153
174
  return {
154
175
  sourceToken,
155
176
  targetToken: "btc_arkade",
156
177
  sourceAmount,
157
- targetAmount: data.targetAmount,
158
- exchangeRate: data.exchangeRate,
178
+ targetAmount: Math.max(0, Math.floor(targetAmount)),
179
+ exchangeRate: rate,
159
180
  fee: {
160
- amount: data.fee?.amount || 0,
161
- percentage: data.fee?.percentage || 0,
181
+ amount: quote.protocol_fee + quote.network_fee,
182
+ percentage: quote.protocol_fee_rate * 100,
162
183
  },
163
- expiresAt: parseExpiry(data.expiresAt, 60000),
184
+ expiresAt: new Date(Date.now() + 60000),
164
185
  };
165
186
  }
166
- /**
167
- * Swap BTC from Arkade to stablecoins on EVM.
168
- */
169
187
  async swapBtcToStablecoin(params) {
170
- const arkAddress = await this.wallet.getAddress();
171
- const response = await this.fetchApi("/swap/btc-to-evm", {
172
- method: "POST",
173
- body: JSON.stringify({
174
- sourceAddress: arkAddress,
175
- targetAddress: params.targetAddress,
176
- targetToken: params.targetToken,
177
- targetChain: params.targetChain,
178
- sourceAmount: params.sourceAmount,
179
- targetAmount: params.targetAmount,
180
- referralCode: params.referralCode || this.referralCode,
181
- }),
182
- });
183
- if (!response.ok) {
184
- throw new Error(`Failed to create swap: ${response.statusText}`);
185
- }
186
- const data = (await response.json());
187
- const resolvedSourceAmount = params.sourceAmount ?? data.sourceAmount ?? 0;
188
- // Store swap locally
189
- const storedSwap = {
190
- swapId: data.swapId,
191
- direction: "btc_to_stablecoin",
192
- status: "awaiting_funding",
193
- sourceToken: "btc_arkade",
188
+ const client = await this.getClient();
189
+ const result = await client.createArkadeToEvmSwap({
190
+ targetAddress: params.targetAddress,
194
191
  targetToken: params.targetToken,
195
- sourceAmount: resolvedSourceAmount,
196
- targetAmount: data.targetAmount || 0,
197
- exchangeRate: data.exchangeRate || 0,
198
- createdAt: Date.now(),
199
- response: data,
200
- };
201
- this.swapStorage.set(data.swapId, storedSwap);
192
+ targetChain: params.targetChain,
193
+ sourceAmount: params.sourceAmount,
194
+ targetAmount: params.targetAmount,
195
+ referralCode: params.referralCode || this.referralCode,
196
+ });
197
+ const resp = result.response;
202
198
  return {
203
- swapId: data.swapId,
204
- status: "awaiting_funding",
205
- sourceAmount: resolvedSourceAmount,
206
- targetAmount: data.targetAmount || 0,
207
- exchangeRate: data.exchangeRate || 0,
199
+ swapId: resp.id,
200
+ status: mapSwapStatus(resp.status),
201
+ sourceAmount: resp.source_amount,
202
+ targetAmount: resp.target_amount,
203
+ exchangeRate: 0,
208
204
  fee: {
209
- amount: data.fee?.amount || 0,
210
- percentage: data.fee?.percentage || 0,
205
+ amount: resp.fee_sats,
206
+ percentage: 0,
211
207
  },
212
- expiresAt: new Date(data.expiresAt || Date.now() + 3600000),
208
+ expiresAt: new Date(resp.vhtlc_refund_locktime * 1000),
213
209
  paymentDetails: {
214
- address: data.paymentAddress,
210
+ address: resp.htlc_address_arkade,
215
211
  },
216
212
  };
217
213
  }
218
- /**
219
- * Swap stablecoins from EVM to BTC on Arkade.
220
- */
221
214
  async swapStablecoinToBtc(params) {
222
- const arkAddress = await this.wallet.getAddress();
223
- const targetAddress = params.targetAddress || arkAddress;
224
- const response = await this.fetchApi("/swap/evm-to-arkade", {
225
- method: "POST",
226
- body: JSON.stringify({
227
- sourceChain: params.sourceChain,
228
- sourceToken: params.sourceToken,
229
- sourceAmount: params.sourceAmount,
230
- targetAddress,
231
- userAddress: params.userAddress,
232
- referralCode: params.referralCode || this.referralCode,
233
- }),
234
- });
235
- if (!response.ok) {
236
- throw new Error(`Failed to create swap: ${response.statusText}`);
237
- }
238
- const data = (await response.json());
239
- // Store swap locally
240
- const storedSwap = {
241
- swapId: data.swapId,
242
- direction: "stablecoin_to_btc",
243
- status: "awaiting_funding",
215
+ const client = await this.getClient();
216
+ const arkAddress = params.targetAddress || (await this.wallet.getAddress());
217
+ const result = await client.createEvmToArkadeSwap({
218
+ sourceChain: params.sourceChain,
244
219
  sourceToken: params.sourceToken,
245
- targetToken: "btc_arkade",
246
220
  sourceAmount: params.sourceAmount,
247
- targetAmount: data.targetAmount || 0,
248
- exchangeRate: data.exchangeRate || 0,
249
- createdAt: Date.now(),
250
- response: data,
251
- };
252
- this.swapStorage.set(data.swapId, storedSwap);
221
+ targetAddress: arkAddress,
222
+ userAddress: params.userAddress,
223
+ referralCode: params.referralCode || this.referralCode,
224
+ });
225
+ const resp = result.response;
253
226
  return {
254
- swapId: data.swapId,
255
- status: "awaiting_funding",
256
- sourceAmount: params.sourceAmount,
257
- targetAmount: data.targetAmount || 0,
258
- exchangeRate: data.exchangeRate || 0,
227
+ swapId: resp.id,
228
+ status: mapSwapStatus(resp.status),
229
+ sourceAmount: resp.source_amount,
230
+ targetAmount: resp.target_amount,
231
+ exchangeRate: 0,
259
232
  fee: {
260
- amount: data.fee?.amount || 0,
261
- percentage: data.fee?.percentage || 0,
233
+ amount: resp.fee_sats,
234
+ percentage: 0,
262
235
  },
263
- expiresAt: new Date(data.expiresAt || Date.now() + 3600000),
236
+ expiresAt: new Date(resp.evm_refund_locktime * 1000),
264
237
  paymentDetails: {
265
- address: data.htlcAddress,
266
- callData: data.fundingCallData,
238
+ address: resp.htlc_address_evm,
239
+ callData: resp.source_token_address,
267
240
  },
268
241
  };
269
242
  }
270
- /**
271
- * Get the status of a swap.
272
- */
273
243
  async getSwapStatus(swapId) {
274
- const response = await this.fetchApi(`/swap/${swapId}`);
275
- if (!response.ok) {
276
- throw new Error(`Failed to get swap status: ${response.statusText}`);
277
- }
278
- const data = (await response.json());
279
- // Update local storage
280
- const stored = this.swapStorage.get(swapId);
281
- if (stored) {
282
- stored.status = data.status;
283
- stored.txid = data.txid;
284
- if (data.status === "completed") {
285
- stored.completedAt = Date.now();
286
- }
287
- }
244
+ const client = await this.getClient();
245
+ const data = await client.getSwap(swapId, { updateStorage: true });
246
+ const direction = data.direction === "evm_to_btc"
247
+ ? "stablecoin_to_btc"
248
+ : "btc_to_stablecoin";
249
+ const status = mapSwapStatus(data.status);
288
250
  return {
289
251
  id: swapId,
290
- direction: data.direction || stored?.direction || "btc_to_stablecoin",
291
- status: data.status,
292
- sourceToken: data.sourceToken || stored?.sourceToken || "",
293
- targetToken: data.targetToken || stored?.targetToken || "",
294
- sourceAmount: data.sourceAmount || stored?.sourceAmount || 0,
295
- targetAmount: data.targetAmount || stored?.targetAmount || 0,
296
- exchangeRate: data.exchangeRate || stored?.exchangeRate || 0,
297
- createdAt: new Date(data.createdAt || stored?.createdAt || Date.now()),
298
- completedAt: data.completedAt ? new Date(data.completedAt) : undefined,
299
- txid: data.txid,
252
+ direction,
253
+ status,
254
+ sourceToken: data.source_token,
255
+ targetToken: data.target_token,
256
+ sourceAmount: data.source_amount,
257
+ targetAmount: data.target_amount,
258
+ exchangeRate: 0,
259
+ createdAt: new Date(data.created_at),
260
+ completedAt: status === "completed" ? new Date() : undefined,
261
+ txid: ("evm_htlc_claim_txid" in data
262
+ ? data.evm_htlc_claim_txid
263
+ : undefined) ?? undefined,
300
264
  };
301
265
  }
302
- /**
303
- * Get pending stablecoin swaps.
304
- */
305
266
  async getPendingSwaps() {
267
+ const client = await this.getClient();
268
+ const allSwaps = await client.listAllSwaps();
306
269
  const pending = [];
307
- for (const [id, swap] of this.swapStorage) {
308
- if (swap.status !== "completed" &&
309
- swap.status !== "expired" &&
310
- swap.status !== "refunded" &&
311
- swap.status !== "failed") {
270
+ for (const stored of allSwaps) {
271
+ const status = mapSwapStatus(stored.response.status);
272
+ if (!isTerminalStatus(status)) {
312
273
  try {
313
- const status = await this.getSwapStatus(id);
314
- pending.push(status);
274
+ const info = await this.getSwapStatus(stored.swapId);
275
+ pending.push(info);
315
276
  }
316
277
  catch {
317
- // Swap might not exist on server anymore
318
- pending.push({
319
- id,
320
- direction: swap.direction,
321
- status: swap.status,
322
- sourceToken: swap.sourceToken,
323
- targetToken: swap.targetToken,
324
- sourceAmount: swap.sourceAmount,
325
- targetAmount: swap.targetAmount,
326
- exchangeRate: swap.exchangeRate,
327
- createdAt: new Date(swap.createdAt),
328
- });
278
+ pending.push(this.storedSwapToInfo(stored));
329
279
  }
330
280
  }
331
281
  }
332
282
  return pending;
333
283
  }
334
- /**
335
- * Get stablecoin swap history.
336
- */
337
284
  async getSwapHistory() {
338
- const history = [];
339
- for (const [id, swap] of this.swapStorage) {
340
- history.push({
341
- id,
342
- direction: swap.direction,
343
- status: swap.status,
344
- sourceToken: swap.sourceToken,
345
- targetToken: swap.targetToken,
346
- sourceAmount: swap.sourceAmount,
347
- targetAmount: swap.targetAmount,
348
- exchangeRate: swap.exchangeRate,
349
- createdAt: new Date(swap.createdAt),
350
- completedAt: swap.completedAt ? new Date(swap.completedAt) : undefined,
351
- txid: swap.txid,
352
- });
353
- }
354
- return history.sort((a, b) => b.createdAt.getTime() - a.createdAt.getTime());
285
+ const client = await this.getClient();
286
+ const allSwaps = await client.listAllSwaps();
287
+ return allSwaps
288
+ .map((stored) => this.storedSwapToInfo(stored))
289
+ .sort((a, b) => b.createdAt.getTime() - a.createdAt.getTime());
355
290
  }
356
- /**
357
- * Get available trading pairs.
358
- */
359
291
  async getAvailablePairs() {
360
- const response = await this.fetchApi("/pairs");
361
- if (!response.ok) {
362
- throw new Error(`Failed to get pairs: ${response.statusText}`);
363
- }
364
- const data = (await response.json());
365
- return (data.pairs || data || []).map((pair) => ({
366
- from: pair.from || pair.source,
367
- to: pair.to || pair.target,
368
- minAmount: pair.minAmount || pair.min || 0,
369
- maxAmount: pair.maxAmount || pair.max || 0,
370
- feePercentage: pair.feePercentage || pair.fee || 0,
292
+ const client = await this.getClient();
293
+ const pairs = await client.getAssetPairs();
294
+ return pairs.map((pair) => ({
295
+ from: pair.source.token_id,
296
+ to: pair.target.token_id,
297
+ minAmount: 0,
298
+ maxAmount: 0,
299
+ feePercentage: 0,
371
300
  }));
372
301
  }
373
- /**
374
- * Claim funds from a completed swap.
375
- */
376
302
  async claimSwap(swapId) {
377
- const response = await this.fetchApi(`/swap/${swapId}/claim`, {
378
- method: "POST",
379
- });
380
- if (!response.ok) {
381
- throw new Error(`Failed to claim swap: ${response.statusText}`);
382
- }
383
- const data = (await response.json());
384
- // Update local storage
385
- const stored = this.swapStorage.get(swapId);
386
- if (stored) {
387
- stored.status = "completed";
388
- stored.completedAt = Date.now();
389
- stored.txid = data.txid;
390
- }
391
- return { txid: data.txid };
303
+ const client = await this.getClient();
304
+ const result = await client.claim(swapId);
305
+ return {
306
+ success: result.success,
307
+ message: result.message,
308
+ txHash: result.txHash,
309
+ chain: result.chain,
310
+ };
392
311
  }
393
- /**
394
- * Refund an expired or failed swap.
395
- */
396
- async refundSwap(swapId) {
397
- const response = await this.fetchApi(`/swap/${swapId}/refund`, {
398
- method: "POST",
399
- });
400
- if (!response.ok) {
401
- throw new Error(`Failed to refund swap: ${response.statusText}`);
402
- }
403
- const data = (await response.json());
404
- // Update local storage
405
- const stored = this.swapStorage.get(swapId);
406
- if (stored) {
407
- stored.status = "refunded";
408
- stored.txid = data.txid;
409
- }
410
- return { txid: data.txid };
312
+ async refundSwap(swapId, options) {
313
+ const client = await this.getClient();
314
+ const refundOptions = options?.destinationAddress
315
+ ? { destinationAddress: options.destinationAddress }
316
+ : undefined;
317
+ const result = await client.refundSwap(swapId, refundOptions);
318
+ return {
319
+ success: result.success,
320
+ message: result.message,
321
+ txId: result.txId,
322
+ refundAmount: result.refundAmount
323
+ ? Number(result.refundAmount)
324
+ : undefined,
325
+ };
326
+ }
327
+ async getEvmFundingCallData(swapId, tokenDecimals) {
328
+ const client = await this.getClient();
329
+ const data = await client.getEvmFundingCallData(swapId, tokenDecimals);
330
+ return {
331
+ approve: { to: data.approve.to, data: data.approve.data },
332
+ createSwap: { to: data.createSwap.to, data: data.createSwap.data },
333
+ };
334
+ }
335
+ async getEvmRefundCallData(swapId) {
336
+ const client = await this.getClient();
337
+ const data = await client.getEvmRefundCallData(swapId);
338
+ return {
339
+ to: data.to,
340
+ data: data.data,
341
+ timelockExpired: data.timelockExpired,
342
+ timelockExpiry: data.timelockExpiry,
343
+ };
411
344
  }
412
345
  /**
413
346
  * Get the underlying wallet instance.
@@ -422,32 +355,31 @@ class LendaSwapSkill {
422
355
  return TOKEN_DECIMALS[token] || 6;
423
356
  }
424
357
  /**
425
- * Helper to fetch from LendaSwap API.
358
+ * Convert a StoredSwap to StablecoinSwapInfo.
426
359
  */
427
- async fetchApi(path, options = {}) {
428
- const url = `${this.apiUrl.replace(/\/$/, "")}${path}`;
429
- const headers = {
430
- "Content-Type": "application/json",
360
+ storedSwapToInfo(stored) {
361
+ const resp = stored.response;
362
+ const direction = resp.direction === "evm_to_btc"
363
+ ? "stablecoin_to_btc"
364
+ : "btc_to_stablecoin";
365
+ const status = mapSwapStatus(resp.status);
366
+ return {
367
+ id: stored.swapId,
368
+ direction,
369
+ status,
370
+ sourceToken: resp.source_token,
371
+ targetToken: resp.target_token,
372
+ sourceAmount: resp.source_amount,
373
+ targetAmount: resp.target_amount,
374
+ exchangeRate: 0,
375
+ createdAt: new Date(resp.created_at),
376
+ completedAt: status === "completed" ? new Date() : undefined,
431
377
  };
432
- if (this.apiKey) {
433
- headers["X-API-Key"] = this.apiKey;
434
- }
435
- return fetch(url, {
436
- ...options,
437
- headers: {
438
- ...headers,
439
- ...options.headers,
440
- },
441
- });
442
378
  }
443
379
  }
444
380
  exports.LendaSwapSkill = LendaSwapSkill;
445
381
  /**
446
382
  * Create a LendaSwapSkill from a wallet.
447
- *
448
- * @param wallet - The Arkade wallet to use
449
- * @param options - Optional configuration
450
- * @returns A new LendaSwapSkill instance
451
383
  */
452
384
  function createLendaSwapSkill(wallet, options) {
453
385
  return new LendaSwapSkill({