@swapkit/toolboxes 1.0.0-beta.3 → 1.0.0-beta.31
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-fjfxga2v.js → chunk-5yxc1e69.js} +1 -1
- package/dist/{chunk-fjfxga2v.js.map → chunk-5yxc1e69.js.map} +1 -1
- package/dist/chunk-6f98phv2.js +4 -0
- package/dist/{chunk-0h4xdrwz.js.map → chunk-6f98phv2.js.map} +2 -2
- package/dist/{chunk-0f0249b1.js → chunk-9bqegm61.js} +1 -1
- package/dist/{chunk-p1kdg37m.js → chunk-s47y8512.js} +2 -2
- package/dist/{chunk-p1kdg37m.js.map → chunk-s47y8512.js.map} +1 -1
- package/dist/chunk-vtd17cje.js +3 -0
- package/dist/chunk-vtd17cje.js.map +10 -0
- package/dist/chunk-zcdeg6h9.js +4 -0
- package/dist/chunk-zcdeg6h9.js.map +10 -0
- package/dist/src/cosmos/index.cjs +3 -0
- package/dist/src/cosmos/index.cjs.map +16 -0
- package/dist/src/cosmos/index.js +3 -0
- package/dist/src/cosmos/index.js.map +16 -0
- package/dist/src/evm/index.cjs +3 -0
- package/dist/src/evm/index.cjs.map +18 -0
- package/dist/src/evm/index.js +3 -0
- package/dist/src/evm/index.js.map +18 -0
- package/dist/src/index.cjs +3 -0
- package/dist/src/index.cjs.map +10 -0
- package/dist/src/index.js +3 -0
- package/dist/src/index.js.map +10 -0
- package/dist/src/near/index.cjs +3 -0
- package/dist/src/near/index.cjs.map +13 -0
- package/dist/src/near/index.js +3 -0
- package/dist/src/near/index.js.map +13 -0
- package/dist/{radix → src/radix}/index.cjs +2 -2
- package/dist/src/radix/index.cjs.map +10 -0
- package/dist/src/radix/index.js +3 -0
- package/dist/src/radix/index.js.map +10 -0
- package/dist/src/ripple/index.cjs +3 -0
- package/dist/src/ripple/index.cjs.map +10 -0
- package/dist/src/ripple/index.js +3 -0
- package/dist/src/ripple/index.js.map +10 -0
- package/dist/src/solana/index.cjs +3 -0
- package/dist/src/solana/index.cjs.map +10 -0
- package/dist/src/solana/index.js +3 -0
- package/dist/src/solana/index.js.map +10 -0
- package/dist/src/substrate/index.cjs +3 -0
- package/dist/src/substrate/index.cjs.map +12 -0
- package/dist/src/substrate/index.js +3 -0
- package/dist/src/substrate/index.js.map +12 -0
- package/dist/src/tron/index.cjs +3 -0
- package/dist/src/tron/index.cjs.map +11 -0
- package/dist/src/tron/index.js +3 -0
- package/dist/src/tron/index.js.map +11 -0
- package/dist/src/utxo/index.cjs +5 -0
- package/dist/src/utxo/index.cjs.map +17 -0
- package/dist/src/utxo/index.js +5 -0
- package/dist/src/utxo/index.js.map +17 -0
- package/package.json +49 -37
- package/src/cosmos/thorchainUtils/addressFormat.ts +4 -1
- package/src/cosmos/thorchainUtils/messages.ts +2 -2
- package/src/cosmos/thorchainUtils/registry.ts +3 -3
- package/src/cosmos/toolbox/cosmos.ts +35 -16
- package/src/cosmos/toolbox/index.ts +2 -2
- package/src/cosmos/toolbox/thorchain.ts +11 -9
- package/src/cosmos/util.ts +76 -6
- package/src/evm/__tests__/address-validation.test.ts +86 -0
- package/src/evm/__tests__/ethereum.test.ts +1 -1
- package/src/evm/helpers.ts +4 -3
- package/src/evm/toolbox/baseEVMToolbox.ts +37 -25
- package/src/evm/toolbox/index.ts +2 -2
- package/src/evm/toolbox/op.ts +21 -7
- package/src/index.ts +118 -100
- package/src/near/__tests__/core.test.ts +80 -0
- package/src/near/helpers/contractFactory.ts +22 -0
- package/src/near/helpers/core.ts +89 -0
- package/src/near/helpers/gasEstimation.ts +110 -0
- package/src/near/helpers/index.ts +5 -0
- package/src/near/helpers/nep141.ts +110 -0
- package/src/near/index.ts +24 -0
- package/src/near/toolbox.ts +498 -0
- package/src/near/types/contract.ts +48 -0
- package/src/near/types/nep141.ts +66 -0
- package/src/near/types.ts +57 -0
- package/src/radix/index.ts +8 -2
- package/src/ripple/index.ts +15 -26
- package/src/solana/toolbox.ts +73 -2
- package/src/substrate/balance.ts +92 -0
- package/src/substrate/substrate.ts +7 -5
- package/src/tron/__tests__/toolbox.test.ts +147 -0
- package/src/tron/helpers/trc20.abi.ts +40 -0
- package/src/tron/index.ts +16 -0
- package/src/tron/toolbox.ts +336 -0
- package/src/tron/types.ts +31 -0
- package/src/utxo/__tests__/zcash-integration.test.ts +114 -0
- package/src/utxo/helpers/api.ts +66 -16
- package/src/utxo/helpers/bchaddrjs.ts +8 -8
- package/src/utxo/helpers/coinselect.ts +4 -2
- package/src/utxo/helpers/txSize.ts +4 -3
- package/src/utxo/index.ts +1 -0
- package/src/utxo/toolbox/bitcoinCash.ts +22 -14
- package/src/utxo/toolbox/index.ts +16 -4
- package/src/utxo/toolbox/utxo.ts +42 -27
- package/src/utxo/toolbox/zcash.ts +208 -0
- package/src/utxo/types.ts +2 -0
- package/dist/chunk-0h4xdrwz.js +0 -4
- package/dist/cosmos/index.cjs +0 -3
- package/dist/cosmos/index.cjs.map +0 -16
- package/dist/cosmos/index.js +0 -3
- package/dist/cosmos/index.js.map +0 -16
- package/dist/evm/index.cjs +0 -3
- package/dist/evm/index.cjs.map +0 -18
- package/dist/evm/index.js +0 -3
- package/dist/evm/index.js.map +0 -18
- package/dist/index.cjs +0 -3
- package/dist/index.cjs.map +0 -10
- package/dist/index.js +0 -3
- package/dist/index.js.map +0 -10
- package/dist/radix/index.cjs.map +0 -10
- package/dist/radix/index.js +0 -3
- package/dist/radix/index.js.map +0 -10
- package/dist/ripple/index.cjs +0 -3
- package/dist/ripple/index.cjs.map +0 -10
- package/dist/ripple/index.js +0 -3
- package/dist/ripple/index.js.map +0 -10
- package/dist/solana/index.cjs +0 -3
- package/dist/solana/index.cjs.map +0 -10
- package/dist/solana/index.js +0 -3
- package/dist/solana/index.js.map +0 -10
- package/dist/substrate/index.cjs +0 -3
- package/dist/substrate/index.cjs.map +0 -11
- package/dist/substrate/index.js +0 -3
- package/dist/substrate/index.js.map +0 -11
- package/dist/utxo/index.cjs +0 -3
- package/dist/utxo/index.cjs.map +0 -16
- package/dist/utxo/index.js +0 -3
- package/dist/utxo/index.js.map +0 -16
- /package/dist/{chunk-0f0249b1.js.map → chunk-9bqegm61.js.map} +0 -0
package/package.json
CHANGED
|
@@ -11,16 +11,19 @@
|
|
|
11
11
|
"@cosmjs/proto-signing": "0.33.1",
|
|
12
12
|
"@cosmjs/stargate": "0.33.1",
|
|
13
13
|
"@polkadot/api": "15.9.2",
|
|
14
|
-
"@polkadot/keyring": "13.
|
|
15
|
-
"@polkadot/util": "13.
|
|
16
|
-
"@polkadot/util-crypto": "13.
|
|
14
|
+
"@polkadot/keyring": "13.5.1",
|
|
15
|
+
"@polkadot/util": "13.5.1",
|
|
16
|
+
"@polkadot/util-crypto": "13.5.1",
|
|
17
17
|
"@psf/bitcoincashjs-lib": "4.0.3",
|
|
18
18
|
"@radixdlt/babylon-gateway-api-sdk": "1.10.1",
|
|
19
19
|
"@radixdlt/radix-dapp-toolkit": "2.2.1",
|
|
20
|
-
"@scure/base": "1.2.
|
|
21
|
-
"@scure/bip32": "1.
|
|
22
|
-
"@scure/bip39": "1.
|
|
23
|
-
"@
|
|
20
|
+
"@scure/base": "1.2.6",
|
|
21
|
+
"@scure/bip32": "1.7.0",
|
|
22
|
+
"@scure/bip39": "1.6.0",
|
|
23
|
+
"@solana/spl-memo": "0.2.5",
|
|
24
|
+
"@solana/spl-token": "0.4.13",
|
|
25
|
+
"@solana/web3.js": "1.98.2",
|
|
26
|
+
"@swapkit/helpers": "3.0.0-beta.21",
|
|
24
27
|
"base64-js": "1.5.1",
|
|
25
28
|
"bitcoinjs-lib": "6.1.7",
|
|
26
29
|
"bs58check": "4.0.0",
|
|
@@ -28,65 +31,74 @@
|
|
|
28
31
|
"coininfo": "5.2.1",
|
|
29
32
|
"cosmjs-types": "0.9.0",
|
|
30
33
|
"ecpair": "2.1.0",
|
|
31
|
-
"ethers": "6.
|
|
32
|
-
"micro-key-producer": "0.7.
|
|
33
|
-
"
|
|
34
|
-
"
|
|
35
|
-
"
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
"
|
|
39
|
-
"
|
|
40
|
-
"@solana/web3.js": "1.98.0"
|
|
34
|
+
"ethers": "6.14.3",
|
|
35
|
+
"micro-key-producer": "0.7.6",
|
|
36
|
+
"near-api-js": "^6.1.0",
|
|
37
|
+
"near-sdk-js": "^2.0.0",
|
|
38
|
+
"near-seed-phrase": "^0.2.0",
|
|
39
|
+
"protobufjs": "7.5.3",
|
|
40
|
+
"tronweb": "6.0.3",
|
|
41
|
+
"ts-pattern": "5.7.1",
|
|
42
|
+
"xrpl": "4.3.0"
|
|
41
43
|
},
|
|
42
44
|
"devDependencies": {
|
|
43
|
-
"@nomicfoundation/hardhat-ethers": "3.0.
|
|
45
|
+
"@nomicfoundation/hardhat-ethers": "3.0.9",
|
|
44
46
|
"@nomicfoundation/hardhat-toolbox": "5.0.0",
|
|
45
47
|
"@polkadot/types": "15.9.2",
|
|
46
|
-
"@types/bn.js": "5.
|
|
48
|
+
"@types/bn.js": "5.2.0",
|
|
47
49
|
"@types/crypto-js": "4.2.2",
|
|
48
50
|
"@types/elliptic": "6.4.18",
|
|
49
|
-
"hardhat": "2.
|
|
51
|
+
"hardhat": "2.24.2"
|
|
50
52
|
},
|
|
51
53
|
"exports": {
|
|
52
54
|
".": {
|
|
53
|
-
"default": "./dist/index.js",
|
|
54
|
-
"require": "./dist/index.cjs",
|
|
55
|
+
"default": "./dist/src/index.js",
|
|
56
|
+
"require": "./dist/src/index.cjs",
|
|
55
57
|
"types": "./src/index.ts"
|
|
56
58
|
},
|
|
57
59
|
"./cosmos": {
|
|
58
|
-
"default": "./dist/cosmos/index.js",
|
|
59
|
-
"require": "./dist/cosmos/index.cjs",
|
|
60
|
+
"default": "./dist/src/cosmos/index.js",
|
|
61
|
+
"require": "./dist/src/cosmos/index.cjs",
|
|
60
62
|
"types": "./src/cosmos/index.ts"
|
|
61
63
|
},
|
|
62
64
|
"./evm": {
|
|
63
|
-
"default": "./dist/evm/index.js",
|
|
64
|
-
"require": "./dist/evm/index.cjs",
|
|
65
|
+
"default": "./dist/src/evm/index.js",
|
|
66
|
+
"require": "./dist/src/evm/index.cjs",
|
|
65
67
|
"types": "./src/evm/index.ts"
|
|
66
68
|
},
|
|
69
|
+
"./near": {
|
|
70
|
+
"default": "./dist/src/near/index.js",
|
|
71
|
+
"require": "./dist/src/near/index.cjs",
|
|
72
|
+
"types": "./src/near/index.ts"
|
|
73
|
+
},
|
|
67
74
|
"./radix": {
|
|
68
|
-
"default": "./dist/radix/index.js",
|
|
69
|
-
"require": "./dist/radix/index.cjs",
|
|
75
|
+
"default": "./dist/src/radix/index.js",
|
|
76
|
+
"require": "./dist/src/radix/index.cjs",
|
|
70
77
|
"types": "./src/radix/index.ts"
|
|
71
78
|
},
|
|
72
79
|
"./ripple": {
|
|
73
|
-
"default": "./dist/ripple/index.js",
|
|
74
|
-
"require": "./dist/ripple/index.cjs",
|
|
80
|
+
"default": "./dist/src/ripple/index.js",
|
|
81
|
+
"require": "./dist/src/ripple/index.cjs",
|
|
75
82
|
"types": "./src/ripple/index.ts"
|
|
76
83
|
},
|
|
77
84
|
"./solana": {
|
|
78
|
-
"default": "./dist/solana/index.js",
|
|
79
|
-
"require": "./dist/solana/index.cjs",
|
|
85
|
+
"default": "./dist/src/solana/index.js",
|
|
86
|
+
"require": "./dist/src/solana/index.cjs",
|
|
80
87
|
"types": "./src/solana/index.ts"
|
|
81
88
|
},
|
|
82
89
|
"./substrate": {
|
|
83
|
-
"default": "./dist/substrate/index.js",
|
|
84
|
-
"require": "./dist/substrate/index.cjs",
|
|
90
|
+
"default": "./dist/src/substrate/index.js",
|
|
91
|
+
"require": "./dist/src/substrate/index.cjs",
|
|
85
92
|
"types": "./src/substrate/index.ts"
|
|
86
93
|
},
|
|
94
|
+
"./tron": {
|
|
95
|
+
"default": "./dist/src/tron/index.js",
|
|
96
|
+
"require": "./dist/src/tron/index.cjs",
|
|
97
|
+
"types": "./src/tron/index.ts"
|
|
98
|
+
},
|
|
87
99
|
"./utxo": {
|
|
88
|
-
"default": "./dist/utxo/index.js",
|
|
89
|
-
"require": "./dist/utxo/index.cjs",
|
|
100
|
+
"default": "./dist/src/utxo/index.js",
|
|
101
|
+
"require": "./dist/src/utxo/index.cjs",
|
|
90
102
|
"types": "./src/utxo/index.ts"
|
|
91
103
|
}
|
|
92
104
|
},
|
|
@@ -107,5 +119,5 @@
|
|
|
107
119
|
"type-check:go": "tsgo"
|
|
108
120
|
},
|
|
109
121
|
"type": "module",
|
|
110
|
-
"version": "1.0.0-beta.
|
|
122
|
+
"version": "1.0.0-beta.31"
|
|
111
123
|
}
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { base64, bech32 } from "@scure/base";
|
|
2
|
+
import { SwapKitError } from "@swapkit/helpers";
|
|
2
3
|
import { fromByteArray, toByteArray } from "base64-js";
|
|
3
4
|
|
|
4
5
|
export function bech32ToBase64(address: string) {
|
|
@@ -17,7 +18,9 @@ export function toBase64(data: Uint8Array) {
|
|
|
17
18
|
|
|
18
19
|
export function fromBase64(base64String: string) {
|
|
19
20
|
if (!base64String.match(/^[a-zA-Z0-9+/]*={0,2}$/)) {
|
|
20
|
-
throw new
|
|
21
|
+
throw new SwapKitError("toolbox_cosmos_invalid_params", {
|
|
22
|
+
error: "Invalid base64 string format",
|
|
23
|
+
});
|
|
21
24
|
}
|
|
22
25
|
return toByteArray(base64String);
|
|
23
26
|
}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type { TxBodyEncodeObject } from "@cosmjs/proto-signing";
|
|
2
|
-
import { AssetValue, Chain, ChainToChainId } from "@swapkit/helpers";
|
|
2
|
+
import { AssetValue, Chain, ChainToChainId, SwapKitError } from "@swapkit/helpers";
|
|
3
3
|
|
|
4
4
|
import {
|
|
5
5
|
createStargateClient,
|
|
@@ -104,7 +104,7 @@ const getAccount = async ({ rpcUrl, sender }: { sender: string; rpcUrl: string }
|
|
|
104
104
|
const account = await client.getAccount(sender);
|
|
105
105
|
|
|
106
106
|
if (!account) {
|
|
107
|
-
throw new
|
|
107
|
+
throw new SwapKitError("toolbox_cosmos_account_not_found", { sender });
|
|
108
108
|
}
|
|
109
109
|
|
|
110
110
|
return account;
|
|
@@ -3,8 +3,8 @@ import { base64ToBech32, bech32ToBase64 } from "./addressFormat";
|
|
|
3
3
|
|
|
4
4
|
export async function createDefaultRegistry() {
|
|
5
5
|
const { $root } = await import("./types/MsgCompiled");
|
|
6
|
-
const { Registry } = await import("@cosmjs/proto-signing");
|
|
7
|
-
const { defaultRegistryTypes } = await import("@cosmjs/stargate");
|
|
6
|
+
const { Registry } = (await import("@cosmjs/proto-signing")).default;
|
|
7
|
+
const { defaultRegistryTypes } = (await import("@cosmjs/stargate")).default;
|
|
8
8
|
|
|
9
9
|
return new Registry([
|
|
10
10
|
...defaultRegistryTypes,
|
|
@@ -14,7 +14,7 @@ export async function createDefaultRegistry() {
|
|
|
14
14
|
}
|
|
15
15
|
|
|
16
16
|
export async function createDefaultAminoTypes(chain: Chain.THORChain | Chain.Maya) {
|
|
17
|
-
const { AminoTypes } = await import("@cosmjs/stargate");
|
|
17
|
+
const { AminoTypes } = (await import("@cosmjs/stargate")).default;
|
|
18
18
|
const aminoTypePrefix = chain === Chain.THORChain ? "thorchain" : "mayachain";
|
|
19
19
|
|
|
20
20
|
return new AminoTypes({
|
|
@@ -17,17 +17,18 @@ import {
|
|
|
17
17
|
SKConfig,
|
|
18
18
|
SwapKitError,
|
|
19
19
|
SwapKitNumber,
|
|
20
|
+
applyFeeMultiplier,
|
|
20
21
|
derivationPathToString,
|
|
21
22
|
updateDerivationPath,
|
|
22
23
|
} from "@swapkit/helpers";
|
|
23
24
|
import { SwapKitApi } from "@swapkit/helpers/api";
|
|
24
25
|
import { P, match } from "ts-pattern";
|
|
25
|
-
import { getBalance } from "../../utils";
|
|
26
26
|
import type { CosmosToolboxParams } from "../types";
|
|
27
27
|
import {
|
|
28
28
|
cosmosCreateTransaction,
|
|
29
29
|
createSigningStargateClient,
|
|
30
30
|
createStargateClient,
|
|
31
|
+
getAssetFromDenom,
|
|
31
32
|
getDenomWithChain,
|
|
32
33
|
getMsgSendDenom,
|
|
33
34
|
} from "../util";
|
|
@@ -38,8 +39,7 @@ export async function fetchFeeRateFromSwapKit(chainId: ChainId, safeDefault: num
|
|
|
38
39
|
const responseGasRate = response.find((gas) => gas.chainId === chainId)?.value;
|
|
39
40
|
|
|
40
41
|
return responseGasRate ? Number.parseFloat(responseGasRate) : safeDefault;
|
|
41
|
-
} catch (
|
|
42
|
-
console.error(e);
|
|
42
|
+
} catch (_e) {
|
|
43
43
|
return safeDefault;
|
|
44
44
|
}
|
|
45
45
|
}
|
|
@@ -52,8 +52,8 @@ export async function getSignerFromPhrase({
|
|
|
52
52
|
| { chain: Chain; index?: number }
|
|
53
53
|
| { derivationPath: string }
|
|
54
54
|
)) {
|
|
55
|
-
const { DirectSecp256k1HdWallet } = await import("@cosmjs/proto-signing");
|
|
56
|
-
const { stringToPath } = await import("@cosmjs/crypto");
|
|
55
|
+
const { DirectSecp256k1HdWallet } = (await import("@cosmjs/proto-signing")).default;
|
|
56
|
+
const { stringToPath } = (await import("@cosmjs/crypto")).default;
|
|
57
57
|
|
|
58
58
|
const derivationPath =
|
|
59
59
|
"derivationPath" in derivationParams
|
|
@@ -73,7 +73,7 @@ export async function getSignerFromPrivateKey({
|
|
|
73
73
|
privateKey: Uint8Array;
|
|
74
74
|
prefix: string;
|
|
75
75
|
}) {
|
|
76
|
-
const { DirectSecp256k1Wallet } = await import("@cosmjs/proto-signing");
|
|
76
|
+
const { DirectSecp256k1Wallet } = (await import("@cosmjs/proto-signing")).default;
|
|
77
77
|
|
|
78
78
|
return DirectSecp256k1Wallet.fromKey(privateKey, prefix);
|
|
79
79
|
}
|
|
@@ -97,7 +97,7 @@ export function verifySignature(getAccount: (address: string) => Promise<Account
|
|
|
97
97
|
}) {
|
|
98
98
|
const account = await getAccount(address);
|
|
99
99
|
if (!account?.pubkey) throw new SwapKitError("toolbox_cosmos_verify_signature_no_pubkey");
|
|
100
|
-
const { Secp256k1Signature, Secp256k1 } = await import("@cosmjs/crypto");
|
|
100
|
+
const { Secp256k1Signature, Secp256k1 } = (await import("@cosmjs/crypto")).default;
|
|
101
101
|
|
|
102
102
|
const secpSignature = Secp256k1Signature.fromFixedLength(base64.decode(signature));
|
|
103
103
|
return Secp256k1.verifySignature(secpSignature, base64.decode(message), account.pubkey.value);
|
|
@@ -185,7 +185,21 @@ export async function createCosmosToolbox({ chain, ...toolboxParams }: CosmosToo
|
|
|
185
185
|
transfer,
|
|
186
186
|
getAddress,
|
|
187
187
|
getAccount,
|
|
188
|
-
getBalance:
|
|
188
|
+
getBalance: async (address: string, _potentialScamFilter?: boolean) => {
|
|
189
|
+
const denomBalances = await cosmosBalanceDenomsGetter(rpcUrl)(address);
|
|
190
|
+
return await Promise.all(
|
|
191
|
+
denomBalances
|
|
192
|
+
.filter(({ denom }) => denom && !denom.includes("IBC/"))
|
|
193
|
+
.map(({ denom, amount }) => {
|
|
194
|
+
const fullDenom =
|
|
195
|
+
[Chain.THORChain, Chain.Maya].includes(chain) &&
|
|
196
|
+
(denom.includes("/") || denom.includes("˜"))
|
|
197
|
+
? `${chain}.${denom}`
|
|
198
|
+
: denom;
|
|
199
|
+
return getAssetFromDenom(fullDenom, amount);
|
|
200
|
+
}),
|
|
201
|
+
);
|
|
202
|
+
},
|
|
189
203
|
getSignerFromPhrase: async ({
|
|
190
204
|
phrase,
|
|
191
205
|
derivationPath,
|
|
@@ -197,7 +211,7 @@ export async function createCosmosToolbox({ chain, ...toolboxParams }: CosmosToo
|
|
|
197
211
|
index,
|
|
198
212
|
}),
|
|
199
213
|
getSignerFromPrivateKey: async (privateKey: Uint8Array) => {
|
|
200
|
-
const { DirectSecp256k1Wallet } = await import("@cosmjs/proto-signing");
|
|
214
|
+
const { DirectSecp256k1Wallet } = (await import("@cosmjs/proto-signing")).default;
|
|
201
215
|
return DirectSecp256k1Wallet.fromKey(privateKey, chainPrefix);
|
|
202
216
|
},
|
|
203
217
|
createPrivateKeyFromPhrase: createPrivateKeyFromPhrase(derivationPath),
|
|
@@ -217,8 +231,7 @@ export async function getFeeRateFromThorswap(chainId: ChainId, safeDefault: numb
|
|
|
217
231
|
const responseGasRate = response.find((gas) => gas.chainId === chainId)?.value;
|
|
218
232
|
|
|
219
233
|
return responseGasRate ? Number.parseFloat(responseGasRate) : safeDefault;
|
|
220
|
-
} catch (
|
|
221
|
-
console.error(e);
|
|
234
|
+
} catch (_e) {
|
|
222
235
|
return safeDefault;
|
|
223
236
|
}
|
|
224
237
|
}
|
|
@@ -262,8 +275,14 @@ async function getFees(chain: Chain, safeDefault: number) {
|
|
|
262
275
|
const baseFee = await fetchFeeRateFromSwapKit(ChainToChainId[chain], safeDefault);
|
|
263
276
|
return {
|
|
264
277
|
average: SwapKitNumber.fromBigInt(BigInt(baseFee), BaseDecimal[chain]),
|
|
265
|
-
fast: SwapKitNumber.fromBigInt(
|
|
266
|
-
|
|
278
|
+
fast: SwapKitNumber.fromBigInt(
|
|
279
|
+
BigInt(applyFeeMultiplier(baseFee, FeeOption.Fast, true)),
|
|
280
|
+
BaseDecimal[chain],
|
|
281
|
+
),
|
|
282
|
+
fastest: SwapKitNumber.fromBigInt(
|
|
283
|
+
BigInt(applyFeeMultiplier(baseFee, FeeOption.Fastest, true)),
|
|
284
|
+
BaseDecimal[chain],
|
|
285
|
+
),
|
|
267
286
|
} as { [key in FeeOption]: SwapKitNumber };
|
|
268
287
|
}
|
|
269
288
|
|
|
@@ -316,9 +335,9 @@ function cosmosBalanceDenomsGetter(rpcUrl: string) {
|
|
|
316
335
|
|
|
317
336
|
function createPrivateKeyFromPhrase(derivationPath: string) {
|
|
318
337
|
return async function createPrivateKeyFromPhrase(phrase: string) {
|
|
319
|
-
const { Bip39, EnglishMnemonic, Slip10, Slip10Curve, stringToPath } =
|
|
320
|
-
"@cosmjs/crypto"
|
|
321
|
-
);
|
|
338
|
+
const { Bip39, EnglishMnemonic, Slip10, Slip10Curve, stringToPath } = (
|
|
339
|
+
await import("@cosmjs/crypto")
|
|
340
|
+
).default;
|
|
322
341
|
|
|
323
342
|
const mnemonicChecked = new EnglishMnemonic(phrase);
|
|
324
343
|
const seed = await Bip39.mnemonicToSeed(mnemonicChecked);
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { Chain, type CosmosChain } from "@swapkit/helpers";
|
|
1
|
+
import { Chain, type CosmosChain, SwapKitError } from "@swapkit/helpers";
|
|
2
2
|
|
|
3
3
|
import type { CosmosToolboxParams } from "../types";
|
|
4
4
|
import { createCosmosToolbox } from "./cosmos";
|
|
@@ -25,7 +25,7 @@ export const getCosmosToolbox = <T extends CosmosChain>(
|
|
|
25
25
|
return createThorchainToolbox({ chain, ...params }) as CosmosToolboxes[T];
|
|
26
26
|
|
|
27
27
|
default:
|
|
28
|
-
throw new
|
|
28
|
+
throw new SwapKitError("toolbox_cosmos_not_supported", { chain });
|
|
29
29
|
}
|
|
30
30
|
};
|
|
31
31
|
|
|
@@ -9,6 +9,7 @@ import {
|
|
|
9
9
|
NetworkDerivationPath,
|
|
10
10
|
RequestClient,
|
|
11
11
|
SKConfig,
|
|
12
|
+
SwapKitError,
|
|
12
13
|
SwapKitNumber,
|
|
13
14
|
derivationPathToString,
|
|
14
15
|
updateDerivationPath,
|
|
@@ -43,8 +44,8 @@ function secp256k1HdWalletFromMnemonic({
|
|
|
43
44
|
derivationPath?: string;
|
|
44
45
|
}) {
|
|
45
46
|
return async function secp256k1HdWalletFromMnemonic(mnemonic: string, index = 0) {
|
|
46
|
-
const { Secp256k1HdWallet } = await import("@cosmjs/amino");
|
|
47
|
-
const { stringToPath } = await import("@cosmjs/crypto");
|
|
47
|
+
const { Secp256k1HdWallet } = (await import("@cosmjs/amino")).default;
|
|
48
|
+
const { stringToPath } = (await import("@cosmjs/crypto")).default;
|
|
48
49
|
|
|
49
50
|
return Secp256k1HdWallet.fromMnemonic(mnemonic, {
|
|
50
51
|
hdPaths: [stringToPath(`${derivationPath}/${index}`)],
|
|
@@ -114,8 +115,8 @@ function broadcastMultisigTx({
|
|
|
114
115
|
threshold: number,
|
|
115
116
|
bodyBytes: Uint8Array,
|
|
116
117
|
) {
|
|
117
|
-
const { encodeSecp256k1Pubkey, pubkeyToAddress } = await import("@cosmjs/amino");
|
|
118
|
-
const { makeMultisignedTxBytes } = await import("@cosmjs/stargate");
|
|
118
|
+
const { encodeSecp256k1Pubkey, pubkeyToAddress } = (await import("@cosmjs/amino")).default;
|
|
119
|
+
const { makeMultisignedTxBytes } = (await import("@cosmjs/stargate")).default;
|
|
119
120
|
|
|
120
121
|
const { sequence, fee } = JSON.parse(tx);
|
|
121
122
|
const multisigPubkey = await createMultisig(membersPubKeys, threshold);
|
|
@@ -142,7 +143,8 @@ function broadcastMultisigTx({
|
|
|
142
143
|
}
|
|
143
144
|
|
|
144
145
|
async function createMultisig(pubKeys: string[], threshold: number, noSortPubKeys = true) {
|
|
145
|
-
const { createMultisigThresholdPubkey, encodeSecp256k1Pubkey } = await import("@cosmjs/amino")
|
|
146
|
+
const { createMultisigThresholdPubkey, encodeSecp256k1Pubkey } = (await import("@cosmjs/amino"))
|
|
147
|
+
.default;
|
|
146
148
|
return createMultisigThresholdPubkey(
|
|
147
149
|
pubKeys.map((pubKey) => encodeSecp256k1Pubkey(base64.decode(pubKey))),
|
|
148
150
|
threshold,
|
|
@@ -161,7 +163,7 @@ async function signWithPrivateKey({
|
|
|
161
163
|
privateKey: Uint8Array;
|
|
162
164
|
message: string;
|
|
163
165
|
}) {
|
|
164
|
-
const { Secp256k1 } = await import("@cosmjs/crypto");
|
|
166
|
+
const { Secp256k1 } = (await import("@cosmjs/crypto")).default;
|
|
165
167
|
|
|
166
168
|
const signature = await Secp256k1.createSignature(base64.decode(message), privateKey);
|
|
167
169
|
return base64.encode(Buffer.concat([signature.r(32), signature.s(32)]));
|
|
@@ -209,7 +211,7 @@ export async function createThorchainToolbox({
|
|
|
209
211
|
} = await RequestClient.get<ThorchainConstantsResponse>(constantsUrl);
|
|
210
212
|
|
|
211
213
|
if (!nativeFee || Number.isNaN(nativeFee) || nativeFee < 0) {
|
|
212
|
-
throw new
|
|
214
|
+
throw new SwapKitError("toolbox_cosmos_invalid_fee", { nativeFee: nativeFee.toString() });
|
|
213
215
|
}
|
|
214
216
|
|
|
215
217
|
fee = new SwapKitNumber(nativeFee);
|
|
@@ -230,7 +232,7 @@ export async function createThorchainToolbox({
|
|
|
230
232
|
}: Omit<GenericTransferParams, "recipient"> & { recipient?: string }) {
|
|
231
233
|
const { TxRaw } = await import("cosmjs-types/cosmos/tx/v1beta1/tx");
|
|
232
234
|
const sender = (await signer?.getAccounts())?.[0]?.address;
|
|
233
|
-
if (!(sender && signer)) throw new
|
|
235
|
+
if (!(sender && signer)) throw new SwapKitError("toolbox_cosmos_no_signer");
|
|
234
236
|
|
|
235
237
|
const isAminoSigner = "signAmino" in signer;
|
|
236
238
|
const registry = await createDefaultRegistry();
|
|
@@ -301,7 +303,7 @@ export async function createThorchainToolbox({
|
|
|
301
303
|
signWithPrivateKey,
|
|
302
304
|
transfer,
|
|
303
305
|
pubkeyToAddress: async (pubkey: Pubkey) => {
|
|
304
|
-
const { pubkeyToAddress } = await import("@cosmjs/amino");
|
|
306
|
+
const { pubkeyToAddress } = (await import("@cosmjs/amino")).default;
|
|
305
307
|
return pubkeyToAddress(pubkey, chainPrefix);
|
|
306
308
|
},
|
|
307
309
|
};
|
package/src/cosmos/util.ts
CHANGED
|
@@ -1,6 +1,14 @@
|
|
|
1
1
|
import type { OfflineSigner } from "@cosmjs/proto-signing";
|
|
2
2
|
import type { SigningStargateClientOptions } from "@cosmjs/stargate";
|
|
3
|
-
import {
|
|
3
|
+
import {
|
|
4
|
+
AssetValue,
|
|
5
|
+
BaseDecimal,
|
|
6
|
+
Chain,
|
|
7
|
+
ChainId,
|
|
8
|
+
type CosmosChain,
|
|
9
|
+
SKConfig,
|
|
10
|
+
SwapKitError,
|
|
11
|
+
} from "@swapkit/helpers";
|
|
4
12
|
|
|
5
13
|
import type { CosmosCreateTransactionParams } from "./thorchainUtils";
|
|
6
14
|
|
|
@@ -69,7 +77,7 @@ export const getDenomWithChain = ({ symbol, chain }: AssetValue) => {
|
|
|
69
77
|
};
|
|
70
78
|
|
|
71
79
|
export async function createStargateClient(url: string) {
|
|
72
|
-
const { StargateClient } = await import("@cosmjs/stargate");
|
|
80
|
+
const { StargateClient } = (await import("@cosmjs/stargate")).default;
|
|
73
81
|
|
|
74
82
|
return StargateClient.connect(url);
|
|
75
83
|
}
|
|
@@ -79,7 +87,7 @@ export async function createSigningStargateClient(
|
|
|
79
87
|
signer: any,
|
|
80
88
|
optionsOrBaseGas: string | SigningStargateClientOptions = {},
|
|
81
89
|
) {
|
|
82
|
-
const { SigningStargateClient, GasPrice } = await import("@cosmjs/stargate");
|
|
90
|
+
const { SigningStargateClient, GasPrice } = (await import("@cosmjs/stargate")).default;
|
|
83
91
|
const gasPrice = typeof optionsOrBaseGas === "string" ? optionsOrBaseGas : "0.0003uatom";
|
|
84
92
|
const options = typeof optionsOrBaseGas === "string" ? {} : optionsOrBaseGas;
|
|
85
93
|
|
|
@@ -93,7 +101,7 @@ export async function createOfflineStargateClient(
|
|
|
93
101
|
wallet: OfflineSigner,
|
|
94
102
|
registry?: SigningStargateClientOptions,
|
|
95
103
|
) {
|
|
96
|
-
const { SigningStargateClient } = await import("@cosmjs/stargate");
|
|
104
|
+
const { SigningStargateClient } = (await import("@cosmjs/stargate")).default;
|
|
97
105
|
|
|
98
106
|
return SigningStargateClient.offline(wallet, registry);
|
|
99
107
|
}
|
|
@@ -126,7 +134,7 @@ const getTransferMsgTypeByChain = (chain: CosmosChain) => {
|
|
|
126
134
|
case Chain.Kujira:
|
|
127
135
|
return "/cosmos.bank.v1beta1.MsgSend";
|
|
128
136
|
default:
|
|
129
|
-
throw new
|
|
137
|
+
throw new SwapKitError("toolbox_cosmos_not_supported", { chain });
|
|
130
138
|
}
|
|
131
139
|
};
|
|
132
140
|
|
|
@@ -149,7 +157,7 @@ export const cosmosCreateTransaction = async ({
|
|
|
149
157
|
const accountOnChain = await client.getAccount(sender);
|
|
150
158
|
|
|
151
159
|
if (!accountOnChain) {
|
|
152
|
-
throw new
|
|
160
|
+
throw new SwapKitError("toolbox_cosmos_account_not_found", { sender });
|
|
153
161
|
}
|
|
154
162
|
|
|
155
163
|
const gasAsset = AssetValue.from({ chain });
|
|
@@ -178,3 +186,65 @@ export const cosmosCreateTransaction = async ({
|
|
|
178
186
|
msgs: [{ typeUrl: getTransferMsgTypeByChain(chain as CosmosChain), value: msgSend }],
|
|
179
187
|
};
|
|
180
188
|
};
|
|
189
|
+
|
|
190
|
+
// Map of known denoms to their asset configurations
|
|
191
|
+
const DENOM_MAP = {
|
|
192
|
+
// THORChain denoms
|
|
193
|
+
rune: { chain: Chain.THORChain, decimals: BaseDecimal[Chain.THORChain] },
|
|
194
|
+
tcy: { asset: "THOR.TCY", decimals: BaseDecimal[Chain.THORChain] },
|
|
195
|
+
"x/kuji": { asset: "THOR.KUJI", decimals: BaseDecimal[Chain.THORChain] },
|
|
196
|
+
|
|
197
|
+
// Cosmos denoms
|
|
198
|
+
uatom: { chain: Chain.Cosmos, decimals: BaseDecimal[Chain.Cosmos] },
|
|
199
|
+
atom: { chain: Chain.Cosmos, decimals: BaseDecimal[Chain.Cosmos] },
|
|
200
|
+
|
|
201
|
+
// Maya denoms
|
|
202
|
+
cacao: { chain: Chain.Maya, decimals: 10 }, // Maya uses 10 decimals for CACAO
|
|
203
|
+
maya: { asset: `${Chain.Maya}.${Chain.Maya}`, decimals: 4 }, // MAYA token uses 4 decimals
|
|
204
|
+
|
|
205
|
+
// Kujira denoms
|
|
206
|
+
ukuji: { chain: Chain.Kujira, decimals: BaseDecimal[Chain.Kujira] },
|
|
207
|
+
kuji: { chain: Chain.Kujira, decimals: BaseDecimal[Chain.Kujira] },
|
|
208
|
+
|
|
209
|
+
// USK on Kujira (lowercase version of the factory denom)
|
|
210
|
+
[USK_KUJIRA_FACTORY_DENOM.toLowerCase()]: {
|
|
211
|
+
asset: `${Chain.Kujira}.USK`,
|
|
212
|
+
decimals: BaseDecimal[Chain.Kujira],
|
|
213
|
+
},
|
|
214
|
+
};
|
|
215
|
+
|
|
216
|
+
/**
|
|
217
|
+
* Converts a Cosmos denom and amount to an AssetValue with proper decimal handling
|
|
218
|
+
* @param denom - The denomination string
|
|
219
|
+
* @param amount - The amount in base units as a string
|
|
220
|
+
* @returns AssetValue with the correct decimal conversion
|
|
221
|
+
*/
|
|
222
|
+
export const getAssetFromDenom = (denom: string, amount: string) => {
|
|
223
|
+
const config = DENOM_MAP[denom.toLowerCase()];
|
|
224
|
+
|
|
225
|
+
if (!config) {
|
|
226
|
+
// For unknown denoms, default to 8 decimals (common for many Cosmos chains)
|
|
227
|
+
// This preserves the original behavior while using fromBaseDecimal
|
|
228
|
+
return AssetValue.from({
|
|
229
|
+
asset: denom,
|
|
230
|
+
value: amount,
|
|
231
|
+
fromBaseDecimal: 8,
|
|
232
|
+
});
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
const { chain, asset, decimals } = config;
|
|
236
|
+
|
|
237
|
+
const assetOrChain = (
|
|
238
|
+
chain
|
|
239
|
+
? {
|
|
240
|
+
chain,
|
|
241
|
+
}
|
|
242
|
+
: { asset }
|
|
243
|
+
) as { asset: string } | { chain: CosmosChain };
|
|
244
|
+
|
|
245
|
+
return AssetValue.from({
|
|
246
|
+
...assetOrChain,
|
|
247
|
+
value: amount,
|
|
248
|
+
fromBaseDecimal: decimals,
|
|
249
|
+
});
|
|
250
|
+
};
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
import { beforeAll, describe, expect, test } from "bun:test";
|
|
2
|
+
import { Chain } from "@swapkit/helpers";
|
|
3
|
+
import { getEvmToolbox } from "../toolbox";
|
|
4
|
+
|
|
5
|
+
const context: {
|
|
6
|
+
validateAddress: (address: string) => boolean;
|
|
7
|
+
} = {} as any;
|
|
8
|
+
|
|
9
|
+
beforeAll(async () => {
|
|
10
|
+
// Get EVM toolbox for address validation
|
|
11
|
+
const toolbox = await getEvmToolbox(Chain.Ethereum);
|
|
12
|
+
context.validateAddress = toolbox.validateAddress;
|
|
13
|
+
});
|
|
14
|
+
|
|
15
|
+
describe("EVM Address Validation", () => {
|
|
16
|
+
test("should validate valid EVM addresses", () => {
|
|
17
|
+
const validAddresses = [
|
|
18
|
+
"0xa052Ddf1c1739419B90FB7bf722843AD3e63114B", // User provided address
|
|
19
|
+
"0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48", // USDC contract
|
|
20
|
+
"0x6d6e022eE439C8aB8B7a7dBb0576f8090319CDc6", // Test address
|
|
21
|
+
"0xE29E61479420Dd1029A9946710Ac31A0d140e77F", // Another valid address
|
|
22
|
+
"0x0000000000000000000000000000000000000000", // Zero address
|
|
23
|
+
"0xFFfFfFffFFfffFFfFFfFFFFFffFFFffffFfFFFfF", // Max address
|
|
24
|
+
"0x1234567890123456789012345678901234567890", // Mixed case
|
|
25
|
+
];
|
|
26
|
+
|
|
27
|
+
for (const address of validAddresses) {
|
|
28
|
+
expect(context.validateAddress(address)).toBe(true);
|
|
29
|
+
}
|
|
30
|
+
});
|
|
31
|
+
|
|
32
|
+
test("should reject invalid EVM addresses", () => {
|
|
33
|
+
const invalidAddresses = [
|
|
34
|
+
"", // Empty string
|
|
35
|
+
"invalid", // Random string
|
|
36
|
+
"TR7NHqjeKQxGTCi8q8ZY4pL8otSzgjLj6t", // TRON address
|
|
37
|
+
"1A1zP1eP5QGefi2DMPTfTL5SLmv7DivfNa", // Bitcoin address
|
|
38
|
+
"cosmos1abc123", // Cosmos address
|
|
39
|
+
"0xa052Ddf1c1739419B90FB7bf722843AD3e63114", // Too short (missing 1 char)
|
|
40
|
+
"0xa052Ddf1c1739419B90FB7bf722843AD3e63114BB", // Too long (extra char)
|
|
41
|
+
"0XA052DDF1C1739419B90FB7BF722843AD3E63114B", // Uppercase 0X prefix
|
|
42
|
+
"0xG052Ddf1c1739419B90FB7bf722843AD3e63114B", // Invalid hex character
|
|
43
|
+
"0x", // Only prefix
|
|
44
|
+
];
|
|
45
|
+
|
|
46
|
+
for (const address of invalidAddresses) {
|
|
47
|
+
expect(context.validateAddress(address)).toBe(false);
|
|
48
|
+
}
|
|
49
|
+
});
|
|
50
|
+
|
|
51
|
+
test("should handle case normalization properly", () => {
|
|
52
|
+
const address = "0xa052Ddf1c1739419B90FB7bf722843AD3e63114B"; // Proper checksum
|
|
53
|
+
const lowerCase = address.toLowerCase();
|
|
54
|
+
|
|
55
|
+
// Valid case variations should be accepted
|
|
56
|
+
expect(context.validateAddress(address)).toBe(true);
|
|
57
|
+
expect(context.validateAddress(lowerCase)).toBe(true);
|
|
58
|
+
});
|
|
59
|
+
|
|
60
|
+
test("should reject invalid checksum addresses", () => {
|
|
61
|
+
const invalidChecksumAddress = "0xA052dDF1C1739419b90fb7BF722843ad3E63114b"; // Invalid checksum
|
|
62
|
+
|
|
63
|
+
// Should reject mixed case with invalid checksum
|
|
64
|
+
expect(context.validateAddress(invalidChecksumAddress)).toBe(false);
|
|
65
|
+
});
|
|
66
|
+
|
|
67
|
+
test("should handle edge cases", () => {
|
|
68
|
+
const edgeCases = [null, undefined, 123, {}, [], true, false];
|
|
69
|
+
|
|
70
|
+
for (const testCase of edgeCases) {
|
|
71
|
+
// Should not throw but return false for invalid inputs
|
|
72
|
+
expect(context.validateAddress(testCase as any)).toBe(false);
|
|
73
|
+
}
|
|
74
|
+
});
|
|
75
|
+
|
|
76
|
+
test("should validate checksummed addresses", () => {
|
|
77
|
+
const checksummedAddresses = [
|
|
78
|
+
"0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48", // USDC with proper checksum
|
|
79
|
+
"0x6d6e022eE439C8aB8B7a7dBb0576f8090319CDc6", // Another checksummed address
|
|
80
|
+
];
|
|
81
|
+
|
|
82
|
+
for (const address of checksummedAddresses) {
|
|
83
|
+
expect(context.validateAddress(address)).toBe(true);
|
|
84
|
+
}
|
|
85
|
+
});
|
|
86
|
+
});
|
|
@@ -35,7 +35,7 @@ beforeEach(async () => {
|
|
|
35
35
|
},
|
|
36
36
|
});
|
|
37
37
|
context.provider = provider;
|
|
38
|
-
context.toolbox = await getEvmToolbox(Chain.Ethereum, { provider, signer });
|
|
38
|
+
context.toolbox = await getEvmToolbox(Chain.Ethereum, { provider, signer: signer as any });
|
|
39
39
|
});
|
|
40
40
|
|
|
41
41
|
afterEach(async () => {
|
package/src/evm/helpers.ts
CHANGED
|
@@ -8,6 +8,7 @@ import {
|
|
|
8
8
|
FeeOption,
|
|
9
9
|
type NetworkParams,
|
|
10
10
|
SKConfig,
|
|
11
|
+
SwapKitError,
|
|
11
12
|
SwapKitNumber,
|
|
12
13
|
} from "@swapkit/helpers";
|
|
13
14
|
import type { BrowserProvider, Provider } from "ethers";
|
|
@@ -71,7 +72,7 @@ export const estimateMaxSendableAmount = async ({
|
|
|
71
72
|
const isFeeEVMLegacyCompatible = "gasPrice" in gasRate && gasRate.gasPrice !== undefined;
|
|
72
73
|
|
|
73
74
|
if (!(gasRate && (isFeeEVMLegacyCompatible || isFeeEIP1559Compatible))) {
|
|
74
|
-
throw new
|
|
75
|
+
throw new SwapKitError("toolbox_evm_no_fee_data");
|
|
75
76
|
}
|
|
76
77
|
|
|
77
78
|
const gasPrice = isFeeEIP1559Compatible
|
|
@@ -116,7 +117,7 @@ export function getEstimateTransactionFee({
|
|
|
116
117
|
return assetValue.set(SwapKitNumber.fromBigInt(fee, assetValue.decimal));
|
|
117
118
|
}
|
|
118
119
|
|
|
119
|
-
throw new
|
|
120
|
+
throw new SwapKitError("toolbox_evm_no_gas_price");
|
|
120
121
|
};
|
|
121
122
|
}
|
|
122
123
|
|
|
@@ -168,6 +169,6 @@ function getNetworkInfo<C extends EVMChain>({ chain }: { chain: C }) {
|
|
|
168
169
|
nativeCurrency: { name: "Polygon", symbol: Chain.Polygon, decimals },
|
|
169
170
|
};
|
|
170
171
|
default:
|
|
171
|
-
throw new
|
|
172
|
+
throw new SwapKitError("toolbox_evm_not_supported", { chain });
|
|
172
173
|
}
|
|
173
174
|
}
|