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