@continuumdao/ctm-mpc-defi 0.2.0 → 0.2.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (100) hide show
  1. package/README.md +20 -78
  2. package/dist/agent/catalog.cjs +563 -5
  3. package/dist/agent/catalog.cjs.map +1 -1
  4. package/dist/agent/catalog.d.ts +166 -20
  5. package/dist/agent/catalog.js +551 -7
  6. package/dist/agent/catalog.js.map +1 -1
  7. package/dist/agent/skills/aave-v4/SKILL.md +43 -0
  8. package/dist/agent/skills/curve-dao/SKILL.md +13 -0
  9. package/dist/agent/skills/ethena/SKILL.md +10 -0
  10. package/dist/agent/skills/euler-v2/SKILL.md +10 -0
  11. package/dist/agent/skills/lido/SKILL.md +22 -0
  12. package/dist/agent/skills/maple-syrup/SKILL.md +10 -0
  13. package/dist/agent/skills/sky/SKILL.md +10 -0
  14. package/dist/agent/skills/uniswap-v4/SKILL.md +22 -0
  15. package/dist/chains/evm/index.cjs +79 -224
  16. package/dist/chains/evm/index.cjs.map +1 -1
  17. package/dist/chains/evm/index.d.ts +26 -26
  18. package/dist/chains/evm/index.js +69 -209
  19. package/dist/chains/evm/index.js.map +1 -1
  20. package/dist/chains/near/index.d.ts +1 -1
  21. package/dist/chains/solana/index.d.ts +1 -1
  22. package/dist/core/index.cjs +68 -106
  23. package/dist/core/index.cjs.map +1 -1
  24. package/dist/core/index.d.ts +21 -36
  25. package/dist/core/index.js +57 -96
  26. package/dist/core/index.js.map +1 -1
  27. package/dist/{envelope-CcE5Cz_q.d.ts → envelope-CpBUh9eP.d.ts} +1 -1
  28. package/dist/index.cjs +356 -1855
  29. package/dist/index.cjs.map +1 -1
  30. package/dist/index.d.ts +7 -11
  31. package/dist/index.js +332 -1826
  32. package/dist/index.js.map +1 -1
  33. package/dist/protocols/evm/aave-v4/index.cjs +1152 -669
  34. package/dist/protocols/evm/aave-v4/index.cjs.map +1 -1
  35. package/dist/protocols/evm/aave-v4/index.d.ts +418 -3
  36. package/dist/protocols/evm/aave-v4/index.js +1126 -670
  37. package/dist/protocols/evm/aave-v4/index.js.map +1 -1
  38. package/dist/protocols/evm/curve-dao/index.cjs +257 -131
  39. package/dist/protocols/evm/curve-dao/index.cjs.map +1 -1
  40. package/dist/protocols/evm/curve-dao/index.d.ts +69 -5
  41. package/dist/protocols/evm/curve-dao/index.js +242 -124
  42. package/dist/protocols/evm/curve-dao/index.js.map +1 -1
  43. package/dist/protocols/evm/ethena/index.cjs +394 -402
  44. package/dist/protocols/evm/ethena/index.cjs.map +1 -1
  45. package/dist/protocols/evm/ethena/index.d.ts +47 -3
  46. package/dist/protocols/evm/ethena/index.js +390 -404
  47. package/dist/protocols/evm/ethena/index.js.map +1 -1
  48. package/dist/protocols/evm/euler-v2/index.cjs +2810 -1191
  49. package/dist/protocols/evm/euler-v2/index.cjs.map +1 -1
  50. package/dist/protocols/evm/euler-v2/index.d.ts +465 -3
  51. package/dist/protocols/evm/euler-v2/index.js +2761 -1192
  52. package/dist/protocols/evm/euler-v2/index.js.map +1 -1
  53. package/dist/protocols/evm/lido/index.cjs +351 -236
  54. package/dist/protocols/evm/lido/index.cjs.map +1 -1
  55. package/dist/protocols/evm/lido/index.d.ts +34 -4
  56. package/dist/protocols/evm/lido/index.js +348 -238
  57. package/dist/protocols/evm/lido/index.js.map +1 -1
  58. package/dist/protocols/evm/maple/index.cjs +390 -395
  59. package/dist/protocols/evm/maple/index.cjs.map +1 -1
  60. package/dist/protocols/evm/maple/index.d.ts +23 -3
  61. package/dist/protocols/evm/maple/index.js +390 -397
  62. package/dist/protocols/evm/maple/index.js.map +1 -1
  63. package/dist/protocols/evm/sky/index.cjs +454 -232
  64. package/dist/protocols/evm/sky/index.cjs.map +1 -1
  65. package/dist/protocols/evm/sky/index.d.ts +57 -3
  66. package/dist/protocols/evm/sky/index.js +444 -231
  67. package/dist/protocols/evm/sky/index.js.map +1 -1
  68. package/dist/protocols/evm/uniswap-v4/index.cjs +423 -658
  69. package/dist/protocols/evm/uniswap-v4/index.cjs.map +1 -1
  70. package/dist/protocols/evm/uniswap-v4/index.d.ts +3 -4
  71. package/dist/protocols/evm/uniswap-v4/index.js +422 -657
  72. package/dist/protocols/evm/uniswap-v4/index.js.map +1 -1
  73. package/dist/{registry-oMKlO_5z.d.ts → registry-Bv5o37_w.d.ts} +1 -1
  74. package/dist/{types-Ce2qNHai.d.cts → types-BfjWdw1j.d.ts} +3 -1
  75. package/dist/{types-5u863Fd9.d.ts → types-DUeNJLr9.d.ts} +1 -1
  76. package/package.json +7 -6
  77. package/dist/agent/catalog.d.cts +0 -939
  78. package/dist/chains/evm/index.d.cts +0 -64
  79. package/dist/chains/near/index.d.cts +0 -37
  80. package/dist/chains/solana/index.d.cts +0 -40
  81. package/dist/core/index.d.cts +0 -43
  82. package/dist/envelope-DYDPnrHZ.d.cts +0 -35
  83. package/dist/index.d.cts +0 -16
  84. package/dist/keygen-CfNp8yKJ.d.cts +0 -9
  85. package/dist/keygen-DsINazx8.d.ts +0 -9
  86. package/dist/nodeRead-BnmSaMGO.d.cts +0 -8
  87. package/dist/nodeRead-BnmSaMGO.d.ts +0 -8
  88. package/dist/protocols/evm/aave-v4/index.d.cts +0 -500
  89. package/dist/protocols/evm/curve-dao/index.d.cts +0 -147
  90. package/dist/protocols/evm/ethena/index.d.cts +0 -161
  91. package/dist/protocols/evm/euler-v2/index.d.cts +0 -317
  92. package/dist/protocols/evm/lido/index.d.cts +0 -120
  93. package/dist/protocols/evm/maple/index.d.cts +0 -109
  94. package/dist/protocols/evm/sky/index.d.cts +0 -218
  95. package/dist/protocols/evm/uniswap-v4/index.d.cts +0 -324
  96. package/dist/registry-BwZoE668.d.cts +0 -8
  97. package/dist/txParams-BC7ogvdR.d.cts +0 -19
  98. package/dist/txParams-BC7ogvdR.d.ts +0 -19
  99. package/dist/types-B8idm_gu.d.cts +0 -34
  100. package/dist/types-Ce2qNHai.d.ts +0 -57
