@continuumdao/ctm-mpc-defi 0.2.62 → 0.2.64

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 (33) hide show
  1. package/dist/agent/catalog.cjs +329 -79
  2. package/dist/agent/catalog.cjs.map +1 -1
  3. package/dist/agent/catalog.d.ts +217 -27
  4. package/dist/agent/catalog.js +325 -80
  5. package/dist/agent/catalog.js.map +1 -1
  6. package/dist/agent/skills/aerodrome/SKILL.md +16 -14
  7. package/dist/agent/skills/continuum-dao/SKILL.md +2 -2
  8. package/dist/agent/skills/railgun/SKILL.md +10 -4
  9. package/dist/agent/skills/yield-compare/SKILL.md +5 -5
  10. package/dist/index.cjs +5 -4
  11. package/dist/index.cjs.map +1 -1
  12. package/dist/index.js +5 -4
  13. package/dist/index.js.map +1 -1
  14. package/dist/protocols/evm/aerodrome/index.cjs +476 -282
  15. package/dist/protocols/evm/aerodrome/index.cjs.map +1 -1
  16. package/dist/protocols/evm/aerodrome/index.d.ts +38 -13
  17. package/dist/protocols/evm/aerodrome/index.js +473 -284
  18. package/dist/protocols/evm/aerodrome/index.js.map +1 -1
  19. package/dist/protocols/evm/continuum-dao/index.cjs +397 -70
  20. package/dist/protocols/evm/continuum-dao/index.cjs.map +1 -1
  21. package/dist/protocols/evm/continuum-dao/index.d.ts +27 -3
  22. package/dist/protocols/evm/continuum-dao/index.js +398 -71
  23. package/dist/protocols/evm/continuum-dao/index.js.map +1 -1
  24. package/dist/protocols/evm/curve-dao/index.cjs +54 -6
  25. package/dist/protocols/evm/curve-dao/index.cjs.map +1 -1
  26. package/dist/protocols/evm/curve-dao/index.js +54 -6
  27. package/dist/protocols/evm/curve-dao/index.js.map +1 -1
  28. package/dist/protocols/evm/euler-v2/index.cjs +45 -10
  29. package/dist/protocols/evm/euler-v2/index.cjs.map +1 -1
  30. package/dist/protocols/evm/euler-v2/index.d.ts +10 -2
  31. package/dist/protocols/evm/euler-v2/index.js +44 -11
  32. package/dist/protocols/evm/euler-v2/index.js.map +1 -1
  33. package/package.json +1 -1
@@ -22,7 +22,11 @@ var init_expiry = __esm({
22
22
  });
23
23
  function isAerodromeChainSupported(chainId) {
24
24
  const n = typeof chainId === "number" ? chainId : Number.parseInt(String(chainId), 10);
25
- return n === exports.AERODROME_CHAIN_ID;
25
+ return exports.AERO_CHAIN_IDS.includes(n);
26
+ }
27
+ function aerodromeUnsupportedChainMessage(chainId) {
28
+ const listed = exports.AERO_CHAIN_IDS.map((id) => `${AERO_CHAIN_LABEL[id]} ${id}`).join(", ");
29
+ return `Aero is not deployed on chain ${chainId}. Launch chains: ${listed}.`;
26
30
  }
