@cryptodevops/n8n-nodes-defillama
Version:
Custom n8n node for DefiLlama API - Access DeFi protocols data, TVL, yields, and chain analytics
1,018 lines (1,017 loc) • 67.3 kB
JavaScript
"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.DefiLlama = void 0;
const n8n_workflow_1 = require("n8n-workflow");
const axios_1 = __importDefault(require("axios"));
class DefiLlama {
constructor() {
this.description = {
displayName: 'DefiLlama',
name: 'defiLlama',
icon: 'file:defillama.svg',
group: ['input'],
version: 1,
subtitle: '={{$parameter["operation"] + ": " + $parameter["resource"]}}',
description: 'Access DeFi protocols data using the DefiLlama API',
defaults: {
name: 'DefiLlama',
},
inputs: ['main'],
outputs: ['main'],
usableAsTool: true,
credentials: [
{
name: 'defiLlamaApi',
required: false,
},
],
requestDefaults: {
baseURL: 'https://api.llama.fi',
headers: {
Accept: 'application/json',
'Content-Type': 'application/json',
},
},
properties: [
{
displayName: 'Resource',
name: 'resource',
type: 'options',
noDataExpression: true,
options: [
{
name: 'Bridge',
value: 'bridges',
},
{
name: 'Category',
value: 'categories',
},
{
name: 'Chain',
value: 'chain',
},
{
name: 'DEXs & Volume',
value: 'dexs',
},
{
name: 'Fees & Revenue',
value: 'fees',
},
{
name: 'Hack',
value: 'hacks',
},
{
name: 'Oracle',
value: 'oracles',
},
{
name: 'Protocol',
value: 'protocol',
},
{
name: 'Raise',
value: 'raises',
},
{
name: 'Stablecoin',
value: 'stablecoins',
},
{
name: 'TVL',
value: 'tvl',
},
{
name: 'Yield',
value: 'yield',
},
],
default: 'protocol',
},
{
displayName: 'Operation',
name: 'operation',
type: 'options',
noDataExpression: true,
displayOptions: {
show: {
resource: ['protocol'],
},
},
options: [
{
name: 'List All Protocols',
value: 'listProtocols',
description: 'Get all DeFi protocols with their TVL data',
action: 'Get all de fi protocols with their tvl data',
},
{
name: 'Get Protocol Details',
value: 'getProtocol',
description: 'Get detailed information about a specific protocol',
action: 'Get detailed information about a specific protocol',
},
{
name: 'Get Protocol TVL',
value: 'getProtocolTvl',
description: 'Get current TVL of a specific protocol',
action: 'Get current TVL of a specific protocol',
},
],
default: 'listProtocols',
},
{
displayName: 'Operation',
name: 'operation',
type: 'options',
noDataExpression: true,
displayOptions: {
show: {
resource: ['chain'],
},
},
options: [
{
name: 'List All Chains',
value: 'listChains',
description: 'Get all blockchain chains with their TVL data',
action: 'Get all blockchain chains with their TVL data',
},
{
name: 'Get Chain TVL',
value: 'getChainTvl',
description: 'Get historical TVL data for a specific chain',
action: 'Get historical TVL data for a specific chain',
},
],
default: 'listChains',
},
{
displayName: 'Operation',
name: 'operation',
type: 'options',
noDataExpression: true,
displayOptions: {
show: {
resource: ['tvl'],
},
},
options: [
{
name: 'Get Historical TVL',
value: 'getHistoricalTvl',
description: 'Get historical TVL data for all chains combined',
action: 'Get historical TVL data for all chains combined',
},
],
default: 'getHistoricalTvl',
},
{
displayName: 'Operation',
name: 'operation',
type: 'options',
noDataExpression: true,
displayOptions: {
show: {
resource: ['yield'],
},
},
options: [
{
name: 'Get Yield Pools',
value: 'getYieldPools',
description: 'Get yield farming opportunities across protocols',
action: 'Get yield farming opportunities across protocols',
},
],
default: 'getYieldPools',
},
{
displayName: 'Operation',
name: 'operation',
type: 'options',
noDataExpression: true,
displayOptions: {
show: {
resource: ['fees'],
},
},
options: [
{
name: 'Get Fees Overview',
value: 'getFeesOverview',
description: 'Get fees and revenue overview across all protocols',
action: 'Get fees and revenue overview across all protocols',
},
{
name: 'Get Protocol Fees',
value: 'getProtocolFees',
description: 'Get fees and revenue data for a specific protocol',
action: 'Get fees and revenue data for a specific protocol',
},
],
default: 'getFeesOverview',
},
{
displayName: 'Operation',
name: 'operation',
type: 'options',
noDataExpression: true,
displayOptions: {
show: {
resource: ['stablecoins'],
},
},
options: [
{
name: 'List Stablecoins',
value: 'listStablecoins',
description: 'Get all stablecoins with market cap and other data',
action: 'Get all stablecoins with market cap and other data',
},
{
name: 'Get Stablecoin Charts',
value: 'getStablecoinCharts',
description: 'Get historical market cap charts for a specific stablecoin',
action: 'Get historical market cap charts for a specific stablecoin',
},
{
name: 'Get Stablecoin Prices',
value: 'getStablecoinPrices',
description: 'Get current prices for all stablecoins',
action: 'Get current prices for all stablecoins',
},
],
default: 'listStablecoins',
},
{
displayName: 'Operation',
name: 'operation',
type: 'options',
noDataExpression: true,
displayOptions: {
show: {
resource: ['dexs'],
},
},
options: [
{
name: 'Get DEXs Overview',
value: 'getDexsOverview',
description: 'Get trading volume overview across all DEXs',
action: 'Get trading volume overview across all de xs',
},
{
name: 'Get DEX Volume',
value: 'getDexVolume',
description: 'Get trading volume data for a specific DEX',
action: 'Get trading volume data for a specific DEX',
},
],
default: 'getDexsOverview',
},
{
displayName: 'Operation',
name: 'operation',
type: 'options',
noDataExpression: true,
displayOptions: {
show: {
resource: ['bridges'],
},
},
options: [
{
name: 'List Bridges',
value: 'listBridges',
description: 'Get all cross-chain bridges with volume data',
action: 'Get all cross chain bridges with volume data',
},
{
name: 'Get Bridge Volume',
value: 'getBridgeVolume',
description: 'Get volume data for a specific bridge',
action: 'Get volume data for a specific bridge',
},
],
default: 'listBridges',
},
{
displayName: 'Operation',
name: 'operation',
type: 'options',
noDataExpression: true,
displayOptions: {
show: {
resource: ['oracles'],
},
},
options: [
{
name: 'List Oracles',
value: 'listOracles',
description: 'Get all oracle protocols with TVS (Total Value Secured)',
action: 'Get all oracle protocols with tvs total value secured',
},
],
default: 'listOracles',
},
{
displayName: 'Operation',
name: 'operation',
type: 'options',
noDataExpression: true,
displayOptions: {
show: {
resource: ['categories'],
},
},
options: [
{
name: 'List Categories',
value: 'listCategories',
description: 'Get all DeFi protocol categories',
action: 'Get all de fi protocol categories',
},
],
default: 'listCategories',
},
{
displayName: 'Operation',
name: 'operation',
type: 'options',
noDataExpression: true,
displayOptions: {
show: {
resource: ['raises'],
},
},
options: [
{
name: 'List Raises',
value: 'listRaises',
description: 'Get funding rounds and investment data',
action: 'Get funding rounds and investment data',
},
],
default: 'listRaises',
},
{
displayName: 'Operation',
name: 'operation',
type: 'options',
noDataExpression: true,
displayOptions: {
show: {
resource: ['hacks'],
},
},
options: [
{
name: 'List Hacks',
value: 'listHacks',
description: 'Get DeFi security incidents and hack data',
action: 'Get de fi security incidents and hack data',
},
],
default: 'listHacks',
},
{
displayName: 'Protocol Slug',
name: 'protocolSlug',
type: 'string',
displayOptions: {
show: {
operation: ['getProtocol', 'getProtocolTvl', 'getProtocolFees'],
resource: ['protocol', 'fees'],
},
},
default: '',
placeholder: 'aave',
description: 'The protocol slug (e.g., aave, uniswap, curve)',
required: true,
},
{
displayName: 'Chain Slug',
name: 'chainSlug',
type: 'string',
displayOptions: {
show: {
operation: ['getChainTvl'],
resource: ['chain'],
},
},
default: '',
placeholder: 'ethereum',
description: 'The chain slug (e.g., ethereum, polygon, arbitrum)',
required: true,
},
{
displayName: 'Stablecoin ID',
name: 'stablecoinId',
type: 'string',
displayOptions: {
show: {
operation: ['getStablecoinCharts'],
resource: ['stablecoins'],
},
},
default: '',
placeholder: '1',
description: 'The stablecoin ID (e.g., 1 for Tether)',
required: true,
},
{
displayName: 'DEX Slug',
name: 'dexSlug',
type: 'string',
displayOptions: {
show: {
operation: ['getDexVolume'],
resource: ['dexs'],
},
},
default: '',
placeholder: 'uniswap',
description: 'The DEX slug (e.g., uniswap, sushiswap, curve)',
required: true,
},
{
displayName: 'Bridge ID',
name: 'bridgeId',
type: 'string',
displayOptions: {
show: {
operation: ['getBridgeVolume'],
resource: ['bridges'],
},
},
default: '',
placeholder: '1',
description: 'The bridge ID (e.g., 1 for Polygon PoS Bridge)',
required: true,
},
{
displayName: 'Additional Fields',
name: 'additionalFields',
type: 'collection',
placeholder: 'Add Field',
default: {},
options: [
{
displayName: 'Max Results',
name: 'maxResults',
type: 'number',
typeOptions: {
minValue: 1,
maxValue: 100,
},
default: 20,
description: 'Maximum number of results to return (1-100)',
},
{
displayName: 'Chain Filter',
name: 'chainFilter',
type: 'string',
displayOptions: {
show: {
'/resource': ['yield'],
},
},
default: '',
placeholder: 'ethereum,polygon',
description: 'Filter by specific chains (comma-separated)',
},
{
displayName: 'Min TVL',
name: 'minTvl',
type: 'number',
displayOptions: {
show: {
'/resource': ['protocol'],
'/operation': ['listProtocols'],
},
},
default: 0,
description: 'Minimum TVL threshold in USD',
},
{
displayName: 'Min APY',
name: 'minApy',
type: 'number',
displayOptions: {
show: {
'/resource': ['yield'],
},
},
default: 0,
description: 'Minimum APY percentage',
},
{
displayName: 'Stablecoin Only',
name: 'stablecoinOnly',
type: 'boolean',
displayOptions: {
show: {
'/resource': ['yield'],
},
},
default: false,
description: 'Whether to filter for stablecoin pools only',
},
{
displayName: 'AI Agent Mode',
name: 'aiMode',
type: 'boolean',
default: false,
description: 'Whether to optimize output format for AI agents (simplified and structured)',
},
{
displayName: 'Include Summary',
name: 'includeSummary',
type: 'boolean',
displayOptions: {
show: {
aiMode: [true],
},
},
default: true,
description: 'Whether to include a human-readable summary for AI agents',
},
{
displayName: 'Min Market Cap',
name: 'minMarketCap',
type: 'number',
displayOptions: {
show: {
'/resource': ['stablecoins'],
},
},
default: 0,
description: 'Minimum market cap threshold in USD for stablecoins',
},
{
displayName: 'Min Volume',
name: 'minVolume',
type: 'number',
displayOptions: {
show: {
'/resource': ['dexs', 'bridges'],
},
},
default: 0,
description: 'Minimum volume threshold in USD',
},
{
displayName: 'Min TVS',
name: 'minTvs',
type: 'number',
displayOptions: {
show: {
'/resource': ['oracles'],
},
},
default: 0,
description: 'Minimum Total Value Secured (TVS) threshold in USD for oracles',
},
{
displayName: 'Date Range',
name: 'dateRange',
type: 'options',
displayOptions: {
show: {
'/resource': ['fees', 'dexs', 'bridges'],
},
},
options: [
{
name: '24 Hours',
value: '24h',
},
{
name: '7 Days',
value: '7d',
},
{
name: '30 Days',
value: '30d',
},
],
default: '24h',
description: 'Time range for data aggregation',
},
{
displayName: 'Include Pegged Assets',
name: 'includePegged',
type: 'boolean',
displayOptions: {
show: {
'/resource': ['stablecoins'],
},
},
default: true,
description: 'Whether to include pegged assets in stablecoin results',
},
],
},
],
};
}
async execute() {
const items = this.getInputData();
const returnData = [];
const length = items.length;
const resource = this.getNodeParameter('resource', 0);
const operation = this.getNodeParameter('operation', 0);
for (let i = 0; i < length; i++) {
try {
const additionalFields = this.getNodeParameter('additionalFields', i);
// Get credentials if available (optional for DefiLlama)
let apiKey = '';
try {
const credentials = await this.getCredentials('defiLlamaApi');
if (credentials && credentials.apiKey) {
apiKey = credentials.apiKey;
}
}
catch (error) {
// API key is optional for most endpoints
}
let endpoint = '';
let responseData;
const headers = {
Accept: 'application/json',
'Content-Type': 'application/json',
};
// Add API key to headers if available
if (apiKey) {
headers['Authorization'] = `Bearer ${apiKey}`;
}
if (resource === 'protocol') {
if (operation === 'listProtocols') {
endpoint = 'protocols';
const response = await axios_1.default.get(`https://api.llama.fi/${endpoint}`, { headers });
responseData = response.data;
// Apply filters
if (additionalFields.minTvl && additionalFields.minTvl > 0) {
responseData = responseData.filter((protocol) => protocol.tvl >= additionalFields.minTvl);
}
// Limit results
const maxResults = additionalFields.maxResults || 20;
responseData = responseData.slice(0, maxResults);
}
else if (operation === 'getProtocol') {
const protocolSlug = this.getNodeParameter('protocolSlug', i);
endpoint = `protocol/${protocolSlug}`;
const response = await axios_1.default.get(`https://api.llama.fi/${endpoint}`, { headers });
responseData = response.data;
}
else if (operation === 'getProtocolTvl') {
const protocolSlug = this.getNodeParameter('protocolSlug', i);
endpoint = `tvl/${protocolSlug}`;
const response = await axios_1.default.get(`https://api.llama.fi/${endpoint}`, { headers });
responseData = { tvl: response.data, protocol: protocolSlug };
}
}
else if (resource === 'chain') {
if (operation === 'listChains') {
endpoint = 'chains';
const response = await axios_1.default.get(`https://api.llama.fi/${endpoint}`, { headers });
responseData = response.data;
// Limit results
const maxResults = additionalFields.maxResults || 20;
responseData = responseData.slice(0, maxResults);
}
else if (operation === 'getChainTvl') {
const chainSlug = this.getNodeParameter('chainSlug', i);
endpoint = `v2/historicalChainTvl/${chainSlug}`;
const response = await axios_1.default.get(`https://api.llama.fi/${endpoint}`, { headers });
responseData = response.data;
}
}
else if (resource === 'tvl') {
if (operation === 'getHistoricalTvl') {
endpoint = 'v2/historicalChainTvl';
const response = await axios_1.default.get(`https://api.llama.fi/${endpoint}`, { headers });
responseData = response.data;
}
}
else if (resource === 'yield') {
if (operation === 'getYieldPools') {
endpoint = 'pools';
const response = await axios_1.default.get(`https://yields.llama.fi/${endpoint}`, { headers });
responseData = response.data.data || response.data;
// Apply filters
if (additionalFields.chainFilter) {
const chains = additionalFields.chainFilter
.split(',')
.map((c) => c.trim().toLowerCase());
responseData = responseData.filter((pool) => { var _a; return chains.includes((_a = pool.chain) === null || _a === void 0 ? void 0 : _a.toLowerCase()); });
}
if (additionalFields.minApy && additionalFields.minApy > 0) {
responseData = responseData.filter((pool) => pool.apy >= additionalFields.minApy);
}
if (additionalFields.stablecoinOnly) {
responseData = responseData.filter((pool) => pool.stablecoin === true ||
(pool.symbol && pool.symbol.toLowerCase().includes('usd')));
}
// Limit results
const maxResults = additionalFields.maxResults || 20;
responseData = responseData.slice(0, maxResults);
}
}
else if (resource === 'fees') {
if (operation === 'getFeesOverview') {
endpoint = 'overview/fees?excludeTotalDataChart=true';
const response = await axios_1.default.get(`https://api.llama.fi/${endpoint}`, { headers });
responseData = response.data.protocols || response.data;
// Apply date range filter
const dateRange = additionalFields.dateRange;
if (dateRange && Array.isArray(responseData)) {
responseData = responseData.map((protocol) => {
const filteredProtocol = { ...protocol };
// Keep only the data for the selected date range
switch (dateRange) {
case '24h':
filteredProtocol.total = protocol.total24h;
filteredProtocol.revenue = protocol.revenue24h;
filteredProtocol.fees = protocol.fees24h;
break;
case '7d':
filteredProtocol.total = protocol.total7d;
filteredProtocol.revenue = protocol.revenue7d;
filteredProtocol.fees = protocol.fees7d;
break;
case '30d':
filteredProtocol.total = protocol.total30d;
filteredProtocol.revenue = protocol.revenue30d;
filteredProtocol.fees = protocol.fees30d;
break;
default:
// Keep all data if no specific range selected
break;
}
filteredProtocol.dateRange = dateRange;
return filteredProtocol;
});
}
// Apply filters
if (additionalFields.minVolume && additionalFields.minVolume > 0) {
responseData = responseData.filter((protocol) => (protocol.total || protocol.total24h) >= additionalFields.minVolume);
}
// Limit results
const maxResults = additionalFields.maxResults || 20;
if (Array.isArray(responseData)) {
responseData = responseData.slice(0, maxResults);
}
}
else if (operation === 'getProtocolFees') {
const protocolSlug = this.getNodeParameter('protocolSlug', i);
endpoint = `summary/fees/${protocolSlug}`;
const response = await axios_1.default.get(`https://api.llama.fi/${endpoint}`, { headers });
responseData = response.data;
// Apply date range filter for protocol fees
const dateRange = additionalFields.dateRange;
if (dateRange && responseData) {
const filteredData = { ...responseData };
switch (dateRange) {
case '24h':
filteredData.total = responseData.total24h;
filteredData.revenue = responseData.revenue24h;
filteredData.fees = responseData.fees24h;
break;
case '7d':
filteredData.total = responseData.total7d;
filteredData.revenue = responseData.revenue7d;
filteredData.fees = responseData.fees7d;
break;
case '30d':
filteredData.total = responseData.total30d;
filteredData.revenue = responseData.revenue30d;
filteredData.fees = responseData.fees30d;
break;
}
filteredData.dateRange = dateRange;
responseData = filteredData;
}
}
}
else if (resource === 'stablecoins') {
if (operation === 'listStablecoins') {
endpoint = 'stablecoins';
const response = await axios_1.default.get(`https://stablecoins.llama.fi/${endpoint}`, {
headers,
});
responseData = response.data.peggedAssets || response.data;
// Apply filters
if (additionalFields.minMarketCap && additionalFields.minMarketCap > 0) {
responseData = responseData.filter((stablecoin) => stablecoin.circulating &&
stablecoin.circulating.peggedUSD >= additionalFields.minMarketCap);
}
if (!additionalFields.includePegged) {
responseData = responseData.filter((stablecoin) => stablecoin.pegType !== 'peggedVAR');
}
// Limit results
const maxResults = additionalFields.maxResults || 20;
responseData = responseData.slice(0, maxResults);
}
else if (operation === 'getStablecoinCharts') {
const stablecoinId = this.getNodeParameter('stablecoinId', i);
endpoint = `stablecoincharts/all?stablecoin=${stablecoinId}`;
const response = await axios_1.default.get(`https://stablecoins.llama.fi/${endpoint}`, {
headers,
});
responseData = response.data;
}
else if (operation === 'getStablecoinPrices') {
endpoint = 'stablecoinprices';
const response = await axios_1.default.get(`https://stablecoins.llama.fi/${endpoint}`, {
headers,
});
responseData = response.data;
// Limit results
const maxResults = additionalFields.maxResults || 20;
if (Array.isArray(responseData)) {
responseData = responseData.slice(0, maxResults);
}
}
}
else if (resource === 'dexs') {
if (operation === 'getDexsOverview') {
endpoint = 'overview/dexs?excludeTotalDataChart=true';
const response = await axios_1.default.get(`https://api.llama.fi/${endpoint}`, { headers });
responseData = response.data.protocols || response.data;
// Apply date range filter
const dateRange = additionalFields.dateRange;
if (dateRange && Array.isArray(responseData)) {
responseData = responseData.map((dex) => {
const filteredDex = { ...dex };
// Keep only the data for the selected date range
switch (dateRange) {
case '24h':
filteredDex.totalVolume = dex.total24h;
filteredDex.change = dex.change_1d;
break;
case '7d':
filteredDex.totalVolume = dex.total7d;
filteredDex.change = dex.change_7d;
break;
case '30d':
filteredDex.totalVolume = dex.total30d;
filteredDex.change = dex.change_30d;
break;
default:
// Keep all data if no specific range selected
break;
}
filteredDex.dateRange = dateRange;
return filteredDex;
});
}
// Apply filters
if (additionalFields.minVolume && additionalFields.minVolume > 0) {
responseData = responseData.filter((dex) => (dex.totalVolume || dex.total24h) >= additionalFields.minVolume);
}
// Limit results
const maxResults = additionalFields.maxResults || 20;
if (Array.isArray(responseData)) {
responseData = responseData.slice(0, maxResults);
}
}
else if (operation === 'getDexVolume') {
const dexSlug = this.getNodeParameter('dexSlug', i);
endpoint = `summary/dexs/${dexSlug}`;
const response = await axios_1.default.get(`https://api.llama.fi/${endpoint}`, { headers });
responseData = response.data;
// Apply date range filter for DEX volume
const dateRange = additionalFields.dateRange;
if (dateRange && responseData) {
const filteredData = { ...responseData };
switch (dateRange) {
case '24h':
filteredData.totalVolume = responseData.total24h;
filteredData.change = responseData.change_1d;
break;
case '7d':
filteredData.totalVolume = responseData.total7d;
filteredData.change = responseData.change_7d;
break;
case '30d':
filteredData.totalVolume = responseData.total30d;
filteredData.change = responseData.change_30d;
break;
}
filteredData.dateRange = dateRange;
responseData = filteredData;
}
}
}
else if (resource === 'bridges') {
if (operation === 'listBridges') {
endpoint = 'bridges';
const response = await axios_1.default.get(`https://bridges.llama.fi/${endpoint}`, { headers });
responseData = response.data.bridges || response.data;
// Apply date range filter
const dateRange = additionalFields.dateRange;
if (dateRange && Array.isArray(responseData)) {
responseData = responseData.map((bridge) => {
const filteredBridge = { ...bridge };
// Keep only the data for the selected date range
switch (dateRange) {
case '24h':
filteredBridge.volume = bridge.volumePrevDay;
filteredBridge.volumeChange = bridge.volumePrev2Day ?
((bridge.volumePrevDay - bridge.volumePrev2Day) / bridge.volumePrev2Day * 100) : 0;
break;
case '7d':
filteredBridge.volume = bridge.volumePrevWeek;
filteredBridge.volumeChange = bridge.volumePrev2Week ?
((bridge.volumePrevWeek - bridge.volumePrev2Week) / bridge.volumePrev2Week * 100) : 0;
break;
case '30d':
filteredBridge.volume = bridge.volumePrevMonth;
filteredBridge.volumeChange = bridge.volumePrev2Month ?
((bridge.volumePrevMonth - bridge.volumePrev2Month) / bridge.volumePrev2Month * 100) : 0;
break;
default:
// Keep all data if no specific range selected
break;
}
filteredBridge.dateRange = dateRange;
return filteredBridge;
});
}
// Apply filters
if (additionalFields.minVolume && additionalFields.minVolume > 0) {
responseData = responseData.filter((bridge) => (bridge.volume || bridge.volumePrevDay) >= additionalFields.minVolume);
}
// Limit results
const maxResults = additionalFields.maxResults || 20;
responseData = responseData.slice(0, maxResults);
}
else if (operation === 'getBridgeVolume') {
const bridgeId = this.getNodeParameter('bridgeId', i);
endpoint = `bridgevolume/${bridgeId}`;
const response = await axios_1.default.get(`https://bridges.llama.fi/${endpoint}`, { headers });
responseData = response.data;
// Apply date range filter for bridge volume
const dateRange = additionalFields.dateRange;
if (dateRange && responseData) {
const filteredData = { ...responseData };
// For bridge volume, we might need to filter the historical data
if (responseData.volumeHistory && Array.isArray(responseData.volumeHistory)) {
const now = Date.now() / 1000;
let cutoffTime = now;
switch (dateRange) {
case '24h':
cutoffTime = now - (24 * 60 * 60);
break;
case '7d':
cutoffTime = now - (7 * 24 * 60 * 60);
break;
case '30d':
cutoffTime = now - (30 * 24 * 60 * 60);
break;
}
filteredData.volumeHistory = responseData.volumeHistory.filter((entry) => entry.date >= cutoffTime);
}
filteredData.dateRange = dateRange;
responseData = filteredData;
}
}
}
else if (resource === 'oracles') {
if (operation === 'listOracles') {
endpoint = 'oracles';
const response = await axios_1.default.get(`https://api.llama.fi/${endpoint}`, { headers });
responseData = response.data;
// Apply filters
if (additionalFields.minTvs && additionalFields.minTvs > 0) {
responseData = responseData.filter((oracle) => oracle.tvs >= additionalFields.minTvs);
}
// Limit results
const maxResults = additionalFields.maxResults || 20;
responseData = responseData.slice(0, maxResults);
}
}
else if (resource === 'categories') {
if (operation === 'listCategories') {
endpoint = 'categories';
const response = await axios_1.default.get(`https://api.llama.fi/${endpoint}`, { headers });
responseData = response.data;
// Limit results
const maxResults = additionalFields.maxResults || 20;
if (Array.isArray(responseData)) {
responseData = responseData.slice(0, maxResults);
}
}
}
else if (resource === 'raises') {
if (operation === 'listRaises') {
endpoint = 'raises';
const response = await axios_1.default.get(`https://api.llama.fi/${endpoint}`, { headers });