diff --git a/defillama-openapi-free.json b/defillama-openapi-free.json index b8a0a7141e5..14e87836b01 100644 --- a/defillama-openapi-free.json +++ b/defillama-openapi-free.json @@ -1,9 +1,26 @@ { "openapi": "3.0.0", "info": { - "description": "\n\nNeed higher rate limits or priority support? We offer a premium plan for 300$/mo. To get it, go to https://defillama.com/subscription \n\n\n Coding with AI? Paste this link to LLM-specific docs for best results \nllms.txt", + "description": "\n\nNeed higher rate limits or priority support? We offer a premium plan for 300$/mo. To get it, go to https://defillama.com/subscription\n\nSDK\n\nInstall:\n```bash\nnpm install @defillama/api\npip install defillama-sdk\n```\n\nQuick start (JavaScript):\n```ts\nimport { DefiLlama } from '@defillama/api'\n\nconst client = new DefiLlama()\nconst protocols = await client.tvl.getProtocols()\n```\n\nQuick start (Python):\n```py\nfrom defillama_sdk import DefiLlama\n\nclient = DefiLlama()\nprotocols = client.tvl.getProtocols()\n```\n\nCoding with AI? Paste this link to LLM-specific docs for best results\nllms.txt", "version": "1.0.0-oas3", - "title": "DefiLlama API" + "title": "DefiLlama API", + "x-scalar-sdk-installation": [ + { + "lang": "node", + "description": "Install the DefiLlama JavaScript SDK:", + "source": "npm install @defillama/api" + }, + { + "lang": "js", + "description": "Install the DefiLlama JavaScript SDK:", + "source": "npm install @defillama/api" + }, + { + "lang": "python", + "description": "Install the DefiLlama Python SDK:", + "source": "pip install defillama-sdk" + } + ] }, "tags": [ { @@ -102,7 +119,19 @@ } } } - } + }, + "x-codeSamples": [ + { + "lang": "javascript", + "label": "JavaScript SDK", + "source": "const result = await client.tvl.getProtocols()" + }, + { + "lang": "python", + "label": "Python SDK", + "source": "result = client.tvl.getProtocols()" + } + ] } }, "/protocol/{protocol}": { @@ -216,7 +245,19 @@ "404": { "description": "Protocol not found" } - } + }, + "x-codeSamples": [ + { + "lang": "javascript", + "label": "JavaScript SDK", + "source": "const result = await client.tvl.getProtocol('')" + }, + { + "lang": "python", + "label": "Python SDK", + "source": "result = client.tvl.getProtocol('')" + } + ] } }, "/v2/historicalChainTvl": { @@ -249,7 +290,19 @@ } } } - } + }, + "x-codeSamples": [ + { + "lang": "javascript", + "label": "JavaScript SDK", + "source": "const result = await client.tvl.getHistoricalChainTvl()" + }, + { + "lang": "python", + "label": "Python SDK", + "source": "result = client.tvl.getHistoricalChainTvl()" + } + ] } }, "/v2/historicalChainTvl/{chain}": { @@ -297,7 +350,19 @@ "404": { "description": "Chain not found" } - } + }, + "x-codeSamples": [ + { + "lang": "javascript", + "label": "JavaScript SDK", + "source": "const result = await client.tvl.getHistoricalChainTvl('')" + }, + { + "lang": "python", + "label": "Python SDK", + "source": "result = client.tvl.getHistoricalChainTvl()" + } + ] } }, "/tvl/{protocol}": { @@ -333,7 +398,19 @@ "404": { "description": "Protocol not found" } - } + }, + "x-codeSamples": [ + { + "lang": "javascript", + "label": "JavaScript SDK", + "source": "const result = await client.tvl.getTvl('')" + }, + { + "lang": "python", + "label": "Python SDK", + "source": "result = client.tvl.getTvl('')" + } + ] } }, "/v2/chains": { @@ -390,7 +467,19 @@ } } } - } + }, + "x-codeSamples": [ + { + "lang": "javascript", + "label": "JavaScript SDK", + "source": "const result = await client.tvl.getChains()" + }, + { + "lang": "python", + "label": "Python SDK", + "source": "result = client.tvl.getChains()" + } + ] } }, "/prices/current/{coins}": { @@ -467,7 +556,19 @@ "502": { "description": "Internal error" } - } + }, + "x-codeSamples": [ + { + "lang": "javascript", + "label": "JavaScript SDK", + "source": "const result = await client.prices.getCurrentPrices([''])" + }, + { + "lang": "python", + "label": "Python SDK", + "source": "result = client.prices.getCurrentPrices([''])" + } + ] } }, "/prices/historical/{timestamp}/{coins}": { @@ -554,7 +655,19 @@ "502": { "description": "Internal error" } - } + }, + "x-codeSamples": [ + { + "lang": "javascript", + "label": "JavaScript SDK", + "source": "const result = await client.prices.getHistoricalPrices(1704067200, [''])" + }, + { + "lang": "python", + "label": "Python SDK", + "source": "result = client.prices.getHistoricalPrices(1704067200, [''])" + } + ] } }, "/batchHistorical": { @@ -639,7 +752,19 @@ "502": { "description": "Internal error" } - } + }, + "x-codeSamples": [ + { + "lang": "javascript", + "label": "JavaScript SDK", + "source": "const result = await client.prices.getBatchHistoricalPrices({ '': [1704067200] })" + }, + { + "lang": "python", + "label": "Python SDK", + "source": "result = client.prices.getBatchHistoricalPrices([''], '')" + } + ] } }, "/chart/{coins}": { @@ -768,7 +893,19 @@ "502": { "description": "Internal error" } - } + }, + "x-codeSamples": [ + { + "lang": "javascript", + "label": "JavaScript SDK", + "source": "const result = await client.prices.getChart([''])" + }, + { + "lang": "python", + "label": "Python SDK", + "source": "result = client.prices.getChart([''])" + } + ] } }, "/percentage/{coins}": { @@ -848,7 +985,19 @@ "502": { "description": "Internal error" } - } + }, + "x-codeSamples": [ + { + "lang": "javascript", + "label": "JavaScript SDK", + "source": "const result = await client.prices.getPercentageChange([''])" + }, + { + "lang": "python", + "label": "Python SDK", + "source": "result = client.prices.getPercentageChange([''])" + } + ] } }, "/prices/first/{coins}": { @@ -910,7 +1059,19 @@ "502": { "description": "Internal error" } - } + }, + "x-codeSamples": [ + { + "lang": "javascript", + "label": "JavaScript SDK", + "source": "const result = await client.prices.getFirstPrices([''])" + }, + { + "lang": "python", + "label": "Python SDK", + "source": "result = client.prices.getFirstPrices([''])" + } + ] } }, "/block/{chain}/{timestamp}": { @@ -971,7 +1132,19 @@ "400": { "description": "Invalid chain or timestamp provided" } - } + }, + "x-codeSamples": [ + { + "lang": "javascript", + "label": "JavaScript SDK", + "source": "const result = await client.prices.getBlockAtTimestamp('', 1704067200)" + }, + { + "lang": "python", + "label": "Python SDK", + "source": "result = client.prices.getBlockAtTimestamp('', 1704067200)" + } + ] } }, "/stablecoins": { @@ -1073,7 +1246,19 @@ } } } - } + }, + "x-codeSamples": [ + { + "lang": "javascript", + "label": "JavaScript SDK", + "source": "const result = await client.stablecoins.getStablecoins()" + }, + { + "lang": "python", + "label": "Python SDK", + "source": "result = client.stablecoins.getStablecoins()" + } + ] } }, "/stablecoincharts/all": { @@ -1126,7 +1311,19 @@ } } } - } + }, + "x-codeSamples": [ + { + "lang": "javascript", + "label": "JavaScript SDK", + "source": "const result = await client.stablecoins.getAllCharts()" + }, + { + "lang": "python", + "label": "Python SDK", + "source": "result = client.stablecoins.getAllCharts()" + } + ] } }, "/stablecoincharts/{chain}": { @@ -1189,7 +1386,19 @@ } } } - } + }, + "x-codeSamples": [ + { + "lang": "javascript", + "label": "JavaScript SDK", + "source": "const result = await client.stablecoins.getChartsByChain('')" + }, + { + "lang": "python", + "label": "Python SDK", + "source": "result = client.stablecoins.getChartsByChain('')" + } + ] } }, "/stablecoin/{asset}": { @@ -1273,7 +1482,19 @@ } } } - } + }, + "x-codeSamples": [ + { + "lang": "javascript", + "label": "JavaScript SDK", + "source": "const result = await client.stablecoins.getStablecoin('')" + }, + { + "lang": "python", + "label": "Python SDK", + "source": "result = client.stablecoins.getStablecoin('')" + } + ] } }, "/stablecoinchains": { @@ -1314,7 +1535,19 @@ } } } - } + }, + "x-codeSamples": [ + { + "lang": "javascript", + "label": "JavaScript SDK", + "source": "const result = await client.stablecoins.getChains()" + }, + { + "lang": "python", + "label": "Python SDK", + "source": "result = client.stablecoins.getChains()" + } + ] } }, "/stablecoinprices": { @@ -1357,7 +1590,19 @@ } } } - } + }, + "x-codeSamples": [ + { + "lang": "javascript", + "label": "JavaScript SDK", + "source": "const result = await client.stablecoins.getPrices()" + }, + { + "lang": "python", + "label": "Python SDK", + "source": "result = client.stablecoins.getPrices()" + } + ] } }, "/pools": { @@ -1465,7 +1710,19 @@ } } } - } + }, + "x-codeSamples": [ + { + "lang": "javascript", + "label": "JavaScript SDK", + "source": "const result = await proClient.yields.getPools()" + }, + { + "lang": "python", + "label": "Python SDK", + "source": "result = pro_client.yields.getPools()" + } + ] } }, "/chart/{pool}": { @@ -1534,7 +1791,19 @@ } } } - } + }, + "x-codeSamples": [ + { + "lang": "javascript", + "label": "JavaScript SDK", + "source": "const result = await proClient.yields.getPoolChart('')" + }, + { + "lang": "python", + "label": "Python SDK", + "source": "result = pro_client.yields.getPoolChart('')" + } + ] } }, "/overview/dexs": { @@ -1644,7 +1913,19 @@ } } } - } + }, + "x-codeSamples": [ + { + "lang": "javascript", + "label": "JavaScript SDK", + "source": "const result = await client.volumes.getDexOverview()" + }, + { + "lang": "python", + "label": "Python SDK", + "source": "result = client.volumes.getDexOverview()" + } + ] } }, "/overview/dexs/{chain}": { @@ -1728,7 +2009,19 @@ } } } - } + }, + "x-codeSamples": [ + { + "lang": "javascript", + "label": "JavaScript SDK", + "source": "const result = await client.volumes.getDexOverviewByChain('')" + }, + { + "lang": "python", + "label": "Python SDK", + "source": "result = client.volumes.getDexOverviewByChain('')" + } + ] } }, "/summary/dexs/{protocol}": { @@ -1824,7 +2117,19 @@ } } } - } + }, + "x-codeSamples": [ + { + "lang": "javascript", + "label": "JavaScript SDK", + "source": "const result = await client.volumes.getDexSummary('')" + }, + { + "lang": "python", + "label": "Python SDK", + "source": "result = client.volumes.getDexSummary('')" + } + ] } }, "/overview/options": { @@ -1909,7 +2214,19 @@ } } } - } + }, + "x-codeSamples": [ + { + "lang": "javascript", + "label": "JavaScript SDK", + "source": "const result = await client.volumes.getOptionsOverview()" + }, + { + "lang": "python", + "label": "Python SDK", + "source": "result = client.volumes.getOptionsOverview()" + } + ] } }, "/overview/options/{chain}": { @@ -1968,7 +2285,19 @@ "200": { "description": "successful operation" } - } + }, + "x-codeSamples": [ + { + "lang": "javascript", + "label": "JavaScript SDK", + "source": "const result = await client.volumes.getOptionsOverviewByChain('')" + }, + { + "lang": "python", + "label": "Python SDK", + "source": "result = client.volumes.getOptionsOverviewByChain('')" + } + ] } }, "/summary/options/{protocol}": { @@ -2007,7 +2336,19 @@ "200": { "description": "successful operation" } - } + }, + "x-codeSamples": [ + { + "lang": "javascript", + "label": "JavaScript SDK", + "source": "const result = await client.volumes.getOptionsSummary('')" + }, + { + "lang": "python", + "label": "Python SDK", + "source": "result = client.volumes.getOptionsSummary('')" + } + ] } }, "/overview/open-interest": { @@ -2226,7 +2567,19 @@ } } } - } + }, + "x-codeSamples": [ + { + "lang": "javascript", + "label": "JavaScript SDK", + "source": "const result = await client.fees.getOverview()" + }, + { + "lang": "python", + "label": "Python SDK", + "source": "result = client.fees.getOverview()" + } + ] } }, "/overview/fees/{chain}": { @@ -2345,7 +2698,19 @@ } } } - } + }, + "x-codeSamples": [ + { + "lang": "javascript", + "label": "JavaScript SDK", + "source": "const result = await client.fees.getOverviewByChain('')" + }, + { + "lang": "python", + "label": "Python SDK", + "source": "result = client.fees.getOverviewByChain('')" + } + ] } }, "/summary/fees/{protocol}": { @@ -2655,7 +3020,19 @@ } } } - } + }, + "x-codeSamples": [ + { + "lang": "javascript", + "label": "JavaScript SDK", + "source": "const result = await client.fees.getSummary('')" + }, + { + "lang": "python", + "label": "Python SDK", + "source": "result = client.fees.getSummary('')" + } + ] } } } diff --git a/defillama-openapi-pro.json b/defillama-openapi-pro.json index fee5344f89d..c5948d7d456 100644 --- a/defillama-openapi-pro.json +++ b/defillama-openapi-pro.json @@ -3,7 +3,24 @@ "info": { "title": "DefiLlama Pro - OpenAPI 3.0", "version": "1.0.0", - "description": "Docs for DefiLlama's Pro API \n\n\n Coding with AI? Paste this link to LLM-specific docs for best results \nllms.txt" + "description": "Docs for DefiLlama's Pro API\n\nSDK\n\nInstall:\n```bash\nnpm install @defillama/api\npip install defillama-sdk\n```\n\nQuick start (JavaScript):\n```ts\nimport { DefiLlama } from '@defillama/api'\n\nconst proClient = new DefiLlama({ apiKey: 'your-api-key' })\nconst protocols = await proClient.tvl.getProtocols()\n```\n\nQuick start (Python):\n```py\nfrom defillama_sdk import DefiLlama\n\npro_client = DefiLlama({\"api_key\": \"your-api-key\"})\nprotocols = pro_client.tvl.getProtocols()\n```\n\nCoding with AI? Paste this link to LLM-specific docs for best results\nllms.txt", + "x-scalar-sdk-installation": [ + { + "lang": "node", + "description": "Install the DefiLlama JavaScript SDK:", + "source": "npm install @defillama/api" + }, + { + "lang": "js", + "description": "Install the DefiLlama JavaScript SDK:", + "source": "npm install @defillama/api" + }, + { + "lang": "python", + "description": "Install the DefiLlama Python SDK:", + "source": "pip install defillama-sdk" + } + ] }, "servers": [ { @@ -109,7 +126,19 @@ } } } - } + }, + "x-codeSamples": [ + { + "lang": "javascript", + "label": "JavaScript SDK", + "source": "const result = await proClient.tvl.getTokenProtocols('')" + }, + { + "lang": "python", + "label": "Python SDK", + "source": "result = pro_client.tvl.getTokenProtocols('')" + } + ] } }, "/api/inflows/{protocol}/{timestamp}": { @@ -251,7 +280,19 @@ } } } - } + }, + "x-codeSamples": [ + { + "lang": "javascript", + "label": "JavaScript SDK", + "source": "const result = await proClient.tvl.getInflows('', 1704067200, 1704153600)" + }, + { + "lang": "python", + "label": "Python SDK", + "source": "result = pro_client.tvl.getInflows('', 1704067200, 1704153600)" + } + ] } }, "/api/chainAssets": { @@ -369,7 +410,19 @@ } } }, - "x-api-plan-only": true + "x-api-plan-only": true, + "x-codeSamples": [ + { + "lang": "javascript", + "label": "JavaScript SDK", + "source": "const result = await proClient.tvl.getChainAssets()" + }, + { + "lang": "python", + "label": "Python SDK", + "source": "result = pro_client.tvl.getChainAssets()" + } + ] } }, "/stablecoins/stablecoindominance/{chain}": { @@ -453,7 +506,19 @@ } } }, - "x-api-plan-only": true + "x-api-plan-only": true, + "x-codeSamples": [ + { + "lang": "javascript", + "label": "JavaScript SDK", + "source": "const result = await proClient.stablecoins.getDominance('')" + }, + { + "lang": "python", + "label": "Python SDK", + "source": "result = pro_client.stablecoins.getDominance('')" + } + ] } }, "/api/emissions": { @@ -568,7 +633,19 @@ } } }, - "x-api-plan-only": true + "x-api-plan-only": true, + "x-codeSamples": [ + { + "lang": "javascript", + "label": "JavaScript SDK", + "source": "const result = await proClient.emissions.getAll()" + }, + { + "lang": "python", + "label": "Python SDK", + "source": "result = pro_client.emissions.getAll()" + } + ] } }, "/api/emission/{protocol}": { @@ -841,7 +918,19 @@ } } }, - "x-api-plan-only": true + "x-api-plan-only": true, + "x-codeSamples": [ + { + "lang": "javascript", + "label": "JavaScript SDK", + "source": "const result = await proClient.emissions.getByProtocol('')" + }, + { + "lang": "python", + "label": "Python SDK", + "source": "result = pro_client.emissions.getByProtocol('')" + } + ] } }, "/api/categories": { @@ -977,7 +1066,19 @@ } } }, - "x-api-plan-only": true + "x-api-plan-only": true, + "x-codeSamples": [ + { + "lang": "javascript", + "label": "JavaScript SDK", + "source": "const result = await proClient.ecosystem.getCategories()" + }, + { + "lang": "python", + "label": "Python SDK", + "source": "result = pro_client.ecosystem.getCategories()" + } + ] } }, "/api/forks": { @@ -1086,7 +1187,19 @@ } } } - } + }, + "x-codeSamples": [ + { + "lang": "javascript", + "label": "JavaScript SDK", + "source": "const result = await proClient.ecosystem.getForks()" + }, + { + "lang": "python", + "label": "Python SDK", + "source": "result = pro_client.ecosystem.getForks()" + } + ] } }, "/api/oracles": { @@ -1188,7 +1301,19 @@ } } }, - "x-api-plan-only": true + "x-api-plan-only": true, + "x-codeSamples": [ + { + "lang": "javascript", + "label": "JavaScript SDK", + "source": "const result = await proClient.ecosystem.getOracles()" + }, + { + "lang": "python", + "label": "Python SDK", + "source": "result = pro_client.ecosystem.getOracles()" + } + ] } }, "/api/hacks": { @@ -1263,7 +1388,19 @@ } } }, - "x-api-plan-only": true + "x-api-plan-only": true, + "x-codeSamples": [ + { + "lang": "javascript", + "label": "JavaScript SDK", + "source": "const result = await proClient.ecosystem.getHacks()" + }, + { + "lang": "python", + "label": "Python SDK", + "source": "result = pro_client.ecosystem.getHacks()" + } + ] } }, "/api/raises": { @@ -1353,7 +1490,19 @@ } } }, - "x-api-plan-only": true + "x-api-plan-only": true, + "x-codeSamples": [ + { + "lang": "javascript", + "label": "JavaScript SDK", + "source": "const result = await proClient.ecosystem.getRaises()" + }, + { + "lang": "python", + "label": "Python SDK", + "source": "result = pro_client.ecosystem.getRaises()" + } + ] } }, "/api/treasuries": { @@ -1509,7 +1658,19 @@ } } }, - "x-api-plan-only": true + "x-api-plan-only": true, + "x-codeSamples": [ + { + "lang": "javascript", + "label": "JavaScript SDK", + "source": "const result = await proClient.ecosystem.getTreasuries()" + }, + { + "lang": "python", + "label": "Python SDK", + "source": "result = pro_client.ecosystem.getTreasuries()" + } + ] } }, "/api/entities": { @@ -1642,7 +1803,19 @@ } } }, - "x-api-plan-only": true + "x-api-plan-only": true, + "x-codeSamples": [ + { + "lang": "javascript", + "label": "JavaScript SDK", + "source": "const result = await proClient.ecosystem.getEntities()" + }, + { + "lang": "python", + "label": "Python SDK", + "source": "result = pro_client.ecosystem.getEntities()" + } + ] } }, "/api/historicalLiquidity/{token}": { @@ -1829,7 +2002,19 @@ } } } - } + }, + "x-codeSamples": [ + { + "lang": "javascript", + "label": "JavaScript SDK", + "source": "const result = await proClient.yields.getPools()" + }, + { + "lang": "python", + "label": "Python SDK", + "source": "result = pro_client.yields.getPools()" + } + ] } }, "/yields/poolsOld": { @@ -2025,7 +2210,19 @@ } } }, - "x-api-plan-only": true + "x-api-plan-only": true, + "x-codeSamples": [ + { + "lang": "javascript", + "label": "JavaScript SDK", + "source": "const result = await proClient.yields.getPoolsOld()" + }, + { + "lang": "python", + "label": "Python SDK", + "source": "result = pro_client.yields.getPoolsOld()" + } + ] } }, "/yields/chart/{pool}": { @@ -2097,7 +2294,19 @@ } } } - } + }, + "x-codeSamples": [ + { + "lang": "javascript", + "label": "JavaScript SDK", + "source": "const result = await proClient.yields.getPoolChart('')" + }, + { + "lang": "python", + "label": "Python SDK", + "source": "result = pro_client.yields.getPoolChart('')" + } + ] } }, "/yields/poolsBorrow": { @@ -2293,7 +2502,19 @@ } } }, - "x-api-plan-only": true + "x-api-plan-only": true, + "x-codeSamples": [ + { + "lang": "javascript", + "label": "JavaScript SDK", + "source": "const result = await proClient.yields.getBorrowPools()" + }, + { + "lang": "python", + "label": "Python SDK", + "source": "result = pro_client.yields.getBorrowPools()" + } + ] } }, "/yields/chartLendBorrow/{pool}": { @@ -2370,7 +2591,19 @@ } } }, - "x-api-plan-only": true + "x-api-plan-only": true, + "x-codeSamples": [ + { + "lang": "javascript", + "label": "JavaScript SDK", + "source": "const result = await proClient.yields.getLendBorrowChart('')" + }, + { + "lang": "python", + "label": "Python SDK", + "source": "result = pro_client.yields.getLendBorrowChart('')" + } + ] } }, "/yields/perps": { @@ -2459,7 +2692,19 @@ } } }, - "x-api-plan-only": true + "x-api-plan-only": true, + "x-codeSamples": [ + { + "lang": "javascript", + "label": "JavaScript SDK", + "source": "const result = await proClient.yields.getPerps()" + }, + { + "lang": "python", + "label": "Python SDK", + "source": "result = pro_client.yields.getPerps()" + } + ] } }, "/yields/lsdRates": { @@ -2527,7 +2772,19 @@ } } }, - "x-api-plan-only": true + "x-api-plan-only": true, + "x-codeSamples": [ + { + "lang": "javascript", + "label": "JavaScript SDK", + "source": "const result = await proClient.yields.getLsdRates()" + }, + { + "lang": "python", + "label": "Python SDK", + "source": "result = pro_client.yields.getLsdRates()" + } + ] } }, "/etfs/snapshot": { @@ -2610,7 +2867,19 @@ } } }, - "x-api-plan-only": true + "x-api-plan-only": true, + "x-codeSamples": [ + { + "lang": "javascript", + "label": "JavaScript SDK", + "source": "const result = await proClient.etfs.getOverview()" + }, + { + "lang": "python", + "label": "Python SDK", + "source": "result = pro_client.etfs.getOverview()" + } + ] } }, "/etfs/flows": { @@ -2653,7 +2922,19 @@ } } }, - "x-api-plan-only": true + "x-api-plan-only": true, + "x-codeSamples": [ + { + "lang": "javascript", + "label": "JavaScript SDK", + "source": "const result = await proClient.etfs.getHistory()" + }, + { + "lang": "python", + "label": "Python SDK", + "source": "result = pro_client.etfs.getHistory()" + } + ] } }, "/fdv/performance/{period}": { @@ -2808,7 +3089,19 @@ } } }, - "x-api-plan-only": true + "x-api-plan-only": true, + "x-codeSamples": [ + { + "lang": "javascript", + "label": "JavaScript SDK", + "source": "const result = await proClient.etfs.getFdvPerformance('30')" + }, + { + "lang": "python", + "label": "Python SDK", + "source": "result = pro_client.etfs.getFdvPerformance('30')" + } + ] } }, "/api/overview/derivatives": { @@ -3201,7 +3494,19 @@ } } }, - "x-api-plan-only": true + "x-api-plan-only": true, + "x-codeSamples": [ + { + "lang": "javascript", + "label": "JavaScript SDK", + "source": "const result = await proClient.volumes.getDerivativesOverview()" + }, + { + "lang": "python", + "label": "Python SDK", + "source": "result = pro_client.volumes.getDerivativesOverview()" + } + ] } }, "/api/summary/derivatives/{protocol}": { @@ -3524,7 +3829,19 @@ } } }, - "x-api-plan-only": true + "x-api-plan-only": true, + "x-codeSamples": [ + { + "lang": "javascript", + "label": "JavaScript SDK", + "source": "const result = await proClient.volumes.getDerivativesSummary('')" + }, + { + "lang": "python", + "label": "Python SDK", + "source": "result = pro_client.volumes.getDerivativesSummary('')" + } + ] } }, "/bridges/bridges": { @@ -3660,7 +3977,19 @@ } } }, - "x-api-plan-only": true + "x-api-plan-only": true, + "x-codeSamples": [ + { + "lang": "javascript", + "label": "JavaScript SDK", + "source": "const result = await client.bridges.getAll()" + }, + { + "lang": "python", + "label": "Python SDK", + "source": "result = client.bridges.getAll()" + } + ] } }, "/bridges/bridge/{id}": { @@ -3930,7 +4259,19 @@ } } }, - "x-api-plan-only": true + "x-api-plan-only": true, + "x-codeSamples": [ + { + "lang": "javascript", + "label": "JavaScript SDK", + "source": "const result = await client.bridges.getById(1)" + }, + { + "lang": "python", + "label": "Python SDK", + "source": "result = client.bridges.getById('')" + } + ] } }, "/bridges/bridgevolume/{chain}": { @@ -4017,7 +4358,19 @@ } } }, - "x-api-plan-only": true + "x-api-plan-only": true, + "x-codeSamples": [ + { + "lang": "javascript", + "label": "JavaScript SDK", + "source": "const result = await client.bridges.getVolumeByChain('')" + }, + { + "lang": "python", + "label": "Python SDK", + "source": "result = client.bridges.getVolumeByChain('')" + } + ] } }, "/bridges/bridgedaystats/{timestamp}/{chain}": { @@ -4214,7 +4567,19 @@ } } }, - "x-api-plan-only": true + "x-api-plan-only": true, + "x-codeSamples": [ + { + "lang": "javascript", + "label": "JavaScript SDK", + "source": "const result = await client.bridges.getDayStats(1704067200, '')" + }, + { + "lang": "python", + "label": "Python SDK", + "source": "result = client.bridges.getDayStats(1704067200, '')" + } + ] } }, "/bridges/transactions/{id}": { @@ -4696,7 +5061,19 @@ } } }, - "x-api-plan-only": true + "x-api-plan-only": true, + "x-codeSamples": [ + { + "lang": "javascript", + "label": "JavaScript SDK", + "source": "const result = await client.bridges.getTransactions(1)" + }, + { + "lang": "python", + "label": "Python SDK", + "source": "result = client.bridges.getTransactions('')" + } + ] } }, "/usage/APIKEY": { @@ -4713,7 +5090,19 @@ "description": "credits left" } }, - "x-api-plan-only": true + "x-api-plan-only": true, + "x-codeSamples": [ + { + "lang": "javascript", + "label": "JavaScript SDK", + "source": "const result = await proClient.account.getUsage()" + }, + { + "lang": "python", + "label": "Python SDK", + "source": "result = pro_client.account.getUsage()" + } + ] } }, "/api/protocols": { @@ -4781,7 +5170,19 @@ } } } - } + }, + "x-codeSamples": [ + { + "lang": "javascript", + "label": "JavaScript SDK", + "source": "const result = await client.tvl.getProtocols()" + }, + { + "lang": "python", + "label": "Python SDK", + "source": "result = client.tvl.getProtocols()" + } + ] } }, "/api/protocol/{protocol}": { @@ -4895,7 +5296,19 @@ "404": { "description": "Protocol not found" } - } + }, + "x-codeSamples": [ + { + "lang": "javascript", + "label": "JavaScript SDK", + "source": "const result = await client.tvl.getProtocol('')" + }, + { + "lang": "python", + "label": "Python SDK", + "source": "result = client.tvl.getProtocol('')" + } + ] } }, "/api/v2/historicalChainTvl": { @@ -4928,7 +5341,19 @@ } } } - } + }, + "x-codeSamples": [ + { + "lang": "javascript", + "label": "JavaScript SDK", + "source": "const result = await client.tvl.getHistoricalChainTvl()" + }, + { + "lang": "python", + "label": "Python SDK", + "source": "result = client.tvl.getHistoricalChainTvl()" + } + ] } }, "/api/v2/historicalChainTvl/{chain}": { @@ -4976,7 +5401,19 @@ "404": { "description": "Chain not found" } - } + }, + "x-codeSamples": [ + { + "lang": "javascript", + "label": "JavaScript SDK", + "source": "const result = await client.tvl.getHistoricalChainTvl('')" + }, + { + "lang": "python", + "label": "Python SDK", + "source": "result = client.tvl.getHistoricalChainTvl()" + } + ] } }, "/api/tvl/{protocol}": { @@ -5012,7 +5449,19 @@ "404": { "description": "Protocol not found" } - } + }, + "x-codeSamples": [ + { + "lang": "javascript", + "label": "JavaScript SDK", + "source": "const result = await client.tvl.getTvl('')" + }, + { + "lang": "python", + "label": "Python SDK", + "source": "result = client.tvl.getTvl('')" + } + ] } }, "/api/v2/chains": { @@ -5069,7 +5518,19 @@ } } } - } + }, + "x-codeSamples": [ + { + "lang": "javascript", + "label": "JavaScript SDK", + "source": "const result = await client.tvl.getChains()" + }, + { + "lang": "python", + "label": "Python SDK", + "source": "result = client.tvl.getChains()" + } + ] } }, "/coins/prices/current/{coins}": { @@ -5141,7 +5602,19 @@ "502": { "description": "Internal error" } - } + }, + "x-codeSamples": [ + { + "lang": "javascript", + "label": "JavaScript SDK", + "source": "const result = await client.prices.getCurrentPrices([''])" + }, + { + "lang": "python", + "label": "Python SDK", + "source": "result = client.prices.getCurrentPrices([''])" + } + ] } }, "/coins/prices/historical/{timestamp}/{coins}": { @@ -5223,7 +5696,19 @@ "502": { "description": "Internal error" } - } + }, + "x-codeSamples": [ + { + "lang": "javascript", + "label": "JavaScript SDK", + "source": "const result = await client.prices.getHistoricalPrices(1704067200, [''])" + }, + { + "lang": "python", + "label": "Python SDK", + "source": "result = client.prices.getHistoricalPrices(1704067200, [''])" + } + ] } }, "/coins/batchHistorical": { @@ -5303,7 +5788,19 @@ "502": { "description": "Internal error" } - } + }, + "x-codeSamples": [ + { + "lang": "javascript", + "label": "JavaScript SDK", + "source": "const result = await client.prices.getBatchHistoricalPrices({ '': [1704067200] })" + }, + { + "lang": "python", + "label": "Python SDK", + "source": "result = client.prices.getBatchHistoricalPrices([''], '')" + } + ] } }, "/coins/chart/{coins}": { @@ -5427,7 +5924,19 @@ "502": { "description": "Internal error" } - } + }, + "x-codeSamples": [ + { + "lang": "javascript", + "label": "JavaScript SDK", + "source": "const result = await client.prices.getChart([''])" + }, + { + "lang": "python", + "label": "Python SDK", + "source": "result = client.prices.getChart([''])" + } + ] } }, "/coins/percentage/{coins}": { @@ -5502,7 +6011,19 @@ "502": { "description": "Internal error" } - } + }, + "x-codeSamples": [ + { + "lang": "javascript", + "label": "JavaScript SDK", + "source": "const result = await client.prices.getPercentageChange([''])" + }, + { + "lang": "python", + "label": "Python SDK", + "source": "result = client.prices.getPercentageChange([''])" + } + ] } }, "/coins/prices/first/{coins}": { @@ -5559,7 +6080,19 @@ "502": { "description": "Internal error" } - } + }, + "x-codeSamples": [ + { + "lang": "javascript", + "label": "JavaScript SDK", + "source": "const result = await client.prices.getFirstPrices([''])" + }, + { + "lang": "python", + "label": "Python SDK", + "source": "result = client.prices.getFirstPrices([''])" + } + ] } }, "/coins/block/{chain}/{timestamp}": { @@ -5615,7 +6148,19 @@ "400": { "description": "Invalid chain or timestamp provided" } - } + }, + "x-codeSamples": [ + { + "lang": "javascript", + "label": "JavaScript SDK", + "source": "const result = await client.prices.getBlockAtTimestamp('', 1704067200)" + }, + { + "lang": "python", + "label": "Python SDK", + "source": "result = client.prices.getBlockAtTimestamp('', 1704067200)" + } + ] } }, "/stablecoins/stablecoins": { @@ -5712,7 +6257,19 @@ } } } - } + }, + "x-codeSamples": [ + { + "lang": "javascript", + "label": "JavaScript SDK", + "source": "const result = await client.stablecoins.getStablecoins()" + }, + { + "lang": "python", + "label": "Python SDK", + "source": "result = client.stablecoins.getStablecoins()" + } + ] } }, "/stablecoins/stablecoincharts/all": { @@ -5760,7 +6317,19 @@ } } } - } + }, + "x-codeSamples": [ + { + "lang": "javascript", + "label": "JavaScript SDK", + "source": "const result = await client.stablecoins.getAllCharts()" + }, + { + "lang": "python", + "label": "Python SDK", + "source": "result = client.stablecoins.getAllCharts()" + } + ] } }, "/stablecoins/stablecoincharts/{chain}": { @@ -5818,7 +6387,19 @@ } } } - } + }, + "x-codeSamples": [ + { + "lang": "javascript", + "label": "JavaScript SDK", + "source": "const result = await client.stablecoins.getChartsByChain('')" + }, + { + "lang": "python", + "label": "Python SDK", + "source": "result = client.stablecoins.getChartsByChain('')" + } + ] } }, "/stablecoins/stablecoin/{asset}": { @@ -5897,7 +6478,19 @@ } } } - } + }, + "x-codeSamples": [ + { + "lang": "javascript", + "label": "JavaScript SDK", + "source": "const result = await client.stablecoins.getStablecoin('')" + }, + { + "lang": "python", + "label": "Python SDK", + "source": "result = client.stablecoins.getStablecoin('')" + } + ] } }, "/stablecoins/stablecoinchains": { @@ -5933,7 +6526,19 @@ } } } - } + }, + "x-codeSamples": [ + { + "lang": "javascript", + "label": "JavaScript SDK", + "source": "const result = await client.stablecoins.getChains()" + }, + { + "lang": "python", + "label": "Python SDK", + "source": "result = client.stablecoins.getChains()" + } + ] } }, "/stablecoins/stablecoinprices": { @@ -5971,7 +6576,19 @@ } } } - } + }, + "x-codeSamples": [ + { + "lang": "javascript", + "label": "JavaScript SDK", + "source": "const result = await client.stablecoins.getPrices()" + }, + { + "lang": "python", + "label": "Python SDK", + "source": "result = client.stablecoins.getPrices()" + } + ] } }, "/api/overview/dexs": { @@ -6076,7 +6693,19 @@ } } } - } + }, + "x-codeSamples": [ + { + "lang": "javascript", + "label": "JavaScript SDK", + "source": "const result = await client.volumes.getDexOverview()" + }, + { + "lang": "python", + "label": "Python SDK", + "source": "result = client.volumes.getDexOverview()" + } + ] } }, "/api/overview/dexs/{chain}": { @@ -6155,7 +6784,19 @@ } } } - } + }, + "x-codeSamples": [ + { + "lang": "javascript", + "label": "JavaScript SDK", + "source": "const result = await client.volumes.getDexOverviewByChain('')" + }, + { + "lang": "python", + "label": "Python SDK", + "source": "result = client.volumes.getDexOverviewByChain('')" + } + ] } }, "/api/summary/dexs/{protocol}": { @@ -6246,7 +6887,19 @@ } } } - } + }, + "x-codeSamples": [ + { + "lang": "javascript", + "label": "JavaScript SDK", + "source": "const result = await client.volumes.getDexSummary('')" + }, + { + "lang": "python", + "label": "Python SDK", + "source": "result = client.volumes.getDexSummary('')" + } + ] } }, "/api/overview/options": { @@ -6326,7 +6979,19 @@ } } } - } + }, + "x-codeSamples": [ + { + "lang": "javascript", + "label": "JavaScript SDK", + "source": "const result = await client.volumes.getOptionsOverview()" + }, + { + "lang": "python", + "label": "Python SDK", + "source": "result = client.volumes.getOptionsOverview()" + } + ] } }, "/api/overview/options/{chain}": { @@ -6745,7 +7410,19 @@ } } } - } + }, + "x-codeSamples": [ + { + "lang": "javascript", + "label": "JavaScript SDK", + "source": "const result = await client.volumes.getOptionsOverviewByChain('')" + }, + { + "lang": "python", + "label": "Python SDK", + "source": "result = client.volumes.getOptionsOverviewByChain('')" + } + ] } }, "/api/summary/options/{protocol}": { @@ -7060,7 +7737,19 @@ } } } - } + }, + "x-codeSamples": [ + { + "lang": "javascript", + "label": "JavaScript SDK", + "source": "const result = await client.volumes.getOptionsSummary('')" + }, + { + "lang": "python", + "label": "Python SDK", + "source": "result = client.volumes.getOptionsSummary('')" + } + ] } }, "/api/overview/open-interest": { @@ -7269,7 +7958,19 @@ } } } - } + }, + "x-codeSamples": [ + { + "lang": "javascript", + "label": "JavaScript SDK", + "source": "const result = await client.fees.getOverview()" + }, + { + "lang": "python", + "label": "Python SDK", + "source": "result = client.fees.getOverview()" + } + ] } }, "/api/overview/fees/{chain}": { @@ -7383,7 +8084,19 @@ } } } - } + }, + "x-codeSamples": [ + { + "lang": "javascript", + "label": "JavaScript SDK", + "source": "const result = await client.fees.getOverviewByChain('')" + }, + { + "lang": "python", + "label": "Python SDK", + "source": "result = client.fees.getOverviewByChain('')" + } + ] } }, "/api/summary/fees/{protocol}": { @@ -7688,7 +8401,19 @@ } } } - } + }, + "x-codeSamples": [ + { + "lang": "javascript", + "label": "JavaScript SDK", + "source": "const result = await client.fees.getSummary('')" + }, + { + "lang": "python", + "label": "Python SDK", + "source": "result = client.fees.getSummary('')" + } + ] } }, "/dat/institutions": { @@ -7978,7 +8703,19 @@ } } } - } + }, + "x-codeSamples": [ + { + "lang": "javascript", + "label": "JavaScript SDK", + "source": "const result = await proClient.dat.getInstitutions()" + }, + { + "lang": "python", + "label": "Python SDK", + "source": "result = pro_client.dat.getInstitutions()" + } + ] } }, "/dat/institutions/{symbol}": { @@ -8328,7 +9065,19 @@ } } } - } + }, + "x-codeSamples": [ + { + "lang": "javascript", + "label": "JavaScript SDK", + "source": "const result = await proClient.dat.getInstitution('MSTR')" + }, + { + "lang": "python", + "label": "Python SDK", + "source": "result = pro_client.dat.getInstitution('')" + } + ] } } } diff --git a/packages/api-reference/src/v2/blocks/scalar-request-example-block/components/RequestExample.vue b/packages/api-reference/src/v2/blocks/scalar-request-example-block/components/RequestExample.vue index 2dbca96cba8..3efc0c3ea5f 100644 --- a/packages/api-reference/src/v2/blocks/scalar-request-example-block/components/RequestExample.vue +++ b/packages/api-reference/src/v2/blocks/scalar-request-example-block/components/RequestExample.vue @@ -173,16 +173,12 @@ const localSelectedClient = ref( findClient(clients.value, selectedClient), ) -/** If the globally selected client changes we can update the local one */ -watch( - () => selectedClient, - (newClient) => { - const client = findClient(clients.value, newClient) - if (client) { - localSelectedClient.value = client - } - }, -) +watch([() => selectedClient, clients], ([newClient]) => { + const client = findClient(clients.value, newClient) + if (client) { + localSelectedClient.value = client + } +}) /** Generate the code snippet for the selected example */ const generatedCode = computed(() => { diff --git a/packages/api-reference/src/v2/blocks/scalar-request-example-block/helpers/find-client.ts b/packages/api-reference/src/v2/blocks/scalar-request-example-block/helpers/find-client.ts index 252927a27e3..306e755eb6b 100644 --- a/packages/api-reference/src/v2/blocks/scalar-request-example-block/helpers/find-client.ts +++ b/packages/api-reference/src/v2/blocks/scalar-request-example-block/helpers/find-client.ts @@ -2,6 +2,33 @@ import type { ClientOption, ClientOptionGroup } from '@/v2/blocks/scalar-request import { AVAILABLE_CLIENTS, type AvailableClients } from '@scalar/snippetz' const DEFAULT_CLIENT = 'shell/curl' +const TARGET_LANG_ALIASES: Record = { + js: ['js', 'javascript'], + javascript: ['js', 'javascript'], + node: ['node'], + python: ['python'], + ruby: ['ruby'], + php: ['php'], + shell: ['shell', 'curl'], +} + +const findCustomByTarget = (clientGroups: ClientOptionGroup[], targetKey: string) => { + const aliases = TARGET_LANG_ALIASES[targetKey] ?? [targetKey] + const normalizedAliases = aliases.map((alias) => alias.toLowerCase()) + for (const group of clientGroups) { + const option = group.options.find((candidate) => { + if (!candidate.id.startsWith('custom/')) { + return false + } + const lang = `${candidate.lang ?? ''}`.toLowerCase() + return normalizedAliases.includes(lang) + }) + if (option) { + return option + } + } + return undefined +} /** Type guard to check if a string is a valid client id */ export const isClient = (id: any): id is AvailableClients[number] => AVAILABLE_CLIENTS.includes(id) @@ -48,6 +75,11 @@ export const findClient = ( // Client ID is passed in if (clientId) { + const targetKey = clientId.split('/')[0] + const customOption = findCustomByTarget(clientGroups, targetKey) + if (customOption) { + return customOption + } for (const group of clientGroups) { const option = group.options.find((option) => option.id === clientId) if (option) { diff --git a/scripts/defillama-python-sdk-snippets.mjs b/scripts/defillama-python-sdk-snippets.mjs new file mode 100644 index 00000000000..1e4c652d245 --- /dev/null +++ b/scripts/defillama-python-sdk-snippets.mjs @@ -0,0 +1,193 @@ +import { readFile, writeFile } from 'node:fs/promises' +import { resolve } from 'node:path' + +const sdkSource = await readFile(resolve('sdks/python_sdk.xml'), 'utf8') + +const moduleRegex = /([\s\S]*?)<\/file>/g +const pathMappings = new Map() + +const variableAliases = new Map([ + ['coins_param', 'coins'], + ['start_timestamp', 'timestamp'], + ['api_key', 'APIKEY'], + ['bridge_id', 'id'], +]) + +const normalizeVariableName = (name) => variableAliases.get(name) ?? name + +const normalizeFStringPath = (value) => { + const withoutQuote = value.replace(/\{quote\(([^)]+)\)\}/g, (_, name) => `{${normalizeVariableName(name)}}`) + return withoutQuote.replace(/\{([a-zA-Z_][a-zA-Z0-9_]*)\}/g, (_, name) => `{${normalizeVariableName(name)}}`) +} + +const signatureToRequiredParams = (signature) => { + const start = signature.indexOf('(') + const end = signature.lastIndexOf(')') + if (start === -1 || end === -1 || end <= start) { + return [] + } + const paramsSection = signature.slice(start + 1, end) + const parts = paramsSection + .split(',') + .map((part) => part.trim()) + .filter(Boolean) + return parts + .filter((part) => !part.startsWith('self')) + .filter((part) => !part.includes('=')) + .map((part) => part.split(':')[0].trim()) +} + +const placeholderByParam = { + protocol: "''", + chain: "''", + coins: "['']", + timestamp: '1704067200', + start_timestamp: '1704067200', + end_timestamp: '1704153600', + pool: "''", + symbol: "''", + asset: "''", + id: '1', + period: "'30'", + token: "''", +} + +const buildArgs = (params) => params.map((param) => placeholderByParam[param] ?? `'<${param}>'`) + +const extractMethodMappings = (moduleName, content) => { + const lines = content.split('\n') + const mappings = [] + const indices = [] + lines.forEach((line, index) => { + if (/^\s*def\s+\w+\s*\(/.test(line)) { + indices.push(index) + } + }) + + indices.forEach((startIndex, index) => { + const endIndex = indices[index + 1] ?? lines.length + const blockLines = lines.slice(startIndex, endIndex) + const block = blockLines.join('\n') + const signatureLines = [] + for (const line of blockLines) { + signatureLines.push(line) + if (line.trim().endsWith(':') && line.includes(')')) { + break + } + } + const signature = signatureLines.join(' ') + const methodMatch = signature.match(/def\s+(\w+)\s*\(/) + if (!methodMatch) { + return + } + const methodName = methodMatch[1] + const requiredParams = signatureToRequiredParams(signature) + const args = buildArgs(requiredParams) + const requiresAuth = /requires_auth=True/.test(block) + const getMatches = [...block.matchAll(/self\._client\.get\(\s*(f?)(["'])([\s\S]*?)\2/g)] + if (!getMatches.length) { + return + } + getMatches.forEach((match) => { + const isFString = match[1] === 'f' + const rawPath = match[3] + const path = isFString ? normalizeFStringPath(rawPath) : rawPath + mappings.push({ + path, + module: moduleName, + method: methodName, + args, + requiresAuth, + }) + }) + }) + + return mappings +} + +for (const match of sdkSource.matchAll(moduleRegex)) { + const moduleFile = match[1] + const content = match[2] + const moduleName = moduleFile.replace('.py', '') + const mappings = extractMethodMappings(moduleName, content) + mappings.forEach((mapping) => { + if (!pathMappings.has(mapping.path)) { + pathMappings.set(mapping.path, mapping) + } + }) +} + +const overviewMapping = pathMappings.get('/overview') +if (overviewMapping && !pathMappings.has('/snapshot')) { + pathMappings.set('/snapshot', overviewMapping) +} +const historyMapping = pathMappings.get('/history') +if (historyMapping && !pathMappings.has('/flows')) { + pathMappings.set('/flows', historyMapping) +} + +pathMappings.set('/usage/APIKEY', { + path: '/usage/APIKEY', + module: 'account', + method: 'getUsage', + args: [], + requiresAuth: true, +}) + +const prefixes = ['/api', '/coins', '/stablecoins', '/bridges', '/yields', '/etfs', '/fdv', '/dat'] + +const resolveMapping = (path) => { + if (pathMappings.has(path)) { + return pathMappings.get(path) + } + for (const prefix of prefixes) { + if (path.startsWith(`${prefix}/`)) { + const basePath = path.slice(prefix.length) + if (pathMappings.has(basePath)) { + return pathMappings.get(basePath) + } + } + } + return null +} + +const buildSnippet = (mapping) => { + const clientName = mapping.requiresAuth ? 'pro_client' : 'client' + const args = mapping.args.length ? mapping.args.join(', ') : '' + return `result = ${clientName}.${mapping.module}.${mapping.method}(${args})` +} + +const updateSpec = (spec, filePath) => { + const missing = [] + for (const [path, methods] of Object.entries(spec.paths || {})) { + for (const [method, operation] of Object.entries(methods)) { + const mapping = resolveMapping(path) + if (!mapping) { + missing.push(`${method.toUpperCase()} ${path}`) + continue + } + const existingSamples = Array.isArray(operation['x-codeSamples']) ? operation['x-codeSamples'] : [] + const nextSamples = existingSamples.filter((sample) => sample?.lang !== 'python') + nextSamples.push({ + lang: 'python', + label: 'Python SDK', + source: buildSnippet(mapping), + }) + operation['x-codeSamples'] = nextSamples + } + } + if (missing.length) { + console.log(`${filePath}: ${missing.length} unmapped operations`) + missing.forEach((entry) => console.log(`${filePath}: ${entry}`)) + } else { + console.log(`${filePath}: all operations mapped`) + } +} + +const files = [resolve('defillama-openapi-free.json'), resolve('defillama-openapi-pro.json')] + +for (const filePath of files) { + const spec = JSON.parse(await readFile(filePath, 'utf8')) + updateSpec(spec, filePath) + await writeFile(filePath, `${JSON.stringify(spec, null, 2)}\n`) +} diff --git a/scripts/defillama-sdk-snippets.mjs b/scripts/defillama-sdk-snippets.mjs new file mode 100644 index 00000000000..f93a08ef63f --- /dev/null +++ b/scripts/defillama-sdk-snippets.mjs @@ -0,0 +1,134 @@ +import { readFile, writeFile } from 'node:fs/promises' +import { resolve } from 'node:path' + +const mapEntry = (module, method, args = [], requiresAuth = false) => ({ + module, + method, + args, + requiresAuth, +}) + +const baseMappings = new Map([ + ['/protocols', mapEntry('tvl', 'getProtocols')], + ['/protocol/{protocol}', mapEntry('tvl', 'getProtocol', ["''"])], + ['/v2/historicalChainTvl', mapEntry('tvl', 'getHistoricalChainTvl')], + ['/v2/historicalChainTvl/{chain}', mapEntry('tvl', 'getHistoricalChainTvl', ["''"])], + ['/tvl/{protocol}', mapEntry('tvl', 'getTvl', ["''"])], + ['/v2/chains', mapEntry('tvl', 'getChains')], + ['/tokenProtocols/{symbol}', mapEntry('tvl', 'getTokenProtocols', ["''"], true)], + [ + '/inflows/{protocol}/{timestamp}', + mapEntry('tvl', 'getInflows', ["''", '1704067200', '1704153600'], true), + ], + ['/chainAssets', mapEntry('tvl', 'getChainAssets', [], true)], + ['/prices/current/{coins}', mapEntry('prices', 'getCurrentPrices', ["['']"])], + ['/prices/historical/{timestamp}/{coins}', mapEntry('prices', 'getHistoricalPrices', ['1704067200', "['']"])], + ['/batchHistorical', mapEntry('prices', 'getBatchHistoricalPrices', ["{ '': [1704067200] }"])], + ['/chart/{coins}', mapEntry('prices', 'getChart', ["['']"])], + ['/percentage/{coins}', mapEntry('prices', 'getPercentageChange', ["['']"])], + ['/prices/first/{coins}', mapEntry('prices', 'getFirstPrices', ["['']"])], + ['/block/{chain}/{timestamp}', mapEntry('prices', 'getBlockAtTimestamp', ["''", '1704067200'])], + ['/stablecoins', mapEntry('stablecoins', 'getStablecoins')], + ['/stablecoincharts/all', mapEntry('stablecoins', 'getAllCharts')], + ['/stablecoincharts/{chain}', mapEntry('stablecoins', 'getChartsByChain', ["''"])], + ['/stablecoin/{asset}', mapEntry('stablecoins', 'getStablecoin', ["''"])], + ['/stablecoinchains', mapEntry('stablecoins', 'getChains')], + ['/stablecoinprices', mapEntry('stablecoins', 'getPrices')], + ['/stablecoindominance/{chain}', mapEntry('stablecoins', 'getDominance', ["''"], true)], + ['/pools', mapEntry('yields', 'getPools', [], true)], + ['/poolsOld', mapEntry('yields', 'getPoolsOld', [], true)], + ['/chart/{pool}', mapEntry('yields', 'getPoolChart', ["''"], true)], + ['/poolsBorrow', mapEntry('yields', 'getBorrowPools', [], true)], + ['/chartLendBorrow/{pool}', mapEntry('yields', 'getLendBorrowChart', ["''"], true)], + ['/perps', mapEntry('yields', 'getPerps', [], true)], + ['/lsdRates', mapEntry('yields', 'getLsdRates', [], true)], + ['/overview/dexs', mapEntry('volumes', 'getDexOverview')], + ['/overview/dexs/{chain}', mapEntry('volumes', 'getDexOverviewByChain', ["''"])], + ['/summary/dexs/{protocol}', mapEntry('volumes', 'getDexSummary', ["''"])], + ['/overview/options', mapEntry('volumes', 'getOptionsOverview')], + ['/overview/options/{chain}', mapEntry('volumes', 'getOptionsOverviewByChain', ["''"])], + ['/summary/options/{protocol}', mapEntry('volumes', 'getOptionsSummary', ["''"])], + ['/overview/derivatives', mapEntry('volumes', 'getDerivativesOverview', [], true)], + ['/summary/derivatives/{protocol}', mapEntry('volumes', 'getDerivativesSummary', ["''"], true)], + ['/overview/fees', mapEntry('fees', 'getOverview')], + ['/overview/fees/{chain}', mapEntry('fees', 'getOverviewByChain', ["''"])], + ['/summary/fees/{protocol}', mapEntry('fees', 'getSummary', ["''"])], + ['/emissions', mapEntry('emissions', 'getAll', [], true)], + ['/emission/{protocol}', mapEntry('emissions', 'getByProtocol', ["''"], true)], + ['/categories', mapEntry('ecosystem', 'getCategories', [], true)], + ['/forks', mapEntry('ecosystem', 'getForks', [], true)], + ['/oracles', mapEntry('ecosystem', 'getOracles', [], true)], + ['/hacks', mapEntry('ecosystem', 'getHacks', [], true)], + ['/raises', mapEntry('ecosystem', 'getRaises', [], true)], + ['/treasuries', mapEntry('ecosystem', 'getTreasuries', [], true)], + ['/entities', mapEntry('ecosystem', 'getEntities', [], true)], + ['/bridges', mapEntry('bridges', 'getAll')], + ['/bridge/{id}', mapEntry('bridges', 'getById', ['1'])], + ['/bridgevolume/{chain}', mapEntry('bridges', 'getVolumeByChain', ["''"])], + ['/bridgedaystats/{timestamp}/{chain}', mapEntry('bridges', 'getDayStats', ['1704067200', "''"])], + ['/transactions/{id}', mapEntry('bridges', 'getTransactions', ['1'])], + ['/snapshot', mapEntry('etfs', 'getOverview', [], true)], + ['/flows', mapEntry('etfs', 'getHistory', [], true)], + ['/performance/{period}', mapEntry('etfs', 'getFdvPerformance', ["'30'"], true)], + ['/institutions', mapEntry('dat', 'getInstitutions', [], true)], + ['/institutions/{symbol}', mapEntry('dat', 'getInstitution', ["'MSTR'"], true)], + ['/usage/APIKEY', mapEntry('account', 'getUsage', [], true)], +]) + +const prefixes = ['/api', '/coins', '/stablecoins', '/bridges', '/yields', '/etfs', '/fdv', '/dat'] + +const resolveMapping = (path) => { + if (baseMappings.has(path)) { + return baseMappings.get(path) + } + for (const prefix of prefixes) { + if (path.startsWith(`${prefix}/`)) { + const basePath = path.slice(prefix.length) + if (baseMappings.has(basePath)) { + return baseMappings.get(basePath) + } + } + } + return null +} + +const buildSnippet = (mapping) => { + const clientName = mapping.requiresAuth ? 'proClient' : 'client' + const args = mapping.args.length ? mapping.args.join(', ') : '' + return `const result = await ${clientName}.${mapping.module}.${mapping.method}(${args})` +} + +const updateSpec = (spec, filePath) => { + const missing = [] + for (const [path, methods] of Object.entries(spec.paths || {})) { + for (const [method, operation] of Object.entries(methods)) { + const mapping = resolveMapping(path) + if (!mapping) { + missing.push(`${method.toUpperCase()} ${path}`) + continue + } + const existingSamples = Array.isArray(operation['x-codeSamples']) ? operation['x-codeSamples'] : [] + const nextSamples = existingSamples.filter((sample) => sample?.lang !== 'javascript') + nextSamples.push({ + lang: 'javascript', + label: 'JavaScript SDK', + source: buildSnippet(mapping), + }) + operation['x-codeSamples'] = nextSamples + } + } + if (missing.length) { + console.log(`${filePath}: ${missing.length} unmapped operations`) + missing.forEach((entry) => console.log(`${filePath}: ${entry}`)) + } else { + console.log(`${filePath}: all operations mapped`) + } +} + +const files = [resolve('defillama-openapi-free.json'), resolve('defillama-openapi-pro.json')] + +for (const filePath of files) { + const spec = JSON.parse(await readFile(filePath, 'utf8')) + updateSpec(spec, filePath) + await writeFile(filePath, `${JSON.stringify(spec, null, 2)}\n`) +}