27
31
  function aerodromeOnChainDeadlineUnix(expiryDate) {
28
32
  if (typeof expiryDate === "number" && Number.isFinite(expiryDate) && expiryDate > 0) {
@@ -34,7 +38,7 @@ function requireAerodromeRpcUrl(rpcUrl) {
34
38
  const url = (rpcUrl ?? "").trim();
35
39
  if (!url) {
36
40
  throw new Error(
37
- "rpcUrl is required. The MCP server injects it from get_chain_registry rpcGateway \u2014 pass chainId 8453 only, do not pass a public RPC URL."
41
+ "rpcUrl is required. The MCP server injects it from get_chain_registry rpcGateway \u2014 pass an Aero chainId (Base 8453, Ethereum 1, OP 10, Arbitrum 42161, Robinhood 4663, Arc 5042, Ink 57073). Do not pass a public RPC URL."
38
42
  );
39
43
  }
40
44
  return url;
@@ -50,26 +54,27 @@ function isAerodromeNativeToken(address) {
50
54
  return false;
51
55
  }
52
56
  }
53
- exports.AERODROME_PROTOCOL_ID = void 0; exports.AERODROME_CHAIN_ID = void 0; exports.AERODROME_NATIVE_PLACEHOLDER = void 0; exports.AERODROME_WETH_BASE = void 0; exports.AERODROME_USDC_BASE = void 0;
57
+ exports.AERODROME_PROTOCOL_ID = void 0; exports.AERODROME_CHAIN_ID = void 0; exports.AERO_CHAIN_IDS = void 0; var AERO_CHAIN_LABEL; exports.AERODROME_NATIVE_PLACEHOLDER = void 0; exports.AERODROME_WETH_BASE = void 0; exports.AERODROME_USDC_BASE = void 0;
54
58
  var init_support = __esm({
55
59
  "src/protocols/evm/aerodrome/support.ts"() {
56
60
  init_expiry();
57
61
  exports.AERODROME_PROTOCOL_ID = "aerodrome";
58
62
  exports.AERODROME_CHAIN_ID = 8453;
63
+ exports.AERO_CHAIN_IDS = [8453, 1, 10, 42161, 4663, 5042, 57073];
64
+ AERO_CHAIN_LABEL = {
65
+ 1: "Ethereum",
66
+ 10: "OP Mainnet",
67
+ 42161: "Arbitrum",
68
+ 4663: "Robinhood Chain",
69
+ 5042: "Arc",
70
+ 8453: "Base",
71
+ 57073: "Ink"
72
+ };
59
73
  exports.AERODROME_NATIVE_PLACEHOLDER = viem.zeroAddress;
60
74
  exports.AERODROME_WETH_BASE = "0x4200000000000000000000000000000000000006";
61
75
  exports.AERODROME_USDC_BASE = "0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913";
62
76
  }
63
77
  });
64
- function asAddr(raw) {
65
- const s = (raw ?? "").trim();
66
- if (!s) return null;
67
- try {
68
- return viem.getAddress(s.startsWith("0x") ? s : `0x${s}`);
69
- } catch {
70
- return null;
71
- }
72
- }
73
78
  function parseSugarBaseEnv(text) {
74
79
  const out = {};
75
80
  for (const line of text.split(/\r?\n/)) {
@@ -89,77 +94,99 @@ function parseSecurityMdxAddresses(text) {
89
94
  let m;
90
95
  while (m = re.exec(text)) {
91
96
  const name = (m[1] ?? "").trim().toLowerCase().replace(/\s+/g, "");
92
- const addr = m[2];
93
- if (name && addr && !out[name]) out[name] = addr;
97
+ const addr2 = m[2];
98
+ if (name && addr2 && !out[name]) out[name] = addr2;
94
99
  }
95
100
  return out;
96
101
  }
97
- function nthAddr(csv, n) {
98
- if (!csv) return null;
99
- const part = csv.split(",")[n];
100
- return part ? asAddr(part.trim()) : null;
102
+ function addr(raw) {
103
+ return viem.getAddress(raw);
104
+ }
105
+ function aeroUsdcAddress(chainId) {
106
+ const raw = AERO_USDC_BY_CHAIN[chainId];
107
+ return raw ? addr(raw) : null;
101
108
  }
102
- function firstAddr(csv) {
103
- return nthAddr(csv, 0);
109
+ function aeroWrappedNativeAddress(chainId) {
110
+ const raw = AERO_WETH_BY_CHAIN[chainId];
111
+ return raw ? addr(raw) : null;
112
+ }
113
+ function aeroRowIconAddresses(chainId) {
114
+ const out = [];
115
+ if (chainId === exports.AERODROME_CHAIN_ID) {
116
+ out.push(addr(exports.AERO_LEGACY_TOKEN_BASE), addr(exports.AERO_TOKEN_BASE));
117
+ }
118
+ const receipt = AERO_RECEIPT_BY_CHAIN[chainId];
119
+ if (receipt) out.push(addr(receipt));
120
+ const weth = aeroWrappedNativeAddress(chainId);
121
+ if (weth) out.push(weth);
122
+ const usdc = aeroUsdcAddress(chainId);
123
+ if (usdc) out.push(usdc);
124
+ return out;
104
125
  }
105
- function mergeLoaded(sugar, docs) {
126
+ function aeroAddressesForChain(chainId) {
106
127
  const fb = exports.AERODROME_BASE_ADDRESSES_FALLBACK;
107
- const pick = (loaded, fallback) => loaded ?? viem.getAddress(fallback);
128
+ const cl = addr(AERO_CL_FACTORY_BY_CHAIN[chainId] ?? AERO_CL_FACTORY_BY_CHAIN[exports.AERODROME_CHAIN_ID]);
129
+ const receipt = addr(AERO_RECEIPT_BY_CHAIN[chainId] ?? AERO_RECEIPT_BY_CHAIN[exports.AERODROME_CHAIN_ID]);
130
+ const weth = aeroWrappedNativeAddress(chainId) ?? addr("0x0000000000000000000000000000000000000000");
131
+ const token = chainId === exports.AERODROME_CHAIN_ID ? addr(exports.AERO_TOKEN_BASE) : receipt;
108
132
  return {
109
- chainId: exports.AERODROME_CHAIN_ID,
110
- aero: pick(asAddr(docs.aero), fb.aero),
111
- router: pick(asAddr(docs.router), fb.router),
112
- poolFactory: pick(firstAddr(sugar.V2_FACTORIES_8453) ?? asAddr(docs.poolfactory), fb.poolFactory),
113
- factoryRegistry: pick(asAddr(sugar.REGISTRY_8453) ?? asAddr(docs.factoryregistry), fb.factoryRegistry),
114
- voter: pick(asAddr(sugar.VOTER_8453) ?? asAddr(docs.voter), fb.voter),
115
- votingEscrow: pick(asAddr(docs.votingescrow), fb.votingEscrow),
116
- rewardsDistributor: pick(asAddr(sugar.DIST_8453) ?? asAddr(docs.rewardsdistributor), fb.rewardsDistributor),
117
- mixedQuoter: pick(asAddr(docs.mixedquoter), fb.mixedQuoter),
118
- mixedQuoterV3: pick(asAddr(docs.mixedquoterv3), fb.mixedQuoterV3),
119
- nfpm: pick(asAddr(docs.nonfungiblepositionmanager), fb.nfpm),
120
- clFactory: pick(firstAddr(sugar.CL_FACTORIES_8453) ?? asAddr(docs.poolfactory), fb.clFactory),
121
- clFactory2: pick(nthAddr(sugar.CL_FACTORIES_8453, 1), fb.clFactory2),
122
- clFactory3: pick(nthAddr(sugar.CL_FACTORIES_8453, 2), fb.clFactory3),
123
- universalRouter: pick(asAddr(docs.universalrouter), fb.universalRouter),
124
- swapRouter: pick(asAddr(docs.swaprouter), fb.swapRouter),
125
- swapRouter2: pick(asAddr(docs.swaprouter2), fb.swapRouter2),
126
- swapRouter3: pick(asAddr(docs.swaprouter3), fb.swapRouter3),
127
- pricesOracle: pick(asAddr(docs.pricesoracle), fb.pricesOracle),
128
- slipstreamHelper: pick(asAddr(docs.slipstreamhelper), fb.slipstreamHelper),
129
- lpSugar: pick(asAddr(sugar.LP_SUGAR_ADDRESS_8453), fb.lpSugar),
130
- sugarSlipstreamHelper: pick(asAddr(sugar.SLIPSTREAM_HELPER_8453), fb.sugarSlipstreamHelper),
131
- swapper: pick(asAddr(sugar.SWAPPER_8453), fb.swapper),
132
- weth: pick(asAddr(exports.AERODROME_WETH_BASE), fb.weth)
133
+ chainId,
134
+ aero: token,
135
+ router: chainId === exports.AERODROME_CHAIN_ID ? addr(fb.router) : addr(exports.AERO_METAROUTER),
136
+ poolFactory: addr(exports.AERO_VOLATILE_POOL_FACTORY),
137
+ factoryRegistry: addr(AERO_FACTORY_REGISTRY_BY_CHAIN[chainId] ?? AERO_FACTORY_REGISTRY_BY_CHAIN[exports.AERODROME_CHAIN_ID]),
138
+ voter: addr(exports.AERO_LEAF_VOTER),
139
+ votingEscrow: addr("0xBF7977E1521e9a3032bf7243Ee4712f311f13915"),
140
+ rewardsDistributor: addr(fb.rewardsDistributor),
141
+ mixedQuoter: addr(exports.AERO_METAQUOTER),
142
+ mixedQuoterV3: addr(exports.AERO_METAQUOTER),
143
+ nfpm: addr(exports.AERO_NFPM),
144
+ clFactory: cl,
145
+ clFactory2: cl,
146
+ clFactory3: cl,
147
+ universalRouter: addr(fb.universalRouter),
148
+ swapRouter: addr(exports.AERO_SWAP_ROUTER),
149
+ swapRouter2: addr(exports.AERO_SWAP_ROUTER),
150
+ swapRouter3: addr(exports.AERO_SWAP_ROUTER),
151
+ pricesOracle: addr(fb.pricesOracle),
152
+ slipstreamHelper: addr(fb.slipstreamHelper),
153
+ lpSugar: chainId === exports.AERODROME_CHAIN_ID ? addr(fb.lpSugar) : addr("0x0000000000000000000000000000000000000000"),
154
+ sugarSlipstreamHelper: addr(fb.sugarSlipstreamHelper),
155
+ swapper: addr(fb.swapper),
156
+ weth,
157
+ stablePoolFactory: addr(exports.AERO_STABLE_POOL_FACTORY),
158
+ volatilePoolFactory: addr(exports.AERO_VOLATILE_POOL_FACTORY),
159
+ metarouter: addr(exports.AERO_METAROUTER),
160
+ metaquoter: addr(exports.AERO_METAQUOTER),
161
+ receiptToken: receipt
133
162
  };
134
163
  }
135
- async function fetchText(url) {
136
- try {
137
- const res = await fetch(url, { cache: "force-cache" });
138
- if (!res.ok) return null;
139
- return await res.text();
140
- } catch {
141
- return null;
142
- }
143
- }
144
- async function loadAerodromeAddresses() {
145
- if (!cache) {
146
- cache = (async () => {
147
- const [sugarText, docsText] = await Promise.all([fetchText(SUGAR_ENV_URL), fetchText(SECURITY_MDX_URL)]);
148
- const sugar = sugarText ? parseSugarBaseEnv(sugarText) : {};
149
- const docs = docsText ? parseSecurityMdxAddresses(docsText) : {};
150
- return mergeLoaded(sugar, docs);
151
- })();
164
+ async function loadAerodromeAddresses(chainId = exports.AERODROME_CHAIN_ID) {
165
+ if (!isAerodromeChainSupported(chainId)) {
166
+ throw new Error(aerodromeUnsupportedChainMessage(chainId));
152
167
  }
153
- return cache;
168
+ const cached = cache.get(chainId);
169
+ if (cached) return cached;
170
+ const addrs = aeroAddressesForChain(chainId);
171
+ cache.set(chainId, addrs);
172
+ return addrs;
154
173
  }
155
174
  function resetAerodromeAddressCache() {
156
- cache = null;
175
+ cache = /* @__PURE__ */ new Map();
157
176
  }
158
177
  function aerodromeFallbackAddresses() {
159
- return mergeLoaded({}, {});
178
+ return aeroAddressesForChain(exports.AERODROME_CHAIN_ID);
160
179
  }
161
180
  function aerodromeClFactoryList(addrs) {
162
- return [addrs.clFactory, addrs.clFactory2, addrs.clFactory3];
181
+ const out = [];
182
+ const seen = /* @__PURE__ */ new Set();
183
+ for (const factory of [addrs.clFactory, addrs.clFactory2, addrs.clFactory3]) {
184
+ const key = factory.toLowerCase();
185
+ if (seen.has(key)) continue;
186
+ seen.add(key);
187
+ out.push(factory);
188
+ }
189
+ return out;
163
190
  }
164
191
  function aerodromeClSwapRouterForFactory(addrs, factory) {
165
192
  const f = viem.getAddress(factory).toLowerCase();
@@ -167,7 +194,7 @@ function aerodromeClSwapRouterForFactory(addrs, factory) {
167
194
  if (f === addrs.clFactory2.toLowerCase()) return addrs.swapRouter2;
168
195
  return addrs.swapRouter;
169
196
  }
170
- exports.AERODROME_BASE_ADDRESSES_FALLBACK = void 0; var SUGAR_ENV_URL, SECURITY_MDX_URL, cache;
197
+ exports.AERODROME_BASE_ADDRESSES_FALLBACK = void 0; exports.AERO_TOKEN_BASE = void 0; exports.AERO_LEGACY_TOKEN_BASE = void 0; exports.AERO_METAROUTER = void 0; exports.AERO_METAQUOTER = void 0; exports.AERO_STABLE_POOL_FACTORY = void 0; exports.AERO_VOLATILE_POOL_FACTORY = void 0; exports.AERO_NFPM = void 0; exports.AERO_SWAP_ROUTER = void 0; exports.AERO_LEAF_VOTER = void 0; var AERO_RECEIPT_BY_CHAIN, AERO_FACTORY_REGISTRY_BY_CHAIN, AERO_CL_FACTORY_BY_CHAIN, OP_STACK_WETH, AERO_WETH_BY_CHAIN, AERO_USDC_BY_CHAIN, cache;
171
198
  var init_addresses = __esm({
172
199
  "src/protocols/evm/aerodrome/addresses.ts"() {
173
200
  init_support();
@@ -201,9 +228,58 @@ var init_addresses = __esm({
201
228
  swapper: "0x91616a7B9CF6D23f8C17845581051EBdC4BcB916",
202
229
  weth: exports.AERODROME_WETH_BASE
203
230
  };
204
- SUGAR_ENV_URL = "https://raw.githubusercontent.com/velodrome-finance/sugar/main/deployments/base.env";
205
- SECURITY_MDX_URL = "https://raw.githubusercontent.com/aerodrome-finance/docs/main/content/security.mdx";
206
- cache = null;
231
+ exports.AERO_TOKEN_BASE = "0x3f5bF3EdAc59d650D8fDf9657a71F2f904A3a4Ee";
232
+ exports.AERO_LEGACY_TOKEN_BASE = "0x940181a94A35A4569E4529A3CDfB74e38FD98631";
233
+ exports.AERO_METAROUTER = "0x0fEf9e88A7b76BCDBF451780C6774FE32965Ee98";
234
+ exports.AERO_METAQUOTER = "0x1dDfeC5058180C207F55BB77D95AcDd0d8227868";
235
+ exports.AERO_STABLE_POOL_FACTORY = "0x78589E876edcEbdce72ee3436ab3c9AD3a7cEF2D";
236
+ exports.AERO_VOLATILE_POOL_FACTORY = "0x8E6a9FCd1d638CC760Ffba397605Fe3355dE76D2";
237
+ exports.AERO_NFPM = "0x4857DB576eE0e45F10525eC59527BfD10beeC60b";
238
+ exports.AERO_SWAP_ROUTER = "0x9Ee35Bf1bd69a03c6F0393582030fCe8Bb93D418";
239
+ exports.AERO_LEAF_VOTER = "0x382409fad8503FbCdbB27A4211551fa03e884078";
240
+ AERO_RECEIPT_BY_CHAIN = {
241
+ 8453: "0x6CdDa0E730744DC6fF67654B35350Adad05EceE7",
242
+ 10: "0xbdEaeA5205d16f34Cb40038052d91235D87B4C54",
243
+ 42161: "0x436a085B2751cB87db270FFa66f8d698F87bEC82",
244
+ 1: "0x9e148C5716b5aAdCFD3B71cEAE9EE7a9e22C29E2",
245
+ 57073: "0x9e148C5716b5aAdCFD3B71cEAE9EE7a9e22C29E2",
246
+ 4663: "0x9e148C5716b5aAdCFD3B71cEAE9EE7a9e22C29E2",
247
+ 5042: "0x20077cC0d5E385A0Fe9C91bbC7DC744f51559307"
248
+ };
249
+ AERO_FACTORY_REGISTRY_BY_CHAIN = {
250
+ 8453: "0x7b2A2c12dC5Ea2a31455952a05031C3E4BB28F3E",
251
+ 10: "0xb6F9705A631CC1C0E8570FFde48882C95E2Df408",
252
+ 42161: "0x9E635b2c689fC52201DF7eF1C9FA607c2F58f666",
253
+ 1: "0xdd1705e23762F4D6e44D8C31BD8Ea80c54612239",
254
+ 57073: "0xdd1705e23762F4D6e44D8C31BD8Ea80c54612239",
255
+ 4663: "0xdd1705e23762F4D6e44D8C31BD8Ea80c54612239",
256
+ 5042: "0xCe44907DC45D3BFa3f5f6035B0e6E8B22D780A42"
257
+ };
258
+ AERO_CL_FACTORY_BY_CHAIN = {
259
+ 8453: "0x9CB220581b91b0C83223012FE69688b92aD07a76",
260
+ 10: "0xfeaB42D90055db3a0616249f76B6002D72266778",
261
+ 42161: "0x88a60ee77392577c355C0acb2A8d476D5a4EC03a",
262
+ 1: "0xF4Fd2E6c5B60c5b365cd1B96DD6245E6D60414c2",
263
+ 57073: "0x7660BF2aDefC687C22906112ca323d60A00358cF",
264
+ 4663: "0xc63d7338c178e805c544B8f897066bD3BBcBE136",
265
+ 5042: "0x7F83235643181E440433400a027618Cd50879751"
266
+ };
267
+ OP_STACK_WETH = "0x4200000000000000000000000000000000000006";
268
+ AERO_WETH_BY_CHAIN = {
269
+ 1: "0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2",
270
+ 10: OP_STACK_WETH,
271
+ 42161: "0x82aF49447D8a07e3bd95BD0d56f35241523fBab1",
272
+ 8453: OP_STACK_WETH,
273
+ 57073: OP_STACK_WETH,
274
+ 4663: "0x0Bd7D308f8E1639FAb988df18A8011f41EAcAD73"
275
+ };
276
+ AERO_USDC_BY_CHAIN = {
277
+ 1: "0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48",
278
+ 10: "0x0b2C639c533813f4Aa9D7837CAf62653d097Ff85",
279
+ 42161: "0xaf88d065e77c8cC2239327C5EDb3A432268e5831",
280
+ 8453: "0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913"
281
+ };
282
+ cache = /* @__PURE__ */ new Map();
207
283
  }
208
284
  });
209
285
  function isCoinbaseB20AssetToken(address) {
@@ -330,7 +406,7 @@ var init_coinbaseB20 = __esm({
330
406
  });
331
407
 
332
408
  // src/protocols/evm/aerodrome/abi.ts
333
- var lpSugarAbi, routerAbi, mixedQuoterAbi, mixedQuoterV3Abi, v2PoolFactoryAbi, clPoolFactoryAbi, clPoolAbi, sugarHelperAbi, nfpmAbi, clSwapRouterAbi, poolClaimFeesAbi, gaugeAbi, clGaugeAbi, aerodromePoolMetaAbi, aerodromeVoterAbi, erc20Abi;
409
+ var lpSugarAbi, routerAbi, mixedQuoterAbi, mixedQuoterV3Abi, aeroV2FactoryAbi, aeroPoolAmountOutAbi, aeroMetarouterAbi, clPoolFactoryAbi, clPoolAbi, sugarHelperAbi, nfpmAbi, clSwapRouterAbi, poolClaimFeesAbi, gaugeAbi, clGaugeAbi, aerodromePoolMetaAbi, aerodromeVoterAbi, erc20Abi;
334
410
  var init_abi = __esm({
335
411
  "src/protocols/evm/aerodrome/abi.ts"() {
336
412
  lpSugarAbi = [
@@ -764,19 +840,42 @@ var init_abi = __esm({
764
840
  ]
765
841
  }
766
842
  ];
767
- v2PoolFactoryAbi = [
843
+ aeroV2FactoryAbi = [
768
844
  {
769
845
  type: "function",
770
846
  name: "getPool",
771
847
  stateMutability: "view",
772
848
  inputs: [
773
849
  { name: "tokenA", type: "address" },
774
- { name: "tokenB", type: "address" },
775
- { name: "stable", type: "bool" }
850
+ { name: "tokenB", type: "address" }
776
851
  ],
777
852
  outputs: [{ name: "", type: "address" }]
778
853
  }
779
854
  ];
855
+ aeroPoolAmountOutAbi = [
856
+ {
857
+ type: "function",
858
+ name: "getAmountOut",
859
+ stateMutability: "view",
860
+ inputs: [
861
+ { name: "amountIn", type: "uint256" },
862
+ { name: "tokenIn", type: "address" }
863
+ ],
864
+ outputs: [{ name: "", type: "uint256" }]
865
+ }
866
+ ];
867
+ aeroMetarouterAbi = [
868
+ {
869
+ type: "function",
870
+ name: "execute",
871
+ stateMutability: "payable",
872
+ inputs: [
873
+ { name: "commands", type: "bytes" },
874
+ { name: "inputs", type: "bytes[]" }
875
+ ],
876
+ outputs: []
877
+ }
878
+ ];
780
879
  clPoolFactoryAbi = [
781
880
  {
782
881
  type: "function",
@@ -1357,8 +1456,8 @@ var init_stockTokens = __esm({
1357
1456
  MAX_OFFICIAL_STOCKS = 40;
1358
1457
  }
1359
1458
  });
1360
- function checksum(addr) {
1361
- return viem.getAddress(addr);
1459
+ function checksum(addr2) {
1460
+ return viem.getAddress(addr2);
1362
1461
  }
1363
1462
  function pairKey(a, b) {
1364
1463
  const [x, y] = [a.toLowerCase(), b.toLowerCase()].sort();
@@ -1400,7 +1499,8 @@ async function tickSpacingsForFactory(rpcUrl, factory) {
1400
1499
  }
1401
1500
  async function aerodromeDiscoverConnectorPools(args) {
1402
1501
  const client = aerodromePublicClient(args.rpcUrl);
1403
- const connectors = [args.addrs.weth, viem.getAddress(exports.AERODROME_USDC_BASE), args.addrs.aero];
1502
+ const usdc = aeroUsdcAddress(args.addrs.chainId);
1503
+ const connectors = [args.addrs.weth, ...usdc ? [usdc] : [], args.addrs.aero];
1404
1504
  const pairs = connectorPairs(args.tokenIn, args.tokenOut, connectors);
1405
1505
  const clFactories = aerodromeClFactoryList(args.addrs);
1406
1506
  const spacingsByFactory = await Promise.all(
@@ -1420,10 +1520,10 @@ async function aerodromeDiscoverConnectorPools(args) {
1420
1520
  allowFailure: true,
1421
1521
  contracts: jobs.map(
1422
1522
  (job) => job.kind === "v2" ? {
1423
- address: args.addrs.poolFactory,
1424
- abi: v2PoolFactoryAbi,
1523
+ address: job.stable ? args.addrs.stablePoolFactory : args.addrs.volatilePoolFactory,
1524
+ abi: aeroV2FactoryAbi,
1425
1525
  functionName: "getPool",
1426
- args: [job.tokenA, job.tokenB, job.stable]
1526
+ args: [job.tokenA, job.tokenB]
1427
1527
  } : {
1428
1528
  address: job.factory,
1429
1529
  abi: clPoolFactoryAbi,
@@ -1451,7 +1551,7 @@ async function aerodromeDiscoverConnectorPools(args) {
1451
1551
  type: job.stable ? 0 : -1,
1452
1552
  token0: checksum(token0),
1453
1553
  token1: checksum(token1),
1454
- factory: args.addrs.poolFactory,
1554
+ factory: job.stable ? args.addrs.stablePoolFactory : args.addrs.volatilePoolFactory,
1455
1555
  poolFee: "0",
1456
1556
  kind: job.stable ? "stable" : "volatile"
1457
1557
  });
@@ -1470,11 +1570,11 @@ async function aerodromeDiscoverConnectorPools(args) {
1470
1570
  return pools;
1471
1571
  }
1472
1572
  async function aerodromeDiscoverConnectorPoolsLoaded(args) {
1473
- const addrs = await loadAerodromeAddresses();
1573
+ const addrs = await loadAerodromeAddresses(args.chainId);
1474
1574
  return aerodromeDiscoverConnectorPools({ ...args, addrs });
1475
1575
  }
1476
1576
  async function aerodromeDiscoverDirectPools(args) {
1477
- const addrs = await loadAerodromeAddresses();
1577
+ const addrs = await loadAerodromeAddresses(args.chainId);
1478
1578
  const client = aerodromePublicClient(args.rpcUrl);
1479
1579
  const tokenA = checksum(args.tokenA);
1480
1580
  const tokenB = checksum(args.tokenB);
@@ -1493,10 +1593,10 @@ async function aerodromeDiscoverDirectPools(args) {
1493
1593
  allowFailure: true,
1494
1594
  contracts: jobs.map(
1495
1595
  (job) => job.kind === "v2" ? {
1496
- address: addrs.poolFactory,
1497
- abi: v2PoolFactoryAbi,
1596
+ address: job.stable ? addrs.stablePoolFactory : addrs.volatilePoolFactory,
1597
+ abi: aeroV2FactoryAbi,
1498
1598
  functionName: "getPool",
1499
- args: [tokenA, tokenB, job.stable]
1599
+ args: [tokenA, tokenB]
1500
1600
  } : {
1501
1601
  address: job.factory,
1502
1602
  abi: clPoolFactoryAbi,
@@ -1524,7 +1624,7 @@ async function aerodromeDiscoverDirectPools(args) {
1524
1624
  type: job.stable ? 0 : -1,
1525
1625
  token0,
1526
1626
  token1,
1527
- factory: addrs.poolFactory,
1627
+ factory: job.stable ? addrs.stablePoolFactory : addrs.volatilePoolFactory,
1528
1628
  poolFee: "0",
1529
1629
  kind: job.stable ? "stable" : "volatile"
1530
1630
  });
@@ -1548,10 +1648,10 @@ function tokenLabel(raw, resolved, isNative) {
1548
1648
  }
1549
1649
  async function aerodromeDiscoverPoolsSummary(args) {
1550
1650
  if (!isAerodromeChainSupported(args.chainId)) {
1551
- throw new Error(`Aerodrome is Base-only (chainId ${exports.AERODROME_CHAIN_ID}).`);
1651
+ throw new Error(aerodromeUnsupportedChainMessage(args.chainId));
1552
1652
  }
1553
1653
  const rpcUrl = requireAerodromeRpcUrl(args.rpcUrl);
1554
- const addrs = await loadAerodromeAddresses();
1654
+ const addrs = await loadAerodromeAddresses(args.chainId);
1555
1655
  await ensureAerodromeStockTickers([args.token, args.tokenOut ?? ""]);
1556
1656
  const isNative = isAerodromeNativeToken(args.token);
1557
1657
  const token = resolveAerodromeErc20OrWeth(args.token, addrs.weth);
@@ -1567,7 +1667,7 @@ async function aerodromeDiscoverPoolsSummary(args) {
1567
1667
  const inLabel = tokenLabel(args.token, token, isNative);
1568
1668
  const outLabel = tokenLabel(counterpartRaw, tokenOut, isNativeOut);
1569
1669
  return {
1570
- chainId: exports.AERODROME_CHAIN_ID,
1670
+ chainId: args.chainId,
1571
1671
  token: {
1572
1672
  address: isNative ? viem.zeroAddress : token,
1573
1673
  symbol: inLabel,
@@ -1634,7 +1734,8 @@ function isMainPair(token0, token1, aero) {
1634
1734
  return mains.has(token0.toLowerCase()) && mains.has(token1.toLowerCase());
1635
1735
  }
1636
1736
  async function fetchSugarYieldPage(args) {
1637
- const addrs = await loadAerodromeAddresses();
1737
+ const addrs = await loadAerodromeAddresses(args.chainId);
1738
+ if (addrs.lpSugar === viem.zeroAddress) return [];
1638
1739
  const client = aerodromePublicClient(args.rpcUrl);
1639
1740
  const rows = await client.readContract({
1640
1741
  address: addrs.lpSugar,
@@ -1724,10 +1825,10 @@ function rankAndCap(rows, query) {
1724
1825
  filtered.sort((a, b) => (b.tvlUsd ?? 0) - (a.tvlUsd ?? 0));
1725
1826
  return filtered.slice(0, exports.AERODROME_IMPORTANT_POOL_CAP);
1726
1827
  }
1727
- async function scanSugarTop(rpcUrl) {
1828
+ async function scanSugarTop(chainId, rpcUrl) {
1728
1829
  const pages = [];
1729
1830
  for (let i = 0; i < SUGAR_SCAN_PAGES; i++) {
1730
- const page = await fetchSugarYieldPage({ rpcUrl, limit: SUGAR_PAGE, offset: i * SUGAR_PAGE });
1831
+ const page = await fetchSugarYieldPage({ chainId, rpcUrl, limit: SUGAR_PAGE, offset: i * SUGAR_PAGE });
1731
1832
  pages.push(page);
1732
1833
  if (page.length < SUGAR_PAGE) break;
1733
1834
  }
@@ -1735,24 +1836,25 @@ async function scanSugarTop(rpcUrl) {
1735
1836
  }
1736
1837
  async function aerodromeFetchImportantPoolsSummary(args) {
1737
1838
  if (!isAerodromeChainSupported(args.chainId)) {
1738
- throw new Error(`Aerodrome is Base-only (chainId ${exports.AERODROME_CHAIN_ID}).`);
1839
+ throw new Error(aerodromeUnsupportedChainMessage(args.chainId));
1739
1840
  }
1740
- const addrs = await loadAerodromeAddresses();
1741
- const scanned = await scanSugarTop(args.rpcUrl);
1841
+ const addrs = await loadAerodromeAddresses(args.chainId);
1842
+ const scanned = await scanSugarTop(args.chainId, args.rpcUrl);
1742
1843
  const aeroUsd = aeroUsdPriceFromRows(scanned, addrs.aero);
1743
1844
  const main = scanned.filter((r) => isMainPair(r.token0, r.token1, addrs.aero));
1744
1845
  const pools = rankAndCap(main.map((r) => toYieldRow(r, aeroUsd)), args.query);
1745
1846
  return {
1746
- chainId: exports.AERODROME_CHAIN_ID,
1847
+ chainId: args.chainId,
1747
1848
  pools,
1748
- notes: `At most ${exports.AERODROME_IMPORTANT_POOL_CAP} important Base pairs (ETH/WETH, USDC, AERO, major stables), TVL-ranked. Not an LpSugar.all dump. feeApr is omitted (Sugar exposes fee tier, not volume). emissionsApr uses on-chain AERO/USDC when priced.`
1849
+ notes: `At most ${exports.AERODROME_IMPORTANT_POOL_CAP} important pairs (ETH/WETH, USDC, AERO, major stables), TVL-ranked from the Base LpSugar index. feeApr is omitted. emissionsApr uses on-chain AERO/USDC when priced. Other Aero chains have no Sugar index, so this list is empty there \u2014 use ctm_aerodrome_discover_pools for a pair. AERO rewards on those chains are sAERO allocation, not a Sugar emissions APR.`
1749
1850
  };
1750
1851
  }
1751
1852
  async function aerodromeFetchLpYieldsSummary(args) {
1752
1853
  return aerodromeFetchImportantPoolsSummary(args);
1753
1854
  }
1754
- async function fetchSugarByAddress(rpcUrl, lp) {
1755
- const addrs = await loadAerodromeAddresses();
1855
+ async function fetchSugarByAddress(chainId, rpcUrl, lp) {
1856
+ const addrs = await loadAerodromeAddresses(chainId);
1857
+ if (addrs.lpSugar === viem.zeroAddress) return null;
1756
1858
  const client = aerodromePublicClient(rpcUrl);
1757
1859
  try {
1758
1860
  const p = await client.readContract({
@@ -1780,27 +1882,30 @@ async function fetchSugarByAddress(rpcUrl, lp) {
1780
1882
  return null;
1781
1883
  }
1782
1884
  }
1783
- function resolveYieldToken(addr, weth) {
1784
- if (isAerodromeNativeToken(addr)) return viem.getAddress(weth);
1785
- return viem.getAddress(addr);
1885
+ function resolveYieldToken(addr2, weth) {
1886
+ if (isAerodromeNativeToken(addr2)) return viem.getAddress(weth);
1887
+ return viem.getAddress(addr2);
1786
1888
  }
1787
- async function aeroUsdFromUsdcPool(rpcUrl, aero) {
1889
+ async function aeroUsdFromUsdcPool(chainId, rpcUrl, aero) {
1890
+ const usdc = aeroUsdcAddress(chainId);
1891
+ if (!usdc) return null;
1788
1892
  const aeroUsdc = await aerodromeDiscoverDirectPools({
1893
+ chainId,
1789
1894
  rpcUrl,
1790
1895
  tokenA: viem.getAddress(aero),
1791
- tokenB: viem.getAddress(exports.AERODROME_USDC_BASE)
1896
+ tokenB: usdc
1792
1897
  });
1793
1898
  const prefer = aeroUsdc.find((p) => p.kind === "volatile") ?? aeroUsdc[0];
1794
1899
  if (!prefer) return null;
1795
- const raw = await fetchSugarByAddress(rpcUrl, prefer.lp);
1900
+ const raw = await fetchSugarByAddress(chainId, rpcUrl, prefer.lp);
1796
1901
  return raw ? aeroUsdPriceFromRows([raw], aero) : null;
1797
1902
  }
1798
1903
  async function aerodromeFetchLpYieldsForPools(args) {
1799
1904
  if (!isAerodromeChainSupported(args.chainId)) {
1800
- throw new Error(`Aerodrome is Base-only (chainId ${exports.AERODROME_CHAIN_ID}).`);
1905
+ throw new Error(aerodromeUnsupportedChainMessage(args.chainId));
1801
1906
  }
1802
- const addrs = await loadAerodromeAddresses();
1803
- const aeroUsd = await aeroUsdFromUsdcPool(args.rpcUrl, addrs.aero);
1907
+ const addrs = await loadAerodromeAddresses(args.chainId);
1908
+ const aeroUsd = await aeroUsdFromUsdcPool(args.chainId, args.rpcUrl, addrs.aero);
1804
1909
  const seen = /* @__PURE__ */ new Set();
1805
1910
  const pools = [];
1806
1911
  for (const rawLp of args.lps) {
@@ -1812,24 +1917,24 @@ async function aerodromeFetchLpYieldsForPools(args) {
1812
1917
  }
1813
1918
  if (lp === viem.zeroAddress || seen.has(lp.toLowerCase())) continue;
1814
1919
  seen.add(lp.toLowerCase());
1815
- const raw = await fetchSugarByAddress(args.rpcUrl, lp);
1920
+ const raw = await fetchSugarByAddress(args.chainId, args.rpcUrl, lp);
1816
1921
  if (raw) pools.push(toYieldRow(raw, aeroUsd));
1817
1922
  }
1818
1923
  return {
1819
- chainId: exports.AERODROME_CHAIN_ID,
1924
+ chainId: args.chainId,
1820
1925
  pools,
1821
1926
  notes: "Same Sugar emissions formula as fetch_lp_yields (AERO/USDC priced). feeApr is omitted (Sugar has fee tier, not volume)."
1822
1927
  };
1823
1928
  }
1824
1929
  async function aerodromeFetchLpYieldsForPair(args) {
1825
1930
  if (!isAerodromeChainSupported(args.chainId)) {
1826
- throw new Error(`Aerodrome is Base-only (chainId ${exports.AERODROME_CHAIN_ID}).`);
1931
+ throw new Error(aerodromeUnsupportedChainMessage(args.chainId));
1827
1932
  }
1828
- const addrs = await loadAerodromeAddresses();
1933
+ const addrs = await loadAerodromeAddresses(args.chainId);
1829
1934
  const tokenA = resolveYieldToken(args.tokenA, addrs.weth);
1830
1935
  const tokenB = resolveYieldToken(args.tokenB, addrs.weth);
1831
1936
  if (tokenA.toLowerCase() === tokenB.toLowerCase()) {
1832
- return { chainId: exports.AERODROME_CHAIN_ID, pools: [], notes: "Pair tokens must differ." };
1937
+ return { chainId: args.chainId, pools: [], notes: "Pair tokens must differ." };
1833
1938
  }
1834
1939
  const discovered = await aerodromeDiscoverDirectPools({ rpcUrl: args.rpcUrl, tokenA, tokenB });
1835
1940
  return aerodromeFetchLpYieldsForPools({
@@ -1839,16 +1944,16 @@ async function aerodromeFetchLpYieldsForPair(args) {
1839
1944
  });
1840
1945
  }
1841
1946
  async function aerodromeFetchStockLpYieldsSummary(args) {
1842
- if (!isAerodromeChainSupported(args.chainId)) {
1843
- throw new Error(`Aerodrome is Base-only (chainId ${exports.AERODROME_CHAIN_ID}).`);
1947
+ if (args.chainId !== 8453) {
1948
+ throw new Error("Aero stock LP yields are Base (8453) only.");
1844
1949
  }
1845
- const addrs = await loadAerodromeAddresses();
1846
- const scanned = await scanSugarTop(args.rpcUrl);
1950
+ const addrs = await loadAerodromeAddresses(args.chainId);
1951
+ const scanned = await scanSugarTop(args.chainId, args.rpcUrl);
1847
1952
  const aeroUsd = aeroUsdPriceFromRows(scanned, addrs.aero);
1848
1953
  const stock = scanned.filter((r) => isCoinbaseB20AssetToken(r.token0) || isCoinbaseB20AssetToken(r.token1));
1849
1954
  const pools = rankAndCap(stock.map((r) => toYieldRow(r, aeroUsd)), args.query);
1850
1955
  return {
1851
- chainId: exports.AERODROME_CHAIN_ID,
1956
+ chainId: args.chainId,
1852
1957
  pools,
1853
1958
  notes: "Coinbase B20 stock LP yields only (typically STOCK/USDC Slipstream). Separate from main-pair fetch_lp_yields. HIP-3 / Arcus stock trading is not this list."
1854
1959
  };
@@ -1922,9 +2027,10 @@ async function paginate(pageSize, maxPages, readPage) {
1922
2027
  }
1923
2028
  async function aerodromeFetchListedTokens(args) {
1924
2029
  if (!isAerodromeChainSupported(args.chainId)) {
1925
- throw new Error(`Aerodrome is Base-only (chainId ${exports.AERODROME_CHAIN_ID}).`);
2030
+ throw new Error(aerodromeUnsupportedChainMessage(args.chainId));
1926
2031
  }
1927
- const addrs = await loadAerodromeAddresses();
2032
+ const addrs = await loadAerodromeAddresses(args.chainId);
2033
+ if (addrs.lpSugar === viem.zeroAddress) return [];
1928
2034
  await ensureCoinbaseB20StockCatalog().catch(() => []);
1929
2035
  const client = aerodromePublicClient(args.rpcUrl);
1930
2036
  const account = args.account?.trim() ? viem.getAddress(args.account) : viem.zeroAddress;
@@ -1965,9 +2071,10 @@ async function aerodromeFetchListedTokens(args) {
1965
2071
  }
1966
2072
  async function aerodromeFetchSwapPools(args) {
1967
2073
  if (!isAerodromeChainSupported(args.chainId)) {
1968
- throw new Error(`Aerodrome is Base-only (chainId ${exports.AERODROME_CHAIN_ID}).`);
2074
+ throw new Error(aerodromeUnsupportedChainMessage(args.chainId));
1969
2075
  }
1970
- const addrs = await loadAerodromeAddresses();
2076
+ const addrs = await loadAerodromeAddresses(args.chainId);
2077
+ if (addrs.lpSugar === viem.zeroAddress) return [];
1971
2078
  const client = aerodromePublicClient(args.rpcUrl);
1972
2079
  const rows = await paginate(
1973
2080
  200,
@@ -1991,9 +2098,10 @@ async function aerodromeFetchSwapPools(args) {
1991
2098
  }
1992
2099
  async function aerodromeFetchPools(args) {
1993
2100
  if (!isAerodromeChainSupported(args.chainId)) {
1994
- throw new Error(`Aerodrome is Base-only (chainId ${exports.AERODROME_CHAIN_ID}).`);
2101
+ throw new Error(aerodromeUnsupportedChainMessage(args.chainId));
1995
2102
  }
1996
- const addrs = await loadAerodromeAddresses();
2103
+ const addrs = await loadAerodromeAddresses(args.chainId);
2104
+ if (addrs.lpSugar === viem.zeroAddress) return [];
1997
2105
  const client = aerodromePublicClient(args.rpcUrl);
1998
2106
  const limit = BigInt(args.limit ?? 50);
1999
2107
  const offset = BigInt(args.offset ?? 0);
@@ -2022,9 +2130,10 @@ function mapSugarLp(p) {
2022
2130
  }
2023
2131
  async function aerodromeFetchPoolsByAddress(args) {
2024
2132
  if (!isAerodromeChainSupported(args.chainId)) {
2025
- throw new Error(`Aerodrome is Base-only (chainId ${exports.AERODROME_CHAIN_ID}).`);
2133
+ throw new Error(aerodromeUnsupportedChainMessage(args.chainId));
2026
2134
  }
2027
- const addrs = await loadAerodromeAddresses();
2135
+ const addrs = await loadAerodromeAddresses(args.chainId);
2136
+ if (addrs.lpSugar === viem.zeroAddress) return /* @__PURE__ */ new Map();
2028
2137
  const client = aerodromePublicClient(args.rpcUrl);
2029
2138
  const unique = [];
2030
2139
  const seen = /* @__PURE__ */ new Set();
@@ -2112,9 +2221,10 @@ async function aerodromeFetchPoolsByAddress(args) {
2112
2221
  }
2113
2222
  async function aerodromeFetchPositions(args) {
2114
2223
  if (!isAerodromeChainSupported(args.chainId)) {
2115
- throw new Error(`Aerodrome is Base-only (chainId ${exports.AERODROME_CHAIN_ID}).`);
2224
+ throw new Error(aerodromeUnsupportedChainMessage(args.chainId));
2116
2225
  }
2117
- const addrs = await loadAerodromeAddresses();
2226
+ const addrs = await loadAerodromeAddresses(args.chainId);
2227
+ if (addrs.lpSugar === viem.zeroAddress) return [];
2118
2228
  const client = aerodromePublicClient(args.rpcUrl);
2119
2229
  const account = viem.getAddress(args.account);
2120
2230
  const rows = await paginate(
@@ -2375,6 +2485,25 @@ function mergePools(into, extra) {
2375
2485
  }
2376
2486
  return out;
2377
2487
  }
2488
+ async function quoteViaPools(rpcUrl, amountIn, hops) {
2489
+ if (hops.length === 0 || hops.some((h) => h.kind === "cl")) return null;
2490
+ const client = aerodromePublicClient(rpcUrl);
2491
+ let cursor = amountIn;
2492
+ for (const hop of hops) {
2493
+ try {
2494
+ cursor = await client.readContract({
2495
+ address: hop.lp,
2496
+ abi: aeroPoolAmountOutAbi,
2497
+ functionName: "getAmountOut",
2498
+ args: [cursor, hop.from]
2499
+ });
2500
+ } catch {
2501
+ return null;
2502
+ }
2503
+ if (cursor <= 0n) return null;
2504
+ }
2505
+ return cursor;
2506
+ }
2378
2507
  async function quoteViaRouter(rpcUrl, router, amountIn, hops) {
2379
2508
  if (hops.some((h) => h.kind === "cl")) return null;
2380
2509
  const client = aerodromePublicClient(rpcUrl);
@@ -2410,6 +2539,8 @@ async function quoteViaMixedQuoter(rpcUrl, quoter, amountIn, hops, abi) {
2410
2539
  }
2411
2540
  }
2412
2541
  async function quoteAerodromeHopsAmountOut(args) {
2542
+ const viaPools = await quoteViaPools(args.rpcUrl, args.amountIn, args.hops);
2543
+ if (viaPools != null && viaPools > 0n) return { out: viaPools, source: "router" };
2413
2544
  const viaRouter = await quoteViaRouter(args.rpcUrl, args.router, args.amountIn, args.hops);
2414
2545
  if (viaRouter != null && viaRouter > 0n) return { out: viaRouter, source: "router" };
2415
2546
  const viaV3 = await quoteViaMixedQuoter(
@@ -2448,10 +2579,10 @@ async function throwIfUnissuedStock(args) {
2448
2579
  }
2449
2580
  async function aerodromeQuote(args) {
2450
2581
  if (!isAerodromeChainSupported(args.chainId)) {
2451
- throw new Error(`Aerodrome is Base-only (chainId ${exports.AERODROME_CHAIN_ID}).`);
2582
+ throw new Error(aerodromeUnsupportedChainMessage(args.chainId));
2452
2583
  }
2453
2584
  const rpcUrl = requireAerodromeRpcUrl(args.rpcUrl);
2454
- const addrs = await loadAerodromeAddresses();
2585
+ const addrs = await loadAerodromeAddresses(args.chainId);
2455
2586
  await ensureAerodromeStockTickers([args.tokenIn, args.tokenOut]);
2456
2587
  const isNativeIn = isAerodromeNativeToken(args.tokenIn);
2457
2588
  const isNativeOut = isAerodromeNativeToken(args.tokenOut);
@@ -2480,9 +2611,10 @@ async function aerodromeQuote(args) {
2480
2611
  let pools = await aerodromeDiscoverConnectorPools({ rpcUrl, tokenIn, tokenOut, addrs });
2481
2612
  let paths = findAerodromePaths(pools, tokenIn, tokenOut);
2482
2613
  if (paths.length === 0) {
2483
- const sugarPools = await aerodromeFetchSwapPools({ chainId: exports.AERODROME_CHAIN_ID, rpcUrl });
2614
+ const sugarPools = await aerodromeFetchSwapPools({ chainId: args.chainId, rpcUrl });
2484
2615
  pools = mergePools(pools, sugarPools);
2485
- const connectors = [addrs.weth, viem.getAddress(exports.AERODROME_USDC_BASE), addrs.aero];
2616
+ const usdc = aeroUsdcAddress(args.chainId);
2617
+ const connectors = [addrs.weth, ...usdc ? [usdc] : [], addrs.aero];
2486
2618
  const relevant = pools.filter((p) => {
2487
2619
  const a = p.token0.toLowerCase();
2488
2620
  const b = p.token1.toLowerCase();
@@ -2555,7 +2687,7 @@ async function aerodromeQuote(args) {
2555
2687
  }
2556
2688
  }
2557
2689
  return {
2558
- chainId: exports.AERODROME_CHAIN_ID,
2690
+ chainId: args.chainId,
2559
2691
  tokenIn: isNativeIn ? viem.zeroAddress : tokenIn,
2560
2692
  tokenOut: isNativeOut ? viem.zeroAddress : tokenOut,
2561
2693
  amountInWei: amountIn.toString(),
@@ -2857,7 +2989,7 @@ async function buildAerodromeMultisignBatch(args) {
2857
2989
  chainCategory: "evm",
2858
2990
  keyGen: args.keyGen,
2859
2991
  purposeText: args.purposeText,
2860
- chainId: exports.AERODROME_CHAIN_ID,
2992
+ chainId: args.chainId ?? exports.AERODROME_CHAIN_ID,
2861
2993
  rpcUrl: args.rpcUrl,
2862
2994
  executorAddress: executor,
2863
2995
  chainDetail: args.chainDetail,
@@ -2888,8 +3020,76 @@ function applySlippage(amountOut, slippagePercent) {
2888
3020
  const bps = BigInt(Math.round(slippagePercent * 100));
2889
3021
  return amountOut - amountOut * bps / 10000n;
2890
3022
  }
2891
- function routerRoutes(hops) {
2892
- return hops.map((h) => ({ from: h.from, to: h.to, stable: h.stable, factory: h.factory }));
3023
+ function encodeAeroV2ExactIn(args) {
3024
+ const commands = [];
3025
+ const inputs = [];
3026
+ const spend = (mode, amount) => viem.encodeAbiParameters(
3027
+ [
3028
+ { type: "uint8", name: "mode" },
3029
+ { type: "uint256", name: "value" }
3030
+ ],
3031
+ [mode, amount]
3032
+ );
3033
+ if (args.wrapNative) {
3034
+ commands.push(11);
3035
+ inputs.push(spend(0, args.amountIn));
3036
+ }
3037
+ commands.push(8);
3038
+ inputs.push(
3039
+ viem.encodeAbiParameters(
3040
+ [
3041
+ { type: "address[]", name: "pools" },
3042
+ { type: "address", name: "tokenIn" },
3043
+ {
3044
+ type: "tuple",
3045
+ name: "amountIn",
3046
+ components: [
3047
+ { name: "mode", type: "uint8" },
3048
+ { name: "value", type: "uint256" }
3049
+ ]
3050
+ },
3051
+ { type: "bool", name: "payerIsUser" },
3052
+ { type: "uint256", name: "minAmountOut" },
3053
+ { type: "address", name: "recipient" }
3054
+ ],
3055
+ [
3056
+ args.pools,
3057
+ args.wrapNative ? args.weth : args.tokenIn,
3058
+ { mode: 0, value: args.amountIn },
3059
+ !args.wrapNative,
3060
+ args.minOut,
3061
+ args.unwrapNative ? args.router : args.recipient
3062
+ ]
3063
+ )
3064
+ );
3065
+ if (args.unwrapNative) {
3066
+ commands.push(12);
3067
+ inputs.push(
3068
+ viem.encodeAbiParameters(
3069
+ [
3070
+ { type: "address", name: "recipient" },
3071
+ {
3072
+ type: "tuple",
3073
+ name: "spend",
3074
+ components: [
3075
+ { name: "mode", type: "uint8" },
3076
+ { name: "value", type: "uint256" }
3077
+ ]
3078
+ }
3079
+ ],
3080
+ [args.recipient, { mode: 1, value: 1000000n }]
3081
+ )
3082
+ );
3083
+ }
3084
+ const commandsBytes = `0x${commands.map((n) => n.toString(16).padStart(2, "0")).join("")}`;
3085
+ return {
3086
+ data: viem.encodeFunctionData({
3087
+ abi: aeroMetarouterAbi,
3088
+ functionName: "execute",
3089
+ args: [commandsBytes, inputs]
3090
+ }),
3091
+ value: args.wrapNative ? args.amountIn : 0n
3092
+ };
2893
3093
  }
2894
3094
  async function appendSequentialMixedHops(args) {
2895
3095
  let remainingIn = args.amountIn;
@@ -2952,63 +3152,41 @@ async function appendSequentialMixedHops(args) {
2952
3152
  rpcUrl: args.rpcUrl,
2953
3153
  token: hop.from,
2954
3154
  owner: args.executor,
2955
- spender: args.addrs.router,
3155
+ spender: args.addrs.metarouter,
2956
3156
  amountWei: remainingIn
2957
3157
  });
2958
3158
  }
2959
- const routes = routerRoutes([hop]);
2960
- if (payNative) {
2961
- args.steps.push({
2962
- to: args.addrs.router,
2963
- data: viem.encodeFunctionData({
2964
- abi: routerAbi,
2965
- functionName: "swapExactETHForTokens",
2966
- args: [hopOutMin, routes, args.executor, args.deadline]
2967
- }),
2968
- value: remainingIn,
2969
- kind: "swap",
2970
- routerSwap: true,
2971
- fallbackGas: 350000n
2972
- });
2973
- } else if (isLast && args.isNativeOut) {
2974
- args.steps.push({
2975
- to: args.addrs.router,
2976
- data: viem.encodeFunctionData({
2977
- abi: routerAbi,
2978
- functionName: "swapExactTokensForETH",
2979
- args: [remainingIn, hopOutMin, routes, args.executor, args.deadline]
2980
- }),
2981
- value: 0n,
2982
- kind: "swap",
2983
- routerSwap: true,
2984
- fallbackGas: 350000n
2985
- });
2986
- } else {
2987
- args.steps.push({
2988
- to: args.addrs.router,
2989
- data: viem.encodeFunctionData({
2990
- abi: routerAbi,
2991
- functionName: "swapExactTokensForTokens",
2992
- args: [remainingIn, hopOutMin, routes, args.executor, args.deadline]
2993
- }),
2994
- value: 0n,
2995
- kind: "swap",
2996
- routerSwap: true,
2997
- fallbackGas: 350000n
2998
- });
2999
- }
3159
+ const encoded = encodeAeroV2ExactIn({
3160
+ router: args.addrs.metarouter,
3161
+ weth: args.addrs.weth,
3162
+ pools: [hop.lp],
3163
+ tokenIn: hop.from,
3164
+ amountIn: remainingIn,
3165
+ minOut: hopOutMin,
3166
+ recipient: args.executor,
3167
+ wrapNative: payNative,
3168
+ unwrapNative: isLast && args.isNativeOut
3169
+ });
3170
+ args.steps.push({
3171
+ to: args.addrs.metarouter,
3172
+ data: encoded.data,
3173
+ value: encoded.value,
3174
+ kind: "swap",
3175
+ routerSwap: true,
3176
+ fallbackGas: 350000n
3177
+ });
3000
3178
  }
3001
3179
  remainingIn = hopOutMin;
3002
3180
  }
3003
3181
  }
3004
3182
  async function buildEvmMultisignBodyAerodromeSwapBatch(args) {
3005
- if (args.chainId !== exports.AERODROME_CHAIN_ID) {
3006
- throw new Error(`Aerodrome is Base-only (chainId ${exports.AERODROME_CHAIN_ID}).`);
3183
+ if (!isAerodromeChainSupported(args.chainId)) {
3184
+ throw new Error(aerodromeUnsupportedChainMessage(args.chainId));
3007
3185
  }
3008
3186
  const executor = viem.getAddress(args.executorAddress);
3009
- const addrs = await loadAerodromeAddresses();
3187
+ const addrs = await loadAerodromeAddresses(args.chainId);
3010
3188
  const quote = args.quoteSnapshot?.hops?.length && args.quoteSnapshot.amountOutWei ? args.quoteSnapshot : await aerodromeQuote({
3011
- chainId: exports.AERODROME_CHAIN_ID,
3189
+ chainId: args.chainId,
3012
3190
  rpcUrl: args.rpcUrl,
3013
3191
  tokenIn: args.tokenIn,
3014
3192
  tokenOut: args.tokenOut,
@@ -3021,12 +3199,12 @@ async function buildEvmMultisignBodyAerodromeSwapBatch(args) {
3021
3199
  const hops = quote.hops;
3022
3200
  const deadline = aerodromeOnChainDeadlineUnix(args.expiryDate);
3023
3201
  const steps = [];
3024
- const sdkTx = await tryAerodromeSdkUnsignedSwap({
3202
+ const sdkTx = hops.length === 0 ? await tryAerodromeSdkUnsignedSwap({
3025
3203
  rpcUrl: args.rpcUrl,
3026
3204
  account: executor,
3027
3205
  quote,
3028
3206
  slippage: args.slippagePercent / 100
3029
- });
3207
+ }) : null;
3030
3208
  if (sdkTx) {
3031
3209
  const tokenInAddr = viem.getAddress(isNativeIn ? addrs.weth : quote.tokenIn);
3032
3210
  if (!isNativeIn) {
@@ -3048,57 +3226,35 @@ async function buildEvmMultisignBodyAerodromeSwapBatch(args) {
3048
3226
  fallbackGas: 400000n
3049
3227
  });
3050
3228
  } else if (hops.length > 0 && hops.every((h) => h.kind !== "cl")) {
3051
- const routes = routerRoutes(hops);
3052
3229
  if (!isNativeIn) {
3053
3230
  await pushErc20ApproveIfNeeded({
3054
3231
  steps,
3055
3232
  rpcUrl: args.rpcUrl,
3056
3233
  token: hops[0].from,
3057
3234
  owner: executor,
3058
- spender: addrs.router,
3235
+ spender: addrs.metarouter,
3059
3236
  amountWei: amountIn
3060
3237
  });
3061
3238
  }
3062
- if (isNativeIn) {
3063
- steps.push({
3064
- to: addrs.router,
3065
- data: viem.encodeFunctionData({
3066
- abi: routerAbi,
3067
- functionName: "swapExactETHForTokens",
3068
- args: [amountOutMin, routes, executor, deadline]
3069
- }),
3070
- value: amountIn,
3071
- kind: "swap",
3072
- routerSwap: true,
3073
- fallbackGas: 350000n
3074
- });
3075
- } else if (isNativeOut) {
3076
- steps.push({
3077
- to: addrs.router,
3078
- data: viem.encodeFunctionData({
3079
- abi: routerAbi,
3080
- functionName: "swapExactTokensForETH",
3081
- args: [amountIn, amountOutMin, routes, executor, deadline]
3082
- }),
3083
- value: 0n,
3084
- kind: "swap",
3085
- routerSwap: true,
3086
- fallbackGas: 350000n
3087
- });
3088
- } else {
3089
- steps.push({
3090
- to: addrs.router,
3091
- data: viem.encodeFunctionData({
3092
- abi: routerAbi,
3093
- functionName: "swapExactTokensForTokens",
3094
- args: [amountIn, amountOutMin, routes, executor, deadline]
3095
- }),
3096
- value: 0n,
3097
- kind: "swap",
3098
- routerSwap: true,
3099
- fallbackGas: 350000n
3100
- });
3101
- }
3239
+ const encoded = encodeAeroV2ExactIn({
3240
+ router: addrs.metarouter,
3241
+ weth: addrs.weth,
3242
+ pools: hops.map((h) => h.lp),
3243
+ tokenIn: hops[0].from,
3244
+ amountIn,
3245
+ minOut: amountOutMin,
3246
+ recipient: executor,
3247
+ wrapNative: isNativeIn,
3248
+ unwrapNative: isNativeOut
3249
+ });
3250
+ steps.push({
3251
+ to: addrs.metarouter,
3252
+ data: encoded.data,
3253
+ value: encoded.value,
3254
+ kind: "swap",
3255
+ routerSwap: true,
3256
+ fallbackGas: 350000n
3257
+ });
3102
3258
  } else if (hops.length === 1 && hops[0].kind === "cl") {
3103
3259
  const hop = hops[0];
3104
3260
  const swapRouter = aerodromeClSwapRouterForFactory(addrs, hop.factory);
@@ -3157,6 +3313,7 @@ async function buildEvmMultisignBodyAerodromeSwapBatch(args) {
3157
3313
  return buildAerodromeMultisignBatch({
3158
3314
  keyGen: args.keyGen,
3159
3315
  rpcUrl: args.rpcUrl,
3316
+ chainId: args.chainId,
3160
3317
  chainDetail: args.chainDetail,
3161
3318
  useCustomGas: args.useCustomGas,
3162
3319
  customGasChainDetails: args.customGasChainDetails,
@@ -3171,14 +3328,14 @@ async function buildEvmMultisignBodyAerodromeSwapBatch(args) {
3171
3328
  name: "ERC20.approve",
3172
3329
  note: "Allowance for this swap amount only."
3173
3330
  }),
3174
- evm: { type: "aerodrome_erc20_approve", version: 1, chainId: String(exports.AERODROME_CHAIN_ID) }
3331
+ evm: { type: "aerodrome_erc20_approve", version: 1, chainId: String(args.chainId) }
3175
3332
  } : {
3176
3333
  signatureText: JSON.stringify({
3177
3334
  kind: "Aerodrome",
3178
3335
  name: "swap",
3179
3336
  hops: hops.map((h) => ({ from: h.from, to: h.to, kind: h.kind }))
3180
3337
  }),
3181
- evm: { type: "aerodrome_swap", version: 1, chainId: String(exports.AERODROME_CHAIN_ID) }
3338
+ evm: { type: "aerodrome_swap", version: 1, chainId: String(args.chainId) }
3182
3339
  }
3183
3340
  });
3184
3341
  }
@@ -3220,9 +3377,9 @@ function formatLpHuman(wei, decimals) {
3220
3377
  }
3221
3378
  async function aerodromeQuoteAddLiquidity(args) {
3222
3379
  if (!isAerodromeChainSupported(args.chainId)) {
3223
- throw new Error(`Aerodrome is Base-only (chainId ${exports.AERODROME_CHAIN_ID}).`);
3380
+ throw new Error(aerodromeUnsupportedChainMessage(args.chainId));
3224
3381
  }
3225
- const addrs = await loadAerodromeAddresses();
3382
+ const addrs = await loadAerodromeAddresses(args.chainId);
3226
3383
  const client = aerodromePublicClient(args.rpcUrl);
3227
3384
  await ensureAerodromeStockTickers([args.tokenA, args.tokenB]);
3228
3385
  const isNativeA = isAerodromeNativeToken(args.tokenA);
@@ -3269,6 +3426,7 @@ async function aerodromeQuoteAddLiquidity(args) {
3269
3426
  const amountBParsed = rawB ? viem.parseUnits(rawB, decB) : 0n;
3270
3427
  if (emptyPool) {
3271
3428
  const cl = await quoteClPairRatio({
3429
+ chainId: args.chainId,
3272
3430
  rpcUrl: args.rpcUrl,
3273
3431
  tokenA,
3274
3432
  tokenB,
@@ -3313,6 +3471,11 @@ async function aerodromeQuoteAddLiquidity(args) {
3313
3471
  }
3314
3472
  const amountADesired = rawA ? amountAParsed : OTHER_SIDE_DESIRED;
3315
3473
  const amountBDesired = rawB ? amountBParsed : OTHER_SIDE_DESIRED;
3474
+ if (addrs.router.toLowerCase() === addrs.metarouter.toLowerCase()) {
3475
+ throw new Error(
3476
+ "Aero v2 add-liquidity on this chain uses the Metarouter and is not encoded yet. Base still quotes through the legacy router."
3477
+ );
3478
+ }
3316
3479
  const [amountA, amountB, liquidity] = await client.readContract({
3317
3480
  address: addrs.router,
3318
3481
  abi: routerAbi,
@@ -3338,6 +3501,7 @@ async function aerodromeQuoteAddLiquidity(args) {
3338
3501
  }
3339
3502
  async function quoteClPairRatio(args) {
3340
3503
  const directs = await aerodromeDiscoverDirectPools({
3504
+ chainId: args.chainId,
3341
3505
  rpcUrl: args.rpcUrl,
3342
3506
  tokenA: args.tokenA,
3343
3507
  tokenB: args.tokenB
@@ -3369,7 +3533,7 @@ async function quoteClPairRatio(args) {
3369
3533
  if (!best) return null;
3370
3534
  const token0 = args.tokenA.toLowerCase() < args.tokenB.toLowerCase() ? args.tokenA : args.tokenB;
3371
3535
  const aIs0 = args.tokenA.toLowerCase() === token0.toLowerCase();
3372
- const addrs = await loadAerodromeAddresses();
3536
+ const addrs = await loadAerodromeAddresses(args.chainId);
3373
3537
  let amount0 = aIs0 ? args.amountAParsed : args.amountBParsed;
3374
3538
  let amount1 = aIs0 ? args.amountBParsed : args.amountAParsed;
3375
3539
  if (args.rawA && !args.rawB) {
@@ -3426,7 +3590,7 @@ function minAfterSlippage(amount, slippagePercent) {
3426
3590
  }
3427
3591
  async function buildEvmMultisignBodyAerodromeAddLiquidityBatch(args) {
3428
3592
  const executor = viem.getAddress(args.executorAddress);
3429
- const addrs = await loadAerodromeAddresses();
3593
+ const addrs = await loadAerodromeAddresses(args.chainId);
3430
3594
  const quote = await aerodromeQuoteAddLiquidity({
3431
3595
  chainId: args.chainId,
3432
3596
  rpcUrl: args.rpcUrl,
@@ -3515,6 +3679,7 @@ async function buildEvmMultisignBodyAerodromeAddLiquidityBatch(args) {
3515
3679
  return buildAerodromeMultisignBatch({
3516
3680
  keyGen: args.keyGen,
3517
3681
  rpcUrl: args.rpcUrl,
3682
+ chainId: args.chainId,
3518
3683
  chainDetail: args.chainDetail,
3519
3684
  useCustomGas: args.useCustomGas,
3520
3685
  customGasChainDetails: args.customGasChainDetails,
@@ -3525,13 +3690,13 @@ async function buildEvmMultisignBodyAerodromeAddLiquidityBatch(args) {
3525
3690
  purposeSuffix: "Aerodrome: add basic-pool liquidity.",
3526
3691
  meta: () => ({
3527
3692
  signatureText: JSON.stringify({ kind: "Aerodrome", name: "addLiquidity", stable: args.stable }),
3528
- evm: { type: "aerodrome_add_liquidity", version: 1, chainId: String(exports.AERODROME_CHAIN_ID) }
3693
+ evm: { type: "aerodrome_add_liquidity", version: 1, chainId: String(args.chainId) }
3529
3694
  })
3530
3695
  });
3531
3696
  }
3532
3697
  async function buildEvmMultisignBodyAerodromeRemoveLiquidityBatch(args) {
3533
3698
  const executor = viem.getAddress(args.executorAddress);
3534
- const addrs = await loadAerodromeAddresses();
3699
+ const addrs = await loadAerodromeAddresses(args.chainId);
3535
3700
  const client = aerodromePublicClient(args.rpcUrl);
3536
3701
  const lp = viem.getAddress(args.lpToken);
3537
3702
  const dec = args.lpDecimals ?? Number(await client.readContract({ address: lp, abi: erc20Abi, functionName: "decimals" }));
@@ -3582,6 +3747,7 @@ async function buildEvmMultisignBodyAerodromeRemoveLiquidityBatch(args) {
3582
3747
  return buildAerodromeMultisignBatch({
3583
3748
  keyGen: args.keyGen,
3584
3749
  rpcUrl: args.rpcUrl,
3750
+ chainId: args.chainId,
3585
3751
  chainDetail: args.chainDetail,
3586
3752
  useCustomGas: args.useCustomGas,
3587
3753
  customGasChainDetails: args.customGasChainDetails,
@@ -3592,7 +3758,7 @@ async function buildEvmMultisignBodyAerodromeRemoveLiquidityBatch(args) {
3592
3758
  purposeSuffix: "Aerodrome: remove basic-pool liquidity.",
3593
3759
  meta: () => ({
3594
3760
  signatureText: JSON.stringify({ kind: "Aerodrome", name: "removeLiquidity", lp }),
3595
- evm: { type: "aerodrome_remove_liquidity", version: 1, chainId: String(exports.AERODROME_CHAIN_ID) }
3761
+ evm: { type: "aerodrome_remove_liquidity", version: 1, chainId: String(args.chainId) }
3596
3762
  })
3597
3763
  });
3598
3764
  }
@@ -3605,9 +3771,9 @@ init_stockTokens();
3605
3771
  init_support();
3606
3772
  async function aerodromeQuoteClDeposit(args) {
3607
3773
  if (!isAerodromeChainSupported(args.chainId)) {
3608
- throw new Error(`Aerodrome is Base-only (chainId ${exports.AERODROME_CHAIN_ID}).`);
3774
+ throw new Error(aerodromeUnsupportedChainMessage(args.chainId));
3609
3775
  }
3610
- const addrs = await loadAerodromeAddresses();
3776
+ const addrs = await loadAerodromeAddresses(args.chainId);
3611
3777
  const client = aerodromePublicClient(args.rpcUrl);
3612
3778
  await ensureAerodromeStockTickers([args.token0, args.token1]);
3613
3779
  const token0 = resolveAerodromeErc20OrWeth(args.token0, addrs.weth);
@@ -3665,7 +3831,7 @@ function minAfterSlippage2(amount, slippagePercent) {
3665
3831
  }
3666
3832
  async function buildEvmMultisignBodyAerodromeClMintBatch(args) {
3667
3833
  const executor = viem.getAddress(args.executorAddress);
3668
- const addrs = await loadAerodromeAddresses();
3834
+ const addrs = await loadAerodromeAddresses(args.chainId);
3669
3835
  const quote = await aerodromeQuoteClDeposit({
3670
3836
  chainId: args.chainId,
3671
3837
  rpcUrl: args.rpcUrl,
@@ -3736,6 +3902,7 @@ async function buildEvmMultisignBodyAerodromeClMintBatch(args) {
3736
3902
  return buildAerodromeMultisignBatch({
3737
3903
  keyGen: args.keyGen,
3738
3904
  rpcUrl: args.rpcUrl,
3905
+ chainId: args.chainId,
3739
3906
  chainDetail: args.chainDetail,
3740
3907
  useCustomGas: args.useCustomGas,
3741
3908
  customGasChainDetails: args.customGasChainDetails,
@@ -3746,13 +3913,13 @@ async function buildEvmMultisignBodyAerodromeClMintBatch(args) {
3746
3913
  purposeSuffix: "Aerodrome Slipstream: mint concentrated position NFT.",
3747
3914
  meta: () => ({
3748
3915
  signatureText: JSON.stringify({ kind: "Aerodrome", name: "nfpm.mint" }),
3749
- evm: { type: "aerodrome_cl_mint", version: 1, chainId: String(exports.AERODROME_CHAIN_ID) }
3916
+ evm: { type: "aerodrome_cl_mint", version: 1, chainId: String(args.chainId) }
3750
3917
  })
3751
3918
  });
3752
3919
  }
3753
3920
  async function buildEvmMultisignBodyAerodromeClIncreaseBatch(args) {
3754
3921
  const executor = viem.getAddress(args.executorAddress);
3755
- const addrs = await loadAerodromeAddresses();
3922
+ const addrs = await loadAerodromeAddresses(args.chainId);
3756
3923
  const amount0 = BigInt(args.amount0Wei);
3757
3924
  const amount1 = BigInt(args.amount1Wei);
3758
3925
  await ensureAerodromeStockTickers([args.token0, args.token1]);
@@ -3803,6 +3970,7 @@ async function buildEvmMultisignBodyAerodromeClIncreaseBatch(args) {
3803
3970
  return buildAerodromeMultisignBatch({
3804
3971
  keyGen: args.keyGen,
3805
3972
  rpcUrl: args.rpcUrl,
3973
+ chainId: args.chainId,
3806
3974
  chainDetail: args.chainDetail,
3807
3975
  useCustomGas: args.useCustomGas,
3808
3976
  customGasChainDetails: args.customGasChainDetails,
@@ -3813,13 +3981,13 @@ async function buildEvmMultisignBodyAerodromeClIncreaseBatch(args) {
3813
3981
  purposeSuffix: "Aerodrome Slipstream: increase liquidity.",
3814
3982
  meta: () => ({
3815
3983
  signatureText: JSON.stringify({ kind: "Aerodrome", name: "nfpm.increaseLiquidity", tokenId: args.tokenId }),
3816
- evm: { type: "aerodrome_cl_increase", version: 1, chainId: String(exports.AERODROME_CHAIN_ID) }
3984
+ evm: { type: "aerodrome_cl_increase", version: 1, chainId: String(args.chainId) }
3817
3985
  })
3818
3986
  });
3819
3987
  }
3820
3988
  async function buildEvmMultisignBodyAerodromeClDecreaseBatch(args) {
3821
3989
  const executor = viem.getAddress(args.executorAddress);
3822
- const addrs = await loadAerodromeAddresses();
3990
+ const addrs = await loadAerodromeAddresses(args.chainId);
3823
3991
  const steps = [
3824
3992
  {
3825
3993
  to: addrs.nfpm,
@@ -3844,6 +4012,7 @@ async function buildEvmMultisignBodyAerodromeClDecreaseBatch(args) {
3844
4012
  return buildAerodromeMultisignBatch({
3845
4013
  keyGen: args.keyGen,
3846
4014
  rpcUrl: args.rpcUrl,
4015
+ chainId: args.chainId,
3847
4016
  chainDetail: args.chainDetail,
3848
4017
  useCustomGas: args.useCustomGas,
3849
4018
  customGasChainDetails: args.customGasChainDetails,
@@ -3854,13 +4023,13 @@ async function buildEvmMultisignBodyAerodromeClDecreaseBatch(args) {
3854
4023
  purposeSuffix: "Aerodrome Slipstream: decrease liquidity.",
3855
4024
  meta: () => ({
3856
4025
  signatureText: JSON.stringify({ kind: "Aerodrome", name: "nfpm.decreaseLiquidity", tokenId: args.tokenId }),
3857
- evm: { type: "aerodrome_cl_decrease", version: 1, chainId: String(exports.AERODROME_CHAIN_ID) }
4026
+ evm: { type: "aerodrome_cl_decrease", version: 1, chainId: String(args.chainId) }
3858
4027
  })
3859
4028
  });
3860
4029
  }
3861
4030
  async function buildEvmMultisignBodyAerodromeClCollectBatch(args) {
3862
4031
  const executor = viem.getAddress(args.executorAddress);
3863
- const addrs = await loadAerodromeAddresses();
4032
+ const addrs = await loadAerodromeAddresses(args.chainId);
3864
4033
  const max = 2n ** 128n - 1n;
3865
4034
  const steps = [
3866
4035
  {
@@ -3878,6 +4047,7 @@ async function buildEvmMultisignBodyAerodromeClCollectBatch(args) {
3878
4047
  return buildAerodromeMultisignBatch({
3879
4048
  keyGen: args.keyGen,
3880
4049
  rpcUrl: args.rpcUrl,
4050
+ chainId: args.chainId,
3881
4051
  chainDetail: args.chainDetail,
3882
4052
  useCustomGas: args.useCustomGas,
3883
4053
  customGasChainDetails: args.customGasChainDetails,
@@ -3888,13 +4058,13 @@ async function buildEvmMultisignBodyAerodromeClCollectBatch(args) {
3888
4058
  purposeSuffix: "Aerodrome Slipstream: collect fees.",
3889
4059
  meta: () => ({
3890
4060
  signatureText: JSON.stringify({ kind: "Aerodrome", name: "nfpm.collect", tokenId: args.tokenId }),
3891
- evm: { type: "aerodrome_cl_collect", version: 1, chainId: String(exports.AERODROME_CHAIN_ID) }
4061
+ evm: { type: "aerodrome_cl_collect", version: 1, chainId: String(args.chainId) }
3892
4062
  })
3893
4063
  });
3894
4064
  }
3895
4065
  async function buildEvmMultisignBodyAerodromeClBurnBatch(args) {
3896
4066
  const executor = viem.getAddress(args.executorAddress);
3897
- const addrs = await loadAerodromeAddresses();
4067
+ const addrs = await loadAerodromeAddresses(args.chainId);
3898
4068
  const steps = [
3899
4069
  {
3900
4070
  to: addrs.nfpm,
@@ -3911,6 +4081,7 @@ async function buildEvmMultisignBodyAerodromeClBurnBatch(args) {
3911
4081
  return buildAerodromeMultisignBatch({
3912
4082
  keyGen: args.keyGen,
3913
4083
  rpcUrl: args.rpcUrl,
4084
+ chainId: args.chainId,
3914
4085
  chainDetail: args.chainDetail,
3915
4086
  useCustomGas: args.useCustomGas,
3916
4087
  customGasChainDetails: args.customGasChainDetails,
@@ -3921,14 +4092,13 @@ async function buildEvmMultisignBodyAerodromeClBurnBatch(args) {
3921
4092
  purposeSuffix: "Aerodrome Slipstream: burn empty position NFT.",
3922
4093
  meta: () => ({
3923
4094
  signatureText: JSON.stringify({ kind: "Aerodrome", name: "nfpm.burn", tokenId: args.tokenId }),
3924
- evm: { type: "aerodrome_cl_burn", version: 1, chainId: String(exports.AERODROME_CHAIN_ID) }
4095
+ evm: { type: "aerodrome_cl_burn", version: 1, chainId: String(args.chainId) }
3925
4096
  })
3926
4097
  });
3927
4098
  }
3928
4099
 
3929
4100
  // src/protocols/evm/aerodrome/gaugeMultisign.ts
3930
4101
  init_abi();
3931
- init_support();
3932
4102
  async function buildEvmMultisignBodyAerodromeGaugeStakeBatch(args) {
3933
4103
  const executor = viem.getAddress(args.executorAddress);
3934
4104
  const gauge = viem.getAddress(args.gauge);
@@ -3978,6 +4148,7 @@ async function buildEvmMultisignBodyAerodromeGaugeStakeBatch(args) {
3978
4148
  return buildAerodromeMultisignBatch({
3979
4149
  keyGen: args.keyGen,
3980
4150
  rpcUrl: args.rpcUrl,
4151
+ chainId: args.chainId,
3981
4152
  chainDetail: args.chainDetail,
3982
4153
  useCustomGas: args.useCustomGas,
3983
4154
  customGasChainDetails: args.customGasChainDetails,
@@ -3988,7 +4159,7 @@ async function buildEvmMultisignBodyAerodromeGaugeStakeBatch(args) {
3988
4159
  purposeSuffix: "Aerodrome: stake LP in gauge.",
3989
4160
  meta: () => ({
3990
4161
  signatureText: JSON.stringify({ kind: "Aerodrome", name: "gauge.deposit" }),
3991
- evm: { type: "aerodrome_gauge_stake", version: 1, chainId: String(exports.AERODROME_CHAIN_ID) }
4162
+ evm: { type: "aerodrome_gauge_stake", version: 1, chainId: String(args.chainId) }
3992
4163
  })
3993
4164
  });
3994
4165
  }
@@ -4023,6 +4194,7 @@ async function buildEvmMultisignBodyAerodromeGaugeUnstakeBatch(args) {
4023
4194
  return buildAerodromeMultisignBatch({
4024
4195
  keyGen: args.keyGen,
4025
4196
  rpcUrl: args.rpcUrl,
4197
+ chainId: args.chainId,
4026
4198
  chainDetail: args.chainDetail,
4027
4199
  useCustomGas: args.useCustomGas,
4028
4200
  customGasChainDetails: args.customGasChainDetails,
@@ -4033,7 +4205,7 @@ async function buildEvmMultisignBodyAerodromeGaugeUnstakeBatch(args) {
4033
4205
  purposeSuffix: "Aerodrome: unstake LP from gauge.",
4034
4206
  meta: () => ({
4035
4207
  signatureText: JSON.stringify({ kind: "Aerodrome", name: "gauge.withdraw" }),
4036
- evm: { type: "aerodrome_gauge_unstake", version: 1, chainId: String(exports.AERODROME_CHAIN_ID) }
4208
+ evm: { type: "aerodrome_gauge_unstake", version: 1, chainId: String(args.chainId) }
4037
4209
  })
4038
4210
  });
4039
4211
  }
@@ -4052,6 +4224,7 @@ async function buildEvmMultisignBodyAerodromeClaimFeesBatch(args) {
4052
4224
  return buildAerodromeMultisignBatch({
4053
4225
  keyGen: args.keyGen,
4054
4226
  rpcUrl: args.rpcUrl,
4227
+ chainId: args.chainId,
4055
4228
  chainDetail: args.chainDetail,
4056
4229
  useCustomGas: args.useCustomGas,
4057
4230
  customGasChainDetails: args.customGasChainDetails,
@@ -4062,7 +4235,7 @@ async function buildEvmMultisignBodyAerodromeClaimFeesBatch(args) {
4062
4235
  purposeSuffix: "Aerodrome: claim basic-pool fees.",
4063
4236
  meta: () => ({
4064
4237
  signatureText: JSON.stringify({ kind: "Aerodrome", name: "pool.claimFees", pool }),
4065
- evm: { type: "aerodrome_claim_fees", version: 1, chainId: String(exports.AERODROME_CHAIN_ID) }
4238
+ evm: { type: "aerodrome_claim_fees", version: 1, chainId: String(args.chainId) }
4066
4239
  })
4067
4240
  });
4068
4241
  }
@@ -4095,6 +4268,7 @@ async function buildEvmMultisignBodyAerodromeClaimEmissionsBatch(args) {
4095
4268
  return buildAerodromeMultisignBatch({
4096
4269
  keyGen: args.keyGen,
4097
4270
  rpcUrl: args.rpcUrl,
4271
+ chainId: args.chainId,
4098
4272
  chainDetail: args.chainDetail,
4099
4273
  useCustomGas: args.useCustomGas,
4100
4274
  customGasChainDetails: args.customGasChainDetails,
@@ -4105,7 +4279,7 @@ async function buildEvmMultisignBodyAerodromeClaimEmissionsBatch(args) {
4105
4279
  purposeSuffix: "Aerodrome: claim gauge emissions.",
4106
4280
  meta: () => ({
4107
4281
  signatureText: JSON.stringify({ kind: "Aerodrome", name: "gauge.getReward" }),
4108
- evm: { type: "aerodrome_claim_emissions", version: 1, chainId: String(exports.AERODROME_CHAIN_ID) }
4282
+ evm: { type: "aerodrome_claim_emissions", version: 1, chainId: String(args.chainId) }
4109
4283
  })
4110
4284
  });
4111
4285
  }
@@ -4172,38 +4346,53 @@ function mergeStocksIntoListed(tokens, stocks) {
4172
4346
  return [...stocksFirst, ...rest];
4173
4347
  }
4174
4348
  async function aerodromeFetchListedTokensSummary(args) {
4175
- const includeSugar = args.includeSugarListed !== false;
4176
- const officialPromise = fetchOfficialBaseTokenizedStocks().catch(() => []);
4349
+ const includeSugar = args.includeSugarListed !== false && args.chainId === 8453;
4350
+ const officialPromise = args.chainId === 8453 ? fetchOfficialBaseTokenizedStocks().catch(() => []) : Promise.resolve([]);
4177
4351
  const tokens = includeSugar ? await aerodromeFetchListedTokens(args) : [];
4178
4352
  const official = await officialPromise;
4179
- const stocks = await aerodromeResolveStockTokens({
4353
+ const stocks = args.chainId === 8453 ? await aerodromeResolveStockTokens({
4180
4354
  rpcUrl: args.rpcUrl,
4181
4355
  official,
4182
4356
  knownTokens: tokens
4183
- });
4184
- const addrs = await loadAerodromeAddresses();
4357
+ }) : [];
4358
+ const addrs = await loadAerodromeAddresses(args.chainId);
4359
+ const usdc = aeroUsdcAddress(args.chainId);
4185
4360
  const core = [
4186
4361
  { address: viem.zeroAddress, symbol: "ETH", decimals: 18, listed: true, emerging: false, accountBalance: "0" },
4187
- {
4188
- address: exports.AERODROME_WETH_BASE,
4189
- symbol: "WETH",
4190
- decimals: 18,
4191
- listed: true,
4192
- emerging: false,
4193
- accountBalance: "0"
4194
- },
4195
- {
4196
- address: exports.AERODROME_USDC_BASE,
4197
- symbol: "USDC",
4198
- decimals: 6,
4199
- listed: true,
4200
- emerging: false,
4201
- accountBalance: "0"
4202
- },
4203
- { address: addrs.aero, symbol: "AERO", decimals: 18, listed: true, emerging: false, accountBalance: "0" }
4362
+ ...addrs.weth === viem.zeroAddress ? [] : [
4363
+ {
4364
+ address: addrs.weth,
4365
+ symbol: "WETH",
4366
+ decimals: 18,
4367
+ listed: true,
4368
+ emerging: false,
4369
+ accountBalance: "0"
4370
+ }
4371
+ ],
4372
+ ...usdc ? [
4373
+ {
4374
+ address: usdc,
4375
+ symbol: "USDC",
4376
+ decimals: 6,
4377
+ listed: true,
4378
+ emerging: false,
4379
+ accountBalance: "0"
4380
+ }
4381
+ ] : [],
4382
+ { address: addrs.aero, symbol: "AERO", decimals: 18, listed: true, emerging: false, accountBalance: "0" },
4383
+ ...addrs.receiptToken.toLowerCase() === addrs.aero.toLowerCase() ? [] : [
4384
+ {
4385
+ address: addrs.receiptToken,
4386
+ symbol: "xAERO",
4387
+ decimals: 18,
4388
+ listed: true,
4389
+ emerging: false,
4390
+ accountBalance: "0"
4391
+ }
4392
+ ]
4204
4393
  ];
4205
4394
  return {
4206
- chainId: exports.AERODROME_CHAIN_ID,
4395
+ chainId: args.chainId,
4207
4396
  native: { address: viem.zeroAddress, symbol: "ETH", decimals: 18 },
4208
4397
  aero: { address: addrs.aero, symbol: "AERO", decimals: 18 },
4209
4398
  stocks,
@@ -4222,7 +4411,7 @@ async function aerodromeFetchPoolsSummary(args) {
4222
4411
  const offset = Math.max(0, args.offset ?? 0);
4223
4412
  const limit = Math.min(Math.max(args.limit ?? pools.length, 1), pools.length);
4224
4413
  return {
4225
- chainId: exports.AERODROME_CHAIN_ID,
4414
+ chainId: args.chainId,
4226
4415
  pools: pools.slice(offset, offset + limit),
4227
4416
  notes
4228
4417
  };
@@ -4231,7 +4420,7 @@ async function aerodromeFetchPositionsSummary(args) {
4231
4420
  const account = (args.account ?? args.executorAddress ?? "").trim();
4232
4421
  if (!account) throw new Error("account or executorAddress is required.");
4233
4422
  if (!isAerodromeChainSupported(args.chainId)) {
4234
- throw new Error(`Aerodrome is Base-only (chainId ${exports.AERODROME_CHAIN_ID}).`);
4423
+ throw new Error(aerodromeUnsupportedChainMessage(args.chainId));
4235
4424
  }
4236
4425
  const positions = await aerodromeFetchPositionsWithPools({
4237
4426
  chainId: args.chainId,
@@ -4239,7 +4428,7 @@ async function aerodromeFetchPositionsSummary(args) {
4239
4428
  account
4240
4429
  });
4241
4430
  return {
4242
- chainId: exports.AERODROME_CHAIN_ID,
4431
+ chainId: args.chainId,
4243
4432
  account,
4244
4433
  notes: "Dust v2 rows hidden (liquidity < 1e12 and no stake/emissions). Claim fees from the pool (claimFees.pool = lp). Claim emissions from the gauge in AERO (claimEmissions); CL staked also needs tokenId + cl. Skip emissions when claimEmissions is null.",
4245
4434
  positions: positions.map((p) => {
@@ -4276,10 +4465,10 @@ var aerodromeProtocolModule = {
4276
4465
  id: "aerodrome.quote",
4277
4466
  protocolId: exports.AERODROME_PROTOCOL_ID,
4278
4467
  chainCategory: "evm",
4279
- description: "Quote an Aerodrome swap on Base via factory discovery + MixedRouteQuoterV3 / Router. Tickers (AAPLc, USDC, ETH) accepted.",
4468
+ description: "Quote an Aero swap (protocol id aerodrome) via factory discovery and pool getAmountOut / Metaquoter. Base 8453 by default; also Ethereum, OP Mainnet, Arbitrum, Robinhood, Arc, and Ink. Tickers (AAPLc, USDC, ETH) accepted. Stock tickers are Base only.",
4280
4469
  commonParams: [],
4281
4470
  params: {
4282
- chainId: { type: "number", required: true, description: `Must be ${exports.AERODROME_CHAIN_ID}` },
4471
+ chainId: { type: "number", required: true, description: "Aero chain: 8453 (Base, default), 1, 10, 42161, 4663, 5042, or 57073." },
4283
4472
  tokenIn: { type: "address", required: true, description: "Ticker (AAPLc, USDC, ETH, WETH, AERO) or 0x / 0x0 native" },
4284
4473
  tokenOut: { type: "address", required: true, description: "Ticker (AAPLc, USDC, ETH, WETH, AERO) or 0x / 0x0 native" },
4285
4474
  amountHuman: { type: "string", required: true, description: "Human-readable input amount (B20 stocks are 8 decimals)" }
@@ -4372,6 +4561,10 @@ exports.AERODROME_CL_FACTORY_NEWEST_BIT = AERODROME_CL_FACTORY_NEWEST_BIT;
4372
4561
  exports.AERODROME_CL_FACTORY_OLDEST_BIT = AERODROME_CL_FACTORY_OLDEST_BIT;
4373
4562
  exports.AERODROME_STABLE_FILLER = AERODROME_STABLE_FILLER;
4374
4563
  exports.AERODROME_VOLATILE_FILLER = AERODROME_VOLATILE_FILLER;
4564
+ exports.aeroAddressesForChain = aeroAddressesForChain;
4565
+ exports.aeroRowIconAddresses = aeroRowIconAddresses;
4566
+ exports.aeroUsdcAddress = aeroUsdcAddress;
4567
+ exports.aeroWrappedNativeAddress = aeroWrappedNativeAddress;
4375
4568
  exports.aerodromeClFactoryList = aerodromeClFactoryList;
4376
4569
  exports.aerodromeClSwapRouterForFactory = aerodromeClSwapRouterForFactory;
4377
4570
  exports.aerodromeCoinbaseStockAddresses = aerodromeCoinbaseStockAddresses;
@@ -4406,6 +4599,7 @@ exports.aerodromeQuoteAddLiquidity = aerodromeQuoteAddLiquidity;
4406
4599
  exports.aerodromeQuoteClDeposit = aerodromeQuoteClDeposit;
4407
4600
  exports.aerodromeResolveStockTokens = aerodromeResolveStockTokens;
4408
4601
  exports.aerodromeUnissuedStockMessage = aerodromeUnissuedStockMessage;
4602
+ exports.aerodromeUnsupportedChainMessage = aerodromeUnsupportedChainMessage;
4409
4603
  exports.assertAerodromeStockIssued = assertAerodromeStockIssued;
4410
4604
  exports.buildAerodromeLiquidityPurposePrefill = buildAerodromeLiquidityPurposePrefill;
4411
4605
  exports.buildAerodromeRewardsPurposePrefill = buildAerodromeRewardsPurposePrefill;