@lifi/sdk 3.0.0 → 3.0.2-beta.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (99) hide show
  1. package/README.md +58 -7
  2. package/package.json +4 -4
  3. package/src/_cjs/config.js +2 -1
  4. package/src/_cjs/config.js.map +1 -1
  5. package/src/_cjs/constants.js +2 -1
  6. package/src/_cjs/constants.js.map +1 -1
  7. package/src/_cjs/core/EVM/EVMStepExecutor.js +13 -20
  8. package/src/_cjs/core/EVM/EVMStepExecutor.js.map +1 -1
  9. package/src/_cjs/core/EVM/checkAllowance.js +8 -17
  10. package/src/_cjs/core/EVM/checkAllowance.js.map +1 -1
  11. package/src/_cjs/core/EVM/utils.js +1 -1
  12. package/src/_cjs/core/EVM/waitForTransactionReceipt.js +42 -0
  13. package/src/_cjs/core/EVM/waitForTransactionReceipt.js.map +1 -0
  14. package/src/_cjs/core/Solana/KeypairWalletAdapter.js +3 -3
  15. package/src/_cjs/core/Solana/KeypairWalletAdapter.js.map +1 -1
  16. package/src/_cjs/core/Solana/SolanaStepExecutor.js +18 -14
  17. package/src/_cjs/core/Solana/SolanaStepExecutor.js.map +1 -1
  18. package/src/_cjs/core/Solana/getSolanaBalance.js +1 -2
  19. package/src/_cjs/core/Solana/getSolanaBalance.js.map +1 -1
  20. package/src/_cjs/core/StatusManager.js +3 -3
  21. package/src/_cjs/core/StatusManager.js.map +1 -1
  22. package/src/_cjs/core/checkBalance.js +2 -3
  23. package/src/_cjs/core/checkBalance.js.map +1 -1
  24. package/src/_cjs/core/processMessages.js +61 -0
  25. package/src/_cjs/core/processMessages.js.map +1 -0
  26. package/src/_cjs/core/utils.js +6 -58
  27. package/src/_cjs/core/utils.js.map +1 -1
  28. package/src/_cjs/core/waitForReceivingTransaction.js +2 -2
  29. package/src/_cjs/core/waitForReceivingTransaction.js.map +1 -1
  30. package/src/_cjs/utils/errors.js +1 -0
  31. package/src/_cjs/utils/errors.js.map +1 -1
  32. package/src/_cjs/version.js +1 -1
  33. package/src/_cjs/version.js.map +1 -1
  34. package/src/_esm/config.js +2 -1
  35. package/src/_esm/config.js.map +1 -1
  36. package/src/_esm/constants.js +1 -0
  37. package/src/_esm/constants.js.map +1 -1
  38. package/src/_esm/core/EVM/EVMStepExecutor.js +13 -18
  39. package/src/_esm/core/EVM/EVMStepExecutor.js.map +1 -1
  40. package/src/_esm/core/EVM/checkAllowance.js +9 -18
  41. package/src/_esm/core/EVM/checkAllowance.js.map +1 -1
  42. package/src/_esm/core/EVM/utils.js +1 -1
  43. package/src/_esm/core/EVM/waitForTransactionReceipt.js +40 -0
  44. package/src/_esm/core/EVM/waitForTransactionReceipt.js.map +1 -0
  45. package/src/_esm/core/Solana/KeypairWalletAdapter.js +1 -1
  46. package/src/_esm/core/Solana/KeypairWalletAdapter.js.map +1 -1
  47. package/src/_esm/core/Solana/SolanaStepExecutor.js +20 -16
  48. package/src/_esm/core/Solana/SolanaStepExecutor.js.map +1 -1
  49. package/src/_esm/core/Solana/getSolanaBalance.js +2 -3
  50. package/src/_esm/core/Solana/getSolanaBalance.js.map +1 -1
  51. package/src/_esm/core/StatusManager.js +1 -1
  52. package/src/_esm/core/StatusManager.js.map +1 -1
  53. package/src/_esm/core/checkBalance.js +2 -3
  54. package/src/_esm/core/checkBalance.js.map +1 -1
  55. package/src/_esm/core/processMessages.js +58 -0
  56. package/src/_esm/core/processMessages.js.map +1 -0
  57. package/src/_esm/core/utils.js +7 -58
  58. package/src/_esm/core/utils.js.map +1 -1
  59. package/src/_esm/core/waitForReceivingTransaction.js +1 -1
  60. package/src/_esm/core/waitForReceivingTransaction.js.map +1 -1
  61. package/src/_esm/utils/errors.js +1 -0
  62. package/src/_esm/utils/errors.js.map +1 -1
  63. package/src/_esm/version.js +1 -1
  64. package/src/_esm/version.js.map +1 -1
  65. package/src/_types/config.d.ts.map +1 -1
  66. package/src/_types/constants.d.ts +1 -0
  67. package/src/_types/constants.d.ts.map +1 -1
  68. package/src/_types/core/EVM/EVMStepExecutor.d.ts.map +1 -1
  69. package/src/_types/core/EVM/checkAllowance.d.ts.map +1 -1
  70. package/src/_types/core/EVM/utils.d.ts +1 -1
  71. package/src/_types/core/EVM/waitForTransactionReceipt.d.ts +11 -0
  72. package/src/_types/core/EVM/waitForTransactionReceipt.d.ts.map +1 -0
  73. package/src/_types/core/Solana/SolanaStepExecutor.d.ts.map +1 -1
  74. package/src/_types/core/StatusManager.d.ts.map +1 -1
  75. package/src/_types/core/checkBalance.d.ts.map +1 -1
  76. package/src/_types/core/processMessages.d.ts +4 -0
  77. package/src/_types/core/processMessages.d.ts.map +1 -0
  78. package/src/_types/core/utils.d.ts +4 -5
  79. package/src/_types/core/utils.d.ts.map +1 -1
  80. package/src/_types/utils/errors.d.ts +2 -1
  81. package/src/_types/utils/errors.d.ts.map +1 -1
  82. package/src/_types/version.d.ts +1 -1
  83. package/src/_types/version.d.ts.map +1 -1
  84. package/src/config.ts +4 -1
  85. package/src/constants.ts +1 -0
  86. package/src/core/EVM/EVMStepExecutor.ts +22 -33
  87. package/src/core/EVM/checkAllowance.ts +10 -27
  88. package/src/core/EVM/utils.ts +1 -1
  89. package/src/core/EVM/waitForTransactionReceipt.ts +86 -0
  90. package/src/core/Solana/KeypairWalletAdapter.ts +1 -1
  91. package/src/core/Solana/SolanaStepExecutor.ts +30 -23
  92. package/src/core/Solana/getSolanaBalance.ts +2 -3
  93. package/src/core/StatusManager.ts +1 -1
  94. package/src/core/checkBalance.ts +2 -3
  95. package/src/core/processMessages.ts +81 -0
  96. package/src/core/utils.ts +9 -84
  97. package/src/core/waitForReceivingTransaction.ts +1 -1
  98. package/src/utils/errors.ts +1 -0
  99. package/src/version.ts +1 -1