@@ -1,6 +1,9 @@
1
- import { getAddress } from 'viem';
1
+ import { getAddress, isAddress } from 'viem';
2
2
  import { zodToJsonSchema } from 'zod-to-json-schema';
3
3
  import { z } from 'zod';
4
+ import { readFileSync } from 'fs';
5
+ import { join, dirname } from 'path';
6
+ import { fileURLToPath } from 'url';
4
7
 
5
8
  // src/core/registry.ts
6
9
  var modules = [];
@@ -159,6 +162,96 @@ function isCurveApiChainSupported(chainId) {
159
162
  if (Number.isNaN(n) || n < 0) return false;
160
163
  return CURVE_FULL_NETWORK_CONSTANTS_CHAIN_IDS.has(n);
161
164
  }
165
+ var CURVE_NATIVE_PLACEHOLDER = "0xeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee";
166
+ var ETH_PLACEHOLDER = CURVE_NATIVE_PLACEHOLDER;
167
+ function normalizeAddr(a) {
168
+ return a.toLowerCase();
169
+ }
170
+ function addEdge(adj, a, b) {
171
+ if (a === b) return;
172
+ if (!adj.has(a)) adj.set(a, /* @__PURE__ */ new Set());
173
+ if (!adj.has(b)) adj.set(b, /* @__PURE__ */ new Set());
174
+ adj.get(a).add(b);
175
+ adj.get(b).add(a);
176
+ }
177
+ function buildCurveLiquidityGraphFromApi(curve) {
178
+ const adj = /* @__PURE__ */ new Map();
179
+ for (const id of curve.getPoolList()) {
180
+ try {
181
+ const pool = curve.getPool(id);
182
+ const w = (pool.wrappedCoinAddresses ?? []).map(normalizeAddr);
183
+ const u = (pool.underlyingCoinAddresses ?? []).map(normalizeAddr);
184
+ const all = [.../* @__PURE__ */ new Set([...w, ...u])];
185
+ for (let i = 0; i < all.length; i++) {
186
+ for (let j = i + 1; j < all.length; j++) {
187
+ addEdge(adj, all[i], all[j]);
188
+ }
189
+ }
190
+ } catch {
191
+ }
192
+ }
193
+ return adj;
194
+ }
195
+ function addNativeWethBridge(adj, wrappedNative) {
196
+ if (!wrappedNative) return;
197
+ const w = wrappedNative.toLowerCase();
198
+ const a = ETH_PLACEHOLDER;
199
+ const b = w;
200
+ if (a === b) return;
201
+ if (!adj.has(a)) adj.set(a, /* @__PURE__ */ new Set());
202
+ if (!adj.has(b)) adj.set(b, /* @__PURE__ */ new Set());
203
+ adj.get(a).add(b);
204
+ adj.get(b).add(a);
205
+ }
206
+ function swappableCurveGraphNodeKeys(adj) {
207
+ const out = /* @__PURE__ */ new Set();
208
+ for (const [k, neigh] of adj) {
209
+ if (neigh.size > 0) out.add(k);
210
+ }
211
+ return out;
212
+ }
213
+
214
+ // src/protocols/evm/curve-dao/apiSession.ts
215
+ async function fetchAllCurvePools(curve) {
216
+ const run = (p) => p.catch(() => void 0);
217
+ await Promise.all([
218
+ run(curve.factory.fetchPools()),
219
+ run(curve.crvUSDFactory.fetchPools()),
220
+ run(curve.EYWAFactory.fetchPools()),
221
+ run(curve.cryptoFactory.fetchPools()),
222
+ run(curve.twocryptoFactory.fetchPools()),
223
+ run(curve.tricryptoFactory.fetchPools()),
224
+ run(curve.stableNgFactory.fetchPools())
225
+ ]);
226
+ }
227
+ async function loadFullCurveSessionForRpc(rpcUrl) {
228
+ const url = (rpcUrl ?? "").trim();
229
+ if (!url) return null;
230
+ try {
231
+ const { default: curve } = await import('@curvefi/api');
232
+ await curve.init("JsonRpc", { url }, {});
233
+ const wrapped = curve.getNetworkConstants().NATIVE_COIN?.wrappedAddress;
234
+ if (!curve.hasRouter || !curve.hasRouter()) {
235
+ return {
236
+ curve,
237
+ adj: /* @__PURE__ */ new Map(),
238
+ swappableNodeKeys: /* @__PURE__ */ new Set(),
239
+ wrappedNative: wrapped
240
+ };
241
+ }
242
+ await fetchAllCurvePools(curve);
243
+ const adj = buildCurveLiquidityGraphFromApi(curve);
244
+ addNativeWethBridge(adj, wrapped);
245
+ return {
246
+ curve,
247
+ adj,
248
+ swappableNodeKeys: swappableCurveGraphNodeKeys(adj),
249
+ wrappedNative: wrapped
250
+ };
251
+ } catch {
252
+ return null;
253
+ }
254
+ }
162
255
 
163
256
  // src/protocols/evm/curve-dao/index.ts
164
257
  var CURVE_DAO_PROTOCOL_ID = "curve-dao";
