@atomiqlabs/sdk 1.3.19 → 2.1.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.
Files changed (49) hide show
  1. package/LICENSE +201 -201
  2. package/README.md +545 -501
  3. package/dist/SmartChainAssets.d.ts +73 -59
  4. package/dist/SmartChainAssets.js +75 -55
  5. package/dist/SwapperFactory.d.ts +49 -0
  6. package/dist/SwapperFactory.js +84 -0
  7. package/dist/Utils.d.ts +11 -0
  8. package/dist/Utils.js +37 -0
  9. package/dist/fs-storage/FileSystemStorageManager.d.ts +15 -0
  10. package/dist/fs-storage/FileSystemStorageManager.js +60 -0
  11. package/dist/fs-storage/index.d.ts +1 -0
  12. package/dist/fs-storage/index.js +17 -0
  13. package/dist/index.d.ts +5 -4
  14. package/dist/index.js +21 -20
  15. package/dist/storage/LocalStorageManager.d.ts +24 -0
  16. package/dist/storage/LocalStorageManager.js +68 -0
  17. package/package.json +31 -32
  18. package/src/SmartChainAssets.js +75 -0
  19. package/src/SmartChainAssets.ts +76 -62
  20. package/src/SwapperFactory.js +96 -0
  21. package/src/SwapperFactory.ts +171 -0
  22. package/src/Utils.js +37 -0
  23. package/src/Utils.ts +31 -0
  24. package/src/example/BrowserExample.js +199 -0
  25. package/src/example/BrowserExample.ts +141 -120
  26. package/src/example/NodeJSExample.js +206 -0
  27. package/src/example/NodeJSExample.ts +150 -120
  28. package/src/fs-storage/FileSystemStorageManager.ts +71 -0
  29. package/src/fs-storage/index.ts +1 -0
  30. package/src/index.js +21 -0
  31. package/src/index.ts +5 -4
  32. package/src/storage/LocalStorageManager.js +72 -0
  33. package/src/storage/LocalStorageManager.ts +81 -0
  34. package/dist/MultichainSwapper.d.ts +0 -46
  35. package/dist/MultichainSwapper.js +0 -83
  36. package/dist/chains/ChainInitializer.d.ts +0 -13
  37. package/dist/chains/ChainInitializer.js +0 -2
  38. package/dist/chains/solana/SolanaChainInitializer.d.ts +0 -41
  39. package/dist/chains/solana/SolanaChainInitializer.js +0 -60
  40. package/dist/chains/solana/SolanaChains.d.ts +0 -14
  41. package/dist/chains/solana/SolanaChains.js +0 -18
  42. package/dist/example/BrowserExample.d.ts +0 -1
  43. package/dist/example/BrowserExample.js +0 -104
  44. package/dist/example/NodeJSExample.d.ts +0 -1
  45. package/dist/example/NodeJSExample.js +0 -104
  46. package/src/MultichainSwapper.ts +0 -156
  47. package/src/chains/ChainInitializer.ts +0 -16
  48. package/src/chains/solana/SolanaChainInitializer.ts +0 -99
  49. package/src/chains/solana/SolanaChains.ts +0 -16
