@atomiqlabs/sdk 4.0.0-beta.4 → 4.0.1

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/README.md CHANGED
@@ -2,6 +2,8 @@
2
2
 
3
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
4
 
5
+ Example SDK integration in NodeJS available [here](https://github.com/atomiqlabs/atomiq-sdk-demo/blob/main/src/index.ts)
6
+
5
7
  ## Installation
6
8
  ```
7
9
  npm install @atomiqlabs/sdk
@@ -18,6 +20,28 @@ npm install @atomiqlabs/chain-starknet
18
20
 
19
21
  ## How to use?
20
22
 
23
+ - [Preparations](#preparations)
24
+ - [Setting up signers](#signer)
25
+ - [Initialization](#initialization)
26
+ - Swaps:
27
+ - [Smart Chain -> BTC L1](#swap-smart-chain---bitcoin-on-chain)
28
+ - [BTC L1 -> Solana (Old swap protocol)](#swap-bitcoin-on-chain---solana)
29
+ - [BTC L1 -> Starknet (New swap protocol)](#swap-bitcoin-on-chain---starknet)
30
+ - [Smart Chain -> BTC Lightning network L2](#swap-smart-chain---bitcoin-lightning-network)
31
+ - [Smart Chain -> BTC Lightning network L2 (LNURL-pay)](#swap-smart-chain---bitcoin-lightning-network-1)
32
+ - [BTC Lightning network L2 -> Smart Chain](#swap-bitcoin-lightning-network---smart-chain)
33
+ - [BTC Lightning network L2 (LNURL-withdraw) -> Smart Chain](#swap-bitcoin-lightning-network---smart-chain-1)
34
+ - [Swap states](#getting-state-of-the-swap)
35
+ - [Swap size limits](#swap-size-limits)
36
+ - [Stored swaps](#stored-swaps)
37
+ - [Get existing swaps](#get-swap-by-id)
38
+ - [Refundable swaps](#get-refundable-swaps)
39
+ - [Claimable swaps](#get-claimable-swaps)
40
+ - [Helpers](#helpers)
41
+ - [Wallet spendable balance](#getting-wallet-balances)
42
+ - [Unified address parsers](#unified-address-parser)
43
+ - [Customize swapper instance](#additional-swapper-options)
44
+
21
45
  ### Preparations
22
46
 
23
47
  Set Solana & Starknet RPC URL to use
@@ -30,6 +54,10 @@ const starknetRpc = "https://starknet-mainnet.public.blastapi.io/rpc/v0_7";
30
54
  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
55
 
32
56
  ```typescript
57
+ import {SolanaInitializer, SolanaInitializerType} from "@atomiqlabs/chain-solana";
58
+ import {StarknetInitializer, StarknetInitializerType} from "@atomiqlabs/chain-starknet";
59
+ import {SwapperFactory} from "@atomiqlabs/sdk";
60
+
33
61
  const Factory = new SwapperFactory<[SolanaInitializerType, StarknetInitializerType]>([SolanaInitializer, StarknetInitializer] as const);
34
62
  const Tokens = Factory.Tokens; //Get the supported tokens for all the specified chains.
35
63
  ```
@@ -39,6 +67,8 @@ const Tokens = Factory.Tokens; //Get the supported tokens for all the specified
39
67
  This uses browser's Indexed DB by default
40
68
 
41
69
  ```typescript
70
+ import {BitcoinNetwork} from "@atomiqlabs/sdk";
71
+
42
72
  const swapper = Factory.newSwapper({
43
73
  chains: {
44
74
  SOLANA: {
@@ -52,11 +82,22 @@ const swapper = Factory.newSwapper({
52
82
  });
53
83
  ```
54
84
 
85
+ if you want to use custom pricing api, mempool.space RPC url, or tune HTTP request timeouts check out [additional options](#additional-swapper-options)
86
+
55
87
  #### NodeJS
56
88
 
57
- For NodeJS we need to explicitly use filesystem storage
89
+ For NodeJS we need to use sqlite storage, for that we first need to install the sqlite storage adaptor
90
+
91
+ ```
92
+ npm install @atomiqlabs/storage-sqlite
93
+ ```
94
+
95
+ Then use pass it in the newSwapper function
58
96
 
59
97
  ```typescript
98
+ import {SqliteStorageManager, SqliteUnifiedStorage} from "@atomiqlabs/storage-sqlite";
99
+ import {BitcoinNetwork} from "@atomiqlabs/sdk";
100
+
60
101
  const swapper = Factory.newSwapper({
61
102
  chains: {
62
103
  SOLANA: {
@@ -67,21 +108,27 @@ const swapper = Factory.newSwapper({
67
108
  }
68
109
  },
69
110
  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,
111
+ //The following lines are important for running on backend node.js,
71
112
  // because the SDK by default uses browser's Indexed DB
72
- storageCtor: (name: string) => new FileSystemStorageManager(name)
113
+ swapStorage: chainId => new SqliteUnifiedStorage("CHAIN_"+chainId+".sqlite3"),
114
+ chainStorageCtor: name => new SqliteStorageManager("STORE_"+name+".sqlite3"),
73
115
  });
74
116
  ```
75
117
 
118
+ if you want to use custom pricing api, mempool.space RPC url, or tune HTTP request timeouts check out [additional options](#additional-swapper-options)
119
+
76
120
  ### Signer
77
121
 
78
122
  ```typescript
79
- //React, using solana wallet adapter
123
+ import {SolanaSigner} from "@atomiqlabs/chain-solana";
124
+ //Browser - react, using solana wallet adapter
80
125
  const anchorWallet = useAnchorWallet();
81
126
  const wallet = new SolanaSigner(anchorWallet);
82
127
  ```
83
128
 
84
129
  ```typescript
130
+ import {WalletAccount} from "starknet";
131
+ import {StarknetSigner} from "@atomiqlabs/chain-starknet";
85
132
  //Browser, using get-starknet
86
133
  const swo = await connect();
87
134
  const wallet = new StarknetSigner(new WalletAccount(starknetRpc, swo.wallet));
@@ -90,8 +137,16 @@ const wallet = new StarknetSigner(new WalletAccount(starknetRpc, swo.wallet));
90
137
  or
91
138
 
92
139
  ```typescript
93
- //Creating a random signer
94
- const wallet = swapper.randomSigner<"SOLANA">("SOLANA");
140
+ import {Keypair} from "@solana/web3.js";
141
+ import {SolanaKeypairWallet, SolanaSigner} from "@atomiqlabs/chain-solana";
142
+ //Creating Solana signer from private key
143
+ const solanaSigner = new SolanaSigner(new SolanaKeypairWallet(Keypair.fromSecretKey(solanaKey)), Keypair.fromSecretKey(solanaKey));
144
+ ```
145
+
146
+ ```typescript
147
+ import {SolanaKeypairWallet, SolanaSigner} from "@atomiqlabs/chain-solana";
148
+ //Creating Starknet signer from private key
149
+ const starknetSigner = new StarknetSigner(new StarknetKeypairWallet(starknetRpc, starknetKey));
95
150
  ```
96
151
 
97
152
  ### Initialization
@@ -106,42 +161,67 @@ Now we have the multichain swapper initialized
106
161
 
107
162
  ### Extract chain-specific swapper with signer
108
163
 
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.
164
+ 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. e.g.:
165
+
166
+ ```typescript
167
+ const solanaSwapper = swapper.withChain<"SOLANA">("SOLANA");
168
+ ```
169
+
170
+ or also with signer
110
171
 
111
172
  ```typescript
112
- const solanaSwapper = swapper.withChain<"SOLANA">("SOLANA").withSigner(signer);
173
+ const starknetSwapperWithSigner = swapper.withChain<"STARKNET">("STARKNET").withSigner(signer);
113
174
  ```
114
175
 
115
176
  ### Bitcoin on-chain swaps
116
177
 
117
178
  #### Swap Smart chain -> Bitcoin on-chain
118
179
 
119
- Initiating & executing the swap.
180
+ Getting swap quote
120
181
 
121
182
  ```typescript
122
183
  const _exactIn = false; //exactIn = false, so we specify the output amount
123
- const _amount = 10000n; //Amount in BTC base units - sats
184
+ const _amount = 10000n; //Amount in BTC base units - sats (10000 sats = 0.0001 BTC)
124
185
  const _address = "bc1qtw67hj77rt8zrkkg3jgngutu0yfgt9czjwusxt"; //BTC address of the recipient
125
186
 
126
187
  //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,
188
+ const swap = await swapper.swap(
189
+ Tokens.SOLANA.SOL, //From specified source token
190
+ Tokens.BITCOIN.BTC, //Swap to BTC
130
191
  _amount,
131
192
  _exactIn,
132
- _address
193
+ solanaSigner.getAddress(), //Source address and smart chain signer
194
+ _address //Destination of the swap
133
195
  );
134
196
 
135
197
  //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)
198
+ const input: string = swap.getInputWithoutFee().toString(); //Input amount excluding fees
199
+ const fee: string = swap.getFee().amountInSrcToken.toString(); //Fees paid on the output
200
+ const inputWithFees: string = swap.getInput().toString(); //Total amount paid including fees
201
+
202
+ const output: string = swap.getOutput().toString(); //Total output amount
138
203
 
139
204
  //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
205
+ const expiry: number = swap.getQuoteExpiry(); //Expiration time of the swap quote in UNIX milliseconds, swap needs to be initiated before this time
206
+
207
+ //Get pricing info
208
+ const swapPrice = swap.getPriceInfo().swapPrice; //Price of the current swap (excluding fees)
209
+ const marketPrice = swap.getPriceInfo().marketPrice; //Current market price
210
+ const difference = swap.getPriceInfo().difference; //Difference between the swap price & current market price
211
+ ```
212
+
213
+ Initiating the swap
141
214
 
215
+ ```typescript
142
216
  //Initiate and pay for the swap
143
- await swap.commit();
217
+ await swap.commit(solanaSigner);
218
+ ```
219
+
220
+ or [sign and send transaction manually](#manually-signing-smart-chain-transactions)
221
+
222
+ Wait for the swap to execute, refund in case of failure
144
223
 
224
+ ```typescript
145
225
  //Wait for the swap to conclude
146
226
  const result: boolean = await swap.waitForPayment();
147
227
  if(!result) {
@@ -172,48 +252,83 @@ if(!result) {
172
252
  - ToBTCSwapState.REFUNDABLE = 4
173
253
  - Swap was initiated but counterparty failed to process it, the user can now refund his funds
174
254
 
175
- #### Swap Bitcoin on-chain -> Smart chain
255
+ #### Swap Bitcoin on-chain -> Solana
256
+
257
+ NOTE: Solana uses an old swap protocol for Bitcoin on-chain -> Solana swaps, the flow here is different from the one for Starknet and other chains.
176
258
 
177
- Initiating & executing the swap.
259
+ Getting swap quote
178
260
 
179
261
  ```typescript
180
262
  const _exactIn = true; //exactIn = true, so we specify the input amount
181
263
  const _amount = fromHumanReadableString("0.0001", Tokens.BITCOIN.BTC); //Amount in BTC base units - sats, we can also use a utility function here
182
264
 
183
265
  //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,
266
+ const swap = await swapper.swap(
267
+ Tokens.BITCOIN.BTC, //Swap from BTC
268
+ Tokens.SOLANA.SOL, //Into specified destination token
187
269
  _amount,
188
- _exactIn
270
+ _exactIn, //Whether we define an input or output amount
271
+ undefined, //Source address for the swap, not used for swaps from BTC
272
+ solanaSigner.getAddress() //Destination address
189
273
  );
190
274
 
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
275
+ //Get the amount required to pay and fee
276
+ const input: string = swap.getInputWithoutFee().toString(); //Input amount excluding fees
277
+ const fee: string = swap.getFee().amountInSrcToken.toString(); //Fees paid on the output
278
+ const inputWithFees: string = swap.getInput().toString(); //Total amount paid including fees
195
279
 
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
280
+ const output: string = swap.getOutput().toString(); //Total output amount
281
+
282
+ //Get swap expiration time
283
+ const expiry: number = swap.getQuoteExpiry(); //Expiration time of the swap quote in UNIX milliseconds, swap needs to be initiated before this time
198
284
 
199
285
  //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;
286
+ const securityDeposit: string = swap.getSecurityDeposit().toString();
201
287
  //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;
288
+ const claimerBounty: string = swap.getClaimerBounty().toString();
203
289
 
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();
290
+ //Get pricing info
291
+ const swapPrice = swap.getPriceInfo().swapPrice; //Price of the current swap (excluding fees)
292
+ const marketPrice = swap.getPriceInfo().marketPrice; //Current market price
293
+ const difference = swap.getPriceInfo().difference; //Difference between the swap price & current market price
294
+ ```
295
+
296
+ Initiating the swap
206
297
 
298
+ ```typescript
299
+ //Initiate the swap on the destination chain (Solana) by opening up the bitcoin swap address
300
+ await swap.commit(solanaSigner);
301
+ ```
302
+
303
+ or [sign and send transaction manually](#manually-signing-smart-chain-transactions)
304
+
305
+ Sending bitcoin
306
+
307
+ ```typescript
207
308
  //Get the bitcoin address
208
309
  const receivingAddressOnBitcoin = swap.getAddress();
209
310
  //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();
311
+ const qrCodeData = swap.getHyperlink(); //Data that can be displayed in the form of QR code
312
+ //Send the exact amount of BTC to the provided address
313
+ ```
314
+
315
+ or get a psbt and sign it
316
+
317
+ ```typescript
318
+ //Or obtain the funded PSBT (input already added) - ready for signing
319
+ const {psbt, signInputs} = await swap.getFundedPsbt({address: "", publicKey: ""});
320
+ for(let signIdx of signInputs) {
321
+ psbt.signIdx(..., signIdx); //Or pass it to external signer
322
+ }
323
+ const bitcoinTxId = await swap.submitPsbt(psbt);
324
+ ```
325
+
326
+ Waiting for swap execution
213
327
 
328
+ ```typescript
214
329
  try {
215
330
  //Wait for the payment to arrive
216
- await swap.waitForPayment(
331
+ await swap.waitForBitcoinTransaction(
217
332
  null, null,
218
333
  (
219
334
  txId: string, //Transaction ID of the received bitcoin transaction
@@ -231,10 +346,10 @@ try {
231
346
 
232
347
  //Swap should get automatically claimed by the watchtowers, if not we can call swap.claim() ourselves
233
348
  try {
234
- await swap.waitTillClaimed(timeoutSignal(30*1000));
349
+ await swap.waitTillClaimed(timeoutSignal(30*1000));
235
350
  } catch (e) {
236
- //Claim ourselves when automatic claim doesn't happen in 30 seconds
237
- await swap.claim();
351
+ //Claim ourselves when automatic claim doesn't happen in 30 seconds
352
+ await swap.claim(solanaSigner);
238
353
  }
239
354
  ```
240
355
 
@@ -255,41 +370,184 @@ try {
255
370
  - FromBTCSwapState.CLAIM_CLAIMED = 3
256
371
  - Swap funds are claimed to the user's wallet
257
372
 
373
+
374
+ #### Swap Bitcoin on-chain -> Starknet
375
+
376
+ NOTE: Starknet uses a new swap protocol for Bitcoin on-chain -> Solana swaps, the flow here is different from the one for Solana!
377
+
378
+ Getting swap quote
379
+
380
+ ```typescript
381
+ const _exactIn = true; //exactIn = true, so we specify the input amount
382
+ const _amount = fromHumanReadableString("0.0001", Tokens.BITCOIN.BTC); //Amount in BTC base units - sats, we can also use a utility function here
383
+
384
+ //Create the swap: swapping _amount of satoshis of Bitcoin on-chain to SOL
385
+ const swap = await swapper.swap(
386
+ Tokens.BITCOIN.BTC, //Swap from BTC
387
+ Tokens.STARKNET.STRK, //Into specified destination token
388
+ _amount,
389
+ _exactIn, //Whether we define an input or output amount
390
+ undefined, //Source address for the swap, not used for swaps from BTC
391
+ starknetSigner.getAddress(), //Destination address
392
+ {
393
+ gasAmount: 1_000_000_000_000_000_000n //We can also request a gas drop on the destination chain (here requesting 1 STRK)
394
+ }
395
+ );
396
+
397
+ //Get the amount required to pay and fee
398
+ const input: string = swap.getInputWithoutFee().toString(); //Input amount excluding fees
399
+ const fee: string = swap.getFee().amountInSrcToken.toString(); //Fees paid on the output
400
+ const inputWithFees: string = swap.getInput().toString(); //Total amount paid including fees
401
+
402
+ const output: string = swap.getOutput().toString(); //Total output amount
403
+
404
+ //Get swap expiration time
405
+ const expiry: number = swap.getQuoteExpiry(); //Expiration time of the swap quote in UNIX milliseconds, swap needs to be initiated before this time
406
+
407
+ //Get pricing info
408
+ const swapPrice = swap.getPriceInfo().swapPrice; //Price of the current swap (excluding fees)
409
+ const marketPrice = swap.getPriceInfo().marketPrice; //Current market price
410
+ const difference = swap.getPriceInfo().difference; //Difference between the swap price & current market price
411
+ ```
412
+
413
+ Initiating the swap
414
+
415
+ ```typescript
416
+ //Obtain the funded PSBT (input already added) - ready for signing
417
+ const {psbt, signInputs} = await swap.getFundedPsbt({address: "", publicKey: ""});
418
+ for(let signIdx of signInputs) {
419
+ psbt.signIdx(..., signIdx); //Or pass it to external signer
420
+ }
421
+ const bitcoinTxId = await swap.submitPsbt(psbt);
422
+ ```
423
+
424
+ or get raw PSBT and add inputs manually
425
+
426
+ ```typescript
427
+ //Or obtain raw PSBT to which inputs still need to be added
428
+ const {psbt, in1sequence} = await swap.getPsbt();
429
+ psbt.addInput(...);
430
+ //Make sure the second input's sequence (index 1) is as specified in the in1sequence variable
431
+ psbt.updateInput(1, {sequence: in1sequence});
432
+ //Sign the PSBT, sign every input except the first one
433
+ for(let i=1;i<psbt.inputsLength; i++) psbt.signIdx(..., i); //Or pass it to external signer
434
+ //Submit the signed PSBT
435
+ const bitcoinTxId = await swap.submitPsbt(psbt);
436
+ ```
437
+
438
+ Waiting for swap execution
439
+
440
+ ```typescript
441
+ try {
442
+ //Wait for the payment to arrive
443
+ await swap.waitForBitcoinTransaction(
444
+ null, null,
445
+ (
446
+ txId: string, //Transaction ID of the received bitcoin transaction
447
+ confirmations: number, //Current confirmations of the transaction
448
+ targetConfirmations: number, //Required confirmations
449
+ transactionETAms: number //Estimated in time (in milliseconds) until when the transaction will receive required amount of confirmations
450
+ ) => {
451
+ //Callback for transaction updates
452
+ }
453
+ );
454
+ } catch(e) {
455
+ //Error occurred while waiting for payment, this is most likely due to network errors
456
+ return;
457
+ }
458
+
459
+ //Swap should get automatically claimed by the watchtowers, if not we can call swap.claim() ourselves
460
+ try {
461
+ await swap.waitTillClaimedOrFronted(timeoutSignal(30*1000));
462
+ } catch (e) {
463
+ //Claim ourselves when automatic claim doesn't happen in 30 seconds
464
+ await swap.claim(starknetSigner);
465
+ }
466
+ ```
467
+
468
+ ##### Swap states
469
+
470
+ - SpvFromBTCSwapState.CLOSED = -5
471
+ - Catastrophic failure during swap, shall never happen
472
+ - SpvFromBTCSwapState.FAILED = -4
473
+ - Bitcoin transaction was sent, but was double-spent later, therefore the swap was failed (no BTC was sent)
474
+ - SpvFromBTCSwapState.DECLINED = -3
475
+ - LP declined to process the swap transaction, no BTC was sent
476
+ - SpvFromBTCSwapState.QUOTE_EXPIRED = -2
477
+ - Swap quote expired and cannot be executed anymore
478
+ - SpvFromBTCSwapState.QUOTE_SOFT_EXPIRED = -1
479
+ - Swap quote soft-expired (i.e. the quote probably expired, but if there is a bitcoin transaction being submitted it might still succeed)
480
+ - SpvFromBTCSwapState.CREATED = 0
481
+ - Swap quote is created, waiting on user to sign the bitcoin swap transaction
482
+ - SpvFromBTCSwapState.SIGNED = 1
483
+ - Bitcoin swap transaction was signed by the client
484
+ - SpvFromBTCSwapState.POSTED = 2
485
+ - Bitcoin swap transaction was posted to the LP
486
+ - SpvFromBTCSwapState.BROADCASTED = 3
487
+ - LP broadcasted the bitcoin swap transaction
488
+ - SpvFromBTCSwapState.FRONTED = 4
489
+ - Swap funds have been deposited to the user's wallet in front of the time
490
+ - SpvFromBTCSwapState.BTC_TX_CONFIRMED = 5
491
+ - Bitcoin swap transaction is confirmed
492
+ - SpvFromBTCSwapState.CLAIM_CLAIMED = 6
493
+ - Swap funds are claimed to the user's wallet
494
+
258
495
  ### Bitcoin lightning network swaps
259
496
 
260
497
  #### Swap Smart chain -> Bitcoin lightning network
261
498
 
499
+ Getting swap quote
500
+
262
501
  ```typescript
263
502
  //Destination lightning network invoice, amount needs to be part of the invoice!
264
503
  const _lightningInvoice = "lnbc10u1pj2q0g9pp5ejs6m677m39cznpzum7muruvh50ys93ln82p4j9ks2luqm56xxlshp52r2anlhddfa9ex9vpw9gstxujff8a0p8s3pzvua930js0kwfea6scqzzsxqyz5vqsp5073zskc5qfgp7lre0t6s8uexxxey80ax564hsjklfwfjq2ew0ewq9qyyssqvzmgs6f8mvuwgfa9uqxhtza07qem4yfhn9wwlpskccmuwplsqmh8pdy6c42kqdu8p73kky9lsnl40qha5396d8lpgn90y27ltfc5rfqqq59cya";
265
504
 
266
505
  //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
506
+ const swap = await swapper.swap(
507
+ Tokens.SOLANA.SOL, //From specified source token
508
+ Tokens.BITCOIN.BTCLN, //Swap to BTC-LN
509
+ undefined, //Amount is specified in the lightning network invoice!
510
+ false, //Make sure we use exactIn=false for swaps to BTC-LN, if you want to use exactIn=true and set an amount, use LNURL-pay!
511
+ solanaSigner.getAddress(), //Source address and smart chain signer
512
+ _lightningInvoice //Destination of the swap
273
513
  );
274
514
 
275
515
  //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)
516
+ const input: string = swap.getInputWithoutFee().toString(); //Input amount excluding fees
517
+ const fee: string = swap.getFee().amountInSrcToken.toString(); //Fees paid on the output
518
+ const inputWithFees: string = swap.getInput().toString(); //Total amount paid including fees
519
+
520
+ const output: string = swap.getOutput().toString(); //Total output amount
278
521
 
279
522
  //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
523
+ const expiry: number = swap.getQuoteExpiry(); //Expiration time of the swap quote in UNIX milliseconds, swap needs to be initiated before this time
524
+
525
+ //Get pricing info
526
+ const swapPrice = swap.getPriceInfo().swapPrice; //Price of the current swap (excluding fees)
527
+ const marketPrice = swap.getPriceInfo().marketPrice; //Current market price
528
+ const difference = swap.getPriceInfo().difference; //Difference between the swap price & current market price
529
+ ```
281
530
 
531
+ Initiating the swap
532
+
533
+ ```typescript
282
534
  //Initiate and pay for the swap
283
- await swap.commit();
535
+ await swap.commit(solanaSigner);
536
+ ```
537
+
538
+ or [sign and send transaction manually](#manually-signing-smart-chain-transactions)
284
539
 
540
+ Wait for the swap to execute, refund in case of failure
541
+
542
+ ```typescript
285
543
  //Wait for the swap to conclude
286
544
  const result: boolean = await swap.waitForPayment();
287
545
  if(!result) {
288
- //Swap failed, money can be refunded
289
- await swap.refund();
546
+ //Swap failed, money can be refunded
547
+ await swap.refund(solanaSigner);
290
548
  } 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();
549
+ //Swap successful, we can get the lightning payment secret pre-image, which acts as a proof of payment
550
+ const lightningSecret = swap.getSecret();
293
551
  }
294
552
  ```
295
553
 
@@ -313,41 +571,79 @@ if(!result) {
313
571
  - Swap was initiated but counterparty failed to process it, the user can now refund his funds
314
572
 
315
573
  #### Swap Bitcoin lightning network -> Smart chain
574
+
575
+ Getting swap quote
576
+
316
577
  ```typescript
317
578
  const _exactIn = true; //exactIn = true, so we specify the input amount
318
579
  const _amount = 10000n; //Amount in BTC base units - sats
319
580
 
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,
581
+ const swap = await swapper.swap(
582
+ Tokens.BITCOIN.BTCLN, //Swap from BTC-LN
583
+ Tokens.STARKNET.STRK, //Into specified destination token
324
584
  _amount,
325
- _exactIn
585
+ _exactIn, //Whether we define an input or output amount
586
+ undefined, //Source address for the swap, not used for swaps from BTC-LN
587
+ signer.getAddress() //Destination address
326
588
  );
327
589
 
328
590
  //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
591
+ const receivingLightningInvoice: string = swap.getAddress();
592
+ //Get the URI hyperlink (contains the lightning network invoice) which can be displayed also as QR code
593
+ const qrCodeData: string = swap.getHyperlink();
594
+
595
+ //Get the amount required to pay and fee
596
+ const input: string = swap.getInputWithoutFee().toString(); //Input amount excluding fees
597
+ const fee: string = swap.getFee().amountInSrcToken.toString(); //Fees paid on the output
598
+ const inputWithFees: string = swap.getInput().toString(); //Total amount paid including fees
332
599
 
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
600
+ const output: string = swap.getOutput().toString(); //Total output amount
337
601
 
602
+ //Get swap expiration time
603
+ const expiry: number = swap.getQuoteExpiry(); //Expiration time of the swap quote in UNIX milliseconds, swap needs to be initiated before this time
604
+
605
+ //Get security deposit amount (Human readable amount of STRK that needs to be put down to rent the liquidity from swap intermediary), you will get this deposit back if the swap succeeds
606
+ const securityDeposit: string = swap.getSecurityDeposit().toString();
607
+
608
+ //Get pricing info
609
+ const swapPrice = swap.getPriceInfo().swapPrice; //Price of the current swap (excluding fees)
610
+ const marketPrice = swap.getPriceInfo().marketPrice; //Current market price
611
+ const difference = swap.getPriceInfo().difference; //Difference between the swap price & current market price
612
+ ```
613
+
614
+ Pay the displayed lightning network invoice from an external wallet
615
+
616
+ Wait for the payment to be received
617
+
618
+ ```typescript
619
+ //Start listening to incoming lightning network payment
620
+ const success = await swap.waitForPayment();
621
+ if(!success) {
622
+ //Lightning network payment not received in time and quote expired!
623
+ return;
624
+ }
625
+ ```
626
+
627
+ Claim the funds on the destination smart chains, this settles the swap and lightning network payment
628
+
629
+ ```typescript
338
630
  try {
339
- //Wait for the lightning payment to arrive
340
- await swap.waitForPayment();
341
631
  //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();
632
+ if(swap.canCommitAndClaimInOneShot()) {
633
+ //Some chains (e.g. Solana) support signing multiple transactions in one flow
634
+ await swap.commitAndClaim(solanaSigner);
635
+ } else {
636
+ //Other chains (e.g. Starknet) don't support signing multiple transaction in one flow, therefore you need to sign one-by-one
637
+ await swap.commit(starknetSigner);
638
+ await swap.claim(starknetSigner);
639
+ }
346
640
  } catch(e) {
347
641
  //Error occurred while waiting for payment
348
642
  }
349
643
  ```
350
644
 
645
+ or [sign and send transactions manually](#manually-signing-smart-chain-transactions)
646
+
351
647
  ##### Swap states
352
648
 
353
649
  - FromBTCLNSwapState.FAILED = -4
@@ -367,24 +663,6 @@ try {
367
663
  - FromBTCLNSwapState.CLAIM_CLAIMED = 3
368
664
  - Funds were successfully claimed & lightning network secret pre-image revealed, so the lightning network payment will settle now
369
665
 
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
666
  ### LNURLs & readable lightning identifiers
389
667
 
390
668
  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)
@@ -394,6 +672,8 @@ This SDK supports:
394
672
  * LNURL-withdraw ([LUD-3](https://github.com/lnurl/luds/blob/luds/03.md))
395
673
  * Static internet identifiers ([LUD-16](https://github.com/lnurl/luds/blob/luds/16.md))
396
674
 
675
+ You can parse LNURLs and lightning invoices automatically using the [Unified address parser](#unified-address-parser)
676
+
397
677
  #### Differences
398
678
 
399
679
  Lightning invoices:
@@ -410,136 +690,385 @@ LNURLs & lightning identifiers:
410
690
  * Possibility to attach a message/comment to a payment
411
691
  * Receive a message/url as a result of the payment
412
692
 
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
693
  #### Swap Smart chain -> Bitcoin lightning network
694
+
695
+ Getting swap quote
696
+
443
697
  ```typescript
444
698
  const _lnurlOrIdentifier: string = "lnurl1dp68gurn8ghj7ampd3kx2ar0veekzar0wd5xjtnrdakj7tnhv4kxctttdehhwm30d3h82unvwqhkx6rfvdjx2ctvxyesuk0a27"; //Destination LNURL-pay or readable identifier
445
699
  const _exactIn = false; //exactIn = false, so we specify the output amount
446
700
  const _amount: bigint = 10000n; //Amount of satoshis to send (1 BTC = 100 000 000 satoshis)
447
701
 
448
702
  //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
703
+ const swap = await swapper.swap(
704
+ Tokens.SOLANA.SOL, //From specified source token
705
+ Tokens.BITCOIN.BTCLN, //Swap to BTC-LN
706
+ _amount, //Now we can specify an amount for a lightning network payment!
707
+ _exactIn, //We can also use exactIn=true here and set an amount in input token
708
+ solanaSigner.getAddress(), //Source address and smart chain signer
709
+ _lnurlOrIdentifier, //Destination of the swap
710
+ {
711
+ comment: "Hello world" //For LNURL-pay we can also pass a comment to the recipient
712
+ }
455
713
  );
456
714
 
457
715
  //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)
716
+ const input: string = swap.getInputWithoutFee().toString(); //Input amount excluding fees
717
+ const fee: string = swap.getFee().amountInSrcToken.toString(); //Fees paid on the output
718
+ const inputWithFees: string = swap.getInput().toString(); //Total amount paid including fees
719
+
720
+ const output: string = swap.getOutput().toString(); //Total output amount
460
721
 
461
722
  //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
723
+ const expiry: number = swap.getQuoteExpiry(); //Expiration time of the swap quote in UNIX milliseconds, swap needs to be initiated before this time
724
+
725
+ //Get pricing info
726
+ const swapPrice = swap.getPriceInfo().swapPrice; //Price of the current swap (excluding fees)
727
+ const marketPrice = swap.getPriceInfo().marketPrice; //Current market price
728
+ const difference = swap.getPriceInfo().difference; //Difference between the swap price & current market price
729
+ ```
463
730
 
731
+ Initiating the swap
732
+
733
+ ```typescript
464
734
  //Initiate and pay for the swap
465
- await swap.commit();
735
+ await swap.commit(solanaSigner);
736
+ ```
737
+
738
+ or [sign and send transaction manually](#manually-signing-smart-chain-transactions)
466
739
 
740
+ Wait for the swap to execute, refund in case of failure
741
+
742
+ ```typescript
467
743
  //Wait for the swap to conclude
468
744
  const result: boolean = await swap.waitForPayment();
469
745
  if(!result) {
470
- //Swap failed, money can be refunded
471
- await swap.refund();
746
+ //Swap failed, money can be refunded
747
+ await swap.refund(solanaSigner);
472
748
  } 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
- }
749
+ //Swap successful, we can get the lightning payment secret pre-image, which acts as a proof of payment
750
+ const lightningSecret = swap.getSecret();
751
+ //In case the LNURL contained a success action, we can read it now and display it to user
752
+ if(swap.hasSuccessAction()) {
753
+ //Contains a success action that should displayed to the user
754
+ const successMessage = swap.getSuccessAction();
755
+ const description: string = successMessage.description; //Description of the message
756
+ const text: (string | null) = successMessage.text; //Main text of the message
757
+ const url: (string | null) = successMessage.url; //URL link which should be displayed
758
+ }
483
759
  }
484
760
  ```
485
761
 
486
762
  #### Swap Bitcoin lightning network -> Smart chain
763
+
764
+ Getting swap quote
765
+
487
766
  ```typescript
488
767
  const _lnurl: string = "lnurl1dp68gurn8ghj7ampd3kx2ar0veekzar0wd5xjtnrdakj7tnhv4kxctttdehhwm30d3h82unvwqhkx6rfvdjx2ctvxyesuk0a27"; //Destination LNURL-pay or readable identifier
489
768
  const _exactIn = true; //exactIn = true, so we specify the input amount
490
769
  const _amount = 10000n; //Amount in BTC base units - sats
491
770
 
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,
771
+ const swap = await swapper.swap(
772
+ Tokens.BITCOIN.BTCLN, //Swap from BTC-LN
773
+ Tokens.STARKNET.STRK, //Into specified destination token
496
774
  _amount,
497
- _exactIn,
498
- _lnurl
775
+ _exactIn, //Whether we define an input or output amount
776
+ _lnurl, //Source LNURL for the swap
777
+ signer.getAddress() //Destination address
499
778
  );
500
779
 
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
780
+ //Get the amount required to pay and fee
781
+ const input: string = swap.getInputWithoutFee().toString(); //Input amount excluding fees
782
+ const fee: string = swap.getFee().amountInSrcToken.toString(); //Fees paid on the output
783
+ const inputWithFees: string = swap.getInput().toString(); //Total amount paid including fees
784
+
785
+ const output: string = swap.getOutput().toString(); //Total output amount
786
+
787
+ //Get swap expiration time
788
+ const expiry: number = swap.getQuoteExpiry(); //Expiration time of the swap quote in UNIX milliseconds, swap needs to be initiated before this time
789
+
790
+ //Get security deposit amount (Human readable amount of STRK that needs to be put down to rent the liquidity from swap intermediary), you will get this deposit back if the swap succeeds
791
+ const securityDeposit: string = swap.getSecurityDeposit().toString();
792
+
793
+ //Get pricing info
794
+ const swapPrice = swap.getPriceInfo().swapPrice; //Price of the current swap (excluding fees)
795
+ const marketPrice = swap.getPriceInfo().marketPrice; //Current market price
796
+ const difference = swap.getPriceInfo().difference; //Difference between the swap price & current market price
797
+ ```
798
+
799
+ Wait for the payment to be received
505
800
 
801
+ ```typescript
802
+ //Start listening to incoming lightning network payment
803
+ const success = await swap.waitForPayment();
804
+ if(!success) {
805
+ //Lightning network payment not received in time and quote expired!
806
+ return;
807
+ }
808
+ ```
809
+
810
+ Claim the funds on the destination smart chains, this settles the swap and lightning network payment
811
+
812
+ ```typescript
506
813
  try {
507
- //Submit the withdraw request & wait for the payment to arrive
508
- await swap.waitForPayment();
509
814
  //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();
815
+ if(swap.canCommitAndClaimInOneShot()) {
816
+ //Some chains (e.g. Solana) support signing multiple transactions in one flow
817
+ await swap.commitAndClaim(solanaSigner);
818
+ } else {
819
+ //Other chains (e.g. Starknet) don't support signing multiple transaction in one flow, therefore you need to sign one-by-one
820
+ await swap.commit(starknetSigner);
821
+ await swap.claim(starknetSigner);
822
+ }
514
823
  } catch(e) {
515
824
  //Error occurred while waiting for payment
516
825
  }
517
826
  ```
518
827
 
519
- ### Get refundable swaps
828
+ or [sign and send transactions manually](#manually-signing-smart-chain-transactions)
829
+
830
+ ### Getting state of the swap
831
+
832
+ You can get the current state of the swap with:
833
+
834
+ ```typescript
835
+ const state = swap.getState();
836
+ ```
837
+
838
+ You can also set a listener to listen for swap state changes:
839
+
840
+ ```typescript
841
+ swap.events.on("swapState", swap => {
842
+ const newState = swap.getState();
843
+ });
844
+ ```
845
+
846
+ For the meaning of the states please refer to the "Swap state" section under each swap type.
847
+
848
+ ### Swap size limits
849
+
850
+ Swap sizes are limited by the LPs you are connected to, they are advertised in BTC terms by LPs during handshake
851
+
852
+ ```typescript
853
+ const swapLimits = swapper.getSwapLimits(srcToken, dstToken);
854
+ const inputMin = swapLimits.input.min;
855
+ const inputMax = swapLimits.input.max;
856
+ const outputMin = swapLimits.output.min;
857
+ const outputMax = swapLimits.output.max;
858
+ ```
859
+
860
+ NOTE: swap limits denominated in BTC are retrieved from the LPs during initial handshake, however limits in other tokens are only returned when getting a quote fails due to amount being too low or too high. For example if you want to get swap limits for the BTC -> SOL swap, the input limits will be immediately available, while the output limits will only get populated once a quote request fails due to amount being too low or high.
861
+
862
+ ```typescript
863
+ let swapLimits = swapper.getSwapLimits(Tokens.BITCOIN.BTC, Tokens.SOLANA.SOL);
864
+ let inputMin = swapLimits.input.min; //Immediately available
865
+ let inputMax = swapLimits.input.max; //Immediately available
866
+ let outputMin = swapLimits.output.min; //Not available from the get-go
867
+ let outputMax = swapLimits.output.max; //Not available from the get-go
868
+
869
+ //You can also listen to swap limit changes (optional)
870
+ swapper.on("swapLimitsChanged", () => {
871
+ //New limits available with swapper.getSwapLimits(srcToken, dstToken)
872
+ //Useful in e.g. a react application where you want to dynamically set min/max swappable amount
873
+ })
874
+
875
+ //Try to swap really small amount of SOL with exactOut swap
876
+ try {
877
+ const swap = await swapper.swap(
878
+ Tokens.BITCOIN.BTC, //Swap from BTC
879
+ Tokens.SOLANA.SOL, //Into specified destination token
880
+ 1n, //1 lamport = 0.000000001 SOL
881
+ false, //Whether we define an input or output amount
882
+ undefined, //Source address for the swap, not used for swaps from BTC
883
+ solanaSigner.getAddress() //Destination address
884
+ );
885
+ } catch (e) {
886
+ //Fails with OutOfBoundsError
887
+ }
888
+
889
+ swapLimits = swapper.getSwapLimits(Tokens.BITCOIN.BTC, Tokens.SOLANA.SOL);
890
+ inputMin = swapLimits.input.min; //Immediately available
891
+ inputMax = swapLimits.input.max; //Immediately available
892
+ outputMin = swapLimits.output.min; //Now available due to failed quote
893
+ outputMax = swapLimits.output.max; //Now available due to failed quote
894
+ ```
895
+
896
+ ### Stored swaps
897
+
898
+ #### Get swap by ID
899
+
900
+ You can retrieve a swap by it's id, you can get an ID of the swap with
901
+
902
+ ```typescript
903
+ const swapId = swap.getId();
904
+ ```
905
+
906
+ And then later retrieve it from the storage
907
+
908
+ ```typescript
909
+ const swap = await swapper.getSwapById(id);
910
+ ```
911
+
912
+ #### Get refundable swaps
520
913
  You can refund the swaps in one of two cases:
521
914
  * In case intermediary is non-cooperative and goes offline, you can claim the funds from the swap contract back after some time.
522
915
  * In case intermediary tried to pay but was unsuccessful, so he sent you signed message with which you can refund now without waiting.
523
916
 
524
917
  This call can be checked on every startup and periodically every few minutes.
525
918
  ```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
- }
919
+ //Get refundable swaps and refund them
920
+ const refundableSolanaSwaps = await swapper.getRefundableSwaps("SOLANA", solanaSigner.getAddress());
921
+ for(let swap of refundableSolanaSwaps) await swap.refund(solanaSigner);
922
+ const refundableStarknetSwaps = await swapper.getRefundableSwaps("STARKNET", starknetSigner.getAddress());
923
+ for(let swap of refundableStarknetSwaps) await swap.refund(starknetSigner);
532
924
  ```
533
925
 
534
- ### Get claimable swaps
926
+ #### Get claimable swaps
535
927
  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
928
 
537
929
  ```typescript
538
930
  //Get the swaps
539
- const claimableSwaps = await solanaSwapper.getClaimableSwaps();
931
+ const claimableSolanaSwaps = await solanaSwapper.getClaimableSwaps("SOLANA", solanaSigner.getAddress());
932
+ //Claim all the claimable swaps
933
+ for(let swap of claimableSolanaSwaps) {
934
+ if(swap.canCommit()) await swap.commit(solanaSigner); //This is for Bitcoin (lightning) -> Smart chain swaps, where commit & claim procedure might be needed
935
+ await swap.claim(solanaSigner);
936
+ }
937
+ //Get the swaps
938
+ const claimableStarknetSwaps = await solanaSwapper.getClaimableSwaps("STARKNET", starknetSigner.getAddress());
540
939
  //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();
940
+ for(let swap of claimableStarknetSwaps) {
941
+ if(swap.canCommit()) await swap.commit(starknetSigner); //This is for Bitcoin (lightning) -> Smart chain swaps, where commit & claim procedure might be needed
942
+ await swap.claim(starknetSigner);
943
+ }
944
+ ```
945
+
946
+ ### Helpers
947
+
948
+ #### Getting wallet balances
949
+
950
+ The SDK also contains helper functions for getting the maximum spendable balance of wallets
951
+
952
+ ```typescript
953
+ //Spendable balance of the starknet wallet address (discounting transaction fees)
954
+ const strkBalance = await swapper.Utils.getSpendableBalance(starknetSigner, Tokens.STARKNET.STRK);
955
+ //Spendable balance of the solana wallet address (discounting transaction fees)
956
+ const solBalance = await swapper.Utils.getSpendableBalance(solanaSigner, Tokens.SOLANA.SOL);
957
+ //Spendable balance of the bitcoin wallet - here we also need to specify the destination chain (as there are different swap protocols available with different on-chain footprints)
958
+ const {balance: btcBalance, feeRate: btcFeeRate} = await swapper.Utils.getBitcoinSpendableBalance(bitcoinWalletAddress, "SOLANA");
959
+ ```
960
+
961
+ #### Unified address parser
962
+
963
+ A common way for parsing all address formats supported by the SDK, automatically recognizes:
964
+ - Bitcoin on-chain L1 address formats (p2pkh, p2wpkh, p2wsh, p2wsh, p2tr)
965
+ - [BIP-21](https://en.bitcoin.it/wiki/BIP_0021) bitcoin payment URI
966
+ - BOLT11 lightning network invoices
967
+ - [LUD-6](https://github.com/lnurl/luds/blob/luds/06.md) LNURL-pay links
968
+ - [LUD-3](https://github.com/lnurl/luds/blob/luds/03.md) LNURL-withdraw links
969
+ - [LUD-16](https://github.com/lnurl/luds/blob/luds/16.md) Lightning static internet identifiers
970
+ - Smart chain addresses (Solana, Starknet, etc.)
971
+
972
+ ```typescript
973
+ const res = await swapper.Utils.parseAddress(address);
974
+ switch(res.type) {
975
+ case "BITCOIN":
976
+ //Bitcoin on-chain L1 address or BIP-21 URI scheme with amount
977
+ const btcAmount = res.amount;
978
+ break;
979
+ case "LIGHTNING":
980
+ //BOLT11 lightning network invoice with pre-set amount
981
+ const lnAmount = res.amount;
982
+ break;
983
+ case "LNURL":
984
+ //LNURL payment or withdrawal link
985
+ if(isLNURLWithdraw(res.lnurl)) {
986
+ //LNURL-withdraw allowing withdrawals over the lightning network
987
+ const lnurlWithdrawData: LNURLWithdraw = res.lnurl;
988
+ const minWithdrawable = res.min; //Minimum payment amount
989
+ const maxWithdrawable = res.max; //Maximum payment amount
990
+ const fixedAmount = res.amount; //If res.min===res.max, an fixed amount is returned instead
991
+ //Should show a UI allowing the user to choose an amount he wishes to withdraw
992
+ }
993
+ if(isLNURLPay(res.lnurl)) {
994
+ //LNURL-pay or static lightning internet identifier allowing repeated payments over the lightning network
995
+ const lnurlPayData: LNURLPay = res.lnurl;
996
+ const minPayable = res.min; //Minimum payment amount
997
+ const maxPayable = res.max; //Maximum payment amount
998
+ const fixedAmount = res.amount; //If res.min===res.max, an fixed amount is returned instead
999
+ const icon: (string | null) = res.lnurl.icon; //URL encoded icon that should be displayed on the UI
1000
+ const shortDescription: (string | null) = res.lnurl.shortDescription; //Short description of the payment
1001
+ const longDescription: (string | null) = res.lnurl.longDescription; //Long description of the payment
1002
+ const maxCommentLength: (number | 0) = res.lnurl.commentMaxLength; //Maximum allowed length of the payment message/comment (0 means no comment allowed)
1003
+ //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
1004
+ }
1005
+ break;
1006
+ default:
1007
+ //Addresses for smart chains
1008
+ break;
544
1009
  }
545
1010
  ```
1011
+
1012
+ ### Manually signing smart chain transactions
1013
+
1014
+ You can also sign the transactions on smart chain side (Solana, Starknet, etc.) of the SDK externally by a separate wallet. Each function which executes any transaction has its txs(action) counterpart, e.g.:
1015
+ - commit() -> txsCommit()
1016
+ - claim() -> txsClaim()
1017
+ - commitAndClaim -> txsCommitAndClaim()
1018
+ - refund() -> txsRefund()
1019
+
1020
+ After sending the transactions, you also need to make sure the SDK has enough time to receive an event notification of the transaction being executed, for this you have the waitTill(action) functions, e.g.:
1021
+
1022
+ - commit() -> waitTillCommited()
1023
+ - claim() -> waitTillClaimed()
1024
+ - commitAndClaim -> waitTillClaimed()
1025
+ - refund() -> waitTillRefunded()
1026
+
1027
+ ```typescript
1028
+ //Example for Solana
1029
+ const txns = await swap.txsCommit(); //Also works with txsClaim, txsRefund, txCommitAndClaim
1030
+ txns.forEach(val => val.tx.sign(...val.signers));
1031
+ const signedTransactions = await solanaSigner.wallet.signAllTransactions(txns.map(val => val.tx));
1032
+ for(let tx of signedTransactions) {
1033
+ const res = await solanaRpc.sendRawTransaction(tx.serialize());
1034
+ await solanaRpc.confirmTransaction(res);
1035
+ }
1036
+ await swap.waitTillCommited(); //Or other relevant waitTillClaimed, waitTillRefunded
1037
+
1038
+ //Example for Starknet
1039
+ const txns = await swap.txsCommit(); //Also works with txsClaim, txsRefund, txCommitAndClaim
1040
+ for(let tx of txns) {
1041
+ if(tx.type==="INVOKE") await starknetSigner.account.execute(tx.tx, tx.details);
1042
+ if(tx.type==="DEPLOY_ACCOUNT") await starknetSigner.account.deployAccount(tx.tx, tx.details);
1043
+ }
1044
+ await swap.waitTillCommited(); //Or other relevant waitTillClaimed, waitTillRefunded
1045
+ ```
1046
+
1047
+ ### Additional swapper options
1048
+
1049
+ You can further customize the swapper instance with these options, you can:
1050
+ - adjust the maximum accepted pricing difference from the LPs
1051
+ - use custom mempool.space instance
1052
+ - use custom pricing API
1053
+ - use own LP node for swaps
1054
+ - adjust HTTP request timeouts
1055
+ - add parameters to be sent with each LP request
1056
+
1057
+ ```typescript
1058
+ const swapper = Factory.newSwapper({
1059
+ ...
1060
+ //Additional optional options
1061
+ pricingFeeDifferencePPM: 20000n, //Maximum allowed pricing difference for quote (between swap & market price) in ppm (parts per million) (20000 == 2%)
1062
+ mempoolApi: new MempoolApi("<url to custom mempool.space instance>"), //Set the SDK to use a custom mempool.space instance instead of the public one
1063
+ getPriceFn: (tickers: string[], abortSignal?: AbortSignal) => customPricingApi.getUsdPriceForTickers(tickers) //Overrides the default pricing API engine with a custom price getter
1064
+
1065
+ intermediaryUrl: "<url to custom LP node>",
1066
+ registryUrl: "<url to custom LP node registry>",
1067
+
1068
+ getRequestTimeout: 10000, //Timeout in milliseconds for GET requests
1069
+ postRequestTimeout: 10000, //Timeout in milliseconds for POST requests
1070
+ defaultAdditionalParameters: {lpData: "Pls give gud price"}, //Additional request data sent to LPs
1071
+
1072
+ defaultTrustedIntermediaryUrl: "<url to custom LP node>" //LP node/intermediary to use for trusted gas swaps
1073
+ });
1074
+ ```