From 50c710b399f764b1ec3c2c78f635980752bb3c16 Mon Sep 17 00:00:00 2001 From: Javier Ortiz Date: Fri, 6 Jun 2025 02:42:02 +0200 Subject: [PATCH 1/3] feat(gt3) initial version --- src/adaptors/gt3/helpers.js | 237 ++++++++++++++++++++++++++++++++++++ src/adaptors/gt3/index.js | 155 +++++++++++++++++++++++ src/adaptors/gt3/queries.js | 174 ++++++++++++++++++++++++++ 3 files changed, 566 insertions(+) create mode 100644 src/adaptors/gt3/helpers.js create mode 100644 src/adaptors/gt3/index.js create mode 100644 src/adaptors/gt3/queries.js diff --git a/src/adaptors/gt3/helpers.js b/src/adaptors/gt3/helpers.js new file mode 100644 index 0000000000..139b67dcc0 --- /dev/null +++ b/src/adaptors/gt3/helpers.js @@ -0,0 +1,237 @@ +// Utilidades específicas para GT3 Finance +const utils = require('../utils'); + +// Usar superagent como fetch si fetch no está disponible +let fetch; +try { + fetch = globalThis.fetch; +} catch (e) { + const superagent = require('superagent'); + fetch = async (url, options) => { + const response = await superagent + .post(url) + .set(options.headers) + .send(JSON.parse(options.body)); + return { + ok: response.status < 400, + status: response.status, + json: async () => response.body + }; + }; +} + +// Configuración de la API +const GRAPHQL_ENDPOINT = 'https://backend.gt3.finance/graphql'; +const PROJECT_KEY = 'GT3'; + +const REQUEST_HEADERS = { + 'accept': '*/*', + 'content-type': 'application/json', + 'origin': 'https://dapp.gt3.finance', + 'referer': 'https://dapp.gt3.finance/', + 'x-project-key': PROJECT_KEY, + 'user-agent': 'Mozilla/5.0 (compatible; DeFiLlama/1.0)' +}; + +// Mapeo de chainID a nombres de cadena para DeFiLlama +const CHAIN_MAPPING = { + 1: 'ethereum', + 56: 'binance', + 137: 'polygon', + 42161: 'arbitrum', + 10: 'optimism', + 8453: 'base', + 43114: 'avalanche', + 250: 'fantom', + 100: 'gnosis', + 324: 'era', + 59144: 'linea', + 534352: 'scroll' +}; + +/** + * Función para hacer peticiones GraphQL usando fetch + * @param {Object} query - Query GraphQL a ejecutar + * @returns {Promise} - Respuesta de la API + */ +const makeGraphQLRequest = async (query) => { + try { + const response = await fetch(GRAPHQL_ENDPOINT, { + method: 'POST', + headers: REQUEST_HEADERS, + body: JSON.stringify([query]) + }); + + if (!response.ok) { + throw new Error(`HTTP error! status: ${response.status}`); + } + + const data = await response.json(); + + if (!data || !Array.isArray(data) || data.length === 0) { + throw new Error('Invalid response format'); + } + + return data[0]; + } catch (error) { + console.error('Error making GraphQL request:', error); + throw new Error(`GraphQL request failed: ${error.message}`); + } +}; + +/** + * Obtener nombre de cadena formateado para DeFiLlama + * @param {number} chainID - ID de la cadena + * @returns {string} - Nombre de la cadena formateado + */ +const getChainName = (chainID) => { + const chainKey = CHAIN_MAPPING[chainID]; + if (!chainKey) { + console.warn(`Unknown chainID: ${chainID}, defaulting to ethereum`); + return 'ethereum'; + } + return utils.formatChain(chainKey); +}; + +/** + * Calcular TVL en USD usando los datos de shareTokenSupply + * @param {Object} pool - Pool completo con shareTokenSupply + * @returns {number} - TVL en USD + */ +const calculateTVLFromPool = (pool) => { + if (!pool || !pool.shareTokenSupply || !pool.shareTokenSupply.currencyAmounts) { + return 0; + } + + try { + // Buscar el valor en USD en shareTokenSupply + const usdAmount = pool.shareTokenSupply.currencyAmounts.find(ca => ca.currencyID === 'USD'); + if (usdAmount && usdAmount.number > 0) { + return usdAmount.number; + } + + // Fallback: usar el número principal del shareTokenSupply + return pool.shareTokenSupply.number || 0; + } catch (error) { + console.error('Error calculating TVL from pool:', error); + return 0; + } +}; + +/** + * Obtener todos los pools con paginación automática + * @param {Function} createPoolStatsQuery - Función para crear query de pools + * @returns {Promise} - Lista completa de pools + */ +const getAllPools = async (createPoolStatsQuery) => { + let allPools = []; + let offset = 0; + const limit = 100; + let hasMore = true; + + while (hasMore) { + try { + const query = createPoolStatsQuery(offset, limit); + const response = await makeGraphQLRequest(query); + + if (response.data.getPoolStats.__typename === 'SimpleError') { + throw new Error(response.data.getPoolStats.description); + } + + const pools = response.data.getPoolStats.items || []; + const metadata = response.data.getPoolStats.metadata; + + allPools = allPools.concat(pools); + + // Verificar si hay más pools + hasMore = pools.length === limit && offset + limit < metadata.numElements; + offset += limit; + + } catch (error) { + console.error(`Error fetching pools at offset ${offset}:`, error); + break; + } + } + + return allPools; +}; + +/** + * Obtener tokens subyacentes de un pool + * @param {Object} poolConfig - Configuración del pool + * @param {Array} addresses - Mapeo de tokenID a address + * @returns {Array} - Lista de direcciones de tokens + */ +const getUnderlyingTokens = (poolConfig, addresses) => { + if (!poolConfig || !poolConfig.tokens || !Array.isArray(poolConfig.tokens)) { + return []; + } + + return poolConfig.tokens + .map(tokenId => { + const addressInfo = addresses.find(addr => addr.tokenID === tokenId); + return addressInfo ? addressInfo.address.toLowerCase() : null; + }) + .filter(address => address !== null); +}; + +/** + * Obtener tokens de recompensa si existen + * @param {Object} poolStats - Estadísticas del pool + * @param {Array} gauges - Lista de gauges de configuración + * @param {Array} addresses - Mapeo de tokenID a address + * @returns {Array} - Lista de direcciones de tokens de recompensa + */ +const getRewardTokens = (poolStats, gauges, addresses) => { + if (!gauges || !Array.isArray(gauges)) { + return []; + } + + const poolGauges = gauges.filter(gauge => gauge.poolID === poolStats.shareTokenID); + + return poolGauges + .map(gauge => { + const addressInfo = addresses.find(addr => addr.tokenID === gauge.rewardTokenID); + return addressInfo ? addressInfo.address.toLowerCase() : null; + }) + .filter(address => address !== null); +}; + +/** + * Validar que los datos del pool son válidos + * @param {Object} pool - Datos del pool + * @returns {boolean} - Si el pool es válido + */ +const isValidPool = (pool) => { + return pool && + pool.address && + (pool.apr > 0 || pool.estimatedApr > 0) && + pool.reserves && + Array.isArray(pool.reserves) && + pool.reserves.length > 0 && + pool.reserves.some(reserve => reserve.currencyAmounts && reserve.currencyAmounts.length > 0); +}; + +/** + * Crear URL específica del pool + * @param {string} poolId - ID/nombre del pool (ej: "GT3-WBTC") + * @returns {string} - URL del pool + */ +const createPoolUrl = (poolId) => { + return `https://dapp.gt3.finance/explore/pools/${poolId}`; +}; + +module.exports = { + GRAPHQL_ENDPOINT, + PROJECT_KEY, + REQUEST_HEADERS, + CHAIN_MAPPING, + makeGraphQLRequest, + getChainName, + calculateTVLFromPool, + getAllPools, + getUnderlyingTokens, + getRewardTokens, + isValidPool, + createPoolUrl +}; \ No newline at end of file diff --git a/src/adaptors/gt3/index.js b/src/adaptors/gt3/index.js new file mode 100644 index 0000000000..f2d4283097 --- /dev/null +++ b/src/adaptors/gt3/index.js @@ -0,0 +1,155 @@ +// Adaptador GT3 Finance para DeFiLlama Yield Server +const utils = require('../utils'); +const { PROJECT_CONFIG_QUERY, createPoolStatsQuery } = require('./queries'); +const { + makeGraphQLRequest, + getChainName, + calculateTVLFromPool, + getAllPools, + getUnderlyingTokens, + getRewardTokens, + isValidPool, + createPoolUrl +} = require('./helpers'); + +/** + * Transformar pool de GT3 a formato DeFiLlama + * @param {Object} pool - Datos del pool de GT3 + * @param {Object} config - Configuración del proyecto + * @param {string} chainName - Nombre de la cadena + * @returns {Promise} - Pool en formato DeFiLlama o null si es inválido + */ +const transformPool = async (pool, config, chainName) => { + try { + // Validar pool + if (!isValidPool(pool)) { + console.log(`Pool ${pool.id} invalid:`, { + hasAddress: !!pool.address, + hasApr: !!(pool.apr > 0 || pool.estimatedApr > 0), + hasReserves: !!(pool.reserves && pool.reserves.currencyAmounts) + }); + return null; + } + + const { tokens, pools: configPools, addresses, gauges } = config; + + // Encontrar configuración del pool + const poolConfig = configPools.find(p => p.id === pool.shareTokenID); + + // Calcular TVL usando los datos de shareTokenSupply directamente + const tvlUsd = calculateTVLFromPool(pool); + + // Filtrar pools con TVL muy bajo según las mejores prácticas de DeFiLlama (>$10k) + if (tvlUsd < 10000) { + console.log(`Pool ${pool.id} filtered out due to low TVL: $${tvlUsd}`); + return null; + } + + // Obtener el APR más confiable (priorizar APR sobre estimatedApr) + const aprValue = pool.apr || 0; + + // Convertir APR a APY usando la utilidad oficial de DeFiLlama + const apyBase = utils.aprToApy(aprValue); + + // Obtener símbolo del pool + const symbol = poolConfig ? + utils.formatSymbol(poolConfig.symbol) : + `GT3-${pool.id}`; + + // Obtener tokens subyacentes + const underlyingTokens = getUnderlyingTokens(poolConfig, addresses); + + // Obtener tokens de recompensa + const rewardTokens = getRewardTokens(pool, gauges, addresses); + + // Crear pool en formato DeFiLlama + const poolData = { + pool: `${pool.address}-${chainName.toLowerCase()}`, + chain: chainName, + project: 'gt3', + symbol: symbol, + tvlUsd: tvlUsd, + apyBase: apyBase, + underlyingTokens: underlyingTokens, + url: createPoolUrl(pool.id) + }; + + if (poolConfig && poolConfig.name) { + poolData.poolMeta = poolConfig.name; + } + + if (rewardTokens.length > 0) { + poolData.rewardTokens = rewardTokens; + } + + return poolData; + + } catch (error) { + console.error(`Error transforming pool ${pool.id}:`, error); + return null; + } +}; + +/** + * Función principal del adaptador + * @returns {Promise} - Lista de pools en formato DeFiLlama + */ +const apy = async () => { + try { + // Obtener configuración del proyecto + const configResponse = await makeGraphQLRequest(PROJECT_CONFIG_QUERY); + + if (configResponse.data.getProjectConfiguration.__typename === 'SimpleError') { + throw new Error(`Configuration error: ${configResponse.data.getProjectConfiguration.description}`); + } + + const config = configResponse.data.getProjectConfiguration; + const { chainID } = config; + const chainName = getChainName(chainID); + + // Obtener todas las estadísticas de pools con paginación + const allPoolStats = await getAllPools(createPoolStatsQuery); + + // Transformar pools al formato DeFiLlama en paralelo + const poolTransformations = allPoolStats.map(pool => + transformPool(pool, config, chainName) + ); + + const transformedPools = await Promise.all(poolTransformations); + + // Filtrar pools válidos y con datos completos + const validPools = transformedPools + .filter(pool => pool !== null) + .filter(pool => { + const isFinite = utils.keepFinite(pool); + if (!isFinite) { + console.log('Pool filtered by keepFinite:', pool); + } + return isFinite; + }); + + // Ordenar por TVL descendente + validPools.sort((a, b) => b.tvlUsd - a.tvlUsd); + + return validPools; + + } catch (error) { + console.error('Error in GT3 adapter:', error); + return []; + } +}; + +/** + * Configuración del módulo del adaptador + */ +module.exports = { + timetravel: false, + apy: apy, + url: 'https://dapp.gt3.finance/', + meta: { + name: 'GT3 Finance', + description: 'Decentralized yield farming protocol', + chains: ['Polygon'], + category: 'yield-farming' + } +}; diff --git a/src/adaptors/gt3/queries.js b/src/adaptors/gt3/queries.js new file mode 100644 index 0000000000..51f4ce7fb1 --- /dev/null +++ b/src/adaptors/gt3/queries.js @@ -0,0 +1,174 @@ +// GraphQL queries para GT3 Finance + +/** + * Query to get project configuration including tokens, pools, addresses, and gauges + */ +const PROJECT_CONFIG_QUERY = { + operationName: "GET_PROJECT_CONFIG_QUERY", + variables: {}, + query: `query GET_PROJECT_CONFIG_QUERY { + getProjectConfiguration { + __typename + ... on ProjectConfig { + id + key + chainID + tokens { + id + name + symbol + decimals + type + metadata { + permitted + domainName + domainVersion + swapFeeType + __typename + } + __typename + } + pools { + id + name + symbol + decimals + type + tokens + multiplier + metadata { + permitted + domainName + domainVersion + swapFeeType + __typename + } + __typename + } + addresses { + tokenID + address + feed + __typename + } + externalSources { + uri + purposes + __typename + } + balances + dexRouters { + id + address + type + __typename + } + synthetics { + id + escrowedTokenId + type + vaultAddress + voterAddress + rebaseAddress + epochDuration + minLockDuration + maxLockDuration + minterAddress + __typename + } + gauges { + poolID + address + rewardTokenID + __typename + } + bribes { + poolID + address + __typename + } + __typename + } + ... on SimpleError { + description + __typename + } + } + }` +}; + +/** + * Query to get pool statistics with pagination + * @param {number} offset - Pagination offset + * @param {number} limit - Number of items per page + * @returns {Object} GraphQL query object + */ +const createPoolStatsQuery = (offset = 0, limit = 100) => ({ + operationName: "GET_POOL_STATS_QUERY", + variables: { + input: { + items: [], + paginationMetadata: { + offset, + limit, + orderBy: "id", + orderDirection: "DESC" + } + } + }, + query: `query GET_POOL_STATS_QUERY($input: GetPoolStatsInput!) { + getPoolStats(input: $input) { + __typename + ... on PoolStatsPaginatedListInfo { + items { + id + address + shareTokenID + shareTokenSupply { + number + bigint + tokenID + currencyAmounts { + number + currencyID + __typename + } + __typename + } + reserves { + number + bigint + tokenID + currencyAmounts { + number + currencyID + __typename + } + __typename + } + apr + estimatedApr + __typename + } + metadata { + offset + limit + orderBy + orderDirection + numElements + __typename + } + __typename + } + ... on SimpleError { + description + __typename + } + } + }` +}); + +module.exports = { + PROJECT_CONFIG_QUERY, + createPoolStatsQuery +}; \ No newline at end of file From 1569976a6294d19979d53db39c38256972674e4e Mon Sep 17 00:00:00 2001 From: Javier Ortiz Date: Fri, 6 Jun 2025 02:51:01 +0200 Subject: [PATCH 2/3] docs translate comments --- src/adaptors/gt3/helpers.js | 68 +++++++++++++++++----------------- src/adaptors/gt3/index.js | 73 ++++++++++++++++--------------------- src/adaptors/gt3/queries.js | 2 +- 3 files changed, 66 insertions(+), 77 deletions(-) diff --git a/src/adaptors/gt3/helpers.js b/src/adaptors/gt3/helpers.js index 139b67dcc0..fa6e44b877 100644 --- a/src/adaptors/gt3/helpers.js +++ b/src/adaptors/gt3/helpers.js @@ -1,7 +1,7 @@ -// Utilidades específicas para GT3 Finance +// GT3 Finance specific utilities const utils = require('../utils'); -// Usar superagent como fetch si fetch no está disponible +// Use superagent as fetch fallback if fetch is not available let fetch; try { fetch = globalThis.fetch; @@ -20,7 +20,7 @@ try { }; } -// Configuración de la API +// API configuration const GRAPHQL_ENDPOINT = 'https://backend.gt3.finance/graphql'; const PROJECT_KEY = 'GT3'; @@ -33,7 +33,7 @@ const REQUEST_HEADERS = { 'user-agent': 'Mozilla/5.0 (compatible; DeFiLlama/1.0)' }; -// Mapeo de chainID a nombres de cadena para DeFiLlama +// Chain ID to chain name mapping for DeFiLlama const CHAIN_MAPPING = { 1: 'ethereum', 56: 'binance', @@ -50,9 +50,9 @@ const CHAIN_MAPPING = { }; /** - * Función para hacer peticiones GraphQL usando fetch - * @param {Object} query - Query GraphQL a ejecutar - * @returns {Promise} - Respuesta de la API + * Make GraphQL requests using fetch + * @param {Object} query - GraphQL query to execute + * @returns {Promise} - API response */ const makeGraphQLRequest = async (query) => { try { @@ -80,9 +80,9 @@ const makeGraphQLRequest = async (query) => { }; /** - * Obtener nombre de cadena formateado para DeFiLlama - * @param {number} chainID - ID de la cadena - * @returns {string} - Nombre de la cadena formateado + * Get formatted chain name for DeFiLlama + * @param {number} chainID - Chain ID + * @returns {string} - Formatted chain name */ const getChainName = (chainID) => { const chainKey = CHAIN_MAPPING[chainID]; @@ -94,9 +94,9 @@ const getChainName = (chainID) => { }; /** - * Calcular TVL en USD usando los datos de shareTokenSupply - * @param {Object} pool - Pool completo con shareTokenSupply - * @returns {number} - TVL en USD + * Calculate TVL in USD using shareTokenSupply data + * @param {Object} pool - Complete pool with shareTokenSupply + * @returns {number} - TVL in USD */ const calculateTVLFromPool = (pool) => { if (!pool || !pool.shareTokenSupply || !pool.shareTokenSupply.currencyAmounts) { @@ -104,13 +104,13 @@ const calculateTVLFromPool = (pool) => { } try { - // Buscar el valor en USD en shareTokenSupply + // Find USD value in shareTokenSupply const usdAmount = pool.shareTokenSupply.currencyAmounts.find(ca => ca.currencyID === 'USD'); if (usdAmount && usdAmount.number > 0) { return usdAmount.number; } - // Fallback: usar el número principal del shareTokenSupply + // Fallback: use main shareTokenSupply number return pool.shareTokenSupply.number || 0; } catch (error) { console.error('Error calculating TVL from pool:', error); @@ -119,9 +119,9 @@ const calculateTVLFromPool = (pool) => { }; /** - * Obtener todos los pools con paginación automática - * @param {Function} createPoolStatsQuery - Función para crear query de pools - * @returns {Promise} - Lista completa de pools + * Get all pools with automatic pagination + * @param {Function} createPoolStatsQuery - Function to create pool query + * @returns {Promise} - Complete list of pools */ const getAllPools = async (createPoolStatsQuery) => { let allPools = []; @@ -143,7 +143,7 @@ const getAllPools = async (createPoolStatsQuery) => { allPools = allPools.concat(pools); - // Verificar si hay más pools + // Check if there are more pools hasMore = pools.length === limit && offset + limit < metadata.numElements; offset += limit; @@ -157,10 +157,10 @@ const getAllPools = async (createPoolStatsQuery) => { }; /** - * Obtener tokens subyacentes de un pool - * @param {Object} poolConfig - Configuración del pool - * @param {Array} addresses - Mapeo de tokenID a address - * @returns {Array} - Lista de direcciones de tokens + * Get underlying tokens from a pool configuration + * @param {Object} poolConfig - Pool configuration + * @param {Array} addresses - Token ID to address mapping + * @returns {Array} - List of token addresses */ const getUnderlyingTokens = (poolConfig, addresses) => { if (!poolConfig || !poolConfig.tokens || !Array.isArray(poolConfig.tokens)) { @@ -176,11 +176,11 @@ const getUnderlyingTokens = (poolConfig, addresses) => { }; /** - * Obtener tokens de recompensa si existen - * @param {Object} poolStats - Estadísticas del pool - * @param {Array} gauges - Lista de gauges de configuración - * @param {Array} addresses - Mapeo de tokenID a address - * @returns {Array} - Lista de direcciones de tokens de recompensa + * Get reward tokens if they exist + * @param {Object} poolStats - Pool statistics + * @param {Array} gauges - Gauge configuration list + * @param {Array} addresses - Token ID to address mapping + * @returns {Array} - List of reward token addresses */ const getRewardTokens = (poolStats, gauges, addresses) => { if (!gauges || !Array.isArray(gauges)) { @@ -198,9 +198,9 @@ const getRewardTokens = (poolStats, gauges, addresses) => { }; /** - * Validar que los datos del pool son válidos - * @param {Object} pool - Datos del pool - * @returns {boolean} - Si el pool es válido + * Validate that pool data is valid + * @param {Object} pool - Pool data + * @returns {boolean} - Whether the pool is valid */ const isValidPool = (pool) => { return pool && @@ -213,9 +213,9 @@ const isValidPool = (pool) => { }; /** - * Crear URL específica del pool - * @param {string} poolId - ID/nombre del pool (ej: "GT3-WBTC") - * @returns {string} - URL del pool + * Create specific pool URL + * @param {string} poolId - Pool ID/name (e.g., "GT3-WBTC") + * @returns {string} - Pool URL */ const createPoolUrl = (poolId) => { return `https://dapp.gt3.finance/explore/pools/${poolId}`; diff --git a/src/adaptors/gt3/index.js b/src/adaptors/gt3/index.js index f2d4283097..f9da655640 100644 --- a/src/adaptors/gt3/index.js +++ b/src/adaptors/gt3/index.js @@ -1,4 +1,4 @@ -// Adaptador GT3 Finance para DeFiLlama Yield Server +// GT3 Finance adapter for DeFiLlama Yield Server const utils = require('../utils'); const { PROJECT_CONFIG_QUERY, createPoolStatsQuery } = require('./queries'); const { @@ -13,56 +13,50 @@ const { } = require('./helpers'); /** - * Transformar pool de GT3 a formato DeFiLlama - * @param {Object} pool - Datos del pool de GT3 - * @param {Object} config - Configuración del proyecto - * @param {string} chainName - Nombre de la cadena - * @returns {Promise} - Pool en formato DeFiLlama o null si es inválido + * Transform GT3 pool to DeFiLlama format + * @param {Object} pool - GT3 pool data + * @param {Object} config - Project configuration + * @param {string} chainName - Chain name + * @returns {Promise} - Pool in DeFiLlama format or null if invalid */ const transformPool = async (pool, config, chainName) => { try { - // Validar pool + // Validate pool if (!isValidPool(pool)) { - console.log(`Pool ${pool.id} invalid:`, { - hasAddress: !!pool.address, - hasApr: !!(pool.apr > 0 || pool.estimatedApr > 0), - hasReserves: !!(pool.reserves && pool.reserves.currencyAmounts) - }); return null; } const { tokens, pools: configPools, addresses, gauges } = config; - // Encontrar configuración del pool + // Find pool configuration const poolConfig = configPools.find(p => p.id === pool.shareTokenID); - // Calcular TVL usando los datos de shareTokenSupply directamente + // Calculate TVL using shareTokenSupply data directly const tvlUsd = calculateTVLFromPool(pool); - // Filtrar pools con TVL muy bajo según las mejores prácticas de DeFiLlama (>$10k) + // Filter pools with very low TVL according to DeFiLlama best practices (>$10k) if (tvlUsd < 10000) { - console.log(`Pool ${pool.id} filtered out due to low TVL: $${tvlUsd}`); return null; } - // Obtener el APR más confiable (priorizar APR sobre estimatedApr) - const aprValue = pool.apr || 0; + // Get most reliable APR (prioritize APR over estimatedApr) + const aprValue = pool.apr || pool.estimatedApr || 0; - // Convertir APR a APY usando la utilidad oficial de DeFiLlama + // Convert APR to APY using DeFiLlama's official utility const apyBase = utils.aprToApy(aprValue); - // Obtener símbolo del pool + // Get pool symbol const symbol = poolConfig ? utils.formatSymbol(poolConfig.symbol) : `GT3-${pool.id}`; - // Obtener tokens subyacentes + // Get underlying tokens const underlyingTokens = getUnderlyingTokens(poolConfig, addresses); - // Obtener tokens de recompensa + // Get reward tokens const rewardTokens = getRewardTokens(pool, gauges, addresses); - // Crear pool en formato DeFiLlama + // Create pool in DeFiLlama format const poolData = { pool: `${pool.address}-${chainName.toLowerCase()}`, chain: chainName, @@ -74,6 +68,7 @@ const transformPool = async (pool, config, chainName) => { url: createPoolUrl(pool.id) }; + // Add optional fields if they exist if (poolConfig && poolConfig.name) { poolData.poolMeta = poolConfig.name; } @@ -91,12 +86,12 @@ const transformPool = async (pool, config, chainName) => { }; /** - * Función principal del adaptador - * @returns {Promise} - Lista de pools en formato DeFiLlama + * Main adapter function + * @returns {Promise} - List of pools in DeFiLlama format */ const apy = async () => { - try { - // Obtener configuración del proyecto + try { + // Get project configuration const configResponse = await makeGraphQLRequest(PROJECT_CONFIG_QUERY); if (configResponse.data.getProjectConfiguration.__typename === 'SimpleError') { @@ -106,29 +101,23 @@ const apy = async () => { const config = configResponse.data.getProjectConfiguration; const { chainID } = config; const chainName = getChainName(chainID); - - // Obtener todas las estadísticas de pools con paginación + + // Get all pool statistics with pagination const allPoolStats = await getAllPools(createPoolStatsQuery); - - // Transformar pools al formato DeFiLlama en paralelo + + // Transform pools to DeFiLlama format in parallel const poolTransformations = allPoolStats.map(pool => transformPool(pool, config, chainName) ); const transformedPools = await Promise.all(poolTransformations); - // Filtrar pools válidos y con datos completos + // Filter valid pools with complete data const validPools = transformedPools .filter(pool => pool !== null) - .filter(pool => { - const isFinite = utils.keepFinite(pool); - if (!isFinite) { - console.log('Pool filtered by keepFinite:', pool); - } - return isFinite; - }); - - // Ordenar por TVL descendente + .filter(pool => utils.keepFinite(pool)); + + // Sort by TVL descending validPools.sort((a, b) => b.tvlUsd - a.tvlUsd); return validPools; @@ -140,7 +129,7 @@ const apy = async () => { }; /** - * Configuración del módulo del adaptador + * Adapter module configuration */ module.exports = { timetravel: false, diff --git a/src/adaptors/gt3/queries.js b/src/adaptors/gt3/queries.js index 51f4ce7fb1..34c7cd2086 100644 --- a/src/adaptors/gt3/queries.js +++ b/src/adaptors/gt3/queries.js @@ -1,4 +1,4 @@ -// GraphQL queries para GT3 Finance +// GraphQL queries for GT3 Finance API /** * Query to get project configuration including tokens, pools, addresses, and gauges From 79a140fb967696cb7346ae7d8d68ad5cb6ab5ecd Mon Sep 17 00:00:00 2001 From: Javier Ortiz Date: Mon, 16 Jun 2025 12:50:34 +0200 Subject: [PATCH 3/3] fix(symbol) update symbol and poolMeta --- src/adaptors/gt3/index.js | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/src/adaptors/gt3/index.js b/src/adaptors/gt3/index.js index f9da655640..aa240da092 100644 --- a/src/adaptors/gt3/index.js +++ b/src/adaptors/gt3/index.js @@ -45,9 +45,9 @@ const transformPool = async (pool, config, chainName) => { // Convert APR to APY using DeFiLlama's official utility const apyBase = utils.aprToApy(aprValue); - // Get pool symbol - const symbol = poolConfig ? - utils.formatSymbol(poolConfig.symbol) : + // Get pool symbol - use pool name/id as symbol for better distinction + const symbol = poolConfig && poolConfig.name ? + utils.formatSymbol(poolConfig.name) : `GT3-${pool.id}`; // Get underlying tokens @@ -68,10 +68,8 @@ const transformPool = async (pool, config, chainName) => { url: createPoolUrl(pool.id) }; - // Add optional fields if they exist - if (poolConfig && poolConfig.name) { - poolData.poolMeta = poolConfig.name; - } + // Add poolMeta with descriptive suffix + poolData.poolMeta = `${symbol} Liquidity Pool`; if (rewardTokens.length > 0) { poolData.rewardTokens = rewardTokens;