@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
|
@@ -507,6 +507,119 @@ async function pendleSearchAssets(args) {
|
|
|
507
507
|
notes: `No Pendle market on chain ${args.chainId} matched ${q}.`
|
|
508
508
|
};
|
|
509
509
|
}
|
|
510
|
+
var COINBASE_B20_STOCK_DECIMALS = 8;
|
|
511
|
+
var COINBASE_B20_ASSET_PREFIX = "0xb200000000000000000000";
|
|
512
|
+
function isCoinbaseB20AssetToken(address) {
|
|
513
|
+
try {
|
|
514
|
+
return getAddress(address).toLowerCase().startsWith(COINBASE_B20_ASSET_PREFIX);
|
|
515
|
+
} catch {
|
|
516
|
+
return false;
|
|
517
|
+
}
|
|
518
|
+
}
|
|
519
|
+
function looksLikeCoinbaseStockSymbol(symbol) {
|
|
520
|
+
return /^[A-Za-z][A-Za-z0-9]{0,8}(?:\.[A-Za-z][A-Za-z0-9]{0,4})?c$/.test((symbol ?? "").trim());
|
|
521
|
+
}
|
|
522
|
+
var COINBASE_TOKENIZED_STOCKS_API_URL = "https://api.coinbase.com/v1/tokenized-stocks";
|
|
523
|
+
var CATALOG_TTL_MS = 15 * 60 * 1e3;
|
|
524
|
+
var CATALOG_MAX = 500;
|
|
525
|
+
var catalogRows = null;
|
|
526
|
+
var catalogAt = 0;
|
|
527
|
+
var catalogInflight = null;
|
|
528
|
+
var catalogBySymbol = /* @__PURE__ */ new Map();
|
|
529
|
+
var catalogByAddress = /* @__PURE__ */ new Map();
|
|
530
|
+
function indexCatalog(rows) {
|
|
531
|
+
catalogRows = rows;
|
|
532
|
+
catalogAt = Date.now();
|
|
533
|
+
catalogBySymbol.clear();
|
|
534
|
+
catalogByAddress.clear();
|
|
535
|
+
for (const row of rows) {
|
|
536
|
+
catalogBySymbol.set(row.symbol.toLowerCase(), row);
|
|
537
|
+
catalogByAddress.set(row.address.toLowerCase(), row);
|
|
538
|
+
}
|
|
539
|
+
}
|
|
540
|
+
function parseCoinbaseTokenizedStocksPayload(payload) {
|
|
541
|
+
const tokens = Array.isArray(payload) ? payload : payload && typeof payload === "object" && Array.isArray(payload.tokens) ? payload.tokens : [];
|
|
542
|
+
const out = [];
|
|
543
|
+
const seen = /* @__PURE__ */ new Set();
|
|
544
|
+
for (const row of tokens) {
|
|
545
|
+
if (!row || typeof row !== "object") continue;
|
|
546
|
+
const rec = row;
|
|
547
|
+
const symbol = typeof rec.symbol === "string" ? rec.symbol.trim() : "";
|
|
548
|
+
const addressRaw = typeof rec.contract_address === "string" ? rec.contract_address.trim() : "";
|
|
549
|
+
if (!looksLikeCoinbaseStockSymbol(symbol) || !isCoinbaseB20AssetToken(addressRaw)) continue;
|
|
550
|
+
const address = getAddress(addressRaw);
|
|
551
|
+
const key = address.toLowerCase();
|
|
552
|
+
if (seen.has(key)) continue;
|
|
553
|
+
seen.add(key);
|
|
554
|
+
const name = typeof rec.name === "string" && rec.name.trim() ? rec.name.trim() : symbol;
|
|
555
|
+
const iconUrl = typeof rec.icon_url === "string" && rec.icon_url.trim() ? rec.icon_url.trim() : void 0;
|
|
556
|
+
const decimals = typeof rec.decimals === "number" && Number.isInteger(rec.decimals) && rec.decimals >= 0 && rec.decimals <= 18 ? rec.decimals : COINBASE_B20_STOCK_DECIMALS;
|
|
557
|
+
out.push({ address, symbol, name, decimals, iconUrl });
|
|
558
|
+
if (out.length >= CATALOG_MAX) break;
|
|
559
|
+
}
|
|
560
|
+
return out;
|
|
561
|
+
}
|
|
562
|
+
async function fetchCoinbaseB20StockCatalog() {
|
|
563
|
+
const merged = [];
|
|
564
|
+
const seen = /* @__PURE__ */ new Set();
|
|
565
|
+
let pageToken = "";
|
|
566
|
+
for (let page = 0; page < 4; page++) {
|
|
567
|
+
const url = new URL(COINBASE_TOKENIZED_STOCKS_API_URL);
|
|
568
|
+
url.searchParams.set("page_size", "500");
|
|
569
|
+
if (pageToken) url.searchParams.set("page_token", pageToken);
|
|
570
|
+
const res = await fetch(url, { cache: "no-store", signal: AbortSignal.timeout(8e3) });
|
|
571
|
+
if (!res.ok) break;
|
|
572
|
+
const json = await res.json();
|
|
573
|
+
for (const row of parseCoinbaseTokenizedStocksPayload(json)) {
|
|
574
|
+
const key = row.address.toLowerCase();
|
|
575
|
+
if (seen.has(key)) continue;
|
|
576
|
+
seen.add(key);
|
|
577
|
+
merged.push(row);
|
|
578
|
+
if (merged.length >= CATALOG_MAX) break;
|
|
579
|
+
}
|
|
580
|
+
pageToken = typeof json.next_page_token === "string" ? json.next_page_token.trim() : "";
|
|
581
|
+
if (!pageToken || merged.length >= CATALOG_MAX) break;
|
|
582
|
+
}
|
|
583
|
+
if (merged.length > 0) indexCatalog(merged);
|
|
584
|
+
return catalogRows ?? [];
|
|
585
|
+
}
|
|
586
|
+
async function ensureCoinbaseB20StockCatalog() {
|
|
587
|
+
if (catalogRows && catalogRows.length > 0 && Date.now() - catalogAt < CATALOG_TTL_MS) return catalogRows;
|
|
588
|
+
if (!catalogInflight) {
|
|
589
|
+
catalogInflight = fetchCoinbaseB20StockCatalog().finally(() => {
|
|
590
|
+
catalogInflight = null;
|
|
591
|
+
});
|
|
592
|
+
}
|
|
593
|
+
try {
|
|
594
|
+
return await catalogInflight;
|
|
595
|
+
} catch {
|
|
596
|
+
return catalogRows ?? [];
|
|
597
|
+
}
|
|
598
|
+
}
|
|
599
|
+
function lookupCoinbaseB20StockToken(token) {
|
|
600
|
+
const key = (token ?? "").trim();
|
|
601
|
+
if (!key) return null;
|
|
602
|
+
const fromCatalog = catalogBySymbol.get(key.toLowerCase());
|
|
603
|
+
if (fromCatalog) return fromCatalog;
|
|
604
|
+
try {
|
|
605
|
+
return catalogByAddress.get(getAddress(key).toLowerCase()) ?? null;
|
|
606
|
+
} catch {
|
|
607
|
+
return null;
|
|
608
|
+
}
|
|
609
|
+
}
|
|
610
|
+
async function canonicalizeEvmTokenInput(token) {
|
|
611
|
+
const raw = (token ?? "").trim();
|
|
612
|
+
if (!raw || isAddress(raw)) return raw;
|
|
613
|
+
if (!looksLikeCoinbaseStockSymbol(raw)) return raw;
|
|
614
|
+
await ensureCoinbaseB20StockCatalog().catch(() => []);
|
|
615
|
+
const hit = lookupCoinbaseB20StockToken(raw);
|
|
616
|
+
if (!hit) {
|
|
617
|
+
throw new Error(
|
|
618
|
+
`Unknown Coinbase stock ticker "${raw}". It is not in the live tokenized-stocks catalog.`
|
|
619
|
+
);
|
|
620
|
+
}
|
|
621
|
+
return hit.address;
|
|
622
|
+
}
|
|
510
623
|
function defiEvmTransport(rpcUrl, opts) {
|
|
511
624
|
const url = rpcUrl.trim();
|
|
512
625
|
return http(url, opts);
|
|
@@ -555,15 +668,16 @@ async function resolvePendleTokenDecimals(args) {
|
|
|
555
668
|
if (args.decimals != null && Number.isInteger(args.decimals) && args.decimals >= 0 && args.decimals <= 18) {
|
|
556
669
|
return args.decimals;
|
|
557
670
|
}
|
|
558
|
-
|
|
559
|
-
|
|
671
|
+
const token = await canonicalizeEvmTokenInput(args.token);
|
|
672
|
+
if (isPendleNativeToken(token)) return 18;
|
|
673
|
+
const id = pendleAssetId(args.chainId, normalizePendleTokenAddress(token));
|
|
560
674
|
try {
|
|
561
675
|
const assets = await pendleFetchAssetsByIds([id]);
|
|
562
676
|
if (assets[0]) return assets[0].decimals;
|
|
563
677
|
} catch {
|
|
564
678
|
}
|
|
565
679
|
if (!args.rpcUrl?.trim()) return 18;
|
|
566
|
-
const addr = getAddress(
|
|
680
|
+
const addr = getAddress(token);
|
|
567
681
|
const ch = defineChain({
|
|
568
682
|
id: args.chainId,
|
|
569
683
|
name: "PendleDecimals",
|
|
@@ -624,11 +738,15 @@ async function pendleConvert(args) {
|
|
|
624
738
|
receiver,
|
|
625
739
|
slippage: slippagePercentToConvert(args.slippagePercent),
|
|
626
740
|
enableAggregator: args.enableAggregator === true,
|
|
627
|
-
inputs:
|
|
628
|
-
|
|
629
|
-
|
|
630
|
-
|
|
631
|
-
|
|
741
|
+
inputs: await Promise.all(
|
|
742
|
+
args.tokensIn.map(async (t) => ({
|
|
743
|
+
token: normalizePendleTokenAddress(await canonicalizeEvmTokenInput(t.token)),
|
|
744
|
+
amount: t.amountWei
|
|
745
|
+
}))
|
|
746
|
+
),
|
|
747
|
+
outputs: await Promise.all(
|
|
748
|
+
args.tokensOut.map(async (t) => normalizePendleTokenAddress(await canonicalizeEvmTokenInput(t)))
|
|
749
|
+
),
|
|
632
750
|
additionalData: args.additionalData ?? "impliedApy,effectiveApy"
|
|
633
751
|
};
|
|
634
752
|
const json = await pendleCoreFetch({
|
|
@@ -642,14 +760,15 @@ async function pendleQuoteConvert(args) {
|
|
|
642
760
|
const receiver = args.receiver?.trim() || PENDLE_NATIVE_PLACEHOLDER;
|
|
643
761
|
const tokensIn = [];
|
|
644
762
|
for (const t of args.tokensIn) {
|
|
763
|
+
const token = await canonicalizeEvmTokenInput(t.token);
|
|
645
764
|
const decimals = await resolvePendleTokenDecimals({
|
|
646
765
|
chainId: args.chainId,
|
|
647
766
|
rpcUrl: args.rpcUrl,
|
|
648
|
-
token
|
|
767
|
+
token,
|
|
649
768
|
decimals: t.decimals
|
|
650
769
|
});
|
|
651
770
|
tokensIn.push({
|
|
652
|
-
token
|
|
771
|
+
token,
|
|
653
772
|
amountWei: parseUnits(t.amountHuman.trim(), decimals).toString()
|
|
654
773
|
});
|
|
655
774
|
}
|