@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
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
import { getAddress, parseAbi, zeroAddress, parseUnits, encodeFunctionData, defineChain, createPublicClient, http, parseGwei, serializeTransaction, keccak256
|
|
1
|
+
import { getAddress, parseAbi, zeroAddress, parseUnits, encodeFunctionData, defineChain, createPublicClient, http, decodeEventLog, parseGwei, serializeTransaction, keccak256 } from 'viem';
|
|
2
|
+
import { fetchChainFeeParams, gasLimitFromEstimateAndChainConfig, gweiToDecimalString, proposalTxParamsToFeeSnapshot, alignEip1559FeesWithLatestBase, getClientIdFromKeyGenResult } from '@continuumdao/continuum-node-sdk';
|
|
2
3
|
|
|
3
4
|
// src/core/registry.ts
|
|
4
5
|
var modules = [];
|
|
@@ -23,87 +24,234 @@ function isEthereumMainnetChainId(chainIdStr) {
|
|
|
23
24
|
return String(chainIdStr ?? "").trim() === String(LIDO_ETHEREUM_MAINNET_CHAIN_ID);
|
|
24
25
|
}
|
|
25
26
|
|
|
26
|
-
// src/core/
|
|
27
|
-
function
|
|
28
|
-
const
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
27
|
+
// src/core/purpose.ts
|
|
28
|
+
function mergePurposeText(purposeText, purposeSuffix) {
|
|
29
|
+
const t = purposeText.trim();
|
|
30
|
+
const suffix = (purposeSuffix ?? "").trim();
|
|
31
|
+
if (!suffix) return t;
|
|
32
|
+
return t ? `${t}
|
|
33
|
+
|
|
34
|
+
${suffix}` : suffix;
|
|
34
35
|
}
|
|
35
36
|
|
|
36
|
-
// src/
|
|
37
|
-
function
|
|
38
|
-
|
|
39
|
-
|
|
37
|
+
// src/core/envelope.ts
|
|
38
|
+
function finalizeMultisign(input) {
|
|
39
|
+
const { keyGen, destinationChainID, legs } = input;
|
|
40
|
+
if (legs.length === 0) {
|
|
41
|
+
throw new Error("finalizeMultisign requires at least one leg");
|
|
42
|
+
}
|
|
43
|
+
const ph = (keyGen.pubkeyhex ?? "").trim();
|
|
44
|
+
if (!ph) throw new Error("keyGen pubKey (pubkeyhex) is required");
|
|
45
|
+
const keyList = keyGen.keylist ?? [];
|
|
46
|
+
const clientId = getClientIdFromKeyGenResult(keyGen);
|
|
47
|
+
const first = legs[0];
|
|
48
|
+
const messageHashes = legs.map((l) => l.msgHash);
|
|
49
|
+
const messageRawBatch = legs.map((l) => l.msgRaw);
|
|
50
|
+
const batchMeta = legs.map((l) => ({
|
|
51
|
+
destinationAddress: l.destinationAddress,
|
|
52
|
+
signatureText: l.signatureText,
|
|
53
|
+
...l.audit
|
|
54
|
+
}));
|
|
55
|
+
const proposalTxParams = legs.map((l) => l.proposalTxParams).filter((p) => p != null && typeof p === "object");
|
|
56
|
+
const extraPayload = {
|
|
57
|
+
batchMeta,
|
|
58
|
+
...input.extraJSON ?? {}
|
|
59
|
+
};
|
|
60
|
+
const extraJSON = JSON.stringify(extraPayload);
|
|
61
|
+
const bodyForSign = {
|
|
62
|
+
keyList,
|
|
63
|
+
pubKey: ph,
|
|
64
|
+
msgHash: messageHashes[0],
|
|
65
|
+
msgRaw: first.msgRaw,
|
|
66
|
+
destinationChainID,
|
|
67
|
+
destinationAddress: input.destinationAddress ?? first.destinationAddress,
|
|
68
|
+
extraJSON,
|
|
69
|
+
signatureText: first.signatureText,
|
|
70
|
+
purpose: mergePurposeText(input.purposeText, input.purposeSuffix),
|
|
71
|
+
...first.feeSnapshot
|
|
72
|
+
};
|
|
73
|
+
if (legs.length > 1) {
|
|
74
|
+
bodyForSign.messageHashes = messageHashes;
|
|
75
|
+
bodyForSign.messageRawBatch = messageRawBatch;
|
|
76
|
+
}
|
|
77
|
+
if (proposalTxParams.length > 0) {
|
|
78
|
+
bodyForSign.proposalTxParams = proposalTxParams;
|
|
40
79
|
}
|
|
41
|
-
const
|
|
42
|
-
|
|
80
|
+
const valueWei = first.valueWei;
|
|
81
|
+
if (valueWei != null && valueWei > 0n) {
|
|
82
|
+
bodyForSign.value = valueWei.toString();
|
|
83
|
+
}
|
|
84
|
+
if (clientId) bodyForSign.clientId = clientId;
|
|
85
|
+
return { bodyForSign, messageToSign: JSON.stringify(bodyForSign) };
|
|
43
86
|
}
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
87
|
+
function routerSwapGasLimitFromEstimate(estimatedGas, chainGasLimit) {
|
|
88
|
+
if (chainGasLimit != null && Number.isFinite(chainGasLimit) && chainGasLimit > 0) {
|
|
89
|
+
return gasLimitFromEstimateAndChainConfig(estimatedGas, chainGasLimit);
|
|
90
|
+
}
|
|
91
|
+
return (estimatedGas * 12n + 9n) / 10n;
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
// src/chains/evm/buildBatch.ts
|
|
95
|
+
async function buildEvmMultisignBatch(args) {
|
|
96
|
+
const { context, steps } = args;
|
|
97
|
+
const {
|
|
98
|
+
chainId,
|
|
99
|
+
rpcUrl,
|
|
100
|
+
executorAddress,
|
|
101
|
+
chainDetail,
|
|
102
|
+
useCustomGas,
|
|
103
|
+
customGasChainDetails,
|
|
104
|
+
keyGen,
|
|
105
|
+
purposeText
|
|
106
|
+
} = context;
|
|
107
|
+
if (steps.length === 0) throw new Error("buildEvmMultisignBatch requires at least one step");
|
|
108
|
+
const ch = defineChain({
|
|
109
|
+
id: chainId,
|
|
110
|
+
name: "Destination",
|
|
52
111
|
nativeCurrency: { decimals: 18, name: "Ether", symbol: "ETH" },
|
|
53
|
-
rpcUrls: { default: { http: [
|
|
112
|
+
rpcUrls: { default: { http: [rpcUrl] } }
|
|
54
113
|
});
|
|
55
|
-
const publicClient = createPublicClient({
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
});
|
|
59
|
-
const
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
114
|
+
const publicClient = createPublicClient({ chain: ch, transport: http(rpcUrl) });
|
|
115
|
+
const feeParams = await fetchChainFeeParams(rpcUrl, chainId);
|
|
116
|
+
const legacy = Boolean(chainDetail?.legacy) || !feeParams.isEip1559;
|
|
117
|
+
const latestBaseFeeWei = !legacy ? (await publicClient.getBlock({ blockTag: "latest" })).baseFeePerGas ?? 0n : 0n;
|
|
118
|
+
const gasLimitConfig = useCustomGas && chainDetail?.gasLimit != null ? Number(chainDetail.gasLimit) : void 0;
|
|
119
|
+
const chainGasLimitRouter = chainDetail?.gasLimit != null && Number.isFinite(Number(chainDetail.gasLimit)) && Number(chainDetail.gasLimit) > 0 ? Number(chainDetail.gasLimit) : void 0;
|
|
120
|
+
const gasFeeMultiplier = useCustomGas && chainDetail?.gasMultiplier != null ? Number(chainDetail.gasMultiplier) : void 0;
|
|
121
|
+
const executor = getAddress(executorAddress);
|
|
122
|
+
const baseNonce = await publicClient.getTransactionCount({ address: executor, blockTag: "pending" });
|
|
123
|
+
const legs = [];
|
|
124
|
+
for (let i = 0; i < steps.length; i++) {
|
|
125
|
+
const step = steps[i];
|
|
126
|
+
const currentNonce = baseNonce + i;
|
|
127
|
+
let estimatedGas;
|
|
128
|
+
if (args.estimateGasForStep) {
|
|
129
|
+
estimatedGas = await args.estimateGasForStep({ step, index: i, publicClient, executor });
|
|
130
|
+
} else {
|
|
131
|
+
try {
|
|
132
|
+
estimatedGas = await publicClient.estimateGas({
|
|
133
|
+
to: step.to,
|
|
134
|
+
data: step.data,
|
|
135
|
+
value: step.value,
|
|
136
|
+
account: executor
|
|
137
|
+
});
|
|
138
|
+
} catch {
|
|
139
|
+
estimatedGas = step.fallbackGas ?? 100000n;
|
|
140
|
+
}
|
|
69
141
|
}
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
}
|
|
142
|
+
let gasLimitI;
|
|
143
|
+
if (args.resolveGasLimit) {
|
|
144
|
+
gasLimitI = await args.resolveGasLimit({ step, index: i, estimatedGas, publicClient });
|
|
145
|
+
} else if (step.routerSwap) {
|
|
146
|
+
gasLimitI = routerSwapGasLimitFromEstimate(estimatedGas, chainGasLimitRouter);
|
|
147
|
+
} else {
|
|
148
|
+
gasLimitI = useCustomGas ? gasLimitFromEstimateAndChainConfig(estimatedGas, gasLimitConfig) : estimatedGas;
|
|
76
149
|
}
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
150
|
+
let proposalTxParams;
|
|
151
|
+
let feeSnapshot;
|
|
152
|
+
let serialized;
|
|
153
|
+
if (legacy) {
|
|
154
|
+
let gasPriceWei = await publicClient.getGasPrice();
|
|
155
|
+
if (useCustomGas && gasFeeMultiplier != null && gasFeeMultiplier > 0) {
|
|
156
|
+
gasPriceWei = gasPriceWei * BigInt(100 + gasFeeMultiplier) / 100n;
|
|
157
|
+
}
|
|
158
|
+
if (useCustomGas && chainDetail?.gasPrice != null && chainDetail.gasPrice > 0) {
|
|
159
|
+
const configured = parseGwei(gweiToDecimalString(Number(chainDetail.gasPrice)));
|
|
160
|
+
if (configured > gasPriceWei) gasPriceWei = configured;
|
|
161
|
+
}
|
|
162
|
+
serialized = serializeTransaction({
|
|
163
|
+
type: "legacy",
|
|
164
|
+
to: step.to,
|
|
165
|
+
data: step.data,
|
|
166
|
+
value: step.value,
|
|
167
|
+
gas: gasLimitI,
|
|
168
|
+
gasPrice: gasPriceWei,
|
|
169
|
+
nonce: currentNonce,
|
|
170
|
+
chainId
|
|
171
|
+
});
|
|
172
|
+
proposalTxParams = {
|
|
173
|
+
nonce: currentNonce,
|
|
174
|
+
gasLimit: gasLimitI.toString(),
|
|
175
|
+
txType: "legacy",
|
|
176
|
+
gasPrice: gasPriceWei.toString()
|
|
177
|
+
};
|
|
178
|
+
feeSnapshot = proposalTxParamsToFeeSnapshot(proposalTxParams);
|
|
179
|
+
} else {
|
|
180
|
+
const fetchedBase = feeParams.baseFeeGwei ?? 0;
|
|
181
|
+
const fetchedPriority = feeParams.priorityFeeGwei ?? 0;
|
|
182
|
+
const configuredBase = useCustomGas && chainDetail?.baseFee != null ? Number(chainDetail.baseFee) : 0;
|
|
183
|
+
const configuredPriority = useCustomGas && chainDetail?.priorityFee != null ? Number(chainDetail.priorityFee) : 0;
|
|
184
|
+
const effectiveBaseFeeGwei = Math.max(fetchedBase, configuredBase);
|
|
185
|
+
const effectivePriorityFeeGwei = Math.max(fetchedPriority, configuredPriority);
|
|
186
|
+
const baseFeeMultiplierPct = useCustomGas && chainDetail?.baseFeeMultiplier != null ? Math.max(100, Number(chainDetail.baseFeeMultiplier)) : 100;
|
|
187
|
+
const baseComponentGwei = effectiveBaseFeeGwei * baseFeeMultiplierPct / 100;
|
|
188
|
+
const maxFeePerGasGwei = baseComponentGwei + effectivePriorityFeeGwei;
|
|
189
|
+
let maxPriorityFeePerGas = effectivePriorityFeeGwei > 0 ? parseGwei(gweiToDecimalString(effectivePriorityFeeGwei)) : parseGwei("1");
|
|
190
|
+
let maxFeePerGas = parseGwei(gweiToDecimalString(maxFeePerGasGwei));
|
|
191
|
+
if (useCustomGas && gasFeeMultiplier != null && gasFeeMultiplier > 0) {
|
|
192
|
+
maxPriorityFeePerGas = maxPriorityFeePerGas * BigInt(100 + gasFeeMultiplier) / 100n;
|
|
193
|
+
maxFeePerGas = maxFeePerGas * BigInt(100 + gasFeeMultiplier) / 100n;
|
|
194
|
+
}
|
|
195
|
+
({ maxFeePerGas, maxPriorityFeePerGas } = alignEip1559FeesWithLatestBase(
|
|
196
|
+
maxFeePerGas,
|
|
197
|
+
maxPriorityFeePerGas,
|
|
198
|
+
latestBaseFeeWei
|
|
199
|
+
));
|
|
200
|
+
serialized = serializeTransaction({
|
|
201
|
+
type: "eip1559",
|
|
202
|
+
to: step.to,
|
|
203
|
+
data: step.data,
|
|
204
|
+
value: step.value,
|
|
205
|
+
gas: gasLimitI,
|
|
206
|
+
maxFeePerGas,
|
|
207
|
+
maxPriorityFeePerGas,
|
|
208
|
+
nonce: currentNonce,
|
|
209
|
+
chainId
|
|
210
|
+
});
|
|
211
|
+
proposalTxParams = {
|
|
212
|
+
nonce: currentNonce,
|
|
213
|
+
gasLimit: gasLimitI.toString(),
|
|
214
|
+
txType: "eip1559",
|
|
215
|
+
maxFeePerGas: maxFeePerGas.toString(),
|
|
216
|
+
maxPriorityFeePerGas: maxPriorityFeePerGas.toString()
|
|
217
|
+
};
|
|
218
|
+
feeSnapshot = i === 0 ? proposalTxParamsToFeeSnapshot(proposalTxParams) : {};
|
|
219
|
+
}
|
|
220
|
+
const h = keccak256(serialized);
|
|
221
|
+
const msgHash = h.startsWith("0x") ? h.slice(2) : h;
|
|
222
|
+
const batchMetaExtra = args.buildBatchMeta({ step, index: i, gasLimit: gasLimitI });
|
|
223
|
+
legs.push({
|
|
224
|
+
msgHash,
|
|
225
|
+
msgRaw: i === 0 && args.firstMsgRawNo0x != null ? args.firstMsgRawNo0x : serialized,
|
|
226
|
+
destinationAddress: step.to,
|
|
227
|
+
signatureText: typeof batchMetaExtra.signatureText === "string" ? batchMetaExtra.signatureText : JSON.stringify(batchMetaExtra.signatureText ?? {}),
|
|
228
|
+
audit: batchMetaExtra,
|
|
229
|
+
feeSnapshot: i === 0 ? feeSnapshot : {},
|
|
230
|
+
proposalTxParams,
|
|
231
|
+
valueWei: i === 0 ? step.value : void 0
|
|
232
|
+
});
|
|
233
|
+
if (i === 0 && args.firstMsgRawNo0x != null) {
|
|
234
|
+
legs[0].msgRaw = args.firstMsgRawNo0x;
|
|
91
235
|
}
|
|
92
236
|
}
|
|
93
|
-
}
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
let maxF = maxFeePerGas;
|
|
97
|
-
if (baseWei > 0n && maxF < baseWei + maxP) {
|
|
98
|
-
maxF = baseWei + maxP + parseGwei("0.001");
|
|
237
|
+
const extraJSON = {};
|
|
238
|
+
if (useCustomGas && customGasChainDetails && Object.keys(customGasChainDetails).length > 0) {
|
|
239
|
+
extraJSON.customGasChainDetails = customGasChainDetails;
|
|
99
240
|
}
|
|
100
|
-
|
|
101
|
-
|
|
241
|
+
const result = finalizeMultisign({
|
|
242
|
+
keyGen,
|
|
243
|
+
purposeText,
|
|
244
|
+
purposeSuffix: args.purposeSuffix,
|
|
245
|
+
destinationChainID: String(chainId),
|
|
246
|
+
destinationAddress: args.destinationAddress ?? steps[0].to,
|
|
247
|
+
legs,
|
|
248
|
+
extraJSON: Object.keys(extraJSON).length > 0 ? extraJSON : void 0
|
|
249
|
+
});
|
|
250
|
+
const pv = args.payableValueWei;
|
|
251
|
+
if (pv != null && pv > 0n) {
|
|
252
|
+
result.bodyForSign.value = pv.toString();
|
|
102
253
|
}
|
|
103
|
-
return
|
|
104
|
-
}
|
|
105
|
-
function alignEip1559FeesWithLatestBase(maxFeePerGas, maxPriorityFeePerGas, latestBlockBaseFeeWei) {
|
|
106
|
-
return finalizeEip1559Fees(maxFeePerGas, maxPriorityFeePerGas, null, latestBlockBaseFeeWei);
|
|
254
|
+
return result;
|
|
107
255
|
}
|
|
108
256
|
|
|
109
257
|
// src/protocols/evm/lido/multisign.ts
|
|
@@ -132,13 +280,6 @@ var wstethAbi = parseAbi([
|
|
|
132
280
|
"function wrap(uint256 stETHAmount) returns (uint256)",
|
|
133
281
|
"function unwrap(uint256 wstETHAmount) returns (uint256)"
|
|
134
282
|
]);
|
|
135
|
-
function gweiToDecimalString(n) {
|
|
136
|
-
if (!Number.isFinite(n)) return "0";
|
|
137
|
-
if (n === 0) return "0";
|
|
138
|
-
const s = String(n);
|
|
139
|
-
if (s.indexOf("e") !== -1 || s.indexOf("E") !== -1) return n.toFixed(9).replace(/\.?0+$/, "") || "0";
|
|
140
|
-
return s;
|
|
141
|
-
}
|
|
142
283
|
function parseExtraJsonObject(detail) {
|
|
143
284
|
const raw = detail?.ExtraJSON ?? detail?.extraJSON;
|
|
144
285
|
if (raw == null) return null;
|
|
@@ -226,167 +367,31 @@ function resolveLidoBatchStepGasFromSignRequest(detail, batchIndex) {
|
|
|
226
367
|
return null;
|
|
227
368
|
}
|
|
228
369
|
async function finalizeLidoMultipart(steps, args) {
|
|
229
|
-
const
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
let firstTxFeePayload = {};
|
|
252
|
-
let firstDataNo0x = "";
|
|
253
|
-
const batchMeta = [];
|
|
254
|
-
for (let i = 0; i < steps.length; i++) {
|
|
255
|
-
const s = steps[i];
|
|
256
|
-
const v = getAddress(s.to);
|
|
257
|
-
const data = s.data;
|
|
258
|
-
const currentNonce = baseNonce + i;
|
|
259
|
-
let estimatedGas;
|
|
260
|
-
try {
|
|
261
|
-
estimatedGas = await publicClient.estimateGas({
|
|
262
|
-
to: v,
|
|
263
|
-
data,
|
|
264
|
-
value: s.value,
|
|
265
|
-
account: executor
|
|
266
|
-
});
|
|
267
|
-
} catch {
|
|
268
|
-
estimatedGas = s.fallbackGas;
|
|
269
|
-
}
|
|
270
|
-
const gasLimitI = useCustomGas ? gasLimitFromEstimateAndChainConfig(estimatedGas, gasLimitConfig) : estimatedGas;
|
|
271
|
-
if (legacy) {
|
|
272
|
-
let gasPriceWei = await publicClient.getGasPrice();
|
|
273
|
-
if (useCustomGas && gasFeeMultiplier != null && gasFeeMultiplier > 0) {
|
|
274
|
-
gasPriceWei = gasPriceWei * BigInt(100 + gasFeeMultiplier) / 100n;
|
|
275
|
-
}
|
|
276
|
-
if (useCustomGas && args.chainDetail?.gasPrice != null && args.chainDetail.gasPrice > 0) {
|
|
277
|
-
const configured = parseGwei(gweiToDecimalString(Number(args.chainDetail.gasPrice)));
|
|
278
|
-
if (configured > gasPriceWei) gasPriceWei = configured;
|
|
279
|
-
}
|
|
280
|
-
const ser = serializeTransaction({
|
|
281
|
-
type: "legacy",
|
|
282
|
-
to: v,
|
|
283
|
-
data,
|
|
284
|
-
value: s.value,
|
|
285
|
-
gas: gasLimitI,
|
|
286
|
-
gasPrice: gasPriceWei,
|
|
287
|
-
nonce: currentNonce,
|
|
288
|
-
chainId: LIDO_ETHEREUM_MAINNET_CHAIN_ID
|
|
289
|
-
});
|
|
290
|
-
const h = keccak256(ser);
|
|
291
|
-
messageHashes.push(h.startsWith("0x") ? h.slice(2) : h);
|
|
292
|
-
messageRawBatch.push(ser);
|
|
293
|
-
proposalTxParamsBatch.push({
|
|
294
|
-
nonce: currentNonce,
|
|
295
|
-
gasLimit: gasLimitI.toString(),
|
|
296
|
-
txType: "legacy",
|
|
297
|
-
gasPrice: gasPriceWei.toString()
|
|
298
|
-
});
|
|
299
|
-
if (i === 0) {
|
|
300
|
-
firstTxFeePayload = { txNonce: currentNonce, txGasLimit: gasLimitI.toString(), txGasPrice: gasPriceWei.toString() };
|
|
301
|
-
firstDataNo0x = data.startsWith("0x") ? data.slice(2) : data;
|
|
302
|
-
}
|
|
303
|
-
} else {
|
|
304
|
-
const fetchedBase = feeParams.baseFeeGwei ?? 0;
|
|
305
|
-
const fetchedPriority = feeParams.priorityFeeGwei ?? 0;
|
|
306
|
-
const configuredBase = useCustomGas && args.chainDetail?.baseFee != null ? Number(args.chainDetail.baseFee) : 0;
|
|
307
|
-
const configuredPriority = useCustomGas && args.chainDetail?.priorityFee != null ? Number(args.chainDetail.priorityFee) : 0;
|
|
308
|
-
const effectiveBaseFeeGwei = Math.max(fetchedBase, configuredBase);
|
|
309
|
-
const effectivePriorityFeeGwei = Math.max(fetchedPriority, configuredPriority);
|
|
310
|
-
const baseFeeMultiplierPct = useCustomGas && args.chainDetail?.baseFeeMultiplier != null ? Math.max(100, Number(args.chainDetail.baseFeeMultiplier)) : 100;
|
|
311
|
-
const baseComponentGwei = effectiveBaseFeeGwei * baseFeeMultiplierPct / 100;
|
|
312
|
-
const maxFeePerGasGwei = baseComponentGwei + effectivePriorityFeeGwei;
|
|
313
|
-
let maxPriorityFeePerGas = effectivePriorityFeeGwei > 0 ? parseGwei(gweiToDecimalString(effectivePriorityFeeGwei)) : parseGwei("1");
|
|
314
|
-
let maxFeePerGas = parseGwei(gweiToDecimalString(maxFeePerGasGwei));
|
|
315
|
-
if (useCustomGas && gasFeeMultiplier != null && gasFeeMultiplier > 0) {
|
|
316
|
-
maxPriorityFeePerGas = maxPriorityFeePerGas * BigInt(100 + gasFeeMultiplier) / 100n;
|
|
317
|
-
maxFeePerGas = maxFeePerGas * BigInt(100 + gasFeeMultiplier) / 100n;
|
|
318
|
-
}
|
|
319
|
-
({ maxFeePerGas, maxPriorityFeePerGas } = alignEip1559FeesWithLatestBase(
|
|
320
|
-
maxFeePerGas,
|
|
321
|
-
maxPriorityFeePerGas,
|
|
322
|
-
latestBaseFeeWei
|
|
323
|
-
));
|
|
324
|
-
const ser = serializeTransaction({
|
|
325
|
-
type: "eip1559",
|
|
326
|
-
to: v,
|
|
327
|
-
data,
|
|
328
|
-
value: s.value,
|
|
329
|
-
gas: gasLimitI,
|
|
330
|
-
maxFeePerGas,
|
|
331
|
-
maxPriorityFeePerGas,
|
|
332
|
-
nonce: currentNonce,
|
|
333
|
-
chainId: LIDO_ETHEREUM_MAINNET_CHAIN_ID
|
|
334
|
-
});
|
|
335
|
-
const h = keccak256(ser);
|
|
336
|
-
messageHashes.push(h.startsWith("0x") ? h.slice(2) : h);
|
|
337
|
-
messageRawBatch.push(ser);
|
|
338
|
-
proposalTxParamsBatch.push({
|
|
339
|
-
nonce: currentNonce,
|
|
340
|
-
gasLimit: gasLimitI.toString(),
|
|
341
|
-
txType: "eip1559",
|
|
342
|
-
maxFeePerGas: maxFeePerGas.toString(),
|
|
343
|
-
maxPriorityFeePerGas: maxPriorityFeePerGas.toString()
|
|
344
|
-
});
|
|
345
|
-
if (i === 0) {
|
|
346
|
-
firstTxFeePayload = {
|
|
347
|
-
txNonce: currentNonce,
|
|
348
|
-
txGasLimit: gasLimitI.toString(),
|
|
349
|
-
txMaxFeePerGas: maxFeePerGas.toString(),
|
|
350
|
-
txMaxPriorityFeePerGas: maxPriorityFeePerGas.toString()
|
|
351
|
-
};
|
|
352
|
-
firstDataNo0x = data.startsWith("0x") ? data.slice(2) : data;
|
|
353
|
-
}
|
|
354
|
-
}
|
|
355
|
-
batchMeta.push(s.buildBatchMeta({ gasLimit: gasLimitI }));
|
|
356
|
-
}
|
|
357
|
-
const extraPayload = { batchMeta };
|
|
358
|
-
if (useCustomGas && args.customGasChainDetails && Object.keys(args.customGasChainDetails).length > 0) {
|
|
359
|
-
extraPayload.customGasChainDetails = args.customGasChainDetails;
|
|
360
|
-
}
|
|
361
|
-
const extraJSON = JSON.stringify(extraPayload);
|
|
362
|
-
const firstSigText = batchMeta[0].signatureText;
|
|
363
|
-
const firstValue = steps[0].value;
|
|
364
|
-
const bodyForSign = {
|
|
365
|
-
keyList,
|
|
366
|
-
pubKey: ph,
|
|
367
|
-
msgHash: messageHashes[0],
|
|
368
|
-
msgRaw: firstDataNo0x,
|
|
369
|
-
messageHashes,
|
|
370
|
-
messageRawBatch,
|
|
371
|
-
destinationChainID: String(LIDO_ETHEREUM_MAINNET_CHAIN_ID),
|
|
370
|
+
const evmSteps = steps.map((s) => ({
|
|
371
|
+
to: s.to,
|
|
372
|
+
data: s.data,
|
|
373
|
+
value: s.value,
|
|
374
|
+
fallbackGas: s.fallbackGas
|
|
375
|
+
}));
|
|
376
|
+
const firstDataNo0x = evmSteps[0].data.startsWith("0x") ? evmSteps[0].data.slice(2) : evmSteps[0].data;
|
|
377
|
+
return buildEvmMultisignBatch({
|
|
378
|
+
context: {
|
|
379
|
+
chainCategory: "evm",
|
|
380
|
+
keyGen: args.keyGen,
|
|
381
|
+
purposeText: args.purposeText,
|
|
382
|
+
chainId: LIDO_ETHEREUM_MAINNET_CHAIN_ID,
|
|
383
|
+
rpcUrl: args.rpcUrl.trim(),
|
|
384
|
+
executorAddress: args.executorAddress,
|
|
385
|
+
chainDetail: args.chainDetail,
|
|
386
|
+
useCustomGas: args.useCustomGas,
|
|
387
|
+
customGasChainDetails: args.customGasChainDetails
|
|
388
|
+
},
|
|
389
|
+
steps: evmSteps,
|
|
390
|
+
purposeSuffix: args.purposeSuffix,
|
|
391
|
+
firstMsgRawNo0x: firstDataNo0x,
|
|
372
392
|
destinationAddress: steps[0].to,
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
purpose: (() => {
|
|
376
|
-
const t = args.purposeText.trim();
|
|
377
|
-
const suffix = args.purposeSuffix.trim();
|
|
378
|
-
return (t ? `${t}
|
|
379
|
-
|
|
380
|
-
` : "") + suffix;
|
|
381
|
-
})(),
|
|
382
|
-
...firstTxFeePayload,
|
|
383
|
-
proposalTxParams: proposalTxParamsBatch
|
|
384
|
-
};
|
|
385
|
-
if (firstValue > 0n) {
|
|
386
|
-
bodyForSign.value = firstValue.toString();
|
|
387
|
-
}
|
|
388
|
-
if (clientId) bodyForSign.clientId = clientId;
|
|
389
|
-
return { bodyForSign, messageToSign: JSON.stringify(bodyForSign) };
|
|
393
|
+
buildBatchMeta: ({ index, gasLimit }) => steps[index].buildBatchMeta({ gasLimit })
|
|
394
|
+
});
|
|
390
395
|
}
|
|
391
396
|
async function buildEvmMultisignBodyLidoSubmit(args) {
|
|
392
397
|
if (args.chainId !== LIDO_ETHEREUM_MAINNET_CHAIN_ID) {
|
|
@@ -782,6 +787,111 @@ function isLidoEvmSignRequestForEstimateWorkaround(detail, batchIndex) {
|
|
|
782
787
|
return isLidoBatchStepEvmSignRequest(detail, batchIndex ?? 0);
|
|
783
788
|
}
|
|
784
789
|
|
|
790
|
+
// src/protocols/evm/lido/aprApi.ts
|
|
791
|
+
async function fetchLidoStethAprLastPct() {
|
|
792
|
+
try {
|
|
793
|
+
const res = await fetch("https://eth-api.lido.fi/v1/protocol/steth/apr/last", { cache: "no-store" });
|
|
794
|
+
if (!res.ok) return null;
|
|
795
|
+
const j = await res.json();
|
|
796
|
+
const apr = j?.data?.apr;
|
|
797
|
+
const n = typeof apr === "number" ? apr : typeof apr === "string" ? parseFloat(apr) : NaN;
|
|
798
|
+
return Number.isFinite(n) ? n : null;
|
|
799
|
+
} catch {
|
|
800
|
+
return null;
|
|
801
|
+
}
|
|
802
|
+
}
|
|
803
|
+
|
|
804
|
+
// src/protocols/evm/lido/withdrawalTimeApi.ts
|
|
805
|
+
function formatIsoUtc(i) {
|
|
806
|
+
try {
|
|
807
|
+
const d = new Date(i);
|
|
808
|
+
if (Number.isNaN(d.getTime())) return i;
|
|
809
|
+
return d.toUTCString();
|
|
810
|
+
} catch {
|
|
811
|
+
return i;
|
|
812
|
+
}
|
|
813
|
+
}
|
|
814
|
+
async function fetchLidoWithdrawalFinalizationEta(args) {
|
|
815
|
+
const raw = args.amountHuman.trim().replace(/,/g, "");
|
|
816
|
+
if (!raw || raw === "." || raw === "0") {
|
|
817
|
+
return { ok: false, error: "" };
|
|
818
|
+
}
|
|
819
|
+
const q = encodeURIComponent(raw);
|
|
820
|
+
try {
|
|
821
|
+
const res = await fetch(`https://wq-api.lido.fi/v2/request-time/calculate?amount=${q}`, {
|
|
822
|
+
cache: "no-store"
|
|
823
|
+
});
|
|
824
|
+
if (!res.ok) {
|
|
825
|
+
return { ok: false, error: `Withdrawal ETA API (${res.status})` };
|
|
826
|
+
}
|
|
827
|
+
const j = await res.json();
|
|
828
|
+
const at = j?.requestInfo?.finalizationAt;
|
|
829
|
+
const s = typeof at === "string" && at.trim() ? at.trim() : null;
|
|
830
|
+
if (!s || j.status !== "calculated") {
|
|
831
|
+
return { ok: false, error: "" };
|
|
832
|
+
}
|
|
833
|
+
return {
|
|
834
|
+
ok: true,
|
|
835
|
+
finalizationAtIso: s,
|
|
836
|
+
displayLabel: formatIsoUtc(s)
|
|
837
|
+
};
|
|
838
|
+
} catch (e) {
|
|
839
|
+
return {
|
|
840
|
+
ok: false,
|
|
841
|
+
error: e instanceof Error ? e.message : "ETA unavailable"
|
|
842
|
+
};
|
|
843
|
+
}
|
|
844
|
+
}
|
|
845
|
+
var erc721TransferAbi = parseAbi([
|
|
846
|
+
"event Transfer(address indexed from, address indexed to, uint256 indexed tokenId)"
|
|
847
|
+
]);
|
|
848
|
+
var requestWithdrawalsAbiSlice = parseAbi(["function requestWithdrawals(uint256[] amounts, address owner)"]);
|
|
849
|
+
var _requestWithdrawalsSelectorPrefix = null;
|
|
850
|
+
function requestWithdrawalsCalldataPrefix() {
|
|
851
|
+
if (_requestWithdrawalsSelectorPrefix === null) {
|
|
852
|
+
_requestWithdrawalsSelectorPrefix = encodeFunctionData({
|
|
853
|
+
abi: requestWithdrawalsAbiSlice,
|
|
854
|
+
functionName: "requestWithdrawals",
|
|
855
|
+
args: [[0n], getAddress(zeroAddress)]
|
|
856
|
+
}).slice(0, 10);
|
|
857
|
+
}
|
|
858
|
+
return _requestWithdrawalsSelectorPrefix;
|
|
859
|
+
}
|
|
860
|
+
function calldataStartsWithRequestWithdrawals(dataHex) {
|
|
861
|
+
const raw = typeof dataHex === "string" ? dataHex.trim() : "";
|
|
862
|
+
if (!raw.startsWith("0x") && !raw.startsWith("0X")) return false;
|
|
863
|
+
const head = (raw.startsWith("0x") || raw.startsWith("0X") ? raw.toLowerCase() : `0x${raw}`).toLowerCase();
|
|
864
|
+
return head.startsWith(requestWithdrawalsCalldataPrefix().toLowerCase());
|
|
865
|
+
}
|
|
866
|
+
function withdrawalQueueMintedTokenIdsFromReceipt(receipt, withdrawalQueue = LIDO_WITHDRAWAL_QUEUE_MAINNET) {
|
|
867
|
+
let wqNorm;
|
|
868
|
+
try {
|
|
869
|
+
wqNorm = getAddress(withdrawalQueue).toLowerCase();
|
|
870
|
+
} catch {
|
|
871
|
+
return [];
|
|
872
|
+
}
|
|
873
|
+
const out = [];
|
|
874
|
+
const zeroFrom = zeroAddress.toLowerCase();
|
|
875
|
+
for (const log of receipt.logs) {
|
|
876
|
+
if ((log.address ?? "").toLowerCase() !== wqNorm) continue;
|
|
877
|
+
try {
|
|
878
|
+
const decoded = decodeEventLog({
|
|
879
|
+
abi: erc721TransferAbi,
|
|
880
|
+
data: log.data,
|
|
881
|
+
topics: log.topics
|
|
882
|
+
});
|
|
883
|
+
const args = decoded && typeof decoded === "object" && "args" in decoded ? decoded.args : void 0;
|
|
884
|
+
const from = args?.from?.toLowerCase();
|
|
885
|
+
if (!from || from !== zeroFrom) continue;
|
|
886
|
+
if (typeof args?.tokenId !== "bigint") continue;
|
|
887
|
+
out.push(args.tokenId);
|
|
888
|
+
} catch {
|
|
889
|
+
}
|
|
890
|
+
}
|
|
891
|
+
out.sort((a, b) => a === b ? 0 : a < b ? -1 : 1);
|
|
892
|
+
return out;
|
|
893
|
+
}
|
|
894
|
+
|
|
785
895
|
// src/protocols/evm/lido/index.ts
|
|
786
896
|
var LIDO_PROTOCOL_ID = "lido";
|
|
787
897
|
var lidoProtocolModule = {
|
|
@@ -804,6 +914,6 @@ var lidoProtocolModule = {
|
|
|
804
914
|
};
|
|
805
915
|
registerProtocolModule(lidoProtocolModule);
|
|
806
916
|
|
|
807
|
-
export { LIDO_CLAIM_WITHDRAWAL_FALLBACK_GAS_UNITS, LIDO_ETHEREUM_MAINNET_CHAIN_ID, LIDO_EVM_TYPES, LIDO_PROTOCOL_ID, LIDO_REQUEST_WITHDRAWALS_FALLBACK_GAS_UNITS, LIDO_STETH_CONTRACT_MAINNET, LIDO_SUBMIT_FALLBACK_GAS_UNITS, LIDO_SUBMIT_REFERRAL_MAINNET, LIDO_WITHDRAWAL_QUEUE_MAINNET, LIDO_WSTETH_CONTRACT_MAINNET, LIDO_WSTETH_UNWRAP_FALLBACK_GAS_UNITS, LIDO_WSTETH_WRAP_FALLBACK_GAS_UNITS, MIN_LIDO_EXECUTE_GAS, buildEvmMultisignBodyLidoClaimWithdrawal, buildEvmMultisignBodyLidoRequestWithdrawals, buildEvmMultisignBodyLidoSubmit, buildEvmMultisignBodyLidoUnwrapWstEth, buildEvmMultisignBodyLidoWrapStEth, isEthereumMainnetChainId, isLidoBatchStepEvmSignRequest, isLidoEvmSignRequestForEstimateWorkaround, lidoProtocolModule, lidoRequestWithdrawalsBatchIndices, resolveLidoBatchStepGasFromSignRequest };
|
|
917
|
+
export { LIDO_CLAIM_WITHDRAWAL_FALLBACK_GAS_UNITS, LIDO_ETHEREUM_MAINNET_CHAIN_ID, LIDO_EVM_TYPES, LIDO_PROTOCOL_ID, LIDO_REQUEST_WITHDRAWALS_FALLBACK_GAS_UNITS, LIDO_STETH_CONTRACT_MAINNET, LIDO_SUBMIT_FALLBACK_GAS_UNITS, LIDO_SUBMIT_REFERRAL_MAINNET, LIDO_WITHDRAWAL_QUEUE_MAINNET, LIDO_WSTETH_CONTRACT_MAINNET, LIDO_WSTETH_UNWRAP_FALLBACK_GAS_UNITS, LIDO_WSTETH_WRAP_FALLBACK_GAS_UNITS, MIN_LIDO_EXECUTE_GAS, buildEvmMultisignBodyLidoClaimWithdrawal, buildEvmMultisignBodyLidoRequestWithdrawals, buildEvmMultisignBodyLidoSubmit, buildEvmMultisignBodyLidoUnwrapWstEth, buildEvmMultisignBodyLidoWrapStEth, calldataStartsWithRequestWithdrawals, fetchLidoStethAprLastPct, fetchLidoWithdrawalFinalizationEta, isEthereumMainnetChainId, isLidoBatchStepEvmSignRequest, isLidoEvmSignRequestForEstimateWorkaround, lidoProtocolModule, lidoRequestWithdrawalsBatchIndices, requestWithdrawalsCalldataPrefix, resolveLidoBatchStepGasFromSignRequest, withdrawalQueueMintedTokenIdsFromReceipt };
|
|
808
918
|
//# sourceMappingURL=index.js.map
|
|
809
919
|
//# sourceMappingURL=index.js.map
|