@continuumdao/ctm-mpc-defi 0.2.56 → 0.2.57
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/dist/agent/catalog.cjs +304 -134
- package/dist/agent/catalog.cjs.map +1 -1
- package/dist/agent/catalog.d.ts +162 -42
- package/dist/agent/catalog.js +304 -136
- package/dist/agent/catalog.js.map +1 -1
- package/dist/agent/skills/aave-v4/SKILL.md +26 -3
- package/dist/agent/skills/aerodrome/SKILL.md +3 -1
- package/dist/agent/skills/curve-dao/SKILL.md +2 -2
- package/dist/agent/skills/uniswap-v4/SKILL.md +2 -2
- package/dist/index.cjs +165 -19
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +166 -20
- package/dist/index.js.map +1 -1
- package/dist/protocols/evm/aave-v4/index.cjs +198 -15
- package/dist/protocols/evm/aave-v4/index.cjs.map +1 -1
- package/dist/protocols/evm/aave-v4/index.d.ts +62 -7
- package/dist/protocols/evm/aave-v4/index.js +189 -16
- package/dist/protocols/evm/aave-v4/index.js.map +1 -1
- package/dist/protocols/evm/aerodrome/index.cjs +152 -63
- package/dist/protocols/evm/aerodrome/index.cjs.map +1 -1
- package/dist/protocols/evm/aerodrome/index.d.ts +30 -58
- package/dist/protocols/evm/aerodrome/index.js +151 -64
- package/dist/protocols/evm/aerodrome/index.js.map +1 -1
- package/dist/protocols/evm/compound-v3/index.cjs +115 -2
- package/dist/protocols/evm/compound-v3/index.cjs.map +1 -1
- package/dist/protocols/evm/compound-v3/index.js +116 -3
- package/dist/protocols/evm/compound-v3/index.js.map +1 -1
- package/dist/protocols/evm/curve-dao/index.cjs +120 -5
- package/dist/protocols/evm/curve-dao/index.cjs.map +1 -1
- package/dist/protocols/evm/curve-dao/index.js +120 -5
- package/dist/protocols/evm/curve-dao/index.js.map +1 -1
- package/dist/protocols/evm/euler-v2/index.cjs +121 -6
- package/dist/protocols/evm/euler-v2/index.cjs.map +1 -1
- package/dist/protocols/evm/euler-v2/index.js +121 -6
- package/dist/protocols/evm/euler-v2/index.js.map +1 -1
- package/dist/protocols/evm/morpho/index.cjs +129 -57
- package/dist/protocols/evm/morpho/index.cjs.map +1 -1
- package/dist/protocols/evm/morpho/index.d.ts +2 -1
- package/dist/protocols/evm/morpho/index.js +129 -58
- package/dist/protocols/evm/morpho/index.js.map +1 -1
- package/dist/protocols/evm/pendle/index.cjs +129 -10
- package/dist/protocols/evm/pendle/index.cjs.map +1 -1
- package/dist/protocols/evm/pendle/index.js +129 -10
- package/dist/protocols/evm/pendle/index.js.map +1 -1
- package/dist/protocols/evm/uniswap-v4/index.cjs +164 -17
- package/dist/protocols/evm/uniswap-v4/index.cjs.map +1 -1
- package/dist/protocols/evm/uniswap-v4/index.js +165 -18
- package/dist/protocols/evm/uniswap-v4/index.js.map +1 -1
- package/package.json +1 -1
|
@@ -376,6 +376,119 @@ function resolveCurveDaoRouterGasUnitsFromSignRequest(detail, batchIndex) {
|
|
|
376
376
|
}
|
|
377
377
|
return null;
|
|
378
378
|
}
|
|
379
|
+
var COINBASE_B20_STOCK_DECIMALS = 8;
|
|
380
|
+
var COINBASE_B20_ASSET_PREFIX = "0xb200000000000000000000";
|
|
381
|
+
function isCoinbaseB20AssetToken(address) {
|
|
382
|
+
try {
|
|
383
|
+
return getAddress(address).toLowerCase().startsWith(COINBASE_B20_ASSET_PREFIX);
|
|
384
|
+
} catch {
|
|
385
|
+
return false;
|
|
386
|
+
}
|
|
387
|
+
}
|
|
388
|
+
function looksLikeCoinbaseStockSymbol(symbol) {
|
|
389
|
+
return /^[A-Za-z][A-Za-z0-9]{0,8}(?:\.[A-Za-z][A-Za-z0-9]{0,4})?c$/.test((symbol ?? "").trim());
|
|
390
|
+
}
|
|
391
|
+
var COINBASE_TOKENIZED_STOCKS_API_URL = "https://api.coinbase.com/v1/tokenized-stocks";
|
|
392
|
+
var CATALOG_TTL_MS = 15 * 60 * 1e3;
|
|
393
|
+
var CATALOG_MAX = 500;
|
|
394
|
+
var catalogRows = null;
|
|
395
|
+
var catalogAt = 0;
|
|
396
|
+
var catalogInflight = null;
|
|
397
|
+
var catalogBySymbol = /* @__PURE__ */ new Map();
|
|
398
|
+
var catalogByAddress = /* @__PURE__ */ new Map();
|
|
399
|
+
function indexCatalog(rows) {
|
|
400
|
+
catalogRows = rows;
|
|
401
|
+
catalogAt = Date.now();
|
|
402
|
+
catalogBySymbol.clear();
|
|
403
|
+
catalogByAddress.clear();
|
|
404
|
+
for (const row of rows) {
|
|
405
|
+
catalogBySymbol.set(row.symbol.toLowerCase(), row);
|
|
406
|
+
catalogByAddress.set(row.address.toLowerCase(), row);
|
|
407
|
+
}
|
|
408
|
+
}
|
|
409
|
+
function parseCoinbaseTokenizedStocksPayload(payload) {
|
|
410
|
+
const tokens = Array.isArray(payload) ? payload : payload && typeof payload === "object" && Array.isArray(payload.tokens) ? payload.tokens : [];
|
|
411
|
+
const out = [];
|
|
412
|
+
const seen = /* @__PURE__ */ new Set();
|
|
413
|
+
for (const row of tokens) {
|
|
414
|
+
if (!row || typeof row !== "object") continue;
|
|
415
|
+
const rec = row;
|
|
416
|
+
const symbol = typeof rec.symbol === "string" ? rec.symbol.trim() : "";
|
|
417
|
+
const addressRaw = typeof rec.contract_address === "string" ? rec.contract_address.trim() : "";
|
|
418
|
+
if (!looksLikeCoinbaseStockSymbol(symbol) || !isCoinbaseB20AssetToken(addressRaw)) continue;
|
|
419
|
+
const address = getAddress(addressRaw);
|
|
420
|
+
const key = address.toLowerCase();
|
|
421
|
+
if (seen.has(key)) continue;
|
|
422
|
+
seen.add(key);
|
|
423
|
+
const name = typeof rec.name === "string" && rec.name.trim() ? rec.name.trim() : symbol;
|
|
424
|
+
const iconUrl = typeof rec.icon_url === "string" && rec.icon_url.trim() ? rec.icon_url.trim() : void 0;
|
|
425
|
+
const decimals = typeof rec.decimals === "number" && Number.isInteger(rec.decimals) && rec.decimals >= 0 && rec.decimals <= 18 ? rec.decimals : COINBASE_B20_STOCK_DECIMALS;
|
|
426
|
+
out.push({ address, symbol, name, decimals, iconUrl });
|
|
427
|
+
if (out.length >= CATALOG_MAX) break;
|
|
428
|
+
}
|
|
429
|
+
return out;
|
|
430
|
+
}
|
|
431
|
+
async function fetchCoinbaseB20StockCatalog() {
|
|
432
|
+
const merged = [];
|
|
433
|
+
const seen = /* @__PURE__ */ new Set();
|
|
434
|
+
let pageToken = "";
|
|
435
|
+
for (let page = 0; page < 4; page++) {
|
|
436
|
+
const url = new URL(COINBASE_TOKENIZED_STOCKS_API_URL);
|
|
437
|
+
url.searchParams.set("page_size", "500");
|
|
438
|
+
if (pageToken) url.searchParams.set("page_token", pageToken);
|
|
439
|
+
const res = await fetch(url, { cache: "no-store", signal: AbortSignal.timeout(8e3) });
|
|
440
|
+
if (!res.ok) break;
|
|
441
|
+
const json = await res.json();
|
|
442
|
+
for (const row of parseCoinbaseTokenizedStocksPayload(json)) {
|
|
443
|
+
const key = row.address.toLowerCase();
|
|
444
|
+
if (seen.has(key)) continue;
|
|
445
|
+
seen.add(key);
|
|
446
|
+
merged.push(row);
|
|
447
|
+
if (merged.length >= CATALOG_MAX) break;
|
|
448
|
+
}
|
|
449
|
+
pageToken = typeof json.next_page_token === "string" ? json.next_page_token.trim() : "";
|
|
450
|
+
if (!pageToken || merged.length >= CATALOG_MAX) break;
|
|
451
|
+
}
|
|
452
|
+
if (merged.length > 0) indexCatalog(merged);
|
|
453
|
+
return catalogRows ?? [];
|
|
454
|
+
}
|
|
455
|
+
async function ensureCoinbaseB20StockCatalog() {
|
|
456
|
+
if (catalogRows && catalogRows.length > 0 && Date.now() - catalogAt < CATALOG_TTL_MS) return catalogRows;
|
|
457
|
+
if (!catalogInflight) {
|
|
458
|
+
catalogInflight = fetchCoinbaseB20StockCatalog().finally(() => {
|
|
459
|
+
catalogInflight = null;
|
|
460
|
+
});
|
|
461
|
+
}
|
|
462
|
+
try {
|
|
463
|
+
return await catalogInflight;
|
|
464
|
+
} catch {
|
|
465
|
+
return catalogRows ?? [];
|
|
466
|
+
}
|
|
467
|
+
}
|
|
468
|
+
function lookupCoinbaseB20StockToken(token) {
|
|
469
|
+
const key = (token ?? "").trim();
|
|
470
|
+
if (!key) return null;
|
|
471
|
+
const fromCatalog = catalogBySymbol.get(key.toLowerCase());
|
|
472
|
+
if (fromCatalog) return fromCatalog;
|
|
473
|
+
try {
|
|
474
|
+
return catalogByAddress.get(getAddress(key).toLowerCase()) ?? null;
|
|
475
|
+
} catch {
|
|
476
|
+
return null;
|
|
477
|
+
}
|
|
478
|
+
}
|
|
479
|
+
async function canonicalizeEvmTokenInput(token) {
|
|
480
|
+
const raw = (token ?? "").trim();
|
|
481
|
+
if (!raw || isAddress(raw)) return raw;
|
|
482
|
+
if (!looksLikeCoinbaseStockSymbol(raw)) return raw;
|
|
483
|
+
await ensureCoinbaseB20StockCatalog().catch(() => []);
|
|
484
|
+
const hit = lookupCoinbaseB20StockToken(raw);
|
|
485
|
+
if (!hit) {
|
|
486
|
+
throw new Error(
|
|
487
|
+
`Unknown Coinbase stock ticker "${raw}". It is not in the live tokenized-stocks catalog.`
|
|
488
|
+
);
|
|
489
|
+
}
|
|
490
|
+
return hit.address;
|
|
491
|
+
}
|
|
379
492
|
function defiEvmTransport(rpcUrl, opts) {
|
|
380
493
|
const url = rpcUrl.trim();
|
|
381
494
|
return http(url, opts);
|
|
@@ -630,7 +743,7 @@ function txToViemStep(tx) {
|
|
|
630
743
|
return { to, data, value };
|
|
631
744
|
}
|
|
632
745
|
async function buildEvmMultisignBodyCurveDaoBatch(args) {
|
|
633
|
-
const tokenIn = getAddress(args.tokenIn);
|
|
746
|
+
const tokenIn = getAddress(await canonicalizeEvmTokenInput(args.tokenIn));
|
|
634
747
|
const executor = getAddress(args.executorAddress);
|
|
635
748
|
const session = await loadFullCurveSessionForRpc(args.rpcUrl);
|
|
636
749
|
if (!session?.curve?.router?.populateSwap) {
|
|
@@ -639,7 +752,7 @@ async function buildEvmMultisignBodyCurveDaoBatch(args) {
|
|
|
639
752
|
const { curve, wrappedNative } = session;
|
|
640
753
|
const wn = wrappedNative;
|
|
641
754
|
const tokenInId = toCurveRouterTokenId(tokenIn, wn);
|
|
642
|
-
const outTrim = (args.tokenOut ?? "").trim();
|
|
755
|
+
const outTrim = (await canonicalizeEvmTokenInput(args.tokenOut ?? "")).trim();
|
|
643
756
|
const tokenOutId = toCurveRouterTokenId(
|
|
644
757
|
outTrim.toLowerCase() === ETH_PLACEHOLDER2 ? ETH_PLACEHOLDER2 : getAddress(outTrim),
|
|
645
758
|
wn
|
|
@@ -821,10 +934,12 @@ async function curveDaoQuote(args) {
|
|
|
821
934
|
if (!isCurveApiChainSupported(args.chainId)) {
|
|
822
935
|
throw new Error(`Chain ${args.chainId} is not supported by Curve Router NG.`);
|
|
823
936
|
}
|
|
937
|
+
const tokenIn = await canonicalizeEvmTokenInput(args.tokenIn);
|
|
938
|
+
const tokenOut = await canonicalizeEvmTokenInput(args.tokenOut);
|
|
824
939
|
const tokenInDecimals = await resolveTokenInDecimals({
|
|
825
940
|
rpcUrl,
|
|
826
941
|
chainId: args.chainId,
|
|
827
|
-
tokenIn
|
|
942
|
+
tokenIn,
|
|
828
943
|
tokenInDecimals: args.tokenInDecimals
|
|
829
944
|
});
|
|
830
945
|
const amountForRouter = normalizeCurveRouterAmountString(
|
|
@@ -845,8 +960,8 @@ async function curveDaoQuote(args) {
|
|
|
845
960
|
throw new Error("Curve router API is unavailable after session load.");
|
|
846
961
|
}
|
|
847
962
|
const { curve, wrappedNative: wn } = session;
|
|
848
|
-
const tokenInRouterId = toCurveRouterTokenId(normalizeNativeTokenIn(
|
|
849
|
-
const tokenOutTrim =
|
|
963
|
+
const tokenInRouterId = toCurveRouterTokenId(normalizeNativeTokenIn(tokenIn), wn);
|
|
964
|
+
const tokenOutTrim = tokenOut.trim();
|
|
850
965
|
const tokenOutRouterId = toCurveRouterTokenId(
|
|
851
966
|
tokenOutTrim.toLowerCase() === CURVE_NATIVE_PLACEHOLDER.toLowerCase() ? CURVE_NATIVE_PLACEHOLDER : getAddress(
|
|
852
967
|
tokenOutTrim.startsWith("0x") ? tokenOutTrim : `0x${tokenOutTrim}`
|