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