@continuumdao/ctm-mpc-defi 0.1.4 → 0.2.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +20 -78
- package/dist/agent/catalog.cjs +1388 -144
- package/dist/agent/catalog.cjs.map +1 -1
- package/dist/agent/catalog.d.ts +881 -17
- package/dist/agent/catalog.js +1327 -145
- package/dist/agent/catalog.js.map +1 -1
- package/dist/agent/skills/aave-v4/SKILL.md +43 -0
- package/dist/agent/skills/curve-dao/SKILL.md +12 -0
- package/dist/agent/skills/ethena/SKILL.md +10 -0
- package/dist/agent/skills/euler-v2/SKILL.md +10 -0
- package/dist/agent/skills/lido/SKILL.md +22 -0
- package/dist/agent/skills/maple-syrup/SKILL.md +10 -0
- package/dist/agent/skills/sky/SKILL.md +10 -0
- package/dist/agent/skills/uniswap-v4/SKILL.md +22 -0
- package/dist/chains/evm/index.cjs +27 -213
- package/dist/chains/evm/index.cjs.map +1 -1
- package/dist/chains/evm/index.d.ts +15 -25
- package/dist/chains/evm/index.js +21 -199
- package/dist/chains/evm/index.js.map +1 -1
- package/dist/chains/near/index.d.ts +1 -1
- package/dist/chains/solana/index.d.ts +1 -1
- package/dist/core/index.cjs +8 -110
- package/dist/core/index.cjs.map +1 -1
- package/dist/core/index.d.ts +5 -39
- package/dist/core/index.js +6 -100
- package/dist/core/index.js.map +1 -1
- package/dist/{envelope-CcE5Cz_q.d.ts → envelope-CpBUh9eP.d.ts} +1 -1
- package/dist/index.cjs +238 -1184
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.ts +7 -10
- package/dist/index.js +227 -1156
- package/dist/index.js.map +1 -1
- package/dist/protocols/evm/aave-v4/index.cjs +1710 -0
- package/dist/protocols/evm/aave-v4/index.cjs.map +1 -0
- package/dist/protocols/evm/aave-v4/index.d.ts +499 -0
- package/dist/protocols/evm/aave-v4/index.js +1666 -0
- package/dist/protocols/evm/aave-v4/index.js.map +1 -0
- package/dist/protocols/evm/curve-dao/index.cjs +24 -124
- package/dist/protocols/evm/curve-dao/index.cjs.map +1 -1
- package/dist/protocols/evm/curve-dao/index.d.ts +3 -4
- package/dist/protocols/evm/curve-dao/index.js +15 -115
- package/dist/protocols/evm/curve-dao/index.js.map +1 -1
- package/dist/protocols/evm/ethena/index.cjs +853 -0
- package/dist/protocols/evm/ethena/index.cjs.map +1 -0
- package/dist/protocols/evm/ethena/index.d.ts +160 -0
- package/dist/protocols/evm/ethena/index.js +831 -0
- package/dist/protocols/evm/ethena/index.js.map +1 -0
- package/dist/protocols/evm/euler-v2/index.cjs +1585 -0
- package/dist/protocols/evm/euler-v2/index.cjs.map +1 -0
- package/dist/protocols/evm/euler-v2/index.d.ts +316 -0
- package/dist/protocols/evm/euler-v2/index.js +1560 -0
- package/dist/protocols/evm/euler-v2/index.js.map +1 -0
- package/dist/protocols/evm/lido/index.cjs +839 -0
- package/dist/protocols/evm/lido/index.cjs.map +1 -0
- package/dist/protocols/evm/lido/index.d.ts +119 -0
- package/dist/protocols/evm/lido/index.js +814 -0
- package/dist/protocols/evm/lido/index.js.map +1 -0
- package/dist/protocols/evm/maple/index.cjs +619 -0
- package/dist/protocols/evm/maple/index.cjs.map +1 -0
- package/dist/protocols/evm/maple/index.d.ts +108 -0
- package/dist/protocols/evm/maple/index.js +605 -0
- package/dist/protocols/evm/maple/index.js.map +1 -0
- package/dist/protocols/evm/sky/index.cjs +1259 -0
- package/dist/protocols/evm/sky/index.cjs.map +1 -0
- package/dist/protocols/evm/sky/index.d.ts +217 -0
- package/dist/protocols/evm/sky/index.js +1234 -0
- package/dist/protocols/evm/sky/index.js.map +1 -0
- package/dist/protocols/evm/uniswap-v4/index.cjs +423 -658
- package/dist/protocols/evm/uniswap-v4/index.cjs.map +1 -1
- package/dist/protocols/evm/uniswap-v4/index.d.ts +3 -4
- package/dist/protocols/evm/uniswap-v4/index.js +422 -657
- package/dist/protocols/evm/uniswap-v4/index.js.map +1 -1
- package/dist/{registry-oMKlO_5z.d.ts → registry-Bv5o37_w.d.ts} +1 -1
- package/dist/{types-Ce2qNHai.d.cts → types-BfjWdw1j.d.ts} +3 -1
- package/dist/{types-5u863Fd9.d.ts → types-DUeNJLr9.d.ts} +1 -1
- package/package.json +43 -8
- package/dist/agent/catalog.d.cts +0 -195
- package/dist/chains/evm/index.d.cts +0 -62
- package/dist/chains/near/index.d.cts +0 -37
- package/dist/chains/solana/index.d.cts +0 -40
- package/dist/core/index.d.cts +0 -43
- package/dist/envelope-DYDPnrHZ.d.cts +0 -35
- package/dist/index.d.cts +0 -15
- package/dist/keygen-CfNp8yKJ.d.cts +0 -9
- package/dist/keygen-DsINazx8.d.ts +0 -9
- package/dist/nodeRead-BnmSaMGO.d.cts +0 -8
- package/dist/nodeRead-BnmSaMGO.d.ts +0 -8
- package/dist/protocols/evm/curve-dao/index.d.cts +0 -147
- package/dist/protocols/evm/uniswap-v4/index.d.cts +0 -324
- package/dist/registry-BwZoE668.d.cts +0 -8
- package/dist/txParams-BC7ogvdR.d.cts +0 -19
- package/dist/txParams-BC7ogvdR.d.ts +0 -19
- package/dist/types-B8idm_gu.d.cts +0 -34
- package/dist/types-Ce2qNHai.d.ts +0 -57
package/dist/agent/catalog.js
CHANGED
|
@@ -1,4 +1,9 @@
|
|
|
1
|
-
import 'viem';
|
|
1
|
+
import { getAddress, isAddress } from 'viem';
|
|
2
|
+
import { zodToJsonSchema } from 'zod-to-json-schema';
|
|
3
|
+
import { z } from 'zod';
|
|
4
|
+
import { readFileSync } from 'fs';
|
|
5
|
+
import { join, dirname } from 'path';
|
|
6
|
+
import { fileURLToPath } from 'url';
|
|
2
7
|
|
|
3
8
|
// src/core/registry.ts
|
|
4
9
|
var modules = [];
|
|
@@ -157,6 +162,96 @@ function isCurveApiChainSupported(chainId) {
|
|
|
157
162
|
if (Number.isNaN(n) || n < 0) return false;
|
|
158
163
|
return CURVE_FULL_NETWORK_CONSTANTS_CHAIN_IDS.has(n);
|
|
159
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
|
+
}
|
|
160
255
|
|
|
161
256
|
// src/protocols/evm/curve-dao/index.ts
|
|
162
257
|
var CURVE_DAO_PROTOCOL_ID = "curve-dao";
|
|
@@ -246,7 +341,14 @@ var MULTISIGN_OUTPUT_DOC = {
|
|
|
246
341
|
}
|
|
247
342
|
};
|
|
248
343
|
var MANAGEMENT_SIG_DOC = {
|
|
249
|
-
description: "Management POST bodies embed NodeMgtKeySig: { nonce, clientSig, nodeKey }. Sign JSON with clientSig cleared; POST with
|
|
344
|
+
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.",
|
|
345
|
+
exceptions: {
|
|
346
|
+
configUpdateImplement: "POST /configUpdateImplement: include nodeKey + plannedYaml + signedMessage (opaque configUpdateImplement|<sha256> line). Sign the opaque line bytes, not the JSON body.",
|
|
347
|
+
postMSQTTKey: "POST /postMSQTTKey: include nodeKey + caCertPem + clientSig. Sign caCertPem PEM bytes directly (use buildPostMqttKeyBody).",
|
|
348
|
+
addManagementKey: "POST /addManagementKey / removeManagementKey (EIP-191): may still use signedMessage equal to the canonical JSON string for dual-mode Ethereum signing.",
|
|
349
|
+
agentLlmConfig: "POST /agentLlmConfig / agentLlmApiKey: sign canonical JSON with action + clientSig cleared; POST body has nonce, clientSig, nodeKey, endpoint fields \u2014 no signedMessage field.",
|
|
350
|
+
multiSignRequest: "POST /multiSignRequest (client key, not management): POST { ...bodyForSign, clientSig, signedMessage: messageToSign }."
|
|
351
|
+
},
|
|
250
352
|
fields: {
|
|
251
353
|
nonce: {
|
|
252
354
|
type: "number",
|
|
@@ -264,52 +366,592 @@ var MANAGEMENT_SIG_DOC = {
|
|
|
264
366
|
helpers: {
|
|
265
367
|
managementSigFields: "Base envelope with clientSig cleared.",
|
|
266
368
|
buildManagementPostBody: "Spread managementSigFields then endpoint fields.",
|
|
369
|
+
buildPostMqttKeyBody: "POST /postMSQTTKey unsigned body (sign PEM directly).",
|
|
370
|
+
buildPostPreferredKeyGenBody: "POST /postPreferredKeyGen unsigned body.",
|
|
371
|
+
buildConfigUpdateImplementPostBody: "POST /configUpdateImplement with opaque signedMessage line.",
|
|
372
|
+
buildSignRequestAgreeUnsignedBody: "POST /signRequestAgree unsigned body with nodeKey.",
|
|
267
373
|
messageToSignManagementBody: "Canonical JSON string to sign.",
|
|
268
374
|
withManagementClientSig: "Attach signature to POST body.",
|
|
269
375
|
fetchNodeKey: "GET /getNodeKey via nodeFetchWithReadAuth.",
|
|
270
|
-
fetchManagementNonce: "GET nonce for Ed25519 or Ethereum management key."
|
|
376
|
+
fetchManagementNonce: "GET nonce for Ed25519 or Ethereum management key.",
|
|
377
|
+
fetchPreferredKeyGen: "GET /getPreferredKeyGen for agent default KeyGen."
|
|
271
378
|
}
|
|
272
379
|
};
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
380
|
+
function zodSchemaToMcpJsonSchema(schema) {
|
|
381
|
+
const raw = zodToJsonSchema(schema, {
|
|
382
|
+
target: "openApi3",
|
|
383
|
+
$refStrategy: "none"
|
|
384
|
+
});
|
|
385
|
+
if (raw.type === "object" || raw.type === "array" || raw.type === "string") {
|
|
386
|
+
const { $schema: _s, ...rest } = raw;
|
|
387
|
+
return rest;
|
|
280
388
|
}
|
|
281
|
-
|
|
282
|
-
|
|
389
|
+
const defs = raw.definitions;
|
|
390
|
+
if (defs) {
|
|
391
|
+
const first = Object.values(defs)[0];
|
|
392
|
+
if (first?.type) {
|
|
393
|
+
const { $schema: _s, ...rest } = first;
|
|
394
|
+
return rest;
|
|
395
|
+
}
|
|
283
396
|
}
|
|
284
|
-
return
|
|
397
|
+
return raw;
|
|
285
398
|
}
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
399
|
+
var evmAddressSchema = z.string().min(1).describe("EVM address (0x-prefixed, 40 hex nibbles)");
|
|
400
|
+
var keyGenSchema = z.object({
|
|
401
|
+
pubkeyhex: z.string().min(1).describe("MPC secp256k1 public key hex (required for multiSignRequest pubKey)"),
|
|
402
|
+
keylist: z.array(z.string()).optional().describe("Key list on the sign request"),
|
|
403
|
+
ClientKeys: z.record(z.string()).optional().describe("Optional client key map from keyGen")
|
|
404
|
+
}).describe(
|
|
405
|
+
"MPC key slice: { pubkeyhex, keylist?, ClientKeys? }. Used for pubKey/keyList on POST /multiSignRequest."
|
|
406
|
+
);
|
|
407
|
+
var chainDetailSchema = z.object({
|
|
408
|
+
legacy: z.boolean().optional(),
|
|
409
|
+
gasLimit: z.number().optional(),
|
|
410
|
+
gasMultiplier: z.number().optional(),
|
|
411
|
+
gasPrice: z.number().optional(),
|
|
412
|
+
baseFee: z.number().optional(),
|
|
413
|
+
priorityFee: z.number().optional(),
|
|
414
|
+
baseFeeMultiplier: z.number().optional()
|
|
415
|
+
}).passthrough().describe(
|
|
416
|
+
"Optional gas config: { legacy?, gasLimit?, gasMultiplier?, gasPrice?, baseFee?, priorityFee?, baseFeeMultiplier? }."
|
|
417
|
+
);
|
|
418
|
+
var evmMultisignCommonInputSchema = z.object({
|
|
419
|
+
keyGen: keyGenSchema,
|
|
420
|
+
purposeText: z.string().min(1).describe(
|
|
421
|
+
"Human-readable purpose for the sign request. Stored in bodyForSign.purpose (may be appended with an automatic batch suffix)."
|
|
422
|
+
),
|
|
423
|
+
useCustomGas: z.boolean().describe(
|
|
424
|
+
"When true, apply chain gas settings from chainDetail / customGasChainDetails instead of raw RPC estimates only."
|
|
425
|
+
),
|
|
426
|
+
chainId: z.number().int().positive().describe("EVM chain id (decimal). Becomes destinationChainID on the sign request."),
|
|
427
|
+
rpcUrl: z.string().min(1).describe("HTTPS JSON-RPC URL for gas estimation, nonce, and allowance reads."),
|
|
428
|
+
executorAddress: evmAddressSchema.describe(
|
|
429
|
+
"MPC wallet address (from keyGen ethereumaddress) \u2014 tx sender for estimates and approvals."
|
|
430
|
+
),
|
|
431
|
+
chainDetail: chainDetailSchema,
|
|
432
|
+
customGasChainDetails: z.record(z.unknown()).optional().describe("Snapshot written to extraJSON.customGasChainDetails when useCustomGas is true.")
|
|
433
|
+
});
|
|
434
|
+
var multisignOutputSchema = z.object({
|
|
435
|
+
bodyForSign: z.record(z.unknown()).describe(
|
|
436
|
+
"POST body fields without clientSig: keyList, pubKey, msgHash, msgRaw, destinationChainID, purpose, extraJSON, proposalTxParams (batch), messageHashes/messageRawBatch when N>1 txs."
|
|
437
|
+
),
|
|
438
|
+
messageToSign: z.string().describe("JSON.stringify(bodyForSign) \u2014 exact string to sign before adding clientSig.")
|
|
439
|
+
}).describe(
|
|
440
|
+
"Unsigned mpc-auth multiSignRequest payload. Sign messageToSign and POST { ...bodyForSign, clientSig, signedMessage } to /multiSignRequest."
|
|
441
|
+
);
|
|
442
|
+
var jsonObjectSchema = z.record(z.unknown());
|
|
443
|
+
var uniswapQuoteTradeTypeSchema = z.enum(["EXACT_INPUT", "EXACT_OUTPUT"]);
|
|
444
|
+
var mcpUniswapV4QuoteInputSchema = z.object({
|
|
445
|
+
type: uniswapQuoteTradeTypeSchema.describe("EXACT_INPUT or EXACT_OUTPUT"),
|
|
446
|
+
amount: z.string().min(1).describe("Amount in token-in base units (wei string for ERC-20)"),
|
|
447
|
+
tokenIn: z.string().min(1).describe("Input token; 0x0 for native ETH"),
|
|
448
|
+
tokenOut: z.string().min(1).describe("Output token address"),
|
|
449
|
+
chainId: z.union([z.number().int().positive(), z.string().min(1)]).describe("tokenInChainId / same-chain default"),
|
|
450
|
+
uniswapApiKey: z.string().min(1).describe("Uniswap Trade API x-api-key"),
|
|
451
|
+
swapper: evmAddressSchema.optional().describe("MPC executor; omit if keyGen + managementNodeUrl provided"),
|
|
452
|
+
slippage: z.union([z.number(), z.string()]).optional().describe("Slippage percent; omit for API auto slippage"),
|
|
453
|
+
keyGen: z.string().optional().describe("KeyGen id \u2014 resolves swapper via GET /getKeyGenResultById when swapper omitted"),
|
|
454
|
+
managementNodeUrl: z.string().min(1).optional().describe("MPC node base URL; required with keyGen when swapper is omitted"),
|
|
455
|
+
tokenInChainId: z.union([z.number(), z.string()]).optional(),
|
|
456
|
+
tokenOutChainId: z.union([z.number(), z.string()]).optional(),
|
|
457
|
+
permit2Disabled: z.boolean().optional(),
|
|
458
|
+
baseUrl: z.string().optional(),
|
|
459
|
+
universalRouterVersion: z.string().optional()
|
|
460
|
+
});
|
|
461
|
+
var mcpUniswapV4QuoteOutputSchema = jsonObjectSchema.describe(
|
|
462
|
+
"Full Uniswap POST /quote JSON (includes nested quote object with input/output amounts)."
|
|
463
|
+
);
|
|
464
|
+
var mcpUniswapV4CreateSwapInputSchema = z.object({
|
|
465
|
+
uniswapApiKey: z.string().min(1).describe("Uniswap Trade API key"),
|
|
466
|
+
fullQuoteFromPermit: jsonObjectSchema.describe("Full quote JSON from ctm_uniswap_v4_quote"),
|
|
467
|
+
swapTransactionDeadlineUnix: z.number().int().positive().optional().describe("On-chain deadline unix seconds; default ~30 min from now"),
|
|
468
|
+
useServerProxy: z.boolean().optional().describe("Set false in Node/agents; true only in browser via Next API route"),
|
|
469
|
+
baseUrl: z.string().optional(),
|
|
470
|
+
universalRouterVersion: z.string().optional()
|
|
471
|
+
});
|
|
472
|
+
var mcpUniswapV4CreateSwapOutputSchema = z.object({
|
|
473
|
+
swap: jsonObjectSchema.describe("Universal Router tx: { to, data, value, gasLimit? }"),
|
|
474
|
+
requestId: z.string().optional(),
|
|
475
|
+
gasFee: z.string().optional()
|
|
476
|
+
}).passthrough().describe("{ swap: TransactionRequest, requestId?, gasFee? }");
|
|
477
|
+
var swapTxRequestSchema = jsonObjectSchema.describe("swap field from create_swap response (to, data, value)");
|
|
478
|
+
var mcpUniswapV4BuildSwapMultisignInputSchema = evmMultisignCommonInputSchema.extend({
|
|
479
|
+
tokenIn: evmAddressSchema.describe("Token in; 0x0 for native ETH"),
|
|
480
|
+
swap: swapTxRequestSchema,
|
|
481
|
+
createSwapResponse: z.object({
|
|
482
|
+
swap: swapTxRequestSchema,
|
|
483
|
+
requestId: z.string().optional(),
|
|
484
|
+
gasFee: z.string().optional()
|
|
485
|
+
}).passthrough().describe("Full create_swap response"),
|
|
486
|
+
fullQuoteSnapshot: jsonObjectSchema.describe("Quote JSON used for the swap"),
|
|
487
|
+
swapDeadlineUnix: z.number().describe("Same deadline passed to create_swap"),
|
|
488
|
+
slippagePercent: z.number().optional().describe("Extra approve headroom for EXACT_OUTPUT")
|
|
489
|
+
});
|
|
490
|
+
var mcpCurveDaoBuildSwapMultisignInputSchema = evmMultisignCommonInputSchema.extend({
|
|
491
|
+
tokenIn: evmAddressSchema.describe("ERC-20 sold (native in uses WETH path in UI)"),
|
|
492
|
+
tokenOut: z.string().min(1).describe("Output token or 0xeeee\u2026 native placeholder"),
|
|
493
|
+
amountHuman: z.string().min(1).describe("Human-readable amount of tokenIn"),
|
|
494
|
+
slippagePercent: z.number().gt(0).lt(100).describe("Slippage 0\u2013100 exclusive")
|
|
495
|
+
});
|
|
496
|
+
function mcpMultisignInput(fields) {
|
|
497
|
+
return evmMultisignCommonInputSchema.extend(fields);
|
|
295
498
|
}
|
|
296
|
-
var
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
499
|
+
var mcpLidoSubmitInputSchema = mcpMultisignInput({
|
|
500
|
+
valueWei: z.string().min(1).describe("ETH to stake (wei decimal string)"),
|
|
501
|
+
referral: evmAddressSchema.optional()
|
|
502
|
+
});
|
|
503
|
+
var mcpLidoRequestWithdrawalsInputSchema = mcpMultisignInput({
|
|
504
|
+
stEthAmountsWei: z.array(z.string()).min(1).describe("stETH amounts per withdrawal request (wei strings)")
|
|
505
|
+
});
|
|
506
|
+
var mcpLidoClaimWithdrawalInputSchema = mcpMultisignInput({
|
|
507
|
+
requestId: z.union([z.string(), z.number()]).describe("Withdrawal queue request id")
|
|
508
|
+
});
|
|
509
|
+
var mcpLidoWrapStEthInputSchema = mcpMultisignInput({
|
|
510
|
+
stEthAmountWei: z.string().min(1)
|
|
511
|
+
});
|
|
512
|
+
var mcpLidoUnwrapWstEthInputSchema = mcpMultisignInput({
|
|
513
|
+
wstEthAmountWei: z.string().min(1)
|
|
514
|
+
});
|
|
515
|
+
var mcpEthenaStakeInputSchema = mcpMultisignInput({
|
|
516
|
+
usdeAmountHuman: z.string().min(1),
|
|
517
|
+
susdeVault: evmAddressSchema.optional()
|
|
518
|
+
});
|
|
519
|
+
var mcpEthenaRedeemInputSchema = mcpMultisignInput({
|
|
520
|
+
susdeSharesHuman: z.string().min(1),
|
|
521
|
+
susdeVault: evmAddressSchema.optional()
|
|
522
|
+
});
|
|
523
|
+
var mcpEthenaCooldownInputSchema = mcpMultisignInput({
|
|
524
|
+
susdeSharesHuman: z.string().min(1),
|
|
525
|
+
susdeVault: evmAddressSchema.optional()
|
|
526
|
+
});
|
|
527
|
+
var mcpEthenaClaimInputSchema = mcpMultisignInput({
|
|
528
|
+
susdeVault: evmAddressSchema.optional()
|
|
529
|
+
});
|
|
530
|
+
var mcpMapleDepositInputSchema = mcpMultisignInput({
|
|
531
|
+
syrupRouter: evmAddressSchema,
|
|
532
|
+
pool: evmAddressSchema,
|
|
533
|
+
asset: evmAddressSchema,
|
|
534
|
+
amountHuman: z.string().min(1),
|
|
535
|
+
authorizeSig: jsonObjectSchema.optional()
|
|
536
|
+
});
|
|
537
|
+
var mcpMapleRequestRedeemInputSchema = mcpMultisignInput({
|
|
538
|
+
pool: evmAddressSchema,
|
|
539
|
+
sharesHuman: z.string().min(1),
|
|
540
|
+
receiver: evmAddressSchema
|
|
541
|
+
});
|
|
542
|
+
var mcpSkyLockstakeStakeInputSchema = mcpMultisignInput({
|
|
543
|
+
skyAmountHuman: z.string().min(1),
|
|
544
|
+
usdsDrawHuman: z.string().optional(),
|
|
545
|
+
farmRef: z.string().optional()
|
|
546
|
+
});
|
|
547
|
+
var mcpSkyLockstakeDrawInputSchema = mcpMultisignInput({
|
|
548
|
+
usdsAmountHuman: z.string().min(1),
|
|
549
|
+
urnIndex: z.number().int().nonnegative()
|
|
550
|
+
});
|
|
551
|
+
var mcpSkyLockstakeWipeInputSchema = mcpMultisignInput({
|
|
552
|
+
usdsAmountHuman: z.string().min(1),
|
|
553
|
+
urnIndex: z.number().int().nonnegative()
|
|
554
|
+
});
|
|
555
|
+
var mcpSkyLockstakeCloseInputSchema = mcpMultisignInput({
|
|
556
|
+
urnIndex: z.number().int().nonnegative()
|
|
557
|
+
});
|
|
558
|
+
var mcpSkyLockstakeGetRewardInputSchema = mcpMultisignInput({
|
|
559
|
+
urnIndex: z.number().int().nonnegative()
|
|
560
|
+
});
|
|
561
|
+
var mcpSkySusdsDepositInputSchema = mcpMultisignInput({
|
|
562
|
+
usdsAmountHuman: z.string().min(1)
|
|
563
|
+
});
|
|
564
|
+
var mcpSkySusdsRedeemInputSchema = mcpMultisignInput({
|
|
565
|
+
sharesHuman: z.string().min(1)
|
|
566
|
+
});
|
|
567
|
+
var mcpAaveV4DepositInputSchema = mcpMultisignInput({
|
|
568
|
+
spoke: evmAddressSchema,
|
|
569
|
+
underlying: evmAddressSchema,
|
|
570
|
+
amountHuman: z.string().min(1),
|
|
571
|
+
marketId: z.string().min(1)
|
|
572
|
+
});
|
|
573
|
+
var mcpAaveV4WithdrawInputSchema = mcpMultisignInput({
|
|
574
|
+
spoke: evmAddressSchema,
|
|
575
|
+
underlying: evmAddressSchema,
|
|
576
|
+
amountHuman: z.string().min(1),
|
|
577
|
+
marketId: z.string().min(1)
|
|
578
|
+
});
|
|
579
|
+
var mcpAaveV4BorrowInputSchema = mcpMultisignInput({
|
|
580
|
+
spoke: evmAddressSchema,
|
|
581
|
+
underlying: evmAddressSchema,
|
|
582
|
+
amountHuman: z.string().min(1),
|
|
583
|
+
marketId: z.string().min(1)
|
|
584
|
+
});
|
|
585
|
+
var mcpAaveV4RepayInputSchema = mcpMultisignInput({
|
|
586
|
+
spoke: evmAddressSchema,
|
|
587
|
+
underlying: evmAddressSchema,
|
|
588
|
+
amountHuman: z.string().min(1),
|
|
589
|
+
marketId: z.string().min(1)
|
|
590
|
+
});
|
|
591
|
+
var mcpEulerV2IsolatedLendInputSchema = mcpMultisignInput({
|
|
592
|
+
vault: evmAddressSchema,
|
|
593
|
+
assetAmountHuman: z.string().min(1)
|
|
594
|
+
});
|
|
595
|
+
var mcpEulerV2IsolatedBorrowInputSchema = mcpMultisignInput({
|
|
596
|
+
vault: evmAddressSchema,
|
|
597
|
+
collateralAsset: evmAddressSchema,
|
|
598
|
+
borrowAsset: evmAddressSchema,
|
|
599
|
+
collateralAmountHuman: z.string().min(1),
|
|
600
|
+
loopBorrowWeis: z.array(z.string()).min(1)
|
|
601
|
+
});
|
|
602
|
+
var mcpEulerV2VaultWithdrawInputSchema = mcpMultisignInput({
|
|
603
|
+
vault: evmAddressSchema,
|
|
604
|
+
sharesHuman: z.string().min(1)
|
|
605
|
+
});
|
|
606
|
+
var mcpEulerV2BorrowRepayInputSchema = mcpMultisignInput({
|
|
607
|
+
vault: evmAddressSchema,
|
|
608
|
+
amountHuman: z.string().min(1)
|
|
609
|
+
});
|
|
610
|
+
var mcpEulerV2CollateralDepositInputSchema = mcpMultisignInput({
|
|
611
|
+
vault: evmAddressSchema,
|
|
612
|
+
collateralAsset: evmAddressSchema,
|
|
613
|
+
amountHuman: z.string().min(1)
|
|
614
|
+
});
|
|
615
|
+
var mcpEulerV2CollateralWithdrawInputSchema = mcpMultisignInput({
|
|
616
|
+
vault: evmAddressSchema,
|
|
617
|
+
collateralAsset: evmAddressSchema,
|
|
618
|
+
amountHuman: z.string().min(1)
|
|
619
|
+
});
|
|
620
|
+
|
|
621
|
+
// src/agent/mcpProtocolTools.ts
|
|
622
|
+
function defineProtocolMcpTool(def) {
|
|
623
|
+
return {
|
|
624
|
+
...def,
|
|
625
|
+
outputZod: multisignOutputSchema,
|
|
626
|
+
inputSchema: zodSchemaToMcpJsonSchema(def.inputZod),
|
|
627
|
+
outputSchema: zodSchemaToMcpJsonSchema(multisignOutputSchema),
|
|
628
|
+
parseInput: (data) => def.inputZod.parse(data),
|
|
629
|
+
parseOutput: (data) => multisignOutputSchema.parse(data)
|
|
630
|
+
};
|
|
631
|
+
}
|
|
632
|
+
var MCP_PROTOCOL_TOOL_DEFINITIONS = [
|
|
633
|
+
defineProtocolMcpTool({
|
|
634
|
+
name: "ctm_lido_build_submit_multisign",
|
|
635
|
+
actionId: "lido.submit",
|
|
636
|
+
protocolId: "lido",
|
|
637
|
+
chainCategory: "evm",
|
|
638
|
+
description: "Build mpc-auth multiSignRequest for Lido ETH stake (submit).",
|
|
639
|
+
prerequisites: ["keyGen", "executorAddress", "RPC URL"],
|
|
640
|
+
followUp: ["Sign messageToSign", "POST /multiSignRequest"],
|
|
641
|
+
handler: { importPath: "protocols/evm/lido", exportName: "buildEvmMultisignBodyLidoSubmit" },
|
|
642
|
+
inputZod: mcpLidoSubmitInputSchema
|
|
643
|
+
}),
|
|
644
|
+
defineProtocolMcpTool({
|
|
645
|
+
name: "ctm_lido_build_request_withdrawals_multisign",
|
|
646
|
+
actionId: "lido.request-withdrawals",
|
|
647
|
+
protocolId: "lido",
|
|
648
|
+
chainCategory: "evm",
|
|
649
|
+
description: "Build batch for Lido withdrawal queue (approve + requestWithdrawals).",
|
|
650
|
+
prerequisites: ["keyGen", "executorAddress", "RPC URL"],
|
|
651
|
+
followUp: ["Sign messageToSign", "POST /multiSignRequest"],
|
|
652
|
+
handler: { importPath: "protocols/evm/lido", exportName: "buildEvmMultisignBodyLidoRequestWithdrawals" },
|
|
653
|
+
inputZod: mcpLidoRequestWithdrawalsInputSchema
|
|
654
|
+
}),
|
|
655
|
+
defineProtocolMcpTool({
|
|
656
|
+
name: "ctm_lido_build_claim_withdrawal_multisign",
|
|
657
|
+
actionId: "lido.claim-withdrawal",
|
|
658
|
+
protocolId: "lido",
|
|
659
|
+
chainCategory: "evm",
|
|
660
|
+
description: "Build tx for Lido claimWithdrawal.",
|
|
661
|
+
prerequisites: ["keyGen", "executorAddress", "RPC URL"],
|
|
662
|
+
followUp: ["Sign messageToSign", "POST /multiSignRequest"],
|
|
663
|
+
handler: { importPath: "protocols/evm/lido", exportName: "buildEvmMultisignBodyLidoClaimWithdrawal" },
|
|
664
|
+
inputZod: mcpLidoClaimWithdrawalInputSchema
|
|
665
|
+
}),
|
|
666
|
+
defineProtocolMcpTool({
|
|
667
|
+
name: "ctm_lido_build_wrap_steth_multisign",
|
|
668
|
+
actionId: "lido.wrap-steth",
|
|
669
|
+
protocolId: "lido",
|
|
670
|
+
chainCategory: "evm",
|
|
671
|
+
description: "Build batch for wstETH wrap.",
|
|
672
|
+
prerequisites: ["keyGen", "executorAddress", "RPC URL"],
|
|
673
|
+
followUp: ["Sign messageToSign", "POST /multiSignRequest"],
|
|
674
|
+
handler: { importPath: "protocols/evm/lido", exportName: "buildEvmMultisignBodyLidoWrapStEth" },
|
|
675
|
+
inputZod: mcpLidoWrapStEthInputSchema
|
|
676
|
+
}),
|
|
677
|
+
defineProtocolMcpTool({
|
|
678
|
+
name: "ctm_lido_build_unwrap_wsteth_multisign",
|
|
679
|
+
actionId: "lido.unwrap-wsteth",
|
|
680
|
+
protocolId: "lido",
|
|
681
|
+
chainCategory: "evm",
|
|
682
|
+
description: "Build tx for wstETH unwrap.",
|
|
683
|
+
prerequisites: ["keyGen", "executorAddress", "RPC URL"],
|
|
684
|
+
followUp: ["Sign messageToSign", "POST /multiSignRequest"],
|
|
685
|
+
handler: { importPath: "protocols/evm/lido", exportName: "buildEvmMultisignBodyLidoUnwrapWstEth" },
|
|
686
|
+
inputZod: mcpLidoUnwrapWstEthInputSchema
|
|
687
|
+
}),
|
|
688
|
+
defineProtocolMcpTool({
|
|
689
|
+
name: "ctm_ethena_build_stake_multisign",
|
|
690
|
+
actionId: "ethena.stake-usde",
|
|
691
|
+
protocolId: "ethena",
|
|
692
|
+
chainCategory: "evm",
|
|
693
|
+
description: "Build batch: USDe approve + sUSDe deposit.",
|
|
694
|
+
prerequisites: ["keyGen", "executorAddress", "Ethereum mainnet RPC"],
|
|
695
|
+
followUp: ["Sign messageToSign", "POST /multiSignRequest"],
|
|
696
|
+
handler: { importPath: "protocols/evm/ethena", exportName: "buildEvmMultisignBodyEthenaUsdeStakeToSusde" },
|
|
697
|
+
inputZod: mcpEthenaStakeInputSchema
|
|
698
|
+
}),
|
|
699
|
+
defineProtocolMcpTool({
|
|
700
|
+
name: "ctm_ethena_build_redeem_multisign",
|
|
701
|
+
actionId: "ethena.redeem-susde",
|
|
702
|
+
protocolId: "ethena",
|
|
703
|
+
chainCategory: "evm",
|
|
704
|
+
description: "Build sUSDe redeem when cooldown is off.",
|
|
705
|
+
prerequisites: ["keyGen", "executorAddress", "RPC URL"],
|
|
706
|
+
followUp: ["Sign messageToSign", "POST /multiSignRequest"],
|
|
707
|
+
handler: { importPath: "protocols/evm/ethena", exportName: "buildEvmMultisignBodyEthenaSusdeRedeemToUsde" },
|
|
708
|
+
inputZod: mcpEthenaRedeemInputSchema
|
|
709
|
+
}),
|
|
710
|
+
defineProtocolMcpTool({
|
|
711
|
+
name: "ctm_ethena_build_cooldown_multisign",
|
|
712
|
+
actionId: "ethena.cooldown-shares",
|
|
713
|
+
protocolId: "ethena",
|
|
714
|
+
chainCategory: "evm",
|
|
715
|
+
description: "Build sUSDe cooldownShares batch step.",
|
|
716
|
+
prerequisites: ["keyGen", "executorAddress", "RPC URL"],
|
|
717
|
+
followUp: ["Sign messageToSign", "POST /multiSignRequest"],
|
|
718
|
+
handler: { importPath: "protocols/evm/ethena", exportName: "buildEvmMultisignBodyEthenaSusdeCooldownShares" },
|
|
719
|
+
inputZod: mcpEthenaCooldownInputSchema
|
|
720
|
+
}),
|
|
721
|
+
defineProtocolMcpTool({
|
|
722
|
+
name: "ctm_ethena_build_claim_multisign",
|
|
723
|
+
actionId: "ethena.claim-unstake",
|
|
724
|
+
protocolId: "ethena",
|
|
725
|
+
chainCategory: "evm",
|
|
726
|
+
description: "Build unstake claim after cooldown.",
|
|
727
|
+
prerequisites: ["keyGen", "executorAddress", "RPC URL"],
|
|
728
|
+
followUp: ["Sign messageToSign", "POST /multiSignRequest"],
|
|
729
|
+
handler: { importPath: "protocols/evm/ethena", exportName: "buildEvmMultisignBodyEthenaUnstakeClaim" },
|
|
730
|
+
inputZod: mcpEthenaClaimInputSchema
|
|
731
|
+
}),
|
|
732
|
+
defineProtocolMcpTool({
|
|
733
|
+
name: "ctm_maple_build_deposit_multisign",
|
|
734
|
+
actionId: "maple-syrup.deposit",
|
|
735
|
+
protocolId: "maple-syrup",
|
|
736
|
+
chainCategory: "evm",
|
|
737
|
+
description: "Build Maple Syrup router deposit batch.",
|
|
738
|
+
prerequisites: ["keyGen", "executorAddress", "router + pool addresses"],
|
|
739
|
+
followUp: ["Sign messageToSign", "POST /multiSignRequest"],
|
|
740
|
+
handler: { importPath: "protocols/evm/maple", exportName: "buildEvmMultisignBodyMapleSyrupDeposit" },
|
|
741
|
+
inputZod: mcpMapleDepositInputSchema
|
|
742
|
+
}),
|
|
743
|
+
defineProtocolMcpTool({
|
|
744
|
+
name: "ctm_maple_build_request_redeem_multisign",
|
|
745
|
+
actionId: "maple-syrup.request-redeem",
|
|
746
|
+
protocolId: "maple-syrup",
|
|
747
|
+
chainCategory: "evm",
|
|
748
|
+
description: "Build Maple PoolV2 requestRedeem batch.",
|
|
749
|
+
prerequisites: ["keyGen", "executorAddress", "pool address"],
|
|
750
|
+
followUp: ["Sign messageToSign", "POST /multiSignRequest"],
|
|
751
|
+
handler: { importPath: "protocols/evm/maple", exportName: "buildEvmMultisignBodyMaplePoolRequestRedeem" },
|
|
752
|
+
inputZod: mcpMapleRequestRedeemInputSchema
|
|
753
|
+
}),
|
|
754
|
+
defineProtocolMcpTool({
|
|
755
|
+
name: "ctm_sky_build_lockstake_stake_multisign",
|
|
756
|
+
actionId: "sky.lockstake-stake",
|
|
757
|
+
protocolId: "sky",
|
|
758
|
+
chainCategory: "evm",
|
|
759
|
+
description: "Build Sky Lockstake open/stake batch.",
|
|
760
|
+
prerequisites: ["keyGen", "executorAddress", "Ethereum mainnet RPC"],
|
|
761
|
+
followUp: ["Sign messageToSign", "POST /multiSignRequest"],
|
|
762
|
+
handler: { importPath: "protocols/evm/sky", exportName: "buildSkyLockstakeStakePositionBatch" },
|
|
763
|
+
inputZod: mcpSkyLockstakeStakeInputSchema
|
|
764
|
+
}),
|
|
765
|
+
defineProtocolMcpTool({
|
|
766
|
+
name: "ctm_sky_build_lockstake_draw_multisign",
|
|
767
|
+
actionId: "sky.lockstake-draw",
|
|
768
|
+
protocolId: "sky",
|
|
769
|
+
chainCategory: "evm",
|
|
770
|
+
description: "Build Lockstake draw (borrow USDS).",
|
|
771
|
+
prerequisites: ["keyGen", "executorAddress", "open urn"],
|
|
772
|
+
followUp: ["Sign messageToSign", "POST /multiSignRequest"],
|
|
773
|
+
handler: { importPath: "protocols/evm/sky", exportName: "buildSkyLockstakeDrawBatch" },
|
|
774
|
+
inputZod: mcpSkyLockstakeDrawInputSchema
|
|
775
|
+
}),
|
|
776
|
+
defineProtocolMcpTool({
|
|
777
|
+
name: "ctm_sky_build_lockstake_wipe_multisign",
|
|
778
|
+
actionId: "sky.lockstake-wipe",
|
|
779
|
+
protocolId: "sky",
|
|
780
|
+
chainCategory: "evm",
|
|
781
|
+
description: "Build Lockstake repay/wipe batch.",
|
|
782
|
+
prerequisites: ["keyGen", "executorAddress", "urn index"],
|
|
783
|
+
followUp: ["Sign messageToSign", "POST /multiSignRequest"],
|
|
784
|
+
handler: { importPath: "protocols/evm/sky", exportName: "buildSkyLockstakeWipeBatch" },
|
|
785
|
+
inputZod: mcpSkyLockstakeWipeInputSchema
|
|
786
|
+
}),
|
|
787
|
+
defineProtocolMcpTool({
|
|
788
|
+
name: "ctm_sky_build_lockstake_close_multisign",
|
|
789
|
+
actionId: "sky.lockstake-close",
|
|
790
|
+
protocolId: "sky",
|
|
791
|
+
chainCategory: "evm",
|
|
792
|
+
description: "Build Lockstake close position batch.",
|
|
793
|
+
prerequisites: ["keyGen", "executorAddress", "urn index"],
|
|
794
|
+
followUp: ["Sign messageToSign", "POST /multiSignRequest"],
|
|
795
|
+
handler: { importPath: "protocols/evm/sky", exportName: "buildSkyLockstakeCloseBatch" },
|
|
796
|
+
inputZod: mcpSkyLockstakeCloseInputSchema
|
|
797
|
+
}),
|
|
798
|
+
defineProtocolMcpTool({
|
|
799
|
+
name: "ctm_sky_build_lockstake_get_reward_multisign",
|
|
800
|
+
actionId: "sky.lockstake-get-reward",
|
|
801
|
+
protocolId: "sky",
|
|
802
|
+
chainCategory: "evm",
|
|
803
|
+
description: "Build Lockstake getReward batch.",
|
|
804
|
+
prerequisites: ["keyGen", "executorAddress", "urn index"],
|
|
805
|
+
followUp: ["Sign messageToSign", "POST /multiSignRequest"],
|
|
806
|
+
handler: { importPath: "protocols/evm/sky", exportName: "buildSkyLockstakeGetRewardBatch" },
|
|
807
|
+
inputZod: mcpSkyLockstakeGetRewardInputSchema
|
|
808
|
+
}),
|
|
809
|
+
defineProtocolMcpTool({
|
|
810
|
+
name: "ctm_sky_build_susds_deposit_multisign",
|
|
811
|
+
actionId: "sky.susds-deposit",
|
|
812
|
+
protocolId: "sky",
|
|
813
|
+
chainCategory: "evm",
|
|
814
|
+
description: "Build USDS \u2192 sUSDS ERC-4626 deposit batch.",
|
|
815
|
+
prerequisites: ["keyGen", "executorAddress", "RPC URL"],
|
|
816
|
+
followUp: ["Sign messageToSign", "POST /multiSignRequest"],
|
|
817
|
+
handler: { importPath: "protocols/evm/sky", exportName: "buildSkySusdsDepositFromUsdsBatch" },
|
|
818
|
+
inputZod: mcpSkySusdsDepositInputSchema
|
|
819
|
+
}),
|
|
820
|
+
defineProtocolMcpTool({
|
|
821
|
+
name: "ctm_sky_build_susds_redeem_multisign",
|
|
822
|
+
actionId: "sky.susds-redeem",
|
|
823
|
+
protocolId: "sky",
|
|
824
|
+
chainCategory: "evm",
|
|
825
|
+
description: "Build sUSDS redeem to USDS batch.",
|
|
826
|
+
prerequisites: ["keyGen", "executorAddress", "RPC URL"],
|
|
827
|
+
followUp: ["Sign messageToSign", "POST /multiSignRequest"],
|
|
828
|
+
handler: { importPath: "protocols/evm/sky", exportName: "buildSkySusdsRedeemToUsdsBatch" },
|
|
829
|
+
inputZod: mcpSkySusdsRedeemInputSchema
|
|
830
|
+
}),
|
|
831
|
+
defineProtocolMcpTool({
|
|
832
|
+
name: "ctm_aave_v4_build_deposit_multisign",
|
|
833
|
+
actionId: "aave-v4.deposit",
|
|
834
|
+
protocolId: "aave-v4",
|
|
835
|
+
chainCategory: "evm",
|
|
836
|
+
description: "Build Aave v4 Spoke supply/deposit batch.",
|
|
837
|
+
prerequisites: ["keyGen", "executorAddress", "spoke + underlying"],
|
|
838
|
+
followUp: ["Sign messageToSign", "POST /multiSignRequest"],
|
|
839
|
+
handler: { importPath: "protocols/evm/aave-v4", exportName: "buildEvmMultisignBodyAaveV4DepositBatch" },
|
|
840
|
+
inputZod: mcpAaveV4DepositInputSchema
|
|
841
|
+
}),
|
|
842
|
+
defineProtocolMcpTool({
|
|
843
|
+
name: "ctm_aave_v4_build_withdraw_multisign",
|
|
844
|
+
actionId: "aave-v4.withdraw",
|
|
845
|
+
protocolId: "aave-v4",
|
|
846
|
+
chainCategory: "evm",
|
|
847
|
+
description: "Build Aave v4 Spoke withdraw batch.",
|
|
848
|
+
prerequisites: ["keyGen", "executorAddress", "spoke + underlying"],
|
|
849
|
+
followUp: ["Sign messageToSign", "POST /multiSignRequest"],
|
|
850
|
+
handler: { importPath: "protocols/evm/aave-v4", exportName: "buildEvmMultisignBodyAaveV4SpokeWithdraw" },
|
|
851
|
+
inputZod: mcpAaveV4WithdrawInputSchema
|
|
852
|
+
}),
|
|
853
|
+
defineProtocolMcpTool({
|
|
854
|
+
name: "ctm_aave_v4_build_borrow_multisign",
|
|
855
|
+
actionId: "aave-v4.borrow",
|
|
856
|
+
protocolId: "aave-v4",
|
|
857
|
+
chainCategory: "evm",
|
|
858
|
+
description: "Build Aave v4 Spoke borrow batch.",
|
|
859
|
+
prerequisites: ["keyGen", "executorAddress", "spoke + underlying"],
|
|
860
|
+
followUp: ["Sign messageToSign", "POST /multiSignRequest"],
|
|
861
|
+
handler: { importPath: "protocols/evm/aave-v4", exportName: "buildEvmMultisignBodyAaveV4SpokeBorrow" },
|
|
862
|
+
inputZod: mcpAaveV4BorrowInputSchema
|
|
863
|
+
}),
|
|
864
|
+
defineProtocolMcpTool({
|
|
865
|
+
name: "ctm_aave_v4_build_repay_multisign",
|
|
866
|
+
actionId: "aave-v4.repay",
|
|
867
|
+
protocolId: "aave-v4",
|
|
868
|
+
chainCategory: "evm",
|
|
869
|
+
description: "Build Aave v4 Spoke repay batch.",
|
|
870
|
+
prerequisites: ["keyGen", "executorAddress", "spoke + underlying"],
|
|
871
|
+
followUp: ["Sign messageToSign", "POST /multiSignRequest"],
|
|
872
|
+
handler: { importPath: "protocols/evm/aave-v4", exportName: "buildEvmMultisignBodyAaveV4SpokeRepay" },
|
|
873
|
+
inputZod: mcpAaveV4RepayInputSchema
|
|
874
|
+
}),
|
|
875
|
+
defineProtocolMcpTool({
|
|
876
|
+
name: "ctm_euler_v2_build_isolated_lend_multisign",
|
|
877
|
+
actionId: "euler-v2.isolated-lend",
|
|
878
|
+
protocolId: "euler-v2",
|
|
879
|
+
chainCategory: "evm",
|
|
880
|
+
description: "Build Euler v2 vault deposit/lend batch.",
|
|
881
|
+
prerequisites: ["keyGen", "executorAddress", "vault address"],
|
|
882
|
+
followUp: ["Sign messageToSign", "POST /multiSignRequest"],
|
|
883
|
+
handler: { importPath: "protocols/evm/euler-v2", exportName: "buildEvmMultisignBodyEulerV2IsolatedLendDepositBatch" },
|
|
884
|
+
inputZod: mcpEulerV2IsolatedLendInputSchema
|
|
885
|
+
}),
|
|
886
|
+
defineProtocolMcpTool({
|
|
887
|
+
name: "ctm_euler_v2_build_isolated_borrow_multisign",
|
|
888
|
+
actionId: "euler-v2.isolated-borrow",
|
|
889
|
+
protocolId: "euler-v2",
|
|
890
|
+
chainCategory: "evm",
|
|
891
|
+
description: "Build Euler v2 isolated borrow loop batch.",
|
|
892
|
+
prerequisites: ["keyGen", "executorAddress", "vault + collateral"],
|
|
893
|
+
followUp: ["Sign messageToSign", "POST /multiSignRequest"],
|
|
894
|
+
handler: { importPath: "protocols/evm/euler-v2", exportName: "buildEvmMultisignBodyEulerV2IsolatedBorrowBatch" },
|
|
895
|
+
inputZod: mcpEulerV2IsolatedBorrowInputSchema
|
|
896
|
+
}),
|
|
897
|
+
defineProtocolMcpTool({
|
|
898
|
+
name: "ctm_euler_v2_build_vault_withdraw_multisign",
|
|
899
|
+
actionId: "euler-v2.vault-withdraw",
|
|
900
|
+
protocolId: "euler-v2",
|
|
901
|
+
chainCategory: "evm",
|
|
902
|
+
description: "Build Euler v2 vault withdraw/redeem batch.",
|
|
903
|
+
prerequisites: ["keyGen", "executorAddress", "vault address"],
|
|
904
|
+
followUp: ["Sign messageToSign", "POST /multiSignRequest"],
|
|
905
|
+
handler: { importPath: "protocols/evm/euler-v2", exportName: "buildEvmMultisignBodyEulerV2VaultWithdraw" },
|
|
906
|
+
inputZod: mcpEulerV2VaultWithdrawInputSchema
|
|
907
|
+
}),
|
|
908
|
+
defineProtocolMcpTool({
|
|
909
|
+
name: "ctm_euler_v2_build_borrow_repay_multisign",
|
|
910
|
+
actionId: "euler-v2.borrow-repay",
|
|
911
|
+
protocolId: "euler-v2",
|
|
912
|
+
chainCategory: "evm",
|
|
913
|
+
description: "Build Euler v2 borrow repay batch.",
|
|
914
|
+
prerequisites: ["keyGen", "executorAddress", "vault address"],
|
|
915
|
+
followUp: ["Sign messageToSign", "POST /multiSignRequest"],
|
|
916
|
+
handler: { importPath: "protocols/evm/euler-v2", exportName: "buildEvmMultisignBodyEulerV2BorrowRepayBatch" },
|
|
917
|
+
inputZod: mcpEulerV2BorrowRepayInputSchema
|
|
918
|
+
}),
|
|
919
|
+
defineProtocolMcpTool({
|
|
920
|
+
name: "ctm_euler_v2_build_collateral_deposit_multisign",
|
|
921
|
+
actionId: "euler-v2.collateral-deposit",
|
|
922
|
+
protocolId: "euler-v2",
|
|
923
|
+
chainCategory: "evm",
|
|
924
|
+
description: "Build Euler v2 borrow collateral deposit batch.",
|
|
925
|
+
prerequisites: ["keyGen", "executorAddress", "vault + collateral asset"],
|
|
926
|
+
followUp: ["Sign messageToSign", "POST /multiSignRequest"],
|
|
927
|
+
handler: { importPath: "protocols/evm/euler-v2", exportName: "buildEvmMultisignBodyEulerV2BorrowCollateralDepositBatch" },
|
|
928
|
+
inputZod: mcpEulerV2CollateralDepositInputSchema
|
|
929
|
+
}),
|
|
930
|
+
defineProtocolMcpTool({
|
|
931
|
+
name: "ctm_euler_v2_build_collateral_withdraw_multisign",
|
|
932
|
+
actionId: "euler-v2.collateral-withdraw",
|
|
933
|
+
protocolId: "euler-v2",
|
|
934
|
+
chainCategory: "evm",
|
|
935
|
+
description: "Build Euler v2 borrow collateral withdraw batch.",
|
|
936
|
+
prerequisites: ["keyGen", "executorAddress", "vault + collateral asset"],
|
|
937
|
+
followUp: ["Sign messageToSign", "POST /multiSignRequest"],
|
|
938
|
+
handler: { importPath: "protocols/evm/euler-v2", exportName: "buildEvmMultisignBodyEulerV2BorrowCollateralWithdrawBatch" },
|
|
939
|
+
inputZod: mcpEulerV2CollateralWithdrawInputSchema
|
|
940
|
+
})
|
|
941
|
+
];
|
|
942
|
+
|
|
943
|
+
// src/agent/mcpTools.ts
|
|
944
|
+
function defineMcpTool(def) {
|
|
945
|
+
return {
|
|
946
|
+
...def,
|
|
947
|
+
inputSchema: zodSchemaToMcpJsonSchema(def.inputZod),
|
|
948
|
+
outputSchema: zodSchemaToMcpJsonSchema(def.outputZod),
|
|
949
|
+
parseInput: (data) => def.inputZod.parse(data),
|
|
950
|
+
parseOutput: (data) => def.outputZod.parse(data)
|
|
951
|
+
};
|
|
952
|
+
}
|
|
953
|
+
var CORE_MCP_TOOL_DEFINITIONS = [
|
|
954
|
+
defineMcpTool({
|
|
313
955
|
name: "ctm_uniswap_v4_quote",
|
|
314
956
|
actionId: "uniswap-v4.quote",
|
|
315
957
|
protocolId: "uniswap-v4",
|
|
@@ -318,33 +960,10 @@ var MCP_TOOL_DEFINITIONS = [
|
|
|
318
960
|
prerequisites: ["Chain must be supported by Uniswap V4 (Universal Router map)."],
|
|
319
961
|
followUp: ["ctm_uniswap_v4_create_swap", "ctm_uniswap_v4_build_swap_multisign"],
|
|
320
962
|
handler: { importPath: "protocols/evm/uniswap-v4", exportName: "uniswapTradeQuote" },
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
amount: { type: "string", required: true, description: "Amount in token-in base units (wei string for ERC-20)" },
|
|
326
|
-
tokenIn: { type: "address", required: true, description: "Input token; 0x0 for native ETH" },
|
|
327
|
-
tokenOut: { type: "address", required: true, description: "Output token address" },
|
|
328
|
-
chainId: { type: "number", required: true, description: "tokenInChainId / same-chain default" },
|
|
329
|
-
uniswapApiKey: { type: "string", required: true, description: "Uniswap Trade API x-api-key" },
|
|
330
|
-
swapper: { type: "address", required: false, description: "MPC executor; omit if keyGen + managementNodeUrl provided" },
|
|
331
|
-
slippage: { type: "number", required: false, description: "Slippage percent; omit for API auto slippage" }
|
|
332
|
-
}),
|
|
333
|
-
required: requiredKeys({
|
|
334
|
-
type: { type: "string", required: true, description: "" },
|
|
335
|
-
amount: { type: "string", required: true, description: "" },
|
|
336
|
-
tokenIn: { type: "address", required: true, description: "" },
|
|
337
|
-
tokenOut: { type: "address", required: true, description: "" },
|
|
338
|
-
chainId: { type: "number", required: true, description: "" },
|
|
339
|
-
uniswapApiKey: { type: "string", required: true, description: "" }
|
|
340
|
-
})
|
|
341
|
-
},
|
|
342
|
-
outputSchema: {
|
|
343
|
-
type: "object",
|
|
344
|
-
description: "Full Uniswap POST /quote JSON (includes nested quote object with input/output amounts)."
|
|
345
|
-
}
|
|
346
|
-
},
|
|
347
|
-
{
|
|
963
|
+
inputZod: mcpUniswapV4QuoteInputSchema,
|
|
964
|
+
outputZod: mcpUniswapV4QuoteOutputSchema
|
|
965
|
+
}),
|
|
966
|
+
defineMcpTool({
|
|
348
967
|
name: "ctm_uniswap_v4_create_swap",
|
|
349
968
|
actionId: "uniswap-v4.create-swap",
|
|
350
969
|
protocolId: "uniswap-v4",
|
|
@@ -353,33 +972,10 @@ var MCP_TOOL_DEFINITIONS = [
|
|
|
353
972
|
prerequisites: ["ctm_uniswap_v4_quote output (fullQuoteFromPermit)"],
|
|
354
973
|
followUp: ["ctm_uniswap_v4_build_swap_multisign"],
|
|
355
974
|
handler: { importPath: "protocols/evm/uniswap-v4", exportName: "uniswapCreateSwap" },
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
fullQuoteFromPermit: { type: "object", required: true, description: "Full quote JSON from ctm_uniswap_v4_quote" },
|
|
361
|
-
swapTransactionDeadlineUnix: {
|
|
362
|
-
type: "number",
|
|
363
|
-
required: false,
|
|
364
|
-
description: "On-chain deadline unix seconds; default ~30 min from now"
|
|
365
|
-
},
|
|
366
|
-
useServerProxy: {
|
|
367
|
-
type: "boolean",
|
|
368
|
-
required: false,
|
|
369
|
-
description: "Set false in Node/agents; true only in browser via Next API route"
|
|
370
|
-
}
|
|
371
|
-
}),
|
|
372
|
-
required: requiredKeys({
|
|
373
|
-
uniswapApiKey: { type: "string", required: true, description: "" },
|
|
374
|
-
fullQuoteFromPermit: { type: "object", required: true, description: "" }
|
|
375
|
-
})
|
|
376
|
-
},
|
|
377
|
-
outputSchema: {
|
|
378
|
-
type: "object",
|
|
379
|
-
description: "{ swap: TransactionRequest, requestId?, gasFee? }"
|
|
380
|
-
}
|
|
381
|
-
},
|
|
382
|
-
{
|
|
975
|
+
inputZod: mcpUniswapV4CreateSwapInputSchema,
|
|
976
|
+
outputZod: mcpUniswapV4CreateSwapOutputSchema
|
|
977
|
+
}),
|
|
978
|
+
defineMcpTool({
|
|
383
979
|
name: "ctm_uniswap_v4_build_swap_multisign",
|
|
384
980
|
actionId: "uniswap-v4.swap-exact-input",
|
|
385
981
|
protocolId: "uniswap-v4",
|
|
@@ -393,33 +989,10 @@ var MCP_TOOL_DEFINITIONS = [
|
|
|
393
989
|
],
|
|
394
990
|
followUp: ["Sign messageToSign", "POST /multiSignRequest with clientSig and signedMessage"],
|
|
395
991
|
handler: { importPath: "protocols/evm/uniswap-v4", exportName: "buildEvmMultisignBodyUniswapV4SkipPermit2Batch" },
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
tokenIn: { type: "address", required: true, description: "Token in; 0x0 for native ETH" },
|
|
401
|
-
swap: { type: "object", required: true, description: "swap field from create_swap response" },
|
|
402
|
-
createSwapResponse: { type: "object", required: true, description: "Full create_swap response" },
|
|
403
|
-
fullQuoteSnapshot: { type: "object", required: true, description: "Quote JSON used for the swap" },
|
|
404
|
-
swapDeadlineUnix: { type: "number", required: true, description: "Same deadline passed to create_swap" },
|
|
405
|
-
slippagePercent: { type: "number", required: false, description: "Extra approve headroom for EXACT_OUTPUT" }
|
|
406
|
-
},
|
|
407
|
-
["keyGen", "purposeText", "useCustomGas", "chainId", "rpcUrl", "executorAddress", "chainDetail", "customGasChainDetails"]
|
|
408
|
-
),
|
|
409
|
-
required: requiredKeys(
|
|
410
|
-
{
|
|
411
|
-
tokenIn: { type: "address", required: true, description: "" },
|
|
412
|
-
swap: { type: "object", required: true, description: "" },
|
|
413
|
-
createSwapResponse: { type: "object", required: true, description: "" },
|
|
414
|
-
fullQuoteSnapshot: { type: "object", required: true, description: "" },
|
|
415
|
-
swapDeadlineUnix: { type: "number", required: true, description: "" }
|
|
416
|
-
},
|
|
417
|
-
["keyGen", "purposeText", "useCustomGas", "chainId", "rpcUrl", "executorAddress", "chainDetail"]
|
|
418
|
-
)
|
|
419
|
-
},
|
|
420
|
-
outputSchema: multisignOutputSchema
|
|
421
|
-
},
|
|
422
|
-
{
|
|
992
|
+
inputZod: mcpUniswapV4BuildSwapMultisignInputSchema,
|
|
993
|
+
outputZod: multisignOutputSchema
|
|
994
|
+
}),
|
|
995
|
+
defineMcpTool({
|
|
423
996
|
name: "ctm_curve_dao_build_swap_multisign",
|
|
424
997
|
actionId: "curve-dao.swap",
|
|
425
998
|
protocolId: "curve-dao",
|
|
@@ -428,36 +1001,45 @@ var MCP_TOOL_DEFINITIONS = [
|
|
|
428
1001
|
prerequisites: ["keyGen", "executorAddress", "tokenIn/tokenOut/amountHuman/slippage", "RPC URL"],
|
|
429
1002
|
followUp: ["Sign messageToSign", "POST /multiSignRequest with clientSig and signedMessage"],
|
|
430
1003
|
handler: { importPath: "protocols/evm/curve-dao", exportName: "buildEvmMultisignBodyCurveDaoBatch" },
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
slippagePercent: { type: "number", required: true, description: "Slippage 0\u2013100 exclusive" }
|
|
439
|
-
},
|
|
440
|
-
["keyGen", "purposeText", "useCustomGas", "chainId", "rpcUrl", "executorAddress", "chainDetail", "customGasChainDetails"]
|
|
441
|
-
),
|
|
442
|
-
required: requiredKeys(
|
|
443
|
-
{
|
|
444
|
-
tokenIn: { type: "address", required: true, description: "" },
|
|
445
|
-
tokenOut: { type: "string", required: true, description: "" },
|
|
446
|
-
amountHuman: { type: "string", required: true, description: "" },
|
|
447
|
-
slippagePercent: { type: "number", required: true, description: "" }
|
|
448
|
-
},
|
|
449
|
-
["keyGen", "purposeText", "useCustomGas", "chainId", "rpcUrl", "executorAddress", "chainDetail"]
|
|
450
|
-
)
|
|
451
|
-
},
|
|
452
|
-
outputSchema: multisignOutputSchema
|
|
453
|
-
}
|
|
1004
|
+
inputZod: mcpCurveDaoBuildSwapMultisignInputSchema,
|
|
1005
|
+
outputZod: multisignOutputSchema
|
|
1006
|
+
})
|
|
1007
|
+
];
|
|
1008
|
+
var MCP_TOOL_DEFINITIONS = [
|
|
1009
|
+
...CORE_MCP_TOOL_DEFINITIONS,
|
|
1010
|
+
...MCP_PROTOCOL_TOOL_DEFINITIONS
|
|
454
1011
|
];
|
|
1012
|
+
function buildToolSchemaMap(kind) {
|
|
1013
|
+
const out = {};
|
|
1014
|
+
for (const tool of MCP_TOOL_DEFINITIONS) {
|
|
1015
|
+
out[tool.name] = kind === "input" ? tool.inputZod : tool.outputZod;
|
|
1016
|
+
}
|
|
1017
|
+
return out;
|
|
1018
|
+
}
|
|
1019
|
+
var MCP_TOOL_INPUT_SCHEMAS = buildToolSchemaMap("input");
|
|
1020
|
+
var MCP_TOOL_OUTPUT_SCHEMAS = buildToolSchemaMap("output");
|
|
455
1021
|
function getMcpToolDefinitions() {
|
|
456
1022
|
return MCP_TOOL_DEFINITIONS;
|
|
457
1023
|
}
|
|
458
1024
|
function getMcpToolByName(name) {
|
|
459
1025
|
return MCP_TOOL_DEFINITIONS.find((t) => t.name === name);
|
|
460
1026
|
}
|
|
1027
|
+
function getMcpToolInputSchema(name) {
|
|
1028
|
+
const schema = MCP_TOOL_INPUT_SCHEMAS[name];
|
|
1029
|
+
if (!schema) throw new Error(`Unknown MCP tool: ${name}`);
|
|
1030
|
+
return schema;
|
|
1031
|
+
}
|
|
1032
|
+
function getMcpToolOutputSchema(name) {
|
|
1033
|
+
const schema = MCP_TOOL_OUTPUT_SCHEMAS[name];
|
|
1034
|
+
if (!schema) throw new Error(`Unknown MCP tool: ${name}`);
|
|
1035
|
+
return schema;
|
|
1036
|
+
}
|
|
1037
|
+
function parseMcpToolInput(name, data) {
|
|
1038
|
+
return getMcpToolInputSchema(name).parse(data);
|
|
1039
|
+
}
|
|
1040
|
+
function parseMcpToolOutput(name, data) {
|
|
1041
|
+
return getMcpToolOutputSchema(name).parse(data);
|
|
1042
|
+
}
|
|
461
1043
|
function getAgentCatalogForMcp() {
|
|
462
1044
|
return {
|
|
463
1045
|
tools: MCP_TOOL_DEFINITIONS,
|
|
@@ -465,6 +1047,9 @@ function getAgentCatalogForMcp() {
|
|
|
465
1047
|
commonParams: EVM_COMMON_PARAM_DOCS,
|
|
466
1048
|
multisignOutput: MULTISIGN_OUTPUT_DOC,
|
|
467
1049
|
managementSig: MANAGEMENT_SIG_DOC,
|
|
1050
|
+
/** Zod schemas for MCP tool I/O — source of truth for continuum-mcp-server validation. */
|
|
1051
|
+
inputSchemas: MCP_TOOL_INPUT_SCHEMAS,
|
|
1052
|
+
outputSchemas: MCP_TOOL_OUTPUT_SCHEMAS,
|
|
468
1053
|
workflow: {
|
|
469
1054
|
evmSwapTypical: [
|
|
470
1055
|
"1. Quote (protocol-specific API if needed)",
|
|
@@ -478,15 +1063,606 @@ function getAgentCatalogForMcp() {
|
|
|
478
1063
|
"2. GET /getPublicMgtKeyNonce or /getNodeMgtKeyNonce \u2192 nonce",
|
|
479
1064
|
"3. buildManagementPostBody(nonce, nodeKey, { \u2026endpoint fields })",
|
|
480
1065
|
"4. messageToSignManagementBody(body) \u2192 sign \u2192 withManagementClientSig(body, sig)",
|
|
481
|
-
"5. POST management route with signed body"
|
|
1066
|
+
"5. POST management route with signed body (no signedMessage field except configUpdateImplement opaque line)"
|
|
1067
|
+
],
|
|
1068
|
+
agentMultisignTypical: [
|
|
1069
|
+
"1. load_defi_protocol for the target protocol",
|
|
1070
|
+
"2. get_defi_protocol_supported_chains / get_token_registry to pick chainId and tokens",
|
|
1071
|
+
"3. MCP build_* tool with keyGenId + chainId \u2192 { requestId }",
|
|
1072
|
+
"4. Base MCP: wait_for_sign_request_ready \u2192 sign_request_agree \u2192 trigger_sign_result \u2192 broadcast_sign_result"
|
|
482
1073
|
]
|
|
483
1074
|
}
|
|
484
1075
|
};
|
|
485
1076
|
}
|
|
1077
|
+
getAddress(
|
|
1078
|
+
"0xae7ab96520DE3A18E5e111B5EaAb095312D7fE84"
|
|
1079
|
+
);
|
|
1080
|
+
getAddress(
|
|
1081
|
+
"0x7f39C581F595B853cBbF37C12FfeeA971C5a5bEa"
|
|
1082
|
+
);
|
|
1083
|
+
getAddress("0x889edC2eDab5f40e902b864aD4d7AdE8E412F9B1");
|
|
1084
|
+
var LIDO_ETHEREUM_MAINNET_CHAIN_ID = 1;
|
|
1085
|
+
|
|
1086
|
+
// src/protocols/evm/lido/index.ts
|
|
1087
|
+
var LIDO_PROTOCOL_ID = "lido";
|
|
1088
|
+
var lidoProtocolModule = {
|
|
1089
|
+
id: LIDO_PROTOCOL_ID,
|
|
1090
|
+
chainCategory: "evm",
|
|
1091
|
+
isChainSupported(ctx) {
|
|
1092
|
+
if (ctx.chainCategory !== "evm") return false;
|
|
1093
|
+
return Number(ctx.chainId) === LIDO_ETHEREUM_MAINNET_CHAIN_ID;
|
|
1094
|
+
},
|
|
1095
|
+
isTokenSupported(token) {
|
|
1096
|
+
return token.category === "evm" && (token.kind === "native" || token.kind === "erc20");
|
|
1097
|
+
},
|
|
1098
|
+
actions: [
|
|
1099
|
+
{ id: "lido.submit", protocolId: LIDO_PROTOCOL_ID, chainCategory: "evm", description: "Stake ETH via Lido submit()", commonParams: ["keyGen", "purposeText", "useCustomGas"], params: { valueWei: { type: "string", required: true, description: "ETH to stake (wei string)" } } },
|
|
1100
|
+
{ id: "lido.request-withdrawals", protocolId: LIDO_PROTOCOL_ID, chainCategory: "evm", description: "Queue stETH withdrawal", commonParams: ["keyGen", "purposeText", "useCustomGas"], params: {} },
|
|
1101
|
+
{ id: "lido.claim-withdrawal", protocolId: LIDO_PROTOCOL_ID, chainCategory: "evm", description: "Claim finalized withdrawal", commonParams: ["keyGen", "purposeText", "useCustomGas"], params: {} },
|
|
1102
|
+
{ id: "lido.wrap-steth", protocolId: LIDO_PROTOCOL_ID, chainCategory: "evm", description: "Wrap stETH to wstETH", commonParams: ["keyGen", "purposeText", "useCustomGas"], params: {} },
|
|
1103
|
+
{ id: "lido.unwrap-wsteth", protocolId: LIDO_PROTOCOL_ID, chainCategory: "evm", description: "Unwrap wstETH to stETH", commonParams: ["keyGen", "purposeText", "useCustomGas"], params: {} }
|
|
1104
|
+
]
|
|
1105
|
+
};
|
|
1106
|
+
registerProtocolModule(lidoProtocolModule);
|
|
1107
|
+
var USDE_ETHEREUM_MAINNET = "0x4c9edd5852cd905f086c759e8383e09bff1e68b3";
|
|
1108
|
+
var SUSDE_ETHEREUM_MAINNET = "0x9d39a5de30e57443bff2a8307a4256c8797a3497";
|
|
1109
|
+
var USDE_MOST_L2S = "0x5d3a1Ff2b6BAb83b63cd9AD0787074081a52ef34";
|
|
1110
|
+
var USDE_ZKSYNC_ERA = "0x39Fe7a0DACcE31Bd90418e3e659fb0b5f0B3Db0d";
|
|
1111
|
+
var L2_SAME_ADDRESS_CHAIN_IDS = /* @__PURE__ */ new Set([
|
|
1112
|
+
42161,
|
|
1113
|
+
// Arbitrum One
|
|
1114
|
+
10,
|
|
1115
|
+
// Optimism
|
|
1116
|
+
8453,
|
|
1117
|
+
// Base
|
|
1118
|
+
56,
|
|
1119
|
+
// BNB Chain
|
|
1120
|
+
59144,
|
|
1121
|
+
// Linea
|
|
1122
|
+
5e3,
|
|
1123
|
+
// Mantle
|
|
1124
|
+
81457,
|
|
1125
|
+
// Blast
|
|
1126
|
+
169,
|
|
1127
|
+
// Manta Pacific
|
|
1128
|
+
534352,
|
|
1129
|
+
// Scroll
|
|
1130
|
+
252,
|
|
1131
|
+
// Fraxtal
|
|
1132
|
+
34443,
|
|
1133
|
+
// Mode
|
|
1134
|
+
196,
|
|
1135
|
+
// X Layer
|
|
1136
|
+
1088,
|
|
1137
|
+
// Metis
|
|
1138
|
+
80084,
|
|
1139
|
+
// Berachain
|
|
1140
|
+
2222,
|
|
1141
|
+
// Kava
|
|
1142
|
+
2818,
|
|
1143
|
+
// Morph
|
|
1144
|
+
1923,
|
|
1145
|
+
// Swell
|
|
1146
|
+
48900
|
|
1147
|
+
// Zircuit
|
|
1148
|
+
]);
|
|
1149
|
+
var FALLBACK_NAME_BY_ID = {
|
|
1150
|
+
1: "Ethereum",
|
|
1151
|
+
42161: "Arbitrum One",
|
|
1152
|
+
10: "Optimism",
|
|
1153
|
+
8453: "Base",
|
|
1154
|
+
56: "BNB Chain",
|
|
1155
|
+
59144: "Linea",
|
|
1156
|
+
5e3: "Mantle",
|
|
1157
|
+
81457: "Blast",
|
|
1158
|
+
169: "Manta Pacific",
|
|
1159
|
+
534352: "Scroll",
|
|
1160
|
+
252: "Fraxtal",
|
|
1161
|
+
34443: "Mode",
|
|
1162
|
+
196: "X Layer",
|
|
1163
|
+
1088: "Metis",
|
|
1164
|
+
80084: "Berachain",
|
|
1165
|
+
2222: "Kava",
|
|
1166
|
+
2818: "Morph",
|
|
1167
|
+
1923: "Swell",
|
|
1168
|
+
48900: "Zircuit",
|
|
1169
|
+
324: "ZKSync Era"
|
|
1170
|
+
};
|
|
1171
|
+
function usdeTokenAddressOnEvmChain(chainId) {
|
|
1172
|
+
if (chainId === 1) return USDE_ETHEREUM_MAINNET;
|
|
1173
|
+
if (chainId === 324) return USDE_ZKSYNC_ERA;
|
|
1174
|
+
if (L2_SAME_ADDRESS_CHAIN_IDS.has(chainId)) return USDE_MOST_L2S;
|
|
1175
|
+
return null;
|
|
1176
|
+
}
|
|
1177
|
+
function listEthenaUsdeEvmNetworkRows() {
|
|
1178
|
+
const rows = [
|
|
1179
|
+
{ chainId: 1, label: FALLBACK_NAME_BY_ID[1], usde: USDE_ETHEREUM_MAINNET }
|
|
1180
|
+
];
|
|
1181
|
+
const l2 = [...L2_SAME_ADDRESS_CHAIN_IDS].sort((a, b) => a - b);
|
|
1182
|
+
for (const id of l2) {
|
|
1183
|
+
rows.push({
|
|
1184
|
+
chainId: id,
|
|
1185
|
+
label: FALLBACK_NAME_BY_ID[id] ?? `Chain ${id}`,
|
|
1186
|
+
usde: USDE_MOST_L2S
|
|
1187
|
+
});
|
|
1188
|
+
}
|
|
1189
|
+
rows.push({ chainId: 324, label: FALLBACK_NAME_BY_ID[324], usde: USDE_ZKSYNC_ERA });
|
|
1190
|
+
return rows.sort((a, b) => {
|
|
1191
|
+
if (a.chainId === 1) return -1;
|
|
1192
|
+
if (b.chainId === 1) return 1;
|
|
1193
|
+
return a.chainId - b.chainId;
|
|
1194
|
+
});
|
|
1195
|
+
}
|
|
1196
|
+
function isEvmChainInEthenaUsdeList(chainId) {
|
|
1197
|
+
return usdeTokenAddressOnEvmChain(chainId) != null;
|
|
1198
|
+
}
|
|
1199
|
+
|
|
1200
|
+
// src/protocols/evm/ethena/index.ts
|
|
1201
|
+
var ETHENA_PROTOCOL_ID = "ethena";
|
|
1202
|
+
var ethenaProtocolModule = {
|
|
1203
|
+
id: ETHENA_PROTOCOL_ID,
|
|
1204
|
+
chainCategory: "evm",
|
|
1205
|
+
isChainSupported(ctx) {
|
|
1206
|
+
if (ctx.chainCategory !== "evm") return false;
|
|
1207
|
+
const n = typeof ctx.chainId === "number" ? ctx.chainId : Number.parseInt(String(ctx.chainId), 10);
|
|
1208
|
+
return isEvmChainInEthenaUsdeList(n);
|
|
1209
|
+
},
|
|
1210
|
+
isTokenSupported(token) {
|
|
1211
|
+
return token.category === "evm" && token.kind === "erc20";
|
|
1212
|
+
},
|
|
1213
|
+
actions: [
|
|
1214
|
+
{ id: "ethena.stake-usde", protocolId: ETHENA_PROTOCOL_ID, chainCategory: "evm", description: "Stake USDe \u2192 sUSDe", commonParams: ["keyGen", "purposeText", "useCustomGas"], params: { amountHuman: { type: "string", required: true, description: "USDe amount" } } },
|
|
1215
|
+
{ id: "ethena.redeem-susde", protocolId: ETHENA_PROTOCOL_ID, chainCategory: "evm", description: "Redeem sUSDe \u2192 USDe (no cooldown)", commonParams: ["keyGen", "purposeText", "useCustomGas"], params: {} },
|
|
1216
|
+
{ id: "ethena.cooldown-shares", protocolId: ETHENA_PROTOCOL_ID, chainCategory: "evm", description: "Start sUSDe cooldown", commonParams: ["keyGen", "purposeText", "useCustomGas"], params: {} },
|
|
1217
|
+
{ id: "ethena.claim-unstake", protocolId: ETHENA_PROTOCOL_ID, chainCategory: "evm", description: "Claim after cooldown", commonParams: ["keyGen", "purposeText", "useCustomGas"], params: {} }
|
|
1218
|
+
]
|
|
1219
|
+
};
|
|
1220
|
+
registerProtocolModule(ethenaProtocolModule);
|
|
1221
|
+
|
|
1222
|
+
// src/protocols/evm/maple/constants.ts
|
|
1223
|
+
function isMapleSyrupSupportedChain(chainId) {
|
|
1224
|
+
return chainId === 1 || chainId === 11155111;
|
|
1225
|
+
}
|
|
1226
|
+
|
|
1227
|
+
// src/protocols/evm/maple/index.ts
|
|
1228
|
+
var MAPLE_PROTOCOL_ID = "maple-syrup";
|
|
1229
|
+
var mapleProtocolModule = {
|
|
1230
|
+
id: MAPLE_PROTOCOL_ID,
|
|
1231
|
+
chainCategory: "evm",
|
|
1232
|
+
isChainSupported(ctx) {
|
|
1233
|
+
if (ctx.chainCategory !== "evm") return false;
|
|
1234
|
+
const n = typeof ctx.chainId === "number" ? ctx.chainId : Number.parseInt(String(ctx.chainId), 10);
|
|
1235
|
+
return isMapleSyrupSupportedChain(n);
|
|
1236
|
+
},
|
|
1237
|
+
isTokenSupported(token) {
|
|
1238
|
+
return token.category === "evm" && token.kind === "erc20";
|
|
1239
|
+
},
|
|
1240
|
+
actions: [
|
|
1241
|
+
{ id: "maple-syrup.deposit", protocolId: MAPLE_PROTOCOL_ID, chainCategory: "evm", description: "Deposit into Maple Syrup pool", commonParams: ["keyGen", "purposeText", "useCustomGas"], params: {} },
|
|
1242
|
+
{ id: "maple-syrup.request-redeem", protocolId: MAPLE_PROTOCOL_ID, chainCategory: "evm", description: "Request redeem from pool", commonParams: ["keyGen", "purposeText", "useCustomGas"], params: {} }
|
|
1243
|
+
]
|
|
1244
|
+
};
|
|
1245
|
+
registerProtocolModule(mapleProtocolModule);
|
|
1246
|
+
|
|
1247
|
+
// src/protocols/evm/sky/mainnet.ts
|
|
1248
|
+
var SKY_ETHEREUM_MAINNET_CHAIN_ID = 1;
|
|
1249
|
+
|
|
1250
|
+
// src/protocols/evm/sky/index.ts
|
|
1251
|
+
var SKY_PROTOCOL_ID = "sky";
|
|
1252
|
+
var skyProtocolModule = {
|
|
1253
|
+
id: SKY_PROTOCOL_ID,
|
|
1254
|
+
chainCategory: "evm",
|
|
1255
|
+
isChainSupported(ctx) {
|
|
1256
|
+
if (ctx.chainCategory !== "evm") return false;
|
|
1257
|
+
return Number(ctx.chainId) === SKY_ETHEREUM_MAINNET_CHAIN_ID;
|
|
1258
|
+
},
|
|
1259
|
+
isTokenSupported(token) {
|
|
1260
|
+
return token.category === "evm" && token.kind === "erc20";
|
|
1261
|
+
},
|
|
1262
|
+
actions: [
|
|
1263
|
+
{ id: "sky.lockstake-stake", protocolId: SKY_PROTOCOL_ID, chainCategory: "evm", description: "Open Lockstake position", commonParams: ["keyGen", "purposeText", "useCustomGas"], params: {} },
|
|
1264
|
+
{ id: "sky.lockstake-draw", protocolId: SKY_PROTOCOL_ID, chainCategory: "evm", description: "Borrow USDS from Lockstake", commonParams: ["keyGen", "purposeText", "useCustomGas"], params: {} },
|
|
1265
|
+
{ id: "sky.lockstake-wipe", protocolId: SKY_PROTOCOL_ID, chainCategory: "evm", description: "Repay Lockstake debt", commonParams: ["keyGen", "purposeText", "useCustomGas"], params: {} },
|
|
1266
|
+
{ id: "sky.lockstake-close", protocolId: SKY_PROTOCOL_ID, chainCategory: "evm", description: "Close Lockstake position", commonParams: ["keyGen", "purposeText", "useCustomGas"], params: {} },
|
|
1267
|
+
{ id: "sky.susds-deposit", protocolId: SKY_PROTOCOL_ID, chainCategory: "evm", description: "Deposit USDS into sUSDS vault", commonParams: ["keyGen", "purposeText", "useCustomGas"], params: {} },
|
|
1268
|
+
{ id: "sky.susds-redeem", protocolId: SKY_PROTOCOL_ID, chainCategory: "evm", description: "Redeem sUSDS to USDS", commonParams: ["keyGen", "purposeText", "useCustomGas"], params: {} }
|
|
1269
|
+
]
|
|
1270
|
+
};
|
|
1271
|
+
registerProtocolModule(skyProtocolModule);
|
|
1272
|
+
var AAVE_V4_GRAPHQL_URL = "https://api.v4.aave.com/graphql";
|
|
1273
|
+
async function aaveV4Gql(query, variables) {
|
|
1274
|
+
const r = await fetch(AAVE_V4_GRAPHQL_URL, {
|
|
1275
|
+
method: "POST",
|
|
1276
|
+
headers: { "content-type": "application/json" },
|
|
1277
|
+
body: JSON.stringify({ query, variables: variables ?? {} })
|
|
1278
|
+
});
|
|
1279
|
+
if (!r.ok) {
|
|
1280
|
+
const t = await r.text().catch(() => "");
|
|
1281
|
+
throw new Error(t ? `Aave V4 API HTTP ${r.status}: ${t.slice(0, 200)}` : `Aave V4 API HTTP ${r.status}`);
|
|
1282
|
+
}
|
|
1283
|
+
const j = await r.json();
|
|
1284
|
+
if (j.errors?.length) {
|
|
1285
|
+
const msg = j.errors.map((e) => e.message ?? "Unknown").join("; ");
|
|
1286
|
+
throw new Error(msg);
|
|
1287
|
+
}
|
|
1288
|
+
if (j.data == null) {
|
|
1289
|
+
throw new Error("Aave V4 API: empty response");
|
|
1290
|
+
}
|
|
1291
|
+
return j.data;
|
|
1292
|
+
}
|
|
1293
|
+
async function fetchAaveV4Chains() {
|
|
1294
|
+
const d = await aaveV4Gql(`
|
|
1295
|
+
query C($c: ChainsRequest!) { chains(request: $c) { chainId name nativeWrappedToken } }
|
|
1296
|
+
`, { c: { query: { filter: "ALL" } } });
|
|
1297
|
+
return d.chains ?? [];
|
|
1298
|
+
}
|
|
1299
|
+
async function loadAaveV4SupportedChainIdsFromV4Api() {
|
|
1300
|
+
const rows = await fetchAaveV4Chains();
|
|
1301
|
+
const s = /* @__PURE__ */ new Set();
|
|
1302
|
+
for (const c of rows) s.add(c.chainId);
|
|
1303
|
+
return s;
|
|
1304
|
+
}
|
|
1305
|
+
var RESERVES_ADDRESS_FRAGMENT = `
|
|
1306
|
+
asset { underlying { address } }
|
|
1307
|
+
`;
|
|
1308
|
+
async function fetchAaveV4NativeWrappedToken(chainId) {
|
|
1309
|
+
const all = await fetchAaveV4Chains();
|
|
1310
|
+
const c = all.find((x) => x.chainId === chainId);
|
|
1311
|
+
const t = (c?.nativeWrappedToken ?? "").trim();
|
|
1312
|
+
if (t && isAddress(t)) return getAddress(t);
|
|
1313
|
+
return null;
|
|
1314
|
+
}
|
|
1315
|
+
async function fetchAaveV4SupportedUnderlyingAddressSet(chainId) {
|
|
1316
|
+
const d = await aaveV4Gql(
|
|
1317
|
+
`
|
|
1318
|
+
query A($r: ReservesRequest!) { reserves(request: $r) { ${RESERVES_ADDRESS_FRAGMENT} } }
|
|
1319
|
+
`,
|
|
1320
|
+
{
|
|
1321
|
+
r: {
|
|
1322
|
+
query: { chainIds: [chainId] },
|
|
1323
|
+
filter: "ALL",
|
|
1324
|
+
orderBy: { supplyApy: "DESC" }
|
|
1325
|
+
}
|
|
1326
|
+
}
|
|
1327
|
+
);
|
|
1328
|
+
const s = /* @__PURE__ */ new Set();
|
|
1329
|
+
for (const r of d.reserves ?? []) {
|
|
1330
|
+
const a = (r.asset?.underlying?.address ?? "").trim();
|
|
1331
|
+
if (a && isAddress(a)) s.add(a.toLowerCase());
|
|
1332
|
+
}
|
|
1333
|
+
return s;
|
|
1334
|
+
}
|
|
1335
|
+
var aaveV4ChainTokenCache = /* @__PURE__ */ new Map();
|
|
1336
|
+
function ensureAaveV4ChainTokenCache(chainId) {
|
|
1337
|
+
const hit = aaveV4ChainTokenCache.get(chainId);
|
|
1338
|
+
if (hit) return hit;
|
|
1339
|
+
const p = (async () => {
|
|
1340
|
+
const [nativeWrapped, supportedUnderlying] = await Promise.all([
|
|
1341
|
+
fetchAaveV4NativeWrappedToken(chainId),
|
|
1342
|
+
fetchAaveV4SupportedUnderlyingAddressSet(chainId)
|
|
1343
|
+
]);
|
|
1344
|
+
return { supportedUnderlying, nativeWrapped };
|
|
1345
|
+
})();
|
|
1346
|
+
aaveV4ChainTokenCache.set(chainId, p);
|
|
1347
|
+
return p;
|
|
1348
|
+
}
|
|
1349
|
+
|
|
1350
|
+
// src/protocols/evm/aave-v4/index.ts
|
|
1351
|
+
var AAVE_V4_PROTOCOL_ID = "aave-v4";
|
|
1352
|
+
var aaveV4ProtocolModule = {
|
|
1353
|
+
id: AAVE_V4_PROTOCOL_ID,
|
|
1354
|
+
chainCategory: "evm",
|
|
1355
|
+
isChainSupported(ctx) {
|
|
1356
|
+
return ctx.chainCategory === "evm";
|
|
1357
|
+
},
|
|
1358
|
+
isTokenSupported(token) {
|
|
1359
|
+
return token.category === "evm" && (token.kind === "native" || token.kind === "erc20");
|
|
1360
|
+
},
|
|
1361
|
+
actions: [
|
|
1362
|
+
{ id: "aave-v4.deposit", protocolId: AAVE_V4_PROTOCOL_ID, chainCategory: "evm", description: "Supply to Aave v4 Spoke", commonParams: ["keyGen", "purposeText", "useCustomGas"], params: {} },
|
|
1363
|
+
{ id: "aave-v4.withdraw", protocolId: AAVE_V4_PROTOCOL_ID, chainCategory: "evm", description: "Withdraw from Spoke", commonParams: ["keyGen", "purposeText", "useCustomGas"], params: {} },
|
|
1364
|
+
{ id: "aave-v4.borrow", protocolId: AAVE_V4_PROTOCOL_ID, chainCategory: "evm", description: "Borrow from Spoke", commonParams: ["keyGen", "purposeText", "useCustomGas"], params: {} },
|
|
1365
|
+
{ id: "aave-v4.repay", protocolId: AAVE_V4_PROTOCOL_ID, chainCategory: "evm", description: "Repay Spoke debt", commonParams: ["keyGen", "purposeText", "useCustomGas"], params: {} }
|
|
1366
|
+
]
|
|
1367
|
+
};
|
|
1368
|
+
registerProtocolModule(aaveV4ProtocolModule);
|
|
1369
|
+
|
|
1370
|
+
// src/protocols/evm/euler-v2/index.ts
|
|
1371
|
+
var EULER_V2_PROTOCOL_ID = "euler-v2";
|
|
1372
|
+
var eulerV2ProtocolModule = {
|
|
1373
|
+
id: EULER_V2_PROTOCOL_ID,
|
|
1374
|
+
chainCategory: "evm",
|
|
1375
|
+
isChainSupported(ctx) {
|
|
1376
|
+
return ctx.chainCategory === "evm";
|
|
1377
|
+
},
|
|
1378
|
+
isTokenSupported(token) {
|
|
1379
|
+
return token.category === "evm" && (token.kind === "native" || token.kind === "erc20");
|
|
1380
|
+
},
|
|
1381
|
+
actions: [
|
|
1382
|
+
{ id: "euler-v2.isolated-lend", protocolId: EULER_V2_PROTOCOL_ID, chainCategory: "evm", description: "Deposit into Euler vault", commonParams: ["keyGen", "purposeText", "useCustomGas"], params: {} },
|
|
1383
|
+
{ id: "euler-v2.isolated-borrow", protocolId: EULER_V2_PROTOCOL_ID, chainCategory: "evm", description: "Borrow from Euler vault", commonParams: ["keyGen", "purposeText", "useCustomGas"], params: {} },
|
|
1384
|
+
{ id: "euler-v2.vault-withdraw", protocolId: EULER_V2_PROTOCOL_ID, chainCategory: "evm", description: "Withdraw from Euler vault", commonParams: ["keyGen", "purposeText", "useCustomGas"], params: {} },
|
|
1385
|
+
{ id: "euler-v2.borrow-repay", protocolId: EULER_V2_PROTOCOL_ID, chainCategory: "evm", description: "Repay Euler borrow", commonParams: ["keyGen", "purposeText", "useCustomGas"], params: {} },
|
|
1386
|
+
{ id: "euler-v2.collateral-deposit", protocolId: EULER_V2_PROTOCOL_ID, chainCategory: "evm", description: "Deposit borrow collateral", commonParams: ["keyGen", "purposeText", "useCustomGas"], params: {} },
|
|
1387
|
+
{ id: "euler-v2.collateral-withdraw", protocolId: EULER_V2_PROTOCOL_ID, chainCategory: "evm", description: "Withdraw borrow collateral", commonParams: ["keyGen", "purposeText", "useCustomGas"], params: {} }
|
|
1388
|
+
]
|
|
1389
|
+
};
|
|
1390
|
+
registerProtocolModule(eulerV2ProtocolModule);
|
|
1391
|
+
var skillsDir = join(dirname(fileURLToPath(import.meta.url)), "skills");
|
|
1392
|
+
var SKILL_PROTOCOL_IDS = [
|
|
1393
|
+
"aave-v4",
|
|
1394
|
+
"lido",
|
|
1395
|
+
"uniswap-v4",
|
|
1396
|
+
"curve-dao",
|
|
1397
|
+
"ethena",
|
|
1398
|
+
"euler-v2",
|
|
1399
|
+
"maple-syrup",
|
|
1400
|
+
"sky"
|
|
1401
|
+
];
|
|
1402
|
+
function getToolsForProtocol(protocolId) {
|
|
1403
|
+
return MCP_TOOL_DEFINITIONS.filter((t) => t.protocolId === protocolId);
|
|
1404
|
+
}
|
|
1405
|
+
function getProtocolSkill(protocolId) {
|
|
1406
|
+
if (!SKILL_PROTOCOL_IDS.includes(protocolId)) {
|
|
1407
|
+
return void 0;
|
|
1408
|
+
}
|
|
1409
|
+
try {
|
|
1410
|
+
return readFileSync(join(skillsDir, protocolId, "SKILL.md"), "utf8");
|
|
1411
|
+
} catch {
|
|
1412
|
+
return void 0;
|
|
1413
|
+
}
|
|
1414
|
+
}
|
|
1415
|
+
function listProtocolsWithSkills() {
|
|
1416
|
+
return [...SKILL_PROTOCOL_IDS];
|
|
1417
|
+
}
|
|
1418
|
+
function getProtocolDiscoverySummary(protocolId) {
|
|
1419
|
+
const mod = getProtocolModules().find((p) => p.id === protocolId);
|
|
1420
|
+
if (!mod) return void 0;
|
|
1421
|
+
return {
|
|
1422
|
+
protocolId: mod.id,
|
|
1423
|
+
chainCategory: mod.chainCategory,
|
|
1424
|
+
actions: mod.actions.map((a) => ({ id: a.id, description: a.description })),
|
|
1425
|
+
tools: getToolsForProtocol(protocolId).map((t) => ({
|
|
1426
|
+
name: t.name,
|
|
1427
|
+
actionId: t.actionId,
|
|
1428
|
+
description: t.description,
|
|
1429
|
+
prerequisites: t.prerequisites,
|
|
1430
|
+
followUp: t.followUp
|
|
1431
|
+
}))
|
|
1432
|
+
};
|
|
1433
|
+
}
|
|
1434
|
+
var EULER_V2_SUBGRAPH_CHAIN_IDS = [
|
|
1435
|
+
1,
|
|
1436
|
+
8453,
|
|
1437
|
+
42161,
|
|
1438
|
+
10,
|
|
1439
|
+
137,
|
|
1440
|
+
56,
|
|
1441
|
+
43114,
|
|
1442
|
+
100,
|
|
1443
|
+
59144,
|
|
1444
|
+
146,
|
|
1445
|
+
1923,
|
|
1446
|
+
130
|
|
1447
|
+
];
|
|
1448
|
+
function advisor(protocolId, tokenFilter, impl) {
|
|
1449
|
+
return { protocolId, tokenFilter, ...impl };
|
|
1450
|
+
}
|
|
1451
|
+
var PROTOCOL_SUPPORT_ADVISORS = {
|
|
1452
|
+
"aave-v4": advisor("aave-v4", "api_underlyings", {
|
|
1453
|
+
async supportedChainIds() {
|
|
1454
|
+
const set = await loadAaveV4SupportedChainIdsFromV4Api();
|
|
1455
|
+
return [...set].sort((a, b) => a - b);
|
|
1456
|
+
},
|
|
1457
|
+
async supportedTokens(chainId) {
|
|
1458
|
+
const cache = await ensureAaveV4ChainTokenCache(chainId);
|
|
1459
|
+
const tokens = [...cache.supportedUnderlying].map((address) => ({
|
|
1460
|
+
address,
|
|
1461
|
+
roles: ["underlying"]
|
|
1462
|
+
}));
|
|
1463
|
+
if (cache.nativeWrapped) {
|
|
1464
|
+
tokens.unshift({
|
|
1465
|
+
address: cache.nativeWrapped,
|
|
1466
|
+
symbol: "WETH",
|
|
1467
|
+
roles: ["native_wrapped"]
|
|
1468
|
+
});
|
|
1469
|
+
}
|
|
1470
|
+
return {
|
|
1471
|
+
tokens,
|
|
1472
|
+
nativeWrapped: cache.nativeWrapped ?? void 0,
|
|
1473
|
+
notes: "Native ETH deposits use wrapped native token address from Aave v4 API."
|
|
1474
|
+
};
|
|
1475
|
+
},
|
|
1476
|
+
async isTokenSupported(chainId, address) {
|
|
1477
|
+
const cache = await ensureAaveV4ChainTokenCache(chainId);
|
|
1478
|
+
let normalized;
|
|
1479
|
+
try {
|
|
1480
|
+
normalized = getAddress(address).toLowerCase();
|
|
1481
|
+
} catch {
|
|
1482
|
+
return false;
|
|
1483
|
+
}
|
|
1484
|
+
if (cache.nativeWrapped && getAddress(cache.nativeWrapped).toLowerCase() === normalized) {
|
|
1485
|
+
return true;
|
|
1486
|
+
}
|
|
1487
|
+
return cache.supportedUnderlying.has(normalized);
|
|
1488
|
+
}
|
|
1489
|
+
}),
|
|
1490
|
+
"uniswap-v4": advisor("uniswap-v4", "any_erc20_on_chain", {
|
|
1491
|
+
async supportedChainIds() {
|
|
1492
|
+
const ids = [];
|
|
1493
|
+
for (const id of [
|
|
1494
|
+
1,
|
|
1495
|
+
5,
|
|
1496
|
+
11155111,
|
|
1497
|
+
137,
|
|
1498
|
+
80001,
|
|
1499
|
+
10,
|
|
1500
|
+
420,
|
|
1501
|
+
42161,
|
|
1502
|
+
421613,
|
|
1503
|
+
42220,
|
|
1504
|
+
44787,
|
|
1505
|
+
56,
|
|
1506
|
+
43114,
|
|
1507
|
+
84531,
|
|
1508
|
+
8453,
|
|
1509
|
+
81457,
|
|
1510
|
+
7777777,
|
|
1511
|
+
324,
|
|
1512
|
+
480,
|
|
1513
|
+
1301,
|
|
1514
|
+
130,
|
|
1515
|
+
10143,
|
|
1516
|
+
84532,
|
|
1517
|
+
1868,
|
|
1518
|
+
143,
|
|
1519
|
+
59144,
|
|
1520
|
+
4217,
|
|
1521
|
+
196
|
|
1522
|
+
]) {
|
|
1523
|
+
if (isUniswapV4ChainSupported(id)) ids.push(id);
|
|
1524
|
+
}
|
|
1525
|
+
return ids;
|
|
1526
|
+
},
|
|
1527
|
+
async supportedTokens() {
|
|
1528
|
+
return {
|
|
1529
|
+
tokens: [],
|
|
1530
|
+
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."
|
|
1531
|
+
};
|
|
1532
|
+
}
|
|
1533
|
+
}),
|
|
1534
|
+
"curve-dao": advisor("curve-dao", "pool_graph", {
|
|
1535
|
+
async supportedChainIds() {
|
|
1536
|
+
return [1, 10, 56, 100, 137, 146, 196, 250, 252, 324, 999, 1284, 2222, 5e3, 8453, 42161, 42220, 43114, 1313161554];
|
|
1537
|
+
},
|
|
1538
|
+
async supportedTokens(chainId, ctx) {
|
|
1539
|
+
if (!isCurveApiChainSupported(chainId)) {
|
|
1540
|
+
return { tokens: [], notes: "Chain not supported by Curve SDK network constants." };
|
|
1541
|
+
}
|
|
1542
|
+
const rpcUrl = ctx?.rpcUrl?.trim();
|
|
1543
|
+
if (!rpcUrl) {
|
|
1544
|
+
return {
|
|
1545
|
+
tokens: [],
|
|
1546
|
+
notes: "Provide rpcUrl (from get_chain_registry) to load Curve pool graph token list."
|
|
1547
|
+
};
|
|
1548
|
+
}
|
|
1549
|
+
const session = await loadFullCurveSessionForRpc(rpcUrl);
|
|
1550
|
+
if (!session?.swappableNodeKeys?.size) {
|
|
1551
|
+
return { tokens: [], notes: "Curve session returned no swappable tokens for this RPC." };
|
|
1552
|
+
}
|
|
1553
|
+
return {
|
|
1554
|
+
tokens: [...session.swappableNodeKeys].map((key) => {
|
|
1555
|
+
const address = key.startsWith("0x") ? key : key.split(":")[0] ?? key;
|
|
1556
|
+
return { address, roles: ["swappable"] };
|
|
1557
|
+
})
|
|
1558
|
+
};
|
|
1559
|
+
}
|
|
1560
|
+
}),
|
|
1561
|
+
lido: advisor("lido", "mainnet_only", {
|
|
1562
|
+
async supportedChainIds() {
|
|
1563
|
+
return [LIDO_ETHEREUM_MAINNET_CHAIN_ID];
|
|
1564
|
+
},
|
|
1565
|
+
async supportedTokens() {
|
|
1566
|
+
return {
|
|
1567
|
+
tokens: [
|
|
1568
|
+
{ address: "0x0000000000000000000000000000000000000000", symbol: "ETH", roles: ["native", "stake"] },
|
|
1569
|
+
{ address: "0xae7ab96520DE3A18E5e111B5EaAb095312D7fE84", symbol: "stETH", roles: ["erc20"] },
|
|
1570
|
+
{ address: "0x7f39C581F595B853cBbF37C12FfeeA971C5a5bEa", symbol: "wstETH", roles: ["erc20"] }
|
|
1571
|
+
],
|
|
1572
|
+
notes: "Lido staking and withdrawals are Ethereum mainnet only."
|
|
1573
|
+
};
|
|
1574
|
+
}
|
|
1575
|
+
}),
|
|
1576
|
+
ethena: advisor("ethena", "minting_contract", {
|
|
1577
|
+
async supportedChainIds() {
|
|
1578
|
+
return listEthenaUsdeEvmNetworkRows().map((r) => r.chainId);
|
|
1579
|
+
},
|
|
1580
|
+
async supportedTokens(chainId) {
|
|
1581
|
+
if (chainId === 1) {
|
|
1582
|
+
return {
|
|
1583
|
+
tokens: [
|
|
1584
|
+
{ address: USDE_ETHEREUM_MAINNET, symbol: "USDe", roles: ["stake"] },
|
|
1585
|
+
{ address: SUSDE_ETHEREUM_MAINNET, symbol: "sUSDe", roles: ["vault"] }
|
|
1586
|
+
],
|
|
1587
|
+
notes: "Ethena stake/redeem UI actions are mainnet-only; USDe exists on other chains for transfers."
|
|
1588
|
+
};
|
|
1589
|
+
}
|
|
1590
|
+
if (isEvmChainInEthenaUsdeList(chainId)) {
|
|
1591
|
+
const row = listEthenaUsdeEvmNetworkRows().find((r) => r.chainId === chainId);
|
|
1592
|
+
return {
|
|
1593
|
+
tokens: row ? [{ address: row.usde, symbol: "USDe", roles: ["erc20"] }] : [],
|
|
1594
|
+
notes: "USDe on L2; staking MCP tools target mainnet only."
|
|
1595
|
+
};
|
|
1596
|
+
}
|
|
1597
|
+
return { tokens: [] };
|
|
1598
|
+
}
|
|
1599
|
+
}),
|
|
1600
|
+
"euler-v2": advisor("euler-v2", "subgraph_vaults", {
|
|
1601
|
+
async supportedChainIds() {
|
|
1602
|
+
return [...EULER_V2_SUBGRAPH_CHAIN_IDS];
|
|
1603
|
+
},
|
|
1604
|
+
async supportedTokens() {
|
|
1605
|
+
return {
|
|
1606
|
+
tokens: [],
|
|
1607
|
+
notes: "Euler vault/collateral assets vary by chain. Pass vault and asset addresses from Euler app or subgraph."
|
|
1608
|
+
};
|
|
1609
|
+
}
|
|
1610
|
+
}),
|
|
1611
|
+
[MAPLE_PROTOCOL_ID]: advisor(MAPLE_PROTOCOL_ID, "fixed_addresses", {
|
|
1612
|
+
async supportedChainIds() {
|
|
1613
|
+
return [1, 11155111];
|
|
1614
|
+
},
|
|
1615
|
+
async supportedTokens() {
|
|
1616
|
+
return {
|
|
1617
|
+
tokens: [],
|
|
1618
|
+
notes: "Maple Syrup pools are discovered via GraphQL; pass syrupRouter, pool, and asset from Maple UI."
|
|
1619
|
+
};
|
|
1620
|
+
}
|
|
1621
|
+
}),
|
|
1622
|
+
[SKY_PROTOCOL_ID]: advisor(SKY_PROTOCOL_ID, "fixed_addresses", {
|
|
1623
|
+
async supportedChainIds() {
|
|
1624
|
+
return [1];
|
|
1625
|
+
},
|
|
1626
|
+
async supportedTokens() {
|
|
1627
|
+
return {
|
|
1628
|
+
tokens: [],
|
|
1629
|
+
notes: "Sky Lockstake and sUSDS use fixed mainnet contract addresses in protocol builders."
|
|
1630
|
+
};
|
|
1631
|
+
}
|
|
1632
|
+
})
|
|
1633
|
+
};
|
|
1634
|
+
function getProtocolSupportAdvisor(protocolId) {
|
|
1635
|
+
return PROTOCOL_SUPPORT_ADVISORS[protocolId];
|
|
1636
|
+
}
|
|
1637
|
+
function listProtocolSupportAdvisorIds() {
|
|
1638
|
+
return Object.keys(PROTOCOL_SUPPORT_ADVISORS);
|
|
1639
|
+
}
|
|
1640
|
+
var mcpServerCommonInputSchema = z.object({
|
|
1641
|
+
keyGenId: z.string().min(1).describe("KeyGen id from fetch_key_gen_result / node preferred KeyGen"),
|
|
1642
|
+
chainId: z.number().int().positive().describe("EVM chain id; RPC and gas config resolved from chain registry"),
|
|
1643
|
+
purposeText: z.string().min(1).describe("Human-readable purpose for the sign request"),
|
|
1644
|
+
useCustomGas: z.boolean().optional().describe("Apply chain gas settings from registry when true")
|
|
1645
|
+
});
|
|
1646
|
+
function mcpServerMultisignInput(fields) {
|
|
1647
|
+
return mcpServerCommonInputSchema.extend(fields);
|
|
1648
|
+
}
|
|
1649
|
+
var mcpServerSubmitOutputSchema = z.object({
|
|
1650
|
+
requestId: z.string().min(1)
|
|
1651
|
+
}).describe("mpc-auth multiSignRequest id; continue with trigger_sign_result / broadcast_sign_result");
|
|
1652
|
+
var MCP_NON_SUBMIT_TOOL_NAMES = /* @__PURE__ */ new Set([
|
|
1653
|
+
"ctm_uniswap_v4_quote",
|
|
1654
|
+
"ctm_uniswap_v4_create_swap"
|
|
1655
|
+
]);
|
|
486
1656
|
|
|
487
1657
|
// src/agent/catalog.ts
|
|
488
1658
|
registerProtocolModule(uniswapV4ProtocolModule);
|
|
489
1659
|
registerProtocolModule(curveDaoProtocolModule);
|
|
1660
|
+
registerProtocolModule(lidoProtocolModule);
|
|
1661
|
+
registerProtocolModule(ethenaProtocolModule);
|
|
1662
|
+
registerProtocolModule(mapleProtocolModule);
|
|
1663
|
+
registerProtocolModule(skyProtocolModule);
|
|
1664
|
+
registerProtocolModule(aaveV4ProtocolModule);
|
|
1665
|
+
registerProtocolModule(eulerV2ProtocolModule);
|
|
490
1666
|
function getAgentCatalog() {
|
|
491
1667
|
return {
|
|
492
1668
|
protocols: getProtocolModules(),
|
|
@@ -497,11 +1673,17 @@ function getAgentCatalog() {
|
|
|
497
1673
|
},
|
|
498
1674
|
uniswapV4: uniswapV4ProtocolModule,
|
|
499
1675
|
curveDao: curveDaoProtocolModule,
|
|
1676
|
+
lido: lidoProtocolModule,
|
|
1677
|
+
ethena: ethenaProtocolModule,
|
|
1678
|
+
maple: mapleProtocolModule,
|
|
1679
|
+
sky: skyProtocolModule,
|
|
1680
|
+
aaveV4: aaveV4ProtocolModule,
|
|
1681
|
+
eulerV2: eulerV2ProtocolModule,
|
|
500
1682
|
/** Prefer getAgentCatalogForMcp() or getMcpToolDefinitions() for MCP servers. */
|
|
501
1683
|
mcp: getAgentCatalogForMcp()
|
|
502
1684
|
};
|
|
503
1685
|
}
|
|
504
1686
|
|
|
505
|
-
export { EVM_COMMON_PARAM_DOCS, MANAGEMENT_SIG_DOC, MCP_TOOL_DEFINITIONS, MULTISIGN_OUTPUT_DOC, getActionsByChainCategory, getAgentCatalog, getAgentCatalogForMcp, getMcpToolByName, getMcpToolDefinitions, getProtocolModules };
|
|
1687
|
+
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, 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 };
|
|
506
1688
|
//# sourceMappingURL=catalog.js.map
|
|
507
1689
|
//# sourceMappingURL=catalog.js.map
|