@continuumdao/ctm-mpc-defi 0.2.0 → 0.2.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/README.md +20 -78
- package/dist/agent/catalog.cjs +563 -5
- package/dist/agent/catalog.cjs.map +1 -1
- package/dist/agent/catalog.d.ts +166 -20
- package/dist/agent/catalog.js +551 -7
- package/dist/agent/catalog.js.map +1 -1
- package/dist/agent/skills/aave-v4/SKILL.md +43 -0
- package/dist/agent/skills/curve-dao/SKILL.md +13 -0
- package/dist/agent/skills/ethena/SKILL.md +10 -0
- package/dist/agent/skills/euler-v2/SKILL.md +10 -0
- package/dist/agent/skills/lido/SKILL.md +22 -0
- package/dist/agent/skills/maple-syrup/SKILL.md +10 -0
- package/dist/agent/skills/sky/SKILL.md +10 -0
- package/dist/agent/skills/uniswap-v4/SKILL.md +22 -0
- package/dist/chains/evm/index.cjs +79 -224
- package/dist/chains/evm/index.cjs.map +1 -1
- package/dist/chains/evm/index.d.ts +26 -26
- package/dist/chains/evm/index.js +69 -209
- package/dist/chains/evm/index.js.map +1 -1
- package/dist/chains/near/index.d.ts +1 -1
- package/dist/chains/solana/index.d.ts +1 -1
- package/dist/core/index.cjs +68 -106
- package/dist/core/index.cjs.map +1 -1
- package/dist/core/index.d.ts +21 -36
- package/dist/core/index.js +57 -96
- package/dist/core/index.js.map +1 -1
- package/dist/{envelope-CcE5Cz_q.d.ts → envelope-CpBUh9eP.d.ts} +1 -1
- package/dist/index.cjs +356 -1855
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.ts +7 -11
- package/dist/index.js +332 -1826
- package/dist/index.js.map +1 -1
- package/dist/protocols/evm/aave-v4/index.cjs +1152 -669
- package/dist/protocols/evm/aave-v4/index.cjs.map +1 -1
- package/dist/protocols/evm/aave-v4/index.d.ts +418 -3
- package/dist/protocols/evm/aave-v4/index.js +1126 -670
- package/dist/protocols/evm/aave-v4/index.js.map +1 -1
- package/dist/protocols/evm/curve-dao/index.cjs +257 -131
- package/dist/protocols/evm/curve-dao/index.cjs.map +1 -1
- package/dist/protocols/evm/curve-dao/index.d.ts +69 -5
- package/dist/protocols/evm/curve-dao/index.js +242 -124
- package/dist/protocols/evm/curve-dao/index.js.map +1 -1
- package/dist/protocols/evm/ethena/index.cjs +394 -402
- package/dist/protocols/evm/ethena/index.cjs.map +1 -1
- package/dist/protocols/evm/ethena/index.d.ts +47 -3
- package/dist/protocols/evm/ethena/index.js +390 -404
- package/dist/protocols/evm/ethena/index.js.map +1 -1
- package/dist/protocols/evm/euler-v2/index.cjs +2810 -1191
- package/dist/protocols/evm/euler-v2/index.cjs.map +1 -1
- package/dist/protocols/evm/euler-v2/index.d.ts +465 -3
- package/dist/protocols/evm/euler-v2/index.js +2761 -1192
- package/dist/protocols/evm/euler-v2/index.js.map +1 -1
- package/dist/protocols/evm/lido/index.cjs +351 -236
- package/dist/protocols/evm/lido/index.cjs.map +1 -1
- package/dist/protocols/evm/lido/index.d.ts +34 -4
- package/dist/protocols/evm/lido/index.js +348 -238
- package/dist/protocols/evm/lido/index.js.map +1 -1
- package/dist/protocols/evm/maple/index.cjs +390 -395
- package/dist/protocols/evm/maple/index.cjs.map +1 -1
- package/dist/protocols/evm/maple/index.d.ts +23 -3
- package/dist/protocols/evm/maple/index.js +390 -397
- package/dist/protocols/evm/maple/index.js.map +1 -1
- package/dist/protocols/evm/sky/index.cjs +454 -232
- package/dist/protocols/evm/sky/index.cjs.map +1 -1
- package/dist/protocols/evm/sky/index.d.ts +57 -3
- package/dist/protocols/evm/sky/index.js +444 -231
- package/dist/protocols/evm/sky/index.js.map +1 -1
- package/dist/protocols/evm/uniswap-v4/index.cjs +423 -658
- package/dist/protocols/evm/uniswap-v4/index.cjs.map +1 -1
- package/dist/protocols/evm/uniswap-v4/index.d.ts +3 -4
- package/dist/protocols/evm/uniswap-v4/index.js +422 -657
- package/dist/protocols/evm/uniswap-v4/index.js.map +1 -1
- package/dist/{registry-oMKlO_5z.d.ts → registry-Bv5o37_w.d.ts} +1 -1
- package/dist/{types-Ce2qNHai.d.cts → types-BfjWdw1j.d.ts} +3 -1
- package/dist/{types-5u863Fd9.d.ts → types-DUeNJLr9.d.ts} +1 -1
- package/package.json +7 -6
- package/dist/agent/catalog.d.cts +0 -939
- package/dist/chains/evm/index.d.cts +0 -64
- package/dist/chains/near/index.d.cts +0 -37
- package/dist/chains/solana/index.d.cts +0 -40
- package/dist/core/index.d.cts +0 -43
- package/dist/envelope-DYDPnrHZ.d.cts +0 -35
- package/dist/index.d.cts +0 -16
- package/dist/keygen-CfNp8yKJ.d.cts +0 -9
- package/dist/keygen-DsINazx8.d.ts +0 -9
- package/dist/nodeRead-BnmSaMGO.d.cts +0 -8
- package/dist/nodeRead-BnmSaMGO.d.ts +0 -8
- package/dist/protocols/evm/aave-v4/index.d.cts +0 -500
- package/dist/protocols/evm/curve-dao/index.d.cts +0 -147
- package/dist/protocols/evm/ethena/index.d.cts +0 -161
- package/dist/protocols/evm/euler-v2/index.d.cts +0 -317
- package/dist/protocols/evm/lido/index.d.cts +0 -120
- package/dist/protocols/evm/maple/index.d.cts +0 -109
- package/dist/protocols/evm/sky/index.d.cts +0 -218
- package/dist/protocols/evm/uniswap-v4/index.d.cts +0 -324
- package/dist/registry-BwZoE668.d.cts +0 -8
- package/dist/txParams-BC7ogvdR.d.cts +0 -19
- package/dist/txParams-BC7ogvdR.d.ts +0 -19
- package/dist/types-B8idm_gu.d.cts +0 -34
- package/dist/types-Ce2qNHai.d.ts +0 -57
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: aave-v4
|
|
3
|
+
description: Aave v4 Spoke supply, withdraw, borrow, and repay via Continuum MPC multiSignRequest tools.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Aave v4 (MCP)
|
|
7
|
+
|
|
8
|
+
## Before any action
|
|
9
|
+
|
|
10
|
+
1. `load_defi_protocol({ protocolId: "aave-v4" })`
|
|
11
|
+
2. `get_defi_protocol_supported_chains` — intersect with `get_chain_registry` (node must have RPC)
|
|
12
|
+
3. `get_defi_protocol_supported_tokens({ protocolId: "aave-v4", chainId })` — market underlyings
|
|
13
|
+
4. `get_token_registry` — map symbols (USDC, stETH, WETH) to addresses
|
|
14
|
+
|
|
15
|
+
## Tool selection
|
|
16
|
+
|
|
17
|
+
| User intent | MCP tool |
|
|
18
|
+
|-------------|----------|
|
|
19
|
+
| Supply / deposit asset | `ctm_aave_v4_build_deposit_multisign` |
|
|
20
|
+
| Withdraw supplied asset | `ctm_aave_v4_build_withdraw_multisign` |
|
|
21
|
+
| Borrow against collateral | `ctm_aave_v4_build_borrow_multisign` |
|
|
22
|
+
| Repay debt | `ctm_aave_v4_build_repay_multisign` |
|
|
23
|
+
|
|
24
|
+
Example: **borrow USDC against stETH** → deposit/wrap collateral first if needed, then `ctm_aave_v4_build_borrow_multisign` with `underlying` = USDC address, `marketId` from Aave UI/API.
|
|
25
|
+
|
|
26
|
+
## Required inputs (per action)
|
|
27
|
+
|
|
28
|
+
- `keyGenId`, `chainId`, `purposeText`
|
|
29
|
+
- `spoke`, `underlying`, `amountHuman`, `marketId` (hub/market segment)
|
|
30
|
+
|
|
31
|
+
## After submit (`{ requestId }`)
|
|
32
|
+
|
|
33
|
+
Use base MCP lifecycle:
|
|
34
|
+
|
|
35
|
+
1. `wait_for_sign_request_ready` (if needed)
|
|
36
|
+
2. `sign_request_agree` (multi-agree)
|
|
37
|
+
3. `trigger_sign_result`
|
|
38
|
+
4. `broadcast_sign_result`
|
|
39
|
+
|
|
40
|
+
## Notes
|
|
41
|
+
|
|
42
|
+
- Native ETH supply uses wrapped native from Aave API on that chain.
|
|
43
|
+
- Token filter: `api_underlyings` — only listed underlyings are valid per chain.
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: curve-dao
|
|
3
|
+
description: Curve Router NG swaps via @curvefi/api session and multisign batch.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Curve DAO (MCP)
|
|
7
|
+
|
|
8
|
+
1. Confirm chain via `get_defi_protocol_supported_chains` and `isCurveApiChainSupported`.
|
|
9
|
+
2. `get_defi_protocol_supported_tokens` with `rpcUrl` from chain registry loads pool-graph swappable tokens.
|
|
10
|
+
3. `ctm_curve_dao_quote` — `chainId`, `tokenIn`, `tokenOut`, `amountHuman` (optional `tokenInDecimals`). Server resolves `rpcUrl` from chain registry.
|
|
11
|
+
4. `ctm_curve_dao_build_swap_multisign` — `keyGenId`, `chainId`, `purposeText`, `tokenIn`, `tokenOut`, `amountHuman`, `slippagePercent`.
|
|
12
|
+
|
|
13
|
+
Base MCP lifecycle after `{ requestId }`.
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: ethena
|
|
3
|
+
description: Ethena USDe stake, redeem, cooldown, and claim on Ethereum mainnet.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Ethena (MCP)
|
|
7
|
+
|
|
8
|
+
Stake/redeem MCP tools target **mainnet (chainId 1)**. Use `get_defi_protocol_supported_tokens` for USDe/sUSDe addresses.
|
|
9
|
+
|
|
10
|
+
Tools: `ctm_ethena_build_stake_multisign`, `_redeem_`, `_cooldown_`, `_claim_`.
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: euler-v2
|
|
3
|
+
description: Euler v2 isolated lend/borrow, vault withdraw, and collateral operations.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Euler v2 (MCP)
|
|
7
|
+
|
|
8
|
+
Supported chains from `get_defi_protocol_supported_chains` (subgraph map). Pass `vault` and asset addresses from Euler UI.
|
|
9
|
+
|
|
10
|
+
Tools include isolated lend/borrow, collateral deposit/withdraw, vault withdraw, borrow repay.
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: lido
|
|
3
|
+
description: Lido ETH staking, withdrawals, and wstETH wrap/unwrap on Ethereum mainnet.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Lido (MCP)
|
|
7
|
+
|
|
8
|
+
## Chains
|
|
9
|
+
|
|
10
|
+
Mainnet only (`chainId: 1`). Use `get_defi_protocol_supported_chains` and confirm node has chain 1 in `get_chain_registry`.
|
|
11
|
+
|
|
12
|
+
## Tools
|
|
13
|
+
|
|
14
|
+
| Intent | Tool |
|
|
15
|
+
|--------|------|
|
|
16
|
+
| Stake ETH | `ctm_lido_build_submit_multisign` |
|
|
17
|
+
| Queue stETH withdrawal | `ctm_lido_build_request_withdrawals_multisign` |
|
|
18
|
+
| Claim withdrawal | `ctm_lido_build_claim_withdrawal_multisign` |
|
|
19
|
+
| Wrap stETH → wstETH | `ctm_lido_build_wrap_steth_multisign` |
|
|
20
|
+
| Unwrap wstETH | `ctm_lido_build_unwrap_wsteth_multisign` |
|
|
21
|
+
|
|
22
|
+
Complete flow with base MCP: `trigger_sign_result` → `broadcast_sign_result`.
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: maple-syrup
|
|
3
|
+
description: Maple Syrup pool deposit and redeem request flows.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Maple Syrup (MCP)
|
|
7
|
+
|
|
8
|
+
Chains: mainnet and Sepolia. Pass `syrupRouter`, `pool`, and `asset` from Maple UI/GraphQL.
|
|
9
|
+
|
|
10
|
+
Tools: `ctm_maple_build_deposit_multisign`, `ctm_maple_build_request_redeem_multisign`.
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: sky
|
|
3
|
+
description: Sky Lockstake and sUSDS deposit/redeem on Ethereum mainnet.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Sky (MCP)
|
|
7
|
+
|
|
8
|
+
Mainnet only. Tools for Lockstake stake/draw/wipe/close/reward and sUSDS deposit/redeem.
|
|
9
|
+
|
|
10
|
+
Use `get_defi_protocol_supported_chains` and base registry for USDS/SKY addresses.
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: uniswap-v4
|
|
3
|
+
description: Uniswap V4 swaps via Trade API quote, swap calldata, and multisign submit.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Uniswap v4 (MCP)
|
|
7
|
+
|
|
8
|
+
## Multi-step swap flow
|
|
9
|
+
|
|
10
|
+
1. `ctm_uniswap_v4_quote` — requires `UNISWAP_API_KEY` env on MCP server
|
|
11
|
+
2. `ctm_uniswap_v4_create_swap` — Universal Router calldata
|
|
12
|
+
3. `ctm_uniswap_v4_build_swap_multisign` — submits sign request → `{ requestId }`
|
|
13
|
+
|
|
14
|
+
## Chains / tokens
|
|
15
|
+
|
|
16
|
+
- Chains: `get_defi_protocol_supported_chains` (Universal Router map)
|
|
17
|
+
- Tokens: any ERC-20 on supported chain; use `get_token_registry` for wallet tokens
|
|
18
|
+
- `tokenOut` may be any address on same chain
|
|
19
|
+
|
|
20
|
+
## After submit
|
|
21
|
+
|
|
22
|
+
Base MCP: `trigger_sign_result` → `broadcast_sign_result`.
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
3
|
var viem = require('viem');
|
|
4
|
+
var continuumNodeSdk = require('@continuumdao/continuum-node-sdk');
|
|
4
5
|
|
|
5
6
|
// src/chains/evm/types.ts
|
|
6
7
|
function isEvmNativeToken(address) {
|
|
@@ -18,100 +19,6 @@ function matchEvmTokenKind(kind, address) {
|
|
|
18
19
|
return true;
|
|
19
20
|
}
|
|
20
21
|
|
|
21
|
-
// src/chains/evm/txParams.ts
|
|
22
|
-
function gasLimitFromEstimateAndChainConfig(estimatedGas, chainGasLimit) {
|
|
23
|
-
if (chainGasLimit == null || !Number.isFinite(chainGasLimit) || chainGasLimit <= 0) {
|
|
24
|
-
return estimatedGas;
|
|
25
|
-
}
|
|
26
|
-
const cfg = BigInt(Math.floor(chainGasLimit));
|
|
27
|
-
return cfg > estimatedGas ? cfg : estimatedGas;
|
|
28
|
-
}
|
|
29
|
-
function routerSwapGasLimitFromEstimate(estimatedGas, chainGasLimit) {
|
|
30
|
-
if (chainGasLimit != null && Number.isFinite(chainGasLimit) && chainGasLimit > 0) {
|
|
31
|
-
return gasLimitFromEstimateAndChainConfig(estimatedGas, chainGasLimit);
|
|
32
|
-
}
|
|
33
|
-
return (estimatedGas * 12n + 9n) / 10n;
|
|
34
|
-
}
|
|
35
|
-
function composeFeePayloadToTxParams(p, legacy) {
|
|
36
|
-
const gl = p.txGasLimit ?? p.txgaslimit;
|
|
37
|
-
if (gl == null || String(gl).trim() === "") return void 0;
|
|
38
|
-
const n = p.txNonce ?? p.txnonce;
|
|
39
|
-
let nonce = 0;
|
|
40
|
-
if (typeof n === "bigint") nonce = Number(n);
|
|
41
|
-
else if (typeof n === "number") nonce = n;
|
|
42
|
-
else if (n != null) nonce = parseInt(String(n), 10);
|
|
43
|
-
if (!Number.isFinite(nonce)) nonce = 0;
|
|
44
|
-
const gasLimit = String(gl);
|
|
45
|
-
if (legacy) {
|
|
46
|
-
const gp = p.txGasPrice ?? p.txgasprice;
|
|
47
|
-
return {
|
|
48
|
-
nonce,
|
|
49
|
-
gasLimit,
|
|
50
|
-
txType: "legacy",
|
|
51
|
-
gasPrice: gp != null ? String(gp) : "0"
|
|
52
|
-
};
|
|
53
|
-
}
|
|
54
|
-
return {
|
|
55
|
-
nonce,
|
|
56
|
-
gasLimit,
|
|
57
|
-
txType: "eip1559",
|
|
58
|
-
maxFeePerGas: String(p.txMaxFeePerGas ?? ""),
|
|
59
|
-
maxPriorityFeePerGas: String(p.txMaxPriorityFeePerGas ?? "")
|
|
60
|
-
};
|
|
61
|
-
}
|
|
62
|
-
function triggerTxParamsFromComposeBody(body) {
|
|
63
|
-
const existing = body.txParams;
|
|
64
|
-
if (existing && typeof existing === "object" && !Array.isArray(existing)) {
|
|
65
|
-
const o = existing;
|
|
66
|
-
if (String(o.gasLimit ?? "").trim() !== "") {
|
|
67
|
-
return { ...o };
|
|
68
|
-
}
|
|
69
|
-
}
|
|
70
|
-
const pb = body.proposalTxParams;
|
|
71
|
-
if (Array.isArray(pb) && pb.length > 0 && typeof pb[0] === "object" && pb[0] !== null) {
|
|
72
|
-
const first = pb[0];
|
|
73
|
-
if (String(first.gasLimit ?? "").trim() !== "") {
|
|
74
|
-
return { ...first };
|
|
75
|
-
}
|
|
76
|
-
}
|
|
77
|
-
const fromSnapshot = composeFeePayloadToTxParams(
|
|
78
|
-
body,
|
|
79
|
-
body.txMaxFeePerGas == null && body.txMaxPriorityFeePerGas == null
|
|
80
|
-
);
|
|
81
|
-
if (fromSnapshot) return fromSnapshot;
|
|
82
|
-
return {
|
|
83
|
-
nonce: 0,
|
|
84
|
-
gasLimit: "",
|
|
85
|
-
txType: "legacy",
|
|
86
|
-
gasPrice: "0"
|
|
87
|
-
};
|
|
88
|
-
}
|
|
89
|
-
function proposalTxParamsToFeeSnapshot(params) {
|
|
90
|
-
if (params.txType === "legacy") {
|
|
91
|
-
return {
|
|
92
|
-
txNonce: params.nonce,
|
|
93
|
-
txGasLimit: params.gasLimit,
|
|
94
|
-
txGasPrice: params.gasPrice ?? "0"
|
|
95
|
-
};
|
|
96
|
-
}
|
|
97
|
-
return {
|
|
98
|
-
txNonce: params.nonce,
|
|
99
|
-
txGasLimit: params.gasLimit,
|
|
100
|
-
txMaxFeePerGas: params.maxFeePerGas ?? "",
|
|
101
|
-
txMaxPriorityFeePerGas: params.maxPriorityFeePerGas ?? ""
|
|
102
|
-
};
|
|
103
|
-
}
|
|
104
|
-
|
|
105
|
-
// src/core/keygen.ts
|
|
106
|
-
function firstClientIdFromKeyGen(data) {
|
|
107
|
-
const map = data?.ClientKeys;
|
|
108
|
-
if (!map || typeof map !== "object") return null;
|
|
109
|
-
for (const v of Object.values(map)) {
|
|
110
|
-
if (typeof v === "string" && v.trim()) return v.trim();
|
|
111
|
-
}
|
|
112
|
-
return null;
|
|
113
|
-
}
|
|
114
|
-
|
|
115
22
|
// src/core/purpose.ts
|
|
116
23
|
function mergePurposeText(purposeText, purposeSuffix) {
|
|
117
24
|
const t = purposeText.trim();
|
|
@@ -131,7 +38,7 @@ function finalizeMultisign(input) {
|
|
|
131
38
|
const ph = (keyGen.pubkeyhex ?? "").trim();
|
|
132
39
|
if (!ph) throw new Error("keyGen pubKey (pubkeyhex) is required");
|
|
133
40
|
const keyList = keyGen.keylist ?? [];
|
|
134
|
-
const clientId =
|
|
41
|
+
const clientId = continuumNodeSdk.getClientIdFromKeyGenResult(keyGen);
|
|
135
42
|
const first = legs[0];
|
|
136
43
|
const messageHashes = legs.map((l) => l.msgHash);
|
|
137
44
|
const messageRawBatch = legs.map((l) => l.msgRaw);
|
|
@@ -172,76 +79,11 @@ function finalizeMultisign(input) {
|
|
|
172
79
|
if (clientId) bodyForSign.clientId = clientId;
|
|
173
80
|
return { bodyForSign, messageToSign: JSON.stringify(bodyForSign) };
|
|
174
81
|
}
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
const chainIdNum = typeof chainId === "string" ? parseInt(chainId, 10) : chainId;
|
|
179
|
-
if (Number.isNaN(chainIdNum)) return { isEip1559: false };
|
|
180
|
-
const chain = viem.defineChain({
|
|
181
|
-
id: chainIdNum,
|
|
182
|
-
name: "Discovery",
|
|
183
|
-
nativeCurrency: { decimals: 18, name: "Ether", symbol: "ETH" },
|
|
184
|
-
rpcUrls: { default: { http: [url] } }
|
|
185
|
-
});
|
|
186
|
-
const publicClient = viem.createPublicClient({
|
|
187
|
-
chain,
|
|
188
|
-
transport: viem.http(url)
|
|
189
|
-
});
|
|
190
|
-
const getGasPriceGwei = async () => {
|
|
191
|
-
const gasPriceWei = await publicClient.getGasPrice();
|
|
192
|
-
return parseFloat(viem.formatUnits(gasPriceWei, 9));
|
|
193
|
-
};
|
|
194
|
-
try {
|
|
195
|
-
const block = await publicClient.getBlock({ blockTag: "latest" });
|
|
196
|
-
const baseFeePerGas = block?.baseFeePerGas;
|
|
197
|
-
if (baseFeePerGas == null || baseFeePerGas === void 0) {
|
|
198
|
-
const gasPriceGwei2 = await getGasPriceGwei();
|
|
199
|
-
return { isEip1559: false, gasPriceGwei: gasPriceGwei2 };
|
|
200
|
-
}
|
|
201
|
-
const baseFeeGwei = parseFloat(viem.formatUnits(baseFeePerGas, 9));
|
|
202
|
-
let priorityFeeGwei;
|
|
203
|
-
try {
|
|
204
|
-
const priorityWei = await publicClient.estimateMaxPriorityFeePerGas();
|
|
205
|
-
priorityFeeGwei = parseFloat(viem.formatUnits(priorityWei, 9));
|
|
206
|
-
} catch {
|
|
207
|
-
}
|
|
208
|
-
const gasPriceGwei = await getGasPriceGwei();
|
|
209
|
-
return {
|
|
210
|
-
isEip1559: true,
|
|
211
|
-
baseFeeGwei,
|
|
212
|
-
priorityFeeGwei,
|
|
213
|
-
gasPriceGwei
|
|
214
|
-
};
|
|
215
|
-
} catch {
|
|
216
|
-
try {
|
|
217
|
-
const gasPriceWei = await publicClient.getGasPrice();
|
|
218
|
-
const gasPriceGwei = parseFloat(viem.formatUnits(gasPriceWei, 9));
|
|
219
|
-
return { isEip1559: false, gasPriceGwei };
|
|
220
|
-
} catch {
|
|
221
|
-
return { isEip1559: false };
|
|
222
|
-
}
|
|
223
|
-
}
|
|
224
|
-
}
|
|
225
|
-
function finalizeEip1559Fees(maxFeePerGas, maxPriorityFeePerGas, floor, baseWei) {
|
|
226
|
-
let maxP = maxPriorityFeePerGas;
|
|
227
|
-
let maxF = maxFeePerGas;
|
|
228
|
-
if (baseWei > 0n && maxF < baseWei + maxP) {
|
|
229
|
-
maxF = baseWei + maxP + viem.parseGwei("0.001");
|
|
230
|
-
}
|
|
231
|
-
if (maxF < maxP) {
|
|
232
|
-
maxF = baseWei > 0n ? baseWei + maxP + viem.parseGwei("0.001") : maxP * 2n;
|
|
82
|
+
function routerSwapGasLimitFromEstimate(estimatedGas, chainGasLimit) {
|
|
83
|
+
if (chainGasLimit != null && Number.isFinite(chainGasLimit) && chainGasLimit > 0) {
|
|
84
|
+
return continuumNodeSdk.gasLimitFromEstimateAndChainConfig(estimatedGas, chainGasLimit);
|
|
233
85
|
}
|
|
234
|
-
return
|
|
235
|
-
}
|
|
236
|
-
function alignEip1559FeesWithLatestBase(maxFeePerGas, maxPriorityFeePerGas, latestBlockBaseFeeWei) {
|
|
237
|
-
return finalizeEip1559Fees(maxFeePerGas, maxPriorityFeePerGas, null, latestBlockBaseFeeWei);
|
|
238
|
-
}
|
|
239
|
-
function gweiToDecimalString(n) {
|
|
240
|
-
if (!Number.isFinite(n)) return "0";
|
|
241
|
-
if (n === 0) return "0";
|
|
242
|
-
const s = String(n);
|
|
243
|
-
if (s.indexOf("e") !== -1 || s.indexOf("E") !== -1) return n.toFixed(9).replace(/\.?0+$/, "") || "0";
|
|
244
|
-
return s;
|
|
86
|
+
return (estimatedGas * 12n + 9n) / 10n;
|
|
245
87
|
}
|
|
246
88
|
|
|
247
89
|
// src/chains/evm/buildBatch.ts
|
|
@@ -265,7 +107,7 @@ async function buildEvmMultisignBatch(args) {
|
|
|
265
107
|
rpcUrls: { default: { http: [rpcUrl] } }
|
|
266
108
|
});
|
|
267
109
|
const publicClient = viem.createPublicClient({ chain: ch, transport: viem.http(rpcUrl) });
|
|
268
|
-
const feeParams = await fetchChainFeeParams(rpcUrl, chainId);
|
|
110
|
+
const feeParams = await continuumNodeSdk.fetchChainFeeParams(rpcUrl, chainId);
|
|
269
111
|
const legacy = Boolean(chainDetail?.legacy) || !feeParams.isEip1559;
|
|
270
112
|
const latestBaseFeeWei = !legacy ? (await publicClient.getBlock({ blockTag: "latest" })).baseFeePerGas ?? 0n : 0n;
|
|
271
113
|
const gasLimitConfig = useCustomGas && chainDetail?.gasLimit != null ? Number(chainDetail.gasLimit) : void 0;
|
|
@@ -278,15 +120,19 @@ async function buildEvmMultisignBatch(args) {
|
|
|
278
120
|
const step = steps[i];
|
|
279
121
|
const currentNonce = baseNonce + i;
|
|
280
122
|
let estimatedGas;
|
|
281
|
-
|
|
282
|
-
estimatedGas = await
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
123
|
+
if (args.estimateGasForStep) {
|
|
124
|
+
estimatedGas = await args.estimateGasForStep({ step, index: i, publicClient, executor });
|
|
125
|
+
} else {
|
|
126
|
+
try {
|
|
127
|
+
estimatedGas = await publicClient.estimateGas({
|
|
128
|
+
to: step.to,
|
|
129
|
+
data: step.data,
|
|
130
|
+
value: step.value,
|
|
131
|
+
account: executor
|
|
132
|
+
});
|
|
133
|
+
} catch {
|
|
134
|
+
estimatedGas = step.fallbackGas ?? 100000n;
|
|
135
|
+
}
|
|
290
136
|
}
|
|
291
137
|
let gasLimitI;
|
|
292
138
|
if (args.resolveGasLimit) {
|
|
@@ -294,7 +140,7 @@ async function buildEvmMultisignBatch(args) {
|
|
|
294
140
|
} else if (step.routerSwap) {
|
|
295
141
|
gasLimitI = routerSwapGasLimitFromEstimate(estimatedGas, chainGasLimitRouter);
|
|
296
142
|
} else {
|
|
297
|
-
gasLimitI = useCustomGas ? gasLimitFromEstimateAndChainConfig(estimatedGas, gasLimitConfig) : estimatedGas;
|
|
143
|
+
gasLimitI = useCustomGas ? continuumNodeSdk.gasLimitFromEstimateAndChainConfig(estimatedGas, gasLimitConfig) : estimatedGas;
|
|
298
144
|
}
|
|
299
145
|
let proposalTxParams;
|
|
300
146
|
let feeSnapshot;
|
|
@@ -305,7 +151,7 @@ async function buildEvmMultisignBatch(args) {
|
|
|
305
151
|
gasPriceWei = gasPriceWei * BigInt(100 + gasFeeMultiplier) / 100n;
|
|
306
152
|
}
|
|
307
153
|
if (useCustomGas && chainDetail?.gasPrice != null && chainDetail.gasPrice > 0) {
|
|
308
|
-
const configured = viem.parseGwei(gweiToDecimalString(Number(chainDetail.gasPrice)));
|
|
154
|
+
const configured = viem.parseGwei(continuumNodeSdk.gweiToDecimalString(Number(chainDetail.gasPrice)));
|
|
309
155
|
if (configured > gasPriceWei) gasPriceWei = configured;
|
|
310
156
|
}
|
|
311
157
|
serialized = viem.serializeTransaction({
|
|
@@ -324,7 +170,7 @@ async function buildEvmMultisignBatch(args) {
|
|
|
324
170
|
txType: "legacy",
|
|
325
171
|
gasPrice: gasPriceWei.toString()
|
|
326
172
|
};
|
|
327
|
-
feeSnapshot = proposalTxParamsToFeeSnapshot(proposalTxParams);
|
|
173
|
+
feeSnapshot = continuumNodeSdk.proposalTxParamsToFeeSnapshot(proposalTxParams);
|
|
328
174
|
} else {
|
|
329
175
|
const fetchedBase = feeParams.baseFeeGwei ?? 0;
|
|
330
176
|
const fetchedPriority = feeParams.priorityFeeGwei ?? 0;
|
|
@@ -335,13 +181,13 @@ async function buildEvmMultisignBatch(args) {
|
|
|
335
181
|
const baseFeeMultiplierPct = useCustomGas && chainDetail?.baseFeeMultiplier != null ? Math.max(100, Number(chainDetail.baseFeeMultiplier)) : 100;
|
|
336
182
|
const baseComponentGwei = effectiveBaseFeeGwei * baseFeeMultiplierPct / 100;
|
|
337
183
|
const maxFeePerGasGwei = baseComponentGwei + effectivePriorityFeeGwei;
|
|
338
|
-
let maxPriorityFeePerGas = effectivePriorityFeeGwei > 0 ? viem.parseGwei(gweiToDecimalString(effectivePriorityFeeGwei)) : viem.parseGwei("1");
|
|
339
|
-
let maxFeePerGas = viem.parseGwei(gweiToDecimalString(maxFeePerGasGwei));
|
|
184
|
+
let maxPriorityFeePerGas = effectivePriorityFeeGwei > 0 ? viem.parseGwei(continuumNodeSdk.gweiToDecimalString(effectivePriorityFeeGwei)) : viem.parseGwei("1");
|
|
185
|
+
let maxFeePerGas = viem.parseGwei(continuumNodeSdk.gweiToDecimalString(maxFeePerGasGwei));
|
|
340
186
|
if (useCustomGas && gasFeeMultiplier != null && gasFeeMultiplier > 0) {
|
|
341
187
|
maxPriorityFeePerGas = maxPriorityFeePerGas * BigInt(100 + gasFeeMultiplier) / 100n;
|
|
342
188
|
maxFeePerGas = maxFeePerGas * BigInt(100 + gasFeeMultiplier) / 100n;
|
|
343
189
|
}
|
|
344
|
-
({ maxFeePerGas, maxPriorityFeePerGas } = alignEip1559FeesWithLatestBase(
|
|
190
|
+
({ maxFeePerGas, maxPriorityFeePerGas } = continuumNodeSdk.alignEip1559FeesWithLatestBase(
|
|
345
191
|
maxFeePerGas,
|
|
346
192
|
maxPriorityFeePerGas,
|
|
347
193
|
latestBaseFeeWei
|
|
@@ -364,7 +210,7 @@ async function buildEvmMultisignBatch(args) {
|
|
|
364
210
|
maxFeePerGas: maxFeePerGas.toString(),
|
|
365
211
|
maxPriorityFeePerGas: maxPriorityFeePerGas.toString()
|
|
366
212
|
};
|
|
367
|
-
feeSnapshot = i === 0 ? proposalTxParamsToFeeSnapshot(proposalTxParams) : {};
|
|
213
|
+
feeSnapshot = i === 0 ? continuumNodeSdk.proposalTxParamsToFeeSnapshot(proposalTxParams) : {};
|
|
368
214
|
}
|
|
369
215
|
const h = viem.keccak256(serialized);
|
|
370
216
|
const msgHash = h.startsWith("0x") ? h.slice(2) : h;
|
|
@@ -408,30 +254,6 @@ var evmChainCategoryModule = {
|
|
|
408
254
|
buildEvmMultisignBatch
|
|
409
255
|
};
|
|
410
256
|
|
|
411
|
-
// src/chains/evm/fees/customGas.ts
|
|
412
|
-
function chainSnapshotForCustomGasExtraJSON(chainDetail) {
|
|
413
|
-
const lr = chainDetail.legacy;
|
|
414
|
-
const legacy = lr === true || typeof lr === "string" && lr.toLowerCase() === "true";
|
|
415
|
-
const push = (o, key, v) => {
|
|
416
|
-
if (v === void 0 || v === null) return;
|
|
417
|
-
if (typeof v === "string" && v.trim() === "") return;
|
|
418
|
-
o[key] = v;
|
|
419
|
-
};
|
|
420
|
-
const fields = {};
|
|
421
|
-
push(fields, "gasLimit", chainDetail.gasLimit);
|
|
422
|
-
if (legacy) {
|
|
423
|
-
push(fields, "gasMultiplier", chainDetail.gasMultiplier);
|
|
424
|
-
push(fields, "gasPrice", chainDetail.gasPrice);
|
|
425
|
-
} else {
|
|
426
|
-
push(fields, "gasMultiplier", chainDetail.gasMultiplier);
|
|
427
|
-
push(fields, "baseFee", chainDetail.baseFee);
|
|
428
|
-
push(fields, "priorityFee", chainDetail.priorityFee);
|
|
429
|
-
push(fields, "baseFeeMultiplier", chainDetail.baseFeeMultiplier);
|
|
430
|
-
}
|
|
431
|
-
push(fields, "legacy", legacy);
|
|
432
|
-
return fields;
|
|
433
|
-
}
|
|
434
|
-
|
|
435
257
|
// src/chains/evm/chainIdParse.ts
|
|
436
258
|
function parseEvmChainIdToNumber(chainId) {
|
|
437
259
|
if (chainId == null) return Number.NaN;
|
|
@@ -455,33 +277,66 @@ function parseEvmChainIdToNumber(chainId) {
|
|
|
455
277
|
}
|
|
456
278
|
return Number.parseInt(t, 10);
|
|
457
279
|
}
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
try {
|
|
464
|
-
const u = new URL(t);
|
|
465
|
-
return u.protocol === "http:" || u.protocol === "https:";
|
|
466
|
-
} catch {
|
|
467
|
-
return false;
|
|
280
|
+
function normalizeHumanDecimalAmount(raw, tokenDecimals) {
|
|
281
|
+
const t = raw.trim().replace(/,/g, "");
|
|
282
|
+
if (!t) return "";
|
|
283
|
+
if (!Number.isInteger(tokenDecimals) || tokenDecimals < 0 || tokenDecimals > 18) {
|
|
284
|
+
throw new Error("Invalid token decimals for amount normalization.");
|
|
468
285
|
}
|
|
286
|
+
const wei = viem.parseUnits(t, tokenDecimals);
|
|
287
|
+
return viem.formatUnits(wei, tokenDecimals);
|
|
288
|
+
}
|
|
289
|
+
var normalizeCurveRouterAmountString = normalizeHumanDecimalAmount;
|
|
290
|
+
|
|
291
|
+
// src/chains/evm/coingecko.ts
|
|
292
|
+
var COINGECKO_PLATFORM_BY_CHAIN_ID = {
|
|
293
|
+
"1": "ethereum",
|
|
294
|
+
"56": "binance-smart-chain",
|
|
295
|
+
"137": "polygon-pos",
|
|
296
|
+
"42161": "arbitrum-one",
|
|
297
|
+
"10": "optimistic-ethereum",
|
|
298
|
+
"43114": "avalanche",
|
|
299
|
+
"8453": "base",
|
|
300
|
+
"324": "zk-sync-era",
|
|
301
|
+
"42220": "celo",
|
|
302
|
+
"250": "fantom",
|
|
303
|
+
"100": "gnosis",
|
|
304
|
+
"204": "op-bnb",
|
|
305
|
+
"534352": "scroll",
|
|
306
|
+
"5000": "mantle",
|
|
307
|
+
"169": "manta-pacific",
|
|
308
|
+
"1116": "core",
|
|
309
|
+
"30": "rootstock",
|
|
310
|
+
"288": "boba",
|
|
311
|
+
"1088": "metis-andromeda",
|
|
312
|
+
"34443": "mode",
|
|
313
|
+
"80084": "berachain",
|
|
314
|
+
"146": "sonic",
|
|
315
|
+
"60808": "bob-network",
|
|
316
|
+
"80094": "berachain",
|
|
317
|
+
"130": "unichain",
|
|
318
|
+
"57073": "ink",
|
|
319
|
+
"999": "hyperevm",
|
|
320
|
+
"239": "tac",
|
|
321
|
+
"9745": "plasma",
|
|
322
|
+
"1923": "swellchain",
|
|
323
|
+
"59144": "linea",
|
|
324
|
+
"81457": "blast",
|
|
325
|
+
"7777777": "zora"
|
|
326
|
+
};
|
|
327
|
+
function coingeckoPlatformForChainId(chainId) {
|
|
328
|
+
return COINGECKO_PLATFORM_BY_CHAIN_ID[String(chainId).trim()];
|
|
469
329
|
}
|
|
470
330
|
|
|
471
|
-
exports.
|
|
331
|
+
exports.COINGECKO_PLATFORM_BY_CHAIN_ID = COINGECKO_PLATFORM_BY_CHAIN_ID;
|
|
472
332
|
exports.buildEvmMultisignBatch = buildEvmMultisignBatch;
|
|
473
|
-
exports.
|
|
474
|
-
exports.composeFeePayloadToTxParams = composeFeePayloadToTxParams;
|
|
333
|
+
exports.coingeckoPlatformForChainId = coingeckoPlatformForChainId;
|
|
475
334
|
exports.evmChainCategoryModule = evmChainCategoryModule;
|
|
476
|
-
exports.fetchChainFeeParams = fetchChainFeeParams;
|
|
477
|
-
exports.gasLimitFromEstimateAndChainConfig = gasLimitFromEstimateAndChainConfig;
|
|
478
|
-
exports.gweiToDecimalString = gweiToDecimalString;
|
|
479
335
|
exports.isEvmNativeToken = isEvmNativeToken;
|
|
480
|
-
exports.isValidRpcUrl = isValidRpcUrl;
|
|
481
336
|
exports.matchEvmTokenKind = matchEvmTokenKind;
|
|
337
|
+
exports.normalizeCurveRouterAmountString = normalizeCurveRouterAmountString;
|
|
338
|
+
exports.normalizeHumanDecimalAmount = normalizeHumanDecimalAmount;
|
|
482
339
|
exports.parseEvmChainIdToNumber = parseEvmChainIdToNumber;
|
|
483
|
-
exports.proposalTxParamsToFeeSnapshot = proposalTxParamsToFeeSnapshot;
|
|
484
340
|
exports.routerSwapGasLimitFromEstimate = routerSwapGasLimitFromEstimate;
|
|
485
|
-
exports.triggerTxParamsFromComposeBody = triggerTxParamsFromComposeBody;
|
|
486
341
|
//# sourceMappingURL=index.cjs.map
|
|
487
342
|
//# sourceMappingURL=index.cjs.map
|