@lifi/sdk 3.4.2 → 3.5.0-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/package.json +2 -2
- package/src/_cjs/constants.js +4 -2
- package/src/_cjs/constants.js.map +1 -1
- package/src/_cjs/core/EVM/EVM.js +0 -4
- package/src/_cjs/core/EVM/EVM.js.map +1 -1
- package/src/_cjs/core/EVM/EVMStepExecutor.js +96 -74
- package/src/_cjs/core/EVM/EVMStepExecutor.js.map +1 -1
- package/src/_cjs/core/EVM/abi.js +36 -43
- package/src/_cjs/core/EVM/abi.js.map +1 -1
- package/src/_cjs/core/EVM/checkAllowance.js +36 -30
- package/src/_cjs/core/EVM/checkAllowance.js.map +1 -1
- package/src/_cjs/core/EVM/getAllowance.js.map +1 -1
- package/src/_cjs/core/EVM/getEVMBalance.js.map +1 -1
- package/src/_cjs/core/EVM/getNativePermit.js +90 -0
- package/src/_cjs/core/EVM/getNativePermit.js.map +1 -0
- package/src/_cjs/core/EVM/parseEVMErrors.js +3 -0
- package/src/_cjs/core/EVM/parseEVMErrors.js.map +1 -1
- package/src/_cjs/core/EVM/permit2/allowanceTransfer.js +100 -0
- package/src/_cjs/core/EVM/permit2/allowanceTransfer.js.map +1 -0
- package/src/_cjs/core/EVM/permit2/constants.js +12 -0
- package/src/_cjs/core/EVM/permit2/constants.js.map +1 -0
- package/src/_cjs/core/EVM/permit2/domain.js +12 -0
- package/src/_cjs/core/EVM/permit2/domain.js.map +1 -0
- package/src/_cjs/core/EVM/permit2/signatureTransfer.js +121 -0
- package/src/_cjs/core/EVM/permit2/signatureTransfer.js.map +1 -0
- package/src/_cjs/core/EVM/setAllowance.js +3 -4
- package/src/_cjs/core/EVM/setAllowance.js.map +1 -1
- package/src/_cjs/core/EVM/signPermitMessage.js +168 -0
- package/src/_cjs/core/EVM/signPermitMessage.js.map +1 -0
- package/src/_cjs/core/EVM/types.js.map +1 -1
- package/src/_cjs/core/EVM/utils.js +2 -1
- package/src/_cjs/core/EVM/utils.js.map +1 -1
- package/src/_cjs/core/EVM/waitForBatchTransactionReceipt.js +29 -0
- package/src/_cjs/core/EVM/waitForBatchTransactionReceipt.js.map +1 -0
- package/src/_cjs/core/checkBalance.js +3 -3
- package/src/_cjs/core/checkBalance.js.map +1 -1
- package/src/_cjs/index.js.map +1 -1
- package/src/_cjs/utils/invariant.js +17 -0
- package/src/_cjs/utils/invariant.js.map +1 -0
- package/src/_cjs/version.js +1 -1
- package/src/_cjs/version.js.map +1 -1
- package/src/_esm/constants.js +3 -1
- package/src/_esm/constants.js.map +1 -1
- package/src/_esm/core/EVM/EVM.js +0 -4
- package/src/_esm/core/EVM/EVM.js.map +1 -1
- package/src/_esm/core/EVM/EVMStepExecutor.js +124 -84
- package/src/_esm/core/EVM/EVMStepExecutor.js.map +1 -1
- package/src/_esm/core/EVM/abi.js +37 -42
- package/src/_esm/core/EVM/abi.js.map +1 -1
- package/src/_esm/core/EVM/checkAllowance.js +41 -32
- package/src/_esm/core/EVM/checkAllowance.js.map +1 -1
- package/src/_esm/core/EVM/getAllowance.js.map +1 -1
- package/src/_esm/core/EVM/getEVMBalance.js.map +1 -1
- package/src/_esm/core/EVM/getNativePermit.js +95 -0
- package/src/_esm/core/EVM/getNativePermit.js.map +1 -0
- package/src/_esm/core/EVM/parseEVMErrors.js +8 -0
- package/src/_esm/core/EVM/parseEVMErrors.js.map +1 -1
- package/src/_esm/core/EVM/permit2/allowanceTransfer.js +93 -0
- package/src/_esm/core/EVM/permit2/allowanceTransfer.js.map +1 -0
- package/src/_esm/core/EVM/permit2/constants.js +9 -0
- package/src/_esm/core/EVM/permit2/constants.js.map +1 -0
- package/src/_esm/core/EVM/permit2/domain.js +9 -0
- package/src/_esm/core/EVM/permit2/domain.js.map +1 -0
- package/src/_esm/core/EVM/permit2/signatureTransfer.js +117 -0
- package/src/_esm/core/EVM/permit2/signatureTransfer.js.map +1 -0
- package/src/_esm/core/EVM/setAllowance.js +3 -4
- package/src/_esm/core/EVM/setAllowance.js.map +1 -1
- package/src/_esm/core/EVM/signPermitMessage.js +162 -0
- package/src/_esm/core/EVM/signPermitMessage.js.map +1 -0
- package/src/_esm/core/EVM/types.js.map +1 -1
- package/src/_esm/core/EVM/utils.js +2 -1
- package/src/_esm/core/EVM/utils.js.map +1 -1
- package/src/_esm/core/EVM/waitForBatchTransactionReceipt.js +25 -0
- package/src/_esm/core/EVM/waitForBatchTransactionReceipt.js.map +1 -0
- package/src/_esm/core/checkBalance.js +3 -3
- package/src/_esm/core/checkBalance.js.map +1 -1
- package/src/_esm/index.js.map +1 -1
- package/src/_esm/utils/invariant.js +43 -0
- package/src/_esm/utils/invariant.js.map +1 -0
- package/src/_esm/version.js +1 -1
- package/src/_esm/version.js.map +1 -1
- package/src/_types/constants.d.ts +3 -1
- package/src/_types/constants.d.ts.map +1 -1
- package/src/_types/core/EVM/EVM.d.ts.map +1 -1
- package/src/_types/core/EVM/EVMStepExecutor.d.ts +7 -4
- package/src/_types/core/EVM/EVMStepExecutor.d.ts.map +1 -1
- package/src/_types/core/EVM/abi.d.ts +202 -5
- package/src/_types/core/EVM/abi.d.ts.map +1 -1
- package/src/_types/core/EVM/checkAllowance.d.ts +12 -2
- package/src/_types/core/EVM/checkAllowance.d.ts.map +1 -1
- package/src/_types/core/EVM/getAllowance.d.ts +5 -4
- package/src/_types/core/EVM/getAllowance.d.ts.map +1 -1
- package/src/_types/core/EVM/getEVMBalance.d.ts +2 -1
- package/src/_types/core/EVM/getEVMBalance.d.ts.map +1 -1
- package/src/_types/core/EVM/getNativePermit.d.ts +18 -0
- package/src/_types/core/EVM/getNativePermit.d.ts.map +1 -0
- package/src/_types/core/EVM/permit2/allowanceTransfer.d.ts +41 -0
- package/src/_types/core/EVM/permit2/allowanceTransfer.d.ts.map +1 -0
- package/src/_types/core/EVM/permit2/constants.d.ts +8 -0
- package/src/_types/core/EVM/permit2/constants.d.ts.map +1 -0
- package/src/_types/core/EVM/permit2/domain.d.ts +8 -0
- package/src/_types/core/EVM/permit2/domain.d.ts.map +1 -0
- package/src/_types/core/EVM/permit2/signatureTransfer.d.ts +42 -0
- package/src/_types/core/EVM/permit2/signatureTransfer.d.ts.map +1 -0
- package/src/_types/core/EVM/setAllowance.d.ts +2 -2
- package/src/_types/core/EVM/setAllowance.d.ts.map +1 -1
- package/src/_types/core/EVM/signPermitMessage.d.ts +22 -0
- package/src/_types/core/EVM/signPermitMessage.d.ts.map +1 -0
- package/src/_types/core/EVM/types.d.ts +1 -18
- package/src/_types/core/EVM/types.d.ts.map +1 -1
- package/src/_types/core/EVM/utils.d.ts +2 -2
- package/src/_types/core/EVM/utils.d.ts.map +1 -1
- package/src/_types/core/EVM/waitForBatchTransactionReceipt.d.ts +4 -0
- package/src/_types/core/EVM/waitForBatchTransactionReceipt.d.ts.map +1 -0
- package/src/_types/core/checkBalance.d.ts.map +1 -1
- package/src/_types/index.d.ts +1 -1
- package/src/_types/index.d.ts.map +1 -1
- package/src/_types/utils/invariant.d.ts +22 -0
- package/src/_types/utils/invariant.d.ts.map +1 -0
- package/src/_types/version.d.ts +1 -1
- package/src/_types/version.d.ts.map +1 -1
- package/src/constants.ts +6 -1
- package/src/core/EVM/EVM.ts +0 -4
- package/src/core/EVM/EVMStepExecutor.ts +177 -134
- package/src/core/EVM/abi.ts +40 -43
- package/src/core/EVM/checkAllowance.ts +96 -92
- package/src/core/EVM/getAllowance.ts +8 -8
- package/src/core/EVM/getEVMBalance.ts +2 -2
- package/src/core/EVM/getNativePermit.ts +113 -0
- package/src/core/EVM/parseEVMErrors.ts +8 -0
- package/src/core/EVM/permit2/allowanceTransfer.ts +168 -0
- package/src/core/EVM/permit2/constants.ts +11 -0
- package/src/core/EVM/permit2/domain.ts +20 -0
- package/src/core/EVM/permit2/signatureTransfer.ts +214 -0
- package/src/core/EVM/setAllowance.ts +14 -15
- package/src/core/EVM/signPermitMessage.ts +248 -0
- package/src/core/EVM/types.ts +1 -27
- package/src/core/EVM/utils.ts +4 -3
- package/src/core/EVM/waitForBatchTransactionReceipt.ts +49 -0
- package/src/core/checkBalance.ts +6 -3
- package/src/index.ts +0 -3
- package/src/utils/invariant.ts +51 -0
- package/src/version.ts +1 -1
- package/src/_cjs/core/EVM/multisig.js +0 -29
- package/src/_cjs/core/EVM/multisig.js.map +0 -1
- package/src/_esm/core/EVM/multisig.js +0 -25
- package/src/_esm/core/EVM/multisig.js.map +0 -1
- package/src/_types/core/EVM/multisig.d.ts +0 -6
- package/src/_types/core/EVM/multisig.d.ts.map +0 -1
- package/src/core/EVM/multisig.ts +0 -54
|
@@ -0,0 +1,214 @@
|
|
|
1
|
+
import { hashTypedData } from 'viem'
|
|
2
|
+
import type { Address, TypedData, TypedDataDomain } from 'viem'
|
|
3
|
+
import { invariant } from '../../../utils/invariant.js'
|
|
4
|
+
import {
|
|
5
|
+
MaxSigDeadline,
|
|
6
|
+
MaxSignatureTransferAmount,
|
|
7
|
+
MaxUnorderedNonce,
|
|
8
|
+
} from './constants.js'
|
|
9
|
+
import { permit2Domain } from './domain.js'
|
|
10
|
+
|
|
11
|
+
export interface Witness {
|
|
12
|
+
witness: any
|
|
13
|
+
witnessTypeName: string
|
|
14
|
+
witnessType: { [key: string]: { name: string; type: string }[] }
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
export interface TokenPermissions {
|
|
18
|
+
token: Address
|
|
19
|
+
amount: bigint
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
export interface PermitTransferFrom {
|
|
23
|
+
permitted: TokenPermissions
|
|
24
|
+
spender: Address
|
|
25
|
+
nonce: bigint
|
|
26
|
+
deadline: bigint
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
export interface PermitBatchTransferFrom {
|
|
30
|
+
permitted: TokenPermissions[]
|
|
31
|
+
spender: Address
|
|
32
|
+
nonce: bigint
|
|
33
|
+
deadline: bigint
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
export type PermitTransferFromData = {
|
|
37
|
+
domain: TypedDataDomain
|
|
38
|
+
types: TypedData
|
|
39
|
+
values: PermitTransferFrom
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
export type PermitBatchTransferFromData = {
|
|
43
|
+
domain: TypedDataDomain
|
|
44
|
+
types: TypedData
|
|
45
|
+
values: PermitBatchTransferFrom
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
const TOKEN_PERMISSIONS = [
|
|
49
|
+
{ name: 'token', type: 'address' },
|
|
50
|
+
{ name: 'amount', type: 'uint256' },
|
|
51
|
+
] as const
|
|
52
|
+
|
|
53
|
+
const PERMIT_TRANSFER_FROM_TYPES = {
|
|
54
|
+
TokenPermissions: TOKEN_PERMISSIONS,
|
|
55
|
+
PermitTransferFrom: [
|
|
56
|
+
{ name: 'permitted', type: 'TokenPermissions' },
|
|
57
|
+
{ name: 'spender', type: 'address' },
|
|
58
|
+
{ name: 'nonce', type: 'uint256' },
|
|
59
|
+
{ name: 'deadline', type: 'uint256' },
|
|
60
|
+
],
|
|
61
|
+
} as const
|
|
62
|
+
|
|
63
|
+
const PERMIT_BATCH_TRANSFER_FROM_TYPES = {
|
|
64
|
+
TokenPermissions: TOKEN_PERMISSIONS,
|
|
65
|
+
PermitBatchTransferFrom: [
|
|
66
|
+
{ name: 'permitted', type: 'TokenPermissions[]' },
|
|
67
|
+
{ name: 'spender', type: 'address' },
|
|
68
|
+
{ name: 'nonce', type: 'uint256' },
|
|
69
|
+
{ name: 'deadline', type: 'uint256' },
|
|
70
|
+
],
|
|
71
|
+
} as const
|
|
72
|
+
|
|
73
|
+
function isPermitTransferFrom(
|
|
74
|
+
permit: PermitTransferFrom | PermitBatchTransferFrom
|
|
75
|
+
): permit is PermitTransferFrom {
|
|
76
|
+
return !Array.isArray(permit.permitted)
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
export function getPermitTransferData(
|
|
80
|
+
permit: PermitTransferFrom,
|
|
81
|
+
permit2Address: Address,
|
|
82
|
+
chainId: number,
|
|
83
|
+
witness?: Witness
|
|
84
|
+
): PermitTransferFromData {
|
|
85
|
+
invariant(MaxSigDeadline >= permit.deadline, 'SIG_DEADLINE_OUT_OF_RANGE')
|
|
86
|
+
invariant(MaxUnorderedNonce >= permit.nonce, 'NONCE_OUT_OF_RANGE')
|
|
87
|
+
|
|
88
|
+
const domain = permit2Domain(permit2Address, chainId)
|
|
89
|
+
|
|
90
|
+
validateTokenPermissions(permit.permitted)
|
|
91
|
+
|
|
92
|
+
const types = witness
|
|
93
|
+
? ({
|
|
94
|
+
TokenPermissions: TOKEN_PERMISSIONS,
|
|
95
|
+
...witness.witnessType,
|
|
96
|
+
PermitWitnessTransferFrom: [
|
|
97
|
+
{ name: 'permitted', type: 'TokenPermissions' },
|
|
98
|
+
{ name: 'spender', type: 'address' },
|
|
99
|
+
{ name: 'nonce', type: 'uint256' },
|
|
100
|
+
{ name: 'deadline', type: 'uint256' },
|
|
101
|
+
{ name: 'witness', type: witness.witnessTypeName },
|
|
102
|
+
],
|
|
103
|
+
} as const)
|
|
104
|
+
: PERMIT_TRANSFER_FROM_TYPES
|
|
105
|
+
|
|
106
|
+
const values = witness
|
|
107
|
+
? Object.assign(permit, { witness: witness.witness })
|
|
108
|
+
: permit
|
|
109
|
+
|
|
110
|
+
return {
|
|
111
|
+
domain,
|
|
112
|
+
types,
|
|
113
|
+
values,
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
export function getPermitBatchTransferData(
|
|
118
|
+
permit: PermitBatchTransferFrom,
|
|
119
|
+
permit2Address: Address,
|
|
120
|
+
chainId: number,
|
|
121
|
+
witness?: Witness
|
|
122
|
+
): PermitBatchTransferFromData {
|
|
123
|
+
invariant(MaxSigDeadline >= permit.deadline, 'SIG_DEADLINE_OUT_OF_RANGE')
|
|
124
|
+
invariant(MaxUnorderedNonce >= permit.nonce, 'NONCE_OUT_OF_RANGE')
|
|
125
|
+
|
|
126
|
+
const domain = permit2Domain(permit2Address, chainId)
|
|
127
|
+
|
|
128
|
+
permit.permitted.forEach(validateTokenPermissions)
|
|
129
|
+
|
|
130
|
+
const types = witness
|
|
131
|
+
? {
|
|
132
|
+
...witness.witnessType,
|
|
133
|
+
TokenPermissions: TOKEN_PERMISSIONS,
|
|
134
|
+
PermitBatchWitnessTransferFrom: [
|
|
135
|
+
{ name: 'permitted', type: 'TokenPermissions[]' },
|
|
136
|
+
{ name: 'spender', type: 'address' },
|
|
137
|
+
{ name: 'nonce', type: 'uint256' },
|
|
138
|
+
{ name: 'deadline', type: 'uint256' },
|
|
139
|
+
{ name: 'witness', type: witness.witnessTypeName },
|
|
140
|
+
],
|
|
141
|
+
}
|
|
142
|
+
: PERMIT_BATCH_TRANSFER_FROM_TYPES
|
|
143
|
+
|
|
144
|
+
const values = witness
|
|
145
|
+
? Object.assign(permit, { witness: witness.witness })
|
|
146
|
+
: permit
|
|
147
|
+
|
|
148
|
+
return {
|
|
149
|
+
domain,
|
|
150
|
+
types,
|
|
151
|
+
values,
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
// return the data to be sent in a eth_signTypedData RPC call
|
|
156
|
+
// for signing the given permit data
|
|
157
|
+
export function getPermitData(
|
|
158
|
+
permit: PermitTransferFrom | PermitBatchTransferFrom,
|
|
159
|
+
permit2Address: Address,
|
|
160
|
+
chainId: number,
|
|
161
|
+
witness?: Witness
|
|
162
|
+
): PermitTransferFromData | PermitBatchTransferFromData {
|
|
163
|
+
if (isPermitTransferFrom(permit)) {
|
|
164
|
+
return getPermitTransferData(permit, permit2Address, chainId, witness)
|
|
165
|
+
}
|
|
166
|
+
return getPermitBatchTransferData(permit, permit2Address, chainId, witness)
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
export function hash(
|
|
170
|
+
permit: PermitTransferFrom | PermitBatchTransferFrom,
|
|
171
|
+
permit2Address: Address,
|
|
172
|
+
chainId: number,
|
|
173
|
+
witness?: Witness
|
|
174
|
+
) {
|
|
175
|
+
if (isPermitTransferFrom(permit)) {
|
|
176
|
+
const { domain, types, values } = getPermitTransferData(
|
|
177
|
+
permit,
|
|
178
|
+
permit2Address,
|
|
179
|
+
chainId,
|
|
180
|
+
witness
|
|
181
|
+
)
|
|
182
|
+
|
|
183
|
+
return hashTypedData({
|
|
184
|
+
domain,
|
|
185
|
+
types,
|
|
186
|
+
primaryType: witness ? 'PermitWitnessTransferFrom' : 'PermitTransferFrom',
|
|
187
|
+
message: {
|
|
188
|
+
...values,
|
|
189
|
+
},
|
|
190
|
+
})
|
|
191
|
+
}
|
|
192
|
+
const { domain, types, values } = getPermitBatchTransferData(
|
|
193
|
+
permit,
|
|
194
|
+
permit2Address,
|
|
195
|
+
chainId,
|
|
196
|
+
witness
|
|
197
|
+
)
|
|
198
|
+
|
|
199
|
+
return hashTypedData({
|
|
200
|
+
domain,
|
|
201
|
+
types,
|
|
202
|
+
primaryType: witness
|
|
203
|
+
? 'PermitBatchWitnessTransferFrom'
|
|
204
|
+
: 'PermitBatchTransferFrom',
|
|
205
|
+
message: { ...values },
|
|
206
|
+
})
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
function validateTokenPermissions(permissions: TokenPermissions) {
|
|
210
|
+
invariant(
|
|
211
|
+
MaxSignatureTransferAmount >= permissions.amount,
|
|
212
|
+
'AMOUNT_OUT_OF_RANGE'
|
|
213
|
+
)
|
|
214
|
+
}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { Client, Hash, SendTransactionParameters } from 'viem'
|
|
1
|
+
import type { Address, Client, Hash, SendTransactionParameters } from 'viem'
|
|
2
2
|
import { encodeFunctionData } from 'viem'
|
|
3
3
|
import { sendTransaction } from 'viem/actions'
|
|
4
4
|
import { isNativeTokenAddress } from '../../utils/isZeroAddress.js'
|
|
@@ -10,10 +10,10 @@ import { getMaxPriorityFeePerGas } from './utils.js'
|
|
|
10
10
|
|
|
11
11
|
export const setAllowance = async (
|
|
12
12
|
client: Client,
|
|
13
|
-
tokenAddress:
|
|
14
|
-
contractAddress:
|
|
13
|
+
tokenAddress: Address,
|
|
14
|
+
contractAddress: Address,
|
|
15
15
|
amount: bigint,
|
|
16
|
-
|
|
16
|
+
executionOptions?: ExecutionOptions,
|
|
17
17
|
returnPopulatedTransaction?: boolean
|
|
18
18
|
): Promise<Hash> => {
|
|
19
19
|
const data = encodeFunctionData({
|
|
@@ -35,9 +35,9 @@ export const setAllowance = async (
|
|
|
35
35
|
: undefined,
|
|
36
36
|
}
|
|
37
37
|
|
|
38
|
-
if (
|
|
38
|
+
if (executionOptions?.updateTransactionRequestHook) {
|
|
39
39
|
const customizedTransactionRequest: TransactionParameters =
|
|
40
|
-
await
|
|
40
|
+
await executionOptions.updateTransactionRequestHook({
|
|
41
41
|
requestType: 'approve',
|
|
42
42
|
...transactionRequest,
|
|
43
43
|
})
|
|
@@ -56,7 +56,6 @@ export const setAllowance = async (
|
|
|
56
56
|
gasPrice: transactionRequest.gasPrice,
|
|
57
57
|
maxFeePerGas: transactionRequest.maxFeePerGas,
|
|
58
58
|
maxPriorityFeePerGas: transactionRequest.maxPriorityFeePerGas,
|
|
59
|
-
chain: null,
|
|
60
59
|
} as SendTransactionParameters)
|
|
61
60
|
}
|
|
62
61
|
|
|
@@ -81,16 +80,16 @@ export const setTokenAllowance = async ({
|
|
|
81
80
|
}
|
|
82
81
|
const approvedAmount = await getAllowance(
|
|
83
82
|
token.chainId,
|
|
84
|
-
token.address,
|
|
83
|
+
token.address as Address,
|
|
85
84
|
walletClient.account!.address,
|
|
86
|
-
spenderAddress
|
|
85
|
+
spenderAddress as Address
|
|
87
86
|
)
|
|
88
87
|
|
|
89
88
|
if (amount > approvedAmount) {
|
|
90
89
|
const approveTx = await setAllowance(
|
|
91
90
|
walletClient,
|
|
92
|
-
token.address,
|
|
93
|
-
spenderAddress,
|
|
91
|
+
token.address as Address,
|
|
92
|
+
spenderAddress as Address,
|
|
94
93
|
amount
|
|
95
94
|
)
|
|
96
95
|
|
|
@@ -117,15 +116,15 @@ export const revokeTokenApproval = async ({
|
|
|
117
116
|
}
|
|
118
117
|
const approvedAmount = await getAllowance(
|
|
119
118
|
token.chainId,
|
|
120
|
-
token.address,
|
|
119
|
+
token.address as Address,
|
|
121
120
|
walletClient.account!.address,
|
|
122
|
-
spenderAddress
|
|
121
|
+
spenderAddress as Address
|
|
123
122
|
)
|
|
124
123
|
if (approvedAmount > 0) {
|
|
125
124
|
const approveTx = await setAllowance(
|
|
126
125
|
walletClient,
|
|
127
|
-
token.address,
|
|
128
|
-
spenderAddress,
|
|
126
|
+
token.address as Address,
|
|
127
|
+
spenderAddress as Address,
|
|
129
128
|
0n
|
|
130
129
|
)
|
|
131
130
|
|
|
@@ -0,0 +1,248 @@
|
|
|
1
|
+
import type { ExtendedChain } from '@lifi/types'
|
|
2
|
+
import type { Client, Hex } from 'viem'
|
|
3
|
+
import { encodeFunctionData } from 'viem'
|
|
4
|
+
import { parseSignature } from 'viem'
|
|
5
|
+
import type { Address } from 'viem'
|
|
6
|
+
import { keccak256 } from 'viem'
|
|
7
|
+
import { readContract, signTypedData } from 'viem/actions'
|
|
8
|
+
import type { TransactionParameters } from '../types.js'
|
|
9
|
+
import { eip2612Types, permit2ProxyAbi } from './abi.js'
|
|
10
|
+
import { type NativePermitData, getNativePermit } from './getNativePermit.js'
|
|
11
|
+
import {
|
|
12
|
+
type PermitTransferFrom,
|
|
13
|
+
getPermitData,
|
|
14
|
+
} from './permit2/signatureTransfer.js'
|
|
15
|
+
|
|
16
|
+
export const signNativePermitMessage = async (
|
|
17
|
+
client: Client,
|
|
18
|
+
transactionRequest: TransactionParameters,
|
|
19
|
+
chain: ExtendedChain,
|
|
20
|
+
tokenAddress: Address,
|
|
21
|
+
amount: bigint,
|
|
22
|
+
nativePermit: NativePermitData
|
|
23
|
+
) => {
|
|
24
|
+
const deadline = BigInt(Math.floor(Date.now() / 1000) + 30 * 60) // 30 minutes
|
|
25
|
+
|
|
26
|
+
const domain = {
|
|
27
|
+
name: nativePermit.name,
|
|
28
|
+
version: nativePermit.version,
|
|
29
|
+
chainId: chain.id,
|
|
30
|
+
verifyingContract: tokenAddress,
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
const message = {
|
|
34
|
+
owner: client.account!.address,
|
|
35
|
+
spender: chain.permit2Proxy as Address,
|
|
36
|
+
value: amount,
|
|
37
|
+
nonce: nativePermit.nonce,
|
|
38
|
+
deadline,
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
const signature = await signTypedData(client, {
|
|
42
|
+
account: client.account!,
|
|
43
|
+
domain,
|
|
44
|
+
types: eip2612Types,
|
|
45
|
+
primaryType: 'Permit',
|
|
46
|
+
message,
|
|
47
|
+
})
|
|
48
|
+
|
|
49
|
+
const { v, r, s } = parseSignature(signature)
|
|
50
|
+
|
|
51
|
+
const data = encodeFunctionData({
|
|
52
|
+
abi: permit2ProxyAbi,
|
|
53
|
+
functionName: 'callDiamondWithEIP2612Signature',
|
|
54
|
+
args: [
|
|
55
|
+
tokenAddress,
|
|
56
|
+
amount,
|
|
57
|
+
deadline,
|
|
58
|
+
Number(v),
|
|
59
|
+
r,
|
|
60
|
+
s,
|
|
61
|
+
transactionRequest.data as Hex,
|
|
62
|
+
],
|
|
63
|
+
})
|
|
64
|
+
|
|
65
|
+
return {
|
|
66
|
+
signature,
|
|
67
|
+
data,
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
export const signPermit2Message = async (
|
|
72
|
+
client: Client,
|
|
73
|
+
transactionRequest: TransactionParameters,
|
|
74
|
+
chain: ExtendedChain,
|
|
75
|
+
tokenAddress: Address,
|
|
76
|
+
amount: bigint
|
|
77
|
+
) => {
|
|
78
|
+
const nonce = await readContract(client, {
|
|
79
|
+
address: chain.permit2Proxy as Address,
|
|
80
|
+
abi: permit2ProxyAbi,
|
|
81
|
+
functionName: 'nextNonce',
|
|
82
|
+
args: [client.account!.address],
|
|
83
|
+
})
|
|
84
|
+
|
|
85
|
+
const permitTransferFrom: PermitTransferFrom = {
|
|
86
|
+
permitted: {
|
|
87
|
+
token: tokenAddress,
|
|
88
|
+
amount: amount,
|
|
89
|
+
},
|
|
90
|
+
spender: chain.permit2Proxy as Address,
|
|
91
|
+
nonce: nonce,
|
|
92
|
+
deadline: BigInt(Math.floor(Date.now() / 1000) + 30 * 60), // 30 minutes
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
const { domain, types, values } = getPermitData(
|
|
96
|
+
permitTransferFrom,
|
|
97
|
+
chain.permit2 as Address,
|
|
98
|
+
chain.id
|
|
99
|
+
)
|
|
100
|
+
|
|
101
|
+
const signature = await signTypedData(client, {
|
|
102
|
+
account: client.account!,
|
|
103
|
+
primaryType: 'PermitTransferFrom',
|
|
104
|
+
domain,
|
|
105
|
+
types,
|
|
106
|
+
message: { ...values },
|
|
107
|
+
})
|
|
108
|
+
|
|
109
|
+
const data = encodeFunctionData({
|
|
110
|
+
abi: permit2ProxyAbi,
|
|
111
|
+
functionName: 'callDiamondWithPermit2',
|
|
112
|
+
args: [
|
|
113
|
+
transactionRequest.data as Hex,
|
|
114
|
+
[
|
|
115
|
+
[tokenAddress, amount],
|
|
116
|
+
permitTransferFrom.nonce,
|
|
117
|
+
permitTransferFrom.deadline,
|
|
118
|
+
],
|
|
119
|
+
signature as Hex,
|
|
120
|
+
],
|
|
121
|
+
})
|
|
122
|
+
|
|
123
|
+
return {
|
|
124
|
+
signature,
|
|
125
|
+
data,
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
export const signPermit2WitnessMessage = async (
|
|
130
|
+
client: Client,
|
|
131
|
+
transactionRequest: TransactionParameters,
|
|
132
|
+
chain: ExtendedChain,
|
|
133
|
+
tokenAddress: Address,
|
|
134
|
+
amount: bigint
|
|
135
|
+
) => {
|
|
136
|
+
const nonce = await readContract(client, {
|
|
137
|
+
address: chain.permit2Proxy as Address,
|
|
138
|
+
abi: permit2ProxyAbi,
|
|
139
|
+
functionName: 'nextNonce',
|
|
140
|
+
args: [client.account!.address],
|
|
141
|
+
})
|
|
142
|
+
|
|
143
|
+
const permitTransferFrom: PermitTransferFrom = {
|
|
144
|
+
permitted: {
|
|
145
|
+
token: tokenAddress,
|
|
146
|
+
amount: amount,
|
|
147
|
+
},
|
|
148
|
+
spender: chain.permit2Proxy as Address,
|
|
149
|
+
nonce: nonce,
|
|
150
|
+
deadline: BigInt(Math.floor(Date.now() / 1000) + 30 * 60), // 30 minutes
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
// Create witness data for the LI.FI call
|
|
154
|
+
const witness = {
|
|
155
|
+
witness: {
|
|
156
|
+
tokenReceiver: chain.permit2Proxy as Address,
|
|
157
|
+
diamondAddress: chain.diamondAddress as Address,
|
|
158
|
+
diamondCalldataHash: keccak256(transactionRequest.data as Hex),
|
|
159
|
+
},
|
|
160
|
+
witnessTypeName: 'LiFiCall',
|
|
161
|
+
witnessType: {
|
|
162
|
+
LiFiCall: [
|
|
163
|
+
{ name: 'diamondAddress', type: 'address' },
|
|
164
|
+
{ name: 'diamondCalldataHash', type: 'bytes32' },
|
|
165
|
+
],
|
|
166
|
+
},
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
const { domain, types, values } = getPermitData(
|
|
170
|
+
permitTransferFrom,
|
|
171
|
+
chain.permit2 as Address,
|
|
172
|
+
chain.id,
|
|
173
|
+
witness
|
|
174
|
+
)
|
|
175
|
+
|
|
176
|
+
const signature = await signTypedData(client, {
|
|
177
|
+
account: client.account!,
|
|
178
|
+
primaryType: 'PermitWitnessTransferFrom',
|
|
179
|
+
domain,
|
|
180
|
+
types,
|
|
181
|
+
message: { ...values },
|
|
182
|
+
})
|
|
183
|
+
|
|
184
|
+
const data = encodeFunctionData({
|
|
185
|
+
abi: permit2ProxyAbi,
|
|
186
|
+
functionName: 'callDiamondWithPermit2Witness',
|
|
187
|
+
args: [
|
|
188
|
+
transactionRequest.data as Hex,
|
|
189
|
+
client.account!.address,
|
|
190
|
+
[
|
|
191
|
+
[tokenAddress, amount],
|
|
192
|
+
permitTransferFrom.nonce,
|
|
193
|
+
permitTransferFrom.deadline,
|
|
194
|
+
],
|
|
195
|
+
signature as Hex,
|
|
196
|
+
],
|
|
197
|
+
})
|
|
198
|
+
|
|
199
|
+
return {
|
|
200
|
+
signature,
|
|
201
|
+
data,
|
|
202
|
+
}
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
export const signPermitMessage = async (
|
|
206
|
+
client: Client,
|
|
207
|
+
transactionRequest: TransactionParameters,
|
|
208
|
+
chain: ExtendedChain,
|
|
209
|
+
tokenAddress: Address,
|
|
210
|
+
amount: bigint,
|
|
211
|
+
nativePermit?: NativePermitData,
|
|
212
|
+
useWitness = false
|
|
213
|
+
) => {
|
|
214
|
+
let _nativePermit = nativePermit
|
|
215
|
+
|
|
216
|
+
if (!_nativePermit) {
|
|
217
|
+
_nativePermit = await getNativePermit(client, chain, tokenAddress)
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
if (_nativePermit.supported) {
|
|
221
|
+
return signNativePermitMessage(
|
|
222
|
+
client,
|
|
223
|
+
transactionRequest,
|
|
224
|
+
chain,
|
|
225
|
+
tokenAddress,
|
|
226
|
+
amount,
|
|
227
|
+
_nativePermit
|
|
228
|
+
)
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
if (useWitness) {
|
|
232
|
+
return signPermit2WitnessMessage(
|
|
233
|
+
client,
|
|
234
|
+
transactionRequest,
|
|
235
|
+
chain,
|
|
236
|
+
tokenAddress,
|
|
237
|
+
amount
|
|
238
|
+
)
|
|
239
|
+
}
|
|
240
|
+
|
|
241
|
+
return signPermit2Message(
|
|
242
|
+
client,
|
|
243
|
+
transactionRequest,
|
|
244
|
+
chain,
|
|
245
|
+
tokenAddress,
|
|
246
|
+
amount
|
|
247
|
+
)
|
|
248
|
+
}
|
package/src/core/EVM/types.ts
CHANGED
|
@@ -1,17 +1,15 @@
|
|
|
1
1
|
import { type BaseToken, ChainType } from '@lifi/types'
|
|
2
|
-
import type { Client
|
|
2
|
+
import type { Client } from 'viem'
|
|
3
3
|
import type { SwitchChainHook } from '../types.js'
|
|
4
4
|
import type { SDKProvider } from '../types.js'
|
|
5
5
|
|
|
6
6
|
export interface EVMProviderOptions {
|
|
7
7
|
getWalletClient?: () => Promise<Client>
|
|
8
8
|
switchChain?: SwitchChainHook
|
|
9
|
-
multisig?: MultisigConfig
|
|
10
9
|
}
|
|
11
10
|
|
|
12
11
|
export interface EVMProvider extends SDKProvider {
|
|
13
12
|
setOptions(options: EVMProviderOptions): void
|
|
14
|
-
multisig?: MultisigConfig
|
|
15
13
|
}
|
|
16
14
|
|
|
17
15
|
export function isEVM(provider: SDKProvider): provider is EVMProvider {
|
|
@@ -50,27 +48,3 @@ export interface RevokeApprovalRequest {
|
|
|
50
48
|
token: BaseToken
|
|
51
49
|
spenderAddress: string
|
|
52
50
|
}
|
|
53
|
-
|
|
54
|
-
export interface MultisigTxDetails {
|
|
55
|
-
status: 'DONE' | 'FAILED' | 'PENDING' | 'CANCELLED'
|
|
56
|
-
txHash?: Hash
|
|
57
|
-
}
|
|
58
|
-
|
|
59
|
-
export interface MultisigTransaction {
|
|
60
|
-
to: string
|
|
61
|
-
value?: bigint
|
|
62
|
-
data: string
|
|
63
|
-
}
|
|
64
|
-
|
|
65
|
-
export interface MultisigConfig {
|
|
66
|
-
isMultisigWalletClient: boolean
|
|
67
|
-
getMultisigTransactionDetails: (
|
|
68
|
-
txHash: Hash,
|
|
69
|
-
fromChainId: number,
|
|
70
|
-
updateIntermediateStatus?: () => void
|
|
71
|
-
) => Promise<MultisigTxDetails>
|
|
72
|
-
sendBatchTransaction?: (
|
|
73
|
-
batchTransactions: MultisigTransaction[]
|
|
74
|
-
) => Promise<Hash>
|
|
75
|
-
shouldBatchTransactions?: boolean
|
|
76
|
-
}
|
package/src/core/EVM/utils.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type { ChainId } from '@lifi/types'
|
|
2
|
-
import type { Client, Transaction } from 'viem'
|
|
2
|
+
import type { Address, Client, Transaction } from 'viem'
|
|
3
3
|
import { getBlock } from 'viem/actions'
|
|
4
4
|
import { config } from '../../config.js'
|
|
5
5
|
import { median } from '../../utils/median.js'
|
|
@@ -37,9 +37,10 @@ export const getMaxPriorityFeePerGas = async (
|
|
|
37
37
|
// Multicall
|
|
38
38
|
export const getMulticallAddress = async (
|
|
39
39
|
chainId: ChainId
|
|
40
|
-
): Promise<
|
|
40
|
+
): Promise<Address | undefined> => {
|
|
41
41
|
const chains = await config.getChains()
|
|
42
|
-
return chains.find((chain) => chain.id === chainId)
|
|
42
|
+
return chains.find((chain) => chain.id === chainId)
|
|
43
|
+
?.multicallAddress as Address
|
|
43
44
|
}
|
|
44
45
|
|
|
45
46
|
// Modified viem retryDelay exponential backoff function.
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
import type {
|
|
2
|
+
Client,
|
|
3
|
+
Hash,
|
|
4
|
+
WalletCallReceipt as _WalletCallReceipt,
|
|
5
|
+
} from 'viem'
|
|
6
|
+
import { getCallsStatus } from 'viem/experimental'
|
|
7
|
+
import { LiFiErrorCode } from '../../errors/constants.js'
|
|
8
|
+
import { TransactionError } from '../../errors/errors.js'
|
|
9
|
+
import { waitForResult } from '../../utils/waitForResult.js'
|
|
10
|
+
|
|
11
|
+
export type WalletCallReceipt = _WalletCallReceipt<
|
|
12
|
+
bigint,
|
|
13
|
+
'success' | 'reverted'
|
|
14
|
+
>
|
|
15
|
+
|
|
16
|
+
export const waitForBatchTransactionReceipt = async (
|
|
17
|
+
client: Client,
|
|
18
|
+
batchHash: Hash
|
|
19
|
+
): Promise<WalletCallReceipt> => {
|
|
20
|
+
return waitForResult(async () => {
|
|
21
|
+
const callsDetails = await getCallsStatus(client, {
|
|
22
|
+
id: batchHash,
|
|
23
|
+
})
|
|
24
|
+
|
|
25
|
+
if (callsDetails.status === 'PENDING') {
|
|
26
|
+
return undefined
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
if (callsDetails.status === 'CONFIRMED') {
|
|
30
|
+
if (
|
|
31
|
+
!callsDetails.receipts?.length ||
|
|
32
|
+
!callsDetails.receipts.every((receipt) => receipt.transactionHash) ||
|
|
33
|
+
callsDetails.receipts.some((receipt) => receipt.status === 'reverted')
|
|
34
|
+
) {
|
|
35
|
+
throw new TransactionError(
|
|
36
|
+
LiFiErrorCode.TransactionFailed,
|
|
37
|
+
'Transaction was reverted.'
|
|
38
|
+
)
|
|
39
|
+
}
|
|
40
|
+
const transactionReceipt = callsDetails.receipts.at(-1)!
|
|
41
|
+
return transactionReceipt
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
throw new TransactionError(
|
|
45
|
+
LiFiErrorCode.TransactionFailed,
|
|
46
|
+
'Transaction not found.'
|
|
47
|
+
)
|
|
48
|
+
}, 3000)
|
|
49
|
+
}
|
package/src/core/checkBalance.ts
CHANGED
|
@@ -28,13 +28,16 @@ export const checkBalance = async (
|
|
|
28
28
|
} else {
|
|
29
29
|
const neeeded = formatUnits(neededBalance, token.decimals)
|
|
30
30
|
const current = formatUnits(currentBalance, token.decimals)
|
|
31
|
-
let
|
|
31
|
+
let errorMessage = `Your ${token.symbol} balance is too low, you try to transfer ${neeeded} ${token.symbol}, but your wallet only holds ${current} ${token.symbol}. No funds have been sent.`
|
|
32
32
|
|
|
33
33
|
if (currentBalance !== 0n) {
|
|
34
|
-
|
|
34
|
+
errorMessage += `If the problem consists, please delete this transfer and start a new one with a maximum of ${current} ${token.symbol}.`
|
|
35
35
|
}
|
|
36
36
|
|
|
37
|
-
throw new BalanceError(
|
|
37
|
+
throw new BalanceError(
|
|
38
|
+
'The balance is too low.',
|
|
39
|
+
new Error(errorMessage)
|
|
40
|
+
)
|
|
38
41
|
}
|
|
39
42
|
}
|
|
40
43
|
}
|
package/src/index.ts
CHANGED
|
@@ -15,9 +15,6 @@ export { isEVM } from './core/EVM/types.js'
|
|
|
15
15
|
export type {
|
|
16
16
|
EVMProvider,
|
|
17
17
|
EVMProviderOptions,
|
|
18
|
-
MultisigConfig,
|
|
19
|
-
MultisigTransaction,
|
|
20
|
-
MultisigTxDetails,
|
|
21
18
|
} from './core/EVM/types.js'
|
|
22
19
|
export { StatusManager } from './core/StatusManager.js'
|
|
23
20
|
export {
|