@@ -174,6 +267,19 @@ var curveDaoProtocolModule = {
174
267
  return token.kind === "native" || token.kind === "erc20";
175
268
  },
176
269
  actions: [
270
+ {
271
+ id: "curve-dao.quote",
272
+ protocolId: CURVE_DAO_PROTOCOL_ID,
273
+ chainCategory: "evm",
274
+ description: "Quote swap via Curve Router NG (getBestRouteAndOutput)",
275
+ commonParams: [],
276
+ params: {
277
+ chainId: { type: "number", required: true, description: "EVM chain id" },
278
+ tokenIn: { type: "address", required: true, description: "Token in or native placeholder" },
279
+ tokenOut: { type: "address", required: true, description: "Token out or native placeholder" },
280
+ amountHuman: { type: "string", required: true, description: "Human-readable input amount" }
281
+ }
282
+ },
177
283
  {
178
284
  id: "curve-dao.swap",
179
285
  protocolId: CURVE_DAO_PROTOCOL_ID,
@@ -248,7 +354,14 @@ var MULTISIGN_OUTPUT_DOC = {
248
354
  }
249
355
  };
250
356
  var MANAGEMENT_SIG_DOC = {
251
- description: "Management POST bodies embed NodeMgtKeySig: { nonce, clientSig, nodeKey }. Sign JSON with clientSig cleared; POST with clientSig set to the Ed25519 128-hex or EIP-191 signature. Legacy Nonce/Sig/sig field names are not accepted.",
357
+ description: "Management POST bodies embed NodeMgtKeySig: { nonce, clientSig, nodeKey }. Sign JSON with clientSig cleared via messageToSignManagementBody; POST with withManagementClientSig(body, sig). Do not put signedMessage in the JSON body for standard management routes. Legacy Nonce/Sig/sig field names are not accepted.",
358
+ exceptions: {
359
+ configUpdateImplement: "POST /configUpdateImplement: include nodeKey + plannedYaml + signedMessage (opaque configUpdateImplement|<sha256> line). Sign the opaque line bytes, not the JSON body.",
360
+ postMSQTTKey: "POST /postMSQTTKey: include nodeKey + caCertPem + clientSig. Sign caCertPem PEM bytes directly (use buildPostMqttKeyBody).",
361
+ addManagementKey: "POST /addManagementKey / removeManagementKey (EIP-191): may still use signedMessage equal to the canonical JSON string for dual-mode Ethereum signing.",
362
+ agentLlmConfig: "POST /agentLlmConfig / agentLlmApiKey: sign canonical JSON with action + clientSig cleared; POST body has nonce, clientSig, nodeKey, endpoint fields \u2014 no signedMessage field.",
363
+ multiSignRequest: "POST /multiSignRequest (client key, not management): POST { ...bodyForSign, clientSig, signedMessage: messageToSign }."
364
+ },
252
365
  fields: {
253
366
  nonce: {
254
367
  type: "number",
@@ -266,10 +379,15 @@ var MANAGEMENT_SIG_DOC = {
266
379
  helpers: {
267
380
  managementSigFields: "Base envelope with clientSig cleared.",
268
381
  buildManagementPostBody: "Spread managementSigFields then endpoint fields.",
382
+ buildPostMqttKeyBody: "POST /postMSQTTKey unsigned body (sign PEM directly).",
383
+ buildPostPreferredKeyGenBody: "POST /postPreferredKeyGen unsigned body.",
384
+ buildConfigUpdateImplementPostBody: "POST /configUpdateImplement with opaque signedMessage line.",
385
+ buildSignRequestAgreeUnsignedBody: "POST /signRequestAgree unsigned body with nodeKey.",
269
386
  messageToSignManagementBody: "Canonical JSON string to sign.",
270
387
  withManagementClientSig: "Attach signature to POST body.",
271
388
  fetchNodeKey: "GET /getNodeKey via nodeFetchWithReadAuth.",
272
- fetchManagementNonce: "GET nonce for Ed25519 or Ethereum management key."
389
+ fetchManagementNonce: "GET nonce for Ed25519 or Ethereum management key.",
390
+ fetchPreferredKeyGen: "GET /getPreferredKeyGen for agent default KeyGen."
273
391
  }
274
392
  };
275
393
  function zodSchemaToMcpJsonSchema(schema) {
@@ -382,6 +500,17 @@ var mcpUniswapV4BuildSwapMultisignInputSchema = evmMultisignCommonInputSchema.ex
382
500
  swapDeadlineUnix: z.number().describe("Same deadline passed to create_swap"),
383
501
  slippagePercent: z.number().optional().describe("Extra approve headroom for EXACT_OUTPUT")
384
502
  });
503
+ var mcpCurveDaoQuoteInputSchema = z.object({
504
+ chainId: z.number().int().positive().describe("EVM chain id (rpcUrl resolved from get_chain_registry rpcGateway)"),
505
+ rpcUrl: z.string().min(1).optional().describe("JSON-RPC URL; continuum-mcp-server injects from chain registry \u2014 do not pass a public RPC URL"),
506
+ tokenIn: z.string().min(1).describe("Input token address, or 0xeeee\u2026 / 0x0 / eth for native"),
507
+ tokenOut: z.string().min(1).describe("Output token address or 0xeeee\u2026 native placeholder"),
508
+ amountHuman: z.string().min(1).describe("Human-readable amount of tokenIn"),
509
+ tokenInDecimals: z.number().int().min(0).max(18).optional().describe("Token-in decimals; omit to read on-chain (native uses 18)")
510
+ });
511
+ var mcpCurveDaoQuoteOutputSchema = jsonObjectSchema.describe(
512
+ "Curve router quote: { inputAmount, output, route, priceImpactPercent?, tokenInRouterId, tokenOutRouterId }"
513
+ );
385
514
  var mcpCurveDaoBuildSwapMultisignInputSchema = evmMultisignCommonInputSchema.extend({
386
515
  tokenIn: evmAddressSchema.describe("ERC-20 sold (native in uses WETH path in UI)"),
387
516
  tokenOut: z.string().min(1).describe("Output token or 0xeeee\u2026 native placeholder"),
@@ -797,7 +926,7 @@ var MCP_PROTOCOL_TOOL_DEFINITIONS = [
797
926
  description: "Build Euler v2 vault withdraw/redeem batch.",
798
927
  prerequisites: ["keyGen", "executorAddress", "vault address"],
799
928
  followUp: ["Sign messageToSign", "POST /multiSignRequest"],
800
- handler: { importPath: "protocols/evm/euler-v2", exportName: "buildEvmMultisignBodyEulerV2VaultWithdrawBatch" },
929
+ handler: { importPath: "protocols/evm/euler-v2", exportName: "buildEvmMultisignBodyEulerV2VaultWithdraw" },
801
930
  inputZod: mcpEulerV2VaultWithdrawInputSchema
802
931
  }),
803
932
  defineProtocolMcpTool({
@@ -887,13 +1016,32 @@ var CORE_MCP_TOOL_DEFINITIONS = [
887
1016
  inputZod: mcpUniswapV4BuildSwapMultisignInputSchema,
888
1017
  outputZod: multisignOutputSchema
889
1018
  }),
1019
+ defineMcpTool({
1020
+ name: "ctm_curve_dao_quote",
1021
+ actionId: "curve-dao.quote",
1022
+ protocolId: "curve-dao",
1023
+ chainCategory: "evm",
1024
+ description: "Fetch a Curve Router NG quote via @curvefi/api getBestRouteAndOutput. Returns output amount, route, and optional priceImpactPercent. Does NOT create a sign request \u2014 call ctm_curve_dao_build_swap_multisign after quoting. Pass chainId only; rpcUrl is resolved from get_chain_registry rpcGateway.",
1025
+ prerequisites: [
1026
+ "Chain must be supported by Curve (@curvefi/api network constants).",
1027
+ "Configure rpcGateway for chainId in get_chain_registry."
1028
+ ],
1029
+ followUp: ["ctm_curve_dao_build_swap_multisign"],
1030
+ handler: { importPath: "protocols/evm/curve-dao", exportName: "curveDaoQuote" },
1031
+ inputZod: mcpCurveDaoQuoteInputSchema,
1032
+ outputZod: mcpCurveDaoQuoteOutputSchema
1033
+ }),
890
1034
  defineMcpTool({
891
1035
  name: "ctm_curve_dao_build_swap_multisign",
892
1036
  actionId: "curve-dao.swap",
893
1037
  protocolId: "curve-dao",
894
1038
  chainCategory: "evm",
895
1039
  description: "Build mpc-auth multiSignRequest for a Curve Router NG swap via @curvefi/api populateSwap. Optionally batches ERC-20 approve txs when allowance is insufficient, then exchange. Requires JSON-RPC and Curve-supported chain.",
896
- prerequisites: ["keyGen", "executorAddress", "tokenIn/tokenOut/amountHuman/slippage", "RPC URL"],
1040
+ prerequisites: [
1041
+ "ctm_curve_dao_quote (recommended) or known-good route",
1042
+ "keyGenId + chainId + purposeText",
1043
+ "tokenIn/tokenOut/amountHuman/slippagePercent"
1044
+ ],
897
1045
  followUp: ["Sign messageToSign", "POST /multiSignRequest with clientSig and signedMessage"],
898
1046
  handler: { importPath: "protocols/evm/curve-dao", exportName: "buildEvmMultisignBodyCurveDaoBatch" },
899
1047
  inputZod: mcpCurveDaoBuildSwapMultisignInputSchema,
@@ -958,7 +1106,13 @@ function getAgentCatalogForMcp() {
958
1106
  "2. GET /getPublicMgtKeyNonce or /getNodeMgtKeyNonce \u2192 nonce",
959
1107
  "3. buildManagementPostBody(nonce, nodeKey, { \u2026endpoint fields })",
960
1108
  "4. messageToSignManagementBody(body) \u2192 sign \u2192 withManagementClientSig(body, sig)",
961
- "5. POST management route with signed body"
1109
+ "5. POST management route with signed body (no signedMessage field except configUpdateImplement opaque line)"
1110
+ ],
1111
+ agentMultisignTypical: [
1112
+ "1. load_defi_protocol for the target protocol",
1113
+ "2. get_defi_protocol_supported_chains / get_token_registry to pick chainId and tokens",
1114
+ "3. MCP build_* tool with keyGenId + chainId \u2192 { requestId }",
1115
+ "4. Base MCP: wait_for_sign_request_ready \u2192 sign_request_agree \u2192 trigger_sign_result \u2192 broadcast_sign_result"
962
1116
  ]
963
1117
  }
964
1118
  };
@@ -994,6 +1148,7 @@ var lidoProtocolModule = {
994
1148
  };
995
1149
  registerProtocolModule(lidoProtocolModule);
996
1150
  var USDE_ETHEREUM_MAINNET = "0x4c9edd5852cd905f086c759e8383e09bff1e68b3";
1151
+ var SUSDE_ETHEREUM_MAINNET = "0x9d39a5de30e57443bff2a8307a4256c8797a3497";
997
1152
  var USDE_MOST_L2S = "0x5d3a1Ff2b6BAb83b63cd9AD0787074081a52ef34";
998
1153
  var USDE_ZKSYNC_ERA = "0x39Fe7a0DACcE31Bd90418e3e659fb0b5f0B3Db0d";
999
1154
  var L2_SAME_ADDRESS_CHAIN_IDS = /* @__PURE__ */ new Set([
@@ -1034,12 +1189,53 @@ var L2_SAME_ADDRESS_CHAIN_IDS = /* @__PURE__ */ new Set([
1034
1189
  48900
1035
1190
  // Zircuit
1036
1191
  ]);
1192
+ var FALLBACK_NAME_BY_ID = {
1193
+ 1: "Ethereum",
1194
+ 42161: "Arbitrum One",
1195
+ 10: "Optimism",
1196
+ 8453: "Base",
1197
+ 56: "BNB Chain",
1198
+ 59144: "Linea",
1199
+ 5e3: "Mantle",
1200
+ 81457: "Blast",
1201
+ 169: "Manta Pacific",
1202
+ 534352: "Scroll",
1203
+ 252: "Fraxtal",
1204
+ 34443: "Mode",
1205
+ 196: "X Layer",
1206
+ 1088: "Metis",
1207
+ 80084: "Berachain",
1208
+ 2222: "Kava",
1209
+ 2818: "Morph",
1210
+ 1923: "Swell",
1211
+ 48900: "Zircuit",
1212
+ 324: "ZKSync Era"
1213
+ };
1037
1214
  function usdeTokenAddressOnEvmChain(chainId) {
1038
1215
  if (chainId === 1) return USDE_ETHEREUM_MAINNET;
1039
1216
  if (chainId === 324) return USDE_ZKSYNC_ERA;
1040
1217
  if (L2_SAME_ADDRESS_CHAIN_IDS.has(chainId)) return USDE_MOST_L2S;
1041
1218
  return null;
1042
1219
  }
1220
+ function listEthenaUsdeEvmNetworkRows() {
1221
+ const rows = [
1222
+ { chainId: 1, label: FALLBACK_NAME_BY_ID[1], usde: USDE_ETHEREUM_MAINNET }
1223
+ ];
1224
+ const l2 = [...L2_SAME_ADDRESS_CHAIN_IDS].sort((a, b) => a - b);
1225
+ for (const id of l2) {
1226
+ rows.push({
1227
+ chainId: id,
1228
+ label: FALLBACK_NAME_BY_ID[id] ?? `Chain ${id}`,
1229
+ usde: USDE_MOST_L2S
1230
+ });
1231
+ }
1232
+ rows.push({ chainId: 324, label: FALLBACK_NAME_BY_ID[324], usde: USDE_ZKSYNC_ERA });
1233
+ return rows.sort((a, b) => {
1234
+ if (a.chainId === 1) return -1;
1235
+ if (b.chainId === 1) return 1;
1236
+ return a.chainId - b.chainId;
1237
+ });
1238
+ }
1043
1239
  function isEvmChainInEthenaUsdeList(chainId) {
1044
1240
  return usdeTokenAddressOnEvmChain(chainId) != null;
1045
1241
  }
@@ -1070,6 +1266,18 @@ registerProtocolModule(ethenaProtocolModule);
1070
1266
  function isMapleSyrupSupportedChain(chainId) {
1071
1267
  return chainId === 1 || chainId === 11155111;
1072
1268
  }
1269
+ async function postJsonViaOptionalProxy(args) {
1270
+ const r = await fetch(args.directUrl, {
1271
+ method: "POST",
1272
+ headers: { "content-type": "application/json" },
1273
+ body: JSON.stringify(args.body)
1274
+ });
1275
+ if (!r.ok) {
1276
+ const t = await r.text().catch(() => "");
1277
+ throw new Error(t ? `HTTP ${r.status}: ${t.slice(0, 200)}` : `HTTP ${r.status}`);
1278
+ }
1279
+ return await r.json();
1280
+ }
1073
1281
 
1074
1282
  // src/protocols/evm/maple/index.ts
1075
1283
  var MAPLE_PROTOCOL_ID = "maple-syrup";
@@ -1116,6 +1324,77 @@ var skyProtocolModule = {
1116
1324
  ]
1117
1325
  };
1118
1326
  registerProtocolModule(skyProtocolModule);
1327
+ var AAVE_V4_GRAPHQL_URL = "https://api.v4.aave.com/graphql";
1328
+ async function aaveV4Gql(query, variables) {
1329
+ const body = { query, variables: variables ?? {} };
1330
+ const j = await postJsonViaOptionalProxy({
1331
+ directUrl: AAVE_V4_GRAPHQL_URL,
1332
+ body});
1333
+ if (j.errors?.length) {
1334
+ const msg = j.errors.map((e) => e.message ?? "Unknown").join("; ");
1335
+ throw new Error(msg);
1336
+ }
1337
+ if (j.data == null) {
1338
+ throw new Error("Aave V4 API: empty response");
1339
+ }
1340
+ return j.data;
1341
+ }
1342
+ async function fetchAaveV4Chains() {
1343
+ const d = await aaveV4Gql(`
1344
+ query C($c: ChainsRequest!) { chains(request: $c) { chainId name nativeWrappedToken } }
1345
+ `, { c: { query: { filter: "ALL" } } });
1346
+ return d.chains ?? [];
1347
+ }
1348
+ async function loadAaveV4SupportedChainIdsFromV4Api() {
1349
+ const rows = await fetchAaveV4Chains();
1350
+ const s = /* @__PURE__ */ new Set();
1351
+ for (const c of rows) s.add(c.chainId);
1352
+ return s;
1353
+ }
1354
+ var RESERVES_ADDRESS_FRAGMENT = `
1355
+ asset { underlying { address } }
1356
+ `;
1357
+ async function fetchAaveV4NativeWrappedToken(chainId) {
1358
+ const all = await fetchAaveV4Chains();
1359
+ const c = all.find((x) => x.chainId === chainId);
1360
+ const t = (c?.nativeWrappedToken ?? "").trim();
1361
+ if (t && isAddress(t)) return getAddress(t);
1362
+ return null;
1363
+ }
1364
+ async function fetchAaveV4SupportedUnderlyingAddressSet(chainId) {
1365
+ const d = await aaveV4Gql(
1366
+ `
1367
+ query A($r: ReservesRequest!) { reserves(request: $r) { ${RESERVES_ADDRESS_FRAGMENT} } }
1368
+ `,
1369
+ {
1370
+ r: {
1371
+ query: { chainIds: [chainId] },
1372
+ filter: "ALL",
1373
+ orderBy: { supplyApy: "DESC" }
1374
+ }
1375
+ }
1376
+ );
1377
+ const s = /* @__PURE__ */ new Set();
1378
+ for (const r of d.reserves ?? []) {
1379
+ const a = (r.asset?.underlying?.address ?? "").trim();
1380
+ if (a && isAddress(a)) s.add(a.toLowerCase());
1381
+ }
1382
+ return s;
1383
+ }
1384
+ var aaveV4ChainTokenCache = /* @__PURE__ */ new Map();
1385
+ function ensureAaveV4ChainTokenCache(chainId) {
1386
+ const hit = aaveV4ChainTokenCache.get(chainId);
1387
+ if (hit) return hit;
1388
+ const p = (async () => {
1389
+ const [nativeWrapped, supportedUnderlying] = await Promise.all([
1390
+ fetchAaveV4NativeWrappedToken(chainId),
1391
+ fetchAaveV4SupportedUnderlyingAddressSet(chainId)
1392
+ ]);
1393
+ return { supportedUnderlying, nativeWrapped };
1394
+ })();
1395
+ aaveV4ChainTokenCache.set(chainId, p);
1396
+ return p;
1397
+ }
1119
1398
 
1120
1399
  // src/protocols/evm/aave-v4/index.ts
1121
1400
  var AAVE_V4_PROTOCOL_ID = "aave-v4";
@@ -1158,6 +1437,271 @@ var eulerV2ProtocolModule = {
1158
1437
  ]
1159
1438
  };
1160
1439
  registerProtocolModule(eulerV2ProtocolModule);
1440
+ var skillsDir = join(dirname(fileURLToPath(import.meta.url)), "skills");
1441
+ var SKILL_PROTOCOL_IDS = [
1442
+ "aave-v4",
1443
+ "lido",
1444
+ "uniswap-v4",
1445
+ "curve-dao",
1446
+ "ethena",
1447
+ "euler-v2",
1448
+ "maple-syrup",
1449
+ "sky"
1450
+ ];
1451
+ function getToolsForProtocol(protocolId) {
1452
+ return MCP_TOOL_DEFINITIONS.filter((t) => t.protocolId === protocolId);
1453
+ }
1454
+ function getProtocolSkill(protocolId) {
1455
+ if (!SKILL_PROTOCOL_IDS.includes(protocolId)) {
1456
+ return void 0;
1457
+ }
1458
+ try {
1459
+ return readFileSync(join(skillsDir, protocolId, "SKILL.md"), "utf8");
1460
+ } catch {
1461
+ return void 0;
1462
+ }
1463
+ }
1464
+ function listProtocolsWithSkills() {
1465
+ return [...SKILL_PROTOCOL_IDS];
1466
+ }
1467
+ function getProtocolDiscoverySummary(protocolId) {
1468
+ const mod = getProtocolModules().find((p) => p.id === protocolId);
1469
+ if (!mod) return void 0;
1470
+ return {
1471
+ protocolId: mod.id,
1472
+ chainCategory: mod.chainCategory,
1473
+ actions: mod.actions.map((a) => ({ id: a.id, description: a.description })),
1474
+ tools: getToolsForProtocol(protocolId).map((t) => ({
1475
+ name: t.name,
1476
+ actionId: t.actionId,
1477
+ description: t.description,
1478
+ prerequisites: t.prerequisites,
1479
+ followUp: t.followUp
1480
+ }))
1481
+ };
1482
+ }
1483
+ var EULER_V2_SUBGRAPH_CHAIN_IDS = [
1484
+ 1,
1485
+ 8453,
1486
+ 42161,
1487
+ 10,
1488
+ 137,
1489
+ 56,
1490
+ 43114,
1491
+ 100,
1492
+ 59144,
1493
+ 146,
1494
+ 1923,
1495
+ 130
1496
+ ];
1497
+ function advisor(protocolId, tokenFilter, impl) {
1498
+ return { protocolId, tokenFilter, ...impl };
1499
+ }
1500
+ var PROTOCOL_SUPPORT_ADVISORS = {
1501
+ "aave-v4": advisor("aave-v4", "api_underlyings", {
1502
+ async supportedChainIds() {
1503
+ const set = await loadAaveV4SupportedChainIdsFromV4Api();
1504
+ return [...set].sort((a, b) => a - b);
1505
+ },
1506
+ async supportedTokens(chainId) {
1507
+ const cache = await ensureAaveV4ChainTokenCache(chainId);
1508
+ const tokens = [...cache.supportedUnderlying].map((address) => ({
1509
+ address,
1510
+ roles: ["underlying"]
1511
+ }));
1512
+ if (cache.nativeWrapped) {
1513
+ tokens.unshift({
1514
+ address: cache.nativeWrapped,
1515
+ symbol: "WETH",
1516
+ roles: ["native_wrapped"]
1517
+ });
1518
+ }
1519
+ return {
1520
+ tokens,
1521
+ nativeWrapped: cache.nativeWrapped ?? void 0,
1522
+ notes: "Native ETH deposits use wrapped native token address from Aave v4 API."
1523
+ };
1524
+ },
1525
+ async isTokenSupported(chainId, address) {
1526
+ const cache = await ensureAaveV4ChainTokenCache(chainId);
1527
+ let normalized;
1528
+ try {
1529
+ normalized = getAddress(address).toLowerCase();
1530
+ } catch {
1531
+ return false;
1532
+ }
1533
+ if (cache.nativeWrapped && getAddress(cache.nativeWrapped).toLowerCase() === normalized) {
1534
+ return true;
1535
+ }
1536
+ return cache.supportedUnderlying.has(normalized);
1537
+ }
1538
+ }),
1539
+ "uniswap-v4": advisor("uniswap-v4", "any_erc20_on_chain", {
1540
+ async supportedChainIds() {
1541
+ const ids = [];
1542
+ for (const id of [
1543
+ 1,
1544
+ 5,
1545
+ 11155111,
1546
+ 137,
1547
+ 80001,
1548
+ 10,
1549
+ 420,
1550
+ 42161,
1551
+ 421613,
1552
+ 42220,
1553
+ 44787,
1554
+ 56,
1555
+ 43114,
1556
+ 84531,
1557
+ 8453,
1558
+ 81457,
1559
+ 7777777,
1560
+ 324,
1561
+ 480,
1562
+ 1301,
1563
+ 130,
1564
+ 10143,
1565
+ 84532,
1566
+ 1868,
1567
+ 143,
1568
+ 59144,
1569
+ 4217,
1570
+ 196
1571
+ ]) {
1572
+ if (isUniswapV4ChainSupported(id)) ids.push(id);
1573
+ }
1574
+ return ids;
1575
+ },
1576
+ async supportedTokens() {
1577
+ return {
1578
+ tokens: [],
1579
+ notes: "Any ERC-20 or native token on a supported chain may be used. Resolve addresses via get_token_registry; tokenOut may be any address."
1580
+ };
1581
+ }
1582
+ }),
1583
+ "curve-dao": advisor("curve-dao", "pool_graph", {
1584
+ async supportedChainIds() {
1585
+ return [1, 10, 56, 100, 137, 146, 196, 250, 252, 324, 999, 1284, 2222, 5e3, 8453, 42161, 42220, 43114, 1313161554];
1586
+ },
1587
+ async supportedTokens(chainId, ctx) {
1588
+ if (!isCurveApiChainSupported(chainId)) {
1589
+ return { tokens: [], notes: "Chain not supported by Curve SDK network constants." };
1590
+ }
1591
+ const rpcUrl = ctx?.rpcUrl?.trim();
1592
+ if (!rpcUrl) {
1593
+ return {
1594
+ tokens: [],
1595
+ notes: "Provide rpcUrl (from get_chain_registry) to load Curve pool graph token list."
1596
+ };
1597
+ }
1598
+ const session = await loadFullCurveSessionForRpc(rpcUrl);
1599
+ if (!session?.swappableNodeKeys?.size) {
1600
+ return { tokens: [], notes: "Curve session returned no swappable tokens for this RPC." };
1601
+ }
1602
+ return {
1603
+ tokens: [...session.swappableNodeKeys].map((key) => {
1604
+ const address = key.startsWith("0x") ? key : key.split(":")[0] ?? key;
1605
+ return { address, roles: ["swappable"] };
1606
+ })
1607
+ };
1608
+ }
1609
+ }),
1610
+ lido: advisor("lido", "mainnet_only", {
1611
+ async supportedChainIds() {
1612
+ return [LIDO_ETHEREUM_MAINNET_CHAIN_ID];
1613
+ },
1614
+ async supportedTokens() {
1615
+ return {
1616
+ tokens: [
1617
+ { address: "0x0000000000000000000000000000000000000000", symbol: "ETH", roles: ["native", "stake"] },
1618
+ { address: "0xae7ab96520DE3A18E5e111B5EaAb095312D7fE84", symbol: "stETH", roles: ["erc20"] },
1619
+ { address: "0x7f39C581F595B853cBbF37C12FfeeA971C5a5bEa", symbol: "wstETH", roles: ["erc20"] }
1620
+ ],
1621
+ notes: "Lido staking and withdrawals are Ethereum mainnet only."
1622
+ };
1623
+ }
1624
+ }),
1625
+ ethena: advisor("ethena", "minting_contract", {
1626
+ async supportedChainIds() {
1627
+ return listEthenaUsdeEvmNetworkRows().map((r) => r.chainId);
1628
+ },
1629
+ async supportedTokens(chainId) {
1630
+ if (chainId === 1) {
1631
+ return {
1632
+ tokens: [
1633
+ { address: USDE_ETHEREUM_MAINNET, symbol: "USDe", roles: ["stake"] },
1634
+ { address: SUSDE_ETHEREUM_MAINNET, symbol: "sUSDe", roles: ["vault"] }
1635
+ ],
1636
+ notes: "Ethena stake/redeem UI actions are mainnet-only; USDe exists on other chains for transfers."
1637
+ };
1638
+ }
1639
+ if (isEvmChainInEthenaUsdeList(chainId)) {
1640
+ const row = listEthenaUsdeEvmNetworkRows().find((r) => r.chainId === chainId);
1641
+ return {
1642
+ tokens: row ? [{ address: row.usde, symbol: "USDe", roles: ["erc20"] }] : [],
1643
+ notes: "USDe on L2; staking MCP tools target mainnet only."
1644
+ };
1645
+ }
1646
+ return { tokens: [] };
1647
+ }
1648
+ }),
1649
+ "euler-v2": advisor("euler-v2", "subgraph_vaults", {
1650
+ async supportedChainIds() {
1651
+ return [...EULER_V2_SUBGRAPH_CHAIN_IDS];
1652
+ },
1653
+ async supportedTokens() {
1654
+ return {
1655
+ tokens: [],
1656
+ notes: "Euler vault/collateral assets vary by chain. Pass vault and asset addresses from Euler app or subgraph."
1657
+ };
1658
+ }
1659
+ }),
1660
+ [MAPLE_PROTOCOL_ID]: advisor(MAPLE_PROTOCOL_ID, "fixed_addresses", {
1661
+ async supportedChainIds() {
1662
+ return [1, 11155111];
1663
+ },
1664
+ async supportedTokens() {
1665
+ return {
1666
+ tokens: [],
1667
+ notes: "Maple Syrup pools are discovered via GraphQL; pass syrupRouter, pool, and asset from Maple UI."
1668
+ };
1669
+ }
1670
+ }),
1671
+ [SKY_PROTOCOL_ID]: advisor(SKY_PROTOCOL_ID, "fixed_addresses", {
1672
+ async supportedChainIds() {
1673
+ return [1];
1674
+ },
1675
+ async supportedTokens() {
1676
+ return {
1677
+ tokens: [],
1678
+ notes: "Sky Lockstake and sUSDS use fixed mainnet contract addresses in protocol builders."
1679
+ };
1680
+ }
1681
+ })
1682
+ };
1683
+ function getProtocolSupportAdvisor(protocolId) {
1684
+ return PROTOCOL_SUPPORT_ADVISORS[protocolId];
1685
+ }
1686
+ function listProtocolSupportAdvisorIds() {
1687
+ return Object.keys(PROTOCOL_SUPPORT_ADVISORS);
1688
+ }
1689
+ var mcpServerCommonInputSchema = z.object({
1690
+ keyGenId: z.string().min(1).describe("KeyGen id from fetch_key_gen_result / node preferred KeyGen"),
1691
+ chainId: z.number().int().positive().describe("EVM chain id; RPC and gas config resolved from chain registry"),
1692
+ purposeText: z.string().min(1).describe("Human-readable purpose for the sign request"),
1693
+ useCustomGas: z.boolean().optional().describe("Apply chain gas settings from registry when true")
1694
+ });
1695
+ function mcpServerMultisignInput(fields) {
1696
+ return mcpServerCommonInputSchema.extend(fields);
1697
+ }
1698
+ var mcpServerSubmitOutputSchema = z.object({
1699
+ requestId: z.string().min(1)
1700
+ }).describe("mpc-auth multiSignRequest id; continue with trigger_sign_result / broadcast_sign_result");
1701
+ var MCP_NON_SUBMIT_TOOL_NAMES = /* @__PURE__ */ new Set([
1702
+ "ctm_uniswap_v4_quote",
1703
+ "ctm_uniswap_v4_create_swap"
1704
+ ]);
1161
1705
 
1162
1706
  // src/agent/catalog.ts
1163
1707
  registerProtocolModule(uniswapV4ProtocolModule);
@@ -1189,6 +1733,6 @@ function getAgentCatalog() {
1189
1733
  };
1190
1734
  }
1191
1735
 
1192
- export { EVM_COMMON_PARAM_DOCS, MANAGEMENT_SIG_DOC, MCP_TOOL_DEFINITIONS, MCP_TOOL_INPUT_SCHEMAS, MCP_TOOL_OUTPUT_SCHEMAS, MULTISIGN_OUTPUT_DOC, chainDetailSchema, evmAddressSchema, evmMultisignCommonInputSchema, getActionsByChainCategory, getAgentCatalog, getAgentCatalogForMcp, getMcpToolByName, getMcpToolDefinitions, getMcpToolInputSchema, getMcpToolOutputSchema, getProtocolModules, jsonObjectSchema, keyGenSchema, mcpAaveV4BorrowInputSchema, mcpAaveV4DepositInputSchema, mcpAaveV4RepayInputSchema, mcpAaveV4WithdrawInputSchema, mcpCurveDaoBuildSwapMultisignInputSchema, mcpEthenaClaimInputSchema, mcpEthenaCooldownInputSchema, mcpEthenaRedeemInputSchema, mcpEthenaStakeInputSchema, mcpEulerV2BorrowRepayInputSchema, mcpEulerV2CollateralDepositInputSchema, mcpEulerV2CollateralWithdrawInputSchema, mcpEulerV2IsolatedBorrowInputSchema, mcpEulerV2IsolatedLendInputSchema, mcpEulerV2VaultWithdrawInputSchema, mcpLidoClaimWithdrawalInputSchema, mcpLidoRequestWithdrawalsInputSchema, mcpLidoSubmitInputSchema, mcpLidoUnwrapWstEthInputSchema, mcpLidoWrapStEthInputSchema, mcpMapleDepositInputSchema, mcpMapleRequestRedeemInputSchema, mcpMultisignInput, multisignOutputSchema as mcpMultisignOutputSchema, mcpSkyLockstakeCloseInputSchema, mcpSkyLockstakeDrawInputSchema, mcpSkyLockstakeGetRewardInputSchema, mcpSkyLockstakeStakeInputSchema, mcpSkyLockstakeWipeInputSchema, mcpSkySusdsDepositInputSchema, mcpSkySusdsRedeemInputSchema, mcpUniswapV4BuildSwapMultisignInputSchema, mcpUniswapV4CreateSwapInputSchema, mcpUniswapV4CreateSwapOutputSchema, mcpUniswapV4QuoteInputSchema, mcpUniswapV4QuoteOutputSchema, multisignOutputSchema, parseMcpToolInput, parseMcpToolOutput, uniswapQuoteTradeTypeSchema, zodSchemaToMcpJsonSchema };
1736
+ export { EVM_COMMON_PARAM_DOCS, MANAGEMENT_SIG_DOC, MCP_NON_SUBMIT_TOOL_NAMES, MCP_TOOL_DEFINITIONS, MCP_TOOL_INPUT_SCHEMAS, MCP_TOOL_OUTPUT_SCHEMAS, MULTISIGN_OUTPUT_DOC, PROTOCOL_SUPPORT_ADVISORS, chainDetailSchema, evmAddressSchema, evmMultisignCommonInputSchema, getActionsByChainCategory, getAgentCatalog, getAgentCatalogForMcp, getMcpToolByName, getMcpToolDefinitions, getMcpToolInputSchema, getMcpToolOutputSchema, getProtocolDiscoverySummary, getProtocolModules, getProtocolSkill, getProtocolSupportAdvisor, getToolsForProtocol, jsonObjectSchema, keyGenSchema, listProtocolSupportAdvisorIds, listProtocolsWithSkills, mcpAaveV4BorrowInputSchema, mcpAaveV4DepositInputSchema, mcpAaveV4RepayInputSchema, mcpAaveV4WithdrawInputSchema, mcpCurveDaoBuildSwapMultisignInputSchema, mcpCurveDaoQuoteInputSchema, mcpCurveDaoQuoteOutputSchema, mcpEthenaClaimInputSchema, mcpEthenaCooldownInputSchema, mcpEthenaRedeemInputSchema, mcpEthenaStakeInputSchema, mcpEulerV2BorrowRepayInputSchema, mcpEulerV2CollateralDepositInputSchema, mcpEulerV2CollateralWithdrawInputSchema, mcpEulerV2IsolatedBorrowInputSchema, mcpEulerV2IsolatedLendInputSchema, mcpEulerV2VaultWithdrawInputSchema, mcpLidoClaimWithdrawalInputSchema, mcpLidoRequestWithdrawalsInputSchema, mcpLidoSubmitInputSchema, mcpLidoUnwrapWstEthInputSchema, mcpLidoWrapStEthInputSchema, mcpMapleDepositInputSchema, mcpMapleRequestRedeemInputSchema, mcpMultisignInput, multisignOutputSchema as mcpMultisignOutputSchema, mcpServerCommonInputSchema, mcpServerMultisignInput, mcpServerSubmitOutputSchema, mcpSkyLockstakeCloseInputSchema, mcpSkyLockstakeDrawInputSchema, mcpSkyLockstakeGetRewardInputSchema, mcpSkyLockstakeStakeInputSchema, mcpSkyLockstakeWipeInputSchema, mcpSkySusdsDepositInputSchema, mcpSkySusdsRedeemInputSchema, mcpUniswapV4BuildSwapMultisignInputSchema, mcpUniswapV4CreateSwapInputSchema, mcpUniswapV4CreateSwapOutputSchema, mcpUniswapV4QuoteInputSchema, mcpUniswapV4QuoteOutputSchema, multisignOutputSchema, parseMcpToolInput, parseMcpToolOutput, uniswapQuoteTradeTypeSchema, zodSchemaToMcpJsonSchema };
1193
1737
  //# sourceMappingURL=catalog.js.map
1194
1738
  //# sourceMappingURL=catalog.js.map