@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.
- package/README.md +58 -7
- package/package.json +4 -4
- package/src/_cjs/config.js +2 -1
- package/src/_cjs/config.js.map +1 -1
- package/src/_cjs/constants.js +2 -1
- package/src/_cjs/constants.js.map +1 -1
- package/src/_cjs/core/EVM/EVMStepExecutor.js +13 -20
- package/src/_cjs/core/EVM/EVMStepExecutor.js.map +1 -1
- package/src/_cjs/core/EVM/checkAllowance.js +8 -17
- package/src/_cjs/core/EVM/checkAllowance.js.map +1 -1
- package/src/_cjs/core/EVM/utils.js +1 -1
- package/src/_cjs/core/EVM/waitForTransactionReceipt.js +42 -0
- package/src/_cjs/core/EVM/waitForTransactionReceipt.js.map +1 -0
- package/src/_cjs/core/Solana/KeypairWalletAdapter.js +3 -3
- package/src/_cjs/core/Solana/KeypairWalletAdapter.js.map +1 -1
- package/src/_cjs/core/Solana/SolanaStepExecutor.js +18 -14
- package/src/_cjs/core/Solana/SolanaStepExecutor.js.map +1 -1
- package/src/_cjs/core/Solana/getSolanaBalance.js +1 -2
- package/src/_cjs/core/Solana/getSolanaBalance.js.map +1 -1
- package/src/_cjs/core/StatusManager.js +3 -3
- package/src/_cjs/core/StatusManager.js.map +1 -1
- package/src/_cjs/core/checkBalance.js +2 -3
- package/src/_cjs/core/checkBalance.js.map +1 -1
- package/src/_cjs/core/processMessages.js +61 -0
- package/src/_cjs/core/processMessages.js.map +1 -0
- package/src/_cjs/core/utils.js +6 -58
- package/src/_cjs/core/utils.js.map +1 -1
- package/src/_cjs/core/waitForReceivingTransaction.js +2 -2
- package/src/_cjs/core/waitForReceivingTransaction.js.map +1 -1
- package/src/_cjs/utils/errors.js +1 -0
- package/src/_cjs/utils/errors.js.map +1 -1
- package/src/_cjs/version.js +1 -1
- package/src/_cjs/version.js.map +1 -1
- package/src/_esm/config.js +2 -1
- package/src/_esm/config.js.map +1 -1
- package/src/_esm/constants.js +1 -0
- package/src/_esm/constants.js.map +1 -1
- package/src/_esm/core/EVM/EVMStepExecutor.js +13 -18
- package/src/_esm/core/EVM/EVMStepExecutor.js.map +1 -1
- package/src/_esm/core/EVM/checkAllowance.js +9 -18
- package/src/_esm/core/EVM/checkAllowance.js.map +1 -1
- package/src/_esm/core/EVM/utils.js +1 -1
- package/src/_esm/core/EVM/waitForTransactionReceipt.js +40 -0
- package/src/_esm/core/EVM/waitForTransactionReceipt.js.map +1 -0
- package/src/_esm/core/Solana/KeypairWalletAdapter.js +1 -1
- package/src/_esm/core/Solana/KeypairWalletAdapter.js.map +1 -1
- package/src/_esm/core/Solana/SolanaStepExecutor.js +20 -16
- package/src/_esm/core/Solana/SolanaStepExecutor.js.map +1 -1
- package/src/_esm/core/Solana/getSolanaBalance.js +2 -3
- package/src/_esm/core/Solana/getSolanaBalance.js.map +1 -1
- package/src/_esm/core/StatusManager.js +1 -1
- package/src/_esm/core/StatusManager.js.map +1 -1
- package/src/_esm/core/checkBalance.js +2 -3
- package/src/_esm/core/checkBalance.js.map +1 -1
- package/src/_esm/core/processMessages.js +58 -0
- package/src/_esm/core/processMessages.js.map +1 -0
- package/src/_esm/core/utils.js +7 -58
- package/src/_esm/core/utils.js.map +1 -1
- package/src/_esm/core/waitForReceivingTransaction.js +1 -1
- package/src/_esm/core/waitForReceivingTransaction.js.map +1 -1
- package/src/_esm/utils/errors.js +1 -0
- package/src/_esm/utils/errors.js.map +1 -1
- package/src/_esm/version.js +1 -1
- package/src/_esm/version.js.map +1 -1
- package/src/_types/config.d.ts.map +1 -1
- package/src/_types/constants.d.ts +1 -0
- package/src/_types/constants.d.ts.map +1 -1
- package/src/_types/core/EVM/EVMStepExecutor.d.ts.map +1 -1
- package/src/_types/core/EVM/checkAllowance.d.ts.map +1 -1
- package/src/_types/core/EVM/utils.d.ts +1 -1
- package/src/_types/core/EVM/waitForTransactionReceipt.d.ts +11 -0
- package/src/_types/core/EVM/waitForTransactionReceipt.d.ts.map +1 -0
- package/src/_types/core/Solana/SolanaStepExecutor.d.ts.map +1 -1
- package/src/_types/core/StatusManager.d.ts.map +1 -1
- package/src/_types/core/checkBalance.d.ts.map +1 -1
- package/src/_types/core/processMessages.d.ts +4 -0
- package/src/_types/core/processMessages.d.ts.map +1 -0
- package/src/_types/core/utils.d.ts +4 -5
- package/src/_types/core/utils.d.ts.map +1 -1
- package/src/_types/utils/errors.d.ts +2 -1
- package/src/_types/utils/errors.d.ts.map +1 -1
- package/src/_types/version.d.ts +1 -1
- package/src/_types/version.d.ts.map +1 -1
- package/src/config.ts +4 -1
- package/src/constants.ts +1 -0
- package/src/core/EVM/EVMStepExecutor.ts +22 -33
- package/src/core/EVM/checkAllowance.ts +10 -27
- package/src/core/EVM/utils.ts +1 -1
- package/src/core/EVM/waitForTransactionReceipt.ts +86 -0
- package/src/core/Solana/KeypairWalletAdapter.ts +1 -1
- package/src/core/Solana/SolanaStepExecutor.ts +30 -23
- package/src/core/Solana/getSolanaBalance.ts +2 -3
- package/src/core/StatusManager.ts +1 -1
- package/src/core/checkBalance.ts +2 -3
- package/src/core/processMessages.ts +81 -0
- package/src/core/utils.ts +9 -84
- package/src/core/waitForReceivingTransaction.ts +1 -1
- package/src/utils/errors.ts +1 -0
- package/src/version.ts +1 -1
package/src/_types/version.d.ts
CHANGED
|
@@ -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,
|
|
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
|
-
|
|
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
|
|
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
|
-
|
|
354
|
-
|
|
355
|
-
.
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
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
|
|
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
|
|
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,
|
|
3
|
-
import { maxUint256
|
|
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 {
|
|
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
|
-
|
|
137
|
-
|
|
138
|
-
|
|
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
|
-
|
|
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:
|
|
166
|
-
txLink: `${chain.metamask.blockExplorerUrls[0]}tx/${
|
|
148
|
+
txHash: transactionHash,
|
|
149
|
+
txLink: `${chain.metamask.blockExplorerUrls[0]}tx/${transactionHash}`,
|
|
167
150
|
})
|
|
168
151
|
}
|
package/src/core/EVM/utils.ts
CHANGED
|
@@ -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
|
|
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 {
|
|
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 =
|
|
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.
|
|
187
|
-
lastValidBlockHeight: blockhashResult.
|
|
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
|
-
|
|
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.
|
|
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 {
|
|
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[
|
|
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<
|
package/src/core/checkBalance.ts
CHANGED
|
@@ -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
|
|
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 './
|
|
11
|
+
import { getSubstatusMessage } from './processMessages.js'
|
|
12
12
|
|
|
13
13
|
const TRANSACTION_HASH_OBSERVERS: Record<string, Promise<StatusResponse>> = {}
|
|
14
14
|
|