package/README.md CHANGED
@@ -1,501 +1,545 @@
1
- # atomiqlabs SDK
2
-
3
- A typescript multichain client for atomiqlabs trustlesss cross-chain swaps.
4
-
5
- ## Installation
6
- ```
7
- npm install @atomiqlabs/sdk
8
- ```
9
-
10
- ## How to use?
11
-
12
- ### Preparations
13
-
14
- Set Solana RPC URL to use
15
-
16
- ```typescript
17
- const solanaRpc = "https://api.mainnet-beta.solana.com";
18
- ```
19
-
20
- #### Browser
21
-
22
- This uses browser's Indexed DB by default
23
-
24
- ```typescript
25
- const swapper: MultichainSwapper = new MultichainSwapper({
26
- chains: {
27
- SOLANA: {
28
- rpcUrl: solanaRpc
29
- }
30
- }
31
- });
32
- ```
33
-
34
- #### NodeJS
35
-
36
- For NodeJS we need to explicitly use filsystem storage
37
-
38
- ```typescript
39
- const swapper: MultichainSwapper = new MultichainSwapper({
40
- chains: {
41
- SOLANA: {
42
- rpcUrl: solanaRpc
43
- }
44
- },
45
- //The following line is important for running on backend node.js,
46
- // because the SDK by default uses browser's Indexed DB
47
- storageCtor: (name: string) => new FileSystemStorageManager(name)
48
- });
49
- ```
50
-
51
- ### Signer
52
-
53
- ```typescript
54
- //React, using solana wallet adapter
55
- const anchorWallet = useAnchorWallet();
56
- const wallet = new SolanaSigner(anchorWallet);
57
- ```
58
-
59
- or
60
-
61
- ```typescript
62
- //Creating a wallet from scratch
63
- const signer = Keypair.fromSecretKey(_privateKey); //Or Keypair.generate() to generate new one
64
- const wallet = new SolanaSigner(signer);
65
- ```
66
-
67
- ### Initialization
68
-
69
- Initialize the swapper
70
-
71
- ```typescript
72
- await swapper.init();
73
- ```
74
-
75
- Now we have the multichain swapper initialized
76
-
77
- ### Extract chain-specific swapper with signer
78
-
79
- To make it easier to do swaps between bitcoin and a specific chain we can extract a chain-specific swapper, and also set a signer.
80
-
81
- ```typescript
82
- const solanaSwapper = swapper.withChain("SOLANA").withSigner(signer);
83
- ```
84
-
85
- ### Bitcoin on-chain swaps
86
-
87
- #### Swap Solana -> Bitcoin on-chain
88
-
89
- Initiating & executing the swap.
90
-
91
- ```typescript
92
- const _exactIn = false; //exactIn = false, so we specify the output amount
93
- const _amount = new BN(10000); //Amount in BTC base units - sats
94
- const _address = "bc1qtw67hj77rt8zrkkg3jgngutu0yfgt9czjwusxt"; //BTC address of the recipient
95
-
96
- //Create the swap: swapping SOL to Bitcoin on-chain, receiving _amount of satoshis (smallest unit of bitcoin) to _address
97
- const swap = await solanaSwapper.create(
98
- Tokens.SOLANA.SOL,
99
- Tokens.BITCOIN.BTC,
100
- _amount,
101
- _exactIn,
102
- _address
103
- );
104
-
105
- //Get the amount required to pay and fee
106
- const amountToBePaid: string = swap.getInput().amount; //Human readable amount to be paid on the Solana side (including fee)
107
- const fee: string = swap.getFee().amountInSrcToken.amount; //Human readable swap fee paid on the Solana side (already included in the the above amount)
108
-
109
- //Get swap expiration time
110
- const expiry: number = swap.getExpiry(); //Expiration time of the swap in UNIX milliseconds, swap needs to be initiated before this time
111
-
112
- //Initiate and pay for the swap
113
- await swap.commit();
114
-
115
- //Wait for the swap to conclude
116
- const result: boolean = await swap.waitForPayment();
117
- if(!result) {
118
- //Swap failed, money can be refunded
119
- await swap.refund();
120
- } else {
121
- //Swap successful, we can get the bitcoin txId
122
- const bitcoinTxId = swap.getBitcoinTxId();
123
- }
124
- ```
125
-
126
- ##### Swap states
127
-
128
- - ToBTCSwapState.REFUNDED = -3
129
- - Swap failed and was successfully refunded
130
- - ToBTCSwapState.QUOTE_EXPIRED = -2
131
- - Swap quote expired and cannot be executed anymore
132
- - ToBTCSwapState.QUOTE_SOFT_EXPIRED = -1
133
- - Swap quote soft-expired (i.e. the quote probably expired, but if there is already an initialization transaction sent it might still succeed)
134
- - ToBTCSwapState.CREATED = 0
135
- - Swap quote is created, waiting to be executed
136
- - ToBTCSwapState.COMMITED = 1,
137
- - Swap was initiated (init transaction sent)
138
- - ToBTCSwapState.SOFT_CLAIMED = 2,
139
- - Swap was processed by the counterparty but not yet claimed on-chain (bitcoin transaction was sent, but unconfirmed yet)
140
- - ToBTCSwapState.CLAIMED = 3
141
- - Swap was finished and funds were successfully claimed by the counterparty
142
- - ToBTCSwapState.REFUNDABLE = 4
143
- - Swap was initiated but counterparty failed to process it, the user can now refund his funds
144
-
145
- #### Swap Bitcoin on-chain -> Solana
146
-
147
- Initiating & executing the swap.
148
-
149
- ```typescript
150
- const _exactIn = true; //exactIn = true, so we specify the input amount
151
- const _amount = new BN(10000); //Amount in BTC base units - sats
152
-
153
- //Create the swap: swapping _amount of satoshis of Bitcoin on-chain to SOL
154
- const swap = await solanaSwapper.create(
155
- Tokens.BITCOIN.BTC,
156
- Tokens.SOLANA.SOL,
157
- _amount,
158
- _exactIn
159
- );
160
-
161
- //Get the amount required to pay, amount to be received and fee
162
- const amountToBePaidOnBitcoin: string = swap.getInput().amount; //Human readable amount of BTC that needs to be send to the BTC swap address
163
- const amountToBeReceivedOnSolana: string = swap.getOutput().amount; //Human readable amount SOL that will be received on Solana
164
- const fee: string = swap.getFee().amountInSrcToken.amount; //Human readable fee in BTC
165
-
166
- //Get swap offer expiration time
167
- const expiry: number = swap.getExpiry(); //Expiration time of the swap offer in UNIX milliseconds, swap needs to be initiated before this time
168
-
169
- //Get security deposit amount (Human readable amount of SOL that needs to be put down to rent the liquidity from swap intermediary), you will get this deposit back if the swap succeeds
170
- const securityDeposit: string = swap.getSecurityDeposit().amount;
171
- //Get claimer bounty (Human readable amount of SOL reserved as a reward for watchtowers to claim the swap on your behalf)
172
- const claimerBounty: string = swap.getClaimerBounty().amount;
173
-
174
- //Once client is happy with swap offer, we can send a Solana transaction that initiates the swap by opening a bitcoin swap address
175
- await swap.commit();
176
-
177
- //Get the bitcoin address
178
- const receivingAddressOnBitcoin = swap.getAddress();
179
- //Get the QR code data (contains the address and amount)
180
- const qrCodeData = swap.getQrData(); //Data that can be displayed in the form of QR code
181
- //Get the bitcoin swap address timeout (in UNIX millis), a transaction needs to be made in under this time
182
- const expiryTime = swap.getTimeoutTime();
183
-
184
- try {
185
- //Wait for the payment to arrive
186
- await swap.waitForPayment(
187
- null, null,
188
- (
189
- txId: string, //Transaction ID of the received bitcoin transaction
190
- confirmations: number, //Current confirmations of the transaction
191
- targetConfirmations: number, //Required confirmations
192
- transactionETAms: number //Estimated in time (in milliseconds) until when the transaction will receive required amount of confirmations
193
- ) => {
194
- //Callback for transaction updates
195
- }
196
- );
197
- //Swap will get automatically claimed by the watchtowers
198
- await swap.waitTillClaimed();
199
- } catch(e) {
200
- //Error occurred while waiting for payment
201
- }
202
- ```
203
-
204
- ##### Swap states
205
-
206
- - FromBTCSwapState.EXPIRED = -3
207
- - Bitcoin swap address expired
208
- - FromBTCSwapState.QUOTE_EXPIRED = -2
209
- - Swap quote expired and cannot be executed anymore
210
- - FromBTCSwapState.QUOTE_SOFT_EXPIRED = -1
211
- - Swap quote soft-expired (i.e. the quote probably expired, but if there is already an initialization transaction sent it might still succeed)
212
- - FromBTCSwapState.PR_CREATED = 0
213
- - Swap quote is created, waiting for the user to open a bitcoin swap address
214
- - FromBTCSwapState.CLAIM_COMMITED = 1
215
- - Bitcoin swap address is opened
216
- - FromBTCSwapState.BTC_TX_CONFIRMED = 2
217
- - Bitcoin transaction sending funds to the swap address is confirmed
218
- - FromBTCSwapState.CLAIM_CLAIMED = 3
219
- - Swap funds are claimed to the user's wallet
220
-
221
- ### Bitcoin lightning network swaps
222
-
223
- #### Swap Solana -> Bitcoin lightning network
224
-
225
- ```typescript
226
- //Destination lightning network invoice, amount needs to be part of the invoice!
227
- const _lightningInvoice = "lnbc10u1pj2q0g9pp5ejs6m677m39cznpzum7muruvh50ys93ln82p4j9ks2luqm56xxlshp52r2anlhddfa9ex9vpw9gstxujff8a0p8s3pzvua930js0kwfea6scqzzsxqyz5vqsp5073zskc5qfgp7lre0t6s8uexxxey80ax564hsjklfwfjq2ew0ewq9qyyssqvzmgs6f8mvuwgfa9uqxhtza07qem4yfhn9wwlpskccmuwplsqmh8pdy6c42kqdu8p73kky9lsnl40qha5396d8lpgn90y27ltfc5rfqqq59cya";
228
-
229
- //Create the swap: swapping SOL to Bitcoin lightning
230
- const swap = await solanaSwapper.create(
231
- Tokens.SOLANA.SOL,
232
- Tokens.BITCOIN.BTCLN,
233
- null,
234
- false,
235
- _lightningInvoice
236
- );
237
-
238
- //Get the amount required to pay and fee
239
- const amountToBePaid: string = swap.getInput().amount; //Human readable amount to be paid on the Solana side (including fee)
240
- const fee: string = swap.getFee().amountInSrcToken.amount; //Human readable swap fee paid on the Solana side (already included in the the above amount)
241
-
242
- //Get swap expiration time
243
- const expiry: number = swap.getExpiry(); //Expiration time of the swap in UNIX milliseconds, swap needs to be initiated before this time
244
-
245
- //Initiate and pay for the swap
246
- await swap.commit();
247
-
248
- //Wait for the swap to conclude
249
- const result: boolean = await swap.waitForPayment();
250
- if(!result) {
251
- //Swap failed, money can be refunded
252
- await swap.refund();
253
- } else {
254
- //Swap successful, we can get the lightning payment secret pre-image, which acts as a proof of payment
255
- const lightningSecret = swap.getSecret();
256
- }
257
- ```
258
-
259
- ##### Swap states
260
-
261
- - ToBTCSwapState.REFUNDED = -3
262
- - Swap failed and was successfully refunded
263
- - ToBTCSwapState.QUOTE_EXPIRED = -2
264
- - Swap quote expired and cannot be executed anymore
265
- - ToBTCSwapState.QUOTE_SOFT_EXPIRED = -1
266
- - Swap quote soft-expired (i.e. the quote probably expired, but if there is already an initialization transaction sent it might still succeed)
267
- - ToBTCSwapState.CREATED = 0
268
- - Swap quote is created, waiting to be executed
269
- - ToBTCSwapState.COMMITED = 1,
270
- - Swap was initiated (init transaction sent)
271
- - ToBTCSwapState.SOFT_CLAIMED = 2,
272
- - Swap was processed by the counterparty but not yet claimed on-chain (lightning network payment secret was revealed)
273
- - ToBTCSwapState.CLAIMED = 3
274
- - Swap was finished and funds were successfully claimed by the counterparty
275
- - ToBTCSwapState.REFUNDABLE = 4
276
- - Swap was initiated but counterparty failed to process it, the user can now refund his funds
277
-
278
- #### Swap Bitcoin lightning network -> Solana
279
- ```typescript
280
- const _exactIn = true; //exactIn = true, so we specify the input amount
281
- const _amount = new BN(10000); //Amount in BTC base units - sats
282
-
283
- //Create the swap: swapping _amount of satoshis from Bitcoin lightning network to SOL
284
- const swap = await solanaSwapper.create(
285
- Tokens.BITCOIN.BTCLN,
286
- Tokens.SOLANA.SOL,
287
- _amount,
288
- _exactIn
289
- );
290
-
291
- //Get the bitcoin lightning network invoice (the invoice contains pre-entered amount)
292
- const receivingLightningInvoice: string = swap.getLightningInvoice();
293
- //Get the QR code (contains the lightning network invoice)
294
- const qrCodeData: string = swap.getQrData(); //Data that can be displayed in the form of QR code
295
-
296
- //Get the amount required to pay, amount to be received and fee
297
- const amountToBePaidOnBitcoin: string = swap.getInput().amount; //Human readable amount of BTC that needs to be send to the BTC swap address
298
- const amountToBeReceivedOnSolana: string = swap.getOutput().amount; //Human readable amount SOL that will be received on Solana
299
- const fee: string = swap.getFee().amountInSrcToken.amount; //Human readable fee in BTC
300
-
301
- try {
302
- //Wait for the lightning payment to arrive
303
- await swap.waitForPayment();
304
- //Claim the swap funds - this will initiate 2 Solana transactions
305
- await swap.commitAndClaim();
306
- } catch(e) {
307
- //Error occurred while waiting for payment
308
- }
309
- ```
310
-
311
- ##### Swap states
312
-
313
- - FromBTCLNSwapState.FAILED = -4
314
- - If the claiming of the funds was initiated, but never concluded, the user will get his lightning network payment refunded
315
- - FromBTCLNSwapState.QUOTE_EXPIRED = -3
316
- - Swap quote expired and cannot be executed anymore
317
- - FromBTCLNSwapState.QUOTE_SOFT_EXPIRED = -2
318
- - Swap quote soft-expired (i.e. the quote probably expired, but if there is already an initialization transaction sent it might still succeed)
319
- - FromBTCLNSwapState.EXPIRED = -1
320
- - Lightning network invoice expired, meaning the swap is expired
321
- - FromBTCLNSwapState.PR_CREATED = 0
322
- - Swap is created, the user should now pay the provided lightning network invoice
323
- - FromBTCLNSwapState.PR_PAID = 1
324
- - Lightning network invoice payment was received (but cannot be settled by the counterparty yet)
325
- - FromBTCLNSwapState.CLAIM_COMMITED = 2
326
- - Claiming of the funds was initiated
327
- - FromBTCLNSwapState.CLAIM_CLAIMED = 3
328
- - Funds were successfully claimed & lightning network secret pre-image revealed, so the lightning network payment will settle now
329
-
330
- ### Getting state of the swap
331
-
332
- You can get the current state of the swap with:
333
-
334
- ```typescript
335
- const state = swap.getState();
336
- ```
337
-
338
- You can also set a listener to listen for swap state changes:
339
-
340
- ```typescript
341
- swap.events.on("swapState", swap => {
342
- const newState = swap.getState();
343
- });
344
- ```
345
-
346
- For the meaning of the states please refer to the "Swap state" section under each swap type.
347
-
348
- ### LNURLs & readable lightning identifiers
349
-
350
- LNURLs extend the lightning network functionality by creating static lightning addreses (LNURL-pay & static internet identifiers) and QR codes which allow you to pull funds from them (LNURL-withdraw)
351
-
352
- This SDK supports:
353
- * LNURL-pay ([LUD-6](https://github.com/lnurl/luds/blob/luds/06.md), [LUD-9](https://github.com/lnurl/luds/blob/luds/09.md), [LUD-10](https://github.com/lnurl/luds/blob/luds/10.md), [LUD-12](https://github.com/lnurl/luds/blob/luds/12.md))
354
- * LNURL-withdraw ([LUD-3](https://github.com/lnurl/luds/blob/luds/03.md))
355
- * Static internet identifiers ([LUD-16](https://github.com/lnurl/luds/blob/luds/16.md))
356
-
357
- #### Differences
358
-
359
- Lightning invoices:
360
- * One time use only
361
- * Need to have a fixed amount, therefore recipient has to set the amount
362
- * Static and bounded expiration
363
- * You can only pay to a lightning invoice, not withdraw funds from it
364
-
365
- LNURLs & lightning identifiers:
366
- * Reusable
367
- * Programmable expiry
368
- * Allows payer to set an amount
369
- * Supports both, paying (LNURL-pay) and withdrawing (LNURL-withdraw)
370
- * Possibility to attach a message/comment to a payment
371
- * Receive a message/url as a result of the payment
372
-
373
- #### Helpers
374
-
375
- It is good practice to automatically distinguish between lightning network invoices & LNURLs and adjust the UI accordingly.
376
- Therefore there are a few helper functions to help with that:
377
- ```typescript
378
- const isLNInvoice: boolean = swapper.isValidLightningInvoice(_input); //Checks if the input is lightning network invoice
379
- const isLNURL: boolean = swapper.isValidLNURL(_input); //Checks if the input is LNURL or lightning identifier
380
- if(isLNURL) {
381
- //Get the type of the LNURL
382
- const result: (LNURLPay | LNURLWithdraw | null) = await swapper.getLNURLTypeAndData(_input);
383
- if(result.type==="pay") {
384
- const lnurlPayData: LNURLPay = result;
385
- const minPayable: BN = lnurlPayData.min; //Minimum payment amount in satoshis
386
- const maxPayable: BN = lnurlPayData.max; //Maximum payment amount in satoshis
387
- const icon: (string | null) = lnurlPayData.icon; //URL encoded icon that should be displayed on the UI
388
- const shortDescription: (string | null) = lnurlPayData.shortDescription; //Short description of the payment
389
- const longDescription: (string | null) = lnurlPayData.longDescription; //Long description of the payment
390
- const maxCommentLength: (number | 0) = lnurlPayData.commentMaxLength; //Maximum allowed length of the payment message/comment (0 means no comment allowed)
391
- //Should show a UI displaying the icon, short description, long description, allowing the user to choose an amount he wishes to pay and possibly also a comment
392
- }
393
- if(result.type==="withdraw") {
394
- const lnurlWithdrawData: LNURLWithdraw = result;
395
- const minWithdrawable: BN = lnurlWithdrawData.min;
396
- const maxWithdrawable: BN = lnurlWithdrawData.max;
397
- //Should show a UI allowing the user to choose an amount he wishes to withdraw
398
- }
399
- }
400
- ```
401
-
402
- #### Swap Solana -> Bitcoin lightning network
403
- ```typescript
404
- const _lnurlOrIdentifier: string = "lnurl1dp68gurn8ghj7ampd3kx2ar0veekzar0wd5xjtnrdakj7tnhv4kxctttdehhwm30d3h82unvwqhkx6rfvdjx2ctvxyesuk0a27"; //Destination LNURL-pay or readable identifier
405
- const _exactIn = false; //exactIn = false, so we specify the output amount
406
- const _amount: BN = new BN(10000); //Amount of satoshis to send (1 BTC = 100 000 000 satoshis)
407
-
408
- //Create the swap: swapping SOL to Bitcoin lightning
409
- const swap = await solanaSwapper.create(
410
- Tokens.SOLANA.SOL,
411
- Tokens.BITCOIN.BTCLN,
412
- _amount,
413
- _exactIn,
414
- _lnurlOrIdentifier
415
- );
416
-
417
- //Get the amount required to pay and fee
418
- const amountToBePaid: string = swap.getInput().amount; //Human readable amount to be paid on the Solana side (including fee)
419
- const fee: string = swap.getFee().amountInSrcToken.amount; //Human readable swap fee paid on the Solana side (already included in the the above amount)
420
-
421
- //Get swap expiration time
422
- const expiry: number = swap.getExpiry(); //Expiration time of the swap in UNIX milliseconds, swap needs to be initiated before this time
423
-
424
- //Initiate and pay for the swap
425
- await swap.commit();
426
-
427
- //Wait for the swap to conclude
428
- const result: boolean = await swap.waitForPayment();
429
- if(!result) {
430
- //Swap failed, money can be refunded
431
- await swap.refund();
432
- } else {
433
- //Swap successful, we can get the lightning payment secret pre-image, which acts as a proof of payment
434
- const lightningSecret = swap.getSecret();
435
- //In case the LNURL contained a success action, we can read it now and display it to user
436
- if(swap.hasSuccessAction()) {
437
- //Contains a success action that should displayed to the user
438
- const successMessage = swap.getSuccessAction();
439
- const description: string = successMessage.description; //Description of the message
440
- const text: (string | null) = successMessage.text; //Main text of the message
441
- const url: (string | null) = successMessage.url; //URL link which should be displayed
442
- }
443
- }
444
- ```
445
-
446
- #### Swap Bitcoin lightning network -> Solana
447
- ```typescript
448
- const _lnurl: string = "lnurl1dp68gurn8ghj7ampd3kx2ar0veekzar0wd5xjtnrdakj7tnhv4kxctttdehhwm30d3h82unvwqhkx6rfvdjx2ctvxyesuk0a27"; //Destination LNURL-pay or readable identifier
449
- const _exactIn = true; //exactIn = true, so we specify the input amount
450
- const _amount = new BN(10000); //Amount in BTC base units - sats
451
-
452
- //Create the swap: swapping _amount of satoshis from Bitcoin lightning network to SOL
453
- const swap = await solanaSwapper.create(
454
- Tokens.BITCOIN.BTCLN,
455
- Tokens.SOLANA.SOL,
456
- _amount,
457
- _exactIn,
458
- _lnurl
459
- );
460
-
461
- //Get the amount of BTC to be withdrawn from LNURL, amount to be received and fee
462
- const amountToBeWithdrawnOnBitcoin: string = swap.getInput().amount; //Human readable amount of BTC that will be withdrawn from the LNURL
463
- const amountToBeReceivedOnSolana: string = swap.getOutput().amount; //Human readable amount SOL that will be received on Solana
464
- const fee: string = swap.getFee().amountInSrcToken.amount; //Human readable fee in BTC
465
-
466
- try {
467
- //Submit the withdraw request & wait for the payment to arrive
468
- await swap.waitForPayment();
469
- //Claim the swap funds - this will initiate 2 Solana transactions
470
- await swap.commitAndClaim();
471
- } catch(e) {
472
- //Error occurred while waiting for payment
473
- }
474
- ```
475
-
476
- ### Get refundable swaps
477
- You can refund the swaps in one of two cases:
478
- * In case intermediary is non-cooperative and goes offline, you can claim the funds from the swap contract back after some time.
479
- * In case intermediary tried to pay but was unsuccessful, so he sent you signed message with which you can refund now without waiting.
480
-
481
- This call can be checked on every startup and periodically every few minutes.
482
- ```typescript
483
- //Get the swaps
484
- const refundableSwaps = await swapper.getRefundableSwaps();
485
- //Refund all the swaps
486
- for(let swap of refundableSwaps) {
487
- await swap.refund();
488
- }
489
- ```
490
-
491
- ### Get claimable swaps
492
- Returns swaps that are ready to be claimed by the client, this can happen if client closes the application when a swap is in-progress and the swap is concluded while the client is offline.
493
-
494
- ```typescript
495
- //Get the swaps
496
- const claimableSwaps = await swapper.getClaimableSwaps();
497
- //Claim all the claimable swaps
498
- for(let swap of claimableSwaps) {
499
- await swap.commitAndClaim();
500
- }
501
- ```
1
+ # atomiqlabs SDK
2
+
3
+ A typescript multichain client for atomiqlabs trustlesss cross-chain swaps. Enables trustless swaps between smart chains (Solana, EVM, Starknet, etc.) and bitcoin (on-chain - L1 and lightning network - L2).
4
+
5
+ ## Installation
6
+ ```
7
+ npm install github:atomiqlabs/atomiq-sdk#refactor-storage
8
+ ```
9
+
10
+ ## Installing chain-specific connectors
11
+
12
+ You can install only the chain-specific connectors that your project requires
13
+
14
+ ```
15
+ npm install github:atomiqlabs/atomiq-chain-solana#add-starknet
16
+ npm install github:atomiqlabs/atomiq-chain-starknet
17
+ ```
18
+
19
+ ## How to use?
20
+
21
+ ### Preparations
22
+
23
+ Set Solana & Starknet RPC URL to use
24
+
25
+ ```typescript
26
+ const solanaRpc = "https://api.mainnet-beta.solana.com";
27
+ const starknetRpc = "https://starknet-mainnet.public.blastapi.io/rpc/v0_7";
28
+ ```
29
+
30
+ Create swapper factory, here we can pick and choose which chains we want to have supported in the SDK, ensure the "as const" keyword is used such that the typescript compiler can properly infer the types.
31
+
32
+ ```typescript
33
+ const Factory = new SwapperFactory<[SolanaInitializerType, StarknetInitializerType]>([SolanaInitializer, StarknetInitializer] as const);
34
+ const Tokens = Factory.Tokens; //Get the supported tokens for all the specified chains.
35
+ ```
36
+
37
+ #### Browser
38
+
39
+ This uses browser's Indexed DB by default
40
+
41
+ ```typescript
42
+ const swapper = Factory.newSwapper({
43
+ chains: {
44
+ SOLANA: {
45
+ rpcUrl: solanaRpc //You can also pass Connection object here
46
+ },
47
+ STARKNET: {
48
+ rpcUrl: starknetRpc //You can also pass Provider object here
49
+ }
50
+ },
51
+ bitcoinNetwork: BitcoinNetwork.TESTNET //or BitcoinNetwork.MAINNET - this also sets the network to use for Solana (solana devnet for bitcoin testnet) & Starknet (sepolia for bitcoin testnet)
52
+ });
53
+ ```
54
+
55
+ #### NodeJS
56
+
57
+ For NodeJS we need to explicitly use filesystem storage
58
+
59
+ ```typescript
60
+ const swapper = Factory.newSwapper({
61
+ chains: {
62
+ SOLANA: {
63
+ rpcUrl: solanaRpc //You can also pass Connection object here
64
+ },
65
+ STARKNET: {
66
+ rpcUrl: starknetRpc //You can also pass Provider object here
67
+ }
68
+ },
69
+ bitcoinNetwork: BitcoinNetwork.TESTNET, //or BitcoinNetwork.MAINNET - this also sets the network to use for Solana (solana devnet for bitcoin testnet) & Starknet (sepolia for bitcoin testnet)
70
+ //The following line is important for running on backend node.js,
71
+ // because the SDK by default uses browser's Indexed DB
72
+ storageCtor: (name: string) => new FileSystemStorageManager(name)
73
+ });
74
+ ```
75
+
76
+ ### Signer
77
+
78
+ ```typescript
79
+ //React, using solana wallet adapter
80
+ const anchorWallet = useAnchorWallet();
81
+ const wallet = new SolanaSigner(anchorWallet);
82
+ ```
83
+
84
+ ```typescript
85
+ //Browser, using get-starknet
86
+ const swo = await connect();
87
+ const wallet = new StarknetSigner(new WalletAccount(starknetRpc, swo));
88
+ ```
89
+
90
+ or
91
+
92
+ ```typescript
93
+ //Creating a random signer
94
+ const wallet = swapper.randomSigner<"SOLANA">("SOLANA");
95
+ ```
96
+
97
+ ### Initialization
98
+
99
+ Initialize the swapper
100
+
101
+ ```typescript
102
+ await swapper.init();
103
+ ```
104
+
105
+ Now we have the multichain swapper initialized
106
+
107
+ ### Extract chain-specific swapper with signer
108
+
109
+ To make it easier to do swaps between bitcoin and a specific chain we can extract a chain-specific swapper, and also set a signer.
110
+
111
+ ```typescript
112
+ const solanaSwapper = swapper.withChain<"SOLANA">("SOLANA").withSigner(signer);
113
+ ```
114
+
115
+ ### Bitcoin on-chain swaps
116
+
117
+ #### Swap Smart chain -> Bitcoin on-chain
118
+
119
+ Initiating & executing the swap.
120
+
121
+ ```typescript
122
+ const _exactIn = false; //exactIn = false, so we specify the output amount
123
+ const _amount = 10000n; //Amount in BTC base units - sats
124
+ const _address = "bc1qtw67hj77rt8zrkkg3jgngutu0yfgt9czjwusxt"; //BTC address of the recipient
125
+
126
+ //Create the swap: swapping SOL to Bitcoin on-chain, receiving _amount of satoshis (smallest unit of bitcoin) to _address
127
+ const swap = await solanaSwapper.create(
128
+ Tokens.SOLANA.SOL,
129
+ Tokens.BITCOIN.BTC,
130
+ _amount,
131
+ _exactIn,
132
+ _address
133
+ );
134
+
135
+ //Get the amount required to pay and fee
136
+ const amountToBePaid: string = swap.getInput().amount; //Human readable amount to be paid on the Solana side (including fee)
137
+ const fee: string = swap.getFee().amountInSrcToken.amount; //Human readable swap fee paid on the Solana side (already included in the the above amount)
138
+
139
+ //Get swap expiration time
140
+ const expiry: number = swap.getExpiry(); //Expiration time of the swap in UNIX milliseconds, swap needs to be initiated before this time
141
+
142
+ //Initiate and pay for the swap
143
+ await swap.commit();
144
+
145
+ //Wait for the swap to conclude
146
+ const result: boolean = await swap.waitForPayment();
147
+ if(!result) {
148
+ //Swap failed, money can be refunded
149
+ await swap.refund();
150
+ } else {
151
+ //Swap successful, we can get the bitcoin txId
152
+ const bitcoinTxId = swap.getBitcoinTxId();
153
+ }
154
+ ```
155
+
156
+ ##### Swap states
157
+
158
+ - ToBTCSwapState.REFUNDED = -3
159
+ - Swap failed and was successfully refunded
160
+ - ToBTCSwapState.QUOTE_EXPIRED = -2
161
+ - Swap quote expired and cannot be executed anymore
162
+ - ToBTCSwapState.QUOTE_SOFT_EXPIRED = -1
163
+ - Swap quote soft-expired (i.e. the quote probably expired, but if there is already an initialization transaction sent it might still succeed)
164
+ - ToBTCSwapState.CREATED = 0
165
+ - Swap quote is created, waiting to be executed
166
+ - ToBTCSwapState.COMMITED = 1,
167
+ - Swap was initiated (init transaction sent)
168
+ - ToBTCSwapState.SOFT_CLAIMED = 2,
169
+ - Swap was processed by the counterparty but not yet claimed on-chain (bitcoin transaction was sent, but unconfirmed yet)
170
+ - ToBTCSwapState.CLAIMED = 3
171
+ - Swap was finished and funds were successfully claimed by the counterparty
172
+ - ToBTCSwapState.REFUNDABLE = 4
173
+ - Swap was initiated but counterparty failed to process it, the user can now refund his funds
174
+
175
+ #### Swap Bitcoin on-chain -> Smart chain
176
+
177
+ Initiating & executing the swap.
178
+
179
+ ```typescript
180
+ const _exactIn = true; //exactIn = true, so we specify the input amount
181
+ const _amount = fromHumanReadableString("0.0001", Tokens.BITCOIN.BTC); //Amount in BTC base units - sats, we can also use a utility function here
182
+
183
+ //Create the swap: swapping _amount of satoshis of Bitcoin on-chain to SOL
184
+ const swap = await solanaSwapper.create(
185
+ Tokens.BITCOIN.BTC,
186
+ Tokens.SOLANA.SOL,
187
+ _amount,
188
+ _exactIn
189
+ );
190
+
191
+ //Get the amount required to pay, amount to be received and fee
192
+ const amountToBePaidOnBitcoin: string = swap.getInput().amount; //Human readable amount of BTC that needs to be send to the BTC swap address
193
+ const amountToBeReceivedOnSolana: string = swap.getOutput().amount; //Human readable amount SOL that will be received on Solana
194
+ const fee: string = swap.getFee().amountInSrcToken.amount; //Human readable fee in BTC
195
+
196
+ //Get swap offer expiration time
197
+ const expiry: number = swap.getExpiry(); //Expiration time of the swap offer in UNIX milliseconds, swap needs to be initiated before this time
198
+
199
+ //Get security deposit amount (Human readable amount of SOL that needs to be put down to rent the liquidity from swap intermediary), you will get this deposit back if the swap succeeds
200
+ const securityDeposit: string = swap.getSecurityDeposit().amount;
201
+ //Get claimer bounty (Human readable amount of SOL reserved as a reward for watchtowers to claim the swap on your behalf)
202
+ const claimerBounty: string = swap.getClaimerBounty().amount;
203
+
204
+ //Once client is happy with swap offer, we can send a Solana transaction that initiates the swap by opening a bitcoin swap address
205
+ await swap.commit();
206
+
207
+ //Get the bitcoin address
208
+ const receivingAddressOnBitcoin = swap.getAddress();
209
+ //Get the QR code data (contains the address and amount)
210
+ const qrCodeData = swap.getQrData(); //Data that can be displayed in the form of QR code
211
+ //Get the bitcoin swap address timeout (in UNIX millis), a transaction needs to be made in under this time
212
+ const expiryTime = swap.getTimeoutTime();
213
+
214
+ try {
215
+ //Wait for the payment to arrive
216
+ await swap.waitForPayment(
217
+ null, null,
218
+ (
219
+ txId: string, //Transaction ID of the received bitcoin transaction
220
+ confirmations: number, //Current confirmations of the transaction
221
+ targetConfirmations: number, //Required confirmations
222
+ transactionETAms: number //Estimated in time (in milliseconds) until when the transaction will receive required amount of confirmations
223
+ ) => {
224
+ //Callback for transaction updates
225
+ }
226
+ );
227
+ } catch(e) {
228
+ //Error occurred while waiting for payment, this is most likely due to network errors
229
+ return;
230
+ }
231
+
232
+ //Swap should get automatically claimed by the watchtowers, if not we can call swap.claim() ourselves
233
+ try {
234
+ await swap.waitTillClaimed(timeoutSignal(30*1000));
235
+ } catch (e) {
236
+ //Claim ourselves when automatic claim doesn't happen in 30 seconds
237
+ await swap.claim();
238
+ }
239
+ ```
240
+
241
+ ##### Swap states
242
+
243
+ - FromBTCSwapState.EXPIRED = -3
244
+ - Bitcoin swap address expired
245
+ - FromBTCSwapState.QUOTE_EXPIRED = -2
246
+ - Swap quote expired and cannot be executed anymore
247
+ - FromBTCSwapState.QUOTE_SOFT_EXPIRED = -1
248
+ - Swap quote soft-expired (i.e. the quote probably expired, but if there is already an initialization transaction sent it might still succeed)
249
+ - FromBTCSwapState.PR_CREATED = 0
250
+ - Swap quote is created, waiting for the user to open a bitcoin swap address
251
+ - FromBTCSwapState.CLAIM_COMMITED = 1
252
+ - Bitcoin swap address is opened
253
+ - FromBTCSwapState.BTC_TX_CONFIRMED = 2
254
+ - Bitcoin transaction sending funds to the swap address is confirmed
255
+ - FromBTCSwapState.CLAIM_CLAIMED = 3
256
+ - Swap funds are claimed to the user's wallet
257
+
258
+ ### Bitcoin lightning network swaps
259
+
260
+ #### Swap Smart chain -> Bitcoin lightning network
261
+
262
+ ```typescript
263
+ //Destination lightning network invoice, amount needs to be part of the invoice!
264
+ const _lightningInvoice = "lnbc10u1pj2q0g9pp5ejs6m677m39cznpzum7muruvh50ys93ln82p4j9ks2luqm56xxlshp52r2anlhddfa9ex9vpw9gstxujff8a0p8s3pzvua930js0kwfea6scqzzsxqyz5vqsp5073zskc5qfgp7lre0t6s8uexxxey80ax564hsjklfwfjq2ew0ewq9qyyssqvzmgs6f8mvuwgfa9uqxhtza07qem4yfhn9wwlpskccmuwplsqmh8pdy6c42kqdu8p73kky9lsnl40qha5396d8lpgn90y27ltfc5rfqqq59cya";
265
+
266
+ //Create the swap: swapping SOL to Bitcoin lightning
267
+ const swap = await solanaSwapper.create(
268
+ Tokens.SOLANA.SOL,
269
+ Tokens.BITCOIN.BTCLN,
270
+ null,
271
+ false,
272
+ _lightningInvoice
273
+ );
274
+
275
+ //Get the amount required to pay and fee
276
+ const amountToBePaid: string = swap.getInput().amount; //Human readable amount to be paid on the Solana side (including fee)
277
+ const fee: string = swap.getFee().amountInSrcToken.amount; //Human readable swap fee paid on the Solana side (already included in the the above amount)
278
+
279
+ //Get swap expiration time
280
+ const expiry: number = swap.getExpiry(); //Expiration time of the swap in UNIX milliseconds, swap needs to be initiated before this time
281
+
282
+ //Initiate and pay for the swap
283
+ await swap.commit();
284
+
285
+ //Wait for the swap to conclude
286
+ const result: boolean = await swap.waitForPayment();
287
+ if(!result) {
288
+ //Swap failed, money can be refunded
289
+ await swap.refund();
290
+ } else {
291
+ //Swap successful, we can get the lightning payment secret pre-image, which acts as a proof of payment
292
+ const lightningSecret = swap.getSecret();
293
+ }
294
+ ```
295
+
296
+ ##### Swap states
297
+
298
+ - ToBTCSwapState.REFUNDED = -3
299
+ - Swap failed and was successfully refunded
300
+ - ToBTCSwapState.QUOTE_EXPIRED = -2
301
+ - Swap quote expired and cannot be executed anymore
302
+ - ToBTCSwapState.QUOTE_SOFT_EXPIRED = -1
303
+ - Swap quote soft-expired (i.e. the quote probably expired, but if there is already an initialization transaction sent it might still succeed)
304
+ - ToBTCSwapState.CREATED = 0
305
+ - Swap quote is created, waiting to be executed
306
+ - ToBTCSwapState.COMMITED = 1,
307
+ - Swap was initiated (init transaction sent)
308
+ - ToBTCSwapState.SOFT_CLAIMED = 2,
309
+ - Swap was processed by the counterparty but not yet claimed on-chain (lightning network payment secret was revealed)
310
+ - ToBTCSwapState.CLAIMED = 3
311
+ - Swap was finished and funds were successfully claimed by the counterparty
312
+ - ToBTCSwapState.REFUNDABLE = 4
313
+ - Swap was initiated but counterparty failed to process it, the user can now refund his funds
314
+
315
+ #### Swap Bitcoin lightning network -> Smart chain
316
+ ```typescript
317
+ const _exactIn = true; //exactIn = true, so we specify the input amount
318
+ const _amount = 10000n; //Amount in BTC base units - sats
319
+
320
+ //Create the swap: swapping _amount of satoshis from Bitcoin lightning network to SOL
321
+ const swap = await solanaSwapper.create(
322
+ Tokens.BITCOIN.BTCLN,
323
+ Tokens.SOLANA.SOL,
324
+ _amount,
325
+ _exactIn
326
+ );
327
+
328
+ //Get the bitcoin lightning network invoice (the invoice contains pre-entered amount)
329
+ const receivingLightningInvoice: string = swap.getLightningInvoice();
330
+ //Get the QR code (contains the lightning network invoice)
331
+ const qrCodeData: string = swap.getQrData(); //Data that can be displayed in the form of QR code
332
+
333
+ //Get the amount required to pay, amount to be received and fee
334
+ const amountToBePaidOnBitcoin: string = swap.getInput().amount; //Human readable amount of BTC that needs to be send to the BTC swap address
335
+ const amountToBeReceivedOnSolana: string = swap.getOutput().amount; //Human readable amount SOL that will be received on Solana
336
+ const fee: string = swap.getFee().amountInSrcToken.amount; //Human readable fee in BTC
337
+
338
+ try {
339
+ //Wait for the lightning payment to arrive
340
+ await swap.waitForPayment();
341
+ //Claim the swap funds - this will initiate 2 transactions
342
+ await swap.commitAndClaim();
343
+ //Or for e.g. starknet which doesn't support signing 2 transactions at once
344
+ // await swap.commit();
345
+ // await swap.claim();
346
+ } catch(e) {
347
+ //Error occurred while waiting for payment
348
+ }
349
+ ```
350
+
351
+ ##### Swap states
352
+
353
+ - FromBTCLNSwapState.FAILED = -4
354
+ - If the claiming of the funds was initiated, but never concluded, the user will get his lightning network payment refunded
355
+ - FromBTCLNSwapState.QUOTE_EXPIRED = -3
356
+ - Swap quote expired and cannot be executed anymore
357
+ - FromBTCLNSwapState.QUOTE_SOFT_EXPIRED = -2
358
+ - Swap quote soft-expired (i.e. the quote probably expired, but if there is already an initialization transaction sent it might still succeed)
359
+ - FromBTCLNSwapState.EXPIRED = -1
360
+ - Lightning network invoice expired, meaning the swap is expired
361
+ - FromBTCLNSwapState.PR_CREATED = 0
362
+ - Swap is created, the user should now pay the provided lightning network invoice
363
+ - FromBTCLNSwapState.PR_PAID = 1
364
+ - Lightning network invoice payment was received (but cannot be settled by the counterparty yet)
365
+ - FromBTCLNSwapState.CLAIM_COMMITED = 2
366
+ - Claiming of the funds was initiated
367
+ - FromBTCLNSwapState.CLAIM_CLAIMED = 3
368
+ - Funds were successfully claimed & lightning network secret pre-image revealed, so the lightning network payment will settle now
369
+
370
+ ### Getting state of the swap
371
+
372
+ You can get the current state of the swap with:
373
+
374
+ ```typescript
375
+ const state = swap.getState();
376
+ ```
377
+
378
+ You can also set a listener to listen for swap state changes:
379
+
380
+ ```typescript
381
+ swap.events.on("swapState", swap => {
382
+ const newState = swap.getState();
383
+ });
384
+ ```
385
+
386
+ For the meaning of the states please refer to the "Swap state" section under each swap type.
387
+
388
+ ### LNURLs & readable lightning identifiers
389
+
390
+ LNURLs extend the lightning network functionality by creating static lightning addreses (LNURL-pay & static internet identifiers) and QR codes which allow you to pull funds from them (LNURL-withdraw)
391
+
392
+ This SDK supports:
393
+ * LNURL-pay ([LUD-6](https://github.com/lnurl/luds/blob/luds/06.md), [LUD-9](https://github.com/lnurl/luds/blob/luds/09.md), [LUD-10](https://github.com/lnurl/luds/blob/luds/10.md), [LUD-12](https://github.com/lnurl/luds/blob/luds/12.md))
394
+ * LNURL-withdraw ([LUD-3](https://github.com/lnurl/luds/blob/luds/03.md))
395
+ * Static internet identifiers ([LUD-16](https://github.com/lnurl/luds/blob/luds/16.md))
396
+
397
+ #### Differences
398
+
399
+ Lightning invoices:
400
+ * One time use only
401
+ * Need to have a fixed amount, therefore recipient has to set the amount
402
+ * Static and bounded expiration
403
+ * You can only pay to a lightning invoice, not withdraw funds from it
404
+
405
+ LNURLs & lightning identifiers:
406
+ * Reusable
407
+ * Programmable expiry
408
+ * Allows payer to set an amount
409
+ * Supports both, paying (LNURL-pay) and withdrawing (LNURL-withdraw)
410
+ * Possibility to attach a message/comment to a payment
411
+ * Receive a message/url as a result of the payment
412
+
413
+ #### Helpers
414
+
415
+ It is good practice to automatically distinguish between lightning network invoices & LNURLs and adjust the UI accordingly.
416
+ Therefore there are a few helper functions to help with that:
417
+ ```typescript
418
+ const isLNInvoice: boolean = swapper.isValidLightningInvoice(_input); //Checks if the input is lightning network invoice
419
+ const isLNURL: boolean = swapper.isValidLNURL(_input); //Checks if the input is LNURL or lightning identifier
420
+ if(isLNURL) {
421
+ //Get the type of the LNURL
422
+ const result: (LNURLPay | LNURLWithdraw | null) = await swapper.getLNURLTypeAndData(_input);
423
+ if(result.type==="pay") {
424
+ const lnurlPayData: LNURLPay = result;
425
+ const minPayable: bigint = lnurlPayData.min; //Minimum payment amount in satoshis
426
+ const maxPayable: bigint = lnurlPayData.max; //Maximum payment amount in satoshis
427
+ const icon: (string | null) = lnurlPayData.icon; //URL encoded icon that should be displayed on the UI
428
+ const shortDescription: (string | null) = lnurlPayData.shortDescription; //Short description of the payment
429
+ const longDescription: (string | null) = lnurlPayData.longDescription; //Long description of the payment
430
+ const maxCommentLength: (number | 0) = lnurlPayData.commentMaxLength; //Maximum allowed length of the payment message/comment (0 means no comment allowed)
431
+ //Should show a UI displaying the icon, short description, long description, allowing the user to choose an amount he wishes to pay and possibly also a comment
432
+ }
433
+ if(result.type==="withdraw") {
434
+ const lnurlWithdrawData: LNURLWithdraw = result;
435
+ const minWithdrawable: bigint = lnurlWithdrawData.min;
436
+ const maxWithdrawable: bigint = lnurlWithdrawData.max;
437
+ //Should show a UI allowing the user to choose an amount he wishes to withdraw
438
+ }
439
+ }
440
+ ```
441
+
442
+ #### Swap Smart chain -> Bitcoin lightning network
443
+ ```typescript
444
+ const _lnurlOrIdentifier: string = "lnurl1dp68gurn8ghj7ampd3kx2ar0veekzar0wd5xjtnrdakj7tnhv4kxctttdehhwm30d3h82unvwqhkx6rfvdjx2ctvxyesuk0a27"; //Destination LNURL-pay or readable identifier
445
+ const _exactIn = false; //exactIn = false, so we specify the output amount
446
+ const _amount: bigint = 10000n; //Amount of satoshis to send (1 BTC = 100 000 000 satoshis)
447
+
448
+ //Create the swap: swapping SOL to Bitcoin lightning
449
+ const swap = await solanaSwapper.create(
450
+ Tokens.SOLANA.SOL,
451
+ Tokens.BITCOIN.BTCLN,
452
+ _amount,
453
+ _exactIn,
454
+ _lnurlOrIdentifier
455
+ );
456
+
457
+ //Get the amount required to pay and fee
458
+ const amountToBePaid: string = swap.getInput().amount; //Human readable amount to be paid on the Solana side (including fee)
459
+ const fee: string = swap.getFee().amountInSrcToken.amount; //Human readable swap fee paid on the Solana side (already included in the the above amount)
460
+
461
+ //Get swap expiration time
462
+ const expiry: number = swap.getExpiry(); //Expiration time of the swap in UNIX milliseconds, swap needs to be initiated before this time
463
+
464
+ //Initiate and pay for the swap
465
+ await swap.commit();
466
+
467
+ //Wait for the swap to conclude
468
+ const result: boolean = await swap.waitForPayment();
469
+ if(!result) {
470
+ //Swap failed, money can be refunded
471
+ await swap.refund();
472
+ } else {
473
+ //Swap successful, we can get the lightning payment secret pre-image, which acts as a proof of payment
474
+ const lightningSecret = swap.getSecret();
475
+ //In case the LNURL contained a success action, we can read it now and display it to user
476
+ if(swap.hasSuccessAction()) {
477
+ //Contains a success action that should displayed to the user
478
+ const successMessage = swap.getSuccessAction();
479
+ const description: string = successMessage.description; //Description of the message
480
+ const text: (string | null) = successMessage.text; //Main text of the message
481
+ const url: (string | null) = successMessage.url; //URL link which should be displayed
482
+ }
483
+ }
484
+ ```
485
+
486
+ #### Swap Bitcoin lightning network -> Smart chain
487
+ ```typescript
488
+ const _lnurl: string = "lnurl1dp68gurn8ghj7ampd3kx2ar0veekzar0wd5xjtnrdakj7tnhv4kxctttdehhwm30d3h82unvwqhkx6rfvdjx2ctvxyesuk0a27"; //Destination LNURL-pay or readable identifier
489
+ const _exactIn = true; //exactIn = true, so we specify the input amount
490
+ const _amount = 10000n; //Amount in BTC base units - sats
491
+
492
+ //Create the swap: swapping _amount of satoshis from Bitcoin lightning network to SOL
493
+ const swap = await solanaSwapper.create(
494
+ Tokens.BITCOIN.BTCLN,
495
+ Tokens.SOLANA.SOL,
496
+ _amount,
497
+ _exactIn,
498
+ _lnurl
499
+ );
500
+
501
+ //Get the amount of BTC to be withdrawn from LNURL, amount to be received and fee
502
+ const amountToBeWithdrawnOnBitcoin: string = swap.getInput().amount; //Human readable amount of BTC that will be withdrawn from the LNURL
503
+ const amountToBeReceivedOnSolana: string = swap.getOutput().amount; //Human readable amount SOL that will be received on Solana
504
+ const fee: string = swap.getFee().amountInSrcToken.amount; //Human readable fee in BTC
505
+
506
+ try {
507
+ //Submit the withdraw request & wait for the payment to arrive
508
+ await swap.waitForPayment();
509
+ //Claim the swap funds - this will initiate 2 transactions
510
+ await swap.commitAndClaim();
511
+ //Or for e.g. starknet which doesn't support signing 2 transactions at once
512
+ // await swap.commit();
513
+ // await swap.claim();
514
+ } catch(e) {
515
+ //Error occurred while waiting for payment
516
+ }
517
+ ```
518
+
519
+ ### Get refundable swaps
520
+ You can refund the swaps in one of two cases:
521
+ * In case intermediary is non-cooperative and goes offline, you can claim the funds from the swap contract back after some time.
522
+ * In case intermediary tried to pay but was unsuccessful, so he sent you signed message with which you can refund now without waiting.
523
+
524
+ This call can be checked on every startup and periodically every few minutes.
525
+ ```typescript
526
+ //Get the swaps
527
+ const refundableSwaps = await solanaSwapper.getRefundableSwaps();
528
+ //Refund all the swaps
529
+ for(let swap of refundableSwaps) {
530
+ await swap.refund();
531
+ }
532
+ ```
533
+
534
+ ### Get claimable swaps
535
+ Returns swaps that are ready to be claimed by the client, this can happen if client closes the application when a swap is in-progress and the swap is concluded while the client is offline.
536
+
537
+ ```typescript
538
+ //Get the swaps
539
+ const claimableSwaps = await solanaSwapper.getClaimableSwaps();
540
+ //Claim all the claimable swaps
541
+ for(let swap of claimableSwaps) {
542
+ if(swap.canCommit()) await swap.commit(); //This is for Bitcoin (lightning) -> Smart chain swaps, where commit & claim procedure might be needed
543
+ await swap.claim();
544
+ }
545
+ ```