@atomiqlabs/sdk 6.0.2 → 7.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,11 +2,11 @@
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)
5
+ Example SDK integration in NodeJS available [here](https://github.com/atomiqlabs/atomiq-sdk-demo/tree/nostr-htlc)
6
6
 
7
7
  ## Installation
8
8
  ```
9
- npm install @atomiqlabs/sdk
9
+ npm install @atomiqlabs/sdk@next
10
10
  ```
11
11
 
12
12
  ## Installing chain-specific connectors
@@ -14,8 +14,9 @@ npm install @atomiqlabs/sdk
14
14
  You can install only the chain-specific connectors that your project requires
15
15
 
16
16
  ```
17
- npm install @atomiqlabs/chain-solana
18
- npm install @atomiqlabs/chain-starknet
17
+ npm install @atomiqlabs/chain-solana@next
18
+ npm install @atomiqlabs/chain-starknet@next
19
+ npm install @atomiqlabs/chain-evm@next
19
20
  ```
20
21
 
21
22
  ## How to use?
@@ -26,11 +27,13 @@ npm install @atomiqlabs/chain-starknet
26
27
  - Swaps:
27
28
  - [Smart Chain -> BTC L1](#swap-smart-chain---bitcoin-on-chain)
28
29
  - [BTC L1 -> Solana (Old swap protocol)](#swap-bitcoin-on-chain---solana)
29
- - [BTC L1 -> Starknet (New swap protocol)](#swap-bitcoin-on-chain---starknet)
30
+ - [BTC L1 -> Starknet/EVM (New swap protocol)](#swap-bitcoin-on-chain---starknetevm)
30
31
  - [Smart Chain -> BTC Lightning network L2](#swap-smart-chain---bitcoin-lightning-network)
31
32
  - [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)
33
+ - [BTC Lightning network L2 -> Solana (Old swap protocol)](#swap-bitcoin-lightning-network---solana)
34
+ - [BTC Lightning network L2 -> Starknet/EVM (New swap protocol)](#swap-bitcoin-lightning-network---starknetevm)
35
+ - [BTC Lightning network L2 (LNURL-withdraw) -> Solana (Old swap protocol)](#swap-bitcoin-lightning-network---solana-1)
36
+ - [BTC Lightning network L2 (LNURL-withdraw) -> Starknet/EVM (New swap protocol)](#swap-bitcoin-lightning-network---starknetevm-1)
34
37
  - [Swap states](#getting-state-of-the-swap)
35
38
  - [Swap size limits](#swap-size-limits)
36
39
  - [Stored swaps](#stored-swaps)
@@ -48,7 +51,8 @@ Set Solana & Starknet RPC URL to use
48
51
 
49
52
  ```typescript
50
53
  const solanaRpc = "https://api.mainnet-beta.solana.com";
51
- const starknetRpc = "https://starknet-mainnet.public.blastapi.io/rpc/v0_7";
54
+ const starknetRpc = "https://starknet-mainnet.public.blastapi.io/rpc/v0_8";
55
+ const citreaRpc = "https://rpc.testnet.citrea.xyz";
52
56
  ```
53
57
 
54
58
  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.
@@ -56,9 +60,10 @@ Create swapper factory, here we can pick and choose which chains we want to have
56
60
  ```typescript
57
61
  import {SolanaInitializer, SolanaInitializerType} from "@atomiqlabs/chain-solana";
58
62
  import {StarknetInitializer, StarknetInitializerType} from "@atomiqlabs/chain-starknet";
63
+ import {CitreaInitializer, CitreaInitializerType} from "@atomiqlabs/chain-evm";
59
64
  import {SwapperFactory} from "@atomiqlabs/sdk";
60
65
 
61
- const Factory = new SwapperFactory<[SolanaInitializerType, StarknetInitializerType]>([SolanaInitializer, StarknetInitializer] as const);
66
+ const Factory = new SwapperFactory<[SolanaInitializerType, StarknetInitializerType, CitreaInitializerType]>([SolanaInitializer, StarknetInitializer, CitreaInitializer] as const);
62
67
  const Tokens = Factory.Tokens; //Get the supported tokens for all the specified chains.
63
68
  ```
64
69
 
@@ -75,7 +80,10 @@ const swapper = Factory.newSwapper({
75
80
  rpcUrl: solanaRpc //You can also pass Connection object here
76
81
  },
77
82
  STARKNET: {
78
- rpcUrl: starknetRpc //You can also pass Provider object here
83
+ rpcUrl: starknetRpc //You can also pass Provider object here
84
+ },
85
+ CITREA: {
86
+ rpcUrl: citreaRpc, //You can also pass JsonApiProvider object here
79
87
  }
80
88
  },
81
89
  bitcoinNetwork: BitcoinNetwork.TESTNET //or BitcoinNetwork.MAINNET, BitcoinNetwork.TESTNET4 - this also sets the network to use for Solana (solana devnet for bitcoin testnet) & Starknet (sepolia for bitcoin testnet)
@@ -89,7 +97,7 @@ if you want to use custom pricing api, mempool.space RPC url, or tune HTTP reque
89
97
  For NodeJS we need to use sqlite storage, for that we first need to install the sqlite storage adaptor
90
98
 
91
99
  ```
92
- npm install @atomiqlabs/storage-sqlite
100
+ npm install @atomiqlabs/storage-sqlite@next
93
101
  ```
94
102
 
95
103
  Then use pass it in the newSwapper function
@@ -105,6 +113,9 @@ const swapper = Factory.newSwapper({
105
113
  },
106
114
  STARKNET: {
107
115
  rpcUrl: starknetRpc //You can also pass Provider object here
116
+ },
117
+ CITREA: {
118
+ rpcUrl: citreaRpc, //You can also pass JsonApiProvider object here
108
119
  }
109
120
  },
110
121
  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)
@@ -131,7 +142,7 @@ import {WalletAccount} from "starknet";
131
142
  import {StarknetSigner} from "@atomiqlabs/chain-starknet";
132
143
  //Browser, using get-starknet
133
144
  const swo = await connect();
134
- const wallet = new StarknetSigner(new WalletAccount(starknetRpc, swo.wallet));
145
+ const wallet = new StarknetBrowserSigner(new WalletAccount(starknetRpc, swo.wallet));
135
146
  ```
136
147
 
137
148
  or
@@ -144,14 +155,22 @@ const solanaSigner = new SolanaSigner(new SolanaKeypairWallet(Keypair.fromSecret
144
155
  ```
145
156
 
146
157
  ```typescript
147
- import {SolanaKeypairWallet, SolanaSigner} from "@atomiqlabs/chain-solana";
158
+ import {StarknetSigner, StarknetKeypairWallet} from "@atomiqlabs/chain-starknet";
148
159
  //Creating Starknet signer from private key
149
160
  const starknetSigner = new StarknetSigner(new StarknetKeypairWallet(starknetRpc, starknetKey));
150
161
  ```
151
162
 
163
+ ```typescript
164
+ import {BaseWallet, SigningKey} from "ethers";
165
+ import {EVMSigner} from "@atomiqlabs/chain-evm";
166
+ //Creating EVM signer from private key
167
+ const wallet = new BaseWallet(new SigningKey(evmKey));
168
+ const evmWallet = new EVMSigner(wallet, wallet.address);
169
+ ```
170
+
152
171
  ### Initialization
153
172
 
154
- Initialize the swapper
173
+ Initialize the swapper, this should be done once when your app starts. Checks existing in-progress swaps and does initial LP discovery
155
174
 
156
175
  ```typescript
157
176
  await swapper.init();
@@ -167,12 +186,6 @@ To make it easier to do swaps between bitcoin and a specific chain we can extrac
167
186
  const solanaSwapper = swapper.withChain<"SOLANA">("SOLANA");
168
187
  ```
169
188
 
170
- or also with signer
171
-
172
- ```typescript
173
- const starknetSwapperWithSigner = swapper.withChain<"STARKNET">("STARKNET").withSigner(signer);
174
- ```
175
-
176
189
  ### Bitcoin on-chain swaps
177
190
 
178
191
  #### Swap Smart chain -> Bitcoin on-chain
@@ -180,18 +193,14 @@ const starknetSwapperWithSigner = swapper.withChain<"STARKNET">("STARKNET").with
180
193
  Getting swap quote
181
194
 
182
195
  ```typescript
183
- const _exactIn = false; //exactIn = false, so we specify the output amount
184
- const _amount = 10000n; //Amount in BTC base units - sats (10000 sats = 0.0001 BTC)
185
- const _address = "bc1qtw67hj77rt8zrkkg3jgngutu0yfgt9czjwusxt"; //BTC address of the recipient
186
-
187
196
  //Create the swap: swapping SOL to Bitcoin on-chain, receiving _amount of satoshis (smallest unit of bitcoin) to _address
188
197
  const swap = await swapper.swap(
189
198
  Tokens.SOLANA.SOL, //From specified source token
190
199
  Tokens.BITCOIN.BTC, //Swap to BTC
191
- _amount,
192
- _exactIn,
200
+ "0.0001", //Amount can be either passed in base units as bigint or in decimal format as string
201
+ SwapAmountType.EXACT_OUT, //EXACT_OUT, so we specify the output amount
193
202
  solanaSigner.getAddress(), //Source address and smart chain signer
194
- _address //Destination of the swap
203
+ "bc1qtw67hj77rt8zrkkg3jgngutu0yfgt9czjwusxt" //BTC address of the recipient
195
204
  );
196
205
 
197
206
  //Get the amount required to pay and fee
@@ -210,30 +219,80 @@ const marketPrice = swap.getPriceInfo().marketPrice; //Current market price
210
219
  const difference = swap.getPriceInfo().difference; //Difference between the swap price & current market price
211
220
  ```
212
221
 
213
- Initiating the swap
222
+ Executing the swap (simple)
214
223
 
215
224
  ```typescript
216
- //Initiate and pay for the swap
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
225
+ const swapSuccessful = await swap.execute(
226
+ solanaSigner,
227
+ { //Callbacks
228
+ onSourceTransactionSent: (txId: string) => {
229
+ //Transaction on the source chain was sent
230
+ },
231
+ onSourceTransactionConfirmed: (txId: string) => {
232
+ //Transaction on the source chain was confirmed
233
+ },
234
+ onSwapSettled: (destinationTxId: string) => {
235
+ //Bitcoin transaction on the destination chain was sent and swap settled
236
+ }
237
+ }
238
+ );
223
239
 
224
- ```typescript
225
- //Wait for the swap to conclude
226
- const result: boolean = await swap.waitForPayment();
227
- if(!result) {
240
+ //Refund in case of failure
241
+ if(!swapSuccessful) {
228
242
  //Swap failed, money can be refunded
229
- await swap.refund();
243
+ await swap.refund(solanaSigner);
230
244
  } else {
231
- //Swap successful, we can get the bitcoin txId
232
- const bitcoinTxId = swap.getBitcoinTxId();
245
+ //Swap successful!
233
246
  }
234
247
  ```
235
248
 
236
- ##### Swap states
249
+ <details>
250
+ <summary>Manual swap execution (advanced)</summary>
251
+
252
+ - __1.__ Initiate the swap on the smart-chain side
253
+
254
+ - __a.__ Commit with a signer
255
+ ```typescript
256
+ await swap.commit(solanaSigner);
257
+ ```
258
+
259
+ - __b.__ Or get the transactions & [sign and send transaction manually](#manually-signing-smart-chain-transactions)
260
+ ```typescript
261
+ const txsCommit = await swap.txsCommit();
262
+ //Sign and send these...
263
+ ...
264
+ //Important to wait till SDK processes the swap initialization
265
+ await swap.waitTillCommited();
266
+ ```
267
+
268
+ - __2.__ Wait for the swap to execute and for the payment to be sent
269
+ ```typescript
270
+ const swapSuccessful = await swap.waitForPayment();
271
+ ```
272
+
273
+ - __3.__ In case the swap fails we can refund our funds on the source chain
274
+
275
+ - __a.__ Refund with a signer
276
+ ```typescript
277
+ if(!swapSuccessful) {
278
+ await swap.refund(solanaSigner);
279
+ return;
280
+ }
281
+ ```
282
+
283
+ - __b.__ Or get the transactions & [sign and send transaction manually](#manually-signing-smart-chain-transactions)
284
+ ```typescript
285
+ if(!swapSuccessful) {
286
+ const txsRefund = await swap.txsRefund();
287
+ //Sign and send these...
288
+ ...
289
+ }
290
+ ```
291
+
292
+ </details>
293
+
294
+ <details>
295
+ <summary>Swap states</summary>
237
296
 
238
297
  - ToBTCSwapState.REFUNDED = -3
239
298
  - Swap failed and was successfully refunded
@@ -252,6 +311,8 @@ if(!result) {
252
311
  - ToBTCSwapState.REFUNDABLE = 4
253
312
  - Swap was initiated but counterparty failed to process it, the user can now refund his funds
254
313
 
314
+ </details>
315
+
255
316
  #### Swap Bitcoin on-chain -> Solana
256
317
 
257
318
  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.
@@ -259,15 +320,12 @@ NOTE: Solana uses an old swap protocol for Bitcoin on-chain -> Solana swaps, the
259
320
  Getting swap quote
260
321
 
261
322
  ```typescript
262
- const _exactIn = true; //exactIn = true, so we specify the input amount
263
- const _amount = fromHumanReadableString("0.0001", Tokens.BITCOIN.BTC); //Amount in BTC base units - sats, we can also use a utility function here
264
-
265
323
  //Create the swap: swapping _amount of satoshis of Bitcoin on-chain to SOL
266
324
  const swap = await swapper.swap(
267
325
  Tokens.BITCOIN.BTC, //Swap from BTC
268
326
  Tokens.SOLANA.SOL, //Into specified destination token
269
- _amount,
270
- _exactIn, //Whether we define an input or output amount
327
+ "0.0001", //Amount can be either passed in base units as bigint or in decimal format as string
328
+ SwapAmountType.EXACT_IN, //EXACT_IN, so we specify the input amount
271
329
  undefined, //Source address for the swap, not used for swaps from BTC
272
330
  solanaSigner.getAddress() //Destination address
273
331
  );
@@ -293,67 +351,123 @@ const marketPrice = swap.getPriceInfo().marketPrice; //Current market price
293
351
  const difference = swap.getPriceInfo().difference; //Difference between the swap price & current market price
294
352
  ```
295
353
 
296
- Initiating the swap
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
354
+ Executing the swap (simple)
306
355
 
307
356
  ```typescript
308
- //Get the bitcoin address
309
- const receivingAddressOnBitcoin = swap.getAddress();
310
- //Get the QR code data (contains the address and amount)
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
357
+ const automaticSettlementSuccess = await swap.execute(
358
+ solanaSigner,
359
+ { //Bitcoin wallet, you can also pass null/undefined and send the bitcoin transaction from an external wallet
360
+ address: "bc1pscnrk588hdj79mwccucu06007mj5np2jurwfwp5mvhkjldzyphzqyk62m5",
361
+ publicKey: "03a2d8b728935f61d5bcba0cfb09c2c443c483b5c31ebd180e1833f37344bd34ba",
362
+ signPsbt: (psbt: {psbt, psbtHex: string, psbtBase64: string}, signInputs: number[]) => {
363
+ //Sign the PSBT with the bitcoin wallet
364
+ ...
365
+ //Return the signed PSBT in the hex or base64 format!
366
+ return "<signed PSBT>";
367
+ }
368
+ },
369
+ { //Callbacks
370
+ onDestinationCommitSent: (swapAddressOpeningTxId: string) => {
371
+ //Swap address opening transaction sent on the destination chain
372
+ },
373
+ onSourceTransactionSent: (txId: string) => {
374
+ //Bitcoin transaction sent on the source
375
+ },
376
+ onSourceTransactionConfirmationStatus: (txId: string, confirmations: number, targetConfirmations: number, txEtaMs: number) => {
377
+ //Bitcoin transaction confirmation status updates
378
+ },
379
+ onSourceTransactionConfirmed: (txId: string) => {
380
+ //Bitcoin transaction confirmed
381
+ },
382
+ onSwapSettled: (destinationTxId: string) => {
383
+ //Swap settled on the destination
384
+ }
385
+ }
386
+ );
316
387
 
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
388
+ //In case the automatic swap settlement fails, we can settle it manually using the wallet of the destination chain
389
+ if(!automaticSettlementSuccess) {
390
+ await swap.claim(solanaSigner);
322
391
  }
323
- const bitcoinTxId = await swap.submitPsbt(psbt);
324
392
  ```
325
393
 
326
- Waiting for swap execution
327
-
328
- ```typescript
329
- try {
330
- //Wait for the payment to arrive
331
- await swap.waitForBitcoinTransaction(
332
- null, null,
333
- (
334
- txId: string, //Transaction ID of the received bitcoin transaction
335
- confirmations: number, //Current confirmations of the transaction
336
- targetConfirmations: number, //Required confirmations
337
- transactionETAms: number //Estimated in time (in milliseconds) until when the transaction will receive required amount of confirmations
338
- ) => {
339
- //Callback for transaction updates
340
- }
341
- );
342
- } catch(e) {
343
- //Error occurred while waiting for payment, this is most likely due to network errors
344
- return;
345
- }
394
+ <details>
395
+ <summary>Manual swap execution (advanced)</summary>
396
+
397
+ - __1.__ Initiate the swap on the destination chain (Solana) by opening up the bitcoin swap address
398
+
399
+ - __a.__ Commit using signer
400
+ ```typescript
401
+ await swap.commit(solanaWallet);
402
+ ```
403
+
404
+ - __b.__ Or get the transactions & [sign and send transaction manually](#manually-signing-smart-chain-transactions)
405
+ ```typescript
406
+ const txsCommit = await swap.txsCommit();
407
+ //Sign and send these...
408
+ ...
409
+ //Important to wait till SDK processes the swap initialization
410
+ await swap.waitTillCommited();
411
+ ```
412
+
413
+ - __2.__ Send bitcoin transaction
414
+
415
+ - __a.__ Get funded PSBT and sign it
416
+ ```typescript
417
+ const {psbt, psbtHex, psbtBase64, signInputs} = await swap.getFundedPsbt({
418
+ address: "bc1pscnrk588hdj79mwccucu06007mj5np2jurwfwp5mvhkjldzyphzqyk62m5",
419
+ publicKey: "03a2d8b728935f61d5bcba0cfb09c2c443c483b5c31ebd180e1833f37344bd34ba"
420
+ });
421
+ //Sign the psbt
422
+ const signedPsbt = ...; //Can be hex or base64 encoded
423
+ const bitcoinTxId = await swap.submitPsbt(signedPsbt);
424
+ ```
425
+
426
+ - __b.__ Get the bitcoin address or deeplink and send from external wallet
427
+ ```typescript
428
+ //It is imporant to send the EXACT amount, sending different amount will lead to loss of funds!
429
+ const btcSwapAddress = swap.getAddress();
430
+ const btcDeepLink = swap.getHyperlink();
431
+ ```
432
+
433
+ - __3.__ Wait for the bitcoin on-chain transaction to confirm
434
+ ```typescript
435
+ await swap.waitForBitcoinTransaction(
436
+ (txId, confirmations, targetConfirmations, txEtaMs) => {
437
+ //Bitcoin transaction confirmation status callback
438
+ }
439
+ );
440
+ ```
441
+
442
+ - __4.__ Wait for the automatic settlement of the swap
443
+ ```typescript
444
+ const automaticSettlementSuccess = await swap.waitTillClaimed(30);
445
+ ```
446
+
447
+ - __5.__ In case the automatic swap settlement fails, we can settle it manually using the wallet of the destination chain
448
+
449
+ - __a.__ Claim with a signer
450
+ ```typescript
451
+ if(!automaticSettlementSuccess) {
452
+ await swap.claim(solanaSigner);
453
+ }
454
+ ```
455
+
456
+ - __b.__ Or get the transactions & [sign and send transaction manually](#manually-signing-smart-chain-transactions)
457
+ ```typescript
458
+ if(!automaticSettlementSuccess) {}
459
+ const txsClaim = await swap.txsClaim();
460
+ //Sign and send these...
461
+ ...
462
+ //Important to wait till SDK processes the swap initialization
463
+ await swap.waitTillCommited();
464
+ }
465
+ ```
346
466
 
347
- //Swap should get automatically claimed by the watchtowers, if not we can call swap.claim() ourselves
348
- try {
349
- await swap.waitTillClaimed(timeoutSignal(30*1000));
350
- } catch (e) {
351
- //Claim ourselves when automatic claim doesn't happen in 30 seconds
352
- await swap.claim(solanaSigner);
353
- }
354
- ```
467
+ </details>
355
468
 
356
- ##### Swap states
469
+ <details>
470
+ <summary>Swap states</summary>
357
471
 
358
472
  - FromBTCSwapState.EXPIRED = -3
359
473
  - Bitcoin swap address expired
@@ -370,23 +484,21 @@ try {
370
484
  - FromBTCSwapState.CLAIM_CLAIMED = 3
371
485
  - Swap funds are claimed to the user's wallet
372
486
 
487
+ </details>
373
488
 
374
- #### Swap Bitcoin on-chain -> Starknet
489
+ #### Swap Bitcoin on-chain -> Starknet/EVM
375
490
 
376
- NOTE: Starknet uses a new swap protocol for Bitcoin on-chain -> Solana swaps, the flow here is different from the one for Solana!
491
+ NOTE: Starknet & EVM uses a new swap protocol for Bitcoin on-chain -> Smart chain swaps, the flow here is different from the one for Solana!
377
492
 
378
493
  Getting swap quote
379
494
 
380
495
  ```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
496
  //Create the swap: swapping _amount of satoshis of Bitcoin on-chain to SOL
385
497
  const swap = await swapper.swap(
386
498
  Tokens.BITCOIN.BTC, //Swap from BTC
387
499
  Tokens.STARKNET.STRK, //Into specified destination token
388
- _amount,
389
- _exactIn, //Whether we define an input or output amount
500
+ "0.0001", //Amount can be either passed in base units as bigint or in decimal format as string
501
+ SwapAmountType.EXACT_IN, //EXACT_IN, so we specify the input amount
390
502
  undefined, //Source address for the swap, not used for swaps from BTC
391
503
  starknetSigner.getAddress(), //Destination address
392
504
  {
@@ -410,62 +522,109 @@ const marketPrice = swap.getPriceInfo().marketPrice; //Current market price
410
522
  const difference = swap.getPriceInfo().difference; //Difference between the swap price & current market price
411
523
  ```
412
524
 
413
- Initiating the swap
525
+ Executing the swap (simple)
414
526
 
415
527
  ```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
528
+ const automaticSettlementSuccess = await swap.execute(
529
+ { //Bitcoin wallet
530
+ address: "bc1pscnrk588hdj79mwccucu06007mj5np2jurwfwp5mvhkjldzyphzqyk62m5",
531
+ publicKey: "03a2d8b728935f61d5bcba0cfb09c2c443c483b5c31ebd180e1833f37344bd34ba",
532
+ signPsbt: (psbt: {psbt, psbtHex: string, psbtBase64: string}, signInputs: number[]) => {
533
+ //Sign the PSBT with the bitcoin wallet
534
+ ...
535
+ //Return the signed PSBT in the hex or base64 format!
536
+ return "<signed PSBT>";
537
+ }
538
+ },
539
+ { //Callbacks
540
+ onSourceTransactionSent: (txId: string) => {
541
+ //Bitcoin transaction sent on the source
542
+ },
543
+ onSourceTransactionConfirmationStatus: (txId: string, confirmations: number, targetConfirmations: number, txEtaMs: number) => {
544
+ //Bitcoin transaction confirmation status updates
545
+ },
546
+ onSourceTransactionConfirmed: (txId: string) => {
547
+ //Bitcoin transaction confirmed
548
+ },
549
+ onSwapSettled: (destinationTxId: string) => {
550
+ //Swap settled on the destination
551
+ }
552
+ }
553
+ );
425
554
 
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);
555
+ //In case the automatic swap settlement fails, we can settle it manually using the wallet of the destination chain
556
+ if(!automaticSettlementSuccess) {
557
+ await swap.claim(starknetWallet);
558
+ }
436
559
  ```
437
560
 
438
- Waiting for swap execution
439
561
 
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
- }
562
+ <details>
563
+ <summary>Manual swap execution (advanced)</summary>
564
+
565
+ - __1.__ Send bitcoin transaction
566
+
567
+ - __a.__ Get funded PSBT and sign it
568
+ ```typescript
569
+ const {psbt, psbtHex, psbtBase64, signInputs} = await swap.getFundedPsbt({
570
+ address: "bc1pscnrk588hdj79mwccucu06007mj5np2jurwfwp5mvhkjldzyphzqyk62m5",
571
+ publicKey: "03a2d8b728935f61d5bcba0cfb09c2c443c483b5c31ebd180e1833f37344bd34ba"
572
+ });
573
+ //Sign the psbt
574
+ const signedPsbt = ...; //Can be hex or base64 encoded
575
+ const bitcoinTxId = await swap.submitPsbt(signedPsbt);
576
+ ```
577
+
578
+ - __b.__ Or obtain raw PSBT to which inputs still need to be added
579
+ ```typescript
580
+ const {psbt, psbtHex, psbtBase64, in1sequence} = await swap.getPsbt();
581
+ psbt.addInput(...);
582
+ //Make sure the second input's sequence (index 1) is as specified in the in1sequence variable
583
+ psbt.updateInput(1, {sequence: in1sequence});
584
+ //Sign the PSBT, sign every input except the first one
585
+ for(let i=1;i<psbt.inputsLength; i++) psbt.signIdx(..., i); //Or pass it to external signer
586
+ //Submit the signed PSBT, can be the Transaction object, or hex/base64 serialized
587
+ const bitcoinTxId = await swap.submitPsbt(psbt);
588
+ ```
589
+
590
+ - __2.__ Wait for the bitcoin on-chain transaction to confirm
591
+ ```typescript
592
+ await swap.waitForBitcoinTransaction(
593
+ (txId, confirmations, targetConfirmations, txEtaMs) => {
594
+ //Bitcoin transaction confirmation status callback
595
+ }
596
+ );
597
+ ```
598
+
599
+ - __3.__ Wait for the automatic settlement of the swap
600
+ ```typescript
601
+ const automaticSettlementSuccess = await swap.waitTillClaimed(60);
602
+ ```
603
+
604
+ - __4.__ In case the automatic swap settlement fails, we can settle it manually using the wallet of the destination chain
605
+
606
+ - __a.__ Claim with a signer
607
+ ```typescript
608
+ if(!automaticSettlementSuccess) {
609
+ await swap.claim(starknetSigner);
610
+ }
611
+ ```
612
+
613
+ - __b.__ Or get the transactions & [sign and send transaction manually](#manually-signing-smart-chain-transactions)
614
+ ```typescript
615
+ if(!automaticSettlementSuccess) {}
616
+ const txsClaim = await swap.txsClaim();
617
+ //Sign and send these...
618
+ ...
619
+ //Important to wait till SDK processes the swap initialization
620
+ await swap.waitTillCommited();
621
+ }
622
+ ```
458
623
 
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
- ```
624
+ </details>
467
625
 
468
- ##### Swap states
626
+ <details>
627
+ <summary>Swap states</summary>
469
628
 
470
629
  - SpvFromBTCSwapState.CLOSED = -5
471
630
  - Catastrophic failure during swap, shall never happen
@@ -491,6 +650,8 @@ try {
491
650
  - Bitcoin swap transaction is confirmed
492
651
  - SpvFromBTCSwapState.CLAIM_CLAIMED = 6
493
652
  - Swap funds are claimed to the user's wallet
653
+ -
654
+ </details>
494
655
 
495
656
  ### Bitcoin lightning network swaps
496
657
 
@@ -499,17 +660,15 @@ try {
499
660
  Getting swap quote
500
661
 
501
662
  ```typescript
502
- //Destination lightning network invoice, amount needs to be part of the invoice!
503
- const _lightningInvoice = "lnbc10u1pj2q0g9pp5ejs6m677m39cznpzum7muruvh50ys93ln82p4j9ks2luqm56xxlshp52r2anlhddfa9ex9vpw9gstxujff8a0p8s3pzvua930js0kwfea6scqzzsxqyz5vqsp5073zskc5qfgp7lre0t6s8uexxxey80ax564hsjklfwfjq2ew0ewq9qyyssqvzmgs6f8mvuwgfa9uqxhtza07qem4yfhn9wwlpskccmuwplsqmh8pdy6c42kqdu8p73kky9lsnl40qha5396d8lpgn90y27ltfc5rfqqq59cya";
504
-
505
663
  //Create the swap: swapping SOL to Bitcoin lightning
506
664
  const swap = await swapper.swap(
507
665
  Tokens.SOLANA.SOL, //From specified source token
508
666
  Tokens.BITCOIN.BTCLN, //Swap to BTC-LN
509
667
  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!
668
+ SwapAmountType.EXACT_OUT, //Make sure we use EXACT_OUT for swaps to BTC-LN, if you want to use EXACT_IN and set an amount, use LNURL-pay!
511
669
  solanaSigner.getAddress(), //Source address and smart chain signer
512
- _lightningInvoice //Destination of the swap
670
+ //Destination lightning network invoice, amount needs to be part of the invoice!
671
+ "lnbc10u1pj2q0g9pp5ejs6m677m39cznpzum7muruvh50ys93ln82p4j9ks2luqm56xxlshp52r2anlhddfa9ex9vpw9gstxujff8a0p8s3pzvua930js0kwfea6scqzzsxqyz5vqsp5073zskc5qfgp7lre0t6s8uexxxey80ax564hsjklfwfjq2ew0ewq9qyyssqvzmgs6f8mvuwgfa9uqxhtza07qem4yfhn9wwlpskccmuwplsqmh8pdy6c42kqdu8p73kky9lsnl40qha5396d8lpgn90y27ltfc5rfqqq59cya"
513
672
  );
514
673
 
515
674
  //Get the amount required to pay and fee
@@ -528,30 +687,80 @@ const marketPrice = swap.getPriceInfo().marketPrice; //Current market price
528
687
  const difference = swap.getPriceInfo().difference; //Difference between the swap price & current market price
529
688
  ```
530
689
 
531
- Initiating the swap
690
+ Executing the swap (simple)
532
691
 
533
692
  ```typescript
534
- //Initiate and pay for the swap
535
- await swap.commit(solanaSigner);
536
- ```
537
-
538
- or [sign and send transaction manually](#manually-signing-smart-chain-transactions)
539
-
540
- Wait for the swap to execute, refund in case of failure
693
+ const swapSuccessful = await swap.execute(
694
+ solanaSigner,
695
+ { //Callbacks
696
+ onSourceTransactionSent: (txId: string) => {
697
+ //Transaction on the source chain was sent
698
+ },
699
+ onSourceTransactionConfirmed: (txId: string) => {
700
+ //Transaction on the source chain was confirmed
701
+ },
702
+ onSwapSettled: (destinationTxId: string) => {
703
+ //Lightning payment on the destination chain was sent and swap settled
704
+ }
705
+ }
706
+ );
541
707
 
542
- ```typescript
543
- //Wait for the swap to conclude
544
- const result: boolean = await swap.waitForPayment();
545
- if(!result) {
546
- //Swap failed, money can be refunded
547
- await swap.refund(solanaSigner);
708
+ //Refund in case of failure
709
+ if(!swapSuccessful) {
710
+ //Swap failed, money can be refunded
711
+ await swap.refund(solanaSigner);
548
712
  } else {
549
- //Swap successful, we can get the lightning payment secret pre-image, which acts as a proof of payment
550
- const lightningSecret = swap.getSecret();
713
+ //Swap successful!
551
714
  }
552
715
  ```
553
716
 
554
- ##### Swap states
717
+ <details>
718
+ <summary>Manual swap execution (advanced)</summary>
719
+
720
+ - __1.__ Initiate the swap on the smart-chain side
721
+
722
+ - __a.__ Commit with a signer
723
+ ```typescript
724
+ await swap.commit(solanaSigner);
725
+ ```
726
+
727
+ - __b.__ Or get the transactions & [sign and send transaction manually](#manually-signing-smart-chain-transactions)
728
+ ```typescript
729
+ const txsCommit = await swap.txsCommit();
730
+ //Sign and send these...
731
+ ...
732
+ //Important to wait till SDK processes the swap initialization
733
+ await swap.waitTillCommited();
734
+ ```
735
+
736
+ - __2.__ Wait for the swap to execute and for the payment to be sent
737
+ ```typescript
738
+ const swapSuccessful = await swap.waitForPayment();
739
+ ```
740
+
741
+ - __3.__ In case the swap fails we can refund our funds on the source chain
742
+
743
+ - __a.__ Refund with a signer
744
+ ```typescript
745
+ if(!swapSuccessful) {
746
+ await swap.refund(solanaSigner);
747
+ return;
748
+ }
749
+ ```
750
+
751
+ - __b.__ Or get the transactions & [sign and send transaction manually](#manually-signing-smart-chain-transactions)
752
+ ```typescript
753
+ if(!swapSuccessful) {
754
+ const txsRefund = await swap.txsRefund();
755
+ //Sign and send these...
756
+ ...
757
+ }
758
+ ```
759
+
760
+ </details>
761
+
762
+ <details>
763
+ <summary>Swap states</summary>
555
764
 
556
765
  - ToBTCSwapState.REFUNDED = -3
557
766
  - Swap failed and was successfully refunded
@@ -570,19 +779,20 @@ if(!result) {
570
779
  - ToBTCSwapState.REFUNDABLE = 4
571
780
  - Swap was initiated but counterparty failed to process it, the user can now refund his funds
572
781
 
573
- #### Swap Bitcoin lightning network -> Smart chain
782
+ </details>
783
+
784
+ #### Swap Bitcoin lightning network -> Solana
785
+
786
+ NOTE: Solana uses an old swap protocol for Bitcoin lightning network -> Solana swaps, the flow here is different from the one for Starknet and other chains.
574
787
 
575
788
  Getting swap quote
576
789
 
577
790
  ```typescript
578
- const _exactIn = true; //exactIn = true, so we specify the input amount
579
- const _amount = 10000n; //Amount in BTC base units - sats
580
-
581
791
  const swap = await swapper.swap(
582
792
  Tokens.BITCOIN.BTCLN, //Swap from BTC-LN
583
- Tokens.STARKNET.STRK, //Into specified destination token
584
- _amount,
585
- _exactIn, //Whether we define an input or output amount
793
+ Tokens.SOLANA.SOL, //Into specified destination token
794
+ 10000n, //Amount can be either passed in base units as bigint or in decimal format as string
795
+ SwapAmountType.EXACT_IN, //SwapAmountType.EXACT_IN, so we specify the input amount
586
796
  undefined, //Source address for the swap, not used for swaps from BTC-LN
587
797
  signer.getAddress() //Destination address
588
798
  );
@@ -611,40 +821,72 @@ const marketPrice = swap.getPriceInfo().marketPrice; //Current market price
611
821
  const difference = swap.getPriceInfo().difference; //Difference between the swap price & current market price
612
822
  ```
613
823
 
614
- Pay the displayed lightning network invoice from an external wallet
615
-
616
- Wait for the payment to be received
824
+ Executing the swap (simple)
617
825
 
618
826
  ```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
- }
827
+ await swap.execute(
828
+ solanaSigner,
829
+ { //Lightning network wallet, you can also pass null/undefined and pay the LN invoice from an external wallet
830
+ payInvoice: (bolt11PaymentRequest: string) => {
831
+ //Here you would usually call the WebLN or NWC to execute the payment, it's completely fine if the
832
+ // promise here would block till the payment is settled
833
+ return Promise.resolve("");
834
+ }
835
+ },
836
+ { //Callbacks
837
+ onSourceTransactionReceived: (sourceLnPaymentHash: string) => {
838
+ //Lightning network payment received by the LP
839
+ },
840
+ onDestinationCommitSent: (destinationCommitTxId: string) => {
841
+ //HTLC initialization transaction sent on the destination chain
842
+ },
843
+ onDestinationClaimSent: (destinationClaimTxId: string) => {
844
+ //HTLC claim transaction sent on the destination chain
845
+ },
846
+ onSwapSettled: (destinationClaimTxId: string) => {
847
+ //Swap settled and funds received on destination
848
+ }
849
+ }
850
+ );
625
851
  ```
626
852
 
627
- Claim the funds on the destination smart chains, this settles the swap and lightning network payment
853
+ <details>
854
+ <summary>Manual swap execution (advanced)</summary>
628
855
 
629
- ```typescript
630
- try {
631
- //Claim the swap funds - this will initiate 2 transactions
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
- }
640
- } catch(e) {
641
- //Error occurred while waiting for payment
642
- }
643
- ```
856
+ - __1.__ Pay the LN invoice from a lightning network wallet
857
+ ```typescript
858
+ const lightningInvoice = swap.getAddress();
859
+ ```
860
+
861
+ - __2.__ Start listening to incoming lightning network payment
862
+ ```typescript
863
+ const success = await swap.waitForPayment();
864
+ if(!success) {
865
+ //Lightning network payment not received in time and quote expired
866
+ return;
867
+ }
868
+ ```
869
+
870
+ - __3.__ Claim the swap at the destination
871
+
872
+ - __a.__ Commit & claim with signer
873
+ ```typescript
874
+ await swap.commitAndClaim(solanaSigner);
875
+ ```
876
+
877
+ - __b.__ Or get the transactions & [sign and send transaction manually](#manually-signing-smart-chain-transactions)
878
+ ```typescript
879
+ const txsCommitAndClaim = await swap.txsCommitAndClaim();
880
+ //Take EXTRA care to make sure transaction are sent sequentially and in order - always wait
881
+ // for prior transaction confirmation before sending the next one
882
+ //Sign and send these...
883
+ ...
884
+ ```
644
885
 
645
- or [sign and send transactions manually](#manually-signing-smart-chain-transactions)
886
+ </details>
646
887
 
647
- ##### Swap states
888
+ <details>
889
+ <summary>Swap states</summary>
648
890
 
649
891
  - FromBTCLNSwapState.FAILED = -4
650
892
  - If the claiming of the funds was initiated, but never concluded, the user will get his lightning network payment refunded
@@ -663,6 +905,138 @@ or [sign and send transactions manually](#manually-signing-smart-chain-transacti
663
905
  - FromBTCLNSwapState.CLAIM_CLAIMED = 3
664
906
  - Funds were successfully claimed & lightning network secret pre-image revealed, so the lightning network payment will settle now
665
907
 
908
+ </details>
909
+
910
+ #### Swap Bitcoin lightning network -> Starknet/EVM
911
+
912
+ Getting swap quote
913
+
914
+ ```typescript
915
+ const swap = await swapper.swap(
916
+ Tokens.BITCOIN.BTCLN, //Swap from BTC-LN
917
+ Tokens.STARKNET.STRK, //Into specified destination token
918
+ 10000n, //Amount can be either passed in base units as bigint or in decimal format as string
919
+ SwapAmountType.EXACT_IN, //SwapAmountType.EXACT_IN, so we specify the input amount
920
+ undefined, //Source address for the swap, not used for swaps from BTC-LN
921
+ signer.getAddress(), //Destination address
922
+ {
923
+ gasAmount: 1_000_000_000_000_000_000n //We can also request a gas drop on the destination chain (here requesting 1 STRK)
924
+ }
925
+ );
926
+
927
+ //Get the bitcoin lightning network invoice (the invoice contains pre-entered amount)
928
+ const receivingLightningInvoice: string = swap.getAddress();
929
+ //Get the URI hyperlink (contains the lightning network invoice) which can be displayed also as QR code
930
+ const qrCodeData: string = swap.getHyperlink();
931
+
932
+ //Get the amount required to pay and fee
933
+ const input: string = swap.getInputWithoutFee().toString(); //Input amount excluding fees
934
+ const fee: string = swap.getFee().amountInSrcToken.toString(); //Fees paid on the output
935
+ const inputWithFees: string = swap.getInput().toString(); //Total amount paid including fees
936
+
937
+ const output: string = swap.getOutput().toString(); //Total output amount
938
+
939
+ //Get swap expiration time
940
+ const expiry: number = swap.getQuoteExpiry(); //Expiration time of the swap quote in UNIX milliseconds, swap needs to be initiated before this time
941
+
942
+ //Get pricing info
943
+ const swapPrice = swap.getPriceInfo().swapPrice; //Price of the current swap (excluding fees)
944
+ const marketPrice = swap.getPriceInfo().marketPrice; //Current market price
945
+ const difference = swap.getPriceInfo().difference; //Difference between the swap price & current market price
946
+ ```
947
+
948
+ Executing the swap (simple)
949
+
950
+ ```typescript
951
+ const automaticSettlementSuccess = await swap.execute(
952
+ { //Lightning network wallet, you can also pass null/undefined and pay the LN invoice from an external wallet
953
+ payInvoice: (bolt11PaymentRequest: string) => {
954
+ //Here you would usually call the WebLN or NWC to execute the payment, it's completely fine if the
955
+ // promise here would block till the payment is settled
956
+ return Promise.resolve("");
957
+ }
958
+ },
959
+ { //Callbacks
960
+ onSourceTransactionReceived: (sourceLnPaymentHash: string) => {
961
+ //Lightning network payment received by the LP
962
+ },
963
+ onSwapSettled: (destinationClaimTxId: string) => {
964
+ //Swap settled and funds received on destination
965
+ }
966
+ }
967
+ );
968
+
969
+ //In case the automatic swap settlement fails, we can settle it manually using the wallet of the destination chain
970
+ if(!automaticSettlementSuccess) {
971
+ await swap.claim(starknetSigner);
972
+ }
973
+ ```
974
+
975
+
976
+ <details>
977
+ <summary>Manual swap execution (advanced)</summary>
978
+
979
+ - __1.__ Pay the LN invoice from a lightning network wallet
980
+ ```typescript
981
+ const lightningInvoice = swap.getAddress();
982
+ ```
983
+
984
+ - __2.__ Start listening to incoming lightning network payment
985
+ ```typescript
986
+ const success = await swap.waitForPayment();
987
+ if(!success) {
988
+ //Lightning network payment not received in time and quote expired
989
+ return;
990
+ }
991
+ ```
992
+
993
+ - __3.__ Wait for the swap to be automatically settled
994
+ ```typescript
995
+ const automaticSettlementSuccess = await swap.waitTillClaimed(60);
996
+ ```
997
+
998
+ - __4.__ In case the automatic swap settlement fails, we can settle it manually using the wallet of the destination chain
999
+
1000
+ - __a.__ Claim with signer
1001
+ ```typescript
1002
+ if(!automaticSettlementSuccess) {
1003
+ await swap.claim(starknetSigner);
1004
+ }
1005
+ ```
1006
+
1007
+ - __b.__ Or get the transactions & [sign and send transaction manually](#manually-signing-smart-chain-transactions)
1008
+ ```typescript
1009
+ if(!automaticSettlementSuccess) {
1010
+ const txsClaim = await swap.txsClaim();
1011
+ //Sign and send these...
1012
+ ...
1013
+ }
1014
+ ```
1015
+
1016
+ </details>
1017
+
1018
+ <details>
1019
+ <summary>Swap states</summary>
1020
+
1021
+ - FromBTCLNAutoSwapState.FAILED = -4
1022
+ - If the claiming of the funds was initiated, but never concluded, the user will get his lightning network payment refunded
1023
+ - FromBTCLNAutoSwapState.QUOTE_EXPIRED = -3
1024
+ - Swap quote expired and cannot be executed anymore
1025
+ - FromBTCLNAutoSwapState.QUOTE_SOFT_EXPIRED = -2
1026
+ - Swap quote soft-expired (i.e. the quote probably expired, but if there is already an initialization transaction sent it might still succeed)
1027
+ - FromBTCLNAutoSwapState.EXPIRED = -1
1028
+ - Lightning network invoice expired, meaning the swap is expired
1029
+ - FromBTCLNAutoSwapState.PR_CREATED = 0
1030
+ - Swap is created, the user should now pay the provided lightning network invoice
1031
+ - FromBTCLNAutoSwapState.PR_PAID = 1
1032
+ - Lightning network invoice payment was received (but cannot be settled by the counterparty yet)
1033
+ - FromBTCLNAutoSwapState.CLAIM_COMMITED = 2
1034
+ - A swap HTLC was offered by the LP to the user
1035
+ - FromBTCLNAutoSwapState.CLAIM_CLAIMED = 3
1036
+ - Funds were successfully claimed & lightning network secret pre-image revealed, so the lightning network payment will settle now
1037
+
1038
+ </details>
1039
+
666
1040
  ### LNURLs & readable lightning identifiers
667
1041
 
668
1042
  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)
@@ -695,18 +1069,15 @@ LNURLs & lightning identifiers:
695
1069
  Getting swap quote
696
1070
 
697
1071
  ```typescript
698
- const _lnurlOrIdentifier: string = "lnurl1dp68gurn8ghj7ampd3kx2ar0veekzar0wd5xjtnrdakj7tnhv4kxctttdehhwm30d3h82unvwqhkx6rfvdjx2ctvxyesuk0a27"; //Destination LNURL-pay or readable identifier
699
- const _exactIn = false; //exactIn = false, so we specify the output amount
700
- const _amount: bigint = 10000n; //Amount of satoshis to send (1 BTC = 100 000 000 satoshis)
701
-
702
1072
  //Create the swap: swapping SOL to Bitcoin lightning
703
1073
  const swap = await swapper.swap(
704
1074
  Tokens.SOLANA.SOL, //From specified source token
705
1075
  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
1076
+ 10000n, //Now we can specify an amount for a lightning network payment!
1077
+ SwapAmountType.EXACT_OUT, //We can also use exactIn=true here and set an amount in input token
708
1078
  solanaSigner.getAddress(), //Source address and smart chain signer
709
- _lnurlOrIdentifier, //Destination of the swap
1079
+ //Destination LNURL-pay or readable identifier
1080
+ "lnurl1dp68gurn8ghj7ampd3kx2ar0veekzar0wd5xjtnrdakj7tnhv4kxctttdehhwm30d3h82unvwqhkx6rfvdjx2ctvxyesuk0a27",
710
1081
  {
711
1082
  comment: "Hello world" //For LNURL-pay we can also pass a comment to the recipient
712
1083
  }
@@ -728,53 +1099,105 @@ const marketPrice = swap.getPriceInfo().marketPrice; //Current market price
728
1099
  const difference = swap.getPriceInfo().difference; //Difference between the swap price & current market price
729
1100
  ```
730
1101
 
731
- Initiating the swap
1102
+
1103
+ Executing the swap (simple)
732
1104
 
733
1105
  ```typescript
734
- //Initiate and pay for the swap
735
- await swap.commit(solanaSigner);
1106
+ const swapSuccessful = await swap.execute(
1107
+ solanaSigner,
1108
+ { //Callbacks
1109
+ onSourceTransactionSent: (txId: string) => {
1110
+ //Transaction on the source chain was sent
1111
+ },
1112
+ onSourceTransactionConfirmed: (txId: string) => {
1113
+ //Transaction on the source chain was confirmed
1114
+ },
1115
+ onSwapSettled: (destinationTxId: string) => {
1116
+ //Lightning payment on the destination chain was sent and swap settled
1117
+ }
1118
+ }
1119
+ );
1120
+
1121
+ //Refund in case of failure
1122
+ if(!swapSuccessful) {
1123
+ //Swap failed, money can be refunded
1124
+ await swap.refund(solanaSigner);
1125
+ return;
1126
+ }
1127
+
1128
+ //Swap successful!
1129
+ const lightningSecret = swap.getSecret();
1130
+ //In case the LNURL contained a success action, we can read it now and display it to user
1131
+ if(swap.hasSuccessAction()) {
1132
+ //Contains a success action that should displayed to the user
1133
+ const successMessage = swap.getSuccessAction();
1134
+ const description: string = successMessage.description; //Description of the message
1135
+ const text: (string | null) = successMessage.text; //Main text of the message
1136
+ const url: (string | null) = successMessage.url; //URL link which should be displayed
1137
+ }
736
1138
  ```
737
1139
 
738
- or [sign and send transaction manually](#manually-signing-smart-chain-transactions)
1140
+ <details>
1141
+ <summary>Manual swap execution (advanced)</summary>
739
1142
 
740
- Wait for the swap to execute, refund in case of failure
1143
+ - __1.__ Initiate the swap on the smart-chain side
741
1144
 
742
- ```typescript
743
- //Wait for the swap to conclude
744
- const result: boolean = await swap.waitForPayment();
745
- if(!result) {
746
- //Swap failed, money can be refunded
747
- await swap.refund(solanaSigner);
748
- } else {
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
1145
+ - __a.__ Commit with a signer
1146
+ ```typescript
1147
+ await swap.commit(solanaSigner);
1148
+ ```
1149
+
1150
+ - __b.__ Or get the transactions & [sign and send transaction manually](#manually-signing-smart-chain-transactions)
1151
+ ```typescript
1152
+ const txsCommit = await swap.txsCommit();
1153
+ //Sign and send these...
1154
+ ...
1155
+ //Important to wait till SDK processes the swap initialization
1156
+ await swap.waitTillCommited();
1157
+ ```
1158
+
1159
+ - __2.__ Wait for the swap to execute and for the payment to be sent
1160
+
1161
+ ```typescript
1162
+ const swapSuccessful = await swap.waitForPayment();
1163
+ ```
1164
+
1165
+ - __3.__ In case the swap fails we can refund our funds on the source chain
1166
+
1167
+ - __a.__ Refund with a signer
1168
+ ```typescript
1169
+ if(!swapSuccessful) {
1170
+ await swap.refund(solanaSigner);
1171
+ return;
758
1172
  }
759
- }
760
- ```
1173
+ ```
1174
+
1175
+ - __b.__ Or get the transactions & [sign and send transaction manually](#manually-signing-smart-chain-transactions)
1176
+ ```typescript
1177
+ if(!swapSuccessful) {
1178
+ const txsRefund = await swap.txsRefund();
1179
+ //Sign and send these...
1180
+ ...
1181
+ }
1182
+ ```
1183
+
1184
+ </details>
1185
+
1186
+ #### Swap Bitcoin lightning network -> Solana
761
1187
 
762
- #### Swap Bitcoin lightning network -> Smart chain
1188
+ NOTE: Solana uses an old swap protocol for Bitcoin lightning network -> Solana swaps, the flow here is different from the one for Starknet and other chains.
763
1189
 
764
1190
  Getting swap quote
765
1191
 
766
1192
  ```typescript
767
- const _lnurl: string = "lnurl1dp68gurn8ghj7ampd3kx2ar0veekzar0wd5xjtnrdakj7tnhv4kxctttdehhwm30d3h82unvwqhkx6rfvdjx2ctvxyesuk0a27"; //Destination LNURL-pay or readable identifier
768
- const _exactIn = true; //exactIn = true, so we specify the input amount
769
- const _amount = 10000n; //Amount in BTC base units - sats
770
-
771
1193
  const swap = await swapper.swap(
772
1194
  Tokens.BITCOIN.BTCLN, //Swap from BTC-LN
773
- Tokens.STARKNET.STRK, //Into specified destination token
774
- _amount,
775
- _exactIn, //Whether we define an input or output amount
776
- _lnurl, //Source LNURL for the swap
777
- signer.getAddress() //Destination address
1195
+ Tokens.SOLANA.SOL, //Into specified destination token
1196
+ 10000n,
1197
+ SwapAmountType.EXACT_IN, //EXACT_IN, so we specify the input amount
1198
+ //Source LNURL-withdraw link
1199
+ "lnurl1dp68gurn8ghj7ampd3kx2ar0veekzar0wd5xjtnrdakj7tnhv4kxctttdehhwm30d3h82unvwqhkx6rfvdjx2ctvxyesuk0a27",
1200
+ signer.getAddress(), //Destination address
778
1201
  );
779
1202
 
780
1203
  //Get the amount required to pay and fee
@@ -796,36 +1219,152 @@ const marketPrice = swap.getPriceInfo().marketPrice; //Current market price
796
1219
  const difference = swap.getPriceInfo().difference; //Difference between the swap price & current market price
797
1220
  ```
798
1221
 
799
- Wait for the payment to be received
1222
+ Executing the swap (simple)
800
1223
 
801
1224
  ```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
- }
1225
+ await swap.execute(
1226
+ solanaSigner,
1227
+ undefined, //No need to specify a wallet, we are sourcing the fund from LNURL-withdraw link
1228
+ { //Callbacks
1229
+ onSourceTransactionReceived: (sourceLnPaymentHash: string) => {
1230
+ //Lightning network payment received by the LP
1231
+ },
1232
+ onDestinationCommitSent: (destinationCommitTxId: string) => {
1233
+ //HTLC initialization transaction sent on the destination chain
1234
+ },
1235
+ onDestinationClaimSent: (destinationClaimTxId: string) => {
1236
+ //HTLC claim transaction sent on the destination chain
1237
+ },
1238
+ onSwapSettled: (destinationClaimTxId: string) => {
1239
+ //Swap settled and funds received on destination
1240
+ }
1241
+ }
1242
+ );
808
1243
  ```
809
1244
 
810
- Claim the funds on the destination smart chains, this settles the swap and lightning network payment
1245
+ <details>
1246
+ <summary>Manual swap execution (advanced)</summary>
1247
+
1248
+ - __1.__ Start listening to incoming lightning network payment (this also requests the payment from LNURL-withdraw service)
1249
+ ```typescript
1250
+ const success = await swap.waitForPayment();
1251
+ if(!success) {
1252
+ //Lightning network payment not received in time and quote expired
1253
+ return;
1254
+ }
1255
+ ```
1256
+
1257
+ - __2.__ Claim the swap at the destination
1258
+
1259
+ - __a.__ Commit & claim with signer
1260
+ ```typescript
1261
+ await swap.commitAndClaim(solanaSigner);
1262
+ ```
1263
+
1264
+ - __b.__ Or get the transactions & [sign and send transaction manually](#manually-signing-smart-chain-transactions)
1265
+ ```typescript
1266
+ const txsCommitAndClaim = await swap.txsCommitAndClaim();
1267
+ //Take EXTRA care to make sure transaction are sent sequentially and in order - always wait
1268
+ // for prior transaction confirmation before sending the next one
1269
+ //Sign and send these...
1270
+ ...
1271
+ ```
1272
+
1273
+ </details>
1274
+
1275
+ #### Swap Bitcoin lightning network -> Starknet/EVM
1276
+
1277
+ Getting swap quote
811
1278
 
812
1279
  ```typescript
813
- try {
814
- //Claim the swap funds - this will initiate 2 transactions
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);
1280
+ const swap = await swapper.swap(
1281
+ Tokens.BITCOIN.BTCLN, //Swap from BTC-LN
1282
+ Tokens.STARKNET.STRK, //Into specified destination token
1283
+ 10000n,
1284
+ SwapAmountType.EXACT_IN, //EXACT_IN, so we specify the input amount
1285
+ //Source LNURL-withdraw link
1286
+ "lnurl1dp68gurn8ghj7ampd3kx2ar0veekzar0wd5xjtnrdakj7tnhv4kxctttdehhwm30d3h82unvwqhkx6rfvdjx2ctvxyesuk0a27",
1287
+ signer.getAddress(), //Destination address
1288
+ {
1289
+ gasAmount: 1_000_000_000_000_000_000n //We can also request a gas drop on the destination chain (here requesting 1 STRK)
1290
+ }
1291
+ );
1292
+
1293
+ //Get the amount required to pay and fee
1294
+ const input: string = swap.getInputWithoutFee().toString(); //Input amount excluding fees
1295
+ const fee: string = swap.getFee().amountInSrcToken.toString(); //Fees paid on the output
1296
+ const inputWithFees: string = swap.getInput().toString(); //Total amount paid including fees
1297
+
1298
+ const output: string = swap.getOutput().toString(); //Total output amount
1299
+
1300
+ //Get swap expiration time
1301
+ const expiry: number = swap.getQuoteExpiry(); //Expiration time of the swap quote in UNIX milliseconds, swap needs to be initiated before this time
1302
+
1303
+ //Get pricing info
1304
+ const swapPrice = swap.getPriceInfo().swapPrice; //Price of the current swap (excluding fees)
1305
+ const marketPrice = swap.getPriceInfo().marketPrice; //Current market price
1306
+ const difference = swap.getPriceInfo().difference; //Difference between the swap price & current market price
1307
+ ```
1308
+
1309
+
1310
+ Executing the swap (simple)
1311
+
1312
+ ```typescript
1313
+ const automaticSettlementSuccess = await swap.execute(
1314
+ undefined, //No need to specify a wallet, we are sourcing the funds from LNURL-withdraw link
1315
+ { //Callbacks
1316
+ onSourceTransactionReceived: (sourceLnPaymentHash: string) => {
1317
+ //Lightning network payment received by the LP
1318
+ },
1319
+ onSwapSettled: (destinationClaimTxId: string) => {
1320
+ //Swap settled and funds received on destination
1321
+ }
822
1322
  }
823
- } catch(e) {
824
- //Error occurred while waiting for payment
1323
+ );
1324
+
1325
+ //In case the automatic swap settlement fails, we can settle it manually using the wallet of the destination chain
1326
+ if(!automaticSettlementSuccess) {
1327
+ await swap.claim(starknetSigner);
825
1328
  }
826
1329
  ```
827
1330
 
828
- or [sign and send transactions manually](#manually-signing-smart-chain-transactions)
1331
+
1332
+ <details>
1333
+ <summary>Manual swap execution (advanced)</summary>
1334
+
1335
+ - __1.__ Start listening to incoming lightning network payment (this also requests the payment from LNURL-withdraw service)
1336
+ ```typescript
1337
+ const success = await swap.waitForPayment();
1338
+ if(!success) {
1339
+ //Lightning network payment not received in time and quote expired
1340
+ return;
1341
+ }
1342
+ ```
1343
+
1344
+ - __2.__ Wait for the swap to be automatically settled
1345
+ ```typescript
1346
+ const automaticSettlementSuccess = await swap.waitTillClaimed(60);
1347
+ ```
1348
+
1349
+ - __3.__ In case the automatic swap settlement fails, we can settle it manually using the wallet of the destination chain
1350
+
1351
+ - __a.__ Claim with signer
1352
+ ```typescript
1353
+ if(!automaticSettlementSuccess) {
1354
+ await swap.claim(starknetSigner);
1355
+ }
1356
+ ```
1357
+
1358
+ - __b.__ Or get the transactions & [sign and send transaction manually](#manually-signing-smart-chain-transactions)
1359
+ ```typescript
1360
+ if(!automaticSettlementSuccess) {
1361
+ const txsClaim = await swap.txsClaim();
1362
+ //Sign and send these...
1363
+ ...
1364
+ }
1365
+ ```
1366
+
1367
+ </details>
829
1368
 
830
1369
  ### Getting state of the swap
831
1370
 
@@ -931,14 +1470,12 @@ Returns swaps that are ready to be claimed by the client, this can happen if cli
931
1470
  const claimableSolanaSwaps = await solanaSwapper.getClaimableSwaps("SOLANA", solanaSigner.getAddress());
932
1471
  //Claim all the claimable swaps
933
1472
  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
1473
  await swap.claim(solanaSigner);
936
1474
  }
937
1475
  //Get the swaps
938
1476
  const claimableStarknetSwaps = await solanaSwapper.getClaimableSwaps("STARKNET", starknetSigner.getAddress());
939
1477
  //Claim all the claimable swaps
940
1478
  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
1479
  await swap.claim(starknetSigner);
943
1480
  }
944
1481
  ```
@@ -1027,7 +1564,7 @@ After sending the transactions, you also need to make sure the SDK has enough ti
1027
1564
  ```typescript
1028
1565
  //Example for Solana
1029
1566
  const txns = await swap.txsCommit(); //Also works with txsClaim, txsRefund, txCommitAndClaim
1030
- txns.forEach(val => val.tx.sign(...val.signers));
1567
+ txns.forEach(val => if(val.signers.length>0) { val.tx.sign(...val.signers) });
1031
1568
  const signedTransactions = await solanaSigner.wallet.signAllTransactions(txns.map(val => val.tx));
1032
1569
  for(let tx of signedTransactions) {
1033
1570
  const res = await solanaRpc.sendRawTransaction(tx.serialize());
@@ -1042,6 +1579,13 @@ for(let tx of txns) {
1042
1579
  if(tx.type==="DEPLOY_ACCOUNT") await starknetSigner.account.deployAccount(tx.tx, tx.details);
1043
1580
  }
1044
1581
  await swap.waitTillCommited(); //Or other relevant waitTillClaimed, waitTillRefunded
1582
+
1583
+ //Example for EVM
1584
+ const txns = await swap.txsCommit(); //Also works with txsClaim, txsRefund, txCommitAndClaim
1585
+ for(let tx of txns) {
1586
+ await evmSigner.account.sendTransaction(tx);
1587
+ }
1588
+ await swap.waitTillCommited(); //Or other relevant waitTillClaimed, waitTillRefunded
1045
1589
  ```
1046
1590
 
1047
1591
  ### Additional swapper options