@continuumdao/ctm-mpc-defi 0.2.30 → 0.2.32

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.
Files changed (40) hide show
  1. package/dist/agent/catalog.cjs +1933 -56
  2. package/dist/agent/catalog.cjs.map +1 -1
  3. package/dist/agent/catalog.d.ts +3671 -661
  4. package/dist/agent/catalog.js +1896 -58
  5. package/dist/agent/catalog.js.map +1 -1
  6. package/dist/agent/skills/aerodrome/SKILL.md +93 -0
  7. package/dist/agent/skills/compound-v3/SKILL.md +132 -0
  8. package/dist/agent/skills/euler-v2/SKILL.md +1 -1
  9. package/dist/agent/skills/morpho/SKILL.md +16 -8
  10. package/dist/buildBatch-CngvebiD.d.ts +45 -0
  11. package/dist/chains/evm/index.d.ts +6 -44
  12. package/dist/core/index.cjs +2 -1
  13. package/dist/core/index.cjs.map +1 -1
  14. package/dist/core/index.js +2 -1
  15. package/dist/core/index.js.map +1 -1
  16. package/dist/index.cjs +119 -1
  17. package/dist/index.cjs.map +1 -1
  18. package/dist/index.d.ts +4 -1
  19. package/dist/index.js +119 -2
  20. package/dist/index.js.map +1 -1
  21. package/dist/protocols/evm/aerodrome/index.cjs +3922 -0
  22. package/dist/protocols/evm/aerodrome/index.cjs.map +1 -0
  23. package/dist/protocols/evm/aerodrome/index.d.ts +792 -0
  24. package/dist/protocols/evm/aerodrome/index.js +3843 -0
  25. package/dist/protocols/evm/aerodrome/index.js.map +1 -0
  26. package/dist/protocols/evm/compound-v3/index.cjs +1542 -0
  27. package/dist/protocols/evm/compound-v3/index.cjs.map +1 -0
  28. package/dist/protocols/evm/compound-v3/index.d.ts +683 -0
  29. package/dist/protocols/evm/compound-v3/index.js +1488 -0
  30. package/dist/protocols/evm/compound-v3/index.js.map +1 -0
  31. package/dist/protocols/evm/euler-v2/index.cjs +17 -10
  32. package/dist/protocols/evm/euler-v2/index.cjs.map +1 -1
  33. package/dist/protocols/evm/euler-v2/index.js +17 -10
  34. package/dist/protocols/evm/euler-v2/index.js.map +1 -1
  35. package/dist/protocols/evm/morpho/index.cjs +746 -39
  36. package/dist/protocols/evm/morpho/index.cjs.map +1 -1
  37. package/dist/protocols/evm/morpho/index.d.ts +161 -14
  38. package/dist/protocols/evm/morpho/index.js +736 -42
  39. package/dist/protocols/evm/morpho/index.js.map +1 -1
  40. package/package.json +15 -1
