@swapkit/toolboxes 1.0.0-beta.0 → 1.0.0-beta.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/chunk-0f0249b1.js +3 -0
- package/dist/chunk-0f0249b1.js.map +10 -0
- package/dist/chunk-0h4xdrwz.js +4 -0
- package/dist/chunk-0h4xdrwz.js.map +10 -0
- package/dist/chunk-4yap1fvd.js +3 -0
- package/dist/chunk-4yap1fvd.js.map +10 -0
- package/dist/chunk-fjfxga2v.js +3 -0
- package/dist/chunk-fjfxga2v.js.map +10 -0
- package/dist/{chunk-tvrdndbw.js → chunk-p1kdg37m.js} +2 -2
- package/dist/{chunk-tvrdndbw.js.map → chunk-p1kdg37m.js.map} +1 -1
- package/dist/cosmos/index.cjs +2 -2
- package/dist/cosmos/index.cjs.map +10 -13
- package/dist/cosmos/index.js +2 -2
- package/dist/cosmos/index.js.map +10 -13
- package/dist/evm/index.cjs +2 -2
- package/dist/evm/index.cjs.map +10 -16
- package/dist/evm/index.js +2 -2
- package/dist/evm/index.js.map +10 -16
- package/dist/index.cjs +2 -2
- package/dist/index.cjs.map +4 -3
- package/dist/index.js +2 -2
- package/dist/index.js.map +4 -3
- package/dist/radix/index.cjs +2 -2
- package/dist/radix/index.cjs.map +3 -3
- package/dist/radix/index.js +2 -2
- package/dist/radix/index.js.map +3 -3
- package/dist/ripple/index.cjs +3 -0
- package/dist/ripple/index.cjs.map +10 -0
- package/dist/ripple/index.js +3 -0
- package/dist/ripple/index.js.map +10 -0
- package/dist/solana/index.cjs +2 -2
- package/dist/solana/index.cjs.map +3 -3
- package/dist/solana/index.js +2 -2
- package/dist/solana/index.js.map +3 -3
- package/dist/substrate/index.cjs +2 -2
- package/dist/substrate/index.cjs.map +5 -6
- package/dist/substrate/index.js +2 -2
- package/dist/substrate/index.js.map +5 -6
- package/dist/utxo/index.cjs +2 -2
- package/dist/utxo/index.cjs.map +9 -11
- package/dist/utxo/index.js +2 -2
- package/dist/utxo/index.js.map +9 -11
- package/package.json +30 -24
- package/src/cosmos/index.ts +2 -9
- package/src/cosmos/thorchainUtils/addressFormat.ts +1 -2
- package/src/cosmos/thorchainUtils/index.ts +1 -1
- package/src/cosmos/thorchainUtils/messages.ts +74 -56
- package/src/cosmos/thorchainUtils/registry.ts +16 -23
- package/src/cosmos/thorchainUtils/types/{proto/MsgCompiled.ts → MsgCompiled.ts} +1 -3
- package/src/cosmos/thorchainUtils/types/client-types.ts +16 -23
- package/src/cosmos/toolbox/cosmos.ts +334 -0
- package/src/cosmos/toolbox/index.ts +33 -0
- package/src/cosmos/toolbox/thorchain.ts +118 -131
- package/src/cosmos/types.ts +37 -18
- package/src/cosmos/util.ts +21 -71
- package/src/evm/__tests__/ethereum.test.ts +110 -116
- package/src/evm/api.ts +11 -147
- package/src/evm/helpers.ts +111 -83
- package/src/evm/index.ts +1 -17
- package/src/evm/toolbox/baseEVMToolbox.ts +742 -0
- package/src/evm/toolbox/evm.ts +69 -0
- package/src/evm/toolbox/index.ts +36 -0
- package/src/evm/toolbox/op.ts +97 -143
- package/src/evm/types.ts +50 -28
- package/src/index.ts +235 -0
- package/src/radix/index.ts +18 -19
- package/src/ripple/index.ts +203 -0
- package/src/solana/index.ts +11 -5
- package/src/solana/toolbox.ts +223 -133
- package/src/substrate/index.ts +2 -3
- package/src/substrate/{toolbox/baseSubstrateToolbox.ts → substrate.ts} +104 -72
- package/src/substrate/types.ts +120 -0
- package/src/utils.ts +27 -0
- package/src/utxo/helpers/api.ts +27 -23
- package/src/utxo/helpers/bchaddrjs.ts +21 -21
- package/src/utxo/helpers/index.ts +0 -1
- package/src/utxo/helpers/txSize.ts +3 -4
- package/src/utxo/index.ts +3 -7
- package/src/utxo/toolbox/bitcoinCash.ts +164 -154
- package/src/utxo/toolbox/index.ts +63 -24
- package/src/utxo/toolbox/utxo.ts +376 -229
- package/src/utxo/types.ts +24 -39
- package/src/cosmos/thorchainUtils/types/proto/MsgCompiled.js +0 -2806
- package/src/cosmos/thorchainUtils/util.ts +0 -46
- package/src/cosmos/toolbox/BaseCosmosToolbox.ts +0 -254
- package/src/cosmos/toolbox/gaia.ts +0 -39
- package/src/cosmos/toolbox/getToolboxByChain.ts +0 -29
- package/src/cosmos/toolbox/kujira.ts +0 -61
- package/src/evm/provider.ts +0 -6
- package/src/evm/toolbox/EVMToolbox.ts +0 -662
- package/src/evm/toolbox/arb.ts +0 -61
- package/src/evm/toolbox/avax.ts +0 -36
- package/src/evm/toolbox/base.ts +0 -42
- package/src/evm/toolbox/bsc.ts +0 -34
- package/src/evm/toolbox/eth.ts +0 -44
- package/src/evm/toolbox/getToolboxByChain.ts +0 -42
- package/src/evm/toolbox/matic.ts +0 -42
- package/src/radix/toolbox.ts +0 -693
- package/src/substrate/toolbox/index.ts +0 -40
- package/src/substrate/types/index.ts +0 -2
- package/src/substrate/types/network.ts +0 -42
- package/src/substrate/types/wallet.ts +0 -78
- package/src/utxo/helpers/utils.ts +0 -45
|
@@ -1,662 +0,0 @@
|
|
|
1
|
-
import {
|
|
2
|
-
type Asset,
|
|
3
|
-
type AssetValue,
|
|
4
|
-
Chain,
|
|
5
|
-
ContractAddress,
|
|
6
|
-
type EVMChain,
|
|
7
|
-
FeeOption,
|
|
8
|
-
SwapKitError,
|
|
9
|
-
SwapKitNumber,
|
|
10
|
-
type WalletTxParams,
|
|
11
|
-
isGasAsset,
|
|
12
|
-
} from "@swapkit/helpers";
|
|
13
|
-
import { erc20ABI } from "@swapkit/helpers/contracts";
|
|
14
|
-
import {
|
|
15
|
-
BrowserProvider,
|
|
16
|
-
Contract,
|
|
17
|
-
type ContractTransaction,
|
|
18
|
-
type Fragment,
|
|
19
|
-
type HDNodeWallet,
|
|
20
|
-
Interface,
|
|
21
|
-
type JsonFragment,
|
|
22
|
-
type JsonRpcSigner,
|
|
23
|
-
MaxInt256,
|
|
24
|
-
type Provider,
|
|
25
|
-
type Signer,
|
|
26
|
-
getAddress,
|
|
27
|
-
hexlify,
|
|
28
|
-
toUtf8Bytes,
|
|
29
|
-
} from "ethers";
|
|
30
|
-
|
|
31
|
-
import {
|
|
32
|
-
type ARBToolbox,
|
|
33
|
-
type AVAXToolbox,
|
|
34
|
-
type BASEToolbox,
|
|
35
|
-
type BSCToolbox,
|
|
36
|
-
type ETHToolbox,
|
|
37
|
-
type MATICToolbox,
|
|
38
|
-
type OPToolbox,
|
|
39
|
-
toHexString,
|
|
40
|
-
} from "../index";
|
|
41
|
-
import type {
|
|
42
|
-
ApproveParams,
|
|
43
|
-
ApprovedParams,
|
|
44
|
-
CallParams,
|
|
45
|
-
EIP1559TxParams,
|
|
46
|
-
EVMTxParams,
|
|
47
|
-
EstimateCallParams,
|
|
48
|
-
IsApprovedParams,
|
|
49
|
-
LegacyEVMTxParams,
|
|
50
|
-
TransferParams,
|
|
51
|
-
} from "../types";
|
|
52
|
-
|
|
53
|
-
export const MAX_APPROVAL = MaxInt256;
|
|
54
|
-
|
|
55
|
-
const baseAssetAddress: Record<EVMChain, string> = {
|
|
56
|
-
[Chain.Arbitrum]: ContractAddress.ARB,
|
|
57
|
-
[Chain.Avalanche]: ContractAddress.AVAX,
|
|
58
|
-
[Chain.Base]: ContractAddress.BASE,
|
|
59
|
-
[Chain.BinanceSmartChain]: ContractAddress.BSC,
|
|
60
|
-
[Chain.Ethereum]: ContractAddress.ETH,
|
|
61
|
-
[Chain.Optimism]: ContractAddress.OP,
|
|
62
|
-
[Chain.Polygon]: ContractAddress.MATIC,
|
|
63
|
-
};
|
|
64
|
-
|
|
65
|
-
const stateMutable = ["payable", "nonpayable"];
|
|
66
|
-
// const nonStateMutable = ['view', 'pure'];
|
|
67
|
-
|
|
68
|
-
const isEIP1559Transaction = (tx: EVMTxParams) =>
|
|
69
|
-
(tx as EIP1559TxParams).type === 2 ||
|
|
70
|
-
!!(tx as EIP1559TxParams).maxFeePerGas ||
|
|
71
|
-
!!(tx as EIP1559TxParams).maxPriorityFeePerGas;
|
|
72
|
-
|
|
73
|
-
export const isBrowserProvider = (provider: any) => provider instanceof BrowserProvider;
|
|
74
|
-
export const createContract = (
|
|
75
|
-
address: string,
|
|
76
|
-
abi: readonly (JsonFragment | Fragment)[],
|
|
77
|
-
provider: Provider,
|
|
78
|
-
) => {
|
|
79
|
-
return new Contract(address, Interface.from(abi), provider);
|
|
80
|
-
};
|
|
81
|
-
|
|
82
|
-
const validateAddress = (address: string) => {
|
|
83
|
-
try {
|
|
84
|
-
getAddress(address);
|
|
85
|
-
return true;
|
|
86
|
-
} catch (_error) {
|
|
87
|
-
return false;
|
|
88
|
-
}
|
|
89
|
-
};
|
|
90
|
-
|
|
91
|
-
export const isStateChangingCall = (abi: readonly JsonFragment[], functionName: string) => {
|
|
92
|
-
const abiFragment = abi.find((fragment: any) => fragment.name === functionName) as any;
|
|
93
|
-
if (!abiFragment) throw new SwapKitError("toolbox_evm_no_abi_fragment", { functionName });
|
|
94
|
-
return abiFragment.stateMutability && stateMutable.includes(abiFragment.stateMutability);
|
|
95
|
-
};
|
|
96
|
-
|
|
97
|
-
export type WithSigner<T> = T & { signer?: Signer };
|
|
98
|
-
|
|
99
|
-
/**
|
|
100
|
-
* @info call contract function
|
|
101
|
-
* When using this method to make a non state changing call to the blockchain, like a isApproved call,
|
|
102
|
-
* the signer needs to be set to undefined
|
|
103
|
-
*/
|
|
104
|
-
const call = async <T>(
|
|
105
|
-
provider: Provider,
|
|
106
|
-
isEIP1559Compatible: boolean,
|
|
107
|
-
{
|
|
108
|
-
callProvider,
|
|
109
|
-
signer,
|
|
110
|
-
contractAddress,
|
|
111
|
-
abi,
|
|
112
|
-
funcName,
|
|
113
|
-
funcParams = [],
|
|
114
|
-
txOverrides = {},
|
|
115
|
-
feeOption = FeeOption.Fast,
|
|
116
|
-
}: WithSigner<CallParams>,
|
|
117
|
-
): Promise<T> => {
|
|
118
|
-
const contractProvider = callProvider || provider;
|
|
119
|
-
if (!contractAddress) throw new Error("contractAddress must be provided");
|
|
120
|
-
|
|
121
|
-
const isStateChanging = isStateChangingCall(abi, funcName);
|
|
122
|
-
const overridesParams = {
|
|
123
|
-
...txOverrides,
|
|
124
|
-
from: txOverrides?.from || (await signer?.getAddress()),
|
|
125
|
-
};
|
|
126
|
-
|
|
127
|
-
if (isStateChanging && isBrowserProvider(contractProvider) && signer) {
|
|
128
|
-
const txObject = await createContractTxObject(contractProvider, {
|
|
129
|
-
contractAddress,
|
|
130
|
-
abi,
|
|
131
|
-
funcName,
|
|
132
|
-
funcParams,
|
|
133
|
-
txOverrides: overridesParams,
|
|
134
|
-
});
|
|
135
|
-
|
|
136
|
-
return EIP1193SendTransaction(contractProvider, txObject) as Promise<T>;
|
|
137
|
-
}
|
|
138
|
-
const contract = createContract(contractAddress, abi, contractProvider);
|
|
139
|
-
|
|
140
|
-
// only use signer if the contract function is state changing
|
|
141
|
-
if (isStateChanging) {
|
|
142
|
-
if (!signer) throw new SwapKitError("toolbox_evm_no_signer");
|
|
143
|
-
|
|
144
|
-
const address = txOverrides?.from || (await signer.getAddress());
|
|
145
|
-
|
|
146
|
-
if (!address) throw new SwapKitError("toolbox_evm_no_signer_address");
|
|
147
|
-
|
|
148
|
-
const connectedContract = contract.connect(signer);
|
|
149
|
-
const { maxFeePerGas, maxPriorityFeePerGas, gasPrice } = (
|
|
150
|
-
await estimateGasPrices(provider, isEIP1559Compatible)
|
|
151
|
-
)[feeOption];
|
|
152
|
-
|
|
153
|
-
const gasLimit = await contract.getFunction(funcName).estimateGas(...funcParams, txOverrides);
|
|
154
|
-
|
|
155
|
-
// @ts-expect-error
|
|
156
|
-
const result = await connectedContract[funcName](...funcParams, {
|
|
157
|
-
...txOverrides,
|
|
158
|
-
gasLimit,
|
|
159
|
-
maxFeePerGas,
|
|
160
|
-
maxPriorityFeePerGas,
|
|
161
|
-
gasPrice,
|
|
162
|
-
/**
|
|
163
|
-
* nonce must be set due to a possible bug with ethers.js,
|
|
164
|
-
* expecting a synchronous nonce while the JsonRpcProvider delivers Promise
|
|
165
|
-
*/
|
|
166
|
-
nonce: txOverrides?.nonce || (await contractProvider.getTransactionCount(address)),
|
|
167
|
-
});
|
|
168
|
-
|
|
169
|
-
return typeof result?.hash === "string" ? result?.hash : result;
|
|
170
|
-
}
|
|
171
|
-
|
|
172
|
-
const result = await contract[funcName]?.(...funcParams);
|
|
173
|
-
|
|
174
|
-
return typeof result?.hash === "string" ? result?.hash : result;
|
|
175
|
-
};
|
|
176
|
-
|
|
177
|
-
export const createContractTxObject = async (
|
|
178
|
-
provider: Provider,
|
|
179
|
-
{ contractAddress, abi, funcName, funcParams = [], txOverrides }: CallParams,
|
|
180
|
-
) =>
|
|
181
|
-
createContract(contractAddress, abi, provider)
|
|
182
|
-
.getFunction(funcName)
|
|
183
|
-
.populateTransaction(...funcParams.concat(txOverrides).filter((p) => typeof p !== "undefined"));
|
|
184
|
-
|
|
185
|
-
const approvedAmount = async (
|
|
186
|
-
provider: Provider,
|
|
187
|
-
{ assetAddress, spenderAddress, from }: IsApprovedParams,
|
|
188
|
-
) =>
|
|
189
|
-
await call<bigint>(provider, true, {
|
|
190
|
-
contractAddress: assetAddress,
|
|
191
|
-
abi: erc20ABI as any,
|
|
192
|
-
funcName: "allowance",
|
|
193
|
-
funcParams: [from, spenderAddress],
|
|
194
|
-
});
|
|
195
|
-
|
|
196
|
-
const isApproved = async (
|
|
197
|
-
provider: Provider,
|
|
198
|
-
{ assetAddress, spenderAddress, from, amount = MAX_APPROVAL }: IsApprovedParams,
|
|
199
|
-
) => {
|
|
200
|
-
return SwapKitNumber.fromBigInt(
|
|
201
|
-
await approvedAmount(provider, { assetAddress, spenderAddress, from }),
|
|
202
|
-
).gte(SwapKitNumber.fromBigInt(BigInt(amount)));
|
|
203
|
-
};
|
|
204
|
-
|
|
205
|
-
const approve = async (
|
|
206
|
-
provider: Provider,
|
|
207
|
-
{
|
|
208
|
-
assetAddress,
|
|
209
|
-
spenderAddress,
|
|
210
|
-
feeOptionKey = FeeOption.Fast,
|
|
211
|
-
amount,
|
|
212
|
-
gasLimitFallback,
|
|
213
|
-
from,
|
|
214
|
-
nonce,
|
|
215
|
-
}: ApproveParams,
|
|
216
|
-
signer?: Signer,
|
|
217
|
-
isEIP1559Compatible = true,
|
|
218
|
-
) => {
|
|
219
|
-
const funcParams = [spenderAddress, BigInt(amount || MAX_APPROVAL)];
|
|
220
|
-
const txOverrides = { from };
|
|
221
|
-
|
|
222
|
-
const functionCallParams = {
|
|
223
|
-
contractAddress: assetAddress,
|
|
224
|
-
abi: erc20ABI,
|
|
225
|
-
funcName: "approve",
|
|
226
|
-
funcParams,
|
|
227
|
-
signer,
|
|
228
|
-
txOverrides,
|
|
229
|
-
};
|
|
230
|
-
|
|
231
|
-
if (isBrowserProvider(provider)) {
|
|
232
|
-
return EIP1193SendTransaction(
|
|
233
|
-
provider,
|
|
234
|
-
await createContractTxObject(provider, functionCallParams),
|
|
235
|
-
);
|
|
236
|
-
}
|
|
237
|
-
|
|
238
|
-
return call<string>(provider, isEIP1559Compatible, {
|
|
239
|
-
...functionCallParams,
|
|
240
|
-
funcParams,
|
|
241
|
-
txOverrides: {
|
|
242
|
-
from,
|
|
243
|
-
nonce,
|
|
244
|
-
gasLimit: gasLimitFallback ? BigInt(gasLimitFallback.toString()) : undefined,
|
|
245
|
-
},
|
|
246
|
-
feeOption: feeOptionKey,
|
|
247
|
-
});
|
|
248
|
-
};
|
|
249
|
-
|
|
250
|
-
const transfer = async (
|
|
251
|
-
provider: Provider | BrowserProvider,
|
|
252
|
-
{
|
|
253
|
-
assetValue,
|
|
254
|
-
memo,
|
|
255
|
-
recipient,
|
|
256
|
-
feeOptionKey = FeeOption.Fast,
|
|
257
|
-
data,
|
|
258
|
-
from: fromOverride,
|
|
259
|
-
maxFeePerGas,
|
|
260
|
-
maxPriorityFeePerGas,
|
|
261
|
-
gasPrice,
|
|
262
|
-
...tx
|
|
263
|
-
}: TransferParams,
|
|
264
|
-
signer?: Signer,
|
|
265
|
-
isEIP1559Compatible = true,
|
|
266
|
-
) => {
|
|
267
|
-
const txAmount = assetValue.getBaseValue("bigint");
|
|
268
|
-
const chain = assetValue.chain as EVMChain;
|
|
269
|
-
|
|
270
|
-
const from = fromOverride || (await signer?.getAddress());
|
|
271
|
-
|
|
272
|
-
if (!from) throw new SwapKitError("toolbox_evm_no_from_address");
|
|
273
|
-
|
|
274
|
-
if (!assetValue.isGasAsset) {
|
|
275
|
-
const contractAddress = getTokenAddress(assetValue, chain);
|
|
276
|
-
if (!contractAddress) throw new SwapKitError("toolbox_evm_no_contract_address");
|
|
277
|
-
|
|
278
|
-
// Transfer ERC20
|
|
279
|
-
return call<string>(provider, isEIP1559Compatible, {
|
|
280
|
-
signer,
|
|
281
|
-
contractAddress,
|
|
282
|
-
abi: erc20ABI,
|
|
283
|
-
funcName: "transfer",
|
|
284
|
-
funcParams: [recipient, txAmount],
|
|
285
|
-
txOverrides: { from, maxFeePerGas, maxPriorityFeePerGas, gasPrice },
|
|
286
|
-
feeOption: feeOptionKey,
|
|
287
|
-
});
|
|
288
|
-
}
|
|
289
|
-
// Transfer ETH
|
|
290
|
-
const txObject = {
|
|
291
|
-
...tx,
|
|
292
|
-
from,
|
|
293
|
-
to: recipient,
|
|
294
|
-
value: txAmount,
|
|
295
|
-
data: data || hexlify(toUtf8Bytes(memo || "")),
|
|
296
|
-
};
|
|
297
|
-
|
|
298
|
-
return sendTransaction(provider, txObject, feeOptionKey, signer, isEIP1559Compatible);
|
|
299
|
-
};
|
|
300
|
-
|
|
301
|
-
export const estimateGasPrices = async (provider: Provider, isEIP1559Compatible = true) => {
|
|
302
|
-
try {
|
|
303
|
-
const { maxFeePerGas, maxPriorityFeePerGas, gasPrice } = await provider.getFeeData();
|
|
304
|
-
|
|
305
|
-
if (isEIP1559Compatible) {
|
|
306
|
-
if (maxFeePerGas === null || maxPriorityFeePerGas === null)
|
|
307
|
-
throw new SwapKitError("toolbox_evm_no_fee_data");
|
|
308
|
-
|
|
309
|
-
return {
|
|
310
|
-
[FeeOption.Average]: { maxFeePerGas, maxPriorityFeePerGas },
|
|
311
|
-
[FeeOption.Fast]: {
|
|
312
|
-
maxFeePerGas: (maxFeePerGas * 15n) / 10n,
|
|
313
|
-
maxPriorityFeePerGas: (maxPriorityFeePerGas * 15n) / 10n,
|
|
314
|
-
},
|
|
315
|
-
[FeeOption.Fastest]: {
|
|
316
|
-
maxFeePerGas: maxFeePerGas * 2n,
|
|
317
|
-
maxPriorityFeePerGas: maxPriorityFeePerGas * 2n,
|
|
318
|
-
},
|
|
319
|
-
};
|
|
320
|
-
}
|
|
321
|
-
if (!gasPrice) throw new SwapKitError("toolbox_evm_no_gas_price");
|
|
322
|
-
|
|
323
|
-
return {
|
|
324
|
-
[FeeOption.Average]: { gasPrice },
|
|
325
|
-
[FeeOption.Fast]: { gasPrice: (gasPrice * 15n) / 10n },
|
|
326
|
-
[FeeOption.Fastest]: { gasPrice: gasPrice * 2n },
|
|
327
|
-
};
|
|
328
|
-
} catch (error) {
|
|
329
|
-
throw new Error(
|
|
330
|
-
`Failed to estimate gas price: ${(error as any).msg ?? (error as any).toString()}`,
|
|
331
|
-
);
|
|
332
|
-
}
|
|
333
|
-
};
|
|
334
|
-
|
|
335
|
-
const estimateCall = (
|
|
336
|
-
provider: Provider,
|
|
337
|
-
{
|
|
338
|
-
signer,
|
|
339
|
-
contractAddress,
|
|
340
|
-
abi,
|
|
341
|
-
funcName,
|
|
342
|
-
funcParams = [],
|
|
343
|
-
txOverrides,
|
|
344
|
-
}: WithSigner<EstimateCallParams>,
|
|
345
|
-
) => {
|
|
346
|
-
if (!contractAddress) throw new SwapKitError("toolbox_evm_no_contract_address");
|
|
347
|
-
|
|
348
|
-
const contract = createContract(contractAddress, abi, provider);
|
|
349
|
-
return signer
|
|
350
|
-
? contract
|
|
351
|
-
.connect(signer)
|
|
352
|
-
.getFunction(funcName)
|
|
353
|
-
.estimateGas(...funcParams, txOverrides)
|
|
354
|
-
: contract.getFunction(funcName).estimateGas(...funcParams, txOverrides);
|
|
355
|
-
};
|
|
356
|
-
|
|
357
|
-
const estimateGasLimit = (
|
|
358
|
-
provider: Provider,
|
|
359
|
-
{
|
|
360
|
-
assetValue,
|
|
361
|
-
recipient,
|
|
362
|
-
memo,
|
|
363
|
-
from,
|
|
364
|
-
funcName,
|
|
365
|
-
funcParams,
|
|
366
|
-
txOverrides,
|
|
367
|
-
signer,
|
|
368
|
-
}: WalletTxParams & {
|
|
369
|
-
assetValue: AssetValue;
|
|
370
|
-
funcName?: string;
|
|
371
|
-
funcParams?: unknown[];
|
|
372
|
-
signer?: Signer;
|
|
373
|
-
txOverrides?: EVMTxParams;
|
|
374
|
-
},
|
|
375
|
-
) => {
|
|
376
|
-
// const value = assetValue.getBaseValue("bigint");
|
|
377
|
-
const value = assetValue.bigIntValue;
|
|
378
|
-
|
|
379
|
-
const assetAddress = assetValue.isGasAsset
|
|
380
|
-
? null
|
|
381
|
-
: getTokenAddress(assetValue, assetValue.chain as EVMChain);
|
|
382
|
-
|
|
383
|
-
if (assetAddress && funcName) {
|
|
384
|
-
// ERC20 gas estimate
|
|
385
|
-
return estimateCall(provider, {
|
|
386
|
-
contractAddress: assetAddress,
|
|
387
|
-
abi: erc20ABI,
|
|
388
|
-
funcName,
|
|
389
|
-
funcParams,
|
|
390
|
-
txOverrides,
|
|
391
|
-
signer,
|
|
392
|
-
});
|
|
393
|
-
}
|
|
394
|
-
|
|
395
|
-
return provider.estimateGas({
|
|
396
|
-
from,
|
|
397
|
-
to: recipient,
|
|
398
|
-
value,
|
|
399
|
-
data: memo ? hexlify(toUtf8Bytes(memo)) : undefined,
|
|
400
|
-
});
|
|
401
|
-
};
|
|
402
|
-
|
|
403
|
-
const sendTransaction = async (
|
|
404
|
-
provider: Provider | BrowserProvider,
|
|
405
|
-
tx: EVMTxParams,
|
|
406
|
-
feeOptionKey: FeeOption = FeeOption.Fast,
|
|
407
|
-
signer?: Signer,
|
|
408
|
-
isEIP1559Compatible = true,
|
|
409
|
-
// biome-ignore lint/complexity/noExcessiveCognitiveComplexity: TODO: refactor
|
|
410
|
-
) => {
|
|
411
|
-
if (!signer) throw new SwapKitError("toolbox_evm_no_signer");
|
|
412
|
-
const { from, to, data, value, ...transaction } = tx;
|
|
413
|
-
if (!to) throw new SwapKitError("toolbox_evm_no_to_address");
|
|
414
|
-
|
|
415
|
-
const parsedTxObject = {
|
|
416
|
-
...transaction,
|
|
417
|
-
data: data || "0x",
|
|
418
|
-
to,
|
|
419
|
-
from,
|
|
420
|
-
value: BigInt(value || 0),
|
|
421
|
-
};
|
|
422
|
-
|
|
423
|
-
// early return to skip gas estimation if provider is EIP-1193
|
|
424
|
-
if (isBrowserProvider(provider)) {
|
|
425
|
-
return EIP1193SendTransaction(provider, parsedTxObject);
|
|
426
|
-
}
|
|
427
|
-
|
|
428
|
-
const address = from || (await signer.getAddress());
|
|
429
|
-
const nonce = tx.nonce || (await provider.getTransactionCount(address));
|
|
430
|
-
const chainId = (await provider.getNetwork()).chainId;
|
|
431
|
-
|
|
432
|
-
const isEIP1559 = isEIP1559Transaction(parsedTxObject) || isEIP1559Compatible;
|
|
433
|
-
|
|
434
|
-
const feeData =
|
|
435
|
-
(isEIP1559 &&
|
|
436
|
-
!(
|
|
437
|
-
(parsedTxObject as EIP1559TxParams).maxFeePerGas &&
|
|
438
|
-
(parsedTxObject as EIP1559TxParams).maxPriorityFeePerGas
|
|
439
|
-
)) ||
|
|
440
|
-
!(parsedTxObject as LegacyEVMTxParams).gasPrice
|
|
441
|
-
? Object.entries(
|
|
442
|
-
(await estimateGasPrices(provider, isEIP1559Compatible))[feeOptionKey],
|
|
443
|
-
).reduce(
|
|
444
|
-
// biome-ignore lint/performance/noAccumulatingSpread: this is a small object
|
|
445
|
-
(acc, [k, v]) => ({ ...acc, [k]: toHexString(BigInt(v)) }),
|
|
446
|
-
{} as {
|
|
447
|
-
maxFeePerGas?: string;
|
|
448
|
-
maxPriorityFeePerGas?: string;
|
|
449
|
-
gasPrice?: string;
|
|
450
|
-
},
|
|
451
|
-
)
|
|
452
|
-
: {};
|
|
453
|
-
let gasLimit: string;
|
|
454
|
-
try {
|
|
455
|
-
gasLimit = toHexString(
|
|
456
|
-
parsedTxObject.gasLimit || ((await provider.estimateGas(parsedTxObject)) * 11n) / 10n,
|
|
457
|
-
);
|
|
458
|
-
} catch (error) {
|
|
459
|
-
throw new SwapKitError("toolbox_evm_error_estimating_gas_limit", { error });
|
|
460
|
-
}
|
|
461
|
-
|
|
462
|
-
try {
|
|
463
|
-
const txObject = {
|
|
464
|
-
...parsedTxObject,
|
|
465
|
-
chainId,
|
|
466
|
-
type: isEIP1559 ? 2 : 0,
|
|
467
|
-
gasLimit,
|
|
468
|
-
nonce,
|
|
469
|
-
...feeData,
|
|
470
|
-
};
|
|
471
|
-
|
|
472
|
-
try {
|
|
473
|
-
const response = await signer.sendTransaction(txObject);
|
|
474
|
-
return response.hash;
|
|
475
|
-
} catch (_error) {
|
|
476
|
-
const txHex = await signer.signTransaction({
|
|
477
|
-
...txObject,
|
|
478
|
-
from: address,
|
|
479
|
-
});
|
|
480
|
-
const response = await provider.broadcastTransaction(txHex);
|
|
481
|
-
return response.hash;
|
|
482
|
-
}
|
|
483
|
-
} catch (error) {
|
|
484
|
-
throw new SwapKitError("toolbox_evm_error_sending_transaction", { error });
|
|
485
|
-
}
|
|
486
|
-
};
|
|
487
|
-
|
|
488
|
-
/**
|
|
489
|
-
* Exported helper functions
|
|
490
|
-
*/
|
|
491
|
-
export const toChecksumAddress = (address: string) => getAddress(address);
|
|
492
|
-
|
|
493
|
-
export const EIP1193SendTransaction = (
|
|
494
|
-
provider: Provider | BrowserProvider,
|
|
495
|
-
{ from, to, data, value }: EVMTxParams | ContractTransaction,
|
|
496
|
-
): Promise<string> => {
|
|
497
|
-
if (!isBrowserProvider(provider))
|
|
498
|
-
throw new SwapKitError("toolbox_evm_provider_not_eip1193_compatible");
|
|
499
|
-
return (provider as BrowserProvider).send("eth_sendTransaction", [
|
|
500
|
-
{ value: toHexString(BigInt(value || 0)), from, to, data } as any,
|
|
501
|
-
]);
|
|
502
|
-
};
|
|
503
|
-
|
|
504
|
-
export const getChecksumAddressFromAsset = (asset: Asset, chain: EVMChain) => {
|
|
505
|
-
const assetAddress = getTokenAddress(asset, chain);
|
|
506
|
-
|
|
507
|
-
if (assetAddress) {
|
|
508
|
-
return getAddress(assetAddress.toLowerCase());
|
|
509
|
-
}
|
|
510
|
-
|
|
511
|
-
throw new SwapKitError("toolbox_evm_invalid_gas_asset_address");
|
|
512
|
-
};
|
|
513
|
-
|
|
514
|
-
export const getTokenAddress = ({ chain, symbol, ticker }: Asset, baseAssetChain: EVMChain) => {
|
|
515
|
-
try {
|
|
516
|
-
const isBSCBNB = chain === Chain.BinanceSmartChain && symbol === "BNB" && ticker === "BNB";
|
|
517
|
-
const isBaseAsset =
|
|
518
|
-
chain === baseAssetChain && symbol === baseAssetChain && ticker === baseAssetChain;
|
|
519
|
-
const isEVMAsset =
|
|
520
|
-
[Chain.Arbitrum, Chain.Base].includes(chain) && symbol === "ETH" && ticker === "ETH";
|
|
521
|
-
|
|
522
|
-
if (isBaseAsset || isBSCBNB || isEVMAsset) {
|
|
523
|
-
return baseAssetAddress[baseAssetChain];
|
|
524
|
-
}
|
|
525
|
-
|
|
526
|
-
// strip 0X only - 0x is still valid
|
|
527
|
-
return getAddress(symbol.slice(ticker.length + 1).replace(/^0X/, ""));
|
|
528
|
-
} catch (_error) {
|
|
529
|
-
return null;
|
|
530
|
-
}
|
|
531
|
-
};
|
|
532
|
-
|
|
533
|
-
const createTransferTx = async (
|
|
534
|
-
provider: Provider | BrowserProvider,
|
|
535
|
-
{
|
|
536
|
-
assetValue,
|
|
537
|
-
memo,
|
|
538
|
-
recipient,
|
|
539
|
-
feeOptionKey = FeeOption.Fast,
|
|
540
|
-
data,
|
|
541
|
-
from: fromOverride,
|
|
542
|
-
maxFeePerGas,
|
|
543
|
-
maxPriorityFeePerGas,
|
|
544
|
-
gasPrice,
|
|
545
|
-
...tx
|
|
546
|
-
}: TransferParams,
|
|
547
|
-
signer?: Signer,
|
|
548
|
-
) => {
|
|
549
|
-
const txAmount = assetValue.getBaseValue("bigint");
|
|
550
|
-
const chain = assetValue.chain as EVMChain;
|
|
551
|
-
|
|
552
|
-
const from = fromOverride || (await signer?.getAddress());
|
|
553
|
-
|
|
554
|
-
if (!from) throw new SwapKitError("toolbox_evm_no_from_address");
|
|
555
|
-
|
|
556
|
-
if (!isGasAsset(assetValue)) {
|
|
557
|
-
const contractAddress = getTokenAddress(assetValue, chain);
|
|
558
|
-
if (!contractAddress) throw new SwapKitError("toolbox_evm_no_contract_address");
|
|
559
|
-
|
|
560
|
-
// Transfer ERC20
|
|
561
|
-
return createContractTxObject(provider, {
|
|
562
|
-
contractAddress,
|
|
563
|
-
abi: erc20ABI,
|
|
564
|
-
funcName: "transfer",
|
|
565
|
-
funcParams: [recipient, txAmount],
|
|
566
|
-
txOverrides: { from, maxFeePerGas, maxPriorityFeePerGas, gasPrice },
|
|
567
|
-
});
|
|
568
|
-
}
|
|
569
|
-
// Transfer ETH
|
|
570
|
-
const txObject = {
|
|
571
|
-
...tx,
|
|
572
|
-
from,
|
|
573
|
-
to: recipient,
|
|
574
|
-
value: txAmount,
|
|
575
|
-
data: data || hexlify(toUtf8Bytes(memo || "")),
|
|
576
|
-
};
|
|
577
|
-
|
|
578
|
-
return txObject;
|
|
579
|
-
};
|
|
580
|
-
|
|
581
|
-
const createApprovalTx = async (
|
|
582
|
-
provider: Provider,
|
|
583
|
-
{ assetAddress, spenderAddress, amount, from }: ApproveParams,
|
|
584
|
-
signer?: Signer,
|
|
585
|
-
) => {
|
|
586
|
-
const funcParams = [spenderAddress, BigInt(amount || MAX_APPROVAL)];
|
|
587
|
-
const txOverrides = { from };
|
|
588
|
-
|
|
589
|
-
const functionCallParams = {
|
|
590
|
-
contractAddress: assetAddress,
|
|
591
|
-
abi: erc20ABI,
|
|
592
|
-
funcName: "approve",
|
|
593
|
-
funcParams,
|
|
594
|
-
signer,
|
|
595
|
-
txOverrides,
|
|
596
|
-
};
|
|
597
|
-
|
|
598
|
-
const txObject = await createContractTxObject(provider, functionCallParams);
|
|
599
|
-
|
|
600
|
-
return txObject;
|
|
601
|
-
};
|
|
602
|
-
|
|
603
|
-
function signMessage(signer?: Signer | JsonRpcSigner | HDNodeWallet) {
|
|
604
|
-
if (!signer) throw new SwapKitError("toolbox_evm_no_signer");
|
|
605
|
-
|
|
606
|
-
return signer.signMessage;
|
|
607
|
-
}
|
|
608
|
-
|
|
609
|
-
export const EVMToolbox = ({
|
|
610
|
-
provider,
|
|
611
|
-
signer,
|
|
612
|
-
isEIP1559Compatible = true,
|
|
613
|
-
}: {
|
|
614
|
-
signer?: Signer | JsonRpcSigner | HDNodeWallet;
|
|
615
|
-
provider: Provider | BrowserProvider;
|
|
616
|
-
isEIP1559Compatible?: boolean;
|
|
617
|
-
}) => ({
|
|
618
|
-
approve: (params: ApproveParams) => approve(provider, params, signer, isEIP1559Compatible),
|
|
619
|
-
approvedAmount: (params: ApprovedParams) => approvedAmount(provider, params),
|
|
620
|
-
broadcastTransaction: provider.broadcastTransaction,
|
|
621
|
-
call: <T>(params: CallParams) => call<T>(provider, isEIP1559Compatible, { ...params, signer }),
|
|
622
|
-
createContract: (
|
|
623
|
-
address: string,
|
|
624
|
-
abi: (JsonFragment | Fragment)[],
|
|
625
|
-
contractProvider?: Provider,
|
|
626
|
-
) => createContract(address, abi, contractProvider || provider),
|
|
627
|
-
createContractTxObject: (params: CallParams) => createContractTxObject(provider, params),
|
|
628
|
-
EIP1193SendTransaction: (tx: EIP1559TxParams) => EIP1193SendTransaction(provider, tx),
|
|
629
|
-
estimateCall: (params: EstimateCallParams) => estimateCall(provider, { ...params, signer }),
|
|
630
|
-
estimateGasLimit: ({
|
|
631
|
-
assetValue,
|
|
632
|
-
recipient,
|
|
633
|
-
memo,
|
|
634
|
-
}: WalletTxParams & { assetValue: AssetValue }) =>
|
|
635
|
-
estimateGasLimit(provider, { assetValue, recipient, memo, signer }),
|
|
636
|
-
estimateGasPrices: () => estimateGasPrices(provider, isEIP1559Compatible),
|
|
637
|
-
isApproved: (params: IsApprovedParams) => isApproved(provider, params),
|
|
638
|
-
sendTransaction: (params: EIP1559TxParams, feeOption?: FeeOption) =>
|
|
639
|
-
sendTransaction(provider, params, feeOption, signer, isEIP1559Compatible),
|
|
640
|
-
transfer: (params: TransferParams) => transfer(provider, params, signer, isEIP1559Compatible),
|
|
641
|
-
validateAddress,
|
|
642
|
-
createTransferTx: (params: TransferParams) => createTransferTx(provider, params, signer),
|
|
643
|
-
createApprovalTx: (params: ApproveParams) => createApprovalTx(provider, params, signer),
|
|
644
|
-
signMessage: signMessage(signer),
|
|
645
|
-
});
|
|
646
|
-
|
|
647
|
-
export const evmValidateAddress = ({ address }: { address: string }) => validateAddress(address);
|
|
648
|
-
|
|
649
|
-
export type EVMWallet = ReturnType<typeof EVMToolbox>;
|
|
650
|
-
export type EVMWalletType = {
|
|
651
|
-
[Chain.Arbitrum]: ReturnType<typeof ARBToolbox>;
|
|
652
|
-
[Chain.Avalanche]: ReturnType<typeof AVAXToolbox>;
|
|
653
|
-
[Chain.Base]: ReturnType<typeof BASEToolbox>;
|
|
654
|
-
[Chain.BinanceSmartChain]: ReturnType<typeof BSCToolbox>;
|
|
655
|
-
[Chain.Ethereum]: ReturnType<typeof ETHToolbox>;
|
|
656
|
-
[Chain.Optimism]: ReturnType<typeof OPToolbox>;
|
|
657
|
-
[Chain.Polygon]: ReturnType<typeof MATICToolbox>;
|
|
658
|
-
};
|
|
659
|
-
|
|
660
|
-
export type EVMWallets = {
|
|
661
|
-
[chain in EVMChain]: EVMWallet & EVMWalletType[chain];
|
|
662
|
-
};
|
package/src/evm/toolbox/arb.ts
DELETED
|
@@ -1,61 +0,0 @@
|
|
|
1
|
-
import {
|
|
2
|
-
BaseDecimal,
|
|
3
|
-
Chain,
|
|
4
|
-
ChainId,
|
|
5
|
-
ChainToExplorerUrl,
|
|
6
|
-
FeeOption,
|
|
7
|
-
SKConfig,
|
|
8
|
-
} from "@swapkit/helpers";
|
|
9
|
-
import type { BrowserProvider, JsonRpcProvider, Provider, Signer } from "ethers";
|
|
10
|
-
|
|
11
|
-
import { type EVMTxBaseParams, estimateTransactionFee, getBalance } from "../index";
|
|
12
|
-
|
|
13
|
-
import { EVMToolbox } from "./EVMToolbox";
|
|
14
|
-
|
|
15
|
-
const getNetworkParams = () => ({
|
|
16
|
-
chainId: ChainId.ArbitrumHex,
|
|
17
|
-
chainName: "Arbitrum One",
|
|
18
|
-
nativeCurrency: { name: "Ethereum", symbol: Chain.Ethereum, decimals: BaseDecimal.ETH },
|
|
19
|
-
rpcUrls: [SKConfig.get("rpcUrls")[Chain.Arbitrum]],
|
|
20
|
-
blockExplorerUrls: [ChainToExplorerUrl[Chain.Arbitrum]],
|
|
21
|
-
});
|
|
22
|
-
|
|
23
|
-
const estimateGasPrices = async (provider: Provider) => {
|
|
24
|
-
try {
|
|
25
|
-
const { gasPrice } = await provider.getFeeData();
|
|
26
|
-
|
|
27
|
-
if (!gasPrice) throw new Error("No fee data available");
|
|
28
|
-
|
|
29
|
-
return {
|
|
30
|
-
[FeeOption.Average]: { gasPrice },
|
|
31
|
-
[FeeOption.Fast]: { gasPrice },
|
|
32
|
-
[FeeOption.Fastest]: { gasPrice },
|
|
33
|
-
};
|
|
34
|
-
} catch (error) {
|
|
35
|
-
throw new Error(
|
|
36
|
-
`Failed to estimate gas price: ${(error as any).msg ?? (error as any).toString()}`,
|
|
37
|
-
);
|
|
38
|
-
}
|
|
39
|
-
};
|
|
40
|
-
|
|
41
|
-
export const ARBToolbox = ({
|
|
42
|
-
provider,
|
|
43
|
-
signer,
|
|
44
|
-
}: { signer?: Signer; provider: JsonRpcProvider | BrowserProvider }) => {
|
|
45
|
-
const evmToolbox = EVMToolbox({ provider, signer, isEIP1559Compatible: false });
|
|
46
|
-
const chain = Chain.Arbitrum;
|
|
47
|
-
|
|
48
|
-
return {
|
|
49
|
-
...evmToolbox,
|
|
50
|
-
getNetworkParams,
|
|
51
|
-
estimateGasPrices: () => estimateGasPrices(provider),
|
|
52
|
-
estimateTransactionFee: (txObject: EVMTxBaseParams) =>
|
|
53
|
-
estimateTransactionFee(txObject, FeeOption.Average, chain, provider, false),
|
|
54
|
-
getBalance: (
|
|
55
|
-
address: string,
|
|
56
|
-
potentialScamFilter = true,
|
|
57
|
-
overwriteProvider?: JsonRpcProvider | BrowserProvider,
|
|
58
|
-
) =>
|
|
59
|
-
getBalance({ provider: overwriteProvider || provider, address, chain, potentialScamFilter }),
|
|
60
|
-
};
|
|
61
|
-
};
|