@swapkit/toolboxes 1.0.0-beta.0 → 1.0.0-beta.2
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,147 +1,141 @@
|
|
|
1
1
|
import { afterEach, beforeAll, beforeEach, describe, expect, test } from "bun:test";
|
|
2
2
|
import type ethers from "@nomicfoundation/hardhat-ethers";
|
|
3
|
-
import
|
|
3
|
+
import helpers from "@nomicfoundation/hardhat-network-helpers";
|
|
4
|
+
import { AssetValue, Chain, SKConfig } from "@swapkit/helpers";
|
|
4
5
|
import { erc20ABI } from "@swapkit/helpers/contracts";
|
|
5
6
|
import type { JsonRpcProvider } from "ethers";
|
|
6
|
-
|
|
7
|
+
import hre from "hardhat";
|
|
8
|
+
import { getProvider } from "../helpers";
|
|
9
|
+
import { getEvmToolbox } from "../toolbox";
|
|
7
10
|
|
|
8
|
-
import type { ETHToolbox } from "../index";
|
|
9
11
|
const testAddress = "0x6d6e022eE439C8aB8B7a7dBb0576f8090319CDc6";
|
|
10
12
|
const emptyRecipient = "0xE29E61479420Dd1029A9946710Ac31A0d140e77F";
|
|
11
13
|
const USDCAddress = "0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48";
|
|
12
14
|
// Get latest block to use as base for reset fork after test
|
|
13
|
-
|
|
15
|
+
const block = await hre.ethers.provider.getBlock("latest");
|
|
14
16
|
|
|
15
17
|
beforeAll(() => {
|
|
16
|
-
|
|
18
|
+
hre.run("node");
|
|
17
19
|
});
|
|
18
20
|
|
|
19
21
|
const context: {
|
|
20
22
|
ethers: typeof ethers;
|
|
21
23
|
provider: JsonRpcProvider;
|
|
22
|
-
toolbox: ReturnType<typeof
|
|
24
|
+
toolbox: Awaited<ReturnType<typeof getEvmToolbox>>;
|
|
23
25
|
} = {} as any;
|
|
24
26
|
|
|
25
27
|
beforeEach(async () => {
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
28
|
+
context.ethers = hre.artifacts;
|
|
29
|
+
const provider = await getProvider(Chain.Ethereum, "http://127.0.0.1:8545/");
|
|
30
|
+
const signer = await hre.ethers.getImpersonatedSigner(testAddress);
|
|
31
|
+
|
|
32
|
+
SKConfig.set({
|
|
33
|
+
apiKeys: {
|
|
34
|
+
swapKit: process.env.TEST_API_KEY || Bun.env.TEST_API_KEY,
|
|
35
|
+
},
|
|
36
|
+
});
|
|
37
|
+
context.provider = provider;
|
|
38
|
+
context.toolbox = await getEvmToolbox(Chain.Ethereum, { provider, signer });
|
|
31
39
|
});
|
|
32
40
|
|
|
33
41
|
afterEach(async () => {
|
|
34
|
-
|
|
42
|
+
await helpers.reset(hre.config.networks.hardhat.forking?.url, block?.number);
|
|
35
43
|
});
|
|
36
44
|
|
|
37
45
|
describe("Ethereum toolkit", () => {
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
(
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
46
|
+
// biome-ignore lint/suspicious/noSkippedTests: env not setup correctly
|
|
47
|
+
test.skip("Get Balances", async () => {
|
|
48
|
+
const balances = await context.toolbox.getBalance(testAddress);
|
|
49
|
+
expect(balances.find((balance) => balance.symbol === "ETH")?.getBaseValue("string")).toBe(
|
|
50
|
+
"20526000000000000",
|
|
51
|
+
);
|
|
52
|
+
expect(
|
|
53
|
+
balances
|
|
54
|
+
.find(
|
|
55
|
+
(balance) =>
|
|
56
|
+
balance.symbol.toLowerCase() ===
|
|
57
|
+
"USDC-0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48".toLowerCase(),
|
|
58
|
+
)
|
|
59
|
+
?.getBaseValue("string"),
|
|
60
|
+
).toBe("6656178");
|
|
61
|
+
}, 10000);
|
|
62
|
+
|
|
63
|
+
test("Send ETH", async () => {
|
|
64
|
+
expect((await context.provider.getBalance(emptyRecipient)).toString()).toBe("0");
|
|
65
|
+
await context.toolbox.transfer({
|
|
66
|
+
recipient: emptyRecipient,
|
|
67
|
+
assetValue: await AssetValue.from({ chain: Chain.Ethereum, value: "0.010526" }),
|
|
68
|
+
sender: testAddress,
|
|
69
|
+
});
|
|
70
|
+
expect((await context.provider.getBalance(emptyRecipient)).toString()).toBe(
|
|
71
|
+
"10526000000000000",
|
|
72
|
+
);
|
|
73
|
+
}, 10000);
|
|
74
|
+
|
|
75
|
+
test("Send Token", async () => {
|
|
76
|
+
const USDC = await context.toolbox.createContract(USDCAddress, erc20ABI);
|
|
77
|
+
const balance = await USDC.balanceOf?.(emptyRecipient);
|
|
78
|
+
expect(balance.toString()).toBe("0");
|
|
79
|
+
|
|
80
|
+
await AssetValue.loadStaticAssets(["thorchain"]);
|
|
81
|
+
|
|
82
|
+
const assetValue = AssetValue.from({
|
|
83
|
+
asset: "ETH.USDC-0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48",
|
|
84
|
+
value: "1",
|
|
85
|
+
});
|
|
86
|
+
|
|
87
|
+
await context.toolbox.transfer({
|
|
88
|
+
recipient: emptyRecipient,
|
|
89
|
+
assetValue,
|
|
90
|
+
sender: testAddress,
|
|
91
|
+
});
|
|
92
|
+
// biome-ignore lint/correctness/noUnsafeOptionalChaining: <explanation>
|
|
93
|
+
expect((await USDC.balanceOf?.(emptyRecipient)).toString()).toBe("1000000");
|
|
94
|
+
}, 10000);
|
|
95
|
+
|
|
96
|
+
test("Approve Token and validate approved amount", async () => {
|
|
97
|
+
expect(
|
|
98
|
+
await context.toolbox.isApproved({
|
|
99
|
+
assetAddress: USDCAddress,
|
|
100
|
+
spenderAddress: emptyRecipient,
|
|
86
101
|
from: testAddress,
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
assetAddress: USDCAddress,
|
|
100
|
-
spenderAddress: emptyRecipient,
|
|
101
|
-
from: testAddress,
|
|
102
|
-
amount: "1000000",
|
|
103
|
-
}),
|
|
104
|
-
).toBe(false);
|
|
105
|
-
await context.toolbox.approve({
|
|
102
|
+
amount: "1000000",
|
|
103
|
+
}),
|
|
104
|
+
).toBe(false);
|
|
105
|
+
|
|
106
|
+
await context.toolbox.approve({
|
|
107
|
+
assetAddress: USDCAddress,
|
|
108
|
+
spenderAddress: emptyRecipient,
|
|
109
|
+
amount: "1000000",
|
|
110
|
+
});
|
|
111
|
+
|
|
112
|
+
expect(
|
|
113
|
+
await context.toolbox.isApproved({
|
|
106
114
|
assetAddress: USDCAddress,
|
|
107
115
|
spenderAddress: emptyRecipient,
|
|
116
|
+
from: testAddress,
|
|
108
117
|
amount: "1000000",
|
|
118
|
+
}),
|
|
119
|
+
).toBe(true);
|
|
120
|
+
}, 10000);
|
|
121
|
+
|
|
122
|
+
test("Create contract tx object and sendTransaction", async () => {
|
|
123
|
+
const USDC = context.toolbox.createContract(USDCAddress, erc20ABI);
|
|
124
|
+
const balance = await USDC.balanceOf?.(emptyRecipient);
|
|
125
|
+
expect(balance.toString()).toBe("0");
|
|
126
|
+
|
|
127
|
+
const txObject = await context.toolbox.createContractTxObject({
|
|
128
|
+
contractAddress: USDCAddress,
|
|
129
|
+
abi: erc20ABI,
|
|
130
|
+
funcName: "transfer",
|
|
131
|
+
funcParams: [emptyRecipient, BigInt("2222222")],
|
|
132
|
+
txOverrides: {
|
|
109
133
|
from: testAddress,
|
|
110
|
-
}
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
amount: "1000000",
|
|
118
|
-
}),
|
|
119
|
-
).toBe(true);
|
|
120
|
-
},
|
|
121
|
-
10000,
|
|
122
|
-
);
|
|
123
|
-
|
|
124
|
-
test.todo(
|
|
125
|
-
"Create contract tx object and sendTransaction",
|
|
126
|
-
async () => {
|
|
127
|
-
const USDC = context.toolbox.createContract(USDCAddress, erc20ABI, context.provider);
|
|
128
|
-
const balance = await USDC.balanceOf?.(emptyRecipient);
|
|
129
|
-
expect(balance.toString()).toBe("0");
|
|
130
|
-
|
|
131
|
-
const txObject = await context.toolbox.createContractTxObject({
|
|
132
|
-
contractAddress: USDCAddress,
|
|
133
|
-
abi: erc20ABI,
|
|
134
|
-
funcName: "transfer",
|
|
135
|
-
funcParams: [emptyRecipient, BigInt("2222222")],
|
|
136
|
-
txOverrides: {
|
|
137
|
-
from: testAddress,
|
|
138
|
-
},
|
|
139
|
-
});
|
|
140
|
-
|
|
141
|
-
await context.toolbox.sendTransaction(txObject, FeeOption.Average);
|
|
142
|
-
// biome-ignore lint/correctness/noUnsafeOptionalChaining: <explanation>
|
|
143
|
-
expect((await USDC?.balanceOf?.(emptyRecipient)).toString()).toBe("2222222");
|
|
144
|
-
},
|
|
145
|
-
10000,
|
|
146
|
-
);
|
|
134
|
+
},
|
|
135
|
+
});
|
|
136
|
+
|
|
137
|
+
await context.toolbox.sendTransaction(txObject);
|
|
138
|
+
// biome-ignore lint/correctness/noUnsafeOptionalChaining: <explanation>
|
|
139
|
+
expect((await USDC?.balanceOf?.(emptyRecipient)).toString()).toBe("2222222");
|
|
140
|
+
}, 10000);
|
|
147
141
|
});
|
package/src/evm/api.ts
CHANGED
|
@@ -1,157 +1,21 @@
|
|
|
1
|
-
import {
|
|
2
|
-
|
|
3
|
-
ChainToChainId,
|
|
4
|
-
type EVMChain,
|
|
5
|
-
RequestClient,
|
|
6
|
-
SKConfig,
|
|
7
|
-
formatBigIntToSafeValue,
|
|
8
|
-
warnOnce,
|
|
9
|
-
} from "@swapkit/helpers";
|
|
1
|
+
import { type EVMChain, SKConfig, warnOnce } from "@swapkit/helpers";
|
|
2
|
+
import { getBalance } from "../utils";
|
|
10
3
|
|
|
11
|
-
|
|
12
|
-
const
|
|
13
|
-
|
|
14
|
-
const { tokens = [] } = await RequestClient.get<AddressInfo>(
|
|
15
|
-
`https://api.ethplorer.io/getAddressInfo/${address}`,
|
|
16
|
-
{ searchParams: { apiKey } },
|
|
17
|
-
);
|
|
18
|
-
|
|
19
|
-
return tokens
|
|
20
|
-
.filter(({ tokenInfo: { symbol }, rawBalance }) => symbol && rawBalance !== "0")
|
|
21
|
-
.map(({ tokenInfo: { symbol, decimals, address: tokenAddress }, rawBalance }) => ({
|
|
22
|
-
chain: Chain.Ethereum,
|
|
23
|
-
decimal: Number.parseInt(decimals),
|
|
24
|
-
symbol: tokenAddress ? `${symbol}-${tokenAddress}` : symbol,
|
|
25
|
-
value: formatBigIntToSafeValue({
|
|
26
|
-
value: BigInt(rawBalance),
|
|
27
|
-
decimal: Number.parseInt(decimals),
|
|
28
|
-
bigIntDecimal: Number.parseInt(decimals),
|
|
29
|
-
}),
|
|
30
|
-
}));
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
async function getCovalentBalance({ chain, address }: { chain: Chain; address: string }) {
|
|
34
|
-
const apiKey = SKConfig.get("apiKeys").covalent;
|
|
4
|
+
export function getEvmApi(chain: EVMChain) {
|
|
5
|
+
const customEvmApi = SKConfig.get("apis")[chain];
|
|
35
6
|
|
|
36
|
-
if (
|
|
37
|
-
warnOnce(true, "
|
|
38
|
-
return
|
|
7
|
+
if (customEvmApi) {
|
|
8
|
+
warnOnce(true, "Using custom EVM API. Be sure to implement all methods to avoid issues.");
|
|
9
|
+
return customEvmApi as ReturnType<typeof evmApi>;
|
|
39
10
|
}
|
|
40
11
|
|
|
41
|
-
|
|
42
|
-
`https://api.covalenthq.com/v1/${ChainToChainId[chain]}/address/${address}/balances_v2/`,
|
|
43
|
-
{ searchParams: { key: apiKey } },
|
|
44
|
-
);
|
|
45
|
-
|
|
46
|
-
return (data?.items || [])
|
|
47
|
-
.filter(({ is_spam }) => !is_spam)
|
|
48
|
-
.map(
|
|
49
|
-
({ balance, contract_decimals, contract_ticker_symbol, contract_address, native_token }) => ({
|
|
50
|
-
value: formatBigIntToSafeValue({
|
|
51
|
-
value: BigInt(balance),
|
|
52
|
-
decimal: contract_decimals,
|
|
53
|
-
bigIntDecimal: contract_decimals,
|
|
54
|
-
}),
|
|
55
|
-
decimal: contract_decimals,
|
|
56
|
-
chain,
|
|
57
|
-
symbol: `${contract_ticker_symbol || "Unknown"}${native_token ? "" : `-${contract_address}`}`,
|
|
58
|
-
}),
|
|
59
|
-
);
|
|
60
|
-
}
|
|
61
|
-
|
|
62
|
-
export function getEvmApi(chain: EVMChain) {
|
|
63
|
-
const getBalance = chain === Chain.Ethereum ? getEthplorerBalance : getCovalentBalance;
|
|
64
|
-
return { getBalance: (address: string) => getBalance({ address, chain }) };
|
|
12
|
+
return evmApi(chain);
|
|
65
13
|
}
|
|
66
14
|
|
|
67
15
|
export function createCustomEvmApi(methods: ReturnType<typeof getEvmApi>) {
|
|
68
16
|
return methods;
|
|
69
17
|
}
|
|
70
18
|
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
next_updated_at: string;
|
|
75
|
-
quote_currency: string;
|
|
76
|
-
items: {
|
|
77
|
-
is_spam: boolean;
|
|
78
|
-
contract_decimals: number;
|
|
79
|
-
contract_name: string;
|
|
80
|
-
contract_ticker_symbol: string;
|
|
81
|
-
contract_address: string;
|
|
82
|
-
logo_url: string;
|
|
83
|
-
last_transferred_at: string;
|
|
84
|
-
native_token: boolean;
|
|
85
|
-
type: string;
|
|
86
|
-
balance: number;
|
|
87
|
-
balance_24h: number;
|
|
88
|
-
quote_rate: number;
|
|
89
|
-
quote_rate_24h: number;
|
|
90
|
-
quote: number;
|
|
91
|
-
quote_24h: number;
|
|
92
|
-
}[];
|
|
93
|
-
};
|
|
94
|
-
|
|
95
|
-
type PriceInfo = {
|
|
96
|
-
rate: number;
|
|
97
|
-
diff: number;
|
|
98
|
-
diff7d?: number;
|
|
99
|
-
ts: number;
|
|
100
|
-
marketCapUsd?: number;
|
|
101
|
-
availableSupply?: number;
|
|
102
|
-
volume24h?: number;
|
|
103
|
-
diff30d?: number;
|
|
104
|
-
volDiff1?: number;
|
|
105
|
-
volDiff7?: number;
|
|
106
|
-
volDiff30?: number;
|
|
107
|
-
currency?: string;
|
|
108
|
-
};
|
|
109
|
-
|
|
110
|
-
type TokenInfo = {
|
|
111
|
-
address: string;
|
|
112
|
-
decimals: string;
|
|
113
|
-
name: string;
|
|
114
|
-
owner: string;
|
|
115
|
-
symbol: string;
|
|
116
|
-
totalSupply: string;
|
|
117
|
-
lastUpdated: number;
|
|
118
|
-
issuancesCount: number;
|
|
119
|
-
holdersCount: number;
|
|
120
|
-
image?: string;
|
|
121
|
-
description?: string;
|
|
122
|
-
website?: string;
|
|
123
|
-
twitter?: string;
|
|
124
|
-
facebook?: string;
|
|
125
|
-
coingecko?: string;
|
|
126
|
-
ethTransfersCount: number;
|
|
127
|
-
price: boolean | PriceInfo | unknown;
|
|
128
|
-
publicTags?: string[];
|
|
129
|
-
txsCount?: number;
|
|
130
|
-
transfersCount?: number;
|
|
131
|
-
};
|
|
132
|
-
|
|
133
|
-
type TokenBalance = {
|
|
134
|
-
tokenInfo: TokenInfo;
|
|
135
|
-
balance: number;
|
|
136
|
-
rawBalance: string;
|
|
137
|
-
totalIn?: number;
|
|
138
|
-
totalOut?: number;
|
|
139
|
-
};
|
|
140
|
-
|
|
141
|
-
export type AddressInfo = {
|
|
142
|
-
address: string;
|
|
143
|
-
ETH: {
|
|
144
|
-
balance: number;
|
|
145
|
-
totalIn?: number;
|
|
146
|
-
totalOut?: number;
|
|
147
|
-
price: PriceInfo;
|
|
148
|
-
};
|
|
149
|
-
contractInfo?: {
|
|
150
|
-
creatorAddress: string;
|
|
151
|
-
transactionHash: string;
|
|
152
|
-
timestamp: string;
|
|
153
|
-
};
|
|
154
|
-
tokenInfo?: TokenInfo;
|
|
155
|
-
tokens?: TokenBalance[];
|
|
156
|
-
countTxs: number;
|
|
157
|
-
};
|
|
19
|
+
function evmApi(chain: EVMChain) {
|
|
20
|
+
return { getBalance: getBalance(chain) };
|
|
21
|
+
}
|
package/src/evm/helpers.ts
CHANGED
|
@@ -1,20 +1,30 @@
|
|
|
1
1
|
import {
|
|
2
2
|
AssetValue,
|
|
3
3
|
BaseDecimal,
|
|
4
|
+
Chain,
|
|
5
|
+
ChainToExplorerUrl,
|
|
6
|
+
ChainToHexChainId,
|
|
4
7
|
type EVMChain,
|
|
5
8
|
FeeOption,
|
|
9
|
+
type NetworkParams,
|
|
10
|
+
SKConfig,
|
|
6
11
|
SwapKitNumber,
|
|
7
|
-
filterAssets,
|
|
8
|
-
formatBigIntToSafeValue,
|
|
9
|
-
isGasAsset,
|
|
10
12
|
} from "@swapkit/helpers";
|
|
11
|
-
import type { BrowserProvider,
|
|
13
|
+
import type { BrowserProvider, Provider } from "ethers";
|
|
12
14
|
|
|
13
|
-
import {
|
|
14
|
-
import {
|
|
15
|
+
import { getEstimateGasPrices } from "./toolbox/baseEVMToolbox";
|
|
16
|
+
import type { EIP1559TxParams, EVMMaxSendableAmountsParams } from "./types";
|
|
15
17
|
|
|
18
|
+
export async function getProvider(chain: EVMChain, customUrl?: string) {
|
|
19
|
+
const { JsonRpcProvider } = await import("ethers");
|
|
20
|
+
|
|
21
|
+
return new JsonRpcProvider(customUrl || SKConfig.get("rpcUrls")[chain]);
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
/**
|
|
25
|
+
* @deprecated
|
|
26
|
+
*/
|
|
16
27
|
export const estimateMaxSendableAmount = async ({
|
|
17
|
-
toolbox,
|
|
18
28
|
from,
|
|
19
29
|
memo = "",
|
|
20
30
|
feeOptionKey = FeeOption.Fastest,
|
|
@@ -25,7 +35,11 @@ export const estimateMaxSendableAmount = async ({
|
|
|
25
35
|
contractAddress,
|
|
26
36
|
txOverrides,
|
|
27
37
|
}: EVMMaxSendableAmountsParams): Promise<AssetValue> => {
|
|
28
|
-
const
|
|
38
|
+
const { getEvmToolbox } = await import("@swapkit/toolboxes/evm");
|
|
39
|
+
const toolbox = await getEvmToolbox(assetValue.chain as EVMChain);
|
|
40
|
+
|
|
41
|
+
const balances = await toolbox.getBalance(from);
|
|
42
|
+
const balance = balances.find(({ symbol, chain }) =>
|
|
29
43
|
assetValue ? symbol === assetValue.symbol : symbol === AssetValue.from({ chain })?.symbol,
|
|
30
44
|
);
|
|
31
45
|
|
|
@@ -47,24 +61,24 @@ export const estimateMaxSendableAmount = async ({
|
|
|
47
61
|
txOverrides,
|
|
48
62
|
})
|
|
49
63
|
: await toolbox.estimateGasLimit({
|
|
50
|
-
from,
|
|
64
|
+
sender: from,
|
|
51
65
|
recipient: from,
|
|
52
66
|
memo,
|
|
53
67
|
assetValue,
|
|
54
68
|
});
|
|
55
69
|
|
|
56
70
|
const isFeeEIP1559Compatible = "maxFeePerGas" in gasRate;
|
|
57
|
-
const isFeeEVMLegacyCompatible = "gasPrice" in gasRate;
|
|
71
|
+
const isFeeEVMLegacyCompatible = "gasPrice" in gasRate && gasRate.gasPrice !== undefined;
|
|
58
72
|
|
|
59
|
-
if (!(isFeeEVMLegacyCompatible || isFeeEIP1559Compatible)) {
|
|
73
|
+
if (!(gasRate && (isFeeEVMLegacyCompatible || isFeeEIP1559Compatible))) {
|
|
60
74
|
throw new Error("Could not fetch fee data");
|
|
61
75
|
}
|
|
62
76
|
|
|
63
|
-
const
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
77
|
+
const gasPrice = isFeeEIP1559Compatible
|
|
78
|
+
? (gasRate.maxFeePerGas || 1n) + (gasRate.maxPriorityFeePerGas || 1n)
|
|
79
|
+
: gasRate.gasPrice || 1n;
|
|
80
|
+
|
|
81
|
+
const fee = gasLimit * gasPrice;
|
|
68
82
|
const maxSendableAmount = SwapKitNumber.fromBigInt(balance.getBaseValue("bigint")).sub(
|
|
69
83
|
fee.toString(),
|
|
70
84
|
);
|
|
@@ -72,74 +86,88 @@ export const estimateMaxSendableAmount = async ({
|
|
|
72
86
|
return AssetValue.from({ chain: balance.chain, value: maxSendableAmount.getValue("string") });
|
|
73
87
|
};
|
|
74
88
|
|
|
75
|
-
export
|
|
89
|
+
export function toHexString(value: bigint) {
|
|
90
|
+
return value > 0n ? `0x${value.toString(16)}` : "0x0";
|
|
91
|
+
}
|
|
76
92
|
|
|
77
|
-
export
|
|
93
|
+
export function getEstimateTransactionFee({
|
|
78
94
|
provider,
|
|
79
|
-
address,
|
|
80
|
-
chain,
|
|
81
|
-
potentialScamFilter,
|
|
82
|
-
}: {
|
|
83
|
-
provider: JsonRpcProvider | BrowserProvider;
|
|
84
|
-
address: string;
|
|
85
|
-
chain: EVMChain;
|
|
86
|
-
potentialScamFilter?: boolean;
|
|
87
|
-
}) => {
|
|
88
|
-
const tokenBalances = await getEvmApi(chain).getBalance(address);
|
|
89
|
-
const evmGasTokenBalance = await provider.getBalance(address);
|
|
90
|
-
|
|
91
|
-
const balances = [
|
|
92
|
-
{
|
|
93
|
-
chain,
|
|
94
|
-
symbol: AssetValue.from({ chain }).symbol,
|
|
95
|
-
value: formatBigIntToSafeValue({
|
|
96
|
-
value: BigInt(evmGasTokenBalance),
|
|
97
|
-
decimal: 18,
|
|
98
|
-
bigIntDecimal: 18,
|
|
99
|
-
}),
|
|
100
|
-
decimal: BaseDecimal[chain],
|
|
101
|
-
},
|
|
102
|
-
...tokenBalances.filter((token) => !isGasAsset(token)),
|
|
103
|
-
];
|
|
104
|
-
|
|
105
|
-
const filteredBalances = potentialScamFilter ? filterAssets(balances) : balances;
|
|
106
|
-
|
|
107
|
-
return filteredBalances.map(
|
|
108
|
-
({ symbol, value, decimal }) =>
|
|
109
|
-
new AssetValue({
|
|
110
|
-
decimal: decimal || BaseDecimal[chain],
|
|
111
|
-
value,
|
|
112
|
-
identifier: `${chain}.${symbol}`,
|
|
113
|
-
}),
|
|
114
|
-
);
|
|
115
|
-
};
|
|
116
|
-
|
|
117
|
-
export const estimateTransactionFee = async (
|
|
118
|
-
txObject: EIP1559TxParams,
|
|
119
|
-
// biome-ignore lint/style/useDefaultParameterLast: Should only be used through wrapped toolboxes
|
|
120
|
-
feeOption: FeeOption = FeeOption.Fast,
|
|
121
|
-
chain: EVMChain,
|
|
122
|
-
provider: Provider | BrowserProvider,
|
|
123
95
|
isEIP1559Compatible = true,
|
|
124
|
-
)
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
);
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
)
|
|
96
|
+
}: { provider: Provider | BrowserProvider; isEIP1559Compatible?: boolean; chain: EVMChain }) {
|
|
97
|
+
return async function estimateTransactionFee({
|
|
98
|
+
feeOption = FeeOption.Fast,
|
|
99
|
+
chain,
|
|
100
|
+
...txObject
|
|
101
|
+
}: EIP1559TxParams & { feeOption: FeeOption; chain: EVMChain }) {
|
|
102
|
+
const estimateGasPrices = getEstimateGasPrices({ provider, isEIP1559Compatible, chain });
|
|
103
|
+
const gasPrices = await estimateGasPrices();
|
|
104
|
+
const gasLimit = await provider.estimateGas(txObject);
|
|
105
|
+
|
|
106
|
+
const assetValue = AssetValue.from({ chain });
|
|
107
|
+
const { gasPrice, maxFeePerGas, maxPriorityFeePerGas } = gasPrices[feeOption];
|
|
108
|
+
|
|
109
|
+
if (!isEIP1559Compatible && gasPrice) {
|
|
110
|
+
return assetValue.set(SwapKitNumber.fromBigInt(gasPrice * gasLimit, assetValue.decimal));
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
if (maxFeePerGas && maxPriorityFeePerGas) {
|
|
114
|
+
const fee = (maxFeePerGas + maxPriorityFeePerGas) * gasLimit;
|
|
115
|
+
|
|
116
|
+
return assetValue.set(SwapKitNumber.fromBigInt(fee, assetValue.decimal));
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
throw new Error("No gas price found");
|
|
120
|
+
};
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
export function getNetworkParams<C extends EVMChain>(chain: C) {
|
|
124
|
+
return () =>
|
|
125
|
+
(Chain.Ethereum === chain
|
|
126
|
+
? undefined
|
|
127
|
+
: {
|
|
128
|
+
...getNetworkInfo({ chain }),
|
|
129
|
+
chainId: ChainToHexChainId[chain],
|
|
130
|
+
rpcUrls: [SKConfig.get("rpcUrls")[chain]],
|
|
131
|
+
blockExplorerUrls: [ChainToExplorerUrl[chain]],
|
|
132
|
+
}) as C extends Chain.Ethereum ? undefined : NetworkParams;
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
export function getIsEIP1559Compatible<C extends EVMChain>(chain: C) {
|
|
136
|
+
const notCompatible = [Chain.Arbitrum, Chain.BinanceSmartChain];
|
|
137
|
+
|
|
138
|
+
return !notCompatible.includes(chain);
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
function getNetworkInfo<C extends EVMChain>({ chain }: { chain: C }) {
|
|
142
|
+
const decimals = BaseDecimal[chain];
|
|
143
|
+
|
|
144
|
+
switch (chain) {
|
|
145
|
+
case Chain.Arbitrum:
|
|
146
|
+
return {
|
|
147
|
+
chainName: "Arbitrum One",
|
|
148
|
+
nativeCurrency: { name: "Ethereum", symbol: Chain.Ethereum, decimals },
|
|
149
|
+
};
|
|
150
|
+
case Chain.Avalanche:
|
|
151
|
+
return {
|
|
152
|
+
chainName: "Avalanche Network",
|
|
153
|
+
nativeCurrency: { name: "Avalanche", symbol: chain, decimals },
|
|
154
|
+
};
|
|
155
|
+
case Chain.Base:
|
|
156
|
+
return {
|
|
157
|
+
chainName: "Base Mainnet",
|
|
158
|
+
nativeCurrency: { name: "Ethereum", symbol: Chain.Ethereum, decimals },
|
|
159
|
+
};
|
|
160
|
+
case Chain.BinanceSmartChain:
|
|
161
|
+
return {
|
|
162
|
+
chainName: "BNB Chain",
|
|
163
|
+
nativeCurrency: { name: "Binance Coin", symbol: "BNB", decimals },
|
|
164
|
+
};
|
|
165
|
+
case Chain.Polygon:
|
|
166
|
+
return {
|
|
167
|
+
chainName: "Polygon Mainnet",
|
|
168
|
+
nativeCurrency: { name: "Polygon", symbol: Chain.Polygon, decimals },
|
|
169
|
+
};
|
|
170
|
+
default:
|
|
171
|
+
throw new Error(`Chain ${chain} is not supported`);
|
|
142
172
|
}
|
|
143
|
-
|
|
144
|
-
throw new Error("No gas price found");
|
|
145
|
-
};
|
|
173
|
+
}
|
package/src/evm/index.ts
CHANGED
|
@@ -1,20 +1,4 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Package
|
|
3
|
-
*/
|
|
4
1
|
export * from "./api";
|
|
5
2
|
export * from "./helpers";
|
|
6
|
-
export * from "./provider";
|
|
7
|
-
export * from "./toolbox/EVMToolbox";
|
|
8
3
|
export * from "./types";
|
|
9
|
-
|
|
10
|
-
/**
|
|
11
|
-
* Toolboxes
|
|
12
|
-
*/
|
|
13
|
-
export * from "./toolbox/arb";
|
|
14
|
-
export * from "./toolbox/avax";
|
|
15
|
-
export * from "./toolbox/bsc";
|
|
16
|
-
export * from "./toolbox/eth";
|
|
17
|
-
export * from "./toolbox/getToolboxByChain";
|
|
18
|
-
export * from "./toolbox/matic";
|
|
19
|
-
export * from "./toolbox/op";
|
|
20
|
-
export * from "./toolbox/base";
|
|
4
|
+
export * from "./toolbox";
|