@@ -0,0 +1,1542 @@
1
+ 'use strict';
2
+
3
+ var viem = require('viem');
4
+ var continuumNodeSdk = require('@continuumdao/continuum-node-sdk');
5
+
6
+ // src/core/registry.ts
7
+ var modules = [];
8
+ function registerProtocolModule(mod) {
9
+ const existing = modules.findIndex((m) => m.id === mod.id);
10
+ if (existing >= 0) {
11
+ modules[existing] = mod;
12
+ } else {
13
+ modules.push(mod);
14
+ }
15
+ }
16
+ var COMPOUND_V3_PROTOCOL_ID = "compound-v3";
17
+ var COMPOUND_V3_CHAIN_IDS = [1, 8453, 42161, 10, 137, 5e3, 130, 59144];
18
+ var COMPOUND_V3_WRAPPED_NATIVE = {
19
+ 1: viem.getAddress("0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2"),
20
+ 8453: viem.getAddress("0x4200000000000000000000000000000000000006"),
21
+ 42161: viem.getAddress("0x82aF49447D8a07e3bd95BD0d56f35241523fBab1"),
22
+ 10: viem.getAddress("0x4200000000000000000000000000000000000006"),
23
+ 137: viem.getAddress("0x0d500B1d8E8eF31E21C99d1Db9A6444d3ADf1270"),
24
+ 5e3: viem.getAddress("0x78c1b0C915c4CD0f08633e2ec3d4961Ab0237669"),
25
+ 130: viem.getAddress("0x4200000000000000000000000000000000000006"),
26
+ 59144: viem.getAddress("0xe5D7C2a44FfDDf6b295A15c148167daaAf5Cf34f")
27
+ };
28
+ function isCompoundV3ChainSupported(chainId) {
29
+ return COMPOUND_V3_CHAIN_IDS.includes(chainId);
30
+ }
31
+ function compoundV3WrappedNative(chainId) {
32
+ return COMPOUND_V3_WRAPPED_NATIVE[chainId] ?? null;
33
+ }
34
+ function isNativeAssetAddress(address) {
35
+ try {
36
+ return viem.getAddress(address) === viem.zeroAddress;
37
+ } catch {
38
+ return false;
39
+ }
40
+ }
41
+ function resolveCompoundV3ActionAsset(args) {
42
+ const nativeWrapped = compoundV3WrappedNative(args.chainId);
43
+ const isNative = args.isNative === true || isNativeAssetAddress(args.asset);
44
+ if (isNative) {
45
+ if (!nativeWrapped) {
46
+ throw new Error(`No wrapped native token configured for Compound III on chain ${args.chainId}.`);
47
+ }
48
+ return { asset: nativeWrapped, isNative: true, nativeWrapped };
49
+ }
50
+ return { asset: viem.getAddress(args.asset), isNative: false, nativeWrapped };
51
+ }
52
+ var COMPOUND_V3_MARKETS = [
53
+ // Ethereum
54
+ {
55
+ chainId: 1,
56
+ slug: "usdc",
57
+ symbol: "cUSDCv3",
58
+ comet: viem.getAddress("0xc3d688B66703497DAA19211EEdff47f25384cdc3"),
59
+ rewards: viem.getAddress("0x1B0e765F6224C21223AeA2af16c1C46E38885a40"),
60
+ bulker: viem.getAddress("0xa397a8C2086C554B531c02E29f3291c9704B00c7"),
61
+ baseToken: viem.getAddress("0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48"),
62
+ source: "comet-deployments"
63
+ },
64
+ {
65
+ chainId: 1,
66
+ slug: "usds",
67
+ symbol: "cUSDSv3",
68
+ comet: viem.getAddress("0x5D409e56D886231aDAf00c8775665AD0f9897b56"),
69
+ rewards: viem.getAddress("0x1B0e765F6224C21223AeA2af16c1C46E38885a40"),
70
+ bulker: viem.getAddress("0xa397a8C2086C554B531c02E29f3291c9704B00c7"),
71
+ baseToken: viem.getAddress("0xdC035D45d973E3EC169d2276DDab16f1e407384F"),
72
+ source: "comet-deployments"
73
+ },
74
+ {
75
+ chainId: 1,
76
+ slug: "usdt",
77
+ symbol: "cUSDTv3",
78
+ comet: viem.getAddress("0x3Afdc9BCA9213A35503b077a6072F3D0d5AB0840"),
79
+ rewards: viem.getAddress("0x1B0e765F6224C21223AeA2af16c1C46E38885a40"),
80
+ bulker: viem.getAddress("0xa397a8C2086C554B531c02E29f3291c9704B00c7"),
81
+ baseToken: viem.getAddress("0xdAC17F958D2ee523a2206206994597C13D831ec7"),
82
+ source: "comet-deployments"
83
+ },
84
+ {
85
+ chainId: 1,
86
+ slug: "wbtc",
87
+ symbol: "cWBTCv3",
88
+ comet: viem.getAddress("0xe85Dc543813B8c2CFEaAc371517b925a166a9293"),
89
+ rewards: viem.getAddress("0x1B0e765F6224C21223AeA2af16c1C46E38885a40"),
90
+ bulker: viem.getAddress("0xa397a8C2086C554B531c02E29f3291c9704B00c7"),
91
+ baseToken: viem.getAddress("0x2260FAC5E5542a773Aa44fBCfeDf7C193bc2C599"),
92
+ source: "comet-deployments"
93
+ },
94
+ {
95
+ chainId: 1,
96
+ slug: "weth",
97
+ symbol: "cWETHv3",
98
+ comet: viem.getAddress("0xA17581A9E3356d9A858b789D68B4d866e593aE94"),
99
+ rewards: viem.getAddress("0x1B0e765F6224C21223AeA2af16c1C46E38885a40"),
100
+ bulker: viem.getAddress("0xa397a8C2086C554B531c02E29f3291c9704B00c7"),
101
+ baseToken: viem.getAddress("0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2"),
102
+ source: "comet-deployments"
103
+ },
104
+ {
105
+ chainId: 1,
106
+ slug: "wsteth",
107
+ symbol: "cWstETHv3",
108
+ comet: viem.getAddress("0x3D0bb1ccaB520A66e607822fC55BC921738fAFE3"),
109
+ rewards: viem.getAddress("0x1B0e765F6224C21223AeA2af16c1C46E38885a40"),
110
+ bulker: viem.getAddress("0x2c776041CCFe903071AF44aa147368a9c8EEA518"),
111
+ baseToken: viem.getAddress("0x7f39C581F595B53c5cb19bD0b3f8dA6c935E2Ca0"),
112
+ source: "comet-deployments"
113
+ },
114
+ // Base
115
+ {
116
+ chainId: 8453,
117
+ slug: "usdc",
118
+ symbol: "cUSDCv3",
119
+ comet: viem.getAddress("0xb125E6687d4313864e53df431d5425969c15Eb2F"),
120
+ rewards: viem.getAddress("0x123964802e6ABabBE1Bc9547D72Ef1B69B00A6b1"),
121
+ bulker: viem.getAddress("0x78D0677032A35c63D142a48A2037048871212a8C"),
122
+ baseToken: viem.getAddress("0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913"),
123
+ source: "comet-deployments"
124
+ },
125
+ {
126
+ chainId: 8453,
127
+ slug: "usdbc",
128
+ symbol: "cUSDbCv3",
129
+ comet: viem.getAddress("0x9c4ec768c28520B50860ea7a15bd7213a9fF58bf"),
130
+ rewards: viem.getAddress("0x123964802e6ABabBE1Bc9547D72Ef1B69B00A6b1"),
131
+ bulker: viem.getAddress("0x78D0677032A35c63D142a48A2037048871212a8C"),
132
+ baseToken: viem.getAddress("0xd9aAEc86B65D86f6A7B5B1b0c42FFA531710b6CA"),
133
+ source: "comet-deployments"
134
+ },
135
+ {
136
+ chainId: 8453,
137
+ slug: "usds",
138
+ symbol: "cUSDSv3",
139
+ comet: viem.getAddress("0x2c776041CCFe903071AF44aa147368a9c8EEA518"),
140
+ rewards: viem.getAddress("0x123964802e6ABabBE1Bc9547D72Ef1B69B00A6b1"),
141
+ bulker: viem.getAddress("0x78D0677032A35c63D142a48A2037048871212a8C"),
142
+ baseToken: viem.getAddress("0x820C137fa70C8691f0e44Dc420a5e53c168921Dc"),
143
+ source: "comet-deployments"
144
+ },
145
+ {
146
+ chainId: 8453,
147
+ slug: "weth",
148
+ symbol: "cWETHv3",
149
+ comet: viem.getAddress("0x46e6b214b524310239732D51387075E0e70970bf"),
150
+ rewards: viem.getAddress("0x123964802e6ABabBE1Bc9547D72Ef1B69B00A6b1"),
151
+ bulker: viem.getAddress("0x78D0677032A35c63D142a48A2037048871212a8C"),
152
+ baseToken: viem.getAddress("0x4200000000000000000000000000000000000006"),
153
+ source: "comet-deployments"
154
+ },
155
+ {
156
+ chainId: 8453,
157
+ slug: "aero",
158
+ symbol: "cAEROv3",
159
+ comet: viem.getAddress("0x784efeB622244d2348d4F2522f8860B96fbEcE89"),
160
+ rewards: viem.getAddress("0x123964802e6ABabBE1Bc9547D72Ef1B69B00A6b1"),
161
+ bulker: viem.getAddress("0x78D0677032A35c63D142a48A2037048871212a8C"),
162
+ baseToken: viem.getAddress("0x940181a94A35A4569E4529A3CDfB74e38FD98631"),
163
+ source: "comet-deployments"
164
+ },
165
+ // Arbitrum
166
+ {
167
+ chainId: 42161,
168
+ slug: "usdc",
169
+ symbol: "cUSDCv3",
170
+ comet: viem.getAddress("0x9c4ec768c28520B50860ea7a15bd7213a9fF58bf"),
171
+ rewards: viem.getAddress("0x88730d254A2f7e6AC8388c3198aFd694bA9f7fae"),
172
+ bulker: viem.getAddress("0xbdE8F31D2DdDA895264e27DD990faB3DC87b372d"),
173
+ baseToken: viem.getAddress("0xaf88d065e77c8cC2239327C5EDb3A432268e5831"),
174
+ source: "comet-deployments"
175
+ },
176
+ {
177
+ chainId: 42161,
178
+ slug: "usdc.e",
179
+ symbol: "cUSDC.ev3",
180
+ comet: viem.getAddress("0xA5EDBDD9646f8dFF606d7448e414884C7d905dCA"),
181
+ rewards: viem.getAddress("0x88730d254A2f7e6AC8388c3198aFd694bA9f7fae"),
182
+ bulker: viem.getAddress("0xbdE8F31D2DdDA895264e27DD990faB3DC87b372d"),
183
+ baseToken: viem.getAddress("0xFF970A61A04b1cA14834A43f5dE4533eBDDB5CC8"),
184
+ source: "comet-deployments"
185
+ },
186
+ {
187
+ chainId: 42161,
188
+ slug: "usdt",
189
+ symbol: "cUSDTv3",
190
+ comet: viem.getAddress("0xd98Be00b5D27fc98112BdE293e487f8D4cA57d07"),
191
+ rewards: viem.getAddress("0x88730d254A2f7e6AC8388c3198aFd694bA9f7fae"),
192
+ bulker: viem.getAddress("0xbdE8F31D2DdDA895264e27DD990faB3DC87b372d"),
193
+ baseToken: viem.getAddress("0xFd086bC7CD5C481DCC9C85ebE478A1C0b69FCbb9"),
194
+ source: "comet-deployments"
195
+ },
196
+ {
197
+ chainId: 42161,
198
+ slug: "weth",
199
+ symbol: "cWETHv3",
200
+ comet: viem.getAddress("0x6f7D514bbD4aFf3BcD1140B7344b32f063dEe486"),
201
+ rewards: viem.getAddress("0x88730d254A2f7e6AC8388c3198aFd694bA9f7fae"),
202
+ bulker: viem.getAddress("0xbdE8F31D2DdDA895264e27DD990faB3DC87b372d"),
203
+ baseToken: viem.getAddress("0x82aF49447D8a07e3bd95BD0d56f35241523fBab1"),
204
+ source: "comet-deployments"
205
+ },
206
+ // Optimism
207
+ {
208
+ chainId: 10,
209
+ slug: "usdc",
210
+ symbol: "cUSDCv3",
211
+ comet: viem.getAddress("0x2e44e174f7D53F0212823acC11C01A11d58c5bCB"),
212
+ rewards: viem.getAddress("0x443EA0340cb75a160F31A440722dec7b5bc3C2E9"),
213
+ bulker: viem.getAddress("0xcb3643CC8294B23171272845473dEc49739d4Ba3"),
214
+ baseToken: viem.getAddress("0x0b2C639c533813f4Aa9D7837CAf62653d097Ff85"),
215
+ source: "comet-deployments"
216
+ },
217
+ {
218
+ chainId: 10,
219
+ slug: "usdt",
220
+ symbol: "cUSDTv3",
221
+ comet: viem.getAddress("0x995E394b8B2437aC8Ce61Ee0bC610D617962B214"),
222
+ rewards: viem.getAddress("0x443EA0340cb75a160F31A440722dec7b5bc3C2E9"),
223
+ bulker: viem.getAddress("0xcb3643CC8294B23171272845473dEc49739d4Ba3"),
224
+ baseToken: viem.getAddress("0x94b008aA00579c1307B0EF2c499aD98a8ce58e58"),
225
+ source: "comet-deployments"
226
+ },
227
+ {
228
+ chainId: 10,
229
+ slug: "weth",
230
+ symbol: "cWETHv3",
231
+ comet: viem.getAddress("0xE36A30D249f7761327fd973001A32010b521b6Fd"),
232
+ rewards: viem.getAddress("0x443EA0340cb75a160F31A440722dec7b5bc3C2E9"),
233
+ bulker: viem.getAddress("0xcb3643CC8294B23171272845473dEc49739d4Ba3"),
234
+ baseToken: viem.getAddress("0x4200000000000000000000000000000000000006"),
235
+ source: "comet-deployments"
236
+ },
237
+ // Polygon
238
+ {
239
+ chainId: 137,
240
+ slug: "usdc",
241
+ symbol: "cUSDCv3",
242
+ comet: viem.getAddress("0xF25212E676D1F7F89Cd72fFEe66158f541246445"),
243
+ rewards: viem.getAddress("0x45939657d1CA34A8FA39A924B71D28Fe8431e581"),
244
+ bulker: viem.getAddress("0x59e242D352ae13166B4987aE5c990C232f7f7CD6"),
245
+ baseToken: viem.getAddress("0x2791Bca1f2de4661ED88A30C99A7a9449Aa84174"),
246
+ source: "comet-deployments"
247
+ },
248
+ {
249
+ chainId: 137,
250
+ slug: "usdt",
251
+ symbol: "cUSDTv3",
252
+ comet: viem.getAddress("0xaeB318360f27748Acb200CE616E389A6C9409a07"),
253
+ rewards: viem.getAddress("0x45939657d1CA34A8FA39A924B71D28Fe8431e581"),
254
+ bulker: viem.getAddress("0x59e242D352ae13166B4987aE5c990C232f7f7CD6"),
255
+ baseToken: viem.getAddress("0xc2132D05D31c914a87C6611C10748AEb04B58e8F"),
256
+ source: "comet-deployments"
257
+ },
258
+ // Mantle
259
+ {
260
+ chainId: 5e3,
261
+ slug: "usde",
262
+ symbol: "cUSDev3",
263
+ comet: viem.getAddress("0x606174f62cd968d8e684c645080fa694c1D7786E"),
264
+ rewards: viem.getAddress("0xCd83CbBFCE149d141A5171C3D6a0F0fCCeE225Ab"),
265
+ bulker: viem.getAddress("0x67DFCa85CcEEFA2C5B1dB4DEe3BEa716A28B9baa"),
266
+ source: "comet-deployments"
267
+ },
268
+ // Unichain
269
+ {
270
+ chainId: 130,
271
+ slug: "usdc",
272
+ symbol: "cUSDCv3",
273
+ comet: viem.getAddress("0x2c7118c4C88B9841FCF839074c26Ae8f035f2921"),
274
+ rewards: viem.getAddress("0x6f7D514bbD4aFf3BcD1140B7344b32f063dEe486"),
275
+ bulker: viem.getAddress("0x58EbB8Db8b4FdF2dCbbB16E04c2F5b952963B514"),
276
+ baseToken: viem.getAddress("0x078D782b760474a361dDA0AF3839290b0EF57AD6"),
277
+ source: "comet-deployments"
278
+ },
279
+ {
280
+ chainId: 130,
281
+ slug: "weth",
282
+ symbol: "cWETHv3",
283
+ comet: viem.getAddress("0x6C987dDE50dB1dcDd32Cd4175778C2a291978E2a"),
284
+ rewards: viem.getAddress("0x6f7D514bbD4aFf3BcD1140B7344b32f063dEe486"),
285
+ bulker: viem.getAddress("0x58EbB8Db8b4FdF2dCbbB16E04c2F5b952963B514"),
286
+ baseToken: viem.getAddress("0x4200000000000000000000000000000000000006"),
287
+ source: "comet-deployments"
288
+ },
289
+ // Linea
290
+ {
291
+ chainId: 59144,
292
+ slug: "usdc",
293
+ symbol: "cUSDCv3",
294
+ comet: viem.getAddress("0x8D38A3d6B3c3B7d96D6536DA7Eef94A9d7dbC991"),
295
+ rewards: viem.getAddress("0x2c7118c4C88B9841FCF839074c26Ae8f035f2921"),
296
+ bulker: viem.getAddress("0x023ee795361B28cDbB94e302983578486A0A5f1B"),
297
+ baseToken: viem.getAddress("0x176211869cA2b568f2A7D4EE941E073a821EE1ff"),
298
+ source: "comet-deployments"
299
+ },
300
+ {
301
+ chainId: 59144,
302
+ slug: "weth",
303
+ symbol: "cWETHv3",
304
+ comet: viem.getAddress("0x60F2058379716A64a7A5d29219397e79bC552194"),
305
+ rewards: viem.getAddress("0x2c7118c4C88B9841FCF839074c26Ae8f035f2921"),
306
+ bulker: viem.getAddress("0x023ee795361B28cDbB94e302983578486A0A5f1B"),
307
+ baseToken: viem.getAddress("0xe5D7C2a44FfDDf6b295A15c148167daaAf5Cf34f"),
308
+ source: "comet-deployments"
309
+ }
310
+ ];
311
+ function listCompoundV3SupportedChainIds() {
312
+ return [...COMPOUND_V3_CHAIN_IDS];
313
+ }
314
+ function listCompoundV3MarketsForChain(chainId) {
315
+ if (!isCompoundV3ChainSupported(chainId)) return [];
316
+ return COMPOUND_V3_MARKETS.filter((m) => m.chainId === chainId);
317
+ }
318
+ function getCompoundV3MarketByComet(chainId, comet) {
319
+ let normalized;
320
+ try {
321
+ normalized = viem.getAddress(comet);
322
+ } catch {
323
+ return null;
324
+ }
325
+ return COMPOUND_V3_MARKETS.find((m) => m.chainId === chainId && m.comet === normalized) ?? null;
326
+ }
327
+ function requireCompoundV3Market(chainId, comet) {
328
+ const market = getCompoundV3MarketByComet(chainId, comet);
329
+ if (!market) {
330
+ throw new Error(
331
+ `Unknown Compound III Comet proxy ${comet} on chain ${chainId}. Use ctm_compound_v3_fetch_markets.`
332
+ );
333
+ }
334
+ return market;
335
+ }
336
+ function listCompoundV3KnownTokenAddresses(chainId) {
337
+ const out = /* @__PURE__ */ new Set();
338
+ for (const m of listCompoundV3MarketsForChain(chainId)) {
339
+ out.add(m.comet);
340
+ if (m.baseToken) out.add(m.baseToken);
341
+ }
342
+ return [...out];
343
+ }
344
+ var cometInterfaceAbi = viem.parseAbi([
345
+ "function supply(address asset, uint256 amount)",
346
+ "function supplyTo(address dst, address asset, uint256 amount)",
347
+ "function withdraw(address asset, uint256 amount)",
348
+ "function withdrawTo(address to, address asset, uint256 amount)",
349
+ "function allow(address manager, bool isAllowed)",
350
+ "function hasPermission(address owner, address manager) view returns (bool)",
351
+ "function balanceOf(address account) view returns (uint256)",
352
+ "function borrowBalanceOf(address account) view returns (uint256)",
353
+ "function collateralBalanceOf(address account, address asset) view returns (uint128)",
354
+ "function baseToken() view returns (address)",
355
+ "function baseTokenPriceFeed() view returns (address)",
356
+ "function decimals() view returns (uint8)",
357
+ "function numAssets() view returns (uint8)",
358
+ "function getUtilization() view returns (uint256)",
359
+ "function getSupplyRate(uint256 utilization) view returns (uint64)",
360
+ "function getBorrowRate(uint256 utilization) view returns (uint64)",
361
+ "function getPrice(address priceFeed) view returns (uint256)",
362
+ "function isBorrowCollateralized(address account) view returns (bool)",
363
+ "function isLiquidatable(address account) view returns (bool)",
364
+ "function getAssetInfo(uint8 i) view returns ((uint8 offset, address asset, address priceFeed, uint64 scale, uint64 borrowCollateralFactor, uint64 liquidateCollateralFactor, uint64 liquidationFactor, uint128 supplyCap))",
365
+ "function getAssetInfoByAddress(address asset) view returns ((uint8 offset, address asset, address priceFeed, uint64 scale, uint64 borrowCollateralFactor, uint64 liquidateCollateralFactor, uint64 liquidationFactor, uint128 supplyCap))"
366
+ ]);
367
+ var cometRewardsAbi = viem.parseAbi([
368
+ "function getRewardOwed(address comet, address account) view returns ((address token, uint256 owed))",
369
+ "function claim(address comet, address src, bool shouldAccrue)"
370
+ ]);
371
+ var cometBulkerAbi = viem.parseAbi([
372
+ "function invoke(bytes32[] actions, bytes[] data) payable"
373
+ ]);
374
+ var erc20ReadAbi = viem.parseAbi([
375
+ "function allowance(address owner, address spender) view returns (uint256)",
376
+ "function decimals() view returns (uint8)",
377
+ "function symbol() view returns (string)",
378
+ "function name() view returns (string)"
379
+ ]);
380
+ var erc20ApproveAbi = viem.parseAbi(["function approve(address spender, uint256 amount) returns (bool)"]);
381
+ var wethAbi = viem.parseAbi(["function deposit() payable", "function withdraw(uint256 wad)"]);
382
+ function bulkerActionId(name) {
383
+ return viem.stringToHex(name, { size: 32 });
384
+ }
385
+ var BULKER_ACTION_SUPPLY_ASSET = bulkerActionId("ACTION_SUPPLY_ASSET");
386
+ var BULKER_ACTION_SUPPLY_NATIVE_TOKEN = bulkerActionId("ACTION_SUPPLY_NATIVE_TOKEN");
387
+ var BULKER_ACTION_WITHDRAW_ASSET = bulkerActionId("ACTION_WITHDRAW_ASSET");
388
+ var BULKER_ACTION_WITHDRAW_NATIVE_TOKEN = bulkerActionId("ACTION_WITHDRAW_NATIVE_TOKEN");
389
+ var BULKER_ACTION_CLAIM_REWARD = bulkerActionId("ACTION_CLAIM_REWARD");
390
+ var BULKER_ACTION_TRANSFER_ASSET = bulkerActionId("ACTION_TRANSFER_ASSET");
391
+
392
+ // src/protocols/evm/compound-v3/compound-js-artifacts/comet-constants.json
393
+ var comet_constants_default = { address: { mainnet_usdc: { COMP: { contract: "0xc00e94Cb662C3520282E6f5717214004A7f26888", priceFeed: "0xdbd020CAeF83eFd542f4De03e3cF0C28A4428bd5" }, WBTC: { contract: "0x2260FAC5E5542a773Aa44fBCfeDf7C193bc2C599", priceFeed: "0xF4030086522a5bEEa4988F8cA5B36dbC97BeE88c" }, WETH: { contract: "0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2", priceFeed: "0x5f4eC3Df9cbd43714FE2740f5E3616155c5b8419" }, UNI: { contract: "0x1f9840a85d5aF5bf1D1762F925BDADdC4201F984", priceFeed: "0x553303d460EE0afB37EdFf9bE42922D8FF63220e" }, LINK: { contract: "0x514910771AF9Ca656af840dff83E8264EcF986CA", priceFeed: "0x2c1d072e956AFFC0D435Cb7AC38EF18d24d9127c" }, USDC: { contract: "0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48", priceFeed: "0x8fFfFfd4AfB6115b954Bd326cbe7B4BA576818f6" }, Comet: "0xc3d688B66703497DAA19211EEdff47f25384cdc3" }, mainnet_weth: { cbETH: { contract: "0xBe9895146f7AF43049ca1c1AE358B0541Ea49704", priceFeed: "0x23a982b74a3236A5F2297856d4391B2edBBB5549" }, wstETH: { contract: "0x7f39C581F595B53c5cb19bD0b3f8dA6c935E2Ca0", priceFeed: "0x4F67e4d9BD67eFa28236013288737D39AeF48e79" }, WETH: { contract: "0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2", priceFeed: "0xD72ac1bCE9177CFe7aEb5d0516a38c88a64cE0AB" }, Comet: "0xA17581A9E3356d9A858b789D68B4d866e593aE94" }, polygon_usdc: { WETH: { contract: "0x7ceB23fD6bC0adD59E62ac25578270cFf1b9f619", priceFeed: "0xF9680D99D6C9589e2a93a78A04A279e509205945" }, WBTC: { contract: "0x1BFD67037B42Cf73acF2047067bd4F2C47D9BfD6", priceFeed: "0xDE31F8bFBD8c84b5360CFACCa3539B938dd78ae6" }, WMATIC: { contract: "0x0d500B1d8E8eF31E21C99d1Db9A6444d3ADf1270", priceFeed: "0xAB594600376Ec9fD91F8e885dADF0CE036862dE0" }, MaticX: { contract: "0xfa68FB4628DFF1028CFEc22b4162FCcd0d45efb6", priceFeed: "0x5d37E4b374E6907de8Fc7fb33EE3b0af403C7403" }, USDC: { contract: "0x2791Bca1f2de4661ED88A30C99A7a9449Aa84174", priceFeed: "0xfE4A8cc5b5B2366C1B58Bea3858e81843581b2F7" }, Comet: "0xF25212E676D1F7F89Cd72fFEe66158f541246445" }, arbitrum_usdc: { ARB: { contract: "0x912CE59144191C1204E64559FE8253a0e49E6548", priceFeed: "0xb2A824043730FE05F3DA2efaFa1CBbe83fa548D6" }, GMX: { contract: "0xfc5A1A6EB076a2C7aD06eD22C90d7E710E35ad0a", priceFeed: "0xDB98056FecFff59D032aB628337A4887110df3dB" }, WETH: { contract: "0x82aF49447D8a07e3bd95BD0d56f35241523fBab1", priceFeed: "0x639Fe6ab55C921f74e7fac1ee960C0B6293ba612" }, WBTC: { contract: "0x2f2a2543B76A4166549F7aaB2e75Bef0aefC5B0f", priceFeed: "0xd0C7101eACbB49F3deCcCc166d238410D6D46d57" }, USDC: { contract: "0xFF970A61A04b1cA14834A43f5dE4533eBDDB5CC8", priceFeed: "0x50834F3163758fcC1Df9973b6e91f0F0F0434aD3" }, Comet: "0xA5EDBDD9646f8dFF606d7448e414884C7d905dCA" }, base_usdbc: { cbETH: { contract: "0x2Ae3F1Ec7F1F5012CFEab0185bfc7aa3cf0DEc22", priceFeed: "0x4687670f5f01716fAA382E2356C103BaD776752C" }, WETH: { contract: "0x4200000000000000000000000000000000000006", priceFeed: "0x71041dddad3595F9CEd3DcCFBe3D1F4b0a16Bb70" }, USDbC: { contract: "0xd9aAEc86B65D86f6A7B5B1b0c42FFA531710b6CA", priceFeed: "0x7e860098F58bBFC8648a4311b374B1D669a2bc6B" }, Comet: "0x9c4ec768c28520B50860ea7a15bd7213a9fF58bf" }, base_weth: { cbETH: { contract: "0x2Ae3F1Ec7F1F5012CFEab0185bfc7aa3cf0DEc22", priceFeed: "0x59e242D352ae13166B4987aE5c990C232f7f7CD6" }, WETH: { contract: "0x4200000000000000000000000000000000000006", priceFeed: "0x9f485610E26B9c0140439f88Dc0C7742903Bd1CF" }, Comet: "0x46e6b214b524310239732D51387075E0e70970bf" }, goerli_usdc: { COMP: { contract: "0x3587b2F7E0E2D6166d6C14230e7Fe160252B0ba4", priceFeed: "0x54a06047087927D9B0fb21c1cf0ebd792764dDB8" }, WBTC: { contract: "0xAAD4992D949f9214458594dF92B44165Fb84dC19", priceFeed: "0xA39434A63A52E749F02807ae27335515BA4b07F7" }, WETH: { contract: "0x42a71137C09AE83D8d05974960fd607d40033499", priceFeed: "0xD4a33860578De61DBAbDc8BFdb98FD742fA7028e" }, LINK: { contract: "0xaf95Ff5fB592646D86BF240B3CaE0903b6E4dd38", priceFeed: "0x48731cF7e84dc94C5f84577882c14Be11a5B7456" }, USDC: { contract: "0x07865c6E87B9F70255377e024ace6630C1Eaa37F", priceFeed: "0xAb5c49580294Aff77670F839ea425f5b78ab3Ae7" }, Comet: "0x3EE77595A8459e93C2888b13aDB354017B198188" }, goerli_weth: { cbETH: { contract: "0x2459f06a13ea0997d623224F362519bE71507258", priceFeed: "0xb79BbFE63309E036dDFa1BD44513d956BeE55c2a" }, wstETH: { contract: "0x4942BBAf745f235e525BAff49D31450810EDed5b", priceFeed: "0x5608d174a3B828abb4eE8b9B6a6433f2346c3E54" }, WETH: { contract: "0x42a71137C09AE83D8d05974960fd607d40033499", priceFeed: "0x1eb99992A2e3456ed2c8C6eD87E4c029bC679FeF" }, Comet: "0x9A539EEc489AAA03D588212a164d0abdB5F08F5F" }, mumbai_usdc: { DAI: { contract: "0x4DAFE12E1293D889221B1980672FE260Ac9dDd28", priceFeed: "0x0FCAa9c899EC5A91eBc3D5Dd869De833b06fB046" }, WETH: { contract: "0xE1e67212B1A4BF629Bdf828e08A3745307537ccE", priceFeed: "0x0715A7794a1dc8e42615F059dD6e406A6594651A" }, WBTC: { contract: "0x4B5A0F4E00bC0d6F16A593Cae27338972614E713", priceFeed: "0x007A22900a3B98143368Bd5906f8E17e9867581b" }, WMATIC: { contract: "0xfec23a9E1DBA805ADCF55E0338Bf5E03488FC7Fb", priceFeed: "0xd0D5e3DB44DE05E9F294BB0a3bEEaF030DE24Ada" }, USDC: { contract: "0xDB3cB4f2688daAB3BFf59C24cC42D4B6285828e9", priceFeed: "0x572dDec9087154dC5dfBB1546Bb62713147e0Ab0" }, Comet: "0xF09F0369aB0a875254fB565E52226c88f10Bc839" }, goerli_arbitrum_usdc: { LINK: { contract: "0xbb7303602bE1B9149B097aAFb094ffce1860E532", priceFeed: "0xd28Ba6CA3bB72bF371b80a2a0a33cBcf9073C954" }, WETH: { contract: "0xe39Ab88f8A4777030A534146A9Ca3B52bd5D43A3", priceFeed: "0x62CAe0FA2da220f43a51F86Db2EDb36DcA9A5A08" }, WBTC: { contract: "0x22d5e2dE578677791f6c90e0110Ec629be9d5Fb5", priceFeed: "0x6550bc2301936011c1334555e62A87705A81C12C" }, USDC: { contract: "0x8FB1E3fC51F3b789dED7557E680551d93Ea9d892", priceFeed: "0x1692Bdd32F31b831caAc1b0c9fAF68613682813b" }, Comet: "0x1d573274E19174260c5aCE3f2251598959d24456" }, goerli_optimism_usdc: { OP: { contract: "0x32719c5e2e35909C8f42167315445e349e749E05", priceFeed: "0xE882831E58eec48B7f304482771F67e6b846733D" }, WETH: { contract: "0x4200000000000000000000000000000000000006", priceFeed: "0x57241A37733983F97C4Ab06448F244A1E0Ca0ba8" }, WBTC: { contract: "0xe0a592353e81a94Db6E3226fD4A99F881751776a", priceFeed: "0xC16679B963CeB52089aD2d95312A5b85E318e9d2" }, USDC: { contract: "0x7E07E15D2a87A24492740D16f5bdF58c16db0c4E", priceFeed: "0x2636B223652d388721A0ED2861792DA9062D8C73" }, Comet: "0xb8F2f9C84ceD7bBCcc1Db6FB7bb1F19A9a4adfF4" }, goerli_base_usdc: { cbETH: { contract: "0x7c6b91D9Be155A6Db01f749217d76fF02A7227F2", priceFeed: "0xcD2A119bD1F7DF95d706DE6F2057fDD45A0503E2" }, WETH: { contract: "0x4200000000000000000000000000000000000006", priceFeed: "0xcD2A119bD1F7DF95d706DE6F2057fDD45A0503E2" }, USDC: { contract: "0x31D3A7711a74b4Ec970F50c3eaf1ee47ba803A95", priceFeed: "0xb85765935B4d9Ab6f841c9a00690Da5F34368bc0" }, Comet: "0xe78Fc55c884704F9485EDa042fb91BfE16fD55c1" }, goerli_base_weth: { cbETH: { contract: "0x7c6b91D9Be155A6Db01f749217d76fF02A7227F2", priceFeed: "0x5B0156A396BdFc2eb814D945Ac99C40A0F8592B2" }, WETH: { contract: "0x4200000000000000000000000000000000000006", priceFeed: "0x22738A450dDA849BedDFcA219739a5d72dfB3Ec6" }, Comet: "0xED94f3052638620fE226a9661ead6a39C2a265bE" }, fuji_usdc: { WBTC_e: { contract: "0xfa78400e01Fc9da830Cb2F13B3e7E18F813414Ff", priceFeed: "0x31CF013A08c6Ac228C94551d535d5BAfE19c602a" }, WAVAX: { contract: "0xA2c25E48269e3f89A60b2CC8e02AAfEeB3BAb761", priceFeed: "0x5498BB86BC934c8D34FDA08E81D444153d0D06aD" }, USDC: { contract: "0x4fed3d02D095f7D92AF161311fA6Ef23dc8dA040", priceFeed: "0x7898AcCC83587C3C55116c5230C17a6Cd9C71bad" }, Comet: "0x59BF4753899C20EA152dEefc6f6A14B2a5CC3021" } }, collaterals: { mainnet_usdc: ["COMP", "WBTC", "WETH", "UNI", "LINK", "USDC"], mainnet_weth: ["cbETH", "wstETH", "WETH"], polygon_usdc: ["WETH", "WBTC", "WMATIC", "MaticX", "USDC"], arbitrum_usdc: ["ARB", "GMX", "WETH", "WBTC", "USDC"], base_usdbc: ["cbETH", "WETH", "USDbC"], base_weth: ["cbETH", "WETH"], goerli_usdc: ["COMP", "WBTC", "WETH", "LINK", "USDC"], goerli_weth: ["cbETH", "wstETH", "WETH"], mumbai_usdc: ["DAI", "WETH", "WBTC", "WMATIC", "USDC"], goerli_arbitrum_usdc: ["LINK", "WETH", "WBTC", "USDC"], goerli_optimism_usdc: ["OP", "WETH", "WBTC", "USDC"], goerli_base_usdc: ["cbETH", "WETH", "USDC"], goerli_base_weth: ["cbETH", "WETH"], fuji_usdc: ["WBTC_e", "WAVAX", "USDC"] }, base: { mainnet_usdc: "USDC", mainnet_weth: "WETH", polygon_usdc: "USDC", arbitrum_usdc: "USDC", base_usdbc: "USDbC", base_weth: "WETH", goerli_usdc: "USDC", goerli_weth: "WETH", mumbai_usdc: "USDC", goerli_arbitrum_usdc: "USDC", goerli_optimism_usdc: "USDC", goerli_base_usdc: "USDC", goerli_base_weth: "WETH", fuji_usdc: "USDC" }};
394
+
395
+ // src/protocols/evm/compound-v3/compoundJs.ts
396
+ var INSTANCE_CHAIN_ID = {
397
+ mainnet_usdc: 1,
398
+ mainnet_weth: 1,
399
+ polygon_usdc: 137,
400
+ arbitrum_usdc: 42161,
401
+ base_usdbc: 8453,
402
+ base_weth: 8453
403
+ };
404
+ function asAddressMap() {
405
+ return comet_constants_default.address;
406
+ }
407
+ function listCompoundJsCometInstances() {
408
+ const address = asAddressMap();
409
+ const base = comet_constants_default.base;
410
+ const collaterals = comet_constants_default.collaterals;
411
+ const out = [];
412
+ for (const [instanceId, contracts] of Object.entries(address)) {
413
+ if (instanceId.startsWith("goerli_") || instanceId.startsWith("mumbai_") || instanceId.startsWith("fuji_")) {
414
+ continue;
415
+ }
416
+ const chainId = INSTANCE_CHAIN_ID[instanceId];
417
+ const cometRaw = contracts.Comet;
418
+ if (typeof cometRaw !== "string" || chainId == null) continue;
419
+ out.push({
420
+ instanceId,
421
+ chainId,
422
+ comet: viem.getAddress(cometRaw),
423
+ baseSymbol: base[instanceId] ?? instanceId,
424
+ collateralSymbols: collaterals[instanceId] ?? []
425
+ });
426
+ }
427
+ return out;
428
+ }
429
+ function compoundJsCometAddress(instanceId) {
430
+ const row = asAddressMap()[instanceId];
431
+ const comet = row?.Comet;
432
+ if (typeof comet !== "string") return null;
433
+ return viem.getAddress(comet);
434
+ }
435
+ function compoundJsCollateralAddresses(instanceId) {
436
+ const row = asAddressMap()[instanceId];
437
+ const names = comet_constants_default.collaterals[instanceId] ?? [];
438
+ const out = [];
439
+ for (const name of names) {
440
+ const entry = row?.[name];
441
+ const contract = typeof entry === "string" ? entry : entry?.contract;
442
+ if (!contract) continue;
443
+ out.push(viem.getAddress(contract));
444
+ }
445
+ return out;
446
+ }
447
+ function compoundJsAgreesWithOfficial(instanceId, officialComet) {
448
+ const js = compoundJsCometAddress(instanceId);
449
+ if (!js) return false;
450
+ return js === viem.getAddress(officialComet);
451
+ }
452
+
453
+ // src/protocols/evm/compound-v3/apr.ts
454
+ var COMPOUND_V3_SECONDS_PER_YEAR = 365 * 24 * 60 * 60;
455
+ var COMPOUND_V3_FACTOR_SCALE = 10n ** 18n;
456
+ function compoundV3RatePerSecondToAprDecimal(ratePerSecond) {
457
+ if (ratePerSecond <= 0n) return 0;
458
+ return Number(ratePerSecond) / 1e18 * COMPOUND_V3_SECONDS_PER_YEAR;
459
+ }
460
+ function compoundV3AprToPercentLabel(aprDecimal) {
461
+ if (!Number.isFinite(aprDecimal)) return "\u2014";
462
+ const pct = aprDecimal * 100;
463
+ if (Math.abs(pct) < 1e-3) return "0.00%";
464
+ return `${pct.toFixed(2)}%`;
465
+ }
466
+ function compoundV3UtilizationToDecimal(utilization) {
467
+ if (utilization <= 0n) return 0;
468
+ return Number(utilization) / 1e18;
469
+ }
470
+ function compoundV3FactorToPercent(factor) {
471
+ return Number(factor) / 1e16;
472
+ }
473
+
474
+ // src/protocols/evm/compound-v3/subgraph.ts
475
+ var COMPOUND_V3_SUBGRAPH_BY_CHAIN = {
476
+ 1: "5nwMCSHaTqG3Kd2gHznbTXEnZ9QNWsssQfbHhDqQSQFp",
477
+ 137: "AaFtUWKfFdj2x8nnE3RxTSJkHwGHvawH3VWFBykCGzLs",
478
+ 42161: "Ff7ha9ELmpmg81D6nYxy4t8aGP26dPztqD1LDJNPqjLS",
479
+ 8453: "2hcXhs36pTBDVUmk5K2Zkr6N4UYGwaHuco2a6jyTsijo",
480
+ 10: "FhHNkfh5z6Z2WCEBxB6V3s8RPxnJfWZ9zAfM5bVvbvbb"
481
+ };
482
+ function compoundV3SubgraphIdForChain(chainId) {
483
+ return COMPOUND_V3_SUBGRAPH_BY_CHAIN[chainId] ?? null;
484
+ }
485
+ async function fetchCompoundV3SubgraphMarkets(args) {
486
+ const id = compoundV3SubgraphIdForChain(args.chainId);
487
+ const apiKey = (args.apiKey ?? process.env.THE_GRAPH_API_KEY ?? "").trim();
488
+ if (!id || !apiKey) return null;
489
+ const url = `https://gateway.thegraph.com/api/${apiKey}/subgraphs/id/${id}`;
490
+ try {
491
+ const res = await fetch(url, {
492
+ method: "POST",
493
+ headers: { "content-type": "application/json" },
494
+ body: JSON.stringify({
495
+ query: `query CompoundV3Markets { markets(first: 50) { id } }`
496
+ })
497
+ });
498
+ if (!res.ok) return null;
499
+ const json = await res.json();
500
+ const markets = json.data?.markets;
501
+ if (!markets) return null;
502
+ return markets.map((m) => ({ id: m.id, comet: m.id }));
503
+ } catch {
504
+ return null;
505
+ }
506
+ }
507
+ function publicClient(rpcUrl, chainId) {
508
+ const chain = viem.defineChain({
509
+ id: chainId,
510
+ name: "Destination",
511
+ nativeCurrency: { decimals: 18, name: "Ether", symbol: "ETH" },
512
+ rpcUrls: { default: { http: [rpcUrl] } }
513
+ });
514
+ return viem.createPublicClient({ chain, transport: viem.http(rpcUrl) });
515
+ }
516
+ async function readTokenMeta(client, asset) {
517
+ const [symbol, decimals] = await Promise.all([
518
+ client.readContract({ address: asset, abi: erc20ReadAbi, functionName: "symbol" }).catch(() => "TOKEN"),
519
+ client.readContract({ address: asset, abi: erc20ReadAbi, functionName: "decimals" }).catch(() => 18)
520
+ ]);
521
+ return { symbol: String(symbol), decimals: Number(decimals) };
522
+ }
523
+ async function enrichMarketOnChain(client, market) {
524
+ const comet = market.comet;
525
+ const [baseToken, utilization, numAssets, decimals] = await Promise.all([
526
+ client.readContract({ address: comet, abi: cometInterfaceAbi, functionName: "baseToken" }),
527
+ client.readContract({ address: comet, abi: cometInterfaceAbi, functionName: "getUtilization" }),
528
+ client.readContract({ address: comet, abi: cometInterfaceAbi, functionName: "numAssets" }),
529
+ client.readContract({ address: comet, abi: cometInterfaceAbi, functionName: "decimals" })
530
+ ]);
531
+ const [supplyRate, borrowRate, baseMeta, baseFeed] = await Promise.all([
532
+ client.readContract({
533
+ address: comet,
534
+ abi: cometInterfaceAbi,
535
+ functionName: "getSupplyRate",
536
+ args: [utilization]
537
+ }),
538
+ client.readContract({
539
+ address: comet,
540
+ abi: cometInterfaceAbi,
541
+ functionName: "getBorrowRate",
542
+ args: [utilization]
543
+ }),
544
+ readTokenMeta(client, viem.getAddress(baseToken)),
545
+ client.readContract({ address: comet, abi: cometInterfaceAbi, functionName: "baseTokenPriceFeed" })
546
+ ]);
547
+ const basePrice = await client.readContract({ address: comet, abi: cometInterfaceAbi, functionName: "getPrice", args: [baseFeed] }).catch(() => 0n);
548
+ const assets = [
549
+ {
550
+ asset: viem.getAddress(baseToken),
551
+ symbol: baseMeta.symbol,
552
+ decimals: Number(decimals) || baseMeta.decimals,
553
+ borrowCollateralFactorPercent: 0,
554
+ liquidateCollateralFactorPercent: 0,
555
+ priceRaw: basePrice.toString(),
556
+ role: "base"
557
+ }
558
+ ];
559
+ const n = Number(numAssets);
560
+ for (let i = 0; i < n; i++) {
561
+ const info = await client.readContract({
562
+ address: comet,
563
+ abi: cometInterfaceAbi,
564
+ functionName: "getAssetInfo",
565
+ args: [i]
566
+ });
567
+ const token = viem.getAddress(info.asset);
568
+ const meta = await readTokenMeta(client, token);
569
+ const price = await client.readContract({ address: comet, abi: cometInterfaceAbi, functionName: "getPrice", args: [info.priceFeed] }).catch(() => 0n);
570
+ assets.push({
571
+ asset: token,
572
+ symbol: meta.symbol,
573
+ decimals: meta.decimals,
574
+ borrowCollateralFactorPercent: compoundV3FactorToPercent(info.borrowCollateralFactor),
575
+ liquidateCollateralFactorPercent: compoundV3FactorToPercent(info.liquidateCollateralFactor),
576
+ priceRaw: price.toString(),
577
+ role: "collateral"
578
+ });
579
+ }
580
+ return {
581
+ chainId: market.chainId,
582
+ slug: market.slug,
583
+ symbol: market.symbol,
584
+ comet: market.comet,
585
+ rewards: market.rewards,
586
+ bulker: market.bulker,
587
+ baseToken: viem.getAddress(baseToken),
588
+ utilization: compoundV3UtilizationToDecimal(utilization),
589
+ supplyAprPercent: compoundV3AprToPercentLabel(compoundV3RatePerSecondToAprDecimal(supplyRate)),
590
+ borrowAprPercent: compoundV3AprToPercentLabel(compoundV3RatePerSecondToAprDecimal(borrowRate)),
591
+ assets
592
+ };
593
+ }
594
+ function registryMarketRow(market) {
595
+ return {
596
+ chainId: market.chainId,
597
+ slug: market.slug,
598
+ symbol: market.symbol,
599
+ comet: market.comet,
600
+ rewards: market.rewards,
601
+ bulker: market.bulker,
602
+ baseToken: market.baseToken ?? null,
603
+ utilization: null,
604
+ supplyAprPercent: null,
605
+ borrowAprPercent: null,
606
+ assets: market.baseToken ? [
607
+ {
608
+ asset: market.baseToken,
609
+ symbol: market.slug.toUpperCase(),
610
+ decimals: 18,
611
+ borrowCollateralFactorPercent: 0,
612
+ liquidateCollateralFactorPercent: 0,
613
+ priceRaw: "0",
614
+ role: "base"
615
+ }
616
+ ] : []
617
+ };
618
+ }
619
+ async function compoundV3FetchMarketsSummary(args) {
620
+ if (!isCompoundV3ChainSupported(args.chainId)) {
621
+ return { markets: [], notes: `Compound III is not deployed on chain ${args.chainId}.` };
622
+ }
623
+ const registry = listCompoundV3MarketsForChain(args.chainId);
624
+ let subgraphNote = "";
625
+ const subgraph = await fetchCompoundV3SubgraphMarkets({ chainId: args.chainId });
626
+ if (subgraph) {
627
+ subgraphNote = ` Subgraph listed ${subgraph.length} market id(s); official comet deployments are the address source.`;
628
+ }
629
+ if (!args.rpcUrl?.trim()) {
630
+ return {
631
+ markets: registry.map(registryMarketRow),
632
+ notes: "Registry from official comet deployments. Pass rpcUrl (MCP server injects it) to enrich APRs and collaterals." + subgraphNote
633
+ };
634
+ }
635
+ const client = publicClient(args.rpcUrl, args.chainId);
636
+ const markets = [];
637
+ for (const row of registry) {
638
+ try {
639
+ markets.push(await enrichMarketOnChain(client, row));
640
+ } catch {
641
+ markets.push(registryMarketRow(row));
642
+ }
643
+ }
644
+ return {
645
+ markets,
646
+ notes: "Comet proxy addresses from official deployments; rates and collaterals from on-chain CometInterface." + subgraphNote
647
+ };
648
+ }
649
+ async function compoundV3FetchMarketSummary(args) {
650
+ if (!args.rpcUrl?.trim()) {
651
+ throw new Error("rpcUrl is required for ctm_compound_v3_fetch_market (MCP server injects it from the chain registry).");
652
+ }
653
+ const market = getCompoundV3MarketByComet(args.chainId, args.comet);
654
+ if (!market) {
655
+ throw new Error(`Unknown Compound III Comet ${args.comet} on chain ${args.chainId}.`);
656
+ }
657
+ const client = publicClient(args.rpcUrl, args.chainId);
658
+ return enrichMarketOnChain(client, market);
659
+ }
660
+ async function compoundV3FetchAccountSummary(args) {
661
+ if (!args.rpcUrl?.trim()) {
662
+ throw new Error(
663
+ "rpcUrl is required for ctm_compound_v3_fetch_account (MCP server injects it from the chain registry)."
664
+ );
665
+ }
666
+ const market = getCompoundV3MarketByComet(args.chainId, args.comet);
667
+ if (!market) {
668
+ throw new Error(`Unknown Compound III Comet ${args.comet} on chain ${args.chainId}.`);
669
+ }
670
+ const client = publicClient(args.rpcUrl, args.chainId);
671
+ const comet = market.comet;
672
+ const account = viem.getAddress(args.account);
673
+ const [baseToken, decimals, supplied, borrowed, numAssets, collateralized, liquidatable] = await Promise.all([
674
+ client.readContract({ address: comet, abi: cometInterfaceAbi, functionName: "baseToken" }),
675
+ client.readContract({ address: comet, abi: cometInterfaceAbi, functionName: "decimals" }),
676
+ client.readContract({ address: comet, abi: cometInterfaceAbi, functionName: "balanceOf", args: [account] }),
677
+ client.readContract({
678
+ address: comet,
679
+ abi: cometInterfaceAbi,
680
+ functionName: "borrowBalanceOf",
681
+ args: [account]
682
+ }),
683
+ client.readContract({ address: comet, abi: cometInterfaceAbi, functionName: "numAssets" }),
684
+ client.readContract({
685
+ address: comet,
686
+ abi: cometInterfaceAbi,
687
+ functionName: "isBorrowCollateralized",
688
+ args: [account]
689
+ }),
690
+ client.readContract({
691
+ address: comet,
692
+ abi: cometInterfaceAbi,
693
+ functionName: "isLiquidatable",
694
+ args: [account]
695
+ })
696
+ ]);
697
+ const baseMeta = await readTokenMeta(client, viem.getAddress(baseToken));
698
+ const dec = Number(decimals) || baseMeta.decimals;
699
+ const collaterals = [];
700
+ const n = Number(numAssets);
701
+ for (let i = 0; i < n; i++) {
702
+ const info = await client.readContract({
703
+ address: comet,
704
+ abi: cometInterfaceAbi,
705
+ functionName: "getAssetInfo",
706
+ args: [i]
707
+ });
708
+ const token = viem.getAddress(info.asset);
709
+ const bal = await client.readContract({
710
+ address: comet,
711
+ abi: cometInterfaceAbi,
712
+ functionName: "collateralBalanceOf",
713
+ args: [account, token]
714
+ });
715
+ const meta = await readTokenMeta(client, token);
716
+ collaterals.push({
717
+ asset: token,
718
+ symbol: meta.symbol,
719
+ balance: viem.formatUnits(bal, meta.decimals)
720
+ });
721
+ }
722
+ let rewardToken = null;
723
+ let rewardOwed = null;
724
+ try {
725
+ const owed = await client.readContract({
726
+ address: market.rewards,
727
+ abi: cometRewardsAbi,
728
+ functionName: "getRewardOwed",
729
+ args: [comet, account]
730
+ });
731
+ rewardToken = viem.getAddress(owed.token);
732
+ const rewardMeta = await readTokenMeta(client, viem.getAddress(owed.token));
733
+ rewardOwed = viem.formatUnits(owed.owed, rewardMeta.decimals);
734
+ } catch {
735
+ rewardToken = null;
736
+ rewardOwed = null;
737
+ }
738
+ return {
739
+ comet,
740
+ symbol: market.symbol,
741
+ baseSupplied: viem.formatUnits(supplied, dec),
742
+ baseBorrowed: viem.formatUnits(borrowed, dec),
743
+ collaterals,
744
+ isBorrowCollateralized: Boolean(collateralized),
745
+ isLiquidatable: Boolean(liquidatable),
746
+ rewardToken,
747
+ rewardOwed
748
+ };
749
+ }
750
+ var chainAssetCache = /* @__PURE__ */ new Map();
751
+ function compoundV3KeyForNodeAssetRow(args) {
752
+ if (isNativeAssetAddress(args.contractAddress)) {
753
+ const wrapped = compoundV3WrappedNative(args.chainId);
754
+ return (wrapped ?? viem.zeroAddress).toLowerCase();
755
+ }
756
+ return viem.getAddress(args.contractAddress).toLowerCase();
757
+ }
758
+ async function ensureCompoundV3ChainAssetCache(args) {
759
+ const existing = chainAssetCache.get(args.chainId);
760
+ if (existing && existing.size > 0 && !args.rpcUrl) return existing;
761
+ const map = /* @__PURE__ */ new Map();
762
+ const add = (address, role) => {
763
+ const key = viem.getAddress(address).toLowerCase();
764
+ const cur = map.get(key) ?? { base: false, collateral: false };
765
+ cur[role] = true;
766
+ map.set(key, cur);
767
+ };
768
+ if (args.rpcUrl?.trim()) {
769
+ try {
770
+ const { markets } = await compoundV3FetchMarketsSummary({ chainId: args.chainId, rpcUrl: args.rpcUrl });
771
+ for (const m of markets) {
772
+ for (const a of m.assets) add(a.asset, a.role === "base" ? "base" : "collateral");
773
+ }
774
+ chainAssetCache.set(args.chainId, map);
775
+ return map;
776
+ } catch {
777
+ }
778
+ }
779
+ for (const m of listCompoundV3MarketsForChain(args.chainId)) {
780
+ if (m.baseToken) add(m.baseToken, "base");
781
+ }
782
+ chainAssetCache.set(args.chainId, map);
783
+ return map;
784
+ }
785
+ function getCompoundV3AssetModesFromCache(chainId, contractAddress) {
786
+ const cache = chainAssetCache.get(chainId);
787
+ if (!cache) return null;
788
+ const key = compoundV3KeyForNodeAssetRow({ contractAddress, chainId });
789
+ return cache.get(key) ?? null;
790
+ }
791
+ function listCompoundV3MarketsForAsset(args) {
792
+ const key = compoundV3KeyForNodeAssetRow({ contractAddress: args.contractAddress, chainId: args.chainId });
793
+ return listCompoundV3MarketsForChain(args.chainId).filter((m) => {
794
+ if (m.baseToken && m.baseToken.toLowerCase() === key) return true;
795
+ const modes = chainAssetCache.get(args.chainId)?.get(key);
796
+ return Boolean(modes?.base || modes?.collateral);
797
+ });
798
+ }
799
+
800
+ // src/core/purpose.ts
801
+ function mergePurposeText(purposeText, purposeSuffix) {
802
+ const t = (purposeText ?? "").trim();
803
+ const suffix = (purposeSuffix ?? "").trim();
804
+ if (!suffix) return t;
805
+ return t ? `${t}
806
+
807
+ ${suffix}` : suffix;
808
+ }
809
+
810
+ // src/core/envelope.ts
811
+ function finalizeMultisign(input) {
812
+ const { keyGen, destinationChainID, legs } = input;
813
+ if (legs.length === 0) {
814
+ throw new Error("finalizeMultisign requires at least one leg");
815
+ }
816
+ const ph = (keyGen.pubkeyhex ?? "").trim();
817
+ if (!ph) throw new Error("keyGen pubKey (pubkeyhex) is required");
818
+ const keyList = keyGen.keylist ?? [];
819
+ const clientId = continuumNodeSdk.getClientIdFromKeyGenResult(keyGen);
820
+ const first = legs[0];
821
+ const messageHashes = legs.map((l) => l.msgHash);
822
+ const messageRawBatch = legs.map((l) => l.msgRaw);
823
+ const batchMeta = legs.map((l) => ({
824
+ destinationAddress: l.destinationAddress,
825
+ signatureText: l.signatureText,
826
+ ...l.audit
827
+ }));
828
+ const proposalTxParams = legs.map((l) => l.proposalTxParams).filter((p) => p != null && typeof p === "object");
829
+ const extraPayload = {
830
+ batchMeta,
831
+ ...input.extraJSON ?? {}
832
+ };
833
+ const extraJSON = JSON.stringify(extraPayload, (_, v) => typeof v === "bigint" ? v.toString() : v);
834
+ const bodyForSign = {
835
+ keyList,
836
+ pubKey: ph,
837
+ msgHash: messageHashes[0],
838
+ msgRaw: first.msgRaw,
839
+ destinationChainID,
840
+ destinationAddress: input.destinationAddress ?? first.destinationAddress,
841
+ extraJSON,
842
+ signatureText: first.signatureText,
843
+ purpose: mergePurposeText(input.purposeText, input.purposeSuffix),
844
+ ...first.feeSnapshot
845
+ };
846
+ if (legs.length > 1) {
847
+ bodyForSign.messageHashes = messageHashes;
848
+ bodyForSign.messageRawBatch = messageRawBatch;
849
+ }
850
+ if (proposalTxParams.length > 0) {
851
+ bodyForSign.proposalTxParams = proposalTxParams;
852
+ }
853
+ const valueWei = first.valueWei;
854
+ if (valueWei != null && valueWei > 0n) {
855
+ bodyForSign.value = valueWei.toString();
856
+ }
857
+ if (clientId) bodyForSign.clientId = clientId;
858
+ if (input.expiryDate != null && input.expiryDate > 0) {
859
+ bodyForSign.expiryDate = Math.floor(input.expiryDate);
860
+ }
861
+ return { bodyForSign, messageToSign: JSON.stringify(bodyForSign) };
862
+ }
863
+ function routerSwapGasLimitFromEstimate(estimatedGas, chainGasLimit) {
864
+ if (chainGasLimit != null && Number.isFinite(chainGasLimit) && chainGasLimit > 0) {
865
+ return continuumNodeSdk.gasLimitFromEstimateAndChainConfig(estimatedGas, chainGasLimit);
866
+ }
867
+ return (estimatedGas * 12n + 9n) / 10n;
868
+ }
869
+
870
+ // src/chains/evm/buildBatch.ts
871
+ async function buildEvmMultisignBatch(args) {
872
+ const { context, steps } = args;
873
+ const {
874
+ chainId,
875
+ rpcUrl,
876
+ executorAddress,
877
+ chainDetail,
878
+ useCustomGas,
879
+ customGasChainDetails,
880
+ keyGen,
881
+ purposeText
882
+ } = context;
883
+ if (steps.length === 0) throw new Error("buildEvmMultisignBatch requires at least one step");
884
+ const ch = viem.defineChain({
885
+ id: chainId,
886
+ name: "Destination",
887
+ nativeCurrency: { decimals: 18, name: "Ether", symbol: "ETH" },
888
+ rpcUrls: { default: { http: [rpcUrl] } }
889
+ });
890
+ const publicClient2 = viem.createPublicClient({ chain: ch, transport: viem.http(rpcUrl) });
891
+ const feeParams = await continuumNodeSdk.fetchChainFeeParams(rpcUrl, chainId);
892
+ const legacy = Boolean(chainDetail?.legacy) || !feeParams.isEip1559;
893
+ const latestBaseFeeWei = !legacy ? (await publicClient2.getBlock({ blockTag: "latest" })).baseFeePerGas ?? 0n : 0n;
894
+ const gasLimitConfig = useCustomGas && chainDetail?.gasLimit != null ? Number(chainDetail.gasLimit) : void 0;
895
+ const chainGasLimitRouter = chainDetail?.gasLimit != null && Number.isFinite(Number(chainDetail.gasLimit)) && Number(chainDetail.gasLimit) > 0 ? Number(chainDetail.gasLimit) : void 0;
896
+ const gasFeeMultiplier = useCustomGas && chainDetail?.gasMultiplier != null ? Number(chainDetail.gasMultiplier) : void 0;
897
+ const executor = viem.getAddress(executorAddress);
898
+ const baseNonce = await publicClient2.getTransactionCount({ address: executor, blockTag: "pending" });
899
+ const legs = [];
900
+ for (let i = 0; i < steps.length; i++) {
901
+ const step = steps[i];
902
+ const currentNonce = baseNonce + i;
903
+ let estimatedGas;
904
+ if (args.estimateGasForStep) {
905
+ estimatedGas = await args.estimateGasForStep({ step, index: i, publicClient: publicClient2, executor });
906
+ } else {
907
+ try {
908
+ estimatedGas = await publicClient2.estimateGas({
909
+ to: step.to,
910
+ data: step.data,
911
+ value: step.value,
912
+ account: executor
913
+ });
914
+ } catch {
915
+ estimatedGas = step.fallbackGas ?? 100000n;
916
+ }
917
+ }
918
+ let gasLimitI;
919
+ if (args.resolveGasLimit) {
920
+ gasLimitI = await args.resolveGasLimit({ step, index: i, estimatedGas, publicClient: publicClient2 });
921
+ } else if (step.routerSwap) {
922
+ gasLimitI = routerSwapGasLimitFromEstimate(estimatedGas, chainGasLimitRouter);
923
+ } else {
924
+ gasLimitI = useCustomGas ? continuumNodeSdk.gasLimitFromEstimateAndChainConfig(estimatedGas, gasLimitConfig) : estimatedGas;
925
+ }
926
+ let proposalTxParams;
927
+ let feeSnapshot;
928
+ let serialized;
929
+ if (legacy) {
930
+ let gasPriceWei = await publicClient2.getGasPrice();
931
+ if (useCustomGas && gasFeeMultiplier != null && gasFeeMultiplier > 0) {
932
+ gasPriceWei = gasPriceWei * BigInt(100 + gasFeeMultiplier) / 100n;
933
+ }
934
+ if (useCustomGas && chainDetail?.gasPrice != null && chainDetail.gasPrice > 0) {
935
+ const configured = viem.parseGwei(continuumNodeSdk.gweiToDecimalString(Number(chainDetail.gasPrice)));
936
+ if (configured > gasPriceWei) gasPriceWei = configured;
937
+ }
938
+ serialized = viem.serializeTransaction({
939
+ type: "legacy",
940
+ to: step.to,
941
+ data: step.data,
942
+ value: step.value,
943
+ gas: gasLimitI,
944
+ gasPrice: gasPriceWei,
945
+ nonce: currentNonce,
946
+ chainId
947
+ });
948
+ proposalTxParams = {
949
+ nonce: currentNonce,
950
+ gasLimit: gasLimitI.toString(),
951
+ txType: "legacy",
952
+ gasPrice: gasPriceWei.toString()
953
+ };
954
+ feeSnapshot = continuumNodeSdk.proposalTxParamsToFeeSnapshot(proposalTxParams);
955
+ } else {
956
+ const fetchedBase = feeParams.baseFeeGwei ?? 0;
957
+ const fetchedPriority = feeParams.priorityFeeGwei ?? 0;
958
+ const configuredBase = useCustomGas && chainDetail?.baseFee != null ? Number(chainDetail.baseFee) : 0;
959
+ const configuredPriority = useCustomGas && chainDetail?.priorityFee != null ? Number(chainDetail.priorityFee) : 0;
960
+ const effectiveBaseFeeGwei = Math.max(fetchedBase, configuredBase);
961
+ const effectivePriorityFeeGwei = Math.max(fetchedPriority, configuredPriority);
962
+ const baseFeeMultiplierPct = useCustomGas && chainDetail?.baseFeeMultiplier != null ? Math.max(100, Number(chainDetail.baseFeeMultiplier)) : 100;
963
+ const baseComponentGwei = effectiveBaseFeeGwei * baseFeeMultiplierPct / 100;
964
+ const maxFeePerGasGwei = baseComponentGwei + effectivePriorityFeeGwei;
965
+ let maxPriorityFeePerGas = effectivePriorityFeeGwei > 0 ? viem.parseGwei(continuumNodeSdk.gweiToDecimalString(effectivePriorityFeeGwei)) : viem.parseGwei("1");
966
+ let maxFeePerGas = viem.parseGwei(continuumNodeSdk.gweiToDecimalString(maxFeePerGasGwei));
967
+ if (useCustomGas && gasFeeMultiplier != null && gasFeeMultiplier > 0) {
968
+ maxPriorityFeePerGas = maxPriorityFeePerGas * BigInt(100 + gasFeeMultiplier) / 100n;
969
+ maxFeePerGas = maxFeePerGas * BigInt(100 + gasFeeMultiplier) / 100n;
970
+ }
971
+ ({ maxFeePerGas, maxPriorityFeePerGas } = continuumNodeSdk.alignEip1559FeesWithLatestBase(
972
+ maxFeePerGas,
973
+ maxPriorityFeePerGas,
974
+ latestBaseFeeWei
975
+ ));
976
+ serialized = viem.serializeTransaction({
977
+ type: "eip1559",
978
+ to: step.to,
979
+ data: step.data,
980
+ value: step.value,
981
+ gas: gasLimitI,
982
+ maxFeePerGas,
983
+ maxPriorityFeePerGas,
984
+ nonce: currentNonce,
985
+ chainId
986
+ });
987
+ proposalTxParams = {
988
+ nonce: currentNonce,
989
+ gasLimit: gasLimitI.toString(),
990
+ txType: "eip1559",
991
+ maxFeePerGas: maxFeePerGas.toString(),
992
+ maxPriorityFeePerGas: maxPriorityFeePerGas.toString()
993
+ };
994
+ feeSnapshot = i === 0 ? continuumNodeSdk.proposalTxParamsToFeeSnapshot(proposalTxParams) : {};
995
+ }
996
+ const h = viem.keccak256(serialized);
997
+ const msgHash = h.startsWith("0x") ? h.slice(2) : h;
998
+ const batchMetaExtra = args.buildBatchMeta({ step, index: i, gasLimit: gasLimitI });
999
+ legs.push({
1000
+ msgHash,
1001
+ msgRaw: i === 0 && args.firstMsgRawNo0x != null ? args.firstMsgRawNo0x : serialized,
1002
+ destinationAddress: step.to,
1003
+ signatureText: typeof batchMetaExtra.signatureText === "string" ? batchMetaExtra.signatureText : JSON.stringify(batchMetaExtra.signatureText ?? {}),
1004
+ audit: batchMetaExtra,
1005
+ feeSnapshot: i === 0 ? feeSnapshot : {},
1006
+ proposalTxParams,
1007
+ valueWei: i === 0 ? step.value : void 0
1008
+ });
1009
+ if (i === 0 && args.firstMsgRawNo0x != null) {
1010
+ legs[0].msgRaw = args.firstMsgRawNo0x;
1011
+ }
1012
+ }
1013
+ const extraJSON = {};
1014
+ if (useCustomGas && customGasChainDetails && Object.keys(customGasChainDetails).length > 0) {
1015
+ extraJSON.customGasChainDetails = customGasChainDetails;
1016
+ }
1017
+ const result = finalizeMultisign({
1018
+ keyGen,
1019
+ purposeText,
1020
+ purposeSuffix: args.purposeSuffix,
1021
+ destinationChainID: String(chainId),
1022
+ destinationAddress: args.destinationAddress ?? steps[0].to,
1023
+ legs,
1024
+ extraJSON: Object.keys(extraJSON).length > 0 ? extraJSON : void 0,
1025
+ expiryDate: context.expiryDate
1026
+ });
1027
+ const pv = args.payableValueWei;
1028
+ if (pv != null && pv > 0n) {
1029
+ result.bodyForSign.value = pv.toString();
1030
+ }
1031
+ return result;
1032
+ }
1033
+ function createCompoundV3PublicClient(rpcUrl, chainId) {
1034
+ const chain = viem.defineChain({
1035
+ id: chainId,
1036
+ name: "Destination",
1037
+ nativeCurrency: { decimals: 18, name: "Ether", symbol: "ETH" },
1038
+ rpcUrls: { default: { http: [rpcUrl] } }
1039
+ });
1040
+ return viem.createPublicClient({ chain, transport: viem.http(rpcUrl) });
1041
+ }
1042
+ async function pushApproveIfNeeded(args) {
1043
+ const current = await args.client.readContract({
1044
+ address: args.token,
1045
+ abi: erc20ReadAbi,
1046
+ functionName: "allowance",
1047
+ args: [viem.getAddress(args.owner), viem.getAddress(args.spender)]
1048
+ });
1049
+ if (current >= args.amountWei) return;
1050
+ if (current > 0n) {
1051
+ args.steps.push({
1052
+ kind: "approve",
1053
+ to: args.token,
1054
+ data: viem.encodeFunctionData({
1055
+ abi: erc20ApproveAbi,
1056
+ functionName: "approve",
1057
+ args: [viem.getAddress(args.spender), 0n]
1058
+ }),
1059
+ value: 0n
1060
+ });
1061
+ }
1062
+ args.steps.push({
1063
+ kind: "approve",
1064
+ to: args.token,
1065
+ data: viem.encodeFunctionData({
1066
+ abi: erc20ApproveAbi,
1067
+ functionName: "approve",
1068
+ args: [viem.getAddress(args.spender), args.amountWei]
1069
+ }),
1070
+ value: 0n
1071
+ });
1072
+ }
1073
+
1074
+ // src/protocols/evm/compound-v3/multisign.ts
1075
+ var WETH_DEPOSIT_FALLBACK = 120000n;
1076
+ var WETH_WITHDRAW_FALLBACK = 80000n;
1077
+ var ERC20_APPROVE_FALLBACK = 100000n;
1078
+ var COMET_SUPPLY_FALLBACK = 500000n;
1079
+ var COMET_WITHDRAW_FALLBACK = 600000n;
1080
+ var REWARDS_CLAIM_FALLBACK = 250000n;
1081
+ function fallbackGas(kind) {
1082
+ if (kind === "weth_deposit") return WETH_DEPOSIT_FALLBACK;
1083
+ if (kind === "weth_withdraw") return WETH_WITHDRAW_FALLBACK;
1084
+ if (kind === "approve") return ERC20_APPROVE_FALLBACK;
1085
+ if (kind === "withdraw") return COMET_WITHDRAW_FALLBACK;
1086
+ if (kind === "claim") return REWARDS_CLAIM_FALLBACK;
1087
+ return COMET_SUPPLY_FALLBACK;
1088
+ }
1089
+ function finishBatch(args) {
1090
+ const evmSteps = args.steps.map((s) => ({
1091
+ to: s.to,
1092
+ data: s.data,
1093
+ value: s.value,
1094
+ fallbackGas: fallbackGas(s.kind)
1095
+ }));
1096
+ const first = evmSteps[0];
1097
+ if (!first) throw new Error("Compound III batch has no steps.");
1098
+ const firstDataNo0x = first.data.startsWith("0x") ? first.data.slice(2) : first.data;
1099
+ return buildEvmMultisignBatch({
1100
+ context: {
1101
+ chainCategory: "evm",
1102
+ keyGen: args.common.keyGen,
1103
+ purposeText: args.common.purposeText,
1104
+ chainId: args.common.chainId,
1105
+ rpcUrl: args.common.rpcUrl,
1106
+ executorAddress: viem.getAddress(args.common.executorAddress),
1107
+ chainDetail: args.common.chainDetail,
1108
+ useCustomGas: args.common.useCustomGas,
1109
+ customGasChainDetails: args.common.customGasChainDetails
1110
+ },
1111
+ steps: evmSteps,
1112
+ purposeSuffix: args.purposeSuffix,
1113
+ firstMsgRawNo0x: firstDataNo0x,
1114
+ destinationAddress: first.to,
1115
+ buildBatchMeta: ({ index }) => {
1116
+ const s = args.steps[index];
1117
+ return {
1118
+ signatureText: JSON.stringify({
1119
+ kind: "CompoundV3",
1120
+ step: s.kind,
1121
+ to: s.to,
1122
+ ...args.extraMeta
1123
+ }),
1124
+ evm: { type: `compound_v3_${s.kind}`, version: 1, chainId: String(args.common.chainId) },
1125
+ compoundV3: { ...args.extraMeta, step: s.kind, comet: args.common.comet }
1126
+ };
1127
+ }
1128
+ });
1129
+ }
1130
+ async function resolveAmountWei(args) {
1131
+ if (args.amountHuman.trim().toLowerCase() === "max") return viem.maxUint256;
1132
+ const client = createCompoundV3PublicClient(args.rpcUrl, args.chainId);
1133
+ const dec = await client.readContract({ address: args.asset, abi: erc20ReadAbi, functionName: "decimals" });
1134
+ const amountWei = viem.parseUnits(args.amountHuman, Number(dec));
1135
+ if (amountWei === 0n) throw new Error("Amount is zero after converting with token decimals.");
1136
+ return amountWei;
1137
+ }
1138
+ async function buildEvmMultisignBodyCompoundV3Supply(args) {
1139
+ const market = requireCompoundV3Market(args.chainId, args.comet);
1140
+ const resolved = resolveCompoundV3ActionAsset({
1141
+ chainId: args.chainId,
1142
+ asset: args.asset,
1143
+ isNative: args.isNative ?? args.isNativeIn
1144
+ });
1145
+ const amountWei = await resolveAmountWei({
1146
+ rpcUrl: args.rpcUrl,
1147
+ chainId: args.chainId,
1148
+ asset: resolved.asset,
1149
+ amountHuman: args.amountHuman
1150
+ });
1151
+ const executor = viem.getAddress(args.executorAddress);
1152
+ const client = createCompoundV3PublicClient(args.rpcUrl, args.chainId);
1153
+ const steps = [];
1154
+ if (resolved.isNative) {
1155
+ steps.push({
1156
+ kind: "weth_deposit",
1157
+ to: resolved.asset,
1158
+ data: viem.encodeFunctionData({ abi: wethAbi, functionName: "deposit", args: [] }),
1159
+ value: amountWei
1160
+ });
1161
+ }
1162
+ await pushApproveIfNeeded({
1163
+ client,
1164
+ steps,
1165
+ token: resolved.asset,
1166
+ owner: executor,
1167
+ spender: market.comet,
1168
+ amountWei
1169
+ });
1170
+ steps.push({
1171
+ kind: "supply",
1172
+ to: market.comet,
1173
+ data: viem.encodeFunctionData({
1174
+ abi: cometInterfaceAbi,
1175
+ functionName: "supply",
1176
+ args: [resolved.asset, amountWei]
1177
+ }),
1178
+ value: 0n
1179
+ });
1180
+ const n = steps.length;
1181
+ return finishBatch({
1182
+ common: { ...args, comet: market.comet, executorAddress: executor },
1183
+ steps,
1184
+ purposeSuffix: resolved.isNative ? `Compound III: ${n}-tx batch \u2014 wrap native to WETH, approve Comet, supply.` : n === 1 ? "Compound III: 1-tx \u2014 supply (allowance already sufficient)." : `Compound III: ${n}-tx batch \u2014 approve Comet, then supply.`,
1185
+ extraMeta: {
1186
+ market: market.symbol,
1187
+ asset: resolved.asset,
1188
+ amountHuman: args.amountHuman,
1189
+ isNative: resolved.isNative
1190
+ }
1191
+ });
1192
+ }
1193
+ async function buildEvmMultisignBodyCompoundV3Repay(args) {
1194
+ return buildEvmMultisignBodyCompoundV3Supply(args);
1195
+ }
1196
+ async function buildEvmMultisignBodyCompoundV3Withdraw(args) {
1197
+ const market = requireCompoundV3Market(args.chainId, args.comet);
1198
+ const resolved = resolveCompoundV3ActionAsset({
1199
+ chainId: args.chainId,
1200
+ asset: args.asset,
1201
+ isNative: args.isNative ?? args.isNativeIn
1202
+ });
1203
+ const amountWei = await resolveAmountWei({
1204
+ rpcUrl: args.rpcUrl,
1205
+ chainId: args.chainId,
1206
+ asset: resolved.asset,
1207
+ amountHuman: args.amountHuman
1208
+ });
1209
+ const executor = viem.getAddress(args.executorAddress);
1210
+ const steps = [
1211
+ {
1212
+ kind: "withdraw",
1213
+ to: market.comet,
1214
+ data: viem.encodeFunctionData({
1215
+ abi: cometInterfaceAbi,
1216
+ functionName: "withdraw",
1217
+ args: [resolved.asset, amountWei]
1218
+ }),
1219
+ value: 0n
1220
+ }
1221
+ ];
1222
+ if (resolved.isNative) {
1223
+ if (amountWei === viem.maxUint256) {
1224
+ throw new Error('Native ETH unwrap cannot use amount "max"; pass an explicit amount to unwrap.');
1225
+ }
1226
+ steps.push({
1227
+ kind: "weth_withdraw",
1228
+ to: resolved.asset,
1229
+ data: viem.encodeFunctionData({ abi: wethAbi, functionName: "withdraw", args: [amountWei] }),
1230
+ value: 0n
1231
+ });
1232
+ }
1233
+ return finishBatch({
1234
+ common: { ...args, comet: market.comet, executorAddress: executor },
1235
+ steps,
1236
+ purposeSuffix: resolved.isNative ? "Compound III: 2-tx batch \u2014 withdraw WETH from Comet, unwrap to ETH." : "Compound III: 1-tx \u2014 withdraw (borrow if this is base while undercollateralized).",
1237
+ extraMeta: {
1238
+ market: market.symbol,
1239
+ asset: resolved.asset,
1240
+ amountHuman: args.amountHuman,
1241
+ isNative: resolved.isNative,
1242
+ note: "Withdraw of base while undercollateralized borrows the base asset."
1243
+ }
1244
+ });
1245
+ }
1246
+ async function buildEvmMultisignBodyCompoundV3ClaimRewards(args) {
1247
+ const market = requireCompoundV3Market(args.chainId, args.comet);
1248
+ const executor = viem.getAddress(args.executorAddress);
1249
+ const steps = [
1250
+ {
1251
+ kind: "claim",
1252
+ to: market.rewards,
1253
+ data: viem.encodeFunctionData({
1254
+ abi: cometRewardsAbi,
1255
+ functionName: "claim",
1256
+ args: [market.comet, executor, true]
1257
+ }),
1258
+ value: 0n
1259
+ }
1260
+ ];
1261
+ return finishBatch({
1262
+ common: { ...args, comet: market.comet, executorAddress: executor },
1263
+ steps,
1264
+ purposeSuffix: "Compound III: 1-tx \u2014 claim rewards.",
1265
+ extraMeta: { market: market.symbol, rewards: market.rewards }
1266
+ });
1267
+ }
1268
+ var ALLOW_FALLBACK = 80000n;
1269
+ var ERC20_APPROVE_FALLBACK2 = 100000n;
1270
+ var BULKER_INVOKE_FALLBACK = 900000n;
1271
+ var cometAllowAbi = viem.parseAbi(["function allow(address manager, bool isAllowed)"]);
1272
+ async function buildEvmMultisignBodyCompoundV3Bulker(args) {
1273
+ if (!args.steps?.length) throw new Error("Bulker requires at least one step.");
1274
+ const market = requireCompoundV3Market(args.chainId, args.comet);
1275
+ if (!market.bulker) throw new Error(`No Bulker contract for ${market.symbol} on chain ${args.chainId}.`);
1276
+ const bulker = market.bulker;
1277
+ const executor = viem.getAddress(args.executorAddress);
1278
+ const client = createCompoundV3PublicClient(args.rpcUrl, args.chainId);
1279
+ const allowed = await client.readContract({
1280
+ address: market.comet,
1281
+ abi: cometInterfaceAbi,
1282
+ functionName: "hasPermission",
1283
+ args: [executor, bulker]
1284
+ }).catch(() => false);
1285
+ const prefix = [];
1286
+ if (!allowed) {
1287
+ prefix.push({
1288
+ kind: "allow",
1289
+ to: market.comet,
1290
+ data: viem.encodeFunctionData({
1291
+ abi: cometAllowAbi,
1292
+ functionName: "allow",
1293
+ args: [bulker, true]
1294
+ }),
1295
+ value: 0n
1296
+ });
1297
+ }
1298
+ const actions = [];
1299
+ const datas = [];
1300
+ let nativeValue = 0n;
1301
+ for (const step of args.steps) {
1302
+ if (step.action === "claim") {
1303
+ actions.push(BULKER_ACTION_CLAIM_REWARD);
1304
+ datas.push(
1305
+ viem.encodeAbiParameters(
1306
+ [
1307
+ { type: "address" },
1308
+ { type: "address" },
1309
+ { type: "address" },
1310
+ { type: "bool" }
1311
+ ],
1312
+ [market.comet, market.rewards, executor, true]
1313
+ )
1314
+ );
1315
+ continue;
1316
+ }
1317
+ if (!step.asset || !step.amountHuman) {
1318
+ throw new Error(`Bulker ${step.action} requires asset and amountHuman.`);
1319
+ }
1320
+ const resolved = resolveCompoundV3ActionAsset({
1321
+ chainId: args.chainId,
1322
+ asset: step.asset,
1323
+ isNative: step.isNative
1324
+ });
1325
+ const dec = await client.readContract({
1326
+ address: resolved.asset,
1327
+ abi: erc20ReadAbi,
1328
+ functionName: "decimals"
1329
+ });
1330
+ const amountWei = viem.parseUnits(step.amountHuman, Number(dec));
1331
+ if (amountWei === 0n) throw new Error("Bulker step amount is zero.");
1332
+ if (step.action === "supply") {
1333
+ if (resolved.isNative) {
1334
+ actions.push(BULKER_ACTION_SUPPLY_NATIVE_TOKEN);
1335
+ datas.push(
1336
+ viem.encodeAbiParameters(
1337
+ [{ type: "address" }, { type: "address" }, { type: "uint256" }],
1338
+ [market.comet, executor, amountWei]
1339
+ )
1340
+ );
1341
+ nativeValue += amountWei;
1342
+ } else {
1343
+ await pushApproveIfNeeded({
1344
+ client,
1345
+ steps: prefix,
1346
+ token: resolved.asset,
1347
+ owner: executor,
1348
+ spender: bulker,
1349
+ amountWei
1350
+ });
1351
+ actions.push(BULKER_ACTION_SUPPLY_ASSET);
1352
+ datas.push(
1353
+ viem.encodeAbiParameters(
1354
+ [{ type: "address" }, { type: "address" }, { type: "address" }, { type: "uint256" }],
1355
+ [market.comet, executor, resolved.asset, amountWei]
1356
+ )
1357
+ );
1358
+ }
1359
+ } else {
1360
+ if (resolved.isNative) {
1361
+ actions.push(BULKER_ACTION_WITHDRAW_NATIVE_TOKEN);
1362
+ datas.push(
1363
+ viem.encodeAbiParameters(
1364
+ [{ type: "address" }, { type: "address" }, { type: "uint256" }],
1365
+ [market.comet, executor, amountWei]
1366
+ )
1367
+ );
1368
+ } else {
1369
+ actions.push(BULKER_ACTION_WITHDRAW_ASSET);
1370
+ datas.push(
1371
+ viem.encodeAbiParameters(
1372
+ [{ type: "address" }, { type: "address" }, { type: "address" }, { type: "uint256" }],
1373
+ [market.comet, executor, resolved.asset, amountWei]
1374
+ )
1375
+ );
1376
+ }
1377
+ }
1378
+ }
1379
+ const invokeData = viem.encodeFunctionData({
1380
+ abi: cometBulkerAbi,
1381
+ functionName: "invoke",
1382
+ args: [actions, datas]
1383
+ });
1384
+ prefix.push({
1385
+ kind: "bulker_invoke",
1386
+ to: bulker,
1387
+ data: invokeData,
1388
+ value: nativeValue
1389
+ });
1390
+ const evmSteps = prefix.map((s) => ({
1391
+ to: s.to,
1392
+ data: s.data,
1393
+ value: s.value,
1394
+ fallbackGas: s.kind === "approve" ? ERC20_APPROVE_FALLBACK2 : s.kind === "allow" ? ALLOW_FALLBACK : BULKER_INVOKE_FALLBACK
1395
+ }));
1396
+ const first = evmSteps[0];
1397
+ const firstDataNo0x = first.data.startsWith("0x") ? first.data.slice(2) : first.data;
1398
+ return buildEvmMultisignBatch({
1399
+ context: {
1400
+ chainCategory: "evm",
1401
+ keyGen: args.keyGen,
1402
+ purposeText: args.purposeText,
1403
+ chainId: args.chainId,
1404
+ rpcUrl: args.rpcUrl,
1405
+ executorAddress: executor,
1406
+ chainDetail: args.chainDetail,
1407
+ useCustomGas: args.useCustomGas,
1408
+ customGasChainDetails: args.customGasChainDetails
1409
+ },
1410
+ steps: evmSteps,
1411
+ purposeSuffix: `Compound III: ${evmSteps.length}-tx Bulker batch (${args.steps.map((s) => s.action).join(", ")}).`,
1412
+ firstMsgRawNo0x: firstDataNo0x,
1413
+ destinationAddress: first.to,
1414
+ payableValueWei: nativeValue > 0n ? nativeValue : void 0,
1415
+ buildBatchMeta: ({ index }) => {
1416
+ const s = prefix[index];
1417
+ return {
1418
+ signatureText: JSON.stringify({
1419
+ kind: "CompoundV3",
1420
+ step: s.kind,
1421
+ bulker,
1422
+ comet: market.comet,
1423
+ actions: args.steps.map((st) => st.action)
1424
+ }),
1425
+ evm: { type: `compound_v3_${s.kind}`, version: 1, chainId: String(args.chainId) },
1426
+ compoundV3: { market: market.symbol, comet: market.comet, bulker, step: s.kind }
1427
+ };
1428
+ }
1429
+ });
1430
+ }
1431
+
1432
+ // src/protocols/evm/compound-v3/index.ts
1433
+ var compoundV3ProtocolModule = {
1434
+ id: COMPOUND_V3_PROTOCOL_ID,
1435
+ chainCategory: "evm",
1436
+ isChainSupported(ctx) {
1437
+ const id = typeof ctx.chainId === "string" ? Number(ctx.chainId) : ctx.chainId;
1438
+ return ctx.chainCategory === "evm" && isCompoundV3ChainSupported(id);
1439
+ },
1440
+ isTokenSupported(token) {
1441
+ return token.category === "evm" && (token.kind === "native" || token.kind === "erc20");
1442
+ },
1443
+ actions: [
1444
+ {
1445
+ id: "compound-v3.supply",
1446
+ protocolId: COMPOUND_V3_PROTOCOL_ID,
1447
+ chainCategory: "evm",
1448
+ description: "Supply base (earn/repay) or collateral to a Comet proxy",
1449
+ commonParams: ["keyGen", "purposeText", "useCustomGas"],
1450
+ params: {}
1451
+ },
1452
+ {
1453
+ id: "compound-v3.withdraw",
1454
+ protocolId: COMPOUND_V3_PROTOCOL_ID,
1455
+ chainCategory: "evm",
1456
+ description: "Withdraw collateral or base (withdraw of base while undercollateralized = borrow)",
1457
+ commonParams: ["keyGen", "purposeText", "useCustomGas"],
1458
+ params: {}
1459
+ },
1460
+ {
1461
+ id: "compound-v3.repay",
1462
+ protocolId: COMPOUND_V3_PROTOCOL_ID,
1463
+ chainCategory: "evm",
1464
+ description: "Repay base debt by supplying base",
1465
+ commonParams: ["keyGen", "purposeText", "useCustomGas"],
1466
+ params: {}
1467
+ },
1468
+ {
1469
+ id: "compound-v3.claim-rewards",
1470
+ protocolId: COMPOUND_V3_PROTOCOL_ID,
1471
+ chainCategory: "evm",
1472
+ description: "Claim COMP / reward token from CometRewards",
1473
+ commonParams: ["keyGen", "purposeText", "useCustomGas"],
1474
+ params: {}
1475
+ },
1476
+ {
1477
+ id: "compound-v3.bulker",
1478
+ protocolId: COMPOUND_V3_PROTOCOL_ID,
1479
+ chainCategory: "evm",
1480
+ description: "Combined Bulker.invoke (optional)",
1481
+ commonParams: ["keyGen", "purposeText", "useCustomGas"],
1482
+ params: {}
1483
+ }
1484
+ ]
1485
+ };
1486
+ registerProtocolModule(compoundV3ProtocolModule);
1487
+
1488
+ exports.BULKER_ACTION_CLAIM_REWARD = BULKER_ACTION_CLAIM_REWARD;
1489
+ exports.BULKER_ACTION_SUPPLY_ASSET = BULKER_ACTION_SUPPLY_ASSET;
1490
+ exports.BULKER_ACTION_SUPPLY_NATIVE_TOKEN = BULKER_ACTION_SUPPLY_NATIVE_TOKEN;
1491
+ exports.BULKER_ACTION_TRANSFER_ASSET = BULKER_ACTION_TRANSFER_ASSET;
1492
+ exports.BULKER_ACTION_WITHDRAW_ASSET = BULKER_ACTION_WITHDRAW_ASSET;
1493
+ exports.BULKER_ACTION_WITHDRAW_NATIVE_TOKEN = BULKER_ACTION_WITHDRAW_NATIVE_TOKEN;
1494
+ exports.COMPOUND_V3_CHAIN_IDS = COMPOUND_V3_CHAIN_IDS;
1495
+ exports.COMPOUND_V3_FACTOR_SCALE = COMPOUND_V3_FACTOR_SCALE;
1496
+ exports.COMPOUND_V3_MARKETS = COMPOUND_V3_MARKETS;
1497
+ exports.COMPOUND_V3_PROTOCOL_ID = COMPOUND_V3_PROTOCOL_ID;
1498
+ exports.COMPOUND_V3_SECONDS_PER_YEAR = COMPOUND_V3_SECONDS_PER_YEAR;
1499
+ exports.COMPOUND_V3_WRAPPED_NATIVE = COMPOUND_V3_WRAPPED_NATIVE;
1500
+ exports.buildEvmMultisignBodyCompoundV3Bulker = buildEvmMultisignBodyCompoundV3Bulker;
1501
+ exports.buildEvmMultisignBodyCompoundV3ClaimRewards = buildEvmMultisignBodyCompoundV3ClaimRewards;
1502
+ exports.buildEvmMultisignBodyCompoundV3Repay = buildEvmMultisignBodyCompoundV3Repay;
1503
+ exports.buildEvmMultisignBodyCompoundV3Supply = buildEvmMultisignBodyCompoundV3Supply;
1504
+ exports.buildEvmMultisignBodyCompoundV3Withdraw = buildEvmMultisignBodyCompoundV3Withdraw;
1505
+ exports.bulkerActionId = bulkerActionId;
1506
+ exports.cometBulkerAbi = cometBulkerAbi;
1507
+ exports.cometInterfaceAbi = cometInterfaceAbi;
1508
+ exports.cometRewardsAbi = cometRewardsAbi;
1509
+ exports.compoundJsAgreesWithOfficial = compoundJsAgreesWithOfficial;
1510
+ exports.compoundJsCollateralAddresses = compoundJsCollateralAddresses;
1511
+ exports.compoundJsCometAddress = compoundJsCometAddress;
1512
+ exports.compoundV3AprToPercentLabel = compoundV3AprToPercentLabel;
1513
+ exports.compoundV3FactorToPercent = compoundV3FactorToPercent;
1514
+ exports.compoundV3FetchAccountSummary = compoundV3FetchAccountSummary;
1515
+ exports.compoundV3FetchMarketSummary = compoundV3FetchMarketSummary;
1516
+ exports.compoundV3FetchMarketsSummary = compoundV3FetchMarketsSummary;
1517
+ exports.compoundV3KeyForNodeAssetRow = compoundV3KeyForNodeAssetRow;
1518
+ exports.compoundV3ProtocolModule = compoundV3ProtocolModule;
1519
+ exports.compoundV3RatePerSecondToAprDecimal = compoundV3RatePerSecondToAprDecimal;
1520
+ exports.compoundV3SubgraphIdForChain = compoundV3SubgraphIdForChain;
1521
+ exports.compoundV3UtilizationToDecimal = compoundV3UtilizationToDecimal;
1522
+ exports.compoundV3WrappedNative = compoundV3WrappedNative;
1523
+ exports.createCompoundV3PublicClient = createCompoundV3PublicClient;
1524
+ exports.ensureCompoundV3ChainAssetCache = ensureCompoundV3ChainAssetCache;
1525
+ exports.erc20ApproveAbi = erc20ApproveAbi;
1526
+ exports.erc20ReadAbi = erc20ReadAbi;
1527
+ exports.fetchCompoundV3SubgraphMarkets = fetchCompoundV3SubgraphMarkets;
1528
+ exports.getCompoundV3AssetModesFromCache = getCompoundV3AssetModesFromCache;
1529
+ exports.getCompoundV3MarketByComet = getCompoundV3MarketByComet;
1530
+ exports.isCompoundV3ChainSupported = isCompoundV3ChainSupported;
1531
+ exports.isNativeAssetAddress = isNativeAssetAddress;
1532
+ exports.listCompoundJsCometInstances = listCompoundJsCometInstances;
1533
+ exports.listCompoundV3KnownTokenAddresses = listCompoundV3KnownTokenAddresses;
1534
+ exports.listCompoundV3MarketsForAsset = listCompoundV3MarketsForAsset;
1535
+ exports.listCompoundV3MarketsForChain = listCompoundV3MarketsForChain;
1536
+ exports.listCompoundV3SupportedChainIds = listCompoundV3SupportedChainIds;
1537
+ exports.pushApproveIfNeeded = pushApproveIfNeeded;
1538
+ exports.requireCompoundV3Market = requireCompoundV3Market;
1539
+ exports.resolveCompoundV3ActionAsset = resolveCompoundV3ActionAsset;
1540
+ exports.wethAbi = wethAbi;
1541
+ //# sourceMappingURL=index.cjs.map
1542
+ //# sourceMappingURL=index.cjs.map