From 9e435ab781799d6edf3f06c5819d58780498962b Mon Sep 17 00:00:00 2001 From: pavel Date: Wed, 1 Oct 2025 10:55:41 +0300 Subject: [PATCH 1/2] Add fees and revenue for mstable v2 --- fees/mstable-v2/index.ts | 133 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 133 insertions(+) create mode 100644 fees/mstable-v2/index.ts diff --git a/fees/mstable-v2/index.ts b/fees/mstable-v2/index.ts new file mode 100644 index 0000000000..4ff4b0a3df --- /dev/null +++ b/fees/mstable-v2/index.ts @@ -0,0 +1,133 @@ +import { FetchOptions, SimpleAdapter } from "../../adapters/types"; +import { CHAIN } from "../../helpers/chains"; +import { GraphQLClient } from "graphql-request"; +import * as sdk from "@defillama/sdk"; + +const queryManagerFeeMinteds = ` + query managerFeeMinteds($manager: Bytes!, $startTimestamp: BigInt!, $endTimestamp: BigInt!, $first: Int!, $skip: Int!) { + managerFeeMinteds( + where: { manager: $manager, managerFee_not: 0, blockTimestamp_gte: $startTimestamp, blockTimestamp_lte: $endTimestamp }, + first: $first, skip: $skip, orderBy: blockTimestamp, orderDirection: desc + ) { managerFee, tokenPriceAtFeeMint, pool, manager, block } + }` + +const queryEntryFeeMinteds = ` + query entryFeeMinteds($manager: Bytes!, $startTimestamp: BigInt!, $endTimestamp: BigInt!, $first: Int!, $skip: Int!) { + entryFeeMinteds( + where: { managerAddress: $manager, time_gte: $startTimestamp, time_lte: $endTimestamp }, + first: $first, skip: $skip, orderBy: time, orderDirection: desc + ) { entryFeeAmount, tokenPrice } + }` + +const queryExitFeeMinteds = ` + query exitFeeMinteds($manager: Bytes!, $startTimestamp: BigInt!, $endTimestamp: BigInt!, $first: Int!, $skip: Int!) { + exitFeeMinteds( + where: { managerAddress: $manager, time_gte: $startTimestamp, time_lte: $endTimestamp }, + first: $first, skip: $skip, orderBy: time, orderDirection: desc + ) { exitFeeAmount, tokenPrice } + }` + +const CONFIG = { + [CHAIN.ETHEREUM]: { + endpoint: sdk.graph.modifyEndpoint("HSPZATdnDvYRNPBJm7eSrzkTeRZqhqYvy7c3Ngm9GCTL"), + mstableManagerAddress: "0x3dd46846eed8D147841AE162C8425c08BD8E1b41", + }, +}; + +const fetchHistoricalFees = async (chainId: CHAIN, query: string, dataField: string, startTimestamp: number, endTimestamp: number) => { + const { endpoint, mstableManagerAddress } = CONFIG[chainId]; + + let allData = []; + let skip = 0; + const batchSize = 1000; + + while (true) { + try { + const data = await new GraphQLClient(endpoint).request(query, { + manager: mstableManagerAddress, + startTimestamp: startTimestamp.toString(), + endTimestamp: endTimestamp.toString(), + first: batchSize, + skip + }); + + const entries = data[dataField]; + if (entries.length === 0) break; + + allData = allData.concat(entries); + skip += batchSize; + + if (entries.length < batchSize) break; + } catch (e) { + throw new Error(`Error fetching data for chain ${chainId}: ${e.message}`); + } + } + return allData; +}; + +const calculateManagerFees = (dailyFees: any): number => + dailyFees.reduce((acc: number, dailyFeesDto: any) => { + const managerFee = Number(dailyFeesDto.managerFee); + const tokenPrice = Number(dailyFeesDto.tokenPriceAtFeeMint); + const managerFeeFormatted = managerFee / 1e18; + const tokenPriceFormatted = tokenPrice / 1e18; + const managerFeeUsd = managerFeeFormatted * tokenPriceFormatted; + return acc + managerFeeUsd; + }, 0); + +const calculateEntryFees = (data: any): number => + data.reduce((acc: number, item: any) => { + const entryFee = Number(item.entryFeeAmount); + const tokenPrice = Number(item.tokenPrice); + const entryFeeFormatted = entryFee / 1e18; + const tokenPriceFormatted = tokenPrice / 1e18; + const result = entryFeeFormatted * tokenPriceFormatted; + return acc + result; + }, 0); + +const calculateExitFees = (data: any): number => + data.reduce((acc: number, item: any) => { + const exitFee = Number(item.exitFeeAmount); + const tokenPrice = Number(item.tokenPrice); + const exitFeeFormatted = exitFee / 1e18; + const tokenPriceFormatted = tokenPrice / 1e18; + const result = exitFeeFormatted * tokenPriceFormatted; + return acc + result; + }, 0); + +const fetch = async ({ chain, endTimestamp, startTimestamp }: FetchOptions) => { + const config = CONFIG[chain]; + if (!config) throw new Error(`Unsupported chain: ${chain}`); + + const dailyManagerFeesEvents = await fetchHistoricalFees(chain as CHAIN, queryManagerFeeMinteds, 'managerFeeMinteds', startTimestamp, endTimestamp); + const dailyEntryFeesEvents = await fetchHistoricalFees(chain as CHAIN, queryEntryFeeMinteds, 'entryFeeMinteds', startTimestamp, endTimestamp); + const dailyExitFeesEvents = await fetchHistoricalFees(chain as CHAIN, queryExitFeeMinteds, 'exitFeeMinteds', startTimestamp, endTimestamp); + + const managerFees = calculateManagerFees(dailyManagerFeesEvents); + const entryFees = calculateEntryFees(dailyEntryFeesEvents); + const exitFees = calculateExitFees(dailyExitFeesEvents); + + const dailyFees = managerFees + entryFees + exitFees; + + return { + dailyFees, + dailyRevenue: dailyFees, + timestamp: endTimestamp, + }; +} + +const methodology = { + Fees: 'All fees generated from mStable vaults.', + Revenue: 'All revenue collected by the mStable protocol.', +} + +const adapter: SimpleAdapter = { + fetch, + methodology, + adapter: { + [CHAIN.ETHEREUM]: { start: '2025-08-12', }, + }, + version: 2 +} + +export default adapter; From 119fd162f9cb516924779a03bfbf9a820ad9468a Mon Sep 17 00:00:00 2001 From: Eden Date: Fri, 17 Oct 2025 01:06:14 +0700 Subject: [PATCH 2/2] update --- fees/mstable-v2/index.ts | 67 ++++++++++++++++++++-------------------- 1 file changed, 33 insertions(+), 34 deletions(-) diff --git a/fees/mstable-v2/index.ts b/fees/mstable-v2/index.ts index 4ff4b0a3df..33ae335374 100644 --- a/fees/mstable-v2/index.ts +++ b/fees/mstable-v2/index.ts @@ -4,40 +4,40 @@ import { GraphQLClient } from "graphql-request"; import * as sdk from "@defillama/sdk"; const queryManagerFeeMinteds = ` - query managerFeeMinteds($manager: Bytes!, $startTimestamp: BigInt!, $endTimestamp: BigInt!, $first: Int!, $skip: Int!) { - managerFeeMinteds( - where: { manager: $manager, managerFee_not: 0, blockTimestamp_gte: $startTimestamp, blockTimestamp_lte: $endTimestamp }, - first: $first, skip: $skip, orderBy: blockTimestamp, orderDirection: desc - ) { managerFee, tokenPriceAtFeeMint, pool, manager, block } - }` +query managerFeeMinteds($manager: Bytes!, $startTimestamp: BigInt!, $endTimestamp: BigInt!, $first: Int!, $skip: Int!) { + managerFeeMinteds( + where: { manager: $manager, managerFee_not: 0, blockTimestamp_gte: $startTimestamp, blockTimestamp_lte: $endTimestamp }, + first: $first, skip: $skip, orderBy: blockTimestamp, orderDirection: desc + ) { managerFee, tokenPriceAtFeeMint, pool, manager, block } +}` const queryEntryFeeMinteds = ` - query entryFeeMinteds($manager: Bytes!, $startTimestamp: BigInt!, $endTimestamp: BigInt!, $first: Int!, $skip: Int!) { - entryFeeMinteds( - where: { managerAddress: $manager, time_gte: $startTimestamp, time_lte: $endTimestamp }, - first: $first, skip: $skip, orderBy: time, orderDirection: desc - ) { entryFeeAmount, tokenPrice } - }` +query entryFeeMinteds($manager: Bytes!, $startTimestamp: BigInt!, $endTimestamp: BigInt!, $first: Int!, $skip: Int!) { + entryFeeMinteds( + where: { managerAddress: $manager, time_gte: $startTimestamp, time_lte: $endTimestamp }, + first: $first, skip: $skip, orderBy: time, orderDirection: desc + ) { entryFeeAmount, tokenPrice } +}` const queryExitFeeMinteds = ` - query exitFeeMinteds($manager: Bytes!, $startTimestamp: BigInt!, $endTimestamp: BigInt!, $first: Int!, $skip: Int!) { - exitFeeMinteds( - where: { managerAddress: $manager, time_gte: $startTimestamp, time_lte: $endTimestamp }, - first: $first, skip: $skip, orderBy: time, orderDirection: desc - ) { exitFeeAmount, tokenPrice } - }` - -const CONFIG = { +query exitFeeMinteds($manager: Bytes!, $startTimestamp: BigInt!, $endTimestamp: BigInt!, $first: Int!, $skip: Int!) { + exitFeeMinteds( + where: { managerAddress: $manager, time_gte: $startTimestamp, time_lte: $endTimestamp }, + first: $first, skip: $skip, orderBy: time, orderDirection: desc + ) { exitFeeAmount, tokenPrice } +}` + +const CONFIG: any = { [CHAIN.ETHEREUM]: { endpoint: sdk.graph.modifyEndpoint("HSPZATdnDvYRNPBJm7eSrzkTeRZqhqYvy7c3Ngm9GCTL"), mstableManagerAddress: "0x3dd46846eed8D147841AE162C8425c08BD8E1b41", }, }; -const fetchHistoricalFees = async (chainId: CHAIN, query: string, dataField: string, startTimestamp: number, endTimestamp: number) => { +const fetchHistoricalFees = async (chainId: string, query: string, dataField: string, startTimestamp: number, endTimestamp: number) => { const { endpoint, mstableManagerAddress } = CONFIG[chainId]; - let allData = []; + let allData: Array = []; let skip = 0; const batchSize = 1000; @@ -58,7 +58,7 @@ const fetchHistoricalFees = async (chainId: CHAIN, query: string, dataField: str skip += batchSize; if (entries.length < batchSize) break; - } catch (e) { + } catch (e: any) { throw new Error(`Error fetching data for chain ${chainId}: ${e.message}`); } } @@ -95,13 +95,13 @@ const calculateExitFees = (data: any): number => return acc + result; }, 0); -const fetch = async ({ chain, endTimestamp, startTimestamp }: FetchOptions) => { - const config = CONFIG[chain]; - if (!config) throw new Error(`Unsupported chain: ${chain}`); +const fetch = async (_1: any, _2: any, options: FetchOptions) => { + const config = CONFIG[options.chain]; + if (!config) throw new Error(`Unsupported chain: ${options.chain}`); - const dailyManagerFeesEvents = await fetchHistoricalFees(chain as CHAIN, queryManagerFeeMinteds, 'managerFeeMinteds', startTimestamp, endTimestamp); - const dailyEntryFeesEvents = await fetchHistoricalFees(chain as CHAIN, queryEntryFeeMinteds, 'entryFeeMinteds', startTimestamp, endTimestamp); - const dailyExitFeesEvents = await fetchHistoricalFees(chain as CHAIN, queryExitFeeMinteds, 'exitFeeMinteds', startTimestamp, endTimestamp); + const dailyManagerFeesEvents = await fetchHistoricalFees(options.chain, queryManagerFeeMinteds, 'managerFeeMinteds', options.startTimestamp, options.endTimestamp); + const dailyEntryFeesEvents = await fetchHistoricalFees(options.chain, queryEntryFeeMinteds, 'entryFeeMinteds', options.startTimestamp, options.endTimestamp); + const dailyExitFeesEvents = await fetchHistoricalFees(options.chain, queryExitFeeMinteds, 'exitFeeMinteds', options.startTimestamp, options.endTimestamp); const managerFees = calculateManagerFees(dailyManagerFeesEvents); const entryFees = calculateEntryFees(dailyEntryFeesEvents); @@ -112,22 +112,21 @@ const fetch = async ({ chain, endTimestamp, startTimestamp }: FetchOptions) => { return { dailyFees, dailyRevenue: dailyFees, - timestamp: endTimestamp, + dailyProtocolRevenue: dailyFees, }; } const methodology = { Fees: 'All fees generated from mStable vaults.', Revenue: 'All revenue collected by the mStable protocol.', + ProtocolRevenue: 'All revenue collected by the mStable protocol.', } const adapter: SimpleAdapter = { fetch, methodology, - adapter: { - [CHAIN.ETHEREUM]: { start: '2025-08-12', }, - }, - version: 2 + chains: [CHAIN.ETHEREUM], + start: '2025-08-12', } export default adapter;