From 2a68ee9006e37eb51a7486b2af55cfc34e0ee680 Mon Sep 17 00:00:00 2001 From: thomaslonggit Date: Mon, 9 Jun 2025 17:42:18 +0800 Subject: [PATCH 1/2] Implement SSV Network adapter to track total ETH staked in validators --- projects/ssv-network/index.js | 67 +++++++++++++++++++++++++++++++++++ 1 file changed, 67 insertions(+) create mode 100644 projects/ssv-network/index.js diff --git a/projects/ssv-network/index.js b/projects/ssv-network/index.js new file mode 100644 index 00000000000..61e33aeb205 --- /dev/null +++ b/projects/ssv-network/index.js @@ -0,0 +1,67 @@ +/** + * DefiLlama Adapter for SSV Network + * Tracks total ETH staked in SSV Network validators + */ + +const { request, gql } = require('graphql-request') + +// Configuration +const SSV_SUBGRAPH_URL = 'https://api.studio.thegraph.com/query/88140/ssv-validators/version/latest' +const ETH_TOKEN = '0x0000000000000000000000000000000000000000' + +// GraphQL Query - Only fetch required fields +const SSV_TVL_QUERY = gql` + query GetSSVTVL { + ssvstats(id: "ssv") { + totalSSVEffectiveBalance + totalSSVValidators + activeSSVValidators + } + } +` + +/** + * Fetches TVL for SSV Network + * @param {Object} api - DefiLlama API instance + */ +async function tvl(api) { + try { + // Make request without hardcoded auth token + // Note: Remove auth header as it should not be hardcoded + const data = await request(SSV_SUBGRAPH_URL, SSV_TVL_QUERY) + + if (!data.ssvstats) { + throw new Error('No SSV stats found in subgraph response') + } + + const stats = data.ssvstats + const totalEffectiveBalance = stats.totalSSVEffectiveBalance + + if (!totalEffectiveBalance || totalEffectiveBalance === '0') { + console.warn('SSV Network: No effective balance found') + return + } + + // Verify unit: totalSSVEffectiveBalance should be in Gwei + // Convert from Gwei to Wei (DefiLlama expects Wei) + const gweiValue = BigInt(totalEffectiveBalance) + const weiValue = gweiValue * BigInt(1e9) + + // Add to DefiLlama TVL + api.add(ETH_TOKEN, weiValue.toString()) + + } catch (error) { + console.error('Error fetching SSV Network TVL:', error.message) + // Don't re-throw to prevent adapter failure + return + } +} + +// DefiLlama Adapter Export +module.exports = { + methodology: 'Tracks total ETH staked in SSV Network validators using totalSSVEffectiveBalance from the SSV subgraph. The effective balance represents the actual ETH amount backing each validator in the network.', + start: 18362616, // Block when SSV Network mainnet launched (October 2023) + ethereum: { + tvl, + } +} \ No newline at end of file From 1e9a6b69e816fce69a2b18839ed0611334d3ffec Mon Sep 17 00:00:00 2001 From: Yuting Zhang Date: Tue, 9 Dec 2025 10:57:37 +0800 Subject: [PATCH 2/2] refactor: migrate SSV Network TVL source from subgraph to official API and update dependencies. --- projects/ssv-network/index.js | 60 +++++++++++------------------------ 1 file changed, 19 insertions(+), 41 deletions(-) diff --git a/projects/ssv-network/index.js b/projects/ssv-network/index.js index 61e33aeb205..c709982d0b7 100644 --- a/projects/ssv-network/index.js +++ b/projects/ssv-network/index.js @@ -1,67 +1,45 @@ /** * DefiLlama Adapter for SSV Network - * Tracks total ETH staked in SSV Network validators + * Tracks total ETH staked in SSV Network validators via official API */ -const { request, gql } = require('graphql-request') +const { get } = require('../helper/http') // Configuration -const SSV_SUBGRAPH_URL = 'https://api.studio.thegraph.com/query/88140/ssv-validators/version/latest' +const SSV_API_URL = 'https://api.ssv.network/api/v4/mainnet/statistics/totalEffectiveBalance' const ETH_TOKEN = '0x0000000000000000000000000000000000000000' -// GraphQL Query - Only fetch required fields -const SSV_TVL_QUERY = gql` - query GetSSVTVL { - ssvstats(id: "ssv") { - totalSSVEffectiveBalance - totalSSVValidators - activeSSVValidators - } - } -` - /** * Fetches TVL for SSV Network * @param {Object} api - DefiLlama API instance */ async function tvl(api) { try { - // Make request without hardcoded auth token - // Note: Remove auth header as it should not be hardcoded - const data = await request(SSV_SUBGRAPH_URL, SSV_TVL_QUERY) - - if (!data.ssvstats) { - throw new Error('No SSV stats found in subgraph response') - } - - const stats = data.ssvstats - const totalEffectiveBalance = stats.totalSSVEffectiveBalance - - if (!totalEffectiveBalance || totalEffectiveBalance === '0') { - console.warn('SSV Network: No effective balance found') - return + // Fetch total effective balance from official API + // Returns: {"total_effective_balance": "4769351000000000"} (in Gwei) + const data = await get(SSV_API_URL) + + if (!data || !data.total_effective_balance) { + throw new Error('Invalid response format or missing total_effective_balance') } - - // Verify unit: totalSSVEffectiveBalance should be in Gwei - // Convert from Gwei to Wei (DefiLlama expects Wei) - const gweiValue = BigInt(totalEffectiveBalance) - const weiValue = gweiValue * BigInt(1e9) - - // Add to DefiLlama TVL - api.add(ETH_TOKEN, weiValue.toString()) - + + const totalEffectiveBalanceGwei = data.total_effective_balance + + // api.add handles big number arithmetic safely + // Input is Gwei (1e9), output needed in Wei (1e18) + // We multiply by 1e9 to convert Gwei to Wei + api.add(ETH_TOKEN, totalEffectiveBalanceGwei + '000000000') + } catch (error) { console.error('Error fetching SSV Network TVL:', error.message) - // Don't re-throw to prevent adapter failure return } } -// DefiLlama Adapter Export module.exports = { - methodology: 'Tracks total ETH staked in SSV Network validators using totalSSVEffectiveBalance from the SSV subgraph. The effective balance represents the actual ETH amount backing each validator in the network.', + methodology: 'Tracks total ETH staked in SSV Network validators using the official SSV Network API (totalEffectiveBalance).', start: 18362616, // Block when SSV Network mainnet launched (October 2023) ethereum: { tvl, } -} \ No newline at end of file +}