@@ -1,3 +1,3 @@
1
1
  export declare const name = "@lifi/sdk";
2
- export declare const version = "3.0.0";
2
+ export declare const version = "3.0.2-beta.0";
3
3
  //# sourceMappingURL=version.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"version.d.ts","sourceRoot":"","sources":["../version.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,IAAI,cAAc,CAAA;AAC/B,eAAO,MAAM,OAAO,UAAU,CAAA"}
1
+ {"version":3,"file":"version.d.ts","sourceRoot":"","sources":["../version.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,IAAI,cAAc,CAAA;AAC/B,eAAO,MAAM,OAAO,iBAAiB,CAAA"}
package/src/config.ts CHANGED
@@ -77,7 +77,10 @@ export const config = (() => {
77
77
  if (!_config.rpcUrls[chainId]?.length) {
78
78
  _config.rpcUrls[chainId] = Array.from(urls)
79
79
  } else {
80
- _config.rpcUrls[chainId]?.push(...urls)
80
+ const filteredUrls = urls.filter(
81
+ (url) => !_config.rpcUrls[chainId]?.includes(url)
82
+ )
83
+ _config.rpcUrls[chainId]?.push(...filteredUrls)
81
84
  }
82
85
  }
83
86
  },
package/src/constants.ts CHANGED
@@ -2,3 +2,4 @@ export const AddressZero = '0x0000000000000000000000000000000000000000'
2
2
  export const AlternativeAddressZero =
3
3
  '0xeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee'
4
4
  export const wrappedSolAddress = 'So11111111111111111111111111111111111111112'
5
+ export const SolSystemProgram = '11111111111111111111111111111111'
@@ -6,7 +6,6 @@ import type {
6
6
  import type {
7
7
  Hash,
8
8
  PublicClient,
9
- ReplacementReason,
10
9
  SendTransactionParameters,
11
10
  WalletClient,
12
11
  } from 'viem'
@@ -23,19 +22,20 @@ import {
23
22
  } from '../../utils/index.js'
24
23
  import { BaseStepExecutor } from '../BaseStepExecutor.js'
25
24
  import { checkBalance } from '../checkBalance.js'
25
+ import { getSubstatusMessage } from '../processMessages.js'
26
26
  import { stepComparison } from '../stepComparison.js'
27
27
  import type {
28
28
  LiFiStepExtended,
29
29
  StepExecutorOptions,
30
30
  TransactionParameters,
31
31
  } from '../types.js'
32
- import { getSubstatusMessage } from '../utils.js'
33
32
  import { waitForReceivingTransaction } from '../waitForReceivingTransaction.js'
34
33
  import { checkAllowance } from './checkAllowance.js'
35
34
  import { updateMultisigRouteProcess } from './multisig.js'
36
35
  import { switchChain } from './switchChain.js'
37
36
  import type { MultisigConfig, MultisigTransaction } from './types.js'
38
- import { getMaxPriorityFeePerGas, retryCount, retryDelay } from './utils.js'
37
+ import { getMaxPriorityFeePerGas } from './utils.js'
38
+ import { waitForTransactionReceipt } from './waitForTransactionReceipt.js'
39
39
 
40
40
  export interface EVMStepExecutorOptions extends StepExecutorOptions {
41
41
  walletClient: WalletClient
@@ -350,40 +350,23 @@ export class EVMStepExecutor extends BaseStepExecutor {
350
350
  }
351
351
  }
352
352
 
353
- let replacementReason: ReplacementReason | undefined
354
- const transactionReceipt = await this.walletClient
355
- .extend(publicActions)
356
- .waitForTransactionReceipt({
357
- hash: txHash,
358
- onReplaced: (response) => {
359
- replacementReason = response.reason
360
- this.statusManager.updateProcess(step, process.type, 'PENDING', {
361
- txHash: response.transaction.hash,
362
- txLink: `${fromChain.metamask.blockExplorerUrls[0]}tx/${response.transaction.hash}`,
363
- })
364
- },
365
- retryCount,
366
- retryDelay,
367
- })
368
-
369
- if (transactionReceipt.status === 'reverted') {
370
- throw new TransactionError(
371
- LiFiErrorCode.TransactionFailed,
372
- 'Transaction was reverted.'
373
- )
374
- }
375
- if (replacementReason === 'cancelled') {
376
- throw new TransactionError(
377
- LiFiErrorCode.TransactionCanceled,
378
- 'User canceled transaction.'
379
- )
380
- }
353
+ const transactionReceipt = await waitForTransactionReceipt({
354
+ walletClient: this.walletClient,
355
+ chainId: fromChain.id,
356
+ txHash,
357
+ onReplaced: (response) => {
358
+ this.statusManager.updateProcess(step, process.type, 'PENDING', {
359
+ txHash: response.transaction.hash,
360
+ txLink: `${fromChain.metamask.blockExplorerUrls[0]}tx/${response.transaction.hash}`,
361
+ })
362
+ },
363
+ })
381
364
 
382
365
  // if it's multisig wallet client and the process is in ACTION_REQUIRED
383
366
  // then signatures are still needed
384
367
  if (isMultisigWalletClient && process.status === 'ACTION_REQUIRED') {
385
368
  await updateMultisigRouteProcess(
386
- transactionReceipt.transactionHash,
369
+ transactionReceipt?.transactionHash || txHash,
387
370
  step,
388
371
  process.type,
389
372
  fromChain,
@@ -392,7 +375,13 @@ export class EVMStepExecutor extends BaseStepExecutor {
392
375
  )
393
376
  }
394
377
 
395
- if (!isMultisigWalletClient) {
378
+ // Update pending process if the transaction hash from the receipt is different.
379
+ // This might happen if the transaction was replaced.
380
+ if (
381
+ !isMultisigWalletClient &&
382
+ transactionReceipt?.transactionHash &&
383
+ transactionReceipt.transactionHash !== txHash
384
+ ) {
396
385
  process = this.statusManager.updateProcess(
397
386
  step,
398
387
  process.type,
@@ -1,13 +1,12 @@
1
1
  import type { Chain, LiFiStep, Process, ProcessType } from '@lifi/types'
2
- import type { Address, Hash, ReplacementReason, WalletClient } from 'viem'
3
- import { maxUint256, publicActions } from 'viem'
4
- import { LiFiErrorCode, TransactionError } from '../../utils/index.js'
2
+ import type { Address, Hash, WalletClient } from 'viem'
3
+ import { maxUint256 } from 'viem'
5
4
  import { parseError } from '../../utils/parseError.js'
6
5
  import type { StatusManager } from '../StatusManager.js'
7
6
  import type { ExecutionOptions } from '../types.js'
8
7
  import { getAllowance } from './getAllowance.js'
9
8
  import { setAllowance } from './setAllowance.js'
10
- import { retryCount, retryDelay } from './utils.js'
9
+ import { waitForTransactionReceipt } from './waitForTransactionReceipt.js'
11
10
 
12
11
  export const checkAllowance = async (
13
12
  chain: Chain,
@@ -127,42 +126,26 @@ const waitForApprovalTransaction = async (
127
126
  chain: Chain,
128
127
  statusManager: StatusManager
129
128
  ) => {
130
- const client = walletClient.extend(publicActions)
131
129
  statusManager.updateProcess(step, processType, 'PENDING', {
132
130
  txHash,
133
131
  txLink: `${chain.metamask.blockExplorerUrls[0]}tx/${txHash}`,
134
132
  })
135
133
 
136
- let replacementReason: ReplacementReason | undefined
137
- const transactionReceipt = await client.waitForTransactionReceipt({
138
- hash: txHash,
134
+ const transactionReceipt = await waitForTransactionReceipt({
135
+ walletClient,
136
+ chainId: chain.id,
137
+ txHash: txHash,
139
138
  onReplaced(response) {
140
- replacementReason = response.reason
141
139
  statusManager.updateProcess(step, processType, 'PENDING', {
142
140
  txHash: response.transaction.hash,
143
141
  txLink: `${chain.metamask.blockExplorerUrls[0]}tx/${response.transaction.hash}`,
144
142
  })
145
143
  },
146
- retryCount,
147
- retryDelay,
148
144
  })
149
145
 
150
- if (transactionReceipt.status === 'reverted') {
151
- throw new TransactionError(
152
- LiFiErrorCode.TransactionFailed,
153
- 'Transaction was reverted.'
154
- )
155
- }
156
-
157
- if (replacementReason === 'cancelled') {
158
- throw new TransactionError(
159
- LiFiErrorCode.TransactionCanceled,
160
- 'User canceled transaction.'
161
- )
162
- }
163
-
146
+ const transactionHash = transactionReceipt?.transactionHash || txHash
164
147
  statusManager.updateProcess(step, processType, 'DONE', {
165
- txHash: transactionReceipt.transactionHash,
166
- txLink: `${chain.metamask.blockExplorerUrls[0]}tx/${transactionReceipt.transactionHash}`,
148
+ txHash: transactionHash,
149
+ txLink: `${chain.metamask.blockExplorerUrls[0]}tx/${transactionHash}`,
167
150
  })
168
151
  }
@@ -45,4 +45,4 @@ export const getMulticallAddress = async (
45
45
  export const retryDelay = ({ count }: { count: number; error: Error }) =>
46
46
  Math.min(~~(1 << count) * 200, 3000)
47
47
 
48
- export const retryCount = 20
48
+ export const retryCount = 30
@@ -0,0 +1,86 @@
1
+ import type { ChainId } from '@lifi/types'
2
+ import type {
3
+ Chain,
4
+ Hash,
5
+ PublicClient,
6
+ ReplacementReason,
7
+ ReplacementReturnType,
8
+ TransactionReceipt,
9
+ WalletClient,
10
+ } from 'viem'
11
+ import { publicActions } from 'viem'
12
+ import { LiFiErrorCode, TransactionError } from '../../utils/index.js'
13
+ import { getPublicClient } from './publicClient.js'
14
+ import { retryCount, retryDelay } from './utils.js'
15
+
16
+ interface WaitForTransactionReceiptProps {
17
+ walletClient: WalletClient
18
+ chainId: ChainId
19
+ txHash: Hash
20
+ onReplaced?: (response: ReplacementReturnType<Chain | undefined>) => void
21
+ }
22
+
23
+ export async function waitForTransactionReceipt({
24
+ walletClient,
25
+ chainId,
26
+ txHash,
27
+ onReplaced,
28
+ }: WaitForTransactionReceiptProps): Promise<TransactionReceipt | undefined> {
29
+ let { transactionReceipt, replacementReason } = await waitForReceipt(
30
+ walletClient.extend(publicActions),
31
+ txHash,
32
+ onReplaced
33
+ )
34
+
35
+ if (!transactionReceipt?.status) {
36
+ const publicClient = await getPublicClient(chainId)
37
+ const result = await waitForReceipt(publicClient, txHash, onReplaced)
38
+ transactionReceipt = result.transactionReceipt
39
+ replacementReason = result.replacementReason
40
+ }
41
+
42
+ if (transactionReceipt?.status === 'reverted') {
43
+ throw new TransactionError(
44
+ LiFiErrorCode.TransactionFailed,
45
+ 'Transaction was reverted.'
46
+ )
47
+ }
48
+ if (replacementReason === 'cancelled') {
49
+ throw new TransactionError(
50
+ LiFiErrorCode.TransactionCanceled,
51
+ 'User canceled transaction.'
52
+ )
53
+ }
54
+
55
+ return transactionReceipt
56
+ }
57
+
58
+ async function waitForReceipt(
59
+ client: PublicClient | WalletClient,
60
+ txHash: Hash,
61
+ onReplaced?: (response: ReplacementReturnType<Chain | undefined>) => void
62
+ ): Promise<{
63
+ transactionReceipt?: TransactionReceipt
64
+ replacementReason?: ReplacementReason
65
+ }> {
66
+ let replacementReason: ReplacementReason | undefined
67
+ let transactionReceipt: TransactionReceipt | undefined
68
+
69
+ try {
70
+ transactionReceipt = await (
71
+ client as PublicClient
72
+ ).waitForTransactionReceipt({
73
+ hash: txHash,
74
+ onReplaced: (response) => {
75
+ replacementReason = response.reason
76
+ onReplaced?.(response)
77
+ },
78
+ retryCount,
79
+ retryDelay,
80
+ })
81
+ } catch (error) {
82
+ // We can ignore errors from waitForTransactionReceipt as we have a status check fallback
83
+ }
84
+
85
+ return { transactionReceipt, replacementReason }
86
+ }
@@ -16,7 +16,7 @@ import type {
16
16
  VersionedTransaction,
17
17
  } from '@solana/web3.js'
18
18
  import { Keypair } from '@solana/web3.js'
19
- import * as bs58 from 'bs58'
19
+ import bs58 from 'bs58'
20
20
 
21
21
  export const KeypairWalletName =
22
22
  'Keypair Wallet' as WalletName<'Keypair Wallet'>
@@ -1,6 +1,7 @@
1
1
  import type { ExtendedTransactionInfo, FullStatusData } from '@lifi/types'
2
2
  import { type SignerWalletAdapter } from '@solana/wallet-adapter-base'
3
3
  import {
4
+ TransactionExpiredBlockheightExceededError,
4
5
  VersionedTransaction,
5
6
  type SendOptions,
6
7
  type SignatureResult,
@@ -16,13 +17,14 @@ import {
16
17
  } from '../../utils/index.js'
17
18
  import { BaseStepExecutor } from '../BaseStepExecutor.js'
18
19
  import { checkBalance } from '../checkBalance.js'
20
+ import { getSubstatusMessage } from '../processMessages.js'
19
21
  import { stepComparison } from '../stepComparison.js'
20
22
  import type {
21
23
  LiFiStepExtended,
22
24
  StepExecutorOptions,
23
25
  TransactionParameters,
24
26
  } from '../types.js'
25
- import { getSubstatusMessage } from '../utils.js'
27
+ import { sleep } from '../utils.js'
26
28
  import { waitForReceivingTransaction } from '../waitForReceivingTransaction.js'
27
29
  import { getSolanaConnection } from './connection.js'
28
30
 
@@ -30,7 +32,7 @@ export interface SolanaStepExecutorOptions extends StepExecutorOptions {
30
32
  walletAdapter: SignerWalletAdapter
31
33
  }
32
34
 
33
- const TX_RETRY_INTERVAL = 500
35
+ const TX_RETRY_INTERVAL = 1000
34
36
  // https://solana.com/docs/advanced/confirmation
35
37
  const TIMEOUT_PERIOD = 60_000
36
38
 
@@ -117,6 +119,10 @@ export class SolanaStepExecutor extends BaseStepExecutor {
117
119
  data: step.transactionRequest.data,
118
120
  }
119
121
 
122
+ const blockhashResult = await connection.getLatestBlockhash({
123
+ commitment: 'confirmed',
124
+ })
125
+
120
126
  if (this.executionOptions?.updateTransactionRequestHook) {
121
127
  const customizedTransactionRequest: TransactionParameters =
122
128
  await this.executionOptions.updateTransactionRequestHook({
@@ -141,14 +147,6 @@ export class SolanaStepExecutor extends BaseStepExecutor {
141
147
  base64ToUint8Array(transactionRequest.data)
142
148
  )
143
149
 
144
- const blockhashResult = await connection.getLatestBlockhashAndContext({
145
- commitment: 'confirmed',
146
- })
147
-
148
- // Update transaction recent blockhash with the latest blockhash
149
- versionedTransaction.message.recentBlockhash =
150
- blockhashResult.value.blockhash
151
-
152
150
  this.checkWalletAdapter(step)
153
151
 
154
152
  const signedTx =
@@ -179,12 +177,14 @@ export class SolanaStepExecutor extends BaseStepExecutor {
179
177
  // In the following section, we wait and constantly check for the transaction to be confirmed
180
178
  // and resend the transaction if it is not confirmed within a certain time interval
181
179
  // thus handling tx retries on the client side rather than relying on the RPC
180
+ const abortController = new AbortController()
182
181
  const confirmTransactionPromise = connection
183
182
  .confirmTransaction(
184
183
  {
185
184
  signature: txSignature,
186
- blockhash: blockhashResult.value.blockhash,
187
- lastValidBlockHeight: blockhashResult.value.lastValidBlockHeight,
185
+ blockhash: blockhashResult.blockhash,
186
+ lastValidBlockHeight: blockhashResult.lastValidBlockHeight,
187
+ abortSignal: abortController.signal,
188
188
  },
189
189
  'confirmed'
190
190
  )
@@ -194,29 +194,36 @@ export class SolanaStepExecutor extends BaseStepExecutor {
194
194
  const startTime = Date.now()
195
195
 
196
196
  while (!confirmedTx && Date.now() - startTime <= TIMEOUT_PERIOD) {
197
+ await connection.sendRawTransaction(
198
+ signedTx.serialize(),
199
+ rawTransactionOptions
200
+ )
197
201
  confirmedTx = await Promise.race([
198
202
  confirmTransactionPromise,
199
- new Promise<null>((resolve) =>
200
- setTimeout(() => {
201
- resolve(null)
202
- }, TX_RETRY_INTERVAL)
203
- ),
203
+ sleep(TX_RETRY_INTERVAL),
204
204
  ])
205
205
  if (confirmedTx) {
206
206
  break
207
207
  }
208
-
209
- await connection.sendRawTransaction(
210
- signedTx.serialize(),
211
- rawTransactionOptions
212
- )
213
208
  }
214
209
 
210
+ // Stop waiting for tx confirmation
211
+ abortController.abort()
212
+
215
213
  if (confirmedTx?.err) {
216
214
  const reason =
217
215
  typeof confirmedTx.err === 'object'
218
216
  ? JSON.stringify(confirmedTx.err)
219
217
  : confirmedTx.err
218
+ if (
219
+ confirmedTx.err instanceof
220
+ TransactionExpiredBlockheightExceededError
221
+ ) {
222
+ throw new TransactionError(
223
+ LiFiErrorCode.TransactionExpired,
224
+ `${reason}`
225
+ )
226
+ }
220
227
  throw new TransactionError(
221
228
  LiFiErrorCode.TransactionFailed,
222
229
  `Transaction failed: ${reason}`
@@ -225,7 +232,7 @@ export class SolanaStepExecutor extends BaseStepExecutor {
225
232
 
226
233
  if (!confirmedTx) {
227
234
  throw new TransactionError(
228
- LiFiErrorCode.TransactionFailed,
235
+ LiFiErrorCode.TransactionExpired,
229
236
  'Failed to land the transaction'
230
237
  )
231
238
  }
@@ -1,6 +1,6 @@
1
1
  import type { ChainId, Token, TokenAmount } from '@lifi/types'
2
2
  import { PublicKey } from '@solana/web3.js'
3
- import { wrappedSolAddress } from '../../constants.js'
3
+ import { SolSystemProgram } from '../../constants.js'
4
4
  import { getSolanaConnection } from './connection.js'
5
5
  import { TokenProgramAddress } from './types.js'
6
6
 
@@ -53,8 +53,7 @@ const getSolanaBalanceDefault = async (
53
53
  {} as Record<string, bigint>
54
54
  )
55
55
  : {}
56
- walletTokenAmounts[wrappedSolAddress] ??= 0n
57
- walletTokenAmounts[wrappedSolAddress] += solBalance
56
+ walletTokenAmounts[SolSystemProgram] = solBalance
58
57
  const tokenAmounts: TokenAmount[] = tokens.map((token) => {
59
58
  if (walletTokenAmounts[token.address]) {
60
59
  return {
@@ -7,8 +7,8 @@ import type {
7
7
  ProcessType,
8
8
  } from '@lifi/types'
9
9
  import { executionState } from './executionState.js'
10
+ import { getProcessMessage } from './processMessages.js'
10
11
  import type { LiFiStepExtended } from './types.js'
11
- import { getProcessMessage } from './utils.js'
12
12
 
13
13
  type OptionalParameters = Partial<
14
14
  Pick<
@@ -2,6 +2,7 @@ import type { LiFiStep } from '@lifi/types'
2
2
  import { formatUnits } from 'viem'
3
3
  import { getTokenBalance } from '../services/balance.js'
4
4
  import { BalanceError } from '../utils/errors.js'
5
+ import { sleep } from './utils.js'
5
6
 
6
7
  export const checkBalance = async (
7
8
  walletAddress: string,
@@ -15,9 +16,7 @@ export const checkBalance = async (
15
16
 
16
17
  if (currentBalance < neededBalance) {
17
18
  if (depth <= 3) {
18
- await new Promise((resolve) => {
19
- setTimeout(resolve, 200)
20
- })
19
+ await sleep(200)
21
20
  await checkBalance(walletAddress, step, depth + 1)
22
21
  } else if (
23
22
  (neededBalance * BigInt((1 - step.action.slippage) * 1_000_000_000)) /
@@ -0,0 +1,81 @@
1
+ import {
2
+ type ProcessStatus,
3
+ type ProcessType,
4
+ type StatusMessage,
5
+ type Substatus,
6
+ } from '@lifi/types'
7
+
8
+ const processMessages: Record<
9
+ ProcessType,
10
+ Partial<Record<ProcessStatus, string>>
11
+ > = {
12
+ TOKEN_ALLOWANCE: {
13
+ STARTED: 'Setting token allowance.',
14
+ PENDING: 'Waiting for token allowance.',
15
+ DONE: 'Token allowance set.',
16
+ },
17
+ SWITCH_CHAIN: {
18
+ PENDING: 'Chain switch required.',
19
+ DONE: 'Chain switched successfully.',
20
+ },
21
+ SWAP: {
22
+ STARTED: 'Preparing swap transaction.',
23
+ ACTION_REQUIRED: 'Please sign the transaction.',
24
+ PENDING: 'Waiting for swap transaction.',
25
+ DONE: 'Swap completed.',
26
+ },
27
+ CROSS_CHAIN: {
28
+ STARTED: 'Preparing bridge transaction.',
29
+ ACTION_REQUIRED: 'Please sign the transaction.',
30
+ PENDING: 'Waiting for bridge transaction.',
31
+ DONE: 'Bridge transaction confirmed.',
32
+ },
33
+ RECEIVING_CHAIN: {
34
+ PENDING: 'Waiting for destination chain.',
35
+ DONE: 'Bridge completed.',
36
+ },
37
+ TRANSACTION: {},
38
+ }
39
+ const substatusMessages: Record<
40
+ StatusMessage,
41
+ Partial<Record<Substatus, string>>
42
+ > = {
43
+ PENDING: {
44
+ BRIDGE_NOT_AVAILABLE: 'Bridge communication is temporarily unavailable.',
45
+ CHAIN_NOT_AVAILABLE: 'RPC communication is temporarily unavailable.',
46
+ UNKNOWN_ERROR:
47
+ 'An unexpected error occurred. Please seek assistance in the LI.FI discord server.',
48
+ WAIT_SOURCE_CONFIRMATIONS:
49
+ 'The bridge deposit has been received. The bridge is waiting for more confirmations to start the off-chain logic.',
50
+ WAIT_DESTINATION_TRANSACTION:
51
+ 'The bridge off-chain logic is being executed. Wait for the transaction to appear on the destination chain.',
52
+ },
53
+ DONE: {
54
+ PARTIAL:
55
+ 'Some of the received tokens are not the requested destination tokens.',
56
+ REFUNDED: 'The tokens were refunded to the sender address.',
57
+ COMPLETED: 'The transfer is complete.',
58
+ },
59
+ FAILED: {},
60
+ INVALID: {},
61
+ NOT_FOUND: {},
62
+ }
63
+
64
+ export function getProcessMessage(
65
+ type: ProcessType,
66
+ status: ProcessStatus
67
+ ): string | undefined {
68
+ const processMessage = processMessages[type][status]
69
+ return processMessage
70
+ }
71
+
72
+ export function getSubstatusMessage(
73
+ status: StatusMessage,
74
+ substatus?: Substatus
75
+ ): string | undefined {
76
+ if (!substatus) {
77
+ return
78
+ }
79
+ const message = substatusMessages[status][substatus]
80
+ return message
81
+ }
package/src/core/utils.ts CHANGED
@@ -1,92 +1,11 @@
1
- import {
2
- type LiFiStep,
3
- type ProcessStatus,
4
- type ProcessType,
5
- type StatusMessage,
6
- type Substatus,
7
- } from '@lifi/types'
8
-
9
- const processMessages: Record<
10
- ProcessType,
11
- Partial<Record<ProcessStatus, string>>
12
- > = {
13
- TOKEN_ALLOWANCE: {
14
- STARTED: 'Setting token allowance.',
15
- PENDING: 'Waiting for token allowance.',
16
- DONE: 'Token allowance set.',
17
- },
18
- SWITCH_CHAIN: {
19
- PENDING: 'Chain switch required.',
20
- DONE: 'Chain switched successfully.',
21
- },
22
- SWAP: {
23
- STARTED: 'Preparing swap transaction.',
24
- ACTION_REQUIRED: 'Please sign the transaction.',
25
- PENDING: 'Waiting for swap transaction.',
26
- DONE: 'Swap completed.',
27
- },
28
- CROSS_CHAIN: {
29
- STARTED: 'Preparing bridge transaction.',
30
- ACTION_REQUIRED: 'Please sign the transaction.',
31
- PENDING: 'Waiting for bridge transaction.',
32
- DONE: 'Bridge transaction confirmed.',
33
- },
34
- RECEIVING_CHAIN: {
35
- PENDING: 'Waiting for destination chain.',
36
- DONE: 'Bridge completed.',
37
- },
38
- TRANSACTION: {},
39
- }
40
- const substatusMessages: Record<
41
- StatusMessage,
42
- Partial<Record<Substatus, string>>
43
- > = {
44
- PENDING: {
45
- BRIDGE_NOT_AVAILABLE: 'Bridge communication is temporarily unavailable.',
46
- CHAIN_NOT_AVAILABLE: 'RPC communication is temporarily unavailable.',
47
- UNKNOWN_ERROR:
48
- 'An unexpected error occurred. Please seek assistance in the LI.FI discord server.',
49
- WAIT_SOURCE_CONFIRMATIONS:
50
- 'The bridge deposit has been received. The bridge is waiting for more confirmations to start the off-chain logic.',
51
- WAIT_DESTINATION_TRANSACTION:
52
- 'The bridge off-chain logic is being executed. Wait for the transaction to appear on the destination chain.',
53
- },
54
- DONE: {
55
- PARTIAL:
56
- 'Some of the received tokens are not the requested destination tokens.',
57
- REFUNDED: 'The tokens were refunded to the sender address.',
58
- COMPLETED: 'The transfer is complete.',
59
- },
60
- FAILED: {},
61
- INVALID: {},
62
- NOT_FOUND: {},
63
- }
64
-
65
- export function getProcessMessage(
66
- type: ProcessType,
67
- status: ProcessStatus
68
- ): string | undefined {
69
- const processMessage = processMessages[type][status]
70
- return processMessage
71
- }
72
-
73
- export function getSubstatusMessage(
74
- status: StatusMessage,
75
- substatus?: Substatus
76
- ): string | undefined {
77
- if (!substatus) {
78
- return
79
- }
80
- const message = substatusMessages[status][substatus]
81
- return message
82
- }
1
+ import { type LiFiStep } from '@lifi/types'
83
2
 
84
3
  /**
85
4
  * Used to check if changed exchange rate is in the range of slippage threshold.
86
5
  * We use a slippage value as a threshold to trigger the rate change hook.
87
6
  * This can result in almost doubled slippage for the user and need to be revisited.
88
- * @param oldStep
89
- * @param newStep
7
+ * @param oldStep - old step
8
+ * @param newStep - new step
90
9
  * @returns Boolean
91
10
  */
92
11
  export function checkStepSlippageThreshold(
@@ -106,3 +25,9 @@ export function checkStepSlippageThreshold(
106
25
  }
107
26
  return actualSlippage <= setSlippage
108
27
  }
28
+
29
+ export function sleep(ms: number): Promise<null> {
30
+ return new Promise((resolve) => {
31
+ setTimeout(() => resolve(null), ms)
32
+ })
33
+ }
@@ -8,7 +8,7 @@ import { getStatus } from '../services/api.js'
8
8
  import { ServerError } from '../utils/errors.js'
9
9
  import { repeatUntilDone } from '../utils/utils.js'
10
10
  import type { StatusManager } from './StatusManager.js'
11
- import { getSubstatusMessage } from './utils.js'
11
+ import { getSubstatusMessage } from './processMessages.js'
12
12
 
13
13
  const TRANSACTION_HASH_OBSERVERS: Record<string, Promise<StatusResponse>> = {}
14
14