@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 { parseAbi, getAddress, parseUnits, encodeFunctionData,
|
|
1
|
+
import { parseAbi, getAddress, parseUnits, encodeFunctionData, defineChain, createPublicClient, http, stringToBytes, toHex, 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 isMapleSyrupSupportedChain(chainId) {
|
|
|
23
24
|
return chainId === 1 || chainId === 11155111;
|
|
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;
|
|
79
|
+
}
|
|
80
|
+
const valueWei = first.valueWei;
|
|
81
|
+
if (valueWei != null && valueWei > 0n) {
|
|
82
|
+
bodyForSign.value = valueWei.toString();
|
|
40
83
|
}
|
|
41
|
-
|
|
42
|
-
return
|
|
84
|
+
if (clientId) bodyForSign.clientId = clientId;
|
|
85
|
+
return { bodyForSign, messageToSign: JSON.stringify(bodyForSign) };
|
|
86
|
+
}
|
|
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;
|
|
43
92
|
}
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
const
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
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: [
|
|
54
|
-
});
|
|
55
|
-
const publicClient = createPublicClient({
|
|
56
|
-
chain,
|
|
57
|
-
transport: http(url)
|
|
112
|
+
rpcUrls: { default: { http: [rpcUrl] } }
|
|
58
113
|
});
|
|
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/maple/multisign.ts
|
|
@@ -126,13 +274,6 @@ var poolV2ExitAbi = parseAbi([
|
|
|
126
274
|
"function requestRedeem(uint256 shares, address receiver) returns (uint256)",
|
|
127
275
|
"function decimals() view returns (uint8)"
|
|
128
276
|
]);
|
|
129
|
-
function gweiToDecimalString(n) {
|
|
130
|
-
if (!Number.isFinite(n)) return "0";
|
|
131
|
-
if (n === 0) return "0";
|
|
132
|
-
const s = String(n);
|
|
133
|
-
if (s.indexOf("e") !== -1 || s.indexOf("E") !== -1) return n.toFixed(9).replace(/\.?0+$/, "") || "0";
|
|
134
|
-
return s;
|
|
135
|
-
}
|
|
136
277
|
function formatBytes32DataLabel(s) {
|
|
137
278
|
const b = stringToBytes(s);
|
|
138
279
|
if (b.length > 32) throw new Error("Maple depositData label is too long for bytes32.");
|
|
@@ -222,10 +363,6 @@ async function buildEvmMultisignBodyMapleSyrupDeposit(args) {
|
|
|
222
363
|
if (args.chainId !== 1 && args.chainId !== 11155111) {
|
|
223
364
|
throw new Error("Maple Syrup deposit is only supported on Ethereum mainnet or Sepolia.");
|
|
224
365
|
}
|
|
225
|
-
const ph = (args.keyGen.pubkeyhex ?? "").trim();
|
|
226
|
-
if (!ph) throw new Error("keyGen pubKey (pubkeyhex) is required");
|
|
227
|
-
const keyList = args.keyGen.keylist ?? [];
|
|
228
|
-
const clientId = firstClientIdFromKeyGen(args.keyGen);
|
|
229
366
|
const asset = getAddress(args.asset);
|
|
230
367
|
const router = getAddress(args.syrupRouter);
|
|
231
368
|
const pool = getAddress(args.pool);
|
|
@@ -281,33 +418,44 @@ async function buildEvmMultisignBodyMapleSyrupDeposit(args) {
|
|
|
281
418
|
});
|
|
282
419
|
steps.push({ kind: "deposit", to: router, data: depositCalldata, value: 0n });
|
|
283
420
|
}
|
|
284
|
-
const
|
|
285
|
-
const
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
const
|
|
292
|
-
const
|
|
293
|
-
const
|
|
294
|
-
const
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
421
|
+
const chainIdStr = String(args.chainId);
|
|
422
|
+
const evmSteps = steps.map((s) => ({
|
|
423
|
+
to: s.to,
|
|
424
|
+
data: s.data,
|
|
425
|
+
value: s.value,
|
|
426
|
+
fallbackGas: s.kind === "approve" ? AAVE_ERC20_APPROVE_FALLBACK : MAPLE_SYRUP_DEPOSIT_FALLBACK
|
|
427
|
+
}));
|
|
428
|
+
const n = steps.length;
|
|
429
|
+
const finalVerb = stakeMethod === "authorizeAndDeposit" ? "authorizeAndDeposit (permission + deposit)" : "deposit";
|
|
430
|
+
const purposeSuffix = n === 1 ? `Maple Syrup: 1-tx \u2014 ${finalVerb} via SyrupRouter (allowance already set).` : `Maple Syrup: ${n}-tx batch \u2014 approve asset for SyrupRouter, then ${finalVerb}.`;
|
|
431
|
+
const firstDataNo0x = evmSteps[0].data.startsWith("0x") ? evmSteps[0].data.slice(2) : evmSteps[0].data;
|
|
432
|
+
return buildEvmMultisignBatch({
|
|
433
|
+
context: {
|
|
434
|
+
chainCategory: "evm",
|
|
435
|
+
keyGen: args.keyGen,
|
|
436
|
+
purposeText: args.purposeText,
|
|
437
|
+
chainId: args.chainId,
|
|
438
|
+
rpcUrl: args.rpcUrl,
|
|
439
|
+
executorAddress: executor,
|
|
440
|
+
chainDetail: args.chainDetail,
|
|
441
|
+
useCustomGas: args.useCustomGas,
|
|
442
|
+
customGasChainDetails: args.customGasChainDetails
|
|
443
|
+
},
|
|
444
|
+
steps: evmSteps,
|
|
445
|
+
purposeSuffix,
|
|
446
|
+
firstMsgRawNo0x: firstDataNo0x,
|
|
447
|
+
destinationAddress: steps[0].to,
|
|
448
|
+
estimateGasForStep: async ({ step, index, publicClient: publicClient2, executor: exec }) => {
|
|
449
|
+
const s = steps[index];
|
|
450
|
+
if ((s.kind === "deposit" || s.kind === "authorizeAndDeposit") && index > 0) {
|
|
451
|
+
return MAPLE_SYRUP_DEPOSIT_FALLBACK;
|
|
452
|
+
}
|
|
305
453
|
try {
|
|
306
|
-
|
|
307
|
-
to:
|
|
308
|
-
data:
|
|
309
|
-
value:
|
|
310
|
-
account:
|
|
454
|
+
return await publicClient2.estimateGas({
|
|
455
|
+
to: step.to,
|
|
456
|
+
data: step.data,
|
|
457
|
+
value: step.value,
|
|
458
|
+
account: exec
|
|
311
459
|
});
|
|
312
460
|
} catch (e) {
|
|
313
461
|
if (s.kind === "deposit" || s.kind === "authorizeAndDeposit") {
|
|
@@ -318,129 +466,43 @@ async function buildEvmMultisignBodyMapleSyrupDeposit(args) {
|
|
|
318
466
|
);
|
|
319
467
|
}
|
|
320
468
|
}
|
|
321
|
-
|
|
322
|
-
}
|
|
323
|
-
}
|
|
324
|
-
const gasLimitI = useCustomGas ? gasLimitFromEstimateAndChainConfig(estimatedGas, gasLimitConfig) : estimatedGas;
|
|
325
|
-
if (legacy) {
|
|
326
|
-
let gasPriceWei = await publicClient.getGasPrice();
|
|
327
|
-
if (useCustomGas && gasFeeMultiplier != null && gasFeeMultiplier > 0) {
|
|
328
|
-
gasPriceWei = gasPriceWei * BigInt(100 + gasFeeMultiplier) / 100n;
|
|
329
|
-
}
|
|
330
|
-
if (useCustomGas && args.chainDetail?.gasPrice != null && args.chainDetail.gasPrice > 0) {
|
|
331
|
-
const configured = parseGwei(gweiToDecimalString(Number(args.chainDetail.gasPrice)));
|
|
332
|
-
if (configured > gasPriceWei) gasPriceWei = configured;
|
|
333
|
-
}
|
|
334
|
-
const ser = serializeTransaction({
|
|
335
|
-
type: "legacy",
|
|
336
|
-
to: s.to,
|
|
337
|
-
data: s.data,
|
|
338
|
-
value: s.value,
|
|
339
|
-
gas: gasLimitI,
|
|
340
|
-
gasPrice: gasPriceWei,
|
|
341
|
-
nonce: currentNonce,
|
|
342
|
-
chainId: args.chainId
|
|
343
|
-
});
|
|
344
|
-
const h = keccak256(ser);
|
|
345
|
-
messageHashes.push(h.startsWith("0x") ? h.slice(2) : h);
|
|
346
|
-
messageRawBatch.push(ser);
|
|
347
|
-
proposalTxParamsBatch.push({
|
|
348
|
-
nonce: currentNonce,
|
|
349
|
-
gasLimit: gasLimitI.toString(),
|
|
350
|
-
txType: "legacy",
|
|
351
|
-
gasPrice: gasPriceWei.toString()
|
|
352
|
-
});
|
|
353
|
-
if (i === 0) {
|
|
354
|
-
firstTxFeePayload = { txNonce: currentNonce, txGasLimit: gasLimitI.toString(), txGasPrice: gasPriceWei.toString() };
|
|
355
|
-
firstDataNo0x = s.data.startsWith("0x") ? s.data.slice(2) : s.data;
|
|
469
|
+
return s.kind === "approve" ? AAVE_ERC20_APPROVE_FALLBACK : MAPLE_SYRUP_DEPOSIT_FALLBACK;
|
|
356
470
|
}
|
|
357
|
-
}
|
|
358
|
-
|
|
359
|
-
const
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
471
|
+
},
|
|
472
|
+
buildBatchMeta: ({ index, gasLimit }) => {
|
|
473
|
+
const s = steps[index];
|
|
474
|
+
if (s.kind === "approve") {
|
|
475
|
+
return {
|
|
476
|
+
signatureText: JSON.stringify({
|
|
477
|
+
kind: "MapleSyrup",
|
|
478
|
+
name: "ERC20.approve",
|
|
479
|
+
note: "Allow SyrupRouter to pull this deposit amount.",
|
|
480
|
+
spender: router,
|
|
481
|
+
asset,
|
|
482
|
+
pool,
|
|
483
|
+
amountHuman: args.amountHuman
|
|
484
|
+
}),
|
|
485
|
+
evm: { type: "maple_syrup_erc20_approve", version: 1, chainId: chainIdStr },
|
|
486
|
+
maple: { step: "approve_asset", router, pool, asset }
|
|
487
|
+
};
|
|
372
488
|
}
|
|
373
|
-
(
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
nonce: currentNonce,
|
|
387
|
-
chainId: args.chainId
|
|
388
|
-
});
|
|
389
|
-
const h = keccak256(ser);
|
|
390
|
-
messageHashes.push(h.startsWith("0x") ? h.slice(2) : h);
|
|
391
|
-
messageRawBatch.push(ser);
|
|
392
|
-
proposalTxParamsBatch.push({
|
|
393
|
-
nonce: currentNonce,
|
|
394
|
-
gasLimit: gasLimitI.toString(),
|
|
395
|
-
txType: "eip1559",
|
|
396
|
-
maxFeePerGas: maxFeePerGas.toString(),
|
|
397
|
-
maxPriorityFeePerGas: maxPriorityFeePerGas.toString()
|
|
398
|
-
});
|
|
399
|
-
if (i === 0) {
|
|
400
|
-
firstTxFeePayload = {
|
|
401
|
-
txNonce: currentNonce,
|
|
402
|
-
txGasLimit: gasLimitI.toString(),
|
|
403
|
-
txMaxFeePerGas: maxFeePerGas.toString(),
|
|
404
|
-
txMaxPriorityFeePerGas: maxPriorityFeePerGas.toString()
|
|
489
|
+
if (s.kind === "deposit") {
|
|
490
|
+
return {
|
|
491
|
+
signatureText: JSON.stringify({
|
|
492
|
+
kind: "MapleSyrup",
|
|
493
|
+
name: "SyrupRouter.deposit",
|
|
494
|
+
function: "deposit(uint256 assets, bytes32 depositData)",
|
|
495
|
+
assets: amountWei.toString(),
|
|
496
|
+
pool,
|
|
497
|
+
router,
|
|
498
|
+
amountHuman: args.amountHuman
|
|
499
|
+
}),
|
|
500
|
+
evm: { type: "maple_syrup_router_deposit", version: 1, chainId: chainIdStr },
|
|
501
|
+
maple: { step: "deposit", router, pool, gasBuildDeposit: { baseGasUnits: gasLimit.toString() } }
|
|
405
502
|
};
|
|
406
|
-
firstDataNo0x = s.data.startsWith("0x") ? s.data.slice(2) : s.data;
|
|
407
503
|
}
|
|
408
|
-
}
|
|
409
|
-
const chainIdStr = String(args.chainId);
|
|
410
|
-
if (s.kind === "approve") {
|
|
411
|
-
batchMeta.push({
|
|
412
|
-
destinationAddress: asset,
|
|
413
|
-
signatureText: JSON.stringify({
|
|
414
|
-
kind: "MapleSyrup",
|
|
415
|
-
name: "ERC20.approve",
|
|
416
|
-
note: "Allow SyrupRouter to pull this deposit amount.",
|
|
417
|
-
spender: router,
|
|
418
|
-
asset,
|
|
419
|
-
pool,
|
|
420
|
-
amountHuman: args.amountHuman
|
|
421
|
-
}),
|
|
422
|
-
evm: { type: "maple_syrup_erc20_approve", version: 1, chainId: chainIdStr },
|
|
423
|
-
maple: { step: "approve_asset", router, pool, asset }
|
|
424
|
-
});
|
|
425
|
-
} else if (s.kind === "deposit") {
|
|
426
|
-
batchMeta.push({
|
|
427
|
-
destinationAddress: router,
|
|
428
|
-
signatureText: JSON.stringify({
|
|
429
|
-
kind: "MapleSyrup",
|
|
430
|
-
name: "SyrupRouter.deposit",
|
|
431
|
-
function: "deposit(uint256 assets, bytes32 depositData)",
|
|
432
|
-
assets: amountWei.toString(),
|
|
433
|
-
pool,
|
|
434
|
-
router,
|
|
435
|
-
amountHuman: args.amountHuman
|
|
436
|
-
}),
|
|
437
|
-
evm: { type: "maple_syrup_router_deposit", version: 1, chainId: chainIdStr },
|
|
438
|
-
maple: { step: "deposit", router, pool, gasBuildDeposit: { baseGasUnits: gasLimitI.toString() } }
|
|
439
|
-
});
|
|
440
|
-
} else {
|
|
441
504
|
const a = args.authorizeSig;
|
|
442
|
-
|
|
443
|
-
destinationAddress: router,
|
|
505
|
+
return {
|
|
444
506
|
signatureText: JSON.stringify({
|
|
445
507
|
kind: "MapleSyrup",
|
|
446
508
|
name: "SyrupRouter.authorizeAndDeposit",
|
|
@@ -454,50 +516,15 @@ async function buildEvmMultisignBodyMapleSyrupDeposit(args) {
|
|
|
454
516
|
amountHuman: args.amountHuman
|
|
455
517
|
}),
|
|
456
518
|
evm: { type: "maple_syrup_router_authorize_and_deposit", version: 1, chainId: chainIdStr },
|
|
457
|
-
maple: { step: "authorize_and_deposit", router, pool, gasBuildDeposit: { baseGasUnits:
|
|
458
|
-
}
|
|
519
|
+
maple: { step: "authorize_and_deposit", router, pool, gasBuildDeposit: { baseGasUnits: gasLimit.toString() } }
|
|
520
|
+
};
|
|
459
521
|
}
|
|
460
|
-
}
|
|
461
|
-
const extraPayload = { batchMeta };
|
|
462
|
-
if (useCustomGas && args.customGasChainDetails && Object.keys(args.customGasChainDetails).length > 0) {
|
|
463
|
-
extraPayload.customGasChainDetails = args.customGasChainDetails;
|
|
464
|
-
}
|
|
465
|
-
const extraJSON = JSON.stringify(extraPayload);
|
|
466
|
-
const firstSigText = batchMeta[0].signatureText;
|
|
467
|
-
const n = steps.length;
|
|
468
|
-
const finalVerb = stakeMethod === "authorizeAndDeposit" ? "authorizeAndDeposit (permission + deposit)" : "deposit";
|
|
469
|
-
const purposeSuffix = n === 1 ? `Maple Syrup: 1-tx \u2014 ${finalVerb} via SyrupRouter (allowance already set).` : `Maple Syrup: ${n}-tx batch \u2014 approve asset for SyrupRouter, then ${finalVerb}.`;
|
|
470
|
-
const bodyForSign = {
|
|
471
|
-
keyList,
|
|
472
|
-
pubKey: ph,
|
|
473
|
-
msgHash: messageHashes[0],
|
|
474
|
-
msgRaw: firstDataNo0x,
|
|
475
|
-
messageHashes,
|
|
476
|
-
messageRawBatch,
|
|
477
|
-
destinationChainID: String(args.chainId),
|
|
478
|
-
destinationAddress: steps[0].to,
|
|
479
|
-
extraJSON,
|
|
480
|
-
signatureText: firstSigText,
|
|
481
|
-
purpose: (() => {
|
|
482
|
-
const t = args.purposeText.trim();
|
|
483
|
-
return (t ? `${t}
|
|
484
|
-
|
|
485
|
-
` : "") + purposeSuffix;
|
|
486
|
-
})(),
|
|
487
|
-
...firstTxFeePayload,
|
|
488
|
-
proposalTxParams: proposalTxParamsBatch
|
|
489
|
-
};
|
|
490
|
-
if (clientId) bodyForSign.clientId = clientId;
|
|
491
|
-
return { bodyForSign, messageToSign: JSON.stringify(bodyForSign) };
|
|
522
|
+
});
|
|
492
523
|
}
|
|
493
524
|
async function buildEvmMultisignBodyMaplePoolRequestRedeem(args) {
|
|
494
525
|
if (args.chainId !== 1 && args.chainId !== 11155111) {
|
|
495
526
|
throw new Error("Maple Syrup redeem request is only supported on Ethereum mainnet or Sepolia.");
|
|
496
527
|
}
|
|
497
|
-
const ph = (args.keyGen.pubkeyhex ?? "").trim();
|
|
498
|
-
if (!ph) throw new Error("keyGen pubKey (pubkeyhex) is required");
|
|
499
|
-
const keyList = args.keyGen.keylist ?? [];
|
|
500
|
-
const clientId = firstClientIdFromKeyGen(args.keyGen);
|
|
501
528
|
const pool = getAddress(args.pool);
|
|
502
529
|
const executor = getAddress(args.executorAddress);
|
|
503
530
|
const receiver = executor;
|
|
@@ -518,113 +545,26 @@ async function buildEvmMultisignBodyMaplePoolRequestRedeem(args) {
|
|
|
518
545
|
functionName: "requestRedeem",
|
|
519
546
|
args: [exitShares, receiver]
|
|
520
547
|
});
|
|
521
|
-
const feeParams = await fetchChainFeeParams(args.rpcUrl, args.chainId);
|
|
522
|
-
const legacy = Boolean(args.chainDetail?.legacy) || !feeParams.isEip1559;
|
|
523
|
-
const latestBaseFeeWei = !legacy ? (await publicClient.getBlock({ blockTag: "latest" })).baseFeePerGas ?? 0n : 0n;
|
|
524
|
-
const useCustomGas = args.useCustomGas;
|
|
525
|
-
const gasLimitConfig = useCustomGas && args.chainDetail?.gasLimit != null ? Number(args.chainDetail.gasLimit) : void 0;
|
|
526
|
-
const gasFeeMultiplier = useCustomGas && args.chainDetail?.gasMultiplier != null ? Number(args.chainDetail.gasMultiplier) : void 0;
|
|
527
|
-
const currentNonce = await publicClient.getTransactionCount({ address: executor, blockTag: "pending" });
|
|
528
|
-
let estimatedGas;
|
|
529
|
-
try {
|
|
530
|
-
estimatedGas = await publicClient.estimateGas({
|
|
531
|
-
to: pool,
|
|
532
|
-
data,
|
|
533
|
-
value: 0n,
|
|
534
|
-
account: executor
|
|
535
|
-
});
|
|
536
|
-
} catch {
|
|
537
|
-
estimatedGas = MAPLE_REQUEST_REDEEM_FALLBACK;
|
|
538
|
-
}
|
|
539
|
-
const gasLimitI = useCustomGas ? gasLimitFromEstimateAndChainConfig(estimatedGas, gasLimitConfig) : estimatedGas;
|
|
540
548
|
const chainIdStr = String(args.chainId);
|
|
541
|
-
let firstTxFeePayload = {};
|
|
542
|
-
let ser;
|
|
543
|
-
let proposalTxParams0;
|
|
544
|
-
if (legacy) {
|
|
545
|
-
let gasPriceWei = await publicClient.getGasPrice();
|
|
546
|
-
if (useCustomGas && gasFeeMultiplier != null && gasFeeMultiplier > 0) {
|
|
547
|
-
gasPriceWei = gasPriceWei * BigInt(100 + gasFeeMultiplier) / 100n;
|
|
548
|
-
}
|
|
549
|
-
if (useCustomGas && args.chainDetail?.gasPrice != null && args.chainDetail.gasPrice > 0) {
|
|
550
|
-
const configured = parseGwei(gweiToDecimalString(Number(args.chainDetail.gasPrice)));
|
|
551
|
-
if (configured > gasPriceWei) gasPriceWei = configured;
|
|
552
|
-
}
|
|
553
|
-
ser = serializeTransaction({
|
|
554
|
-
type: "legacy",
|
|
555
|
-
to: pool,
|
|
556
|
-
data,
|
|
557
|
-
value: 0n,
|
|
558
|
-
gas: gasLimitI,
|
|
559
|
-
gasPrice: gasPriceWei,
|
|
560
|
-
nonce: currentNonce,
|
|
561
|
-
chainId: args.chainId
|
|
562
|
-
});
|
|
563
|
-
firstTxFeePayload = {
|
|
564
|
-
txNonce: currentNonce,
|
|
565
|
-
txGasLimit: gasLimitI.toString(),
|
|
566
|
-
txGasPrice: gasPriceWei.toString()
|
|
567
|
-
};
|
|
568
|
-
proposalTxParams0 = {
|
|
569
|
-
nonce: currentNonce,
|
|
570
|
-
gasLimit: gasLimitI.toString(),
|
|
571
|
-
txType: "legacy",
|
|
572
|
-
gasPrice: gasPriceWei.toString()
|
|
573
|
-
};
|
|
574
|
-
} else {
|
|
575
|
-
const fetchedBase = feeParams.baseFeeGwei ?? 0;
|
|
576
|
-
const fetchedPriority = feeParams.priorityFeeGwei ?? 0;
|
|
577
|
-
const configuredBase = useCustomGas && args.chainDetail?.baseFee != null ? Number(args.chainDetail.baseFee) : 0;
|
|
578
|
-
const configuredPriority = useCustomGas && args.chainDetail?.priorityFee != null ? Number(args.chainDetail.priorityFee) : 0;
|
|
579
|
-
const effectiveBaseFeeGwei = Math.max(fetchedBase, configuredBase);
|
|
580
|
-
const effectivePriorityFeeGwei = Math.max(fetchedPriority, configuredPriority);
|
|
581
|
-
const baseFeeMultiplierPct = useCustomGas && args.chainDetail?.baseFeeMultiplier != null ? Math.max(100, Number(args.chainDetail.baseFeeMultiplier)) : 100;
|
|
582
|
-
const baseComponentGwei = effectiveBaseFeeGwei * baseFeeMultiplierPct / 100;
|
|
583
|
-
const maxFeePerGasGwei = baseComponentGwei + effectivePriorityFeeGwei;
|
|
584
|
-
let maxPriorityFeePerGas = effectivePriorityFeeGwei > 0 ? parseGwei(gweiToDecimalString(effectivePriorityFeeGwei)) : parseGwei("1");
|
|
585
|
-
let maxFeePerGas = parseGwei(gweiToDecimalString(maxFeePerGasGwei));
|
|
586
|
-
if (useCustomGas && gasFeeMultiplier != null && gasFeeMultiplier > 0) {
|
|
587
|
-
maxPriorityFeePerGas = maxPriorityFeePerGas * BigInt(100 + gasFeeMultiplier) / 100n;
|
|
588
|
-
maxFeePerGas = maxFeePerGas * BigInt(100 + gasFeeMultiplier) / 100n;
|
|
589
|
-
}
|
|
590
|
-
({ maxFeePerGas, maxPriorityFeePerGas } = alignEip1559FeesWithLatestBase(
|
|
591
|
-
maxFeePerGas,
|
|
592
|
-
maxPriorityFeePerGas,
|
|
593
|
-
latestBaseFeeWei
|
|
594
|
-
));
|
|
595
|
-
ser = serializeTransaction({
|
|
596
|
-
type: "eip1559",
|
|
597
|
-
to: pool,
|
|
598
|
-
data,
|
|
599
|
-
value: 0n,
|
|
600
|
-
gas: gasLimitI,
|
|
601
|
-
maxFeePerGas,
|
|
602
|
-
maxPriorityFeePerGas,
|
|
603
|
-
nonce: currentNonce,
|
|
604
|
-
chainId: args.chainId
|
|
605
|
-
});
|
|
606
|
-
firstTxFeePayload = {
|
|
607
|
-
txNonce: currentNonce,
|
|
608
|
-
txGasLimit: gasLimitI.toString(),
|
|
609
|
-
txMaxFeePerGas: maxFeePerGas.toString(),
|
|
610
|
-
txMaxPriorityFeePerGas: maxPriorityFeePerGas.toString()
|
|
611
|
-
};
|
|
612
|
-
proposalTxParams0 = {
|
|
613
|
-
nonce: currentNonce,
|
|
614
|
-
gasLimit: gasLimitI.toString(),
|
|
615
|
-
txType: "eip1559",
|
|
616
|
-
maxFeePerGas: maxFeePerGas.toString(),
|
|
617
|
-
maxPriorityFeePerGas: maxPriorityFeePerGas.toString()
|
|
618
|
-
};
|
|
619
|
-
}
|
|
620
|
-
const h = keccak256(ser);
|
|
621
|
-
const messageHashes = [h.startsWith("0x") ? h.slice(2) : h];
|
|
622
|
-
const messageRawBatch = [ser];
|
|
623
|
-
const proposalTxParamsBatch = [proposalTxParams0];
|
|
624
549
|
const firstDataNo0x = data.startsWith("0x") ? data.slice(2) : data;
|
|
625
|
-
const
|
|
626
|
-
|
|
627
|
-
|
|
550
|
+
const purposeSuffix = "Maple Syrup: 1-tx \u2014 request redeem (queue withdrawal of underlying from pool shares).";
|
|
551
|
+
return buildEvmMultisignBatch({
|
|
552
|
+
context: {
|
|
553
|
+
chainCategory: "evm",
|
|
554
|
+
keyGen: args.keyGen,
|
|
555
|
+
purposeText: args.purposeText,
|
|
556
|
+
chainId: args.chainId,
|
|
557
|
+
rpcUrl: args.rpcUrl,
|
|
558
|
+
executorAddress: executor,
|
|
559
|
+
chainDetail: args.chainDetail,
|
|
560
|
+
useCustomGas: args.useCustomGas,
|
|
561
|
+
customGasChainDetails: args.customGasChainDetails
|
|
562
|
+
},
|
|
563
|
+
steps: [{ to: pool, data, value: 0n, fallbackGas: MAPLE_REQUEST_REDEEM_FALLBACK }],
|
|
564
|
+
purposeSuffix,
|
|
565
|
+
firstMsgRawNo0x: firstDataNo0x,
|
|
566
|
+
destinationAddress: pool,
|
|
567
|
+
buildBatchMeta: ({ gasLimit }) => ({
|
|
628
568
|
signatureText: JSON.stringify({
|
|
629
569
|
kind: "MapleSyrup",
|
|
630
570
|
name: "PoolV2.requestRedeem",
|
|
@@ -635,37 +575,90 @@ async function buildEvmMultisignBodyMaplePoolRequestRedeem(args) {
|
|
|
635
575
|
pool
|
|
636
576
|
}),
|
|
637
577
|
evm: { type: "maple_pool_v2_request_redeem", version: 1, chainId: chainIdStr },
|
|
638
|
-
maple: { step: "request_redeem", pool, gasBuildRedeem: { baseGasUnits:
|
|
639
|
-
}
|
|
640
|
-
|
|
641
|
-
|
|
642
|
-
|
|
643
|
-
|
|
578
|
+
maple: { step: "request_redeem", pool, gasBuildRedeem: { baseGasUnits: gasLimit.toString() } }
|
|
579
|
+
})
|
|
580
|
+
});
|
|
581
|
+
}
|
|
582
|
+
async function postJsonViaOptionalProxy(args) {
|
|
583
|
+
const r = await fetch(args.directUrl, {
|
|
584
|
+
method: "POST",
|
|
585
|
+
headers: { "content-type": "application/json" },
|
|
586
|
+
body: JSON.stringify(args.body)
|
|
587
|
+
});
|
|
588
|
+
if (!r.ok) {
|
|
589
|
+
const t = await r.text().catch(() => "");
|
|
590
|
+
throw new Error(t ? `HTTP ${r.status}: ${t.slice(0, 200)}` : `HTTP ${r.status}`);
|
|
644
591
|
}
|
|
645
|
-
|
|
646
|
-
|
|
647
|
-
const bodyForSign = {
|
|
648
|
-
keyList,
|
|
649
|
-
pubKey: ph,
|
|
650
|
-
msgHash: messageHashes[0],
|
|
651
|
-
msgRaw: firstDataNo0x,
|
|
652
|
-
messageHashes,
|
|
653
|
-
messageRawBatch,
|
|
654
|
-
destinationChainID: String(args.chainId),
|
|
655
|
-
destinationAddress: pool,
|
|
656
|
-
extraJSON,
|
|
657
|
-
signatureText: batchMeta[0].signatureText,
|
|
658
|
-
purpose: (() => {
|
|
659
|
-
const t = args.purposeText.trim();
|
|
660
|
-
return (t ? `${t}
|
|
592
|
+
return await r.json();
|
|
593
|
+
}
|
|
661
594
|
|
|
662
|
-
|
|
663
|
-
|
|
664
|
-
|
|
665
|
-
|
|
595
|
+
// src/protocols/evm/maple/graphql.ts
|
|
596
|
+
var POOLS_GQL = `
|
|
597
|
+
query MapleSyrupPools {
|
|
598
|
+
poolV2S(where: { syrupRouter_not: null }) {
|
|
599
|
+
id
|
|
600
|
+
name
|
|
601
|
+
asset {
|
|
602
|
+
id
|
|
603
|
+
symbol
|
|
604
|
+
decimals
|
|
605
|
+
}
|
|
606
|
+
syrupRouter {
|
|
607
|
+
id
|
|
608
|
+
}
|
|
609
|
+
}
|
|
610
|
+
}
|
|
611
|
+
`;
|
|
612
|
+
function normalizePool(p) {
|
|
613
|
+
return {
|
|
614
|
+
id: getAddress(p.id),
|
|
615
|
+
name: (p.name ?? "").trim(),
|
|
616
|
+
asset: {
|
|
617
|
+
id: getAddress(p.asset.id),
|
|
618
|
+
symbol: (p.asset.symbol ?? "").trim(),
|
|
619
|
+
decimals: Number(p.asset.decimals)
|
|
620
|
+
},
|
|
621
|
+
syrupRouter: { id: getAddress(p.syrupRouter.id) }
|
|
666
622
|
};
|
|
667
|
-
|
|
668
|
-
|
|
623
|
+
}
|
|
624
|
+
async function mapleGraphqlPost(args) {
|
|
625
|
+
const endpoint = mapleGraphqlEndpointForChain(args.chainId);
|
|
626
|
+
if (!endpoint) throw new Error(`Maple GraphQL is not configured for chain ${args.chainId}`);
|
|
627
|
+
const body = { query: args.query, variables: args.variables ?? {} };
|
|
628
|
+
return postJsonViaOptionalProxy({
|
|
629
|
+
directUrl: endpoint,
|
|
630
|
+
body,
|
|
631
|
+
proxyEnvelope: { chainId: args.chainId, query: args.query, variables: args.variables ?? {} }
|
|
632
|
+
});
|
|
633
|
+
}
|
|
634
|
+
async function fetchMapleSyrupPools(chainId) {
|
|
635
|
+
const raw = await mapleGraphqlPost({ chainId, query: POOLS_GQL });
|
|
636
|
+
if (raw.errors?.length) {
|
|
637
|
+
throw new Error(raw.errors.map((e) => e.message ?? "GraphQL error").join("; "));
|
|
638
|
+
}
|
|
639
|
+
const rows = raw.data?.poolV2S ?? [];
|
|
640
|
+
return rows.map(normalizePool);
|
|
641
|
+
}
|
|
642
|
+
var ACCOUNT_GQL = `
|
|
643
|
+
query MapleAccount($accountId: ID!) {
|
|
644
|
+
account(id: $accountId) {
|
|
645
|
+
isSyrupLender
|
|
646
|
+
}
|
|
647
|
+
}
|
|
648
|
+
`;
|
|
649
|
+
async function fetchMapleAccountIsSyrupLender(args) {
|
|
650
|
+
try {
|
|
651
|
+
const raw = await mapleGraphqlPost({
|
|
652
|
+
chainId: args.chainId,
|
|
653
|
+
query: ACCOUNT_GQL,
|
|
654
|
+
variables: { accountId: args.account.toLowerCase() }
|
|
655
|
+
});
|
|
656
|
+
const acct = raw.data?.account;
|
|
657
|
+
if (!acct) return null;
|
|
658
|
+
return Boolean(acct.isSyrupLender);
|
|
659
|
+
} catch {
|
|
660
|
+
return null;
|
|
661
|
+
}
|
|
669
662
|
}
|
|
670
663
|
|
|
671
664
|
// src/protocols/evm/maple/index.ts
|
|
@@ -688,6 +681,6 @@ var mapleProtocolModule = {
|
|
|
688
681
|
};
|
|
689
682
|
registerProtocolModule(mapleProtocolModule);
|
|
690
683
|
|
|
691
|
-
export { MAPLE_INTEGRATION_DOCS_URL, MAPLE_PROTOCOL_ID, MAPLE_SYRUP_DEPOSIT_DATA_ASCII, MAPLE_SYRUP_DEPOSIT_GAS_FALLBACK, buildEvmMultisignBodyMaplePoolRequestRedeem, buildEvmMultisignBodyMapleSyrupDeposit, isMapleSyrupSupportedChain, mapleGraphqlEndpointForChain, mapleProtocolModule, parseMapleStakeAuthInputs, readMaplePoolShareDecimals, readMapleStakePreviewShares, readMapleUnstakeExitSharesForAssets };
|
|
684
|
+
export { MAPLE_INTEGRATION_DOCS_URL, MAPLE_PROTOCOL_ID, MAPLE_SYRUP_DEPOSIT_DATA_ASCII, MAPLE_SYRUP_DEPOSIT_GAS_FALLBACK, buildEvmMultisignBodyMaplePoolRequestRedeem, buildEvmMultisignBodyMapleSyrupDeposit, fetchMapleAccountIsSyrupLender, fetchMapleSyrupPools, isMapleSyrupSupportedChain, mapleGraphqlEndpointForChain, mapleProtocolModule, parseMapleStakeAuthInputs, readMaplePoolShareDecimals, readMapleStakePreviewShares, readMapleUnstakeExitSharesForAssets };
|
|
692
685
|
//# sourceMappingURL=index.js.map
|
|
693
686
|
//# sourceMappingURL=index.js.map
|