diff --git a/.github/workflows/commentResult.js b/.github/workflows/commentResult.js index 140cce99e3..8afad4f98a 100644 --- a/.github/workflows/commentResult.js +++ b/.github/workflows/commentResult.js @@ -9,19 +9,24 @@ async function main() { const [_, adapterName] = adapterNameKey.split('@') - const errorString = '------ ERROR ------'; - const summaryIndex = file.indexOf('_______________________________________'); + const errorString = 'ERROR'; + const summaryIndex = file.indexOf('---------------------------------------------------'); const errorIndex = file.indexOf(errorString); let body; if (summaryIndex != -1) { - body = `The ${adapterName} adapter exports: - \n \n ${file.substring(summaryIndex).replaceAll('\n', '\n ')}`; + body = `The ${adapterName} adapter exports: + \n \n ${file.replaceAll('\n', '\n ')}`; + console.info(`Posting comment:\n${body}`) } else if (errorIndex != -1) { - body = `Error while running adapter ${adapterName} adapter: + body = `Error while running adapter ${adapterName} adapter: \n \n ${file.split(errorString)[1].replaceAll('\n', '\n ')}`; - } else + console.info(`Posting comment:\n${body}`) + } else { + console.info(`No error or summary found in log file`); return; + } + console.info(`Posting comment:\n${body}`) @@ -37,4 +42,4 @@ async function main() { function translate(input) { return input ? translate(input.substring(1)) + input[0] : input; }; -main(); \ No newline at end of file +main(); diff --git a/.github/workflows/getFileList.js b/.github/workflows/getFileList.js index d4a5c63022..62355afe4c 100644 --- a/.github/workflows/getFileList.js +++ b/.github/workflows/getFileList.js @@ -1,4 +1,4 @@ -const ALLOWED_ROOTS = ['volumes', 'dexs', 'options', 'derivatives', 'incentives', 'fees', 'options', 'protocols'] +const ALLOWED_ROOTS = ['volumes', 'dexs', 'options', 'derivatives', 'incentives', 'fees', 'options', 'protocols', 'aggregators','aggregator-derivatives'] const MODIFIED = parse(process.env.MODIFIED) const ADDED = parse(process.env.ADDED) const fileSet = new Set(); @@ -13,4 +13,4 @@ console.log(JSON.stringify([...fileSet])) function parse(data) { return data.replace('[', '').replace(']', '').split(',') -} \ No newline at end of file +} diff --git a/.github/workflows/test-adapter.yml b/.github/workflows/test-adapter.yml index e4252de8cc..6674b61042 100644 --- a/.github/workflows/test-adapter.yml +++ b/.github/workflows/test-adapter.yml @@ -13,6 +13,15 @@ jobs: uses: actions/checkout@v2 - name: Run changes files through test script run: | + # Store the current commit hash in a variable + current_commit=$(git rev-parse HEAD) + + # Checkout to master to check if new adapters files are of v2 + git fetch origin master:master + + # Checkout back to the original commit + git checkout $current_commit + RUN_FILES=$( MODIFIED=${{ steps.file_changes.outputs.files_modified}} \ ADDED=${{ steps.file_changes.outputs.files_added}} \ @@ -24,21 +33,20 @@ jobs: exit 0 fi - yarn install --production - yarn upgrade @defillama/sdk + npm ci list=$(echo $RUN_FILES | tr -d '"[]' | tr "," "\n") for i in ${list} - do - { + do + { IFS='@' read -r -a array <<< "$i" - yarn test ${array[0]} ${array[1]} 2>&1 | tee output.txt + npm run test ${array[0]} ${array[1]} 2>&1 | tee output.txt node ${{ github.workspace }}/.github/workflows/commentResult.js /home/runner/work/dimension-adapters/dimension-adapters/output.txt "${{ github.repository_owner }}" "${{ github.event.repository.name }}" "${{ github.event.number }}" ${i} if grep -q "\-\-\-\- ERROR \-\-\-\-" output.txt; then exit 1; fi - } || { + } || { echo -n $i echo ' doesnt run' } diff --git a/.github/workflows/ts-check.yml b/.github/workflows/ts-check.yml index d91e6701da..1702b75ddc 100644 --- a/.github/workflows/ts-check.yml +++ b/.github/workflows/ts-check.yml @@ -7,13 +7,12 @@ jobs: runs-on: ubuntu-latest steps: - uses: actions/checkout@v2 - - run: yarn run update-submodules - name: Get Node.js uses: actions/setup-node@v1 with: node-version: '16' - - run: yarn + - run: npm ci - name: Checking adapters - run: yarn run ts-check + run: npm run ts-check - name: Checking cli - run: yarn run ts-check-cli \ No newline at end of file + run: npm run ts-check-cli \ No newline at end of file diff --git a/adapters/types.ts b/adapters/types.ts index 475e856242..c4756f9aa0 100644 --- a/adapters/types.ts +++ b/adapters/types.ts @@ -69,10 +69,10 @@ export type IStartTimestamp = () => Promise export type BaseAdapter = { [chain: string]: { - start: IStartTimestamp | number - fetch: Fetch|FetchV2; + start?: IStartTimestamp | number + fetch: Fetch | FetchV2; runAtCurrTime?: boolean; - customBackfill?: Fetch; + customBackfill?: Fetch | FetchV2; meta?: { methodology?: string | IJSON hallmarks?: [number, string][] @@ -119,6 +119,8 @@ export type FetchResultVolume = FetchResultBase & { dailyShortOpenInterest?: FetchResponseValue dailyLongOpenInterest?: FetchResponseValue dailyOpenInterest?: FetchResponseValue + dailyBridgeVolume?: FetchResponseValue + totalBridgeVolume?: FetchResponseValue }; // FEES @@ -170,11 +172,21 @@ export enum AdapterType { OPTIONS = 'options', PROTOCOLS = 'protocols', ROYALTIES = 'royalties', - AGGREGATOR_DERIVATIVES = 'aggregator-derivatives' + AGGREGATOR_DERIVATIVES = 'aggregator-derivatives', + BRIDGE_AGGREGATORS = 'bridge-aggregators', } export type FetchResult = FetchResultVolume & FetchResultFees & FetchResultAggregators & FetchResultOptions & FetchResultIncentives +export const whitelistedDimensionKeys = new Set([ + 'startTimestamp', 'chain', 'timestamp','block', + + 'dailyVolume', 'totalVolume', 'dailyShortOpenInterest', 'dailyLongOpenInterest', 'dailyOpenInterest', 'dailyBridgeVolume', 'totalBridgeVolume', + 'totalFees', 'dailyFees', 'dailyUserFees', 'totalRevenue', 'dailyRevenue', 'dailyProtocolRevenue', 'dailyHoldersRevenue', 'dailySupplySideRevenue', 'totalProtocolRevenue', 'totalSupplySideRevenue', 'totalUserFees', 'dailyBribesRevenue', 'dailyTokenTaxes', 'totalHoldersRevenue', + 'tokenIncentives', + 'totalPremiumVolume', 'totalNotionalVolume', 'dailyPremiumVolume', 'dailyNotionalVolume', +]) + // End of specific adaptors type export interface IJSON { diff --git a/adapters/utils/runAdapter.ts b/adapters/utils/runAdapter.ts index 13756d73f9..df4a2bc0d0 100644 --- a/adapters/utils/runAdapter.ts +++ b/adapters/utils/runAdapter.ts @@ -1,13 +1,19 @@ -import { Balances, ChainApi, getEventLogs, getProvider } from '@defillama/sdk' +import { Balances, ChainApi, getEventLogs, getProvider, elastic } from '@defillama/sdk' import { BaseAdapter, ChainBlocks, DISABLED_ADAPTER_KEY, Fetch, FetchGetLogsOptions, FetchOptions, FetchResultGeneric, FetchV2, } from '../types' import { getBlock } from "../../helpers/getBlock"; import { getUniqStartOfTodayTimestamp } from '../../helpers/getUniSubgraphFees'; const ONE_DAY_IN_SECONDS = 60 * 60 * 24 +function getUnixTimeNow() { + return Math.floor(Date.now() / 1000) +} + export default async function runAdapter(volumeAdapter: BaseAdapter, cleanCurrentDayTimestamp: number, chainBlocks: ChainBlocks, id?: string, version?: string, { - adapterVersion = 1 + adapterVersion = 1, + isTest = false, }: any = {}) { + const closeToCurrentTime = Math.trunc(Date.now() / 1000) - cleanCurrentDayTimestamp < 24 * 60 * 60 // 12 hours const chains = Object.keys(volumeAdapter).filter(c => c !== DISABLED_ADAPTER_KEY) const validStart = {} as { @@ -18,9 +24,23 @@ export default async function runAdapter(volumeAdapter: BaseAdapter, cleanCurren } await Promise.all(chains.map(setChainValidStart)) - return Promise.all(chains.filter(chain => validStart[chain]?.canRun).map(getChainResult)) + const response = await Promise.all(chains.filter(chain => { + const res = validStart[chain]?.canRun + if (isTest && !res) console.log(`Skipping ${chain} because the configured start time is ${new Date(validStart[chain]?.startTimestamp * 1e3).toUTCString()} \n\n`) + return validStart[chain]?.canRun + }).map(getChainResult)) + return response async function getChainResult(chain: string) { + const startTime = getUnixTimeNow() + const metadata = { + application: "dimensions", + type: 'protocol-chain', + name: id, + chain, + version, + } + const fetchFunction = volumeAdapter[chain].customBackfill ?? volumeAdapter[chain].fetch try { const options = await getOptionsObject(cleanCurrentDayTimestamp, chain, chainBlocks) @@ -47,19 +67,31 @@ export default async function runAdapter(volumeAdapter: BaseAdapter, cleanCurren result[key] = +Number(result[key]).toFixed(0) if (isNaN(result[key] as number)) throw new Error(`[${chain}]Value: ${value} ${key} is NaN`) } + + const endTime = getUnixTimeNow() + await elastic.addRuntimeLog({ runtime: endTime - startTime, success: true, metadata, }) + return { chain, startTimestamp: validStart[chain].startTimestamp, ...result } } catch (error) { - try { (error as any).chain = chain } catch { } + + const endTime = getUnixTimeNow() + + try { + await elastic.addErrorLog({ error, metadata, errorString: error?.toString(), } as any) + await elastic.addRuntimeLog({ runtime: endTime - startTime, success: false, metadata, }); + + (error as any).chain = chain + } catch { } throw error } } async function getOptionsObject(timestamp: number, chain: string, chainBlocks: ChainBlocks): Promise { - const withinTwoHours = Math.trunc(Date.now() / 1000) - timestamp < 2 * 60 * 60 // 2 hours + const withinTwoHours = Math.trunc(Date.now() / 1000) - timestamp < 24 * 60 * 60 // 24 hours const createBalances: () => Balances = () => { return new Balances({ timestamp: closeToCurrentTime ? undefined : timestamp, chain }) } @@ -88,7 +120,7 @@ export default async function runAdapter(volumeAdapter: BaseAdapter, cleanCurren const api = new ChainApi({ chain, timestamp: withinTwoHours ? undefined : timestamp, block: toBlock }) const startOfDay = getUniqStartOfTodayTimestamp(new Date(toTimestamp * 1000)) const startTimestamp = fromTimestamp - const endTimestamp = toTimestamp + const endTimestamp = toTimestamp + 1 const getStartBlock = getFromBlock const getEndBlock = getToBlock const toApi = api diff --git a/aggregator-derivatives/.gitkeep b/aggregator-derivatives/.gitkeep new file mode 100644 index 0000000000..e69de29bb2 diff --git a/aggregator-derivatives/bitoro/index.ts b/aggregator-derivatives/bitoro/index.ts new file mode 100644 index 0000000000..94f42515b4 --- /dev/null +++ b/aggregator-derivatives/bitoro/index.ts @@ -0,0 +1,55 @@ +import fetchURL from "../../utils/fetchURL"; +import { FetchResult, SimpleAdapter } from "../../adapters/types"; +import { CHAIN } from "../../helpers/chains"; + +const BitoroX_BASE_URL = "https://min-api.bitoro.network/btr/stats/global"; +const BitoroPro_BASE_URL = "https://min-api.inj.bitoro.network/stats/global"; +const startTimestamp_bitoro_x = 1711324800; // 2024-03-25 00:00:00 +const startTimestamp_bitoro_pro = 1718323200; // 2024-06-14 00:00:00 + +const getBitoroXUrl = (startTime: number, endTime: number): string => { + return `${BitoroX_BASE_URL}?start=${startTime}&end=${endTime}`; +} + +const getBitoroProUrl = (startTime: number, endTime: number): string => { + return `${BitoroPro_BASE_URL}?start=${startTime}&end=${endTime}`; +} + +const fetchBitoroX = async (_:any, _b:any ,options: any): Promise => { + const { endTimestamp, startTimestamp } = options; + const dailyVolume = await fetchURL(getBitoroXUrl(startTimestamp, endTimestamp)); + const totalVolume = await fetchURL(getBitoroXUrl(startTimestamp_bitoro_x, endTimestamp)); + + return { + timestamp: startTimestamp, + dailyVolume: dailyVolume.volume || 0, + totalVolume: totalVolume.volume || 0, + }; +}; + +const fetchBitoroPro = async (_:any, _b:any ,options: any): Promise => { + const { fromTimestamp, toTimestamp } = options; + const dailyVolume = await fetchURL(getBitoroProUrl(fromTimestamp, toTimestamp)); + const totalVolume = await fetchURL(getBitoroProUrl(startTimestamp_bitoro_pro, toTimestamp)); + + return { + timestamp: fromTimestamp, + dailyVolume: dailyVolume.volume || 0, + totalVolume: totalVolume.volume || 0, + }; +}; + +const adapter: SimpleAdapter = { + adapter: { + [CHAIN.ARBITRUM]: { + fetch: fetchBitoroX, + start: startTimestamp_bitoro_x + }, + [CHAIN.INJECTIVE]: { + fetch: fetchBitoroPro, + start: startTimestamp_bitoro_pro + } + } +} + +export default adapter; diff --git a/aggregator-derivatives/flat-money/index.ts b/aggregator-derivatives/flat-money/index.ts new file mode 100644 index 0000000000..5db77df912 --- /dev/null +++ b/aggregator-derivatives/flat-money/index.ts @@ -0,0 +1,148 @@ +import { SimpleAdapter, FetchV2, FetchResultV2 } from "../../adapters/types"; +import { CHAIN } from "../../helpers/chains"; +import { gql, GraphQLClient } from "graphql-request"; + +const CONFIG = { + [CHAIN.BASE]: { + startTimestamp: 1721161357, + endpoint: "https://api.studio.thegraph.com/query/48129/flatcoin-base/version/latest", + leverageOpensQuery: gql` + query leverageOpens($startTimestamp: BigInt!, $endTimestamp: BigInt!) { + leverageOpens( + where: { blockTimestamp_gte: $startTimestamp, blockTimestamp_lte: $endTimestamp }, + first: 1000, orderBy: blockTimestamp, orderDirection: asc + ) { + margin, + size, + entryPrice + } + }`, + leverageAdjustsQuery: gql` + query leverageAdjusts($startTimestamp: BigInt!, $endTimestamp: BigInt!) { + leverageAdjusts( + where: { blockTimestamp_gte: $startTimestamp, blockTimestamp_lte: $endTimestamp }, + first: 1000, orderBy: blockTimestamp, orderDirection: asc + ) { + marginDelta, + sizeDelta, + adjustPrice + } + }`, + leverageClosesQuery: gql` + query leverageCloses($startTimestamp: BigInt!, $endTimestamp: BigInt!) { + leverageCloses( + where: { blockTimestamp_gte: $startTimestamp, blockTimestamp_lte: $endTimestamp }, + first: 1000, orderBy: blockTimestamp, orderDirection: asc + ) { + settledMargin, + size, + closePrice + } + }`, + leverageOpensField: "leverageOpens", + leverageAdjustsField: "leverageAdjusts", + leverageClosesField: "leverageCloses" + }, +}; + +const fetchVolume = async (chainId: CHAIN, query: string, volumeField: string, startTimestamp: number, endTimestamp: number) => { + const { endpoint } = CONFIG[chainId]; + + let allData = []; + let skip = 0; + const batchSize = 1000; + + while (true) { + try { + const data = await new GraphQLClient(endpoint).request(query, { + startTimestamp, + endTimestamp, + first: batchSize, + skip + }); + + const entries = data[volumeField]; + if (entries.length === 0) break; + allData = allData.concat(entries); + skip += batchSize; + + if (entries.length < batchSize) break; + + await sleep(500); + } catch (e) { + throw new Error(`Error fetching data for chain ${chainId}: ${e.message}`); + } + } + return allData; +}; + +const calculateOpensVolume = (data: any): number => + data.reduce((acc: number, item: any) => { + const priceFormatted = Number(item.entryPrice) / 1e18; + const marginFormatted = Number(item.margin) / 1e18; + const sizeFormatted = Number(item.size) / 1e18; + return acc + (marginFormatted + sizeFormatted) * priceFormatted; + }, 0); + +const calculateAdjustsVolume = (data: any): number => + data.reduce((acc: number, item: any) => { + const priceFormatted = Number(item.adjustPrice) / 1e18; + const marginDeltaFormatted = Number(Math.abs(item.marginDelta)) / 1e18; + const sizeDeltaFormatted = Number(Math.abs(item.sizeDelta)) / 1e18; + return acc + (marginDeltaFormatted + sizeDeltaFormatted) * priceFormatted; + }, 0); + +const calculateClosesVolume = (data: any): number => + data.reduce((acc: number, item: any) => { + const priceFormatted = Number(item.closePrice) / 1e18; + const settledMarginFormatted = Number(item.settledMargin) / 1e18; + const sizeFormatted = Number(item.size) / 1e18; + return acc + (settledMarginFormatted + sizeFormatted) * priceFormatted; + }, 0); + +const fetch: FetchV2 = async ({ startTimestamp, endTimestamp, chain }): Promise => { + const config = CONFIG[chain]; + if (!config) throw new Error(`Unsupported chain: ${chain}`); + + const [ + dailyOpensData, + dailyAdjustsData, + dailyClosesData, + totalOpensData, + totalAdjustsData, + totalClosesData + ] = await Promise.all([ + fetchVolume(chain as CHAIN, config.leverageOpensQuery, config.leverageOpensField, startTimestamp || (endTimestamp - 86400), endTimestamp), + fetchVolume(chain as CHAIN, config.leverageAdjustsQuery, config.leverageAdjustsField, startTimestamp || (endTimestamp - 86400), endTimestamp), + fetchVolume(chain as CHAIN, config.leverageClosesQuery, config.leverageClosesField, startTimestamp || (endTimestamp - 86400), endTimestamp), + fetchVolume(chain as CHAIN, config.leverageOpensQuery, config.leverageOpensField, config.startTimestamp, endTimestamp), + fetchVolume(chain as CHAIN, config.leverageAdjustsQuery, config.leverageAdjustsField, config.startTimestamp, endTimestamp), + fetchVolume(chain as CHAIN, config.leverageClosesQuery, config.leverageClosesField, config.startTimestamp, endTimestamp), + ]); + + return { + timestamp: endTimestamp, + dailyVolume: calculateOpensVolume(dailyOpensData) + + calculateAdjustsVolume(dailyAdjustsData) + + calculateClosesVolume(dailyClosesData), + totalVolume: calculateOpensVolume(totalOpensData) + + calculateAdjustsVolume(totalAdjustsData) + + calculateClosesVolume(totalClosesData) + }; +}; + +function sleep(ms) { + return new Promise(resolve => setTimeout(resolve, ms)); +} + +const adapter: SimpleAdapter = { + adapter: Object.fromEntries( + Object.entries(CONFIG).map(([chain, config]) => [ + chain, + { fetch, start: config.startTimestamp } + ]) + ), + version: 2 +}; + +export default adapter; diff --git a/aggregator-derivatives/kwenta/index.ts b/aggregator-derivatives/kwenta/index.ts new file mode 100644 index 0000000000..0e8c6309ea --- /dev/null +++ b/aggregator-derivatives/kwenta/index.ts @@ -0,0 +1,87 @@ +import { SimpleAdapter, FetchV2, FetchResultV2 } from "../../adapters/types"; +import { CHAIN } from "../../helpers/chains"; +import { gql, GraphQLClient } from "graphql-request"; + +const PROVIDER_CONFIG = { + [CHAIN.BASE]: { + startTimestamp: 1702943900, + endpoint: "https://subgraph.satsuma-prod.com/404b0c87e4a3/kwenta/base-perps-v3/api", + query: gql` + query aggregateStats($startTimestamp: BigInt!, $endTimestamp: BigInt!) { + perpsV3AggregateStats( + where: { timestamp_gte: $startTimestamp, timestamp_lte: $endTimestamp, period: "86400", marketId: "0" }, + first: 9999, orderBy: timestamp, orderDirection: asc + ) { timestamp, volume } + }`, + volumeField: "perpsV3AggregateStats" + }, + [CHAIN.OPTIMISM]: { + startTimestamp: 1671494100, + endpoint: "https://subgraph.satsuma-prod.com/404b0c87e4a3/kwenta/optimism-perps/api", + query: gql` + query aggregateStats($startTimestamp: BigInt!, $endTimestamp: BigInt!) { + futuresAggregateStats( + where: { timestamp_gte: $startTimestamp, timestamp_lte: $endTimestamp, asset: "0x", period: "86400" }, + first: 9999, orderBy: timestamp, orderDirection: asc + ) { timestamp, volume } + }`, + volumeField: "futuresAggregateStats" + }, + [CHAIN.ARBITRUM]: { + startTimestamp: 1696032000, + endpoint: "https://subgraph.perennial.finance/arbitrum", + query: gql` + query aggregateStats($startTimestamp: BigInt!, $endTimestamp: BigInt!) { + marketAccumulations( + where: { and: [{ bucket: daily, timestamp_gte: $startTimestamp, timestamp_lte: $endTimestamp }, + { or: [{ shortNotional_gt: "0" }, { longNotional_gt: "0" }] }] }, + first: 9999, orderBy: timestamp, orderDirection: asc + ) { timestamp, longNotional, shortNotional } + }`, + volumeField: "marketAccumulations" + } +}; + +const fetchVolume = async (chainId: CHAIN, startTimestamp: number, endTimestamp: number) => { + const { endpoint, query } = PROVIDER_CONFIG[chainId]; + try { + return await new GraphQLClient(endpoint).request(query, { startTimestamp, endTimestamp }); + } catch (e) { + throw new Error(`Failed to fetch data for chain ${chainId}: ${e.message}`); + } +}; + +const calculateVolume = (data: any, volumeField: string): number => + data[volumeField].reduce((acc: number, item: any) => + acc + (volumeField === "marketAccumulations" + ? (Number(item.longNotional) + Number(item.shortNotional)) / 1e6 + : Number(item.volume) / 1e18 + ), 0); + +const fetch: FetchV2 = async ({ startTimestamp, endTimestamp, chain }): Promise => { + const config = PROVIDER_CONFIG[chain]; + if (!config) throw new Error(`Unsupported chain: ${chain}`); + + const [dailyData, totalData] = await Promise.all([ + fetchVolume(chain as CHAIN, startTimestamp || (endTimestamp - 86400), endTimestamp), + fetchVolume(chain as CHAIN, config.startTimestamp, endTimestamp) + ]); + + return { + timestamp: endTimestamp, + dailyVolume: calculateVolume(dailyData, config.volumeField).toString(), + totalVolume: calculateVolume(totalData, config.volumeField).toString() + }; +}; + +const adapter: SimpleAdapter = { + adapter: Object.fromEntries( + Object.entries(PROVIDER_CONFIG).map(([chain, config]) => [ + chain, + { fetch, start: config.startTimestamp } + ]) + ), + version: 2 +}; + +export default adapter; \ No newline at end of file diff --git a/aggregator-derivatives/perpie/index.ts b/aggregator-derivatives/perpie/index.ts new file mode 100644 index 0000000000..94668c8774 --- /dev/null +++ b/aggregator-derivatives/perpie/index.ts @@ -0,0 +1,72 @@ +import { + BreakdownAdapter, + Fetch, + FetchOptions, + FetchResult, + FetchResultV2, + FetchV2 +} from "../../adapters/types"; +import { queryDune } from "../../helpers/dune"; +import { getUniqStartOfTodayTimestamp } from "../../helpers/getUniSubgraphFees"; + +const arbitrumStartTimestamp = 1696982400; // 2023-10-11 00:00:00 + +type StatRow = { + volume_24hr: number; + fees_24hr: number; + total_volume: number; + total_fees: number; +}; + +const chainsMap: Record = { + ARBITRUM: "arbitrum", +}; + +const fetchVolumeAndFees: (chain: string) => FetchV2 = + (chain: string) => + async (options: FetchOptions): Promise => { + chain; + + const date = new Date(options.startOfDay * 1000); + + const dayStartOfDayTimestamp = getUniqStartOfTodayTimestamp(date); + + let data = ( + await queryDune("3855069", { + daytime: date.toISOString(), + }) + )[0] as StatRow; + + return { + dailyVolume: data.volume_24hr || 0, + totalVolume: data.total_volume || 0, + dailyRevenue: data.fees_24hr || 0, + totalRevenue: data.total_fees || 0, + timestamp: dayStartOfDayTimestamp, + }; + }; + +const fetchAll: (chain: string) => Fetch = + (chain: string) => + async (_a: any, _t: any ,options: FetchOptions): Promise => { + const volumeAndFees = await fetchVolumeAndFees(chain)(options); + return { ...volumeAndFees } as FetchResult; + }; +const adapter: BreakdownAdapter = { + isExpensiveAdapter: true, + breakdown: { + derivatives: { + ...Object.values(chainsMap).reduce((acc, chain) => { + return { + ...acc, + [(chainsMap as any)[chain] || chain]: { + start: arbitrumStartTimestamp, + fetch: fetchAll(chain), + }, + }; + }, {}), + }, + }, +}; + +export default adapter; diff --git a/aggregator-derivatives/rage-trade/index.ts b/aggregator-derivatives/rage-trade/index.ts new file mode 100644 index 0000000000..5d69779b01 --- /dev/null +++ b/aggregator-derivatives/rage-trade/index.ts @@ -0,0 +1,44 @@ +import { postURL } from '../../utils/fetchURL' +import { FetchResult, SimpleAdapter } from '../../adapters/types' +import { CHAIN } from '../../helpers/chains' + +const URL = 'https://leaderboard-production.rage.trade' +const endpoint = '/api/stats/defillama' +const arbitrumStartTimestamp = 1701302400 // 2023-11-30 00:00:00 +const optimismStartTimestamp = 1701302400 // 2023-11-30 00:00:00 +const ethereumStartTimestamp = 1710374400 // 2023-11-30 00:00:00 + +const fetch = + (chain: string) => + async (timestamp: number): Promise => { + const { dailyVolume: dailyVolumeE30, totalVolume: totalVolumeE30 } = + await postURL(`${URL}${endpoint}`, { + timestamp, + chain, + }) + + return { + dailyVolume: dailyVolumeE30 ? dailyVolumeE30 / 1e30 : 0, + totalVolume: totalVolumeE30 ? totalVolumeE30 / 1e30 : 0, + timestamp, + } + } + +const adapter: SimpleAdapter = { + adapter: { + [CHAIN.ARBITRUM]: { + fetch: fetch(CHAIN.ARBITRUM), + start: arbitrumStartTimestamp, + }, + [CHAIN.ETHEREUM]: { + fetch: fetch(CHAIN.ETHEREUM), + start: ethereumStartTimestamp, + }, + [CHAIN.OPTIMISM]: { + fetch: fetch(CHAIN.OPTIMISM), + start: optimismStartTimestamp, + }, + }, +} + +export default adapter diff --git a/aggregator-derivatives/sharpe-perp/index.ts b/aggregator-derivatives/sharpe-perp/index.ts new file mode 100644 index 0000000000..fa4e03cf79 --- /dev/null +++ b/aggregator-derivatives/sharpe-perp/index.ts @@ -0,0 +1,27 @@ +import fetchURL from "../../utils/fetchURL"; +import { FetchResultV2 } from "../../adapters/types"; +import { CHAIN } from "../../helpers/chains"; + +const fetch = async (options: any): Promise => { + let timestamp = options.toTimestamp + + const fetchOptions:any = {method: 'GET'}; + + const data:any = await fetchURL('https://api-evm.orderly.network/v1/public/volume/stats?broker_id=sharpe_ai') + const dailyData:any = await fetchURL('https://base-api.sharpe.ai/api/dailySharpePerpVolume') + + return { + totalVolume: data?.data?.perp_volume_ltd, + dailyVolume: dailyData?.dailyVolume + }; +}; +// CHAIN.ARBITRUM, CHAIN.MANTLE, CHAIN.OPTIMISM, CHAIN.BASE, +export default { + adapter: { + [CHAIN.ETHEREUM]: { + fetch: fetch, + start: 1711963031 + }, + }, + version: 2 +} diff --git a/aggregator-derivatives/unidex-agg-perp/index.ts b/aggregator-derivatives/unidex-agg-perp/index.ts new file mode 100644 index 0000000000..084344af33 --- /dev/null +++ b/aggregator-derivatives/unidex-agg-perp/index.ts @@ -0,0 +1,161 @@ +import * as sdk from "@defillama/sdk"; +import { FetchResultVolume } from "../../adapters/types"; +import { CHAIN } from "../../helpers/chains"; +import { getTimestampAtStartOfDayUTC } from "../../utils/date"; +import { Chain } from "@defillama/sdk/build/general"; +import request, { gql } from "graphql-request"; +import customBackfill from "../../helpers/customBackfill"; + +interface IReferralRecord { + volume: string; // Assuming volume is a string that represents a number + timestamp: number; +} + +type TChainIDs = { + [key in Chain]?: number; +}; + +const chainIDs: TChainIDs = { + [CHAIN.FANTOM]: 250, + [CHAIN.ARBITRUM]: 42161, + [CHAIN.OPTIMISM]: 10, + [CHAIN.ERA]: 324, + [CHAIN.BASE]: 8453, + [CHAIN.EVMOS]: 9001, + [CHAIN.METIS]: 1088, +}; + +interface IDayProduct { + cumulativeVolumeUsd: number; + chainId: number; +} + +const fetchReferralVolume = async (timestamp: number): Promise => { + const todaysTimestamp = getTimestampAtStartOfDayUTC(timestamp); + + const referralQuery = gql` + { + affiliateStats( + where: {affiliate: "0x8c128f336b479b142429a5f351af225457a987fa", timestamp_gt: "${todaysTimestamp}"} + ) { + volume + } + } + `; + + const referralEndpoint = "https://subgraph.satsuma-prod.com/3b2ced13c8d9/gmx/gmx-arbitrum-referrals/api"; + const referralRes = await request(referralEndpoint, referralQuery); + // If there's no volume data, return 0 + if (!referralRes.affiliateStats || referralRes.affiliateStats.length === 0) { + return 0; + } + + return Number(referralRes.affiliateStats[0].volume) / 10 ** 30; +}; + + +const fetch = (chain: Chain) => { + return async (timestamp: number): Promise => { + const todaysTimestamp = getTimestampAtStartOfDayUTC(timestamp); + + const graphQuery = gql` + query MyQuery { + DayProducts(filter: {date: ${todaysTimestamp}}) { + cumulativeVolumeUsd + chainId + } + } + `; + + const endpoint = 'https://arkiver.moltennetwork.com/graphql'; + const response = await request(endpoint, graphQuery); + const dayProducts: IDayProduct[] = response.DayProducts; + + const volumeByChain: { [chainId: number]: number } = {}; + dayProducts.forEach((product) => { + const chainId = product.chainId; + if (chainId === 360) { + // Combine volume for chainID 360 with chainID 42161 + volumeByChain[42161] = (volumeByChain[42161] || 0) + product.cumulativeVolumeUsd; + } else { + volumeByChain[chainId] = (volumeByChain[chainId] || 0) + product.cumulativeVolumeUsd; + } + }); + + const chainID = chainIDs[chain]; + let dailyVolumeUSD = chainID !== undefined ? volumeByChain[chainID] || 0 : 0; + + if (chain === CHAIN.ARBITRUM) { + const referralVolumeUSD = await fetchReferralVolume(timestamp); + dailyVolumeUSD += referralVolumeUSD; + } + + return { + dailyVolume: dailyVolumeUSD.toString(), + timestamp: todaysTimestamp + }; + }; +}; + + +const methodology = { + dailyVolume: "Sum of cumulativeVolumeUsd for all products on the specified chain for the given day", +}; + + +const adapteraggderivative: any = { + adapter: { + [CHAIN.OPTIMISM]: { + fetch: fetch(CHAIN.OPTIMISM), + start: 1687422746, + meta: { + methodology, + }, + }, + [CHAIN.ERA]: { + fetch: fetch(CHAIN.ERA), + start: 1687422746, + meta: { + methodology, + }, + }, + [CHAIN.ARBITRUM]: { + fetch: fetch(CHAIN.ARBITRUM), + start: 1687422746, + customBackfill: customBackfill(CHAIN.ARBITRUM, fetch), + meta: { + methodology, + }, + }, + [CHAIN.BASE]: { + fetch: fetch(CHAIN.BASE), + start: 1687422746, + meta: { + methodology, + }, + }, + [CHAIN.FANTOM]: { + fetch: fetch(CHAIN.FANTOM), + start: 1687422746, + meta: { + methodology, + }, + }, + [CHAIN.METIS]: { + fetch: fetch(CHAIN.METIS), + start: 1687898060, + meta: { + methodology, + }, + }, + [CHAIN.EVMOS]: { + fetch: fetch(CHAIN.EVMOS), + start: 1700104066, + meta: { + methodology, + }, + }, + } +}; + +export default adapteraggderivative; diff --git a/aggregator-derivatives/vooi/index.ts b/aggregator-derivatives/vooi/index.ts new file mode 100644 index 0000000000..796ec33ec2 --- /dev/null +++ b/aggregator-derivatives/vooi/index.ts @@ -0,0 +1,89 @@ +import fetchURL from "../../utils/fetchURL"; +import { FetchResult, SimpleAdapter, FetchOptions } from "../../adapters/types"; +import { CHAIN } from "../../helpers/chains"; + +const URL = "https://vooi-rebates.fly.dev/"; +const endpoint = "defillama/volumes"; +const startTimestampArbitrum = 1714608000; // 02.05.2024 +const startTimestampBlast = 1719792000; // 01.07.2024 +const startTimestampOpBNB = 1717200000; // 01.06.2024 +const startTimestampBase = 1722470400; // 01.08.2024 + +const fetchArbitrum = async (timestamp: number, _t: any, options: FetchOptions): Promise => { + // const timestamp = options.toTimestamp + const fetchData = await fetchURL(`${URL}${endpoint}?ts=${options.startOfDay}`) // returns data for the day before + let orderlyItem = fetchData.find(((item) => item.protocol == "orderly")) + if (!orderlyItem) { + orderlyItem = {dailyVolume: 0, totalVolume: 0} + } + let synfuturesItem = fetchData.filter(((item) => item.protocol == "synfutures")) + if (!synfuturesItem) { + synfuturesItem = {dailyVolume: 0, totalVolume: 0} + } + let kiloexItem = fetchData.filter(((item) => item.protocol == "kiloex")) + if (!kiloexItem) { + kiloexItem = {dailyVolume: 0, totalVolume: 0} + } + let dailyVolume = Number(orderlyItem.dailyVolume) + let totalVolume = Number(orderlyItem.totalVolume) + for (let i in synfuturesItem){ + dailyVolume = Number(dailyVolume) + Number(synfuturesItem[i].dailyVolume) + totalVolume = Number(totalVolume) + Number(synfuturesItem[i].totalVolume) + } + for (let i in kiloexItem){ + dailyVolume = Number(dailyVolume) + Number(kiloexItem[i].dailyVolume) + totalVolume = Number(totalVolume) + Number(kiloexItem[i].totalVolume) + } + return { + dailyVolume, + totalVolume, + timestamp + }; +}; + + +const fetchOpBNB = async (timestamp: number): Promise => { + return { + dailyVolume: 0, + totalVolume: 0, + timestamp + }; +}; + +const fetchBlast = async (timestamp: number): Promise => { + return { + dailyVolume: 0, + totalVolume: 0, + timestamp + }; +}; + +const fetchBase = async (timestamp: number): Promise => { + return { + dailyVolume: 0, + totalVolume: 0, + timestamp + }; +}; + +const adapter: SimpleAdapter = { + adapter: { + [CHAIN.ARBITRUM]: { + fetch: fetchArbitrum, + start: startTimestampArbitrum + }, + [CHAIN.OP_BNB]: { + fetch: fetchOpBNB, + start: startTimestampOpBNB + }, + [CHAIN.BLAST]: { + fetch: fetchBlast, + start: startTimestampBlast + }, + [CHAIN.BASE]: { + fetch: fetchBase, + start: startTimestampBase + }, + }, +} +export default adapter diff --git a/aggregators/1inch-agg/index.ts b/aggregators/1inch-agg/index.ts index 6a569b161b..13ececa496 100644 --- a/aggregators/1inch-agg/index.ts +++ b/aggregators/1inch-agg/index.ts @@ -22,7 +22,7 @@ const fetch = const chainData = data.result.rows.find( (row: any) => chainsMap[row.blockchain] === chain ); - + if (!chainData) throw new Error(`Dune query failed: ${JSON.stringify(data)}`) return { dailyVolume: chainData.volume_24h, timestamp: unixTimestamp, diff --git a/aggregators/7k-aggregator/index.ts b/aggregators/7k-aggregator/index.ts new file mode 100644 index 0000000000..cc4447938f --- /dev/null +++ b/aggregators/7k-aggregator/index.ts @@ -0,0 +1,24 @@ +import fetchURL from '../../utils/fetchURL'; +import { FetchV2, SimpleAdapter } from '../../adapters/types'; +import { CHAIN } from '../../helpers/chains'; + +const URL = 'https://statistic.7k.ag'; + +const fetch: FetchV2 = async ({ fromTimestamp, toTimestamp }) => { + const dailyVolume = await fetchURL( + `${URL}/volume-with-ts?from_timestamp=${fromTimestamp}&to_timestamp=${toTimestamp}`, + ); + return { dailyVolume }; +}; + +const adapter: SimpleAdapter = { + version: 2, + adapter: { + [CHAIN.SUI]: { + fetch, + start: 1719563120, + }, + }, +}; + +export default adapter; diff --git a/aggregators/aggre/index.ts b/aggregators/aggre/index.ts index 15b4cd4bc3..fc9dc65dd3 100644 --- a/aggregators/aggre/index.ts +++ b/aggregators/aggre/index.ts @@ -1,5 +1,5 @@ import { Chain } from "@defillama/sdk/build/general"; -import { FetchOptions, FetchResultAggregators, SimpleAdapter } from "../../adapters/types"; +import { FetchV2, SimpleAdapter } from "../../adapters/types"; import { CHAIN } from "../../helpers/chains"; let abi = ["event SwapExecuted(address indexed user, address tokenIn, address tokenOut, uint amountIn, uint amountOut, uint swapType)"]; @@ -12,13 +12,13 @@ const contract: IContract = { [CHAIN.SCROLL]: '0xcf8bcaCb401C31774EA39296b367B9DaB4F72267', } -const fetch: any = async (timestamp: number, _, { getLogs, createBalances, chain, }: FetchOptions): Promise => { +const fetch: FetchV2 = async ({ getLogs, createBalances, chain, }) => { const dailyVolume = createBalances(); const logs = (await getLogs({ target: contract[chain], eventAbi: abi[0], })) logs.map((log: any) => dailyVolume.add(log.tokenOut, log.amountOut)); - return { dailyVolume, timestamp, }; + return { dailyVolume, }; }; const adapter: SimpleAdapter = { @@ -30,7 +30,8 @@ const adapter: SimpleAdapter = { start: 1698660910, } } - }, {}) + }, {}), + version: 2, }; export default adapter; \ No newline at end of file diff --git a/aggregators/akka/index.ts b/aggregators/akka/index.ts new file mode 100644 index 0000000000..0a24fc2158 --- /dev/null +++ b/aggregators/akka/index.ts @@ -0,0 +1,36 @@ +import fetchURL from "../../utils/fetchURL" +import { FetchResult, SimpleAdapter } from "../../adapters/types"; +import { CHAIN } from "../../helpers/chains"; +import { getUniqStartOfTodayTimestamp } from "../../helpers/getUniSubgraphVolume"; + +const URL = 'https://routerv2.akka.finance'; +const endpoint = '/v2/1116/statistics/dappradar'; +const startTimestamp = 1717200000;// 6/1/2024 + +interface IAPIResponse { + dailyVolume: string; + totalVolume: string; +} + +const fetch = async (timestamp: number): Promise => { + const dayTimestamp = getUniqStartOfTodayTimestamp(new Date(timestamp * 1000)); + const { dailyVolume, totalVolume }: IAPIResponse = (await fetchURL(`${URL}${endpoint}`)); + return { + dailyVolume, + totalVolume, + timestamp: dayTimestamp, + }; +} + +const adapter: SimpleAdapter = { + version: 1, + adapter: { + [CHAIN.CORE]: { + fetch, + runAtCurrTime: true, + start: startTimestamp, + }, + }, +}; + +export default adapter; diff --git a/aggregators/aperture-swap/index.ts b/aggregators/aperture-swap/index.ts new file mode 100644 index 0000000000..b712184a2d --- /dev/null +++ b/aggregators/aperture-swap/index.ts @@ -0,0 +1,130 @@ +import { httpGet } from "../../utils/fetchURL"; +import { ChainBlocks, FetchOptions, SimpleAdapter } from "../../adapters/types"; +import { CHAIN } from "../../helpers/chains"; + +const chainToId: Record = { + [CHAIN.ETHEREUM]: 1, + [CHAIN.ARBITRUM]: 42161, + [CHAIN.AVAX]: 43114, + [CHAIN.BSC]: 56, + [CHAIN.FANTOM]: 250, + [CHAIN.OPTIMISM]: 10, + [CHAIN.POLYGON]: 137, + [CHAIN.LINEA]: 59144, + [CHAIN.SCROLL]: 534352, + [CHAIN.ERA]: 324, + [CHAIN.CRONOS]: 25, + [CHAIN.MANTA]: 169, +}; + + +const url = "https://api.aperture.finance/getMetricsBreakDownSinceInception" + +interface VolumeInfo { + chainId: number; + tve: number; + txCount: number; +} + +interface VolumeResponse { + dailyVolume: VolumeInfo[]; + totalVolume: VolumeInfo[]; +} + +const fetch = async (timestamp: number, _: ChainBlocks, options: FetchOptions) => { + const chainId = chainToId[options.chain] + if (!chainId) { + return { + dailyVolume: 0, + totalVolume: 0, + timestamp: timestamp, + } + } + const fetchUrl = `${url}?chainid=${chainId}×tamp=${timestamp}` + const data: VolumeResponse = (await httpGet(fetchUrl, { timeout: 100000 })); + + if (data) { + let dailyVolume :number = 0 + let totalVolume :number = 0 + if (data.dailyVolume) { + data.dailyVolume.forEach(r => { + if (r.chainId == chainId) { + dailyVolume = r.tve + } + }) + } + + if (data.totalVolume) { + data.totalVolume.forEach(r => { + if (r.chainId == chainId) { + totalVolume = r.tve + } + }) + } + + return { + dailyVolume: dailyVolume, + totalVolume: totalVolume, + timestamp: timestamp + } + } else { + //console.log("no data") + return { + dailyVolume: 0, + totalVolume: 0, + timestamp: timestamp, + } + } +} + +const adapter: SimpleAdapter = { + adapter: { + [CHAIN.ETHEREUM]: { + fetch: fetch, + runAtCurrTime: false, + start: 1689657695, + }, + [CHAIN.ARBITRUM]: { + fetch: fetch, + runAtCurrTime: false, + start: 1689014691, + }, + [CHAIN.AVAX]: { + fetch: fetch, + runAtCurrTime: false, + start: 1696671295, + }, + [CHAIN.BASE]: { + fetch: fetch, + runAtCurrTime: false, + start: 1697229723, + }, + [CHAIN.BSC]: { + fetch: fetch, + runAtCurrTime: false, + start: 1696963675, + }, + [CHAIN.OPTIMISM]: { + fetch: fetch, + runAtCurrTime: false, + start: 1696888429, + }, + [CHAIN.POLYGON]: { + fetch: fetch, + runAtCurrTime: false, + start: 1696888519, + }, + [CHAIN.MANTA]: { + fetch: fetch, + runAtCurrTime: false, + start: 1695079629, + }, + [CHAIN.SCROLL]: { + fetch: fetch, + runAtCurrTime: false, + start: 1702694992, + } + } +}; + +export default adapter diff --git a/aggregators/arcane-dex/index.ts b/aggregators/arcane-dex/index.ts index abbcce6c8e..7f06334040 100644 --- a/aggregators/arcane-dex/index.ts +++ b/aggregators/arcane-dex/index.ts @@ -1,10 +1,10 @@ +import * as sdk from "@defillama/sdk"; import ADDRESSES from '../../helpers/coreAssets.json' import request from "graphql-request" import { FetchResultVolume, SimpleAdapter } from "../../adapters/types" import { CHAIN } from "../../helpers/chains" import { getBlock } from "../../helpers/getBlock" -import * as sdk from "@defillama/sdk" interface IResponse { today: { @@ -38,7 +38,7 @@ const fetchVolume = async (timestamp: number): Promise => { } } ` - const result: IResponse = await request("https://api.thegraph.com/subgraphs/name/0xandee/arcanedex", query) + const result: IResponse = await request(sdk.graph.modifyEndpoint('BocqFij8hqUaDGmR1FpSuAYJmtqafZrFmBtHknP7kVd'), query) const ethAddress = "ethereum:" + ADDRESSES.null; const dailyVolumeInEth = Number(result.today.totalVolumeInEth) - Number(result.yesterday.totalVolumeInEth) diff --git a/aggregators/avnu/index.ts b/aggregators/avnu/index.ts index 9577584512..540bc2a0a6 100644 --- a/aggregators/avnu/index.ts +++ b/aggregators/avnu/index.ts @@ -20,6 +20,8 @@ const fetch = async (timestamp: number): Promise => { totalVolume, timestamp: dayTimestamp, }; + + } const adapter: SimpleAdapter = { diff --git a/aggregators/bebop/index.ts b/aggregators/bebop/index.ts index 8267ae145c..f8d063d098 100644 --- a/aggregators/bebop/index.ts +++ b/aggregators/bebop/index.ts @@ -1,6 +1,8 @@ import { ethers } from "ethers"; -import { ChainBlocks, FetchOptions } from "../../adapters/types"; +import { Adapter, FetchOptions } from "../../adapters/types"; import { getTransactions } from "../../helpers/getTxReceipts"; +import JAM_ABI from "./jamAbi"; +import {queryDuneSql} from "../../helpers/dune" const abis = { "AggregateOrderExecuted": "event AggregateOrderExecuted(bytes32 order_hash)", @@ -35,11 +37,16 @@ const abis = { } const contract_interface = new ethers.Interface(Object.values(abis)); +const JamContract = new ethers.Contract('0xbebebeb035351f58602e0c1c8b59ecbff5d5f47b', JAM_ABI) +const jamAddress = { + era:'0x574d1fcF950eb48b11de5DF22A007703cbD2b129', + default: '0xbebebeb035351f58602e0c1c8b59ecbff5d5f47b' +} + -const fetch = async (timestamp: number, _: ChainBlocks, { createBalances, getLogs, chain, api }: FetchOptions) => { +const fetch = async ({ createBalances, getLogs, chain, api }: FetchOptions) => { const dailyVolume = createBalances() const cowswapData: any = {} - const logs = await getLogs({ target: '0xBeB09000fa59627dc02Bb55448AC1893EAa501A5', topics: ['0xc59522161f93d59c8c4520b0e7a3635fb7544133275be812a4ea970f4f14251b'] // AggregateOrderExecuted @@ -76,14 +83,53 @@ const fetch = async (timestamp: number, _: ChainBlocks, { createBalances, getLog api.log('no order', d.hash, d.input.slice(0, 10), d.to, chain, decoded.signature) } } - return { timestamp, dailyVolume } + + const jamLogs = await getLogs({ + target: jamAddress[chain] || jamAddress.default, + topics: ['0x7a70845dec8dc098eecb16e760b0c1569874487f0459ae689c738e281b28ed38'] // Settlement, + }); + + const jamData: any = await getTransactions(chain, jamLogs.map((log: any) => log.transactionHash), { cacheKey: 'bebop' }) + for (const d of jamData) { + const decoded = JamContract.interface.parseTransaction(d) + if (!decoded) { + api.log('jam no decoded', d.hash, d.input.slice(0, 10), d.to, chain) + continue; + } + const {buyAmounts = [], sellAmounts = [], buyTokens = [], sellTokens = []} = decoded?.args?.order + buyAmounts?.forEach((amount: any, i: number) => { + dailyVolume.add(buyTokens[i], amount) + }) + sellAmounts?.forEach((amount: any, i: number) => { + dailyVolume.add(sellTokens[i], amount) + }) + } + + return { dailyVolume } }; -const adapter: any = { +async function fetchDune(options: FetchOptions){ + const vol = await queryDuneSql(options, `SELECT SUM(amount_usd) AS vol FROM bebop.trades WHERE blockchain = 'CHAIN' AND TIME_RANGE`) + const dailyVolume = options.createBalances() + dailyVolume.addCGToken("tether", vol[0].vol) + return { dailyVolume } +} + +const adapter: Adapter = { + version: 2, + isExpensiveAdapter: true, adapter: { - arbitrum: { fetch, start: 1685491200, }, - ethereum: { fetch, start: 1685491200, }, - polygon: { fetch, start: 1685491200, }, + arbitrum: { fetch: fetchDune, start: 1685491200, }, + ethereum: { fetch: fetchDune, start: 1685491200, }, + polygon: { fetch: fetchDune, start: 1685491200, }, + bsc: { fetch: fetchDune, start: 1685491200, }, + blast: { fetch, start: 1685491200, }, + era: { fetch, start: 1685491200, }, + optimism: { fetch: fetchDune, start: 1685491200, }, + mode: { fetch, start: 1685491200, }, + base: { fetch: fetchDune, start: 1685491200, }, + scroll: { fetch: fetchDune, start: 1685491200, }, + taiko: { fetch, start: 1685491200, }, }, }; diff --git a/aggregators/bebop/jamAbi.ts b/aggregators/bebop/jamAbi.ts new file mode 100644 index 0000000000..133db5229c --- /dev/null +++ b/aggregators/bebop/jamAbi.ts @@ -0,0 +1,766 @@ +const ABI = [ + { + inputs: [ + { internalType: "address", name: "_permit2", type: "address" }, + { internalType: "address", name: "_daiAddress", type: "address" }, + ], + stateMutability: "nonpayable", + type: "constructor", + }, + { + anonymous: false, + inputs: [ + { + indexed: true, + internalType: "address", + name: "receiver", + type: "address", + }, + { + indexed: false, + internalType: "uint256", + name: "amount", + type: "uint256", + }, + ], + name: "NativeTransfer", + type: "event", + }, + { + anonymous: false, + inputs: [ + { + indexed: true, + internalType: "uint256", + name: "nonce", + type: "uint256", + }, + ], + name: "Settlement", + type: "event", + }, + { + inputs: [], + name: "DOMAIN_SEPARATOR", + outputs: [{ internalType: "bytes32", name: "", type: "bytes32" }], + stateMutability: "view", + type: "function", + }, + { + inputs: [], + name: "EIP712_DOMAIN_TYPEHASH", + outputs: [{ internalType: "bytes32", name: "", type: "bytes32" }], + stateMutability: "view", + type: "function", + }, + { + inputs: [], + name: "JAM_ORDER_TYPE_HASH", + outputs: [{ internalType: "bytes32", name: "", type: "bytes32" }], + stateMutability: "view", + type: "function", + }, + { + inputs: [], + name: "balanceManager", + outputs: [ + { + internalType: "contract IJamBalanceManager", + name: "", + type: "address", + }, + ], + stateMutability: "view", + type: "function", + }, + { + inputs: [{ internalType: "uint256", name: "nonce", type: "uint256" }], + name: "cancelLimitOrder", + outputs: [], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [ + { + components: [ + { + components: [ + { internalType: "bool", name: "result", type: "bool" }, + { internalType: "address", name: "to", type: "address" }, + { internalType: "uint256", name: "value", type: "uint256" }, + { internalType: "bytes", name: "data", type: "bytes" }, + ], + internalType: "struct JamInteraction.Data[]", + name: "beforeSettle", + type: "tuple[]", + }, + { + components: [ + { internalType: "bool", name: "result", type: "bool" }, + { internalType: "address", name: "to", type: "address" }, + { internalType: "uint256", name: "value", type: "uint256" }, + { internalType: "bytes", name: "data", type: "bytes" }, + ], + internalType: "struct JamInteraction.Data[]", + name: "afterSettle", + type: "tuple[]", + }, + ], + internalType: "struct JamHooks.Def", + name: "hooks", + type: "tuple", + }, + ], + name: "hashHooks", + outputs: [{ internalType: "bytes32", name: "", type: "bytes32" }], + stateMutability: "pure", + type: "function", + }, + { + inputs: [ + { + components: [ + { internalType: "address", name: "taker", type: "address" }, + { internalType: "address", name: "receiver", type: "address" }, + { internalType: "uint256", name: "expiry", type: "uint256" }, + { internalType: "uint256", name: "nonce", type: "uint256" }, + { internalType: "address", name: "executor", type: "address" }, + { internalType: "uint16", name: "minFillPercent", type: "uint16" }, + { internalType: "bytes32", name: "hooksHash", type: "bytes32" }, + { internalType: "address[]", name: "sellTokens", type: "address[]" }, + { internalType: "address[]", name: "buyTokens", type: "address[]" }, + { internalType: "uint256[]", name: "sellAmounts", type: "uint256[]" }, + { internalType: "uint256[]", name: "buyAmounts", type: "uint256[]" }, + { internalType: "uint256[]", name: "sellNFTIds", type: "uint256[]" }, + { internalType: "uint256[]", name: "buyNFTIds", type: "uint256[]" }, + { internalType: "bytes", name: "sellTokenTransfers", type: "bytes" }, + { internalType: "bytes", name: "buyTokenTransfers", type: "bytes" }, + ], + internalType: "struct JamOrder.Data", + name: "order", + type: "tuple", + }, + { internalType: "bytes32", name: "hooksHash", type: "bytes32" }, + ], + name: "hashOrder", + outputs: [{ internalType: "bytes32", name: "", type: "bytes32" }], + stateMutability: "view", + type: "function", + }, + { + inputs: [ + { internalType: "address", name: "taker", type: "address" }, + { internalType: "uint256", name: "nonce", type: "uint256" }, + ], + name: "isLimitOrderNonceValid", + outputs: [{ internalType: "bool", name: "", type: "bool" }], + stateMutability: "view", + type: "function", + }, + { + inputs: [ + { internalType: "address", name: "", type: "address" }, + { internalType: "address", name: "", type: "address" }, + { internalType: "uint256[]", name: "", type: "uint256[]" }, + { internalType: "uint256[]", name: "", type: "uint256[]" }, + { internalType: "bytes", name: "", type: "bytes" }, + ], + name: "onERC1155BatchReceived", + outputs: [{ internalType: "bytes4", name: "", type: "bytes4" }], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [ + { internalType: "address", name: "", type: "address" }, + { internalType: "address", name: "", type: "address" }, + { internalType: "uint256", name: "", type: "uint256" }, + { internalType: "uint256", name: "", type: "uint256" }, + { internalType: "bytes", name: "", type: "bytes" }, + ], + name: "onERC1155Received", + outputs: [{ internalType: "bytes4", name: "", type: "bytes4" }], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [ + { internalType: "address", name: "", type: "address" }, + { internalType: "address", name: "", type: "address" }, + { internalType: "uint256", name: "", type: "uint256" }, + { internalType: "bytes", name: "", type: "bytes" }, + ], + name: "onERC721Received", + outputs: [{ internalType: "bytes4", name: "", type: "bytes4" }], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [ + { + components: [ + { internalType: "address", name: "taker", type: "address" }, + { internalType: "address", name: "receiver", type: "address" }, + { internalType: "uint256", name: "expiry", type: "uint256" }, + { internalType: "uint256", name: "nonce", type: "uint256" }, + { internalType: "address", name: "executor", type: "address" }, + { internalType: "uint16", name: "minFillPercent", type: "uint16" }, + { internalType: "bytes32", name: "hooksHash", type: "bytes32" }, + { internalType: "address[]", name: "sellTokens", type: "address[]" }, + { internalType: "address[]", name: "buyTokens", type: "address[]" }, + { internalType: "uint256[]", name: "sellAmounts", type: "uint256[]" }, + { internalType: "uint256[]", name: "buyAmounts", type: "uint256[]" }, + { internalType: "uint256[]", name: "sellNFTIds", type: "uint256[]" }, + { internalType: "uint256[]", name: "buyNFTIds", type: "uint256[]" }, + { internalType: "bytes", name: "sellTokenTransfers", type: "bytes" }, + { internalType: "bytes", name: "buyTokenTransfers", type: "bytes" }, + ], + internalType: "struct JamOrder.Data", + name: "order", + type: "tuple", + }, + { + components: [ + { + internalType: "enum Signature.Type", + name: "signatureType", + type: "uint8", + }, + { internalType: "bytes", name: "signatureBytes", type: "bytes" }, + ], + internalType: "struct Signature.TypedSignature", + name: "signature", + type: "tuple", + }, + { + components: [ + { internalType: "bool", name: "result", type: "bool" }, + { internalType: "address", name: "to", type: "address" }, + { internalType: "uint256", name: "value", type: "uint256" }, + { internalType: "bytes", name: "data", type: "bytes" }, + ], + internalType: "struct JamInteraction.Data[]", + name: "interactions", + type: "tuple[]", + }, + { + components: [ + { + components: [ + { internalType: "bool", name: "result", type: "bool" }, + { internalType: "address", name: "to", type: "address" }, + { internalType: "uint256", name: "value", type: "uint256" }, + { internalType: "bytes", name: "data", type: "bytes" }, + ], + internalType: "struct JamInteraction.Data[]", + name: "beforeSettle", + type: "tuple[]", + }, + { + components: [ + { internalType: "bool", name: "result", type: "bool" }, + { internalType: "address", name: "to", type: "address" }, + { internalType: "uint256", name: "value", type: "uint256" }, + { internalType: "bytes", name: "data", type: "bytes" }, + ], + internalType: "struct JamInteraction.Data[]", + name: "afterSettle", + type: "tuple[]", + }, + ], + internalType: "struct JamHooks.Def", + name: "hooks", + type: "tuple", + }, + { + components: [ + { + internalType: "address", + name: "balanceRecipient", + type: "address", + }, + { internalType: "uint16", name: "curFillPercent", type: "uint16" }, + ], + internalType: "struct ExecInfo.SolverData", + name: "solverData", + type: "tuple", + }, + ], + name: "settle", + outputs: [], + stateMutability: "payable", + type: "function", + }, + { + inputs: [ + { + components: [ + { internalType: "address", name: "taker", type: "address" }, + { internalType: "address", name: "receiver", type: "address" }, + { internalType: "uint256", name: "expiry", type: "uint256" }, + { internalType: "uint256", name: "nonce", type: "uint256" }, + { internalType: "address", name: "executor", type: "address" }, + { internalType: "uint16", name: "minFillPercent", type: "uint16" }, + { internalType: "bytes32", name: "hooksHash", type: "bytes32" }, + { internalType: "address[]", name: "sellTokens", type: "address[]" }, + { internalType: "address[]", name: "buyTokens", type: "address[]" }, + { internalType: "uint256[]", name: "sellAmounts", type: "uint256[]" }, + { internalType: "uint256[]", name: "buyAmounts", type: "uint256[]" }, + { internalType: "uint256[]", name: "sellNFTIds", type: "uint256[]" }, + { internalType: "uint256[]", name: "buyNFTIds", type: "uint256[]" }, + { internalType: "bytes", name: "sellTokenTransfers", type: "bytes" }, + { internalType: "bytes", name: "buyTokenTransfers", type: "bytes" }, + ], + internalType: "struct JamOrder.Data[]", + name: "orders", + type: "tuple[]", + }, + { + components: [ + { + internalType: "enum Signature.Type", + name: "signatureType", + type: "uint8", + }, + { internalType: "bytes", name: "signatureBytes", type: "bytes" }, + ], + internalType: "struct Signature.TypedSignature[]", + name: "signatures", + type: "tuple[]", + }, + { + components: [ + { + internalType: "bytes[]", + name: "permitSignatures", + type: "bytes[]", + }, + { + internalType: "bytes", + name: "signatureBytesPermit2", + type: "bytes", + }, + { internalType: "uint48[]", name: "noncesPermit2", type: "uint48[]" }, + { internalType: "uint48", name: "deadline", type: "uint48" }, + ], + internalType: "struct Signature.TakerPermitsInfo[]", + name: "takersPermitsInfo", + type: "tuple[]", + }, + { + components: [ + { internalType: "bool", name: "result", type: "bool" }, + { internalType: "address", name: "to", type: "address" }, + { internalType: "uint256", name: "value", type: "uint256" }, + { internalType: "bytes", name: "data", type: "bytes" }, + ], + internalType: "struct JamInteraction.Data[]", + name: "interactions", + type: "tuple[]", + }, + { + components: [ + { + components: [ + { internalType: "bool", name: "result", type: "bool" }, + { internalType: "address", name: "to", type: "address" }, + { internalType: "uint256", name: "value", type: "uint256" }, + { internalType: "bytes", name: "data", type: "bytes" }, + ], + internalType: "struct JamInteraction.Data[]", + name: "beforeSettle", + type: "tuple[]", + }, + { + components: [ + { internalType: "bool", name: "result", type: "bool" }, + { internalType: "address", name: "to", type: "address" }, + { internalType: "uint256", name: "value", type: "uint256" }, + { internalType: "bytes", name: "data", type: "bytes" }, + ], + internalType: "struct JamInteraction.Data[]", + name: "afterSettle", + type: "tuple[]", + }, + ], + internalType: "struct JamHooks.Def[]", + name: "hooks", + type: "tuple[]", + }, + { + components: [ + { + internalType: "address", + name: "balanceRecipient", + type: "address", + }, + { + internalType: "uint16[]", + name: "curFillPercents", + type: "uint16[]", + }, + { + internalType: "bool[]", + name: "takersPermitsUsage", + type: "bool[]", + }, + { internalType: "bool", name: "transferExactAmounts", type: "bool" }, + ], + internalType: "struct ExecInfo.BatchSolverData", + name: "solverData", + type: "tuple", + }, + ], + name: "settleBatch", + outputs: [], + stateMutability: "payable", + type: "function", + }, + { + inputs: [ + { + components: [ + { internalType: "address", name: "taker", type: "address" }, + { internalType: "address", name: "receiver", type: "address" }, + { internalType: "uint256", name: "expiry", type: "uint256" }, + { internalType: "uint256", name: "nonce", type: "uint256" }, + { internalType: "address", name: "executor", type: "address" }, + { internalType: "uint16", name: "minFillPercent", type: "uint16" }, + { internalType: "bytes32", name: "hooksHash", type: "bytes32" }, + { internalType: "address[]", name: "sellTokens", type: "address[]" }, + { internalType: "address[]", name: "buyTokens", type: "address[]" }, + { internalType: "uint256[]", name: "sellAmounts", type: "uint256[]" }, + { internalType: "uint256[]", name: "buyAmounts", type: "uint256[]" }, + { internalType: "uint256[]", name: "sellNFTIds", type: "uint256[]" }, + { internalType: "uint256[]", name: "buyNFTIds", type: "uint256[]" }, + { internalType: "bytes", name: "sellTokenTransfers", type: "bytes" }, + { internalType: "bytes", name: "buyTokenTransfers", type: "bytes" }, + ], + internalType: "struct JamOrder.Data", + name: "order", + type: "tuple", + }, + { + components: [ + { + internalType: "enum Signature.Type", + name: "signatureType", + type: "uint8", + }, + { internalType: "bytes", name: "signatureBytes", type: "bytes" }, + ], + internalType: "struct Signature.TypedSignature", + name: "signature", + type: "tuple", + }, + { + components: [ + { + components: [ + { internalType: "bool", name: "result", type: "bool" }, + { internalType: "address", name: "to", type: "address" }, + { internalType: "uint256", name: "value", type: "uint256" }, + { internalType: "bytes", name: "data", type: "bytes" }, + ], + internalType: "struct JamInteraction.Data[]", + name: "beforeSettle", + type: "tuple[]", + }, + { + components: [ + { internalType: "bool", name: "result", type: "bool" }, + { internalType: "address", name: "to", type: "address" }, + { internalType: "uint256", name: "value", type: "uint256" }, + { internalType: "bytes", name: "data", type: "bytes" }, + ], + internalType: "struct JamInteraction.Data[]", + name: "afterSettle", + type: "tuple[]", + }, + ], + internalType: "struct JamHooks.Def", + name: "hooks", + type: "tuple", + }, + { + components: [ + { + internalType: "uint256[]", + name: "increasedBuyAmounts", + type: "uint256[]", + }, + { internalType: "uint16", name: "curFillPercent", type: "uint16" }, + ], + internalType: "struct ExecInfo.MakerData", + name: "makerData", + type: "tuple", + }, + ], + name: "settleInternal", + outputs: [], + stateMutability: "payable", + type: "function", + }, + { + inputs: [ + { + components: [ + { internalType: "address", name: "taker", type: "address" }, + { internalType: "address", name: "receiver", type: "address" }, + { internalType: "uint256", name: "expiry", type: "uint256" }, + { internalType: "uint256", name: "nonce", type: "uint256" }, + { internalType: "address", name: "executor", type: "address" }, + { internalType: "uint16", name: "minFillPercent", type: "uint16" }, + { internalType: "bytes32", name: "hooksHash", type: "bytes32" }, + { internalType: "address[]", name: "sellTokens", type: "address[]" }, + { internalType: "address[]", name: "buyTokens", type: "address[]" }, + { internalType: "uint256[]", name: "sellAmounts", type: "uint256[]" }, + { internalType: "uint256[]", name: "buyAmounts", type: "uint256[]" }, + { internalType: "uint256[]", name: "sellNFTIds", type: "uint256[]" }, + { internalType: "uint256[]", name: "buyNFTIds", type: "uint256[]" }, + { internalType: "bytes", name: "sellTokenTransfers", type: "bytes" }, + { internalType: "bytes", name: "buyTokenTransfers", type: "bytes" }, + ], + internalType: "struct JamOrder.Data", + name: "order", + type: "tuple", + }, + { + components: [ + { + internalType: "enum Signature.Type", + name: "signatureType", + type: "uint8", + }, + { internalType: "bytes", name: "signatureBytes", type: "bytes" }, + ], + internalType: "struct Signature.TypedSignature", + name: "signature", + type: "tuple", + }, + { + components: [ + { + internalType: "bytes[]", + name: "permitSignatures", + type: "bytes[]", + }, + { + internalType: "bytes", + name: "signatureBytesPermit2", + type: "bytes", + }, + { internalType: "uint48[]", name: "noncesPermit2", type: "uint48[]" }, + { internalType: "uint48", name: "deadline", type: "uint48" }, + ], + internalType: "struct Signature.TakerPermitsInfo", + name: "takerPermitsInfo", + type: "tuple", + }, + { + components: [ + { + components: [ + { internalType: "bool", name: "result", type: "bool" }, + { internalType: "address", name: "to", type: "address" }, + { internalType: "uint256", name: "value", type: "uint256" }, + { internalType: "bytes", name: "data", type: "bytes" }, + ], + internalType: "struct JamInteraction.Data[]", + name: "beforeSettle", + type: "tuple[]", + }, + { + components: [ + { internalType: "bool", name: "result", type: "bool" }, + { internalType: "address", name: "to", type: "address" }, + { internalType: "uint256", name: "value", type: "uint256" }, + { internalType: "bytes", name: "data", type: "bytes" }, + ], + internalType: "struct JamInteraction.Data[]", + name: "afterSettle", + type: "tuple[]", + }, + ], + internalType: "struct JamHooks.Def", + name: "hooks", + type: "tuple", + }, + { + components: [ + { + internalType: "uint256[]", + name: "increasedBuyAmounts", + type: "uint256[]", + }, + { internalType: "uint16", name: "curFillPercent", type: "uint16" }, + ], + internalType: "struct ExecInfo.MakerData", + name: "makerData", + type: "tuple", + }, + ], + name: "settleInternalWithPermitsSignatures", + outputs: [], + stateMutability: "payable", + type: "function", + }, + { + inputs: [ + { + components: [ + { internalType: "address", name: "taker", type: "address" }, + { internalType: "address", name: "receiver", type: "address" }, + { internalType: "uint256", name: "expiry", type: "uint256" }, + { internalType: "uint256", name: "nonce", type: "uint256" }, + { internalType: "address", name: "executor", type: "address" }, + { internalType: "uint16", name: "minFillPercent", type: "uint16" }, + { internalType: "bytes32", name: "hooksHash", type: "bytes32" }, + { internalType: "address[]", name: "sellTokens", type: "address[]" }, + { internalType: "address[]", name: "buyTokens", type: "address[]" }, + { internalType: "uint256[]", name: "sellAmounts", type: "uint256[]" }, + { internalType: "uint256[]", name: "buyAmounts", type: "uint256[]" }, + { internalType: "uint256[]", name: "sellNFTIds", type: "uint256[]" }, + { internalType: "uint256[]", name: "buyNFTIds", type: "uint256[]" }, + { internalType: "bytes", name: "sellTokenTransfers", type: "bytes" }, + { internalType: "bytes", name: "buyTokenTransfers", type: "bytes" }, + ], + internalType: "struct JamOrder.Data", + name: "order", + type: "tuple", + }, + { + components: [ + { + internalType: "enum Signature.Type", + name: "signatureType", + type: "uint8", + }, + { internalType: "bytes", name: "signatureBytes", type: "bytes" }, + ], + internalType: "struct Signature.TypedSignature", + name: "signature", + type: "tuple", + }, + { + components: [ + { + internalType: "bytes[]", + name: "permitSignatures", + type: "bytes[]", + }, + { + internalType: "bytes", + name: "signatureBytesPermit2", + type: "bytes", + }, + { internalType: "uint48[]", name: "noncesPermit2", type: "uint48[]" }, + { internalType: "uint48", name: "deadline", type: "uint48" }, + ], + internalType: "struct Signature.TakerPermitsInfo", + name: "takerPermitsInfo", + type: "tuple", + }, + { + components: [ + { internalType: "bool", name: "result", type: "bool" }, + { internalType: "address", name: "to", type: "address" }, + { internalType: "uint256", name: "value", type: "uint256" }, + { internalType: "bytes", name: "data", type: "bytes" }, + ], + internalType: "struct JamInteraction.Data[]", + name: "interactions", + type: "tuple[]", + }, + { + components: [ + { + components: [ + { internalType: "bool", name: "result", type: "bool" }, + { internalType: "address", name: "to", type: "address" }, + { internalType: "uint256", name: "value", type: "uint256" }, + { internalType: "bytes", name: "data", type: "bytes" }, + ], + internalType: "struct JamInteraction.Data[]", + name: "beforeSettle", + type: "tuple[]", + }, + { + components: [ + { internalType: "bool", name: "result", type: "bool" }, + { internalType: "address", name: "to", type: "address" }, + { internalType: "uint256", name: "value", type: "uint256" }, + { internalType: "bytes", name: "data", type: "bytes" }, + ], + internalType: "struct JamInteraction.Data[]", + name: "afterSettle", + type: "tuple[]", + }, + ], + internalType: "struct JamHooks.Def", + name: "hooks", + type: "tuple", + }, + { + components: [ + { + internalType: "address", + name: "balanceRecipient", + type: "address", + }, + { internalType: "uint16", name: "curFillPercent", type: "uint16" }, + ], + internalType: "struct ExecInfo.SolverData", + name: "solverData", + type: "tuple", + }, + ], + name: "settleWithPermitsSignatures", + outputs: [], + stateMutability: "payable", + type: "function", + }, + { + inputs: [{ internalType: "bytes4", name: "interfaceId", type: "bytes4" }], + name: "supportsInterface", + outputs: [{ internalType: "bool", name: "", type: "bool" }], + stateMutability: "view", + type: "function", + }, + { + inputs: [ + { internalType: "address", name: "receiver", type: "address" }, + { internalType: "uint256", name: "amount", type: "uint256" }, + ], + name: "transferNativeFromContract", + outputs: [], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [ + { internalType: "address", name: "validationAddress", type: "address" }, + { internalType: "bytes32", name: "hash", type: "bytes32" }, + { + components: [ + { + internalType: "enum Signature.Type", + name: "signatureType", + type: "uint8", + }, + { internalType: "bytes", name: "signatureBytes", type: "bytes" }, + ], + internalType: "struct Signature.TypedSignature", + name: "signature", + type: "tuple", + }, + ], + name: "validateSignature", + outputs: [], + stateMutability: "view", + type: "function", + }, + { stateMutability: "payable", type: "receive" }, +]; +export default ABI; diff --git a/aggregators/bountive/index.ts b/aggregators/bountive/index.ts new file mode 100644 index 0000000000..6ae843e2c6 --- /dev/null +++ b/aggregators/bountive/index.ts @@ -0,0 +1,36 @@ +import fetchURL from "../../utils/fetchURL"; +import { FetchResultV2, SimpleAdapter } from "../../adapters/types"; +import { CHAIN } from "../../helpers/chains"; + +const URL = 'https://app.bountive.fi'; +const endpoint = '/api/metrics/volumes/'; +const startTimestamp = 1709356735;// 02.03.2024 + +interface IAPIResponse { + date: number; + dailyVolume: string; + totalVolume: string; +} + +const fetch = async ({ endTimestamp, startTimestamp }): Promise => { + const { dailyVolume, totalVolume }: IAPIResponse = await fetchURL( + `${URL}${endpoint}${startTimestamp * 1000}/${endTimestamp * 1000}`, + ); + + return { + dailyVolume, + totalVolume, + }; +}; + +const adapter: SimpleAdapter = { + version: 2, + adapter: { + [CHAIN.STARKNET]: { + fetch: fetch, + start: startTimestamp, + }, + }, +}; + +export default adapter; \ No newline at end of file diff --git a/aggregators/cetus-aggregator/index.ts b/aggregators/cetus-aggregator/index.ts new file mode 100644 index 0000000000..7132e7c6b0 --- /dev/null +++ b/aggregators/cetus-aggregator/index.ts @@ -0,0 +1,23 @@ +import { CHAIN } from "../../helpers/chains"; +import { httpGet } from "../../utils/fetchURL"; +import { FetchOptions } from "../../adapters/types"; + +const fetchVolume = async (options: FetchOptions) => { + const url = `https://api-sui.cetus.zone/v2/sui/aggregator_vol?startTimestamp=${options.startOfDay}&endTimestamp=${options.startOfDay}`; + const res = await httpGet(url); + return { + dailyVolume: res.data.list[0].totalUSD, + } +}; + +const adapter_agge: any = { + version: 2, + adapter: { + [CHAIN.SUI]: { + fetch: fetchVolume, + start: 1721260800, + }, + }, +}; + +export default adapter_agge; diff --git a/aggregators/chainspot/index.ts b/aggregators/chainspot/index.ts new file mode 100644 index 0000000000..eff1ca543f --- /dev/null +++ b/aggregators/chainspot/index.ts @@ -0,0 +1,101 @@ +import { httpGet } from "../../utils/fetchURL"; +import { getUniqStartOfTodayTimestamp } from "../../helpers/getUniSubgraphVolume"; +import { CHAIN } from "../../helpers/chains"; +import { FetchOptions } from "../../adapters/types"; + +const chains = [ + CHAIN.ETHEREUM, + CHAIN.POLYGON, + CHAIN.BSC, + CHAIN.AVAX, + CHAIN.OPTIMISM, + CHAIN.FANTOM, + CHAIN.ARBITRUM, + CHAIN.AURORA, + CHAIN.CELO, + CHAIN.BOBA, + CHAIN.XDAI, + CHAIN.TELOS, + CHAIN.BASE, + CHAIN.LINEA, + CHAIN.MANTLE, + CHAIN.MOONBEAM, + CHAIN.CRONOS, + CHAIN.BLAST, + CHAIN.EVMOS, + CHAIN.FUSE, + CHAIN.HARMONY, + CHAIN.KAVA, + CHAIN.MOONRIVER, + CHAIN.OKEXCHAIN, + CHAIN.SCROLL, + CHAIN.TRON, + CHAIN.TON, + CHAIN.WAN, + CHAIN.ZKLINK, + CHAIN.ZKSYNC, +]; + +const chainToId: Record = { + [CHAIN.ETHEREUM]: 1, + [CHAIN.POLYGON]: 137, + [CHAIN.BSC]: 56, + [CHAIN.AVAX]: 43114, + [CHAIN.OPTIMISM]: 10, + [CHAIN.FANTOM]: 250, + [CHAIN.ARBITRUM]: 42161, + [CHAIN.AURORA]: 1313161554, + [CHAIN.CELO]: 42220, + [CHAIN.BOBA]: 288, + [CHAIN.XDAI]: 100, + [CHAIN.TELOS]: 40, + [CHAIN.BASE]: 8453, + [CHAIN.LINEA]: 59144, + [CHAIN.MANTLE]: 5000, + [CHAIN.MOONBEAM]: 1284, + [CHAIN.CRONOS]: 25, + [CHAIN.BLAST]: 81457, + [CHAIN.EVMOS]: 9001, + [CHAIN.FUSE]: 122, + [CHAIN.HARMONY]: 1666600000, + [CHAIN.KAVA]: 2222, + [CHAIN.MOONRIVER]: 1285, + [CHAIN.OKEXCHAIN]: 66, + [CHAIN.SCROLL]: 534352, + [CHAIN.TRON]: 728126428, + [CHAIN.TON]: -239, + [CHAIN.WAN]: 888, + [CHAIN.ZKLINK]: 810180, + [CHAIN.ZKSYNC]: 324, +}; + +const fetch = async (_at: number, _t: any, options: FetchOptions) => { + const unixTimestamp = getUniqStartOfTodayTimestamp( + new Date(options.startOfDay * 1000) + ); + const url = `https://app.chainspot.io/api/2.0/statistic/daily-volume?chainId=${chainToId[options.chain]}×tamp=${unixTimestamp * 1e3}`; + const volume = ( + await httpGet(url) + )?.volume; + + return { + dailyVolume: volume || 0, + timestamp: unixTimestamp, + }; +}; + +const adapter: any = { + adapter: { + ...chains.reduce((acc, chain) => { + return { + ...acc, + [chain]: { + fetch: fetch, + start: 1704067200, + }, + }; + }, {}), + }, +}; + +export default adapter; diff --git a/aggregators/cowswap/index.ts b/aggregators/cowswap/index.ts index c858d1fdd9..78d623fcf1 100644 --- a/aggregators/cowswap/index.ts +++ b/aggregators/cowswap/index.ts @@ -18,6 +18,7 @@ const adapter: any = { adapter: { ethereum: { fetch, start: 1685491200, }, xdai: { fetch, start: 1685491200, }, + arbitrum: { fetch, start: 1714142553, }, }, }; diff --git a/aggregators/dexible/index.ts b/aggregators/dexible/index.ts index b291d7ea74..2b5d2528c8 100644 --- a/aggregators/dexible/index.ts +++ b/aggregators/dexible/index.ts @@ -1,6 +1,7 @@ -import { BreakdownAdapter, Fetch, SimpleAdapter } from "../../adapters/types"; +import { BreakdownAdapter, DISABLED_ADAPTER_KEY, Fetch, SimpleAdapter } from "../../adapters/types"; import { CHAIN } from "../../helpers/chains"; import { httpGet } from "../../utils/fetchURL"; +import disabledAdapter from "../../helpers/disabledAdapter"; const chains = [ CHAIN.ETHEREUM, @@ -76,6 +77,7 @@ const getFetch = (chain: string): Fetch => async (timestamp: number) => { const adapter: BreakdownAdapter = { breakdown: { "Dexible_v2": { + [DISABLED_ADAPTER_KEY]: disabledAdapter, // site has been sunset and discord is dead ...chains.reduce((acc, chain) => { return { ...acc, diff --git a/aggregators/dodo-agg/index.ts b/aggregators/dodo-agg/index.ts index 45796de7bb..88c2e8d7e0 100644 --- a/aggregators/dodo-agg/index.ts +++ b/aggregators/dodo-agg/index.ts @@ -1,6 +1,7 @@ +import { ChainBlocks, FetchOptions, SimpleAdapter } from "../../adapters/types"; // https://api.dodoex.io/dodo-contract/list -const config = { +const config: any = { ethereum: { DODOFeeRouteProxys: ['0x21b9F852534Fb9DdC3A0A7B24f067B50d8AC9a99', '0x50f9bDe1c76bba997a5d6e7FEFff695ec8536194']}, optimism: { DODOFeeRouteProxys: ['0x716fcc67dcA500A91B4a28c9255262c398D8f971', '0xc7d7CC1e9f5E823887980c9C51F9c418ee3A3e28']}, bsc: { DODOFeeRouteProxys: ['0xa8b034301Bb5DD3610db585Def3e7C0d52f2319F', '0x0656fD85364d03b103CEEda192FB2D3906A6ac15']}, @@ -16,26 +17,31 @@ const config = { scroll: { DODOFeeRouteProxys: ['0xf0512872fEc0173d1d99c2dd8CDCb770054b675b', '0x4e998615aD430C1cA46A69d813edE6EB3EC55eDb']}, } -import { ChainBlocks, FetchOptions } from "../../adapters/types"; - const abis = { "OrderHistory": "event OrderHistory (address fromToken, address toToken, address sender, uint256 fromAmount, uint256 returnAmount)", } -const fetch = async (timestamp: number, _: ChainBlocks, { createBalances, getLogs, chain, api }: FetchOptions) => { +const fetch = async (timestamp: number, _: ChainBlocks, { createBalances, getLogs, chain }: FetchOptions) => { const dailyVolume = createBalances() - - const logs = await getLogs({ targets: config[chain].DODOFeeRouteProxys, eventAbi: abis.OrderHistory, }) - logs.forEach((log: any) => { - dailyVolume.add(log.toToken, log.returnAmount) - }) - return { timestamp, dailyVolume } + try { + const logs = await getLogs({ targets: config[chain].DODOFeeRouteProxys, eventAbi: abis.OrderHistory, }) + logs.forEach((log: any) => { + dailyVolume.add(log.toToken, log.returnAmount) + }) + return { timestamp, dailyVolume } + } catch (e) { + return { timestamp, dailyVolume } + } }; -const adapter: any = { +const adapter_agg = { adapter: {}, }; -Object.keys(config).forEach((chain) => adapter.adapter[chain] = { fetch, start: 1690848000, }); +Object.keys(config).forEach((chain) => adapter_agg.adapter[chain] = { fetch, start: 1690848000, }); + +const adapter: SimpleAdapter = { + adapter: adapter_agg.adapter, +} -export default adapter; +export default adapter diff --git a/aggregators/eisen/index.ts b/aggregators/eisen/index.ts new file mode 100644 index 0000000000..924a800768 --- /dev/null +++ b/aggregators/eisen/index.ts @@ -0,0 +1,50 @@ +import { FetchOptions, SimpleAdapter } from "../../adapters/types"; +import { CHAIN } from "../../helpers/chains"; + +const event_swap = + "event EisenSwapCompleted(address indexed sender, address indexed fromAssetId, address indexed toAssetId, address receiver, uint256 fromAmount, uint256 toAmount, uint256 expectedToAmount, uint256 fee)"; + +type TPool = { + [c: string]: string[]; +}; + +type TBlock = { + [c: string]: number; +}; + +const FEE_COLLECTORS: TPool = { + [CHAIN.MODE]: ["0x37Cb37b752DBDcd08A872e7dfec256A216C7144C"], + [CHAIN.SCROLL]: ["0xA06568773A247657E7b89BBA465014CF85702093"], + [CHAIN.MANTLE]: ["0x31d6F212142D3B222EF11c9eBB6AF3569b8442EE"], + [CHAIN.BLAST]: ["0xd57Ed7F46D64Ec7b6f04E4A8409D88C55Ef8AA3b"], + [CHAIN.BITLAYER]: ["0x5722c0B501e7B9880F9bB13A14217851e45C454f"], + [CHAIN.LINEA]: ["0x206168f099013b9eAb979d3520cA00aAD453De55"], + [CHAIN.CRONOS]: ["0x0C15c845C4A970b284c0dd61Bcf01c4DC1117d0F"], +}; + +const START_BLOCKS = { + [CHAIN.MODE]: 1704067200, + [CHAIN.SCROLL]: 1704067200, + [CHAIN.MANTLE]: 1704067200, + [CHAIN.BLAST]: 1704067200, + [CHAIN.BITLAYER]: 1704067200, + [CHAIN.LINEA]: 1704067200, + [CHAIN.CRONOS]: 1704067200, +}; + +async function fetch({ getLogs, createBalances, chain }: FetchOptions) { + const feeCollectors = FEE_COLLECTORS[chain]; + const dailyVolume = createBalances(); + const logs = await getLogs({ targets: feeCollectors, eventAbi: event_swap }); + + logs.forEach((i) => dailyVolume.add(i.toAssetId, i.toAmount)); + + return { dailyVolume }; +} + +const adapter: SimpleAdapter = { adapter: {}, version: 2 }; +Object.keys(FEE_COLLECTORS).forEach( + (chain) => (adapter.adapter[chain] = { fetch, start: START_BLOCKS[chain] }) +); + +export default adapter; diff --git a/aggregators/etaswap/index.ts b/aggregators/etaswap/index.ts new file mode 100644 index 0000000000..a4aea7c301 --- /dev/null +++ b/aggregators/etaswap/index.ts @@ -0,0 +1,25 @@ +import BigNumber from "bignumber.js"; +import { CHAIN } from "../../helpers/chains"; +import { httpGet } from "../../utils/fetchURL"; + +const fetchLogs = async (timestamp: number) => { + const res = await httpGet(`https://api.etaswap.com/v1/statistics/volume/total?timestamp=${timestamp}`); + return { + dailyVolume: new BigNumber(res.volume_USD_24h).div(100).toFixed(2), + totalVolume: new BigNumber(res.volume_USD_total).div(100).toFixed(2), + dailyFees: new BigNumber(res.fee_USD_24h).div(100).toFixed(2), + totalFees: new BigNumber(res.fee_USD_total).div(100).toFixed(2), + timestamp: timestamp, + }; +}; + +const adapter: any = { + adapter: { + [CHAIN.HEDERA]: { + fetch: fetchLogs, + start: 1709395559, + }, + }, +}; + +export default adapter; diff --git a/aggregators/fibrous-finance/index.ts b/aggregators/fibrous-finance/index.ts new file mode 100644 index 0000000000..8e036363b6 --- /dev/null +++ b/aggregators/fibrous-finance/index.ts @@ -0,0 +1,38 @@ +import fetchURL from "../../utils/fetchURL"; +import { FetchResult, SimpleAdapter } from "../../adapters/types"; +import { CHAIN } from "../../helpers/chains"; +import { getUniqStartOfTodayTimestamp } from "../../helpers/getUniSubgraphVolume"; + +const URL = "https://stats.fibrous.finance/volume"; + +interface IAPIResponse { + status: number; + data: { + dailyVolume: string; + totalVolume: string; + }; + message: string; +} +const fetch = async (timestamp: number): Promise => { + const dayTimestamp = getUniqStartOfTodayTimestamp(new Date(timestamp * 1000)); + const response: IAPIResponse = await fetchURL(`${URL}`); + const dailyVolume = response.data.dailyVolume; + const totalVolume = response.data.totalVolume; + return { + dailyVolume, + totalVolume, + timestamp: dayTimestamp, + }; +}; + +const adapter: SimpleAdapter = { + adapter: { + [CHAIN.STARKNET]: { + fetch, + start: 1683408691, + runAtCurrTime: true + }, + }, +}; + +export default adapter; diff --git a/aggregators/flowx-aggregator/index.ts b/aggregators/flowx-aggregator/index.ts new file mode 100644 index 0000000000..b89ff05c89 --- /dev/null +++ b/aggregators/flowx-aggregator/index.ts @@ -0,0 +1,28 @@ +import { CHAIN } from "../../helpers/chains"; +import { httpGet } from "../../utils/fetchURL"; +import { FetchOptions } from "../../adapters/types"; +import { version } from "os"; + +const fetchVolume = async (options: FetchOptions) => { + const url = `https://flowx-finance-mono.vercel.app/api/defillama/aggregator-vol?startTimestamp=${options.startOfDay}&endTimestamp=${options.startOfDay}`; + const res = await httpGet(url); + const record = res[0]; + return { + dailyVolume: record.totalUSD, + } + + + +}; + +const adapter: any = { + version: 2, + adapter: { + [CHAIN.SUI]: { + fetch: fetchVolume, + start: 1717200000, + }, + }, +}; + +export default adapter; diff --git a/aggregators/hallswap/index.ts b/aggregators/hallswap/index.ts new file mode 100644 index 0000000000..92642ead0c --- /dev/null +++ b/aggregators/hallswap/index.ts @@ -0,0 +1,57 @@ +import fetchURL from "../../utils/fetchURL"; +import { FetchV2, SimpleAdapter } from "../../adapters/types"; + +// Main API url to hit +const API_URL = "https://api.seer.coinhall.org/api/hallswap/metrics"; +// The first launch of Hallswap (1st December 2021) +const START_TIMESTAMP = 1638316800; +// Map of the chain names used by defillama to the chain names used by hallswap +const CHAINS = { + archway: "archway", + chihuahua: "chihuahua", + dymension: "dymension", + injective: "injective", + juno: "juno", + kujira: "kujira", + migaloo: "migaloo", + neutron: "neutron", + orai: "oraichain", + osmosis: "osmosis", + sei: "sei", + solana: "solana", + // terra: "terraclassic", + terra2: "terra", +} as const; +// Number of milliseconds in a day (24 hours) +const DAY_IN_MILLIS = 86_400_000; + +const fetch = + (chain: string): FetchV2 => + async (options) => { + const timestampMillis = options.toTimestamp * 1_000; + const dayBeforeMillis = timestampMillis - DAY_IN_MILLIS; + const dailyVolume = await fetchURL( + `${API_URL}?chains=${chain}&from=${dayBeforeMillis}&to=${timestampMillis}` + ); + const totalVolume = await fetchURL( + `${API_URL}?chains=${chain}&to=${timestampMillis}` + ); + return { + dailyVolume: dailyVolume[chain], + totalVolume: totalVolume[chain], + timestamp: options.toTimestamp, + }; + }; + +const adapter: SimpleAdapter = { + version: 2, + adapter: {}, +}; +for (const [defillamaChain, hallswapChain] of Object.entries(CHAINS)) { + adapter.adapter[defillamaChain] = { + fetch: fetch(hallswapChain), + start: START_TIMESTAMP, + }; +} + +export default adapter; diff --git a/aggregators/hop-aggregator/index.ts b/aggregators/hop-aggregator/index.ts new file mode 100644 index 0000000000..b0a73d03b7 --- /dev/null +++ b/aggregators/hop-aggregator/index.ts @@ -0,0 +1,28 @@ +import { CHAIN } from "../../helpers/chains"; +import { httpPost } from "../../utils/fetchURL"; +import { FetchOptions } from "../../adapters/types"; +import { getTimestampAtStartOfDayUTC } from "../../utils/date" + +const fetchVolume = async (_t: any, _b: any ,options: FetchOptions) => { + const timestamp = getTimestampAtStartOfDayUTC(options.startOfDay) * 1_000; + + const res = await httpPost("https://d3axhvc6i89jmo.cloudfront.net/api/volume", { timestamp }); + const record = res.record || {}; + + return { + dailyVolume: record.total_volume_usd ? record.total_volume_usd.toFixed(2) : 0, + totalVolume: res.total_volume_usd ? res.total_volume_usd.toFixed(2) : 0, + timestamp: timestamp, + }; +}; + +const adapter: any = { + adapter: { + [CHAIN.SUI]: { + fetch: fetchVolume, + start: 1714276800 + }, + }, +}; + +export default adapter; diff --git a/aggregators/injex/index.ts b/aggregators/injex/index.ts new file mode 100644 index 0000000000..24b7a95a54 --- /dev/null +++ b/aggregators/injex/index.ts @@ -0,0 +1,22 @@ +import { httpGet } from '../../utils/fetchURL'; + +const fetchLogs = async (timestamp: any) => { + const res = await httpGet(`https://inj-api-78847b1b16a1.herokuapp.com/api/volume-stats/usd?timestamp=${timestamp.startOfDay}`); + return { + dailyVolume: res.dailyVolume, + totalVolume: res.totalVolume, + timestamp: timestamp.startOfDay, + }; +}; + +const adapter: any = { + version: 2, + adapter: { + injective: { + fetch: fetchLogs, + start: 1716411599, + }, + }, +}; + +export default adapter; diff --git a/aggregators/jumper-exchange/index.ts b/aggregators/jumper-exchange/index.ts index 5ee72a6b3d..5563b753f1 100644 --- a/aggregators/jumper-exchange/index.ts +++ b/aggregators/jumper-exchange/index.ts @@ -15,7 +15,11 @@ const contract: IContract = { [CHAIN.BSC]: '0x1231deb6f5749ef6ce6943a275a1d3e7486f4eae', [CHAIN.POLYGON]: '0x1231deb6f5749ef6ce6943a275a1d3e7486f4eae', [CHAIN.POLYGON_ZKEVM]: '0x1231deb6f5749ef6ce6943a275a1d3e7486f4eae', - [CHAIN.FANTOM]: '0x1231deb6f5749ef6ce6943a275a1d3e7486f4eae' + [CHAIN.FANTOM]: '0x1231deb6f5749ef6ce6943a275a1d3e7486f4eae', + [CHAIN.MODE]: '0x1231deb6f5749ef6ce6943a275a1d3e7486f4eae', + [CHAIN.SCROLL]: '0x1231deb6f5749ef6ce6943a275a1d3e7486f4eae', + [CHAIN.ERA]: '0x1231deb6f5749ef6ce6943a275a1d3e7486f4eae', + [CHAIN.METIS]: '0x1231deb6f5749ef6ce6943a275a1d3e7486f4eae', } const fetch: any = async (timestamp: number, _, { chain, getLogs, createBalances, }: FetchOptions): Promise => { @@ -23,8 +27,14 @@ const fetch: any = async (timestamp: number, _, { chain, getLogs, createBalances const data: any[] = await getLogs({ target: contract[chain], eventAbi: 'event LiFiGenericSwapCompleted(bytes32 indexed transactionId, string integrator, string referrer, address receiver, address fromAssetId, address toAssetId, uint256 fromAmount, uint256 toAmount)' - }) - data.forEach((e: any) => dailyVolume.add(e.toAssetId, e.toAmount)); + }); + + data.forEach((e: any) => { + if (e.integrator === 'jumper.exchange' || e.integrator === 'jumper.exchange.gas') { + dailyVolume.add(e.toAssetId, e.toAmount); + } + }); + return { dailyVolume, timestamp, } as any; }; diff --git a/aggregators/kanalabs/index.ts b/aggregators/kanalabs/index.ts index d5a0ecc7ba..c00d1b42cd 100644 --- a/aggregators/kanalabs/index.ts +++ b/aggregators/kanalabs/index.ts @@ -1,7 +1,6 @@ import fetchURL from "../../utils/fetchURL"; -import { SimpleAdapter } from "../../adapters/types"; +import { FetchOptions, SimpleAdapter } from "../../adapters/types"; import { CHAIN } from "../../helpers/chains"; -import { getUniqStartOfTodayTimestamp } from "../../helpers/getUniSubgraphVolume"; const URL = "https://stats.kanalabs.io/transaction/volume"; const TRADE_URL = "https://stats.kanalabs.io/trade/volume"; @@ -10,56 +9,39 @@ export enum KanaChainID { "solana" = 1, "aptos" = 2, "polygon" = 3, - "ethereum" = 4, - "bsc" = 5, - "klaytn" = 6, - "sui" = 8, - "Arbitrum" = 9, + "bsc" = 4, + "sui" = 5, + "ethereum" = 6, + "base" = 7, + "klaytn" = 8, + "zkSync" = 9, "Avalanche" = 10, - "zkSync" = 11, - "base" = 12, + "Arbitrum" = 11, + "optimistic" = 12, } -const fetch = (chain: KanaChainID) => async (timestamp: number) => { - const dayTimestamp = getUniqStartOfTodayTimestamp(new Date(timestamp * 1000)); - try { - const data = await fetchURL( - `${URL}?timestamp=${timestamp}&chainId=${chain}` - ); - return { - timestamp: dayTimestamp, - dailyVolume: data.today.volume, - totalVolume: data.totalVolume.volume, - }; - } catch (err) { - console.log(err); - return { - timestamp: dayTimestamp, - dailyVolume: "0", - totalVolume: "0", - }; - } +const fetch = (chain: KanaChainID) => async (timestamp: number, _t: any, options: FetchOptions) => { + const dayTimestamp = options.startOfDay + 86400; + const data = await fetchURL( + `${URL}?timestamp=${dayTimestamp - 1}&chainId=${chain}` + ); + return { + timestamp: timestamp, + dailyVolume: data.today.volume, + totalVolume: data.totalVolume.volume, + }; }; -const fetchDerivatives = (chain: KanaChainID) => async (timestamp: number) => { - const dayTimestamp = getUniqStartOfTodayTimestamp(new Date(timestamp * 1000)); - try { - const data = await fetchURL( - `${TRADE_URL}?timestamp=${timestamp}&chainId=${chain}` - ); - return { - timestamp: dayTimestamp, - dailyVolume: data.today.volume, - totalVolume: data.totalVolume.volume, - }; - } catch (err) { - console.log(err); - return { - timestamp: dayTimestamp, - dailyVolume: "0", - totalVolume: "0", - }; - } +const fetchDerivatives = (chain: KanaChainID) => async (timestamp: number, _t: any, options: FetchOptions) => { + const dayTimestamp = options.startOfDay + 86400; + const data = await fetchURL( + `${TRADE_URL}?timestamp=${dayTimestamp - 1}&chainId=${chain}` + ); + return { + timestamp: timestamp, + dailyVolume: data.today.volume, + totalVolume: data.totalVolume.volume, + }; }; const startTimeBlock = 1695897800; @@ -97,9 +79,9 @@ const adapter: SimpleAdapter = { start: startTimeBlock, }, [CHAIN.APTOS]: { - fetch: async (timestamp: number) => { - const swap = await fetch(KanaChainID.aptos)(timestamp); - const trade = await fetchDerivatives(KanaChainID.aptos)(timestamp); + fetch: async (timestamp: number, _t: any, options: FetchOptions) => { + const swap = await fetch(KanaChainID.aptos)(options.startOfDay, _t, options) + const trade = await fetchDerivatives(KanaChainID.aptos)(options.startOfDay, _t, options); return { dailyVolume: (+swap.dailyVolume + +trade.dailyVolume).toString(), totalVolume: (+swap.totalVolume + +trade.totalVolume).toString(), diff --git a/aggregators/kyberswap/index.ts b/aggregators/kyberswap/index.ts index 99eea6b75d..73255f892f 100644 --- a/aggregators/kyberswap/index.ts +++ b/aggregators/kyberswap/index.ts @@ -1,8 +1,6 @@ import { httpGet } from "../../utils/fetchURL"; -import { getUniqStartOfTodayTimestamp } from "../../helpers/getUniSubgraphVolume"; import { CHAIN } from "../../helpers/chains"; -import { ChainBlocks, FetchOptions, SimpleAdapter } from "../../adapters/types"; - +import { FetchOptions, SimpleAdapter } from "../../adapters/types"; const chainToId: Record = { [CHAIN.ETHEREUM]: 1, @@ -16,21 +14,51 @@ const chainToId: Record = { [CHAIN.SCROLL]: 534352, [CHAIN.ERA]: 324, [CHAIN.CRONOS]: 25, + [CHAIN.BASE]: 8453, + [CHAIN.MANTLE]: 5000, + [CHAIN.BLAST]: 81457, + [CHAIN.POLYGON_ZKEVM]: 1101, + [CHAIN.BITTORRENT]: 199, }; -const fetch = async (timestamp: number, _: ChainBlocks, options: FetchOptions) => { - const unixTimestamp = getUniqStartOfTodayTimestamp(new Date(timestamp * 1000)); - const url = `https://common-service.kyberswap.com/api/v1/aggregator/volume/daily?chainId=${chainToId[options.chain]}×tamps=${unixTimestamp}`; - const data = (await httpGet(url, { headers: { 'origin': 'https://common-service.kyberswap.com'}})).data?.volumes?.[0]; +const fetch = async (_a: any, _b: any, options: FetchOptions) => { + const url = `https://common-service.kyberswap.com/api/v1/aggregator/volume/daily?chainId=${ + chainToId[options.chain] + }×tamps=${options.startOfDay}`; + const data = ( + await httpGet(url, { + headers: { origin: "https://common-service.kyberswap.com" }, + }) + ).data?.volumes?.[0]; return { dailyVolume: data.value, - timestamp: timestamp, }; }; -const adapter: SimpleAdapter = { +const adapter = { + version: 1, adapter: { + [CHAIN.BASE]: { + fetch: fetch, + start: 1622544000, + }, + [CHAIN.MANTLE]: { + fetch: fetch, + start: 1622544000, + }, + [CHAIN.BLAST]: { + fetch: fetch, + start: 1622544000, + }, + [CHAIN.POLYGON_ZKEVM]: { + fetch: fetch, + start: 1622544000, + }, + /*[CHAIN.BITTORRENT]: { + fetch: fetch, + start: 1622544000, + },*/ [CHAIN.ETHEREUM]: { fetch: fetch, start: 1622544000, diff --git a/aggregators/logx/index.ts b/aggregators/logx/index.ts deleted file mode 100644 index badc642553..0000000000 --- a/aggregators/logx/index.ts +++ /dev/null @@ -1,33 +0,0 @@ -import fetchURL from "../../utils/fetchURL"; -import { FetchResult, SimpleAdapter } from "../../adapters/types"; -import { CHAIN } from "../../helpers/chains"; - -const URL = "https://logx-data-analytics-xmxmxbqxaq-uc.a.run.app/"; -const endpoint = "defillama/defillama/"; -const startTimestamp = 1686205277; // 08.06.2023 - -interface IAPIResponse { - dailyVolume: string; - totalVolume: string; -} -const fetch = async (timestamp: number): Promise => { - const { dailyVolume, totalVolume }: IAPIResponse = ( - await fetchURL(`${URL}${endpoint}${timestamp}`) - ); - return { - dailyVolume, - totalVolume, - timestamp, - }; -}; - -const adapter: SimpleAdapter = { - adapter: { - [CHAIN.ARBITRUM]: { - fetch, - start: startTimestamp, - }, - }, -}; - -export default adapter; diff --git a/aggregators/lumia/index.ts b/aggregators/lumia/index.ts new file mode 100644 index 0000000000..33c6a6022c --- /dev/null +++ b/aggregators/lumia/index.ts @@ -0,0 +1,50 @@ +import fetchURL from "../../utils/fetchURL"; +import {FetchOptions, FetchResult, SimpleAdapter} from "../../adapters/types"; +import {CHAIN} from "../../helpers/chains"; + +const chains: Record = { + [CHAIN.ETHEREUM]: 'ethereum', + [CHAIN.BSC]: 'binance-smart-chain', + [CHAIN.POLYGON]: 'polygon', + [CHAIN.ARBITRUM]: 'arbitrum', + [CHAIN.OP_BNB]: 'opbnb', + [CHAIN.LINEA]: 'linea' +}; + +interface ApiResponse { + daily_volume_in_usd: string; + daily_transaction_count: string; + total_volume_in_usd: string; + total_transaction_count: string; +} + +const fetch = (chain: string) => async (options: FetchOptions): Promise => { + const response: ApiResponse = ( + await fetchURL(`https://trade.orion.xyz/frontage/api/v1/statistics/defilama?date=${options.startTimestamp}&network=${chain}`) + ); + + return { + dailyVolume: response?.daily_volume_in_usd || '0', + totalVolume: response?.total_volume_in_usd || '0', + timestamp: options.startTimestamp, + }; +}; + +const adapter: SimpleAdapter = { + adapter: { + ...Object.entries(chains).reduce((acc, chain) => { + const [key, value] = chain; + + return { + ...acc, + [key]: { + fetch: fetch(value), + start: 1672531200, // 01.01.2023 + }, + }; + }, {}), + }, + version: 2 +}; + +export default adapter; diff --git a/aggregators/magpie/index.ts b/aggregators/magpie/index.ts new file mode 100644 index 0000000000..3b3a04638a --- /dev/null +++ b/aggregators/magpie/index.ts @@ -0,0 +1,99 @@ +import { postURL } from "../../utils/fetchURL"; +import { ChainBlocks, FetchOptions, FetchResult, SimpleAdapter } from "../../adapters/types"; +import { getTimestampAtStartOfDayUTC } from "../../utils/date" +import { CHAIN } from "../../helpers/chains"; + +const fetch = async (_t: number, _: ChainBlocks, {chain, startOfDay}: FetchOptions): Promise => { + const unixTimestamp= getTimestampAtStartOfDayUTC(startOfDay) + const data = await postURL(`https://prewimvk04.execute-api.us-west-1.amazonaws.com/prod/llama`, {timestamp: unixTimestamp, chain:chain}, 10); + const chainData = data.result + if (chainData === undefined ) { + return { + dailyVolume: 0, + timestamp: unixTimestamp, + }; + } else { + return { + dailyVolume: chainData.dailyVolume, + timestamp: unixTimestamp, + }; + } + }; + + const adapter: SimpleAdapter = { + adapter: { + [CHAIN.ETHEREUM]: { + fetch: fetch, + runAtCurrTime: true, + start: 1662595200, + }, + [CHAIN.ARBITRUM]: { + fetch: fetch, + runAtCurrTime: true, + start: 1662595200, + }, + [CHAIN.POLYGON]: { + fetch: fetch, + runAtCurrTime: true, + start: 1662595200, + }, + [CHAIN.AVAX]: { + fetch: fetch, + runAtCurrTime: true, + start: 1662595200, + }, + [CHAIN.BSC]: { + fetch: fetch, + runAtCurrTime: true, + start: 1662595200, + }, + [CHAIN.OPTIMISM]: { + fetch: fetch, + runAtCurrTime: true, + start: 1662595200, + }, + [CHAIN.BASE]: { + fetch: fetch, + runAtCurrTime: true, + start: 1662595200, + }, + [CHAIN.SCROLL]: { + fetch: fetch, + runAtCurrTime: true, + start: 1662595200, + }, + [CHAIN.MANTA]: { + fetch: fetch, + runAtCurrTime: true, + start: 1662595200, + }, + [CHAIN.TAIKO]: { + fetch: fetch, + runAtCurrTime: true, + start: 1662595200, + }, + [CHAIN.POLYGON_ZKEVM]: { + fetch: fetch, + runAtCurrTime: true, + start: 1662595200, + }, + [CHAIN.BLAST]: { + fetch: fetch, + runAtCurrTime: true, + start: 1662595200, + }, + [CHAIN.METIS]: { + fetch: fetch, + runAtCurrTime: true, + start: 1662595200, + }, + [CHAIN.FANTOM]: { + fetch: fetch, + runAtCurrTime: true, + start: 1662595200, + }, + }, + // isExpensiveAdapter: true, + }; + +export default adapter; diff --git a/aggregators/odos.ts b/aggregators/odos/index.ts similarity index 73% rename from aggregators/odos.ts rename to aggregators/odos/index.ts index cc5c543da6..e78b7096b4 100644 --- a/aggregators/odos.ts +++ b/aggregators/odos/index.ts @@ -1,7 +1,6 @@ -import { ChainBlocks, FetchOptions, FetchResultVolume, SimpleAdapter } from "../adapters/types"; -import { CHAIN } from "../helpers/chains"; -import { Chain } from "@defillama/sdk/build/general"; +import { FetchOptions, SimpleAdapter } from "../../adapters/types"; +import { CHAIN } from "../../helpers/chains"; const event_swap = 'event Swap (address sender, uint256 inputAmount, address inputToken, uint256 amountOut, address outputToken, int256 slippage, uint32 referralCode)'; const event_multiswap = 'event SwapMulti(address sender, uint256[] amountsIn, address[] tokensIn, uint256[] amountsOut, address[] tokensOut, uint32 referralCode)'; @@ -19,11 +18,13 @@ const FEE_COLLECTORS: TPool = { [CHAIN.BSC]: ['0x89b8AA89FDd0507a99d334CBe3C808fAFC7d850E',], [CHAIN.FANTOM]: ['0xd0c22a5435f4e8e5770c1fafb5374015fc12f7cd',], [CHAIN.ERA]: ['0x4bBa932E9792A2b917D47830C93a9BC79320E4f7',], - [CHAIN.POLYGON_ZKEVM]: ['0x2b8B3f0949dfB616602109D2AAbBA11311ec7aEC',], + [CHAIN.MODE]: ['0x7E15EB462cdc67Cf92Af1f7102465a8F8c784874',], + [CHAIN.LINEA]: ['0x2d8879046f1559E53eb052E949e9544bCB72f414',], + [CHAIN.MANTLE]: ['0xD9F4e85489aDCD0bAF0Cd63b4231c6af58c26745',], + [CHAIN.SCROLL]: ['0xbFe03C9E20a9Fc0b37de01A172F207004935E0b1',], } -async function fetch(timestamp: number, _: ChainBlocks, { getLogs, createBalances, chain }: FetchOptions): Promise { - timestamp = Math.floor(Date.now() / 1000) +async function fetch({ getLogs, createBalances, chain }: FetchOptions) { const feeCollectors = FEE_COLLECTORS[chain]; const dailyVolume = createBalances() const logs = await getLogs({ targets: feeCollectors, eventAbi: event_swap, }) @@ -31,11 +32,11 @@ async function fetch(timestamp: number, _: ChainBlocks, { getLogs, createBalance logs.forEach(i => dailyVolume.add(i.outputToken, i.amountOut)) multiswapLogs.forEach(i => dailyVolume.add(i.tokensOut, i.amountsOut)) - return { dailyVolume, timestamp, }; + return { dailyVolume, }; } const start = 1689292800 -const adapter: SimpleAdapter = { adapter: { }}; +const adapter: SimpleAdapter = { adapter: {}, version: 2, }; Object.keys(FEE_COLLECTORS).forEach((chain) => adapter.adapter[chain] = { fetch, start, }); -export default adapter; \ No newline at end of file +export default adapter; diff --git a/aggregators/okx/index.ts b/aggregators/okx/index.ts new file mode 100644 index 0000000000..bd51bde138 --- /dev/null +++ b/aggregators/okx/index.ts @@ -0,0 +1,84 @@ +import { CHAIN } from "../../helpers/chains"; +import { FetchOptions } from "../../adapters/types"; +import { getEnv } from "../../helpers/env"; +import axios from "axios"; +import { createHmac } from "crypto"; +const plimit = require('p-limit'); +const limits = plimit(1); + +type TChain = { + [key: string]: number; +}; +const CHAINS: TChain = { + [CHAIN.ETHEREUM]: 1, + [CHAIN.BSC]: 56, + [CHAIN.OKEXCHAIN]: 66, + [CHAIN.POLYGON]: 137, + [CHAIN.TRON]: 195, + [CHAIN.AVAX]: 43114, + [CHAIN.FANTOM]: 250, + [CHAIN.ARBITRUM]: 42161, + [CHAIN.OPTIMISM]: 10, + [CHAIN.CRONOS]: 25, + [CHAIN.SOLANA]: 501, + [CHAIN.OSMOSIS]: 706, + // 10001, "EthereumPoW" + [CHAIN.APTOS]: 637, + //[CHAIN.FLARE]: 14, // broken + [CHAIN.ERA]: 324, + [CHAIN.CONFLUX]: 1030, // Conflux eSpace + [CHAIN.SUI]: 784, + //[CHAIN.BITCOIN]: 0, // broken + [CHAIN.POLYGON_ZKEVM]: 1101, + [CHAIN.SEI]: 70000029, + [CHAIN.LINEA]: 59144, + [CHAIN.MANTLE]: 5000, + [CHAIN.BASE]: 8453, + [CHAIN.STACKS]: 5757, + [CHAIN.STARKNET]: 9004, + [CHAIN.SCROLL]: 534352, + [CHAIN.XLAYER]: 196, + [CHAIN.MANTA]: 169, + [CHAIN.METIS]: 1088, + [CHAIN.ZETA]: 7000, + [CHAIN.MERLIN]: 4200, + [CHAIN.BLAST]: 81457, + [CHAIN.MODE]: 34443, + [CHAIN.TON]: 607, +}; + +const fetch = async (_timestampParam: number, block: any, options: FetchOptions) => { + const timestamp = new Date().toISOString() + const path = `/api/v5/dex/aggregator/volume?timestamp=${options.endTimestamp * 1e3}&chainId=${CHAINS[options.chain]}` + const [secretKey, passphrase] = getEnv("0KX_API_KEY").split(":") + const data = await limits(() => axios.get(`https://www.okx.com${path}`, { + headers: { + 'OK-ACCESS-PROJECT': 'be0ee327bbc230c3977c6868a77cd894', + 'OK-ACCESS-KEY': 'feb1a319-69e0-4c00-96df-d1188d8a616a', + 'OK-ACCESS-SIGN': createHmac('sha256', secretKey) + .update(timestamp + 'GET' + path) + .digest('base64'), + 'OK-ACCESS-PASSPHRASE': passphrase, + 'OK-ACCESS-TIMESTAMP': timestamp + } + })); + return { + dailyVolume: data.data.data.volumeUsdLast24hour, + timestamp: options.endTimestamp, + }; +}; + +const adapter: any = { + version: 1, // api supports other timestamps but if you try using current timestamps, it breaks, so sticking to v1 even though it should be able to support v2 + adapter: Object.keys(CHAINS).reduce((acc, chain) => { + return { + ...acc, + [chain]: { + fetch: fetch, + start: 1652745600, + }, + }; + }, {}), +}; + +export default adapter; diff --git a/aggregators/opt-agg/index.ts b/aggregators/opt-agg/index.ts new file mode 100644 index 0000000000..cf82c98f74 --- /dev/null +++ b/aggregators/opt-agg/index.ts @@ -0,0 +1,26 @@ +import fetchURL from "../../utils/fetchURL"; +import { FetchResult, SimpleAdapter } from "../../adapters/types"; +import { CHAIN } from "../../helpers/chains"; + +const URL = "https://api.opt.finance/stat/vol"; + +const fetch = async (timestamp: number): Promise => { + const dailyVolume = (await fetchURL(`${URL}`)).data.total_24h; + + return { + dailyVolume, + timestamp, +}; +}; + +const adapter: SimpleAdapter = { + adapter: { + [CHAIN.WEMIX]: { + fetch, + start: 1705017600, + runAtCurrTime: true + }, + }, +}; + +export default adapter; diff --git a/aggregators/paraswap/index.ts b/aggregators/paraswap/index.ts index ba2a4f9f3c..0e0a3a2fab 100644 --- a/aggregators/paraswap/index.ts +++ b/aggregators/paraswap/index.ts @@ -1,38 +1,3 @@ -// https://developers.paraswap.network/smart-contracts -const chains = [ - "ethereum", - "arbitrum", - "avax", - "bsc", - "fantom", - "optimism", - "polygon", - "base", - "polygon_zkevm", -]; +import { getParaswapAdapter } from "./paraswapApi"; -import { ChainBlocks, FetchOptions } from "../../adapters/types"; - -const abis = { - "SwappedDirect": "event SwappedDirect(bytes16 uuid, address partner, uint256 feePercent, address initiator, uint8 kind, address indexed beneficiary, address indexed srcToken, address indexed destToken, uint256 srcAmount, uint256 receivedAmount, uint256 expectedAmount)", - "SwappedV3": "event SwappedV3(bytes16 uuid, address partner, uint256 feePercent, address initiator, address indexed beneficiary, address indexed srcToken, address indexed destToken, uint256 srcAmount, uint256 receivedAmount, uint256 expectedAmount)", -} - -const defaultSwapper = '0xDEF171Fe48CF0115B1d80b88dc8eAB59176FEe57' -const fetch = async (timestamp: number, _: ChainBlocks, { createBalances, getLogs, chain, }: FetchOptions) => { - const dailyVolume = createBalances() - let target = defaultSwapper - if (chain === "polygon_zkevm") target = '0xb83b554730d29ce4cb55bb42206c3e2c03e4a40a' - const swappedDirectLogs = await getLogs({ target, eventAbi: abis.SwappedDirect, }) - const swappedV3Logs = await getLogs({ target, eventAbi: abis.SwappedV3, }); - [swappedDirectLogs, swappedV3Logs].flat().forEach((log: any) => { - dailyVolume.add(log.destToken, log.receivedAmount) - }) - return { timestamp, dailyVolume } -}; - -const adapter: any = { adapter: {}, }; - -chains.forEach((chain) => adapter.adapter[chain] = { fetch, start: 1676592000, }); - -export default adapter; +export default getParaswapAdapter("volume"); diff --git a/aggregators/paraswap/paraswapApi.ts b/aggregators/paraswap/paraswapApi.ts new file mode 100644 index 0000000000..ebc5b52535 --- /dev/null +++ b/aggregators/paraswap/paraswapApi.ts @@ -0,0 +1,77 @@ +import { Adapter, FetchResultFees, FetchResultVolume } from "../../adapters/types"; +import { CHAIN } from "../../helpers/chains"; +import { getTimestampAtStartOfDayUTC } from "../../utils/date"; +import { Chain } from "@defillama/sdk/build/general"; +import fetchURL from "../../utils/fetchURL"; + + +const feesMMURL = "https://api.paraswap.io/stk/volume-stats/breakdown-by-chain"; +type TChainId = { + [l: string | Chain]: string; +} +const mapChainId: TChainId = { + [CHAIN.ETHEREUM]: '1', + [CHAIN.POLYGON]: '137', + [CHAIN.BSC]: '56', + [CHAIN.AVAX]: '43114', + [CHAIN.FANTOM]: '250', + [CHAIN.ARBITRUM]: '42161', + [CHAIN.OPTIMISM]: '10', + [CHAIN.BASE]: '8453', + [CHAIN.POLYGON_ZKEVM]: '1101' +} + +interface IResponse { + daily: any[]; + allTime: any; +} + +export function getParaswapAdapter(type:"fees"|"volume"){ +const fetch = (chain: Chain) => { + return async (timestamp: number): Promise => { + const timestampToday = getTimestampAtStartOfDayUTC(timestamp) + const response: IResponse = (await fetchURL(feesMMURL)); + const dailyResultFees: any[] = response.daily; + const [totalVolume,totalPartnerRevenue, totalProtocolRevenue]: number[] = response.allTime[mapChainId[chain]]; + const [dailyVolume, partnerRevenue, protocolRevenue]: number[] = dailyResultFees.filter(([time]: any) => time === timestampToday) + .map(([_, data]: any) => data[mapChainId[chain]]).flat() + const otherFees = partnerRevenue + protocolRevenue; + const otherProtocolReveune = protocolRevenue; + + const dailyFees = otherFees; + if (dailyFees > 1_000_000) { + return {} as FetchResultFees; + } + const dailyRevenue = otherProtocolReveune; + const totalFees = totalPartnerRevenue + totalProtocolRevenue; + const totalRevenue = totalProtocolRevenue; + if(type === "fees"){ + return { + dailyFees: dailyFees ? dailyFees.toString() : undefined, + dailyRevenue: dailyRevenue ? dailyRevenue.toString() : undefined, + totalRevenue: totalRevenue ? totalRevenue.toString() : undefined, + totalFees: totalFees ? totalFees.toString(): undefined, + timestamp + } + } else { + return { + dailyVolume: dailyVolume.toString(), + totalVolume: totalVolume.toString(), + timestamp + } + } + } +} + +const adapter: Adapter = { + adapter: Object.keys(mapChainId).reduce((all, chain)=>({ + ...all, + [chain]:{ + fetch: fetch(chain), + start: 1647907200, + } + }), {} as any) +} + +return adapter +} diff --git a/aggregators/plexus/index.ts b/aggregators/plexus/index.ts index a59b52b2dd..571184bcde 100644 --- a/aggregators/plexus/index.ts +++ b/aggregators/plexus/index.ts @@ -13,7 +13,7 @@ const ChainId: TChainID = { [CHAIN.XDAI]: 100, [CHAIN.POLYGON]: 137, [CHAIN.FANTOM]: 250, - [CHAIN.ERA]: 324, + // [CHAIN.ERA]: 324, [CHAIN.POLYGON_ZKEVM]: 1101, [CHAIN.KAVA]: 2222, [CHAIN.KLAYTN]: 8217, diff --git a/aggregators/rainbow-swap/index.ts b/aggregators/rainbow-swap/index.ts new file mode 100644 index 0000000000..8815e34d25 --- /dev/null +++ b/aggregators/rainbow-swap/index.ts @@ -0,0 +1,32 @@ +import {Fetch, SimpleAdapter} from "../../adapters/types"; +import {CHAIN} from "../../helpers/chains"; +import fetchURL from "../../utils/fetchURL"; + +const URL = 'https://api.blackbot.technology'; +const endpoint = '/rainbow/analytics/volumes'; +const start = 1720645200;// 11.07.2024 + +interface IAPIResponse { + dailyVolume: string; + totalVolume: string; +} + +const fetch: Fetch = async (timestamp) => { + const {dailyVolume, totalVolume}: IAPIResponse = await fetchURL(`${URL}${endpoint}?timestamp=${timestamp * 1000}`); + + return { + timestamp, + dailyVolume, + totalVolume + }; +}; + +const adapters: SimpleAdapter = { + adapter: { + [CHAIN.TON]: { + start, + fetch + } + } +} +export default adapters diff --git a/aggregators/rubic/index.ts b/aggregators/rubic/index.ts new file mode 100644 index 0000000000..e313bd6264 --- /dev/null +++ b/aggregators/rubic/index.ts @@ -0,0 +1,81 @@ +import fetchURL from "../../utils/fetchURL"; +import {FetchOptions, FetchResult, SimpleAdapter} from "../../adapters/types"; +import {CHAIN} from "../../helpers/chains"; + + +const chains: Record = { + [CHAIN.SOLANA]: 'solana', + [CHAIN.ETHEREUM]: 'ethereum', + [CHAIN.BSC]: 'binance-smart-chain', + [CHAIN.AVAX]: 'avalanche', + [CHAIN.POLYGON]: 'polygon', + [CHAIN.ARBITRUM]: 'arbitrum', + [CHAIN.ZKSYNC]: 'zksync', + [CHAIN.BLAST]: 'blast', + [CHAIN.LINEA]: 'linea', + [CHAIN.SCROLL]: 'scroll', + [CHAIN.ZETA]: 'zetachain', + [CHAIN.MANTLE]: 'mantle', + [CHAIN.MANTA]: 'manta-pacific', + [CHAIN.POLYGON_ZKEVM]: 'polygon-zkevm', + [CHAIN.PULSECHAIN]: 'pulsechain', + [CHAIN.BASE]: 'base', + [CHAIN.FANTOM]: 'fantom', + [CHAIN.BOBA]: 'boba', + [CHAIN.TELOS]: 'telos-evm', + [CHAIN.KAVA]: 'kava', + [CHAIN.OPTIMISM]: 'optimistic-ethereum', + [CHAIN.AURORA]: 'aurora', + [CHAIN.METIS]: 'metis', + [CHAIN.MOONRIVER]: 'moonriver', + [CHAIN.TRON]: 'tron', + [CHAIN.MOONBEAM]: 'moonbeam', + [CHAIN.FUSE]: 'fuse', + [CHAIN.CELO]: 'celo', + [CHAIN.OKEXCHAIN]: 'oke-x-chain', + [CHAIN.CRONOS]: 'cronos', + [CHAIN.MODE]: 'mode', + [CHAIN.MERLIN]: 'merlin', + [CHAIN.CORE]: 'core', + [CHAIN.TAIKO]: 'taiko', + [CHAIN.ZKLINK]: 'zklink', + [CHAIN.BITLAYER]: 'bitlayer' +}; + +interface ApiResponse { + daily_volume_in_usd: string; + daily_transaction_count: string; + total_volume_in_usd: string; + total_transaction_count: string; +} + +const fetch = (chain: string) => async (options: FetchOptions): Promise => { + const response: ApiResponse = ( + await fetchURL(`https://api.rubic.exchange/api/stats/defilama_onchain?date=${options.startTimestamp}&network=${chain}`) + ); + + return { + dailyVolume: response?.daily_volume_in_usd || '0', + totalVolume: response?.total_volume_in_usd || '0', + timestamp: options.startTimestamp, + }; +}; + +const adapter: SimpleAdapter = { + adapter: { + ...Object.entries(chains).reduce((acc, chain) => { + const [key, value] = chain; + + return { + ...acc, + [key]: { + fetch: fetch(value), + start: 1672531200, // 01.01.2023 + }, + }; + }, {}), + }, + version: 2 +}; + +export default adapter; diff --git a/aggregators/scallop/index.ts b/aggregators/scallop/index.ts new file mode 100644 index 0000000000..c53c0e88f4 --- /dev/null +++ b/aggregators/scallop/index.ts @@ -0,0 +1,22 @@ +import fetchURL from '../../utils/fetchURL'; +import { FetchV2, SimpleAdapter } from '../../adapters/types'; +import { CHAIN } from '../../helpers/chains'; + +const fetch: FetchV2 = async ({ startTimestamp, endTimestamp }) => { + const dailyVolume = await fetchURL( + `https://sui.apis.scallop.io/statistic/swap/daily-volume?fromTimestamp=${startTimestamp}&toTimestamp=${endTimestamp}`, + ); + return { dailyVolume: dailyVolume.swapVolume }; +}; + +const adapter: SimpleAdapter = { + version: 2, + adapter: { + [CHAIN.SUI]: { + fetch, + start: 1722877683, + }, + }, +}; + +export default adapter; diff --git a/aggregators/swap-coffee/index.ts b/aggregators/swap-coffee/index.ts new file mode 100644 index 0000000000..8c5e84e273 --- /dev/null +++ b/aggregators/swap-coffee/index.ts @@ -0,0 +1,38 @@ +import { Adapter, FetchV2 } from "../../adapters/types"; +import { httpGet } from "../../utils/fetchURL"; +import { CHAIN } from "../../helpers/chains"; +import { DAY, getTimestampAtStartOfDay } from "../../utils/date"; + +const statisticsEndpoint = "https://backend.swap.coffee/v1/statistics/generic" + +const fetch: FetchV2 = async ({startTimestamp}) => { + const start = getTimestampAtStartOfDay(startTimestamp) + const end = start + DAY + + const statistics = await httpGet( + statisticsEndpoint, + { + params: { + from: start, + to: end + } + }) + + return { + timestamp: end, + dailyVolume: statistics?.volume, + dailyFees: statistics?.fees, + }; +} + +const adapter: Adapter = { + version: 2, + adapter: { + [CHAIN.TON]: { + fetch, + start: 1717957740, + }, + } +} + +export default adapter; diff --git a/aggregators/swapgpt/index.ts b/aggregators/swapgpt/index.ts index c9414769c3..60cccdccb4 100644 --- a/aggregators/swapgpt/index.ts +++ b/aggregators/swapgpt/index.ts @@ -1,42 +1,37 @@ -import fetchURL from "../../utils/fetchURL" -import { SimpleAdapter } from "../../adapters/types"; +import { httpGet } from "../../utils/fetchURL"; +import { FetchOptions, SimpleAdapter } from "../../adapters/types"; import { CHAIN } from "../../helpers/chains"; -import { getUniqStartOfTodayTimestamp } from "../../helpers/getUniSubgraphVolume"; - - interface IVolumeall { - grouptimestamp: string; - amount: string; + totalVolumeUSD: string; + dailyVolumeUSD: Array<{ + startDateTime: string; + dailyVolumeUSD: string; + }> } -const baseUrl = "https://stats.swapgpt.ai" -const endpoint = "stats/getDefiLamaStats" - - -const fetch = async (timestamp: number) => { - const dayTimestamp = getUniqStartOfTodayTimestamp(new Date(timestamp * 1000)) - const historicalVolume: IVolumeall[] = (await fetchURL(`${baseUrl}/${endpoint}`))?.volumeInUsd - const totalVolume = historicalVolume - .filter(volItem => (new Date(volItem.grouptimestamp).getTime() / 1000) <= dayTimestamp) - .reduce((acc, { amount }) => acc + Number(amount), 0) - - const dailyVolume = historicalVolume - .find(dayItem => (new Date(dayItem.grouptimestamp).getTime() / 1000) === dayTimestamp)?.amount +const baseUrl = "https://stats-api.panora.exchange"; +const endpoint = "getDefiLlamaStats"; +const fetch = async (options: FetchOptions) => { + const timestamp = options.startOfDay + const dateStr = new Date(timestamp * 1000).toISOString().split('T')[0]; + const response: IVolumeall = (await httpGet(`${baseUrl}/${endpoint}`)); + const totalVolume = response.totalVolumeUSD; + const dailyVolume = response.dailyVolumeUSD.find((d) => d.startDateTime.split('T')[0] === dateStr); return { - totalVolume: `${totalVolume}`, - dailyVolume: dailyVolume ? `${dailyVolume}` : undefined, - timestamp: dayTimestamp, - }; + dailyVolume: dailyVolume?.dailyVolumeUSD, + totalVolume + } }; const adapter: SimpleAdapter = { + version: 2, adapter: { [CHAIN.APTOS]: { - fetch: fetch, - start: (new Date('2023-11-28T00:00:00.000Z').getTime() / 1000), - } + fetch, + start: 1701129600, + }, }, }; diff --git a/aggregators/tondiamonds/index.ts b/aggregators/tondiamonds/index.ts new file mode 100644 index 0000000000..3ff9b91116 --- /dev/null +++ b/aggregators/tondiamonds/index.ts @@ -0,0 +1,26 @@ +import { Adapter, FetchV2 } from "../../adapters/types"; +import { httpGet } from "../../utils/fetchURL"; +import { CHAIN } from "../../helpers/chains"; + +const statisticsEndpoint = "https://ton.diamonds/api/v2/dex/stats" + +const fetch: FetchV2 = async ({startTimestamp}) => { + const statistics = await httpGet(statisticsEndpoint) + + return { + timestamp: Math.floor(new Date(statistics?.data?.yesterday).getTime() / 1000), + dailyVolume: statistics?.data?.yesterdayVolume, + }; +} + +const adapter: Adapter = { + version: 2, + adapter: { + [CHAIN.TON]: { + fetch, + start: 1725148800, + }, + } +} + +export default adapter; diff --git a/aggregators/udex-agg/index.ts b/aggregators/udex-agg/index.ts new file mode 100644 index 0000000000..1435d1c972 --- /dev/null +++ b/aggregators/udex-agg/index.ts @@ -0,0 +1,47 @@ +import { Chain } from "@defillama/sdk/build/general"; +import { FetchResult, FetchResultV2, FetchV2, SimpleAdapter } from "../../adapters/types"; +import { CHAIN } from "../../helpers/chains"; +import customBackfill from "../../helpers/customBackfill"; + +let abi = ["event Swap(address indexed payer,address indexed payee,address fromToken,address toToken,uint fromAmount,uint receivedAmount)"]; +let knownTokens=new Set(["0xbb4CdB9CBd36B01bD1cBaEBF2De08d9173bc095c","0x55d398326f99059fF775485246999027B3197955","0x8ac76a51cc950d9822d68b83fe1ad97b32cd580d"]) +type IContract = { + [c: string | Chain]: string; +} + +const contract: IContract = { + [CHAIN.BSC]: '0xfCD555b55AA785d46E8c6e9bBB109b10602c431c', + [CHAIN.POLYGON]:'0x464599BDaC77E8e5843D5BbC531EC8aD75d3F7b1', + [CHAIN.ETHEREUM]:'0x9556E8ce70ceA3c43e4A6c17ad2FAb258067b058', + [CHAIN.BASE]:'0x334F493613c1dD33a364684802fB9C728dfcE1A5', + [CHAIN.OP_BNB]:'0x8A3e34e45b76885001aa024d6F35FBAcfDBd9DB0' + +} + +const fetch: FetchV2 = async ({ getLogs, createBalances, chain, }): Promise => { + const dailyVolume = createBalances(); + const logs = (await getLogs({ target: contract[chain], eventAbi: abi[0] })) + logs.map((log: any) => { + if ( knownTokens.has(log.toToken)){ + dailyVolume.add(log.toToken, log.receivedAmount) + }else{ + dailyVolume.add(log.fromToken, log.fromAmount) + } + }); + return { dailyVolume }; +}; + +const adapter: SimpleAdapter = { + adapter: Object.keys(contract).reduce((acc, chain) => { + return { + ...acc, + [chain]: { + fetch, + start: 1726531200, + runAtCurrTime:false + }, + } + }, {}), + version: 2, +}; +export default adapter; \ No newline at end of file diff --git a/aggregators/unidex/index.ts b/aggregators/unidex/index.ts deleted file mode 100644 index ec2bef8a48..0000000000 --- a/aggregators/unidex/index.ts +++ /dev/null @@ -1,53 +0,0 @@ -import { FetchResult } from "../../adapters/types"; -import { getUniqStartOfTodayTimestamp } from "../../helpers/getUniSubgraphVolume"; -import { CHAIN } from "../../helpers/chains"; -import { httpGet } from "../../utils/fetchURL"; - -const chainsMap: Record = { - ETHEREUM: "ethereum", - ARBITRUM: "arbitrum", - POLYGON: "polygon", - BNB: "bsc", - OPTIMISM: "optimism", - BASE: "base", - FANTOM: "fantom", - METIS: "metis", - GNOSIS: "gnosis", - [CHAIN.ERA]: "zksync", - AVALANCHE: "avax", -}; - -const fetch = - (chain: string) => - async (_: number): Promise => { - const unixTimestamp = getUniqStartOfTodayTimestamp(); - - const response = await httpGet(`https://unidexswaps.metabaseapp.com/api/public/dashboard/f0dd81ef-7bc7-47b5-9ac4-281c7cd71bdc/dashcard/11/card/12?parameters=%5B%5D`) - - const rows = response.data.rows; - const chainData = rows.find( - (row: any) => row[1].toLowerCase() === chain - ); - - return { - dailyVolume: chainData ? chainData[2].toString() : "0", - timestamp: unixTimestamp, - }; - }; - -const adapter: any = { - adapter: { - ...Object.values(chainsMap).reduce((acc, chain) => { - return { - ...acc, - [(chainsMap as any)[chain] || chain]: { - fetch: fetch(chain), - runAtCurrTime: true, - start: 1704348000, - }, - }; - }, {}), - }, -}; - -export default adapter; diff --git a/aggregators/wolfswap/index.ts b/aggregators/wolfswap/index.ts new file mode 100644 index 0000000000..7a073b99ef --- /dev/null +++ b/aggregators/wolfswap/index.ts @@ -0,0 +1,38 @@ +import { ChainBlocks, FetchOptions } from "../../adapters/types"; + +const abis = { + "Swapped": "event Swapped(uint indexed id, address wallet, address sourceToken, address destinationToken, uint amountOut)", +} + +const contracts = { + polygon: '0x9fB5f7Bc34cEd4dE039405D7bE26CbF1D0a420d9', + cronos: '0xeC68090566397DCC37e54B30Cc264B2d68CF0489', + cronos_zkevm: '0x7c39eAcCd16cDAD8BFE05e1874da1BD315DB766F', + base: '0xE6174feAD698da575312ae85020A3224E556f8F9', + avax: '0x643dEB007DfA43c0D7BeA2155E97E61279d9a56F', + sei: '0x1AD805e80b59C802f9D8059f904DCA6AC153de30', + blast: '0xb86a6e5702C327c5C051Bf5323Cb2bAb5E628d0c', +} + +const fetch = async (timestamp: number, _: ChainBlocks, { createBalances, getLogs, chain, api }: FetchOptions) => { + const dailyVolume = createBalances() + const logs = await getLogs({ target: contracts[chain], eventAbi: abis.Swapped, }) + logs.forEach((log: any) => { + dailyVolume.add(log.destinationToken, log.amountOut) + }) + return { timestamp, dailyVolume } +}; + +const adapter: any = { + adapter: { + polygon: { fetch, start: 1710972000, }, + cronos: { fetch, start: 1711317600, }, + cronos_zkevm: { fetch, start: 1718830800, }, + base: { fetch, start: 1713128400, }, + avax: { fetch, start: 1717189200, }, + //sei: { fetch, start: 1717189200, }, + blast: { fetch, start: 1709848800, }, + }, +}; + +export default adapter; diff --git a/aggregators/wowmax/index.ts b/aggregators/wowmax/index.ts index 4081697b42..36dda617bc 100644 --- a/aggregators/wowmax/index.ts +++ b/aggregators/wowmax/index.ts @@ -10,6 +10,10 @@ const chains = [ CHAIN.SCROLL, CHAIN.CRONOS, CHAIN.MANTA, + CHAIN.BLAST, + CHAIN.XLAYER, + CHAIN.METIS, + CHAIN.ARBITRUM ]; const chainToId: Record = { @@ -19,7 +23,11 @@ const chainToId: Record = { [CHAIN.LINEA]: 59144, [CHAIN.SCROLL]: 534352, [CHAIN.CRONOS]: 25, - [CHAIN.MANTA]: 169 + [CHAIN.MANTA]: 169, + [CHAIN.BLAST]: 81457, + [CHAIN.METIS]: 1088, + [CHAIN.XLAYER]: 196, + [CHAIN.ARBITRUM]: 42161, }; const fetch = (chain: string) => async (timestamp: number) => { diff --git a/aggregators/zrx/index.ts b/aggregators/zrx/index.ts index 51e1b50ed2..a3a33645ab 100644 --- a/aggregators/zrx/index.ts +++ b/aggregators/zrx/index.ts @@ -1,18 +1,24 @@ import { GraphQLClient, gql } from "graphql-request"; + +import { CHAIN } from "../../helpers/chains"; import { getUniqStartOfTodayTimestamp } from "../../helpers/getUniSubgraphVolume"; +import { FetchOptions } from "../../adapters/types"; import { getEnv } from "../../helpers/env"; -const CHAINS = [ - "Arbitrum", - "Avalanche", - "Base", - "BSC", - "Celo", - "Ethereum", - "Fantom", - "Optimism", - "Polygon", -]; +type TChain = { + [key: string]: string; +}; +const CHAINS: TChain = { + [CHAIN.ARBITRUM]: "Arbitrum", + [CHAIN.AVAX]: "Avalanche", + [CHAIN.BASE]: "Base", + [CHAIN.BSC]: "BSC", + [CHAIN.CELO]: "Celo", + [CHAIN.ETHEREUM]: "Ethereum", + [CHAIN.FANTOM]: "Fantom", + [CHAIN.OPTIMISM]: "Optimism", + [CHAIN.POLYGON]: "Polygon", +}; const graphQLClient = new GraphQLClient("https://api.0x.org/data/v0"); const getGQLClient = () => { @@ -41,31 +47,39 @@ const getVolumeByChain = async (chain: string) => { return data; }; -const fetch = (chain: string) => async (timestamp: number) => { +const fetch = async (options: FetchOptions) => { const unixTimestamp = getUniqStartOfTodayTimestamp( - new Date(timestamp * 1000) + new Date(options.endTimestamp * 1000) ); - - const data = await getVolumeByChain(chain); - const dayData = data.find( - ({ timestamp }: { timestamp: number }) => - getUniqStartOfTodayTimestamp(new Date(timestamp)) === unixTimestamp - ); - - return { - dailyVolume: dayData.volumeUSD, - timestamp: unixTimestamp, - }; + try { + const data = await getVolumeByChain(options.chain); + const strDate = new Date(unixTimestamp * 1000).toISOString().split("T")[0]; + const dayData = data.find( + ({ timestamp }: { timestamp: string }) => + timestamp.split("T")[0] === strDate + ); + return { + dailyVolume: dayData?.volumeUSD, + timestamp: unixTimestamp, + }; + } catch (e) { + console.error(e); + return { + dailyVolume: "0", + timestamp: unixTimestamp, + }; + } }; const adapter: any = { + version: 1, adapter: { ...Object.values(CHAINS).reduce((acc, chain) => { return { ...acc, [chain]: { - fetch: fetch(chain), - start: 1671062400, + fetch: fetch, + start: 1652745600, }, }; }, {}), diff --git a/bridge-aggregators/bungee/index.ts b/bridge-aggregators/bungee/index.ts new file mode 100644 index 0000000000..4b34650476 --- /dev/null +++ b/bridge-aggregators/bungee/index.ts @@ -0,0 +1,52 @@ +import { Chain } from "@defillama/sdk/build/general"; +import { FetchOptions, FetchResultVolume, SimpleAdapter } from "../../adapters/types"; +import { CHAIN } from "../../helpers/chains"; + +type IContract = { + [c: string | Chain]: string; +} + +const contract: IContract = { + [CHAIN.AURORA]: '0x3a23f943181408eac424116af7b7790c94cb97a5', + [CHAIN.ARBITRUM]: '0x3a23f943181408eac424116af7b7790c94cb97a5', + [CHAIN.OPTIMISM]: '0x3a23f943181408eac424116af7b7790c94cb97a5', + [CHAIN.BASE]: '0x3a23f943181408eac424116af7b7790c94cb97a5', + [CHAIN.BLAST]: '0x3a23f943181408eac424116af7b7790c94cb97a5', + [CHAIN.ETHEREUM]: '0x3a23f943181408eac424116af7b7790c94cb97a5', + [CHAIN.AVAX]: '0x3a23f943181408eac424116af7b7790c94cb97a5', + [CHAIN.BSC]: '0x3a23f943181408eac424116af7b7790c94cb97a5', + [CHAIN.POLYGON]: '0x3a23f943181408eac424116af7b7790c94cb97a5', + [CHAIN.POLYGON_ZKEVM]: '0x3a23f943181408eac424116af7b7790c94cb97a5', + [CHAIN.FANTOM]: '0x3a23f943181408eac424116af7b7790c94cb97a5', + [CHAIN.LINEA]: '0x3a23f943181408eac424116af7b7790c94cb97a5', + [CHAIN.MANTLE]: '0x3a23f943181408eac424116af7b7790c94cb97a5', + [CHAIN.SCROLL]: '0x3a23f943181408eac424116af7b7790c94cb97a5', + [CHAIN.ZKSYNC]: '0x3a23f943181408eac424116af7b7790c94cb97a5', + [CHAIN.XDAI]: '0x3a23f943181408eac424116af7b7790c94cb97a5', +} + +const fetch: any = async (timestamp: number, _, { chain, getLogs, createBalances, }: FetchOptions): Promise => { + const dailyVolume = createBalances(); + const data: any[] = await getLogs({ + target: contract[chain], + eventAbi: 'event SocketBridge(uint256 amount, address token, uint256 toChainId, bytes32 bridgeName, address sender, address receiver, bytes32 metadata)' + }); + data.forEach((e: any) => { + if (e.metadata === '0x00000000000000000000000000000000000000000000000000000000000000cd') { + dailyVolume.add(e.token, e.amount); + } + }); + + return { dailyBridgeVolume: dailyVolume , timestamp, } as any; +}; + +const adapter: SimpleAdapter = { + adapter: Object.keys(contract).reduce((acc, chain) => { + return { + ...acc, + [chain]: { fetch, start: 1691625600, } + } + }, {}) +}; + +export default adapter; diff --git a/bridge-aggregators/jumper.exchange/index.ts b/bridge-aggregators/jumper.exchange/index.ts new file mode 100644 index 0000000000..aa2200cc32 --- /dev/null +++ b/bridge-aggregators/jumper.exchange/index.ts @@ -0,0 +1,53 @@ +import { Chain } from "@defillama/sdk/build/general"; +import { FetchOptions, FetchResultVolume, SimpleAdapter } from "../../adapters/types"; +import { CHAIN } from "../../helpers/chains"; + +type IContract = { + [c: string | Chain]: string; +} + +const contract: IContract = { + [CHAIN.AURORA]: '0x1231deb6f5749ef6ce6943a275a1d3e7486f4eae', + [CHAIN.ARBITRUM]: '0x1231deb6f5749ef6ce6943a275a1d3e7486f4eae', + [CHAIN.OPTIMISM]: '0x1231deb6f5749ef6ce6943a275a1d3e7486f4eae', + [CHAIN.BASE]: '0x1231deb6f5749ef6ce6943a275a1d3e7486f4eae', + [CHAIN.ETHEREUM]: '0x1231deb6f5749ef6ce6943a275a1d3e7486f4eae', + [CHAIN.AVAX]: '0x1231deb6f5749ef6ce6943a275a1d3e7486f4eae', + [CHAIN.BSC]: '0x1231deb6f5749ef6ce6943a275a1d3e7486f4eae', + [CHAIN.LINEA]: '0x1231deb6f5749ef6ce6943a275a1d3e7486f4eae', + [CHAIN.MANTA]: '0x1231deb6f5749ef6ce6943a275a1d3e7486f4eae', + [CHAIN.POLYGON]: '0x1231deb6f5749ef6ce6943a275a1d3e7486f4eae', + [CHAIN.POLYGON_ZKEVM]: '0x1231deb6f5749ef6ce6943a275a1d3e7486f4eae', + [CHAIN.FANTOM]: '0x1231deb6f5749ef6ce6943a275a1d3e7486f4eae', + [CHAIN.MODE]: '0x1231deb6f5749ef6ce6943a275a1d3e7486f4eae', + [CHAIN.SCROLL]: '0x1231deb6f5749ef6ce6943a275a1d3e7486f4eae', + [CHAIN.ERA]: '0x1231deb6f5749ef6ce6943a275a1d3e7486f4eae', + [CHAIN.METIS]: '0x1231deb6f5749ef6ce6943a275a1d3e7486f4eae', + [CHAIN.XDAI]: '0x1231deb6f5749ef6ce6943a275a1d3e7486f4eae', +} + +const fetch: any = async (timestamp: number, _, { chain, getLogs, createBalances, }: FetchOptions): Promise => { + const dailyVolume = createBalances(); + const data: any[] = await getLogs({ + target: contract[chain], + eventAbi: 'event LiFiTransferStarted(bytes32 indexed transactionId, string bridge, string integrator, address referrer, address sendingAssetId, address receiver, uint256 minAmount, uint256 destinationChainId,bool hasSourceSwaps,bool hasDestinationCall )' + }); + data.forEach((e: any) => { + if (e.integrator === 'jumper.exchange' || e.integrator === 'jumper.exchange.gas') { + dailyVolume.add(e.sendingAssetId, e.minAmount); + } + }); + + return { dailyBridgeVolume: dailyVolume, timestamp, } as any; +}; + +const adapter: SimpleAdapter = { + adapter: Object.keys(contract).reduce((acc, chain) => { + return { + ...acc, + [chain]: { fetch, start: 1691625600, } + } + }, {}) +}; + +export default adapter; diff --git a/bridge-aggregators/sharpe-bridge/index.ts b/bridge-aggregators/sharpe-bridge/index.ts new file mode 100644 index 0000000000..6594796693 --- /dev/null +++ b/bridge-aggregators/sharpe-bridge/index.ts @@ -0,0 +1,54 @@ +import { Chain } from "@defillama/sdk/build/general"; +import { FetchOptions, FetchResultVolume, SimpleAdapter } from "../../adapters/types"; +import { CHAIN } from "../../helpers/chains"; + +type IContract = { + [c: string | Chain]: string; +} + +const contract: IContract = { + [CHAIN.AURORA]: '0x1231deb6f5749ef6ce6943a275a1d3e7486f4eae', + [CHAIN.ARBITRUM]: '0x1231deb6f5749ef6ce6943a275a1d3e7486f4eae', + [CHAIN.OPTIMISM]: '0x1231deb6f5749ef6ce6943a275a1d3e7486f4eae', + [CHAIN.BASE]: '0x1231deb6f5749ef6ce6943a275a1d3e7486f4eae', + [CHAIN.ETHEREUM]: '0x1231deb6f5749ef6ce6943a275a1d3e7486f4eae', + [CHAIN.AVAX]: '0x1231deb6f5749ef6ce6943a275a1d3e7486f4eae', + [CHAIN.BSC]: '0x1231deb6f5749ef6ce6943a275a1d3e7486f4eae', + [CHAIN.LINEA]: '0x1231deb6f5749ef6ce6943a275a1d3e7486f4eae', + [CHAIN.MANTA]: '0x1231deb6f5749ef6ce6943a275a1d3e7486f4eae', + [CHAIN.POLYGON]: '0x1231deb6f5749ef6ce6943a275a1d3e7486f4eae', + [CHAIN.POLYGON_ZKEVM]: '0x1231deb6f5749ef6ce6943a275a1d3e7486f4eae', + [CHAIN.FANTOM]: '0x1231deb6f5749ef6ce6943a275a1d3e7486f4eae', + [CHAIN.MODE]: '0x1231deb6f5749ef6ce6943a275a1d3e7486f4eae', + [CHAIN.SCROLL]: '0x1231deb6f5749ef6ce6943a275a1d3e7486f4eae', + [CHAIN.ZKSYNC]: '0x1231deb6f5749ef6ce6943a275a1d3e7486f4eae', + [CHAIN.METIS]: '0x1231deb6f5749ef6ce6943a275a1d3e7486f4eae', + [CHAIN.XDAI]: '0x1231deb6f5749ef6ce6943a275a1d3e7486f4eae', +} + +const fetch: any = async (timestamp: number, _, { chain, getLogs, createBalances, }: FetchOptions): Promise => { + const dailyVolume = createBalances(); + const data: any[] = await getLogs({ + target: contract[chain], + eventAbi: 'event LiFiTransferStarted(bytes32 indexed transactionId, string bridge, string integrator, address referrer, address sendingAssetId, address receiver, uint256 minAmount, uint256 destinationChainId,bool hasSourceSwaps,bool hasDestinationCall )' + }); + data.forEach((e: any) => { + if (e.integrator === 'sharpe.ai') { + dailyVolume.add(e.sendingAssetId, e.minAmount); + } + }); + + return { dailyBridgeVolume: dailyVolume, timestamp, } as any; +}; + +const adapter: SimpleAdapter = { + version: 2, + adapter: Object.keys(contract).reduce((acc, chain) => { + return { + ...acc, + [chain]: { fetch, start: 1711963031, } + } + }, {}) +}; + +export default adapter; diff --git a/bridge-aggregators/xy-finance/index.ts b/bridge-aggregators/xy-finance/index.ts new file mode 100644 index 0000000000..f1065e18c0 --- /dev/null +++ b/bridge-aggregators/xy-finance/index.ts @@ -0,0 +1,187 @@ +import { Chain } from "@defillama/sdk/build/general"; +import { FetchOptions, FetchResultVolume, SimpleAdapter } from "../../adapters/types"; +import { CHAIN } from "../../helpers/chains"; + +type Contract = { + [c: string | Chain]: { + yBridge: string, + xyRouter: string, + }; +} + +const contract: Contract = { + [CHAIN.ETHEREUM]: { + yBridge: '0x4315f344a905dC21a08189A117eFd6E1fcA37D57', + xyRouter: "0xFfB9faf89165585Ad4b25F81332Ead96986a2681" + }, + [CHAIN.SCROLL]: { + yBridge: "0x778C974568e376146dbC64fF12aD55B2d1c4133f", + xyRouter: "0x22bf2A9fcAab9dc96526097318f459eF74277042" + }, + [CHAIN.MANTLE]: { + yBridge: "0x73Ce60416035B8D7019f6399778c14ccf5C9c7A1", + xyRouter: "0x52075Fd1fF67f03beABCb5AcdA9679b02d98cA37" + }, + [CHAIN.LINEA]: { + yBridge: "0x73Ce60416035B8D7019f6399778c14ccf5C9c7A1", + xyRouter: "0xc693C8AAD9745588e95995fef4570d6DcEF98000" + }, + [CHAIN.BASE]: { + yBridge: "0x73Ce60416035B8D7019f6399778c14ccf5C9c7A1", + xyRouter: "0x6aCd0Ec9405CcB701c57A88849C4F1CD85a3f3ab" + }, + [CHAIN.ARBITRUM]: { + yBridge: "0x33383265290421C704c6b09F4BF27ce574DC4203", + xyRouter: "0x062b1Db694F6A437e3c028FC60dd6feA7444308c" + }, + [CHAIN.ERA]: { + yBridge: "0xe4e156167cc9C7AC4AbD8d39d203a5495F775547", + xyRouter: "0x30E63157bD0bA74C814B786F6eA2ed9549507b46" + }, + [CHAIN.BSC]: { + yBridge: "0x7D26F09d4e2d032Efa0729fC31a4c2Db8a2394b1", + xyRouter: "0xDF921bc47aa6eCdB278f8C259D6a7Fef5702f1A9" + }, + [CHAIN.POLYGON]: { + yBridge: "0x0c988b66EdEf267D04f100A879db86cdb7B9A34F", + xyRouter: "0xa1fB1F1E5382844Ee2D1BD69Ef07D5A6Abcbd388" + }, + [CHAIN.KLAYTN]: { + yBridge: "0x52075Fd1fF67f03beABCb5AcdA9679b02d98cA37", + xyRouter: "0x252eA5AebEB648e7e871DAD7E0aB6cb49096BdD5" + }, + [CHAIN.POLYGON_ZKEVM]: { + yBridge: "0x3689D3B912d4D73FfcAad3a80861e7caF2d4F049", + xyRouter: "0x218Ef86b88765df568E9D7d7Fd34B5Dc88098080" + }, + [CHAIN.AVAX]: { + yBridge: "0x2C86f0FF75673D489b7D72D9986929a2b0Ed596C", + xyRouter: "0xa0c0F962DECD78D7CDE5707895603CBA74C02989" + }, + [CHAIN.OPTIMISM]: { + yBridge: "0x7a6e01880693093abACcF442fcbED9E0435f1030", + xyRouter: "0xF8d342db903F266de73B10a1e46601Bb08a3c195" + }, + [CHAIN.CRONOS]: { + yBridge: "0xF103b5B479d2A629F422C42bb35E7eEceE1ad55E", + xyRouter: "0x5d6e7E537cb4a8858C8B733A2A307B4aAFDc42ca" + }, + [CHAIN.FANTOM]: { + yBridge: "0xDa241399697fa3F6cD496EdAFab6191498Ec37F5", + xyRouter: "0x1E1a70eDb9cd26ccc05F01C66B882cef0E4f7d2D" + }, + [CHAIN.ASTAR]: { + yBridge: "0x5C6C12Fd8b1f7E60E5B60512712cFbE0192E795E", + xyRouter: "0x9c83E6F9E8DA12af8a0Cb8E276b722EB3D7668aF" + }, + [CHAIN.KCC]: { + yBridge: "0x7e803b54295Cd113Bf48E7f069f0531575DA1139", + xyRouter: "0x562afa22b2Fc339fd7Fa03E734E7008C3EccF8CF" + }, + [CHAIN.MOONRIVER]: { + yBridge: "0xc67Dd7054915a2B0aA3e48f35DA714Ff861e71BD", + xyRouter: "0x64d17beaE666cC435B9d40a21f058b379b2a0194" + }, + [CHAIN.THUNDERCORE]: { + yBridge: "0xF103b5B479d2A629F422C42bb35E7eEceE1ad55E", + xyRouter: "0xbF26ca7cf925e9EA0765c737B066253CF80e0E09" + }, + [CHAIN.NUMBERS]: { + yBridge: "", + xyRouter: "0x1acCfC3a45313f8F862BE7fbe9aB25f20A93d598" + }, + [CHAIN.WEMIX]: { + yBridge: "0x73Ce60416035B8D7019f6399778c14ccf5C9c7A1", + xyRouter: "0x6471fAd467ac2854b403e7FE3e95FBbB3287a7ee" + }, + [CHAIN.BLAST]: { + yBridge: "0x73Ce60416035B8D7019f6399778c14ccf5C9c7A1", + xyRouter: "0x43A86823EBBe2ECF9A384aDfD989E26A30626458" + }, + [CHAIN.XLAYER]: { + yBridge: "0x73Ce60416035B8D7019f6399778c14ccf5C9c7A1", + xyRouter: "0x6A816cEE105a9409D8df0A83d8eeaeD9EB4309fE" + }, + [CHAIN.TAIKO]: { + yBridge: "0x73Ce60416035B8D7019f6399778c14ccf5C9c7A1", + xyRouter: "0xedC061306A79257f15108200C5B82ACc874C239d" + }, + [CHAIN.CRONOS_ZKEVM]: { + yBridge: "0xE22747472A565e96D0867741811193895b9538f2", + xyRouter: "0x986138f6ed1350a85De6B18280f7d139F74B7282" + }, +} +const yBridgeContractTopic = '0xb0e9a29a6096a927bd389ba0d0d1a15f82df21a331d23a33eeb7de1cf7ab2684' +const xyRouterContractTopic = '0xcfdc06da1b80f541716b9dc11dba02141fbc401b0d152e9286df44c79b9d4000' +const yBridgeContractEventAbi = 'event SwapRequested(uint256 _swapId, address indexed _aggregatorAdaptor, tuple(uint32 dstChainId, address dstChainToken, address dstAggregatorAdaptor, uint256 expectedDstChainTokenAmount, uint32 slippage) _dstChainDesc, address _srcToken, address indexed _vaultToken, uint256 _vaultTokenAmount, address _receiver, uint256 _srcTokenAmount, uint256 _expressFeeAmount, address indexed _referrer)' +const xyRouterContractEventAbi = `event XYRouterRequested( + uint256 xyRouterRequestId, + address indexed sender, + address srcToken, + uint256 amountIn, + address indexed bridgeAddress, + address bridgeToken, + uint256 bridgeAmount, + uint256 dstChainId, + bytes bridgeAssetReceiver, + tuple( + tuple(bool hasTip, address tipReceiver) tipInfo, + tuple( + bool hasDstChainSwap, + tuple( + tuple(address srcToken, address dstToken, uint256 minReturnAmount, address receiver) swapRequest, + address dexAddress, + address approveToAddress, + bytes dexCalldata + ) swapAction + ) dstChainSwapInfo, + tuple(bool hasIM, address xApp, address refundReceiver, bytes message) imInfo + ) dstChainAction, + address indexed affiliate)` + +const fetch: any = async (timestamp: number, _, { chain, getLogs, createBalances, getFromBlock, getToBlock }: FetchOptions): Promise => { + const dailyVolume = createBalances(); + try { + const yBridgeContract = contract[chain].yBridge; + const xyRouterContract = contract[chain].xyRouter; + + const logPromises: (Promise)[] = []; + if (yBridgeContract) { + logPromises.push(getLogs({ + target: yBridgeContract, + topics: [yBridgeContractTopic], + eventAbi: yBridgeContractEventAbi, + })) + } + if (xyRouterContract) { + logPromises.push(getLogs({ + target: xyRouterContract, + topics: [xyRouterContractTopic], + eventAbi: xyRouterContractEventAbi, + })) + } + const [yBridgeData, xyRouterData] = await Promise.all(logPromises); + yBridgeData?.forEach((e: any) => { + dailyVolume.add(e._vaultToken, e._vaultTokenAmount) + }); + + xyRouterData?.forEach((e: any) => { + dailyVolume.add(e.bridgeToken, e.bridgeAmount); + }); + } catch (error) { + console.error(`XY Finance fetch chain ${chain} error: ${JSON.stringify(error)}`); + } finally { + return { dailyBridgeVolume: dailyVolume , timestamp, } as any; + } +} + +const adapter: SimpleAdapter = { + adapter: Object.keys(contract).reduce((acc, chain) => { + return { + ...acc, + [chain]: { fetch, start: 1691625600, } + } + }, {}) +} + +export default adapter diff --git a/cli/testAdapter.ts b/cli/testAdapter.ts index 28c727649d..083e5f5b69 100644 --- a/cli/testAdapter.ts +++ b/cli/testAdapter.ts @@ -1,11 +1,22 @@ require('dotenv').config() -import * as path from 'path' +import { execSync } from 'child_process'; +import * as path from 'path'; import { Adapter, AdapterType, ChainBlocks, } from '../adapters/types'; -import { checkArguments, ERROR_STRING, formatTimestampAsDate, printVolumes, upperCaseFirst } from './utils'; -import { getUniqStartOfTodayTimestamp } from '../helpers/getUniSubgraphVolume'; -import runAdapter from '../adapters/utils/runAdapter' -import { canGetBlock, getBlock } from '../helpers/getBlock'; import getChainsFromDexAdapter from '../adapters/utils/getChainsFromDexAdapter'; +import runAdapter from '../adapters/utils/runAdapter'; +import { canGetBlock, getBlock } from '../helpers/getBlock'; +import { getUniqStartOfTodayTimestamp } from '../helpers/getUniSubgraphVolume'; +import { checkArguments, printVolumes } from './utils'; + +function checkIfFileExistsInMasterBranch(_filePath: any) { + const res = execSync(`git ls-tree --name-only -r master`) + + // const resString = res.toString() + // if (!resString.includes(filePath)) { + // console.log("\n\n\nERROR: Use Adapter v2 format for new adapters\n\n\n") + // process.exit(1) + // } +} // tmp const handleError = (e: Error) => console.error(e) @@ -18,26 +29,33 @@ process.on('uncaughtException', handleError) checkArguments(process.argv) function getTimestamp30MinutesAgo() { - return Math.trunc(Date.now() / 1000) - 60 * 30 + return Math.trunc(Date.now() / 1000) - 60 * 60 * 2.5 } // Get path of module import const adapterType: AdapterType = process.argv[2] as AdapterType +const file = `${adapterType}/${process.argv[3]}` + const passedFile = path.resolve(process.cwd(), `./${adapterType}/${process.argv[3]}`); (async () => { - const cleanDayTimestamp = process.argv[4] ? getUniqStartOfTodayTimestamp(new Date(+process.argv[4] * 1000 + 60 * 60 * 24 * 1000)) : getUniqStartOfTodayTimestamp(new Date()) - let endCleanDayTimestamp = cleanDayTimestamp - 1 + + const cleanDayTimestamp = process.argv[4] ? Number(process.argv[4]) : getUniqStartOfTodayTimestamp(new Date()) + let endCleanDayTimestamp = cleanDayTimestamp; console.info(`🦙 Running ${process.argv[3].toUpperCase()} adapter 🦙`) - console.info(`_______________________________________`) + console.info(`---------------------------------------------------`) // Import module to test let module: Adapter = (await import(passedFile)).default const adapterVersion = module.version - let timestamp = endCleanDayTimestamp + let endTimestamp = endCleanDayTimestamp if (adapterVersion === 2) { - timestamp = process.argv[4] ? +process.argv[4] : getTimestamp30MinutesAgo() + endTimestamp = (process.argv[4] ? Number(process.argv[4]) : getTimestamp30MinutesAgo()) // 1 day; + } else { + checkIfFileExistsInMasterBranch(file) } - console.info(`${upperCaseFirst(adapterType)} for ${formatTimestampAsDate(String(getUniqStartOfTodayTimestamp(new Date(timestamp * 1000))))}`) - console.info(`_______________________________________\n`) + + console.info(`Start Date:\t${new Date((endTimestamp - 3600*24)*1e3).toUTCString()}`) + console.info(`End Date:\t${new Date(endTimestamp*1e3).toUTCString()}`) + console.info(`---------------------------------------------------\n`) // Get closest block to clean day. Only for EVM compatible ones. const allChains = getChainsFromDexAdapter(module).filter(canGetBlock) @@ -45,7 +63,7 @@ const passedFile = path.resolve(process.cwd(), `./${adapterType}/${process.argv[ const chainBlocks: ChainBlocks = {}; await Promise.all(allChains.map(async (chain) => { try { - const latestBlock = await getBlock(timestamp, chain, chainBlocks).catch((e: any) => console.error(`${e.message}; ${timestamp}, ${chain}`)) + const latestBlock = await getBlock(endTimestamp, chain, chainBlocks).catch((e: any) => console.error(`${e.message}; ${endTimestamp}, ${chain}`)) if (latestBlock) chainBlocks[chain] = latestBlock } catch (e) { console.log(e) } @@ -54,7 +72,7 @@ const passedFile = path.resolve(process.cwd(), `./${adapterType}/${process.argv[ if ("adapter" in module) { const adapter = module.adapter // Get adapter - const volumes = await runAdapter(adapter, timestamp, chainBlocks, undefined, undefined, { + const volumes = await runAdapter(adapter, endTimestamp, chainBlocks, undefined, undefined, { adapterVersion, }) printVolumes(volumes, adapter) @@ -62,8 +80,9 @@ const passedFile = path.resolve(process.cwd(), `./${adapterType}/${process.argv[ } else if ("breakdown" in module) { const breakdownAdapter = module.breakdown const allVolumes = await Promise.all(Object.entries(breakdownAdapter).map(([version, adapter]) => - runAdapter(adapter, timestamp, chainBlocks, undefined, undefined, { + runAdapter(adapter, endTimestamp, chainBlocks, undefined, undefined, { adapterVersion, + isTest: true, }).then(res => ({ version, res })) )) allVolumes.forEach(({ version, res }) => { @@ -73,4 +92,4 @@ const passedFile = path.resolve(process.cwd(), `./${adapterType}/${process.argv[ }) } else throw new Error("No compatible adapter found") process.exit(0) -})() \ No newline at end of file +})() diff --git a/cli/utils.ts b/cli/utils.ts index 95feec5748..a6aa457e90 100644 --- a/cli/utils.ts +++ b/cli/utils.ts @@ -1,5 +1,5 @@ import { getLatestBlock } from "@defillama/sdk/build/util"; -import { BaseAdapter, } from "../adapters/types"; +import { BaseAdapter, whitelistedDimensionKeys, } from "../adapters/types"; import { humanizeNumber } from "@defillama/sdk/build/computeTVL/humanizeNumber"; export const ERROR_STRING = '------ ERROR ------' @@ -24,6 +24,11 @@ export async function getLatestBlockRetry(chain: string) { export function printVolumes(volumes: any[], baseAdapter?: BaseAdapter) { const exclude2Print = ['startTimestamp', 'chain'] + let keys = volumes.map((element) => Object.keys(element)).flat() + keys.forEach((key) => { + if (!whitelistedDimensionKeys.has(key)) + throw new Error(`"${key}" is not a supported metric.Supported metrics can be found in adapters/types.ts`) + }) volumes.forEach((element) => { const methodology = baseAdapter?.[element.chain].meta?.methodology if (typeof element.chain === 'string') @@ -35,8 +40,8 @@ export function printVolumes(volumes: any[], baseAdapter?: BaseAdapter) { else if (!methodology) console.log("NO METHODOLOGY SPECIFIED") Object.entries(element).forEach(([attribute, value]) => { if (!exclude2Print.includes(attribute)) { - const valueFormatted = typeof value === 'object' ? JSON.stringify(value, null, 2) : attribute === "timestamp" ? value + ` (${new Date((value as any) * 1e3).toISOString()})` : humanizeNumber(Number(value)) - console.info(`${camelCaseToSpaces(attribute)}: ${valueFormatted}`) + const valueFormatted = typeof value === 'object' ? JSON.stringify(value, null, 2) : attribute === "timestamp" ? value + ` (${new Date((value as any) * 1e3).toISOString()})` : humanizeNumber(Number(value)) + console.info(`${camelCaseToSpaces(attribute === "timestamp" ? "endTimestamp" : attribute)}: ${valueFormatted}`) if (valueFormatted !== undefined && typeof methodology === 'object' && methodology[attribute.slice(5)]) console.log("└─ Methodology:", methodology?.[attribute.slice(5)]) } diff --git a/dexs/0x/index.ts b/dexs/0x/index.ts index fbc85ca214..69693deb80 100644 --- a/dexs/0x/index.ts +++ b/dexs/0x/index.ts @@ -12,7 +12,7 @@ const config = { [CHAIN.AVAX]: { exchange: '0xdef1c0ded9bec7f1a1670819833240f027b25eff' }, arbitrum: { exchange: '0xdef1c0ded9bec7f1a1670819833240f027b25eff' }, base: { exchange: '0xdef1c0ded9bec7f1a1670819833240f027b25eff' }, -} +} as {[chain:string]:{exchange:string}} // https://github.com/0xProject/protocol/blob/development/packages/contract-artifacts/artifacts/IZeroEx.json const abi = { diff --git a/dexs/3xcalibur/index.ts b/dexs/3xcalibur/index.ts index 279b09af12..865104b7ae 100644 --- a/dexs/3xcalibur/index.ts +++ b/dexs/3xcalibur/index.ts @@ -1,25 +1,23 @@ +import * as sdk from "@defillama/sdk"; import { SimpleAdapter } from "../../adapters/types"; import { getStartTimestamp } from "../../helpers/getStartTimestamp"; -import { DEFAULT_DAILY_VOLUME_FIELD, DEFAULT_TOTAL_VOLUME_FIELD, getChainVolume } from "../../helpers/getUniSubgraphVolume"; +import { DEFAULT_DAILY_VOLUME_FIELD, DEFAULT_TOTAL_VOLUME_FIELD, getChainVolume2 } from "../../helpers/getUniSubgraphVolume"; import { CHAIN } from "../../helpers/chains"; const endpoints = { - [CHAIN.ARBITRUM]: "https://api.thegraph.com/subgraphs/name/0xleez/xcali-arbitrum", + [CHAIN.ARBITRUM]: sdk.graph.modifyEndpoint('J9xPBr2XdBxWvLi2HSiz8hW76HUU91WQ9ztkicCRccDS'), }; -const graphs = getChainVolume({ +const graphs = getChainVolume2({ graphUrls: endpoints, totalVolume: { factory: "swapFactories", field: DEFAULT_TOTAL_VOLUME_FIELD, }, - dailyVolume: { - factory: "uniswapDayData", - field: DEFAULT_DAILY_VOLUME_FIELD, - }, }); const adapter: SimpleAdapter = { + version: 2, adapter: { [CHAIN.ARBITRUM]: { fetch: graphs(CHAIN.ARBITRUM), diff --git a/dexs/ArbitrumExchange/index.ts b/dexs/ArbitrumExchange/index.ts index 947ae22ea9..e70b32c602 100644 --- a/dexs/ArbitrumExchange/index.ts +++ b/dexs/ArbitrumExchange/index.ts @@ -1,25 +1,23 @@ +import * as sdk from "@defillama/sdk"; import { Chain } from "@defillama/sdk/build/general"; import { BreakdownAdapter, BaseAdapter } from "../../adapters/types"; import { CHAIN } from "../../helpers/chains"; import { getStartTimestamp } from "../../helpers/getStartTimestamp"; import { - getGraphDimensions, - DEFAULT_DAILY_VOLUME_FACTORY, + getGraphDimensions2, DEFAULT_TOTAL_VOLUME_FIELD, } from "../../helpers/getUniSubgraph" const v2Endpoints = { - [CHAIN.ARBITRUM]: "https://api.thegraph.com/subgraphs/name/hekman-eth/arbidex", + [CHAIN.ARBITRUM]: sdk.graph.modifyEndpoint('DsZsQrDp7VswGGm6PburYZ91AM3E9vwH45nwLCj3kXHA'), }; const v3Endpoints = { - [CHAIN.ARBITRUM]: "https://api.thegraph.com/subgraphs/name/hekman-eth/arbidex-v3", + [CHAIN.ARBITRUM]: sdk.graph.modifyEndpoint('AQPMJVpukYUo96WvuKqn7aPZn3m8BHckYs82ZLSMKyeu'), }; -const VOLUME_USD = "volumeUSD"; - -const v2Graph = getGraphDimensions({ +const v2Graph = getGraphDimensions2({ graphUrls: v2Endpoints, feesPercent: { type: "volume", @@ -32,16 +30,12 @@ const v2Graph = getGraphDimensions({ } }); -const v3Graphs = getGraphDimensions({ +const v3Graphs = getGraphDimensions2({ graphUrls: v3Endpoints, totalVolume: { factory: "factories", field: DEFAULT_TOTAL_VOLUME_FIELD, }, - dailyVolume: { - factory: DEFAULT_DAILY_VOLUME_FACTORY, - field: VOLUME_USD, - }, feesPercent: { type: "fees", ProtocolRevenue: 0, @@ -66,6 +60,7 @@ const startTimeV3:TStartTime = { [CHAIN.ARBITRUM]: 1683590400, } const adapter: BreakdownAdapter = { + version: 2, breakdown: { v2: { [CHAIN.ARBITRUM]: { diff --git a/dexs/DerpDEX/index.ts b/dexs/DerpDEX/index.ts index 69d4718321..29d3e98e30 100644 --- a/dexs/DerpDEX/index.ts +++ b/dexs/DerpDEX/index.ts @@ -1,53 +1,45 @@ +import * as sdk from "@defillama/sdk"; import { Adapter } from "../../adapters/types"; import { CHAIN } from "../../helpers/chains"; -import { getGraphDimensions } from "../../helpers/getUniSubgraph"; +import { getGraphDimensions2 } from "../../helpers/getUniSubgraph"; const endpoints = { - [CHAIN.ERA]: "https://api.studio.thegraph.com/query/49147/derpdex-v3-amm/v0.0.10", - [CHAIN.BASE]: "https://api.thegraph.com/subgraphs/name/geckocoding/derpdex-amm-base", - [CHAIN.OP_BNB]: "https://opbnb.subgraph.derpdex.com/subgraphs/name/geckocoding/derpdex-opbnb" + [CHAIN.ERA]: + "https://api.studio.thegraph.com/query/49147/derpdex-v3-amm/v0.0.10", + [CHAIN.BASE]: + sdk.graph.modifyEndpoint('6WLn1VLCtCYHNMPLT3AfKCCrKrq91qs1wCFcULWQUX96'), + // [CHAIN.OP_BNB]: + // "https://opbnb.subgraph.derpdex.com/subgraphs/name/geckocoding/derpdex-opbnb", +}; +const v3StartTimes = { + [CHAIN.ERA]: 1688515200, + [CHAIN.BASE]: 1692296100, + // [CHAIN.OP_BNB]: 1695275237, }; -const v3Graphs = getGraphDimensions({ +const v3Graphs = getGraphDimensions2({ graphUrls: endpoints, totalVolume: { factory: "factories", field: "totalVolumeUSD", }, - dailyVolume: { - factory: "uniswapDayData", - field: "volumeUSD", - dateField: "date" - }, - dailyFees: { - factory: "uniswapDayData", - field: "feesUSD", - }, feesPercent: { type: "fees", ProtocolRevenue: 0, HoldersRevenue: 0, UserFees: 100, // User fees are 0% of collected fees SupplySideRevenue: 100, // 100% of fees are going to LPs - Revenue: 0 // Revenue is 0% of collected fees - } + Revenue: 0, // Revenue is 0% of collected fees + }, }); -const adapter: Adapter = { - adapter: { - [CHAIN.ERA]: { - fetch: v3Graphs(CHAIN.ERA), - start: 1688515200 - }, - [CHAIN.BASE]: { - fetch: v3Graphs(CHAIN.BASE), - start: 1692296100 - }, - [CHAIN.OP_BNB]: { - fetch: v3Graphs(CHAIN.OP_BNB), - start: 1695275237 - } - } -}; +const adapter: Adapter = { adapter: {}, version: 2 }; + +Object.keys(endpoints).map((chain: string) => { + adapter.adapter[chain] = { + fetch: v3Graphs(chain), + start: v3StartTimes[chain], + }; +}); export default adapter; diff --git a/dexs/FeeFree/index.ts b/dexs/FeeFree/index.ts new file mode 100644 index 0000000000..8450fd6ac9 --- /dev/null +++ b/dexs/FeeFree/index.ts @@ -0,0 +1,92 @@ +import { FetchOptions, FetchV2, SimpleAdapter } from "../../adapters/types"; +import { CHAIN } from "../../helpers/chains"; +import { addOneToken } from "../../helpers/prices"; + +const INITIALIZE_EVENT_ABI = 'event Initialize(bytes32 id, address indexed currency0, address indexed currency1, uint24 fee, int24 tickSpacing, address hooks)'; +const SWAP_EVENT_ABI = "event Swap(bytes32 indexed id, address sender, int128 amount0, int128 amount1, uint160 sqrtPriceX96, uint128 liquidity, int24 tick, uint24 fee)"; + +const CONFIG = { + [CHAIN.ZORA]: { + pool: "0xB43287b2106BC044F07aE674794f5492E851d3dC", + router: "0x0Fee97363deEFBE4De038D437D805A98dbEbA400", + fromBlock: 13704184, + swapFee: 10000000000000n, + }, + [CHAIN.BASE]: { + pool: "0xc08304a5300D9a2310A603b8D7fB8470f752947F", + router: "0x0Fee76f15DE74A5211e5Bc2aBF95394d7f50C400", + fromBlock: 14089843, + swapFee: 10000000000000n, + }, +}; + +type Pair = { + id: string, + currency0: string; + currency1: string; +}; + +const getTokenPairs = async (options: FetchOptions): Promise<{[id:string]: Pair}> => { + const config = CONFIG[options.chain]; + + const logs = await options.api.getLogs({ + target: config.pool, + eventAbi: INITIALIZE_EVENT_ABI, + fromBlock: config.fromBlock, + toBlock: options.api.block, + onlyArgs: true, + }); + + const pairs = logs.map(log => { + const [id, currency0, currency1] = log + return { id, currency0, currency1 } + }); + + return Object.fromEntries(pairs.map((pair) => [pair.id, pair])); +} + +const fetchVolume: FetchV2 = async (options: FetchOptions) => { + const dailyVolume = options.createBalances(); + const dailyFees = options.createBalances(); + const pairs = await getTokenPairs(options); + + const config = CONFIG[options.chain]; + const logs = await options.getLogs({ + target: config.pool, + eventAbi: SWAP_EVENT_ABI, + }); + logs.forEach((log: any) => { + const [id,,amount0, amount1] = log; + const pair = pairs[id]; + addOneToken({ + balances: dailyVolume, + chain: options.chain, + token0: pair.currency0, + token1: pair.currency1, + amount0, + amount1, + }); + }); + dailyFees.addGasToken(config.swapFee * BigInt(logs.length)); + + return { + dailyVolume, + dailyFees, + } +} + +const adapter: SimpleAdapter = { + version: 2, + adapter: { + [CHAIN.ZORA]: { + fetch: fetchVolume, + start: 1714060800, + }, + [CHAIN.BASE]: { + fetch: fetchVolume, + start: 1714939200, + }, + } +} + +export default adapter; diff --git a/dexs/ICDex/index.ts b/dexs/ICDex/index.ts index 9d78b135b0..cf667a707e 100644 --- a/dexs/ICDex/index.ts +++ b/dexs/ICDex/index.ts @@ -13,7 +13,7 @@ const fetch = async (timestamp: number): Promise => { } return { dailyVolume: `${dailyVolume}`, - totalVolume: `${totalVolume}`, + // totalVolume: `${totalVolume}`, timestamp } }; diff --git a/dexs/MantisSwap/index.ts b/dexs/MantisSwap/index.ts index 4ccb415fef..187a707724 100644 --- a/dexs/MantisSwap/index.ts +++ b/dexs/MantisSwap/index.ts @@ -10,10 +10,8 @@ type PoolData = { const fetch = (chain: string) => async (timestamp: number) => { const from = timestamp - 86400; // 60*60*24 const to = timestamp; - const stats: PoolData = ( - await fetchURL( - `https://api.mantissa.finance/api/pool/stats/volume/${chain}/?from_timestamp=${from}&to_timestamp=${to}` - ) + const stats: PoolData = await fetchURL( + `https://api.mantissa.finance/api/pool/stats/volume/${chain}/?from_timestamp=${from}&to_timestamp=${to}` ); return { totalVolume: `${stats.total_volume}`, @@ -32,6 +30,10 @@ const adapter: SimpleAdapter = { fetch: fetch("1101"), start: 1685355566, }, + [CHAIN.MODE]: { + fetch: fetch("34443"), + start: 1709717650, + }, }, }; diff --git a/dexs/Omnidrome/index.ts b/dexs/Omnidrome/index.ts index b5f1216ff7..622c264c26 100644 --- a/dexs/Omnidrome/index.ts +++ b/dexs/Omnidrome/index.ts @@ -1,63 +1,13 @@ -import { FetchOptions, FetchResultVolume, SimpleAdapter } from "../../adapters/types" +import { DISABLED_ADAPTER_KEY, SimpleAdapter } from "../../adapters/types" import { CHAIN } from "../../helpers/chains" +import disabledAdapter from "../../helpers/disabledAdapter"; -const lphelper = '0x1f176AABA9c6e2014455E5C199afD15A70f9e34e'; -const abis: any = { - "forSwaps": "function forSwaps(uint256 _limit, uint256 _offset) view returns ((address lp, bool stable, address token0, address token1, address factory, uint256 poolFee)[])" -} - -interface IForSwap { - lp: string; - token0: string; - token1: string; -} - -interface ILog { - address: string; - data: string; - transactionHash: string; - topics: string[]; -} -const event_swap = 'event Swap(address indexed sender,address indexed to,uint256 amount0In,uint256 amount1In,uint256 amount0Out,uint256 amount1Out)' - -const fetch = async (timestamp: number, _: any, { api, getLogs, createBalances, }: FetchOptions): Promise => { - const dailyVolume = createBalances() - const forSwaps: IForSwap[] = (await api.call({ - target: lphelper, - params: [1000, 0], - abi: abis.forSwaps, - chain: CHAIN.ZETA, - })).map((e: any) => { - return { - lp: e.lp, - token0: e.token0, - token1: e.token1, - } - }) - - const targets = forSwaps.map((forSwap: IForSwap) => forSwap.lp) - - const logs: ILog[][] = await getLogs({ - targets, - eventAbi: event_swap, - flatten: false, - }) - - logs.forEach((logs: ILog[], idx: number) => { - const { token0, token1 } = forSwaps[idx] - logs.forEach((log: any) => { - dailyVolume.add(token0, log.amount0Out) - dailyVolume.add(token1, log.amount1Out) - }) - }) - - return { dailyVolume, timestamp } -} const adapters: SimpleAdapter = { adapter: { + [DISABLED_ADAPTER_KEY]: disabledAdapter, [CHAIN.ZETA]: { - fetch: fetch as any, + fetch: async (timestamp: number) => {return {timestamp, dailyVolume: '0'}}, start: 1707177600, } } diff --git a/dexs/Scale/index.ts b/dexs/Scale/index.ts index 7a2b448177..fe9c77420a 100644 --- a/dexs/Scale/index.ts +++ b/dexs/Scale/index.ts @@ -1,16 +1,6 @@ -import { SimpleAdapter } from "../../adapters/types"; import { CHAIN } from "../../helpers/chains"; -import { getDexVolumeExports } from "../../helpers/dexVolumeLogs"; +import { uniV2Exports } from "../../helpers/uniswap"; -const FACTORY_ADDRESS = '0xEd8db60aCc29e14bC867a497D94ca6e3CeB5eC04'; - -const adapter: SimpleAdapter = { - adapter: { - [CHAIN.BASE]: { - fetch: getDexVolumeExports({ chain: CHAIN.BASE, factory: FACTORY_ADDRESS }), - start: 1695458888, - }, - } -}; - -export default adapter; +export default uniV2Exports({ + [CHAIN.BASE]: { factory: '0xEd8db60aCc29e14bC867a497D94ca6e3CeB5eC04', }, +}) diff --git a/dexs/SmarDex/index.ts b/dexs/SmarDex/index.ts index fe070ffdc6..d1c88910cc 100644 --- a/dexs/SmarDex/index.ts +++ b/dexs/SmarDex/index.ts @@ -1,8 +1,7 @@ import { SimpleAdapter } from "../../adapters/types"; import { - DEFAULT_DAILY_VOLUME_FIELD, DEFAULT_TOTAL_VOLUME_FIELD, - getGraphDimensions, + getGraphDimensions2, } from "../../helpers/getUniSubgraph"; import { CHAIN } from "../../helpers/chains"; import { Chain } from "@defillama/sdk/build/general"; @@ -39,48 +38,35 @@ const graphRequestHeaders:IMap = { [CHAIN.POLYGON]: defaultHeaders, }; +const startTimes = { + [CHAIN.ARBITRUM]: 1689582249, + [CHAIN.BASE]: 1691491872, + [CHAIN.BSC]: 1689581494, + [CHAIN.ETHEREUM]: 1678404995, + [CHAIN.POLYGON]: 1689582144, +} + /** * @note We are using this method that allow us to use http headers * The method `getGraphDimensions` try returns daily fees and total fees * but we are currently not using them in our subgraphs, so they are undefined */ -const graphs = getGraphDimensions({ +const graphs = getGraphDimensions2({ graphUrls, graphRequestHeaders, totalVolume: { factory: "smardexFactories", field: DEFAULT_TOTAL_VOLUME_FIELD, }, - dailyVolume: { - factory: "factoryDayData", - field: DEFAULT_DAILY_VOLUME_FIELD, - dateField: "date", - }, }); -const adapter: SimpleAdapter = { - adapter: { - [CHAIN.ETHEREUM]: { - fetch: graphs(CHAIN.ETHEREUM), - start: 1678404995, // birthBlock timestamp - }, - [CHAIN.BSC]: { - fetch: graphs(CHAIN.BSC), - start: 1689581494, - }, - [CHAIN.POLYGON]: { - fetch: graphs(CHAIN.POLYGON), - start: 1689582144, - }, - [CHAIN.ARBITRUM]: { - fetch: graphs(CHAIN.ARBITRUM), - start: 1689582249, - }, - [CHAIN.BASE]: { - fetch: graphs(CHAIN.BASE), - start: 1691491872, - }, - }, -}; +const adapter: SimpleAdapter = { adapter: {}, version: 2 } + +Object.keys(graphUrls).map((chain: string) => { + adapter.adapter[chain] = { + fetch: graphs(chain), + start: startTimes[chain] + } +}) export default adapter; diff --git a/dexs/SubstanceX/index.ts b/dexs/SubstanceX/index.ts index 96bbefe2ae..6f3ed1002c 100644 --- a/dexs/SubstanceX/index.ts +++ b/dexs/SubstanceX/index.ts @@ -1,3 +1,4 @@ +import * as sdk from "@defillama/sdk"; import { Adapter } from "../../adapters/types"; import { CHAIN } from "../../helpers/chains"; import { request, gql, GraphQLClient } from "graphql-request"; @@ -6,18 +7,21 @@ import { Chain } from "@defillama/sdk/build/general"; const endpoints = { - [CHAIN.ARBITRUM]: "https://api.thegraph.com/subgraphs/name/substanceexchangedevelop/coreprod", + [CHAIN.ARBITRUM]: sdk.graph.modifyEndpoint('HETFHppem3dz1Yjjv53D7K98dm5t5TErgYAMPBFPHVpi'), + [CHAIN.ZETA]: "https://gql-zeta.substancex.io/subgraphs/name/substanceexchangedevelop/zeta" }; const blockNumberGraph = { - [CHAIN.ARBITRUM]: "https://api.thegraph.com/subgraphs/name/ianlapham/arbitrum-one-blocks", + [CHAIN.ARBITRUM]: sdk.graph.modifyEndpoint('64DCU8nq48qdDABnobpDafsg7RF75Rx5soKrHiGA8mqp'), + [CHAIN.ZETA]: "https://gql-zeta.substancex.io/subgraphs/name/substanceexchangedevelop/zeta-blocks" } +const headers = { 'sex-dev': 'ServerDev'} + const graphs = (graphUrls: ChainEndpoints) => { return (chain: Chain) => { return async (timestamp: number) => { - if (chain === CHAIN.ARBITRUM) { // Get blockNumers const blockNumerQuery = gql` { @@ -46,8 +50,12 @@ const graphs = (graphUrls: ChainEndpoints) => { } `; - const blockNumberGraphQLClient = new GraphQLClient(blockNumberGraph[chain]); - const graphQLClient = new GraphQLClient(graphUrls[chain]); + const blockNumberGraphQLClient = new GraphQLClient(blockNumberGraph[chain], { + headers: chain === CHAIN.ZETA ? headers: null, + }); + const graphQLClient = new GraphQLClient(graphUrls[chain], { + headers: chain === CHAIN.ZETA ? headers: null, + }); const blockNumber = ( @@ -103,7 +111,7 @@ const graphs = (graphUrls: ChainEndpoints) => { }; }; }; -}; + const adapter: Adapter = { adapter: { @@ -111,6 +119,10 @@ const adapter: Adapter = { fetch: graphs(endpoints)(CHAIN.ARBITRUM), start: 1700323200, }, + [CHAIN.ZETA]: { + fetch: graphs(endpoints)(CHAIN.ZETA), + start: 2631301, + }, }, }; diff --git a/dexs/Viridian/index.ts b/dexs/Viridian/index.ts new file mode 100644 index 0000000000..72a98ebe47 --- /dev/null +++ b/dexs/Viridian/index.ts @@ -0,0 +1,6 @@ +import { CHAIN } from "../../helpers/chains"; +import { uniV2Exports } from "../../helpers/uniswap"; + +export default uniV2Exports({ + [CHAIN.CORE]: { factory: '0xb54a83cfEc6052E05BB2925097FAff0EC22893F3', }, +}) diff --git a/dexs/aark/index.ts b/dexs/aark/index.ts index d564fa2873..84663e396b 100644 --- a/dexs/aark/index.ts +++ b/dexs/aark/index.ts @@ -3,7 +3,7 @@ import { CHAIN } from "../../helpers/chains"; import { getUniqStartOfTodayTimestamp } from "../../helpers/getUniSubgraphVolume"; import fetchURL from "../../utils/fetchURL"; -const endpoint = "https://api.aark.digital/stats/volume/futures"; +const endpoint = "https://public-api.aark.digital/stats/volume/futures"; const fetch = async (timestamp: number) => { const dayTimestamp = getUniqStartOfTodayTimestamp(new Date(timestamp * 1000)); diff --git a/dexs/abcdefx/index.ts b/dexs/abcdefx/index.ts index 464a0e4ddb..7c15aaaa58 100644 --- a/dexs/abcdefx/index.ts +++ b/dexs/abcdefx/index.ts @@ -1,22 +1,11 @@ -import { SimpleAdapter } from "../../adapters/types"; import { CHAIN } from "../../helpers/chains"; -import { Chain } from "@defillama/sdk/build/general"; -import { getDexVolumeExports } from "../../helpers/dexVolumeLogs"; +import { uniV2Exports } from "../../helpers/uniswap"; const FACTORY_ADDRESS = '0x01f43d2a7f4554468f77e06757e707150e39130c'; -const graph = (_chain: Chain) => - getDexVolumeExports({ chain: _chain, factory: FACTORY_ADDRESS }) - -const adapter: SimpleAdapter = { - adapter: { - [CHAIN.KCC]: { fetch: graph(CHAIN.KCC), start: 1670188701 }, - //[CHAIN.MULTIVAC]: { fetch: graph(CHAIN.MULTIVAC), start: 1670226950 }, /// ! typeof CHAIN - [CHAIN.FANTOM]: { fetch: graph(CHAIN.FANTOM), start: 1671580916 }, - //[CHAIN.ECHELON]: { fetch: graph(CHAIN.ECHELON), start: 1671608400 }, /// ded!? - [CHAIN.KAVA]: { fetch: graph(CHAIN.KAVA), start: 1676855943 } - } -}; - -export default adapter; \ No newline at end of file +export default uniV2Exports({ + [CHAIN.FANTOM]: { factory: FACTORY_ADDRESS, }, + [CHAIN.KCC]: { factory: FACTORY_ADDRESS, }, + [CHAIN.KAVA]: { factory: FACTORY_ADDRESS, }, +}) diff --git a/dexs/aerodrome-slipstream/index.ts b/dexs/aerodrome-slipstream/index.ts new file mode 100644 index 0000000000..91ec0708fa --- /dev/null +++ b/dexs/aerodrome-slipstream/index.ts @@ -0,0 +1,52 @@ +import { FetchOptions, FetchResult, SimpleAdapter } from "../../adapters/types" +import { CHAIN } from "../../helpers/chains" +import { addOneToken } from "../../helpers/prices"; +import { filterPools2 } from "../../helpers/uniswap"; + +interface ILog { + address: string; + data: string; + transactionHash: string; + topics: string[]; +} +const event_swap = 'event Swap(address indexed sender, address indexed recipient, int256 amount0, int256 amount1, uint160 sqrtPriceX96, uint128 liquidity, int24 tick)' + +const fetch = async (fetchOptions: FetchOptions): Promise => { + const { api, getLogs, createBalances, } = fetchOptions + const chain = api.chain + const dailyVolume = createBalances() + const dailyFees = createBalances() + let pairs = await api.fetchList({ lengthAbi: 'allPoolsLength', itemAbi: 'allPools', target: '0x5e7BB104d84c7CB9B682AaC2F3d509f5F406809A' }) + let token0s = await api.multiCall({ abi: 'address:token0', calls: pairs }) + let token1s = await api.multiCall({ abi: 'address:token1', calls: pairs }) + const res = await filterPools2({ fetchOptions, pairs, token0s, token1s }) + api.log(res.pairs.length, 'pairs out of', pairs.length, chain, 'aerodrome') + pairs = res.pairs + token0s = res.token0s + token1s = res.token1s + const fees = await api.multiCall({ abi: 'uint256:fee', calls: pairs }) + + let logs: ILog[][] = await getLogs({ targets: pairs, eventAbi: event_swap, flatten: false, }) + logs.forEach((logs: ILog[], idx: number) => { + const token0 = token0s[idx] + const token1 = token1s[idx] + const fee = fees[idx]/1e6 + logs.forEach((log: any) => { + addOneToken({ chain, balances: dailyVolume, token0, token1, amount0: log.amount0, amount1: log.amount1 }) + addOneToken({ chain, balances: dailyFees, token0, token1, amount0: Number(log.amount0) * fee, amount1: Number(log.amount1) * fee }) + }) + }) + + return { dailyVolume, dailyFees, dailyRevenue: dailyFees, dailyHoldersRevenue: dailyFees } as any +} + +const adapters: SimpleAdapter = { + version: 2, + adapter: { + [CHAIN.BASE]: { + fetch: fetch as any, + start: 1714743000, + } + } +} +export default adapters; diff --git a/dexs/aerodrome/index.ts b/dexs/aerodrome/index.ts index 6d271e322b..0c866acda6 100644 --- a/dexs/aerodrome/index.ts +++ b/dexs/aerodrome/index.ts @@ -1,63 +1,8 @@ -import { FetchOptions, FetchResultVolume, SimpleAdapter } from "../../adapters/types" import { CHAIN } from "../../helpers/chains" +import { uniV2Exports } from "../../helpers/uniswap"; -const gurar = '0x2073D8035bB2b0F2e85aAF5a8732C6f397F9ff9b'; -const abis: any = { - "forSwaps": "function forSwaps() view returns ((address lp, bool stable, address token0, address token1, address factory)[])" -} +const swapEvent = 'event Swap(address indexed sender, address indexed to, uint256 amount0In, uint256 amount1In, uint256 amount0Out, uint256 amount1Out)' -interface IForSwap { - lp: string; - token0: string; - token1: string; -} - -interface ILog { - address: string; - data: string; - transactionHash: string; - topics: string[]; -} -const event_swap = 'event Swap(address indexed sender,address indexed to,uint256 amount0In,uint256 amount1In,uint256 amount0Out,uint256 amount1Out)' - -const fetch = async (timestamp: number, _: any, { api, getLogs, createBalances, }: FetchOptions): Promise => { - const dailyVolume = createBalances() - const forSwaps: IForSwap[] = (await api.call({ - target: gurar, - abi: abis.forSwaps, - chain: CHAIN.BASE, - })).map((e: any) => { - return { - lp: e.lp, - token0: e.token0, - token1: e.token1, - } - }) - - const targets = forSwaps.map((forSwap: IForSwap) => forSwap.lp) - - const logs: ILog[][] = await getLogs({ - targets, - eventAbi: event_swap, - flatten: false, - }) - - logs.forEach((logs: ILog[], idx: number) => { - const { token0, token1 } = forSwaps[idx] - logs.forEach((log: any) => { - dailyVolume.add(token0, log.amount0Out) - dailyVolume.add(token1, log.amount1Out) - }) - }) - - return { dailyVolume, timestamp } -} -const adapters: SimpleAdapter = { - adapter: { - [CHAIN.BASE]: { - fetch: fetch as any, - start: 1693180800, - } - } -} -export default adapters; +export default uniV2Exports({ + [CHAIN.BASE]: { factory: '0x420DD381b31aEf6683db6B902084cB0FFECe40Da', swapEvent, }, +}) diff --git a/dexs/agni-fi/index.ts b/dexs/agni-fi/index.ts index 9fbfa25c80..66e31d4ad3 100644 --- a/dexs/agni-fi/index.ts +++ b/dexs/agni-fi/index.ts @@ -1,27 +1,17 @@ import { SimpleAdapter } from "../../adapters/types"; import { CHAIN } from "../../helpers/chains"; -import { DEFAULT_TOTAL_VOLUME_FIELD, getGraphDimensions } from "../../helpers/getUniSubgraph"; +import { DEFAULT_TOTAL_VOLUME_FIELD, getGraphDimensions2 } from "../../helpers/getUniSubgraph"; const v3Endpoints = { [CHAIN.MANTLE]: "https://agni.finance/graph/subgraphs/name/agni/exchange-v3" } -const VOLUME_USD = "volumeUSD"; - -const v3Graphs = getGraphDimensions({ +const v3Graphs = getGraphDimensions2({ graphUrls: v3Endpoints, totalVolume: { factory: "factories", field: DEFAULT_TOTAL_VOLUME_FIELD, }, - dailyVolume: { - factory: "pancakeDayData", - field: VOLUME_USD, - }, - dailyFees: { - factory: "pancakeDayData", - field: "feesUSD", - }, feesPercent: { type: "fees", ProtocolRevenue: 0, @@ -34,6 +24,7 @@ const v3Graphs = getGraphDimensions({ }); const adapter: SimpleAdapter = { + version: 2, adapter: { [CHAIN.MANTLE]: { fetch: v3Graphs(CHAIN.MANTLE), diff --git a/dexs/aktionariat/index.ts b/dexs/aktionariat/index.ts new file mode 100644 index 0000000000..a652aa3a92 --- /dev/null +++ b/dexs/aktionariat/index.ts @@ -0,0 +1,21 @@ +import * as sdk from "@defillama/sdk"; +import { CHAIN } from "../../helpers/chains"; +import { univ2Adapter } from "../../helpers/getUniSubgraphVolume"; + +const adapters = univ2Adapter({ + [CHAIN.ETHEREUM]: sdk.graph.modifyEndpoint('2ZoJCp4S7YP7gbYN2ndsYNjPeZBV1PMti7BBoPRRscNq'), + [CHAIN.OPTIMISM]: sdk.graph.modifyEndpoint('3QfEXbPfP23o3AUzcmjTfRtUUd4bfrFj3cJ4jET57CTX'), + [CHAIN.POLYGON]: sdk.graph.modifyEndpoint('7camBLZckE5TLKha372tqawpDs8Lkez6yYiri7PykRak'), +}, { + factoriesName: "registries", + totalVolume: "totalVolumeUSD", + dayData: "aktionariatDayDatas", + dailyVolume: "volumeUSD", + dailyVolumeTimestampField: "date" +}); + +adapters.adapter.ethereum.start = 14830096; +adapters.adapter.optimism.start = 4198027; +adapters.adapter.polygon.start = 58116009; + +export default adapters; \ No newline at end of file diff --git a/dexs/alienfi/index.ts b/dexs/alienfi/index.ts index 86814554a7..2f95fcdea7 100644 --- a/dexs/alienfi/index.ts +++ b/dexs/alienfi/index.ts @@ -1,8 +1,9 @@ +import * as sdk from "@defillama/sdk"; import { univ2Adapter } from "../../helpers/getUniSubgraphVolume"; import { CHAIN } from "../../helpers/chains"; const endpoints = { - [CHAIN.ARBITRUM]: "https://api.thegraph.com/subgraphs/name/spearminttechnolgies/alien-exchange-test", + [CHAIN.ARBITRUM]: sdk.graph.modifyEndpoint('E6A4mHKkMhiNeoiwDU8PME7btMt6xGGSHAZR6ccJsLJe'), }; const adapter = univ2Adapter(endpoints, { diff --git a/dexs/ambient/index.ts b/dexs/ambient/index.ts index 5ca77bdce0..f5c063634f 100644 --- a/dexs/ambient/index.ts +++ b/dexs/ambient/index.ts @@ -1,84 +1,51 @@ -import { Adapter, ChainBlocks, FetchOptions, FetchResultVolume } from "../../adapters/types"; +import PromisePool from "@supercharge/promise-pool"; +import { FetchV2 } from "../../adapters/types"; import { CHAIN } from "../../helpers/chains"; -import { Chain } from "@defillama/sdk/build/general"; -import { request, } from "graphql-request"; - -type TEndpoint = { - [s: Chain | string]: string; -} -const endpoints: TEndpoint = { - [CHAIN.ETHEREUM]: "https://api.thegraph.com/subgraphs/name/crocswap/croc-mainnet", -} -interface IPool { - quote: string; -} -interface ISwap { - quoteFlow: string; - pool: IPool; - dex: string; -} - -const toPositive = (n: any) => +n > 0 ? +n : n * -1 - -const graphs = (chain: Chain) => { - return async (timestamp: number, _: ChainBlocks, { fromTimestamp, toTimestamp, createBalances, }: FetchOptions): Promise => { - const query = ` - { - swaps(where: { - time_gte: ${fromTimestamp} - time_lte: ${toTimestamp} - dex: "croc" - }, orderBy:time, orderDirection: desc) { - quoteFlow - pool { - quote - } - dex - } - } - ` - const graphRes: ISwap[] = (await request(endpoints[chain], query)).swaps; - const dailyVolume = createBalances() - graphRes.map((e: ISwap) => { - dailyVolume.add(e.pool.quote, toPositive(e.quoteFlow)) +import { httpGet } from "../../utils/fetchURL"; + +const config = { + scroll: { endpoint: 'https://ambindexer.net/scroll-gcgo/', chainId: '0x82750', poolIdx: '420' }, + blast: { endpoint: 'https://ambindexer.net/blast-gcgo/', chainId: '0x13e31', poolIdx: '420' }, + ethereum: { endpoint: 'https://ambindexer.net/gcgo/', chainId: '0x1', poolIdx: '420' }, + canto: { endpoint: 'https://ambient-graphcache.fly.dev/gcgo/', chainId: '0x1e14', poolIdx: '420' }, +} + +const fetch: FetchV2 = async ({ startTimestamp, endTimestamp, createBalances, chain }) => { + const dailyVolume = createBalances() + const dailyFees = createBalances() + const { poolIdx, chainId, endpoint, } = config[chain] + const { data } = await httpGet(endpoint + 'pool_list', { params: { poolIdx, chainId } }) + + const { errors } = await PromisePool + .withConcurrency(10) + .for(data) + .process(async ({ base, quote }: any) => { + const { data, } = await httpGet(endpoint + 'pool_stats', { params: { poolIdx, chainId, base, quote, histTime: endTimestamp, } }) + const { data: dataOld } = await httpGet(endpoint + 'pool_stats', { params: { poolIdx, chainId, base, quote, histTime: startTimestamp, } }) + + // dailyVolume.add(base, data.baseVolume) + dailyVolume.add(quote, data.quoteVolume) + // dailyVolume.subtractToken(base, dataOld.baseVolume) + dailyVolume.subtractToken(quote, dataOld.quoteVolume) + + // dailyFees.add(base, data.baseVolume * data.feeRate) + dailyFees.add(quote, data.quoteVolume * data.feeRate) + // dailyFees.subtractToken(base, dataOld.baseVolume * data.feeRate) + dailyFees.subtractToken(quote, dataOld.quoteVolume * data.feeRate) }) - return { dailyVolume, timestamp, } - } + if (errors?.length) throw errors + return { dailyVolume, dailyFees, } } -const swapEvent = 'event CrocSwap (address indexed base, address indexed quote, uint256 poolIdx, bool isBuy, bool inBaseQty, uint128 qty, uint16 tip, uint128 limitPrice, uint128 minOut, uint8 reserveFlags, int128 baseFlow, int128 quoteFlow)'; +const adapter = { fetch, start: 1685232000, } -type TContractAddress = { - [s: Chain]: string; -} -interface ILog { - quote: string; - quoteFlow: string; -} -const contract_address: TContractAddress = { - [CHAIN.SCROLL]: '0xaaaaaaaacb71bf2c8cae522ea5fa455571a74106', -} -const fetchVolume = (chain: Chain) => { - return async (timestamp: number, _: ChainBlocks, { getLogs, createBalances, }: FetchOptions): Promise => { - const dailyVolume = createBalances() - const logs: ILog[] = await getLogs({ target: contract_address[chain], eventAbi: swapEvent, }) - logs.forEach((log: ILog) => dailyVolume.add(log.quote, Number(log.quoteFlow) < 0 ? 0 : log.quoteFlow)); - return { dailyVolume, timestamp, } - } -} - -const adapter: Adapter = { +export default { adapter: { - [CHAIN.ETHEREUM]: { - fetch: graphs(CHAIN.ETHEREUM), - start: 1685232000, - }, - [CHAIN.SCROLL]: { - fetch: fetchVolume(CHAIN.SCROLL), - start: 1685232000, - }, - } -} - -export default adapter; + [CHAIN.ETHEREUM]: adapter, + [CHAIN.SCROLL]: adapter, + [CHAIN.CANTO]: adapter, + [CHAIN.BLAST]: adapter, + }, + version: 2, +}; diff --git a/dexs/ampleswap/index.ts b/dexs/ampleswap/index.ts index 2619b7451f..27890e9b0a 100644 --- a/dexs/ampleswap/index.ts +++ b/dexs/ampleswap/index.ts @@ -1,8 +1,9 @@ +import * as sdk from "@defillama/sdk"; import { univ2Adapter } from "../../helpers/getUniSubgraphVolume"; import { CHAIN } from "../../helpers/chains"; const endpoints = { - [CHAIN.BSC]: "https://api.thegraph.com/subgraphs/name/shrinivasmani/ampleswapgraph", + [CHAIN.BSC]: sdk.graph.modifyEndpoint('2MF3GHhPgvCk8ZHBso8uxTkcT97zjmoEPfxkbeH4D7Jb'), }; const adapter = univ2Adapter(endpoints, {}); diff --git a/dexs/anyhedge/index.ts b/dexs/anyhedge/index.ts new file mode 100644 index 0000000000..88be091da0 --- /dev/null +++ b/dexs/anyhedge/index.ts @@ -0,0 +1,79 @@ +import { FetchOptions, SimpleAdapter } from "../../adapters/types"; +import fetchURL from "../../utils/fetchURL"; +import { CHAIN } from "../../helpers/chains"; +import { getTimestampAtStartOfNextDayUTC } from "../../utils/date"; + +const methodology = { + Volume: "Scan the blockchain for AnyHedge input pattern, add up all such inputs BCH value. The daily volume is the volume of all settled contracts for the day. Indexer: https://gitlab.com/0353F40E/anyhedge-stats", + Fees: "N/A", + Revenue: "N/A", +} + +interface IAnyhedgeVolumeResponse { + daily_volume: number; + total_volume: number; +} + +// day formatted as 2011-12-13 +export const anyhedgeVolumeEndpoint = (day: string) => { + // Data & calculation method is fully reproducible, see: + // https://gitlab.com/0353F40E/anyhedge-stats/-/blob/master/readme.md + return "https://gitlab.com/0353F40E/anyhedge-stats/-/raw/master/stats_daily/" + day + ".csv"; +} + +const fetchAnyhedgeVolumeData: Fetch = async (timestamp: number, _: ChainBlocks, options: FetchOptions) => { + const dayString = new Date(timestamp * 1000).toISOString().slice(0,10); + const anyhedgeVolumeData = await getAnyhedgeVolumeData(anyhedgeVolumeEndpoint(dayString)); + + const dailyVolume = options.createBalances(); + const totalVolume = options.createBalances(); + dailyVolume.addCGToken('bitcoin-cash', Number(anyhedgeVolumeData?.daily_volume)); + totalVolume.addCGToken('bitcoin-cash', Number(anyhedgeVolumeData?.total_volume)); + + return { + timestamp, + dailyVolume, + totalVolume, + }; +} + +async function getAnyhedgeVolumeData(endpoint: string): Promise { + try { + let data = await fetchURL(endpoint); + data = parseCSV(data); + const retval: IAnyhedgeVolumeResponse = {} as IAnyhedgeVolumeResponse; + retval.daily_volume = data[0].volume_closed; + retval.total_volume = data[0].volume_closed_cumulative; + return retval; + } catch { + return null; + } +} + +function parseCSV(csvData) { + csvData = csvData.replaceAll('\r', '').split('\n').map(i => i.split(',')) + const headers = csvData.shift() + const retval = csvData.map(row => toObject(headers, row)); + return retval; +} + +function toObject(keys, values) { + const res = {} + keys.forEach((key, i) => { + res[key] = values[i] + }) + return res +} + +const adapter: SimpleAdapter = { + adapter: { + [CHAIN.BITCOIN_CASH]: { + fetch: fetchAnyhedgeVolumeData, + start: 1654787405, + meta: { + methodology + } + }, + }, +}; +export default adapter; diff --git a/dexs/apestore/index.ts b/dexs/apestore/index.ts new file mode 100644 index 0000000000..33f6f52a0f --- /dev/null +++ b/dexs/apestore/index.ts @@ -0,0 +1,49 @@ +import { httpPost } from "../../utils/fetchURL" +import { FetchOptions, FetchResultV2, Adapter } from "../../adapters/types"; + +interface VolumeInfo { + dailyVolume: string; + totalVolume: string; + timeStamp: number; +} + +const adapter: Adapter = { + version: 2, + adapter: { + base: { + fetch: async (options: FetchOptions): Promise => { + const volumeData: VolumeInfo = await httpPost('https://api.ape.store/base/volume', { date: options.startOfDay }, { + headers: { + "Authorization": "92ff54fa-80b7-4f2c-bae1-f862ea7525ae" + }, + }); + + return { + totalVolume: volumeData.totalVolume, + dailyVolume: volumeData.dailyVolume, + timestamp: volumeData.timeStamp, + }; + }, + start: 1712265900, + }, + ethereum: { + fetch: async (options: FetchOptions): Promise => { + const volumeData: VolumeInfo = await httpPost('https://api.ape.store/eth/volume', { date: options.startOfDay }, { + headers: { + "Authorization": "92ff54fa-80b7-4f2c-bae1-f862ea7525ae" + }, + }); + + return { + totalVolume: volumeData.totalVolume, + dailyVolume: volumeData.dailyVolume, + timestamp: volumeData.timeStamp, + }; + }, + start: 1712265900, + } + }, +}; + + +export default adapter; \ No newline at end of file diff --git a/dexs/apeswap/index.ts b/dexs/apeswap/index.ts index 28ba8ff6b7..74b85b7614 100644 --- a/dexs/apeswap/index.ts +++ b/dexs/apeswap/index.ts @@ -1,11 +1,12 @@ +import * as sdk from "@defillama/sdk"; import { CHAIN } from "../../helpers/chains"; import { univ2Adapter } from "../../helpers/getUniSubgraphVolume"; const adapters = univ2Adapter({ - [CHAIN.BSC]: "https://api.thegraph.com/subgraphs/name/apeswapfinance/bsc-dex", - [CHAIN.POLYGON]: "https://api.thegraph.com/subgraphs/name/prof-sd/as-matic-graft", - [CHAIN.ETHEREUM]: "https://api.thegraph.com/subgraphs/name/apeswapfinance/ethereum-dex", - [CHAIN.ARBITRUM]: "https://api.thegraph.com/subgraphs/name/prof-sd/arbitrum-dex" + [CHAIN.BSC]: sdk.graph.modifyEndpoint('GH4Zt29mCApHwMfavNFw5ZdQDH3owc2Wq8DdU4hGPXYe'), + [CHAIN.POLYGON]: sdk.graph.modifyEndpoint('EcLNjgAFADeXVopmhv3HY79fayzXRtK8R9imZNopRBpE'), + [CHAIN.ETHEREUM]: sdk.graph.modifyEndpoint('6J4fEY6pSRsqaqDbHn17HJY1viPzrGc1pjCqBKrrQXPC'), + [CHAIN.ARBITRUM]: sdk.graph.modifyEndpoint('AGyZUDiBcG9GkW9GX6vXPkuTj5kjf1S6aznEks6PVpi') // [CHAIN.TELOS]: "https://telos.apeswapgraphs.com/subgraphs/name/ape-swap/apeswap-graph" }, {}); diff --git a/dexs/apex-omni/index.ts b/dexs/apex-omni/index.ts new file mode 100644 index 0000000000..6bd9264dcf --- /dev/null +++ b/dexs/apex-omni/index.ts @@ -0,0 +1,80 @@ +import fetchURL, { httpGet } from "../../utils/fetchURL"; +import { SimpleAdapter } from "../../adapters/types"; +import { CHAIN } from "../../helpers/chains"; +import { getUniqStartOfTodayTimestamp } from "../../helpers/getUniSubgraphVolume"; + +const historicalVolumeEndpoint = (symbol: string, endTime: number) => `https://omni.apex.exchange/api/v3/klines?end=${endTime}&interval=D&start=1718380800&symbol=${symbol}&limit=10` +const allTiker = (symbol: string) => `https://omni.apex.exchange/api/v3/ticker?symbol=${symbol}` +const getSumbols = async ()=>{ + const res = await fetchURL('https://omni.apex.exchange/api/v3/all-open-tickers') + const symbol = res?.data?.map((i: any)=>i?.ticker_id) + return symbol || [] +} +interface IVolumeall { + id: string; + volume: string; + timestamp: number; + price: string; + volumeUSD: number; +} + +interface IOpenInterest { + id: string; + openInterest: string; + lastPrice: string; +} + +const getVolume = async (timestamp: number) => { + const symbol = [ + 'BTCUSDT', 'ETHUSDT', 'SOLUSDT', + 'TONUSDT', 'NEARUSDT', 'XRPUSDT', + 'ADAUSDT', 'SUIUSDT', 'AVAXUSDT', + 'BCHUSDT', 'LTCUSDT', 'MATICUSDT', + 'ARBUSDT', 'OPUSDT', 'STXUSDT', + 'DOGEUSDT', '1000SHIBUSDT', '1000PEPEUSDT', + '1000BONKUSDT', 'WIFUSDT', 'ORDIUSDT', + 'PEOPLEUSDT', 'WLDUSDT', 'RNDRUSDT', + 'ONDOUSDT', 'LINKUSDT', 'ENSUSDT', + 'UNIUSDT', 'ENAUSDT', 'PENDLEUSDT', + 'LDOUSDT', 'JUPUSDT', 'RONUSDT', + 'FILUSDT', 'ARUSDT', 'ZKUSDT', + 'IOUSDT', 'NOTUSDT', 'ZROUSDT', + 'BLASTUSDT' + ] + + const dayTimestamp = getUniqStartOfTodayTimestamp(new Date(timestamp * 1000)) + const historical: any[] = (await Promise.all(symbol.map((coins: string) => httpGet(historicalVolumeEndpoint(coins, dayTimestamp + 60 * 60 * 24), { timeout: 10000 })))) + .map((e: any) => Object.values(e.data)).flat().flat() + .map((e: any) => { return { timestamp: e.t / 1000, volume: e.v, price: e.c } }); + const openInterestHistorical: IOpenInterest[] = (await Promise.all(symbol.map((coins: string) => httpGet(allTiker(coins), { timeout: 10000 })))) + .map((e: any) => e.data).flat().map((e: any) => { return { id: e.symbol, openInterest: e.openInterest, lastPrice: e.lastPrice } }); + const dailyOpenInterest = openInterestHistorical.reduce((a: number, { openInterest, lastPrice }) => a + Number(openInterest) * Number(lastPrice), 0); + const historicalUSD = historical.map((e: IVolumeall) => { + return { + ...e, + volumeUSD: Number(e.volume) * Number(e.price) + } + }); + const dailyVolume = historicalUSD.filter((e: IVolumeall) => e.timestamp === dayTimestamp) + .reduce((a: number, { volumeUSD }) => a + volumeUSD, 0); + const totalVolume = historicalUSD.filter((e: IVolumeall) => e.timestamp <= dayTimestamp) + .reduce((a: number, { volumeUSD }) => a + volumeUSD, 0); + + return { + totalVolume: `${totalVolume}`, + dailyOpenInterest: `${dailyOpenInterest}`, + dailyVolume: dailyVolume ? `${dailyVolume}` : undefined, + timestamp: dayTimestamp, + }; +}; + +const adapter: SimpleAdapter = { + adapter: { + [CHAIN.ETHEREUM]: { + fetch: getVolume, + start: 1718380800, + } + }, +}; + +export default adapter; diff --git a/dexs/apex/index.ts b/dexs/apex/index.ts index a1f3890cbc..ebedc57580 100644 --- a/dexs/apex/index.ts +++ b/dexs/apex/index.ts @@ -3,7 +3,7 @@ import { SimpleAdapter, Fetch } from "../../adapters/types"; import { CHAIN } from "../../helpers/chains"; import { getUniqStartOfTodayTimestamp } from "../../helpers/getUniSubgraphVolume"; -const historicalVolumeEndpoint = (symbol: string, endTime: number) => `https://pro.apex.exchange/api/v1/klines?end=${endTime}&interval=D&start=1664928000&symbol=${symbol}&limit=100` +const historicalVolumeEndpoint = (symbol: string, endTime: number) => `https://pro.apex.exchange/api/v1/klines?end=${endTime}&interval=D&start=1708732800&symbol=${symbol}&limit=10` const allTiker = (symbol: string) => `https://pro.apex.exchange/api/v1/ticker?symbol=${symbol}` interface IVolumeall { id: string; @@ -12,34 +12,24 @@ interface IVolumeall { price: string; volumeUSD: number; } -const symbol: string[] = ['1000PEPEUSDC', -'APTUSDC', -'ARBUSDC', -'ATOMUSDC', -'AVAXUSDC', -'BCHUSDC', -'BLURUSDC', -'BNBUSDC', -'BTCUSDC', -'BTCUSDT', -'DOGEUSDC', -'DYDXUSDC', -'ETCUSDC', -'ETHUSDC', -'ETHUSDT', -'LBRUSDC', -'LDOUSDC', -'LINKUSDC', -'LTCUSDC', -'MATICUSDC', -'OPUSDC', -'ORDIUSDT', -'SOLUSDC', -'TIAUSDC', -'TONUSDC', -'WLDUSDC', -'XRPUSDC' -] +const symbol: string[] = [...new Set([ + '1000PEPEUSDC', 'APTUSDC', 'ARBUSDC', + 'ATOMUSDC', 'AVAXUSDC', 'BCHUSDC', + 'BLURUSDC', 'BNBUSDC', 'BTCUSDC', + 'BTCUSDT', 'DOGEUSDC', 'DYDXUSDC', + 'ETCUSDC', 'ETHUSDC', 'ETHUSDT', + 'LBRUSDC', 'LDOUSDC', 'LINKUSDC', + 'LTCUSDC', 'MATICUSDC', 'OPUSDC', + 'ORDIUSDT', 'SOLUSDC', 'TIAUSDC', + 'TONUSDC', 'WLDUSDC', 'XRPUSDC', + 'STXUSDT', 'BIGTIMEUSDT', 'MEMEUSDT', + 'PYTHUSDT', 'FETUSDT', 'RNDRUSDT', + 'ICPUSDT', '1000BONKUSDT', 'DOTUSDT', + 'SEIUSDT', 'INJUSDT', 'ENSUSDT', + '1000SATSUSDT', 'PENDLEUSDT', 'GMTUSDT', + 'MANTAUSDT', 'LINKUSDT', 'SOLUSDT', + 'MATICUSDT', 'STRKUSDT', 'SUIUSDT' +])] interface IOpenInterest { id: string; openInterest: string; diff --git a/dexs/apollox/index.ts b/dexs/apollox/index.ts index 85538dde59..ad07efe6d2 100644 --- a/dexs/apollox/index.ts +++ b/dexs/apollox/index.ts @@ -35,16 +35,50 @@ type V1TickerItem = { count: number; }; +type TotalVolumeV1AndV2ForBscItem = { + "openInterestTotal": string + "totalUser": string + "v1TotalVolume": string + "v2TotalVolume": string +} + + +type TotalVolumeItem = { + "alpFeeVOFor24Hour": { + "fee": number + "revenue": number + }, + "allAlpFeeVO": { + "fee": number + "revenue": number + }, + "cumVol": number + } + +const TotalVolumeV1AndV2ForBscAPI = "https://fapi.apollox.finance/fapi/v1/openInterestAndTrader" +const TotalVolumeAPI = "https://www.apollox.finance/bapi/futures/v1/public/future/apx/fee/all" + const v2VolumeAPI = "https://www.apollox.finance/bapi/future/v1/public/future/apx/pair"; const v1VolumeAPI = "https://www.apollox.finance/fapi/v1/ticker/24hr"; +async function sleep (time: number) { + return new Promise((resolve) => setTimeout(() => resolve(), time)) +} +let sleepCount = 0 const fetchV2Volume = async (chain: Chain) => { - const { data = [] } = ( + console.log('fetch ', chain, sleepCount * 2 * 1e3) + // This is very important!!! because our API will throw error when send >=2 requests at the same time. + await sleep(sleepCount++ * 2 * 1e3) + const res = ( await httpGet(v2VolumeAPI, { params: { chain, excludeCake: true } }) - ) as { data: ResponseItem[] } - const dailyVolume = data.reduce((p, c) => p + +c.qutoVol, 0); + ) as { data: ResponseItem[], success: boolean } + if (res.data === null && res.success === false) { + console.log(res, v2VolumeAPI, { chain, excludeCake: true }) + return fetchV2Volume(chain) + } + const dailyVolume = (res.data || []).reduce((p, c) => p + +c.qutoVol, 0); return dailyVolume }; @@ -56,47 +90,81 @@ const fetchV1Volume = async () => { return dailyVolume }; +const fetchTotalVolumeV1AndV2ForBSC = async () => { + const data = ( + await httpGet(TotalVolumeV1AndV2ForBscAPI) + ) as TotalVolumeV1AndV2ForBscItem + return { v1: Number(data.v1TotalVolume), v2: Number(data.v2TotalVolume) } +}; + +const fetchTotalV2Volume = async (chain: Chain) => { + const { data } = ( + await httpGet(TotalVolumeAPI, { params: { chain, } }) + ) as { data: TotalVolumeItem } + + return Number(data.cumVol) +}; + const adapter: SimpleAdapter = { adapter: { [CHAIN.BSC]: { + // runAtCurrTime: true, fetch: async (timestamp) => { - const [v1, v2] = await Promise.all([ + const [v1, v2, totalV2Volume, { v1 : totalV1Volume }] = await Promise.all([ fetchV2Volume(CHAIN.BSC), fetchV1Volume(), + fetchTotalV2Volume(CHAIN.BSC), + fetchTotalVolumeV1AndV2ForBSC() ]); return { dailyVolume: v1 + v2, + totalVolume: totalV1Volume + totalV2Volume, timestamp, }; }, start: 1682035200, }, [CHAIN.ARBITRUM]: { + // runAtCurrTime: true, fetch: async (timestamp) => { - const dailyVolume = await fetchV2Volume(CHAIN.ARBITRUM); + const [v2, totalVolume] = await Promise.all([ + fetchV2Volume(CHAIN.ARBITRUM), + fetchTotalV2Volume(CHAIN.ARBITRUM), + ]); return { timestamp, - dailyVolume: dailyVolume, + dailyVolume: v2, + totalVolume, }; }, start: 1682035200, }, [CHAIN.OP_BNB]: { + // runAtCurrTime: true, fetch: async (timestamp) => { - const dailyVolume = await fetchV2Volume('opbnb'); + const [v2, totalVolume] = await Promise.all([ + fetchV2Volume('opbnb'), + fetchTotalV2Volume('opbnb'), + ]); return { timestamp, - dailyVolume: dailyVolume, + dailyVolume: v2, + totalVolume, }; }, start: 1682035200, }, [CHAIN.BASE]: { + // runAtCurrTime: true, fetch: async (timestamp) => { - const dailyVolume = await fetchV2Volume(CHAIN.BASE); + const [v2, totalVolume] = await Promise.all([ + fetchV2Volume(CHAIN.BASE), + fetchTotalV2Volume(CHAIN.BASE), + ]); return { timestamp, - dailyVolume: dailyVolume, + dailyVolume: v2, + totalVolume, }; }, start: 1682035200, diff --git a/dexs/aqua-network/index.ts b/dexs/aqua-network/index.ts new file mode 100644 index 0000000000..f2150973c3 --- /dev/null +++ b/dexs/aqua-network/index.ts @@ -0,0 +1,41 @@ +import fetchURL from "../../utils/fetchURL" +import { SimpleAdapter } from "../../adapters/types"; +import { CHAIN } from "../../helpers/chains"; +import { getUniqStartOfTodayTimestamp } from "../../helpers/getUniSubgraphVolume"; + +const AQUA_VOLUME_ENDPOINT = "https://amm-api.aqua.network/api/external/v1/statistics/totals/?size=all" + +interface IVolumeAll { + volume: number; + tvl: number; + date: string; +} + +const fetch = async (timestamp: number) => { + const dayTimestamp = getUniqStartOfTodayTimestamp(new Date(timestamp * 1000)) + const historicalVolume: IVolumeAll[] = (await fetchURL(AQUA_VOLUME_ENDPOINT)); + + const totalVolume = historicalVolume + .filter(volItem => (new Date(volItem.date).getTime() / 1000) <= dayTimestamp) + .reduce((acc, { volume }) => acc + Number(volume), 0) + + const dailyVolume = historicalVolume + .find(dayItem => (new Date(dayItem.date).getTime() / 1000) === dayTimestamp)?.volume + + return { + totalVolume: `${totalVolume / 10e7}`, + dailyVolume: dailyVolume ? `${Number(dailyVolume) / 10e7}` : undefined, + timestamp: dayTimestamp, + }; +}; + +const adapter: SimpleAdapter = { + adapter: { + [CHAIN.STELLAR]: { + fetch, + start: 1719792000, + }, + }, +}; + +export default adapter; diff --git a/dexs/archly-finance-v2/index.ts b/dexs/archly-finance-v2/index.ts new file mode 100644 index 0000000000..84413f2e30 --- /dev/null +++ b/dexs/archly-finance-v2/index.ts @@ -0,0 +1,31 @@ +import { CHAIN } from "../../helpers/chains"; +import { uniV2Exports } from "../../helpers/uniswap"; + +const factory = '0x12508dd9108Abab2c5fD8fC6E4984E46a3CF7824'; +const FACTORY_ADDRESS_ZKSYNC = '0x30A0DD3D0D9E99BD0E67b323FB706788766dCff2'; +const FACTORY_ADDRESS_ETHERUEM = '0xE8E2b714C57937E0b29c6ABEAF00B52388cAb598'; + + +export default uniV2Exports({ + [CHAIN.ARBITRUM_NOVA]: { factory }, + [CHAIN.ARBITRUM]: { factory }, + [CHAIN.AVAX]: { factory }, + [CHAIN.BASE]: { factory }, + [CHAIN.BLAST]: { factory }, + [CHAIN.BSC]: { factory }, + [CHAIN.CRONOS]: { factory }, + [CHAIN.ETHEREUM]: { factory: FACTORY_ADDRESS_ETHERUEM }, + [CHAIN.FANTOM]: { factory }, + [CHAIN.FILECOIN]: { factory }, + [CHAIN.FRAXTAL]: { factory }, + [CHAIN.KAVA]: { factory }, + [CHAIN.MANTLE]: { factory }, + [CHAIN.METIS]: { factory }, + [CHAIN.MODE]: { factory }, + [CHAIN.NEON]: { factory }, + [CHAIN.OPTIMISM]: { factory }, + [CHAIN.POLYGON]: { factory }, + [CHAIN.TELOS]: { factory }, + [CHAIN.ERA]: { factory: FACTORY_ADDRESS_ZKSYNC }, + [CHAIN.ZORA]: { factory }, +}) \ No newline at end of file diff --git a/dexs/archly-finance/index.ts b/dexs/archly-finance/index.ts index 755b578d01..757b051d39 100644 --- a/dexs/archly-finance/index.ts +++ b/dexs/archly-finance/index.ts @@ -1,17 +1,14 @@ import { Adapter } from "../../adapters/types"; import { CHAIN } from "../../helpers/chains"; import { getStartTimestamp } from "../../helpers/getStartTimestamp"; -import { getGraphDimensions } from "../../helpers/getUniSubgraph"; +import { getGraphDimensions2 } from "../../helpers/getUniSubgraph"; const endpoints = { [CHAIN.TELOS]: "https://api.archly.fi/subgraphs/name/archly/amm", }; -const graphFetch = getGraphDimensions({ +const graphFetch = getGraphDimensions2({ graphUrls: endpoints, - totalVolume: { - factory: "factories" - }, dailyVolume: { factory: "dayData" }, @@ -27,6 +24,7 @@ const graphFetch = getGraphDimensions({ }); const adapter: Adapter = { + version: 2, adapter: { [CHAIN.TELOS]: { fetch: graphFetch(CHAIN.TELOS), diff --git a/dexs/ascent/index.ts b/dexs/ascent/index.ts index a4cee08c5e..522f650d54 100644 --- a/dexs/ascent/index.ts +++ b/dexs/ascent/index.ts @@ -1,46 +1,34 @@ import { BreakdownAdapter } from "../../adapters/types"; import { CHAIN } from "../../helpers/chains"; -import { DEFAULT_DAILY_VOLUME_FACTORY, DEFAULT_DAILY_VOLUME_FIELD, DEFAULT_TOTAL_VOLUME_FACTORY, DEFAULT_TOTAL_VOLUME_FIELD, getChainVolume } from "../../helpers/getUniSubgraphVolume"; - - - +import { DEFAULT_TOTAL_VOLUME_FACTORY, DEFAULT_TOTAL_VOLUME_FIELD, getChainVolume2 } from "../../helpers/getUniSubgraphVolume"; const endpoints = { [CHAIN.EON]: "https://eon-graph.horizenlabs.io/subgraphs/name/Ascent/ascent-subgraph", }; -const graphs = getChainVolume({ +const graphs = getChainVolume2({ graphUrls: endpoints, totalVolume: { factory: DEFAULT_TOTAL_VOLUME_FACTORY, field: DEFAULT_TOTAL_VOLUME_FIELD, }, - dailyVolume: { - factory: DEFAULT_DAILY_VOLUME_FACTORY, - field: DEFAULT_DAILY_VOLUME_FIELD, - dateField: "date" - }, }); const endpointsV3 = { [CHAIN.EON]: "https://eon-graph.horizenlabs.io/subgraphs/name/surfacing8671/v3AscentFull2", }; -const graphsV3 = getChainVolume({ +const graphsV3 = getChainVolume2({ graphUrls: endpointsV3, totalVolume: { factory: "factories", field: "totalVolumeUSD", }, - dailyVolume: { - factory: "pancakeDayData", - field: "volumeUSD", - dateField: "date" - }, }); const adapter: BreakdownAdapter = { + version: 2, breakdown: { v2: { [CHAIN.EON]: { diff --git a/dexs/ash-perp/index.ts b/dexs/ash-perp/index.ts new file mode 100644 index 0000000000..01391259e8 --- /dev/null +++ b/dexs/ash-perp/index.ts @@ -0,0 +1,42 @@ +import { request } from "graphql-request"; +import { SimpleAdapter } from "../../adapters/types"; +import { CHAIN } from "../../helpers/chains"; +import { getUniqStartOfTodayTimestamp } from "../../helpers/getUniSubgraphVolume"; + +const API_URL = 'https://statistic-api.ashperp.trade/graphql'; + +interface IVolume { + volume: string; + timestamp: number; +} + +const VolumeQuery = ` +query getVolume { + overview { + getPrevious24h { + volume_24h + } + } +} +` + +const fetch = async (timestamp: number) => { + const dayTimestamp = getUniqStartOfTodayTimestamp(new Date(timestamp * 1000)) + 86400; + const dailyVolume: number = (await request(API_URL, VolumeQuery)).overview.getPrevious24h.volume_24h; + return { + dailyVolume, + timestamp: dayTimestamp, + }; +} + +const adapter: SimpleAdapter = { + adapter: { + [CHAIN.ELROND]: { + fetch: fetch, + runAtCurrTime: true, + start: 1707782400 + }, + }, +}; + +export default adapter; diff --git a/dexs/astrolescent/index.ts b/dexs/astrolescent/index.ts new file mode 100644 index 0000000000..58c930f176 --- /dev/null +++ b/dexs/astrolescent/index.ts @@ -0,0 +1,29 @@ +import { FetchResultFees, FetchResultVolume, SimpleAdapter } from "../../adapters/types" +import { CHAIN } from "../../helpers/chains" +import fetchURL from "../../utils/fetchURL" +import customBackfill from "../../helpers/customBackfill"; + +interface AstrolescentStats { + volumeUSD: number; +} +const fetchVolume = async (timestamp: number): Promise => { + const response: AstrolescentStats = (await fetchURL(`https://api.astrolescent.com/stats/history?timestamp=${timestamp}`)); + const dailyVolume = Number(response?.volumeUSD); + + return { + dailyVolume, + timestamp + } +} + +const adapters: SimpleAdapter = { + adapter: { + [CHAIN.RADIXDLT]: { + fetch: fetchVolume, + start: 1698624000, + customBackfill: customBackfill(CHAIN.RADIXDLT, () => fetchVolume), + runAtCurrTime: false + } + } +} +export default adapters; diff --git a/dexs/astroport-v2/index.ts b/dexs/astroport-v2/index.ts index 7a34f187af..22554f4fab 100644 --- a/dexs/astroport-v2/index.ts +++ b/dexs/astroport-v2/index.ts @@ -16,7 +16,7 @@ query Stats($chains: [String]!) { } } `; -const url = 'https://app.astroport.fi/api/trpc/protocol.stats?input={"json":{"chains":["phoenix-1","injective-1","neutron-1","pacific-1"]}}' +const url = 'https://app.astroport.fi/api/trpc/protocol.stats?input={"json":{"chains":["phoenix-1","injective-1","neutron-1","pacific-1","osmosis-1"]}}' const fetch = (chainId: string) => { return async (timestamp: number): Promise => { const dayTimestamp = getUniqStartOfTodayTimestamp(new Date(timestamp * 1000)); @@ -54,6 +54,12 @@ const adapter: SimpleAdapter = { runAtCurrTime: true, customBackfill: undefined, start: 0, + }, + [CHAIN.OSMOSIS]: { + fetch: fetch("osmosis-1"), + runAtCurrTime: true, + customBackfill: undefined, + start: 0, } }, }; diff --git a/dexs/auragi/index.ts b/dexs/auragi/index.ts index 97164ab902..3994730b1d 100644 --- a/dexs/auragi/index.ts +++ b/dexs/auragi/index.ts @@ -1,25 +1,23 @@ +import * as sdk from "@defillama/sdk"; import { SimpleAdapter } from "../../adapters/types"; import { getStartTimestamp } from "../../helpers/getStartTimestamp"; -import { DEFAULT_DAILY_VOLUME_FIELD, DEFAULT_TOTAL_VOLUME_FIELD, getChainVolume } from "../../helpers/getUniSubgraphVolume"; +import { DEFAULT_DAILY_VOLUME_FIELD, DEFAULT_TOTAL_VOLUME_FIELD, getChainVolume2 } from "../../helpers/getUniSubgraphVolume"; import { CHAIN } from "../../helpers/chains"; const endpoints = { - [CHAIN.ARBITRUM]: "https://api.thegraph.com/subgraphs/name/oxbill/auragi", + [CHAIN.ARBITRUM]: sdk.graph.modifyEndpoint('DtNQcRXx82k4azEb5QvUjRbmXSNLTUsUePzPY6PtryEc'), }; -const graphs = getChainVolume({ +const graphs = getChainVolume2({ graphUrls: endpoints, totalVolume: { factory: "factories", field: DEFAULT_TOTAL_VOLUME_FIELD, }, - dailyVolume: { - factory: "dayData", - field: DEFAULT_DAILY_VOLUME_FIELD, - }, }); const adapter: SimpleAdapter = { + version: 2, adapter: { [CHAIN.ARBITRUM]: { fetch: graphs(CHAIN.ARBITRUM), diff --git a/dexs/auraswap/index.ts b/dexs/auraswap/index.ts index e892c438ef..f6b21388bd 100644 --- a/dexs/auraswap/index.ts +++ b/dexs/auraswap/index.ts @@ -1,8 +1,9 @@ +import * as sdk from "@defillama/sdk"; import { CHAIN } from "../../helpers/chains"; import { univ2Adapter } from "../../helpers/getUniSubgraphVolume"; const adapters = univ2Adapter({ - [CHAIN.POLYGON]: "https://api.thegraph.com/subgraphs/name/auraswap-dex/exchange", + [CHAIN.POLYGON]: sdk.graph.modifyEndpoint('HimtcQxxRnR2Uj4pq7EZQ3nUnhz8f5UJu7uax6WuYCGt'), }, { factoriesName: "factories", dayData: "dayData", diff --git a/dexs/auroraswap/index.ts b/dexs/auroraswap/index.ts index b7aaf8fe3b..b6aab258a0 100644 --- a/dexs/auroraswap/index.ts +++ b/dexs/auroraswap/index.ts @@ -1,30 +1,6 @@ -import { SimpleAdapter } from "../../adapters/types" -import { CHAIN } from "../../helpers/chains" -import { getDexVolumeExports } from "../../helpers/dexVolumeLogs"; +import { CHAIN } from "../../helpers/chains"; +import { uniV2Exports } from "../../helpers/uniswap"; - -const pools: string[] = [ - '0xf3de9dc38f62608179c45fe8943a0ca34ba9cefc', - '0xc57ecc341ae4df32442cf80f34f41dc1782fe067', - '0x480a68ba97d70495e80e11e05d59f6c659749f27', - '0xec538fafafcbb625c394c35b11252cef732368cd', - '0xdb0363ee28a5b40bdc2f4701e399c63e00f91aa8', - '0xefcf518ca36dc3362f539965807b42a77dc26be0', - '0x5bdac608cd38c5c8738f5be20813194a3150d4ff', - '0xcb8584360dc7a4eac4878b48fb857aa794e46fa8', - '0x865c59d555e59c9f35487bbdfb22d617c67aeabd', - '0xe11a3f2bab372d88d133b64487d1772847eec4ea', - '0x23524a789f93b798a6e7011b276edf09083cfde6', - '0x30c3d6c114a350026ea0aa770788374ad6c6f765' -].map((address: string) => address.toLowerCase()); - -const adapters: SimpleAdapter = { - adapter: { - [CHAIN.AURORA]: { - fetch: getDexVolumeExports({ chain: CHAIN.AURORA, pools }), - start: 1678838400, - } - } -} - -export default adapters +export default uniV2Exports({ + [CHAIN.AURORA]: { factory: '0xC5E1DaeC2ad401eBEBdd3E32516d90Ab251A3aA3', }, +}) diff --git a/dexs/autoshark/index.ts b/dexs/autoshark/index.ts index bdd284318d..316336247f 100644 --- a/dexs/autoshark/index.ts +++ b/dexs/autoshark/index.ts @@ -1,6 +1,7 @@ +import * as sdk from "@defillama/sdk"; import { CHAIN } from "../../helpers/chains"; import { univ2Adapter } from "../../helpers/getUniSubgraphVolume"; export default univ2Adapter({ - [CHAIN.BSC]: "https://api.thegraph.com/subgraphs/name/autoshark-finance/exchange-v1" + [CHAIN.BSC]: sdk.graph.modifyEndpoint('4NDG5dRjJX9BcWaHxKNwTZ1u4jwYP836QX4rgBdeGowD') }, {}); diff --git a/dexs/avantis/index.ts b/dexs/avantis/index.ts new file mode 100644 index 0000000000..adfd6c0346 --- /dev/null +++ b/dexs/avantis/index.ts @@ -0,0 +1,58 @@ +import { Chain } from "@defillama/sdk/build/general"; +import { CHAIN } from "../../helpers/chains"; +import { SimpleAdapter } from "../../adapters/types"; +import fetchURL from "../../utils/fetchURL"; +import { getTimestampAtStartOfDayUTC } from "../../utils/date"; +import { FetchResultVolume } from "../../adapters/types"; + +interface IData { + success: boolean; + cumulativeVolume: number; + history: { + date: string; + volume: number; + buyVolume: number; + sellVolume: number; + cumulativeVolume: number; + }[]; +} + +const API_URL = "https://api.avantisfi.com/v1"; + +const fetchData = (_: Chain) => { + return async (timestamp: number): Promise => { + const todaysTimestamp = getTimestampAtStartOfDayUTC(timestamp); + + // Convert timestamp to Date object and format to YYYY-MM-DD in UTC + const date = new Date(todaysTimestamp * 1000); + const dateStr = date.toISOString().split("T")[0]; + + // Find difference in days between today and the timestamp + const today = new Date(); + const diffTime = Math.abs(today.getTime() - date.getTime()); + const diffDays = Math.ceil(diffTime / (1000 * 60 * 60 * 24)); + + const url = `${API_URL}/history/analytics/daily-volumes/${diffDays}`; + const value: IData = await fetchURL(url); + if (!value.success) throw new Error("Failed to fetch data"); + + const dailyVolume = value.history.find((d) => d.date === dateStr)?.volume; + const totalVolume = value.history[value.history.length - 1]?.cumulativeVolume; + return { + dailyVolume: dailyVolume ? `${dailyVolume}` : undefined, + totalVolume: totalVolume ? `${totalVolume}` : undefined, + timestamp: todaysTimestamp, + }; + }; +}; + +const adapter: SimpleAdapter = { + adapter: { + [CHAIN.BASE]: { + fetch: fetchData(CHAIN.BASE), + start: 1706313600, + }, + }, +}; + +export default adapter; diff --git a/dexs/babyswap/index.ts b/dexs/babyswap/index.ts index 2da2b37f83..36c18f7de9 100644 --- a/dexs/babyswap/index.ts +++ b/dexs/babyswap/index.ts @@ -1,8 +1,9 @@ +import * as sdk from "@defillama/sdk"; import { CHAIN } from "../../helpers/chains"; import { univ2Adapter } from "../../helpers/getUniSubgraphVolume"; const adapters = univ2Adapter({ - [CHAIN.BSC]: "https://api.thegraph.com/subgraphs/name/babyswapgraph/exchange4" + [CHAIN.BSC]: sdk.graph.modifyEndpoint('CfeVCTevsVCZrmsrYEcpVzPYgxGmMihASYirpWP7r228') }, { factoriesName: "pancakeFactories", dayData: "pancakeDayData", diff --git a/dexs/balanced/balanced.ts b/dexs/balanced/balanced.ts new file mode 100644 index 0000000000..1f0a3b0485 --- /dev/null +++ b/dexs/balanced/balanced.ts @@ -0,0 +1,151 @@ +const apiUrl = 'https://balanced.icon.community/api/v1/pools'; +const SOLIDWALLET_ENDPOINT = 'https://ctz.solidwallet.io/api/v3'; + +// Helper function to fetch the real-time price of bnUSD from the Balanced Network Oracle, expressed in USD. +const fetchBnUsdPrice = async () => { + const GET_PRICES = { + jsonrpc: "2.0", + id: new Date().getTime(), + method: "icx_call", + params: { + to: "cx133c6015bb29f692b12e71c1792fddf8f7014652", + dataType: "call", + data: { + method: "getLastPriceInUSD", + params: { symbol: "bnUSD" } + } + } + }; + + const response = await fetch(SOLIDWALLET_ENDPOINT, { + method: "POST", + headers: { 'Content-Type': 'application/json' }, + body: JSON.stringify(GET_PRICES) + }); + + if (!response.ok) { + throw new Error(`HTTP Error: ${response.status}`); + } + + const data = await response.json(); + + if (!data.result) { + throw new Error('No result found'); + } + + return (parseInt(data.result, 16) / 1e18).toFixed(5); +}; + +// Helper function to build a price map for conversion rates of all Balanced Network assets to USD. +const buildPriceMap = (data, bnUsdPrice) => { + const priceMap = { bnUSD: Number(bnUsdPrice) }; + + data.forEach(pool => { + if (pool.base_symbol === 'bnUSD' || pool.quote_symbol === 'bnUSD') { + if (pool.base_symbol !== 'bnUSD') { + priceMap[pool.base_symbol] = parseFloat(pool.price_24h) * bnUsdPrice || 0; + } + if (pool.quote_symbol !== 'bnUSD') { + priceMap[pool.quote_symbol] = 1 / (parseFloat(pool.price_24h) * bnUsdPrice || 1); + } + } + }); + + return priceMap; +}; + + + +// Helper function to calculate total Balanced DEX pool fees, expressed in pool base values. +const calculateTotalFeesInBase24h = (baseLpFees24h, baseBalnFees24h, quoteLpFees24h, quoteBalnFees24h, price24h, baseSymbol, priceMap) => { + if (price24h === 0 || isNaN(price24h)) { + return 0; + } + + let totalFeesInBase24h = (baseLpFees24h + baseBalnFees24h) + ((quoteLpFees24h + quoteBalnFees24h) / price24h); + + if (totalFeesInBase24h > 0) { + totalFeesInBase24h *= priceMap[baseSymbol] || 1; + } + + return totalFeesInBase24h; +}; + +// Helper function to calculate total Balanced DEX pool volumes, expressed in USD. +const calculateTotalVolumesInUSD24h = (baseVolume24h, quoteVolume24h, baseSymbol, priceMap) => { + const baseVolumeInUSD = baseVolume24h * (priceMap[baseSymbol] || 0); + const quoteVolumeInUSD = quoteVolume24h * (priceMap['bnUSD'] || 1); + + return baseVolumeInUSD + quoteVolumeInUSD; +}; + +// Main function to fetch the 24-hour LP fees from the Balanced API and convert them to USD value +export const getPoolFees_24h = async () => { + try { + const bnUsdPrice = await fetchBnUsdPrice(); + const response = await fetch(apiUrl); + const data = await response.json(); + + const priceMap = buildPriceMap(data, bnUsdPrice); + + const totalLpFeesInUSD24h = data.reduce((total, pool) => { + const baseLpFees24h = parseFloat(pool.base_lp_fees_24h) || 0; + const quoteLpFees24h = parseFloat(pool.quote_lp_fees_24h) || 0; + const baseBalnFees24h = parseFloat(pool.base_baln_fees_24h) || 0; + const quoteBalnFees24h = parseFloat(pool.quote_baln_fees_24h) || 0; + const baseSymbol = pool.base_symbol; + const price24h = parseFloat(pool.price_24h) || 0; + + const totalFeesInBase24h = calculateTotalFeesInBase24h( + baseLpFees24h, + baseBalnFees24h, + quoteLpFees24h, + quoteBalnFees24h, + price24h, + baseSymbol, + priceMap + ); + + return total + totalFeesInBase24h; + }, 0); + // console.log('totalLpFeesInBnUsd24h:', totalLpFeesInUSD24h) + return totalLpFeesInUSD24h; + } catch (error) { + console.error('Error fetching or processing data:', error); + throw error; + } +}; + +// Main function to fetch the 24-hour pool volumes from the Balanced API and convert them to USD value +export const getPoolVolumes_24h = async () => { + try { + const bnUsdPrice = await fetchBnUsdPrice(); + const response = await fetch(apiUrl); + const data = await response.json(); + + const priceMap = buildPriceMap(data, bnUsdPrice); + + const totalVolumeInUSD24h = data.reduce((total, pool) => { + const baseVolume24h = parseFloat(pool.base_volume_24h) || 0; + const quoteVolume24h = parseFloat(pool.quote_volume_24h) || 0; + const baseSymbol = pool.base_symbol; + + const totalVolumeInUSD = calculateTotalVolumesInUSD24h( + baseVolume24h, + quoteVolume24h, + baseSymbol, + priceMap + ); + + return total + totalVolumeInUSD; + }, 0); + + // console.log('totalVolumeInUSD24h:', totalVolumeInUSD24h); + return totalVolumeInUSD24h; + } catch (error) { + console.error('Error fetching or processing data:', error); + throw error; + } +}; + + diff --git a/dexs/balanced/index.ts b/dexs/balanced/index.ts new file mode 100644 index 0000000000..dadf7fa742 --- /dev/null +++ b/dexs/balanced/index.ts @@ -0,0 +1,29 @@ +import { getPoolFees_24h, getPoolVolumes_24h } from './balanced.ts' +import { CHAIN } from '../../helpers/chains' + +export default { + version: 1, + adapter: { + [CHAIN.ICON]: { + runAtCurrTime: true, + start: 1700000000, + meta: { + methodology: { + Fees: 'Fees: Collected from borrowers and traders.', + TVL: 'TVL: The total liquidity held on the Balanced exchange and used as collateral for bnUSD.', + DataSource: 'Data is sourced from the Balanced Network API and ICON Tracker RPC Node. It is processed to calculate trading fees and volume accrued over a 24-hour period. Stats can be verified at https://stats.balanced.network/' + }, + }, + fetch: async () => { + const volumeResponse = await getPoolVolumes_24h() + const feeResponse = await getPoolFees_24h() + + return { + dailyVolume: volumeResponse.toString(), + dailyFees: feeResponse.toString(), + timestamp: Date.now() + } + }, + }, + } +} \ No newline at end of file diff --git a/dexs/balancer/index.ts b/dexs/balancer/index.ts index bda454de3e..d87a4f3797 100644 --- a/dexs/balancer/index.ts +++ b/dexs/balancer/index.ts @@ -1,22 +1,41 @@ +import * as sdk from "@defillama/sdk"; import { Chain } from "@defillama/sdk/build/general"; import request, { gql } from "graphql-request"; -import { BaseAdapter, BreakdownAdapter, ChainEndpoints, FetchResultVolume } from "../../adapters/types"; +import { + BaseAdapter, + BreakdownAdapter, + ChainEndpoints, + FetchOptions, + FetchResultV2, +} from "../../adapters/types"; import { CHAIN } from "../../helpers/chains"; -import customBackfill from "../../helpers/customBackfill"; import { getStartTimestamp } from "../../helpers/getStartTimestamp"; -import { getChainVolume, getUniqStartOfTodayTimestamp } from "../../helpers/getUniSubgraphVolume"; -import { getTimestampAtStartOfDayUTC } from "../../utils/date"; +import { getChainVolume2 } from "../../helpers/getUniSubgraphVolume"; const endpoints: ChainEndpoints = { - [CHAIN.ETHEREUM]: "https://api.thegraph.com/subgraphs/name/balancer-labs/balancer-v2", - [CHAIN.POLYGON]: - "https://api.thegraph.com/subgraphs/name/balancer-labs/balancer-polygon-v2", - [CHAIN.ARBITRUM]: - "https://api.thegraph.com/subgraphs/name/balancer-labs/balancer-arbitrum-v2", - [CHAIN.XDAI]: "https://api.thegraph.com/subgraphs/name/balancer-labs/balancer-gnosis-chain-v2", - [CHAIN.POLYGON_ZKEVM]: "https://api.studio.thegraph.com/query/24660/balancer-polygon-zk-v2/version/latest", - [CHAIN.AVAX]: "https://api.thegraph.com/subgraphs/name/balancer-labs/balancer-avalanche-v2", - [CHAIN.BASE]: "https://api.studio.thegraph.com/query/24660/balancer-base-v2/version/latest" + [CHAIN.ETHEREUM]: sdk.graph.modifyEndpoint( + "C4ayEZP2yTXRAB8vSaTrgN4m9anTe9Mdm2ViyiAuV9TV", + ), + [CHAIN.POLYGON]: sdk.graph.modifyEndpoint( + "78nZMyM9yD77KG6pFaYap31kJvj8eUWLEntbiVzh8ZKN", + ), + [CHAIN.ARBITRUM]: sdk.graph.modifyEndpoint( + "itkjv6Vdh22HtNEPQuk5c9M3T7VeGLQtXxcH8rFi1vc", + ), + [CHAIN.XDAI]: sdk.graph.modifyEndpoint( + "EJezH1Cp31QkKPaBDerhVPRWsKVZLrDfzjrLqpmv6cGg", + ), + [CHAIN.POLYGON_ZKEVM]: + "https://api.studio.thegraph.com/query/24660/balancer-polygon-zk-v2/version/latest", + [CHAIN.AVAX]: sdk.graph.modifyEndpoint( + "7asfmtQA1KYu6CP7YVm5kv4bGxVyfAHEiptt2HMFgkHu", + ), + [CHAIN.BASE]: + "https://api.studio.thegraph.com/query/24660/balancer-base-v2/version/latest", + [CHAIN.MODE]: + "https://api.studio.thegraph.com/query/75376/balancer-mode-v2/version/latest", + [CHAIN.FRAXTAL]: + "https://api.goldsky.com/api/public/project_clwhu1vopoigi01wmbn514m1z/subgraphs/balancer-fraxtal-v2/latest/gn", }; const graphParams = { @@ -25,63 +44,62 @@ const graphParams = { field: "totalSwapVolume", }, hasDailyVolume: false, -} -interface IPool { - id: string; - swapVolume: string; -} +}; interface IPoolSnapshot { - today: IPool[]; - yesterday: IPool[]; + today: { totalSwapVolume: number }[]; + yesterday: { totalSwapVolume: number }[]; } - const v2Graphs = (chain: Chain) => { - return async (timestamp: number): Promise => { - const startTimestamp = getTimestampAtStartOfDayUTC(timestamp) - const fromTimestamp = startTimestamp - 60 * 60 * 24 - const toTimestamp = startTimestamp - const graphQuery = gql - `query fees { - today:poolSnapshots(where: {timestamp:${toTimestamp}, protocolFee_gt:0}, orderBy:swapFees, orderDirection: desc) { - id - swapVolume - } - yesterday:poolSnapshots(where: {timestamp:${fromTimestamp}, protocolFee_gt:0}, orderBy:swapFees, orderDirection: desc) { - id - swapVolume - } + return async ({ + getFromBlock, + getToBlock, + }: FetchOptions): Promise => { + const [fromBlock, toBlock] = await Promise.all([ + getFromBlock(), + getToBlock(), + ]); + const graphQuery = gql`query fees { + today:balancers(block: { number: ${toBlock}}) { totalSwapVolume } + yesterday:balancers(block: { number: ${fromBlock}}) { totalSwapVolume } }`; - // const blackList = ['0x93d199263632a4ef4bb438f1feb99e57b4b5f0bd0000000000000000000005c2'] - const graphRes: IPoolSnapshot = (await request(endpoints[chain], graphQuery)); - const dailyVolume = graphRes["today"].map((p: IPool) => { - const yesterdayValue = Number(graphRes.yesterday.find((e: IPool) => e.id.split('-')[0] === p.id.split('-')[0])?.swapVolume || '0') - if (yesterdayValue === 0) return 0; - return Number(p.swapVolume) - yesterdayValue; - }).filter(e => e < 100_000_000).reduce((a: number, b: number) => a + b, 0) - return { - dailyVolume: `${dailyVolume}`, - timestamp, - }; + const graphRes: IPoolSnapshot = await request(endpoints[chain], graphQuery); + + const totalVolume = graphRes.today.reduce( + (p, c) => p + c.totalSwapVolume, + 0, + ); + const previousVolume = graphRes.yesterday.reduce( + (p, c) => p + c.totalSwapVolume, + 0, + ); + + const dailyVolume = totalVolume - previousVolume; + + return { + dailyVolume, + totalVolume, }; }; +}; - -const v1graphs = getChainVolume({ +const v1graphs = getChainVolume2({ graphUrls: { - [CHAIN.ETHEREUM]: "https://api.thegraph.com/subgraphs/name/balancer-labs/balancer" + [CHAIN.ETHEREUM]: sdk.graph.modifyEndpoint( + "93yusydMYauh7cfe9jEfoGABmwnX4GffHd7in8KJi1XB", + ), }, - ...graphParams + ...graphParams, }); const adapter: BreakdownAdapter = { + version: 2, breakdown: { v1: { [CHAIN.ETHEREUM]: { fetch: v1graphs(CHAIN.ETHEREUM), start: 1582761600, - customBackfill: customBackfill(CHAIN.ETHEREUM, v1graphs) }, }, v2: Object.keys(endpoints).reduce((acc, chain) => { @@ -93,13 +111,13 @@ const adapter: BreakdownAdapter = { endpoints, chain: chain, dailyDataField: `balancerSnapshots`, - dateField: 'timestamp', - volumeField: 'totalSwapVolume' + dateField: "timestamp", + volumeField: "totalSwapVolume", }), - } - } - }, {} as BaseAdapter) - } -} + }, + }; + }, {} as BaseAdapter), + }, +}; export default adapter; diff --git a/dexs/based-markets/index.ts b/dexs/based-markets/index.ts index f462385898..c774d91443 100644 --- a/dexs/based-markets/index.ts +++ b/dexs/based-markets/index.ts @@ -1,91 +1,30 @@ -import request, { gql } from "graphql-request"; -import { FetchResultVolume, SimpleAdapter } from "../../adapters/types"; +import * as sdk from "@defillama/sdk"; +import { SimpleAdapter } from "../../adapters/types"; import { CHAIN } from "../../helpers/chains"; -import BigNumber from "bignumber.js"; -import { getUniqStartOfTodayTimestamp } from "../../helpers/getUniSubgraphVolume"; - -const ONE_DAY_IN_SECONDS = 60 * 60 * 24 - -const endpoint = "https://api.thegraph.com/subgraphs/name/symmiograph/symmioanalytics_base_8_2" - -const query = gql` - query stats($from: String!, $to: String!) { - dailyHistories(where: {timestamp_gte: $from, timestamp_lte: $to, accountSource: "0x1c03B6480a4efC2d4123ba90d7857f0e1878B780"}){ - timestamp - platformFee - accountSource - tradeVolume - } - totalHistories(where: {accountSource: "0x1c03B6480a4efC2d4123ba90d7857f0e1878B780"}) { - timestamp - platformFee - accountSource - tradeVolume - } - } -` - - -interface IGraphResponse { - dailyHistories: Array<{ - tiemstamp: string, - platformFee: string, - accountSource: string, - tradeVolume: string - }> - totalHistories: Array<{ - tiemstamp: string, - platformFee: string, - accountSource: string, - tradeVolume: BigNumber - }> -} - -const toString = (x: BigNumber) => { - if (x.isEqualTo(0)) return undefined - return x.toString() -} - -const fetchVolume = async (timestamp: number): Promise => { - const response: IGraphResponse = await request(endpoint, query, { - from: String(timestamp - ONE_DAY_IN_SECONDS), - to: String(timestamp) - }) - - - let dailyVolume = new BigNumber(0); - response.dailyHistories.forEach(data => { - dailyVolume = dailyVolume.plus(new BigNumber(data.tradeVolume)) - }); - - let totalVolume = new BigNumber(0); - response.totalHistories.forEach(data => { - totalVolume = totalVolume.plus(new BigNumber(data.tradeVolume)) - }); - - dailyVolume = dailyVolume.dividedBy(new BigNumber(1e18)) - totalVolume = totalVolume.dividedBy(new BigNumber(1e18)) - - const _dailyVolume = toString(dailyVolume) - const _totalVolume = toString(totalVolume) - - const dayTimestamp = getUniqStartOfTodayTimestamp(new Date((timestamp * 1000))) - - return { - timestamp: dayTimestamp, - dailyVolume: _dailyVolume, - totalVolume: _totalVolume, - } - -} +import { getGraphDimensions2 } from "../../helpers/getUniSubgraph"; + +const fetch = getGraphDimensions2({ + graphUrls: { + [CHAIN.BASE]: sdk.graph.modifyEndpoint( + "3E7EJF1zWHD3LHTKV5L6dspCno2ghxZ3WYe9MN7QVnEE", + ), + }, + totalVolume: { + factory: "factories", + }, + totalFees: { + factory: "factories", + }, +}); const adapter: SimpleAdapter = { + version: 2, adapter: { [CHAIN.BASE]: { - fetch: fetchVolume, - start: 1704009000 - } - } -} + fetch: fetch(CHAIN.BASE), + start: 1704009000, + }, + }, +}; export default adapter; diff --git a/dexs/baseswap/index.ts b/dexs/baseswap/index.ts index 3997bd6246..d1b1f31076 100644 --- a/dexs/baseswap/index.ts +++ b/dexs/baseswap/index.ts @@ -1,33 +1,28 @@ +import * as sdk from "@defillama/sdk"; import customBackfill from "../../helpers/customBackfill"; import { DEFAULT_TOTAL_VOLUME_FACTORY, DEFAULT_TOTAL_VOLUME_FIELD, - DEFAULT_DAILY_VOLUME_FACTORY, - DEFAULT_DAILY_VOLUME_FIELD, } from "../../helpers/getUniSubgraphVolume"; import { CHAIN } from "../../helpers/chains"; import type { BaseAdapter, BreakdownAdapter, ChainEndpoints } from "../../adapters/types"; import type { Chain } from "@defillama/sdk/build/general"; -import { getGraphDimensions } from "../../helpers/getUniSubgraph"; +import { getGraphDimensions2 } from "../../helpers/getUniSubgraph"; const v2Endpoints: ChainEndpoints = { - [CHAIN.BASE]: "https://api.thegraph.com/subgraphs/name/harleen-m/baseswap", + [CHAIN.BASE]: sdk.graph.modifyEndpoint('BWHCfpXMHFDx3u4E14hEwv4ST7SUyN89FKJ2RjzWKgA9'), }; const v3Endpoints = { - [CHAIN.BASE]: "https://api.thegraph.com/subgraphs/name/baseswapfi/v3-base", + [CHAIN.BASE]: 'https://api.goldsky.com/api/public/project_cltceeuudv1ij01x7ekxhfl46/subgraphs/v3-base/prod/gn' }; // Fetch function to query the subgraphs -const v2Graph = getGraphDimensions({ +const v2Graph = getGraphDimensions2({ graphUrls: v2Endpoints, totalVolume: { factory: DEFAULT_TOTAL_VOLUME_FACTORY, field: DEFAULT_TOTAL_VOLUME_FIELD, }, - dailyVolume: { - factory: DEFAULT_DAILY_VOLUME_FACTORY, - field: DEFAULT_DAILY_VOLUME_FIELD, - }, feesPercent: { type: "volume", UserFees: 0.25, @@ -38,16 +33,12 @@ const v2Graph = getGraphDimensions({ }, }); -const v3Graphs = getGraphDimensions({ +const v3Graphs = getGraphDimensions2({ graphUrls: v3Endpoints, totalVolume: { factory: "factories", field: DEFAULT_TOTAL_VOLUME_FIELD, }, - dailyVolume: { - factory: DEFAULT_DAILY_VOLUME_FACTORY, - field: "volumeUSD", - }, feesPercent: { type: "fees", ProtocolRevenue: 64, @@ -78,6 +69,7 @@ const startTimeV3 = { }; const adapter: BreakdownAdapter = { + version: 2, breakdown: { v2: Object.keys(v2Endpoints).reduce((acc, chain) => { return { diff --git a/dexs/basin/index.ts b/dexs/basin/index.ts new file mode 100644 index 0000000000..778e43e21b --- /dev/null +++ b/dexs/basin/index.ts @@ -0,0 +1,94 @@ +import { request, gql } from "graphql-request"; +import { BreakdownAdapter, FetchOptions, FetchResultV2 } from "../../adapters/types"; +import { CHAIN } from "../../helpers/chains"; + +class SubgraphVolumeResponse { + wells: SubgraphWell[]; +} + +class SubgraphWell { + rollingDailyTradeVolumeUSD: string; + cumulativeTradeVolumeUSD: string; +} + +enum WellType { + SPOT +}; + +const chains = { + [CHAIN.ETHEREUM]: { + startBlock: 17977905, + startTime: 1692793703, + subgraph: "https://graph.node.bean.money/subgraphs/name/basin" + } +}; + +const methodology = { + dailyVolume: "USD sum of all swaps and add/remove liquidity operations that affect the price of pooled tokens", + UserFees: "There are no user fees.", + SupplySideRevenue: "There is no swap revenue for LP holders. However, rewards can be received if whitelisted LP tokens are deposited in the Beanstalk Silo.", + Fees: "There are no fees." +}; + +/** + * Returns daily/cumulative volume for the requested wells. + * @param chain - the chain for which to retrieve the statistics. + * @param type - the type of Well for which to get the volume. + * @param block - the block in which to query the subgraph. + * @dev Currently only type=SPOT is supported, as this is the only type of market which has been deployed + * so far. Future work in this adapter includes updating the subgraph query to account for the well type. + */ +async function getVolumeStats(chain: CHAIN, type: WellType, block: number): Promise { + + // Gets the volume of each well from the subgraph. + // If there are more than 1,000 wells at some point in the future, this may need to be revisited. + const subgraphVolume = await request(chains[chain].subgraph, gql` + { + wells( + block: {number: ${block}} + first: 1000 + orderBy: cumulativeTradeVolumeUSD + orderDirection: desc + ) { + rollingDailyTradeVolumeUSD + cumulativeTradeVolumeUSD + } + }` + ) as SubgraphVolumeResponse; + + // Sum and return the overall volume + return subgraphVolume.wells.reduce((result: FetchResultV2, next: SubgraphWell) => { + return { + dailyVolume: result.dailyVolume as number + parseFloat(next.rollingDailyTradeVolumeUSD), + totalVolume: result.totalVolume as number + parseFloat(next.cumulativeTradeVolumeUSD) + }; + }, { dailyVolume: 0, totalVolume: 0 }); +} + +function volumeForCategory(chain: CHAIN, type: WellType) { + + return { + [chain]: { + fetch: async (fetchParams: FetchOptions): Promise => { + const block = await fetchParams.getEndBlock(); + return await getVolumeStats(chain, type, block); + }, + start: async () => chains[chain].startTime, + runAtCurrTime: false, // Backfill is allowed + meta: { + methodology + }, + } + } +} + +// Currently there are only spot wells available, but it is expeted for more to exist in the future, +// therefore using BreakdownAdapter. +const adapter: BreakdownAdapter = { + version: 2, + breakdown: { + "spot": volumeForCategory(CHAIN.ETHEREUM, WellType.SPOT) + } +}; + +export default adapter; diff --git a/dexs/beamex/index.ts b/dexs/beamex/index.ts index 0844c75608..2d3e022319 100644 --- a/dexs/beamex/index.ts +++ b/dexs/beamex/index.ts @@ -5,7 +5,7 @@ import { getUniqStartOfTodayTimestamp } from "../../helpers/getUniSubgraphVolume const endpointsBeamex: ChainEndpoints = { [CHAIN.MOONBEAN]: - "https://api.thegraph.com/subgraphs/name/flisko/stats-moonbeam", + 'https://graph.beamswap.io/subgraphs/name/beamswap/beamex-stats', }; const historicalDataSwap = gql` query get_volume($period: String!, $id: String!) { @@ -36,54 +36,54 @@ interface IGraphResponse { const getFetch = (query: string) => - (chain: string): Fetch => - async (timestamp: number) => { - const dayTimestamp = getUniqStartOfTodayTimestamp( - new Date(timestamp * 1000) - ); - const dailyData: IGraphResponse = await request( - endpointsBeamex[chain], - query, - { - id: String(dayTimestamp), - period: "daily", - } - ); - const totalData: IGraphResponse = await request( - endpointsBeamex[chain], - query, - { - id: "total", - period: "total", - } - ); + (chain: string): Fetch => + async (timestamp: number) => { + const dayTimestamp = getUniqStartOfTodayTimestamp( + new Date(timestamp * 1000) + ); + const dailyData: IGraphResponse = await request( + endpointsBeamex[chain], + query, + { + id: String(dayTimestamp), + period: "daily", + } + ); + const totalData: IGraphResponse = await request( + endpointsBeamex[chain], + query, + { + id: "total", + period: "total", + } + ); - return { - timestamp: dayTimestamp, - dailyVolume: - dailyData.volumeStats.length == 1 - ? String( - Number( - Object.values(dailyData.volumeStats[0]).reduce((sum, element) => - String(Number(sum) + Number(element)) - ) - ) * + return { + timestamp: dayTimestamp, + dailyVolume: + dailyData.volumeStats.length == 1 + ? String( + Number( + Object.values(dailyData.volumeStats[0]).reduce((sum, element) => + String(Number(sum) + Number(element)) + ) + ) * 10 ** -30 - ) - : undefined, - totalVolume: - totalData.volumeStats.length == 1 - ? String( - Number( - Object.values(totalData.volumeStats[0]).reduce((sum, element) => - String(Number(sum) + Number(element)) - ) - ) * + ) + : undefined, + totalVolume: + totalData.volumeStats.length == 1 + ? String( + Number( + Object.values(totalData.volumeStats[0]).reduce((sum, element) => + String(Number(sum) + Number(element)) + ) + ) * 10 ** -30 - ) - : undefined, - }; - }; + ) + : undefined, + }; + }; const methodologyBeamex = { Fees: "Fees from open/close position (0.2%), liquidations, swap (0.2% to 0.4%), mint and burn (based on tokens balance in the pool) and borrow fee ((assets borrowed)/(total assets in pool)*0.02%)", diff --git a/dexs/beamswap-v3/index.ts b/dexs/beamswap-v3/index.ts index 428b809bfd..3fed8eabde 100644 --- a/dexs/beamswap-v3/index.ts +++ b/dexs/beamswap-v3/index.ts @@ -2,26 +2,21 @@ import { BreakdownAdapter } from "../../adapters/types"; import { CHAIN } from "../../helpers/chains"; import customBackfill from "../../helpers/customBackfill"; import { - DEFAULT_DAILY_VOLUME_FACTORY, DEFAULT_TOTAL_VOLUME_FIELD, - getGraphDimensions, + getGraphDimensions2, } from "../../helpers/getUniSubgraph"; const endpointV3 = { [CHAIN.MOONBEAM]: - "https://api.thegraph.com/subgraphs/name/beamswap/beamswap-v3", + "https://graph.beamswap.io/subgraphs/name/beamswap/beamswap-amm-v3", }; -const VOLUME_USD = "volumeUSD"; -const v3Graphs = getGraphDimensions({ + +const v3Graphs = getGraphDimensions2({ graphUrls: endpointV3, totalVolume: { factory: "factories", field: DEFAULT_TOTAL_VOLUME_FIELD, }, - dailyVolume: { - factory: DEFAULT_DAILY_VOLUME_FACTORY, - field: VOLUME_USD, - }, feesPercent: { type: "fees", ProtocolRevenue: 16, @@ -40,6 +35,7 @@ const methodologyv3 = { }; const adapter: BreakdownAdapter = { + version: 2, breakdown: { v3: { [CHAIN.MOONBEAN]: { diff --git a/dexs/beamswap/index.ts b/dexs/beamswap/index.ts index cab000b1d5..d0319e6877 100644 --- a/dexs/beamswap/index.ts +++ b/dexs/beamswap/index.ts @@ -2,25 +2,19 @@ import { BreakdownAdapter, ChainEndpoints } from "../../adapters/types"; import { CHAIN } from "../../helpers/chains"; import customBackfill from "../../helpers/customBackfill"; import { getStartTimestamp } from "../../helpers/getStartTimestamp"; -import { getGraphDimensions } from "../../helpers/getUniSubgraph"; +import { getGraphDimensions2 } from "../../helpers/getUniSubgraph"; const endpoints: ChainEndpoints = { [CHAIN.MOONBEAN]: - "https://api.thegraph.com/subgraphs/name/beamswap/beamswap-dex-v2", + "https://graph.beamswap.io/subgraphs/name/beamswap/beamswap-amm-v2", }; - - -const graphs = getGraphDimensions({ +const graphs = getGraphDimensions2({ graphUrls: endpoints, totalVolume: { factory: "uniswapFactories", field: "totalVolumeUSD", }, - dailyVolume: { - factory: "uniswapDayData", - field: "dailyVolumeUSD", - }, feesPercent: { type: "volume", UserFees: 0.3, @@ -32,20 +26,15 @@ const graphs = getGraphDimensions({ }, }); -const v1graphs = getGraphDimensions({ +const v1graphs = getGraphDimensions2({ graphUrls: { [CHAIN.MOONBEAN]: - "https://api.thegraph.com/subgraphs/name/beamswap/beamswap-stable-amm", + "https://graph.beamswap.io/subgraphs/name/beamswap/beamswap-stableamm", }, totalVolume: { factory: "tradeVolumes", field: "volume", }, - dailyVolume: { - factory: "dailyVolume", - field: "volume", - dateField: "timestamp", - }, feesPercent: { type: "volume", UserFees: 0.04, @@ -57,7 +46,6 @@ const v1graphs = getGraphDimensions({ }, }); - const methodology = { UserFees: "User pays 0.30% fees on each swap.", Fees: "A 0.30% of each swap is collected as trading fees", @@ -77,6 +65,7 @@ const methodologyStable = { }; const adapter: BreakdownAdapter = { + version: 2, breakdown: { classic: { [CHAIN.MOONBEAN]: { diff --git a/dexs/beethoven-x/index.ts b/dexs/beethoven-x/index.ts index 7368b07523..9d37b1424b 100644 --- a/dexs/beethoven-x/index.ts +++ b/dexs/beethoven-x/index.ts @@ -1,3 +1,4 @@ +import * as sdk from "@defillama/sdk"; import { ChainEndpoints, FetchResultVolume, SimpleAdapter } from "../../adapters/types"; import { CHAIN } from "../../helpers/chains"; import { Chain } from "@defillama/sdk/build/general"; @@ -5,8 +6,8 @@ import { getTimestampAtStartOfDayUTC } from "../../utils/date"; import request, { gql } from "graphql-request"; const endpoints: ChainEndpoints = { - [CHAIN.FANTOM]: "https://api.thegraph.com/subgraphs/name/beethovenxfi/beethovenx", - [CHAIN.OPTIMISM]: "https://api.thegraph.com/subgraphs/name/beethovenxfi/beethovenx-optimism", + [CHAIN.FANTOM]: sdk.graph.modifyEndpoint('4XKeW12D2RAhqefPYT3MLoT64p1JnT5TBLnYaNeSLA8k'), + [CHAIN.OPTIMISM]: sdk.graph.modifyEndpoint('F5jeL2nMXZt5LU6kSway7Vi2PTUcqDbw1gMQEbrmiVdJ'), }; interface IPool { diff --git a/dexs/biswap/index.ts b/dexs/biswap/index.ts index 3d29e62b1c..7e24d4c895 100644 --- a/dexs/biswap/index.ts +++ b/dexs/biswap/index.ts @@ -1,8 +1,9 @@ +import * as sdk from "@defillama/sdk"; import { CHAIN } from "../../helpers/chains"; import { univ2Adapter } from "../../helpers/getUniSubgraphVolume"; export default univ2Adapter({ - [CHAIN.BSC]: "https://api.thegraph.com/subgraphs/name/biswapcom/exchange5" + [CHAIN.BSC]: sdk.graph.modifyEndpoint('2D9rXpMTvAgofWngsyRE17jKr5ywrU4W3Eaa71579qkd') }, { factoriesName: "pancakeFactories", dayData: "pancakeDayData", diff --git a/dexs/bitkeep/index.ts b/dexs/bitkeep/index.ts index 2135b6c0fd..69d128c593 100644 --- a/dexs/bitkeep/index.ts +++ b/dexs/bitkeep/index.ts @@ -39,10 +39,10 @@ const adapter: SimpleAdapter = { fetch: graph(CHAIN.ETHEREUM), start: 1667232000, }, - [CHAIN.POLYGON]: { - fetch: graph(CHAIN.POLYGON), - start: 1667232000, - }, + // [CHAIN.POLYGON]: { + // fetch: graph(CHAIN.POLYGON), + // start: 1667232000, + // }, [CHAIN.BSC]: { fetch: graph(CHAIN.BSC), start: 1667232000, diff --git a/dexs/bladeswap/index.ts b/dexs/bladeswap/index.ts new file mode 100644 index 0000000000..c7af6a01ad --- /dev/null +++ b/dexs/bladeswap/index.ts @@ -0,0 +1,51 @@ +import { CHAIN } from "../../helpers/chains"; +import { univ2Adapter2 } from "../../helpers/getUniSubgraphVolume"; +import { FetchOptions, BreakdownAdapter } from "../../adapters/types"; +const adapters = univ2Adapter2( + { + [CHAIN.BLAST]: + "https://api.studio.thegraph.com/query/75205/blade-algebra/mainnet-info-1.0.3", + }, + { + factoriesName: "factories", + dayData: "algebraDayData", + dailyVolume: "volumeUSD", + totalVolume: "totalVolumeUSD", + } +); + +const fetch: any = async ({ getLogs, createBalances, }: FetchOptions) => { + const dailyVolume = createBalances() + let eventAbi = "event Swap(address indexed pool, address indexed user, bytes32[] tokenRef, int128[] delta)" + const logs = await getLogs({ target: "0x10F6b147D51f7578F760065DF7f174c3bc95382c", eventAbi, }) + logs.forEach((log: any) => { + const pool = log.pool.toLowerCase() + const hasPool = log.tokenRef.some((val: string) => '0x' + val.slice(2 + 24).toLowerCase() === pool) + // this is lp deposit/withdrawal, not swap + if (hasPool) return; + log.tokenRef.forEach((val: string, i: number) => { + const token = '0x' + val.slice(2 + 24).toLowerCase() + const volume = Number(log.delta[i]) + if (volume < 0) return; + dailyVolume.add(token, volume) + }) + }) + return { dailyVolume }; +} + +adapters.adapter.blast.start = 1717740000; + +const adapter: BreakdownAdapter = { + breakdown: { + v2: { + [CHAIN.BLAST]: { + fetch, + start: 1709208245, + } + }, + CL: adapters.adapter + }, + version: 2 +} + +export default adapter; diff --git a/dexs/blastfutures/index.ts b/dexs/blastfutures/index.ts index b5a8c15af4..8d3cd0fc38 100644 --- a/dexs/blastfutures/index.ts +++ b/dexs/blastfutures/index.ts @@ -1,51 +1,39 @@ import fetchURL from "../../utils/fetchURL" -import { FetchResultVolume, SimpleAdapter } from "../../adapters/types"; - -const historicalVolumeEndpoint = "https://api.bfx.trade/markets" -const candles = (market: string, timestampFrom: number, timestampTo: number) => { - const url = `https://api.bfx.trade/candles?market_id=${market}×tamp_from=${timestampFrom}×tamp_to=${timestampTo}&period=1440`; - return url; +import {FetchResultVolume, SimpleAdapter} from "../../adapters/types"; +import {getUniqStartOfTodayTimestamp} from "../../helpers/getUniSubgraphVolume"; +const historicalVolumeEndpoint = "https://api.prod.rabbitx.io/bfx/volume" +const volumeByTime = (timestampFrom: number, timestampTo: number) => { + const url = `${historicalVolumeEndpoint}?start_date=${timestampFrom}&end_date=${timestampTo}`; + return url; } interface IVolumeall { - volume: string; - time: string; - close: string; + volume: string; } const fetchVolume = async (timestamp: number): Promise => { - const fromTimestamp = timestamp - 60 * 60 * 24 - const toTimestamp = timestamp - - // Get market data - const response = await fetchURL(historicalVolumeEndpoint); - const marketsData = response.result; - - // Fetch candles for each USD market - const historical: IVolumeall[] = (await Promise.all(marketsData.map((market: any) => fetchURL(candles(market.id, fromTimestamp, toTimestamp))))) - .map((e: any) => e.result) - .flat(); - - // Calculate daily volume - const dailyVolume = historical - .filter((e: IVolumeall) => Number(e.time) >= fromTimestamp ) - .filter((e: IVolumeall) => Number(e.time) <= toTimestamp) - .reduce((a: number, b: IVolumeall) => a + Number(b.volume), 0) - - return { - dailyVolume: dailyVolume ? `${dailyVolume}` : undefined, - timestamp: timestamp, - }; + const dayTimestamp = getUniqStartOfTodayTimestamp(new Date(timestamp * 1000)) + const fromMS = dayTimestamp * 1000 * 1000; + const toMS = (dayTimestamp + 60 * 60 * 24) * 1000 * 1000; + + const response = await fetchURL(volumeByTime(fromMS, toMS)); + const marketsData: IVolumeall[] = response.result; + const dailyVolume = marketsData.reduce((acc, {volume}) => acc + Number(volume), 0); + + return { + dailyVolume: dailyVolume ? `${dailyVolume}` : undefined, + timestamp: timestamp, + }; }; const adapter: SimpleAdapter = { - adapter: { - "blast": { - fetch: fetchVolume, - start: 1700179200, // Replace with actual start timestamp + adapter: { + "blast": { + fetch: fetchVolume, + start: 1700179200, // Replace with actual start timestamp + }, }, - }, }; export default adapter; diff --git a/dexs/blex/index.ts b/dexs/blex/index.ts index 4ff51e9cb4..99e352c67c 100644 --- a/dexs/blex/index.ts +++ b/dexs/blex/index.ts @@ -1,10 +1,11 @@ +import * as sdk from "@defillama/sdk"; import request, { gql } from "graphql-request"; import { BreakdownAdapter, Fetch, SimpleAdapter } from "../../adapters/types"; import { CHAIN } from "../../helpers/chains"; import { getUniqStartOfTodayTimestamp } from "../../helpers/getUniSubgraphVolume"; const endpoints: { [key: string]: string } = { - [CHAIN.ARBITRUM]: "https://api.thegraph.com/subgraphs/name/blex-dex/arbitrum_42161", + [CHAIN.ARBITRUM]: sdk.graph.modifyEndpoint('FZz1rRe9kEd3FG6ZiX2tdoryxYiSFH4RnzKjMwny3mFH'), } const allData=gql` diff --git a/dexs/blitz/index.ts b/dexs/blitz/index.ts new file mode 100644 index 0000000000..4ee4f10dd7 --- /dev/null +++ b/dexs/blitz/index.ts @@ -0,0 +1,107 @@ +import { BreakdownAdapter } from "../../adapters/types"; +import { CHAIN } from "../../helpers/chains"; +import { httpGet, httpPost } from "../../utils/fetchURL"; + +interface IProducts { + spot_products: number[]; + perp_products: number[]; + margined_products: number[]; +} + +const gatewayBaseUrl = "https://gateway.blast-prod.vertexprotocol.com/v1"; +const archiveBaseUrl = "https://archive.blast-prod.vertexprotocol.com/v1"; + +const fetchValidSymbols = async (): Promise => { + const symbols = await httpGet(`${gatewayBaseUrl}/symbols`); + return symbols.map((product: { product_id: number }) => product.product_id); +}; + +const fetchProducts = async (): Promise => { + const validSymbols = await fetchValidSymbols(); + const allProducts = ( + await httpGet(`${gatewayBaseUrl}/query?type=all_products`) + ).data; + return { + spot_products: allProducts.spot_products + .map((product: { product_id: number }) => product.product_id) + .filter((id: number) => validSymbols.includes(id) && id > 0), + perp_products: allProducts.perp_products + .map((product: { product_id: number }) => product.product_id) + .filter((id: number) => validSymbols.includes(id)), + margined_products: allProducts.spot_products + .map((product: { product_id: number }) => product.product_id) + .filter((id: number) => validSymbols.includes(id) && id > 0), + }; +}; + +const computeVolume = async (timestamp: number, productIds: number[]) => { + const snapshots = ( + await httpPost(archiveBaseUrl, { + market_snapshots: { + interval: { + count: 2, + granularity: 86400, + max_time: timestamp, + }, + product_ids: productIds, + }, + }) + ).snapshots; + const lastCumulativeVolumes: Record = + snapshots[0].cumulative_volumes; + const prevCumulativeVolumes: Record = + snapshots[1].cumulative_volumes; + const totalVolume = Number( + Object.values(lastCumulativeVolumes).reduce( + (acc, current) => acc + Number(current), + Number(0) + ) / Number(10 ** 18) + ); + const totalVolumeOneDayAgo = Number( + Object.values(prevCumulativeVolumes).reduce( + (acc, current) => acc + Number(current), + Number(0) + ) / Number(10 ** 18) + ); + const dailyVolume = totalVolume - totalVolumeOneDayAgo; + return { + totalVolume: totalVolume ? `${totalVolume}` : undefined, + dailyVolume: dailyVolume !== undefined ? `${dailyVolume}` : undefined, + timestamp: timestamp, + }; +}; + +const fetchSpots = async (timeStamp: number) => { + const spotProductIds = (await fetchProducts()).spot_products; + return await computeVolume(timeStamp, spotProductIds); +}; + +const fetchPerps = async (timeStamp: number) => { + const perpProductIds = (await fetchProducts()).perp_products; + const marginedProductIds = (await fetchProducts()).margined_products; + return await computeVolume( + timeStamp, + perpProductIds.concat(marginedProductIds) + ); +}; + +const startTime = 1710259200; + +const adapter: BreakdownAdapter = { + breakdown: { + swap: { + [CHAIN.BLAST]: { + fetch: fetchSpots, + start: startTime, + }, + }, + derivatives: { + [CHAIN.BLAST]: { + fetch: fetchPerps, + start: startTime, + }, + }, + }, +}; + +export default adapter; diff --git a/dexs/blue-planet/index.ts b/dexs/blue-planet/index.ts index 3d324e9120..ff8aafe6c7 100644 --- a/dexs/blue-planet/index.ts +++ b/dexs/blue-planet/index.ts @@ -1,8 +1,9 @@ +import * as sdk from "@defillama/sdk"; import { CHAIN } from "../../helpers/chains"; import { univ2Adapter } from "../../helpers/getUniSubgraphVolume"; export default univ2Adapter({ - [CHAIN.BSC]: "https://api.thegraph.com/subgraphs/name/makemyideatech/planet-finance" + [CHAIN.BSC]: sdk.graph.modifyEndpoint('5Jo2jtiEVnVhSxHqzp24RUAjJrfeFPaZExxVwubTVBQ3') }, { factoriesName: "planetFinanceFactories", dayData: "planetFinanceDayData" diff --git a/dexs/bluemove.ts b/dexs/bluemove.ts new file mode 100644 index 0000000000..7269e2293f --- /dev/null +++ b/dexs/bluemove.ts @@ -0,0 +1,40 @@ +import fetchURL from "../utils/fetchURL" +import { SimpleAdapter } from "../adapters/types"; +import { CHAIN } from "../helpers/chains"; +import { getUniqStartOfTodayTimestamp } from "../helpers/getUniSubgraphVolume"; + +const historicalVolumeEndpoint = "https://aptos-mainnet-api.bluemove.net/api/histogram"; + +interface IVolumeall { + num: string; + date: string; +} + +const fetch = async (timestamp: number) => { + const dayTimestamp = getUniqStartOfTodayTimestamp(new Date(timestamp * 1000)) + const historicalVolume: IVolumeall[] = (await fetchURL(historicalVolumeEndpoint))?.data.list; + const totalVolume = historicalVolume + .filter(volItem => (new Date(volItem.date.split('T')[0]).getTime() / 1000) <= dayTimestamp) + .reduce((acc, { num }) => acc + Number(num), 0) + + const dailyVolume = historicalVolume + .find(dayItem => (new Date(dayItem.date.split('T')[0]).getTime() / 1000) === dayTimestamp)?.num + return { + totalVolume: `${totalVolume}`, + dailyVolume: dailyVolume ? `${dailyVolume}` : undefined, + timestamp: dayTimestamp, + }; +}; + + +const adapter: SimpleAdapter = { + adapter: { + [CHAIN.APTOS]: { + fetch, + start: 1666224000, + }, + }, + version: 1 +}; + +export default adapter; diff --git a/dexs/bmx-freestyle/index.ts b/dexs/bmx-freestyle/index.ts new file mode 100644 index 0000000000..b0ffea9888 --- /dev/null +++ b/dexs/bmx-freestyle/index.ts @@ -0,0 +1,121 @@ +import BigNumber from "bignumber.js"; +import { + FetchOptions, + FetchResultVolume, + SimpleAdapter, +} from "../../adapters/types"; +import request, { gql } from "graphql-request"; +import { CHAIN } from "../../helpers/chains"; + +const freestyleEndpoints: { [key: string]: string } = { + [CHAIN.BASE]: + "https://api-v2.morphex.trade/subgraph/3KhmYXgsM3CM1bbUCX8ejhcxQCtWwpUGhP7p9aDKZ94Z", +}; + +interface IGraphResponseFreestyle { + dailyHistories: Array<{ + tiemstamp: string; + platformFee: string; + accountSource: string; + tradeVolume: string; + }>; + totalHistories: Array<{ + tiemstamp: string; + platformFee: string; + accountSource: string; + tradeVolume: BigNumber; + }>; +} + +interface IGraphResponse { + volumeStats: Array<{ + burn: string; + liquidation: string; + margin: string; + mint: string; + swap: string; + }>; +} + +const ONE_DAY_IN_SECONDS = 60 * 60 * 24; + +const toString = (x: BigNumber) => { + if (x.isEqualTo(0)) return undefined; + return x.toString(); +}; + +const freestyleQuery = gql` + query stats($from: String!, $to: String!) { + dailyHistories( + where: { + timestamp_gte: $from + timestamp_lte: $to + accountSource: "0x6D63921D8203044f6AbaD8F346d3AEa9A2719dDD" + } + ) { + timestamp + platformFee + accountSource + tradeVolume + } + totalHistories( + where: { accountSource: "0x6D63921D8203044f6AbaD8F346d3AEa9A2719dDD" } + ) { + timestamp + platformFee + accountSource + tradeVolume + } + } +`; + +const fetchFreestyleVolume = async ( + timestamp: number, + _t: any, + options: FetchOptions +): Promise => { + const startTime = options.startOfDay; + const endTime = startTime + ONE_DAY_IN_SECONDS; + const response: IGraphResponseFreestyle = await request( + freestyleEndpoints[options.chain], + freestyleQuery, + { + from: String(startTime), + to: String(endTime), + } + ); + + let dailyVolume = new BigNumber(0); + let totalVolume = new BigNumber(0); + + response.dailyHistories.forEach((data) => { + dailyVolume = dailyVolume.plus(new BigNumber(data.tradeVolume)); + }); + response.totalHistories.forEach((data) => { + totalVolume = totalVolume.plus(new BigNumber(data.tradeVolume)); + }); + + dailyVolume = dailyVolume.dividedBy(new BigNumber(1e18)); + totalVolume = totalVolume.dividedBy(new BigNumber(1e18)); + + const _dailyVolume = toString(dailyVolume); + const _totalVolume = toString(totalVolume); + + return { + timestamp: timestamp, + dailyVolume: _dailyVolume ?? "0", + totalVolume: _totalVolume ?? "0", + }; +}; + +const adapter: SimpleAdapter = { + version: 1, + adapter: { + [CHAIN.BASE]: { + fetch: fetchFreestyleVolume, + start: 1714554000, + }, + }, +}; + +export default adapter; diff --git a/dexs/bmx/index.ts b/dexs/bmx/index.ts index 1b3746e486..cc3ff2ea5c 100644 --- a/dexs/bmx/index.ts +++ b/dexs/bmx/index.ts @@ -2,10 +2,17 @@ import request, { gql } from "graphql-request"; import { BreakdownAdapter, Fetch } from "../../adapters/types"; import { CHAIN } from "../../helpers/chains"; import { getUniqStartOfTodayTimestamp } from "../../helpers/getUniSubgraphVolume"; +import BigNumber from "bignumber.js"; +const startTimestamps: { [chain: string]: number } = { + [CHAIN.BASE]: 1694304000, + [CHAIN.MODE]: 1720627435, +}; const endpoints: { [key: string]: string } = { [CHAIN.BASE]: - "https://api.thegraph.com/subgraphs/name/morphex-labs/bmx-base-stats", + "https://api-v2.morphex.trade/subgraph/2vZHkWfx8g27Tri5LkTbhvCExCQcXJ3f28X2BwzFhjf6", + [CHAIN.MODE]: + "https://api-v2.morphex.trade/subgraph/8tp7xrDSCuutJ5omjfQKHvkGJpLszqPVWg3pby9XMLEz", }; const historicalDataSwap = gql` @@ -15,7 +22,6 @@ const historicalDataSwap = gql` } } `; - const historicalDataDerivatives = gql` query get_volume($period: String!, $id: String!) { volumeStats(where: { period: $period, id: $id }) { @@ -24,6 +30,15 @@ const historicalDataDerivatives = gql` } } `; +const historicalOI = gql` + query get_trade_stats($period: String!, $id: String!) { + tradingStats(where: { period: $period, id: $id }) { + id + longOpenInterest + shortOpenInterest + } + } +`; interface IGraphResponse { volumeStats: Array<{ @@ -34,6 +49,27 @@ interface IGraphResponse { swap: string; }>; } +interface IGraphResponseOI { + tradingStats: Array<{ + id: string; + longOpenInterest: string; + shortOpenInterest: string; + }>; +} +interface IGraphResponseFreestyle { + dailyHistories: Array<{ + tiemstamp: string; + platformFee: string; + accountSource: string; + tradeVolume: string; + }>; + totalHistories: Array<{ + tiemstamp: string; + platformFee: string; + accountSource: string; + tradeVolume: BigNumber; + }>; +} const getFetch = (query: string) => @@ -50,9 +86,41 @@ const getFetch = id: "total", period: "total", }); + let dailyOpenInterest = 0; + let dailyLongOpenInterest = 0; + let dailyShortOpenInterest = 0; + + if (query === historicalDataDerivatives) { + const tradingStats: IGraphResponseOI = await request( + endpoints[chain], + historicalOI, + { + id: String(dayTimestamp) + ":daily", + period: "daily", + } + ); + dailyOpenInterest = + Number(tradingStats.tradingStats[0]?.longOpenInterest || 0) + + Number(tradingStats.tradingStats[0]?.shortOpenInterest || 0); + dailyLongOpenInterest = Number( + tradingStats.tradingStats[0]?.longOpenInterest || 0 + ); + dailyShortOpenInterest = Number( + tradingStats.tradingStats[0]?.shortOpenInterest || 0 + ); + } return { timestamp: dayTimestamp, + dailyLongOpenInterest: dailyLongOpenInterest + ? String(dailyLongOpenInterest * 10 ** -30) + : undefined, + dailyShortOpenInterest: dailyShortOpenInterest + ? String(dailyShortOpenInterest * 10 ** -30) + : undefined, + dailyOpenInterest: dailyOpenInterest + ? String(dailyOpenInterest * 10 ** -30) + : undefined, dailyVolume: dailyData.volumeStats.length == 1 ? String( @@ -80,18 +148,24 @@ const getFetch = const adapter: BreakdownAdapter = { breakdown: { - swap: { - [CHAIN.BASE]: { - fetch: getFetch(historicalDataSwap)(CHAIN.BASE), - start: 1694304000, - }, - }, - derivatives: { - [CHAIN.BASE]: { - fetch: getFetch(historicalDataDerivatives)(CHAIN.BASE), - start: 1694304000, - }, - }, + swap: Object.keys(endpoints).reduce((acc, chain) => { + return { + ...acc, + [chain]: { + fetch: getFetch(historicalDataSwap)(chain), + start: startTimestamps[chain], + }, + }; + }, {}), + derivatives: Object.keys(endpoints).reduce((acc, chain) => { + return { + ...acc, + [chain]: { + fetch: getFetch(historicalDataDerivatives)(chain), + start: startTimestamps[chain], + }, + }; + }, {}), }, }; diff --git a/dexs/bsx/index.ts b/dexs/bsx/index.ts new file mode 100644 index 0000000000..576d0d7aa0 --- /dev/null +++ b/dexs/bsx/index.ts @@ -0,0 +1,34 @@ +import { SimpleAdapter, FetchV2 } from "../../adapters/types"; +import fetchURL from "../../utils/fetchURL"; +import { CHAIN } from "../../helpers/chains"; +import { getTimestampAtStartOfPreviousDayUTC } from "../../utils/date"; + +interface IBsxStatsResponse { + volume_24h: string; + volume_total: string; +} + +const fetchBsxVolumeData: FetchV2 = async ({ endTimestamp }) => { + const url = "https://api.bsx.exchange/defillama-stats?end_time=" + endTimestamp * 1e9; + const data: IBsxStatsResponse = await fetchURL(url); + const dailyVolume = Number(data.volume_24h).toFixed(2); + const totalVolume = Number(data.volume_total).toFixed(2); + + return { + timestamp: endTimestamp, + dailyVolume, + totalVolume, + }; +} + +const adapter: SimpleAdapter = { + version: 2, + adapter: { + [CHAIN.BASE]: { + fetch: fetchBsxVolumeData, + start: 1711929600, + }, + }, +}; + +export default adapter; diff --git a/dexs/butterxyz/index.ts b/dexs/butterxyz/index.ts index a11ff6c622..91801b06c2 100644 --- a/dexs/butterxyz/index.ts +++ b/dexs/butterxyz/index.ts @@ -1,25 +1,22 @@ -import { SimpleAdapter } from '../../adapters/types'; -import { CHAIN } from '../../helpers/chains'; -import { getGraphDimensions } from '../../helpers/getUniSubgraph'; +import { SimpleAdapter } from "../../adapters/types"; +import { CHAIN } from "../../helpers/chains"; +import { getGraphDimensions2 } from "../../helpers/getUniSubgraph"; -const dimensions = getGraphDimensions({ +const dimensions = getGraphDimensions2({ graphUrls: { - [CHAIN.MANTLE]: 'https://graph.butter.xyz/subgraphs/name/butterxyz/v3-subgraph', + [CHAIN.MANTLE]: + "https://graph.butter.xyz/subgraphs/name/butterxyz/v3-subgraph", }, totalVolume: { - factory: 'factories', - field: 'totalVolumeUSD', + factory: "factories", + field: "totalVolumeUSD", }, - dailyVolume: { - factory: 'butterDayData', - field: 'volumeUSD', - }, - dailyFees: { - factory: 'butterDayData', - field: 'feesUSD', + totalFees: { + factory: "factories", + field: "totalFeesUSD", }, feesPercent: { - type: 'fees', + type: "fees", ProtocolRevenue: 0, HoldersRevenue: 0, Fees: 0, @@ -30,10 +27,11 @@ const dimensions = getGraphDimensions({ }); export default { + version: 2, adapter: { [CHAIN.MANTLE]: { fetch: dimensions(CHAIN.MANTLE), start: 1702339200, - } - } + }, + }, } as SimpleAdapter; diff --git a/dexs/bxh/index.ts b/dexs/bxh/index.ts index 1b312395c7..e2c1929381 100644 --- a/dexs/bxh/index.ts +++ b/dexs/bxh/index.ts @@ -1,10 +1,11 @@ +import * as sdk from "@defillama/sdk"; import { CHAIN } from "../../helpers/chains"; import { univ2Adapter } from "../../helpers/getUniSubgraphVolume"; const adapters = univ2Adapter({ - [CHAIN.BSC]: "https://api.thegraph.com/subgraphs/name/privatelabs-chainx/bxhbnb", - [CHAIN.ETHEREUM]: "https://api.thegraph.com/subgraphs/name/privatelabs-chainx/bxheth", - // [CHAIN.AVAX]: "https://api.thegraph.com/subgraphs/name/privatelabs-chainx/bxhavax", not current daily volume + [CHAIN.BSC]: sdk.graph.modifyEndpoint('HvbSoSSDp99Pe9U7gjDhmXUzTbAKTcj77SnV3XKLVChn'), + [CHAIN.ETHEREUM]: sdk.graph.modifyEndpoint('9vZWBdQwCE7oi29YzBrQND5BLnS2iqPhosdG8jr6Rp9R'), + // [CHAIN.AVAX]: sdk.graph.modifyEndpoint('6dJhWGdrAgYXzky2EFFYw8GZsmZbrwdPMTq69CEqJEFD'), not current daily volume }, {}); adapters.adapter.bsc.start = 1627172051; diff --git a/dexs/c3-exchange/index.ts b/dexs/c3-exchange/index.ts new file mode 100644 index 0000000000..33db0459f9 --- /dev/null +++ b/dexs/c3-exchange/index.ts @@ -0,0 +1,84 @@ +import { + Adapter, + BaseAdapter, + FetchOptions, + FetchResultV2, + FetchV2, +} from "../../adapters/types"; +import { CHAIN } from "../../helpers/chains"; +import fetchURL from "../../utils/fetchURL"; + +const barsEndpoint = "https://api.c3.io/v1/markets/{id}/bars"; + +const ONE_DAY_IN_MILISECONDS = 60 * 60 * 24 * 1000; +const HALF_DAY_IN_MILISECONDS = ONE_DAY_IN_MILISECONDS / 2; + +const marketsOfChains = { + [CHAIN.ALGORAND]: ["ALGO-USDC"], + [CHAIN.AVAX]: ["AVAX-USDC"], + [CHAIN.BITCOIN]: ["WBTC-USDC"], + [CHAIN.ETHEREUM]: ["ETH-USDC"], + [CHAIN.ARBITRUM]: ["ARB-USDC"], + [CHAIN.BSC]: ["BNB-USDC"], + [CHAIN.SOLANA]: ["SOL-USDC", "PYTH-USDC", "W-USDC"], +}; + +async function fetchVolume({ + chain, + startOfDay, +}: FetchOptions): Promise { + const markets = marketsOfChains[chain]; + + const from = Math.floor(startOfDay) * 1000 - HALF_DAY_IN_MILISECONDS; + const to = Math.floor(startOfDay) * 1000 + HALF_DAY_IN_MILISECONDS; + const barsPromises = markets.map((market) => { + const endpoint = barsEndpoint.replace("{id}", market); + const url = `${endpoint}?from=${from}&to=${to}&granularity=1D`; + return fetchURL(url); + }); + + const volume24h = (await Promise.all(barsPromises)).reduce((acc, bars) => { + const last = bars[bars.length - 1]; + const quoteVolume = last?.quoteVolume ?? 0; + return acc + +quoteVolume; + }, 0); + + return { + dailyVolume: Math.round(volume24h), + timestamp: startOfDay, + }; +} + +function adapterConstructor( + fetchVolumeFunc: FetchV2, + chains: string[] +): Adapter { + const chainVolumes: BaseAdapter = chains.reduce( + (obj, chain) => ({ + ...obj, + [chain]: { + fetch: fetchVolumeFunc, + start: 1688169600, // 1st July 2023, 00:00:00 GMT + // runAtCurrTime: false, + meta: { + methodology: { + dailyVolume: "Volume is calculated by summing the quote token volume of all trades settled on the protocol that day.", + } + }, + }, + }), + {} + ); + + return { + version: 2, + adapter: chainVolumes, + }; +} + +const adapter: Adapter = adapterConstructor( + fetchVolume, + Object.keys(marketsOfChains) +); + +export default adapter; diff --git a/dexs/camelot-v3/index.ts b/dexs/camelot-v3/index.ts index ad8895505e..4cdd583fb6 100644 --- a/dexs/camelot-v3/index.ts +++ b/dexs/camelot-v3/index.ts @@ -1,13 +1,11 @@ -// https://api.thegraph.com/subgraphs/name/camelotlabs/camelot-amm-2 +import * as sdk from "@defillama/sdk"; import { CHAIN } from "../../helpers/chains"; -import { univ2Adapter } from "../../helpers/getUniSubgraphVolume"; +import { univ2Adapter2 } from "../../helpers/getUniSubgraphVolume"; -const adapters = univ2Adapter({ - [CHAIN.ARBITRUM]: "https://api.thegraph.com/subgraphs/name/camelotlabs/camelot-amm-v3" +const adapters = univ2Adapter2({ + [CHAIN.ARBITRUM]: sdk.graph.modifyEndpoint('7mPnp1UqmefcCycB8umy4uUkTkFxMoHn1Y7ncBUscePp') }, { factoriesName: "factories", - dayData: "algebraDayData", - dailyVolume: "volumeUSD", totalVolume: "totalVolumeUSD", }); diff --git a/dexs/camelot/index.ts b/dexs/camelot/index.ts index 8e2852e493..fb1b521996 100644 --- a/dexs/camelot/index.ts +++ b/dexs/camelot/index.ts @@ -1,9 +1,9 @@ -// https://api.thegraph.com/subgraphs/name/camelotlabs/camelot-amm-2 +import * as sdk from "@defillama/sdk"; import { CHAIN } from "../../helpers/chains"; -import { univ2Adapter } from "../../helpers/getUniSubgraphVolume"; +import { univ2Adapter2 } from "../../helpers/getUniSubgraphVolume"; -const adapters = univ2Adapter({ - [CHAIN.ARBITRUM]: "https://api.thegraph.com/subgraphs/name/camelotlabs/camelot-amm-2" +const adapters = univ2Adapter2({ + [CHAIN.ARBITRUM]: sdk.graph.modifyEndpoint('8zagLSufxk5cVhzkzai3tyABwJh53zxn9tmUYJcJxijG') }, {}); adapters.adapter.arbitrum.start = 1668124800; diff --git a/dexs/canary/index.ts b/dexs/canary/index.ts index 4272a3c5fd..fe27ae7305 100644 --- a/dexs/canary/index.ts +++ b/dexs/canary/index.ts @@ -1,7 +1,8 @@ +import * as sdk from "@defillama/sdk"; import { univ2Adapter } from "../../helpers/getUniSubgraphVolume"; export default univ2Adapter({ - "avax": "https://api.thegraph.com/subgraphs/name/canarydeveloper/canarydex" + "avax": sdk.graph.modifyEndpoint('An3x5Mz4YXEERomXYC4AhGgNhRthPFXNYDnrMCjrAJe') }, { factoriesName: "canaryFactories", dayData: "canaryDayData", diff --git a/dexs/canto-dex/index.ts b/dexs/canto-dex/index.ts index 68e8d84712..5d01d5b0eb 100644 --- a/dexs/canto-dex/index.ts +++ b/dexs/canto-dex/index.ts @@ -1,23 +1,6 @@ -import { SimpleAdapter } from "../../adapters/types"; import { CHAIN } from "../../helpers/chains"; -import { getDexVolumeExports } from "../../helpers/dexVolumeLogs"; +import { uniV2Exports } from "../../helpers/uniswap"; -const lpAddress = [ - '0x9571997a66d63958e1b3de9647c22bd6b9e7228c', - '0x1d20635535307208919f0b67c3b2065965a85aa9', - '0x30838619c55b787bafc3a4cd9aea851c1cfb7b19', - '0x216400ba362d8fce640085755e47075109718c8b', - '0x35db1f3a6a6f07f82c76fcc415db6cfb1a7df833', - '0x830fbc440a0a61b429b9ece5b7a4af003537fad2', -]; - -const adapter: SimpleAdapter = { - adapter: { - [CHAIN.CANTO]: { - fetch: getDexVolumeExports({ chain: CHAIN.CANTO, pools: lpAddress }), - start: 1668988800, - }, - } -}; - -export default adapter; +export default uniV2Exports({ + [CHAIN.CANTO]: { factory: '0xE387067f12561e579C5f7d4294f51867E0c1cFba', }, +}) diff --git a/dexs/capybara-exchange/index.ts b/dexs/capybara-exchange/index.ts new file mode 100644 index 0000000000..60c876a4c0 --- /dev/null +++ b/dexs/capybara-exchange/index.ts @@ -0,0 +1,80 @@ +import { FetchOptions, FetchResultV2, SimpleAdapter } from "../../adapters/types"; +import { CHAIN } from "../../helpers/chains"; +import { gql, request } from "graphql-request"; +import { getUniqStartOfTodayTimestamp } from "../../helpers/getUniSubgraphVolume"; +import { Chain } from "@defillama/sdk/build/general"; +import { getBlock } from "../../helpers/getBlock"; +import BigNumber from 'bignumber.js'; + +interface IGraph { + dailyTradeVolumeUSD: string; + dayID: string; +} + +interface IProtocol { + totalTradeVolumeUSD: string; +} + +interface IData { + protocolDayData: IGraph; + protocols: IProtocol[]; +} + +type TEndpoint = { + [s: string | Chain]: string; +}; + +// Updated using studio +const endpoints: TEndpoint = { + [CHAIN.KLAYTN]: + "https://klaytn-graphnode.ecosystem-dev.klaytn.in/cypress/graph/http/subgraphs/name/capy-exchange/capy-klaytn" +}; + +const feesRatio = 0.0004; + +const fetchVolume = (chain: Chain) => { + return async (options: FetchOptions): Promise => { + const {startTimestamp} = options; + const dayTimestamp = getUniqStartOfTodayTimestamp( + new Date(startTimestamp * 1000) + ); + const todaysBlock = await getBlock(dayTimestamp, chain, {}); + const dayID = dayTimestamp / 86400; + const query = gql` + { + protocolDayData(id: "${dayID}") { + dayID + dailyTradeVolumeUSD + }, + protocols(block: { number: ${todaysBlock} }) { + totalTradeVolumeUSD + } + }`; + const response: IData = await request(endpoints[chain], query); + const dailyVolume = + Number(response.protocolDayData.dailyTradeVolumeUSD) / 2; + const totalTradeVolumeUSD = + Number(response.protocols[0].totalTradeVolumeUSD) / 2; + const dailyFees = new BigNumber(dailyVolume ? dailyVolume : '0').multipliedBy(feesRatio).toString() + const totalFees = new BigNumber(totalTradeVolumeUSD ? totalTradeVolumeUSD : '0').multipliedBy(feesRatio).toString() + return { + dailyVolume: dailyVolume ? `${dailyVolume}` : undefined, + totalVolume: totalTradeVolumeUSD ? `${totalTradeVolumeUSD}` : undefined, + dailyFees: dailyFees, + totalFees: totalFees, + timestamp: dayTimestamp + }; + }; +}; + +const adapter: SimpleAdapter = { + version: 2, + adapter: { + [CHAIN.KLAYTN]: { + fetch: fetchVolume(CHAIN.KLAYTN), + start: 1715752335 + } + } +}; + +export default adapter; diff --git a/dexs/carbondefi/index.ts b/dexs/carbondefi/index.ts new file mode 100644 index 0000000000..2a6df4940c --- /dev/null +++ b/dexs/carbondefi/index.ts @@ -0,0 +1,93 @@ +import { FetchOptions, IJSON, SimpleAdapter } from "../../adapters/types"; +import { CHAIN } from "../../helpers/chains"; +import fetchURL from "../../utils/fetchURL"; +import { CarbonAnalyticsResponse } from "./types"; +import { + getEmptyData, + getDimensionsSum, + getDimensionsSumByToken, +} from "./utils"; + +const CARBON_METADATA: { + methodology: IJSON; + hallmarks: [number, string][]; +} = { + hallmarks: [ + [1681986059, "CarbonDeFi Ethereum Launch"], + [1716825673, "CarbonDeFi Sei Launch"], + [1721813184, "CarbonDeFi Celo Launch"], + ], + methodology: { + Volume: + "Volume is calculated as the sum of the targetAmount tokens from TokensTraded events emitted by the CarbonController contract.", + Fees: "Fees are calculated as the sum of the tradingFeeAmount amount for the sourceToken if tradeByTarget is true or the targetToken if tradeByTarget is false, taken from TokensTraded events emitted by the CarbonController contract.", + }, +}; + +const chainInfo: { [key: string]: any } = { + [CHAIN.ETHEREUM]: { + endpoint: "https://api.carbondefi.xyz/v1/analytics/volume", + startBlock: 17087375, + startTimestamp: 1681986059, + getDimensionsByToken: false, + }, + [CHAIN.SEI]: { + endpoint: "https://sei-api.carbondefi.xyz/v1/analytics/volume", + startBlock: 79146720, + startTimestamp: 1716825673, + getDimensionsByToken: true, + }, + [CHAIN.CELO]: { + endpoint: "https://celo-api.carbondefi.xyz/v1/analytics/volume", + startBlock: 26828280, + startTimestamp: 1721813184, + getDimensionsByToken: true, + }, +}; + +const getData = async (options: FetchOptions) => { + const analyticsEndpoint = chainInfo[options.chain].endpoint; + const getDimensionsByToken = chainInfo[options.chain].getDimensionsByToken; + const startTimestamp = options.fromTimestamp; + const endTimestamp = options.toTimestamp; + + try { + const swapData: CarbonAnalyticsResponse = await fetchURL(analyticsEndpoint); + + if (getDimensionsByToken) { + return getDimensionsSumByToken( + swapData, + startTimestamp, + endTimestamp, + getEmptyData(options) + ); + } + return getDimensionsSum(swapData, startTimestamp, endTimestamp); + } catch (e) { + console.error(e); + // Return empty values + return getEmptyData(options); + } +}; + +const adapter: SimpleAdapter = { + version: 2, + adapter: { + [CHAIN.ETHEREUM]: { + fetch: getData, + start: chainInfo[CHAIN.ETHEREUM].startTimestamp, + meta: CARBON_METADATA, + }, + [CHAIN.SEI]: { + fetch: getData, + start: chainInfo[CHAIN.SEI].startTimestamp, + meta: CARBON_METADATA, + }, + [CHAIN.CELO]: { + fetch: getData, + start: chainInfo[CHAIN.CELO].startTimestamp, + meta: CARBON_METADATA, + }, + }, +}; +export default adapter; diff --git a/dexs/carbondefi/types.ts b/dexs/carbondefi/types.ts new file mode 100644 index 0000000000..cd40d205ee --- /dev/null +++ b/dexs/carbondefi/types.ts @@ -0,0 +1,13 @@ +interface CarbonAnalyticsItem { + timestamp: string; + feesymbol: string; + feeaddress: string; + tradingfeeamount_real: number; + tradingfeeamount_usd: number; + targetsymbol: string; + targetaddress: string; + targetamount_real: number; + targetamount_usd: number; +} + +export interface CarbonAnalyticsResponse extends Array {} diff --git a/dexs/carbondefi/utils.ts b/dexs/carbondefi/utils.ts new file mode 100644 index 0000000000..7140a3cff6 --- /dev/null +++ b/dexs/carbondefi/utils.ts @@ -0,0 +1,115 @@ +import { Balances } from "@defillama/sdk"; +import { CarbonAnalyticsResponse } from "./types"; +import { FetchOptions } from "../../adapters/types"; + +const filterDataByDate = ( + swapData: CarbonAnalyticsResponse, + startTimestampS: number, + endTimestampS: number +) => { + const startTimestampMs = startTimestampS * 1000; + const endTimestampMs = endTimestampS * 1000; + + return swapData.filter((swap) => { + const swapTsMs = Date.parse(swap.timestamp); + return swapTsMs >= startTimestampMs && swapTsMs <= endTimestampMs; + }); +}; + +export const getDimensionsSum = ( + swapData: CarbonAnalyticsResponse, + startTimestamp: number, + endTimestamp: number +) => { + const dailyData = filterDataByDate(swapData, startTimestamp, endTimestamp); + + const { dailyVolume, dailyFees } = dailyData.reduce( + (prev, curr) => { + return { + dailyVolume: prev.dailyVolume + curr.targetamount_usd, + dailyFees: prev.dailyFees + curr.tradingfeeamount_usd, + }; + }, + { + dailyVolume: 0, + dailyFees: 0, + } + ); + const { totalVolume, totalFees } = swapData.reduce( + (prev, curr) => { + return { + totalVolume: prev.totalVolume + curr.targetamount_usd, + totalFees: prev.totalFees + curr.tradingfeeamount_usd, + }; + }, + { + totalVolume: 0, + totalFees: 0, + } + ); + return { + dailyVolume, + totalVolume, + dailyFees, + totalFees, + }; +}; + +const isNativeToken = (address: string) => address.toLowerCase() === "0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE".toLowerCase(); + +export const getDimensionsSumByToken = ( + swapData: CarbonAnalyticsResponse, + startTimestamp: number, + endTimestamp: number, + emptyData: { + dailyVolume: Balances; + dailyFees: Balances; + totalVolume: Balances; + totalFees: Balances; + }, +) => { + const dailyData = filterDataByDate(swapData, startTimestamp, endTimestamp); + const { dailyVolume, dailyFees, totalFees, totalVolume } = emptyData; + + swapData.forEach((swap) => { + if (isNativeToken(swap.targetaddress)) { + totalVolume.addGasToken(swap.targetamount_real * 1e18); + } else { + totalVolume.add(swap.targetaddress, swap.targetamount_real); + } + if (isNativeToken(swap.feeaddress)) { + totalFees.addGasToken(swap.tradingfeeamount_real * 1e18); + } else { + totalFees.add(swap.feeaddress, swap.tradingfeeamount_real); + } + }); + + dailyData.forEach((swap) => { + if (isNativeToken(swap.targetaddress)) { + dailyVolume.addGasToken(swap.targetamount_real * 1e18); + } else { + dailyVolume.add(swap.targetaddress, swap.targetamount_real); + } + if (isNativeToken(swap.feeaddress)) { + dailyFees.addGasToken(swap.tradingfeeamount_real * 1e18); + } else { + dailyFees.add(swap.feeaddress, swap.tradingfeeamount_real); + } + }); + + return { + dailyVolume, + dailyFees, + totalVolume, + totalFees, + }; +}; + +export const getEmptyData = (options: FetchOptions) => { + return { + dailyVolume: options.createBalances(), + dailyFees: options.createBalances(), + totalVolume: options.createBalances(), + totalFees: options.createBalances(), + }; +}; diff --git a/dexs/carthage/index.ts b/dexs/carthage/index.ts index 576b76ad83..d6f8f45669 100644 --- a/dexs/carthage/index.ts +++ b/dexs/carthage/index.ts @@ -1,16 +1,12 @@ import { BreakdownAdapter } from "../../adapters/types"; - const { - getChainVolume, + getChainVolume2, DEFAULT_DAILY_VOLUME_FACTORY, DEFAULT_TOTAL_VOLUME_FIELD, } = require("../../helpers/getUniSubgraphVolume"); - const { CANDLE } = require("../../helpers/chains"); - const { getStartTimestamp } = require("../../helpers/getStartTimestamp"); - const v3Endpoints = { [CANDLE]: "https://thegraph.cndlchain.com/subgraphs/name/ianlapham/uniswap-v3-test", @@ -18,7 +14,7 @@ const v3Endpoints = { const VOLUME_USD = "volumeUSD"; -const v3Graphs = getChainVolume({ +const v3Graphs = getChainVolume2({ graphUrls: { ...v3Endpoints, }, @@ -26,13 +22,10 @@ const v3Graphs = getChainVolume({ factory: "factories", field: DEFAULT_TOTAL_VOLUME_FIELD, }, - dailyVolume: { - factory: DEFAULT_DAILY_VOLUME_FACTORY, - field: VOLUME_USD, - }, }); const adapter: BreakdownAdapter = { + version: 2, breakdown: { v3: { [CANDLE]: { @@ -41,8 +34,8 @@ const adapter: BreakdownAdapter = { endpoints: v3Endpoints, chain: CANDLE, volumeField: VOLUME_USD, - }) - } + }), + }, }, }, }; diff --git a/dexs/cauldron/index.ts b/dexs/cauldron/index.ts new file mode 100644 index 0000000000..779784a769 --- /dev/null +++ b/dexs/cauldron/index.ts @@ -0,0 +1,59 @@ +// This adaptor uses the Riftenlabs Indexer API to query for volume. +// +// This indexer is open source (AGPLv3) and available at: +// https://gitlab.com/riftenlabs/riftenlabs-indexer + +import { FetchOptions, FetchResult, SimpleAdapter } from "../../adapters/types"; +import fetchURL from "../../utils/fetchURL"; +import { CHAIN } from "../../helpers/chains"; + +const INDEXER_URL = "https://indexer.cauldron.quest"; + +const methodology = { + Volume: "Scrape the blockchain and filter for spent transaction outputs that match the cauldron contract's redeem script. Check if the transaction has an output with a locking script that matches the redeem script in the input. A match on locking script means the funds are still locked in the DEX contract. Aggregate the difference of funds in contract utxos as trade volume.", + Fees: "N/A", + Revenue: "N/A", +} + +const adapter: SimpleAdapter = { + adapter: { + [CHAIN.BITCOIN_CASH]: { + fetch: fetchCauldronVolume, + start: 1688198180, + meta: { + methodology + } + }, + }, +}; + +export async function fetchCauldronVolume( + timestamp: number, _, options: FetchOptions +): Promise { + const endpoint = `${INDEXER_URL}/cauldron/contract/volume?end=${timestamp}`; + const volume = await fetchURL(endpoint) + + const total_sats = volume.reduce((acc, token) => { + return acc + Number(token.total_sats) + }, Number(0)); + + const daily_sats = volume.reduce((acc, token) => { + return acc + Number(token.one_day_sats) + }, Number(0)); + + const COIN = 100000000; + + const dailyVolume = options.createBalances(); + const totalVolume = options.createBalances(); + + dailyVolume.addCGToken('bitcoin-cash', Number(daily_sats / COIN)); + totalVolume.addCGToken('bitcoin-cash', Number(total_sats / COIN)); + + return { + timestamp, + dailyVolume, + totalVolume, + }; +} + +export default adapter; diff --git a/dexs/cellana-finance/index.ts b/dexs/cellana-finance/index.ts new file mode 100644 index 0000000000..18d8b191ae --- /dev/null +++ b/dexs/cellana-finance/index.ts @@ -0,0 +1,61 @@ +import {httpGet} from "../../utils/fetchURL"; +import { SimpleAdapter } from "../../adapters/types"; +import { CHAIN } from "../../helpers/chains"; +//API +const config_rule = { + headers: { + 'user-agent': 'axios/1.6.7' + }, + withCredentials:true +} +const cellanaDappUrl = 'https://api.cellana.finance/api/v1/tool/trading-volume-chart?timeframe='; + +const dayEndpoint = (endTimestamp: number, timeframe: string) => + cellanaDappUrl + timeframe + `&endTimestamp=${endTimestamp}` + +const totalEndpoint = (endTimestamp: number, timeframe: string) => + cellanaDappUrl + timeframe + +interface IVolumeall { + value: number; + timestamp: string; +} + +const fetch = async (timestamp: number) => { + const dayVolumeQuery = (await httpGet(dayEndpoint(timestamp, "VOLUME_1H"), config_rule)).data; + const dailyVolume = dayVolumeQuery.reduce((partialSum: number, a: IVolumeall) => partialSum + a.value, 0); + + const totalVolumeQuery = (await httpGet(totalEndpoint(0, "VOLUME_ALL"), config_rule)).data; + const totalVolume = totalVolumeQuery.reduce((partialSum: number, a: IVolumeall) => partialSum + a.value, 0); + + const dayFeesQuery = (await httpGet(dayEndpoint(timestamp, "FEE_1H"), config_rule)).data; + const dailyFees = dayFeesQuery.reduce((partialSum: number, a: IVolumeall) => partialSum + a.value, 0); + + const totalFeesQuery = (await httpGet(totalEndpoint(0, "FEE_ALL"), config_rule)).data; + const totalFees = totalFeesQuery.reduce((partialSum: number, a: IVolumeall) => partialSum + a.value, 0); + + const dailyProtocolRevenue = 0; + const totalProtocolRevenue = 0; + + return { + totalVolume: `${totalVolume}`, + dailyVolume: `${dailyVolume}`, + totalFees: `${totalFees}`, + dailyFees: `${dailyFees}`, + totalProtocolRevenue: `${totalProtocolRevenue}`, + dailyProtocolRevenue: `${dailyProtocolRevenue}`, + timestamp, + }; +}; + + +const adapter: SimpleAdapter = { + adapter: { + [CHAIN.APTOS]: { + fetch, + start: 1709078400 + }, + }, +}; + +export default adapter; diff --git a/dexs/cetus/index.ts b/dexs/cetus/index.ts index c1055d7c72..f041c58e8b 100644 --- a/dexs/cetus/index.ts +++ b/dexs/cetus/index.ts @@ -1,34 +1,41 @@ -import fetchURL from "../../utils/fetchURL" +import fetchURL from "../../utils/fetchURL"; import { Chain } from "@defillama/sdk/build/general"; -import { SimpleAdapter } from "../../adapters/types"; +import { FetchOptions, SimpleAdapter } from "../../adapters/types"; import { CHAIN } from "../../helpers/chains"; import { getUniqStartOfTodayTimestamp } from "../../helpers/getUniSubgraphVolume"; type IUrl = { - [s: string]: string; + [s: string]: { + countUrl: string, + histogramUrl: string, + }; } + const url: IUrl = { - [CHAIN.APTOS]: "https://api.cetus.zone/v1/histogram?date_type=day&typ=vol", - [CHAIN.SUI]: "https://api-sui.cetus.zone/v2/sui/histogram?date_type=day&typ=vol" + [CHAIN.APTOS]: { + countUrl: 'https://api.cetus.zone/v2/swap/count', + histogramUrl: "https://api.cetus.zone/v2/histogram?date_type=day&typ=vol&limit=99999", + }, + [CHAIN.SUI]: { + countUrl: 'https://api-sui.cetus.zone/v2/sui/swap/count/v3', + histogramUrl: "https://api-sui.cetus.zone/v2/sui/histogram?date_type=day&typ=vol&limit=99999" + } } + interface IVolumeall { num: string; date: string; } const fetch = (chain: Chain) => { - return async (timestamp: number) => { - const dayTimestamp = getUniqStartOfTodayTimestamp(new Date(timestamp * 1000)) - const historicalVolume: IVolumeall[] = (await fetchURL(url[chain])).data.list; - const totalVolume = historicalVolume - .filter(volItem => (new Date(volItem.date.split('T')[0]).getTime() / 1000) <= dayTimestamp) - .reduce((acc, { num }) => acc + Number(num), 0) - + return async (options: FetchOptions) => { + const dayTimestamp = getUniqStartOfTodayTimestamp(new Date(options.endTimestamp * 1000)) + const historicalVolume: IVolumeall[] = (await fetchURL(url[chain].histogramUrl)).data.list; + const totalVolume = (await fetchURL(url[chain].countUrl)).data.vol_in_usd const dailyVolume = historicalVolume .find(dayItem => (new Date(dayItem.date.split('T')[0]).getTime() / 1000) === dayTimestamp)?.num - return { totalVolume: `${totalVolume}`, dailyVolume: dailyVolume ? `${dailyVolume}` : undefined, @@ -39,17 +46,19 @@ const fetch = (chain: Chain) => { + const adapter: SimpleAdapter = { + version: 2, adapter: { - [CHAIN.APTOS]: { - fetch: fetch(CHAIN.APTOS), - start: 1666224000, - }, - [CHAIN.SUI]: { - fetch: fetch(CHAIN.SUI), - start: 1682985600, - } - }, + [CHAIN.APTOS]: { + fetch: fetch(CHAIN.APTOS), + start: 1666224000, + }, + [CHAIN.SUI]: { + fetch: fetch(CHAIN.SUI), + start: 1682985600, + } + } }; export default adapter; diff --git a/dexs/chainflip/index.ts b/dexs/chainflip/index.ts new file mode 100644 index 0000000000..c7045cb633 --- /dev/null +++ b/dexs/chainflip/index.ts @@ -0,0 +1,32 @@ +import { SimpleAdapter } from "../../adapters/types"; +import { CHAIN } from "../../helpers/chains"; +import { httpGet } from "../../utils/fetchURL"; + +const dimensionsEndpoint = "https://chainflip-broker.io/defillama/dexs" + +const fetch = async (timestamp: number) => { + const dimensionsData = await httpGet(`${dimensionsEndpoint}?timestamp=${timestamp}`, { headers: {"x-client-id": "defillama"}}); + + return { + timestamp: dimensionsData.timestamp, + dailyVolume: dimensionsData.dailyVolume, + totalVolume: dimensionsData.totalVolume + }; +}; + +const adapter: SimpleAdapter = { + adapter: { + [CHAIN.CHAINFLIP]: { + fetch, + start: 1700740800, // FLIP went live on 2023-11-23 12:00 UTC + runAtCurrTime: true, + meta: { + methodology: { + Volume: "Deposit value of a swap.", + } + } + }, + }, +}; + +export default adapter; diff --git a/dexs/champagneswap/index.ts b/dexs/champagneswap/index.ts index 480c7938a4..291db63998 100644 --- a/dexs/champagneswap/index.ts +++ b/dexs/champagneswap/index.ts @@ -1,20 +1,20 @@ +import * as sdk from "@defillama/sdk"; import { DISABLED_ADAPTER_KEY, SimpleAdapter } from "../../adapters/types"; import disabledAdapter from "../../helpers/disabledAdapter"; - const { - getChainVolume, + getChainVolume2, DEFAULT_TOTAL_VOLUME_FIELD, - DEFAULT_DAILY_VOLUME_FIELD, } = require("../../helpers/getUniSubgraphVolume"); const { BSC } = require("../../helpers/chains"); const { getStartTimestamp } = require("../../helpers/getStartTimestamp"); + const endpoints = { - [BSC]: "https://api.thegraph.com/subgraphs/name/champagneswap/exchangev3", + [BSC]: sdk.graph.modifyEndpoint( + "9gXThrkBPCRnK5ncBGySQJZoFUUSC5RDAYYciEZ323Pj", + ), }; -const DAILY_VOLUME_FACTORY = "champagneDayData"; - -const graphs = getChainVolume({ +const graphs = getChainVolume2({ graphUrls: { [BSC]: endpoints[BSC], }, @@ -22,13 +22,10 @@ const graphs = getChainVolume({ factory: "champagneFactories", field: DEFAULT_TOTAL_VOLUME_FIELD, }, - dailyVolume: { - factory: DAILY_VOLUME_FACTORY, - field: DEFAULT_DAILY_VOLUME_FIELD, - }, }); const adapter: SimpleAdapter = { + version: 2, adapter: { [DISABLED_ADAPTER_KEY]: disabledAdapter, [BSC]: { @@ -36,7 +33,7 @@ const adapter: SimpleAdapter = { start: getStartTimestamp({ endpoints, chain: BSC, - dailyDataField: `${DAILY_VOLUME_FACTORY}s`, + dailyDataField: `champagneDayDatas`, }), }, }, diff --git a/dexs/cherryswap/index.ts b/dexs/cherryswap/index.ts index 1908294c87..e17f5a39b3 100644 --- a/dexs/cherryswap/index.ts +++ b/dexs/cherryswap/index.ts @@ -1,4 +1,4 @@ -import { DEFAULT_DAILY_VOLUME_FIELD, DEFAULT_TOTAL_VOLUME_FIELD, getChainVolume } from "../../helpers/getUniSubgraphVolume"; +import { DEFAULT_TOTAL_VOLUME_FIELD, getChainVolume2 } from "../../helpers/getUniSubgraphVolume"; import { CHAIN } from "../../helpers/chains"; import request, { gql } from "graphql-request"; import { SimpleAdapter } from "../../adapters/types"; @@ -39,26 +39,24 @@ const getCustomBlock = async (timestamp: number) => { return block; }; -const DAILY_VOLUME_FACTORY = "uniswapDayData"; - -const graphs = getChainVolume({ +const graphs = getChainVolume2({ graphUrls: endpoints, totalVolume: { factory: "uniswapFactories", field: DEFAULT_TOTAL_VOLUME_FIELD, }, - dailyVolume: { - factory: DAILY_VOLUME_FACTORY, - field: DEFAULT_DAILY_VOLUME_FIELD, - dateField: 'date' - }, getCustomBlock, }); const adapter: SimpleAdapter = { + version: 2, adapter: { [CHAIN.OKEXCHAIN]: { - fetch: graphs(CHAIN.OKEXCHAIN), + fetch: async () => { + return { + dailyVolume: '0' + } + }, start: 1627385129, }, }, diff --git a/dexs/chronos-v2/index.ts b/dexs/chronos-v2/index.ts index 557ac6c270..b5eefeb5b6 100644 --- a/dexs/chronos-v2/index.ts +++ b/dexs/chronos-v2/index.ts @@ -1,16 +1,7 @@ -import { Fetch, SimpleAdapter } from "../../adapters/types" -import { CHAIN } from "../../helpers/chains" -import { getDexVolumeExportsV3 } from "../../helpers/dexVolumeLogs"; +import { uniV3Exports } from "../../helpers/uniswap"; -const poolFactoryAddress = '0x4Db9D624F67E00dbF8ef7AE0e0e8eE54aF1dee49'; - -const adapters: SimpleAdapter = { - adapter: { - [CHAIN.ARBITRUM]: { - fetch: getDexVolumeExportsV3({ factory: poolFactoryAddress, factoryFromBlock: 114041129, chain: CHAIN.ARBITRUM, }) as Fetch, - start: 1690070400, - } +export default uniV3Exports({ + arbitrum: { + factory: '0x4Db9D624F67E00dbF8ef7AE0e0e8eE54aF1dee49', } -} - -export default adapters; +}) \ No newline at end of file diff --git a/dexs/chronos/index.ts b/dexs/chronos/index.ts index b7acbc6e61..2dde375259 100644 --- a/dexs/chronos/index.ts +++ b/dexs/chronos/index.ts @@ -1,16 +1,9 @@ -import { SimpleAdapter } from "../../adapters/types"; import { CHAIN } from "../../helpers/chains"; -import { getDexVolumeExports } from "../../helpers/dexVolumeLogs"; +import { uniV2Exports } from "../../helpers/uniswap"; const FACTORY_ADDRESS = '0xCe9240869391928253Ed9cc9Bcb8cb98CB5B0722'; -const adapter: SimpleAdapter = { - adapter: { - [CHAIN.ARBITRUM]: { - fetch: getDexVolumeExports({ chain: CHAIN.ARBITRUM, factory: FACTORY_ADDRESS }), - start: 1679702400, - }, - } -}; +export default uniV2Exports({ + [CHAIN.ARBITRUM]: { factory: FACTORY_ADDRESS, }, +}) -export default adapter; diff --git a/dexs/clipper/index.ts b/dexs/clipper/index.ts index 546b4d3ec6..72a0e1ab12 100644 --- a/dexs/clipper/index.ts +++ b/dexs/clipper/index.ts @@ -1,38 +1,36 @@ +import * as sdk from "@defillama/sdk"; import { Chain } from "@defillama/sdk/build/general"; import { SimpleAdapter } from "../../adapters/types"; import { CHAIN } from "../../helpers/chains"; -import customBackfill from "../../helpers/customBackfill"; -const { - getChainVolume, -} = require("../../helpers/getUniSubgraphVolume"); +import { getChainVolume2 } from "../../helpers/getUniSubgraphVolume"; + const endpoints = { - [CHAIN.ETHEREUM]: "https://api.thegraph.com/subgraphs/name/edoapp/clipper-mainnet", - [CHAIN.OPTIMISM]: "https://api.thegraph.com/subgraphs/name/edoapp/clipper-optimism", - [CHAIN.POLYGON]: "https://api.thegraph.com/subgraphs/name/edoapp/clipper-polygon", - [CHAIN.MOONBEAN]: "https://api.thegraph.com/subgraphs/name/edoapp/clipper-moonbeam", - [CHAIN.ARBITRUM]: "https://api.thegraph.com/subgraphs/name/edoapp/clipper-arbitrum", + [CHAIN.ETHEREUM]: sdk.graph.modifyEndpoint('2BhN8mygHMmRkceMmod7CEEsGkcxh91ExRbEfRVkpVGM'), + [CHAIN.OPTIMISM]: sdk.graph.modifyEndpoint('Cu6atAfi6uR9mLMEBBjkhKSUUXHCobbB83ctdooexQ9f'), + [CHAIN.POLYGON]: sdk.graph.modifyEndpoint('Brmf2gRdpLFsEF6YjSAMVrXqSfbhsaaWaWzdCYjE7iYY'), + // [CHAIN.MOONBEAN]: sdk.graph.modifyEndpoint('8zRk4WV9vUU79is2tYGWq9GKh97f93LsZ8V9wy1jSMvA'), + [CHAIN.ARBITRUM]: sdk.graph.modifyEndpoint('ATBQPRjT28GEK6UaBAzXy64x9kFkNk1r64CdgmDJ587W'), }; const VOLUME_FIELD = "volumeUSD"; -const graphs = getChainVolume({ +const graphs = getChainVolume2({ graphUrls: endpoints, totalVolume: { factory: "pools", field: VOLUME_FIELD, }, - hasDailyVolume: false, }); const adapter: SimpleAdapter = { + version: 2, adapter: Object.keys(endpoints).reduce((acc, chain: any) => { return { ...acc, [chain]: { fetch: graphs(chain as Chain), start: 1657437036, - customBackfill: customBackfill(chain, graphs), } } }, {}) diff --git a/dexs/clober-v2/const.ts b/dexs/clober-v2/const.ts new file mode 100644 index 0000000000..32c30a88c6 --- /dev/null +++ b/dexs/clober-v2/const.ts @@ -0,0 +1,26 @@ +import {CHAIN} from "../../helpers/chains"; + +export const CONTRACT_INFOS: Record = { + [CHAIN.BASE]: { + bookManagerContract: { + address: '0x382CCccbD3b142D7DA063bF68cd0c89634767F76', + fromBlock: 14528050, + abi: { + openEvent: 'event Open(uint192 indexed id, address indexed base, address indexed quote, uint64 unitSize, uint24 makerPolicy, uint24 takerPolicy, address hooks)', + takeEvent: 'event Take(uint192 indexed bookId, address indexed user, int24 tick, uint64 unit)' + } + } + }, + [CHAIN.ERA]: { + bookManagerContract: { + address: '0xAaA0e933e1EcC812fc075A81c116Aa0a82A5bbb8', + fromBlock: 34448160, + abi: { + openEvent: 'event Open(uint192 indexed id, address indexed base, address indexed quote, uint64 unitSize, uint24 makerPolicy, uint24 takerPolicy, address hooks)', + takeEvent: 'event Take(uint192 indexed bookId, address indexed user, int24 tick, uint64 unit)' + } + } + }, +} + +export const zeroAddress = '0x0000000000000000000000000000000000000000' diff --git a/dexs/clober-v2/index.ts b/dexs/clober-v2/index.ts new file mode 100644 index 0000000000..63a592472e --- /dev/null +++ b/dexs/clober-v2/index.ts @@ -0,0 +1,81 @@ +import type {SimpleAdapter} from "../../adapters/types"; +import {FetchOptions, FetchResultV2, FetchV2} from "../../adapters/types"; +import {getTimestampAtStartOfDayUTC} from "../../utils/date" +import {CHAIN} from "../../helpers/chains"; +import {CONTRACT_INFOS} from "./const"; + +const fetch: FetchV2 = async (options: FetchOptions): Promise => { + const dayTimestamp = getTimestampAtStartOfDayUTC(options.toTimestamp) + + const dailyVolume = options.createBalances() + + const bookInfos: any = {} + const CONTRACT_INFO = CONTRACT_INFOS[options.chain]; + + const openEvents = await options.getLogs({ + target: CONTRACT_INFO.bookManagerContract.address, + fromBlock: CONTRACT_INFO.bookManagerContract.fromBlock, + eventAbi: CONTRACT_INFO.bookManagerContract.abi.openEvent, + onlyArgs: true, + }) + for (const open of openEvents) { + const bookId = open.id; + bookInfos[bookId] = { + quote: open.quote, + unitSize: open.unitSize, + } + } + + const dailyTakeEvents = await options.getLogs({ + target: CONTRACT_INFO.bookManagerContract.address, + eventAbi: CONTRACT_INFO.bookManagerContract.abi.takeEvent, + onlyArgs: true, + }) + const takeEvents = [ + { + events: dailyTakeEvents, + volume: dailyVolume, + }, + ] + for (const {events, volume} of takeEvents) { + for (const take of events) { + const bookId = take.bookId; + const bookInfo = bookInfos[bookId]; + if (!bookInfo) { + continue; + } + const quote = bookInfo.quote; + const quoteVolume = take.unit * bookInfo.unitSize; + volume.add(quote, quoteVolume); + } + } + + return { + dailyVolume: dailyVolume, + timestamp: dayTimestamp, + }; +}; + +const adapter: SimpleAdapter = { + version: 2, + adapter: { + [CHAIN.BASE]: { + fetch: fetch, + // runAtCurrTime: true, + start: 1718169619, + meta: { + methodology: 'Volume is calculated by summing the quote token volume of all trades on the protocol.', + } + }, + [CHAIN.ERA]: { + fetch: fetch, + // runAtCurrTime: true, + start: 1718169619, + meta: { + methodology: 'Volume is calculated by summing the quote token volume of all trades on the protocol.', + } + }, + } +}; + +export default adapter; diff --git a/dexs/cometh/index.ts b/dexs/cometh/index.ts index 90547d5bc3..2e7d759d79 100644 --- a/dexs/cometh/index.ts +++ b/dexs/cometh/index.ts @@ -1,7 +1,8 @@ +import * as sdk from "@defillama/sdk"; import { CHAIN } from "../../helpers/chains"; import { univ2Adapter } from "../../helpers/getUniSubgraphVolume"; export default univ2Adapter({ - [CHAIN.POLYGON]: "https://api.thegraph.com/subgraphs/name/cometh-game/comethswap" + [CHAIN.POLYGON]: sdk.graph.modifyEndpoint('GcokW8RfC9YJeZF4CPoLUwJwZRcQ8kbDR7WziCMus7LF') }, { }); diff --git a/dexs/complus-network/index.ts b/dexs/complus-network/index.ts index 6325b4333b..6470b501d9 100644 --- a/dexs/complus-network/index.ts +++ b/dexs/complus-network/index.ts @@ -1,9 +1,10 @@ +import * as sdk from "@defillama/sdk"; import { CHAIN } from "../../helpers/chains"; import { univ2Adapter } from "../../helpers/getUniSubgraphVolume"; const adapters = univ2Adapter({ - [CHAIN.AVAX]: 'https://api.thegraph.com/subgraphs/name/complusnetwork/subgraph-ava', - [CHAIN.BSC]: 'https://api.thegraph.com/subgraphs/name/complusnetwork/bsc-subgraph', + [CHAIN.AVAX]: sdk.graph.modifyEndpoint('JAcTKhMyEmiz467QXnt9W1cJXBpZqVmVJbPycEJ7f7nR'), + [CHAIN.BSC]: sdk.graph.modifyEndpoint('C4gWYKo4aKh993B1GNVuoeApQGj18dJShm2wMf6viihH'), // [CHAIN.POLYGON]: 'https://api.thegraph.com/subgraphs/name/complusnetwork/subgraph-matic', // [CHAIN.HECO]: 'https://hg2.bitcv.net/subgraphs/name/complusnetwork/subgraph-heco' }, { diff --git a/dexs/cone/index.ts b/dexs/cone/index.ts index 715fe1c32c..9dd2a6e443 100644 --- a/dexs/cone/index.ts +++ b/dexs/cone/index.ts @@ -1,8 +1,9 @@ +import * as sdk from "@defillama/sdk"; import { CHAIN } from "../../helpers/chains"; import { univ2Adapter } from "../../helpers/getUniSubgraphVolume"; const endpoints = { - [CHAIN.BSC]: "https://api.thegraph.com/subgraphs/name/cone-exchange/cone", + [CHAIN.BSC]: sdk.graph.modifyEndpoint('CeXrZ218JFm5S7iD6sGusqSSQgyFM6wuYoUk7iVygq1c'), }; const adapter = univ2Adapter(endpoints, {}); adapter.adapter.bsc.start = 1626677527; diff --git a/dexs/contango/index.ts b/dexs/contango/index.ts index 1cf619c117..a3aab7af06 100644 --- a/dexs/contango/index.ts +++ b/dexs/contango/index.ts @@ -1,3 +1,4 @@ +import * as sdk from "@defillama/sdk"; import request from "graphql-request"; import { ChainBlocks, FetchOptions, SimpleAdapter } from "../../adapters/types"; import { CHAIN } from "../../helpers/chains"; @@ -10,12 +11,12 @@ type IEndpoint = { } const endpoint: IEndpoint = { - [CHAIN.ARBITRUM]: "https://api.thegraph.com/subgraphs/name/contango-xyz/v2-arbitrum", - [CHAIN.OPTIMISM]: "https://api.thegraph.com/subgraphs/name/contango-xyz/v2-optimism", - [CHAIN.ETHEREUM]: "https://api.thegraph.com/subgraphs/name/contango-xyz/v2-mainnet", - [CHAIN.POLYGON]: "https://api.thegraph.com/subgraphs/name/contango-xyz/v2-polygon", + [CHAIN.ARBITRUM]: sdk.graph.modifyEndpoint('BmHqxUxxLuMoDYgbbXU6YR8VHUTGPBf9ghD7XH6RYyTQ'), + [CHAIN.OPTIMISM]: sdk.graph.modifyEndpoint('PT2TcgYqhQmx713U3KVkdbdh7dJevgoDvmMwhDR29d5'), + [CHAIN.ETHEREUM]: sdk.graph.modifyEndpoint('FSn2gMoBKcDXEHPvshaXLPC1EJN7YsfCP78swEkXcntY'), + [CHAIN.POLYGON]: sdk.graph.modifyEndpoint('5t3rhrAYt79iyjm929hgwyiaPLk9uGxQRMiKEasGgeSP'), [CHAIN.BASE]: "https://graph.contango.xyz:18000/subgraphs/name/contango-xyz/v2-base", - [CHAIN.XDAI]: "https://api.thegraph.com/subgraphs/name/contango-xyz/v2-gnosis", + [CHAIN.XDAI]: sdk.graph.modifyEndpoint('9h1rHUKJK9CGqztdaBptbj4Q9e2zL9jABuu9LpRQ1XkC'), } interface IAssetTotals { diff --git a/dexs/core-markets/index.ts b/dexs/core-markets/index.ts new file mode 100644 index 0000000000..9f6a9a1c7b --- /dev/null +++ b/dexs/core-markets/index.ts @@ -0,0 +1,90 @@ +import BigNumber from "bignumber.js"; +import request, { gql } from "graphql-request"; +import { FetchResultVolume, SimpleAdapter } from "../../adapters/types"; +import { CHAIN } from "../../helpers/chains"; +import { getUniqStartOfTodayTimestamp } from "../../helpers/getUniSubgraphVolume"; + +const ONE_DAY_IN_SECONDS = 60 * 60 * 24; + +const endpoint = "https://api.studio.thegraph.com/query/62472/core-analytics-082/version/latest"; + +const query = gql` + query stats($from: String!, $to: String!) { + dailyHistories( + where: { timestamp_gte: $from, timestamp_lte: $to, accountSource: "0xd6ee1fd75d11989e57B57AA6Fd75f558fBf02a5e" } + ) { + timestamp + platformFee + accountSource + tradeVolume + } + totalHistories(where: { accountSource: "0xd6ee1fd75d11989e57B57AA6Fd75f558fBf02a5e" }) { + timestamp + platformFee + accountSource + tradeVolume + } + } +`; + +interface IGraphResponse { + dailyHistories: Array<{ + tiemstamp: string; + platformFee: string; + accountSource: string; + tradeVolume: string; + }>; + totalHistories: Array<{ + tiemstamp: string; + platformFee: string; + accountSource: string; + tradeVolume: BigNumber; + }>; +} + +const toString = (x: BigNumber) => { + if (x.isEqualTo(0)) return undefined; + return x.toString(); +}; + +const fetchVolume = async (timestamp: number): Promise => { + const response: IGraphResponse = await request(endpoint, query, { + from: String(timestamp - ONE_DAY_IN_SECONDS), + to: String(timestamp), + }); + + let dailyVolume = new BigNumber(0); + response.dailyHistories.forEach((data) => { + dailyVolume = dailyVolume.plus(new BigNumber(data.tradeVolume)); + }); + + let totalVolume = new BigNumber(0); + response.totalHistories.forEach((data) => { + totalVolume = totalVolume.plus(new BigNumber(data.tradeVolume)); + }); + + dailyVolume = dailyVolume.dividedBy(new BigNumber(1e18)); + totalVolume = totalVolume.dividedBy(new BigNumber(1e18)); + + const _dailyVolume = toString(dailyVolume); + const _totalVolume = toString(totalVolume); + + const dayTimestamp = getUniqStartOfTodayTimestamp(new Date(timestamp * 1000)); + + return { + timestamp: dayTimestamp, + dailyVolume: _dailyVolume ?? "0", + totalVolume: _totalVolume ?? "0", + }; +}; + +const adapter: SimpleAdapter = { + adapter: { + [CHAIN.BLAST]: { + fetch: fetchVolume, + start: async () => 236678, + }, + }, +}; + +export default adapter; diff --git a/dexs/covo-v2/index.ts b/dexs/covo-v2/index.ts index 1220462f9a..b307b00849 100644 --- a/dexs/covo-v2/index.ts +++ b/dexs/covo-v2/index.ts @@ -1,3 +1,4 @@ +import * as sdk from "@defillama/sdk"; import request, { gql } from "graphql-request"; import { BreakdownAdapter, DISABLED_ADAPTER_KEY, Fetch, SimpleAdapter } from "../../adapters/types"; import { CHAIN } from "../../helpers/chains"; @@ -5,7 +6,7 @@ import { getUniqStartOfTodayTimestamp } from "../../helpers/getUniSubgraphVolume import disabledAdapter from "../../helpers/disabledAdapter"; const endpoints: { [key: string]: string } = { - [CHAIN.POLYGON]: "https://api.thegraph.com/subgraphs/name/defi-techz/covo-v2-2", + [CHAIN.POLYGON]: sdk.graph.modifyEndpoint('GmEspRRKwqTj7tfazuAxwNwqeXajJq4NnZoGaiNyx3tq'), } const historicalDataSwap = gql` diff --git a/dexs/crescent-swap/index.ts b/dexs/crescent-swap/index.ts index 5bc0e73a8f..7f68b79088 100644 --- a/dexs/crescent-swap/index.ts +++ b/dexs/crescent-swap/index.ts @@ -1,24 +1,22 @@ +import * as sdk from "@defillama/sdk"; import { SimpleAdapter } from "../../adapters/types"; -import { getChainVolume } from "../../helpers/getUniSubgraphVolume"; +import { getChainVolume2 } from "../../helpers/getUniSubgraphVolume"; import { CHAIN } from "../../helpers/chains"; const endpoints = { - [CHAIN.ARBITRUM]: "https://api.thegraph.com/subgraphs/name/hangpiece/crescentswap-arb", + [CHAIN.ARBITRUM]: sdk.graph.modifyEndpoint('8kFH5we1wSUT75VDWWyCB2Nqivawf6QaCE8L5k56nrfy'), }; -const graphs = getChainVolume({ +const graphs = getChainVolume2({ graphUrls: endpoints, totalVolume: { factory: "factories", field: "totalVolumeUSD", }, - dailyVolume: { - factory: "uniswapDayData", - field: "volumeUSD", - }, }); const adapter: SimpleAdapter = { + version: 2, adapter: { [CHAIN.ARBITRUM]: { fetch: graphs(CHAIN.ARBITRUM), diff --git a/dexs/cropper-clmm/index.ts b/dexs/cropper-clmm/index.ts new file mode 100644 index 0000000000..445cbffa2c --- /dev/null +++ b/dexs/cropper-clmm/index.ts @@ -0,0 +1,31 @@ +import { CHAIN } from '../../helpers/chains'; +import { httpGet } from '../../utils/fetchURL'; + + +const cropperEndpoint = "https://flow.cropper.finance/stats24.json"; + +interface Stats24H { + dailyVolume: number + dailyFees: number + details: number + timestamp: number +}; + +async function fetch(timestamp: any) { + let response: Stats24H = await httpGet(cropperEndpoint); + return { + dailyVolume: response.dailyVolume, + timestamp: timestamp + }; +} + +export default { + version: 2, + adapter: { + [CHAIN.SOLANA]: { + fetch: fetch, + runAtCurrTime: true, + start: 1714435200, + } + } +} diff --git a/dexs/cryptoswap/index.ts b/dexs/cryptoswap/index.ts index 41009b24f3..f7b5b3e6ba 100644 --- a/dexs/cryptoswap/index.ts +++ b/dexs/cryptoswap/index.ts @@ -1,7 +1,7 @@ +import * as sdk from "@defillama/sdk"; const { - getChainVolume, + getChainVolume2, DEFAULT_TOTAL_VOLUME_FIELD, - DEFAULT_DAILY_VOLUME_FIELD, } = require("../../helpers/getUniSubgraphVolume"); const { getStartTimestamp } = require("../../helpers/getStartTimestamp"); @@ -9,31 +9,28 @@ import { SimpleAdapter } from "../../adapters/types"; import { CHAIN } from "../../helpers/chains"; const endpoints = { - [CHAIN.BSC]: "https://api.thegraph.com/subgraphs/name/cryptolover705/cryptoswap", + [CHAIN.BSC]: sdk.graph.modifyEndpoint( + "46UXg1gyUFk7q8WrmNEMp7qoc2paiDqy5HpMvF4UQBze", + ), }; -const DAILY_VOLUME_FACTORY = "cstdayData"; - -const graphs = getChainVolume({ +const graphs = getChainVolume2({ graphUrls: endpoints, totalVolume: { factory: "cstfactories", field: DEFAULT_TOTAL_VOLUME_FIELD, }, - dailyVolume: { - factory: DAILY_VOLUME_FACTORY, - field: DEFAULT_DAILY_VOLUME_FIELD, - }, }); const adapter: SimpleAdapter = { + version: 2, adapter: { [CHAIN.BSC]: { fetch: graphs(CHAIN.BSC), start: getStartTimestamp({ endpoints, chain: CHAIN.BSC, - dailyDataField: `${DAILY_VOLUME_FACTORY}s`, + dailyDataField: "cstdayDatas", }), }, }, diff --git a/dexs/curve/index.ts b/dexs/curve/index.ts index 6b0d035615..9227d34d61 100644 --- a/dexs/curve/index.ts +++ b/dexs/curve/index.ts @@ -9,7 +9,9 @@ const endpoints: { [chain: string]: string } = { [CHAIN.ARBITRUM]: "https://api.curve.fi/api/getSubgraphData/arbitrum", [CHAIN.AVAX]: "https://api.curve.fi/api/getSubgraphData/avalanche", [CHAIN.OPTIMISM]: "https://api.curve.fi/api/getSubgraphData/optimism", - [CHAIN.XDAI]: "https://api.curve.fi/api/getSubgraphData/xdai" + [CHAIN.XDAI]: "https://api.curve.fi/api/getSubgraphData/xdai", + // [CHAIN.CELO]: "https://api.curve.fi/api/getSubgraphData/celo", + [CHAIN.FRAXTAL]: "https://api.curve.fi/api/getSubgraphData/fraxtal", }; interface IAPIResponse { @@ -22,12 +24,17 @@ interface IAPIResponse { } const fetch = (chain: string) => async (timestamp: number) => { - const response: IAPIResponse = (await fetchURL(endpoints[chain])); - const t = response.data.generatedTimeMs ? response.data.generatedTimeMs / 1000 : timestamp - return { - dailyVolume: `${response.data.totalVolume}`, - timestamp: t, - }; + try { + const response: IAPIResponse = (await fetchURL(endpoints[chain])); + const t = response.data.generatedTimeMs ? response.data.generatedTimeMs / 1000 : timestamp + return { + dailyVolume: `${response.data.totalVolume}`, + timestamp: t, + }; + } catch (e) { + return { timestamp } + } + }; const adapter: SimpleAdapter = { diff --git a/dexs/cyberperp/cyberperp.ts b/dexs/cyberperp/cyberperp.ts new file mode 100644 index 0000000000..456ff4db37 --- /dev/null +++ b/dexs/cyberperp/cyberperp.ts @@ -0,0 +1,48 @@ +import { request, gql } from "graphql-request"; +import { FetchOptions } from "../../adapters/types"; +import BigNumber from "bignumber.js"; + +const graphUrl = + "https://iota.graph.cyberperp.io/api/subgraphs/name/cyberLP-pool"; + +const getData = async (timestamp: number) => { + const query = gql` + { + volumeStats(first: 1, where: { period: daily, timestamp: ${timestamp} }) { + id + burn + margin + mint + swap + period + timestamp + } + } + `; + + const response = await request(graphUrl, query); + let dailyVolume = new BigNumber(0); + + if (response.volumeStats) { + const data = response.volumeStats[0]; + dailyVolume = dailyVolume + .plus(new BigNumber(data.mint)) + // .plus(new BigNumber(data.swap)) // is not list spot + .plus(new BigNumber(data.burn)) + .plus(new BigNumber(data.margin)) + .dividedBy(new BigNumber(1e30)); + } + const _dailyVolume = dailyVolume.toString(); + return { + dailyVolume: _dailyVolume, + timestamp: timestamp, + }; +}; + +export const fetchVolume = async (options: FetchOptions) => { + const data = await getData(options.startOfDay); + return { + dailyVolume: data.dailyVolume, + timestamp: data.timestamp, + }; +}; diff --git a/dexs/cyberperp/index.ts b/dexs/cyberperp/index.ts new file mode 100644 index 0000000000..55f5aefbb9 --- /dev/null +++ b/dexs/cyberperp/index.ts @@ -0,0 +1,14 @@ +import { SimpleAdapter } from "../../adapters/types"; +import { CHAIN } from "../../helpers/chains"; +import { fetchVolume } from "./cyberperp"; + +const adapter: SimpleAdapter = { + version: 2, + adapter: { + [CHAIN.IOTAEVM]: { + fetch: fetchVolume, + start: 1721692800, + }, + }, +}; +export default adapter; diff --git a/dexs/dackieswap-v2/index.ts b/dexs/dackieswap-v2/index.ts index ce39b804fd..595317504d 100644 --- a/dexs/dackieswap-v2/index.ts +++ b/dexs/dackieswap-v2/index.ts @@ -1,33 +1,27 @@ import customBackfill from "../../helpers/customBackfill"; -import { - DEFAULT_TOTAL_VOLUME_FACTORY, - DEFAULT_TOTAL_VOLUME_FIELD, - DEFAULT_DAILY_VOLUME_FACTORY, - DEFAULT_DAILY_VOLUME_FIELD -} from "../../helpers/getUniSubgraphVolume"; import {CHAIN} from "../../helpers/chains"; import type {ChainEndpoints, SimpleAdapter} from "../../adapters/types"; import type {Chain} from "@defillama/sdk/build/general"; -import {getGraphDimensions} from "../../helpers/getUniSubgraph"; +import { getGraphDimensions2} from "../../helpers/getUniSubgraph"; // Subgraphs endpoints const endpoints: ChainEndpoints = { [CHAIN.BASE]: "https://api.studio.thegraph.com/query/50473/subgraphs-exchange-v2/version/latest", [CHAIN.OPTIMISM]: "https://api.studio.thegraph.com/query/50473/v2-optimism/version/latest", [CHAIN.ARBITRUM]: "https://api.studio.thegraph.com/query/50473/v2-arbitrum/version/latest", + [CHAIN.BLAST]: "https://api.studio.thegraph.com/query/50473/v2-blast/version/latest", + [CHAIN.MODE]: "https://api.studio.thegraph.com/query/50473/v2-mode/version/latest", + [CHAIN.XLAYER]: "https://api.studio.thegraph.com/query/50473/v2-xlayer/version/latest", + [CHAIN.LINEA]: "https://api.studio.thegraph.com/query/50473/v2-linea/version/latest", }; // Fetch function to query the subgraphs -const graphs = getGraphDimensions({ +const graphs = getGraphDimensions2({ graphUrls: endpoints, totalVolume: { factory: "pancakeFactories", field: "totalVolumeUSD", }, - dailyVolume: { - factory: "pancakeDayData", - field: "dailyVolumeUSD", - }, feesPercent: { type: "volume", UserFees: 0.25, @@ -47,6 +41,7 @@ const methodology = { }; const adapter: SimpleAdapter = { + version: 2, adapter: Object.keys(endpoints).reduce((acc, chain) => { return { ...acc, @@ -56,7 +51,11 @@ const adapter: SimpleAdapter = { chain === CHAIN.BASE ? 1690173000 : chain === CHAIN.OPTIMISM ? 1705993200 : chain === CHAIN.ARBITRUM ? 1707885300 - : 0, + : chain === CHAIN.BLAST ? 1709722800 + : chain === CHAIN.MODE ? 1712371653 + : chain === CHAIN.XLAYER ? 1712369493 + : chain === CHAIN.LINEA ? 1725062400 + : 0, customBackfill: customBackfill(chain, graphs), meta: {methodology}, } diff --git a/dexs/dackieswap/index.ts b/dexs/dackieswap/index.ts index 7e5a2406f6..80e0130107 100644 --- a/dexs/dackieswap/index.ts +++ b/dexs/dackieswap/index.ts @@ -1,7 +1,6 @@ import { IJSON, SimpleAdapter } from "../../adapters/types"; import { CHAIN } from "../../helpers/chains"; - -import { getGraphDimensions } from "../../helpers/getUniSubgraph"; +import { getGraphDimensions2 } from "../../helpers/getUniSubgraph"; const v3Endpoint = { [CHAIN.BASE]: @@ -10,32 +9,34 @@ const v3Endpoint = { "https://api.studio.thegraph.com/query/50473/v3-optimism/version/latest", [CHAIN.ARBITRUM]: "https://api.studio.thegraph.com/query/50473/v3-arbitrum/version/latest", + [CHAIN.BLAST]: + "https://api.studio.thegraph.com/query/50473/v3-blast/version/latest", + [CHAIN.MODE]: + "https://api.studio.thegraph.com/query/50473/v3-mode/version/latest", + [CHAIN.XLAYER]: + "https://api.studio.thegraph.com/query/50473/v3-xlayer/version/latest", + [CHAIN.LINEA]: + "https://api.studio.thegraph.com/query/50473/v3-linea/version/latest", }; -const VOLUME_USD = "volumeUSD"; - -const v3Graph = getGraphDimensions({ +const v3Graph = getGraphDimensions2({ graphUrls: v3Endpoint, totalVolume: { factory: "factories", }, - dailyVolume: { - factory: "pancakeDayData", - field: VOLUME_USD, - }, - totalFees:{ + totalFees: { factory: "factories", }, - dailyFees: { - factory: "pancakeDayData", - field: "feesUSD" - }, }); const v3StartTimes = { [CHAIN.BASE]: 1691712000, [CHAIN.OPTIMISM]: 1705993200, [CHAIN.ARBITRUM]: 1707885300, + [CHAIN.BLAST]: 1722556800, + [CHAIN.MODE]: 1712371653, + [CHAIN.XLAYER]: 1712369493, + [CHAIN.LINEA]: 1725062400, } as IJSON; const adapter: SimpleAdapter = { @@ -52,7 +53,24 @@ const adapter: SimpleAdapter = { fetch: v3Graph(CHAIN.ARBITRUM), start: async () => v3StartTimes[CHAIN.ARBITRUM] }, + [CHAIN.BLAST]: { + fetch: v3Graph(CHAIN.BLAST), + start: async () => v3StartTimes[CHAIN.BLAST] + }, + [CHAIN.MODE]: { + fetch: v3Graph(CHAIN.MODE), + start: async () => v3StartTimes[CHAIN.MODE] + }, + [CHAIN.XLAYER]: { + fetch: v3Graph(CHAIN.XLAYER), + start: async () => v3StartTimes[CHAIN.XLAYER] + }, + [CHAIN.LINEA]: { + fetch: v3Graph(CHAIN.LINEA), + start: async () => v3StartTimes[CHAIN.LINEA] + }, }, + version: 2 }; export default adapter; diff --git a/dexs/dao-swap/index.ts b/dexs/dao-swap/index.ts index f78bdcaf51..934e9ab844 100644 --- a/dexs/dao-swap/index.ts +++ b/dexs/dao-swap/index.ts @@ -1,8 +1,9 @@ +import * as sdk from "@defillama/sdk"; import { CHAIN } from "../../helpers/chains"; import { univ2Adapter } from "../../helpers/getUniSubgraphVolume"; const adpters = univ2Adapter({ - [CHAIN.BSC]: "https://api.thegraph.com/subgraphs/name/daomaker/bsc-amm" + [CHAIN.BSC]: sdk.graph.modifyEndpoint('7APt1aJ4g5VJqcKF47if3kDjsNSG8mHPGv9YSt8Qf39i') }, { factoriesName: "pancakeFactories", dayData: "pancakeDayData", diff --git a/dexs/dedust/index.ts b/dexs/dedust/index.ts new file mode 100644 index 0000000000..60b107d34f --- /dev/null +++ b/dexs/dedust/index.ts @@ -0,0 +1,86 @@ +import { postURL } from "../../utils/fetchURL" +import { CHAIN } from "../../helpers/chains"; +import { FetchOptions, SimpleAdapter } from "../../adapters/types"; + +const GRAPHQL_ENDPOINT = 'https://api.dedust.io/v3/graphql'; + +const POOLS_QUERY = ` +query GetPools($filter: PoolsFiltersInput) { + pools(filter: $filter) { + address + totalSupply + type + tradeFee + assets + reserves + fees + volume + } + } +`; + +const ASSETS_QUERY = ` +query GetAssets { + assets { + type + address + symbol + decimals + price + } + } +`; + + +const fetch = async (options: FetchOptions) => { + const assetsList = (await postURL(GRAPHQL_ENDPOINT, { + query: ASSETS_QUERY, + operationName: 'GetAssets' + })).data.assets; + + const assetInfo = {}; + for (const asset of assetsList) { + const address = asset.type == 'native' ? 'native' : 'jetton:' + asset.address; + assetInfo[address] = { + decimals: asset.decimals, + price: Number(asset.price), + symbol: asset.symbol + } + } + + const poolsList = (await postURL(GRAPHQL_ENDPOINT, { + query: POOLS_QUERY, + operationName: 'GetPools' + })).data.pools; + + let dailyVolume = 0; + for (const pool of poolsList) { + const address = pool.address; + const leftAddr = pool.assets[0]; + const rightAddr = pool.assets[1]; + if (!(leftAddr in assetInfo && rightAddr in assetInfo)) { + continue; + } + const left = assetInfo[leftAddr]; + const right = assetInfo[rightAddr]; + + dailyVolume += (left.price * Number(pool.volume[0]) / Math.pow(10, left.decimals) + + right.price * Number(pool.volume[1]) / Math.pow(10, right.decimals)) / 2; + } + + return { + dailyVolume: dailyVolume + }; +}; + + +const adapter: SimpleAdapter = { + adapter: { + [CHAIN.TON]: { + fetch, + start: 1681931480, + }, + }, +}; + +export default adapter; diff --git a/dexs/defi-swap/index.ts b/dexs/defi-swap/index.ts index 78b5557ad7..f5da1304d4 100644 --- a/dexs/defi-swap/index.ts +++ b/dexs/defi-swap/index.ts @@ -1,8 +1,9 @@ +import * as sdk from "@defillama/sdk"; import { CHAIN } from "../../helpers/chains"; -import { univ2Adapter } from "../../helpers/getUniSubgraphVolume"; +import { univ2Adapter2 } from "../../helpers/getUniSubgraphVolume"; -const adapter = univ2Adapter({ - [CHAIN.ETHEREUM]: "https://api.thegraph.com/subgraphs/name/crypto-com/swap-subgraph" +const adapter = univ2Adapter2({ + [CHAIN.ETHEREUM]: sdk.graph.modifyEndpoint('G7W3G1JGcFbWseucNkHHvQorxyjQLEQt7vt9yPN97hri') }, { factoriesName: "factories", dayData: "dayData", diff --git a/dexs/defiplaza/index.ts b/dexs/defiplaza/index.ts index 3e0ee47f27..9e3e2357b5 100644 --- a/dexs/defiplaza/index.ts +++ b/dexs/defiplaza/index.ts @@ -1,3 +1,4 @@ +import * as sdk from "@defillama/sdk"; import request, { gql } from "graphql-request"; import { FetchResultGeneric, SimpleAdapter } from "../../adapters/types"; import { CHAIN } from "../../helpers/chains"; @@ -14,7 +15,7 @@ type RadixPlazaResponse = { swaps: number } -const thegraph_endpoints = "https://api.thegraph.com/subgraphs/name/omegasyndicate/defiplaza"; +const thegraph_endpoints = sdk.graph.modifyEndpoint('4z9FBF12CrfoQJhAkWicqzY2fKYN9QRmuzSsizVXhjKa'); const radix_endpoint = "https://radix.defiplaza.net/api/defillama/volume"; const adapter: SimpleAdapter = { diff --git a/dexs/delta-trade/index.ts b/dexs/delta-trade/index.ts new file mode 100644 index 0000000000..272ddfbe0a --- /dev/null +++ b/dexs/delta-trade/index.ts @@ -0,0 +1,29 @@ +import type { SimpleAdapter } from "../../adapters/types"; +import { getUniqStartOfTodayTimestamp } from "../../helpers/getUniSubgraphVolume"; +import { httpGet } from "../../utils/fetchURL"; + +const api = "https://api.deltatrade.ai/api/home/data"; + +const fetch = async () => { + const timestamp = getUniqStartOfTodayTimestamp(); + const res = await httpGet(api); + const { total_24h, total } = res.data; + + return { + timestamp, + dailyVolume: total_24h, + totalVolume: total, + }; +}; + +const adapter: SimpleAdapter = { + adapter: { + near: { + fetch, + start: 0, + runAtCurrTime: true, + }, + }, +}; + +export default adapter; diff --git a/dexs/deltaswap/index.ts b/dexs/deltaswap/index.ts index 8d8a4f5709..e2a32f291c 100644 --- a/dexs/deltaswap/index.ts +++ b/dexs/deltaswap/index.ts @@ -1,14 +1,8 @@ -import { SimpleAdapter } from "../../adapters/types"; import { CHAIN } from "../../helpers/chains"; -import { getDexVolumeExports } from "../../helpers/dexVolumeLogs"; +import { uniV2Exports } from "../../helpers/uniswap"; -const FACTORY_ADDRESS = '0xcb85e1222f715a81b8edaeb73b28182fa37cffa8' -const adapters: SimpleAdapter = { - adapter: { - [CHAIN.ARBITRUM]: { - fetch: getDexVolumeExports({ chain: CHAIN.MANTLE, factory: FACTORY_ADDRESS }), - start: 1706745600, - } - } -} -export default adapters; +export default uniV2Exports({ + [CHAIN.ARBITRUM]: { factory: '0xcb85e1222f715a81b8edaeb73b28182fa37cffa8', }, + [CHAIN.BASE]: { factory: '0x9a9a171c69cc811dc6b59bb2f9990e34a22fc971', }, + [CHAIN.ETHEREUM]: { factory: '0x5fbe219e88f6c6f214ce6f5b1fcaa0294f31ae1b', }, +}) diff --git a/dexs/dexalot/index.ts b/dexs/dexalot/index.ts index 64ed02bae4..cbf52c0780 100644 --- a/dexs/dexalot/index.ts +++ b/dexs/dexalot/index.ts @@ -1,51 +1,70 @@ -import { Chain } from "@defillama/sdk/build/general"; -import { SimpleAdapter } from "../../adapters/types"; +import { BaseAdapter, FetchOptions, FetchResult, SimpleAdapter } from "../../adapters/types"; import { CHAIN } from "../../helpers/chains"; -import customBackfill from "../../helpers/customBackfill"; -import { getUniqStartOfTodayTimestamp } from "../../helpers/getUniSubgraphVolume"; import { httpGet } from "../../utils/fetchURL"; -const historicalVolumeEndpoint = "https://api.dexalot.com/api/stats/dailyvolumes" +const historicalVolumeEndpoint = "https://api.dexalot.com/api/stats/chaindailyvolumes" interface IVolumeall { volumeusd: string; - date: number; + date: string; } -const fetch = async (timestamp: number) => { - const dayTimestamp = getUniqStartOfTodayTimestamp(new Date(timestamp * 1000)) - const historicalVolume: IVolumeall[] = (await httpGet(historicalVolumeEndpoint, { headers: { - 'origin': 'https://app.dexalot.com' - }})) - const totalVolume = historicalVolume - .filter(volItem => (new Date(volItem.date).getTime() / 1000) <= dayTimestamp) - .reduce((acc, { volumeusd }) => acc + Number(volumeusd), 0) - - const dailyVolume = historicalVolume - .find(dayItem => (new Date(dayItem.date).getTime() / 1000) === dayTimestamp)?.volumeusd - - return { - totalVolume: `${totalVolume}`, - dailyVolume: dailyVolume ? `${dailyVolume}` : undefined, - timestamp: dayTimestamp, - }; +const supportedChains = [CHAIN.DEXALOT, CHAIN.AVAX, CHAIN.ARBITRUM, CHAIN.BASE] + +const chainToEnv = (chain: CHAIN) => { + switch (chain) { + case CHAIN.AVAX: + return "production-multi-avax" + case CHAIN.ARBITRUM: + return "production-multi-arb" + case CHAIN.BASE: + return "production-multi-base" + default: + return "production-multi-subnet" + } +} + +const fetchFromChain = (chain: CHAIN) => { + const endpoint = `${historicalVolumeEndpoint}?env=${chainToEnv(chain)}` + + return async (_a:any, _t: any, options: FetchOptions): Promise => { + const dayTimestamp = new Date(options.startOfDay * 1000) + const dateStr = dayTimestamp.toISOString().split('T')[0] + const historicalVolume: IVolumeall[] = await httpGet(endpoint) + + const totalVolume = historicalVolume + .filter(volItem => new Date(volItem.date) <= dayTimestamp) + .reduce((acc, { volumeusd }) => acc + Number(volumeusd), 0) + const dailyVolume = historicalVolume + .find(dayItem => dayItem.date.split('T')[0] === dateStr)?.volumeusd + + return { + timestamp: options.startOfDay, + totalVolume: `${totalVolume}`, + dailyVolume: dailyVolume ? `${dailyVolume}` : undefined, + }; + } }; -const getStartTimestamp = async () => { - const historicalVolume: IVolumeall[] = (await httpGet(historicalVolumeEndpoint, { headers: { - 'origin': 'https://app.dexalot.com' - }})) - return (new Date(historicalVolume[0].date).getTime()) / 1000 +const getStartTimestamp = (chain: CHAIN) => { + const endpoint = `${historicalVolumeEndpoint}?env=${chainToEnv(chain)}` + return async () => { + const historicalVolume: IVolumeall[] = await httpGet(endpoint) + return (new Date(historicalVolume[0].date).getTime()) / 1000 + } } const adapter: SimpleAdapter = { - adapter: { - [CHAIN.AVAX]: { - fetch, - start: getStartTimestamp, - customBackfill: customBackfill(CHAIN.AVAX as Chain, (_chian: string) => fetch) - }, - }, + version: 1, + adapter: supportedChains.reduce((acc, chain) => { + return { + ...acc, + [chain]: { + fetch: fetchFromChain(chain), + start: getStartTimestamp(chain), + } + } + }, {} as BaseAdapter), }; export default adapter; diff --git a/dexs/dexswap/index.ts b/dexs/dexswap/index.ts new file mode 100644 index 0000000000..339fe741f1 --- /dev/null +++ b/dexs/dexswap/index.ts @@ -0,0 +1,71 @@ +import * as sdk from "@defillama/sdk"; +import { FetchOptions } from "../../adapters/types" +import request, { gql } from "graphql-request"; +import { SimpleAdapter } from "../../adapters/types"; +import { CHAIN } from "../../helpers/chains"; +import BigNumber from "bignumber.js"; +import { uniV2Exports } from "../../helpers/uniswap"; + +const FACTORY_ADDRESS = '0x3e40739d8478c58f9b973266974c58998d4f9e8b'; + +const endpoints = { + [CHAIN.ARBITRUM]: sdk.graph.modifyEndpoint('AaAYom6ATrw15xZq3LJijLHsBj8xWdcL11Xg6sCxEBqZ'), + }; + +const startDate = 1684702800; + + +const feeAdapter = uniV2Exports({ + [CHAIN.ARBITRUM]: { factory: FACTORY_ADDRESS, }, +}).adapter[CHAIN.ARBITRUM].fetch + + +const fetch = async (options: FetchOptions) => { + const dataFactory = await request(endpoints[options.chain], gql + `{ + dexSwapFactories { + totalVolumeETH + } + }` + ) + const totalVolume = dataFactory.dexSwapFactories[0].totalVolumeETH; + let totalFees = new BigNumber(0); + let date = startDate; + let skip = 0; + while (true) { + const dataFees = await request(endpoints[options.chain], gql + `query DexSwapFees { + dexSwapFees(first: 1000,skip: ${skip}, orderBy: timestamp, where: { timestamp_gt: ${date}, timestamp_lte: ${options.endTimestamp} }) { + volume, + timestamp + } + }` + ) + if (!dataFees.dexSwapFees.length) break; + if (dataFees.dexSwapFees.length === 1000) { + skip += 1000; + } + dataFees.dexSwapFees.forEach((data) => { + totalFees = totalFees.plus(data.volume); + }) + if (dataFees.dexSwapFees.length < 1000) break; + } + const dailyData = await feeAdapter(options as any, {}, options); + return { + ...dailyData, + totalVolume, + totalFees: totalFees.div(10 ** 18).toString(), + } +} + +const adapter: SimpleAdapter = { + version: 2, + adapter: { + [CHAIN.ARBITRUM]: { + fetch, + start: startDate, + }, + } +}; + +export default adapter; diff --git a/dexs/dfyn/index.ts b/dexs/dfyn/index.ts index d2e680ffb1..ccf9181bb8 100644 --- a/dexs/dfyn/index.ts +++ b/dexs/dfyn/index.ts @@ -1,7 +1,8 @@ +import * as sdk from "@defillama/sdk"; import { univ2Adapter } from "../../helpers/getUniSubgraphVolume"; import { CHAIN } from "../../helpers/chains"; // Not complete! Missing older versions export default univ2Adapter({ - [CHAIN.POLYGON]: "https://api.thegraph.com/subgraphs/name/ss-sonic/dfyn-v4", + [CHAIN.POLYGON]: sdk.graph.modifyEndpoint('Dizc6HBJZWB276wcyycYMxN8FMKeKb7RpSvwu83F4gTc'), }, {}); \ No newline at end of file diff --git a/dexs/dinosaur-eggs/index.ts b/dexs/dinosaur-eggs/index.ts index 6715a45d2a..9577be2031 100644 --- a/dexs/dinosaur-eggs/index.ts +++ b/dexs/dinosaur-eggs/index.ts @@ -1,8 +1,9 @@ +import * as sdk from "@defillama/sdk"; import { CHAIN } from "../../helpers/chains"; import { univ2Adapter } from "../../helpers/getUniSubgraphVolume"; const adapters = univ2Adapter({ - [CHAIN.BSC]: "https://api.thegraph.com/subgraphs/name/dinosaur-eggs/swap" + [CHAIN.BSC]: sdk.graph.modifyEndpoint('63auEwyBju1rZWUNZ32k2qwrBQZSEU4XetvKh3ZCwHLA') }, { factoriesName: "swapFactories", dayData: "swapDayData" diff --git a/dexs/dodo/index.ts b/dexs/dodo/index.ts index 2c76d0fe09..c43ef6d1c8 100644 --- a/dexs/dodo/index.ts +++ b/dexs/dodo/index.ts @@ -1,9 +1,8 @@ -import { Adapter, ChainEndpoints, Fetch, IStartTimestamp, SimpleAdapter } from "../../adapters/types"; +import { Fetch, FetchOptions, IStartTimestamp, SimpleAdapter } from "../../adapters/types"; import { CHAIN } from "../../helpers/chains"; import { getUniqStartOfTodayTimestamp } from "../../helpers/getUniSubgraphVolume"; import { postURL } from "../../utils/fetchURL"; import dailyVolumePayload from "./dailyVolumePayload"; -import totalVolumePayload from "./totalVolumePayload"; /* const endpoints = { [CHAIN.ARBITRUM]: "https://api.dodoex.io/graphql?opname=FetchDashboardDailyData", @@ -11,9 +10,9 @@ import totalVolumePayload from "./totalVolumePayload"; [CHAIN.BSC]: "https://api.dodoex.io/graphql?opname=FetchDashboardDailyData", [CHAIN.ETHEREUM]: "https://api.dodoex.io/graphql?opname=FetchDashboardDailyData", [CHAIN.POLYGON]: "https://api.dodoex.io/graphql?opname=FetchDashboardDailyData", - // [MOONRIVER]: "https://api.thegraph.com/subgraphs/name/dodoex/dodoex-v2-moonriver", - // [AVAX]: "https://api.thegraph.com/subgraphs/name/dodoex/dodoex-v2-avax", - // [BOBA]: "https://api.thegraph.com/subgraphs/name/dodoex/dodoex-v2-boba" + // [MOONRIVER]: sdk.graph.modifyEndpoint('G4HFPFJue7zf2BktJuKETh72DscimLJRybVA6iD6A7yM'), + // [AVAX]: sdk.graph.modifyEndpoint('8GUXi8PNrW4ACf968KCWxH9AkeNt8YEQin7MDa7RuULW'), + // [BOBA]: sdk.graph.modifyEndpoint('6PVfSucTfTimvx3aMgWsatmRDBNxW7yQKayyZ7Mxrf73') // [HECO]: "https://n10.hg.network/subgraphs/name/dodoex-mine-v3-heco/heco", // [OKEXCHAIN]: "https://graph.kkt.one/subgraphs/name/dodoex/dodoex-v2-okchain", } as ChainEndpoints */ @@ -53,8 +52,8 @@ interface ITotalResponse { } } -const getFetch = (chain: string): Fetch => async (timestamp: number) => { - const dayTimestamp = getUniqStartOfTodayTimestamp(new Date(timestamp * 1000)) +const getFetch = (chain: string): Fetch => async (_ts: number, _t: any, options: FetchOptions) => { + const dayTimestamp = getUniqStartOfTodayTimestamp(new Date(options.startOfDay * 1000)) const dailyResponse = (await postURL(dailyEndpoint, dailyVolumePayload(chain))) as IDailyResponse // const totalResponse = (await postURL(totalEndpoint, totalVolumePayload(chain))) as ITotalResponse @@ -95,7 +94,10 @@ const volume = chains.reduce( {} ); + const adapter: SimpleAdapter = { adapter: volume }; -export default adapter; + + +export default adapter diff --git a/dexs/doveswap/index.ts b/dexs/doveswap/index.ts index 18be32c56f..c8ec1c0b45 100644 --- a/dexs/doveswap/index.ts +++ b/dexs/doveswap/index.ts @@ -1,60 +1,47 @@ import { Chain } from "@defillama/sdk/build/general"; -import { BreakdownAdapter, FetchResultGeneric, BaseAdapter } from "../../adapters/types"; +import { BreakdownAdapter, BaseAdapter } from "../../adapters/types"; import { CHAIN } from "../../helpers/chains"; -import { getStartTimestamp } from "../../helpers/getStartTimestamp"; - import { - getGraphDimensions, - DEFAULT_DAILY_VOLUME_FACTORY, DEFAULT_TOTAL_VOLUME_FIELD, -} from "../../helpers/getUniSubgraph" -import { type } from "os"; - + getGraphDimensions2, +} from "../../helpers/getUniSubgraph"; const v3Endpoints = { [CHAIN.POLYGON_ZKEVM]: "https://api.studio.thegraph.com/query/47443/v3-test/v0.0.5", - }; -const VOLUME_USD = "volumeUSD"; - - -const v3Graphs = getGraphDimensions({ +const v3Graphs = getGraphDimensions2({ graphUrls: v3Endpoints, totalVolume: { factory: "factories", field: DEFAULT_TOTAL_VOLUME_FIELD, }, - dailyVolume: { - factory: DEFAULT_DAILY_VOLUME_FACTORY, - field: VOLUME_USD, - }, feesPercent: { type: "fees", ProtocolRevenue: 25, HoldersRevenue: 0, // Holders get no revenue directly for now because buy and burn mechanism is in place UserFees: 100, // User fees are 100% of collected fees SupplySideRevenue: 75, // 75% of fees are going to LPs - Revenue: 100 // Revenue is 100% of collected fees - } + Revenue: 100, // Revenue is 100% of collected fees + }, }); const methodology = { UserFees: "User pays 0.01%, 0.05%, 0.30%, or 1% on each swap.", ProtocolRevenue: "Protocol has revenue.", SupplySideRevenue: "75% of user fees are distributed among LPs.", - HoldersRevenue: "Holders have no revenue." -} + HoldersRevenue: "Holders have no revenue.", +}; type TStartTime = { [key: string]: number; -} -const startTimeV3:TStartTime = { - [CHAIN.POLYGON_ZKEVM]: 1679875200, - -} +}; +const startTimeV3: TStartTime = { + [CHAIN.POLYGON_ZKEVM]: 1679875200, +}; const adapter: BreakdownAdapter = { + version: 2, breakdown: { v3: Object.keys(v3Endpoints).reduce((acc, chain) => { acc[chain] = { @@ -63,13 +50,13 @@ const adapter: BreakdownAdapter = { meta: { methodology: { ...methodology, - UserFees: "User pays 0.01%, 0.05%, 0.30%, or 1% on each swap." - } - } - } - return acc - }, {} as BaseAdapter) - } -} + UserFees: "User pays 0.01%, 0.05%, 0.30%, or 1% on each swap.", + }, + }, + }; + return acc; + }, {} as BaseAdapter), + }, +}; export default adapter; diff --git a/dexs/dpex/index.ts b/dexs/dpex/index.ts index 89cd0f967a..063985de84 100644 --- a/dexs/dpex/index.ts +++ b/dexs/dpex/index.ts @@ -1,3 +1,4 @@ +import * as sdk from "@defillama/sdk"; import request, { gql } from "graphql-request"; import { Fetch, SimpleAdapter } from "../../adapters/types"; import { CHAIN } from "../../helpers/chains"; @@ -5,7 +6,7 @@ import { getUniqStartOfTodayTimestamp } from "../../helpers/getUniSubgraphVolume import customBackfill from "../../helpers/customBackfill"; const endpoints: { [key: string]: string } = { - [CHAIN.POLYGON]: "https://api.thegraph.com/subgraphs/name/dpex-io/core", + [CHAIN.POLYGON]: sdk.graph.modifyEndpoint('2k6i4iv8DHfp7ZdimWZvc4jGY3NR5oPeAaDx43zszuUj'), } const historicalDataSwap = gql` diff --git a/dexs/dragonswap-sei/index.ts b/dexs/dragonswap-sei/index.ts new file mode 100644 index 0000000000..12a9d3828f --- /dev/null +++ b/dexs/dragonswap-sei/index.ts @@ -0,0 +1,35 @@ +import request, { gql } from "graphql-request"; +import { FetchOptions, SimpleAdapter } from "../../adapters/types"; +import { CHAIN } from "../../helpers/chains"; + +const fetch = async (timestamp: number, _:any, options: FetchOptions): Promise => { + const dayID = Math.floor(options.startOfDay / 86400); + const query =gql` + { + uniswapDayData(id:${dayID}) { + id + dailyVolumeUSD + } + uniswapFactories { + totalVolumeUSD + } + }`; + const url = "https://api.goldsky.com/api/public/project_clu1fg6ajhsho01x7ajld3f5a/subgraphs/dragonswap-prod/1.0.0/gn"; + const req = await request(url, query); + return { + dailyVolume: req.uniswapDayData.dailyVolumeUSD, + totalVolume: req.uniswapFactories[0].totalVolumeUSD, + timestamp: timestamp, + } +} + +const adapter: SimpleAdapter = { + adapter: { + [CHAIN.SEI]: { + fetch, + start: 1716854400, + }, + } +} + +export default adapter; diff --git a/dexs/dragonswap/index.ts b/dexs/dragonswap/index.ts index 5860ea9e3f..e1ecef611e 100644 --- a/dexs/dragonswap/index.ts +++ b/dexs/dragonswap/index.ts @@ -1,7 +1,7 @@ import { Chain } from "@defillama/sdk/build/types"; import { BaseAdapter, BreakdownAdapter, IJSON } from "../../adapters/types"; import { CHAIN } from "../../helpers/chains"; -import { getGraphDimensions } from "../../helpers/getUniSubgraph"; +import { getGraphDimensions2 } from "../../helpers/getUniSubgraph"; const endpoints = { [CHAIN.KLAYTN]: "https://graph.dgswap.io/subgraphs/name/dragonswap/exchange-v2", @@ -11,8 +11,6 @@ const v3Endpoint = { [CHAIN.KLAYTN]: "https://graph.dgswap.io/subgraphs/name/dragonswap/exchange-v3", }; -const VOLUME_USD = "volumeUSD"; - const startTimes = { [CHAIN.KLAYTN]: 1707297572, } as IJSON; @@ -30,7 +28,7 @@ const methodology = { Fees: "All fees comes from the user." } -const graphs = getGraphDimensions({ +const graphs = getGraphDimensions2({ graphUrls: endpoints, graphRequestHeaders: { [CHAIN.KLAYTN]: { @@ -40,9 +38,6 @@ const graphs = getGraphDimensions({ totalVolume: { factory: "pancakeFactories" }, - dailyVolume: { - factory: "pancakeDayData" - }, feesPercent: { type: "volume", Fees: 0.3, @@ -54,25 +49,18 @@ const graphs = getGraphDimensions({ } }); -const v3Graph = getGraphDimensions({ +const v3Graph = getGraphDimensions2({ graphUrls: v3Endpoint, totalVolume: { factory: "factories", }, - dailyVolume: { - factory: "pancakeDayData", - field: VOLUME_USD - }, totalFees: { factory: "factories", }, - dailyFees: { - factory: "pancakeDayData", - field: "feesUSD" - }, }); const adapter: BreakdownAdapter = { + version: 2, breakdown: { v2: Object.keys(endpoints).reduce((acc, chain) => { acc[chain] = { @@ -86,14 +74,7 @@ const adapter: BreakdownAdapter = { }, {} as BaseAdapter), v3: Object.keys(v3Endpoint).reduce((acc, chain) => { acc[chain] = { - fetch: async (timestamp: number) => { - const v3stats = await v3Graph(chain)(timestamp, {}) - return { - ...v3stats, - timestamp - } - - }, + fetch: v3Graph(chain), start: v3StartTimes[chain], } return acc diff --git a/dexs/drift-protocol/index.ts b/dexs/drift-protocol/index.ts index b9994f4ff6..a55e241857 100644 --- a/dexs/drift-protocol/index.ts +++ b/dexs/drift-protocol/index.ts @@ -1,47 +1,80 @@ import { CHAIN } from "../../helpers/chains"; -import { httpGet } from "../../utils/fetchURL"; - -const dailyVolEndpoint = - "https://mainnet-beta.api.drift.trade/stats/24HourVolume"; - -async function fetch(type: "perp" | "spot") { - const volumeResponse = await httpGet( - `${dailyVolEndpoint}?${ - type === "perp" ? "perpMarkets" : "spotMarkets" - }=true` - ); - - const rawVolumeQuotePrecision = volumeResponse.data.volume; - - // Volume will be returned in 10^6 precision - const volumeNumber = - rawVolumeQuotePrecision.length >= 6 - ? Number(rawVolumeQuotePrecision.slice(0, -6)) - : 0; - - return { - dailyVolume: volumeNumber, - timestamp: Date.now() / 1e3, - }; +import { queryDune } from "../../helpers/dune"; +import { BreakdownAdapter, FetchOptions } from "../../adapters/types"; + +// const DUNE_QUERY_ID = "3756979"; // https://dune.com/queries/3756979/6318568 +const DUNE_QUERY_ID = "4057938"; // Should be faster than the above - https://dune.com/queries/3782153/6359334 + +type DimentionResult = { + dailyVolume?: number; + dailyFees?: number; + dailyUserFees?: number; + dailyRevenue?: number; +}; + +type IRequest = { + [key: string]: Promise; +} +const requests: IRequest = {} + +export async function fetchURLWithRetry(url: string, options: FetchOptions) { + const start = options.startOfDay; + const key = `${url}-${start}`; + if (!requests[key]) + requests[key] = queryDune("4117889", { + start: start, + end: start + 24 * 60 * 60, + }) + return requests[key] +} + +async function getPerpDimensions(options: FetchOptions): Promise { + const volumeResponse = await fetchURLWithRetry("4117889", options) + const dailyVolume = volumeResponse[0].perpetual_volume; + const dailyFees = volumeResponse[0].total_taker_fee; + const dailyRevenue = volumeResponse[0].total_revenue; + return { dailyVolume, dailyFees, dailyRevenue }; +} + +async function getSpotDimensions(options: FetchOptions): Promise { + const volumeResponse = await fetchURLWithRetry("4117889", options) + const dailyVolume = volumeResponse[0].spot_volume; + return { dailyVolume }; +} + +async function fetch(type: "perp" | "spot", options: FetchOptions) { + const timestamp = Date.now() / 1e3; + if (type === "perp") { + const results = await getPerpDimensions(options); + return { + ...results, + timestamp, + }; + } else { + const results = await getSpotDimensions(options); + return { + ...results, + timestamp: Date.now() / 1e3, + }; + } } -const adapter = { +const adapter: BreakdownAdapter = { breakdown: { swap: { [CHAIN.SOLANA]: { - fetch: () => fetch("spot"), - runAtCurrTime: true, + fetch: (_t: any, _tt: any, options: FetchOptions) => fetch("spot", options), start: 1690239600, }, }, derivatives: { [CHAIN.SOLANA]: { - fetch: () => fetch("perp"), - runAtCurrTime: true, + fetch: (_t: any, _tt: any, options: FetchOptions) => fetch("perp", options), start: 1690239600, }, }, }, + isExpensiveAdapter: true, }; export default adapter; diff --git a/dexs/dusa/index.ts b/dexs/dusa/index.ts new file mode 100644 index 0000000000..accf6ae334 --- /dev/null +++ b/dexs/dusa/index.ts @@ -0,0 +1,39 @@ +import { Adapter, FetchOptions } from "../../adapters/types"; +import fetchURL from "../../utils/fetchURL"; + +type TEndpoint = { + [s: string]: string; +}; + +const endpoints: TEndpoint = { + ["massa"]: "https://api-mainnet-dusa.up.railway.app/api/volume", +}; + +const fetchVolume = async (options: FetchOptions) => { + const historicalVolume = await fetchURL(`${endpoints["massa"]}?take=${options.endTimestamp}`); + + const totalVolume = historicalVolume.totalVolume.volume; + const dailyVolume = historicalVolume.dailyVolume.volume; + + const dailyFees = historicalVolume.dailyVolume.fees; + const totalFee = historicalVolume.totalVolume.fees; + + return { + totalVolume: `${totalVolume}`, + dailyVolume: dailyVolume !== undefined ? `${dailyVolume}` : undefined, + dailyFees: `${dailyFees}`, + totalFees: `${totalFee}`, + }; +}; + +const adapter: Adapter = { + version: 2, + adapter: { + massa: { + fetch: fetchVolume, + start: 1713170000 + }, + } +} + +export default adapter; diff --git a/dexs/dystopia/index.ts b/dexs/dystopia/index.ts index 87a2d83321..68db3cc15c 100644 --- a/dexs/dystopia/index.ts +++ b/dexs/dystopia/index.ts @@ -1,8 +1,9 @@ +import * as sdk from "@defillama/sdk"; import { CHAIN } from "../../helpers/chains"; import { univ2Adapter } from "../../helpers/getUniSubgraphVolume"; const adapters = univ2Adapter({ - [CHAIN.POLYGON]: "https://api.thegraph.com/subgraphs/name/dystopia-exchange/dystopia" + [CHAIN.POLYGON]: sdk.graph.modifyEndpoint('A1pnYfdxjPz6WMTRtmhyFKYDvwSuAyAdckwsUVWvgd6F') }, {}); adapters.adapter.polygon.start = 1652932015; export default adapters; diff --git a/dexs/econia/index.ts b/dexs/econia/index.ts index bebcab86dd..5f0eebe312 100644 --- a/dexs/econia/index.ts +++ b/dexs/econia/index.ts @@ -25,7 +25,7 @@ const fetch = async (timestamp: number) => { markets.map(async m => await fetchURL(`${BASE_URL}/rpc/volume_history?market_id=${m.market_id}&time=${dayISO}`) .then(res => ( - { daily: res[0].daily * m.tick_size / 1000000, total: res[0].total * m.tick_size / 1000000 } + { daily: res[0].daily / 1000000, total: res[0].total / 1000000 } )) ) ); @@ -34,9 +34,24 @@ const fetch = async (timestamp: number) => { return { daily: prev.daily + curr.daily, total: prev.total + curr.total }; }, {daily: 0, total: 0}); + const feesPerMarket = await Promise.all( + markets.map(async m => + await fetchURL(`${BASE_URL}/rpc/fees?market_id=${m.market_id}&time=${dayISO}`) + .then(res => ( + { daily: res[0].daily / 1000000, total: res[0].total / 1000000 } + )) + ) + ); + + const fees = feesPerMarket.reduce((prev, curr) => { + return { daily: prev.daily + curr.daily, total: prev.total + curr.total }; + }, { daily: 0, total: 0 }); + let res = { totalVolume: `${volumes.total}`, dailyVolume: `${volumes.daily}`, + dailyFees: `${fees.daily}`, + totalFees: `${fees.total}`, timestamp: dayTimestamp, }; diff --git a/dexs/edgeX/index.ts b/dexs/edgeX/index.ts new file mode 100644 index 0000000000..12670dee6e --- /dev/null +++ b/dexs/edgeX/index.ts @@ -0,0 +1,64 @@ +import fetchURL from "../../utils/fetchURL" +import { FetchResultVolume, SimpleAdapter } from "../../adapters/types"; +import { CHAIN } from "../../helpers/chains"; +import { getUniqStartOfTodayTimestamp } from "../../helpers/getUniSubgraphVolume"; + +const metaDataEndpoint = "https://pro.edgex.exchange/api/v1/public/meta/getMetaData" +const klineDailyEndpoint = (contractId: string, startTime: number, endTime: number) => `https://pro.edgex.exchange/api/v1/public/quote/getKline?contractId=${contractId}&klineType=DAY_1&filterBeginKlineTimeInclusive=${startTime}&filterEndKlineTimeExclusive=${endTime}&priceType=LAST_PRICE` + +interface KlineData { + contractId: string; + contractName: string; + klineType: string; + klineTime: string; + priceType: string; + trades: string; + size: string; + value: string; +} + +interface ResponseData { + dataList: KlineData[]; +} + +interface ApiResponse { + code: string; + data: ResponseData; + msg: string | null; + errorParam: string | null; +} + +function parseContractIds(response: any): string[] { + return response.data.contractList.map(contract => contract.contractId); +} + + +const fetch = async (timestamp: number): Promise => { + const dayTimestamp = getUniqStartOfTodayTimestamp(new Date(timestamp * 1000)) * 1000 + const toTimestamp = dayTimestamp + 60 * 60 * 24 * 1000; + const contractIds: string[] = [ + '10000001', '10000002', + '10000003', '10000004', + '10000005', '10000006', + '10000007', '10000008', + '10000009', '10000010' + ] + const klines = (await Promise.all(contractIds.map(async (contractId) => fetchURL(klineDailyEndpoint(contractId, dayTimestamp, toTimestamp))))) + .map((response: ApiResponse) => response.data.dataList); + const volumes = klines + .flat() + .map(kline => parseFloat(kline.value)) + .reduce((acc, value) => acc + value, 0); + return { dailyVolume: volumes, timestamp: toTimestamp / 1000 - 1 }; +}; + +const adapter: SimpleAdapter = { + adapter: { + [CHAIN.ETHEREUM]: { + fetch, + start: 1722902400, + }, + }, +}; + +export default adapter; diff --git a/dexs/el-dorado-exchange/index.ts b/dexs/el-dorado-exchange/index.ts index 7293b34417..79da73b86d 100644 --- a/dexs/el-dorado-exchange/index.ts +++ b/dexs/el-dorado-exchange/index.ts @@ -1,11 +1,13 @@ +import * as sdk from "@defillama/sdk"; import request, { gql } from "graphql-request"; -import {BreakdownAdapter, Fetch, SimpleAdapter} from "../../adapters/types"; +import {BreakdownAdapter, DISABLED_ADAPTER_KEY, Fetch, SimpleAdapter} from "../../adapters/types"; import { CHAIN } from "../../helpers/chains"; import { getUniqStartOfTodayTimestamp } from "../../helpers/getUniSubgraphVolume"; +import disabledAdapter from "../../helpers/disabledAdapter"; const endpoints: { [key: string]: string } = { - // [CHAIN.BSC]: "https://api.thegraph.com/subgraphs/name/metaverseblock/ede_stats_elpall_test", - [CHAIN.ARBITRUM]: "https://api.thegraph.com/subgraphs/name/metaverseblock/ede_state_elp1_arbitrimone", + // [CHAIN.BSC]: sdk.graph.modifyEndpoint('FiegiatdkorjPCvK72UyHvmJHvWtS3oQS6zwnR94Xe7c'), + [CHAIN.ARBITRUM]: sdk.graph.modifyEndpoint('G3wquxtaw68uX5GAZ7XBPWK8Fa7Buf66Y27uT8erqQZ4'), } const historicalDataSwap = gql` @@ -79,12 +81,15 @@ const startTimestamps: { [chain: string]: number } = { const adapter: BreakdownAdapter = { + breakdown: { + "swap": Object.keys(endpoints).reduce((acc, chain) => { return { ...acc, + [DISABLED_ADAPTER_KEY]: disabledAdapter, [chain]: { - fetch: getFetch(historicalDataSwap)(chain), + fetch: async (timestamp: number) => {return {timestamp}}, start: startTimestamps[chain] } } @@ -92,8 +97,9 @@ const adapter: BreakdownAdapter = { "derivatives": Object.keys(endpoints).reduce((acc, chain) => { return { ...acc, + [DISABLED_ADAPTER_KEY]: disabledAdapter, [chain]: { - fetch: getFetch(historicalDataDerivatives)(chain), + fetch: async (timestamp: number) => {return {timestamp}}, start: startTimestamps[chain] } } diff --git a/dexs/elektrik/index.ts b/dexs/elektrik/index.ts index 799229d408..18b2659856 100644 --- a/dexs/elektrik/index.ts +++ b/dexs/elektrik/index.ts @@ -1,24 +1,21 @@ import { SimpleAdapter } from "../../adapters/types"; -import { DEFAULT_TOTAL_VOLUME_FIELD, getChainVolume } from "../../helpers/getUniSubgraphVolume"; +import { DEFAULT_TOTAL_VOLUME_FIELD, getChainVolume2 } from "../../helpers/getUniSubgraphVolume"; import { CHAIN } from "../../helpers/chains"; const endpoints = { [CHAIN.LIGHTLINK_PHOENIX]: "https://subgraph.elektrik.network/subgraphs/name/ELEKTRIK-GRAPH", }; -const graphs = getChainVolume({ +const graphs = getChainVolume2({ graphUrls: endpoints, totalVolume: { factory: "factories", field: DEFAULT_TOTAL_VOLUME_FIELD, }, - dailyVolume: { - factory: "uniswapDayData", - field: "volumeUSD", - }, }); const adapter: SimpleAdapter = { + version: 2, adapter: { [CHAIN.LIGHTLINK_PHOENIX]: { fetch: graphs(CHAIN.LIGHTLINK_PHOENIX), diff --git a/dexs/elk/index.ts b/dexs/elk/index.ts index 361ac43fea..92d2f906b6 100644 --- a/dexs/elk/index.ts +++ b/dexs/elk/index.ts @@ -1,20 +1,21 @@ +import * as sdk from "@defillama/sdk"; import { univ2Adapter } from "../../helpers/getUniSubgraphVolume"; import { CHAIN } from "../../helpers/chains"; const adapter = univ2Adapter({ - [CHAIN.ARBITRUM]: "https://api.thegraph.com/subgraphs/name/elkfinance/elkdex-arbitrum", - [CHAIN.AVAX]: "https://api.thegraph.com/subgraphs/name/elkfinance/elkdex-avax", - [CHAIN.BSC]: "https://api.thegraph.com/subgraphs/name/elkfinance/elkdex-bsc", - [CHAIN.FANTOM]: "https://api.thegraph.com/subgraphs/name/elkfinance/elkdex-ftm", - [CHAIN.POLYGON]: "https://api.thegraph.com/subgraphs/name/elkfinance/elkdex-matic", + [CHAIN.ARBITRUM]: sdk.graph.modifyEndpoint('B8TGNwQ8xMoeFCdsv9dPkciRBpEYAy1UxmXDr7nc9fpE'), + [CHAIN.AVAX]: sdk.graph.modifyEndpoint('2dyce92CewvhV17C8BMFoMCgaXdPTtwBzaz8AReQR3YV'), + [CHAIN.BSC]: sdk.graph.modifyEndpoint('5tRz9anigEVND48Gx1mUpNNM4YSm3NpzG9XRB8dYAMhb'), + [CHAIN.FANTOM]: sdk.graph.modifyEndpoint('pmqe2dQvH4PK7aaFh4GXrr49wpKRr3GjPCnNEgEb6U2'), + [CHAIN.POLYGON]: sdk.graph.modifyEndpoint('8jzpT6nnKgmqcdGocys97YWkuqwDbHBxpozsKcxH1KUP'), // [CHAIN.HECO]: "https://api.thegraph.com/subgraphs/name/elkfinance/elkdex-heco" - [CHAIN.XDAI]: "https://api.thegraph.com/subgraphs/name/elkfinance/elkdex-xdai", + [CHAIN.XDAI]: sdk.graph.modifyEndpoint('kD9njskfB9xv7gDnsU2sz4X4sXfEimBv8xMJ6votFND'), // [CHAIN.MOONRIVER]: "https://moonriver-graph.elk.finance/subgraphs/name/elkfinance/elkdex-moonriver", // [CHAIN.ELASTOS]: "https://elastos-graph.elk.finance/subgraphs/name/elkfinance/elkdex-elastos", // [CHAIN.OKEXCHAIN]: "https://okex-graph.elk.finance/subgraphs/name/elkfinance/elkdex-okex", // [CHAIN.KCC]: "https://kcc-graph.elk.finance/subgraphs/name/elkfinance/elkdex-kcc", - [CHAIN.ETHEREUM]: "https://api.thegraph.com/subgraphs/name/elkfinance/elkdex-eth", - [CHAIN.OPTIMISM]: "https://api.thegraph.com/subgraphs/name/elkfinance/elkdex-optimism", + [CHAIN.ETHEREUM]: sdk.graph.modifyEndpoint('59tcH5BPyXj41XZgn1ZYy4pE8iDdzaZpR9MRhmuPW4Lr'), + [CHAIN.OPTIMISM]: sdk.graph.modifyEndpoint('H7UcKWuAqQPqWKcnNLn2Jamy9zE7wVgsLSRQpPwXo2Ag'), // [CHAIN.CRONOS]: "https://cronos-graph.elk.finance/subgraphs/name/elkfinance/elkdex-cronos", // [CHAIN.FUSE]: "https://fuse-graph.elk.finance/subgraphs/name/elkfinance/elkdex-fuse", // [CHAIN.IOTEX]: "https://iotex-graph.elk.finance/subgraphs/name/elkfinance/elkdex-iotex", diff --git a/dexs/empiredex/index.ts b/dexs/empiredex/index.ts index 3bc4ec8bce..a795b4f047 100644 --- a/dexs/empiredex/index.ts +++ b/dexs/empiredex/index.ts @@ -1,10 +1,11 @@ +import * as sdk from "@defillama/sdk"; import { CHAIN } from "../../helpers/chains"; import { univ2Adapter } from "../../helpers/getUniSubgraphVolume"; export default univ2Adapter({ - [CHAIN.BSC]: "https://api.thegraph.com/subgraphs/name/trnhgquan/empiredexbsc", + [CHAIN.BSC]: sdk.graph.modifyEndpoint('6YsqBAMACpzsx2GktPSfCcfAs1C4WZzqcUk1mBWwFxtN'), [CHAIN.XDAI]: "https://api.thegraph.com/subgraphs/name/zikyfranky/empire-xdai", - [CHAIN.POLYGON]: "https://api.thegraph.com/subgraphs/name/zikyfranky/empire-polygon", - [CHAIN.AVAX]: "https://api.thegraph.com/subgraphs/name/zikyfranky/empire-subgraph-avax", + [CHAIN.POLYGON]: sdk.graph.modifyEndpoint('57ZPKjowRMAcH4j4pTz6Aig2wm4LyjUStuUiETVRTmdF'), + [CHAIN.AVAX]: sdk.graph.modifyEndpoint('BpubdJRtMZpkrodAbbkm43m8d3AeT5tBkTxShb6Eu8hc'), }, { }); diff --git a/dexs/equalizer-exchange/index.ts b/dexs/equalizer-exchange/index.ts index 24d6a0d9de..b45dbca2f2 100644 --- a/dexs/equalizer-exchange/index.ts +++ b/dexs/equalizer-exchange/index.ts @@ -1,16 +1,6 @@ -import { SimpleAdapter } from "../../adapters/types"; import { CHAIN } from "../../helpers/chains"; -import { getDexVolumeExports } from "../../helpers/dexVolumeLogs"; +import { uniV2Exports } from "../../helpers/uniswap"; -const FACTORY_ADDRESS = '0xc6366efd0af1d09171fe0ebf32c7943bb310832a'; - -const adapter: SimpleAdapter = { - adapter: { - [CHAIN.FANTOM]: { - fetch: getDexVolumeExports({ chain: CHAIN.FANTOM, factory: FACTORY_ADDRESS }), - start: 1670544000, - }, - } -}; - -export default adapter; +export default uniV2Exports({ + [CHAIN.FANTOM]: { factory: '0xc6366efd0af1d09171fe0ebf32c7943bb310832a', }, +}) diff --git a/dexs/equation-v3/index.ts b/dexs/equation-v3/index.ts new file mode 100644 index 0000000000..4babfdd2a9 --- /dev/null +++ b/dexs/equation-v3/index.ts @@ -0,0 +1,68 @@ + +import { CHAIN } from "../../helpers/chains"; +import { BreakdownAdapter, FetchV2, SimpleAdapter } from "../../adapters/types"; +import request, { gql } from "graphql-request"; +import { getUniqStartOfTodayTimestamp } from "../../helpers/getUniSubgraphVolume"; + +const endpoints: { [key: string]: string } = { + [CHAIN.ARBITRUM]: "https://graph-arbitrum.equation.trade/subgraphs/name/equation-stats-v3-arbitrum", +} + +const methodology = { + DailyVolume: "Volume from the sum of the open/close/liquidation of positions and liquidity positions.", +} + +const queryVolume = gql` + query query_volume($id: String!) { + protocolStatistics(where: {id: $id}) { + volumeUSD + } + } +` + +const queryTotalVolume = gql` + query query_total { + protocolState(id: "protocol_state") { + totalVolumeUSD + } + } +` + +interface IDailyResponse { + protocolStatistics: [{ + volumeUSD: string, + }] +} + +interface ITotalResponse { + protocolState: { + totalVolumeUSD: string, + } +} + +const getFetch = () => (chain: string): FetchV2 => async ({ startOfDay }) => { + const dailyData: IDailyResponse = await request(endpoints[chain], queryVolume, { + id: 'Daily:' + startOfDay, + }) + const totalData: ITotalResponse = await request(endpoints[chain], queryTotalVolume) + return { + timestamp: startOfDay, + dailyVolume: dailyData.protocolStatistics[0].volumeUSD, + totalVolume: totalData.protocolState.totalVolumeUSD, + } +} + +const adapter: SimpleAdapter = { + version: 2, + adapter: { + [CHAIN.ARBITRUM]: { + fetch: getFetch()(CHAIN.ARBITRUM), + start: 1715558400, + meta:{ + methodology: methodology, + }, + }, + }, +} + +export default adapter; \ No newline at end of file diff --git a/dexs/equation/index.ts b/dexs/equation/index.ts index 2a5c7241ce..cba4cedee0 100644 --- a/dexs/equation/index.ts +++ b/dexs/equation/index.ts @@ -1,69 +1,69 @@ - import { CHAIN } from "../../helpers/chains"; -import { BreakdownAdapter, Fetch, SimpleAdapter } from "../../adapters/types"; +import { FetchV2, SimpleAdapter } from "../../adapters/types"; import request, { gql } from "graphql-request"; -import { getUniqStartOfTodayTimestamp } from "../../helpers/getUniSubgraphVolume"; const endpoints: { [key: string]: string } = { - [CHAIN.ARBITRUM]: "https://graph-arbitrum.equation.trade/subgraphs/name/equation-stats-arbitrum", -} + [CHAIN.ARBITRUM]: + "https://graph-arbitrum.equation.trade/subgraphs/name/equation-stats-arbitrum", +}; const methodology = { - DailyVolume: "Volume from the sum of the open/close/liquidation of positions and liquidity positions.", -} - -const queryVolume = gql` - query query_volume($id: String!) { - protocolStatistics(where: {id: $id}) { - volumeUSD - } - } -` + DailyVolume: + "Volume from the sum of the open/close/liquidation of positions and liquidity positions.", +}; const queryTotalVolume = gql` - query query_total { - protocolState(id: "protocol_state") { - totalVolumeUSD + query query_total($block: Int) { + protocolState(id: "protocol_state", block: { number: $block }) { + totalVolumeUSD } } -` - -interface IDailyResponse { - protocolStatistics: [{ - volumeUSD: string, - }] -} +`; interface ITotalResponse { - protocolState: { - totalVolumeUSD: string, - } + protocolState: { + totalVolumeUSD: number; + }; } +const getFetch = + () => + (chain: string): FetchV2 => + async ({ getStartBlock, getEndBlock }) => { + const [startBlock, endBlock] = await Promise.all([ + getStartBlock(), + getEndBlock(), + ]); + const [prevData, totalData]: ITotalResponse[] = await Promise.all([ + request(endpoints[chain], queryTotalVolume, { + block: startBlock, + }), + request(endpoints[chain], queryTotalVolume, { + block: endBlock, + }), + ]); + + const dailyVolume = + totalData.protocolState.totalVolumeUSD - + prevData.protocolState.totalVolumeUSD; -const getFetch = () => (chain: string): Fetch => async (timestamp: number) => { - const dayTimestamp = getUniqStartOfTodayTimestamp(new Date((timestamp * 1000))) - const dailyData: IDailyResponse = await request(endpoints[chain], queryVolume, { - id: 'Daily:' + dayTimestamp, - }) - const totalData: ITotalResponse = await request(endpoints[chain], queryTotalVolume) return { - timestamp: dayTimestamp, - dailyVolume: dailyData.protocolStatistics[0].volumeUSD, - totalVolume: totalData.protocolState.totalVolumeUSD, - } -} + dailyVolume, + totalVolume: totalData.protocolState.totalVolumeUSD, + }; + }; const adapter: SimpleAdapter = { - adapter: { - [CHAIN.ARBITRUM]: { - fetch: getFetch()(CHAIN.ARBITRUM), - start: 1697760000, - meta:{ - methodology: methodology, - }, - }, + version: 2, + adapter: { + [CHAIN.ARBITRUM]: { + fetch: getFetch()(CHAIN.ARBITRUM), + start: 1697760000, + meta: { + methodology: methodology, + }, }, -} + }, +}; -export default adapter; \ No newline at end of file +export default adapter; diff --git a/dexs/equilibre/index.ts b/dexs/equilibre/index.ts index 52785dcce5..35d386cbae 100644 --- a/dexs/equilibre/index.ts +++ b/dexs/equilibre/index.ts @@ -1,16 +1,6 @@ -import { SimpleAdapter } from "../../adapters/types"; import { CHAIN } from "../../helpers/chains"; -import { getDexVolumeExports } from "../../helpers/dexVolumeLogs"; +import { uniV2Exports } from "../../helpers/uniswap"; -const FACTORY_ADDRESS = '0xA138FAFc30f6Ec6980aAd22656F2F11C38B56a95' - -const adapter: SimpleAdapter = { - adapter: { - [CHAIN.KAVA]: { - fetch: getDexVolumeExports({ chain: CHAIN.KAVA, factory: FACTORY_ADDRESS }), - start: 1677888000, - }, - } -}; - -export default adapter; +export default uniV2Exports({ + [CHAIN.KAVA]: { factory: '0xA138FAFc30f6Ec6980aAd22656F2F11C38B56a95', }, +}) diff --git a/dexs/equity-spot/index.ts b/dexs/equity-spot/index.ts index d8e1cb81a7..489a0b176d 100644 --- a/dexs/equity-spot/index.ts +++ b/dexs/equity-spot/index.ts @@ -1,10 +1,11 @@ +import * as sdk from "@defillama/sdk"; import request, { gql } from "graphql-request"; import { Fetch, SimpleAdapter } from "../../adapters/types"; import { CHAIN } from "../../helpers/chains"; import { getUniqStartOfTodayTimestamp } from "../../helpers/getUniSubgraphVolume"; const endpoints: { [key: string]: string } = { - [CHAIN.FANTOM]: "https://api.thegraph.com/subgraphs/name/chimpydev/equity-core2", + [CHAIN.FANTOM]: sdk.graph.modifyEndpoint('9USQeMVzzBbxsXhQUmCk5fZursvL9Vj3cv8joYNXeKt9'), } const historicalData = gql` diff --git a/dexs/fairyswap/index.ts b/dexs/fairyswap/index.ts index 7a95960946..b47a1a8372 100644 --- a/dexs/fairyswap/index.ts +++ b/dexs/fairyswap/index.ts @@ -1,4 +1,4 @@ -import { DEFAULT_DAILY_VOLUME_FIELD, DEFAULT_TOTAL_VOLUME_FIELD, getChainVolume } from "../../helpers/getUniSubgraphVolume"; +import { DEFAULT_TOTAL_VOLUME_FIELD, getChainVolume2 } from "../../helpers/getUniSubgraphVolume"; import { CHAIN } from "../../helpers/chains"; import request, { gql } from "graphql-request"; import { SimpleAdapter } from "../../adapters/types"; @@ -39,23 +39,17 @@ const getCustomBlock = async (timestamp: number) => { return block; }; -const DAILY_VOLUME_FACTORY = "fairyDayData"; - -const graphs = getChainVolume({ +const graphs = getChainVolume2({ graphUrls: endpoints, totalVolume: { factory: "fairyFactories", field: DEFAULT_TOTAL_VOLUME_FIELD, }, - dailyVolume: { - factory: DAILY_VOLUME_FACTORY, - field: DEFAULT_DAILY_VOLUME_FIELD, - dateField: 'date' - }, getCustomBlock, }); const adapter: SimpleAdapter = { + version: 2, adapter: { [CHAIN.FINDORA]: { fetch: graphs(CHAIN.FINDORA), diff --git a/dexs/fcon-dex/index.ts b/dexs/fcon-dex/index.ts index 879763fd13..69fa9b8e8a 100644 --- a/dexs/fcon-dex/index.ts +++ b/dexs/fcon-dex/index.ts @@ -31,7 +31,7 @@ const adapter: SimpleAdapter = { adapter: { [DISABLED_ADAPTER_KEY]: disabledAdapter, [CHAIN.MANTLE]: { - fetch: fetch, + fetch: async (timestamp: number) => {return {timestamp}}, start: 1691280000, }, }, diff --git a/dexs/fenix-finance/index.ts b/dexs/fenix-finance/index.ts new file mode 100644 index 0000000000..4870189d80 --- /dev/null +++ b/dexs/fenix-finance/index.ts @@ -0,0 +1,18 @@ +import { CHAIN } from "../../helpers/chains"; +import { univ2Adapter } from "../../helpers/getUniSubgraphVolume"; + +const adapters = univ2Adapter( + { + [CHAIN.BLAST]: + "https://api.studio.thegraph.com/query/67572/mainnet-algebra-fenix/version/latest", + }, + { + factoriesName: "factories", + dayData: "algebraDayData", + dailyVolume: "volumeUSD", + totalVolume: "totalVolumeUSD", + } +); + +adapters.adapter.blast.start = 1714590000; +export default adapters; diff --git a/dexs/ferro/index.ts b/dexs/ferro/index.ts index 672344e266..a01ccb061f 100644 --- a/dexs/ferro/index.ts +++ b/dexs/ferro/index.ts @@ -1,26 +1,21 @@ import { SimpleAdapter } from "../../adapters/types"; -import { getChainVolume } from "../../helpers/getUniSubgraphVolume"; +import { getChainVolume2 } from "../../helpers/getUniSubgraphVolume"; import { CHAIN } from "../../helpers/chains"; - const endpoints = { [CHAIN.CRONOS]: "https://graph.cronoslabs.com/subgraphs/name/ferro/swap", }; -const graphs = getChainVolume({ +const graphs = getChainVolume2({ graphUrls: endpoints, totalVolume: { factory: "tradeVolumes", field: "volume", }, - dailyVolume: { - factory: "dailyVolume", - field: "volume", - dateField: "timestamp" - }, }); const adapter: SimpleAdapter = { + version: 2, adapter: { [CHAIN.CRONOS]: { fetch: graphs(CHAIN.CRONOS), diff --git a/dexs/filament/index.ts b/dexs/filament/index.ts new file mode 100644 index 0000000000..7c3ef58e11 --- /dev/null +++ b/dexs/filament/index.ts @@ -0,0 +1,29 @@ +import type { SimpleAdapter } from "../../adapters/types"; +import { getUniqStartOfTodayTimestamp } from "../../helpers/getUniSubgraphVolume"; +import { httpGet } from "../../utils/fetchURL"; + +const api = "https://orderbook.filament.finance/sei/api/v1/orderbook/tradeVolumeStats/BTC"; + +const fetch = async () => { + const timestamp = getUniqStartOfTodayTimestamp(); + const res = await httpGet(api); + const { allTimeVolume, volumeIn24Hours } = res; + + return { + timestamp, + dailyVolume: volumeIn24Hours, + totalVolume: allTimeVolume, + }; +}; + +const adapter: SimpleAdapter = { + adapter: { + sei: { + fetch, + start: 100601154, + runAtCurrTime: true, + }, + }, +}; + +export default adapter; diff --git a/dexs/firefly/index.ts b/dexs/firefly/index.ts new file mode 100644 index 0000000000..d2fcabd911 --- /dev/null +++ b/dexs/firefly/index.ts @@ -0,0 +1,58 @@ +import { Chain } from "@defillama/sdk/build/general"; +import { BreakdownAdapter, BaseAdapter } from "../../adapters/types"; +import { CHAIN } from "../../helpers/chains"; +import { + DEFAULT_TOTAL_VOLUME_FIELD, + getGraphDimensions2, +} from "../../helpers/getUniSubgraph"; + +const v3Endpoints = { + [CHAIN.MANTA]: "https://subgraph.fireflydex.io/subgraphs/name/firefly/v3", +}; + +const v3Graphs = getGraphDimensions2({ + graphUrls: v3Endpoints, + totalVolume: { + factory: "factories", + field: DEFAULT_TOTAL_VOLUME_FIELD, + }, + feesPercent: { + type: "fees", + UserFees: 100, // User fees are 100% of collected fees + SupplySideRevenue: 100, // 100% of fees are going to LPs + }, +}); + +const methodology = { + UserFees: "Users pay 0.05%, 0.3%, 1% depending on the fee rate for the swap.", + ProtocolRevenue: "Protocol have no revenue.", + SupplySideRevenue: "All user fees are distributed among LPs.", + HoldersRevenue: "Holders have no revenue.", +}; + +type TStartTime = { + [key: string]: number; +}; +const startTimeV3: TStartTime = { + [CHAIN.MANTA]: 1711991119, +}; + +const adapter: BreakdownAdapter = { + version: 2, + breakdown: { + v3: Object.keys(v3Endpoints).reduce((acc, chain) => { + acc[chain] = { + fetch: v3Graphs(chain as Chain), + start: startTimeV3[chain], + meta: { + methodology: { + ...methodology, + }, + }, + }; + return acc; + }, {} as BaseAdapter), + }, +}; + +export default adapter; diff --git a/dexs/fjord-foundry/index.ts b/dexs/fjord-foundry/index.ts new file mode 100644 index 0000000000..ba984fc71a --- /dev/null +++ b/dexs/fjord-foundry/index.ts @@ -0,0 +1,86 @@ +import { BreakdownAdapter, FetchOptions } from "../../adapters/types"; +import { getTimestampAtStartOfDayUTC } from "../../utils/date"; +import fetchURL from "../../utils/fetchURL"; +import { CHAIN } from "../../helpers/chains"; + +const feeEndpoint = "https://fjord-api.vercel.app/api/daily-stats?version=2"; +const feeEndpointV1 = "https://fjord-api.vercel.app/api/daily-stats?version=1"; + +const v2ChainIDs = { + [CHAIN.ETHEREUM]: 1, + [CHAIN.POLYGON]: 137, + [CHAIN.ARBITRUM]: 42161, + [CHAIN.AVAX]: 43114, + [CHAIN.BASE]: 8453, + [CHAIN.BLAST]: 81457, + [CHAIN.BSC]: 56, +}; + +const v1ChainIDs = { + [CHAIN.ETHEREUM]: 1, + [CHAIN.POLYGON]: 137, + [CHAIN.ARBITRUM]: 42161, +}; + +const getV2Data = async (endTimestamp: number, chainId: number) => { + const dayTimestamp = getTimestampAtStartOfDayUTC(endTimestamp) + const historicalVolume = (await fetchURL(feeEndpoint)) + + const chainData = historicalVolume.stats.find(cd => cd.chainId === chainId); + + const totalVolume = chainData.stats + .filter(item => item.timestamp <= dayTimestamp) + .reduce((acc, { volume }) => acc + volume, 0) + + const dailyVolume = chainData.stats + .find(dayItem => dayItem.timestamp === dayTimestamp)?.volume + + return { + totalVolume: `${totalVolume}`, + dailyVolume: dailyVolume ? `${dailyVolume}` : '0', + }; +}; + +const getV1Data = async (endTimestamp: number, chainId: number) => { + const dayTimestamp = getTimestampAtStartOfDayUTC(endTimestamp) + const historicalVolume = (await fetchURL(feeEndpointV1)) + + const chainData = historicalVolume.stats.find(cd => cd.chainId === chainId); + + const totalVolume = chainData.stats + .filter(item => item.timestamp <= dayTimestamp) + .reduce((acc, { volume }) => acc + volume, 0) + + const dailyVolume = chainData.stats + .find(dayItem => dayItem.timestamp === dayTimestamp)?.volume + + return { + totalVolume: `${totalVolume}`, + dailyVolume: dailyVolume ? `${dailyVolume}` : '0', + }; +}; + +const adapter: BreakdownAdapter = { + breakdown: { + v2: Object.keys(v2ChainIDs).reduce((acc, chain) => { + return { + ...acc, + [chain]: { + fetch: async (_ts: number, _chain: any, { startOfDay }: FetchOptions) => await getV2Data(startOfDay, v2ChainIDs[chain]), + start: 1702857600, + }, + } + }, {}), + v1: Object.keys(v1ChainIDs).reduce((acc, chain) => { + return { + ...acc, + [chain]: { + fetch: async (_ts: number, _chain: any, { startOfDay }: FetchOptions) => await getV1Data(startOfDay, v1ChainIDs[chain]), + start: 1631836800, + }, + } + }, {}), + } +} + +export default adapter; diff --git a/dexs/flashtrade/index.ts b/dexs/flashtrade/index.ts new file mode 100644 index 0000000000..0366700507 --- /dev/null +++ b/dexs/flashtrade/index.ts @@ -0,0 +1,30 @@ +import { BreakdownAdapter, ProtocolType, FetchResultVolume } from "../../adapters/types"; +import { CHAIN } from "../../helpers/chains"; +import fetchURL from "../../utils/fetchURL"; + +const marketsCombinedVolumeDaily = "https://api.prod.flash.trade/market-stats"; + +const fetchPerpVolume = async( + timestamp: number +):Promise => { + const marketStats = (await fetchURL(marketsCombinedVolumeDaily)); + return { + dailyVolume: marketStats?.dailyVolumeInUsd.toString(), + totalVolume: marketStats?.totalVolumeInUsd.toString(), + timestamp: timestamp + } +} + +const adapter: BreakdownAdapter = { + breakdown: { + perp: { + [CHAIN.SOLANA]: { + fetch: fetchPerpVolume, + start: 1710028800 // start time llama collect + } + } + }, + protocolType: ProtocolType.PROTOCOL, +} + +export default adapter; diff --git a/dexs/forge/index.ts b/dexs/forge/index.ts index 27aab5e22c..fa8ae2a48d 100644 --- a/dexs/forge/index.ts +++ b/dexs/forge/index.ts @@ -1,27 +1,22 @@ import { SimpleAdapter } from "../../adapters/types"; import { CHAIN } from "../../helpers/chains"; -const { - getChainVolume, -} = require("../../helpers/getUniSubgraphVolume"); +import { getChainVolume2 } from "../../helpers/getUniSubgraphVolume"; const endpoints = { [CHAIN.EVMOS]: "https://subgraph.satsuma-prod.com/09c9cf3574cc/orbital-apes/v3-subgraph/api", }; -const v1Graph = getChainVolume({ +const v1Graph = getChainVolume2({ graphUrls: endpoints, totalVolume: { factory: "factories", field: "totalVolumeUSD", }, - dailyVolume: { - factory: "uniswapDayData", - field: "volumeUSD" - }, }); const adapter: SimpleAdapter = { + version: 2, adapter: { [CHAIN.EVMOS]: { fetch: v1Graph(CHAIN.EVMOS), diff --git a/dexs/frax-swap/index.ts b/dexs/frax-swap/index.ts index 2f8705f1b5..0d1c6620d2 100644 --- a/dexs/frax-swap/index.ts +++ b/dexs/frax-swap/index.ts @@ -22,6 +22,7 @@ const chains: TChains = { [CHAIN.MOONBEAN]: 'Moonbeam', [CHAIN.MOONRIVER]: 'Moonriver', [CHAIN.POLYGON]: 'Polygon', + [CHAIN.FRAXTAL]: 'Fraxtal', }; interface IVolumeall { diff --git a/dexs/fulcrom-finance/index.ts b/dexs/fulcrom-finance/index.ts index f180408a87..80341d76a2 100644 --- a/dexs/fulcrom-finance/index.ts +++ b/dexs/fulcrom-finance/index.ts @@ -8,6 +8,7 @@ const endpoints: { [key: string]: string } = { "https://graph.cronoslabs.com/subgraphs/name/fulcrom/stats-prod", [CHAIN.ERA]: "https://api.studio.thegraph.com/query/52869/stats-prod/version/latest", + [CHAIN.CRONOS_ZKEVM]: "https://api.goldsky.com/api/public/project_clwrfupe2elf301wlhnd7bvva/subgraphs/fulcrom-stats-mainnet/prod/gn" }; const historicalDataSwap = gql` @@ -39,51 +40,52 @@ interface IGraphResponse { const getFetch = (query: string) => - (chain: string): Fetch => - async (timestamp: number) => { - const dayTimestamp = getUniqStartOfTodayTimestamp( - new Date(timestamp * 1000) - ); - const dailyData: IGraphResponse = await request(endpoints[chain], query, { - id: "daily:" + String(dayTimestamp), - period: "daily", - }); - const totalData: IGraphResponse = await request(endpoints[chain], query, { - id: "total", - period: "total", - }); + (chain: string): Fetch => + async (timestamp: number) => { + const dayTimestamp = getUniqStartOfTodayTimestamp( + new Date(timestamp * 1000) + ); + const dailyData: IGraphResponse = await request(endpoints[chain], query, { + id: "daily:" + String(dayTimestamp), + period: "daily", + }); + const totalData: IGraphResponse = await request(endpoints[chain], query, { + id: "total", + period: "total", + }); - return { - timestamp: dayTimestamp, - dailyVolume: - dailyData.volumeStats.length == 1 - ? String( - Number( - Object.values(dailyData.volumeStats[0]).reduce((sum, element) => - String(Number(sum) + Number(element)) - ) - ) * + return { + timestamp: dayTimestamp, + dailyVolume: + dailyData.volumeStats.length == 1 + ? String( + Number( + Object.values(dailyData.volumeStats[0]).reduce((sum, element) => + String(Number(sum) + Number(element)) + ) + ) * 10 ** -30 - ) - : undefined, - totalVolume: - totalData.volumeStats.length == 1 - ? String( - Number( - Object.values(totalData.volumeStats[0]).reduce((sum, element) => - String(Number(sum) + Number(element)) - ) - ) * + ) + : undefined, + totalVolume: + totalData.volumeStats.length == 1 + ? String( + Number( + Object.values(totalData.volumeStats[0]).reduce((sum, element) => + String(Number(sum) + Number(element)) + ) + ) * 10 ** -30 - ) - : undefined, - }; - }; + ) + : undefined, + }; + }; - const startTimestamps: { [chain: string]: number } = { - [CHAIN.CRONOS]: 1677470400, - [CHAIN.ERA]: 1696496400, - }; +const startTimestamps: { [chain: string]: number } = { + [CHAIN.CRONOS]: 1677470400, + [CHAIN.ERA]: 1696496400, + [CHAIN.CRONOS_ZKEVM]: 1723698700, +}; const adapter: BreakdownAdapter = { breakdown: { diff --git a/dexs/fusionx-v2/index.ts b/dexs/fusionx-v2/index.ts index e871b210ef..970388e6fd 100644 --- a/dexs/fusionx-v2/index.ts +++ b/dexs/fusionx-v2/index.ts @@ -1,21 +1,17 @@ import { SimpleAdapter } from "../../adapters/types"; import { CHAIN } from "../../helpers/chains"; -import { DEFAULT_TOTAL_VOLUME_FIELD, getGraphDimensions } from "../../helpers/getUniSubgraph"; +import { DEFAULT_TOTAL_VOLUME_FIELD, getGraphDimensions2 } from "../../helpers/getUniSubgraph"; const v2Endpoints = { [CHAIN.MANTLE]: "https://graphv3.fusionx.finance/subgraphs/name/fusionx/exchange" } -const v2Graphs = getGraphDimensions({ +const v2Graphs = getGraphDimensions2({ graphUrls: v2Endpoints, totalVolume: { factory: "fusionxFactories", field: DEFAULT_TOTAL_VOLUME_FIELD, }, - dailyVolume: { - factory: "fusionxDayData", - field: "dailyVolumeUSD", - }, feesPercent: { type: "volume", ProtocolRevenue: 0.04, @@ -28,6 +24,7 @@ const v2Graphs = getGraphDimensions({ }); const adapter: SimpleAdapter = { + version: 2, adapter: { [CHAIN.MANTLE]: { fetch: v2Graphs(CHAIN.MANTLE), diff --git a/dexs/fusionx-v3/index.ts b/dexs/fusionx-v3/index.ts index 9cb028c967..e5669a381c 100644 --- a/dexs/fusionx-v3/index.ts +++ b/dexs/fusionx-v3/index.ts @@ -1,27 +1,21 @@ import { SimpleAdapter } from "../../adapters/types"; import { CHAIN } from "../../helpers/chains"; -import { DEFAULT_TOTAL_VOLUME_FIELD, getGraphDimensions } from "../../helpers/getUniSubgraph"; +import { + DEFAULT_TOTAL_VOLUME_FIELD, + getGraphDimensions2, +} from "../../helpers/getUniSubgraph"; const v3Endpoints = { - [CHAIN.MANTLE]: "https://graphv3.fusionx.finance/subgraphs/name/fusionx/exchange-v3" -} - -const VOLUME_USD = "volumeUSD"; + [CHAIN.MANTLE]: + "https://graphv3.fusionx.finance/subgraphs/name/fusionx/exchange-v3", +}; -const v3Graphs = getGraphDimensions({ +const v3Graphs = getGraphDimensions2({ graphUrls: v3Endpoints, totalVolume: { factory: "factories", field: DEFAULT_TOTAL_VOLUME_FIELD, }, - dailyVolume: { - factory: "fusionXDayData", - field: VOLUME_USD, - }, - dailyFees: { - factory: "fusionXDayData", - field: "feesUSD", - }, feesPercent: { type: "fees", ProtocolRevenue: 16.7, @@ -29,11 +23,12 @@ const v3Graphs = getGraphDimensions({ Fees: 100, UserFees: 100, // User fees are 100% of collected fees SupplySideRevenue: 66.6, // 66% of fees are going to LPs - Revenue: 33.4 // Revenue is 33% of collected fees - } + Revenue: 33.4, // Revenue is 33% of collected fees + }, }); const adapter: SimpleAdapter = { + version: 2, adapter: { [CHAIN.MANTLE]: { fetch: v3Graphs(CHAIN.MANTLE), diff --git a/dexs/fvm-exchange/index.ts b/dexs/fvm-exchange/index.ts index 7dd0c3571b..dffbcc0d4d 100644 --- a/dexs/fvm-exchange/index.ts +++ b/dexs/fvm-exchange/index.ts @@ -1,16 +1,6 @@ -import { SimpleAdapter } from "../../adapters/types"; import { CHAIN } from "../../helpers/chains"; -import { getDexVolumeExports } from "../../helpers/dexVolumeLogs"; +import { uniV2Exports } from "../../helpers/uniswap"; -const FACTORY_ADDRESS = '0x472f3C3c9608fe0aE8d702f3f8A2d12c410C881A' - -const adapter: SimpleAdapter = { - adapter: { - [CHAIN.FANTOM]: { - fetch: getDexVolumeExports({ chain: CHAIN.FANTOM, factory: FACTORY_ADDRESS }), - start: 1688172646, // when PairFactory was created https://ftmscan.com/address/0x472f3C3c9608fe0aE8d702f3f8A2d12c410C881A - }, - }, -} - -export default adapter \ No newline at end of file +export default uniV2Exports({ + [CHAIN.FANTOM]: { factory: '0x472f3C3c9608fe0aE8d702f3f8A2d12c410C881A', }, +}) diff --git a/dexs/fwx-dex/index.ts b/dexs/fwx-dex/index.ts new file mode 100644 index 0000000000..81cd2336ee --- /dev/null +++ b/dexs/fwx-dex/index.ts @@ -0,0 +1,27 @@ +import { CHAIN } from "../../helpers/chains"; +import { univ2Adapter } from "../../helpers/getUniSubgraphVolume"; + +const adapters = univ2Adapter( + { + [CHAIN.AVAX]: + "https://subgraphs.fwx.finance/avac/subgraphs/name/fwx-exchange-avac", + [CHAIN.BASE]: + "https://subgraphs.fwx.finance/base/subgraphs/name/fwx-exchange-base-prod", + }, + { + factoriesName: "pancakeDayDatas", + totalVolumeFilterParams: [ + { + name: "id", + type: "Int", + }, + ], + dayData: "pancakeDayData", + hasDailyVolume: true, + } +); + +adapters.adapter.avax.start = 1717632000; +adapters.adapter.base.start = 1725408000; + +export default adapters; diff --git a/dexs/fwx/index.ts b/dexs/fwx/index.ts index 6cde318638..427cf60b4b 100644 --- a/dexs/fwx/index.ts +++ b/dexs/fwx/index.ts @@ -4,47 +4,24 @@ import { CHAIN } from "../../helpers/chains"; import { getUniqStartOfTodayTimestamp } from "../../helpers/getUniSubgraphVolume"; import { httpPost } from "../../utils/fetchURL"; -interface IConfigs { - pairs: IPairData[]; -} - -interface IPairData { - pair_name: string; - pair_byte: string; - underlying_asset: string; - collateral_asset: string; -} - interface IDailyData { - all: string; - long: string; - short: string; -} -interface IChartData { date: string; - daily_data: IDailyData; -} -interface IChart { - type: string; - data: IChartData[]; + short: string; + long: string; + total: string; } -interface IChartRes { - charts: IChart[]; - pair_names: string[]; +interface IRes { + data: IDailyData[]; } -interface IEndpoint { - pairData: string; - tradingVolume: string; - openInterest: string; -} +const CHAIN_ID = { + [CHAIN.AVAX]: 43114, + [CHAIN.BASE]: 8453, +}; -const endpoints: Record = { - [CHAIN.AVAX]: { - pairData: "https://app.fwx.finance/api/43114/v1//configs", - tradingVolume: "https://app.fwx.finance/api/43114/v1//chart/trading-volume", - openInterest: "https://app.fwx.finance/api/43114/v1//chart/open-interest", - }, +const endpoints = { + tradingVolume: `https://app.fwx.finance/api/v2/trade/volume`, + openInterest: `https://analytics.fwx.finance/api/trade/daily-open-interest`, }; const fetch = (chain: Chain) => { @@ -56,45 +33,50 @@ const fetch = (chain: Chain) => { const formattedDate = date.toISOString().replace(/\.(\d{3})Z$/, ".$1Z"); // * call api for daily volume - const pairDataRes = await httpPost(endpoints[chain].pairData, {}); - const pairData = pairDataRes as IConfigs - const pairs = pairData.pairs.map((p: IPairData) => p.pair_name); - - // * call api for daily volume - const tradingVolumeRes = await httpPost(endpoints[chain].tradingVolume, { + const tradingVolumePerpRes = await httpPost(endpoints.tradingVolume, { from_date: formattedDate, to_date: formattedDate, - pair_names: pairs, - type: ["all"], + chain_id: CHAIN_ID[chain], + is_perp: true, }); - const tradingVolume = tradingVolumeRes as IChartRes - const totalVolumeData = tradingVolume.charts.find( - (x: IChart) => x.type == "all" + const tradingVolumePerp = tradingVolumePerpRes as IRes; + const dailyPerpVolumeData = tradingVolumePerp?.data.find( + (x: IDailyData) => + new Date(x.date).getTime() == new Date(formattedDate).getTime() ); - const dailyVolumeData = totalVolumeData?.data.find( - (x: IChartData) => + + const tradingVolumeAphRes = await httpPost(endpoints.tradingVolume, { + from_date: formattedDate, + to_date: formattedDate, + chain_id: CHAIN_ID[chain], + is_perp: false, + }); + const tradingVolumeAph = tradingVolumeAphRes as IRes; + const dailyAphVolumeData = tradingVolumeAph?.data.find( + (x: IDailyData) => new Date(x.date).getTime() == new Date(formattedDate).getTime() - )?.daily_data; + ); // * call api for daily open interest - const openInterestRes = await httpPost(endpoints[chain].openInterest, { + const openInterestRes = await httpPost(endpoints.openInterest, { from_date: formattedDate, to_date: formattedDate, - pair_names: pairs, - type: ["all"], + chain_id: CHAIN_ID[chain], }); - const openInterest = openInterestRes as IChartRes - const openInterestData = openInterest.charts.find( - (x: IChart) => x.type == "all" - ); + const openInterestData = openInterestRes as IRes; const dailyOpenInterestData = openInterestData?.data.find( - (x: IChartData) => + (x: IDailyData) => new Date(x.date).getTime() == new Date(formattedDate).getTime() - )?.daily_data; + ); return { - dailyVolume: dailyVolumeData?.all, - dailyOpenInterest: dailyOpenInterestData?.all, + dailyVolume: convertStringNumber( + BigInt(dailyPerpVolumeData?.total || "0") + + BigInt(dailyAphVolumeData?.total || "0") + ), + dailyOpenInterest: convertStringNumber( + BigInt(dailyOpenInterestData?.total || "0") + ), timestamp: timestamp, }; }; @@ -106,7 +88,21 @@ const adapter: SimpleAdapter = { fetch: fetch(CHAIN.AVAX), start: 1701907200, }, + [CHAIN.BASE]: { + fetch: fetch(CHAIN.BASE), + start: 1725408000, + }, }, }; export default adapter; + +// devide by 1e18 +function convertStringNumber(number: bigint) { + const divisor = BigInt(1e18); + let integerPart = number / divisor; + let fractionalPart = number % divisor; + let fractionalString = fractionalPart.toString().padStart(18, "0"); + let result = `${integerPart}.${fractionalString}`; + return result; +} diff --git a/dexs/fxdx/index.ts b/dexs/fxdx/index.ts index 66af991d6f..0dc0571eb8 100644 --- a/dexs/fxdx/index.ts +++ b/dexs/fxdx/index.ts @@ -1,11 +1,12 @@ +import * as sdk from "@defillama/sdk"; import request, { gql } from "graphql-request"; import { Fetch, SimpleAdapter } from "../../adapters/types"; import { CHAIN } from "../../helpers/chains"; import { getUniqStartOfTodayTimestamp } from "../../helpers/getUniSubgraphVolume"; const endpoints: { [key: string]: string } = { - // [CHAIN.OPTIMISM]: "https://api.thegraph.com/subgraphs/name/danielsmith0630/fxdx-optimism-stats", - [CHAIN.BASE]: "https://api.thegraph.com/subgraphs/name/danielsmith0630/fxdx-base-stats" + // [CHAIN.OPTIMISM]: sdk.graph.modifyEndpoint('Ey9sNQbCAa12m5f89moJrjPxXb5X7rUnGujsfbnSAs48'), + [CHAIN.BASE]: sdk.graph.modifyEndpoint('61tpLfrdoEor2ep2WctQSpGDSMetmMBc3Bb7zz7iyqsH') } const historicalDataSwap = gql` diff --git a/dexs/gains-network/index.ts b/dexs/gains-network/index.ts index 78a744b4b2..3bfd435d9f 100644 --- a/dexs/gains-network/index.ts +++ b/dexs/gains-network/index.ts @@ -6,23 +6,56 @@ type IAddresses = { [s: string | Chain]: string[]; }; +type IPrecisionException = { + [chain in CHAIN]?: { + [key: string | number]: number; + }; +}; + interface ILog { address: string; data: string; + topics: string[]; } +const V8_LIMIT_TOPIC0 = "0xc10f67c0e22c53149183a414c16a62334103432a2c48b839a057cd9bd5fdeb99"; +const V8_MARKET_TOPIC0 = "0xbbd5cfa7b4ec0d44d4155fcaad32af9cf7e65799d6b8b08f233b930de7bcd9a8"; + const topic0_limit_ex = [ "0x1ab0771256522e5114b583b488c490436d6f8fe02b1e1c9697443e8704c4e840", // v5-v6 "0xa97091b8c54bf9d1906c2a06322d0ea74fedde4538cdcdf95d81d0ffdca41857", // v7 + V8_LIMIT_TOPIC0, // v8 ]; const topic0_market_ex = [ "0x2739a12dffae5d66bd9e126a286078ed771840f2288f0afa5709ce38c3330997", // v5-v6 "0xca42b0e44cd853d207b87e8f8914eaefef9c9463a8c77ca33754aa62f6904f00", // v7 + V8_MARKET_TOPIC0, // v8 ]; +const topic0_partials = [ + "0xf09a9c949c4bd4cbe75b424bea11c683c3ae55e7cdb8321c3ec37e01af72c8d5", // PositionSizeIncreaseExecuted + "0xe74b50af866d7f8e3577bc959bf73a2690841f0abce22ab0cfb1b1c84122a7d7", // PositionSizeDecreaseExecuted +]; + +const precisionException: IPrecisionException = { + [CHAIN.POLYGON]: { + "0x2ac6749d0affd42c8d61ef25e433f92e375a1aef": 1e6, + "0x4542256c583bcad66a19a525b57203773a6485bf": 1e6, + 3: 1e6, // v8 USDC + }, + [CHAIN.ARBITRUM]: { + "0x2ac6749d0affd42c8d61ef25e433f92e375a1aef": 1e6, + "0x4542256c583bcad66a19a525b57203773a6485bf": 1e6, + 3: 1e6, // v8 USDC + }, + [CHAIN.BASE]: { + 1: 1e6, // USDC is collateralIndex 1 on Base + }, +}; -const precisionException: { [a: string]: number } = { - "0x2ac6749d0affd42c8d61ef25e433f92e375a1aef": 1e6, - "0x4542256c583bcad66a19a525b57203773a6485bf": 1e6, +const diamonds = { + [CHAIN.POLYGON]: "0x209a9a01980377916851af2ca075c2b170452018", + [CHAIN.ARBITRUM]: "0xff162c694eaa571f685030649814282ea457f169", + [CHAIN.BASE]: "0x6cD5aC19a07518A8092eEFfDA4f1174C72704eeb", }; const contract_addresses: IAddresses = { @@ -30,66 +63,119 @@ const contract_addresses: IAddresses = { "0x82e59334da8c667797009bbe82473b55c7a6b311", // DAI TradingCallbacks "0x0bbed2eac3237ba128643670b7cf3be475933755", // ETH TradingCallbacks "0x2ac6749d0affd42c8d61ef25e433f92e375a1aef", // USDC TradingCallbacks + diamonds[CHAIN.POLYGON], // v8 Diamond ], [CHAIN.ARBITRUM]: [ "0x298a695906e16aea0a184a2815a76ead1a0b7522", // DAI TradingCallbacks "0x62a9f50c92a57c719ff741133caa55c7a81ce019", // ETH TradingCallbacks "0x4542256c583bcad66a19a525b57203773a6485bf", // USDC TradingCallbacks + diamonds[CHAIN.ARBITRUM], // v8 Diamond ], + [CHAIN.BASE]: [diamonds[CHAIN.BASE]], }; -const fetch: any = async (timestamp: number, _, { getLogs, createBalances, chain }): Promise => { - const limitLogs: ILog[] = ( - (await Promise.all( - topic0_limit_ex.map(async (topic0) => - getLogs({ - targets: contract_addresses[chain], - topics: [topic0], - }) - ) - )) as ILog[][] - ).flat(); - - const marketLogs: ILog[] = ( - (await Promise.all( - topic0_market_ex.map(async (topic0) => - getLogs({ - targets: contract_addresses[chain], - topics: [topic0], - }) - ) - )) as ILog[][] - ).flat(); +const fetch: any = async (timestamp: number, _, { getLogs, chain }): Promise => { + const chainPrecisionExceptions = precisionException[chain]; + const [limitLogs, marketLogs, partialsLogs] = ( + await Promise.all([ + // Limit Executed logs + (await Promise.all( + topic0_limit_ex.map(async (topic0) => + getLogs({ + targets: contract_addresses[chain], + topics: [topic0], + }) + ) + )) as ILog[][], + + // Market Executed logs + (await Promise.all( + topic0_market_ex.map(async (topic0) => + getLogs({ + targets: contract_addresses[chain], + topics: [topic0], + }) + ) + )) as ILog[][], + + // Partial Increase/Decrease logs + (await Promise.all( + topic0_partials.map(async (topic0) => + getLogs({ + targets: [diamonds[chain]], + topics: [topic0], + }) + ) + )) as ILog[][], + ]) + ).map((logs: ILog[][]) => logs.flat()); const limit_volume = limitLogs .map((e: ILog) => { const data = e.data.replace("0x", ""); - const leverage = Number("0x" + data.slice(512, 576)); - const positionSizeDai = Number("0x" + data.slice(896, 960)) / (precisionException[e.address] ?? 1e18); - const collateralPrice = (data.length === 1216 ? Number("0x" + data.slice(1088, 1152)) : 1e8) / 1e8; - return leverage * positionSizeDai * collateralPrice; + + // v8 + if (e.topics[0] === V8_LIMIT_TOPIC0) { + const leverage = Number("0x" + data.slice(320, 384)) / 1e3; + const collateralIndex = Number("0x" + data.slice(512, 576)); + const collateralAmount = Number("0x" + data.slice(640, 704)) / (chainPrecisionExceptions[collateralIndex] ?? 1e18); + const collateralPriceUsd = Number("0x" + data.slice(1280, 1344)) / 1e8; + return leverage * collateralAmount * collateralPriceUsd; + } else { + // v5-v7 + const leverage = Number("0x" + data.slice(512, 576)); + const positionSizeDai = Number("0x" + data.slice(896, 960)) / (chainPrecisionExceptions[e.address] ?? 1e18); + const collateralPrice = (data.length === 1216 ? Number("0x" + data.slice(1088, 1152)) : 1e8) / 1e8; + return leverage * positionSizeDai * collateralPrice; + } }) .reduce((a: number, b: number) => a + b, 0); const market_volume = marketLogs .map((e: ILog) => { const data = e.data.replace("0x", ""); - const leverage = Number("0x" + data.slice(448, 512)); - const positionSizeDai = Number("0x" + data.slice(832, 896)) / (precisionException[e.address] ?? 1e18); - const collateralPrice = (data.length === 1088 ? Number("0x" + data.slice(1024, 1088)) : 1e8) / 1e8; - return leverage * positionSizeDai * collateralPrice; + // v8 + if (e.topics[0] === V8_MARKET_TOPIC0) { + const leverage = Number("0x" + data.slice(320, 384)) / 1e3; + const collateralIndex = Number("0x" + data.slice(512, 576)); + const collateralAmount = Number("0x" + data.slice(640, 704)) / (chainPrecisionExceptions[collateralIndex] ?? 1e18); + const collateralPriceUsd = Number("0x" + data.slice(1280, 1344)) / 1e8; + return leverage * collateralAmount * collateralPriceUsd; + } else { + // v5-v7 + const leverage = Number("0x" + data.slice(448, 512)); + const positionSizeDai = Number("0x" + data.slice(832, 896)) / (chainPrecisionExceptions[e.address] ?? 1e18); + const collateralPrice = (data.length === 1088 ? Number("0x" + data.slice(1024, 1088)) : 1e8) / 1e8; + return leverage * positionSizeDai * collateralPrice; + } + }) + .reduce((a: number, b: number) => a + b, 0); + + const partials_volume = partialsLogs + .map((e: ILog) => { + const data = e.data.replace("0x", ""); + const cancelReason = Number("0x" + data.slice(128, 192)); + + if (cancelReason > 0) return 0; + + const collateralPrecision = chainPrecisionExceptions[Number(e.topics[1])] ?? 1e18; + const collateralPriceUsd = Number("0x" + data.slice(384, 448)) / 1e8; + const positionSizeDelta = Number("0x" + data.slice(576, 640)) / collateralPrecision; + + return positionSizeDelta * collateralPriceUsd; }) .reduce((a: number, b: number) => a + b, 0); - const dailyVolume = limit_volume + market_volume; + const dailyVolume = limit_volume + market_volume + partials_volume; - return { dailyVolume, timestamp, }; + return { dailyVolume, timestamp }; }; const adapter: SimpleAdapter = { adapter: { - [CHAIN.ARBITRUM]: { fetch, start: 1684972800, }, - [CHAIN.POLYGON]: { fetch, start: 1684972800, }, + [CHAIN.ARBITRUM]: { fetch, start: 1684972800 }, + [CHAIN.POLYGON]: { fetch, start: 1684972800 }, + [CHAIN.BASE]: { fetch, start: 1727351131 }, }, }; diff --git a/dexs/gambit/index.ts b/dexs/gambit/index.ts index fb0c0f845d..7240300d6b 100644 --- a/dexs/gambit/index.ts +++ b/dexs/gambit/index.ts @@ -1,7 +1,5 @@ -import { FetchResultVolume, SimpleAdapter } from "../../adapters/types"; +import { FetchOptions, SimpleAdapter } from "../../adapters/types"; import { CHAIN } from "../../helpers/chains"; -import * as sdk from "@defillama/sdk"; -import { getBlock } from "../../helpers/getBlock"; import { Chain } from "@defillama/sdk/build/general"; const topic0_limit_ex = @@ -9,18 +7,10 @@ const topic0_limit_ex = const topic0_market_ex = "0x2739a12dffae5d66bd9e126a286078ed771840f2288f0afa5709ce38c3330997"; -const USDC_DECIMAL = 6; -const LEVERAGE_DECIMAL = 18; - type IAddress = { [s: string | Chain]: string[]; }; -interface ILog { - data: string; - transactionHash: string; - topics: string[]; -} // GambitTradingCallbacksV1 address const CONTRACT_ADDRESS: IAddress = { @@ -30,94 +20,44 @@ const CONTRACT_ADDRESS: IAddress = { "0x50853A14cD14CC6A891BF034A204A15d294AF056", "0x240d75373f9941b8F7FbA660b9ae73dfa655f7Da", // v1.3.4 "0x43c1cc807Dc22bCF7C789eDE4d1B4828C87A06D1", // v1.5.1 + "0x3bEa4Af64689ce3429D312cf205312842C944DeE", // v1.6.0 ], [CHAIN.ARBITRUM]: [ "0x8d85f4615ea5F2Ea8D91C196aaD4C04D8416865C", "0xB88C3A703B3565cb7bfdB1806Ba3728C54dd4b91", // v1.3.1 "0x77233F7F6f11300Fd30B338dA38D96a7bFD5aB86", // v1.5.1 + "0xB4099795021506b67ef974eCb85e10898e2F0D45", // v1.6.0 ], }; -const fetch = (chain: Chain) => { - return async (timestamp: number): Promise => { - const fromTimestamp = timestamp - 60 * 60 * 24; - const toTimestamp = timestamp; - - const fromBlock = await getBlock(fromTimestamp, chain, {}); - const toBlock = await getBlock(toTimestamp, chain, {}); - const contractAddressList = CONTRACT_ADDRESS[chain]; - const logs_limit_ex: ILog[] = ( - await Promise.all( - contractAddressList.map(async (address) => { - return sdk.getEventLogs({ - target: address, - toBlock: toBlock, - fromBlock: fromBlock, - chain: chain, - topics: [topic0_limit_ex], - }); - }) - ) - ).flatMap((response) => response as any) as ILog[]; - - const logs_market_ex: ILog[] = ( - await Promise.all( - contractAddressList.map(async (address) => { - return sdk.getEventLogs({ - target: address, - toBlock: toBlock, - fromBlock: fromBlock, - chain: chain, - topics: [topic0_market_ex], - }); - }) - ) - ).flatMap((response) => response as any) as ILog[]; - const limit_volume = logs_limit_ex - .map((e: ILog) => { - const data = e.data.replace("0x", ""); - let leverage = Number("0x" + data.slice(448, 512)); - if (leverage > 1000) { - leverage = leverage / 10 ** LEVERAGE_DECIMAL; - } - const positionSizeUsdc = - Number("0x" + data.slice(896, 960)) / 10 ** USDC_DECIMAL; - return leverage * positionSizeUsdc; - }) - .reduce((a: number, b: number) => a + b, 0); - - const market_volume = logs_market_ex - .map((e: ILog) => { - const data = e.data.replace("0x", ""); - let leverage = Number("0x" + data.slice(448, 512)); - if (leverage > 1000) { - leverage = leverage / 10 ** LEVERAGE_DECIMAL; - } - const positionSizeUsdc = - Number("0x" + data.slice(832, 896)) / 10 ** USDC_DECIMAL; - return leverage * positionSizeUsdc; - }) - .reduce((a: number, b: number) => a + b, 0); - - const dailyVolume = limit_volume + market_volume; - return { - dailyVolume: `${dailyVolume}`, - timestamp, - }; - }; -}; +const fetch = async ({ chain, createBalances, getLogs }: FetchOptions) => { + const dailyVolume = createBalances(); + const marketLogs = await getLogs({ + targets: CONTRACT_ADDRESS[chain], + eventAbi: "event MarketExecuted(uint256 indexed orderId, (address trader, uint256 pairIndex, uint256 index, uint256 initialPosToken, uint256 positionSizeUsdc, uint256 openPrice, bool buy, uint256 leverage, uint256 tp, uint256 sl) t, bool open, uint256 price, uint256 priceImpactP, uint256 positionSizeUsdc, int256 percentProfit, uint256 usdcSentToTrader)", + topics: [topic0_market_ex], + }); + const limitLogs = await getLogs({ + targets: CONTRACT_ADDRESS[chain], + eventAbi: "event LimitExecuted(uint256 indexed orderId, uint256 limitIndex, (address trader, uint256 pairIndex, uint256 index, uint256 initialPosToken, uint256 positionSizeUsdc, uint256 openPrice, bool buy, uint256 leverage, uint256 tp, uint256 sl) t, address indexed nftHolder, uint8 orderType, uint256 price, uint256 priceImpactP, uint256 positionSizeUsdc, int256 percentProfit, uint256 usdcSentToTrader)", + topics: [topic0_limit_ex], + }); + marketLogs.concat(limitLogs).forEach(i => { + let leverage = Number(i.t.leverage) + if (leverage > 1000) + leverage = leverage / 1e18 + dailyVolume.addUSDValue(leverage * i.positionSizeUsdc.toString() / 1e6) + }); + + return { dailyVolume }; +} const adapter: SimpleAdapter = { adapter: { - [CHAIN.ERA]: { - fetch: fetch(CHAIN.ERA), - start: 1690848000, // 2023/08/01 00:00:00 - }, - [CHAIN.ARBITRUM]: { - fetch: fetch(CHAIN.ARBITRUM), - start: 1698883200, // 2023/11/02 00:00:00 - }, + [CHAIN.ERA]: { fetch, start: 1690848000, }, + [CHAIN.ARBITRUM]: { fetch, start: 1698883200, }, }, + version: 2 }; export default adapter; diff --git a/dexs/gaspump/index.ts b/dexs/gaspump/index.ts new file mode 100644 index 0000000000..dd446928ad --- /dev/null +++ b/dexs/gaspump/index.ts @@ -0,0 +1,34 @@ +import fetchURL from "../../utils/fetchURL" +import { CHAIN } from "../../helpers/chains"; +import { FetchOptions } from "../../adapters/types"; +import { getPrices } from "../../utils/prices"; + + +const endpoint = "https://api.gas111.com/api/v1/internal/tokens/volume-stats?" + + +const fetch = async (options: FetchOptions) => { + const startTime = new Date(options.startTimestamp * 1000).toISOString().split(".")[0] + const endTime = new Date(options.endTimestamp * 1000).toISOString().split(".")[0] + const res = await fetchURL(`${endpoint}start_date=${startTime}&end_date=${endTime}`) + const TON = "coingecko:the-open-network" + const ton_price = await getPrices([TON], options.startTimestamp); + + return { + dailyVolume: parseInt(res.volume_ton) * ton_price[TON].price, + timestamp: options.startTimestamp, + }; +}; + + +const adapter: any = { + version: 2, + adapter: { + [CHAIN.TON]: { + fetch, + start: 1725134400, + }, + }, +}; + +export default adapter; diff --git a/dexs/gin-finance/index.ts b/dexs/gin-finance/index.ts index 190adabb61..55c7f22ed9 100644 --- a/dexs/gin-finance/index.ts +++ b/dexs/gin-finance/index.ts @@ -1,8 +1,9 @@ +import * as sdk from "@defillama/sdk"; import { CHAIN } from "../../helpers/chains"; import { univ2Adapter } from "../../helpers/getUniSubgraphVolume"; const adapters = univ2Adapter({ - [CHAIN.BOBA]: "https://api.thegraph.com/subgraphs/name/gindev2/gin-subgraph" + [CHAIN.BOBA]: sdk.graph.modifyEndpoint('BicQZ5AsMXGPC1YZbm2SW3F2EqMA6zNSJiH6g338Hnrv') }, { }); diff --git a/dexs/glowswap/index.ts b/dexs/glowswap/index.ts new file mode 100644 index 0000000000..f8897221cc --- /dev/null +++ b/dexs/glowswap/index.ts @@ -0,0 +1,22 @@ +import { SimpleAdapter } from "../../adapters/types" +import { httpGet } from "../../utils/fetchURL" + +const fetch = async () => { + const url = "https://api.glowswap.io/v1/analytics" + const response = await httpGet(url) + const dailyVolume = response.data.volUSD.day; + return { + dailyVolume, + } +} +const adapter: SimpleAdapter = { + version: 2, + adapter: { + bsquared: { + fetch, + start: 0, + runAtCurrTime: true, + } + } +} +export default adapter diff --git a/dexs/glyph-exchange-v4/index.ts b/dexs/glyph-exchange-v4/index.ts new file mode 100644 index 0000000000..4d54bc800c --- /dev/null +++ b/dexs/glyph-exchange-v4/index.ts @@ -0,0 +1,61 @@ +import { BreakdownAdapter } from "../../adapters/types"; +import { Chain } from "@defillama/sdk/build/general"; +import { CHAIN } from "../../helpers/chains"; +import { getGraphDimensions2 } from "../../helpers/getUniSubgraph"; + +const endpointsClassic = { + [CHAIN.CORE]: "https://thegraph.coredao.org/subgraphs/name/glyph/algebra", +}; + +const VOLUME_FIELD = "totalVolumeUSD"; +const FEES_FIELD = "totalFeesUSD"; + +const graphsClassic = getGraphDimensions2({ + graphUrls: endpointsClassic, + totalVolume: { + factory: "factories", + field: VOLUME_FIELD, + }, + totalFees: { + factory: "factories", + field: FEES_FIELD, + }, + //dynamic fee + feesPercent: { + type: "fees", + Fees: 100, + UserFees: 100, + Revenue: 15, + ProtocolRevenue: 15, + SupplySideRevenue: 85, + }, +}); + +const classic = Object.keys(endpointsClassic).reduce( + (acc, chain) => ({ + ...acc, + [chain]: { + fetch: graphsClassic(chain as Chain), + start: 1710806400, + meta: { + methodology: { + Fees: "GlyphExchange-v4 charges a dynamic fee", + UserFees: "GlyphExchange-v4 charges a dynamic fee", + Revenue: "15% fees goes to treasury", + ProtocolRevenue: "Treasury receives a share of the fees", + SupplySideRevenue: "85% fees goes to liquidity providers", + }, + }, + }, + }), + {}, +) as any; + +const adapter: BreakdownAdapter = { + version: 2, + breakdown: { + classic: classic, + }, +}; + +export default adapter; diff --git a/dexs/glyph-exchange/index.ts b/dexs/glyph-exchange/index.ts new file mode 100644 index 0000000000..6f6a999975 --- /dev/null +++ b/dexs/glyph-exchange/index.ts @@ -0,0 +1,58 @@ +import { BreakdownAdapter } from "../../adapters/types"; +import { Chain } from "@defillama/sdk/build/general"; +import { CHAIN } from "../../helpers/chains"; +import { getGraphDimensions2 } from "../../helpers/getUniSubgraph"; + +const endpointsClassic = { + [CHAIN.CORE]: "https://thegraph.coredao.org/subgraphs/name/glyph/glyph-tvl" +}; + +const VOLUME_FIELD = "totalVolumeUSD"; + +//0.3 swap fee, 6/10 to lp, 4/10 to treasury +const feesPercent = { + type: "volume" as "volume", + Fees: 0.3, + UserFees: 0.3, + Revenue: 0.12, + ProtocolRevenue: 0.12, + SupplySideRevenue: 0.18 +} + +const graphsClassic = getGraphDimensions2({ + graphUrls: endpointsClassic, + totalVolume: { + factory: "glyphFactories", + field: VOLUME_FIELD, + }, + feesPercent +}); + +const classic = Object.keys(endpointsClassic).reduce( + (acc, chain) => ({ + ...acc, + [chain]: { + fetch: graphsClassic(chain as Chain), + start: 1710806400, + meta: { + methodology: { + Fees: "GlyphExchange charges a flat 0.3% fee", + UserFees: "Users pay a 0.3% fee on each trade", + Revenue: "A 0.12% of each trade goes to treasury", + ProtocolRevenue: "Treasury receives a share of the fees", + SupplySideRevenue: "Liquidity providers get 6/10 of all trades in their pools" + } + } + }, + }), + {} +) as any; + +const adapter: BreakdownAdapter = { + version: 2, + breakdown: { + classic: classic, + } +} + +export default adapter diff --git a/dexs/gmx-v2/index.ts b/dexs/gmx-v2/index.ts index ed6e6a0452..61935a4ba6 100644 --- a/dexs/gmx-v2/index.ts +++ b/dexs/gmx-v2/index.ts @@ -1,89 +1,95 @@ -import { BreakdownAdapter, FetchResultVolume, SimpleAdapter } from "../../adapters/types"; +import request, { gql } from "graphql-request"; +import { BreakdownAdapter, Fetch, FetchOptions, SimpleAdapter } from "../../adapters/types"; import { CHAIN } from "../../helpers/chains"; -import * as sdk from "@defillama/sdk"; -import { getBlock } from "../../helpers/getBlock"; -import { Chain } from "@defillama/sdk/build/general"; -import { adapter_trade } from './gmx-v2-trade/index' +import { getUniqStartOfTodayTimestamp } from "../../helpers/getUniSubgraphVolume"; -interface ILog { - data: string; - transactionHash: string; - topics: string[]; +const endpoints: { [key: string]: string } = { + [CHAIN.ARBITRUM]: "https://subgraph.satsuma-prod.com/3b2ced13c8d9/gmx/synthetics-arbitrum-stats/api", + [CHAIN.AVAX]: "https://subgraph.satsuma-prod.com/3b2ced13c8d9/gmx/synthetics-avalanche-stats/api", } -const topic0_ins = '0x137a44067c8961cd7e1d876f4754a5a3a75989b4552f1843fc69c3b372def160'; -const topic1_ins = '0xf35c99b746450c623be607459294d15f458678f99d535718db6cfcbccb117c09'; - -interface IToken { - amount: number; - token: string; -} +const historicalDataSwap = gql` + query get_volume($period: String!, $id: String!) { + volumeInfos(where: {period: $period, id: $id}) { + swapVolumeUsd + } + } +` -type TChain = { - [s: Chain | string]: string; -} +const historicalDataDerivatives = gql` + query get_volume($period: String!, $id: String!) { + volumeInfos(where: {period: $period, id: $id}) { + marginVolumeUsd + } + } +` -const contract: TChain = { - [CHAIN.ARBITRUM]: '0xc8ee91a54287db53897056e12d9819156d3822fb', - [CHAIN.AVAX]: '0xdb17b211c34240b014ab6d61d4a31fa0c0e20c26' +interface IGraphResponse { + volumeInfos: Array<{ + marginVolumeUsd: string, + swapVolumeUsd: string, + }> } -const fetch = (chain: Chain) => { - return async (timestamp: number): Promise => { - const balances = new sdk.Balances({ chain, timestamp }) - const fromTimestamp = timestamp - 60 * 60 * 24 - const toTimestamp = timestamp - const fromBlock = (await getBlock(fromTimestamp, chain, {})); - const toBlock = (await getBlock(toTimestamp, chain, {})); - - const swap_logs: ILog[] = (await sdk.getEventLogs({ - target: contract[chain], - toBlock: toBlock, - fromBlock: fromBlock, - chain: chain, - topics: [topic0_ins, topic1_ins] - })) as ILog[]; - - const raw_in = swap_logs.map((e: ILog) => { - const data = e.data.replace('0x', ''); - const volume = Number('0x' + data.slice(53 * 64, (53 * 64) + 64)); - const address = data.slice(27 * 64, (27 * 64) + 64); - const contract_address = '0x' + address.slice(24, address.length); - return { - amount: volume, - token: contract_address, - } as IToken - }) - - raw_in.map((e: IToken) => { - balances.add(e.token, e.amount) - }) +const getFetch = (query: string)=> (chain: string): Fetch => async (_tt: number, _t: any, options: FetchOptions) => { + const dayTimestamp = getUniqStartOfTodayTimestamp(new Date((options.startOfDay * 1000))) + const dailyData: IGraphResponse = await request(endpoints[chain], query, { + id: '1d:' + String(dayTimestamp), + period: '1d', + }) + const totalData: IGraphResponse = await request(endpoints[chain], query, { + id: 'total', + period: 'total', + }) - return { - dailyVolume: await balances.getUSDString(), - timestamp - } + return { + timestamp: dayTimestamp, + dailyVolume: + dailyData.volumeInfos.length == 1 + ? String(Number(Object.values(dailyData.volumeInfos[0]).reduce((sum, element) => String(Number(sum) + Number(element)))) * 10 ** -30) + : undefined, + totalVolume: + totalData.volumeInfos.length == 1 + ? String(Number(Object.values(totalData.volumeInfos[0]).reduce((sum, element) => String(Number(sum) + Number(element)))) * 10 ** -30) + : undefined, } } +const startTimestamps: { [chain: string]: number } = { + [CHAIN.ARBITRUM]: 1630368000, + [CHAIN.AVAX]: 1640131200, +} -const adapter: any = { - adapter: { - [CHAIN.ARBITRUM]: { - fetch: fetch(CHAIN.ARBITRUM), - start: 1688428800, - }, - [CHAIN.AVAX]: { - fetch: fetch(CHAIN.AVAX), - start: 1688428800, - }, - }, -}; +const methodology = { + dailyVolume: + "Sum of daily total volume for all markets on a given day.", + totalVolume: + "Sum of overall total volume for all markets since inception." +} -const adapters: BreakdownAdapter = { +const adapter: BreakdownAdapter = { breakdown: { - "gmx-v2-swap": adapter["adapter"], - "gmx-v2-trade": adapter_trade["adapter"], + "gmx-v2-swap": Object.keys(endpoints).reduce((acc, chain) => { + return { + ...acc, + [chain]: { + fetch: getFetch(historicalDataSwap)(chain), + start: startTimestamps[chain], + meta: {methodology} + } + } + }, {}), + "gmx-v2-trade": Object.keys(endpoints).reduce((acc, chain) => { + return { + ...acc, + [chain]: { + fetch: getFetch(historicalDataDerivatives)(chain), + start: startTimestamps[chain], + meta: {methodology} + } + } + }, {}) } } -export default adapters; + +export default adapter; diff --git a/dexs/goosefx/index.ts b/dexs/goosefx/index.ts index 2d1d96956a..8dc7b088e4 100644 --- a/dexs/goosefx/index.ts +++ b/dexs/goosefx/index.ts @@ -8,7 +8,7 @@ const gooseFxEndpoint = "https://api-services.goosefx.io/getDefillamaStats"; const fetch = async (timestamp: number) => { const timeStampInMs = timestamp * 1000; const res = await postURL(gooseFxEndpoint, { - timeStamp: timeStampInMs + timestamp: timeStampInMs }); return { timestamp: timeStampInMs, diff --git a/dexs/gravis/index.ts b/dexs/gravis/index.ts index 05e791244d..4b8dc23906 100644 --- a/dexs/gravis/index.ts +++ b/dexs/gravis/index.ts @@ -1,10 +1,11 @@ +import * as sdk from "@defillama/sdk"; import { CHAIN } from "../../helpers/chains"; import { univ2Adapter } from "../../helpers/getUniSubgraphVolume"; const adapters = univ2Adapter({ - [CHAIN.POLYGON]: "https://api.thegraph.com/subgraphs/name/darth-crypto/gravis-finance", - [CHAIN.BSC]: "https://api.thegraph.com/subgraphs/name/vkolerts/bsc-main" + [CHAIN.POLYGON]: sdk.graph.modifyEndpoint('YyFnnb7YkVbrxti9TP7pdUdCbY7fD58LxTAYdjRmTwi'), + [CHAIN.BSC]: sdk.graph.modifyEndpoint('CLMjk3GaCwWCXqz8jFR28YnazCxgXxQmg976JxJoeGtD') }, { }); diff --git a/dexs/gravity-finance/index.ts b/dexs/gravity-finance/index.ts index cdf8f9323a..7a4cdb1e8e 100644 --- a/dexs/gravity-finance/index.ts +++ b/dexs/gravity-finance/index.ts @@ -1,9 +1,10 @@ +import * as sdk from "@defillama/sdk"; import { CHAIN } from "../../helpers/chains"; import { univ2Adapter } from "../../helpers/getUniSubgraphVolume"; const adapters = univ2Adapter({ - [CHAIN.POLYGON]: "https://api.thegraph.com/subgraphs/name/agelesszeal/gravity-analytics", + [CHAIN.POLYGON]: sdk.graph.modifyEndpoint('82hBGNdZXvp3JbJbHvRptFanP4q5RszxYWndRact8qzD'), }, { }); diff --git a/dexs/grizzly-trade-derivatives-v2/index.ts b/dexs/grizzly-trade-derivatives-v2/index.ts new file mode 100644 index 0000000000..6ee8157756 --- /dev/null +++ b/dexs/grizzly-trade-derivatives-v2/index.ts @@ -0,0 +1,69 @@ +import request, { gql } from "graphql-request"; +import { FetchResultVolume, SimpleAdapter } from "../../adapters/types"; +import { CHAIN } from "../../helpers/chains"; +import { getTimestampAtStartOfDayUTC } from "../../utils/date"; + +const grizzlyPerpsV2Subgraph = + "https://api.studio.thegraph.com/query/55804/bnb-trade/version/latest"; + +interface IReferralRecord { + volume: string; // Assuming volume is a string that represents a number + timestamp: number; +} + +interface IVolumeStat { + cumulativeVolumeUsd: string; + volumeUsd: string; + id: string; +} + +const fetch = () => { + return async (timestamp: number): Promise => { + const todaysTimestamp = getTimestampAtStartOfDayUTC(timestamp); + + const graphQuery = gql` + query MyQuery { + volumeStats(where: {timestamp: ${todaysTimestamp}, period: "daily"}) { + cumulativeVolumeUsd + id + volumeUsd + } + } + `; + + const response = await request(grizzlyPerpsV2Subgraph, graphQuery); + const volumeStats: IVolumeStat[] = response.volumeStats; + + let dailyVolumeUSD = BigInt(0); + + volumeStats.forEach((vol) => { + dailyVolumeUSD += BigInt(vol.volumeUsd); + }); + + const finalDailyVolume = parseInt(dailyVolumeUSD.toString()) / 1e18; + + return { + dailyVolume: finalDailyVolume.toString(), + timestamp: todaysTimestamp, + }; + }; +}; + +const methodology = { + dailyVolume: + "Total cumulativeVolumeUsd for specified chain for the given day", +}; + +const adapter: SimpleAdapter = { + adapter: { + [CHAIN.BSC]: { + fetch: fetch(), + start: async () => 1706832000, + meta: { + methodology, + }, + }, + }, +}; + +export default adapter; diff --git a/dexs/grizzly-trade/index.ts b/dexs/grizzly-trade/index.ts index 8807cc3a67..5f74fbc3ec 100644 --- a/dexs/grizzly-trade/index.ts +++ b/dexs/grizzly-trade/index.ts @@ -1,3 +1,4 @@ +import * as sdk from "@defillama/sdk"; import request, { gql } from "graphql-request"; import { BreakdownAdapter, DISABLED_ADAPTER_KEY, Fetch } from "../../adapters/types"; import { CHAIN } from "../../helpers/chains"; @@ -5,7 +6,7 @@ import { getUniqStartOfTodayTimestamp } from "../../helpers/getUniSubgraphVolume import disabledAdapter from "../../helpers/disabledAdapter"; const endpoints: { [key: string]: string } = { - [CHAIN.BSC]: "https://api.thegraph.com/subgraphs/name/metavault-trade/grizzly-bnb-subgraph", + [CHAIN.BSC]: sdk.graph.modifyEndpoint('3CUU9roJ9PsMdijcBdaCBRHhTUBobLeDLyMW4QF2XNmn'), } const historicalDataSwap = gql` diff --git a/dexs/h2-finance-v3/index.ts b/dexs/h2-finance-v3/index.ts new file mode 100644 index 0000000000..fcbd1916d6 --- /dev/null +++ b/dexs/h2-finance-v3/index.ts @@ -0,0 +1,12 @@ +import { univ2Adapter2 } from "../../helpers/getUniSubgraphVolume"; +import { CHAIN } from "../../helpers/chains"; + +const adapter = univ2Adapter2({ + [CHAIN.CRONOS_ZKEVM]: "https://api.goldsky.com/api/public/project_clwrfupe2elf301wlhnd7bvva/subgraphs/h2-exchange-v3-cronos-zkevm/latest/gn" +},{ + factoriesName: "factories", +}); + +adapter.adapter[CHAIN.CRONOS_ZKEVM].start = 1; + +export default adapter diff --git a/dexs/h2-finance/index.ts b/dexs/h2-finance/index.ts new file mode 100644 index 0000000000..5af768e778 --- /dev/null +++ b/dexs/h2-finance/index.ts @@ -0,0 +1,12 @@ +import { univ2Adapter2 } from "../../helpers/getUniSubgraphVolume"; +import { CHAIN } from "../../helpers/chains"; + +const adapter = univ2Adapter2({ + [CHAIN.CRONOS_ZKEVM]: "https://api.goldsky.com/api/public/project_clwrfupe2elf301wlhnd7bvva/subgraphs/h2-exchange-v2-cronos-zkevm/latest/gn" +},{ + factoriesName: "vvsFactories", +}); + +adapter.adapter[CHAIN.CRONOS_ZKEVM].start = 1; + +export default adapter diff --git a/dexs/hadouken-amm/index.ts b/dexs/hadouken-amm/index.ts index 8a3282276f..459720285f 100644 --- a/dexs/hadouken-amm/index.ts +++ b/dexs/hadouken-amm/index.ts @@ -1,12 +1,12 @@ -import { ChainEndpoints, DISABLED_ADAPTER_KEY, SimpleAdapter } from "../../adapters/types"; -import { getChainVolume } from "../../helpers/getUniSubgraphVolume"; +import { ChainEndpoints, SimpleAdapter } from "../../adapters/types"; +import { getChainVolume2 } from "../../helpers/getUniSubgraphVolume"; import { CHAIN } from "../../helpers/chains"; import { Chain } from "@defillama/sdk/build/general"; import customBackfill from "../../helpers/customBackfill"; -import disabledAdapter from "../../helpers/disabledAdapter"; const endpoints: ChainEndpoints = { - [CHAIN.GODWOKEN_V1]: "https://graph-prod-http-hadouken-prod.hadouken.finance/subgraphs/name/balancer-godwoken-mainnet", + [CHAIN.GODWOKEN_V1]: + "https://graph-prod-http-hadouken-prod.hadouken.finance/subgraphs/name/balancer-godwoken-mainnet", }; const graphParams = { @@ -14,21 +14,20 @@ const graphParams = { factory: "balancers", field: "totalSwapVolume", }, - hasDailyVolume: false, -} +}; -const v1graphs = getChainVolume({ +const v1graphs = getChainVolume2({ graphUrls: endpoints, - ...graphParams + ...graphParams, }); - const adapter: SimpleAdapter = { + version: 2, adapter: { [CHAIN.GODWOKEN_V1]: { fetch: v1graphs(CHAIN.GODWOKEN_V1 as Chain), start: 1669248000, - customBackfill: customBackfill(CHAIN.GODWOKEN_V1 as Chain, v1graphs) + customBackfill: customBackfill(CHAIN.GODWOKEN_V1 as Chain, v1graphs), }, }, }; diff --git a/dexs/hakuswap/index.ts b/dexs/hakuswap/index.ts index 8d5a09ef47..2e613422b7 100644 --- a/dexs/hakuswap/index.ts +++ b/dexs/hakuswap/index.ts @@ -1,7 +1,8 @@ +import * as sdk from "@defillama/sdk"; import { CHAIN } from "../../helpers/chains"; import { univ2Adapter } from "../../helpers/getUniSubgraphVolume"; export default univ2Adapter({ - [CHAIN.AVAX]: "https://api.thegraph.com/subgraphs/name/smartcookie0501/hakuswap-subgraph" + [CHAIN.AVAX]: sdk.graph.modifyEndpoint('7TYvKnsZnaihZ1x5V8LgMRuvv7N8VuaM21GVRXPK6WR6') }, { }); diff --git a/dexs/harmony-swap/index.ts b/dexs/harmony-swap/index.ts new file mode 100644 index 0000000000..3de229a9a8 --- /dev/null +++ b/dexs/harmony-swap/index.ts @@ -0,0 +1,44 @@ +import * as sdk from "@defillama/sdk"; +import { CHAIN } from "../../helpers/chains"; +import { DEFAULT_TOTAL_VOLUME_FIELD } from "../../helpers/getUniSubgraphFees"; +import { getGraphDimensions2 } from "../../helpers/getUniSubgraph"; +import { FetchOptions, SimpleAdapter } from "../../adapters/types"; + +const endpoint: any = { + [CHAIN.HARMONY]: sdk.graph.modifyEndpoint("GVkp9F6TzzC5hY4g18Ukzb6gGcYDfQrpMpcj867jsenJ"), +}; + +const v3Graphs = getGraphDimensions2({ + graphUrls: endpoint, + totalVolume: { + factory: "factories", + field: DEFAULT_TOTAL_VOLUME_FIELD, + }, +}); + +const adapters: SimpleAdapter = { + version: 2, + adapter: { + [CHAIN.HARMONY]: { + fetch: async (options: FetchOptions) => { + try { + const res = await v3Graphs(CHAIN.HARMONY)(options); + return { + totalVolume: res?.totalVolume || 0, + dailyVolume: res?.dailyVolume || 0, + }; + } catch(e) { + console.error("Error fetching volume:", e); + return { + totalVolume: 0, + dailyVolume: 0, + }; + } + }, + start: 0, + }, + }, +}; + + +export default adapters; diff --git a/dexs/hashflow/index.ts b/dexs/hashflow/index.ts index 6ce860adf9..3738aa0895 100644 --- a/dexs/hashflow/index.ts +++ b/dexs/hashflow/index.ts @@ -3,12 +3,13 @@ import { CHAIN } from "../../helpers/chains"; import { getUniqStartOfTodayTimestamp } from "../../helpers/getUniSubgraphVolume"; import { httpGet } from "../../utils/fetchURL"; -const chains = [CHAIN.ETHEREUM, CHAIN.AVAX, CHAIN.BSC, CHAIN.ARBITRUM, CHAIN.OPTIMISM, CHAIN.POLYGON] +const chains = [CHAIN.ETHEREUM, CHAIN.AVAX, CHAIN.BSC, CHAIN.ARBITRUM, CHAIN.OPTIMISM, CHAIN.POLYGON, CHAIN.SOLANA] const dateToTs = (date: string) => new Date(date).getTime() / 1000 const normalizeChain = (c: string) => { if (c === "bnb") return CHAIN.BSC if (c === "avalanche") return CHAIN.AVAX + if(c === "solana-mainnet") return CHAIN.SOLANA return c } diff --git a/dexs/hbarsuite-dex/index.ts b/dexs/hbarsuite-dex/index.ts new file mode 100644 index 0000000000..0b05f6c925 --- /dev/null +++ b/dexs/hbarsuite-dex/index.ts @@ -0,0 +1,86 @@ +import { SimpleAdapter } from "../../adapters/types"; +import { CHAIN } from "../../helpers/chains"; +import axios from "axios"; +import asyncRetry from "async-retry"; +import { getUniqStartOfTodayTimestamp } from "../../helpers/getUniSubgraphVolume"; +const BigNumber = require("bignumber.js"); + +/* + * HbarSuite is a decentralized network of features built on Hedera Hashgraph. + * It is a suite of products that are built on top of the layer 1, + * relying on the security and speed of the Hedera network. + * + * HbarSute Network relies entirely on HCS (Hedera Consensus Service) for its data storage, + * and HFS (Hedera File Service) for its file storage. + * + * It also uses NFTs (Non-Fungible Tokens) to represent the Liquidity Providers' shares in the pools, + * storing the data on IPFS. + */ + +// Listing the urls of the nodes that are used by HbarSuite to connect to the Hedera Mainnet. +const nodes = [ + 'https://mainnet-sn1.hbarsuite.network', + 'https://mainnet-sn2.hbarsuite.network', + 'https://mainnet-sn3.hbarsuite.network', + 'https://mainnet-sn4.hbarsuite.network', + 'https://mainnet-sn5.hbarsuite.network', + 'https://mainnet-sn6.hbarsuite.network', + 'https://mainnet-sn7.hbarsuite.network', + 'https://mainnet-sn8.hbarsuite.network' +] + +interface IHbarSuiteVolumes { + ticker: string + pool: string + daily: string + total: string +} + +const methodology = { + UserFees: "User pays 0.3% fees on each swap.", + ProtocolRevenue: "Liquidity Providers earn a fixed APR in HSUITE tokens.", + Revenue: "All revenue generated comes from user fees.", + Fees: "All fees comes from the user." +} + +const fetch = async (timestamp: number) => { + const dayTimestamp = getUniqStartOfTodayTimestamp(new Date(timestamp * 1000)); + + // generating a random number, so to grab a random smart-node from the network.. + let randomNode = nodes[Math.floor(Math.random() * nodes.length)]; + + let volumesForPools: Array = (await asyncRetry(async() => await axios.get( + `${randomNode}/dex/analytics/volumes` + ))).data; + + let dailyVolumes = volumesForPools.reduce((acc, pool) => { + acc = new BigNumber(acc).plus(pool.daily); + return acc; + }, "0"); + + let allTimeVolumes = volumesForPools.reduce((acc, pool) => { + acc = new BigNumber(acc).plus(pool.total); + return acc; + }, "0"); + + return { + totalVolume: allTimeVolumes.toString(), + dailyVolume: dailyVolumes.toString(), + timestamp: dayTimestamp + }; +}; + +const adapter: SimpleAdapter = { + adapter: { + [CHAIN.HEDERA]: { + fetch, + start: async () => 1672531200, + meta: { + methodology + }, + runAtCurrTime: true + }, + }, +}; + +export default adapter; diff --git a/dexs/helix-markets/index.ts b/dexs/helix-markets/index.ts new file mode 100644 index 0000000000..9fe6c0ad4d --- /dev/null +++ b/dexs/helix-markets/index.ts @@ -0,0 +1,31 @@ + +import { FetchOptions, FetchResultV2, FetchV2, SimpleAdapter } from "../../adapters/types"; +import { CHAIN } from "../../helpers/chains"; +import { httpGet } from "../../utils/fetchURL"; + + +const URL = "https://dgw.helixic.io/api/v1/ticker"; +interface IVolume { + quoteVolume: string; +} + + +const fetch: FetchV2 = async (_: FetchOptions): Promise => { + const quoteVolume: IVolume[] = (await httpGet(URL)); + const dailyVolume = quoteVolume.reduce((e: number, a: IVolume) => parseFloat(a.quoteVolume) + e, 0); + return { + dailyVolume: `${dailyVolume}` + } +} + +const adapter: SimpleAdapter = { + version: 2, + adapter: { + [CHAIN.ICP]: { + fetch: fetch, + start: 1713830400, + runAtCurrTime: true, + } + } +} +export default adapter; diff --git a/dexs/hercules-v3/index.ts b/dexs/hercules-v3/index.ts new file mode 100644 index 0000000000..a6fd17f80d --- /dev/null +++ b/dexs/hercules-v3/index.ts @@ -0,0 +1,12 @@ +import { CHAIN } from "../../helpers/chains"; +import { univ2Adapter2 } from "../../helpers/getUniSubgraphVolume"; + +const adapters = univ2Adapter2({ + [CHAIN.METIS]: "https://metisapi.0xgraph.xyz/subgraphs/name/cryptoalgebra/analytics" +}, { + factoriesName: "factories", + totalVolume: "totalVolumeUSD", +}); + +adapters.adapter.metis.start = 1698983690; +export default adapters; diff --git a/dexs/hercules/index.ts b/dexs/hercules/index.ts new file mode 100644 index 0000000000..79f0cd8e70 --- /dev/null +++ b/dexs/hercules/index.ts @@ -0,0 +1,10 @@ +// https://metisapi.0xgraph.xyz/subgraphs/name/amm-subgraph-andromeda/ +import { CHAIN } from "../../helpers/chains"; +import { univ2Adapter } from "../../helpers/getUniSubgraphVolume"; + +const adapters = univ2Adapter({ + [CHAIN.METIS]: "https://metisapi.0xgraph.xyz/subgraphs/name/amm-subgraph-andromeda/" +}, {}); + +adapters.adapter.metis.start = 1710115200; +export default adapters; diff --git a/dexs/hermes-protocol/index.ts b/dexs/hermes-protocol/index.ts index 63c420584e..f46dac7a20 100644 --- a/dexs/hermes-protocol/index.ts +++ b/dexs/hermes-protocol/index.ts @@ -1,16 +1,6 @@ -import { SimpleAdapter } from "../../adapters/types"; import { CHAIN } from "../../helpers/chains"; -import { getDexVolumeExports } from "../../helpers/dexVolumeLogs"; +import { uniV2Exports } from "../../helpers/uniswap"; -const FACTORY_ADDRESS = '0x633a093C9e94f64500FC8fCBB48e90dd52F6668F' - -const adapter: SimpleAdapter = { - adapter: { - [CHAIN.METIS]: { - fetch: getDexVolumeExports({ chain: CHAIN.METIS, factory: FACTORY_ADDRESS }), - start: 1670544000, - }, - } -}; - -export default adapter; +export default uniV2Exports({ + [CHAIN.METIS]: { factory: '0x633a093C9e94f64500FC8fCBB48e90dd52F6668F', }, +}) diff --git a/dexs/hinkal/index.ts b/dexs/hinkal/index.ts new file mode 100644 index 0000000000..1643d5dff3 --- /dev/null +++ b/dexs/hinkal/index.ts @@ -0,0 +1,174 @@ +import axios from "axios"; +import { Adapter, FetchOptions, SimpleAdapter } from "../../adapters/types"; +import { CHAIN } from "../../helpers/chains"; + +const fetchEthereum = async (_t: any, _ta: any,options: FetchOptions) => { + const timestamp = options.startOfDay; + const urlTotal = `https://ethMainnet.server.hinkal.pro/totalVolume/${timestamp}/false/1`; + const urlDaily = `https://ethMainnet.server.hinkal.pro/totalVolume/${timestamp}/true/1`; + try { + const responseTotal = await axios.get(urlTotal); + const dataTotal = responseTotal.data; + const totalVolume = dataTotal.internal_volume + dataTotal.external_volume; + + const responseDaily = await axios.get(urlDaily); + const dataDaily = responseDaily.data; + const dailyVolume = dataDaily.internal_volume + dataDaily.external_volume; + return {timestamp: options.startOfDay, totalVolume, dailyVolume }; + } catch (error) { + console.error("Error fetching volume:", error); + return {timestamp: options.startOfDay, totalVolume: 0, dailyVolume: 0 }; + } +}; + +const fetchBase = async (_t: any, _ta: any,options: FetchOptions) => { + const timestamp = options.startOfDay; + const urlTotal = `https://base.server.hinkal.pro/totalVolume/${timestamp}/false/8453`; + const urlDaily = `https://base.server.hinkal.pro/totalVolume/${timestamp}/true/8453`; + try { + const responseTotal = await axios.get(urlTotal); + const dataTotal = responseTotal.data; + const totalVolume = dataTotal.internal_volume + dataTotal.external_volume; + + const responseDaily = await axios.get(urlDaily); + const dataDaily = responseDaily.data; + const dailyVolume = dataDaily.internal_volume + dataDaily.external_volume; + return {timestamp: options.startOfDay, totalVolume, dailyVolume }; + } catch (error) { + console.error("Error fetching volume:", error); + return {timestamp: options.startOfDay, totalVolume: 0, dailyVolume: 0 }; + } +}; + +const fetchArbitrum = async (_t: any, _ta: any,options: FetchOptions) => { + const timestamp = options.startOfDay; + const urlTotal = `https://arbMainnet.server.hinkal.pro/totalVolume/${timestamp}/false/42161`; + const urlDaily = `https://arbMainnet.server.hinkal.pro/totalVolume/${timestamp}/true/42161`; + try { + const responseTotal = await axios.get(urlTotal); + const dataTotal = responseTotal.data; + const totalVolume = dataTotal.internal_volume + dataTotal.external_volume; + + const responseDaily = await axios.get(urlDaily); + const dataDaily = responseDaily.data; + const dailyVolume = dataDaily.internal_volume + dataDaily.external_volume; + return {timestamp: options.startOfDay, totalVolume, dailyVolume }; + } catch (error) { + console.error("Error fetching volume:", error); + return {timestamp: options.startOfDay, totalVolume: 0, dailyVolume: 0 }; + } +}; + +const fetchPolygon = async (_t: any, _ta: any,options: FetchOptions) => { + const timestamp = options.startOfDay; + const urlTotal = `https://polygon.server.hinkal.pro/totalVolume/${timestamp}/false/137`; + const urlDaily = `https://polygon.server.hinkal.pro/totalVolume/${timestamp}/true/137`; + try { + const responseTotal = await axios.get(urlTotal); + const dataTotal = responseTotal.data; + const totalVolume = dataTotal.internal_volume + dataTotal.external_volume; + + const responseDaily = await axios.get(urlDaily); + const dataDaily = responseDaily.data; + const dailyVolume = dataDaily.internal_volume + dataDaily.external_volume; + return {timestamp: options.startOfDay, totalVolume, dailyVolume }; + } catch (error) { + console.error("Error fetching volume:", error); + return {timestamp: options.startOfDay, totalVolume: 0, dailyVolume: 0 }; + } +}; + +const fetchBNB = async (_t: any, _ta: any,options: FetchOptions) => { + const timestamp = options.startOfDay; + const urlTotal = `https://bnbMainnet.server.hinkal.pro/totalVolume/${timestamp}/false/56`; + const urlDaily = `https://bnbMainnet.server.hinkal.pro/totalVolume/${timestamp}/true/56`; + try { + const responseTotal = await axios.get(urlTotal); + const dataTotal = responseTotal.data; + const totalVolume = dataTotal.internal_volume + dataTotal.external_volume; + + const responseDaily = await axios.get(urlDaily); + const dataDaily = responseDaily.data; + const dailyVolume = dataDaily.internal_volume + dataDaily.external_volume; + return {timestamp: options.startOfDay, totalVolume, dailyVolume }; + } catch (error) { + console.error("Error fetching volume:", error); + return {timestamp: options.startOfDay, totalVolume: 0, dailyVolume: 0 }; + } +}; + +const fetchAVALANCHE = async (_t: any, _ta: any,options: FetchOptions) => { + const timestamp = options.startOfDay; + const urlTotal = `https://avalanche.server.hinkal.pro/totalVolume/${timestamp}/false/43114`; + const urlDaily = `https://avalanche.server.hinkal.pro/totalVolume/${timestamp}/true/43114`; + try { + const responseTotal = await axios.get(urlTotal); + const dataTotal = responseTotal.data; + const totalVolume = dataTotal.internal_volume + dataTotal.external_volume; + + const responseDaily = await axios.get(urlDaily); + const dataDaily = responseDaily.data; + const dailyVolume = dataDaily.internal_volume + dataDaily.external_volume; + return {timestamp: options.startOfDay, totalVolume, dailyVolume }; + } catch (error) { + console.error("Error fetching volume:", error); + return {timestamp: options.startOfDay, totalVolume: 0, dailyVolume: 0 }; + } +}; + +const fetchOPTIMISM = async (_t: any, _ta: any,options: FetchOptions) => { + const timestamp = options.startOfDay; + const urlTotal = `https://optimism.server.hinkal.pro/totalVolume/${timestamp}/false/10`; + const urlDaily = `https://optimism.server.hinkal.pro/totalVolume/${timestamp}/true/10`; + try { + const responseTotal = await axios.get(urlTotal); + const dataTotal = responseTotal.data; + const totalVolume = dataTotal.internal_volume + dataTotal.external_volume; + + const responseDaily = await axios.get(urlDaily); + const dataDaily = responseDaily.data; + const dailyVolume = dataDaily.internal_volume + dataDaily.external_volume; + return {timestamp: options.startOfDay, totalVolume, dailyVolume }; + } catch (error) { + console.error("Error fetching volume:", error); + return {timestamp: options.startOfDay, totalVolume: 0, dailyVolume: 0 }; + } +}; + +const fetchBLAST = async (_t: any, _ta: any,options: FetchOptions) => { + const timestamp = options.startOfDay; + const urlTotal = `https://blast.server.hinkal.pro/totalVolume/${timestamp}/false/81457`; + const urlDaily = `https://blast.server.hinkal.pro/totalVolume/${timestamp}/true/81457`; + try { + const responseTotal = await axios.get(urlTotal); + const dataTotal = responseTotal.data; + const totalVolume = dataTotal.internal_volume + dataTotal.external_volume; + + const responseDaily = await axios.get(urlDaily); + const dataDaily = responseDaily.data; + const dailyVolume = dataDaily.internal_volume + dataDaily.external_volume; + return {timestamp: options.startOfDay, totalVolume, dailyVolume }; + } catch (error) { + console.error("Error fetching volume:", error); + return {timestamp: options.startOfDay, totalVolume: 0, dailyVolume: 0 }; + } +}; + +const adapter: SimpleAdapter = { + version: 1, + adapter: { + [CHAIN.ETHEREUM]: { + fetch: fetchEthereum, + start: 1713561695, + }, + [CHAIN.BASE]: { fetch: fetchBase, start: 1713561695 }, + [CHAIN.ARBITRUM]: { fetch: fetchArbitrum, start: 1713561695 }, + [CHAIN.POLYGON]: { fetch: fetchPolygon, start: 1713561695 }, + [CHAIN.BSC]: { fetch: fetchBNB, start: 1713561695 }, + [CHAIN.AVAX]: { fetch: fetchAVALANCHE, start: 1713561695 }, + [CHAIN.OPTIMISM]: { fetch: fetchOPTIMISM, start: 1713561695 }, + [CHAIN.BLAST]: { fetch: fetchBLAST, start: 1713561695 }, + }, +}; + +export default adapter; diff --git a/dexs/hmx/index.ts b/dexs/hmx/index.ts index 05131417b2..b32e900090 100644 --- a/dexs/hmx/index.ts +++ b/dexs/hmx/index.ts @@ -1,12 +1,15 @@ import { Adapter } from "../../adapters/types"; import { CHAIN } from "../../helpers/chains"; -import { request, gql, GraphQLClient } from "graphql-request"; +import { gql, GraphQLClient } from "graphql-request"; import type { ChainEndpoints } from "../../adapters/types"; import { Chain } from "@defillama/sdk/build/general"; import { HOUR, getTimestampAtStartOfHour } from "../../utils/date"; const endpoints = { - [CHAIN.ARBITRUM]: "https://subgraph.satsuma-prod.com/3a60064481e5/1lxclx3pz4zrusx6414nvj/arbitrum-one-stats/api", + [CHAIN.ARBITRUM]: + "https://subgraph.satsuma-prod.com/3a60064481e5/1lxclx3pz4zrusx6414nvj/arbitrum-one-stats/api", + [CHAIN.BLAST]: + "https://api.studio.thegraph.com/query/45963/blast-mainnet-stats/version/latest", }; type MarketStat = { @@ -17,7 +20,7 @@ type MarketStat = { const graphs = (graphUrls: ChainEndpoints) => { return (chain: Chain) => { return async (timestamp: number) => { - if (chain === CHAIN.ARBITRUM) { + if (chain === CHAIN.ARBITRUM || chain === CHAIN.BLAST) { // Get total trading volume const totalTradingVolumeQuery = gql` { @@ -28,7 +31,7 @@ const graphs = (graphUrls: ChainEndpoints) => { } `; const graphQLClient = new GraphQLClient(graphUrls[chain]); - graphQLClient.setHeader('origin', 'https://hmx.org') + graphQLClient.setHeader("origin", "https://hmx.org"); const totalMarketStats = ( await graphQLClient.request(totalTradingVolumeQuery) ).marketStats as Array; @@ -39,23 +42,32 @@ const graphs = (graphUrls: ChainEndpoints) => { 0 as number ) / 1e30; - // Get daily trading volume - const ids: Array = []; - let latestHourIndex = Math.floor( - getTimestampAtStartOfHour(timestamp) / HOUR - ); - for (let i = 0; i < 24; i++) { - for (const marketStat of totalMarketStats) { - ids.push(`"${latestHourIndex - i}_${marketStat.id}"`); - } + const chunkSize = 10; + const splitMarket: MarketStat[][] = []; + for (let i = 0; i < totalMarketStats.length; i += chunkSize) { + const chunk = totalMarketStats.slice(i, i + chunkSize); + splitMarket.push(chunk); } - const filter = ids.join(","); - // first 2400 should covers 100 markets last 24 hours - // which virtually covers all markets - const last24hrVolumeQuery = gql` + + let last24hrVolume = 0; + for (const markets of splitMarket) { + // Get daily trading volume + const ids: Array = []; + let latestHourIndex = Math.floor( + getTimestampAtStartOfHour(timestamp) / HOUR + ); + + for (const marketStat of markets) { + for (let i = 1; i < 25; i++) { + ids.push(`"${latestHourIndex - i}_${marketStat.id}"`); + } + } + + const filter = ids.join(","); + + const last24hrVolumeQuery = gql` { marketHourlyStats( - first: 2400 where: { id_in: [${filter}] } @@ -64,14 +76,17 @@ const graphs = (graphUrls: ChainEndpoints) => { } } `; - const last24hrMarketStats = ( - await graphQLClient.request(last24hrVolumeQuery) - ).marketHourlyStats as Array<{ tradingVolume: string }>; - const last24hrVolume = - last24hrMarketStats.reduce( - (accum, t) => accum + parseInt(t.tradingVolume), - 0 as number - ) / 1e30; + + const last24hrMarketStats = ( + await graphQLClient.request(last24hrVolumeQuery) + ).marketHourlyStats as Array<{ tradingVolume: string }>; + + last24hrVolume += + last24hrMarketStats.reduce( + (accum, t) => accum + parseInt(t.tradingVolume), + 0 as number + ) / 1e30; + } return { timestamp, @@ -95,6 +110,10 @@ const adapter: Adapter = { fetch: graphs(endpoints)(CHAIN.ARBITRUM), start: 1687806000, }, + [CHAIN.BLAST]: { + fetch: graphs(endpoints)(CHAIN.BLAST), + start: 1707094598, + }, }, }; diff --git a/dexs/holdr/index.ts b/dexs/holdr/index.ts index 135ea7495a..dd234f5519 100644 --- a/dexs/holdr/index.ts +++ b/dexs/holdr/index.ts @@ -1,11 +1,14 @@ +import * as sdk from "@defillama/sdk"; import { ChainEndpoints, SimpleAdapter } from "../../adapters/types"; -import { getChainVolume } from "../../helpers/getUniSubgraphVolume"; +import { getChainVolume2 } from "../../helpers/getUniSubgraphVolume"; import { CHAIN } from "../../helpers/chains"; import { Chain } from "@defillama/sdk/build/general"; import customBackfill from "../../helpers/customBackfill"; const endpoints: ChainEndpoints = { - [CHAIN.AURORA]: "https://api.thegraph.com/subgraphs/name/kyzooghost/balancer_aurora_fork", + [CHAIN.AURORA]: sdk.graph.modifyEndpoint( + "5Yn3qgjM8y6KnN1jZd8TjcDLPRioVpiTC46XYgEwK56S", + ), }; const graphParams = { @@ -13,21 +16,20 @@ const graphParams = { factory: "balancers", field: "totalSwapVolume", }, - hasDailyVolume: false, -} +}; -const v1graphs = getChainVolume({ +const v1graphs = getChainVolume2({ graphUrls: endpoints, - ...graphParams + ...graphParams, }); - const adapter: SimpleAdapter = { + version: 2, adapter: { [CHAIN.AURORA]: { fetch: v1graphs(CHAIN.AURORA as Chain), start: 1672531200, - customBackfill: customBackfill(CHAIN.AURORA as Chain, v1graphs) + customBackfill: customBackfill(CHAIN.AURORA as Chain, v1graphs), }, }, }; diff --git a/dexs/horiza/index.ts b/dexs/horiza/index.ts index d84a44b2d6..fb96a97237 100644 --- a/dexs/horiza/index.ts +++ b/dexs/horiza/index.ts @@ -1,21 +1,17 @@ import { SimpleAdapter } from "../../adapters/types"; import { CHAIN } from "../../helpers/chains"; -import { DEFAULT_DAILY_VOLUME_FACTORY, DEFAULT_TOTAL_VOLUME_FIELD, getGraphDimensions } from "../../helpers/getUniSubgraph"; +import { DEFAULT_TOTAL_VOLUME_FIELD, getGraphDimensions2 } from "../../helpers/getUniSubgraph"; const endpointV3 = { [CHAIN.ARBITRUM]: 'https://subgraph-prod.goerli.horiza.io/subgraphs/name/retro-arbitrum-one-uniswap-v3' } -const VOLUME_USD = 'volumeUSD' -const v3Graphs = getGraphDimensions({ + +const v3Graphs = getGraphDimensions2({ graphUrls: endpointV3, totalVolume: { factory: "factories", field: DEFAULT_TOTAL_VOLUME_FIELD, }, - dailyVolume: { - factory: DEFAULT_DAILY_VOLUME_FACTORY, - field: VOLUME_USD, - }, feesPercent: { type: "fees", ProtocolRevenue: 10, @@ -27,6 +23,7 @@ const v3Graphs = getGraphDimensions({ }); const adapters: SimpleAdapter = { + version: 2, adapter: { [CHAIN.ARBITRUM]: { fetch: v3Graphs(CHAIN.ARBITRUM), diff --git a/dexs/horizondex/index.ts b/dexs/horizondex/index.ts index 26507eb896..18d8fbc7f4 100644 --- a/dexs/horizondex/index.ts +++ b/dexs/horizondex/index.ts @@ -12,6 +12,7 @@ const adapters = univ2Adapter({ }); adapters.adapter.linea.start = 1689373614; +adapters.adapter.linea.fetch = async (timestamp: number) => { return { timestamp } }; adapters.adapter.base.start = 1690894800; export default adapters; diff --git a/dexs/huckleberry/index.ts b/dexs/huckleberry/index.ts index 5d0b7be501..0669fa0729 100644 --- a/dexs/huckleberry/index.ts +++ b/dexs/huckleberry/index.ts @@ -1,7 +1,8 @@ +import * as sdk from "@defillama/sdk"; import { CHAIN } from "../../helpers/chains"; import { univ2Adapter } from "../../helpers/getUniSubgraphVolume"; export default univ2Adapter({ - [CHAIN.MOONRIVER]: "https://api.thegraph.com/subgraphs/name/huckleberrydex/huckleberry-subgraph", + [CHAIN.MOONRIVER]: sdk.graph.modifyEndpoint('EMTH8qnNbMGgjoFxE8YZh4qGMMxTQu44WDbn2xKexzwb'), // [CHAIN.CLV]: "https://clover-graph-node.huckleberry.finance/subgraphs/name/huckleberry/clv-parachain-subgraph" }, {}); diff --git a/dexs/hydradex/index.ts b/dexs/hydradex/index.ts index e422a69461..326a8d2227 100644 --- a/dexs/hydradex/index.ts +++ b/dexs/hydradex/index.ts @@ -2,21 +2,13 @@ import { Chain } from '@defillama/sdk/build/general'; import { BreakdownAdapter, BaseAdapter, DISABLED_ADAPTER_KEY } from '../../adapters/types'; import { CHAIN } from '../../helpers/chains'; import { getStartTimestamp } from '../../helpers/getStartTimestamp'; - import { - getGraphDimensions, - DEFAULT_DAILY_VOLUME_FACTORY, - DEFAULT_TOTAL_VOLUME_FIELD, - DEFAULT_DAILY_VOLUME_FIELD, wrapGraphError, + getGraphDimensions2, } from '../../helpers/getUniSubgraph'; -import request, { gql } from 'graphql-request'; +import request from 'graphql-request'; import disabledAdapter from '../../helpers/disabledAdapter'; -const v2Endpoints = { - [CHAIN.HYDRA]: 'https://info.hydradex.org/graphql', -}; - const v3Endpoints = { [CHAIN.HYDRA]: 'https://graph.hydradex.org/subgraphs/name/v3-subgraph', }; @@ -24,22 +16,6 @@ const v3Endpoints = { const VOLUME_USD = 'volumeUSD'; const FEES_USD = 'feesUSD'; -const getV2CustomBlock = async (timestamp: number) => { - const blockGraphQuery = ` - query get_block { - blocks(orderBy: "height", first: 1, orderDirection: "desc", where: { timestamp_lte: ${timestamp} }) { - number - } - } - `; - try { - const blocks = (await request(v2Endpoints[CHAIN.HYDRA], blockGraphQuery)).blocks; - return Number(blocks[0].number); - } catch (e) { - throw new Error(`Error getting block: ${CHAIN.HYDRA} ${timestamp} ${wrapGraphError(e).message}`) - } -}; - const getV3CustomBlock = async (timestamp: number) => { const blockGraphQuery = ` query get_block { @@ -59,43 +35,12 @@ const getV3CustomBlock = async (timestamp: number) => { } }; -const v2Graph = getGraphDimensions({ - graphUrls: v2Endpoints, - feesPercent: { - type: 'volume', - UserFees: 0.3, - ProtocolRevenue: 0, - SupplySideRevenue: 0.3, - HoldersRevenue: 0, - Revenue: 0, - Fees: 0.3, - }, - totalVolume: { - factory: 'hydraswapFactories', - field: DEFAULT_TOTAL_VOLUME_FIELD, - blockGraphType: 'Float!', - }, - dailyVolume: { - factory: 'getHydraswapDayDataById', - field: DEFAULT_DAILY_VOLUME_FIELD, - idGraphType: 'String!', - }, - dailyFees: { - factory: 'hydraswapDayData', - }, - getCustomBlock: getV2CustomBlock, -}); - -const v3Graphs = getGraphDimensions({ +const v3Graphs = getGraphDimensions2({ graphUrls: v3Endpoints, totalVolume: { factory: 'factories', field: VOLUME_USD, }, - dailyVolume: { - factory: DEFAULT_DAILY_VOLUME_FACTORY, - field: VOLUME_USD, - }, feesPercent: { type: 'fees', ProtocolRevenue: 0, @@ -118,16 +63,17 @@ const methodology = { }; const adapter: BreakdownAdapter = { + version: 2, breakdown: { v2: { [DISABLED_ADAPTER_KEY]: disabledAdapter, [CHAIN.HYDRA]: { - fetch: v2Graph(CHAIN.HYDRA), - start: getStartTimestamp({ - endpoints: v2Endpoints, - chain: CHAIN.HYDRA, - dailyDataField: 'hydraswapDayDatas', - }), + fetch: async (timestamp: number) => { + return { + timestamp + } + }, + start: 0, meta: { methodology, }, diff --git a/dexs/hyperjump/index.ts b/dexs/hyperjump/index.ts index 9cb50847cd..71647baf14 100644 --- a/dexs/hyperjump/index.ts +++ b/dexs/hyperjump/index.ts @@ -1,8 +1,9 @@ +import * as sdk from "@defillama/sdk"; import { univ2Adapter } from "../../helpers/getUniSubgraphVolume"; import { CHAIN } from "../../helpers/chains"; const endpoints = { - [CHAIN.BSC]: "https://api.thegraph.com/subgraphs/name/angry-mech/hyperjump-bsc-main", + [CHAIN.BSC]: sdk.graph.modifyEndpoint('5fWfhux2ZJbU33j7Z1sn6m4vj7N7vapTj9hBKeZ5uyaU'), }; const adapter = univ2Adapter(endpoints, { diff --git a/dexs/hyperliquid/index.ts b/dexs/hyperliquid/index.ts index 0702d0c1bb..1a1cdd80ee 100644 --- a/dexs/hyperliquid/index.ts +++ b/dexs/hyperliquid/index.ts @@ -1,7 +1,7 @@ import type { SimpleAdapter } from "../../adapters/types"; import { getUniqStartOfTodayTimestamp } from "../../helpers/getUniSubgraphVolume"; import { CHAIN } from "../../helpers/chains"; -import { httpPost } from "../../utils/fetchURL"; +import { httpGet, httpPost } from "../../utils/fetchURL"; const URL = "https://api.hyperliquid.xyz/info"; @@ -23,7 +23,7 @@ const fetch = async (timestamp: number) => { const adapter: SimpleAdapter = { adapter: { - [CHAIN.ARBITRUM]: { + "hyperliquid": { fetch, start: 1677283200, }, diff --git a/dexs/icpswap/index.ts b/dexs/icpswap/index.ts index bb4ff9d86f..eeeea0b488 100644 --- a/dexs/icpswap/index.ts +++ b/dexs/icpswap/index.ts @@ -1,39 +1,14 @@ import { Adapter, FetchResultVolume } from "../../adapters/types" import { CHAIN } from "../../helpers/chains"; -import { getUniqStartOfTodayTimestamp } from "../../helpers/getUniSubgraphVolume"; -import { getTimestampAtStartOfDayUTC } from "../../utils/date"; +import { getUniqStartOfTodayTimestamp } from "../../helpers/getUniSubgraph/utils"; import fetchURL from "../../utils/fetchURL"; -const pairsURL = "https://uvevg-iyaaa-aaaak-ac27q-cai.raw.ic0.app/pairs"; -const volumeURL = (pool_id: string) => `https://uvevg-iyaaa-aaaak-ac27q-cai.raw.ic0.app/totalVolumeUSD?poolId=${pool_id}&limit=1000`; - -interface IPairs { - pool_id: string; - ticker_id: string; - base: string; - target: string; -} - -interface IVolume { - day: string; - totalVolumeUSD: string; - volumeUSDChange: string; - volumeUSD: string; -} -const pairs: IPairs[] = [{"ticker_id": "CHAT_GHOST","base": "CHAT","target": "GHOST","pool_id": "m6cnd-wiaaa-aaaag-qchkq-cai"},{"ticker_id": "TENDY_KINIC","base": "TENDY","target": "KINIC","pool_id": "344ln-paaaa-aaaag-qcdkq-cai"},{"ticker_id": "CHAT_TENDY","base": "CHAT","target": "TENDY","pool_id": "ebw3a-fiaaa-aaaag-qcbda-cai"},{"ticker_id": "DOGMI_ICP","base": "DOGMI","target": "ICP","pool_id": "pkhyt-7iaaa-aaaag-qca7a-cai"},{"ticker_id": "TENDY_BABY AROF token","base": "TENDY","target": "BABY AROF token","pool_id": "3o24u-dqaaa-aaaag-qcdjq-cai"},{"ticker_id": "TENDY_CLOUD","base": "TENDY","target": "CLOUD","pool_id": "2yre7-waaaa-aaaag-qcdmq-cai"},{"ticker_id": "ckBTC_ICP","base": "ckBTC","target": "ICP","pool_id": "xmiu5-jqaaa-aaaag-qbz7q-cai"},{"ticker_id": "CHAT_ICL","base": "CHAT","target": "ICL","pool_id": "yt4cy-4yaaa-aaaag-qce5q-cai"},{"ticker_id": "ICP_NDP","base": "ICP","target": "NDP","pool_id": "yp7ey-cyaaa-aaaag-qblqq-cai"},{"ticker_id": "DMD_ICP","base": "DMD","target": "ICP","pool_id": "3ynik-taaaa-aaaag-qblya-cai"},{"ticker_id": "GHOST_ICP","base": "GHOST","target": "ICP","pool_id": "dwahc-eyaaa-aaaag-qcgnq-cai"},{"ticker_id": "BOX_ICP","base": "BOX","target": "ICP","pool_id": "yg4pe-uqaaa-aaaag-qblra-cai"},{"ticker_id": "KINIC_ICP","base": "KINIC","target": "ICP","pool_id": "335nz-cyaaa-aaaag-qcdka-cai"},{"ticker_id": "GHOST_BABY AROF token","base": "GHOST","target": "BABY AROF token","pool_id": "6vaaf-faaaa-aaaag-qcdwq-cai"},{"ticker_id": "OGY_ICP","base": "OGY","target": "ICP","pool_id": "yu2y5-yaaaa-aaaag-qblsa-cai"},{"ticker_id": "TENDY_ALIEN","base": "TENDY","target": "ALIEN","pool_id": "rghwb-niaaa-aaaag-qccta-cai"},{"ticker_id": "_ICP","base": "","target": "ICP","pool_id": "5ufyj-eiaaa-aaaag-qblpq-cai"},{"ticker_id": "$LAND_ICP","base": "$LAND","target": "ICP","pool_id": "zlslk-3yaaa-aaaag-qblwq-cai"},{"ticker_id": "TENDY_SNS1","base": "TENDY","target": "SNS1","pool_id": "etqmz-jyaaa-aaaag-qcbaa-cai"},{"ticker_id": "🥕_ICP","base": "🥕","target": "ICP","pool_id": "zmtn6-waaaa-aaaag-qblwa-cai"},{"ticker_id": "ICP_","base": "ICP","target": "","pool_id": "f6zug-pqaaa-aaaag-qboiq-cai"},{"ticker_id": "GHOST_SNS1","base": "GHOST","target": "SNS1","pool_id": "p4xq4-gyaaa-aaaag-qchbq-cai"},{"ticker_id": "TENDY_SPICE","base": "TENDY","target": "SPICE","pool_id": "to5je-7iaaa-aaaag-qcc7a-cai"},{"ticker_id": "ICYPEES_SPICE","base": "ICYPEES","target": "SPICE","pool_id": "tj4pq-sqaaa-aaaag-qcc7q-cai"},{"ticker_id": "STAR_ICP","base": "STAR","target": "ICP","pool_id": "y2yvv-dqaaa-aaaag-qblta-cai"},{"ticker_id": "ICP_ALIEN","base": "ICP","target": "ALIEN","pool_id": "r5cke-xqaaa-aaaag-qccrq-cai"},{"ticker_id": "GHOST_WOJAKIC","base": "GHOST","target": "WOJAKIC","pool_id": "62vrv-pyaaa-aaaag-qcigq-cai"},{"ticker_id": "WOJAKIC_ICP","base": "WOJAKIC","target": "ICP","pool_id": "qckzt-uiaaa-aaaag-qccva-cai"},{"ticker_id": "ICYPEES_ICP","base": "ICYPEES","target": "ICP","pool_id": "y5ztb-oiaaa-aaaag-qbltq-cai"},{"ticker_id": "TENDY_OGY","base": "TENDY","target": "OGY","pool_id": "vlws3-6iaaa-aaaag-qccja-cai"},{"ticker_id": "ICL_ICP","base": "ICL","target": "ICP","pool_id": "zqxxp-baaaa-aaaag-qblua-cai"},{"ticker_id": "PLAT_ICP","base": "PLAT","target": "ICP","pool_id": "3rodw-fiaaa-aaaag-qblzq-cai"},{"ticker_id": "SONICX_ICP","base": "SONICX","target": "ICP","pool_id": "6ktdw-kyaaa-aaaag-qcejq-cai"},{"ticker_id": "TENDY_GHOST","base": "TENDY","target": "GHOST","pool_id": "3kmdc-wqaaa-aaaag-qceua-cai"},{"ticker_id": "CHAT_ckBTC","base": "CHAT","target": "ckBTC","pool_id": "nm7k6-wyaaa-aaaag-qcasa-cai"},{"ticker_id": "XCANIC_SNS1","base": "XCANIC","target": "SNS1","pool_id": "ntmjn-zaaaa-aaaag-qchna-cai"},{"ticker_id": "SPICE_SNS1","base": "SPICE","target": "SNS1","pool_id": "howsv-wqaaa-aaaag-qcgua-cai"},{"ticker_id": "HOT_ICP","base": "HOT","target": "ICP","pool_id": "rxwy2-zaaaa-aaaag-qcfna-cai"},{"ticker_id": "BABY AROF token_ICP","base": "BABY AROF token","target": "ICP","pool_id": "s7qlk-oaaaa-aaaag-qbnvq-cai"},{"ticker_id": "EMC_ICP","base": "EMC","target": "ICP","pool_id": "fx5dl-qyaaa-aaaag-qcbga-cai"},{"ticker_id": "WHALE_ICP","base": "WHALE","target": "ICP","pool_id": "zzu4t-xiaaa-aaaag-qblvq-cai"},{"ticker_id": "GHOST_GHOST","base": "GHOST","target": "GHOST","pool_id": "ddhwp-fqaaa-aaaag-qcgoa-cai"},{"ticker_id": "ICP_SPICE","base": "ICP","target": "SPICE","pool_id": "x7ixp-3iaaa-aaaag-qccha-cai"},{"ticker_id": "DOGMI_DOGMI","base": "DOGMI","target": "DOGMI","pool_id": "pdetp-jaaaa-aaaag-qca6q-cai"},{"ticker_id": "CHAT_ICP","base": "CHAT","target": "ICP","pool_id": "ne2vj-6yaaa-aaaag-qb3ia-cai"},{"ticker_id": "TENDY_ICYPEES","base": "TENDY","target": "ICYPEES","pool_id": "png6h-sqaaa-aaaag-qca7q-cai"},{"ticker_id": "GHOST_ICP","base": "GHOST","target": "ICP","pool_id": "yi6cm-paaaa-aaaag-qblqa-cai"},{"ticker_id": "AVOCADO_ICP","base": "AVOCADO","target": "ICP","pool_id": "zfqgc-aiaaa-aaaag-qblxq-cai"},{"ticker_id": "GHOST_TENDY","base": "GHOST","target": "TENDY","pool_id": "on5od-6qaaa-aaaag-qchea-cai"},{"ticker_id": "TENDY_ckBTC","base": "TENDY","target": "ckBTC","pool_id": "dswyu-ryaaa-aaaag-qcbqa-cai"},{"ticker_id": "GHOST_EMC","base": "GHOST","target": "EMC","pool_id": "psv5u-5iaaa-aaaag-qchaq-cai"},{"ticker_id": "DOGMI_ICP","base": "DOGMI","target": "ICP","pool_id": "yt36j-vyaaa-aaaag-qblsq-cai"},{"ticker_id": "01_ICP","base": "01","target": "ICP","pool_id": "37mo6-6yaaa-aaaag-qblyq-cai"},{"ticker_id": "CHAT_GHOST","base": "CHAT","target": "GHOST","pool_id": "nl6mk-3aaaa-aaaag-qcasq-cai"},{"ticker_id": "TENDY_","base": "TENDY","target": "","pool_id": "w7thl-xiaaa-aaaag-qcf4q-cai"},{"ticker_id": "ICD_ICP","base": "ICD","target": "ICP","pool_id": "zxwr3-myaaa-aaaag-qbluq-cai"},{"ticker_id": "XCANIC_ICP","base": "XCANIC","target": "ICP","pool_id": "z6v2h-2qaaa-aaaag-qblva-cai"},{"ticker_id": "TENDY_EMC","base": "TENDY","target": "EMC","pool_id": "q2y4u-wiaaa-aaaag-qcfkq-cai"},{"ticker_id": "ICP_SNS1","base": "ICP","target": "SNS1","pool_id": "3ejs3-eaaaa-aaaag-qbl2a-cai"},{"ticker_id": "WOJAKIC_GHOST","base": "WOJAKIC","target": "GHOST","pool_id": "5rdhw-jaaaa-aaaag-qcima-cai"},{"ticker_id": "CLOUD_ICP","base": "CLOUD","target": "ICP","pool_id": "3s6gf-uqaaa-aaaag-qcdlq-cai"},{"ticker_id": "ckBTC_SNS1","base": "ckBTC","target": "SNS1","pool_id": "nx2w3-maaaa-aaaag-qcaqq-cai"},{"ticker_id": "ICL_TENDY","base": "ICL","target": "TENDY","pool_id": "eivq4-taaaa-aaaag-qcbcq-cai"},{"ticker_id": "CHAT_","base": "CHAT","target": "","pool_id": "nzy3t-xqaaa-aaaag-qcarq-cai"},{"ticker_id": "TENDY_ICP","base": "TENDY","target": "ICP","pool_id": "ojlrv-lqaaa-aaaag-qcazq-cai"}]; - const fetch = async (timestamp: number): Promise => { - const pools = pairs.map((e: IPairs) => e.pool_id); - const todayTimestamp = getUniqStartOfTodayTimestamp(new Date(timestamp * 1000)); - const dateId = Math.floor(getTimestampAtStartOfDayUTC(todayTimestamp) / 86400) - const historicalVolume: IVolume[] = (await Promise.all(pools.map((e: string) => fetchURL(volumeURL(e))))).map((e: any) => e).flat(); - const dailyVolume = historicalVolume.filter((e: IVolume) => Number(e.day) === dateId) - .reduce((a: number, b: IVolume) => a + Number(b.volumeUSD), 0) - const totalVolume = historicalVolume.filter((e: IVolume) => Number(e.day) <= dateId) - .reduce((a: number, b: IVolume) => a + Number(b.totalVolumeUSD), 0) + const { volumeUSD } = await fetchURL('https://uvevg-iyaaa-aaaak-ac27q-cai.raw.ic0.app/overview') + + timestamp = getUniqStartOfTodayTimestamp(new Date(timestamp * 1000)); return { - dailyVolume: `${dailyVolume}`, - totalVolume: `${totalVolume}`, + dailyVolume: volumeUSD, timestamp } } @@ -43,6 +18,7 @@ const adapter: Adapter = { adapter: { [CHAIN.ICP]: { fetch: fetch, + runAtCurrTime: true, start: 1689465600, }, } diff --git a/dexs/immortalx/index.ts b/dexs/immortalx/index.ts index 2a030470e9..f0a3d5930b 100644 --- a/dexs/immortalx/index.ts +++ b/dexs/immortalx/index.ts @@ -1,3 +1,4 @@ +import * as sdk from "@defillama/sdk"; import { Chain } from "@defillama/sdk/build/general"; import request, { gql } from "graphql-request"; import { Adapter, FetchResultVolume } from "../../adapters/types"; @@ -18,7 +19,7 @@ type IURL = { }; const endpoints: IURL = { - [CHAIN.CELO]: "https://api.thegraph.com/subgraphs/name/immortalx-io/immortalx", + [CHAIN.CELO]: sdk.graph.modifyEndpoint('DGN3dMffNnXZRAHFyCAq3csJbe2o7g9Jdg2XHe2mzVdG'), }; const fetch = (chain: Chain) => { diff --git a/dexs/increment-protocol/index.ts b/dexs/increment-protocol/index.ts new file mode 100644 index 0000000000..95df7609ec --- /dev/null +++ b/dexs/increment-protocol/index.ts @@ -0,0 +1,35 @@ +import { request, gql } from "graphql-request"; + +const subgraphUrl = + "https://subgraph.increment.finance/subgraphs/name/Increment-Finance/subgraph"; + +const volumeQuery = gql` + query volumeQuery($endTimestamp: Int!) { + dailyCandles( + orderBy: openTimestamp + orderDirection: desc + first: 24 + where: { openTimestamp: $endTimestamp } + ) { + volume + } + } +`; + +export default { + adapter: { + era: { + fetch: async (_t: any, _c: any, { endTimestamp }) => { + const volumeData = await request(subgraphUrl, volumeQuery, { + endTimestamp: endTimestamp ?? Math.floor(Date.now() / 1000) + }); + const dailyVolume = volumeData.dailyCandles.reduce( + (acc, { volume }) => acc + volume * 10 ** -18, + 0 + ); + return { dailyVolume }; + }, + start: 1710720000 + } + } +}; diff --git a/dexs/integral/index.ts b/dexs/integral/index.ts index 977a4f31b5..66769b2ded 100644 --- a/dexs/integral/index.ts +++ b/dexs/integral/index.ts @@ -1,9 +1,10 @@ +import * as sdk from "@defillama/sdk"; import { BaseAdapter, SimpleAdapter } from "../../adapters/types"; import { getStartTimestamp } from "../../helpers/getStartTimestamp"; import { DEFAULT_DAILY_VOLUME_FIELD, DEFAULT_TOTAL_VOLUME_FIELD, - getChainVolume, + getChainVolume2, } from "../../helpers/getUniSubgraphVolume"; import { CHAIN } from "../../helpers/chains"; import { Chain } from "@defillama/sdk/build/general"; @@ -14,24 +15,21 @@ export const chains = [ ]; export const endpoints = { [CHAIN.ETHEREUM]: - "https://api.thegraph.com/subgraphs/name/integralhq/integral-size", + sdk.graph.modifyEndpoint('ANd5QJuYtyfngmXvBMu9kZAv935vhcqp4xAGBkmCADN3'), [CHAIN.ARBITRUM]: - "https://api.thegraph.com/subgraphs/name/integralhq/integral-size-arbitrum", + sdk.graph.modifyEndpoint('HXeVedRK7VgogXwbK5Sc4mjyLkhBAS5akskRvbSYnkHU'), }; -const graphs = getChainVolume({ +const graphs = getChainVolume2({ graphUrls: endpoints, totalVolume: { factory: "factories", field: DEFAULT_TOTAL_VOLUME_FIELD, }, - dailyVolume: { - factory: "dayData", - field: DEFAULT_DAILY_VOLUME_FIELD, - }, }); const adapter: SimpleAdapter = { + version: 2, adapter: chains.reduce((acc, chain) => { return { ...acc, diff --git a/dexs/intent-x/index.tsx b/dexs/intent-x/index.tsx index 322cb02396..85857769ca 100644 --- a/dexs/intent-x/index.tsx +++ b/dexs/intent-x/index.tsx @@ -1,15 +1,19 @@ +import BigNumber from "bignumber.js"; import request, { gql } from "graphql-request"; import { FetchResultVolume, SimpleAdapter } from "../../adapters/types"; import { CHAIN } from "../../helpers/chains"; -import BigNumber from "bignumber.js"; import { getUniqStartOfTodayTimestamp } from "../../helpers/getUniSubgraphVolume"; const ONE_DAY_IN_SECONDS = 60 * 60 * 24; const endpoint_0_8_0 = - "https://api.thegraph.com/subgraphs/name/intent-x/perpetuals-analytics_base"; + "https://api.studio.thegraph.com/query/62472/perpetuals-analytics_base/version/latest"; const endpoint = - "https://api.studio.thegraph.com/query/62472/intentx-analytics_082/version/latest"; + "https://api.goldsky.com/api/public/project_cm0bho0j0ji6001t8e26s0wv8/subgraphs/intentx-base-analytics-083/latest/gn"; +const endpoint_blast = + "https://api.goldsky.com/api/public/project_cm0bho0j0ji6001t8e26s0wv8/subgraphs/intentx-blast-analytics-083/latest/gn"; +const endpoint_mantle = + "https://api.goldsky.com/api/public/project_cm0bho0j0ji6001t8e26s0wv8/subgraphs/intentx-mantle-analytics-083/latest/gn"; const query_0_8_0 = gql` query stats($from: String!, $to: String!) { @@ -61,6 +65,56 @@ const query = gql` } `; +const queryBlast = gql` + query stats($from: String!, $to: String!) { + dailyHistories( + where: { + timestamp_gte: $from + timestamp_lte: $to + accountSource: "0x083267D20Dbe6C2b0A83Bd0E601dC2299eD99015" + } + ) { + timestamp + platformFee + accountSource + tradeVolume + } + totalHistories( + where: { accountSource: "0x083267D20Dbe6C2b0A83Bd0E601dC2299eD99015" } + ) { + timestamp + platformFee + accountSource + tradeVolume + } + } +`; + +const queryMantle = gql` + query stats($from: String!, $to: String!) { + dailyHistories( + where: { + timestamp_gte: $from + timestamp_lte: $to + accountSource: "0xECbd0788bB5a72f9dFDAc1FFeAAF9B7c2B26E456" + } + ) { + timestamp + platformFee + accountSource + tradeVolume + } + totalHistories( + where: { accountSource: "0xECbd0788bB5a72f9dFDAc1FFeAAF9B7c2B26E456" } + ) { + timestamp + platformFee + accountSource + tradeVolume + } + } +`; + interface IGraphResponse { dailyHistories: Array<{ tiemstamp: string; @@ -95,24 +149,122 @@ const fetchVolume = async (timestamp: number): Promise => { to: String(timestamp), }); - let dailyVolume = new BigNumber(0); + let dailyMakerVolume = new BigNumber(0); + let dailyTakerVolume = new BigNumber(0); response_0_8_0.dailyHistories.forEach((data) => { - dailyVolume = dailyVolume.plus(new BigNumber(data.tradeVolume)); + dailyMakerVolume = dailyMakerVolume.plus(new BigNumber(data.tradeVolume)); + dailyTakerVolume = dailyTakerVolume.plus(new BigNumber(data.tradeVolume)); }); response.dailyHistories.forEach((data) => { - dailyVolume = dailyVolume.plus(new BigNumber(data.tradeVolume)); + dailyMakerVolume = dailyMakerVolume.plus(new BigNumber(data.tradeVolume)); + dailyTakerVolume = dailyTakerVolume.plus(new BigNumber(data.tradeVolume)); }); - let totalVolume = new BigNumber(0); + let totalMakerVolume = new BigNumber(0); + let totalTakerVolume = new BigNumber(0); response_0_8_0.totalHistories.forEach((data) => { - totalVolume = totalVolume.plus(new BigNumber(data.tradeVolume)); + totalMakerVolume = totalMakerVolume.plus(new BigNumber(data.tradeVolume)); + totalTakerVolume = totalTakerVolume.plus(new BigNumber(data.tradeVolume)); }); response.totalHistories.forEach((data) => { - totalVolume = totalVolume.plus(new BigNumber(data.tradeVolume)); + totalMakerVolume = totalMakerVolume.plus(new BigNumber(data.tradeVolume)); + totalTakerVolume = totalTakerVolume.plus(new BigNumber(data.tradeVolume)); + }); + + const dailyVolume = dailyMakerVolume + .plus(dailyTakerVolume) + .dividedBy(new BigNumber(1e18)); + const totalVolume = totalMakerVolume + .plus(totalTakerVolume) + .dividedBy(new BigNumber(1e18)); + + const _dailyVolume = toString(dailyVolume); + const _totalVolume = toString(totalVolume); + + const dayTimestamp = getUniqStartOfTodayTimestamp(new Date(timestamp * 1000)); + + return { + timestamp: dayTimestamp, + dailyVolume: _dailyVolume ?? "0", + totalVolume: _totalVolume ?? "0", + }; +}; + +const fetchVolumeBlast = async ( + timestamp: number +): Promise => { + let dailyMakerVolume = new BigNumber(0); + let dailyTakerVolume = new BigNumber(0); + let totalMakerVolume = new BigNumber(0); + let totalTakerVolume = new BigNumber(0); + + const response_blast: IGraphResponse = await request( + endpoint_blast, + queryBlast, + { + from: String(timestamp - ONE_DAY_IN_SECONDS), + to: String(timestamp), + } + ); + response_blast.dailyHistories.forEach((data) => { + dailyMakerVolume = dailyMakerVolume.plus(new BigNumber(data.tradeVolume)); + dailyTakerVolume = dailyTakerVolume.plus(new BigNumber(data.tradeVolume)); + }); + response_blast.totalHistories.forEach((data) => { + totalMakerVolume = totalMakerVolume.plus(new BigNumber(data.tradeVolume)); + totalTakerVolume = totalTakerVolume.plus(new BigNumber(data.tradeVolume)); }); - dailyVolume = dailyVolume.dividedBy(new BigNumber(1e18)); - totalVolume = totalVolume.dividedBy(new BigNumber(1e18)); + const dailyVolume = dailyMakerVolume + .plus(dailyTakerVolume) + .dividedBy(new BigNumber(1e18)); + const totalVolume = totalMakerVolume + .plus(totalTakerVolume) + .dividedBy(new BigNumber(1e18)); + + const _dailyVolume = toString(dailyVolume); + const _totalVolume = toString(totalVolume); + + const dayTimestamp = getUniqStartOfTodayTimestamp(new Date(timestamp * 1000)); + + return { + timestamp: dayTimestamp, + dailyVolume: _dailyVolume ?? "0", + totalVolume: _totalVolume ?? "0", + }; +}; + +const fetchVolumeMantle = async ( + timestamp: number +): Promise => { + let dailyMakerVolume = new BigNumber(0); + let dailyTakerVolume = new BigNumber(0); + let totalMakerVolume = new BigNumber(0); + let totalTakerVolume = new BigNumber(0); + + const response_mantle: IGraphResponse = await request( + endpoint_mantle, + queryMantle, + { + from: String(timestamp - ONE_DAY_IN_SECONDS), + to: String(timestamp), + } + ); + response_mantle.dailyHistories.forEach((data) => { + dailyMakerVolume = dailyMakerVolume.plus(new BigNumber(data.tradeVolume)); + dailyTakerVolume = dailyTakerVolume.plus(new BigNumber(data.tradeVolume)); + }); + response_mantle.totalHistories.forEach((data) => { + totalMakerVolume = totalMakerVolume.plus(new BigNumber(data.tradeVolume)); + totalTakerVolume = totalTakerVolume.plus(new BigNumber(data.tradeVolume)); + }); + + const dailyVolume = dailyMakerVolume + .plus(dailyTakerVolume) + .dividedBy(new BigNumber(1e18)); + const totalVolume = totalMakerVolume + .plus(totalTakerVolume) + .dividedBy(new BigNumber(1e18)); const _dailyVolume = toString(dailyVolume); const _totalVolume = toString(totalVolume); @@ -132,6 +284,14 @@ const adapter: SimpleAdapter = { fetch: fetchVolume, start: 1698796800, }, + [CHAIN.BLAST]: { + fetch: fetchVolumeBlast, + start: 1698796800, + }, + [CHAIN.MANTLE]: { + fetch: fetchVolumeMantle, + start: 1698796800, + }, }, }; diff --git a/dexs/ipor/index.ts b/dexs/ipor/index.ts index 175a6f0aca..a76636a931 100644 --- a/dexs/ipor/index.ts +++ b/dexs/ipor/index.ts @@ -41,12 +41,17 @@ const fetch: any = async (timestamp: number, _: any, { chain, getLogs, createBal const logsStables = await getLogs({ targets: stables, topic: OpenSwapStablesTopic, eventAbi: openSwapStablesEventAbi }); const logsStETHs = await getLogs({ targets: stETHs, topic: OpenSwapStEthTopic, eventAbi: openSwapStETHEventAbi }); const logs = logsStables.concat(logsStETHs) - logs.forEach(log => { - const balance = Number(log.money?.notional || log.amounts?.notional) - dailyNotionalVolume.add(log.asset, balance) + let balance = Number(log.money?.notional || log.amounts?.notional) + if (log.asset.toLowerCase() === '0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48'.toLowerCase()) { + balance = balance / 1e12 + } + if (log.asset.toLowerCase() === '0xdAC17F958D2ee523a2206206994597C13D831ec7'.toLowerCase() + || log.asset.toLowerCase() === '0xaf88d065e77c8cC2239327C5EDb3A432268e5831'.toLowerCase()) { // 6 + balance = balance / 1e10 + } + dailyNotionalVolume.add(log.asset, balance) }) - return { timestamp, dailyVolume: dailyNotionalVolume }; }; diff --git a/dexs/iziswap/index.ts b/dexs/iziswap/index.ts index 2f82a1ed08..4031dbd121 100644 --- a/dexs/iziswap/index.ts +++ b/dexs/iziswap/index.ts @@ -34,6 +34,8 @@ const chains: TChains = { [CHAIN.SCROLL]: 534352, [CHAIN.BASE]: 8453, [CHAIN.MANTA]: 169, + [CHAIN.ZETA]: 7000, + [CHAIN.MODE]: 34443 }; const fetch = (chain: Chain) => { diff --git a/dexs/javsphere/index.ts b/dexs/javsphere/index.ts new file mode 100644 index 0000000000..d58f0d0189 --- /dev/null +++ b/dexs/javsphere/index.ts @@ -0,0 +1,56 @@ + +import fetchURL from "../../utils/fetchURL"; +import type { SimpleAdapter } from "../../adapters/types"; +import { CHAIN } from "../../helpers/chains"; + +type DexData = { + countTotal: number, + volumeTotal: number, + feeTotal: number, + tradesBuy: number, + volumeBuy: number, + volumeBuyFees: number, + countSell: number, + volumeSell: number, + volumeSellFees: number, + volume24: number, + fee24: number + +}; + +type StakingData = { + totalFees: number, + dailyFees: number, +}; + +const methodology = { + Fees: "User pays 0.1% fees on each trade. User pays 10% fee of rewards in dusdstaking.", + Volume: "User buys and sell RWA tokens.", +} + +const fetch = async (timestamp: number) => { + const stats: DexData = (await fetchURL(`https://aws-api.javlis.com/api/dtoken/stats`)).data; + const statsStaking: StakingData = (await fetchURL(`https://aws-api.javlis.com/api/dusdStaking/stats`)).data; + return { + totalVolume: `${stats.volumeTotal}`, + totalFees: `${stats.feeTotal + statsStaking.totalFees}`, + dailyFees: `${stats.fee24 + statsStaking.dailyFees}`, + dailyVolume: `${stats.volume24}`, + timestamp, + }; +}; + +const adapter: SimpleAdapter = { + adapter: { + [CHAIN.DEFICHAIN]: { + fetch, + start: 0, + runAtCurrTime: true, + meta: { + methodology + }, + }, + }, +}; + +export default adapter; diff --git a/dexs/jellyverse/index.ts b/dexs/jellyverse/index.ts new file mode 100644 index 0000000000..c085e81c88 --- /dev/null +++ b/dexs/jellyverse/index.ts @@ -0,0 +1,90 @@ +import * as sdk from "@defillama/sdk"; +import { Chain } from "@defillama/sdk/build/general"; +import request, { gql } from "graphql-request"; +import { BaseAdapter, BreakdownAdapter, ChainEndpoints, FetchResultV2 } from "../../adapters/types"; +import { CHAIN } from "../../helpers/chains"; +import { getStartTimestamp } from "../../helpers/getStartTimestamp"; +import { getTimestampAtStartOfDayUTC } from "../../utils/date"; + +const endpoints: ChainEndpoints = { + [CHAIN.SEI]: "https://graph.mainnet.jellyverse.org/subgraphs/name/jelly/verse" +}; + +interface IPool { + id: string; + swapVolume: string; + swapFees: string; +} + +interface IPoolSnapshot { + today: IPool[]; + yesterday: IPool[]; +} + +const v2Graphs = (chain: Chain) => { + return async ({ endTimestamp }): Promise => { + const startTimestamp = getTimestampAtStartOfDayUTC(endTimestamp) + const fromTimestamp = startTimestamp - 60 * 60 * 24 + const toTimestamp = startTimestamp + + const graphQuery = gql` + query volumes { + today: poolSnapshots(where: {timestamp: ${toTimestamp}}, orderBy: swapVolume, orderDirection: desc) { + id + swapVolume + swapFees + } + yesterday: poolSnapshots(where: {timestamp: ${fromTimestamp}}, orderBy: swapVolume, orderDirection: desc) { + id + swapVolume + swapFees + } + } + `; + + const graphRes: IPoolSnapshot = await request(endpoints[chain], graphQuery); + + const { dailyVolume, dailyFees } = graphRes.today.reduce((acc, p: IPool) => { + const yesterdayPool = graphRes.yesterday.find((e: IPool) => e.id.split('-')[0] === p.id.split('-')[0]); + const yesterdayVolume = Number(yesterdayPool?.swapVolume || '0'); + const yesterdayFees = Number(yesterdayPool?.swapFees || '0'); + + const volumeDiff = Number(p.swapVolume) - yesterdayVolume; + const feesDiff = Number(p.swapFees) - yesterdayFees; + + acc.dailyVolume += volumeDiff; + acc.dailyFees += feesDiff; + + return acc; + }, { dailyVolume: 0, dailyFees: 0 }); + + if (dailyVolume > 1_000_000_000) { + return {} + } + + return { + dailyVolume: dailyVolume.toString(), + dailyFees: dailyFees.toString(), + }; + }; +}; + +const adapter: BreakdownAdapter = { + version: 2, + breakdown: { + v2: { + [CHAIN.SEI]: { + fetch: v2Graphs(CHAIN.SEI), + start: getStartTimestamp({ + endpoints, + chain: CHAIN.SEI, + dailyDataField: `balancerSnapshots`, + dateField: 'timestamp', + volumeField: 'totalSwapVolume' + }), + } + } + } +}; + +export default adapter; diff --git a/dexs/jetswap/index.ts b/dexs/jetswap/index.ts index 9c2f228277..152edd129e 100644 --- a/dexs/jetswap/index.ts +++ b/dexs/jetswap/index.ts @@ -1,6 +1,7 @@ +import * as sdk from "@defillama/sdk"; import { CHAIN } from "../../helpers/chains"; import { univ2Adapter } from "../../helpers/getUniSubgraphVolume"; export default univ2Adapter({ - [CHAIN.BSC]: "https://api.thegraph.com/subgraphs/name/smartcookie0501/jetswap-subgraph" + [CHAIN.BSC]: sdk.graph.modifyEndpoint('5PoznNdqBAVSxsGv7MQMrVabVrYBbLobrFpWEnNcC6Xw') }, {}); diff --git a/dexs/jibswap/index.ts b/dexs/jibswap/index.ts index a37dad0986..0d2aa44cc0 100644 --- a/dexs/jibswap/index.ts +++ b/dexs/jibswap/index.ts @@ -1,7 +1,7 @@ import { CHAIN } from "../../helpers/chains"; -import { univ2Adapter } from "../../helpers/getUniSubgraphVolume"; +import { univ2Adapter2 } from "../../helpers/getUniSubgraphVolume"; -const adapters = univ2Adapter({ +const adapters = univ2Adapter2({ [CHAIN.JBC]: "https://graph.jibswap.com/subgraphs/name/jibswap", }, {}); diff --git a/dexs/joe-v2.1/index.ts b/dexs/joe-v2.1/index.ts index 5859561aa1..ee3991ded9 100644 --- a/dexs/joe-v2.1/index.ts +++ b/dexs/joe-v2.1/index.ts @@ -1,4 +1,4 @@ -import { FetchOptions, SimpleAdapter } from "../../adapters/types"; +import { FetchOptions, FetchResultV2, FetchV2, SimpleAdapter } from "../../adapters/types"; import { CHAIN } from "../../helpers/chains"; const event_swap = 'event Swap(address indexed sender,address indexed to,uint24 id,bytes32 amountsIn,bytes32 amountsOut,uint24 volatilityAccumulator,bytes32 totalFees,bytes32 protocolFees)'; @@ -47,38 +47,43 @@ const pools: TPool = { ] } -const fetch: any = async (timestamp: number, _, { api, chain, getLogs, createBalances, }: FetchOptions) => { - const dailyVolume = createBalances(); - const lpTokens = pools[chain] - const [tokens0, tokens1] = await Promise.all( - ['address:getTokenX', 'address:getTokenY'].map((abi: string) => - api.multiCall({ abi, calls: lpTokens, }) ) - ); +const fetch: FetchV2 = async (options: FetchOptions): Promise => { + const dailyVolume = options.createBalances(); + const lpTokens = pools[options.chain] + try { + const tokens0 = await options.api.multiCall({ abi: 'address:getTokenX', calls: lpTokens! }) + const tokens1 = await options.api.multiCall({ abi: 'address:getTokenY', calls: lpTokens! }) - const logs: any[][] = (await getLogs({ - targets: lpTokens, - eventAbi: event_swap, - flatten: false, - })) + const logs: any[][] = (await Promise.all(lpTokens.map((lp: string) => options.getLogs({ + target: lp, + eventAbi: event_swap, + flatten: false + })))) - logs.map((log: any, index: number) => { - const token0 = tokens0[index]; - const token1 = tokens1[index]; - log.forEach((i: any) => { - const amountInX = Number('0x' + '0'.repeat(32) + i.amountsIn.replace('0x', '').slice(0, 32)) - const amountInY = Number('0x' + '0'.repeat(32) + i.amountsIn.replace('0x', '').slice(32, 64)) - dailyVolume.add(token0, amountInY); - dailyVolume.add(token1, amountInX); - }) - }); - return { dailyVolume, timestamp, }; + logs.map((log: any, index: number) => { + const token0 = tokens0[index]; + const token1 = tokens1[index]; + log.forEach((i: any) => { + const amountInX = Number('0x' + '0'.repeat(32) + i.amountsIn.replace('0x', '').slice(0, 32)) + const amountInY = Number('0x' + '0'.repeat(32) + i.amountsIn.replace('0x', '').slice(32, 64)) + dailyVolume.add(token0, amountInY); + dailyVolume.add(token1, amountInX); + }) + }); + console.info(`joe-v2.1: ${options.chain} done`) + return { dailyVolume }; + } catch (err: any) { + console.error(`joe-v2.1: ${options.chain} error ${err}`) + return { dailyVolume }; + } } const adapter: SimpleAdapter = { + version: 2, adapter: { + [CHAIN.AVAX]: { fetch, start: 1682467200, }, [CHAIN.ARBITRUM]: { fetch, start: 1682121600, }, [CHAIN.BSC]: { fetch, start: 1681084800, }, - [CHAIN.AVAX]: { fetch, start: 1682467200, }, } }; diff --git a/dexs/jojo/index.ts b/dexs/jojo/index.ts index 76a1d7dd21..11213a1cdd 100644 --- a/dexs/jojo/index.ts +++ b/dexs/jojo/index.ts @@ -1,53 +1,55 @@ import fetchURL from "../../utils/fetchURL" -import { SimpleAdapter, Fetch } from "../../adapters/types"; +import { SimpleAdapter, Fetch, FetchOptions } from "../../adapters/types"; import { CHAIN } from "../../helpers/chains"; import { getUniqStartOfTodayTimestamp } from "../../helpers/getUniSubgraphVolume"; - -const historicalVolumeEndpointZk = (symbol: string, chain: string) => `https://api.`+ chain +`-mainnet.jojo.exchange/v1/klines?marketId=${symbol}&interval=1D&startTime=1687017600000&limit=500` +const historicalVolumeEndpointZk = (symbol: string, chain: string) => `https://api.` + chain + `-mainnet.jojo.exchange/v1/platform/tradeVolume?marketId=${symbol}` const coins = { 'ethusdc': 'coingecko:ethereum', 'btcusdc': 'coingecko:bitcoin', - 'arbusdc': 'coingecko:arbitrum', 'solusdc': 'coingecko:solana', - 'linkusdc': 'coingecko:link', + 'wifusdc': 'coingecko:wif', + 'enausdc': 'coingecko:ena', + 'ckbusdc': 'coingecko:ckb', + 'bomeusdc': 'coingecko:bome', + 'wusdc': 'coingecko:w', + 'ethfiusdc': 'coingecko:ethfi', + 'ondousdc': 'coingecko:ondo', + 'dogeusdc': 'coingecko:doge', 'memeusdc': 'coingecko:meme', 'ordiusdc': 'coingecko:ordi', 'wldusdc': 'coingecko:wld', 'agixusdc': 'coingecko:agix', - 'arusdc': 'coingecko:ar', 'tiausdc': 'coingecko:tia', - 'strkusdc': 'coingecko:strk', - 'avaxusdc': 'coingecko:avax', - 'xrpusdc': 'coingecko:xrp', - 'trxusdc': 'coingecko:trx', 'rndrusdc': 'coingecko:rndr', - 'adausdc': 'coingecko:ada', 'altusdc': 'coingecko:alt', - 'dogeusdc': 'coingecko:doge', - 'xaiusdc': 'coingecko:xai' + 'xaiusdc': 'coingecko:xai', + 'linkusdc': 'coingecko:link' + } interface IVolumeall { id: string; volume: string; timestamp: number; - quoteVolume: string; } -const getVolume = async (timestamp: number, chain: string) => { - const dayTimestamp = getUniqStartOfTodayTimestamp(new Date(timestamp * 1000)) - const historical = (await Promise.all(Object.keys(coins).map((coins: string) => fetchURL(historicalVolumeEndpointZk(coins, chain))))) - .map((a: any, index: number) => a.map((e: any) => { return { timestamp: e.time / 1000, volume: e.volume, id: Object.values(coins)[index], quoteVolume: e.quote_volume } })).flat() - const historicalUSD = historical.map((e: IVolumeall) => { +const getVolume = async (options: FetchOptions) => { + const dayTimestamp = getUniqStartOfTodayTimestamp(new Date(options.endTimestamp * 1000)) + + const historical = (await Promise.all(Object.keys(coins).map((coins: string) => fetchURL(historicalVolumeEndpointZk(coins, options.chain))))); + + const historicalVolume = historical.map((item => item?.dailyVolume || [])) + const historicalUSD = historicalVolume.map((a: any, index: number) => a.map((e: any) => { return { timestamp: e.t / 1000, volume: e.v, id: Object.values(coins)[index] } })).flat() + const historicalUSD2 = historicalUSD.map((e: IVolumeall) => { return { ...e, - volumeUSD: Number(e.quoteVolume) + volumeUSD: Number(e.volume) } }); - const dailyVolume = historicalUSD.filter((e: IVolumeall) => e.timestamp === dayTimestamp) - .reduce((a: number, { volumeUSD }) => a + volumeUSD, 0); - const totalVolume = historicalUSD.filter((e: IVolumeall) => e.timestamp <= dayTimestamp) + const dailyVolume = historicalUSD2.filter((e: IVolumeall) => e.timestamp === dayTimestamp) .reduce((a: number, { volumeUSD }) => a + volumeUSD, 0); + + const totalVolume = historical.map(item => item.totalVolume).reduce((accumulator, currentValue) => accumulator + parseFloat(currentValue), 0); return { totalVolume: `${totalVolume}`, dailyVolume: dailyVolume ? `${dailyVolume}` : undefined, @@ -55,15 +57,12 @@ const getVolume = async (timestamp: number, chain: string) => { }; }; -const getFetch = (chain: string): Fetch => async (timestamp: number) => { - return getVolume(timestamp, chain); -} - const adapter: SimpleAdapter = { + version: 2, adapter: { - [CHAIN.ARBITRUM]: { - fetch: getFetch("arbitrum"), - start: 1687017600, + [CHAIN.BASE]: { + fetch: getVolume, + start: 1711965100, }, }, }; diff --git a/dexs/jswap/index.ts b/dexs/jswap/index.ts index 303d9a80a7..85a8846142 100644 --- a/dexs/jswap/index.ts +++ b/dexs/jswap/index.ts @@ -1,7 +1,7 @@ import request, { gql } from "graphql-request"; import { DISABLED_ADAPTER_KEY, SimpleAdapter } from "../../adapters/types"; import { CHAIN } from "../../helpers/chains"; -import { DEFAULT_DAILY_VOLUME_FIELD, DEFAULT_TOTAL_VOLUME_FIELD, getGraphDimensions } from "../../helpers/getUniSubgraph"; +import { DEFAULT_TOTAL_VOLUME_FIELD, getGraphDimensions2 } from "../../helpers/getUniSubgraph"; import disabledAdapter from "../../helpers/disabledAdapter"; const blocksGraph = @@ -40,23 +40,17 @@ const getCustomBlock = async (timestamp: number) => { return block; }; -const DAILY_VOLUME_FACTORY = "jswapDayData"; - -const graphs = getGraphDimensions({ +const graphs = getGraphDimensions2({ graphUrls: endpoints, totalVolume: { factory: "jswapFactories", field: DEFAULT_TOTAL_VOLUME_FIELD, }, - dailyVolume: { - factory: DAILY_VOLUME_FACTORY, - field: DEFAULT_DAILY_VOLUME_FIELD, - dateField: 'date' - }, getCustomBlock, }); const adapter: SimpleAdapter = { + version: 2, adapter: { [DISABLED_ADAPTER_KEY]: disabledAdapter, [CHAIN.OKEXCHAIN]: { diff --git a/dexs/jupiter-perpetual/index.ts b/dexs/jupiter-perpetual/index.ts index 7c49506af9..ee3cf5cd74 100644 --- a/dexs/jupiter-perpetual/index.ts +++ b/dexs/jupiter-perpetual/index.ts @@ -1,19 +1,40 @@ import { FetchResult } from "../../adapters/types"; import { CHAIN } from "../../helpers/chains"; -import { getUniqStartOfTodayTimestamp } from "../../helpers/getUniSubgraphVolume"; -import { queryDune } from "../../helpers/dune"; +import { httpGet } from "../../utils/fetchURL"; + +const list_of_mints: string[] = [ + "So11111111111111111111111111111111111111112", + "3NZ9JMVBmGAqocybic2c7LQCJScmgsAZ6vQqTDzcqmJh", + "7vfCXTUXx5WJV5JADk17DUJ4ksgau7utNKj4b963voxs", +] const fetch = async (timestamp: number): Promise => { - const unixTimestamp = getUniqStartOfTodayTimestamp(new Date(timestamp * 1000)); - // 3385640 old query id - const data = await queryDune("3391484", { endTime: unixTimestamp + 86400 }); + const header_user = { + "accept": "*/*", + "accept-language": "en-US,en;q=0.9", + "content-type": "application/json", + "sec-ch-ua": "\" Not A;Brand\";v=\"99\", \"Chromium\";v=\"90\", \"Google Chrome\";v=\"90\"", + "sec-ch-ua-mobile": "?0", + "sec-fetch-dest": "empty", + "sec-fetch-mode": "cors", + "sec-fetch-site": "cross-site", + "sec-gpc": "1", + "referrer": "https://www.jup.ag/", + "referrerPolicy": "strict-origin-when-cross-origin", + "mode": "cors", + "user-agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/90.0.4430.212 Safari/537.36", + } + const url = (token: string) => `https://perp-api.jup.ag/trpc/tradeVolume?batch=1&input={"0":{"json":{"mint":"${token}"}}}` + const fetches = (await Promise.all(list_of_mints.map(token => httpGet(url(token), { headers: header_user })))).flat(); + const dailyVolume = fetches.reduce((acc, { result }) => acc + result.data.json.volume, 0); return { - dailyVolume: data[0].volume, - timestamp: unixTimestamp, + dailyVolume: dailyVolume, + timestamp: timestamp, }; }; const adapter = { + version: 2, breakdown: { derivatives: { [CHAIN.SOLANA]: { @@ -22,8 +43,6 @@ const adapter = { start: 1705968000, }, }, - }, - isExpensiveAdapter: true, + } }; - export default adapter; diff --git a/dexs/katana/index.ts b/dexs/katana/index.ts index 932313b640..53c017f571 100644 --- a/dexs/katana/index.ts +++ b/dexs/katana/index.ts @@ -1,75 +1,17 @@ -import { SimpleAdapter } from "../../adapters/types"; - -const { request, gql } = require("graphql-request"); const { RONIN } = require("../../helpers/chains"); -const { getStartTimestamp } = require("../../helpers/getStartTimestamp"); -const { - getChainVolume, - DEFAULT_TOTAL_VOLUME_FIELD, - DEFAULT_DAILY_VOLUME_FIELD, -} = require("../../helpers/getUniSubgraphVolume"); - -const endpoints = { - [RONIN]: - "https://thegraph.roninchain.com/subgraphs/name/axieinfinity/katana-subgraph-blue", -}; - -const blocksGraph = - "https://thegraph.roninchain.com/subgraphs/name/axieinfinity/ronin-blocks"; -const ONE_DAY_IN_SECONDS = 60 * 60 * 24 -const blockQuery = gql` - query blocks($timestampFrom: Int!, $timestampTo: Int!) { - blocks( - first: 1 - orderBy: timestamp - orderDirection: asc - where: { timestamp_gt: $timestampFrom, timestamp_lt: $timestampTo } - ) { - id - number - timestamp - __typename - } - } -`; - -const getCustomBlock = async (timestamp: number) => { - const block = Number( - ( - await request(blocksGraph, blockQuery, { - timestampFrom: timestamp - ONE_DAY_IN_SECONDS, - timestampTo: timestamp + ONE_DAY_IN_SECONDS, - }) - ).blocks[0].number - ); - - return block; -}; - -const DAILY_VOLUME_FACTORY = "katanaDayData"; - -const graphs = getChainVolume({ - graphUrls: { - [RONIN]: endpoints[RONIN], - }, - totalVolume: { - factory: "katanaFactories", - field: DEFAULT_TOTAL_VOLUME_FIELD, - }, - dailyVolume: { - factory: DAILY_VOLUME_FACTORY, - field: DEFAULT_DAILY_VOLUME_FIELD, - }, - getCustomBlock, +import { univ2Adapter } from "../../helpers/getUniSubgraphVolume"; + +/* +use axiedao.org proxy, because public endpoint +https://thegraph-v2.roninchain.com/subgraphs/name/axieinfinity/katana-subgraph-blue +blocks requests from the DefiLlama server +*/ +const adpters = univ2Adapter({ + [RONIN]: "https://defillama.axiedao.org/graphql/katana" +}, { + factoriesName: "katanaFactories", + dayData: "katanaDayData", }); -const adapter: SimpleAdapter = { - adapter: { - [RONIN]: { - fetch: graphs(RONIN), - start: 1635724800, - }, - }, -}; - -export default adapter; +adpters.adapter[RONIN].start = 1635724800; +export default adpters; diff --git a/dexs/keller-cl/index.ts b/dexs/keller-cl/index.ts new file mode 100644 index 0000000000..b6caf5b7c6 --- /dev/null +++ b/dexs/keller-cl/index.ts @@ -0,0 +1,7 @@ +import { uniV3Exports } from "../../helpers/uniswap"; + +export default uniV3Exports({ + scroll: { + factory: '0x952aC46B2586737df679e836d9B980E43E12B2d8', + } +}) \ No newline at end of file diff --git a/dexs/keller/index.ts b/dexs/keller/index.ts new file mode 100644 index 0000000000..496cb92dd3 --- /dev/null +++ b/dexs/keller/index.ts @@ -0,0 +1,7 @@ +import { uniV2Exports } from "../../helpers/uniswap"; + +export default uniV2Exports({ + scroll: { + factory: '0xbc83f7dF70aE8A3e4192e1916d9D0F5C2ee86367', + } +}) diff --git a/dexs/kiloex/index.ts b/dexs/kiloex/index.ts index 572f9200c8..077ad5de40 100644 --- a/dexs/kiloex/index.ts +++ b/dexs/kiloex/index.ts @@ -12,7 +12,9 @@ type ChainMap = { const historicalVolumeEndpoints: ChainMap = { [CHAIN.BSC]: "https://api.kiloex.io/common/queryTradeSummary", [CHAIN.OP_BNB]: "https://opapi.kiloex.io/common/queryTradeSummary", - [CHAIN.MANTA]: "https://mantaapi.kiloex.io/common/queryTradeSummary" + [CHAIN.MANTA]: "https://mantaapi.kiloex.io/common/queryTradeSummary", + [CHAIN.TAIKO]: "https://taikoapi.kiloex.io/common/queryTradeSummary", + [CHAIN.BSQUARED]: "https://b2api.kiloex.io/common/queryTradeSummary", }; interface IVolume { @@ -52,6 +54,12 @@ const adapter: SimpleAdapter = { [CHAIN.MANTA]: { fetch: fetch(CHAIN.MANTA), start: 1698796800 }, + [CHAIN.TAIKO]: { + fetch: fetch(CHAIN.TAIKO), start: async () => 1717027200 + }, + [CHAIN.BSQUARED]: { + fetch: fetch(CHAIN.BSQUARED), start: async () => 1722297600 + }, }, }; diff --git a/dexs/kinetix-derivatives-v2/index.ts b/dexs/kinetix-derivatives-v2/index.ts index 58b9b2dda4..e863b2c09b 100644 --- a/dexs/kinetix-derivatives-v2/index.ts +++ b/dexs/kinetix-derivatives-v2/index.ts @@ -5,7 +5,7 @@ import { Chain } from "@defillama/sdk/build/general"; import request, { gql } from "graphql-request"; const kinetixPerpsV2Subgraph = - "https://kava-graph-node.metavault.trade/subgraphs/name/kinetixfi/perpv2"; + "https://kava-graph-node.metavault.trade/subgraphs/name/kinetixfi/kava-trade"; interface IReferralRecord { volume: string; // Assuming volume is a string that represents a number diff --git a/dexs/kinetix-v3/index.ts b/dexs/kinetix-v3/index.ts index 50f0ad489b..7e104fd8b9 100644 --- a/dexs/kinetix-v3/index.ts +++ b/dexs/kinetix-v3/index.ts @@ -1,23 +1,21 @@ import { Chain } from "@defillama/sdk/build/general"; import { CHAIN } from "../../helpers/chains"; -import { getGraphDimensions } from "../../helpers/getUniSubgraph"; +import { getGraphDimensions2 } from "../../helpers/getUniSubgraph"; import { BreakdownAdapter } from "../../adapters/types"; const endpointsV3 = { [CHAIN.KAVA]: "https://kava-graph-node.metavault.trade/subgraphs/name/kinetixfi/v3-subgraph", + [CHAIN.BASE]: + "https://api.studio.thegraph.com/query/55804/kinetixfi-base-v3/version/latest", }; -const v3Graphs = getGraphDimensions({ +const v3Graphs = getGraphDimensions2({ graphUrls: endpointsV3, totalVolume: { factory: "factories", field: "totalVolumeUSD", }, - dailyVolume: { - factory: "uniswapDayData", - field: "volumeUSD", - }, feesPercent: { type: "fees", ProtocolRevenue: 0, @@ -30,6 +28,7 @@ const v3Graphs = getGraphDimensions({ const startTimeV3: { [key: string]: number } = { [CHAIN.KAVA]: 1693267200, + [CHAIN.BASE]: 1715126400, }; const v3 = Object.keys(endpointsV3).reduce( @@ -55,6 +54,7 @@ const v3 = Object.keys(endpointsV3).reduce( ); const adapter: BreakdownAdapter = { + version: 2, breakdown: { v3: v3, }, diff --git a/dexs/klex-finance/index.ts b/dexs/klex-finance/index.ts index f33904fc51..548f8885fa 100644 --- a/dexs/klex-finance/index.ts +++ b/dexs/klex-finance/index.ts @@ -1,5 +1,5 @@ import { ChainEndpoints, DISABLED_ADAPTER_KEY, SimpleAdapter } from "../../adapters/types"; -import { getChainVolume } from "../../helpers/getUniSubgraphVolume"; +import { getChainVolume2 } from "../../helpers/getUniSubgraphVolume"; import customBackfill from "../../helpers/customBackfill"; import { CHAIN } from "../../helpers/chains"; import { Chain } from "@defillama/sdk/build/general"; @@ -15,16 +15,16 @@ const graphParams = { factory: "balancers", field: "totalSwapVolume", }, - hasDailyVolume: false, } -const graphs = getChainVolume({ +const graphs = getChainVolume2({ graphUrls: endpoints, ...graphParams }); const adapter: SimpleAdapter = { + version: 2, adapter: Object.keys(endpoints).reduce((acc, chain: any) => { return { ...acc, diff --git a/dexs/knightswap-finance/index.ts b/dexs/knightswap-finance/index.ts index 1473ad90b7..3fdab08278 100644 --- a/dexs/knightswap-finance/index.ts +++ b/dexs/knightswap-finance/index.ts @@ -1,28 +1,27 @@ +import * as sdk from "@defillama/sdk"; import { SimpleAdapter } from "../../adapters/types"; import { CHAIN } from "../../helpers/chains"; -const { - getChainVolume -} = require("../../helpers/getUniSubgraphVolume"); +import { getChainVolume2 } from "../../helpers/getUniSubgraphVolume"; const endpoints = { - [CHAIN.BSC]: "https://api.thegraph.com/subgraphs/name/shahzeb8285/knight-new-graph", - [CHAIN.FANTOM]: "https://api.thegraph.com/subgraphs/name/shahzeb8285/thedarkknightanalytics", + [CHAIN.BSC]: sdk.graph.modifyEndpoint( + "GknVfnDT8h7aFsdS6Y6CeWTx3bHFnUnGxNgAUSSCQPz1", + ), + [CHAIN.FANTOM]: sdk.graph.modifyEndpoint( + "GhBfNocNJJCjS4norsp6Cpiw2vJompiURM9frjgsnVdW", + ), }; -const v2Graph = getChainVolume({ +const v2Graph = getChainVolume2({ graphUrls: endpoints, totalVolume: { factory: "pancakeFactories", field: "totalVolumeUSD", }, - dailyVolume: { - factory: "pancakeDayData", - field: "dailyVolumeUSD", - }, }); - const adapter: SimpleAdapter = { + version: 2, adapter: { [CHAIN.BSC]: { fetch: v2Graph(CHAIN.BSC), diff --git a/dexs/koi-finance-cl/index.ts b/dexs/koi-finance-cl/index.ts new file mode 100644 index 0000000000..3cf7e6bb7a --- /dev/null +++ b/dexs/koi-finance-cl/index.ts @@ -0,0 +1,17 @@ +import { CHAIN } from "../../helpers/chains"; +import { univ2Adapter2 } from "../../helpers/getUniSubgraphVolume"; + +const endpoints = { + [CHAIN.ERA]: "https://api.studio.thegraph.com/query/12332/koi-finance-v3/version/latest", + }; + +const adapter = univ2Adapter2(endpoints, { + factoriesName: "factories", + dayData: "koiFinanceDayData", + dailyVolume: "volumeUSD", + totalVolume: "totalVolumeUSD", +}); + +adapter.adapter.era.start = 1679529600 + +export default adapter diff --git a/dexs/koyo/index.ts b/dexs/koyo/index.ts index ff4812bb77..fe2e6773e4 100644 --- a/dexs/koyo/index.ts +++ b/dexs/koyo/index.ts @@ -1,23 +1,24 @@ +import * as sdk from "@defillama/sdk"; import { SimpleAdapter } from "../../adapters/types"; import { CHAIN } from "../../helpers/chains"; import customBackfill from "../../helpers/customBackfill"; -import { getChainVolume } from "../../helpers/getUniSubgraphVolume"; +import { getChainVolume2 } from "../../helpers/getUniSubgraphVolume"; const endpoints = { [CHAIN.BOBA]: - "https://api.thegraph.com/subgraphs/name/koyo-finance/exchange-subgraph-boba", + sdk.graph.modifyEndpoint('3CdxAdbTrVDhM6WQCr5TN4y4zxAodMAmcZwFFWRnEKz3'), }; -const graphs = getChainVolume({ +const graphs = getChainVolume2({ graphUrls: endpoints, totalVolume: { factory: "koyos", field: "totalSwapVolume", }, - hasDailyVolume: false }); const adapter: SimpleAdapter = { + version: 2, adapter: { [CHAIN.BOBA]: { fetch: graphs(CHAIN.BOBA), diff --git a/dexs/kriya-clmm/index.ts b/dexs/kriya-clmm/index.ts new file mode 100644 index 0000000000..f8633517e9 --- /dev/null +++ b/dexs/kriya-clmm/index.ts @@ -0,0 +1,46 @@ +import fetchURL from "../../utils/fetchURL" +import { Chain } from "@defillama/sdk/build/general"; +import { FetchResultV2, SimpleAdapter } from "../../adapters/types"; +import { CHAIN } from "../../helpers/chains"; +import { getUniqStartOfTodayTimestamp } from "../../helpers/getUniSubgraphVolume"; + +type IUrl = { + [s: string]: string; +} + +const url: IUrl = { + [CHAIN.SUI]: `https://tkmw8dmcp8.execute-api.ap-southeast-1.amazonaws.com/prod/volume/clmm/` +} + +interface IVolume { + totalVolume: number, + dailyVolume: number, + weeklyVolume: number, + monthlyVolume: number, +} + +const fetch = (chain: Chain) => { + return async ({ endTimestamp }): Promise => { + const dayTimestamp = getUniqStartOfTodayTimestamp(new Date(endTimestamp * 1000)); + // fetch for the passed timestamp. + const volumeUrl = url[chain] + String(endTimestamp); + const volume: IVolume = (await fetchURL(volumeUrl)); + return { + totalVolume: `${volume?.totalVolume || undefined}`, + dailyVolume: `${volume?.dailyVolume || undefined}`, + timestamp: dayTimestamp, + }; + }; +} + +const adapter: SimpleAdapter = { + version: 2, + adapter: { + [CHAIN.SUI]: { + fetch: fetch(CHAIN.SUI), + start: 1683604174, + } + }, +}; + +export default adapter; \ No newline at end of file diff --git a/dexs/ktx/index.ts b/dexs/ktx/index.ts index 0f38b3aff2..56c2a9b140 100644 --- a/dexs/ktx/index.ts +++ b/dexs/ktx/index.ts @@ -4,9 +4,9 @@ import { CHAIN } from "../../helpers/chains"; import { getUniqStartOfTodayTimestamp } from "../../helpers/getUniSubgraphVolume"; const endpoints: { [key: string]: string } = { - [CHAIN.BSC]: "https://subgraph.ktx.finance/subgraphs/name/ktx", - [CHAIN.MANTLE]: "https://mantlesubgraph.ktx.finance/subgraphs/name/ktx", - [CHAIN.ARBITRUM]: "https://arbisubgraph.ktx.systems/subgraphs/name/ktx", + [CHAIN.BSC]: "https://subgraph.satsuma-prod.com/dff088b6cd75/kesters-team/bsc_stats/api", + [CHAIN.MANTLE]: "https://subgraph.satsuma-prod.com/dff088b6cd75/kesters-team/mantle_stats/api", + [CHAIN.ARBITRUM]: "https://subgraph.satsuma-prod.com/dff088b6cd75/kesters-team/ktx_stats/api", }; const historicalDataSwap = gql` diff --git a/dexs/kwenta/index.ts b/dexs/kwenta/index.ts deleted file mode 100644 index 2dc3cafe85..0000000000 --- a/dexs/kwenta/index.ts +++ /dev/null @@ -1,37 +0,0 @@ -import { Chain } from "@defillama/sdk/build/general" -import { CHAIN } from "../../helpers/chains"; -import { SimpleAdapter } from "../../adapters/types"; -import fetchURL from "../../utils/fetchURL"; -import { getTimestampAtStartOfDayUTC } from "../../utils/date"; -import { FetchResultVolume } from "../../adapters/types"; - -interface IData { - timestamp: number; - volume: number; -} -const url = 'https://storage.kwenta.io/25710180-23d8-43f4-b0c9-5b7f55f63165-bucket/data/stats/daily_stats.json'; -const fetchData = (_: Chain) => { - return async (timestamp: number): Promise => { - const todaysTimestamp = getTimestampAtStartOfDayUTC(timestamp) - const value: IData[] = (await fetchURL(url)); - const dailyVolume = value.find((d) => d.timestamp === todaysTimestamp)?.volume; - const totalVolume = value.filter((e: IData) => e.timestamp <= todaysTimestamp) - .reduce((acc: number, e: IData) => acc + e.volume, 0) - return { - dailyVolume: dailyVolume ? `${dailyVolume}` : undefined, - totalVolume: totalVolume ? `${totalVolume}` : undefined, - timestamp: todaysTimestamp - } - } -} - -const adapter: SimpleAdapter = { - adapter: { - [CHAIN.OPTIMISM]: { - fetch: fetchData(CHAIN.OPTIMISM), - start: 1682121600, - }, - } -}; - -export default adapter; diff --git a/dexs/kyberswap/index.ts b/dexs/kyberswap/index.ts index 1de592c7ee..2f8292b23d 100644 --- a/dexs/kyberswap/index.ts +++ b/dexs/kyberswap/index.ts @@ -1,6 +1,7 @@ +import * as sdk from "@defillama/sdk"; import ADDRESSES from '../../helpers/coreAssets.json' import request from "graphql-request"; -import { BaseAdapter, BreakdownAdapter, FetchResultVolume } from "../../adapters/types"; +import { BaseAdapter, BreakdownAdapter, FetchOptions, FetchResultVolume } from "../../adapters/types"; import { CHAIN } from "../../helpers/chains"; import { getStartTimestamp } from "../../helpers/getStartTimestamp"; import { @@ -34,7 +35,7 @@ const kyberswapElasticV2 = univ2Adapter({ dailyVolume: "volumeUSD", totalVolume: "totalVolumeUSD", }); - +kyberswapElasticV2.version = 2; kyberswapElasticV2.adapter.ethereum.start = 1654905600; kyberswapElasticV2.adapter.bsc.start = 1654732800; kyberswapElasticV2.adapter.polygon.start = 1654732800; @@ -54,9 +55,9 @@ const elasticEndpoints = elasticChains.reduce((acc, chain)=>({ ...acc, }), { //cronos: "https://cronos-graph.kyberengineering.io/subgraphs/name/kybernetwork/kyberswap-elastic-cronos", // missing -> almost no volume and stale - ethereum: "https://api.thegraph.com/subgraphs/name/kybernetwork/kyberswap-elastic-mainnet", + ethereum: sdk.graph.modifyEndpoint('4U9PxDR4asVvfXyoVy18fhuj6NHnQhLzZkjZ5Bmuc5xk'), arbitrum: "https://arbitrum-graph.kyberengineering.io/subgraphs/name/kybernetwork/kyberswap-elastic-arbitrum", - polygon: "https://api.thegraph.com/subgraphs/name/kybernetwork/kyberswap-elastic-matic", + polygon: sdk.graph.modifyEndpoint('8g4tJKCJ7eMAHjzZNeRWz9BkYG5U7vDNjdanSXfDXGXT'), [CHAIN.LINEA]: "https://linea-graph.kyberengineering.io/subgraphs/name/kybernetwork/kyberswap-elastic-linea", [CHAIN.BASE]: "https://base-graph.kyberengineering.io/subgraphs/name/kybernetwork/kyberswap-elastic-base", [CHAIN.SCROLL]: "https://scroll-graph.kyberengineering.io/subgraphs/name/kybernetwork/kyberswap-elastic-scroll" @@ -95,7 +96,7 @@ interface IPoolDayData { const optimismElastic = async (timestamp: number) => { const todayTimestamp = getUniqStartOfTodayTimestamp(new Date(timestamp * 1000)); - const url = "https://api.thegraph.com/subgraphs/name/kybernetwork/kyberswap-elastic-optimism"; + const url = sdk.graph.modifyEndpoint('3Kpd8i7U94pTz3Mgdb8hyvT5o26fpwT7SUHAbTa6JzfZ'); const blacklisted = [ '0xa00e3a3511aac35ca78530c85007afcd31753819', ADDRESSES.optimism.sUSD, @@ -141,7 +142,7 @@ const optimismElastic = async (timestamp: number) => { const ethereumElasicVolume = async (timestamp: number) => { const todayTimestamp = getUniqStartOfTodayTimestamp(new Date(timestamp * 1000)); - const url = "https://api.thegraph.com/subgraphs/name/kybernetwork/kyberswap-elastic-mainnet"; + const url = sdk.graph.modifyEndpoint('4U9PxDR4asVvfXyoVy18fhuj6NHnQhLzZkjZ5Bmuc5xk'); const blacklisted = [ '0xdefa4e8a7bcba345f687a2f1456f5edd9ce97202', @@ -210,33 +211,28 @@ const customeElasicVolumeFunctions: {[s: Chain]: any} = { function buildFromEndpoints(endpoints: typeof classicEndpoints, graphs: typeof classicGraphs, volumeField:string, dailyDataField:string, isElastic: boolean){ return Object.keys(endpoints).reduce((acc, chain) => { acc[chain] = { - fetch: async (timestamp: number) => { - const a = (customeElasicVolumeFunctions[chain] !== undefined) && isElastic ? await customeElasicVolumeFunctions[chain](timestamp) : (await graphs(chain as any)(timestamp, {})) - const elasticV2 = (kyberswapElasticV2.adapter[chain as Chain]?.fetch != undefined && isElastic) ? (await kyberswapElasticV2.adapter[chain as Chain]?.fetch(timestamp, {})) : {} as FetchResultVolume; - const dailyVolume = Number(a.dailyVolume) + Number(elasticV2?.dailyVolume || 0) - const totalVolume = Number(a.totalVolume) + Number(elasticV2?.totalVolume || 0) + fetch: async (options: FetchOptions) => { + const a = (customeElasicVolumeFunctions[chain] !== undefined) && isElastic ? await customeElasicVolumeFunctions[chain](options.endTimestamp) : (await graphs(chain as any)(options)) + const elasticV2 = (kyberswapElasticV2.adapter[chain as Chain]?.fetch != undefined && isElastic) ? (await kyberswapElasticV2.adapter[chain as Chain]?.fetch(options as any, {}, options)) : {} as FetchResultVolume; + const dailyVolume = Number(a?.dailyVolume || 0) + Number(elasticV2?.dailyVolume || 0) + const totalVolume = Number(a?.totalVolume || 0) + Number(elasticV2?.totalVolume || 0) return { dailyVolume: `${dailyVolume}`, totalVolume: chain === CHAIN.ARBITRUM ? undefined : `${totalVolume}`, - timestamp }; }, - start: getStartTimestamp({ - endpoints: endpoints, - chain: chain, - volumeField, - dailyDataField - }) + start: 0, } return acc }, {} as BaseAdapter) } const adapter: BreakdownAdapter = { + version: 2, breakdown: { classic: buildFromEndpoints(classicEndpoints, classicGraphs, DEFAULT_DAILY_VOLUME_FIELD, "dmmDayDatas", false), elastic: buildFromEndpoints(elasticEndpoints, elasticGraphs, "volumeUSD", "kyberSwapDayDatas", true) } } -export default adapter; +export default adapter; \ No newline at end of file diff --git a/dexs/kyotoswap/index.ts b/dexs/kyotoswap/index.ts index b9d753b521..7651f9c0d6 100644 --- a/dexs/kyotoswap/index.ts +++ b/dexs/kyotoswap/index.ts @@ -1,10 +1,11 @@ +import * as sdk from "@defillama/sdk"; import { CHAIN } from "../../helpers/chains"; import { univ2Adapter } from "../../helpers/getUniSubgraphVolume"; const adapters = univ2Adapter( { [CHAIN.BSC]: - "https://api.thegraph.com/subgraphs/name/miguelangelrm/kyotoswap-exchange", + sdk.graph.modifyEndpoint('B1VWKexyptT1ixDdHsxj3EJnAxvuje7ANT39rnfq9rRG'), }, { factoriesName: "pancakeFactories", diff --git a/dexs/leonicornswap/index.ts b/dexs/leonicornswap/index.ts index 71ae184e1b..a59dfe1738 100644 --- a/dexs/leonicornswap/index.ts +++ b/dexs/leonicornswap/index.ts @@ -1,8 +1,9 @@ +import * as sdk from "@defillama/sdk"; import { CHAIN } from "../../helpers/chains"; import { univ2Adapter } from "../../helpers/getUniSubgraphVolume"; export default univ2Adapter({ - [CHAIN.BSC]: "https://api.thegraph.com/subgraphs/name/leonicornswap/exchange" + [CHAIN.BSC]: sdk.graph.modifyEndpoint('ttjEWD8FZJecTZrHHhtiYnQtWhSmgtqqABU4pgAttaC') }, { factoriesName: "leonicornFactories", dayData: "leonicornDayData", diff --git a/dexs/levana/fetch.ts b/dexs/levana/fetch.ts index 6fe7500d1c..eed5d4f6a4 100644 --- a/dexs/levana/fetch.ts +++ b/dexs/levana/fetch.ts @@ -4,18 +4,20 @@ import { httpGet } from "../../utils/fetchURL"; const INDEXER_URL = "https://indexer-mainnet.levana.finance"; const QUERIER_URL = "https://querier-mainnet.levana.finance"; -type Chain = "osmosis" | "injective" | "sei" +type Chain = "osmosis" | "injective" | "sei" | "neutron" const factoryAddr:Record = { osmosis: "osmo1ssw6x553kzqher0earlkwlxasfm2stnl3ms3ma2zz4tnajxyyaaqlucd45", sei: "sei18rdj3asllguwr6lnyu2sw8p8nut0shuj3sme27ndvvw4gakjnjqqper95h", - injective: "inj1vdu3s39dl8t5l88tyqwuhzklsx9587adv8cnn9" + injective: "inj1vdu3s39dl8t5l88tyqwuhzklsx9587adv8cnn9", + neutron: "neutron1an8ls6d57c4qcvjq0jmm27jtrpk65twewfjqzdn7annefv7gadqsjs7uc3", } const networkName:Record = { osmosis: "osmosis-mainnet", sei: "sei-mainnet", - injective: "injective-mainnet" + injective: "injective-mainnet", + neutron: "neutron-mainnet" } export interface MarketInfo { diff --git a/dexs/levana/index.ts b/dexs/levana/index.ts index 4ed1c5bed5..bd1deb9315 100644 --- a/dexs/levana/index.ts +++ b/dexs/levana/index.ts @@ -40,6 +40,19 @@ const adapter: SimpleAdapter = { return { timestamp, dailyVolume, totalVolume, } }, start: 1695738685 + }, + neutron: { + fetch: async (timestamp: number): Promise => { + const marketInfos = await fetchMarketInfos("neutron"); + + const [dailyVolume, totalVolume] = await Promise.all([ + fetchVolume("daily", marketInfos, timestamp), + fetchVolume("total", marketInfos, timestamp) + ]); + + return { timestamp, dailyVolume, totalVolume, } + }, + start: 1715168042 } } } diff --git a/dexs/level-finance/index.ts b/dexs/level-finance/index.ts index b005f08690..2da3b659cf 100644 --- a/dexs/level-finance/index.ts +++ b/dexs/level-finance/index.ts @@ -1,3 +1,4 @@ +import * as sdk from "@defillama/sdk"; import request, { gql } from "graphql-request"; import { BreakdownAdapter, Fetch, SimpleAdapter } from "../../adapters/types"; import { CHAIN } from "../../helpers/chains"; @@ -5,8 +6,8 @@ import { getUniqStartOfTodayTimestamp } from "../../helpers/getUniSubgraphVolume import { adapter_derivative } from "./level-finance-derivative"; const endpoints: { [key: string]: string } = { - [CHAIN.BSC]: "https://api.thegraph.com/subgraphs/name/level-fi/levelfinanceanalytics", - [CHAIN.ARBITRUM]: "https://api.thegraph.com/subgraphs/name/level-fi/analytics-arb", + [CHAIN.BSC]: sdk.graph.modifyEndpoint('AFaRssJTqNReTtU2XdTGPhN38YVPNBc7faMNKA1mU54h'), + [CHAIN.ARBITRUM]: sdk.graph.modifyEndpoint('AV58XWaZUZPJ2w1x2wYmGEivVZmDojGW3fAYggUAujtD'), } const historicalDataSwap = gql` diff --git a/dexs/level-finance/level-finance-derivative/index.ts b/dexs/level-finance/level-finance-derivative/index.ts index 8452b1b111..4e90f9d57a 100644 --- a/dexs/level-finance/level-finance-derivative/index.ts +++ b/dexs/level-finance/level-finance-derivative/index.ts @@ -1,11 +1,12 @@ +import * as sdk from "@defillama/sdk"; import request, { gql } from "graphql-request"; import { Fetch, SimpleAdapter } from "../../../adapters/types"; import { CHAIN } from "../../../helpers/chains"; import { getUniqStartOfTodayTimestamp } from "../../../helpers/getUniSubgraphVolume"; const endpoints: { [key: string]: string } = { - [CHAIN.BSC]: "https://api.thegraph.com/subgraphs/name/level-fi/levelfinanceanalytics", - [CHAIN.ARBITRUM]: "https://api.thegraph.com/subgraphs/name/level-fi/analytics-arb", + [CHAIN.BSC]: sdk.graph.modifyEndpoint('AFaRssJTqNReTtU2XdTGPhN38YVPNBc7faMNKA1mU54h'), + [CHAIN.ARBITRUM]: sdk.graph.modifyEndpoint('AV58XWaZUZPJ2w1x2wYmGEivVZmDojGW3fAYggUAujtD'), } const historicalDataDerivatives = gql` diff --git a/dexs/levinswap/index.ts b/dexs/levinswap/index.ts index deb16b80fd..50d1ec552d 100644 --- a/dexs/levinswap/index.ts +++ b/dexs/levinswap/index.ts @@ -1,8 +1,9 @@ +import * as sdk from "@defillama/sdk"; import { CHAIN } from "../../helpers/chains"; import { univ2Adapter } from "../../helpers/getUniSubgraphVolume"; const adapters = univ2Adapter({ - [CHAIN.XDAI]: "https://api.thegraph.com/subgraphs/name/levinswap/uniswap-v2" + [CHAIN.XDAI]: sdk.graph.modifyEndpoint('2gNP6y1kTvg6aAhus8DU8DyGS1cn5TvGD3S6VjjXCZZC') }, {}); adapters.adapter.xdai.start = 1610767793; diff --git a/dexs/lifinity/index.ts b/dexs/lifinity/index.ts index 9de281e50c..21641df9a3 100644 --- a/dexs/lifinity/index.ts +++ b/dexs/lifinity/index.ts @@ -5,7 +5,7 @@ import { CHAIN } from "../../helpers/chains"; import customBackfill from "../../helpers/customBackfill"; import { getUniqStartOfTodayTimestamp } from "../../helpers/getUniSubgraphVolume"; -const historicalVolumeEndpoint = "https://lifinity.io/api/dashboard/volume" +const historicalVolumeEndpoint = "https://api.lifinity.io/api/dashboard/volume" interface IVolumeall { volume: number; diff --git a/dexs/linehub-perps/index.ts b/dexs/linehub-perps/index.ts new file mode 100644 index 0000000000..391f70ce85 --- /dev/null +++ b/dexs/linehub-perps/index.ts @@ -0,0 +1,68 @@ +import request, { gql } from "graphql-request"; +import { Adapter, ChainEndpoints, FetchV2 } from "../../adapters/types"; +import { CHAIN } from "../../helpers/chains"; +import { getTimestampAtStartOfDayUTC } from "../../utils/date"; + +const endpoints = { + [CHAIN.LINEA]: + "https://api.studio.thegraph.com/query/55804/linehub-trade/version/latest", +}; + +interface IVolumeStat { + cumulativeVolumeUsd: string; + volumeUsd: string; + id: string; +} + +const graphs = (graphUrls: ChainEndpoints) => { + const fetch: FetchV2 = async ({ chain, startTimestamp }) => { + const todaysTimestamp = getTimestampAtStartOfDayUTC(startTimestamp); + + const graphQuery = gql` + query MyQuery { + volumeStats(where: {timestamp: ${todaysTimestamp}, period: "daily"}) { + cumulativeVolumeUsd + volumeUsd + id + } + } + `; + + const graphRes = await request(graphUrls[chain], graphQuery); + const volumeStats: IVolumeStat[] = graphRes.volumeStats; + + let dailyVolumeUSD = BigInt(0); + + volumeStats.forEach((vol) => { + dailyVolumeUSD += BigInt(vol.volumeUsd); + }); + + const finalDailyVolume = parseInt(dailyVolumeUSD.toString()) / 1e18; + + return { + dailyVolume: finalDailyVolume.toString(), + timestamp: todaysTimestamp, + }; + }; + return fetch; +}; + +const methodology = { + dailyVolume: + "Total cumulativeVolumeUsd for specified chain for the given day", +}; + +const adapter: Adapter = { + version: 2, + adapter: { + [CHAIN.LINEA]: { + fetch: graphs(endpoints), + start: 1719878400, + meta: { + methodology, + }, + }, + }, +}; + +export default adapter; diff --git a/dexs/linehub-v3/index.ts b/dexs/linehub-v3/index.ts new file mode 100644 index 0000000000..a35edc86ed --- /dev/null +++ b/dexs/linehub-v3/index.ts @@ -0,0 +1,60 @@ +import { Chain } from "@defillama/sdk/build/general"; +import { CHAIN } from "../../helpers/chains"; +import { getGraphDimensions2 } from "../../helpers/getUniSubgraph"; +import { BreakdownAdapter } from "../../adapters/types"; + +const endpointsV3 = { + [CHAIN.LINEA]: + "https://api.studio.thegraph.com/query/55804/linehub-v3/version/latest", +}; + +const v3Graphs = getGraphDimensions2({ + graphUrls: endpointsV3, + totalVolume: { + factory: "factories", + field: "totalVolumeUSD", + }, + feesPercent: { + type: "fees", + ProtocolRevenue: 0, + HoldersRevenue: 0, + UserFees: 100, // User fees are 100% of collected fees + SupplySideRevenue: 100, // 100% of fees are going to LPs + Revenue: 0, // Set revenue to 0 as protocol fee is not set for all pools for now + }, +}); + +const startTimeV3: { [key: string]: number } = { + [CHAIN.LINEA]: 1713398400, // Thursday, April 18, 2024 12:00:00 AM +}; + +const v3 = Object.keys(endpointsV3).reduce( + (acc, chain) => ({ + ...acc, + [chain]: { + fetch: v3Graphs(chain as Chain), + start: startTimeV3[chain], + meta: { + methodology: { + Fees: "Each pool charge between 0.01% to 1% fee", + UserFees: "Users pay between 0.01% to 1% fee", + Revenue: "0 to 1/4 of the fee goes to treasury", + HoldersRevenue: "None", + ProtocolRevenue: "Treasury receives a share of the fees", + SupplySideRevenue: + "Liquidity providers get most of the fees of all trades in their pools", + }, + }, + }, + }), + {} +); + +const adapter: BreakdownAdapter = { + version: 2, + breakdown: { + v3: v3, + }, +}; + +export default adapter; diff --git a/dexs/liquidswap/index.ts b/dexs/liquidswap/index.ts index 13b189db72..518c3ed7ff 100644 --- a/dexs/liquidswap/index.ts +++ b/dexs/liquidswap/index.ts @@ -19,7 +19,7 @@ const fetch = async (timestamp: number) => { .reduce((acc, { value }) => acc + Number(value), 0) const dailyVolume = historicalVolume - .find(dayItem => Number(dayItem.timestamp) === dayTimestamp)?.value + .find(dayItem => getUniqStartOfTodayTimestamp(new Date(Number(dayItem.timestamp) * 1000)) === dayTimestamp)?.value return { totalVolume: `${totalVolume}`, diff --git a/dexs/litx/index.ts b/dexs/litx/index.ts index dc6bba5367..633f4efc1b 100644 --- a/dexs/litx/index.ts +++ b/dexs/litx/index.ts @@ -1,10 +1,11 @@ +import * as sdk from "@defillama/sdk"; import { DISABLED_ADAPTER_KEY } from "../../adapters/types"; import { CHAIN } from "../../helpers/chains"; import disabledAdapter from "../../helpers/disabledAdapter"; import { univ2Adapter } from "../../helpers/getUniSubgraphVolume"; const adapters = univ2Adapter({ - [CHAIN.BSC]: "https://api.thegraph.com/subgraphs/name/iliaazhel/litx-v1-1", + [CHAIN.BSC]: sdk.graph.modifyEndpoint('4b9bf8yyMfQBkjD94wmxFc4zf9ewhhQHhHfPqJrsSiq1'), [CHAIN.PULSECHAIN]: "https://api.algebra.finance/pulse-graph/subgraphs/name/cryptoalgebra/litx-analytics" }, { factoriesName: "factories", @@ -15,5 +16,7 @@ const adapters = univ2Adapter({ adapters.adapter.bsc.start = 1687305600; adapters.adapter.pulse.start = 1686096000; +adapters.adapter.bsc.fetch = async (timestamp: number) => {return{timestamp, dailyVolume: 0}} +adapters.adapter.pulse.fetch = async (timestamp: number) => {return{timestamp, dailyVolume: 0}} adapters.adapter[DISABLED_ADAPTER_KEY] = disabledAdapter; export default adapters; diff --git a/aggregator-derivatives/logx-aggregator/index.ts b/dexs/logx/index.ts similarity index 52% rename from aggregator-derivatives/logx-aggregator/index.ts rename to dexs/logx/index.ts index badc642553..e9b5502f43 100644 --- a/aggregator-derivatives/logx-aggregator/index.ts +++ b/dexs/logx/index.ts @@ -2,32 +2,32 @@ import fetchURL from "../../utils/fetchURL"; import { FetchResult, SimpleAdapter } from "../../adapters/types"; import { CHAIN } from "../../helpers/chains"; -const URL = "https://logx-data-analytics-xmxmxbqxaq-uc.a.run.app/"; -const endpoint = "defillama/defillama/"; -const startTimestamp = 1686205277; // 08.06.2023 + +const URLEndpoint = "https://apiserver.logx.network/api/v1/stats/defillama?endTime="; +const startTimestamp = 1725580800; // 06.09.2024 interface IAPIResponse { - dailyVolume: string; + last24HourVolume: string; totalVolume: string; } const fetch = async (timestamp: number): Promise => { - const { dailyVolume, totalVolume }: IAPIResponse = ( - await fetchURL(`${URL}${endpoint}${timestamp}`) + const { last24HourVolume, totalVolume }: IAPIResponse = ( + await fetchURL(`${URLEndpoint}${timestamp}`) ); return { - dailyVolume, - totalVolume, - timestamp, + totalVolume: totalVolume, + dailyVolume: last24HourVolume, + timestamp: timestamp }; }; const adapter: SimpleAdapter = { adapter: { - [CHAIN.ARBITRUM]: { + [CHAIN.LOGX]: { fetch, start: startTimestamp, }, - }, + } }; export default adapter; diff --git a/dexs/luaswap/index.ts b/dexs/luaswap/index.ts index 092b9b84df..0236b15fb0 100644 --- a/dexs/luaswap/index.ts +++ b/dexs/luaswap/index.ts @@ -1,8 +1,9 @@ +import * as sdk from "@defillama/sdk"; import { CHAIN } from "../../helpers/chains"; import { univ2Adapter } from "../../helpers/getUniSubgraphVolume"; // process.env.NODE_TLS_REJECT_UNAUTHORIZED='0' // TODO: disable TLS check only for this adapter, above line disables it for all adapters which is not ok export default univ2Adapter({ - [CHAIN.TOMOCHAIN]: "https://api.luaswap.org/subgraphs/name/phucngh/Luaswap3", - [CHAIN.ETHEREUM]: "https://api.thegraph.com/subgraphs/name/phucngh/luaswap" + // [CHAIN.TOMOCHAIN]: "https://api.luaswap.org/subgraphs/name/phucngh/Luaswap3", + [CHAIN.ETHEREUM]: sdk.graph.modifyEndpoint('DuiyRWD7SNu5rMGtM1MMP25VN57NcRGynCLJR7pah2E4') }, {}); diff --git a/dexs/lynex-v1/index.ts b/dexs/lynex-v1/index.ts index 5500411e3f..b39e01e723 100644 --- a/dexs/lynex-v1/index.ts +++ b/dexs/lynex-v1/index.ts @@ -1,19 +1,31 @@ +import { SimpleAdapter } from "../../adapters/types"; import { CHAIN } from "../../helpers/chains"; -import { univ2Adapter } from "../../helpers/getUniSubgraphVolume"; +import { getChainVolume } from "../../helpers/getUniSubgraphVolume"; -const adapters = univ2Adapter( - { - [CHAIN.LINEA]: - "https://api.studio.thegraph.com/query/59052/lynex-v1/v0.0.4", +const graphqlV3 = getChainVolume({ + graphUrls: { + [CHAIN.LINEA]: "https://api.studio.thegraph.com/query/59052/lynex-v1/v0.1.0", }, - { - factoriesName: "factories", - dayData: "dayData", - dailyVolume: "dailyVolumeUSD", - totalVolume: "totalVolumeUSD", + totalVolume: { + factory: "factories", + field: "totalVolumeUSD", + }, + dailyVolume: { + factory: "dayData", + field: "dailyVolumeUSD", + dateField: "date" } -); +}); + + +const adapters: SimpleAdapter = { + adapter: { + [CHAIN.LINEA]: { + fetch: graphqlV3(CHAIN.LINEA), + start: 1707620640, + }, + }, + version: 2, +} -// New v1 factory contract created at block 2202427 = UNIX timestamp 1707620640 -adapters.adapter.linea.start = 1707620640; export default adapters; diff --git a/dexs/lynex/index.ts b/dexs/lynex/index.ts index aebddd92b1..75750ab084 100644 --- a/dexs/lynex/index.ts +++ b/dexs/lynex/index.ts @@ -1,12 +1,10 @@ import { CHAIN } from "../../helpers/chains"; -import { univ2Adapter } from "../../helpers/getUniSubgraphVolume"; +import { univ2Adapter2 } from "../../helpers/getUniSubgraphVolume"; -const adapters = univ2Adapter({ - [CHAIN.LINEA]: "https://graph-query.linea.build/subgraphs/name/cryptoalgebra/analytics" +const adapters = univ2Adapter2({ + [CHAIN.LINEA]: "https://api.studio.thegraph.com/query/59052/lynex-cl/v1.0.1" }, { factoriesName: "factories", - dayData: "algebraDayData", - dailyVolume: "volumeUSD", totalVolume: "totalVolumeUSD", }); diff --git a/dexs/lyra/index.ts b/dexs/lyra/index.ts new file mode 100644 index 0000000000..060016a7f0 --- /dev/null +++ b/dexs/lyra/index.ts @@ -0,0 +1,51 @@ +import { ChainBlocks, FetchOptions, SimpleAdapter } from "../../adapters/types"; +import fetchURL from "../../utils/fetchURL"; +import { CHAIN } from "../../helpers/chains"; +import { getTimestampAtStartOfNextDayUTC } from "../../utils/date"; + +interface ILyraVolumeResponse { + daily_premium_volume: string; + total_premium_volume: string; +} + +// endTime is in nanoseconds +export const lyraVolumeEndpoint = (endTime: number) => { + return ( + "https://api.lyra.finance/public/statistics?instrument_name=PERP&end_time=" + + endTime + ); +}; + +const adapter: SimpleAdapter = { + adapter: { + [CHAIN.LYRA]: { + fetch: fetchLyraVolumeData, + start: 1702630075, + }, + }, +}; + +export async function fetchLyraVolumeData( + timestamp: number +) { + const dayTimestamp = getTimestampAtStartOfNextDayUTC(timestamp); + const timestamp_in_ms = dayTimestamp * 1000 + const lyraVolumeData = await getLyraVolumeData(lyraVolumeEndpoint(timestamp_in_ms)); + const dailyVolume = Number(lyraVolumeData.daily_premium_volume).toFixed(2); + const totalVolume = Number(lyraVolumeData.total_premium_volume).toFixed(2); + + return { + timestamp, + dailyVolume, + totalVolume, + }; +} + +async function getLyraVolumeData( + endpoint: string +): Promise { + const results = await fetchURL(endpoint) + return results.result; +} + +export default adapter; diff --git a/dexs/macaron-xyz/index.ts b/dexs/macaron-xyz/index.ts new file mode 100644 index 0000000000..6cc88d4554 --- /dev/null +++ b/dexs/macaron-xyz/index.ts @@ -0,0 +1,57 @@ +import fetchURL from "../../utils/fetchURL" +import { ChainBlocks, SimpleAdapter } from "../../adapters/types"; +import { CHAIN } from "../../helpers/chains"; +import customBackfill from "../../helpers/customBackfill"; +import { getUniqStartOfTodayTimestamp } from "../../helpers/getUniSubgraphVolume"; +import { Chain } from "@defillama/sdk/build/general"; + +const historicalVolumeEndpoint = "https://info-api.macaron.xyz/pair/" + +interface IVolume { + count: string; + statistics_date: string; + volume: string; +} +type ChainMapId = { + [chain: string | Chain]: number; +} +const mapChainId: ChainMapId = { + [CHAIN.BITLAYER]: 200901 +}; +const fetch = (chain: Chain) => { + return async (timestamp: any) => { + const dayTimestamp = getUniqStartOfTodayTimestamp(new Date(timestamp.toTimestamp * 1000)); + const historicalVolume: IVolume[] = (await fetchURL(`${historicalVolumeEndpoint}/${mapChainId[chain]}/volume`)).data; + const totalVolume = historicalVolume + .filter(volItem => getUniqStartOfTodayTimestamp(new Date(volItem.statistics_date)) <= dayTimestamp) + .reduce((acc, { volume }) => acc + Number(volume), 0) + const dailyVolume = historicalVolume + .find(dayItem => getUniqStartOfTodayTimestamp(new Date(dayItem.statistics_date)) === dayTimestamp)?.volume + return { + totalVolume: `${totalVolume}`, + dailyVolume: dailyVolume ? `${dailyVolume}` : undefined, + timestamp: dayTimestamp, + }; + }; +} + +const getStartTimestamp = async (chain: Chain) => { + // const queryByChainId = `?chain_id=${mapChainId[chain]}`; + const historicalVolume: IVolume[] = (await fetchURL(`${historicalVolumeEndpoint}/${mapChainId[chain]}/volume`)).data; + return (new Date(historicalVolume[0].statistics_date).getTime()) / 1000 +} +const adapter: SimpleAdapter = { + version: 2, + adapter: Object.keys(mapChainId).reduce((acc, chain: any) => { + return { + ...acc, + [chain]: { + fetch: fetch(chain as Chain), + start: async () => getStartTimestamp(chain), + customBackfill: customBackfill(chain as Chain, fetch), + } + } + }, {}) +}; + +export default adapter; diff --git a/dexs/maia-v3/index.ts b/dexs/maia-v3/index.ts index e816a089d8..420aa8fd41 100644 --- a/dexs/maia-v3/index.ts +++ b/dexs/maia-v3/index.ts @@ -1,11 +1,9 @@ import { SimpleAdapter } from "../../adapters/types"; import { CHAIN } from "../../helpers/chains"; -import { getStartTimestamp } from "../../helpers/getStartTimestamp"; - import { - getGraphDimensions, DEFAULT_DAILY_VOLUME_FACTORY, DEFAULT_TOTAL_VOLUME_FIELD, + getGraphDimensions2, } from "../../helpers/getUniSubgraph" const v3Endpoints = { @@ -14,19 +12,15 @@ const v3Endpoints = { const VOLUME_USD = "volumeUSD"; -const v3Graphs = getGraphDimensions({ +const v3Graphs = getGraphDimensions2({ graphUrls: v3Endpoints, totalVolume: { factory: "factories", field: DEFAULT_TOTAL_VOLUME_FIELD, }, - dailyVolume: { - factory: DEFAULT_DAILY_VOLUME_FACTORY, - field: VOLUME_USD, - }, feesPercent: { type: "fees", - ProtocolRevenue: 10, // 10% of fees are going to LPs + ProtocolRevenue: 10, // 10% of fees are going to protocol HoldersRevenue: 0, UserFees: 100, // User fees are 100% of collected fees SupplySideRevenue: 90, // 90% of fees are going to LPs @@ -42,6 +36,7 @@ const methodology = { } const adapter: SimpleAdapter = { + version: 2, adapter: { [CHAIN.METIS]: { fetch: v3Graphs(CHAIN.METIS), diff --git a/dexs/makiswap/index.ts b/dexs/makiswap/index.ts index 203a2042d4..0241ed2593 100644 --- a/dexs/makiswap/index.ts +++ b/dexs/makiswap/index.ts @@ -1,9 +1,13 @@ import { CHAIN } from "../../helpers/chains"; import { univ2Adapter } from "../../helpers/getUniSubgraphVolume"; -export default univ2Adapter({ +const adapter = univ2Adapter({ [CHAIN.HECO]: "https://api2.makiswap.com/subgraphs/name/maki-mainnet/exchange" }, { factoriesName: "pancakeFactories", dayData: "pancakeDayData" }); + +adapter.adapter[CHAIN.HECO].start = 1630000000; +adapter.adapter[CHAIN.HECO].fetch = async (timestamp: number) => { return { timestamp}}; +export default adapter; diff --git a/dexs/mangrove/index.ts b/dexs/mangrove/index.ts new file mode 100644 index 0000000000..4ebcde2913 --- /dev/null +++ b/dexs/mangrove/index.ts @@ -0,0 +1,101 @@ +import type { ChainApi } from "@defillama/sdk"; +import type { + Adapter, + BaseAdapter, + FetchOptions, + FetchResultV2, +} from "../../adapters/types"; +import { CHAIN } from "../../helpers/chains"; + +type ChainConfig = { + core: string; + start: number; +}; + +const mangrove: Record = { + [CHAIN.BLAST]: { + core: "0xb1a49C54192Ea59B233200eA38aB56650Dfb448C", + start: 1708992000, + }, + [CHAIN.ARBITRUM]: { + core: "0x109d9CDFA4aC534354873EF634EF63C235F93f61", + start: 1721664539, + }, +}; + +const abi = { + OfferSuccess: + "event OfferSuccess(bytes32 indexed olKeyHash, address indexed taker, uint indexed id, uint takerWants, uint takerGives)", + OfferSuccessWithPosthookData: + "event OfferSuccessWithPosthookData(bytes32 indexed olKeyHash,address indexed taker,uint indexed id,uint takerWants,uint takerGives,bytes32 posthookData)", + olKeys: + "function olKeys(bytes32 olKeyHash) external view returns (address outbound_tkn,address inbound_tkn,uint tickSpacing)", +}; + +async function getToken( + map: Map, + olKeyHash: string, + api: ChainApi, + chain: string, +): Promise { + let token = map.get(olKeyHash.toLowerCase()); + if (token) { + return token; + } + const apiToken = await api.call({ + abi: abi.olKeys, + params: [olKeyHash], + target: mangrove[chain].core, + }); + token = apiToken[0] as string; + map.set(olKeyHash.toLowerCase(), token); + return token; +} + +async function fetch({ + getLogs, + api, + chain, + createBalances, +}: FetchOptions): Promise { + const dailyVolume = createBalances(); + const olKeys = new Map(); + const logs = await Promise.all([ + getLogs({ + eventAbi: abi.OfferSuccessWithPosthookData, + target: mangrove[chain].core, + }), + getLogs({ + eventAbi: abi.OfferSuccess, + target: mangrove[chain].core, + }), + ]).then((r) => r.flat()); + for (const log of logs) { + const olKeyHash = log.olKeyHash; + const token = await getToken(olKeys, olKeyHash, api, chain); + dailyVolume.add(token, log.takerWants); + } + return { + dailyVolume, + }; +} + +const adapter: Adapter = { + version: 2, + adapter: { + ...Object.entries(mangrove).reduce((acc, [key, config]) => { + acc[key] = { + meta: { + methodology: { + dailyVolume: "Sum of all offers taken in the last 24hrs", + }, + }, + fetch, + start: config.start, + }; + return acc; + }, {} as BaseAdapter), + }, +}; + +export default adapter; diff --git a/dexs/maverick-v2/index.ts b/dexs/maverick-v2/index.ts new file mode 100644 index 0000000000..1fb8f5f7da --- /dev/null +++ b/dexs/maverick-v2/index.ts @@ -0,0 +1,36 @@ +// Maverick v2 volume +import { SimpleAdapter } from "../../adapters/types"; +import { CHAIN } from "../../helpers/chains"; +import { getData, maverickV2Factories } from "./maverick-v2"; + +const adapter: SimpleAdapter = { + version: 2, + adapter: { + [CHAIN.BSC]: { + fetch: getData, + start: maverickV2Factories[CHAIN.BSC].startTimestamp, + }, + [CHAIN.BASE]: { + fetch: getData, + start: maverickV2Factories[CHAIN.BASE].startTimestamp, + }, + [CHAIN.ERA]: { + fetch: getData, + start: maverickV2Factories[CHAIN.ERA].startTimestamp, + }, + [CHAIN.ETHEREUM]: { + fetch: getData, + start: maverickV2Factories[CHAIN.ETHEREUM].startTimestamp, + }, + [CHAIN.ARBITRUM]: { + fetch: getData, + start: maverickV2Factories[CHAIN.ARBITRUM].startTimestamp, + }, + [CHAIN.SCROLL]: { + fetch: getData, + start: maverickV2Factories[CHAIN.SCROLL].startTimestamp, + }, + }, +}; + +export default adapter; diff --git a/dexs/maverick-v2/maverick-v2.ts b/dexs/maverick-v2/maverick-v2.ts new file mode 100644 index 0000000000..5d851af58d --- /dev/null +++ b/dexs/maverick-v2/maverick-v2.ts @@ -0,0 +1,91 @@ +import { CHAIN } from "../../helpers/chains"; +import { FetchOptions } from "../../adapters/types"; + +export const maverickV2Factories: { [key: string]: any } = { + [CHAIN.ETHEREUM]: { + factory: "0x0A7e848Aca42d879EF06507Fca0E7b33A0a63c1e", + startBlock: 20027236, + startTimestamp: 1717372801, + }, + [CHAIN.ARBITRUM]: { + factory: "0x0A7e848Aca42d879EF06507Fca0E7b33A0a63c1e", + startBlock: 219205177, + startTimestamp: 1717372801, + }, + [CHAIN.ERA]: { + factory: "0x7A6902af768a06bdfAb4F076552036bf68D1dc56", + startBlock: 35938167, + startTimestamp: 1717372801, + }, + [CHAIN.BSC]: { + factory: "0x0A7e848Aca42d879EF06507Fca0E7b33A0a63c1e", + startBlock: 39421941, + startTimestamp: 1717372801, + }, + [CHAIN.BASE]: { + factory: "0x0A7e848Aca42d879EF06507Fca0E7b33A0a63c1e", + startBlock: 15321281, + startTimestamp: 1717372801, + }, + [CHAIN.SCROLL]: { + factory: "0x0A7e848Aca42d879EF06507Fca0E7b33A0a63c1e", + startBlock: 7332349, + startTimestamp: 1720621814, + }, +}; + +const mavV2PoolCreated = `event PoolCreated(address poolAddress,uint8 protocolFeeRatio,uint256 feeAIn,uint256 feeBIn,uint256 tickSpacing,uint256 lookback,int32 activeTick,address tokenA,address tokenB,uint8 kinds,address accessor)`; + +const mavV2SwapEvent = + "event PoolSwap(address sender,address recipient,(uint256 amount,bool tokenAIn,bool exactOutput,int32 tickLimit) params,uint256 amountIn,uint256 amountOut)"; + +export const getData = async (options: FetchOptions) => { + const factory = maverickV2Factories[options.chain].factory; + const factoryFromBlock = maverickV2Factories[options.chain].startBlock; + const dailyFees = options.createBalances(); + const dailyVolume = options.createBalances(); + try { + const logs = await options.getLogs({ + target: factory, + fromBlock: factoryFromBlock, + eventAbi: mavV2PoolCreated, + }); + const pools = [...new Set(logs.map((log: any) => log.poolAddress))]; + const tokenAs = await options.api.multiCall({ abi: "address:tokenA", calls: pools! }); + const tokenBs = await options.api.multiCall({ abi: "address:tokenB", calls: pools! }); + const swapLogs = await options.getLogs({ + targets: pools, + eventAbi: mavV2SwapEvent, + topic: "0x103ed084e94a44c8f5f6ba8e3011507c41063177e29949083c439777d8d63f60", + flatten: false, + }); + + const feesA = logs.map((log: any) => Number(log.feeAIn)); + const feesB = logs.map((log: any) => Number(log.feeBIn)); + + swapLogs.forEach((log: any[], index: number) => { + const tokenA = tokenAs[index]; + const tokenB = tokenBs[index]; + if (!log.length) return; + log.forEach((i: any) => { + // element 3 is amount in + const amount = Number(i[3]); + // element 2,1 is tokenAIn + const tokenAIn = Boolean(i[2][1]); + const fee = tokenAIn ? feesA[index] : feesB[index]; + dailyFees.add(tokenAIn ? tokenA : tokenB, (amount) * (fee / 1e18)); + dailyVolume.add(tokenAIn ? tokenA : tokenB, amount); + }); + }); + return { + dailyVolume: dailyVolume, + dailyFees: dailyFees, + }; + } catch (e) { + console.error(e); + return { + dailyVolume: dailyVolume, + dailyFees: dailyFees, + }; + } +}; diff --git a/dexs/maverick/index.ts b/dexs/maverick/index.ts index d2cf308802..79f51909d5 100644 --- a/dexs/maverick/index.ts +++ b/dexs/maverick/index.ts @@ -1,25 +1,26 @@ // Maverick v1 volume import { SimpleAdapter } from "../../adapters/types"; import { CHAIN } from "../../helpers/chains"; -import { fetchVolume } from "./maverick"; +import { fetchVolumeV1, maverickV1Factories } from "./maverick-v1"; const adapter: SimpleAdapter = { + version: 2, adapter: { - [CHAIN.ETHEREUM]: { - fetch: fetchVolume(CHAIN.ETHEREUM), - start: 1676851200, - }, - [CHAIN.ERA]: { - fetch: fetchVolume(CHAIN.ERA), - start: 1681257600, - }, [CHAIN.BSC]: { - fetch: fetchVolume(CHAIN.BSC), - start: 29241049, + fetch: fetchVolumeV1(), + start: maverickV1Factories[CHAIN.BSC].startTimestamp, }, [CHAIN.BASE]: { - fetch: fetchVolume(CHAIN.BASE), - start: 1489614, + fetch: fetchVolumeV1(), + start: maverickV1Factories[CHAIN.BASE].startTimestamp, + }, + [CHAIN.ERA]: { + fetch: fetchVolumeV1(), + start: maverickV1Factories[CHAIN.ERA].startTimestamp, + }, + [CHAIN.ETHEREUM]: { + fetch: fetchVolumeV1(), + start: maverickV1Factories[CHAIN.ETHEREUM].startTimestamp, }, }, }; diff --git a/dexs/maverick/maverick-v1.ts b/dexs/maverick/maverick-v1.ts new file mode 100644 index 0000000000..cc807a9aff --- /dev/null +++ b/dexs/maverick/maverick-v1.ts @@ -0,0 +1,97 @@ +import { CHAIN } from "../../helpers/chains"; +import { FetchOptions } from "../../adapters/types"; +import { filterPools2 } from "../../helpers/uniswap"; + +export const maverickV1Factories: { [key: string]: any } = { + [CHAIN.ETHEREUM]: { + factory: "0xEb6625D65a0553c9dBc64449e56abFe519bd9c9B", + startBlock: 17210220, + startTimestamp: 1683417601, + }, + [CHAIN.ERA]: { + factory: "0x2C1a605f843A2E18b7d7772f0Ce23c236acCF7f5", + startBlock: 3002730, + startTimestamp: 1683417601, + }, + [CHAIN.BSC]: { + factory: "0x76311728FF86054Ad4Ac52D2E9Ca005BC702f589", + startBlock: 29241049, + startTimestamp: 1687132801, + }, + [CHAIN.BASE]: { + factory: "0xB2855783a346735e4AAe0c1eb894DEf861Fa9b45", + startBlock: 1489614, + startTimestamp: 1689724801, + }, +}; + +const mavV2PoolCreated = + "event PoolCreated(address poolAddress,uint256 fee,uint256 tickSpacing,int32 activeTick,int256 lookback,uint64 protocolFeeRatio,address tokenA,address tokenB)"; + +const mavV2SwapEvent = + "event Swap(address sender,address recipient,bool tokenAIn,bool exactOutput,uint256 amountIn,uint256 amountOut,int32 activeTick)"; + +const getData = async (options: any, dataType: "volume" | "fee") => { + const factory = maverickV1Factories[options.chain].factory; + const factoryFromBlock = maverickV1Factories[options.chain].startBlock; + + let pools: string[]; + const logs = await options.getLogs({ target: factory, fromBlock: factoryFromBlock, eventAbi: mavV2PoolCreated, }); + + pools = logs.map((log: any) => log.poolAddress.toLowerCase()); + const tokenAs = await options.api.multiCall({ abi: "address:tokenA", calls: pools!, }); + const tokenBs = await options.api.multiCall({ abi: "address:tokenB", calls: pools!, }); + let fees = await options.api.multiCall({ abi: "function fee() view returns (uint256)", calls: pools!, }); + const poolInfos = { } as any + pools.forEach((pool, idx) => { + poolInfos[pool] = { + tokenA: tokenAs[idx], + tokenB: tokenBs[idx], + fee: fees[idx] / 1e18, + } + }) + + const filteredPoolsRes = await filterPools2({ fetchOptions: options, pairs: pools, token0s: tokenAs, token1s: tokenBs }) + pools = filteredPoolsRes.pairs + + const swapLogs = await options.getLogs({ targets: pools, eventAbi: mavV2SwapEvent, flatten: false, }); + + swapLogs.forEach((log: any[], index: number) => { + const { tokenA, tokenB, fee } = poolInfos[pools[index]] + if (!log.length) return; + log.forEach((i: any) => { + let amount = Number(i.amountIn); + let tokenAIn = Boolean(i.tokenAIn); + + if (dataType == "fee") { + options.api.add(tokenAIn ? tokenA : tokenB, amount * fee); + } else { + options.api.add(tokenAIn ? tokenA : tokenB, amount); + } + }); + }); + + let amount = await options.api.getBalancesV2(); + if (dataType == "fee") { + return { + dailyFees: amount, + dailyUserFees: amount, + }; + } else { + return { + dailyVolume: amount, + }; + } +}; + +export const fetchVolumeV1 = () => { + return async (options: FetchOptions) => { + return await getData(options, "volume"); + }; +}; + +export const fetchFeeV1 = () => { + return async (options: FetchOptions) => { + return await getData(options, "fee"); + }; +}; diff --git a/dexs/maverick/maverick.ts b/dexs/maverick/maverick.ts deleted file mode 100644 index e22f756ed8..0000000000 --- a/dexs/maverick/maverick.ts +++ /dev/null @@ -1,119 +0,0 @@ -import { CHAIN } from "../../helpers/chains"; -import { ChainBlocks, FetchOptions } from "../../adapters/types"; -const { request, } = require("graphql-request"); - -const info: { [key: string]: any } = { - [CHAIN.ETHEREUM]: { - subgraph: "https://api.thegraph.com/subgraphs/name/maverick-protocol/maverick-mainnet-data", - }, - [CHAIN.ERA]: { - subgraph: - "https://app.zeeve.io/shared-api/subgraph/query/query-node-0/50ad2beaefaac4b1eda15839c3eac8259d0759b7d4ae1002/subgraphs/name/zksync", - }, - [CHAIN.BSC]: { - subgraph: - "https://api.thegraph.com/subgraphs/name/maverick-protocol/maverick-bnb-app", - }, - [CHAIN.BASE]: { - subgraph: - "https://api.studio.thegraph.com/query/42519/maverick-base/version/latest", - }, -}; - -const getData = async ({ chain, createBalances, startOfDay }: FetchOptions) => { - const dailyFees = createBalances(); - const totalFees = createBalances(); - const dailyUserFees = createBalances(); - const totalUserFees = createBalances(); - const dailyVolume = createBalances(); - const totalVolume = createBalances(); - - let returnCount = 1000; - let step = 0; - while (returnCount == 1000) { - const graphQL = `{ - poolDayStats( - orderBy: id - orderDirection: desc - first: 1000 - skip: ${step * 1000} - where: {timestamp: "${startOfDay}"} - ) { - id - pool { - id - tokenB { - id - decimals - } - tokenA { - id - decimals - } - tokenAVolume - tokenBVolume - fee - } - tokenAVolume - tokenBVolume - timestamp - } - }`; - - const data = await request(info[chain].subgraph, graphQL); - returnCount = data.poolDayStats.length; - step++; - - for (const dailyData of data.poolDayStats) { - const tokenAId = dailyData.pool.tokenA.id; - const tokenBId = dailyData.pool.tokenB.id; - const multiplierA = 10 ** dailyData.pool.tokenA.decimals; - const multiplierB = 10 ** dailyData.pool.tokenB.decimals; - dailyVolume.add(tokenAId, dailyData.tokenAVolume * multiplierA); - dailyVolume.add(tokenBId, dailyData.tokenBVolume * multiplierB); - dailyFees.add(tokenAId, dailyData.tokenAVolume * multiplierA * dailyData.pool.fee); - dailyFees.add(tokenBId, dailyData.tokenBVolume * multiplierB * dailyData.pool.fee); - - totalVolume.add(tokenAId, dailyData.pool.tokenAVolume * multiplierA); - totalVolume.add(tokenBId, dailyData.pool.tokenBVolume * multiplierB); - totalFees.add(tokenAId, dailyData.pool.tokenAVolume * multiplierA * dailyData.pool.fee); - totalFees.add(tokenBId, dailyData.pool.tokenBVolume * multiplierB * dailyData.pool.fee); - } - } - - return { - dailyFees, - totalFees, - dailyUserFees: dailyFees, - totalUserFees: totalFees, - totalVolume, - dailyVolume, - timestamp: startOfDay, - }; -}; - -export const fetchVolume = (_chain: string) => { - return async (_timestamp: number, _: ChainBlocks, options: FetchOptions) => { - const data = await getData(options); - - return { - // totalVolume: data.totalVolume, - dailyVolume: data.dailyVolume, - timestamp: data.timestamp, - }; - }; -}; - -export const fetchFee = (_chain: string) => { - return async (timestamp: number, _: ChainBlocks, options: FetchOptions) => { - const data = await getData(options); - - return { - timestamp, - dailyFees: data.dailyFees, - // totalFees: data.totalFees, - dailyUserFees: data.dailyUserFees, - // totalUserFees: data.totalUserFees, - }; - }; -}; diff --git a/dexs/merchant-moe/index.ts b/dexs/merchant-moe/index.ts index d0edf02173..e9e050b37f 100644 --- a/dexs/merchant-moe/index.ts +++ b/dexs/merchant-moe/index.ts @@ -1,14 +1,6 @@ -import { SimpleAdapter } from "../../adapters/types"; import { CHAIN } from "../../helpers/chains"; -import { getDexVolumeExports } from "../../helpers/dexVolumeLogs"; +import { uniV2Exports } from "../../helpers/uniswap"; -const FACTORY_ADDRESS = '0x5bef015ca9424a7c07b68490616a4c1f094bedec' -const adapters: SimpleAdapter = { - adapter: { - [CHAIN.MANTLE]: { - fetch: getDexVolumeExports({ chain: CHAIN.MANTLE, factory: FACTORY_ADDRESS }), - start: 1706745600, - } - } -} -export default adapters; +export default uniV2Exports({ + [CHAIN.MANTLE]: { factory: '0x5bef015ca9424a7c07b68490616a4c1f094bedec', }, +}) diff --git a/dexs/merlinswap/index.ts b/dexs/merlinswap/index.ts new file mode 100644 index 0000000000..db8307752c --- /dev/null +++ b/dexs/merlinswap/index.ts @@ -0,0 +1,73 @@ +import fetchURL from "../../utils/fetchURL" +import { Chain } from "@defillama/sdk/build/general"; +import { FetchOptions, FetchResultVolume, SimpleAdapter } from "../../adapters/types"; +import customBackfill from "../../helpers/customBackfill"; +import { CHAIN } from "../../helpers/chains"; +import { getUniqStartOfTodayTimestamp } from "../../helpers/getUniSubgraphVolume"; + + +const historicalVolumeEndpoint = (chain_id: number, page: number) => `https://api-dass.izumi.finance/api/v1/izi_swap/summary_record/?chain_id=${chain_id}&type=4&page_size=100000&page=${page}` + +interface IVolumeall { + volDay: number; + chainId: number; + timestamp: number; +} +type TChains = { + [k: Chain | string]: number; +}; +type TAdapter = { + [key:string]: any; +}; + +const chains: TChains = { + [CHAIN.MERLIN]: 4200, +}; + +const fetch = async (options: FetchOptions): Promise => { + const dayTimestamp = getUniqStartOfTodayTimestamp(new Date(options.endTimestamp * 1000)) + let isSuccess = true; + let page = 1; + const historical: IVolumeall[] = []; + while (isSuccess) { + const response = (await fetchURL(historicalVolumeEndpoint(chains[options.chain], page))); + if (response.is_success){ + Array.prototype.push.apply(historical, response.data); + page += 1; + } else { + isSuccess = false; + }; + }; + const historicalVolume = historical.filter(e => e.chainId === chains[options.chain]); + const totalVolume = historicalVolume + .filter(volItem => (new Date(volItem.timestamp).getTime()) <= dayTimestamp) + .reduce((acc, { volDay }) => acc + Number(volDay), 0) + + const dailyVolume = historicalVolume + .find(dayItem => (new Date(dayItem.timestamp).getTime()) === dayTimestamp)?.volDay + + return { + totalVolume: `${totalVolume}`, + dailyVolume: dailyVolume ? `${dailyVolume}` : undefined, + timestamp: dayTimestamp, + }; +} + +const adapters: TAdapter = {}; +for (const chain in chains) { + let startTime = 1706946000; + if (chains.hasOwnProperty(chain)) { + adapters[chain] = { + fetch: fetch, + start: startTime, + customBackfill: customBackfill(chain, () => fetch) + }; + }; +}; + +const adapter: SimpleAdapter = { + adapter: adapters, + version: 2, +}; + +export default adapter; diff --git a/dexs/metavault-derivatives-v2/index.ts b/dexs/metavault-derivatives-v2/index.ts index edcacf3514..2741ed774f 100644 --- a/dexs/metavault-derivatives-v2/index.ts +++ b/dexs/metavault-derivatives-v2/index.ts @@ -1,9 +1,21 @@ -import { SimpleAdapter, FetchResultVolume } from "../../adapters/types"; +import * as sdk from "@defillama/sdk"; +import { + SimpleAdapter, + FetchResultVolume, + ChainEndpoints, +} from "../../adapters/types"; import { CHAIN } from "../../helpers/chains"; import { getTimestampAtStartOfDayUTC } from "../../utils/date"; import { Chain } from "@defillama/sdk/build/general"; import request, { gql } from "graphql-request"; +const endpoints: ChainEndpoints = { + [CHAIN.LINEA]: + "https://api.studio.thegraph.com/query/55804/linea-trade/version/latest", + [CHAIN.POLYGON]: + sdk.graph.modifyEndpoint('GAvL1WKMAVDdnSk96qvmSCMwL6pxfhAVYkQw6AgZU3td'), +}; + interface IReferralRecord { volume: string; // Assuming volume is a string that represents a number timestamp: number; @@ -15,7 +27,7 @@ interface IVolumeStat { id: string; } -const fetch = () => { +const fetch = (endpoint) => { return async (timestamp: number): Promise => { const todaysTimestamp = getTimestampAtStartOfDayUTC(timestamp); @@ -29,8 +41,6 @@ const fetch = () => { } `; - const endpoint = - "https://linea-graph-node.metavault.trade/subgraphs/name/metavault/perpv1"; const response = await request(endpoint, graphQuery); const volumeStats: IVolumeStat[] = response.volumeStats; @@ -57,8 +67,15 @@ const methodology = { const adapter: SimpleAdapter = { adapter: { [CHAIN.LINEA]: { - fetch: fetch(), - start: 1701950449, + fetch: fetch(endpoints[CHAIN.LINEA]), + start: 1709251200, + meta: { + methodology, + }, + }, + [CHAIN.POLYGON]: { + fetch: fetch(endpoints[CHAIN.POLYGON]), + start: 1709251200, meta: { methodology, }, diff --git a/dexs/metavault-v3/index.ts b/dexs/metavault-v3/index.ts index b6dd42a8c2..6de3304703 100644 --- a/dexs/metavault-v3/index.ts +++ b/dexs/metavault-v3/index.ts @@ -1,24 +1,19 @@ import { Chain } from "@defillama/sdk/build/general"; import { CHAIN } from "../../helpers/chains"; -import { getGraphDimensions } from "../../helpers/getUniSubgraph"; +import { getGraphDimensions2 } from "../../helpers/getUniSubgraph"; import { BreakdownAdapter } from "../../adapters/types"; const endpointsV3 = { - [CHAIN.LINEA]: - "https://linea-graph-node.metavault.trade/subgraphs/name/metavault/v3", + // [CHAIN.LINEA]: "https://linea-graph-node.metavault.trade/subgraphs/name/metavault/v3", [CHAIN.SCROLL]: "https://api.studio.thegraph.com/query/55804/metavault-v3/version/latest", }; -const v3Graphs = getGraphDimensions({ +const v3Graphs = getGraphDimensions2({ graphUrls: endpointsV3, totalVolume: { factory: "factories", field: "totalVolumeUSD", }, - dailyVolume: { - factory: "uniswapDayData", - field: "volumeUSD", - }, feesPercent: { type: "fees", ProtocolRevenue: 0, @@ -57,6 +52,7 @@ const v3 = Object.keys(endpointsV3).reduce( ); const adapter: BreakdownAdapter = { + version: 2, breakdown: { v3: v3, }, diff --git a/dexs/metavault.trade/index.ts b/dexs/metavault.trade/index.ts index 943a9fcc34..e2c0061d10 100644 --- a/dexs/metavault.trade/index.ts +++ b/dexs/metavault.trade/index.ts @@ -1,10 +1,11 @@ +import * as sdk from "@defillama/sdk"; import request, { gql } from "graphql-request"; import { BreakdownAdapter, Fetch, SimpleAdapter } from "../../adapters/types"; import { CHAIN } from "../../helpers/chains"; import { getUniqStartOfTodayTimestamp } from "../../helpers/getUniSubgraphVolume"; const endpoints: { [key: string]: string } = { - [CHAIN.POLYGON]: "https://api.thegraph.com/subgraphs/name/sdcrypt0/metavault-mvx-subgraph", + [CHAIN.POLYGON]: sdk.graph.modifyEndpoint('BMn9XsegbLxw9TL6uyw5NntoiGRyMqRpF2vShkKzusJ3'), } const historicalData = gql` diff --git a/dexs/meteora/index.ts b/dexs/meteora/index.ts new file mode 100644 index 0000000000..82f0694c05 --- /dev/null +++ b/dexs/meteora/index.ts @@ -0,0 +1,56 @@ +import { CHAIN } from '../../helpers/chains'; +import { httpGet } from '../../utils/fetchURL'; + +const meteoraStatsEndpoint = 'https://amm-v2.meteora.ag/pools/v2'; + +interface Stats24H { + dailyVolume: number + timestamp: number +}; + +interface Pool { + total_count: number + data: Array<{ + trading_volume: number + }> +} + +async function fetch(timestamp: number): Promise { + let dailyVolume = 0; + let page = 0; + try { + // while (true) { + const url = `${meteoraStatsEndpoint}?page=${page}&size=100000`; + const response:Pool = (await httpGet(url)); + response.data.forEach(pool => { + dailyVolume += pool.trading_volume; + }) + // if (response.data.length < 500) { + // break; + // } + // if (page > 50) break; + page++; + // } + return { + dailyVolume: dailyVolume, + timestamp: timestamp + } + } catch (error) { + return { + dailyVolume: dailyVolume, + timestamp: timestamp + } + } + +} + +export default { + version: 2, + adapter: { + [CHAIN.SOLANA]: { + fetch: fetch, + runAtCurrTime: true, + start: 1714435200, // Apr 30 2024 - 00:00:00 UTC + } + } +} diff --git a/dexs/metropolis/index.ts b/dexs/metropolis/index.ts index 3f24a1dd6b..754565adde 100644 --- a/dexs/metropolis/index.ts +++ b/dexs/metropolis/index.ts @@ -1,10 +1,11 @@ +import * as sdk from "@defillama/sdk"; import { univ2Adapter } from "../../helpers/getUniSubgraphVolume"; import { CHAIN } from "../../helpers/chains"; import disabledAdapter from "../../helpers/disabledAdapter"; import { DISABLED_ADAPTER_KEY } from "../../adapters/types"; const endpoints = { - [CHAIN.FANTOM]: "https://api.thegraph.com/subgraphs/name/0xhans1/metropolis-v2", + [CHAIN.FANTOM]: sdk.graph.modifyEndpoint('C9pjtfL9qqoHoCbLenWiztCBdT2YoG6rk3bHLaCMBS3H'), }; const adapter = univ2Adapter(endpoints, { diff --git a/dexs/miaswap/index.ts b/dexs/miaswap/index.ts index 335f43b31a..f74942a9eb 100644 --- a/dexs/miaswap/index.ts +++ b/dexs/miaswap/index.ts @@ -1,27 +1,18 @@ -import { SimpleAdapter } from "../../adapters/types"; +import { DISABLED_ADAPTER_KEY, SimpleAdapter } from "../../adapters/types"; import { CHAIN } from "../../helpers/chains"; -import { DEFAULT_TOTAL_VOLUME_FIELD, getGraphDimensions } from "../../helpers/getUniSubgraph"; +import disabledAdapter from "../../helpers/disabledAdapter"; +import { DEFAULT_TOTAL_VOLUME_FIELD, getGraphDimensions2 } from "../../helpers/getUniSubgraph"; const v3Endpoints = { [CHAIN.ONUS]: "https://subgraph.onuschain.io/subgraphs/name/onus/miaswap-v3-subgraph" } -const VOLUME_USD = "volumeUSD"; - -const v3Graphs = getGraphDimensions({ +const v3Graphs = getGraphDimensions2({ graphUrls: v3Endpoints, totalVolume: { factory: "factories", field: DEFAULT_TOTAL_VOLUME_FIELD, }, - dailyVolume: { - factory: "uniswapDayData", - field: VOLUME_USD, - }, - dailyFees: { - factory: "uniswapDayData", - field: "feesUSD", - }, feesPercent: { type: "fees", ProtocolRevenue: 0, @@ -34,9 +25,11 @@ const v3Graphs = getGraphDimensions({ }); const adapter: SimpleAdapter = { + version: 2, adapter: { + [DISABLED_ADAPTER_KEY]: disabledAdapter, [CHAIN.ONUS]: { - fetch: v3Graphs(CHAIN.ONUS), + fetch: async (timestamp: number) => { return { timestamp } }, start: 1685577600, }, }, diff --git a/dexs/mimo/index.ts b/dexs/mimo/index.ts index b0a49e34b1..8d1096c1f0 100644 --- a/dexs/mimo/index.ts +++ b/dexs/mimo/index.ts @@ -1,29 +1,23 @@ import { Chain } from "@defillama/sdk/build/general"; import { SimpleAdapter } from "../../adapters/types"; import { CHAIN } from "../../helpers/chains"; +import { getChainVolume2 } from "../../helpers/getUniSubgraphVolume"; -const { - getChainVolume, -} = require("../../helpers/getUniSubgraphVolume"); const endpoints = { [CHAIN.IOTEX]: "https://graph.mimo.exchange/subgraphs/name/mimo/mainnet" }; -const graphs = getChainVolume({ +const graphs = getChainVolume2({ graphUrls: endpoints, totalVolume: { factory: "uniswapFactories", field: "totalVolumeUSD", }, - dailyVolume: { - factory: "uniswapDayData", - field: "dailyVolumeUSD", - dateField: "date" - } }); const adapter: SimpleAdapter = { + version: 2, adapter: Object.keys(endpoints).reduce((acc, chain: any) => { return { ...acc, diff --git a/dexs/mistswap/index.ts b/dexs/mistswap/index.ts index 4d34cc45de..3bb77674b4 100644 --- a/dexs/mistswap/index.ts +++ b/dexs/mistswap/index.ts @@ -14,5 +14,6 @@ const adapters = univ2Adapter({ }); adapters.adapter.smartbch.start = 1633220803; +adapters.adapter.smartbch.fetch = async (timestamp: number) => { return { timestamp } }; adapters.adapter[DISABLED_ADAPTER_KEY] = disabledAdapter; export default adapters; diff --git a/dexs/mm-finance-arbitrum/index.ts b/dexs/mm-finance-arbitrum/index.ts index fe45da6eea..d886400e61 100644 --- a/dexs/mm-finance-arbitrum/index.ts +++ b/dexs/mm-finance-arbitrum/index.ts @@ -1,8 +1,9 @@ +import * as sdk from "@defillama/sdk"; import { univ2Adapter } from "../../helpers/getUniSubgraphVolume"; import { CHAIN } from "../../helpers/chains"; const endpoints = { - [CHAIN.ARBITRUM]: "https://api.thegraph.com/subgraphs/name/polymmfinance/arbitrum-exchange", + [CHAIN.ARBITRUM]: sdk.graph.modifyEndpoint('7DHMSRfftzCDjRVYSGTt65PagbTF61ACg4XUCP7JQKJG'), }; const adapter = univ2Adapter(endpoints, { diff --git a/dexs/mm-stableswap-polygon/index.ts b/dexs/mm-stableswap-polygon/index.ts index 424c0a8bfd..400f46be1d 100644 --- a/dexs/mm-stableswap-polygon/index.ts +++ b/dexs/mm-stableswap-polygon/index.ts @@ -1,8 +1,9 @@ -import { univ2Adapter } from "../../helpers/getUniSubgraphVolume"; +import * as sdk from "@defillama/sdk"; +import { univ2Adapter2 } from "../../helpers/getUniSubgraphVolume"; import { CHAIN } from "../../helpers/chains"; -export default univ2Adapter({ - [CHAIN.POLYGON]: "https://api.thegraph.com/subgraphs/name/polymmfinance/exchang" +export default univ2Adapter2({ + [CHAIN.POLYGON]: sdk.graph.modifyEndpoint('HTJcrXUUtrVFKyNHZH99ywRx3TQm5ChSFVbn3oBiqGq6') }, { factoriesName: "pancakeFactories", dayData: "pancakeDayData" diff --git a/dexs/mobius-money/index.ts b/dexs/mobius-money/index.ts index 62716277cb..2bcd8cfb4e 100644 --- a/dexs/mobius-money/index.ts +++ b/dexs/mobius-money/index.ts @@ -1,32 +1,26 @@ +import * as sdk from "@defillama/sdk"; import { SimpleAdapter } from "../../adapters/types"; -import { getChainVolume } from "../../helpers/getUniSubgraphVolume"; +import { getChainVolume2 } from "../../helpers/getUniSubgraphVolume"; import { CHAIN } from "../../helpers/chains"; -import { Chain } from "@defillama/sdk/build/general"; -import customBackfill from "../../helpers/customBackfill"; const endpoints = { - [CHAIN.CELO]: "https://api.thegraph.com/subgraphs/name/d-mooers/mobius", + [CHAIN.CELO]: sdk.graph.modifyEndpoint('CcSNm5hBSGYk3WT1faPGDKBxHCdHkyyXYFujHC9DPtmY'), }; -const graphs = getChainVolume({ +const graphs = getChainVolume2({ graphUrls: endpoints, totalVolume: { factory: "tradeVolumes", field: "volume", }, - dailyVolume: { - factory: "dailyVolume", - field: "volume", - dateField: "timestamp" - }, }); const adapter: SimpleAdapter = { + version: 2, adapter: { [CHAIN.CELO]: { fetch: graphs(CHAIN.CELO), start: 1636514733, - // customBackfill: customBackfill(CHAIN.CELO as Chain, graphs) }, }, }; diff --git a/dexs/monocerus/index.ts b/dexs/monocerus/index.ts index 3d5e9b6420..aa384432b1 100644 --- a/dexs/monocerus/index.ts +++ b/dexs/monocerus/index.ts @@ -1,45 +1,6 @@ -import { Adapter, DISABLED_ADAPTER_KEY } from "../../adapters/types"; -import { CHAIN } from "../../helpers/chains"; -import disabledAdapter from "../../helpers/disabledAdapter"; -import { getGraphDimensions } from "../../helpers/getUniSubgraph"; +import { uniV3Exports } from "../../helpers/uniswap"; -const endpoints = { - [CHAIN.MANTA]: "https://api.goldsky.com/api/public/project_clpm9wvhralny01szb1oa4pue/subgraphs/monocerus/1.2.0/gn" -}; - -const v3Graphs = getGraphDimensions({ - graphUrls: endpoints, - totalVolume: { - factory: "factories", - field: "totalVolumeUSD", - }, - dailyVolume: { - factory: "uniswapDayData", - field: "volumeUSD", - dateField: "date" - }, - dailyFees: { - factory: "uniswapDayData", - field: "feesUSD", - }, - feesPercent: { - type: "fees", - ProtocolRevenue: 0, - HoldersRevenue: 0, - UserFees: 100, // User fees are 0% of collected fees - SupplySideRevenue: 100, // 100% of fees are going to LPs - Revenue: 0 // Revenue is 0% of collected fees - } -}); - -const adapter: Adapter = { - adapter: { - [DISABLED_ADAPTER_KEY]: disabledAdapter, - [CHAIN.MANTA]: { - fetch: v3Graphs(CHAIN.MANTA), - start: 1703548800 - } - } -}; - -export default adapter; +export default uniV3Exports({ + avax: { factory: "0x8d312c2B300239B84c304B5af5A3D00cBF0803F6", }, + manta: { factory: "0x481F4b658d1447A9559B220640Fb79C2B993032A", }, +}) diff --git a/dexs/mooniswap/index.ts b/dexs/mooniswap/index.ts index 9eda0ad558..c8db6fc681 100644 --- a/dexs/mooniswap/index.ts +++ b/dexs/mooniswap/index.ts @@ -1,16 +1,14 @@ import { SimpleAdapter } from "../../adapters/types"; import { ETHEREUM } from "../../helpers/chains"; import { getStartTimestamp } from "../../helpers/getStartTimestamp"; -import { DEFAULT_DAILY_VOLUME_FIELD, DEFAULT_TOTAL_VOLUME_FIELD, getChainVolume } from "../../helpers/getUniSubgraphVolume"; +import { DEFAULT_TOTAL_VOLUME_FIELD, getChainVolume2 } from "../../helpers/getUniSubgraphVolume"; const endpoints = { [ETHEREUM]: "https://api.thegraph.com/subgraphs/name/1inch-exchange/oneinch-liquidity-protocol-v2", }; -const dailyDataFactory = "mooniswapDayData"; - -const graphs = getChainVolume({ +const graphs = getChainVolume2({ graphUrls: { [ETHEREUM]: endpoints[ETHEREUM], }, @@ -18,20 +16,17 @@ const graphs = getChainVolume({ factory: "mooniswapFactories", field: DEFAULT_TOTAL_VOLUME_FIELD, }, - dailyVolume: { - factory: dailyDataFactory, - field: DEFAULT_DAILY_VOLUME_FIELD, - }, }); const adapter: SimpleAdapter = { + version: 2, adapter: { [ETHEREUM]: { fetch: graphs(ETHEREUM), start: getStartTimestamp({ endpoints, chain: ETHEREUM, - dailyDataField: `${dailyDataFactory}s`, + dailyDataField: `mooniswapDayDatas`, }), }, }, diff --git a/dexs/morpheus-swap/index.ts b/dexs/morpheus-swap/index.ts index 6e2145f448..fe9e2b7603 100644 --- a/dexs/morpheus-swap/index.ts +++ b/dexs/morpheus-swap/index.ts @@ -1,8 +1,9 @@ +import * as sdk from "@defillama/sdk"; import { CHAIN } from "../../helpers/chains"; import { univ2Adapter } from "../../helpers/getUniSubgraphVolume"; const adapters = univ2Adapter({ - [CHAIN.FANTOM]: "https://api.thegraph.com/subgraphs/name/daedboi/morpheus-swap" + [CHAIN.FANTOM]: sdk.graph.modifyEndpoint('C5XUzYLrDHiiKL7zGjLLyiQueJkQfeUyMZCcgwnVWcNr') }, { factoriesName: "pancakeFactories", dayData: "pancakeDayData", diff --git a/dexs/morphex-old/index.ts b/dexs/morphex-old/index.ts index 147ea673fb..7567b3a163 100644 --- a/dexs/morphex-old/index.ts +++ b/dexs/morphex-old/index.ts @@ -1,3 +1,4 @@ +import * as sdk from "@defillama/sdk"; import request, { gql } from "graphql-request"; import { BreakdownAdapter, DISABLED_ADAPTER_KEY, Fetch } from "../../adapters/types"; import { CHAIN } from "../../helpers/chains"; @@ -6,7 +7,7 @@ import disabledAdapter from "../../helpers/disabledAdapter"; const endpoints: { [key: string]: string } = { [CHAIN.FANTOM]: - "https://api.thegraph.com/subgraphs/name/morphex-labs/morphex-fantom-stats", + sdk.graph.modifyEndpoint('EH6ZfhnYQd7Kv1SdnUAp96vMUWKCTfPrctwududH5cmG'), }; const historicalDataSwap = gql` diff --git a/dexs/morphex/index.ts b/dexs/morphex/index.ts index 6e14a4b88b..650e1f7d59 100644 --- a/dexs/morphex/index.ts +++ b/dexs/morphex/index.ts @@ -1,3 +1,4 @@ +import * as sdk from "@defillama/sdk"; import request, { gql } from "graphql-request"; import { BreakdownAdapter, Fetch } from "../../adapters/types"; import { CHAIN } from "../../helpers/chains"; @@ -5,9 +6,9 @@ import { getUniqStartOfTodayTimestamp } from "../../helpers/getUniSubgraphVolume const endpoints: { [key: string]: string } = { [CHAIN.FANTOM]: - "https://api.thegraph.com/subgraphs/name/morphex-labs/morphex-fantom-stats-new", + sdk.graph.modifyEndpoint('6GjHurahqYLUUYkqfCgrWfcH2pfTEFPtPvCPvQ1BHLed'), [CHAIN.BSC]: - "https://api.thegraph.com/subgraphs/name/morphex-labs/morphex-bsc-stats", + sdk.graph.modifyEndpoint('4Zdyx9D4oYLGSm1C26jpTU7Ho7ecswEuTPg3WANGkMTx'), }; const historicalDataSwap = gql` diff --git a/dexs/mu-exchange/index.ts b/dexs/mu-exchange/index.ts index 9d57e03418..9f56912769 100644 --- a/dexs/mu-exchange/index.ts +++ b/dexs/mu-exchange/index.ts @@ -1,3 +1,4 @@ +import * as sdk from "@defillama/sdk"; import request, { gql } from 'graphql-request'; import { Fetch, SimpleAdapter } from '../../adapters/types'; import { CHAIN } from '../../helpers/chains'; @@ -6,7 +7,7 @@ import { } from '../../helpers/getUniSubgraphVolume'; const ENDPOINTS: { [key: string]: string } = { - [CHAIN.XDAI]: 'https://api.thegraph.com/subgraphs/name/bryant11112/mu-beta', + [CHAIN.XDAI]: sdk.graph.modifyEndpoint('7LkMoW2UtUVauMkexF75bowQp2DE6bNB3jUXySYtBp9x'), }; const SDAI_DECIMALS: { [key: string]: number } = { [CHAIN.XDAI]: 18, diff --git a/dexs/muesliswap/index.ts b/dexs/muesliswap/index.ts index 77f0de4336..344ad12fc6 100644 --- a/dexs/muesliswap/index.ts +++ b/dexs/muesliswap/index.ts @@ -10,17 +10,17 @@ interface IVolumeall { const historicalVolumeEndpoint = "https://analyticsv3.muesliswap.com/historical-volume"; -const fetch = async (timestamp: number, _: ChainBlocks, { startOfDay, createBalances, }: FetchOptions) => { - const dailyVolume = createBalances(); - const totalVolume = createBalances(); +const fetch = async (options: FetchOptions) => { + const dailyVolume = options.createBalances(); + const totalVolume = options.createBalances(); const vols: IVolumeall[] = (await httpGet(historicalVolumeEndpoint)); vols - .filter((volItem: IVolumeall) => Number(volItem.time) <= startOfDay) + .filter((volItem: IVolumeall) => Number(volItem.time) <= options.startOfDay) .map(({ volume }) => totalVolume.addGasToken(volume)); - dailyVolume.addGasToken(vols.find(dayItem => dayItem.time === startOfDay)?.volume) + dailyVolume.addGasToken(vols.find(dayItem => dayItem.time === options.startOfDay)?.volume) return { - timestamp: startOfDay, + timestamp: options.startOfDay, dailyVolume, // totalVolume, } diff --git a/dexs/mummy-finance/index.ts b/dexs/mummy-finance/index.ts index 51ebd2f824..62cb66799f 100644 --- a/dexs/mummy-finance/index.ts +++ b/dexs/mummy-finance/index.ts @@ -1,3 +1,4 @@ +import * as sdk from "@defillama/sdk"; import request, { gql } from "graphql-request"; import { Fetch, SimpleAdapter } from "../../adapters/types"; import { CHAIN } from "../../helpers/chains"; @@ -5,8 +6,8 @@ import { getUniqStartOfTodayTimestamp } from "../../helpers/getUniSubgraphVolume import customBackfill from "../../helpers/customBackfill"; const endpoints: { [key: string]: string } = { - [CHAIN.FANTOM]: "https://api.thegraph.com/subgraphs/name/mummyfinance/fantom-stats-v2", - [CHAIN.OPTIMISM]: "https://api.thegraph.com/subgraphs/name/mummyfinance/op-stats", + [CHAIN.FANTOM]: sdk.graph.modifyEndpoint('8LdLE9Aan39FQCcHX3x1HdnNzoZzPvxskhj1utLb2SA9'), + [CHAIN.OPTIMISM]: sdk.graph.modifyEndpoint('6dZD4zDx9bGZfRdgoUBsZjWBygYVXAe4G41LjTLNJWk1'), } const historicalDataSwap = gql` diff --git a/dexs/mute.io/index.ts b/dexs/mute.io/index.ts index 2ef992c945..e9832a49c1 100644 --- a/dexs/mute.io/index.ts +++ b/dexs/mute.io/index.ts @@ -2,7 +2,7 @@ import { univ2Adapter } from "../../helpers/getUniSubgraphVolume"; import { CHAIN } from "../../helpers/chains"; const endpoints = { - [CHAIN.ERA]: "https://api.studio.thegraph.com/query/12332/muteswitch---zksync-era/v0.0.5", + [CHAIN.ERA]: "https://api.goldsky.com/api/public/project_clmtie4nnezuh2nw6hhjg6mo7/subgraphs/mute_switch/v0.0.7/gn", }; const adapter = univ2Adapter(endpoints, { @@ -15,4 +15,4 @@ const adapter = univ2Adapter(endpoints, { adapter.adapter.era.start = 1679529600 -export default adapter +export default adapter \ No newline at end of file diff --git a/dexs/mux-protocol/index.ts b/dexs/mux-protocol/index.ts index 600409987b..a02b364ad5 100644 --- a/dexs/mux-protocol/index.ts +++ b/dexs/mux-protocol/index.ts @@ -1,11 +1,11 @@ import type { BreakdownAdapter, ChainBlocks, FetchOptions, SimpleAdapter } from "../../adapters/types"; import { CHAIN } from "../../helpers/chains"; -import { adapteragges } from "./agge"; +import { adapteragges } from "./agge"; type TChainAddress = { [chain: string]: string; } -const contract_address: TChainAddress = { +const contract_address: TChainAddress = { [CHAIN.ARBITRUM]: "0x3e0199792ce69dc29a0a36146bfa68bd7c8d6633", [CHAIN.BSC]: "0x855e99f768fad76dd0d3eb7c446c0b759c96d520", [CHAIN.AVAX]: "0x0ba2e492e8427fad51692ee8958ebf936bee1d84", @@ -13,45 +13,37 @@ const contract_address: TChainAddress = { [CHAIN.FANTOM]: "0x2e81f443a11a943196c88afcb5a0d807721a88e6", } -const fetchVolume = async (timestamp: number, _: ChainBlocks, { createBalances, getLogs, chain, api }: FetchOptions) => { +const fetchVolume = async (timestamp: number, _: ChainBlocks, { createBalances, getLogs, chain, }: FetchOptions) => { const dailyVolume = createBalances(); - const logs_openposition = await getLogs({ - target: contract_address[chain], - topics: ["0xdb27855d3e94a6c985e1e59c77870a73484ef3c40d29fbfe14bb3e686da86efb"], - }); - const logs_closeposition = await getLogs({ - target: contract_address[chain], - topics: ["0x645156066afee3ede009256908a9e96538cc1ad681c46b10114f6ce98ebd0600"] - }); - const logs_liqposition = await getLogs({ - target: contract_address[chain], - topics: ["0xd63e21d9ddaf46f8d28d121f06e7ed33fcc0300af1f8c794e69056dbf37e2d6a"] - }); - const hash: string[] = []; + const logs_openposition = await getLogs({ target: contract_address[chain], topics: ["0xdb27855d3e94a6c985e1e59c77870a73484ef3c40d29fbfe14bb3e686da86efb"], }); + const logs_closeposition = await getLogs({ target: contract_address[chain], topics: ["0x645156066afee3ede009256908a9e96538cc1ad681c46b10114f6ce98ebd0600"] }); + const logs_liqposition = await getLogs({ target: contract_address[chain], topics: ["0xd63e21d9ddaf46f8d28d121f06e7ed33fcc0300af1f8c794e69056dbf37e2d6a"] }); + const hash = new Set() logs_openposition.forEach((log) => { - if (hash.includes(log.transactionHash)) return; + if (hash.has(log.transactionHash)) return; const data = log.data.replace('0x', ''); - const amount = Number('0x'+data.slice(3 * 64, 4 * 64)) / 1e18; - const assetPrice = Number('0x'+data.slice(4 * 64, 5 * 64)) / 1e18; + const amount = Number('0x' + data.slice(3 * 64, 4 * 64)) / 1e18; + const assetPrice = Number('0x' + data.slice(4 * 64, 5 * 64)) / 1e18; dailyVolume.addCGToken('tether', amount * assetPrice); - hash.push(log.transactionHash); + hash.add(log.transactionHash); }); logs_closeposition.forEach((log) => { - if (hash.includes(log.transactionHash)) return; + if (hash.has(log.transactionHash)) return; const data = log.data.replace('0x', ''); - const amount = Number('0x'+data.slice(4 * 64, 5 * 64)) / 1e18; - const assetPrice = Number('0x'+data.slice(5 * 64, 6 * 64)) / 1e18; + const amount = Number('0x' + data.slice(4 * 64, 5 * 64)) / 1e18; + const assetPrice = Number('0x' + data.slice(5 * 64, 6 * 64)) / 1e18; dailyVolume.addCGToken('tether', amount * assetPrice); - hash.push(log.transactionHash); + hash.add(log.transactionHash); }); logs_liqposition.forEach((log) => { - if (hash.includes(log.transactionHash)) return; + if (hash.has(log.transactionHash)) return; const data = log.data.replace('0x', ''); - const amount = Number('0x'+data.slice(4 * 64, 5 * 64)) / 1e18; - const assetPrice = Number('0x'+data.slice(5 * 64, 6 * 64)) / 1e18; + const amount = Number('0x' + data.slice(4 * 64, 5 * 64)) / 1e18; + const assetPrice = Number('0x' + data.slice(5 * 64, 6 * 64)) / 1e18; dailyVolume.addCGToken('tether', amount * assetPrice); }); + return { dailyVolume, timestamp, diff --git a/dexs/myswap-cl/index.ts b/dexs/myswap-cl/index.ts new file mode 100644 index 0000000000..96a95e22d3 --- /dev/null +++ b/dexs/myswap-cl/index.ts @@ -0,0 +1,27 @@ +import { SimpleAdapter } from "../../adapters/types"; +import { CHAIN } from "../../helpers/chains"; +import fetchURL from "../../utils/fetchURL"; + +type VolumeResponse = { timestamp: number; volume: number }; +const fetch = async (timestamp: number) => { + const response = (await fetchURL( + "https://myswap-cl-charts.s3.amazonaws.com/data/total_volume.json" + )) as VolumeResponse[]; + return { + timestamp: timestamp, + dailyVolume: response[response.length - 1].volume, + }; +}; + +const adapter: SimpleAdapter = { + version: 2, + adapter: { + [CHAIN.STARKNET]: { + fetch: fetch, + runAtCurrTime: true, + start: 1695081600, + }, + }, +}; + +export default adapter; diff --git a/dexs/myx-finance/index.ts b/dexs/myx-finance/index.ts new file mode 100644 index 0000000000..e5149c5f39 --- /dev/null +++ b/dexs/myx-finance/index.ts @@ -0,0 +1,59 @@ +import { ChainEndpoints, Fetch, FetchOptions, SimpleAdapter } from "../../adapters/types"; +import { CHAIN } from "../../helpers/chains"; +import { getUniqStartOfTodayTimestamp } from "../../helpers/getUniSubgraphVolume"; +import fetchURL from "../../utils/fetchURL"; + +const endpoints: ChainEndpoints = { + [CHAIN.ARBITRUM]: "https://api-arb.myx.finance/coingecko/contracts", + [CHAIN.LINEA]: "https://api-linea.myx.finance/coingecko/contracts", +} + +const methodology = { + TotalVolume: "Total Volume from the sum of the open/close/liquidation of positions.", + DailyVolume: "Daily Volume from the sum of the open/close/liquidation of positions.", +} + +const getFetch = async (optios: FetchOptions) => { + const result = await fetchURL(endpoints[optios.chain]) + + const dayTimestamp = getUniqStartOfTodayTimestamp(new Date((optios.endTimestamp * 1000))) + + + const volume = result.data.reduce((acc, item) => { + return acc + (item?.target_volume || 0) + }, 0) + + console.log({ + timestamp: dayTimestamp, + dailyVolume: volume || "0", + }) + + return { + timestamp: dayTimestamp, + dailyVolume: volume || "0", + } +} + + +const startTimestamps: { [chain: string]: number } = { + [CHAIN.ARBITRUM]: 1706659200, + [CHAIN.LINEA]: 1708473600, +} + +const adapter: SimpleAdapter = { + version: 2, + adapter: Object.keys(endpoints).reduce((acc, chain) => { + return { + ...acc, + [chain]: { + fetch: getFetch, + start: startTimestamps[chain], + meta: { + methodology: methodology, + }, + } + } + }, {}) +} + +export default adapter; diff --git a/dexs/native/index.ts b/dexs/native/index.ts index a845d16ad8..10c74b7a52 100644 --- a/dexs/native/index.ts +++ b/dexs/native/index.ts @@ -10,10 +10,12 @@ const chains = [ CHAIN.ARBITRUM, CHAIN.AVAX, CHAIN.MANTLE, + CHAIN.BASE, + CHAIN.ZETA ]; const NATIVE_ANALYTICS_ENDPOINT = - "http://chain-monitoring.native.org/analytics/overview"; + "https://newapi.native.org/native-offchain-monitor-mono/analytics/overview"; interface ResEntry { date: number; diff --git a/dexs/nearpad/index.ts b/dexs/nearpad/index.ts index 6927d857ab..5e6489c0b7 100644 --- a/dexs/nearpad/index.ts +++ b/dexs/nearpad/index.ts @@ -1,26 +1,6 @@ -import { SimpleAdapter } from "../../adapters/types" -import { CHAIN } from "../../helpers/chains" -import { getDexVolumeExports } from "../../helpers/dexVolumeLogs"; +import { CHAIN } from "../../helpers/chains"; +import { uniV2Exports } from "../../helpers/uniswap"; -const pools: string[] = [ - '0xc374776cf5c497adeef6b505588b00cb298531fd', - '0x73155e476d6b857fe7722aefebad50f9f8bd0b38', - '0x63b4a0538ce8d90876b201af1020d13308a8b253', - '0xa188d79d6bdbc1120a662de9eb72384e238af104', - '0x24886811d2d5e362ff69109aed0a6ee3eeeec00b', - '0xfe28a27a95e51bb2604abd65375411a059371616', - '0x1fd6cbbfc0363aa394bd77fc74f64009bf54a7e9', - '0xb53bc2537e641c37c7b7a8d33aba1b30283cda2f', - '0xaf3f197ce82bf524dab0e9563089d443cb950048', -].map((address: string) => address.toLowerCase()); - -const adapters: SimpleAdapter = { - adapter: { - [CHAIN.AURORA]: { - fetch: getDexVolumeExports({ chain: CHAIN.AURORA, pools }), - start: 1678838400, - } - } -} - -export default adapters +export default uniV2Exports({ + [CHAIN.AURORA]: { factory: '0x34484b4E416f5d4B45D4Add0B6eF6Ca08FcED8f1', }, +}) diff --git a/dexs/nile-exchange-v1/index.ts b/dexs/nile-exchange-v1/index.ts new file mode 100644 index 0000000000..5371233b36 --- /dev/null +++ b/dexs/nile-exchange-v1/index.ts @@ -0,0 +1,6 @@ +import { CHAIN } from "../../helpers/chains"; +import { uniV2Exports } from "../../helpers/uniswap"; + +export default uniV2Exports({ + [CHAIN.LINEA]: { factory: '0xAAA16c016BF556fcD620328f0759252E29b1AB57', }, +}) diff --git a/dexs/nile-exchange/index.ts b/dexs/nile-exchange/index.ts new file mode 100644 index 0000000000..bba81755c5 --- /dev/null +++ b/dexs/nile-exchange/index.ts @@ -0,0 +1,12 @@ +import { CHAIN } from "../../helpers/chains"; +import { univ2Adapter2 } from "../../helpers/getUniSubgraphVolume"; + +const adapters = univ2Adapter2({ + [CHAIN.LINEA]: "https://graph-query.linea.build/subgraphs/name/nileexchange/cl-subgraph" +}, { + factoriesName: "factories", + totalVolume: "totalVolumeUSD", +}); + +adapters.adapter.linea.start = 1705968000; +export default adapters; diff --git a/dexs/nlx/index.ts b/dexs/nlx/index.ts new file mode 100644 index 0000000000..52fcea8525 --- /dev/null +++ b/dexs/nlx/index.ts @@ -0,0 +1,74 @@ +import { BreakdownAdapter, FetchOptions, FetchResultVolume, } from "../../adapters/types"; +import { CHAIN } from "../../helpers/chains"; +import { Chain } from "@defillama/sdk/build/general"; +import { adapter_trade } from './nlx-trade/index' + +interface ILog { + data: string; + transactionHash: string; + topics: string[]; +} + +const topic0_ins = '0x137a44067c8961cd7e1d876f4754a5a3a75989b4552f1843fc69c3b372def160'; +const topic1_ins = '0xf35c99b746450c623be607459294d15f458678f99d535718db6cfcbccb117c09'; + +interface IToken { + amount: number; + token: string; +} + +type TChain = { + [s: Chain | string]: string; +} + +const contract: TChain = { + [CHAIN.CORE]: '0x29792F84224c77e2c672213c4d942fE280D596ef', +} + +const fetch = (chain: Chain) => { + return async ({ getLogs, createBalances, }: FetchOptions): Promise => { + + const dailyVolume = createBalances() + + const swap_logs: ILog[] = (await getLogs({ + target: contract[chain], + topics: [topic0_ins, topic1_ins] + })) as ILog[]; + + const raw_in = swap_logs.map((e: ILog) => { + const data = e.data.replace('0x', ''); + const volume = Number('0x' + data.slice(53 * 64, (53 * 64) + 64)); + const address = data.slice(27 * 64, (27 * 64) + 64); + const contract_address = '0x' + address.slice(24, address.length); + return { + amount: volume, + token: contract_address, + } as IToken + }) + + raw_in.map((e: IToken) => { + dailyVolume.add(e.token, e.amount) + }) + + return { dailyVolume } as any + } +} + + +const adapter: any = { + adapter: { + [CHAIN.CORE]: { + fetch: fetch(CHAIN.CORE), + start: 1713916800, + }, + }, +}; + +const adapters: BreakdownAdapter = { + breakdown: { + "nlx-swap": adapter["adapter"], + "nlx-trade": adapter_trade["adapter"], + }, + version: 2 +} +export default adapters; diff --git a/dexs/gmx-v2/gmx-v2-trade/index.ts b/dexs/nlx/nlx-trade/index.ts similarity index 54% rename from dexs/gmx-v2/gmx-v2-trade/index.ts rename to dexs/nlx/nlx-trade/index.ts index 57796d26a5..7eb76d6950 100644 --- a/dexs/gmx-v2/gmx-v2-trade/index.ts +++ b/dexs/nlx/nlx-trade/index.ts @@ -1,7 +1,5 @@ -import { FetchResultVolume, SimpleAdapter } from "../../../adapters/types"; +import { FetchOptions, } from "../../../adapters/types"; import { CHAIN } from "../../../helpers/chains"; -import * as sdk from "@defillama/sdk"; -import { getBlock } from "../../../helpers/getBlock"; import { Chain } from "@defillama/sdk/build/general"; interface ILog { @@ -16,49 +14,27 @@ const topic1_ins = '0xf94196ccb31f81a3e67df18f2a62cbfb50009c80a7d3c728a3f542e3ab const topic0_des = '0x137a44067c8961cd7e1d876f4754a5a3a75989b4552f1843fc69c3b372def160'; const topic1_des = '0x07d51b51b408d7c62dcc47cc558da5ce6a6e0fd129a427ebce150f52b0e5171a'; -const topic0_fees = '0x137a44067c8961cd7e1d876f4754a5a3a75989b4552f1843fc69c3b372def160'; -const topic1_fees = '0xe096982abd597114bdaa4a60612f87fabfcc7206aa12d61c50e7ba1e6c291100'; - type TChain = { [s: Chain | string]: string; } const contract: TChain = { - [CHAIN.ARBITRUM]: '0xc8ee91a54287db53897056e12d9819156d3822fb', - [CHAIN.AVAX]: '0xdb17b211c34240b014ab6d61d4a31fa0c0e20c26' + [CHAIN.CORE]: '0x29792F84224c77e2c672213c4d942fE280D596ef', } const fetch = (chain: Chain) => { - return async (timestamp: number): Promise => { - const fromTimestamp = timestamp - 60 * 60 * 24 - const toTimestamp = timestamp - const fromBlock = (await getBlock(fromTimestamp, chain, {})); - const toBlock = (await getBlock(toTimestamp, chain, {})); + return async ({ getLogs, }: FetchOptions) => { - const posistion_logs: ILog[] = (await sdk.getEventLogs({ + const posistion_logs: ILog[] = (await getLogs({ target: contract[chain], - toBlock: toBlock, - fromBlock: fromBlock, - chain: chain, topics: [topic0_ins, topic1_ins] })) as ILog[]; - const decress_logs: ILog[] = (await sdk.getEventLogs({ + const decress_logs: ILog[] = (await getLogs({ target: contract[chain], - toBlock: toBlock, - fromBlock: fromBlock, - chain: chain, topics: [topic0_des, topic1_des] })) as ILog[]; - // const fees_logs: ILog[] = (await sdk.getEventLogs({ - // target: contract[chain], - // toBlock: toBlock, - // fromBlock: fromBlock, - // chain: chain, - // topics: [topic0_fees, topic1_fees] - // }))as ILog[]; - let hash: string[] = []; const raw_des = decress_logs.map((e: ILog) => { const data = e.data.replace('0x', ''); @@ -83,7 +59,6 @@ const fetch = (chain: Chain) => { return { dailyVolume: `${dailyVolume}`, - timestamp } } } @@ -91,13 +66,9 @@ const fetch = (chain: Chain) => { const adapter_trade: any = { adapter: { - [CHAIN.ARBITRUM]: { - fetch: fetch(CHAIN.ARBITRUM), - start: 1688428800, - }, - [CHAIN.AVAX]: { - fetch: fetch(CHAIN.AVAX), - start: 1688428800, + [CHAIN.CORE]: { + fetch: fetch(CHAIN.CORE), + start: 1713916800, }, }, }; diff --git a/dexs/nomiswap/index.ts b/dexs/nomiswap/index.ts index 29ed48eba9..922a0c0ab0 100644 --- a/dexs/nomiswap/index.ts +++ b/dexs/nomiswap/index.ts @@ -1,11 +1,10 @@ -import { univ2Adapter } from "../../helpers/getUniSubgraphVolume"; +import * as sdk from "@defillama/sdk"; import { CHAIN } from "../../helpers/chains"; -import { getGraphDimensions } from "../../helpers/getUniSubgraph"; -import { SimpleAdapter } from "../../adapters/types"; -import { time } from "console"; +import { getGraphDimensions2 } from "../../helpers/getUniSubgraph"; +import { FetchOptions, SimpleAdapter } from "../../adapters/types"; const endpoints = { - [CHAIN.BSC]: "https://api.thegraph.com/subgraphs/name/chopachom/nomiswap-subgraph-exchange", + [CHAIN.BSC]: sdk.graph.modifyEndpoint('9ggB4DiKGyXfiS4vh1xqQJMcTQEvxxt715HVm8S3r27G'), }; const VOLUME_FIELD = "dailyVolumeUSD"; @@ -14,25 +13,22 @@ const blacklistTokens = { "0x7f9ad7a5854658d984924e868187b2135514fb88" ] } -const graphsClassic = getGraphDimensions({ +const graphsClassic = getGraphDimensions2({ graphUrls: endpoints, totalVolume: { factory: "nomiswapFactories", field: "totalVolumeUSD", }, - dailyVolume: { - factory: "nomiswapDayData", - field: VOLUME_FIELD, - }, blacklistTokens }); const adapters: SimpleAdapter = { + version: 2, adapter: { [CHAIN.BSC]: { - fetch: async (timestamp: number) => { - const data = await graphsClassic(CHAIN.BSC)(timestamp, {}); - const removeSpike = Number(data.totalVolume) - 2035654137.527446631277942307129497; + fetch: async (options: FetchOptions) => { + const data = await graphsClassic(CHAIN.BSC)(options); + const removeSpike = Number(data.totalVolume) - 7035654137.527446631277942307129497; data.totalVolume = removeSpike > 0 ? removeSpike : data.totalVolume; return { ...data diff --git a/dexs/nostra-pools/index.ts b/dexs/nostra-pools/index.ts new file mode 100644 index 0000000000..0d7eb6257a --- /dev/null +++ b/dexs/nostra-pools/index.ts @@ -0,0 +1,26 @@ +import { CHAIN } from "../../helpers/chains"; +import fetchURL from "../../utils/fetchURL"; +import { SimpleAdapter } from "../../adapters/types"; + +async function fetch() { + const data = await fetchURL("https://api.nostra.finance/query/pool_aprs"); + const dailyVolume = Object.values(data).reduce((acc: number, pool: any) => { + return acc + Number(pool.volume); + }, 0); + + return { + dailyVolume, + }; +} + +const adapter: SimpleAdapter = { + version: 2, + adapter: { + [CHAIN.STARKNET]: { + fetch, + start: async () => 1718236800, + }, + }, +}; + +export default adapter; diff --git a/dexs/nuri-exchange-v1/index.ts b/dexs/nuri-exchange-v1/index.ts new file mode 100644 index 0000000000..48fea63c2b --- /dev/null +++ b/dexs/nuri-exchange-v1/index.ts @@ -0,0 +1,6 @@ +import { CHAIN } from "../../helpers/chains"; +import { uniV2Exports } from "../../helpers/uniswap"; + +export default uniV2Exports({ + [CHAIN.SCROLL]: { factory: '0xAAA16c016BF556fcD620328f0759252E29b1AB57', }, +}) diff --git a/dexs/nuri-exchange-v2/index.ts b/dexs/nuri-exchange-v2/index.ts new file mode 100644 index 0000000000..9c1b644180 --- /dev/null +++ b/dexs/nuri-exchange-v2/index.ts @@ -0,0 +1,5 @@ +import { CHAIN } from '../../helpers/chains' +import { uniV3Exports } from '../../helpers/uniswap' +export default uniV3Exports({ + [CHAIN.SCROLL]: { factory: '0xAAA32926fcE6bE95ea2c51cB4Fcb60836D320C42' } +}) diff --git a/dexs/ociswap/index.ts b/dexs/ociswap/index.ts new file mode 100644 index 0000000000..0cd086c352 --- /dev/null +++ b/dexs/ociswap/index.ts @@ -0,0 +1,55 @@ +import { BreakdownAdapter, FetchResultVolume, SimpleAdapter } from "../../adapters/types" +import { CHAIN } from "../../helpers/chains" +import fetchURL from "../../utils/fetchURL" + +interface PoolStatistics { + pool_type: string; + volume: { + xrd: { + '24h': string; + total: string; + }; + usd: { + '24h': string; + total: string; + }; + }; +} + +const fetchVolume = (poolType: 'basic' | 'precision') => { + return async (timestamp: number): Promise => { + const response: Array = await fetchURL('http://api.ociswap.com/statistics/pool-types'); + + const index = response.findIndex(pool => pool.pool_type === poolType); + + const dailyVolume = Number(response[index].volume.usd["24h"]); + const totalVolume = Number(response[index].volume.usd.total); + + return { + dailyVolume: `${dailyVolume}`, + totalVolume: `${totalVolume}`, + timestamp + }; + }; +}; + +const adapters: BreakdownAdapter = { + version: 2, + breakdown: { + basic: { + [CHAIN.RADIXDLT]: { + fetch: fetchVolume('basic'), + start: 1696118400, + // runAtCurrTime: true + } + }, + precision: { + [CHAIN.RADIXDLT]: { + fetch: fetchVolume('precision'), + start: 1696118400, + // runAtCurrTime: true + } + } + } +} +export default adapters; \ No newline at end of file diff --git a/dexs/okcswap/index.ts b/dexs/okcswap/index.ts index a3c6e271b3..ab3c23459b 100644 --- a/dexs/okcswap/index.ts +++ b/dexs/okcswap/index.ts @@ -1,4 +1,4 @@ -import { DEFAULT_DAILY_VOLUME_FIELD, DEFAULT_TOTAL_VOLUME_FIELD, getChainVolume } from "../../helpers/getUniSubgraphVolume"; +import { DEFAULT_DAILY_VOLUME_FIELD, DEFAULT_TOTAL_VOLUME_FIELD, getChainVolume, getChainVolume2 } from "../../helpers/getUniSubgraphVolume"; import { CHAIN } from "../../helpers/chains"; import request, { gql } from "graphql-request"; import { SimpleAdapter } from "../../adapters/types"; @@ -38,23 +38,17 @@ const getCustomBlock = async (timestamp: number) => { return block; }; -const DAILY_VOLUME_FACTORY = "uniswapDayData"; - -const graphs = getChainVolume({ +const graphs = getChainVolume2({ graphUrls: endpoints, totalVolume: { factory: "uniswapFactories", field: DEFAULT_TOTAL_VOLUME_FIELD, }, - dailyVolume: { - factory: DAILY_VOLUME_FACTORY, - field: DEFAULT_DAILY_VOLUME_FIELD, - dateField: 'date' - }, getCustomBlock, }); const adapter: SimpleAdapter = { + version: 2, adapter: { [CHAIN.OKEXCHAIN]: { fetch: graphs(CHAIN.OKEXCHAIN), diff --git a/dexs/onepunch/index.ts b/dexs/onepunch/index.ts index 0bdfee5cd1..8279de33b8 100644 --- a/dexs/onepunch/index.ts +++ b/dexs/onepunch/index.ts @@ -1,10 +1,11 @@ +import * as sdk from "@defillama/sdk"; import { CHAIN } from "../../helpers/chains"; import { univ2Adapter } from "../../helpers/getUniSubgraphVolume"; const adapters = univ2Adapter( { [CHAIN.BSC]: - "https://api.thegraph.com/subgraphs/name/one-punch-team/onepunch-subgraph-bsc", + sdk.graph.modifyEndpoint('GQJoTmGyx4SGL1iVRBvyxA8jLNgcV8YMHcbLjf6DrUbv'), }, { factoriesName: "onePunchDatas", diff --git a/dexs/oolongswap/index.ts b/dexs/oolongswap/index.ts index 96f993bbe7..febc34b921 100644 --- a/dexs/oolongswap/index.ts +++ b/dexs/oolongswap/index.ts @@ -1,8 +1,9 @@ +import * as sdk from "@defillama/sdk"; import { CHAIN } from "../../helpers/chains"; import { univ2Adapter } from "../../helpers/getUniSubgraphVolume"; const endpoints = { - [CHAIN.BOBA]: "https://api.thegraph.com/subgraphs/name/oolongswap/oolongswap-mainnet", + [CHAIN.BOBA]: sdk.graph.modifyEndpoint('opoNLKkoTJtLzbPv5pf6XDzQp4XUk9pJfqvgHCUyzqo'), }; const adapter = univ2Adapter(endpoints, {}); diff --git a/dexs/openbook/index.ts b/dexs/openbook/index.ts index 869de687fd..32012c1083 100644 --- a/dexs/openbook/index.ts +++ b/dexs/openbook/index.ts @@ -1,18 +1,22 @@ import { SimpleAdapter } from "../../adapters/types"; import { CHAIN } from "../../helpers/chains"; import { getUniqStartOfTodayTimestamp } from "../../helpers/getUniSubgraphVolume"; -import fetchURL from "../../utils/fetchURL"; +import fetchURL, { httpGet } from "../../utils/fetchURL"; interface IVolume { - volume_24h: number; + notionalVolume24hour: number; } const fetch = async (timestamp: number) => { const dayTimestamp = getUniqStartOfTodayTimestamp(new Date(timestamp * 1000)); - const url = `https://dry-ravine-67635.herokuapp.com/pairs`; - const historicalVolume: IVolume[] = (await fetchURL(url)); - const dailyVolume = historicalVolume.reduce((a: number, b: IVolume) => a + b.volume_24h, 0); + const url = `https://prod.arcana.markets/api/openbookv2/markets`; + const historicalVolume: IVolume[] = (await httpGet(url, { headers: { + "origin": "https://www.openbook.ag", + "Referer": "https://www.openbook.ag", + "user-agent":"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/122.0.0.0 Safari/537.36" } + })); + const dailyVolume = historicalVolume.reduce((a: number, b: IVolume) => a + b.notionalVolume24hour, 0); return { timestamp: dayTimestamp, diff --git a/dexs/opx-finance/index.ts b/dexs/opx-finance/index.ts index a5be41d27f..e474d35417 100644 --- a/dexs/opx-finance/index.ts +++ b/dexs/opx-finance/index.ts @@ -1,10 +1,11 @@ +import * as sdk from "@defillama/sdk"; import request, { gql } from "graphql-request"; import { Fetch, SimpleAdapter } from "../../adapters/types"; import { CHAIN } from "../../helpers/chains"; import { getUniqStartOfTodayTimestamp } from "../../helpers/getUniSubgraphVolume"; const endpoints: { [key: string]: string } = { - [CHAIN.OPTIMISM]: "https://api.thegraph.com/subgraphs/name/opx-finance/opx-op-stats", + [CHAIN.OPTIMISM]: sdk.graph.modifyEndpoint('B8ZSq8gQJGk3C8hduPokgkr4PVcfe4Ydy5jDBk8siPe4'), } const historicalDataSwap = gql` diff --git a/dexs/oraidex-v3/index.ts b/dexs/oraidex-v3/index.ts new file mode 100644 index 0000000000..66810c943d --- /dev/null +++ b/dexs/oraidex-v3/index.ts @@ -0,0 +1,42 @@ +import { gql, GraphQLClient } from "graphql-request"; +import { FetchOptions, SimpleAdapter } from "../../adapters/types"; +import { CHAIN } from "../../helpers/chains"; +import { getUniqStartOfTodayTimestamp } from "../../helpers/getUniSubgraphVolume"; + +const historicalVolumeEndpoint = "https://staging-ammv3-indexer.oraidex.io/"; +const fetch = async (_timestamp: number, _t: any, options: FetchOptions) => { + const dayTimestamp = getUniqStartOfTodayTimestamp(new Date(options.startOfDay * 1000)); + const dayIndex = Math.floor(dayTimestamp / 86400); + const query = gql` + query PoolDayData { + poolDayData( + filter: { + dayIndex: { equalTo: ${dayIndex} } + } + ) { + aggregates { + sum { + volumeInUSD + } + } + } + }`; + + const res = await new GraphQLClient(historicalVolumeEndpoint).request(query); + const dailyVolume = res.poolDayData.aggregates.sum.volumeInUSD; + return { + dailyVolume: dailyVolume ? `${dailyVolume}` : undefined, + timestamp: dayTimestamp, + }; +}; + +const adapter: SimpleAdapter = { + adapter: { + [CHAIN.ORAI]: { + fetch, + start: 1722587676, + }, + }, +}; + +export default adapter; diff --git a/dexs/orca/index.ts b/dexs/orca/index.ts index 219eb9aade..ba1a8bb646 100644 --- a/dexs/orca/index.ts +++ b/dexs/orca/index.ts @@ -1,11 +1,13 @@ import { CHAIN } from '../../helpers/chains'; import { httpGet } from '../../utils/fetchURL'; -const wpEndpoint = "https://api.mainnet.orca.so/v1/whirlpool/list?whitelisted=true"; +const wpEndpoint = "https://api.mainnet.orca.so/v1/whirlpool/list"; async function fetch(timestamp: number) { const [whirlpools] = await Promise.all([httpGet(wpEndpoint)]); - const wpVol = whirlpools.whirlpools.reduce((sum: number, pool: any) => + const wpVol = whirlpools.whirlpools + .filter((pool: any) => pool?.tvl > 100_000) + .reduce((sum: number, pool: any) => sum + (pool?.volume?.day || 0) , 0); return { diff --git a/dexs/orderly-network/index.ts b/dexs/orderly-network/index.ts index 3181fbb592..b06ad23fc9 100644 --- a/dexs/orderly-network/index.ts +++ b/dexs/orderly-network/index.ts @@ -1,4 +1,4 @@ -import type { BreakdownAdapter } from "../../adapters/types"; +import type { BreakdownAdapter, FetchOptions } from "../../adapters/types"; import { CHAIN } from "../../helpers/chains"; import { getUniqStartOfTodayTimestamp } from "../../helpers/getUniSubgraphVolume"; import { httpGet } from "../../utils/fetchURL"; @@ -12,12 +12,20 @@ const adapter: BreakdownAdapter = { "orderly-network": { [CHAIN.NEAR]: { start: 1669977923, - fetch: async(ts)=>{ - const data = await httpGet(apiNear) - const cleanTimestamp = getUniqStartOfTodayTimestamp(new Date(ts * 1000)) - return { - timestamp: cleanTimestamp, - dailyVolume: data.find((t:any)=>dateToTs(t.date) === cleanTimestamp)?.volume + fetch: async(__t: number, _: any, { startOfDay }: FetchOptions) => { + try { + const data = await httpGet(apiNear) // error + const cleanTimestamp = getUniqStartOfTodayTimestamp(new Date(startOfDay * 1000)) + return { + timestamp: cleanTimestamp, + dailyVolume: data.find((t:any)=>dateToTs(t.date) === cleanTimestamp)?.volume + } + } catch (e) { + console.error(e); + return { + timestamp: startOfDay, + dailyVolume: 0 + } } } }, @@ -25,11 +33,11 @@ const adapter: BreakdownAdapter = { "orderly-network-derivatives": { [CHAIN.ARBITRUM]: { start: 1698278400, - fetch: async (timestamp: number) =>{ + fetch: async (__t: number, _: any, { startOfDay }: FetchOptions) =>{ const data = await httpGet(apiEVM) - const cleanTimestamp = getUniqStartOfTodayTimestamp(new Date(timestamp * 1000)) + const cleanTimestamp = getUniqStartOfTodayTimestamp(new Date(startOfDay * 1000)) return { - timestamp: timestamp, + timestamp: cleanTimestamp, dailyVolume: data.find((t:any)=>dateToTs(t.date) === cleanTimestamp)?.volume } } diff --git a/dexs/padswap/index.ts b/dexs/padswap/index.ts index 3e36bf7737..240b67d84f 100644 --- a/dexs/padswap/index.ts +++ b/dexs/padswap/index.ts @@ -1,10 +1,11 @@ +import * as sdk from "@defillama/sdk"; import { CHAIN } from "../../helpers/chains"; import { univ2Adapter } from "../../helpers/getUniSubgraphVolume"; const adapters = univ2Adapter({ - // [CHAIN.MOONRIVER]: 'https://api.thegraph.com/subgraphs/name/toadguy/padswap-subgraph-moonriver', - [CHAIN.BSC]: 'https://api.thegraph.com/subgraphs/name/d1stsys/padswap-backup-2', - [CHAIN.MOONBEAN]: 'https://api.thegraph.com/subgraphs/name/toadguy/padswap-subgraph-moonbeam', + // [CHAIN.MOONRIVER]: sdk.graph.modifyEndpoint('2Mi1JF6Rq5ZSBhrcomyXnCady3Fuwy8eyEPT95qitT9U'), + [CHAIN.BSC]: sdk.graph.modifyEndpoint('85ZjqMyuYVWcWWW7Ei8ptMyVRhwYwxGBHo83TmNJkw2U'), + [CHAIN.MOONBEAN]: sdk.graph.modifyEndpoint('HZrJDqzqR12BBUfmxaaPNbnSB9JunWzdzkpQaGYSHNcv'), }, {}); adapters.adapter.bsc.start = 1620518400; diff --git a/dexs/palmswap/index.ts b/dexs/palmswap/index.ts index 933554af41..df1f391dc5 100644 --- a/dexs/palmswap/index.ts +++ b/dexs/palmswap/index.ts @@ -1,3 +1,4 @@ +import * as sdk from "@defillama/sdk"; import { SimpleAdapter } from "../../adapters/types"; import { CHAIN } from "../../helpers/chains"; import { BigNumberish, ethers } from "ethers"; @@ -34,7 +35,7 @@ const formatAmount = ( const info: { [key: string]: any } = { bsc: { subgraph: - "https://api.thegraph.com/subgraphs/name/palmswap/synthetic-stats-mainnet", + sdk.graph.modifyEndpoint('DdLtKxzUi6ExMok8dNWh9B2HN5WeTWcQsfSSZMKH1trQ'), }, }; diff --git a/dexs/panacakeswap-perp/index.ts b/dexs/panacakeswap-perp/index.ts index 9340360a2f..c2afcad96c 100644 --- a/dexs/panacakeswap-perp/index.ts +++ b/dexs/panacakeswap-perp/index.ts @@ -3,6 +3,8 @@ const config = { arbitrum: { contract: '0xb3879e95a4b8e3ee570c232b19d520821f540e48', }, bsc: { contract: '0x1b6f2d3844c6ae7d56ceb3c3643b9060ba28feb0', }, + //op_bnb: { contract: '0x5A5454A6030FB50ceb3eb78977D140198A27be5e' }, + base: {contract: '0x9D93e5B2364070bC9837e91833F162430246DD57' }, } import { ChainBlocks, FetchOptions } from "../../adapters/types"; diff --git a/dexs/pangolin/index.ts b/dexs/pangolin/index.ts index 6826f96abd..0ad4c0f6f6 100644 --- a/dexs/pangolin/index.ts +++ b/dexs/pangolin/index.ts @@ -1,8 +1,13 @@ -import { univ2Adapter } from "../../helpers/getUniSubgraphVolume"; +import * as sdk from "@defillama/sdk"; +import { univ2Adapter2 } from "../../helpers/getUniSubgraphVolume"; -export default univ2Adapter({ - "avax": "https://api.thegraph.com/subgraphs/name/pangolindex/exchange" -}, { +export default univ2Adapter2( + { + avax: sdk.graph.modifyEndpoint( + "CPXTDcwh6tVP88QvFWW7pdvZJsCN4hSnfMmYeF1sxCLq", + ), + }, + { factoriesName: "pangolinFactories", - dayData: "pangolinDayData", -}); + }, +); diff --git a/dexs/pear-protocol/index.ts b/dexs/pear-protocol/index.ts new file mode 100644 index 0000000000..c47449ac30 --- /dev/null +++ b/dexs/pear-protocol/index.ts @@ -0,0 +1,28 @@ +import { SimpleAdapter } from "../../adapters/types"; +import { CHAIN } from "../../helpers/chains"; +import { httpGet } from "../../utils/fetchURL"; + +const fetch = async (timestamp: number) => { + const url = `https://www.api.pearprotocol.io/v1/metric?timestamp=${timestamp}`; + const response = await httpGet(url); + + const totalVolume = response.payload.totalVolume; + const dailyVolume = response.payload.dailyVolume; + + return { + totalVolume, + dailyVolume, + timestamp, + }; +}; + +const adapter: SimpleAdapter = { + adapter: { + [CHAIN.ARBITRUM]: { + fetch: fetch, + start: 1715199684, + }, + }, +}; + +export default adapter; diff --git a/dexs/pearlfi/index.ts b/dexs/pearlfi/index.ts index 6645953dd7..3697425612 100644 --- a/dexs/pearlfi/index.ts +++ b/dexs/pearlfi/index.ts @@ -1,16 +1,6 @@ -import { SimpleAdapter } from "../../adapters/types"; import { CHAIN } from "../../helpers/chains"; -import { getDexVolumeExports } from "../../helpers/dexVolumeLogs"; +import { uniV2Exports } from "../../helpers/uniswap"; -const FACTORY_ADDRESS = '0xEaF188cdd22fEEBCb345DCb529Aa18CA9FcB4FBd' - -const adapter: SimpleAdapter = { - adapter: { - [CHAIN.POLYGON]: { - fetch: getDexVolumeExports({ chain: CHAIN.POLYGON, factory: FACTORY_ADDRESS }), - start: 1686268800, - }, - } -}; - -export default adapter; +export default uniV2Exports({ + [CHAIN.POLYGON]: { factory: '0xEaF188cdd22fEEBCb345DCb529Aa18CA9FcB4FBd', }, +}) diff --git a/dexs/pegasys-v3/index.ts b/dexs/pegasys-v3/index.ts index c8b7257fa5..c58e8f8ec9 100644 --- a/dexs/pegasys-v3/index.ts +++ b/dexs/pegasys-v3/index.ts @@ -1,24 +1,21 @@ import { SimpleAdapter } from "../../adapters/types"; -import { DEFAULT_TOTAL_VOLUME_FIELD, getChainVolume } from "../../helpers/getUniSubgraphVolume"; +import { DEFAULT_TOTAL_VOLUME_FIELD, getChainVolume, getChainVolume2 } from "../../helpers/getUniSubgraphVolume"; import { CHAIN } from "../../helpers/chains"; const endpoints = { [CHAIN.ROLLUX]: "https://rollux.graph.pegasys.fi/subgraphs/name/pollum-io/pegasys-v3", }; -const graphs = getChainVolume({ +const graphs = getChainVolume2({ graphUrls: endpoints, totalVolume: { factory: "factories", field: DEFAULT_TOTAL_VOLUME_FIELD, }, - dailyVolume: { - factory: "pegasysDayData", - field: "volumeUSD", - }, }); // rollux const adapter: SimpleAdapter = { + version: 2, adapter: { [CHAIN.ROLLUX]: { fetch: graphs(CHAIN.ROLLUX), diff --git a/dexs/pendle/index.ts b/dexs/pendle/index.ts new file mode 100644 index 0000000000..7a996d5d56 --- /dev/null +++ b/dexs/pendle/index.ts @@ -0,0 +1,117 @@ +import { + FetchGetLogsOptions, + FetchOptions, + FetchResultV2, + SimpleAdapter, +} from "../../adapters/types"; +import { CHAIN } from "../../helpers/chains"; +import { Chain } from "@defillama/sdk/build/general"; +import fetchURL from "../../utils/fetchURL"; +import { Balances } from "@defillama/sdk"; + +type MarketData = { + address: string; + sy: { + address: string; + }; + yt: { + address: string; + }; +}; + +const abi: { [event: string]: string } = { + orderFilledV2: + "event OrderFilledV2(bytes32 indexed orderHash, uint8 indexed orderType, address indexed YT, address token, uint256 netInputFromMaker, uint256 netOutputToMaker, uint256 feeAmount, uint256 notionalVolume, address maker, address taker)", + marketSwapEvent: + "event Swap(address indexed caller, address indexed receiver, int256 netPtOut, int256 netSyOut, uint256 netSyFee, uint256 netSyToReserve)", +}; + +const chains: { [chain: string]: { id: number; start: number } } = { + [CHAIN.ETHEREUM]: { id: 1, start: 1686268800 }, + [CHAIN.ARBITRUM]: { id: 42161, start: 1686268800 }, + [CHAIN.MANTLE]: { id: 5000, start: 1711506087 }, + [CHAIN.BSC]: { id: 56, start: 1686268800 }, + [CHAIN.OPTIMISM]: { id: 10, start: 1691733600 }, +}; + +async function amm( + apiData: MarketData[], + getLogs: (params: FetchGetLogsOptions) => Promise, + balances: Balances, +): Promise { + const assets: { [address: string]: string } = {}; + apiData.map((market: MarketData) => { + assets[market.address] = market.sy.address; + }); + + const swapEvents: { [address: string]: any[] } = {}; + await Promise.all( + Object.keys(assets).map( + async (target: string) => + await getLogs({ + eventAbi: abi.marketSwapEvent, + target, + }).then((e) => { + swapEvents[target] = e; + }), + ), + ); + + Object.keys(swapEvents).map((market) => { + swapEvents[market].map((swap) => { + balances.add(assets[market], Math.abs(Number(swap.netSyOut))); + }); + }); +} + +async function limitOrder( + apiData: MarketData[], + getLogs: (params: FetchGetLogsOptions) => Promise, + balances: Balances, +): Promise { + const fills = await getLogs({ + target: "0x000000000000c9b3e2c3ec88b1b4c0cd853f4321", + eventAbi: abi.orderFilledV2, + }); + + const ytToSy: { [yt: string]: string } = {}; + apiData.map((market: MarketData) => { + ytToSy[market.yt.address.toLowerCase()] = market.sy.address; + }); + + fills.map((fill) => + balances.add(ytToSy[fill.YT.toLowerCase()], fill.notionalVolume), + ); +} + +const fetch = (chain: Chain) => { + return async (options: FetchOptions): Promise => { + const dailyVolume: Balances = options.createBalances(); + const res = await fetchURL( + `https://api-v2.pendle.finance/core/v1/${chains[chain].id}/markets?limit=100&select=pro&is_active=true`, + ); + + await Promise.all([ + await amm(res.results, options.getLogs, dailyVolume), + await limitOrder(res.results, options.getLogs, dailyVolume), + ]); + + return { + dailyVolume, + }; + }; +}; + +const adapter: SimpleAdapter = { + version: 2, + adapter: {}, +}; + +Object.keys(chains).map((chain) => { + adapter.adapter[chain] = { + fetch: fetch(chain), + start: chains[chain].start, + }; +}); + +export default adapter; diff --git a/dexs/perennial-v2/index.ts b/dexs/perennial-v2/index.ts index 290f0a2e23..0878884ec3 100644 --- a/dexs/perennial-v2/index.ts +++ b/dexs/perennial-v2/index.ts @@ -6,28 +6,21 @@ import { getEnv } from '../../helpers/env' const apiKey = getEnv('PERENNIAL_V2_SUBGRAPH_API_KEY') const graphUrls: { [key: string]: string } = { - [CHAIN.ARBITRUM]: `https://subgraph.satsuma-prod.com/${apiKey}/equilibria/perennial-v2-arbitrum/api`, + [CHAIN.ARBITRUM]: `https://subgraph.satsuma-prod.com/${apiKey}/equilibria/perennial-v2-arbitrum-new/api`, } const volumeDataQuery = gql` query PNLVolume($period: BigInt!, $periodEnd: BigInt!) { - daily: bucketedVolumes( - where: { - bucket: daily - periodStartTimestamp_gte: $period - periodStartTimestamp_lt: $periodEnd - } + daily: protocolAccumulations( + where: { bucket: daily, timestamp_gte: $period, timestamp_lt: $periodEnd } first: 1000 - orderBy: periodStartTimestamp + orderBy: timestamp orderDirection: desc ) { - market longNotional shortNotional } - - total: bucketedVolumes(where: { bucket: all }, first: 1000) { - market + total: protocolAccumulations(where: { bucket: all }) { longNotional shortNotional } diff --git a/dexs/pharaoh-exchange/index.ts b/dexs/pharaoh-exchange/index.ts index 58485e68cb..72533e46cf 100644 --- a/dexs/pharaoh-exchange/index.ts +++ b/dexs/pharaoh-exchange/index.ts @@ -1,12 +1,11 @@ +import * as sdk from "@defillama/sdk"; import { CHAIN } from "../../helpers/chains"; -import { univ2Adapter } from "../../helpers/getUniSubgraphVolume"; +import { univ2Adapter2 } from "../../helpers/getUniSubgraphVolume"; -const adapters = univ2Adapter({ - [CHAIN.AVAX]: "https://api.thegraph.com/subgraphs/name/ramsesexchange/pharaoh-cl-subgraph" +const adapters = univ2Adapter2({ + [CHAIN.AVAX]: sdk.graph.modifyEndpoint('oM4WnuyAbSwPpjk6niUkp88AZg1hSTi9aC1ZM4RcsqR') }, { factoriesName: "factories", - dayData: "uniswapDayData", - dailyVolume: "volumeUSD", totalVolume: "totalVolumeUSD", }); diff --git a/dexs/physica-finance/index.ts b/dexs/physica-finance/index.ts new file mode 100644 index 0000000000..c843643b22 --- /dev/null +++ b/dexs/physica-finance/index.ts @@ -0,0 +1,59 @@ +import { Chain } from "@defillama/sdk/build/general"; +import { CHAIN } from "../../helpers/chains"; +import { getGraphDimensions2 } from "../../helpers/getUniSubgraph"; +import { BreakdownAdapter } from "../../adapters/types"; + +const endpointsV3 = { + [CHAIN.PLANQ]: "https://subgraph.planq.finance/subgraphs/name/ianlapham/uniswap-v3", +}; + +const v3Graphs = getGraphDimensions2({ + graphUrls: endpointsV3, + totalVolume: { + factory: "factories", + field: "totalVolumeUSD", + }, + feesPercent: { + type: "fees", + ProtocolRevenue: 14.2857, // 1/7th of generated LP fees are protocol fees + HoldersRevenue: 0, + UserFees: 100, // User fees are 100% of collected fees + SupplySideRevenue: 85.7143, // ~85% of fees are going to LPs + Revenue: 100, // Revenue is 100% of collected fees + }, +}); + +const startTimeV3: { [key: string]: number } = { + [CHAIN.PLANQ]: 1716372437, +}; + +const v3 = Object.keys(endpointsV3).reduce( + (acc, chain) => ({ + ...acc, + [chain]: { + fetch: v3Graphs(chain as Chain), + start: startTimeV3[chain], + meta: { + methodology: { + Fees: "Each pool charge between 0.01% to 1% fee", + UserFees: "Users pay between 0.01% to 1% fee", + Revenue: "0 to 1/4 of the fee goes to Physica Token stakers", + HoldersRevenue: "None", + ProtocolRevenue: "Physica token stakers receive a share of the fees", + SupplySideRevenue: + "Liquidity providers get most of the fees of all trades in their pools", + }, + }, + }, + }), + {} +); + +const adapter: BreakdownAdapter = { + version: 2, + breakdown: { + v3: v3, + }, +}; + +export default adapter; diff --git a/dexs/pika-protocol-v4/index.ts b/dexs/pika-protocol-v4/index.ts index a859d98e9f..59607272b3 100644 --- a/dexs/pika-protocol-v4/index.ts +++ b/dexs/pika-protocol-v4/index.ts @@ -1,3 +1,4 @@ +import * as sdk from "@defillama/sdk"; import { Chain } from "@defillama/sdk/build/general"; import BigNumber from "bignumber.js"; import request, { gql } from "graphql-request"; @@ -22,7 +23,7 @@ interface IValume { } const endpoints: IURL = { - [CHAIN.OPTIMISM]: "https://api.thegraph.com/subgraphs/name/ethandev0/pikaperpv4_optimism" + [CHAIN.OPTIMISM]: sdk.graph.modifyEndpoint('6Z7dcfhWCWxvM5EWYtS9ZRmJSKmButFjuTvvDoCWEef') } const fetch = (chain: Chain) => { diff --git a/dexs/pika-protocol/index.ts b/dexs/pika-protocol/index.ts index 670c1f9279..7c6f9dca69 100644 --- a/dexs/pika-protocol/index.ts +++ b/dexs/pika-protocol/index.ts @@ -1,3 +1,4 @@ +import * as sdk from "@defillama/sdk"; import { Chain } from "@defillama/sdk/build/general"; import BigNumber from "bignumber.js"; import request, { gql } from "graphql-request"; @@ -22,7 +23,7 @@ interface IValume { } const endpoints: IURL = { - [CHAIN.OPTIMISM]: "https://api.thegraph.com/subgraphs/name/ethandev0/pikaperpv3_optimism" + [CHAIN.OPTIMISM]: sdk.graph.modifyEndpoint('DUcxevdqV8kBQdHWcdUcaEctaoVyqYZTtCftojL23NbA') } const fetch = (chain: Chain) => { @@ -45,8 +46,8 @@ const fetch = (chain: Chain) => { `; const res: IValume = (await request(endpoints[chain], graphQuery)); - const dailyVolume = Number(res.vaultDayData.cumulativeVolume) / 10 ** 8; - const totalVolume = Number(res.vaults[0].cumulativeVolume) / 10 ** 8; + const dailyVolume = Number(res.vaultDayData?.cumulativeVolume || 0) / 10 ** 8; + const totalVolume = Number(res.vaults[0]?.cumulativeVolume || 0) / 10 ** 8; return { timestamp, diff --git a/dexs/pingu/index.ts b/dexs/pingu/index.ts index e2217aacf2..7cf38f610f 100644 --- a/dexs/pingu/index.ts +++ b/dexs/pingu/index.ts @@ -11,7 +11,7 @@ interface IGraph { id: string; } -const URL = 'https://api.studio.thegraph.com/query/43986/pingu-sg/0.1.0'; +const URL = 'https://api.studio.thegraph.com/query/75208/pingu-sg-v2/0.0.1/'; const fetch = async (timestamp: number): Promise => { const dayTimestamp = getUniqStartOfTodayTimestamp(new Date(timestamp * 1000)); const chain = CHAIN.ARBITRUM; diff --git a/dexs/pinkswap/index.ts b/dexs/pinkswap/index.ts index 15ab383287..7b754e6eea 100644 --- a/dexs/pinkswap/index.ts +++ b/dexs/pinkswap/index.ts @@ -1,6 +1,7 @@ +import * as sdk from "@defillama/sdk"; import { CHAIN } from "../../helpers/chains"; import { univ2Adapter } from "../../helpers/getUniSubgraphVolume"; export default univ2Adapter({ - [CHAIN.BSC]: "https://api.thegraph.com/subgraphs/name/pinkmoonfinance/pinkswap" + [CHAIN.BSC]: sdk.graph.modifyEndpoint('CwTzDabgebYMipjh9gqP4Kyrbi3HGQSabBuR4ngorXUt') }, {}); diff --git a/dexs/platypus/index.ts b/dexs/platypus/index.ts index 7ba10753df..3c6c86c15c 100644 --- a/dexs/platypus/index.ts +++ b/dexs/platypus/index.ts @@ -1,3 +1,4 @@ +import * as sdk from "@defillama/sdk"; import { DISABLED_ADAPTER_KEY, FetchResult, SimpleAdapter } from "../../adapters/types"; import { CHAIN } from "../../helpers/chains"; import { gql, request } from "graphql-request"; @@ -10,7 +11,7 @@ interface IGraph { dayID: string; } -const URL = 'https://api.thegraph.com/subgraphs/name/platypus-finance/platypus-dashboard'; +const URL = sdk.graph.modifyEndpoint('Bu5QPRWGnZB6NxU4S7kAKQZJpY4pHmAq3TV69V1W2Qqw'); const fetch = async (timestamp: number): Promise => { const dayTimestamp = getUniqStartOfTodayTimestamp(new Date(timestamp * 1000)); const dayID = (dayTimestamp / 86400); diff --git a/dexs/polkadex/index.ts b/dexs/polkadex/index.ts new file mode 100644 index 0000000000..41a3dad741 --- /dev/null +++ b/dexs/polkadex/index.ts @@ -0,0 +1,28 @@ +import fetchURL from "../../utils/fetchURL" +import {FetchOptions, FetchV2, SimpleAdapter} from "../../adapters/types"; +import { CHAIN } from "../../helpers/chains"; + +type IAPIResponse = { + volume_usd: number; +}; + +const fetchVolume: FetchV2 = async (options: FetchOptions) => { + const response: IAPIResponse = (await fetchURL(`https://integration-api.polkadex.trade/v1/volumeByRange?start=${options.startTimestamp}&end=${options.endTimestamp}`)); + const dailyVolume = response.volume_usd; + + return { + dailyVolume: dailyVolume ? `${dailyVolume}` : undefined + }; +}; + +const adapter: SimpleAdapter = { + version: 2, + adapter: { + [CHAIN.POLKADEX]: { + fetch: fetchVolume, + start: 1704292840 + } + } +}; + +export default adapter; \ No newline at end of file diff --git a/dexs/polkaswap/index.ts b/dexs/polkaswap/index.ts index d7e8cb1a80..9bb1a4413a 100644 --- a/dexs/polkaswap/index.ts +++ b/dexs/polkaswap/index.ts @@ -16,7 +16,7 @@ const getDailyVolume = () => { }` } -const graphQLClient = new GraphQLClient("https://api.subquery.network/sq/sora-xor/sora-prod-sub4"); +const graphQLClient = new GraphQLClient("https://api.subquery.network/sq/sora-xor/sora-prod"); const getGQLClient = () => { return graphQLClient } diff --git a/dexs/polycat/index.ts b/dexs/polycat/index.ts index 2d24130c89..64123b0348 100644 --- a/dexs/polycat/index.ts +++ b/dexs/polycat/index.ts @@ -1,7 +1,8 @@ +import * as sdk from "@defillama/sdk"; import { CHAIN } from "../../helpers/chains"; import { univ2Adapter } from "../../helpers/getUniSubgraphVolume"; export default univ2Adapter({ - [CHAIN.POLYGON]: "https://api.thegraph.com/subgraphs/name/polycatfi/polycat-finance-amm" + [CHAIN.POLYGON]: sdk.graph.modifyEndpoint('9xwmkrJTk5s5e8QoBnQG1yTN8seLwzLWwACaqTgq2U9x') }, { }); diff --git a/dexs/predict-fun/index.ts b/dexs/predict-fun/index.ts new file mode 100644 index 0000000000..a72b873382 --- /dev/null +++ b/dexs/predict-fun/index.ts @@ -0,0 +1,79 @@ +import request from "graphql-request"; +import { Fetch, SimpleAdapter } from "../../adapters/types"; +import { CHAIN } from "../../helpers/chains"; +import { getUniqStartOfTodayTimestamp } from "../../helpers/getUniSubgraphVolume"; + + +const endpoints: { [key: string]: string } = { + blast: 'https://graphql.predict.fun/graphql' +} + +const query = (after?: string) => `query { + categories (pagination: { + first: 100 + ${after ? `after: "${after}"` : ''} + }) { + totalCount + pageInfo { + hasNextPage + startCursor + endCursor + } + edges { + node { + id + slug + title + statistics { + liquidityValueUsd + volume24hUsd + volumeTotalUsd + } + } + } + } +} +` + +const fetch: Fetch = async (_: any, __, { chain }) => { + const dayTimestamp = getUniqStartOfTodayTimestamp() + const categories: any = [] + let after + do { + const data = await request(endpoints[chain], query(after)) + categories.push(...data.categories.edges) + if (data.categories.pageInfo.hasNextPage) { + after = data.pageInfo.endCursor + } + } while (after) + const dailyVolume = categories.reduce((vol, category) => vol + category.node.statistics.volume24hUsd, 0) + const totalVolume = categories.reduce((vol, category) => vol + category.node.statistics.volumeTotalUsd, 0) + + + return { + timestamp: dayTimestamp, + dailyVolume, + totalVolume, + } +} + +const startTimestamps: { [chain: string]: number } = { + [CHAIN.BLAST]: 1691128800, +} + +const volume = Object.keys(endpoints).reduce( + (acc, chain) => ({ + ...acc, + [chain]: { + fetch, + start: startTimestamps[chain] + }, + }), + {} +); + +const adapter: SimpleAdapter = { + timetravel: false, + adapter: volume +}; +export default adapter; diff --git a/dexs/primex-finance/index.ts b/dexs/primex-finance/index.ts index 19d3ea29ec..060cacb316 100644 --- a/dexs/primex-finance/index.ts +++ b/dexs/primex-finance/index.ts @@ -1,37 +1,80 @@ -import { ChainBlocks, FetchOptions, FetchResultVolume, SimpleAdapter } from "../../adapters/types" -import { config, } from "./utils"; +import { + ChainBlocks, + FetchOptions, + FetchResultVolume, + SimpleAdapter, +} from "../../adapters/types"; +import { config, topics } from "./utils"; const abi = { - "SpotSwap": "event SpotSwap(address indexed trader, address indexed receiver, address tokenA, address tokenB, uint256 amountSold, uint256 amountBought)", - "OpenPosition": "event OpenPosition(uint256 indexed positionId, address indexed trader, address indexed openedBy, (uint256 id, uint256 scaledDebtAmount, address bucket, address soldAsset, uint256 depositAmountInSoldAsset, address positionAsset, uint256 positionAmount, address trader, uint256 openBorrowIndex, uint256 createdAt, uint256 updatedConditionsAt, bytes extraParams) position, address feeToken, uint256 protocolFee, uint256 entryPrice, uint256 leverage, (uint256 managerType, bytes params)[] closeConditions)", - "ClosePosition": "event ClosePosition(uint256 indexed positionId, address indexed trader, address indexed closedBy, address bucketAddress, address soldAsset, address positionAsset, uint256 decreasePositionAmount, int256 profit, uint256 positionDebt, uint256 amountOut, uint8 reason)", - "PartialClosePosition": "event PartialClosePosition(uint256 indexed positionId, address indexed trader, address bucketAddress, address soldAsset, address positionAsset, uint256 decreasePositionAmount, uint256 depositedAmount, uint256 scaledDebtAmount, int256 profit, uint256 positionDebt, uint256 amountOut)" -} + SpotSwap: + "event SpotSwap(address indexed trader, address indexed receiver, address tokenA, address tokenB, uint256 amountSold, uint256 amountBought)", + OpenPosition: + "event OpenPosition(uint256 indexed positionId, address indexed trader, address indexed openedBy, (uint256 id, uint256 scaledDebtAmount, address bucket, address soldAsset, uint256 depositAmountInSoldAsset, address positionAsset, uint256 positionAmount, address trader, uint256 openBorrowIndex, uint256 createdAt, uint256 updatedConditionsAt, bytes extraParams) position, address feeToken, uint256 protocolFee, uint256 entryPrice, uint256 leverage, (uint256 managerType, bytes params)[] closeConditions)", + OpenPositionV2: + "event OpenPosition( uint256 indexed positionId, address indexed trader, address indexed openedBy, (uint256 id, uint256 scaledDebtAmount, address bucket, address soldAsset, uint256 depositAmountInSoldAsset, address positionAsset, uint256 positionAmount, address trader, uint256 openBorrowIndex, uint256 createdAt, uint256 updatedConditionsAt, bytes extraParams) position, uint256 entryPrice, uint256 leverage, (uint256 managerType, bytes params)[] closeConditions)", + ClosePosition: + "event ClosePosition(uint256 indexed positionId, address indexed trader, address indexed closedBy, address bucketAddress, address soldAsset, address positionAsset, uint256 decreasePositionAmount, int256 profit, uint256 positionDebt, uint256 amountOut, uint8 reason)", + PartialClosePosition: + "event PartialClosePosition(uint256 indexed positionId, address indexed trader, address bucketAddress, address soldAsset, address positionAsset, uint256 decreasePositionAmount, uint256 depositedAmount, uint256 scaledDebtAmount, int256 profit, uint256 positionDebt, uint256 amountOut)", +}; -const fetch = (chain: string) => async (timestamp: number, _: ChainBlocks, { createBalances, getLogs, }: FetchOptions): Promise => { - const { swapManager, positionManager, batchManager } = config[chain]; - const dailyVolume = createBalances() +const fetch = + (chain: string) => + async ( + timestamp: number, + _: ChainBlocks, + { createBalances, getLogs }: FetchOptions + ): Promise => { + const { swapManager, positionManager, batchManager } = config[chain]; + const dailyVolume = createBalances(); - const logsConfig = [ - { targets: swapManager, eventAbi: abi.SpotSwap }, - { targets: positionManager, eventAbi: abi.OpenPosition }, - { targets: positionManager, eventAbi: abi.ClosePosition }, - { targets: positionManager, eventAbi: abi.PartialClosePosition }, - { targets: batchManager, eventAbi: abi.ClosePosition }, - ] + const logsConfig = [ + { targets: swapManager, eventAbi: abi.SpotSwap }, + { + targets: positionManager, + eventAbi: abi.OpenPosition, + topic: topics.openPosition, + }, + { + targets: positionManager, + eventAbi: abi.OpenPositionV2, + topic: topics.openPositionV2, + }, + { targets: positionManager, eventAbi: abi.ClosePosition }, + { targets: positionManager, eventAbi: abi.PartialClosePosition }, + { targets: batchManager, eventAbi: abi.ClosePosition }, + ]; - const [swapLogs, openPositionLogs, closePositionLogs, partiallyClosePositionLogs, closePositionBatchLogs] = await Promise.all(logsConfig.map(async (config) => getLogs(config))) + const [ + swapLogs, + openPositionLogs, + openPositionV2Logs, + closePositionLogs, + partiallyClosePositionLogs, + closePositionBatchLogs, + ] = await Promise.all(logsConfig.map(async (config) => getLogs(config))); - swapLogs.forEach((e: any) => dailyVolume.add(e.tokenA, e.amountSold)) - openPositionLogs.forEach((e: any) => dailyVolume.add(e.position.soldAsset, e.position.amountSold * e.leverage)) - closePositionLogs.forEach((e: any) => dailyVolume.add(e.soldAsset, e.amountOut)) - partiallyClosePositionLogs.forEach((e: any) => dailyVolume.add(e.soldAsset, e.amountOut)) - closePositionBatchLogs.forEach((e: any) => dailyVolume.add(e.soldAsset, e.amountOut)) + swapLogs.forEach((e: any) => dailyVolume.add(e.tokenA, e.amountSold)); + openPositionLogs.forEach((e: any) => + dailyVolume.add(e.position.positionAsset, e.position.positionAmount) + ); + openPositionV2Logs.forEach((e: any) => + dailyVolume.add(e.position.positionAsset, e.position.positionAmount) + ); + closePositionLogs.forEach((e: any) => + dailyVolume.add(e.soldAsset, e.amountOut) + ); + partiallyClosePositionLogs.forEach((e: any) => + dailyVolume.add(e.soldAsset, e.amountOut) + ); + closePositionBatchLogs.forEach((e: any) => + dailyVolume.add(e.soldAsset, e.amountOut) + ); - return { dailyVolume: dailyVolume, timestamp, } + return { dailyVolume: dailyVolume, timestamp }; + }; - -} const adapters: SimpleAdapter = { adapter: Object.keys(config).reduce((acc, chain) => { return { @@ -39,8 +82,8 @@ const adapters: SimpleAdapter = { [chain]: { fetch: fetch(chain), start: config[chain].start, - } - } - }, {}) -} + }, + }; + }, {}), +}; export default adapters; diff --git a/dexs/primex-finance/utils.ts b/dexs/primex-finance/utils.ts index 1f0c98e769..066f4a67c4 100644 --- a/dexs/primex-finance/utils.ts +++ b/dexs/primex-finance/utils.ts @@ -9,357 +9,55 @@ interface ChainConfig { const config: { [chain: string]: ChainConfig } = { [CHAIN.POLYGON]: { - swapManager: ['0x0AaDC2Eae6963ED983d85cbF088b0c294f4c26ff', '0xA0069a14Df3ECd19a38c509757eBc2C2Aaa44992'], - positionManager: ['0x02bcaA4633E466d151b34112608f60A82a4F6035'], - batchManager: ['0xC6B1AF3dEb9E379ccADF2Fa21263a50E91F4776C', '0xc10771D8f5B6Ba702E3a44EC76969f07578F08b7'], + swapManager: [ + "0x0AaDC2Eae6963ED983d85cbF088b0c294f4c26ff", + "0x140D437ac247D8D8FC43534f8f4E6c555B257a9e", + "0xA0069a14Df3ECd19a38c509757eBc2C2Aaa44992", + ], + positionManager: ["0x02bcaA4633E466d151b34112608f60A82a4F6035"], + batchManager: [ + "0xC6B1AF3dEb9E379ccADF2Fa21263a50E91F4776C", + "0xc611c8c3689B67096180289643Bd086ae5833ADC", + "0xc10771D8f5B6Ba702E3a44EC76969f07578F08b7", + ], start: 1697587200, }, [CHAIN.ARBITRUM]: { - swapManager: ['0xbE3de856EB22bf6EFA03DD55e65DF22bA212e6Db'], - positionManager: ['0x86890E30cE9E1e13Db5560BbEb435c55567Af1cd'], - batchManager: ['0xF2225a8f90311DaF9e989db1AfFd47617bb69E96'], + swapManager: [ + "0xbE3de856EB22bf6EFA03DD55e65DF22bA212e6Db", + "0xC024DE24f34eEc431D41340DA5A18d67eE46BA79", + ], + positionManager: ["0x86890E30cE9E1e13Db5560BbEb435c55567Af1cd"], + batchManager: [ + "0xF2225a8f90311DaF9e989db1AfFd47617bb69E96", + "0xE81ed447d923153f51207fdc41973B204F085f21", + ], start: 1700611200, }, [CHAIN.ETHEREUM]: { - swapManager: ['0xa6d76535e265357187653d4AAd9b362404D42EA8'], - positionManager: ['0x99d63fEA4b3Ef6ca77941df3C5740dAd1586f0B8'], - batchManager: ['0x1da9c104C517C7b4465c8Eef458Da0a6c61835Fe'], + swapManager: [ + "0xa6d76535e265357187653d4AAd9b362404D42EA8", + "0xb980D7b0F4A05572DE635E8916A222F05fC64552", + ], + positionManager: ["0x99d63fEA4b3Ef6ca77941df3C5740dAd1586f0B8"], + batchManager: [ + "0x1da9c104C517C7b4465c8Eef458Da0a6c61835Fe", + "0x2ff2D294312D3224d609fCc0b2EeE82b5f665753", + ], start: 1702771200, }, -} +}; const topics = { - swap: '0x5fcf6637f014854f918b233372226c5492e6a5157e517674a8588675550c40c6', - openPosition: '0x3f505465ce78d219c28bcf9bed881a651c4800d1161454b0d5c93225196e7b8e', - partiallyClosePosition: '0xda47f84a849dfb28125ae28a0bf305b75e72bff27796fc4bca36e2f848b0a0e6', - closePosition: '0x4a06c6510972c5a49ff5582d7d8e59f20228038c8cb9ea05d78f02ac7ee40662' -} - -const abi = [ - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "trader", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "receiver", - "type": "address" - }, - { - "indexed": false, - "internalType": "address", - "name": "tokenA", - "type": "address" - }, - { - "indexed": false, - "internalType": "address", - "name": "tokenB", - "type": "address" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "amountSold", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "amountBought", - "type": "uint256" - } - ], - "name": "SpotSwap", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "positionId", - "type": "uint256" - }, - { - "indexed": true, - "internalType": "address", - "name": "trader", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "openedBy", - "type": "address" - }, - { - "components": [ - { - "internalType": "uint256", - "name": "id", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "scaledDebtAmount", - "type": "uint256" - }, - { - "internalType": "contract IBucket", - "name": "bucket", - "type": "address" - }, - { - "internalType": "address", - "name": "soldAsset", - "type": "address" - }, - { - "internalType": "uint256", - "name": "depositAmountInSoldAsset", - "type": "uint256" - }, - { - "internalType": "address", - "name": "positionAsset", - "type": "address" - }, - { - "internalType": "uint256", - "name": "positionAmount", - "type": "uint256" - }, - { - "internalType": "address", - "name": "trader", - "type": "address" - }, - { - "internalType": "uint256", - "name": "openBorrowIndex", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "createdAt", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "updatedConditionsAt", - "type": "uint256" - }, - { - "internalType": "bytes", - "name": "extraParams", - "type": "bytes" - } - ], - "indexed": false, - "internalType": "struct PositionLibrary.Position", - "name": "position", - "type": "tuple" - }, - { - "indexed": false, - "internalType": "address", - "name": "feeToken", - "type": "address" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "protocolFee", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "entryPrice", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "leverage", - "type": "uint256" - }, - { - "components": [ - { - "internalType": "uint256", - "name": "managerType", - "type": "uint256" - }, - { - "internalType": "bytes", - "name": "params", - "type": "bytes" - } - ], - "indexed": false, - "internalType": "struct LimitOrderLibrary.Condition[]", - "name": "closeConditions", - "type": "tuple[]" - } - ], - "name": "OpenPosition", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "positionId", - "type": "uint256" - }, - { - "indexed": true, - "internalType": "address", - "name": "trader", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "closedBy", - "type": "address" - }, - { - "indexed": false, - "internalType": "address", - "name": "bucketAddress", - "type": "address" - }, - { - "indexed": false, - "internalType": "address", - "name": "soldAsset", - "type": "address" - }, - { - "indexed": false, - "internalType": "address", - "name": "positionAsset", - "type": "address" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "decreasePositionAmount", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "int256", - "name": "profit", - "type": "int256" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "positionDebt", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "amountOut", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "enum PositionLibrary.CloseReason", - "name": "reason", - "type": "uint8" - } - ], - "name": "ClosePosition", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "positionId", - "type": "uint256" - }, - { - "indexed": true, - "internalType": "address", - "name": "trader", - "type": "address" - }, - { - "indexed": false, - "internalType": "address", - "name": "bucketAddress", - "type": "address" - }, - { - "indexed": false, - "internalType": "address", - "name": "soldAsset", - "type": "address" - }, - { - "indexed": false, - "internalType": "address", - "name": "positionAsset", - "type": "address" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "decreasePositionAmount", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "depositedAmount", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "scaledDebtAmount", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "int256", - "name": "profit", - "type": "int256" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "positionDebt", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "amountOut", - "type": "uint256" - } - ], - "name": "PartialClosePosition", - "type": "event" - } -] + swap: "0x5fcf6637f014854f918b233372226c5492e6a5157e517674a8588675550c40c6", + openPosition: + "0x3f505465ce78d219c28bcf9bed881a651c4800d1161454b0d5c93225196e7b8e", + openPositionV2: + "0x7eb8abd0eb2f629d9150adef2d047584ab0d0830368a1d5d5243955f73f884e7", + partiallyClosePosition: + "0xda47f84a849dfb28125ae28a0bf305b75e72bff27796fc4bca36e2f848b0a0e6", + closePosition: + "0x4a06c6510972c5a49ff5582d7d8e59f20228038c8cb9ea05d78f02ac7ee40662", +}; -export { config, topics, abi } \ No newline at end of file +export { config, topics }; diff --git a/dexs/protofi/index.ts b/dexs/protofi/index.ts index 010e856593..688dada2b7 100644 --- a/dexs/protofi/index.ts +++ b/dexs/protofi/index.ts @@ -1,8 +1,9 @@ +import * as sdk from "@defillama/sdk"; import { CHAIN } from "../../helpers/chains"; import { univ2Adapter } from "../../helpers/getUniSubgraphVolume"; export default univ2Adapter({ - [CHAIN.FANTOM]: "https://api.thegraph.com/subgraphs/name/theothercrypto/protofi-dex-fantom", + [CHAIN.FANTOM]: sdk.graph.modifyEndpoint('6D3HgYNegniVRGGF1cceiZ6Kg3KWGNzQCqjWMtZu7wTQ'), }, { factoriesName: "pancakeFactories", dayData: "pancakeDayData", diff --git a/dexs/pulsex-v2/index.ts b/dexs/pulsex-v2/index.ts index 8c2ca1150d..1ae6dd8092 100644 --- a/dexs/pulsex-v2/index.ts +++ b/dexs/pulsex-v2/index.ts @@ -1,11 +1,10 @@ import { CHAIN } from "../../helpers/chains"; -import { univ2Adapter } from "../../helpers/getUniSubgraphVolume"; +import { univ2Adapter2 } from "../../helpers/getUniSubgraphVolume"; -const adapters = univ2Adapter({ +const adapters = univ2Adapter2({ [CHAIN.PULSECHAIN]: "https://graph.pulsechain.com/subgraphs/name/pulsechain/pulsexv2" }, { factoriesName: "pulseXFactories", - dayData: "pulsexDayData", }); adapters.adapter.pulse.start = 1685577600; diff --git a/dexs/pyeswap/index.ts b/dexs/pyeswap/index.ts index 9327367f8d..f508764c30 100644 --- a/dexs/pyeswap/index.ts +++ b/dexs/pyeswap/index.ts @@ -1,8 +1,9 @@ +import * as sdk from "@defillama/sdk"; import { CHAIN } from "../../helpers/chains"; import { univ2Adapter } from "../../helpers/getUniSubgraphVolume"; const adapter = univ2Adapter({ - [CHAIN.BSC]: "https://api.thegraph.com/subgraphs/name/officialdevteamsix/pyeswap" + [CHAIN.BSC]: sdk.graph.modifyEndpoint('56dMe6VDoxCisTvkgXw8an3aQbGR8oGhR292hSu6Rh3K') }, { factoriesName: "pyeFactories", dayData: "pyeDayData", diff --git a/dexs/quickswap/index.ts b/dexs/quickswap/index.ts index a873d09f94..2430984f86 100644 --- a/dexs/quickswap/index.ts +++ b/dexs/quickswap/index.ts @@ -1,11 +1,20 @@ +import * as sdk from "@defillama/sdk"; import { BreakdownAdapter } from "../../adapters/types"; import { CHAIN } from "../../helpers/chains"; import { getGraphDimensions } from "../../helpers/getUniSubgraph"; -import { DEFAULT_DAILY_VOLUME_FACTORY, DEFAULT_DAILY_VOLUME_FIELD, DEFAULT_TOTAL_VOLUME_FACTORY, DEFAULT_TOTAL_VOLUME_FIELD, getChainVolume } from "../../helpers/getUniSubgraphVolume"; -import fetchURL from "../../utils/fetchURL" +import { + DEFAULT_DAILY_VOLUME_FACTORY, + DEFAULT_DAILY_VOLUME_FIELD, + DEFAULT_TOTAL_VOLUME_FACTORY, + DEFAULT_TOTAL_VOLUME_FIELD, + getChainVolume, +} from "../../helpers/getUniSubgraphVolume"; +import fetchURL from "../../utils/fetchURL"; const endpoints = { - [CHAIN.POLYGON]: "https://api.thegraph.com/subgraphs/name/sameepsi/quickswap06", + [CHAIN.POLYGON]: sdk.graph.modifyEndpoint( + "FUWdkXWpi8JyhAnhKL5pZcVshpxuaUQG8JHMDqNCxjPd", + ), }; const graphs = getChainVolume({ @@ -17,19 +26,27 @@ const graphs = getChainVolume({ dailyVolume: { factory: DEFAULT_DAILY_VOLUME_FACTORY, field: DEFAULT_DAILY_VOLUME_FIELD, - dateField: "date" + dateField: "date", }, + hasDailyVolume: true, }); const endpointsAlgebraV3 = { - [CHAIN.POLYGON]: "https://api.thegraph.com/subgraphs/name/sameepsi/quickswap-v3", + [CHAIN.POLYGON]: sdk.graph.modifyEndpoint( + "CCFSaj7uS128wazXMdxdnbGA3YQnND9yBdHjPtvH7Bc7", + ), // [CHAIN.DOGECHAIN]: "https://graph-node.dogechain.dog/subgraphs/name/quickswap/dogechain-info", - [CHAIN.POLYGON_ZKEVM]:"https://api.studio.thegraph.com/query/44554/quickswap-v3-02/0.0.7", - [CHAIN.MANTA]:"https://api.goldsky.com/api/public/project_clo2p14by0j082owzfjn47bag/subgraphs/quickswap/prod/gn" + [CHAIN.POLYGON_ZKEVM]: + "https://api.studio.thegraph.com/query/44554/quickswap-v3-02/0.0.7", + [CHAIN.MANTA]: + "https://api.goldsky.com/api/public/project_clo2p14by0j082owzfjn47bag/subgraphs/quickswap/prod/gn", }; const endpointsUniV3 = { - [CHAIN.MANTA]:"https://api.goldsky.com/api/public/project_clo2p14by0j082owzfjn47bag/subgraphs/quickswap/prod/gn" + [CHAIN.MANTA]: + "https://api.goldsky.com/api/public/project_clo2p14by0j082owzfjn47bag/subgraphs/quickswap/prod/gn", + [CHAIN.ASTAR_ZKEVM]: + "https://api.studio.thegraph.com/query/44554/astar-quickswap/version/latest", }; const graphsAlgebraV3 = getChainVolume({ @@ -41,7 +58,7 @@ const graphsAlgebraV3 = getChainVolume({ dailyVolume: { factory: "algebraDayData", field: "volumeUSD", - dateField: "date" + dateField: "date", }, }); @@ -65,36 +82,37 @@ const v3GraphsUni = getGraphDimensions({ }, }); - const fetchLiquidityHub = async (timestamp: number) => { - let dailyResult = (await fetchURL('https://hub.orbs.network/analytics-daily/v1')); - - let rows = dailyResult.result.rows; - let lastDay = rows[rows.length - 1]; - let dailyVolume = lastDay.daily_total_calculated_value; - let totalVolume = (await fetchURL(`https://hub.orbs.network/analytics/v1`)).result.rows[0].total_calculated_value; - - return { - dailyVolume: `${dailyVolume}`, - totalVolume: `${totalVolume}`, - timestamp: timestamp, - }; + let dailyResult = await fetchURL( + "https://hub.orbs.network/analytics-daily/v1", + ); -} + let rows = dailyResult.result.rows; + let lastDay = rows[rows.length - 1]; + let dailyVolume = lastDay.daily_total_calculated_value; + let totalVolume = (await fetchURL(`https://hub.orbs.network/analytics/v1`)) + .result.rows[0].total_calculated_value; + return { + dailyVolume: `${dailyVolume}`, + totalVolume: `${totalVolume}`, + timestamp: timestamp, + }; +}; const adapter: BreakdownAdapter = { + version: 1, breakdown: { v2: { [CHAIN.POLYGON]: { fetch: graphs(CHAIN.POLYGON), - start: 1602118043 + start: 1602118043, }, }, v3: { [CHAIN.POLYGON]: { fetch: graphsAlgebraV3(CHAIN.POLYGON), - start: 1662425243 + start: 1662425243, }, // [CHAIN.DOGECHAIN]: { // fetch: graphsV3(CHAIN.DOGECHAIN), @@ -102,17 +120,17 @@ const adapter: BreakdownAdapter = { // }, [CHAIN.POLYGON_ZKEVM]: { fetch: graphsAlgebraV3(CHAIN.POLYGON_ZKEVM), - start: 1679875200 + start: 1679875200, }, [CHAIN.MANTA]: { fetch: v3GraphsUni(CHAIN.MANTA), - start: 1697690974 - } + start: 1697690974, + }, }, liquidityHub: { [CHAIN.POLYGON]: { fetch: fetchLiquidityHub, - start: 1695042000 + start: 1695042000, }, }, }, diff --git a/dexs/rabbitx/index.ts b/dexs/rabbitx/index.ts index c5bcee11f0..55c33b8893 100644 --- a/dexs/rabbitx/index.ts +++ b/dexs/rabbitx/index.ts @@ -1,10 +1,11 @@ import fetchURL from "../../utils/fetchURL" import { FetchResultVolume, SimpleAdapter } from "../../adapters/types"; import { CHAIN } from "../../helpers/chains"; +import { getTimestampAtStartOfDay, getTimestampAtStartOfDayUTC, getTimestampAtStartOfNextDayUTC } from "../../utils/date"; const historicalVolumeEndpoint = "https://api.prod.rabbitx.io/markets" const candles = (market: string, timestampFrom: number, timestampTo: number) => { - const url = `https://api.prod.rabbitx.io/candles?market_id=${market}×tamp_from=${timestampFrom}×tamp_to=${timestampTo}&period=1440`; +const url = `https://api.prod.rabbitx.io/candles?market_id=${market}×tamp_from=${timestampFrom}×tamp_to=${timestampTo}&period=1440`; return url; } @@ -16,8 +17,8 @@ interface IVolumeall { } const fetchVolume = async (timestamp: number): Promise => { - const fromTimestamp = timestamp - 60 * 60 * 24 - const toTimestamp = timestamp + const fromTimestamp = getTimestampAtStartOfDayUTC(timestamp); + const toTimestamp = getTimestampAtStartOfNextDayUTC(fromTimestamp) - 1; // Get market data const response = await fetchURL(historicalVolumeEndpoint); @@ -42,7 +43,7 @@ const fetchVolume = async (timestamp: number): Promise => { const adapter: SimpleAdapter = { adapter: { - [CHAIN.STARKNET]: { + [CHAIN.ETHEREUM]: { fetch: fetchVolume, start: 1700179200, // Replace with actual start timestamp }, diff --git a/dexs/radioshack/index.ts b/dexs/radioshack/index.ts index 6122343855..ef44771b8a 100644 --- a/dexs/radioshack/index.ts +++ b/dexs/radioshack/index.ts @@ -1,29 +1,27 @@ +import * as sdk from "@defillama/sdk"; import { SimpleAdapter } from "../../adapters/types"; import { CHAIN } from "../../helpers/chains"; import { getStartTimestamp } from "../../helpers/getStartTimestamp"; -import { DEFAULT_DAILY_VOLUME_FACTORY, DEFAULT_DAILY_VOLUME_FIELD, DEFAULT_TOTAL_VOLUME_FACTORY, DEFAULT_TOTAL_VOLUME_FIELD, getChainVolume } from "../../helpers/getUniSubgraphVolume"; +import { DEFAULT_DAILY_VOLUME_FACTORY, DEFAULT_DAILY_VOLUME_FIELD, DEFAULT_TOTAL_VOLUME_FACTORY, DEFAULT_TOTAL_VOLUME_FIELD, getChainVolume2 } from "../../helpers/getUniSubgraphVolume"; const endpoints = { - [CHAIN.POLYGON]: "https://api.thegraph.com/subgraphs/name/radioshackcreator/unigraph-polygon", - [CHAIN.BSC]: "https://api.thegraph.com/subgraphs/name/radioshackcreator/unigraph-bsc", - // [CHAIN.ETHEREUM]: "https://api.thegraph.com/subgraphs/name/radioshackcreator/unigraph-ethereum", - [CHAIN.AVAX]: "https://api.thegraph.com/subgraphs/name/radioshackcreator/unigraph-avalanche", - // [CHAIN.FANTOM]: "https://api.thegraph.com/subgraphs/name/radioshackcreator/unigraph-fantom", + [CHAIN.POLYGON]: sdk.graph.modifyEndpoint('743VoDTGxZ1m3QHC3BCnTkKcvXqo8PfyTSs6QGHgcQKd'), + [CHAIN.BSC]: sdk.graph.modifyEndpoint('xw8NYXanrWADWixeXQ8DBViHtEQvr85eAFcSADEmeDz'), + // [CHAIN.ETHEREUM]: sdk.graph.modifyEndpoint('EduCYTCLoqd93219xiiVLFmpWbv8T7CXKtQMRNKKEeTY'), + [CHAIN.AVAX]: sdk.graph.modifyEndpoint('ChLQrP8tJHHuFVHmKWoKfgUVNtYcbA7YAV1Y75Qjy6Sv'), + // [CHAIN.FANTOM]: sdk.graph.modifyEndpoint('CK42aJEkVpr5kS3wygQrpmDegNcRDbdqtkzNhzRLfW21'), }; -const graphs = getChainVolume({ +const graphs = getChainVolume2({ graphUrls: endpoints, totalVolume: { factory: DEFAULT_TOTAL_VOLUME_FACTORY, field: DEFAULT_TOTAL_VOLUME_FIELD, }, - dailyVolume: { - factory: DEFAULT_DAILY_VOLUME_FACTORY, - field: DEFAULT_DAILY_VOLUME_FIELD, - }, }); const adapter: SimpleAdapter = { + version: 2, adapter: { [CHAIN.POLYGON]: { fetch: graphs(CHAIN.POLYGON), diff --git a/dexs/ramses-exchange-v2/index.ts b/dexs/ramses-exchange-v2/index.ts index 16d81e682c..7695fbcd35 100644 --- a/dexs/ramses-exchange-v2/index.ts +++ b/dexs/ramses-exchange-v2/index.ts @@ -1,12 +1,11 @@ +import * as sdk from "@defillama/sdk"; import { CHAIN } from "../../helpers/chains"; -import { univ2Adapter } from "../../helpers/getUniSubgraphVolume"; +import { univ2Adapter2 } from "../../helpers/getUniSubgraphVolume"; -const adapters = univ2Adapter({ - [CHAIN.ARBITRUM]: "https://api.thegraph.com/subgraphs/name/ramsesexchange/concentrated-liquidity-graph" +const adapters = univ2Adapter2({ + [CHAIN.ARBITRUM]: sdk.graph.modifyEndpoint('G2tXDm6mgqBMuC7hq9GRVeTv5SRBAVnPFGcpGBab2cea') }, { factoriesName: "factories", - dayData: "uniswapDayData", - dailyVolume: "volumeUSD", totalVolume: "totalVolumeUSD", }); diff --git a/dexs/ramses-exchange/index.ts b/dexs/ramses-exchange/index.ts index 74cbe4cbbe..1c482a5d19 100644 --- a/dexs/ramses-exchange/index.ts +++ b/dexs/ramses-exchange/index.ts @@ -1,16 +1,6 @@ -import { SimpleAdapter } from "../../adapters/types"; import { CHAIN } from "../../helpers/chains"; -import { getDexVolumeExports } from "../../helpers/dexVolumeLogs"; +import { uniV2Exports } from "../../helpers/uniswap"; -const FACTORY_ADDRESS = '0xaaa20d08e59f6561f242b08513d36266c5a29415' - -const adapter: SimpleAdapter = { - adapter: { - [CHAIN.ARBITRUM]: { - fetch: getDexVolumeExports({ chain: CHAIN.ARBITRUM, factory: FACTORY_ADDRESS }), - start: 1678752000, - }, - } -}; - -export default adapter; +export default uniV2Exports({ + [CHAIN.ARBITRUM]: { factory: '0xaaa20d08e59f6561f242b08513d36266c5a29415', }, +}) diff --git a/dexs/raydium/index.ts b/dexs/raydium/index.ts index 3071b57556..b3e893f70a 100644 --- a/dexs/raydium/index.ts +++ b/dexs/raydium/index.ts @@ -1,33 +1,67 @@ -import { FetchResultVolume, SimpleAdapter } from "../../adapters/types"; +import { FetchResultFees, FetchResultVolume, SimpleAdapter } from "../../adapters/types"; +import fetchURL, { postURL } from "../../utils/fetchURL" -import fetchURL from "../../utils/fetchURL" +const graphs = async (timestamp: number): Promise => { + const ammPoolStandard: any[] = [ + ...(await fetchURL("https://api-v3.raydium.io/pools/info/list?poolType=all&poolSortField=default&sortType=desc&pageSize=1000&page=1")).data.data, + ...(await fetchURL("https://api-v3.raydium.io/pools/info/list?poolType=all&poolSortField=default&sortType=desc&pageSize=1000&page=2")).data.data, + ]; -const urlAmmPool = "https://api.raydium.io/v2/main/info"; -const urlAmmPoolStandard = "https://api.raydium.io/v2/ammV3/ammPools" + const dailyVolumeAmmPool = ammPoolStandard + .filter((i: any) => Number(i.tvl) > 100_000) + .reduce((a: number, b) => a + b.day.volume, 0) -interface IAmmPoool { - totalvolume: string; - volume24h: number; -} + let ammFee = 0 + let clmmFee = 0 + let cpmmFee = 0 + for (const item of ammPoolStandard.filter((i: any) => Number(i.tvl) > 100_000)){ + if (item.programId === 'CAMMCzo5YL8w4VFF8KVHrK22GGUsp5VTaW7grrKgrWqK') clmmFee += item.day.volumeFee + else if (item.programId === 'CPMMoo8L3F4NbTegBCKVNunggL7H1ZpdTHKxQB5qKP1C') cpmmFee += item.day.volumeFee + else ammFee += item.day.volumeFee + } -interface IAmmPooolStandar { - volume: number; - tvl: number; -} + const dailyVolumeAmmPoolFee = ammFee + clmmFee + cpmmFee -const graphs = async (timestamp: number): Promise => { - const ammPool: IAmmPoool = (await fetchURL(urlAmmPool)); - const ammPoolStandard: any[] = (await fetchURL(urlAmmPoolStandard)).data;; - const ammPoolStandardVolume: IAmmPooolStandar[] = ammPoolStandard.map((e: any) => e.day); - const dailyVolumeAmmPool = ammPoolStandardVolume - .filter((e: IAmmPooolStandar) => e.tvl > 100_000) - .reduce((a: number, b: IAmmPooolStandar) => a + b.volume, 0) - const dailyVolume = ammPool?.volume24h ? ammPool?.volume24h + dailyVolumeAmmPool: undefined; - const fiveBill = 3_000_000_000; // set the threshold to 3B + const dailyRevenueFund = ammFee * 0.03 + clmmFee * 0.04 + cpmmFee * 0.04 + const dailyRevenueProtocol = ammFee * 0.0 + clmmFee * 0.12 + cpmmFee * 0.12 + + // const buyRay = await postURL('https://explorer-api.mainnet-beta.solana.com/', JSON.stringify({ + const buyRay = await postURL('https://api.mainnet-beta.solana.com', JSON.stringify({ + "jsonrpc": "2.0", + "id": 123, + "method": "getMultipleAccounts", + "params": [ + [ + "G7rxL8ySm5qPbtTus9FhAn2nEAZn8DDsUEeHGXgWTP1x", + "BnTSNB2VqsUGiauSfwfyQBdFwPYnteb1M69Y1VXziP5u", + "FpDWkidnRD6pWzYZAnDWEU3kC1hXSmQSqhd9w4nMCn1", + "E5BMFn1mzTGuFWzNHZ7cybWfzetmqhFKS7SM91N5WePU", + "BEVT2yGq2rvvPCnMipktFWxJaouidExC7scW9GHhMuzi", + ], + { + "encoding": "jsonParsed" + } + ] + }), 3, {headers: {'content-type': 'application/json'}}) + + const buyRayAll = buyRay.result.value.map((i: any) => i?.data?.parsed?.info?.tokenAmount?.uiAmount ?? 0).reduce((a: number,b: number) => a + b, 0) + + const rayPrice = (await fetchURL('https://api-v3.raydium.io/mint/price?mints=4k3Dyjzvzp8eMZWUXbBCjEvwSkkk59S5iCNLY3QrkX6R'))?.data['4k3Dyjzvzp8eMZWUXbBCjEvwSkkk59S5iCNLY3QrkX6R'] ?? 0 return { - dailyVolume: dailyVolume ? `${dailyVolume < fiveBill ? dailyVolume : undefined}`: undefined, + dailyVolume: `${dailyVolumeAmmPool}`, timestamp: timestamp, + totalFees: `${dailyVolumeAmmPoolFee}`, + dailyFees: `${dailyVolumeAmmPoolFee}`, + dailyUserFees: `${dailyVolumeAmmPoolFee}`, + totalRevenue: `${dailyRevenueFund + dailyRevenueProtocol}`, + dailyRevenue: `${dailyRevenueFund + dailyRevenueProtocol}`, + dailyProtocolRevenue: `${dailyRevenueFund + dailyRevenueProtocol}`, + // dailyHoldersRevenue: `${buyRayAll * rayPrice}`, // seem it total value not daily + dailySupplySideRevenue: `${dailyVolumeAmmPoolFee - dailyRevenueFund - dailyRevenueProtocol}`, + totalProtocolRevenue: `${dailyRevenueFund + dailyRevenueProtocol}`, + totalSupplySideRevenue: `${dailyVolumeAmmPoolFee - dailyRevenueFund - dailyRevenueProtocol}`, + totalUserFees: `${dailyVolumeAmmPoolFee}`, }; }; @@ -35,11 +69,9 @@ const adapter: SimpleAdapter = { adapter: { solana: { fetch: graphs, - // runAtCurrTime: true, - customBackfill: undefined, + runAtCurrTime: true, start: 1660521600, }, - // TODO custom backfill }, }; diff --git a/dexs/reax-one-dex/index.ts b/dexs/reax-one-dex/index.ts index 392352c72c..18c261941a 100644 --- a/dexs/reax-one-dex/index.ts +++ b/dexs/reax-one-dex/index.ts @@ -1,9 +1,8 @@ import { ChainEndpoints, SimpleAdapter } from "../../adapters/types"; -import { getChainVolume } from "../../helpers/getUniSubgraphVolume"; +import { getChainVolume2 } from "../../helpers/getUniSubgraphVolume"; import customBackfill from "../../helpers/customBackfill"; import { CHAIN } from "../../helpers/chains"; import { Chain } from "@defillama/sdk/build/general"; -import { getStartTimestamp } from "../../helpers/getStartTimestamp"; const endpoints: ChainEndpoints = { [CHAIN.MANTLE]: "https://subgraph-api.mantle.xyz/subgraphs/name/reax/swaps-1", @@ -14,16 +13,16 @@ const graphParams = { factory: "balancers", field: "totalSwapVolume", }, - hasDailyVolume: false, } -const graphs = getChainVolume({ +const graphs = getChainVolume2({ graphUrls: endpoints, ...graphParams }); const adapter: SimpleAdapter = { + version: 2, adapter: Object.keys(endpoints).reduce((acc, chain: any) => { return { ...acc, diff --git a/dexs/ref-finance/index.ts b/dexs/ref-finance/index.ts index 65adbb8c6d..1ec6f27ffe 100644 --- a/dexs/ref-finance/index.ts +++ b/dexs/ref-finance/index.ts @@ -1,4 +1,4 @@ -import type { SimpleAdapter } from "../../adapters/types"; +import type { FetchOptions, SimpleAdapter } from "../../adapters/types"; import { getUniqStartOfTodayTimestamp } from "../../helpers/getUniSubgraphVolume"; import { httpGet } from "../../utils/fetchURL"; @@ -13,16 +13,20 @@ const adapter: SimpleAdapter = { const data = await httpGet(api) return dateToTs(data[0].date) }, - fetch: async(ts)=>{ + fetch: async(ts, _t: any, options: FetchOptions)=>{ const data = await httpGet(api) - const cleanTimestamp = getUniqStartOfTodayTimestamp(new Date(ts * 1000)) + const dateStr = new Date(options.startOfDay * 1000).toISOString().split('T')[0] + const dailyVolume = data.find((t:any)=> t.date.split('T')[0] === dateStr)?.volume + if (!dailyVolume || Number(dailyVolume) < 0 || Number((dailyVolume)) > 1_000_000_000) { + throw new Error(`Invalid daily volume: ${dailyVolume}`) + } return { - timestamp: cleanTimestamp, - dailyVolume: data.find((t:any)=>dateToTs(t.date) === cleanTimestamp)?.volume + timestamp: options.startOfDay , + dailyVolume: dailyVolume } } } } }; -export default adapter; \ No newline at end of file +export default adapter; diff --git a/dexs/retro/index.ts b/dexs/retro/index.ts index 38797f1c8b..034b8e110e 100644 --- a/dexs/retro/index.ts +++ b/dexs/retro/index.ts @@ -1,21 +1,18 @@ +import * as sdk from "@defillama/sdk"; import { SimpleAdapter } from "../../adapters/types"; import { CHAIN } from "../../helpers/chains"; -import { DEFAULT_DAILY_VOLUME_FACTORY, DEFAULT_TOTAL_VOLUME_FIELD, getGraphDimensions } from "../../helpers/getUniSubgraph"; +import { DEFAULT_TOTAL_VOLUME_FIELD, getGraphDimensions2 } from "../../helpers/getUniSubgraph"; const endpointV3 = { - [CHAIN.POLYGON]: 'https://api.thegraph.com/subgraphs/name/ruvlol/univ3-test' + [CHAIN.POLYGON]: sdk.graph.modifyEndpoint('DZyDuvUHNThtJJQAEbYGr32xYc93BZAdfqatpYUNMZbe') } -const VOLUME_USD = 'volumeUSD' -const v3Graphs = getGraphDimensions({ + +const v3Graphs = getGraphDimensions2({ graphUrls: endpointV3, totalVolume: { factory: "factories", field: DEFAULT_TOTAL_VOLUME_FIELD, }, - dailyVolume: { - factory: DEFAULT_DAILY_VOLUME_FACTORY, - field: VOLUME_USD, - }, feesPercent: { type: "fees", ProtocolRevenue: 10, @@ -27,6 +24,7 @@ const v3Graphs = getGraphDimensions({ }); const adapters: SimpleAdapter = { + version: 2, adapter: { [CHAIN.POLYGON]: { fetch: v3Graphs(CHAIN.POLYGON), diff --git a/dexs/revoswap/index.ts b/dexs/revoswap/index.ts new file mode 100644 index 0000000000..67636a29e5 --- /dev/null +++ b/dexs/revoswap/index.ts @@ -0,0 +1,16 @@ +import { univ2Adapter } from "../../helpers/getUniSubgraphVolume"; +import { CHAIN } from "../../helpers/chains"; + +const endpoints = { + [CHAIN.XLAYER]: "https://graph.revoswap.com/subgraphs/name/okx-mainnet/exchange", +}; + +const adapter = univ2Adapter(endpoints, { + factoriesName: "pancakeFactories", + dayData: "pancakeDayData" +}); + +adapter.adapter[CHAIN.XLAYER].start = 1713225600; + + +export default adapter diff --git a/dexs/rollie-finance/index.ts b/dexs/rollie-finance/index.ts new file mode 100644 index 0000000000..a773cb7ed7 --- /dev/null +++ b/dexs/rollie-finance/index.ts @@ -0,0 +1,63 @@ +import request, { gql } from 'graphql-request'; +import {FetchOptions, FetchResultV2, FetchV2, SimpleAdapter} from '../../adapters/types'; +import { CHAIN } from '../../helpers/chains'; +import { + getUniqStartOfTodayTimestamp, +} from '../../helpers/getUniSubgraphVolume'; + +const ENDPOINTS: { [key: string]: string } = { + [CHAIN.SCROLL]: 'https://api.studio.thegraph.com/query/76203/rollie-finance/0.0.3/', +}; +const USDC_DECIMALS: { [key: string]: number } = { + [CHAIN.SCROLL]: 6, +}; + +const getVolume = gql` + query get_volume($id: String!) { + market(id: "1") { + id + tradeVolume + marketDayDatas(where: {id: $id}) { + id + tradeVolume + } + } + } +`; + + +const getFetch = (chain: string): FetchV2 => async (options: FetchOptions): Promise => { + const { startTimestamp} = options; + const dayTimestamp = getUniqStartOfTodayTimestamp( + new Date(startTimestamp * 1000) + ); + const dayIndex = Math.floor(options.startOfDay / 86400); + const { market: response } = await request(ENDPOINTS[chain], + getVolume, { + id: String(dayIndex), + }); + + return { + timestamp: getUniqStartOfTodayTimestamp(new Date(dayTimestamp)), + dailyVolume: + response.marketDayDatas.length === 1 + ? (BigInt(response.marketDayDatas[0].tradeVolume) / + BigInt(10 ** USDC_DECIMALS[chain])).toString() + : '0', + totalVolume: (BigInt(response.tradeVolume) / + BigInt(10 ** USDC_DECIMALS[chain])).toString(), + + }; +}; + +const adapter: SimpleAdapter = { + version: 2, + adapter: { + [CHAIN.SCROLL]: { + fetch: getFetch(CHAIN.SCROLL), + start: 1715212800, + }, + }, +}; + +export default adapter; diff --git a/dexs/rollup-finace/index.ts b/dexs/rollup-finace/index.ts index e54ab18b66..19834d5916 100644 --- a/dexs/rollup-finace/index.ts +++ b/dexs/rollup-finace/index.ts @@ -1,7 +1,9 @@ import request, { gql } from "graphql-request"; -import { BreakdownAdapter, Fetch, SimpleAdapter } from "../../adapters/types"; +import { BreakdownAdapter, DISABLED_ADAPTER_KEY, Fetch, SimpleAdapter } from "../../adapters/types"; import { CHAIN } from "../../helpers/chains"; import { getUniqStartOfTodayTimestamp } from "../../helpers/getUniSubgraphVolume"; +import disabledAdapter from "../../helpers/disabledAdapter"; +import { httpGet } from "../../utils/fetchURL"; const endpoints: { [key: string]: string } = { [CHAIN.ERA]: "https://subgraph.rollup.finance/subgraphs/name/rollUp/stats", @@ -25,41 +27,24 @@ const historicalDataDerivatives = gql` ` interface IGraphResponse { - volumeStats: Array<{ + list: Array<{ burn: string, liquidation: string, margin: string, mint: string, swap: string, + period: string }> } -const getFetch = (query: string)=> (chain: string): Fetch => async (timestamp: number) => { - const dayTimestamp = getUniqStartOfTodayTimestamp(new Date((timestamp * 1000))) - const fromTimestamp = dayTimestamp - 60 * 60 * 24 - const dailyData: IGraphResponse = await request(endpoints[chain], query, { - id: String(dayTimestamp), - period: 'daily', - }) - const yesterDay: IGraphResponse = await request(endpoints[chain], query, { - id: String(fromTimestamp), - period: 'daily', - }) - const totalData: IGraphResponse = await request(endpoints[chain], query, { - id: 'total', - period: 'total', - }) - const todayVolume = Number(Object.values(dailyData.volumeStats[0]).reduce((sum, element) => String(Number(sum) + Number(element)))) * 10 ** -30 - const yesterdayVolume = Number(Object.values(yesterDay.volumeStats[0]).reduce((sum, element) => String(Number(sum) + Number(element)))) * 10 ** -30 - const dailyVolume = (todayVolume - yesterdayVolume); +const fetchDerivatives = async (timestamp: number) => { + const data: IGraphResponse = (await httpGet("https://terminal.rollup.finance/analy-v1/analytics/volume?pageNum=1&pageSize=32")).data + const dataItem = data.list.find((e) => e.period === getUniqStartOfTodayTimestamp(new Date(timestamp * 1000)).toString()) + const dailyVolume = Number(dataItem?.liquidation || 0) + Number(dataItem?.margin || 0) return { - timestamp: dayTimestamp, - dailyVolume: `${dailyVolume}`, - totalVolume: - totalData.volumeStats.length == 1 - ? String(Number(Object.values(totalData.volumeStats[0]).reduce((sum, element) => String(Number(sum) + Number(element)))) * 10 ** -30) - : undefined, + dailyFees: dailyVolume.toString(), + timestamp } } @@ -82,7 +67,7 @@ const adapter: BreakdownAdapter = { return { ...acc, [chain]: { - fetch: getFetch(historicalDataDerivatives)(chain), + fetch: fetchDerivatives, start: startTimestamps[chain] } } diff --git a/dexs/rubicon/index.ts b/dexs/rubicon/index.ts index 72f077d461..189fbbe5cf 100644 --- a/dexs/rubicon/index.ts +++ b/dexs/rubicon/index.ts @@ -1,17 +1,77 @@ import { CHAIN } from "../../helpers/chains"; -import { univ2Adapter } from "../../helpers/getUniSubgraphVolume"; +import { univ2Adapter, univ2Adapter2 } from "../../helpers/getUniSubgraphVolume"; -const adapters = univ2Adapter({ - [CHAIN.ARBITRUM]: "https://api.thegraph.com/subgraphs/name/jossduff/rubiconmetricsarbitrum", - [CHAIN.OPTIMISM]: "https://api.thegraph.com/subgraphs/name/denverbaumgartner/rubiconmetricsoptimism" +// Define the old and new adapters +const adapterOld = univ2Adapter2({ + [CHAIN.ARBITRUM]: 'https://graph-v2.rubicon.finance/subgraphs/name/Metrics_Arbitrum_V2', + [CHAIN.OPTIMISM]: 'https://graph-v2.rubicon.finance/subgraphs/name/Metrics_Optimism_V2' }, { factoriesName: "rubicons", totalVolume: "total_volume_usd", - dayData: "dayVolume", - dailyVolume: "volume_usd", - dailyVolumeTimestampField: "dayStartUnix" }); -adapters.adapter.arbitrum.start = 1686345120; -adapters.adapter.optimism.start = 1637020800; -export default adapters; \ No newline at end of file +adapterOld.adapter.arbitrum.start = 0; +adapterOld.adapter.optimism.start = 0; + +const adapterNew = univ2Adapter2({ + [CHAIN.OPTIMISM]: 'https://graph-v2.rubicon.finance/subgraphs/name/Gladius_Metrics_Optimism_V2', + [CHAIN.ARBITRUM]: 'https://graph-v2.rubicon.finance/subgraphs/name/Gladius_Metrics_Arbitrum_V2', + [CHAIN.BASE]: 'https://graph-v2.rubicon.finance/subgraphs/name/Gladius_Metrics_Base_V2', + [CHAIN.ETHEREUM]: 'https://graph-v2.rubicon.finance/subgraphs/name/Gladius_Metrics_Mainnet_V2', +}, { + factoriesName: "rubicons", + totalVolume: "total_volume_usd", +}); + +adapterNew.adapter.arbitrum.start = 183178326; +adapterNew.adapter.optimism.start = 116354792; +adapterNew.adapter.base.start = 10029602; +adapterNew.adapter.ethereum.start = 19361393; + +// Define the function to fetch and combine data from both adapters +async function combinedFetch(chain, timestamp, chainBlocks, options) { + let oldData = null; + let newData = null; + + if (adapterOld.adapter[chain] && adapterOld.adapter[chain].fetch) { + oldData = await adapterOld.adapter[chain].fetch(timestamp, chainBlocks, options).catch(() => null); + } + + if (adapterNew.adapter[chain] && adapterNew.adapter[chain].fetch) { + newData = await adapterNew.adapter[chain].fetch(timestamp, chainBlocks, options).catch(() => null); + } + + if (!oldData) return newData; + if (!newData) return oldData; + + return { + totalVolume: (oldData.totalVolume || 0) + (newData.totalVolume || 0), + dailyVolume: (oldData.dailyVolume || 0) + (newData.dailyVolume || 0), + // Add any other fields that need to be combined here + }; +} + +// Create the combined adapter +const combinedAdapter = { + adapter: { + [CHAIN.ARBITRUM]: { + fetch: (timestamp, chainBlocks, options) => combinedFetch(CHAIN.ARBITRUM, timestamp, chainBlocks, options), + start: adapterOld.adapter.arbitrum.start, + }, + [CHAIN.OPTIMISM]: { + fetch: (timestamp, chainBlocks, options) => combinedFetch(CHAIN.OPTIMISM, timestamp, chainBlocks, options), + start: adapterOld.adapter.optimism.start, + }, + [CHAIN.BASE]: { + fetch: (timestamp, chainBlocks, options) => adapterNew.adapter.base.fetch(timestamp, chainBlocks, options), + start: adapterNew.adapter.base.start, + }, + [CHAIN.ETHEREUM]: { + fetch: (timestamp, chainBlocks, options) => adapterNew.adapter.ethereum.fetch(timestamp, chainBlocks, options), + start: adapterNew.adapter.ethereum.start, + }, + }, + version: 2, +}; + +export default combinedAdapter; diff --git a/dexs/ryze/index.ts b/dexs/ryze/index.ts index ab9c868604..76ee52ed26 100644 --- a/dexs/ryze/index.ts +++ b/dexs/ryze/index.ts @@ -1,3 +1,4 @@ +import * as sdk from "@defillama/sdk"; import { ChainEndpoints, FetchResultVolume, SimpleAdapter } from "../../adapters/types"; import { CHAIN } from "../../helpers/chains"; import { Chain } from "@defillama/sdk/build/general"; @@ -6,7 +7,7 @@ import request, { gql } from "graphql-request"; import { getBlock } from "../../helpers/getBlock"; const endpoints: ChainEndpoints = { - [CHAIN.ARBITRUM]: "https://api.thegraph.com/subgraphs/name/chinu-dev/ryze-dashboard-subgraph-prod", + [CHAIN.ARBITRUM]: sdk.graph.modifyEndpoint('3MwM7j7s5EMrXE3uA5WUKU9GR4pfegirg4tSWTVMLwTK'), }; interface IPoolSnapshot { diff --git a/dexs/saddle-finance/index.ts b/dexs/saddle-finance/index.ts index d952a8cc8b..f722d6b6ae 100644 --- a/dexs/saddle-finance/index.ts +++ b/dexs/saddle-finance/index.ts @@ -1,27 +1,24 @@ +import * as sdk from "@defillama/sdk"; import { SimpleAdapter } from "../../adapters/types"; -import { getChainVolume } from "../../helpers/getUniSubgraphVolume"; +import { getChainVolume2 } from "../../helpers/getUniSubgraphVolume"; import { CHAIN } from "../../helpers/chains"; const endpoints = { - [CHAIN.ETHEREUM]: "https://api.thegraph.com/subgraphs/name/saddle-finance/saddle", - [CHAIN.ARBITRUM]: "https://api.thegraph.com/subgraphs/name/saddle-finance/saddle-arbitrum" + [CHAIN.ETHEREUM]: sdk.graph.modifyEndpoint('79UL5SaLLsbXqC8Ks6v3fwWHR1FRs636FFRHn55o5SWq'), + [CHAIN.ARBITRUM]: sdk.graph.modifyEndpoint('AB2t32R1htdcguMQVVGt4biKGFeQ2HfXkEgJNkKi1dJa') }; -const graphs = getChainVolume({ +const graphs = getChainVolume2({ graphUrls: endpoints, totalVolume: { factory: "tradeVolumes", field: "volume", }, - dailyVolume: { - factory: "dailyVolume", - field: "volume", - dateField: "timestamp" - }, }); const adapter: SimpleAdapter = { + version: 2, adapter: { [CHAIN.ARBITRUM]: { fetch: graphs(CHAIN.ARBITRUM), diff --git a/dexs/satori/index.ts b/dexs/satori/index.ts index 4899861d61..f5ec32d2b3 100644 --- a/dexs/satori/index.ts +++ b/dexs/satori/index.ts @@ -3,11 +3,13 @@ import { SimpleAdapter } from "../../adapters/types"; import { CHAIN } from "../../helpers/chains"; -const ZKEVM_URL = 'https://zksync.satori.finance/api/data-center/pub/overview/integration' +const ZKEVM_URL = 'https://zkevm.satori.finance/api/data-center/pub/overview/integration' const ZkSYNC_URL = 'https://zksync.satori.finance/api/data-center/pub/overview/integration' const SCROLL_URL = 'https://scroll.satori.finance/api/data-center/pub/overview/integration' const LINEA_URL = 'https://linea.satori.finance/api/data-center/pub/overview/integration' - +const BASE_URL = 'https://base.satori.finance/api/data-center/pub/overview/integration' +const ARBITRUM_URL = 'https://arbitrum.satori.finance/api/data-center/pub/overview/integration' +const XLARY_URL = 'https://xlayer.satori.finance/api/data-center/pub/overview/integration' interface VolumeInfo { fee24h: string; tradVol24h: string; @@ -28,6 +30,15 @@ const scroll = { const linea = { "exchange":"linea" } +const base = { + "exchange":"base" +} +const arbitrum = { + "exchange":"arbitrum-one" +} +const xlayer = { + "exchange":"xlayer" +} const evm_fetch = async (_timestamp: number) => { const volumeData: VolumeInfo = (await postURL(ZKEVM_URL,zk_evm)).data; @@ -53,7 +64,7 @@ const era_fetch = async (_timestamp: number) => { }; const linea_fetch = async (_timestamp: number) => { - const volumeData: VolumeInfo = (await postURL(ZkSYNC_URL,linea)).data; + const volumeData: VolumeInfo = (await postURL(LINEA_URL,linea)).data; return { totalVolume: volumeData.totalTradVol, @@ -65,7 +76,43 @@ const linea_fetch = async (_timestamp: number) => { }; const scroll_fetch = async (_timestamp: number) => { - const volumeData: VolumeInfo = (await postURL(ZkSYNC_URL,scroll)).data; + const volumeData: VolumeInfo = (await postURL(SCROLL_URL,scroll)).data; + + return { + totalVolume: volumeData.totalTradVol, + dailyVolume: volumeData.tradVol24h, + dailyFees: volumeData.fee24h, + dailyRevenue : volumeData.fee24h, + timestamp: parseInt(volumeData.time), + }; +}; + +const base_fetch = async (_timestamp: number) => { + const volumeData: VolumeInfo = (await postURL(BASE_URL,base)).data; + + return { + totalVolume: volumeData.totalTradVol, + dailyVolume: volumeData.tradVol24h, + dailyFees: volumeData.fee24h, + dailyRevenue : volumeData.fee24h, + timestamp: parseInt(volumeData.time), + }; +}; + +const arbitrum_fetch = async (_timestamp: number) => { + const volumeData: VolumeInfo = (await postURL(ARBITRUM_URL,arbitrum)).data; + + return { + totalVolume: volumeData.totalTradVol, + dailyVolume: volumeData.tradVol24h, + dailyFees: volumeData.fee24h, + dailyRevenue : volumeData.fee24h, + timestamp: parseInt(volumeData.time), + }; +}; + +const xlayer_fetch = async (_timestamp: number) => { + const volumeData: VolumeInfo = (await postURL(XLARY_URL,xlayer)).data; return { totalVolume: volumeData.totalTradVol, @@ -96,6 +143,21 @@ const adapter: SimpleAdapter = { fetch:scroll_fetch, runAtCurrTime: true, start: 1684003134, + }, + [CHAIN.BASE]: { + fetch:base_fetch, + runAtCurrTime: true, + start: 1684003134, + }, + [CHAIN.ARBITRUM]: { + fetch:arbitrum_fetch, + runAtCurrTime: true, + start: 1684003134, + }, + [CHAIN.XLAYER]: { + fetch:xlayer_fetch, + runAtCurrTime: true, + start: 1684003134, } }, }; diff --git a/dexs/saturnswap/index.ts b/dexs/saturnswap/index.ts new file mode 100644 index 0000000000..d90d82d50d --- /dev/null +++ b/dexs/saturnswap/index.ts @@ -0,0 +1,27 @@ +import fetchURL from "../../utils/fetchURL"; +import { CHAIN } from "../../helpers/chains"; +import { FetchResultVolume, SimpleAdapter } from "../../adapters/types"; + +const fetch = async (timestamp: any): Promise => { + const startOfDay = timestamp.startOfDay; + const response: any = await fetchURL( + `https://api.saturnswap.io/v1/defillama/volume?timestamp=${startOfDay}` + ); + const dailyVolume = response.volume.volume; + return { + dailyVolume: `${dailyVolume}`, + timestamp: startOfDay, + }; +}; + +const adapter: SimpleAdapter = { + version: 2, + adapter: { + [CHAIN.CARDANO]: { + fetch, + start: 1718251200, + }, + }, +}; + +export default adapter; diff --git a/dexs/savmswap/index.ts b/dexs/savmswap/index.ts new file mode 100644 index 0000000000..30d4e502e5 --- /dev/null +++ b/dexs/savmswap/index.ts @@ -0,0 +1,11 @@ +import { CHAIN } from "../../helpers/chains"; +import { univ2Adapter } from "../../helpers/getUniSubgraphVolume"; + +const adapter = univ2Adapter({ + [CHAIN.SVM]: "https://subgraph.8gr.xyz/subgraphs/name/savmswap/savmswap", +}, { + hasTotalVolume: false, +}); + +adapter.adapter.svm.start = 1711411200 +export default adapter diff --git a/dexs/seiyan-fun/index.ts b/dexs/seiyan-fun/index.ts new file mode 100644 index 0000000000..6491a70dce --- /dev/null +++ b/dexs/seiyan-fun/index.ts @@ -0,0 +1,33 @@ +import fetchURL from "../../utils/fetchURL"; +import { CHAIN } from "../../helpers/chains"; +import { FetchOptions } from "../../adapters/types"; + +const SEIYAN_FUN_BASE_URL = "https://seiyan.fun/api/public/v1"; +const SEI_PACIFIC_CAIP_CHAIN_ID = "cosmos:sei-pacific-1"; +const SEIYAN_FUN_INITIAL_TIMESTAMP = 1722470400; // 2024-08-01 00:00:00 UTC + +const buildTradingVolumeUrl = (startAt: number, endAt: number) => + `${SEIYAN_FUN_BASE_URL}/trading-volume?caipChainID=${SEI_PACIFIC_CAIP_CHAIN_ID}&startAt=${startAt}&endAt=${endAt}`; + +const fetch = async (timestamp: number, _t: any, options: FetchOptions) => { + const dayStart = options.startOfDay; + const nextDayStart = dayStart + 86400; + const url = buildTradingVolumeUrl(dayStart, nextDayStart); + console.log("fetching seiyan fun", url); + const { volume }= await fetchURL(url); + return { + dailyVolume: volume, + timestamp, + }; +}; + +const adapter = { + adapter: { + [CHAIN.SEI]: { + fetch, + start: SEIYAN_FUN_INITIAL_TIMESTAMP, + }, + }, +}; + +export default adapter; diff --git a/dexs/sharpe-dex/index.ts b/dexs/sharpe-dex/index.ts new file mode 100644 index 0000000000..c0e9affed9 --- /dev/null +++ b/dexs/sharpe-dex/index.ts @@ -0,0 +1,30 @@ +import { ChainBlocks, FetchOptions, SimpleAdapter } from "../../adapters/types"; +import { CHAIN } from "../../helpers/chains"; +import { getUniqStartOfTodayTimestamp } from "../../helpers/getUniSubgraphVolume"; +import { getPrices } from "../../utils/prices"; +import fetchURL from "../../utils/fetchURL"; + + +const fetch = async () => { + + const data:any = await fetchURL('https://base-api.sharpe.ai/api/dexVolume') + const dailyData:any = await fetchURL('https://base-api.sharpe.ai/api/dailySharpeDexVolume') + + return { + totalVolume: data?.totalVolume, + dailyVolume: dailyData?.dailyVolume + }; +}; + + +const adapter: SimpleAdapter = { + version: 2, + adapter: { + [CHAIN.ETHEREUM]: { + fetch, + start: 1711963031, + }, + }, +}; + +export default adapter; diff --git a/dexs/shell-protocol/constants.ts b/dexs/shell-protocol/constants.ts new file mode 100644 index 0000000000..a9682f1537 --- /dev/null +++ b/dexs/shell-protocol/constants.ts @@ -0,0 +1,1071 @@ +import * as sdk from "@defillama/sdk"; +const POOL_DATA = { + "arbitrum-one": { + "DAI+USDC": { + address: "0x96c7dc9d473e621a1e3968cb862803eaede21888", + oceanId: "86270164020279270457882504196273935359968493071668180156634591477940032783414", + init_block: "36636559", + init_timestamp: 1668003543, + tokens: { + "6035551758411270646474335658514335349674717801108451006051182668568832578004": { + name: "DAI", + type: "ERC-20", + }, + "67271412857715135027962267816154255654502207397591045005455032686546771069218": { + name: "USDC.e", + type: "ERC-20", + }, + }, + type: "Shell" + }, + "USDT+USDC": { + address: "0x0cb736ea2ad425221c368407caafdd323b7bdc83", + oceanId: "79083523100770850082743952656854591086173719343826704660418696417194860926059", + init_block: "42075614", + init_timestamp: 1669702987, + tokens: { + "94403927151183364591870487470764120937216882736599114675039888021977646377740": { + name: "USDT", + type: "ERC-20", + }, + "67271412857715135027962267816154255654502207397591045005455032686546771069218": { + name: "USDC.e", + type: "ERC-20", + }, + }, + type: "Shell" + }, + Stablepool: { + address: "0x4f9d367636d5d2056f848803c11872fdbc2afc47", + oceanId: "50499815543108572175104934225903567768471344593830008376869981553060268559849", + init_block: "47423825", + init_timestamp: 1671494873, + tokens: { + "86270164020279270457882504196273935359968493071668180156634591477940032783414": { + name: "DAI+USDC", + type: "LP-TOKEN", + }, + "79083523100770850082743952656854591086173719343826704660418696417194860926059": { + name: "USDT+USDC", + type: "LP-TOKEN", + }, + }, + type: "Shell" + }, + "ETH+USD": { + address: "0xa2db39e781a5eee0eaa625dace6f097c17dff7ea", + oceanId: "27693504145523314218894589300395733675161932643753970852158242624431218756354", + init_block: "53417512", + init_timestamp: 1673855382, + tokens: { + "68598205499637732940393479723998335974150219832588297998851264911405221787060": { + name: "ETH", + type: "ERC-20", + }, + "50499815543108572175104934225903567768471344593830008376869981553060268559849": { + name: "Stablepool", + type: "LP-TOKEN", + }, + }, + type: "Shell" + }, + "WBTC+USD": { + address: "0x3402d87df0817b2a96b210b8873d33dd979c8d19", + oceanId: "6480478799218559580732937919612426141340033633546174499046941101679426262163", + init_block: "53417512", + init_timestamp: 1673855382, + tokens: { + "59141285909977308443388272935459943129132961051990188111045082080537753428204": { + name: "WBTC", + type: "ERC-20", + }, + "50499815543108572175104934225903567768471344593830008376869981553060268559849": { + name: "Stablepool", + type: "LP-TOKEN", + }, + }, + type: "Shell" + }, + "wstETH+ETH": { + address: "0x2eab95a938d1fabb1b62132bdb0c5a2405a57887", + oceanId: "26161836847743413948413034628704721503292768718421569713619308421179160924635", + init_block: "66475550", + init_timestamp: 1677873600, + tokens: { + "32724548576318001670556591985246081159609078531619344196326067264614400219953": { + name: "wstETH", + type: "ERC-20", + }, + "68598205499637732940393479723998335974150219832588297998851264911405221787060": { + name: "ETH", + type: "ERC-20", + }, + }, + type: "Shell" + }, + "ARB+ETH": { + address: "0xa16f40437213020a167c230e4667ff8f13640f75", + oceanId: "68515004581702575971665429209434508064197021588557669913848091771465963043386", + init_block: "78137705", + init_timestamp: 1680912000, + tokens: { + "15289338637746492243507508172075284374606272498339755847074708978610947567249": { + name: "ARB", + type: "ERC-20", + }, + "68598205499637732940393479723998335974150219832588297998851264911405221787060": { + name: "ETH", + type: "ERC-20", + }, + }, + type: "Shell" + }, + "TOUCOIN+ETH": { + address: "0x81f6f6664e8ece1e81bc9097084373c1dddb8daa", + oceanId: "70238467452623058468527174827445810334914491155089699502631234539680221277556", + init_block: "82253134", + init_timestamp: 1681948800, + tokens: { + "15808556184875223810048460736501637507395435268298861084424311766206176811454": { + name: "TOUCOIN", + type: "ERC-20", + }, + "68598205499637732940393479723998335974150219832588297998851264911405221787060": { + name: "ETH", + type: "ERC-20", + }, + }, + type: "Shell" + }, + "MAGIC+ETH": { + address: "0x0699645f2fd448398272ae07f82eee8d0388de1c", + oceanId: "108582900101494590745798316052054643639067348767864236727953179211932209525623", + init_block: "89077571", + init_timestamp: 1683676800, + tokens: { + "32579059836797942647105779116600635779018130912142677201118367918170517694627": { + name: "MAGIC", + type: "ERC-20", + }, + "68598205499637732940393479723998335974150219832588297998851264911405221787060": { + name: "ETH", + type: "ERC-20", + }, + }, + type: "Shell" + }, + "REUNI+ETH": { + address: "0x3917c74fdec42071e29461c849bceb81cbc3059c", + oceanId: "7453518040095615866313620376139838305458784864962987054364257726153447971877", + init_block: "106539130", + init_timestamp: 1688149532, + tokens: { + "5159943940022542831786931686149875617997271331367331992406615704720154440846": { + name: "REUNI", + type: "ERC-20", + }, + "68598205499637732940393479723998335974150219832588297998851264911405221787060": { + name: "ETH", + type: "ERC-20", + }, + }, + type: "Shell" + }, + "STG+ETH": { + address: "0xe043eb17cc12c3fd4f5eac765d0f1b965975f470", + oceanId: "25942847557684497966353865858489468088339168695395774319392946098495635065854", + init_block: "106544285", + init_timestamp: 1688150836, + tokens: { + "25188701624367602286863586734041950338476366818463077389075015866458016215753": { + name: "STG", + type: "ERC-20", + }, + "68598205499637732940393479723998335974150219832588297998851264911405221787060": { + name: "ETH", + type: "ERC-20", + }, + }, + type: "Shell" + }, + "COLLAB+ETH": { + address: "0x6d0f58fdd73a34cb012b0ba10695440cbf3f7476", + oceanId: "12019623494817756380437074616714970021545559996320236667034221720319302215223", + init_block: "", + init_timestamp: "", + tokens: { + "47031892645123413813452285580465101509871002082298663714739686269575691564264": { + name: "COLLAB", + type: "ERC-20", + }, + "68598205499637732940393479723998335974150219832588297998851264911405221787060": { + name: "ETH", + type: "ERC-20", + }, + }, + type: "Shell" + }, + }, +}; + +const POOL_DATA_V3 = { + "arbitrum-one": { + "SHELL+ETH": { + address: "0xc32a9fc5665affce85cf043472f718029577f7e0", + oceanId: "46864527747283260416172465674867187053251418815143623071567044305059723246874", + init_block: "174647445", + init_timestamp: 1706343578, + tokens: { + "55775470912842449128362975021839710091330191047929748450380616189704765485120": { + name: "SHELL", + type: "ERC-20", + }, + "68598205499637732940393479723998335974150219832588297998851264911405221787060": { + name: "ETH", + type: "ERC-20", + }, + }, + type: "Shell" + }, + "2CRV": { + address: "0x02b4ab3b517371d0bd71d325dbe7dfc0320742e4", + oceanId: "56805135409275017365251878438063985963672982213118458131256538763459274364291", + init_block: "174445053", + init_timestamp: 1706290849, + tokens: { + "67271412857715135027962267816154255654502207397591045005455032686546771069218": { + name: "USDC.e", + type: "ERC-20", + }, + "94403927151183364591870487470764120937216882736599114675039888021977646377740": { + name: "USDT", + type: "ERC-20", + }, + }, + type: "Curve", + externalPoolData: { + address: "0x7f90122BF0700F9E7e1F688fe926940E8839F353", + registryId: "main", + }, + }, + MIM3CRV: { + address: "0xc77030692f296bc53b7995f85e6d54cb679e1115", + oceanId: "56247553860588029018853451520286591218739793556013904791066477425992761504445", + init_block: "178790598", + init_timestamp: 1707425630, + tokens: { + "91722490995000427636075218300093964528492897954739277896713301331071869717571": { + name: "MIM", + type: "ERC-20", + }, + "56805135409275017365251878438063985963672982213118458131256538763459274364291": { + name: "2CRV", + type: "LP-TOKEN", + }, + }, + type: "Curve", + externalPoolData: { + address: "0x30dF229cefa463e991e29D42DB0bae2e122B2AC7", + registryId: "factory", + }, + }, + "crvUSD-USDC": { + address: "0xe428f7c5f9dc057fdcad4c5ff11301c10f78f6ed", + oceanId: "96830010867471238027255154228872174108968894109842904899653760555726997952563", + init_block: "191519727", + init_timestamp: 1710732841, + tokens: { + "67532563260917598181951841572684814967773477625354614038586498409914688218745": { + name: "crvUSD", + type: "ERC-20", + }, + "65497510402545399551520058037845653596132436094743325967104100149253253417279": { + name: "USDC", + type: "ERC-20", + }, + }, + type: "Curve", + externalPoolData: { + address: "0xec090cf6DD891D2d014beA6edAda6e05E025D93d", + registryId: "factory-stable-ng", + }, + }, + "crvUSD-USDT": { + address: "0x5c4826cba1cf3daa1a06a11d46070fc258d2645e", + oceanId: "21630455680440541917048860910544197139742439661378217401115488980888935043791", + init_block: "183277999", + init_timestamp: 1708590044, + tokens: { + "67532563260917598181951841572684814967773477625354614038586498409914688218745": { + name: "crvUSD", + type: "ERC-20", + }, + "94403927151183364591870487470764120937216882736599114675039888021977646377740": { + name: "USDT", + type: "ERC-20", + }, + }, + type: "Curve", + externalPoolData: { + address: "0x73aF1150F265419Ef8a5DB41908B700C32D49135", + registryId: "factory-stable-ng", + }, + }, + "crvUSD-FRAX": { + address: "0x7cdf1b25c74fc6562a75c86127a9ba4a650bfb9a", + oceanId: "87746299629492763459531514658987151891436814966645430819196234486961790363555", + init_block: "194179596", + init_timestamp: 1711400494, + tokens: { + "67532563260917598181951841572684814967773477625354614038586498409914688218745": { + name: "crvUSD", + type: "ERC-20", + }, + "5086067331732638080193725315844452957031597417411157230007610310066989168100": { + name: "FRAX", + type: "ERC-20", + }, + }, + type: "Curve", + externalPoolData: { + address: "0x2FE7AE43591E534C256A1594D326e5779E302Ff4", + registryId: "factory-stable-ng", + }, + }, + "crvUSD-USDC.e": { + address: "0x67f868b76a47fdc02540e9d977be95924a164bd5", + oceanId: "9903511510347662909465582287155028979434242292704913609635879322827229695658", + init_block: "193827209", + init_timestamp: 1711312231, + tokens: { + "67532563260917598181951841572684814967773477625354614038586498409914688218745": { + name: "crvUSD", + type: "ERC-20", + }, + "67271412857715135027962267816154255654502207397591045005455032686546771069218": { + name: "USDC.e", + type: "ERC-20", + }, + }, + type: "Curve", + externalPoolData: { + address: "0x3aDf984c937FA6846E5a24E0A68521Bdaf767cE1", + registryId: "factory-stable-ng", + }, + }, + "crvUSD-MIM": { + address: "0x0fd3eaac40225621390c7df6b8339af7fce31b12", + oceanId: "92867757628956361952024008281824550507023392228551477883673021304280118213833", + init_block: "181219935", + init_timestamp: 1708057546, + tokens: { + "67532563260917598181951841572684814967773477625354614038586498409914688218745": { + name: "crvUSD", + type: "ERC-20", + }, + "91722490995000427636075218300093964528492897954739277896713301331071869717571": { + name: "MIM", + type: "ERC-20", + }, + }, + type: "Curve", + externalPoolData: { + address: "0x4070C044ABc8d9d22447DFE4B032405970878d06", + registryId: "factory-stable-ng", + }, + }, + "wstETH-WETH-BPT": { + address: "0xa8cb454449143912159e066760c1cf3b92415b4a", + oceanId: "6221326419901973194768243650192682495765194747438031992552468391261990689817", + init_block: "176415505", + init_timestamp: 1706798102, + tokens: { + "32724548576318001670556591985246081159609078531619344196326067264614400219953": { + name: "wstETH", + type: "ERC-20", + }, + "107389195714870137694742846735951097405173041024247631974378186743297911362693": { + name: "WETH", + type: "ERC-20", + }, + }, + type: "Balancer", + externalPoolData: { + poolId: "0x9791d590788598535278552eecd4b211bfc790cb000000000000000000000498", + }, + }, + "rETH-WETH-BPT": { + address: "0x85482fec354e3959c7b7fb6d99b658db9b53a39c", + oceanId: "33230866528760364324509366705651160917859056531104451573851701352566795107079", + init_block: "176631118", + init_timestamp: 1706855971, + tokens: { + "107389195714870137694742846735951097405173041024247631974378186743297911362693": { + name: "WETH", + type: "ERC-20", + }, + "65697692034218081496653529939460146670386632488974804976166733454285361435508": { + name: "rETH", + type: "ERC-20", + }, + }, + type: "Balancer", + externalPoolData: { + poolId: "0xade4a71bb62bec25154cfc7e6ff49a513b491e81000000000000000000000497", + }, + }, + "ezETH-wstETH-BPT": { + address: "0x9f2b52085e0d17e3d1b299052ac99df5ba206fd8", + oceanId: "87583293452612841250520025267213631461697157069859304510018702462959608349510", + init_block: "197253965", + init_timestamp: 1712172613, + tokens: { + "97521216940859396985929621458628180000488672900711906345789006892556331338006": { + name: "ezETH", + type: "ERC-20", + }, + "32724548576318001670556591985246081159609078531619344196326067264614400219953": { + name: "wstETH", + type: "ERC-20", + }, + }, + type: "Balancer", + externalPoolData: { + poolId: "0xb61371ab661b1acec81c699854d2f911070c059e000000000000000000000516", + }, + }, + aArbWETH: { + address: "0xdef2a2572fd3cfc6e862ddf856ce5b51b1231e85", + oceanId: "", + init_block: "187440773", + init_timestamp: 1709668557, + tokens: { + "107389195714870137694742846735951097405173041024247631974378186743297911362693": { + name: "WETH", + type: "ERC-20", + }, + "32287189094433887732495178397695981907519138049525202807442741595969650957993": { + name: "aArbWETH", + type: "ERC-20", + }, + }, + type: "Aave", + }, + aArbDAI: { + address: "0x9cc9ce741b99392f592cee49ffc0a954f835120c", + oceanId: "", + init_block: "187436581", + init_timestamp: 1709667508, + tokens: { + "6035551758411270646474335658514335349674717801108451006051182668568832578004": { + name: "DAI", + type: "ERC-20", + }, + "46293440179860815442846138074669145181176812637822851616989775372005575298739": { + name: "aArbDAI", + type: "ERC-20", + }, + }, + type: "Aave", + }, + aArbUSDC: { + address: "0xe03bc2c0d75e3f759be67e5afba8c9242a7be8b1", + oceanId: "", + init_block: "187439714", + init_timestamp: 1709668294, + tokens: { + "67271412857715135027962267816154255654502207397591045005455032686546771069218": { + name: "USDC.e", + type: "ERC-20", + }, + "11173402814424780680347648560776202508592609406370572977719758819269100936273": { + name: "aArbUSDC", + type: "ERC-20", + }, + }, + type: "Aave", + }, + aArbUSDCn: { + address: "0x6428bb8d0e12bd3f8524f433c5cdaff8f2cbeb5f", + oceanId: "", + init_block: "185790043", + init_timestamp: 1709238983, + tokens: { + "65497510402545399551520058037845653596132436094743325967104100149253253417279": { + name: "USDC", + type: "ERC-20", + }, + "93035257646780654601219673806882269003567010963386764840663764243117029370673": { + name: "aArbUSDCn", + type: "ERC-20", + }, + }, + type: "Aave", + }, + aArbUSDT: { + address: "0x218406574f04fb7586583b86e253135acf56baef", + oceanId: "", + init_block: "186135366", + init_timestamp: 1709327720, + tokens: { + "94403927151183364591870487470764120937216882736599114675039888021977646377740": { + name: "USDT", + type: "ERC-20", + }, + "19486903687061128366226641069427279349272927175035037794030688853165107404828": { + name: "aArbUSDT", + type: "ERC-20", + }, + }, + type: "Aave", + }, + aArbWBTC: { + address: "0xa6485d25c44eb97d01369de7781e8614a4200c4e", + oceanId: "", + init_block: "187437125", + init_timestamp: 1709667641, + tokens: { + "59141285909977308443388272935459943129132961051990188111045082080537753428204": { + name: "WBTC", + type: "ERC-20", + }, + "101767238015240620684475239083233401505187715881293698502492037160064700768141": { + name: "aArbWBTC", + type: "ERC-20", + }, + }, + type: "Aave", + }, + aArbARB: { + address: "0xc44f80f509c73b463e3097a8ad308cdde9aa511b", + oceanId: "", + init_block: "187137201", + init_timestamp: 1709589936, + tokens: { + "15289338637746492243507508172075284374606272498339755847074708978610947567249": { + name: "ARB", + type: "ERC-20", + }, + "67113731696707448389784391517895044843361327522484211880606533823229502330722": { + name: "aArbARB", + type: "ERC-20", + }, + }, + type: "Aave", + }, + aArbwstETH: { + address: "0x51f29cac3ca66c80eb1e6f873c5dfb4116466d22", + oceanId: "", + init_block: "186135683", + init_timestamp: 1709327800, + tokens: { + "32724548576318001670556591985246081159609078531619344196326067264614400219953": { + name: "wstETH", + type: "ERC-20", + }, + "91093229841157604626313271672108285548592177277249487722925924721050955646824": { + name: "aArbwstETH", + type: "ERC-20", + }, + }, + type: "Aave", + }, + aArbrETH: { + address: "0xa31fc8119dc3df0ad89e8da57e5b3b5941cfb49b", + oceanId: "", + init_block: "187146467", + init_timestamp: 1709592516, + tokens: { + "65697692034218081496653529939460146670386632488974804976166733454285361435508": { + name: "rETH", + type: "ERC-20", + }, + "40177552568766901594577503394188203447699328835588919744826273671507118837490": { + name: "aArbrETH", + type: "ERC-20", + }, + }, + type: "Aave", + }, + aArbFRAX: { + address: "0xee7102828895a02f63633871f7ac796286fe670c", + oceanId: "", + init_block: "187146467", + init_timestamp: 1709592516, + tokens: { + "50860673317326380801937253158444529570315974174111572300076103100669891681007": { + name: "FRAX", + type: "ERC-20", + }, + "62737710164857693093828292272408067305395809108851898088764058485588468616985": { + name: "aArbFRAX", + type: "ERC-20", + }, + }, + type: "Aave", + }, + "PT-aUSDC-27JUN2024": { + address: "0x2535ef127dc6b5d478b805db58277d626d64f255", + oceanId: "", + init_block: "193153536", + init_timestamp: 1711143403, + tokens: { + "93035257646780654601219673806882269003567010963386764840663764243117029370673": { + name: "aArbUSDCn", + type: "ERC-20", + }, + "22158479876455523465132052222114921573855771147771930222773162206588024770301": { + name: "PT-aUSDC-27JUN2024", + type: "ERC-20", + }, + }, + type: "Pendle", + externalPoolData: { + metadata: "0xBa4A858d664Ddb052158168DB04AFA3cFF5CFCC8", + }, + }, + "YT-aUSDC-27JUN2024": { + address: "0x9a45bbd515121a5dd330891428165fff0ebe6533", + oceanId: "", + init_block: "193228848", + init_timestamp: 1711162272, + tokens: { + "93035257646780654601219673806882269003567010963386764840663764243117029370673": { + name: "aArbUSDCn", + type: "ERC-20", + }, + "34575906478927623152359410103621233312172185882077148157990762477739834035682": { + name: "YT-aUSDC-27JUN2024", + type: "ERC-20", + }, + }, + type: "Pendle", + externalPoolData: { + metadata: "0xBa4A858d664Ddb052158168DB04AFA3cFF5CFCC8", + }, + }, + "PT-rETH-26JUN2025": { + address: "0x90988aba8be06f4993df20dc95a50c71a12b74b8", + oceanId: "", + init_block: "195211129", + init_timestamp: 1711659187, + tokens: { + "65697692034218081496653529939460146670386632488974804976166733454285361435508": { + name: "rETH", + type: "ERC-20", + }, + "113984486213754292433428245469825086541760714876178679167623315101209615376248": { + name: "PT-rETH-26JUN2025", + type: "ERC-20", + }, + }, + type: "Pendle", + externalPoolData: { + metadata: "0x14FbC760eFaF36781cB0eb3Cb255aD976117B9Bd", + }, + }, + "YT-rETH-26JUN2025": { + address: "0x4873144dd892bba5b196f5ca14c091b35fabe14f", + oceanId: "", + init_block: "196977325", + init_timestamp: 1712102988, + tokens: { + "65697692034218081496653529939460146670386632488974804976166733454285361435508": { + name: "rETH", + type: "ERC-20", + }, + "15496211073448363950298098790681985432267884346172851336910641790557779081466": { + name: "YT-rETH-26JUN2025", + type: "ERC-20", + }, + }, + type: "Pendle", + externalPoolData: { + metadata: "0x14FbC760eFaF36781cB0eb3Cb255aD976117B9Bd", + }, + }, + "PT-ezETH-27JUN2024": { + address: "0x75e2b2b5290c47db74596ad634b019a0fa658ee9", + oceanId: "", + init_block: "196982923", + init_timestamp: 1712104399, + tokens: { + "97521216940859396985929621458628180000488672900711906345789006892556331338006": { + name: "ezETH", + type: "ERC-20", + }, + "21255544990739897682581236116373986414601870233534299979116490105453819368742": { + name: "PT-ezETH-27JUN2024", + type: "ERC-20", + }, + }, + type: "Pendle", + externalPoolData: { + metadata: "0x5e03c94fc5fb2e21882000a96df0b63d2c4312e2", + }, + }, + "YT-ezETH-27JUN2024": { + address: "0x7184f6bbe5e0d57ec8122560413668e1c7428cb0", + oceanId: "", + init_block: "199430087", + init_timestamp: 1712719119, + tokens: { + "97521216940859396985929621458628180000488672900711906345789006892556331338006": { + name: "ezETH", + type: "ERC-20", + }, + "55639919809206193568500842344773620127854206653949340632711507458136603356588": { + name: "YT-ezETH-27JUN2024", + type: "ERC-20", + }, + }, + type: "Pendle", + externalPoolData: { + metadata: "0x5e03c94fc5fb2e21882000a96df0b63d2c4312e2", + }, + }, + "PT-USDe-29AUG2024": { + address: "0xa8f37e857d0de88d3f13239e9229bcdac8786053", + oceanId: "", + init_block: "208736435", + init_timestamp: 1715074793, + tokens: { + "43097216419243339615480683813881147729783086182653928934910040896291310829654": { + name: "USDe", + type: "ERC-20", + }, + "108743081410830411492925255391025370276650592677553877715994729540596987151073": { + name: "PT-USDe-29AUG2024", + type: "ERC-20", + }, + }, + type: "Pendle", + externalPoolData: { + metadata: "0x2dfaf9a5e4f293bceede49f2dba29aacdd88e0c4", + }, + }, + "YT-USDe-29AUG2024": { + address: "0x0d8c8346e32dcd4083cf7434b5a5fa3d639f5fa5", + oceanId: "", + init_block: "208736435", + init_timestamp: 1715074793, + tokens: { + "43097216419243339615480683813881147729783086182653928934910040896291310829654": { + name: "USDe", + type: "ERC-20", + }, + "3218810948409087489564911893595970494325069414091822510566943926871605465391": { + name: "YT-USDe-29AUG2024", + type: "ERC-20", + }, + }, + type: "Pendle", + externalPoolData: { + metadata: "0x2dfaf9a5e4f293bceede49f2dba29aacdd88e0c4", + }, + }, + UNI: { + address: "0xc98675da140b7493448b986019933483400536ce", + oceanId: "", + init_block: "197623247", + init_timestamp: 1712265339, + tokens: {}, + type: "Uniswap", + }, + mooCurve2Pool: { + address: "0xe9fcbe88c96a56f0a32477406bdc27f80f4ef8d2", + oceanId: "", + init_block: "206170508", + init_timestamp: 1714427516, + tokens: { + "56805135409275017365251878438063985963672982213118458131256538763459274364291": { + name: "2CRV", + type: "LP-TOKEN", + }, + "67519689751198590455268252479366259960152206660586074518480803469592084720220": { + name: "mooCurve2Pool", + type: "ERC-20", + }, + }, + type: "Beefy", + externalPoolData: { + metadata: "curve-arb-2pool", + }, + }, + "mooCurveCrvUSD-USDC.e": { + address: "0xe9fcbe88c96a56f0a32477406bdc27f80f4ef8d2", + oceanId: "", + init_block: "206170508", + init_timestamp: 1714427516, + tokens: { + "9903511510347662909465582287155028979434242292704913609635879322827229695658": { + name: "crvUSD-USDC.e", + type: "LP-TOKEN", + }, + "75475707189745957832787429007302824076198891026655832860297822459514410408344": { + name: "mooCurveCrvUSD-USDC.e", + type: "ERC-20", + }, + }, + type: "Beefy", + externalPoolData: { + metadata: "curve-arb-crvusd-usdc.e", + }, + }, + "mooCurveCrvUSD-USDC": { + address: "0xe9fcbe88c96a56f0a32477406bdc27f80f4ef8d2", + oceanId: "", + init_block: "206170508", + init_timestamp: 1714427516, + tokens: { + "96830010867471238027255154228872174108968894109842904899653760555726997952563": { + name: "crvUSD-USDC", + type: "LP-TOKEN", + }, + "96335577909249586215342316106422069904464397103443552349219756345211174634729": { + name: "mooCurveCrvUSD-USDC", + type: "ERC-20", + }, + }, + type: "Beefy", + externalPoolData: { + metadata: "curve-arb-crvusd-usdc", + }, + }, + "mooCurveCrvUSD-USDT": { + address: "0xe9fcbe88c96a56f0a32477406bdc27f80f4ef8d2", + oceanId: "", + init_block: "206170508", + init_timestamp: 1714427516, + tokens: { + "21630455680440541917048860910544197139742439661378217401115488980888935043791": { + name: "crvUSD-USDT", + type: "LP-TOKEN", + }, + "114422817501810387655747963160637095180954150612499739306071997181890983272998": { + name: "mooCurveCrvUSD-USDT", + type: "ERC-20", + }, + }, + type: "Beefy", + externalPoolData: { + metadata: "curve-arb-crvusd-usdt", + }, + }, + "mooCurveCrvUSD-MIM": { + address: "0xe9fcbe88c96a56f0a32477406bdc27f80f4ef8d2", + oceanId: "", + init_block: "206170508", + init_timestamp: 1714427516, + tokens: { + "92867757628956361952024008281824550507023392228551477883673021304280118213833": { + name: "crvUSD-MIM", + type: "LP-TOKEN", + }, + "94456099924753924649148702377209899224932903322609952317520644765118077292344": { + name: "mooCurveCrvUSD-MIM", + type: "ERC-20", + }, + }, + type: "Beefy", + externalPoolData: { + metadata: "curve-arb-crvusd-mim", + }, + }, + "mooAbrcdbrMIM-2CRV": { + address: "0xe9fcbe88c96a56f0a32477406bdc27f80f4ef8d2", + oceanId: "", + init_block: "206170508", + init_timestamp: 1714427516, + tokens: { + "56247553860588029018853451520286591218739793556013904791066477425992761504445": { + name: "MIM3CRV", + type: "LP-TOKEN", + }, + "15576440120825720136006100386482497723566960296306656902679358379492901724876": { + name: "mooAbrcdbrMIM-2CRV", + type: "ERC-20", + }, + }, + type: "Beefy", + externalPoolData: { + metadata: "spell-mim-crv", + }, + }, + "mooBalancerArbwstETH-ETH": { + address: "0xe9fcbe88c96a56f0a32477406bdc27f80f4ef8d2", + oceanId: "", + init_block: "206170508", + init_timestamp: 1714427516, + tokens: { + "6221326419901973194768243650192682495765194747438031992552468391261990689817": { + name: "wstETH-WETH-BPT", + type: "LP-TOKEN", + }, + "44605810225174412184533351979235793773152336376173914031105481599543834119907": { + name: "mooBalancerArbwstETH-ETH", + type: "ERC-20", + }, + }, + type: "Beefy", + externalPoolData: { + metadata: "balancer-wsteth-weth-v3", + }, + }, + "mooBalancerArbETH-rETH": { + address: "0xe9fcbe88c96a56f0a32477406bdc27f80f4ef8d2", + oceanId: "", + init_block: "206170508", + init_timestamp: 1714427516, + tokens: { + "33230866528760364324509366705651160917859056531104451573851701352566795107079": { + name: "rETH-WETH-BPT", + type: "LP-TOKEN", + }, + "11673284798174487886367517892461860847832521034306076171090731998049164031862": { + name: "mooBalancerArbETH-rETH", + type: "ERC-20", + }, + }, + type: "Beefy", + externalPoolData: { + metadata: "balancer-weth-reth", + }, + }, + "mooAuraArbezETH-wstETH": { + address: "0xe9fcbe88c96a56f0a32477406bdc27f80f4ef8d2", + oceanId: "", + init_block: "206170508", + init_timestamp: 1714427516, + tokens: { + "87583293452612841250520025267213631461697157069859304510018702462959608349510": { + name: "ezETH-wstETH-BPT", + type: "LP-TOKEN", + }, + "13906327766104167821603618133457906999489435155916468837741767231750622296813": { + name: "mooAuraArbezETH-wstETH", + type: "ERC-20", + }, + }, + type: "Beefy", + externalPoolData: { + metadata: "aura-arb-ezeth-wsteth", + }, + }, + }, +}; + +const TOKEN_NAMES = { + "arbitrum-one": { + DAI: "6035551758411270646474335658514335349674717801108451006051182668568832578004", + "USDC.e": "67271412857715135027962267816154255654502207397591045005455032686546771069218", + USDT: "94403927151183364591870487470764120937216882736599114675039888021977646377740", + ETH: "68598205499637732940393479723998335974150219832588297998851264911405221787060", + WBTC: "59141285909977308443388272935459943129132961051990188111045082080537753428204", + wstETH: "32724548576318001670556591985246081159609078531619344196326067264614400219953", + ARB: "15289338637746492243507508172075284374606272498339755847074708978610947567249", + TOUCOIN: "15808556184875223810048460736501637507395435268298861084424311766206176811454", + COLLAB: "47031892645123413813452285580465101509871002082298663714739686269575691564264", + MAGIC: "32579059836797942647105779116600635779018130912142677201118367918170517694627", + "DAI+USDC": "86270164020279270457882504196273935359968493071668180156634591477940032783414", + "USDT+USDC": "79083523100770850082743952656854591086173719343826704660418696417194860926059", + Stablepool: "50499815543108572175104934225903567768471344593830008376869981553060268559849", + "ETH+USD": "27693504145523314218894589300395733675161932643753970852158242624431218756354", + "WBTC+USD": "6480478799218559580732937919612426141340033633546174499046941101679426262163", + "wstETH+ETH": "26161836847743413948413034628704721503292768718421569713619308421179160924635", + "ARB+ETH": "68515004581702575971665429209434508064197021588557669913848091771465963043386", + "TOUCOIN+ETH": "70238467452623058468527174827445810334914491155089699502631234539680221277556", + "MAGIC+ETH": "108582900101494590745798316052054643639067348767864236727953179211932209525623", + "REUNI+ETH": "7453518040095615866313620376139838305458784864962987054364257726153447971877", + REUNI: "5159943940022542831786931686149875617997271331367331992406615704720154440846", + "STG+ETH": "25942847557684497966353865858489468088339168695395774319392946098495635065854", + STG: "25188701624367602286863586734041950338476366818463077389075015866458016215753", + "COLLAB+ETH": "12019623494817756380437074616714970021545559996320236667034221720319302215223", + USDC: "65497510402545399551520058037845653596132436094743325967104100149253253417279", + "SHELL+ETH": "46864527747283260416172465674867187053251418815143623071567044305059723246874", + SHELL: "55775470912842449128362975021839710091330191047929748450380616189704765485120", + crvUSD: "67532563260917598181951841572684814967773477625354614038586498409914688218745", + FRAX: "50860673317326380801937253158444529570315974174111572300076103100669891681007", + MIM: "91722490995000427636075218300093964528492897954739277896713301331071869717571", + WETH: "107389195714870137694742846735951097405173041024247631974378186743297911362693", + rETH: "65697692034218081496653529939460146670386632488974804976166733454285361435508", + MIM3CRV: "56247553860588029018853451520286591218739793556013904791066477425992761504445", + aArbWETH: "32287189094433887732495178397695981907519138049525202807442741595969650957993", + aArbDAI: "46293440179860815442846138074669145181176812637822851616989775372005575298739", + aArbUSDC: "11173402814424780680347648560776202508592609406370572977719758819269100936273", + aArbUSDCn: "93035257646780654601219673806882269003567010963386764840663764243117029370673", + aArbUSDT: "19486903687061128366226641069427279349272927175035037794030688853165107404828", + aArbWBTC: "101767238015240620684475239083233401505187715881293698502492037160064700768141", + aArbARB: "67113731696707448389784391517895044843361327522484211880606533823229502330722", + aArbwstETH: "91093229841157604626313271672108285548592177277249487722925924721050955646824", + aArbrETH: "40177552568766901594577503394188203447699328835588919744826273671507118837490", + aArbFRAX: "62737710164857693093828292272408067305395809108851898088764058485588468616985", + "PT-aUSDC-27JUN2024": "22158479876455523465132052222114921573855771147771930222773162206588024770301", + "YT-aUSDC-27JUN2024": "34575906478927623152359410103621233312172185882077148157990762477739834035682", + "PT-rETH-26JUN2025": "113984486213754292433428245469825086541760714876178679167623315101209615376248", + "YT-rETH-26JUN2025": "15496211073448363950298098790681985432267884346172851336910641790557779081466", + "PT-ezETH-27JUN2024": "21255544990739897682581236116373986414601870233534299979116490105453819368742", + "YT-ezETH-27JUN2024": "55639919809206193568500842344773620127854206653949340632711507458136603356588", + ezETH: "97521216940859396985929621458628180000488672900711906345789006892556331338006", + mooCurve2Pool: "67519689751198590455268252479366259960152206660586074518480803469592084720220", + "mooCurveCrvUSD-USDC.e": "75475707189745957832787429007302824076198891026655832860297822459514410408344", + "mooCurveCrvUSD-USDC": "96335577909249586215342316106422069904464397103443552349219756345211174634729", + "mooCurveCrvUSD-USDT": "114422817501810387655747963160637095180954150612499739306071997181890983272998", + "mooCurveCrvUSD-MIM": "94456099924753924649148702377209899224932903322609952317520644765118077292344", + "mooAbrcdbrMIM-2CRV": "15576440120825720136006100386482497723566960296306656902679358379492901724876", + "mooBalancerArbwstETH-ETH": "44605810225174412184533351979235793773152336376173914031105481599543834119907", + "mooBalancerArbETH-rETH": "11673284798174487886367517892461860847832521034306076171090731998049164031862", + "mooAuraArbezETH-wstETH": "13906327766104167821603618133457906999489435155916468837741767231750622296813", + USDe: "43097216419243339615480683813881147729783086182653928934910040896291310829654", + "PT-USDe-29AUG2024": "108743081410830411492925255391025370276650592677553877715994729540596987151073", + "YT-USDe-29AUG2024": "3218810948409087489564911893595970494325069414091822510566943926871605465391", + }, +}; + +const MAINNET_SUBGRAPH_URL = sdk.graph.modifyEndpoint('H6vTCuujLYzXdgGDbB9UzwLjbGc4gXPttx6ULtBJBxdX'); +const MAINNET_V3_SUBGRAPH_URL = "https://api.studio.thegraph.com/query/42384/shell-v3-arbitrum-one-rl/version/latest"; +const MAINNET_BLOCKS_URL = sdk.graph.modifyEndpoint('3mQwWddUyzqxqMkb1HMPxoHGSLg3fKfmLawMtyUoDxmD'); + +const COIN_GECKO_IDS = { + DAI: "dai", + "USDC.e": "usd-coin-ethereum-bridged", + USDT: "tether", + ETH: "ethereum", + WBTC: "bitcoin", + wstETH: "wrapped-steth", + ARB: "arbitrum", + TOUCOIN: "government-toucans", + MAGIC: "magic", + COLLAB: "collab-land", + REUNI: "reunit-wallet", + STG: "stargate-finance", + USDC: "usd-coin", + SHELL: "shSHELL", + tUSDC: "true-usd", + tBTC: "tbtc", + crvUSD: "crvusd", + FRAX: "frax", + MIM: "magic-internet-money", + WETH: "weth", + rETH: "rocket-pool-eth", + MIM3CRV: "MIM3CRV", + aArbWETH: "aave-v3-weth", + aArbDAI: "aave-v3-dai", + aArbUSDC: "aave-v3-usdc-e", + aArbUSDCn: "aave-v3-usdc", + aArbUSDT: "aave-v3-usdt", + aArbWBTC: "aave-v3-wbtc", + aArbARB: "aave-v3-arb", + aArbwstETH: "aave-v3-wsteth", + aArbrETH: "aave-v3-reth", + aArbFRAX: "aave-v3-frax", + ezETH: "renzo-restaked-eth", + USDe: "ethena-usde", + USDbC: "bridged-usd-coin-base", + weETH: "wrapped-eeth", + cbETH: "coinbase-wrapped-staked-eth", + DEGEN: "degen-base", + AERO: "aerodrome-finance", +}; + +export { POOL_DATA, POOL_DATA_V3, TOKEN_NAMES, MAINNET_SUBGRAPH_URL, MAINNET_V3_SUBGRAPH_URL, MAINNET_BLOCKS_URL, COIN_GECKO_IDS }; diff --git a/dexs/shell-protocol/helpers.ts b/dexs/shell-protocol/helpers.ts new file mode 100644 index 0000000000..5797dcd24a --- /dev/null +++ b/dexs/shell-protocol/helpers.ts @@ -0,0 +1,479 @@ +import { POOL_DATA, POOL_DATA_V3, TOKEN_NAMES, MAINNET_SUBGRAPH_URL, MAINNET_V3_SUBGRAPH_URL, COIN_GECKO_IDS, MAINNET_BLOCKS_URL } from "./constants.ts"; + +function defineComputesQuery(poolAddress: string, timestamp: number, endTimestamp: number, inputLastId: string, outputLastId: string): string { + let computesQuery = ""; + if (inputLastId !== "-1") { + computesQuery += `computeInputAmounts (where:{externalContract: "${poolAddress}", timestamp_gte: ${timestamp}, timestamp_lte: ${endTimestamp}, id_gt: ${inputLastId}}, first: 1000){ id inputToken inputAmount outputToken outputAmount timestamp}`; + } + if (outputLastId !== "-1") { + computesQuery += `computeOutputAmounts (where:{externalContract: "${poolAddress}", timestamp_gte: ${timestamp}, timestamp_lte: ${endTimestamp}, id_gt: ${outputLastId}}, first: 1000){ id inputToken inputAmount outputToken outputAmount timestamp}`; + } + return `{${computesQuery}}`; +} + +function definePoolBalancesQuery(poolAddress: string, oceanId: string, blockNumber: number): string { + return ` + { + user (id: "${poolAddress}", block: {number: ${blockNumber}}){ + id + userBalances { + oceanId + balance + } + } + oceanToken (id: "${oceanId}", block: {number: ${blockNumber}}){ + supply + } + } + `; +} + +async function getPrices(chain: string): Promise<{ [key: string]: { usd: number } }> { + let prices: { [key: string]: { usd: number } } = {}; + + try { + const options = { + method: "GET", + headers: { + accept: "application/json", + "x-cg-demo-api-key": "CG-DfuTtr6HEjL8t2eD6MpyeLp5", + }, + }; + + prices = await fetch(`https://api.coingecko.com/api/v3/simple/price?ids=${Object.values(COIN_GECKO_IDS)}&vs_currencies=usd`, options).then((response) => + response.json() + ); + + const tokenBalancesTOUCOIN = await getTokenBalance(chain, "TOUCOIN+ETH"); + if (tokenBalancesTOUCOIN) { + prices["government-toucans"] = { + usd: (tokenBalancesTOUCOIN["ETH"] / tokenBalancesTOUCOIN["TOUCOIN"]) * prices.ethereum.usd, + }; + } + + const tokenBalancesSHELL = await getTokenBalance(chain, "SHELL+ETH", "v3"); + if (tokenBalancesSHELL) { + prices["shSHELL"] = { + usd: (tokenBalancesSHELL["ETH"] / tokenBalancesSHELL["SHELL"]) * prices.ethereum.usd, + }; + } + } catch (error) { + console.error("Error fetching prices:", error); + } + + return prices; +} + +async function getCurveAnalytics(chain: string, prices: { [key: string]: { usd: number } }, externalPoolData: { registryId: string; address: string }) { + const output: any = {}; + + const curveApiCallData = await fetch(`https://api.curve.fi/api/getPools/arbitrum/${externalPoolData.registryId}`).then((response) => response.json()); + const curveApiCall = curveApiCallData.data.poolData; + + for (const pool of curveApiCall) { + if (pool.address === externalPoolData.address) { + output.totalValueLocked = parseFloat(pool.usdTotal); + output.LPTokenPrice = parseFloat(pool.virtualPrice) / 1e18; + output.LPTokenBalance = parseFloat(pool.totalSupply) / 1e18; + + output.balances = {}; + output.breakdown = {}; + + for (const coin of pool.coins) { + const balance = parseFloat(coin.poolBalance) / Math.pow(10, parseInt(coin.decimals)); + const breakdown = Math.round(((balance * coin.usdPrice) / parseFloat(pool.usdTotal)) * 100); + + if (POOL_DATA_V3[chain][coin.symbol]) { + const poolTokenBalance = await getCurveAnalytics(chain, prices, POOL_DATA_V3[chain][coin.symbol].externalPoolData); + prices[coin.symbol] = { usd: poolTokenBalance.LPTokenPrice }; + for (const token in poolTokenBalance.breakdown) { + output.balances[token] = (balance * poolTokenBalance.breakdown[token]) / 100; + output.breakdown[token] = Math.round((breakdown * poolTokenBalance.breakdown[token]) / 100); + } + } else { + output.balances[coin.symbol] = balance; + output.breakdown[coin.symbol] = breakdown; + } + } + } + } + + return output; +} + +async function getBalancerAnalytics(chain: string, poolName: string, externalPoolData: { poolId: string }, ethPrice: number) { + const output: any = {}; + const apiCallData = await fetch(`https://api.balancer.fi/pools/42161/${externalPoolData.poolId}`).then((response) => response.json()); + + output.totalValueLocked = parseFloat(apiCallData.totalLiquidity); + output.LPTokenPrice = 0; + output.LPTokenBalance = parseFloat(apiCallData.totalShares); + output.breakdown = {}; + output.balances = {}; + + for (const token of apiCallData.tokens) { + if (poolName === token.symbol || token.token.pool) { + output.LPTokenPrice = parseFloat(token.token.latestUSDPrice); + continue; + } + output.balances[token.symbol] = parseFloat(token.balance); + output.breakdown[token.symbol] = Math.round(((output.balances[token.symbol] * parseFloat(token.priceRate) * ethPrice) / output.totalValueLocked) * 100); + } + + return output; +} + +async function getPoolData( + chain: string, + poolName: string, + prices: { [key: string]: { usd: number } }, + version: string, + startTime: number, + endTime: number +): Promise<{ + totalValueLocked: number; + LPTokenPrice: number; + LPTokenBalance: number; + breakdown: { [key: string]: number }; + balances: { [key: string]: number }; + "24HrVolume": number; +}> { + let pool = version === "v3" ? POOL_DATA_V3[chain][poolName] : POOL_DATA[chain][poolName]; + + let totalValueLocked: number = 0; + let LPTokenPrice: number = 0; + let LPTokenBalance: number = 0; + let breakdown: { [key: string]: number } = {}; + let balances: { [key: string]: number } = {}; + let volume: number = 0; + + let subTokenPrices: { [key: string]: number } = {}; + let fractalPoolData: { [key: string]: any } = {}; + + if (pool.type !== "Shell") { + if (pool.type == "Curve") { + const output = await getCurveAnalytics(chain, prices, pool.externalPoolData); + + totalValueLocked = output.totalValueLocked; + LPTokenPrice = output.LPTokenPrice; + LPTokenBalance = output.LPTokenBalance; + breakdown = output.breakdown; + balances = output.balances; + } else if (pool.type == "Balancer") { + const output = await getBalancerAnalytics(chain, poolName, pool.externalPoolData, prices[COIN_GECKO_IDS["ETH"]]["usd"]); + + totalValueLocked = output.totalValueLocked; + LPTokenPrice = output.LPTokenPrice; + LPTokenBalance = output.LPTokenBalance; + breakdown = output.breakdown; + balances = output.balances; + } else if (pool.type == "Aave") { + prices[poolName] = prices[(Object.values(pool.tokens)[0] as any).name]; + } else if (pool.type == "Pendle") { + const marketData = await fetch(`https://api-v2.pendle.finance/core/v1/42161/markets/${pool.externalPoolData.metadata}`).then((response) => + response.json() + ); + prices[poolName] = poolName.startsWith("PT-") ? marketData.pt.price.usd : marketData.yt.price.usd; + } else if (pool.type == "Beefy") { + const data = await fetch("https://api.beefy.finance/vaults").then((response) => response.json()); + prices[poolName] = { usd: parseFloat(data.find((obj) => obj.id == pool.externalPoolData.metadata).pricePerFullShare) / 1e18 }; + for (const token of Object.values(pool.tokens) as any[]) { + if (token.type == "LP-TOKEN") { + const subPoolName = token.name; + const subPoolData = await getPoolData(chain, subPoolName, prices, version, startTime, endTime); + subTokenPrices[subPoolName] = subPoolData.LPTokenPrice; + } + } + } + } else { + let tokenBalances: { [key: string]: number } = {}; + let userBalances: { [key: string]: string } = {}; + + let currentBalances = await queryPoolBalances(chain, poolName, version, startTime, endTime); + + currentBalances["user"]["userBalances"].forEach((userBalance: { [key: string]: string }) => { + userBalances[userBalance["oceanId"]] = userBalance["balance"]; + }); + + Object.keys(pool["tokens"]).forEach((token: string) => { + let tokenName = pool["tokens"][token]["name"]; + tokenBalances[tokenName] = parseInt(userBalances[token]) / 1e18; + }); + + LPTokenBalance = parseInt(currentBalances["oceanToken"]["supply"]) / 1e18; + + let sub_token_volume: number = 0; + + for (const token of Object.keys(pool.tokens)) { + let tokenType = pool["tokens"][token]["type"]; + let tokenName = pool["tokens"][token]["name"]; + + if (tokenType === "LP-TOKEN") { + let subTokenPoolData = await getPoolData(chain, tokenName, prices, version, startTime, endTime); + subTokenPrices[tokenName] = subTokenPoolData["LPTokenPrice"]; + Object.keys(subTokenPoolData["breakdown"]).forEach((subToken: string) => { + fractalPoolData[tokenName] = { + balanceInPool: tokenBalances[tokenName], + totalBalance: subTokenPoolData["LPTokenBalance"], + balancesBreakdown: subTokenPoolData["balances"], + "24HrVolume": subTokenPoolData["24HrVolume"], + }; + }); + } + } + + Object.keys(tokenBalances).forEach((token: string) => { + let tokenData = pool["tokens"][TOKEN_NAMES[chain][token]]; + + if (tokenData["type"] === "ERC-20" || tokenData["type"] === "ERC-1155") { + balances[token] = tokenBalances[token]; + } else if (tokenData["type"] === "LP-TOKEN") { + let tokenPercentage = fractalPoolData[token]["balanceInPool"] / fractalPoolData[token]["totalBalance"]; + sub_token_volume += tokenPercentage * fractalPoolData[token]["24HrVolume"]; + + Object.keys(fractalPoolData[token]["balancesBreakdown"]).forEach((subToken: string) => { + let tokenBalance = fractalPoolData[token]["balancesBreakdown"][subToken] * tokenPercentage; + if (balances[subToken]) { + balances[subToken] += tokenBalance; + } else { + balances[subToken] = tokenBalance; + } + }); + } + }); + + volume = sub_token_volume; + + Object.keys(balances).forEach((token: string) => { + totalValueLocked += balances[token] * prices[COIN_GECKO_IDS[token]]["usd"]; + }); + + Object.keys(balances).forEach((token: string) => { + breakdown[token] = Math.round(((balances[token] * prices[COIN_GECKO_IDS[token]]["usd"]) / totalValueLocked) * 100); + }); + + LPTokenPrice = totalValueLocked / LPTokenBalance; + } + + let namesToId = Object.fromEntries(Object.entries(TOKEN_NAMES[chain]).map(([k, v]) => [v, k])); + + let setOfTokens = [...Object.keys(pool["tokens"]), pool["oceanId"]]; + + let interactions = await queryPoolInteractions(chain, poolName, version, startTime, endTime); + + Object.keys(interactions).forEach((interactionType: string) => { + interactions[interactionType].forEach((interaction: { [key: string]: string }) => { + if ( + poolName == "UNI" || + (setOfTokens.includes(interaction["inputToken"]) && (interaction["outputToken"] === setOfTokens[0] || interaction["outputToken"] === setOfTokens[1])) + ) { + let price: number; + if (namesToId[interaction["inputToken"]] in subTokenPrices) { + price = subTokenPrices[namesToId[interaction["inputToken"]]]; + } else if (namesToId[interaction["inputToken"]] === poolName) { + price = LPTokenPrice; + } else { + price = prices[COIN_GECKO_IDS[namesToId[interaction["inputToken"]]]]["usd"]; + } + + volume += (parseInt(interaction["inputAmount"]) / 1e18) * price; + } + }); + }); + + return { + totalValueLocked, + LPTokenPrice, + LPTokenBalance, + breakdown, + balances, + "24HrVolume": volume, + }; +} + +// Function that defines the query to get the previous block before the start of a given date +function blockQuery(timestamp: number): string { + return ` + { + blocks(first: 1, where: {timestamp_lt: ${timestamp}}, orderBy: timestamp, orderDirection: desc) { + number + timestamp + } + }`; +} + +// Function that queries a subgraph and gets the last block before a given date +async function getBlocks(date: number, chain: string): Promise { + const url: string = chain === "arbitrum-one" ? MAINNET_BLOCKS_URL : ""; + const query: string = blockQuery(date); + + try { + const response = await fetch(url, { + method: "POST", + headers: { + "Content-Type": "application/json", + }, + body: JSON.stringify({ query }), + }); + + const data = await response.json(); + const endBlock: number = data.data.blocks[0].number; + return endBlock; + } catch (error) { + console.error("Error fetching block data:", error); + throw error; + } +} + +async function queryPoolBalances( + chain: string, + poolName: string, + version: string, + startTime: number | null = null, + endTime: number | null = null +): Promise { + let url: string = ""; + if (chain === "arbitrum-one") { + url = version === "v3" ? MAINNET_V3_SUBGRAPH_URL : MAINNET_SUBGRAPH_URL; + } + + let pool: any = version === "v3" ? POOL_DATA_V3[chain][poolName] : POOL_DATA[chain][poolName]; + let poolAddress: string = `${pool["address"]}`; + let oceanId: string = `${pool["oceanId"]}`; + let endTimeStamp: number = endTime || Math.floor(Date.now() / 1000); + let blockNumber: number = (await getBlocks(endTimeStamp, chain)) - 100; + + let query: string = definePoolBalancesQuery(poolAddress, oceanId, blockNumber); + const currentBalancesData: any = ( + await fetch(url, { + method: "POST", + headers: { "Content-Type": "application/json" }, + body: JSON.stringify({ query }), + }).then((response) => response.json()) + ).data; + + return currentBalancesData; +} + +async function queryPoolInteractions(chain: string, poolName: string, version: string, startTime: number, endTime: number): Promise { + let url: string = ""; + if (chain === "arbitrum-one") { + url = version === "v3" ? MAINNET_V3_SUBGRAPH_URL : MAINNET_SUBGRAPH_URL; + } + + let pool: any = version === "v3" ? POOL_DATA_V3[chain][poolName] : POOL_DATA[chain][poolName]; + let poolAddress: string = `${pool["address"]}`; + let interactionsData: any = {}; + + let computeInputAmountsList: any[] = []; + let computeOutputAmountsList: any[] = []; + let inputAmountsLastId: string = '""'; + let outputAmountsLastId: string = '""'; + + while (true) { + const query = defineComputesQuery(poolAddress, startTime, endTime, inputAmountsLastId, outputAmountsLastId); + const computesResponse = await fetch(url, { + method: "POST", + headers: { "Content-Type": "application/json" }, + body: JSON.stringify({ query }), + }); + const computes: any = (await computesResponse.json()).data; + + const computeOutputAmounts: any[] = computes.computeOutputAmounts || []; + const computeInputAmounts: any[] = computes.computeInputAmounts || []; + + if (computeInputAmounts.length === 0 && computeOutputAmounts.length === 0) { + break; + } else if (computeInputAmounts.length === 0) { + outputAmountsLastId = `"${computeOutputAmounts[computeOutputAmounts.length - 1].id}"`; + inputAmountsLastId = "-1"; + } else if (computeOutputAmounts.length === 0) { + inputAmountsLastId = `"${computeInputAmounts[computeInputAmounts.length - 1].id}"`; + outputAmountsLastId = "-1"; + } else { + inputAmountsLastId = `"${computeInputAmounts[computeInputAmounts.length - 1].id}"`; + outputAmountsLastId = `"${computeOutputAmounts[computeOutputAmounts.length - 1].id}"`; + } + + computeInputAmountsList = computeInputAmountsList.concat(computeInputAmounts); + computeOutputAmountsList = computeOutputAmountsList.concat(computeOutputAmounts); + } + + interactionsData["computeInputAmounts"] = computeInputAmountsList; + interactionsData["computeOutputAmounts"] = computeOutputAmountsList; + + return interactionsData; +} + +async function getTokenBalance(chain: string, pool: string, version: string = "v2"): Promise<{ [key: string]: number }> { + const url: string = chain === "arbitrum-one" ? (version === "v3" ? MAINNET_V3_SUBGRAPH_URL : MAINNET_SUBGRAPH_URL) : ""; + + const poolData: any = version === "v3" ? POOL_DATA_V3[chain][pool] : POOL_DATA[chain][pool]; + const poolAddress: string = `${poolData.address}`; + const oceanId: string = `${poolData.oceanId}`; + const endTime: number = Math.floor(Date.now() / 1000); + const blockNumber: number = (await getBlocks(endTime, chain)) - 150; + const query: string = definePoolBalancesQuery(poolAddress, oceanId, blockNumber); + + const response: Response = await fetch(url, { + method: "POST", + headers: { "Content-Type": "application/json" }, + body: JSON.stringify({ query }), + }); + const currentBalances: any = await response.json(); + + const tokenBalances: { [key: string]: number } = {}; + const userBalances: { [key: string]: string } = {}; + + currentBalances.data.user.userBalances.forEach((userBalance: any) => { + userBalances[userBalance.oceanId] = userBalance.balance; + }); + + Object.keys(poolData.tokens).forEach((token: string) => { + const tokenName: string = poolData.tokens[token].name; + tokenBalances[tokenName] = parseInt(userBalances[token]) / 1e18; + }); + + tokenBalances["supply"] = parseFloat(currentBalances.data.oceanToken.supply) / 1e18; + + return tokenBalances; +} + + +// Volume is derived by summing up the token dollar values of all the Ocean interactions that went through all the pools +export async function getVolume(timestamp: number): Promise { + const chain: string = "arbitrum-one"; + const prices: { [key: string]: { usd: number } } = await getPrices(chain); + const endTime: number = timestamp; + const startTime: number = endTime - 24 * 60 * 60; + + const poolKeys: string[] = Object.keys(POOL_DATA["arbitrum-one"]).concat(Object.keys(POOL_DATA_V3["arbitrum-one"])); + + const poolDataPromises: Promise<{ + totalValueLocked: number; + LPTokenPrice: number; + LPTokenBalance: number; + breakdown: { [key: string]: number }; + balances: { [key: string]: number }; + "24HrVolume": number; + }>[] = []; + for (const poolKey of poolKeys) { + const version: string = POOL_DATA["arbitrum-one"][poolKey] ? "v2" : "v3"; + poolDataPromises.push(getPoolData(chain, poolKey, prices, version, startTime, endTime)); + } + + const poolDataResults: { + totalValueLocked: number; + LPTokenPrice: number; + LPTokenBalance: number; + breakdown: { [key: string]: number }; + balances: { [key: string]: number }; + "24HrVolume": number; + }[] = await Promise.all(poolDataPromises); + + const total24HrVolume: number = poolDataResults.reduce((sum: number, poolData: any) => { + return sum + (poolData["24HrVolume"] || 0); + }, 0); + + return total24HrVolume; +} diff --git a/dexs/shell-protocol/index.ts b/dexs/shell-protocol/index.ts index 8016e9f6a8..8469cf90a8 100644 --- a/dexs/shell-protocol/index.ts +++ b/dexs/shell-protocol/index.ts @@ -1,28 +1,19 @@ -import ADDRESSES from '../../helpers/coreAssets.json' import { ChainBlocks, FetchOptions, SimpleAdapter } from "../../adapters/types"; import { CHAIN } from "../../helpers/chains"; -import { addTokensReceived } from "../../helpers/token"; - +import { getVolume } from "./helpers"; const fetch = async (timestamp: number, _: ChainBlocks, options: FetchOptions) => { - const tokens = [ - ADDRESSES.arbitrum.DAI, - ADDRESSES.arbitrum.USDC, - ADDRESSES.arbitrum.USDT, - ADDRESSES.arbitrum.WBTC, - ] - const dailyVolume = await addTokensReceived({ tokens, options, fromAddressFilter: '0xC32eB36f886F638fffD836DF44C124074cFe3584' }) - return { timestamp, dailyVolume } -} - + const dailyVolume = await getVolume(timestamp); + return { timestamp, dailyVolume }; +}; const adapter: SimpleAdapter = { adapter: { [CHAIN.ARBITRUM]: { fetch, - start: 1667260800, + start: 1705968000, }, - } + }, }; export default adapter; diff --git a/dexs/shibaswap/index.ts b/dexs/shibaswap/index.ts index c2d236b3c0..cebac52d6a 100644 --- a/dexs/shibaswap/index.ts +++ b/dexs/shibaswap/index.ts @@ -1,11 +1,12 @@ +import * as sdk from "@defillama/sdk"; import { CHAIN } from "../../helpers/chains"; -import { univ2Adapter } from "../../helpers/getUniSubgraphVolume"; +import { univ2Adapter2 } from "../../helpers/getUniSubgraphVolume"; const endpoints = { - [CHAIN.ETHEREUM]: "https://api.thegraph.com/subgraphs/name/shibaswaparmy/exchange", + [CHAIN.ETHEREUM]: sdk.graph.modifyEndpoint('FvP7tK71rX51wsb663j5GRx2YTtDRa1Adq8QSCi5akLS'), }; -const adapter = univ2Adapter(endpoints, { +const adapter = univ2Adapter2(endpoints, { factoriesName: "factories", dayData: "dayData", dailyVolume: "volumeUSD", diff --git a/dexs/shimmersea/index.ts b/dexs/shimmersea/index.ts index 14cd66008e..1813e711c7 100644 --- a/dexs/shimmersea/index.ts +++ b/dexs/shimmersea/index.ts @@ -1,20 +1,16 @@ import { SimpleAdapter } from "../../adapters/types"; import { CHAIN } from "../../helpers/chains"; -import { getGraphDimensions } from "../../helpers/getUniSubgraph"; -import { DEFAULT_DAILY_VOLUME_FACTORY, DEFAULT_TOTAL_VOLUME_FIELD, univ2Adapter } from "../../helpers/getUniSubgraphVolume"; +import { getGraphDimensions2 } from "../../helpers/getUniSubgraph"; +import { DEFAULT_TOTAL_VOLUME_FIELD } from "../../helpers/getUniSubgraphVolume"; const v3Endpoints = { - [CHAIN.SHIMMER_EVM]: "https://graph-c.shimmersea.finance/subgraphs/name/shimmersea/shimmer-dex", + [CHAIN.SHIMMER_EVM]: "https://graph-c-ha.shimmersea.finance/subgraphs/name/shimmersea/shimmer-dex", } -const v3Graphs = getGraphDimensions({ +const v3Graphs = getGraphDimensions2({ graphUrls: v3Endpoints, totalVolume: { factory: "uniswapFactories", field: DEFAULT_TOTAL_VOLUME_FIELD, }, - dailyVolume: { - factory: DEFAULT_DAILY_VOLUME_FACTORY, - field: "dailyVolumeUSD", - }, feesPercent: { type: "volume", UserFees: 0.3, @@ -27,6 +23,7 @@ const v3Graphs = getGraphDimensions({ }); const adapter: SimpleAdapter = { + version: 2, adapter: Object.keys(v3Endpoints).reduce((acc, chain) => { return { ...acc, diff --git a/dexs/smartdex/index.ts b/dexs/smartdex/index.ts index 99722f3f01..2878886de9 100644 --- a/dexs/smartdex/index.ts +++ b/dexs/smartdex/index.ts @@ -1,7 +1,8 @@ +import * as sdk from "@defillama/sdk"; import { CHAIN } from "../../helpers/chains"; import { univ2Adapter } from "../../helpers/getUniSubgraphVolume"; export default univ2Adapter({ - [CHAIN.POLYGON]: "https://api.thegraph.com/subgraphs/name/akashzeromile/smartdex-subgraph" + [CHAIN.POLYGON]: sdk.graph.modifyEndpoint('8Lw1rRcKYgi4qfdLuk4gRubLVR48RpGuBCJiB7hLtupt') }, { }); diff --git a/dexs/sobal/index.ts b/dexs/sobal/index.ts index 94deb2599f..e3b0456598 100644 --- a/dexs/sobal/index.ts +++ b/dexs/sobal/index.ts @@ -1,5 +1,5 @@ -import { ChainEndpoints, BreakdownAdapter, BaseAdapter, SimpleAdapter } from "../../adapters/types"; -import { getChainVolume } from "../../helpers/getUniSubgraphVolume"; +import { ChainEndpoints, SimpleAdapter } from "../../adapters/types"; +import { getChainVolume2 } from "../../helpers/getUniSubgraphVolume"; import { CHAIN } from "../../helpers/chains"; import customBackfill from "../../helpers/customBackfill"; import { Chain } from "@defillama/sdk/build/general"; @@ -14,15 +14,15 @@ const graphParams = { factory: "balancers", field: "totalSwapVolume", }, - hasDailyVolume: false, } -const graphs = getChainVolume({ +const graphs = getChainVolume2({ graphUrls: endpoints, ...graphParams }); const adapter: SimpleAdapter = { + version: 2, adapter: { [CHAIN.NEON]: { fetch: graphs(CHAIN.NEON), diff --git a/dexs/solarbeam/index.ts b/dexs/solarbeam/index.ts index be229ca2ed..27594fec41 100644 --- a/dexs/solarbeam/index.ts +++ b/dexs/solarbeam/index.ts @@ -1,10 +1,10 @@ +import * as sdk from "@defillama/sdk"; import { CHAIN } from "../../helpers/chains"; -import { univ2Adapter } from "../../helpers/getUniSubgraphVolume"; +import { univ2Adapter2 } from "../../helpers/getUniSubgraphVolume"; -const adapter = univ2Adapter({ - [CHAIN.MOONRIVER]: "https://api.thegraph.com/subgraphs/name/solarbeamio/amm-v2" +const adapter = univ2Adapter2({ + [CHAIN.MOONRIVER]: sdk.graph.modifyEndpoint('71vx2Ph76RyX8y7RRqzNKToMm4w6now3YBJjAWpGyUCP') },{ - hasTotalVolume: false, }); adapter.adapter.moonriver.start = 1630903340; export default adapter; diff --git a/dexs/solarflare/index.ts b/dexs/solarflare/index.ts index 9c2c0167fc..b436304c4a 100644 --- a/dexs/solarflare/index.ts +++ b/dexs/solarflare/index.ts @@ -1,9 +1,10 @@ +import * as sdk from "@defillama/sdk"; import { CHAIN } from "../../helpers/chains"; import { univ2Adapter } from "../../helpers/getUniSubgraphVolume"; const adapter = univ2Adapter({ - [CHAIN.MOONBEAM]: "https://api.thegraph.com/subgraphs/name/solarbeamio/solarflare-subgraph" + [CHAIN.MOONBEAM]: sdk.graph.modifyEndpoint('Cg4bWziUWqtUZrvZ6QZihsgUukAh6r8o5KZQzJRVkA31') },{}); adapter.adapter.moonbeam.start = 1642032000; export default adapter; diff --git a/dexs/solidly-v3/index.ts b/dexs/solidly-v3/index.ts index 24e9d98704..36e6404462 100644 --- a/dexs/solidly-v3/index.ts +++ b/dexs/solidly-v3/index.ts @@ -1,16 +1,15 @@ +import * as sdk from "@defillama/sdk"; import { CHAIN } from "../../helpers/chains"; -import { univ2Adapter } from "../../helpers/getUniSubgraphVolume"; +import { univ2Adapter2 } from "../../helpers/getUniSubgraphVolume"; -const adapters = univ2Adapter({ - [CHAIN.ETHEREUM]: "https://api.thegraph.com/subgraphs/name/solidlylabs/solidly-v3", - [CHAIN.BASE]: "https://api.studio.thegraph.com/query/64631/solidly-v3-base/version/latest", - [CHAIN.OPTIMISM]: "https://api.thegraph.com/subgraphs/name/solidlylabs/solidly-v3-optimism", - [CHAIN.ARBITRUM]: "https://api.thegraph.com/subgraphs/name/solidlylabs/solidly-v3-arbitrum", - [CHAIN.FANTOM]: "https://api.thegraph.com/subgraphs/name/solidlylabs/solidly-v3-fantom" +const adapters = univ2Adapter2({ + [CHAIN.ETHEREUM]: sdk.graph.modifyEndpoint('7StqFFqbxi3jcN5C9YxhRiTxQM8HA8XEHopsynqqxw3t'), + // [CHAIN.BASE]: "https://api.studio.thegraph.com/query/64631/solidly-v3-base/version/latest", + [CHAIN.OPTIMISM]: sdk.graph.modifyEndpoint('HCThb3gJC45qUYmNEaYmZZTqJW3pSq7X6tb4MqNHEvZf'), + [CHAIN.ARBITRUM]: sdk.graph.modifyEndpoint('ALCsbp7jWC6EQjwgicvZkG6dDEFGMV32QUZJvJGqL9Kx'), + [CHAIN.FANTOM]: sdk.graph.modifyEndpoint('HDNu25S2uqr13BHrQdPv2PfTpwxJgPB7QEnC8fsgKcM9') }, { factoriesName: "factories", - dayData: "solidlyDayData", - dailyVolume: "volumeUSD", totalVolume: "totalVolumeUSD", }); diff --git a/dexs/solidly/index.ts b/dexs/solidly/index.ts index b7400eda0d..68e5d7126d 100644 --- a/dexs/solidly/index.ts +++ b/dexs/solidly/index.ts @@ -1,16 +1,6 @@ -import { SimpleAdapter } from "../../adapters/types"; import { CHAIN } from "../../helpers/chains"; -import { getDexVolumeExports } from "../../helpers/dexVolumeLogs"; +import { uniV2Exports } from "../../helpers/uniswap"; -const FACTORY_ADDRESS = '0x3fAaB499b519fdC5819e3D7ed0C26111904cbc28' - -const adapter: SimpleAdapter = { - adapter: { - [CHAIN.FANTOM]: { - fetch: getDexVolumeExports({ chain: CHAIN.FANTOM, factory: FACTORY_ADDRESS,}), - start: 1644462536, - }, - } -}; - -export default adapter; \ No newline at end of file +export default uniV2Exports({ + [CHAIN.FANTOM]: { factory: '0x3fAaB499b519fdC5819e3D7ed0C26111904cbc28', }, +}) diff --git a/dexs/solidlydex/index.ts b/dexs/solidlydex/index.ts index 329e8ac946..fda7139ee2 100644 --- a/dexs/solidlydex/index.ts +++ b/dexs/solidlydex/index.ts @@ -1,8 +1,9 @@ +import * as sdk from "@defillama/sdk"; import { univ2Adapter } from "../../helpers/getUniSubgraphVolume"; import { CHAIN } from "../../helpers/chains"; const endpoints = { - [CHAIN.ETHEREUM]: "https://api.thegraph.com/subgraphs/name/0xc30/solidly", + [CHAIN.ETHEREUM]: sdk.graph.modifyEndpoint('4GX8RE9TzEWormbkayeGj4NQmmhYE46izVVUvXv8WPDh'), }; const adapter = univ2Adapter(endpoints, {}); diff --git a/dexs/soulswap/index.ts b/dexs/soulswap/index.ts index fe4a658be1..3d96133867 100644 --- a/dexs/soulswap/index.ts +++ b/dexs/soulswap/index.ts @@ -1,17 +1,18 @@ -import { getChainVolumeWithGasToken } from "../../helpers/getUniSubgraphVolume"; +import * as sdk from "@defillama/sdk"; +import { getChainVolumeWithGasToken2 } from "../../helpers/getUniSubgraphVolume"; import { getStartTimestamp } from "../../helpers/getStartTimestamp"; import { /*AVAX,*/ FANTOM } from "../../helpers/chains"; import { SimpleAdapter } from "../../adapters/types"; import { Chain } from "@defillama/sdk/build/general"; const endpoints = { - //[AVAX]: "https://api.thegraph.com/subgraphs/name/soulswapfinance/avalanche-exchange", - [FANTOM]: "https://api.thegraph.com/subgraphs/name/soulswapfinance/fantom-exchange", + //[AVAX]: sdk.graph.modifyEndpoint('Ao7hF1zBTZ6pkotKPguC536KkU9Gi4DQLBZFkLR5NafN'), + [FANTOM]: sdk.graph.modifyEndpoint('DftDSxq9ud7icPSKcEThpFLCgXd7Kx94ns8dK4Js63Fy'), }; const VOLUME_FIELD = "volumeUSD"; -const graphs = getChainVolumeWithGasToken({ +const graphs = getChainVolumeWithGasToken2({ graphUrls: { //[AVAX]: endpoints[AVAX], [FANTOM]: endpoints[FANTOM] @@ -20,10 +21,6 @@ const graphs = getChainVolumeWithGasToken({ factory: "factories", field: VOLUME_FIELD, }, - dailyVolume: { - factory: "dayData", - field: VOLUME_FIELD, - }, priceToken: "coingecko:fantom" }); @@ -45,6 +42,7 @@ const volume = Object.keys(endpoints).reduce( ); const adapter: SimpleAdapter = { + version: 2, adapter: volume, }; diff --git a/dexs/spacedex/index.ts b/dexs/spacedex/index.ts index 173bb443fc..8e27d91ade 100644 --- a/dexs/spacedex/index.ts +++ b/dexs/spacedex/index.ts @@ -1,11 +1,12 @@ +import * as sdk from "@defillama/sdk"; import request, { gql } from "graphql-request"; import { BreakdownAdapter, Fetch, SimpleAdapter } from "../../adapters/types"; import { CHAIN } from "../../helpers/chains"; import { getUniqStartOfTodayTimestamp } from "../../helpers/getUniSubgraphVolume"; const endpoints: { [key: string]: string } = { - [CHAIN.ARBITRUM]: "https://api.thegraph.com/subgraphs/name/spcdex-io/arbitrum-stats", - [CHAIN.BSC]: "https://api.thegraph.com/subgraphs/name/spcdex-io/bsc-stats", + [CHAIN.ARBITRUM]: sdk.graph.modifyEndpoint('9ob9R8ufkfEXnqp1s3izXjwQgXEnkSi9KXazYC9LdBC4'), + [CHAIN.BSC]: sdk.graph.modifyEndpoint('EMyH7BU8sp2sBCAtfDCqfnXyiKDUf3NbPpU6bg6vdAaH'), } const historicalDataSwap = gql` diff --git a/dexs/spacewhale/index.ts b/dexs/spacewhale/index.ts new file mode 100644 index 0000000000..ff7621824d --- /dev/null +++ b/dexs/spacewhale/index.ts @@ -0,0 +1,46 @@ +import ADDRESSES from '../../helpers/coreAssets.json' +import { FetchResult, SimpleAdapter } from "../../adapters/types"; +import { CHAIN } from "../../helpers/chains"; +import { gql, request } from "graphql-request"; +import { getUniqStartOfTodayTimestamp } from "../../helpers/getUniSubgraphVolume"; +import * as sdk from "@defillama/sdk"; + +interface IGraph { + volumeEth: string; + volumeUsdc: string; + id: string; +} + +const URL = 'https://api.studio.thegraph.com/query/84618/spacewhale1/0.0.5'; +const fetch = async (timestamp: number): Promise => { + const dayTimestamp = getUniqStartOfTodayTimestamp(new Date(timestamp * 1000)); + const chain = CHAIN.ARBITRUM; + const balances = new sdk.Balances({ chain, timestamp }) + const query = gql` + { + dayData(id: ${dayTimestamp * 1000}) { + volumeEth + volumeUsdc + } + }`; + const response: IGraph = (await request(URL, query)).dayData; + const element = response; + balances._add(ADDRESSES.arbitrum.USDC_CIRCLE, element.volumeUsdc); + balances._add(ADDRESSES.arbitrum.WETH, element.volumeEth); + + return { + dailyVolume: await balances.getUSDString(), + timestamp: dayTimestamp, + }; +} + +const adapter: SimpleAdapter = { + adapter: { + [CHAIN.ARBITRUM]: { + fetch: fetch, + start: async () => 1712109600, + }, + }, +}; + +export default adapter; diff --git a/dexs/sparkdex-v3/index.ts b/dexs/sparkdex-v3/index.ts new file mode 100644 index 0000000000..c96b4d7ffe --- /dev/null +++ b/dexs/sparkdex-v3/index.ts @@ -0,0 +1,60 @@ +import { Chain } from "@defillama/sdk/build/general"; +import { CHAIN } from "../../helpers/chains"; +import { getGraphDimensions2 } from "../../helpers/getUniSubgraph"; +import { BreakdownAdapter } from "../../adapters/types"; + +const endpointsV3 = { + [CHAIN.FLARE]: + "https://api.goldsky.com/api/public/project_cly4708cqpcj601tt7gzf1jdj/subgraphs/sparkdex-v3/latest/gn", +}; + +const v3Graphs = getGraphDimensions2({ + graphUrls: endpointsV3, + totalVolume: { + factory: "factories", + field: "totalVolumeUSD", + }, + feesPercent: { + type: "fees", + ProtocolRevenue: 0, + HoldersRevenue: 0, + UserFees: 100, // User fees are 100% of collected fees + SupplySideRevenue: 100, // 100% of fees are going to LPs + Revenue: 0, // Set revenue to 0 as protocol fee is not set for all pools for now + }, +}); + +const startTimeV3: { [key: string]: number } = { + [CHAIN.FLARE]: 1719878400, +}; + +const v3 = Object.keys(endpointsV3).reduce( + (acc, chain) => ({ + ...acc, + [chain]: { + fetch: v3Graphs(chain as Chain), + start: startTimeV3[chain], + meta: { + methodology: { + Fees: "Each pool charge between 0.01% to 1% fee", + UserFees: "Users pay between 0.01% to 1% fee", + Revenue: "0 to 1/4 of the fee goes to treasury", + HoldersRevenue: "None", + ProtocolRevenue: "Treasury receives a share of the fees", + SupplySideRevenue: + "Liquidity providers get most of the fees of all trades in their pools", + }, + }, + }, + }), + {} +); + +const adapter: BreakdownAdapter = { + version: 2, + breakdown: { + v3: v3, + }, +}; + +export default adapter; diff --git a/dexs/spartacus-exchange/index.ts b/dexs/spartacus-exchange/index.ts index d252541a60..cbb707d4f9 100644 --- a/dexs/spartacus-exchange/index.ts +++ b/dexs/spartacus-exchange/index.ts @@ -1,8 +1,9 @@ +import * as sdk from "@defillama/sdk"; import { CHAIN } from "../../helpers/chains"; import { univ2Adapter } from "../../helpers/getUniSubgraphVolume"; const endpoints = { - [CHAIN.FANTOM]: "https://api.thegraph.com/subgraphs/name/spartacus-finance/spadexinfo", + [CHAIN.FANTOM]: sdk.graph.modifyEndpoint('3kxULFsyJPAqbtCQUtQBH4Hktd6EboqCF22cVtkZg1eY'), }; const adapter = univ2Adapter(endpoints, {"gasToken" : "coingecko:fantom"}); adapter.adapter.fantom.start = 1650883041; diff --git a/dexs/spartan/index.ts b/dexs/spartan/index.ts index f40f303357..1a77f0e1b6 100644 --- a/dexs/spartan/index.ts +++ b/dexs/spartan/index.ts @@ -1,3 +1,4 @@ +import * as sdk from "@defillama/sdk"; import { Chain } from "@defillama/sdk/build/general"; import { gql, GraphQLClient } from "graphql-request"; import { FetchResultVolume, SimpleAdapter } from "../../adapters/types"; @@ -14,7 +15,7 @@ const getDailyVolume = () => { }` } -const graphQLClient = new GraphQLClient("https://api.thegraph.com/subgraphs/name/spartan-protocol/pool-factory"); +const graphQLClient = new GraphQLClient(sdk.graph.modifyEndpoint('9vN1kRac6B224oTjNnFe9vYnJXj5fxaa3ivDfg1hh3v5')); const getGQLClient = () => { return graphQLClient } diff --git a/dexs/sphynx/index.ts b/dexs/sphynx/index.ts index fcb28fdc13..8dc5d1c3ba 100644 --- a/dexs/sphynx/index.ts +++ b/dexs/sphynx/index.ts @@ -1,8 +1,9 @@ +import * as sdk from "@defillama/sdk"; import { CHAIN } from "../../helpers/chains"; import { univ2Adapter } from "../../helpers/getUniSubgraphVolume"; const adapters = univ2Adapter({ - [CHAIN.BSC]: "https://api.thegraph.com/subgraphs/name/sphynxswap/exchange", + [CHAIN.BSC]: sdk.graph.modifyEndpoint('C4bw9Bt2Ewbx1pB6uYwduNXpWQAc4HRSayc6KeNy2n1b'), // [CHAIN.CRONOS]: "https://crnode.thesphynx.co/graph/subgraphs/name/exchange/cronos", [CHAIN.BITGERT]: "https://brgraph.thesphynx.co/subgraphs/name/exchange/brise" }, { diff --git a/dexs/spiritswap/index.ts b/dexs/spiritswap/index.ts index deacfecce3..2343621998 100644 --- a/dexs/spiritswap/index.ts +++ b/dexs/spiritswap/index.ts @@ -1,15 +1,12 @@ import { SimpleAdapter } from "../../adapters/types"; - -const { - getChainVolumeWithGasToken, -} = require("../../helpers/getUniSubgraphVolume"); +import * as sdk from "@defillama/sdk"; +import { getChainVolumeWithGasToken2 } from "../../helpers/getUniSubgraphVolume"; const endpoints = { - fantom: - "https://api.thegraph.com/subgraphs/name/layer3org/spiritswap-analytics", + fantom: sdk.graph.modifyEndpoint('E6viiLSqVvjLy9re7aBPkaXAB2itNDho2LR3CP2q1uqP'), }; -const graphs = getChainVolumeWithGasToken({ +const graphs = getChainVolumeWithGasToken2({ graphUrls: { fantom: endpoints.fantom, }, @@ -17,14 +14,11 @@ const graphs = getChainVolumeWithGasToken({ factory: "spiritswapFactories", field: 'totalVolumeFTM', }, - dailyVolume: { - factory: "spiritswapDayData", - field: 'dailyVolumeFTM', - }, priceToken: "coingecko:fantom" }); const adapter: SimpleAdapter = { + version: 2, adapter: { fantom: { fetch: graphs("fantom"), diff --git a/dexs/spookyswap/index.ts b/dexs/spookyswap/index.ts index 0635d1441d..b2ddc566ad 100644 --- a/dexs/spookyswap/index.ts +++ b/dexs/spookyswap/index.ts @@ -1,29 +1,31 @@ +import * as sdk from "@defillama/sdk"; import { SimpleAdapter } from "../../adapters/types"; import { CHAIN } from "../../helpers/chains"; import { getStartTimestamp } from "../../helpers/getStartTimestamp"; -import { DEFAULT_DAILY_VOLUME_FIELD, DEFAULT_TOTAL_VOLUME_FIELD, getChainVolume } from "../../helpers/getUniSubgraphVolume"; - -const { getChainVolumeWithGasToken } = require("../../helpers/getUniSubgraphVolume"); +import { DEFAULT_TOTAL_VOLUME_FIELD, getChainVolume2, getChainVolumeWithGasToken2 } from "../../helpers/getUniSubgraphVolume"; const { FANTOM } = require("../../helpers/chains"); + const endpoints = { - [FANTOM]: "https://api.thegraph.com/subgraphs/name/eerieeight/spookyswap", + [FANTOM]: sdk.graph.modifyEndpoint('HyhMfT7gehNHMBmFiExqeg3pDtop9UikjvBPfAXT3b21'), [CHAIN.EON]: "https://eon-graph.horizenlabs.io/subgraphs/name/0xALUKARD/spookyswap-eon", + // [CHAIN.BITTORRENT]: "https://subgraph.spook.fi/subgraphs/name/eerieeight/spooky-swap-new" }; -const graphs = getChainVolumeWithGasToken({ +const graphs = getChainVolumeWithGasToken2({ graphUrls: { [FANTOM]: endpoints[FANTOM], }, - priceToken: "coingecko:fantom" + priceToken: "coingecko:fantom", + totalVolume: { + factory: "uniswapFactories", + field: DEFAULT_TOTAL_VOLUME_FIELD, + }, }); -const graphsV3 = getChainVolume({ +const graphsV3 = getChainVolume2({ graphUrls: { [CHAIN.EON]: endpoints[CHAIN.EON], - }, - dailyVolume: { - factory: "uniswapDayData", - field: DEFAULT_DAILY_VOLUME_FIELD, + // [CHAIN.BITTORRENT]: endpoints[CHAIN.BITTORRENT] }, totalVolume: { factory: "uniswapFactories", @@ -32,6 +34,7 @@ const graphsV3 = getChainVolume({ }); const adapter: SimpleAdapter = { + version: 2, adapter: { [FANTOM]: { fetch: graphs(FANTOM), @@ -44,6 +47,10 @@ const adapter: SimpleAdapter = { fetch: graphsV3(CHAIN.EON), start: 1698969600 }, + // [CHAIN.BITTORRENT]: { + // fetch: graphsV3(CHAIN.BITTORRENT), + // start: 23534368 + // }, }, }; diff --git a/dexs/squadswap-v2/index.ts b/dexs/squadswap-v2/index.ts index 60c6843f9f..eb0a58773b 100644 --- a/dexs/squadswap-v2/index.ts +++ b/dexs/squadswap-v2/index.ts @@ -1,22 +1,19 @@ -import { DEFAULT_TOTAL_VOLUME_FIELD, univ2Adapter } from "../../helpers/getUniSubgraphVolume"; +import * as sdk from "@defillama/sdk"; +import { DEFAULT_TOTAL_VOLUME_FIELD } from "../../helpers/getUniSubgraphVolume"; import { CHAIN } from "../../helpers/chains"; -import { DEFAULT_DAILY_VOLUME_FIELD, getGraphDimensions } from "../../helpers/getUniSubgraph"; +import { getGraphDimensions2 } from "../../helpers/getUniSubgraph"; import { SimpleAdapter } from "../../adapters/types"; const endpoints = { - [CHAIN.BSC]: "https://api.thegraph.com/subgraphs/name/q1q0/squad-exchange", + [CHAIN.BSC]: sdk.graph.modifyEndpoint('FDn5m4S3bFqd8TV97P61i3dhZLpSigFwpRQEan2mrjTE'), }; -const v2Graph = getGraphDimensions({ +const v2Graph = getGraphDimensions2({ graphUrls: endpoints, totalVolume: { factory: "pancakeFactories", field: DEFAULT_TOTAL_VOLUME_FIELD, }, - dailyVolume: { - factory: "pancakeDayData", - field: DEFAULT_DAILY_VOLUME_FIELD, - }, feesPercent: { type: "volume", Fees: 0.02, @@ -29,6 +26,7 @@ const v2Graph = getGraphDimensions({ }); const adapter: SimpleAdapter = { + version: 2, adapter: { [CHAIN.BSC]: { fetch: v2Graph(CHAIN.BSC), diff --git a/dexs/squadswap-v3/index.ts b/dexs/squadswap-v3/index.ts index c65dd3f019..8aac3161bb 100644 --- a/dexs/squadswap-v3/index.ts +++ b/dexs/squadswap-v3/index.ts @@ -1,27 +1,19 @@ +import * as sdk from "@defillama/sdk"; import { SimpleAdapter } from "../../adapters/types"; -import { getStartTimestamp } from "../../helpers/getStartTimestamp"; -import { DEFAULT_DAILY_VOLUME_FIELD, DEFAULT_TOTAL_VOLUME_FIELD, getChainVolume } from "../../helpers/getUniSubgraphVolume"; +import { DEFAULT_TOTAL_VOLUME_FIELD } from "../../helpers/getUniSubgraphVolume"; import { CHAIN } from "../../helpers/chains"; -import { getGraphDimensions } from "../../helpers/getUniSubgraph"; +import { getGraphDimensions2 } from "../../helpers/getUniSubgraph"; const endpoints = { - [CHAIN.BSC]: "https://api.thegraph.com/subgraphs/name/carlos53093/exchange-v3", + [CHAIN.BSC]: sdk.graph.modifyEndpoint('CTCJRpNgyiCMaQhPsKTWfsCfFBSPkzaQKKi2EjMyidCt'), }; -const v3Graphs = getGraphDimensions({ +const v3Graphs = getGraphDimensions2({ graphUrls: endpoints, totalVolume: { factory: "factories", field: DEFAULT_TOTAL_VOLUME_FIELD, }, - dailyVolume: { - factory: "pancakeDayData", - field: "volumeUSD", - }, - dailyFees: { - factory: "pancakeDayData", - field: "feesUSD", - }, feesPercent: { type: "fees", ProtocolRevenue: 25, @@ -33,6 +25,7 @@ const v3Graphs = getGraphDimensions({ }); const adapter: SimpleAdapter = { + version: 2, adapter: { [CHAIN.BSC]: { fetch: v3Graphs(CHAIN.BSC), diff --git a/dexs/stabble/index.ts b/dexs/stabble/index.ts new file mode 100644 index 0000000000..b079393dc1 --- /dev/null +++ b/dexs/stabble/index.ts @@ -0,0 +1,21 @@ +import { CHAIN } from '../../helpers/chains'; +import { httpGet } from '../../utils/fetchURL'; + +async function fetch(timestamp: number) { + const dailyVolume = await httpGet('https://api.stabble.org/stats/volume?type=daily'); + return { + dailyVolume: dailyVolume, + timestamp: timestamp + } +} + +export default { + version: 2, + adapter: { + [CHAIN.SOLANA]: { + fetch: fetch, + runAtCurrTime: true, + start: 1717563162, + } + } +} diff --git a/dexs/stellaswap-v3/index.ts b/dexs/stellaswap-v3/index.ts index 75d2ec79f4..b1404ecab7 100644 --- a/dexs/stellaswap-v3/index.ts +++ b/dexs/stellaswap-v3/index.ts @@ -1,9 +1,10 @@ +import * as sdk from "@defillama/sdk"; // https://api.thegraph.com/subgraphs/name/stellaswap/pulsar import { CHAIN } from "../../helpers/chains"; import { univ2Adapter } from "../../helpers/getUniSubgraphVolume"; const adapters = univ2Adapter({ - [CHAIN.MOONBEAN]: "https://api.thegraph.com/subgraphs/name/stellaswap/pulsar" + [CHAIN.MOONBEAN]: sdk.graph.modifyEndpoint('85R1ZetugVABa7BiqKFqE2MewRuJ8b2SaLHffyTHDAht') }, { factoriesName: "factories", dayData: "algebraDayData", diff --git a/dexs/stellaswap/index.ts b/dexs/stellaswap/index.ts index b4bf383148..2b73a4ed20 100644 --- a/dexs/stellaswap/index.ts +++ b/dexs/stellaswap/index.ts @@ -1,8 +1,9 @@ +import * as sdk from "@defillama/sdk"; import { CHAIN } from "../../helpers/chains"; -import { univ2Adapter } from "../../helpers/getUniSubgraphVolume"; +import { univ2Adapter2 } from "../../helpers/getUniSubgraphVolume"; -const adapters = univ2Adapter({ - [CHAIN.MOONBEAN]: "https://api.thegraph.com/subgraphs/name/stellaswap/stella-swap" +const adapters = univ2Adapter2({ + [CHAIN.MOONBEAN]: sdk.graph.modifyEndpoint('HgSAfZvHEDbAVuZciPUYEqFzhAUnjJWmyix5C1R2tmTp') }, {}); adapters.adapter.moonbeam.start = 1641960253; export default adapters; diff --git a/dexs/ston/index.ts b/dexs/ston/index.ts new file mode 100644 index 0000000000..173471c19b --- /dev/null +++ b/dexs/ston/index.ts @@ -0,0 +1,30 @@ +import postURL from "../../utils/fetchURL" +import { CHAIN } from "../../helpers/chains"; +import { FetchOptions } from "../../adapters/types"; + +const endpoint = "https://api.ston.fi/v1/stats/dex?" + + +const fetch = async (options: FetchOptions) => { + const startTime = new Date(options.startTimestamp * 1000).toISOString().split(".")[0] + const endTime = new Date(options.endTimestamp * 1000).toISOString().split(".")[0] + const res = await postURL(`${endpoint}since=${startTime}&until=${endTime}`) + + return { + dailyVolume: parseInt(res['stats']['volume_usd']), + timestamp: options.startTimestamp, + }; +}; + + +const adapter: any = { + version: 2, + adapter: { + [CHAIN.TON]: { + fetch, + start: 1668801600, + }, + }, +}; + +export default adapter; diff --git a/dexs/stormtrade/index.ts b/dexs/stormtrade/index.ts index e728aba5d8..93a252865d 100644 --- a/dexs/stormtrade/index.ts +++ b/dexs/stormtrade/index.ts @@ -1,6 +1,8 @@ +import { time } from 'console'; import { CHAIN } from '../../helpers/chains' -import fetchURL from '../../utils/fetchURL' +import { postURL } from '../../utils/fetchURL' +const GRAPHQL_ENDPOINT = 'https://api5.storm.tg/graphql'; export default { adapter: { @@ -10,15 +12,23 @@ export default { meta: { methodology: { DailyVolume: 'Leverage trading volume', - DataSource: 'Data collected by the re:doubt team, available at https://beta.redoubt.online/tracker' + DataSource: 'Data prepared by the project team by indexing blockchain data' }, }, - fetch: async () => { - const response = await fetchURL('https://api.redoubt.online/dapps/v1/export/defi/storm') + fetch: async (timestamp: number) => { + const response = (await postURL(GRAPHQL_ENDPOINT, { + query: ` + query VolumeDaily { + marketInfo { + exchangedTradeVolume + } + } + ` + })); return { - dailyVolume: response.volume.toString(), - timestamp: response.timestamp + dailyVolume: response.data.marketInfo.exchangedTradeVolume / 1e9, + timestamp: new Date().getTime() / 1000 } }, }, diff --git a/dexs/subzero-zswap/index.ts b/dexs/subzero-zswap/index.ts index 74e36393f0..2d79428209 100644 --- a/dexs/subzero-zswap/index.ts +++ b/dexs/subzero-zswap/index.ts @@ -1,8 +1,9 @@ +import * as sdk from "@defillama/sdk"; import { univ2Adapter } from "../../helpers/getUniSubgraphVolume"; import { CHAIN } from "../../helpers/chains"; const endpoints = { - [CHAIN.AVAX]: "https://api.thegraph.com/subgraphs/name/mkrman/exchange", + [CHAIN.AVAX]: sdk.graph.modifyEndpoint('7L3pXgL3sBVDkCjZjautaRjPr5u4dcUsG1KK6vj4XCec'), }; const adapter = univ2Adapter(endpoints, { diff --git a/dexs/sundaeswap/index.ts b/dexs/sundaeswap/index.ts index 28bf483299..802e11fd04 100644 --- a/dexs/sundaeswap/index.ts +++ b/dexs/sundaeswap/index.ts @@ -1,8 +1,7 @@ -import fetchURL from "../../utils/fetchURL" -import { ChainBlocks, DISABLED_ADAPTER_KEY, FetchOptions, FetchResultVolume, SimpleAdapter } from "../../adapters/types"; +import fetchURL from "../../utils/fetchURL"; +import { FetchOptions, FetchResult, FetchResultV2, FetchResultVolume, SimpleAdapter } from "../../adapters/types"; import { CHAIN } from "../../helpers/chains"; -import { getUniqStartOfTodayTimestamp } from "../../helpers/getUniSubgraphVolume"; -import disabledAdapter from "../../helpers/disabledAdapter"; +import { getTimestampAtStartOfDayUTC } from "../../utils/date"; const historicalVolumeEndpoint = "https://stats.sundaeswap.finance/api/defillama/v0/global-stats/2100" @@ -11,21 +10,27 @@ interface IVolumeall { day: string; } -const fetch = async (timestamp: number, _: ChainBlocks, { createBalances, startOfDay }: FetchOptions): Promise => { +const fetch = async (_,_a:any,{ createBalances, startOfDay }: FetchOptions): Promise => { const dailyVolume = createBalances() + const dayTimestamp = getTimestampAtStartOfDayUTC(startOfDay); + const dateStr = new Date(dayTimestamp * 1000).toISOString().split('T')[0]; const historicalVolume: IVolumeall[] = (await fetchURL(historicalVolumeEndpoint)).response; - - dailyVolume.addGasToken(historicalVolume - .find(dayItem => getUniqStartOfTodayTimestamp(new Date(dayItem.day)) === startOfDay)?.volumeLovelace as any) + const volume = historicalVolume.find(dayItem => dayItem.day === dateStr)?.volumeLovelace as any + if (!volume) { + return { + timestamp: dayTimestamp, + } + } + dailyVolume.addGasToken(volume) return { + timestamp: dayTimestamp, dailyVolume, - timestamp: startOfDay, }; }; const adapter: SimpleAdapter = { + version: 1, adapter: { - [DISABLED_ADAPTER_KEY]: disabledAdapter, [CHAIN.CARDANO]: { fetch, start: 1643673600, diff --git a/dexs/supswap-v2/index.ts b/dexs/supswap-v2/index.ts index 7efae4a30f..a941155a96 100644 --- a/dexs/supswap-v2/index.ts +++ b/dexs/supswap-v2/index.ts @@ -1,21 +1,17 @@ import { SimpleAdapter } from "../../adapters/types"; import { CHAIN } from "../../helpers/chains"; -import { DEFAULT_TOTAL_VOLUME_FIELD, getGraphDimensions } from "../../helpers/getUniSubgraph"; +import { DEFAULT_TOTAL_VOLUME_FIELD, getGraphDimensions2 } from "../../helpers/getUniSubgraph"; const v2Endpoints = { [CHAIN.MODE]: "https://api.goldsky.com/api/public/project_clrhmyxsvvuao01tu4aqj653e/subgraphs/supswap-exchange-v2/1.0.0/gn" } -const v2Graphs = getGraphDimensions({ +const v2Graphs = getGraphDimensions2({ graphUrls: v2Endpoints, totalVolume: { factory: "supFactories", field: DEFAULT_TOTAL_VOLUME_FIELD, }, - dailyVolume: { - factory: "supDayData", - field: "dailyVolumeUSD", - }, feesPercent: { type: "volume", ProtocolRevenue: 0.08, @@ -28,6 +24,7 @@ const v2Graphs = getGraphDimensions({ }); const adapter: SimpleAdapter = { + version: 2, adapter: { [CHAIN.MODE]: { fetch: v2Graphs(CHAIN.MODE), diff --git a/dexs/supswap-v3/index.ts b/dexs/supswap-v3/index.ts index d09a6cb0f7..23a2d8948a 100644 --- a/dexs/supswap-v3/index.ts +++ b/dexs/supswap-v3/index.ts @@ -1,27 +1,17 @@ import { SimpleAdapter } from "../../adapters/types"; import { CHAIN } from "../../helpers/chains"; -import { DEFAULT_TOTAL_VOLUME_FIELD, getGraphDimensions } from "../../helpers/getUniSubgraph"; +import { DEFAULT_TOTAL_VOLUME_FIELD, getGraphDimensions2 } from "../../helpers/getUniSubgraph"; const v3Endpoints = { [CHAIN.MODE]: "https://api.goldsky.com/api/public/project_clrhmyxsvvuao01tu4aqj653e/subgraphs/supswap-exchange-v3/1.0.0/gn" } -const VOLUME_USD = "volumeUSD"; - -const v3Graphs = getGraphDimensions({ +const v3Graphs = getGraphDimensions2({ graphUrls: v3Endpoints, totalVolume: { factory: "factories", field: DEFAULT_TOTAL_VOLUME_FIELD, }, - dailyVolume: { - factory: "supDayData", - field: VOLUME_USD, - }, - dailyFees: { - factory: "supDayData", - field: "feesUSD", - }, feesPercent: { type: "fees", ProtocolRevenue: 33.33, @@ -34,6 +24,7 @@ const v3Graphs = getGraphDimensions({ }); const adapter: SimpleAdapter = { + version: 2, adapter: { [CHAIN.MODE]: { fetch: v3Graphs(CHAIN.MODE), diff --git a/dexs/surfone/index.ts b/dexs/surfone/index.ts index 56228b97d9..3417ba1c11 100644 --- a/dexs/surfone/index.ts +++ b/dexs/surfone/index.ts @@ -3,26 +3,28 @@ import { CHAIN } from "../../helpers/chains"; import { getUniqStartOfTodayTimestamp } from "../../helpers/getUniSubgraphVolume"; import { httpGet } from "../../utils/fetchURL"; -const volumeEndpoint = "https://apigateway.surf.one/pool/24h/data" +// const volumeEndpoint = "https://apigateway.surf.one/pool/24h/data" +const volumeEndpointV2 = "https://apigateway.surf.one/v2/market/total/stat" const headers = { - "Block-Chain-Id": '8453', + "Block-Chain-Id":"4200", + "user-agent":"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/122.0.0.0 Safari/537.36" }; interface IVolume { - totalVolume: number, - totalTradeSize: number, + 'total_vol': number, + '24h_vol': number, } const fetch = () => { return async (timestamp: number) => { const dayTimestamp = getUniqStartOfTodayTimestamp(new Date(timestamp * 1000)) - const response = (await httpGet(volumeEndpoint, { headers })); + const response = (await httpGet(volumeEndpointV2, { headers })); const volume: IVolume = response.data; return { - totalVolume: `${volume?.totalVolume || undefined}`, - dailyVolume: `${volume?.totalTradeSize || undefined}`, + totalVolume: `${volume?.total_vol || undefined}`, + dailyVolume: `${volume['24h_vol'] || undefined}`, timestamp: dayTimestamp, }; }; @@ -31,10 +33,10 @@ const fetch = () => { const adapter: SimpleAdapter = { adapter: { - [CHAIN.BASE]: { + ['merlin']: { fetch: fetch(), runAtCurrTime: true, - start: 7963804, + start: 9142115, } }, }; diff --git a/dexs/surfswap/index.ts b/dexs/surfswap/index.ts index 661b7f624a..1af9bb0250 100644 --- a/dexs/surfswap/index.ts +++ b/dexs/surfswap/index.ts @@ -1,5 +1,5 @@ import { ChainEndpoints, BreakdownAdapter } from "../../adapters/types"; -import { getGraphDimensions } from "../../helpers/getUniSubgraph"; +import { getGraphDimensions2 } from "../../helpers/getUniSubgraph"; import { CHAIN } from "../../helpers/chains"; import { Chain } from "@defillama/sdk/build/general"; import request, { gql } from "graphql-request"; @@ -37,20 +37,16 @@ const getCustomBlock = async (timestamp: number) => { return Number(block.blocks[0].number); }; -const graphs = getGraphDimensions({ +const graphs = getGraphDimensions2({ graphUrls: endpoints, totalVolume: { factory: "uniswapFactories", field: "totalVolumeUSD", }, - dailyVolume: { - factory: "uniswapDayData", - field: "dailyVolumeUSD", - }, getCustomBlock }); -const v1graphs = getGraphDimensions({ +const v1graphs = getGraphDimensions2({ graphUrls: { [CHAIN.KAVA]: "https://the-graph.kava.io/subgraphs/name/surfswap-stable-amm", }, @@ -58,15 +54,11 @@ const v1graphs = getGraphDimensions({ factory: "tradeVolumes", field: "volume", }, - dailyVolume: { - factory: "dailyVolume", - field: "volume", - dateField: "timestamp" - }, getCustomBlock }); const adapter: BreakdownAdapter = { + version: 2, breakdown: { classic: { [CHAIN.KAVA]: { diff --git a/dexs/sushiswap/classic.ts b/dexs/sushiswap/classic.ts index dd67edfb45..fdee10fb47 100644 --- a/dexs/sushiswap/classic.ts +++ b/dexs/sushiswap/classic.ts @@ -1,12 +1,10 @@ +import * as sdk from "@defillama/sdk"; import { Chain } from "@defillama/sdk/build/general"; import { getStartTimestamp } from "../../helpers/getStartTimestamp"; -import { - CHAIN, -} from "../../helpers/chains"; -import { getGraphDimensions } from "../../helpers/getUniSubgraph"; -import { - getChainVolumeWithGasToken, -} from "../../helpers/getUniSubgraphVolume"; +import { CHAIN } from "../../helpers/chains"; +import { getGraphDimensions2 } from "../../helpers/getUniSubgraph"; +import { getChainVolumeWithGasToken2 } from "../../helpers/getUniSubgraphVolume"; +import { FetchOptions } from "../../adapters/types"; const blacklistTokens = { [CHAIN.ARBITRUM]: [ @@ -52,19 +50,21 @@ const blacklistTokens = { } const endpointsClassic = { - [CHAIN.ETHEREUM]: "https://api.thegraph.com/subgraphs/name/sushiswap/exchange", - [CHAIN.BSC]: "https://api.thegraph.com/subgraphs/name/sushiswap/bsc-exchange", - [CHAIN.POLYGON]: "https://api.thegraph.com/subgraphs/name/sushiswap/matic-exchange", - //[CHAIN.FANTOM]: "https://api.thegraph.com/subgraphs/name/sushiswap/fantom-exchange", - [CHAIN.ARBITRUM]: "https://api.thegraph.com/subgraphs/name/sushiswap/arbitrum-exchange", - [CHAIN.CELO]: "https://api.thegraph.com/subgraphs/name/sushiswap/celo-exchange", - [CHAIN.AVAX]: "https://api.thegraph.com/subgraphs/name/sushiswap/avalanche-exchange", - [CHAIN.HARMONY]: "https://api.thegraph.com/subgraphs/name/sushiswap/harmony-exchange", - // [CHAIN.MOONRIVER]: "https://api.thegraph.com/subgraphs/name/sushiswap/moonriver-exchange", - [CHAIN.XDAI]: "https://api.thegraph.com/subgraphs/name/sushiswap/xdai-exchange", - // [CHAIN.MOONBEAM]: 'https://api.thegraph.com/subgraphs/name/sushiswap/exchange-moonbeam', - [CHAIN.BOBA]: 'https://api.thegraph.com/subgraphs/name/sushi-v2/sushiswap-boba', - [CHAIN.FUSE]: 'https://api.thegraph.com/subgraphs/name/sushiswap/exchange-fuse', + [CHAIN.ETHEREUM]: sdk.graph.modifyEndpoint('6NUtT5mGjZ1tSshKLf5Q3uEEJtjBZJo1TpL5MXsUBqrT'), + [CHAIN.BSC]: sdk.graph.modifyEndpoint('GPRigpbNuPkxkwpSbDuYXbikodNJfurc1LCENLzboWer'), + [CHAIN.POLYGON]: sdk.graph.modifyEndpoint('8NiXkxLRT3R22vpwLB4DXttpEf3X1LrKhe4T1tQ3jjbP'), + //[CHAIN.FANTOM]: sdk.graph.modifyEndpoint('3nozHyFKUhxnEvekFg5G57bxPC5V63eiWbwmgA35N5VK'), + [CHAIN.ARBITRUM]: sdk.graph.modifyEndpoint('8nFDCAhdnJQEhQF3ZRnfWkJ6FkRsfAiiVabVn4eGoAZH'), + // [CHAIN.CELO]: sdk.graph.modifyEndpoint('8roCC7H2tsGYGvxD52QQbUoHXXx77H9tPhNn1qcjB5yj'), + [CHAIN.AVAX]: sdk.graph.modifyEndpoint('6VAhbtW5u2sPYkJKAcMsxgqTBu4a1rqmbiVQWgtNjrvT'), + [CHAIN.HARMONY]: sdk.graph.modifyEndpoint('FrcJBCCKCYGTLLXJmhppXfPKsNoyod4zqNLjHfXj1KHg'), + // [CHAIN.MOONRIVER]: sdk.graph.modifyEndpoint('5skUrJzgVm6vXAmdKN7gw4CjYx3pgLDeUeUqVzqLXkWT'), + [CHAIN.XDAI]: sdk.graph.modifyEndpoint('4a8hcsttqsmycmmeFcpffGMZhBDU4NhHfyHH6YNcnu7b'), + // [CHAIN.MOONBEAM]: sdk.graph.modifyEndpoint('3tNHz9aTBa2KUthYZiZZxayYYpxXACverKRrkafhoBru'), + [CHAIN.BOBA]: sdk.graph.modifyEndpoint('EC3ZtCpCaV5GyyhyPNHs584wdGA72nud7qcuxWNTfPr4'), + [CHAIN.FUSE]: sdk.graph.modifyEndpoint('DcaAUrnx2mWKVQNsVJiuz7zhjoLkvtDUcoq73NdBvbTo'), + [CHAIN.CORE]: 'https://thegraph.coredao.org/subgraphs/name/sushi-v2/sushiswap-core', + [CHAIN.BLAST]: 'https://api.goldsky.com/api/public/project_clslspm3c0knv01wvgfb2fqyq/subgraphs/sushiswap/sushiswap-blast/gn', }; const VOLUME_FIELD = "volumeUSD"; @@ -79,31 +79,22 @@ const feesPercent = { SupplySideRevenue: 0.25 } -const graphsClassic = getGraphDimensions({ +const graphsClassic = getGraphDimensions2({ graphUrls: endpointsClassic, totalVolume: { factory: "factories", field: VOLUME_FIELD, }, - dailyVolume: { - factory: "dayData", - field: VOLUME_FIELD, - }, feesPercent, blacklistTokens }); -const graphsClassicBoba = getGraphDimensions({ +const graphsClassicBoba = getGraphDimensions2({ graphUrls: endpointsClassic, totalVolume: { factory: "factories", field: VOLUME_FIELD, }, - dailyVolume: { - factory: "factoryDaySnapshot", - field: VOLUME_FIELD, - dateField: "date" - }, feesPercent }); @@ -117,8 +108,32 @@ const classic = Object.keys(endpointsClassic).reduce( (acc, chain) => ({ ...acc, [chain]: { - fetch: chain == "boba" ? graphsClassicBoba(chain as Chain) : graphsClassic(chain as Chain), - start: chain == "boba" ? getStartTimestamp({ ...startTimeQueryClassic, dailyDataField: "factoryDaySnapshots", chain }) : getStartTimestamp({ ...startTimeQueryClassic, chain }), + fetch: async (options: FetchOptions) => { + try { + const call = chain === CHAIN.BOBA ? graphsClassicBoba : graphsClassic; + const values = (await call(chain)(options)); + return { + dailyVolume: values?.dailyVolume || 0, + dailyFees: values?.dailyFees || 0, + dailyUserFees: values?.dailyUserFees || 0, + dailyProtocolRevenue: values?.dailyProtocolRevenue || 0, + dailySupplySideRevenue: values?.dailySupplySideRevenue || 0, + dailyHoldersRevenue: values?.dailyHoldersRevenue || 0, + dailyRevenue: values?.dailyRevenue || 0, + } + } catch { + return { + dailyVolume: 0, + dailyFees: 0, + dailyUserFees: 0, + dailyProtocolRevenue: 0, + dailySupplySideRevenue: 0, + dailyHoldersRevenue: 0, + dailyRevenue: 0, + } + } + }, + start: 1711982400, meta: { methodology: { Fees: "SushiSwap charges a flat 0.3% fee", @@ -134,24 +149,20 @@ const classic = Object.keys(endpointsClassic).reduce( {} ) as any; -const fantomGraphs = getChainVolumeWithGasToken({ +const fantomGraphs = getChainVolumeWithGasToken2({ graphUrls: { - [CHAIN.FANTOM]: "https://api.thegraph.com/subgraphs/name/sushiswap/fantom-exchange" + [CHAIN.FANTOM]: sdk.graph.modifyEndpoint('3nozHyFKUhxnEvekFg5G57bxPC5V63eiWbwmgA35N5VK') }, totalVolume: { factory: "factories", field: 'volumeETH', }, - dailyVolume: { - factory: "dayData", - field: 'volumeETH', - dateField: "date" - }, priceToken: "coingecko:fantom" } as any); + classic[CHAIN.FANTOM] = { - fetch: async (timestamp: number) => { - const values = await fantomGraphs(CHAIN.FANTOM)(timestamp, {}); + fetch: async (options: FetchOptions) => { + const values = await fantomGraphs(CHAIN.FANTOM)(options); const vol = Number(values.dailyVolume) return { ...values, diff --git a/dexs/sushiswap/index.ts b/dexs/sushiswap/index.ts index 13967b4393..3f5b34e4dc 100644 --- a/dexs/sushiswap/index.ts +++ b/dexs/sushiswap/index.ts @@ -2,9 +2,12 @@ import { BreakdownAdapter } from "../../adapters/types"; import trident from './trident' import classic from './classic' import v3 from './v3' +import swap from './swap' const adapter: BreakdownAdapter = { + version: 2, breakdown: { + "agg-dex": swap, classic: classic, trident: trident, v3: v3 diff --git a/dexs/sushiswap/swap.ts b/dexs/sushiswap/swap.ts new file mode 100644 index 0000000000..147a0953ee --- /dev/null +++ b/dexs/sushiswap/swap.ts @@ -0,0 +1,338 @@ +import axios from "axios"; +import { FetchResultV2, FetchV2 } from "../../adapters/types"; +import { CHAIN } from "../../helpers/chains"; + +const ROUTE_EVENT = 'event Route(address indexed from, address to, address indexed tokenIn, address indexed tokenOut, uint256 amountIn, uint256 amountOutMin,uint256 amountOut)' + +const CHAIN_ID = { + [CHAIN.ETHEREUM]: 1, + [CHAIN.ARBITRUM]: 42161, + [CHAIN.OPTIMISM]: 10, + [CHAIN.BASE]: 8453, + [CHAIN.POLYGON]: 137, + [CHAIN.AVAX]: 43114, + [CHAIN.BSC]: 56, + [CHAIN.LINEA]: 59144, + [CHAIN.ARBITRUM_NOVA]: 42170, + [CHAIN.XDAI]: 100, + [CHAIN.FANTOM]: 250, + [CHAIN.BITTORRENT]: 199, + [CHAIN.CELO]: 42220, + [CHAIN.FILECOIN]: 314, + [CHAIN.HAQQ]: 11235, + [CHAIN.KAVA]: 2222, + [CHAIN.METIS]: 1088, + [CHAIN.THUNDERCORE]: 108, + [CHAIN.SCROLL]: 534352, + [CHAIN.ZETA]: 7000, + [CHAIN.MOONBEAM]: 1284, + [CHAIN.MOONRIVER]: 1285, + [CHAIN.POLYGON_ZKEVM]: 1101, + [CHAIN.FUSE]: 122, + [CHAIN.HARMONY]: 1666600000, + [CHAIN.TELOS]: 40, + [CHAIN.BOBA]: 288, + [CHAIN.BOBA_BNB]: 56288, + [CHAIN.CORE]: 1116, + [CHAIN.CRONOS]: 81457, + [CHAIN.BLAST]: 81457, + [CHAIN.SKALE_EUROPA]: 2046399126, + [CHAIN.ROOTSTOCK]: 30, +} + +const RP4_ADDRESS = { + [CHAIN.ETHEREUM]: '0xe43ca1Dee3F0fc1e2df73A0745674545F11A59F5', + [CHAIN.ARBITRUM]: '0x544bA588efD839d2692Fc31EA991cD39993c135F', + [CHAIN.OPTIMISM]: '0x1f2FCf1d036b375b384012e61D3AA33F8C256bbE', + [CHAIN.BASE]: '0x0389879e0156033202c44bf784ac18fc02edee4f', + [CHAIN.POLYGON]: '0x46B3fDF7b5CDe91Ac049936bF0bDb12c5d22202e', + [CHAIN.AVAX]: '0xCdBCd51a5E8728E0AF4895ce5771b7d17fF71959', + [CHAIN.BSC]: '0x33d91116e0370970444B0281AB117e161fEbFcdD', + [CHAIN.LINEA]: '0x46b3fdf7b5cde91ac049936bf0bdb12c5d22202e', + [CHAIN.ARBITRUM_NOVA]: '0xCdBCd51a5E8728E0AF4895ce5771b7d17fF71959', + [CHAIN.XDAI]: '0x46b3fdf7b5cde91ac049936bf0bdb12c5d22202e', + [CHAIN.FANTOM]: '0x46b3fdf7b5cde91ac049936bf0bdb12c5d22202e', + [CHAIN.BITTORRENT]: '0x93c31c9C729A249b2877F7699e178F4720407733', + [CHAIN.CELO]: '0xCdBCd51a5E8728E0AF4895ce5771b7d17fF71959', + [CHAIN.FILECOIN]: '0x1f2FCf1d036b375b384012e61D3AA33F8C256bbE', + [CHAIN.HAQQ]: '0xc3Ec4e1511c6935ed2F92b9A61881a1B95bB1566', + [CHAIN.KAVA]: '0xB45e53277a7e0F1D35f2a77160e91e25507f1763', + [CHAIN.METIS]: '0xB45e53277a7e0F1D35f2a77160e91e25507f1763', + [CHAIN.THUNDERCORE]: '0x57bfFa72db682f7eb6C132DAE03FF36bBEB0c459', + [CHAIN.SCROLL]: '0x734583f62Bb6ACe3c9bA9bd5A53143CA2Ce8C55A', + [CHAIN.ZETA]: '0x640129e6b5C31B3b12640A5b39FECdCa9F81C640', + [CHAIN.MOONBEAM]: '0xB45e53277a7e0F1D35f2a77160e91e25507f1763', + [CHAIN.MOONRIVER]: '0x46B3fDF7b5CDe91Ac049936bF0bDb12c5d22202e', + [CHAIN.POLYGON_ZKEVM]: '0x57bfFa72db682f7eb6C132DAE03FF36bBEB0c459', + [CHAIN.FUSE]: '0x46B3fDF7b5CDe91Ac049936bF0bDb12c5d22202e', + [CHAIN.HARMONY]: '0x9B3336186a38E1b6c21955d112dbb0343Ee061eE', + [CHAIN.TELOS]: '0x1400feFD6F9b897970f00Df6237Ff2B8b27Dc82C', + [CHAIN.BOBA]: '0xe43ca1Dee3F0fc1e2df73A0745674545F11A59F5', + [CHAIN.BOBA_BNB]: '0xCdBCd51a5E8728E0AF4895ce5771b7d17fF71959', + [CHAIN.CORE]: '0x0389879e0156033202C44BF784ac18fC02edeE4f', + [CHAIN.CRONOS]: '0xCdBCd51a5E8728E0AF4895ce5771b7d17fF71959', + [CHAIN.BLAST]: '0xCdBCd51a5E8728E0AF4895ce5771b7d17fF71959', + [CHAIN.SKALE_EUROPA]: '0xbA61F775730C0a3E3361717195ee86785ee33055', + [CHAIN.ROOTSTOCK]: '0xb46e319390De313B8cc95EA5aa30C7bBFD79Da94', +} + +const RP5_ADDRESS = { + [CHAIN.ETHEREUM]: '0xf2614A233c7C3e7f08b1F887Ba133a13f1eb2c55', + [CHAIN.ARBITRUM]: '0xf2614A233c7C3e7f08b1F887Ba133a13f1eb2c55', + [CHAIN.OPTIMISM]: '0xf2614A233c7C3e7f08b1F887Ba133a13f1eb2c55', + [CHAIN.BASE]: '0xf2614A233c7C3e7f08b1F887Ba133a13f1eb2c55', + [CHAIN.POLYGON]: '0xf2614A233c7C3e7f08b1F887Ba133a13f1eb2c55', + [CHAIN.AVAX]: '0xf2614A233c7C3e7f08b1F887Ba133a13f1eb2c55', + [CHAIN.BSC]: '0xf2614A233c7C3e7f08b1F887Ba133a13f1eb2c55', + [CHAIN.LINEA]: '0xf2614A233c7C3e7f08b1F887Ba133a13f1eb2c55', + [CHAIN.ARBITRUM_NOVA]: '0xf2614A233c7C3e7f08b1F887Ba133a13f1eb2c55', + [CHAIN.XDAI]: '0xf2614A233c7C3e7f08b1F887Ba133a13f1eb2c55', + [CHAIN.FANTOM]: '0xf2614A233c7C3e7f08b1F887Ba133a13f1eb2c55', + [CHAIN.BITTORRENT]: '0xf2614A233c7C3e7f08b1F887Ba133a13f1eb2c55', + [CHAIN.CELO]: '0xf2614A233c7C3e7f08b1F887Ba133a13f1eb2c55', + [CHAIN.FILECOIN]: '0xf2614A233c7C3e7f08b1F887Ba133a13f1eb2c55', + [CHAIN.HAQQ]: '0xf2614A233c7C3e7f08b1F887Ba133a13f1eb2c55', + [CHAIN.KAVA]: '0xf2614A233c7C3e7f08b1F887Ba133a13f1eb2c55', + [CHAIN.METIS]: '0xf2614A233c7C3e7f08b1F887Ba133a13f1eb2c55', + [CHAIN.THUNDERCORE]: '0xf2614A233c7C3e7f08b1F887Ba133a13f1eb2c55', + [CHAIN.SCROLL]: '0xf2614A233c7C3e7f08b1F887Ba133a13f1eb2c55', + [CHAIN.ZETA]: '0xf2614A233c7C3e7f08b1F887Ba133a13f1eb2c55', + [CHAIN.MOONBEAM]: '0xf2614A233c7C3e7f08b1F887Ba133a13f1eb2c55', + [CHAIN.MOONRIVER]: '0xf2614A233c7C3e7f08b1F887Ba133a13f1eb2c55', + [CHAIN.POLYGON_ZKEVM]: '0xf2614A233c7C3e7f08b1F887Ba133a13f1eb2c55', + [CHAIN.FUSE]: '0xf2614A233c7C3e7f08b1F887Ba133a13f1eb2c55', + [CHAIN.HARMONY]: '0xf2614A233c7C3e7f08b1F887Ba133a13f1eb2c55', + [CHAIN.TELOS]: '0xf2614A233c7C3e7f08b1F887Ba133a13f1eb2c55', + [CHAIN.BOBA]: '0xf2614A233c7C3e7f08b1F887Ba133a13f1eb2c55', + [CHAIN.BOBA_BNB]: '0xf2614A233c7C3e7f08b1F887Ba133a13f1eb2c55', + [CHAIN.CORE]: '0xf2614A233c7C3e7f08b1F887Ba133a13f1eb2c55', + [CHAIN.CRONOS]: '0xf2614A233c7C3e7f08b1F887Ba133a13f1eb2c55', + [CHAIN.BLAST]: '0xf2614A233c7C3e7f08b1F887Ba133a13f1eb2c55', + [CHAIN.SKALE_EUROPA]: '0xf2614A233c7C3e7f08b1F887Ba133a13f1eb2c55', + [CHAIN.ROOTSTOCK]: '0xf2614A233c7C3e7f08b1F887Ba133a13f1eb2c55', +} + +const WNATIVE_ADDRESS = { + [CHAIN.ETHEREUM]: '0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2', + [CHAIN.ARBITRUM]: '0x82af49447d8a07e3bd95bd0d56f35241523fbab1', + [CHAIN.OPTIMISM]: '0x4200000000000000000000000000000000000006', + [CHAIN.BASE]: '0x4200000000000000000000000000000000000006', + [CHAIN.POLYGON]: '0x0d500b1d8e8ef31e21c99d1db9a6444d3adf1270', + [CHAIN.AVAX]: '0xb31f66aa3c1e785363f0875a1b74e27b85fd66c7', + [CHAIN.BSC]: '0xbb4cdb9cbd36b01bd1cbaebf2de08d9173bc095c', + [CHAIN.LINEA]: '0xe5d7c2a44ffddf6b295a15c148167daaaf5cf34f', + [CHAIN.ARBITRUM_NOVA]: '0x722e8bdd2ce80a4422e880164f2079488e115365', + [CHAIN.XDAI]: '0xe91d153e0b41518a2ce8dd3d7944fa863463a97d', + [CHAIN.FANTOM]: '0x21be370d5312f44cb42ce377bc9b8a0cef1a4c83', + [CHAIN.BITTORRENT]: '0x23181f21dea5936e24163ffaba4ea3b316b57f3c', + [CHAIN.CELO]: '0x471ece3750da237f93b8e339c536989b8978a438', + [CHAIN.FILECOIN]: '0x60e1773636cf5e4a227d9ac24f20feca034ee25a', + [CHAIN.HAQQ]: '0xec8cc083787c6e5218d86f9ff5f28d4cc377ac54', + [CHAIN.KAVA]: '0xc86c7c0efbd6a49b35e8714c5f59d99de09a225b', + [CHAIN.METIS]: '0x75cb093e4d61d2a2e65d8e0bbb01de8d89b53481', + [CHAIN.THUNDERCORE]: '0x413cefea29f2d07b8f2acfa69d92466b9535f717', + [CHAIN.SCROLL]: '0x5300000000000000000000000000000000000004', + [CHAIN.ZETA]: '0x5f0b1a82749cb4e2278ec87f8bf6b618dc71a8bf', + [CHAIN.MOONBEAM]: '0xacc15dc74880c9944775448304b263d191c6077f', + [CHAIN.MOONRIVER]: '0xf50225a84382c74cbdea10b0c176f71fc3de0c4d', + [CHAIN.POLYGON_ZKEVM]: '0x4f9a0e7fd2bf6067db6994cf12e4495df938e6e9', + [CHAIN.FUSE]: '0x0be9e53fd7edac9f859882afdda116645287c629', + [CHAIN.HARMONY]: '0xcf664087a5bb0237a0bad6742852ec6c8d69a27a', + [CHAIN.TELOS]: '0xd102ce6a4db07d247fcc28f366a623df0938ca9e', + [CHAIN.BOBA]: '0xdeaddeaddeaddeaddeaddeaddeaddeaddead0000', + [CHAIN.BOBA_BNB]: '0xc58aad327d6d58d979882601ba8dda0685b505ea', + [CHAIN.CORE]: '0x40375c92d9faf44d2f9db9bd9ba41a3317a2404f', + [CHAIN.CRONOS]: '0x5c7f8a570d578ed84e63fdfa7b1ee72deae1ae23', + [CHAIN.BLAST]: '0x4300000000000000000000000000000000000004', + [CHAIN.SKALE_EUROPA]: '0x0000000000000000000000000000000000000000', + [CHAIN.ROOTSTOCK]: '0x542fda317318ebf1d3deaf76e0b632741a7e677d', +} + +const useSushiAPIPrice = (chain) => [ + CHAIN.BOBA_BNB, + CHAIN.MOONRIVER +].includes(chain) + +const fetch: FetchV2 = async ({ getLogs, createBalances, chain, }): Promise => { + const logs = await Promise.all([ + getLogs({ target: RP4_ADDRESS[chain], eventAbi: ROUTE_EVENT }), + getLogs({ target: RP5_ADDRESS[chain], eventAbi: ROUTE_EVENT }) + ]).then(([rp4Logs, rp5Logs]) => [...rp4Logs, ...rp5Logs]) + + if (useSushiAPIPrice(chain)) { + const [tokensQuery, pricesQuery] = await Promise.all([ + axios.get(`https://tokens.sushi.com/v0/${CHAIN_ID[chain]}`) + .then(response => response.data), + axios.get(`https://api.sushi.com/price/v1/${CHAIN_ID[chain]}`) + .then(response => Object.entries(response.data).reduce( + (acc, [key, value]) => { + acc[key.toLowerCase()] = value + return acc + }, + {}, + )), + ]) + + const tokens = tokensQuery.reduce((tokens, token) => { + const address = token.address.toLowerCase() + tokens[address] = { + ...token, + price: pricesQuery[address] ?? 0 + } + + return tokens + }, {}) + + let dailyVolume = 0 + + logs.forEach((log) => { + const token = tokens[ + log.tokenIn === '0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE' ? WNATIVE_ADDRESS[chain] : log.tokenIn.toLowerCase() + ] + + if (token) dailyVolume += Number(log.amountIn) * token.price / 10 ** token.decimals + }) + + return { dailyVolume } + } else { + const dailyVolume = createBalances() + + logs.forEach((log) => { + if (log.tokenIn === '0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE') + dailyVolume.addGasToken(log.amountIn) + else + dailyVolume.add(log.tokenIn, log.amountIn) + }) + + return { dailyVolume } + } +} + +const adapters = { + [CHAIN.ARBITRUM]: { + fetch, + start: 1708849166, + }, + [CHAIN.ARBITRUM_NOVA]: { + fetch, + start: 1708859455 + }, + [CHAIN.AVAX]: { + fetch, + start: 1708861373 + }, + [CHAIN.BASE]: { + fetch, + start: 1708860457 + }, + [CHAIN.BLAST]: { + fetch, + start: 1709257139 + }, + [CHAIN.BOBA]: { + fetch, + start: 1711114904 + }, + [CHAIN.BOBA_BNB]: { + fetch, + start: 1708869909 + }, + [CHAIN.BSC]: { + fetch, + start: 1708861767 + }, + [CHAIN.BITTORRENT]: { + fetch, + start: 1708849432 + }, + [CHAIN.CELO]: { + fetch, + start: 1708862981 + }, + [CHAIN.CORE]: { + fetch, + start: 1708868629 + }, + [CHAIN.ETHEREUM]: { + fetch, + start: 1708848791 + }, + [CHAIN.FANTOM]: { + fetch, + start: 1708862854 + }, + // [CHAIN.FILECOIN]: { + // fetch, + // start: 1708863300 + // }, + [CHAIN.FUSE]: { + fetch, + start: 1708842355 + }, + [CHAIN.XDAI]: { + fetch, + start: 1708862650 + }, + // [CHAIN.HAQQ]: { + // fetch, + // start: 1708838485 + // }, + // [CHAIN.HARMONY]: { + // fetch, + // start: 1708867604 + // }, + [CHAIN.KAVA]: { + fetch, + start: 1708864014 + }, + [CHAIN.LINEA]: { + fetch, + start: 1708861967 + }, + [CHAIN.METIS]: { + fetch, + start: 1708864370 + }, + [CHAIN.MOONBEAM]: { + fetch, + start: 1708866396 + }, + [CHAIN.MOONRIVER]: { + fetch, + start: 1708867026 + }, + [CHAIN.OPTIMISM]: { + fetch, + start: 1708860181 + }, + [CHAIN.POLYGON]: { + fetch, + start: 1708860721 + }, + [CHAIN.POLYGON_ZKEVM]: { + fetch, + start: 1708867809 + }, + // [CHAIN.ROOTSTOCK]: { + // fetch, + // start: 1716315751 + // }, + [CHAIN.SCROLL]: { + fetch, + start: 1708865967 + }, + // [CHAIN.SKALE_EUROPA]: { + // fetch, + // start: 1713803839 + // }, + [CHAIN.THUNDERCORE]: { + fetch, + start: 1708889900 + }, + [CHAIN.ZETA]: { + fetch, + start: 1708865999 + }, +} + +export default adapters \ No newline at end of file diff --git a/dexs/sushiswap/trident.ts b/dexs/sushiswap/trident.ts index 854c7f1346..afe056a0b9 100644 --- a/dexs/sushiswap/trident.ts +++ b/dexs/sushiswap/trident.ts @@ -1,18 +1,18 @@ +import * as sdk from "@defillama/sdk"; import request, { gql } from "graphql-request"; -import { - CHAIN, -} from "../../helpers/chains"; +import { CHAIN } from "../../helpers/chains"; import { getStartTimestamp } from "../../helpers/getStartTimestamp"; +import { FetchOptions } from "../../adapters/types"; const endpointsTrident: Record = { - [CHAIN.POLYGON]: 'https://api.thegraph.com/subgraphs/name/sushi-v2/trident-polygon', - [CHAIN.OPTIMISM]: 'https://api.thegraph.com/subgraphs/name/sushi-v2/trident-optimism', + [CHAIN.POLYGON]: sdk.graph.modifyEndpoint('BSdbRfU6PjWSdKjhpfUQ6EgUpzMxgpf5c1ugaVwBJFsQ'), + [CHAIN.OPTIMISM]: sdk.graph.modifyEndpoint('FEgRuH9zeTRMZgpVv5YavoFEcisoK6KHk3zgQRRBqt51'), //[CHAIN.KAVA]: 'https://pvt.graph.kava.io/subgraphs/name/sushi-v2/trident-kava', - [CHAIN.METIS]: 'https://andromeda.thegraph.metis.io/subgraphs/name/sushi-v2/trident-metis', - [CHAIN.BITTORRENT]: 'https://subgraphs.sushi.com/subgraphs/name/sushi-v2/trident-bttc', - [CHAIN.ARBITRUM]: 'https://api.thegraph.com/subgraphs/name/sushi-v2/trident-arbitrum', - [CHAIN.BSC]: 'https://api.thegraph.com/subgraphs/name/sushi-v2/trident-bsc', - [CHAIN.AVAX]: 'https://api.thegraph.com/subgraphs/name/sushi-v2/trident-avalanche', + // [CHAIN.METIS]: 'https://andromeda.thegraph.metis.io/subgraphs/name/sushi-v2/trident-metis', + // [CHAIN.BITTORRENT]: 'https://subgraphs.sushi.com/subgraphs/name/sushi-v2/trident-bttc', + [CHAIN.ARBITRUM]: sdk.graph.modifyEndpoint('4x8H6ZoGfJykyZqAe2Kx2g5afsp17S9pn8GroRkpezhx'), + [CHAIN.BSC]: sdk.graph.modifyEndpoint('9TQaBw1sU3wi2kdevuygKhfhjP3STnwBe1jUnKxmNhmn'), + [CHAIN.AVAX]: sdk.graph.modifyEndpoint('NNTV3MgqSGtHMBGdMVLXzzDbKDKmsY87k3PsQ2knmC1'), } const VOLUME_FIELD = "volumeUSD"; @@ -24,19 +24,13 @@ const startTimeQueryTrident = { }; const tridentQuery = gql` - query trident($timestampLow: Int, $timestampHigh: Int) { - factoryDaySnapshots(where: {date_gt: $timestampLow, date_lt: $timestampHigh}, first: 10) { - date + query trident($number: Int) { + factory( + id: "ALL" + block: { number: $number } + ) { volumeUSD feesUSD - factory { - type - } - } - factories(where: {type: "ALL"}) { - volumeUSD - feesUSD - type } } ` @@ -45,25 +39,28 @@ const trident = Object.keys(endpointsTrident).reduce( (acc, chain) => ({ ...acc, [chain]: { - fetch: async (timestamp: number) => { - const res = await request(endpointsTrident[chain], tridentQuery, { - timestampHigh: timestamp, - timestampLow: timestamp - 3600 * 24, + fetch: async ({ getStartBlock, getEndBlock }: FetchOptions) => { + const [startBlock, endBlock] = await Promise.all([ + getStartBlock(), + getEndBlock() + ]) + const beforeRes = await request(endpointsTrident[chain], tridentQuery, { + number: startBlock, }); - const daily = res.factoryDaySnapshots.find((snapshot: any) => { - return snapshot.factory.type == "ALL" - }) + const afterRes = await await request(endpointsTrident[chain], tridentQuery, { + number: endBlock, + }); + return { - timestamp: timestamp, - totalVolume: res.factories[0]?.volumeUSD, - totalFees: res.factories[0]?.feesUSD, - totalUserFees: res.factories[0]?.feesUSD, - dailyVolume: daily?.volumeUSD || 0, - dailyFees: daily?.feesUSD || 0, - dailyUserFees: daily?.feesUSD || 0 + totalVolume: afterRes.factory.volumeUSD, + totalFees: afterRes.factory.feesUSD, + totalUserFees: afterRes.factory.feesUSD, + dailyVolume: afterRes.factory.volumeUSD - beforeRes.factory.volumeUSD, + dailyFees: afterRes.factory.feesUSD - beforeRes.factory.feesUSD, + dailyUserFees: afterRes.factory.feesUSD - beforeRes.factory.feesUSD } }, - start: getStartTimestamp({ ...startTimeQueryTrident, chain }), + start: 1711982400, }, }), {} diff --git a/dexs/sushiswap/v3.ts b/dexs/sushiswap/v3.ts index a0cce49c6d..6df8c9a090 100644 --- a/dexs/sushiswap/v3.ts +++ b/dexs/sushiswap/v3.ts @@ -1,35 +1,45 @@ +import * as sdk from "@defillama/sdk"; import { Chain } from "@defillama/sdk/build/general"; import { CHAIN } from "../../helpers/chains"; -import { getGraphDimensions } from "../../helpers/getUniSubgraph"; +import { getGraphDimensions2 } from "../../helpers/getUniSubgraph"; +import { FetchOptions } from "../../adapters/types"; const endpointsV3 = { - [CHAIN.ARBITRUM_NOVA]: 'https://subgraphs.sushi.com/subgraphs/name/sushi-v3/v3-arbitrum-nova', - [CHAIN.ARBITRUM]: 'https://api.thegraph.com/subgraphs/name/sushi-v3/v3-arbitrum', - [CHAIN.AVAX]: 'https://api.thegraph.com/subgraphs/name/sushi-v3/v3-avalanche', - [CHAIN.BSC]: 'https://api.thegraph.com/subgraphs/name/sushi-v3/v3-bsc', - [CHAIN.BOBA]: 'https://api.thegraph.com/subgraphs/name/sushi-v3/v3-boba', - [CHAIN.ETHEREUM]: 'https://api.thegraph.com/subgraphs/name/sushi-v3/v3-ethereum', - [CHAIN.FANTOM]: 'https://api.thegraph.com/subgraphs/name/sushi-v3/v3-fantom', - [CHAIN.FUSE]: 'https://api.thegraph.com/subgraphs/name/sushi-v3/v3-fuse', - [CHAIN.XDAI]: 'https://api.thegraph.com/subgraphs/name/sushi-v3/v3-gnosis', - // [CHAIN.MOONRIVER]: 'https://api.thegraph.com/subgraphs/name/sushi-v3/v3-moonriver', - [CHAIN.OPTIMISM]: 'https://api.thegraph.com/subgraphs/name/sushi-v3/v3-optimism', - [CHAIN.POLYGON]: 'https://api.thegraph.com/subgraphs/name/sushi-v3/v3-polygon', - [CHAIN.POLYGON_ZKEVM]: 'https://api.studio.thegraph.com/query/32073/v3-polygon-zkevm/v0.0.2', + [CHAIN.ARBITRUM_NOVA]: "https://api.goldsky.com/api/public/project_clslspm3c0knv01wvgfb2fqyq/subgraphs/sushi-v3/v3-arbitrum-nova/gn", + [CHAIN.ARBITRUM]: sdk.graph.modifyEndpoint('4vRhyrcGqN63T7FXvL9W5X72iQN8H9fDNfLcUQBG91Wi'), + [CHAIN.AVAX]: sdk.graph.modifyEndpoint('HE31GSTGpXsRnuT4sAJoFayGBZX2xBQqWq4db48YuKmD'), + [CHAIN.BSC]: sdk.graph.modifyEndpoint('GtUp5iLfjfYXtX76wF1yyteSSC5WqnYV8br5ixHZgFmW'), + [CHAIN.BOBA]: sdk.graph.modifyEndpoint('Du43Wz3rZ5ajzScgsTnuPv5NvRmQLTDPPkBxYEmFBmWM'), + [CHAIN.ETHEREUM]: sdk.graph.modifyEndpoint('7okunX6MGm2pdFK7WJSwm9o82okpBLEzfGrqHDDMWYvq'), + [CHAIN.FANTOM]: sdk.graph.modifyEndpoint('6z2W9fLTVmhpCecSMTMpRNeSBTRPJLmKsSXrtdkpeJDz'), + [CHAIN.FUSE]: sdk.graph.modifyEndpoint('7E265DKJJiTn8bVF1nqmBr6C2tmo5MVQFNb9sm4cxng5'), + [CHAIN.XDAI]: sdk.graph.modifyEndpoint('GFvGfWBX47RNnvgwL6SjAAf2mrqrPxF91eA53F4eNegW'), + // [CHAIN.MOONRIVER]: sdk.graph.modifyEndpoint('F46W9YVQXGism5iN9NZNhKm2DQCvjhr4u847rL1tRebS'), + [CHAIN.OPTIMISM]: sdk.graph.modifyEndpoint('Hc3vTLxWmtyrn59t2Yv3MiXJVxjfNyZi41iKE3rXXHMf'), + [CHAIN.POLYGON]: sdk.graph.modifyEndpoint('G1Q6dviDfMm6hVLvCqbfeB19kLmvs7qrnBvXeFndjhaU'), + // [CHAIN.POLYGON_ZKEVM]: sdk.graph.modifyEndpoint('E2x2gmtYdm2HX3QXorUBY4KegfGu79Za6TEQYjVrx15c'), [CHAIN.THUNDERCORE]: 'https://graph-node.thundercore.com/subgraphs/name/sushi-v3/v3-thundercore', - [CHAIN.BASE]: "https://api.studio.thegraph.com/query/32073/v3-base/v0.0.1" + [CHAIN.BASE]: "https://api.studio.thegraph.com/query/32073/v3-base/v0.0.1", + [CHAIN.CORE]: "https://thegraph.coredao.org/subgraphs/name/sushi-v3/v3-core", + [CHAIN.BLAST]: "https://api.goldsky.com/api/public/project_clslspm3c0knv01wvgfb2fqyq/subgraphs/sushiswap/v3-blast/gn", + // [CHAIN.ROOTSTOCK]: "https://api.goldsky.com/api/public/project_clslspm3c0knv01wvgfb2fqyq/subgraphs/sushiswap/v3-rootstock/gn", + [CHAIN.BITTORRENT]: "https://api.goldsky.com/api/public/project_clslspm3c0knv01wvgfb2fqyq/subgraphs/sushi-v3/v3-bttc/gn", + [CHAIN.FILECOIN]: "https://sushi.laconic.com/subgraphs/name/sushiswap/v3-filecoin", + [CHAIN.METIS]: "https://metisapi.0xgraph.xyz/api/public/fc1ae952-7a36-44ac-9e9b-f46d70cedf7d/subgraphs/sushi-v3/v3-metis/v0.0.1/gn", + [CHAIN.KAVA]: "https://api.goldsky.com/api/public/project_clslspm3c0knv01wvgfb2fqyq/subgraphs/sushi-v3/v3-kava/gn", + // [CHAIN.ZETA]: "https://api.goldsky.com/api/public/project_cls39ugcfyhbq01xl9tsf6g38/subgraphs/v3-zetachain/1.0.0/gn", + // [CHAIN.HAQQ]: "https://haqq.graph.p2p.org/subgraphs/name/sushi/v3-haqq-2", + [CHAIN.LINEA]: sdk.graph.modifyEndpoint('E2vqqvSzDdUiPP1r7PFnPKZQ34pAhNZjc6rEcdj3uE5t'), + [CHAIN.SCROLL]: sdk.graph.modifyEndpoint('5gyhoHx768oHn3GxsHsEc7oKFMPFg9AH8ud1dY8EirRc'), + // [CHAIN.SKALE_EUROPA]: "https://elated-tan-skat-graph.skalenodes.com:8000/subgraphs/name/sushi/v3-skale-europa", } -const v3Graphs = getGraphDimensions({ +const v3Graphs = getGraphDimensions2({ graphUrls: endpointsV3, totalVolume: { factory: "factories", field: "totalVolumeUSD", }, - dailyVolume: { - factory: "uniswapDayData", - field: "volumeUSD", - }, feesPercent: { type: "fees", ProtocolRevenue: 0, @@ -56,13 +66,46 @@ const startTimeV3: {[key: string]: number} = { [CHAIN.POLYGON_ZKEVM]: 1680739200, [CHAIN.THUNDERCORE]: 1684281600, [CHAIN.BASE]: 1691020800, + [CHAIN.CORE]: 1689897600, + [CHAIN.BLAST]: 1709337600, + [CHAIN.ROOTSTOCK]: 1709337600, + [CHAIN.BITTORRENT]: 1711982400, + [CHAIN.FILECOIN]: 1711982400, + [CHAIN.METIS]: 1711982400, + [CHAIN.KAVA]: 1711982400, + [CHAIN.ZETA]: 1711982400, + [CHAIN.HAQQ]: 1711982400, + [CHAIN.LINEA]: 1711982400, + [CHAIN.SCROLL]: 1711982400, + [CHAIN.SKALE_EUROPA]: 1711982400, } const v3 = Object.keys(endpointsV3).reduce( (acc, chain) => ({ ...acc, [chain]: { - fetch: v3Graphs(chain as Chain), + fetch: async (options: FetchOptions) => { + try { + const res = (await v3Graphs(chain as Chain)(options)) + return { + totalVolume: res?.totalVolume || 0, + dailyVolume: res?.dailyVolume || 0, + totalFees: res?.totalFees || 0, + totalUserFees: res?.totalUserFees || 0, + dailyFees: res?.dailyFees, + dailyUserFees: res?.dailyUserFees || 0 + } + } catch { + return { + totalVolume: 0, + dailyVolume: 0, + totalFees: 0, + totalUserFees: 0, + dailyFees: 0, + dailyUserFees: 0 + } + } + }, start: startTimeV3[chain], meta: { methodology: { diff --git a/dexs/swaap/index.ts b/dexs/swaap/index.ts index 226e586837..5bed0e981b 100644 --- a/dexs/swaap/index.ts +++ b/dexs/swaap/index.ts @@ -1,10 +1,8 @@ -import {BaseAdapter, BreakdownAdapter} from "../../adapters/types"; -import {CHAIN} from "../../helpers/chains"; -import {gql, GraphQLClient} from "graphql-request"; -import {Chain} from "@defillama/sdk/build/general"; -import {getTimestampAtStartOfDay,} from "../../utils/date"; -import {getChainVolume} from "../../helpers/getUniSubgraphVolume"; -import customBackfill from "../../helpers/customBackfill"; +import * as sdk from "@defillama/sdk"; +import { BreakdownAdapter, FetchOptions, FetchResult } from "../../adapters/types"; +import { CHAIN } from "../../helpers/chains"; +import { gql, GraphQLClient } from "graphql-request"; +import { getChainVolume } from "../../helpers/getUniSubgraphVolume"; interface ChainConfig{ api: string, @@ -15,118 +13,120 @@ interface ChainConfig{ const config:Record = { [CHAIN.ETHEREUM]: { - api: "https://api.thegraph.com/subgraphs/name/swaap-labs/swaapv2-ethereum", + api: "https://api.goldsky.com/api/public/project_clws2t7g7ae9c01xsbnu80a51/subgraphs/swaapv2-ethereum/1.0.0/gn", start: 1688169600, id: '2', firstDayVolume: 0 }, [CHAIN.POLYGON]: { - api: "https://api.thegraph.com/subgraphs/name/swaap-labs/swaapv2-polygon", + api: "https://api.goldsky.com/api/public/project_clws2t7g7ae9c01xsbnu80a51/subgraphs/swaapv2-polygon/1.0.0/gn", start: 1688083200, id: '2', firstDayVolume: 240.41984714755376 }, [CHAIN.ARBITRUM]: { - api: "https://api.thegraph.com/subgraphs/name/swaap-labs/swaapv2-arbitrum", + api: "https://api.goldsky.com/api/public/project_clws2t7g7ae9c01xsbnu80a51/subgraphs/swaapv2-arbitrum/1.0.0/gn", start: 1696464000, id: '2', firstDayVolume: 0 }, + [CHAIN.OPTIMISM]: { + api: "https://api.goldsky.com/api/public/project_clws2t7g7ae9c01xsbnu80a51/subgraphs/swaapv2-optimism/1.0.0/gn", + start: 1716986361, + id: '2', + firstDayVolume: 0 + }, + [CHAIN.BSC]: { + api: "https://api.goldsky.com/api/public/project_clws2t7g7ae9c01xsbnu80a51/subgraphs/swaapv2-bsc/1.0.0/gn", + start: 1716994360, + id: '2', + firstDayVolume: 0 + }, + [CHAIN.BASE]: { + api: "https://api.goldsky.com/api/public/project_clws2t7g7ae9c01xsbnu80a51/subgraphs/swaapv2-base/1.0.0/gn", + start: 1715692069, + id: '2', + firstDayVolume: 0 + }, + [CHAIN.MODE]: { + api: "https://api.goldsky.com/api/public/project_clws2t7g7ae9c01xsbnu80a51/subgraphs/swaapv2-mode/1.0.1/gn", + start: 1714652681, + id: '2', + firstDayVolume: 0 + }, + [CHAIN.SCROLL]: { + api: "https://api.goldsky.com/api/public/project_clws2t7g7ae9c01xsbnu80a51/subgraphs/swaapv2-scroll/prod/gn", + start: 1719508309, + id: '2', + firstDayVolume: 0 + }, + [CHAIN.LINEA]: { + api: "https://api.goldsky.com/api/public/project_clws2t7g7ae9c01xsbnu80a51/subgraphs/swaapv2-linea/prod/gn", + start: 1719507890, + id: '2', + firstDayVolume: 0 + }, + [CHAIN.MANTLE]: { + api: "https://api.goldsky.com/api/public/project_clws2t7g7ae9c01xsbnu80a51/subgraphs/swaapv2-linea/prod/gn", + start: 1719508654, + id: '2', + firstDayVolume: 0 + }, + } interface Data { - swaapSnapshot: { + start: { id: string, totalSwapVolume: string - } | null + }, + end: { + id: string, + totalSwapVolume: string + } } -async function getTotalVolume(chain: Chain, timestamp: number): Promise { - let id = config[chain].id + '-' + timestamp - const url = config[chain].api - const graphQLClient = new GraphQLClient(url); - const todayVolumeQuery = gql` +const getVolume = async (options: FetchOptions) => { + const starttimestamp = options.startOfDay; + const endtimestamp = starttimestamp + 86400 + const startId = config[options.chain].id + '-' + starttimestamp + const endId = config[options.chain].id + '-' + endtimestamp + + const query = gql` { - swaapSnapshot(id:"${id}"){ + start:swaapSnapshot(id: "${startId}") { id totalSwapVolume - } - } - `; - - const result = await graphQLClient.request(todayVolumeQuery) as Data - return result.swaapSnapshot ? Number(result.swaapSnapshot.totalSwapVolume) : null -} - -/** - * While the getTotalVolume is null, fetch getTotalVolume of the previous day - * @param chain - * @param timestamp - */ -async function getClosestTotalVolume(chain: Chain, timestamp: number): Promise { - - const minimalTS = config[chain].start - if (timestamp <= minimalTS) { - return config[chain].firstDayVolume - } - - - let totalVolume = await getTotalVolume(chain, timestamp) - if (totalVolume === null) { - const yesterdayTS = timestamp - 24 * 3600 - totalVolume = await getClosestTotalVolume(chain, yesterdayTS) + } + end:swaapSnapshot(id: "${endId}") { + id + totalSwapVolume + } } - return totalVolume -} - - -async function getVolume(chain: Chain, timestamp: number,) { - - const timestampBegin =getTimestampAtStartOfDay(timestamp) - const timestampYesterday = timestampBegin - 24 * 3600 - - const totalVolume = await getClosestTotalVolume(chain, timestampBegin) - const yesterdayVolume = await getClosestTotalVolume(chain, timestampYesterday) - - const dailyVolume = totalVolume - yesterdayVolume - + ` + const url = config[options.chain].api + const graphQLClient = new GraphQLClient(url, { timeout: 3000 }); + const result: Data = await graphQLClient.request(query) + const dailyVolume = Number(result.end?.totalSwapVolume || 0) - Number(result.start?.totalSwapVolume || 0) + const totalVolume = Number(result.end?.totalSwapVolume || 0) return { + // If the daily volume is negative, set it to 0 + dailyVolume: dailyVolume < 0 ? 0 : dailyVolume, totalVolume, - dailyVolume } } -const v2graphs = (chain: Chain) => { - return async (timestamp: number) => { - - const {totalVolume, dailyVolume} = await getVolume( chain, timestamp) - return { - timestamp, - totalVolume:totalVolume.toString(), - dailyVolume:dailyVolume.toString() - - }; +const v2graphs = async (_t: any, _tt: any ,options: FetchOptions): Promise => { + const { dailyVolume, totalVolume } = await getVolume(options) + return { + timestamp: options.startOfDay, + dailyVolume, + totalVolume } } -const adapterV2: BaseAdapter = Object.keys(config).reduce((acc, chain) => { - return { - ...acc, - [chain]: { - fetch: v2graphs(chain), - start: config[chain].start, - runAtCurrTime: false, - meta: { - methodology: 'Comparing total volume of the current day with the total volume of the previous day, using TheGraph.' - } - }, - } - }, {} as BaseAdapter) -; - -// Directly from Balancer adapter const graphParams = { totalVolume: { factory: "swaapProtocols", @@ -137,25 +137,75 @@ const graphParams = { const v1graphs = getChainVolume({ graphUrls: { - [CHAIN.POLYGON]: "https://api.thegraph.com/subgraphs/name/swaap-labs/swaapv1" + [CHAIN.POLYGON]: sdk.graph.modifyEndpoint('A1ibaGVUkqdLeBG7VeeSB8jm9QNmS8phSz8iooXR8puv') }, - ...graphParams + ...graphParams, }); const adapter: BreakdownAdapter = { + version: 1, breakdown: { v1: { [CHAIN.POLYGON]: { - fetch: v1graphs(CHAIN.POLYGON), - start: 1655195452, - customBackfill: customBackfill(CHAIN.POLYGON, v1graphs) + fetch: async (_t: any, _tt: any ,options: FetchOptions) => { + const { dailyVolume, totalVolume } = await v1graphs(options.chain)(_t, _tt, options) + return { + timestamp: options.startOfDay, + dailyVolume, + totalVolume + } + }, + start: 1655195452 }, }, - v2: adapterV2 + v2: { + [CHAIN.ETHEREUM]: { + fetch: v2graphs, + start: 1688169600, + + }, + [CHAIN.POLYGON]: { + fetch: v2graphs, + start: 1688083200, + + }, + [CHAIN.ARBITRUM]: { + fetch: v2graphs, + start: 1696464000, + }, + [CHAIN.OPTIMISM]: { + fetch: v2graphs, + start: 1716986361, + }, + [CHAIN.BSC]: { + fetch: v2graphs, + start: 1716994360, + }, + [CHAIN.BASE]: { + fetch: v2graphs, + start: 1715692069, + }, + [CHAIN.MODE]: { + fetch: v2graphs, + start: 1714652681, + }, + [CHAIN.SCROLL]: { + fetch: v2graphs, + start: 1719508309, + }, + [CHAIN.LINEA]: { + fetch: v2graphs, + start: 1719507890, + }, + [CHAIN.MANTLE]: { + fetch: v2graphs, + start: 1719508654, + }, + + } } } export default adapter; - diff --git a/dexs/swapbased/index.ts b/dexs/swapbased/index.ts index 3e18398fb6..844087aba3 100644 --- a/dexs/swapbased/index.ts +++ b/dexs/swapbased/index.ts @@ -1,7 +1,17 @@ import customBackfill from "../../helpers/customBackfill"; -import { DEFAULT_TOTAL_VOLUME_FACTORY, DEFAULT_TOTAL_VOLUME_FIELD, DEFAULT_DAILY_VOLUME_FACTORY, DEFAULT_DAILY_VOLUME_FIELD, getChainVolume } from "../../helpers/getUniSubgraphVolume"; +import { + DEFAULT_TOTAL_VOLUME_FACTORY, + DEFAULT_TOTAL_VOLUME_FIELD, + DEFAULT_DAILY_VOLUME_FACTORY, + DEFAULT_DAILY_VOLUME_FIELD, + getChainVolume, +} from "../../helpers/getUniSubgraphVolume"; import { CHAIN } from "../../helpers/chains"; -import type { Fetch, ChainEndpoints, BreakdownAdapter } from "../../adapters/types"; +import type { + Fetch, + ChainEndpoints, + BreakdownAdapter, +} from "../../adapters/types"; import { getGraphDimensions } from "../../helpers/getUniSubgraph"; import request, { gql } from "graphql-request"; import { getUniqStartOfTodayTimestamp } from "../../helpers/getUniSubgraphVolume"; @@ -24,16 +34,17 @@ const graphs = getGraphDimensions({ }, feesPercent: { type: "volume", - UserFees: 0.30, + UserFees: 0.3, SupplySideRevenue: 0.25, ProtocolRevenue: 0.05, Revenue: 0.25, - Fees: 0.30, - } + Fees: 0.3, + }, }); const endpointsV3 = { - [CHAIN.BASE]: "https://api.thegraph.com/subgraphs/name/chimpydev/swapbased-algebra-core", + [CHAIN.BASE]: + "https://api.studio.thegraph.com/query/67101/swapbased-pcsv3-core/version/latest", }; const graphsV3 = getChainVolume({ graphUrls: endpointsV3, @@ -42,9 +53,9 @@ const graphsV3 = getChainVolume({ field: "totalVolumeUSD", }, dailyVolume: { - factory: "algebraDayData", + factory: "pancakeDayData", field: "volumeUSD", - dateField: "date" + dateField: "date", }, }); @@ -59,85 +70,128 @@ const methodology = { /* PERPS */ const endpointsPerps: { [key: string]: string } = { - [CHAIN.BASE]: "https://api.thegraph.com/subgraphs/name/chimpydev/swapbased-perps-core", -} + [CHAIN.BASE]: + "https://api.thegraph.com/subgraphs/name/chimpydev/swapbased-perps-core", +}; const historicalDataSwap = gql` query get_volume($period: String!, $id: String!) { - volumeStats(where: {period: $period, id: $id}) { - liquidation - margin - } + volumeStats(where: { period: $period, id: $id }) { + liquidation + margin + } } -` +`; const historicalOI = gql` query get_trade_stats($period: String!, $id: String!) { - tradingStats(where: {period: $period, id: $id}) { + tradingStats(where: { period: $period, id: $id }) { id longOpenInterest shortOpenInterest } } -` - +`; interface IGraphResponse { volumeStats: Array<{ - burn: string, - liquidation: string, - margin: string, - mint: string, - swap: string, - }> + burn: string; + liquidation: string; + margin: string; + mint: string; + swap: string; + }>; } interface IGraphResponseOI { tradingStats: Array<{ - id: string, - longOpenInterest: string, - shortOpenInterest: string, - }> + id: string; + longOpenInterest: string; + shortOpenInterest: string; + }>; } -const getFetch = (query: string)=> (chain: string): any => async (timestamp: number) => { - const dayTimestamp = getUniqStartOfTodayTimestamp(new Date((timestamp * 1000))) - const dailyData: IGraphResponse = await request(endpointsPerps[chain], query, { - id: String(dayTimestamp) + ':daily', - period: 'daily', - }) - const totalData: IGraphResponse = await request(endpointsPerps[chain], query, { - id: 'total', - period: 'total', - }) - - const tradingStats: IGraphResponseOI = await request(endpointsPerps[chain], historicalOI, { - id: String(dayTimestamp) + ':daily', - period: 'daily', - }) - - const dailyOpenInterest = Number(tradingStats.tradingStats[0]?.longOpenInterest || 0) + Number(tradingStats.tradingStats[0]?.shortOpenInterest || 0); - const dailyLongOpenInterest = Number(tradingStats.tradingStats[0]?.longOpenInterest || 0); - const dailyShortOpenInterest = Number(tradingStats.tradingStats[0]?.shortOpenInterest || 0); - - return { - timestamp: dayTimestamp, - dailyLongOpenInterest: dailyLongOpenInterest ? String(dailyLongOpenInterest * 10 ** -30) : undefined, - dailyShortOpenInterest: dailyShortOpenInterest ? String(dailyShortOpenInterest * 10 ** -30) : undefined, - dailyOpenInterest: dailyOpenInterest ? String(dailyOpenInterest * 10 ** -30) : undefined, - dailyVolume: - dailyData.volumeStats.length == 1 - ? String(Number(Object.values(dailyData.volumeStats[0]).reduce((sum, element) => String(Number(sum) + Number(element)))) * 10 ** -30) +const getFetch = + (query: string) => + (chain: string): any => + async (timestamp: number) => { + const dayTimestamp = getUniqStartOfTodayTimestamp( + new Date(timestamp * 1000), + ); + const dailyData: IGraphResponse = await request( + endpointsPerps[chain], + query, + { + id: String(dayTimestamp) + ":daily", + period: "daily", + }, + ); + const totalData: IGraphResponse = await request( + endpointsPerps[chain], + query, + { + id: "total", + period: "total", + }, + ); + + const tradingStats: IGraphResponseOI = await request( + endpointsPerps[chain], + historicalOI, + { + id: String(dayTimestamp) + ":daily", + period: "daily", + }, + ); + + const dailyOpenInterest = + Number(tradingStats.tradingStats[0]?.longOpenInterest || 0) + + Number(tradingStats.tradingStats[0]?.shortOpenInterest || 0); + const dailyLongOpenInterest = Number( + tradingStats.tradingStats[0]?.longOpenInterest || 0, + ); + const dailyShortOpenInterest = Number( + tradingStats.tradingStats[0]?.shortOpenInterest || 0, + ); + + return { + timestamp: dayTimestamp, + dailyLongOpenInterest: dailyLongOpenInterest + ? String(dailyLongOpenInterest * 10 ** -30) : undefined, - totalVolume: - totalData.volumeStats.length == 1 - ? String(Number(Object.values(totalData.volumeStats[0]).reduce((sum, element) => String(Number(sum) + Number(element)))) * 10 ** -30) + dailyShortOpenInterest: dailyShortOpenInterest + ? String(dailyShortOpenInterest * 10 ** -30) : undefined, - - } -} + dailyOpenInterest: dailyOpenInterest + ? String(dailyOpenInterest * 10 ** -30) + : undefined, + dailyVolume: + dailyData.volumeStats.length == 1 + ? String( + Number( + Object.values(dailyData.volumeStats[0]).reduce((sum, element) => + String(Number(sum) + Number(element)), + ), + ) * + 10 ** -30, + ) + : undefined, + totalVolume: + totalData.volumeStats.length == 1 + ? String( + Number( + Object.values(totalData.volumeStats[0]).reduce((sum, element) => + String(Number(sum) + Number(element)), + ), + ) * + 10 ** -30, + ) + : undefined, + }; + }; const adapter: BreakdownAdapter = { + version: 1, breakdown: { v2: { [CHAIN.BASE]: { @@ -145,20 +199,20 @@ const adapter: BreakdownAdapter = { start: 1690495200, customBackfill: customBackfill(CHAIN.BASE, graphs), meta: { methodology }, - } + }, }, v3: { [CHAIN.BASE]: { fetch: graphsV3(CHAIN.BASE), start: 1690443269, - } + }, }, perps: { [CHAIN.BASE]: { fetch: getFetch(historicalDataSwap)(CHAIN.BASE), start: 1688913853, - } - } + }, + }, }, }; diff --git a/dexs/swapr/index.ts b/dexs/swapr/index.ts index 0b8d93e2dd..43279f38ba 100644 --- a/dexs/swapr/index.ts +++ b/dexs/swapr/index.ts @@ -1,9 +1,10 @@ +import * as sdk from "@defillama/sdk"; import { CHAIN } from "../../helpers/chains"; import { univ2Adapter } from "../../helpers/getUniSubgraphVolume"; const endpoints = { - [CHAIN.ETHEREUM]: "https://api.thegraph.com/subgraphs/name/dxgraphs/swapr-mainnet-v2", - [CHAIN.ARBITRUM]: "https://api.thegraph.com/subgraphs/name/dxgraphs/swapr-arbitrum-one-v3", + [CHAIN.ETHEREUM]: sdk.graph.modifyEndpoint('CfBvQzwWyg41ceiR3XM64KzJiAKVPML4iztwEaHYdCFw'), + [CHAIN.ARBITRUM]: sdk.graph.modifyEndpoint('8CtcD8EzHq6YyQrnb4XFz2pnwXVx3nHruj4pcDjHRKpt'), [CHAIN.XDAI]: "https://api.thegraph.com/subgraphs/name/dxgraphs/swapr-xdai-v2" }; diff --git a/dexs/swapsicle/index.ts b/dexs/swapsicle/index.ts index 4ad599ec86..668f652f73 100644 --- a/dexs/swapsicle/index.ts +++ b/dexs/swapsicle/index.ts @@ -1,8 +1,9 @@ +import * as sdk from "@defillama/sdk"; import { CHAIN } from "../../helpers/chains"; import { univ2Adapter } from "../../helpers/getUniSubgraphVolume"; export default univ2Adapter({ - [CHAIN.AVAX]: "https://api.thegraph.com/subgraphs/name/billy93/swapsicleexc2", + [CHAIN.AVAX]: sdk.graph.modifyEndpoint('3CpYKjaYzYk34muKEjBkDmWJLUMdAL6FEeKtLvYUbAuH'), }, { factoriesName: "factories", totalVolume: "volumeUSD", diff --git a/dexs/swop/index.ts b/dexs/swop/index.ts new file mode 100644 index 0000000000..f38411ef9c --- /dev/null +++ b/dexs/swop/index.ts @@ -0,0 +1,61 @@ +import fetchURL from "../../utils/fetchURL" +import type { SimpleAdapter } from "../../adapters/types"; +import { CHAIN } from "../../helpers/chains"; + +const URL = "https://backend.swop.fi/pools" + +const methodology = { + Fees: "A minor fee is collected on each swap, functioning as trading fees.\n" + + "The fees are set at 0.6% for CPMM pools (with volatile coins) and 0.15% for stablecoin pools. A fee discount of 5-35% is granted to governance token stakers.", + Revenue: "Revenue is 35% of all collected fees", + ProtocolRevenue: "10% of all collected fees go to the Team Fund. 21% of fees are spent for the governance token buyout and burning. ", + HoldersRevenue: "Revenue for stakers is 14% of all collected fees", + SupplySideRevenue: "LP revenue is 55% of all collected fees" +} +interface IInfo { + day: IVolume; + week: IVolume; +}; + +interface IVolume { + liquidityFee: string; + amountTransactions: string; + governanceFee: string; + volume: string; +}; + +interface IAPIResponse { + overall: IInfo; +}; + +const fetch = async (timestamp: number) => { + const response: IAPIResponse = (await fetchURL(URL)); + const fees = (parseFloat(response.overall.day.liquidityFee) + parseFloat(response.overall.day.governanceFee)) // 90% of fees + const teamRevenue = fees / 90 * 10 // 10% of fees going to team treasure + return { + dailyVolume: `${response.overall.day.volume}`, + dailyFees: `${fees + teamRevenue}`, + dailyUserFees: `${fees + teamRevenue}`, + dailyRevenue: `${response.overall.day.governanceFee}`, + dailyProtocolRevenue: `${teamRevenue}`, + dailyHoldersRevenue: `${response.overall.day.governanceFee}`, + dailySupplySideRevenue: `${response.overall.day.liquidityFee}`, + timestamp: timestamp, + }; +}; + +const adapter: SimpleAdapter = { + adapter: { + [CHAIN.WAVES]: { + fetch, + runAtCurrTime: true, + customBackfill: undefined, + start: 0, + meta: { + methodology + } + }, + } +}; + +export default adapter; diff --git a/dexs/swych/index.ts b/dexs/swych/index.ts new file mode 100644 index 0000000000..9f868f3319 --- /dev/null +++ b/dexs/swych/index.ts @@ -0,0 +1,136 @@ +import * as sdk from "@defillama/sdk"; +import axios from "axios"; +import {CHAIN} from "../../helpers/chains"; +import {getTimestampAtStartOfDayUTC} from "../../utils/date"; + +const STATUS = { + FILLED: "FILLED", +}; + +const SUBGRAPHS = { + pdex: sdk.graph.modifyEndpoint('6tn8tNYxKCEM5bTceMfA5jeGm3gtCrUGDwbKN7QGGat4'), +}; + +const toBigInt = (value: string | number) => { + return BigInt(value); +}; + +const convertToUsd = (value: bigint, decimals = 30) => { + if (!value) { + return 0; + } + + const wei = toBigInt(10) ** toBigInt(decimals); + return Number(value / wei); +}; + +const calculate24hTimestamps = (timestamp: number) => { + const startOfCurrentDay = getTimestampAtStartOfDayUTC(timestamp); + const endOfCurrentDay = startOfCurrentDay + 24 * 60 * 60; + return { + startOfCurrentDay, + endOfCurrentDay, + }; +}; + +const generateOrdersQuery = (timeStart: number = 0, timeEnd: number, skip: number = 0, first: number = 1000) => { + return { + query: ` + { + orders( + where: { + submissionTimestamp_gt: "${timeStart}", + submissionTimestamp_lt: "${timeEnd}", + status: FILLED + }, + first: ${first}, + skip: ${skip}, + orderBy: submissionTimestamp, + orderDirection: asc + ) { + id + side + type + status + submissionTimestamp + collateralValue + sizeChange + updateType + owner + } + }` + }; +}; + +const queryOrders = async (timestamp: number) => { + const timeStart = 0; + const timeEnd = timestamp; + const orders: Array = []; + const pageSize = 1000; + let hasMoreData = true; + while (hasMoreData) { + const query = generateOrdersQuery(timeStart, timeEnd, orders.length, pageSize); + const response = await axios.post(SUBGRAPHS.pdex, query); + const fetchedOrders = response?.data?.data?.orders; + if (!fetchedOrders) { + hasMoreData = false; + continue; + } + orders.push(...fetchedOrders); + hasMoreData = fetchedOrders.length === pageSize; + } + + return orders; +}; + +const getOrders = async (timestamp: number) => { + return queryOrders(timestamp); +}; + +const calculateTradingVolumeFromOrders = (orders: Array, timestamp: number) => { + const filteredOrders = orders.filter( + order => order.status === STATUS.FILLED + ); + const {startOfCurrentDay, endOfCurrentDay} = calculate24hTimestamps(timestamp); + const filteredOrders24h = filteredOrders.filter( + order => order.submissionTimestamp >= startOfCurrentDay + && order.submissionTimestamp <= endOfCurrentDay + ); + const tradingVolume = filteredOrders.reduce( + (acc, order) => acc + toBigInt(order.sizeChange), + toBigInt(0) + ); + const tradingVolume24h = filteredOrders24h.reduce( + (acc, order) => acc + toBigInt(order.sizeChange), + toBigInt(0) + ); + return { + tradingVolume, + tradingVolume24h, + }; +}; + +const fetchVolumeStats = async (timestamp: number) => { + const {startOfCurrentDay, endOfCurrentDay} = calculate24hTimestamps(timestamp); + const orders = await getOrders(endOfCurrentDay); + const {tradingVolume, tradingVolume24h} = calculateTradingVolumeFromOrders(orders, startOfCurrentDay); + const [ + convertedTradingVolume, + convertedTradingVolume24h, + ] = [tradingVolume, tradingVolume24h].map(value => convertToUsd(value)); + return { + timestamp, + dailyVolume: convertedTradingVolume24h.toString(), + totalVolume: convertedTradingVolume.toString(), + }; +}; + +export default { + adapter: { + [CHAIN.BSC]: { + fetch: fetchVolumeStats, + start: 1701720000, + runAtCurrTime: false, + }, + }, +}; diff --git a/dexs/symmetric/index.ts b/dexs/symmetric/index.ts index df73ac8fed..2f5ffb350c 100644 --- a/dexs/symmetric/index.ts +++ b/dexs/symmetric/index.ts @@ -1,3 +1,4 @@ +import * as sdk from "@defillama/sdk"; import { Chain } from "@defillama/sdk/build/general"; import request, { gql } from "graphql-request"; import { BaseAdapter, BreakdownAdapter, ChainEndpoints, FetchResultVolume } from "../../adapters/types"; @@ -8,8 +9,8 @@ import { getChainVolume, getUniqStartOfTodayTimestamp } from "../../helpers/getU import { getTimestampAtStartOfDayUTC } from "../../utils/date"; const endpoints: ChainEndpoints = { - [CHAIN.XDAI]:'https://api.thegraph.com/subgraphs/name/centfinance/symmetric-v2-gnosis', - [CHAIN.CELO]: 'https://api.thegraph.com/subgraphs/name/centfinance/symmetric-v2-celo', + [CHAIN.XDAI]:sdk.graph.modifyEndpoint('9kdgh1tW36E8MKthUmZ2FJbe2KCuvkibz984SxbQSdJw'), + [CHAIN.CELO]: sdk.graph.modifyEndpoint('2iS1nCtSKbJT7MZ2xH9hMej3CjJDRRGuv25cAt6kbEwj'), [CHAIN.TELOS]:'https://api.goldsky.com/api/public/project_clnbo3e3c16lj33xva5r2aqk7/subgraphs/symmetric-telos/prod/gn', }; diff --git a/dexs/syncswap/index.ts b/dexs/syncswap/index.ts index e3333d2b5c..8a43e7c051 100644 --- a/dexs/syncswap/index.ts +++ b/dexs/syncswap/index.ts @@ -1,18 +1,16 @@ -import { univ2Adapter } from "../../helpers/getUniSubgraphVolume"; +import { univ2Adapter2 } from "../../helpers/getUniSubgraphVolume"; import { CHAIN } from "../../helpers/chains"; const endpoints = { - [CHAIN.ERA]: "https://api.studio.thegraph.com/query/30365/zksync-blocks/v0.0.9", + [CHAIN.ERA]: + "https://api.studio.thegraph.com/query/30365/syncswap-graph/1.4.0", }; -const adapter = univ2Adapter(endpoints, { +const adapter = univ2Adapter2(endpoints, { factoriesName: "syncSwapFactories", - dayData: "dayData", - dailyVolume: "dailyVolumeUSD", totalVolume: "totalVolumeUSD", - dailyVolumeTimestampField: "date", }); -adapter.adapter.era.start = 1679529600 +adapter.adapter.era.start = 1679529600; -export default adapter +export default adapter; diff --git a/dexs/synfutures/index.ts b/dexs/synfutures-v1/index.ts similarity index 81% rename from dexs/synfutures/index.ts rename to dexs/synfutures-v1/index.ts index 85a3bb12d7..3ecc11ed55 100644 --- a/dexs/synfutures/index.ts +++ b/dexs/synfutures-v1/index.ts @@ -1,3 +1,4 @@ +import * as sdk from "@defillama/sdk"; // SynFutures v1 volume import { ChainBlocks, FetchOptions, SimpleAdapter } from "../../adapters/types"; import { CHAIN } from "../../helpers/chains"; @@ -6,16 +7,16 @@ const { request, } = require("graphql-request"); const info: {[key: string]: any} = { polygon: { - subgraph: 'https://api.thegraph.com/subgraphs/name/synfutures/polygon-v1', + subgraph: sdk.graph.modifyEndpoint('AoQ1npLLN7fTJc96XjnL8MgwHAvzxFDuE27kWfdrVATD'), }, ethereum: { - subgraph: 'https://api.thegraph.com/subgraphs/name/synfutures/ethereum-v1', + subgraph: sdk.graph.modifyEndpoint('HLqiPUB5pYH8VztXAcvMW6VTq6avHkW77mYnKe8ov44r'), }, bsc: { - subgraph: 'https://api.thegraph.com/subgraphs/name/synfutures/bsc-v1', + subgraph: sdk.graph.modifyEndpoint('9AuL6Mga3pzjYDoLEJHncC3rQMCHibaW8syCwJv1QMNW'), }, arbitrum: { - subgraph: 'https://api.thegraph.com/subgraphs/name/synfutures/arbitrum-one-v1', + subgraph: sdk.graph.modifyEndpoint('HktZa8SikfXFpjjGZML578RTrsieQdVENJviucpokLwH'), }, } diff --git a/dexs/synfutures-v3/index.ts b/dexs/synfutures-v3/index.ts index b723b1d4a2..3d84d72fbf 100644 --- a/dexs/synfutures-v3/index.ts +++ b/dexs/synfutures-v3/index.ts @@ -1,30 +1,48 @@ +import BigNumber from "bignumber.js"; import request from "graphql-request"; import { Chain } from "@defillama/sdk/build/general"; import { CHAIN } from "../../helpers/chains"; import { ChainBlocks, FetchOptions, SimpleAdapter } from "../../adapters/types"; +import { getTimestampAtStartOfDayUTC, getTimestampAtStartOfNextDayUTC } from "../../utils/date"; const info: { [key: string]: any } = { [CHAIN.BLAST]: { subgraph: "https://api.synfutures.com/thegraph/v3-blast", }, + [CHAIN.BASE]: { + subgraph: "https://api.synfutures.com/thegraph/v3-base", + } }; +function convertDecimals(value: string | number, decimals: number) { + if (decimals > 18) { + return new BigNumber(value).multipliedBy(10 ** (decimals - 18)).toString(); + } else if (decimals < 18) { + return new BigNumber(value).dividedToIntegerBy(10 ** (18 - decimals)).toString(); + } else { + return value; + } +} + const fetch = (chain: Chain) => { return async ( timestamp: number, _: ChainBlocks, - { createBalances, startTimestamp, endTimestamp, startOfDay }: FetchOptions + { createBalances, startOfDay }: FetchOptions ) => { const dailyVolume = createBalances(); - + const cumulativeVolume = createBalances(); + const to = getTimestampAtStartOfNextDayUTC(timestamp) + const from = getTimestampAtStartOfDayUTC(timestamp) const graphQL = `{ amms(where: {status_in: [TRADING, SETTLING]}) { instrument { quote { id + decimals } } - hourlyDataList(where: {timestamp_gte: ${startTimestamp}, timestamp_lt: ${endTimestamp}}, orderBy: timestamp, orderDirection: desc) { + hourlyDataList(where: {timestamp_gte: ${from}, timestamp_lte: ${to - 1}}, orderBy: timestamp, orderDirection: desc) { volume } } @@ -35,16 +53,41 @@ const fetch = (chain: Chain) => { for (const { hourlyDataList, instrument: { - quote: { id }, + quote: { id, decimals }, }, } of data.amms) { for (const { volume } of hourlyDataList) { - dailyVolume.addToken(id, volume); + dailyVolume.addToken(id, convertDecimals(volume, decimals)); } } + const totalVolumeGraphQl = `{ + quoteDatas { + id + quote{ + decimals + } + totalVolume + } + }`; + + const totalVolumeData = await request( + info[chain].subgraph, + totalVolumeGraphQl + ); + + for (const { + id, + quote: { decimals }, + totalVolume, + } of totalVolumeData.quoteDatas) { + cumulativeVolume.addToken(id, convertDecimals(totalVolume, decimals)); + } + + return { dailyVolume, + totalVolume: cumulativeVolume, timestamp: startOfDay, }; }; @@ -56,6 +99,10 @@ const adapter: SimpleAdapter = { fetch: fetch(CHAIN.BLAST), start: 1709197491, }, + [CHAIN.BASE]: { + fetch: fetch(CHAIN.BASE), + start: 1719383967, + }, }, }; diff --git a/dexs/synthetix-v3/index.ts b/dexs/synthetix-v3/index.ts new file mode 100644 index 0000000000..00a41add82 --- /dev/null +++ b/dexs/synthetix-v3/index.ts @@ -0,0 +1,33 @@ +import { ChainBlocks, FetchOptions, SimpleAdapter } from "../../adapters/types"; +import { CHAIN } from "../../helpers/chains"; + +const contract_address = '0x0a2af931effd34b81ebcc57e3d3c9b1e1de1c9ce'; +const usdt = 'tether' +const event_order_settled = 'event OrderSettled(uint128 indexed marketId,uint128 indexed accountId,uint256 fillPrice,int256 pnl,int256 accruedFunding,int128 sizeDelta,int128 newSize,uint256 totalFees,uint256 referralFees,uint256 collectedFees,uint256 settlementReward,bytes32 indexed trackingCode,address settler)' +const fetchFees = async (timestamp: number, _: ChainBlocks, options: FetchOptions) => { + const dailyVolume = options.createBalances(); + const logs = await options.getLogs({ + target: contract_address, + eventAbi: event_order_settled + }); + + logs.forEach((log: any) => { + const volume = Math.abs(Number(log.fillPrice)/1e18 * Number(log.sizeDelta)/1e18) + dailyVolume.addCGToken(usdt, volume) + }); + + return { + dailyVolume: dailyVolume, + timestamp + } +} + +const adapters: SimpleAdapter = { + adapter: { + [CHAIN.BASE]: { + fetch: fetchFees, + start: 1705104000, + }, + } +} +export default adapters diff --git a/dexs/syrup-finance/index.ts b/dexs/syrup-finance/index.ts index 35e633ea7b..353182de2d 100644 --- a/dexs/syrup-finance/index.ts +++ b/dexs/syrup-finance/index.ts @@ -1,3 +1,4 @@ +import * as sdk from "@defillama/sdk"; import request, { gql } from "graphql-request"; import { DISABLED_ADAPTER_KEY, Fetch, SimpleAdapter } from "../../adapters/types"; import { CHAIN } from "../../helpers/chains"; @@ -5,7 +6,7 @@ import disabledAdapter from "../../helpers/disabledAdapter"; import { getUniqStartOfTodayTimestamp } from "../../helpers/getUniSubgraphVolume"; const endpoints: { [key: string]: string } = { - [CHAIN.BSC]: "https://api.thegraph.com/subgraphs/name/syrupmaker/srx-stats-bsc", + [CHAIN.BSC]: sdk.graph.modifyEndpoint('FxC8dAGA6jXCN4EUoPqDeoUWM9XE1VrttiEVT7LEGyxw'), } const historicalDataSwap = gql` diff --git a/dexs/tangleswap/index.ts b/dexs/tangleswap/index.ts index d4bb141392..e4d279aef4 100644 --- a/dexs/tangleswap/index.ts +++ b/dexs/tangleswap/index.ts @@ -1,20 +1,16 @@ import { SimpleAdapter } from "../../adapters/types"; import { CHAIN } from "../../helpers/chains"; -import { getGraphDimensions } from "../../helpers/getUniSubgraph"; -import { DEFAULT_DAILY_VOLUME_FACTORY, DEFAULT_TOTAL_VOLUME_FIELD, univ2Adapter } from "../../helpers/getUniSubgraphVolume"; +import { getGraphDimensions2 } from "../../helpers/getUniSubgraph"; +import { DEFAULT_TOTAL_VOLUME_FIELD } from "../../helpers/getUniSubgraphVolume"; const v3Endpoints = { [CHAIN.SHIMMER_EVM]: "https://shimmer.subgraph.tangleswap.space/subgraphs/name/tangleswap/shimmer-v3", } -const v3Graphs = getGraphDimensions({ +const v3Graphs = getGraphDimensions2({ graphUrls: v3Endpoints, totalVolume: { factory: "factories", field: DEFAULT_TOTAL_VOLUME_FIELD, }, - dailyVolume: { - factory: DEFAULT_DAILY_VOLUME_FACTORY, - field: "volumeUSD", - }, feesPercent: { type: "fees", ProtocolRevenue: 0, @@ -24,6 +20,7 @@ const v3Graphs = getGraphDimensions({ }); const adapter: SimpleAdapter = { + version: 2, adapter: Object.keys(v3Endpoints).reduce((acc, chain) => { return { ...acc, diff --git a/dexs/tegro/index.ts b/dexs/tegro/index.ts index beaff8935f..871717a4be 100644 --- a/dexs/tegro/index.ts +++ b/dexs/tegro/index.ts @@ -1,12 +1,13 @@ +import * as sdk from "@defillama/sdk"; import { CHAIN } from "../../helpers/chains"; import { univ2Adapter } from "../../helpers/getUniSubgraphVolume"; const adapters = univ2Adapter({ - [CHAIN.ETHEREUM]: 'https://api.thegraph.com/subgraphs/name/ashtegro/tegro', - [CHAIN.POLYGON]: 'https://api.thegraph.com/subgraphs/name/ashtegro/tegro-polygon', - [CHAIN.AVAX]: 'https://api.thegraph.com/subgraphs/name/ashtegro/tegro-avax', - [CHAIN.BSC]: 'https://api.thegraph.com/subgraphs/name/ashtegro/tegro-bnb', - [CHAIN.ARBITRUM]: 'https://api.thegraph.com/subgraphs/name/ashtegro/tegro-arbitrum', + [CHAIN.ETHEREUM]: sdk.graph.modifyEndpoint('Cypy2AGAgWwBUjBtQc6GeoGmibLH75v3eVhC9UPXHcHP'), + [CHAIN.POLYGON]: sdk.graph.modifyEndpoint('793XgZSYH8fTiZUMLYAE7mVkGgh9KGQufQhVjRvEdHn3'), + [CHAIN.AVAX]: sdk.graph.modifyEndpoint('N56YWKqnNPcruU72KM2rxtdFhAAKx2BWgCjZ1gxFokj'), + [CHAIN.BSC]: sdk.graph.modifyEndpoint('ExjMBMGp5EDeBBD9Yt43PeZJtKpP29wRs45JXkeCd712'), + [CHAIN.ARBITRUM]: sdk.graph.modifyEndpoint('7xPJ5PFAhXmqacuRQmftnYYixhqhfMvARZ6onXtbX3nQ'), }, { factoriesName: "totalVolumes", dailyVolume: "volume", diff --git a/dexs/templedao-trade/index.ts b/dexs/templedao-trade/index.ts index a09339c6c0..b741d0ca05 100644 --- a/dexs/templedao-trade/index.ts +++ b/dexs/templedao-trade/index.ts @@ -1,27 +1,26 @@ +import * as sdk from "@defillama/sdk"; import { Chain } from "@defillama/sdk/build/general"; import { SimpleAdapter } from "../../adapters/types"; import { CHAIN } from "../../helpers/chains"; import customBackfill from "../../helpers/customBackfill"; +import { getChainVolume2 } from "../../helpers/getUniSubgraphVolume"; -const { - getChainVolume, -} = require("../../helpers/getUniSubgraphVolume"); const endpoints = { - [CHAIN.ETHEREUM]: "https://api.thegraph.com/subgraphs/name/templedao/templedao-core" + [CHAIN.ETHEREUM]: sdk.graph.modifyEndpoint('6No9vpT4V56r2c4y4TxHsKs7hEbAWu66u19wNGAX8nxL') }; const VOLUME_FIELD = "volumeUSD"; -const graphs = getChainVolume({ +const graphs = getChainVolume2({ graphUrls: endpoints, totalVolume: { factory: "metrics", field: VOLUME_FIELD, }, - hasDailyVolume: false, }); const adapter: SimpleAdapter = { + version: 2, adapter: Object.keys(endpoints).reduce((acc, chain: any) => { return { ...acc, diff --git a/dexs/tetu/index.ts b/dexs/tetu/index.ts index 4dcf6815dd..d7935178ce 100644 --- a/dexs/tetu/index.ts +++ b/dexs/tetu/index.ts @@ -1,8 +1,9 @@ +import * as sdk from "@defillama/sdk"; import { CHAIN } from "../../helpers/chains"; import { univ2Adapter } from "../../helpers/getUniSubgraphVolume"; const adapters = univ2Adapter({ - [CHAIN.POLYGON]: "https://api.thegraph.com/subgraphs/name/tetu-io/tetu-swap" + [CHAIN.POLYGON]: sdk.graph.modifyEndpoint('D1aLXNYC1pZocgumq9yyKQMjFwZ14Gum3NUbZUA35Gty') }, { }); diff --git a/dexs/thalaswap/index.ts b/dexs/thalaswap/index.ts index 86e194ab75..01e8c2f2cf 100644 --- a/dexs/thalaswap/index.ts +++ b/dexs/thalaswap/index.ts @@ -2,16 +2,20 @@ import fetchURL from "../../utils/fetchURL"; import { SimpleAdapter } from "../../adapters/types"; import { CHAIN } from "../../helpers/chains"; -const thalaDappURL = 'https://app.thala.fi'; -const volumeQueryURL = `${thalaDappURL}/api/trading-volume-chart?timeframe=`; -const feesQueryURL = `${thalaDappURL}/api/trading-fee-chart?timeframe=`; -const protocolRatioQueryURL = `${thalaDappURL}/api/protocol-revenue-ratio`; +const thalaDappURL = "https://app.thala.fi"; +const volumeQueryURL = `${thalaDappURL}/api/defillama/trading-volume-chart?timeframe=`; +const feesQueryURL = `${thalaDappURL}/api/defillama/trading-fee-chart?timeframe=`; +const protocolRatioQueryURL = `${thalaDappURL}/api/defillama/protocol-revenue-ratio`; -const volumeEndpoint = (endTimestamp: number, timeframe: string) => -endTimestamp ? volumeQueryURL + timeframe + `&endTimestamp=${endTimestamp}` : volumeQueryURL + timeframe; +const volumeEndpoint = (endTimestamp: number, timeframe: string) => + endTimestamp + ? volumeQueryURL + timeframe + `&endTimestamp=${endTimestamp}` + : volumeQueryURL + timeframe; -const feesEndpoint = (endTimestamp: number, timeframe: string) => -endTimestamp ? feesQueryURL + timeframe + `&endTimestamp=${endTimestamp}` : feesQueryURL + timeframe; +const feesEndpoint = (endTimestamp: number, timeframe: string) => + endTimestamp + ? feesQueryURL + timeframe + `&endTimestamp=${endTimestamp}` + : feesQueryURL + timeframe; interface IVolumeall { value: number; @@ -19,21 +23,34 @@ interface IVolumeall { } const fetch = async (timestamp: number) => { - const dayVolumeQuery = (await fetchURL(volumeEndpoint(timestamp, "1D"))).data; - const dailyVolume = dayVolumeQuery.reduce((partialSum: number, a: IVolumeall) => partialSum + a.value, 0); + const dayVolumeQuery = (await fetchURL(volumeEndpoint(timestamp, "1D"))) + ?.data; + const dailyVolume = dayVolumeQuery.reduce( + (partialSum: number, a: IVolumeall) => partialSum + a.value, + 0 + ); - const totalVolumeQuery = (await fetchURL(volumeEndpoint(0, "ALL"))).data; - const totalVolume = totalVolumeQuery.reduce((partialSum: number, a: IVolumeall) => partialSum + a.value, 0); + const totalVolumeQuery = (await fetchURL(volumeEndpoint(0, "ALL")))?.data; + const totalVolume = totalVolumeQuery.reduce( + (partialSum: number, a: IVolumeall) => partialSum + a.value, + 0 + ); - const dayFeesQuery = (await fetchURL(feesEndpoint(timestamp, "1D"))).data; - const dailyFees = dayFeesQuery.reduce((partialSum: number, a: IVolumeall) => partialSum + a.value, 0); + const dayFeesQuery = (await fetchURL(feesEndpoint(timestamp, "1D")))?.data; + const dailyFees = dayFeesQuery.reduce( + (partialSum: number, a: IVolumeall) => partialSum + a.value, + 0 + ); - const totalFeesQuery = (await fetchURL(feesEndpoint(0, "ALL"))).data; - const totalFees = totalFeesQuery.reduce((partialSum: number, a: IVolumeall) => partialSum + a.value, 0); - - const protocolFeeRatio = (await fetchURL(protocolRatioQueryURL)).data; - const dailyProtocolRevenue = dailyFees * protocolFeeRatio; - const totalProtocolRevenue = totalFees * protocolFeeRatio; + const totalFeesQuery = (await fetchURL(feesEndpoint(0, "ALL")))?.data; + const totalFees = totalFeesQuery.reduce( + (partialSum: number, a: IVolumeall) => partialSum + a.value, + 0 + ); + + const protocolFeeRatio = (await fetchURL(protocolRatioQueryURL))?.data; + const dailyProtocolRevenue = dailyFees * protocolFeeRatio; + const totalProtocolRevenue = totalFees * protocolFeeRatio; return { totalVolume: `${totalVolume}`, @@ -46,12 +63,11 @@ const fetch = async (timestamp: number) => { }; }; - const adapter: SimpleAdapter = { adapter: { [CHAIN.APTOS]: { fetch, - start: 1680652406 + start: 1680652406, }, }, }; diff --git a/dexs/thena-perp/index.ts b/dexs/thena-perp/index.ts index 4d9e3939e9..03bdce385e 100644 --- a/dexs/thena-perp/index.ts +++ b/dexs/thena-perp/index.ts @@ -1,3 +1,4 @@ +import * as sdk from "@defillama/sdk"; import request, { gql } from "graphql-request"; import { FetchResultVolume, SimpleAdapter } from "../../adapters/types"; import { CHAIN } from "../../helpers/chains"; @@ -6,7 +7,7 @@ import { getUniqStartOfTodayTimestamp } from "../../helpers/getUniSubgraphVolume const ONE_DAY_IN_SECONDS = 60 * 60 * 24 -const endpoint = "https://api.thegraph.com/subgraphs/name/symmiograph/symmioanalytics_bnb_8_2" +const endpoint = sdk.graph.modifyEndpoint('DYHqLcjXMBC9c7AGvrYSBfQ6fQS723PJHF2usA9JX8NN') const query = gql` query stats($from: String!, $to: String!) { diff --git a/dexs/thena-v3/index.ts b/dexs/thena-v3/index.ts index 813d85c7b8..0250902c5b 100644 --- a/dexs/thena-v3/index.ts +++ b/dexs/thena-v3/index.ts @@ -1,8 +1,9 @@ +import * as sdk from "@defillama/sdk"; import { CHAIN } from "../../helpers/chains"; -import { univ2Adapter } from "../../helpers/getUniSubgraphVolume"; +import { univ2Adapter2 } from "../../helpers/getUniSubgraphVolume"; -const adapters = univ2Adapter({ - [CHAIN.BSC]: "https://api.thegraph.com/subgraphs/name/thenaursa/thena-fusion" +const adapters = univ2Adapter2({ + [CHAIN.BSC]: sdk.graph.modifyEndpoint('Hnjf3ipVMCkQze3jmHp8tpSMgPmtPnXBR38iM4ix1cLt') }, { factoriesName: "factories", dayData: "fusionDayData", @@ -10,5 +11,6 @@ const adapters = univ2Adapter({ totalVolume: "totalVolumeUSD", }); +adapters.version = 2; adapters.adapter.bsc.start = 1681516800; export default adapters; diff --git a/dexs/thena/index.ts b/dexs/thena/index.ts index 1f29106611..941e0abb85 100644 --- a/dexs/thena/index.ts +++ b/dexs/thena/index.ts @@ -1,14 +1,12 @@ +import * as sdk from "@defillama/sdk"; import { CHAIN } from "../../helpers/chains"; -import { univ2Adapter } from "../../helpers/getUniSubgraphVolume"; +import { univ2Adapter2 } from "../../helpers/getUniSubgraphVolume"; -const adapters = univ2Adapter({ - [CHAIN.BSC]: "https://api.thegraph.com/subgraphs/name/thenaursa/thena-v1" +const adapters = univ2Adapter2({ + [CHAIN.BSC]: sdk.graph.modifyEndpoint('FKEt2N5VmSdEYcz7fYLPvvnyEUkReQ7rvmXzs6tiKCz1') }, { factoriesName: "factories", totalVolume: "totalVolumeUSD", - dayData: "dayData", - dailyVolume: "dailyVolumeUSD", - dailyVolumeTimestampField: "date" }); adapters.adapter.bsc.start = 1672790400; diff --git a/dexs/thick/index.ts b/dexs/thick/index.ts index 530849a3e2..f664047ab6 100644 --- a/dexs/thick/index.ts +++ b/dexs/thick/index.ts @@ -1,6 +1,6 @@ -import { Fetch, SimpleAdapter } from "../../adapters/types"; +import { SimpleAdapter } from "../../adapters/types"; import { CHAIN } from "../../helpers/chains"; -import { getDexVolumeExportsV3 } from "../../helpers/dexVolumeLogs"; +import { uniV3Exports } from "../../helpers/uniswap"; const poolFactoryAddress = '0xE6dA85feb3B4E0d6AEd95c41a125fba859bB9d24'; @@ -11,24 +11,15 @@ const methodology = { HoldersRevenue: "Holders benefit from buyback using Protocol fees." } -const adapters: SimpleAdapter = { - adapter: { - [CHAIN.FANTOM]: { - fetch: getDexVolumeExportsV3({ factory: poolFactoryAddress, factoryFromBlock: 70309749, chain: CHAIN.FANTOM, }) as Fetch, - start: 1699300000, - meta: { methodology: { ...methodology, } }, - }, - [CHAIN.ARBITRUM]: { - fetch: getDexVolumeExportsV3({ factory: poolFactoryAddress, factoryFromBlock: 148243463, chain: CHAIN.ARBITRUM, }) as Fetch, - start: 1699300000, - meta: { methodology: { ...methodology, } }, - }, - [CHAIN.BASE]: { - fetch: getDexVolumeExportsV3({ factory: poolFactoryAddress, factoryFromBlock: 6314325, chain: CHAIN.BASE, }) as Fetch, - start: 1699300000, - meta: { methodology: { ...methodology, } }, - } - } -} +const adapters: SimpleAdapter = uniV3Exports({ + [CHAIN.FANTOM]: { factory: poolFactoryAddress, }, + [CHAIN.ARBITRUM]: { factory: poolFactoryAddress, }, + [CHAIN.BASE]: { factory: poolFactoryAddress, }, +}) + + +Object.keys(adapters.adapter).forEach((chain: any) => { + adapters.adapter[chain].meta = { methodology } +}) export default adapters; diff --git a/dexs/throne-v3/index.ts b/dexs/throne-v3/index.ts index 2df22f6b8c..553febae4e 100644 --- a/dexs/throne-v3/index.ts +++ b/dexs/throne-v3/index.ts @@ -1,31 +1,21 @@ +import * as sdk from "@defillama/sdk"; import { IJSON, SimpleAdapter } from "../../adapters/types"; import { CHAIN } from "../../helpers/chains"; - -import { getGraphDimensions } from "../../helpers/getUniSubgraph"; +import { getGraphDimensions2 } from "../../helpers/getUniSubgraph"; const v3Endpoint = { [CHAIN.BASE]: - "https://api.thegraph.com/subgraphs/name/somberload/throne-exchange-v3", + sdk.graph.modifyEndpoint('HRaFknkbRxB17ziZoMcT7EJuT42BKRYeYvKyQvJrQWJf'), }; -const VOLUME_USD = "volumeUSD"; - -const v3Graph = getGraphDimensions({ +const v3Graph = getGraphDimensions2({ graphUrls: v3Endpoint, totalVolume: { factory: "factories", }, - dailyVolume: { - factory: "pancakeDayData", - field: VOLUME_USD, - }, totalFees: { factory: "factories", }, - dailyFees: { - factory: "pancakeDayData", - field: "feesUSD", - }, }); const v3StartTimes = { @@ -33,6 +23,7 @@ const v3StartTimes = { } as IJSON; const adapter: SimpleAdapter = { + version: 2, adapter: { [CHAIN.BASE]: { fetch: v3Graph(CHAIN.BASE), diff --git a/dexs/titano-swych/index.ts b/dexs/titano-swych/index.ts index 68a383a124..de085d7213 100644 --- a/dexs/titano-swych/index.ts +++ b/dexs/titano-swych/index.ts @@ -1,9 +1,10 @@ +import * as sdk from "@defillama/sdk"; import { CHAIN } from "../../helpers/chains"; import { univ2Adapter } from "../../helpers/getUniSubgraphVolume"; const adapters = univ2Adapter({ - [CHAIN.BSC]: "https://api.thegraph.com/subgraphs/name/swychfinance/exchange" + [CHAIN.BSC]: sdk.graph.modifyEndpoint('FyXg4ty4DFtijG9wF9VzRpBPW21vNwuqVVYYap5mayy7') }, { factoriesName: "pancakeFactories", dayData: "pancakeDayData", diff --git a/dexs/tlx-finance/index.ts b/dexs/tlx-finance/index.ts new file mode 100644 index 0000000000..7cbf27a947 --- /dev/null +++ b/dexs/tlx-finance/index.ts @@ -0,0 +1,76 @@ +import BigNumber from "bignumber.js"; +import { + FetchGetLogsOptions, + FetchOptions, + FetchResultV2, + SimpleAdapter, +} from "../../adapters/types"; +import { CHAIN } from "../../helpers/chains"; +import { ChainApi } from "@defillama/sdk"; + +const FACTORY = "0x5Dd85f51e9fD6aDE8ecc216C07919ecD443eB14d"; +const MINT_EVENT = "event Minted(address indexed account, uint256 leveragedTokenAmount, uint256 baseAssetAmount)"; +const REDEEM_EVENT = "event Redeemed(address indexed account, uint256 leveragedTokenAmount, uint256 baseAssetAmount)"; + +const fetchLeveragedTokenVolume = async ( + getLogs: (params: FetchGetLogsOptions) => Promise, + toApi: ChainApi, + tokens: string[] +): Promise => { + const targetLeverages = await toApi.multiCall({ + abi: "function targetLeverage() view returns (uint256)", + calls: tokens.map((token) => ({ + target: token, + params: [], + })), + }); + + const mints_logs: any[] = await getLogs({ + targets: tokens, + eventAbi: MINT_EVENT, + flatten: false + }); + const redeems_logs: any[] = await getLogs({ + targets: tokens, + eventAbi: REDEEM_EVENT, + flatten: false + }); + + const mint_valume = mints_logs.map((logs, i) => { + return logs.map((log: any) => { + return new BigNumber(log.leveragedTokenAmount).times(targetLeverages[i]).div(1e18) + }) + }).flat().reduce((acc: any, log: any) => acc.plus(log), new BigNumber(0)); + + const redeem_valume = redeems_logs.map((logs, i) => { + return logs.map((log: any) => { + return new BigNumber(log.leveragedTokenAmount).times(targetLeverages[i]).div(1e18) + }) + }).flat().reduce((acc: any, log: any) => acc.plus(log), new BigNumber(0)); + + return mint_valume.plus(redeem_valume).toNumber(); +}; + +const fetchVolume = async (options: FetchOptions): Promise => { + const { getLogs, api } = options; + const allTokens = await api.call({ + target: FACTORY, + abi: "function allTokens() view returns (address[] memory)", + params: [], + }); + const volume = await fetchLeveragedTokenVolume(getLogs, api, allTokens) + const dailyVolume = options.createBalances() + dailyVolume.add("0x8c6f28f2F1A3C87F0f938b96d27520d9751ec8d9", volume); + return { dailyVolume }; +}; +const adapter: SimpleAdapter = { + version: 2, + adapter: { + [CHAIN.OPTIMISM]: { + fetch: fetchVolume, + start: 1715656337, + }, + }, +}; + +export default adapter; diff --git a/dexs/tokenlon/index.ts b/dexs/tokenlon/index.ts index cf0beb8607..ff99be8816 100644 --- a/dexs/tokenlon/index.ts +++ b/dexs/tokenlon/index.ts @@ -1,27 +1,142 @@ +import * as sdk from "@defillama/sdk"; import ADDRESSES from "../../helpers/coreAssets.json"; import { BreakdownAdapter, ChainBlocks, FetchOptions, FetchResultVolume, SimpleAdapter } from "../../adapters/types"; import { CHAIN } from "../../helpers/chains"; import { gql, request } from "graphql-request"; import { Chain } from "@defillama/sdk/build/general"; -import { getPrices } from "../../utils/prices"; +import { ethers } from "ethers"; interface IGraph { makerAssetAddr: string; makerAssetAmount: string; + makerToken: string; + makerTokenAmount: string; } interface IData { fillOrders: IGraph[]; swappeds: IGraph[]; + filledRFQs: IGraph[]; } +const ammABI = [{ + "anonymous": false, + "inputs": [ + { + "components": [ + { + "internalType": "string", + "name": "source", + "type": "string" + }, + { + "internalType": "bytes32", + "name": "transactionHash", + "type": "bytes32" + }, + { + "internalType": "uint256", + "name": "settleAmount", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "receivedAmount", + "type": "uint256" + }, + { + "internalType": "uint16", + "name": "feeFactor", + "type": "uint16" + }, + { + "internalType": "uint16", + "name": "subsidyFactor", + "type": "uint16" + } + ], + "indexed": false, + "internalType": "struct AMMWrapper.TxMetaData", + "name": "", + "type": "tuple" + }, + { + "components": [ + { + "internalType": "address", + "name": "makerAddr", + "type": "address" + }, + { + "internalType": "address", + "name": "takerAssetAddr", + "type": "address" + }, + { + "internalType": "address", + "name": "makerAssetAddr", + "type": "address" + }, + { + "internalType": "uint256", + "name": "takerAssetAmount", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "makerAssetAmount", + "type": "uint256" + }, + { + "internalType": "address", + "name": "userAddr", + "type": "address" + }, + { + "internalType": "address payable", + "name": "receiverAddr", + "type": "address" + }, + { + "internalType": "uint256", + "name": "salt", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "deadline", + "type": "uint256" + } + ], + "indexed": false, + "internalType": "struct AMMLibEIP712.Order", + "name": "order", + "type": "tuple" + } + ], + "name": "Swapped", + "type": "event" +}] + +const ammDecoder = new ethers.Interface(ammABI) + type TEndpoint = { [s: string | Chain]: string; }; +const config = { + [CHAIN.POLYGON]: { exchange: '0xac4F3817a726016fC8254119FC48bE838a21f17F' }, + [CHAIN.ARBITRUM]: { exchange: '0xac4F3817a726016fC8254119FC48bE838a21f17F' }, + [CHAIN.BASE]: { exchange: '0xac4F3817a726016fC8254119FC48bE838a21f17F' }, + [CHAIN.BSC]: { exchange: '0xac4F3817a726016fC8254119FC48bE838a21f17F' }, + [CHAIN.OPTIMISM]: { exchange: '0xac4F3817a726016fC8254119FC48bE838a21f17F' }, + [CHAIN.ERA]: { exchange: '0xC63c379Ae456af9C73Bf81A7D745fAF1d9e180e0' }, +} + const endpoints: TEndpoint = { - [CHAIN.ETHEREUM]: "https://api.thegraph.com/subgraphs/name/consenlabs/tokenlon-v5-exchange", + [CHAIN.ETHEREUM]: sdk.graph.modifyEndpoint('5JhweAV1Y3k3GbbEssfetBaoyDNWz1Y72zscRrYsAgVT'), }; +const rfqV2Endpoint = "https://satsuma-subgraph.token.im/subgraph/rfqv2/api" const fetchVolume = (chain: Chain) => { return async ( @@ -47,6 +162,21 @@ const fetchVolume = (chain: Chain) => { historicalData.map((e: IGraph) => { dailyVolume.add(e.makerAssetAddr, e.makerAssetAmount); }); + + const rfqv2Query = `{ + filledRFQs( + first: 1000 + where: {blockTimestamp_gte: ${fromTimestamp}, blockTimestamp_lte: ${toTimestamp}} + ) { + makerToken + makerTokenAmount + }}` + const rfqV2Response = await request(rfqV2Endpoint, rfqv2Query) + const rfqv2Record: IGraph[] = [...rfqV2Response.filledRFQs] + rfqv2Record.map((e: IGraph) => { + dailyVolume.add(e.makerToken, e.makerTokenAmount); + }); + return { dailyVolume, timestamp: toTimestamp }; }; }; @@ -56,19 +186,59 @@ const abis = { "event FillOrder(string source, bytes32 indexed transactionHash, bytes32 indexed orderHash, address indexed userAddr, address takerAssetAddr, uint256 takerAssetAmount, address makerAddr, address makerAssetAddr, uint256 makerAssetAmount, address receiverAddr, uint256 settleAmount, uint16 feeFactor)", Swapped: "event Swapped(string source, bytes32 indexed transactionHash, address indexed userAddr, address takerAssetAddr, uint256 takerAssetAmount, address makerAddr, address makerAssetAddr, uint256 makerAssetAmount, address receiverAddr, uint256 settleAmount, uint256 receivedAmount, uint16 feeFactor, uint16 subsidyFactor)", + FilledRFQ: + "event FilledRFQ(bytes32 indexed offerHash,address indexed user,address indexed maker,address takerToken,uint256 takerTokenAmount,address makerToken,uint256 makerTokenAmount,address recipient,uint256 settleAmount,uint256 feeFactor)", + FillOrderByRFQ: + "event FillOrder( string source,bytes32 indexed transactionHash,bytes32 indexed orderHash,address indexed userAddr,address takerAssetAddr,uint256 takerAssetAmount,address makerAddr,address makerAssetAddr,uint256 makerAssetAmount,address receiverAddr,uint256 settleAmount,uint16 feeFactor)", + + Swap: + "event Swap(bytes32 indexed swapHash,address indexed maker, address indexed taker,address recipient,address inputToken,uint256 inputAmount,address outputToken,uint256 outputAmount)", }; const fetch = async (timestamp: number, _: ChainBlocks, { createBalances, getLogs, chain, api }: FetchOptions) => { const dailyVolume = createBalances(); const pmmLogs = await getLogs({ target: "0x8D90113A1e286a5aB3e496fbD1853F265e5913c6", eventAbi: abis.FillOrder }); - const ammLogs = await getLogs({ target: "0x4a14347083B80E5216cA31350a2D21702aC3650d", eventAbi: abis.Swapped }); - [pmmLogs, ammLogs].flat().forEach((log: any) => { + const rfqv1Logs = await getLogs({ target: "0xfD6C2d2499b1331101726A8AC68CCc9Da3fAB54F", eventAbi: abis.FillOrderByRFQ }); + const rfqv2Logs = await getLogs({ target: "0x91c986709bb4fe0763edf8e2690ee9d5019bea4a", eventAbi: abis.FilledRFQ }); + const ammV1Logs = await getLogs({ target: "0x4a14347083B80E5216cA31350a2D21702aC3650d", eventAbi: abis.Swapped}); + const ammV2Logs = await getLogs({ target: "0x4a14347083B80E5216cA31350a2D21702aC3650d", topic: "0xc36ae6e11a161c28ae95fc0f8c0f56d3d0fb7f3a3524499c53fb6733ed86764d"}); + + [ammV1Logs, rfqv1Logs, pmmLogs].flat().forEach((log: any) => { dailyVolume.add(log.makerAssetAddr, log.makerAssetAmount); }); + + [ammV2Logs].flat().forEach((log: any) => { + const parsedLog = ammDecoder.parseLog(log) + if (parsedLog == null) { + return + } + const order = parsedLog.args.order + dailyVolume.add(order.makerAssetAddr, order.makerAssetAmount); + }); + + [rfqv2Logs].flat().forEach((log: any) => { + dailyVolume.add(log.makerToken, log.makerTokenAmount); + }); + return { timestamp, dailyVolume }; +}; + +const fetchL2 = async (timestamp: number, _: ChainBlocks, { createBalances, getLogs, chain, api }: FetchOptions) => { + const dailyVolume = createBalances(); + const ammLogs = await getLogs({ target: config[chain].exchange, eventAbi: abis.Swap }); + + [ammLogs].flat().forEach((log: any) => { + dailyVolume.add(log.inputToken, log.inputAmount); + }); return { timestamp, dailyVolume }; }; +const adaptersMultiChain : any = {} +adaptersMultiChain[CHAIN.ETHEREUM] = {fetch, start: 1608048000} +Object.keys(config).forEach(chain => { + adaptersMultiChain[chain] = { fetch: fetchL2, start: 0 } +}) + const adapter: BreakdownAdapter = { breakdown: { tokenlon: { @@ -77,12 +247,7 @@ const adapter: BreakdownAdapter = { start: 1608216488, }, }, - "tokenlon-agg": { - [CHAIN.ETHEREUM]: { - fetch, - start: 1702857600, - }, - }, + "tokenlon-agg":adaptersMultiChain, }, }; diff --git a/dexs/torch/index.ts b/dexs/torch/index.ts new file mode 100644 index 0000000000..893dc69b82 --- /dev/null +++ b/dexs/torch/index.ts @@ -0,0 +1,23 @@ +import fetchURL from '../../utils/fetchURL' +import { FetchOptions, SimpleAdapter } from '../../adapters/types' + +const fetch = async (options: FetchOptions) => { + const dailyVolumeResult = await fetchURL( + 'https://api.torch.finance/stats/daily-volume', + ) + + return { + dailyVolume: dailyVolumeResult.dailyVolume, + } +} + +const adapter: SimpleAdapter = { + adapter: { + ton: { + fetch, + start: 1725256740, + }, + }, +} + +export default adapter diff --git a/dexs/traderjoe-lb-v2-2/index.ts b/dexs/traderjoe-lb-v2-2/index.ts new file mode 100644 index 0000000000..88c4d85a77 --- /dev/null +++ b/dexs/traderjoe-lb-v2-2/index.ts @@ -0,0 +1,68 @@ +import { abi } from "@defillama/sdk/build/api"; +import { Fetch, FetchOptions, IJSON, SimpleAdapter } from "../../adapters/types"; +import { CHAIN } from "../../helpers/chains"; + + +const factory = { + [CHAIN.AVAX]: '0xb43120c4745967fa9b93E79C149E66B0f2D6Fe0c', + [CHAIN.ARBITRUM]: '0xb43120c4745967fa9b93E79C149E66B0f2D6Fe0c', +} +const swap_event = 'event Swap(address indexed sender,address indexed to,uint24 id,bytes32 amountsIn,bytes32 amountsOut,uint24 volatilityAccumulator,bytes32 totalFees,bytes32 protocolFees)' +const fetchVolume = async (options: FetchOptions) => { + const {api } = options; + const pools = await api.fetchList({ target: factory[options.chain], itemAbi: 'getLBPairAtIndex', lengthAbi: 'getNumberOfLBPairs', }) + const tokenA = await api.multiCall({ abi: 'address:getTokenX', calls: pools, }) + const tokenB = await api.multiCall({ abi: 'address:getTokenY', calls: pools, }) + + const decimalsXs = await api.multiCall({ abi: 'erc20:decimals', calls: tokenA }) + const decimalsYs = await api.multiCall({ abi: 'erc20:decimals', calls: tokenB }) + + const pairObject: IJSON = {} + pools.forEach((pair: string, i: number) => { + pairObject[pair] = [tokenA[i], tokenB[i]] + }) + const logs = await options.getLogs({ + targets: pools, + eventAbi: swap_event, + flatten: false, + }) + const dailyVolume = options.createBalances() + const dailyFees = options.createBalances() + const dailyRevenue = options.createBalances() + logs.forEach((_logs, i) => { + _logs.forEach(log => { + const amountInX = Number('0x' + '0'.repeat(32) + log.amountsIn.replace('0x', '').slice(0, 32)) + const amountInY = Number('0x' + '0'.repeat(32) + log.amountsIn.replace('0x', '').slice(32, 64)) + const token0 = tokenA[i] + const token1 = tokenB[i] + dailyVolume.add(token0, amountInY); + dailyVolume.add(token1, amountInX); + const decimalsX = decimalsXs[i]; + const decimalsY = decimalsYs[i]; + const protocolFeesY = Number('0x' + log.protocolFees.replace('0x', '').slice(0, 32)) + const protocolFeesX = Number('0x' + log.protocolFees.replace('0x', '').slice(32, 64)) + const totalFeesY = Number('0x' + log.totalFees.replace('0x', '').slice(0, 32)); + const totalFeesX = Number('0x' + log.totalFees.replace('0x', '').slice(32, 64)); + dailyFees.add(token0, totalFeesX / 10 ** (18 - decimalsX)) + dailyFees.add(token1, totalFeesY / 10 ** (18 - decimalsY)) + dailyRevenue.add(token0, protocolFeesX / 10 ** (18 - decimalsX)) + dailyRevenue.add(token1, protocolFeesY / 10 ** (18 - decimalsY)) + }) + }) + return {dailyVolume, dailyFees, dailyRevenue} +} + +const adapters: SimpleAdapter = { + version: 2, + adapter: { + [CHAIN.AVAX]: { + fetch: fetchVolume, + start: 0, + }, + [CHAIN.ARBITRUM]: { + fetch: fetchVolume, + start: 0, + }, + } +} +export default adapters diff --git a/dexs/traderjoe/index.ts b/dexs/traderjoe/index.ts index 376566db99..bfe26bdeb8 100644 --- a/dexs/traderjoe/index.ts +++ b/dexs/traderjoe/index.ts @@ -1,44 +1,54 @@ +import * as sdk from "@defillama/sdk"; import { Chain } from "@defillama/sdk/build/general"; -import { BreakdownAdapter, FetchResultVolume } from "../../adapters/types"; +import { BreakdownAdapter, FetchOptions, FetchResult, FetchResultV2 } from "../../adapters/types"; import { CHAIN } from "../../helpers/chains"; -import { getChainVolume, getUniqStartOfTodayTimestamp } from "../../helpers/getUniSubgraphVolume"; -import fetchURL from "../../utils/fetchURL"; +import { getChainVolume, getChainVolume2, getUniqStartOfTodayTimestamp } from "../../helpers/getUniSubgraphVolume"; +import { httpGet } from "../../utils/fetchURL"; const endpoints = { - [CHAIN.AVAX]: "https://api.thegraph.com/subgraphs/name/traderjoe-xyz/exchange", - [CHAIN.BSC]: "https://api.thegraph.com/subgraphs/name/traderjoe-xyz/joe-v1-bnb", - [CHAIN.ARBITRUM]: "https://api.thegraph.com/subgraphs/name/traderjoe-xyz/joe-v1-arbitrum", + [CHAIN.AVAX]: sdk.graph.modifyEndpoint('9ZjERoA7jGANYNz1YNuFMBt11fK44krveEhzssJTWokM'), + [CHAIN.BSC]: sdk.graph.modifyEndpoint('3VgCBQh13PseR81hPNAbKua3gD8b8r33LauKjVnMbSAs'), + [CHAIN.ARBITRUM]: sdk.graph.modifyEndpoint('3jFnXqk6UXZyciPu5jfUuPR7kzGXPSndsLNrWXQ6xAxk'), }; type TEndpoint = { [s: string | Chain]: string; } const endpointsV2: TEndpoint = { - [CHAIN.AVAX]: "https://api.thegraph.com/subgraphs/name/traderjoe-xyz/joe-v2", + [CHAIN.AVAX]: sdk.graph.modifyEndpoint('6KD9JYCg2qa3TxNK3tLdhj5zuZTABoLLNcnUZXKG9vuH'), [CHAIN.ARBITRUM]: "https://barn.traderjoexyz.com/v1/dex/analytics/arbitrum?startTime=1672012800&aggregateBy=daily", - [CHAIN.BSC]: "https://barn.traderjoexyz.com/v1/dex/analytics/binance?startTime=1677801600&aggregateBy=daily" + [CHAIN.BSC]: "https://barn.traderjoexyz.com/v1/dex/analytics/binance?startTime=1677801600&aggregateBy=daily", + [CHAIN.ETHEREUM]: "https://barn.traderjoexyz.com/v1/dex/analytics/ethereum?startTime=1695513600&aggregateBy=daily" } interface IVolume { timestamp: number; volumeUsd: number; } -const fetchV2 = (chain: Chain) => { - return async (timestamp: number): Promise => { - const dayTimestamp = getUniqStartOfTodayTimestamp(new Date(timestamp * 1000)) - const historicalVolume: IVolume[] = (await fetchURL(endpointsV2[chain])); - const totalVolume = historicalVolume - .filter(volItem => volItem.timestamp <= dayTimestamp) - .reduce((acc, { volumeUsd }) => acc + Number(volumeUsd), 0) +const fetchV2 = async (_t: any, _tt: any, options: FetchOptions): Promise => { + const dayTimestamp = options.startOfDay; + const start = options.startOfDay; + const end = start + 24 * 60 * 60; + const url = `https://api.traderjoexyz.dev/v1/dex/analytics/${mapChain(options.chain)}?startTime=${start}&endTime=${end}` + const historicalVolume: IVolume[] = (await httpGet(url, { headers: { + 'x-traderjoe-api-key': process.env.TRADERJOE_API_KEY + }})); - const dailyVolume = historicalVolume - .find(dayItem => dayItem.timestamp === dayTimestamp)?.volumeUsd - return { - totalVolume: `${totalVolume}`, - dailyVolume: dailyVolume !== undefined ? `${dailyVolume}` : undefined, - timestamp: dayTimestamp, - } + const totalVolume = historicalVolume + .filter(volItem => volItem.timestamp <= dayTimestamp) + .reduce((acc, { volumeUsd }) => acc + Number(volumeUsd), 0) + + const dailyVolume = historicalVolume + .find(dayItem => dayItem.timestamp === dayTimestamp)?.volumeUsd + return { + totalVolume: `${totalVolume}`, + dailyVolume: dailyVolume !== undefined ? `${dailyVolume}` : undefined, + timestamp: dayTimestamp, } } +const mapChain = (chain: Chain): string => { + if (chain === CHAIN.BSC) return "binance" + return chain +} const graphsV1 = getChainVolume({ graphUrls: endpoints, @@ -46,11 +56,6 @@ const graphsV1 = getChainVolume({ factory: "factories", field: "volumeUSD", }, - dailyVolume: { - factory: "dayData", - field: "volumeUSD", - dateField: "date" - }, }); @@ -60,14 +65,10 @@ const graphsV2 = getChainVolume({ factory: "lbfactories", field: "volumeUSD", }, - dailyVolume: { - factory: "traderJoeDayData", - field: "volumeUSD", - dateField: "date" - }, }); const adapter: BreakdownAdapter = { + version: 1, breakdown: { v1: { [CHAIN.AVAX]: { @@ -89,13 +90,17 @@ const adapter: BreakdownAdapter = { start: 1668556800 }, [CHAIN.ARBITRUM]: { - fetch: fetchV2(CHAIN.ARBITRUM), + fetch: fetchV2, start: 1672012800 }, [CHAIN.BSC]: { - fetch: fetchV2(CHAIN.BSC), + fetch: fetchV2, start: 1677801600 }, + [CHAIN.ETHEREUM]: { + fetch: fetchV2, + start: 1695513600 + } } }, }; diff --git a/dexs/tradoor/index.ts b/dexs/tradoor/index.ts new file mode 100644 index 0000000000..911cadc7c5 --- /dev/null +++ b/dexs/tradoor/index.ts @@ -0,0 +1,31 @@ +import { postURL } from "../../utils/fetchURL" +import { CHAIN } from "../../helpers/chains"; +import { FetchOptions } from "../../adapters/types"; + +const endpoint = "https://www.tradoor.io/stats/volume" + + +const fetch = async (options: FetchOptions) => { + const res = await postURL(endpoint, { + "startTime": options.startTimestamp, + "endTime": options.endTimestamp + }) + + return { + dailyVolume: parseInt(res['data']), + timestamp: options.startTimestamp, + }; +}; + + +const adapter: any = { + version: 2, + adapter: { + [CHAIN.TON]: { + fetch, + start: 1716048000, + }, + }, +}; + +export default adapter; diff --git a/dexs/trisolaris/index.ts b/dexs/trisolaris/index.ts index 2c9001ec69..c56935f451 100644 --- a/dexs/trisolaris/index.ts +++ b/dexs/trisolaris/index.ts @@ -1,29 +1,6 @@ -import { SimpleAdapter } from "../../adapters/types" -import { CHAIN } from "../../helpers/chains" -import { getDexVolumeExports } from "../../helpers/dexVolumeLogs"; +import { CHAIN } from "../../helpers/chains"; +import { uniV2Exports } from "../../helpers/uniswap"; -const pools: string[] = [ - '0x1e0e812fbcd3eb75d8562ad6f310ed94d258d008', - '0x63da4db6ef4e7c62168ab03982399f9588fcd198', - '0x03b666f3488a7992b2385b12df7f35156d7b29cd', - '0x20f8aefb5697b77e0bb835a8518be70775cda1b0', - '0xbc8a244e8fb683ec1fd6f88f3cc6e565082174eb', - '0x84b123875f0f36b966d0b6ca14b31121bd9676ad', - '0x5eec60f348cb1d661e4a5122cf4638c7db7a886e', - '0xd1654a7713617d41a8c9530fb9b948d00e162194', - '0x61c9e05d1cdb1b70856c7a2c53fa9c220830633c', - '0x48887ceea1b8ad328d5254bef774be91b90faa09', - '0x044b6b0cd3bb13d2b9057781df4459c66781dce7', - '0x5e74d85311fe2409c341ce49ce432bb950d221de' -].map((address: string) => address.toLowerCase()); - -const adapters: SimpleAdapter = { - adapter: { - [CHAIN.AURORA]: { - fetch: getDexVolumeExports({ chain: CHAIN.AURORA, pools }), - start: 1678838400, - } - } -} - -export default adapters +export default uniV2Exports({ + [CHAIN.AURORA]: { factory: '0xc66F594268041dB60507F00703b152492fb176E7', }, +}) diff --git a/dexs/ubeswap/index.ts b/dexs/ubeswap/index.ts index c8c6fdf4ed..d60ea16812 100644 --- a/dexs/ubeswap/index.ts +++ b/dexs/ubeswap/index.ts @@ -1,8 +1,9 @@ +import * as sdk from "@defillama/sdk"; import { CHAIN } from "../../helpers/chains"; import { univ2Adapter } from "../../helpers/getUniSubgraphVolume"; const adapters = univ2Adapter({ - [CHAIN.CELO]: "https://api.thegraph.com/subgraphs/name/ubeswap/ubeswap" + [CHAIN.CELO]: sdk.graph.modifyEndpoint('JWDRLCwj4H945xEkbB6eocBSZcYnibqcJPJ8h9davFi') }, { factoriesName: "ubeswapFactories", dayData: "ubeswapDayData", diff --git a/dexs/unidex/index.ts b/dexs/unidex/index.ts index ae5d159a9f..6cc3037c4a 100644 --- a/dexs/unidex/index.ts +++ b/dexs/unidex/index.ts @@ -1,13 +1,11 @@ -import { SimpleAdapter, FetchResultVolume } from "../../adapters/types"; +import { FetchResultVolume, BreakdownAdapter } from "../../adapters/types"; import { CHAIN } from "../../helpers/chains"; import { getTimestampAtStartOfDayUTC } from "../../utils/date"; import { Chain } from "@defillama/sdk/build/general"; import request, { gql } from "graphql-request"; +import { adapter_dexs_agg } from './unidex-dexs-agg/index'; -type TChainIDs = { - [key in Chain]?: number; -}; - +type TChainIDs = { [key in Chain]?: number; }; const chainIDs: TChainIDs = { [CHAIN.FANTOM]: 250, [CHAIN.ARBITRUM]: 42161, @@ -20,36 +18,38 @@ const chainIDs: TChainIDs = { interface IDayProduct { cumulativeVolumeUsd: number; - _id: string; + chainId: number; } const fetch = (chain: Chain) => { return async (timestamp: number): Promise => { const todaysTimestamp = getTimestampAtStartOfDayUTC(timestamp); - const graphQuery = gql` query MyQuery { - DayProducts(limit: 0, filter: {date: ${todaysTimestamp}}) { + DayProducts(limit: 0, filter: { date: ${todaysTimestamp} }) { cumulativeVolumeUsd - _id + chainId } } `; - - const endpoint = "https://arkiverbackup.moltennetwork.com/graphql"; + const endpoint = "https://arkiver.moltennetwork.com/graphql"; const response = await request(endpoint, graphQuery); const dayProducts: IDayProduct[] = response.DayProducts; - const chainID = chainIDs[chain]; - let dailyVolumeUSD = 0; - + const volumeByChain: { [chainId: number]: number } = {}; dayProducts.forEach((product) => { - const productChainID = parseInt(product._id.split(":")[2]); - if (productChainID === chainID) { - dailyVolumeUSD += product.cumulativeVolumeUsd; + const chainId = product.chainId; + if (chainId === 360) { + // Combine volume for chainID 360 with chainID 42161 + volumeByChain[42161] = (volumeByChain[42161] || 0) + product.cumulativeVolumeUsd; + } else { + volumeByChain[chainId] = (volumeByChain[chainId] || 0) + product.cumulativeVolumeUsd; } }); + const chainID = chainIDs[chain]; + const dailyVolumeUSD = chainID !== undefined ? volumeByChain[chainID] || 0 : 0; + return { dailyVolume: dailyVolumeUSD.toString(), timestamp: todaysTimestamp, @@ -58,62 +58,54 @@ const fetch = (chain: Chain) => { }; const methodology = { - dailyVolume: - "Sum of cumulativeVolumeUsd for all products on the specified chain for the given day", + dailyVolume: "Sum of cumulativeVolumeUsd for all products on the specified chain for the given day", }; -const adapter: SimpleAdapter = { +const adapter: any = { adapter: { [CHAIN.OPTIMISM]: { fetch: fetch(CHAIN.OPTIMISM), start: 1687422746, - meta: { - methodology, - }, + meta: { methodology }, }, [CHAIN.ERA]: { fetch: fetch(CHAIN.ERA), start: 1687422746, - meta: { - methodology, - }, + meta: { methodology }, }, [CHAIN.ARBITRUM]: { fetch: fetch(CHAIN.ARBITRUM), start: 1687422746, - meta: { - methodology, - }, + meta: { methodology }, }, [CHAIN.BASE]: { fetch: fetch(CHAIN.BASE), start: 1687422746, - meta: { - methodology, - }, + meta: { methodology }, }, [CHAIN.FANTOM]: { fetch: fetch(CHAIN.FANTOM), start: 1687422746, - meta: { - methodology, - }, + meta: { methodology }, }, [CHAIN.METIS]: { fetch: fetch(CHAIN.METIS), start: 1687898060, - meta: { - methodology, - }, + meta: { methodology }, }, [CHAIN.EVMOS]: { fetch: fetch(CHAIN.EVMOS), start: 1700104066, - meta: { - methodology, - }, + meta: { methodology }, }, }, }; -export default adapter; +const adapterbreakdown: BreakdownAdapter = { + breakdown: { + "unidex": adapter["adapter"], + "unidex-dexs-agg": adapter_dexs_agg["adapter"], + } +}; + +export default adapterbreakdown; diff --git a/dexs/unidex/unidex-dexs-agg/index.ts b/dexs/unidex/unidex-dexs-agg/index.ts new file mode 100644 index 0000000000..7a81f1432d --- /dev/null +++ b/dexs/unidex/unidex-dexs-agg/index.ts @@ -0,0 +1,62 @@ +import { FetchResult } from "../../../adapters/types"; +import { getUniqStartOfTodayTimestamp } from "../../../helpers/getUniSubgraphVolume"; +import { CHAIN } from "../../../helpers/chains"; +import { httpGet } from "../../../utils/fetchURL"; + +const chainsMap: Record = { + ETHEREUM: "ethereum", + ARBITRUM: "arbitrum", + POLYGON: "polygon", + BNB: "bsc", + OPTIMISM: "optimism", + BASE: "base", + FANTOM: "fantom", + METIS: "metis", + GNOSIS: "gnosis", + [CHAIN.ERA]: "zksync", + AVALANCHE: "avax", +}; + +const fetch = + (chain: string) => + async (timestamp: number): Promise => { + try { + const unixTimestamp = getUniqStartOfTodayTimestamp(); + + const response = await httpGet(`https://unidexswaps.metabaseapp.com/api/public/dashboard/f0dd81ef-7bc7-47b5-9ac4-281c7cd71bdc/dashcard/11/card/12?parameters=%5B%5D`) + + const rows = response.data.rows; + const chainData = rows.find( + (row: any) => row[1].toLowerCase() === chain + ); + + return { + dailyVolume: chainData ? chainData[2]?.toString() : "0", + timestamp: unixTimestamp, + }; + } catch (e: any) { + return { + dailyVolume: "0", + timestamp: timestamp, + } + } + }; + +const adapter_dexs_agg: any = { + adapter: { + ...Object.values(chainsMap).reduce((acc, chain) => { + return { + ...acc, + [(chainsMap as any)[chain] || chain]: { + fetch: fetch(chain), + runAtCurrTime: true, + start: 1704348000, + }, + }; + }, {}), + }, +}; + +export { + adapter_dexs_agg +} diff --git a/dexs/vapordex/index.ts b/dexs/vapordex/index.ts index d71f45f1d0..b995877c01 100644 --- a/dexs/vapordex/index.ts +++ b/dexs/vapordex/index.ts @@ -3,6 +3,7 @@ import v2 from "./v2"; import { BreakdownAdapter } from "../../adapters/types"; const adapter: BreakdownAdapter = { + version: 2, breakdown: { v1: v1, v2: v2, diff --git a/dexs/vapordex/v1.ts b/dexs/vapordex/v1.ts index 9c33b448a8..a287076366 100644 --- a/dexs/vapordex/v1.ts +++ b/dexs/vapordex/v1.ts @@ -1,10 +1,11 @@ +import * as sdk from "@defillama/sdk"; import { CHAIN } from "../../helpers/chains"; import { univ2Adapter } from "../../helpers/getUniSubgraphVolume"; const v1 = univ2Adapter( { [CHAIN.AVAX]: - "https://api.thegraph.com/subgraphs/name/mejiasd3v/vapordex-avalanche", + sdk.graph.modifyEndpoint('B6Tur5gXGCcswG8rEtmwfjBqeyDXCDUQSwM9wUXHoui5'), }, { factoriesName: "dexAmmProtocols", diff --git a/dexs/vapordex/v2.ts b/dexs/vapordex/v2.ts index 5bab677215..63e6bd52bb 100644 --- a/dexs/vapordex/v2.ts +++ b/dexs/vapordex/v2.ts @@ -43,7 +43,7 @@ const v2 = Object.keys(endpointsV2).reduce( start: startTimeV2[chain], }, }), - {} + { } ); export default v2; diff --git a/dexs/vela/index.ts b/dexs/vela/index.ts index cd0d7885ab..79eebf2c6d 100644 --- a/dexs/vela/index.ts +++ b/dexs/vela/index.ts @@ -1,3 +1,4 @@ +import * as sdk from "@defillama/sdk"; import { Adapter } from "../../adapters/types"; import { CHAIN } from "../../helpers/chains"; import { request, gql } from "graphql-request"; @@ -7,9 +8,9 @@ import { getTimestampAtStartOfDayUTC } from "../../utils/date"; const endpoints = { [CHAIN.ARBITRUM]: - "https://api.thegraph.com/subgraphs/name/velaexchange/vela-exchange-official", + sdk.graph.modifyEndpoint('https://api.goldsky.com/api/public/project_clu01p4nr68r301pze2tj4sh7/subgraphs/vela-arbitrum/mainnet/gn'), [CHAIN.BASE]: - "https://api.thegraph.com/subgraphs/name/velaexchange/vela-exchange-official-base" + sdk.graph.modifyEndpoint('https://api.goldsky.com/api/public/project_clu01p4nr68r301pze2tj4sh7/subgraphs/vela-base/mainnet/gn') }; const graphs = (graphUrls: ChainEndpoints) => { diff --git a/dexs/velocimeter-v2/index.ts b/dexs/velocimeter-v2/index.ts index 5337e6c9af..e1b04b1492 100644 --- a/dexs/velocimeter-v2/index.ts +++ b/dexs/velocimeter-v2/index.ts @@ -1,17 +1,6 @@ -import { SimpleAdapter } from '../../adapters/types' -import { CHAIN } from '../../helpers/chains' -import { getDexVolumeExports } from '../../helpers/dexVolumeLogs' +import { CHAIN } from "../../helpers/chains"; +import { uniV2Exports } from "../../helpers/uniswap"; -// see https://docs.velocimeter.xyz/security#v2-contract-addresses -const FACTORY_ADDRESS = '0xF80909DF0A01ff18e4D37BF682E40519B21Def46' - -const adapter: SimpleAdapter = { - adapter: { - [CHAIN.CANTO]: { - fetch: getDexVolumeExports({ chain: CHAIN.CANTO, factory: FACTORY_ADDRESS }), - start: 1678512026, // when PairFactory was created https://tuber.build/address/0xF80909DF0A01ff18e4D37BF682E40519B21Def46 - }, - }, -} - -export default adapter +export default uniV2Exports({ + [CHAIN.CANTO]: { factory: '0xF80909DF0A01ff18e4D37BF682E40519B21Def46', }, +}) diff --git a/dexs/velodrome-slipstream/index.ts b/dexs/velodrome-slipstream/index.ts new file mode 100644 index 0000000000..ad5671e241 --- /dev/null +++ b/dexs/velodrome-slipstream/index.ts @@ -0,0 +1,105 @@ +import { FetchOptions, FetchResultV2, SimpleAdapter } from "../../adapters/types"; +import { CHAIN } from "../../helpers/chains"; + +const sugarOld = '0x3e532BC1998584fe18e357B5187897ad0110ED3A'; // old Sugar version doesn't properly support pagination +const sugar = '0xdE2aE25FB984dd60C77dcF6489Be9ee6438eC195'; +const abis: any = { + "forSwaps": "function forSwaps(uint256 _limit, uint256 _offset) view returns ((address lp, int24 type, address token0, address token1, address factory, uint256 pool_fee)[])" +} + +interface IForSwap { + lp: string; + token0: string; + token1: string; + pool_fee: string; +} + +interface ILog { + address: string; + data: string; + transactionHash: string; + topics: string[]; +} +const event_swap = 'event Swap(address indexed sender, address indexed recipient, int256 amount0, int256 amount1, uint160 sqrtPriceX96, uint128 liquidity, int24 tick)' + +const fetch = async (options: FetchOptions): Promise => { + const dailyVolume = options.createBalances() + const dailyFees = options.createBalances() + let chunkSize = 400; + let currentOffset = 0; + const allForSwaps: IForSwap[] = []; + let unfinished = true; + let sugarContract = sugar; + + // before the new Sugar is deployed, we must use the old Sugar contract, and make one large Sugar call + if (options.startOfDay < 1715160600) { + chunkSize = 1800; + sugarContract = sugarOld; + } + + while (unfinished) { + const forSwapsUnfiltered: IForSwap[] = (await options.api.call({ + target: sugarContract, + params: [chunkSize, currentOffset], + abi: abis.forSwaps, + chain: CHAIN.OPTIMISM, + })); + + const forSwaps: IForSwap[] = forSwapsUnfiltered.filter(t => Number(t.type) > 0).map((e: any) => { + return { + lp: e.lp, + token0: e.token0, + token1: e.token1, + pool_fee: e.pool_fee, + } + }); + + unfinished = forSwapsUnfiltered.length !== 0; + currentOffset += chunkSize; + allForSwaps.push(...forSwaps); + } + + const targets = allForSwaps.map((forSwap: IForSwap) => forSwap.lp) + + let logs: ILog[][] = []; + const targetChunkSize = 5; + let currentTargetOffset = 0; + unfinished = true; + + while (unfinished) { + let endOffset = currentTargetOffset + targetChunkSize; + if (endOffset >= targets.length) { + unfinished = false; + endOffset = targets.length; + } + + let currentLogs: ILog[][] = await options.getLogs({ + targets: targets.slice(currentTargetOffset, endOffset), + eventAbi: event_swap, + flatten: false, + }) + + logs.push(...currentLogs); + currentTargetOffset += targetChunkSize; + } + + logs.forEach((logs: ILog[], idx: number) => { + const { token1, pool_fee } = allForSwaps[idx] + logs.forEach((log: any) => { + dailyVolume.add(token1, BigInt(Math.abs(Number(log.amount1)))) + dailyFees.add(token1, BigInt( Math.round((((Math.abs(Number(log.amount1))) * Number(pool_fee)) / 1000000)))) // 1% fee represented as pool_fee=10000 + }) + }) + + return { dailyVolume, dailyFees, dailyRevenue: dailyFees, dailyHoldersRevenue: dailyFees } +} +const adapters: SimpleAdapter = { + version: 2, + adapter: { + [CHAIN.OPTIMISM]: { + fetch: fetch as any, + start: 1709724600, + } + } +} +export default adapters; diff --git a/dexs/velodrome-v2/index.ts b/dexs/velodrome-v2/index.ts index 5ccc4d82e5..53ec460e68 100644 --- a/dexs/velodrome-v2/index.ts +++ b/dexs/velodrome-v2/index.ts @@ -1,14 +1,7 @@ -import { SimpleAdapter } from "../../adapters/types"; import { CHAIN } from "../../helpers/chains"; -import { fetchV2 } from "./v2"; +import { uniV2Exports } from "../../helpers/uniswap"; +const swapEvent = 'event Swap(address indexed sender, address indexed to, uint256 amount0In, uint256 amount1In, uint256 amount0Out, uint256 amount1Out)'; -const adapter: SimpleAdapter = { - adapter: { - [CHAIN.OPTIMISM]: { - fetch: fetchV2, - start: 1677110400 - }, - }, -}; - -export default adapter; +export default uniV2Exports({ + [CHAIN.OPTIMISM]: { factory: '0xF1046053aa5682b4F9a81b5481394DA16BE5FF5a', swapEvent, }, +}) diff --git a/dexs/velodrome-v2/v2.ts b/dexs/velodrome-v2/v2.ts deleted file mode 100644 index 3fd736010c..0000000000 --- a/dexs/velodrome-v2/v2.ts +++ /dev/null @@ -1,7 +0,0 @@ - -import { getDexVolumeExports } from "../../helpers/dexVolumeLogs"; - -const FACTORY_ADDRESS = '0xF1046053aa5682b4F9a81b5481394DA16BE5FF5a'; - -const swapEvent = 'event Swap(address indexed sender, address indexed to, uint256 amount0In, uint256 amount1In, uint256 amount0Out, uint256 amount1Out)'; -export const fetchV2 = getDexVolumeExports({ swapEvent, factory: FACTORY_ADDRESS, chain: 'optimism', pairItemAbi: 'allPools', pairLengthAbi: 'allPoolsLength' }) \ No newline at end of file diff --git a/dexs/velodrome/index.ts b/dexs/velodrome/index.ts index 79619e8d73..5688ae7efc 100644 --- a/dexs/velodrome/index.ts +++ b/dexs/velodrome/index.ts @@ -1,41 +1,49 @@ -import { SimpleAdapter } from "../../adapters/types"; -import { DEFAULT_DAILY_VOLUME_FIELD, DEFAULT_TOTAL_VOLUME_FIELD, getChainVolume } from "../../helpers/getUniSubgraphVolume"; +import * as sdk from "@defillama/sdk"; +import { FetchOptions, SimpleAdapter } from "../../adapters/types"; +import { DEFAULT_TOTAL_VOLUME_FIELD, getChainVolume2 } from "../../helpers/getUniSubgraphVolume"; import { CHAIN } from "../../helpers/chains"; import { Chain } from "@defillama/sdk/build/general"; +import { fetchV2Volume } from "./v2" const endpoints = { - [CHAIN.OPTIMISM]: "https://api.thegraph.com/subgraphs/name/dmihal/velodrome", + [CHAIN.OPTIMISM]: sdk.graph.modifyEndpoint('2bam2XEb91cFqABFPSKj3RiSjpop9HvDt1MnYq5cDX5E'), }; -const graphs = getChainVolume({ +const graphs = getChainVolume2({ graphUrls: endpoints, totalVolume: { factory: "factories", field: DEFAULT_TOTAL_VOLUME_FIELD, }, - dailyVolume: { - factory: "dayData", - field: DEFAULT_DAILY_VOLUME_FIELD, - }, }); + + const fetch = (chain: Chain) => { - return async (timestamp: number) => { - const [v1] = await Promise.all([graphs(chain)(timestamp, {})]) + return async (options: FetchOptions) => { + const [v1] = await Promise.all([graphs(chain)(options)]) const dailyVolume = Number(v1.dailyVolume); return { dailyVolume: `${dailyVolume}`, - timestamp } } } const adapter: SimpleAdapter = { + version: 2, adapter: { [CHAIN.OPTIMISM]: { fetch: fetch(CHAIN.OPTIMISM), start: 1677110400 }, + [CHAIN.MODE]: { + fetch: fetchV2Volume, + start: 1715763701 + }, + [CHAIN.BOB]: { + fetch: fetchV2Volume, + start: 1715763701 + } }, }; diff --git a/dexs/velodrome/v2.ts b/dexs/velodrome/v2.ts new file mode 100644 index 0000000000..ec00cfc08f --- /dev/null +++ b/dexs/velodrome/v2.ts @@ -0,0 +1,126 @@ +import { FetchOptions, FetchResultV2 } from "../../adapters/types" +import { CHAIN } from "../../helpers/chains" + +const sugars = { + [CHAIN.MODE]: "0x207DfB36A449fd10d9c3bA7d75e76290a0c06731", + [CHAIN.BOB]: "0x3e71CCdf495d9628D3655A600Bcad3afF2ddea98" +} +const abis: any = { + "forSwaps": "function forSwaps(uint256 _limit, uint256 _offset) view returns ((address lp, int24 type, address token0, address token1, address factory, uint256 pool_fee)[])" +} + +interface IForSwap { + lp: string; + type: string; + token0: string; + token1: string; + pool_fee: string; +} + +interface ILog { + address: string; + data: string; + transactionHash: string; + topics: string[]; +} +const event_swap = 'event Swap(address indexed sender,address indexed to,uint256 amount0In,uint256 amount1In,uint256 amount0Out,uint256 amount1Out)' +const event_swap_slipstream = 'event Swap(address indexed sender, address indexed recipient, int256 amount0, int256 amount1, uint160 sqrtPriceX96, uint128 liquidity, int24 tick)' + +const fetchV2Volume = async ({ api, getLogs, createBalances, chain }: FetchOptions): Promise => { + const dailyVolume = createBalances() + const dailyFees = createBalances() + const chunkSize = 400; + let currentOffset = 0; + const allForSwaps: IForSwap[] = []; + let unfinished = true; + +while (unfinished) { + const forSwaps: IForSwap[] = (await api.call({ + target: sugars[chain], + params: [chunkSize, currentOffset], + abi: abis.forSwaps, + chain: chain, + })).filter(t => Number(t.type) >= -1).map((e: any) => { + return { + lp: e.lp, + type: e.type, + token0: e.token0, + token1: e.token1, + pool_fee: e.pool_fee, + } + }); + + unfinished = forSwaps.length !== 0; + currentOffset += chunkSize; + allForSwaps.push(...forSwaps); +} + +const targets = allForSwaps.map((forSwap: IForSwap) => forSwap.lp) + +let logs: ILog[][] = []; +const targetChunkSize = 5; +let currentTargetOffset = 0; +unfinished = true; + +while (unfinished) { + let endOffset = currentTargetOffset + targetChunkSize; + if (endOffset >= targets.length) { + unfinished = false; + endOffset = targets.length; + } + + let currentLogs: ILog[][] = await getLogs({ + targets: targets.slice(currentTargetOffset, endOffset), + eventAbi: event_swap, + flatten: false, + }) + + logs.push(...currentLogs); + currentTargetOffset += targetChunkSize; +} + +logs.forEach((logs: ILog[], idx: number) => { + const { token0, token1, pool_fee } = allForSwaps[idx] + logs.forEach((log: any) => { + dailyVolume.add(token0, BigInt(Math.abs(Number(log.amount0In)))) + dailyVolume.add(token1, BigInt(Math.abs(Number(log.amount1In)))) + dailyFees.add(token0, BigInt( Math.round((((Math.abs(Number(log.amount0In))) * Number(pool_fee)) / 10000)))) // 1% fee represented as pool_fee=100 + dailyFees.add(token1, BigInt( Math.round((((Math.abs(Number(log.amount1In))) * Number(pool_fee)) / 10000)))) + }) +}) + +let slipstreamLogs: ILog[][] = []; +currentTargetOffset = 0; +unfinished = true; + +while (unfinished) { + let endOffset = currentTargetOffset + targetChunkSize; + if (endOffset >= targets.length) { + unfinished = false; + endOffset = targets.length; + } + + let currentSlipstreamLogs: ILog[][] = await getLogs({ + targets: targets.slice(currentTargetOffset, endOffset), + eventAbi: event_swap_slipstream, + flatten: false, + }) + + slipstreamLogs.push(...currentSlipstreamLogs); + currentTargetOffset += targetChunkSize; +} + +slipstreamLogs.forEach((logs: ILog[], idx: number) => { + const { token1, pool_fee } = allForSwaps[idx] + logs.forEach((log: any) => { + dailyVolume.add(token1, BigInt(Math.abs(Number(log.amount1)))) + dailyFees.add(token1, BigInt( Math.round((((Math.abs(Number(log.amount1))) * Number(pool_fee)) / 1000000)))) // 1% fee represented as pool_fee=10000 for Slipstream + }) +}) + +return { dailyVolume, dailyFees, dailyRevenue: dailyFees, dailyHoldersRevenue: dailyFees } +} + +export { + fetchV2Volume +} diff --git a/dexs/veniceswap/index.ts b/dexs/veniceswap/index.ts index d4735e6cde..99f48c4b9f 100644 --- a/dexs/veniceswap/index.ts +++ b/dexs/veniceswap/index.ts @@ -13,6 +13,7 @@ const adapter = univ2Adapter(endpoints, { }); adapter.adapter.findora.start = 1675036800; +adapter.adapter.findora.fetch = async (timestamp: number) => {return{timestamp}} adapter.adapter[DISABLED_ADAPTER_KEY] = disabledAdapter; export default adapter diff --git a/dexs/verse/index.ts b/dexs/verse/index.ts index b293ad6bf0..04c88a3ff9 100644 --- a/dexs/verse/index.ts +++ b/dexs/verse/index.ts @@ -1,22 +1,19 @@ +import * as sdk from "@defillama/sdk"; import { CHAIN } from "../../helpers/chains"; import { ChainEndpoints, SimpleAdapter, BaseAdapter } from "../../adapters/types"; -import { getChainVolume } from "../../helpers/getUniSubgraphVolume"; +import { getChainVolume2 } from "../../helpers/getUniSubgraphVolume"; const endpoints: ChainEndpoints = { - [CHAIN.ETHEREUM]: "https://api.thegraph.com/subgraphs/name/arnkthr/ethv1", + [CHAIN.ETHEREUM]: sdk.graph.modifyEndpoint('CvSasxLYUvFbYyi7VXGhXL6PNgkZPoVDo2bo66ftEA2V'), [CHAIN.SMARTBCH]: "https://analytics-dex.api.bitcoin.com/subgraphs/name/verse/exchange", }; -const fetch = getChainVolume({ +const fetch = getChainVolume2({ graphUrls: endpoints, totalVolume: { factory: "factories", field: "volumeUSD", }, - dailyVolume: { - factory: "dayData", - field: "volumeUSD", - }, }); const volumeAdapter: BaseAdapter = { @@ -31,6 +28,7 @@ const volumeAdapter: BaseAdapter = { } const adapter: SimpleAdapter = { + version: 2, adapter: volumeAdapter, } diff --git a/dexs/vertex-protocol/index.ts b/dexs/vertex-protocol/index.ts index 87be6260f2..2291397853 100644 --- a/dexs/vertex-protocol/index.ts +++ b/dexs/vertex-protocol/index.ts @@ -1,4 +1,4 @@ -import { BreakdownAdapter } from "../../adapters/types"; +import { BreakdownAdapter, FetchOptions } from "../../adapters/types"; import { CHAIN } from "../../helpers/chains"; import { httpGet, httpPost } from "../../utils/fetchURL"; @@ -11,14 +11,41 @@ interface IProducts { const gatewayBaseUrl = "https://gateway.prod.vertexprotocol.com/v1"; const archiveBaseUrl = "https://archive.prod.vertexprotocol.com/v1"; -const fetchValidSymbols = async (): Promise => { - const symbols = (await httpGet(`${gatewayBaseUrl}/symbols`)); +const gatewayMatleBaseUrl = "https://gateway.mantle-prod.vertexprotocol.com/v1"; +const archiveMatleBaseUrl = "https://archive.mantle-prod.vertexprotocol.com/v1"; + +const gatewaySeiBaseUrl = "https://gateway.sei-prod.vertexprotocol.com/v1"; +const archiveSeiBaseUrl = "https://archive.sei-prod.vertexprotocol.com/v1"; + +type TURL = { + [s: string]: { + gateway: string; + archive: string; + } +} +const url: TURL = { + [CHAIN.ARBITRUM]: { + gateway: gatewayBaseUrl, + archive: archiveBaseUrl, + }, + [CHAIN.MANTLE]: { + gateway: gatewayMatleBaseUrl, + archive: archiveMatleBaseUrl, + }, + [CHAIN.SEI]: { + gateway: gatewaySeiBaseUrl, + archive: archiveSeiBaseUrl, + }, +} + +const fetchValidSymbols = async (fetchOptions: FetchOptions): Promise => { + const symbols = (await httpGet(`${url[fetchOptions.chain].gateway}/symbols`)); return symbols.map((product: { product_id: number }) => product.product_id); }; -const fetchProducts = async (): Promise => { - const validSymbols = await fetchValidSymbols(); - const allProducts = (await httpGet(`${gatewayBaseUrl}/query?type=all_products`)).data; +const fetchProducts = async (fetchOptions: FetchOptions): Promise => { + const validSymbols = await fetchValidSymbols(fetchOptions); + const allProducts = (await httpGet(`${url[fetchOptions.chain].gateway}/query?type=all_products`)).data; return { spot_products: allProducts.spot_products .map((product: { product_id: number }) => product.product_id) @@ -32,9 +59,9 @@ const fetchProducts = async (): Promise => { }; }; -const computeVolume = async (timestamp: number, productIds: number[]) => { +const computeVolume = async (timestamp: number, productIds: number[], fetchOptions: FetchOptions) => { const snapshots = ( - await httpPost(archiveBaseUrl, { + await httpPost(url[fetchOptions.chain].archive, { market_snapshots: { interval: { count: 2, @@ -69,21 +96,23 @@ const computeVolume = async (timestamp: number, productIds: number[]) => { }; }; -const fetchSpots = async (timeStamp: number) => { - const spotProductIds = (await fetchProducts()).spot_products; - return await computeVolume(timeStamp, spotProductIds); +const fetchSpots = async (timeStamp: number, _: any, fetchOptions: FetchOptions) => { + const spotProductIds = (await fetchProducts(fetchOptions)).spot_products; + return await computeVolume(timeStamp, spotProductIds, fetchOptions); }; -const fetchPerps = async (timeStamp: number) => { - const perpProductIds = (await fetchProducts()).perp_products; - const marginedProductIds = (await fetchProducts()).margined_products; +const fetchPerps = async (timeStamp: number, _: any, fetchOptions: FetchOptions) => { + const perpProductIds = (await fetchProducts(fetchOptions)).perp_products; + const marginedProductIds = (await fetchProducts(fetchOptions)).margined_products; return await computeVolume( timeStamp, - perpProductIds.concat(marginedProductIds) + perpProductIds.concat(marginedProductIds), + fetchOptions ); }; const startTime = 1682514000; +const seiStartTime = 1723547681 const adapter: BreakdownAdapter = { breakdown: { @@ -92,12 +121,28 @@ const adapter: BreakdownAdapter = { fetch: fetchSpots, start: startTime, }, + [CHAIN.MANTLE]: { + fetch: fetchSpots, + start: startTime, + }, + [CHAIN.SEI]: { + fetch: fetchSpots, + start: seiStartTime, + } }, derivatives: { [CHAIN.ARBITRUM]: { fetch: fetchPerps, - start: startTime, + start: 1718841600, + }, + [CHAIN.MANTLE]: { + fetch: fetchPerps, + start: 1718841600, }, + [CHAIN.SEI]: { + fetch: fetchPerps, + start: seiStartTime, + } }, }, }; diff --git a/dexs/viperswap/index.ts b/dexs/viperswap/index.ts index 3196836015..0c4e34b1c7 100644 --- a/dexs/viperswap/index.ts +++ b/dexs/viperswap/index.ts @@ -3,7 +3,7 @@ import { DISABLED_ADAPTER_KEY, SimpleAdapter } from "../../adapters/types"; import { CHAIN } from "../../helpers/chains"; import disabledAdapter from "../../helpers/disabledAdapter"; import { getStartTimestamp } from "../../helpers/getStartTimestamp"; -import { DEFAULT_DAILY_VOLUME_FIELD, DEFAULT_TOTAL_VOLUME_FIELD, getChainVolume, univ2Adapter } from "../../helpers/getUniSubgraphVolume"; +import { DEFAULT_TOTAL_VOLUME_FIELD, getChainVolume2 } from "../../helpers/getUniSubgraphVolume"; const blocksGraph = "https://graph.viper.exchange/subgraphs/name/harmony/blocks"; const blockQuery = gql` @@ -42,20 +42,17 @@ const endpoints = { const DAILY_VOLUME_FACTORY = "uniswapDayData"; -const graphs = getChainVolume({ +const graphs = getChainVolume2({ graphUrls: endpoints, totalVolume: { factory: "uniswapFactories", field: DEFAULT_TOTAL_VOLUME_FIELD, }, - dailyVolume: { - factory: DAILY_VOLUME_FACTORY, - field: DEFAULT_DAILY_VOLUME_FIELD, - }, getCustomBlock, }); const adapter: SimpleAdapter = { + version: 2, adapter: { [DISABLED_ADAPTER_KEY]: disabledAdapter, [CHAIN.HARMONY]: { diff --git a/dexs/voltage-v3/index.ts b/dexs/voltage-v3/index.ts new file mode 100644 index 0000000000..9b4217b383 --- /dev/null +++ b/dexs/voltage-v3/index.ts @@ -0,0 +1,33 @@ +import { SimpleAdapter } from "../../adapters/types"; +import {CHAIN} from "../../helpers/chains"; +import { getGraphDimensions2 } from "../../helpers/getUniSubgraph"; + +const endpoint = { + [CHAIN.FUSE]: "https://api.studio.thegraph.com/query/78455/exchange-v3/version/latest", +}; + +const v3Graph = getGraphDimensions2({ + graphUrls: endpoint, + totalVolume: { + factory: "factories" + }, + totalFees: { + factory: "factories" + }, +}) + +const v3StartTimes = { + [CHAIN.FUSE]: 1703725380, +} + +const adapter: SimpleAdapter = { + version: 2, + adapter: { + [CHAIN.FUSE]: { + fetch: v3Graph(CHAIN.FUSE), + start: v3StartTimes[CHAIN.FUSE] + } + } +} + +export default adapter diff --git a/dexs/voltage/index.ts b/dexs/voltage/index.ts index 5703d33ba4..d3e6ed9a5a 100644 --- a/dexs/voltage/index.ts +++ b/dexs/voltage/index.ts @@ -1,8 +1,9 @@ +import * as sdk from "@defillama/sdk"; import { CHAIN } from "../../helpers/chains"; import { univ2Adapter } from "../../helpers/getUniSubgraphVolume"; const adapters = univ2Adapter({ - [CHAIN.FUSE]: "https://api.thegraph.com/subgraphs/name/voltfinance/voltage-exchange" + [CHAIN.FUSE]: sdk.graph.modifyEndpoint('4buFyoUT8Lay3T1DK9ctdMdcpkZMdi5EpCBWZCBTKvQd') }, { }); diff --git a/dexs/voltswap/index.ts b/dexs/voltswap/index.ts index 6fbb381413..07221d993d 100644 --- a/dexs/voltswap/index.ts +++ b/dexs/voltswap/index.ts @@ -1,11 +1,8 @@ import { BreakdownAdapter, DISABLED_ADAPTER_KEY } from "../../adapters/types"; import { CHAIN } from "../../helpers/chains"; import disabledAdapter from "../../helpers/disabledAdapter"; -const { - getChainVolume, - DEFAULT_TOTAL_VOLUME_FIELD, - DEFAULT_DAILY_VOLUME_FIELD, -} = require("../../helpers/getUniSubgraphVolume"); +import { getChainVolume2 } from "../../helpers/getUniSubgraphVolume"; +const { DEFAULT_TOTAL_VOLUME_FIELD } = require("../../helpers/getUniSubgraphVolume"); const { getStartTimestamp } = require("../../helpers/getStartTimestamp"); const endpoints = { [CHAIN.METER]: "https://graph-meter.voltswap.finance/subgraphs/name/meterio/voltswapv2-subgraph", @@ -13,19 +10,16 @@ const endpoints = { const DAILY_VOLUME_FACTORY = "uniswapDayData"; -const graphs = getChainVolume({ +const graphs = getChainVolume2({ graphUrls: endpoints, totalVolume: { factory: "uniswapFactories", field: DEFAULT_TOTAL_VOLUME_FIELD, }, - dailyVolume: { - factory: DAILY_VOLUME_FACTORY, - field: DEFAULT_DAILY_VOLUME_FIELD, - }, }); const adapter: BreakdownAdapter = { + version: 2, breakdown: { v1: { [DISABLED_ADAPTER_KEY]: disabledAdapter, diff --git a/dexs/voodoo-trade/index.ts b/dexs/voodoo-trade/index.ts index d74147fdb1..58b9a851a6 100644 --- a/dexs/voodoo-trade/index.ts +++ b/dexs/voodoo-trade/index.ts @@ -1,3 +1,4 @@ +import * as sdk from "@defillama/sdk"; /// Project URL: https://voodoo.trade /// Contact: chickenjuju@proton.me /// @@ -14,7 +15,7 @@ import { BreakdownAdapter, Fetch } from "../../adapters/types"; import { CHAIN } from "../../helpers/chains"; import { getUniqStartOfTodayTimestamp } from "../../helpers/getUniSubgraphVolume"; -const endpoint = "https://api.thegraph.com/subgraphs/name/chicken-juju/voodoo-base-stats" +const endpoint = sdk.graph.modifyEndpoint('6eeKiwCJQECCwhE7doeoKCAqSK7VatCsv3piHomYzi6o') const historicalDataSwap = gql` query get_volume($period: String!, $id: String!) { diff --git a/dexs/vvs-finance/index.ts b/dexs/vvs-finance/index.ts index 1375d9b330..ef77266859 100644 --- a/dexs/vvs-finance/index.ts +++ b/dexs/vvs-finance/index.ts @@ -1,10 +1,9 @@ -import { univ2Adapter } from "../../helpers/getUniSubgraphVolume"; +import { univ2Adapter2 } from "../../helpers/getUniSubgraphVolume"; -const adapter = univ2Adapter({ +const adapter = univ2Adapter2({ "cronos": "https://graph.cronoslabs.com/subgraphs/name/vvs/exchange" },{ factoriesName: "vvsFactories", - dayData: "vvsDayData", }); adapter.adapter.cronos.start = 1632035122; // 1 a year ago diff --git a/dexs/wagmi/index.ts b/dexs/wagmi/index.ts index 56881a4f23..c86f5f2028 100644 --- a/dexs/wagmi/index.ts +++ b/dexs/wagmi/index.ts @@ -3,25 +3,26 @@ import { CHAIN } from "../../helpers/chains"; import { fetchVolume } from "./wagmi"; const adapter: SimpleAdapter = { + version:2, adapter: { - [CHAIN.ERA]: { - fetch: fetchVolume(CHAIN.ERA), - start: 1681257600, - }, + // [CHAIN.ERA]: { + // fetch: fetchVolume(CHAIN.ERA), error: "Wagmi does not exist on Era", + // start: 1681257600, + // }, [CHAIN.FANTOM]: { - fetch: fetchVolume(CHAIN.FANTOM), + fetch: fetchVolume, start: 1681257600, }, [CHAIN.ETHEREUM]: { - fetch: fetchVolume(CHAIN.ETHEREUM), + fetch: fetchVolume, start: 18240112, }, - [CHAIN.METIS]: { - fetch: fetchVolume(CHAIN.METIS), - start: 1702888970, - }, + // [CHAIN.METIS]: { + // fetch: fetchVolume(CHAIN.METIS), + // start: 1702888970, + // }, [CHAIN.KAVA]: { - fetch: fetchVolume(CHAIN.KAVA), + fetch: fetchVolume, start: 1694476800, }, }, diff --git a/dexs/wagmi/wagmi.ts b/dexs/wagmi/wagmi.ts index 25047cdfc1..9ee346f7cf 100644 --- a/dexs/wagmi/wagmi.ts +++ b/dexs/wagmi/wagmi.ts @@ -1,9 +1,11 @@ +import * as sdk from "@defillama/sdk"; // Wagmi data import { CHAIN } from "../../helpers/chains"; const { request, gql } = require("graphql-request"); import { getTimestampAtStartOfDayUTC } from "../../utils/date"; import { getBlock } from "../../helpers/getBlock"; import { Chain } from "@defillama/sdk/build/general"; +import { FetchOptions } from "../../adapters/types"; export const LINKS: { [key: string]: any } = { [CHAIN.ERA]: { @@ -14,9 +16,9 @@ export const LINKS: { [key: string]: any } = { }, [CHAIN.FANTOM]: { subgraph: - "https://api.thegraph.com/subgraphs/name/0xfantaholic/wagmi-fantom", + sdk.graph.modifyEndpoint('BtyzJrSwED7QFDBhC68myEJ851KJ47vRD11vkenPwgQz'), blocks: - "https://api.thegraph.com/subgraphs/name/beethovenxfi/fantom-blocks", + sdk.graph.modifyEndpoint('BjhETUnXsKV77w7P6GWNxWik762YDmV54nkMRG4ekk2W'), }, [CHAIN.KAVA]: { subgraph: "https://kava.graph.wagmi.com/subgraphs/name/v3", @@ -25,7 +27,7 @@ export const LINKS: { [key: string]: any } = { [CHAIN.ETHEREUM]: { subgraph: "https://api.studio.thegraph.com/query/53494/v3/version/latest", blocks: - "https://api.thegraph.com/subgraphs/name/blocklytics/ethereum-blocks", + sdk.graph.modifyEndpoint('9A6bkprqEG2XsZUYJ5B2XXp6ymz9fNcn4tVPxMWDztYC'), }, [CHAIN.METIS]: { subgraph: "https://metis.graph.wagmi.com/subgraphs/name/v3", @@ -67,8 +69,8 @@ const getData = async (chain: Chain, timestamp: number) => { const totalVolume = Number(data.factories[0].totalVolumeUSD); const totalFee = Number(data.factories[0].totalFeesUSD); - const dailyVolume = Number(data.uniswapDayData.volumeUSD); - const dailyFees = Number(data.uniswapDayData.feesUSD); + const dailyVolume = Number(data.uniswapDayData?.volumeUSD ?? '0'); + const dailyFees = Number(data.uniswapDayData?.feesUSD ?? '0'); return { dailyFees: `${dailyFees}`, @@ -81,16 +83,13 @@ const getData = async (chain: Chain, timestamp: number) => { }; }; -export const fetchVolume = (chain: string) => { - return async (timestamp: number) => { - const data = await getData(chain, timestamp); - +export const fetchVolume = async (options: FetchOptions) => { + const data = await getData(options.chain, options.startOfDay); return { totalVolume: data.totalVolume, dailyVolume: data.dailyVolume, timestamp: data.timestamp, }; - }; }; export const fetchFee = (chain: string) => { diff --git a/dexs/wannaswap/index.ts b/dexs/wannaswap/index.ts index bb9d560516..5779ae7caf 100644 --- a/dexs/wannaswap/index.ts +++ b/dexs/wannaswap/index.ts @@ -1,34 +1,6 @@ -import { SimpleAdapter } from "../../adapters/types" -import { CHAIN } from "../../helpers/chains" -import { getDexVolumeExports } from "../../helpers/dexVolumeLogs"; +import { CHAIN } from "../../helpers/chains"; +import { uniV2Exports } from "../../helpers/uniswap"; - -const pools: string[] = [ -'0xf56997948d4235514dcc50fc0ea7c0e110ec255d', -'0xbf9eef63139b67fd0abf22bd5504acb0519a4212', -'0x3502eac6fa27beebdc5cd3615b7cb0784b0ce48f', -'0x256d03607eee0156b8a2ab84da1d5b283219fe97', -'0xbf58062d23f869a90c6eb04b9655f0dfca345947', -'0xca461686c711aeaadf0b516f9c2ad9d9b645a940', -'0xbf560771b6002a58477efbcdd6774a5a1947587b', -'0x957b4bc289d29129680b2d6c6d06c9106a38bb82', -'0xddccf2f096fa400ce90ba0568908233e6a950961', -'0x2a6e6d58547d2580b490445cca0ce625c4f5d84a', -'0x523fae29d7ff6fd38842c8f271edf2ebd3150435', -'0xe22606659ec950e0328aa96c7f616adc4907cbe3', -'0x2e02bea8e9118f7d2ccada1d402286cc6d54bd67', -'0x7e9ea10e5984a09d19d05f31ca3cb65bb7df359d', -'0x10c0c000b9ef01ba07d7473729a19e85e89b6246', -'0xe6c47b036f6fd0684b109b484ac46094e633af2e' -].map((address: string) => address.toLowerCase()); - -const adapters: SimpleAdapter = { - adapter: { - [CHAIN.AURORA]: { - fetch: getDexVolumeExports({ chain: CHAIN.AURORA, pools }), - start: 1678838400, - } - } -} - -export default adapters +export default uniV2Exports({ + [CHAIN.AURORA]: { factory: '0x7928D4FeA7b2c90C732c10aFF59cf403f0C38246', }, +}) diff --git a/dexs/wardenswap/index.ts b/dexs/wardenswap/index.ts index e547013e41..4a85c063d4 100644 --- a/dexs/wardenswap/index.ts +++ b/dexs/wardenswap/index.ts @@ -1,35 +1,30 @@ +import * as sdk from "@defillama/sdk"; import { Chain } from "@defillama/sdk/build/general"; import { SimpleAdapter } from "../../adapters/types"; import { CHAIN } from "../../helpers/chains"; +import { getChainVolume2 } from "../../helpers/getUniSubgraphVolume"; -const { - getChainVolume, -} = require("../../helpers/getUniSubgraphVolume"); const endpoints = { - [CHAIN.BSC]: "https://api.thegraph.com/subgraphs/name/wardenluna/wardenswap", - [CHAIN.OPTIMISM]: "https://api.thegraph.com/subgraphs/name/wardenluna/wardenswap-optimism", - [CHAIN.ARBITRUM]: "https://api.thegraph.com/subgraphs/name/wardenluna/wardenswap-arbitrum", - [CHAIN.ETHEREUM]: "https://api.thegraph.com/subgraphs/name/wardenluna/wardenswap-ethereum", - [CHAIN.POLYGON]: "https://api.thegraph.com/subgraphs/name/wardenluna/wardenswap-polygon", + [CHAIN.BSC]: sdk.graph.modifyEndpoint('DFn2ZaLXK4tJkXZ6AhfLF22pNobtTC88f3Ff3bC8by3r'), + [CHAIN.OPTIMISM]: sdk.graph.modifyEndpoint('BEKfdhcWBQQuZP5vz8jDZ8ZKRRqAeNYEGfuzdDPzzwnQ'), + [CHAIN.ARBITRUM]: sdk.graph.modifyEndpoint('B3L4WgKQ6kc6XyMiZqxQivb7VAQxAntUZcDjUuMHsWuF'), + [CHAIN.ETHEREUM]: sdk.graph.modifyEndpoint('AC7En34fgba7xJaoziBZtQLc5HgYD53K6YLzKnZy2cai'), + [CHAIN.POLYGON]: sdk.graph.modifyEndpoint('9NEeTNdvHDVvLxtzqSGVTiyZ2WqaKWfsv1cDksQbC917'), }; const VOLUME_FIELD = "volumeUSD"; -const graphs = getChainVolume({ +const graphs = getChainVolume2({ graphUrls: endpoints, totalVolume: { factory: "wardenSwaps", field: VOLUME_FIELD, }, - dailyVolume: { - factory: "dayData", - field: "volumeUSD", - dateField: "date" - } }); const adapter: SimpleAdapter = { + version: 2, adapter: Object.keys(endpoints).reduce((acc, chain: any) => { return { ...acc, diff --git a/dexs/warpgate/index.ts b/dexs/warpgate/index.ts new file mode 100644 index 0000000000..10ff2ef96f --- /dev/null +++ b/dexs/warpgate/index.ts @@ -0,0 +1,27 @@ +import { SimpleAdapter } from "../../adapters/types"; +import { getChainVolume2 } from "../../helpers/getUniSubgraphVolume"; +import { CHAIN } from "../../helpers/chains"; + +const endpoints = { + [CHAIN.IMX]: "https://subgraph.warpgate.pro/subgraphs/name/warpgate/subgraph-v3", +}; + +const graphs = getChainVolume2({ + graphUrls: endpoints, + totalVolume: { + factory: "factories", + field: "totalVolumeUSD", + }, +}); + +const adapter: SimpleAdapter = { + version: 2, + adapter: { + [CHAIN.IMX]: { + fetch: graphs(CHAIN.IMX), + start: 1708041600 + }, + }, +}; + +export default adapter; diff --git a/dexs/wavelength-dao/index.ts b/dexs/wavelength-dao/index.ts index 48c426ec91..554929975b 100644 --- a/dexs/wavelength-dao/index.ts +++ b/dexs/wavelength-dao/index.ts @@ -1,54 +1,21 @@ -const { request, gql } = require("graphql-request"); import { SimpleAdapter } from "../../adapters/types"; import { CHAIN } from "../../helpers/chains"; import customBackfill, { IGraphs } from "../../helpers/customBackfill"; -import { getChainVolume } from "../../helpers/getUniSubgraphVolume"; - -const blocksGraph = "https://teste.testeborabora.cyou/graphql"; -const ONE_DAY_IN_SECONDS = 60 * 60 * 24 -const blockQuery = gql` - query blocks($timestampFrom: Int!, $timestampTo: Int!) { - blocks( - first: 1 - orderBy: timestamp - orderDirection: asc - where: { timestamp_gt: $timestampFrom, timestamp_lt: $timestampTo } - ) { - id - number - timestamp - __typename - } - } -`; - - -const getCustomBlock = async (timestamp: number) => { - const block = - ( - await request(blocksGraph, blockQuery, { - timestampFrom: timestamp - ONE_DAY_IN_SECONDS, - timestampTo: timestamp + ONE_DAY_IN_SECONDS, - }) - ).blocks[0].number - ; - return Number(block); -}; +import { getChainVolume2 } from "../../helpers/getUniSubgraphVolume"; const endpoints = { [CHAIN.VELAS]: "https://testeborabora.cyou/subgraphs/name/wavelength22" } -const graphs = getChainVolume({ +const graphs = getChainVolume2({ graphUrls: endpoints, totalVolume: { factory: "balancers", field: "totalSwapVolume", }, - hasDailyVolume: false, - // getCustomBlock, }); const adapter: SimpleAdapter = { + version: 2, adapter: { [CHAIN.VELAS]: { fetch: graphs(CHAIN.VELAS), diff --git a/dexs/web3world/index.ts b/dexs/web3world/index.ts new file mode 100644 index 0000000000..9476f69893 --- /dev/null +++ b/dexs/web3world/index.ts @@ -0,0 +1,69 @@ +import BigNumber from "bignumber.js"; +import { FetchOptions, FetchV2, SimpleAdapter } from "../../adapters/types"; +import { postURL } from "../../utils/fetchURL"; + +interface IWeb3WorldPoolsStats { + pools: Array<{ + meta: { + currencies: string[]; + currencyAddresses: string[]; + poolAddress: string; + lpAddress: string; + pairType: string; + fee: string; + feeBeneficiary: string | null; + beneficiaryAddress: string | null; + }; + tvl: string; + tvlChange: string; + volumesLocked: string[]; + prices: string[]; + lpLocked: string; + count24Transactions: number; + volume24h: string; + volume24hChange: string; + volume7d: string; + fee24h: string; + fee7d: string; + feeAllTime: string; + stableOneSwap: string[] | null; + }>; +} + +const fetch: FetchV2 = async (options: FetchOptions) => { + const response: IWeb3WorldPoolsStats = await postURL( + "https://api.web3.world/v2/pools", + { + limit: 1000, + offset: 0, + ordering: "tvldescending", + whiteListUri: "https://static.web3.world/assets/manifest.json", + } + ); + let dailyVolumeBN = new BigNumber(0); + let dailyFeesBN = new BigNumber(0); + let totalFeesBN = new BigNumber(0); + response.pools.forEach((pool) => { + dailyVolumeBN = dailyVolumeBN.plus(pool.volume24h); + dailyFeesBN = dailyFeesBN.plus(pool.fee24h); + totalFeesBN = totalFeesBN.plus(pool.feeAllTime); + }); + return { + dailyVolume: dailyVolumeBN.toString(10), + dailyFees: dailyFeesBN.toString(10), + dailyUserFees: dailyFeesBN.toString(10), + totalFees: totalFeesBN.toString(10), + }; +}; +const adapter: SimpleAdapter = { + adapter: { + venom: { + fetch, + runAtCurrTime: true, + start: 1713139200, // 2024-04-15T00:00:00.000Z + }, + }, + version: 1, +}; + +export default adapter; diff --git a/dexs/wefi/index.ts b/dexs/wefi/index.ts new file mode 100644 index 0000000000..8315456cc4 --- /dev/null +++ b/dexs/wefi/index.ts @@ -0,0 +1,46 @@ +import { FetchOptions, FetchV2, SimpleAdapter } from "../../adapters/types"; +import { CHAIN } from "../../helpers/chains"; +import { addOneToken } from "../../helpers/prices"; + +const address: any = { + [CHAIN.LINEA]: '0x7e0da0deccac2e7b9ad06e378ee09c15b5bdeefa', + [CHAIN.XDC]: '0x7e0da0deccac2e7b9ad06e378ee09c15b5bdeefa', + [CHAIN.POLYGON]: '0xA42e5d2A738F83a1e1a907eB3aE031e5A768C085', + [CHAIN.BOBA]: '0x7E0DA0DECCAc2E7B9AD06E378ee09c15B5BDeefa' +} + +const fetchVolume: FetchV2 = async (options: FetchOptions) => { + const logs = await options.getLogs({ + target: address[options.chain], + eventAbi: 'event Swap(uint8 dex, address sender, address recipient, address tokenIn, address tokenOut, uint256 amountIn, uint256 amountOut)', + }) + const dailyVolume = options.createBalances(); + logs.forEach((log: any) => { + addOneToken({ chain: options.chain, balances: dailyVolume, token0: log.tokenIn, token1: log.tokenOut, amount0: log.amountIn, amount1: log.amountOut }) + }); + return { + dailyVolume: dailyVolume, + } +} +const adapter: SimpleAdapter = { + version: 2, + adapter: { + [CHAIN.LINEA]: { + fetch: fetchVolume, + start: 1704067200, + }, + [CHAIN.XDC]: { + fetch: fetchVolume, + start: 1704067200, + }, + [CHAIN.POLYGON]: { + fetch: fetchVolume, + start: 1704067200, + }, + [CHAIN.BOBA]: { + fetch: fetchVolume, + start: 1704067200, + }, + } +} +export default adapter; diff --git a/dexs/whaleswap/index.ts b/dexs/whaleswap/index.ts index a087b00bf4..4bac47a4cb 100644 --- a/dexs/whaleswap/index.ts +++ b/dexs/whaleswap/index.ts @@ -1,20 +1,17 @@ +import * as sdk from "@defillama/sdk"; import { SimpleAdapter } from "../../adapters/types"; +import { DEFAULT_TOTAL_VOLUME_FIELD, getChainVolume2 } from "../../helpers/getUniSubgraphVolume"; -const { - getChainVolume, - DEFAULT_TOTAL_VOLUME_FIELD, - DEFAULT_DAILY_VOLUME_FIELD, -} = require("../../helpers/getUniSubgraphVolume"); const { BSC, FANTOM } = require("../../helpers/chains"); const { getStartTimestamp } = require("../../helpers/getStartTimestamp"); const endpoints = { - [BSC]: "https://api.thegraph.com/subgraphs/name/whale-swap/exchange-bsc", - [FANTOM]: "https://api.thegraph.com/subgraphs/name/whale-swap/exchange-ftm", + [BSC]: sdk.graph.modifyEndpoint('6GFVtwE9cc6Rs5N4zh3WE4HxppKkaHyuetwPLutjRqZw'), + [FANTOM]: sdk.graph.modifyEndpoint('GVz2cRMu62ePnd3dXq42SDdTMds7koaJ1w4X5cxfdrco'), }; const DAILY_VOLUME_FACTORY = "dayData"; -const graphs = getChainVolume({ +const graphs = getChainVolume2({ graphUrls: { [BSC]: endpoints[BSC], [FANTOM]: endpoints[FANTOM], @@ -23,13 +20,10 @@ const graphs = getChainVolume({ factory: "whaleswapFactories", field: DEFAULT_TOTAL_VOLUME_FIELD, }, - dailyVolume: { - factory: DAILY_VOLUME_FACTORY, - field: DEFAULT_DAILY_VOLUME_FIELD, - }, }); const adapter: SimpleAdapter = { + version: 2, adapter: { [BSC]: { fetch: graphs(BSC), diff --git a/dexs/wigoswap/index.ts b/dexs/wigoswap/index.ts index 9ae91ed5fa..edbf847adc 100644 --- a/dexs/wigoswap/index.ts +++ b/dexs/wigoswap/index.ts @@ -1,13 +1,6 @@ import { CHAIN } from "../../helpers/chains"; -import { univ2Adapter } from "../../helpers/getUniSubgraphVolume"; +import { uniV2Exports } from "../../helpers/uniswap"; -const adapters = univ2Adapter({ - [CHAIN.FANTOM]: "https://api.thegraph.com/subgraphs/name/wigoswap/exchange2" -}, { - factoriesName: "wigoswapFactories", - dayData: "wigoDayData", - gasToken: "coingecko:fantom" -}); - -adapters.adapter.fantom.start = 1642982400; -export default adapters; +export default uniV2Exports({ + [CHAIN.FANTOM]: { factory: '0xc831a5cbfb4ac2da5ed5b194385dfd9bf5bfcba7', }, +}) diff --git a/dexs/wingriders/index.ts b/dexs/wingriders/index.ts index 13cce6283d..ca2b95d9e8 100644 --- a/dexs/wingriders/index.ts +++ b/dexs/wingriders/index.ts @@ -1,14 +1,28 @@ import { Adapter, ChainBlocks, FetchOptions } from "../../adapters/types" import { CHAIN } from "../../helpers/chains"; -import { httpPost } from "../../utils/fetchURL"; +import request, { gql } from "graphql-request"; -const volUrl = 'https://aggregator.mainnet.wingriders.com/volumeInAda'; +const url = 'https://api.mainnet.wingriders.com/graphql'; + +const query = gql` +query Volume($input: VolumeInput!) { + volume(input: $input) +} +` + +interface IResponse { + volume: number +} async function fetchVolume(timestamp: number , _: ChainBlocks, { createBalances }: FetchOptions) { const dailyVolume = createBalances() - const last24hVolInAda = await httpPost(volUrl, { "lastNHours": 24 }); - // const totalVolumeInAda = await httpPost(volUrl, {}); - dailyVolume.addGasToken(last24hVolInAda * 1e6); + const response: IResponse = await request(url, query, { + input: { + lastNHours: 24, + baseCurrency: "ADA" + } + }); + dailyVolume.addGasToken(response.volume * 1e6); return { dailyVolume, timestamp diff --git a/dexs/wingswap/index.ts b/dexs/wingswap/index.ts index 2311d6b911..cfc7ee0ce5 100644 --- a/dexs/wingswap/index.ts +++ b/dexs/wingswap/index.ts @@ -1,8 +1,9 @@ +import * as sdk from "@defillama/sdk"; import { univ2Adapter } from "../../helpers/getUniSubgraphVolume"; import { CHAIN } from "../../helpers/chains"; const endpoints = { - [CHAIN.FANTOM]: "https://api.thegraph.com/subgraphs/name/wingswap/wingswap-exchange", + [CHAIN.FANTOM]: sdk.graph.modifyEndpoint('FQXGq9b1cWfrZVU4VVZyyRAgaLRQjUULE6YS26rkB1WM'), }; const adapter = univ2Adapter(endpoints, { diff --git a/dexs/wojak-finance/index.ts b/dexs/wojak-finance/index.ts index b556b6a315..4d258d9037 100644 --- a/dexs/wojak-finance/index.ts +++ b/dexs/wojak-finance/index.ts @@ -61,10 +61,11 @@ const graphs = getChainVolume({ }); const adapter: SimpleAdapter = { + version: 1, adapter: { [DISABLED_ADAPTER_KEY]: disabledAdapter, [CHAIN.DOGECHAIN]: { - fetch: graphs(CHAIN.DOGECHAIN), + fetch: async (timestamp: number) => {return {timestamp} }, start: 1661731200, }, }, diff --git a/dexs/wombat-exchange/index.ts b/dexs/wombat-exchange/index.ts index 19c772fb80..b430961fd7 100644 --- a/dexs/wombat-exchange/index.ts +++ b/dexs/wombat-exchange/index.ts @@ -1,4 +1,5 @@ -import { FetchResultVolume, SimpleAdapter } from "../../adapters/types"; +import * as sdk from "@defillama/sdk"; +import {FetchOptions, FetchResultV2, SimpleAdapter} from "../../adapters/types"; import { CHAIN } from "../../helpers/chains"; import { gql, request } from "graphql-request"; import { getUniqStartOfTodayTimestamp } from "../../helpers/getUniSubgraphVolume"; @@ -25,25 +26,26 @@ type TEndpoint = { // Updated using studio const endpoints: TEndpoint = { [CHAIN.BSC]: - "https://api.thegraph.com/subgraphs/name/wombat-exchange/wombat-exchange-bsc", + sdk.graph.modifyEndpoint('DPuFUNkRpW5AG2HBWyRhzvYCodocb1H8vjVLijyEJyGE'), [CHAIN.ARBITRUM]: - "https://api.thegraph.com/subgraphs/name/wombat-exchange/wombat-exchange-arbone", + sdk.graph.modifyEndpoint('HADLg9LFYHJupr3xvWdmp7piPpwjGEwjbCknkSVrfyDQ'), [CHAIN.ETHEREUM]: - "https://api.thegraph.com/subgraphs/name/wombat-exchange/wombat-exchange-eth", + sdk.graph.modifyEndpoint('3S2iHctknomx91fcAcyqrPvCcGfnuhKdEKBs2xThoCvJ'), [CHAIN.SCROLL]: "https://api.studio.thegraph.com/query/56564/wombat-exchange-scroll/version/latest", [CHAIN.AVAX]: - "https://api.thegraph.com/subgraphs/name/wombat-exchange/wombat-exchange-avax", + sdk.graph.modifyEndpoint('6PbnpSVfrWgVeRiTbbM4yFNAiYacLjGLg1ztzasxqxGf'), [CHAIN.BASE]: "https://api.studio.thegraph.com/query/56564/wombat-exchange-base/version/latest", [CHAIN.OPTIMISM]: - "https://api.thegraph.com/subgraphs/name/wombat-exchange/wombat-exchange-op", + sdk.graph.modifyEndpoint('4phYPx7RdkSSKFuoFBRZFFbPMkRCnYLfi8bENyQf4NA6'), }; const fetchVolume = (chain: Chain) => { - return async (timestamp: number): Promise => { + return async (options: FetchOptions): Promise => { + const { startTimestamp} = options; const dayTimestamp = getUniqStartOfTodayTimestamp( - new Date(timestamp * 1000) + new Date(startTimestamp * 1000) ); const todaysBlock = await getBlock(dayTimestamp, chain, {}); const dayID = dayTimestamp / 86400; @@ -71,6 +73,7 @@ const fetchVolume = (chain: Chain) => { }; const adapter: SimpleAdapter = { + version: 2, adapter: { [CHAIN.BSC]: { fetch: fetchVolume(CHAIN.BSC), diff --git a/dexs/woofi/index.ts b/dexs/woofi/index.ts index ed2071f30a..120f568159 100644 --- a/dexs/woofi/index.ts +++ b/dexs/woofi/index.ts @@ -1,21 +1,23 @@ +import * as sdk from "@defillama/sdk"; import { Chain } from "@defillama/sdk/build/general"; -import { ChainBlocks, SimpleAdapter } from "../../adapters/types"; +import { FetchOptions, SimpleAdapter } from "../../adapters/types"; import { CHAIN } from "../../helpers/chains"; +import { getChainVolume } from "../../helpers/getUniSubgraphVolume"; +import request, { gql } from "graphql-request"; -const { getChainVolume } = require("../../helpers/getUniSubgraphVolume"); const endpoints = { - [CHAIN.AVAX]: "https://api.thegraph.com/subgraphs/name/woonetwork/woofi-avax", - [CHAIN.BSC]: "https://api.thegraph.com/subgraphs/name/woonetwork/woofi-bsc", - [CHAIN.FANTOM]: "https://api.thegraph.com/subgraphs/name/woonetwork/woofi-fantom", - [CHAIN.POLYGON]: "https://api.thegraph.com/subgraphs/name/woonetwork/woofi-polygon", - [CHAIN.ARBITRUM]: "https://api.thegraph.com/subgraphs/name/woonetwork/woofi-arbitrum", - [CHAIN.OPTIMISM]: "https://api.thegraph.com/subgraphs/name/woonetwork/woofi-optimism", + [CHAIN.AVAX]: sdk.graph.modifyEndpoint('BL45YVVLVkCRGaAtyTjvuRt1yHnUt4QbZg8bWcZtLvLm'), + [CHAIN.BSC]: sdk.graph.modifyEndpoint('CxWDreK8yXVX9qxLTNoyTrcNT2uojrPiseC7mBqRENem'), + [CHAIN.FANTOM]: sdk.graph.modifyEndpoint('B1TxafnDavup8z9rwi5TKDwZxCBR24tw8sFeyLSShhiP'), + [CHAIN.POLYGON]: sdk.graph.modifyEndpoint('Bn68xGN5mLu9cAVgCNrACxXWf5FR1dDQ6JxvXzimd7eZ'), + [CHAIN.ARBITRUM]: sdk.graph.modifyEndpoint('9wYUKdu85CGGwiV8mawEUwMhj4go7dx6ezfSkh9DUrFa'), + [CHAIN.OPTIMISM]: sdk.graph.modifyEndpoint('F7nNhkyaR53fs14vhfJmsUAotN1aJiyMbVc677ngFHWU'), [CHAIN.ERA]: "https://api.studio.thegraph.com/query/45576/woofi-zksync/version/latest", - [CHAIN.POLYGON_ZKEVM]: "https://api.studio.thegraph.com/query/45576/woofi-polygon-zkevm/version/latest", - [CHAIN.LINEA]: "https://woofi-subgraph.mer1in.com/subgraphs/name/woonetwork/woofi-linea", - [CHAIN.BASE]: "https://api.studio.thegraph.com/query/45576/woofi-base/version/latest", - [CHAIN.MANTLE]: "https://woofi-subgraph.mer1in.com/subgraphs/name/woonetwork/woofi-mantle", + [CHAIN.POLYGON_ZKEVM]: "https://api.studio.thegraph.com/query/71937/woofi-polygon-zkevm/version/latest", + [CHAIN.LINEA]: "https://api.studio.thegraph.com/query/71937/woofi-linea/version/latest", + [CHAIN.BASE]: "https://api.studio.thegraph.com/query/71937/woofi-base/version/latest", + [CHAIN.MANTLE]: "https://subgraph-api.mantle.xyz/api/public/9e9d6e8a-be9d-42d1-9747-3a8f001214c5/subgraphs/woonetwork/woofi-mantle/v0.0.1/gn", }; type TStartTime = { @@ -54,15 +56,38 @@ const graphs = getChainVolume({ }, }); -const fetch = (chain: string) => { - return async (timestamp: number, chainBlocks: ChainBlocks) => { - const result = await graphs(chain)(timestamp, chainBlocks); - if (!result) return {}; +const dailyQuery = gql` + query getDailyVolume($Id: Int!) { + dayData(id: $Id) { + volumeUSD + }, + globalVariables { + totalVolumeUSD + } + } +` + +interface FetchResult { + dayData: { + volumeUSD: string; + } + globalVariables: Array<{ + totalVolumeUSD: string; + }> +} +const fetch = async (_t: any, _c: any,options: FetchOptions) => { + try { + console.log('fetching volume for', options.startOfDay); + const dateId = Math.floor(options.startOfDay / 86400); + const response: FetchResult = await request(endpoints[options.chain], dailyQuery, { Id: dateId }); + if (!response) return {}; return { - ...result, - totalVolume: `${result.totalVolume / 10 ** 18}`, - dailyVolume: `${result.dailyVolume / 10 ** 18}` + dailyVolume: Number(response?.dayData?.volumeUSD || 0) / 1e18, + totalVolume: Number(response?.globalVariables[0]?.totalVolumeUSD || 0) / 1e18, }; + } catch (error) { + console.error(error); + return {}; } } @@ -70,7 +95,7 @@ const volume = Object.keys(endpoints).reduce( (acc, chain) => ({ ...acc, [chain]: { - fetch: fetch(chain), + fetch: fetch, start: startTime[chain], }, }), @@ -78,6 +103,7 @@ const volume = Object.keys(endpoints).reduce( ); const adapter: SimpleAdapter = { + version: 1, adapter: volume, }; export default adapter; diff --git a/dexs/xei/index.ts b/dexs/xei/index.ts new file mode 100644 index 0000000000..e1df4cf6c9 --- /dev/null +++ b/dexs/xei/index.ts @@ -0,0 +1,33 @@ +import { Chain } from "@defillama/sdk/build/general"; +import { FetchResult, FetchResultV2, FetchV2, SimpleAdapter } from "../../adapters/types"; +import { CHAIN } from "../../helpers/chains"; +import customBackfill from "../../helpers/customBackfill"; +import { httpGet } from "../../utils/fetchURL"; + +const fetch: FetchV2 = async ({ chain,toTimestamp,endTimestamp,fromTimestamp }): Promise => { + let volumeRes=await httpGet("https://app.xei.finance/indexer/1329/xei/dexVolume?endAt="+toTimestamp.toString()) + // console.log(volumeRes) + return { + dailyVolume:parseInt(volumeRes.data), + + }; +}; +const contract = { + [CHAIN.SEI]: '0x0596a0469D5452F876523487251BDdE73D4B2597', + +} +const adapter: SimpleAdapter = { + adapter: Object.keys(contract).reduce((acc, chain) => { + return { + ...acc, + [chain]: { + fetch, + start: 1716890175, + runAtCurrTime:false, + // customBackfill:customBackfill(contract, chain) + }, + } + }, {}), + version: 2, +}; +export default adapter; \ No newline at end of file diff --git a/dexs/xexchange/index.ts b/dexs/xexchange/index.ts index ddfca207c5..66ab863306 100644 --- a/dexs/xexchange/index.ts +++ b/dexs/xexchange/index.ts @@ -1,7 +1,6 @@ import { gql, GraphQLClient } from "graphql-request"; -import { SimpleAdapter } from "../../adapters/types"; +import { FetchOptions, SimpleAdapter } from "../../adapters/types"; import { CHAIN } from "../../helpers/chains"; -import { getUniqStartOfTodayTimestamp } from "../../helpers/getUniSubgraphVolume"; const getDailyVolume = () => { return gql`{ @@ -20,16 +19,15 @@ interface IGraphResponse { totalVolumeUSD24h: string; } -const fetch = async (timestamp: number) => { - const dayTimestamp = getUniqStartOfTodayTimestamp(new Date(timestamp * 1000)); +const fetch = async (_: FetchOptions) => { const historicalVolume: IGraphResponse = (await getGQLClient().request(getDailyVolume())).factory; return { dailyVolume: historicalVolume.totalVolumeUSD24h ? `${historicalVolume.totalVolumeUSD24h}` : undefined, - timestamp: dayTimestamp, }; } const adapter: SimpleAdapter = { + version: 2, adapter: { [CHAIN.ELROND]: { fetch: fetch, diff --git a/dexs/xswap-protocol/index.ts b/dexs/xswap-protocol/index.ts index f00e3083c6..67defa4fe2 100644 --- a/dexs/xswap-protocol/index.ts +++ b/dexs/xswap-protocol/index.ts @@ -1,12 +1,12 @@ import { SimpleAdapter } from "../../adapters/types"; import { CHAIN } from "../../helpers/chains"; -import { getGraphDimensions } from "../../helpers/getUniSubgraph"; +import { getGraphDimensions2 } from "../../helpers/getUniSubgraph"; const endpoints = { [CHAIN.XDC]: "https://analytics.xspswap.finance/subgraphs/name/some/factory" } -const graphs = getGraphDimensions({ +const graphs = getGraphDimensions2({ graphUrls: endpoints, graphRequestHeaders: { [CHAIN.XDC]: { @@ -17,6 +17,7 @@ const graphs = getGraphDimensions({ }); const adapters: SimpleAdapter = { + version: 2, adapter: { [CHAIN.XDC]: { fetch: graphs(CHAIN.XDC), diff --git a/dexs/yakafinance/index.ts b/dexs/yakafinance/index.ts new file mode 100644 index 0000000000..2f88e5bd03 --- /dev/null +++ b/dexs/yakafinance/index.ts @@ -0,0 +1,13 @@ +import { CHAIN } from "../../helpers/chains"; +import { univ2Adapter } from "../../helpers/getUniSubgraphVolume"; + +const adapters = univ2Adapter({ + [CHAIN.SEI]: "https://api.studio.thegraph.com/query/82132/yaka-finance/version/latest" +}, { + factoriesName: "pancakeFactories", + dayData: "pancakeDayData", +}); + + +adapters.adapter.sei.start = 1719432193; +export default adapters; \ No newline at end of file diff --git a/dexs/yfx-v4/index.ts b/dexs/yfx-v4/index.ts new file mode 100644 index 0000000000..81d8ee70b3 --- /dev/null +++ b/dexs/yfx-v4/index.ts @@ -0,0 +1,93 @@ +import request, { gql } from "graphql-request"; +import { Fetch, SimpleAdapter } from "../../adapters/types"; +import { CHAIN } from "../../helpers/chains"; +import { getUniqStartOfTodayTimestamp } from "../../helpers/getUniSubgraphVolume"; + +const chains = [CHAIN.ARBITRUM, CHAIN.BASE] + +const endpoints: { [key: string]: string } = { + [CHAIN.ARBITRUM]: "https://graph-v4.yfx.com/yfx_v4", + [CHAIN.BASE]: "https://graph-v4.yfx.com/yfx_v4_base", +} + +const historicalDailyData = gql` + query marketInfoDailies($dayTime: String!){ + marketInfoDailies(where: {dayTime: $dayTime}) { + liqVolUSD + totalVolUSD + } + } +` +const historicalTotalData = gql` + query markets { + markets { + # liqVol + totalVolUSD + } + } +` + +interface IGraphResponse { + marketInfoDailies: Array<{ + liqVolUSD: string, + totalVolUSD: string, + }> +} +interface IGraphResponse { + markets: Array<{ + liqVolUSD: string, + totalVolUSD: string, + }> +} + + +const getFetch = (chain: string): Fetch => async (timestamp: any) => { + const dayTimestamp = getUniqStartOfTodayTimestamp(new Date((timestamp.toTimestamp * 1000))) + + const dailyData: IGraphResponse = await request(endpoints[chain], historicalDailyData, { + dayTime: String(dayTimestamp), + }) + + let dailyVolume = 0; + for(let i in dailyData.marketInfoDailies) { + dailyVolume += parseFloat(dailyData.marketInfoDailies[i].totalVolUSD) + } + + const totalData: IGraphResponse = await request(endpoints[chain], historicalTotalData, {}) + let totalVolume = 0; + for(let i in totalData.markets) { + totalVolume += parseFloat(totalData.markets[i].totalVolUSD) + } + + return { + timestamp: dayTimestamp, + dailyVolume: dailyVolume.toString(), + totalVolume: totalVolume.toString() + } +} + +const getStartTimestamp = async (chain: string) => { + const startTimestamps: { [chain: string]: number } = { + [CHAIN.ARBITRUM]: 1713916800, + [CHAIN.BASE]: 1721001600, + } + return startTimestamps[chain] +} + + +const volume = chains.reduce( + (acc, chain) => ({ + ...acc, + [chain]: { + fetch: getFetch(chain), + start: async () => getStartTimestamp(chain) + }, + }), + {} +); + +const adapter: SimpleAdapter = { + version: 2, + adapter: volume +}; +export default adapter; diff --git a/dexs/yieldfields/index.ts b/dexs/yieldfields/index.ts index 6337a35770..e62feaafcc 100644 --- a/dexs/yieldfields/index.ts +++ b/dexs/yieldfields/index.ts @@ -1,20 +1,16 @@ -const { - getChainVolume, - DEFAULT_TOTAL_VOLUME_FIELD, - DEFAULT_DAILY_VOLUME_FIELD, -} = require("../../helpers/getUniSubgraphVolume"); +import * as sdk from "@defillama/sdk"; const { BSC } = require("../../helpers/chains"); const { getStartTimestamp } = require("../../helpers/getStartTimestamp"); - import { SimpleAdapter } from "../../adapters/types"; +import { DEFAULT_TOTAL_VOLUME_FIELD, getChainVolume2 } from "../../helpers/getUniSubgraphVolume"; const endpoints = { - [BSC]: "https://api.thegraph.com/subgraphs/name/sotblad/yieldfieldsexchange", + [BSC]: sdk.graph.modifyEndpoint('6PGfw9826xTB8JNN9HuMyY5eaFZLq6uqUcBwH7YEytsZ'), }; const DAILY_VOLUME_FACTORY = "yieldFieldsDayData"; -const graphs = getChainVolume({ +const graphs = getChainVolume2({ graphUrls: { [BSC]: endpoints[BSC], }, @@ -22,13 +18,10 @@ const graphs = getChainVolume({ factory: "yieldFieldsFactories", field: DEFAULT_TOTAL_VOLUME_FIELD, }, - dailyVolume: { - factory: DAILY_VOLUME_FACTORY, - field: DEFAULT_DAILY_VOLUME_FIELD, - }, }); const adapter: SimpleAdapter = { + version: 2, adapter: { [BSC]: { fetch: graphs(BSC), diff --git a/dexs/yodeswap/index.ts b/dexs/yodeswap/index.ts index a203230a7b..5bd76bd03f 100644 --- a/dexs/yodeswap/index.ts +++ b/dexs/yodeswap/index.ts @@ -1,6 +1,10 @@ import { CHAIN } from "../../helpers/chains"; import { univ2Adapter } from "../../helpers/getUniSubgraphVolume"; -export default univ2Adapter({ +const adapter = univ2Adapter({ [CHAIN.DOGECHAIN]: "https://graph.yodeswap.dog/subgraphs/name/yodeswap" }, {}); + +adapter.adapter[CHAIN.DOGECHAIN].start = 1630000000; +adapter.adapter[CHAIN.DOGECHAIN].fetch = async (timestamp: number) => { return { timestamp}}; +export default adapter; diff --git a/dexs/yoshi-exchange/index.ts b/dexs/yoshi-exchange/index.ts index b3321375c7..064722c296 100644 --- a/dexs/yoshi-exchange/index.ts +++ b/dexs/yoshi-exchange/index.ts @@ -1,10 +1,11 @@ +import * as sdk from "@defillama/sdk"; import { univ2Adapter } from "../../helpers/getUniSubgraphVolume"; import { CHAIN } from "../../helpers/chains"; const endpoints = { - [CHAIN.FANTOM]: "https://api.thegraph.com/subgraphs/name/yoshiexchange/yoshi-exchange", - [CHAIN.BSC]: "https://api.thegraph.com/subgraphs/name/yoshiexchange/yoshi-exchange-bsc", - [CHAIN.ETHEREUM]: "https://api.thegraph.com/subgraphs/name/yoshiexchange/yoshi-exchange-eth", + [CHAIN.FANTOM]: sdk.graph.modifyEndpoint('EWBFCUSAd8eGb735UtAfsW99fNaEDAPnE2bbKWsRQLNt'), + [CHAIN.BSC]: sdk.graph.modifyEndpoint('Ap2c45H9tD4DqqcUYDACkv1zks7GC2WmoGq8QUgSVD81'), + [CHAIN.ETHEREUM]: sdk.graph.modifyEndpoint('CbpyZn3XuTwDtiWqw33cTxM4SQFB1vmtpYqyrkJ6v52S'), }; export default univ2Adapter(endpoints, { diff --git a/dexs/zebra-v2/index.ts b/dexs/zebra-v2/index.ts index ac8bdc2e38..dd10418bee 100644 --- a/dexs/zebra-v2/index.ts +++ b/dexs/zebra-v2/index.ts @@ -1,18 +1,14 @@ -// https://api.studio.thegraph.com/query/55584/v3_scroll/version/latest -import { univ2Adapter } from "../../helpers/getUniSubgraphVolume"; +import { univ2Adapter2 } from "../../helpers/getUniSubgraphVolume"; import { CHAIN } from "../../helpers/chains"; const endpoints = { [CHAIN.SCROLL]: "https://api.studio.thegraph.com/query/55584/v3_scroll/version/latest", }; -const adapter = univ2Adapter(endpoints, { +const adapter = univ2Adapter2(endpoints, { factoriesName: "factories", - dayData: "uniswapDayData", - dailyVolume: "volumeUSD", totalVolume: "totalVolumeUSD", - dailyVolumeTimestampField: "date", }); adapter.adapter.scroll.start = 1700697600 diff --git a/dexs/zeno/index.ts b/dexs/zeno/index.ts new file mode 100644 index 0000000000..95cdafbbbe --- /dev/null +++ b/dexs/zeno/index.ts @@ -0,0 +1,62 @@ +import { Adapter } from "../../adapters/types"; +import { CHAIN } from "../../helpers/chains"; +import { gql, GraphQLClient } from "graphql-request"; +import { FetchOptions } from "../../adapters/types"; + +const endpoints = { + [CHAIN.METIS]: + "https://metisapi.0xgraph.xyz/subgraphs/name/metis-andromeda-prod-stats", +}; + +type MarketStat = { + id: string; + totalTradingVolume: string; +}; + +type MarketDailyStat = { + day: number; + tradingVolume: string; +} + +const fetch = async (_t: any, _tt: any, options: FetchOptions) => { + const dayId = Math.floor(options.startOfDay / 86400); + const query = gql` + { + marketDailyStats(where: { day: ${dayId} }) { + day + tradingVolume + } + marketStats { + id + totalTradingVolume + } + } + `; + const graphQLClient = new GraphQLClient(endpoints[options.chain]); + graphQLClient.setHeader("origin", "https://zeno.exchange"); + const data = await graphQLClient.request(query); + const dailyVolume = data.marketDailyStats.reduce( + (accum: number, t: MarketDailyStat) => accum + parseInt(t.tradingVolume) / 1e30, + 0 as number + ); + const totalVolume = data.marketStats.reduce( + (accum: number, t: MarketStat) => accum + parseInt(t.totalTradingVolume) / 1e30, + 0 as number + ); + return { + timestamp: options.startOfDay, + dailyVolume: dailyVolume, + totalVolume: totalVolume, + } +} + +const adapter: Adapter = { + adapter: { + [CHAIN.METIS]: { + fetch: fetch, + start: 1710294153, + }, + }, +}; + +export default adapter; diff --git a/dexs/zipswap/index.ts b/dexs/zipswap/index.ts index c6114ab178..ba782aaa9c 100644 --- a/dexs/zipswap/index.ts +++ b/dexs/zipswap/index.ts @@ -1,6 +1,7 @@ +import * as sdk from "@defillama/sdk"; import { CHAIN } from "../../helpers/chains"; import { univ2Adapter } from "../../helpers/getUniSubgraphVolume"; export default univ2Adapter({ - [CHAIN.OPTIMISM]: "https://api.thegraph.com/subgraphs/name/nonamefits/zipswap" + [CHAIN.OPTIMISM]: sdk.graph.modifyEndpoint('5tAUjmnM9iE4aADZwKhk3fobY8fMFbb1VMsrSKvo4kFr') }, {}); diff --git a/dexs/zklite/index.ts b/dexs/zklite/index.ts new file mode 100644 index 0000000000..9f840401c8 --- /dev/null +++ b/dexs/zklite/index.ts @@ -0,0 +1,59 @@ +import fetchURL from "../../utils/fetchURL" +import type { SimpleAdapter } from "../../adapters/types"; +import { getUniqStartOfTodayTimestamp } from "../../helpers/getUniSubgraphVolume"; +import { CHAIN } from "../../helpers/chains"; + +type TMarket = { + [s: string]: { + baseVolume: number; + usdVolume24h: number; + usdVolumeAll: number; + } +} + +type TMarketInfo = { + [s: string]: { + baseAsset: { + usdPrice: number; + }; + } +} + + +const fetch = async (timestamp: number) => { + const dayTimestamp = getUniqStartOfTodayTimestamp(new Date(timestamp * 1000)) + const markets: TMarket = (await fetchURL('https://api.zklite.io/api/v1/markets')); + const marketInfos: TMarketInfo = (await fetchURL('https://api.zklite.io/api/v1/marketinfos?chain_id=1&market=' + Object.keys(markets).join(','))); + let dailyVolume = 0 + let totalVolume = 0 + Object.keys(markets).forEach(market => { + const { baseVolume, usdVolume24h, usdVolumeAll } = markets[market] + if (usdVolume24h) { + dailyVolume += usdVolume24h; + totalVolume += usdVolumeAll; + return; + } + + const info = marketInfos[market] + if (!info) return; + dailyVolume += baseVolume * info.baseAsset.usdPrice; + }) + return { + dailyVolume, + totalVolume, + timestamp: dayTimestamp, + }; +}; + +const adapter: SimpleAdapter = { + adapter: { + [CHAIN.ZKSYNC]: { + fetch, + runAtCurrTime: true, + customBackfill: undefined, + start: 1712718123, + }, + } +}; + +export default adapter; diff --git a/dexs/zkswap/index.ts b/dexs/zkswap/index.ts index 481d6fc0db..a6a4f4e223 100644 --- a/dexs/zkswap/index.ts +++ b/dexs/zkswap/index.ts @@ -1,7 +1,6 @@ -import { time } from "console"; -import { SimpleAdapter } from "../../adapters/types"; +import { FetchOptions, SimpleAdapter } from "../../adapters/types"; import { CHAIN } from "../../helpers/chains"; -import { getGraphDimensions } from "../../helpers/getUniSubgraph"; +import { getGraphDimensions2 } from "../../helpers/getUniSubgraph"; const endpoints = { [CHAIN.ERA]: "https://api.studio.thegraph.com/query/60365/zksync-zkswap/v0.0.5" @@ -13,29 +12,20 @@ const blacklistTokens = { ] } -const graph = getGraphDimensions({ +const graph = getGraphDimensions2({ graphUrls: endpoints, totalVolume: { factory: "uniswapFactories", field: "totalVolumeUSD", }, - dailyVolume: { - factory: "uniswapDayData", - field: "dailyVolumeUSD", - }, blacklistTokens }); const adapters: SimpleAdapter = { + version: 2, adapter: { [CHAIN.ERA]: { - fetch: async (timestamp: number) => { - const data = await graph(CHAIN.ERA)(timestamp, {}); - data.totalVolume = undefined; - return { - ...data - }; - }, + fetch: graph(CHAIN.ERA), start: 1700524800, } } diff --git a/dexs/zyberswap/index.ts b/dexs/zyberswap/index.ts index ad4aa2b261..6516f196bd 100644 --- a/dexs/zyberswap/index.ts +++ b/dexs/zyberswap/index.ts @@ -1,59 +1,46 @@ +import * as sdk from "@defillama/sdk"; import { BreakdownAdapter } from "../../adapters/types"; import { CHAIN } from "../../helpers/chains"; -import { DEFAULT_DAILY_VOLUME_FACTORY, DEFAULT_DAILY_VOLUME_FIELD, DEFAULT_TOTAL_VOLUME_FACTORY, DEFAULT_TOTAL_VOLUME_FIELD, getChainVolume } from "../../helpers/getUniSubgraphVolume"; +import { DEFAULT_TOTAL_VOLUME_FACTORY, DEFAULT_TOTAL_VOLUME_FIELD, getChainVolume, getChainVolume2 } from "../../helpers/getUniSubgraphVolume"; const endpoints = { - [CHAIN.ARBITRUM]: "https://api.thegraph.com/subgraphs/name/zyberswap-arbitrum/zyber-amm", + [CHAIN.ARBITRUM]: sdk.graph.modifyEndpoint('3g83GYhbyHtjy581vpTmN1AP9cB9MjWMh5TiuNpvTU4R'), }; -const graphs = getChainVolume({ +const graphs = getChainVolume2({ graphUrls: endpoints, totalVolume: { factory: DEFAULT_TOTAL_VOLUME_FACTORY, field: DEFAULT_TOTAL_VOLUME_FIELD, }, - dailyVolume: { - factory: DEFAULT_DAILY_VOLUME_FACTORY, - field: DEFAULT_DAILY_VOLUME_FIELD, - dateField: "date" - }, }); const endpointsV3 = { - [CHAIN.ARBITRUM]: "https://api.thegraph.com/subgraphs/name/iliaazhel/zyberswap-info", + [CHAIN.ARBITRUM]: sdk.graph.modifyEndpoint('7ZP9MeeuXno2y9pWR5LzA96UtYuZYWTA4WYZDZR7ghbN'), }; -const graphsV3 = getChainVolume({ +const graphsV3 = getChainVolume2({ graphUrls: endpointsV3, totalVolume: { factory: "factories", field: "totalVolumeUSD", }, - dailyVolume: { - factory: "algebraDayData", - field: "volumeUSD", - dateField: "date" - }, }); const endpointsStable = { - [CHAIN.ARBITRUM]: "https://api.thegraph.com/subgraphs/name/zyberswap-arbitrum/zyber-stableamm" + [CHAIN.ARBITRUM]: sdk.graph.modifyEndpoint('H7QEsa69B3bbXZVtmqGaRZVUV8PCUqsKfqXGRb69LHa6') }; -const graphsStable = getChainVolume({ +const graphsStable = getChainVolume2({ graphUrls: endpointsStable, totalVolume: { factory: "tradeVolumes", field: "volume", }, - dailyVolume: { - factory: "dailyVolume", - field: "volume", - dateField: "timestamp" - }, }); const adapter: BreakdownAdapter = { + version: 2, breakdown: { v2: { [CHAIN.ARBITRUM]: { diff --git a/fees/0vix.ts b/fees/0vix.ts index e58ffe6ea6..420a3998fc 100644 --- a/fees/0vix.ts +++ b/fees/0vix.ts @@ -1,3 +1,4 @@ +import * as sdk from "@defillama/sdk"; import { Adapter, DISABLED_ADAPTER_KEY } from "../adapters/types"; import { CHAIN } from "../helpers/chains"; import { request, gql } from "graphql-request"; @@ -9,7 +10,7 @@ import disabledAdapter from "../helpers/disabledAdapter"; const endpoints = { [CHAIN.POLYGON]: - "https://api.thegraph.com/subgraphs/name/0vix/ovix-lending-subgraph", + sdk.graph.modifyEndpoint('DRe1wuJiBQK3SWBQwah7sovvTRqBeqNrkzWNjjoWinh9'), [CHAIN.POLYGON_ZKEVM]: "https://api.studio.thegraph.com/query/30443/0vix-zkevm/v0.0.1", }; diff --git a/fees/0x0dex.ts b/fees/0x0dex.ts index 2f76d4b7e0..14bbbfd0d9 100644 --- a/fees/0x0dex.ts +++ b/fees/0x0dex.ts @@ -1,4 +1,4 @@ -import { Adapter, FetchOptions, FetchResult } from "../adapters/types"; +import { Adapter, FetchOptions } from "../adapters/types"; import { ETHEREUM } from "../helpers/chains"; const OxOPoolETHAddress = "0x3d18AD735f949fEbD59BBfcB5864ee0157607616"; @@ -9,10 +9,10 @@ const discount = 0.0045; // Deposit Event const discountThreshold = 1000000 * (9 ** 18); -const fetch: any = async (timestamp: number, _: any, { getLogs, api }: FetchOptions): Promise => { +const fetch: any = async ({ getLogs, api,}: FetchOptions) => { const logs = await getLogs({ target: OxOPoolETHAddress, - eventAbi: "event Deposit (address sender, uint256 tokenAmount, uint256 ringIndex)" + eventAbi: "event Deposit (address sender, uint256 tokenAmount, uint256 ringIndex)", }) const senders = logs.map((log: any) => log.sender); const balances = await api.multiCall({ abi: 'erc20:balanceOf', calls: senders, target: OxOToken }) @@ -25,7 +25,6 @@ const fetch: any = async (timestamp: number, _: any, { getLogs, api }: FetchOpti dailyFees /= 1e18; return { - timestamp, dailyFees, // 100% of the revenue going to holders, hence, fees = revenue, fees = holdersRevenue dailyHoldersRevenue: dailyFees, @@ -34,6 +33,7 @@ const fetch: any = async (timestamp: number, _: any, { getLogs, api }: FetchOpti }; const adapter: Adapter = { + version: 2, adapter: { [ETHEREUM]: { fetch, diff --git a/fees/4cast/index.ts b/fees/4cast/index.ts new file mode 100644 index 0000000000..e1e02bc05f --- /dev/null +++ b/fees/4cast/index.ts @@ -0,0 +1,41 @@ +import { Adapter, FetchOptions, FetchV2 } from "../../adapters/types"; +import { CHAIN } from "../../helpers/chains"; +import { postURL } from "../../utils/fetchURL"; + +interface IData { + dailyFees: string; +} + +const endpoint = "https://www.4cast.win/api/api/platformFees"; + +function createSolBalances(options: FetchOptions, value: string) { + const balances = options.createBalances(); + + balances.add('So11111111111111111111111111111111111111112', Number(value) * 1e9); + + return balances; +} + +const fetch: FetchV2 = async (options) => { + const data: IData = await postURL(endpoint, { + startTimestamp: options.startTimestamp, + endTimestamp: options.endTimestamp, + }); + + return { + dailyFees: createSolBalances(options, data.dailyFees), + }; +}; + +const adapter: Adapter = { + version: 2, + adapter: { + [CHAIN.SOLANA]: { + fetch, + runAtCurrTime: false, + start: 1721174400, + }, + }, +}; + +export default adapter; diff --git a/fees/Omnidrome/bribes.ts b/fees/Omnidrome/bribes.ts deleted file mode 100644 index 9bcf65df5a..0000000000 --- a/fees/Omnidrome/bribes.ts +++ /dev/null @@ -1,163 +0,0 @@ -import * as sdk from "@defillama/sdk"; -import { getPrices } from "../../utils/prices"; -import { ethers } from "ethers"; -import { CHAIN } from "../../helpers/chains"; -import { FetchOptions } from "../../adapters/types"; - -const event_notify_reward = - "event NotifyReward(address indexed from,address indexed reward,uint256 indexed epoch,uint256 amount)"; -const event_geuge_created = - "event GaugeCreated(address indexed poolFactory,address indexed votingRewardsFactory,address indexed gaugeFactory,address pool,address bribeVotingReward,address feeVotingReward,address gauge,address creator)"; - -// const topic0_geuge_created = -// "0xef9f7d1ffff3b249c6b9bf2528499e935f7d96bb6d6ec4e7da504d1d3c6279e1"; -const contract_interface = new ethers.Interface([ - event_notify_reward, - event_geuge_created, -]); - -// type TPrice = { -// [s: string]: { -// price: number; -// decimals: number; -// }; -// }; - -interface ILog { - data: string; - transactionHash: string; - topics: string[]; -} - -// interface IBribes { -// token: string; -// name: string; -// symbol: string; -// decimals: number; -// amount: number; -// } - -const lphelper = "0x11D66FF243715169d6C14865E18fcc30d3557830"; -const factory = "0x769d1BcB5FDf30F5a9D19f1ab8A3cF8b60a6e855"; - -const abis: any = { - "getLPDetailsPaginated": - "function getLPDetailsPaginated(uint256 pageNumber, uint256 pageLength, address factory, address account) view returns (((address lp, address factory, string symbol, uint8 decimals, string name, bool stable, uint256 totalSupply), (address token0, uint8 token0Decimals, uint256 reserve0, string token0Name, string token0Symbol), (address token1, uint8 token1Decimals, uint256 reserve1, string token1Name, string token1Symbol), (address gauge, uint256 gaugeTotalSupply, uint256 emissions, address emissionsToken, uint8 emissionsDecimals, string emissionSymbol, bool gaugeAlive), (address feeAddress, address bribeAddress, address factoryAddress, uint256 poolFee, uint256 token0Fees, uint256 token1Fees), (uint256 accountBalance, uint256 accountEarned, uint256 accountStaked, uint256 claimable0, uint256 claimable1))[])", - "allPoolsLength": "function allPoolsLength() view returns (uint256)", -}; - -export const fees_bribes = async ( - fetchOptions: FetchOptions - // fromBlock: number, - // toBlock: number, - // timestamp: number -): Promise => { - let poolsArr: any[] = []; - const allPoolsLength = Number( - await sdk.api2.abi.call({ - target: factory, - abi: abis.allPoolsLength, - chain: CHAIN.ZETA, - }) - ); - const itemsPerPage = 15; - const ZERO_ADDRESS = "0x0000000000000000000000000000000000000000"; - - if (allPoolsLength < itemsPerPage) { - poolsArr = await sdk.api2.abi.call({ - target: lphelper, - params: [1, allPoolsLength, factory, ZERO_ADDRESS], - abi: abis.getLPDetailsPaginated, - chain: CHAIN.ZETA, - }); - } else { - const numberOfPages = Math.ceil(allPoolsLength / itemsPerPage); - for (let i = 0; i < numberOfPages; i++) { - const pools4page = await sdk.api2.abi.call({ - target: lphelper, - params: [i + 1, itemsPerPage, factory, ZERO_ADDRESS], - abi: abis.getLPDetailsPaginated, - chain: CHAIN.ZETA, - }); - poolsArr = [...poolsArr, ...pools4page]; - } - } - console.log(poolsArr); - const bribeVotingReward: string[] = poolsArr - .map((e: any) => { - return e[4].bribeAddress; - }) - .filter((e: string) => e !== ZERO_ADDRESS); - - // const bribeVotingReward: string[] = (await sdk.api2.abi.call({ - // target: lphelper, - // params: [1, 1000, "0x769d1BcB5FDf30F5a9D19f1ab8A3cF8b60a6e855", '0x0000000000000000000000000000000000000000'], - // abi: abis.getLPDetailsPaginated, - // chain: CHAIN.ZETA, - // })).map((e: any) => { - // return e[4].bribeAddress; - // }).filter((e: string) => e !== ZERO_ADDRESS); - const bribe_contracct = [...new Set(bribeVotingReward)]; - const logs: ILog[] = await fetchOptions.getLogs({ - targets: bribe_contracct, - topics: ['0x52977ea98a2220a03ee9ba5cb003ada08d394ea10155483c95dc2dc77a7eb24b'] - }) - const dailyBribesRevenue = fetchOptions.createBalances(); - logs.forEach((e: ILog) => { - const value = contract_interface.parseLog(e) - dailyBribesRevenue.add(value!.args.reward, value!.args.amount) - }) - return { - dailyBribesRevenue: dailyBribesRevenue - }; - // const logs: ILog[] = ( - // await Promise.all( - // bribe_contracct.map((address: string) => - // sdk.getEventLogs({ - // target: address, - // toBlock: toBlock, - // fromBlock: fromBlock, - // chain: CHAIN.ZETA, - // topics: [ - // "0x52977ea98a2220a03ee9ba5cb003ada08d394ea10155483c95dc2dc77a7eb24b", - // ], - // }) - // ) - // ) - // ).flat() as ILog[]; - - // const logs_bribes = logs.map((e: ILog) => { - // const value = contract_interface.parseLog(e); - // return { - // token: value!.args.reward, - // amount: Number(value!.args.amount), - // } as IBribes; - // }); - // const coins = [ - // ...new Set( - // logs_bribes.map((e: IBribes) => `${CHAIN.ZETA}:${e.token.toLowerCase()}`) - // ), - // ]; - // const coins_split: string[][] = []; - // for (let i = 0; i < coins.length; i += 100) { - // coins_split.push(coins.slice(i, i + 100)); - // } - // const prices_result: any = ( - // await Promise.all(coins_split.map((a: string[]) => getPrices(a, timestamp))) - // ) - // .flat() - // .flat() - // .flat(); - // const prices: TPrice = Object.assign({}, {}); - // prices_result.map((a: any) => Object.assign(prices, a)); - // const fees_bribes_usd = logs_bribes - // .map((e: IBribes) => { - // const price = - // prices[`${CHAIN.ZETA}:${e.token.toLowerCase()}`]?.price || 0; - // const decimals = - // prices[`${CHAIN.ZETA}:${e.token.toLowerCase()}`]?.decimals || 0; - // return (Number(e.amount) / 10 ** decimals) * price; - // }) - // .reduce((a: number, b: number) => a + b, 0); - // return fees_bribes_usd; -}; diff --git a/fees/Omnidrome/index.ts b/fees/Omnidrome/index.ts index 52072524f8..481fd6e8ff 100644 --- a/fees/Omnidrome/index.ts +++ b/fees/Omnidrome/index.ts @@ -1,89 +1,15 @@ -import { - ChainBlocks, - FetchOptions, - FetchResultFees, - SimpleAdapter, -} from "../../adapters/types"; -import { CHAIN } from "../../helpers/chains"; -import * as sdk from "@defillama/sdk"; -import { getBlock } from "../../helpers/getBlock"; -import { fees_bribes } from "./bribes"; -import { getDexFees } from "../../helpers/dexVolumeLogs"; +import { DISABLED_ADAPTER_KEY, SimpleAdapter } from "../../adapters/types" +import { CHAIN } from "../../helpers/chains" +import disabledAdapter from "../../helpers/disabledAdapter"; -const lphelper = "0x1f176AABA9c6e2014455E5C199afD15A70f9e34e"; -const abis: any = { - forSwaps: - "function forSwaps(uint256 _limit, uint256 _offset) view returns ((address lp, bool stable, address token0, address token1, address factory, uint256 poolFee)[])", -}; -const fetch = async ( - timestamp: number, - _: ChainBlocks, - fetchOptions: FetchOptions -): Promise => { - const fromTimestamp = timestamp - 60 * 60 * 24; - const toTimestamp = timestamp; - const forSwaps = await sdk.api2.abi.call({ - target: lphelper, - params: [1000, 0], - abi: abis.forSwaps, - chain: CHAIN.ZETA, - }); - const pools = forSwaps.map((e: any) => e.lp); - // const pools: string[] = [ - // '0x22e48B354eA9806e46D18554fCC44dAe0E6c8e0a', - // '0x739Cd2720F35D5176EC05067739BC2533c1314a7', - // '0x6F685FFa223c96a2Be05C26defEF80339F0EdBce', - // '0x8640E4807392627a4238312920618D4c6602e7fa', - // '0x4cfF774c9eA4466463214d1D1a6E7492E9057440', - // '0x3B48FFf7Dd8b827EF300DBA5Ae79fc7a322c49Ac', - // '0x51a857F95D9AB60Ae2C8A0f121d15637fc046EE7', - // '0xD9EBfC4Ba412a0B0c9F81Ef53641f33A8ae33884', - // '0xB8567E77491964539E62788F2BC44B6c2092a9a9', - // '0x5F3b15d89Fcc91229dC0C978302151cE9a83DaA1', - // '0x5b031943a2cA4905cfa4E4EB7f6F940EC4c3f924', - // '0x542D185C63E8B04a84B53cd05B47bB11eD9f11De', - // '0x1F69A5376929C86B6d4802781bDDe82F18c0BbC9', - // '0x26FeaB16c9bC84a3f4AAaD5b3F6158d5EC012f60', - // '0xDC63883280F43f607B3E463f40914Aab54325da4', - // '0xDbeC64831fc5faEa6AbD43F1EB62b9840bb8F239', - // '0xa1EDc8F027223f1291912D3D5AE2867836617f1f', - // '0x01DbC4861D3Ab7bF2D12957eb5f0e251B20D1AdE', - // '0xD2C04cbb9D374C1f4108343867784Fb2bFDf5043', - // '0x990391699bbE5DA396e53B64FA917E89992c0A91', - // '0x47201Cf6ba8007631c2B7247DCF8a37786eF26B3', - // '0x8C0066844223C80755938623298AbbB7356AdE7c', - // '0x17E4d8D30f4082E1Ca224046D0Db725c505a1bA8', - // '0x1Aa3dB8066a555B30b4C0977F0b700a00455529D', - // '0x83C251B5a4DD9CEE6414069b888b0b25Ad646F7D', - // '0x0b0e9b5019728B543CC5B436586319E6F5946820', - // '0xba01Aaa4f51baB79AD26c83fA687B0D169aD7FBf', - // '0x7d3292145320594B48cAf8383E70d98BeEdfC90f' - // ] - - const res: any = await getDexFees({ - chain: CHAIN.ZETA, - fromTimestamp, - toTimestamp, - pools, - timestamp, - fetchOptions, - }); - // const fromBlock = await getBlock(fromTimestamp, CHAIN.ZETA, {}); - // const toBlock = await getBlock(toTimestamp, CHAIN.ZETA, {}); - // const dailyBribesRevenue = await fees_bribes(fromBlock, toBlock, timestamp); - // res.dailyBribesRevenue = dailyBribesRevenue.toString(); - // return res; - const { dailyBribesRevenue } = await fees_bribes(fetchOptions); - res.dailyBribesRevenue = dailyBribesRevenue - return res -}; const adapters: SimpleAdapter = { adapter: { + [DISABLED_ADAPTER_KEY]: disabledAdapter, [CHAIN.ZETA]: { - fetch: fetch, + fetch: async (timestamp: number) => {return {timestamp, dailyFees: '0'}}, start: 1707177600, - }, - }, -}; + } + } +} export default adapters; diff --git a/fees/Scale.ts b/fees/Scale.ts index c938fced1f..40590ed5ca 100644 --- a/fees/Scale.ts +++ b/fees/Scale.ts @@ -11,7 +11,8 @@ const adapter: SimpleAdapter = { fetch: getFeesExport({ FACTORY_ADDRESS, VOTER_ADDRESS, }), start: 1695458888, }, - } + }, + version: 2, }; export default adapter; \ No newline at end of file diff --git a/fees/SmarDex/index.ts b/fees/SmarDex/index.ts index 2f42a7b61c..51b110726f 100644 --- a/fees/SmarDex/index.ts +++ b/fees/SmarDex/index.ts @@ -50,7 +50,7 @@ const methodology = { }; // Define the adapter -const adapter: Adapter = { adapter: {} }; +const adapter: Adapter = { version: 1, adapter: {} }; for (let chain in FEES) { adapter.adapter[chain] = { fetch: (timestamp: number) => diff --git a/fees/Viridian/index.ts b/fees/Viridian/index.ts new file mode 100644 index 0000000000..579a7f5dde --- /dev/null +++ b/fees/Viridian/index.ts @@ -0,0 +1,7 @@ +import { CHAIN } from '../../helpers/chains'; +import { uniV2Exports } from '../../helpers/uniswap'; + + +export default uniV2Exports({ + [CHAIN.CORE]: { factory: '0xb54a83cfEc6052E05BB2925097FAff0EC22893F3', voter: '0xbB7855fA0Ad297EC6e4aa1d4BE30f148447eD68c', }, +}) diff --git a/fees/aave/index.ts b/fees/aave/index.ts index 8bf5c26f88..e082e2e3ef 100644 --- a/fees/aave/index.ts +++ b/fees/aave/index.ts @@ -1,20 +1,25 @@ -import { Adapter } from "../../adapters/types"; +import * as sdk from "@defillama/sdk"; import { AVAX, OPTIMISM, FANTOM, HARMONY, ARBITRUM, ETHEREUM, POLYGON, CHAIN } from "../../helpers/chains"; import { request, gql } from "graphql-request"; -import type { ChainEndpoints } from "../../adapters/types"; - -import { getTimestampAtStartOfPreviousDayUTC, getTimestampAtStartOfDayUTC, getTimestampAtStartOfNextDayUTC } from "../../utils/date"; +import type { ChainEndpoints, FetchOptions } from "../../adapters/types"; import { V1Reserve, V2Reserve, V3Reserve } from "./types" import { Chain } from "@defillama/sdk/build/general"; +//POOL_ADDRESSES_PROVIDER available in https://github.com/bgd-labs/aave-address-book +//remember to lowercase const poolIDs = { V1: '0x24a42fd28c976a61df5d00d0599c34c4f90748c8', V2: '0xb53c1a33016b2dc2ff3653530bff1848a515c8c5', V2_AMM: '0xacc030ef66f9dfeae9cbb0cd1b25654b82cfa8d5', V2_POLYGON: '0xd05e3e715d945b59290df0ae8ef85c1bdb684744', V2_AVALANCHE: '0xb6a86025f0fe1862b372cb0ca18ce3ede02a318f', - V3: '0xa97684ead0e402dc232d5a977953df7ecbab3cdb', + V3: '0xa97684ead0e402dc232d5a977953df7ecbab3cdb', // arbitrum, Optimism, fantom, harmony, polygon, avalanche V3_ETH: '0x2f39d218133afab8f2b819b1066c7e434ad94e9e', + V3_BNB: '0xff75b6da14ffbbfd355daf7a2731456b3562ba6d', + V3_GNOSIS: '0x36616cf17557639614c1cddb356b1b83fc0b2132', + V3_METIS: '0xb9fabd7500b2c6781c35dd48d54f81fc2299d7af', + V3_BASE: '0xe20fcbdbffc4dd138ce8b2e6fbb6cb49777ad64d', + V3_SCROLL: '0x69850d0b276776781c063771b161bd8894bcdd04', } type THeader = { [s: string]: string; @@ -28,23 +33,29 @@ const headers: THeader = { const ONE_DAY = 24 * 60 * 60; const v1Endpoints = { - [ETHEREUM]: "https://api.thegraph.com/subgraphs/name/aave/protocol-multy-raw", + [ETHEREUM]: sdk.graph.modifyEndpoint('GJfRcmN4YAzKW3VH2ZKzTcWXjgtvkpAYSwFh1LfHsEuh'), } const v2Endpoints = { - [ETHEREUM]: "https://api.thegraph.com/subgraphs/name/aave/protocol-v2", - [AVAX]: 'https://api.thegraph.com/subgraphs/name/aave/protocol-v2-avalanche', - [POLYGON]: "https://api.thegraph.com/subgraphs/name/aave/aave-v2-matic" + [ETHEREUM]: sdk.graph.modifyEndpoint('8wR23o1zkS4gpLqLNU4kG3JHYVucqGyopL5utGxP2q1N'), + [AVAX]: sdk.graph.modifyEndpoint('EZvK18pMhwiCjxwesRLTg81fP33WnR6BnZe5Cvma3H1C'), + [POLYGON]: sdk.graph.modifyEndpoint('H1Et77RZh3XEf27vkAmJyzgCME2RSFLtDS2f4PPW6CGp') }; +//V3 endpoints avilable here: https://github.com/aave/protocol-subgraphs const v3Endpoints = { - [POLYGON]: 'https://api.thegraph.com/subgraphs/name/aave/protocol-v3-polygon', - [AVAX]: 'https://api.thegraph.com/subgraphs/name/aave/protocol-v3-avalanche', - [ARBITRUM]: 'https://api.thegraph.com/subgraphs/name/aave/protocol-v3-arbitrum', - [OPTIMISM]: 'https://api.thegraph.com/subgraphs/name/aave/protocol-v3-optimism', - [FANTOM]: 'https://api.thegraph.com/subgraphs/name/aave/protocol-v3-fantom', - [HARMONY]: 'https://api.thegraph.com/subgraphs/name/aave/protocol-v3-harmony', - [CHAIN.ETHEREUM]: 'https://api.thegraph.com/subgraphs/name/aave/protocol-v3', + [POLYGON]: sdk.graph.modifyEndpoint('Co2URyXjnxaw8WqxKyVHdirq9Ahhm5vcTs4dMedAq211'), + [AVAX]: sdk.graph.modifyEndpoint('2h9woxy8RTjHu1HJsCEnmzpPHFArU33avmUh4f71JpVn'), + [ARBITRUM]: sdk.graph.modifyEndpoint('DLuE98kEb5pQNXAcKFQGQgfSQ57Xdou4jnVbAEqMfy3B'), + [OPTIMISM]: sdk.graph.modifyEndpoint('DSfLz8oQBUeU5atALgUFQKMTSYV9mZAVYp4noLSXAfvb'), + [FANTOM]: sdk.graph.modifyEndpoint('6L1vPqyE3xvkzkWjh6wUKc1ABWYYps5HJahoxhrv2PJn'), + [HARMONY]: sdk.graph.modifyEndpoint('FifJapBdCqT9vgNqJ5axmr6eNyUpUSaRAbbZTfsViNsT'), + [CHAIN.ETHEREUM]: sdk.graph.modifyEndpoint('Cd2gEDVeqnjBn1hSeqFMitw8Q1iiyV9FYUZkLNRcL87g'), + [CHAIN.BSC]: sdk.graph.modifyEndpoint('7Jk85XgkV1MQ7u56hD8rr65rfASbayJXopugWkUoBMnZ'), + [CHAIN.XDAI]: sdk.graph.modifyEndpoint('HtcDaL8L8iZ2KQNNS44EBVmLruzxuNAz1RkBYdui1QUT'), + [CHAIN.METIS]: 'https://metisapi.0xgraph.xyz/subgraphs/name/aave/protocol-v3-metis', + [CHAIN.BASE]: 'https://api.goldsky.com/api/public/project_clk74pd7lueg738tw9sjh79d6/subgraphs/aave-v3-base/1.0.0/gn', + [CHAIN.SCROLL]: 'https://api.goldsky.com/api/public/project_clk74pd7lueg738tw9sjh79d6/subgraphs/aave-v3-scroll/1.0.0/gn', } @@ -80,9 +91,9 @@ const v1Reserves = async (graphUrls: ChainEndpoints, chain: string, timestamp: n const v1Graphs = (graphUrls: ChainEndpoints) => { return (chain: Chain) => { - return async (timestamp: number) => { - const todaysTimestamp = timestamp - const yesterdaysTimestamp = timestamp - 60 * 60 * 24 + return async ({ endTimestamp }: FetchOptions) => { + const todaysTimestamp = endTimestamp + const yesterdaysTimestamp = endTimestamp - 60 * 60 * 24 const todaysReserves: V1Reserve[] = await v1Reserves(graphUrls, chain, todaysTimestamp); const yesterdaysReserves: V1Reserve[] = await v1Reserves(graphUrls, chain, yesterdaysTimestamp); @@ -136,7 +147,6 @@ const v1Graphs = (graphUrls: ChainEndpoints) => { }, 0); return { - timestamp, dailyFees: dailyFee.toString(), dailyRevenue: dailyRev.toString(), dailyHoldersRevenue: '0', @@ -185,9 +195,9 @@ const blacklisted_v2_symbol: TMap = { } const v2Graphs = (graphUrls: ChainEndpoints) => { return (chain: Chain) => { - return async (timestamp: number) => { - const todaysTimestamp = timestamp - const yesterdaysTimestamp = timestamp - 60 * 60 * 24 + return async ({ endTimestamp }: FetchOptions) => { + const todaysTimestamp = endTimestamp + const yesterdaysTimestamp = endTimestamp - 60 * 60 * 24 let poolID = poolIDs.V2 if (chain == "avax") { @@ -286,7 +296,6 @@ const v2Graphs = (graphUrls: ChainEndpoints) => { } return { - timestamp, dailyFees: dailyFee.toString(), dailyRevenue: dailyRev.toString(), }; @@ -297,9 +306,32 @@ const v2Graphs = (graphUrls: ChainEndpoints) => { const v3Reserves = async (graphUrls: ChainEndpoints, chain: string, timestamp: number) => { + let poolid; + if (chain === CHAIN.ETHEREUM) { + poolid = poolIDs.V3_ETH; + } + else if (chain === CHAIN.BSC) { + poolid = poolIDs.V3_BNB; + } + else if (chain === CHAIN.XDAI) { + poolid = poolIDs.V3_GNOSIS; + } + else if (chain === CHAIN.METIS) { + poolid = poolIDs.V3_METIS; + } + else if (chain === CHAIN.BASE) { + poolid = poolIDs.V3_BASE; + } + else if (chain === CHAIN.SCROLL) { + poolid = poolIDs.V3_SCROLL; + } + else { + poolid= poolIDs.V3; + } + const graphQuery = `{ - reserves(where: { pool: "${chain === CHAIN.ETHEREUM ? poolIDs.V3_ETH : poolIDs.V3}" }) { + reserves(where: { pool: "${poolid}" }) { id paramsHistory( where: { timestamp_lte: ${timestamp}, timestamp_gte: ${timestamp - ONE_DAY} }, @@ -332,10 +364,9 @@ const v3Reserves = async (graphUrls: ChainEndpoints, chain: string, timestamp: n const v3Graphs = (graphUrls: ChainEndpoints) => { return (chain: Chain) => { - return async (timestamp: number) => { - const _timestamp = getTimestampAtStartOfNextDayUTC(timestamp); - const todaysTimestamp = _timestamp - const yesterdaysTimestamp = _timestamp - 60 * 60 * 24 + return async ({ endTimestamp }: FetchOptions) => { + const todaysTimestamp = endTimestamp + const yesterdaysTimestamp = endTimestamp - 60 * 60 * 24 const todaysReserves: V3Reserve[] = await v3Reserves(graphUrls, chain, todaysTimestamp); const yesterdaysReserves: V3Reserve[] = await v3Reserves(graphUrls, chain, yesterdaysTimestamp); @@ -389,11 +420,10 @@ const v3Graphs = (graphUrls: ChainEndpoints) => { treasuryIncomeUSD: 0, outstandingTreasuryIncomeUSD: 0 }); - const dailyFee = feeBreakdown.depositorInterestUSD + feeBreakdown.outstandingTreasuryIncomeUSD + feeBreakdown.treasuryIncomeUSD - const dailyRev = feeBreakdown.treasuryIncomeUSD + feeBreakdown.outstandingTreasuryIncomeUSD + const dailyFee = feeBreakdown.depositorInterestUSD + feeBreakdown.treasuryIncomeUSD + const dailyRev = feeBreakdown.treasuryIncomeUSD return { - timestamp, dailyFees: dailyFee.toString(), dailyRevenue: dailyRev.toString(), }; @@ -401,14 +431,15 @@ const v3Graphs = (graphUrls: ChainEndpoints) => { }; }; -const adapter: Adapter = { +const adapter = { breakdown: { - // v1: { - // [ETHEREUM]: { - // fetch: v1Graphs(v1Endpoints)(ETHEREUM), - // start: 1578459600 - // }, - // }, +//v1 subgraph no longer responding +// v1: { +// [ETHEREUM]: { +// fetch: v1Graphs(v1Endpoints)(ETHEREUM), +// start: 1578459600 +// }, +// }, v2: { [AVAX]: { fetch: v2Graphs(v2Endpoints)(AVAX), @@ -452,8 +483,29 @@ const adapter: Adapter = { fetch: v3Graphs(v3Endpoints)(CHAIN.ETHEREUM), start: 1647230400 }, + [CHAIN.BSC]: { + fetch: v3Graphs(v3Endpoints)(CHAIN.BSC), + start: 1700222400 + }, + [CHAIN.XDAI]: { + fetch: v3Graphs(v3Endpoints)(CHAIN.XDAI), + start: 1696420800 + }, + [CHAIN.METIS]: { + fetch: v3Graphs(v3Endpoints)(CHAIN.METIS), + start: 1682164800 + }, + [CHAIN.BASE]: { + fetch: v3Graphs(v3Endpoints)(CHAIN.BASE), + start: 1691496000 + }, + [CHAIN.SCROLL]: { + fetch: v3Graphs(v3Endpoints)(CHAIN.SCROLL), + start: 1705741200 + }, } - } + }, + version: 2 } export default adapter; diff --git a/fees/abcdefx.ts b/fees/abcdefx.ts index e0fea66619..596bd3e583 100644 --- a/fees/abcdefx.ts +++ b/fees/abcdefx.ts @@ -1,15 +1,8 @@ import { SimpleAdapter } from "../adapters/types"; import { CHAIN } from "../helpers/chains"; -import { getDexFeesExports } from "../helpers/dexVolumeLogs"; -import { Chain } from "@defillama/sdk/build/general"; const FACTORY_ADDRESS = '0x01f43d2a7f4554468f77e06757e707150e39130c'; -const graph = (_chain: Chain) => { - // LPs get 0% fees, 100% goes to Guru's Treasury, which buys back ELITE - return getDexFeesExports({ chain: _chain, factory: FACTORY_ADDRESS }) -} - const methodology = { UserFees: "Users pay a Trading fee on each swap, including Flash Loans.", Fees: "Net Trading fees paid by all ABcDeFx users.", @@ -19,14 +12,16 @@ const methodology = { SupplySideRevenue: "0% of trading fees are distributed among liquidity providers." } -const adapter: SimpleAdapter = { - adapter: { - [CHAIN.KCC]: { fetch: graph(CHAIN.KCC), start: 1670188701, meta: { methodology } }, - //[CHAIN.MULTIVAC]: { fetch: graph(CHAIN.MULTIVAC), start: 1670226950, meta: { methodology } }, /// ! typeof CHAIN - [CHAIN.FANTOM]: { fetch: graph(CHAIN.FANTOM), start: 1671580916, meta: { methodology } }, - //[CHAIN.ECHELON]: { fetch: graph(CHAIN.ECHELON), start: 1671608400, meta: { methodology } }, /// ded!? - [CHAIN.KAVA]: { fetch: graph(CHAIN.KAVA), start: 1676855943, meta: { methodology } } - } -}; +import { uniV2Exports } from "../helpers/uniswap"; + +const adapters: SimpleAdapter = uniV2Exports({ + [CHAIN.FANTOM]: { factory: FACTORY_ADDRESS, }, + [CHAIN.KCC]: { factory: FACTORY_ADDRESS, }, + [CHAIN.KAVA]: { factory: FACTORY_ADDRESS, }, +}) + -export default adapter; \ No newline at end of file +Object.keys(adapters.adapter).forEach((chain: any) => { + adapters.adapter[chain].meta = { methodology } +}) +export default adapters; \ No newline at end of file diff --git a/fees/abracadabra.ts b/fees/abracadabra.ts index db747d2c29..b176b123e3 100644 --- a/fees/abracadabra.ts +++ b/fees/abracadabra.ts @@ -1,18 +1,17 @@ -import { Adapter, ChainBlocks } from "../adapters/types"; +import * as sdk from "@defillama/sdk"; +import { Adapter } from "../adapters/types"; import { CHAIN } from "../helpers/chains"; import { request, gql } from "graphql-request"; -import type { ChainEndpoints } from "../adapters/types" +import type { ChainEndpoints, FetchOptions } from "../adapters/types" import { Chain } from '@defillama/sdk/build/general'; -import { getTimestampAtStartOfDayUTC, getTimestampAtStartOfNextDayUTC } from "../utils/date"; -import { getBlock } from "../helpers/getBlock"; const endpoints = { - [CHAIN.ETHEREUM]: "https://api.thegraph.com/subgraphs/name/ap0calyp/abracadabra-mainnet-fees", - [CHAIN.FANTOM]: "https://api.thegraph.com/subgraphs/name/ap0calyp/abracadabra-fantom-fees", - [CHAIN.AVAX]: "https://api.thegraph.com/subgraphs/name/ap0calyp/abracadabra-avalanche-fees", - [CHAIN.BSC]: "https://api.thegraph.com/subgraphs/name/ap0calyp/abracadabra-binancesmartchain-fees", - [CHAIN.ARBITRUM]: "https://api.thegraph.com/subgraphs/name/ap0calyp/abracadabra-arbitrum-fees" + [CHAIN.ETHEREUM]: sdk.graph.modifyEndpoint('ktva51TWWq7t1hLnTGb88toXYtpxFo6gZfUC5NRnd9m'), + [CHAIN.FANTOM]: sdk.graph.modifyEndpoint('CnY2wTox8Pxh5t1UskQahPhMQdmuTmTAgwU62scUA8uM'), + [CHAIN.AVAX]: sdk.graph.modifyEndpoint('Ak8GFBj7XruiuMd4nV3vfNzButNsj3pF7ogSBq6qdKcq'), + [CHAIN.BSC]: sdk.graph.modifyEndpoint('2RsqpTn7JBLs2sU775C7ZcM7oUrcZmpDhTnUbFCJWLfV'), + [CHAIN.ARBITRUM]: sdk.graph.modifyEndpoint('ASL3E8FZLN5AKxFoagSb7i3kFkDkMfoRovmDDLZAY8t4') } type DataResponse = { @@ -39,12 +38,8 @@ const getFees = (data: DataResponse): number => { const graphs = (graphUrls: ChainEndpoints) => { return (chain: Chain) => { - return async (timestamp: number, _: ChainBlocks) => { - const todaysTimestamp = getTimestampAtStartOfDayUTC(timestamp) - const yesterdaysTimestamp = getTimestampAtStartOfNextDayUTC(timestamp) - - const startBlock = (await getBlock(todaysTimestamp, chain, {})); - const endBlock = (await getBlock(yesterdaysTimestamp, chain, {})); + return async ({ getFromBlock, getToBlock}: FetchOptions) => { + const [startBlock, endBlock] = await Promise.all([getFromBlock(), getToBlock()]) const graphQuery = gql `query fees($startBlock: Int!, $endBlock: Int!) { startValue: cauldronFees(block: { number: $startBlock }) { @@ -63,7 +58,6 @@ const graphs = (graphUrls: ChainEndpoints) => { const dailyFeeUsd = dailyFee; const dailyRevenue = dailyFeeUsd * .5; return { - timestamp, dailyFees: dailyFeeUsd.toString(), dailyRevenue: dailyRevenue.toString(), }; @@ -73,6 +67,7 @@ const graphs = (graphUrls: ChainEndpoints) => { const adapter: Adapter = { + version: 2, adapter: { [CHAIN.ETHEREUM]: { fetch: graphs(endpoints)(CHAIN.ETHEREUM), diff --git a/fees/across.ts b/fees/across.ts index d36eb7ebef..6880b539ca 100644 --- a/fees/across.ts +++ b/fees/across.ts @@ -1,67 +1,92 @@ -import { Chain } from "@defillama/sdk/build/general" -import { ChainBlocks, FetchOptions, FetchResultFees, SimpleAdapter } from "../adapters/types" -import { CHAIN } from "../helpers/chains" +import { + FetchOptions, + SimpleAdapter, +} from "../adapters/types"; +import { CHAIN } from "../helpers/chains"; const abis = { - "FundsDeposited": "event FundsDeposited(uint256 amount, uint256 originChainId, uint256 indexed destinationChainId, int64 relayerFeePct, uint32 indexed depositId, uint32 quoteTimestamp, address originToken, address recipient, address indexed depositor, bytes message)", - "FilledRelay": "event FilledRelay(uint256 amount, uint256 totalFilledAmount, uint256 fillAmount, uint256 repaymentChainId, uint256 indexed originChainId, uint256 destinationChainId, int64 relayerFeePct, int64 realizedLpFeePct, uint32 indexed depositId, address destinationToken, address relayer, address indexed depositor, address recipient, bytes message, (address recipient, bytes message, int64 relayerFeePct, bool isSlowRelay, int256 payoutAdjustmentPct) updatableRelayData)" -} -const topic0_fund_disposit_v2 = '0xafc4df6845a4ab948b492800d3d8a25d538a102a2bc07cd01f1cfa097fddcff6'; -const topic0_filled_replay_v2 = '0x8ab9dc6c19fe88e69bc70221b339c84332752fdd49591b7c51e66bae3947b73c'; - + FundsDeposited: + "event FundsDeposited(uint256 amount, uint256 originChainId, uint256 indexed destinationChainId, int64 relayerFeePct, uint32 indexed depositId, uint32 quoteTimestamp, address originToken, address recipient, address indexed depositor, bytes message)", + V3FundsDeposited: + "event V3FundsDeposited(address inputToken, address outputToken, uint256 inputAmount, uint256 outputAmount, uint256 indexed destinationChainId, uint32 depositId, uint32 quoteTimestamp, uint32 fillDeadline, uint32 exclusivityDeadline, address indexed depositor, address recipient, address exclusiveRelayer, bytes message)", + FilledRelay: + "event FilledRelay(uint256 amount, uint256 totalFilledAmount, uint256 fillAmount, uint256 repaymentChainId, uint256 indexed originChainId, uint256 destinationChainId, int64 relayerFeePct, int64 realizedLpFeePct, uint32 indexed depositId, address destinationToken, address relayer, address indexed depositor, address recipient, bytes message, (address recipient, bytes message, int64 relayerFeePct, bool isSlowRelay, int256 payoutAdjustmentPct) updatableRelayData)", + FilledV3Relay: + "event FilledV3Relay(address inputToken, address outputToken, uint256 inputAmount, uint256 outputAmount, uint256 repaymentChainId, uint256 indexed originChainId, uint32 indexed depositId, uint32 fillDeadline, uint32 exclusivityDeadline, address exclusiveRelayer, address indexed relayer, address depositor, address recipient, bytes message, (address updatedRecipient, bytes updatedMessage, uint256 updatedOutputAmount, uint8 fillType) relayExecutionInfo)", +}; +const topic0_filled_replay_v2 = + "0x8ab9dc6c19fe88e69bc70221b339c84332752fdd49591b7c51e66bae3947b73c"; +const topic0_filled_replay_v3 = + "0x571749edf1d5c9599318cdbc4e28a6475d65e87fd3b2ddbe1e9a8d5e7a0f0ff7"; const address: any = { - [CHAIN.ETHEREUM]: '0x5c7BCd6E7De5423a257D81B442095A1a6ced35C5', - [CHAIN.ARBITRUM]: '0xe35e9842fceaCA96570B734083f4a58e8F7C5f2A', - [CHAIN.OPTIMISM]: '0x6f26Bf09B1C792e3228e5467807a900A503c0281', - [CHAIN.POLYGON]: '0x9295ee1d8C5b022Be115A2AD3c30C72E34e7F096' -} - -const graph = (chain: Chain) => { - return async (timestamp: number, _: ChainBlocks, { createBalances, getLogs, }: FetchOptions): Promise => { - const dailyFees = createBalances() - const logs_fund_disposit = (await getLogs({ + [CHAIN.ETHEREUM]: "0x5c7BCd6E7De5423a257D81B442095A1a6ced35C5", + [CHAIN.ARBITRUM]: "0xe35e9842fceaCA96570B734083f4a58e8F7C5f2A", + [CHAIN.OPTIMISM]: "0x6f26Bf09B1C792e3228e5467807a900A503c0281", + [CHAIN.POLYGON]: "0x9295ee1d8C5b022Be115A2AD3c30C72E34e7F096", +}; +const graph = async ({ createBalances, getLogs, chain }: FetchOptions) => { + const dailyFees = createBalances(); + const logs_fund_disposit = ( + await getLogs({ target: address[chain], eventAbi: abis.FundsDeposited, - topic: topic0_fund_disposit_v2, - })).filter((a: any) => Number(a!.destinationChainId) === 288) + }) + ).filter((a: any) => Number(a!.destinationChainId) === 288); - const logs_filled_replay = (await getLogs({ + const logs_fund_disposit_v3 = ( + await getLogs({ target: address[chain], - eventAbi: abis.FilledRelay, - topic: topic0_filled_replay_v2, - })) + eventAbi: abis.V3FundsDeposited, + }) + ).filter((a: any) => Number(a!.destinationChainId) === 288); + + const logs_filled_replay = await getLogs({ + target: address[chain], + eventAbi: abis.FilledRelay, + topic: topic0_filled_replay_v2, + }); - logs_fund_disposit.map((a: any) => dailyFees.add(a.originToken, Number(a.amount * a.relayerFeePct) / 1e18)); - logs_filled_replay.map((a: any) => dailyFees.add(a.destinationToken, Number(a.amount) * Number(a.relayerFeePct + a.realizedLpFeePct) / 1e18)) - return { - dailyFees, - dailySupplySideRevenue: dailyFees, - timestamp - } - } -} + const logs_filled_replay_v3 = await getLogs({ + target: address[chain], + eventAbi: abis.FilledV3Relay, + topic: topic0_filled_replay_v3, + }); + logs_fund_disposit.map((a: any) => + dailyFees.add(a.originToken, Number(a.amount * a.relayerFeePct) / 1e18), + ); + + logs_fund_disposit_v3.map((a: any) => + dailyFees.add(a.outputToken, Number(a.inputAmount - a.outputAmount)), + ); + + logs_filled_replay.map((a: any) => + dailyFees.add( + a.destinationToken, + (Number(a.amount) * Number(a.relayerFeePct + a.realizedLpFeePct)) / + 1e18, + ), + ); + + logs_filled_replay_v3.map((a: any) => + dailyFees.add(a.outputToken, Number(a.inputAmount - a.outputAmount)), + ); + + return { + dailyFees, + dailySupplySideRevenue: dailyFees, + }; +}; const adapter: SimpleAdapter = { + version: 2, adapter: { - [CHAIN.ETHEREUM]: { - fetch: graph(CHAIN.ETHEREUM), - start: 1682840443, - }, - [CHAIN.ARBITRUM]: { - fetch: graph(CHAIN.ARBITRUM), - start: 1682840443, - }, - [CHAIN.OPTIMISM]: { - fetch: graph(CHAIN.OPTIMISM), - start: 1682840443, - }, - [CHAIN.POLYGON]: { - fetch: graph(CHAIN.POLYGON), - start: 1682840443, - }, - } + [CHAIN.ETHEREUM]: { fetch: graph, start: 1682840443, }, + [CHAIN.ARBITRUM]: { fetch: graph, start: 1682840443, }, + [CHAIN.OPTIMISM]: { fetch: graph, start: 1682840443, }, + [CHAIN.POLYGON]: { fetch: graph, start: 1682840443, }, + }, }; export default adapter; diff --git a/fees/aerodrome/bribes.ts b/fees/aerodrome/bribes.ts deleted file mode 100644 index 811bb616c4..0000000000 --- a/fees/aerodrome/bribes.ts +++ /dev/null @@ -1,30 +0,0 @@ -import ADDRESSES from '../../helpers/coreAssets.json' -import { FetchOptions } from '../../adapters/types'; - -const event_notify_reward = 'event NotifyReward(address indexed from,address indexed reward,uint256 indexed epoch,uint256 amount)'; - -const gurar = '0x2073D8035bB2b0F2e85aAF5a8732C6f397F9ff9b'; - -const abis: any = { - "all": "function all(uint256 _limit, uint256 _offset, address _account) view returns ((address lp, string symbol, uint8 decimals, bool stable, uint256 total_supply, address token0, uint256 reserve0, uint256 claimable0, address token1, uint256 reserve1, uint256 claimable1, address gauge, uint256 gauge_total_supply, bool gauge_alive, address fee, address bribe, address factory, uint256 emissions, address emissions_token, uint256 account_balance, uint256 account_earned, uint256 account_staked, uint256 pool_fee, uint256 token0_fees, uint256 token1_fees)[])" -} - -export const fees_bribes = async ({ getLogs, api, createBalances }: FetchOptions)=> { - const dailyFees = createBalances() - const bribeVotingReward: string[] = (await api.call({ - target: gurar, - params: [1000, 0, ADDRESSES.null], - abi: abis.all, - })).map((e: any) => { - return e.bribe; - }).filter((e: string) => e !== ADDRESSES.null); - const bribe_contracct = [...new Set(bribeVotingReward)]; - const logs = await getLogs({ - targets: bribe_contracct, - eventAbi: event_notify_reward, - }) - logs.map((e: any) => { - dailyFees.add(e.reward, e.amount) - }) - return dailyFees; -} diff --git a/fees/aerodrome/index.ts b/fees/aerodrome/index.ts index 718fc84993..e28d1b3549 100644 --- a/fees/aerodrome/index.ts +++ b/fees/aerodrome/index.ts @@ -1,41 +1,8 @@ -import { ChainBlocks, FetchOptions, FetchResultFees, SimpleAdapter } from "../../adapters/types" import { CHAIN } from "../../helpers/chains" -import * as sdk from "@defillama/sdk"; -import { fees_bribes } from "./bribes"; -import { getDexFees } from "../../helpers/dexVolumeLogs"; +import { uniV2Exports } from "../../helpers/uniswap"; -const gurar = '0x2073D8035bB2b0F2e85aAF5a8732C6f397F9ff9b'; -const abis: any = { - "forSwaps": "function forSwaps() view returns ((address lp, bool stable, address token0, address token1, address factory)[])" -} -// defualt abi for multiCall is error some pools -const multiCall = async (callN: any) => { - return (await sdk.api.abi.multiCall({ - abi: callN.abi, - calls: callN.calls.map((pool: any) => ({ - target: pool, - })), - chain: CHAIN.BASE, - permitFailure: true, - })).output.map((r: any) => r.output).flat() -} +const swapEvent = 'event Swap(address indexed sender, address indexed to, uint256 amount0In, uint256 amount1In, uint256 amount0Out, uint256 amount1Out)' -const fetch = async (timestamp: number, _: ChainBlocks, fetchOptions: FetchOptions): Promise => { - const forSwaps = await sdk.api2.abi.call({ target: gurar, abi: abis.forSwaps, chain: CHAIN.BASE, }) - const pools = forSwaps.map((e: any) => e.lp) - fetchOptions.api.multiCall = multiCall - const res: any = await getDexFees({ chain: CHAIN.BASE, fromTimestamp: fetchOptions.fromTimestamp, toTimestamp: fetchOptions.toTimestamp, pools, timestamp, fetchOptions }) - res.dailyBribesRevenue = await fees_bribes(fetchOptions); - - return res - -} -const adapters: SimpleAdapter = { - adapter: { - [CHAIN.BASE]: { - fetch: fetch, - start: 1693180800, - } - } -} -export default adapters; +export default uniV2Exports({ + [CHAIN.BASE]: { factory: '0x420DD381b31aEf6683db6B902084cB0FFECe40Da', swapEvent, voter: '0x16613524e02ad97eDfeF371bC883F2F5d6C480A50', maxPairSize: 65, }, +}) diff --git a/fees/aimbot.ts b/fees/aimbot.ts index e2b0b1b6b8..e97babf66e 100644 --- a/fees/aimbot.ts +++ b/fees/aimbot.ts @@ -1,4 +1,4 @@ -import { FetchOptions, FetchResultFees, SimpleAdapter } from "../adapters/types"; +import { FetchOptions, SimpleAdapter } from "../adapters/types"; import { CHAIN } from "../helpers/chains"; import { queryIndexer } from "../helpers/indexer"; import { httpGet } from "../utils/fetchURL"; @@ -8,7 +8,7 @@ interface IData { value: string; } -const fetch: any = async (timestamp: number, _: any, options: FetchOptions): Promise => { +const fetch: any = async (options: FetchOptions) => { const { createBalances, } = options const dailyFees = createBalances() const transfer_txs = ` @@ -41,11 +41,12 @@ const fetch: any = async (timestamp: number, _: any, options: FetchOptions): Pro const openBotFundAmount = openBotFundData['total']; dailyFees.addGasToken(openBotFundAmount * 1e18); - return { dailyFees, dailyRevenue: dailyFees, timestamp } + return { dailyFees, dailyRevenue: dailyFees } } const adapter: SimpleAdapter = { + version: 2, adapter: { [CHAIN.ETHEREUM]: { fetch: fetch, diff --git a/fees/airswap.ts b/fees/airswap.ts index b3f8a07dd0..9b63e8f088 100644 --- a/fees/airswap.ts +++ b/fees/airswap.ts @@ -1,4 +1,4 @@ -import { ChainBlocks, FetchOptions, FetchResultFees, SimpleAdapter } from "../adapters/types"; +import { FetchOptions, SimpleAdapter } from "../adapters/types"; import { CHAIN } from "../helpers/chains"; import { Chain } from "@defillama/sdk/build/general"; @@ -16,7 +16,7 @@ const address: TAddress = { } const graph = (chain: Chain) => { - return async (timestamp: number, _: ChainBlocks, { createBalances, getLogs, }: FetchOptions): Promise => { + return async ({ createBalances, getLogs,}: FetchOptions) => { const dailyFees = createBalances(); (await getLogs({ @@ -25,12 +25,13 @@ const graph = (chain: Chain) => { })).map((e: any) => { dailyFees.add(e.signerToken, e.signerAmount.toString() * e.protocolFee.toString() / 10000) }) - return { dailyFees, dailyRevenue: dailyFees, timestamp, }; + return { dailyFees, dailyRevenue: dailyFees, }; } } const adapter: SimpleAdapter = { + version: 2, adapter: { [CHAIN.ETHEREUM]: { fetch: graph(CHAIN.ETHEREUM), diff --git a/fees/alchemix.ts b/fees/alchemix.ts index 1856838bf0..07f9c8daef 100644 --- a/fees/alchemix.ts +++ b/fees/alchemix.ts @@ -1,7 +1,8 @@ -import { Adapter, FetchResultFees } from "../adapters/types"; +import * as sdk from "@defillama/sdk"; +import { Adapter } from "../adapters/types"; import { CHAIN } from "../helpers/chains"; import { request, gql } from "graphql-request"; -import type { ChainBlocks, ChainEndpoints, FetchOptions } from "../adapters/types" +import type { ChainEndpoints, FetchOptions } from "../adapters/types" import { Chain } from '@defillama/sdk/build/general'; interface IData { @@ -11,9 +12,9 @@ interface IData { } const endpoints = { - [CHAIN.ETHEREUM]: "https://api.thegraph.com/subgraphs/name/alchemix-finance/alchemix_v2", - [CHAIN.FANTOM]: "https://api.thegraph.com/subgraphs/name/alchemix-finance/alchemix_v2_ftm", - [CHAIN.OPTIMISM]: "https://api.thegraph.com/subgraphs/name/alchemix-finance/alchemix_v2_optimisim" + [CHAIN.ETHEREUM]: sdk.graph.modifyEndpoint('GJ9CJ66TgbJnXcXGuZiSYAdGNkJBAwqMcKHEvfVmCkdG'), + [CHAIN.FANTOM]: sdk.graph.modifyEndpoint('DezAiEADYFdotrBqB8BqXFMfzCczg7eXMLowvcBvwm9X'), + [CHAIN.OPTIMISM]: sdk.graph.modifyEndpoint('GYBJ8wsQFkSwcgCqhaxnz5RU2VbgedAkWUk2qx9gTnzr') }; const graph = (graphUrls: ChainEndpoints) => { @@ -39,7 +40,7 @@ const graph = (graphUrls: ChainEndpoints) => { }`; return (chain: Chain) => { - return async (timestamp: number, _: ChainBlocks, { createBalances, fromTimestamp, toTimestamp }: FetchOptions): Promise => { + return async ({ createBalances, fromTimestamp, toTimestamp }: FetchOptions) => { const dailyFees = createBalances() const graphRes: IData[] = (await request(graphUrls[chain], graphQuery, { @@ -50,13 +51,14 @@ const graph = (graphUrls: ChainEndpoints) => { graphRes.map((a: IData) => dailyFees.add(a.yieldToken, a.totalHarvested)) const dailyRevenue = dailyFees.clone(0.1) - return { dailyFees, dailyRevenue, timestamp } + return { dailyFees, dailyRevenue } } } }; const adapter: Adapter = { + version: 2, adapter: { // [CHAIN.ETHEREUM]: { // index error // fetch: graph(endpoints)(CHAIN.ETHEREUM), diff --git a/fees/allbridge-classic.ts b/fees/allbridge-classic.ts index 4c810bd5ee..21debfbf6d 100644 --- a/fees/allbridge-classic.ts +++ b/fees/allbridge-classic.ts @@ -86,6 +86,7 @@ const methodology = { }; const adapter: Adapter = { + version: 1, adapter: Object.keys(chainCodeMap).reduce((acc, chain) => { acc[chain] = { fetch: getFeesFunction(chain), diff --git a/fees/allbridge-core.ts b/fees/allbridge-core.ts index 013dd783d7..4085a2afcd 100644 --- a/fees/allbridge-core.ts +++ b/fees/allbridge-core.ts @@ -22,13 +22,19 @@ const lpTokenAddresses: TChainAddress = { '0x4C42DfDBb8Ad654b42F66E0bD4dbdC71B52EB0A6', ], [CHAIN.ARBITRUM]: [ - '0x690e66fc0F8be8964d40e55EdE6aEBdfcB8A21Df' + '0x690e66fc0F8be8964d40e55EdE6aEBdfcB8A21Df', + '0x47235cB71107CC66B12aF6f8b8a9260ea38472c7', ], [CHAIN.AVAX]: [ - '0xe827352A0552fFC835c181ab5Bf1D7794038eC9f' + '0xe827352A0552fFC835c181ab5Bf1D7794038eC9f', + '0x2d2f460d7a1e7a4fcC4Ddab599451480728b5784', + ], + [CHAIN.BASE]: [ + '0xDA6bb1ec3BaBA68B26bEa0508d6f81c9ec5e96d5' ], [CHAIN.OPTIMISM]: [ - '0x3B96F88b2b9EB87964b852874D41B633e0f1f68F' + '0x3B96F88b2b9EB87964b852874D41B633e0f1f68F', + '0xb24A05d54fcAcfe1FC00c59209470d4cafB0deEA', ], [CHAIN.TRON]: [ 'TAC21biCBL9agjuUyzd4gZr356zRgJq61b' @@ -86,7 +92,7 @@ const getTronLogs = async (address: string, eventName: string, minBlockTimestamp return res.data; } -const fetch: any = async (timestamp: number, _: any, options: FetchOptions) => { +const fetch: any = async (options: FetchOptions) => { let dailyFees = await (options.chain === CHAIN.TRON ? fetchFeesTron(options) : fetchFees(options)); const dailyRevenue = dailyFees * 0.2; const dailySupplySideRevenue = dailyFees * 0.8; @@ -94,7 +100,6 @@ const fetch: any = async (timestamp: number, _: any, options: FetchOptions) => { dailyFees, dailyRevenue: dailyRevenue, dailySupplySideRevenue: dailySupplySideRevenue, - timestamp, }; }; @@ -107,6 +112,7 @@ const meta = { }; const adapters: SimpleAdapter = { + version: 2, adapter: { [CHAIN.ETHEREUM]: { fetch, @@ -133,6 +139,11 @@ const adapters: SimpleAdapter = { start: 1698030000, meta, }, + [CHAIN.BASE]: { + fetch, + start: 1706798200, + meta, + }, [CHAIN.OPTIMISM]: { fetch, start: 1702868400, diff --git a/fees/amphor/index.ts b/fees/amphor/index.ts index 4619d92ab3..5f7d28b93c 100644 --- a/fees/amphor/index.ts +++ b/fees/amphor/index.ts @@ -1,59 +1,12 @@ -import ADDRESSES from '../../helpers/coreAssets.json' -import * as sdk from "@defillama/sdk"; -import { ethers, EventFilter } from 'ethers'; - -import { Adapter, FetchResultFees } from "../../adapters/types"; -import { CHAIN } from "../../helpers/chains"; +import { Adapter, FetchOptions, FetchResultV2 } from "../../adapters/types"; import { ETHEREUM } from "../../helpers/chains"; -import { getBlock } from "../../helpers/getBlock"; - -const AmphorILHedgedUSDC_contractAddress: string = '0x3b022EdECD65b63288704a6fa33A8B9185b5096b'; -const AmphorILHedgedWSTETH_contractAddress: string = '0x2791EB5807D69Fe10C02eED6B4DC12baC0701744'; -const AmphorILHedgedWBTC_contractAddress: string = '0xC4A324fDF8a2495776B4d6cA46599B5a52f96489'; - -const contractAbi: ethers.InterfaceAbi = [ - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "timestamp", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "lastSavedBalance", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "returnedAssets", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "fees", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "totalShares", - "type": "uint256" - } - ], - "name": "EpochEnd", - "type": "event" - }, -] +import ADDRESSES from '../../helpers/coreAssets.json'; -const AmphorILHedgedUSDC_contract: ethers.Contract = new ethers.Contract(AmphorILHedgedUSDC_contractAddress, contractAbi); -const AmphorILHedgedWSTETH_contract: ethers.Contract = new ethers.Contract(AmphorILHedgedWSTETH_contractAddress, contractAbi); -const AmphorILHedgedWBTC_contract: ethers.Contract = new ethers.Contract(AmphorILHedgedWBTC_contractAddress, contractAbi); +const AmphorILHedgedWETH_contractAddress: string = '0xcDC51F2B0e5F0906f2fd5f557de49D99c34Df54e'; +const AmphorLRTwstETHVault_contractAddress: string = '0x06824C27C8a0DbDe5F72f770eC82e3c0FD4DcEc3'; +const AmphorPTezETHVault_contractAddress: string = '0xeEE8aED1957ca1545a0508AfB51b53cCA7e3c0d1'; +const AmphorPTrsETHVault_contractAddress: string = '0xB05cABCd99cf9a73b19805edefC5f67CA5d1895E'; +const AmphorPTweETHVault_contractAddress: string = '0xc69Ad9baB1dEE23F4605a82b3354F8E40d1E5966'; const methodology = { UserFees: "Include performance fees.", @@ -61,140 +14,39 @@ const methodology = { ProtocolRevenue: "Share of revenue going to Amphor treasury.", Revenue: "Sum of protocol revenue.", } +const event = 'event EpochEnd(uint256 indexed timestamp,uint256 lastSavedBalance,uint256 returnedAssets,uint256 fees,uint256 totalShares)' +const addresss: string[] = [ + AmphorILHedgedWETH_contractAddress, + AmphorLRTwstETHVault_contractAddress, + AmphorPTezETHVault_contractAddress, + AmphorPTrsETHVault_contractAddress, + AmphorPTweETHVault_contractAddress +] +const data = async (options: FetchOptions): Promise => { + const logs = (await options.getLogs({ + targets: addresss, + eventAbi: event, + flatten: true + })) -interface ILog { - address: string; - data: string; - transactionHash: string; - topics: string[]; -} - -const data = async (timestamp: number): Promise => { - const toTimestamp = timestamp; - const fromTimestamp = timestamp - 60 * 60 * 24; - const toBlock = await getBlock(toTimestamp, CHAIN.ETHEREUM, {}); - - const eventFilterUSDC: EventFilter = { - address: AmphorILHedgedUSDC_contractAddress, - topics: [ethers.id('EpochEnd(uint256,uint256,uint256,uint256,uint256)')] - }; - const eventFilterWSTETH: EventFilter = { - address: AmphorILHedgedWSTETH_contractAddress, - topics: [ethers.id('EpochEnd(uint256,uint256,uint256,uint256,uint256)')] - }; - const eventFilterWBTC: EventFilter = { - address: AmphorILHedgedWBTC_contractAddress, - topics: [ethers.id('EpochEnd(uint256,uint256,uint256,uint256,uint256)')] - }; - - const eventsUSDC = (await sdk.getEventLogs({ - target: AmphorILHedgedUSDC_contractAddress, - topics: eventFilterUSDC.topics as string[], - fromBlock: 18299242, - toBlock: toBlock, - chain: CHAIN.ETHEREUM, - })) as ethers.Log[]; - - const eventsWSTETH = (await sdk.getEventLogs({ - target: AmphorILHedgedWSTETH_contractAddress, - topics: eventFilterWSTETH.topics as string[], - fromBlock: 18535914, - toBlock: toBlock, - chain: CHAIN.ETHEREUM, - })) as ethers.Log[]; - - const eventsWBTC = (await sdk.getEventLogs({ - target: AmphorILHedgedWBTC_contractAddress, - topics: eventFilterWBTC.topics as string[], - fromBlock: 18535914, - toBlock: toBlock, - chain: CHAIN.ETHEREUM, - })) as ethers.Log[]; - - let totalRevenueUSDC = BigInt(0); - let totalFeesUSDC = BigInt(0); - let totalRevenueWSTETH = BigInt(0); - let totalFeesWSTETH = BigInt(0); - let totalRevenueWBTC = BigInt(0); - let totalFeesWBTC = BigInt(0); - - let dailyFeesUSDC = BigInt(0); - let dailyFeesWSTETH = BigInt(0); - let dailyFeesWBTC = BigInt(0); - let dailyRevenueUSDC = BigInt(0); - let dailyRevenueWSTETH = BigInt(0); - let dailyRevenueWBTC = BigInt(0); - - - eventsUSDC.forEach(res => { - const event = AmphorILHedgedUSDC_contract.interface.parseLog(res as any); - totalRevenueUSDC += BigInt(event!.args.returnedAssets) - BigInt(event!.args.lastSavedBalance) - totalFeesUSDC += BigInt(event!.args.fees) - if (event!.args.timestamp > fromTimestamp && event!.args.timestamp < toTimestamp) { - dailyFeesUSDC += BigInt(event!.args.fees) - dailyRevenueUSDC = BigInt(event!.args.returnedAssets) - BigInt(event!.args.lastSavedBalance) - } - }); - - eventsWSTETH.forEach(res => { - const event = AmphorILHedgedWSTETH_contract.interface.parseLog(res as any); - totalRevenueWSTETH += BigInt(event!.args.returnedAssets) - BigInt(event!.args.lastSavedBalance) - totalFeesWSTETH += BigInt(event!.args.fees) - if (event!.args.timestamp > fromTimestamp && event!.args.timestamp < toTimestamp) { - dailyFeesWSTETH += BigInt(event!.args.fees) - dailyRevenueWSTETH = BigInt(event!.args.returnedAssets) - BigInt(event!.args.lastSavedBalance) - } - }); - - eventsWBTC.forEach(res => { - const event = AmphorILHedgedWBTC_contract.interface.parseLog(res as any); - totalRevenueWBTC = totalRevenueWBTC + BigInt(event!.args.returnedAssets) - BigInt(event!.args.lastSavedBalance) - totalFeesWBTC = totalFeesWBTC + BigInt(event!.args.fees) - if (event!.args.timestamp > fromTimestamp && event!.args.timestamp < toTimestamp) { - dailyFeesWBTC += BigInt(event!.args.fees) - dailyRevenueWBTC = BigInt(event!.args.returnedAssets) - BigInt(event!.args.lastSavedBalance) - } - }); + const dailyFees = options.createBalances() + const dailyRevenue = options.createBalances() const TOKENS = { - USDC: ADDRESSES.ethereum.USDC, - WSTETH: ADDRESSES.ethereum.WSTETH, - WBTC: ADDRESSES.ethereum.WBTC, + WETH: ADDRESSES.ethereum.WETH, } - const totalFees = new sdk.Balances({ chain: CHAIN.ETHEREUM, timestamp: toTimestamp }); - const totalRevenue = new sdk.Balances({ chain: CHAIN.ETHEREUM, timestamp: toTimestamp }); - const dailyFees = new sdk.Balances({ chain: CHAIN.ETHEREUM, timestamp: toTimestamp }); - const dailyRevenue = new sdk.Balances({ chain: CHAIN.ETHEREUM, timestamp: toTimestamp }); - - totalFees.add(TOKENS.USDC, totalFeesUSDC.toString()); - totalFees.add(TOKENS.WSTETH, totalFeesWSTETH.toString()); - totalFees.add(TOKENS.WBTC, totalFeesWBTC.toString()); - - totalRevenue.add(TOKENS.USDC, totalRevenueUSDC.toString()); - totalRevenue.add(TOKENS.WSTETH, totalRevenueWSTETH.toString()); - totalRevenue.add(TOKENS.WBTC, totalRevenueWBTC.toString()); - dailyFees.add(TOKENS.USDC, dailyFeesUSDC.toString()); - dailyFees.add(TOKENS.WSTETH, dailyFeesWSTETH.toString()); - dailyFees.add(TOKENS.WBTC, dailyFeesWBTC.toString()); - - dailyRevenue.add(TOKENS.USDC, dailyRevenueUSDC.toString()); - dailyRevenue.add(TOKENS.WSTETH, dailyRevenueWSTETH.toString()); - dailyRevenue.add(TOKENS.WBTC, dailyRevenueWBTC.toString()); - - - const totalFeesNumber = Number(await totalFees.getUSDValue()).toFixed(0); - const dailyRevenueNumber = Number(await dailyRevenue.getUSDValue()).toFixed(0); + logs.forEach((log) => { + dailyFees.add(TOKENS.WETH, log.fees) + if (log.fees > 0) { + dailyRevenue.add(TOKENS.WETH, log.returnedAssets - log.lastSavedBalance) + } + }) return { - timestamp: timestamp, - totalFees: totalFeesNumber, - totalRevenue: Number(await totalRevenue.getUSDValue()).toFixed(0), - totalProtocolRevenue: totalFeesNumber, - totalUserFees: totalFeesNumber, - dailyFees: Number(await dailyFees.getUSDValue()).toFixed(0), - dailyProtocolRevenue: dailyRevenueNumber, - dailyRevenue: dailyRevenueNumber, - }; + dailyFees, + dailyRevenue, + dailyProtocolRevenue: dailyFees, + } } const adapter: Adapter = { @@ -206,7 +58,8 @@ const adapter: Adapter = { methodology } } - } + }, + version: 2 } export default adapter; diff --git a/fees/angle/index.ts b/fees/angle/index.ts index a552a5da26..3ab63cb28e 100644 --- a/fees/angle/index.ts +++ b/fees/angle/index.ts @@ -1,4 +1,4 @@ -import { SimpleAdapter } from "../../adapters/types"; +import { FetchOptions, SimpleAdapter } from "../../adapters/types"; import { CHAIN } from "../../helpers/chains"; import { request, gql } from "graphql-request"; import { getTimestampAtStartOfPreviousDayUTC, getTimestampAtStartOfDayUTC } from "../../utils/date"; @@ -201,20 +201,15 @@ function aggregateFee( const graph = (graphUrls: ChainEndpoint) => { return (chain: CHAIN) => { - return async (timestamp: number) => { - - const todayTimestamp = getTimestampAtStartOfDayUTC(timestamp) - const yesterdayTimestamp = getTimestampAtStartOfPreviousDayUTC(timestamp) - - const borrowFees = await getBorrowFees(graphUrls[chain] as string, todayTimestamp, yesterdayTimestamp); - const coreFees = await getCoreFees(graphUrls[chain] as string, todayTimestamp, yesterdayTimestamp); - const veANGLEInterest = await getVEANGLERevenues(graphUrls[chain] as string, todayTimestamp); + return async ({ endTimestamp, startTimestamp }: FetchOptions) => { + const borrowFees = await getBorrowFees(graphUrls[chain] as string, endTimestamp, startTimestamp); + const coreFees = await getCoreFees(graphUrls[chain] as string, endTimestamp, startTimestamp); + const veANGLEInterest = await getVEANGLERevenues(graphUrls[chain] as string, endTimestamp); const total = aggregateFee("totalFees", coreFees, borrowFees); const daily = aggregateFee("deltaFees", coreFees, borrowFees); return { - timestamp, totalFees: (total.totalFees + veANGLEInterest.totalInterest).toString(), dailyFees: (daily.totalFees + veANGLEInterest.deltaInterest).toString(), totalRevenue: (total.totalRevenue + veANGLEInterest.totalInterest).toString(), @@ -246,7 +241,8 @@ const adapter: SimpleAdapter = { fetch: graph(endpoints)(CHAIN.POLYGON), start: 1672531200, }, - } + }, + version: 2 } export default adapter; diff --git a/fees/apeswap.ts b/fees/apeswap.ts index ec4c173b4f..ba0eecb90f 100644 --- a/fees/apeswap.ts +++ b/fees/apeswap.ts @@ -85,7 +85,8 @@ const baseAdapter: BaseAdapter = { } const adapter: Adapter = { - adapter: baseAdapter + adapter: baseAdapter, + version: 1, }; diff --git a/fees/apex-omni.ts b/fees/apex-omni.ts new file mode 100644 index 0000000000..f5180359be --- /dev/null +++ b/fees/apex-omni.ts @@ -0,0 +1,30 @@ +import { FetchOptions, FetchResultFees, SimpleAdapter } from "../adapters/types" +import { CHAIN } from "../helpers/chains"; +import { getTimestampAtStartOfDayUTC } from "../utils/date" +import fetchURL, { httpGet } from "../utils/fetchURL" + + +interface IFees { + feeOfDate: string; +} +const fees = async (_:any, _b: any, options: FetchOptions): Promise => { + const todaysTimestamp = getTimestampAtStartOfDayUTC(options.startOfDay) * 1000; + const url = `https://omni.apex.exchange/api/v3/data/fee-by-date?time=${todaysTimestamp}`; + const feesData: IFees = (await httpGet(url, { timeout: 10000 })).data; + const dailyFees = feesData?.feeOfDate || '0'; + return { + dailyFees: dailyFees, + dailyUserFees: dailyFees, + timestamp: todaysTimestamp + } +} +const adapter: SimpleAdapter = { + version: 1, + adapter: { + [CHAIN.ETHEREUM]: { + fetch: fees, + start: 1693440000, + } + } +} +export default adapter; diff --git a/fees/apex.ts b/fees/apex.ts index 49d35f0fad..1f2d294ba5 100644 --- a/fees/apex.ts +++ b/fees/apex.ts @@ -19,6 +19,7 @@ const fees = async (timestamp: number): Promise => { } } const adapter: SimpleAdapter = { + version: 1, adapter: { [CHAIN.ETHEREUM]: { fetch: fees, diff --git a/fees/apexdefi/index.ts b/fees/apexdefi/index.ts new file mode 100644 index 0000000000..f349893672 --- /dev/null +++ b/fees/apexdefi/index.ts @@ -0,0 +1,104 @@ +import { Chain } from "@defillama/sdk/build/general"; +import { Adapter, FetchOptions } from "../../adapters/types"; +import { CHAIN } from "../../helpers/chains"; + +const abis = { + allTokens: "address[]:getAllTokens", +}; + +type TAddress = { + [s: string | Chain]: string; +}; + +type Swap = { + sender: string; + amountTokenIn: string; + amountNativeIn: string; + amountTokenOut: string; + amountNativeOut: string; + flashSwap: boolean; +}; + +const methodology = { + Fees: "Swap fees paid by users of 0.03%", + UserFees: "Swap fees paid by users of 0.03%", + Revenue: "30% of collected swap fees", + ProtocolRevenue: "30% of collected swap fees", + SupplySideRevenue: + "70% of collected swap fees are distributed to liquidity providers", +}; + +const FACTORIES: TAddress = { + [CHAIN.AVAX]: "0x3D193de151F8e4e3cE1C4CB2977F806663106A87", + [CHAIN.BASE]: "0x4ccf7aa5736c5e8b6da5234d1014b5019f50cb56", + [CHAIN.ETHEREUM]: "0x820c889D5749847217599B43ab86FcC91781019f", +}; + +const scaleFactor = BigInt(10000); +const factoryFee = BigInt(10); // 0.1% +const lpFee = BigInt(20); // 0.2% + +const fetch = async (options: FetchOptions) => { + const dailyFees = options.createBalances(); + const dailySupplySideRevenue = options.createBalances(); + const dailyProtocolRevenue = options.createBalances(); + const dailyVolume = options.createBalances(); + const totalVolume = options.createBalances(); + + const allTokens = await options.api.call({ + target: FACTORIES[options.chain], + abi: abis.allTokens, + }); + + const logs = await options.getLogs({ + targets: allTokens, + eventAbi: + "event Swap(address indexed sender, uint256 amountTokenIn, uint256 amountNativeIn, uint256 amountTokenOut, uint256 amountNativeOut, bool flashSwap)", + }); + + logs.map((tx: Swap) => { + const nativeAmount = BigInt(tx.amountNativeIn) + BigInt(tx.amountNativeOut); + const fee = (nativeAmount * lpFee) / scaleFactor; + const protocolRevenue = (nativeAmount * factoryFee) / scaleFactor; + dailyFees.addGasToken(fee + protocolRevenue); + dailyProtocolRevenue.addGasToken(protocolRevenue); + dailySupplySideRevenue.addGasToken(fee); + dailyVolume.addGasToken(nativeAmount); + }); + + return { + dailyFees, + dailyVolume, + dailyProtocolRevenue, + dailySupplySideRevenue, + }; +}; + +const adapters: Adapter = { + version: 2, + adapter: { + [CHAIN.AVAX]: { + fetch: fetch, + start: 1716868800, + meta: { + methodology, + }, + }, + [CHAIN.BASE]: { + fetch: fetch, + start: 1716868800, + meta: { + methodology, + }, + }, + [CHAIN.ETHEREUM]: { + fetch: fetch, + start: 1716868800, + meta: { + methodology, + }, + }, + }, +}; + +export default adapters; diff --git a/fees/apollox/index.ts b/fees/apollox/index.ts index 7135baa1f4..641078930b 100644 --- a/fees/apollox/index.ts +++ b/fees/apollox/index.ts @@ -1,19 +1,17 @@ -import { Adapter, ChainEndpoints } from "../../adapters/types"; +import { Adapter } from "../../adapters/types"; import { CHAIN } from "../../helpers/chains"; import { Chain } from "@defillama/sdk/build/general"; import { httpGet } from "../../utils/fetchURL"; -const endpoints = { - [CHAIN.BSC]: "https://www.apollox.finance/bapi/futures/v1/public/future/apx/fee/all", -} +const FeesAndRevenueURL = "https://www.apollox.finance/bapi/futures/v1/public/future/apx/fee/all" -const request = (urls: ChainEndpoints) => { +const request = () => { return (chain: Chain) => { - return async (timestamp: number) => { - const { data } = await httpGet(urls[chain]); + return async () => { + const url = `${FeesAndRevenueURL}?chain=${chain}` + const { data } = await httpGet(url) const { alpFeeVOFor24Hour, allAlpFeeVO } = data return { - timestamp, dailyFees: alpFeeVOFor24Hour.fee || 0, dailyRevenue: alpFeeVOFor24Hour.revenue || 0, totalFees: allAlpFeeVO.fee || 0, @@ -26,9 +24,25 @@ const request = (urls: ChainEndpoints) => { const adapter: Adapter = { adapter: { [CHAIN.BSC]: { - fetch: request(endpoints)(CHAIN.BSC), + runAtCurrTime: true, + fetch: request()(CHAIN.BSC), start: 1689609600, }, + [CHAIN.ARBITRUM]: { + runAtCurrTime: true, + fetch: request()(CHAIN.ARBITRUM), + start: 1689609600, + }, + [CHAIN.OP_BNB]: { + runAtCurrTime: true, + fetch: request()('opbnb'), + start: 1689609600, + }, + [CHAIN.BASE]: { + runAtCurrTime: true, + fetch: request()(CHAIN.BASE), + start: 1689609600, + } } } diff --git a/fees/arbitrum/index.ts b/fees/arbitrum/index.ts index 368d44e73f..c498a1f682 100644 --- a/fees/arbitrum/index.ts +++ b/fees/arbitrum/index.ts @@ -6,7 +6,7 @@ import { queryIndexer } from "../../helpers/indexer"; const adapter: Adapter = { adapter: { [CHAIN.ARBITRUM]: { - fetch: (async (timestamp: number, _: any, options: FetchOptions) => { + fetch: (async (options: FetchOptions) => { const { getFromBlock, getToBlock, createBalances, } = options const startblock = await getFromBlock() const endblock = await getToBlock() @@ -25,21 +25,23 @@ const adapter: Adapter = { ` // const seqGas: number = sequencerGas[0].sum const seqGas: any = await queryIndexer(sequencerGas, options) - const feeQuery = await queryFlipside(`SELECT SUM(TX_FEE) from arbitrum.core.fact_transactions where BLOCK_NUMBER > ${startblock} AND BLOCK_NUMBER < ${endblock}`) + const feeQuery = await queryFlipside(`SELECT SUM(TX_FEE) from arbitrum.core.fact_transactions where BLOCK_NUMBER > ${startblock} AND BLOCK_NUMBER < ${endblock}`, 260) const fees = Number(feeQuery[0][0]) dailyFees.addGasToken(fees * 1e18) dailyRevenue.addGasToken(seqGas[0].sum * -1) dailyRevenue.addGasToken(fees * 1e18) - return { timestamp, dailyFees, dailyRevenue, }; + return { dailyFees, dailyRevenue, }; }) as any, - start: 1628553600 + start: 1628553600, + runAtCurrTime: true, }, }, isExpensiveAdapter: true, - protocolType: ProtocolType.CHAIN + protocolType: ProtocolType.CHAIN, + version: 2 } export default adapter; diff --git a/fees/arrakis-v2/index.ts b/fees/arrakis-v2/index.ts new file mode 100644 index 0000000000..e333f77d32 --- /dev/null +++ b/fees/arrakis-v2/index.ts @@ -0,0 +1,129 @@ +import { Chain } from "@defillama/sdk/build/general"; +import { Adapter, FetchOptions } from "../../adapters/types"; +import { CHAIN } from "../../helpers/chains"; + +type IVault = { + helper: string; + factory: string; +}; + +type IAddress = { + [s: string | Chain]: IVault; +}; + +const abi = { + numVaults: "uint256:numVaults", + vaults: + "function vaults(uint256 startIndex_, uint256 endIndex_) returns (address[] memory)", + token0: "address:token0", + token1: "address:token1", + fees: "function totalUnderlyingWithFees(address vault_) external view returns (uint256 amount0, uint256 amount1, uint256 fee0, uint256 fee1)", +}; + +const contracts: IAddress = { + [CHAIN.ETHEREUM]: { + helper: "0x89E4bE1F999E3a58D16096FBe405Fc2a1d7F07D6", + factory: "0xECb8Ffcb2369EF188A082a662F496126f66c8288", + }, + [CHAIN.POLYGON]: { + helper: "0x89E4bE1F999E3a58D16096FBe405Fc2a1d7F07D6", + factory: "0xECb8Ffcb2369EF188A082a662F496126f66c8288", + }, + [CHAIN.OPTIMISM]: { + helper: "0x89E4bE1F999E3a58D16096FBe405Fc2a1d7F07D6", + factory: "0xECb8Ffcb2369EF188A082a662F496126f66c8288", + }, + [CHAIN.BASE]: { + helper: "0x89E4bE1F999E3a58D16096FBe405Fc2a1d7F07D6", + factory: "0xECb8Ffcb2369EF188A082a662F496126f66c8288", + }, + [CHAIN.ARBITRUM]: { + helper: "0x89E4bE1F999E3a58D16096FBe405Fc2a1d7F07D6", + factory: "0xECb8Ffcb2369EF188A082a662F496126f66c8288", + }, +}; + +async function getVaultsFees( + { api, fromApi, toApi, createBalances }: FetchOptions, + { helper, factory }: IVault +) { + const totalFees = createBalances(); + const dailyFees = createBalances(); + + const limit = await api.call({ target: factory, abi: abi.numVaults }); + const vaults = await api.call({ + target: factory, + abi: abi.vaults, + params: [0, limit], + }); + + const calls = vaults.map((v: string) => ({ target: helper, params: [v] })); + + const [token0s, token1s, prevBals, currBals] = await Promise.all([ + api.multiCall({ calls: vaults, abi: abi.token0, permitFailure: true }), + api.multiCall({ calls: vaults, abi: abi.token1, permitFailure: true }), + fromApi.multiCall({ calls, abi: abi.fees, permitFailure: true }), + toApi.multiCall({ calls, abi: abi.fees, permitFailure: true }), + ]); + + vaults.forEach((_: string, index: number) => { + const token0 = token0s[index]; + const prevFee0 = prevBals[index]?.fee0 ?? 0; + const currFee0 = currBals[index].fee0; + + const token1 = token1s[index]; + const prevFee1 = prevBals[index]?.fee1 ?? 0; + const currFee1 = currBals[index].fee1; + + if (token0 && prevFee0 && currFee0) { + totalFees.add(token0, currFee0); + const dailyFee0 = BigInt(currFee0) - BigInt(prevFee0); + if (dailyFee0 >= 0) { + dailyFees.add(token0, dailyFee0); + } + } + + if (token1 && prevFee1 && currFee1) { + totalFees.add(token1, currFee1); + const dailyFee1 = BigInt(currFee1) - BigInt(prevFee1); + if (dailyFee1 >= 0) { + dailyFees.add(token1, dailyFee1); + } + } + }); + + return { totalFees, dailyFees }; +} + +const adapter: Adapter = { + adapter: { + [CHAIN.ETHEREUM]: { + fetch: (options: FetchOptions) => + getVaultsFees(options, contracts[CHAIN.ETHEREUM]), + start: 1693039022, + }, + // [CHAIN.POLYGON]: { + // fetch: (options: FetchOptions) => + // getVaultsFees(options, contracts[CHAIN.POLYGON]), + // start: 1693039022, + // }, + // [CHAIN.OPTIMISM]: { + // fetch: (options: FetchOptions) => + // getVaultsFees(options, contracts[CHAIN.OPTIMISM]), + // start: 1693039022, + // }, + // [CHAIN.BASE]: { + // fetch: (options: FetchOptions) => + // getVaultsFees(options, contracts[CHAIN.BASE]), + // start: 1693039022, + // }, + // [CHAIN.ARBITRUM]: { + // fetch: (options: FetchOptions) => + // getVaultsFees(options, contracts[CHAIN.ARBITRUM]), + // start: 1693039022, + // }, + }, + version: 2, +}; + +export default adapter; diff --git a/fees/ascent-v2.ts b/fees/ascent-v2.ts index fa09603625..532a45c055 100644 --- a/fees/ascent-v2.ts +++ b/fees/ascent-v2.ts @@ -1,9 +1,7 @@ import BigNumber from "bignumber.js"; import request, { gql } from "graphql-request"; -import { FetchResultFees, SimpleAdapter } from "../adapters/types"; +import { FetchOptions, FetchResultFees, SimpleAdapter } from "../adapters/types"; import { CHAIN } from "../helpers/chains"; -import { getTimestampAtStartOfDayUTC } from "../utils/date"; -import { getBlock } from "../helpers/getBlock"; const STABLE_FEES = 0.0001; const VOLATILE_FEES = 0.002; @@ -20,21 +18,17 @@ interface IGraphResponse { yesterday: IPair[]; } const getFees = () => { - return async (timestamp: number): Promise => { - const todaysTimestamp = getTimestampAtStartOfDayUTC(timestamp); - const fromTimestamp = todaysTimestamp - 60 * 60 * 24 - const toTimestamp = todaysTimestamp - const todaysBlock = await getBlock(toTimestamp, CHAIN.EON, {}); - const yesterdaysBlock = await getBlock(fromTimestamp, CHAIN.EON, {}); + return async ({ getFromBlock, getToBlock}: FetchOptions) => { + const [fromBlock, toBlock] = await Promise.all([getFromBlock(), getToBlock()]) const query = gql` query fees { - yesterday: pairs(block: {number: ${yesterdaysBlock}}, where: {volumeUSD_gt: "0"}, first: 1000) { + yesterday: pairs(block: {number: ${fromBlock}}, where: {volumeUSD_gt: "0"}, first: 1000) { id isStable volumeUSD } - today: pairs(block: {number: ${todaysBlock}}, where: {volumeUSD_gt: "0"}, first: 1000) { + today: pairs(block: {number: ${toBlock}}, where: {volumeUSD_gt: "0"}, first: 1000) { id isStable volumeUSD @@ -61,7 +55,6 @@ const getFees = () => { const dailyFee = totalFeesToday.minus(totalFeesYesterday); return { - timestamp, dailyFees: dailyFee.toString(), dailyUserFees: dailyFee.toString(), dailyRevenue: dailyFee.multipliedBy(0.32).toString(), @@ -71,6 +64,7 @@ const getFees = () => { const adapter: SimpleAdapter = { + version: 2, adapter: { [CHAIN.EON]: { fetch: getFees(), diff --git a/fees/ascent-v3.ts b/fees/ascent-v3.ts index 8a80a3c633..e180221f6a 100644 --- a/fees/ascent-v3.ts +++ b/fees/ascent-v3.ts @@ -1,18 +1,8 @@ import { Chain } from "@defillama/sdk/build/general"; - import { SimpleAdapter } from "../adapters/types"; import { CHAIN } from "../helpers/chains"; -import { - DEFAULT_DAILY_VOLUME_FACTORY, - DEFAULT_TOTAL_VOLUME_FIELD, -} from "../helpers/getUniSubgraphVolume"; - -import { getGraphDimensions } from "../helpers/getUniSubgraph"; - -interface IPoolData { - id: number; - feesUSD: string; -} +import { DEFAULT_TOTAL_VOLUME_FIELD } from "../helpers/getUniSubgraphVolume"; +import { getGraphDimensions2 } from "../helpers/getUniSubgraph"; type IURL = { [l: string | Chain]: string; @@ -23,20 +13,12 @@ const endpoints: IURL = { "https://eon-graph.horizenlabs.io/subgraphs/name/surfacing8671/v3AscentFull2", }; -const v3Graphs = getGraphDimensions({ +const v3Graphs = getGraphDimensions2({ graphUrls: endpoints, totalVolume: { factory: "factories", field: DEFAULT_TOTAL_VOLUME_FIELD, }, - dailyVolume: { - factory: "pancakeDayData", - field: "volumeUSD", - }, - dailyFees: { - factory: "pancakeDayData", - field: "feesUSD", - }, feesPercent: { type: "fees", ProtocolRevenue: 32, @@ -45,6 +27,7 @@ const v3Graphs = getGraphDimensions({ }); const adapter: SimpleAdapter = { + version: 2, adapter: { [CHAIN.EON]: { fetch: v3Graphs(CHAIN.EON), diff --git a/fees/ash-perp/index.ts b/fees/ash-perp/index.ts new file mode 100644 index 0000000000..8213844233 --- /dev/null +++ b/fees/ash-perp/index.ts @@ -0,0 +1,39 @@ +import { Adapter, FetchOptions } from "../../adapters/types"; +import { CHAIN } from "../../helpers/chains"; +import request from "graphql-request"; + +const API_URL = 'https://statistic-api.ashperp.trade/graphql'; + +const fetch = async ({ endTimestamp, startTimestamp}: FetchOptions) => { + const feeQuery =`query Trading { + trading { + getDailyFee(from: ${startTimestamp}, to: ${endTimestamp}){ + daily_fees + daily_holders_revenue + daily_protocol_revenue + } + } + }`; + + const dailyFee = (await request(API_URL, feeQuery)); + const dailyRevenue = Number(dailyFee.trading.getDailyFee.daily_holders_revenue) + Number(dailyFee.trading.getDailyFee.daily_protocol_revenue); + return { + dailyFees: `${dailyFee.trading.getDailyFee.daily_fees}`, + dailyRevenue: `${dailyRevenue}`, + dailyHoldersRevenue: `${dailyFee.trading.getDailyFee.daily_holders_revenue}`, + dailyProtocolRevenue: `${dailyFee.trading.getDailyFee.daily_protocol_revenue}`, + }; + }; + +const adapter: Adapter = { + adapter: { + [CHAIN.ELROND]: { + fetch, + start: 1706745600, + runAtCurrTime: true, + } + }, + isExpensiveAdapter: true, + version: 2 +}; +export default adapter; diff --git a/fees/aura.ts b/fees/aura.ts index 46f0ee67d6..b1bd08e48d 100644 --- a/fees/aura.ts +++ b/fees/aura.ts @@ -4,7 +4,7 @@ import { queryIndexer } from "../helpers/indexer"; const BAL_TOKEN = '0xba100000625a3754423978a60c9317c58a424e3D'; -const fetch = async (timestamp: number, _: any, options: FetchOptions): Promise => { +const fetch = async (options: FetchOptions) => { const dailyFees = options.createBalances(); @@ -77,10 +77,11 @@ const fetch = async (timestamp: number, _: any, options: FetchOptions): Promise< const dailyHoldersRevenue = dailyFees.clone(); dailyHoldersRevenue.resizeBy(0.04); - return { timestamp, dailyFees, dailyRevenue, dailySupplySideRevenue, dailyHoldersRevenue, } + return { dailyFees, dailyRevenue, dailySupplySideRevenue, dailyHoldersRevenue, } } const adapter: Adapter = { + version: 2, adapter: { [CHAIN.ETHEREUM]: { fetch: fetch as any, diff --git a/fees/auragi.ts b/fees/auragi.ts index a8b1910c57..bf79192214 100644 --- a/fees/auragi.ts +++ b/fees/auragi.ts @@ -1,33 +1,25 @@ +import * as sdk from "@defillama/sdk"; import request, { gql } from "graphql-request"; -import { Adapter } from "../adapters/types"; -import { getBlock } from "../helpers/getBlock"; -import {getTimestampAtStartOfDayUTC, getTimestampAtStartOfPreviousDayUTC} from "../utils/date"; +import { Adapter, FetchOptions } from "../adapters/types"; import BigNumber from "bignumber.js"; import { CHAIN } from "../helpers/chains"; const STABLE_FEES = 0.0001; const VOLATILE_FEES = 0.0005; -const endpoint = "https://api.thegraph.com/subgraphs/name/oxbill/auragi"; +const endpoint = sdk.graph.modifyEndpoint('DtNQcRXx82k4azEb5QvUjRbmXSNLTUsUePzPY6PtryEc'); const getFees = () => { - return async (timestamp: number) => { - const todaysTimestamp = getTimestampAtStartOfDayUTC(timestamp); - const yesterdaysTimestamp = getTimestampAtStartOfPreviousDayUTC(timestamp); - const todaysBlock = await getBlock( - todaysTimestamp, - CHAIN.ARBITRUM, - {} - ); - const yesterdaysBlock = await getBlock(yesterdaysTimestamp, CHAIN.ARBITRUM, {}); - + return async ({ getFromBlock, getToBlock}: FetchOptions) => { + const [fromBlock, toBlock] = await Promise.all([getFromBlock(), getToBlock()]) + const query = gql` query fees { - yesterday: pairs(block: {number: ${yesterdaysBlock}}, where: {volumeUSD_gt: "0"}, first: 1000) { + yesterday: pairs(block: {number: ${fromBlock}}, where: {volumeUSD_gt: "0"}, first: 1000) { id isStable volumeUSD } - today: pairs(block: {number: ${todaysBlock}}, where: {volumeUSD_gt: "0"}, first: 1000) { + today: pairs(block: {number: ${toBlock}}, where: {volumeUSD_gt: "0"}, first: 1000) { id isStable volumeUSD @@ -54,7 +46,6 @@ const getFees = () => { } return { - timestamp, dailyFees: dailyFee.toString(), dailyRevenue: dailyFee.toString(), dailyHoldersRevenue: dailyFee.toString(), @@ -63,6 +54,7 @@ const getFees = () => { }; const adapter: Adapter = { + version: 2, adapter: { [CHAIN.ARBITRUM]: { fetch: getFees(), diff --git a/fees/avalanche.ts b/fees/avalanche.ts index 3f3070a647..cc9967ae88 100644 --- a/fees/avalanche.ts +++ b/fees/avalanche.ts @@ -1,15 +1,15 @@ -import { Adapter, ChainBlocks, FetchOptions, ProtocolType } from "../adapters/types"; +import { Adapter, FetchOptions, ProtocolType } from "../adapters/types"; import { CHAIN } from "../helpers/chains"; import { getTokenDiff } from "../helpers/token"; const adapter: Adapter = { + version: 2, adapter: { [CHAIN.AVAX]: { - fetch: async (timestamp: number, _: ChainBlocks, options: FetchOptions) => { + fetch: async (options: FetchOptions) => { const dailyFees = await getTokenDiff({ target: '0x0100000000000000000000000000000000000000', includeGasToken: true, options}) return { - timestamp, dailyFees: dailyFees, dailyRevenue: dailyFees, dailyHoldersRevenue: dailyFees, diff --git a/fees/avantis/index.ts b/fees/avantis/index.ts new file mode 100644 index 0000000000..628801ff67 --- /dev/null +++ b/fees/avantis/index.ts @@ -0,0 +1,62 @@ +import { Chain } from "@defillama/sdk/build/general"; +import { CHAIN } from "../../helpers/chains"; +import { SimpleAdapter } from "../../adapters/types"; +import fetchURL from "../../utils/fetchURL"; +import { getTimestampAtStartOfDayUTC } from "../../utils/date"; +import { FetchResultFees } from "../../adapters/types"; + +interface IData { + success: boolean; + cumulativeFee: number; + history: { + date: string; + totalFees: number; + cumulativeFee: number; + totalClosingFee: number; + totalOpeningFee: number; + totalRolloverFee: number; + }[]; +} + +const API_URL = "https://api.avantisfi.com/v1"; + +const fetchData = (_: Chain) => { + return async (timestamp: number): Promise => { + const todaysTimestamp = getTimestampAtStartOfDayUTC(timestamp); + + // Convert timestamp to Date object and format to YYYY-MM-DD in UTC + const date = new Date(todaysTimestamp * 1000); + const dateStr = date.toISOString().split("T")[0]; + + // Find difference in days between today and the timestamp + const today = new Date(); + const diffTime = Math.abs(today.getTime() - date.getTime()); + const diffDays = Math.ceil(diffTime / (1000 * 60 * 60 * 24)); + + const url = `${API_URL}/history/analytics/total-fees/${diffDays}`; + const value: IData = await fetchURL(url); + if (!value.success) throw new Error("Failed to fetch data"); + + const dailyFee = value.history.find((d) => d.date === dateStr)?.totalFees; + const totalFees = value.history[value.history.length - 1]?.cumulativeFee; + return { + dailyUserFees: dailyFee ? `${dailyFee}` : undefined, + dailyFees: dailyFee ? `${dailyFee}` : undefined, + totalFees: totalFees ? `${totalFees}` : undefined, + totalUserFees: totalFees ? `${totalFees}` : undefined, + timestamp: todaysTimestamp, + }; + }; +}; + +const adapter: SimpleAdapter = { + adapter: { + [CHAIN.BASE]: { + fetch: fetchData(CHAIN.BASE), + start: 1706313600, + }, + }, + version: 1 +}; + +export default adapter; diff --git a/fees/azuro/index.ts b/fees/azuro/index.ts index 4ec5eea09a..cd9ac855fc 100644 --- a/fees/azuro/index.ts +++ b/fees/azuro/index.ts @@ -1,150 +1,119 @@ -import {Adapter, ChainEndpoints, FetchResultFees} from "../../adapters/types"; -import {CHAIN} from "../../helpers/chains"; -import {Bet, BetResult} from "./types"; -import {Chain} from "@defillama/sdk/build/general"; -import {request, gql} from "graphql-request"; -import {getTimestampAtStartOfDayUTC} from "../../utils/date"; +import { Adapter, ChainEndpoints, FetchOptions } from "../../adapters/types"; +import { CHAIN } from "../../helpers/chains"; +import { Bet, BetResult } from "./types"; +import { Chain } from "@defillama/sdk/build/general"; +import { request, gql } from "graphql-request"; -const endpoints = { +const endpoints: ChainEndpoints = { [CHAIN.POLYGON]: "https://thegraph.azuro.org/subgraphs/name/azuro-protocol/azuro-api-polygon-v3", [CHAIN.XDAI]: "https://thegraph.azuro.org/subgraphs/name/azuro-protocol/azuro-api-gnosis-v3", [CHAIN.ARBITRUM]: "https://thegraph.azuro.org/subgraphs/name/azuro-protocol/azuro-api-arbitrum-one-v3", - [CHAIN.LINEA]: "https://thegraph.bookmaker.xyz/subgraphs/name/azuro-protocol/azuro-api-linea-v3" -} -type IStart = { - [s: string | Chain]: number -} -const getStartTimestamp: IStart = { + [CHAIN.LINEA]: "https://thegraph.bookmaker.xyz/subgraphs/name/azuro-protocol/azuro-api-linea-v3", + [CHAIN.CHILIZ]: "https://thegraph.bookmaker.xyz/subgraphs/name/azuro-protocol/azuro-api-chiliz-v3" +}; + +const getStartTimestamp: { [chain: string]: number } = { [CHAIN.POLYGON]: 1675209600, [CHAIN.XDAI]: 1654646400, [CHAIN.ARBITRUM]: 1686009600, - [CHAIN.LINEA]: 1691452800 -} - -const graphs = (graphUrls: ChainEndpoints) => { - return (chain: Chain) => { - return async (timestamp: number): Promise => { - const todaysTimestamp = getTimestampAtStartOfDayUTC(timestamp) - const fromTimestamp = todaysTimestamp - 60 * 60 * 24 - const toTimestamp = todaysTimestamp - const bets: Bet[] = [] - const total_bets: Bet[] = [] - let skip = 0 - - while (true) { - const graphQuery = gql` - { - bets( - where: { - status: Resolved, - _isFreebet: false - resolvedBlockTimestamp_gte: ${fromTimestamp}, - resolvedBlockTimestamp_lte: ${toTimestamp}, - } - first: 1000, - skip: ${skip} - ) { - amount - odds - result - } - } - `; - const graphRes = await request(graphUrls[chain], graphQuery); - - bets.push(...graphRes.bets) - skip += 1000 + [CHAIN.LINEA]: 1691452800, + [CHAIN.CHILIZ]: 1716422400 +}; - if (graphRes.bets.length < 1000) break +const fetchBets = async (url: string, from: number, to: number, skip: number, live = false): Promise => { + const query = gql` + { + ${live ? 'liveBets' : 'bets'}( + where: { + status: Resolved, + _isFreebet: false, + resolvedBlockTimestamp_gte: ${from}, + resolvedBlockTimestamp_lte: ${to} + }, + first: 1000, + skip: ${skip} + ) { + amount + odds + result } + } + `; + const response = await request(url, query); + return response[live ? 'liveBets' : 'bets']; +}; - let skip_total = 0 - while (true) { - const graphQuery = gql` - { - bets( - where: { - status: Resolved, - _isFreebet: false - resolvedBlockTimestamp_gte: ${getStartTimestamp[chain]}, - resolvedBlockTimestamp_lte: ${toTimestamp}, - } - first: 1000, - skip: ${skip_total} - ) { - amount - odds - result - } - } - `; - const graphRes = await request(graphUrls[chain], graphQuery); - - total_bets.push(...graphRes.bets) - skip_total += 1000 - if (graphRes.bets.length < 1000) break - } - const totalBetAmount = total_bets.reduce((e: number, {amount}) => e+Number(amount), 0); - const totalWonAmount = total_bets.filter(({result}) => result === BetResult.Won) - .reduce((e: number, {amount, odds}) => e+Number(amount) * Number(odds), 0); - const totalFees = totalBetAmount - totalWonAmount; +const fetchAllBets = async (url: string, from: number, to: number, live = false): Promise => { + let bets: Bet[] = []; + let skip = 0; + while (true) { + const newBets = await fetchBets(url, from, to, skip, live); + bets = [...bets, ...newBets]; + if (newBets.length < 1000) break; + skip += 1000; + } + return bets; +}; - const dailyBetAmount = bets.reduce((e: number, {amount}) => e+Number(amount), 0) - const dailyWonAmount = bets.filter(({result}) => result === BetResult.Won) - .reduce((e: number, {amount, odds}) => e+Number(amount) * Number(odds), 0) +const calculateAmounts = (bets: Bet[]) => { + const totalBetAmount = bets.reduce((sum, { amount }) => sum + Number(amount), 0); + const totalWonAmount = bets + .filter(({ result }) => result === BetResult.Won) + .reduce((sum, { amount, odds }) => sum + Number(amount) * Number(odds), 0); + return { totalBetAmount, totalWonAmount }; +}; - const totalPoolProfit = dailyBetAmount - dailyWonAmount; - const dailyFees = totalPoolProfit; - const dailyRevenue = totalPoolProfit; +const graphs = (graphUrls: ChainEndpoints) => { + return (chain: Chain) => { + return async ({ endTimestamp, startTimestamp }: FetchOptions) => { + const [bets] = await Promise.all([ + fetchAllBets(graphUrls[chain], startTimestamp, endTimestamp, false), + ]); + const { totalBetAmount: dailyBetAmount, totalWonAmount: dailyWonAmount } = calculateAmounts(bets); + const dailyPoolProfit = dailyBetAmount - dailyWonAmount; return { - timestamp, - dailyFees: dailyFees.toString(), - dailyRevenue: dailyRevenue.toString(), - totalFees: totalFees.toString(), - totalRevenue: totalFees.toString(), + dailyFees: dailyPoolProfit.toString(), + dailyRevenue: dailyPoolProfit.toString() }; - } - } -} + }; + }; +}; const methodology = { Fees: "Total pools profits (equals total bets amount minus total won bets amount)", Revenue: "Total pools profits (equals total bets amount minus total won bets amount)", -} +}; const adapter: Adapter = { adapter: { [CHAIN.POLYGON]: { fetch: graphs(endpoints)(CHAIN.POLYGON), - start: 1675209600, - meta: { - methodology - } + start: getStartTimestamp[CHAIN.POLYGON], + meta: { methodology }, }, [CHAIN.XDAI]: { fetch: graphs(endpoints)(CHAIN.XDAI), - start: 1654646400, - meta: { - methodology - } + start: getStartTimestamp[CHAIN.XDAI], + meta: { methodology }, }, [CHAIN.ARBITRUM]: { fetch: graphs(endpoints)(CHAIN.ARBITRUM), - start: 1686009600, - meta: { - methodology - } + start: getStartTimestamp[CHAIN.ARBITRUM], + meta: { methodology }, }, [CHAIN.LINEA]: { fetch: graphs(endpoints)(CHAIN.LINEA), - start: 1691452800, - meta: { - methodology - } + start: getStartTimestamp[CHAIN.LINEA], + meta: { methodology }, }, - - } -} + [CHAIN.CHILIZ]: { + fetch: graphs(endpoints)(CHAIN.CHILIZ), + start: getStartTimestamp[CHAIN.CHILIZ], + meta: { methodology }, + }, + }, + version: 2 +}; export default adapter; diff --git a/fees/babydogeswap.ts b/fees/babydogeswap.ts index 0ead71e4c5..5ffbc0fb4c 100644 --- a/fees/babydogeswap.ts +++ b/fees/babydogeswap.ts @@ -1,17 +1,14 @@ import { CHAIN } from "../helpers/chains"; -import { univ2DimensionAdapter } from "../helpers/getUniSubgraph"; +import { univ2DimensionAdapter2 } from "../helpers/getUniSubgraph"; // 0.2% to LP providers // 0.05% to treasury // 0.05% to buy back and burn BabyDoge! -const adapters = univ2DimensionAdapter({ +const adapters = univ2DimensionAdapter2({ graphUrls: { [CHAIN.BSC]: "https://graph-bsc-mainnet.babydoge.com/subgraphs/name/babydoge/exchange" }, - dailyVolume: { - factory: "factoryDayData" - }, totalVolume: { factory: "babyDogeFactories" }, @@ -34,5 +31,6 @@ const adapters = univ2DimensionAdapter({ } }); + adapters.adapter.bsc.start = 1661780137; export default adapters; diff --git a/fees/balancer.ts b/fees/balancer.ts index 32af257c3d..3dba5c2166 100644 --- a/fees/balancer.ts +++ b/fees/balancer.ts @@ -1,50 +1,49 @@ +import * as sdk from "@defillama/sdk"; import { Adapter } from "../adapters/types"; import { CHAIN }from "../helpers/chains"; import { request, gql } from "graphql-request"; -import type { ChainEndpoints } from "../adapters/types" +import type { ChainEndpoints, FetchOptions } from "../adapters/types" import { Chain } from '@defillama/sdk/build/general'; -import { getBlock } from "../helpers/getBlock"; -import { ChainBlocks } from "../adapters/types"; import BigNumber from "bignumber.js"; -import { getTimestampAtStartOfPreviousDayUTC, getTimestampAtStartOfDayUTC } from "../utils/date"; +import { getTimestampAtStartOfDay, getTimestampAtStartOfDayUTC } from "../utils/date"; const v1Endpoints = { [CHAIN.ETHEREUM]: - "https://api.thegraph.com/subgraphs/name/balancer-labs/balancer", + sdk.graph.modifyEndpoint('93yusydMYauh7cfe9jEfoGABmwnX4GffHd7in8KJi1XB'), } const v2Endpoints = { [CHAIN.ETHEREUM]: - "https://api.thegraph.com/subgraphs/name/balancer-labs/balancer-v2-beta", + sdk.graph.modifyEndpoint('Fog6Z9z7DXvWy4bx36c7ETQftdtr4Ppxn7Mjpxkzka2i'), [CHAIN.ARBITRUM]: - "https://api.thegraph.com/subgraphs/name/balancer-labs/balancer-arbitrum-v2", + sdk.graph.modifyEndpoint('itkjv6Vdh22HtNEPQuk5c9M3T7VeGLQtXxcH8rFi1vc'), [CHAIN.POLYGON]: - "https://api.thegraph.com/subgraphs/name/balancer-labs/balancer-polygon-v2", + sdk.graph.modifyEndpoint('78nZMyM9yD77KG6pFaYap31kJvj8eUWLEntbiVzh8ZKN'), [CHAIN.AVAX]: - "https://api.thegraph.com/subgraphs/name/balancer-labs/balancer-avalanche-v2", + sdk.graph.modifyEndpoint('7asfmtQA1KYu6CP7YVm5kv4bGxVyfAHEiptt2HMFgkHu'), [CHAIN.XDAI]: - "https://api.thegraph.com/subgraphs/name/balancer-labs/balancer-gnosis-chain-v2", + sdk.graph.modifyEndpoint('EJezH1Cp31QkKPaBDerhVPRWsKVZLrDfzjrLqpmv6cGg'), [CHAIN.BASE]: "https://api.studio.thegraph.com/query/24660/balancer-base-v2/version/latest", [CHAIN.POLYGON_ZKEVM]: "https://api.studio.thegraph.com/query/24660/balancer-polygon-zk-v2/version/latest", + [CHAIN.MODE]: + "https://api.studio.thegraph.com/query/75376/balancer-mode-v2/version/latest", + [CHAIN.FRAXTAL]: + "https://api.goldsky.com/api/public/project_clwhu1vopoigi01wmbn514m1z/subgraphs/balancer-fraxtal-v2/latest/gn" }; const v1Graphs = (graphUrls: ChainEndpoints) => { return (chain: Chain) => { - return async (timestamp: number, chainBlocks: ChainBlocks) => { - const todaysTimestamp = getTimestampAtStartOfDayUTC(timestamp) - const yesterdaysTimestamp = getTimestampAtStartOfPreviousDayUTC(timestamp) - - const todaysBlock = (await getBlock(todaysTimestamp, chain, chainBlocks)); - const yesterdaysBlock = (await getBlock(yesterdaysTimestamp, chain, {})); + return async ({ getFromBlock, getToBlock}: FetchOptions) => { + const [fromBlock, toBlock] = await Promise.all([getFromBlock(), getToBlock()]) const graphQuery = gql `{ - today: balancer(id: "1", block: { number: ${todaysBlock} }) { + today: balancer(id: "1", block: { number: ${toBlock} }) { totalSwapFee } - yesterday: balancer(id: "1", block: { number: ${yesterdaysBlock} }) { + yesterday: balancer(id: "1", block: { number: ${fromBlock} }) { totalSwapFee } }`; @@ -53,7 +52,6 @@ const v1Graphs = (graphUrls: ChainEndpoints) => { const dailyFee = (new BigNumber(graphRes["today"]["totalSwapFee"]).minus(new BigNumber(graphRes["yesterday"]["totalSwapFee"]))) return { - timestamp, totalFees: graphRes["today"]["totalSwapFee"], dailyFees: dailyFee.toString(), totalUserFees: graphRes["today"]["totalSwapFee"], @@ -68,102 +66,80 @@ const v1Graphs = (graphUrls: ChainEndpoints) => { }; }; }; -interface IPool { +interface IBalancer { id: string; - swapFees: string; - protocolFee: string; + totalSwapFee: string; + totalProtocolFee: string; } -interface IPoolSnapshot { - today: IPool[]; - yesterday: IPool[]; +interface IBalancerSnapshot { + today: IBalancer[]; + yesterday: IBalancer[]; tenPcFeeChange: { totalSwapFee: string; + totalProtocolFee: string; timestamp: number; } fiftyPcFeeChange: { totalSwapFee: string; + totalProtocolFee: string; timestamp: number; } } const v2Graphs = (graphUrls: ChainEndpoints) => { return (chain: Chain) => { - return async (timestamp: number) => { - const startTimestamp = getTimestampAtStartOfDayUTC(timestamp) - const fromTimestamp = startTimestamp - 60 * 60 * 24 - const toTimestamp = startTimestamp + return async ({ fromTimestamp, toTimestamp}: FetchOptions) => { + const todayTimestamp = getTimestampAtStartOfDayUTC(toTimestamp); + const yesterdayTimestamp = getTimestampAtStartOfDayUTC(fromTimestamp); const graphQuery = gql `query fees { - today:poolSnapshots(where: {timestamp:${toTimestamp}, protocolFee_gt:0}, orderBy:swapFees, orderDirection: desc) { + today: balancerSnapshots(where: {timestamp:${todayTimestamp}, totalProtocolFee_gt:0}, orderBy: totalProtocolFee, orderDirection: desc) { id - swapFees - protocolFee + totalSwapFee + totalProtocolFee } - yesterday:poolSnapshots(where: {timestamp:${fromTimestamp}, protocolFee_gt:0}, orderBy:swapFees, orderDirection: desc) { + yesterday: balancerSnapshots(where: {timestamp:${yesterdayTimestamp}, totalProtocolFee_gt:0}, orderBy: totalProtocolFee, orderDirection: desc) { id - swapFees - protocolFee + totalSwapFee + totalProtocolFee } tenPcFeeChange: balancerSnapshot(id: "2-18972") { - totalSwapFee timestamp } fiftyPcFeeChange: balancerSnapshot(id: "2-19039") { - totalSwapFee timestamp } }`; - const graphRes: IPoolSnapshot = await request(graphUrls[chain], graphQuery); - const dailyFee = graphRes["today"].map((e: IPool) => { - const yesterdayValue = new BigNumber(graphRes["yesterday"].find((p: IPool) => p.id.split('-')[0] === e.id.split('-')[0])?.swapFees || 0); - if(yesterdayValue.toNumber()) return new BigNumber('0') - return new BigNumber(e.swapFees).minus(yesterdayValue); - }).filter(e => new BigNumber(e).toNumber() < 10000).reduce((a: BigNumber, b: BigNumber) => a.plus(b), new BigNumber('0')) - - - const currentTotalSwapFees = graphRes["today"].map((e: IPool) => new BigNumber(e.swapFees)).reduce((a: BigNumber, b: BigNumber) => a.plus(b), new BigNumber('0')) + const graphRes: IBalancerSnapshot = await request(graphUrls[chain], graphQuery); + let dailySwapFee = new BigNumber(0); + let dailyProtocolFee = new BigNumber(0); + if (graphRes["today"].length > 0 && graphRes["yesterday"].length > 0) { + dailySwapFee = new BigNumber(graphRes["today"][0]["totalSwapFee"]).minus(new BigNumber(graphRes["yesterday"][0]["totalSwapFee"])); + dailyProtocolFee = new BigNumber(graphRes["today"][0]["totalProtocolFee"]).minus(new BigNumber(graphRes["yesterday"][0]["totalProtocolFee"])); + } - let tenPcFeeTimestamp = 0 - let fiftyPcFeeTimestamp = 0 - let tenPcTotalSwapFees = new BigNumber(0) - let fiftyPcTotalSwapFees = new BigNumber(0) + let tenPcFeeTimestamp = 0; + let fiftyPcFeeTimestamp = 0; if (chain === CHAIN.ETHEREUM || chain === CHAIN.POLYGON || chain === CHAIN.ARBITRUM) { tenPcFeeTimestamp = graphRes["tenPcFeeChange"]["timestamp"] fiftyPcFeeTimestamp = graphRes["fiftyPcFeeChange"]["timestamp"] - tenPcTotalSwapFees = new BigNumber(graphRes["tenPcFeeChange"]["totalSwapFee"]) - fiftyPcTotalSwapFees = new BigNumber(graphRes["fiftyPcFeeChange"]["totalSwapFee"]) } // 10% gov vote enabled: https://vote.balancer.fi/#/proposal/0xf6238d70f45f4dacfc39dd6c2d15d2505339b487bbfe014457eba1d7e4d603e3 // 50% gov vote change: https://vote.balancer.fi/#/proposal/0x03e64d35e21467841bab4847437d4064a8e4f42192ce6598d2d66770e5c51ace - const dailyRevenue = startTimestamp < tenPcFeeTimestamp ? "0" : ( - startTimestamp < fiftyPcFeeTimestamp ? dailyFee.multipliedBy(0.1) : dailyFee.multipliedBy(0.5)) - const totalRevenue = startTimestamp < tenPcFeeTimestamp ? "0" : ( - startTimestamp < fiftyPcFeeTimestamp ? currentTotalSwapFees.minus(tenPcTotalSwapFees).multipliedBy(0.1) : currentTotalSwapFees.minus(fiftyPcTotalSwapFees).multipliedBy(0.5)) - - const dailyProtocolFee = graphRes["today"].map((e: IPool) => { - const yesterdayValue = new BigNumber(graphRes["yesterday"].find((p: IPool) => p.id.split('-')[0] === e.id.split('-')[0])?.protocolFee || 0); - if (yesterdayValue.toNumber() === 0) return new BigNumber('0') - return new BigNumber(e.protocolFee).minus(yesterdayValue); - }).filter(e => new BigNumber(e).toNumber() < 10000) - .reduce((a: BigNumber, b: BigNumber) => a.plus(b), new BigNumber('0')) + const dailyFees = toTimestamp < tenPcFeeTimestamp ? "0" : ( + toTimestamp < fiftyPcFeeTimestamp ? dailyProtocolFee.multipliedBy(10) : dailyProtocolFee.multipliedBy(2)) return { - timestamp, - // totalUserFees: currentTotalSwapFees.toString(), - dailyUserFees: dailyFee.toString(), - // totalFees: currentTotalSwapFees.toString(), - dailyFees: dailyFee.toString(), - // totalRevenue: dailyProtocolFee.toString(), // balancer v2 subgraph does not flash loan fees yet - dailyRevenue: dailyProtocolFee.toString(), // balancer v2 subgraph does not flash loan fees yet - // totalProtocolRevenue: totalRevenue.toString(), - dailyProtocolRevenue: dailyRevenue.toString(), - // totalSupplySideRevenue: currentTotalSwapFees.minus(totalRevenue.toString()).toString(), - dailySupplySideRevenue: new BigNumber(dailyFee.toString()).minus(dailyRevenue.toString()).toString(), + dailyUserFees: dailySwapFee.toString(), + dailyFees: dailyFees.toString(), + dailyRevenue: dailyProtocolFee.toString(), + dailyProtocolRevenue: dailyProtocolFee.toString(), + dailySupplySideRevenue: dailySwapFee.toString(), }; }; }; @@ -171,13 +147,14 @@ const v2Graphs = (graphUrls: ChainEndpoints) => { const methodology = { UserFees: "Trading fees paid by users, ranging from 0.0001% to 10%", - Fees: "All trading fees collected (doesn't include withdrawal and flash loan fees)", + Fees: "All trading fees collected (includes swap and yield fee)", Revenue: "Protocol revenue from all fees collected", - ProtocolRevenue: "Set to 10% of collected fees by a governance vote", - SupplySideRevenue: "A small percentage of the trade paid by traders to pool LPs, set by the pool creator or dynamically optimized by Gauntlet", + ProtocolRevenue: "Balancer V2 protocol fees are set to 50%", + SupplySideRevenue: "A small percentage of the trade paid by traders to pool LPs", } const adapter: Adapter = { + version: 2, breakdown: { v1: { [CHAIN.ETHEREUM]: { @@ -186,7 +163,7 @@ const adapter: Adapter = { meta: { methodology: { UserFees: "Trading fees paid by users, ranging from 0.0001% and 10%", - Fees: "All trading fees collected", + Fees: "All trading fees collected (includes swap and yield fee)", Revenue: "Balancer V1 protocol fees are set to 0%", ProtocolRevenue: "Balancer V1 protocol fees are set to 0%", SupplySideRevenue: "Trading fees are distributed among LPs", @@ -243,7 +220,21 @@ const adapter: Adapter = { meta: { methodology } - } + }, + [CHAIN.MODE]: { + fetch: v2Graphs(v2Endpoints)(CHAIN.MODE), + start: 1716336000, + meta: { + methodology + } + }, + [CHAIN.FRAXTAL]: { + fetch: v2Graphs(v2Endpoints)(CHAIN.FRAXTAL), + start: 1716163200, + meta: { + methodology + } + }, } } } diff --git a/fees/banana-gun-trading.ts b/fees/banana-gun-trading.ts index 6d084af7a1..79caf1b7e0 100644 --- a/fees/banana-gun-trading.ts +++ b/fees/banana-gun-trading.ts @@ -1,75 +1,75 @@ -import { FetchOptions, FetchResultFees, SimpleAdapter } from "../adapters/types"; +import { ChainBlocks, FetchOptions, FetchResultFees, SimpleAdapter } from "../adapters/types"; import { CHAIN } from "../helpers/chains"; -import { getTimestampAtStartOfDayUTC } from "../utils/date"; import { queryDune } from "../helpers/dune"; -import { queryIndexer } from "../helpers/indexer"; - -interface IData { - data: string; -} -const fetch: any = async (timestamp: number, _: any, options: FetchOptions): Promise => { - const todaysTimestamp = getTimestampAtStartOfDayUTC(timestamp); - - const deployer = [ - "xf414d478934c29d9a80244a3626c681a71e53bb2", "x37aab97476ba8dc785476611006fd5dda4eed66b" - ].map(i => `'\\${i}'::bytea`).join(', ') - console.log(deployer) - - const transactions = await queryIndexer(` - SELECT - encode(data, 'hex') AS data - FROM - ethereum.event_logs - WHERE - block_number > 17345415 - AND contract_address IN ( - SELECT DISTINCT address - FROM ethereum.traces - WHERE - block_number > 17345415 - AND from_address IN ( ${deployer} ) - AND "type" = 'create' - and address is not null - ) - AND topic_0 = '\\x72015ace03712f361249380657b3d40777dd8f8a686664cab48afd9dbbe4499f' - AND block_time BETWEEN llama_replace_date_range; - `, options) - const dailyFees = options.createBalances(); - transactions.map((e: any) => { - dailyFees.addGasToken(Number('0x' + e.data.slice(0, 64))); - }) - return { dailyFees, dailyRevenue: dailyFees, timestamp } - -} - -const fethcFeesSolana = async (timestamp: number): Promise => { - const todaysTimestamp = getTimestampAtStartOfDayUTC(timestamp); +const fethcFeesSolana = async (options: FetchOptions) => { try { - const value = await queryDune("3410455", { endTime: todaysTimestamp + 86400 }); + const dailyFees = options.createBalances(); + const dailyRevenue = options.createBalances(); + const value = (await queryDune("3521814", { + start: options.startTimestamp, + end: options.endTimestamp, + receiver: '47hEzz83VFR23rLTEeVm9A7eFzjJwjvdupPPmX3cePqF' + })); + dailyFees.add('So11111111111111111111111111111111111111112', value[0].fee_token_amount); + dailyRevenue.add('So11111111111111111111111111111111111111112', value[0].fee_token_amount); return { - dailyFees: value[0]?.fees_usd || "0", - timestamp + dailyFees: dailyFees, + dailyRevenue: dailyRevenue, } } catch (error: any) { + console.error('Error fetching fees for Solana', error); return { dailyFees: "0", - timestamp } } } +const contract_address: any = { + [CHAIN.BLAST]: '0x461efe0100be0682545972ebfc8b4a13253bd602', + [CHAIN.BASE]: '0x1fba6b0bbae2b74586fba407fb45bd4788b7b130', + [CHAIN.ETHEREUM]: '0x3328f7f4a1d1c57c35df56bbf0c9dcafca309c49', +} + +const fetchFees = async (options: FetchOptions) => { + const dailyFees = options.createBalances(); + const dailyRevenue = options.createBalances(); + const logs = await options.getLogs({ + topic: '0x72015ace03712f361249380657b3d40777dd8f8a686664cab48afd9dbbe4499f', + target: contract_address[options.chain], + }); + logs.map((log: any) => { + const data = log.data.replace('0x', ''); + const gasToken = data.slice(0, 64); + dailyFees.addGasToken(Number('0x' + gasToken)); + dailyRevenue.addGasToken(Number('0x' + gasToken)); + }); + return { + dailyFees: dailyFees, + dailyRevenue: dailyRevenue, + } +} + const adapter: SimpleAdapter = { + version: 2, adapter: { [CHAIN.ETHEREUM]: { - fetch: fetch, + fetch: fetchFees, + start: 1685577600, + }, + [CHAIN.SOLANA]: { + fetch: fethcFeesSolana, + runAtCurrTime: true, + start: 1685577600, + }, + [CHAIN.BLAST]: { + fetch: fetchFees, + start: 1685577600, + }, + [CHAIN.BASE]: { + fetch: fetchFees, start: 1685577600, }, - // [CHAIN.SOLANA]: { - // fetch: fethcFeesSolana, - // runAtCurrTime: true, - // start: async () => 1685577600, - // }, }, isExpensiveAdapter: true, }; diff --git a/fees/base.ts b/fees/base.ts index a7ef7a3c35..d010b17b3f 100644 --- a/fees/base.ts +++ b/fees/base.ts @@ -10,6 +10,7 @@ const ethereumWallets = [ ] const adapter: Adapter = { + version: 2, adapter: { [CHAIN.BASE]: { fetch: L2FeesFetcher({ ethereumWallets }), diff --git a/fees/basecamp/index.ts b/fees/basecamp/index.ts new file mode 100644 index 0000000000..de56874312 --- /dev/null +++ b/fees/basecamp/index.ts @@ -0,0 +1,21 @@ +import { FetchOptions, SimpleAdapter } from "../../adapters/types"; +import { CHAIN } from "../../helpers/chains"; +import { addTokensReceived } from '../../helpers/token'; + +const fetch: any = async (options: FetchOptions) => { + const dailyFees = await addTokensReceived({ options, tokens: ["0x4200000000000000000000000000000000000006"], targets: ["0xbcb4a982d3c2786e69a0fdc0f0c4f2db1a04e875"] }) + + return { dailyFees, dailyRevenue: dailyFees } +} + +const adapter: SimpleAdapter = { + version: 2, + adapter: { + [CHAIN.BASE]: { + fetch: fetch, + start: 0, + }, + }, +}; + +export default adapter; diff --git a/fees/based-markets.ts b/fees/based-markets.ts index 8ba3eaa112..32ee0a695f 100644 --- a/fees/based-markets.ts +++ b/fees/based-markets.ts @@ -1,12 +1,11 @@ +import * as sdk from "@defillama/sdk"; import request, { gql } from "graphql-request"; import { CHAIN } from "../helpers/chains"; import BigNumber from "bignumber.js"; import { getUniqStartOfTodayTimestamp } from "../helpers/getUniSubgraphVolume"; -import { FetchResultFees, SimpleAdapter } from "../adapters/types"; +import { FetchOptions, FetchResultFees, SimpleAdapter } from "../adapters/types"; -const ONE_DAY_IN_SECONDS = 60 * 60 * 24 - -const endpoint = "https://api.thegraph.com/subgraphs/name/symmiograph/base_analytics_8" +const endpoint = sdk.graph.modifyEndpoint('9rrUvLtMMDLkSQeFdFza8pxea64hEaV3D8hxZYie1jpZ') const query = gql` query stats($from: String!, $to: String!) { @@ -46,10 +45,10 @@ const toString = (x: BigNumber) => { return x.toString() } -const fetchVolume = async (timestamp: number): Promise => { +const fetchVolume = async ({ fromTimestamp, toTimestamp}: FetchOptions) => { const response: IGraphResponse = await request(endpoint, query, { - from: String(timestamp - ONE_DAY_IN_SECONDS), - to: String(timestamp) + from: String(fromTimestamp), + to: String(toTimestamp) }) @@ -80,11 +79,7 @@ const fetchVolume = async (timestamp: number): Promise => { const totalProtocolRevenue = '0'; const totalSupplySideRevenue = '0'; - const dayTimestamp = getUniqStartOfTodayTimestamp(new Date((timestamp * 1000))) - return { - timestamp: dayTimestamp, - dailyFees: _dailyFees, totalFees: _totalFees, @@ -103,6 +98,7 @@ const fetchVolume = async (timestamp: number): Promise => { const adapter: SimpleAdapter = { + version: 2, adapter: { [CHAIN.BASE]: { fetch: fetchVolume, diff --git a/fees/basepaint.ts b/fees/basepaint.ts index 63d6cd4168..bbd7fd014c 100644 --- a/fees/basepaint.ts +++ b/fees/basepaint.ts @@ -1,5 +1,5 @@ import ADDRESSES from '../helpers/coreAssets.json' -import { FetchOptions, FetchResultFees, SimpleAdapter } from "../adapters/types" +import { FetchOptions, SimpleAdapter } from "../adapters/types" import { CHAIN } from "../helpers/chains" const contract = '0xBa5e05cb26b78eDa3A2f8e3b3814726305dcAc83' @@ -8,7 +8,7 @@ const protocol_fees = 10; // 10% fees const ethAddress = ADDRESSES.null; -const fetch: any = async (timestamp: number, _: any, { getLogs, createBalances, }: FetchOptions): Promise => { +const fetch: any = async ({ getLogs, createBalances, }: FetchOptions) => { const logs = await getLogs({ target: contract, eventAbi }) const dailyFees = createBalances() const dailyRevenue = createBalances() @@ -18,10 +18,11 @@ const fetch: any = async (timestamp: number, _: any, { getLogs, createBalances, dailyRevenue.addBalances(dailyFees) dailyRevenue.resizeBy(protocol_fees / 100) // 10% of the fees go to the protocol - return { dailyFees, dailyRevenue, timestamp } + return { dailyFees, dailyRevenue } } const adapterFees: SimpleAdapter = { + version: 2, adapter: { [CHAIN.BASE]: { fetch, diff --git a/fees/bcraft.ts b/fees/bcraft.ts new file mode 100644 index 0000000000..e44d628cc3 --- /dev/null +++ b/fees/bcraft.ts @@ -0,0 +1,47 @@ +import { Adapter, FetchV2 } from "../adapters/types"; +import { CHAIN } from "../helpers/chains"; + +const adapter: Adapter = { + adapter: { + [CHAIN.BASE]: { + fetch: (async ({ getLogs, createBalances }) => { + const dailyFees = createBalances(); + const dailyRevenue = createBalances(); + const coinBuyLogs = await getLogs({ + target: "0x7BaEA50509d5d742909592CF045101526b306bE4", + eventAbi: + "event MineUpgraded(address indexed user, uint256 newLevel, uint256 cost)", + }); + coinBuyLogs.map((e: any) => { + dailyFees.addGasToken(e.cost); + dailyRevenue.addGasToken(e.cost); + }); + const buySharesLogs = await getLogs({ + target: "0x0De0D0cF717af57D2101F6Be0962fA890c1FBeC6", + eventAbi: + "event BuyClanShare(address indexed buyer, uint256 indexed clanId, uint256 amount, uint256 price, uint256 protocolFee, uint256 subjectFee)", + }); + buySharesLogs.map((e: any) => { + dailyFees.addGasToken(e.protocolFee); + dailyRevenue.addGasToken(e.protocolFee); + }); + + const sellSharesLogs = await getLogs({ + target: "0x0De0D0cF717af57D2101F6Be0962fA890c1FBeC6", + eventAbi: + "event SellClanShare(address indexed seller, uint256 indexed clanId, uint256 amount, uint256 price, uint256 protocolFee, uint256 subjectFee)", + }); + sellSharesLogs.map((e: any) => { + dailyFees.addGasToken(e.protocolFee); + dailyRevenue.addGasToken(e.protocolFee); + }); + + return { dailyFees, dailyRevenue }; + }) as FetchV2, + start: 18607509, + }, + }, + version: 2, +}; + +export default adapter; diff --git a/fees/beamex.ts b/fees/beamex.ts index 5b134014d5..cb13ebe9b5 100644 --- a/fees/beamex.ts +++ b/fees/beamex.ts @@ -5,7 +5,7 @@ import { getTimestampAtStartOfDayUTC } from "../utils/date"; const endpointsBeamex: ChainEndpoints = { [CHAIN.MOONBEAN]: - "https://api.thegraph.com/subgraphs/name/flisko/stats-moonbeam", + 'https://graph.beamswap.io/subgraphs/name/beamswap/beamex-stats', }; const methodologyBeamex = { @@ -13,11 +13,11 @@ const methodologyBeamex = { UserFees: "Fees from open/close position (0.1%), swap (0.1% to 0.4%) and borrow fee ((assets borrowed)/(total assets in pool)*0.04%)", HoldersRevenue: - "30% of all collected fees are distributed to $stGLINT stakers", + "20% of all collected fees are distributed to $stGLINT stakers", SupplySideRevenue: - "70% of all collected fees will be distributed to BLP stakers. Currently they are distributed to treasury", - Revenue: "70% of all collected fees are distributed to the treasury", - ProtocolRevenue: "70% of all collected fees are distributed to the treasury", + "60% of all collected fees are distributed to BLP stakers. Currently they are distributed to treasury", + Revenue: "20% of all collected fees are distributed to the treasury and upkeep", + ProtocolRevenue: "20% of all collected fees are distributed to the treasury and upkeep", }; const graphsBeamex = (chain: string) => async (timestamp: number) => { @@ -74,21 +74,22 @@ const graphsBeamex = (chain: string) => async (timestamp: number) => { timestamp, dailyFees: finalDailyFee.toString(), dailyUserFees: finalUserFee.toString(), - dailyRevenue: (finalDailyFee * 0.7).toString(), - dailyProtocolRevenue: (finalDailyFee * 0.7).toString(), - dailyHoldersRevenue: (finalDailyFee * 0.3).toString(), - dailySupplySideRevenue: (finalDailyFee * 0.3).toString(), + dailyRevenue: (finalDailyFee * 0.2).toString(), + dailyProtocolRevenue: (finalDailyFee * 0.2).toString(), + dailyHoldersRevenue: (finalDailyFee * 0.2).toString(), + dailySupplySideRevenue: (finalDailyFee * 0.6).toString(), totalFees: finalTotalFee.toString(), - totalProtocolRevenue: (finalTotalFee * 0.7).toString(), - totalRevenue: (finalTotalFee * 0.7).toString(), + totalProtocolRevenue: (finalTotalFee * 0.6).toString(), + totalRevenue: (finalTotalFee * 0.6).toString(), totalUserFees: finalTotalUserFee.toString(), - totalSupplySideRevenue: (finalTotalFee * 0.3).toString(), + totalSupplySideRevenue: (finalTotalFee * 0.6).toString(), }; }; const adapter: Adapter = { + version: 1, adapter: { [CHAIN.MOONBEAM]: { fetch: graphsBeamex(CHAIN.MOONBEAM), diff --git a/fees/beamswap-v3.ts b/fees/beamswap-v3.ts index b87e42a3fd..433c190b57 100644 --- a/fees/beamswap-v3.ts +++ b/fees/beamswap-v3.ts @@ -1,3 +1,4 @@ +import * as sdk from "@defillama/sdk"; import { Chain } from "@defillama/sdk/build/general"; import BigNumber from "bignumber.js"; import request, { gql } from "graphql-request"; @@ -20,7 +21,7 @@ type IURL = { } const endpoints: IURL = { - [CHAIN.MOONBEAM]: "https://api.thegraph.com/subgraphs/name/beamswap/beamswap-v3", + [CHAIN.MOONBEAM]: sdk.graph.modifyEndpoint('2YnTZfQmenjvJ3bihewLGgAKnyqjrMWrStux8ZFE7ee6'), } const fetch = (chain: Chain) => { @@ -75,6 +76,7 @@ const fetch = (chain: Chain) => { } const adapter: Adapter = { + version: 1, adapter: { [CHAIN.MOONBEAM]: { fetch: fetch(CHAIN.MOONBEAM), diff --git a/fees/beamswap.ts b/fees/beamswap.ts index f8bf5fddef..0c9e123e47 100644 --- a/fees/beamswap.ts +++ b/fees/beamswap.ts @@ -1,40 +1,46 @@ - +import * as sdk from "@defillama/sdk"; import { Adapter, ChainEndpoints } from "../adapters/types"; import { CHAIN } from "../helpers/chains"; import { getStartTimestamp } from "../helpers/getStartTimestamp"; -import { getDexChainFees } from "../helpers/getUniSubgraphFees"; -import { univ2Adapter } from "../helpers/getUniSubgraphVolume"; - -const TOTAL_FEES = 0.0030; -const PROTOCOL_FEES = 0.0013; +import { + DEFAULT_TOTAL_VOLUME_FACTORY, + DEFAULT_TOTAL_VOLUME_FIELD, + getGraphDimensions2, +} from "../helpers/getUniSubgraph"; const endpoints: ChainEndpoints = { - [CHAIN.MOONBEAN]: - "https://api.thegraph.com/subgraphs/name/beamswap/beamswap-dex-v2", + [CHAIN.MOONBEAN]: sdk.graph.modifyEndpoint( + "9CwTvN5R8sztZSBZqbDZWcHZjM41RRiz63QmRMsJBn6X", + ), }; - -const volumeAdapter = univ2Adapter({ - [CHAIN.MOONBEAN]: "https://api.thegraph.com/subgraphs/name/beamswap/beamswap-dex-v2", -}, {}); - -volumeAdapter.adapter.moonbeam.start = getStartTimestamp({ - endpoints, - chain: CHAIN.MOONBEAN, - dailyDataField: "uniswapDayDatas", - dateField: "date", - volumeField: "dailyVolumeUSD", -}) - -const feeAdapter = getDexChainFees({ - totalFees: TOTAL_FEES, - protocolFees: PROTOCOL_FEES, - volumeAdapter +const graphs = getGraphDimensions2({ + graphUrls: endpoints, + totalVolume: { + factory: DEFAULT_TOTAL_VOLUME_FACTORY, + field: DEFAULT_TOTAL_VOLUME_FIELD, + }, + feesPercent: { + type: "fees", + ProtocolRevenue: 0.0013, + UserFees: 0.0017, + }, }); const adapter: Adapter = { - adapter: feeAdapter + version: 2, + adapter: { + [CHAIN.MOONBEAM]: { + fetch: graphs(CHAIN.MOONBEAM), + start: getStartTimestamp({ + endpoints, + chain: CHAIN.MOONBEAN, + dailyDataField: "uniswapDayDatas", + dateField: "date", + volumeField: "dailyVolumeUSD", + }), + }, + }, }; - export default adapter; diff --git a/fees/beefy/index.ts b/fees/beefy/index.ts new file mode 100644 index 0000000000..f825063d8d --- /dev/null +++ b/fees/beefy/index.ts @@ -0,0 +1,138 @@ +import { Adapter, Fetch, FetchResultFees } from '../../adapters/types'; +import { CHAIN } from '../../helpers/chains'; +import { queryDune } from '../../helpers/dune'; + +const totalFee = 9.5; +const strategistFee = 0.5; +const callFee = 0.01; +const revenueFee = totalFee - strategistFee - callFee; +const holderShare = 36; +const protocolShare = 64; + +function getDay(timestamp: number): string { + const date = new Date(timestamp * 1000); + return date.toISOString().split('T')[0]; +} + +interface IRevenue { + day: string; + arbitrum: number; + base: number; + polygon: number; + avalanche: number; + fantom: number; + optimism: number; + BNB: number; + ethereum: number; + linea: number; +} + +const fetch = (chain: Exclude): Fetch => { + return async (timestamp, _, {startOfDay}): Promise => { + const endTimestamp = startOfDay + 86400; + const allRevenue: IRevenue[] = (await queryDune('3594948', {endTimestamp})); + const day = getDay(timestamp); + const entry = allRevenue.find(r => r.day === day); + + if (!entry) { + throw new Error(`No fees found for ${day}`); + } + + const dailyRevenue = entry[chain] || 0; + const dailyFees = dailyRevenue * (totalFee / revenueFee); + return { + dailyFees, + dailyRevenue, + dailyProtocolRevenue: `${dailyRevenue * (protocolShare/100)}`, + dailyHoldersRevenue: `${dailyRevenue * (holderShare/100)}`, + timestamp, + }; + }; +}; + +const methodology = { + Fees: `${totalFee}% of each harvest is charged as a performance fee`, + Revenue: `All fees except for ${strategistFee}% to strategist and variable harvest() call fee are revenue`, + HoldersRevenue: `${holderShare}% of revenue is distributed to holders who stake`, + ProtocolRevenue: `${protocolShare}% of revenue is distributed to the treasury`, +}; + +const adapter: Adapter = { + version: 1, + adapter: { + [CHAIN.ARBITRUM]: { + fetch: fetch('arbitrum'), + start: 1693958400, // 2023-09-06 + runAtCurrTime: false, + meta: { + methodology + } + }, + [CHAIN.BASE]: { + fetch: fetch('base'), + start: 1692921600, // 2023-08-25 + runAtCurrTime: false, + meta: { + methodology + } + }, + [CHAIN.POLYGON]: { + fetch: fetch('polygon'), + start: 1693958400, // 2023-09-06 + runAtCurrTime: false, + meta: { + methodology + } + }, + [CHAIN.AVAX]: { + fetch: fetch('avalanche'), + start: 1693958400, // 2023-09-06 + runAtCurrTime: false, + meta: { + methodology + } + }, + [CHAIN.FANTOM]: { + fetch: fetch('fantom'), + start: 1692921600, // 2023-08-25 + runAtCurrTime: false, + meta: { + methodology + } + }, + [CHAIN.OPTIMISM]: { + fetch: fetch('optimism'), + start: 1692921600, // 2023-08-25 + runAtCurrTime: false, + meta: { + methodology + } + }, + [CHAIN.BSC]: { + fetch: fetch('BNB'), + start: 1692921600, // 2023-08-25 + runAtCurrTime: false, + meta: { + methodology + } + }, + [CHAIN.ETHEREUM]: { + fetch: fetch('ethereum'), + start: 1698105600, // 2023-10-24 + runAtCurrTime: false, + meta: { + methodology + } + }, + [CHAIN.LINEA]: { + fetch: fetch('linea'), + start: 1710028800, // 2024-03-10 + runAtCurrTime: false, + meta: { + methodology + } + }, + }, + isExpensiveAdapter: true, +}; +export default adapter; diff --git a/fees/beethoven-x.ts b/fees/beethoven-x.ts index 191f8756e9..aac1440b4b 100644 --- a/fees/beethoven-x.ts +++ b/fees/beethoven-x.ts @@ -15,6 +15,7 @@ const adapters: SimpleAdapter = { adapter: { [CHAIN.OPTIMISM]: { fetch: getFeesExport(vaultAddresses[CHAIN.OPTIMISM]), start: 1672531200 }, [CHAIN.FANTOM]: { fetch: getFeesExport(vaultAddresses[CHAIN.FANTOM]), start: 1672531200 }, - } + }, + version: 2, } export default adapters diff --git a/fees/bellumexchange.ts b/fees/bellumexchange.ts new file mode 100644 index 0000000000..b5f8586327 --- /dev/null +++ b/fees/bellumexchange.ts @@ -0,0 +1,33 @@ +import { Adapter, FetchOptions, } from "../adapters/types"; +import { CHAIN } from "../helpers/chains"; + +const FACTORIES = [ + '0x9f383e31aA37b6a4F0F57033558C54c37B5De45F', + '0xE0C0Cb05b6dFe6C7d196493963Bf083E726fc517', + '0xde11a16D6e04551168dfD54e936829B024A236C4', +]; + +const FEE = BigInt(100); + +const adapter: Adapter = { + version: 2, + adapter: { + [CHAIN.AVAX]: { + fetch: (async (options: FetchOptions) => { + const dailyFees = options.createBalances(); + const logs = await options.getLogs({ + targets: FACTORIES, + eventAbi: "event BellumSwap(address indexed token, address indexed sender, uint amount0In, uint amount0Out, uint amount1In, uint amount1Out)", + }) + logs.map((tx: any) => { + dailyFees.addGasToken((tx.amount1In + tx.amount1Out) / FEE) + }) + return { dailyFees, dailyRevenue: dailyFees } + }) as any, + start: 1723360238 + }, + }, + +} + +export default adapter; diff --git a/fees/benqi-lending.ts b/fees/benqi-lending.ts index 3c459a6667..4f13eb80f4 100644 --- a/fees/benqi-lending.ts +++ b/fees/benqi-lending.ts @@ -1,16 +1,5 @@ -import { Adapter, } from "../adapters/types" -import { CHAIN } from "../helpers/chains"; -import { getFeesExport } from "../helpers/compoundV2"; +import { compoundV2Export, } from "../helpers/compoundV2"; const unitroller = "0x486Af39519B4Dc9a7fCcd318217352830E8AD9b4"; -const adapter: Adapter = { - adapter: { - [CHAIN.AVAX]: { - fetch: getFeesExport(unitroller), - start: 1664582400, - }, - }, -}; - -export default adapter; +export default compoundV2Export({ avax: unitroller}); diff --git a/fees/benqi-staked-avax.ts b/fees/benqi-staked-avax.ts index 039cb6dfc9..17f0e12559 100644 --- a/fees/benqi-staked-avax.ts +++ b/fees/benqi-staked-avax.ts @@ -4,17 +4,18 @@ import { CHAIN } from "../helpers/chains"; const topic0 = '0x8fbf6a230d02fb8f41af8c1ca90b126472e11286c47d7ed86bb2e1fc51a283d8'; const address = '0x2b2c81e08f1af8835a78bb2a90ae924ace0ea4be' -const fetchFees = async (timestamp: number, _: ChainBlocks, { createBalances, getLogs, }: FetchOptions): Promise => { +const fetchFees = async ({ createBalances, getLogs, }: FetchOptions) => { const dailyFees = createBalances() const logs = await getLogs({ target: address, topics: [topic0] }) logs.map((log) => dailyFees.add('0x2b2c81e08f1af8835a78bb2a90ae924ace0ea4be', log.data)) dailyFees.resizeBy(1 / 0.9) const dailyRevenue = dailyFees.clone(0.1) const dailySupplySideRevenue = dailyFees.clone(0.9) - return { dailyFees, dailyRevenue, dailySupplySideRevenue, timestamp } + return { dailyFees, dailyRevenue, dailySupplySideRevenue } } const adapters: SimpleAdapter = { + version: 2, adapter: { [CHAIN.AVAX]: { fetch: fetchFees, diff --git a/fees/betmode.ts b/fees/betmode.ts new file mode 100644 index 0000000000..ae179e5afd --- /dev/null +++ b/fees/betmode.ts @@ -0,0 +1,24 @@ +import { FetchOptions, SimpleAdapter } from "../adapters/types"; +import { CHAIN } from "../helpers/chains"; + +const address = '0xeb5D5af6a0ac3B64243858094d6b3b379B8772Aa' +const fetch = async (options: FetchOptions) => { + const dailyFees = options.createBalances(); + const feesStart = await options.fromApi.call({ target: address, abi: "uint:GGR" }) + const feesEnd = await options.toApi.call({ target: address, abi: "uint:GGR" }) + dailyFees.add("0xd988097fb8612cc24eeC14542bC03424c656005f", feesEnd - feesStart) + dailyFees.resizeBy(0.065) + return { dailyFees, dailyRevenue: dailyFees } +} + +const adapter: SimpleAdapter = { + version: 2, + adapter: { + [CHAIN.MODE]: { + fetch: fetch, + start: 0, + } + } +} + +export default adapter; diff --git a/fees/betswirl/index.ts b/fees/betswirl/index.ts index 0fd04bff65..d57a2eaf5e 100644 --- a/fees/betswirl/index.ts +++ b/fees/betswirl/index.ts @@ -1,33 +1,17 @@ +import * as sdk from "@defillama/sdk"; import { request } from "graphql-request"; -import BigNumber from "bignumber.js"; - -import { Adapter, ChainBlocks, FetchOptions, FetchResultFees } from "../../adapters/types"; +import { Adapter, FetchOptions } from "../../adapters/types"; import { BSC, POLYGON, AVAX, ARBITRUM } from "../../helpers/chains"; -import { getTimestampAtStartOfDayUTC, getTimestampAtStartOfNextDayUTC } from "../../utils/date"; import { Chain } from "@defillama/sdk/build/general"; -import { getPrices } from "../../utils/prices"; -import { getBlock } from "../../helpers/getBlock"; - -const ten = toBN("10"); -function fromWei(wei: string | BigNumber, unit = 18) { - return toBN(wei).dividedBy(ten.pow(unit)); -} -function toBN(wei: string | BigNumber) { - return new BigNumber(wei); -} const endpoints: any = { - [BSC]: "https://api.thegraph.com/subgraphs/name/betswirl/betswirl-bnb", + [BSC]: sdk.graph.modifyEndpoint('DhivnGkd3FnqgEDpBi8xP2QeqdBB1LWjakwdL7W6KJoE'), [POLYGON]: - "https://api.thegraph.com/subgraphs/name/betswirl/betswirl-polygon", - [AVAX]: "https://api.thegraph.com/subgraphs/name/betswirl/betswirl-avalanche", - [ARBITRUM]: "https://api.thegraph.com/subgraphs/name/betswirl/betswirl-arbitrum", + sdk.graph.modifyEndpoint('FL3ePDCBbShPvfRJTaSCNnehiqxsPHzpLud6CpbHoeKW'), + [AVAX]: sdk.graph.modifyEndpoint('WicBtHWBzT58U45mCh9QEBRib1ieqt86yiNkXvPdkEN'), + [ARBITRUM]: sdk.graph.modifyEndpoint('8awdcK7DwcmmamNBHxobxpxMyRFkoQpF678rHsqB1yJq'), }; -type TBalance = { - [s: string]: number; -} - interface IToken { id: string; dividendAmount: string; @@ -53,7 +37,7 @@ interface IGraph { function graphs() { return (chain: Chain): any => { - return async (timestamp: number, _: ChainBlocks, { createBalances, getFromBlock, getToBlock }: FetchOptions): Promise => { + return async ({ createBalances, getFromBlock, getToBlock }: FetchOptions) => { const todaysBlock = await getToBlock(); const yesterdaysBlock = await getFromBlock(); @@ -159,7 +143,6 @@ function graphs() { dailySupplySideRevenue.add(tokenKey, 0 - +initiatorAmount) } return { - timestamp, dailyFees, dailyUserFees: dailyFees, dailyRevenue, @@ -233,6 +216,7 @@ const meta = { }; const adapter: Adapter = { + version: 2, adapter: { [BSC]: { start: 1658880000, diff --git a/fees/bifrost-liquid-staking/index.ts b/fees/bifrost-liquid-staking/index.ts new file mode 100644 index 0000000000..948560990a --- /dev/null +++ b/fees/bifrost-liquid-staking/index.ts @@ -0,0 +1,27 @@ +import { CHAIN } from "../../helpers/chains"; +import { FetchOptions } from "../../adapters/types"; +import fetchURL from "../../utils/fetchURL"; + + + + +const fetch = async (options: FetchOptions) => { + const startTime = new Date(options.startTimestamp * 1000).toISOString().split("T")[0] + const res = await fetchURL('https://dapi.bifrost.io/api/dapp/stats') + const { dailyFees, dailyRevenue, totalRevenue, totalFees } = res.find(v => v.date === startTime) + + return { dailyFees, dailyRevenue, totalRevenue, totalFees, timestamp: options.startTimestamp }; +}; + + +const adapter: any = { + version: 2, + adapter: { + [CHAIN.BIFROST]: { + fetch, + start: 1640995200, + }, + }, +}; + +export default adapter; diff --git a/fees/biswap.ts b/fees/biswap.ts index 441568f39c..8c9ee5629c 100644 --- a/fees/biswap.ts +++ b/fees/biswap.ts @@ -1,12 +1,10 @@ +import { graph } from "@defillama/sdk"; import { CHAIN } from "../helpers/chains"; -import { univ2DimensionAdapter } from "../helpers/getUniSubgraph"; +import { univ2DimensionAdapter2 } from "../helpers/getUniSubgraph"; -const adapters = univ2DimensionAdapter({ +const adapters = univ2DimensionAdapter2({ graphUrls: { - [CHAIN.BSC]: "https://api.thegraph.com/subgraphs/name/biswapcom/exchange5" - }, - dailyVolume: { - factory: "pancakeDayData" + [CHAIN.BSC]: graph.modifyEndpoint('2D9rXpMTvAgofWngsyRE17jKr5ywrU4W3Eaa71579qkd') }, totalVolume: { factory: "pancakeFactories" @@ -30,4 +28,5 @@ const adapters = univ2DimensionAdapter({ } }); -export default adapters; \ No newline at end of file + +export default adapters; diff --git a/fees/bitcoin.ts b/fees/bitcoin.ts index ecbf8554a4..294e74b49b 100644 --- a/fees/bitcoin.ts +++ b/fees/bitcoin.ts @@ -5,6 +5,7 @@ import { chainAdapter } from "../helpers/getChainFees"; const feeAdapter = chainAdapter(BITCOIN, "btc", 1230958800); const adapter: Adapter = { + version: 1, adapter: feeAdapter, protocolType: ProtocolType.CHAIN } diff --git a/fees/bitlayer/index.ts b/fees/bitlayer/index.ts new file mode 100644 index 0000000000..aa45d9f935 --- /dev/null +++ b/fees/bitlayer/index.ts @@ -0,0 +1,54 @@ +import { + Adapter, + FetchOptions, + ProtocolType, +} from "../../adapters/types"; +import { httpPost } from "../../utils/fetchURL"; +import { CHAIN } from "../../helpers/chains"; +import { time } from "console"; + +export async function getFeeUSD({ startOfDay, createBalances }: FetchOptions, url: string) { + const dailyFees = createBalances() + const response = await httpPost(url, { + responseType: 'blob', headers: { + "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.169 Safari/537.36", + "Content-Type": "text/csv; charset=utf-8", + "Accept": "text/csv; charset=utf-8", + "origin": url, + } + }); + const feesToday = response + .split("\n") + .map((line: any) => { + return { + timestamp: Number((line.split(",")[1] as string)?.replace(/"/g, "")), + value: Number((line.split(",")[2] as string)?.replace(/"/g, "")) + } + }).filter((fee: any) => fee.timestamp === startOfDay) + const gasToken = "bitcoin"; + feesToday.forEach((fee: any) => { + const value = Number(fee.value); + const amountReal = value / 1e18; + dailyFees.addCGToken(gasToken, amountReal); + }); + return dailyFees; +} + +const adapter: Adapter = { + version: 1, + adapter: { + [CHAIN.BITLAYER]: { + fetch: async (_t: any, _b: any, options: FetchOptions) => { + const url = "https://api.btrscan.com/scan/v1/chain/txForDefillama"; + const dailyFees = await getFeeUSD(options, url); + return { + timestamp: options.startOfDay, + dailyFees: dailyFees, + }; + }, + start: 1713089236, + }, + }, + protocolType: ProtocolType.CHAIN, +}; +export default adapter; diff --git a/fees/blastapi.ts b/fees/blastapi.ts index e821a2f344..e46a22e16b 100644 --- a/fees/blastapi.ts +++ b/fees/blastapi.ts @@ -18,17 +18,18 @@ const marketplace_address: TMarketPlaceAddress = { } const fetch = (chain: Chain) => { - return async (timestamp: number , _: ChainBlocks, { createBalances, getLogs, }: FetchOptions): Promise => { + return async ({ createBalances, getLogs, }: FetchOptions) => { const dailyFees = createBalances(); (await getLogs({ target: marketplace_address[chain], eventAbi: 'event Deposit (address indexed account, address indexed erc20, uint256 amount)' })).forEach((e: any) => dailyFees.add(e.erc20, e.amount)) - return { dailyFees, timestamp, dailyRevenue: dailyFees }; + return { dailyFees, dailyRevenue: dailyFees }; } } const adapter: Adapter = { + version: 2, adapter: { [CHAIN.ETHEREUM]: { fetch: fetch(CHAIN.ETHEREUM), diff --git a/fees/blazebot.ts b/fees/blazebot.ts index a192cb198e..698632b886 100644 --- a/fees/blazebot.ts +++ b/fees/blazebot.ts @@ -1,7 +1,8 @@ -import { Adapter, ChainBlocks, FetchOptions, FetchResultFees } from "../adapters/types"; +import { Adapter, ChainBlocks, DISABLED_ADAPTER_KEY, FetchOptions, FetchResultFees } from "../adapters/types"; import { CHAIN } from "../helpers/chains"; import { Chain } from "@defillama/sdk/build/general"; import { request, } from "graphql-request"; +import disabledAdapter from "../helpers/disabledAdapter"; type TEndpoint = { [s: Chain | string]: string; @@ -37,8 +38,9 @@ const graphs = (chain: Chain) => { const adapter: Adapter = { adapter: { + [DISABLED_ADAPTER_KEY]: disabledAdapter, [CHAIN.BASE]: { - fetch: graphs(CHAIN.BASE), + fetch: async (timestamp: number) => {return{timestamp}}, start: 1694131200, }, } diff --git a/fees/blex/index.ts b/fees/blex/index.ts index 088fea02c9..0db9ab2e29 100644 --- a/fees/blex/index.ts +++ b/fees/blex/index.ts @@ -111,7 +111,8 @@ const adapter: Adapter = { fetch: getFetch(allFeesData,userFeesData)(ARBITRUM), start: 1691211277, }, - } + }, + version: 1 } export default adapter; diff --git a/fees/blitz.ts b/fees/blitz.ts new file mode 100644 index 0000000000..fb7e6eb477 --- /dev/null +++ b/fees/blitz.ts @@ -0,0 +1,128 @@ +import { CHAIN } from "../helpers/chains"; +import { Adapter, FetchResultFees } from "../adapters/types"; +import { httpPost } from "../utils/fetchURL"; + +interface MarketSnapshots { + interval: { + count: number; + granularity: number; + max_time: number; + }; +} + +interface QueryBody { + market_snapshots: MarketSnapshots; +} +interface IData { + [s: string]: string; +} + +interface Snapshot { + [s: string]: IData; +} + +interface Response { + snapshots: Snapshot[]; +} + +const query = async (max_time: number): Promise => { + const body: QueryBody = { + market_snapshots: { + interval: { + count: 2, + granularity: 86400, + max_time: max_time, + }, + }, + }; + + const archiveBaseUrl = "https://archive.blast-prod.vertexprotocol.com/v1"; + const response = await httpPost(archiveBaseUrl, body); + return response; +}; + +const sumAllProductStats = (stat_map: IData): number => { + let stat_sum = 0; + for (const v of Object.values(stat_map)) { + stat_sum += parseInt(v); + } + return stat_sum / 1e18; +}; + +const get24hrStat = async ( + field: string, + max_time: number +): Promise => { + const response = await query(max_time); + const cur_res: Snapshot = response.snapshots[0]; + const past_res: Snapshot = response.snapshots[1]; + return ( + sumAllProductStats(cur_res[field]) - sumAllProductStats(past_res[field]) + ); +}; + +const getCumulativeStat = async ( + field: string, + max_time: number +): Promise => { + const response = await query(max_time); + const cur_res = response.snapshots[0]; + return sumAllProductStats(cur_res[field]); +}; + +const getCumulativeFees = async (max_time: number): Promise => { + const fees = await getCumulativeStat("cumulative_taker_fees", max_time); + const sequencer_fees = await getCumulativeStat( + "cumulative_sequencer_fees", + max_time + ); + return fees - sequencer_fees; +}; + +const getCumulativeRevenue = async (max_time: number): Promise => { + const fees = await getCumulativeFees(max_time); + const rebates = await getCumulativeStat("cumulative_maker_fees", max_time); + return fees + rebates; +}; + +const get24hrFees = async (max_time: number): Promise => { + const fees = await get24hrStat("cumulative_taker_fees", max_time); + const sequencer_fees = await get24hrStat( + "cumulative_sequencer_fees", + max_time + ); + return fees - sequencer_fees; +}; + +const get24hrRevenue = async (max_time: number): Promise => { + const fees = await get24hrFees(max_time); + const rebates = await get24hrStat("cumulative_maker_fees", max_time); + return fees + rebates; +}; + +const fetch = async (timestamp: number): Promise => { + const dailyFees = await get24hrFees(timestamp); + const dailyRevenue = await get24hrRevenue(timestamp); + const totalFees = await getCumulativeFees(timestamp); + const totalRev = await getCumulativeRevenue(timestamp); + return { + dailyFees: `${dailyFees}`, + dailyRevenue: `${dailyRevenue}`, + totalRevenue: `${totalRev}`, + totalFees: `${totalFees}`, + timestamp, + }; +}; + +const adapter: Adapter = { + version: 1, + adapter: { + [CHAIN.BLAST]: { + fetch: fetch, + runAtCurrTime: true, + start: 1710259200, + }, + }, +}; + +export default adapter; diff --git a/fees/blocxroute.ts b/fees/blocxroute.ts new file mode 100644 index 0000000000..41a768adba --- /dev/null +++ b/fees/blocxroute.ts @@ -0,0 +1,29 @@ +import { FetchOptions, SimpleAdapter } from "../adapters/types"; +import { CHAIN } from "../helpers/chains"; +import { queryDune } from "../helpers/dune"; + +const fetch: any = async (options: FetchOptions) => { + const dailyFees = options.createBalances(); + const value = (await queryDune("3521814", { + start: options.startTimestamp, + end: options.endTimestamp, + receiver: 'HWEoBxYs7ssKuudEjzjmpfJVX7Dvi7wescFsVx2L5yoY' + })); + dailyFees.add('So11111111111111111111111111111111111111112', value[0].fee_token_amount); + + return { dailyFees } + +} + +const adapter: SimpleAdapter = { + version: 2, + adapter: { + [CHAIN.SOLANA]: { + fetch: fetch, + start: 0, + }, + }, + isExpensiveAdapter: true +}; + +export default adapter; diff --git a/fees/bluefin.ts b/fees/bluefin.ts index 1b196d4aaa..b8294038de 100644 --- a/fees/bluefin.ts +++ b/fees/bluefin.ts @@ -19,6 +19,7 @@ const fetch_sui = async (timestamp: number): Promise => { }; const adapter: SimpleAdapter = { + version: 1, adapter: { [CHAIN.SUI]: { fetch: fetch_sui, diff --git a/fees/bluemove/index.ts b/fees/bluemove/index.ts index 65f879ae77..6d267b8dd1 100644 --- a/fees/bluemove/index.ts +++ b/fees/bluemove/index.ts @@ -23,8 +23,6 @@ const fetch = async (timestamp: number) => { const dailyFees = Number(dailyVolume) * rateFees; const totalFees = Number(totalVolume) * rateFees; return { - totalVolume: `${totalVolume}`, - dailyVolume: dailyVolume ? `${dailyVolume}` : undefined, totalFees: `${totalFees}`, dailyFees: dailyFees ? `${dailyFees}` : undefined, timestamp: dayTimestamp, @@ -39,6 +37,7 @@ const adapter: SimpleAdapter = { start: 1666224000, }, }, + version: 1 }; export default adapter; diff --git a/fees/blur/index.ts b/fees/blur/index.ts index 284fda2e1d..cb9d6f3410 100644 --- a/fees/blur/index.ts +++ b/fees/blur/index.ts @@ -1,4 +1,4 @@ -import { Adapter, FetchOptions, FetchResultFees } from "../../adapters/types" +import { Adapter, FetchOptions } from "../../adapters/types" import { CHAIN } from "../../helpers/chains" import { ethers } from "ethers" import { queryIndexer } from "../../helpers/indexer"; @@ -18,7 +18,7 @@ const unpackTypePriceCollection = (packedValue: any): any => { }; -const fetch: any = async (timestamp: number, _: any, options: FetchOptions) => { +const fetch: any = async (options: FetchOptions) => { const contract_interface = new ethers.Interface(abi); const dailyFees = options.createBalances(); @@ -81,7 +81,7 @@ const fetch: any = async (timestamp: number, _: any, options: FetchOptions) => { const _price = price.toString() * 1 dailyFees.addGasToken(_rate * _price); }) - return { dailyFees, timestamp } + return { dailyFees } } const adapter: Adapter = { @@ -90,6 +90,7 @@ const adapter: Adapter = { fetch, start: 1688256000 } - } + }, + version: 2 } export default adapter diff --git a/fees/bmx-freestyle.ts b/fees/bmx-freestyle.ts new file mode 100644 index 0000000000..925280474a --- /dev/null +++ b/fees/bmx-freestyle.ts @@ -0,0 +1,113 @@ +import BigNumber from "bignumber.js"; +import request, { gql } from "graphql-request"; +import { FetchOptions, SimpleAdapter } from "../adapters/types"; +import { CHAIN } from "../helpers/chains"; + +const endpoint = + "https://api-v2.morphex.trade/subgraph/3KhmYXgsM3CM1bbUCX8ejhcxQCtWwpUGhP7p9aDKZ94Z"; + +const query = gql` + query stats($from: String!, $to: String!) { + dailyHistories( + where: { + timestamp_gte: $from + timestamp_lte: $to + accountSource: "0x6D63921D8203044f6AbaD8F346d3AEa9A2719dDD" + } + ) { + timestamp + platformFee + accountSource + tradeVolume + } + totalHistories( + where: { accountSource: "0x6D63921D8203044f6AbaD8F346d3AEa9A2719dDD" } + ) { + timestamp + platformFee + accountSource + tradeVolume + } + } +`; + +interface IGraphResponse { + dailyHistories: Array<{ + tiemstamp: string; + platformFee: string; + accountSource: string; + tradeVolume: string; + }>; + totalHistories: Array<{ + tiemstamp: string; + platformFee: string; + accountSource: string; + tradeVolume: BigNumber; + }>; +} + +const toString = (x: BigNumber) => { + if (x.isEqualTo(0)) return undefined; + return x.toString(); +}; + +const fetchVolume = async ({ endTimestamp, startTimestamp }: FetchOptions) => { + const response: IGraphResponse = await request(endpoint, query, { + from: String(startTimestamp), + to: String(endTimestamp), + }); + + // Merging both responses + let dailyFees = new BigNumber(0); + response.dailyHistories.forEach((data) => { + dailyFees = dailyFees.plus(new BigNumber(data.platformFee)); + }); + + let totalFees = new BigNumber(0); + response.totalHistories.forEach((data) => { + totalFees = totalFees.plus(new BigNumber(data.platformFee)); + }); + + dailyFees = dailyFees.dividedBy(new BigNumber(1e18)); + totalFees = totalFees.dividedBy(new BigNumber(1e18)); + + const _dailyFees = toString(dailyFees); + const _totalFees = toString(totalFees); + + const dailyUserFees = _dailyFees; + const dailyRevenue = _dailyFees; + const dailyProtocolRevenue = "0"; + const dailyHoldersRevenue = _dailyFees; + const dailySupplySideRevenue = "0"; + + const totalUserFees = _totalFees; + const totalRevenue = _totalFees; + const totalProtocolRevenue = "0"; + const totalSupplySideRevenue = "0"; + + return { + dailyFees: _dailyFees ?? "0", + totalFees: _totalFees ?? "0", + + dailyUserFees: dailyUserFees ?? "0", + dailyRevenue: dailyRevenue ?? "0", + dailyProtocolRevenue: dailyProtocolRevenue ?? "0", + dailyHoldersRevenue: dailyHoldersRevenue ?? "0", + dailySupplySideRevenue: dailySupplySideRevenue ?? "0", + totalUserFees: totalUserFees ?? "0", + totalRevenue: totalRevenue ?? "0", + totalProtocolRevenue: totalProtocolRevenue ?? "0", + totalSupplySideRevenue: totalSupplySideRevenue ?? "0", + }; +}; + +const adapter: SimpleAdapter = { + version: 2, + adapter: { + [CHAIN.BASE]: { + fetch: fetchVolume, + start: 1714554000, + }, + }, +}; +export default adapter; diff --git a/fees/bmx.ts b/fees/bmx.ts index 89a9051cf5..b359527d08 100644 --- a/fees/bmx.ts +++ b/fees/bmx.ts @@ -1,26 +1,28 @@ import { Adapter } from "../adapters/types"; import { CHAIN } from "../helpers/chains"; import { request, gql } from "graphql-request"; +import type { FetchV2 } from "../adapters/types"; import { getTimestampAtStartOfDayUTC } from "../utils/date"; const endpoints: { [key: string]: string } = { [CHAIN.BASE]: - "https://api.thegraph.com/subgraphs/name/morphex-labs/bmx-base-stats", + "https://api-v2.morphex.trade/subgraph/2vZHkWfx8g27Tri5LkTbhvCExCQcXJ3f28X2BwzFhjf6", + [CHAIN.MODE]: + "https://api-v2.morphex.trade/subgraph/8tp7xrDSCuutJ5omjfQKHvkGJpLszqPVWg3pby9XMLEz", }; const methodology = { Fees: "Fees from open/close position (0.1%), liquidations, swap (0.2% to 0.8%), mint and burn (based on tokens balance in the pool) and borrow fee ((assets borrowed)/(total assets in pool)*0.01%)", UserFees: "Fees from open/close position (0.1%), swap (0.2% to 0.8%) and borrow fee ((assets borrowed)/(total assets in pool)*0.01%)", - HoldersRevenue: "30% of all collected fees are distributed to BMX/wBLT LP stakers", + HoldersRevenue: "10% of all collected fees are distributed to BMX stakers", SupplySideRevenue: "60% of all collected fees are distributed to BLT stakers", Revenue: - "Governance revenue is 30% of all collected fees, which are distributed to BMX/wBLT LP stakers", - ProtocolRevenue: "10% of all collected fees are distributed to the treasury", + "Revenue is 40% of all collected fees, which are distributed to BMX/wBLT LP stakers and BMX stakers", }; -const graphs = (chain: string) => async (timestamp: number) => { - const todaysTimestamp = getTimestampAtStartOfDayUTC(timestamp); +const graphs: FetchV2 = async ({ chain, endTimestamp }) => { + const todaysTimestamp = getTimestampAtStartOfDayUTC(endTimestamp); const searchTimestamp = todaysTimestamp + ":daily"; const graphQuery = gql`{ @@ -46,25 +48,31 @@ const graphs = (chain: string) => async (timestamp: number) => { const finalUserFee = userFee / 1e30; return { - timestamp, dailyFees: finalDailyFee.toString(), dailyUserFees: finalUserFee.toString(), - dailyRevenue: (finalDailyFee * 0.3).toString(), - dailyProtocolRevenue: (finalDailyFee * 0.1).toString(), - dailyHoldersRevenue: (finalDailyFee * 0.3).toString(), + dailyRevenue: (finalDailyFee * 0.4).toString(), + dailyHoldersRevenue: (finalDailyFee * 0.4).toString(), dailySupplySideRevenue: (finalDailyFee * 0.6).toString(), }; }; const adapter: Adapter = { + version: 2, adapter: { [CHAIN.BASE]: { - fetch: graphs(CHAIN.BASE), + fetch: graphs, start: 1694304000, meta: { methodology, }, }, + [CHAIN.MODE]: { + fetch: graphs, + start: 1720627435, + meta: { + methodology, + }, + }, }, }; diff --git a/fees/boba.ts b/fees/boba.ts index 7af9bff6d5..9e4a5c396e 100644 --- a/fees/boba.ts +++ b/fees/boba.ts @@ -8,6 +8,7 @@ const ethereumWallets = [ ] const adapter: Adapter = { + version: 2, adapter: { [CHAIN.BOBA]: { fetch: L2FeesFetcher({ ethereumWallets, }), diff --git a/fees/bonk-bot/index.ts b/fees/bonk-bot/index.ts index 920ed1e1c7..f77c102f91 100644 --- a/fees/bonk-bot/index.ts +++ b/fees/bonk-bot/index.ts @@ -19,13 +19,15 @@ const fetchFees = async (timestamp: number): Promise => { } const adapter: SimpleAdapter = { + version: 1, adapter: { [CHAIN.SOLANA]: { fetch: fetchFees, start: 1692748800, runAtCurrTime: true, } - } + }, + isExpensiveAdapter: true } export default adapter; diff --git a/fees/bsc.ts b/fees/bsc.ts index 9671c64273..eac92f0bdf 100644 --- a/fees/bsc.ts +++ b/fees/bsc.ts @@ -1,19 +1,19 @@ +import * as sdk from "@defillama/sdk"; import { Adapter, ProtocolType } from "../adapters/types"; import { BSC } from "../helpers/chains"; import { request, } from "graphql-request"; import type { ChainEndpoints, FetchOptions } from "../adapters/types" import { Chain } from '@defillama/sdk/build/general'; -import { ChainBlocks } from "../adapters/types"; const endpoints = { [BSC]: - "https://api.thegraph.com/subgraphs/name/dmihal/bsc-validator-rewards" + sdk.graph.modifyEndpoint('3a3f5kp31kutZzjmQoE2NKBSr6Ady5rgxRxD2nygYcQo') } const graphs = (graphUrls: ChainEndpoints) => { return (chain: Chain) => { - return async (timestamp: number, _chainBlocks: ChainBlocks, { createBalances, getFromBlock, getToBlock, }: FetchOptions) => { + return async ({ createBalances, getFromBlock, getToBlock, toTimestamp }: FetchOptions) => { const dailyFees = createBalances() const graphQuery = `query txFees { @@ -32,9 +32,9 @@ const graphs = (graphUrls: ChainEndpoints) => { dailyFees.addGasToken(dailyFee * 1e18) return { - timestamp, dailyFees, + dailyFees, // totalFees: finalTotalFee.toString(), - dailyRevenue: timestamp < 1638234000 ? 0: dailyFees.clone(0.1), // https://github.com/bnb-chain/BEPs/blob/master/BEP95.md + dailyRevenue: toTimestamp < 1638234000 ? 0: dailyFees.clone(0.1), // https://github.com/bnb-chain/BEPs/blob/master/BEP95.md }; }; }; @@ -42,6 +42,7 @@ const graphs = (graphUrls: ChainEndpoints) => { const adapter: Adapter = { + version: 2, adapter: { [BSC]: { fetch: graphs(endpoints)(BSC), diff --git a/fees/buffer/index.ts b/fees/buffer/index.ts index 1f1a4e0a0d..d2da616c39 100644 --- a/fees/buffer/index.ts +++ b/fees/buffer/index.ts @@ -1,60 +1,46 @@ import { CHAIN } from "../../helpers/chains"; import { request, gql } from "graphql-request"; -import type { ChainEndpoints } from "../../adapters/types" -import { Chain } from '@defillama/sdk/build/general'; +import type { ChainEndpoints } from "../../adapters/types"; +import { Chain } from "@defillama/sdk/build/general"; import BigNumber from "bignumber.js"; -import { getTimestampAtStartOfDayUTC } from "../../utils/date"; -import { Adapter } from "../../adapters/types" +import { Adapter } from "../../adapters/types"; const endpoints = { - [CHAIN.ARBITRUM]: "https://subgraph.satsuma-prod.com/e66b06ce96d2/bufferfinance/v2.5-arbitrum-mainnet/api" -} + [CHAIN.ARBITRUM]: "https://satsuma-dump.buffer.finance/", +}; export function _getDayId(timestamp: number): string { let dayTimestamp = Math.floor((timestamp - 16 * 3600) / 86400); return dayTimestamp.toString(); } -const graphs = (graphUrls: ChainEndpoints) => { +const graphs = (baseUrls: ChainEndpoints) => { return (chain: Chain) => { return async (timestamp: number) => { const dateId = _getDayId(timestamp); - const graphQuery = gql - `{ - defillamaFeeStat(id: ${dateId}) { - fee - } - }`; - - const graphRes = await request(graphUrls[chain], graphQuery); - - const dailyFee = new BigNumber(graphRes.defillamaFeeStat.fee).div(1000000); - // const protocolRev = new BigNumber(graphRes.dailyRevenueAndFee.settlementFee).div(1000000).times(0.05); - // const userHolderRev = new BigNumber(graphRes.dailyRevenueAndFee.settlementFee).div(1000000).times(0.4); - // const supplySideRev = new BigNumber(graphRes.dailyRevenueAndFee.settlementFee).div(1000000).times(0.55); - const dailyRev = new BigNumber(graphRes.defillamaFeeStat.fee).div(1000000); + const url = new URL(baseUrls[chain]); + url.searchParams.append("day", dateId); + const response = await fetch(url); + const dailyFee = (await response.json()).fee / 1000000; return { timestamp, dailyFees: dailyFee.toString(), - // dailyProtocolRevenue: protocolRev.toString(), - // dailyUserHolderRevenue: userHolderRev.toString(), - // dailySupplySideRevenue: supplySideRev.toString(), - dailyRevenue: dailyRev.toString() + dailyRevenue: dailyFee.toString(), }; }; }; }; - const adapter: Adapter = { adapter: { [CHAIN.ARBITRUM]: { - fetch: graphs(endpoints)(CHAIN.ARBITRUM), - start: 1674950400 , + fetch: graphs(endpoints)(CHAIN.ARBITRUM), + start: 1674950400, }, - } -} + }, + version: 1, +}; export default adapter; diff --git a/fees/cakepie.ts b/fees/cakepie.ts new file mode 100644 index 0000000000..f7d90e2e48 --- /dev/null +++ b/fees/cakepie.ts @@ -0,0 +1,69 @@ +import { FetchOptions, SimpleAdapter } from "../adapters/types"; +import { CHAIN } from "../helpers/chains"; +import { Chain } from "@defillama/sdk/build/general"; + +const event_paid_stream = 'event V3PoolFeesPaidTo (address indexed _user, uint256 _positionId, address _token, uint256 _feeAmount)'; +const event_paid_bribe = 'event NewBribe ( address indexed _user, uint256 indexed _targetTime, address _pool, address _bribeToken, uint256 _amount)'; + +type TAddress = { + [c: string]: string; +} +const address_reward: TAddress = { + + [CHAIN.BSC]: '0xb47b790076050423888cde9EBB2D5Cb86544F327', + [CHAIN.ARBITRUM]: '0x6DB96BBEB081d2a85E0954C252f2c1dC108b3f81', + [CHAIN.ETHEREUM]: '0x6E799758CEE75DAe3d84e09D40dc416eCf713652' +} + +const address_bribe: TAddress = { + [CHAIN.BSC]: '0xD521BF2Fd3c625101feAE9717351EF1E1E702dDF', + [CHAIN.ARBITRUM]: '0xA08d8e0aEe5929BcD6D72323A2EaCde4Cc951b71', + [CHAIN.ETHEREUM]: '0xa346Bd80943Aa3042E6709d80Ce9C3b8fbeAc4Ab' +} + +//cake emissions and vote incentives for pools are the revenue +const graph = (chain: Chain) => { + return async ({ createBalances, getLogs, }: FetchOptions) => { + const dailyFees = createBalances(); + if (chain=='BSC'){ + (await getLogs({ + target: address_reward[chain], + eventAbi: event_paid_stream, + })).map((e: any) => { + // check if it is cake address + if (e.token === '0x0e09fabb73bd3ade0a17ecc321fd13a19e81ce82') { + dailyFees.add(e._token, e._feeAmount); + } + }) + } + (await getLogs({ + target: address_bribe[chain], + eventAbi: event_paid_bribe, + })).map((e: any) => { + dailyFees.add(e._bribeToken, e._amount) + }) + return { dailyFees, dailyRevenue: dailyFees,dailyUserFees:dailyFees }; + } +} + + +const adapter: SimpleAdapter = { + version: 2, + adapter: { + + [CHAIN.BSC]: { + fetch: graph(CHAIN.BSC), + start: 77678653, + }, + [CHAIN.ARBITRUM]: { + fetch: graph(CHAIN.ARBITRUM), + start: 77678653, + }, + [CHAIN.ETHEREUM]: { + fetch: graph(CHAIN.ETHEREUM), + start: 77678653, + }, + } +}; + +export default adapter; diff --git a/fees/camelot-v2.ts b/fees/camelot-v2.ts new file mode 100644 index 0000000000..41ed9d5a24 --- /dev/null +++ b/fees/camelot-v2.ts @@ -0,0 +1,59 @@ +import * as sdk from "@defillama/sdk"; +import { Chain } from "@defillama/sdk/build/general"; +import BigNumber from "bignumber.js"; +import request, { gql } from "graphql-request"; +import { Adapter, FetchOptions, FetchResultV2 } from "../adapters/types"; +import { CHAIN } from "../helpers/chains"; + +interface IPoolData { + date: number; + dailyFeeUSD: string; +} + +type IURL = { + [l: string | Chain]: string; +} + +const endpoints: IURL = { + [CHAIN.ARBITRUM]: sdk.graph.modifyEndpoint('8zagLSufxk5cVhzkzai3tyABwJh53zxn9tmUYJcJxijG') +} + +const fetch = async (options: FetchOptions): Promise => { + const graphQuery = gql + ` + { + pairDayDatas(where:{date_gte:${options.fromTimestamp}, date_lte:${options.endTimestamp}, reserveUSD_gt:1000}, orderBy:dailyFeeUSD, orderDirection:desc) { + id + dailyFeeUSD + reserveUSD + } + } + `; + + const graphRes: IPoolData[] = (await request(endpoints[options.chain], graphQuery)).pairDayDatas; + const dailyFeeUSD = graphRes; + const dailyFee = dailyFeeUSD.reduce((acc, pool) => { + return acc.plus(pool.dailyFeeUSD); + }, new BigNumber(0)); + return { + dailyFees: dailyFee.toString(), + dailyUserFees: dailyFee.toString(), + dailyRevenue: dailyFee.multipliedBy(0.4).toString(), + dailyProtocolRevenue: dailyFee.multipliedBy(0.05).toString(), + dailyHoldersRevenue: dailyFee.multipliedBy(0.35).toString(), + dailySupplySideRevenue: dailyFee.multipliedBy(0.60).toString(), + }; + +} + +const adapter: Adapter = { + version: 2, + adapter: { + [CHAIN.ARBITRUM]: { + fetch: fetch, + start: 1668124800, + }, + }, +}; + +export default adapter; diff --git a/fees/camelot-v3.ts b/fees/camelot-v3.ts index 1be6b91f93..cca490566f 100644 --- a/fees/camelot-v3.ts +++ b/fees/camelot-v3.ts @@ -1,3 +1,4 @@ +import * as sdk from "@defillama/sdk"; import { Chain } from "@defillama/sdk/build/general"; import BigNumber from "bignumber.js"; import request, { gql } from "graphql-request"; @@ -16,7 +17,7 @@ type IURL = { } const endpoints: IURL = { - [CHAIN.ARBITRUM]: "https://api.thegraph.com/subgraphs/name/camelotlabs/camelot-amm-v3" + [CHAIN.ARBITRUM]: sdk.graph.modifyEndpoint('7mPnp1UqmefcCycB8umy4uUkTkFxMoHn1Y7ncBUscePp') } const fetch = (chain: Chain) => { @@ -50,6 +51,7 @@ const fetch = (chain: Chain) => { } const adapter: Adapter = { + version: 1, adapter: { [CHAIN.ARBITRUM]: { fetch: fetch(CHAIN.ARBITRUM), diff --git a/fees/camelot.ts b/fees/camelot.ts deleted file mode 100644 index d4c24011da..0000000000 --- a/fees/camelot.ts +++ /dev/null @@ -1,61 +0,0 @@ -import { Chain } from "@defillama/sdk/build/general"; -import BigNumber from "bignumber.js"; -import request, { gql } from "graphql-request"; -import { Adapter, FetchResultFees } from "../adapters/types"; -import { CHAIN } from "../helpers/chains"; -import { getUniqStartOfTodayTimestamp } from "../helpers/getUniSubgraphVolume"; -import { getTimestampAtStartOfDayUTC } from "../utils/date"; - -interface IPoolData { - date: number; - dailyFeeUSD: string; -} - -type IURL = { - [l: string | Chain]: string; -} - -const endpoints: IURL = { - [CHAIN.ARBITRUM]: "https://api.thegraph.com/subgraphs/name/camelotlabs/camelot-amm-2" -} - -const fetch = (chain: Chain) => { - return async (timestamp: number): Promise => { - const todayTimestamp = getUniqStartOfTodayTimestamp(new Date(timestamp * 1000)); - const dateId = Math.floor(getTimestampAtStartOfDayUTC(todayTimestamp) / 86400) - const graphQuery = gql - ` - { - uniswapDayData(id: ${dateId}) { - id - dailyFeeUSD - } - } - `; - - const graphRes: IPoolData = (await request(endpoints[chain], graphQuery)).uniswapDayData; - const dailyFeeUSD = graphRes; - const dailyFee = dailyFeeUSD?.dailyFeeUSD ? new BigNumber(dailyFeeUSD.dailyFeeUSD) : undefined - if (dailyFee === undefined) return { timestamp } - return { - timestamp, - dailyFees: dailyFee.toString(), - dailyUserFees: dailyFee.toString(), - dailyRevenue: dailyFee.multipliedBy(0.4).toString(), - dailyProtocolRevenue: dailyFee.multipliedBy(0.05).toString(), - dailyHoldersRevenue: dailyFee.multipliedBy(0.35).toString(), - dailySupplySideRevenue: dailyFee.multipliedBy(0.60).toString(), - }; - }; -} - -const adapter: Adapter = { - adapter: { - [CHAIN.ARBITRUM]: { - fetch: fetch(CHAIN.ARBITRUM), - start: 1668124800, - }, - }, -}; - -export default adapter; diff --git a/fees/canto.ts b/fees/canto.ts index 8062aa9054..7daa9c618e 100644 --- a/fees/canto.ts +++ b/fees/canto.ts @@ -1,4 +1,4 @@ import { CHAIN } from "../helpers/chains"; import { blockscoutFeeAdapter } from "../helpers/blockscoutFees"; -export default blockscoutFeeAdapter(CHAIN.CANTO, "https://evm.explorer.canto.io/api?module=stats&action=totalfees", "canto") \ No newline at end of file +export default blockscoutFeeAdapter(CHAIN.CANTO, "https://explorer.plexnode.wtf/api/v2/stats?module=stats&action=totalfees", "canto") \ No newline at end of file diff --git a/fees/cardano.ts b/fees/cardano.ts index 247fb855cd..1332e4591e 100644 --- a/fees/cardano.ts +++ b/fees/cardano.ts @@ -54,6 +54,7 @@ const fetch = async (timestamp: number , _: ChainBlocks, { createBalances }: Fet }; const adapter: Adapter = { + version: 1, adapter: { [CHAIN.CARDANO]: { fetch: fetch, diff --git a/fees/caviar-tangible.ts b/fees/caviar-tangible.ts index ebf5c269dc..39bc7734a3 100644 --- a/fees/caviar-tangible.ts +++ b/fees/caviar-tangible.ts @@ -1,20 +1,20 @@ import ADDRESSES from '../helpers/coreAssets.json' -import { ChainBlocks, FetchOptions, FetchResultFees, SimpleAdapter } from "../adapters/types" +import { FetchOptions, SimpleAdapter } from "../adapters/types" import { CHAIN } from "../helpers/chains" import { addTokensReceived } from '../helpers/token'; -const fetchFees = async (timestamp: number , _: ChainBlocks, options: FetchOptions): Promise => { +const fetchFees = async (options: FetchOptions) => { const dailyFees = await addTokensReceived({ options, tokens: [ADDRESSES.polygon.USDC], fromAddressFilter: '0xbbc843dcb1009bc7dc988bceb5bb1b50299d9a6d' , target: '0x6ced48efbb581a141667d7487222e42a3fa17cf7' }) return { dailyFees: dailyFees, dailyHoldersRevenue: dailyFees, dailyRevenue: dailyFees, - timestamp } } const adapter: SimpleAdapter = { + version: 2, adapter: { [CHAIN.POLYGON]: { fetch: fetchFees, diff --git a/fees/caviarnine-lsu-pool.ts b/fees/caviarnine-lsu-pool.ts index b452fad321..ff9214e08c 100644 --- a/fees/caviarnine-lsu-pool.ts +++ b/fees/caviarnine-lsu-pool.ts @@ -28,6 +28,7 @@ const fetchFees = async (timestamp: number): Promise => { } const adapters: SimpleAdapter = { + version: 1, adapter: { [CHAIN.RADIXDLT]: { fetch: fetchFees, diff --git a/fees/caviarnine-shape-liquidity.ts b/fees/caviarnine-shape-liquidity.ts index b1621482b8..da74790160 100644 --- a/fees/caviarnine-shape-liquidity.ts +++ b/fees/caviarnine-shape-liquidity.ts @@ -30,6 +30,7 @@ const fetchFees = async (timestamp: number): Promise => { } } const adapters: SimpleAdapter = { + version: 1, adapter: { [CHAIN.RADIXDLT]: { fetch: fetchFees, diff --git a/fees/cellula/index.ts b/fees/cellula/index.ts new file mode 100644 index 0000000000..abab1bf826 --- /dev/null +++ b/fees/cellula/index.ts @@ -0,0 +1,74 @@ +import { CHAIN } from "../../helpers/chains"; +import { Adapter, FetchV2 } from "../../adapters/types"; + +const CELL_ADDRESS = "0xa258107cb9dcd325a37c7d65a7f4850bb9986bc6"; +const CELL_ABI = "event MintFeeReceived(uint256 tokenId, uint256 amount)" + +const LIFE_ADDRESS = "0xabd1780208a62b9cbf9d3b7a1617918d42493933"; +const LIFE_ABI = "event FeedEvent(uint256 tokenId, uint256 startTime, uint256 workTime)" + +const methodology = { + Fees: "The cost of renting a Cell.", + Revenue: "The sum of life charging fees and life mint fees.", +}; +const adapter: Adapter = { + adapter: { + [CHAIN.BSC]: { + fetch: (async ({ getLogs, createBalances, }) => { + // Fees + // const totalFees = createBalances() + const dailyFees = createBalances() // ✅ + + // Revenue + const dailyRevenue = createBalances() // ✅ + const dailyProtocolRevenue = createBalances() // 70% + Food + const dailyHoldersRevenue = createBalances() // 5% + const dailySupplySideRevenue = createBalances() // 25% + // const totalRevenue = createBalances() + // const totalProtocolRevenue = createBalances() + // const totalSupplySideRevenue = createBalances() + // const totalUserFees = createBalances() + // const dailyBribesRevenue = createBalances() + // const dailyTokenTaxes = createBalances() + + const logs = await getLogs({ target: CELL_ADDRESS, eventAbi: CELL_ABI }) + logs.map((e: any) => { + dailyFees.addGasToken(e.amount * BigInt(20)) + + dailyRevenue.addGasToken(e.amount * BigInt(20)) + dailyProtocolRevenue.addGasToken(e.amount * BigInt(14)) + dailyHoldersRevenue.addGasToken(e.amount) + dailySupplySideRevenue.addGasToken(e.amount * BigInt(5)) + }) + const buyFoodLogs = await getLogs({ target: LIFE_ADDRESS, eventAbi: LIFE_ABI }) + // 0.0017 BNB / 1 D + // 0.0051 BNB / 3 D + // 0.0119 BNB / 7 D + const workTimePrice = { + "86400": "1700000000000000", + "259200": "5100000000000000", + "604800": "11900000000000000", + } + buyFoodLogs.map(e => { + if (!workTimePrice[e.workTime]) { + return + } + dailyFees.addGasToken(workTimePrice[e.workTime]) + dailyRevenue.addGasToken(workTimePrice[e.workTime]) + dailyProtocolRevenue.addGasToken(workTimePrice[e.workTime]) + }) + return { + dailyFees, + dailyRevenue, dailyProtocolRevenue, dailyHoldersRevenue, dailySupplySideRevenue + } + }) as FetchV2, + start: 1713052800, + meta: { + methodology + }, + }, + }, + version: 2, +} + +export default adapter; diff --git a/fees/cetus/index.ts b/fees/cetus/index.ts new file mode 100644 index 0000000000..29fbb5bfb8 --- /dev/null +++ b/fees/cetus/index.ts @@ -0,0 +1,49 @@ +import { Adapter, FetchResultV2, FetchV2 } from '../../adapters/types'; +import { CHAIN } from '../../helpers/chains'; +import fetchURL from '../../utils/fetchURL'; + +const cetusApiURL = 'https://api-sui.cetus.zone/v2/sui/daily-fees'; + +interface CetusStats { + data:{ + fee: string; + protocolFee: string; + } +} + +const methodology = { + Fees: 'Swap fees generated by the swap transactions on Cetus Protocol.', + ProtocolRevenue: 'Protocol fees charged from the swap fees.', +}; + +const fetchCetusStats: FetchV2 = async ({ + startTimestamp, + endTimestamp, +}): Promise => { + const url = `${cetusApiURL}?fromTimestamp=${startTimestamp}&toTimestamp=${endTimestamp}`; + const { data }: CetusStats = await fetchURL(url); + const dailyFees = data.fee; + const dailyRevenue = data.protocolFee; + return { + dailyFees: dailyFees, + dailyRevenue: dailyRevenue, + dailyProtocolRevenue: dailyRevenue, + }; +}; + +const adapter: Adapter = { + version: 2, + adapter: { + [CHAIN.SUI]: { + runAtCurrTime: false, + customBackfill: undefined, + fetch: fetchCetusStats, + start: 1704067200, + meta: { + methodology, + }, + }, + }, +}; + +export default adapter; diff --git a/fees/chainflip/index.ts b/fees/chainflip/index.ts new file mode 100644 index 0000000000..edf64f7123 --- /dev/null +++ b/fees/chainflip/index.ts @@ -0,0 +1,57 @@ +import { SimpleAdapter } from "../../adapters/types"; +import { CHAIN } from "../../helpers/chains"; +import { httpGet } from "../../utils/fetchURL"; + +const dimensionsEndpoint = "https://chainflip-broker.io/defillama/fees" + +const fetch = async (timestamp: number) => { + const dimensionsData = await httpGet(`${dimensionsEndpoint}?timestamp=${timestamp}`, { headers: {"x-client-id": "defillama"}}); + + return { + timestamp: timestamp, + + // All fees and value collected from all sources, this also includes liquid staking rewards, generated yields and possible mint and burn fees paid by LP (but not transaction or gas fees). + dailyFees: dimensionsData.dailyFees, + + // Fees paid by protocol users excluding gas fees. This includes swap fees to open/close positions, borrow fees and all fees user has to pay. + dailyUserFees: dimensionsData.dailyUserFees, + + // (FLIP Burn) Revenue of the protocol governance, this includes treasury and gov token holders + dailyRevenue: dimensionsData.dailyRevenue, + + // Value earned by liquidity providers + dailySupplySideRevenue: dimensionsData.dailySupplySideRevenue, + + // Cumulative value of dailyFees + totalFees: dimensionsData.totalFees, + + // Cumulative value of dailyUserFees + totalUserFees: dimensionsData.totalUserFees, + + // Cumulative value of dailyRevenue + totalRevenue: dimensionsData.totalRevenue, + + // Cumulative value of dailySupplySideRevenue + totalSupplySideRevenue: dimensionsData.totalSupplySideRevenue + }; +}; + +const adapter: SimpleAdapter = { + adapter: { + [CHAIN.CHAINFLIP]: { + fetch, + start: 1717113600, // First decent swap was 2024-05-31 09:22:30.000000 + runAtCurrTime: true, + meta: { + methodology: { + Fees: "Ingress, Broker, LP, Protocol and Egress fees.", + UserFees: "Broker, LP, Protocol fees.", + Revenue: "Protocol burns 0.10% of each swap.", + SupplySideRevenue: "LP pools have a 0.05% fee.", + } + } + }, + }, +}; + +export default adapter; diff --git a/fees/chainlink-ccip.ts b/fees/chainlink-ccip.ts index 195244ef4f..7b5e304aba 100644 --- a/fees/chainlink-ccip.ts +++ b/fees/chainlink-ccip.ts @@ -1,13 +1,8 @@ -import ADDRESSES from '../helpers/coreAssets.json' -import { Chain } from "@defillama/sdk/build/general"; -import { FetchResultFees, SimpleAdapter } from "../adapters/types"; +import { FetchOptions, FetchResultV2, SimpleAdapter } from "../adapters/types"; import { CHAIN } from "../helpers/chains"; -import { getBlock } from "../helpers/getBlock"; -import * as sdk from "@defillama/sdk"; -import { getPrices } from "../utils/prices"; -const topic_0 = '0xaffc45517195d6499808c643bd4a7b0ffeedf95bea5852840d7bfcf63f59e821'; +const topic_0 = '0xd0c3c799bf9e2639de44391e7f524d229b2b55f5b1ea94b2bf7da42f7243dddd'; type IContractAddress = { [k: string]: string[]; } @@ -25,145 +20,128 @@ interface ILog { const contract_address: IContractAddress = { [CHAIN.ETHEREUM]: [ - '0xd0b5fc9790a6085b048b8aa1ed26ca2b3b282cf2', - '0x0f27c8532457b66d6037141deb0ed479dad04b3c', - '0xcc19bc4d43d17eb6859f0d22ba300967c97780b0', - '0x181314cec446cd372e555a26fc3bff3c714cd838', - '0x70349b74888b1364ee4862d9ef8cb1af7ab47464', - '0x1c0c7858c7ad7a6b3f4aa813ee81e56d7405c712', - '0x5b0c089abf23b9f078a59c683abf015773f25f66', - '0xe94b16e0fa1f6ff0a28e1dece4946ffb5748c595', - '0xf1e3d79b19b1c810812cc0ce991e6421511f2824', - '0xdf1d7fd22ac3ab5171e275796f123224039f3b24', - '0x333f976915195ba9044fd0cd603cece936f6264e', - '0xe2eb229e88f56691e96bb98256707bc62160fe73', - '0xe5c9121cc3f796a8446b9d35b0d53b67eb4c1ab2', + '0x35F0ca9Be776E4B38659944c257bDd0ba75F1B8B', + '0x86b47d8411006874eef8e4584bdfd7be8e5549d1', + '0xf538da6c673a30338269655f4e019b71ba58cfd4', + '0xcbe7e5da76dc99ac317adf6d99137005fda4e2c4', + '0x925228d7b82d883dde340a55fe8e6da56244a22c', + '0xe2c2ab221aa0b957805f229d2aa57fbe2f4dadf7', + '0x91d25a56db77ad5147437d8b83eb563d46ebfa69', + '0x3df8dae2d123081c4d5e946e655f7c109b9dd630' ], [CHAIN.ARBITRUM]: [ - '0x98dd9e9b8ae458225119ab5b8c947a9d1cd0b648', - '0x6264f5c5bc1c0201159a5bcd6486d9c6c2f75439', - '0x590791aa846ec4d2aa2b8697edeb6158f6054839', - '0x9409b222c96ae8377db6a4b6645350f7dc94e9ef', + '0x122f05f49e90508f089ee8d0d868d1a4f3e5a809', + '0x66a0046ac9fa104eb38b04cff391ccd0122e6fbc', + '0x77b60f85b25fd501e3dded6c1fe7bf565c08a22a', + '0xc09b72e8128620c40d89649019d995cc79f030c3', + '0x79f3abece5a3afff32d47f4cfe45e7b65c9a2d91', + '0x05b723f3db92430fbe4395fd03e40cc7e9d17988', + '0xce11020d56e5fdbfe46d9fc3021641ffbbb5adee', ], [CHAIN.OPTIMISM]: [ - '0xad1b1f2a6dd55627e3893b771a00cd43f69dce35', - '0xd9fb89196c902d46c07ca91e492d3e0c77a5bf93', - '0xf06a2e32477363bcacae5b86479e176ca83d3f9d', - '0xb188bd6cc347299eebb3ae93f57d90f580536b3a', - '0xc40f7c8763e35fb64ab968dc812c2d24c6f8404c', - '0x872f782a861519b3fdfb1060649f4c8343d806fe', + '0x0c9be7cfd12c735e5aae047c1dcb845d54e518c3', + '0x55183db1d2ae0b63e4c92a64bef2cbfc2032b127', + '0xa3c9544b82846c45be37593d5d9acffbe61bf3a6', + '0x82e9f4c5ec4a84e310d60d462a12042e5cba0954', + '0x0b1760a8112183303c5526c6b24569fd3a274f3b', + '0x6b57145e322c877e7d91ed8e31266eb5c02f7efc', + '0xd0d3e757bfbce7ae1881ddd7f6d798ddce588445', ], [CHAIN.BSC]: [ - '0x1f17d464652f5bd74a03446fea20590ccfb3332d', - '0xcad54be1a4bc5e467cd5b53896eb692d9f6956cd', - '0xfdc26aa261655580f7ac413927983f664291fd22', - '0xf7c9b607cf09b4048f09c84236ce7f11df6d6364', + '0x1467ff8f249f5bc604119af26a47035886f856be', + '0x2788b46bacff49bd89562e6ba5c5fbbbe5fa92f7', + '0x6aa72a998859ef93356c6521b72155d355d0cfd2', + '0x0bf40b034872d0b364f3dcec04c7434a4da1c8d9', + '0x6bd4754d86fc87fe5b463d368f26a3587a08347c', + '0x70bc7f7a6d936b289bbf5c0e19ece35b437e2e36', + '0x4feb11a454c9e8038a8d0adf599fe7612ce114ba', ], [CHAIN.BASE]: [ - '0xd44371bfde87f2db3ea6df242091351a06c2e181', - '0xe96563b8a6b4ea245e7fcefaba813104fc889c6c', - '0x064f0960ab66f44a5e6c7d2335b19de4bb75aa0d', - '0x223953db4e0a4c33bac1b17b0df1c22919984c60', + '0xd952feacdd5919cc5e9454b53bf45d4e73dd6457', + '0x1e5ca70d1e7a1b26061125738a880bbea42feb21', + '0x3db8bea142e41ca3633890d0e5640f99a895d6a5', + '0xdd4fb402d41beb0eeef6cfb1bf445f50bdc8c981', + '0xbe5a9e336d9614024b4fa10d8112671fc9a42d96', + '0xdea286dc0e01cb4755650a6cf8d1076b454ea1cb', ], [CHAIN.POLYGON]: [ - '0x84347c236f4d4fb27673929899e554ab1151aa73', - '0xae0e486fa6577188d586a8e4c12360fb82e2a386', - '0x21f786fd1f6734b86ecaaf25fda67c0e6a730d41', - '0x47d945f7bbb814b65775a89c71f5d2229be96ce9', - '0xffaacdd8fb3af6ada58ababaec549587c81351bf', - '0xd8e79def51a98b71c98b4c19d4a314341670ac36', - '0xb0fdecbfcdb211b5db4fcc44a27d2d7d66d582d0', + '0x5fa30697e90eb30954895c45b028f7c0ddd39b12', + '0x3111cfbf5e84b5d9bd952dd8e957f4ca75f728cf', + '0xfd77c53aa4ef0e3c01f5ac012bf7cc7a3ecf5168', + '0x20b028a2e0f6cce3a11f3ce5f2b8986f932e89b4', + '0xd16d025330edb91259eea8ed499dacd39087c295', + '0x5060ef647a1f66be6ee27fae3046faf8d53ceb2d', + '0x4616621704c81801a56d29c961f9395ee153d46c', + '0xf5b5a2fc11bf46b1669c3b19d98b19c79109dca9', ], [CHAIN.AVAX]: [ - '0x3d3817270db2b89e9f68ba27297fb4672082f942', - '0x2d306510fe83cdb33ff1658c71c181e9567f0009', - '0xb4e2776aeab42ba24ac10cd9c73b985845597402', - '0x82834e4d676a1d7a1e1969d0356515e973e6b460', + '0xd0701fcc7818c31935331b02eb21e91ec71a1704', + '0x97500490d9126f34cf9aa0126d64623e170319ef', + '0x9b1ed9de069be4d50957464b359f98ed0bf34dd5', + '0x98f51b041e493fc4d72b8bd33218480ba0c66ddf', + '0x268fb4311d2c6cb2bba01cca9ac073fb3bfd1c7c', + '0x8629008887e073260c5434d6cacfc83c3001d211', + '0x8eaae6462816cb4957184c48b86afa7642d8bf2b', ] } -const fetchFees = (chain: Chain) => { - return async (timestamp: number): Promise => { - const toTimestamp = timestamp; - const fromTimestamp = timestamp - 60 * 60 * 24; - const toBlock = await getBlock(toTimestamp, chain, {}); - const fromBlock = await getBlock(fromTimestamp, chain, {}); - const logs: ILog[] = (await Promise.all(contract_address[chain].map((address: string) => sdk.getEventLogs({ - target: address, - toBlock: toBlock, - fromBlock: fromBlock, - chain: chain, - topics: [topic_0] - })))).flat(); +const fetchFees = async (options: FetchOptions): Promise => { + const logs: ILog[] = await options.getLogs({ + topic: topic_0, + targets: contract_address[options.chain], + }); const rawData = logs.map((log: ILog) => { const data = log.data.replace('0x', ''); - const amount = Number('0x' + data.slice((3 * 64), (3 * 64) + 64)); - const address = data.slice((11 * 64), (11 * 64) + 64); + const amount = Number('0x' + data.slice((9 * 64), (9 * 64) + 64)); + const address = data.slice((8 * 64), (8 * 64) + 64); const addressString = `0x${address.slice(24)}`; return { amount: amount, address: addressString, } }); - const linkETH = `${CHAIN.ETHEREUM}:${ADDRESSES.ethereum.LINK}`; - const coins = [...new Set(rawData.map((e: any) => `${chain}:${e.address}`)), linkETH]; - const prices = await getPrices(coins, timestamp); - const dailyFees = rawData.reduce((acc: number, { amount, address }: any) => { - if (chain === CHAIN.BSC && address === '0x404460c6a5ede2d891e8297795264fde62adbb75') { - const price = prices[linkETH].price; - const decimals = prices[linkETH].decimals; - const normalizedAmount = amount / (10 ** decimals); - return acc + (normalizedAmount * price); - } - if (chain === CHAIN.POLYGON && address === '0xb0897686c545045afc77cf20ec7a532e3120e0f1') { - const price = prices[linkETH].price; - const decimals = prices[linkETH].decimals; - const normalizedAmount = amount / (10 ** decimals); - return acc + (normalizedAmount * price); - } - const price = prices[`${chain}:${address}`].price; - const decimals = prices[`${chain}:${address}`].decimals; - const normalizedAmount = amount / (10 ** decimals); - return acc + (normalizedAmount * price); - }, 0); + const dailyFees = options.createBalances(); + const dailyRevenue = options.createBalances(); + rawData.map((data: any) => { + dailyFees.add(data.address, data.amount); + }); return { - timestamp, - dailyFees: `${dailyFees}`, - dailyRevenue: '0' + dailyFees: dailyFees, + dailyRevenue: dailyRevenue }; - } } const adapter: SimpleAdapter = { + version: 2, adapter: { [CHAIN.ETHEREUM]: { - fetch: fetchFees(CHAIN.ETHEREUM), + fetch: fetchFees, start: 1688515200, }, [CHAIN.ARBITRUM]: { - fetch: fetchFees(CHAIN.ARBITRUM), + fetch: fetchFees, start: 1688515200, }, [CHAIN.OPTIMISM]: { - fetch: fetchFees(CHAIN.OPTIMISM), + fetch: fetchFees, start: 1688515200, }, [CHAIN.BSC]: { - fetch: fetchFees(CHAIN.BSC), + fetch: fetchFees, start: 1688515200, }, [CHAIN.BASE]: { - fetch: fetchFees(CHAIN.BASE), + fetch: fetchFees, start: 1688515200, }, [CHAIN.POLYGON]: { - fetch: fetchFees(CHAIN.POLYGON), + fetch: fetchFees, start: 1688515200, }, [CHAIN.AVAX]: { - fetch: fetchFees(CHAIN.AVAX), + fetch: fetchFees, start: 1688515200, } } diff --git a/fees/chainlink-keepers.ts b/fees/chainlink-keepers.ts index d9b6969072..0d10a66c78 100644 --- a/fees/chainlink-keepers.ts +++ b/fees/chainlink-keepers.ts @@ -1,11 +1,8 @@ -import ADDRESSES from '../helpers/coreAssets.json' -import { SimpleAdapter, ChainBlocks, FetchResultFees, IJSON } from "../adapters/types"; +import { SimpleAdapter, FetchOptions } from "../adapters/types"; import { CHAIN } from "../helpers/chains"; import { getPrices } from "../utils/prices"; -import { getBlock } from "../helpers/getBlock"; import { getTxReceipts } from "../helpers/getTxReceipts"; -import { Chain, getProvider } from "@defillama/sdk/build/general"; -import * as sdk from "@defillama/sdk"; +import { Chain } from "@defillama/sdk/build/general"; type TAddrress = { [l: string | Chain]: string; @@ -42,17 +39,10 @@ const gasTokenId: IGasTokenId = { } const fetchKeeper = (chain: Chain) => { - return async (timestamp: number, _: ChainBlocks): Promise => { - const fromTimestamp = timestamp - 60 * 60 * 24 - const toTimestamp = timestamp - const fromBlock = (await getBlock(fromTimestamp, chain, {})); - const toBlock = (await getBlock(toTimestamp, chain, {})); - const logs: ITx[] = (await sdk.getEventLogs({ + return async ({ toTimestamp, getLogs, }: FetchOptions) => { + const logs: ITx[] = (await getLogs({ target: address_keeper[chain], - fromBlock: fromBlock, - toBlock: toBlock, topics: [topic0_keeper], - chain: chain })).map((e: any) => { return { ...e, data: e.data.replace('0x', ''), transactionHash: e.transactionHash, } as ITx }) .filter((e: ITx) => e.topics.includes(success_topic)); const tx_hash: string[] = [...new Set([...logs].map((e: ITx) => e.transactionHash))] @@ -67,7 +57,7 @@ const fetchKeeper = (chain: Chain) => { }); const linkAddress = "coingecko:chainlink"; const gasToken = gasTokenId[chain]; - const prices = (await getPrices([linkAddress, gasToken], timestamp)) + const prices = (await getPrices([linkAddress, gasToken], toTimestamp)) const linkPrice = prices[linkAddress].price const gagPrice = prices[gasToken].price const dailyFees = payAmount.reduce((a: number, b: number) => a + b, 0); @@ -78,12 +68,12 @@ const fetchKeeper = (chain: Chain) => { return { dailyFees: dailyFeesUsd.toString(), dailyRevenue: chain === CHAIN.OPTIMISM ? undefined : dailyRevenue.toString(), - timestamp } } } const adapter: SimpleAdapter = { + version: 2, adapter: { [CHAIN.ETHEREUM]: { fetch: fetchKeeper(CHAIN.ETHEREUM), diff --git a/fees/chainlink-requests.ts b/fees/chainlink-requests.ts index 4888862b0c..c814a1e4d2 100644 --- a/fees/chainlink-requests.ts +++ b/fees/chainlink-requests.ts @@ -1,4 +1,4 @@ -import { SimpleAdapter, ChainBlocks, FetchResultFees } from "../adapters/types"; +import { SimpleAdapter, ChainBlocks, FetchResultFees, FetchOptions } from "../adapters/types"; import { CHAIN } from "../helpers/chains"; import { getPrices } from "../utils/prices"; import { queryFlipside } from "../helpers/flipsidecrypto"; @@ -27,9 +27,7 @@ interface ILog { const chains: string[] = [...new Set([CHAIN.ETHEREUM, CHAIN.BSC, CHAIN.POLYGON, CHAIN.OPTIMISM, CHAIN.ARBITRUM, CHAIN.AVAX])]; -const build_gas_query = (timestamp: number): string => { - const now = new Date(timestamp * 1e3) - const dayAgo = new Date(now.getTime() - 1000 * 60 * 60 * 24) +const build_gas_query = (from: number, to: number): string => { return chains.map((chain: Chain) => ` SELECT SUM(TX_FEE), @@ -41,12 +39,10 @@ const build_gas_query = (timestamp: number): string => { txs.BLOCK_NUMBER > 1000000 and logs.BLOCK_NUMBER > 1000000 and logs.TOPICS[0] = '0x9e9bc7616d42c2835d05ae617e508454e63b30b934be8aa932ebc125e0e58a64' - AND logs.BLOCK_TIMESTAMP BETWEEN '${dayAgo.toISOString()}' AND '${now.toISOString()}'`).join(" union all ") + AND logs.BLOCK_TIMESTAMP BETWEEN '${from * 1000}' AND '${to * 1000}'`).join(" union all ") } -const build_link_query = (timestamp: number): string => { - const now = new Date(timestamp * 1e3) - const dayAgo = new Date(now.getTime() - 1000 * 60 * 60 * 24) +const build_link_query = (from: number, to: number): string => { return chains.map((chain: Chain) => ` SELECT data, @@ -57,15 +53,15 @@ const build_link_query = (timestamp: number): string => { ${chain === "avax" ? "avalanche" : chain}.core.fact_event_logs logs WHERE topics[0] = '0xd8d7ecc4800d25fa53ce0372f13a416d98907a7ef3d8d3bdd79cf4fe75529c65' - AND logs.BLOCK_TIMESTAMP BETWEEN '${dayAgo.toISOString()}' AND '${now.toISOString()}'`).join(" union all ") + AND logs.BLOCK_TIMESTAMP BETWEEN '${from * 1000}' AND '${to * 1000}'`).join(" union all ") } const fetchRequests = (chain: Chain) => { - return async (timestamp: number, _: ChainBlocks): Promise => { - const query_paid = build_link_query(timestamp) - const gas_query = build_gas_query(timestamp) + return async ({ fromTimestamp, toTimestamp }: FetchOptions) => { + const query_paid = build_link_query(fromTimestamp, toTimestamp) + const gas_query = build_gas_query(fromTimestamp, toTimestamp) - const linkPaid_logs: ILog[] = (await queryFlipside(query_paid, 360)) + const linkPaid_logs: ILog[] = (await queryFlipside(query_paid, 260)) .map(([data, topics, transactionHash, chain]: [string, string[], string, string]) => { return { data, @@ -80,7 +76,7 @@ const fetchRequests = (chain: Chain) => { const payments = Number('0x'+data.slice(128, 192)) / 10 ** 18; return payments; }).reduce((a: number, b: number) => a + b, 0); - const ethGas = await queryFlipside(gas_query, 360) + const ethGas = await queryFlipside(gas_query, 260) const gas_fees = ethGas.map(([fee, chain]: [string, string]) => { return { @@ -90,7 +86,7 @@ const fetchRequests = (chain: Chain) => { const linkAddress = "coingecko:chainlink"; const gasToken = gasTokenId[chain]; - const prices = (await getPrices([linkAddress, gasToken], timestamp)) + const prices = (await getPrices([linkAddress, gasToken], fromTimestamp)) const linkPrice = prices[linkAddress].price const dailyFeesUsd = link_amount * linkPrice; const dailyGasUsd = gas_fees * prices[gasToken].price; @@ -98,7 +94,6 @@ const fetchRequests = (chain: Chain) => { return { dailyFees: dailyFeesUsd.toString(), dailyRevenue: (dailyFeesUsd - dailyGasUsd).toString(), - timestamp } } @@ -106,6 +101,7 @@ const fetchRequests = (chain: Chain) => { const adapter: SimpleAdapter = { + version: 2, adapter: { [CHAIN.ETHEREUM]: { fetch: fetchRequests(CHAIN.ETHEREUM), @@ -130,6 +126,7 @@ const adapter: SimpleAdapter = { [CHAIN.AVAX]: { fetch: fetchRequests(CHAIN.AVAX), start: 1675382400, + runAtCurrTime: true, }, }, isExpensiveAdapter: true, diff --git a/fees/chainlink-vrf-v1.ts b/fees/chainlink-vrf-v1.ts index 60d1e182da..58d8ca9fc4 100644 --- a/fees/chainlink-vrf-v1.ts +++ b/fees/chainlink-vrf-v1.ts @@ -1,10 +1,6 @@ -import { SimpleAdapter, ChainBlocks, FetchResultFees, IJSON } from "../adapters/types"; +import { SimpleAdapter, FetchOptions, FetchResultV2 } from "../adapters/types"; import { CHAIN } from "../helpers/chains"; -import { getTimestampAtStartOfDayUTC, getTimestampAtStartOfNextDayUTC } from "../utils/date"; -import { getPrices } from "../utils/prices"; -import { getBlock } from "../helpers/getBlock"; -import { Chain, getProvider } from "@defillama/sdk/build/general"; -import * as sdk from "@defillama/sdk"; +import { Chain } from "@defillama/sdk/build/general"; import getTxReceipts from "../helpers/getTxReceipts"; const topic0_v1 = '0xa2e7a402243ebda4a69ceeb3dfb682943b7a9b3ac66d6eefa8db65894009611c'; @@ -36,55 +32,30 @@ interface ITx { transactionHash: string; topics: string[]; } -type IFeeV2 = { - [l: string | Chain]: number; -} -const feesV2: IFeeV2 = { - [CHAIN.ETHEREUM]: 0.25, - [CHAIN.BSC]: 0.005, - [CHAIN.POLYGON]: 0.0005, - [CHAIN.FANTOM]: 0.0005, - [CHAIN.AVAX]: 0.005, -} - -const feesV1: IFeeV2 = { - [CHAIN.ETHEREUM]: 2, - [CHAIN.BSC]: 0.2, - [CHAIN.POLYGON]: 0.0001, -} type IGasTokenId = { [l: string | Chain]: string; } const gasTokenId: IGasTokenId = { - [CHAIN.ETHEREUM]: "coingecko:ethereum", - [CHAIN.BSC]: "coingecko:binancecoin", - [CHAIN.POLYGON]: "coingecko:matic-network", - [CHAIN.FANTOM]: "coingecko:fantom", - [CHAIN.AVAX]: "coingecko:avalanche-2", - [CHAIN.ARBITRUM]: "coingecko:ethereum", - [CHAIN.OPTIMISM]: "coingecko:ethereum" + [CHAIN.ETHEREUM]: "ethereum", + [CHAIN.BSC]: "binancecoin", + [CHAIN.POLYGON]: "matic-network", + [CHAIN.FANTOM]: "fantom", + [CHAIN.AVAX]: "avalanche-2", + [CHAIN.ARBITRUM]: "ethereum", + [CHAIN.OPTIMISM]: "ethereum" } -const fetch = (chain: Chain, version: number) => { - return async (timestamp: number, _: ChainBlocks): Promise => { - const fromTimestamp = timestamp - 60 * 60 * 24 - const toTimestamp = timestamp - const fromBlock = (await getBlock(fromTimestamp, chain, {})); - const toBlock = (await getBlock(toTimestamp, chain, {})); - const logs_1: ITx[] = (await sdk.getEventLogs({ +const fetch = async (options: FetchOptions): Promise => { + const version = 1; + const chain = options.chain + const logs_1: ITx[] = (await options.getLogs({ target: version === 1 ? address_v1[chain] : address_v2[chain], - fromBlock: fromBlock, - toBlock: toBlock, topics: version === 1 ? [topic0_v1] : [topic0_v2], - chain: chain })).map((e: any) => { return { data: e.data.replace('0x', ''), transactionHash: e.transactionHash } as ITx }); - const logs_2: ITx[] = (await sdk.getEventLogs({ + const logs_2: ITx[] = (await options.getLogs({ target: version === 1 ? address_v1[chain] : address_v2[chain], - fromBlock: fromBlock, - toBlock: toBlock, topics: version === 1 ? [topic1_v1] : [topic1_v2], - chain: chain })).map((e: any) => { return { data: e.data.replace('0x', ''), transactionHash: e.transactionHash } as ITx }); const request_fees: any[] = logs_2.map((e: ITx) => { @@ -103,43 +74,41 @@ const fetch = (chain: Chain, version: number) => { return fees?.fees || 0; }).reduce((a: number, b: number) => a+b, 0) - const tx_hash: string[] = [...new Set([...logs_1].map((e: ITx) => e.transactionHash).filter(e => !exclude.includes(e)))] const txReceipt: number[] = chain === CHAIN.OPTIMISM ? [] : (await getTxReceipts(chain, tx_hash, { cacheKey: 'chainlink-vrf-v1' })) .map((e: any) => { const amount = (Number(e?.gasUsed || 0) * Number(e?.effectiveGasPrice || 0)) / 10 ** 18 return amount }) - const linkAddress = "coingecko:chainlink"; + const linkAddress = "chainlink"; const gasToken = gasTokenId[chain]; - const prices = await getPrices([linkAddress, gasToken], timestamp); + const dailyGasUsd = options.createBalances() + const dailyFees = options.createBalances() const dailyGas = txReceipt.reduce((a: number, b: number) => a + b, 0); - const linkPrice = prices[linkAddress].price - const gagPrice = prices[gasToken].price - const dailyGasUsd = dailyGas * gagPrice; - const dailyFees =(fees_amount * linkPrice); - const dailyRevenue = dailyFees - dailyGasUsd; + dailyGasUsd.addCGToken(gasToken, dailyGas); + dailyFees.addCGToken(linkAddress, fees_amount); + const dailyRevenue = dailyFees.clone() + dailyRevenue.subtract(dailyGasUsd) return { - dailyFees: dailyFees.toString(), - dailyRevenue: chain === CHAIN.OPTIMISM ? undefined : dailyRevenue.toString(), - timestamp + dailyFees: dailyFees, + dailyRevenue: dailyRevenue, } - } } const adapter: SimpleAdapter = { + version: 2, adapter: { [CHAIN.ETHEREUM]: { - fetch: fetch(CHAIN.ETHEREUM, 1), + fetch: fetch, start: 1675382400, }, [CHAIN.BSC]: { - fetch: fetch(CHAIN.BSC, 1), + fetch: fetch, start: 1675382400, }, [CHAIN.POLYGON]: { - fetch: fetch(CHAIN.POLYGON, 1), + fetch: fetch, start: 1675382400, } } diff --git a/fees/chainlink-vrf-v2.ts b/fees/chainlink-vrf-v2.ts index d8bcd2db0b..e0a7770207 100644 --- a/fees/chainlink-vrf-v2.ts +++ b/fees/chainlink-vrf-v2.ts @@ -1,4 +1,4 @@ -import { SimpleAdapter, ChainBlocks, FetchResultFees, IJSON } from "../adapters/types"; +import { SimpleAdapter, ChainBlocks, FetchResultFees, IJSON, FetchOptions } from "../adapters/types"; import { CHAIN } from "../helpers/chains"; import { getPrices } from "../utils/prices"; import { getBlock } from "../helpers/getBlock"; @@ -65,17 +65,10 @@ const gasTokenId: IGasTokenId = { const fetch = (chain: Chain, version: number) => { - return async (timestamp: number, _: ChainBlocks): Promise => { - const fromTimestamp = timestamp - 60 * 60 * 24 - const toTimestamp = timestamp - const fromBlock = (await getBlock(fromTimestamp, chain, {})); - const toBlock = (await getBlock(toTimestamp, chain, {})); - const logs_1: ITx[] = (await sdk.getEventLogs({ + return async ({ toTimestamp, getLogs }: FetchOptions) => { + const logs_1: ITx[] = (await getLogs({ target: version === 1 ? address_v1[chain] : address_v2[chain], - fromBlock: fromBlock, - toBlock: toBlock, topics: version === 1 ? [topic0_v1] : [topic0_v2], - chain: chain })).map((e: any) => { return { data: e.data.replace('0x', ''), transactionHash: e.transactionHash } as ITx }); const amount_fullfill = logs_1.map((e: ITx) => { @@ -91,7 +84,7 @@ const fetch = (chain: Chain, version: number) => { }) const linkAddress = "coingecko:chainlink"; const gasToken = gasTokenId[chain]; - const prices = (await getPrices([linkAddress, gasToken], timestamp)); + const prices = (await getPrices([linkAddress, gasToken], toTimestamp)); const dailyGas = txReceipt.reduce((a: number, b: number) => a + b, 0); const linkPrice = prices[linkAddress].price const gagPrice = prices[gasToken].price @@ -103,7 +96,6 @@ const fetch = (chain: Chain, version: number) => { return { dailyFees: dailyFees.toString(), dailyRevenue: chain === CHAIN.OPTIMISM ? undefined : dailyRevenue.toString(), - timestamp } } @@ -111,6 +103,7 @@ const fetch = (chain: Chain, version: number) => { const adapter: SimpleAdapter = { + version: 2, adapter: { [CHAIN.ETHEREUM]: { fetch: fetch(CHAIN.ETHEREUM, 2), diff --git a/fees/chimpexchange.ts b/fees/chimpexchange.ts index f2ab36e4fe..1f3cd7f960 100644 --- a/fees/chimpexchange.ts +++ b/fees/chimpexchange.ts @@ -1,10 +1,9 @@ import { Adapter } from "../adapters/types"; import { CHAIN } from "../helpers/chains"; import { request, gql } from "graphql-request"; -import type { ChainEndpoints } from "../adapters/types"; +import type { ChainEndpoints, FetchOptions } from "../adapters/types"; import { Chain } from "@defillama/sdk/build/general"; import BigNumber from "bignumber.js"; -import { getTimestampAtStartOfDayUTC } from "../utils/date"; const endpoints = { [CHAIN.LINEA]: @@ -32,10 +31,7 @@ interface IPoolSnapshot { const graphs = (graphUrls: ChainEndpoints) => { return (chain: Chain) => { - return async (timestamp: number) => { - const startTimestamp = getTimestampAtStartOfDayUTC(timestamp); - const fromTimestamp = startTimestamp - 60 * 60 * 24; - const toTimestamp = startTimestamp; + return async ({ fromTimestamp, toTimestamp }: FetchOptions) => { const graphQuery = gql`query fees { today:poolSnapshots(where: {timestamp:${toTimestamp}}, orderBy:swapFees, orderDirection: desc) { id @@ -85,7 +81,6 @@ const graphs = (graphUrls: ChainEndpoints) => { .reduce((a: BigNumber, b: BigNumber) => a.plus(b), new BigNumber("0")); return { - timestamp, totalUserFees: currentTotalSwapFees.toString(), dailyUserFees: dailyFee.toString(), totalFees: currentTotalSwapFees.toString(), @@ -115,6 +110,7 @@ const methodology = { }; const adapter: Adapter = { + version: 2, adapter: { [CHAIN.LINEA]: { fetch: graphs(endpoints)(CHAIN.LINEA), diff --git a/fees/chronos.ts b/fees/chronos.ts index 40729db6f9..942d17cca5 100644 --- a/fees/chronos.ts +++ b/fees/chronos.ts @@ -1,16 +1,8 @@ -import { SimpleAdapter } from "../adapters/types"; import { CHAIN } from "../helpers/chains"; -import { getDexFeesExports } from "../helpers/dexVolumeLogs"; +import { uniV2Exports } from "../helpers/uniswap"; const FACTORY_ADDRESS = '0xCe9240869391928253Ed9cc9Bcb8cb98CB5B0722'; -const adapter: SimpleAdapter = { - adapter: { - [CHAIN.ARBITRUM]: { - fetch: getDexFeesExports({ chain: CHAIN.ARBITRUM, factory: FACTORY_ADDRESS }), - start: 1682380800, - }, - } -}; - -export default adapter; +export default uniV2Exports({ + [CHAIN.ARBITRUM]: { factory: FACTORY_ADDRESS }, +}) diff --git a/fees/cipher.ts b/fees/cipher.ts index cd57a4956c..32f0bdb846 100644 --- a/fees/cipher.ts +++ b/fees/cipher.ts @@ -8,7 +8,8 @@ const adapter: Adapter = { fetch: getFeesExport('0x2544a6412bc5aec279ea0f8d017fb4a9b6673dca'), start: 1695600000, }, - } + }, + version: 2, } export default adapter; diff --git a/fees/circle.ts b/fees/circle.ts new file mode 100644 index 0000000000..70ccf159dd --- /dev/null +++ b/fees/circle.ts @@ -0,0 +1,29 @@ +import { Adapter, FetchOptions } from "../adapters/types"; + +const adapter: Adapter = { + version: 2, + adapter: { + ethereum: { + fetch: async ({ fromTimestamp, createBalances }: FetchOptions) => { + const dailyFees = createBalances() + + // Based on https://www.circle.com/en/transparency + if(fromTimestamp > 1719709261){ + let annualYield = 0 + // per the last report, there's: + annualYield += 11.2e9*5.287/100 // 11.2bn in tbills + annualYield += 17.1e9*5.35/100 // in repos, which should be earning SOFR + dailyFees.addCGToken("usd-coin", annualYield/365) + } + + return { + dailyFees, + dailyRevenue: dailyFees + } + }, + start: 0 + } + } +} + +export default adapter; \ No newline at end of file diff --git a/fees/cleopatra-exchange.ts b/fees/cleopatra-exchange.ts index 5af83abbbc..d1cc4bde89 100644 --- a/fees/cleopatra-exchange.ts +++ b/fees/cleopatra-exchange.ts @@ -1,64 +1,58 @@ -import { SimpleAdapter, FetchResultFees, BaseAdapter } from "../adapters/types"; +import { SimpleAdapter } from "../adapters/types"; import { MANTLE, CHAIN } from "../helpers/chains"; - - import { - getGraphDimensions, - DEFAULT_DAILY_VOLUME_FACTORY, - DEFAULT_TOTAL_VOLUME_FIELD, - } from "../helpers/getUniSubgraph" + DEFAULT_TOTAL_VOLUME_FIELD, + getGraphDimensions2, +} from "../helpers/getUniSubgraph"; type TStartTime = { -[key: string]: number; -} -const startTimeV2:TStartTime = { -[CHAIN.MANTLE]: 1704326400, -} - + [key: string]: number; +}; +const startTimeV2: TStartTime = { + [CHAIN.MANTLE]: 1704326400, +}; const v2Endpoints = { - [CHAIN.MANTLE]: "https://subgraph-api.mantle.xyz/subgraphs/name/cleoexchange/cl-subgraph", - }; - -const VOLUME_USD = "volumeUSD"; - -const v2Graphs = getGraphDimensions({ - graphUrls: v2Endpoints, - totalVolume: { - factory: "factories", - field: DEFAULT_TOTAL_VOLUME_FIELD, - }, - dailyVolume: { - factory: DEFAULT_DAILY_VOLUME_FACTORY, - field: VOLUME_USD, + [CHAIN.MANTLE]: + "https://subgraph-api.mantle.xyz/subgraphs/name/cleoexchange/cl-subgraph", +}; + +const v2Graphs = getGraphDimensions2({ + graphUrls: v2Endpoints, + totalVolume: { + factory: "factories", + field: DEFAULT_TOTAL_VOLUME_FIELD, + }, + feesPercent: { + type: "fees", + HoldersRevenue: 72, + ProtocolRevenue: 8, + UserFees: 100, // User fees are 100% of collected fees + Revenue: 80, // Revenue is 50% of collected fees + SupplySideRevenue: 20, + }, +}); + +const methodology = { + UserFees: "User pays 0.3% fees on each swap.", + ProtocolRevenue: "Revenue going to the protocol.", + HoldersRevenue: "User fees are distributed among holders.", +}; + +const adapter: SimpleAdapter = { + version: 2, + adapter: { + [CHAIN.MANTLE]: { + fetch: v2Graphs(MANTLE), + start: startTimeV2[CHAIN.MANTLE], + meta: { + methodology: { + ...methodology, + UserFees: "User pays 0.05%, 0.30%, or 1% on each swap.", + }, + }, }, - feesPercent: { - type: "fees", - HoldersRevenue: 50, - UserFees: 100, // User fees are 100% of collected fees - Revenue: 50, // Revenue is 50% of collected fees - SupplySideRevenue: 50, - } - }); - - const methodology = { - UserFees: "User pays 0.3% fees on each swap.", - ProtocolRevenue: "Revenue going to the protocol.", - HoldersRevenue: "User fees are distributed among holders." - } - - const adapter: SimpleAdapter = { - adapter: { - [CHAIN.MANTLE]: {fetch: v2Graphs(MANTLE), - start: startTimeV2[CHAIN.MANTLE], - meta: { - methodology: { - ...methodology, - UserFees: "User pays 0.05%, 0.30%, or 1% on each swap." - } - } - }, - } - }; + }, +}; export default adapter; diff --git a/fees/clever.ts b/fees/clever.ts index d6de35ceaf..abcea2560b 100644 --- a/fees/clever.ts +++ b/fees/clever.ts @@ -1,34 +1,43 @@ +import * as sdk from "@defillama/sdk"; import { Adapter } from "../adapters/types"; import { ETHEREUM } from "../helpers/chains"; -import { request, } from "graphql-request"; -import type { ChainBlocks, ChainEndpoints, FetchOptions } from "../adapters/types"; +import { request } from "graphql-request"; +import type { ChainEndpoints, FetchOptions } from "../adapters/types"; import { Chain } from "@defillama/sdk/build/general"; const endpoints = { [ETHEREUM]: - "https://api.thegraph.com/subgraphs/name/aladdindaogroup/aladdin-fees", + sdk.graph.modifyEndpoint('CCaEZU1PJyNaFmEjpyc4AXUiANB6M6DGDCJuWa48JWTo'), }; const graph = (graphUrls: ChainEndpoints) => { return (chain: Chain) => { - return async (_timestamp: number, _: ChainBlocks, { createBalances, startOfDay }: FetchOptions) => { - const dailyRevenue = createBalances() + return async ({ createBalances, startOfDay }: FetchOptions) => { + const dailyRevenue = createBalances(); const dateId = Math.floor(startOfDay); const graphQuery = `{ dailyRevenueSnapshot(id: ${dateId}) { cvxRevenue fraxRevenue } }`; - const { dailyRevenueSnapshot: snapshot } = await request(graphUrls[chain], graphQuery); + const { dailyRevenueSnapshot: snapshot } = await request( + graphUrls[chain], + graphQuery + ); if (!snapshot) throw new Error("No data found"); - dailyRevenue.addCGToken("convex-finance", snapshot.cvxRevenue); - dailyRevenue.addCGToken("frax", snapshot.fraxRevenue); - const dailyFees = dailyRevenue.clone(2); - return { timestamp: startOfDay, dailyFees, dailyRevenue, } + dailyRevenue.addCGToken("convex-finance", snapshot.cvxRevenue * 1e18); + dailyRevenue.addCGToken("frax", snapshot.fraxRevenue * 1e18); + + const usd = await dailyRevenue.getUSDValue(); + const revenue = (usd / 1e18).toFixed(0); + const dailyFees = ((usd * 2) / 1e18).toFixed(0); + + return { dailyFees, dailyRevenue: revenue }; }; }; }; const adapter: Adapter = { + version: 2, adapter: { [ETHEREUM]: { fetch: graph(endpoints)(ETHEREUM), diff --git a/fees/clipper.ts b/fees/clipper.ts index 21b6cc7380..7d3cc9e30f 100644 --- a/fees/clipper.ts +++ b/fees/clipper.ts @@ -1,8 +1,8 @@ +import * as sdk from "@defillama/sdk"; import { Chain } from "@defillama/sdk/build/general"; import { CHAIN } from "../helpers/chains"; -import { type } from "os"; import request, { gql } from "graphql-request"; -import { Fetch, FetchResultFees, SimpleAdapter } from "../adapters/types"; +import { FetchOptions, FetchResultFees, SimpleAdapter } from "../adapters/types"; import { getBlock } from "../helpers/getBlock"; type TEndpoint = { @@ -10,11 +10,11 @@ type TEndpoint = { } const endpoints: TEndpoint = { - [CHAIN.ETHEREUM]: "https://api.thegraph.com/subgraphs/name/edoapp/clipper-mainnet", - [CHAIN.OPTIMISM]: "https://api.thegraph.com/subgraphs/name/edoapp/clipper-optimism", - [CHAIN.POLYGON]: "https://api.thegraph.com/subgraphs/name/edoapp/clipper-polygon", - // [CHAIN.MOONBEAN]: "https://api.thegraph.com/subgraphs/name/edoapp/clipper-moonbeam", - [CHAIN.ARBITRUM]: "https://api.thegraph.com/subgraphs/name/edoapp/clipper-arbitrum", + [CHAIN.ETHEREUM]: sdk.graph.modifyEndpoint('2BhN8mygHMmRkceMmod7CEEsGkcxh91ExRbEfRVkpVGM'), + [CHAIN.OPTIMISM]: sdk.graph.modifyEndpoint('Cu6atAfi6uR9mLMEBBjkhKSUUXHCobbB83ctdooexQ9f'), + [CHAIN.POLYGON]: sdk.graph.modifyEndpoint('Brmf2gRdpLFsEF6YjSAMVrXqSfbhsaaWaWzdCYjE7iYY'), + // [CHAIN.MOONBEAN]: sdk.graph.modifyEndpoint('8zRk4WV9vUU79is2tYGWq9GKh97f93LsZ8V9wy1jSMvA'), + [CHAIN.ARBITRUM]: sdk.graph.modifyEndpoint('ATBQPRjT28GEK6UaBAzXy64x9kFkNk1r64CdgmDJ587W'), }; interface IPool { @@ -49,11 +49,9 @@ const feesQuery = gql` ` const fetchFees = (chain: Chain) => { - return async (timestamp: number): Promise => { + return async ({ fromTimestamp, toTimestamp, getToBlock }: FetchOptions) => { const endpoint = endpoints[chain]; - const toTimestamp = timestamp; - const fromTimestamp = timestamp - 60 * 60 * 24; - const toBlock = await getBlock(timestamp, chain, {}); + const toBlock = await getToBlock(); const response: IResponse = (await request(endpoint, feesQuery, { fromTimestamp, @@ -81,12 +79,12 @@ const fetchFees = (chain: Chain) => { totalFees: `${totalFees}`, totalRevenue: `${totalRevenue}`, totalProtocolRevenue: `${totalRevenue}`, - timestamp } } } const adapters: SimpleAdapter = { + version: 2, adapter: { [CHAIN.ETHEREUM]: { fetch: fetchFees(CHAIN.ETHEREUM), diff --git a/fees/clusters.ts b/fees/clusters.ts new file mode 100644 index 0000000000..ce015e33e9 --- /dev/null +++ b/fees/clusters.ts @@ -0,0 +1,20 @@ +import { FetchOptions, SimpleAdapter } from "../adapters/types" +import { CHAIN } from "../helpers/chains" + +const adapters: SimpleAdapter = { + adapter: { + [CHAIN.ETHEREUM]: { + fetch: async ({ createBalances, getLogs }: FetchOptions) => { + const dailyFees = createBalances() + const logs = await getLogs({ target: "0x00000000000E1A99dDDd5610111884278BDBda1D", + eventAbi: 'event Bid(bytes32 from, uint256 amount, bytes32 name)' }) + logs.forEach((i: any) => dailyFees.add("0x0000000000000000000000000000000000000000", i.amount)) + + return { dailyFees, dailyRevenue: dailyFees } + }, + start: 1706746140 + }, + }, + version: 2 +} +export default adapters; \ No newline at end of file diff --git a/fees/coinbase-commerce.ts b/fees/coinbase-commerce.ts new file mode 100644 index 0000000000..c0919b8aba --- /dev/null +++ b/fees/coinbase-commerce.ts @@ -0,0 +1,44 @@ +import { Chain } from "@defillama/sdk/build/general"; +import { FetchOptions, SimpleAdapter } from "../adapters/types"; +import { CHAIN } from "../helpers/chains"; + +type TContract = { + [s: string | Chain]: string[]; +} +const contracts: TContract = { + [CHAIN.ETHEREUM]: ['0x3263bc4976C8c180bd5EB90a57ED1A2f1CFcAC67', '0x7915f087685fffD71608E5d118f3B70c27D9eF4e', "0x131642c019AF815Ae5F9926272A70C84AE5C37ab"], + [CHAIN.POLYGON]: ["0x551c6791c2f01c3Cd48CD35291Ac4339F206430d", "0xe63fb3a3cd48df6a336560a91f78ac6013557f7d", "0x7f52269092F2a5EF06C36C91e46F9196deb90336", "0x48073112c8C48e2550Bd42E4CD0aA483a416c5af"], + [CHAIN.BASE]: ["0xeF0D482Daa16fa86776Bc582Aff3dFce8d9b8396", "0x131642c019AF815Ae5F9926272A70C84AE5C37ab", "0x9Bb4D44e6963260A1850926E8f6bEB8d5803836F", "0x30E95edE0b3C7Ef147EE97A5e88FdE06311EA11f"], +} + +const fetchFees = (chain: Chain) => { + return async ({ createBalances, getLogs }: FetchOptions) => { + const dailyFees = createBalances() + await Promise.all(contracts[chain].map(async contract => { + const logs = await getLogs({ target: contract, eventAbi: 'event Transferred (address indexed operator, bytes16 id, address recipient, address sender, uint256 spentAmount, address spentCurrency)' }) + logs.forEach((i: any) => dailyFees.add(i.spentCurrency, i.spentAmount / BigInt(100))) + })) + + return { dailyFees, dailyRevenue: dailyFees } + } +} + +const start = 1700053261 +const adapters: SimpleAdapter = { + adapter: { + [CHAIN.ETHEREUM]: { + fetch: fetchFees(CHAIN.ETHEREUM), + start + }, + [CHAIN.BASE]: { + fetch: fetchFees(CHAIN.BASE), + start + }, + [CHAIN.POLYGON]: { + fetch: fetchFees(CHAIN.POLYGON), + start + } + }, + version: 2 +} +export default adapters; diff --git a/fees/colony/airdrops.ts b/fees/colony/airdrops.ts new file mode 100644 index 0000000000..98c530d751 --- /dev/null +++ b/fees/colony/airdrops.ts @@ -0,0 +1,71 @@ +import { Balances } from "@defillama/sdk"; +import { FetchOptions } from "../../adapters/types"; +import { request, gql } from "graphql-request"; +import fetchURL from "../../utils/fetchURL"; + +export interface Airdrops { + dailyHoldersRevenue: Balances; + totalHoldersRevenue: Balances; +} + +interface IGraphAirdropsResponse { + rewards: { + token: { + id: string + } + amount: string + }[] +} + +const queryAirdrops = gql + `query Airdrops($timestampFrom: BigInt!, $timestampTo: BigInt!) { + rewards( + where: {createdAt_gte: $timestampFrom, createdAt_lt: $timestampTo, categoryId_in: [3, 4]} + ) { + token { + id + } + amount + } + }`; + +export async function airdrops( + options: FetchOptions, + stakingV3SubgraphEndpoint: string, +): Promise { + const { createBalances, startTimestamp, endTimestamp } = options; + + let dailyHoldersRevenue = createBalances() + let totalHoldersRevenue = createBalances() + + try { + const res: IGraphAirdropsResponse = await request(stakingV3SubgraphEndpoint, queryAirdrops, { + timestampFrom: startTimestamp, + timestampTo: endTimestamp + }); + + if (res.rewards.length > 0) { + for (const airdrop of res.rewards) { + dailyHoldersRevenue.add(airdrop.token.id, airdrop.amount) + } + } + } catch (e) { + console.error(e); + } + + try { + const dataServiceResponse = await fetchURL('https://data-service.colonylab.io/airdrops') + + for (const airdrop of [...dataServiceResponse.airdrops[3] ?? [], ...dataServiceResponse.airdrops[4] ?? []]) { + totalHoldersRevenue.add(airdrop.address, airdrop.airdroppedAmount) + } + } + catch (e) { + console.error(e); + } + + return { + dailyHoldersRevenue, + totalHoldersRevenue + } +} diff --git a/fees/colony/cai.ts b/fees/colony/cai.ts new file mode 100644 index 0000000000..5bd7bcba81 --- /dev/null +++ b/fees/colony/cai.ts @@ -0,0 +1,51 @@ +import { Balances } from "@defillama/sdk"; +import { FetchOptions } from "../../adapters/types"; +import { queryDune } from "../../helpers/dune"; +import BigNumber from "bignumber.js"; + +const usdcToken = '0xB97EF9Ef8734C71904D8002F8b6Bc66Dd9c48a6E' + +interface CaiFees { + dailyProtocolRevenue: Balances; + totalProtocolRevenue: Balances; + dailyHoldersRevenue: Balances; + totalHoldersRevenue: Balances; +} + +interface DuneResponse { + fees: string; + cum_fees: string; + date: string; +} + +export async function caiFees(options: FetchOptions): Promise { + const dailyProtocolRevenue = options.createBalances(); + const totalProtocolRevenue = options.createBalances(); + const dailyHoldersRevenue = options.createBalances(); + const totalHoldersRevenue = options.createBalances(); + + try { + const response = (await queryDune("3944152")); + + const result = response.filter((x: DuneResponse) => { + const recordTimestamp = Date.parse(x.date) / 1000 + return recordTimestamp >= options.fromTimestamp && recordTimestamp < options.toTimestamp + }) + + dailyProtocolRevenue.addToken(usdcToken, new BigNumber(result[0].fees).multipliedBy(0.5).multipliedBy(1e6).toFixed(0)) + totalProtocolRevenue.addToken(usdcToken, new BigNumber(result[0].cum_fees).multipliedBy(0.5).multipliedBy(1e6).toFixed(0)) + + dailyHoldersRevenue.addToken(usdcToken, new BigNumber(result[0].fees).multipliedBy(0.5).multipliedBy(1e6).toFixed(0)) + totalHoldersRevenue.addToken(usdcToken, new BigNumber(result[0].cum_fees).multipliedBy(0.5).multipliedBy(1e6).toFixed(0)) + } catch (e) { + console.error(e); + } + + return { + dailyProtocolRevenue, + totalProtocolRevenue, + dailyHoldersRevenue, + totalHoldersRevenue + } +} + diff --git a/fees/colony/dex.ts b/fees/colony/dex.ts new file mode 100644 index 0000000000..4f2ad7c4ed --- /dev/null +++ b/fees/colony/dex.ts @@ -0,0 +1,74 @@ +import { getGraphDimensions, getGraphDimensions2 } from "../../helpers/getUniSubgraph" +import { FetchOptions } from "../../adapters/types"; +import { Balances } from "@defillama/sdk"; +import BigNumber from "bignumber.js"; + +interface DexFees { + timestamp: number + block?: number + dailyVolume: Balances + totalVolume: Balances + dailyProtocolRevenue: Balances + totalProtocolRevenue: Balances + dailySupplySideRevenue: Balances + totalSupplySideRevenue: Balances +} + +const usdcToken = '0xB97EF9Ef8734C71904D8002F8b6Bc66Dd9c48a6E'; + +export async function dexFees( + options: FetchOptions, + dexSubgraphEndpoint: string +): Promise { + const { createBalances } = options; + + let dailyVolume = createBalances() + let totalVolume = createBalances() + let dailyProtocolRevenue = createBalances() + let totalProtocolRevenue = createBalances() + let dailySupplySideRevenue = createBalances() + let totalSupplySideRevenue = createBalances() + + const VOLUME_USD = "volumeUSD"; + const FEES_USD = "feesUSD"; + + const v2Graph = getGraphDimensions2({ + graphUrls: { + [options.chain]: dexSubgraphEndpoint, + }, + totalVolume: { + factory: "factories", + field: VOLUME_USD, + }, + totalFees: { + factory: "factories", + field: FEES_USD, + }, + }); + + const results = await v2Graph(options.chain)(options) + const resultsDailyFees = new BigNumber(results.dailyFees?.toString() ?? 0).multipliedBy(1e6) + const resultsTotalFees = new BigNumber(results.totalFees?.toString() ?? 0).multipliedBy(1e6) + const resultsDailyVolume = new BigNumber(results.dailyVolume?.toString() ?? 0).multipliedBy(1e6) + const resultsTotalVolume = new BigNumber(results.totalVolume?.toString() ?? 0).multipliedBy(1e6) + + dailySupplySideRevenue.add(usdcToken, resultsDailyFees.multipliedBy(5).div(6).toFixed(0)) + totalSupplySideRevenue.add(usdcToken, resultsTotalFees.multipliedBy(5).div(6).toFixed(0)) + + dailyProtocolRevenue.add(usdcToken, resultsDailyFees.div(6).toFixed(0)) + totalProtocolRevenue.add(usdcToken, resultsTotalFees.div(6).toFixed(0)) + + dailyVolume.add(usdcToken, resultsDailyVolume.toFixed(0)) + totalVolume.add(usdcToken, resultsTotalVolume.toFixed(0)) + + return { + timestamp: results.timestamp, + block: results.block, + dailyVolume, + totalVolume, + dailyProtocolRevenue, + totalProtocolRevenue, + dailySupplySideRevenue, + totalSupplySideRevenue + } +} diff --git a/fees/colony/earlystage.ts b/fees/colony/earlystage.ts new file mode 100644 index 0000000000..a918da627f --- /dev/null +++ b/fees/colony/earlystage.ts @@ -0,0 +1,127 @@ +import { Balances } from "@defillama/sdk"; +import { FetchOptions } from "../../adapters/types"; +import { request, gql } from "graphql-request"; +import BigNumber from "bignumber.js"; + +const usdcToken = '0xB97EF9Ef8734C71904D8002F8b6Bc66Dd9c48a6E' + +export interface EarlyStageFees { + dailyProtocolRevenue: Balances; + totalProtocolRevenue: Balances; + dailyHoldersRevenue: Balances; + totalHoldersRevenue: Balances; +} + +interface IProjectDistribution { + project: { + tokenPrice: string; + } + ceTokenColonyFee: string; + ceTokenStakingReward: string; + ceTokenDexBoost: string; + ceTokenDexInitialLiquidity: string; + stablecoinInitialLiquidity: string; + stablecoinColonyFee: string; + timestamp: number +} + +interface IGraphEarlyStageFeesResponse { + projectDistributions: IProjectDistribution[]; +} + +const queryEarlyStageFees = gql +`query fees { + projectDistributions(first: 1000) { + project { + tokenPrice + } + ceTokenColonyFee + ceTokenStakingReward + ceTokenDexBoost + ceTokenDexInitialLiquidity + stablecoinInitialLiquidity + stablecoinColonyFee + timestamp + } +}`; + +export async function earlyStageFees( + options: FetchOptions, + earlystageSubgraphEndpoint: string, +): Promise { + const { createBalances, startTimestamp, endTimestamp } = options; + + let dailyProtocolRevenue = createBalances() + let totalProtocolRevenue = createBalances() + let dailyHoldersRevenue = createBalances() + let totalHoldersRevenue = createBalances() + + try { + const res: IGraphEarlyStageFeesResponse = await request(earlystageSubgraphEndpoint, queryEarlyStageFees); + + if (res.projectDistributions && res.projectDistributions.length) { + const todayRes = res.projectDistributions.filter(x => x.timestamp >= startTimestamp && x.timestamp < endTimestamp) + + // --- Protocol Revenue + dailyProtocolRevenue = todayRes.reduce((acc: Balances, x) => { + acc.add(usdcToken, x.stablecoinColonyFee) + return acc + }, dailyProtocolRevenue) + + totalProtocolRevenue = res.projectDistributions.reduce((acc: Balances, x) => { + acc.add(usdcToken, x.stablecoinColonyFee) + return acc + }, totalProtocolRevenue) + + dailyProtocolRevenue = todayRes.reduce((acc: Balances, x) => { + acc.add(usdcToken, new BigNumber(x.ceTokenColonyFee).multipliedBy(x.project.tokenPrice).div(new BigNumber(10).pow(18)).toFixed(0)) + return acc + }, dailyProtocolRevenue) + + totalProtocolRevenue = res.projectDistributions.reduce((acc: Balances, x) => { + acc.add(usdcToken, new BigNumber(x.ceTokenColonyFee).multipliedBy(x.project.tokenPrice).div(new BigNumber(10).pow(18)).toFixed(0)) + return acc + }, totalProtocolRevenue) + + dailyProtocolRevenue = todayRes.reduce((acc: Balances, x) => { + acc.add(usdcToken, new BigNumber(x.ceTokenDexInitialLiquidity).multipliedBy(x.project.tokenPrice).div(new BigNumber(10).pow(18)).toFixed(0)) + return acc + }, dailyProtocolRevenue) + + totalProtocolRevenue = res.projectDistributions.reduce((acc: Balances, x) => { + acc.add(usdcToken, new BigNumber(x.ceTokenDexInitialLiquidity).multipliedBy(x.project.tokenPrice).div(new BigNumber(10).pow(18)).toFixed(0)) + return acc + }, totalProtocolRevenue) + + dailyProtocolRevenue = todayRes.reduce((acc: Balances, x) => { + acc.add(usdcToken, x.stablecoinInitialLiquidity) + return acc + }, dailyProtocolRevenue) + + totalProtocolRevenue = res.projectDistributions.reduce((acc: Balances, x) => { + acc.add(usdcToken, x.stablecoinInitialLiquidity) + return acc + }, totalProtocolRevenue) + + // --- Holders Revenue + dailyHoldersRevenue = todayRes.reduce((acc: Balances, x) => { + acc.add(usdcToken, new BigNumber(x.ceTokenStakingReward).multipliedBy(x.project.tokenPrice).div(new BigNumber(10).pow(18)).toFixed(0)) + return acc + }, dailyHoldersRevenue) + + totalHoldersRevenue = res.projectDistributions.reduce((acc: Balances, x) => { + acc.add(usdcToken, new BigNumber(x.ceTokenStakingReward).multipliedBy(x.project.tokenPrice).div(new BigNumber(10).pow(18)).toFixed(0)) + return acc + }, totalHoldersRevenue) + } + } catch (e) { + console.error(e); + } + + return { + dailyProtocolRevenue, + totalProtocolRevenue, + dailyHoldersRevenue, + totalHoldersRevenue + } +} diff --git a/fees/colony/index.ts b/fees/colony/index.ts new file mode 100644 index 0000000000..50671b66d9 --- /dev/null +++ b/fees/colony/index.ts @@ -0,0 +1,162 @@ +import { Adapter, FetchOptions, FetchResultV2 } from "../../adapters/types"; +import { CHAIN } from "../../helpers/chains"; + +import { stakingFees } from "./staking"; +import { dexFees } from "./dex"; +import { earlyStageFees } from "./earlystage"; +import { caiFees } from "./cai"; +import { validatorProgramFees } from "./validatorProgram"; +import { airdrops } from "./airdrops"; +import { masterChef } from "./masterChef"; + +const ColonyGovernanceToken = "0xec3492a2508DDf4FDc0cD76F31f340b30d1793e6"; + +const stakingSubgraphEndpoint = 'https://graph.colonylab.io/subgraphs/name/colony/stakingV3-avalanche-production'; +const dexSubgraphEndpoint = 'https://graph.colonylab.io/subgraphs/name/colony-dex/exchange-avalanche-production'; +const earlystageSubgraphEndpoint = 'https://graph.colonylab.io/subgraphs/name/colony/earlystage-avalanche-production'; +const masterChefSubgraphEndpoint = 'https://graph.colonylab.io/subgraphs/name/colony-dex/masterchef-avalanche-production' + +const methodology = { + HoldersRevenue: "Revenue distributed to token stakers includes 100% from CLY staking and unstaking fees, 50% of CAI fees, 8% of early-stage activity fees (ceTokens), and 70% of Validator Program activity revenues. This distribution creates a strong APY for CLY stakers, incentivizing protocol staking and long-term involvement in Colony's protocol.", + SupplySideRevenue: "83.33% of the fees collected from Colony DEX transactions are distributed to liquidity providers. Additionally, 10% of ceTokens are distributed to staked liquidity providers on Colony's DEX, incentivizing them to continue providing liquidity and supporting the exchange. Additional revenue can be generated through farm rewards based on specific marketing campaigns and incentive programs.", + ProtocolRevenue: "Revenue sources directly retained by the protocol include 50% from CAI fees (minting 0.20%, redemption 0.5%, and management 1%), 2% from early-stage platform activities (ceTokens distribution), 2% from USDC fundraised by a project, 16.66% from Colony DEX swap fees, and 30% from Validator Program activities. These funds support the protocol's ongoing development and operations." +} + +async function fetch(options: FetchOptions): Promise { + const { createBalances } = options; + + const stakingResult = await stakingFees( + options, + stakingSubgraphEndpoint, + ColonyGovernanceToken + ); + + const dexResult = await dexFees( + options, + dexSubgraphEndpoint + ); + + const earlystageResult = await earlyStageFees( + options, + earlystageSubgraphEndpoint, + ); + + const caiResult = await caiFees( + options + ); + + const validatorProgramResult = await validatorProgramFees( + options, + stakingSubgraphEndpoint + ); + + const airdropsResult = await airdrops( + options, + stakingSubgraphEndpoint + ); + + const masterChefResults = await masterChef( + options, + masterChefSubgraphEndpoint, + earlystageSubgraphEndpoint + ); + + let dailyFees = createBalances(); + let totalFees = createBalances(); + let dailyRevenue = createBalances(); + let totalRevenue = createBalances(); + let dailyHoldersRevenue = createBalances(); + let totalHoldersRevenue = createBalances(); + let dailyProtocolRevenue = createBalances(); + let totalProtocolRevenue = createBalances(); + let dailySupplySideRevenue = createBalances(); + let totalSupplySideRevenue = createBalances(); + + // --- Holders Revenue + dailyHoldersRevenue.addBalances(stakingResult.dailyHoldersRevenue) + totalHoldersRevenue.addBalances(stakingResult.totalHoldersRevenue) + + dailyHoldersRevenue.addBalances(earlystageResult.dailyHoldersRevenue) + totalHoldersRevenue.addBalances(earlystageResult.totalHoldersRevenue) + + dailyHoldersRevenue.addBalances(caiResult.dailyHoldersRevenue) + totalHoldersRevenue.addBalances(caiResult.totalHoldersRevenue) + + dailyHoldersRevenue.addBalances(validatorProgramResult.dailyHoldersRevenue) + totalHoldersRevenue.addBalances(validatorProgramResult.totalHoldersRevenue) + + dailyHoldersRevenue.addBalances(airdropsResult.dailyHoldersRevenue) + totalHoldersRevenue.addBalances(airdropsResult.totalHoldersRevenue) + + // --- Protocol Revenue + dailyProtocolRevenue.addBalances(earlystageResult.dailyProtocolRevenue) + totalProtocolRevenue.addBalances(earlystageResult.totalProtocolRevenue) + + dailyProtocolRevenue.addBalances(caiResult.dailyProtocolRevenue) + totalProtocolRevenue.addBalances(caiResult.totalProtocolRevenue) + + dailyProtocolRevenue.addBalances(validatorProgramResult.dailyProtocolRevenue) + totalProtocolRevenue.addBalances(validatorProgramResult.totalProtocolRevenue) + + dailyProtocolRevenue.addBalances(dexResult.dailyProtocolRevenue) + totalProtocolRevenue.addBalances(dexResult.totalProtocolRevenue) + + // --- Supply Side Revenue + dailySupplySideRevenue.addBalances(dexResult.dailySupplySideRevenue) + totalSupplySideRevenue.addBalances(dexResult.totalSupplySideRevenue) + + dailySupplySideRevenue.addBalances(masterChefResults.dailySupplySideRevenue) + totalSupplySideRevenue.addBalances(masterChefResults.totalSupplySideRevenue) + + // --- Revenue + dailyRevenue.addBalances(dailyProtocolRevenue) + totalRevenue.addBalances(totalProtocolRevenue) + + dailyRevenue.addBalances(dailyHoldersRevenue) + totalRevenue.addBalances(totalHoldersRevenue) + + // --- Fees + dailyFees.addBalances(dailyRevenue) + totalFees.addBalances(totalRevenue) + + dailyFees.addBalances(dailySupplySideRevenue) + totalFees.addBalances(totalSupplySideRevenue) + + return { + timestamp: dexResult.timestamp, + block: dexResult.block, + + dailyVolume: dexResult.dailyVolume, + totalVolume: dexResult.totalVolume, + + dailyFees, + totalFees, + + dailyRevenue, + totalRevenue, + + dailyHoldersRevenue, + totalHoldersRevenue, + + dailyProtocolRevenue, + totalProtocolRevenue, + + dailySupplySideRevenue, + totalSupplySideRevenue + } +} + +const adapter: Adapter = { + version: 2, + adapter: { + [CHAIN.AVAX]: { + fetch, + start: 1704067200, + meta: { + methodology + } + }, + } +} + +export default adapter; diff --git a/fees/colony/masterChef.ts b/fees/colony/masterChef.ts new file mode 100644 index 0000000000..2b40954584 --- /dev/null +++ b/fees/colony/masterChef.ts @@ -0,0 +1,129 @@ +import { Balances } from "@defillama/sdk"; +import { FetchOptions } from "../../adapters/types"; +import { request, gql } from "graphql-request"; +import BigNumber from "bignumber.js"; + +const usdcToken = '0xB97EF9Ef8734C71904D8002F8b6Bc66Dd9c48a6E' + +export interface Airdrops { + dailySupplySideRevenue: Balances; + totalSupplySideRevenue: Balances; +} + +interface IGraphAirdropsResponse { + rewarders: { + rewardToken: string + name: string + decimals: number + schedule: { + rangeAmount: string + }[] + startTimestamp: number + }[] +} + +interface ICeTokensResponse { + projects: { + ceToken: { + id: string + } + tokenPrice: string + }[] +} + +const rewardersQuery = gql + `{ + rewarders { + rewardToken + name + decimals + schedule { + rangeAmount + } + startTimestamp + } + }`; + +const ceTokensQuery = gql + `{ + projects(where: {ceToken_not: null}) { + ceToken { + id + } + tokenPrice + } + }`; + +function addTokenBalance( + balance: Balances, + prices: Map, + tokenAddress: string, + tokenDecimals: number, + rewarderSchedule: Array<{ rangeAmount: string }>, + isCeToken: boolean +) { + if (isCeToken) { + const price = prices.get(tokenAddress.toLowerCase()) ?? 0 + const totalCeToken = rewarderSchedule.reduce((acc, x) => { + return acc.plus(x.rangeAmount) + }, new BigNumber(0)) + + balance.add(usdcToken, totalCeToken.multipliedBy(price).div(new BigNumber(10).pow(tokenDecimals)).toFixed(0)) + } + else { + balance.add(tokenAddress, rewarderSchedule.reduce((acc, x) => { + return acc.plus(x.rangeAmount) + }, new BigNumber(0)).toFixed(0)) + } + + return balance +} + +export async function masterChef( + options: FetchOptions, + masterChefSubgraphEndpoint: string, + earlyStageSubgraphEndpoint: string, +): Promise { + const { createBalances, startTimestamp, endTimestamp } = options; + + let dailySupplySideRevenue = createBalances() + let totalSupplySideRevenue = createBalances() + + try { + const ceTokenRes: ICeTokensResponse = await request(earlyStageSubgraphEndpoint, ceTokensQuery); + const priceMap = new Map() + for (const ceToken of ceTokenRes.projects) { + priceMap.set(ceToken.ceToken.id.toLowerCase(), ceToken.tokenPrice) + } + + const rewardersRes: IGraphAirdropsResponse = await request(masterChefSubgraphEndpoint, rewardersQuery); + for (const rewarder of rewardersRes.rewarders) { + if (rewarder.startTimestamp >= startTimestamp && rewarder.startTimestamp < endTimestamp) { + addTokenBalance( + dailySupplySideRevenue, + priceMap, + rewarder.rewardToken, + rewarder.decimals, + rewarder.schedule, + rewarder.name.includes(' ceToken') + ) + } + addTokenBalance( + totalSupplySideRevenue, + priceMap, + rewarder.rewardToken, + rewarder.decimals, + rewarder.schedule, + rewarder.name.includes(' ceToken') + ) + } + + } catch (e) { + console.error(e); + } + + return { + dailySupplySideRevenue, + totalSupplySideRevenue + } +} diff --git a/fees/colony/staking.ts b/fees/colony/staking.ts new file mode 100644 index 0000000000..da9f04d81e --- /dev/null +++ b/fees/colony/staking.ts @@ -0,0 +1,54 @@ +import { Balances } from "@defillama/sdk"; +import { FetchOptions } from "../../adapters/types"; +import { request, gql } from "graphql-request"; + +const queryStakingFeesMetrics = gql` + query fees($block: Int!) { + metrics(block: { number: $block }) { + totalStakeFees + totalUnstakeFees + } + } +`; + +export async function stakingFees( + options: FetchOptions, + stakingSubgraphEndpoint: string, + ColonyGovernanceToken: string, +): Promise<{ + dailyHoldersRevenue: Balances; + totalHoldersRevenue: Balances; +}> { + const { createBalances, getStartBlock, getEndBlock } = options; + + const [startBlock, endBlock] = await Promise.all([ + getStartBlock(), + getEndBlock(), + ]); + let dailyHoldersRevenue = createBalances(); + let totalHoldersRevenue = createBalances(); + + const [beforeRes, afterRes] = await Promise.all([ + request(stakingSubgraphEndpoint, queryStakingFeesMetrics, { + block: startBlock, + }), + request(stakingSubgraphEndpoint, queryStakingFeesMetrics, { + block: endBlock, + }), + ]); + + const beforeFees: number = + Number(beforeRes.metrics[0].totalStakeFees) + + Number(beforeRes.metrics[0].totalUnstakeFees); + const afterFees: number = + Number(afterRes.metrics[0].totalStakeFees) + + Number(afterRes.metrics[0].totalUnstakeFees); + + dailyHoldersRevenue.add(ColonyGovernanceToken, afterFees - beforeFees); + totalHoldersRevenue.add(ColonyGovernanceToken, afterFees); + + return { + dailyHoldersRevenue, + totalHoldersRevenue, + }; +} diff --git a/fees/colony/validatorProgram.ts b/fees/colony/validatorProgram.ts new file mode 100644 index 0000000000..9dcfea487b --- /dev/null +++ b/fees/colony/validatorProgram.ts @@ -0,0 +1,76 @@ +import { Balances } from "@defillama/sdk"; +import { FetchOptions } from "../../adapters/types"; +import { request, gql } from "graphql-request"; +import BigNumber from "bignumber.js"; + +export interface ValidatorProgramFees { + dailyProtocolRevenue: Balances; + totalProtocolRevenue: Balances; + dailyHoldersRevenue: Balances; + totalHoldersRevenue: Balances; +} + +interface IGraphEarlyStageFeesResponse { + rewards: { + amount: string + }[] + rewardPerTokenPerCategories: { + amountTotal: string + }[] +} + +const wavaxToken = '0xb31f66aa3c1e785363f0875a1b74e27b85fd66c7' + +const queryValidatorProgramFees = gql + `query ValidatorProgramFees($timestampFrom: BigInt!, $timestampTo: BigInt!) { + rewards( + where: {createdAt_gte: $timestampFrom, createdAt_lt: $timestampTo, token: "${wavaxToken}", categoryId: 1} + ) { + amount + } + rewardPerTokenPerCategories( + where: {token: "${wavaxToken}", categoryId: 1} + ) { + amountTotal + } + }`; + + +export async function validatorProgramFees( + options: FetchOptions, + stakingV3SubgraphEndpoint: string, +): Promise { + const { createBalances, startTimestamp, endTimestamp } = options; + + let dailyProtocolRevenue = createBalances() + let totalProtocolRevenue = createBalances() + let dailyHoldersRevenue = createBalances() + let totalHoldersRevenue = createBalances() + + try { + const res: IGraphEarlyStageFeesResponse = await request(stakingV3SubgraphEndpoint, queryValidatorProgramFees, { + timestampFrom: startTimestamp, + timestampTo: endTimestamp + }); + + if (res.rewards[0] !== undefined) { + dailyProtocolRevenue.add(wavaxToken, new BigNumber(res.rewards[0].amount).div(0.7).multipliedBy(0.3).toFixed(0)) + dailyHoldersRevenue.add(wavaxToken, res.rewards[0].amount) + } + + if (res.rewardPerTokenPerCategories[0] !== undefined) { + totalProtocolRevenue.add(wavaxToken, new BigNumber(res.rewardPerTokenPerCategories[0].amountTotal).div(0.7).multipliedBy(0.3).toFixed(0)) + totalHoldersRevenue.add(wavaxToken, res.rewardPerTokenPerCategories[0].amountTotal) + } + + } catch (e) { + console.error(e); + } + + return { + dailyProtocolRevenue, + totalProtocolRevenue, + dailyHoldersRevenue, + totalHoldersRevenue + } +} diff --git a/fees/compound.ts b/fees/compound.ts index abc78ba144..662a9c8f04 100644 --- a/fees/compound.ts +++ b/fees/compound.ts @@ -1,3 +1,4 @@ +import * as sdk from "@defillama/sdk"; import { Adapter } from "../adapters/types"; import { ETHEREUM } from "../helpers/chains"; import { request, gql } from "graphql-request"; @@ -10,7 +11,7 @@ import { getTimestampAtStartOfPreviousDayUTC, getTimestampAtStartOfDayUTC } from const endpoints = { [ETHEREUM]: - "https://api.thegraph.com/subgraphs/name/messari/compound-v2-ethereum" + sdk.graph.modifyEndpoint('Rh7h4KeZCnJZoBv3nZ4K8occAXEnwxRkR6pTKDsN3Fj') } @@ -57,6 +58,7 @@ const graphs = (graphUrls: ChainEndpoints) => { const adapter: Adapter = { + version: 1, adapter: { [ETHEREUM]: { fetch: graphs(endpoints)(ETHEREUM), diff --git a/fees/concentrator.ts b/fees/concentrator.ts index 6edbe8d741..f9918634bd 100644 --- a/fees/concentrator.ts +++ b/fees/concentrator.ts @@ -1,36 +1,57 @@ +import * as sdk from "@defillama/sdk"; import { Adapter } from "../adapters/types"; import { ETHEREUM } from "../helpers/chains"; import { request, gql } from "graphql-request"; -import type { ChainBlocks, ChainEndpoints, FetchOptions } from "../adapters/types"; +import type { + ChainBlocks, + ChainEndpoints, + FetchOptions, +} from "../adapters/types"; import { Chain } from "@defillama/sdk/build/general"; -import { getTimestampAtStartOfDayUTC } from "../utils/date"; +import fetchURL from "../utils/fetchURL"; + +const priceUrl = "https://api.aladdin.club/api/coingecko/price"; const endpoints = { [ETHEREUM]: - "https://api.thegraph.com/subgraphs/name/aladdindaogroup/aladdin-fees", + sdk.graph.modifyEndpoint('CCaEZU1PJyNaFmEjpyc4AXUiANB6M6DGDCJuWa48JWTo'), }; const graph = (graphUrls: ChainEndpoints) => { return (chain: Chain) => { - return async (timestamp: number, _: ChainBlocks, { createBalances }: FetchOptions) => { - const dateId = Math.floor(getTimestampAtStartOfDayUTC(timestamp)); + return async ( + _timestamp: number, + _: ChainBlocks, + { startOfDay }: FetchOptions + ) => { + const dateId = Math.floor(startOfDay); const graphQuery = gql`{ dailyRevenueSnapshot(id: ${dateId}) { aCRVRevenue } }`; - const { dailyRevenueSnapshot: snapshot } = await request(graphUrls[chain], graphQuery); + const { dailyRevenueSnapshot: snapshot } = await request( + graphUrls[chain], + graphQuery + ); if (!snapshot) throw new Error("No data found"); - const dailyRevenue = createBalances(); - dailyRevenue.addCGToken("aladdin-crv", snapshot.aCRVRevenue); - const dailyFees = dailyRevenue.clone(2); - return { timestamp, dailyFees, dailyRevenue }; + + const { aCRV } = (await fetchURL(priceUrl))?.data; + + const dailyRevenue = snapshot.aCRVRevenue; + + const usd = dailyRevenue * aCRV.usd; + const revenue = usd.toFixed(0); + const dailyFees = (usd * 2).toFixed(0); + + return { timestamp: startOfDay, dailyFees, dailyRevenue: revenue }; }; }; }; const adapter: Adapter = { + version: 1, adapter: { [ETHEREUM]: { fetch: graph(endpoints)(ETHEREUM), diff --git a/fees/convex.ts b/fees/convex.ts index 9859648b36..d9ab9a5edf 100644 --- a/fees/convex.ts +++ b/fees/convex.ts @@ -1,3 +1,4 @@ +import * as sdk from "@defillama/sdk"; import {Adapter} from "../adapters/types"; import {ETHEREUM} from "../helpers/chains"; import {request, gql} from "graphql-request"; @@ -8,7 +9,7 @@ import BigNumber from "bignumber.js"; const endpoints = { [ETHEREUM]: - "https://api.thegraph.com/subgraphs/name/convex-community/convex", + sdk.graph.modifyEndpoint('2jMwDRmUtTRAw9w3nMuZZPQtC97Ro28nLdJFWnFQnJdz'), }; @@ -85,6 +86,7 @@ const graph = (graphUrls: ChainEndpoints) => { }; const adapter: Adapter = { + version: 1, adapter: { [ETHEREUM]: { fetch: graph(endpoints)(ETHEREUM), diff --git a/fees/core-markets/index.ts b/fees/core-markets/index.ts new file mode 100644 index 0000000000..71a013e414 --- /dev/null +++ b/fees/core-markets/index.ts @@ -0,0 +1,109 @@ +import BigNumber from "bignumber.js"; +import request, { gql } from "graphql-request"; +import { FetchOptions, SimpleAdapter } from "../../adapters/types"; +import { CHAIN } from "../../helpers/chains"; + +const endpoint = "https://api.studio.thegraph.com/query/62472/core-analytics-082/version/latest"; + +const query = gql` + query stats($from: String!, $to: String!) { + dailyHistories( + where: { timestamp_gte: $from, timestamp_lte: $to, accountSource: "0xd6ee1fd75d11989e57B57AA6Fd75f558fBf02a5e" } + ) { + timestamp + platformFee + accountSource + tradeVolume + } + totalHistories(where: { accountSource: "0xd6ee1fd75d11989e57B57AA6Fd75f558fBf02a5e" }) { + timestamp + platformFee + accountSource + tradeVolume + } + } +`; + +interface IGraphResponse { + dailyHistories: Array<{ + tiemstamp: string; + platformFee: string; + accountSource: string; + tradeVolume: string; + }>; + totalHistories: Array<{ + tiemstamp: string; + platformFee: string; + accountSource: string; + tradeVolume: BigNumber; + }>; +} + +const toString = (x: BigNumber) => { + if (x.isEqualTo(0)) return undefined; + return x.toString(); +}; + +const fetchVolume = async ({ startTimestamp, endTimestamp }: FetchOptions) => { + + const response: IGraphResponse = await request(endpoint, query, { + from: startTimestamp, + to: endTimestamp, + }); + + // Merging both responses + let dailyFees = new BigNumber(0); + + response.dailyHistories.forEach((data) => { + dailyFees = dailyFees.plus(new BigNumber(data.platformFee)); + }); + + let totalFees = new BigNumber(0); + + response.totalHistories.forEach((data) => { + totalFees = totalFees.plus(new BigNumber(data.platformFee)); + }); + + dailyFees = dailyFees.dividedBy(new BigNumber(1e18)); + totalFees = totalFees.dividedBy(new BigNumber(1e18)); + + const _dailyFees = toString(dailyFees); + const _totalFees = toString(totalFees); + + const dailyUserFees = _dailyFees; + const dailyRevenue = _dailyFees; + const dailyProtocolRevenue = "0"; + const dailyHoldersRevenue = _dailyFees; + const dailySupplySideRevenue = "0"; + + const totalUserFees = _totalFees; + const totalRevenue = _totalFees; + const totalProtocolRevenue = "0"; + const totalSupplySideRevenue = "0"; + + return { + dailyFees: _dailyFees ?? "0", + totalFees: _totalFees ?? "0", + + dailyUserFees: dailyUserFees ?? "0", + dailyRevenue: dailyRevenue ?? "0", + dailyProtocolRevenue: dailyProtocolRevenue ?? "0", + dailyHoldersRevenue: dailyHoldersRevenue ?? "0", + dailySupplySideRevenue: dailySupplySideRevenue ?? "0", + totalUserFees: totalUserFees ?? "0", + totalRevenue: totalRevenue ?? "0", + totalProtocolRevenue: totalProtocolRevenue ?? "0", + totalSupplySideRevenue: totalSupplySideRevenue ?? "0", + }; +}; + +const adapter: SimpleAdapter = { + adapter: { + [CHAIN.BLAST]: { + fetch: fetchVolume, + start: async () => 236678, + }, + }, + version: 2 +}; +export default adapter; diff --git a/fees/covo-finance.ts b/fees/covo-finance.ts index 7bf2a76a79..5b3dcaede0 100644 --- a/fees/covo-finance.ts +++ b/fees/covo-finance.ts @@ -1,3 +1,4 @@ +import * as sdk from "@defillama/sdk"; import { Adapter } from "../adapters/types"; import { POLYGON, AVAX } from "../helpers/chains"; import { request, gql } from "graphql-request"; @@ -6,7 +7,7 @@ import { Chain } from '@defillama/sdk/build/general'; import { getTimestampAtStartOfDayUTC } from "../utils/date"; const endpoints = { - [POLYGON]: "https://api.thegraph.com/subgraphs/name/defi-techz/graphordertst", + [POLYGON]: sdk.graph.modifyEndpoint('CvqFU9sqzqpdNJMyJri2J9LjUjkzdjQZDGwdvzf1naXH'), } let dailyFee= 0; @@ -64,6 +65,7 @@ const graphs = (graphUrls: ChainEndpoints) => { const adapter: Adapter = { + version: 1, adapter: { [POLYGON]: { fetch: graphs(endpoints)(POLYGON), diff --git a/fees/covo-v2.ts b/fees/covo-v2.ts index 15a545d393..6b6ebeb8cd 100644 --- a/fees/covo-v2.ts +++ b/fees/covo-v2.ts @@ -1,3 +1,4 @@ +import * as sdk from "@defillama/sdk"; import { Adapter } from "../adapters/types"; import { POLYGON, AVAX } from "../helpers/chains"; import { request, gql } from "graphql-request"; @@ -6,7 +7,7 @@ import { Chain } from '@defillama/sdk/build/general'; import { getTimestampAtStartOfDayUTC } from "../utils/date"; const endpoints = { - [POLYGON]: "https://api.thegraph.com/subgraphs/name/defi-techz/covo-v2", + [POLYGON]: sdk.graph.modifyEndpoint('B8469Fs5athX6XeADT1LUYLKpcupEpWumfRuMbQw6cXs'), } let dailyFee= 0; @@ -82,6 +83,7 @@ const graphs = (graphUrls: ChainEndpoints) => { const adapter: Adapter = { + version: 1, adapter: { [POLYGON]: { fetch: graphs(endpoints)(POLYGON), diff --git a/fees/cow-protocol.ts b/fees/cow-protocol.ts index 005e9d50ef..6f42fd81f5 100644 --- a/fees/cow-protocol.ts +++ b/fees/cow-protocol.ts @@ -1,8 +1,7 @@ -import ADDRESSES from '../helpers/coreAssets.json' -import { Adapter, FetchOptions, FetchResultFees } from "../adapters/types"; +import { Adapter, FetchOptions } from "../adapters/types"; import { CHAIN } from "../helpers/chains"; import { Chain, } from "@defillama/sdk/build/general"; -import { queryIndexer } from "../helpers/indexer"; +import { queryDune } from "../helpers/dune"; type TAddress = { [l: string | Chain]: string; @@ -13,35 +12,24 @@ const address: TAddress = { } -const fetch = (chain: Chain) => { - return async (timestamp: number, _: any, options: FetchOptions): Promise => { - const logs = await options.getLogs({ - target: address[chain], - eventAbi: "event Trade (address indexed owner, address sellToken, address buyToken, uint256 sellAmount, uint256 buyAmount, uint256 feeAmount, bytes orderUid)", - }) +const fetch = (_: Chain) => { + return async (options: FetchOptions) => { const dailyFees = options.createBalances(); - logs.map((tx: any) => dailyFees.add(tx.sellToken, tx.feeAmount)) - const dailyRevenue = dailyFees.clone() - if (chain === CHAIN.ETHEREUM) { - const gasUsed = await queryIndexer(` - SELECT - COUNT(ethereum.event_logs.transaction_hash) as _count, - ethereum.transactions.gas_used * ethereum.transactions.gas_price AS sum - FROM - ethereum.event_logs - INNER JOIN ethereum.blocks ON ethereum.event_logs.block_number = ethereum.blocks.number - INNER JOIN ethereum.transactions on ethereum.event_logs.transaction_hash = ethereum.transactions.hash - WHERE - ethereum.event_logs.contract_address = '\\x9008d19f58aabd9ed0d60971565aa8510560ab41' - AND ethereum.event_logs.topic_0 = '\\xed99827efb37016f2275f98c4bcf71c7551c75d59e9b450f79fa32e60be672c2' - AND success = TRUE - AND ethereum.event_logs.block_time BETWEEN llama_replace_date_range - GROUP by sum`, options); - - gasUsed.map((e: any) => dailyRevenue.add(ADDRESSES.ethereum.WETH, e.sum * -1 / e._count)) + try { + const value = (await queryDune("3968762")); + const dateStr = new Date(options.endTimestamp * 1000).toISOString().split("T")[0]; + const dayItem = value.find((item: any) => item.time.split(' ')[0] === dateStr); + dailyFees.addGasToken((dayItem?.total_revenue) * 1e18 || 0) + return { + dailyFees: dailyFees, + dailyRevenue: dailyFees, + } + } catch (e) { + return { + dailyFees: dailyFees, + dailyRevenue: dailyFees, + } } - - return { dailyUserFees: dailyFees, dailyFees, dailyRevenue, timestamp } } } @@ -52,6 +40,7 @@ const methodology = { } const adapter: Adapter = { + version: 2, adapter: { [CHAIN.ETHEREUM]: { fetch: fetch(CHAIN.ETHEREUM) as any, @@ -67,7 +56,8 @@ const adapter: Adapter = { // methodology // } // } - } + }, + isExpensiveAdapter: true, } export default adapter; diff --git a/fees/crv-usd.ts b/fees/crv-usd.ts index 58d942d440..25468985a3 100644 --- a/fees/crv-usd.ts +++ b/fees/crv-usd.ts @@ -17,11 +17,17 @@ const controller: TContract = { } const fetchFees = (chain: Chain) => { - return async (timestamp: number, _: ChainBlocks, { createBalances, getLogs, }: FetchOptions): Promise => { + return async ({ createBalances, getLogs, fromApi, toApi }: FetchOptions) => { const dailyFees = createBalances() - const logs = await getLogs({ targets: controller[chain], eventAbi: 'event CollectFees (uint256 amount, uint256 new_supply)' }) - logs.forEach((i: any) => dailyFees.add('0xf939E0A03FB07F59A73314E73794Be0E57ac1b4E', i.amount)) - return { dailyFees, timestamp, dailyRevenue: dailyFees, dailyHoldersRevenue: dailyFees } + await Promise.all(controller[chain].map(async controller=>{ + const logs = await getLogs({ target: controller, eventAbi: 'event CollectFees (uint256 amount, uint256 new_supply)' }) + logs.forEach((i: any) => dailyFees.add('0xf939E0A03FB07F59A73314E73794Be0E57ac1b4E', i.amount)) + const feesStart = await fromApi.call({target: controller, abi: "uint:admin_fees"}) + const feesEnd = await toApi.call({target: controller, abi: "uint:admin_fees"}) + dailyFees.add("0xf939E0A03FB07F59A73314E73794Be0E57ac1b4E", feesEnd-feesStart) + })) + + return { dailyFees, dailyRevenue: dailyFees, dailyHoldersRevenue: dailyFees } } } @@ -31,6 +37,7 @@ const adapters: SimpleAdapter = { fetch: fetchFees(CHAIN.ETHEREUM), start: 1684047600 } - } + }, + version: 2 } export default adapters; diff --git a/fees/cryptex-v2.ts b/fees/cryptex-v2.ts index 12b9db9992..fd92b9d7c3 100644 --- a/fees/cryptex-v2.ts +++ b/fees/cryptex-v2.ts @@ -1,27 +1,11 @@ -import { Adapter, FetchResultFees } from "../adapters/types"; +import { Adapter, FetchOptions } from "../adapters/types"; import { CHAIN } from "../helpers/chains"; -import * as sdk from "@defillama/sdk"; -import { getBlock } from "../helpers/getBlock"; -import { ethers } from "ethers"; -import { getPrices } from "../utils/prices"; -import { type } from "os"; - -interface ILog { - data: string; - transactionHash: string; - topics: string[]; - address: string; -} const products: string[] = [ '0x4243b34374cfb0a12f184b92f52035d03d4f7056', // TCAP '0x1cd33f4e6edeee8263aa07924c2760cf2ec8aad0', // TCAP ]; -const make_closed_topic0 = '0x39854479080fac0b5e7c0ecedb0fb02308a72a43cd102c6b9f918653d3400367' -const make_opened_topic0 = '0xf98b31465ac12e92b5cb136ade913276c267463c4395bb1a3999bc88fb837806' -const take_closed_topic0 = '0x63625b85818a29587ee919ee6a968ee0b32f3513f2884b3968001062ba49eb6b' -const take_opened_topic0 = '0xb9726781b72c53f23217f424d70445b222951f008aeac7eece8139caed71ed2d' const make_closed_event = 'event MakeClosed(address indexed account,uint256 version,uint256 amount)' const make_opened_event = 'event MakeOpened(address indexed account,uint256 version,uint256 amount)' @@ -29,20 +13,6 @@ const make_opened_event = 'event MakeOpened(address indexed account,uint256 vers const take_closed_event = 'event TakeClosed(address indexed account,uint256 version,uint256 amount)' const take_opened_event = 'event TakeOpened(address indexed account,uint256 version,uint256 amount)' -const contract_interface = new ethers.Interface([ - make_closed_event, - make_opened_event, - take_closed_event, - take_opened_event -]); - -type IMapCoin = { - [s: string]: string; -} -const coinsId: IMapCoin = { - '0x4243b34374cfb0a12f184b92f52035d03d4f7056': 'coingecko:total-crypto-market-cap-token', // TCAP - '0x1cd33f4e6edeee8263aa07924c2760cf2ec8aad0': 'coingecko:total-crypto-market-cap-token', // TCAP -} const abis: any = { "makerFee": "uint256:makerFee", @@ -53,117 +23,56 @@ type IPrice = { [s: string]: number; } -const fetch = async (timestamp: number): Promise => { - - const fromTimestamp = timestamp - 60 * 60 * 24 - const toTimestamp = timestamp - const fromBlock = (await getBlock(fromTimestamp, CHAIN.ARBITRUM, {})); - const toBlock = (await getBlock(toTimestamp, CHAIN.ARBITRUM, {})); - const make_closed_topic0_logs: ILog[] = (await Promise.all(products.map((address: string) => sdk.getEventLogs({ - target: address, - toBlock: toBlock, - fromBlock: fromBlock, - chain: CHAIN.ARBITRUM, - topics: [make_closed_topic0] - })))).flat(); - - const make_opened_topic0_logs: ILog[] = (await Promise.all(products.map((address: string) => sdk.getEventLogs({ - target: address, - toBlock: toBlock, - fromBlock: fromBlock, - chain: CHAIN.ARBITRUM, - topics: [make_opened_topic0] - })))).flat(); - - const take_closed_topic0_logs: ILog[] = (await Promise.all(products.map((address: string) => sdk.getEventLogs({ - target: address, - toBlock: toBlock, - fromBlock: fromBlock, - chain: CHAIN.ARBITRUM, - topics: [take_closed_topic0] - })))).flat(); - - const take_opened_topic0_logs: ILog[] = (await Promise.all(products.map((address: string) => sdk.getEventLogs({ - target: address, - toBlock: toBlock, - fromBlock: fromBlock, - chain: CHAIN.ARBITRUM, - topics: [take_opened_topic0] - })))).flat(); - - const [makerFee, takerFee] = await Promise.all( - ['makerFee', 'takerFee'].map((method: string) => - sdk.api2.abi.multiCall({ - abi: abis[method], - calls: products.map((address: string) => ({ - target: address, - })), - chain: CHAIN.ARBITRUM - }) - ) - ); - - const makerFees = makerFee.map((res: any) => Number(res) / 10 ** 18); - const takerFees = takerFee.map((res: any) => Number(res) / 10 ** 18); - - const all: ILog[] = [ - ...make_closed_topic0_logs, - ...make_opened_topic0_logs, - ...take_closed_topic0_logs, - ...take_opened_topic0_logs - ] - const versions = [...new Set(all.map(e => contract_interface.parseLog(e)).map(e => Number(e!.args.version)))]; - const price_ = (await sdk.api2.abi.multiCall({ - abi: abis.atVersion, - calls: versions.map((version: number) => ({ - target: products[0], - params: [version] - })), - chain: CHAIN.ARBITRUM - })) - const _prices: IPrice = {} - price_.forEach((e: any) => { - const raw_price: string = e.price; - const version: string = e.version; - const price = Number(raw_price.toString().replace('-', '')) / 10 ** 18; - _prices[version] = price; - }); - - const maker_logs: ILog[] = [ - ...make_closed_topic0_logs, - ...make_opened_topic0_logs, - ] - const taker_logs: ILog[] = [ - ...take_closed_topic0_logs, - ...take_opened_topic0_logs - ] - - const makerFeesAmount = maker_logs.map((a: ILog) => { - const value = contract_interface.parseLog(a); - const price = _prices[value!.args.version] - const findIndex = products.findIndex(p => p.toLowerCase() === a.address.toLowerCase()); - const fees = makerFees[findIndex] - return ((Number(value!.args.amount) / 1e18) * price) * fees; - }).reduce((a: number, b: number) => a + b, 0) - - const takerFeesAmount = taker_logs.map((a: ILog) => { - const value = contract_interface.parseLog(a); - const price = _prices[value!.args.version] - const findIndex = products.findIndex(p => p.toLowerCase() === a.address.toLowerCase()); - const fees = takerFees[findIndex] - return ((Number(value!.args.amount) / 1e18) * price) * fees; - }).reduce((a: number, b: number) => a + b, 0) - - const dailyFees = (makerFeesAmount + takerFeesAmount); - const dailyRevenue = dailyFees; - return { - dailyFees: `${dailyFees}`, - dailyRevenue: `${dailyRevenue}`, - timestamp +const fetch = async ({ getLogs, api, createBalances }: FetchOptions) => { + const dailyFees = createBalances(); + for (const product of products) { + const make_closed_topic0_logs = await getLogs({ target: product, eventAbi: make_closed_event }) + const make_opened_topic0_logs = await getLogs({ target: product, eventAbi: make_opened_event }) + const take_closed_topic0_logs = await getLogs({ target: product, eventAbi: take_closed_event }) + const take_opened_topic0_logs = await getLogs({ target: product, eventAbi: take_opened_event }) + + const [makerFees, takerFees] = await Promise.all( + ['makerFee', 'takerFee'].map((method: string) => api.multiCall({ abi: abis[method], calls: [product], })) + ); + + const all = [make_closed_topic0_logs, make_opened_topic0_logs, take_closed_topic0_logs, take_opened_topic0_logs].flat() + const versions = [...new Set(all.map(e => Number(e.version)))]; + const price_ = (await api.multiCall({ abi: abis.atVersion, target: products[0], calls: versions, })) + const _prices: IPrice = {} + price_.forEach((e: any) => { + const raw_price: string = e.price; + const version: string = e.version; + const price = Number(raw_price.toString().replace('-', '')) / 10 ** 18; + _prices[version] = price; + }); + + const maker_logs = [ + ...make_closed_topic0_logs, + ...make_opened_topic0_logs, + ] + const taker_logs = [ + ...take_closed_topic0_logs, + ...take_opened_topic0_logs + ] + + maker_logs.forEach((value: any) => { + const price = _prices[value!.version] + const fees = makerFees[0].toString() + dailyFees.addUSDValue(value.amount.toString() * price * fees / 1e36) + }) + + taker_logs.forEach((value: any) => { + const price = _prices[value!.version] + const fees = takerFees[0].toString() + dailyFees.addUSDValue(value.amount.toString() * price * fees / 1e36) + }) } + + return { dailyFees, dailyRevenue: dailyFees, } } const adapter: Adapter = { + version: 2, adapter: { [CHAIN.ARBITRUM]: { fetch: fetch, diff --git a/fees/curve.ts b/fees/curve.ts index cbee0571ea..55a8469537 100644 --- a/fees/curve.ts +++ b/fees/curve.ts @@ -1,25 +1,26 @@ -import { Adapter, FetchResult } from "../adapters/types"; +import * as sdk from "@defillama/sdk"; +import { Adapter } from "../adapters/types"; import { ARBITRUM, ETHEREUM, OPTIMISM, POLYGON, AVAX, FANTOM, XDAI } from "../helpers/chains"; import { request, gql } from "graphql-request"; -import type { ChainEndpoints } from "../adapters/types" +import type { ChainEndpoints, FetchOptions, FetchResultV2 } from "../adapters/types" import { Chain } from '@defillama/sdk/build/general'; - +import fetchURL from "../utils/fetchURL"; const endpoints = { [ETHEREUM]: - "https://api.thegraph.com/subgraphs/name/convex-community/volume-mainnet", + sdk.graph.modifyEndpoint('7FpNAjYhdo41FSdEro5P55uviKw69yhfPgxiWzPkr9au'), [OPTIMISM]: - "https://api.thegraph.com/subgraphs/name/convex-community/volume-optimism", + sdk.graph.modifyEndpoint('7cXBpS75ThtbYwtCD8B277vUfWptmz6vbhk9BKgYrEvQ'), [ARBITRUM]: - "https://api.thegraph.com/subgraphs/name/convex-community/volume-arbitrum", + sdk.graph.modifyEndpoint('6okUrfq2HYokFytJd2JDhXW2kdyViy5gXWWpZkTnSL8w'), [POLYGON]: - "https://api.thegraph.com/subgraphs/name/convex-community/volume-matic", + sdk.graph.modifyEndpoint('EXzFgeWbfgcLgUFEa9rHcQtTy2EcdvJnosTVkPvKe7EU'), [AVAX]: - "https://api.thegraph.com/subgraphs/name/convex-community/volume-avalanche", + sdk.graph.modifyEndpoint('4m6FwSHYnkQRUBSKdhh5heGd1ojTAXwEiacUyFix2Ygx'), [FANTOM]: - "https://api.thegraph.com/subgraphs/name/convex-community/volume-fantom", + sdk.graph.modifyEndpoint('7ZnKrxY26bDHZPSqJ3MNkDNjaRXLoc1ZiATDLbVjWa7H'), [XDAI]: - "https://api.thegraph.com/subgraphs/name/convex-community/volume-xdai", + sdk.graph.modifyEndpoint('i82AxuGMFX7bqGNpXGrUvXqFMWZjLeRTNpJFvc3aW8L'), }; const graph = (graphUrls: ChainEndpoints) => { @@ -46,10 +47,7 @@ const graph = (graphUrls: ChainEndpoints) => { }`; return (chain: Chain) => { - return async (timestamp: number) => { - - const fromTimestamp = timestamp - 60 * 60 * 24 - const toTimestamp = timestamp + return async ({ fromTimestamp, toTimestamp }: FetchOptions) => { const graphRes = await request(graphUrls[chain], graphQuery, { timestampFrom: fromTimestamp, timestampTo: toTimestamp @@ -66,7 +64,7 @@ const graph = (graphUrls: ChainEndpoints) => { return parseFloat(vol.lpFeesUSD); }); - const res: FetchResult = { timestamp, dailyProtocolRevenue: "0", } + const res: FetchResultV2 = { dailyProtocolRevenue: "0", } if (feesPerPool.length > 0) { const dailyFee = feesPerPool.reduce((acc: number, curr: number) => acc + curr, 0.); res["dailyUserFees"] = dailyFee.toString() @@ -86,6 +84,34 @@ const graph = (graphUrls: ChainEndpoints) => { } }; +const fetch = (chain: string) => async (options: FetchOptions) => { + if(options.toTimestamp < Date.now()/1e3-36*3600){ + return graph(endpoints)(chain)(options) + } + const response = (await fetchURL(`https://prices.curve.fi/v1/chains/${chain}`)); + const fees = (response.data as any[]) + .filter(e => e.trading_fee_24h < 1_000_000).reduce((all, pool)=>{ + return all + pool.liquidity_fee_24h+pool.trading_fee_24h + }, 0) + const allFees:any = { + dailyFees: `${fees}`, + dailyRevenue: `${fees/2}`, + dailyHoldersRevenue: `${fees/2}`, + }; + if(chain === ETHEREUM){ + const bribes:any[] = (await fetchURL(`https://raw.githubusercontent.com/pierremarsotlyon1/chainhub-backend/main/data/stats.json`)).claimsLast7Days.claims + const yesterday = bribes.reduce((closest, item)=>{ + const timeDiff = (val:any) => Math.abs(val.timestamp - (Date.now()/1e3-24*3600)) + if(timeDiff(item) < timeDiff(closest)){ + return item + } + return closest + }) + allFees.dailyBribesRevenue = (bribes[bribes.length-1].value - yesterday.value).toString() + } + return allFees +}; + const methodology = { UserFees: "Users pay a trading fee from 0.04% to 0.4% on each swap (as of July 2022, the fee on all pools was 0.04%)", Fees: "Trading fees paid by users", @@ -95,58 +121,30 @@ const methodology = { SupplySideRevenue: "A 50% of all trading fees are distributed among liquidity providers" } +const starts = { + [ETHEREUM]: 1577854800, + [OPTIMISM]: 1620532800, + [ARBITRUM]: 1632110400, + [POLYGON]: 1620014400, + //[AVAX]: 1633492800, + [FANTOM]: 1620532800, + [XDAI]: 1620532800 +} as { + [chain:string]:number +} + const adapter: Adapter = { - adapter: { - [ETHEREUM]: { - fetch: graph(endpoints)(ETHEREUM), - start: 1577854800, - meta: { - methodology - } - }, - [OPTIMISM]: { - fetch: graph(endpoints)(OPTIMISM), - start: 1620532800, - meta: { - methodology - } - }, - [ARBITRUM]: { - fetch: graph(endpoints)(ARBITRUM), - start: 1632110400, + version: 2, + adapter: Object.keys(starts).reduce((all, chain)=>{ + all[chain] = { + fetch: fetch(chain), + start: starts[chain], meta: { methodology - } - }, - [POLYGON]: { - fetch: graph(endpoints)(POLYGON), - start: 1620014400, - meta: { - methodology - } - }, - [AVAX]: { - fetch: graph(endpoints)(AVAX), - start: 1633492800, - meta: { - methodology - } - }, - [FANTOM]: { - fetch: graph(endpoints)(FANTOM), - start: 1620532800, - meta: { - methodology - } - }, - [XDAI]: { - fetch: graph(endpoints)(XDAI), - start: 1620532800, - meta: { - methodology - } - }, - } + }, + } + return all + }, {} as any) } export default adapter; diff --git a/fees/d2finance/index.ts b/fees/d2finance/index.ts new file mode 100644 index 0000000000..b9061ecfe8 --- /dev/null +++ b/fees/d2finance/index.ts @@ -0,0 +1,117 @@ +import BigNumber from "bignumber.js"; +import { FetchV2 } from "../../adapters/types"; +import { ARBITRUM } from "../../helpers/chains"; +import { getPrices } from "../../utils/prices"; +import { gql, GraphQLClient } from "graphql-request"; +import { + getTimestampAtStartOfMonth, + getTimestampAtStartOfNextMonth, +} from "../../utils/date"; + +interface Token { + ticker: string; + geckoId: string; + decimals: number; +} + +interface DataItem { + blockTimestamp: number; + contract: string; + token: string; + amount: string; +} + +const tokens = [ + { + ticker: "ARB", + geckoId: "coingecko:arbitrum", + decimals: 18, + }, + { + ticker: "ETH", + geckoId: "coingecko:ethereum", + decimals: 18, + }, + { + ticker: "USDC", + geckoId: "coingecko:usd-coin", + decimals: 6, + }, +]; + +const fetchFeeData = async (timestamp: number) => { + const client = new GraphQLClient("https://d2.finance/subgraphs/name/d2"); + const req = gql` + query Query { + feesWithdrawns(where: { blockTimestamp_lte: ${timestamp} }) { + blockTimestamp + contract + token + amount + } + } + `; + const response = await client.request(req); + const feesWithdrawns: DataItem[] = response.feesWithdrawns; + return feesWithdrawns; +}; + +const fetchTokenPrices = async (timestamp: number) => { + const prices = await getPrices( + tokens.map((token: Token) => token.geckoId), + timestamp + ); + + return prices; +}; + +const fetch: FetchV2 = async ({ startTimestamp }) => { + const monthStartTimeStamp = getTimestampAtStartOfMonth(startTimestamp); + const monthEndTimestamp = getTimestampAtStartOfNextMonth(startTimestamp); + + const result = await fetchFeeData(startTimestamp); + const tokenPrices = await fetchTokenPrices(startTimestamp); + + let totalAmount = 0; + let monthlyAmount = 0; + for (let data of result) { + const token = tokens.find((token) => token.ticker === data.token); + if (token) { + const price = tokenPrices[token.geckoId].price; + const amountInDollar = Number( + BigNumber(data.amount) + .times(price) + .dividedBy(BigNumber(10).pow(token.decimals)) + ); + totalAmount += amountInDollar; + if ( + data.blockTimestamp >= monthStartTimeStamp && + data.blockTimestamp < monthEndTimestamp + ) { + monthlyAmount += amountInDollar; + } + } + } + + const monthFee = monthlyAmount / 30; + + return { + dailyFees: monthFee, + dailyRevenue: monthFee, + dailyProtocolRevenue: monthFee, + totalFees: totalAmount, + totalRevenue: totalAmount, + totalProtocolRevenue: totalAmount, + }; +}; + +export default { + version: 2, + adapter: { + [ARBITRUM]: { + fetch, + start: 1705715264, + runAtCurrTime: true, + }, + }, +}; diff --git a/fees/danogo/index.ts b/fees/danogo/index.ts index 2902b9a8bb..027bc98966 100644 --- a/fees/danogo/index.ts +++ b/fees/danogo/index.ts @@ -1,4 +1,4 @@ -import { SimpleAdapter } from "../../adapters/types"; +import { FetchOptions, SimpleAdapter } from "../../adapters/types"; import { getPrices } from "../../utils/prices"; import fetchURL from "../../utils/fetchURL"; import { DanogoDimensions, DanogoFees } from "./types"; @@ -35,13 +35,12 @@ const convertDataToUSD = (data: DanogoDimensions, price: number) => { return convertedData; } -const fetchData = async (timestamp: number) => { - const dataPromise = fetchDanogoGatewayData(timestamp); - const adaPricePromise = fetchADAprice(timestamp); +const fetchData = async ({ endTimestamp }: FetchOptions) => { + const dataPromise = fetchDanogoGatewayData(endTimestamp); + const adaPricePromise = fetchADAprice(endTimestamp); const [data, adaPrice] = await Promise.all([dataPromise, adaPricePromise]); return { - timestamp: timestamp, ...convertDataToUSD(data, adaPrice) }; } @@ -53,7 +52,8 @@ const adapter: SimpleAdapter = { start: DANOGO_START_TIMESTAMP, runAtCurrTime: false, } - } + }, + version: 2 }; export default adapter; diff --git a/fees/dedust/index.ts b/fees/dedust/index.ts new file mode 100644 index 0000000000..2c3f01b6bf --- /dev/null +++ b/fees/dedust/index.ts @@ -0,0 +1,97 @@ +import { FetchResultV2 } from '../../adapters/types'; +import { CHAIN } from '../../helpers/chains' +import { postURL } from "../../utils/fetchURL" + +const GRAPHQL_ENDPOINT = 'https://api.dedust.io/v3/graphql'; + +const POOLS_QUERY = ` +query GetPools($filter: PoolsFiltersInput) { + pools(filter: $filter) { + address + totalSupply + type + tradeFee + assets + reserves + fees + volume + } + } +`; + +const ASSETS_QUERY = ` +query GetAssets { + assets { + type + address + symbol + decimals + price + } + } +`; + +// LPs get 80% of fees +const FEES_PERCENT_TO_LP = 0.8; +const fetchFees = async (): Promise => { + const assetsList = (await postURL(GRAPHQL_ENDPOINT, { + query: ASSETS_QUERY, + operationName: 'GetAssets' + })).data.assets; + + const assetInfo = {}; + for (const asset of assetsList) { + const address = asset.type == 'native' ? 'native' : 'jetton:' + asset.address; + assetInfo[address] = { + decimals: asset.decimals, + price: Number(asset.price), + symbol: asset.symbol + } + } + + const poolsList = (await postURL(GRAPHQL_ENDPOINT, { + query: POOLS_QUERY, + operationName: 'GetPools' + })).data.pools; + + let dailyFees = 0; + for (const pool of poolsList) { + const address = pool.address; + const leftAddr = pool.assets[0]; + const rightAddr = pool.assets[1]; + if (!(leftAddr in assetInfo && rightAddr in assetInfo)) { + console.warn("No assets info for pool", pool); + continue; + } + const left = assetInfo[leftAddr]; + const right = assetInfo[rightAddr]; + + dailyFees += (left.price * Number(pool.fees[0]) / Math.pow(10, left.decimals) + + right.price * Number(pool.fees[1]) / Math.pow(10, right.decimals)) / 2; + } + + + return { + dailyUserFees: dailyFees, + dailyFees: dailyFees, + dailySupplySideRevenue: dailyFees * FEES_PERCENT_TO_LP, + dailyRevenue: dailyFees * (1 - FEES_PERCENT_TO_LP) + } +} + +export default { + version: 2, + adapter: { + [CHAIN.TON]: { + start: 1700000000, + meta: { + methodology: { + UserFees: "User pays fee on each swap (depends on pool, 0.1% - 1%).", + Revenue: "Protocol receives 20% of fees, it is distributed among SCALE stakers.", + SupplySideRevenue: "80% of user fees are distributed among LPs.", + }, + }, + fetch: fetchFees, + }, + }, +} diff --git a/fees/defi-saver.ts b/fees/defi-saver.ts index 769cdd96b2..054dfe9753 100644 --- a/fees/defi-saver.ts +++ b/fees/defi-saver.ts @@ -1,7 +1,7 @@ -import { FetchOptions, FetchResultFees, SimpleAdapter } from "../adapters/types"; +import { FetchOptions, SimpleAdapter } from "../adapters/types"; import { CHAIN } from "../helpers/chains"; import { queryIndexer } from "../helpers/indexer"; -const fetch = async (timestamp: number, _: any, options: FetchOptions): Promise => { +const fetch = async (options: FetchOptions) => { const dailyFees = options.createBalances(); const logsTranferERC20: any[] = await queryIndexer(` SELECT @@ -16,10 +16,11 @@ const fetch = async (timestamp: number, _: any, options: FetchOptions): Promise< AND block_time BETWEEN llama_replace_date_range; `, options); logsTranferERC20.map((p: any) => dailyFees.add(p.contract_address, p.value)) - return { dailyFees, dailyRevenue: dailyFees, timestamp } + return { dailyFees, dailyRevenue: dailyFees } } const adapter: SimpleAdapter = { + version: 2, adapter: { [CHAIN.ETHEREUM]: { fetch: fetch as any, diff --git a/fees/defi-swap.ts b/fees/defi-swap.ts index ff06efbcef..1db13a7cbc 100644 --- a/fees/defi-swap.ts +++ b/fees/defi-swap.ts @@ -10,6 +10,7 @@ const feeAdapter = getDexChainFees({ }); const adapter: Adapter = { + version: 2, adapter: feeAdapter }; diff --git a/fees/defiplaza/index.ts b/fees/defiplaza/index.ts index b97fbb355a..fd17515f24 100644 --- a/fees/defiplaza/index.ts +++ b/fees/defiplaza/index.ts @@ -1,7 +1,7 @@ +import * as sdk from "@defillama/sdk"; import request, { gql } from "graphql-request"; -import { FetchResultGeneric, SimpleAdapter } from "../../adapters/types"; +import { FetchOptions, SimpleAdapter } from "../../adapters/types"; import { CHAIN } from "../../helpers/chains"; -import { getChainVolume, getUniqStartOfTodayTimestamp } from "../../helpers/getUniSubgraphVolume"; import fetchURL from "../../utils/fetchURL"; type RadixPlazaResponse = { @@ -14,15 +14,14 @@ type RadixPlazaResponse = { swaps: number } -const thegraph_endpoints = "https://api.thegraph.com/subgraphs/name/omegasyndicate/defiplaza"; +const thegraph_endpoints = sdk.graph.modifyEndpoint('4z9FBF12CrfoQJhAkWicqzY2fKYN9QRmuzSsizVXhjKa'); const radix_endpoint = "https://radix.defiplaza.net/api/defillama/volume"; const adapter: SimpleAdapter = { + version: 2, adapter: { [CHAIN.ETHEREUM]: { - fetch: async (timestamp: number): Promise => { - const toTimestamp = getUniqStartOfTodayTimestamp(new Date(timestamp * 1000)) - const fromTimestamp = timestamp - 86400; + fetch: async ({ startTimestamp, endTimestamp }: FetchOptions) => { const graphData = (await request(thegraph_endpoints, gql` { factories(first: 1) { @@ -30,7 +29,7 @@ const adapter: SimpleAdapter = { totalTradeVolumeUSD totalFeesEarnedUSD } - dailies(first: 1, where:{date_lte: ${toTimestamp}, date_gte: ${fromTimestamp}}, orderBy: date, orderDirection:desc) { + dailies(first: 1, where:{date_lte: ${endTimestamp}, date_gte: ${startTimestamp}}, orderBy: date, orderDirection:desc) { date tradeVolumeUSD swapUSD @@ -49,7 +48,6 @@ const adapter: SimpleAdapter = { dailyUserFees, dailyFees, dailySupplySideRevenue, - timestamp } }, meta: { @@ -61,8 +59,8 @@ const adapter: SimpleAdapter = { start: 1633237008 }, [CHAIN.RADIXDLT]: { - fetch: async (timestamp: number): Promise => { - const daily: RadixPlazaResponse = (await fetchURL(radix_endpoint + `?timestamp=${timestamp}`)); + fetch: async ({ endTimestamp }: FetchOptions) => { + const daily: RadixPlazaResponse = (await fetchURL(radix_endpoint + `?timestamp=${endTimestamp}`)); const dailySupplySideRevenue = daily.feesUSD; const dailyProtocolRevenue = daily.royaltiesUSD; @@ -77,7 +75,6 @@ const adapter: SimpleAdapter = { dailyRevenue, dailyProtocolRevenue, dailySupplySideRevenue, - timestamp } }, meta: { diff --git a/fees/demented-games/abi.ts b/fees/demented-games/abi.ts new file mode 100644 index 0000000000..cdd290362c --- /dev/null +++ b/fees/demented-games/abi.ts @@ -0,0 +1,16 @@ +export const commonAbi = [ + { + constant: true, + inputs: [], + name: 'accumulatedFees', + outputs: [ + { + name: '', + type: 'uint256', + }, + ], + payable: false, + stateMutability: 'view', + type: 'function', + }, + ]; \ No newline at end of file diff --git a/fees/demented-games/index.ts b/fees/demented-games/index.ts new file mode 100644 index 0000000000..bc0726f152 --- /dev/null +++ b/fees/demented-games/index.ts @@ -0,0 +1,61 @@ +import { ETHER_ADDRESS } from '@defillama/sdk/build/general'; +import BigNumber from 'bignumber.js'; +import { Adapter, FetchOptions } from '../../adapters/types'; +import { CHAIN } from '../../helpers/chains'; +import { commonAbi } from './abi'; + +const ROULETTE_ADDRESS = '0x94ba26ee118ef6c407c75dbb23385b1ad71a4547'; +const PUMP_OR_REKT_ADDRESS = '0xcbc003cb76c5d218cba2dfb3a2b2f101950ed7e7'; + +async function fetch({ createBalances, api, fromApi, toApi }: FetchOptions) { + const totalFees = createBalances(); + const dailyFees = createBalances(); + const pumpOrRektFeesFrom = await fromApi.call({ + abi: commonAbi[0], + target: PUMP_OR_REKT_ADDRESS, + }); + const pumpOrRektFeesTo = await toApi.call({ + abi: commonAbi[0], + target: PUMP_OR_REKT_ADDRESS, + }); + + const roulletteFeesFrom = await fromApi.call({ + abi: commonAbi[0], + target: ROULETTE_ADDRESS, + }); + + const roulletteFeesTo = await toApi.call({ + abi: commonAbi[0], + target: ROULETTE_ADDRESS, + }); + + const dailypumpOrRektFees = Number(pumpOrRektFeesTo) - Number(pumpOrRektFeesFrom); + const dailyroulletteFees = Number(roulletteFeesTo) - Number(roulletteFeesFrom); + const tottal = Number(pumpOrRektFeesTo) + Number(roulletteFeesTo); + const dailyTotal = dailypumpOrRektFees + dailyroulletteFees; + totalFees.add(ETHER_ADDRESS, tottal); + dailyFees.add(ETHER_ADDRESS, dailyTotal); + + return { + totalFees, + dailyFees, + }; +} + +const adapter: Adapter = { + version: 2, + adapter: { + [CHAIN.FUSE]: { + fetch, + runAtCurrTime: true, + start: 1720396800, + meta: { + methodology: { + Fees: 'Sum of all fees from each game on the Demented Games platform.', + }, + }, + }, + }, +}; + +export default adapter; diff --git a/fees/dexscreener.ts b/fees/dexscreener.ts new file mode 100644 index 0000000000..1bd67e033d --- /dev/null +++ b/fees/dexscreener.ts @@ -0,0 +1,54 @@ +import { Adapter, FetchOptions } from "../adapters/types"; +import { CHAIN } from "../helpers/chains"; +import coreAssets from "../helpers/coreAssets.json"; +import { queryDune } from "../helpers/dune"; +import { addTokensReceived } from '../helpers/token'; + +const USDC = { + ethereum: coreAssets.ethereum.USDC, + polygon: coreAssets.polygon.USDC_CIRCLE, + base: coreAssets.base.USDC, +} as any + +const eth = async (options: FetchOptions) => { + const dailyFees = await addTokensReceived({ options, tokens: [USDC[options.chain]], target: '0xbf07aFF5114BAd83720A8b9Fc7585aFd2ef9E4C2' }) + return { + dailyFees, + dailyRevenue: dailyFees, + } +} + +// TODO: check whether 5qR17nnyyBjoHPiGiAD4ZHFCSJixebJCYymArGgZiDnh was an older address where they received payments +const sol = async (options: FetchOptions) => { + const dailyFees = options.createBalances(); + const value = (await queryDune("3986808", { + start: options.startTimestamp, + end: options.endTimestamp, + receiver: '23vEM5NAmK68uBHFM52nfNtZn7CgpHDSmAGWebsjg5ft', + token_mint_address: 'EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v' + })); + dailyFees.add('EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v', value[0].received*1e6); + return { + dailyFees, + dailyRevenue: dailyFees, + } +} + +const adapter: Adapter = { + version: 2, + adapter: [CHAIN.ETHEREUM, CHAIN.BASE, CHAIN.POLYGON].reduce((all, chain) => ({ + ...all, + [chain]: { + fetch: eth, + start: 0, + } + }), { + [CHAIN.SOLANA]: { + fetch: sol, + start: 0 + } + }), + isExpensiveAdapter: true +} + +export default adapter; \ No newline at end of file diff --git a/fees/dexter/index.ts b/fees/dexter/index.ts index 81438e6367..3c8a4b9050 100644 --- a/fees/dexter/index.ts +++ b/fees/dexter/index.ts @@ -37,7 +37,8 @@ const adapter: Adapter = { runAtCurrTime: true, start: 0, }, - } + }, + version: 1 }; export default adapter; diff --git a/fees/dextools.ts b/fees/dextools.ts new file mode 100644 index 0000000000..c380f7d8b1 --- /dev/null +++ b/fees/dextools.ts @@ -0,0 +1,82 @@ +/* +Payment Transaction Link (etherscan,bscscan...) +* +Fast Track Update Fee (for tokens deployed on all chains): + +The fee for a fast track update can be paid using either 1500 $DEXT, 0.4 $ETH, or 2 $BNB. +Please make the payment exclusively to this address: 0x997Cc123cF292F46E55E6E63e806CD77714DB70f +Submit the form immediately after payment to avoid losing its validity. +Fast Track Update Fee ONLY for tokens deployed on Solana: + +The discounted fee for a fast track update can be paid using 5 $SOL. +Please make the payment exclusively to this address: GZ7GGigCJF5AUDky2kts5GAsHwdfkzuFXochCQy3cxfW + +Ensure all information in the form is accurate before submitting, we do not issue refunds. Do NOT send from an exchange. For a smoother update, it is advised to send funds from the token's deployer. + +Correct: https://etherscan.io/tx/0x123.... +Not correct: 0x123.... + +🔥 🔥 🔥 Get 50% discount on your update for tokens deployed on BASE Blockchain for a limited time: +The fee for a fast track update on BASE can be paid using either 750 $DEXT, 0.2 $ETH, or 1 $BNB. +Please make the payment exclusively to this address: 0x997Cc123cF292F46E55E6E63e806CD77714DB70f +Submit the form immediately after payment to avoid losing its validity. + +🔥 🔥 🔥 Get 70% discount on your update for tokens deployed on TON and TRON Blockchain for a limited time: +The fee for a fast track update on TON can be paid using 60 $TON, 0.12 $ETH, 450 $DEXT, or 0.6 $BNB. +Please make the payment exclusively to this address (ERC20 payments to the ERC20 address above): +UQC2-PvRTlqkHfeUdDx80rVRnaW7WoNWlpq4LBx7oWVhKisC + +Submit the form immediately after payment to avoid losing its validity. +The discount is valid only if applied at payment and while it is displayed in the form; no refunds for overpayments or unused discounts! + +For Tokens created with https://creator.dextools.io, enter "//TOKENCREATOR//" as the payment code. Entering the token creator's payment code without creating the token through the creator will mark your update request as spam. +*/ + +import { Adapter, FetchOptions } from "../adapters/types"; +import { CHAIN } from "../helpers/chains"; +import { queryDune } from "../helpers/dune"; +import { evmReceivedGasAndTokens } from '../helpers/token'; + +const tokens = { + ethereum: [ + "0xfb7b4564402e5500db5bb6d63ae671302777c75a", // DEXT + ], + bsc: [ + "0xe91a8d2c584ca93c7405f15c22cdfe53c29896e3", // DEXT + ], + base: [] +} as any + +const sol = async (options: FetchOptions) => { + const dailyFees = options.createBalances(); + const value = (await queryDune("3521814", { + start: options.startTimestamp, + end: options.endTimestamp, + receiver: 'GZ7GGigCJF5AUDky2kts5GAsHwdfkzuFXochCQy3cxfW' + })); + dailyFees.add('So11111111111111111111111111111111111111112', value[0].fee_token_amount); + return { + dailyFees, + dailyRevenue: dailyFees, + } +} + +const adapter: Adapter = { + version: 2, + isExpensiveAdapter: true, + adapter: [CHAIN.ETHEREUM, CHAIN.BASE, CHAIN.BSC].reduce((all, chain) => ({ + ...all, + [chain]: { + fetch: evmReceivedGasAndTokens('0x997Cc123cF292F46E55E6E63e806CD77714DB70f', tokens[chain]), + start: 0, + } + }), { + [CHAIN.SOLANA]: { + fetch: sol, + start: 0 + } + }) + // missing tron and ton +} + +export default adapter; \ No newline at end of file diff --git a/fees/dhedge/index.ts b/fees/dhedge/index.ts new file mode 100644 index 0000000000..072e560d74 --- /dev/null +++ b/fees/dhedge/index.ts @@ -0,0 +1,105 @@ +import { FetchOptions, SimpleAdapter } from "../../adapters/types"; +import { CHAIN } from "../../helpers/chains"; +import { GraphQLClient } from "graphql-request"; +const query = ` + query managerFeeMinteds($startTimestamp: BigInt!, $endTimestamp: BigInt!, $first: Int!, $skip: Int!) { + managerFeeMinteds( + where: { daoFee_not: 0, blockTimestamp_gte: $startTimestamp, blockTimestamp_lte: $endTimestamp }, + first: $first, skip: $skip, orderBy: blockTimestamp, orderDirection: desc + ) { daoFee, tokenPriceAtLastFeeMint } + }` + + +// if graph goes down, can be pulled via event logs, example: +// https://optimistic.etherscan.io/tx/0x265e1eeb9a2c68ef8f58fe5e1d7e3f1151dd5e6686d4147445bf1bd8895deb38#eventlog check topic: 0x755a8059d66d8d243bc9f6913f429a811f154599d0538bb0b6a2ac23f23d2ccd +/* const fetch = async ({ chain, createBalances, getLogs }: FetchOptions) => { + const dailyFees = createBalances(); + const logs = await getLogs({ + eventAbi: 'event ManagerFeeMinted (address pool, address manager, uint256 available, uint256 daoFee, uint256 managerFee, uint256 tokenPriceAtLastFeeMint)', + }); + logs.forEach(i => { + dailyFees.addUSDValue(i.daoFee.toString() * i.tokenPriceAtLastFeeMint.toString() / 1e36) + }); + + return { dailyFees, dailyRevenue: dailyFees }; +} */ +const PROVIDER_CONFIG = { + [CHAIN.OPTIMISM]: { + endpoint: "https://api.studio.thegraph.com/query/48129/dhedge-v2-optimism/version/latest", + }, + [CHAIN.POLYGON]: { + endpoint: "https://api.studio.thegraph.com/query/48129/dhedge-v2-polygon/version/latest", + }, + [CHAIN.ARBITRUM]: { + endpoint: "https://api.studio.thegraph.com/query/48129/dhedge-v2-arbitrum/version/latest", + }, + [CHAIN.BASE]: { + startTimestamp: 1712227101, + endpoint: "https://api.studio.thegraph.com/query/48129/dhedge-v2-base-mainnet/version/latest", + }, +}; + +const fetchHistoricalFees = async (chainId: CHAIN, query: string, volumeField: string, startTimestamp: number, endTimestamp: number) => { + const { endpoint } = PROVIDER_CONFIG[chainId]; + + let allData = []; + let skip = 0; + const batchSize = 1000; + + while (true) { + try { + const data = await new GraphQLClient(endpoint).request(query, { + startTimestamp: startTimestamp.toString(), + endTimestamp: endTimestamp.toString(), + first: batchSize, + skip + }); + + const entries = data[volumeField]; + 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 calculateFees = (data: any): number => + data.reduce((acc: number, item: any) => { + const daoFee = Number(item.daoFee); + const tokenPrice = Number(item.tokenPriceAtLastFeeMint); + const daoFeeInEth = daoFee / 1e18; + const tokenPriceInEth = tokenPrice / 1e18; + const result = daoFeeInEth * tokenPriceInEth; + return acc + result; + }, 0); + +const fetch = async ({ chain, endTimestamp, startTimestamp }: FetchOptions) => { + const config = PROVIDER_CONFIG[chain]; + if (!config) throw new Error(`Unsupported chain: ${chain}`); + + const dailyFees = await fetchHistoricalFees(chain as CHAIN, query, 'managerFeeMinteds', startTimestamp, endTimestamp) + + return { + dailyFees: calculateFees(dailyFees), + dailyRevenue: calculateFees(dailyFees), + timestamp: endTimestamp, + }; +} + +const adapter: SimpleAdapter = { + adapter: { + [CHAIN.OPTIMISM]: { fetch, start: 1638446653, }, + [CHAIN.POLYGON]: { fetch, start: 1627560253, }, + [CHAIN.ARBITRUM]: { fetch, start: 1679918653, }, + [CHAIN.BASE]: { fetch, start: 1703073853, }, + }, + version: 2 +} + +export default adapter; diff --git a/fees/dln/index.ts b/fees/dln/index.ts index 636d573b14..055b438b93 100644 --- a/fees/dln/index.ts +++ b/fees/dln/index.ts @@ -38,6 +38,7 @@ function formatTimestampAsDate(timestamp: number) { } const adapter: Adapter = { + version: 1, adapter: { [CHAIN.ETHEREUM]: { fetch: fetch(1), diff --git a/fees/dodo.ts b/fees/dodo-fees.ts similarity index 75% rename from fees/dodo.ts rename to fees/dodo-fees.ts index 8a6e6e2d81..3943a283fc 100644 --- a/fees/dodo.ts +++ b/fees/dodo-fees.ts @@ -1,4 +1,4 @@ -import { Adapter } from "../adapters/types"; +import { Adapter, BreakdownAdapter } from "../adapters/types"; import { request, gql } from "graphql-request"; const feesReq = gql` @@ -21,7 +21,9 @@ const adapter: Adapter = { "Content-Type": "application/json", "user-agent": "insomnia/2022.5.0" }) - const fees = Object.values(pairs.dashboard_pairs_rate_24.pairs).reduce((sum:number, p:any)=>sum+Number(p.fee), 0); + const fees = Object.values(pairs.dashboard_pairs_rate_24.pairs) + .filter((p:any)=> Number(p.tvl) > 1000) + .reduce((sum:number, p:any)=>sum+Number(p.fee), 0); return { timestamp: Date.now()/1e3, dailyFees: fees, @@ -34,5 +36,12 @@ const adapter: Adapter = { }), {} as any) }; +const breakdownAdapter: BreakdownAdapter = { + version: 1, + breakdown: { + "dodo": adapter.adapter + } +} + -export default adapter; +export default breakdownAdapter; diff --git a/fees/doge.ts b/fees/doge.ts index 3fba6ebf71..158375d8fe 100644 --- a/fees/doge.ts +++ b/fees/doge.ts @@ -5,6 +5,7 @@ import { chainAdapter } from "../helpers/getChainFees"; const feeAdapter = chainAdapter(DOGE, "doge", 1386478800); const adapter: Adapter = { + version: 1, adapter: feeAdapter, protocolType: ProtocolType.CHAIN } diff --git a/fees/dragonswap-sei.ts b/fees/dragonswap-sei.ts new file mode 100644 index 0000000000..ea995739d4 --- /dev/null +++ b/fees/dragonswap-sei.ts @@ -0,0 +1,57 @@ +import { Adapter } from "../adapters/types"; +import { CHAIN } from "../helpers/chains"; +import { request, gql } from "graphql-request"; +import type { ChainEndpoints, FetchOptions, FetchV2 } from "../adapters/types" +import { getTimestampAtStartOfDayUTC } from "../utils/date"; +import { time } from "console"; + +const endpoints = { + [CHAIN.SEI]: "https://api.goldsky.com/api/public/project_clu1fg6ajhsho01x7ajld3f5a/subgraphs/dragonswap-prod/1.0.0/gn" +} + +const methodology = { + Fees: "DragonSwap protocol swap fee (0.3% per swap).", + LPProvidersRevenue: "Fees distributed to the LP providers (70% of total accumulated fees).", + ProtocolAccumulation: "Fees sent to the protocol wallet (30% of total accumulated fees), is used to provide benefits to users in custom ways." +} + +const graphs = async (_t: any, _b: any, options: FetchOptions) => { + + + const dayID = Math.floor(options.startOfDay / 86400); + const query =gql` + { + uniswapDayData(id:${dayID}) { + id + dailyVolumeUSD + dailyFeesUSD + } + + }`; + const url = "https://api.goldsky.com/api/public/project_clu1fg6ajhsho01x7ajld3f5a/subgraphs/dragonswap-prod/1.0.0/gn"; + const req = await request(url, query); + const dailyFee = Number(req.uniswapDayData.dailyFeesUSD); + return { + timestamp: options.startOfDay, + dailyFees: dailyFee.toString(), + // dailyLPProvidersRevenue: (dailyFee * 0.7).toString(), + dailyRevenue: (dailyFee * 0.3).toString(), + }; + +}; + + +const adapter: Adapter = { + version: 1, + adapter: { + [CHAIN.SEI]: { + fetch: graphs, + start: 79157663, + meta: { + methodology + } + } + } +} + +export default adapter; diff --git a/fees/dragonswap/index.ts b/fees/dragonswap/index.ts index 5860ea9e3f..e1ecef611e 100644 --- a/fees/dragonswap/index.ts +++ b/fees/dragonswap/index.ts @@ -1,7 +1,7 @@ import { Chain } from "@defillama/sdk/build/types"; import { BaseAdapter, BreakdownAdapter, IJSON } from "../../adapters/types"; import { CHAIN } from "../../helpers/chains"; -import { getGraphDimensions } from "../../helpers/getUniSubgraph"; +import { getGraphDimensions2 } from "../../helpers/getUniSubgraph"; const endpoints = { [CHAIN.KLAYTN]: "https://graph.dgswap.io/subgraphs/name/dragonswap/exchange-v2", @@ -11,8 +11,6 @@ const v3Endpoint = { [CHAIN.KLAYTN]: "https://graph.dgswap.io/subgraphs/name/dragonswap/exchange-v3", }; -const VOLUME_USD = "volumeUSD"; - const startTimes = { [CHAIN.KLAYTN]: 1707297572, } as IJSON; @@ -30,7 +28,7 @@ const methodology = { Fees: "All fees comes from the user." } -const graphs = getGraphDimensions({ +const graphs = getGraphDimensions2({ graphUrls: endpoints, graphRequestHeaders: { [CHAIN.KLAYTN]: { @@ -40,9 +38,6 @@ const graphs = getGraphDimensions({ totalVolume: { factory: "pancakeFactories" }, - dailyVolume: { - factory: "pancakeDayData" - }, feesPercent: { type: "volume", Fees: 0.3, @@ -54,25 +49,18 @@ const graphs = getGraphDimensions({ } }); -const v3Graph = getGraphDimensions({ +const v3Graph = getGraphDimensions2({ graphUrls: v3Endpoint, totalVolume: { factory: "factories", }, - dailyVolume: { - factory: "pancakeDayData", - field: VOLUME_USD - }, totalFees: { factory: "factories", }, - dailyFees: { - factory: "pancakeDayData", - field: "feesUSD" - }, }); const adapter: BreakdownAdapter = { + version: 2, breakdown: { v2: Object.keys(endpoints).reduce((acc, chain) => { acc[chain] = { @@ -86,14 +74,7 @@ const adapter: BreakdownAdapter = { }, {} as BaseAdapter), v3: Object.keys(v3Endpoint).reduce((acc, chain) => { acc[chain] = { - fetch: async (timestamp: number) => { - const v3stats = await v3Graph(chain)(timestamp, {}) - return { - ...v3stats, - timestamp - } - - }, + fetch: v3Graph(chain), start: v3StartTimes[chain], } return acc diff --git a/fees/dydx-v4/index.ts b/fees/dydx-v4/index.ts new file mode 100644 index 0000000000..5d45c53286 --- /dev/null +++ b/fees/dydx-v4/index.ts @@ -0,0 +1,33 @@ +import { ChainBlocks, FetchOptions, SimpleAdapter } from '../../adapters/types' +import { httpGet } from '../../utils/fetchURL' + +interface IFees { + day: string + sum_tradingfeecollection: string +} +const fetchFees = async (timestamp: number, _t: ChainBlocks ,options: FetchOptions) => { + const url = 'https://api.lacertalabs.xyz/data/tradingfeecollection' + const dateStr = new Date(options.startOfDay * 1000).toISOString().split('T')[0] + const res = await httpGet(url) + delete res['latestTen'] + const item: IFees[] = Object.values(res) + const dailyFees = item.find((i) => i.day.split('T')[0] === dateStr)?.sum_tradingfeecollection + const dailyFeesNum = dailyFees ? parseFloat(dailyFees) : undefined + return { + dailyFees: dailyFeesNum, + dailyRevenue: dailyFeesNum, + dailyHoldersRevenue: dailyFeesNum, + timestamp: timestamp, + } +} + +const adapter: SimpleAdapter = { + adapter: { + "dydx": { + fetch: fetchFees, + start: 1699747200, + } + } +} + +export default adapter diff --git a/fees/dydx.ts b/fees/dydx.ts index eb659f050a..9e1b3bec1d 100644 --- a/fees/dydx.ts +++ b/fees/dydx.ts @@ -22,6 +22,7 @@ const fetch = async (timestamp: number): Promise => { }; const adapter: SimpleAdapter = { + version: 1, adapter: { [CHAIN.ETHEREUM]: { fetch, diff --git a/fees/e3.ts b/fees/e3.ts index 9e0df3bfe9..b8165f0f90 100644 --- a/fees/e3.ts +++ b/fees/e3.ts @@ -15,7 +15,7 @@ const ABIs: TABI = { } const graph = (_chain: Chain) => { - return async (timestamp: number, _: ChainBlocks, { createBalances, api, getLogs, }: FetchOptions) => { + return async ({ createBalances, api, getLogs, }: FetchOptions) => { const lpTokens = await api.fetchList({ lengthAbi: ABIs.getNumberOfLBPairs, itemAbi: ABIs.getLBPairAtIndex, target: FACTORY_ADDRESS }) const dailyFees = createBalances(); @@ -65,7 +65,6 @@ const graph = (_chain: Chain) => { dailyProtocolRevenue: dailyRevenue, dailyHoldersRevenue: dailyRevenue, dailySupplySideRevenue, - timestamp, }; } } @@ -80,6 +79,7 @@ const methodology = { } const adapter: SimpleAdapter = { + version: 2, adapter: { [CHAIN.FANTOM]: { fetch: graph(CHAIN.FANTOM), diff --git a/fees/echelon.ts b/fees/echelon.ts new file mode 100644 index 0000000000..af3f4abcd9 --- /dev/null +++ b/fees/echelon.ts @@ -0,0 +1,47 @@ +import fetchURL from "../utils/fetchURL"; +import { SimpleAdapter } from "../adapters/types"; +import { CHAIN } from "../helpers/chains"; + +const thalaDappURL = "https://app.echelon.market"; +const feesQueryURL = `${thalaDappURL}/api/defillama/fees?timeframe=`; + +interface IVolumeall { + value: number; + timestamp: string; +} + +const feesEndpoint = (endTimestamp: number, timeframe: string) => + endTimestamp + ? feesQueryURL + timeframe + `&endTimestamp=${endTimestamp}` + : feesQueryURL + timeframe; + +const fetch = async (timestamp: number) => { + const dayFeesQuery = (await fetchURL(feesEndpoint(timestamp, "1D")))?.data; + const dailyFees = dayFeesQuery.reduce( + (partialSum: number, a: IVolumeall) => partialSum + a.value, + 0 + ); + + const totalFeesQuery = (await fetchURL(feesEndpoint(0, "ALL")))?.data; + const totalFees = totalFeesQuery.reduce( + (partialSum: number, a: IVolumeall) => partialSum + a.value, + 0 + ); + + return { + totalFees: `${totalFees}`, + dailyFees: `${dailyFees}`, + timestamp, + }; +}; + +const adapter: SimpleAdapter = { + adapter: { + [CHAIN.APTOS]: { + fetch, + start: async () => 1680480000, + }, + }, +}; + +export default adapter; diff --git a/fees/edebase.ts b/fees/edebase.ts index abc142dadb..d816af943f 100644 --- a/fees/edebase.ts +++ b/fees/edebase.ts @@ -47,6 +47,7 @@ const graphs = (graphUrls: ChainEndpoints) => { }; const adapter: Adapter = { + version: 1, adapter: { [CHAIN.BASE]: { fetch: graphs(endpoints)(CHAIN.BASE), diff --git a/fees/eesee.ts b/fees/eesee.ts new file mode 100644 index 0000000000..2de0fd2435 --- /dev/null +++ b/fees/eesee.ts @@ -0,0 +1,30 @@ +import { Adapter, FetchV2, } from "../adapters/types"; +import { CHAIN } from "../helpers/chains"; + +const abi_event = { + TokenPaymasterOperation: "event TokenPaymasterOperation (address indexed sender, address indexed token, uint256 indexed totalCharge, address oracleAggregator, uint32 priceMarkup, bytes32 userOpHash, uint256 exchangeRate, uint8 priceSource)", +}; + +const paymaster = '0x00000f7365ca6c59a2c93719ad53d567ed49c14c'; + +const adapter: Adapter = { + adapter: { + [CHAIN.BLAST]: { + fetch: (async (options) => { + const dailyFees = options.createBalances(); + const logs = await options.getLogs({ target: paymaster, eventAbi: abi_event.TokenPaymasterOperation, }) + logs.map((tx: any) => { + dailyFees.add(tx.token, tx.totalCharge) + }) + return { dailyFees, } + }) as FetchV2, + start: 0, + meta: { + methodology: {} + } + }, + }, + version: 2, +} + +export default adapter; \ No newline at end of file diff --git a/fees/ekubo.ts b/fees/ekubo.ts index 1ef36fcf86..188a05a296 100644 --- a/fees/ekubo.ts +++ b/fees/ekubo.ts @@ -13,17 +13,17 @@ function getDimension(responseRaw: any[], key: string, balances: any) { return balances } -const fetch = async (timestamp: number, _: ChainBlocks, { createBalances }: FetchOptions) => { +const fetch = async ({ createBalances }: FetchOptions) => { const dailyFees = getDimension((await fetchURL("https://mainnet-api.ekubo.org/overview")).volumeByToken_24h, "fees", createBalances()) const dailyRevenue = getDimension((await fetchURL("https://mainnet-api.ekubo.org/overview")).revenueByToken_24h, "revenue", createBalances()) return { dailyFees, dailyRevenue, - timestamp, } } const adapter: Adapter = { + version: 2, adapter: { [CHAIN.STARKNET]: { fetch: fetch, diff --git a/fees/el-dorado-exchange.ts b/fees/el-dorado-exchange.ts index b5b0765a88..460416e99f 100644 --- a/fees/el-dorado-exchange.ts +++ b/fees/el-dorado-exchange.ts @@ -1,13 +1,15 @@ +import * as sdk from "@defillama/sdk"; import { Chain } from "@defillama/sdk/build/general"; import { gql, request } from "graphql-request"; import type { ChainEndpoints } from "../adapters/types"; -import { Adapter } from "../adapters/types"; -import { BSC, ARBITRUM } from "../helpers/chains"; +import { Adapter, DISABLED_ADAPTER_KEY } from "../adapters/types"; +import { ARBITRUM } from "../helpers/chains"; import { getTimestampAtStartOfDayUTC } from "../utils/date"; +import disabledAdapter from "../helpers/disabledAdapter"; const endpoints = { - // [BSC]: "https://api.thegraph.com/subgraphs/name/metaverseblock/ede_stats_elpall_test", - [ARBITRUM]: "https://api.thegraph.com/subgraphs/name/metaverseblock/ede_state_elp1_arbitrimone", + // [BSC]: sdk.graph.modifyEndpoint('FiegiatdkorjPCvK72UyHvmJHvWtS3oQS6zwnR94Xe7c'), + [ARBITRUM]: sdk.graph.modifyEndpoint('G3wquxtaw68uX5GAZ7XBPWK8Fa7Buf66Y27uT8erqQZ4'), }; const graphs = (graphUrls: ChainEndpoints) => { @@ -48,7 +50,9 @@ const graphs = (graphUrls: ChainEndpoints) => { }; const adapter: Adapter = { + version: 1, adapter: { + [DISABLED_ADAPTER_KEY]: disabledAdapter, // [BSC]: { // fetch: graphs(endpoints)(BSC), // start: 1670659200, @@ -61,7 +65,7 @@ const adapter: Adapter = { // } // }, [ARBITRUM]: { - fetch: graphs(endpoints)(ARBITRUM), + fetch: async (timestamp: number) => {return {timestamp}}, start: 1678147200, meta: { methodology: { diff --git a/fees/elk.ts b/fees/elk.ts index 2e39e107ee..59c9eed33a 100644 --- a/fees/elk.ts +++ b/fees/elk.ts @@ -1,29 +1,27 @@ +import * as sdk from "@defillama/sdk"; import { CHAIN } from "../helpers/chains"; -import { univ2DimensionAdapter } from "../helpers/getUniSubgraph"; +import { univ2DimensionAdapter2 } from "../helpers/getUniSubgraph"; -const adapter = univ2DimensionAdapter({ +const adapter = univ2DimensionAdapter2({ graphUrls: { - [CHAIN.ARBITRUM]: "https://api.thegraph.com/subgraphs/name/elkfinance/elkdex-arbitrum", - [CHAIN.AVAX]: "https://api.thegraph.com/subgraphs/name/elkfinance/elkdex-avax", - [CHAIN.BSC]: "https://api.thegraph.com/subgraphs/name/elkfinance/elkdex-bsc", - [CHAIN.FANTOM]: "https://api.thegraph.com/subgraphs/name/elkfinance/elkdex-ftm", - [CHAIN.POLYGON]: "https://api.thegraph.com/subgraphs/name/elkfinance/elkdex-matic", + [CHAIN.ARBITRUM]: sdk.graph.modifyEndpoint('B8TGNwQ8xMoeFCdsv9dPkciRBpEYAy1UxmXDr7nc9fpE'), + [CHAIN.AVAX]: sdk.graph.modifyEndpoint('2dyce92CewvhV17C8BMFoMCgaXdPTtwBzaz8AReQR3YV'), + [CHAIN.BSC]: sdk.graph.modifyEndpoint('5tRz9anigEVND48Gx1mUpNNM4YSm3NpzG9XRB8dYAMhb'), + [CHAIN.FANTOM]: sdk.graph.modifyEndpoint('pmqe2dQvH4PK7aaFh4GXrr49wpKRr3GjPCnNEgEb6U2'), + [CHAIN.POLYGON]: sdk.graph.modifyEndpoint('8jzpT6nnKgmqcdGocys97YWkuqwDbHBxpozsKcxH1KUP'), // [CHAIN.HECO]: "https://api.thegraph.com/subgraphs/name/elkfinance/elkdex-heco" - [CHAIN.XDAI]: "https://api.thegraph.com/subgraphs/name/elkfinance/elkdex-xdai", + [CHAIN.XDAI]: sdk.graph.modifyEndpoint('kD9njskfB9xv7gDnsU2sz4X4sXfEimBv8xMJ6votFND'), // [CHAIN.MOONRIVER]: "https://moonriver-graph.elk.finance/subgraphs/name/elkfinance/elkdex-moonriver", // [CHAIN.ELASTOS]: "https://elastos-graph.elk.finance/subgraphs/name/elkfinance/elkdex-elastos", // [CHAIN.OKEXCHAIN]: "https://okex-graph.elk.finance/subgraphs/name/elkfinance/elkdex-okex", // [CHAIN.KCC]: "https://kcc-graph.elk.finance/subgraphs/name/elkfinance/elkdex-kcc", - [CHAIN.ETHEREUM]: "https://api.thegraph.com/subgraphs/name/elkfinance/elkdex-eth", - [CHAIN.OPTIMISM]: "https://api.thegraph.com/subgraphs/name/elkfinance/elkdex-optimism", + [CHAIN.ETHEREUM]: sdk.graph.modifyEndpoint('59tcH5BPyXj41XZgn1ZYy4pE8iDdzaZpR9MRhmuPW4Lr'), + [CHAIN.OPTIMISM]: sdk.graph.modifyEndpoint('H7UcKWuAqQPqWKcnNLn2Jamy9zE7wVgsLSRQpPwXo2Ag'), // [CHAIN.CRONOS]: "https://cronos-graph.elk.finance/subgraphs/name/elkfinance/elkdex-cronos", // [CHAIN.FUSE]: "https://fuse-graph.elk.finance/subgraphs/name/elkfinance/elkdex-fuse", // [CHAIN.IOTEX]: "https://iotex-graph.elk.finance/subgraphs/name/elkfinance/elkdex-iotex", // [CHAIN.TELOS]: "https://telos-graph2.elk.finance/subgraphs/name/elkfinance/elkdex-telos" }, - dailyVolume: { - factory: "elkDayData" - }, totalVolume: { factory: "elkFactories" }, @@ -62,4 +60,5 @@ adapter.adapter.optimism.start = 1651542817; // adapter.adapter.iotex.start = 1639792417; // adapter.adapter.telos.start = 1648684800; + export default adapter; diff --git a/fees/emdx.ts b/fees/emdx.ts index 18aaddf461..410d681fa5 100644 --- a/fees/emdx.ts +++ b/fees/emdx.ts @@ -1,41 +1,24 @@ -import { Adapter, FetchResultFees } from "../adapters/types"; +import { Adapter, FetchOptions, } from "../adapters/types"; import { CHAIN } from "../helpers/chains"; -import { getTimestampAtStartOfDayUTC, getTimestampAtStartOfNextDayUTC } from "../utils/date"; -import * as sdk from "@defillama/sdk"; -import { getBlock } from "../helpers/getBlock"; const address = '0xbfb083840b0507670b92456264164e5fecd0430b'; -const topic0 = '0x4c7b764f428c13bbea8cc8da90ebe6eef4dafeb27a4e3d9041d64208c47ca7c2'; -interface ITx { - data: string; - transactionHash: string; -} - -const fetch = async (timestamp: number): Promise => { - const todaysTimestamp = getTimestampAtStartOfDayUTC(timestamp) - const yesterdaysTimestamp = getTimestampAtStartOfNextDayUTC(timestamp) +const fetch = async ({ createBalances, getLogs, }: FetchOptions) => { + const dailyFees = await createBalances(); - const fromBlock = (await getBlock(todaysTimestamp, CHAIN.AVAX, {})); - const toBlock = (await getBlock(yesterdaysTimestamp, CHAIN.AVAX, {})); - const logs: ITx[] = (await sdk.getEventLogs({ + const logs = (await getLogs({ target: address, - fromBlock: fromBlock, - toBlock: toBlock, - topics: [topic0], - chain: CHAIN.AVAX - })).map((e: any) => { return { data: e.data.replace('0x', ''), transactionHash: e.transactionHash } as ITx}); - const dailyFees = logs.map((tx: ITx) => { - const amount = Number('0x' + tx.data.slice(192, 256)) / 10 ** 18; - return amount; - }).reduce((a: number, b: number) => a+b,0); - return { - timestamp: timestamp, - dailyFees: `${dailyFees}`, - }; + eventAbi: 'event PositionChanged (address indexed trader, address indexed amm, uint256 margin, uint256 positionNotional, int256 exchangedPositionSize, uint256 fee, int256 positionSizeAfter, int256 realizedPnl, int256 unrealizedPnlAfter, uint256 badDebt, uint256 liquidationPenalty, uint256 spotPrice, int256 fundingPayment)' + })) + logs.forEach((tx: any) => { + const fee = Number(tx.fee) / 10 ** 18; + dailyFees.addUSDValue(fee); + }) + return { dailyFees, }; } const adapter: Adapter = { + version: 2, adapter: { [CHAIN.AVAX]: { fetch: fetch, diff --git a/fees/ens.ts b/fees/ens.ts index f73ea1c5ec..c9e5a7c1ff 100644 --- a/fees/ens.ts +++ b/fees/ens.ts @@ -15,9 +15,10 @@ const methodology = { } const adapter: Adapter = { + version: 2, adapter: { [CHAIN.ETHEREUM]: { - fetch: (async (timestamp: number, _: any, options: FetchOptions) => { + fetch: (async (options: FetchOptions) => { const dailyFees = options.createBalances(); const registeredLogs = await options.getLogs({ targets: [address_v4, address_v5], @@ -30,7 +31,7 @@ const adapter: Adapter = { registeredLogs.concat(renewedLogs).map((tx: any) => { dailyFees.addGasToken(tx.cost) }) - return { timestamp, dailyFees, dailyRevenue: dailyFees, } + return { dailyFees, dailyRevenue: dailyFees, } }) as any, start: 1677110400, meta: { diff --git a/fees/equalizer-exchange.ts b/fees/equalizer-exchange.ts index f461759b82..858278a33a 100644 --- a/fees/equalizer-exchange.ts +++ b/fees/equalizer-exchange.ts @@ -6,6 +6,7 @@ const VOTER_ADDRESS = '0xE3D1A117dF7DCaC2eB0AC8219341bAd92f18dAC1'; const FACTORY_ADDRESS = '0xc6366EFD0AF1d09171fe0EBF32c7943BB310832a'; const adapter: SimpleAdapter = { + version: 2, adapter: { [CHAIN.FANTOM]: { fetch: getFeesExport({ VOTER_ADDRESS, FACTORY_ADDRESS }), @@ -14,4 +15,4 @@ const adapter: SimpleAdapter = { } }; -export default adapter; \ No newline at end of file +export default adapter; diff --git a/fees/equation-v2/index.ts b/fees/equation-v2/index.ts index b650f64171..8d4f6738ea 100644 --- a/fees/equation-v2/index.ts +++ b/fees/equation-v2/index.ts @@ -50,6 +50,7 @@ const getFetch = () => (chain: string): Fetch => async (timestamp: number) => { }; const adapter: SimpleAdapter = { + version: 1, adapter: { [CHAIN.ARBITRUM]: { fetch: getFetch()(CHAIN.ARBITRUM), diff --git a/fees/equation-v3/index.ts b/fees/equation-v3/index.ts new file mode 100644 index 0000000000..236069c199 --- /dev/null +++ b/fees/equation-v3/index.ts @@ -0,0 +1,64 @@ +import { request, gql } from "graphql-request"; +import { Chain } from '@defillama/sdk/build/general'; +import { getUniqStartOfTodayTimestamp } from "../../helpers/getUniSubgraphVolume"; +import { CHAIN } from "../../helpers/chains"; +import { BreakdownAdapter, FetchV2, SimpleAdapter } from "../../adapters/types"; + +const endpoints: { [key: string]: string } = { + [CHAIN.ARBITRUM]: "https://graph-arbitrum.equation.trade/subgraphs/name/equation-stats-v3-arbitrum", +} + +const methodology = { + Fees: "Fees from open/close position and placed limit order (0.05%), with invitation code (0.045%)", + Revenue: "Revenue is 50% of all collected fees", + ProtocolRevenue: "Revenue is 50% of all collected fees" +} + +const queryFee = gql` +query query_volume($id: String!) { + protocolStatistics(where: {id: $id}) { + stakeFee + architectFee + protocolFee + } +} +` + +interface IDailyResponse { + protocolStatistics: [ + { + protocolFee: string, + architectFee: string, + stakeFee: string, + } + ] +} + +const getFetch = () => (chain: string): FetchV2 => async ({ startOfDay }) => { + const graphRes: IDailyResponse = await request(endpoints[chain], queryFee, { + id: 'Daily:' + startOfDay, + }) + const dailyFee = graphRes.protocolStatistics[0].protocolFee + const dailyProtocolRevenue = parseFloat(graphRes.protocolStatistics[0].architectFee) + parseFloat(graphRes.protocolStatistics[0].stakeFee) + + return { + timestamp: startOfDay, + dailyFees: dailyFee.toString(), + dailyProtocolRevenue: dailyProtocolRevenue.toString(), + }; +}; + +const adapter: SimpleAdapter = { + version: 2, + adapter: { + [CHAIN.ARBITRUM]: { + fetch: getFetch()(CHAIN.ARBITRUM), + start: 1715558400, + meta: { + methodology + } + }, + } +} + +export default adapter; \ No newline at end of file diff --git a/fees/equation/index.ts b/fees/equation/index.ts index 729fd9151d..55cf54940f 100644 --- a/fees/equation/index.ts +++ b/fees/equation/index.ts @@ -1,64 +1,68 @@ import { request, gql } from "graphql-request"; -import { Chain } from '@defillama/sdk/build/general'; -import { getUniqStartOfTodayTimestamp } from "../../helpers/getUniSubgraphVolume"; import { CHAIN } from "../../helpers/chains"; -import { BreakdownAdapter, Fetch, SimpleAdapter } from "../../adapters/types"; +import { FetchV2, SimpleAdapter } from "../../adapters/types"; const endpoints: { [key: string]: string } = { - [CHAIN.ARBITRUM]: "https://graph-arbitrum.equation.trade/subgraphs/name/equation-stats-arbitrum", -} + [CHAIN.ARBITRUM]: + "https://graph-arbitrum.equation.trade/subgraphs/name/equation-stats-arbitrum", +}; const methodology = { - Fees: "Fees from open/close position and placed limit order (0.05%), with invitation code (0.045%)", - Revenue: "Revenue is 50% of all collected fees", - ProtocolRevenue: "Revenue is 50% of all collected fees" -} + Fees: "Fees from open/close position and placed limit order (0.05%), with invitation code (0.045%)", + Revenue: "Revenue is 50% of all collected fees", + ProtocolRevenue: "Revenue is 50% of all collected fees", +}; -const queryFee = gql` -query query_volume($id: String!) { - protocolStatistics(where: {id: $id}) { - stakeFee - architectFee - protocolFee +const queryTotalFee = gql` + query query_total($block: Int) { + protocolState(id: "protocol_state", block: { number: $block }) { + totalFee } -} -` + } +`; -interface IDailyResponse { - protocolStatistics: [ - { - protocolFee: string, - architectFee: string, - stakeFee: string, - } - ] -} +const getFetch = + () => + (chain: string): FetchV2 => + async ({ getStartBlock, getEndBlock }) => { + const [startBlock, endBlock] = await Promise.all([ + getStartBlock(), + getEndBlock(), + ]); + const [prevData, totalData] = await Promise.all([ + request(endpoints[chain], queryTotalFee, { + block: startBlock, + }), + request(endpoints[chain], queryTotalFee, { + block: endBlock, + }), + ]); -const getFetch = () => (chain: string): Fetch => async (timestamp: number) => { - const todaysTimestamp = getUniqStartOfTodayTimestamp(new Date((timestamp * 1000))) - const graphRes: IDailyResponse = await request(endpoints[chain], queryFee, { - id: 'Daily:' + todaysTimestamp, - }) - const dailyFee = graphRes.protocolStatistics[0].protocolFee - const dailyProtocolRevenue = parseFloat(graphRes.protocolStatistics[0].architectFee) + parseFloat(graphRes.protocolStatistics[0].stakeFee) + const dailyFees = + totalData.protocolState.totalFee - prevData.protocolState.totalFee; + const totalFees = totalData.protocolState.totalFee; return { - timestamp: todaysTimestamp, - dailyFees: dailyFee.toString(), - dailyProtocolRevenue: dailyProtocolRevenue.toString(), + dailyFees, + dailyRevenue: dailyFees / 2, + dailyProtocolRevenue: dailyFees / 2, + totalFees, + totalRevenue: totalFees / 2, + totalProtocolRevenue: totalFees / 2, }; -}; + }; const adapter: SimpleAdapter = { - adapter: { - [CHAIN.ARBITRUM]: { - fetch: getFetch()(CHAIN.ARBITRUM), - start: 1697760000, - meta: { - methodology - } - }, - } -} + version: 2, + adapter: { + [CHAIN.ARBITRUM]: { + fetch: getFetch()(CHAIN.ARBITRUM), + start: 1697760000, + meta: { + methodology, + }, + }, + }, +}; -export default adapter; \ No newline at end of file +export default adapter; diff --git a/fees/equilibre-exchange.ts b/fees/equilibre-exchange.ts index 4f5e4ca8bb..2a8d20616c 100644 --- a/fees/equilibre-exchange.ts +++ b/fees/equilibre-exchange.ts @@ -1,15 +1,6 @@ -import { SimpleAdapter } from "../adapters/types"; import { CHAIN } from "../helpers/chains"; -import { getDexFeesExports } from "../helpers/dexVolumeLogs"; +import { uniV2Exports } from "../helpers/uniswap"; -const FACTORY_ADDRESS = '0xA138FAFc30f6Ec6980aAd22656F2F11C38B56a95' -const adapter: SimpleAdapter = { - adapter: { - [CHAIN.KAVA]: { - fetch: getDexFeesExports({ chain: CHAIN.KAVA, factory: FACTORY_ADDRESS,}), - start: 1677888000, - }, - } -}; - -export default adapter; +export default uniV2Exports({ + [CHAIN.KAVA]: { factory: '0xA138FAFc30f6Ec6980aAd22656F2F11C38B56a95' }, +}) diff --git a/fees/equity/index.ts b/fees/equity/index.ts index 102f98549f..5fe96df0e8 100644 --- a/fees/equity/index.ts +++ b/fees/equity/index.ts @@ -1,3 +1,4 @@ +import * as sdk from "@defillama/sdk"; import { Chain } from "@defillama/sdk/build/general"; import { gql, request } from "graphql-request"; import type { ChainEndpoints } from "../../adapters/types"; @@ -6,7 +7,7 @@ import { FANTOM } from "../../helpers/chains"; import { getTimestampAtStartOfDayUTC } from "../../utils/date"; const endpoints = { - [FANTOM]: "https://api.thegraph.com/subgraphs/name/chimpydev/equity-core2", + [FANTOM]: sdk.graph.modifyEndpoint('9USQeMVzzBbxsXhQUmCk5fZursvL9Vj3cv8joYNXeKt9'), }; const graphs = (graphUrls: ChainEndpoints) => { @@ -43,6 +44,7 @@ const graphs = (graphUrls: ChainEndpoints) => { }; const adapter: Adapter = { + version: 1, adapter: { [FANTOM]: { fetch: graphs(endpoints)(FANTOM), diff --git a/fees/erinaceus/index.ts b/fees/erinaceus/index.ts new file mode 100644 index 0000000000..73a2455f0f --- /dev/null +++ b/fees/erinaceus/index.ts @@ -0,0 +1,87 @@ +import { Adapter, FetchOptions } from "../../adapters/types"; +import { CHAIN } from "../../helpers/chains"; +import { getPrices } from "../../utils/prices"; +import { Chain } from "@defillama/sdk/build/general"; +import getTxReceipts from "../../helpers/getTxReceipts"; +const sdk = require('@defillama/sdk') + + +const topic0_v2 = '0x221ad2e5b871cead1dd7f75c2fb223c0cfa34bdc049a15f3f82a1f0e943e605a'; + +type TAddrress = { + [l: string | Chain]: string; +} + + +const address_v2: TAddrress = { + [CHAIN.BAHAMUT]: '0x7fDBF4fe2DBBDf956C010b3dD83177CB86Eb1b14', +} + +interface ITx { + data: string; + transactionHash: string; + topics: string[]; +} + +type IGasTokenId = { + [l: string | Chain]: string; +} +const gasTokenId: IGasTokenId = { + [CHAIN.BAHAMUT]: "coingecko:fasttoken", +} + + +const fetch = (chain: Chain) => { + return async ({ getFromBlock, getToBlock, toTimestamp }: FetchOptions) => { + const [fromBlock, toBlock] = await Promise.all([getFromBlock(), getToBlock()]) + const logs_1: ITx[] = (await sdk.getEventLogs({ + target: address_v2[chain], + fromBlock: fromBlock, + toBlock: toBlock, + topics: [topic0_v2], + chain: chain + })).map((e: any) => { return { data: e.data.replace('0x', ''), transactionHash: e.transactionHash } as ITx }); + + const amount_fullfill = logs_1.map((e: ITx) => { + const payment = Number('0x' + e.data.slice(64, 128)) / 10 ** 18 + return payment; + }).reduce((a: number, b: number) => a + b, 0); + + const tx_hash: string[] = [...new Set([...logs_1].map((e: ITx) => e.transactionHash))] + const txReceipt: number[] = (await getTxReceipts(chain, tx_hash, { cacheKey: '' })) + .map((e: any) => { + const amount = (Number(e?.gasUsed || 0) * Number(e.effectiveGasPrice || 0)) / 10 ** 18 + return amount + }) + const gasToken = gasTokenId[chain]; + const prices = (await getPrices([gasToken], toTimestamp)); + const dailyGas = txReceipt.reduce((a: number, b: number) => a + b, 0); + const gagPrice = prices[gasToken].price + const dailyGasUsd = dailyGas * gagPrice; + const totalExFees = (amount_fullfill * gagPrice); + const dailyFees = (totalExFees) + const dailyRevenue = dailyFees - dailyGasUsd; + + return { + dailyFees: dailyFees.toString(), + dailyRevenue: dailyRevenue.toString(), + } + + } +} + + +const adapter: Adapter = { + version: 2, + adapter: { + [CHAIN.BAHAMUT]: { + fetch: fetch(CHAIN.BAHAMUT), + start: 1716364800, + meta: { + methodology: 'All Fees generated from activity on Erinaceus VRF Coordinator contract.' + }, + } + } +} +export default adapter; + diff --git a/fees/ethena.ts b/fees/ethena.ts new file mode 100644 index 0000000000..04f1c0332b --- /dev/null +++ b/fees/ethena.ts @@ -0,0 +1,69 @@ +import { ethers } from "ethers"; +import { FetchOptions } from "../adapters/types"; +import { CHAIN } from "../helpers/chains"; + +const usdt = "0xdac17f958d2ee523a2206206994597c13d831ec7" + +const mint_event = + "event Mint( address indexed minter,address indexed benefactor,address indexed beneficiary,address collateral_asset,uint256 collateral_amount,uint256 usde_amount)"; +const fetch = async (_t:number, _c:any, options: FetchOptions) => { + const logs = await options.getLogs({ + eventAbi: mint_event, + target: "0x2cc440b721d2cafd6d64908d6d8c4acc57f8afc3", + }); + const in_flow = (await options.getLogs({ + targets: [usdt], + flatten: false, + eventAbi: 'event Transfer (address indexed from, address indexed to, uint256 value)', + topics: ['0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef', null, [ + ethers.zeroPadValue("0x71e4f98e8f20c88112489de3dded4489802a3a87", 32), + ethers.zeroPadValue("0x2b5ab59163a6e93b4486f6055d33ca4a115dd4d5", 32), + ]] as any, + }))[0].filter((log:any[])=>!["0x71e4f98e8f20c88112489de3dded4489802a3a87", "0x2b5ab59163a6e93b4486f6055d33ca4a115dd4d5"] + .some(a=>a.toLowerCase() === log[0].toLowerCase())) + + const out_flow = (await options.getLogs({ + targets: [usdt], + flatten: false, + eventAbi: 'event Transfer (address indexed from, address indexed to, uint256 value)', + topics: ['0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef', null, [ + ethers.zeroPadValue("0xf2fa332bd83149c66b09b45670bce64746c6b439", 32), + ]] as any, + }))[0] + + const dailyFeesInflow = options.createBalances(); + const supplyRewards = options.createBalances(); + + in_flow.map((log: any) => { + const amount = Number(log.value); + dailyFeesInflow.add(usdt, amount); + }); + out_flow.map((log: any) => { + const amount = Number(log.value); + supplyRewards.add(usdt, amount); + }); + const dailyFeesMint = options.createBalances(); + logs.map((log) => { + dailyFeesMint.add(log.collateral_asset, log.collateral_amount); + }); + + dailyFeesMint.resizeBy(0.001); + dailyFeesMint.addBalances(dailyFeesInflow); + const revenue = dailyFeesMint.clone(); + revenue.subtract(supplyRewards); + return { + dailyFees: dailyFeesMint, + dailyRevenue: revenue, + }; +}; + +const adapters = { + // version v1 because if we track expenses but not income it leads to wrong data, need to include both + adapter: { + [CHAIN.ETHEREUM]: { + fetch: fetch, + start: 1700784000, + }, + }, +}; +export default adapters; diff --git a/fees/ether-fi/index.ts b/fees/ether-fi/index.ts new file mode 100644 index 0000000000..7506c76a20 --- /dev/null +++ b/fees/ether-fi/index.ts @@ -0,0 +1,43 @@ +// https://etherfi.gitbook.io/etherfi/liquid/technical-documentation#fees +import { Adapter, FetchOptions } from "../../adapters/types"; +import { CHAIN } from "../../helpers/chains"; + +const LIQUID_VAULT = "0xeA1A6307D9b18F8d1cbf1c3Dd6aad8416C06a221"; +const YEAR = 365; +const ANNUAL_FEE_RATE = 0.02; + +const fetch = async (options: FetchOptions) => { + const dailyFeeRate = ANNUAL_FEE_RATE / YEAR; + const dailyFees = options.createBalances(); + const [asset, totalSupply] = await Promise.all([ + options.api.call({ + target: LIQUID_VAULT, + abi: "function asset() external view returns (address)", + }), + options.api.call({ + target: LIQUID_VAULT, + abi: "function totalAssets() external view returns (uint256 assets)", + }), + ]); + dailyFees.add(asset, totalSupply); + dailyFees.resizeBy(dailyFeeRate); + return { dailyFees }; +}; + +const adapter: Adapter = { + version: 2, + adapter: { + [CHAIN.ETHEREUM]: { + fetch, + meta: { + methodology: { + totalFees: + "Ether.fi-Liquid vault charges an annualized 2% platform fee based on vault TVL", + }, + }, + start: 1710284400, + }, + }, +}; + +export default adapter; diff --git a/fees/ethereum/index.ts b/fees/ethereum/index.ts index 6ed9e371d2..fb4b01528e 100644 --- a/fees/ethereum/index.ts +++ b/fees/ethereum/index.ts @@ -1,9 +1,9 @@ -import { Adapter, ChainBlocks, FetchOptions, ProtocolType } from "../../adapters/types"; +import { Adapter, FetchOptions, ProtocolType } from "../../adapters/types"; import { ETHEREUM } from "../../helpers/chains"; import { queryIndexer } from '../../helpers/indexer'; -const fetch = async (timestamp: number, _: ChainBlocks, options: FetchOptions) => { +const fetch = async (options: FetchOptions) => { const toBlock = await options.getToBlock() const fromBlock = await options.getFromBlock() const eth_txs: any = await queryIndexer(` @@ -37,7 +37,6 @@ const fetch = async (timestamp: number, _: ChainBlocks, options: FetchOptions) = const dailyFee = options.createBalances() dailyFee.addGasToken(Number(eth_txs[0].txn_fees) * 10 ** 18) return { - timestamp, dailyFees: dailyFee, dailyRevenue: dailyRev, dailyHoldersRevenue: dailyRev, @@ -45,6 +44,7 @@ const fetch = async (timestamp: number, _: ChainBlocks, options: FetchOptions) = }; const adapter: Adapter = { + version: 2, adapter: { [ETHEREUM]: { fetch, diff --git a/fees/ethervista.ts b/fees/ethervista.ts new file mode 100644 index 0000000000..6f18a30f16 --- /dev/null +++ b/fees/ethervista.ts @@ -0,0 +1,16 @@ +import { Adapter } from "../adapters/types"; +import { CHAIN } from "../helpers/chains"; +import { evmReceivedGasAndTokens } from "../helpers/token"; + +const adapter: Adapter = { + version: 2, + isExpensiveAdapter: true, + adapter: { + [CHAIN.ETHEREUM]: { + fetch: evmReceivedGasAndTokens('0xca90d843288e35beeadfce14e5f906e3f1afc7cb', []), + start: 0, + }, + } +} + +export default adapter; \ No newline at end of file diff --git a/fees/extra/index.ts b/fees/extra/index.ts index 8031344e3d..2a24c9a85a 100644 --- a/fees/extra/index.ts +++ b/fees/extra/index.ts @@ -1,4 +1,4 @@ -import { Adapter, ChainBlocks, FetchOptions, FetchResultFees } from "../../adapters/types"; +import { Adapter, FetchOptions } from "../../adapters/types"; import { CHAIN } from "../../helpers/chains"; import request from "graphql-request"; import BigNumber from "bignumber.js"; @@ -7,8 +7,8 @@ type TEndpoint = { [s: CHAIN | string]: string; } const endpoints: TEndpoint = { - [CHAIN.OPTIMISM]: `https://api.thegraph.com/subgraphs/name/extrafi/extrasubgraph`, - [CHAIN.BASE]: `https://api.thegraph.com/subgraphs/name/extrafi/extrafionbase` + [CHAIN.OPTIMISM]: `https://gateway-arbitrum.network.thegraph.com/api/a4998f968b8ad324eb3e47ed20c00220/subgraphs/id/3Htp5TKs6BHCcwAYRCoBD6R4X62ThLRv2JiBBikyYze`, + [CHAIN.BASE]: `https://api.studio.thegraph.com/query/46015/extrafionbase/version/latest` } interface IFeePaid { @@ -28,12 +28,9 @@ interface ILendingPool { } const graphs = (chain: CHAIN) => { - return async (timestamp: number, _: ChainBlocks, { createBalances, startOfDay }: FetchOptions): Promise => { + return async ({ fromTimestamp, toTimestamp, createBalances }: FetchOptions) => { const dailyFees = createBalances() - const fromTimestamp = startOfDay - 60 * 60 * 24 - const toTimestamp = startOfDay - const farmingQuery = `{ feePaids( where: { blockTimestamp_lte: ${toTimestamp}, blockTimestamp_gte: ${fromTimestamp} }, @@ -93,13 +90,13 @@ const graphs = (chain: CHAIN) => { dailyRevenue.resizeBy(0.5) return { - timestamp: startOfDay, dailyFees, dailyRevenue, }; }; } const adapter: Adapter = { + version: 2, adapter: { [CHAIN.OPTIMISM]: { fetch: graphs(CHAIN.OPTIMISM), diff --git a/fees/factor/index.ts b/fees/factor/index.ts new file mode 100644 index 0000000000..06a33692fc --- /dev/null +++ b/fees/factor/index.ts @@ -0,0 +1,46 @@ +// https://docs.factor.fi/governance/factordao/platform-fees#harvest-fees +// https://docs.factor.fi/factor-sdk/rest-apis/utility-apis/stats + +import axios from "axios"; +import { Adapter, FetchResultFees } from "../../adapters/types"; +import { CHAIN } from "../../helpers/chains"; + +const url = "https://factor-stats-api.fly.dev/stats/dao-revenues/"; + +interface Date { + year: number; + month: number; + day: number; +} + +const getFormattedDate = (timestamp: number): Date => { + const date = new Date(timestamp * 1000); + const year = date.getFullYear(); + const month = date.getMonth() + 1; + const day = date.getDate(); + return { year, month, day }; +}; + +const fetch = async (timestamp: number): Promise => { + const { year, month, day } = getFormattedDate(timestamp); + const { data } = await axios.get(`${url}${year}/${month}`); + const dateKey = `${year}-${month}-${day}`; + const relevantData = data[dateKey]; + + return { + timestamp, + dailyFees: relevantData.todayIncome, + dailyRevenue: relevantData.todayIncome / 2, + }; +}; +const adapter: Adapter = { + adapter: { + [CHAIN.ARBITRUM]: { + fetch, + start: 1714687200, + runAtCurrTime: false, + }, + }, +}; + +export default adapter; diff --git a/fees/fantasy-top/index.ts b/fees/fantasy-top/index.ts new file mode 100644 index 0000000000..dfb0a3f185 --- /dev/null +++ b/fees/fantasy-top/index.ts @@ -0,0 +1,23 @@ +import { Adapter, FetchResultV2 } from '../../adapters/types'; +import { CHAIN } from '../../helpers/chains'; +import { addTokensReceived } from '../../helpers/token'; + +const getFees = async (options): Promise => { + const dailyFees = options.createBalances() + + await addTokensReceived({ options, tokens: ["0x4300000000000000000000000000000000000004"], target: "0x8ab15fe88a00b03724ac91ee4ee1f998064f2e31", balances: dailyFees }) + return { + dailyFees, + } +} + +const adapter: Adapter = { + version: 2, + adapter: { + [CHAIN.BLAST]: { + fetch: getFees, + start: 1714445967 + }, + }, +}; +export default adapter; diff --git a/fees/farcaster.ts b/fees/farcaster.ts new file mode 100644 index 0000000000..838212b875 --- /dev/null +++ b/fees/farcaster.ts @@ -0,0 +1,20 @@ +import { Adapter } from "../adapters/types"; +import { CHAIN } from "../helpers/chains"; +import { evmReceivedGasAndTokens } from "../helpers/token"; + +const adapter: Adapter = { + version: 2, + isExpensiveAdapter: true, + adapter: { + [CHAIN.OPTIMISM]: { + fetch: evmReceivedGasAndTokens('0x00000000fcce7f938e7ae6d3c335bd6a1a7c593d', []), // actual protocol payments + start: 0, + }, + [CHAIN.BASE]: { + fetch: evmReceivedGasAndTokens('0xbc698ce1933afb2980d4a5a0f85fea1b02fbb1c9', []), // zora rewards + start: 0, + } + } +} + +export default adapter; \ No newline at end of file diff --git a/fees/ferro.ts b/fees/ferro.ts index 0b8557095e..765babd80d 100644 --- a/fees/ferro.ts +++ b/fees/ferro.ts @@ -1,15 +1,10 @@ import { CHAIN } from "../helpers/chains"; -import { univ2DimensionAdapter } from "../helpers/getUniSubgraph"; +import { univ2DimensionAdapter2 } from "../helpers/getUniSubgraph"; -const adapters = univ2DimensionAdapter({ +const adapters = univ2DimensionAdapter2({ graphUrls: { [CHAIN.CRONOS]: "https://graph.cronoslabs.com/subgraphs/name/ferro/swap", }, - dailyVolume: { - factory: "dailyVolume", - field: "volume", - dateField: "timestamp" - }, totalVolume: { factory: "tradeVolumes", field: "volume" @@ -25,5 +20,6 @@ const adapters = univ2DimensionAdapter({ } }, { }); + adapters.adapter.cronos.start = 1661731973; export default adapters; diff --git a/fees/filament/index.tsx b/fees/filament/index.tsx new file mode 100644 index 0000000000..42430fd411 --- /dev/null +++ b/fees/filament/index.tsx @@ -0,0 +1,106 @@ +import BigNumber from "bignumber.js"; +import request, { gql } from "graphql-request"; +import { FetchOptions, SimpleAdapter } from "../../adapters/types"; +import { CHAIN } from "../../helpers/chains"; + +const endpoint = + "https://api.goldsky.com/api/public/project_cm0qvthsz96sp01utcnk55ib0/subgraphs/filament-sei/v1/gn"; + +// Get timestamps for yesterday and today +const now = Math.floor(Date.now() / 1000); // Current timestamp in seconds +const yesterday = now - 86400; // 24 hours ago + +const queryDaily = gql` + query stats($yesterday: Int!, $now: Int!) { + totalTradingFees( + orderBy: block_number + orderDirection: asc + where: { timestamp__gte: $yesterday, timestamp__lte: $now } + ) { + timestamp_ + block_number + account + totalFees + } + } +`; + +const queryTotal = gql` + query stats { + totalTradingFees(orderBy: block_number, orderDirection: asc) { + timestamp_ + block_number + account + totalFees + } + } +`; + +interface IGraphResponse { + totalTradingFees: Array<{ + timestamp: string; + blocknumber: string; + account: string; + totalFees: string; + }>; +} + +const methodology = { + totalFees: + "Tracks the cumulative fees (borrowing fees + trading fees) generated by all transactions.", + dailyFees: + "Tracks the fees (borrowing fees + trading fees) generated by transactions on a daily basis.", +}; + +const toString = (x: BigNumber) => { + if (x.isEqualTo(0)) return undefined; + return x.toString(); +}; + +const fetchProtocolFees = async () => { + // Fetch daily fees + console.log(now); + const yesterday = now - 86400; // 24 hours ago + console.log(yesterday); + const responseDaily: IGraphResponse = await request(endpoint, queryDaily, { + yesterday, + now, + }); + + let dailyFees = new BigNumber(0); + responseDaily.totalTradingFees.forEach((data) => { + dailyFees = dailyFees.plus(new BigNumber(data.totalFees)); + }); + + // Fetch total fees + const responseTotal: IGraphResponse = await request(endpoint, queryTotal); + + let totalFees = new BigNumber(0); + responseTotal.totalTradingFees.forEach((data) => { + totalFees = totalFees.plus(new BigNumber(data.totalFees)); + }); + + dailyFees = dailyFees.dividedBy(new BigNumber(1e18)); + totalFees = totalFees.dividedBy(new BigNumber(1e18)); + + const _dailyFees = toString(dailyFees); + const _totalFees = toString(totalFees); + + return { + dailyFees: _dailyFees ?? "0", + totalFees: _totalFees ?? "0", + }; +}; + +const adapter: SimpleAdapter = { + adapter: { + [CHAIN.SEI]: { + fetch: fetchProtocolFees, + start: 1725741586, + meta: { + methodology, + }, + }, + }, +}; +export default adapter; diff --git a/fees/firebird-finance.ts b/fees/firebird-finance.ts index b8669404f5..4c1bddc956 100644 --- a/fees/firebird-finance.ts +++ b/fees/firebird-finance.ts @@ -34,6 +34,7 @@ const methodology = { }; const adapter: Adapter = { + version: 1, adapter: { [CHAIN.AVAX]: { fetch: fetch(43114), diff --git a/fees/first-crypto-bank/index.ts b/fees/first-crypto-bank/index.ts index c72c2db82b..2ce2f4c29f 100644 --- a/fees/first-crypto-bank/index.ts +++ b/fees/first-crypto-bank/index.ts @@ -4,7 +4,7 @@ import { queryIndexer } from "../../helpers/indexer"; /** Calculate USD equivalent for a given ether amount */ -const fetch: any = async (timestamp: number, _: any, options: FetchOptions) => { +const fetch: any = async (options: FetchOptions) => { const dailyFees = options.createBalances(); @@ -24,10 +24,11 @@ const fetch: any = async (timestamp: number, _: any, options: FetchOptions) => { AND block_time BETWEEN llama_replace_date_range; `, options); transactions.map((transaction: any) => dailyFees.addGasToken(transaction.eth_value)) - return { timestamp, dailyFees, } + return { dailyFees, } } const adapter: Adapter = { + version: 2, adapter: { ethereum: { fetch, diff --git a/fees/fjord-foundry/index.ts b/fees/fjord-foundry/index.ts new file mode 100644 index 0000000000..250e1ccc80 --- /dev/null +++ b/fees/fjord-foundry/index.ts @@ -0,0 +1,102 @@ +import { BreakdownAdapter, FetchOptions } from "../../adapters/types"; +import { getTimestampAtStartOfDayUTC } from "../../utils/date"; +import fetchURL from "../../utils/fetchURL"; +import { CHAIN } from "../../helpers/chains"; + +const feeEndpoint = "https://fjord-api.vercel.app/api/daily-stats?version=2"; +const feeEndpointV1 = "https://fjord-api.vercel.app/api/daily-stats?version=1"; + +const v2ChainIDs = { + [CHAIN.ETHEREUM]: 1, + [CHAIN.POLYGON]: 137, + [CHAIN.ARBITRUM]: 42161, + [CHAIN.AVAX]: 43114, + [CHAIN.BASE]: 8453, + [CHAIN.BLAST]: 81457, + [CHAIN.BSC]: 56, +}; + +const v1ChainIDs = { + [CHAIN.ETHEREUM]: 1, + [CHAIN.POLYGON]: 137, + [CHAIN.ARBITRUM]: 42161, +}; + +const getV2Data = async (endTimestamp: number, chainId: number) => { + const dayTimestamp = getTimestampAtStartOfDayUTC(endTimestamp) + const historicalFees = (await fetchURL(feeEndpoint)) + + const chainData = [...historicalFees.stats.evm, ...historicalFees.stats.svm].find(cd => cd.chainId === chainId); + + const totalFee = chainData.stats + .filter(item => item.timestamp <= dayTimestamp) + .reduce((acc, { fees }) => acc + fees, 0) + + const dailyFee = chainData.stats + .find(dayItem => dayItem.timestamp === dayTimestamp)?.fees + + return { + totalFees: `${totalFee}`, + dailyFees: dailyFee ? `${dailyFee}` : '0', + totalRevenue: `${totalFee}`, + dailyRevenue: dailyFee ? `${dailyFee}` : '0', + }; +}; + +const getV1Data = async (endTimestamp: number, chainId: number) => { + const dayTimestamp = getTimestampAtStartOfDayUTC(endTimestamp) + const historicalFees = (await fetchURL(feeEndpointV1)) + + const chainData = historicalFees.stats.find(cd => cd.chainId === chainId); + + const totalFee = chainData.stats + .filter(item => item.timestamp <= dayTimestamp) + .reduce((acc, { fees }) => acc + fees, 0) + + const dailyFee = chainData.stats + .find(dayItem => dayItem.timestamp === dayTimestamp)?.fees + + return { + totalFees: `${totalFee}`, + dailyFees: dailyFee ? `${dailyFee}` : '0', + totalRevenue: `${totalFee}`, + dailyRevenue: dailyFee ? `${dailyFee}` : '0', + }; +}; + +const methodology = { + Fees: "Fees collected from user trading fees", + Revenue: "Revenue is 100% fee of each swap which goes to treasury", +}; + +const adapter: BreakdownAdapter = { + version: 2, + breakdown: { + v2: Object.keys(v2ChainIDs).reduce((acc, chain) => { + return { + ...acc, + [chain]: { + fetch: async ({ startOfDay }: FetchOptions) => await getV2Data(startOfDay, v2ChainIDs[chain]), + start: 1702857600, + meta: { + methodology, + }, + }, + } + }, {}), + v1: Object.keys(v1ChainIDs).reduce((acc, chain) => { + return { + ...acc, + [chain]: { + fetch: async ({ startOfDay }: FetchOptions) => await getV1Data(startOfDay, v1ChainIDs[chain]), + start: 1631836800, + meta: { + methodology, + }, + }, + } + }, {}), + } +} + +export default adapter; diff --git a/fees/flashtrade.ts b/fees/flashtrade.ts new file mode 100644 index 0000000000..88b1a1fd8c --- /dev/null +++ b/fees/flashtrade.ts @@ -0,0 +1,64 @@ +import { Adapter, FetchResultFees } from "../adapters/types"; +import { CHAIN } from "../helpers/chains"; +import fetchURL from "../utils/fetchURL"; + +interface Pool { + pool: string; + accured: string; + paid: string; +} + +const methodology = { + Fees: 'Sum of all fees accrued from LP pools.', + ProtocolReveneue: '30% of all the fees accrued excluding Community pool.' +} + +const urlTotalStats = "https://api.prod.flash.trade/market-stat/revenue-all-time"; +const urlDailyStats = "https://api.prod.flash.trade/market-stat/revenue-24hr"; + +const calculateProtocolRevenue = (stats: Pool[]) => { + return stats + .filter(item => item.pool !== "Community.1") + .reduce((sum, item) => sum + 0.3 * parseFloat(item.accured), 0); +} + +const fetchFlashStats = async (timestamp: number): Promise => { + const totalStatsResponse = await fetchURL(urlTotalStats); + const dailyStatsResponse = await fetchURL(urlDailyStats); + + const totalStats: Pool[] = totalStatsResponse; + const dailyStats: Pool[] = dailyStatsResponse; + + const dailyAccrued = dailyStats.reduce((sum, item) => sum + parseFloat(item.accured), 0); + const totalAccrued = totalStats.reduce((sum, item) => sum + parseFloat(item.accured), 0); + + const dailyProtocolRevenue = calculateProtocolRevenue(dailyStats); + const totalProtocolRevenue = calculateProtocolRevenue(totalStats); + + return { + timestamp, + dailyFees: dailyAccrued.toString(), + totalFees: totalAccrued.toString(), + dailyRevenue: dailyProtocolRevenue.toString(), + dailyProtocolRevenue: dailyProtocolRevenue.toString(), + totalProtocolRevenue: totalProtocolRevenue.toString(), + totalRevenue: totalProtocolRevenue.toString(), + }; +}; + +const adapter: Adapter = { + version: 2, + adapter: { + [CHAIN.SOLANA]: { + runAtCurrTime: true, + customBackfill: undefined, + fetch: fetchFlashStats, + start: 0, + meta: { + methodology, + }, + }, + }, +}; + +export default adapter; diff --git a/fees/fluid/index.ts b/fees/fluid/index.ts new file mode 100644 index 0000000000..04028af8e9 --- /dev/null +++ b/fees/fluid/index.ts @@ -0,0 +1,615 @@ +import * as sdk from "@defillama/sdk"; +import { getBlock } from "@defillama/sdk/build/util/blocks"; +import BigNumber from "bignumber.js"; +import { Adapter, FetchOptions, FetchV2 } from "../../adapters/types"; +import { CHAIN } from "../../helpers/chains"; + +const abis: any = { + revenueResolver: { + calcRevenueSimulatedTime: + "function calcRevenueSimulatedTime(uint256 totalAmounts_,uint256 exchangePricesAndConfig_,uint256 liquidityTokenBalance_,uint256 simulatedTimestamp_) public view returns (uint256 revenueAmount_)", + getRevenue: + "function getRevenue(address token_) public view returns (uint256 revenueAmount_)", + }, + liquidityResolver: { + listedTokens: + "function listedTokens() public view returns (address[] listedTokens_)", + getExchangePricesAndConfig: + "function getExchangePricesAndConfig(address token_) public view returns (uint256)", + getTotalAmounts: + "function getTotalAmounts(address token_) public view returns (uint256)", + }, + vaultResolver_before_19992222: { + getAllVaultsAddresses: + "function getAllVaultsAddresses() external view returns (address[] vaults_)", + getVaultEntireData: + "function getVaultEntireData(address vault_) view returns ((address vault, (address liquidity, address factory, address adminImplementation, address secondaryImplementation, address supplyToken, address borrowToken, uint8 supplyDecimals, uint8 borrowDecimals, uint256 vaultId, bytes32 liquiditySupplyExchangePriceSlot, bytes32 liquidityBorrowExchangePriceSlot, bytes32 liquidityUserSupplySlot, bytes32 liquidityUserBorrowSlot) constantVariables, (uint16 supplyRateMagnifier, uint16 borrowRateMagnifier, uint16 collateralFactor, uint16 liquidationThreshold, uint16 liquidationMaxLimit, uint16 withdrawalGap, uint16 liquidationPenalty, uint16 borrowFee, address oracle, uint256 oraclePrice, address rebalancer) configs, (uint256 lastStoredLiquiditySupplyExchangePrice, uint256 lastStoredLiquidityBorrowExchangePrice, uint256 lastStoredVaultSupplyExchangePrice, uint256 lastStoredVaultBorrowExchangePrice, uint256 liquiditySupplyExchangePrice, uint256 liquidityBorrowExchangePrice, uint256 vaultSupplyExchangePrice, uint256 vaultBorrowExchangePrice, uint256 supplyRateVault, uint256 borrowRateVault, uint256 supplyRateLiquidity, uint256 borrowRateLiquidity, uint256 rewardsRate) exchangePricesAndRates, (uint256 totalSupplyVault, uint256 totalBorrowVault, uint256 totalSupplyLiquidity, uint256 totalBorrowLiquidity, uint256 absorbedSupply, uint256 absorbedBorrow) totalSupplyAndBorrow, (uint256 withdrawLimit, uint256 withdrawableUntilLimit, uint256 withdrawable, uint256 borrowLimit, uint256 borrowableUntilLimit, uint256 borrowable, uint256 minimumBorrowing) limitsAndAvailability, (uint256 totalPositions, int256 topTick, uint256 currentBranch, uint256 totalBranch, uint256 totalBorrow, uint256 totalSupply, (uint256 status, int256 minimaTick, uint256 debtFactor, uint256 partials, uint256 debtLiquidity, uint256 baseBranchId, int256 baseBranchMinima) currentBranchState) vaultState, (bool modeWithInterest, uint256 supply, uint256 withdrawalLimit, uint256 lastUpdateTimestamp, uint256 expandPercent, uint256 expandDuration, uint256 baseWithdrawalLimit, uint256 withdrawableUntilLimit, uint256 withdrawable) liquidityUserSupplyData, (bool modeWithInterest, uint256 borrow, uint256 borrowLimit, uint256 lastUpdateTimestamp, uint256 expandPercent, uint256 expandDuration, uint256 baseBorrowLimit, uint256 maxBorrowLimit, uint256 borrowableUntilLimit, uint256 borrowable) liquidityUserBorrowData) vaultData_)", + }, + vaultResolver_after_19992222: { + getAllVaultsAddresses: + "function getAllVaultsAddresses() external view returns (address[] vaults_)", + getVaultEntireData: + "function getVaultEntireData(address vault_) view returns ((address vault, (address liquidity, address factory, address adminImplementation, address secondaryImplementation, address supplyToken, address borrowToken, uint8 supplyDecimals, uint8 borrowDecimals, uint256 vaultId, bytes32 liquiditySupplyExchangePriceSlot, bytes32 liquidityBorrowExchangePriceSlot, bytes32 liquidityUserSupplySlot, bytes32 liquidityUserBorrowSlot) constantVariables, (uint16 supplyRateMagnifier, uint16 borrowRateMagnifier, uint16 collateralFactor, uint16 liquidationThreshold, uint16 liquidationMaxLimit, uint16 withdrawalGap, uint16 liquidationPenalty, uint16 borrowFee, address oracle, uint256 oraclePriceOperate, uint256 oraclePriceLiquidate, address rebalancer) configs, (uint256 lastStoredLiquiditySupplyExchangePrice, uint256 lastStoredLiquidityBorrowExchangePrice, uint256 lastStoredVaultSupplyExchangePrice, uint256 lastStoredVaultBorrowExchangePrice, uint256 liquiditySupplyExchangePrice, uint256 liquidityBorrowExchangePrice, uint256 vaultSupplyExchangePrice, uint256 vaultBorrowExchangePrice, uint256 supplyRateVault, uint256 borrowRateVault, uint256 supplyRateLiquidity, uint256 borrowRateLiquidity, uint256 rewardsRate) exchangePricesAndRates, (uint256 totalSupplyVault, uint256 totalBorrowVault, uint256 totalSupplyLiquidity, uint256 totalBorrowLiquidity, uint256 absorbedSupply, uint256 absorbedBorrow) totalSupplyAndBorrow, (uint256 withdrawLimit, uint256 withdrawableUntilLimit, uint256 withdrawable, uint256 borrowLimit, uint256 borrowableUntilLimit, uint256 borrowable, uint256 borrowLimitUtilization, uint256 minimumBorrowing) limitsAndAvailability, (uint256 totalPositions, int256 topTick, uint256 currentBranch, uint256 totalBranch, uint256 totalBorrow, uint256 totalSupply, (uint256 status, int256 minimaTick, uint256 debtFactor, uint256 partials, uint256 debtLiquidity, uint256 baseBranchId, int256 baseBranchMinima) currentBranchState) vaultState, (bool modeWithInterest, uint256 supply, uint256 withdrawalLimit, uint256 lastUpdateTimestamp, uint256 expandPercent, uint256 expandDuration, uint256 baseWithdrawalLimit, uint256 withdrawableUntilLimit, uint256 withdrawable) liquidityUserSupplyData, (bool modeWithInterest, uint256 borrow, uint256 borrowLimit, uint256 lastUpdateTimestamp, uint256 expandPercent, uint256 expandDuration, uint256 baseBorrowLimit, uint256 maxBorrowLimit, uint256 borrowableUntilLimit, uint256 borrowable, uint256 borrowLimitUtilization) liquidityUserBorrowData) vaultData_)", + }, + vault: { + constantsView: + "function constantsView() public view returns((address liquidity,address factory,address adminImplementation,address secondaryImplementation,address supplyToken,address borrowToken,uint8 supplyDecimals,uint8 borrowDecimals,uint vaultId,bytes32 liquiditySupplyExchangePriceSlot,bytes32 liquidityBorrowExchangePriceSlot,bytes32 liquidityUserSupplySlot,bytes32 liquidityUserBorrowSlot))", + }, +}; + +const revenueResolver = async (api: sdk.ChainApi) => { + const block = await api.getBlock(); + + let address; + let abi = abis.revenueResolver; + switch (api.chain) { + case CHAIN.ETHEREUM: + if (block < 19784319) { + break; // fluid RevenueResolver Exist After Block 19784319 + } + if (block < 20138676) { + address = "0x0F683159f14857D61544650607549Cdc21abE774"; + break; + } + address = "0xFe4affaD55c7AeC012346195654634F7C786fA2c"; + break; + case CHAIN.ARBITRUM: + address = "0xFe4affaD55c7AeC012346195654634F7C786fA2c"; + break; + case CHAIN.BASE: + address = "0xFe4affaD55c7AeC012346195654634F7C786fA2c"; + break; + } + + return { + calcRevenueSimulatedTime: async ( + totalAmounts: string, + exchangePricesAndConfig: string, + liquidityTokenBalance: string | BigNumber, + timestamp: string | number + ) => { + if (!address) { + return 0; + } + + return await api.call({ + target: address, + abi: abi.calcRevenueSimulatedTime, + params: [ + totalAmounts, + exchangePricesAndConfig, + liquidityTokenBalance as string, + timestamp, + ], + }); + }, + getRevenue: async (token: string) => { + if (!address) { + return 0; + } + + return await api.call({ + target: address, + abi: abi.getRevenue, + params: [token], + }); + }, + }; +}; + +const liquidityResolver = async (api: sdk.ChainApi) => { + const block = await api.getBlock(); + + let address; + let abi = abis.liquidityResolver; + switch (api.chain) { + case CHAIN.ETHEREUM: + if (block < 19992056) { + address = "0x741c2Cd25f053a55fd94afF1afAEf146523E1249"; + break; + } + address = "0xD7588F6c99605Ab274C211a0AFeC60947668A8Cb"; + break; + case CHAIN.ARBITRUM: + address = "0x46859d33E662d4bF18eEED88f74C36256E606e44"; + break; + case CHAIN.BASE: + address = "0x35A915336e2b3349FA94c133491b915eD3D3b0cd"; + break; + } + + return { + listedTokens: async () => { + if (!address) { + return []; + } + + return await api.call({ + target: address, + abi: abi.listedTokens, + params: undefined, + }); + }, + getExchangePricesAndConfig: async (tokens: string[]) => { + if (!address) { + return 0; + } + + return await api.multiCall({ + abi: abi.getExchangePricesAndConfig, + calls: tokens.map((token) => ({ target: address, params: [token] })), + }); + }, + getTotalAmounts: async (tokens: string[]) => { + if (!address) { + return 0; + } + + return await api.multiCall({ + abi: abi.getTotalAmounts, + calls: tokens.map((token) => ({ target: address, params: [token] })), + }); + }, + }; +}; + +const vaultResolver = async (api: sdk.ChainApi) => { + const block = await api.getBlock(); + + let address; + let abi = abis.vaultResolver_after_19992222; + switch (api.chain) { + case CHAIN.ETHEREUM: + if (block < 19313700) { + // vault resolver related revenue only exists after this block. revenue / fees before are negligible + break; + } + + if (block < 19662786) { + address = "0x8DD65DaDb217f73A94Efb903EB2dc7B49D97ECca"; + abi = abis.vaultResolver_before_19992222; + break; + } + if (block < 19992222) { + address = "0x93CAB6529aD849b2583EBAe32D13817A2F38cEb4"; + abi = abis.vaultResolver_before_19992222; + break; + } + address = "0x56ddF84B2c94BF3361862FcEdB704C382dc4cd32"; + break; + case CHAIN.ARBITRUM: + address = "0x77648D39be25a1422467060e11E5b979463bEA3d"; + break; + case CHAIN.BASE: + address = "0x94695A9d0429aD5eFec0106a467aDEaDf71762F9"; + break; + } + + return { + getAllVaultsAddresses: async () => { + if (!address) { + return []; + } + + return await api.call({ + target: address, + abi: abi.getAllVaultsAddresses, + params: undefined, + }); + }, + getVaultEntireData: async (vaults: string[]) => { + if (!address) { + return null; + } + + return await api.multiCall({ + abi: abi.getVaultEntireData, + calls: vaults.map((vault) => ({ target: address, params: [vault] })), + permitFailure: true, + }); + }, + }; +}; + +const config: any = { + liquidity: "0x52aa899454998be5b000ad077a46bbe360f4e497", + ethereum: { + dataStartTimestamp: 1708246655, // ~ when liquidity resolver was deployed + + revenueResolverExistAfterBlock: 19959852, + // vault resolver related revenue only exists after this timestamp. revenue / fees before are negligible + vaultResolverExistAfterTimestamp: 1708931052, + vaultResolverExistAfterBlock: 19313700, + }, + arbitrum: { + dataStartTimestamp: 1720018638, // ~ before any activity started (block 228361633) + + revenueResolverExistAfterBlock: 228361632, + // vault resolver related revenue only exists after this timestamp. revenue / fees before are negligible + vaultResolverExistAfterTimestamp: 1720018637, + vaultResolverExistAfterBlock: 228361632, + }, + base: { + dataStartTimestamp: 1723484700, // ~ before any activity started (block 18347681) + + revenueResolverExistAfterBlock: 18347681, + // vault resolver related revenue only exists after this timestamp. revenue / fees before are negligible + vaultResolverExistAfterTimestamp: 1723484700, + vaultResolverExistAfterBlock: 18347681, + }, +}; + +const methodologyFluid = { + Fees: "Interest paid by borrowers", + Revenue: "Percentage of interest going to treasury", +}; + +const fetch: FetchV2 = async (options: FetchOptions) => { + return { + dailyFees: await getFeesFromTo(options), + dailyRevenue: await getRevenueFromTo(options), + }; +}; +const adapter: Adapter = { + version: 2, + adapter: { + [CHAIN.ETHEREUM]: { + fetch, + start: config.ethereum.dataStartTimestamp, + meta: { + methodology: methodologyFluid, + }, + }, + [CHAIN.ARBITRUM]: { + fetch, + start: config.arbitrum.dataStartTimestamp, + meta: { + methodology: methodologyFluid, + }, + }, + [CHAIN.BASE]: { + fetch, + start: config.base.dataStartTimestamp, + meta: { + methodology: methodologyFluid, + }, + }, + }, +}; + +export default adapter; + +const getFeesFromTo = async ( + options: FetchOptions +): Promise => { + + const liquidityOperateLogs = (await options.getLogs({ + target: config.liquidity, + onlyArgs: true, + eventAbi: "event LogOperate(address indexed user,address indexed token,int256 supplyAmount,int256 borrowAmount,address withdrawTo,address borrowTo,uint256 totalAmounts,uint256 exchangePricesAndConfig)", + })) as any[]; + + const dailyFees = options.createBalances(); + + const fromApi = options.fromApi; + const toApi = options.toApi; + const vaults: string[] = await ( + await vaultResolver(toApi) + ).getAllVaultsAddresses(); + + const vaultEntiresDataFrom: any[] = (await ( + await vaultResolver(fromApi) + ).getVaultEntireData(vaults)) as any[]; + + const vaultEntiresDataTo: any[] = (await ( + await vaultResolver(toApi) + ).getVaultEntireData(vaults)) as any[]; + + const vaultBorrowTokenCall = (await toApi.multiCall({ + abi: abis.vault.constantsView, + calls: vaults, + })) as { borrowToken: string }[]; + + + for (const [index, vault] of vaults.entries()) { + let borrowBalance = new BigNumber(0); + let borrowToken = ""; + try { + const { constantVariables, totalSupplyAndBorrow } = vaultEntiresDataFrom[index]; + + borrowToken = constantVariables.borrowToken; + borrowBalance = new BigNumber(totalSupplyAndBorrow.totalBorrowVault); + } catch (ex) { + // when vault did not exist yet, getVaultEntireData() will revert. at from block then we start from 0 balance. + } + + if (!borrowToken) { + const { borrowToken: vaultBorrowToken } = vaultBorrowTokenCall[index]; + borrowToken = vaultBorrowToken; + } + + // get block numbers where an update to vault borrow amounts happened + start block and end block + const vaultOperates = liquidityOperateLogs.filter( + (x) => + x[0] == vault && // filter user must be vault + x[1] == borrowToken // filter token must be vault borrow token (ignore supply / withdraw) + ); + + for (const vaultOperate of vaultOperates) { + borrowBalance = borrowBalance.plus(new BigNumber(vaultOperate[3])); + } + try { + const { totalSupplyAndBorrow: totalSupplyAndBorrowTo } = vaultEntiresDataTo[index]; + + dailyFees.add( + borrowToken, + new BigNumber(totalSupplyAndBorrowTo.totalBorrowVault).minus( + borrowBalance + ) + ); + } catch (ex) {} + + } + + return dailyFees; +}; + +const getRevenueFromTo = async ( + options: FetchOptions +): Promise => { + const LPRsevenueFromTo = await getLiquidityRevenueFromTo(options); + const vaultRevenueFromTo = await getVaultsMagnifierRevenueFromTo(options); + return LPRsevenueFromTo + vaultRevenueFromTo; +}; + +const getLiquidityRevenueFromTo = async ( + options: FetchOptions +) => { + const { fromTimestamp, toTimestamp, api } = options; + const tokens: string[] = await (await liquidityResolver(api)).listedTokens(); + + const collectRevenueLogs: [string, BigNumber][] = (await options.getLogs({ + target: config.liquidity, + eventAbi: + "event LogCollectRevenue(address indexed token, uint256 indexed amount)", + })) as [string, BigNumber][]; + + const revenueFrom: BigNumber[] = await getLiquidityUncollectedRevenueAt( + api, + fromTimestamp, + tokens + ); + + const revenueTo:BigNumber[] = await getLiquidityUncollectedRevenueAt( + api, + toTimestamp, + tokens + ); + const dailyValues = options.createBalances(); + for await (const [index, token] of tokens.entries()) { + + // consider case where collect revenue has been executed in the time frame + const logs = collectRevenueLogs.filter((x) => x[0] == token); + const collectedRevenue: BigNumber = logs.reduce((sum: BigNumber, x) => { + return sum.plus(x[1]); + }, new BigNumber(0)); + + // add collected revenue in time frame to the to time point revenue. + // to revenue = uncollected at that point + all collected revenue since from + const _revenueTo = BigNumber(revenueTo[index]) + _revenueTo.plus(collectedRevenue); + + // get uncollected revenue in from -> to timespan + dailyValues.add( + token, + _revenueTo.gt(revenueFrom[index]) + ? _revenueTo.minus(revenueFrom[index]) + : new BigNumber(0) + ); + } + + return await dailyValues.getUSDValue(); +}; + +const getLiquidityUncollectedRevenueAt = async ( + api: sdk.ChainApi, + timestamp: number, + tokens: string[] +) => { + const timestampedApi = new sdk.ChainApi({ + chain: api.chain, + block: (await getBlock(api.chain, timestamp)).number, + }); + + // check if token was listed at that timestamp at Liquidity, if not, revenue is 0 + + // get liquidity packed storage slots data at timestamped Api block number + const totalAmounts: any[] = await ( + await liquidityResolver(timestampedApi) + ).getTotalAmounts(tokens) as any[]; + + const exchangePricesAndConfig: any[] = await ( + await liquidityResolver(timestampedApi) + ).getExchangePricesAndConfig(tokens) as any[]; + + const ee = "0xeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee"; + const findIndex = tokens.findIndex((x) => x.toLowerCase() === ee); + const liquidityTokenBalance: string[] = await timestampedApi.multiCall({ + abi: "erc20:balanceOf", + calls: tokens + .filter(e => e.toLowerCase() !== ee) + .map((token) => ({ target: token, params: [config.liquidity] })), + }); + + if (findIndex != -1) { + const eeBalance = ( + await sdk.api.eth.getBalance({ + target: config.liquidity, + chain: timestampedApi.chain, + block: await timestampedApi.getBlock(), + }) + ).output; + liquidityTokenBalance.splice(findIndex, 0, eeBalance); + } + + + // // pass data into revenue resolver, available at current api block, which calculates revenue at the + // // simulated timestamp based on storage slots data + const uncollectedRevenue: BigNumber[] = [] + for(const [index, _token] of tokens.entries()) { + try { + const _uncollectedRevenue = await ( + await revenueResolver(api) + ).calcRevenueSimulatedTime( + totalAmounts[index], + exchangePricesAndConfig[index], + liquidityTokenBalance[index], + timestamp + ); + uncollectedRevenue.push(new BigNumber(_uncollectedRevenue)); + } catch (ex) { + console.error(ex); + } + } + + return uncollectedRevenue; +}; + +const getVaultsMagnifierRevenueFromTo = async ( + options: FetchOptions +) => { + const { fromTimestamp, toTimestamp, api } = options; + if (toTimestamp < config[api.chain].vaultResolverExistAfterTimestamp) { + return 0; + } + + const vaults: string[] = await ( + await vaultResolver(api) + ).getAllVaultsAddresses(); + + const fromBalancesApi = await getVaultMagnifierUncollectedRevenueAt( + api, + fromTimestamp, + vaults, + options + ); + + let toBalancesApi = await getVaultMagnifierUncollectedRevenueAt( + api, + toTimestamp, + vaults, + options + ); + + toBalancesApi = await getVaultMagnifierCollectedRevenueFromTo( + options, + vaults + ); + + const revenueFrom = await fromBalancesApi.getUSDValue(); + const revenueTo = await toBalancesApi.getUSDValue(); + + return revenueTo > revenueFrom ? revenueTo - revenueFrom : 0; +}; + +const getVaultMagnifierCollectedRevenueFromTo = async ( + options: FetchOptions, + vaults: string[], +) => { + const values = options.createBalances(); + const rebalanceEventLogs = await options.getLogs({ + targets: vaults, + onlyArgs: true, + flatten: false, + eventAbi: + /// @notice emitted when a `rebalance()` has been executed, balancing out total supply / borrow between Vault + /// and Fluid Liquidity pools. + /// if `colAmt_` is negative then profit, meaning withdrawn from vault and sent to rebalancer address. + /// if `debtAmt_` is positive then profit, meaning borrow from vault and sent to rebalancer address. + "event LogRebalance(int colAmt_, int debtAmt_)", + }) + + if (rebalanceEventLogs.length == 0) { + return values + } + + + // get collateral and borrow token of the vault + const contractViews: any[] = await options.api.multiCall({ + abi: abis.vault.constantsView, + calls: vaults.map((vault) => ({ target: vault })), + }); + + rebalanceEventLogs.forEach((logs, index) => { + logs.forEach((log: any) => { + if (log.colAmt.isNegative()) { + // add collateral token amount to balances + const colAmt = new BigNumber(log.colAmt_); + values.add(contractViews[index].supplyToken, colAmt.absoluteValue()); + } + if (log.debtAmt.isPositive()) { + // add borrow token amount to balances + const debtAmt = new BigNumber(log.debtAmt_); + values.add(contractViews[index].borrowToken, debtAmt); + } + }) + }); + return values; +}; + +const getVaultMagnifierUncollectedRevenueAt = async ( + api: sdk.ChainApi, + timestamp: number, + vaults: string[], + options: FetchOptions +) => { + const values = options.createBalances(); + if (timestamp < config[api.chain].vaultResolverExistAfterTimestamp) { + // vault resolver related revenue only exists after this timestamp. before this there has been no such revenue. + return values; + } + + const targetBlock = (await getBlock(api.chain, timestamp)).number; + + const timestampedApi = new sdk.ChainApi({ + chain: api.chain, + block: targetBlock, + }); + const vaultEntiresDataFrom: any[] = await ( + await vaultResolver(timestampedApi) + ).getVaultEntireData(vaults) as any[]; + + for (const [index, _vault] of vaults.entries()) { + try { + const { totalSupplyAndBorrow , constantVariables} = vaultEntiresDataFrom[index]; + const totalSupplyVault = new BigNumber( + totalSupplyAndBorrow.totalSupplyVault + ); + const totalBorrowVault = new BigNumber( + totalSupplyAndBorrow.totalBorrowVault + ); + const totalSupplyLiquidity = new BigNumber( + totalSupplyAndBorrow.totalSupplyLiquidity + ); + const totalBorrowLiquidity = new BigNumber( + totalSupplyAndBorrow.totalBorrowLiquidity + ); + + // if more supply at liquidity than at vault -> uncollected profit + const supplyTokenProfit = totalSupplyLiquidity.gt(totalSupplyVault) + ? totalSupplyLiquidity.minus(totalSupplyVault) + : new BigNumber(0); + // if less borrow at liquidity than at vault -> profit + const borrowTokenProfit = totalBorrowVault.gt(totalBorrowLiquidity) + ? totalBorrowVault.minus(totalBorrowLiquidity) + : new BigNumber(0); + + values.add(constantVariables.supplyToken, supplyTokenProfit); + values.add(constantVariables.borrowToken, borrowTokenProfit); + } catch (ex) { + // when vault did not exist yet, getVaultEntireData() will revert. at from block then we start from 0 balance. + } + } + return values; +}; +// yarn test fees fluid diff --git a/fees/forge.ts b/fees/forge.ts index 1bf8ae82f9..0961fe2fc8 100644 --- a/fees/forge.ts +++ b/fees/forge.ts @@ -46,6 +46,7 @@ const fetch = (chain: Chain) => { } const adapter: Adapter = { + version: 1, adapter: { [CHAIN.EVMOS]: { fetch: fetch(CHAIN.EVMOS), diff --git a/fees/foundation.ts b/fees/foundation.ts index 38d99eb7c2..b405cbd1a5 100644 --- a/fees/foundation.ts +++ b/fees/foundation.ts @@ -11,7 +11,7 @@ const topic_0_mint_from_fixed_price_drop = '0x05ebbb6b0ce7d564230ba625dd7a0e5108 const topic_0_withdraw_creator_revenue_from_dutch_auction = '0x5e16e96b4ba4fe46f3be73d54d1fa0da481494ab74c2d6e33328366d6437693c' // todo: track new events -const fetch = async (timestamp: number , _: ChainBlocks, { createBalances, getLogs, }: FetchOptions): Promise => { +const fetch = async ({ createBalances, getLogs, }: FetchOptions) => { const dailyFees = createBalances(); (await getLogs({ target: market_address, @@ -62,12 +62,13 @@ const fetch = async (timestamp: number , _: ChainBlocks, { createBalances, getLo }); return { - dailyFees, dailyRevenue: dailyFees, timestamp + dailyFees, dailyRevenue: dailyFees } } const adapter: Adapter = { + version: 2, adapter: { [CHAIN.ETHEREUM]: { fetch: fetch, diff --git a/fees/franklin-templeton/index.ts b/fees/franklin-templeton/index.ts new file mode 100644 index 0000000000..0a9692a8dc --- /dev/null +++ b/fees/franklin-templeton/index.ts @@ -0,0 +1,82 @@ +// https://www.franklintempleton.com/investments/options/money-market-funds/products/29386/SINGLCLASS/franklin-on-chain-u-s-government-money-fund/FOBXX#distributions + +import { ChainApi } from "@defillama/sdk"; +import { Chain } from "@defillama/sdk/build/general"; +import axios from "axios"; +import { + Adapter, + Fetch, + FetchOptions, + FetchResultFees, +} from "../../adapters/types"; +import { CHAIN } from "../../helpers/chains"; +import ADDRESSES from "../../helpers/coreAssets.json"; + +const CONFIG: Record = { + [CHAIN.POLYGON]: "0x408a634b8a8f0de729b48574a3a7ec3fe820b00a", + [CHAIN.STELLAR]: + "BENJI-GBHNGLLIE3KWGKCHIKMHJ5HVZHYIK7WTBE4QF5PLAKL4CJGSEU7HZIW5", +}; + +const EXPENSE_LIMITATION_TIMESTAMP = 1754006400; // 08/2025 +const GROSS_EXPENSE_YEAR = 0.0026; +const NET_EXPENSE_YEAR = 0.002; + +const stellarAUM = async (token: string): Promise => { + const stellarApi = `https://api.stellar.expert/explorer/public/asset/${token}`; + const { data } = await axios.get(stellarApi); + const { supply, toml_info } = data; + const adjustedSupply = supply / 10 ** (toml_info.decimals - 6); + return adjustedSupply; +}; + +const polygonAUM = async (token: string, api: ChainApi): Promise => { + const [decimals, supply] = await Promise.all([ + api.call({ target: token, abi: "erc20:decimals" }), + api.call({ target: token, abi: "erc20:totalSupply" }), + ]); + + const adjustedSupplyInUSDT = supply / 10 ** (decimals - 6); + return adjustedSupplyInUSDT; +}; + +const fetch = async ( + timestamp: number, + _: any, + { api, createBalances, endTimestamp }: FetchOptions, + token: string +): Promise => { + const dailyFees = createBalances(); + let supply: number = 0; + + if (api.chain === "polygon") supply = await polygonAUM(token, api); + if (api.chain === "stellar") supply = await stellarAUM(token); + + const expenseRatio = + endTimestamp < EXPENSE_LIMITATION_TIMESTAMP + ? NET_EXPENSE_YEAR + : GROSS_EXPENSE_YEAR; + + const dailySupply = (supply * expenseRatio) / 365; + dailyFees.add(ADDRESSES.ethereum.USDT, dailySupply, { skipChain: true }); + + return { timestamp, dailyFees }; +}; + +const adapter: Adapter = { + timetravel: false, + adapter: { + [CHAIN.POLYGON]: { + fetch: (...args: Parameters) => + fetch(...args, CONFIG[CHAIN.POLYGON]), + start: 1696370400, + }, + [CHAIN.STELLAR]: { + fetch: (...args: Parameters) => + fetch(...args, CONFIG[CHAIN.STELLAR]), + start: 1696370400, + }, + }, +}; + +export default adapter; diff --git a/fees/frax-amo.ts b/fees/frax-amo.ts new file mode 100644 index 0000000000..2c5dac76ae --- /dev/null +++ b/fees/frax-amo.ts @@ -0,0 +1,106 @@ +import * as sdk from "@defillama/sdk"; +import { gql, GraphQLClient } from "graphql-request"; +import { FetchOptions, SimpleAdapter } from "../adapters/types"; +import { CHAIN } from "../helpers/chains"; + +const query = (amo: string, timestamp: number) => gql` +{ + amos( + where: { + id: "${amo.toLowerCase()}" + }) { + id + name + positions { + depositAddress + name + fraxAccountingPerDay( + first: 3, + orderBy: timestamp, + orderDirection: desc + where: { + timestamp_lt: ${timestamp} + }) { + balance + depositedAmount + profitTaken + timestamp + } + } + } + } +`; + +const getGQLClient = (endpoint: string) => new GraphQLClient(endpoint); + +const findRevenue = (timedData: any) => + Number(timedData.balance) - + Number(timedData.depositedAmount) + + Number(timedData.profitTaken); + +const fetch = async ({ createBalances, chain, toTimestamp }: FetchOptions) => { + const { amos, graph, FRAX } = config[chain]; + const client = getGQLClient(graph); + const dailyRevenue = createBalances(); + const totalRevenue = createBalances(); + const dailyFees = createBalances(); + + await Promise.all( + amos.map(async (amo: string) => { + const data = (await client.request(query(amo, toTimestamp))).amos[0]; + data.positions.map((p: any) => { + const latest = findRevenue(p.fraxAccountingPerDay[0]); + const previous = findRevenue(p.fraxAccountingPerDay[1]); + dailyRevenue.add(FRAX, latest - previous); + totalRevenue.add(FRAX, latest); + }); + }), + ); + + return { + dailyRevenue, + totalRevenue, + dailyFees: dailyRevenue, + totalFees: totalRevenue, + }; +}; + +const config: { + [chain: string]: { FRAX: string; amos: string[]; graph: string }; +} = { + [CHAIN.ETHEREUM]: { + FRAX: "0x853d955aCEf822Db058eb8505911ED77F175b99e", + graph: + sdk.graph.modifyEndpoint('5pkNZTvdKuik24p8xtHctfaHcmNghNqb4ANo2BfQVefZ'), + amos: [ + // '0x49ee75278820f409ecd67063D8D717B38d66bd71', // curve + // '0x629C473e0E698FD101496E5fbDA4bcB58DA78dC4', // twaamm + // '0x452420df4AC1e3db5429b5FD629f3047482C543C', // fxb + "0x0Ed8fA7FC63A8eb5487E7F87CAF1aB3914eA4eCa", // v1 + "0xf6E697e95D4008f81044337A749ECF4d15C30Ea6", // v3 + ], + }, + [CHAIN.ARBITRUM]: { + FRAX: "0x17FC002b466eEc40DaE837Fc4bE5c67993ddBd6F", + graph: + sdk.graph.modifyEndpoint('4zJMfZFyGvqbKyyyeVs4qE15BaEuwr5DLLZiSLhJzBNs'), + amos: [ + "0xCDeE1B853AD2E96921250775b7A60D6ff78fD8B4", // v3 + ], + }, +}; + +const adapter: SimpleAdapter = { + adapter: Object.keys(config).reduce((acc, chain) => { + return { + ...acc, + [chain]: { + fetch, + start: 0, + }, + }; + }, {}), + version: 2, +}; + +export default adapter; diff --git a/fees/frax-ether.ts b/fees/frax-ether.ts index 1beef4a638..9e20fd914f 100644 --- a/fees/frax-ether.ts +++ b/fees/frax-ether.ts @@ -1,9 +1,9 @@ -import { Adapter, FetchOptions, FetchResultFees } from "../adapters/types"; +import { Adapter, FetchOptions } from "../adapters/types"; import { CHAIN } from "../helpers/chains"; import { queryIndexer } from "../helpers/indexer"; const fetch = (): any => { - return async (timestamp: number, _: any, options: FetchOptions): Promise => { + return async (options: FetchOptions) => { const dailyFees = options.createBalances(); const logs = await queryIndexer(` @@ -32,7 +32,6 @@ const fetch = (): any => { return { - timestamp, dailyFees, dailySupplySideRevenue: dailySupplySideRevenue, dailyRevenue: dailyRevenue, @@ -44,6 +43,7 @@ const fetch = (): any => { } const adapter: Adapter = { + version: 2, adapter: { [CHAIN.ETHEREUM]: { fetch: fetch(), diff --git a/fees/frax-fpi.ts b/fees/frax-fpi.ts index eececda1d9..8d5f0eb779 100644 --- a/fees/frax-fpi.ts +++ b/fees/frax-fpi.ts @@ -37,6 +37,7 @@ const fetch = async (timestamp: number) => { } const adapter: Adapter = { + version: 1, adapter: { [CHAIN.ETHEREUM]: { fetch: fetch, diff --git a/fees/frax-swap.ts b/fees/frax-swap.ts index 662e102815..31bba23f77 100644 --- a/fees/frax-swap.ts +++ b/fees/frax-swap.ts @@ -1,6 +1,5 @@ import { CHAIN } from "../helpers/chains"; import { Chain } from "@defillama/sdk/build/general"; -import type { ChainEndpoints } from "../adapters/types" import fetchURL from "../utils/fetchURL"; import { Adapter } from "../adapters/types"; import { getUniqStartOfTodayTimestamp } from "../helpers/getUniSubgraphFees"; @@ -68,6 +67,7 @@ const methodology = { } const adapter: Adapter = { + version: 1, adapter: { [CHAIN.ARBITRUM]: { fetch: graphs()(CHAIN.ARBITRUM), diff --git a/fees/friend-room.ts b/fees/friend-room.ts index beaea95c3e..16f29fcce9 100644 --- a/fees/friend-room.ts +++ b/fees/friend-room.ts @@ -11,7 +11,8 @@ const adapter: Adapter = { fetch: getFeesExport(friendRoomSharesAddress, [event_trade]), start: 1693731179, }, - } + }, + version: 2, } export default adapter; diff --git a/fees/friend-tech.ts b/fees/friend-tech.ts index db6dca608c..0cec6ab876 100644 --- a/fees/friend-tech.ts +++ b/fees/friend-tech.ts @@ -1,14 +1,30 @@ -import { Adapter,} from "../adapters/types"; -import { getFeesExport } from "../helpers/friend-tech"; +import { Adapter, FetchV2, } from "../adapters/types"; import { CHAIN } from "../helpers/chains"; const adapter: Adapter = { adapter: { [CHAIN.BASE]: { - fetch: getFeesExport('0xcf205808ed36593aa40a44f10c7f7c2f67d4a4d4'), + fetch: (async ({ getLogs, createBalances, }) => { + const dailyFees = createBalances() + const dailyRevenue = createBalances() + const logs = await getLogs({ target: "0xcf205808ed36593aa40a44f10c7f7c2f67d4a4d4", eventAbi: 'event Trade(address trader, address subject, bool isBuy, uint256 shareAmount, uint256 ethAmount, uint256 protocolEthAmount, uint256 subjectEthAmount, uint256 supply)' }) + logs.map((e: any) => { + dailyFees.addGasToken(e.protocolEthAmount) + dailyRevenue.addGasToken(e.protocolEthAmount) + dailyFees.addGasToken(e.subjectEthAmount) + }) + const clubBuy = await getLogs({ target: "0x201e95f275f39a5890c976dc8a3e1b4af114e635", eventAbi: 'event Buy(uint256 indexed id, uint256 indexed pointsIn, uint256 indexed keysOut, uint256 protocolFee)' }) + const clubSell = await getLogs({ target: "0x201e95f275f39a5890c976dc8a3e1b4af114e635", eventAbi: 'event Sell(uint256 indexed id, uint256 indexed pointsOut, uint256 indexed keysIn, uint256 protocolFee)' }) + clubBuy.concat(clubSell).map(e=>{ + dailyFees.add("0x0bd4887f7d41b35cd75dff9ffee2856106f86670", e.protocolFee * BigInt(2)) + dailyRevenue.add("0x0bd4887f7d41b35cd75dff9ffee2856106f86670", e.protocolFee) + }) + return { dailyFees, dailyRevenue, } + }) as FetchV2, start: 1691539200, }, - } + }, + version: 2, } export default adapter; \ No newline at end of file diff --git a/fees/friend3.ts b/fees/friend3.ts index 63d374e28b..8f527504de 100644 --- a/fees/friend3.ts +++ b/fees/friend3.ts @@ -18,7 +18,8 @@ const adapter: Adapter = { fetch: getFeesExport(FriendV2Address, [event_trade_V2]), start: 1698710400, }, - } + }, + version: 2, } export default adapter; diff --git a/fees/fulcrom-finance.ts b/fees/fulcrom-finance.ts index 9ac49a5cea..dc05ba8d20 100644 --- a/fees/fulcrom-finance.ts +++ b/fees/fulcrom-finance.ts @@ -9,6 +9,7 @@ const endpoints = { "https://graph.cronoslabs.com/subgraphs/name/fulcrom/stats-prod", [CHAIN.ERA]: "https://api.studio.thegraph.com/query/52869/stats-prod/version/latest", + [CHAIN.CRONOS_ZKEVM]: "https://api.goldsky.com/api/public/project_clwrfupe2elf301wlhnd7bvva/subgraphs/fulcrom-stats-mainnet/prod/gn" }; const methodology = { @@ -83,6 +84,7 @@ const graphs = (graphUrls: ChainEndpoints) => { }; const adapter: Adapter = { + version: 1, adapter: { [CHAIN.CRONOS]: { fetch: graphs(endpoints)(CHAIN.CRONOS), @@ -98,6 +100,13 @@ const adapter: Adapter = { methodology, }, }, + [CHAIN.CRONOS_ZKEVM]: { + fetch: graphs(endpoints)(CHAIN.CRONOS_ZKEVM), + start: 1723698700, + meta: { + methodology, + }, + }, }, }; diff --git a/fees/furucombo/index.ts b/fees/furucombo/index.ts index 7c8798d662..20609dd3e7 100644 --- a/fees/furucombo/index.ts +++ b/fees/furucombo/index.ts @@ -1,29 +1,27 @@ -import { Adapter, FetchResultFees } from "../../adapters/types"; +import { Adapter, FetchOptions } from "../../adapters/types"; import { CHAIN } from "../../helpers/chains"; import fetchURL from "../../utils/fetchURL"; -import { getTimestampAtStartOfDayUTC } from "../../utils/date"; function fetch(chainId: number) { - return async (timestamp: number): Promise => { - const timestampToday = getTimestampAtStartOfDayUTC(timestamp); + return async ({ endTimestamp }: FetchOptions) => { const resp: { totalFees: string; dailyFees: string; } = await fetchURL( - `https://api.furucombo.app/v1/defillama/${chainId}/fees?timestamp=${timestampToday}` + `https://api.furucombo.app/v1/defillama/${chainId}/fees?timestamp=${endTimestamp}` ); return { ...resp, totalRevenue: resp.totalFees, dailyRevenue: resp.dailyFees, - timestamp, }; }; } const adapter: Adapter = { + version: 2, adapter: { [CHAIN.ETHEREUM]: { fetch: fetch(1), diff --git a/fees/fvm-exchange.ts b/fees/fvm-exchange.ts index c878c87c51..ffc61b8436 100644 --- a/fees/fvm-exchange.ts +++ b/fees/fvm-exchange.ts @@ -1,4 +1,4 @@ -import { ChainBlocks, FetchOptions, FetchResultFees, SimpleAdapter } from "../adapters/types"; +import { FetchOptions, SimpleAdapter } from "../adapters/types"; import { CHAIN } from "../helpers/chains"; const FACTORY_ADDRESS = "0x472f3C3c9608fe0aE8d702f3f8A2d12c410C881A"; @@ -10,7 +10,7 @@ const ABIs: TABI = { "allPairs": "function allPairs(uint256) view returns (address)" } -const fetch = async (timestamp: number, _: ChainBlocks, { createBalances, getLogs, api }: FetchOptions): Promise => { +const fetch = async ({ createBalances, getLogs, api }: FetchOptions) => { const dailyFees = createBalances() const lpTokens = await api.fetchList({ lengthAbi: ABIs.allPairsLength, itemAbi: ABIs.allPairs, target: FACTORY_ADDRESS }); @@ -23,11 +23,11 @@ const fetch = async (timestamp: number, _: ChainBlocks, { createBalances, getLog dailyFees: dailyFees, dailyRevenue: dailyFees, dailyHoldersRevenue: dailyFees, - timestamp, }; }; const adapter: SimpleAdapter = { + version: 2, adapter: { [CHAIN.FANTOM]: { fetch, diff --git a/fees/fwx-dex/index.ts b/fees/fwx-dex/index.ts new file mode 100644 index 0000000000..636537711d --- /dev/null +++ b/fees/fwx-dex/index.ts @@ -0,0 +1,80 @@ +import * as sdk from "@defillama/sdk"; +import { CHAIN } from "../../helpers/chains"; +import { univ2DimensionAdapter2 } from "../../helpers/getUniSubgraph"; +import { SimpleAdapter } from "../../adapters/types"; + +const chainConfigs = { + [CHAIN.AVAX]: { + graphUrl: + "https://subgraphs.fwx.finance/avac/subgraphs/name/fwx-exchange-avac", + feesPercent: { + UserFees: 0.1, + Fees: 0.1, + SupplySideRevenue: 0.075, + ProtocolRevenue: 0.025, + Revenue: 0.025, + }, + methodology: { + UserFees: "User pays 0.1% fees on each swap", + Fees: "A 0.1% of each swap is collected as trading fees", + SupplySideRevenue: + "A 0.075% from each swap is distributed to liquidity providers", + ProtocolRevenue: "A 0.025% fees goes to FWX treasury", + Revenue: "Governance revenue is 0.025% trading fees", + }, + start: 1717632000, + }, + [CHAIN.BASE]: { + graphUrl: + "https://subgraphs.fwx.finance/base/subgraphs/name/fwx-exchange-base-prod", + feesPercent: { + UserFees: 0.25, + Fees: 0.25, + SupplySideRevenue: 0.20833, + ProtocolRevenue: 0.04167, + Revenue: 0.04167, + }, + methodology: { + UserFees: "User pays 0.25% fees on each swap", + Fees: "A 0.25% of each swap is collected as trading fees", + SupplySideRevenue: + "A 0.20833% from each swap is distributed to liquidity providers", + ProtocolRevenue: "A 0.04167% fees goes to FWX treasury", + Revenue: "Governance revenue is 0.04167% trading fees", + }, + start: 1725408000, + }, +}; + +const adapters: SimpleAdapter = { + adapter: {}, + version: 2, +}; + +Object.entries(chainConfigs).reduce((acc, [chain, value]) => { + adapters.adapter[chain] = { + ...univ2DimensionAdapter2( + { + graphUrls: { + [chain]: sdk.graph.modifyEndpoint(value.graphUrl), + }, + dailyVolume: { + factory: "pancakeDayData", + }, + totalVolume: { + factory: "pancakeDayDatas", + filterParams: [{ + name: "id", + type: "Int" + }] + }, + feesPercent: { ...value.feesPercent, type: "volume" }, + }, + { methodology: value.methodology } + ).adapter[chain], + start: value.start, + }; + return acc; +}, {} as SimpleAdapter); + +export default adapters; diff --git a/fees/fwx/index.ts b/fees/fwx/index.ts index 947c75c02c..feea4a5a05 100644 --- a/fees/fwx/index.ts +++ b/fees/fwx/index.ts @@ -4,34 +4,28 @@ import { CHAIN } from "../../helpers/chains"; import { getUniqStartOfTodayTimestamp } from "../../helpers/getUniSubgraphVolume"; import { httpPost } from "../../utils/fetchURL"; -interface IEndpoint { - dailyFees: string; - realtimeCompanyRevenue: string; -} - interface IDailyFeeData { - claimable_token_interest: string; - held_token_interest: string; - fee_profit: string; - fee_auction: string; - daily_revenue: string; - daily_fees: string; + daily_interest_paid: string; + daily_trading_fee: string; + daily_otf_fee: string; + daily_bounty_fee_to_protocol: string; + daily_bounty_fee_to_liquidator: string; + daily_liquidation_fee: string; + total_interest_paid: string; + total_trading_fee: string; + total_otf_fee: string; + total_bounty_fee_to_protocol: string; + total_bounty_fee_to_liquidator: string; + total_liquidation_fee: string; } -interface ICompanyRevenue { - total_claimable_token_interest: string; - total_held_token_interest: string; - total_fee_profit: string; - total_fee_auction: string; - total_revenue: string; - total_fees: string; -} +const endpoints = { + dailyFees: "https://analytics.fwx.finance/api/fees", +}; -const endpoints: Record = { - [CHAIN.AVAX]: { - dailyFees: "https://app.fwx.finance/api/43114/v1/dashboard/daily-fees", - realtimeCompanyRevenue: "https://app.fwx.finance/api/43114/v1/realtime/company-revenue", - }, +const CHAIN_ID = { + [CHAIN.AVAX]: 43114, + [CHAIN.BASE]: 8453, }; const fetch = (chain: Chain) => { @@ -43,20 +37,99 @@ const fetch = (chain: Chain) => { const formattedDate = date.toISOString().replace(/\.(\d{3})Z$/, ".$1Z"); // * call api for daily fees and revenue - const dailyRes = await httpPost(endpoints[chain].dailyFees, { date: formattedDate }); - const dailyData = dailyRes as IDailyFeeData; + const marginTradeRes = await httpPost(endpoints.dailyFees, { + date: formattedDate, + chain_id: CHAIN_ID[chain], + is_perp: false, + }); + const marginTradeResData = marginTradeRes as IDailyFeeData; - // * call api for realtime total fees and revenue - const realtimeRes = await httpPost(endpoints[chain].realtimeCompanyRevenue, {}); - const realtimeData = realtimeRes as ICompanyRevenue; + const perpRes = await httpPost(endpoints.dailyFees, { + date: formattedDate, + chain_id: CHAIN_ID[chain], + is_perp: true, + }); + const perpResData = perpRes as IDailyFeeData; + + const dailyInterestPaid = + parseFloat(marginTradeResData.daily_interest_paid) + + parseFloat(perpResData.daily_interest_paid); + const dailyTradingFee = + parseFloat(marginTradeResData.daily_trading_fee) + + parseFloat(perpResData.daily_trading_fee); + const dailyOtfFee = + parseFloat(marginTradeResData.daily_otf_fee) + + parseFloat(perpResData.daily_otf_fee); + const dailyBountyFeeToProtocol = + parseFloat(marginTradeResData.daily_bounty_fee_to_protocol) + + parseFloat(perpResData.daily_bounty_fee_to_protocol); + const dailyBountyFeeToLiquidator = + parseFloat(marginTradeResData.daily_bounty_fee_to_liquidator) + + parseFloat(perpResData.daily_bounty_fee_to_liquidator); + const dailyLiquidationFee = + parseFloat(marginTradeResData.daily_liquidation_fee) + + parseFloat(perpResData.daily_liquidation_fee); + const totalInterestPaid = + parseFloat(marginTradeResData.total_interest_paid) + + parseFloat(perpResData.total_interest_paid); + const totalTradingFee = + parseFloat(marginTradeResData.total_trading_fee) + + parseFloat(perpResData.total_trading_fee); + const totalOtfFee = + parseFloat(marginTradeResData.total_otf_fee) + + parseFloat(perpResData.total_otf_fee); + const totalBountyFeeToProtocol = + parseFloat(marginTradeResData.total_bounty_fee_to_protocol) + + parseFloat(perpResData.total_bounty_fee_to_protocol); + const totalBountyFeeToLiquidator = + parseFloat(marginTradeResData.total_bounty_fee_to_liquidator) + + parseFloat(perpResData.total_bounty_fee_to_liquidator); + const totalLiquidationFee = + parseFloat(marginTradeResData.total_liquidation_fee) + + parseFloat(perpResData.total_liquidation_fee); + + // daily + const dailyFees = + dailyInterestPaid + + dailyTradingFee + + dailyLiquidationFee + + dailyBountyFeeToLiquidator + + dailyBountyFeeToProtocol + + dailyOtfFee; + const dailySupplySideRevenue = + 0.1 * dailyInterestPaid + + 0.8 * dailyTradingFee + + dailyBountyFeeToProtocol + + dailyOtfFee; + const dailyProtocolRevenue = + 0.9 * dailyInterestPaid + 0.2 * dailyTradingFee; + + // total + const totalFees = + totalInterestPaid + + totalTradingFee + + totalLiquidationFee + + totalBountyFeeToLiquidator + + totalBountyFeeToProtocol + + totalOtfFee; + const totalSupplySideRevenue = + 0.1 * totalInterestPaid + + 0.8 * totalTradingFee + + totalBountyFeeToProtocol + + totalOtfFee; + const totalProtocolRevenue = + 0.9 * totalInterestPaid + 0.2 * totalTradingFee; return { timestamp, - dailyFees: dailyData.daily_fees, - dailyRevenue: dailyData.daily_revenue, - dailySupplySideRevenue: dailyData.claimable_token_interest, - totalFees: realtimeData.total_fees, - totalRevenue: realtimeData.total_revenue, + dailyFees: dailyFees, + dailyRevenue: dailyProtocolRevenue + dailySupplySideRevenue, + dailyProtocolRevenue: dailyProtocolRevenue, + dailySupplySideRevenue: dailySupplySideRevenue, + totalFees: totalFees, + totalRevenue: totalProtocolRevenue + totalSupplySideRevenue, + totalProtocolRevenue: totalProtocolRevenue, + totalSupplySideRevenue: totalSupplySideRevenue, }; }; }; @@ -67,6 +140,11 @@ const adapter: Adapter = { fetch: fetch(CHAIN.AVAX), start: 1701907200, }, + [CHAIN.BASE]: { + fetch: fetch(CHAIN.BASE), + start: 1725408000, + }, }, + version: 1, }; export default adapter; diff --git a/fees/fx-protocol.ts b/fees/fx-protocol.ts new file mode 100644 index 0000000000..fa3a88bb3f --- /dev/null +++ b/fees/fx-protocol.ts @@ -0,0 +1,58 @@ +import * as sdk from "@defillama/sdk"; +import { Adapter } from "../adapters/types"; +import { ETHEREUM } from "../helpers/chains"; +import { request } from "graphql-request"; +import type { + ChainBlocks, + ChainEndpoints, + FetchOptions, +} from "../adapters/types"; +import { Chain } from "@defillama/sdk/build/general"; + +const endpoints = { + [ETHEREUM]: + sdk.graph.modifyEndpoint('CCaEZU1PJyNaFmEjpyc4AXUiANB6M6DGDCJuWa48JWTo'), +}; + +const graph = (graphUrls: ChainEndpoints) => { + return (chain: Chain) => { + return async ( + _timestamp: number, + _: ChainBlocks, + { createBalances, startOfDay }: FetchOptions + ) => { + let dailyRevenue = createBalances(); + const dateId = Math.floor(startOfDay); + + const graphQuery = `{ dailyRevenueSnapshot(id: ${dateId}) { wstETHRevenue } }`; + + const { dailyRevenueSnapshot: snapshot } = await request( + graphUrls[chain], + graphQuery + ); + + if (!snapshot) { + dailyRevenue.addCGToken("wrapped-steth", 0); + } else { + dailyRevenue.addCGToken("wrapped-steth", snapshot.wstETHRevenue * 1e18); + } + + + const usd = await dailyRevenue.getUSDValue(); + const revenue = (usd / 1e18).toFixed(0); + const dailyFees = (usd / 0.75 / 1e18).toFixed(0); + return { timestamp: startOfDay, dailyFees, dailyRevenue: revenue }; + }; + }; +}; + +const adapter: Adapter = { + adapter: { + [ETHEREUM]: { + fetch: graph(endpoints)(ETHEREUM), + start: 1700524800, + }, + }, +}; + +export default adapter; diff --git a/fees/gains-network.ts b/fees/gains-network.ts index 40f057c386..f836779433 100644 --- a/fees/gains-network.ts +++ b/fees/gains-network.ts @@ -19,6 +19,16 @@ const event: string[] = [ "event BorrowingFeeCharged(address indexed trader, uint tradeValueDai, uint valueDai)", ]; +const eventV8: string[] = [ + "event GovFeeCharged(address indexed trader, uint8 indexed collateralIndex, uint256 amountCollateral)", + "event ReferralFeeCharged(address indexed trader, uint8 indexed collateralIndex, uint256 amountCollateral)", + "event TriggerFeeCharged(address indexed trader, uint8 indexed collateralIndex, uint256 amountCollateral)", + "event GnsStakingFeeCharged(address indexed trader, uint8 indexed collateralIndex, uint256 amountCollateral)", + "event GTokenFeeCharged(address indexed trader, uint8 indexed collateralIndex, uint256 amountCollateral)", + "event BorrowingFeeCharged(address indexed trader, uint8 indexed collateralIndex, uint256 amountCollateral)", +]; + +// Pre-v8 const addressConfig: { [a: string]: string } = { "0x82e59334da8c667797009bbe82473b55c7a6b311": ADDRESSES.polygon.DAI, "0x0bbed2eac3237ba128643670b7cf3be475933755": ADDRESSES.polygon.WETH, @@ -28,37 +38,67 @@ const addressConfig: { [a: string]: string } = { "0x4542256c583bcad66a19a525b57203773a6485bf": ADDRESSES.arbitrum.USDC_CIRCLE, }; +// Post-v8 +const collateralIndexMap: { [s: string | Chain]: { [a: number]: string } } = { + [CHAIN.POLYGON]: { 1: ADDRESSES.polygon.DAI, 2: ADDRESSES.polygon.WETH, 3: ADDRESSES.polygon.USDC_CIRCLE }, + [CHAIN.ARBITRUM]: { 1: ADDRESSES.arbitrum.DAI, 2: ADDRESSES.arbitrum.WETH, 3: ADDRESSES.arbitrum.USDC_CIRCLE }, + [CHAIN.BASE]: { 1: ADDRESSES.base.USDC }, +}; + const contract_addresses: IAddresses = { [CHAIN.POLYGON]: [ "0x82e59334da8c667797009bbe82473b55c7a6b311", // DAI TradingCallbacks "0x0bbed2eac3237ba128643670b7cf3be475933755", // ETH TradingCallbacks "0x2ac6749d0affd42c8d61ef25e433f92e375a1aef", // USDC TradingCallbacks + "0x209a9a01980377916851af2ca075c2b170452018", // v8 Diamond ], [CHAIN.ARBITRUM]: [ "0x298a695906e16aea0a184a2815a76ead1a0b7522", // DAI TradingCallbacks "0x62a9f50c92a57c719ff741133caa55c7a81ce019", // ETH TradingCallbacks "0x4542256c583bcad66a19a525b57203773a6485bf", // USDC TradingCallbacks + "0xff162c694eaa571f685030649814282ea457f169", // v8 Diamond + ], + [CHAIN.BASE]: [ + "0x6cD5aC19a07518A8092eEFfDA4f1174C72704eeb", // v9.3 Diamond ], }; const fetch = (chain: Chain) => { - return async (timestamp: number, _: ChainBlocks, { createBalances, getLogs, }: FetchOptions): Promise => { - const dailyFees = createBalances() - const dailyRevenue = createBalances() - const dailyHoldersRevenue = createBalances() + return async (timestamp: number, _: ChainBlocks, { createBalances, getLogs }: FetchOptions): Promise => { + const collateralIndexToToken = collateralIndexMap[chain]; + const dailyFees = createBalances(); + const dailyRevenue = createBalances(); + const dailyHoldersRevenue = createBalances(); for (const target of contract_addresses[chain]) { - const token = addressConfig[target] - const [ - devFee, ssFee, referralFee, nftBotFee, daiVault, lpFee, triggerFee, govFee, borrowingFee, - ]: any = await Promise.all(event.map((eventAbi) => getLogs({ target, eventAbi }))); + const token = addressConfig[target]; + + // pre-v8 + if (token) { + const [devFee, ssFee, referralFee, nftBotFee, daiVault, lpFee, triggerFee, govFee, borrowingFee]: any = await Promise.all( + event.map((eventAbi) => getLogs({ target, eventAbi })) + ); - [devFee, ssFee, referralFee, nftBotFee, daiVault, lpFee, triggerFee, govFee, borrowingFee,].flat().forEach((i: any) => dailyFees.add(token, i.valueDai)); - [devFee, ssFee, govFee,].flat().forEach((i: any) => dailyRevenue.add(token, i.valueDai)); - ssFee.forEach((i: any) => dailyHoldersRevenue.add(token, i.valueDai)); + [devFee, ssFee, referralFee, nftBotFee, daiVault, lpFee, triggerFee, govFee, borrowingFee] + .flat() + .forEach((i: any) => dailyFees.add(token, i.valueDai)); + [devFee, ssFee, govFee].flat().forEach((i: any) => dailyRevenue.add(token, i.valueDai)); + ssFee.forEach((i: any) => dailyHoldersRevenue.add(token, i.valueDai)); + } else { + // v8 + const [govFee, referralFee, triggerFee, stakingFee, gTokenFee, borrowingFee]: any = await Promise.all( + eventV8.map((eventAbi) => getLogs({ target, eventAbi })) + ); + + [govFee, referralFee, triggerFee, stakingFee, gTokenFee, borrowingFee] + .flat() + .forEach((i: any) => dailyFees.add(collateralIndexToToken[i.collateralIndex], i.amountCollateral)); + [govFee, stakingFee].flat().forEach((i: any) => dailyRevenue.add(collateralIndexToToken[i.collateralIndex], i.amountCollateral)); + stakingFee.forEach((i: any) => dailyHoldersRevenue.add(collateralIndexToToken[i.collateralIndex], i.amountCollateral)); + } } - return { timestamp, dailyFees, dailyRevenue, dailyHoldersRevenue, } + return { timestamp, dailyFees, dailyRevenue, dailyHoldersRevenue }; }; }; @@ -72,6 +112,10 @@ const adapter: Adapter = { fetch: fetch(CHAIN.ARBITRUM), start: 1672358400, }, + [CHAIN.BASE]: { + fetch: fetch(CHAIN.BASE), + start: 1727351131, + }, }, }; diff --git a/fees/gambit.ts b/fees/gambit.ts index fc5b452e0d..f6a4e7db24 100644 --- a/fees/gambit.ts +++ b/fees/gambit.ts @@ -22,11 +22,13 @@ const FEE_ADDRESS = { "0x50853A14cD14CC6A891BF034A204A15d294AF056", "0x240d75373f9941b8F7FbA660b9ae73dfa655f7Da", // v1.3.4 "0x43c1cc807Dc22bCF7C789eDE4d1B4828C87A06D1", // v1.5.1 + "0x3bEa4Af64689ce3429D312cf205312842C944DeE", // v1.6.0 ], [CHAIN.ARBITRUM]: [ "0x8d85f4615ea5F2Ea8D91C196aaD4C04D8416865C", "0xB88C3A703B3565cb7bfdB1806Ba3728C54dd4b91", // v1.3.1 "0x77233F7F6f11300Fd30B338dA38D96a7bFD5aB86", // v1.5.1 + "0xB4099795021506b67ef974eCb85e10898e2F0D45", // v1.6.0 ], }; diff --git a/fees/gamma.ts b/fees/gamma.ts index 08cadadec7..3d3a253ad9 100644 --- a/fees/gamma.ts +++ b/fees/gamma.ts @@ -58,23 +58,23 @@ const fetchFees = (chain: string) => { const adapter: SimpleAdapter = { adapter: { [CHAIN.ETHEREUM]: { - fetch: fetchFees(CHAIN.ETHEREUM), - start: 1682121600, - }, - [CHAIN.ARBITRUM]: { - fetch: fetchFees(CHAIN.ARBITRUM), + fetch: fetchFees("ethereum"), start: 1682121600, }, [CHAIN.POLYGON]: { - fetch: fetchFees(CHAIN.POLYGON), + fetch: fetchFees("polygon"), start: 1682121600, }, [CHAIN.POLYGON_ZKEVM]: { - fetch: fetchFees(CHAIN.POLYGON_ZKEVM), + fetch: fetchFees("polygon_zkevm"), start: 1682121600, }, [CHAIN.OPTIMISM]: { - fetch: fetchFees(CHAIN.OPTIMISM), + fetch: fetchFees("optimism"), + start: 1682121600, + }, + [CHAIN.ARBITRUM]: { + fetch: fetchFees("arbitrum"), start: 1682121600, }, [CHAIN.BSC]: { @@ -85,40 +85,92 @@ const adapter: SimpleAdapter = { fetch: fetchFees("moonbeam"), start: 1682121600, }, + [CHAIN.CELO]: { + fetch: fetchFees("celo"), + start: 1682121600, + }, + [CHAIN.AVAX]: { + fetch: fetchFees("avalanche"), + start: 1682121600, + }, + [CHAIN.FANTOM]: { + fetch: fetchFees("fantom"), + start: 1682121600, + }, + [CHAIN.MANTLE]: { + fetch: fetchFees("mantle"), + start: 1682121600, + }, [CHAIN.ROLLUX]: { - fetch: fetchFees(CHAIN.ROLLUX), + fetch: fetchFees("rollux"), start: 1682121600, }, [CHAIN.LINEA]: { - fetch: fetchFees(CHAIN.LINEA), + fetch: fetchFees("linea"), start: 1682121600, }, - [CHAIN.MANTA]: { - fetch: fetchFees("manta"), + [CHAIN.BASE]: { + fetch: fetchFees("base"), start: 1682121600, }, - [CHAIN.BASE]: { - fetch: fetchFees("base"), + [CHAIN.KAVA]: { + fetch: fetchFees("kava"), start: 1682121600, }, - [CHAIN.AVAX]: { - fetch: fetchFees("avalanche"), + [CHAIN.OP_BNB]: { + fetch: fetchFees("op_bnb"), + start: 1682121600, + }, + [CHAIN.MANTA]: { + fetch: fetchFees("manta"), + start: 1682121600, + }, + [CHAIN.METIS]: { + fetch: fetchFees("metis"), start: 1682121600, }, - [CHAIN.XDAI]: { + [CHAIN.XDAI]: { fetch: fetchFees("gnosis"), start: 1682121600, }, - [CHAIN.MANTLE]: { - fetch: fetchFees("mantle"), + [CHAIN.ASTRZK]: { + fetch: fetchFees("astar_zkevm"), start: 1682121600, }, - [CHAIN.CELO]: { - fetch: fetchFees("celo"), + [CHAIN.IMX]: { + fetch: fetchFees("immutable_zkevm"), start: 1682121600, }, - [CHAIN.METIS]: { - fetch: fetchFees("metis"), + [CHAIN.SCROLL]: { + fetch: fetchFees("scroll"), + start: 1682121600, + }, + [CHAIN.BLAST]: { + fetch: fetchFees("blast"), + start: 1682121600, + }, + [CHAIN.XLAYER]: { + fetch: fetchFees("xlayer"), + start: 1682121600, + }, + [CHAIN.MODE]: { + fetch: fetchFees("mode"), + start: 1682121600, + }, + [CHAIN.TAIKO]: { + fetch: fetchFees("taiko"), + start: 1682121600, + }, + [CHAIN.ROOTSTOCK]: { + fetch: fetchFees("rootstock"), + start: 1682121600, + }, + [CHAIN.SEI]: { + fetch: fetchFees("sei"), + start: 1682121600, + }, + [CHAIN.IOTAEVM]: { + fetch: fetchFees("iota_evm"), start: 1682121600, }, } diff --git a/fees/garden/index.ts b/fees/garden/index.ts index 1cd336e2bf..d203b762e5 100644 --- a/fees/garden/index.ts +++ b/fees/garden/index.ts @@ -1,4 +1,4 @@ -import { FetchResultFees, SimpleAdapter } from "../../adapters/types"; +import { FetchOptions, SimpleAdapter } from "../../adapters/types"; import { CHAIN } from "../../helpers/chains"; import fetchURL from "../../utils/fetchURL"; import BigNumber from "bignumber.js"; @@ -9,26 +9,26 @@ const chainMapper: Record = { [CHAIN.ARBITRUM]: "ethereum_arbitrum", }; -const baseUrl = "http://leaderboard.garden.finance"; +const baseUrl = "https://referral.garden.finance"; const feeUrl = (chain: string, timestamp: number, interval?: string) => `${baseUrl}/fee?chain=${chain}&end=${timestamp}${ interval ? `&interval=${interval}` : "" }`; -type IApiFeeResponse = { +type ApiFeeResponse = { data: { fee: string; }; }; -const fetch = (chain: string) => async (timestamp: number): Promise => { - const dailyFeeResponse: IApiFeeResponse = ( - await fetchURL(feeUrl(chainMapper[chain], timestamp, "day")) +const fetch = (chain: string) => async ({ endTimestamp }: FetchOptions) => { + const dailyFeeResponse: ApiFeeResponse = ( + await fetchURL(feeUrl(chainMapper[chain], endTimestamp, "day")) ); - const totalFeeResponse: IApiFeeResponse = ( - await fetchURL(feeUrl(chainMapper[chain], timestamp)) + const totalFeeResponse: ApiFeeResponse = ( + await fetchURL(feeUrl(chainMapper[chain], endTimestamp)) ); const dailyUserFees = new BigNumber(dailyFeeResponse.data.fee); @@ -39,7 +39,6 @@ const fetch = (chain: string) => async (timestamp: number): Promise async (timestamp: number): Promise { return { ...acc, diff --git a/fees/gaspump/index.ts b/fees/gaspump/index.ts new file mode 100644 index 0000000000..7f7a020294 --- /dev/null +++ b/fees/gaspump/index.ts @@ -0,0 +1,34 @@ +import fetchURL from "../../utils/fetchURL" +import { CHAIN } from "../../helpers/chains"; +import { FetchOptions } from "../../adapters/types"; +import { getPrices } from "../../utils/prices"; + + +const endpoint = "https://api.gas111.com/api/v1/internal/tokens/volume-stats?" + + +const fetch = async (options: FetchOptions) => { + const startTime = new Date(options.startTimestamp * 1000).toISOString().split(".")[0] + const endTime = new Date(options.endTimestamp * 1000).toISOString().split(".")[0] + const res = await fetchURL(`${endpoint}start_date=${startTime}&end_date=${endTime}`) + const TON = "coingecko:the-open-network" + const ton_price = await getPrices([TON], options.startTimestamp); + + return { + dailyFees: parseInt(res.fee_ton) * ton_price[TON].price, + timestamp: options.startTimestamp, + }; +}; + + +const adapter: any = { + version: 2, + adapter: { + [CHAIN.TON]: { + fetch, + start: 1725134400, + }, + }, +}; + +export default adapter; diff --git a/fees/gearbox/index.ts b/fees/gearbox/index.ts index 3e5bf8bfca..a85929b272 100644 --- a/fees/gearbox/index.ts +++ b/fees/gearbox/index.ts @@ -51,7 +51,7 @@ interface ILog { } -const fetch: any = async (timestamp: number, _: any, options: FetchOptions) => { +const fetch: any = async (options: FetchOptions) => { const dailyFees = options.createBalances(); @@ -167,10 +167,11 @@ const fetch: any = async (timestamp: number, _: any, options: FetchOptions) => { }); const dailyRevenue = dailyFees.clone() dailyRevenue.resizeBy(0.5); - return { timestamp, dailyFees, dailyRevenue, }; + return { dailyFees, dailyRevenue, }; }; const adapter: Adapter = { + version: 2, adapter: { [CHAIN.ETHEREUM]: { fetch: fetch, diff --git a/fees/geist-finance/index.ts b/fees/geist-finance/index.ts index ecc3a86874..3a7c7a3608 100644 --- a/fees/geist-finance/index.ts +++ b/fees/geist-finance/index.ts @@ -39,6 +39,7 @@ const graphs = () => { const adapter: Adapter = { + version: 1, adapter: { [DISABLED_ADAPTER_KEY]: disabledAdapter, [FANTOM]: { diff --git a/fees/geodnet.ts b/fees/geodnet.ts new file mode 100644 index 0000000000..0d11debb67 --- /dev/null +++ b/fees/geodnet.ts @@ -0,0 +1,59 @@ +import { FetchOptions, SimpleAdapter } from '../adapters/types'; +import { CHAIN } from '../helpers/chains'; + +const GEODNET_TOKEN_ADDRESS = '0xAC0F66379A6d7801D7726d5a943356A172549Adb'; +const TOPIC_0_EVT_TRANSFER = + '0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef'; +const PADDED_BURN_ADDRESS = + '0x000000000000000000000000000000000000000000000000000000000000dead'; + +interface ILog { + data: string; + transactionHash: string; + topics: string[]; + address: string; +} + +const fetchFees = async ({ getLogs, createBalances }: FetchOptions)=> { + const balances = createBalances(); + + const burnedEventLogs: ILog[] = await getLogs({ + target: GEODNET_TOKEN_ADDRESS, + topics: [TOPIC_0_EVT_TRANSFER, null, PADDED_BURN_ADDRESS] as any, + }) + + burnedEventLogs.forEach((log: ILog) => { + balances.add(GEODNET_TOKEN_ADDRESS, Number(log.data)); + }) + + + const dailyHoldersRevenue = balances + const dailyFees = balances.clone(1/0.8) + const dailyRevenue = dailyFees; + + return { + dailyFees, + dailyRevenue, + dailyHoldersRevenue, + }; +}; + +const adapter: SimpleAdapter = { + version: 2, + adapter: { + [CHAIN.POLYGON]: { + fetch: fetchFees, + start: 1694304000, + meta: { + methodology: { + Fees: 'GEODNET receives fees for station access to their RTK network.', + Revenue: + "When GEODNET receives fees for station access, 80% of the fees are used to repurchase GEOD tokens from the open market and remove them from circulation. The remaining 20% supports the foundation's organizational costs.", + HoldersRevenue: + '80% of the fees are used to repurchase GEOD tokens from the open market and remove them from circulation.', + }, + }, + }, + }, +}; +export default adapter; diff --git a/fees/get-protocol.ts b/fees/get-protocol.ts index 793fd1cdd2..79df0cb7db 100644 --- a/fees/get-protocol.ts +++ b/fees/get-protocol.ts @@ -1,10 +1,11 @@ +import * as sdk from "@defillama/sdk"; import { Adapter, ChainBlocks, FetchOptions } from "../adapters/types"; import { POLYGON } from "../helpers/chains"; import { request, gql } from "graphql-request"; -const PROTOCOL_SUBGRAPH = "https://api.thegraph.com/subgraphs/name/getprotocol/get-protocol-subgraph"; -const TOKEN_SUBGRAPH_POLYGON = "https://api.thegraph.com/subgraphs/name/getprotocol/get-token-polygon"; -const TOKEN_SUBGRAPH_ETHEREUM = "https://api.thegraph.com/subgraphs/name/getprotocol/get-token-ethereum"; +const PROTOCOL_SUBGRAPH = sdk.graph.modifyEndpoint('5CW9dVhyCBHhhxpaEwqtZrfGms3gSYnGQKpqULsu4qSU'); +const TOKEN_SUBGRAPH_POLYGON = sdk.graph.modifyEndpoint('EjxRk3KsW58veQVZaeKNFk9G7qo56hTJh98bcFJEY5HS'); +const TOKEN_SUBGRAPH_ETHEREUM = sdk.graph.modifyEndpoint('HGzbNN7tVyE3eT3uJbZuyMo9Vtf59uAGieLcNXvp94pA'); const PRICE_ID = "get-token"; const sumKeys = (keys: string[], obj: any) => keys.reduce((tally: number, key: string) => tally + (obj[key] || 0), 0); diff --git a/fees/ghostmarket/index.ts b/fees/ghostmarket/index.ts index caf8c94009..7aa7bb9da8 100644 --- a/fees/ghostmarket/index.ts +++ b/fees/ghostmarket/index.ts @@ -1,6 +1,5 @@ import { Adapter, DISABLED_ADAPTER_KEY } from "../../adapters/types"; -import type { ChainEndpoints } from "../../adapters/types" -import { getTimestampAtStartOfDayUTC } from "../../utils/date"; +import type { ChainEndpoints, FetchOptions } from "../../adapters/types" import fetchURL from "../../utils/fetchURL"; import { CHAIN } from "../../helpers/chains"; import disabledAdapter from "../../helpers/disabledAdapter"; @@ -12,6 +11,7 @@ const endpoints = { [CHAIN.POLYGON]: "https://api-external.ghostmarket.io/defillama/fees?chain=polygon×tamp=", [CHAIN.ETHEREUM]: "https://api-external.ghostmarket.io/defillama/fees?chain=eth×tamp=", [CHAIN.PHANTASMA]: "https://api-external.ghostmarket.io/defillama/fees?chain=pha×tamp=", + [CHAIN.BASE]: "https://api-external.ghostmarket.io/defillama/fees?chain=base×tamp=", } const buildUrl = async (apiUrl: string, timestamp: number) => { @@ -29,13 +29,11 @@ const methodology = { const apis = (apiUrls: ChainEndpoints) => { return (chain: CHAIN) => { - return async (timestamp: number) => { - const todaysTimestamp = getTimestampAtStartOfDayUTC(timestamp); - const url = await buildUrl(apiUrls[chain], todaysTimestamp); + return async ({ endTimestamp }: FetchOptions) => { + const url = await buildUrl(apiUrls[chain], endTimestamp); const data = (await fetchURL(url)); return { - timestamp, dailyFees: String(data.dailyFees), totalFees: String(data.userFees), dailyUserFees: String(data.dailyFees), @@ -54,6 +52,7 @@ const apis = (apiUrls: ChainEndpoints) => { }; const adapter: Adapter = { + version: 2, adapter: { [DISABLED_ADAPTER_KEY]: disabledAdapter, [CHAIN.NEO]: { @@ -97,6 +96,13 @@ const adapter: Adapter = { meta: { methodology } + }, + [CHAIN.BASE]: { + fetch: apis(endpoints)(CHAIN.BASE), + start: 1691660245, + meta: { + methodology + } } } } diff --git a/fees/gmx-v2/index.ts b/fees/gmx-v2/index.ts index 96f48c229f..921d669609 100644 --- a/fees/gmx-v2/index.ts +++ b/fees/gmx-v2/index.ts @@ -1,5 +1,5 @@ import { Chain } from "@defillama/sdk/build/general"; -import { Adapter, FetchResultFees } from "../../adapters/types"; +import { Adapter, FetchOptions, FetchResultFees } from "../../adapters/types"; import { CHAIN } from "../../helpers/chains"; import { queryDune } from "../../helpers/dune"; import { getUniqStartOfTodayTimestamp } from "../../helpers/getUniSubgraphVolume"; @@ -12,8 +12,8 @@ interface IFee { } const fetch = (chain: Chain) => { - return async (timestamp: number): Promise => { - const fees: IFee[] = (await queryDune(chain === CHAIN.ARBITRUM ? "3464532" : "3464559")) + return async (timestamp: number, _t: any, _: FetchOptions): Promise => { + const fees: IFee[] = (await queryDune(chain === CHAIN.ARBITRUM ? "3971843" : "3971936")) // const queryId = chain === CHAIN.ARBITRUM ? "3186689" : "3186714"; // const fees: IFee[] = (await fetchURLWithRetry(`https://api.dune.com/api/v1/query/${queryId}/results`)).result.rows; // const fees: IFee[] = require(`./${chain}.json`); @@ -21,7 +21,7 @@ const fetch = (chain: Chain) => { const dateString = new Date(dayTimestamp * 1000).toISOString().split("T")[0]; const daily = fees.find(fee => fee.time.split(' ')[0] === dateString); const dailyFees = daily?.v2_fees || 0 - const total_fees = daily?.total_fees; + const total_fees = daily?.total_fees || 0; return { dailyFees: `${dailyFees}`, dailyRevenue: `${dailyFees * 0.37}`, @@ -34,16 +34,15 @@ const fetch = (chain: Chain) => { }; const adapter: Adapter = { + version: 1, adapter: { [CHAIN.ARBITRUM]: { fetch: fetch(CHAIN.ARBITRUM), start: 1690848000, - runAtCurrTime: true, }, [CHAIN.AVAX]: { fetch: fetch(CHAIN.AVAX), start: 1692835200, - runAtCurrTime: true, }, }, isExpensiveAdapter: true, diff --git a/fees/gmx.ts b/fees/gmx.ts index c12349b003..0ece74762c 100644 --- a/fees/gmx.ts +++ b/fees/gmx.ts @@ -1,11 +1,10 @@ import { Adapter } from "../adapters/types"; import { ARBITRUM, AVAX } from "../helpers/chains"; import { request, gql } from "graphql-request"; -import type { ChainEndpoints } from "../adapters/types" -import { Chain } from '@defillama/sdk/build/general'; +import type { ChainEndpoints, FetchV2 } from "../adapters/types" import { getTimestampAtStartOfDayUTC } from "../utils/date"; -const endpoints = { +const endpoints: any = { [ARBITRUM]: "https://subgraph.satsuma-prod.com/3b2ced13c8d9/gmx/gmx-arbitrum-stats/api", [AVAX]: "https://subgraph.satsuma-prod.com/3b2ced13c8d9/gmx/gmx-avalanche-stats/api" } @@ -19,55 +18,50 @@ const methodology = { ProtocolRevenue: "Treasury has no revenue" } -const graphs = (graphUrls: ChainEndpoints) => { - return (chain: Chain) => { - return async (timestamp: number) => { - const todaysTimestamp = getTimestampAtStartOfDayUTC(timestamp) - const searchTimestamp = chain == "arbitrum" ? todaysTimestamp : todaysTimestamp + ":daily" +const graphs: FetchV2 = async ({ chain, endTimestamp }) => { + const todaysTimestamp = getTimestampAtStartOfDayUTC(endTimestamp) + const searchTimestamp = chain == "arbitrum" ? todaysTimestamp : todaysTimestamp + ":daily" - const graphQuery = gql - `{ - feeStat(id: "${searchTimestamp}") { - mint - burn - marginAndLiquidation - swap - } - }`; - - const graphRes = await request(graphUrls[chain], graphQuery); + const graphQuery = gql + `{ + feeStat(id: "${searchTimestamp}") { + mint + burn + marginAndLiquidation + swap + } + }`; - const dailyFee = parseInt(graphRes.feeStat.mint) + parseInt(graphRes.feeStat.burn) + parseInt(graphRes.feeStat.marginAndLiquidation) + parseInt(graphRes.feeStat.swap) - const finalDailyFee = (dailyFee / 1e30); - const userFee = parseInt(graphRes.feeStat.marginAndLiquidation) + parseInt(graphRes.feeStat.swap) - const finalUserFee = (userFee / 1e30); + const graphRes = await request(endpoints[chain], graphQuery); + const dailyFee = parseInt(graphRes.feeStat.mint) + parseInt(graphRes.feeStat.burn) + parseInt(graphRes.feeStat.marginAndLiquidation) + parseInt(graphRes.feeStat.swap) + const finalDailyFee = (dailyFee / 1e30); + const userFee = parseInt(graphRes.feeStat.marginAndLiquidation) + parseInt(graphRes.feeStat.swap) + const finalUserFee = (userFee / 1e30); - return { - timestamp, - dailyFees: finalDailyFee.toString(), - dailyUserFees: finalUserFee.toString(), - dailyRevenue: (finalDailyFee * 0.3).toString(), - dailyProtocolRevenue: "0", - totalProtocolRevenue: "0", - dailyHoldersRevenue: (finalDailyFee * 0.3).toString(), - dailySupplySideRevenue: (finalDailyFee * 0.7).toString(), - }; + return { + dailyFees: finalDailyFee.toString(), + dailyUserFees: finalUserFee.toString(), + dailyRevenue: (finalDailyFee * 0.3).toString(), + dailyProtocolRevenue: "0", + totalProtocolRevenue: "0", + dailyHoldersRevenue: (finalDailyFee * 0.3).toString(), + dailySupplySideRevenue: (finalDailyFee * 0.7).toString(), }; - }; }; const adapter: Adapter = { + version: 2, adapter: { [ARBITRUM]: { - fetch: graphs(endpoints)(ARBITRUM), + fetch: graphs, start: 1630468800, meta: { methodology } }, [AVAX]: { - fetch: graphs(endpoints)(AVAX), + fetch: graphs, start: 1641445200, meta: { methodology diff --git a/fees/gnd-protocol.ts b/fees/gnd-protocol.ts index 20be25da44..80cac092ed 100644 --- a/fees/gnd-protocol.ts +++ b/fees/gnd-protocol.ts @@ -1,6 +1,6 @@ import ADDRESSES from '../helpers/coreAssets.json' import { Chain } from "@defillama/sdk/build/general"; -import { Adapter, ChainBlocks, FetchOptions, FetchResultFees } from "../adapters/types"; +import { Adapter, FetchOptions } from "../adapters/types"; import { CHAIN } from "../helpers/chains"; import { addTokensReceived } from '../helpers/token'; @@ -13,7 +13,7 @@ const address_buyback: TAddress = { } const fetch = (chain: Chain) => { - return async (timestamp: number, _: ChainBlocks, options: FetchOptions) => { + return async (options: FetchOptions) => { const dividends = await addTokensReceived({ tokens: [ADDRESSES.arbitrum.WETH], options, fromAddressFilter: '0xd70811f1e4992aa051d54e29a04c8925b32fba7d', target: '0x535ec56479892d9c02fe2bb86cebf7ed62e81131' }) const logs_fund_disposit = (await options.getLogs({ @@ -31,7 +31,6 @@ const fetch = (chain: Chain) => { dailyRevenue: dailyRevenue, dailyHoldersRevenue: dailyRevenue, dailySupplySideRevenue: dividends, - timestamp } } } @@ -44,6 +43,7 @@ const methodology = { } const adapter: Adapter = { + version: 2, adapter: { [CHAIN.ARBITRUM]: { fetch: fetch(CHAIN.ARBITRUM), diff --git a/fees/goku-money/index.ts b/fees/goku-money/index.ts index 4134106f9f..c934e8b6a7 100644 --- a/fees/goku-money/index.ts +++ b/fees/goku-money/index.ts @@ -1,8 +1,7 @@ import ADDRESSES from '../../helpers/coreAssets.json' import * as sdk from "@defillama/sdk"; -import { Adapter, ChainBlocks } from "../../adapters/types"; +import { Adapter, FetchOptions } from "../../adapters/types"; import { CHAIN } from "../../helpers/chains"; -import { getBlock } from "../../helpers/getBlock"; import { Chain } from "@defillama/sdk/build/general"; const BORROW_CONTRACT_ADDRESS = [ @@ -38,40 +37,20 @@ const PYTH_CONFIG = { type PYTH_CONFIG_TYPE = typeof PYTH_CONFIG; type PYTH_CONFIG_KEYS = keyof PYTH_CONFIG_TYPE; -const fetchGaiRevenue = async (timestamp: number, balances: sdk.Balances) => { - const fromTimestamp = timestamp - 60 * 60 * 24; - const toTimestamp = timestamp; - - const fromBlock = await getBlock(fromTimestamp, CHAIN.MANTA as Chain, {}); - const toBlock = await getBlock(toTimestamp, CHAIN.MANTA as Chain, {}); - - const logs = await sdk.getEventLogs({ +const fetchGaiRevenue = async (getLogs: any, balances: sdk.Balances) => { + const logs = await getLogs({ targets: BORROW_CONTRACT_ADDRESS, - toBlock: toBlock, - fromBlock: fromBlock, - chain: CHAIN.MANTA as Chain, eventAbi: "event GAIBorrowingFeePaid(address indexed _borrower, uint256 _GAIFee)", - onlyArgs: true, }); logs.forEach(log => balances.add('0xcd91716ef98798A85E79048B78287B13ae6b99b2', log._GAIFee)) }; -const fetchCollateralRedemptionRevenue = async (timestamp: number, balances: sdk.Balances) => { - const fromTimestamp = timestamp - 60 * 60 * 24; - const toTimestamp = timestamp; - - const fromBlock = await getBlock(fromTimestamp, CHAIN.MANTA as Chain, {}); - const toBlock = await getBlock(toTimestamp, CHAIN.MANTA as Chain, {}); - +const fetchCollateralRedemptionRevenue = async (getLogs: any, balances: sdk.Balances) => { for (const token of Object.keys(PYTH_CONFIG) as PYTH_CONFIG_KEYS[]) { const { contractAddress, address, } = PYTH_CONFIG[token]; - const logs = await sdk.getEventLogs({ + const logs = await getLogs({ target: contractAddress, - toBlock: toBlock, - fromBlock: fromBlock, - chain: CHAIN.MANTA as Chain, - onlyArgs: true, eventAbi: "event Redemption(uint256 _attemptedGAIAmount, uint256 _actualGAIAmount, uint256 _COLSent, uint256 _COLFee)", }); @@ -81,16 +60,16 @@ const fetchCollateralRedemptionRevenue = async (timestamp: number, balances: sdk }; const adapter: Adapter = { + version: 2, adapter: { [CHAIN.MANTA]: { - fetch: async (timestamp: number, _: ChainBlocks) => { - const balances = new sdk.Balances({ chain: CHAIN.MANTA as Chain, timestamp }); - await fetchGaiRevenue(timestamp, balances); - await fetchCollateralRedemptionRevenue(timestamp, balances); + fetch: async ({getLogs }: FetchOptions) => { + const balances = new sdk.Balances({ chain: CHAIN.MANTA as Chain }); + await fetchGaiRevenue(getLogs, balances); + await fetchCollateralRedemptionRevenue(getLogs, balances); const totalRevenue = await balances.getUSDString() return { - timestamp, dailyFees: totalRevenue, dailyRevenue: totalRevenue, dailyHoldersRevenue: totalRevenue, diff --git a/fees/goldfinch.ts b/fees/goldfinch.ts index 6278a11d2d..d4446356c8 100644 --- a/fees/goldfinch.ts +++ b/fees/goldfinch.ts @@ -1,35 +1,5 @@ -// contract -// 0xb01b315e32d1d9b5ce93e296d483e1f0aad39e75 -// topic: 0x9bbd517758fbae61197f1c1c04c8614064e89512dbaf4350dcdf76fcaa5e2161 -// poolAmount / 1e6 - -// 0xd20508E1E971b80EE172c73517905bfFfcBD87f9 -// topic: 0x4f2ce4e40f623ca765fc0167a25cb7842ceaafb8d82d3dec26ca0d0e0d2d4896 // poolCreated -// topic: 1 // pool address - -// pool address -// topic: 0xd1055dc2c2a003a83dfacb1c38db776eab5ef89d77a8f05a3512e8cf57f953ce -// (interestAmount - reserveAmount) / 1e6 - -// --- rev -// 0xb01b315e32d1d9b5ce93e296d483e1f0aad39e75 -// topic: 0xf3583f178a8d4f8888c3683f8e948faf9b6eb701c4f1fab265a6ecad1a1ddebb -// amount / 1e6 - -// 0x8481a6ebaf5c7dabc3f7e09e44a89531fd31f822 -// topic: 0xf3583f178a8d4f8888c3683f8e948faf9b6eb701c4f1fab265a6ecad1a1ddebb -// amount / 1e6 - - -// pool address -// topic: 0xf3583f178a8d4f8888c3683f8e948faf9b6eb701c4f1fab265a6ecad1a1ddebb -// amount / 1e6 - -import { FetchResultFees, SimpleAdapter } from "../adapters/types"; +import { FetchOptions, SimpleAdapter } from "../adapters/types"; import { CHAIN } from "../helpers/chains"; -import { getBlock } from "../helpers/getBlock"; -import * as sdk from "@defillama/sdk"; -import { EventLog } from "ethers"; const pools: string[] = [ @@ -69,64 +39,37 @@ const pools: string[] = [ const core_pool = '0xb01b315e32d1d9b5ce93e296d483e1f0aad39e75'; const senior_pool = '0x8481a6ebaf5c7dabc3f7e09e44a89531fd31f822'; -const topic0_interest_collected = '0x9bbd517758fbae61197f1c1c04c8614064e89512dbaf4350dcdf76fcaa5e2161'; -const topic0_payment_appli = '0xd1055dc2c2a003a83dfacb1c38db776eab5ef89d77a8f05a3512e8cf57f953ce'; -const topic0_reserve_fund_collect = '0xf3583f178a8d4f8888c3683f8e948faf9b6eb701c4f1fab265a6ecad1a1ddebb' -const fetchFees = async (timestamp: number): Promise => { - const ONE_DAY_IN_SECONDS = 86400; - const toTimestamp = timestamp; - const fromTimestamp = timestamp - ONE_DAY_IN_SECONDS; - const toBlock = await getBlock(toTimestamp, 'ethereum', {}); - const fromBlock = await getBlock(fromTimestamp, 'ethereum', {}); +const fetchFees = async ({ createBalances, getLogs, }: FetchOptions) => { + const dailyFees = createBalances(); + const dailyRevenue = createBalances(); + const dailySupplySideRevenue = createBalances(); - const logs_interest_collect: EventLog[] = (await sdk.getEventLogs({ + const InterestCollected = (await getLogs({ target: core_pool, - fromBlock: fromBlock, - toBlock: toBlock, - topics: [topic0_interest_collected], - chain: 'ethereum' - })) as EventLog[]; - const pool_interest_collected = logs_interest_collect - .reduce((a: number, b: EventLog) => a + Number('0x' + b.data.replace('0x', '').slice(0, 64)), 0) / 1e6; - - const logs_pool_payment_applie: EventLog[] = (await Promise.all(pools.map(async (pool: string) => sdk.getEventLogs({ - target: pool, - fromBlock: fromBlock, - toBlock: toBlock, - topics: [topic0_payment_appli], - chain: 'ethereum' - })))).flat() as EventLog[]; - - const logs_reserve_fund_collect: EventLog[] = (await Promise.all([...pools, core_pool, senior_pool].map(async (pool: string) => sdk.getEventLogs({ - target: pool, - fromBlock: fromBlock, - toBlock: toBlock, - topics: [topic0_reserve_fund_collect], - chain: 'ethereum' - })))).flat() as EventLog[]; - - const pool_payment_applied = logs_pool_payment_applie.map((log: EventLog) => { - const data = log.data.replace('0x', '') - const interestAmount = Number('0x' + data.slice(0, 64)) / 1e6; - const reserveAmount = Number('0x' + data.slice(64 * 3, (64 * 3) + 64)) / 1e6; - return interestAmount - reserveAmount; - }).reduce((a: number, b: number) => a + b, 0); - - const pool_reserve_fund_collect = logs_reserve_fund_collect.map((log: EventLog) => { - const amount = Number(log.data) / 1e6; - return amount; - }).reduce((a: number, b: number) => a + b, 0); - const dailyFees = pool_interest_collected + pool_payment_applied + pool_reserve_fund_collect; - const dailyRevenue = pool_reserve_fund_collect; - const dailySupplySideRevenue = dailyFees - dailyRevenue; - - return { - dailyFees: dailyFees.toString(), - dailyRevenue: dailyRevenue.toString(), - dailySupplySideRevenue: dailySupplySideRevenue > 0 ? dailySupplySideRevenue.toString() : '0', - timestamp - } + eventAbi: 'event InterestCollected (address indexed payer, uint256 poolAmount, uint256 reserveAmount)' + })) + const PaymentApplied = (await getLogs({ + targets: pools, + eventAbi: 'event PaymentApplied (address indexed payer, address indexed pool, uint256 interestAmount, uint256 principalAmount, uint256 remainingAmount, uint256 reserveAmount)' + })) + const ReserveFundsCollected = (await getLogs({ + targets: pools.concat([core_pool, senior_pool]), + eventAbi: 'event ReserveFundsCollected (address indexed user, uint256 amount)' + })) + InterestCollected.forEach((log: any) => { + dailyFees.addUSDValue(log.poolAmount.toString() / 1e6) + dailySupplySideRevenue.addUSDValue(log.poolAmount.toString() / 1e6) + }); + PaymentApplied.forEach((log: any) => { + dailyFees.addUSDValue((log.interestAmount.toString() - log.reserveAmount.toString()) / 1e6) + dailySupplySideRevenue.addUSDValue((log.interestAmount.toString() - log.reserveAmount.toString()) / 1e6) + }); + ReserveFundsCollected.forEach((log: any) => dailyFees.addUSDValue(log.amount.toString() / 1e6)); + ReserveFundsCollected.forEach((log: any) => dailyRevenue.addUSDValue(log.amount.toString() / 1e6)); + + + return { dailyFees, dailyRevenue, dailySupplySideRevenue } as any } const adapters: SimpleAdapter = { @@ -135,6 +78,7 @@ const adapters: SimpleAdapter = { fetch: fetchFees, start: 1629331200 } - } + }, + version: 2, } export default adapters; diff --git a/fees/goplus.ts b/fees/goplus.ts new file mode 100644 index 0000000000..0192881018 --- /dev/null +++ b/fees/goplus.ts @@ -0,0 +1,61 @@ +import { FetchOptions, SimpleAdapter } from "../adapters/types"; +import { CHAIN } from "../helpers/chains"; +import BigNumber from "bignumber.js"; + +const USDT_MINT = "0x55d398326f99059ff775485246999027b3197955"; +const GOPLUS_FOUNDATION = "0x34ebddd30ccbd3f1e385b41bdadb30412323e34f"; +const GOPLUS_REVENUE_POOL = "0x648d7f4ad39186949e37e9223a152435ab97706c"; + +const BALANCE_ABI = 'erc20:balanceOf'; +const CALLS = [ + { + target: USDT_MINT, + params: [GOPLUS_FOUNDATION] + }, + { + target: USDT_MINT, + params: [GOPLUS_REVENUE_POOL] + }, + ]; + +const fetch = async (options: FetchOptions) => { + const dailyFees = options.createBalances(); + const totalFees = options.createBalances(); + const dailyProtocolRevenue = options.createBalances(); + const totalProtocolRevenue = options.createBalances(); + const [foundationBalanceStart, revenueBalanceStart] = await options.fromApi.multiCall({ + abi: BALANCE_ABI, + calls: CALLS + }); + const [foundationBalanceEnd, revenueBalanceEnd] = await options.toApi.multiCall({ + abi: BALANCE_ABI, + calls: CALLS + }); + const dailyFoundationReceived = BigNumber(foundationBalanceEnd).minus(BigNumber(foundationBalanceStart)); + const dailyRevenueReceived = BigNumber(revenueBalanceEnd).minus(BigNumber(revenueBalanceStart)); + const dailyTotal = dailyFoundationReceived.plus(dailyRevenueReceived).toFixed(0); + const totalFee = BigNumber(foundationBalanceEnd).plus(BigNumber(revenueBalanceEnd)).toFixed(0); + dailyFees.add(USDT_MINT, dailyTotal); + totalFees.add(USDT_MINT, totalFee); + dailyProtocolRevenue.add(USDT_MINT, dailyTotal); + totalProtocolRevenue.add(USDT_MINT, totalFee); + return { dailyFees, totalFees, dailyRevenue: dailyProtocolRevenue, dailyProtocolRevenue, totalProtocolRevenue }; +}; + +const adapter: SimpleAdapter = { + version: 2, + adapter: { + [CHAIN.BSC]: { + fetch: fetch, + start: 1709740800, + meta: { + methodology: { + ProtocolRevenue: "The revenue of the agreement comes from users purchasing security services, and the total cost equals the revenue.", + Fees: "All fees comes from users for security service provided by GoPlus Network." + } + } + }, + }, +}; + +export default adapter; diff --git a/fees/grizzly-trade-derivatives-v2.ts b/fees/grizzly-trade-derivatives-v2.ts new file mode 100644 index 0000000000..c35b728e36 --- /dev/null +++ b/fees/grizzly-trade-derivatives-v2.ts @@ -0,0 +1,60 @@ +import { Chain } from "@defillama/sdk/build/general"; +import { gql, request } from "graphql-request"; +import type { ChainEndpoints } from "../adapters/types"; +import { Adapter } from "../adapters/types"; +import { CHAIN } from "../helpers/chains"; + +import { getTimestampAtStartOfDayUTC } from "../utils/date"; + +const endpoints = { + [CHAIN.BSC]: + "https://api.studio.thegraph.com/query/55804/bnb-trade/version/latest", +}; + +const graphs = (graphUrls: ChainEndpoints) => { + return (chain: Chain) => { + return async (timestamp: number) => { + const todaysTimestamp = getTimestampAtStartOfDayUTC(timestamp); + const period = "daily"; + + const graphQuery = gql`{ + feeStats(where: {timestamp: ${todaysTimestamp}, period: "${period}"}) { + id + timestamp + period + cumulativeFee + cumulativeFeeUsd + feeUsd + } + }`; + + const graphRes = await request(graphUrls[chain], graphQuery); + + const dailyFee = parseInt(graphRes.feeStats[0].feeUsd); + + const finalDailyFee = dailyFee / 1e18; + const totalFees = parseInt(graphRes.feeStats[0].cumulativeFeeUsd) / 1e18; + + return { + timestamp, + dailyFees: finalDailyFee.toString(), + totalFees: totalFees.toString(), + //dailyRevenue: (finalDailyFee * 0.3).toString(), + }; + }; + }; +}; + +const adapter: Adapter = { + adapter: { + [CHAIN.BSC]: { + fetch: graphs(endpoints)(CHAIN.BSC), + start: async () => 1706832000, + meta: { + methodology: "All treasury, pool and keeper fees are collected", + }, + }, + }, +}; + +export default adapter; diff --git a/fees/grizzly-trade.ts b/fees/grizzly-trade.ts index ca8faf7b29..cb9d8fa9ec 100644 --- a/fees/grizzly-trade.ts +++ b/fees/grizzly-trade.ts @@ -1,3 +1,4 @@ +import * as sdk from "@defillama/sdk"; import { Adapter, DISABLED_ADAPTER_KEY } from "../adapters/types"; import { ARBITRUM, AVAX, BSC } from "../helpers/chains"; import { request, gql } from "graphql-request"; @@ -7,7 +8,7 @@ import { getTimestampAtStartOfDayUTC } from "../utils/date"; import disabledAdapter from "../helpers/disabledAdapter"; const endpoints = { - [BSC]: "https://api.thegraph.com/subgraphs/name/metavault-trade/grizzly-bnb-subgraph" + [BSC]: sdk.graph.modifyEndpoint('3CUU9roJ9PsMdijcBdaCBRHhTUBobLeDLyMW4QF2XNmn') } const methodology = { diff --git a/fees/hashnote-usyc/index.ts b/fees/hashnote-usyc/index.ts new file mode 100644 index 0000000000..ba3911a4a4 --- /dev/null +++ b/fees/hashnote-usyc/index.ts @@ -0,0 +1,55 @@ +// https://usyc.hashnote.com/api/price-reports +// https://usyc.hashnote.com/ + +import axios from "axios"; +import { Adapter, FetchOptions, FetchResultFees } from "../../adapters/types"; +import { CHAIN } from "../../helpers/chains"; +import ADDRESSES from "../../helpers/coreAssets.json"; + +type IResponse = { + timestamp: string; + fee: number; +}; + +const url: string = "https://usyc.hashnote.com/api/price-reports"; + +const formatTimestampToISO = (timestamp: number | string): string => { + const date = new Date(Number(timestamp) * 1000); + return date.toISOString().split("T")[0]; +}; + +const formatDatasToISO = (datas: IResponse[]): IResponse[] => { + return datas.map(({ timestamp, fee }) => ({ + timestamp: formatTimestampToISO(timestamp), + fee, + })); +}; + +const fetch = async ( + timestamp: number, + _: any, + { createBalances }: FetchOptions +): Promise => { + const dailyFees = createBalances(); + const response = await axios.get(url); + + const datas = formatDatasToISO(response.data.data); + const isoTimestamp = formatTimestampToISO(timestamp); + + const fees = datas.find(({ timestamp }) => timestamp === isoTimestamp); + if (fees) dailyFees.add(ADDRESSES.ethereum.USDC, Math.round(fees.fee) * 1e6); + + return { timestamp, dailyFees }; +}; + +const adapter: Adapter = { + adapter: { + [CHAIN.ETHEREUM]: { + fetch, + start: 1686693600, + runAtCurrTime: false, + }, + }, +}; + +export default adapter; diff --git a/fees/helio.ts b/fees/helio.ts new file mode 100644 index 0000000000..c31ecca717 --- /dev/null +++ b/fees/helio.ts @@ -0,0 +1,45 @@ +/* +Example swap tx: https://solscan.io/tx/4ZNV9hKmmRch2wiQvoQWuVttTADC38Cf3bSVkyEp8G9uQ1cAzyGgiR6SdPCgWo6sgBVBUuAgYnECrVJ6iZSZtmSM +Helio Fee Account: FudPMePeNqmnjMX19zEKDfGXpbp6HAdW6ZGprB5gYRTZ +Dao Fee Account: JBGUGPmKUEHCpxGGoMowQxoV4c7HyqxEnyrznVPxftqk +*/ + +import { FetchOptions, SimpleAdapter } from "../adapters/types"; +import { CHAIN } from "../helpers/chains"; +import { queryDune } from "../helpers/dune"; + +const solanaDecimals = { + EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v: 6, + Es9vMFrzaCERmJfrF4H2FYD4KCoNkY11McCe8BenwNYB: 6 +} as any + +const fetch: any = async (options: FetchOptions) => { + const receivedTokens = (await queryDune("3996080", { + start: options.startTimestamp, + end: options.endTimestamp, + receiver: 'FudPMePeNqmnjMX19zEKDfGXpbp6HAdW6ZGprB5gYRTZ' + })) as any[] + const dailyFees = options.createBalances(); + receivedTokens.forEach(row=>{ + if(!solanaDecimals[row.token_mint_address]){ + return; // skip unknown tokens + } + dailyFees.add(row.token_mint_address, (row.received * 10**solanaDecimals[row.token_mint_address]).toFixed(0)) + }) + dailyFees.resizeBy(1.11) + + return { dailyFees, dailyRevenue: dailyFees, dailyHoldersRevenue: dailyFees.clone(0.1) } +} + +const adapter: SimpleAdapter = { + version: 2, + adapter: { + [CHAIN.SOLANA]: { + fetch: fetch, + start: 0, + }, + }, + isExpensiveAdapter: true +}; + +export default adapter; diff --git a/fees/hercules-v2.ts b/fees/hercules-v2.ts new file mode 100644 index 0000000000..656fbb3aef --- /dev/null +++ b/fees/hercules-v2.ts @@ -0,0 +1,50 @@ +import { Chain } from "@defillama/sdk/build/general"; +import request from "graphql-request"; +import { FetchV2 } from "../adapters/types"; +import { CHAIN } from "../helpers/chains"; + +type IURL = { + [l: string | Chain]: string; +} + +const endpoints: IURL = { + [CHAIN.METIS]: "https://metisapi.0xgraph.xyz/subgraphs/name/amm-subgraph-andromeda/" +} + +const fetch: FetchV2 = async (options) => { + const { api, getStartBlock, getEndBlock, createBalances } = options + const fromBlock = await getStartBlock() + const toBlock = await getEndBlock() + const graphQuery = (block: any) => ` + { + uniswapFactories(block: { number: ${block}}) { + id + totalFeeUSD + } + } + `; + + const { uniswapFactories: startRes }: any = await request(endpoints[api.chain], graphQuery(fromBlock)) + const { uniswapFactories: endRes }: any = await request(endpoints[api.chain], graphQuery(toBlock)) + + let dailyFees = endRes.reduce((acc: number, val: any) => acc + +val.totalFeeUSD, 0) - startRes.reduce((acc: number, val: any) => acc + +val.totalFeeUSD, 0) + + return { + dailyFees: dailyFees, + dailyUserFees: dailyFees, + dailyRevenue: dailyFees * 0.4, + dailyProtocolRevenue: dailyFees * 0.05, + dailyHoldersRevenue: dailyFees * 0.35, + dailySupplySideRevenue: dailyFees * 0.6, + }; +}; + +const adapter = { fetch, start: 1710115200, } + + +export default { + adapter: { + [CHAIN.METIS]: adapter, + }, + version: 2, +}; diff --git a/fees/hercules-v3.ts b/fees/hercules-v3.ts new file mode 100644 index 0000000000..d63af58a92 --- /dev/null +++ b/fees/hercules-v3.ts @@ -0,0 +1,49 @@ +import { Chain } from "@defillama/sdk/build/general"; +import request from "graphql-request"; +import { FetchV2 } from "../adapters/types"; +import { CHAIN } from "../helpers/chains"; +type IURL = { + [l: string | Chain]: string; +} + +const endpoints: IURL = { + [CHAIN.METIS]: "https://metisapi.0xgraph.xyz/subgraphs/name/cryptoalgebra/analytics" +} + +const fetch: FetchV2 = async (options) => { + const { api, getStartBlock, getEndBlock, createBalances } = options + const fromBlock = await getStartBlock() + const toBlock = await getEndBlock() + const graphQuery = (block: any) => ` + { + factories(block: { number: ${block}}) { + id + totalFeesUSD + } + } + `; + + const { factories: startRes }: any = await request(endpoints[api.chain], graphQuery(fromBlock)) + const { factories: endRes }: any = await request(endpoints[api.chain], graphQuery(toBlock)) + + let dailyFees = endRes.reduce((acc: number, val: any) => acc + +val.totalFeesUSD, 0) - startRes.reduce((acc: number, val: any) => acc + +val.totalFeesUSD, 0) + + return { + dailyFees: dailyFees, + dailyUserFees: dailyFees, + dailyRevenue: dailyFees * 0.15, + dailyProtocolRevenue: dailyFees * 0.03, + dailyHoldersRevenue: dailyFees * 0.12, + dailySupplySideRevenue: dailyFees * 0.85, + }; +}; + +const adapter = { fetch, start: 1698983690, } + + +export default { + adapter: { + [CHAIN.METIS]: adapter, + }, + version: 2, +}; diff --git a/fees/hipo/index.ts b/fees/hipo/index.ts index e9b6fdc6bf..37e486ea4c 100644 --- a/fees/hipo/index.ts +++ b/fees/hipo/index.ts @@ -2,9 +2,10 @@ import { CHAIN } from '../../helpers/chains' import { postURL } from '../../utils/fetchURL' import * as sdk from '@defillama/sdk' -const address = 'EQBNo5qAG8I8J6IxGaz15SfQVB-kX98YhKV_mT36Xo5vYxUa' +const address = 'EQCLyZHP4Xe8fpchQz76O-_RmUhaVc_9BAoGyJrwJrcbz2eZ' export default { + version: 2, adapter: { [CHAIN.TON]: { runAtCurrTime: true, @@ -12,49 +13,42 @@ export default { meta: { hallmarks: [ [1698685200, 'Hipo Launch'], + [1710821940, 'Hipo v2'], ], methodology: { UserFees: 'Stakers pay no fees for using Hipo.', ProtocolRevenue: 'Hipo receives a small fee before distributing rewards to stakers.', SupplySideRevenue: 'Stakers receive the rest of the rewards, after deducting validators share and protocol fee.', - HoldersRevenue: 'Currently there is not government token.', + HoldersRevenue: 'Currently there is no governance token.', Revenue: 'All generated revenue is from protocol fee.', Fees: 'The total reward is calculated after deducting validators share, so it is the stakers revenue plus protocol revenue.', }, }, fetch: async () => { - const response1 = await postURL('https://toncenter.com/api/v2/runGetMethod', { + const getTreasuryState = await postURL('https://toncenter.com/api/v3/runGetMethod', { address, method: 'get_treasury_state', stack: [], }) - if (!response1.ok) { - throw new Error('Error in calling toncenter.com/api/v2/runGetMethod') - } - const getTreasuryState = response1.result if (getTreasuryState.exit_code !== 0) { throw new Error('Expected a zero exit code, but got ' + getTreasuryState.exit_code) } - const response2 = await postURL('https://toncenter.com/api/v2/runGetMethod', { + const getTimes = await postURL('https://toncenter.com/api/v3/runGetMethod', { address, method: 'get_times', stack: [], }) - if (!response2.ok) { - throw new Error('Error in calling toncenter.com/api/v2/runGetMethod') - } - const getTimes = response2.result if (getTimes.exit_code !== 0) { throw new Error('Expected a zero exit code, but got ' + getTimes.exit_code) } - const lastStaked = Number(getTreasuryState.stack[5][1]) - const lastRecovered = Number(getTreasuryState.stack[6][1]) - const governanceFee = Number(getTreasuryState.stack[16][1]) + const lastStaked = Number(getTreasuryState.stack[11].value) + const lastRecovered = Number(getTreasuryState.stack[12].value) + const governanceFee = Number(getTreasuryState.stack[16].value) - const currentRoundSince = Number(getTimes.stack[0][1]) - const nextRoundSince = Number(getTimes.stack[3][1]) + const currentRoundSince = Number(getTimes.stack[0].value) + const nextRoundSince = Number(getTimes.stack[3].value) const duration = nextRoundSince - currentRoundSince const normalize = normalizer(duration) diff --git a/fees/honeyswap.ts b/fees/honeyswap.ts index b2fd033ef1..ff81768b53 100644 --- a/fees/honeyswap.ts +++ b/fees/honeyswap.ts @@ -1,14 +1,11 @@ import { CHAIN } from "../helpers/chains"; -import { univ2DimensionAdapter } from "../helpers/getUniSubgraph"; +import { univ2DimensionAdapter2 } from "../helpers/getUniSubgraph"; -const adapters = univ2DimensionAdapter({ +const adapters = univ2DimensionAdapter2({ graphUrls: { [CHAIN.POLYGON]: " https://api.thegraph.com/subgraphs/name/1hive/honeyswap-polygon", [CHAIN.XDAI]: "https://api.thegraph.com/subgraphs/name/1hive/honeyswap-xdai" }, - dailyVolume: { - factory: "honeyswapDayData" - }, totalVolume: { factory: "honeyswapFactories" }, @@ -34,4 +31,5 @@ const adapters = univ2DimensionAdapter({ adapters.adapter.polygon.start = 1622173831; adapters.adapter.xdai.start = 1599191431; + export default adapters; diff --git a/fees/hono.ts b/fees/hono.ts index 390f39b632..210b2934f6 100644 --- a/fees/hono.ts +++ b/fees/hono.ts @@ -1,3 +1,4 @@ +import * as sdk from "@defillama/sdk"; import { Adapter, FetchResultFees } from "../adapters/types"; import { CHAIN } from "../helpers/chains"; import { request, gql } from "graphql-request"; @@ -10,7 +11,7 @@ interface IData { } const endpoints = { - [CHAIN.ETHEREUM]: "https://api.thegraph.com/subgraphs/name/nuoanunu/defilahma-revenue-hono" + [CHAIN.ETHEREUM]: sdk.graph.modifyEndpoint('7Trkrt6hPzhLXUH2x4Xt9cSnSmAFKDmKNWuUHEwzgCYJ') }; const graph = (graphUrls: ChainEndpoints) => { diff --git a/fees/hopr/index.ts b/fees/hopr/index.ts index 147c07f07a..7c965f85cb 100644 --- a/fees/hopr/index.ts +++ b/fees/hopr/index.ts @@ -1,11 +1,8 @@ import ADDRESSES from '../../helpers/coreAssets.json' -import { Adapter, FetchResultFees } from "../../adapters/types"; +import { Adapter, FetchOptions, } from "../../adapters/types"; import { CHAIN } from "../../helpers/chains"; -import * as sdk from "@defillama/sdk"; import { ethers } from "ethers"; import { getProvider } from "@defillama/sdk/build/general"; -import { getBlock } from "../../helpers/getBlock"; -import { getPrices } from "../../utils/prices"; const channels_address = '0x693Bac5ce61c720dDC68533991Ceb41199D8F8ae'; const wxHOPR_address = ADDRESSES.xdai.XHOPR; @@ -25,77 +22,52 @@ interface ITx { transactionHash: string; } -const fetch = async (timestamp: number): Promise => { +const fetch = async ({ toTimestamp, getLogs, createBalances, }: FetchOptions) => { const provider = getProvider('xdai'); const iface = new ethers.Interface(['function execTransactionFromModule(address to,uint256 value,bytes data,uint8 operation)']) - const fromTimestamp = timestamp - 60 * 60 * 24 - const toTimestamp = timestamp - const fromBlock = (await getBlock(fromTimestamp, CHAIN.XDAI, {})); - const toBlock = (await getBlock(toTimestamp, CHAIN.XDAI, {})); - - const ticketRedeemedLogs: ITx[] = (await sdk.getEventLogs({ + const ticketRedeemedLogs: ITx[] = await getLogs({ target: channels_address, - topic: topic0, - fromBlock: fromBlock, - toBlock: toBlock, - topics: [topic0], - chain: CHAIN.XDAI - }))as ITx[]; + eventAbi: 'event TicketRedeemed (bytes32 indexed channelId, uint48 newTicketIndex)', entireLog: true, + }) + const ticketRedeemedHashSet = new Set(ticketRedeemedLogs.map(ticket => ticket.transactionHash.toLowerCase())); + console.log('ticketRedeemedHashSet', ticketRedeemedHashSet.size); - const batchSize = 4500; - const batches = Math.ceil((toBlock - fromBlock) / batchSize); - const erc20transferLog: ITx[] = await Promise.all( - Array.from({ length: batches }, (_, index) => - sdk.getEventLogs({ - target: wxHOPR_address, - topic: topic1, - toBlock: fromBlock + (index + 1) * batchSize, - fromBlock: fromBlock + index * batchSize, - topics: [topic1, topic2], - chain: CHAIN.XDAI - }) - ) - ).then((responses) => responses.flatMap((response) => response as ITx[])); + const erc20transferLog: ITx[] = await getLogs({ + target: wxHOPR_address, topics: [topic1, topic2], entireLog: true, + eventAbi: 'event Transfer (address indexed from, address indexed to, uint256 value)', + }); + const erc20transferHashSet = new Set(erc20transferLog.map(transaction => transaction.transactionHash.toLowerCase())); + console.log('erc20transferHashSet', erc20transferHashSet.size); + const erc20TransferMap = new Map(erc20transferLog.map(transaction => [transaction.transactionHash.toLowerCase(), transaction.data])); let dailyRevenueStayedInChannelsTXs: string[] = []; const dailyRevenueArrayPaidToSafe = ticketRedeemedLogs.map(ticket => { - const transactionHash = ticket.transactionHash; - const index = erc20transferLog.findIndex(transaction => transaction.transactionHash === transactionHash); - if(index !== -1) { - return erc20transferLog[index].data; - } else { - dailyRevenueStayedInChannelsTXs.push(ticket.transactionHash); - } + const transactionHash = ticket.transactionHash.toLowerCase(); + const data = erc20TransferMap[transactionHash]; + if (data) + return data.args.value + dailyRevenueStayedInChannelsTXs.push(ticket.transactionHash); }).filter(elem => elem !== undefined) as string[]; - const dailyRevenueStayedInChannels = await Promise.all(dailyRevenueStayedInChannelsTXs.map(async(transactionHash) => { + const dailyRevenueStayedInChannels = await Promise.all(dailyRevenueStayedInChannelsTXs.map(async (transactionHash) => { const tx = await provider.getTransaction(transactionHash) as any; const data = tx!.input; const decodedInput = iface.decodeFunctionData('execTransactionFromModule', data) - const hexValue = '0x' + decodedInput[2].substring(138,202); + const hexValue = '0x' + decodedInput[2].substring(138, 202); return hexValue; })); - const dailyRevenue = [...dailyRevenueArrayPaidToSafe, ...dailyRevenueStayedInChannels].map((data: string) => { - const amount = Number(data) / 10 ** 18; - return amount; - }).reduce((a: number, b: number) => a+b,0); - - const prices: any = (await getPrices([`${chain}:${xHOPR_address}`], toTimestamp)); - const price = prices[`${chain}:${xHOPR_address}`]?.price || 0; - const dailyRevenueUSD = dailyRevenue * price; + const dailyRevenue = dailyRevenueArrayPaidToSafe.concat(dailyRevenueStayedInChannels) - return { - timestamp: timestamp, - dailyFees: `${dailyRevenueUSD}`, - dailyUserFees: `${dailyRevenueUSD}`, - dailyRevenue: `${dailyRevenueUSD}` - }; + const dailyFees = createBalances(); + dailyFees.add(xHOPR_address, dailyRevenue); + return { dailyFees, dailyUserFees: dailyFees, dailyRevenue: dailyFees }; } const adapter: Adapter = { + version: 2, adapter: { [CHAIN.XDAI]: { fetch: fetch, diff --git a/fees/houdini-swap.ts b/fees/houdini-swap.ts index 7648272071..d9581075b7 100644 --- a/fees/houdini-swap.ts +++ b/fees/houdini-swap.ts @@ -1,20 +1,11 @@ -import { Chain } from "@defillama/sdk/build/general" +import { Chain } from "@defillama/sdk/build/general"; import { CHAIN } from "../helpers/chains"; import { Adapter, FetchOptions, FetchResultFees } from "../adapters/types"; -import { queryIndexer } from "../helpers/indexer"; +import { addTokensReceived } from "../helpers/token"; const graph = (_chain: Chain): any => { return async (timestamp: number, _: any, options: FetchOptions): Promise => { - const dailyFees = options.createBalances(); - const query = await queryIndexer(` - SELECT value FROM ethereum.transactions - WHERE block_number > 16416220 - and to_address = '\\xc36d36dd4a45f8817a49d3751557fec9871f0e32' - and success = true - and encode(data, 'hex') = '' - AND block_time BETWEEN llama_replace_date_range; - `, options); - query.map((a: any) => dailyFees.addGasToken(a.value)) + const dailyFees = await addTokensReceived({target: '0x45CF73349a4895fabA18c0f51f06D79f0794898D', tokens: ['0x922d8563631b03c2c4cf817f4d18f6883aba0109'], options}) return { dailyFees, dailyRevenue: dailyFees, dailyHoldersRevenue: dailyFees, timestamp } } } diff --git a/fees/hyperionx/index.ts b/fees/hyperionx/index.ts index 89f2a0b9aa..1e8aec403f 100644 --- a/fees/hyperionx/index.ts +++ b/fees/hyperionx/index.ts @@ -1,6 +1,5 @@ -import { Adapter, FetchResultFees } from "../../adapters/types"; +import { Adapter, FetchOptions } from "../../adapters/types"; import { CHAIN } from "../../helpers/chains"; -import { getBlock } from "../../helpers/getBlock"; import { gql, GraphQLClient } from "graphql-request"; import { Chain } from "@defillama/sdk/build/general"; @@ -23,11 +22,9 @@ interface IResponse { const graphs = (chain: Chain) => { - return async (timestamp: number): Promise => { - const toTimestamp = timestamp; - const fromTimestamp = timestamp - 24 * 60 * 60; - const toBlock = (await getBlock(toTimestamp, chain, {})); - const fromBlock = (await getBlock(fromTimestamp, chain, {})); + return async ({ getFromBlock, getToBlock }: FetchOptions) => { + const [fromBlock, toBlock] = await Promise.all([getFromBlock(), getToBlock()]) + const query = gql` { today:protocolMetrics(block:{number:${toBlock}}, where: {id: "1"}){ @@ -47,7 +44,6 @@ const graphs = (chain: Chain) => { const totalFee = Number(response.today[0].totalFee) / 10 ** 6; return { - timestamp, totalFees: totalFee.toString(), dailyFees: dailyFees.toString(), }; @@ -61,6 +57,7 @@ const adapter: Adapter = { start: 1706659200, }, }, + version: 2 }; export default adapter; diff --git a/fees/illuvium.ts b/fees/illuvium.ts new file mode 100644 index 0000000000..993f613312 --- /dev/null +++ b/fees/illuvium.ts @@ -0,0 +1,46 @@ +import { Adapter, FetchOptions, } from '../adapters/types'; +import { CHAIN } from '../helpers/chains'; + +const fetchFees = async (options: FetchOptions) => { + const dailyFees = options.createBalances(); + const end = Date.now() + const start = end - 3600*24*1e3 + let transfers = [] as any[] + let cursor = "" + do{ + const url = `https://api.immutable.com/v1/transfers?receiver=0x2208850ea5569617d5350f8cf681031102c1d931&max_timestamp=${new Date(end).toISOString()}&min_timestamp=${new Date(start).toISOString()}&cursor=${cursor}` + const data = await fetch(url).then(r=>r.json()) + transfers = transfers.concat(data.result) + cursor=data.cursor + } while(cursor !== "") + + const users = new Set() + transfers.forEach(transfer=>{ + if(transfer.token.type === "ETH"){ + users.add(transfer.user) + dailyFees.addCGToken("ethereum", transfer.token.data.quantity/1e18) + } + }) + console.log(Array.from(users).length) + return { + dailyFees, + dailyRevenue: dailyFees, + } +} + +const adapter: Adapter = { + version: 2, + adapter: { + [CHAIN.IMMUTABLEX]: { + fetch: fetchFees, + start: 0, + meta: { + methodology: { + Fees: "ETH paid to purchase fuel", + } + } + }, + }, +} + +export default adapter; diff --git a/fees/immortalx/index.ts b/fees/immortalx/index.ts index a38db987a3..d61388cd97 100644 --- a/fees/immortalx/index.ts +++ b/fees/immortalx/index.ts @@ -1,8 +1,8 @@ +import * as sdk from "@defillama/sdk"; import { Chain } from "@defillama/sdk/build/general"; import request, { gql } from "graphql-request"; -import { Adapter, FetchResultFees } from "../../adapters/types"; +import { Adapter, FetchOptions } from "../../adapters/types"; import { CHAIN } from "../../helpers/chains"; -import { getTimestampAtStartOfDayUTC } from "../../utils/date"; interface IData { totalTradeFee: string; @@ -18,16 +18,14 @@ type IURL = { }; const endpoints: IURL = { - [CHAIN.CELO]: "https://api.thegraph.com/subgraphs/name/immortalx-io/immortalx", + [CHAIN.CELO]: sdk.graph.modifyEndpoint('DGN3dMffNnXZRAHFyCAq3csJbe2o7g9Jdg2XHe2mzVdG'), }; const fetch = (chain: Chain) => { - return async (timestamp: number): Promise => { - const todayTimestamp = getTimestampAtStartOfDayUTC(timestamp); - + return async ({ startOfDay }: FetchOptions) => { const graphQuery = gql` { - protocolByDay(id: "${todayTimestamp}") { + protocolByDay(id: "${startOfDay}") { totalTradeFee } protocol(id: "1") { @@ -41,7 +39,6 @@ const fetch = (chain: Chain) => { const totalFees = Number(res.protocol.totalTradeFee) / 10 ** 18; return { - timestamp, dailyFees: dailyFees.toString(), totalFees: totalFees.toString(), }; @@ -55,6 +52,7 @@ const adapter: Adapter = { start: 1690848000, }, }, + version: 2 }; export default adapter; diff --git a/fees/impermax-finance.ts b/fees/impermax-finance.ts index 316ed1089a..e59e3cb7da 100644 --- a/fees/impermax-finance.ts +++ b/fees/impermax-finance.ts @@ -1,36 +1,41 @@ import { Adapter } from "../adapters/types"; -import { ARBITRUM, AVAX, CHAIN, ETHEREUM, FANTOM, MOONRIVER, POLYGON } from "../helpers/chains"; +import { CHAIN } from "../helpers/chains"; import fetchURL from "../utils/fetchURL"; // NOTE: the yields server does not return all pools if liquidity is too low, which // may result in calculated fees and revenue being lower than what is real -const yieldPool = "https://yields.llama.fi/pools"; +const borrowPool = "https://yields.llama.fi/poolsBorrow"; const methodology = { Fees: "Fees are calculated as 90% of the borrowing fees for qualified pools, paid by the borrowers to the lenders.", Revenue: "Revenue is the remaining 10% of all collected borrowing fees and go to the protocol.", } -interface IYield { - apyBase: number; - project: string; - tvlUsd: number; - chain: string; -}; +interface IPoolBorrow { + chain: string, + project: string, + pool: string, + totalSupplyUsd: number, + totalBorrowUsd: number, + tvlUsd: number, + apyBase: number + apyBaseBorrow: number +} const graphs = () => { return (chain: CHAIN) => { return async (timestamp: number) => { - const poolsCall: IYield[] = (await fetchURL(yieldPool))?.data; + const poolsCall: IPoolBorrow[] = (await fetchURL(borrowPool))?.data; + const pools = poolsCall - .filter((e: IYield) => e.project === "impermax-finance") - .filter((e: IYield) => e.chain.toLowerCase() === chain.toLowerCase()); + .filter((e: IPoolBorrow) => e.project === "impermax-finance") + .filter((e: IPoolBorrow) => e.chain.toLowerCase() === chain.toLowerCase()); // Fees and revenue is derived from borrowing fees: 90% of the borrowing fees // go to the lenders, and 10% is routed to the treasury as revenue const fees = pools - .map(pool => pool.tvlUsd * pool.apyBase / 100 / 365) - .reduce((prev, curr) => prev + curr, 0) / .9; + .map(pool => pool.totalBorrowUsd * pool.apyBaseBorrow / 100 / 365) + .reduce((prev, curr) => prev + curr, 0); const revenue = fees * .1; return { timestamp, @@ -108,6 +113,30 @@ const adapter: Adapter = { methodology } }, + [CHAIN.BASE]: { + fetch: graphs()(CHAIN.BASE), + runAtCurrTime: true, + start: 1698019200, + meta: { + methodology + } + }, + [CHAIN.SCROLL]: { + fetch: graphs()(CHAIN.SCROLL), + runAtCurrTime: true, + start: 1698019200, + meta: { + methodology + } + }, + [CHAIN.OPTIMISM]: { + fetch: graphs()(CHAIN.OPTIMISM), + runAtCurrTime: true, + start: 1698019200, + meta: { + methodology + } + }, }, } diff --git a/fees/instadapp/index.ts b/fees/instadapp/index.ts index e2f9ab7206..a3c84d6a20 100644 --- a/fees/instadapp/index.ts +++ b/fees/instadapp/index.ts @@ -5,7 +5,6 @@ import { SimpleAdapter, } from "../../adapters/types"; import { Balances } from "@defillama/sdk"; -import { call } from "@defillama/sdk/build/abi/abi2"; const instaFlashAggregators: { [chain: Chain]: { address: string; deployedAt: number }; diff --git a/fees/integral/index.ts b/fees/integral/index.ts index 1a13521cdc..4f3b95a366 100644 --- a/fees/integral/index.ts +++ b/fees/integral/index.ts @@ -43,6 +43,7 @@ const graphs = (graphUrls: ChainEndpoints) => { }; const adapters: SimpleAdapter = { + version: 1, adapter: chains.reduce((acc, chain) => { return { ...acc, diff --git a/fees/intent-x/index.tsx b/fees/intent-x/index.tsx index 17259a56cf..5241095985 100644 --- a/fees/intent-x/index.tsx +++ b/fees/intent-x/index.tsx @@ -1,15 +1,16 @@ +import BigNumber from "bignumber.js"; import request, { gql } from "graphql-request"; +import { FetchOptions, SimpleAdapter } from "../../adapters/types"; import { CHAIN } from "../../helpers/chains"; -import BigNumber from "bignumber.js"; -import { getUniqStartOfTodayTimestamp } from "../../helpers/getUniSubgraphVolume"; -import { FetchResultFees, SimpleAdapter } from "../../adapters/types"; - -const ONE_DAY_IN_SECONDS = 60 * 60 * 24; const endpoint_0_8_0 = - "https://api.thegraph.com/subgraphs/name/intent-x/perpetuals-analytics_base"; + "https://api.studio.thegraph.com/query/62472/perpetuals-analytics_base/version/latest"; const endpoint = - "https://api.studio.thegraph.com/query/62472/intentx-analytics_082/version/latest"; + "https://api.goldsky.com/api/public/project_cm0bho0j0ji6001t8e26s0wv8/subgraphs/intentx-base-analytics-083/latest/gn"; +const endpoint_blast = + "https://api.goldsky.com/api/public/project_cm0bho0j0ji6001t8e26s0wv8/subgraphs/intentx-blast-analytics-083/latest/gn"; +const endpoint_mantle = + "https://api.goldsky.com/api/public/project_cm0bho0j0ji6001t8e26s0wv8/subgraphs/intentx-mantle-analytics-083/latest/gn"; const query_0_8_0 = gql` query stats($from: String!, $to: String!) { @@ -61,6 +62,56 @@ const query = gql` } `; +const queryBlast = gql` + query stats($from: String!, $to: String!) { + dailyHistories( + where: { + timestamp_gte: $from + timestamp_lte: $to + accountSource: "0x083267D20Dbe6C2b0A83Bd0E601dC2299eD99015" + } + ) { + timestamp + platformFee + accountSource + tradeVolume + } + totalHistories( + where: { accountSource: "0x083267D20Dbe6C2b0A83Bd0E601dC2299eD99015" } + ) { + timestamp + platformFee + accountSource + tradeVolume + } + } +`; + +const queryMantle = gql` + query stats($from: String!, $to: String!) { + dailyHistories( + where: { + timestamp_gte: $from + timestamp_lte: $to + accountSource: "0xECbd0788bB5a72f9dFDAc1FFeAAF9B7c2B26E456" + } + ) { + timestamp + platformFee + accountSource + tradeVolume + } + totalHistories( + where: { accountSource: "0xECbd0788bB5a72f9dFDAc1FFeAAF9B7c2B26E456" } + ) { + timestamp + platformFee + accountSource + tradeVolume + } + } +`; + interface IGraphResponse { dailyHistories: Array<{ tiemstamp: string; @@ -81,18 +132,18 @@ const toString = (x: BigNumber) => { return x.toString(); }; -const fetchVolume = async (timestamp: number): Promise => { +const fetchVolume = async ({ endTimestamp, startTimestamp }: FetchOptions) => { const response_0_8_0: IGraphResponse = await request( endpoint_0_8_0, query_0_8_0, { - from: String(timestamp - ONE_DAY_IN_SECONDS), - to: String(timestamp), + from: String(startTimestamp), + to: String(endTimestamp), } ); const response: IGraphResponse = await request(endpoint, query, { - from: String(timestamp - ONE_DAY_IN_SECONDS), - to: String(timestamp), + from: String(startTimestamp), + to: String(endTimestamp), }); // Merging both responses @@ -129,11 +180,115 @@ const fetchVolume = async (timestamp: number): Promise => { const totalProtocolRevenue = "0"; const totalSupplySideRevenue = "0"; - const dayTimestamp = getUniqStartOfTodayTimestamp(new Date(timestamp * 1000)); + return { + dailyFees: _dailyFees ?? "0", + totalFees: _totalFees ?? "0", + + dailyUserFees: dailyUserFees ?? "0", + dailyRevenue: dailyRevenue ?? "0", + dailyProtocolRevenue: dailyProtocolRevenue ?? "0", + dailyHoldersRevenue: dailyHoldersRevenue ?? "0", + dailySupplySideRevenue: dailySupplySideRevenue ?? "0", + totalUserFees: totalUserFees ?? "0", + totalRevenue: totalRevenue ?? "0", + totalProtocolRevenue: totalProtocolRevenue ?? "0", + totalSupplySideRevenue: totalSupplySideRevenue ?? "0", + }; +}; + +const fetchVolumeBlast = async ({ + endTimestamp, + startTimestamp, +}: FetchOptions) => { + let dailyFees = new BigNumber(0); + let totalFees = new BigNumber(0); + + const response_blast: IGraphResponse = await request( + endpoint_blast, + queryBlast, + { + from: String(startTimestamp), + to: String(endTimestamp), + } + ); + response_blast.dailyHistories.forEach((data) => { + dailyFees = dailyFees.plus(new BigNumber(data.platformFee)); + }); + response_blast.totalHistories.forEach((data) => { + totalFees = totalFees.plus(new BigNumber(data.platformFee)); + }); + + dailyFees = dailyFees.dividedBy(new BigNumber(1e18)); + totalFees = totalFees.dividedBy(new BigNumber(1e18)); + const _dailyFees = toString(dailyFees); + const _totalFees = toString(totalFees); + + const dailyUserFees = _dailyFees; + const dailyRevenue = _dailyFees; + const dailyProtocolRevenue = "0"; + const dailyHoldersRevenue = _dailyFees; + const dailySupplySideRevenue = "0"; + + const totalUserFees = _totalFees; + const totalRevenue = _totalFees; + const totalProtocolRevenue = "0"; + const totalSupplySideRevenue = "0"; return { - timestamp: dayTimestamp, + dailyFees: _dailyFees ?? "0", + totalFees: _totalFees ?? "0", + dailyUserFees: dailyUserFees ?? "0", + dailyRevenue: dailyRevenue ?? "0", + dailyProtocolRevenue: dailyProtocolRevenue ?? "0", + dailyHoldersRevenue: dailyHoldersRevenue ?? "0", + dailySupplySideRevenue: dailySupplySideRevenue ?? "0", + totalUserFees: totalUserFees ?? "0", + totalRevenue: totalRevenue ?? "0", + totalProtocolRevenue: totalProtocolRevenue ?? "0", + totalSupplySideRevenue: totalSupplySideRevenue ?? "0", + }; +}; + +const fetchVolumeMantle = async ({ + endTimestamp, + startTimestamp, +}: FetchOptions) => { + let dailyFees = new BigNumber(0); + let totalFees = new BigNumber(0); + + const response_mantle: IGraphResponse = await request( + endpoint_mantle, + queryMantle, + { + from: String(startTimestamp), + to: String(endTimestamp), + } + ); + response_mantle.dailyHistories.forEach((data) => { + dailyFees = dailyFees.plus(new BigNumber(data.platformFee)); + }); + response_mantle.totalHistories.forEach((data) => { + totalFees = totalFees.plus(new BigNumber(data.platformFee)); + }); + + dailyFees = dailyFees.dividedBy(new BigNumber(1e18)); + totalFees = totalFees.dividedBy(new BigNumber(1e18)); + const _dailyFees = toString(dailyFees); + const _totalFees = toString(totalFees); + + const dailyUserFees = _dailyFees; + const dailyRevenue = _dailyFees; + const dailyProtocolRevenue = "0"; + const dailyHoldersRevenue = _dailyFees; + const dailySupplySideRevenue = "0"; + + const totalUserFees = _totalFees; + const totalRevenue = _totalFees; + const totalProtocolRevenue = "0"; + const totalSupplySideRevenue = "0"; + + return { dailyFees: _dailyFees ?? "0", totalFees: _totalFees ?? "0", @@ -150,11 +305,20 @@ const fetchVolume = async (timestamp: number): Promise => { }; const adapter: SimpleAdapter = { + version: 2, adapter: { [CHAIN.BASE]: { fetch: fetchVolume, start: 1698796800, }, + [CHAIN.BLAST]: { + fetch: fetchVolumeBlast, + start: 1698796800, + }, + [CHAIN.MANTLE]: { + fetch: fetchVolumeMantle, + start: 1698796800, + }, }, }; export default adapter; diff --git a/fees/inverse-finance/index.ts b/fees/inverse-finance/index.ts index 553d693f4c..9309621891 100644 --- a/fees/inverse-finance/index.ts +++ b/fees/inverse-finance/index.ts @@ -61,7 +61,7 @@ const toDbrUSDValue = (bn: BigNumber, dbrHistoPrice: number) => { } const fetch = (chain: Chain) => { - return async (timestamp: number, _: ChainBlocks, { createBalances, getLogs, getFromBlock, api }: FetchOptions): Promise => { + return async ({ toTimestamp, createBalances, getLogs, getFromBlock, api }: FetchOptions) => { const dbr = DBR_CONTRACTS[chain]; const dola = DOLA_CONTRACTS[chain]; const dbrAuction = DBR_AUCTION_CONTRACTS[chain]; @@ -78,7 +78,7 @@ const fetch = (chain: Chain) => { getDbrPrices(), ]); - const dbrHistoPrice = dbrPrices.findLast(d => d.timestamp < (timestamp * 1000)).price; + const dbrHistoPrice = dbrPrices.findLast(d => d.timestamp < (toTimestamp * 1000)).price; const existingMarkets = markets.filter(m => m.startingBlock <= block) @@ -159,12 +159,12 @@ const fetch = (chain: Chain) => { dailyFees, dailyRevenue, dailyHoldersRevenue, - timestamp, } } } const adapter: SimpleAdapter = { + version: 2, adapter: { [CHAIN.ETHEREUM]: { fetch: fetch(CHAIN.ETHEREUM), diff --git a/fees/jibswap/index.ts b/fees/jibswap/index.ts index 9944ad5c77..3290fa8adb 100644 --- a/fees/jibswap/index.ts +++ b/fees/jibswap/index.ts @@ -12,6 +12,7 @@ const feeAdapter = getDexChainFees({ }); const adapter: Adapter = { + version: 2, adapter: feeAdapter }; diff --git a/fees/jito.ts b/fees/jito.ts new file mode 100644 index 0000000000..0775d9546f --- /dev/null +++ b/fees/jito.ts @@ -0,0 +1,34 @@ +import { time } from "console" +import { FetchOptions, SimpleAdapter } from "../adapters/types" +import { CHAIN } from "../helpers/chains" +import { queryDune } from "../helpers/dune" + +const fetchFees = async (_a:any, _: any,options: FetchOptions) => { + const dailyFees = options.createBalances() + const dailyRevenue = options.createBalances() + const result = await queryDune("3740661"); + const dateStr = new Date(options.startOfDay * 1000).toISOString().split('T')[0] + const day = result.find((r: any) => r.day === dateStr) + dailyFees.add('So11111111111111111111111111111111111111112', day.sol_tip * 1e9) + dailyRevenue.add('So11111111111111111111111111111111111111112', day.sol_tip * 1e9) + dailyRevenue.resizeBy(0.04) + + return { + timestamp: options.startOfDay, + dailyFees: dailyFees, + dailyRevenue: dailyRevenue, + } +} + +const adapter: SimpleAdapter = { + // version: 2, + adapter: { + [CHAIN.SOLANA]: { + fetch: fetchFees, + start: 1714435200, + } + }, + isExpensiveAdapter: true +} + +export default adapter diff --git a/fees/joe-v2.1.ts b/fees/joe-v2.1.ts index 05cfcfc595..7e8f90220e 100644 --- a/fees/joe-v2.1.ts +++ b/fees/joe-v2.1.ts @@ -10,9 +10,9 @@ type TPool = { } const pools: TPool = { [CHAIN.BSC]: [ - '0xdce12347b429a32a177708646d4024449827a69a', - '0x3708d924f627d8109687ce10f6c324445c28347c', - '0x7e6857d4b2efaf9ff29f88f6d7d083a160e0849e', + // '0xdce12347b429a32a177708646d4024449827a69a', + // '0x3708d924f627d8109687ce10f6c324445c28347c', + // '0x7e6857d4b2efaf9ff29f88f6d7d083a160e0849e', ], [CHAIN.AVAX]: [ '0xd9fa522f5bc6cfa40211944f2c8da785773ad99d', @@ -50,7 +50,7 @@ const pools: TPool = { } const graph = (chain: Chain) => { - return async (timestamp: number , _: ChainBlocks, { createBalances, getLogs, api }: FetchOptions): Promise => { + return async ({ createBalances, getLogs, api }: FetchOptions) => { const dailyFees = createBalances(); const dailyRevenue = createBalances(); const lpTokens = pools[chain] @@ -62,15 +62,17 @@ const graph = (chain: Chain) => { }) ) ); - const decimalsXs = await api.multiCall({ abi: 'erc20:decimals', calls: tokenXs}) - const decimalsYs = await api.multiCall({ abi: 'erc20:decimals', calls: tokenYs}) + const decimalsXs = await api.multiCall({ abi: 'erc20:decimals', calls: tokenXs }) + const decimalsYs = await api.multiCall({ abi: 'erc20:decimals', calls: tokenYs }) - const logs: any[][] = await getLogs({ - targets: lpTokens, - eventAbi: event_swap, - flatten: false, - }) + let logs: any[][] = [] + if (lpTokens.length) + logs = await getLogs({ + targets: lpTokens, + eventAbi: event_swap, + flatten: false, + }) lpTokens.map((_: string, index: number) => { logs[index] @@ -99,13 +101,13 @@ const graph = (chain: Chain) => { dailyProtocolRevenue: dailyRevenue, dailyHoldersRevenue: dailyRevenue, dailySupplySideRevenue, - timestamp, }; } } const adapter: SimpleAdapter = { + version: 2, adapter: { [CHAIN.ARBITRUM]: { fetch: graph(CHAIN.ARBITRUM), diff --git a/fees/jojo/index.ts b/fees/jojo/index.ts new file mode 100644 index 0000000000..d4bab51226 --- /dev/null +++ b/fees/jojo/index.ts @@ -0,0 +1,32 @@ +import { FetchOptions, SimpleAdapter, FetchV2, FetchResultV2 } from '../../adapters/types' +import { CHAIN } from '../../helpers/chains' +import { httpGet } from '../../utils/fetchURL' + +interface IFees { + day: string + fee: string +} + +const getFetch: FetchV2 = async (options: FetchOptions): Promise => { + const url = 'https://api.base-mainnet.jojo.exchange/v1/private/tradingFee?limit=365' + const dateStr = new Date((options.startOfDay - 86400) * 1000).toISOString().split('T')[0] + const res = await httpGet(url) + delete res['latestTen'] + const item: IFees[] = Object.values(res) + const dailyFees = item.flat().find((i) => i.day.split('T')[0] === dateStr)?.fee + return { + dailyFees: dailyFees ? dailyFees : undefined, + } +} + +const adapter: SimpleAdapter = { + version: 2, + adapter: { + [CHAIN.BASE]: { + fetch: getFetch, + start: 1712678400, + } + } +} + +export default adapter diff --git a/fees/juice-finance/index.ts b/fees/juice-finance/index.ts new file mode 100644 index 0000000000..77fe024a79 --- /dev/null +++ b/fees/juice-finance/index.ts @@ -0,0 +1,86 @@ +// https://juice-finance.gitbook.io/juice-finance/juice-protocol/fees#protocol-fees +import { Adapter, FetchOptions, FetchResultV2 } from "../../adapters/types"; +import { CHAIN } from "../../helpers/chains"; +import ADDRESSES from "../../helpers/coreAssets.json"; + +const event = "event DepositFeeTaken(uint256 amount)"; +const WETH = ADDRESSES.blast.WETH; +const USDB = ADDRESSES.blast.USDB; + +const WETH_WETH_stategies: string[] = [ + "0x78E6265a11a41E5Dcd1431448d00f3524943fD11", + "0x3FeC7f626923445F587C4881a80D00a7104782d1", + "0x6F3Bc2f9034C151326A80F5ca1Ee0F1eA1E6f002", + "0xEA42f500A92E4CAa02b2F10E323EadEE1F00fbF7", + "0x40214EDef589149b9cebb7BE7025197d885D6CB1", + "0x9Dfd4094b3e88f3b9E79b04514B1669D6779AeC9", + "0x741011f52B7499ca951f8b8Ee547DD3Cdd813Fda", + "0x576314F851732b208d807260FE19FeC7Dba3E40C", + "0x15e44C3f3F9B34fC49cc15A18a597bf80F144bC9", + "0x98546CdD046219b25B2E617A55563A5e4a3b9Adc", + "0x3e1B017D21ad613c58F8eE2f78987b3c9F14f643", + "0xC2eB02621e74E294B73B9fab0A94081393F31978", +]; + +const WETH_USDB_stategies: string[] = [ + "0xbc0b332d88DCF65a4CD6905eF939213f485FE1A3", + "0xc1B1aE2502D2cDEF4772FB4A4a6fcBf4fd9c1b80", + "0x542A672B1DEa78EFd83B9D7D8CAe76cEa59964a1", + "0x8034b01555487C26D4e21F4E33b7A30fbc90d181", + "0x4A355D57fc1A5eEB33C0a19539744A2144220027", + "0x0CA56aa647E83A8F0a5f7a81a2fdcA393bC68D78", + "0xfEc64ae675CC4B1AacF8F9C0ABeaD585c5496382", + "0x72E4ce9b7cC5d9C017F64ad58e512C253a11d30a", +]; + +const USDB_USDB_stategies: string[] = [ + "0xbc0b332d88DCF65a4CD6905eF939213f485FE1A3", + "0xc1B1aE2502D2cDEF4772FB4A4a6fcBf4fd9c1b80", + "0xd04c891876675f8c02160ee33466315ac13afc38", + "0x542A672B1DEa78EFd83B9D7D8CAe76cEa59964a1", + "0x0CA56aa647E83A8F0a5f7a81a2fdcA393bC68D78", +]; + +const getAndSumFees = async ( + options: FetchOptions, + targets: string[], + event: string +) => { + const logsFees = await options.getLogs({ + targets, + eventAbi: event, + flatten: true, + }); + return logsFees.reduce((acc, fee) => acc + Number(fee), 0); +}; + +const fetch = async (options: FetchOptions): Promise => { + const dailyFees = options.createBalances(); + + const [wethwethFees, wethusdbFees, usdbusdbFees] = await Promise.all([ + getAndSumFees(options, WETH_WETH_stategies, event), + getAndSumFees(options, WETH_USDB_stategies, event), + getAndSumFees(options, USDB_USDB_stategies, event), + ]); + + dailyFees.add(WETH, wethwethFees); + dailyFees.add(USDB, wethusdbFees + usdbusdbFees); + + return { dailyFees, dailyRevenue: dailyFees }; +}; + +const adapter: Adapter = { + adapter: { + [CHAIN.BLAST]: { + fetch, + start: 1709247600, + meta: { + methodology: + "Applied to strategies at the team's discretion and always noted on the vault page. It is charged upon entering the strategy, typically ranging from 0.5% to 2%.", + }, + }, + }, + version: 2, +}; + +export default adapter; diff --git a/fees/jup-ape.ts b/fees/jup-ape.ts new file mode 100644 index 0000000000..6c9cbf0050 --- /dev/null +++ b/fees/jup-ape.ts @@ -0,0 +1,29 @@ +import { FetchOptions, SimpleAdapter } from "../adapters/types"; +import { CHAIN } from "../helpers/chains"; +import { queryDune } from "../helpers/dune"; + +const fetch: any = async (options: FetchOptions) => { + const dailyFees = options.createBalances(); + const value = (await queryDune("3521814", { + start: options.startTimestamp, + end: options.endTimestamp, + receiver: 'GqNdpkmqM1Aay1J7dRPmmupincfHTpF2tQLcfZuPy6uC' + })); + dailyFees.add('So11111111111111111111111111111111111111112', value[0].fee_token_amount); + + return { dailyFees, dailyRevenue: dailyFees } + +} + +const adapter: SimpleAdapter = { + version: 2, + adapter: { + [CHAIN.SOLANA]: { + fetch: fetch, + start: 0, + }, + }, + isExpensiveAdapter: true +}; + +export default adapter; diff --git a/fees/kamino-lending/index.ts b/fees/kamino-lending/index.ts new file mode 100644 index 0000000000..1e93b36f95 --- /dev/null +++ b/fees/kamino-lending/index.ts @@ -0,0 +1,57 @@ +import { Adapter, FetchV2 } from "../../adapters/types"; +import fetchURL from "../../utils/fetchURL"; +import { CHAIN } from "../../helpers/chains"; +import { getTimestampAtStartOfPreviousDayUTC } from "../../utils/date"; + +// Define the URL of the endpoint +const AllezLabsKaminoFeeEndpoint = 'https://allez-xyz--kamino-fees-api-get-fees-lifetime-kamino.modal.run'; +const KaminoStartTimestamp = 1697068700; + +// Function to make the GET request +const fetch: FetchV2 = async ({ endTimestamp }) => { + const dayTimestamp = getTimestampAtStartOfPreviousDayUTC(endTimestamp); + const historicalFeesRes = (await fetchURL(AllezLabsKaminoFeeEndpoint)); + + const totalFee = historicalFeesRes['data'] + .filter(row => row.timestamp <= dayTimestamp) + .reduce((acc, {KlendFeesUsd}) => acc + KlendFeesUsd, 0); + + const totalRevenue = historicalFeesRes['data'] + .filter(row => row.timestamp <= dayTimestamp) + .reduce((acc, {KlendRevenueUsd}) => acc + KlendRevenueUsd, 0); + + + const dailyFee = historicalFeesRes['data'] + .find(row => Math.abs(row.timestamp - dayTimestamp) < 3600*24 - 1)?.KlendFeesUsd; + + const dailyRevenue = historicalFeesRes['data'] + .find(row => Math.abs(row.timestamp - dayTimestamp) < 3600*24 - 1)?.KlendRevenueUsd; + + return { + timestamp: dayTimestamp, + totalFees: `${totalFee}`, + dailyFees: `${dailyFee}`, + totalRevenue: `${totalRevenue}`, + dailyRevenue: `${dailyRevenue}` + }; +}; +const methodology = { + Fees: "Fees are aggregated by Allez Labs using the Kamino API" +} + +const adapter: Adapter = { + version: 2, + adapter: { + [CHAIN.SOLANA]: { + fetch, + runAtCurrTime: true, + start: 1697068700, + meta: { + methodology + } + } + } +} +export default adapter; + + diff --git a/fees/keller-cl/index.ts b/fees/keller-cl/index.ts new file mode 100644 index 0000000000..bc128c2f8d --- /dev/null +++ b/fees/keller-cl/index.ts @@ -0,0 +1,28 @@ +import { uniV3Exports } from "../../helpers/uniswap"; + +const customLogic = async ({ pairObject, dailyFees, fetchOptions, filteredPairs, }: any) => { + const collectProtocolEvent = 'event CollectProtocol(address indexed sender,address indexed recipient,uint128 amount0,uint128 amount1)'; + const { createBalances, getLogs } = fetchOptions + const dailyProtocolRevenue = createBalances(); + + await Promise.all(Object.keys(filteredPairs).map(async (pair) => { + const [token0, token1] = pairObject[pair] + const logs = await getLogs({ target: pair, eventAbi: collectProtocolEvent }) + + logs.forEach(log => { + dailyProtocolRevenue.add(token0, log.amount0) + dailyProtocolRevenue.add(token1, log.amount1) + }) + })) + return { + dailyFees, + dailyProtocolRevenue, + }; +} + +export default uniV3Exports({ + scroll: { + factory: '0x952aC46B2586737df679e836d9B980E43E12B2d8', + customLogic, + } +}) \ No newline at end of file diff --git a/fees/keller/index.ts b/fees/keller/index.ts new file mode 100644 index 0000000000..5f167ec1a7 --- /dev/null +++ b/fees/keller/index.ts @@ -0,0 +1,7 @@ +import { CHAIN } from '../../helpers/chains'; +import { uniV2Exports } from '../../helpers/uniswap'; + +export default uniV2Exports({ + [CHAIN.SCROLL]: { factory: '0xbc83f7dF70aE8A3e4192e1916d9D0F5C2ee86367', voter: '0x30f827DECe6F25c74F37d0dD45bC245d893266e6', }, +}) + diff --git a/fees/keom.ts b/fees/keom.ts index 9088f3a82b..117b245c50 100644 --- a/fees/keom.ts +++ b/fees/keom.ts @@ -31,17 +31,17 @@ const graphs = (graphUrls: ChainEndpoints) => { const graphRes = await request(graphUrls[chain], graphQuery); - const totalFee = new BigNumber( - graphRes.financialsDailySnapshot.cumulativeTotalRevenueUSD + const totalFee = Number( + graphRes.financialsDailySnapshot?.cumulativeTotalRevenueUSD || '0' ); - const dailyFee = new BigNumber( - graphRes.financialsDailySnapshot.dailyTotalRevenueUSD + const dailyFee = Number( + graphRes.financialsDailySnapshot?.dailyTotalRevenueUSD || '0' ); - const totalRev = new BigNumber( - graphRes.financialsDailySnapshot.cumulativeProtocolSideRevenueUSD + const totalRev = Number( + graphRes.financialsDailySnapshot?.cumulativeProtocolSideRevenueUSD || '0' ); - const dailyRev = new BigNumber( - graphRes.financialsDailySnapshot.dailyProtocolSideRevenueUSD + const dailyRev = Number( + graphRes.financialsDailySnapshot?.dailyProtocolSideRevenueUSD || '0' ); return { @@ -61,10 +61,10 @@ const adapter: Adapter = { fetch: graphs(endpoints)(CHAIN.POLYGON), start: 1699520408, }, - [CHAIN.POLYGON_ZKEVM]: { - fetch: graphs(endpoints)(CHAIN.POLYGON_ZKEVM), - start: 1679921168, - }, + // [CHAIN.POLYGON_ZKEVM]: { + // fetch: graphs(endpoints)(CHAIN.POLYGON_ZKEVM), // error the graph is not available + // start: 1679921168, + // }, [CHAIN.MANTA]: { fetch: graphs(endpoints)(CHAIN.MANTA), start: 1698838028, @@ -72,4 +72,4 @@ const adapter: Adapter = { }, }; -export default adapter; \ No newline at end of file +export default adapter; diff --git a/fees/kiloex/index.ts b/fees/kiloex/index.ts index 37a02b8000..da3baab6b7 100644 --- a/fees/kiloex/index.ts +++ b/fees/kiloex/index.ts @@ -12,7 +12,9 @@ type ChainMap = { const endpoints: ChainMap = { [CHAIN.BSC]: "https://api.kiloex.io/common/queryTradeSummary", [CHAIN.OP_BNB]: "https://opapi.kiloex.io/common/queryTradeSummary", - [CHAIN.MANTA]: "https://mantaapi.kiloex.io/common/queryTradeSummary" + [CHAIN.MANTA]: "https://mantaapi.kiloex.io/common/queryTradeSummary", + [CHAIN.TAIKO]: "https://taikoapi.kiloex.io/common/queryTradeSummary", + [CHAIN.BSQUARED]: "https://b2api.kiloex.io/common/queryTradeSummary" }; interface IFee { @@ -42,6 +44,7 @@ const fetch = (chainId: string) => { const adapter: SimpleAdapter = { + version: 1, adapter: { [CHAIN.BSC]: { fetch: fetch(CHAIN.BSC), start: 1686528000 @@ -52,6 +55,12 @@ const adapter: SimpleAdapter = { [CHAIN.MANTA]: { fetch: fetch(CHAIN.MANTA), start: 1698796800 }, + [CHAIN.TAIKO]: { + fetch: fetch(CHAIN.TAIKO), start: async () => 1717027200 + }, + [CHAIN.BSQUARED]: { + fetch: fetch(CHAIN.BSQUARED), start: async () => 1722297600 + }, }, }; diff --git a/fees/kinetix-derivatives-v2/index.ts b/fees/kinetix-derivatives-v2/index.ts index e135570049..abade52877 100644 --- a/fees/kinetix-derivatives-v2/index.ts +++ b/fees/kinetix-derivatives-v2/index.ts @@ -8,7 +8,7 @@ import { getTimestampAtStartOfDayUTC } from "../../utils/date"; const endpoints = { [CHAIN.KAVA]: - "https://kava-graph-node.metavault.trade/subgraphs/name/kinetixfi/perpv2", + "https://kava-graph-node.metavault.trade/subgraphs/name/kinetixfi/kava-trade", }; const graphs = (graphUrls: ChainEndpoints) => { @@ -46,6 +46,7 @@ const graphs = (graphUrls: ChainEndpoints) => { }; const adapter: Adapter = { + version: 1, adapter: { [CHAIN.KAVA]: { fetch: graphs(endpoints)(CHAIN.KAVA), diff --git a/fees/kinetix/index.ts b/fees/kinetix/index.ts index e7c3a1bbb7..5704109ddd 100644 --- a/fees/kinetix/index.ts +++ b/fees/kinetix/index.ts @@ -44,6 +44,7 @@ const graphs = (graphUrls: ChainEndpoints) => { }; const adapter: Adapter = { + version: 1, adapter: { [CHAIN.KAVA]: { fetch: graphs(endpoints)(CHAIN.KAVA), diff --git a/fees/koi-finance-cl.ts b/fees/koi-finance-cl.ts new file mode 100644 index 0000000000..da11fcc200 --- /dev/null +++ b/fees/koi-finance-cl.ts @@ -0,0 +1,48 @@ +import request, { gql } from "graphql-request"; +import { FetchOptions, FetchResultFees, SimpleAdapter } from "../adapters/types"; +import { CHAIN } from "../helpers/chains"; +import { getUniqStartOfTodayTimestamp } from "../helpers/getUniSubgraphFees"; +import BigNumber from "bignumber.js"; + +const endpoints: any = { + [CHAIN.ERA]: "https://api.studio.thegraph.com/query/12332/koi-finance-v3/version/latest", +} + +interface IData { + feesUSD: string +} +interface IPoolDay { + poolDayDatas: IData[] +} + +const fetchFees = async (timestamp: number, _t: any, options: FetchOptions): Promise => { + const todayTimestamp = getUniqStartOfTodayTimestamp(new Date(options.startOfDay * 1000)); + const graphQuery = gql`{ + poolDayDatas(frist: 1000, where:{date:${todayTimestamp},tvlUSD_gt: 1000},orderBy:feesUSD, orderDirection: desc) { + feesUSD + } + }`; + + try { + const graphRes: IPoolDay = await request(endpoints[options.chain], graphQuery); + const dailyFee = new BigNumber(graphRes.poolDayDatas.reduce((a: number, b: IData) => a + Number(b.feesUSD), 0)) + return { + timestamp, + dailyFees: dailyFee.toString(), + dailyRevenue: dailyFee.times(0.2).toString(), + }; + } catch (e) { + return { timestamp }; + } +}; + +const adapter: SimpleAdapter = { + adapter: { + [CHAIN.ERA]: { + fetch: fetchFees, + start: 0 + }, + }, +}; + +export default adapter; diff --git a/fees/koi-finance/index.ts b/fees/koi-finance/index.ts new file mode 100644 index 0000000000..94906cf03c --- /dev/null +++ b/fees/koi-finance/index.ts @@ -0,0 +1,27 @@ +import { Adapter, FetchOptions, FetchResultFees } from '../../adapters/types'; +import { ZKSYNC } from '../../helpers/chains'; +import { fetchV1 } from './koi-finance'; + + +const getFees = async (options: FetchOptions) => { + const [feeV1] = await Promise.all([fetchV1()(options)]); + const dailyFees = Number(feeV1.dailyFees); + const dailyRevenue = Number(feeV1.dailyRevenue); + + return { + dailyFees: `${dailyFees}`, + dailyRevenue: `${dailyRevenue}`, + } +} + +const adapter: Adapter = { + version: 2, + adapter: { + [ZKSYNC]: { + fetch: getFees, + start: 1677110400, // TODO: Add accurate timestamp + }, + }, +}; + +export default adapter; \ No newline at end of file diff --git a/fees/koi-finance/koi-finance.ts b/fees/koi-finance/koi-finance.ts new file mode 100644 index 0000000000..78ffde9e5e --- /dev/null +++ b/fees/koi-finance/koi-finance.ts @@ -0,0 +1,52 @@ +import request, { gql } from "graphql-request"; +import BigNumber from "bignumber.js"; +import { FetchOptions } from "../../adapters/types"; +import { getBlock } from "../../helpers/getBlock"; + +const endpoint = + "https://api.goldsky.com/api/public/project_clmtie4nnezuh2nw6hhjg6mo7/subgraphs/mute_switch/v0.0.7/gn"; + +export const fetchV1 = () => { + return async ({ endTimestamp, startTimestamp }: FetchOptions) => { + const [todaysBlock, yesterdaysBlock] = await Promise.all([ + getBlock(endTimestamp, "era", {}), + getBlock(startTimestamp, "era", {}), + ]); + + const query = gql` + query fees { + yesterday: pairs(block: {number: ${yesterdaysBlock}}, where: {volumeUSD_gt: "0"}, first: 1000, orderBy:volumeUSD, orderDirection:desc) { + id + stable + pairFee + volumeUSD + } + today: pairs(block: {number: ${todaysBlock}}, where: {volumeUSD_gt: "0"}, first: 1000, orderBy:volumeUSD, orderDirection:desc) { + id + stable + pairFee + volumeUSD + } + } + `; + const todayVolume: { [id: string]: BigNumber } = {}; + const graphRes = await request(endpoint, query); + let dailyFee = new BigNumber(0); + for (const pool of graphRes["today"]) { + todayVolume[pool.id] = new BigNumber(pool.volumeUSD); + } + + for (const pool of graphRes["yesterday"]) { + if (!todayVolume[pool.id]) continue; + + const dailyVolume = BigNumber(todayVolume[pool.id]).minus(pool.volumeUSD); + + dailyFee = dailyFee.plus(dailyVolume.times(pool.pairFee).div(10000)); + } + + return { + dailyFees: dailyFee.toString(), + dailyRevenue: dailyFee.times(0.2).toString(), + }; + }; +}; diff --git a/fees/kperp-exchange.ts b/fees/kperp-exchange.ts index 7309b904f5..62ee4e645e 100644 --- a/fees/kperp-exchange.ts +++ b/fees/kperp-exchange.ts @@ -47,7 +47,7 @@ const adapter: Adapter = { adapter: { [DISABLED_ADAPTER_KEY]: disabledAdapter, [CHAIN.KAVA]: { - fetch: graphs(endpoints)(CHAIN.KAVA), + fetch: async (timestamp: number) => {return{timestamp}}, start: 2578000, meta: { methodology: 'All mint, burn, marginAndLiquidation and swap fees are collected and the daily fee amount is determined. Daily revenue is calculated as 30% of the total fee.' diff --git a/fees/ktx.ts b/fees/ktx.ts index 69b8c6442f..8e3b60ece3 100644 --- a/fees/ktx.ts +++ b/fees/ktx.ts @@ -6,9 +6,9 @@ import { Chain } from "@defillama/sdk/build/general"; import { getTimestampAtStartOfDayUTC } from "../utils/date"; const endpoints = { - [BSC]: "https://subgraph.ktx.finance/subgraphs/name/ktx", - [MANTLE]: "https://mantlesubgraph.ktx.finance/subgraphs/name/ktx", - [ARBITRUM]: "https://arbisubgraph.ktx.systems/subgraphs/name/ktx", + [BSC]: "https://subgraph.satsuma-prod.com/dff088b6cd75/kesters-team/bsc_stats/api", + [MANTLE]: "https://subgraph.satsuma-prod.com/dff088b6cd75/kesters-team/mantle_stats/api", + [ARBITRUM]: "https://subgraph.satsuma-prod.com/dff088b6cd75/kesters-team/ktx_stats/api", }; const methodology = { diff --git a/fees/kyberswap-aggregator.ts b/fees/kyberswap-aggregator.ts new file mode 100644 index 0000000000..7996b0ed1a --- /dev/null +++ b/fees/kyberswap-aggregator.ts @@ -0,0 +1,27 @@ +import { CHAIN } from "../helpers/chains" +import { FetchOptions, SimpleAdapter } from "../adapters/types"; +import { addTokensReceived } from "../helpers/token"; + +const chains = [CHAIN.ETHEREUM, CHAIN.ARBITRUM, CHAIN.OPTIMISM, CHAIN.ERA, CHAIN.POLYGON, CHAIN.BASE, CHAIN.BSC, CHAIN.LINEA, CHAIN.SCROLL, CHAIN.AVAX, CHAIN.FANTOM, +// disabled chains: CHAIN.MANTLE, CHAIN.BLAST, CHAIN.CRONOS, CHAIN.POLYGON_ZKEVM, +] + +const feeCollector = "0x4f82e73edb06d29ff62c91ec8f5ff06571bdeb29" +async function fetch(options:FetchOptions){ + // MISSING INTERNAL ETH TRANSFERS! + const dailyFees = await addTokensReceived({target: feeCollector, options}) + return {dailyFees, dailyRevenue: dailyFees } +} + +export default { + adapter: + chains.reduce((acc, curr)=>({ + ...acc, + [curr]:{ + fetch: fetch, + start: 1683893231 + } + }), {}) + , + version: 2 +} as SimpleAdapter; diff --git a/fees/kyberswap.ts b/fees/kyberswap.ts index 9dd5af4b44..d70c610e1f 100644 --- a/fees/kyberswap.ts +++ b/fees/kyberswap.ts @@ -1,3 +1,4 @@ +import * as sdk from "@defillama/sdk"; import { BaseAdapter, BreakdownAdapter, FetchResultFees } from "../adapters/types"; import { CHAIN } from "../helpers/chains"; import { request, gql } from "graphql-request"; @@ -27,9 +28,9 @@ const elasticEndpoints: TEndpoint = elasticChains.reduce((acc, chain) => ({ [chain]: `https://api.thegraph.com/subgraphs/name/kybernetwork/kyberswap-elastic-${normalizeChain[chain] ?? chain}`, ...acc, }), { - [CHAIN.ETHEREUM]: "https://api.thegraph.com/subgraphs/name/kybernetwork/kyberswap-elastic-mainnet", - [CHAIN.ARBITRUM]: "https://api.thegraph.com/subgraphs/name/kybernetwork/kyberswap-elastic-arbitrum-one", - [CHAIN.POLYGON]: "https://api.thegraph.com/subgraphs/name/kybernetwork/kyberswap-elastic-matic", + [CHAIN.ETHEREUM]: sdk.graph.modifyEndpoint('4U9PxDR4asVvfXyoVy18fhuj6NHnQhLzZkjZ5Bmuc5xk'), + [CHAIN.ARBITRUM]: sdk.graph.modifyEndpoint('C36tj8jSpEHxcNbjM3z7ayUZHVjrk4HRqnpGMFuRgXs6'), + [CHAIN.POLYGON]: sdk.graph.modifyEndpoint('8g4tJKCJ7eMAHjzZNeRWz9BkYG5U7vDNjdanSXfDXGXT'), [CHAIN.LINEA]: "https://linea-graph.kyberengineering.io/subgraphs/name/kybernetwork/kyberswap-elastic-linea", [CHAIN.BITTORRENT]: "https://bttc-graph.kyberengineering.io/subgraphs/name/kybernetwork/kyberswap-elastic-bttc", [CHAIN.BASE]: "https://base-graph.kyberengineering.io/subgraphs/name/kybernetwork/kyberswap-elastic-base", @@ -110,18 +111,21 @@ const graphsElasticV2 = (chain: Chain) => { }`; if (!elasticEndpointsV2[chain]) return { timestamp }; - const graphRes: IPoolDay = await request(elasticEndpointsV2[chain], graphQuery); - const dailyFee = new BigNumber(graphRes.poolDayDatas.reduce((a: number, b: IData) => a + Number(b.feesUSD), 0)) - - return { - timestamp, - dailyUserFees: dailyFee.toString(), - dailyFees: dailyFee.toString(), - dailyRevenue: dailyFee.multipliedBy(0.16).toString(), - dailyProtocolRevenue: "0", - dailyHoldersRevenue: dailyFee.multipliedBy(0.16).toString(), - dailySupplySideRevenue: dailyFee.multipliedBy(0.84).toString(), - }; + try { + const graphRes: IPoolDay = await request(elasticEndpointsV2[chain], graphQuery); + const dailyFee = new BigNumber(graphRes.poolDayDatas.reduce((a: number, b: IData) => a + Number(b.feesUSD), 0)) + return { + timestamp, + dailyUserFees: dailyFee.toString(), + dailyFees: dailyFee.toString(), + dailyRevenue: dailyFee.multipliedBy(0.16).toString(), + dailyProtocolRevenue: "0", + dailyHoldersRevenue: dailyFee.multipliedBy(0.16).toString(), + dailySupplySideRevenue: dailyFee.multipliedBy(0.84).toString(), + }; + } catch (e) { + return { timestamp }; + } }; }; @@ -183,6 +187,7 @@ const graphsClassic = (chain: Chain) => { } } `; + try { const graphRes: IPoolData[] = (await request(classicEndpoints[chain], graphQuery)).poolDayDatas; const dailyFeeUSD = graphRes.reduce((a: number, b: IPoolData) => a + Number(b.dailyFeeUSD), 0) @@ -198,6 +203,9 @@ const graphsClassic = (chain: Chain) => { dailyHoldersRevenue: dailyFee.multipliedBy(0.16).toString(), dailySupplySideRevenue: dailyFee.multipliedBy(0.84).toString(), }; + } catch (e) { + return { timestamp } + } }; }; diff --git a/fees/kyotoswap.ts b/fees/kyotoswap.ts index 7b89cdee87..2999b680ab 100644 --- a/fees/kyotoswap.ts +++ b/fees/kyotoswap.ts @@ -1,28 +1,23 @@ -import { getDexChainFees } from "../helpers/getUniSubgraphFees"; -import volumeAdapter from "../dexs/spookyswap"; +import * as sdk from "@defillama/sdk"; import { Adapter, BaseAdapter, - BreakdownAdapter, IJSON, } from "../adapters/types"; import { CHAIN } from "../helpers/chains"; -import { getGraphDimensions } from "../helpers/getUniSubgraph"; +import { getGraphDimensions, getGraphDimensions2 } from "../helpers/getUniSubgraph"; import { Chain } from "@defillama/sdk/build/general"; const endpoints = { [CHAIN.BSC]: - "https://api.thegraph.com/subgraphs/name/miguelangelrm/kyotoswap-exchange", + sdk.graph.modifyEndpoint('B1VWKexyptT1ixDdHsxj3EJnAxvuje7ANT39rnfq9rRG'), }; -const graphs = getGraphDimensions({ +const graphs = getGraphDimensions2({ graphUrls: endpoints, totalVolume: { factory: "pancakeFactories", }, - dailyVolume: { - factory: "pancakeDayData", - }, feesPercent: { type: "volume", Fees: 0.25, @@ -46,6 +41,7 @@ const methodology = { }; const adapter: Adapter = { + version: 2, adapter: Object.keys(endpoints).reduce((acc, chain) => { acc[chain] = { fetch: graphs(chain as Chain), diff --git a/fees/lens-protocol.ts b/fees/lens-protocol.ts index bb90f68517..c95619e2ac 100644 --- a/fees/lens-protocol.ts +++ b/fees/lens-protocol.ts @@ -23,7 +23,7 @@ const adapter: SimpleAdapter = { adapter: { [CHAIN.POLYGON]: { fetch: fetch, - start: 1693180800, + start: 1708819200, }, }, version: 2 diff --git a/fees/level-finance.ts b/fees/level-finance.ts index feb215d280..5fcae3b9cd 100644 --- a/fees/level-finance.ts +++ b/fees/level-finance.ts @@ -1,3 +1,4 @@ +import * as sdk from "@defillama/sdk"; import BigNumber from 'bignumber.js' import { Chain } from '@defillama/sdk/build/general' import { gql, GraphQLClient } from 'graphql-request' @@ -7,8 +8,8 @@ import { BSC, ARBITRUM } from '../helpers/chains' import { getBlock } from '../helpers/getBlock' const endpoints = { - [BSC]: 'https://api.thegraph.com/subgraphs/name/level-fi/levelfinanceanalytics', - [ARBITRUM]: 'https://api.thegraph.com/subgraphs/name/level-fi/analytics-arb', + [BSC]: sdk.graph.modifyEndpoint('AFaRssJTqNReTtU2XdTGPhN38YVPNBc7faMNKA1mU54h'), + [ARBITRUM]: sdk.graph.modifyEndpoint('AV58XWaZUZPJ2w1x2wYmGEivVZmDojGW3fAYggUAujtD'), } const graphs = (graphUrls: ChainEndpoints) => { diff --git a/fees/lexer/index.ts b/fees/lexer/index.ts index 69b14db023..4cff2cb8ba 100644 --- a/fees/lexer/index.ts +++ b/fees/lexer/index.ts @@ -1,7 +1,6 @@ -import { Fetch, FetchResultFees, SimpleAdapter } from "../../adapters/types"; +import { FetchOptions, FetchV2, SimpleAdapter } from "../../adapters/types"; import { CHAIN } from "../../helpers/chains"; import { gql, request } from 'graphql-request'; -import { getUniqStartOfTodayTimestamp } from "../../helpers/getUniSubgraphVolume"; // TODO: change these endpoints const apiEndPoints = [ @@ -32,14 +31,13 @@ const historicalDataSwap = gql` `; -const fetch: Fetch = async(timestamp): Promise => { +const fetch: FetchV2 = async({ startOfDay }: FetchOptions) => { // TODO: get result from fetching api call let dailyFees = 0; let totalFees = 0; - const t = getUniqStartOfTodayTimestamp(new Date(timestamp * 1000)) for (const api of apiEndPoints){ const response: FeeStatsQuery = await request(api, historicalDataSwap, { - id: String(t), + id: String(startOfDay), period: "daily", }) dailyFees += response.feeStats.length ? Number( @@ -62,13 +60,13 @@ const fetch: Fetch = async(timestamp): Promise => { dailyFees /= 1e30 totalFees /= 1e30 return { - timestamp, dailyFees: dailyFees.toString(), totalFees: totalFees.toString(), } } const adapter: SimpleAdapter = { + version: 2, adapter: { [CHAIN.ARBITRUM]: { start: 1704758400, diff --git a/fees/lido.ts b/fees/lido.ts index 9f7e76ef82..3c81250cc7 100644 --- a/fees/lido.ts +++ b/fees/lido.ts @@ -1,3 +1,4 @@ +import * as sdk from "@defillama/sdk"; import { Adapter } from "../adapters/types"; import { ETHEREUM } from "../helpers/chains"; import { request, gql } from "graphql-request"; @@ -7,7 +8,7 @@ import { getTimestampAtStartOfDayUTC } from "../utils/date"; import BigNumber from "bignumber.js"; const endpoints = { - [ETHEREUM]: "https://api.thegraph.com/subgraphs/name/messari/lido-ethereum", + [ETHEREUM]: sdk.graph.modifyEndpoint('C3ahLtmwYjrPsxgJpKtRieLFyT33FWSxfPcUFXFBo6KW'), } const graphs = (graphUrls: ChainEndpoints) => { diff --git a/fees/lifinity.ts b/fees/lifinity.ts index 6a0198532e..e9dcd3371b 100644 --- a/fees/lifinity.ts +++ b/fees/lifinity.ts @@ -4,7 +4,7 @@ import { CHAIN } from "../helpers/chains"; import { getUniqStartOfTodayTimestamp } from "../helpers/getUniSubgraphVolume"; import fetchURL from "../utils/fetchURL"; -const historicalVolumeEndpoint = "https://lifinity.io/api/dashboard/volume" +const historicalVolumeEndpoint = "https://api.lifinity.io/api/dashboard/volume" interface IVolumeall { fees: number; @@ -29,18 +29,18 @@ const fetch = async (timestamp: number): Promise => { if (dailyFees !== undefined) { const dailyFeesUsd = new BigNumber(dailyFees); fetchResponse['dailyFees'] = dailyFeesUsd.toString() - fetchResponse['dailyRevenue'] = dailyFeesUsd.multipliedBy(0.15).toString() - fetchResponse['dailyProtocolRevenue'] = dailyFeesUsd.multipliedBy(0.15).toString() - fetchResponse['dailySupplySideRevenue'] = dailyFeesUsd.multipliedBy(0.85).toString() + fetchResponse['dailyRevenue'] = dailyFeesUsd.toString() + fetchResponse['dailyProtocolRevenue'] = dailyFeesUsd.toString() + fetchResponse['dailySupplySideRevenue'] = dailyFeesUsd.multipliedBy(0).toString() fetchResponse['dailyUserFees'] = dailyFeesUsd.toString() } if (totalFees !== undefined) { const totalFeesUsd = new BigNumber(totalFees); fetchResponse['totalFees'] = totalFeesUsd.toString() - fetchResponse['totalRevenue'] = totalFeesUsd.multipliedBy(0.15).toString() - fetchResponse['totalProtocolRevenue'] = totalFeesUsd.multipliedBy(0.15).toString() - fetchResponse['totalSupplySideRevenue'] = totalFeesUsd.multipliedBy(0.85).toString() + fetchResponse['totalRevenue'] = totalFeesUsd.toString() + fetchResponse['totalProtocolRevenue'] = totalFeesUsd.toString() + fetchResponse['totalSupplySideRevenue'] = totalFeesUsd.multipliedBy(0).toString() fetchResponse['totalUserFees'] = totalFeesUsd.toString() } @@ -50,9 +50,9 @@ const fetch = async (timestamp: number): Promise => { const methodology = { UserFees: "Base trading fee differs on each pool", Fees: "All fees generated from trading fees", - SupplySideRevenue: "LPs currently receive 85% of trading fees", - ProtocolRevenue: "A 15% of trading fees is retained as a protocol fee", - Revenue: "A 15% of trading fees is retained as a protocol fee", + SupplySideRevenue: "LPs currently receive 0% of trading fees", + ProtocolRevenue: "100% of trading fees is retained as a protocol fee", + Revenue: "100% of trading fees is retained as a protocol fee", HoldersRevenue: "Holders have no revenue from trading fees", } diff --git a/fees/linehub-perps/index.ts b/fees/linehub-perps/index.ts new file mode 100644 index 0000000000..67c025d949 --- /dev/null +++ b/fees/linehub-perps/index.ts @@ -0,0 +1,73 @@ +import { gql, request } from "graphql-request"; +import type { ChainEndpoints, FetchV2 } from "../../adapters/types"; +import { Adapter } from "../../adapters/types"; +import { CHAIN } from "../../helpers/chains"; + +import { getTimestampAtStartOfDayUTC } from "../../utils/date"; + +const endpoints = { + [CHAIN.LINEA]: + "https://api.studio.thegraph.com/query/55804/linehub-trade/version/latest", +}; + +interface IFeeStat { + cumulativeFeeUsd: string; + feeUsd: string; + id: string; +} + +const graphs = (graphUrls: ChainEndpoints) => { + const fetch: FetchV2 = async ({ chain, startTimestamp }) => { + const todaysTimestamp = getTimestampAtStartOfDayUTC(startTimestamp); + + const graphQuery = gql` + query MyQuery { + feeStats(where: {timestamp: ${todaysTimestamp}, period: daily}) { + cumulativeFeeUsd + feeUsd + id + } + } + `; + + const graphRes = await request(graphUrls[chain], graphQuery); + const feeStats: IFeeStat[] = graphRes.feeStats; + + let dailyFeeUSD = BigInt(0); + let totalFeeUSD = BigInt(0); + + feeStats.forEach((fee) => { + dailyFeeUSD += BigInt(fee.feeUsd); + totalFeeUSD += BigInt(fee.cumulativeFeeUsd); + }); + + const finalDailyFee = parseInt(dailyFeeUSD.toString()) / 1e18; + const finalTotalFee = parseInt(totalFeeUSD.toString()) / 1e18; + + return { + timestamp: todaysTimestamp, + dailyFees: finalDailyFee.toString(), + totalFees: finalTotalFee.toString(), + }; + }; + return fetch; +}; + +const methodology = { + dailyFees: "Total cumulativeFeeUsd for specified chain for the given day", +}; + +const adapter: Adapter = { + version: 2, + adapter: { + [CHAIN.LINEA]: { + fetch: graphs(endpoints), + start: 1719878400, + meta: { + methodology, + }, + }, + }, +}; + +export default adapter; diff --git a/fees/liondex/index.ts b/fees/liondex/index.ts index 28f910c115..27b4273dfa 100644 --- a/fees/liondex/index.ts +++ b/fees/liondex/index.ts @@ -1,15 +1,14 @@ import { Adapter, DISABLED_ADAPTER_KEY } from "../../adapters/types"; import { ARBITRUM } from "../../helpers/chains"; import { request, gql } from "graphql-request"; -import type { ChainEndpoints } from "../../adapters/types"; +import type { ChainEndpoints, FetchOptions } from "../../adapters/types"; import { Chain } from "@defillama/sdk/build/general"; -import { getTimestampAtStartOfDayUTC } from "../../utils/date"; import * as sdk from "@defillama/sdk"; import disabledAdapter from "../../helpers/disabledAdapter"; const endpoints = { [ARBITRUM]: - "https://api.thegraph.com/subgraphs/name/liondextrade/finance", + sdk.graph.modifyEndpoint('EDnnTmgZVXAywK9ujCbwhi2hNhuaLAgeSvRL7dPAsV13'), }; const methodology = { @@ -28,12 +27,10 @@ async function lpPrice() { const graphs = (graphUrls: ChainEndpoints) => { return (chain: Chain) => { - return async (timestamp: number) => { - const todaysTimestamp = getTimestampAtStartOfDayUTC(timestamp); - + return async ({ startOfDay }: FetchOptions) => { const graphQuery = gql` { - dailyGlobalInfo(id: "global-fee-${todaysTimestamp}" ) { + dailyGlobalInfo(id: "global-fee-${startOfDay}" ) { fees } } @@ -42,7 +39,6 @@ const graphs = (graphUrls: ChainEndpoints) => { const fees = graphRes.dailyGlobalInfo.fees * (await lpPrice()) / 1e18; return { - timestamp, dailyFees: fees.toString() }; }; @@ -50,6 +46,7 @@ const graphs = (graphUrls: ChainEndpoints) => { }; const adapter: Adapter = { + version: 2, adapter: { [DISABLED_ADAPTER_KEY]: disabledAdapter, [ARBITRUM]: { diff --git a/fees/liquid-bolt.ts b/fees/liquid-bolt.ts index d0b95a521a..1ab016e99e 100644 --- a/fees/liquid-bolt.ts +++ b/fees/liquid-bolt.ts @@ -72,8 +72,10 @@ const getAdapter = () => { methodology } }, - [CHAIN.POLYGON]: { - fetch: fetch(CHAIN.POLYGON), + [CHAIN.POLYGON]: { // no longer in api response + fetch: async (timestamp: number) => ({ + timestamp + }), start: 1669312800, runAtCurrTime: true, meta: { diff --git a/fees/liquid-collective/index.ts b/fees/liquid-collective/index.ts new file mode 100644 index 0000000000..fc5a584f13 --- /dev/null +++ b/fees/liquid-collective/index.ts @@ -0,0 +1,35 @@ +// https://docs.liquidcollective.io/v1/faqs#what-is-the-protocol-service-fee +import { Adapter, FetchOptions, FetchResultV2 } from "../../adapters/types"; +import { ETHEREUM } from "../../helpers/chains"; +import ADDRESSES from "../../helpers/coreAssets.json"; + +const lsETH = "0x8c1BEd5b9a0928467c9B1341Da1D7BD5e10b6549"; +const event = "event PulledELFees(uint256 amount)"; +const WETH = ADDRESSES.ethereum.WETH; + +const fetch = async (options: FetchOptions): Promise => { + const dailyFees = options.createBalances(); + const fees = await options.getLogs({ + target: lsETH, + eventAbi: event, + }); + + dailyFees.add(WETH, fees); + return { dailyFees }; +}; + +const adapter: Adapter = { + adapter: { + [ETHEREUM]: { + fetch, + start: 1668812400, + meta: { + methodology: + "The Liquid Collective protocol charges a service fee set at 15.0% of network rewards, split amongst Node Operators, Platforms, Wallet & Custody Providers, Service Providers, the protocol's Slashing Coverage Treasury, and the Liquid Collective DAO, which comprises a broad and dispersed community of protocol participants", + }, + }, + }, + version: 2, +}; + +export default adapter; diff --git a/fees/liquity.ts b/fees/liquity.ts index 9a800950e9..9f19dc0bc1 100644 --- a/fees/liquity.ts +++ b/fees/liquity.ts @@ -1,9 +1,10 @@ +import * as sdk from "@defillama/sdk"; import { Adapter, ChainBlocks, FetchOptions, } from "../adapters/types"; import { CHAIN } from "../helpers/chains"; const { request, gql } = require("graphql-request"); -const URL = 'https://api.thegraph.com/subgraphs/name/liquity/liquity' +const URL = sdk.graph.modifyEndpoint('8wump5sEYBV7vG1sKaNrvbqhTAV4EPKCdPw4ygms3Dmd') interface IValue { totalBorrowingFeesPaid: string; totalRedemptionFeesPaid: string; diff --git a/fees/lista-lisusd/index.ts b/fees/lista-lisusd/index.ts new file mode 100644 index 0000000000..1dfa647577 --- /dev/null +++ b/fees/lista-lisusd/index.ts @@ -0,0 +1,177 @@ +import BigNumber from "bignumber.js"; +import { FetchOptions, SimpleAdapter } from "../../adapters/types"; +import { CHAIN } from "../../helpers/chains"; +import ADDRESSES from "../../helpers/coreAssets.json"; + +const treasury = "0x8d388136d578dCD791D081c6042284CED6d9B0c6"; + +/** + * Fetches data from Lista DAO + * @doc https://listaorg.notion.site/Profit-cfd754931df449eaa9a207e38d3e0a54 + * @test npx ts-node --transpile-only cli/testAdapter.ts fees lista-lisusd + * + * @treasury + * https://bscscan.com/address/0x8d388136d578dcd791d081c6042284ced6d9b0c6#tokentxns + * https://bscscan.com/address/0x34b504a5cf0ff41f8a480580533b6dda687fa3da#tokentxns + */ + +const HelioETHProvider = "0x0326c157bfF399e25dd684613aEF26DBb40D3BA4"; +// const MasterVault = "0x986b40C2618fF295a49AC442c5ec40febB26CC54"; +const SnBnbYieldConverterStrategy = + "0x6F28FeC449dbd2056b76ac666350Af8773E03873"; +const CeETHVault = "0xA230805C28121cc97B348f8209c79BEBEa3839C0"; +const HayJoin = "0x4C798F81de7736620Cd8e6510158b1fE758e22F7"; + +// token +const lista = "0xFceB31A79F71AC9CBDCF853519c1b12D379EdC46"; +const slisBNB = "0xb0b84d294e0c75a6abe60171b70edeb2efd14a1b"; +const eth = "0x2170Ed0880ac9A755fd29B2688956BD959F933F8"; +const bnb = "0xbb4CdB9CBd36B01bD1cBaEBF2De08d9173bc095c"; +const lisUSD = "0x0782b6d8c4551B9760e74c0545a9bCD90bdc41E5"; + +const fetch = async (options: FetchOptions) => { + const dailyFees = options.createBalances(); + + const logs_claim = await options.getLogs({ + target: HelioETHProvider, + eventAbi: "event Claim(address recipient, uint256 amount)", + entireLog: true, + }); + + // enable later + // const logs_fees_claim = await options.getLogs({ + // target: MasterVault, + // eventAbi: "event FeeClaimed(address receiver, uint256 amount)", + // }); + + const logs_fees_harvested = await options.getLogs({ + target: SnBnbYieldConverterStrategy, + eventAbi: "event Harvested(address to, uint256 amount)", + }); + + // CeETHVault + const eth_transfer1 = await options.getLogs({ + target: eth, + topics: [ + "0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef", + "0x000000000000000000000000a230805c28121cc97b348f8209c79bebea3839c0", + "0x0000000000000000000000008d388136d578dcd791d081c6042284ced6d9b0c6", + ], + }); + + const eth_transfer2 = await options.getLogs({ + target: eth, + topics: [ + "0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef", + "0x000000000000000000000000a230805c28121cc97b348f8209c79bebea3839c0", + "0x00000000000000000000000034b504a5cf0ff41f8a480580533b6dda687fa3da", + ], + }); + + // flash loan + const lisusd_transfer1 = await options.getLogs({ + target: lisUSD, + topics: [ + "0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef", + "0x000000000000000000000000a230805c28121cc97b348f8209c79bebea3839c0", + "0x0000000000000000000000008d388136d578dcd791d081c6042284ced6d9b0c6", + ], + }); + + const lisusd_transfer2 = await options.getLogs({ + target: lisUSD, + topics: [ + "0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef", + "0x000000000000000000000000a230805c28121cc97b348f8209c79bebea3839c0", + "0x00000000000000000000000034b504a5cf0ff41f8a480580533b6dda687fa3da", + ], + }); + + // early exit + const logs_exit1 = await options.getLogs({ + target: HayJoin, + topics: [ + "0x22d324652c93739755cf4581508b60875ebdd78c20c0cff5cf8e23452b299631", + "0x0000000000000000000000008d388136d578dcd791d081c6042284ced6d9b0c6", + ], + }); + + const logs_exit2 = await options.getLogs({ + target: HayJoin, + topics: [ + "0x22d324652c93739755cf4581508b60875ebdd78c20c0cff5cf8e23452b299631", + "0x00000000000000000000000034b504a5cf0ff41f8a480580533b6dda687fa3da", + ], + }); + + // claim penalty + const early_claim_penalty1 = await options.getLogs({ + target: lista, + topics: [ + "0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef", + "0x000000000000000000000000d0c380d31db43cd291e2bbe2da2fd6dc877b87b3", + "0x0000000000000000000000008d388136d578dcd791d081c6042284ced6d9b0c6", + ], + }); + + const early_claim_penalty2 = await options.getLogs({ + target: lista, + topics: [ + "0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef", + "0x000000000000000000000000d0c380d31db43cd291e2bbe2da2fd6dc877b87b3", + "0x00000000000000000000000034b504a5cf0ff41f8a480580533b6dda687fa3da", + ], + }); + + [...early_claim_penalty1, ...early_claim_penalty2].forEach((log) => { + const amount = Number(log.data); + dailyFees.add(lista, amount); + }); + + logs_claim.forEach((log) => { + const amount = Number(log.data); + dailyFees.add(eth, amount); + }); + + // enable later + // logs_fees_claim.forEach((log) => { + // const amount = log.amount; + // dailyFees.add(bnb, amount); + // }); + + logs_fees_harvested.forEach((log) => { + const amount = log.amount; + dailyFees.add(slisBNB, amount); + }); + + [...eth_transfer1, ...eth_transfer2].forEach((log) => { + const amount = Number(log.data); + dailyFees.add(eth, amount); + }); + + [...lisusd_transfer1, ...lisusd_transfer2].forEach((log) => { + const amount = Number(log.data); + dailyFees.add(lisUSD, amount); + }); + + [...logs_exit1, ...logs_exit2].forEach((log) => { + dailyFees.add(lisUSD, Number(log.data)); + }); + + return { + dailyFees, + dailyRevenue: dailyFees, + }; +}; + +const adapter: SimpleAdapter = { + version: 2, + adapter: { + [CHAIN.BSC]: { + fetch, + start: 1693361953, + }, + }, +}; + +export default adapter; diff --git a/fees/lista-slisbnb/index.ts b/fees/lista-slisbnb/index.ts new file mode 100644 index 0000000000..508b0e6de6 --- /dev/null +++ b/fees/lista-slisbnb/index.ts @@ -0,0 +1,50 @@ +import { FetchOptions, SimpleAdapter } from "../../adapters/types"; +import { CHAIN } from "../../helpers/chains"; + +const treasury = "0x8d388136d578dCD791D081c6042284CED6d9B0c6"; + +/** + * Fetches data from Lista DAO + * @doc https://listaorg.notion.site/Profit-cfd754931df449eaa9a207e38d3e0a54 + * @test npx ts-node --transpile-only cli/testAdapter.ts fees lista-slisbnb + * + * @treasury + * https://bscscan.com/address/0x8d388136d578dcd791d081c6042284ced6d9b0c6#tokentxns + * https://bscscan.com/address/0x34b504a5cf0ff41f8a480580533b6dda687fa3da#tokentxns + */ + +const ListaStakeManagerAddress = "0x1adB950d8bB3dA4bE104211D5AB038628e477fE6"; + +// token +const slisBNB = "0xb0b84d294e0c75a6abe60171b70edeb2efd14a1b"; + +const fetch = async (options: FetchOptions) => { + const dailyFees = options.createBalances(); + + const logs_reward = await options.getLogs({ + target: ListaStakeManagerAddress, + eventAbi: "event RewardsCompounded(uint256 _amount)", + }); + + logs_reward.forEach((log) => { + const amount = log._amount; + dailyFees.add(slisBNB, amount); + }); + + return { + dailyFees, + dailyRevenue: dailyFees, + }; +}; + +const adapter: SimpleAdapter = { + version: 2, + adapter: { + [CHAIN.BSC]: { + fetch, + start: 1693361953, + }, + }, +}; + +export default adapter; diff --git a/fees/llamalend.ts b/fees/llamalend.ts index 6c07ac9ad0..aa2f149f7c 100644 --- a/fees/llamalend.ts +++ b/fees/llamalend.ts @@ -1,3 +1,4 @@ +import * as sdk from "@defillama/sdk"; import { Adapter } from "../adapters/types"; import { CHAIN } from "../helpers/chains"; import { request, } from "graphql-request"; @@ -5,7 +6,7 @@ import type { ChainBlocks, ChainEndpoints, FetchOptions } from "../adapters/type import { Chain } from '@defillama/sdk/build/general'; const endpoints = { - [CHAIN.ETHEREUM]: "https://api.thegraph.com/subgraphs/name/0xngmi/llamalend", + [CHAIN.ETHEREUM]: sdk.graph.modifyEndpoint('7cG6NVPRm4CQmfVsh4d1bYGqaWNazRyVTn3xuvdDRNPi'), } const ONE_DAY_IN_SECONDS = 60 * 60 * 24 diff --git a/fees/looksrare.ts b/fees/looksrare.ts index 5bef9d3628..c5b1af0c21 100644 --- a/fees/looksrare.ts +++ b/fees/looksrare.ts @@ -1,6 +1,5 @@ -import { Adapter, ChainBlocks, FetchOptions } from "../adapters/types"; +import { Adapter, FetchOptions } from "../adapters/types"; import { ETHEREUM } from "../helpers/chains"; -import { Chain } from '@defillama/sdk/build/general'; const address = "0x0000000000e655fae4d56241588680f86e3b2377"; const topic0_taker_bid = "0x3ee3de4684413690dee6fff1a0a4f92916a1b97d1c5a83cdf24671844306b2e3"; @@ -10,40 +9,37 @@ const eventAbis = { "TakerBid": "event TakerBid((bytes32 orderHash, uint256 orderNonce, bool isNonceInvalidated) nonceInvalidationParameters, address bidUser, address bidRecipient, uint256 strategyId, address currency, address collection, uint256[] itemIds, uint256[] amounts, address[2] feeRecipients, uint256[3] feeAmounts)", } -const graphs = (_chain: Chain) => { - return async (timestamp: number, _: ChainBlocks, { createBalances, getLogs, }: FetchOptions) => { - - const logs_bid = await getLogs({ - target: address, - topics: [topic0_taker_bid], - eventAbi:eventAbis.TakerBid - }) - - const logs_ask = await getLogs({ - target: address, - topics: [topic0_taker_ask], - eventAbi:eventAbis.TakerAsk, - }) - const logs = logs_bid.concat(logs_ask) - const dailyFees = createBalances() - logs.map((tx: any) => { - dailyFees.add(tx.currency, tx.feeAmounts[2]) - }); - - return { - timestamp, - dailyFees: dailyFees, - dailyRevenue: dailyFees, - dailyHoldersRevenue: dailyFees, - }; +const fetch = async ({ createBalances, getLogs, }: FetchOptions) => { + + const logs_bid = await getLogs({ + target: address, + topics: [topic0_taker_bid], + eventAbi: eventAbis.TakerBid + }) + + const logs_ask = await getLogs({ + target: address, + topics: [topic0_taker_ask], + eventAbi: eventAbis.TakerAsk, + }) + const logs = logs_bid.concat(logs_ask) + const dailyFees = createBalances() + logs.map((tx: any) => { + dailyFees.add(tx.currency, tx.feeAmounts[2]) + }); + + return { + dailyFees: dailyFees, + dailyRevenue: dailyFees, + dailyHoldersRevenue: dailyFees, }; }; - const adapter: Adapter = { + version: 2, adapter: { [ETHEREUM]: { - fetch: graphs(ETHEREUM), + fetch, start: 1640775864, }, } diff --git a/fees/lybra-finance.ts b/fees/lybra-finance.ts index d91112d73b..4fcb2a3d6c 100644 --- a/fees/lybra-finance.ts +++ b/fees/lybra-finance.ts @@ -1,47 +1,20 @@ -import { FetchResultFees, SimpleAdapter } from "../adapters/types"; +import { FetchOptions, SimpleAdapter } from "../adapters/types"; import { CHAIN } from "../helpers/chains"; -import * as sdk from "@defillama/sdk"; -import { getBlock } from "../helpers/getBlock"; -import { getPrices } from "../utils/prices"; -import { Chain } from "@defillama/sdk/build/general"; -import { ethers } from "ethers"; - const address = '0x97de57eC338AB5d51557DA3434828C5DbFaDA371' -const topic0_fees_distibute = '0xec0804e8e1decb589af9c4ba8ebfbacd3be98929d4d53457dfd186061f489f04'; const event_fees_distibute = 'event FeeDistribution(address indexed feeAddress,uint256 feeAmount,uint256 timestamp)'; -const contract_interface = new ethers.Interface([ - event_fees_distibute -]); -const fetch = async (timestamp: number): Promise => { - const fromTimestamp = timestamp - 60 * 60 * 24 - const toTimestamp = timestamp - const fromBlock = (await getBlock(fromTimestamp, CHAIN.ETHEREUM, {})); - const toBlock = (await getBlock(toTimestamp, CHAIN.ETHEREUM, {})); - const dailyFees = (await sdk.getEventLogs({ - target: address, - fromBlock: fromBlock, - toBlock: toBlock, - topics: [topic0_fees_distibute], - chain: CHAIN.ETHEREUM - })).map((e: any) => contract_interface.parseLog(e)) - .map((e: any) => { - return Number(e!.args.feeAmount) / 10 ** 18; - }).reduce((a: number, b: number) => a + b, 0) +const fetch = async ({ createBalances, getLogs, }: FetchOptions) => { + const logs = await getLogs({ target: address, eventAbi: event_fees_distibute }) + const dailyFees = createBalances() + logs.forEach((tx: any) => dailyFees.addUSDValue(Number(tx.feeAmount) / 10 ** 18)) const dailyRevenue = dailyFees; const dailyHoldersRevenue = dailyFees; - return { - dailyFees: `${dailyFees}`, - dailyRevenue: `${dailyRevenue}`, - dailyHoldersRevenue: `${dailyHoldersRevenue}`, - timestamp - } - + return { dailyRevenue, dailyHoldersRevenue, dailyFees, }; } - const adapter: SimpleAdapter = { + version: 2, adapter: { [CHAIN.ETHEREUM]: { fetch: fetch, diff --git a/fees/lybra-v2.ts b/fees/lybra-v2.ts index 9447186bd3..b9dcf7b450 100644 --- a/fees/lybra-v2.ts +++ b/fees/lybra-v2.ts @@ -1,47 +1,22 @@ -import { FetchResultFees, SimpleAdapter } from "../adapters/types"; +import { FetchOptions, SimpleAdapter } from "../adapters/types"; import { CHAIN } from "../helpers/chains"; -import * as sdk from "@defillama/sdk"; -import { getBlock } from "../helpers/getBlock"; -import { getPrices } from "../utils/prices"; -import { Chain } from "@defillama/sdk/build/general"; -import { ethers } from "ethers"; + const address = '0xa980d4c0C2E48d305b582AA439a3575e3de06f0E' -const topic0_fees_distibute = '0xec0804e8e1decb589af9c4ba8ebfbacd3be98929d4d53457dfd186061f489f04'; const event_fees_distibute = 'event FeeDistribution(address indexed feeAddress,uint256 feeAmount,uint256 timestamp)'; -const contract_interface = new ethers.Interface([ - event_fees_distibute -]); -const fetch = async (timestamp: number): Promise => { - const fromTimestamp = timestamp - 60 * 60 * 24 - const toTimestamp = timestamp - const fromBlock = (await getBlock(fromTimestamp, CHAIN.ETHEREUM, {})); - const toBlock = (await getBlock(toTimestamp, CHAIN.ETHEREUM, {})); - const dailyFees = (await sdk.getEventLogs({ - target: address, - fromBlock: fromBlock, - toBlock: toBlock, - topics: [topic0_fees_distibute], - chain: CHAIN.ETHEREUM - })).map((e: any) => contract_interface.parseLog(e)) - .map((e: any) => { - return Number(e!.args.feeAmount) / 10 ** 18; - }).reduce((a: number, b: number) => a + b, 0) +const fetch = async ({ createBalances, getLogs, }: FetchOptions) => { + const logs = await getLogs({ target: address, eventAbi: event_fees_distibute }) + const dailyFees = createBalances() + logs.forEach((tx: any) => dailyFees.addUSDValue(Number(tx.feeAmount) / 10 ** 18)) const dailyRevenue = dailyFees; const dailyHoldersRevenue = dailyFees; - return { - dailyFees: `${dailyFees}`, - dailyRevenue: `${dailyRevenue}`, - dailyHoldersRevenue: `${dailyHoldersRevenue}`, - timestamp - } - + return { dailyRevenue, dailyHoldersRevenue, dailyFees, }; } - const adapter: SimpleAdapter = { + version: 2, adapter: { [CHAIN.ETHEREUM]: { fetch: fetch, diff --git a/fees/lynex-v1.ts b/fees/lynex-v1.ts new file mode 100644 index 0000000000..5d201f128e --- /dev/null +++ b/fees/lynex-v1.ts @@ -0,0 +1,92 @@ +import { Chain } from "@defillama/sdk/build/general"; +import BigNumber from "bignumber.js"; +import request, { gql } from "graphql-request"; +import { Adapter, FetchOptions, FetchResultV2 } from "../adapters/types"; +import { CHAIN } from "../helpers/chains"; + +interface IPairDayData { + id: string; + dailyVolumeUSD: string; +} + +interface IPair { + id: string; + isStable: boolean; +} + +type IURL = { + [l: string | Chain]: string; +}; +interface IPair { + id: string; + volumeUSD: string; + isStable: boolean; +} + +interface IGraphResponse { + today: IPair[]; + yesterday: IPair[]; +} +const STABLE_FEES = 0.0001; +const VOLATILE_FEES = 0.0025; + +const endpoints: IURL = { + [CHAIN.LINEA]: + "https://api.studio.thegraph.com/query/59052/lynex-v1/version/latest", +}; + +const fetch = async ({ getFromBlock, getToBlock, chain}: FetchOptions): Promise => { + const [fromBlock, toBlock] = await Promise.all([getFromBlock(), getToBlock()]) + + const query = gql` + query fees { + yesterday: pairs(block: {number: ${fromBlock}}, where: {volumeUSD_gt: "0"}, first: 1000) { + id + isStable + volumeUSD + } + today: pairs(block: {number: ${toBlock}}, where: {volumeUSD_gt: "0"}, first: 1000) { + id + isStable + volumeUSD + } + } + `; + + const graphRes: IGraphResponse = await request(endpoints[chain], query); + const totalFeesToday = graphRes.today.reduce((acc, pool) => { + if (pool.isStable) { + return acc.plus(new BigNumber(pool.volumeUSD).times(STABLE_FEES)); + } else { + return acc.plus(new BigNumber(pool.volumeUSD).times(VOLATILE_FEES)); + } + }, new BigNumber(0)); + + const totalFeesYesterday = graphRes.yesterday.reduce((acc, pool) => { + if (pool.isStable) { + return acc.plus(new BigNumber(pool.volumeUSD).times(STABLE_FEES)); + } else { + return acc.plus(new BigNumber(pool.volumeUSD).times(VOLATILE_FEES)); + } + }, new BigNumber(0)); + const dailyFee = totalFeesToday.minus(totalFeesYesterday); + + return { + dailyFees: dailyFee.toString(), + dailyUserFees: dailyFee.toString(), + dailyRevenue: dailyFee.toString(), + dailyHoldersRevenue: dailyFee.toString(), + }; +}; + +const adapter: Adapter = { + version: 2, + adapter: { + [CHAIN.LINEA]: { + fetch: fetch, + start: 1691394680, + }, + }, +}; + +export default adapter; diff --git a/fees/lynex.ts b/fees/lynex.ts index d13fba111c..082a0c9b38 100644 --- a/fees/lynex.ts +++ b/fees/lynex.ts @@ -1,3 +1,4 @@ +import * as sdk from "@defillama/sdk"; import { Chain } from "@defillama/sdk/build/general"; import BigNumber from "bignumber.js"; import request, { gql } from "graphql-request"; @@ -5,7 +6,10 @@ import { Adapter, FetchResultFees } from "../adapters/types"; import { CHAIN } from "../helpers/chains"; import { getUniqStartOfTodayTimestamp } from "../helpers/getUniSubgraphVolume"; import { getTimestampAtStartOfDayUTC } from "../utils/date"; +import { FetchOptions } from "../adapters/types"; +const LYNX = '0x1a51b19ce03dbe0cb44c1528e34a7edd7771e9af'; +const bveLYNX = '0xe8a4c9b6a2b79fd844c9e3adbc8dc841eece557b'; interface IPoolData { id: number; feesUSD: string; @@ -16,26 +20,58 @@ type IURL = { } const endpoints: IURL = { - [CHAIN.LINEA]: "https://graph-query.linea.build/subgraphs/name/cryptoalgebra/analytics" + [CHAIN.LINEA]: "https://api.studio.thegraph.com/query/59052/lynex-cl/v1.0.1" } -const fetch = (chain: Chain) => { - return async (timestamp: number): Promise => { +const event_reward_added = 'event RewardAdded(address indexed rewardToken,uint256 reward,uint256 startTimestamp)'; +const event_gauge_created = 'event GaugeCreated(address indexed gauge, address creator,address internal_bribe,address indexed external_bribe,address indexed pool)' + +export const fees_bribes = async ({ getLogs, createBalances, getToBlock }: FetchOptions): Promise => { + const voter = '0x0B2c83B6e39E32f694a86633B4d1Fe69d13b63c5'; + const dailyFees = createBalances() + const logs_geuge_created = (await getLogs({ + target: voter, + fromBlock: 2207763, + toBlock: await getToBlock(), + eventAbi: event_gauge_created, + cacheInCloud: true, + })) + const bribes_contract: string[] = logs_geuge_created.map((e: any) => e.external_bribe.toLowerCase()); + + const logs = await getLogs({ + targets: bribes_contract, + eventAbi: event_reward_added, + }) + logs.map((e: any) => { + // NOTE: bveLYNX is a derivative token 1:1 to LYNX and should be counted as LYNX as it is not tracked in coingecko + if (e.rewardToken.toLowerCase() === bveLYNX) + dailyFees.add(LYNX, e.reward) + else + dailyFees.add(e.rewardToken, e.reward) + }) + return dailyFees; +} + + +const fetch = async (fetchOptions: FetchOptions): Promise => { + const chain = fetchOptions.chain; + const timestamp = fetchOptions.startOfDay; const todayTimestamp = getUniqStartOfTodayTimestamp(new Date(timestamp * 1000)); const dateId = Math.floor(getTimestampAtStartOfDayUTC(todayTimestamp) / 86400) const graphQuery = gql ` - { - algebraDayData(id: ${dateId}) { - id - feesUSD - } - } - `; + { + algebraDayData(id: ${dateId}) { + id + feesUSD + } + } + `; const graphRes: IPoolData = (await request(endpoints[chain], graphQuery)).algebraDayData; const dailyFeeUSD = graphRes; const dailyFee = dailyFeeUSD?.feesUSD ? new BigNumber(dailyFeeUSD.feesUSD) : undefined + const dailyBribesRevenue = await fees_bribes(fetchOptions) if (dailyFee === undefined) return { timestamp } return { @@ -44,14 +80,15 @@ const fetch = (chain: Chain) => { dailyUserFees: dailyFee.toString(), dailyRevenue: dailyFee.toString(), dailyHoldersRevenue: dailyFee.toString(), + dailyBribesRevenue }; - }; } const adapter: Adapter = { + version: 2, adapter: { [CHAIN.LINEA]: { - fetch: fetch(CHAIN.LINEA), + fetch: fetch, start: 1691394680, }, }, diff --git a/fees/maestro.ts b/fees/maestro.ts index ca70371b58..8ba7e968a8 100644 --- a/fees/maestro.ts +++ b/fees/maestro.ts @@ -7,6 +7,8 @@ const dispatcher: any = { [CHAIN.ETHEREUM]: "0x2ff99ee6b22aedaefd8fd12497e504b18983cb14", [CHAIN.BSC]: "0x7176456e98443a7000b44e09149a540d06733965", [CHAIN.ARBITRUM]: "0x34b5561c30a152b5882c8924973f19df698470f4", + [CHAIN.BASE]: "0xb0999731f7c2581844658a9d2ced1be0077b7397", + [CHAIN.TRON]: "TS4yvUzwmaSh4XM1scBXRgoKeVdb4oot4S" } const feesAddress = '0xB0999731f7c2581844658A9d2ced1be0077b7397' @@ -33,12 +35,35 @@ async function fetch(timestamp: number, _1: any, options: FetchOptions) { const chainAdapter = { fetch: fetch as any, start: 1656633600, } +import { queryDune } from "../helpers/dune"; + +const fetchSolana: any = async (_timestamp: number, _1: any, options: FetchOptions) => { + const dailyFees = options.createBalances(); + const value = (await queryDune("3521814", { + start: options.startTimestamp, + end: options.endTimestamp, + receiver: 'FRMxAnZgkW58zbYcE7Bxqsg99VWpJh6sMP5xLzAWNabN' + })); + dailyFees.add('So11111111111111111111111111111111111111112', value[0].fee_token_amount); + + return { dailyFees, dailyRevenue: dailyFees } + +} + + const adapter: Adapter = { adapter: { [CHAIN.ETHEREUM]: chainAdapter, [CHAIN.BSC]: chainAdapter, [CHAIN.ARBITRUM]: chainAdapter, - } + [CHAIN.SOLANA]: { + fetch: fetchSolana, + start: 1656633600, // wrong? + }, + [CHAIN.BASE]: chainAdapter, + [CHAIN.TRON]: chainAdapter, + }, + isExpensiveAdapter: true } export default adapter; diff --git a/fees/magpie.ts b/fees/magpie.ts new file mode 100644 index 0000000000..2c9d7b440b --- /dev/null +++ b/fees/magpie.ts @@ -0,0 +1,58 @@ +import { FetchOptions, SimpleAdapter } from "../adapters/types"; +import { CHAIN } from "../helpers/chains"; +import { Chain } from "@defillama/sdk/build/general"; + +const event_paid_stream = 'event RewardPaid (address indexed _user,address indexed _receiver,uint256 _reward,address indexed _rewardToken)'; +const event_paid_base = 'event RewardPaid (address indexed _user,address indexed _receiver,uint256 _reward,address indexed _token)'; + +type TAddress = { + [c: string]: string; +} +const address_stream: TAddress = { + + [CHAIN.BSC]: '0x924786bb8d6888bE49E5c27E6E2Df71D6077A2D3', + [CHAIN.ARBITRUM]: '0x2B5D9ADea07B590b638FFc165792b2C610EdA649' +} + +const address_base: TAddress = { + [CHAIN.BSC]: '0x94Eb0E6800F10E22550e104EC04f98F043B6b3ad', + [CHAIN.ARBITRUM]: '0x4E47d553FD423316094aBB07E42970A689E1f5f7' +} +//all revenue is from bribes and is given to governance token holders 100% + +const graph = (chain: Chain) => { + return async ({ createBalances, getLogs, }: FetchOptions) => { + const dailyFees = createBalances(); + (await getLogs({ + target: address_stream[chain], + eventAbi: event_paid_stream, + })).map((e: any) => { + dailyFees.add(e._rewardToken, e._reward) + }), + (await getLogs({ + target: address_base[chain], + eventAbi: event_paid_base, + })).map((e: any) => { + dailyFees.add(e._token, e._reward) + }) + return { dailyFees, dailyRevenue: dailyFees,dailyUserFees:dailyFees }; + } +} + + +const adapter: SimpleAdapter = { + version: 2, + adapter: { + + [CHAIN.BSC]: { + fetch: graph(CHAIN.BSC), + start: 77678653, + }, + [CHAIN.ARBITRUM]: { + fetch: graph(CHAIN.ARBITRUM), + start: 77678653, + }, + } +}; + +export default adapter; diff --git a/fees/makerdao.ts b/fees/makerdao.ts index ab46e2b4c4..2b3dbdba69 100644 --- a/fees/makerdao.ts +++ b/fees/makerdao.ts @@ -1,16 +1,16 @@ +import * as sdk from "@defillama/sdk"; import { Adapter } from "../adapters/types"; import { ETHEREUM } from "../helpers/chains"; import { request, gql } from "graphql-request"; -import type { ChainEndpoints } from "../adapters/types" +import type { ChainEndpoints, FetchOptions } from "../adapters/types" import { Chain } from '@defillama/sdk/build/general'; -import { getBlock } from "../helpers/getBlock"; -import { ChainBlocks } from "../adapters/types"; import BigNumber from "bignumber.js"; -import { getTimestampAtStartOfPreviousDayUTC, getTimestampAtStartOfDayUTC } from "../utils/date"; + +const RAY = new BigNumber(10).pow(27); const endpoints = { [ETHEREUM]: - "https://api.thegraph.com/subgraphs/name/protofire/maker-protocol" + sdk.graph.modifyEndpoint('CLddaQxuXLjpzyyA67FMmNjmyX74yQDQZEAsytoQTtCD') } // Source: https://makerburn.com/#/rundown @@ -26,23 +26,26 @@ const collateralYields = { [rwa:string]:number } +const MCD_POT={ + address: '0x197e90f9fad81970ba7976f33cbd77088e5d7cf7', + abis: { + Pie: {"constant":true,"inputs":[],"name":"Pie","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"}, + dsr: {"constant":true,"inputs":[],"name":"dsr","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"}, + chi: {"constant":true,"inputs":[],"name":"chi","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"}, + } as any +} + const graphs = (graphUrls: ChainEndpoints) => { return (chain: Chain) => { - return async (timestamp: number, chainBlocks: ChainBlocks) => { - const todaysTimestamp = getTimestampAtStartOfDayUTC(timestamp) - const yesterdaysTimestamp = getTimestampAtStartOfPreviousDayUTC(timestamp) - - const todaysBlock = (await getBlock(todaysTimestamp, chain, chainBlocks)); - const yesterdaysBlock = (await getBlock(yesterdaysTimestamp, chain, {})); - + return async ({getEndBlock, getStartBlock, startTimestamp, endTimestamp, toApi} : FetchOptions) => { const graphQuery = gql `query fees { - yesterday: collateralTypes(block: {number: ${yesterdaysBlock}}) { + yesterday: collateralTypes(block: {number: ${await getStartBlock()}}) { id totalDebt stabilityFee } - today: collateralTypes(block: {number: ${todaysBlock}}) { + today: collateralTypes(block: {number: ${await getEndBlock()}}) { id totalDebt stabilityFee @@ -51,7 +54,7 @@ const graphs = (graphUrls: ChainEndpoints) => { const graphRes = await request(graphUrls[chain], graphQuery); - const secondsBetweenDates = todaysTimestamp - yesterdaysTimestamp; + const secondsBetweenDates = endTimestamp - startTimestamp; const todayDebts: { [id: string]: BigNumber } = {}; let dailyFee = new BigNumber(0) @@ -70,11 +73,25 @@ const graphs = (graphUrls: ChainEndpoints) => { dailyFee = dailyFee.plus(avgDebt.multipliedBy(accFees)) } } + const sparkSupplyAPR = await toApi.call({target: "0xC13e21B648A5Ee794902342038FF3aDAB66BE987", params: ["0x6B175474E89094C44Da98b954EedeAC495271d0F"], abi:{"inputs":[{"internalType":"address","name":"asset","type":"address"}],"name":"getReserveData","outputs":[{"components":[{"components":[{"internalType":"uint256","name":"data","type":"uint256"}],"internalType":"struct DataTypes.ReserveConfigurationMap","name":"configuration","type":"tuple"},{"internalType":"uint128","name":"liquidityIndex","type":"uint128"},{"internalType":"uint128","name":"currentLiquidityRate","type":"uint128"},{"internalType":"uint128","name":"variableBorrowIndex","type":"uint128"},{"internalType":"uint128","name":"currentVariableBorrowRate","type":"uint128"},{"internalType":"uint128","name":"currentStableBorrowRate","type":"uint128"},{"internalType":"uint40","name":"lastUpdateTimestamp","type":"uint40"},{"internalType":"uint16","name":"id","type":"uint16"},{"internalType":"address","name":"aTokenAddress","type":"address"},{"internalType":"address","name":"stableDebtTokenAddress","type":"address"},{"internalType":"address","name":"variableDebtTokenAddress","type":"address"},{"internalType":"address","name":"interestRateStrategyAddress","type":"address"},{"internalType":"uint128","name":"accruedToTreasury","type":"uint128"},{"internalType":"uint128","name":"unbacked","type":"uint128"},{"internalType":"uint128","name":"isolationModeTotalDebt","type":"uint128"}],"internalType":"struct DataTypes.ReserveData","name":"","type":"tuple"}],"stateMutability":"view","type":"function"}}) + const sparkSupply = await toApi.call({target: "0x4dedf26112b3ec8ec46e7e31ea5e123490b05b8b", params: ["0xAfA2DD8a0594B2B24B59de405Da9338C4Ce23437"], abi:"erc20:balanceOf"}) + const SECONDS_IN_YEAR = 365*24*60*60 + const sparkSupplyAPY = (sparkSupplyAPR.currentLiquidityRate/1e27 / SECONDS_IN_YEAR + 1)**(24*3600) - 1 + + dailyFee = dailyFee.plus(sparkSupplyAPY*sparkSupply/1e18) + + const [Pie, chi, dsr] = await Promise.all(["Pie", "chi", "dsr"].map(async name=>( + await toApi.call({ + target: MCD_POT.address, + abi: MCD_POT.abis[name], + }) + ))) + const dsrTvl = BigNumber(Pie).times(chi).div(1e18).div(RAY) // check against https://makerburn.com/#/ + const dsrExpenses = BigNumber(dsr).div(RAY).pow(60*60*24).minus(1).times(dsrTvl) return { - timestamp, dailyFees: dailyFee.toString(), - dailyRevenue: dailyFee.toString(), + dailyRevenue: dailyFee.minus(dsrExpenses).toString(), }; }; }; @@ -82,6 +99,7 @@ const graphs = (graphUrls: ChainEndpoints) => { const adapter: Adapter = { + version: 2, adapter: { [ETHEREUM]: { fetch: graphs(endpoints)(ETHEREUM), diff --git a/fees/manifold.ts b/fees/manifold.ts new file mode 100644 index 0000000000..01be640f99 --- /dev/null +++ b/fees/manifold.ts @@ -0,0 +1,61 @@ +import { Adapter, FetchOptions } from "../adapters/types"; +import { queryDune, queryDuneSql } from "../helpers/dune"; +import { nullAddress } from "../helpers/token"; + +// Found by looking at contracts deployed by 0xa8863bf1c8933f649e7b03eb72109e5e187505ea +// Yes, i manually checked hundreds of txs T_T + +const CREATE2_CONTRACTS = ["0x1eb73fee2090fb1c20105d5ba887e3c3ba14a17e", "0x04ba6cf3c5aa6d4946f5b7f7adf111012a9fac65", "0x23aa05a271debffaa3d75739af5581f744b326e4", "0x26bbea7803dcac346d5f5f135b57cf2c752a02be", "0xfc29813beeb3c7395c7a5f8dfc3352491d5ea0e2"] +const contracts = { + ethereum: ["0x3b8c2feb0f4953870f825df64322ec967aa26b8c", "0xDb8d79C775452a3929b86ac5DEaB3e9d38e1c006", ...CREATE2_CONTRACTS], // missing old burn redeem and erc721 burn redeem + optimism: CREATE2_CONTRACTS, + base: CREATE2_CONTRACTS, +} as any + + +const evm = async (options: FetchOptions) => { + const pre = await options.fromApi.sumTokens({ + token: nullAddress, + owners: contracts[options.chain] + }) + const post = await options.toApi.sumTokens({ + token: nullAddress, + owners: contracts[options.chain] + }) as any + const dailyFees = options.createBalances(); + dailyFees.addBalances(post) + dailyFees.subtract(pre) + if(Number(Object.values(dailyFees.getBalances())[0])<0){ + /* + When a new NFT is minted, a fee gets paid, the fee changes based on whether the NFT was minted with no whitelist or with a merkle whitelist + However there's no event emitted that can be used to differentiate those two cases, so its impossible to track exact fees via events, only upper and lower bounds + Because of that, the best way to track fees would be to track the difference in ETH balance for the contract and then subtract any withdrawal from the team + But withdrawals don't emit any event + So, given that withdrawals are very rare, what we do is just track the balance difference and when there's a withdrawal we fetch from traces + */ + const nativeTransfers = await queryDuneSql(options, `select sum(value) as withdrawn from CHAIN.traces + where "from" IN (${contracts[options.chain].join(', ')}) + AND to IN (0x93fd235c56964e0ffb49229e8d642c3fd81310a5, 0xfa0f022aac5a1fd99094df8aadb947ce08f79d5b, 0x3a0079197027d80c260f8cd482210fdc48ec51e5, 0x267bfe2905dccec10cb22115ca1d0b1da11ddad5) + AND success = TRUE + AND TIME_RANGE`) + dailyFees.add(nullAddress, nativeTransfers[0].withdrawn) + } + + return { + dailyFees: dailyFees, + dailyRevenue: dailyFees, + } +} + +const adapter: Adapter = { + version: 2, + adapter: Object.keys(contracts).reduce((all, chain) => ({ + ...all, + [chain]: { + fetch: evm, + start: 0, + } + }), {}) +} + +export default adapter; \ No newline at end of file diff --git a/fees/manta.ts b/fees/manta.ts index 6c79be53c2..517b222e73 100644 --- a/fees/manta.ts +++ b/fees/manta.ts @@ -9,6 +9,7 @@ const ethereumWallets = [ ] const adapter: Adapter = { + version: 2, adapter: { [CHAIN.MANTA]: { fetch: L2FeesFetcher({ ethereumWallets }), diff --git a/fees/marinade-liquid-staking/index.ts b/fees/marinade-liquid-staking/index.ts index 2af2fab0cb..70c5b47229 100644 --- a/fees/marinade-liquid-staking/index.ts +++ b/fees/marinade-liquid-staking/index.ts @@ -15,7 +15,7 @@ interface MarinadeAmounts { totalUserFees: string; } -const fetch = async (timestamp: number, _:ChainBlocks, { createBalances }: FetchOptions): Promise => { +const fetch = async ({ createBalances }: FetchOptions) => { // Amounts in SOL lamports const amounts: MarinadeAmounts = (await fetchURL('https://stats-api.marinade.finance/v1/integrations/defillama/fees')).liquid const coin = 'So11111111111111111111111111111111111111112' @@ -42,7 +42,6 @@ const fetch = async (timestamp: number, _:ChainBlocks, { createBalances }: Fetch totalUserFees.add(coin, amounts.totalUserFees); return { - timestamp: timestamp, dailyFees, totalFees, dailyUserFees, @@ -57,6 +56,7 @@ const fetch = async (timestamp: number, _:ChainBlocks, { createBalances }: Fetch } const adapter: SimpleAdapter = { + version: 2, adapter: { [CHAIN.SOLANA]: { fetch, diff --git a/fees/marinade-native/index.ts b/fees/marinade-native/index.ts index a50cd9e173..3a1fb812a7 100644 --- a/fees/marinade-native/index.ts +++ b/fees/marinade-native/index.ts @@ -15,7 +15,7 @@ interface MarinadeAmounts { totalUserFees: string; } -const fetch = async (timestamp: number, _: ChainBlocks, { createBalances }: FetchOptions): Promise => { +const fetch = async ({ createBalances }: FetchOptions) => { // Amounts in SOL lamports const amounts: MarinadeAmounts = (await fetchURL('https://stats-api.marinade.finance/v1/integrations/defillama/fees')).native const coin = 'So11111111111111111111111111111111111111112' @@ -42,7 +42,6 @@ const fetch = async (timestamp: number, _: ChainBlocks, { createBalances }: Fetc totalUserFees.add(coin, amounts.totalUserFees); return { - timestamp: timestamp, totalFees, dailyFees, dailyUserFees, @@ -57,6 +56,7 @@ const fetch = async (timestamp: number, _: ChainBlocks, { createBalances }: Fetc } const adapter: SimpleAdapter = { + version: 2, adapter: { [CHAIN.SOLANA]: { fetch, diff --git a/fees/maverick.ts b/fees/maverick.ts index e6f12f76b6..38cea7fd06 100644 --- a/fees/maverick.ts +++ b/fees/maverick.ts @@ -1,7 +1,7 @@ // Maverick v1 fee import { SimpleAdapter } from "../adapters/types"; import { CHAIN } from "../helpers/chains"; -import { fetchFee } from "../dexs/maverick/maverick"; +import { fetchFeeV1, maverickV1Factories } from "../dexs/maverick/maverick-v1"; const methodology = { UserFees: "LPs collect 100% of the fee generated in a pool", @@ -11,34 +11,23 @@ const methodology = { }; const adapter: SimpleAdapter = { + version: 2, adapter: { - [CHAIN.ETHEREUM]: { - fetch: fetchFee(CHAIN.ETHEREUM), - start: 1676851200, - meta: { - methodology, - }, - }, - [CHAIN.ERA]: { - fetch: fetchFee(CHAIN.ERA), - start: 1681257600, - meta: { - methodology, - }, - }, [CHAIN.BSC]: { - fetch: fetchFee(CHAIN.BSC), - start: 29241049, - meta: { - methodology, - }, + fetch: fetchFeeV1(), + start: maverickV1Factories[CHAIN.BSC].startTimestamp, }, [CHAIN.BASE]: { - fetch: fetchFee(CHAIN.BASE), - start: 1489614, - meta: { - methodology, - }, + fetch: fetchFeeV1(), + start: maverickV1Factories[CHAIN.BASE].startTimestamp, + }, + [CHAIN.ERA]: { + fetch: fetchFeeV1(), + start: maverickV1Factories[CHAIN.ERA].startTimestamp, + }, + [CHAIN.ETHEREUM]: { + fetch: fetchFeeV1(), + start: maverickV1Factories[CHAIN.ETHEREUM].startTimestamp, }, }, }; diff --git a/fees/memecooking/index.ts b/fees/memecooking/index.ts new file mode 100644 index 0000000000..a2e4f6ac34 --- /dev/null +++ b/fees/memecooking/index.ts @@ -0,0 +1,80 @@ +import { formatUnits } from "ethers"; +import { Adapter, FetchV2 } from "../../adapters/types"; +import { CHAIN } from "../../helpers/chains"; +import { httpGet } from "../../utils/fetchURL"; + +const API_BASE_URL = "https://api.meme.cooking"; + +type MemeCookingStats = { + total_volume: string; + total_protocol_fees: string; + total_referral_fees: string; + total_withdraw_fees: string; +}; + +const fetch: FetchV2 = async ({ endTimestamp, createBalances }) => { + const dateString = new Date(endTimestamp * 1000).toISOString().split("T")[0]; + const { + total_volume: daily_volume, + total_protocol_fees: daily_protocol_fees, + total_referral_fees: daily_referral_fees, + total_withdraw_fees: daily_withdraw_fees, + }: MemeCookingStats = await httpGet( + `${API_BASE_URL}/info/daily-stats?date=${dateString}` + ); + + const dailyVolume = createBalances(); + dailyVolume.addCGToken("near", +formatUnits(daily_volume, 24)); + + const dailyFees = createBalances(); + dailyFees.addCGToken( + "near", + +formatUnits( + ( + BigInt(daily_protocol_fees) + + BigInt(daily_referral_fees) + + BigInt(daily_withdraw_fees) + ).toString(), + 24 + ) + ); + + const dailyRevenue = createBalances(); + dailyRevenue.addCGToken("near", +formatUnits(daily_protocol_fees, 24)); + + const dailySupplySideRevenue = createBalances(); + dailySupplySideRevenue.addCGToken( + "near", + +formatUnits(daily_withdraw_fees, 24) + ); + + return { + dailyVolume, + dailyFees, + dailyRevenue, + dailySupplySideRevenue, + }; +}; + +const adapter: Adapter = { + adapter: { + [CHAIN.NEAR]: { + start: 1727708400, + fetch, + meta: { + methodology: { + Volume: + "All deposits and withdrawals into currently ongoing auctions", + Fees: "Fees from deposits (0.5%), withdrawals (2%) and referrals (shares 50% of deposit fee)", + Revenue: "All fees from deposits are for the protocol", + SupplySideRevenue: + "There is a 2% withdrawal fee, which gets redistributed to all depositors of the same auction", + }, + }, + runAtCurrTime: true, + }, + }, + version: 2, +}; + +export default adapter; diff --git a/fees/meowl/index.ts b/fees/meowl/index.ts index 052b801b70..da97508efc 100644 --- a/fees/meowl/index.ts +++ b/fees/meowl/index.ts @@ -4,17 +4,17 @@ import { CHAIN } from "../../helpers/chains"; const adapter: Adapter = { adapter: { [CHAIN.ETHEREUM]: { - fetch: async (timestamp: number) => { + fetch: async () => { const fees = 0; return { - timestamp, dailyFees: fees.toString(), dailyRevenue: fees.toString(), }; }, start: 1685332595 }, - } + }, + version: 2 } export default adapter; diff --git a/fees/merchant-moe-dex.ts b/fees/merchant-moe-dex.ts new file mode 100644 index 0000000000..9326801b47 --- /dev/null +++ b/fees/merchant-moe-dex.ts @@ -0,0 +1,7 @@ +import { uniV2Exports } from "../helpers/uniswap"; + +export default uniV2Exports({ + mantle: { + factory: '0x5bef015ca9424a7c07b68490616a4c1f094bedec', + } +}) \ No newline at end of file diff --git a/fees/merlin.ts b/fees/merlin.ts index 12f3aabbf3..45ba2aaef4 100644 --- a/fees/merlin.ts +++ b/fees/merlin.ts @@ -55,7 +55,7 @@ const adapter: Adapter = { adapter: { [DISABLED_ADAPTER_KEY]: disabledAdapter, [CHAIN.ERA]: { - fetch: fetch(CHAIN.ERA), + fetch: async (timestamp: number) => {return{timestamp}}, start: 1680274800, }, }, diff --git a/fees/metamask.ts b/fees/metamask.ts index d2f976ee2e..518880d044 100644 --- a/fees/metamask.ts +++ b/fees/metamask.ts @@ -38,12 +38,14 @@ const graph = (chain: Chain) => { TX_HASH from ${chain}.core.fact_transactions - WHERE to_address = '${address[chain]}' - and BLOCK_NUMBER > ${await getFromBlock()} AND BLOCK_NUMBER < ${await getToBlock()} + WHERE + BLOCK_NUMBER > ${await getFromBlock()} AND BLOCK_NUMBER < ${await getToBlock()} + and to_address = '${address[chain]}' + and status = 'SUCCESS' ` - const value: string[][] = (await queryFlipside(query, 510)) + const value: string[][] = (await queryFlipside(query, 260)) const rawData = value.map((a: string[]) => { const data = a[0].replace('0x5f575529', ''); const address = data.slice(64, 128); @@ -90,8 +92,10 @@ const adapter: Adapter = { [CHAIN.ARBITRUM]: { fetch: graph(CHAIN.ARBITRUM), start: 1672531200, + runAtCurrTime: true, } - } + }, + isExpensiveAdapter: true, } export default adapter; diff --git a/fees/metaplex.ts b/fees/metaplex.ts new file mode 100644 index 0000000000..89c9443939 --- /dev/null +++ b/fees/metaplex.ts @@ -0,0 +1,34 @@ +import { FetchOptions, SimpleAdapter } from "../adapters/types" +import { CHAIN } from "../helpers/chains" +import { httpGet } from "../utils/fetchURL" + +const METAPLEX_API_KEY = process.env.METAPLEX_API_KEY +const url = `https://analytics.topledger.xyz/metaplex/api/queries/10849/results.json?api_key=${METAPLEX_API_KEY}` + +interface IFees { + block_date: string; + revenue_in_usd: number; + cumulative_revenue_in_usd: number; +} +const fetchFees = async (timestamp: number, _t: any, options: FetchOptions) => { + const res: IFees[] = (await httpGet(url)).query_result.data.rows; + const dateStr = new Date(options.startOfDay * 1000).toISOString().split('T')[0] + const dailyItem = res.find(item => item.block_date === dateStr) + return { + dailyFees: dailyItem?.revenue_in_usd || 0, + totalFees: dailyItem?.cumulative_revenue_in_usd || 0, + dailyRevenue: dailyItem?.revenue_in_usd || 0, + totalRevenue: dailyItem?.cumulative_revenue_in_usd || 0, + timestamp, + } +} + +const adapter: SimpleAdapter = { + adapter: { + [CHAIN.SOLANA]: { + fetch: fetchFees, + start: 1631952000, + } + } +} +export default adapter diff --git a/fees/metavault-derivatives-v2/index.ts b/fees/metavault-derivatives-v2/index.ts index 2aac2caeac..9dc50a70cd 100644 --- a/fees/metavault-derivatives-v2/index.ts +++ b/fees/metavault-derivatives-v2/index.ts @@ -1,3 +1,4 @@ +import * as sdk from "@defillama/sdk"; import { Chain } from "@defillama/sdk/build/general"; import { gql, request } from "graphql-request"; import type { ChainEndpoints } from "../../adapters/types"; @@ -6,18 +7,24 @@ import { CHAIN } from "../../helpers/chains"; import { getTimestampAtStartOfDayUTC } from "../../utils/date"; -const endpoints = { +const endpoints: ChainEndpoints = { [CHAIN.LINEA]: - "https://linea-graph-node.metavault.trade/subgraphs/name/metavault/perpv1", + "https://api.studio.thegraph.com/query/55804/linea-trade/version/latest", + [CHAIN.POLYGON]: + sdk.graph.modifyEndpoint('GAvL1WKMAVDdnSk96qvmSCMwL6pxfhAVYkQw6AgZU3td'), }; +interface IFeeStat { + cumulativeFeeUsd: string; + feeUsd: string; + id: string; +} -const graphs = (graphUrls: ChainEndpoints) => { - return (chain: Chain) => { - return async (timestamp: number) => { - const todaysTimestamp = getTimestampAtStartOfDayUTC(timestamp); - const period = "daily"; +const fetch = (endpoint) => { + return async (timestamp: number) => { + const todaysTimestamp = getTimestampAtStartOfDayUTC(timestamp); + const period = "daily"; - const graphQuery = gql`{ + const graphQuery = gql`{ feeStats(where: {timestamp: ${todaysTimestamp}, period: "${period}"}) { id timestamp @@ -28,28 +35,41 @@ const graphs = (graphUrls: ChainEndpoints) => { } }`; - const graphRes = await request(graphUrls[chain], graphQuery); + const response = await request(endpoint, graphQuery); + const feeStats: IFeeStat[] = response.feeStats; - const dailyFee = parseInt(graphRes.feeStats[0].feeUsd); + let dailyFeeUSD = BigInt(0); + let totalFeeUSD = BigInt(0); - const finalDailyFee = dailyFee / 1e18; - const totalFees = parseInt(graphRes.feeStats[0].cumulativeFeeUsd) / 1e18; + feeStats.forEach((fee) => { + dailyFeeUSD += BigInt(fee.feeUsd); + totalFeeUSD += BigInt(fee.cumulativeFeeUsd); + }); - return { - timestamp, - dailyFees: finalDailyFee.toString(), - totalFees: totalFees.toString(), - //dailyRevenue: (finalDailyFee * 0.3).toString(), - }; + const finalDailyFee = parseInt(dailyFeeUSD.toString()) / 1e18; + const finalTotalFee = parseInt(totalFeeUSD.toString()) / 1e18; + + return { + timestamp: todaysTimestamp, + dailyFees: finalDailyFee.toString(), + totalFees: finalTotalFee.toString(), }; }; }; const adapter: Adapter = { + version: 1, adapter: { [CHAIN.LINEA]: { - fetch: graphs(endpoints)(CHAIN.LINEA), - start: 1701950449, + fetch: fetch(endpoints[CHAIN.LINEA]), + start: 1709251200, + meta: { + methodology: "All treasuryFee, poolFee and keeperFee are collected", + }, + }, + [CHAIN.POLYGON]: { + fetch: fetch(endpoints[CHAIN.POLYGON]), + start: 1709251200, meta: { methodology: "All treasuryFee, poolFee and keeperFee are collected", }, diff --git a/fees/metavault.trade/index.ts b/fees/metavault.trade/index.ts index 32f680dbe4..ab4dcb855d 100644 --- a/fees/metavault.trade/index.ts +++ b/fees/metavault.trade/index.ts @@ -1,3 +1,4 @@ +import * as sdk from "@defillama/sdk"; import { Chain } from "@defillama/sdk/build/general"; import { gql, request } from "graphql-request"; import type { ChainEndpoints } from "../../adapters/types"; @@ -6,7 +7,7 @@ import { POLYGON } from "../../helpers/chains"; import { getTimestampAtStartOfDayUTC } from "../../utils/date"; const endpoints = { - [POLYGON]: "https://api.thegraph.com/subgraphs/name/sdcrypt0/metavault-mvx-subgraph", + [POLYGON]: sdk.graph.modifyEndpoint('BMn9XsegbLxw9TL6uyw5NntoiGRyMqRpF2vShkKzusJ3'), }; const graphs = (graphUrls: ChainEndpoints) => { @@ -43,6 +44,7 @@ const graphs = (graphUrls: ChainEndpoints) => { }; const adapter: Adapter = { + version: 1, adapter: { [POLYGON]: { fetch: graphs(endpoints)(POLYGON), diff --git a/fees/mevx.ts b/fees/mevx.ts new file mode 100644 index 0000000000..3053a5201b --- /dev/null +++ b/fees/mevx.ts @@ -0,0 +1,27 @@ +import { FetchOptions, SimpleAdapter } from "../adapters/types"; +import { CHAIN } from "../helpers/chains"; +import { queryDune } from "../helpers/dune"; + +const fetch: any = async (options: FetchOptions) => { + const dailyFees = options.createBalances(); + const value = (await queryDune("3967214", { + start: options.startTimestamp, + end: options.endTimestamp, + })); + dailyFees.add('So11111111111111111111111111111111111111112', value[0].fee_token_amount); + + return { dailyFees, dailyRevenue: dailyFees } +} + +const adapter: SimpleAdapter = { + version: 2, + adapter: { + [CHAIN.SOLANA]: { + fetch: fetch, + start: 0, + }, + }, + isExpensiveAdapter: true +}; + +export default adapter; diff --git a/fees/milkyway.ts b/fees/milkyway.ts new file mode 100644 index 0000000000..fa19bcea0d --- /dev/null +++ b/fees/milkyway.ts @@ -0,0 +1,56 @@ +import { Adapter, FetchV2 } from "../adapters/types"; +import { httpGet } from "../utils/fetchURL"; + +interface FeeResponse { + staking_rewards: number; + fees: number; + supply_side_revenue: number; +} + + +const fetch: FetchV2 = async ({ startTimestamp, endTimestamp, createBalances }) => { + const startDate = new Date(startTimestamp * 1000); + const endDate = new Date(endTimestamp * 1000); + const params = { + from: startDate.toISOString(), + to: endDate.toISOString(), + currency: 'tia' + } + const response: FeeResponse = await httpGet('https://apis.milkyway.zone/milktia/fees/range', { params }); + const dailyUserFees = createBalances() + const dailyStakingRewards = createBalances() + const dailySupplySideRevenue = createBalances() + dailyUserFees.addCGToken('celestia', response.fees); + dailyStakingRewards.addCGToken('celestia', response.staking_rewards); + dailySupplySideRevenue.addCGToken('celestia', response.supply_side_revenue); + return { + dailyUserFees, + dailyFees: dailyStakingRewards, + dailyRevenue: dailyUserFees, + dailyProtocolRevenue: dailyUserFees, + dailySupplySideRevenue, + }; +}; + +const adapter: Adapter = { + adapter: { + osmosis: { + fetch, + runAtCurrTime: false, + // 2024-04-30T17:55:14:00Z + start: 1714499714, + meta: { + methodology: { + UserFees: "MilkyWay takes 10% fee on users staking rewards", + Fees: "Staking rewards earned by all staked TIA", + Revenue: "MilkyWay takes 10% fee on users staking rewards", + ProtocolRevenue: "MilkyWay takes 10% fee on users staking rewards", + SuplySideRevenue: "Staking rewards earned by milkTIA holders", + }, + } + }, + }, + version: 2 +}; + +export default adapter; // yarn test fees milktia diff --git a/fees/mimo.ts b/fees/mimo.ts index dc090d8edd..9482aa1f96 100644 --- a/fees/mimo.ts +++ b/fees/mimo.ts @@ -1,7 +1,7 @@ import { CHAIN } from "../helpers/chains"; -import { univ2DimensionAdapter } from "../helpers/getUniSubgraph"; +import { univ2DimensionAdapter2 } from "../helpers/getUniSubgraph"; -const adapter = univ2DimensionAdapter({ +const adapter = univ2DimensionAdapter2({ graphUrls: { [CHAIN.IOTEX]: "https://graph.mimo.exchange/subgraphs/name/mimo/mainnet" }, @@ -9,11 +9,6 @@ const adapter = univ2DimensionAdapter({ factory: "uniswapFactories", field: "totalVolumeUSD", }, - dailyVolume: { - factory: "uniswapDayData", - field: "dailyVolumeUSD", - dateField: "date" - }, feesPercent: { type: "volume", UserFees: 0.3, @@ -35,4 +30,6 @@ const adapter = univ2DimensionAdapter({ }); + + export default adapter; diff --git a/fees/mm-stableswap-polygon.ts b/fees/mm-stableswap-polygon.ts index 8fac0669c3..9602fb1de6 100644 --- a/fees/mm-stableswap-polygon.ts +++ b/fees/mm-stableswap-polygon.ts @@ -12,6 +12,7 @@ const feeAdapter: BaseAdapter = getDexChainFees({ }); const adapter: Adapter = { + version: 2, adapter: feeAdapter }; diff --git a/fees/mojitoswap.ts b/fees/mojitoswap.ts index c1327f1a06..ef63df4122 100644 --- a/fees/mojitoswap.ts +++ b/fees/mojitoswap.ts @@ -1,11 +1,11 @@ import { CHAIN } from "../helpers/chains"; -import { univ2DimensionAdapter } from "../helpers/getUniSubgraph"; +import { univ2DimensionAdapter2 } from "../helpers/getUniSubgraph"; const graphUrls = { [CHAIN.KCC]: "https://thegraph.kcc.network/subgraphs/name/mojito/swap", }; -const adapter = univ2DimensionAdapter({ +const adapter = univ2DimensionAdapter2({ graphUrls, feesPercent: { type: "volume", @@ -29,4 +29,5 @@ const adapter = univ2DimensionAdapter({ adapter.adapter.kcc.start = 1634200191; + export default adapter diff --git a/fees/monarchpay/index.ts b/fees/monarchpay/index.ts index 2b749012b6..a060ec70b0 100644 --- a/fees/monarchpay/index.ts +++ b/fees/monarchpay/index.ts @@ -1,40 +1,23 @@ -import { Adapter, FetchResultFees } from "../../adapters/types"; +import { Adapter, FetchOptions } from "../../adapters/types"; import { CHAIN } from "../../helpers/chains"; -import { getTimestampAtStartOfDayUTC, getTimestampAtStartOfNextDayUTC } from "../../utils/date"; -import * as sdk from "@defillama/sdk"; -import { getBlock } from "../../helpers/getBlock"; const address = '0x0296fD8b25D2f7B0B434eD4423BFA0CC47D08276'; -interface ITx { - data: string; - transactionHash: string; -} - -const fetch = async (timestamp: number): Promise => { - const fromTimestamp = timestamp - 60 * 60 * 24 - const toTimestamp = timestamp - - const fromBlock = (await getBlock(fromTimestamp, CHAIN.KAVA, {})); - const toBlock = (await getBlock(toTimestamp, CHAIN.KAVA, {})); - const logs: ITx[] = (await sdk.getEventLogs({ +const fetch = async ({ getLogs }: FetchOptions) => { + const logs = (await getLogs({ target: address, - fromBlock: fromBlock, - toBlock: toBlock, topics: ['0xfee17e5caac7cbef9c34199cc11ac3c5a17abb3b07d5835053be283278606e43'], - chain: CHAIN.KAVA - })).map((e: any) => { return { data: e.data.replace('0x', ''), transactionHash: e.transactionHash } as ITx}); - const dailyFees = logs.map((tx: ITx) => { - const amount = Number('0x' + tx.data) / 10 ** 6; - return amount; - }).reduce((a: number, b: number) => a+b,0); + })) + const dailyFees = logs.map((tx: any) => { + return Number('0x' + tx.data) / 10 ** 6; + }).reduce((a: number, b: number) => a + b, 0); return { - timestamp: timestamp, - dailyFees: `${dailyFees}` + dailyFees: dailyFees }; } const adapter: Adapter = { + version: 2, adapter: { [CHAIN.KAVA]: { fetch: fetch, diff --git a/fees/mooniswap.ts b/fees/mooniswap.ts index b1342cb084..14add2e3b6 100644 --- a/fees/mooniswap.ts +++ b/fees/mooniswap.ts @@ -10,6 +10,7 @@ const baseAdapter = getDexChainFees({ }); const adapter: Adapter = { + version: 2, adapter: baseAdapter }; diff --git a/fees/moonshot-money.ts b/fees/moonshot-money.ts new file mode 100644 index 0000000000..31aab38860 --- /dev/null +++ b/fees/moonshot-money.ts @@ -0,0 +1,32 @@ +import { FetchOptions, SimpleAdapter } from "../adapters/types"; +import { CHAIN } from "../helpers/chains"; +import { queryDune } from "../helpers/dune"; + +const fetch: any = async (options: FetchOptions) => { + const dailyFees = options.createBalances(); + const value = (await queryDune("3986808", { + start: options.startTimestamp, + end: options.endTimestamp, + receiver: '5wkyL2FLEcyUUgc3UeGntHTAfWfzDrVuxMnaMm7792Gk', + token_mint_address: 'EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v' + })); + dailyFees.add('EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v', value[0].received*1e6); + return { + dailyFees, + dailyRevenue: dailyFees, + } + +} + +const adapter: SimpleAdapter = { + version: 2, + adapter: { + [CHAIN.SOLANA]: { + fetch: fetch, + start: 0, + }, + }, + isExpensiveAdapter: true +}; + +export default adapter; diff --git a/fees/moonshot.ts b/fees/moonshot.ts new file mode 100644 index 0000000000..12295f653e --- /dev/null +++ b/fees/moonshot.ts @@ -0,0 +1,29 @@ +import { FetchOptions, SimpleAdapter } from "../adapters/types"; +import { CHAIN } from "../helpers/chains"; +import { queryDune } from "../helpers/dune"; + +const fetch: any = async (options: FetchOptions) => { + const dailyFees = options.createBalances(); + const value = (await queryDune("3521814", { + start: options.startTimestamp, + end: options.endTimestamp, + receiver: '3udvfL24waJcLhskRAsStNMoNUvtyXdxrWQz4hgi953N' + })); + dailyFees.add('So11111111111111111111111111111111111111112', value[0].fee_token_amount); + + return { dailyFees, dailyRevenue: dailyFees } + +} + +const adapter: SimpleAdapter = { + version: 2, + adapter: { + [CHAIN.SOLANA]: { + fetch: fetch, + start: 0, + }, + }, + isExpensiveAdapter: true +}; + +export default adapter; diff --git a/fees/moonwell-apollo.ts b/fees/moonwell-apollo.ts index fad4431927..028a11e624 100644 --- a/fees/moonwell-apollo.ts +++ b/fees/moonwell-apollo.ts @@ -1,3 +1,4 @@ +import * as sdk from "@defillama/sdk"; import { Adapter } from "../adapters/types"; import { CHAIN } from "../helpers/chains"; import { request, gql } from "graphql-request"; @@ -7,7 +8,7 @@ import BigNumber from "bignumber.js"; import { getTimestampAtStartOfDayUTC } from "../utils/date"; const endpoints = { - [CHAIN.MOONRIVER]: "https://api.thegraph.com/subgraphs/name/messari/moonwell-moonriver" + [CHAIN.MOONRIVER]: sdk.graph.modifyEndpoint('9JAn68UTLzUqkyXSqifMbeQH7pkHQ6hmpeuqsnSgKxLE') } diff --git a/fees/moonwell-artemis.ts b/fees/moonwell-artemis.ts index 181ad64323..dd7c71c0fd 100644 --- a/fees/moonwell-artemis.ts +++ b/fees/moonwell-artemis.ts @@ -1,3 +1,4 @@ +import * as sdk from "@defillama/sdk"; import { Adapter } from "../adapters/types"; import { CHAIN } from "../helpers/chains"; import { request, gql } from "graphql-request"; @@ -7,7 +8,7 @@ import BigNumber from "bignumber.js"; import { getTimestampAtStartOfDayUTC } from "../utils/date"; const endpoints = { - [CHAIN.MOONBEAN]: "https://api.thegraph.com/subgraphs/name/messari/moonwell-moonbeam" + [CHAIN.MOONBEAN]: sdk.graph.modifyEndpoint('DQhrdUHwspQf3hSjDtyfS6uqq9YiKoLF3Ut3U9os2HK') } diff --git a/fees/moonwell/index.ts b/fees/moonwell/index.ts new file mode 100644 index 0000000000..e8c29e5b28 --- /dev/null +++ b/fees/moonwell/index.ts @@ -0,0 +1,123 @@ +import ADDRESSES from '../../helpers/coreAssets.json' +import { BaseAdapter, FetchOptions, IJSON, SimpleAdapter } from "../../adapters/types"; +import * as sdk from "@defillama/sdk"; + +const comptrollerABI = { + underlying: "address:underlying", + exchangeRateCurrent: "uint256:exchangeRateCurrent", + getAllMarkets: "address[]:getAllMarkets", + liquidationIncentiveMantissa: "uint256:liquidationIncentiveMantissa", + accrueInterest: "event AccrueInterest(uint256 cashPrior,uint256 interestAccumulated,uint256 borrowIndex,uint256 totalBorrows)", + reservesAdded: "event ReservesAdded(address benefactor,uint256 addAmount,uint256 newTotalReserves)", + liquidateBorrow: "event LiquidateBorrow (address liquidator, address borrower, uint256 repayAmount, address mTokenCollateral, uint256 seizeTokens)", + reserveFactor: "uint256:reserveFactorMantissa", +}; + +const baseUnitroller = "0xfBb21d0380beE3312B33c4353c8936a0F13EF26C"; +const moonbeamUnitroller = "0x8E00D5e02E65A19337Cdba98bbA9F84d4186a180"; +const moonriverUnitroller = "0x0b7a0EAA884849c6Af7a129e899536dDDcA4905E"; +const optimismUnitroller = "0xCa889f40aae37FFf165BccF69aeF1E82b5C511B9"; + +async function getFees(market: string, { createBalances, api, getLogs, }: FetchOptions, { + dailyFees, + dailyRevenue, + abis = {}, +}: { + dailyFees?: sdk.Balances, + dailyRevenue?: sdk.Balances, + abis?: any +}) { + if (!dailyFees) dailyFees = createBalances() + if (!dailyRevenue) dailyRevenue = createBalances() + let markets + try { + markets = await api.call({ target: market, abi: comptrollerABI.getAllMarkets, }) + } catch (error) { + return { dailyFees, dailyRevenue } + } + const liquidationIncentiveMantissa = await api.call({ target: market, abi: comptrollerABI.liquidationIncentiveMantissa, }) + const underlyings = await api.multiCall({ calls: markets, abi: comptrollerABI.underlying, permitFailure: true, }); + const exchangeRatesCurrent = await api.multiCall({ calls: markets, abi: comptrollerABI.exchangeRateCurrent, permitFailure: true, }); + underlyings.forEach((underlying, index) => { + if (!underlying) underlyings[index] = ADDRESSES.null + }) + const reserveFactors = await api.multiCall({ calls: markets, abi: abis.reserveFactor ?? comptrollerABI.reserveFactor, }); + const logs: any[] = (await getLogs({ + targets: markets, + flatten: false, + eventAbi: comptrollerABI.accrueInterest, + })).map((log: any, index: number) => { + return log.map((i: any) => ({ + ...i, + interestAccumulated: Number(i.interestAccumulated), + marketIndex: index, + })); + }).flat() + + const reservesAddedLogs: any[] = (await getLogs({ + targets: markets, + flatten: false, + eventAbi: comptrollerABI.reservesAdded, + })).map((log: any, index: number) => { + return log.map((i: any) => ({ + ...i, + addAmount: Number(i.addAmount), + marketIndex: index, + })); + }).flat() + + const liquidateBorrowLogs: any[] = (await getLogs({ + targets: markets, + flatten: false, + eventAbi: comptrollerABI.liquidateBorrow, + })).map((log: any, index: number) => { + return log.map((i: any) => ({ + ...i, + seizeTokens: Number(i.seizeTokens), + marketIndex: markets.indexOf(i.mTokenCollateral), + })); + }).flat() + + logs.forEach((log: any) => { + const marketIndex = log.marketIndex; + const underlying = underlyings[marketIndex] + dailyFees!.add(underlying, log.interestAccumulated); + dailyRevenue!.add(underlying, log.interestAccumulated * Number(reserveFactors[marketIndex]) / 1e18); + }) + + reservesAddedLogs.forEach((log: any) => { + const marketIndex = log.marketIndex; + const underlying = underlyings[marketIndex] + dailyRevenue!.add(underlying, log.addAmount); + }) + + liquidateBorrowLogs.forEach((log: any) => { + const marketIndex = log.marketIndex; + const underlying = underlyings[marketIndex] + dailyFees!.add(underlying, (log.seizeTokens * ((liquidationIncentiveMantissa / 1e18) - 1) * (exchangeRatesCurrent[marketIndex] / 1e18))); + }) + + return { dailyFees, dailyRevenue } +} + +function moonwellExport(config: IJSON) { + const exportObject: BaseAdapter = {} + Object.entries(config).map(([chain, market]) => { + exportObject[chain] = { + fetch: (async (options: FetchOptions) => { + const { dailyFees, dailyRevenue } = await getFees(market, options, {}) + const dailyHoldersRevenue = dailyRevenue + const dailySupplySideRevenue = options.createBalances() + dailySupplySideRevenue.addBalances(dailyFees) + Object.entries(dailyRevenue.getBalances()).forEach(([token, balance]) => { + dailySupplySideRevenue.addTokenVannila(token, Number(balance) * -1) + }) + return { dailyFees, dailyRevenue, dailyHoldersRevenue, dailySupplySideRevenue } + }), + start: 0, + } + }) + return { adapter: exportObject, version: 2 } as SimpleAdapter +} + +export default moonwellExport({ base: baseUnitroller, moonbeam: moonbeamUnitroller, moonriver: moonriverUnitroller, optimism: optimismUnitroller }); \ No newline at end of file diff --git a/fees/morphex-old.ts b/fees/morphex-old.ts index 7415b911fe..a16dce32b0 100644 --- a/fees/morphex-old.ts +++ b/fees/morphex-old.ts @@ -1,3 +1,4 @@ +import * as sdk from "@defillama/sdk"; import { Adapter } from "../adapters/types"; import { CHAIN } from "../helpers/chains"; import { request, gql } from "graphql-request"; @@ -5,7 +6,7 @@ import { getTimestampAtStartOfDayUTC } from "../utils/date"; const endpoints: { [key: string]: string } = { [CHAIN.FANTOM]: - "https://api.thegraph.com/subgraphs/name/morphex-labs/morphex-fantom-stats", + sdk.graph.modifyEndpoint('EH6ZfhnYQd7Kv1SdnUAp96vMUWKCTfPrctwududH5cmG'), }; const methodology = { diff --git a/fees/morphex.ts b/fees/morphex.ts index 1e61ece73b..3d90bcd7c3 100644 --- a/fees/morphex.ts +++ b/fees/morphex.ts @@ -1,3 +1,4 @@ +import * as sdk from "@defillama/sdk"; import { Adapter } from "../adapters/types"; import { CHAIN } from "../helpers/chains"; import { request, gql } from "graphql-request"; @@ -5,9 +6,9 @@ import { getTimestampAtStartOfDayUTC } from "../utils/date"; const endpoints: { [key: string]: string } = { [CHAIN.FANTOM]: - "https://api.thegraph.com/subgraphs/name/morphex-labs/morphex-fantom-stats-new", + sdk.graph.modifyEndpoint('6GjHurahqYLUUYkqfCgrWfcH2pfTEFPtPvCPvQ1BHLed'), [CHAIN.BSC]: - "https://api.thegraph.com/subgraphs/name/morphex-labs/morphex-bsc-stats", + sdk.graph.modifyEndpoint('4Zdyx9D4oYLGSm1C26jpTU7Ho7ecswEuTPg3WANGkMTx'), }; const methodology = { diff --git a/fees/morpho-compound.ts b/fees/morpho-compound.ts index de79af0762..1fc8eb118c 100644 --- a/fees/morpho-compound.ts +++ b/fees/morpho-compound.ts @@ -1,17 +1,5 @@ -import { Adapter, } from "../adapters/types" -import { CHAIN } from "../helpers/chains"; -import { getFeesExport } from "../helpers/compoundV2"; +import { compoundV2Export, } from "../helpers/compoundV2"; const unitroller = "0x930f1b46e1d081ec1524efd95752be3ece51ef67"; -const adapter: Adapter = { - adapter: { - [CHAIN.ETHEREUM]: { - fetch: getFeesExport(unitroller), - start: 1697932800, - runAtCurrTime: true, - }, - }, -}; - -export default adapter; +export default compoundV2Export({ ethereum: unitroller}); diff --git a/fees/morpho/index.ts b/fees/morpho/index.ts new file mode 100644 index 0000000000..736f17fb98 --- /dev/null +++ b/fees/morpho/index.ts @@ -0,0 +1,90 @@ +const { request, gql } = require("graphql-request"); +import { Balances } from "@defillama/sdk"; +import { FetchV2, SimpleAdapter } from "../../adapters/types"; + +type Market = { + loanAsset: { address: string; decimals: number }; + state: { + supplyApy: number; + borrowApy: number; + supplyAssets: number; + borrowAssets: number; + }; +}; + +const BLUE_API_ENDPOINT = "https://blue-api.morpho.org/graphql"; + +const query = gql` + query GetMarketsData($chainId: Int!) { + markets(where: { chainId_in: [$chainId] }) { + items { + loanAsset { + address + } + state { + borrowAssets + supplyAssets + supplyApy + borrowApy + } + } + } + } +`; + +const apyToDaily = (apy: number): number => + (((apy / 100 + 1) ** (1 / 365) - 1) * 365) / (0.01 * 365); + +const fetchMarkets = async (chainId: number, url: string) => { + const res = await request(url, query, { chainId }); + + let marketData: { + dailySupplySideRevenue: Balances; + dailyUserFees: Balances; + dailyFees?: Balances; + } = { + dailySupplySideRevenue: new Balances({ + chain: chainId === 1 ? "ethereum" : "base", + }), + dailyUserFees: new Balances({ chain: chainId === 1 ? "ethereum" : "base" }), + }; + + res.markets.items.map((m: Market) => { + const { address } = m.loanAsset; + const { supplyApy, borrowApy, supplyAssets, borrowAssets } = m.state; + + const supply = supplyAssets * apyToDaily(supplyApy); + const borrow = borrowAssets * apyToDaily(borrowApy); + + marketData.dailySupplySideRevenue.add(address, supply); + marketData.dailyUserFees.add(address, borrow); + }); + + marketData.dailyFees = marketData.dailyUserFees; + + return marketData; +}; + +const fetchEthereum: FetchV2 = async (options) => { + return fetchMarkets(1, BLUE_API_ENDPOINT); +}; + +const fetchBase: FetchV2 = async (options) => { + return fetchMarkets(8453, BLUE_API_ENDPOINT); +}; + +const adapter: SimpleAdapter = { + adapter: { + ethereum: { + fetch: fetchEthereum, + start: 1704197610, + }, + base: { + fetch: fetchBase, + start: 1714743643, + }, + }, + version: 2, +}; + +export default adapter; diff --git a/fees/move-dollar.ts b/fees/move-dollar.ts index 4a9133cab4..78e97c11ad 100644 --- a/fees/move-dollar.ts +++ b/fees/move-dollar.ts @@ -2,11 +2,13 @@ import fetchURL from "../utils/fetchURL"; import { SimpleAdapter } from "../adapters/types"; import { CHAIN } from "../helpers/chains"; -const thalaDappURL = 'https://app.thala.fi'; -const feesQueryURL = `${thalaDappURL}/api/protocol-fee-chart?timeframe=`; +const thalaDappURL = "https://app.thala.fi"; +const feesQueryURL = `${thalaDappURL}/api/defillama/protocol-fee-chart?timeframe=`; -const feesEndpoint = (endTimestamp: number, timeframe: string) => -endTimestamp ? feesQueryURL + timeframe + `&endTimestamp=${endTimestamp}` : feesQueryURL + timeframe; +const feesEndpoint = (endTimestamp: number, timeframe: string) => + endTimestamp + ? feesQueryURL + timeframe + `&endTimestamp=${endTimestamp}` + : feesQueryURL + timeframe; interface IVolumeall { value: number; @@ -14,11 +16,17 @@ interface IVolumeall { } const fetch = async (timestamp: number) => { - const dayFeesQuery = (await fetchURL(feesEndpoint(timestamp, "1D"))).data; - const dailyFees = dayFeesQuery.reduce((partialSum: number, a: IVolumeall) => partialSum + a.value, 0); - - const totalFeesQuery = (await fetchURL(feesEndpoint(0, "ALL"))).data; - const totalFees = totalFeesQuery.reduce((partialSum: number, a: IVolumeall) => partialSum + a.value, 0); + const dayFeesQuery = (await fetchURL(feesEndpoint(timestamp, "1D")))?.data; + const dailyFees = dayFeesQuery.reduce( + (partialSum: number, a: IVolumeall) => partialSum + a.value, + 0 + ); + + const totalFeesQuery = (await fetchURL(feesEndpoint(0, "ALL")))?.data; + const totalFees = totalFeesQuery.reduce( + (partialSum: number, a: IVolumeall) => partialSum + a.value, + 0 + ); return { totalFees: `${totalFees}`, @@ -27,12 +35,11 @@ const fetch = async (timestamp: number) => { }; }; - const adapter: SimpleAdapter = { adapter: { [CHAIN.APTOS]: { fetch, - start: 1680652406 + start: 1680652406, }, }, }; diff --git a/fees/multichain/index.ts b/fees/multichain/index.ts index 0fdea02387..5e77bf11dc 100644 --- a/fees/multichain/index.ts +++ b/fees/multichain/index.ts @@ -26,6 +26,7 @@ const fetch = async (timestamp: number) => { const adapter: Adapter = { + version: 1, adapter: { ["anyswap"]: { fetch: fetch, diff --git a/fees/mummy-finance.ts b/fees/mummy-finance.ts index b85232639b..0cd0eed89b 100644 --- a/fees/mummy-finance.ts +++ b/fees/mummy-finance.ts @@ -1,3 +1,4 @@ +import * as sdk from "@defillama/sdk"; import request, { gql } from "graphql-request"; import { Fetch, SimpleAdapter } from "../adapters/types"; import { CHAIN } from "../helpers/chains"; @@ -7,8 +8,8 @@ import { Chain } from "@defillama/sdk/build/general"; import { getTimestampAtStartOfDayUTC } from "../utils/date"; const endpoints: { [key: string]: string } = { - [CHAIN.FANTOM]: "https://api.thegraph.com/subgraphs/name/mummyfinance/fantom-stats-v2", - [CHAIN.OPTIMISM]: "https://api.thegraph.com/subgraphs/name/mummyfinance/op-stats", + [CHAIN.FANTOM]: sdk.graph.modifyEndpoint('8LdLE9Aan39FQCcHX3x1HdnNzoZzPvxskhj1utLb2SA9'), + [CHAIN.OPTIMISM]: sdk.graph.modifyEndpoint('6dZD4zDx9bGZfRdgoUBsZjWBygYVXAe4G41LjTLNJWk1'), }; const historicalDataSwap = gql` diff --git a/fees/myx-finance/index.tsx b/fees/myx-finance/index.tsx new file mode 100644 index 0000000000..02f32fb02e --- /dev/null +++ b/fees/myx-finance/index.tsx @@ -0,0 +1,74 @@ +import { SimpleAdapter, FetchResultFees, FetchOptions } from "../../adapters/types"; +import fetchURL from "../../utils/fetchURL"; +import { CHAIN } from "../../helpers/chains"; + +const DAILYURL = 'https://api.myx.finance/v2/scan/defilama/fee/all_by_chain' +const TOTALURL = 'https://api.myx.finance/v2/scan/defilama/cum_fee/all_by_chain' + +enum FetchType { + TOTAL = 1, + DAILY = 2 +} + +type Data = { + chainId: number, + time: number, + tradingFee?: string, + cumTradingFee?: string +} + +const methodology = { + totalFees: "Tracks the cumulative fees generated by all transactions.", + dailyFees: "Tracks the fees generated by transactions on a daily basis.", +} + + +const fetchApi = async (type: FetchType, startTime: number, endTime: number) => { + const rs = await fetchURL(`${type === FetchType.DAILY ? DAILYURL : TOTALURL}?startTime=${startTime}&endTime=${endTime}`) + const data: Data[] = rs?.data ?? [] + + return data +} + +const fetchFees = async (_t: any, _b: any, optios: FetchOptions) => { + const start = optios.startOfDay; + const end = start + 86400; + const dailyAlls: Data[] = await fetchApi(FetchType.DAILY, start, end) + const dailyFees = dailyAlls.find((daily: Data)=> daily.chainId === optios.toApi.chainId) + + const totalAlls: Data[] = await fetchApi(FetchType.TOTAL, start, end) + const totalFees = totalAlls.find((daily: Data)=> daily.chainId === optios.toApi.chainId) + + return { + totalFees: totalFees?.tradingFee, + dailyFees: dailyFees?.tradingFee, + timestamp: optios.startTimestamp + } +} + +const startTimestamps: { [chain: string]: number } = { + [CHAIN.ARBITRUM]: 1706659200, + [CHAIN.LINEA]: 1708473600, +} + +const adapter: SimpleAdapter = { + version: 1, + adapter: { + [CHAIN.ARBITRUM]: { + fetch: fetchFees, + start: startTimestamps[CHAIN.ARBITRUM], + meta: { + methodology + } + }, + [CHAIN.LINEA]: { + fetch: fetchFees, + start: startTimestamps[CHAIN.LINEA], + meta: { + methodology + } + }, + } +} + +export default adapter; diff --git a/fees/near/index.ts b/fees/near/index.ts index 25bcd51839..410ad06f4e 100644 --- a/fees/near/index.ts +++ b/fees/near/index.ts @@ -27,6 +27,7 @@ const fetchFees = async (timestamp: number): Promise => { } const adapter: SimpleAdapter = { + version: 1, adapter: { [CHAIN.NEAR]: { fetch: fetchFees, diff --git a/fees/nether-fi/index.ts b/fees/nether-fi/index.ts index 5ed8ff31ba..778aa11545 100644 --- a/fees/nether-fi/index.ts +++ b/fees/nether-fi/index.ts @@ -53,6 +53,7 @@ const getFetch = (): Fetch => async (timestamp: number) => { }; const adapter: Adapter = { + version: 1, adapter: { [CHAIN.BASE]: { fetch: getFetch(), diff --git a/fees/nile-exchange-v1/index.ts b/fees/nile-exchange-v1/index.ts new file mode 100644 index 0000000000..3c7c92f906 --- /dev/null +++ b/fees/nile-exchange-v1/index.ts @@ -0,0 +1,17 @@ +import { CHAIN } from "../../helpers/chains"; +import { uniV2Exports } from "../../helpers/uniswap"; + +const methodology = { + UserFees: "User pays 0.05%, 0.30%, or 1% on each swap.", + ProtocolRevenue: "Revenue going to the protocol. 5% of collected fees. (is probably right because the distribution is dynamic.)", + HoldersRevenue: "User fees are distributed among holders. 75% of collected fees. (is probably right because the distribution is dynamic.)", + SupplySideRevenue: "20% of collected fees are distributed among LPs. (is probably right because the distribution is dynamic.)" +} + + +const adapter = uniV2Exports({ + [CHAIN.LINEA]: { factory: '0xAAA16c016BF556fcD620328f0759252E29b1AB57', }, +}) + +adapter.adapter[CHAIN.LINEA].meta = { methodology } +export default adapter; \ No newline at end of file diff --git a/fees/nile-exchange/bribes.ts b/fees/nile-exchange/bribes.ts new file mode 100644 index 0000000000..6892de4354 --- /dev/null +++ b/fees/nile-exchange/bribes.ts @@ -0,0 +1,35 @@ +import request from "graphql-request"; +import { Balances } from "@defillama/sdk"; + +interface IBribes { + amount: number; + token: { + id: string; + decimals: number; + }; +} + +export const fees_bribes = async (fromBlock: number, timestamp: number, balances: Balances) => { + const endpoint = 'https://api.studio.thegraph.com/query/66247/nile-cl/version/latest'; + const graphQuery = ` + query GetBribes($fromBlock: Int!) { + bribes( + where: { timestamp_gte: ${timestamp} } + ) { + amount + token { + id + decimals + } + } + } + `; + + const graphRes: { bribes: IBribes[] } = await request(endpoint, graphQuery, { fromBlock, }); + + const logs_bribes = graphRes.bribes; + + logs_bribes.map((e: IBribes) => { + balances.add(e.token.id, e.amount * Math.pow(10, e.token.decimals)); + }) +}; diff --git a/fees/nile-exchange/index.ts b/fees/nile-exchange/index.ts new file mode 100644 index 0000000000..84533903f2 --- /dev/null +++ b/fees/nile-exchange/index.ts @@ -0,0 +1,80 @@ +import { Adapter, FetchOptions } from "../../adapters/types"; +import { CHAIN } from "../../helpers/chains"; +import { fees_bribes } from './bribes'; +import { + getGraphDimensions, + DEFAULT_DAILY_VOLUME_FACTORY, + DEFAULT_TOTAL_VOLUME_FIELD, + getGraphDimensions2, +} from "../../helpers/getUniSubgraph" + +type TStartTime = { + [key: string]: number; +} +const startTimeV2: TStartTime = { + [CHAIN.LINEA]: 1705968000, +} + +const getBribes = async ({ fromTimestamp, toTimestamp, createBalances, getFromBlock, }: FetchOptions): Promise => { + const fromBlock = await getFromBlock() + const bribes = createBalances(); + const bribes_delta = createBalances(); + await fees_bribes(fromBlock, toTimestamp, bribes_delta); + await fees_bribes(fromBlock, fromTimestamp, bribes); + bribes.subtract(bribes_delta); + return { + timestamp: toTimestamp, + dailyBribesRevenue: bribes, + }; +}; + +const v2Endpoints = { + [CHAIN.LINEA]: "https://api.studio.thegraph.com/query/66247/nile-cl/version/latest/", +}; + +const v2Graphs = getGraphDimensions2({ + graphUrls: v2Endpoints, + totalVolume: { + factory: "factories", + field: DEFAULT_TOTAL_VOLUME_FIELD, + }, + feesPercent: { + type: "fees", + HoldersRevenue: 72, + ProtocolRevenue: 8, + SupplySideRevenue: 20, + UserFees: 100, // User fees are 100% of collected fees + Revenue: 80 // Revenue is 100% of collected fees + } +}); +// https://docs.ramses.exchange/ramses-cl-v2/concentrated-liquidity/fee-distribution +const methodology = { + UserFees: "User pays 0.3% fees on each swap.", + ProtocolRevenue: "Revenue going to the protocol. 5% of collected fees. (is probably right because the distribution is dynamic.)", + HoldersRevenue: "User fees are distributed among holders. 75% of collected fees. (is probably right because the distribution is dynamic.)", + SupplySideRevenue: "20% of collected fees are distributed among LPs. (is probably right because the distribution is dynamic.)" +} + +const adapter: Adapter = { + version: 2, + adapter: { + [CHAIN.LINEA]: { + fetch: async (options: FetchOptions) => { + const v2Result = await v2Graphs(CHAIN.LINEA)(options) + const bribesResult = await getBribes(options); + v2Result.dailyBribesRevenue = bribesResult.dailyBribesRevenue; + + return v2Result; + }, + start: startTimeV2[CHAIN.LINEA], + meta: { + methodology: { + ...methodology, + UserFees: "User pays 0.05%, 0.30%, or 1% on each swap.", + }, + }, + }, + }, +}; + +export default adapter; diff --git a/fees/nomiswap.ts b/fees/nomiswap.ts index a9cc77bb7f..80f9bead80 100644 --- a/fees/nomiswap.ts +++ b/fees/nomiswap.ts @@ -12,6 +12,7 @@ const feeAdapter: BaseAdapter = getDexChainFees({ }); const adapter: Adapter = { + version: 2, adapter: feeAdapter }; diff --git a/fees/nuri-exchange-v1/index.ts b/fees/nuri-exchange-v1/index.ts new file mode 100644 index 0000000000..48fea63c2b --- /dev/null +++ b/fees/nuri-exchange-v1/index.ts @@ -0,0 +1,6 @@ +import { CHAIN } from "../../helpers/chains"; +import { uniV2Exports } from "../../helpers/uniswap"; + +export default uniV2Exports({ + [CHAIN.SCROLL]: { factory: '0xAAA16c016BF556fcD620328f0759252E29b1AB57', }, +}) diff --git a/fees/nuri-exchange-v2/bribes.ts b/fees/nuri-exchange-v2/bribes.ts new file mode 100644 index 0000000000..5aba456d6c --- /dev/null +++ b/fees/nuri-exchange-v2/bribes.ts @@ -0,0 +1,35 @@ +import request from "graphql-request"; +import { Balances } from "@defillama/sdk"; + +interface IBribes { + amount: number; + token: { + id: string; + decimals: number; + }; +} + +export const fees_bribes = async (fromBlock: number, timestamp: number, balances: Balances) => { + const endpoint = 'https://api.studio.thegraph.com/query/66247/nuri-cl/version/latest'; + const graphQuery = ` + query GetBribes($fromBlock: Int!) { + bribes( + where: { timestamp_gte: ${timestamp} } + ) { + amount + token { + id + decimals + } + } + } + `; + + const graphRes: { bribes: IBribes[] } = await request(endpoint, graphQuery, { fromBlock, }); + + const logs_bribes = graphRes.bribes; + + logs_bribes.map((e: IBribes) => { + balances.add(e.token.id, e.amount * Math.pow(10, e.token.decimals)); + }) +}; diff --git a/fees/nuri-exchange-v2/index.ts b/fees/nuri-exchange-v2/index.ts new file mode 100644 index 0000000000..798d67f7cd --- /dev/null +++ b/fees/nuri-exchange-v2/index.ts @@ -0,0 +1,78 @@ +import { Adapter, FetchOptions } from "../../adapters/types"; +import { CHAIN } from "../../helpers/chains"; +import { fees_bribes } from './bribes'; +import { + DEFAULT_TOTAL_VOLUME_FIELD, + getGraphDimensions2, +} from "../../helpers/getUniSubgraph" + +type TStartTime = { + [key: string]: number; +} +const startTimeV2: TStartTime = { + [CHAIN.SCROLL]: 1714608000, +} + +const getBribes = async ({ fromTimestamp, toTimestamp, createBalances, getFromBlock, }: FetchOptions): Promise => { + const fromBlock = await getFromBlock() + const bribes = createBalances(); + const bribes_delta = createBalances(); + await fees_bribes(fromBlock, toTimestamp, bribes_delta); + await fees_bribes(fromBlock, fromTimestamp, bribes); + bribes.subtract(bribes_delta); + return { + timestamp: toTimestamp, + dailyBribesRevenue: bribes, + }; +}; + +const v2Endpoints = { + [CHAIN.SCROLL]: "https://api.studio.thegraph.com/query/66247/nuri-cl/version/latest", +}; + +const v2Graphs = getGraphDimensions2({ + graphUrls: v2Endpoints, + totalVolume: { + factory: "factories", + field: DEFAULT_TOTAL_VOLUME_FIELD, + }, + feesPercent: { + type: "fees", + HoldersRevenue: 72, + ProtocolRevenue: 8, + SupplySideRevenue: 20, + UserFees: 100, // User fees are 100% of collected fees + Revenue: 80 // Revenue is 100% of collected fees + } +}); +// https://docs.ramses.exchange/ramses-cl-v2/concentrated-liquidity/fee-distribution +const methodology = { + UserFees: "User pays 0.3% fees on each swap.", + ProtocolRevenue: "Revenue going to the protocol. 8% of collected fees. (is probably right because the distribution is dynamic.)", + HoldersRevenue: "User fees are distributed among holders. 72% of collected fees. (is probably right because the distribution is dynamic.)", + SupplySideRevenue: "20% of collected fees are distributed among LPs. (is probably right because the distribution is dynamic.)" +} + +const adapter: Adapter = { + version: 2, + adapter: { + [CHAIN.SCROLL]: { + fetch: async (options: FetchOptions) => { + const v2Result = await v2Graphs(CHAIN.SCROLL)(options) + const bribesResult = await getBribes(options); + v2Result.dailyBribesRevenue = bribesResult.dailyBribesRevenue; + + return v2Result; + }, + start: startTimeV2[CHAIN.SCROLL], + meta: { + methodology: { + ...methodology, + UserFees: "User pays 0.05%, 0.30%, or 1% on each swap.", + }, + }, + }, + }, +}; + +export default adapter; diff --git a/fees/ociswap.ts b/fees/ociswap.ts new file mode 100644 index 0000000000..f853ff715a --- /dev/null +++ b/fees/ociswap.ts @@ -0,0 +1,55 @@ +import { BreakdownAdapter, FetchResultFees, SimpleAdapter } from "../adapters/types" +import { CHAIN } from "../helpers/chains" +import fetchURL from "../utils/fetchURL" + +interface PoolStatistics { + pool_type: string; + fees: { + xrd: { + '24h': string; + total: string; + }; + usd: { + '24h': string; + total: string; + }; + }; +} + +const fetchFees = (poolType: 'basic' | 'precision') => { + return async (timestamp: number): Promise => { + const response: Array = await fetchURL('http://api.ociswap.com/statistics/pool-types'); + + const index = response.findIndex(pool => pool.pool_type === poolType); + + const dailyFees = Number(response[index].fees.usd["24h"]); + const totalFees = Number(response[index].fees.usd.total); + + return { + dailyFees: `${dailyFees}`, + totalFees: `${totalFees}`, + timestamp + }; + }; +}; + +const adapters: BreakdownAdapter = { + version: 2, + breakdown: { + basic: { + [CHAIN.RADIXDLT]: { + fetch: fetchFees('basic'), + start: 1696118400, + // runAtCurrTime: true + } + }, + precision: { + [CHAIN.RADIXDLT]: { + fetch: fetchFees('precision'), + start: 1696118400, + // runAtCurrTime: true + } + } + } +} +export default adapters; \ No newline at end of file diff --git a/fees/odos.ts b/fees/odos.ts index 3b64c650c8..813fba5427 100644 --- a/fees/odos.ts +++ b/fees/odos.ts @@ -49,8 +49,11 @@ const FEE_COLLECTORS: TPool = { [CHAIN.AVAX]: ['0x88de50B233052e4Fb783d4F6db78Cc34fEa3e9FC',], [CHAIN.BSC]: ['0x89b8AA89FDd0507a99d334CBe3C808fAFC7d850E',], [CHAIN.FANTOM]: ['0xd0c22a5435f4e8e5770c1fafb5374015fc12f7cd',], - [CHAIN.ERA]: [ '0x4bBa932E9792A2b917D47830C93a9BC79320E4f7', ], - [CHAIN.POLYGON_ZKEVM]: ['0x2b8B3f0949dfB616602109D2AAbBA11311ec7aEC',], + [CHAIN.ERA]: [ '0x4bBa932E9792A2b917D47830C93a9BC79320E4f7', ], + [CHAIN.MODE]: ['0x7E15EB462cdc67Cf92Af1f7102465a8F8c784874',], + [CHAIN.LINEA]: ['0x2d8879046f1559E53eb052E949e9544bCB72f414',], + [CHAIN.MANTLE]: ['0xD9F4e85489aDCD0bAF0Cd63b4231c6af58c26745',], + [CHAIN.SCROLL]: ['0xbFe03C9E20a9Fc0b37de01A172F207004935E0b1',], } const graph = (chain: Chain): any => { @@ -82,11 +85,14 @@ const adapter: SimpleAdapter = { [CHAIN.BASE]: { fetch: graph(CHAIN.BASE), start: 1689292800 }, [CHAIN.POLYGON]: { fetch: graph(CHAIN.POLYGON), start: 1689292800 }, [CHAIN.AVAX]: { fetch: graph(CHAIN.AVAX), start: 1689292800 }, - [CHAIN.BSC]: { fetch: graph(CHAIN.BSC), start: 1689292800 }, + [CHAIN.BSC]: { fetch: graph(CHAIN.BSC), start: 1689292800 }, [CHAIN.FANTOM]: { fetch: graph(CHAIN.FANTOM), start: 1689292800 }, - [CHAIN.ERA]: { fetch: graph(CHAIN.ERA), start: 1689292800 }, - [CHAIN.POLYGON_ZKEVM]: { fetch: graph(CHAIN.POLYGON_ZKEVM), start: 1689292800 } + [CHAIN.ERA]: { fetch: graph(CHAIN.ERA), start: 1689292800 }, + [CHAIN.MODE]: { fetch: graph(CHAIN.MODE), start: 1689292800 }, + [CHAIN.LINEA]: { fetch: graph(CHAIN.LINEA), start: 1689292800 }, + [CHAIN.MANTLE]: { fetch: graph(CHAIN.MANTLE), start: 1689292800 }, + [CHAIN.SCROLL]: { fetch: graph(CHAIN.SCROLL), start: 1689292800 }, } }; -export default adapter; \ No newline at end of file +export default adapter; diff --git a/fees/op-bnb.ts b/fees/op-bnb.ts index 511f69d9cc..a15498cd7d 100644 --- a/fees/op-bnb.ts +++ b/fees/op-bnb.ts @@ -49,6 +49,7 @@ const adapter: Adapter = { [CHAIN.OP_BNB]: { fetch: fetch as any, start: 1691971200, + runAtCurrTime: true, }, }, isExpensiveAdapter: true, diff --git a/fees/openeden-t-bills/index.ts b/fees/openeden-t-bills/index.ts new file mode 100644 index 0000000000..ebc9e37d0c --- /dev/null +++ b/fees/openeden-t-bills/index.ts @@ -0,0 +1,65 @@ +// https://docs.openeden.com/treasury-bills-vault/fees + +import { Chain } from "@defillama/sdk/build/general"; +import { Adapter, FetchOptions, FetchResultV2 } from "../../adapters/types"; +import { CHAIN } from "../../helpers/chains"; +import ADDRESSES from "../../helpers/coreAssets.json"; + +const eventAbi = `event ProcessDeposit( + address sender, + address receiver, + uint256 assets, + uint256 shares, + uint256 oeFee, + uint256 pFee, + uint256 totalFee, + address oplTreasury, + address treasury +)`; + +const VAULT_ADDRESSES: Record = { + [CHAIN.ETHEREUM]: "0xdd50C053C096CB04A3e3362E2b622529EC5f2e8a", + [CHAIN.ARBITRUM]: "0xF84D28A8D28292842dD73D1c5F99476A80b6666A", +}; + +const MANAGEMENT_FEES: number = 0.003; +const DAILY_MANAGEMENT_FEES: number = MANAGEMENT_FEES / 365; + +const fetch = async ( + vault: string, + { api, getLogs, createBalances }: FetchOptions +): Promise => { + const dailyFees = createBalances(); + + const [logs, totalUSDC] = await Promise.all([ + getLogs({ target: vault, eventAbi }), + api.call({ target: vault, abi: "uint256:totalAssets" }), + ]); + + dailyFees.add(ADDRESSES[api.chain].USDC, totalUSDC * DAILY_MANAGEMENT_FEES); + + logs.forEach((log) => { + const feeAmount = log[4]; + dailyFees.add(ADDRESSES[api.chain].USDC, feeAmount); + }); + + return { dailyFees }; +}; + +const adapter: Adapter = { + version: 2, + adapter: { + [CHAIN.ETHEREUM]: { + fetch: (options: FetchOptions) => + fetch(VAULT_ADDRESSES[CHAIN.ETHEREUM], options), + start: 1697580000, + }, + [CHAIN.ARBITRUM]: { + fetch: (options: FetchOptions) => + fetch(VAULT_ADDRESSES[CHAIN.ARBITRUM], options), + start: 1707778800, + }, + }, +}; + +export default adapter; diff --git a/fees/opensea/index.ts b/fees/opensea/index.ts index 4008ec301e..c939966ed6 100644 --- a/fees/opensea/index.ts +++ b/fees/opensea/index.ts @@ -1,3 +1,4 @@ +import * as sdk from "@defillama/sdk"; import { Adapter, DISABLED_ADAPTER_KEY } from "../../adapters/types"; import type { ChainEndpoints } from "../../adapters/types" import { Chain } from '@defillama/sdk/build/general'; @@ -7,7 +8,7 @@ import { fetch } from "./seaport"; import disabledAdapter from "../../helpers/disabledAdapter"; const seaportEndpoints = { - [CHAIN.ETHEREUM]: 'https://api.thegraph.com/subgraphs/name/messari/opensea-seaport-ethereum', + [CHAIN.ETHEREUM]: sdk.graph.modifyEndpoint('kGCuz7xhxMuyRSk8QdnUgijUEqgvhGwkzAVHkbYedCk'), } const graphs = (_: ChainEndpoints) => { @@ -24,6 +25,7 @@ const graphs = (_: ChainEndpoints) => { }; const adapter: Adapter = { + version: 1, breakdown: { v1: { [DISABLED_ADAPTER_KEY]: disabledAdapter, diff --git a/fees/optimism.ts b/fees/optimism.ts index fc4ad46da3..21d229c7e6 100644 --- a/fees/optimism.ts +++ b/fees/optimism.ts @@ -10,6 +10,7 @@ const ethereumWallets = [ ] const adapter: Adapter = { + version: 2, adapter: { [CHAIN.OPTIMISM]: { fetch: L2FeesFetcher({ ethereumWallets }), diff --git a/fees/optionBlitz/index.ts b/fees/optionBlitz/index.ts new file mode 100644 index 0000000000..37a70b2bc5 --- /dev/null +++ b/fees/optionBlitz/index.ts @@ -0,0 +1,88 @@ +import ADDRESSES from "../../helpers/coreAssets.json"; +import { FetchResult, SimpleAdapter } from "../../adapters/types"; +import { CHAIN } from "../../helpers/chains"; +import { gql, request } from "graphql-request"; +import * as sdk from "@defillama/sdk"; +import { getTimestampAtStartOfDay } from "../../utils/date"; + +interface IDayDataGraph { + id: string; + rewardsUsdc: string; + lossesUsdc: string; +} +interface ITotalDataGraph { + id: string; + totalRewardsUsdc: string; + totalLossesUsdc: string; + timestamp: string; +} + +const URL = sdk.graph.modifyEndpoint('5m8N5qAkDWTf2hhMFhJJJDsWWF5b9J7bzFbXwPnZHJQQ'); + +const fetch = async (timestamp: number): Promise => { + const dayTimestamp = getTimestampAtStartOfDay(timestamp); + const chain = CHAIN.ARBITRUM; + const balances = new sdk.Balances({ chain }); + const balances1 = new sdk.Balances({ chain }); + const dayDataQuery = gql` + { + dayData(id: ${dayTimestamp * 1000}) { + id + rewardsUsdc + lossesUsdc + } + }`; + + const totalDataQuery = gql` + { + totalDatas { + id + totalRewardsUsdc + totalLossesUsdc + timestamp + } + }` + + const dayDataResponse: IDayDataGraph = (await request(URL, dayDataQuery)).dayData; + const totalDataResponse: ITotalDataGraph[] = (await request(URL, totalDataQuery)).totalDatas; + + let perDayIncome = 0; + let totalIncome = 0; + + if (dayDataResponse) { + perDayIncome = Math.abs(Number(dayDataResponse.rewardsUsdc) - Number(dayDataResponse.lossesUsdc)); + } + + if (totalDataResponse.length > 0) { + totalIncome = Math.abs(Number(totalDataResponse[0].totalRewardsUsdc) - Number(totalDataResponse[0].totalLossesUsdc)); + } + + balances.add(ADDRESSES[chain].USDC_CIRCLE, perDayIncome); + balances1.add(ADDRESSES[chain].USDC_CIRCLE, totalIncome); + + + return { + dailyFees: await balances.getUSDString(), + totalFees: await balances1.getUSDString(), + timestamp: dayTimestamp, + }; +}; + +const methodology = { + Fees: "Trade collateral collected.", + Revenue: "Platform profit, (trader losses minus trader wins).", +}; + +const adapters: SimpleAdapter = { + version: 1, + adapter: { + [CHAIN.ARBITRUM]: { + fetch: fetch as any, + start: 194784191, + meta: { + methodology: methodology, + }, + }, + }, +}; +export default adapters; diff --git a/fees/orby-network.ts b/fees/orby-network.ts new file mode 100644 index 0000000000..07a949bbcd --- /dev/null +++ b/fees/orby-network.ts @@ -0,0 +1,73 @@ +import { Adapter, ChainEndpoints, FetchV2 } from "../adapters/types"; +import { CHAIN } from "../helpers/chains"; +import { getTimestampAtStartOfPreviousDayUTC } from "../utils/date"; +const { request, gql } = require("graphql-request"); + +const endpoints = { + [CHAIN.CRONOS]: "https://graph.cronoslabs.com/subgraphs/name/orby/orby", +}; + +const graphs = (graphUrls: ChainEndpoints) => { + const fetch: FetchV2 = async ({ + chain, + createBalances, + endTimestamp, + getStartBlock, + getEndBlock, + }) => { + const dayTimestamp = getTimestampAtStartOfPreviousDayUTC(endTimestamp); + const dailyFees = createBalances(); + + const graphQuery = gql` + query fees($startOfDayBlock: Int!, $endOfDayBlock: Int!) { + yesterday: global(id: "only", block: { number: $startOfDayBlock }) { + totalBorrowingFeesPaid + totalRedemptionFeesPaid + } + today: global(id: "only", block: { number: $endOfDayBlock }) { + totalBorrowingFeesPaid + totalRedemptionFeesPaid + } + } + `; + const [startBlock, endBlock] = await Promise.all([ + getStartBlock(), + getEndBlock(), + ]); + + const graphRes = await request(graphUrls[chain], graphQuery, { + startOfDayBlock: startBlock, + endOfDayBlock: endBlock - 2, + }); + + const borrowingFees = + Number(graphRes.today.totalBorrowingFeesPaid) - + Number(graphRes.yesterday.totalBorrowingFeesPaid); + const redemptionFeesETH = + Number(graphRes.today.totalRedemptionFeesPaid) - + Number(graphRes.yesterday.totalRedemptionFeesPaid); + + dailyFees.addCGToken("tether", borrowingFees); + dailyFees.addGasToken(redemptionFeesETH * 10 ** 18); + + return { + timestamp: dayTimestamp, + dailyFees: dailyFees, + dailyRevenue: dailyFees, + dailyHoldersRevenue: dailyFees, + }; + }; + return fetch; +}; + +const adapter: Adapter = { + version: 2, + adapter: { + [CHAIN.CRONOS]: { + fetch: graphs(endpoints), + start: 1706837536, + }, + }, +}; + +export default adapter; diff --git a/fees/orderly/index.ts b/fees/orderly/index.ts new file mode 100644 index 0000000000..f3c983e12a --- /dev/null +++ b/fees/orderly/index.ts @@ -0,0 +1,37 @@ +import type { Adapter, FetchOptions } from "../../adapters/types"; +import { CHAIN } from "../../helpers/chains"; +import { getUniqStartOfTodayTimestamp } from "../../helpers/getUniSubgraphVolume"; +import fetchURL from "../../utils/fetchURL"; + +const apiEVM = "https://api-evm.orderly.org/md/volume/daily_stats"; + +type DailyStats = { + volume: string; + date: string; + netFee: number; + dateString: string; + createdAt: string; + updatedAt: string; +}; + +const adapter: Adapter = { + adapter: { + [CHAIN.ARBITRUM]: { + start: async () => 1698278400, + fetch: async (__t: number, _: any, { startOfDay }: FetchOptions) => { + const t = getUniqStartOfTodayTimestamp(new Date(startOfDay * 1000)); + const data: DailyStats[] = await fetchURL(apiEVM); + const totalFee = data.reduce((acc, { netFee }) => acc + netFee, 0); + return { + timestamp: t, + dailyFees: data.find( + ({ createdAt }) => new Date(createdAt).valueOf() / 1_000 === t + )?.netFee, + totalFees: totalFee, + }; + }, + }, + }, +}; + +export default adapter; diff --git a/fees/origin-dollar/index.ts b/fees/origin-dollar/index.ts new file mode 100644 index 0000000000..ec0dc70a32 --- /dev/null +++ b/fees/origin-dollar/index.ts @@ -0,0 +1,64 @@ +// https://docs.originprotocol.com/ogn/staking#staking-rewards +import axios from "axios"; +import { Adapter, FetchOptions, FetchResultV2 } from "../../adapters/types"; +import { CHAIN } from "../../helpers/chains"; +import ADDRESSES from "../../helpers/coreAssets.json"; + +const apiUrl: string = "https://api.originprotocol.com/api/v2/protocol-fees"; +const USDT: string = ADDRESSES.ethereum.USDT; +const decimals: number = 1e6; + +interface DayData { + date: number; + revenue: number; +} + +interface ApiResponse { + revenue: { + now: number; + oneDayAgo: number; + twoDaysAgo: number; + oneWeekAgo: number; + twoWeeksAgo: number; + thirtyDaysAgo: number; + sixtyDaysAgo: number; + ninetyDaysAgo: number; + }; + days: DayData[]; +} + +const fetch = async (options: FetchOptions): Promise => { + const { startOfDay, createBalances } = options; + const dailyRevenue = createBalances(); + const totalRevenue = createBalances(); + + const { data } = await axios.get(apiUrl); + + const dailyData = data.days.find((day) => day.date === startOfDay); + if (dailyData) dailyRevenue.add(USDT, dailyData.revenue * decimals); + totalRevenue.add(USDT, data.revenue.now * decimals); + + return { + dailyRevenue, + dailyFees: dailyRevenue, + totalRevenue, + totalFees: totalRevenue, + }; +}; + +const adapter: Adapter = { + adapter: { + [CHAIN.ETHEREUM]: { + fetch, + start: 1635811200, + runAtCurrTime: false, + meta: { + methodology: + "20% of all yield generated by OUSD and OETH is collected as a protocol fee.", + }, + }, + }, + version: 2, +}; + +export default adapter; diff --git a/fees/osmosis.ts b/fees/osmosis.ts index dc32919601..63a7b77bb1 100644 --- a/fees/osmosis.ts +++ b/fees/osmosis.ts @@ -1,43 +1,52 @@ -import { Adapter } from "../adapters/types"; -import { getTimestampAtStartOfPreviousDayUTC } from "../utils/date"; +import { Adapter, FetchResultV2, FetchV2 } from "../adapters/types"; import fetchURL from "../utils/fetchURL"; import { CHAIN } from "../helpers/chains"; -const feeEndpoint = "https://api-osmosis.imperator.co/fees/v1/total/historical" - interface IChartItem { - time: string - fees_spent: number + labels: string; + protorev: number; + swap_fees: number; + taker_fees: number; } -const fetch = async (timestamp: number) => { - const dayTimestamp = getTimestampAtStartOfPreviousDayUTC(timestamp) - const historicalFees: IChartItem[] = (await fetchURL(feeEndpoint)) - - const totalFee = historicalFees - .filter(feeItem => (new Date(feeItem.time).getTime() / 1000) <= dayTimestamp) - .reduce((acc, { fees_spent }) => acc + fees_spent, 0) - - const dailyFee = historicalFees - .find(dayItem => (new Date(dayItem.time).getTime() / 1000) === dayTimestamp)?.fees_spent +const fetch: FetchV2 = async ({ + startTimestamp, + endTimestamp, +}): Promise => { + const startDate = new Date(startTimestamp * 1000).toISOString().slice(0, 10); + const endDate = new Date(endTimestamp * 1000).toISOString().slice(0, 10); + const feeEndpoint = `https://www.datalenses.zone/numia/osmosis/lenses/hourly_revenue?start_date=${startDate}&end_date=${endDate}`; + const historicalFees: IChartItem[] = await fetchURL(feeEndpoint); + + let dailyFees: number = 0; + let dailyRevenue: number = 0; + + historicalFees + .filter((feeItem) => { + const date = new Date(feeItem.labels).getTime() / 1000; + return date >= startTimestamp && date <= endTimestamp; + }) + .map(({ protorev, swap_fees, taker_fees }) => { + dailyRevenue += protorev; + dailyFees += swap_fees; + dailyFees += taker_fees; + }); return { - timestamp: dayTimestamp, - totalFees: `${totalFee}`, - dailyFees: dailyFee ? `${dailyFee}` : undefined, - totalRevenue: "0", - dailyRevenue: "0", + dailyFees, + dailyRevenue, }; }; const adapter: Adapter = { + version: 2, adapter: { [CHAIN.COSMOS]: { fetch, runAtCurrTime: true, start: 1665964800, }, - } -} + }, +}; export default adapter; diff --git a/fees/paal-ai/index.ts b/fees/paal-ai/index.ts index 8a944746ca..2906335b4d 100644 --- a/fees/paal-ai/index.ts +++ b/fees/paal-ai/index.ts @@ -5,7 +5,7 @@ import { getTokenDiff } from "../../helpers/token"; /** Address to check = paalecosystemfund.eth */ const CONTRACT_ADDRESS = "0x54821d1B461aa887D37c449F3ace8dddDFCb8C0a"; -const fetch: any = async (timestamp: number, _: any, options: FetchOptions) => { +const fetch = async (options: FetchOptions) => { const dailyFees = options.createBalances(); await getTokenDiff({ target: CONTRACT_ADDRESS, options, includeGasToken: true, balances: dailyFees, }) const transactions = await queryIndexer(` @@ -25,11 +25,12 @@ const fetch: any = async (timestamp: number, _: any, options: FetchOptions) => { `, options); transactions.map((transaction: any) => dailyFees.addGasToken(transaction.eth_value)) - return { timestamp, dailyFees, } + return { dailyFees, } } /** Adapter */ const adapter: Adapter = { + version: 2, adapter: { ethereum: { fetch, diff --git a/fees/pangolin.ts b/fees/pangolin.ts index a4f0355ae6..729b00595a 100644 --- a/fees/pangolin.ts +++ b/fees/pangolin.ts @@ -1,12 +1,10 @@ +import { graph } from "@defillama/sdk"; import { CHAIN } from "../helpers/chains"; -import { univ2DimensionAdapter } from "../helpers/getUniSubgraph"; +import { univ2DimensionAdapter2 } from "../helpers/getUniSubgraph"; -const adapter = univ2DimensionAdapter({ +const adapter = univ2DimensionAdapter2({ graphUrls: { - [CHAIN.AVAX]: "https://api.thegraph.com/subgraphs/name/pangolindex/exchange" - }, - dailyVolume: { - factory: "pangolinDayData" + [CHAIN.AVAX]: graph.modifyEndpoint('CPXTDcwh6tVP88QvFWW7pdvZJsCN4hSnfMmYeF1sxCLq') }, totalVolume: { factory: "pangolinFactories" @@ -31,4 +29,5 @@ const adapter = univ2DimensionAdapter({ } }); -export default adapter; \ No newline at end of file + +export default adapter; diff --git a/fees/paraswap.ts b/fees/paraswap.ts index 9989ddfef0..63766e3543 100644 --- a/fees/paraswap.ts +++ b/fees/paraswap.ts @@ -1,88 +1,3 @@ -import { Adapter, FetchResultFees } from "../adapters/types"; -import { CHAIN } from "../helpers/chains"; -import { getTimestampAtStartOfDayUTC } from "../utils/date"; -import { Chain } from "@defillama/sdk/build/general"; -import fetchURL from "../utils/fetchURL"; +import {getParaswapAdapter} from "../aggregators/paraswap/paraswapApi" - -const feesMMURL = "https://api.paraswap.io/stk/volume-stats/breakdown-by-chain"; -type TChainId = { - [l: string | Chain]: string; -} -const mapChainId: TChainId = { - [CHAIN.ETHEREUM]: '1', - [CHAIN.POLYGON]: '137', - [CHAIN.BSC]: '56', - [CHAIN.AVAX]: '43114', - [CHAIN.FANTOM]: '250', - [CHAIN.ARBITRUM]: '42161', - [CHAIN.OPTIMISM]: '10', -} - -interface IResponse { - daily: any[]; - allTime: any; -} - -const fetch = (chain: Chain) => { - return async (timestamp: number): Promise => { - const timestampToday = getTimestampAtStartOfDayUTC(timestamp) - const response: IResponse = (await fetchURL(feesMMURL)); - const dailyResultFees: any[] = response.daily; - const [__,totalPartnerRevenue, totalProtocolRevenue]: number[] = response.allTime[mapChainId[chain]]; - const [_, partnerRevenue, protocolRevenue]: number[] = dailyResultFees.filter(([time]: any) => time === timestampToday) - .map(([_, data]: any) => data[mapChainId[chain]]).flat() - const otherFees = partnerRevenue + protocolRevenue; - const otherProtocolReveune = protocolRevenue; - - const dailyFees = otherFees; - if (dailyFees > 1_000_000) { - return {} as FetchResultFees; - } - const dailyRevenue = otherProtocolReveune; - const totalFees = totalPartnerRevenue + totalProtocolRevenue; - const totalRevenue = totalProtocolRevenue; - return { - dailyFees: dailyFees ? dailyFees.toString() : undefined, - dailyRevenue: dailyRevenue ? dailyRevenue.toString() : undefined, - totalRevenue: totalRevenue ? totalRevenue.toString() : undefined, - totalFees: totalFees ? totalFees.toString(): undefined, - timestamp - } - } -} - -const adapter: Adapter = { - adapter: { - [CHAIN.ETHEREUM]: { - fetch: fetch(CHAIN.ETHEREUM), - start: 1647907200, - }, - [CHAIN.POLYGON]: { - fetch: fetch(CHAIN.POLYGON), - start: 1647907200, - }, - [CHAIN.BSC]: { - fetch: fetch(CHAIN.BSC), - start: 1647907200, - }, - [CHAIN.AVAX]: { - fetch: fetch(CHAIN.AVAX), - start: 1647907200, - }, - [CHAIN.FANTOM]: { - fetch: fetch(CHAIN.FANTOM), - start: 1647907200, - }, - [CHAIN.ARBITRUM]: { - fetch: fetch(CHAIN.ARBITRUM), - start: 1647907200, - }, - [CHAIN.OPTIMISM]: { - fetch: fetch(CHAIN.OPTIMISM), - start: 1647907200, - } - } -} - -export default adapter; +export default getParaswapAdapter("fees"); \ No newline at end of file diff --git a/fees/paxos-gold/index.ts b/fees/paxos-gold/index.ts new file mode 100644 index 0000000000..2270017707 --- /dev/null +++ b/fees/paxos-gold/index.ts @@ -0,0 +1,36 @@ +import { Adapter, FetchOptions, FetchResultV2 } from "../../adapters/types"; +import { CHAIN } from "../../helpers/chains"; + +const PAXG = "0x45804880de22913dafe09f4980848ece6ecbaf78"; + +const eventAbi = `event FeeCollected( + address indexed from, + address indexed to, + uint256 value +)`; + +const fetch = async ({ + getLogs, + createBalances, +}: FetchOptions): Promise => { + const dailyFees = createBalances(); + const logs = await getLogs({ target: PAXG, eventAbi }); + + logs.forEach(([_from, _to, fee]) => { + dailyFees.add(PAXG, fee); + }); + + return { dailyFees }; +}; + +const adapter: Adapter = { + version: 2, + adapter: { + [CHAIN.ETHEREUM]: { + fetch, + start: 1704063600, + }, + }, +}; + +export default adapter; diff --git a/fees/pear-protocol/index.ts b/fees/pear-protocol/index.ts new file mode 100644 index 0000000000..a0fdef061a --- /dev/null +++ b/fees/pear-protocol/index.ts @@ -0,0 +1,31 @@ +import { Adapter, FetchOptions, SimpleAdapter } from "../../adapters/types"; +import { CHAIN } from "../../helpers/chains"; +import { httpGet } from "../../utils/fetchURL"; + +const fetch = async (timestamp: number) => { + const url = `https://www.api.pearprotocol.io/v1/metric?timestamp=${timestamp}`; + const response = await httpGet(url); + const totalFees = response.payload.totalFees; + const dailyFees = response.payload.dailyFees; + const dailyRevenue = dailyFees; + const totalRevenue = totalFees; + + return { + dailyFees, + totalFees, + dailyRevenue, + totalRevenue, + timestamp, + }; +}; + +const adapter: SimpleAdapter = { + adapter: { + [CHAIN.ARBITRUM]: { + fetch: fetch, + start: 1715199684, + }, + }, +}; + +export default adapter; diff --git a/fees/pearlfi.ts b/fees/pearlfi.ts index 8987d5d51c..61eb30a0ba 100644 --- a/fees/pearlfi.ts +++ b/fees/pearlfi.ts @@ -1,16 +1,5 @@ -import { SimpleAdapter } from "../adapters/types"; -import { CHAIN } from "../helpers/chains"; -import { getDexFeesExports } from "../helpers/dexVolumeLogs"; +import { uniV2Exports } from "../helpers/uniswap"; -const FACTORY_ADDRESS = '0xEaF188cdd22fEEBCb345DCb529Aa18CA9FcB4FBd'; - -const adapter: SimpleAdapter = { - adapter: { - [CHAIN.POLYGON]: { - fetch: getDexFeesExports({ chain: CHAIN.POLYGON, factory: FACTORY_ADDRESS,}), - start: 1686268800, - }, - } -}; - -export default adapter; +export default uniV2Exports({ + polygon: { factory: '0xEaF188cdd22fEEBCb345DCb529Aa18CA9FcB4FBd', }, +}); diff --git a/fees/pendle.ts b/fees/pendle.ts index 749fe7990e..98e22c25c0 100644 --- a/fees/pendle.ts +++ b/fees/pendle.ts @@ -6,33 +6,25 @@ import { } from "../adapters/types"; import { CHAIN } from "../helpers/chains"; import { Chain } from "@defillama/sdk/build/general"; -import request from "graphql-request"; import { addTokensReceived } from "../helpers/token"; -import { StringNumber } from "@defillama/sdk/build/types"; import BigNumber from "bignumber.js"; +import { getConfig } from "../helpers/cache"; +import { ChainApi } from "@defillama/sdk"; + +const ABI = { + assetInfo: "function assetInfo() view returns (uint8,address,uint8)", + getRewardTokens: "function getRewardTokens() view returns (address[])", + exchangeRate: "function exchangeRate() view returns (uint256)", + marketSwapEvent: + "event Swap(address indexed caller, address indexed receiver, int256 netPtOut, int256 netSyOut, uint256 netSyFee, uint256 netSyToReserve)", +}; type IConfig = { [s: string | Chain]: { - endpoint: string; treasury: string; }; }; -const gqlQuery = ` -{ - assets(first: 1000, where: { - type_in: ["SY"] - }) { - id, - type - accountingAssetType - accountingAsset { - id - } - } -} -`; - const STETH_ETHEREUM = "ethereum:0xae7ab96520de3a18e5e111b5eaab095312d7fe84"; const EETH_ETHEREUM = "ethereum:0x35fa164735182de50811e8e2e824cfb9b6118ac2"; const WETH_ETHEREUM = "ethereum:0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2"; @@ -52,31 +44,26 @@ const BRIDGED_ASSETS = [ }, { sy: "0x9d6d509c0354aca187aac6bea7d063d3ef68e2a0", - asset: WETH_ETHEREUM + asset: WETH_ETHEREUM, }, ]; const chainConfig: IConfig = { [CHAIN.ETHEREUM]: { - endpoint: - "https://api.thegraph.com/subgraphs/name/pendle-finance/core-mainnet-23-dec-18", treasury: "0x8270400d528c34e1596ef367eedec99080a1b592", }, [CHAIN.ARBITRUM]: { - endpoint: - "https://api.thegraph.com/subgraphs/name/pendle-finance/core-arbitrum-23-dec-18", treasury: "0xcbcb48e22622a3778b6f14c2f5d258ba026b05e6", }, [CHAIN.BSC]: { - endpoint: - "https://api.thegraph.com/subgraphs/name/pendle-finance/core-bsc-23-dec-18", treasury: "0xd77e9062c6df3f2d1cb5bf45855fa1e7712a059e", }, [CHAIN.OPTIMISM]: { - endpoint: - "https://api.thegraph.com/subgraphs/name/pendle-finance/core-optimism-23-dec-18", treasury: "0xe972d450ec5b11b99d97760422e0e054afbc8042", }, + [CHAIN.MANTLE]: { + treasury: "0x5c30d3578a4d07a340650a76b9ae5df20d5bdf55" + } }; const fetch = (chain: Chain) => { @@ -85,94 +72,130 @@ const fetch = (chain: Chain) => { _: ChainBlocks, options: FetchOptions ): Promise => { - const { api } = options; - const allSyDatas: { - id: string; - type: string; - accountingAssetType: number; - accountingAsset: { - id: string; - }; - }[] = (await request(chainConfig[chain].endpoint, gqlQuery)).assets; - - const allSy: string[] = allSyDatas - .filter((token: any) => token.type === "SY") - .map((token: any) => token.id.toLowerCase()); + await getWhitelistedAssets(options.api); + const { api, getLogs, createBalances } = options; + + const { markets, sys, marketToSy } = await getWhitelistedAssets(api); const rewardTokens: string[] = ( await api.multiCall({ permitFailure: true, - abi: getRewardTokensABI, - calls: allSy, + abi: ABI.getRewardTokens, + calls: sys, }) ).flat(); const exchangeRates: String | null[] = []; - for (const sy of allSy) { + const assetInfos: (string[] | null)[] = []; + for (const sy of sys) { try { - const exchangeRate = await api.call({ target: sy, abi: exchangeRateABI, }); - exchangeRates.push(exchangeRate) + const exchangeRate = await api.call({ + target: sy, + abi: ABI.exchangeRate, + }); + const assetInfo = await api.call({ target: sy, abi: ABI.assetInfo }); + exchangeRates.push(exchangeRate); + assetInfos.push(assetInfo); } catch (e) { - console.error(e) - exchangeRates.push(null) + exchangeRates.push(null); + assetInfos.push(null); } } - const dailyFees = await addTokensReceived({ + const dailySupplySideFees = createBalances(); + const allSwapEvents = await getLogs({ + targets: markets, + eventAbi: ABI.marketSwapEvent, + flatten: false, + }); + + markets.forEach((market, i) => { + const token = marketToSy.get(market); + const logs = allSwapEvents[i] + logs.forEach((log: any) => { + const netSyFee = log.netSyFee; + const netSyToReserve = log.netSyToReserve; + dailySupplySideFees.add(token!, netSyFee - netSyToReserve); // excluding revenue fee + }) + }) + + const dailyRevenue = await addTokensReceived({ options, target: chainConfig[chain].treasury, - tokens: rewardTokens.concat(allSy), + tokens: rewardTokens.concat(sys), }); - const allTokenList = dailyFees.getBalances(); - for (const token in allTokenList) { + const allRevenueTokenList = dailyRevenue.getBalances(); + const allSupplySideTokenList = dailySupplySideFees.getBalances(); + + for (const token in allRevenueTokenList) { const tokenAddr = token.split(":")[1]; - const index = allSyDatas.findIndex( - (syData) => syData.id.toLowerCase() === tokenAddr.toLowerCase() - ); + const index = sys.indexOf(tokenAddr); - if (index == -1) continue; + if (index == -1 || !assetInfos[index]) continue; - const rawAmount = allTokenList[token]; - dailyFees.removeTokenBalance(token); + const assetInfo = assetInfos[index]!; - let underlyingAsset = allSyDatas[index].accountingAsset.id; + const rawAmountRevenue = allRevenueTokenList[token]; + const rawAmountSupplySide = allSupplySideTokenList[token]; + + dailyRevenue.removeTokenBalance(token); + dailySupplySideFees.removeTokenBalance(token); + + let underlyingAsset = assetInfo[1]!; let isBridged = false; for (const bridge of BRIDGED_ASSETS) { - if (bridge.sy.toLowerCase() === tokenAddr.toLowerCase()) { + if (bridge.sy === tokenAddr) { underlyingAsset = bridge.asset; isBridged = true; break; } } - let assetAmount = new BigNumber(rawAmount) - if (allSyDatas[index].accountingAssetType === 0) { - assetAmount = assetAmount.times(exchangeRates[index] ?? 0) + let assetAmountRevenue = new BigNumber(rawAmountRevenue); + let assetAmountSupplySide = new BigNumber(rawAmountSupplySide); + if (assetInfo[0] === "0") { + const rate = exchangeRates[index] ?? 0; + assetAmountRevenue = assetAmountRevenue + .times(rate) + .dividedToIntegerBy(1e18); + assetAmountSupplySide = assetAmountSupplySide + .times(rate) .dividedToIntegerBy(1e18); } - - dailyFees.addToken( + dailyRevenue.addToken( underlyingAsset, - assetAmount, + assetAmountRevenue, isBridged ? { skipChain: true, } : undefined ); + + if (rawAmountSupplySide !== undefined) { + dailySupplySideFees.addToken( + underlyingAsset, + assetAmountSupplySide, + isBridged + ? { + skipChain: true, + } + : undefined + ); + } } - const dailyRevenue = dailyFees.clone(); - const dailySupplySideRevenue = dailyFees.clone(); + const dailyFees = dailyRevenue.clone(); + dailyFees.addBalances(dailySupplySideFees); return { dailyFees: dailyFees, - dailyRevenue: dailyFees, + dailyRevenue: dailyRevenue, dailyHoldersRevenue: dailyRevenue, - dailySupplySideRevenue: dailySupplySideRevenue, + dailySupplySideRevenue: dailySupplySideFees, timestamp, }; }; @@ -195,11 +218,33 @@ const adapter: SimpleAdapter = { [CHAIN.OPTIMISM]: { fetch: fetch(CHAIN.OPTIMISM), start: 1691733600, - } + }, + [CHAIN.MANTLE]: { + fetch: fetch(CHAIN.MANTLE), + start: 1711506087, + }, }, }; -const getRewardTokensABI = "address[]:getRewardTokens"; -const exchangeRateABI = "uint256:exchangeRate"; +async function getWhitelistedAssets(api: ChainApi): Promise<{ + markets: string[]; + sys: string[]; + marketToSy: Map; +}> { + const { results } = await getConfig( + "pendle/v2/revenue-" + api.chain, + `https://api-v2.pendle.finance/core/v1/${api.chainId!}/markets?order_by=name%3A1&skip=0&limit=100&select=all` + ); + const markets = results.map((d: any) => d.lp.address); + const sySet: Set = new Set(results.map((d: any) => d.sy.address)); + const sys = Array.from(sySet); + + const marketToSy = new Map(); + for (const result of results) { + marketToSy.set(result.lp.address, result.sy.address); + } + + return { markets, sys, marketToSy }; +} -export default adapter; +export default adapter; \ No newline at end of file diff --git a/fees/penpie.ts b/fees/penpie.ts new file mode 100644 index 0000000000..23ea9a658a --- /dev/null +++ b/fees/penpie.ts @@ -0,0 +1,94 @@ +import { FetchOptions, SimpleAdapter } from "../adapters/types"; +import { CHAIN } from "../helpers/chains"; +import { Chain } from "@defillama/sdk/build/general"; +const ADDRESSES = require('../helpers/coreAssets.json') + +const event_paid_stream = 'event RewardPaidTo (address _market, address _to, address _rewardToken, uint256 _feeAmount)'; +const event_paid_bribe = 'event RewardClaimed (address indexed token, address indexed account, uint256 amount, uint256 updateCount)'; +const event_pendle_fee= 'event RUpdateProtocolClaimable ( address indexed user, uint256 sumTopUp)'; + +type TAddress = { + [c: string]: string; +} +const address_reward: TAddress = { + + [CHAIN.BSC]: '0x782D9D67FeaA4d1CDF8222D9053c8CBA1c3B7982', + [CHAIN.ARBITRUM]: '0x6DB96BBEB081d2a85E0954C252f2c1dC108b3f81', + [CHAIN.ETHEREUM]: '0x6E799758CEE75DAe3d84e09D40dc416eCf713652' +} +const reward_eth_pendle='0x8C237520a8E14D658170A633D96F8e80764433b9' +const exclude: any = { + [CHAIN.ETHEREUM]: [ + '0xd1D7D99764f8a52Aff007b7831cc02748b2013b5', + '0xC374f7eC85F8C7DE3207a10bB1978bA104bdA3B2', + '0x6010676Bc2534652aD1Ef5Fa8073DcF9AD7EBFBe', + '0x038C1b03daB3B891AfbCa4371ec807eDAa3e6eB6' + ], + [CHAIN.BSC]: [], + [CHAIN.ARBITRUM]: [ + '0xa877a0E177b54A37066c1786F91a1DAb68F094AF' + ] +} +const address_bribe: TAddress = { + [CHAIN.BSC]: '0x6E796bCF2B63b070F9cC0a7D3d857FeF628E9e5b', + [CHAIN.ARBITRUM]: '0x8CE523cf1120d9B7703806c745B69663a2847504', + [CHAIN.ETHEREUM]: '0xa346Bd80943Aa3042E6709d80Ce9C3b8fbeAc4Ab' +} +//all revenue is from bribes and is given to governance token holders 100% + +const graph = (chain: Chain) => { + return async ({ createBalances, getLogs, }: FetchOptions) => { + const dailyFees = createBalances(); + if (chain=='ETHEREUM'){ + (await getLogs({ + target:reward_eth_pendle , + eventAbi: event_pendle_fee, + })).map((e: any) => { + // check if it is penpie + if (e.user === '0x6e799758cee75dae3d84e09d40dc416ecf713652') { + dailyFees.add(ADDRESSES.null, e.sumTopUp); + } + }) + } + (await getLogs({ + target: address_reward[chain], + eventAbi: event_paid_stream, + })).map((e: any) => { + if (exclude[chain].includes(e._rewardToken)) { + return + } + dailyFees.add(e._rewardToken, e._feeAmount) + }), + (await getLogs({ + target: address_bribe[chain], + eventAbi: event_paid_bribe, + })).map((e: any) => { + if (exclude[chain].includes(e.token)) { + return + } + dailyFees.add(e.token, e.amount) + }) + return { dailyFees, dailyRevenue: dailyFees,dailyUserFees:dailyFees }; + } +} + + +const adapter: SimpleAdapter = { + version: 2, + adapter: { + [CHAIN.BSC]: { + fetch: graph(CHAIN.BSC), + start: 77678653, + }, + [CHAIN.ARBITRUM]: { + fetch: graph(CHAIN.ARBITRUM), + start: 77678653, + }, + [CHAIN.ETHEREUM]: { + fetch: graph(CHAIN.ETHEREUM), + start: 77678653, + }, + } +}; + +export default adapter; diff --git a/fees/pepe-swaves/index.ts b/fees/pepe-swaves/index.ts index 7ae167f801..49ac0360ef 100644 --- a/fees/pepe-swaves/index.ts +++ b/fees/pepe-swaves/index.ts @@ -35,7 +35,7 @@ const extractShareReward = (rewardShares: RewardShares, miner: string): number = }, 0) } -const fetch = async (timestamp: number, _: ChainBlocks, { createBalances, getFromBlock, getToBlock, }: FetchOptions) => { +const fetch = async ({ createBalances, getFromBlock, getToBlock, }: FetchOptions) => { let miner = (await getData(ADAPTER, "ADAPTEE")).value; let feeRate = +(await getData(ADAPTER, "FEE_RATE")).value / FEE_DIVIDER; @@ -62,12 +62,11 @@ const fetch = async (timestamp: number, _: ChainBlocks, { createBalances, getFro const dailyRevenue = dailyFees.clone() dailyRevenue.resizeBy(feeRate) - return { - timestamp, dailyFees, dailyRevenue, - }; + return { dailyFees, dailyRevenue }; }; const adapter: Adapter = { + version: 2, adapter: { [CHAIN.WAVES]: { fetch, diff --git a/fees/perp88.ts b/fees/perp88.ts index b08734b8b0..c082c562e0 100644 --- a/fees/perp88.ts +++ b/fees/perp88.ts @@ -1,113 +1,120 @@ import { Adapter } from "../adapters/types"; -import { ARBITRUM, CHAIN, POLYGON } from "../helpers/chains"; -import { request, gql, GraphQLClient } from "graphql-request"; -import type { ChainEndpoints } from "../adapters/types"; -import { Chain } from "@defillama/sdk/build/general"; -import { getTimestampAtStartOfDayUTC, getTimestampAtStartOfNextDayUTC } from "../utils/date"; -import { getBlock } from "../helpers/getBlock"; +import { CHAIN } from "../helpers/chains"; +import { gql, GraphQLClient } from "graphql-request"; +import type { ChainEndpoints, FetchV2 } from "../adapters/types"; +import { getTimestampAtStartOfDayUTC } from "../utils/date"; const endpoints = { - [CHAIN.POLYGON]: "https://api.thegraph.com/subgraphs/name/perp88/plp-pool", - [CHAIN.ARBITRUM]: "https://subgraph.satsuma-prod.com/3a60064481e5/1lxclx3pz4zrusx6414nvj/arbitrum-one-stats/api", + [CHAIN.ARBITRUM]: + "https://subgraph.satsuma-prod.com/3a60064481e5/1lxclx3pz4zrusx6414nvj/arbitrum-one-stats/api", + [CHAIN.BLAST]: + "https://api.studio.thegraph.com/query/45963/blast-mainnet-stats/version/latest", }; -interface IData { - totalFees: string; -} -interface IGraph { - yesterday: IData; - today: IData; - statistic: IData; -} const graphs = (graphUrls: ChainEndpoints) => { - return (chain: Chain) => { - return async (timestamp: number) => { - if (chain === CHAIN.POLYGON) { - const todaysTimestamp = getTimestampAtStartOfDayUTC(timestamp) - const yesterdaysTimestamp = getTimestampAtStartOfNextDayUTC(timestamp) - - const todaysBlock = (await getBlock(todaysTimestamp, chain, {})); - const yesterdaysBlock = (await getBlock(yesterdaysTimestamp, chain, {})); - const graphQuery = gql` - { - statistic(id: 0, block: {number: ${yesterdaysBlock}}) { - totalFees - } - } - `; - const queryDaily = gql` - query fees { - yesterday: statistic(id: "0", block: {number: ${yesterdaysBlock}}){ - totalFees - } - today: statistic(id: "0", block: {number: ${todaysBlock}}) { - totalFees - } - } - ` - - const graphRes: IGraph = await request(graphUrls[chain], graphQuery); - const graphResDaily: IGraph = await request(graphUrls[chain], queryDaily); - const dailyFee = (Number(graphResDaily.yesterday.totalFees) - Number(graphResDaily.today.totalFees))/1e30; - const totalFees = parseInt(graphRes.statistic.totalFees) / 1e30; - - return { - timestamp, - dailyFees: dailyFee.toString(), - totalFees: totalFees.toString(), - }; - } else if (chain === CHAIN.ARBITRUM) { - const floorDayTimestamp = getTimestampAtStartOfDayUTC(timestamp); - const totalFeeQuery = gql` - { - globalFeesStat(id: "global") { - totalFeePaid - } + const fetch: FetchV2 = async ({ chain, startTimestamp }) => { + if (chain === CHAIN.ARBITRUM || chain === CHAIN.BLAST) { + const floorDayTimestamp = getTimestampAtStartOfDayUTC(startTimestamp); + const totalFeeQuery = gql` + { + globalFeesStat(id: "global") { + totalFeePaid + settlementFeePaid + liquidationFeePaid + borrowingFeePaid + tradingFeePaid + addLiquidityFeePaid + removeLiquidityFeePaid + fundingFeePaid } - ` - const dailyFeeQuery = gql` + } + `; + const dailyFeeQuery = gql` { dailyFeesStat(id: "${floorDayTimestamp}") { totalFeePaid + settlementFeePaid + liquidationFeePaid + borrowingFeePaid + tradingFeePaid + addLiquidityFeePaid + removeLiquidityFeePaid + fundingFeePaid } } - ` - const graphQLClient = new GraphQLClient(graphUrls[chain]); - graphQLClient.setHeader('origin', 'https://hmx.org') - const totalFeeResp = await graphQLClient.request(totalFeeQuery); - const dailyFeeResp = await graphQLClient.request(dailyFeeQuery); + `; + const graphQLClient = new GraphQLClient(graphUrls[chain]); + graphQLClient.setHeader("origin", "https://hmx.org"); + const totalFeeResp = await graphQLClient.request(totalFeeQuery); + const dailyFeeResp = await graphQLClient.request(dailyFeeQuery); - const finalizedDailyFee = (Number(dailyFeeResp.dailyFeesStat.totalFeePaid) / 1e30); - const finalizedTotalFee = (Number(totalFeeResp.globalFeesStat.totalFeePaid) / 1e30); - - return { - timestamp, - dailyFees: finalizedDailyFee.toString(), - totalFees: finalizedTotalFee.toString(), - dailyHoldersRevenue: (finalizedDailyFee * 0.25).toString(), - dailySupplySideRevenue: (finalizedDailyFee * 0.75).toString(), - } - } + const finalizedDailyFee = + Number(dailyFeeResp.dailyFeesStat.totalFeePaid) / 1e30; + const finalizedTotalFee = + Number(totalFeeResp.globalFeesStat.totalFeePaid) / 1e30; + const finalizedDailyFeeWithoutFundingFee = + (Number(dailyFeeResp.dailyFeesStat.tradingFeePaid) + + Number(dailyFeeResp.dailyFeesStat.borrowingFeePaid) + + Number(dailyFeeResp.dailyFeesStat.liquidationFeePaid) + + Number(dailyFeeResp.dailyFeesStat.settlementFeePaid) + + Number(dailyFeeResp.dailyFeesStat.addLiquidityFeePaid) + + Number(dailyFeeResp.dailyFeesStat.removeLiquidityFeePaid)) / + 1e30; + const finalizedDailyUserFee = + (Number(dailyFeeResp.dailyFeesStat.tradingFeePaid) + + Number(dailyFeeResp.dailyFeesStat.borrowingFeePaid) + + Number(dailyFeeResp.dailyFeesStat.liquidationFeePaid) + + Number(dailyFeeResp.dailyFeesStat.fundingFeePaid) + + Number(dailyFeeResp.dailyFeesStat.settlementFeePaid)) / + 1e30; + const finalizedTotalUserFee = + (Number(totalFeeResp.globalFeesStat.tradingFeePaid) + + Number(totalFeeResp.globalFeesStat.borrowingFeePaid) + + Number(totalFeeResp.globalFeesStat.liquidationFeePaid) + + Number(totalFeeResp.globalFeesStat.fundingFeePaid) + + Number(totalFeeResp.globalFeesStat.settlementFeePaid)) / + 1e30; + const dailyHoldersRevenue = (finalizedDailyFeeWithoutFundingFee * 35) / 90; + const dailyProtocolRevenue = (finalizedDailyFeeWithoutFundingFee * 5) / 90; + const dailySupplySideRevenue = (finalizedDailyFeeWithoutFundingFee * 50) / 90; return { - timestamp, - dailyFees: "0", - totalFees: "0", - } + dailyFees: finalizedDailyFee.toString(), + dailyUserFees: finalizedDailyUserFee.toString(), + dailyRevenue: (dailyHoldersRevenue + dailyProtocolRevenue).toString(), + dailyProtocolRevenue: dailyProtocolRevenue.toString(), + dailyHoldersRevenue: dailyHoldersRevenue.toString(), + dailySupplySideRevenue: dailySupplySideRevenue.toString(), + totalFees: finalizedTotalFee.toString(), + totalUserFees: finalizedTotalUserFee.toString(), + }; + } + + return { + dailyFees: "0", + dailyUserFees: "0", + dailyRevenue: "0", + dailyProtocolRevenue: "0", + dailyHoldersRevenue: "0", + dailySupplySideRevenue: "0", + totalFees: "0", + totalUserFees: "0", }; }; + return fetch; }; const adapter: Adapter = { + version: 2, adapter: { - [CHAIN.POLYGON]: { - fetch: graphs(endpoints)(CHAIN.POLYGON), - start: 1668643200, - }, [CHAIN.ARBITRUM]: { - fetch: graphs(endpoints)(CHAIN.ARBITRUM), + fetch: graphs(endpoints), start: 1687392000, - } + }, + [CHAIN.BLAST]: { + fetch: graphs(endpoints), + start: 1707094598, + }, }, }; diff --git a/fees/perpetual-protocol.ts b/fees/perpetual-protocol.ts index 90bfd0e155..bea056aab6 100644 --- a/fees/perpetual-protocol.ts +++ b/fees/perpetual-protocol.ts @@ -1,53 +1,22 @@ -import { FetchResultFees, SimpleAdapter } from "../adapters/types"; -import * as sdk from "@defillama/sdk"; +import { FetchOptions, SimpleAdapter } from "../adapters/types"; import { CHAIN } from "../helpers/chains"; -import { ethers } from "ethers"; -import { getBlock } from "../helpers/getBlock"; const address = '0x82ac2ce43e33683c58be4cdc40975e73aa50f459'; -const topic0_position_change = '0x968bc4f738eae0486dc6736c4b427dbafa4acfdf6eaf223337791ddeb3a56247' const event_postion_change = 'event PositionChanged(address indexed trader,address indexed baseToken,int256 exchangedPositionSize,int256 exchangedPositionNotional,uint256 fee,int256 openNotional,int256 realizedPnl,uint256 sqrtPriceAfterX96)'; -const contract_interface = new ethers.Interface([ - event_postion_change, -]); -interface ILog { - data: string; - transactionHash: string; - topics: string[]; -} - -const fetchFees = async (timestamp: number): Promise => { - const toTimestamp = timestamp - const fromTimestamp = timestamp - 60 * 60 * 24 - const fromBlock = (await getBlock(fromTimestamp, CHAIN.OPTIMISM, {})) - const toBlock = (await getBlock(toTimestamp, CHAIN.OPTIMISM, {})) - const logs_position_chnage: ILog[] = (await sdk.getEventLogs({ - target: address, - topics: [topic0_position_change], - toBlock: toBlock, - fromBlock: fromBlock, - chain: CHAIN.OPTIMISM - })) as ILog[]; +const fetchFees = async ({ createBalances, getLogs, }: FetchOptions) => { + const logs = await getLogs({ target: address, eventAbi: event_postion_change }) + const dailyFees = createBalances() + logs.map((e: any) => { dailyFees.addUSDValue(Number(e.fee) / 10 ** 18) }) - const fees_details = logs_position_chnage.map((e: ILog) => { - const value = contract_interface.parseLog(e); - return Number(value!.args.fee) / 10 ** 18; - }).reduce((a: number, b: number) => a + b, 0) - - const dailyFees = fees_details - const dailyRevenue = dailyFees * 0.2; - const dailySupplySideRevenue = dailyFees * 0.8; - return { - dailyFees: `${dailyFees}`, - dailyRevenue: `${dailyRevenue}`, - dailySupplySideRevenue: `${dailySupplySideRevenue}`, - timestamp - } + const dailyRevenue = dailyFees.clone(0.2) + const dailySupplySideRevenue = dailyFees.clone(0.8) + return { dailyFees, dailyRevenue, dailySupplySideRevenue, } } const adapters: SimpleAdapter = { + version: 2, adapter: { [CHAIN.OPTIMISM]: { fetch: fetchFees, diff --git a/fees/pharaoh-exchange.ts b/fees/pharaoh-exchange.ts index c00c818e5b..f3b464ec50 100644 --- a/fees/pharaoh-exchange.ts +++ b/fees/pharaoh-exchange.ts @@ -1,64 +1,62 @@ -import { SimpleAdapter, FetchResultFees, BaseAdapter } from "../adapters/types"; +import * as sdk from "@defillama/sdk"; +import { SimpleAdapter } from "../adapters/types"; import { AVAX, CHAIN } from "../helpers/chains"; - - import { - getGraphDimensions, - DEFAULT_DAILY_VOLUME_FACTORY, - DEFAULT_TOTAL_VOLUME_FIELD, - } from "../helpers/getUniSubgraph" + DEFAULT_DAILY_VOLUME_FACTORY, + DEFAULT_TOTAL_VOLUME_FIELD, + getGraphDimensions2, +} from "../helpers/getUniSubgraph"; type TStartTime = { -[key: string]: number; -} -const startTimeV2:TStartTime = { -[CHAIN.AVAX]: 1702339200, -} - + [key: string]: number; +}; +const startTimeV2: TStartTime = { + [CHAIN.AVAX]: 1702339200, +}; const v2Endpoints = { - [CHAIN.AVAX]: "https://api.thegraph.com/subgraphs/name/ramsesexchange/pharaoh-cl-subgraph", - }; + [CHAIN.AVAX]: + sdk.graph.modifyEndpoint('oM4WnuyAbSwPpjk6niUkp88AZg1hSTi9aC1ZM4RcsqR'), +}; const VOLUME_USD = "volumeUSD"; -const v2Graphs = getGraphDimensions({ - graphUrls: v2Endpoints, - totalVolume: { - factory: "factories", - field: DEFAULT_TOTAL_VOLUME_FIELD, +const v2Graphs = getGraphDimensions2({ + graphUrls: v2Endpoints, + totalVolume: { + factory: "factories", + field: DEFAULT_TOTAL_VOLUME_FIELD, + }, + feesPercent: { + type: "fees", + HoldersRevenue: 72, + UserFees: 100, // User fees are 100% of collected fees + Revenue: 80, // Revenue is 50% of collected fees + SupplySideRevenue: 20, + ProtocolRevenue: 8, + }, +}); + +const methodology = { + UserFees: "User pays 0.3% fees on each swap.", + ProtocolRevenue: "Revenue going to the protocol.", + HoldersRevenue: "User fees are distributed among holders.", +}; + +const adapter: SimpleAdapter = { + version: 2, + adapter: { + [CHAIN.AVAX]: { + fetch: v2Graphs(AVAX), + start: startTimeV2[CHAIN.AVAX], + meta: { + methodology: { + ...methodology, + UserFees: "User pays 0.05%, 0.30%, or 1% on each swap.", + }, + }, }, - dailyVolume: { - factory: DEFAULT_DAILY_VOLUME_FACTORY, - field: VOLUME_USD, - }, - feesPercent: { - type: "fees", - HoldersRevenue: 50, - UserFees: 100, // User fees are 100% of collected fees - Revenue: 50, // Revenue is 50% of collected fees - SupplySideRevenue: 50, - } - }); - - const methodology = { - UserFees: "User pays 0.3% fees on each swap.", - ProtocolRevenue: "Revenue going to the protocol.", - HoldersRevenue: "User fees are distributed among holders." - } - - const adapter: SimpleAdapter = { - adapter: { - [CHAIN.AVAX]: {fetch: v2Graphs(AVAX), - start: startTimeV2[CHAIN.AVAX], - meta: { - methodology: { - ...methodology, - UserFees: "User pays 0.05%, 0.30%, or 1% on each swap." - } - } - }, - } - }; + }, +}; export default adapter; diff --git a/fees/photon.ts b/fees/photon.ts new file mode 100644 index 0000000000..14f8d53380 --- /dev/null +++ b/fees/photon.ts @@ -0,0 +1,29 @@ +import { FetchOptions, SimpleAdapter } from "../adapters/types"; +import { CHAIN } from "../helpers/chains"; +import { queryDune } from "../helpers/dune"; + +const fetch: any = async (options: FetchOptions) => { + const dailyFees = options.createBalances(); + const value = (await queryDune("3521814", { + start: options.startTimestamp, + end: options.endTimestamp, + receiver: 'AVUCZyuT35YSuj4RH7fwiyPu82Djn2Hfg7y2ND2XcnZH' + })); + dailyFees.add('So11111111111111111111111111111111111111112', value[0].fee_token_amount); + + return { dailyFees, dailyRevenue: dailyFees } + +} + +const adapter: SimpleAdapter = { + version: 2, + adapter: { + [CHAIN.SOLANA]: { + fetch: fetch, + start: 0, + }, + }, + isExpensiveAdapter: true +}; + +export default adapter; \ No newline at end of file diff --git a/fees/pika-protocol-v4.ts b/fees/pika-protocol-v4.ts index 99242e67f6..29af4ef8df 100644 --- a/fees/pika-protocol-v4.ts +++ b/fees/pika-protocol-v4.ts @@ -1,3 +1,4 @@ +import * as sdk from "@defillama/sdk"; import { Chain } from "@defillama/sdk/build/general"; import BigNumber from "bignumber.js"; import request, { gql } from "graphql-request"; @@ -37,7 +38,7 @@ interface ILiquidations { } const endpoints: IURL = { - [CHAIN.OPTIMISM]: "https://api.thegraph.com/subgraphs/name/ethandev0/pikaperpv4_optimism" + [CHAIN.OPTIMISM]: sdk.graph.modifyEndpoint('5dP9FpbXxmNPRaERfzyKEGuRKh2NRQuwPBWfMLGoSRX5') } const fetch = (chain: Chain) => { diff --git a/fees/pika-protocol.ts b/fees/pika-protocol.ts index 12494bdeb7..57b65a3e17 100644 --- a/fees/pika-protocol.ts +++ b/fees/pika-protocol.ts @@ -1,3 +1,4 @@ +import * as sdk from "@defillama/sdk"; import { Chain } from "@defillama/sdk/build/general"; import BigNumber from "bignumber.js"; import request, { gql } from "graphql-request"; @@ -37,7 +38,7 @@ interface ILiquidations { } const endpoints: IURL = { - [CHAIN.OPTIMISM]: "https://api.thegraph.com/subgraphs/name/ethandev0/pikaperpv3_optimism" + [CHAIN.OPTIMISM]: sdk.graph.modifyEndpoint('DUcxevdqV8kBQdHWcdUcaEctaoVyqYZTtCftojL23NbA') } const fetch = (chain: Chain) => { @@ -121,7 +122,7 @@ const fetch = (chain: Chain) => { const adapter: Adapter = { adapter: { [CHAIN.OPTIMISM]: { - fetch: fetch(CHAIN.OPTIMISM), + fetch: async (timestamp: number) => {return {timestamp, dailyFees: "0", dailyRevenue: "0", dailySupplySideRevenue: "0", dailyProtocolRevenue: "0"}}, start: 1658534400, }, }, diff --git a/fees/pingu/index.ts b/fees/pingu/index.ts index b4f6c6a7ba..d5f5deafa4 100644 --- a/fees/pingu/index.ts +++ b/fees/pingu/index.ts @@ -11,7 +11,7 @@ interface IGraph { id: string; } -const URL = 'https://api.studio.thegraph.com/query/43986/pingu-sg/0.1.0'; +const URL = 'https://api.studio.thegraph.com/query/75208/pingu-sg-v2/0.0.1/'; const fetch = async (timestamp: number): Promise => { const dayTimestamp = getUniqStartOfTodayTimestamp(new Date(timestamp * 1000)); @@ -39,6 +39,7 @@ const fetch = async (timestamp: number): Promise => { } const adapter: SimpleAdapter = { + version: 1, adapter: { [CHAIN.ARBITRUM]: { fetch: fetch, diff --git a/fees/pocket-universe.ts b/fees/pocket-universe.ts new file mode 100644 index 0000000000..4598981aba --- /dev/null +++ b/fees/pocket-universe.ts @@ -0,0 +1,24 @@ +import { FetchOptions, SimpleAdapter } from "../adapters/types"; +import { CHAIN } from "../helpers/chains"; +import { addTokensReceived } from "../helpers/token"; + +const fetch: any = async (options: FetchOptions) => { + const dailyFees = await addTokensReceived({ + options, targets: [ + '0x77777D91c0B8Ec9984a05302E4Ef041dcCf77FeE', + ] + }) + + return { dailyFees, } +}; + +const adapter: SimpleAdapter = { + version: 2, + adapter: { + [CHAIN.ETHEREUM]: { + fetch, + start: 0, + }, + }, +}; +export default adapter; diff --git a/fees/polter/index.ts b/fees/polter/index.ts new file mode 100644 index 0000000000..f60fdc4b6f --- /dev/null +++ b/fees/polter/index.ts @@ -0,0 +1,174 @@ +import { Adapter } from "../../adapters/types"; +import { CHAIN } from "../../helpers/chains"; +import { request, gql } from "graphql-request"; +import { FetchV2 } from "../../adapters/types"; + +type THeader = { + [s: string]: string; +}; +const headers: THeader = { + origin: "https://polter.finance/", + referer: "https://polter.finance/", + "user-agent": + "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36", +}; + +const RECORDS_PER_PAGE = 1000; +const endpoints: any = { + [CHAIN.FANTOM]: + "https://api.studio.thegraph.com/query/71811/polter/version/latest", + [CHAIN.BASE]: + "https://api.studio.thegraph.com/query/71811/polter-base/version/latest", +}; + +const tokens: any = { + fantom: { + "0x5c725631fd299703d0a74c23f89a55c6b9a0c52f": { + gecko: "polter-finance", + decimals: 18, + }, + "0xbbce4b1513d4285bd7a59c2c63835535151c8e7c": { + gecko: "fantom", + decimals: 18, + }, + "0x5a75a5f3a637cc9394816efc553d102302d4cfcd": { + gecko: "usd-coin", + decimals: 6, + }, + "0xa826b29d81caef8c9aa212f172ab3ef00566e91e": { + gecko: "magic-internet-money", + decimals: 18, + }, + "0x4bf6f3210488091a0111daf7ab7cf840a3af8022": { + gecko: "stader-sftmx", + decimals: 18, + }, + "0x0299553df0fa396c0f6f3456d293608e189c3cf3": { + gecko: "solana", + decimals: 18, + }, + "0xb49da25f726451ba0e7c7e1c0b273322d2656514": { + gecko: "layerzero-usdc", + decimals: 6, + }, + "0xc60f08059586849810d9c19c67919d2d99174ecf": { + gecko: "axlusdc", + decimals: 6, + }, + "0xa37e0d5590436bd9abd2803c18c328a650b236ee": { + gecko: "bitcoin", + decimals: 8, + }, + "0x328c7a684f160c089ebff07ff1b5a417f024979e": { + gecko: "bridged-wrapped-ether-stargate", + decimals: 18, + }, + }, + base: { + "0xa0820613976b441e2c6a90e4877e2fb5f7d72552": { + gecko: "polter-finance", + decimals: 18, + }, + "0xca4e076c6d8a84a990986a3c405093087991a8fe": { + gecko: "ethereum", + decimals: 18, + }, + "0x2a96e27e204ef366671232df28f147fa30e735ce": { + gecko: "coinbase-wrapped-btc", + decimals: 8, + }, + "0x1ddaeebbd69dccc92f5cf76593104976b9c62434": { + gecko: "usd-coin", + decimals: 6, + }, + }, +}; + +const nonTokens: string[] = [ + "0x6f78d5d203ee7f4f3821ea7ae507e3e20b0930ef", // pAERO +]; + +type RewardsPaid = { + id: number; + reward: BigInt; + rewardsToken: string; + blockTimestamp: number; +}; + +const fetch: FetchV2 = async ({ + chain, + startTimestamp, + endTimestamp, + createBalances, +}) => { + let skip = 0; + const dailyFees = createBalances(); + const dailyRevenue = createBalances(); + const rewardsPaids: RewardsPaid[] = []; + while (true) { + const graphQuery = gql`{ + rewardPaids( + first: ${RECORDS_PER_PAGE}, + skip: ${skip} + where: { blockTimestamp_lte: ${endTimestamp}, blockTimestamp_gte: ${startTimestamp} }, + orderBy: blockTimestamp + order: ASC + ) { + id + reward + rewardsToken + blockTimestamp + } + }`; + + const graphRes = await request(endpoints[chain], graphQuery, {}, headers); + const rewardsPaid = graphRes.rewardPaids; + if (rewardsPaid.length == 0) { + break; + } + skip += RECORDS_PER_PAGE; + rewardsPaids.push(...rewardsPaid); + } + rewardsPaids.forEach((reward: RewardsPaid) => { + if (nonTokens.includes(reward.rewardsToken.toLowerCase())) return; + const { gecko, decimals } = tokens[chain][reward.rewardsToken]; + if (!gecko) { + return; + } + dailyFees.addCGToken(gecko, Number(reward.reward) / 10 ** decimals); + dailyRevenue.addCGToken(gecko, Number(reward.reward) / 10 ** decimals); + }); + dailyRevenue.resizeBy(0.5); + return { + dailyFees, + dailyRevenue, + }; +}; + +const adapter: Adapter = { + version: 2, + adapter: { + [CHAIN.FANTOM]: { + fetch: fetch, + start: 1706546953, // Jan-29-2024 04:49:13 PM +UTC + meta: { + methodology: { + Fees: "lockers' revenue = stakers' revenue + 50% penalty from early exit", + Revenue: "depositors' revenue from borrow interests", + }, + }, + }, + [CHAIN.BASE]: { + fetch: fetch, + start: 19746482, // Sep-14-2024 02:51:51 AM +UTC + meta: { + methodology: { + Fees: "lockers' revenue = stakers' revenue + 50% penalty from early exit", + Revenue: "depositors' revenue from borrow interests", + }, + }, + }, + }, +}; + +export default adapter; diff --git a/fees/polter/types.ts b/fees/polter/types.ts new file mode 100644 index 0000000000..9c26b29141 --- /dev/null +++ b/fees/polter/types.ts @@ -0,0 +1,10 @@ +export type V2Reserve = { + lifetimeFlashLoanPremium: string + lifetimeReserveFactorAccrued: string + lifetimeDepositorsInterestEarned: string + priceInUsd: string + reserve: { + decimals: number + symbol: string + } +} diff --git a/fees/polygon.ts b/fees/polygon.ts index 6a61ba186f..2ce0f69d4b 100644 --- a/fees/polygon.ts +++ b/fees/polygon.ts @@ -54,8 +54,9 @@ const adapter: Adapter = { return { timestamp, dailyFees, dailyRevenue, }; }, // start: 1575158400, - start: 1672531200 - }, + start: 1672531200, + runAtCurrTime: true, + } }, isExpensiveAdapter: true, protocolType: ProtocolType.CHAIN diff --git a/fees/post-tech.ts b/fees/post-tech.ts index 79f347b85c..3e5a69d6b1 100644 --- a/fees/post-tech.ts +++ b/fees/post-tech.ts @@ -11,7 +11,8 @@ const adapter: SimpleAdapter = { fetch: getFeesExport(contract_address, [event_trade]), start: 1693267200 } - } + }, + version: 2, } export default adapter; diff --git a/fees/predy-finance/index.ts b/fees/predy-finance/index.ts index b18b9ffec4..58b513214f 100644 --- a/fees/predy-finance/index.ts +++ b/fees/predy-finance/index.ts @@ -1,3 +1,4 @@ +import * as sdk from "@defillama/sdk"; import ADDRESSES from '../../helpers/coreAssets.json' import { Chain } from "@defillama/sdk/build/general"; import BigNumber from "bignumber.js"; @@ -11,17 +12,17 @@ import disabledAdapter from "../../helpers/disabledAdapter"; const v3endpoints = { [CHAIN.ARBITRUM]: - "https://api.thegraph.com/subgraphs/name/predy-dev/predyv3arbitrum", + sdk.graph.modifyEndpoint('4ZDgpHaNhFWKFvUZ9ND4hsWjsz3vR2osCZyrkun3GghM'), }; const v320endpoints = { [CHAIN.ARBITRUM]: - "https://api.thegraph.com/subgraphs/name/predy-dev/predy-v320-arbitrum", + sdk.graph.modifyEndpoint('5icuXT29ipuwqJBF1qux8eA1zskVazyYNq9NzQvoB6eS'), }; const v5endpoints = { [CHAIN.ARBITRUM]: - "https://api.thegraph.com/subgraphs/name/predy-dev/predy-v4-arbitrum", + sdk.graph.modifyEndpoint('GxfTCbMfhaBSJaXHj88Ja1iVG9CXwGWhVQsQ8YA7oLdo'), }; const USDC_DECIMAL = 1e6; @@ -423,6 +424,7 @@ const v3DailyRevenue = async ( }; const adapter: BreakdownAdapter = { + version: 1, breakdown: { v3: { [DISABLED_ADAPTER_KEY]: disabledAdapter, diff --git a/fees/premia/index.ts b/fees/premia/index.ts index 5f6c1b58a5..93589b1a7e 100644 --- a/fees/premia/index.ts +++ b/fees/premia/index.ts @@ -1,3 +1,4 @@ +import * as sdk from "@defillama/sdk"; import { CHAIN } from "../../helpers/chains" import { BreakdownAdapter, ChainEndpoints } from "../../adapters/types" @@ -6,13 +7,13 @@ import getV3Data from "./v3" const v2Endpoints: ChainEndpoints = { [CHAIN.ETHEREUM]: - "https://api.thegraph.com/subgraphs/name/premiafinance/premiav2", + sdk.graph.modifyEndpoint('CqWfkgRsJRrQ5vWq9tkEr68F5nvbAg63ati5SVJQLjK8'), [CHAIN.ARBITRUM]: - "https://api.thegraph.com/subgraphs/name/premiafinance/premia-arbitrum", + sdk.graph.modifyEndpoint('3o6rxHKuXZdy8jFifV99gMUe8FaVUL8w8bDTNdc4zyYg'), [CHAIN.FANTOM]: - "https://api.thegraph.com/subgraphs/name/premiafinance/premia-fantom", + sdk.graph.modifyEndpoint('5ahtXN7DVTwnPuDhWqgJWvEeAEP3JD7h2kD1Kpe67VuW'), [CHAIN.OPTIMISM]: - "https://api.thegraph.com/subgraphs/name/premiafinance/premia-optimism", + sdk.graph.modifyEndpoint('8wMexS8BB1cXWYu2V8cPHURGXSRGDBhshnU9nTiSkXQ7'), } const v2StartTimes: { [chain: string]: number } = { diff --git a/fees/prerich-app.ts b/fees/prerich-app.ts new file mode 100644 index 0000000000..027890d676 --- /dev/null +++ b/fees/prerich-app.ts @@ -0,0 +1,40 @@ +import { FetchOptions, SimpleAdapter } from "../adapters/types"; +import { CHAIN } from "../helpers/chains"; +import { queryDune } from "../helpers/dune"; + +const fethcFeesSolana = async (options: FetchOptions) => { + try { + const dailyFees = options.createBalances(); + const dailyRevenue = options.createBalances(); + const value = (await queryDune("3521814", { + start: options.startTimestamp, + end: options.endTimestamp, + receiver: '2F6oCWmo44sxTzg228GkqKhwuhFTrUNTPCnSFBsyLZeg' + })); + dailyFees.add('So11111111111111111111111111111111111111112', value[0].fee_token_amount); + dailyRevenue.add('So11111111111111111111111111111111111111112', value[0].fee_token_amount); + return { + dailyFees: dailyFees, + dailyRevenue: dailyRevenue, + } + } catch (error: any) { + console.error('Error fetching fees for Solana', error); + return { + dailyFees: "0", + } + } +} + + +const adapter: SimpleAdapter = { + version: 2, + isExpensiveAdapter: true, + adapter: { + [CHAIN.SOLANA]: { + fetch: fethcFeesSolana, + start: 1685577600, + }, + } +} + +export default adapter; diff --git a/fees/primordium.ts b/fees/primordium.ts new file mode 100644 index 0000000000..d716557eaf --- /dev/null +++ b/fees/primordium.ts @@ -0,0 +1,29 @@ +import { FetchOptions, SimpleAdapter } from "../adapters/types"; +import { CHAIN } from "../helpers/chains"; +import { queryDune } from "../helpers/dune"; + +const fetch: any = async (options: FetchOptions) => { + const dailyFees = options.createBalances(); + const value = (await queryDune("3521814", { + start: options.startTimestamp, + end: options.endTimestamp, + receiver: '9yMwSPk9mrXSN7yDHUuZurAh1sjbJsfpUqjZ7SvVtdco' + })); + dailyFees.add('So11111111111111111111111111111111111111112', value[0].fee_token_amount); + + return { dailyFees, dailyRevenue: dailyFees } + +} + +const adapter: SimpleAdapter = { + version: 2, + adapter: { + [CHAIN.SOLANA]: { + fetch: fetch, + start: 0, + }, + }, + isExpensiveAdapter: true +}; + +export default adapter; diff --git a/fees/pumpdotfun.ts b/fees/pumpdotfun.ts new file mode 100644 index 0000000000..ad94bfbf66 --- /dev/null +++ b/fees/pumpdotfun.ts @@ -0,0 +1,28 @@ +import { FetchOptions, SimpleAdapter } from "../adapters/types"; +import { CHAIN } from "../helpers/chains"; +import { queryDune } from "../helpers/dune"; + +const fetch: any = async (options: FetchOptions) => { + const dailyFees = options.createBalances(); + const value = (await queryDune("4006384", { + start: options.startTimestamp, + end: options.endTimestamp, + })); + dailyFees.add('So11111111111111111111111111111111111111112', value[0].fee_token_amount); + + return { dailyFees, dailyRevenue: dailyFees } + +} + +const adapter: SimpleAdapter = { + version: 2, + adapter: { + [CHAIN.SOLANA]: { + fetch: fetch, + start: 0, + }, + }, + isExpensiveAdapter: true +}; + +export default adapter; diff --git a/fees/pumpup.ts b/fees/pumpup.ts new file mode 100644 index 0000000000..319080abd6 --- /dev/null +++ b/fees/pumpup.ts @@ -0,0 +1,22 @@ +import { FetchOptions, SimpleAdapter } from "../adapters/types"; +import { CHAIN } from "../helpers/chains"; +import {queryEvents} from "../helpers/sui" + +const fetchFees = async (options: FetchOptions) => { + const dailyFees = options.createBalances() + const events = await queryEvents({eventType:"0x3f2a0baf78f98087a04431f848008bad050cb5f4427059fa08eeefaa94d56cca::curve::Points", options}) + events.map(ev=>dailyFees.addCGToken("sui", ev.amount/1e9)) + + return { dailyFees, dailyRevenue: dailyFees } + } + +const adapters: SimpleAdapter = { + adapter: { + [CHAIN.SUI]: { + fetch: fetchFees, + start: 1717290061 + }, + }, + version: 2 +} +export default adapters; diff --git a/fees/quickswap.ts b/fees/quickswap.ts index b4b914de1d..ee1dfa3122 100644 --- a/fees/quickswap.ts +++ b/fees/quickswap.ts @@ -1,16 +1,15 @@ +import * as sdk from "@defillama/sdk"; import { Chain } from "@defillama/sdk/build/general"; import { BreakdownAdapter, BaseAdapter } from "../adapters/types"; import { CHAIN } from "../helpers/chains"; -import customBackfill from "../helpers/customBackfill"; - -import { - getGraphDimensions -} from "../helpers/getUniSubgraph" +import { getGraphDimensions2 } from "../helpers/getUniSubgraph"; const v2Endpoints = { - [CHAIN.POLYGON]: "https://api.thegraph.com/subgraphs/name/sameepsi/quickswap06", -} -const v2Graph = getGraphDimensions({ + [CHAIN.POLYGON]: sdk.graph.modifyEndpoint( + "FUWdkXWpi8JyhAnhKL5pZcVshpxuaUQG8JHMDqNCxjPd", + ), +}; +const v2Graph = getGraphDimensions2({ graphUrls: v2Endpoints, feesPercent: { type: "volume", @@ -19,41 +18,35 @@ const v2Graph = getGraphDimensions({ SupplySideRevenue: 0.3, HoldersRevenue: 0, Revenue: 0, - Fees: 0.3 - } + Fees: 0.3, + }, }); const v3Endpoints = { - [CHAIN.POLYGON]: "https://api.thegraph.com/subgraphs/name/sameepsi/quickswap-v3", + [CHAIN.POLYGON]: sdk.graph.modifyEndpoint( + "CCFSaj7uS128wazXMdxdnbGA3YQnND9yBdHjPtvH7Bc7", + ), // [CHAIN.DOGECHAIN]: "https://graph-node.dogechain.dog/subgraphs/name/quickswap/dogechain-info", - [CHAIN.POLYGON_ZKEVM]:"https://api.studio.thegraph.com/query/44554/quickswap-v3-02/0.0.7" -} + [CHAIN.POLYGON_ZKEVM]: + "https://api.studio.thegraph.com/query/44554/quickswap-v3-02/0.0.7", +}; type TStartTime = { [s: string | Chain]: number; -} +}; const startTimeV3: TStartTime = { [CHAIN.POLYGON]: 1662425243, [CHAIN.POLYGON_ZKEVM]: 1679875200, [CHAIN.DOGECHAIN]: 1660694400, -} +}; -const v3Graphs = getGraphDimensions({ +const v3Graphs = getGraphDimensions2({ graphUrls: v3Endpoints, totalVolume: { factory: "factories", field: "totalVolumeUSD", }, - dailyVolume: { - factory: "algebraDayData", - field: "volumeUSD", - dateField: "date" - }, - dailyFees: { - factory: "algebraDayData", - field: "feesUSD", - }, feesPercent: { type: "fees", ProtocolRevenue: 0, @@ -61,8 +54,8 @@ const v3Graphs = getGraphDimensions({ Fees: 0, UserFees: 100, // User fees are 100% of collected fees SupplySideRevenue: 100, // 100% of fees are going to LPs - Revenue: 0 // Revenue is 100% of collected fees - } + Revenue: 0, // Revenue is 100% of collected fees + }, }); const methodology = { @@ -71,17 +64,18 @@ const methodology = { Revenue: "Protocol have no revenue", ProtocolRevenue: "Protocol have no revenue.", SupplySideRevenue: "All user fees are distributed among LPs.", - HoldersRevenue: "Holders have no revenue." -} + HoldersRevenue: "Holders have no revenue.", +}; const adapter: BreakdownAdapter = { + version: 2, breakdown: { v2: { [CHAIN.POLYGON]: { fetch: v2Graph(CHAIN.POLYGON), start: 1602118043, meta: { - methodology + methodology, }, }, }, @@ -90,12 +84,12 @@ const adapter: BreakdownAdapter = { fetch: v3Graphs(chain as Chain), start: startTimeV3[chain], meta: { - methodology - } - } - return acc - }, {} as BaseAdapter) - } -} + methodology, + }, + }; + return acc; + }, {} as BaseAdapter), + }, +}; export default adapter; diff --git a/fees/radiant.ts b/fees/radiant.ts index 3fa4c2506c..e1de3297e3 100644 --- a/fees/radiant.ts +++ b/fees/radiant.ts @@ -1,93 +1,39 @@ -import { Adapter, FetchResultFees } from "../adapters/types"; +import { Adapter, FetchOptions, } from "../adapters/types"; import { CHAIN } from "../helpers/chains"; -import { getTimestampAtStartOfDayUTC, getTimestampAtStartOfNextDayUTC } from "../utils/date"; -import * as sdk from "@defillama/sdk"; -import { getBlock } from "../helpers/getBlock"; import { Chain } from "@defillama/sdk/build/general"; -const topic0NewTransferAdded = '0xc5e1cdb94ac0a9f4f65e1a23fd59354025cffdf472eb03020ac4ba0e92d9969f'; type TAddress = { [l: string | Chain]: string; } -const address: TAddress = { +const address: TAddress = { [CHAIN.ARBITRUM]: '0xE10997B8d5C6e8b660451f61accF4BBA00bc901f', [CHAIN.BSC]: '0xcebdff400A23E5Ad1CDeB11AfdD0087d5E9dFed8', - [CHAIN.ETHEREUM]: '0x28E395a54a64284DBA39652921Cd99924f4e3797' -} - -interface ITx { - data: string; - transactionHash: string; - topics: string[]; -} - -interface IData { - contract_address: string; - amount: number; + [CHAIN.ETHEREUM]: '0x28E395a54a64284DBA39652921Cd99924f4e3797', + [CHAIN.BASE]: '0xC49b4D1e6CbbF4cAEf542f297449696d8B47E411' } +const fetch = async ({ chain, createBalances, getLogs }: FetchOptions) => { + const dailyFees = createBalances() + const logs = await getLogs({ target: address[chain], eventAbi: 'event NewTransferAdded (address indexed asset, uint256 lpUsdValue)' }) + logs.forEach((log) => dailyFees.addUSDValue(Number(log.lpUsdValue) / 1e18)) + const dailySupplySideRevenue = dailyFees.clone(0.25); + const dailyHoldersRevenue = dailyFees.clone(0.60); + const dailyProtocolRevenue = dailyFees.clone(0.15); + const dailyRevenue = dailyFees.clone(0.85); -const fetch = (chain: Chain) => { - return async (timestamp: number): Promise => { - const todaysTimestamp = getTimestampAtStartOfDayUTC(timestamp) - const yesterdaysTimestamp = getTimestampAtStartOfNextDayUTC(timestamp) - - const fromBlock = (await getBlock(todaysTimestamp, chain, {})); - const toBlock = (await getBlock(yesterdaysTimestamp, chain, {})); - const logs: ITx[] = (await sdk.getEventLogs({ - target: address[chain], - fromBlock: fromBlock, - toBlock: toBlock, - topics: [topic0NewTransferAdded], - chain: chain - })).map((e: any) => { return { data: e.data.replace('0x', ''), transactionHash: e.transactionHash, topics: e.topics } as ITx}); - const raw_data_logs: IData[] = logs.map((tx: ITx) => { - const amount = Number('0x'+tx.data); - const address = tx.topics[1]; - const contract_address = '0x' + address.slice(26, address.length); - return { - amount, - contract_address, - tx: tx.transactionHash - }; - }) - const feesAmuntsUSD: any[] = raw_data_logs.map((d: any) => { - return {amount: d.amount / 10 ** 18, tx: d.tx, a: d.contract_address} // debug - }); - const dailyFee = feesAmuntsUSD.reduce((a: number, b: any) => a+b.amount, 0); - const supplySideRev = dailyFee * 0.25; - const dailyHoldersRevenue = dailyFee * .60; - const protocolRev = dailyFee * .15; - - return { - dailyFees: dailyFee.toString(), - dailySupplySideRevenue: supplySideRev.toString(), - dailyHoldersRevenue: dailyHoldersRevenue.toString(), - dailyProtocolRevenue: protocolRev.toString(), - dailyRevenue: (protocolRev + dailyHoldersRevenue).toString(), - timestamp - } - } + return { dailyRevenue, dailyHoldersRevenue, dailyProtocolRevenue, dailySupplySideRevenue, dailyFees, }; } const adapter: Adapter = { + version: 2, adapter: { - [CHAIN.ARBITRUM]: { - fetch: fetch(CHAIN.ARBITRUM), - start: 1679097600, - }, - [CHAIN.BSC]: { - fetch: fetch(CHAIN.BSC), - start: 1679788800, - }, - [CHAIN.ETHEREUM]: { - fetch: fetch(CHAIN.ETHEREUM), - start: 1698796800, - }, + [CHAIN.ARBITRUM]: { fetch, start: 1679097600, }, + [CHAIN.BSC]: { fetch, start: 1679788800, }, + [CHAIN.ETHEREUM]: { fetch, start: 1698796800, }, + [CHAIN.BASE]: { fetch, start: 1719592253, }, } } - export default adapter; diff --git a/fees/radioshack.ts b/fees/radioshack.ts index 2682730d36..226d65f917 100644 --- a/fees/radioshack.ts +++ b/fees/radioshack.ts @@ -12,6 +12,7 @@ const feeAdapter: BaseAdapter = getDexChainFees({ }); const adapter: Adapter = { + version: 2, adapter: feeAdapter }; diff --git a/fees/radpie.ts b/fees/radpie.ts new file mode 100644 index 0000000000..1d80a5c457 --- /dev/null +++ b/fees/radpie.ts @@ -0,0 +1,84 @@ +import { FetchOptions, SimpleAdapter } from "../adapters/types"; +import { CHAIN } from "../helpers/chains"; +import { Chain } from "@defillama/sdk/build/general"; + +const event_paid_stream = 'event RewardPaid (address indexed _user, address indexed _receiver, uint256 _reward, address indexed _token)'; +const event_paid_rdnt= 'event RDNTEntitled (address indexed _receipt, uint256 _amount)'; + +type TAddress = { + [c: string]: string; +} +const address_reward: TAddress = { + + [CHAIN.BSC]: '0xe05157aA8D14b8ED1d816D505b3D5DEEB83ca131', + [CHAIN.ARBITRUM]: '0x18a192dFe0BE1E5E9AA424738FdAd800646283b2', + [CHAIN.ETHEREUM]: '0x7e6E8aeCCb0508FeD6547C9F3731E8f75C5C2932' +} +const address_rdnt_reward: TAddress = { +[CHAIN.BSC]: '0x91DD506e1f27f50dd40d0E8634013b1F2393DCa0', +[CHAIN.ARBITRUM]: '0xD97EbDd4a104e8336760C6350930a96A9A659A66', +[CHAIN.ETHEREUM]: '0x086295a932d0f91da4e878ec33d4355d196bbc44' + +} +const address_rdnt: TAddress = { + + [CHAIN.BSC]: '0xf7de7e8a6bd59ed41a4b5fe50278b3b7f31384df', + [CHAIN.ARBITRUM]: '0x3082CC23568eA640225c2467653dB90e9250AaA0', + [CHAIN.ETHEREUM]: '0x137dDB47Ee24EaA998a535Ab00378d6BFa84F893' + + } + +const graph = (chain: Chain) => { + return async ({ createBalances, getLogs, api }: FetchOptions) => { + const dailyFees = createBalances(); + let poolLength = await api.call({ abi: 'uint256:poolLength', target:address_reward[chain], }); + // console.log(poolLength); + let array = Array.from({ length: poolLength }, (_, index) => index); + const pools=await api.multiCall({ abi: 'function poolTokenList(uint256) view returns(address)', calls:array , target:address_reward[chain] }) // (await getLogs({ + // console.log(pools) + const rewardContracts = await api.multiCall({ abi: 'function pools(address) view returns ( address asset, address rToken, address vdToken, address rewarder, address receiptToken , uint256 maxCap, uint256 lastActionHandled, bool isNative, bool isActive)', calls:pools , target:address_reward[chain] }) // (await getLogs({ + // console.log(rewardContracts[0].rewarder) + for (const i of rewardContracts) { + const logs = await getLogs({ + target: i.rewarder, + eventAbi: event_paid_stream, + }); + // console.log(logs) + logs.forEach((e: any) => { + // console.log(e._token,e._reward) + dailyFees.add(e._token, e._reward); + }); + } + + (await getLogs({ + target: address_rdnt_reward[chain], + eventAbi: event_paid_rdnt, + })).map((e: any) => { + // console.log(e) + dailyFees.add(address_rdnt[chain], e._amount) + }) + return { dailyFees, dailyRevenue: dailyFees,dailyUserFees:dailyFees }; + } +} + + +const adapter: SimpleAdapter = { + version: 2, + adapter: { + + [CHAIN.BSC]: { + fetch: graph(CHAIN.BSC), + start: 77678653, + }, + [CHAIN.ARBITRUM]: { + fetch: graph(CHAIN.ARBITRUM), + start: 77678653, + }, + [CHAIN.ETHEREUM]: { + fetch: graph(CHAIN.ETHEREUM), + start: 77678653, + }, + } +}; + +export default adapter; diff --git a/fees/railgun.ts b/fees/railgun.ts index 1fb691d77b..9b788aad95 100644 --- a/fees/railgun.ts +++ b/fees/railgun.ts @@ -38,8 +38,7 @@ const fetchFees: FetchV2 = async ({ createBalances, getLogs, chain, }) => { return { dailyFees: dailyFees, - dailyRevenue: dailyFees, - dailyBribesRevenue: dailyFees, + dailyRevenue: dailyFees } } diff --git a/fees/rainbow-wallet.ts b/fees/rainbow-wallet.ts index 4430b1a86b..de93dff4d3 100644 --- a/fees/rainbow-wallet.ts +++ b/fees/rainbow-wallet.ts @@ -42,7 +42,9 @@ const adapter: Adapter = { [CHAIN.OPTIMISM]: chainAdapter, [CHAIN.ARBITRUM]: chainAdapter, [CHAIN.POLYGON]: chainAdapter, + [CHAIN.BASE]: chainAdapter, [CHAIN.BSC]: chainAdapter, + [CHAIN.AVAX]: chainAdapter, }, } diff --git a/fees/ramses-exchange-v1/bribes.ts b/fees/ramses-exchange-v1/bribes.ts new file mode 100644 index 0000000000..7df14464db --- /dev/null +++ b/fees/ramses-exchange-v1/bribes.ts @@ -0,0 +1,36 @@ +import * as sdk from "@defillama/sdk"; +import request from "graphql-request"; +import { Balances } from "@defillama/sdk"; + +interface IBribes { + amount: number; + token: { + id: string; + decimals: number; + }; +} + +export const fees_bribes = async (fromBlock: number, timestamp: number, balances: Balances) => { + const endpoint = sdk.graph.modifyEndpoint('G2tXDm6mgqBMuC7hq9GRVeTv5SRBAVnPFGcpGBab2cea'); + const graphQuery = ` + query GetBribes($fromBlock: Int!) { + bribes( + where: { timestamp_gte: ${timestamp} } + ) { + amount + token { + id + decimals + } + } + } + `; + + const graphRes: { bribes: IBribes[] } = await request(endpoint, graphQuery, { fromBlock, }); + + const logs_bribes = graphRes.bribes; + + logs_bribes.map((e: IBribes) => { + balances.add(e.token.id, e.amount * Math.pow(10, e.token.decimals)); + }) +}; diff --git a/fees/ramses-exchange-v1/index.ts b/fees/ramses-exchange-v1/index.ts new file mode 100644 index 0000000000..b477ed47e9 --- /dev/null +++ b/fees/ramses-exchange-v1/index.ts @@ -0,0 +1,64 @@ +import { Adapter, FetchOptions } from "../../adapters/types"; +import { CHAIN } from "../../helpers/chains"; +import { uniV2Exports } from "../../helpers/uniswap"; +import { fees_bribes } from './bribes'; + + +const FACTORY_ADDRESS = '0xaaa20d08e59f6561f242b08513d36266c5a29415'; + +type TStartTime = { + [key: string]: number; +} +const startTimeV2: TStartTime = { + [CHAIN.ARBITRUM]: 1678838400, +} + +const getBribes = async ({ fromTimestamp, toTimestamp, createBalances, getFromBlock, }: FetchOptions): Promise => { + const fromBlock = await getFromBlock() + const bribes = createBalances(); + const bribes_delta = createBalances(); + await fees_bribes(fromBlock, toTimestamp, bribes_delta); + await fees_bribes(fromBlock, fromTimestamp, bribes); + bribes.subtract(bribes_delta); + return { + timestamp: toTimestamp, + dailyBribesRevenue: bribes, + }; +}; + +const methodology = { + UserFees: "User pays 0.3% fees on each swap.", + ProtocolRevenue: "Revenue going to the protocol. 5% of collected fees. (is probably right because the distribution is dynamic.)", + HoldersRevenue: "User fees are distributed among holders. 75% of collected fees. (is probably right because the distribution is dynamic.)", + SupplySideRevenue: "20% of collected fees are distributed among LPs. (is probably right because the distribution is dynamic.)" +} + + +const feeAdapter = uniV2Exports({ + [CHAIN.ARBITRUM]: { factory: FACTORY_ADDRESS, }, +}).adapter[CHAIN.ARBITRUM].fetch + + +const adapter: Adapter = { + version: 2, + adapter: { + [CHAIN.ARBITRUM]: { + fetch: async (options: FetchOptions) => { + const v1Results = await feeAdapter(options as any, {}, options) + const bribesResult = await getBribes(options); + v1Results.dailyBribesRevenue = bribesResult.dailyBribesRevenue; + + return v1Results; + }, + start: startTimeV2[CHAIN.ARBITRUM], + meta: { + methodology: { + ...methodology, + UserFees: "User pays 0.05%, 0.30%, or 1% on each swap.", + }, + }, + }, + }, +}; + +export default adapter; diff --git a/fees/ramses-exchange-v2/bribes.ts b/fees/ramses-exchange-v2/bribes.ts index 29e01279c5..7df14464db 100644 --- a/fees/ramses-exchange-v2/bribes.ts +++ b/fees/ramses-exchange-v2/bribes.ts @@ -1,3 +1,4 @@ +import * as sdk from "@defillama/sdk"; import request from "graphql-request"; import { Balances } from "@defillama/sdk"; @@ -10,7 +11,7 @@ interface IBribes { } export const fees_bribes = async (fromBlock: number, timestamp: number, balances: Balances) => { - const endpoint = 'https://api.thegraph.com/subgraphs/name/ramsesexchange/concentrated-liquidity-graph'; + const endpoint = sdk.graph.modifyEndpoint('G2tXDm6mgqBMuC7hq9GRVeTv5SRBAVnPFGcpGBab2cea'); const graphQuery = ` query GetBribes($fromBlock: Int!) { bribes( diff --git a/fees/ramses-exchange-v2/index.ts b/fees/ramses-exchange-v2/index.ts index 361876e250..d4d300ff43 100644 --- a/fees/ramses-exchange-v2/index.ts +++ b/fees/ramses-exchange-v2/index.ts @@ -1,10 +1,10 @@ +import * as sdk from "@defillama/sdk"; import { Adapter, FetchOptions } from "../../adapters/types"; import { ARBITRUM, CHAIN } from "../../helpers/chains"; import { fees_bribes } from './bribes'; import { - getGraphDimensions, - DEFAULT_DAILY_VOLUME_FACTORY, DEFAULT_TOTAL_VOLUME_FIELD, + getGraphDimensions2, } from "../../helpers/getUniSubgraph" type TStartTime = { @@ -28,25 +28,19 @@ const getBribes = async ({ fromTimestamp, toTimestamp, createBalances, getFromBl }; const v2Endpoints = { - [CHAIN.ARBITRUM]: "https://api.thegraph.com/subgraphs/name/ramsesexchange/concentrated-liquidity-graph", + [CHAIN.ARBITRUM]: sdk.graph.modifyEndpoint('G2tXDm6mgqBMuC7hq9GRVeTv5SRBAVnPFGcpGBab2cea'), }; -const VOLUME_USD = "volumeUSD"; - -const v2Graphs = getGraphDimensions({ +const v2Graphs = getGraphDimensions2({ graphUrls: v2Endpoints, totalVolume: { factory: "factories", field: DEFAULT_TOTAL_VOLUME_FIELD, }, - dailyVolume: { - factory: DEFAULT_DAILY_VOLUME_FACTORY, - field: VOLUME_USD, - }, feesPercent: { type: "fees", - HoldersRevenue: 75, - ProtocolRevenue: 5, + HoldersRevenue: 72, + ProtocolRevenue: 8, SupplySideRevenue: 20, UserFees: 100, // User fees are 100% of collected fees Revenue: 80 // Revenue is 100% of collected fees @@ -61,10 +55,11 @@ const methodology = { } const adapter: Adapter = { + version: 2, adapter: { [CHAIN.ARBITRUM]: { - fetch: async (timestamp: number, chainBlocks: any, options: FetchOptions) => { - const v2Result = await v2Graphs(ARBITRUM)(timestamp, chainBlocks); // Pass chainBlocks as the second argument + fetch: async (options: FetchOptions) => { + const v2Result = await v2Graphs(ARBITRUM)(options) const bribesResult = await getBribes(options); v2Result.dailyBribesRevenue = bribesResult.dailyBribesRevenue; diff --git a/fees/ramses-exchange.ts b/fees/ramses-exchange.ts deleted file mode 100644 index 449455c6c0..0000000000 --- a/fees/ramses-exchange.ts +++ /dev/null @@ -1,16 +0,0 @@ -import { SimpleAdapter } from "../adapters/types"; -import { CHAIN } from "../helpers/chains"; -import { getDexFeesExports } from "../helpers/dexVolumeLogs"; - -const FACTORY_ADDRESS = '0xaaa20d08e59f6561f242b08513d36266c5a29415'; - -const adapter: SimpleAdapter = { - adapter: { - [CHAIN.ARBITRUM]: { - fetch: getDexFeesExports({ chain: CHAIN.ARBITRUM, factory: FACTORY_ADDRESS,}), - start: 1678838400, - }, - } -}; - -export default adapter; \ No newline at end of file diff --git a/fees/raybot.ts b/fees/raybot.ts new file mode 100644 index 0000000000..527639d2b8 --- /dev/null +++ b/fees/raybot.ts @@ -0,0 +1,29 @@ +import { FetchOptions, SimpleAdapter } from "../adapters/types"; +import { CHAIN } from "../helpers/chains"; +import { queryDune } from "../helpers/dune"; + +const fetch: any = async (options: FetchOptions) => { + const dailyFees = options.createBalances(); + const value = (await queryDune("3521814", { + start: options.startTimestamp, + end: options.endTimestamp, + receiver: '4mih95RmBqfHYvEfqq6uGGLp1Fr3gVS3VNSEa3JVRfQK' + })); + dailyFees.add('So11111111111111111111111111111111111111112', value[0].fee_token_amount); + + return { dailyFees, dailyRevenue: dailyFees } + +} + +const adapter: SimpleAdapter = { + version: 2, + adapter: { + [CHAIN.SOLANA]: { + fetch: fetch, + start: 0, + }, + }, + isExpensiveAdapter: true +}; + +export default adapter; diff --git a/fees/raydium.ts b/fees/raydium.ts index f5528a4d48..0599069909 100644 --- a/fees/raydium.ts +++ b/fees/raydium.ts @@ -1,6 +1,6 @@ import { BaseAdapter, Adapter } from "../adapters/types"; import volumeAdapter from "../dexs/raydium"; -import { getDexChainFees } from "../helpers/getUniSubgraphFees"; +import { getDexChainFees } from "../helpers/getRaydiumFees"; const TOTAL_FEES = 0.0025; const PROTOCOL_FEES = 0; @@ -15,17 +15,25 @@ const feeAdapter: BaseAdapter = getDexChainFees({ volumeAdapter, meta: { methodology: { - UserFees: "User pays 0.25% fees on each swap", - Fees: "A 0.25% of each swap is collected as trading fees", - SupplySideRevenue: "A 0.22% of the trades goes back to the LP pool as fees earned", - HoldersRevenue: "A 0.03% of the trade goes to buying RAY and distributing it to stakers", - ProtocolRevenue: "Raydium's AMM earns from the spread it places on the order book and all earnings from market making go back to Raydium liquidity providers", - Revenue: "A 0.03% of the trade goes to buying RAY and distributing it to stakers", + // UserFees: "User pays 0.25% fees on each swap", + // Fees: "A 0.25% of each swap is collected as trading fees", + // SupplySideRevenue: "A 0.22% of the trades goes back to the LP pool as fees earned", + // HoldersRevenue: "A 0.03% of the trade goes to buying RAY and distributing it to stakers", + // ProtocolRevenue: "Raydium's AMM earns from the spread it places on the order book and all earnings from market making go back to Raydium liquidity providers", + // Revenue: "A 0.03% of the trade goes to buying RAY and distributing it to stakers", + + UserFees: "User paid fees for swaps", + Fees: "Fees collected from swaps", + SupplySideRevenue: "Total fees to liquidity providers", + HoldersRevenue: "RAY Buybacks", + ProtocolRevenue: "Revenue earned from buybacks and DAO treasury", + Revenue: "A portion of all trading fees goes to buying back RAY", } } }); const adapter: Adapter = { + version: 2, adapter: feeAdapter }; diff --git a/fees/ref-finance/index.ts b/fees/ref-finance/index.ts new file mode 100644 index 0000000000..4b49938874 --- /dev/null +++ b/fees/ref-finance/index.ts @@ -0,0 +1,21 @@ +import { SimpleAdapter } from "../../adapters/types"; +import { httpGet } from "../../utils/fetchURL"; +const api_fee = "https://api.ref.finance/get-total-fee" +const api_revenue = "https://api.ref.finance/get-total-revenue" +const adapter: SimpleAdapter = { + adapter: { + "near": { + start: 1725897600, + fetch: async () => { + const fee_result = await httpGet(api_fee); + const revenue_result = await httpGet(api_revenue); + return { + dailyFees: fee_result?.data?.total_fee || '0', + dailyRevenue: revenue_result?.data.total_revenue || '0', + } + } + } + } +}; + +export default adapter; diff --git a/fees/reserve/index.ts b/fees/reserve/index.ts index e30ef31d74..c9a0d66494 100644 --- a/fees/reserve/index.ts +++ b/fees/reserve/index.ts @@ -1,4 +1,5 @@ -import { Adapter } from "../../adapters/types"; +import * as sdk from "@defillama/sdk"; +import { Adapter, FetchOptions } from "../../adapters/types"; import { CHAIN } from "../../helpers/chains"; import request from "graphql-request"; @@ -11,7 +12,7 @@ const rtokenCreationAbi = "event RTokenCreated(address indexed main, address indexed rToken, address stRSR, address indexed owner, string version)"; const endpoints = { - [CHAIN.ETHEREUM]: "https://api.thegraph.com/subgraphs/name/lcamargof/reserve", + [CHAIN.ETHEREUM]: sdk.graph.modifyEndpoint('BT7YCEWL7JHbEBD9WXWmtMSzCuW6YXisWTqHPVb4u6uC'), }; const graphQuery = ` @@ -33,7 +34,7 @@ const graphQuery = ` } `; -const fetch: any = async (timestamp: number, _, { getLogs, createBalances }) => { +const fetch: any = async ({ getLogs, createBalances, toTimestamp }: FetchOptions) => { const RSR = '0x320623b8e4ff03373931769a31fc52a4e78b5d70' // Get list of deployed RTokens @@ -43,7 +44,7 @@ const fetch: any = async (timestamp: number, _, { getLogs, createBalances }) => const rtokens = rtokenCreationLogs.map((i) => i.rToken.toLowerCase()); const graphRes = ( - await request(endpoints[CHAIN.ETHEREUM], graphQuery, { currentTime: timestamp, rtokens, }) + await request(endpoints[CHAIN.ETHEREUM], graphQuery, { currentTime: toTimestamp, rtokens, }) ).rtokens; const dailyFees = createBalances(); @@ -57,10 +58,11 @@ const fetch: any = async (timestamp: number, _, { getLogs, createBalances }) => dailyFees.add(RSR, snapshots[0].rsrStaked * (todayRate - yesterdayRate)); }); - return { timestamp, dailyFees, dailyRevenue: dailyFees, }; + return { dailyFees, dailyRevenue: dailyFees, }; }; const adapter: Adapter = { + version: 2, adapter: { [CHAIN.ETHEREUM]: { fetch, diff --git a/fees/ribbon/index.ts b/fees/ribbon/index.ts new file mode 100644 index 0000000000..1fffc12f14 --- /dev/null +++ b/fees/ribbon/index.ts @@ -0,0 +1,95 @@ +import * as sdk from "@defillama/sdk"; +import request, { gql } from "graphql-request"; +import { Adapter, FetchOptions, FetchResultV2 } from "../../adapters/types"; +import { CHAIN } from "../../helpers/chains"; + +interface IVault { + id: string; + totalFeeCollected: number; + totalNominalVolume: number; + underlyingAsset: string; +} + +interface IVaultsResponse { + vaults: IVault[]; +} + +const ethereum_endpointId: string = + "3GhHcRwF6yH7WXGcJJvac9B5MHPuoXhS9uxc49TPqLf6"; +const avax_endpointId: string = "AmJzFkqot9NjxPCRLK8yXopYt3rtS736ZEX2zEFg7Tz2"; + +const query = gql` + query getVaults($block: Int!) { + vaults(block: { number: $block }) { + id + totalFeeCollected + totalNominalVolume + underlyingAsset + } + } +`; + +const fetch = async ( + endpointId: string, + { getStartBlock, getEndBlock, createBalances }: FetchOptions +): Promise => { + const dailyFees = createBalances(); + const totalFees = createBalances(); + const dailyVolume = createBalances(); + const totalVolume = createBalances(); + + const [prevDayBlock, toDayBlock] = await Promise.all([ + getStartBlock(), + getEndBlock(), + ]); + + const endpoint = sdk.graph.modifyEndpoint(endpointId); + + const [{ vaults: fromVaults }, { vaults: toVaults }] = await Promise.all([ + request(endpoint, query, { block: prevDayBlock - 50 }), + request(endpoint, query, { block: toDayBlock - 50 }), + ]); + + toVaults.forEach((toVault) => { + const fromVault = fromVaults.find((vault) => vault.id === toVault.id); + + const token = toVault.underlyingAsset; + const prevFee = fromVault ? fromVault.totalFeeCollected : 0; + const currFee = toVault.totalFeeCollected; + + const prevVolume = fromVault ? fromVault.totalNominalVolume : 0; + const currVolume = toVault.totalNominalVolume; + + if (token) { + totalFees.add(token, currFee); + const dailyFee = currFee - prevFee; + if (dailyFee >= 0) { + dailyFees.add(token, dailyFee); + } + + totalVolume.add(token, currVolume); + const dailyVolumee = currVolume - prevVolume; + if (dailyVolumee >= 0) { + dailyVolume.add(token, dailyVolumee); + } + } + }); + + return { dailyFees, dailyVolume, totalFees, totalVolume }; +}; + +const adapter: Adapter = { + version: 2, + adapter: { + [CHAIN.ETHEREUM]: { + fetch: (options: FetchOptions) => fetch(ethereum_endpointId, options), + start: 1617228000, + }, + [CHAIN.AVAX]: { + fetch: (options: FetchOptions) => fetch(avax_endpointId, options), + start: 1617228000, + }, + }, +}; + +export default adapter; diff --git a/fees/rollup-finace.ts b/fees/rollup-finace.ts index 99799a978e..15f2d97f7b 100644 --- a/fees/rollup-finace.ts +++ b/fees/rollup-finace.ts @@ -65,7 +65,11 @@ const graphs = (graphUrls: ChainEndpoints) => { const adapter: Adapter = { adapter: { [CHAIN.ERA]: { - fetch: graphs(endpoints)(CHAIN.ERA), + // sunset 24 Sept 2024 + fetch: async () => ({ + dailyFees: 0, + dailyUserFees: 0 + }), start: 1682035200, }, } diff --git a/fees/scallop/index.ts b/fees/scallop/index.ts new file mode 100644 index 0000000000..69ffb3b17a --- /dev/null +++ b/fees/scallop/index.ts @@ -0,0 +1,68 @@ +import { + Adapter, + FetchResultFees, + FetchResultV2, + FetchV2, +} from "../../adapters/types"; +import { CHAIN } from "../../helpers/chains"; +import fetchURL from "../../utils/fetchURL"; + +const scallopApiURL = 'https://sui.apis.scallop.io/statistic/daily-fees'; + +interface DailyStats { + borrowingInterestFee: number, + liquidationFee: number, + borrowingFee: number, + flashloanFee: number, + liquidityProviderInterest: number, + dateHistory: string; +} + +const methodology = { + Fees: 'Interest and fees paid by borrowers and the liquidated', + UserFees: 'Interest and fees paid by borrowers and the liquidated', + ProtocolRevenue: 'The portion of the total fees going to the Scallop treasury', + SupplySideRevenue: '80% of all collected borrowing interest fees go to liquidity providers.' +} + +const fetchScallopStats: FetchV2 = async ({ startTimestamp, endTimestamp }): Promise => { + const url = `${scallopApiURL}?fromTimestamp=${startTimestamp}&toTimestamp=${endTimestamp}` + const stats: DailyStats = await fetchURL(url); + + const dailyFees = stats.borrowingInterestFee + + stats.liquidationFee + + stats.borrowingFee + + stats.flashloanFee + + stats.liquidityProviderInterest; + + const dailyRevenue = stats.liquidationFee + + stats.borrowingFee + + stats.flashloanFee + + stats.borrowingInterestFee; + + return { + dailyFees: dailyFees.toString(), + dailyUserFees: dailyFees.toString(), + dailyRevenue: dailyRevenue.toString(), + dailyProtocolRevenue: dailyRevenue.toString(), + dailySupplySideRevenue: stats.liquidityProviderInterest.toString(), + }; +}; + + +const adapter: Adapter = { + version: 2, + adapter: { + [CHAIN.SUI]: { + runAtCurrTime: false, + customBackfill: undefined, + fetch: fetchScallopStats, + start: 1703980799, + meta: { + methodology, + }, + }, + }, +}; + +export default adapter; diff --git a/fees/scoop.ts b/fees/scoop.ts new file mode 100644 index 0000000000..dfcaf4a16b --- /dev/null +++ b/fees/scoop.ts @@ -0,0 +1,27 @@ +import { Adapter, FetchOptions, } from '../adapters/types'; +import { CHAIN } from '../helpers/chains'; + +const address = '0x864d6cAfFEa0725057E6ED775b34E6Dd6F04AD49'; +const fetchFees = async (options: FetchOptions) => { + const dailyFees = options.createBalances(); + await options.api.sumTokens({ owners: [address], tokens: ["0x0000000000000000000000000000000000000000"] }) + await options.fromApi.sumTokens({ owners: [address], tokens: ["0x0000000000000000000000000000000000000000"] }) + dailyFees.addBalances(options.api.getBalancesV2()) + dailyFees.subtract(options.fromApi.getBalancesV2()) + return { + dailyFees, + dailyRevenue: dailyFees.clone(), + } +} + +const adapter: Adapter = { + version: 2, + adapter: { + [CHAIN.BASE]: { + fetch: fetchFees, + start: 1656633600, // + } + } +} + +export default adapter; diff --git a/fees/sharesgram.ts b/fees/sharesgram.ts index 274d9c5c2e..b2cc7a4ca4 100644 --- a/fees/sharesgram.ts +++ b/fees/sharesgram.ts @@ -9,6 +9,7 @@ const adapter: Adapter = { fetch: getFeesExport('0xbe74a95d159e8e323b8c1a70f825efc85fed27c4'), start: 1693180800 } - } + }, + version: 2, } export default adapter; diff --git a/fees/sharpe-earn/index.ts b/fees/sharpe-earn/index.ts new file mode 100644 index 0000000000..8f6bc4a7c4 --- /dev/null +++ b/fees/sharpe-earn/index.ts @@ -0,0 +1,54 @@ +import { SimpleAdapter, FetchOptions, ChainBlocks } from "../../adapters/types"; +import { CHAIN } from "../../helpers/chains"; +import { addTokensReceived } from "../../helpers/token"; + +const supportedERC20Tokens: Record = { + [CHAIN.ARBITRUM]: [ + "0x5979D7b546E38E414F7E9822514be443A4800529", + "0xEC70Dcb4A1EFa46b8F2D97C310C9c4790ba5ffA8", + "0x82aF49447D8a07e3bd95BD0d56f35241523fBab1", + ], + [CHAIN.OPTIMISM]: [ + "0x1F32b1c2345538c0c6f582fCB022739c4A194Ebb", + "0x9Bcef72be871e61ED4fBbc7630889beE758eb81D", + "0x4200000000000000000000000000000000000006", + ], + [CHAIN.BASE]: [ + "0x4200000000000000000000000000000000000006", + "0xc1cba3fcea344f92d9239c08c0568f6f2f0ee452", + "0x2ae3f1ec7f1f5012cfeab0185bfc7aa3cf0dec22", + ], +}; + +const fetch = async (options: FetchOptions) => { + const tokenlist = supportedERC20Tokens[options.chain as CHAIN]; + const fee = await addTokensReceived({ + tokens: tokenlist, + options, + target: "0x10cc9d85441f27a500776357758961031218e3ae", + }); + + return { + dailyFees: fee, + }; +}; + +const adapter: SimpleAdapter = { + version: 2, + adapter: { + [CHAIN.ARBITRUM]: { + fetch: fetch, + start: async () => 1710037587, + }, + [CHAIN.OPTIMISM]: { + fetch: fetch, + start: async () => 1710037587, + }, + [CHAIN.BASE]: { + fetch: fetch, + start: async () => 1710037587, + }, + }, +}; + +export default adapter; diff --git a/fees/shibaswap.ts b/fees/shibaswap.ts index 7b88b3a1c9..8db120bc9f 100644 --- a/fees/shibaswap.ts +++ b/fees/shibaswap.ts @@ -10,6 +10,7 @@ const feeAdapter = getDexChainFees({ }); const adapter: Adapter = { + version: 2, adapter: feeAdapter }; diff --git a/fees/shoebillFinance-v2/index.ts b/fees/shoebillFinance-v2/index.ts index a67d31ac05..5effddcd1f 100644 --- a/fees/shoebillFinance-v2/index.ts +++ b/fees/shoebillFinance-v2/index.ts @@ -12,17 +12,18 @@ const unitrollers = { ] } -const fetch: any = async (timestamp: number, chainBlocks: ChainBlocks, options: FetchOptions): Promise => { +const fetch: any = async (options: FetchOptions) => { const { chain, createBalances, } = options const dailyFees = createBalances(); const dailyRevenue = createBalances(); for (const market of unitrollers[chain]) { await getFees(market, options, { dailyFees, dailyRevenue, abis: { reserveFactor: "uint256:reserveFactorMantissa", } }); } - return { timestamp, dailyFees, dailyRevenue, dailyHoldersRevenue: dailyRevenue, }; + return { dailyFees, dailyRevenue, dailyHoldersRevenue: dailyRevenue, }; }; const adapter: Adapter = { + version: 2, adapter: { [CHAIN.MANTA]: { fetch, diff --git a/fees/sideshift.ts b/fees/sideshift.ts new file mode 100644 index 0000000000..47238f1e56 --- /dev/null +++ b/fees/sideshift.ts @@ -0,0 +1,32 @@ +import { FetchOptions, SimpleAdapter } from "../adapters/types"; +import { CHAIN } from "../helpers/chains"; + +const token = '0x35e78b3982E87ecfD5b3f3265B601c046cDBe232' +const fetchFees = async (options: FetchOptions) => { + const dailyFees = options.createBalances(); + const logs = await options.getLogs({ + target: token, + topics: [ + '0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef', + '0x000000000000000000000000cdd37ada79f589c15bd4f8fd2083dc88e34a2af2', + '0x0000000000000000000000003808708e761b988d23ae011ed0e12674fb66bd62' + ] + }) + logs.forEach(log => { + dailyFees.add(token, Number(log.data)) + }) + const holderRevenue = dailyFees.clone() + dailyFees.resizeBy(4) + + return { dailyFees, dailyRevenue: dailyFees, dailyHoldersRevenue: holderRevenue } +} +const adapters: SimpleAdapter = { + version: 2, + adapter: { + [CHAIN.ETHEREUM]: { + fetch: fetchFees, + start: 0, + } + } +} +export default adapters diff --git a/fees/silo-finance/index.ts b/fees/silo-finance/index.ts new file mode 100644 index 0000000000..6e8aed81ed --- /dev/null +++ b/fees/silo-finance/index.ts @@ -0,0 +1,230 @@ +import { Chain } from "@defillama/sdk/build/general"; +import { Adapter, FetchOptions, FetchResultV2 } from "../../adapters/types"; +import { CHAIN } from "../../helpers/chains"; + +type FeeResult = { + asset: string; + fee: bigint; +}; + +type IFactory = { + address: string; + block: number; +}; + +type ISilo = { + lens: string; + factory: IFactory | IFactory[]; + silos?: { silo: string; assets: string[] }[]; +}; + +type IAddress = { + [s: string | Chain]: ISilo[]; +}; + +const silo: IAddress = { + [CHAIN.ETHEREUM]: [ + { + lens: "0x0e466FC22386997daC23D1f89A43ecb2CB1e76E9", + factory: [ + { + address: "0x4D919CEcfD4793c0D47866C8d0a02a0950737589", + block: 15307294, + }, + { + address: "0x6d4A256695586F61b77B09bc3D28333A91114d5a", + block: 17391885, + }, + ], + }, + { + lens: "0x32a4Bcd8DEa5E18a12a50584682f8E4B77fFF2DF", + factory: { + address: "0x2c0fA05281730EFd3ef71172d8992500B36b56eA", + block: 17782576, + }, + }, + ], + [CHAIN.ARBITRUM]: [ + { + lens: "0xBDb843c7a7e48Dc543424474d7Aa63b61B5D9536", + factory: { + address: "0x4166487056A922D784b073d4d928a516B074b719", + block: 51894508, + }, + }, + ], + [CHAIN.OPTIMISM]: [ + { + lens: "0xd3De080436b9d38DC315944c16d89C050C414Fed", + factory: { + address: "0x6B14c4450a29Dd9562c20259eBFF67a577b540b9", + block: 120480601, + }, + }, + ], + [CHAIN.BASE]: [ + { + lens: "0x196D312fd81412B6443620Ca81B41103b4E123FD", + factory: { + address: "0x408822E4E8682413666809b0655161093cd36f2b", + block: 16262586, + }, + }, + ], +}; + +async function getSilos( + silos: ISilo[], + { getLogs }: FetchOptions +): Promise { + const logs: any = []; + + const fetchLogsFromFactory = async (address: string, block: number) => { + const logChunk = await getLogs({ + target: address, + fromBlock: block, + eventAbi: + "event NewSiloCreated(address indexed silo, address indexed asset, uint128 version)", + }); + + logs.push(logChunk.map((result) => result[0])); + }; + + for (const { factory } of silos) { + if (Array.isArray(factory)) { + for (const { address, block } of factory) { + await fetchLogsFromFactory(address, block); + } + } else { + const { address, block } = factory; + await fetchLogsFromFactory(address, block); + } + } + + return silos.map((silo, index) => ({ + ...silo, + silos: logs[index]?.map((siloAddress: string) => ({ + silo: siloAddress, + assets: [], + })), + })); +} + +async function getSilosAssets( + silos: ISilo[], + { api }: FetchOptions +): Promise { + const siloAddresses = silos.flatMap((silo) => + (silo.silos || []).map((s) => ({ target: s.silo })) + ); + + const assetsInSilosRes = await api.multiCall({ + calls: siloAddresses, + abi: "function getAssets() view returns (address[] assets)", + }); + + const assetsMap: { [key: string]: string[] } = {}; + siloAddresses.forEach((call, index) => { + assetsMap[call.target] = assetsInSilosRes[index]; + }); + + return silos.map((silo) => ({ + ...silo, + silos: (silo.silos || []).map((s) => ({ + silo: s.silo, + assets: assetsMap[s.silo] || [], + })), + })); +} + +async function getSilosFeesStorage( + rawSilos: ISilo[], + { fromApi, toApi }: FetchOptions +): Promise<{ totalFeesResults: FeeResult[]; dailyFeesResults: FeeResult[] }> { + const totalFeesResults: FeeResult[] = []; + const dailyFeesResults: FeeResult[] = []; + + const calls = rawSilos.flatMap((silo) => + (silo.silos || []).flatMap(({ silo: siloAddress, assets }) => + assets.map((asset) => ({ + target: silo.lens, + params: [siloAddress, asset], + })) + ) + ); + + const [prevFeesInSilosRes, currFeesInSilosRes] = await Promise.all([ + fromApi.multiCall({ + calls: calls, + abi: "function protocolFees(address _silo, address _asset) view returns (uint256)", + permitFailure: true, + }), + toApi.multiCall({ + calls: calls, + abi: "function protocolFees(address _silo, address _asset) view returns (uint256)", + permitFailure: true, + }), + ]); + + calls.forEach((call, index) => { + const [_siloAddress, asset] = call.params; + const prevFee = prevFeesInSilosRes[index]; + const currFee = currFeesInSilosRes[index]; + + if (!prevFee || !currFee) return; + totalFeesResults.push({ asset, fee: currFee }); + dailyFeesResults.push({ asset, fee: BigInt(currFee - prevFee) }); + }); + + return { totalFeesResults, dailyFeesResults }; +} + +async function fetch( + options: FetchOptions, + rawSilos: ISilo[] +): Promise { + const totalFees = options.createBalances(); + const dailyFees = options.createBalances(); + + const rawSiloWithAddresses = await getSilos(rawSilos, options); + const siloWithAssets = await getSilosAssets(rawSiloWithAddresses, options); + const { totalFeesResults, dailyFeesResults } = await getSilosFeesStorage( + siloWithAssets, + options + ); + + totalFeesResults.forEach(({ asset, fee }) => { + totalFees.add(asset, fee); + }); + + dailyFeesResults.forEach(({ asset, fee }) => { + dailyFees.add(asset, fee); + }); + + return { totalFees, dailyFees }; +} + +const adapter: Adapter = { + adapter: { + [CHAIN.ETHEREUM]: { + fetch: (options: FetchOptions) => fetch(options, silo[CHAIN.ETHEREUM]), + start: 1660150409, + }, + [CHAIN.ARBITRUM]: { + fetch: (options: FetchOptions) => fetch(options, silo[CHAIN.ARBITRUM]), + start: 1683046409, + }, + [CHAIN.OPTIMISM]: { + fetch: (options: FetchOptions) => fetch(options, silo[CHAIN.OPTIMISM]), + start: 1716656009, + }, + [CHAIN.BASE]: { + fetch: (options: FetchOptions) => fetch(options, silo[CHAIN.BASE]), + start: 1719420809, + }, + }, + version: 2, +}; + +export default adapter; diff --git a/fees/size-credit.ts b/fees/size-credit.ts new file mode 100644 index 0000000000..e2c0bff3f8 --- /dev/null +++ b/fees/size-credit.ts @@ -0,0 +1,63 @@ +import ADDRESSES from '../helpers/coreAssets.json'; +import { Adapter, FetchOptions } from "../adapters/types"; +import { CHAIN } from "../helpers/chains"; + +const SZWETH_CONTRACT = '0x974583f05de1fd18c59c77c4a8803cf0c7db5333'; +const SZAUSDC_CONTRACT = '0x38978038a06a21602a4202dfa66968e7f525bf3e'; +const AUSDC_CONTRACT = '0x4e65fe4dba92790696d040ac24aa414708f5c0ab'; +const SIZE_PROXY_CONTRACT = '0xC2a429681CAd7C1ce36442fbf7A4a68B11eFF940'; + +const fetch: any = async ({ createBalances, getLogs, api, }: FetchOptions) => { + const fees = createBalances() + const FEE_MAPPING = [ + ADDRESSES.base.WETH, + AUSDC_CONTRACT + ] + const logsArray = await Promise.all([ + getLogs({ + target: SZWETH_CONTRACT, + eventAbi: "event Transfer(address indexed from, address indexed to, uint256 value)", + }), + getLogs({ + target: SZAUSDC_CONTRACT, + eventAbi: "event TransferUnscaled(address indexed from, address indexed to, uint256 value)", + }) + ]) + const feeConfig = await api.call({ + target: SIZE_PROXY_CONTRACT, + abi: "function feeConfig() view returns (uint256 swapFeeAPR, uint256 fragmentationFee, uint256 liquidationRewardPercent, uint256 overdueCollateralProtocolPercent, uint256 collateralProtocolPercent, address feeRecipient)", + }); + const feeRecipient = feeConfig.feeRecipient; + logsArray.forEach((logs, i) => { + logs.forEach((log) => { + if (log.to.toLowerCase() === feeRecipient.toLowerCase()) { + fees.add(FEE_MAPPING[i], Number(log.value)); + } + }) + }) + + return { + dailyFees: fees, + dailyRevenue: fees, + dailyProtocolRevenue: fees + }; +}; + +const methodology = "Swap fees are applied on every cash-for-credit trade, and fragmentation fees are charged on every credit split" + +const adapter: Adapter = { + version: 2, + adapter: { + [CHAIN.BASE]: { + fetch, + start: 1721083903, + meta: { + methodology: { + Fees: methodology, + ProtocolRevenue: methodology + } + } + }, + } +} +export default adapter; diff --git a/fees/sns.ts b/fees/sns.ts index a044eeb41f..52fd9467e9 100644 --- a/fees/sns.ts +++ b/fees/sns.ts @@ -1,6 +1,6 @@ import { Adapter, FetchResultFees } from "../adapters/types"; import { CHAIN } from "../helpers/chains"; -import { getTimestampAtStartOfDayUTC } from "../utils/date"; +import { getTimestampAtStartOfDayUTC, getTimestampAtStartOfNextDayUTC } from "../utils/date"; import { httpGet } from "../utils/fetchURL"; const API_URL = "https://sns-api.bonfida.com/v2/defilama/fees-adapter"; @@ -11,9 +11,9 @@ interface IData { } const fetch = async (timestamp: number): Promise => { - const todaysTimestamp = getTimestampAtStartOfDayUTC(timestamp); - - const url = `${API_URL}?from=${todaysTimestamp}&to=${timestamp}`; + const todaysTimestamp = getTimestampAtStartOfNextDayUTC(timestamp); + const fromTimestamp = getTimestampAtStartOfDayUTC(timestamp); + const url = `${API_URL}?from=${fromTimestamp}&to=${todaysTimestamp-1}`; const data: IData = await httpGet(url); return { timestamp: todaysTimestamp, diff --git a/fees/solarbeam.ts b/fees/solarbeam.ts index 020bd1088f..e833a4307d 100644 --- a/fees/solarbeam.ts +++ b/fees/solarbeam.ts @@ -13,6 +13,7 @@ const feeAdapter: BaseAdapter = getDexChainFees({ }); const adapter: Adapter = { + version: 2, adapter: { [CHAIN.MOONRIVER]: { fetch: feeAdapter.moonriver.fetch, diff --git a/fees/solidly-v3.ts b/fees/solidly-v3.ts index bf132882b9..ba0b6f7903 100644 --- a/fees/solidly-v3.ts +++ b/fees/solidly-v3.ts @@ -1,3 +1,4 @@ +import * as sdk from "@defillama/sdk"; import { Chain } from "@defillama/sdk/build/general"; import BigNumber from "bignumber.js"; import request, { gql } from "graphql-request"; @@ -16,11 +17,11 @@ type IURL = { } const endpoints: IURL = { - [CHAIN.ETHEREUM]: "https://api.thegraph.com/subgraphs/name/solidlylabs/solidly-v3", - [CHAIN.BASE]: "https://api.studio.thegraph.com/query/64631/solidly-v3-base/version/latest", - [CHAIN.OPTIMISM]: "https://api.thegraph.com/subgraphs/name/solidlylabs/solidly-v3-optimism", - [CHAIN.ARBITRUM]: "https://api.thegraph.com/subgraphs/name/solidlylabs/solidly-v3-arbitrum", - [CHAIN.FANTOM]: "https://api.thegraph.com/subgraphs/name/solidlylabs/solidly-v3-fantom" + [CHAIN.ETHEREUM]: sdk.graph.modifyEndpoint('7StqFFqbxi3jcN5C9YxhRiTxQM8HA8XEHopsynqqxw3t'), + // [CHAIN.BASE]: "https://api.studio.thegraph.com/query/64631/solidly-v3-base/version/latest", + [CHAIN.OPTIMISM]: sdk.graph.modifyEndpoint('HCThb3gJC45qUYmNEaYmZZTqJW3pSq7X6tb4MqNHEvZf'), + [CHAIN.ARBITRUM]: sdk.graph.modifyEndpoint('ALCsbp7jWC6EQjwgicvZkG6dDEFGMV32QUZJvJGqL9Kx'), + [CHAIN.FANTOM]: sdk.graph.modifyEndpoint('HDNu25S2uqr13BHrQdPv2PfTpwxJgPB7QEnC8fsgKcM9') } const fetch = (chain: Chain) => { @@ -58,10 +59,10 @@ const adapter: Adapter = { fetch: fetch(CHAIN.ETHEREUM), start: 1693526400, }, - [CHAIN.BASE]: { - fetch: fetch(CHAIN.BASE), - start: 0, - }, + // [CHAIN.BASE]: { + // fetch: fetch(CHAIN.BASE), + // start: 0, + // }, [CHAIN.OPTIMISM]: { fetch: fetch(CHAIN.OPTIMISM), start: 0, diff --git a/fees/solidlydex.ts b/fees/solidlydex.ts index 62da349ea6..3da775c230 100644 --- a/fees/solidlydex.ts +++ b/fees/solidlydex.ts @@ -1,3 +1,4 @@ +import * as sdk from "@defillama/sdk"; import request, { gql } from "graphql-request"; import { Adapter, FetchResultFees } from "../adapters/types"; import { CHAIN } from "../helpers/chains"; @@ -5,7 +6,7 @@ import { getBlock } from "../helpers/getBlock"; import { getTimestampAtStartOfDayUTC, getTimestampAtStartOfNextDayUTC } from "../utils/date"; -const URL = "https://api.thegraph.com/subgraphs/name/0xc30/solidly"; +const URL = sdk.graph.modifyEndpoint('4GX8RE9TzEWormbkayeGj4NQmmhYE46izVVUvXv8WPDh'); interface IPair { id: string; fee: string; diff --git a/fees/solv-finance/index.ts b/fees/solv-finance/index.ts new file mode 100644 index 0000000000..c17ff9145c --- /dev/null +++ b/fees/solv-finance/index.ts @@ -0,0 +1,198 @@ +import { Chain } from "@defillama/sdk/build/general"; +import { CHAIN } from "../../helpers/chains"; +import { FetchOptions, FetchV2, SimpleAdapter } from "../../adapters/types"; +import { getTimestampAtStartOfDayUTC } from "../../utils/date"; +import { addTokensReceived } from "../../helpers/token"; +import { httpGet } from "../../utils/fetchURL"; +import { gql, request } from "graphql-request"; +import { getPrices } from "../../utils/prices"; +import { BigNumber } from "bignumber.js" +import { Balances } from "@defillama/sdk"; + +const feesConfig = "https://raw.githubusercontent.com/solv-finance-dev/slov-protocol-defillama/main/solv-fees.json"; +const graphUrl = "https://raw.githubusercontent.com/solv-finance-dev/slov-protocol-defillama/refs/heads/main/solv-graph.json"; +const yields = 0.2; + +const chains: { + [chain: Chain]: { deployedAt: number }; +} = { + [CHAIN.ETHEREUM]: { + deployedAt: 1726531200, + }, + [CHAIN.BSC]: { + deployedAt: 1726531200, + }, + [CHAIN.ARBITRUM]: { + deployedAt: 1726531200, + }, + [CHAIN.MANTLE]: { + deployedAt: 1726531200, + }, + [CHAIN.MERLIN]: { + deployedAt: 1726531200, + }, + [CHAIN.CORE]: { + deployedAt: 1726531200, + }, +}; + +const fetch: FetchV2 = async (options) => { + const contracts: { + [chain: Chain]: { + [protocolFees: string]: { address: string[]; token: string[]; deployedAt: number }; + } + } = await httpGet(feesConfig); + + if (!contracts[options.chain]) { + return { + timestamp: new Date().getTime(), + }; + } + + const dailyFees = options.createBalances(); + const protocolFees = await protocol(options, contracts); + dailyFees.addBalances(protocolFees); + + const poolFees = await pool(options, contracts); + dailyFees.addBalances(poolFees); + return { + dailyFees, + dailyRevenue: dailyFees.clone(yields) + } +}; + +async function protocol(options: FetchOptions, contracts: any): Promise { + if (!contracts[options.chain]["protocolFees"]) { + return options.createBalances(); + } + const dailyFees = await addTokensReceived({ + options, + targets: contracts[options.chain]["protocolFees"].address, + tokens: contracts[options.chain]["protocolFees"].token, + }); + + return dailyFees; +} + +async function pool(options: FetchOptions, contracts: any): Promise { + if (!contracts[options.chain]["poolFees"]) { + return options.createBalances(); + } + const pools = await getGraphData(contracts[options.chain]["poolFees"], options.chain); + const shareConcretes = await concrete(pools, options); + + const fromTimestamp = getTimestampAtStartOfDayUTC(options.fromTimestamp); + const toTimestamp = getTimestampAtStartOfDayUTC(options.toTimestamp); + + const yesterdayNavs = await options.fromApi.multiCall({ + abi: 'function getSubscribeNav(bytes32 poolId_, uint256 time_) view returns (uint256 nav_, uint256 navTime_)', + calls: pools.map((pool: { navOracle: string; poolId: string }) => ({ + target: pool.navOracle, + params: [pool.poolId, fromTimestamp], + })), + }); + + const todayNavs = await options.toApi.multiCall({ + abi: 'function getSubscribeNav(bytes32 poolId_, uint256 time_) view returns (uint256 nav_, uint256 navTime_)', + calls: pools.map((pool: { navOracle: string; poolId: string }) => ({ + target: pool.navOracle, + params: [pool.poolId, toTimestamp], + })), + }); + + const poolBaseInfos = await options.api.multiCall({ + abi: `function slotBaseInfo(uint256 slot_) view returns (tuple(address issuer, address currency, uint64 valueDate, uint64 maturity, uint64 createTime, bool transferable, bool isValid))`, + calls: pools.map((index: { contractAddress: string | number; openFundShareSlot: any; }) => ({ + target: shareConcretes[index.contractAddress], + params: [index.openFundShareSlot] + })), + }); + + const shareTotalValues = await options.api.multiCall({ + abi: 'function slotTotalValue(uint256) view returns (uint256)', + calls: pools.map((index: { contractAddress: string | number; openFundShareSlot: any; }) => ({ + target: shareConcretes[index.contractAddress], + params: [index.openFundShareSlot] + })), + }); + + const dailyFees = options.createBalances(); + for (let i = 0; i < pools.length; i++) { + const poolNavIncrease = todayNavs[i].nav_ - yesterdayNavs[i].nav_; + const poolBaseInfo = poolBaseInfos[i]; + const shareTotalValue = shareTotalValues[i]; + + if (poolNavIncrease <= 0) { + continue; + } + if (shareTotalValue == 0) { + continue; + } + + const token = `${options.chain}:${poolBaseInfo.currency}`; + // PoolFee = (ShareTotalValue / 10^(ShareDecimals)) * (PoolNavIncrease / 10^(PoolTokenDecimals)) * 10^(PoolTokenDecimals) + const poolFee = BigNumber(shareTotalValue) + .dividedBy(BigNumber(10).pow(18)) + .times(BigNumber(poolNavIncrease)); + dailyFees.addBalances({ [token]: poolFee.toNumber() }); + } + + return dailyFees; +} + +async function getGraphData(poolId: string[], chain: Chain) { + const graphUrlList: { + [chain: Chain]: string; + } = (await httpGet(graphUrl)) + const query = gql`{ + poolOrderInfos(first: 1000 where:{poolId_in: ${JSON.stringify(poolId)}}) { + marketContractAddress + contractAddress + navOracle + poolId + vault + openFundShareSlot + } + }`; + let response: any; + if (graphUrlList[chain]) { + response = (await request(graphUrlList[chain], query)).poolOrderInfos; + } + + return response; +} + + +async function concrete(slots: any[], options: FetchOptions): Promise { + var slotsList: any[] = []; + var only = {}; + for (var i = 0; i < slots.length; i++) { + if (!only[slots[i].contractAddress]) { + slotsList.push(slots[i]); + only[slots[i].contractAddress] = true; + } + } + + const concreteLists = await options.api.multiCall({ + calls: slotsList.map((index) => index.contractAddress), + abi: 'address:concrete', + }) + + let concretes = {}; + for (var k = 0; k < concreteLists.length; k++) { + concretes[slotsList[k].contractAddress] = concreteLists[k]; + } + + return concretes; +} + +const adapter: SimpleAdapter = { adapter: {}, version: 2 }; + +Object.keys(chains).forEach((chain: Chain) => { + adapter.adapter[chain] = { + fetch, + start: chains[chain].deployedAt, + }; +}); + +export default adapter; diff --git a/fees/sonne-finance/index.ts b/fees/sonne-finance/index.ts index f880a1d78d..51ec39815a 100644 --- a/fees/sonne-finance/index.ts +++ b/fees/sonne-finance/index.ts @@ -5,36 +5,51 @@ import { } from "./helpers"; import { getFees } from "../../helpers/compoundV2"; -const unitroller = "0x60CF091cD3f50420d50fD7f707414d0DF4751C58"; -const veloGauge = "0x3786d4419d6b4a902607ceb2bb319bb336735df8"; -const veloToken = "0x3c8b650257cfb5f272f799f5e2b4e65093a11a05"; -const veVeloHolder = "0x17063ad4e83b0aba4ca0f3fc3a9794e807a00ed7"; - -const getDailyVeloRewards = async ({ api, fromTimestamp, toTimestamp, createBalances }: FetchOptions) => { - const balances = createBalances(); - const { lastEarn, earned } = await getVeloGaugeDetails(veloGauge, veloToken, veVeloHolder, api,); - - const timespan = toTimestamp - fromTimestamp; - const earnedTimespan = toTimestamp - lastEarn; - const ratio = timespan / earnedTimespan; - balances.add(veloToken, earned * ratio); - return balances +const unitrollerOP = "0x60CF091cD3f50420d50fD7f707414d0DF4751C58"; +const unitrollerBASE = "0x1DB2466d9F5e10D7090E7152B68d62703a2245F0"; +// const veloGauge = "0x62D9e4e99482aF8D573d5ce1ed527C96783153ad"; +// const veloToken = "0x9560e827aF36c94D2Ac33a39bCE1Fe78631088Db"; +// const veVeloHolder = "0x784b82a27029c9e114b521abcc39d02b3d1deaf2"; + +// const getDailyVeloRewards = async ({ api, fromTimestamp, toTimestamp, createBalances }: FetchOptions) => { +// const balances = createBalances(); +// const { lastEarn, earned } = await getVeloGaugeDetails(veloGauge, veloToken, veVeloHolder, api,); + +// const timespan = toTimestamp - fromTimestamp; +// const earnedTimespan = toTimestamp - lastEarn; +// const ratio = timespan / earnedTimespan; +// balances.add(veloToken, earned * ratio); +// return balances +// }; + + +const fetchoptimism = async (options: FetchOptions) => { + const { dailyFees, dailyRevenue } = await getFees(unitrollerOP, options, {}); + // const dailyHoldersRevenue = await getDailyVeloRewards(options) + // dailyHoldersRevenue.addBalances(dailyRevenue) + + return { dailyFees, dailyRevenue, }; }; -const fetch = async (timestamp: number, chainBlocks: ChainBlocks, options: FetchOptions): Promise => { - const { dailyFees, dailyRevenue } = await getFees(unitroller, options, {}); - const dailyHoldersRevenue = await getDailyVeloRewards(options) - dailyHoldersRevenue.addBalances(dailyRevenue) +const fetchbase = async (options: FetchOptions) => { + const { dailyFees, dailyRevenue } = await getFees(unitrollerBASE, options, {}); + // const dailyHoldersRevenue = await getDailyVeloRewards(options) + // dailyHoldersRevenue.addBalances(dailyRevenue) - return { timestamp, dailyFees, dailyRevenue, dailyHoldersRevenue, }; + return { dailyFees, dailyRevenue, }; }; const adapter: Adapter = { + version: 2, adapter: { [CHAIN.OPTIMISM]: { - fetch: fetch as any, + fetch: fetchoptimism as any, start: 1664582400, }, + [CHAIN.BASE]: { + fetch: fetchbase as any, + start: 1693449471, + }, }, }; diff --git a/fees/spacewhale/index.ts b/fees/spacewhale/index.ts new file mode 100644 index 0000000000..1d996ef0cf --- /dev/null +++ b/fees/spacewhale/index.ts @@ -0,0 +1,51 @@ +import ADDRESSES from '../../helpers/coreAssets.json' +import { FetchResult, SimpleAdapter } from "../../adapters/types"; +import { CHAIN } from "../../helpers/chains"; +import { gql, request } from "graphql-request"; +import { getUniqStartOfTodayTimestamp } from "../../helpers/getUniSubgraphVolume"; +import * as sdk from "@defillama/sdk"; + +interface IGraph { + totalFeesEth: string; + totalFeesUsdc: string; + id: string; +} + +const URL = 'https://api.studio.thegraph.com/query/84618/spacewhale1/0.0.5'; + +const fetch = async (timestamp: number): Promise => { + const dayTimestamp = getUniqStartOfTodayTimestamp(new Date(timestamp * 1000)); + const chain = CHAIN.ARBITRUM; + const balances = new sdk.Balances({ chain, timestamp }); + const query = gql` + { + dayData(id: ${dayTimestamp * 1000}) { + totalFeesEth + totalFeesUsdc + id + } + }` + + const response: IGraph = (await request(URL, query)).dayData; + const element = response; + + balances._add(ADDRESSES.arbitrum.USDC_CIRCLE, element.totalFeesUsdc); + balances._add(ADDRESSES.arbitrum.WETH, element.totalFeesEth); + + return { + dailyFees: await balances.getUSDString(), + timestamp: dayTimestamp, + }; +} + +const adapter: SimpleAdapter = { + version: 1, + adapter: { + [CHAIN.ARBITRUM]: { + fetch: fetch, + start: async () => 1712109600, + }, + }, +}; + +export default adapter; \ No newline at end of file diff --git a/fees/sparkdex-v3/index.ts b/fees/sparkdex-v3/index.ts new file mode 100644 index 0000000000..79665d66ef --- /dev/null +++ b/fees/sparkdex-v3/index.ts @@ -0,0 +1,73 @@ +import { gql, request } from "graphql-request"; +import type { ChainEndpoints, FetchV2 } from "../../adapters/types"; +import { Adapter } from "../../adapters/types"; +import { CHAIN } from "../../helpers/chains"; + +import { getTimestampAtStartOfDayUTC } from "../../utils/date"; + +const endpoints = { + [CHAIN.FLARE]: + "https://api.goldsky.com/api/public/project_cly4708cqpcj601tt7gzf1jdj/subgraphs/sparkdex-v3/latest/gn", +}; + +interface IFeeStat { + cumulativeFeeUsd: string; + feeUsd: string; + id: string; +} + +const graphs = (graphUrls: ChainEndpoints) => { + const fetch: FetchV2 = async ({ chain, startTimestamp }) => { + const todaysTimestamp = getTimestampAtStartOfDayUTC(startTimestamp); + + const graphQuery = gql` + query MyQuery { + feeStats(where: {timestamp: ${todaysTimestamp}, period: daily}) { + cumulativeFeeUsd + feeUsd + id + } + } + `; + + const graphRes = await request(graphUrls[chain], graphQuery); + const feeStats: IFeeStat[] = graphRes.feeStats; + + let dailyFeeUSD = BigInt(0); + let totalFeeUSD = BigInt(0); + + feeStats.forEach((fee) => { + dailyFeeUSD += BigInt(fee.feeUsd); + totalFeeUSD += BigInt(fee.cumulativeFeeUsd); + }); + + const finalDailyFee = parseInt(dailyFeeUSD.toString()) / 1e18; + const finalTotalFee = parseInt(totalFeeUSD.toString()) / 1e18; + + return { + timestamp: todaysTimestamp, + dailyFees: finalDailyFee.toString(), + totalFees: finalTotalFee.toString(), + }; + }; + return fetch; +}; + +const methodology = { + dailyFees: "Total cumulativeFeeUsd for specified chain for the given day", +}; + +const adapter: Adapter = { + version: 2, + adapter: { + [CHAIN.FLARE]: { + fetch: graphs(endpoints), + start: 1719878400, + meta: { + methodology, + }, + }, + }, +}; + +export default adapter; diff --git a/fees/spiko/index.ts b/fees/spiko/index.ts new file mode 100644 index 0000000000..1ef6b2a42b --- /dev/null +++ b/fees/spiko/index.ts @@ -0,0 +1,100 @@ +// https://docs.spiko.xyz/spiko-mmfs/fees + +import { Adapter, FetchOptions, FetchResultV2 } from "../../adapters/types"; +import { CHAIN } from "../../helpers/chains"; + +type IFunds = { + [s: string]: string; +}; + +type IAddress = { + [key: string]: IFunds; +}; + +const funds: IAddress = { + [CHAIN.ETHEREUM]: { + EUTBL: "0xa0769f7A8fC65e47dE93797b4e21C073c117Fc80", + USTBL: "0xe4880249745eAc5F1eD9d8F7DF844792D560e750", + }, + [CHAIN.POLYGON]: { + EUTBL: "0xa0769f7A8fC65e47dE93797b4e21C073c117Fc80", + USTBL: "0xe4880249745eAc5F1eD9d8F7DF844792D560e750", + }, +}; + +const calcFees = (totalSupply: number, isEUTBL: boolean) => { + const baseFeeRate = 0.1; + const performanceFeeRate = 0.3; + const revenueRate = 0.15; + const minAumForFees = 100 * 1e6; + + const managementFee = + isEUTBL && totalSupply <= minAumForFees ? 0 : baseFeeRate; + const totalFeesBalance = + (totalSupply * (managementFee + performanceFeeRate)) / 100; + const totalRevenuesBalance = + (totalSupply * + (isEUTBL && totalSupply <= minAumForFees ? 0 : revenueRate)) / + 100; + + return { + fees: totalFeesBalance, + revenues: totalRevenuesBalance, + }; +}; + +async function getFundsFees( + funds: IFunds, + { api, createBalances }: FetchOptions +): Promise { + const dailyFees = createBalances(); + const dailyRevenues = createBalances(); + const totalFees = createBalances(); + const totalRevenues = createBalances(); + const { EUTBL, USTBL } = funds; + + const totalSupplies = await api.multiCall({ + calls: [EUTBL, USTBL], + abi: "erc20:totalSupply", + }); + + const [eutlbSupply, ustblSupply] = [EUTBL, USTBL].map((fund, index) => { + const totalSupply: number = totalSupplies[index]; + return { fund, totalSupply }; + }); + + const ustblFees = calcFees(ustblSupply.totalSupply, false); + const eutblFees = calcFees(eutlbSupply.totalSupply, true); + + const feesDatas = [ + { ...ustblFees, fund: ustblSupply.fund }, + { ...eutblFees, fund: eutlbSupply.fund }, + ]; + + feesDatas.forEach(({ fund, fees, revenues }) => { + dailyFees.add(fund, fees / 365); + totalFees.add(fund, fees); + dailyRevenues.add(fund, revenues / 365); + totalRevenues.add(fund, revenues); + }); + + return { dailyFees, dailyRevenues, totalFees, totalRevenues }; +} + +const adapter: Adapter = { + version: 2, + adapter: { + [CHAIN.ETHEREUM]: { + start: 1714514400, + fetch: (options: FetchOptions) => + getFundsFees(funds[CHAIN.ETHEREUM], options), + }, + [CHAIN.POLYGON]: { + start: 1713564000, + fetch: (options: FetchOptions) => + getFundsFees(funds[CHAIN.POLYGON], options), + }, + }, +}; + +export default adapter; diff --git a/fees/spiritswap.ts b/fees/spiritswap.ts index 0b52c82854..e4654e95fb 100644 --- a/fees/spiritswap.ts +++ b/fees/spiritswap.ts @@ -12,6 +12,7 @@ const feeAdapter = getDexChainFees({ }); const adapter: Adapter = { + version: 2, adapter: feeAdapter }; diff --git a/fees/splash/index.ts b/fees/splash/index.ts new file mode 100644 index 0000000000..08ceb40ebd --- /dev/null +++ b/fees/splash/index.ts @@ -0,0 +1,32 @@ +// https://docs.splash.trade/concepts/dao/dao-business-model#dao-fees-from-pools + +import axios from "axios"; +import { Adapter, FetchResultV2 } from "../../adapters/types"; +import { CHAIN } from "../../helpers/chains"; + +const url: string = "https://api2.splash.trade/platform-api/v1/platform/stats"; + +const fetch = async (): Promise => { + const { + data: { lpFeeUsd, volumeUsd }, + } = await axios.get(url); + + return { + dailyFees: lpFeeUsd, + dailyRevenue: lpFeeUsd / 2, + dailyVolume: volumeUsd, + }; +}; + +const adapter: Adapter = { + version: 1, + adapter: { + [CHAIN.CARDANO]: { + fetch, + start: 1717452000, + runAtCurrTime: true, + }, + }, +}; + +export default adapter; diff --git a/fees/spookyswap.ts b/fees/spookyswap.ts index 2799a3288d..fe8894449e 100644 --- a/fees/spookyswap.ts +++ b/fees/spookyswap.ts @@ -16,6 +16,7 @@ const feeAdapter: BaseAdapter = getDexChainFees({ }); const adapter: Adapter = { + version: 2, adapter: feeAdapter }; diff --git a/fees/squa-defi.ts b/fees/squa-defi.ts index 5cc1e7c543..b3b56076e6 100644 --- a/fees/squa-defi.ts +++ b/fees/squa-defi.ts @@ -14,7 +14,8 @@ const adapter: Adapter = { }), start: 1703255087, }, - } + }, + version: 2, } export default adapter; diff --git a/fees/stargate-finance-v2/index.ts b/fees/stargate-finance-v2/index.ts new file mode 100644 index 0000000000..6d41548da3 --- /dev/null +++ b/fees/stargate-finance-v2/index.ts @@ -0,0 +1,106 @@ +import { Chain } from "@defillama/sdk/build/general"; +import { Adapter, FetchOptions, FetchResultV2 } from "../../adapters/types"; +import { CHAIN } from "../../helpers/chains"; + +type IAddress = { + [s: string | Chain]: string[]; +}; + +const abi = { + token: "address:token", + fee: "uint64:treasuryFee", +}; + +const contracts: IAddress = { + [CHAIN.ETHEREUM]: [ + "0x77b2043768d28E9C9aB44E1aBfC95944bcE57931", + "0xc026395860Db2d07ee33e05fE50ed7bD583189C7", + "0x933597a323Eb81cAe705C5bC29985172fd5A3973", + "0xcDafB1b2dB43f366E48e6F614b8DCCBFeeFEEcD3", + "0x268Ca24DAefF1FaC2ed883c598200CcbB79E931D", + ], + [CHAIN.BSC]: ["0x138EB30f73BC423c6455C53df6D89CB01d9eBc63"], + [CHAIN.AVAX]: [ + "0x5634c4a5FEd09819E3c46D86A965Dd9447d86e47", + "0x12dC9256Acc9895B076f6638D628382881e62CeE", + ], + [CHAIN.POLYGON]: [ + "0x9Aa02D4Fae7F58b8E8f34c66E756cC734DAc7fe4", + "0xd47b03ee6d86Cf251ee7860FB2ACf9f91B9fD4d7", + ], + [CHAIN.ARBITRUM]: [ + "0xA45B5130f36CDcA45667738e2a258AB09f4A5f7F", + "0xe8CDF27AcD73a434D661C84887215F7598e7d0d3", + "0xcE8CcA271Ebc0533920C83d39F417ED6A0abB7D0", + ], + [CHAIN.OPTIMISM]: [ + "0xe8CDF27AcD73a434D661C84887215F7598e7d0d3", + "0xcE8CcA271Ebc0533920C83d39F417ED6A0abB7D0", + "0x19cFCE47eD54a88614648DC3f19A5980097007dD", + ], + [CHAIN.METIS]: [ + "0xD9050e7043102a0391F81462a3916326F86331F0", + "0x36ed193dc7160D3858EC250e69D12B03Ca087D08", + "0x4dCBFC0249e8d5032F89D6461218a9D2eFff5125", + ], + [CHAIN.LINEA]: ["0x81F6138153d473E8c5EcebD3DC8Cd4903506B075"], + [CHAIN.MANTLE]: [ + "0x4c1d3Fc3fC3c177c3b633427c2F769276c547463", + "0xAc290Ad4e0c891FDc295ca4F0a6214cf6dC6acDC", + "0xB715B85682B731dB9D5063187C450095c91C57FC", + "0xF7628d84a2BbD9bb9c8E686AC95BB5d55169F3F1", + ], + [CHAIN.BASE]: [ + "0xdc181Bd607330aeeBEF6ea62e03e5e1Fb4B6F7C7", + "0x27a16dc786820B16E5c9028b75B99F6f604b5d26", + ], + [CHAIN.KAVA]: ["0x41A5b0470D96656Fb3e8f68A218b39AdBca3420b"], + [CHAIN.SCROLL]: [ + "0xC2b638Cb5042c1B3c5d5C969361fB50569840583", + "0x3Fc69CC4A842838bCDC9499178740226062b14E4", + ], + [CHAIN.AURORA]: ["0x81F6138153d473E8c5EcebD3DC8Cd4903506B075"], +}; + +async function getPoolFees( + { api, fromApi, toApi, createBalances }: FetchOptions, + contracts: string[] +): Promise { + const totalFees = createBalances(); + const dailyFees = createBalances(); + + const [assets, prevFees, currFees] = await Promise.all([ + api.multiCall({ calls: contracts, abi: abi.token, permitFailure: true }), + fromApi.multiCall({ calls: contracts, abi: abi.fee, permitFailure: true }), + toApi.multiCall({ calls: contracts, abi: abi.fee, permitFailure: true }), + ]); + + assets.forEach((asset, index) => { + const prevFee = prevFees[index]; + const currFee = currFees[index]; + + if (!prevFee || !currFee) return; + totalFees.add(asset, currFees[index]); + dailyFees.add(asset, currFees[index] - prevFees[index]); + }); + + return { totalFees, dailyFees }; +} + +function adapterByChain(contracts: string[], timestamp: number) { + return { + fetch: (options: FetchOptions) => getPoolFees(options, contracts), + start: timestamp, + }; +} + +const timestamp = 1716892946; +const adapter: Adapter = { + adapter: Object.keys(contracts).reduce((acc, chain: Chain) => { + acc[chain] = adapterByChain(contracts[chain], timestamp); + return acc; + }, {}), + version: 2, +}; + +export default adapter; diff --git a/fees/stargate.ts b/fees/stargate.ts index 02ee411e13..fe6685da78 100644 --- a/fees/stargate.ts +++ b/fees/stargate.ts @@ -1,68 +1,143 @@ -import ADDRESSES from '../helpers/coreAssets.json' -import { Adapter, ChainBlocks, FetchOptions, FetchResultFees } from "../adapters/types"; -import { CHAIN } from "../helpers/chains"; import { Chain } from "@defillama/sdk/build/general"; +import { + Adapter, + ChainBlocks, + FetchOptions, + FetchResultFees, +} from "../adapters/types"; +import { CHAIN } from "../helpers/chains"; +import ADDRESSES from "../helpers/coreAssets.json"; -const event0_swap = 'event Swap(uint16 chainId,uint256 dstPoolId,address from,uint256 amountSD,uint256 eqReward,uint256 eqFee,uint256 protocolFee,uint256 lpFee)' -const event0_swap_remote = 'event SwapRemote( address to,uint256 amountSD,uint256 protocolFee,uint256 dstFee)' +const event0_swap = + "event Swap(uint16 chainId,uint256 dstPoolId,address from,uint256 amountSD,uint256 eqReward,uint256 eqFee,uint256 protocolFee,uint256 lpFee)"; +const event0_swap_remote = + "event SwapRemote( address to,uint256 amountSD,uint256 protocolFee,uint256 dstFee)"; type IAddress = { [s: string | Chain]: string[]; -} +}; const contract_address: IAddress = { [CHAIN.ETHEREUM]: [ - '0xdf0770dF86a8034b3EFEf0A1Bb3c889B8332FF56', - '0x38EA452219524Bb87e18dE1C24D3bB59510BD783', - '0x101816545F6bd2b1076434B54383a1E633390A2E', + "0x101816545f6bd2b1076434b54383a1e633390a2e", + "0x101816545F6bd2b1076434B54383a1E633390A2E", + "0xdf0770dF86a8034b3EFEf0A1Bb3c889B8332FF56", + "0x38ea452219524bb87e18de1c24d3bb59510bd783", + "0x692953e758c3669290cb1677180c64183cEe374e", + "0x0Faf1d2d3CED330824de3B8200fc8dc6E397850d", + "0xfA0F307783AC21C39E939ACFF795e27b650F6e68", + "0x590d4f8A68583639f215f675F3a259Ed84790580", + "0xE8F55368C82D38bbbbDb5533e7F56AfC2E978CC2", + "0x9cef9a0b1be0d289ac9f4a98ff317c33eaa84eb8", + "0xd8772edBF88bBa2667ed011542343b0eDDaCDa47", + "0x430Ebff5E3E80A6C58E7e6ADA1d90F5c28AA116d", + "0xa572d137666dcbadfa47c3fc41f15e90134c618c", ], [CHAIN.ARBITRUM]: [ - '0x892785f33CdeE22A30AEF750F285E18c18040c3e', - '0xB6CfcF89a7B22988bfC96632aC2A9D6daB60d641', - '0x915A55e36A01285A14f05dE6e81ED9cE89772f8e', + "0x915A55e36A01285A14f05dE6e81ED9cE89772f8e", + "0x892785f33CdeE22A30AEF750F285E18c18040c3e", + "0xB6CfcF89a7B22988bfC96632aC2A9D6daB60d641", + "0xaa4BF442F024820B2C28Cd0FD72b82c63e66F56C", + "0xF39B7Be294cB36dE8c510e267B82bb588705d977", + "0x600E576F9d853c95d58029093A16EE49646F3ca5", ], [CHAIN.AVAX]: [ - '0x1205f31718499dBf1fCa446663B532Ef87481fe1', - '0x29e38769f23701A2e4A8Ef0492e19dA4604Be62c', + "0x1205f31718499dBf1fCa446663B532Ef87481fe1", + "0x29e38769f23701A2e4A8Ef0492e19dA4604Be62c", + "0x1c272232Df0bb6225dA87f4dEcD9d37c32f63Eea", + "0x8736f92646B2542B3e5F3c63590cA7Fe313e283B", + "0xEAe5c2F6B25933deB62f754f239111413A0A25ef", ], [CHAIN.BSC]: [ - '0x9aA83081AA06AF7208Dcc7A4cB72C94d057D2cda', - '0x98a5737749490856b401DB5Dc27F522fC314A4e1', - ], - [CHAIN.FANTOM]: [ - '0x12edeA9cd262006cC3C4E77c90d2CD2DD4b1eb97' + "0x9aA83081AA06AF7208Dcc7A4cB72C94d057D2cda", + "0x98a5737749490856b401DB5Dc27F522fC314A4e1", + "0x4e145a589e4c03cBe3d28520e4BF3089834289Df", + "0x7BfD7f2498C4796f10b6C611D9db393D3052510C", + "0x68C6c27fB0e02285829e69240BE16f32C5f8bEFe", ], + [CHAIN.FANTOM]: ["0x12edeA9cd262006cC3C4E77c90d2CD2DD4b1eb97"], [CHAIN.OPTIMISM]: [ - '0xDecC0c09c3B5f6e92EF4184125D5648a66E35298', - '0xd22363e3762cA7339569F3d33EADe20127D5F98C', + "0xd22363e3762cA7339569F3d33EADe20127D5F98C", + "0x165137624F1f692e69659f944BF69DE02874ee27", + "0x368605D9C6243A80903b9e326f1Cddde088B8924", + "0x2F8bC9081c7FCFeC25b9f41a50d97EaA592058ae", + "0x3533F5e279bDBf550272a199a223dA798D9eff78", + "0x5421FA1A48f9FF81e4580557E86C7C0D24C18036", ], [CHAIN.POLYGON]: [ - '0x1205f31718499dBf1fCa446663B532Ef87481fe1', - '0x29e38769f23701A2e4A8Ef0492e19dA4604Be62c', - ] -} + "0x1205f31718499dBf1fCa446663B532Ef87481fe1", + "0x29e38769f23701A2e4A8Ef0492e19dA4604Be62c", + "0x1c272232Df0bb6225dA87f4dEcD9d37c32f63Eea", + "0x8736f92646B2542B3e5F3c63590cA7Fe313e283B", + ], + [CHAIN.METIS]: [ + "0xAad094F6A75A14417d39f04E690fC216f080A41a", + "0x2b60473a7C41Deb80EDdaafD5560e963440eb632", + ], + [CHAIN.BASE]: [ + "0x28fc411f9e1c480AD312b3d9C60c22b965015c6B", + "0x4c80e24119cfb836cdf0a6b53dc23f04f7e652ca", + ], + [CHAIN.LINEA]: ["0xAad094F6A75A14417d39f04E690fC216f080A41a"], + [CHAIN.KAVA]: ["0xAad094F6A75A14417d39f04E690fC216f080A41a"], + [CHAIN.MANTLE]: [ + "0xAad094F6A75A14417d39f04E690fC216f080A41a", + "0x2b60473a7C41Deb80EDdaafD5560e963440eb632", + "0xf52b354FFDB323E0667E87a0136040e3e4D9dF33", + ], +}; type IMap = { [s: string]: string; -} +}; const mapTokenPrice: IMap = { - ['0x101816545f6bd2b1076434b54383a1e633390a2e'.toLowerCase()]: ADDRESSES.null, - ['0x915a55e36a01285a14f05de6e81ed9ce89772f8e'.toLowerCase()]: ADDRESSES.null, - ['0xd22363e3762ca7339569f3d33eade20127d5f98c'.toLowerCase()]: ADDRESSES.null, -} + ["0x101816545f6bd2b1076434b54383a1e633390a2e".toLowerCase()]: ADDRESSES.null, + ["0xa572d137666dcbadfa47c3fc41f15e90134c618c".toLowerCase()]: ADDRESSES.null, + ["0x915a55e36a01285a14f05de6e81ed9ce89772f8e".toLowerCase()]: ADDRESSES.null, + ["0xd22363e3762ca7339569f3d33eade20127d5f98c".toLowerCase()]: ADDRESSES.null, + ["0x28fc411f9e1c480AD312b3d9C60c22b965015c6B".toLowerCase()]: ADDRESSES.null, + ["0xAad094F6A75A14417d39f04E690fC216f080A41a".toLowerCase()]: ADDRESSES.null, + ["0xf52b354FFDB323E0667E87a0136040e3e4D9dF33".toLowerCase()]: ADDRESSES.null, +}; const fetch = (chain: Chain) => { - return async (timestamp: number, _: ChainBlocks, { createBalances, getLogs }: FetchOptions): Promise => { - const dailyFees = createBalances() - const transform = (a: string) => mapTokenPrice[a.toLowerCase()] ?? a - const logs = await getLogs({ targets: contract_address[chain], eventAbi: event0_swap, flatten: false, }) - const logs_swap_remote = await getLogs({ targets: contract_address[chain], eventAbi: event0_swap_remote, flatten: false }) - logs.forEach((_: any, index: number) => _.forEach((log: any) => dailyFees.add(transform(contract_address[chain][index]), log.protocolFee))) - logs_swap_remote.forEach((_: any, index: number) => _.forEach((log: any) => dailyFees.add(transform(contract_address[chain][index]), log.protocolFee))) - return { dailyFees, dailyRevenue: dailyFees, timestamp, } - } -} + return async ( + timestamp: number, + _: ChainBlocks, + { createBalances, getLogs }: FetchOptions + ): Promise => { + const dailyFees = createBalances(); + const transform = (a: string) => mapTokenPrice[a.toLowerCase()] ?? a; + const logs = await getLogs({ + targets: contract_address[chain], + eventAbi: event0_swap, + flatten: false, + }); + const logs_swap_remote = await getLogs({ + targets: contract_address[chain], + eventAbi: event0_swap_remote, + flatten: false, + }); + logs.forEach((_: any, index: number) => + _.forEach((log: any) => + dailyFees.add( + transform(contract_address[chain][index]), + log.protocolFee + ) + ) + ); + logs_swap_remote.forEach((_: any, index: number) => + _.forEach((log: any) => + dailyFees.add( + transform(contract_address[chain][index]), + log.protocolFee + ) + ) + ); + return { dailyFees, dailyRevenue: dailyFees, timestamp }; + }; +}; const adapter: Adapter = { adapter: { @@ -94,7 +169,27 @@ const adapter: Adapter = { fetch: fetch(CHAIN.POLYGON), start: 1661990400, }, - } -} + [CHAIN.METIS]: { + fetch: fetch(CHAIN.METIS), + start: 1661990400, + }, + [CHAIN.BASE]: { + fetch: fetch(CHAIN.BASE), + start: 1661990400, + }, + [CHAIN.LINEA]: { + fetch: fetch(CHAIN.LINEA), + start: 1661990400, + }, + [CHAIN.MANTLE]: { + fetch: fetch(CHAIN.MANTLE), + start: 1661990400, + }, + [CHAIN.KAVA]: { + fetch: fetch(CHAIN.KAVA), + start: 1661990400, + }, + }, +}; export default adapter; diff --git a/fees/stars-arena.ts b/fees/stars-arena.ts index 3b1c3c89b4..d25feeeee8 100644 --- a/fees/stars-arena.ts +++ b/fees/stars-arena.ts @@ -1,18 +1,27 @@ -import { Adapter, DISABLED_ADAPTER_KEY, FetchResultFees } from "../adapters/types"; +import { Adapter, FetchOptions } from "../adapters/types"; import { CHAIN } from "../helpers/chains"; -import disabledAdapter from "../helpers/disabledAdapter"; -const fetch = async (timestamp: number): Promise => { +const fetch = async ({createBalances, getLogs}: FetchOptions) => { + const dailyFees = createBalances(); + const dailyRevenue = createBalances() + const logs = await getLogs({ + topic: '0xc9d4f93ded9b42fa24561e02b2a40f720f71601eb1b3f7b3fd4eff20877639ee', + targets: ['0xC605C2cf66ee98eA925B1bb4FeA584b71C00cC4C', '0x69B7F08B2952e2EE3CA4222190BCF07831f1096f'], + eventAbi: 'event Trade (address trader, address subject, bool isBuy, uint256 shareAmount, uint256 amount, uint256 protocolAmount, uint256 subjectAmount, uint256 referralAmount, uint256 supply, uint256 buyPrice, uint256 myShares)' + }); + logs.map((log: any) => { + dailyFees.addGasToken(log.protocolAmount+log.subjectAmount+log.referralAmount); + dailyRevenue.addGasToken(log.protocolAmount) + }); return { - dailyFees: `${0}`, - dailyRevenue: `${0}`, - timestamp + dailyFees, + dailyRevenue } } const adapter: Adapter = { + version: 2, adapter: { - [DISABLED_ADAPTER_KEY]: disabledAdapter, [CHAIN.AVAX]: { fetch: fetch, start: 1695081600, diff --git a/fees/stbot.ts b/fees/stbot.ts new file mode 100644 index 0000000000..ad7f57819c --- /dev/null +++ b/fees/stbot.ts @@ -0,0 +1,27 @@ +import { FetchOptions, SimpleAdapter } from "../adapters/types"; +import { CHAIN } from "../helpers/chains"; +import { queryDune } from "../helpers/dune"; + +const fetch: any = async (options: FetchOptions) => { + const dailyFees = options.createBalances(); + const value = (await queryDune("3997872", { + start: options.startTimestamp, + end: options.endTimestamp, + })); + dailyFees.add('So11111111111111111111111111111111111111112', value[0].fee_token_amount); + + return { dailyFees, dailyRevenue: dailyFees } +} + +const adapter: SimpleAdapter = { + version: 2, + adapter: { + [CHAIN.SOLANA]: { + fetch: fetch, + start: 0, + }, + }, + isExpensiveAdapter: true +}; + +export default adapter; \ No newline at end of file diff --git a/fees/stellaswap.ts b/fees/stellaswap.ts index 143bee12b3..b84f5ae5a8 100644 --- a/fees/stellaswap.ts +++ b/fees/stellaswap.ts @@ -12,6 +12,7 @@ const feeAdapter = getDexChainFees({ }); const adapter: Adapter = { + version: 2, adapter: feeAdapter }; diff --git a/fees/ston/index.ts b/fees/ston/index.ts new file mode 100644 index 0000000000..807b407648 --- /dev/null +++ b/fees/ston/index.ts @@ -0,0 +1,87 @@ +import { CHAIN } from "../../helpers/chains"; +import postURL from "../../utils/fetchURL"; +import fetchURL from "../../utils/fetchURL"; +import { FetchOptions, SimpleAdapter } from "../../adapters/types"; + +const endpoint = "https://api.ston.fi/v1/stats/operations?"; + +const fetchFees = async (options: FetchOptions) => { + const pool_list = (await fetchURL("https://api.ston.fi/v1/pools")).pool_list; + // store pools info for each asset to calculate weigthed price later + const asset2pools = {}; + const add_pool = (address: string, tvl: number, reserve: number) => { + if (!asset2pools[address]) { + asset2pools[address] = []; + } + asset2pools[address].push({ tvl, reserve }); + }; + for (const pool of pool_list) { + // ignore pools with low liquidity + if (pool["lp_total_supply_usd"] < 1000) { + continue; + } + add_pool(pool["token0_address"], Number(pool["lp_total_supply_usd"]) / 2, Number(pool["reserve0"])); + add_pool(pool["token1_address"], Number(pool["lp_total_supply_usd"]) / 2, Number(pool["reserve1"])); + } + // price is calculated as total tvl / total reserve across all pools + const asset_prices = {}; + for (const asset in asset2pools) { + const pools = asset2pools[asset]; + const price = + pools.map((pool) => pool.tvl).reduce((a, b) => a + b, 0) / + pools.map((pool) => pool.reserve).reduce((a, b) => a + b, 0); + asset_prices[asset] = price; + } + // explicitly set price for pTON based on TON price + asset_prices["EQCM3B12QK1e4yZSf8GtBRT0aLMNyEsBc_DhVfRRtOEffLez"] = + asset_prices["EQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAM9c"]; + + const startTime = new Date(options.startTimestamp * 1000).toISOString().split(".")[0]; + const endTime = new Date(options.endTimestamp * 1000).toISOString().split(".")[0]; + const res = await postURL(`${endpoint}since=${startTime}&until=${endTime}`); + + let total_lp_fees = 0; + let total_protocol_fees = 0; + let referral_fees = 0; + + // go through all operations and calculate fees based on the current prices + for (const item of res["operations"]) { + const operation = item.operation; + if (operation.success && operation.operation_type == "swap" && operation.exit_code == "swap_ok") { + if (operation.fee_asset_address in asset_prices) { + const price = asset_prices[operation.fee_asset_address]; + total_lp_fees += operation.lp_fee_amount * price; + total_protocol_fees += operation.protocol_fee_amount * price; + referral_fees += (operation.referral_fee_amount || 0) * price; + } else { + // console.log("Fee asset not found", operation.fee_asset_address) + continue; + } + } + } + + return { + dailyUserFees: total_lp_fees + total_protocol_fees + referral_fees, + dailyFees: total_lp_fees + total_protocol_fees + referral_fees, + dailySupplySideRevenue: total_lp_fees, + dailyRevenue: total_protocol_fees, + }; +}; + +const adapter: SimpleAdapter = { + version: 2, + adapter: { + [CHAIN.TON]: { + start: 1700000000, + meta: { + methodology: { + UserFees: "User pays fee on each swap. Fees go to the protocol, LPs and optinally to the referral address.", + Revenue: "Protocol receives 1/3 of fees paid by users (not including referral fees).", + SupplySideRevenue: "2/3 of user fees are distributed among LPs (not including referral fees).", + }, + }, + fetch: fetchFees, + }, + }, +}; +export default adapter; diff --git a/fees/stormtrade/index.ts b/fees/stormtrade/index.ts index 9f50bfa66a..9612cdee2d 100644 --- a/fees/stormtrade/index.ts +++ b/fees/stormtrade/index.ts @@ -3,6 +3,7 @@ import fetchURL from '../../utils/fetchURL' export default { + version: 1, adapter: { [CHAIN.TON]: { runAtCurrTime: true, diff --git a/fees/stride.ts b/fees/stride.ts index 557ffe25c9..8a0c88e180 100644 --- a/fees/stride.ts +++ b/fees/stride.ts @@ -10,13 +10,15 @@ interface DailyFeeResponse { } const chainOverrides: { [key: string]: string } = { - "terra": "terra2", + terra: "terra2", }; const fetch = (chain: string) => { return async (timestamp: number): Promise => { const overriddenChain = chainOverrides[chain] || chain; // Override if exists, else use original - const response: DailyFeeResponse = await httpGet(`https://edge.stride.zone/api/${overriddenChain}/stats/fees`); + const response: DailyFeeResponse = await httpGet( + `https://edge.stride.zone/api/${overriddenChain}/stats/fees` + ); return { timestamp: timestamp, @@ -26,7 +28,6 @@ const fetch = (chain: string) => { }; }; - const meta = { methodology: { Fees: "Fees are staking rewards earned by tokens staked with Stride. They are measured across Stride's LSD tokens' yields and converted to USD terms.", @@ -43,12 +44,30 @@ const adapter: Adapter = { start: 0, meta, }, + celestia: { + fetch: fetch("celestia"), + runAtCurrTime: true, + start: 0, + meta, + }, osmosis: { fetch: fetch("osmosis"), runAtCurrTime: true, start: 0, meta, }, + dydx: { + fetch: fetch("dydx"), + runAtCurrTime: true, + start: 0, + meta, + }, + dymension: { + fetch: fetch("dymension"), + runAtCurrTime: true, + start: 0, + meta, + }, juno: { fetch: fetch("juno"), runAtCurrTime: true, @@ -85,6 +104,24 @@ const adapter: Adapter = { start: 0, meta, }, + comdex: { + fetch: fetch("comdex"), + runAtCurrTime: true, + start: 0, + meta, + }, + haqq: { + fetch: fetch("haqq"), + runAtCurrTime: true, + start: 0, + meta, + }, + band: { + fetch: fetch("band"), + runAtCurrTime: true, + start: 0, + meta, + }, }, }; diff --git a/fees/substanceX/index.ts b/fees/substanceX/index.ts index 570e00af02..eee8bc78b7 100644 --- a/fees/substanceX/index.ts +++ b/fees/substanceX/index.ts @@ -1,28 +1,32 @@ +import * as sdk from "@defillama/sdk"; import { Adapter } from "../../adapters/types"; import { CHAIN } from "../../helpers/chains"; -import { request, gql, GraphQLClient } from "graphql-request"; -import type { ChainEndpoints } from "../../adapters/types"; +import { gql, GraphQLClient } from "graphql-request"; +import type { ChainEndpoints, FetchOptions } from "../../adapters/types"; import { Chain } from "@defillama/sdk/build/general"; const endpoints = { - [CHAIN.ARBITRUM]: "https://api.thegraph.com/subgraphs/name/substanceexchangedevelop/coreprod", + [CHAIN.ARBITRUM]: sdk.graph.modifyEndpoint('HETFHppem3dz1Yjjv53D7K98dm5t5TErgYAMPBFPHVpi'), + [CHAIN.ZETA]: "https://gql-zeta.substancex.io/subgraphs/name/substanceexchangedevelop/zeta" }; const blockNumberGraph = { - [CHAIN.ARBITRUM]: "https://api.thegraph.com/subgraphs/name/ianlapham/arbitrum-one-blocks", + [CHAIN.ARBITRUM]: sdk.graph.modifyEndpoint('64DCU8nq48qdDABnobpDafsg7RF75Rx5soKrHiGA8mqp'), + [CHAIN.ZETA]: "https://gql-zeta.substancex.io/subgraphs/name/substanceexchangedevelop/zeta-blocks" } +const headers = { 'sex-dev': 'ServerDev'} + const graphs = (graphUrls: ChainEndpoints) => { return (chain: Chain) => { - return async (timestamp: number) => { + return async ({ toTimestamp }: FetchOptions) => { - if (chain === CHAIN.ARBITRUM) { // Get blockNumers const blockNumerQuery = gql` { blocks( - where: {timestamp_lte:${timestamp}} + where: {timestamp_lte:${toTimestamp}} orderBy: timestamp orderDirection: desc first: 1 @@ -35,7 +39,7 @@ const graphs = (graphUrls: ChainEndpoints) => { const last24hBlockNumberQuery = gql` { blocks( - where: {timestamp_lte:${timestamp - 24 * 60 * 60}} + where: {timestamp_lte:${toTimestamp - 24 * 60 * 60}} orderBy: timestamp orderDirection: desc first: 1 @@ -46,8 +50,12 @@ const graphs = (graphUrls: ChainEndpoints) => { } `; - const blockNumberGraphQLClient = new GraphQLClient(blockNumberGraph[chain]); - const graphQLClient = new GraphQLClient(graphUrls[chain]); + const blockNumberGraphQLClient = new GraphQLClient(blockNumberGraph[chain], { + headers: chain === CHAIN.ZETA ? headers: null, + }); + const graphQLClient = new GraphQLClient(graphUrls[chain], { + headers: chain === CHAIN.ZETA ? headers: null, + }); const blockNumber = ( @@ -89,28 +97,29 @@ const graphs = (graphUrls: ChainEndpoints) => { const dailyFee = Number(totalFee) - (Number(last24hTotalFee) / 10 ** 6) return { - timestamp, dailyFees: dailyFee.toString(), totalFees: totalFee.toString(), }; } - return { - timestamp, dailyFees: "0", totalFees: "0", }; }; - }; }; const adapter: Adapter = { + version: 2, adapter: { [CHAIN.ARBITRUM]: { fetch: graphs(endpoints)(CHAIN.ARBITRUM), start: 1700323200, }, + [CHAIN.ZETA]: { + fetch: graphs(endpoints)(CHAIN.ZETA), + start: 2631301, + }, }, }; diff --git a/fees/summer.fi/index.ts b/fees/summer.fi/index.ts index 3a9ac8281f..5aa46cb316 100644 --- a/fees/summer.fi/index.ts +++ b/fees/summer.fi/index.ts @@ -28,7 +28,6 @@ const fetch: FetchV2 = async (options) => { const dailyFees = await addTokensReceived({ options, target: contracts[options.chain].address, - fetchTokenList: true, }); return { diff --git a/fees/sunpump.ts b/fees/sunpump.ts new file mode 100644 index 0000000000..6203a8f742 --- /dev/null +++ b/fees/sunpump.ts @@ -0,0 +1,35 @@ +import { time } from "console"; +import { Adapter, FetchOptions, } from "../adapters/types"; +import { CHAIN } from "../helpers/chains"; +import { httpGet } from "../utils/fetchURL"; + +const api = "https://openapi.sunpump.meme/pump-api/api/feeData" +interface IResponse { + date: number; + count: number; + amount: number; +} + +const adapter: Adapter = { + version: 1, + adapter: { + [CHAIN.TRON]: { + fetch: (async (_t: any, _a: any ,options: FetchOptions) => { + const start = options.startOfDay * 1000; + const end = start + 86400; + const startStr = new Date(start).toISOString().split("T")[0]; + const endStr = new Date(end).toISOString().split("T")[0]; + const url = `${api}?fromDate=${startStr}&toDate=${endStr}`; + const res: IResponse[] = (await httpGet(url)).data; + const dailyFees = options.createBalances(); + const dayItem = res.find((item) => item.date === start); + dailyFees.addGasToken((dayItem?.amount || 0) * 1e6); + return { dailyFees, dailyRevenue: dailyFees, timestamp: options.startOfDay }; + }) as any, + start: 1723334400 + }, + }, + +} + +export default adapter; diff --git a/fees/sunswap-v1.ts b/fees/sunswap-v1.ts new file mode 100644 index 0000000000..e971599294 --- /dev/null +++ b/fees/sunswap-v1.ts @@ -0,0 +1,34 @@ +import { time } from "console"; +import { Adapter, FetchOptions, } from "../adapters/types"; +import { CHAIN } from "../helpers/chains"; +import { httpGet } from "../utils/fetchURL"; + +const api = "https://openapi.sun.io/open/api/feeData" +interface IResponse { + date: number; + fee: number; +} + +const adapter: Adapter = { + version: 1, + adapter: { + [CHAIN.TRON]: { + fetch: (async (_t: any, _a: any ,options: FetchOptions) => { + const start = options.startOfDay * 1000; + const end = start + 86400; + const startStr = new Date(start).toISOString().split("T")[0]; + const endStr = new Date(end).toISOString().split("T")[0]; + const url = `${api}?fromDate=${startStr}&toDate=${endStr}&version=v1`; + const res: IResponse[] = (await httpGet(url)).data; + const dailyFees = options.createBalances(); + const dayItem = res.find((item) => item.date === start); + dailyFees.addGasToken((dayItem?.fee || 0) * 1e6); + return { dailyFees, timestamp: options.startOfDay }; + }) as any, + start: 1704560436 + }, + }, + +} + +export default adapter; diff --git a/fees/sunswap-v2.ts b/fees/sunswap-v2.ts new file mode 100644 index 0000000000..4003e37c2f --- /dev/null +++ b/fees/sunswap-v2.ts @@ -0,0 +1,33 @@ +import { time } from "console"; +import { Adapter, FetchOptions, } from "../adapters/types"; +import { CHAIN } from "../helpers/chains"; +import { httpGet } from "../utils/fetchURL"; + +const api = "https://openapi.sun.io/open/api/feeData" +interface IResponse { + date: number; + fee: number; +} + +const adapter: Adapter = { + version: 1, + adapter: { + [CHAIN.TRON]: { + fetch: (async (_t: any, _a: any ,options: FetchOptions) => { + const start = options.startOfDay * 1000; + const end = start + 86400; + const startStr = new Date(start).toISOString().split("T")[0]; + const endStr = new Date(end).toISOString().split("T")[0]; + const url = `${api}?fromDate=${startStr}&toDate=${endStr}&version=v2`; + const res: IResponse[] = (await httpGet(url)).data; + const dayItem = res.find((item) => item.date === start); + const dailyFees = dayItem?.fee || 0; + return { dailyFees, timestamp: options.startOfDay }; + }) as any, + start: 1704560436 + }, + }, + +} + +export default adapter; diff --git a/fees/sunswap-v3.ts b/fees/sunswap-v3.ts new file mode 100644 index 0000000000..fc61e54740 --- /dev/null +++ b/fees/sunswap-v3.ts @@ -0,0 +1,33 @@ +import { time } from "console"; +import { Adapter, FetchOptions, } from "../adapters/types"; +import { CHAIN } from "../helpers/chains"; +import { httpGet } from "../utils/fetchURL"; + +const api = "https://openapi.sun.io/open/api/feeData" +interface IResponse { + date: number; + fee: number; +} + +const adapter: Adapter = { + version: 1, + adapter: { + [CHAIN.TRON]: { + fetch: (async (_t: any, _a: any ,options: FetchOptions) => { + const start = options.startOfDay * 1000; + const end = start + 86400; + const startStr = new Date(start).toISOString().split("T")[0]; + const endStr = new Date(end).toISOString().split("T")[0]; + const url = `${api}?fromDate=${startStr}&toDate=${endStr}&version=v3`; + const res: IResponse[] = (await httpGet(url)).data; + const dayItem = res.find((item) => item.date === start); + const dailyFees = dayItem?.fee || 0; + return { dailyFees, timestamp: options.startOfDay }; + }) as any, + start: 1704560436 + }, + }, + +} + +export default adapter; diff --git a/fees/superchain.ts b/fees/superchain.ts new file mode 100644 index 0000000000..bed84e278d --- /dev/null +++ b/fees/superchain.ts @@ -0,0 +1,44 @@ +import { FetchOptions, SimpleAdapter } from "../adapters/types" +import { CHAIN } from "../helpers/chains" +import ADDRESSES from '../helpers/coreAssets.json' + +const fees: any = { + [CHAIN.BASE]: ['0x9c3631dDE5c8316bE5B7554B0CcD2631C15a9A05'], + [CHAIN.ETHEREUM]: [ + '0xa3d596eafab6b13ab18d40fae1a962700c84adea', + '0x793e01dCf6F9759Bf26dd7869b03129e64217537', + '0x4a4962275DF8C60a80d3a25faEc5AA7De116A746', + '0xe900b3Edc1BA0430CFa9a204A1027B90825ac951', + '0xed4811010a86f7c39134fbc20206d906ad1176b6', + '0x13f37e6b638ca83e7090bb3722b3ae04bf884019', + '0x99c9fc46f92e8a1c0dec1b1747d010903e884be1' + ] +} +const fetchFees = async (options: FetchOptions) => { + const { api, fromApi, createBalances } = options; + await api.sumTokens({ owners: fees[options.chain], tokens: [ADDRESSES.null] }) + await fromApi.sumTokens({ owners: fees[options.chain], tokens: [ADDRESSES.null] }) + const balances = createBalances() + balances.addBalances(api.getBalancesV2()) + balances.subtract(fromApi.getBalancesV2()) + const dailyFees = balances.clone() + return { + dailyFees, + } +} + +const adapter: SimpleAdapter = { + version: 2, + adapter: { + [CHAIN.BASE]: { + fetch: fetchFees, + start: 0, + }, + [CHAIN.ETHEREUM]: { + fetch: fetchFees, + start: 0, + }, + } +} + +export default adapter diff --git a/fees/superstate/index.ts b/fees/superstate/index.ts new file mode 100644 index 0000000000..352752a099 --- /dev/null +++ b/fees/superstate/index.ts @@ -0,0 +1,71 @@ +// https://docs.superstate.co/ustb/income-fees-and-yield +// https://docs.superstate.co/uscc/income-fees-and-yield + +import { Adapter, FetchOptions, FetchResultFees } from "../../adapters/types"; +import { CHAIN } from "../../helpers/chains"; +import { httpGet } from "../../utils/fetchURL"; + +const _fundsAddresses: string[] = [ + "0x43415eb6ff9db7e26a15b704e7a3edce97d31c4e", + "0x14d60e7fdc0d71d8611742720e4c50e7a974020c", +]; + +function formatDate(date: Date): string { + const day = String(date.getDate()).padStart(2, "0"); + const month = String(date.getMonth() + 1).padStart(2, "0"); + const year = date.getFullYear(); + return `${month}/${day}/${year}`; +} + +function findDailyData(data: any[], targetDate: string) { + return data.find((item: any) => item.net_asset_value_date === targetDate); +} + +async function getFundsFees(timestamp: number, _: any, options: FetchOptions): Promise { + let ustbTotalFees: number = 0; + let usccTotalFees: number = 0; + + const targetDate = formatDate(new Date(options.startOfDay * 1000)); + + const [ustbRes, usccRes] = await Promise.all([ + httpGet("https://api.superstate.co/v1/funds/1/nav-daily"), + httpGet("https://api.superstate.co/v1/funds/2/nav-daily"), + ]) + + const ustbDailyData = findDailyData(ustbRes, targetDate); + const usccDailyData = findDailyData(usccRes, targetDate); + + if (ustbDailyData) { + const { assets_under_management } = ustbDailyData; + if (assets_under_management > 200 * 1e6) { + // no fees until 200 MM AUM + ustbTotalFees = (assets_under_management * 0.15) / 100; // 0.15bps + } + } + + if (usccDailyData) { + const { assets_under_management } = usccDailyData; + if (assets_under_management > 50 * 1e6) { + // no fees until 50 MM AUM + usccTotalFees = (assets_under_management * 0.75) / 100; // 0.75bps + } + } + + return { + timestamp, + dailyFees: (ustbTotalFees + usccTotalFees) / 365, + totalFees: ustbTotalFees + usccTotalFees, + }; +} + +const adapter: Adapter = { + adapter: { + [CHAIN.ETHEREUM]: { + fetch: getFundsFees, + start: 1709247600, + runAtCurrTime: false, + }, + }, +}; + +export default adapter; diff --git a/fees/surfone/index.ts b/fees/surfone/index.ts index 7daeade8d5..1c2fb1a101 100644 --- a/fees/surfone/index.ts +++ b/fees/surfone/index.ts @@ -1,38 +1,41 @@ -import { SimpleAdapter } from "../../adapters/types"; -import { CHAIN } from "../../helpers/chains"; +import {FetchOptions, SimpleAdapter} from "../../adapters/types"; import { getUniqStartOfTodayTimestamp } from "../../helpers/getUniSubgraphVolume"; import { httpGet } from "../../utils/fetchURL"; -const volumeEndpoint = "https://apigateway.surf.one/pool/24h/data" +// const volumeEndpoint = "https://apigateway.surf.one/pool/24h/data" +const volumeEndpointV2 = "https://apigateway.surf.one/v2/market/total/stat" const headers = { - "Block-Chain-Id": '8453', + "Block-Chain-Id":"4200", + "user-agent":"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/122.0.0.0 Safari/537.36" }; -interface IVolume { - totalTradeFee: number, +interface IFee { + daily_fee: number, + total_fee: number, } const fetch = () => { return async (timestamp: number) => { const dayTimestamp = getUniqStartOfTodayTimestamp(new Date(timestamp * 1000)) - const response = (await httpGet(volumeEndpoint, { headers })); + const response = (await httpGet(volumeEndpointV2, {headers})); - const volume: IVolume = response.data; + const fee: IFee = response.data; return { - dailyFees: `${volume?.totalTradeFee || undefined}`, + dailyFees: `${fee?.daily_fee || undefined}`, + totalFees: `${fee?.total_fee || undefined}`, timestamp: dayTimestamp, }; }; } - const adapter: SimpleAdapter = { + version: 1, adapter: { - [CHAIN.BASE]: { + ['merlin']: { fetch: fetch(), runAtCurrTime: true, - start: 7963804, + start: 9142115, } }, }; diff --git a/fees/swych/index.ts b/fees/swych/index.ts new file mode 100644 index 0000000000..4fdb7ffc55 --- /dev/null +++ b/fees/swych/index.ts @@ -0,0 +1,138 @@ +import * as sdk from "@defillama/sdk"; +import {Adapter, FetchOptions, FetchResultFees} from "../../adapters/types"; +import { CHAIN } from "../../helpers/chains"; +import axios from "axios"; + +export const SUBGRAPHS = { + pdex: sdk.graph.modifyEndpoint('6tn8tNYxKCEM5bTceMfA5jeGm3gtCrUGDwbKN7QGGat4'), +}; + +const contractAddresses = { + Pool: "0xF86f70fb4959a9FCF1e7dD67A05dC0AC95c3802d", + Oracle: "0xe4460109425EbC1CE34cAd59Ab7ce60535956BF5", +}; + +const event_incress_position = "event IncreasePosition(bytes32 indexed key,address account,address collateralToken,address indexToken,uint256 collateralValue,uint256 sizeChanged,uint8 side,uint256 indexPrice,uint256 feeValue)"; +const event_decrease_position = "event DecreasePosition(bytes32 indexed key,address account,address collateralToken,address indexToken,uint256 collateralChanged,uint256 sizeChanged,uint8 side,uint256 indexPrice,uint256 pnl,uint256 feeValue)"; +const event_liquidate_position = "event LiquidatePosition(bytes32 indexed key,address account,address collateralToken,address indexToken,uint8 side,uint256 size,uint256 collateralValue,uint256 reserveAmount,uint256 indexPrice,uint256 pnl,uint256 feeValue)"; +const event_swap = "event Swap(address indexed sender,address tokenIn,address tokenOut,uint256 amountIn,uint256 amountOut,uint256 fee)"; +interface FeeWithdrawal { + amount: bigint; + id: string; + recipient: string; + timestamp: number; + token: string; +} + +type TIsStable = { + [key: string]: boolean; +} +const isStable:TIsStable = { + "0x55d398326f99059ff775485246999027b3197955": true, + "0xbb4cdb9cbd36b01bd1cbaebf2de08d9173bc095c": false, + "0x7130d2a12b9bcbfae4f2634d864a1ee1ce3ead9c": false, + "0x2170ed0880ac9a755fd29b2688956bd959f933f8": false, + "0x570a5d26f7765ecb712c0924e4de545b89fd43df": false, +} +const OracleABI = { + getPrice: "function getPrice(address token, bool useCache) view returns (uint256)", +}; + +const generateWithdrawalFeesQuery = (timeStart = 0, endTime = 0, skip = 0, limit = 1000) => { + return { + query: ` + { + feeWithdrawals( + first: ${limit} + skip: ${skip} + orderBy: timestamp + orderDirection: asc + where: {timestamp_gt: "${timeStart}" timestamp_lte: "${endTime}"} + ) { + amount + id + recipient + timestamp + token + } + }` + }; +}; + +const fetchWithdrawalFees = async (timestamp: number): Promise => { + const data: FeeWithdrawal[] = []; + const pageSize = 1000; + const startTime = timestamp; + const endTime = timestamp + 24 * 60 * 60; + let hasMoreData = true; + + while (hasMoreData) { + const query = generateWithdrawalFeesQuery(startTime, endTime, data.length, pageSize); + const response = await axios.post(SUBGRAPHS.pdex, query); + const fetchedData: FeeWithdrawal[] = response?.data?.data?.feeWithdrawals; + if (!fetchedData) { + hasMoreData = false; + continue; + } + data.push(...fetchedData); + hasMoreData = fetchedData.length === pageSize; + } + + return data; +}; + +const fetchTotalProtocolRevenue = async (options: FetchOptions) => { + const dailyFees = options.createBalances(); + const logs_incress_position = await options.getLogs({ target: contractAddresses.Pool, eventAbi: event_incress_position }); + const logs_decrease_position = await options.getLogs({ target: contractAddresses.Pool, eventAbi: event_decrease_position }); + const logs_liquidate_position = await options.getLogs({ target: contractAddresses.Pool, eventAbi: event_liquidate_position }); + const logs_swap = await options.getLogs({ target: contractAddresses.Pool, eventAbi: event_swap }); + logs_swap.forEach((log) => { + const fee = Number(log.fee) / 1e30; + dailyFees.addCGToken('tether', fee); + }) + logs_incress_position.forEach((log) => { + const fee = (Number(log.feeValue)/ 1e30) + dailyFees.addCGToken('tether', fee); + }) + logs_decrease_position.forEach((log) => { + const fee = (Number(log.feeValue)/ 1e30) + dailyFees.addCGToken('tether', fee); + }) + logs_liquidate_position.forEach((log) => { + const fee = (Number(log.feeValue)/ 1e30) + dailyFees.addCGToken('tether', fee); + }); + return dailyFees; +}; + +const fetchFees = async (options: FetchOptions) => { + const dailyFees = await fetchTotalProtocolRevenue(options); + const totalWithdrawalFeeData = await fetchWithdrawalFees(options.startOfDay); + const tokenWithdrawalFees = [...new Set(totalWithdrawalFeeData.map((fee) => fee.token))]; + const decimals: string[] = await options.api.multiCall({ abi: 'erc20:decimals', calls: tokenWithdrawalFees}) + totalWithdrawalFeeData.forEach((fee) => { + const index = tokenWithdrawalFees.indexOf(fee.token); + const token_decimal = Number(decimals[index]); + const feeValue = Number(fee.amount)/10 ** (30 - token_decimal) + dailyFees.add(fee.token, feeValue); + }); + return { dailyFees: dailyFees } +}; + +const adapter: Adapter = { + version: 2, + adapter: { + [CHAIN.BSC]: { + fetch: fetchFees, + start: 1701720000, + meta: { + methodology: { + Fees: 'Swych collects fees from different transactions done on the Perpetual Exchange.', + }, + }, + }, + }, +} + +export default adapter diff --git a/fees/synapse/index.ts b/fees/synapse/index.ts index 3c23e7b1d1..43ec3fb765 100644 --- a/fees/synapse/index.ts +++ b/fees/synapse/index.ts @@ -27,7 +27,7 @@ const chains: TChains = { [CHAIN.AURORA]:"aurora", [CHAIN.HARMONY]:"harmony", [CHAIN.CANTO]:"canto", - [CHAIN.DOGECHAIN]:"dogechain", + // [CHAIN.DOGECHAIN]:"dogechain", [CHAIN.BASE]: "base", }; @@ -63,10 +63,20 @@ const query = ` }` +type IRequest = { + [key: string]: Promise; +} +const requests: IRequest = {} + +export async function fetchrequest(url: string, query: string) { + if (!requests[url]) + requests[url] = request(url, query) + return requests[url] +} const graphs = (chain: Chain) => { return async (timestamp: number) => { const dayTimestamp = getUniqStartOfTodayTimestamp(new Date(timestamp * 1000)) - const historical: IHistory[] = (await request(url, query)).dailyStatisticsByChain; + const historical: IHistory[] = (await fetchrequest(url, query)).dailyStatisticsByChain; // const historical: IHistory[] = require('./historical.json'); const historicalVolume = historical const date = new Date(timestamp * 1000); @@ -97,6 +107,7 @@ const methodology = { } const adapter: Adapter = { + version: 1, adapter: Object.keys(chains).reduce((acc, chain: any) => { return { ...acc, diff --git a/fees/synfutures-v3/index.ts b/fees/synfutures-v3/index.ts new file mode 100644 index 0000000000..8701742350 --- /dev/null +++ b/fees/synfutures-v3/index.ts @@ -0,0 +1,113 @@ +import BigNumber from "bignumber.js"; +import { request, gql } from "graphql-request"; +import type { ChainEndpoints, FetchV2, Adapter } from "../../adapters/types" +import { CHAIN } from "../../helpers/chains"; +import { getTimestampAtStartOfDayUTC } from "../../utils/date"; + +const endpoints = { + [CHAIN.BLAST]: "https://api.synfutures.com/thegraph/v3-blast", + [CHAIN.BASE]: "https://api.synfutures.com/thegraph/v3-base", +} + +// Fee = LiquidityFee + ProtocolFee +// LiquidityFee = MakerRebates + FeesToLP +const methodology = { + Fees: "fees paid by takers on the protocol by using market orders, these fees paid goes to limit order makers, AMM LP and protocol fees", + MakerRebates: "fees rebated received by limit order makers on the protocol, these fees are paid by takers", + FeesToLp: "fees received by AMM LPs on the protocol, these fees are paid by takers", + ProcotolFees: "fees received by the protocol from takers, these fees are paid by takers" +} + +function convertDecimals(value: string | number, decimals: number) { + if (decimals > 18) { + return new BigNumber(value).multipliedBy(10 ** (decimals - 18)).toString(); + } else if (decimals < 18) { + return new BigNumber(value).dividedToIntegerBy(10 ** (18 - decimals)).toString(); + } else { + return value; + } +} + +const graphs = (graphUrls: ChainEndpoints) => { + const fetch: FetchV2 = async ({ chain, startTimestamp, createBalances }) => { + const todaysTimestamp = getTimestampAtStartOfDayUTC(startTimestamp) + const graphQuery = gql + `{ + dailyQuoteDatas(where: {timestamp: "${todaysTimestamp}"}){ + timestamp + quote{ + id + symbol + decimals + } + liquidityFee + poolFee + protocolFee + + totalLiquidityFee + totalPoolFee + totalProtocolFee + } + }`; + + const dailyFee = createBalances(); + const dailyMakerRebates = createBalances(); + const dailyFeesToLP = createBalances(); + const dailyProcotolFees = createBalances(); + + const totalFee = createBalances(); + const totalMakerRebates = createBalances(); + const totalFeesToLP = createBalances(); + const totalProcotolFees = createBalances(); + + const graphRes = await request(graphUrls[chain], graphQuery); + + for (const record of graphRes.dailyQuoteDatas) { + dailyFee.addToken(record.quote.id, convertDecimals(Number(record.liquidityFee) + Number(record.protocolFee), record.quote.decimals)) + dailyMakerRebates.addToken(record.quote.id, convertDecimals(Number(record.liquidityFee) - Number(record.poolFee), record.quote.decimals)) + dailyFeesToLP.addToken(record.quote.id, convertDecimals(Number(record.poolFee), record.quote.decimals)) + dailyProcotolFees.addToken(record.quote.id, convertDecimals(Number(record.protocolFee), record.quote.decimals)) + + totalFee.addToken(record.quote.id, convertDecimals(Number(record.totalLiquidityFee) + Number(record.totalProtocolFee), record.quote.decimals)) + totalMakerRebates.addToken(record.quote.id, convertDecimals(Number(record.totalLiquidityFee) - Number(record.totalPoolFee), record.quote.decimals)) + totalFeesToLP.addToken(record.quote.id, convertDecimals(Number(record.totalPoolFee), record.quote.decimals)) + totalProcotolFees.addToken(record.quote.id, convertDecimals(Number(record.totalProtocolFee), record.quote.decimals)) + } + + return { + dailyFees: await dailyFee.getUSDValue(), + dailyMakerRebates: await dailyMakerRebates.getUSDValue(), + dailyFeesToLp: await dailyFeesToLP.getUSDValue(), + dailyProcotolFees: await dailyProcotolFees.getUSDValue(), + + totalFees: await totalFee.getUSDValue(), + totalMakerRebates: await totalMakerRebates.getUSDValue(), + totalFeesToLp: await totalFeesToLP.getUSDValue(), + totalProcotolFees: await totalProcotolFees.getUSDValue() + }; + }; + return fetch +}; + + +const adapter: Adapter = { + version: 2, + adapter: { + [CHAIN.BLAST]: { + fetch: graphs(endpoints), + start: 1709049600, + meta: { + methodology + } + }, + [CHAIN.BASE]: { + fetch: graphs(endpoints), + start: 1719383967, + meta: { + methodology + } + } + } +} + +export default adapter; diff --git a/fees/synthetix-v3.ts b/fees/synthetix-v3.ts new file mode 100644 index 0000000000..93107239e5 --- /dev/null +++ b/fees/synthetix-v3.ts @@ -0,0 +1,46 @@ +import { ChainBlocks, FetchOptions, SimpleAdapter } from "../adapters/types"; +import { CHAIN } from "../helpers/chains"; + +const contract_address = '0x0a2af931effd34b81ebcc57e3d3c9b1e1de1c9ce'; +const usdt = 'tether' +const event_order_settled = 'event OrderSettled(uint128 indexed marketId,uint128 indexed accountId,uint256 fillPrice,int256 pnl,int256 accruedFunding,int128 sizeDelta,int128 newSize,uint256 totalFees,uint256 referralFees,uint256 collectedFees,uint256 settlementReward,bytes32 indexed trackingCode,address settler)' +const fetchFees = async (timestamp: number, _: ChainBlocks, options: FetchOptions) => { + const dailyFees = options.createBalances(); + const dailyRevenue = options.createBalances(); + const dailyHoldersRevenue = options.createBalances(); + const dailySupplySideRevenue = options.createBalances(); + const logs = await options.getLogs({ + target: contract_address, + eventAbi: event_order_settled + }); + + logs.forEach((log: any) => { + const totalFees = Number(log.totalFees) + const collectedFees = Number(log.collectedFees) + const referralFees = Number(log.referralFees) + const settlementReward = Number(log.settlementReward) + dailyFees.addCGToken(usdt, totalFees/1e18) + dailyRevenue.addCGToken(usdt, collectedFees/1e18) + dailyHoldersRevenue.addCGToken(usdt, collectedFees/1e18) + const supplySideRevenue = Number(totalFees) - Number(collectedFees) - Number(referralFees) - Number(settlementReward) + dailySupplySideRevenue.addCGToken(usdt, supplySideRevenue/1e18) + }); + + return { + dailyFees: dailyFees, + dailyRevenue: dailyRevenue, + dailyHoldersRevenue: dailyHoldersRevenue, + dailySupplySideRevenue: dailySupplySideRevenue, + timestamp + } +} + +const adapters: SimpleAdapter = { + adapter: { + [CHAIN.BASE]: { + fetch: fetchFees, + start: 1705104000, + }, + } +} +export default adapters diff --git a/fees/synthetix.ts b/fees/synthetix.ts index bbe51c4eb7..eb26ead658 100644 --- a/fees/synthetix.ts +++ b/fees/synthetix.ts @@ -1,5 +1,5 @@ import ADDRESSES from '../helpers/coreAssets.json' -import { Adapter, ChainBlocks, FetchOptions } from "../adapters/types"; +import { Adapter, FetchOptions } from "../adapters/types"; import { CHAIN } from "../helpers/chains"; import { Chain } from '@defillama/sdk/build/general'; import { addTokensReceived } from '../helpers/token'; @@ -20,12 +20,11 @@ const contract_address: IContract = { [CHAIN.OPTIMISM]: ADDRESSES.optimism.sUSD } const graphs = (chain: Chain) => { - return async (timestamp: number, _: ChainBlocks, options: FetchOptions) => { + return async (options: FetchOptions) => { const token = contract_address[chain] const dailyFee = await addTokensReceived({ tokens: [token], options, target: '0xfeefeefeefeefeefeefeefeefeefeefeefeefeef' }) return { - timestamp, dailyUserFees: dailyFee, dailyFees: dailyFee, dailyRevenue: dailyFee, @@ -36,6 +35,7 @@ const graphs = (chain: Chain) => { const adapter: Adapter = { + version: 2, adapter: { [CHAIN.ETHEREUM]: { fetch: graphs(CHAIN.ETHEREUM), diff --git a/fees/tangible-rwa.ts b/fees/tangible-rwa.ts index a0efff8ac3..19b4039dd2 100644 --- a/fees/tangible-rwa.ts +++ b/fees/tangible-rwa.ts @@ -1,27 +1,24 @@ import ADDRESSES from '../helpers/coreAssets.json' -import { ChainBlocks, FetchOptions, FetchResultFees, SimpleAdapter } from "../adapters/types"; +import { FetchOptions, SimpleAdapter } from "../adapters/types"; import { CHAIN } from "../helpers/chains" import { addTokensReceived } from '../helpers/token'; - -const fetchFees = async (timestamp: number, _: ChainBlocks, options: FetchOptions): Promise => { +const fetchFees = async (options: FetchOptions) => { const fromAdddesses = [ '0x43e656716cf49c008435a8196d8f825f66f37254', '0xcb7daa45ed2a9253ad3c900583b33bed822e8283', '0x49c7371daecb7f06fc7303a14ab80174453df4cf', ]; const dailyFees = options.createBalances() - for (const fromAdddress of fromAdddesses) { - await addTokensReceived({ options, target: '0x6ceD48EfBb581A141667D7487222E42a3FA17cf7', fromAddressFilter: fromAdddress, balances: dailyFees, tokens: [ADDRESSES.polygon.USDC] }) - } + await addTokensReceived({ options, target: '0x6ceD48EfBb581A141667D7487222E42a3FA17cf7', fromAdddesses: fromAdddesses, balances: dailyFees, tokens: [ADDRESSES.polygon.USDC] }) return { dailyFees: dailyFees, dailyRevenue: dailyFees, - timestamp } } const adapter: SimpleAdapter = { + version: 2, adapter: { [CHAIN.POLYGON]: { fetch: fetchFees, diff --git a/fees/tether.ts b/fees/tether.ts new file mode 100644 index 0000000000..b6205798b8 --- /dev/null +++ b/fees/tether.ts @@ -0,0 +1,29 @@ +import { Adapter, FetchOptions } from "../adapters/types"; + +const adapter: Adapter = { + version: 2, + adapter: { + ethereum: { + fetch: async ({ fromTimestamp, createBalances }: FetchOptions) => { + const dailyFees = createBalances() + + // Based on https://tether.to/en/transparency/?tab=reports + if(fromTimestamp > 1719709261){ + let annualYield = 0 + // per the last report, there's: + annualYield += 80948e6*5.287/100 // 80.9bn in treasury bills with a maturity of less tham 90d, so picking the lowest yield between 1/2/3 mo treasurys + annualYield += 11.2e9*5.35/100 // 11.2bn in repos, which should be earning SOFR + dailyFees.addCGToken("tether", annualYield/365) + } + + return { + dailyFees, + dailyRevenue: dailyFees + } + }, + start: 0 + } + } +} + +export default adapter; \ No newline at end of file diff --git a/fees/thalaswap.ts b/fees/thalaswap.ts index 2ea9461d44..be77129522 100644 --- a/fees/thalaswap.ts +++ b/fees/thalaswap.ts @@ -1,33 +1,37 @@ import fetchURL from "../utils/fetchURL"; import { SimpleAdapter } from "../adapters/types"; import { CHAIN } from "../helpers/chains"; -import { getUniqStartOfTodayTimestamp } from "../helpers/getUniSubgraphVolume"; -const thalaDappURL = 'https://app.thala.fi/'; -const volumeQueryURL = `${thalaDappURL}/api/trading-volume-chart?timeframe=`; -const feesQueryURL = `${thalaDappURL}/api/trading-fee-chart?timeframe=`; -const protocolRatioQueryURL = `${thalaDappURL}/api/protocol-revenue-ratio`; +const thalaDappURL = "https://app.thala.fi"; +const feesQueryURL = `${thalaDappURL}/api/defillama/trading-fee-chart?timeframe=`; +const protocolRatioQueryURL = `${thalaDappURL}/api/defillama/protocol-revenue-ratio`; -const feesEndpoint = (startTimestamp: number, timeframe: string) => -startTimestamp ? feesQueryURL + timeframe + `&startTimestamp=${startTimestamp}` : feesQueryURL + timeframe; - -const historicalEndpoint = "https://app.thala.fi/api/trading-fee-chart"; interface IVolumeall { value: number; timestamp: string; } -const fetch = async (timestamp: number) => { - const dayTime = getUniqStartOfTodayTimestamp(new Date(timestamp * 1000)); - const dayFeesQuery = (await fetchURL(historicalEndpoint))?.data; - const dailyFees = dayFeesQuery.find((a:IVolumeall) => Number(a.timestamp) === dayTime)?.value; - - const totalFeesQuery = (await fetchURL(feesEndpoint(0, "ALL")))?.data; - const totalFees = totalFeesQuery.reduce((partialSum: number, a: IVolumeall) => partialSum + a.value, 0); +const feesEndpoint = (endTimestamp: number, timeframe: string) => + endTimestamp + ? feesQueryURL + timeframe + `&endTimestamp=${endTimestamp}` + : feesQueryURL + timeframe; - const protocolFeeRatio = (await fetchURL(protocolRatioQueryURL))?.data; - const dailyProtocolRevenue = dailyFees * protocolFeeRatio; - const totalProtocolRevenue = totalFees * protocolFeeRatio; +const fetch = async (timestamp: number) => { + const dayFeesQuery = (await fetchURL(feesEndpoint(timestamp, "1D")))?.data; + const dailyFees = dayFeesQuery.reduce( + (partialSum: number, a: IVolumeall) => partialSum + a.value, + 0 + ); + + const totalFeesQuery = (await fetchURL(feesEndpoint(0, "ALL")))?.data; + const totalFees = totalFeesQuery.reduce( + (partialSum: number, a: IVolumeall) => partialSum + a.value, + 0 + ); + + const protocolFeeRatio = (await fetchURL(protocolRatioQueryURL))?.data; + const dailyProtocolRevenue = dailyFees * protocolFeeRatio; + const totalProtocolRevenue = totalFees * protocolFeeRatio; return { totalFees: `${totalFees}`, @@ -38,12 +42,11 @@ const fetch = async (timestamp: number) => { }; }; - const adapter: SimpleAdapter = { adapter: { [CHAIN.APTOS]: { fetch, - start: 1680480000 + start: async () => 1680480000, }, }, }; diff --git a/fees/thegraph.ts b/fees/thegraph.ts new file mode 100644 index 0000000000..25b83b3e80 --- /dev/null +++ b/fees/thegraph.ts @@ -0,0 +1,25 @@ +import { Adapter, FetchOptions, } from "../adapters/types"; +import { CHAIN } from "../helpers/chains"; + +const adapter: Adapter = { + version: 2, + adapter: { + [CHAIN.ARBITRUM]: { + fetch: (async (options: FetchOptions) => { + const dailyFees = options.createBalances(); + const logs = await options.getLogs({ + targets: ['0x1B07D3344188908Fb6DEcEac381f3eE63C48477a'], + eventAbi: "event TokensPulled(address indexed user,uint256 amount)", + }) + logs.map((tx: any) => { + dailyFees.add("0x9623063377ad1b27544c965ccd7342f7ea7e88c7", tx.amount) + }) + return { dailyFees, dailyRevenue: dailyFees, } + }) as any, + start: 0 + }, + }, + +} + +export default adapter; diff --git a/fees/thena-perp.ts b/fees/thena-perp.ts index cdde02246d..2224e2dfdf 100644 --- a/fees/thena-perp.ts +++ b/fees/thena-perp.ts @@ -1,3 +1,4 @@ +import * as sdk from "@defillama/sdk"; import request, { gql } from "graphql-request"; import { CHAIN } from "../helpers/chains"; import BigNumber from "bignumber.js"; @@ -6,7 +7,7 @@ import { FetchResultFees, SimpleAdapter } from "../adapters/types"; const ONE_DAY_IN_SECONDS = 60 * 60 * 24 -const endpoint = "https://api.thegraph.com/subgraphs/name/navid-fkh/symmetrical_bsc" +const endpoint = sdk.graph.modifyEndpoint('79T7bT3tnBWmFPukyDdEY4mqHWrYTaJtzgoz6ufzC9xN') const query = gql` query stats($from: String!, $to: String!) { diff --git a/fees/thena.ts b/fees/thena-v1.ts similarity index 95% rename from fees/thena.ts rename to fees/thena-v1.ts index f763f00b12..455a58a5c4 100644 --- a/fees/thena.ts +++ b/fees/thena-v1.ts @@ -1,3 +1,4 @@ +import * as sdk from "@defillama/sdk"; import request, { gql } from "graphql-request"; import { Adapter, FetchResultFees } from "../adapters/types"; import { getBlock } from "../helpers/getBlock"; @@ -11,7 +12,7 @@ import { CHAIN } from "../helpers/chains"; const STABLE_FEES = 0.0001; const VOLATILE_FEES = 0.002; const endpoint = - "https://api.thegraph.com/subgraphs/name/thenaursa/thena-v1"; + sdk.graph.modifyEndpoint('FKEt2N5VmSdEYcz7fYLPvvnyEUkReQ7rvmXzs6tiKCz1'); const getFees = () => { return async (timestamp: number): Promise => { diff --git a/fees/thena-v3.ts b/fees/thena-v3.ts index 7c0224307e..8aa7903695 100644 --- a/fees/thena-v3.ts +++ b/fees/thena-v3.ts @@ -1,3 +1,4 @@ +import * as sdk from "@defillama/sdk"; import { Chain } from "@defillama/sdk/build/general"; import BigNumber from "bignumber.js"; import request, { gql } from "graphql-request"; @@ -16,7 +17,7 @@ type IURL = { } const endpoints: IURL = { - [CHAIN.BSC]: "https://api.thegraph.com/subgraphs/name/thenaursa/thena-fusion" + [CHAIN.BSC]: sdk.graph.modifyEndpoint('Hnjf3ipVMCkQze3jmHp8tpSMgPmtPnXBR38iM4ix1cLt') } const fetch = (chain: Chain) => { diff --git a/fees/thick.ts b/fees/thick.ts index 2151594dc7..5c64c86c79 100644 --- a/fees/thick.ts +++ b/fees/thick.ts @@ -1,6 +1,6 @@ import { SimpleAdapter } from "../adapters/types"; import { CHAIN } from "../helpers/chains"; -import { getDexFeesExportsV3 } from "../helpers/dexVolumeLogs"; +import { uniV3Exports } from "../helpers/uniswap"; const poolFactoryAddress = '0xE6dA85feb3B4E0d6AEd95c41a125fba859bB9d24'; @@ -13,24 +13,14 @@ const methodology = { SupplySideRevenue: "The portion of trading fees paid to liquidity providers." } -const adapters: SimpleAdapter = { - adapter: { - [CHAIN.FANTOM]: { - fetch: getDexFeesExportsV3({ chain: CHAIN.FANTOM, factory: poolFactoryAddress, factoryFromBlock: 70309749}), - start: 1699300000, - meta: { methodology: { ...methodology, } }, - }, - [CHAIN.ARBITRUM]: { - fetch: getDexFeesExportsV3({ chain: CHAIN.ARBITRUM, factory: poolFactoryAddress, factoryFromBlock: 148243463}), - start: 1699300000, - meta: { methodology: { ...methodology, } }, - }, - [CHAIN.BASE]: { - fetch: getDexFeesExportsV3({ chain: CHAIN.BASE, factory: poolFactoryAddress, factoryFromBlock: 6314325}), - start: 1699300000, - meta: { methodology: { ...methodology, } }, - } - } -} +const adapters: SimpleAdapter = uniV3Exports({ + [CHAIN.FANTOM]: { factory: poolFactoryAddress, }, + [CHAIN.ARBITRUM]: { factory: poolFactoryAddress, }, + [CHAIN.BASE]: { factory: poolFactoryAddress, }, +}) + +Object.keys(adapters.adapter).forEach((chain: any) => { + adapters.adapter[chain].meta = { methodology } +}) export default adapters; diff --git a/fees/thorswap/index.ts b/fees/thorswap/index.ts index 783fff94e1..8f4985197b 100644 --- a/fees/thorswap/index.ts +++ b/fees/thorswap/index.ts @@ -45,8 +45,8 @@ interface IEarning { const fetchFees = async (timestamp: number): Promise => { const dayTimestamp = getUniqStartOfTodayTimestamp(new Date(timestamp * 1000)) - const url1 = "https://api.flipsidecrypto.com/api/v2/queries/1d13d4a1-d073-4a73-a46b-d7aadf060672/data/latest" - const url2 = "https://api.flipsidecrypto.com/api/v2/queries/46dc4fa4-a362-420e-97ec-d3a58d46b9e7/data/latest" + const url1 = "https://flipsidecrypto.xyz/api/v1/queries/9ed4f699-100a-41e5-a3e6-a7f9ed3bfd5c/data/latest" + const url2 = "https://flipsidecrypto.xyz/api/v1/queries/40798a6b-1e67-4ecb-b8b3-8f8354b5798a/data/latest" const url3 = `https://midgard.ninerealms.com/v2/history/earnings?interval=day&count=400` const [reveune, fees, earnings]: any = (await Promise.all([ httpGet(url1), @@ -62,11 +62,11 @@ const fetchFees = async (timestamp: number): Promise => { const dailyRevenueData: IRevenue = reveuneData.find(item => item.DAY.split(" ")[0] === dayTimestampStr) as IRevenue const dailyFeesData: IFees = feesData.find(item => item.DAY.split(" ")[0] === dayTimestampStr) as IFees const dailyErningData: IEarning = earningData.find(item => Number(item.startTime) === dayTimestamp) as IEarning - const dailyFees = dailyRevenueData.REVENUE; + const dailyFees = Number(dailyRevenueData.REVENUE) * Number(dailyErningData.runePriceUSD); const dailyUsersFees = dailyFeesData?.LIQUIDITY_FEES || 0 + dailyRevenueData?.OUTBOUND_FEE || 0; - const dailyRevenue = dailyRevenueData.REVENUE; - const dailyProtocolRev = dailyRevenueData.REVENUE; - const dailyHoldersRevenue = (Number(dailyErningData.bondingEarnings) / 1e8) * Number(dailyErningData.runePriceUSD); + const dailyRevenue = Number(dailyRevenueData.REVENUE) * Number(dailyErningData.runePriceUSD); + const dailyProtocolRev = Number(dailyRevenueData.REVENUE) * Number(dailyErningData.runePriceUSD); + const dailyHoldersRevenue = (Number(dailyErningData.bondingEarnings) / 1e8) *Number(dailyErningData.runePriceUSD); const dailySupplySideRevenue = dailyHoldersRevenue @@ -81,12 +81,15 @@ const fetchFees = async (timestamp: number): Promise => { } } const adapters: SimpleAdapter = { + version: 1, adapter: { [CHAIN.THORCHAIN]: { + runAtCurrTime: true, fetch: fetchFees, start: 1618099200, } - } + }, + isExpensiveAdapter: true } export default adapters diff --git a/fees/tigris/index.ts b/fees/tigris/index.ts index cd62324728..70804e60e0 100644 --- a/fees/tigris/index.ts +++ b/fees/tigris/index.ts @@ -68,6 +68,7 @@ const fetch = (chain: Chain) => { } const adapter: Adapter = { + version: 1, adapter: { [CHAIN.ARBITRUM]: { fetch: fetch(CHAIN.ARBITRUM), diff --git a/fees/time-fun.ts b/fees/time-fun.ts new file mode 100644 index 0000000000..5df81eb1d4 --- /dev/null +++ b/fees/time-fun.ts @@ -0,0 +1,15 @@ +import { Adapter,} from "../adapters/types"; +import { getFeesExport } from "../helpers/time-fun"; +import { CHAIN } from "../helpers/chains"; + +const adapter: Adapter = { + adapter: { + [CHAIN.BASE]: { + fetch: getFeesExport('0x428aeF7fB31E4E86162D62d4530a4dd7232D953D'), + start: 1718288800, + }, + }, + version: 2, +} + +export default adapter; diff --git a/fees/tlx-finance/index.ts b/fees/tlx-finance/index.ts new file mode 100644 index 0000000000..1923b5b788 --- /dev/null +++ b/fees/tlx-finance/index.ts @@ -0,0 +1,35 @@ +import { Adapter, FetchOptions } from "../../adapters/types"; +import { OPTIMISM } from "../../helpers/chains"; + +const STAKER = "0xc30877315f3b621a8f7bcda27819ec29429f3817"; +const DONATE_EVENT = "event DonatedRewards(address indexed account, uint256 amount)"; +const token = "0x8c6f28f2F1A3C87F0f938b96d27520d9751ec8d9" + +const getFees = async (options: FetchOptions) => { + const { getLogs } = options; + const logs = await getLogs({ + targets: [STAKER], + eventAbi: DONATE_EVENT, + }); + const dailyFees = options.createBalances(); + logs.forEach((log) => { + dailyFees.add(token, log.amount); + }) + + return { + dailyFees: dailyFees, + dailyRevenue: dailyFees, + dailyHoldersRevenue: dailyFees, + }; +}; + +const adapter: Adapter = { + version: 2, + adapter: { + [OPTIMISM]: { + fetch: getFees, + start: 1712727843, + }, + }, +}; +export default adapter; diff --git a/fees/tna.ts b/fees/tna.ts new file mode 100644 index 0000000000..6143f36960 --- /dev/null +++ b/fees/tna.ts @@ -0,0 +1,37 @@ +import { Adapter, FetchOptions, } from "../adapters/types"; +import { CHAIN } from "../helpers/chains"; + +const abi_event = { + nameRegistered: "event Register(address indexed owner,uint256 indexed rootId,uint256 indexed tokenId,uint256 fee,bytes fullName)", +}; + +const methodology = { + Fees: "registration and renew cost", + Revenue: "registration and renew cost", +} + +const adapter: Adapter = { + version: 2, + adapter: { + [CHAIN.BITLAYER]: { + fetch: (async (options: FetchOptions) => { + const dailyFees = options.createBalances(); + const registeredLogs = await options.getLogs({ + targets: ['0x048d86f26952aB5e1F601f897BC9512A1E7fA675'], + eventAbi: abi_event.nameRegistered, + }) + registeredLogs.map((tx: any) => { + dailyFees.addGasToken(tx.fee) + }) + return { dailyFees, dailyRevenue: dailyFees, } + }) as any, + start: 1677110400, + meta: { + methodology + } + }, + }, + +} + +export default adapter; diff --git a/fees/torch/index.ts b/fees/torch/index.ts new file mode 100644 index 0000000000..d97564ff72 --- /dev/null +++ b/fees/torch/index.ts @@ -0,0 +1,34 @@ +import { FetchResultV2 } from '../../adapters/types' +import { CHAIN } from '../../helpers/chains' +import fetchURL, { postURL } from '../../utils/fetchURL' + +const fetchFees = async (): Promise => { + const dailyFeesResult = await fetchURL( + 'https://api.torch.finance/stats/daily-fees', + ) + + return { + dailyFees: dailyFeesResult.dailyUserFees, + dailyUserFees: dailyFeesResult.dailyUserFees, + dailyRevenue: dailyFeesResult.dailyRevenue, + dailySupplySideRevenue: dailyFeesResult.dailySupplySideRevenue + } +} + +export default { + version: 2, + adapter: { + [CHAIN.TON]: { + start: 1700000000, + meta: { + methodology: { + UserFees: 'User pays fee on each swap (depends on pool, 0.1% - 1%).', + Revenue: 'Protocol receives 50% of fees.', + SupplySideRevenue: + '50% of user fees are paid to liquidity providers, increasing the pool size.', + }, + }, + fetch: fetchFees, + }, + }, +} diff --git a/fees/toros/index.ts b/fees/toros/index.ts new file mode 100644 index 0000000000..8580648d68 --- /dev/null +++ b/fees/toros/index.ts @@ -0,0 +1,112 @@ +import { FetchOptions, SimpleAdapter } from "../../adapters/types"; +import { CHAIN } from "../../helpers/chains"; +import { GraphQLClient } from "graphql-request"; +const query = ` + query managerFeeMinteds($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, tokenPriceAtLastFeeMint } + }` + +// if graph goes down, can be pulled via event logs, example: +// https://optimistic.etherscan.io/tx/0x265e1eeb9a2c68ef8f58fe5e1d7e3f1151dd5e6686d4147445bf1bd8895deb38#eventlog check topic: 0x755a8059d66d8d243bc9f6913f429a811f154599d0538bb0b6a2ac23f23d2ccd +/* const fetch = async ({ chain, createBalances, getLogs }: FetchOptions) => { + let torosManagerAddress = CONFIG[chain].torosManagerAddress.toLowerCase(); + const dailyFees = createBalances(); + const logs = await getLogs({ + eventAbi: 'event ManagerFeeMinted (address pool, address manager, uint256 available, uint256 daoFee, uint256 managerFee, uint256 tokenPriceAtLastFeeMint)', + }); + logs.forEach(i => { + if (i.manager.toLowerCase() !== torosManagerAddress) return; + dailyFees.addUSDValue(i.daoFee.toString() * i.tokenPriceAtLastFeeMint.toString() / 1e36) + }); + + return { dailyFees, dailyRevenue: dailyFees }; +} */ +const CONFIG = { + [CHAIN.OPTIMISM]: { + endpoint: "https://api.studio.thegraph.com/query/48129/dhedge-v2-optimism/version/latest", + torosManagerAddress: "0x813123a13d01d3f07d434673fdc89cbba523f14d", + }, + [CHAIN.POLYGON]: { + endpoint: "https://api.studio.thegraph.com/query/48129/dhedge-v2-polygon/version/latest", + torosManagerAddress: "0x090e7fbd87a673ee3d0b6ccacf0e1d94fb90da59", + }, + [CHAIN.ARBITRUM]: { + endpoint: "https://api.studio.thegraph.com/query/48129/dhedge-v2-arbitrum/version/latest", + torosManagerAddress: "0xfbd2b4216f422dc1eee1cff4fb64b726f099def5", + }, + [CHAIN.BASE]: { + startTimestamp: 1712227101, + endpoint: "https://api.studio.thegraph.com/query/48129/dhedge-v2-base-mainnet/version/latest", + torosManagerAddress: "0x5619ad05b0253a7e647bd2e4c01c7f40ceab0879", + }, +}; + +const fetchHistoricalFees = async (chainId: CHAIN, managerAddress: string, startTimestamp: number, endTimestamp: number) => { + const { endpoint, } = CONFIG[chainId]; + + let allData = []; + let skip = 0; + const batchSize = 1000; + + while (true) { + try { + const data = await new GraphQLClient(endpoint).request(query, { + manager: managerAddress, + startTimestamp: startTimestamp.toString(), + endTimestamp: endTimestamp.toString(), + first: batchSize, + skip + }); + + const entries = data.managerFeeMinteds + 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 calculateFees = (data: any): number => + data.reduce((acc: number, item: any) => { + const managerFee = Number(item.managerFee); + const tokenPrice = Number(item.tokenPriceAtLastFeeMint); + const managerFeeFormatted = managerFee / 1e18; + const tokenPriceFormatted = tokenPrice / 1e18; + const managerFeeUsd = managerFeeFormatted * tokenPriceFormatted; + return acc + managerFeeUsd; + }, 0); + +const fetch = async ({ chain, endTimestamp, startTimestamp }: FetchOptions) => { + const config = CONFIG[chain]; + if (!config) throw new Error(`Unsupported chain: ${chain}`); + + const dailyFees = await fetchHistoricalFees(chain as CHAIN, config.torosManagerAddress, startTimestamp, endTimestamp) + + return { + dailyFees: calculateFees(dailyFees), + dailyRevenue: calculateFees(dailyFees), + timestamp: endTimestamp, + }; +} + +const adapter: SimpleAdapter = { + adapter: { + [CHAIN.OPTIMISM]: { fetch, start: 1638446653, }, + [CHAIN.POLYGON]: { fetch, start: 1627560253, }, + [CHAIN.ARBITRUM]: { fetch, start: 1679918653, }, + [CHAIN.BASE]: { fetch, start: 1703073853, }, + }, + version: 2 +} + +export default adapter; diff --git a/fees/touch.fan.ts b/fees/touch.fan.ts index 6aaf4cdd1d..316f2d2b12 100644 --- a/fees/touch.fan.ts +++ b/fees/touch.fan.ts @@ -24,7 +24,8 @@ const adapter: Adapter = { fetch: fetch, start: 1698494400, }, - } + }, + version: 2, } export default adapter; \ No newline at end of file diff --git a/fees/traderjoe.ts b/fees/traderjoe.ts index a16ec7eabf..706614fb7f 100644 --- a/fees/traderjoe.ts +++ b/fees/traderjoe.ts @@ -1,10 +1,9 @@ -import { getDexChainFees, getUniqStartOfTodayTimestamp } from "../helpers/getUniSubgraphFees"; -import volumeAdapter from "../dexs/traderjoe"; -import { Adapter, FetchResultFees } from "../adapters/types"; +import { Adapter, FetchOptions } from "../adapters/types"; import { Chain } from "@defillama/sdk/build/general"; import { CHAIN } from "../helpers/chains"; -import fetchURL from "../utils/fetchURL"; - +import { httpGet } from "../utils/fetchURL"; +import * as sdk from "@defillama/sdk"; +import { getChainVolume } from "../helpers/getUniSubgraphVolume"; const TOTAL_FEES = 0.003; const LP_FEE = 0.0025; @@ -19,61 +18,130 @@ interface IData { type TEndpoint = { [s: string | Chain]: string; -} +}; const endpointsV2: TEndpoint = { - [CHAIN.AVAX]: "https://barn.traderjoexyz.com/v1/dex/analytics/avalanche?startTime=1669420800&aggregateBy=daily", - [CHAIN.ARBITRUM]: "https://barn.traderjoexyz.com/v1/dex/analytics/arbitrum?startTime=1672012800&aggregateBy=daily", - [CHAIN.BSC]: "https://barn.traderjoexyz.com/v1/dex/analytics/binance?startTime=1677801600&aggregateBy=daily" -} + [CHAIN.AVAX]: + "https://barn.traderjoexyz.com/v1/dex/analytics/avalanche?startTime=1669420800&aggregateBy=daily", + [CHAIN.ARBITRUM]: + "https://barn.traderjoexyz.com/v1/dex/analytics/arbitrum?startTime=1672012800&aggregateBy=daily", + [CHAIN.BSC]: + "https://barn.traderjoexyz.com/v1/dex/analytics/binance?startTime=1677801600&aggregateBy=daily", + [CHAIN.ETHEREUM]: + "https://barn.traderjoexyz.com/v1/dex/analytics/ethereum?startTime=1695513600&aggregateBy=daily", +}; -const adapterV1 = getDexChainFees({ - totalFees: TOTAL_FEES, - protocolFees: PROTOCOL_FEES, - revenue: PROTOCOL_FEES, - supplySideRevenue: LP_FEE, - holdersRevenue: HOLDER_REV, - volumeAdapter: {adapter: volumeAdapter.breakdown.v1} -}); +const endpoints = { + [CHAIN.AVAX]: sdk.graph.modifyEndpoint('9ZjERoA7jGANYNz1YNuFMBt11fK44krveEhzssJTWokM'), + [CHAIN.BSC]: sdk.graph.modifyEndpoint('3VgCBQh13PseR81hPNAbKua3gD8b8r33LauKjVnMbSAs'), + [CHAIN.ARBITRUM]: sdk.graph.modifyEndpoint('3jFnXqk6UXZyciPu5jfUuPR7kzGXPSndsLNrWXQ6xAxk'), +}; -const graph = (chain: Chain) => { - return async (timestamp: number): Promise => { - const dayTimestamp = getUniqStartOfTodayTimestamp(new Date(timestamp * 1000)) - const historical: IData[] = (await fetchURL(endpointsV2[chain])); - const dailyFees = historical - .find(dayItem => dayItem.timestamp === dayTimestamp)?.feesUsd - const dailyRevenue = historical - .find(dayItem => dayItem.timestamp === dayTimestamp)?.protocolFeesUsd +const graphsV1 = getChainVolume({ + graphUrls: endpoints, + totalVolume: { + factory: "factories", + field: "volumeUSD", + }, +}); +const graph = async (_t: any, _tt: any, options: FetchOptions) => { + const dayTimestamp = options.startOfDay; + const start = options.startOfDay; + const end = start + 24 * 60 * 60; + const url = `https://api.traderjoexyz.dev/v1/dex/analytics/${mapChain(options.chain)}?startTime=${start}&endTime=${end}` + const historical: IData[] = (await httpGet(url, { headers: { + 'x-traderjoe-api-key': process.env.TRADERJOE_API_KEY + }})); + const dailyFees = + historical.find((dayItem) => dayItem.timestamp === dayTimestamp) + ?.feesUsd || 0; + const dailyRevenue = + historical.find((dayItem) => dayItem.timestamp === dayTimestamp) + ?.protocolFeesUsd || 0; return { dailyUserFees: `${dailyFees}`, dailyFees: `${dailyFees}`, dailyRevenue: `${dailyRevenue}`, dailyHoldersRevenue: `${dailyRevenue}`, - dailySupplySideRevenue: dailyFees ? `${(dailyFees || 0) - (dailyRevenue || 0)}` : undefined, + dailySupplySideRevenue: dailyFees + ? `${(dailyFees || 0) - (dailyRevenue || 0)}` + : undefined, dailyProtocolRevenue: `${dailyRevenue}`, - timestamp - } - } -} + timestamp: options.startOfDay, + }; +}; + +const mapChain = (chain: Chain): string => { + if (chain === CHAIN.BSC) return "binance"; + if (chain === CHAIN.AVAX) return "avalanche"; + return chain; +}; const adapter: Adapter = { + version: 1, breakdown: { - v1: adapterV1, + v1: { + [CHAIN.ARBITRUM]: { + fetch: async (_t: any, _tt: any, options: FetchOptions) => { + const data = await graphsV1(CHAIN.ARBITRUM)(_t, _tt, options); + return { + dailyFees: data.dailyVolume ? `${Number(data.dailyVolume) * TOTAL_FEES}` : "0", + dailyUserFees: data.dailyVolume ? `${Number(data.dailyVolume) * TOTAL_FEES}` : "0", + dailyRevenue: data.dailyVolume ? `${Number(data.dailyVolume) * PROTOCOL_FEES}` : "0", + dailyHoldersRevenue: data.dailyVolume ? `${Number(data.dailyVolume) * HOLDER_REV}` : "0", + dailySupplySideRevenue: data.dailyVolume ? `${Number(data.dailyVolume) * LP_FEE}` : "0", + timestamp: options.startOfDay, + }; + }, + start: 1672012800, + }, + [CHAIN.BSC]: { + fetch: async (_t: any, _tt: any, options: FetchOptions) => { + const data = await graphsV1(CHAIN.BSC)(_t, _tt, options); + return { + dailyFees: data.dailyVolume ? `${Number(data.dailyVolume) * TOTAL_FEES}` : "0", + dailyUserFees: data.dailyVolume ? `${Number(data.dailyVolume) * TOTAL_FEES}` : "0", + dailyRevenue: data.dailyVolume ? `${Number(data.dailyVolume) * PROTOCOL_FEES}` : "0", + dailyHoldersRevenue: data.dailyVolume ? `${Number(data.dailyVolume) * HOLDER_REV}` : "0", + dailySupplySideRevenue: data.dailyVolume ? `${Number(data.dailyVolume) * LP_FEE}` : "0", + timestamp: options.startOfDay, + }; + }, + start: 1664841600, + }, + [CHAIN.AVAX]: { + fetch: async (_t: any, _tt: any, options: FetchOptions) => { + const data = await graphsV1(CHAIN.AVAX)(_t, _tt, options); + return { + dailyFees: data.dailyVolume ? `${Number(data.dailyVolume) * TOTAL_FEES}` : "0", + dailyUserFees: data.dailyVolume ? `${Number(data.dailyVolume) * TOTAL_FEES}` : "0", + dailyRevenue: data.dailyVolume ? `${Number(data.dailyVolume) * PROTOCOL_FEES}` : "0", + dailyHoldersRevenue: data.dailyVolume ? `${Number(data.dailyVolume) * HOLDER_REV}` : "0", + dailySupplySideRevenue: data.dailyVolume ? `${Number(data.dailyVolume) * LP_FEE}` : "0", + timestamp: options.startOfDay, + }; + }, + start: 1669420800, + }, + }, v2: { [CHAIN.AVAX]: { - fetch: graph(CHAIN.AVAX), - start: 1669420800 + fetch: graph, + start: 1669420800, }, [CHAIN.ARBITRUM]: { - fetch: graph(CHAIN.ARBITRUM), - start: 1672012800 + fetch: graph, + start: 1672012800, }, [CHAIN.BSC]: { - fetch: graph(CHAIN.BSC), - start: 1678147200 - } - } - } + fetch: graph, + start: 1678147200, + }, + [CHAIN.ETHEREUM]: { + fetch: graph, + start: 1695513600, + }, + }, + }, }; - export default adapter; diff --git a/fees/umoja/index.ts b/fees/umoja/index.ts new file mode 100644 index 0000000000..96356a0ce2 --- /dev/null +++ b/fees/umoja/index.ts @@ -0,0 +1,32 @@ +import * as Fetch from "../../utils/fetchURL"; +import * as Chains from "../../helpers/chains"; +import * as Adapters from "../../adapters/types"; +import * as C from "../../options/umoja/constants"; + +const get_data = async (timestamp: number) => { + const url = `${C.base_endpoint}/tokens/performance/d-llama`; + const date = new Date(timestamp * 1000).toISOString(); + const params = { date: date, range: 24 * 60 * 60, token: "*" }; + const result = await Fetch.httpGet(url, { params: params }, { withMetadata: false }); + + return { + timestamp: timestamp, + dailyFees: result.fees, + totalFees: result.fees_to_date, + }; +}; + +const adapter: Adapters.SimpleAdapter = { + adapter: { + [Chains.ARBITRUM]: { + fetch: get_data, + start: async () => new Date(C.min_start_date).getTime() / 1000, + meta: { + methodology: C.methodology, + hallmarks: C.hallmarks, + }, + }, + }, +}; + +export default adapter; diff --git a/fees/unidex.ts b/fees/unidex.ts index 6a715fc209..b27ce781df 100644 --- a/fees/unidex.ts +++ b/fees/unidex.ts @@ -4,11 +4,7 @@ import { getTimestampAtStartOfDayUTC } from "../utils/date"; import { Chain } from "@defillama/sdk/build/general"; import request, { gql } from "graphql-request"; - -type TChainIDs = { - [key in Chain]?: number; -}; - +type TChainIDs = { [key in Chain]?: number }; const chainIDs: TChainIDs = { [CHAIN.FANTOM]: 250, [CHAIN.ARBITRUM]: 42161, @@ -20,7 +16,7 @@ const chainIDs: TChainIDs = { interface IDayProduct { cumulativeFeesUsd: number; - _id: string; + chainId: number; } const fetch = (chain: Chain) => { @@ -31,35 +27,38 @@ const fetch = (chain: Chain) => { query MyQuery { DayProducts(filter: {date: ${todaysTimestamp}}) { cumulativeFeesUsd - _id + chainId } } `; - const endpoint = "https://arkiverbackup.moltennetwork.com/graphql"; + const endpoint = "https://arkiver.moltennetwork.com/graphql"; const response = await request(endpoint, graphQuery); const dayProducts: IDayProduct[] = response.DayProducts; - const chainID = chainIDs[chain]; - let dailyFeeUSD = 0; - + const feesByChain: { [chainId: number]: number } = {}; dayProducts.forEach((product) => { - const productChainID = parseInt(product._id.split(":")[2]); - if (productChainID === chainID) { - dailyFeeUSD += product.cumulativeFeesUsd; + const chainId = product.chainId; + if (chainId === 360) { + feesByChain[42161] = (feesByChain[42161] || 0) + product.cumulativeFeesUsd; + } else { + feesByChain[chainId] = (feesByChain[chainId] || 0) + product.cumulativeFeesUsd; } }); - const dailyHoldersRevenue = dailyFeeUSD * 0.35; - const dailyProtocolRevenue = dailyFeeUSD * 0.70; - const dailySupplySideRevenue = dailyFeeUSD * 0.3; + const chainID = chainIDs[chain]; + const dailyFeeUSD = chainID !== undefined ? feesByChain[chainID] || 0 : 0; + + const dailyHoldersRevenue = dailyFeeUSD * 0.65; + const dailyProtocolRevenue = dailyFeeUSD; + const dailySupplySideRevenue = dailyFeeUSD * 0.20; + return { dailyFees: dailyFeeUSD.toString(), dailyHoldersRevenue: dailyHoldersRevenue.toString(), dailyProtocolRevenue: dailyProtocolRevenue.toString(), - dailyRevenue: dailyProtocolRevenue.toString(), dailySupplySideRevenue: dailySupplySideRevenue.toString(), - timestamp + timestamp, }; }; }; @@ -67,8 +66,7 @@ const fetch = (chain: Chain) => { const methodology = { Fees: "Fees collected from user trading fees", Revenue: "Fees going to the treasury + holders", - HoldersRevenue: "Fees going to token holders", - SupplySideRevenue: "Fees going to liquidity providers of counterparty pools" + SupplySideFees: "Fees going to liquidity providers of the protocol", }; const adapter: Adapter = { @@ -76,53 +74,39 @@ const adapter: Adapter = { [CHAIN.OPTIMISM]: { fetch: fetch(CHAIN.OPTIMISM), start: 1687422746, - meta: { - methodology, - }, + meta: { methodology }, }, [CHAIN.ERA]: { fetch: fetch(CHAIN.ERA), start: 1687422746, - meta: { - methodology, - }, + meta: { methodology }, }, [CHAIN.ARBITRUM]: { fetch: fetch(CHAIN.ARBITRUM), start: 1687422746, - meta: { - methodology, - }, + meta: { methodology }, }, [CHAIN.BASE]: { fetch: fetch(CHAIN.BASE), start: 1687422746, - meta: { - methodology, - }, + meta: { methodology }, }, [CHAIN.FANTOM]: { fetch: fetch(CHAIN.FANTOM), start: 1687422746, - meta: { - methodology, - }, + meta: { methodology }, }, [CHAIN.METIS]: { fetch: fetch(CHAIN.METIS), start: 1687898060, - meta: { - methodology, - }, + meta: { methodology }, }, [CHAIN.EVMOS]: { fetch: fetch(CHAIN.EVMOS), start: 1700104066, - meta: { - methodology, - }, + meta: { methodology }, }, }, }; -export default adapter; +export default adapter; \ No newline at end of file diff --git a/fees/uniswap-lab.ts b/fees/uniswap-lab.ts index 255ec44a11..6a52a6e1b8 100644 --- a/fees/uniswap-lab.ts +++ b/fees/uniswap-lab.ts @@ -1,26 +1,27 @@ import ADDRESSES from '../helpers/coreAssets.json' -import { ChainBlocks, FetchOptions, FetchResultFees, SimpleAdapter } from "../adapters/types"; -import { CHAIN } from "../helpers/chains"; +import { FetchOptions, SimpleAdapter } from "../adapters/types"; import { addTokensReceived } from '../helpers/token'; const config: any = { ethereum: { tokens: [ADDRESSES.ethereum.USDC], targets: ['0x163c5e051049e92915017fe7bb9b8ce6182bcbb1', '0x6460d14dbaeb27aefec8ebef85db35defa31c3b9', '0x27213E28D7fDA5c57Fe9e5dD923818DBCcf71c47'] }, - optimism: { tokens: [ADDRESSES.optimism.USDC_CIRCLE], targets: ['0xd4ce1f1b8640c1988360a6729d9a73c85a0c80a3'] }, - polygon: { tokens: [ADDRESSES.polygon.USDC, ADDRESSES.polygon.USDC_CIRCLE], targets: ['0xce946931adf7afc0797de2a76270a28458f487ed'] }, - arbitrum: { tokens: [ADDRESSES.arbitrum.USDC_CIRCLE], targets: ['0xd4ce1f1b8640c1988360a6729d9a73c85a0c80a3'] }, + optimism: { tokens: [ADDRESSES.optimism.USDC_CIRCLE], targets: ['0xd4ce1f1b8640c1988360a6729d9a73c85a0c80a3', '0x7ffc3dbf3b2b50ff3a1d5523bc24bb5043837b14'] }, + polygon: { tokens: [ADDRESSES.polygon.USDC, ADDRESSES.polygon.USDC_CIRCLE], targets: ['0xce946931adf7afc0797de2a76270a28458f487ed', '0x7ffc3dbf3b2b50ff3a1d5523bc24bb5043837b14'] }, + arbitrum: { tokens: [ADDRESSES.arbitrum.USDC_CIRCLE], targets: ['0xd4ce1f1b8640c1988360a6729d9a73c85a0c80a3', '0x7ffc3dbf3b2b50ff3a1d5523bc24bb5043837b14'] }, + base: {tokens: [ADDRESSES.base.USDC], targets: ["0x7ffc3dbf3b2b50ff3a1d5523bc24bb5043837b14"]}, + bsc: {tokens: [ADDRESSES.bsc.USDC], targets: ["0x7ffc3dbf3b2b50ff3a1d5523bc24bb5043837b14"]}, + avax: {tokens: [ADDRESSES.avax.USDC], targets: ["0x7ffc3dbf3b2b50ff3a1d5523bc24bb5043837b14"]}, } -const fetch = async (timestamp: number, _: ChainBlocks, options: FetchOptions): Promise => { +const fetch = async (options: FetchOptions) => { const dailyFees = await addTokensReceived({ ...config[options.chain], options}) - return { timestamp, dailyFees, dailyRevenue: dailyFees } + return { dailyFees, dailyRevenue: dailyFees } } const adapters: SimpleAdapter = { - adapter: { - [CHAIN.ETHEREUM]: { fetch, start: 1696896000 }, - [CHAIN.OPTIMISM]: { fetch, start: 1696896000 }, - [CHAIN.POLYGON]: { fetch, start: 1696896000 }, - [CHAIN.ARBITRUM]: { fetch, start: 1696896000 } - } + adapter: Object.keys(config).reduce((all, chain)=>({ + ...all, + [chain]: { fetch, start: 1696896000 } + }), {}), + version: 2 } export default adapters; diff --git a/fees/usdo.ts b/fees/usdo.ts index b3dae9427d..762ea5b24a 100644 --- a/fees/usdo.ts +++ b/fees/usdo.ts @@ -1,4 +1,4 @@ -import { FetchResultFees, SimpleAdapter } from "../adapters/types" +import { FetchOptions, FetchResultFees, SimpleAdapter } from "../adapters/types" import * as sdk from "@defillama/sdk"; import { CHAIN } from "../helpers/chains"; import { getBlock } from "../helpers/getBlock"; @@ -35,34 +35,21 @@ const contract_interface = new ethers.Interface([ event_increase_value, ]); -const fetch = async (timestamp: number): Promise => { +const fetch = async ({ getLogs, startOfDay }: FetchOptions) => { throw new Error("I think neither of these should be counted as fees? or we just count 0.5% of redeemed USDO as fees?") - const fromTimestamp = timestamp - 60 * 60 * 24 - const toTimestamp = timestamp - const fromBlock = (await getBlock(fromTimestamp, CHAIN.ONUS, {})); - const toBlock = (await getBlock(toTimestamp, CHAIN.ONUS, {})); - const logs_increase_value = (await sdk.getEventLogs({ + const logs_increase_value = (await getLogs({ target: usdo, - toBlock: toBlock, - fromBlock: fromBlock, - chain: CHAIN.ONUS, topics: [topic0_increase_value] })).map(((e: any) => contract_interface.parseLog(e))); - const logs_tx: string[] = (await sdk.getEventLogs({ + const logs_tx: string[] = (await getLogs({ target: usdo, - toBlock: toBlock, - fromBlock: fromBlock, - chain: CHAIN.ONUS, topics: [topic0_withdraw] })).map((e: any) => e.transactionHash.toLowerCase()); - const logs: ILog[][] = (await Promise.all(pools.map((address: string) => sdk.getEventLogs({ + const logs: ILog[][] = (await Promise.all(pools.map((address: string) => getLogs({ target: address, - toBlock: toBlock, - fromBlock: fromBlock, - chain: CHAIN.ONUS, topics: [topic0_swap] })))) as any; @@ -82,7 +69,7 @@ const fetch = async (timestamp: number): Promise => { const tokens1 = underlyingToken1; const rawCoins = [...tokens0, ...tokens1].map((e: string) => `${CHAIN.ONUS}:${e}`); const coins = [...new Set(rawCoins)] - const prices = await getPrices(coins, timestamp); + const prices = await getPrices(coins, startOfDay); const untrackVolumes: number[] = pools.map((_: string, index: number) => { const token0Decimals = (prices[`${CHAIN.ONUS}:${tokens0[index]}`]?.decimals || 0) @@ -123,11 +110,11 @@ const fetch = async (timestamp: number): Promise => { return { dailyFees: `${dailyFee}`, dailyRevenue: `${dailyFee}`, - timestamp } } const adapter: SimpleAdapter = { + version: 2, adapter: { [CHAIN.ONUS]: { fetch, diff --git a/fees/valorem/constants.ts b/fees/valorem/constants.ts index 2d4d7b2b3f..08c87eee7a 100644 --- a/fees/valorem/constants.ts +++ b/fees/valorem/constants.ts @@ -1,9 +1,10 @@ +import * as sdk from "@defillama/sdk"; import { ChainEndpoints } from "../../adapters/types"; import { CHAIN } from "../../helpers/chains"; export const endpoints: ChainEndpoints = { [CHAIN.ARBITRUM]: - "https://api.thegraph.com/subgraphs/name/valorem-labs-inc/valorem-v1-arbitrum", + sdk.graph.modifyEndpoint('2cwenw6DXZBaSAQWvDVGqxrjbpnGR3JShhgySEvMJtBJ'), }; export const methodology = { diff --git a/fees/valorem/index.ts b/fees/valorem/index.ts index d4f00f31a7..8fbebcc2c9 100644 --- a/fees/valorem/index.ts +++ b/fees/valorem/index.ts @@ -105,6 +105,7 @@ const graphOptions = (graphUrls: ChainEndpoints) => { }; const adapter: Adapter = { + version: 1, adapter: { [ARBITRUM]: { fetch: graphOptions(endpoints)(ARBITRUM), diff --git a/fees/vaultka.ts b/fees/vaultka.ts index d3afb7d155..4d75f31177 100644 --- a/fees/vaultka.ts +++ b/fees/vaultka.ts @@ -1,61 +1,23 @@ -import { FetchResultFees, SimpleAdapter } from "../adapters/types"; +import { FetchOptions, SimpleAdapter } from "../adapters/types"; import { CHAIN } from "../helpers/chains"; -import { getBlock } from "../helpers/getBlock"; -import * as sdk from "@defillama/sdk"; +import { addTokensReceived } from "../helpers/token"; -const topic0_evt_transfer = "0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef"; -const topic2_evt_transfer = "0x0000000000000000000000001b5e59759577fa0079e2a35bc89143bc0603d546"; -const topic2_evt_transfer_2 = "0x000000000000000000000000d5ac6419635aa6352ebade0ab42d25fbfa570d21"; const usdc = "0xaf88d065e77c8cC2239327C5EDb3A432268e5831"; const usdce = "0xFF970A61A04b1cA14834A43f5dE4533eBDDB5CC8"; -interface ILog { - data: string; - transactionHash: string; - topics: string[]; - address: string; -} +const fetchFees = async (options: FetchOptions) => { + const dailyFees = await addTokensReceived({ + options, tokens: [usdc, usdce], targets: [ + '0x1b5e59759577fa0079e2a35bc89143bc0603d546', + '0xD5aC6419635Aa6352EbaDe0Ab42d25FbFa570D21', + ] + }) -const fetchFees = async (timestamp: number): Promise => { - const toTimestamp = timestamp; - const fromTimestamp = timestamp - 60 * 60 * 24; // 24 hours before - const fromBlock = await getBlock(fromTimestamp, CHAIN.ARBITRUM, {}); - const toBlock = await getBlock(toTimestamp, CHAIN.ARBITRUM, {}); - - // Fetch logs for the first topic - const logsForFirstTopic: ILog[] = (await sdk.getEventLogs({ - targets: [usdc, usdce], - toBlock: toBlock, - fromBlock: fromBlock, - chain: CHAIN.ARBITRUM, - topics: [topic0_evt_transfer, null, topic2_evt_transfer], // Adjusted for a single topic - })) as ILog[]; - - // Fetch logs for the second topic - const logsForSecondTopic: ILog[] = (await sdk.getEventLogs({ - targets: [usdc, usdce], - toBlock: toBlock, - fromBlock: fromBlock, - chain: CHAIN.ARBITRUM, - topics: [topic0_evt_transfer, null, topic2_evt_transfer_2], // Adjusted for a single topic - })) as ILog[]; - - // Combine logs from both calls - const combinedLogs = [...logsForFirstTopic, ...logsForSecondTopic]; - - // Calculate daily fees from combined logs - const dailyFees = combinedLogs.reduce((acc: number, log: ILog) => { - const amount = Number(log.data) / 10 ** 6; // Assuming 6 decimals for USDC and USDC.e - return acc + amount; - }, 0); - - return { - dailyFees: `${dailyFees}`, - timestamp, - }; + return { dailyFees, } }; const adapter: SimpleAdapter = { + version: 2, adapter: { [CHAIN.ARBITRUM]: { fetch: fetchFees, diff --git a/fees/vela/index.ts b/fees/vela/index.ts index 4adb134228..3c6a0497c2 100644 --- a/fees/vela/index.ts +++ b/fees/vela/index.ts @@ -1,13 +1,16 @@ +import * as sdk from "@defillama/sdk"; import { Adapter } from "../../adapters/types"; -import { ARBITRUM, AVAX } from "../../helpers/chains"; +import { CHAIN } from "../../helpers/chains"; import { request, gql } from "graphql-request"; import type { ChainEndpoints } from "../../adapters/types"; import { Chain } from "@defillama/sdk/build/general"; import { getTimestampAtStartOfDayUTC } from "../../utils/date"; const endpoints = { - [ARBITRUM]: - "https://api.thegraph.com/subgraphs/name/velaexchange/vela-exchange-official", + [CHAIN.ARBITRUM]: + sdk.graph.modifyEndpoint('https://api.goldsky.com/api/public/project_clu01p4nr68r301pze2tj4sh7/subgraphs/vela-arbitrum/mainnet/gn'), + [CHAIN.BASE]: + sdk.graph.modifyEndpoint('https://api.goldsky.com/api/public/project_clu01p4nr68r301pze2tj4sh7/subgraphs/vela-base/mainnet/gn') }; const methodology = { @@ -36,14 +39,22 @@ const graphs = (graphUrls: ChainEndpoints) => { }; const adapter: Adapter = { + version: 1, adapter: { - [ARBITRUM]: { - fetch: graphs(endpoints)(ARBITRUM), + [CHAIN.ARBITRUM]: { + fetch: graphs(endpoints)(CHAIN.ARBITRUM), start: 1687806000, meta: { methodology, }, }, + [CHAIN.BASE]: { + fetch: graphs(endpoints)(CHAIN.BASE), + start: 1693785600, + meta: { + methodology, + }, + } }, }; diff --git a/fees/velo/index.ts b/fees/velo/index.ts new file mode 100644 index 0000000000..4b9a4e5b19 --- /dev/null +++ b/fees/velo/index.ts @@ -0,0 +1,39 @@ +import ADDRESSES from '../../helpers/coreAssets.json' +import { FetchOptions, SimpleAdapter } from "../../adapters/types"; +import { addTokensReceived } from "../../helpers/token"; + +const config: any = { + bsc: { + targets: ["0x6C22422f4044dfBA79f4EA6BbB9C09162c3BF912"], + tokens: [ + ADDRESSES.bsc.BUSD, + ADDRESSES.bsc.USDT, + ADDRESSES.bsc.WBNB, + "0xf486ad071f3bEE968384D2E39e2D8aF0fCf6fd46", // VELO + "0xBe0D3526fc797583Dada3F30BC390013062A048B" , // PLEARN + "0x80458Df7142Ab707346020A180C44d02271C64Be", // USDV + "0xC2d4A3709e076A7A3487816362994a78ddaeabB6", // EVRY + ] + }, +}; + +const fetch = async (options: FetchOptions) => { + const dailyFees = await addTokensReceived({ + ...config[options.chain], + options, + }); + + return { dailyFees }; +}; + +const adapters: SimpleAdapter = { + adapter: Object.keys(config).reduce( + (all, chain) => ({ + ...all, + [chain]: { fetch, start: 1634010700 }, + }), + {} + ), + version: 2, +}; +export default adapters; \ No newline at end of file diff --git a/fees/velodrome-v2/bribes.ts b/fees/velodrome-v2/bribes.ts deleted file mode 100644 index b110a111d1..0000000000 --- a/fees/velodrome-v2/bribes.ts +++ /dev/null @@ -1,27 +0,0 @@ -import * as sdk from "@defillama/sdk"; -import { FetchOptions } from "../../adapters/types"; - -const event_notify_reward = 'event NotifyReward(address indexed from,address indexed reward,uint256 indexed epoch,uint256 amount)'; -const event_geuge_created = 'event GaugeCreated(address indexed poolFactory,address indexed votingRewardsFactory,address indexed gaugeFactory,address pool,address bribeVotingReward,address feeVotingReward,address gauge,address creator)' - -export const fees_bribes = async ({ getLogs, createBalances, getToBlock }: FetchOptions): Promise => { - const voter = '0x41c914ee0c7e1a5edcd0295623e6dc557b5abf3c'; - const dailyFees = createBalances() - const logs_geuge_created = (await getLogs({ - target: voter, - fromBlock: 105896851, - toBlock: await getToBlock(), - eventAbi: event_geuge_created, - cacheInCloud: true, - })) - const bribes_contract: string[] = logs_geuge_created.map((e: any) => e.bribeVotingReward.toLowerCase()); - - const logs = await getLogs({ - targets: bribes_contract, - eventAbi: event_notify_reward, - }) - logs.map((e: any) => { - dailyFees.add(e.reward, e.amount) - }) - return dailyFees; -} diff --git a/fees/velodrome-v2/index.ts b/fees/velodrome-v2/index.ts index 2dc4259a76..f7c08464f2 100644 --- a/fees/velodrome-v2/index.ts +++ b/fees/velodrome-v2/index.ts @@ -1,26 +1,43 @@ -import { Adapter, FetchOptions, FetchResultFees } from '../../adapters/types'; -import { OPTIMISM } from '../../helpers/chains'; -import { fetchV2 } from './velodrome-v2'; -import { fees_bribes } from './bribes'; +import { CHAIN } from "../../helpers/chains" +import { uniV2Exports } from "../../helpers/uniswap"; +const swapEvent = 'event Swap(address indexed sender, address indexed to, uint256 amount0In, uint256 amount1In, uint256 amount0Out, uint256 amount1Out)' +const notifyRewardEvent = 'event NotifyReward(address indexed from,uint256 amount)'; -const getFees = async (timestamp: number, _, fetchOptions: FetchOptions): Promise => { - const { getFromBlock, getToBlock, } = fetchOptions - const fromBlock = await getFromBlock() - const toBlock = await getToBlock() - const [feeV2, bribes] = await Promise.all([fetchV2(fromBlock, toBlock,timestamp, fetchOptions), fees_bribes(fetchOptions)]); - return { - ...feeV2, - dailyBribesRevenue: bribes, +const config = { + [CHAIN.MODE]: { + stakingRewards: '0xD2F998a46e4d9Dd57aF1a28EBa8C34E7dD3851D7', + rewardToken: '0xDfc7C877a950e49D2610114102175A06C2e3167a', + }, + [CHAIN.BOB]: { + stakingRewards: "0x8Eb6838B4e998DA08aab851F3d42076f21530389", + rewardToken: "0x4200000000000000000000000000000000000006", } } -const adapter: Adapter = { - adapter: { - [OPTIMISM]: { - fetch: getFees, - start: 1677110400, // TODO: Add accurate timestamp - }, - }, -}; -export default adapter; + +const customLogic = async ({ dailyFees, fetchOptions, filteredPairs, }: any) => { + const { createBalances, getLogs, chain, api, } = fetchOptions + const { stakingRewards, rewardToken, } = config[chain] + const pairs = Object.keys(filteredPairs) + const gauges = await api.multiCall({ target: stakingRewards, abi: 'function gauges(address) view returns (address)', calls: pairs }) + const dailyBribesRevenue = createBalances() + const logs = await getLogs({ targets: gauges, eventAbi: notifyRewardEvent }) + + logs.forEach(log => { + dailyBribesRevenue.add(rewardToken, log.amount) + }) + return { + dailyFees, + dailyRevenue: dailyFees, + dailyHoldersRevenue: dailyFees, + dailyBribesRevenue, + }; +} + +export default uniV2Exports({ + [CHAIN.OPTIMISM]: { factory: '0xF1046053aa5682b4F9a81b5481394DA16BE5FF5a', swapEvent, voter: '0x41c914ee0c7e1a5edcd0295623e6dc557b5abf3c', maxPairSize: 51, }, + [CHAIN.MODE]: { factory: '0x31832f2a97Fd20664D76Cc421207669b55CE4BC0', customLogic }, + [CHAIN.BOB]: { factory: '0x31832f2a97Fd20664D76Cc421207669b55CE4BC0', swapEvent, customLogic, }, +}) + diff --git a/fees/velodrome-v2/velodrome-v2.ts b/fees/velodrome-v2/velodrome-v2.ts deleted file mode 100644 index 0762bfba6d..0000000000 --- a/fees/velodrome-v2/velodrome-v2.ts +++ /dev/null @@ -1,9 +0,0 @@ -import { FetchOptions, FetchResultFees } from "../../adapters/types"; -import { CHAIN } from "../../helpers/chains"; -import { getDexFees } from "../../helpers/dexVolumeLogs"; - -const FACTORY_ADDRESS = '0xF1046053aa5682b4F9a81b5481394DA16BE5FF5a'; - -export const fetchV2 = async (fromBlock: number, toBlock: number, timestamp: number, fetchOptions: FetchOptions): Promise => { - return getDexFees({ chain: CHAIN.OPTIMISM, fromBlock, toBlock, factory: FACTORY_ADDRESS, timestamp, lengthAbi: 'allPoolsLength', itemAbi: 'allPools', fetchOptions }) -} diff --git a/fees/velodrome/index.ts b/fees/velodrome/index.ts index cd05e69db0..0a16dfc275 100644 --- a/fees/velodrome/index.ts +++ b/fees/velodrome/index.ts @@ -1,25 +1,12 @@ -import { Adapter, FetchResultFees } from '../../adapters/types'; +import { Adapter, } from '../../adapters/types'; import { OPTIMISM } from '../../helpers/chains'; import { fetchV1 } from './velodrome'; - -const getFees = async (timestamp: number): Promise => { - const [feeV1] = await Promise.all([fetchV1()(timestamp)]); - const dailyFees = Number(feeV1.dailyFees); - const dailyRevenue = Number(feeV1.dailyRevenue); - const dailyHoldersRevenue = Number(feeV1.dailyHoldersRevenue); - return { - dailyFees: `${dailyFees}`, - dailyRevenue: `${dailyRevenue}`, - dailyHoldersRevenue: `${dailyHoldersRevenue}`, - timestamp - } -} - const adapter: Adapter = { + version: 2, adapter: { [OPTIMISM]: { - fetch: getFees, + fetch: fetchV1(), start: 1677110400, // TODO: Add accurate timestamp }, }, diff --git a/fees/velodrome/velodrome.ts b/fees/velodrome/velodrome.ts index de3a2b4415..3c2a772870 100644 --- a/fees/velodrome/velodrome.ts +++ b/fees/velodrome/velodrome.ts @@ -1,36 +1,25 @@ +import * as sdk from "@defillama/sdk"; import request, { gql } from "graphql-request"; -import { Adapter } from "../../adapters/types"; -import { getBlock } from "../../helpers/getBlock"; -import { - getTimestampAtStartOfDayUTC, - getTimestampAtStartOfPreviousDayUTC -} from "../../utils/date"; +import { FetchOptions } from "../../adapters/types"; import BigNumber from "bignumber.js"; const STABLE_FEES = 0.0002; const VOLATILE_FEES = 0.0005; const endpoint = - "https://api.thegraph.com/subgraphs/name/dmihal/velodrome"; + sdk.graph.modifyEndpoint('2bam2XEb91cFqABFPSKj3RiSjpop9HvDt1MnYq5cDX5E'); export const fetchV1 = () => { - return async (timestamp: number) => { - const todaysTimestamp = getTimestampAtStartOfDayUTC(timestamp); - const yesterdaysTimestamp = getTimestampAtStartOfPreviousDayUTC(timestamp); - const todaysBlock = await getBlock( - todaysTimestamp, - "optimism", - {} - ); - const yesterdaysBlock = await getBlock(yesterdaysTimestamp, "optimism", {}); + return async ({ getToBlock, getFromBlock }: FetchOptions) => { + const [toBlock, fromBlock] = await Promise.all([ getToBlock(), getFromBlock()]) const query = gql` query fees { - yesterday: pairs(block: {number: ${yesterdaysBlock}}, where: {volumeUSD_gt: "0"}, first: 1000) { + yesterday: pairs(block: {number: ${fromBlock}}, where: {volumeUSD_gt: "0"}, first: 1000) { id isStable volumeUSD } - today: pairs(block: {number: ${todaysBlock}}, where: {volumeUSD_gt: "0"}, first: 1000) { + today: pairs(block: {number: ${toBlock}}, where: {volumeUSD_gt: "0"}, first: 1000) { id isStable volumeUSD @@ -57,7 +46,6 @@ export const fetchV1 = () => { } return { - timestamp, dailyFees: dailyFee.toString(), dailyRevenue: dailyFee.toString(), dailyHoldersRevenue: dailyFee.toString(), diff --git a/fees/venus-finance.ts b/fees/venus-finance.ts index 90eb6a8ccb..1692d0e689 100644 --- a/fees/venus-finance.ts +++ b/fees/venus-finance.ts @@ -1,16 +1,3 @@ -import { Adapter, } from "../adapters/types" -import { CHAIN } from "../helpers/chains"; -import { getFeesExport } from "../helpers/compoundV2"; +import { compoundV2Export, } from "../helpers/compoundV2"; -const unitroller = "0xfD36E2c2a6789Db23113685031d7F16329158384"; - -const adapter: Adapter = { - adapter: { - [CHAIN.BSC]: { - fetch: getFeesExport(unitroller), - start: 1691798400, - }, - }, -}; - -export default adapter; +export default compoundV2Export({ bsc: '0xfD36E2c2a6789Db23113685031d7F16329158384'}); \ No newline at end of file diff --git a/fees/verse.ts b/fees/verse.ts index ab40815dda..57f00b60de 100644 --- a/fees/verse.ts +++ b/fees/verse.ts @@ -2,6 +2,7 @@ import { CHAIN } from "../helpers/chains"; import { BaseAdapter, Adapter, ChainBlocks, FetchOptions, Fetch } from "../adapters/types"; import volumeAdapter from "../dexs/verse"; import BigNumber from "bignumber.js"; +import { version } from "os"; const adapterObj = volumeAdapter.adapter; @@ -49,11 +50,12 @@ const baseAdapter: BaseAdapter = { meta: { methodology } - } + }, } const adapter: Adapter = { - adapter: baseAdapter + adapter: baseAdapter, + version: 2 }; export default adapter; diff --git a/fees/vertex-protocol.ts b/fees/vertex-protocol.ts index cf05b2b514..ccc4f92036 100644 --- a/fees/vertex-protocol.ts +++ b/fees/vertex-protocol.ts @@ -1,5 +1,5 @@ import { CHAIN } from "../helpers/chains"; -import { Adapter, FetchResultFees } from "../adapters/types"; +import { Adapter, FetchOptions, FetchResultFees } from "../adapters/types"; import { httpPost } from "../utils/fetchURL"; interface MarketSnapshots { @@ -13,6 +13,7 @@ interface MarketSnapshots { interface QueryBody { market_snapshots: MarketSnapshots; } + interface IData { [s: string]: string; } @@ -25,7 +26,21 @@ interface Response { snapshots: Snapshot[]; } -const query = async (max_time: number): Promise => { +const archiveBaseUrl = "https://archive.prod.vertexprotocol.com/v1"; +const archiveMatleBaseUrl = "https://archive.mantle-prod.vertexprotocol.com/v1"; +const archiveSeiBaseUrl = "https://archive.sei-prod.vertexprotocol.com/v1"; + +type TURL = { + [s: string]: string; +}; + +const url: TURL = { + [CHAIN.ARBITRUM]: archiveBaseUrl, + [CHAIN.MANTLE]: archiveMatleBaseUrl, + [CHAIN.SEI]: archiveSeiBaseUrl, // Added Sei chain URL +}; + +const query = async (max_time: number, fetchOptions: FetchOptions): Promise => { const body: QueryBody = { market_snapshots: { interval: { @@ -36,8 +51,7 @@ const query = async (max_time: number): Promise => { }, }; - const archiveBaseUrl = "https://archive.prod.vertexprotocol.com/v1"; - const response = await httpPost(archiveBaseUrl, body); + const response = await httpPost(url[fetchOptions.chain], body); return response; }; @@ -51,9 +65,10 @@ const sumAllProductStats = (stat_map: IData): number => { const get24hrStat = async ( field: string, - max_time: number + max_time: number, + fetchOptions: FetchOptions ): Promise => { - const response = await query(max_time); + const response = await query(max_time, fetchOptions); const cur_res: Snapshot = response.snapshots[0]; const past_res: Snapshot = response.snapshots[1]; return ( @@ -63,48 +78,51 @@ const get24hrStat = async ( const getCumulativeStat = async ( field: string, - max_time: number + max_time: number, + fetchOptions: FetchOptions ): Promise => { - const response = await query(max_time); + const response = await query(max_time, fetchOptions); const cur_res = response.snapshots[0]; return sumAllProductStats(cur_res[field]); }; -const getCumulativeFees = async (max_time: number): Promise => { - const fees = await getCumulativeStat("cumulative_taker_fees", max_time); +const getCumulativeFees = async (max_time: number, fetchOptions: FetchOptions): Promise => { + const fees = await getCumulativeStat("cumulative_taker_fees", max_time, fetchOptions); const sequencer_fees = await getCumulativeStat( "cumulative_sequencer_fees", - max_time + max_time, + fetchOptions ); return fees - sequencer_fees; }; -const getCumulativeRevenue = async (max_time: number): Promise => { - const fees = await getCumulativeFees(max_time); - const rebates = await getCumulativeStat("cumulative_maker_fees", max_time); +const getCumulativeRevenue = async (max_time: number, fetchOptions: FetchOptions): Promise => { + const fees = await getCumulativeFees(max_time, fetchOptions); + const rebates = await getCumulativeStat("cumulative_maker_fees", max_time, fetchOptions); return fees + rebates; }; -const get24hrFees = async (max_time: number): Promise => { - const fees = await get24hrStat("cumulative_taker_fees", max_time); +const get24hrFees = async (max_time: number, fetchOptions: FetchOptions): Promise => { + const fees = await get24hrStat("cumulative_taker_fees", max_time, fetchOptions); const sequencer_fees = await get24hrStat( "cumulative_sequencer_fees", - max_time + max_time, + fetchOptions ); return fees - sequencer_fees; }; -const get24hrRevenue = async (max_time: number): Promise => { - const fees = await get24hrFees(max_time); - const rebates = await get24hrStat("cumulative_maker_fees", max_time); +const get24hrRevenue = async (max_time: number, fetchOptions: FetchOptions): Promise => { + const fees = await get24hrFees(max_time, fetchOptions); + const rebates = await get24hrStat("cumulative_maker_fees", max_time, fetchOptions); return fees + rebates; }; -const fetch = async (timestamp: number): Promise => { - const dailyFees = await get24hrFees(timestamp); - const dailyRevenue = await get24hrRevenue(timestamp); - const totalFees = await getCumulativeFees(timestamp); - const totalRev = await getCumulativeRevenue(timestamp); +const fetch = async (timestamp: number, _: any, fetchOptions: FetchOptions): Promise => { + const dailyFees = await get24hrFees(timestamp, fetchOptions); + const dailyRevenue = await get24hrRevenue(timestamp, fetchOptions); + const totalFees = await getCumulativeFees(timestamp, fetchOptions); + const totalRev = await getCumulativeRevenue(timestamp, fetchOptions); return { dailyFees: `${dailyFees}`, dailyRevenue: `${dailyRevenue}`, @@ -121,6 +139,16 @@ const adapter: Adapter = { runAtCurrTime: true, start: 1682514000, }, + [CHAIN.MANTLE]: { + fetch: fetch, + runAtCurrTime: true, + start: 1682514000, + }, + [CHAIN.SEI]: { + fetch: fetch, + runAtCurrTime: true, + start: 1723547681 + }, }, }; diff --git a/fees/vfat/index.ts b/fees/vfat/index.ts new file mode 100644 index 0000000000..716314a5ff --- /dev/null +++ b/fees/vfat/index.ts @@ -0,0 +1,134 @@ +import { FetchOptions, SimpleAdapter } from "../../adapters/types"; +import { CHAIN } from "../../helpers/chains"; + +const chainSettings: any = { + base: { + factory: '0x71D234A3e1dfC161cc1d081E6496e76627baAc31', + fromBlock: 12116234, + chainName: 'base', + }, + optimism: { + factory: '0xB4C31b0f0B76b351395D4aCC94A54dD4e6fbA1E8', + fromBlock: 117753454, + chainName: 'optimism', + }, + arbitrum: { + factory: '0x53d9780DbD3831E3A797Fd215be4131636cD5FDf', + fromBlockSickle: 197499243, + chainName: 'arbitrum', + }, + linea: { + factory: '0x0F6aBc6B808B377d6AeD8dA1FAD5E135C99C81a3', + fromBlockSickle: 4949355, + chainName: 'linea', + }, + ethereum: { + factory: '0x9D70B9E5ac2862C405D64A0193b4A4757Aab7F95', + chainName: 'ethereum', + fromBlockSickle: 19580798, + }, + mode: { + factory: '0x53d9780DbD3831E3A797Fd215be4131636cD5FDf', + chainName: 'mode', + fromBlockSickle: 7464171, + }, + fantom: { + factory: '0x53d9780DbD3831E3A797Fd215be4131636cD5FDf', + chainName: 'fantom', + fromBlockSickle: 79166260, + }, + mantle: { + factory: '0xB4C31b0f0B76b351395D4aCC94A54dD4e6fbA1E8', + chainName: 'mantle', + fromBlockSickle: 62383980, + }, + bsc: { + factory: '0x53d9780DbD3831E3A797Fd215be4131636cD5FDf', + chainName: 'bsc', + fromBlockSickle: 37565801 + }, + }; + + const fetchFees = async ({ createBalances, getLogs, chain }: FetchOptions) => { + const dailyFees = createBalances(); + const settings = chainSettings[chain]; + + +/* // Fetch Deploy events to get all Sickle contract addresses + const deployLogs = await getLogs({ + target: settings.factory, + fromBlock: settings.fromBlock, + eventAbi: 'event Deploy(address indexed admin, address sickle)', + cacheInCloud: true, + }); + + const sickleContracts = deployLogs.map((log: any) => log.sickle); */ + + const logs = await getLogs({ + // targets: sickleContracts, + eventAbi: 'event FeeCharged(bytes32 feesHash, uint256 amount, address token)', + }); + + const logs2 = await getLogs({ + // targets: sickleContracts, + eventAbi: 'event FeeCharged(address strategy, bytes4 feeDescriptor, uint256 amount, address token)', + }); + + + logs.forEach((log: any) => { + dailyFees.add(log.token, log.amount); + }); + + logs2.forEach((log: any) => { + dailyFees.add(log.token, log.amount); + }); + + return { + dailyFees, + dailyRevenue: dailyFees, + }; + }; + + const adapter: SimpleAdapter = { + version: 2, + adapter: { + [CHAIN.OPTIMISM]: { + fetch: fetchFees, + start: 1710979200, + }, + [CHAIN.BASE]: { + fetch: fetchFees, + start: 1710979200, + }, + [CHAIN.ARBITRUM]: { + fetch: fetchFees, + start: 1710979200, + }, + [CHAIN.LINEA]: { + fetch: fetchFees, + start: 1710979200, + }, + [CHAIN.ETHEREUM]: { + fetch: fetchFees, + start: 1710979200, + }, + [CHAIN.MODE]: { + fetch: fetchFees, + start: 1710979200, + }, + [CHAIN.FANTOM]: { + fetch: fetchFees, + start: 1710979200, + }, + [CHAIN.MANTLE]: { + fetch: fetchFees, + start: 1710979200, + }, + [CHAIN.BSC]: { + fetch: fetchFees, + start: 1710979200, + }, + } + } + + export default adapter; diff --git a/fees/voodoo-trade.ts b/fees/voodoo-trade.ts index 1f495b4e98..324b3d9fe2 100644 --- a/fees/voodoo-trade.ts +++ b/fees/voodoo-trade.ts @@ -1,3 +1,4 @@ +import * as sdk from "@defillama/sdk"; /// Project URL: https://voodoo.trade /// Contact: chickenjuju@proton.me /// @@ -17,7 +18,7 @@ import { getUniqStartOfTodayTimestamp } from "../helpers/getUniSubgraphVolume"; // Smart contract pads values with 10^30. I.e. 10 USD is stored as 10 * 10^30 const DECIMAL_PLACES = BigInt(10)**BigInt(30); -const graphQLClient = new GraphQLClient("https://api.thegraph.com/subgraphs/name/chicken-juju/voodoo-base-stats"); +const graphQLClient = new GraphQLClient(sdk.graph.modifyEndpoint('6eeKiwCJQECCwhE7doeoKCAqSK7VatCsv3piHomYzi6o')); const GET_FEE_BY_ID = gql`query getFeeById($id: ID!) { feeStat(id: $id) { diff --git a/fees/vvs-finance.ts b/fees/vvs-finance.ts index 76ea751a13..c9d04ec4c3 100644 --- a/fees/vvs-finance.ts +++ b/fees/vvs-finance.ts @@ -1,13 +1,10 @@ import { CHAIN } from "../helpers/chains"; -import { univ2DimensionAdapter } from "../helpers/getUniSubgraph"; +import { univ2DimensionAdapter2 } from "../helpers/getUniSubgraph"; -const adapters = univ2DimensionAdapter({ +const adapters = univ2DimensionAdapter2({ graphUrls: { [CHAIN.CRONOS]: "https://graph.cronoslabs.com/subgraphs/name/vvs/exchange" }, - dailyVolume: { - factory: "vvsDayData" - }, totalVolume: { factory: "vvsFactories" }, @@ -23,4 +20,5 @@ const adapters = univ2DimensionAdapter({ }, { }); adapters.adapter.cronos.start = 1632035122; + export default adapters; diff --git a/fees/wagmi/index.ts b/fees/wagmi/index.ts index 3118294b9e..6011d5191c 100644 --- a/fees/wagmi/index.ts +++ b/fees/wagmi/index.ts @@ -12,13 +12,13 @@ const methodology = { const adapter: SimpleAdapter = { adapter: { - [CHAIN.ERA]: { - fetch: fetchFee(CHAIN.ERA), - start: 1681257600, - meta: { - methodology, - }, - }, + // [CHAIN.ERA]: { + // fetch: fetchFee(CHAIN.ERA), + // start: 1681257600, + // meta: { + // methodology, + // }, + // }, [CHAIN.FANTOM]: { fetch: fetchFee(CHAIN.FANTOM), start: 1681257600, @@ -40,13 +40,13 @@ const adapter: SimpleAdapter = { methodology, }, }, - [CHAIN.METIS]: { - fetch: fetchFee(CHAIN.METIS), - start: 1702888970, - meta: { - methodology, - }, - }, + // [CHAIN.METIS]: { + // fetch: fetchFee(CHAIN.METIS), + // start: 1702888970, + // meta: { + // methodology, + // }, + // }, }, }; diff --git a/fees/waves/index.ts b/fees/waves/index.ts index f1536217c2..d71aaab38a 100644 --- a/fees/waves/index.ts +++ b/fees/waves/index.ts @@ -1,4 +1,4 @@ -import { Adapter, ChainBlocks, FetchOptions, ProtocolType } from "../../adapters/types"; +import { Adapter, FetchOptions, ProtocolType } from "../../adapters/types"; import { CHAIN } from "../../helpers/chains"; import fetchURL from "../../utils/fetchURL"; @@ -9,7 +9,7 @@ interface IBlockHeader { totalFee: number, } -const fetch = async (timestamp: number, _: ChainBlocks, { createBalances, getFromBlock, getToBlock }: FetchOptions) => { +const fetch = async ({ createBalances, getFromBlock, getToBlock }: FetchOptions) => { const dailyFees = createBalances() let startBlock = await getFromBlock(); @@ -29,10 +29,11 @@ const fetch = async (timestamp: number, _: ChainBlocks, { createBalances, getFro dailyFees.add(wavesToken, blockHeaders.reduce((acc, header) => acc + header.totalFee, 0)) - return { timestamp, dailyFees, }; + return { dailyFees, }; }; const adapter: Adapter = { + version: 2, adapter: { [CHAIN.WAVES]: { fetch, diff --git a/fees/wbtc/index.ts b/fees/wbtc/index.ts new file mode 100644 index 0000000000..016274ddfa --- /dev/null +++ b/fees/wbtc/index.ts @@ -0,0 +1,38 @@ +import { FetchOptions } from "../../adapters/types"; + +const btcRpcCall = (method:string, params:any)=> fetch("https://rpc.ankr.com/btc", { + method: "POST", + body: JSON.stringify({ + "jsonrpc": "1.0", + "id": "1", + method, + params + }) + }).then(r=>r.json()) + +async function getBitcoinTx(txId:string){ + const fullTx = await btcRpcCall("getrawtransaction",[txId]) + return btcRpcCall("decoderawtransaction", [fullTx.result]) +} + +export default { + adapter: { + "ethereum": { + fetch: async ({ getLogs, createBalances }: FetchOptions) => { + const mints = await getLogs({target: "0xe5A5F138005E19A3E6D0FE68b039397EeEf2322b", eventAbi: "event MintConfirmed (uint256 indexed nonce, address indexed requester, uint256 amount, string btcDepositAddress, string btcTxid, uint256 timestamp, bytes32 requestHash)"}) + const burns = await getLogs({target: "0xe5A5F138005E19A3E6D0FE68b039397EeEf2322b", eventAbi: "event BurnConfirmed (uint256 indexed nonce, address indexed requester, uint256 amount, string btcDepositAddress, string btcTxid, uint256 timestamp, bytes32 inputRequestHash)"}) + const dailyFees = createBalances(); + await Promise.all(mints.concat(burns).map(async event=>{ + const amount = Number(event.amount) + const btcTx = await getBitcoinTx(event.btcTxid) + const btcSend = btcTx.result.vout.filter(v=>v.scriptPubKey.address === event.btcDepositAddress).reduce((sum, v)=>sum+v.value, 0) + dailyFees.add('0x2260fac5e5542a773aa44fbcfedf7c193bc2c599', Math.abs(amount-btcSend*1e8)); + })) + return { dailyFees, dailyRevenue: dailyFees } + + }, + start: 1543017600 + } + }, + version: 2 +} \ No newline at end of file diff --git a/fees/wen-markets.ts b/fees/wen-markets.ts new file mode 100644 index 0000000000..1835780796 --- /dev/null +++ b/fees/wen-markets.ts @@ -0,0 +1,92 @@ +import { FetchOptions, SimpleAdapter } from "../adapters/types"; +import { CHAIN } from "../helpers/chains"; + +const wenLedger: any = { + [CHAIN.POLYGON]: "0x5574d1e44eFcc5530409fbE1568f335DaF83951c" +} +const abis: any = { + getStats: { + "inputs": [], + "name": "getStats", + "outputs": [ + { + "components": [ + { + "internalType": "uint256", + "name": "totalVolume", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "totalLiquidityBootstrapped", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "totalTokensCreated", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "totalTokensGraduated", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "totalTrades", + "type": "uint256" + } + ], + "internalType": "struct WenLedger.Stats", + "name": "", + "type": "tuple" + } + ], + "stateMutability": "view", + "type": "function" + } +}; + +const fetchFees = async (options: FetchOptions) => { + const tradeVolume = options.createBalances(); + const bootstrapped = options.createBalances(); + + const fromStats = await options.fromApi.call({ + target: wenLedger[options.chain], + abi: abis.getStats, + }); + + const toStats = await options.toApi.call({ + target: wenLedger[options.chain], + abi: abis.getStats, + }); + + const dailyVolume = toStats.totalVolume - fromStats.totalVolume; + const dailyBootstrapped = toStats.totalLiquidityBootstrapped - fromStats.totalLiquidityBootstrapped; + + tradeVolume.addGasToken(dailyVolume); + bootstrapped.addGasToken(dailyBootstrapped / 0.93); + bootstrapped.resizeBy(0.07); // 7% of liquidity bootstrapped + + const dailyFees = tradeVolume.clone(); + dailyFees.resizeBy(0.01); // 1% of trading volume + dailyFees.addBalances(bootstrapped); + + return { + dailyFees, + dailyRevenue: dailyFees, + dailyProtocolRevenue: dailyFees + }; +}; + +const adapters: SimpleAdapter = { + version: 2, + adapter: { + [CHAIN.POLYGON]: { + fetch: fetchFees, + start: 1716854400 + }, + } +}; + +export default adapters; diff --git a/fees/wigoswap.ts b/fees/wigoswap.ts index d7abea453e..79a6f5f925 100644 --- a/fees/wigoswap.ts +++ b/fees/wigoswap.ts @@ -1,12 +1,10 @@ +import { graph } from "@defillama/sdk"; import { CHAIN } from "../helpers/chains"; -import { univ2DimensionAdapter } from "../helpers/getUniSubgraph"; +import { univ2DimensionAdapter2 } from "../helpers/getUniSubgraph"; -const adapters = univ2DimensionAdapter({ +const adapters = univ2DimensionAdapter2({ graphUrls: { - [CHAIN.FANTOM]: "https://api.thegraph.com/subgraphs/name/wigoswap/exchange2" - }, - dailyVolume: { - factory: "wigoDayData" + [CHAIN.FANTOM]: graph.modifyEndpoint('71os49womDk3DFcNRCAFYzATxxMgWpSMKhRn5ih6aWF1') }, totalVolume: { factory: "wigoswapFactories" @@ -23,4 +21,5 @@ const adapters = univ2DimensionAdapter({ }, { }); adapters.adapter.fantom.start = 1642982400; + export default adapters; diff --git a/fees/wombat-exchange.ts b/fees/wombat-exchange.ts index a2bd7c813e..78665cda3a 100644 --- a/fees/wombat-exchange.ts +++ b/fees/wombat-exchange.ts @@ -2,7 +2,7 @@ import { Adapter } from "../adapters/types"; import volumeAdapter from "../dexs/wombat-exchange"; import { getDexChainFees } from "../helpers/getUniSubgraphFees"; -const TOTAL_FEES = 0.0001; +const TOTAL_FEES = 0.0004; const feeAdapter = getDexChainFees({ totalFees: TOTAL_FEES, @@ -10,6 +10,7 @@ const feeAdapter = getDexChainFees({ }); const adapter: Adapter = { + version: 2, adapter: feeAdapter }; diff --git a/fees/woofi.ts b/fees/woofi.ts index f8c44b2008..8342c0c2aa 100644 --- a/fees/woofi.ts +++ b/fees/woofi.ts @@ -1,4 +1,4 @@ -import { Adapter, ChainBlocks, FetchOptions, FetchResultFees } from "../adapters/types"; +import { Adapter, FetchOptions, } from "../adapters/types"; import { CHAIN } from "../helpers/chains"; import { Chain } from "@defillama/sdk/build/general"; import { addTokensReceived } from '../helpers/token'; @@ -12,27 +12,39 @@ type TFeeDetail = { } const fee_detail: TFeeDetail = { [CHAIN.AVAX]: { - from: '0x6cb1bc6c8aabdae822a2bf8d83b36291cb70f169', + from: '0xc45b55032cafeaff3b8057d52758d8f8211da54d', }, [CHAIN.BSC]: { - from: '0xda5e1d3aaa93e8716f87b5ee39e5f514cc934d5e', + from: '0xc45b55032cafeaff3b8057d52758d8f8211da54d', }, [CHAIN.FANTOM]: { from: '0x0b5025d8d409a51615cb624b8ede132bb11a2550', }, [CHAIN.POLYGON]: { - from: '0x938021351425dbfa606ed2b81fc66952283e0dd5', + from: '0xc45b55032cafeaff3b8057d52758d8f8211da54d', }, [CHAIN.ARBITRUM]: { - from: '0x0ba6c34af9713d15141dcc91d2788c3f370ecb9e', + from: '0xc45b55032cafeaff3b8057d52758d8f8211da54d', }, [CHAIN.OPTIMISM]: { - from: '0xa058798cd293f5acb4e7757b08c960a79f527699', - } + from: '0xc45b55032cafeaff3b8057d52758d8f8211da54d', + }, + [CHAIN.ERA]: { + from: '0x01b50b57a3d3c1a54433813585e60713e75f3de9', + }, + [CHAIN.LINEA]: { + from: '0xc45b55032cafeaff3b8057d52758d8f8211da54d', + }, + [CHAIN.BASE]: { + from: '0xc45b55032cafeaff3b8057d52758d8f8211da54d', + }, + [CHAIN.MANTLE]: { + from: '0xc45b55032cafeaff3b8057d52758d8f8211da54d', + }, } const fetch = (chain: Chain) => { - return async (timestamp: number, _: ChainBlocks, options: FetchOptions): Promise => { + return async (options: FetchOptions) => { const { api } = options; const { from, } = fee_detail[chain]; const token = await api.call({ abi: 'address:quoteToken', target: from }) @@ -46,12 +58,12 @@ const fetch = (chain: Chain) => { dailyFees, dailyRevenue, dailyHoldersRevenue, - timestamp } } } const adapter: Adapter = { + version: 2, adapter: { [CHAIN.AVAX]: { fetch: fetch(CHAIN.AVAX), @@ -77,6 +89,22 @@ const adapter: Adapter = { fetch: fetch(CHAIN.OPTIMISM), start: 1673222400, }, + [CHAIN.ERA]: { + fetch: fetch(CHAIN.ERA), + start: 1673222400, + }, + [CHAIN.LINEA]: { + fetch: fetch(CHAIN.LINEA), + start: 1673222400, + }, + [CHAIN.BASE]: { + fetch: fetch(CHAIN.BASE), + start: 1673222400, + }, + [CHAIN.MANTLE]: { + fetch: fetch(CHAIN.MANTLE), + start: 1673222400, + } } } diff --git a/fees/xoxno/index.ts b/fees/xoxno/index.ts index 36964d2a0c..a8048433d9 100644 --- a/fees/xoxno/index.ts +++ b/fees/xoxno/index.ts @@ -1,4 +1,4 @@ -import { FetchResultFees, SimpleAdapter } from "../../adapters/types"; +import { FetchOptions, SimpleAdapter } from "../../adapters/types"; import { CHAIN } from "../../helpers/chains"; import { httpGet } from "../../utils/fetchURL"; @@ -8,34 +8,29 @@ interface IRaw { Day: string; } -const fetchFees = async (timestamp: number): Promise => { - const startTime = 1683849600; - const beforeTime = timestamp + 86400; - const startTimeStr = new Date(startTime * 1000).toISOString().split("T")[0]; - const toDayTime = new Date(timestamp * 1000).toISOString().split("T")[0]; - const toDayTimeStr = new Date(beforeTime * 1000).toISOString().split("T")[0]; - const url = `https://proxy-api.xoxno.com/getMarketplaceVolume?after=${startTimeStr}&before=${toDayTimeStr}&bin=1d`; - const response: IRaw[] = (await httpGet(url, { - headers: { - origin: 'https://xoxno.com', - referer: 'https://xoxno.com/' - } - })); - // const fs = require('fs'); - // fs.writeFileSync('./xoxno.json', JSON.stringify(response)); - // const response: IRaw[] = require('./xoxno.json'); +const fetchFees = async ({ fromTimestamp, toTimestamp }: FetchOptions) => { + // const startTimeStr = new Date(fromTimestamp * 1000).toISOString().split("T")[0]; + // const toDayTimeStrNext = new Date((toTimestamp + 84000) * 1000).toISOString().split("T")[0]; + // const toDayTimeStr = new Date((toTimestamp) * 1000).toISOString().split("T")[0]; + // const url = `https://proxy-api.xoxno.com/getMarketplaceVolume?after=${startTimeStr}&before=${toDayTimeStrNext}&bin=1d`; + // const response: IRaw[] = (await httpGet(url, { + // headers: { + // origin: 'https://xoxno.com', + // referer: 'https://xoxno.com/' + // } + // })); - const toDayStr = toDayTime.split('-')[1] +'-'+ toDayTime.split('-')[2]; - const dayData = response.find((item) => item.Day === toDayStr); - const dailyFees = (dayData?.XO_FeesPaidUSD || 0) + (dayData?.XO_RoyaltiesPaidUSD || 0); - const dailyRevenue = dayData?.XO_FeesPaidUSD; + // const toDayStr = toDayTimeStr.split('-')[1] +'-'+ toDayTimeStr.split('-')[2]; + // const dayData = response.find((item) => item.Day === toDayStr); + // const dailyFees = (dayData?.XO_FeesPaidUSD || 0) + (dayData?.XO_RoyaltiesPaidUSD || 0); + // const dailyRevenue = dayData?.XO_FeesPaidUSD || 0; return { - dailyFees: `${dailyFees}`, - dailyRevenue: `${dailyRevenue}`, - timestamp + dailyFees: `${0}`, + dailyRevenue: `${0}`, } } const adapters: SimpleAdapter = { + version: 2, adapter: { [CHAIN.ELROND]: { fetch: fetchFees, diff --git a/fees/y2k/index.ts b/fees/y2k/index.ts index 08e273cc10..a3cdb792f0 100644 --- a/fees/y2k/index.ts +++ b/fees/y2k/index.ts @@ -9,6 +9,7 @@ const methodology = { }; const adapter: Adapter = { + version: 2, breakdown: { v1: { [CHAIN.ARBITRUM]: { diff --git a/fees/y2k/y2k-finance-v2.ts b/fees/y2k/y2k-finance-v2.ts index 925bd8064c..2b9fc7a2cd 100644 --- a/fees/y2k/y2k-finance-v2.ts +++ b/fees/y2k/y2k-finance-v2.ts @@ -1,5 +1,5 @@ import ADDRESSES from '../../helpers/coreAssets.json' -import { FetchResultFees } from "../../adapters/types"; +import { FetchOptions } from "../../adapters/types"; import { addTokensReceived } from '../../helpers/token'; const factory = "0xC3179AC01b7D68aeD4f27a19510ffe2bfb78Ab3e"; @@ -12,7 +12,7 @@ const tokens = [ ]; const treasury = "0x5c84cf4d91dc0acde638363ec804792bb2108258"; -const fetch = async (timestamp: number, _, options): Promise => { +const fetch = async (options: FetchOptions) => { const { createBalances, getLogs, } = options const market_create = await getLogs({ @@ -27,11 +27,10 @@ const fetch = async (timestamp: number, _, options): Promise => const vaults = [...new Set([...premium, ...collateral])]; const dailyFees = createBalances() - for (const vault of vaults) - await addTokensReceived({ options, tokens, fromAddressFilter: vault, target: treasury, balances: dailyFees }) + await addTokensReceived({ options, tokens, fromAdddesses: vaults, target: treasury, balances: dailyFees }) - return { dailyFees, dailyRevenue: dailyFees, timestamp, }; + return { dailyFees, dailyRevenue: dailyFees }; }; export default fetch; diff --git a/fees/y2k/y2k-finance.ts b/fees/y2k/y2k-finance.ts index 64a13957fd..7fa084daca 100644 --- a/fees/y2k/y2k-finance.ts +++ b/fees/y2k/y2k-finance.ts @@ -1,5 +1,5 @@ import ADDRESSES from '../../helpers/coreAssets.json' -import { FetchResultFees } from "../../adapters/types"; +import { FetchOptions } from "../../adapters/types"; import { addTokensReceived } from '../../helpers/token'; const vault_factory = "0x984e0eb8fb687afa53fc8b33e12e04967560e092"; @@ -16,18 +16,17 @@ const tokens = [ const treasury = "0x5c84cf4d91dc0acde638363ec804792bb2108258"; -const fetch = async (timestamp: number, _, options): Promise => { - const { api, createBalances, getLogs, } = options +const fetch = async (options: FetchOptions) => { + const { api, createBalances } = options const vaultRes = await api.fetchList({ lengthAbi: abis.marketIndex, itemAbi: abis.getVaults, target: vault_factory }) const vaults = vaultRes.flat() const dailyFees = createBalances() - for (const vault of vaults) - await addTokensReceived({ options, tokens, fromAddressFilter: vault, target: treasury, balances: dailyFees }) + await addTokensReceived({ options, tokens, fromAdddesses: vaults, target: treasury, balances: dailyFees }) - return { dailyFees, dailyRevenue: dailyFees, timestamp, }; + return { dailyFees, dailyRevenue: dailyFees, }; }; export default fetch; diff --git a/fees/yfx-v4.ts b/fees/yfx-v4.ts new file mode 100644 index 0000000000..94fc63fd02 --- /dev/null +++ b/fees/yfx-v4.ts @@ -0,0 +1,84 @@ +import { Adapter } from "../adapters/types"; +import { CHAIN } from "../helpers/chains"; +import { request, gql } from "graphql-request"; +import type { ChainEndpoints } from "../adapters/types" +import { Chain } from '@defillama/sdk/build/general'; +import { getTimestampAtStartOfDayUTC } from "../utils/date"; + +const endpoints: { [key: string]: string } = { + [CHAIN.ARBITRUM]: "https://graph-v4.yfx.com/yfx_v4", + [CHAIN.BASE]: "https://graph-v4.yfx.com/yfx_v4_base", +} + +const methodology = { + Fees: "Fees from open/close position (0.05%) and remove liquidity fees (0%)", + UserFees: "Fees from open/close position (0.05%)", +} + +const graphs = (graphUrls: ChainEndpoints) => { + return (chain: Chain) => { + return async (timestamp: any) => { + const time = timestamp.toTimestamp; + const todaysTimestamp = getTimestampAtStartOfDayUTC(time) + + const marketData = gql` + { + marketInfoDailies(where: {dayTime: "${todaysTimestamp}"}) { + totalFeeUSD + totalCommissionUSD + totalDiscountUSD + } + }` + const poolData = gql` + { + poolDailyDatas(where: {dayTime: "${todaysTimestamp}"}) { + removeLiquidityFeeUSD + } + } + ` + + + const marketFees = await request(graphUrls[chain], marketData); + const poolFees = await request(graphUrls[chain], poolData); + + let swapFee = 0 + let liquidityFee = 0 + for (let i in marketFees.marketInfoDailies) { + swapFee += parseFloat(marketFees.marketInfoDailies[i].totalFeeUSD); + } + + for (let i in poolFees.poolDataDailyDatas) { + liquidityFee += parseFloat(poolFees.poolDataDailyDatas[i].removeLiquidityFeeUSD) + } + + return { + time: time.toString(), + dailyFees: (swapFee+liquidityFee).toString(), + dailyUserFees: swapFee.toString(), + }; + }; + }; +}; + + +const adapter: Adapter = { + version: 2, + adapter: { + [CHAIN.ARBITRUM]: { + fetch: graphs(endpoints)(CHAIN.ARBITRUM), + start: async () => 1713916800, + meta: { + methodology + } + }, + [CHAIN.BASE]: { + fetch: graphs(endpoints)(CHAIN.BASE), + start: async () => 1721001600, + meta: { + methodology + } + }, + } +} + +export default adapter; diff --git a/fees/yologames/index.ts b/fees/yologames/index.ts new file mode 100644 index 0000000000..d9f6adcd54 --- /dev/null +++ b/fees/yologames/index.ts @@ -0,0 +1,36 @@ +import { ETHER_ADDRESS } from "@defillama/sdk/build/general"; +import { Adapter, FetchOptions } from "../../adapters/types"; +import { CHAIN } from "../../helpers/chains"; +import fetchURL from "../../utils/fetchURL"; + +const fetchDailyStats = async ( + from: number, to: number +): Promise<{ feesETH: number }> => { + const url = `https://stats.yologames.io/stats?from=${from * 1000}&to=${to * 1000}`; + const response = await fetchURL(url); + return { feesETH: response.feesETH }; +}; + +const fetch: any = async ({ createBalances, fromTimestamp, toTimestamp }: FetchOptions) => { + const dailyFees = createBalances(); + const statsApiResponse = await fetchDailyStats(fromTimestamp, toTimestamp); + dailyFees.add(ETHER_ADDRESS, statsApiResponse.feesETH * 1e18); + return { dailyFees }; +}; + +const adapter: Adapter = { + version: 2, + adapter: { + [CHAIN.BLAST]: { + fetch, + start: 1709251200, + meta: { + methodology: { + Fees: "YOLO Games collects a 1% fee for Moon Or Doom and YOLO winnings, and a 3% fee on Poke The Bear winnings.", + }, + }, + }, + }, +}; + +export default adapter; diff --git a/fees/zapper-channels.ts b/fees/zapper-channels.ts index 511a73456b..c8b51001eb 100644 --- a/fees/zapper-channels.ts +++ b/fees/zapper-channels.ts @@ -11,7 +11,8 @@ const adapter: Adapter = { fetch: getFeesExport(FriendtechSharesAddress, [event_trade]), start: 1696204800, }, - } + }, + version: 2, } export default adapter; diff --git a/fees/zeno.ts b/fees/zeno.ts new file mode 100644 index 0000000000..a05bc326d0 --- /dev/null +++ b/fees/zeno.ts @@ -0,0 +1,119 @@ +import { Adapter } from "../adapters/types"; +import { CHAIN } from "../helpers/chains"; +import { gql, GraphQLClient } from "graphql-request"; +import type { ChainEndpoints, FetchV2 } from "../adapters/types"; +import { getTimestampAtStartOfDayUTC } from "../utils/date"; + +const endpoints = { + [CHAIN.METIS]: + "https://metisapi.0xgraph.xyz/subgraphs/name/metis-andromeda-prod-stats", +}; + +const graphs = (graphUrls: ChainEndpoints) => { + const fetch: FetchV2 = async ({ chain, startTimestamp }) => { + if (chain === CHAIN.METIS) { + const floorDayTimestamp = getTimestampAtStartOfDayUTC(startTimestamp); + const totalFeeQuery = gql` + { + globalFeesStat(id: "global") { + totalFeePaid + settlementFeePaid + liquidationFeePaid + borrowingFeePaid + tradingFeePaid + addLiquidityFeePaid + removeLiquidityFeePaid + fundingFeePaid + } + } + `; + const dailyFeeQuery = gql` + { + dailyFeesStat(id: "${floorDayTimestamp}") { + totalFeePaid + settlementFeePaid + liquidationFeePaid + borrowingFeePaid + tradingFeePaid + addLiquidityFeePaid + removeLiquidityFeePaid + fundingFeePaid + } + } + `; + const graphQLClient = new GraphQLClient(graphUrls[chain]); + graphQLClient.setHeader("origin", "https://zeno.exchange"); + const totalFeeResp = await graphQLClient.request(totalFeeQuery); + const dailyFeeResp = await graphQLClient.request(dailyFeeQuery); + + const finalizedDailyFee = + Number(dailyFeeResp.dailyFeesStat.totalFeePaid) / 1e30; + + const finalizedTotalFee = + Number(totalFeeResp.globalFeesStat.totalFeePaid) / 1e30; + const finalizedDailyFeeWithoutFundingFee = + (Number(dailyFeeResp.dailyFeesStat.tradingFeePaid) + + Number(dailyFeeResp.dailyFeesStat.borrowingFeePaid) + + Number(dailyFeeResp.dailyFeesStat.liquidationFeePaid) + + Number(dailyFeeResp.dailyFeesStat.settlementFeePaid) + + Number(dailyFeeResp.dailyFeesStat.addLiquidityFeePaid) + + Number(dailyFeeResp.dailyFeesStat.removeLiquidityFeePaid)) / + 1e30; + const finalizedDailyUserFee = + (Number(dailyFeeResp.dailyFeesStat.tradingFeePaid) + + Number(dailyFeeResp.dailyFeesStat.borrowingFeePaid) + + Number(dailyFeeResp.dailyFeesStat.liquidationFeePaid) + + Number(dailyFeeResp.dailyFeesStat.fundingFeePaid) + + Number(dailyFeeResp.dailyFeesStat.settlementFeePaid)) / + 1e30; + const finalizedTotalUserFee = + (Number(totalFeeResp.globalFeesStat.tradingFeePaid) + + Number(totalFeeResp.globalFeesStat.borrowingFeePaid) + + Number(totalFeeResp.globalFeesStat.liquidationFeePaid) + + Number(totalFeeResp.globalFeesStat.fundingFeePaid) + + Number(totalFeeResp.globalFeesStat.settlementFeePaid)) / + 1e30; + + const dailyHoldersRevenue = + (finalizedDailyFeeWithoutFundingFee * 35) / 90; + const dailyProtocolRevenue = + (finalizedDailyFeeWithoutFundingFee * 5) / 90; + const dailySupplySideRevenue = + (finalizedDailyFeeWithoutFundingFee * 50) / 90; + return { + dailyFees: finalizedDailyFee.toString(), + dailyUserFees: finalizedDailyUserFee.toString(), + dailyRevenue: (dailyHoldersRevenue + dailyProtocolRevenue).toString(), + dailyProtocolRevenue: dailyProtocolRevenue.toString(), + dailyHoldersRevenue: dailyHoldersRevenue.toString(), + dailySupplySideRevenue: dailySupplySideRevenue.toString(), + totalFees: finalizedTotalFee.toString(), + totalUserFees: finalizedTotalUserFee.toString(), + }; + } + + return { + dailyFees: "0", + dailyUserFees: "0", + dailyRevenue: "0", + dailyProtocolRevenue: "0", + dailyHoldersRevenue: "0", + dailySupplySideRevenue: "0", + totalFees: "0", + totalUserFees: "0", + }; + }; + return fetch; +}; + +const adapter: Adapter = { + version: 2, + adapter: { + [CHAIN.METIS]: { + fetch: graphs(endpoints), + start: 1710294153, + }, + }, +}; + +export default adapter; diff --git a/fees/zerion-wallet.ts b/fees/zerion-wallet.ts index 6df1d94404..a888afba46 100644 --- a/fees/zerion-wallet.ts +++ b/fees/zerion-wallet.ts @@ -1,4 +1,4 @@ -import { Adapter, FetchOptions, FetchResultFees } from "../adapters/types"; +import { Adapter, FetchOptions, } from "../adapters/types"; import { CHAIN } from "../helpers/chains"; import { addGasTokensReceived, addTokensReceived } from "../helpers/token"; @@ -17,10 +17,10 @@ const multisigs: TMulitsig = { [CHAIN.BSC]: [multisig1] } -const fetch: any = async (timestamp: number, _: any, options: FetchOptions): Promise => { +const fetch: any = async (options: FetchOptions) => { const dailyFees = await addGasTokensReceived({ multisigs: multisigs[options.chain], options }) - await addTokensReceived({ targets: multisigs[options.chain], options, balances: dailyFees, fetchTokenList: true, }) - return { timestamp, dailyFees, dailyRevenue: dailyFees, dailyProtocolRevenue: dailyFees, } + await addTokensReceived({ targets: multisigs[options.chain], options, balances: dailyFees,}) + return { dailyFees, dailyRevenue: dailyFees, dailyProtocolRevenue: dailyFees, } } const methodology = { @@ -30,6 +30,7 @@ const methodology = { const chainAdapter = { fetch, start: 1672531200, meta: { methodology } } const adapter: Adapter = { + version: 2, adapter: { [CHAIN.ETHEREUM]: chainAdapter, [CHAIN.OPTIMISM]: chainAdapter, diff --git a/fees/zns/index.ts b/fees/zns/index.ts new file mode 100644 index 0000000000..4426cb0ee4 --- /dev/null +++ b/fees/zns/index.ts @@ -0,0 +1,174 @@ +import type { Balances } from "@defillama/sdk"; +import { Adapter, FetchOptions } from "../../adapters/types"; +import { CHAIN } from "../../helpers/chains"; + +const abi_event = { + mintedDomain: "event MintedDomain(string domainName,uint256 indexed tokenId,address indexed owner,uint256 indexed expiry)", + renewedDomain: "event RenewedDomain(uint256 indexed tokenId,uint256 indexed expiry,string domainName)", +}; + +type TAddress = { + [s: string]: string; +}; +const addresses: TAddress = { + [CHAIN.BSC]: "0x7e2cf06f092c9f5cf5972ef021635b6c8e1c5bb2", + [CHAIN.SCROLL]: "0xB00910Bac7DA44c0D440798809dbF8d51FDBb635", + [CHAIN.BLAST]: "0x59B9Ac688e39A14b938AC8C3269db66D8aDB9aF6", + [CHAIN.POLYGON]: "0x8ccD9c0A9C084412416A85Fd748c7f1E9b86442D", + [CHAIN.TAIKO]: "0xFb2Cd41a8aeC89EFBb19575C6c48d872cE97A0A5", + [CHAIN.XLAYER]: "0x71709a5f1831ba48c414375fb6a58662a40c01b5", + [CHAIN.ZORA]: "0xf180136DdC9e4F8c9b5A9FE59e2b1f07265C5D4D", + [CHAIN.BOBA]: "0xf1D09DA87c50820eD3b924aFf3C37058eD6eA40e", + [CHAIN.ZKLINK]: "0xe0971a2B6E34bd060866081aE879630e83C4A0BD", +}; + +const methodology = { + Fees: "registration and renew cost", + Revenue: "registration and renew cost", +}; + +const ABI = { + priceToRegister: { + inputs: [{ internalType: "uint16", name: "len", type: "uint16" }], + name: "priceToRegister", + outputs: [{ internalType: "uint256", name: "", type: "uint256" }], + stateMutability: "view", + type: "function", + }, + priceToRenew: { + inputs: [{ internalType: "uint16", name: "len", type: "uint16" }], + name: "priceToRenew", + outputs: [{ internalType: "uint256", name: "", type: "uint256" }], + stateMutability: "view", + type: "function", + }, +} + +const fetchLogsAndCalculateFees = async ( + options: FetchOptions, +): Promise<{ dailyFees: Balances; dailyRevenue: Balances }> => { + const address = addresses[options.chain]; + const dailyFees = options.createBalances(); + + const mintedLogs = await options.getLogs({ + target: address, + eventAbi: abi_event.mintedDomain, + }); + + const renewedLogs = await options.getLogs({ + target: address, + eventAbi: abi_event.renewedDomain, + }); + const lens = [1,2,3,4,5] + + const znsPriceRegistor = await options.api.multiCall({ + abi: ABI.priceToRegister, + calls: lens.map(len=>({ + params: [len], + target: address + })) + }); + + const znsPriceRenew = await options.api.multiCall({ + abi: ABI.priceToRenew, + calls: lens.map(len=>({ + params: [len], + target: address + })), + }); + + mintedLogs.forEach((log) => { + const domainName = log.domainName; + let domainPrice = 0; + if (domainName.length === 1) domainPrice = znsPriceRegistor[0]; + else if (domainName.length === 2) domainPrice = znsPriceRegistor[1]; + else if (domainName.length === 3) domainPrice = znsPriceRegistor[2]; + else if (domainName.length === 4) domainPrice = znsPriceRegistor[3]; + else domainPrice = znsPriceRegistor[4]; + dailyFees.addGasToken(domainPrice); + }); + + renewedLogs.forEach((log) => { + const domainName = log.domainName; + let domainPrice = 0; + if (domainName.length === 1) domainPrice = znsPriceRenew[0]; + else if (domainName.length === 2) domainPrice = znsPriceRenew[1]; + else if (domainName.length === 3) domainPrice = znsPriceRenew[2]; + else if (domainName.length === 4) domainPrice = znsPriceRenew[3]; + else domainPrice = znsPriceRenew[4]; + dailyFees.addGasToken(domainPrice); + }); + + return { dailyFees, dailyRevenue: dailyFees }; +}; + +const adapter: Adapter = { + version: 2, + adapter: { + [CHAIN.BSC]: { + fetch: fetchLogsAndCalculateFees, + start: 1714506194, + meta: { + methodology, + }, + }, + [CHAIN.SCROLL]: { + fetch: fetchLogsAndCalculateFees, + start: 1714773760, + meta: { + methodology, + }, + }, + [CHAIN.BLAST]: { + fetch: fetchLogsAndCalculateFees, + start: 1717180581, + meta: { + methodology, + }, + }, + [CHAIN.POLYGON]: { + fetch: fetchLogsAndCalculateFees, + start: 1717195742, + meta: { + methodology, + }, + }, + [CHAIN.TAIKO]: { + fetch: fetchLogsAndCalculateFees, + start: 1717048139, + meta: { + methodology, + }, + }, + [CHAIN.XLAYER]: { + fetch: fetchLogsAndCalculateFees, + start: 1713379405, + meta: { + methodology, + }, + }, + [CHAIN.ZORA]: { + fetch: fetchLogsAndCalculateFees, + start: 1719239283, + meta: { + methodology, + }, + }, + [CHAIN.BOBA]: { + fetch: fetchLogsAndCalculateFees, + start: 1719631449, + meta: { + methodology, + }, + }, + [CHAIN.ZKLINK]: { + fetch: fetchLogsAndCalculateFees, + start: 1719631449, + meta: { + methodology, + }, + }, + }, +}; + +export default adapter; diff --git a/fees/zyberswap.ts b/fees/zyberswap.ts index ef25180e3d..4c2213ec4e 100644 --- a/fees/zyberswap.ts +++ b/fees/zyberswap.ts @@ -1,16 +1,15 @@ +import * as sdk from "@defillama/sdk"; import { Chain } from "@defillama/sdk/build/general"; import { BreakdownAdapter, BaseAdapter } from "../adapters/types"; import { CHAIN } from "../helpers/chains"; -import customBackfill from "../helpers/customBackfill"; - -import { - getGraphDimensions -} from "../helpers/getUniSubgraph" +import { getGraphDimensions2 } from "../helpers/getUniSubgraph"; const v2Endpoints = { - [CHAIN.ARBITRUM]: "https://api.thegraph.com/subgraphs/name/zyberswap-arbitrum/zyber-amm", -} -const v2Graph = getGraphDimensions({ + [CHAIN.ARBITRUM]: sdk.graph.modifyEndpoint( + "3g83GYhbyHtjy581vpTmN1AP9cB9MjWMh5TiuNpvTU4R", + ), +}; +const v2Graph = getGraphDimensions2({ graphUrls: v2Endpoints, feesPercent: { type: "volume", @@ -19,28 +18,21 @@ const v2Graph = getGraphDimensions({ SupplySideRevenue: 0.15, HoldersRevenue: 0, Revenue: 0.1, - Fees: 0.25 - } + Fees: 0.25, + }, }); const v3Endpoints = { - [CHAIN.ARBITRUM]: "https://api.thegraph.com/subgraphs/name/iliaazhel/zyberswap-info", -} -const v3Graphs = getGraphDimensions({ + [CHAIN.ARBITRUM]: sdk.graph.modifyEndpoint( + "7ZP9MeeuXno2y9pWR5LzA96UtYuZYWTA4WYZDZR7ghbN", + ), +}; +const v3Graphs = getGraphDimensions2({ graphUrls: v3Endpoints, totalVolume: { factory: "factories", field: "totalVolumeUSD", }, - dailyVolume: { - factory: "algebraDayData", - field: "volumeUSD", - dateField: "date" - }, - dailyFees: { - factory: "algebraDayData", - field: "feesUSD", - }, feesPercent: { type: "fees", ProtocolRevenue: 10, @@ -48,25 +40,22 @@ const v3Graphs = getGraphDimensions({ Fees: 10, UserFees: 90, // User fees are 90% of collected fees SupplySideRevenue: 90, // 90% of fees are going to LPs - Revenue: 10 // Revenue is 10% of collected fees - } + Revenue: 10, // Revenue is 10% of collected fees + }, }); const endpointsStable = { - [CHAIN.ARBITRUM]: "https://api.thegraph.com/subgraphs/name/zyberswap-arbitrum/zyber-stableamm" + [CHAIN.ARBITRUM]: sdk.graph.modifyEndpoint( + "H7QEsa69B3bbXZVtmqGaRZVUV8PCUqsKfqXGRb69LHa6", + ), }; -const stableGraph = getGraphDimensions({ +const stableGraph = getGraphDimensions2({ graphUrls: endpointsStable, totalVolume: { factory: "tradeVolumes", field: "volume", }, - dailyVolume: { - factory: "dailyVolume", - field: "volume", - dateField: "timestamp" - }, feesPercent: { type: "volume", UserFees: 0.04, @@ -74,18 +63,19 @@ const stableGraph = getGraphDimensions({ SupplySideRevenue: 0.02, HoldersRevenue: 0, Revenue: 0.02, - Fees: 0.04 - } + Fees: 0.04, + }, }); const methodology = { UserFees: "User pays 0.25% fees on each swap.", Fees: "A 0.25% of each swap is collected as trading fees", - Revenue: "Protocol receives 0.1% on each swap. A part is used to buyback and burn and a part is used to buy WETH and distribute to stakers.", + Revenue: + "Protocol receives 0.1% on each swap. A part is used to buyback and burn and a part is used to buy WETH and distribute to stakers.", ProtocolRevenue: "Protocol receives 0.1% on each swap.", SupplySideRevenue: "All user fees are distributed among LPs.", - HoldersRevenue: "Stakers receive WETH a part of protocol revenue." -} + HoldersRevenue: "Stakers receive WETH a part of protocol revenue.", +}; const methodologyV3 = { UserFees: "User pays dynamic swap fee.", @@ -93,9 +83,9 @@ const methodologyV3 = { Revenue: "Protocol receives 10% of the dynamic swap fee", ProtocolRevenue: "Protocol receives 10% of the dynamic swap fee", SupplySideRevenue: "90% of the dynamic swap fee is distributed to LPs", - HoldersRevenue: "A portion of the protocol fees is used to purchase WETH and distribute to stakers." -} - + HoldersRevenue: + "A portion of the protocol fees is used to purchase WETH and distribute to stakers.", +}; const methodologyStable = { UserFees: "User pays a 0.04% fee on each swap.", @@ -103,17 +93,19 @@ const methodologyStable = { Revenue: "Protocol receives 0.02% of the swap fee", ProtocolRevenue: "Protocol receives 0.02% of the swap fee", SupplySideRevenue: "0.02% of the swap fee is distributed to LPs", - HoldersRevenue: "A portion of the protocol fees is used to purchase WETH and distribute to stakers." -} + HoldersRevenue: + "A portion of the protocol fees is used to purchase WETH and distribute to stakers.", +}; const adapter: BreakdownAdapter = { + version: 2, breakdown: { v2: { [CHAIN.ARBITRUM]: { fetch: v2Graph(CHAIN.ARBITRUM), start: 1674432000, meta: { - methodology + methodology, }, }, }, @@ -122,21 +114,21 @@ const adapter: BreakdownAdapter = { fetch: v3Graphs(chain as Chain), start: 1676887200, meta: { - methodology: methodologyV3 - } - } - return acc + methodology: methodologyV3, + }, + }; + return acc; }, {} as BaseAdapter), stable: { [CHAIN.ARBITRUM]: { fetch: stableGraph(CHAIN.ARBITRUM), start: 1676113200, meta: { - methodology: methodologyStable + methodology: methodologyStable, }, }, }, - } -} + }, +}; export default adapter; diff --git a/helpers/balancer.ts b/helpers/balancer.ts index 1971403c3c..25d71582fd 100644 --- a/helpers/balancer.ts +++ b/helpers/balancer.ts @@ -1,6 +1,4 @@ -import { Fetch, FetchOptions } from "../adapters/types"; -import * as sdk from "@defillama/sdk"; - +import { FetchOptions, FetchV2 } from "../adapters/types"; const event_pools_balance_change = "event PoolBalanceChanged(bytes32 indexed poolId,address indexed liquidityProvider,address[] tokens,int256[] deltas,uint256[] protocolFeeAmounts)" const event_flash_bot = "event FlashLoan(address indexed recipient,address indexed token,uint256 amount,uint256 feeAmount)" @@ -33,7 +31,7 @@ export async function getFees(vault: string, { createBalances, api, getLogs, }: } export function getFeesExport(vault: string, { revenueRatio = 0.25 }: { revenueRatio?: number } = {}) { - return (async (timestamp: number, _: any, options: FetchOptions) => { + return (async (options) => { const dailyFees = await getFees(vault, options) const { createBalances } = options const dailyRevenue = createBalances() @@ -42,6 +40,6 @@ export function getFeesExport(vault: string, { revenueRatio = 0.25 }: { revenueR dailySupplySideRevenue.addBalances(dailyFees) dailyRevenue.resizeBy(revenueRatio) dailySupplySideRevenue.resizeBy(1 - revenueRatio) - return { dailyFees, dailyRevenue, dailySupplySideRevenue, timestamp, } - }) as Fetch + return { dailyFees, dailyRevenue, dailySupplySideRevenue, } + }) as FetchV2 } \ No newline at end of file diff --git a/helpers/blockscoutFees.ts b/helpers/blockscoutFees.ts index e5f57da018..fd34a41928 100644 --- a/helpers/blockscoutFees.ts +++ b/helpers/blockscoutFees.ts @@ -1,15 +1,18 @@ import { Adapter, ChainBlocks, FetchOptions, ProtocolType } from "../adapters/types"; import { httpGet } from '../utils/fetchURL'; +import { CHAIN } from "./chains"; export function blockscoutFeeAdapter(chain: string, url: string, CGToken?: string) { const adapter: Adapter = { + version: 1, adapter: { [chain]: { fetch: async (_timestamp: number, _: ChainBlocks, { createBalances, startOfDay, }: FetchOptions) => { const dailyFees = createBalances() const date = new Date(startOfDay * 1000).toISOString().slice(0, "2011-10-05".length) const fees = await httpGet(`${url}&date=${date}`) - if (CGToken) dailyFees.addCGToken(CGToken, fees.result/1e18) + if (chain == CHAIN.CANTO && CGToken) dailyFees.addCGToken(CGToken, fees.gas_used_today * fees.gas_prices.average /1e18) + else if (CGToken) dailyFees.addCGToken(CGToken, fees.result/1e18) else dailyFees.addGasToken(fees.result) return { diff --git a/helpers/chains.ts b/helpers/chains.ts index 79bf4f9819..033c8ed31e 100644 --- a/helpers/chains.ts +++ b/helpers/chains.ts @@ -3,17 +3,22 @@ export enum CHAIN { ARBITRUM = "arbitrum", AVAX = "avax", BLAST = "blast", + BAHAMUT = "ftn", BOBA = "boba", + BOBA_BNB = "boba_bnb", BSC = "bsc", + BIFROST = "bifrost", CELO = "celo", ETHEREUM = "ethereum", FANTOM = "fantom", HARMONY = "harmony", + HAQQ = "haqq", HECO = "heco", OKEXCHAIN = "okexchain", OPTIMISM = "optimism", POLYGON = "polygon", RONIN = "ronin", + ROOTSTOCK = "rsk", XDAI = "xdai", AURORA = "aurora", MOONRIVER = "moonriver", @@ -26,6 +31,7 @@ export enum CHAIN { CARDANO = "cardano", LITECOIN = "litecoin", BITCOIN = "bitcoin", + BITCOIN_CASH = "bitcoincash", DOGECHAIN = "dogechain", ENERGI = "energi", VELAS = "velas", @@ -133,9 +139,37 @@ export enum CHAIN { ROLLUX = "rollux", MODE = "mode", PERSISTENCE = "persistence", + POLKADEX = "polkadex", JBC = "jbc", ZKFAIR = "zkfair", - ZETA = "zeta" + ZETA = "zeta", + ASTAR = 'astar', + ASTAR_ZKEVM = "astrzk", + FILECOIN = "filecoin", + FRAXTAL = "fraxtal", + IMX = "imx", + KROMA = "kroma", + ZORA = "zora", + SVM = "svm", + ASTRZK = "astrzk", + LYRA = "lyra", + BITLAYER = "bitlayer", + XLAYER = "xlayer", + MERLIN = "merlin", + CHILIZ = "chiliz", + PLANQ = "planq", + BOB = "bob", + TAIKO = "taiko", + SKALE_EUROPA = "skale_europa", + IOTAEVM = "iotaevm", + ZKLINK = "zklink", + DEXALOT = "dexalot", + IMMUTABLEX = "immutablex", + CHAINFLIP = "chainflip", + CRONOS_ZKEVM = "cronos_zkevm", + LOGX = "logx_network", + FLARE = "flare", + NUMBERS = "numbers", } // Don´t use @@ -162,25 +196,25 @@ const ZKSYNC = "zksync"; const MANTLE = "mantle"; // Don't use export { - ZKSYNC, ARBITRUM, + AURORA, AVAX, + BITCOIN, BOBA, BSC, CELO, + DOGE, ETHEREUM, FANTOM, HARMONY, HECO, + LITECOIN, + MANTLE, + MOONRIVER, OKEXCHAIN, OPTIMISM, POLYGON, RONIN, XDAI, - AURORA, - MOONRIVER, - BITCOIN, - LITECOIN, - DOGE, - MANTLE + ZKSYNC, }; diff --git a/helpers/compoundV2.ts b/helpers/compoundV2.ts index 5987040352..68c171dcaa 100644 --- a/helpers/compoundV2.ts +++ b/helpers/compoundV2.ts @@ -1,5 +1,5 @@ import ADDRESSES from './coreAssets.json' -import { Fetch, FetchOptions } from "../adapters/types"; +import { BaseAdapter, Fetch, FetchOptions, IJSON, SimpleAdapter } from "../adapters/types"; import * as sdk from "@defillama/sdk"; const comptrollerABI = { @@ -59,4 +59,24 @@ export function getFeesExport(market: string) { }) return { timestamp, dailyFees, dailyRevenue, dailyHoldersRevenue, dailySupplySideRevenue } }) as Fetch -} \ No newline at end of file +} + +export function compoundV2Export(config: IJSON) { + const exportObject: BaseAdapter = {} + Object.entries(config).map(([chain, market]) => { + exportObject[chain] = { + fetch: (async (options: FetchOptions) => { + const { dailyFees, dailyRevenue } = await getFees(market, options, {}) + const dailyHoldersRevenue = dailyRevenue + const dailySupplySideRevenue = options.createBalances() + dailySupplySideRevenue.addBalances(dailyFees) + Object.entries(dailyRevenue.getBalances()).forEach(([token, balance]) => { + dailySupplySideRevenue.addTokenVannila(token, Number(balance) * -1) + }) + return { dailyFees, dailyRevenue, dailyHoldersRevenue, dailySupplySideRevenue } + }) , + start: 0, + } + }) + return { adapter: exportObject, version: 2 } as SimpleAdapter +} diff --git a/helpers/coreAssets.json b/helpers/coreAssets.json index af9ce98911..7424bd45fc 100644 --- a/helpers/coreAssets.json +++ b/helpers/coreAssets.json @@ -41,10 +41,17 @@ "LUSD": "0x5f98805A4E8be255a32880FDeC7F6728C6568bA0", "sUSD_OLD": "0x57ab1e02fee23774580c119740129eac7081e9d3", "sUSD": "0x57Ab1ec28D129707052df4dF418D58a2D46d5f51", + "sUSDe": "0x9D39A5DE30e57443BfF2A8307A4256c8797A3497", "SUSHI": "0x6b3595068778dd592e39a122f4f5a5cf09c90fe2", "cbETH": "0xBe9895146f7AF43049ca1c1AE358B0541Ea49704", "FDUSD": "0xc5f0f7b66764f6ec8c8dff7ba683102295e16409", - "EETH": "0x35fa164735182de50811e8e2e824cfb9b6118ac2" + "EETH": "0x35fa164735182de50811e8e2e824cfb9b6118ac2", + "AEVO": "0xB528edBef013aff855ac3c50b381f253aF13b997", + "STONE": "0x4d831e22f062b5327dfdb15f0b6a5df20e2e3dd0", + "USDM": "0x59D9356E565Ab3A36dD77763Fc0d87fEaf85508C", + "USDe": "0x4c9edd5852cd905f086c759e8383e09bff1e68b3", + "amprETH": "0xcDC51F2B0e5F0906f2fd5f557de49D99c34Df54e", + "amphrLRT": "0x06824C27C8a0DbDe5F72f770eC82e3c0FD4DcEc3" }, "fantom": { "WFTM": "0x21be370d5312f44cb42ce377bc9b8a0cef1a4c83", @@ -74,12 +81,14 @@ }, "avax": { "WAVAX": "0xb31f66aa3c1e785363f0875a1b74e27b85fd66c7", + "SAVAX": "0x2b2c81e08f1af8835a78bb2a90ae924ace0ea4be", "USDC": "0xb97ef9ef8734c71904d8002f8b6bc66dd9c48a6e", "EURC": "0xc891eb4cbdeff6e073e859e987815ed1505c2acd", "DAI": "0xd586E7F844cEa2F87f50152665BCbc2C279D8d70", "USDT_e": "0xc7198437980c041c805a1edcba50c1ce5db95118", "USDt": "0x9702230a8ea53601f5cd2dc00fdbc13d4df4a8c7", "BTC_b": "0x152b9d0fdc40c096757f570a51e494bd4b943e50", + "WBTC_e": "0x50b7545627a5162F82A992c33b87aDc75187B218", "USDC_e": "0xa7d7079b0fead91f3e65f86e8915cb59c1a4c664", "WETH_e": "0x49d5c2bdffac6ce2bfdb6640f4f80f226bc10bab", "JOE": "0x6e84a6216ea6dacc71ee8e6b0a5b7322eebc0fdd", @@ -196,6 +205,7 @@ "OP": "0x4200000000000000000000000000000000000042", "WETH": "0x121ab82b49b2bc4c7901ca46b8277962b4350204", "WETH_1": "0x4200000000000000000000000000000000000006", + "WSTETH": "0x1F32b1c2345538c0c6f582fCB022739c4A194Ebb", "BitANT": "0x5029c236320b8f15ef0a657054b84d90bfbeded3", "FEI": "0x35d48a789904e9b15705977192e5d95e2af7f1d3", "alUSD": "0xcb8fa9a76b8e203d8c3797bf438d8fb81ea3326a", @@ -216,7 +226,10 @@ "USDC": "0xe3f5a90f9cb311505cd691a46596599aa1a0ad7d", "ETH": "0x639a647fbe20b6c8ac19e48e2de44ea792c62c5c", "ELK": "0xe1c110e1b1b4a1ded0caf3e42bfbdbb7b5d7ce1c", - "BEPRO": "0xcb4a593ce512d78162c58384f0b2fd6e802c2c47" + "BEPRO": "0xcb4a593ce512d78162c58384f0b2fd6e802c2c47", + "MOVR": "0xffffffff98e37bf6a393504b5adc5b53b4d0ba11", + "BNC": "0xffffffff3646a00f78cadf8883c5a2791bfcddc4", + "KSM": "0xffffffffc6deec7fc8b11a2c8dde9a59f8c62efe" }, "moonbeam": { "WGLMR": "0x5f6c5c2fb289db2228d159c69621215e354218d7", @@ -232,7 +245,9 @@ "MOVR": "0x1d4c2a246311bb9f827f4c768e277ff5787b7d7e", "xcUSDT": "0xffffffffea09fb06d082fd1275cd48b191cbcd1d", "BEPRO": "0x4edf8e0778967012d46968ceadb75436d0426f88", - "stDOT": "0xfa36fe1da08c89ec72ea1f0143a35bfd5daea108" + "stDOT": "0xfa36fe1da08c89ec72ea1f0143a35bfd5daea108", + "VGLMR": "0xffffffff99dabe1a8de0ea22baa6fd48fde96f6c", + "FIL": "0xffffffffcd0ad0ea6576b7b285295c85e94cf4c1" }, "arbitrum": { "WETH": "0x82af49447d8a07e3bd95bd0d56f35241523fbab1", @@ -256,7 +271,8 @@ "fGLP": "0x4e971a87900b931ff39d1aad67697f49835400b6", "GMX": "0xfc5A1A6EB076a2C7aD06eD22C90d7E710E35ad0a", "WSTETH": "0x5979D7b546E38E414F7E9822514be443A4800529", - "plvGLP": "0x5326e71ff593ecc2cf7acae5fe57582d6e74cff1" + "plvGLP": "0x5326e71ff593ecc2cf7acae5fe57582d6e74cff1", + "USDe": "0x5d3a1ff2b6bab83b63cd9ad0787074081a52ef34" }, "fuse": { "WFUSE": "0x0be9e53fd7edac9f859882afdda116645287c629", @@ -267,7 +283,14 @@ "USDT": "0xfadbbf8ce7d5b7041be672561bba99f79c532e10", "KNC": "0x43b17749b246fd2a96de25d9e4184e27e09765b0", "BUSD": "0x6a5f6a8121592becd6747a38d67451b310f7f156", - "null": "0x0000000000000000000000000000000000000000" + "null": "0x0000000000000000000000000000000000000000", + "USDC_2": "0x28c3d1cd466ba22f6cae51b1a4692a831696391a", + "USDT_2": "0x68c9736781e9316ebf5c3d49fe0c1f45d2d104cd", + "VOLT": "0x34ef2cc892a88415e9f02b91bfa9c91fc0be6bd4", + "FUSD_3": "0xce86a1cf3cff48139598de6bf9b1df2e0f79f86f", + "WETH_2": "0x5622f6dc93e08a8b717b149677930c38d5d50682", + "BNB": "0x6acb34b1df86e254b544189ec32cf737e2482058", + "BNB_2": "0x117c0419352ddb6fe575a67faa70315bdc4a93f3" }, "evmos": { "WEVMOS": "0xd4949664cd82660aae99bedc034a0dea8a0bd517", @@ -486,6 +509,10 @@ "SWAPZ": "0x9b6fbf0ea23faf0d77b94d5699b44062e5e747ac", "DAI": "0xe3f5a90f9cb311505cd691a46596599aa1a0ad7d", "SCAR": "0x8d9fb713587174ee97e91866050c383b5cee6209", + "sVLX": "0xaadbaa6758fc00dec9b43a0364a372605d8f1883", + "VLX": "0x2b1abeb48f875465bf0d3a262a2080ab1c7a3e39", + "ETH_1": "0x380f73bad5e7396b260f737291ae5a8100baabcd", + "USDT_1": "0x4b773e1ae1baa4894e51cc1d1faf485c91b1012f", "ADA": "0x3611fbfb06ffbcef9afb210f6ace86742e6c14a4" }, "telos": { @@ -496,7 +523,8 @@ "USDC": "0x818ec0a7fe18ff94269904fced6ae3dae6d6dc0b", "USDT": "0xefaeee334f0fd1712f9a8cc375f427d9cdd40d73", "STLOS": "0xb4b01216a5bc8f1c8a33cd990a1239030e60c905", - "sBUSD": "0x017043607270ecbb440e20b0f0bc5e760818b3d8" + "sBUSD": "0x017043607270ecbb440e20b0f0bc5e760818b3d8", + "syUSDC": "0xe6E5f3d264117E030C21920356641DbD5B3d660c" }, "reichain": { "BNB": "0xf8ab4aaf70cef3f3659d3f466e35dc7ea10d4a5d", @@ -523,6 +551,7 @@ "BUSDbs": "5RpUwQ8wtdPCZHhu6MERp2RGrpobsbZ6MH5dDHkUjs2" }, "astar": { + "WASTR_1": "0xaeaaf0e2c81af264101b9129c00f4440ccf0f720", "WASTR": "0xecc867de9f5090f55908aaa1352950b9eed390cd", "WETH": "0x81ecac0d6be0550a00ff064a4f9dd2400585fe9c", "WBTC": "0xad543f18cff85c77e140e3e5e3c3392f6ba9d5ca", @@ -532,7 +561,6 @@ "USDC": "0x6a2d262d56735dba19dd70682b39f6be9a931d98", "USDT": "0x3795c36e7d12a8c252a20c5a7b455f7c57b60283", "nativeUSDT": "0xffffffff000000000000000000000001000007c0", - "ARSW": "0xde2578edec4669ba7f41c5d5d2386300bcea4678", "DOT": "0xffffffffffffffffffffffffffffffffffffffff", "DAI": "0x6de33698e9e9b787e09d3bd7771ef63557e148bb", "MUUU": "0xc5bcac31cf55806646017395ad119af2441aee37", @@ -554,7 +582,18 @@ "ATID": "0x5271d85ce4241b310c0b34b7c2f1f036686a6d7c", "JPYC": "0x431d5dff03120afa4bdf332c61a6e1766ef37bdb", "aUSD": "0xffffffff00000000000000010000000000000001", - "vDOT": "0xFfFfFfff00000000000000010000000000000008" + "vDOT": "0xFfFfFfff00000000000000010000000000000008", + "ASTR": "0xffffffff00000000000000010000000000000010" + }, + "astarzk": { + "WETH": "0xe9cc37904875b459fa5d0fe37680d36f1ed55e38", + "USDC": "0xa8ce8aee21bc2a48a5ef670afcc9274c7bbbc035", + "USDT": "0x1e4a5963abfd975d8c9021ce480b42188849d41d", + "WBTC": "0xea034fb02eb1808c2cc3adbc15f447b93cbe08e1", + "DAI": "0xc5015b9d9161dca7e18e32f6f25c4ad850731fd4", + "MATIC": "0xa2036f0538221a77a3937f1379699f44945018d0", + "wstETH": "0x5d8cff95d7a57c0bf50b30b43c7cc0d52825d4a9", + "weETH": "0xcd68dff4415358c35a28f96fd5bf7083b22de1d6" }, "cardano": { "ADA": "ADA" @@ -636,7 +675,8 @@ }, "kujira": { "KUJI": "ukuji", - "USK": "factory/kujira1qk00h5atutpsv900x202pxx42npjr9thg58dnqpa72f2p7m2luase444a7/uusk" + "USK": "factory/kujira1qk00h5atutpsv900x202pxx42npjr9thg58dnqpa72f2p7m2luase444a7/uusk", + "FUZION": "factory/kujira1sc6a0347cc5q3k890jj0pf3ylx2s38rh4sza4t/ufuzn" }, "injective": { "INJ": "inj", @@ -659,7 +699,12 @@ "USDC": "0xea1199d50ee09fa8062fd9da3d55c6f90c1babd2" }, "tomochain": { - "WTOMO": "0xb1f66997a5760428d3a87d68b90bfe0ae64121cc" + "WTOMO": "0xb1f66997a5760428d3a87d68b90bfe0ae64121cc", + "TOMO": "0xc054751bdbd24ae713ba3dc9bd9434abe2abc1ce", + "USDT": "0xbbbfab9dcc27771d21d027f37f36b67cc4a25db0", + "USDC": "0x20cc4574f263c54eb7ad630c9ac6d4d9068cf127", + "ETH": "0x9ede19ede2baf93d25fba4c8f58577e008b8f963", + "SAROS": "0xb786d9c8120d311b948cf1e5aa48d8fbacf477e2" }, "ethereumclassic": { "WETC": "0x82A618305706B14e7bcf2592D4B9324A366b6dAd" @@ -723,7 +768,8 @@ "rsk": { "WRBTC": "0x967f8799af07df1534d48a95a5c9febe92c53ae0", "WRBTC1": "0x542fDA317318eBF1d3DEAf76E0b632741A7e677d", - "ETHs": "0x1d931bf8656d795e50ef6d639562c5bd8ac2b78f" + "ETHs": "0x1d931bf8656d795e50ef6d639562c5bd8ac2b78f", + "rUSDT": "0xef213441a85df4d7acbdae0cf78004e1e486bb96" }, "polis": { "WPOLIS": "0x6fc851b8d66116627fb1137b9d5fe4e2e1bea978" @@ -752,7 +798,8 @@ "CELER_DAI": "0x8d87a65ba30e09357fa2edea2c80dbac296e5dec2b18287113500b902942929d::celer_coin_manager::DaiCoin", "CELER_ETH": "0x8d87a65ba30e09357fa2edea2c80dbac296e5dec2b18287113500b902942929d::celer_coin_manager::WethCoin", "CELER_WBTC": "0x8d87a65ba30e09357fa2edea2c80dbac296e5dec2b18287113500b902942929d::celer_coin_manager::WbtcCoin", - "amAPT": "0x111ae3e5bc816a5e63c2da97d0aa3886519e0cd5e4b046659fa35796bd11542a::amapt_token::AmnisApt" + "amAPT": "0x111ae3e5bc816a5e63c2da97d0aa3886519e0cd5e4b046659fa35796bd11542a::amapt_token::AmnisApt", + "aBTC": "0x4e1854f6d332c9525e258fb6e66f84b6af8aba687bbcb832a24768c4e175feec::abtc::ABTC" }, "dogechain": { "WWDOGE": "0xb7ddc6414bf4f5515b52d8bdd69973ae205ff101", @@ -923,7 +970,6 @@ "YFI": "BLRxWVJWaVuR2CsCoTvTw2bDZ3sQLeTbCofcJv7dP5J4", "APE": "2GBgdhqMjUPqreqPziXvZFSmDiQVrxNuGxR1z7ZVsm4Z", "CRV": "3KhNcHo4We1G5EWps7b1e5DTdLgWDzctc8S6ynu37KAb", - "USDC": "6XtHjpXbs9RRJP2Sr9GUyVqzACcby9TkThHXnjVC5CDJ", "LINK": "2bbGhKo5C31iEiB4CwGuqMYwjD7gCA9eXmm51fe2v8vT", "AAVE": "7TMu26hAs7B2oW6c5sfx45KSZT7GQA3TZNYuCav8Dcqt", "NSBT": "6nSpVyNH7yM69eg446wrQR94ipbbcmZMU1ENPwanC97g", @@ -943,7 +989,6 @@ "USDN": "DG2xFkPdDwKUoBkzGAhQtLpSGzfXLiCYPEzeKH2Ad24p", "UST": "2thtesXvnVMcCnih9iZbJL3d2NQZMfzENJo8YFj6r5jU", "LUNA": "6QUVF8nVVVvM7do7JT2eJ5o5ehnZgXUg13ysiB9JiQrZ", - "USDT": "34N9YcEETLWn93qYQ64EsP1x89tSruJU44RrEMSXXEPJ", "WAVES": "WAVES" }, "songbird": { @@ -1108,9 +1153,7 @@ "XSP": "0x36726235dadbdb4658d33e62a249dca7c4b2bc68" }, "kardia": { - "WKAI": "0xaf984e23eaa3e7967f3c5e007fbe397d8566d23d", - "USDT": "0x551a5dcac57c66aa010940c2dcff5da9c53aa53b", - "KUSD_T": "0x92364ec610efa050d296f1eeb131f2139fb8810e" + "WKAI": "0xaf984e23eaa3e7967f3c5e007fbe397d8566d23d" }, "empire": { "USDC": "0xc61a71c75ed4742dcae74b8cac27a37d46fc6751" @@ -1126,7 +1169,8 @@ "AVAX": "0x4200000000000000000000000000000000000023" }, "omax": { - "WOMAX": "0xfebabc6a9b2ec46d6357879b8bf39b593f11a5b9" + "WOMAX": "0xfebabc6a9b2ec46d6357879b8bf39b593f11a5b9", + "OMAX": "0x373e4b4E4D328927bc398A9B50e0082C6f91B7bb" }, "wemix": { "WWEMIX": "0x7d72b22a74a216af4a002a1095c8c707d6ec1c5f", @@ -1217,6 +1261,7 @@ "EVMOS_boot": "4B322204B4F59D770680FE4D7A565DDC3F37BFF035474B717476C66A4F83DD72" }, "starknet": { + "STRK": "0x04718f5a0fc34cc1af16a1cdee98ffb20c31f5cd61d6ab07201858f4287c938d", "DAI": "0x00da114221cb83fa859dbdb4c44beeaa0bb37c7537ad5ae66fe5e0efd20e6eb3", "USDC": "0x053c91253bc9682c04929ca02ed00b3e423f6710d2ee7e0d5ebb06f3ecf368a8", "USDT": "0x068f5c6a61780768455de69077e07e89787839bf8166decfbf92b645209c0fb8", @@ -1224,7 +1269,10 @@ "ETH": "0x049d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", "WSTETH": "0x042b8f0484674ca266ac5d08e4ac6a3fe65bd3129795def2dca5c34ecc5f96d2", "LUSD": "0x070a76fd48ca0ef910631754d77dd822147fe98a569b826ec85e3c33fde586ac", - "RETH": "0x0319111a5037cbec2b3e638cc34a3474e2d2608299f3e62866e9cc683208c610" + "RETH": "0x0319111a5037cbec2b3e638cc34a3474e2d2608299f3e62866e9cc683208c610", + "UNO": "0x0719b5092403233201aa822ce928bd4b551d0cdb071a724edd7dc5e5f57b7f34", + "NSTSTRK": "0x04619e9ce4109590219c5263787050726be63382148538f3f936c22aa87d2fc2", + "ZEND": "0x00585c32b625999e6e5e78645ff8df7a9001cf5cf3eb6b80ccdd16cb64bd3a34" }, "ton": { "TON": "0x0000000000000000000000000000000000000000", @@ -1233,12 +1281,14 @@ "TON_3": "EQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAM9c", "TON_4": "EQCajaUU1XXSAjTD-xOV7pE49fGtg4q8kF3ELCOJtGvQFQ2C", "USDC": "EQC61IQRl0_la95t27xhIpjxZt32vl1QQVF2UgTNuvD18W-4", - "USDT": "EQC_1YoM8RBixN95lz7odcF3Vrkc_N8Ne7gQi7Abtlet_Efi", + "oUSDT": "EQC_1YoM8RBixN95lz7odcF3Vrkc_N8Ne7gQi7Abtlet_Efi", "ETH": "EQAW42HutyDem98Be1f27PoXobghh81umTQ-cGgaKVmRLS7-", "MATIC": "EQBq4d4GPyBoh-Pjnf3wxUyQSS28WY2Yt-7cPAG8FHpWpNRX", "ORC": "EQDCIEo0HUUYsAV-lTMviOd-GkSXfVPsNZMGjRaNOA_6--FD", "MEGA": "EQBf6-YoR9xylol_NwjHrLkrTFAZJCX-bsd-Xx_902OaPaBf", - "WEMIX": "EQCf7Nb341dxOE3N0jimngRxGEV8T3zo-eU2EZVs_nchNhhZ" + "WEMIX": "EQCf7Nb341dxOE3N0jimngRxGEV8T3zo-eU2EZVs_nchNhhZ", + "jUSDT": "EQBynBO23ywHy_CgarY9NK9FTz0yDsG82PtcbSTQgGoXwiuA", + "USDT": "EQCxE6mUtQJKFnGfaROTKOt1lZbDiiX1kCixRv7Nw2Id_sDs" }, "defichain": { "DFI": "DFI", @@ -1258,8 +1308,10 @@ }, "core": { "WCORE": "0x40375c92d9faf44d2f9db9bd9ba41a3317a2404f", + "WCORE_1": "0x191e94fa59739e188dce837f7f6978d84727ad01", "USDT": "0x900101d06a7426441ae63e9ab3b9b0f63be145f1", - "USDC": "0xa4151b2b3e269645181dccf2d426ce75fcbdeca9" + "USDC": "0xa4151b2b3e269645181dccf2d426ce75fcbdeca9", + "coreBTC": "0x8034aB88C3512246Bf7894f57C834DdDBd1De01F" }, "crab": { "WCRAB": "0x2d2b97ea380b0185e9fdf8271d1afb5d2bf18329" @@ -1278,7 +1330,18 @@ "BUSD": "0x35bf4004c3fc9f509259d4942da6bae3669e1db1", "WMAPO": "0x13cb04d4a5dfb6398fc5ab005a6c84337256ee23", "USDC": "0x9f722b2cb30093f766221fd0d37964949ed66918", - "ETH": "0x05ab928d446d8ce6761e368c8e7be03c3168a9ec" + "ETH": "0x05ab928d446d8ce6761e368c8e7be03c3168a9ec", + "ROUP": "0x3e76deF74d4187B5a01aBE4E011Bd94d9f057d94", + "WROUP": "0x5a1c3f3aaE616146C7b9bf9763E0ABA9bAFc5eaE", + "ORDI": "0xB719e46B6eB5b23E2759526CdE24589d87097733", + "WORDI": "0x9CA528368964cFb92cfFdd51dCcED25E27ACCef9", + "RATS": "0xcAF17cDdb80F72484e5A279921b98a0a9A2391ee", + "WRATS": "0x6369414F2b0e973c7E85A362141aA1430bc30056", + "CSAS": "0x640a4C0AaA4870BaDE2F646B7Da87b3D53819C4f", + "WSAS": "0x141b30Dd30FAFb87ec10312d52e5dbD86122FE14", + "BTCS": "0x0e2cA3e003f3c73C8cC18ec244d46DB9d4c4DCEB", + "WBTCS": "0xBE81B9390D894fEBf5e5D4Ea1486a003C1e8dc63", + "MMSS": "0x0fBb3B3Fb1e928f75B3Ed8b506bAb4503373fdca" }, "bone": { "WBONE": "0xcda1fa23ff3b9b7172be82237bf662efb69437e9" @@ -1324,6 +1387,7 @@ "USDC_SOL": "0xb231fcda8bbddb31f2ef02e6161444aec64a514e2c89279584ac9806ce9cf037::coin::COIN", "USDC_ARB": "0xe32d3ebafa42e6011b87ef1087bbc6053b499bf6f095807b9013aff5a6ecd7bb::coin::COIN", "USDC_BNB": "0x909cba62ce96d54de25bec9502de5ca7b4f28901747bbf96b76c2e63ec5f1cba::coin::COIN", + "BUCK": "0xce7ff77a83ea0cb6fd39bd8748e2ec89a3f41e8efdc3f4eb123e0ca37b184db2::buck::BUCK", "SUI": "0x2::sui::SUI" }, "grove": { @@ -1345,6 +1409,7 @@ }, "pulse": { "WPLS": "0xa1077a294dde1b09bb078844df40758a5d0f9a27", + "PLSX": "0x95B303987A60C71504D99Aa1b13B4DA07b0790ab", "ETH": "0x02dcdd04e3f455d838cd1249292c58f3b79e3c3c", "USDC": "0x15D38573d2feeb82e7ad5187aB8c1D52810B1f07", "USDT": "0x0Cb6F5a34ad42ec934882A05265A7d5F59b51A2f", @@ -1361,7 +1426,14 @@ }, "stacks": { "WSTX": "SP1Z92MPDQEWZXW36VX71Q25HKF5K2EPCJ304F275.wstx-token-v4a", - "WBTC": "SP3DX3H4FEYZJZ586MFBS25ZW3HZDMEW92260R2PR.Wrapped-Bitcoin::wrapped-bitcoin" + "WSTX_1": "SP2C2YFP12AJZB4MABJBAJ55XECVS7E4PMMZ89YZR.wstx-token::wstx", + "WSTX_2": "SP1Y5YSTAHZ88XYK1VPDH24GY0HPX5J4JECTMY4A1.wstx", + "ABTC": "SP3K8BC0PPEVCV7NZ6QSRWPQ2JE9E5B6N3PA0KBR9.token-abtc", + "WBTC": "SP3DX3H4FEYZJZ586MFBS25ZW3HZDMEW92260R2PR.Wrapped-Bitcoin::wrapped-bitcoin", + "stSTX": "SP4SZE494VC2YC5JYG7AYFQ44F5Q4PYV7DVMDPBG.ststx-token::ststx", + "USDT": "SP3K8BC0PPEVCV7NZ6QSRWPQ2JE9E5B6N3PA0KBR9.token-susdt::bridged-usdt", + "aeUSDC": "SP3Y2ZSH8P7D50B0VBTSX11S7XSG24M1VB9YFQA4K.token-aeusdc", + "aBTC": "SP3K8BC0PPEVCV7NZ6QSRWPQ2JE9E5B6N3PA0KBR9.token-abtc::bridged-btc" }, "neon_evm": { "WNEON": "0xb14760c064a1b9eaf9ec5a8a421971e40a51b59c" @@ -1402,7 +1474,9 @@ "USDCar": "factory/sei189adguawugk3e55zn63z8r9ll29xrjwca636ra7v7gxuzn98sxyqwzt47l/7edDfnf4mku8So3t4Do215GNHwASEwCWrdhM5GqD51xZ", "USDTet": "factory/sei189adguawugk3e55zn63z8r9ll29xrjwca636ra7v7gxuzn98sxyqwzt47l/HktfLoADCk9mnjv7XJiN4YXK9ayE6xinLzt8wzcsR2rY", "USDTbs": "factory/sei189adguawugk3e55zn63z8r9ll29xrjwca636ra7v7gxuzn98sxyqwzt47l/871jbn9unTavWsAe83f2Ma9GJWSv6BKsyWYLiQ6z3Pva", - "WBTC": "factory/sei189adguawugk3e55zn63z8r9ll29xrjwca636ra7v7gxuzn98sxyqwzt47l/7omXa4gryZ5NiBmLep7JsTtTtANCVKXwT9vbN91aS1br" + "WBTC": "factory/sei189adguawugk3e55zn63z8r9ll29xrjwca636ra7v7gxuzn98sxyqwzt47l/7omXa4gryZ5NiBmLep7JsTtTtANCVKXwT9vbN91aS1br", + "USDC": "0x3894085Ef7Ff0f0aeDf52E2A2704928d1Ec074F1", + "USDT": "0xB75D0B03c06A926e488e2659DF1A861F860bD3d1" }, "op_bnb": { "WBNB": "0x4200000000000000000000000000000000000006", @@ -1446,6 +1520,7 @@ "BONE_2": "0x6c19a35875217b134e963ca9e61b005b855cad21", "BONE_3": "0x1b2f364032f12bd8a4c89e672e6272de03ae2680", "BONE_4": "0xa2899c776baaf9925d432f83c950d5054a6cf59c", + "BONE_5": "0x839FdB6cc98342B428E074C1573ADF6D48CA3bFd", "DAI": "0x50c5725949a6f0c72e6c4a641f24049a917db0cb" }, "nos": { @@ -1456,7 +1531,8 @@ "kroma": { "WETH": "0x4200000000000000000000000000000000000001", "USDC": "0x49A5010110a358d9069282873F3e7eCf6B41DC10", - "USDT": "0x0Cf7c2A584988871b654Bd79f96899e4cd6C41C0" + "USDT": "0x0Cf7c2A584988871b654Bd79f96899e4cd6C41C0", + "WEMIX": "0x3720b1dc2c8dde3bd6cfcf0b593d0a2bbcac856e" }, "radixdlt": { "XRD": "resource_rdx1tknxxxxxxxxxradxrdxxxxxxxxx009923554798xxxxxxxxxradxrd", @@ -1489,12 +1565,15 @@ "UnifiedDAI": "0xcDB9579Db96EB5C8298dF889D915D0FF668AfF2a", "WITCH": "0xB1f3A83597Bce2AD842c29bD750AE17afc474137", "SAT": "0x17102AC78a02a98fC78B0c29B7b0506f035A99E5", - "BIFI": "0x047938C3aD13c1eB821C8e310B2B6F889b6d0003" + "BIFI": "0x047938C3aD13c1eB821C8e310B2B6F889b6d0003", + "WBTC": "0x7b8FAC5F29E101BaaB33c5f9c39d4F85ba2cc7C1", + "BTCB": "0xd267F821F1b8344B5A63626c8c824697194A173E" }, "scroll": { "WETH": "0x5300000000000000000000000000000000000004", "USDT": "0xf55bec9cafdbe8730f096aa55dad6d22d44099df", - "USDC": "0x06eFdBFf2a14a7c8E15944D1F4A48F9F95F663A4" + "USDC": "0x06eFdBFf2a14a7c8E15944D1F4A48F9F95F663A4", + "STONE": "0x80137510979822322193FC997d400D5A6C747bf7" }, "darwinia": { "RING": "0xe7578598aac020abfb918f33a20fad5b71d670b4" @@ -1522,7 +1601,11 @@ "MEER_2": "0x457dE4e275A6b3C0D3750519221dD1dF19d54f01" }, "mode": { - "WETH": "0x4200000000000000000000000000000000000006" + "STONE": "0x80137510979822322193fc997d400d5a6c747bf7", + "WETH": "0x4200000000000000000000000000000000000006", + "USDC": "0xd988097fb8612cc24eeC14542bC03424c656005f", + "USDT": "0xf0F161fDA2712DB8b566946122a5af183995e2eD", + "WBTC": "0xcdd475325d6f564d27247d1dddbb0dac6fa0a5cf" }, "zilliqa": { "WZIL": "0x94e18ae7dd5ee57b55f30c4b63e2760c09efb192", @@ -1552,10 +1635,7 @@ }, "airdao": { "SAMB": "0x2b2d892c3fe2b4113dd7ac0d2c1882af202fb28f", - "USDC": "0xd8dd0273d31c1cd9dba104daca7c1dfee4f7b805", - "BUSD": "0x7a477aa8ed4884509387dba81ba6f2b7c97597e2", - "AINU": "0x618220b06e8e30a972ffbe66fe56588fe4d5044a", - "BOND": "0x096b5914c95c34df19500daff77470c845ec749d" + "BUSD": "0x7a477aa8ed4884509387dba81ba6f2b7c97597e2" }, "acala": { "DOT": "0x0000000000000000000100000000000000000002", @@ -1566,6 +1646,174 @@ "NEW": "0xf4905b9bc02ce21c98eac1803693a9357d5253bf" }, "zeta": { + "USDC": "0x05BA149A7bd6dC1F937fA9046A9e05C05f3b18b0", + "USDC_1": "0x0cbe0dF132a6c6B4a2974Fa1b7Fb953CF0Cc798a", + "USDT": "0x7c8dDa80bbBE1254a7aACf3219EBe1481c6E01d7", + "USDT_1": "0x91d4F0D54090Df2D81e834c3c8CE71C6c865e79F", + "ETH": "0xd97b1de3619ed2c6beb3860147e30ca8a7dc9891", + "BNB": "0x48f80608b672dc30dc7e3dbbd0343c5f02c738eb", + "BTC": "0x13A0c5930C028511Dc02665E7285134B6d11A5f4", "WZETA": "0x5f0b1a82749cb4e2278ec87f8bf6b618dc71a8bf" + }, + "blast": { + "USDB": "0x4300000000000000000000000000000000000003", + "fwWETH": "0x66714db8f3397c767d0a602458b5b4e3c0fe7dd1", + "fwUSDB": "0x866f2c06b83df2ed7ca9c2d044940e7cd55a06d6", + "WETH": "0x4300000000000000000000000000000000000004", + "ezETH": "0x2416092f143378750bb29b79eD961ab195CcEea5", + "weETH": "0x04C0599Ae5A44757c0af6F9eC3b93da8976c150A" + }, + "chz": { + "WCHZ": "0x721ef6871f1c4efe730dce047d40d1743b886946" + }, + "bitrock": { + "WBR": "0x413f0e3a440aba7a15137f4278121450416882d5", + "BR": "0xde67d97b8770dc98c746a3fc0093c538666eb493" + }, + "btn": { + "BTN": "0x8148b71232162ea7a0b1c8bfe2b8f023934bfb58" + }, + "area": { + "AREA": "0x298b6a733cd34e41ca87b264d968c8ca7b0b9931", + "WAREA": "0x1d1bc800e71576a59f9ef88bb679fa13c2e10abf" + }, + "defiverse": { + "OAS": "0x5a89E11Cb554E00c2f51C4bb7F05bc7Ab0Fa6351", + "USDC": "0x7c6b91D9Be155A6Db01f749217d76fF02A7227F2", + "WBTC": "0x50c5725949A6F0c72E6C4a641F24049A917DB0Cb", + "ETH": "0xE7798f023fC62146e8Aa1b36Da45fb70855a77Ea" + }, + "xai": { + "XAI": "0x36be1fd6ff2a6beb34b500a04f89103a524516d8", + "USDC": "0x300a7b57dc85b6a9776e249614abf0fe5c9905fb" + }, + "merlin": { + "SATS": "0x4dcb91cc19aadfe5a6672781eb09abad00c19e4c", + "RATS": "0x69181a1f082ea83a152621e4fa527c936abfa501", + "ORDI": "0x0726523eba12edad467c55a962842ef358865559", + "USDT": "0x967aec3276b63c5e2262da9641db9dbebb07dc0d", + "USDC": "0x6b4ecada640f1b30dbdb68f77821a03a5f282ebe", + "WBTC": "0xF6D226f9Dc15d9bB51182815b320D3fBE324e1bA", + "WBTC_1": "0xB880fd278198bd590252621d4CD071b1842E9Bcd" + }, + "ftn": { + "USDC": "0x4237e0A5b55233D5B6D6d1D9BF421723954130D8" + }, + "q": { + "WBTC": "0xde397e6C442A3E697367DecBF0d50733dc916b79", + "WDAI": "0xDeb87c37Dcf7F5197026f574cd40B3Fc8Aa126D1", + "WUSDC": "0x79Cb92a2806BF4f82B614A84b6805963b8b1D8BB", + "WETH": "0xd56F9ffF3fe3BD0C7B52afF9A42eb70E05A287Cc", + "ELK": "0xeEeEEb57642040bE42185f49C52F7E9B38f8eeeE" + }, + "zklink": { + "WBTC": "0xda4aaed3a53962c83b35697cd138cc6df43af71f", + "USDT": "0x2f8a25ac62179b31d62d7f80884ae57464699059", + "USDC": "0x1a1a3b2ff016332e866787b311fcb63928464509", + "WETH": "0x8280a4e7D5B3B658ec4580d3Bc30f5e50454F169" + }, + "kinto": { + "WETH": "0x7526B5318Cbe690FBd3eC8DD7ad122f4F1b1d76F" + }, + "bevm": { + "WBTC": "0xB5136FEba197f5fF4B765E5b50c74db717796dcD" + }, + "degen": { + "WDEGEN": "0xeb54dacb4c2ccb64f8074eceea33b5ebb38e5387" + }, + "imx": { + "WIMX": "0x3A0C2Ba54D6CBd3121F01b96dFd20e99D1696C9D", + "ETH": "0x52a6c53869ce09a731cd772f245b97a4401d3348", + "USDC": "0x6de8acc0d406837030ce4dd28e7c08c5a96a30d2" + }, + "sapphire": { + "WOAS": "0x1ffd8a218fdc5b38210d64cbb45f40dc55a4e019", + "USDT": "0x9ca066f00e55b90623efe323feb2a649686538b6" + }, + "rss3_vsl": { + "WRSS": "0xe27d019909738d98ab7f850c05ee07806c30c71d" + }, + "svm": { + "BTC": "0x5db252ead05C54B08A83414adCAbF46Eaa9E0337" + }, + "islm": { + "ISLM ": "0xeC8CC083787c6e5218D86f9FF5f28d4cC377Ac54", + "DAI": "0xc5e00d3b04563950941f7137b5afa3a534f0d6d6", + "ETH": "0xeceeefcee421d8062ef8d6b4d814efe4dc898265", + "WBTC": "0x5fd55a1b9fc24967c4db09c513c3ba0dfa7ff687", + "USDT": "0xd567b3d7b8fe3c79a1ad8da978812cfc4fa05e75", + "AXLUSDC": "0x80b5a32e4f032b2a058b4f29ec95eefeeb87adcd" + }, + "xlayer": { + "WOKB": "0xe538905cf8410324e03a5a23c1c177a474d59b2b", + "WBTC": "0xea034fb02eb1808c2cc3adbc15f447b93cbe08e1", + "WETH": "0x5A77f1443D16ee5761d310e38b62f77f726bC71c", + "USDT": "0x1E4a5963aBFD975d8c9021ce480b42188849D41d", + "USDC": "0x74b7f16337b8972027f6196a17a631ac6de26d22" + }, + "genesys": { + "WGSYS": "0xAa7aE83eb30DDdd14A017D4222121776317EA8Ba" + }, + "zora": { + "USDzC": "0xcccccccc7021b32ebb4e8c08314bd62f7c653ec4" + }, + "ancient8": { + "WETH": "0x4200000000000000000000000000000000000006" + }, + "karak": { + "USDC": "0xa415021bc5c4c3b5b989116dc35ae95d9c962c8d", + "rsETH": "0xf948aacec00289fc33d8226391f7e04bb457ad49", + "WETH": "0x4200000000000000000000000000000000000006" + }, + "bsquared": { + "WBTC": "0x4200000000000000000000000000000000000006", + "USDT": "0x681202351a488040fa4fdcc24188afb582c9dd62", + "USDC": "0xe544e8a38add9b1abf21922090445ba93f74b9e5", + "ETH": "0xD48d3A551757ac47655fCe25BDE1B0B6b1Cb2a5A", + "MATIC": "0xc3ee2Df14B1Bc526c24ED802f1873d49664a0d5c", + "FDUSD": "0xC2Fe4f673455Ef92299770a09CDB5E8756A525D5", + "BSTONE": "0x7537C1F80c9E157ED7AFD93a494be3e1f04f1462", + "ORDI": "0xa0f4470B714677AEEcE0d20074c540b3Cf6a477E", + "SATS": "0x7eBFcE05E418C380a2b6EB0F65995cA04ef4bc00", + "UBTC": "0x796e4D53067FF374B89b2Ac101ce0c1f72ccaAc2" + }, + "planq": { + "WPLANQ": "0x5ebcdf1de1781e8b5d41c016b0574ad53e2f6e1a", + "USDC": "0xecEEEfCEE421D8062EF8d6b4D814efe4dc898265", + "USDC_1": "0x75E20C5d4aade76143b8b74d1C5E2865347f9d3B" + }, + "lac": { + "LAC": "0x2911a1ab18546cb501628be8625c7503a2a7db54" + }, + "bob": { + "WETH": "0x4200000000000000000000000000000000000006", + "WBTC": "0x03c7054bcb39f7b2e5b2c7acb37583e32d70cfa3", + "USDT": "0x05d032ac25d322df992303dca074ee7392c117b9", + "USDC": "0xe75d0fb2c24a55ca1e3f96781a2bcc7bdba058f0", + "STETH": "0x85008aE6198BC91aC0735CB5497CF125ddAAc528", + "STONE": "0x96147a9ae9a42d7da551fd2322ca15b71032f342", + "RETH": "0xb5686c4f60904ec2bda6277d6fe1f7caa8d1b41a", + "TBTC": "0xbba2ef945d523c4e2608c9e1214c2cc64d4fc2e2" + }, + "btr": { + "ETH": "0xef63d4e178b3180beec9b0e143e0f37f4c93f4c2" + }, + "taiko": { + "USDC": "0x07d83526730c7438048D55A4fc0b850e2aaB6f0b", + "WETH": "0xA51894664A773981C6C112C43ce576f315d5b1B6" + }, + "stellar": { + "XLM": "CAS3J7GYLGXMF6TDJBBYYSE3HQ6BBSMLNUQ34T6TZMYMW2EVH34XOWMA", + "USDC": "CCW67TSZV3SSS2HXMBQ5JFGCKJNXKZM7UQUWUZPUTHXSTZLEO7SJMI75" + }, + "lukso": { + "WLYX": "0x2db41674f2b882889e5e1bd09a3f3613952bc472" + }, + "defichain_evm": { + "DFI": "0x49febbf9626b2d39aba11c01d83ef59b3d56d2a4", + "USDT": "0xff0000000000000000000000000000000000000d", + "USDC": "0xff00000000000000000000000000000000000003", + "ETH": "0xff00000000000000000000000000000000000001", + "DUSD": "0xff0000000000000000000000000000000000000f" } } diff --git a/helpers/customBackfill.ts b/helpers/customBackfill.ts index 74ba31f2bf..9f1fab8096 100644 --- a/helpers/customBackfill.ts +++ b/helpers/customBackfill.ts @@ -1,4 +1,4 @@ -import { ChainBlocks, Fetch, FetchResultGeneric } from "../adapters/types" +import { FetchOptions, FetchResultGeneric, Fetch, FetchV2, ChainBlocks } from "../adapters/types" import { getBlock } from "./getBlock" import { util } from '@defillama/sdk'; import { Chain } from "@defillama/sdk/build/general"; @@ -7,16 +7,24 @@ import BigNumber from "bignumber.js"; const { blocks: { chainsForBlocks } } = util const ONE_DAY_IN_SECONDS = 60 * 60 * 24 -export type IGraphs = (chain: Chain) => (timestamp: number, chainBlocks: ChainBlocks) => Promise +export type IGraphs = (chain: Chain) => (options: FetchOptions|number, chainBlocks: ChainBlocks) => Promise -export default (chain: Chain, graphs: IGraphs): Fetch => async (timestamp: number, chainBlocks: ChainBlocks): Promise => { +export default (chain: Chain, graphs: any): Fetch|FetchV2 => async (options: FetchOptions|number, chainBlocks: ChainBlocks): Promise => { const fetchGetVolume = graphs(chain) - const resultDayN = await fetchGetVolume(timestamp, chainBlocks) - const timestampPreviousDay = timestamp - ONE_DAY_IN_SECONDS - let chainBlocksPreviousDay = {} - if (chainsForBlocks.includes(chain) || chain === "ethereum") - chainBlocksPreviousDay = { [chain]: await getBlock(timestampPreviousDay, chain, {}).catch(() => { }) } - const resultPreviousDayN = await fetchGetVolume(timestampPreviousDay, chainBlocksPreviousDay) + let resultPreviousDayN: any = {} + let resultDayN: any = {} + if (typeof options == 'number') { + resultDayN = await fetchGetVolume(options, chainBlocks) + const timestampPreviousDay = options - ONE_DAY_IN_SECONDS + let chainBlocksPreviousDay = {} + if (chainsForBlocks.includes(chain) || chain === "ethereum") + chainBlocksPreviousDay = { [chain]: await getBlock(timestampPreviousDay, chain, {}).catch(() => { }) } + resultPreviousDayN = await fetchGetVolume(timestampPreviousDay, chainBlocksPreviousDay) + } else { + resultDayN = await fetchGetVolume(options) + options.endTimestamp = options.endTimestamp - ONE_DAY_IN_SECONDS; + resultPreviousDayN = await fetchGetVolume(options) + } const response: FetchResultGeneric = resultDayN Object.keys(resultPreviousDayN).filter((key) => key.includes('total')).forEach(key => { const dimension = `daily${key.slice(5)}` diff --git a/helpers/dexVolumeLogs.ts b/helpers/dexVolumeLogs.ts deleted file mode 100644 index c685be3a5d..0000000000 --- a/helpers/dexVolumeLogs.ts +++ /dev/null @@ -1,148 +0,0 @@ - -import { FetchOptions } from "../adapters/types"; - -const _swapEvent = "event Swap(address indexed sender, uint256 amount0In, uint256 amount1In, uint256 amount0Out, uint256 amount1Out, address indexed to)" -// const swapTopic = "0xd78ad95fa46c994b6551d0da85fc275fe613ce37657fb8d5e3d130840159d822" - -type getDexVolumeParams = { chain: string, fromTimestamp: number, toTimestamp?: number, factory?: string, timestamp: number, pools?: string[], fetchOptions: FetchOptions, pairLengthAbi?: string, pairItemAbi?: string, swapEvent?: string, } -type getDexVolumeFeeParamsV3 = { chain: string, fromTimestamp: number, toTimestamp?: number, factory?: string, factoryFromBlock?: number, timestamp: number, pools?: string[], isFee?: boolean, fetchOptions: FetchOptions, } - -type getDexVolumeExportsParams = { chain: string, factory?: string, pools?: string[], pairLengthAbi?: string, pairItemAbi?: string, } -type getDexVolumeExportsParamsV3 = { chain: string, factory?: string, pools?: string[], factoryFromBlock?: number, swapEvent?: string, } - -export async function getDexVolume({ factory, timestamp, pools, fetchOptions, pairLengthAbi = 'allPairsLength', pairItemAbi = 'allPairs', swapEvent = _swapEvent }: getDexVolumeParams) { - const { api } = fetchOptions; - if (!pools) pools = await api.fetchList({ lengthAbi: pairLengthAbi, itemAbi: pairItemAbi, target: factory! }) - - const token0s = await api.multiCall({ abi: 'address:token0', calls: pools! }) - const token1s = await api.multiCall({ abi: 'address:token1', calls: pools! }) - - const logs = await fetchOptions.getLogs({ - targets: pools, - eventAbi: swapEvent, - flatten: false, - }); - logs.forEach((log: any[], index: number) => { - const token0 = token0s[index] - const token1 = token1s[index] - if (!log.length) return - log.forEach((i: any) => { - // api.add(token0, i.amount0In) // we should count only one side of the swap - api.add(token0, i.amount0Out) - // api.add(token1, i.amount1In) - api.add(token1, i.amount1Out) - }) - }) - return { - timestamp, - dailyVolume: api.getBalancesV2(), - } -} - -export function getDexVolumeExports(options: getDexVolumeExportsParams): any { - return async (timestamp: number, _cb: any, fetchOptions: FetchOptions) => { - const params = { ...options, timestamp, fromTimestamp: fetchOptions.fromTimestamp, toTimestamp: fetchOptions.toTimestamp, fetchOptions } - return getDexVolume(params) - } -} - -type getDexFeesParams = { chain: string, fromTimestamp?: number, toTimestamp?: number, factory?: string, timestamp: number, pools?: string[], lengthAbi?: string, itemAbi?: string, fromBlock?: number, toBlock?: number, fetchOptions: FetchOptions, } -type getDexFeesExportParams = { chain: string, factory?: string, pools?: string[], lengthAbi?: string, itemAbi?: string, } - -const feesEvent = "event Fees(address indexed sender, uint256 amount0, uint256 amount1)" -// const feesTopic = '0x112c256902bf554b6ed882d2936687aaeb4225e8cd5b51303c90ca6cf43a8602' -export async function getDexFees({ factory, timestamp, pools, lengthAbi = 'allPairsLength', itemAbi = 'allPairs', fetchOptions, }: getDexFeesParams) { - const { api } = fetchOptions - if (!pools) pools = await api.fetchList({ lengthAbi, itemAbi, target: factory! }) - - const token0s = await api.multiCall({ abi: 'address:token0', calls: pools!, permitFailure: true, }) - const token1s = await api.multiCall({ abi: 'address:token1', calls: pools!, permitFailure: true, }) - - const logs = await fetchOptions.getLogs({ - targets: pools, - eventAbi: feesEvent, - flatten: false, - }); - logs.forEach((log: any[], index: number) => { - const token0 = token0s[index] - const token1 = token1s[index] - if (!log.length || !token0 || !token1) return - log.forEach((i: any) => { - api.add(token0, i.amount0) - api.add(token1, i.amount1) - }) - }) - const value = api.getBalancesV2() - return { - timestamp, - dailyFees: value, - dailyRevenue: value, - dailyHoldersRevenue: value, - } -} - -export function getDexFeesExports(options: getDexFeesExportParams): any { - return async (timestamp: number, _cb: any, fetchOptions: FetchOptions) => { - const params = { ...options, timestamp, fromTimestamp: fetchOptions.fromTimestamp, toTimestamp: fetchOptions.toTimestamp, fetchOptions, } - return getDexFees(params) - } -} - -const v3PoolCreated = 'event PoolCreated(address indexed token0,address indexed token1,uint24 indexed fee,int24 tickSpacing,address pool)'; -const v3SwapEvent = 'event Swap(address indexed sender,address indexed recipient,int256 amount0,int256 amount1,uint160 sqrtPriceX96,uint128 liquidity,int24 tick)' - -export async function getDexVolumeFeeV3({ factory, timestamp, pools, factoryFromBlock, isFee = false, fetchOptions: { getLogs, api }, }: getDexVolumeFeeParamsV3) { - if (!pools) { - const logs = await getLogs({ - target: factory, - fromBlock: factoryFromBlock, - eventAbi: v3PoolCreated, - }); - pools = logs.map((log: any) => log.pool) - } - - let fees = [] as any - if (isFee) - fees = await api.multiCall({ abi: 'function fee() view returns (uint24)', calls: pools! }) - const token1s = await api.multiCall({ abi: 'address:token1', calls: pools! }) - - const logs = await getLogs({ - targets: pools, - eventAbi: v3SwapEvent, - flatten: false, - }); - logs.forEach((log: any[], index: number) => { - const token1 = token1s[index] - if (!log.length) return - let fee = 1 - if (isFee) { - fee = fees[index] ?? 0 - if (fee === 0) return; - fee /= 1e6 - } - log.forEach((i: any) => { - let amount = Number(i.amount1) - if (+amount < 0) amount *= -1 - api.add(token1, amount * fee) - }) - }) - return { - timestamp, - dailyVolume: await api.getBalancesV2(), - } -} - -export function getDexVolumeExportsV3(options: getDexVolumeExportsParamsV3) { - return async (timestamp: number, _cb: any, fetchOptions: FetchOptions) => { - const params = { ...options, timestamp, fromTimestamp: fetchOptions.fromTimestamp, toTimestamp: fetchOptions.toTimestamp, fetchOptions } - return getDexVolumeFeeV3(params) - } -} - - -export function getDexFeesExportsV3(options: getDexVolumeExportsParamsV3): any { - return async (timestamp: number, _cb: any, fetchOptions: FetchOptions) => { - const params = { ...options, timestamp, fromTimestamp: fetchOptions.fromTimestamp, toTimestamp: fetchOptions.toTimestamp, fetchOptions, isFee: true, } - return getDexVolumeFeeV3(params) - } -} diff --git a/helpers/dune.ts b/helpers/dune.ts index e3711ed112..f70cacd19a 100644 --- a/helpers/dune.ts +++ b/helpers/dune.ts @@ -1,10 +1,8 @@ -import { IJSON } from "../adapters/types"; import { httpGet, httpPost } from "../utils/fetchURL"; import { getEnv } from "./env"; const plimit = require('p-limit'); const limit = plimit(1); -const token = {} as IJSON const API_KEYS =getEnv('DUNE_API_KEYS')?.split(',') ?? ["L0URsn5vwgyrWbBpQo9yS1E3C1DBJpZh"] let API_KEY_INDEX = 0; @@ -29,21 +27,25 @@ const getLatestData = async (queryId: string) => { throw e; } } -const delay = (ms: number) => new Promise(resolve => setTimeout(resolve, ms)) -const inquiryStatus = async (queryId: string) => { + +async function randomDelay() { + const delay = Math.floor(Math.random() * 5) + 2 + return new Promise((resolve) => setTimeout(resolve, delay * 1000)) +} + +const inquiryStatus = async (execution_id: string, queryId:string) => { let _status = undefined; - if (token[queryId] === undefined) throw new Error("execution is not undefined.") do { try { - _status = (await limit(() => httpGet(`https://api.dune.com/api/v1/execution/${token[queryId]}/status`, { + _status = (await limit(() => httpGet(`https://api.dune.com/api/v1/execution/${execution_id}/status`, { headers: { "x-dune-api-key": API_KEYS[API_KEY_INDEX] } }))).state if (['QUERY_STATE_PENDING', 'QUERY_STATE_EXECUTING'].includes(_status)) { console.info(`waiting for query id ${queryId} to complete...`) - await delay(5000) // 5s + await randomDelay() // 1 - 4s } } catch (e: any) { throw e; @@ -54,37 +56,35 @@ const inquiryStatus = async (queryId: string) => { const submitQuery = async (queryId: string, query_parameters = {}) => { let query: undefined | any = undefined - if (!token[queryId]) { - try { - query = await limit(() => httpPost(`https://api.dune.com/api/v1/query/${queryId}/execute`, { query_parameters }, { - headers: { - "x-dune-api-key": API_KEYS[API_KEY_INDEX], - 'Content-Type': 'application/json' - } - })) - if (query?.execution_id) { - token[queryId] = query?.execution_id - } else { - throw new Error("error query data: " + query) + try { + query = await limit(() => httpPost(`https://api.dune.com/api/v1/query/${queryId}/execute`, { query_parameters }, { + headers: { + "x-dune-api-key": API_KEYS[API_KEY_INDEX], + 'Content-Type': 'application/json' } - } catch (e: any) { - throw e; + })) + if (query?.execution_id) { + return query?.execution_id + } else { + throw new Error("error query data: " + query) } - } + } catch (e: any) { + throw e; + } } -export const queryDune = async (queryId: string, query_parameters = {}) => { +export const queryDune = async (queryId: string, query_parameters:any = {}) => { if (Object.keys(query_parameters).length === 0) { const latest_result = await getLatestData(queryId) if (latest_result !== undefined) return latest_result } - await submitQuery(queryId, query_parameters) - const _status = await inquiryStatus(queryId) + const execution_id = await submitQuery(queryId, query_parameters) + const _status = await inquiryStatus(execution_id, queryId) if (_status === 'QUERY_STATE_COMPLETED') { const API_KEY = API_KEYS[API_KEY_INDEX] try { - const queryStatus = await limit(() => httpGet(`https://api.dune.com/api/v1/execution/${token[queryId]}/results?limit=5&offset=0`, { + const queryStatus = await limit(() => httpGet(`https://api.dune.com/api/v1/execution/${execution_id}/results?limit=5&offset=0`, { headers: { "x-dune-api-key": API_KEY } @@ -95,3 +95,16 @@ export const queryDune = async (queryId: string, query_parameters = {}) => { } } } + +const tableName = { + bsc: "bnb", + ethereum: "ethereum", + base: "base", +} as any + +export const queryDuneSql = (options:any, query:string) => { + return queryDune("3996608", { + fullQuery: query.replace("CHAIN", tableName[options.chain] ?? options.chain).replace("TIME_RANGE", `block_time >= from_unixtime(${options.startTimestamp}) + AND block_time <= from_unixtime(${options.endTimestamp})`) + }) +} diff --git a/helpers/env.ts b/helpers/env.ts index 09256c464c..f98149f203 100644 --- a/helpers/env.ts +++ b/helpers/env.ts @@ -4,7 +4,11 @@ const BOOL_KEYS = [ const DEFAULTS: any = { ANKR_API_KEY: '79258ce7f7ee046decc3b5292a24eb4bf7c910d7e39b691384c7ce0cfb839a01', - ZETA_RPC: "https://zetachain-evm.blockpi.network/v1/rpc/public,https://zetachain-mainnet-archive.allthatnode.com:8545" + ZETA_RPC: "https://zetachain-evm.blockpi.network/v1/rpc/public,https://zetachain-mainnet-archive.allthatnode.com:8545", + SVM_RPC: "https://rpc.cosvm.net", + XLAYER_RPC: "https://xlayerrpc.okx.com", + BITLAYER_RPC: "https://rpc-bitlayer.rockx.com", + PLANQ_RPC: "https://planq-rpc.nodies.app,https://jsonrpc.planq.nodestake.top", } export const ENV_KEYS = new Set([ @@ -23,6 +27,8 @@ export const ENV_KEYS = new Set([ 'ZEROx_API_KEY', 'ZEROX_API_KEY', 'AGGREGATOR_0X_API_KEY', + 'SUI_RPC', + '0KX_API_KEY' ]) // This is done to support both ZEROx_API_KEY and ZEROX_API_KEY @@ -38,4 +44,3 @@ export function getEnv(key: string): any { const value = process.env[key] ?? DEFAULTS[key] return BOOL_KEYS.includes(key) ? !!value : value } - diff --git a/helpers/ethereum-l2.ts b/helpers/ethereum-l2.ts index c9f6c089a7..eaa6040e0c 100644 --- a/helpers/ethereum-l2.ts +++ b/helpers/ethereum-l2.ts @@ -37,7 +37,7 @@ export function L2FeesFetcher({ feeVaults?: string[]; ethereumWallets: string[]; }): any { - return async (timestamp: number, _chainBlocks: ChainBlocks, options: FetchOptions): Promise => { + return async (options: FetchOptions) => { const sequencerGas = queryIndexer(` SELECT sum(ethereum.transactions.gas_used * ethereum.transactions.gas_price) AS sum @@ -52,6 +52,6 @@ export function L2FeesFetcher({ dailyRevenue.addTokenVannila(gasToken, (totalSpentBySequencer as any)[0].sum * -1) else dailyRevenue.addGasToken((totalSpentBySequencer as any)[0].sum * -1) - return { timestamp, dailyFees, dailyRevenue, } + return { dailyFees, dailyRevenue, } } } diff --git a/helpers/etherscanFees.ts b/helpers/etherscanFees.ts index e82ad7272c..677aa1d498 100644 --- a/helpers/etherscanFees.ts +++ b/helpers/etherscanFees.ts @@ -1,4 +1,4 @@ -import { Adapter, ChainBlocks, FetchOptions, ProtocolType } from "../adapters/types"; +import { Adapter, FetchOptions, ProtocolType } from "../adapters/types"; import { httpPost } from '../utils/fetchURL'; @@ -17,9 +17,10 @@ export async function getEtherscanFees({ startOfDay, }: FetchOptions, url: strin export function etherscanFeeAdapter(chain: string, url: string, cgToken?: string) { const adapter: Adapter = { + version: 2, adapter: { [chain]: { - fetch: async (_timestamp: number, _: ChainBlocks, options: FetchOptions) => { + fetch: async (options: FetchOptions) => { const amount = await getEtherscanFees(options, url) const dailyFees = options.createBalances() if (cgToken) @@ -33,7 +34,7 @@ export function etherscanFeeAdapter(chain: string, url: string, cgToken?: string } return { - timestamp: options.startOfDay, dailyFees, + dailyFees, }; }, start: 1690761600 diff --git a/helpers/flipsidecrypto.ts b/helpers/flipsidecrypto.ts index 7b2e1b94c8..47f1c4d6d0 100644 --- a/helpers/flipsidecrypto.ts +++ b/helpers/flipsidecrypto.ts @@ -13,6 +13,11 @@ type IRequest = { } const query: IRequest = {}; +async function randomDelay() { + const delay = Math.floor(Math.random() * 4) + 1 + return new Promise((resolve) => setTimeout(resolve, delay * 1000)) +} + export async function queryFlipside(sqlQuery: string, maxAgeMinutes: number = 90) { if (!query[sqlQuery]) { query[sqlQuery] = _queryFlipside(sqlQuery, maxAgeMinutes) @@ -48,8 +53,8 @@ async function _queryFlipside(sqlQuery: string, maxAgeMinutes: number = 90) { headers: { "x-api-key": FLIPSIDE_API_KEY, 'Content-Type': 'application/json' - } - }) + }, + }, { withMetadata: true }) if(query?.result?.queryRun?.id){ token[sqlQuery] = query?.result.queryRun.id } else { @@ -63,19 +68,28 @@ async function _queryFlipside(sqlQuery: string, maxAgeMinutes: number = 90) { if(API_KEY_INDEX < nextIndex){ API_KEY_INDEX = nextIndex; } + console.info("flipside increasing API_KEY_INDEX to -> ", FLIPSIDE_API_KEYS[API_KEY_INDEX]) throw "Increasing API_KEY_INDEX"; } else { const error = new Error(`Payment Required`) bail(error) - throw error + console.error("Payment Required: " + FLIPSIDE_API_KEY) + return [] } } + if (!e.response) { + bail(e) + console.error("flipside not found response error") + return [] + } console.log("make query flipside", e.response, e) - throw e + bail(e) + return [] } } if (!token[sqlQuery]) { + console.error("Couldn't get a token from flipsidecrypto") throw new Error("Couldn't get a token from flipsidecrypto") } @@ -92,7 +106,7 @@ async function _queryFlipside(sqlQuery: string, maxAgeMinutes: number = 90) { headers: { "x-api-key": FLIPSIDE_API_KEY } - }) + }, { withMetadata: true }) const status = queryStatus.result.queryRun.state if (status === "QUERY_STATE_SUCCESS") { @@ -119,7 +133,7 @@ async function _queryFlipside(sqlQuery: string, maxAgeMinutes: number = 90) { headers: { "x-api-key": FLIPSIDE_API_KEY } - }) + }, { withMetadata: true }) if(results.result.rows === null){ return [] // empty result } @@ -151,9 +165,11 @@ async function _queryFlipside(sqlQuery: string, maxAgeMinutes: number = 90) { headers: { "x-api-key": FLIPSIDE_API_KEY } - }) + }, { withMetadata: true }) bail(new Error('max retries exceeded')) } + await randomDelay() + console.info(`Flipside query ${token[sqlQuery]} still running... retrying ${attempt}`) throw new Error("Still running") }, { diff --git a/helpers/friend-tech.ts b/helpers/friend-tech.ts index 677b4c8a60..2faf3b69cb 100644 --- a/helpers/friend-tech.ts +++ b/helpers/friend-tech.ts @@ -1,4 +1,4 @@ -import { ChainBlocks, Fetch, FetchOptions } from "../adapters/types"; +import { FetchV2 } from "../adapters/types"; import ADDRESSES from "./coreAssets.json"; @@ -6,8 +6,8 @@ const event_trade = 'event Trade(address trader, address subject, bool isBuy, ui export function getFeesExport(FriendtechSharesAddress: string, eventAbis = [event_trade], { token = ADDRESSES.null, -}: { token?: string } = {}) { - return (async (timestamp: number, _: ChainBlocks, { getLogs, createBalances, }: FetchOptions) => { +}: { token?: string } = {}) { + return (async ({ getLogs, createBalances, }) => { const dailyFees = createBalances() const dailyRevenue = createBalances() for (const eventAbi of eventAbis) { @@ -22,6 +22,6 @@ export function getFeesExport(FriendtechSharesAddress: string, eventAbis = [even if (e.holderEthAmount) dailyFees.add(token, e.holderEthAmount) }) } - return { dailyFees, dailyRevenue, timestamp, } - }) as Fetch + return { dailyFees, dailyRevenue, } + }) as FetchV2 } \ No newline at end of file diff --git a/helpers/getBlock.ts b/helpers/getBlock.ts index 76e7e6ebfe..5461926dff 100644 --- a/helpers/getBlock.ts +++ b/helpers/getBlock.ts @@ -7,7 +7,6 @@ import { httpGet } from "../utils/fetchURL"; const retry = require("async-retry") const blacklistedChains: string[] = [ - "tron", "juno", "cardano", "litecoin", @@ -27,6 +26,7 @@ const blacklistedChains: string[] = [ "thorchain", "flow", "aptos", + "polkadex", "neo", "phantasma", "starknet", @@ -42,7 +42,6 @@ const blacklistedChains: string[] = [ "icp", "hydradx", "osmosis", - "sei", "ergo", "radixdlt", "near", @@ -50,75 +49,95 @@ const blacklistedChains: string[] = [ "sui", "neutron", "terra2", + "dymension" ]; +const cache = { + +} as any + async function getBlock(timestamp: number, chain: Chain, chainBlocks = {} as ChainBlocks) { - if (blacklistedChains.includes(chain)) { - return null - } - if (chainBlocks[chain] !== undefined) - return chainBlocks[chain] + try { + if (!cache[chain]) cache[chain] = {} + if (!cache[chain][timestamp]) cache[chain][timestamp] = _getBlock(timestamp, chain, {}) + const block = await cache[chain][timestamp] + if (block) chainBlocks[chain] = block + return block + } catch (e) { + console.error('error fetching block' + chain + ' ' + (e as any)?.message) + return null + } +} +async function _getBlock(timestamp: number, chain: Chain, chainBlocks = {} as ChainBlocks) { + if (chain === CHAIN.DOGECHAIN) throw new Error("DOGECHAIN not supported") + if (blacklistedChains.includes(chain)) { + return null + } + if (chainBlocks[chain] !== undefined) + return chainBlocks[chain] - let block: number | undefined - try { - if (chain === CHAIN.WAVES) - timestamp = Math.floor(timestamp * 1000) - block = await sdk.blocks.getBlockNumber(chain, timestamp) - } catch (e) { console.log('error fetching block', e) } - if (block) { - chainBlocks[chain] = block - return block + let block: number | undefined + try { + if (chain === CHAIN.WAVES) + timestamp = Math.floor(timestamp * 1000) + block = await sdk.blocks.getBlockNumber(chain, timestamp) + } catch (e) { + if (chain === CHAIN.SEI) { + return null } + console.log('error fetching block', e) + } - if (chain === CHAIN.CELO) - block = Number((await retry(async () => (await httpGet("https://explorer.celo.org/api?module=block&action=getblocknobytime×tamp=" + timestamp + "&closest=before").catch((e) => { - throw new Error(`Error getting block: ${chain} ${timestamp} ${e.message}`) - }))?.result?.blockNumber))); - else if (chain === CHAIN.KAVA) - block = Number((await retry(async () => (await httpGet(`https://explorer.kava.io/api?module=block&action=getblocknobytime×tamp=${timestamp}&closest=before`).catch((e) => { - throw new Error(`Error getting block: ${chain} ${timestamp} ${e.message}`) - }))?.result?.blockNumber))); - else if (chain === CHAIN.ONUS) - block = Number((await retry(async () => (await httpGet(`https://explorer.onuschain.io/api?module=block&action=getblocknobytime×tamp=${timestamp}&closest=before`).catch((e) => { - throw new Error(`Error getting block: ${chain} ${timestamp} ${e.message}`) - }))?.result?.blockNumber))); - else if (chain as CHAIN === CHAIN.POLYGON_ZKEVM || chain === CHAIN.VISION || chain as CHAIN === CHAIN.ERA) - return sdk.api.util.lookupBlock(timestamp, { chain }).then((blockData: any) => blockData.block) // TODO after get block support chain polygon_zkevm then swith to use api https://coins.llama.fi/block - else if (chain as CHAIN === CHAIN.WAVES) - block = Number((await retry(async () => (await httpGet(`https://nodes.wavesnodes.com/blocks/heightByTimestamp/${(timestamp * 1000)}`).catch((e) => { - throw new Error(`Error getting block: ${chain} ${timestamp} ${e.message}`) - }))?.height, { retries: 3 }))); - else if (chain === CHAIN.BASE) - block = Number((await retry(async () => (await httpGet(`https://base.blockscout.com/api?module=block&action=getblocknobytime×tamp=${timestamp}&closest=before`).catch((e) => { - throw new Error(`Error getting block: ${chain} ${timestamp} ${e.message}`) - }))?.result?.blockNumber))); - else if (chain === CHAIN.SCROLL) - block = Number((await retry(async () => (await httpGet(`https://blockscout.scroll.io/api?module=block&action=getblocknobytime×tamp=${timestamp}&closest=before`).catch((e) => { - throw new Error(`Error getting block: ${chain} ${timestamp} ${e.message}`) - }))?.result?.blockNumber))); - else - block = Number((await retry(async () => (await httpGet(`https://coins.llama.fi/block/${chain}/${timestamp}`).catch((e) => { - throw new Error(`Error getting block: ${chain} ${timestamp} ${e.message}`) - }))?.height, { retries: 1 }))); - if (block) chainBlocks[chain] = block + if (block) { + chainBlocks[chain] = block return block - // https://base.blockscout.com - // https://explorer.kava.io - //return sdk.api.util.lookupBlock(timestamp, { chain }).then(blockData => blockData.block) + } + + if (chain === CHAIN.CELO) + block = Number((await retry(async () => (await httpGet("https://explorer.celo.org/api?module=block&action=getblocknobytime×tamp=" + timestamp + "&closest=before").catch((e) => { + throw new Error(`Error getting block: ${chain} ${timestamp} ${e.message}`) + }))?.result?.blockNumber, { retries: 3 }))); + else if (chain === CHAIN.ONUS) + block = Number((await retry(async () => (await httpGet(`https://explorer.onuschain.io/api?module=block&action=getblocknobytime×tamp=${timestamp}&closest=before`).catch((e) => { + throw new Error(`Error getting block: ${chain} ${timestamp} ${e.message}`) + }))?.result?.blockNumber, { retries: 3 }))); + else if (chain as CHAIN === CHAIN.POLYGON_ZKEVM || chain === CHAIN.VISION || chain as CHAIN === CHAIN.ERA) + return sdk.api.util.lookupBlock(timestamp, { chain }).then((blockData: any) => blockData.block) // TODO after get block support chain polygon_zkevm then swith to use api https://coins.llama.fi/block + else if (chain as CHAIN === CHAIN.WAVES) + block = Number((await retry(async () => (await httpGet(`https://nodes.wavesnodes.com/blocks/heightByTimestamp/${(timestamp * 1000)}`).catch((e) => { + throw new Error(`Error getting block: ${chain} ${timestamp} ${e.message}`) + }))?.height, { retries: 3 }))); + else if (chain === CHAIN.BASE) + block = Number((await retry(async () => (await httpGet(`https://base.blockscout.com/api?module=block&action=getblocknobytime×tamp=${timestamp}&closest=before`).catch((e) => { + throw new Error(`Error getting block: ${chain} ${timestamp} ${e.message}`) + }))?.result?.blockNumber, { retries: 3 }))); + else if (chain === CHAIN.SCROLL) + block = Number((await retry(async () => (await httpGet(`https://blockscout.scroll.io/api?module=block&action=getblocknobytime×tamp=${timestamp}&closest=before`).catch((e) => { + throw new Error(`Error getting block: ${chain} ${timestamp} ${e.message}`) + }))?.result?.blockNumber, { retries: 3 }))); + else + block = Number((await retry(async () => (await httpGet(`https://coins.llama.fi/block/${chain}/${timestamp}`, { timeout: 10000 }).catch((e) => { + throw new Error(`Error getting block: ${chain} ${timestamp} ${e.message}`) + }))?.height, { retries: 1 }))); + if (block) chainBlocks[chain] = block + return block + // https://base.blockscout.com + // https://explorer.kava.io + //return sdk.api.util.lookupBlock(timestamp, { chain }).then(blockData => blockData.block) } async function getBlocks(chain: Chain, timestamps: number[]) { - return Promise.all(timestamps.map(t => getBlock(t, chain, {}))) + return Promise.all(timestamps.map(t => getBlock(t, chain, {}))) } const canGetBlock = (chain: string) => Object.keys(providers).includes(chain) export { - getBlock, - canGetBlock, - getBlocks + getBlock, + canGetBlock, + getBlocks } diff --git a/helpers/getRaydiumFees.ts b/helpers/getRaydiumFees.ts new file mode 100644 index 0000000000..69855955da --- /dev/null +++ b/helpers/getRaydiumFees.ts @@ -0,0 +1,241 @@ +import { Chain } from "@defillama/sdk/build/general"; +import { + Adapter, + BaseAdapter, + BreakdownAdapter, + ChainBlocks, + FetchResultVolume +} from "../adapters/types"; + +import BigNumber from "bignumber.js"; +import { gql, request } from "graphql-request"; +import type { ChainEndpoints, Fetch, FetchOptions, FetchResultV2, FetchV2 } from "../adapters/types"; +import { getBlock } from "./getBlock"; +import { + DEFAULT_DAILY_VOLUME_FACTORY, + DEFAULT_DAILY_VOLUME_FIELD, + DEFAULT_TOTAL_VOLUME_FACTORY, + DEFAULT_TOTAL_VOLUME_FIELD, + getUniqStartOfTodayTimestamp, +} from "./getUniSubgraphVolume"; + +// To get ID for daily data https://docs.uniswap.org/protocol/V2/reference/API/entities +const getUniswapDateId = (date?: Date) => getUniqStartOfTodayTimestamp(date) / 86400; + +const DEFAULT_TOTAL_FEES_FACTORY = "factories"; +const DEFAULT_TOTAL_FEES_FIELD = "totalFeesUSD"; + +const DEFAULT_DAILY_FEES_FACTORY = "uniswapDayData"; +const DEFAULT_DAILY_FEES_FIELD = "feesUSD"; + +interface IGetRawChainFeeParams { + graphUrls: ChainEndpoints, + totalFees?: number, + protocolFees?: number, + totalVolume?: { + factory: string, + field: string + }, + dailyVolume?: { + factory: string, + field: string + }, + customDailyVolume?: string, + hasDailyVolume?: boolean + hasTotalVolume?: boolean + getCustomBlock?: (timestamp: number) => Promise +} + +interface IGetChainFeeParams { + volumeAdapter: Adapter, + totalFees?: number, + protocolFees?: number, + revenue?: number, + userFees?: number, + supplySideRevenue?: number, + holdersRevenue?: number, + meta?: BaseAdapter[string]['meta'] +} + + +const getUniswapV3Fees = (graphUrls: ChainEndpoints) => { + const graphQuery = gql`query fees($dateId: Int!) { + ${DEFAULT_DAILY_FEES_FACTORY}(id: $dateId) { + ${DEFAULT_DAILY_FEES_FIELD} + }, + ${DEFAULT_TOTAL_FEES_FACTORY} { + ${DEFAULT_TOTAL_FEES_FIELD} + } + }`; + + return (chain: Chain) => { + return async (timestamp: number) => { + const dateId = getUniswapDateId(new Date(timestamp * 1000)); + + const graphRes = await request(graphUrls[chain], graphQuery, { + dateId, + }); + + return { + timestamp, + totalFees: graphRes[DEFAULT_TOTAL_FEES_FACTORY][0][DEFAULT_TOTAL_FEES_FIELD], + dailyFees: graphRes[DEFAULT_DAILY_FEES_FACTORY][DEFAULT_DAILY_FEES_FIELD], + totalRevenue: "0", // uniswap has no rev yet + dailyRevenue: "0", // uniswap has no rev yet + }; + }; + }; +}; + +const getDexChainBreakdownFees = ({ volumeAdapter, totalFees = 0, protocolFees = 0 }: IGetChainFeeParams) => { + if ('breakdown' in volumeAdapter) { + let breakdownAdapter = {} as BreakdownAdapter['breakdown'] + const volumeBreakdownAdapter = volumeAdapter.breakdown + + for (const [version, adapterObj] of Object.entries(volumeBreakdownAdapter)) { + const volAdapter: BaseAdapter = adapterObj + + const baseAdapters = Object.keys(volAdapter).map(chain => { + const fetchFees = async (timestamp: number, chainBlocks: ChainBlocks, options: FetchOptions) => { + const fetchedResult: FetchResultVolume = await (volAdapter[chain].fetch as Fetch)(timestamp, chainBlocks, options) + const chainDailyVolume = fetchedResult.dailyVolume ? fetchedResult.dailyVolume as number : "0"; + const chainTotalVolume = fetchedResult.totalVolume ? fetchedResult.totalVolume as number : "0"; + + return { + timestamp, + totalFees: new BigNumber(chainTotalVolume).multipliedBy(totalFees).toString(), + dailyFees: chainDailyVolume ? new BigNumber(chainDailyVolume).multipliedBy(totalFees).toString() : undefined, + totalRevenue: new BigNumber(chainTotalVolume).multipliedBy(protocolFees).toString(), + dailyRevenue: chainDailyVolume ? new BigNumber(chainDailyVolume).multipliedBy(protocolFees).toString() : undefined + }; + } + + const baseAdapter: BaseAdapter = { + [chain]: { + ...volAdapter[chain], + fetch: fetchFees, + customBackfill: fetchFees, + } + } + return baseAdapter + }); + + breakdownAdapter = { [version]: baseAdapters[0], ...breakdownAdapter } + } + + return breakdownAdapter; + } else { + console.log(`Failed to grab dex volume data (volume adapter not include 'breakdown' props)`) + return {} + } +} + + +const getDexChainFees = ({ volumeAdapter, totalFees = 0, protocolFees = 0, ...params }: IGetChainFeeParams) => { + if ('adapter' in volumeAdapter) { + let finalBaseAdapter: BaseAdapter = {} + const adapterObj = volumeAdapter.adapter + + Object.keys(adapterObj).map(chain => { + const fetchFees = async (options: FetchOptions) => { + return await (adapterObj[chain].fetch as FetchV2)(options) + } + + const baseAdapter: BaseAdapter = { + [chain]: { + ...adapterObj[chain], + fetch: fetchFees, + customBackfill: fetchFees, + meta: params.meta + } + } + finalBaseAdapter = { ...baseAdapter, ...finalBaseAdapter } + return baseAdapter + }); + + return finalBaseAdapter; + } else { + console.log(`Failed to grab dex volume data (volume adapter not include 'volume' props)`, volumeAdapter) + return {} + } +} + +// Raw method if we do not want to rely on dexVolumes +function getDexChainFeesRaw({ + graphUrls, + totalFees = 0, + protocolFees = 0, + totalVolume = { + factory: DEFAULT_TOTAL_VOLUME_FACTORY, + field: DEFAULT_TOTAL_VOLUME_FIELD, + }, + dailyVolume = { + factory: DEFAULT_DAILY_VOLUME_FACTORY, + field: DEFAULT_DAILY_VOLUME_FIELD, + }, + customDailyVolume = undefined, + hasDailyVolume = true, + hasTotalVolume = true, + getCustomBlock = undefined, +}: IGetRawChainFeeParams) { + const totalVolumeQuery = gql` + ${totalVolume.factory}( + block: { number: $block } + ) { + ${totalVolume.field} + } + `; + + const dailyVolumeQuery = + customDailyVolume || + gql` + ${dailyVolume.factory} ( + id: $id + ) { + ${dailyVolume.field} + } + `; + + const graphQuery = gql` +query get_volume($block: Int, $id: Int) { + ${hasTotalVolume ? totalVolumeQuery : ""} + ${hasDailyVolume ? dailyVolumeQuery : ""} +} +`; + return (chain: Chain) => { + return async (timestamp: number, chainBlocks: ChainBlocks) => { + const block = + (getCustomBlock && (await getCustomBlock(timestamp))) || + (await getBlock(timestamp, chain, chainBlocks)); + + const id = getUniswapDateId(new Date(timestamp * 1000)); + + const graphRes = await request(graphUrls[chain], graphQuery, { + block, + id, + }); + + const chainTotalVolume = graphRes[totalVolume.factory][0][totalVolume.field]; + const chainDailyVolume = hasDailyVolume ? (graphRes?.[dailyVolume.factory]?.[dailyVolume.field] ?? "0") : undefined; + + return { + timestamp, + block, + totalFees: new BigNumber(chainTotalVolume).multipliedBy(totalFees).toString(), + dailyFees: (hasDailyVolume && chainDailyVolume) ? new BigNumber(chainDailyVolume).multipliedBy(totalFees).toString() : undefined, + totalRevenue: new BigNumber(chainTotalVolume).multipliedBy(protocolFees).toString(), + dailyRevenue: (hasDailyVolume && chainDailyVolume) ? new BigNumber(chainDailyVolume).multipliedBy(protocolFees).toString() : undefined + }; + }; + }; +} + +export { + DEFAULT_DAILY_FEES_FACTORY, + DEFAULT_DAILY_FEES_FIELD, DEFAULT_DAILY_VOLUME_FACTORY, + DEFAULT_DAILY_VOLUME_FIELD, DEFAULT_TOTAL_FEES_FACTORY, + DEFAULT_TOTAL_FEES_FIELD, DEFAULT_TOTAL_VOLUME_FACTORY, + DEFAULT_TOTAL_VOLUME_FIELD, getDexChainBreakdownFees, getDexChainFees, + getDexChainFeesRaw, getUniqStartOfTodayTimestamp, getUniswapV3Fees +}; + diff --git a/helpers/getUniSubgraph/index.ts b/helpers/getUniSubgraph/index.ts index 4127a9f8b8..dad74e5f23 100644 --- a/helpers/getUniSubgraph/index.ts +++ b/helpers/getUniSubgraph/index.ts @@ -1,7 +1,6 @@ import { Chain } from "@defillama/sdk/build/general"; import { request, gql } from "graphql-request"; -import { getBlock } from "../getBlock"; -import { BaseAdapter, ChainBlocks, FetchResultGeneric, IJSON, SimpleAdapter } from "../../adapters/types"; +import { BaseAdapter, FetchOptions, FetchResultGeneric, IJSON, SimpleAdapter } from "../../adapters/types"; import { DEFAULT_DAILY_FEES_FACTORY, DEFAULT_DAILY_FEES_FIELD, DEFAULT_TOTAL_FEES_FACTORY, DEFAULT_TOTAL_FEES_FIELD } from "../getUniSubgraphFees"; import BigNumber from "bignumber.js"; import { getUniqStartOfTodayTimestamp, getUniswapDateId, handle200Errors } from "./utils"; @@ -13,11 +12,16 @@ const DEFAULT_TOTAL_VOLUME_FIELD = "totalVolumeUSD"; const DEFAULT_DAILY_VOLUME_FACTORY = "uniswapDayData"; const DEFAULT_DAILY_VOLUME_FIELD = "dailyVolumeUSD"; const DEFAULT_DAILY_DATE_FIELD = "date"; -const DEFAULT_DAILY_PAIR_FACTORY = "pairDayDatas" +const DEFAULT_DAILY_PAIR_FACTORY = "pairDayDatas"; const DEFAULT_ID_TYPE = 'ID!' const DEFAULT_BLOCK_TYPE = 'Int' +interface IGetChainVolumeFilterParams { + name: string, + type: string +} + interface IGetChainVolumeParams { graphUrls: { [chains: string]: string @@ -29,6 +33,7 @@ interface IGetChainVolumeParams { factory?: string, field?: string, blockGraphType?: string + filterParams?: IGetChainVolumeFilterParams[], }, dailyVolume?: { factory?: string, @@ -70,6 +75,7 @@ type pair = { } } & IJSON + function getGraphDimensions({ graphUrls, graphRequestHeaders, @@ -126,10 +132,19 @@ function getGraphDimensions({ const graphFieldsTotalVolume = { factory: totalVolume.factory ?? DEFAULT_TOTAL_VOLUME_FACTORY, field: totalVolume.field ?? DEFAULT_TOTAL_VOLUME_FIELD, - blockGraphType: totalVolume.blockGraphType ?? DEFAULT_BLOCK_TYPE + blockGraphType: totalVolume.blockGraphType ?? DEFAULT_BLOCK_TYPE, + filterParams: totalVolume.filterParams ?? undefined } // Queries - const totalVolumeQuery = gql` + const totalVolumeQuery = graphFieldsTotalVolume.filterParams + ? gql`query get_total_volume(${graphFieldsTotalVolume.filterParams.map(item => `$${item.name}: ${item.type}`).join(', ')}) { + ${graphFieldsTotalVolume.factory}( + where: {${graphFieldsTotalVolume.filterParams.map(item => `${item.name}: $${item.name}`).join(', ')}} + ) { + ${graphFieldsTotalVolume.field} + } + } + ` : gql` query total_volume ($block: ${graphFieldsTotalVolume.blockGraphType}) { ${graphFieldsTotalVolume.factory}(block: { number: $block }) { ${graphFieldsTotalVolume.field} @@ -181,26 +196,49 @@ function getGraphDimensions({ ${graphFieldsDailyVolume.field} } } - `: undefined - return async (timestamp: number, chainBlocks: ChainBlocks) => { + ` + : undefined; + return async (_a: any, _b: any, options: FetchOptions) => { + const { endTimestamp, getEndBlock } = options; + // ts-node --transpile-only cli/testAdapter.ts protocols uniswap + const customBlockFunc = getCustomBlock ? getCustomBlock : getEndBlock; + const block = + (await customBlockFunc(endTimestamp).catch((e: any) => + console.log(wrapGraphError(e).message), + )) ?? undefined; // Get params - const id = String(getUniswapDateId(new Date(timestamp * 1000))); - const cleanTimestamp = getUniqStartOfTodayTimestamp(new Date(timestamp * 1000)) - const customBlockFunc = getCustomBlock ? getCustomBlock : chainBlocks?.[chain] ? async (_: number) => chainBlocks[chain] : getBlock - const block = await customBlockFunc(timestamp, chain, chainBlocks).catch(e => console.log(wrapGraphError(e).message)) ?? undefined + const id = String(getUniswapDateId(new Date(endTimestamp * 1000))); // Execute queries // DAILY VOLUME - let graphResDailyVolume - let dailyVolume: any + let graphResDailyVolume; + let dailyVolume: any; if (dailyVolumePairsQuery) { - console.info("Calculating volume excluding blacklisted tokens...") - graphResDailyVolume = await request(graphUrls[chain], dailyVolumePairsQuery, { - timestamp_gt: timestamp - 3600 * 24, - timestamp_lte: timestamp - }, graphRequestHeaders?.[chain]).catch(handle200Errors).catch(e => console.error(`GraphFetchError: Failed to get daily volume on ${chain} with graph ${graphUrls[chain]}: ${wrapGraphError(e).message}`)) - dailyVolume = graphResDailyVolume?.[graphFieldsDailyVolume.pairs]?.reduce((acc: number | undefined, current: pair) => { - if (blacklistTokens[chain].includes(current.token0.id) || blacklistTokens[chain].includes(current.token1.id)) - return acc + console.info("Calculating volume excluding blacklisted tokens..."); + graphResDailyVolume = await request( + graphUrls[chain], + dailyVolumePairsQuery, + { + timestamp_gt: endTimestamp - 3600 * 24, + timestamp_lte: endTimestamp, + }, + graphRequestHeaders?.[chain], + ) + .catch(handle200Errors) + .catch((e) => + console.error( + `GraphFetchError: Failed to get daily volume on ${chain} with graph ${ + graphUrls[chain] + }: ${wrapGraphError(e).message}`, + ), + ); + dailyVolume = graphResDailyVolume?.[ + graphFieldsDailyVolume.pairs + ]?.reduce((acc: number | undefined, current: pair) => { + if ( + blacklistTokens[chain].includes(current.token0.id) || + blacklistTokens[chain].includes(current.token1.id) + ) + return acc; if (current?.[graphFieldsDailyVolume.field]) { if (acc) return acc += +current?.[graphFieldsDailyVolume.field] return +current?.[graphFieldsDailyVolume.field] @@ -212,14 +250,29 @@ function getGraphDimensions({ dailyVolume = graphResDailyVolume?.[graphFieldsDailyVolume.factory]?.[graphFieldsDailyVolume.field] if (!graphResDailyVolume || !dailyVolume) { console.info("Attempting with alternative query...") - graphResDailyVolume = await request(graphUrls[chain], alternativeDailyQuery, { timestamp: cleanTimestamp }, graphRequestHeaders?.[chain]).catch(handle200Errors).catch(e => console.error(`Failed to get alternative daily volume on ${chain} with graph ${graphUrls[chain]}: ${wrapGraphError(e).message}`)) + graphResDailyVolume = await request(graphUrls[chain], alternativeDailyQuery, { timestamp: getUniqStartOfTodayTimestamp(new Date(endTimestamp * 1000)) }, graphRequestHeaders?.[chain]).catch(handle200Errors).catch(e => console.error(`Failed to get alternative daily volume on ${chain} with graph ${graphUrls[chain]}: ${wrapGraphError(e).message}`)) const factory = graphFieldsDailyVolume.factory.toLowerCase().charAt(graphFieldsDailyVolume.factory.length - 1) === 's' ? graphFieldsDailyVolume.factory : `${graphFieldsDailyVolume.factory}s` dailyVolume = graphResDailyVolume?.[factory].reduce((p: any, c: any) => p + Number(c[graphFieldsDailyVolume.field]), 0); } } // TOTAL VOLUME - const graphResTotalVolume = await request(graphUrls[chain], totalVolumeQuery, { block }, graphRequestHeaders?.[chain]).catch(handle200Errors).catch(e => console.error(`GraphFetchError: Failed to get total volume on ${chain} with graph ${graphUrls[chain]}: ${wrapGraphError(e).message}`)); + let graphQueryTodayTotalVolumeVariables: { [key: string]: any } = {} + let graphQueryYesterdayTotalVolumeVariables: { [key: string]: any } = {} + if (graphFieldsTotalVolume.filterParams) { + graphFieldsTotalVolume.filterParams.forEach((item) => { + switch (item.name) { + case "id": + graphQueryTodayTotalVolumeVariables["id"] = parseInt(id); + graphQueryYesterdayTotalVolumeVariables["id"] = parseInt(id)-1 + default: + } + }); + } else { + graphQueryTodayTotalVolumeVariables = { block } + } + + const graphResTotalVolume = await request(graphUrls[chain], totalVolumeQuery, graphQueryTodayTotalVolumeVariables, graphRequestHeaders?.[chain]).catch(handle200Errors).catch(e => console.error(`GraphFetchError: Failed to get total volume on ${chain} with graph ${graphUrls[chain]}: ${wrapGraphError(e).message}`)); const totalVolume = graphResTotalVolume?.[graphFieldsTotalVolume.factory]?.reduce((total: number, factory: any) => total + Number(factory[graphFieldsTotalVolume.field]), 0)?.toString() // DAILY FEES @@ -237,7 +290,7 @@ function getGraphDimensions({ const totalFees = graphResTotalFees?.[graphFieldsTotalFees.factory]?.reduce((total: number, factory: any) => total + Number(factory[graphFieldsTotalFees.field]), 0) const response: FetchResultGeneric = { - timestamp, + timestamp: endTimestamp, block, totalVolume, dailyVolume, @@ -262,6 +315,114 @@ function getGraphDimensions({ }; } +function getGraphDimensions2({ + graphUrls, + graphRequestHeaders, + totalVolume = { + factory: DEFAULT_TOTAL_VOLUME_FACTORY, + field: DEFAULT_TOTAL_VOLUME_FIELD, + blockGraphType: DEFAULT_BLOCK_TYPE + }, + totalFees = { + factory: DEFAULT_TOTAL_FEES_FACTORY, + field: DEFAULT_TOTAL_FEES_FIELD, + }, + getCustomBlock, + feesPercent, +}: IGetChainVolumeParams) { + // TOTAL VOLUME + // Graph fields + const graphFieldsTotalVolume = { + factory: totalVolume.factory ?? DEFAULT_TOTAL_VOLUME_FACTORY, + field: totalVolume.field ?? DEFAULT_TOTAL_VOLUME_FIELD, + blockGraphType: totalVolume.blockGraphType ?? DEFAULT_BLOCK_TYPE + } + // Queries + const totalVolumeQuery = gql` + query total_volume ($block: ${graphFieldsTotalVolume.blockGraphType}) { + ${graphFieldsTotalVolume.factory}(block: { number: $block }) { + ${graphFieldsTotalVolume.field} + } + }`; + + // TOTAL FEES + // Graph fields + const graphFieldsTotalFees = { + factory: totalFees.factory ?? DEFAULT_TOTAL_FEES_FACTORY, + field: totalFees.field ?? DEFAULT_TOTAL_FEES_FIELD + } + // Query + const totalFeesQuery = gql` + query total_fees ($block: ${graphFieldsTotalVolume.blockGraphType}) { + ${graphFieldsTotalFees.factory}(block: { number: $block }) { + ${graphFieldsTotalFees.field} + } + }`; + + return (chain: Chain) => { + return async (options: FetchOptions) => { + const { endTimestamp, startTimestamp, getEndBlock, getStartBlock } = options; + + const endBlock = (await (getCustomBlock ? getCustomBlock(endTimestamp) : getEndBlock()).catch((e: any) => + console.log(wrapGraphError(e).message), + )) ?? undefined; + const startBlock = (await (getCustomBlock ? getCustomBlock(startTimestamp) :getStartBlock()).catch((e: any) => + console.log(wrapGraphError(e).message), + )) ?? undefined; + + let dailyVolume: any; + // TOTAL VOLUME + const graphResTotalVolume = await request(graphUrls[chain], totalVolumeQuery, { block: endBlock }, graphRequestHeaders?.[chain]).catch(handle200Errors).catch(e => console.error(`GraphFetchError: Failed to get total volume on ${chain} with graph ${graphUrls[chain]}: ${wrapGraphError(e).message}`)); + const totalVolume = graphResTotalVolume?.[graphFieldsTotalVolume.factory]?.reduce((total: number, factory: any) => total + Number(factory[graphFieldsTotalVolume.field]), 0)?.toString() + + // PREV TOTAL VOLUME + const graphResPrevTotalVolume = await request(graphUrls[chain], totalVolumeQuery, { block: startBlock }, graphRequestHeaders?.[chain]).catch(handle200Errors).catch(e => console.error(`GraphFetchError: Failed to get total volume on ${chain} with graph ${graphUrls[chain]}: ${wrapGraphError(e).message}`)); + const prevTotalVolume = graphResPrevTotalVolume?.[graphFieldsTotalVolume.factory]?.reduce((total: number, factory: any) => total + Number(factory[graphFieldsTotalVolume.field]), 0)?.toString() + dailyVolume = totalVolume - prevTotalVolume + + // TOTAL FEES + const graphResTotalFees = await request(graphUrls[chain], totalFeesQuery, { block: endBlock }, graphRequestHeaders?.[chain]).catch(_e => { + if (totalVolume === undefined || feesPercent?.Fees === undefined) + console.error(`Unable to get total fees on ${chain} from graph.`) + }); + const totalFees = graphResTotalFees?.[graphFieldsTotalFees.factory]?.reduce((total: number, factory: any) => total + Number(factory[graphFieldsTotalFees.field]), 0) + + // PREV TOTAL FEES + const graphResPrevTotalFees = await request(graphUrls[chain], totalFeesQuery, { block: startBlock }, graphRequestHeaders?.[chain]).catch(_e => { + if (totalVolume === undefined || feesPercent?.Fees === undefined) + console.error(`Unable to get total fees on ${chain} from graph.`) + }); + const prevTotalFees = graphResPrevTotalFees?.[graphFieldsTotalFees.factory]?.reduce((total: number, factory: any) => total + Number(factory[graphFieldsTotalFees.field]), 0) + + const dailyFees = (totalFees == undefined && prevTotalFees == undefined) ? undefined : totalFees - prevTotalFees + + // ts-node --transpile-only cli/testAdapter.ts protocols uniswap + let response: FetchResultGeneric = { + timestamp: endTimestamp, + block: endBlock, + totalVolume, + dailyVolume, + dailyFees, + totalFees + }; + + if (feesPercent) { + const feeBase = feesPercent.type + const dailyBase = feeBase === 'volume' ? dailyVolume : dailyFees + const totalBase = feeBase === 'volume' ? totalVolume : totalFees + Object.entries(feesPercent).forEach(([feeType, feePercentType]) => { + if (typeof feePercentType !== "number") return + if (dailyBase !== undefined && response[`daily${feeType}`] === undefined) + response[`daily${feeType}`] = new BigNumber(dailyBase).multipliedBy(feePercentType / 100).toString() + if (totalBase && response[`total${feeType}`] === undefined) + response[`total${feeType}`] = new BigNumber(totalBase).multipliedBy(feePercentType / 100).toString() + }) + } + return response + }; + }; +} + function univ2DimensionAdapter(params: IGetChainVolumeParams, meta: BaseAdapter[string]['meta']) { const graphs = getGraphDimensions(params); @@ -276,30 +437,59 @@ function univ2DimensionAdapter(params: IGetChainVolumeParams, meta: BaseAdapter[ chain, volumeField: params.dailyVolume?.field, dailyDataField: params.dailyVolume?.factory + "s", - dateField: params.dailyVolume?.dateField + dateField: params.dailyVolume?.dateField, }), - meta - } - } - }, {} as BaseAdapter) + meta, + }, + }; + }, {} as BaseAdapter), + version: 1 + }; + + return adapter; +} + +function univ2DimensionAdapter2(params: IGetChainVolumeParams, meta: BaseAdapter[string]['meta']) { + const graphs = getGraphDimensions2(params); + + const adapter: SimpleAdapter = { + adapter: Object.keys(params.graphUrls).reduce((acc, chain) => { + return { + ...acc, + [chain]: { + fetch: graphs(chain as Chain), + start: getStartTimestamp({ + endpoints: params.graphUrls, + chain, + volumeField: params.dailyVolume?.field, + dailyDataField: params.dailyVolume?.factory + "s", + dateField: params.dailyVolume?.dateField, + }), + meta, + }, + }; + }, {} as BaseAdapter), + version: 2 }; return adapter; } function wrapGraphError(e: Error) { - const message = (e as any).response?.errors?.[0]?.message ?? e.message - return new Error(shortenString(message)) + const message = (e as any).response?.errors?.[0]?.message ?? e.message; + return new Error(shortenString(message)); function shortenString(str: string, maxLength: number = 420) { - return str.length > maxLength ? str.slice(0, maxLength) + '...' : str + return str.length > maxLength ? str.slice(0, maxLength) + "..." : str; } } export { wrapGraphError, getGraphDimensions, + getGraphDimensions2, univ2DimensionAdapter, + univ2DimensionAdapter2, DEFAULT_TOTAL_VOLUME_FACTORY, DEFAULT_TOTAL_VOLUME_FIELD, DEFAULT_DAILY_VOLUME_FACTORY, diff --git a/helpers/getUniSubgraphFees.ts b/helpers/getUniSubgraphFees.ts index b318474c81..dd286bccc2 100644 --- a/helpers/getUniSubgraphFees.ts +++ b/helpers/getUniSubgraphFees.ts @@ -18,7 +18,7 @@ import { DEFAULT_DAILY_VOLUME_FACTORY, DEFAULT_DAILY_VOLUME_FIELD, } from "../helpers/getUniSubgraphVolume"; -import type { ChainEndpoints, Fetch, FetchOptions } from "../adapters/types"; +import type { ChainEndpoints, Fetch, FetchOptions, FetchResultV2, FetchV2 } from "../adapters/types"; // To get ID for daily data https://docs.uniswap.org/protocol/V2/reference/API/entities const getUniswapDateId = (date?: Date) => getUniqStartOfTodayTimestamp(date) / 86400; @@ -138,11 +138,11 @@ const getDexChainFees = ({ volumeAdapter, totalFees = 0, protocolFees = 0, ...pa const adapterObj = volumeAdapter.adapter Object.keys(adapterObj).map(chain => { - const fetchFees = async (timestamp: number, chainBlocks: ChainBlocks, options: FetchOptions) => { - const fetchedResult: FetchResultVolume = await (adapterObj[chain].fetch as Fetch)(timestamp, chainBlocks, options) + const fetchFees = async (options: FetchOptions) => { + const fetchedResult: FetchResultV2 = await (adapterObj[chain].fetch as FetchV2)(options) const chainDailyVolume = fetchedResult.dailyVolume as number; const chainTotalVolume = fetchedResult.totalVolume as number; - const response: FetchResultGeneric = { timestamp } + const response: FetchResultV2 = { } if (chainDailyVolume !== undefined) { if (totalFees) response["dailyFees"] = new BigNumber(chainDailyVolume).multipliedBy(totalFees).toString() diff --git a/helpers/getUniSubgraphVolume.ts b/helpers/getUniSubgraphVolume.ts index 7991c680fe..b9dcc8af2d 100644 --- a/helpers/getUniSubgraphVolume.ts +++ b/helpers/getUniSubgraphVolume.ts @@ -1,7 +1,6 @@ import { Chain } from "@defillama/sdk/build/general"; import { request, gql } from "graphql-request"; -import { getBlock } from "./getBlock"; -import { BaseAdapter, ChainBlocks } from "../adapters/types"; +import { BaseAdapter, FetchOptions, FetchResultV2 } from "../adapters/types"; import { SimpleAdapter } from "../adapters/types"; import { DEFAULT_DATE_FIELD, getStartTimestamp } from "./getStartTimestamp"; import { Balances } from "@defillama/sdk"; @@ -32,13 +31,19 @@ const DEFAULT_DAILY_VOLUME_FACTORY = "uniswapDayData"; const DEFAULT_DAILY_VOLUME_FIELD = "dailyVolumeUSD"; const DEFAULT_DAILY_DATE_FIELD = "date"; +interface IGetChainVolumeFilterParams { + name: string, + type: string +} + interface IGetChainVolumeParams { graphUrls: { [chains: string]: string }, totalVolume: { factory: string, - field: string + field: string, + filterParams?: IGetChainVolumeFilterParams[], }, dailyVolume?: { factory: string, @@ -50,7 +55,7 @@ interface IGetChainVolumeParams { hasTotalVolume?: boolean getCustomBlock?: (timestamp: number) => Promise } - +// HERE function getChainVolume({ graphUrls, totalVolume = { @@ -63,16 +68,25 @@ function getChainVolume({ dateField: DEFAULT_DAILY_DATE_FIELD }, customDailyVolume = undefined, - hasDailyVolume = true, + hasDailyVolume = false, hasTotalVolume = true, getCustomBlock = undefined, }: IGetChainVolumeParams) { - const totalVolumeQuery = gql` - ${totalVolume.factory}( - block: { number: $block } - ) { - ${totalVolume.field} - } + const totalVolumeQuery = totalVolume.filterParams + ? gql`query get_total_volume(${totalVolume.filterParams.map(item => `$${item.name}: ${item.type}`).join(', ')}) { + ${totalVolume.factory}( + where: {${totalVolume.filterParams.map(item => `${item.name}: $${item.name}`).join(', ')}} + ) { + ${totalVolume.field} + } + } + ` : gql`query get_total_volume($block: Int) { + ${totalVolume.factory}( + block: { number: $block } + ) { + ${totalVolume.field} + } + } `; const dailyVolumeQuery = @@ -89,17 +103,33 @@ function getChainVolume({ } }`; - const graphQueryTotalVolume = gql`${hasTotalVolume ? `query get_total_volume($block: Int) { ${totalVolumeQuery} }` : ""}` + const graphQueryTotalVolume = gql`${hasTotalVolume ? totalVolumeQuery : ""}` const graphQueryDailyVolume = gql`${hasDailyVolume ? `query get_daily_volume($id: Int) { ${dailyVolumeQuery} }` : ""}`; return (chain: Chain) => { - return async (timestamp: number, chainBlocks: ChainBlocks) => { - const block = - (getCustomBlock ? - await getCustomBlock(timestamp).catch(e => console.log(e.message)) : - await getBlock(timestamp, chain, chainBlocks).catch(e => console.log(e.message))) ?? undefined; - const id = getUniswapDateId(new Date(timestamp * 1000)); - const graphResTotal = hasTotalVolume ? await request(graphUrls[chain], graphQueryTotalVolume, { block }).catch(e => { + return async (_a: any, _b: any, options: FetchOptions) => { + const { endTimestamp, getEndBlock, getFromBlock, getToBlock } = options; + const customBlockFunc = getCustomBlock ? getCustomBlock : getEndBlock; + const block = (await customBlockFunc(endTimestamp).catch((e: any) => + console.log(wrapGraphError(e).message), + )) ?? undefined; + const id = getUniswapDateId(new Date(endTimestamp * 1000)); + let graphQueryTodayTotalVolumeVariables: { [key: string]: any } = {} + let graphQueryYesterdayTotalVolumeVariables: { [key: string]: any } = {} + if (totalVolume.filterParams) { + totalVolume.filterParams.forEach((item) => { + switch (item.name) { + case "id": + graphQueryTodayTotalVolumeVariables["id"] = id; + graphQueryYesterdayTotalVolumeVariables["id"] = id-1 + default: + } + }); + } else { + graphQueryTodayTotalVolumeVariables = { block } + } + + const graphResTotal = hasTotalVolume ? await request(graphUrls[chain], graphQueryTotalVolume, graphQueryTodayTotalVolumeVariables).catch(e => { try { return JSON.parse(e.response.error).data } catch (error) { @@ -115,7 +145,7 @@ function getChainVolume({ }) : undefined; let dailyVolumeValue = graphResDaily ? graphResDaily[dailyVolume.factory]?.[dailyVolume.field] : undefined if (hasDailyVolume && !dailyVolumeValue) { - graphResDaily = await request(graphUrls[chain], alternativeDaily(getUniqStartOfTodayTimestamp(new Date(timestamp * 1000)))).catch(e => { + graphResDaily = await request(graphUrls[chain], alternativeDaily(getUniqStartOfTodayTimestamp(new Date(endTimestamp * 1000)))).catch(e => { try { return JSON.parse(e.response.error).data } catch (error) { @@ -125,9 +155,26 @@ function getChainVolume({ const factory = dailyVolume.factory.toLowerCase().charAt(dailyVolume.factory.length - 1) === 's' ? dailyVolume.factory : `${dailyVolume.factory}s` dailyVolumeValue = graphResDaily ? graphResDaily[`${factory}`].reduce((p: any, c: any) => p + Number(c[`${dailyVolume.field}`]), 0) : undefined; } + if (!hasDailyVolume) { + const fromBlock = await getFromBlock() + const toBlock = await getToBlock(); + if (!totalVolume.filterParams) { + graphQueryTodayTotalVolumeVariables["block"] = toBlock; + graphQueryYesterdayTotalVolumeVariables["block"] = fromBlock + } + try { + const [yesterdayResult, todayResult] = await Promise.all([request(graphUrls[chain], graphQueryTotalVolume, graphQueryYesterdayTotalVolumeVariables), request(graphUrls[chain], graphQueryTotalVolume, graphQueryTodayTotalVolumeVariables)]) + const todayVolume = todayResult[totalVolume.factory].reduce((p: any, c: any) => p + Number(c[`${totalVolume.field}`]), 0) + const yesterdayVolume = yesterdayResult[totalVolume.factory].reduce((p: any, c: any) => p + Number(c[`${totalVolume.field}`]), 0) + const volume24H = todayVolume - yesterdayVolume; + dailyVolumeValue = volume24H; + } catch (e: any) { + console.error(`Failed to get daily volume via alternative query on ${graphUrls[chain]} ${chain}: ${wrapGraphError(e).message}`) + } + } return { - timestamp, + timestamp: endTimestamp, block, totalVolume: graphResTotal ? graphResTotal[totalVolume.factory]?.reduce((total: number, factory: any) => total + Number(factory[totalVolume.field]), 0) : undefined, dailyVolume: dailyVolumeValue, @@ -135,7 +182,64 @@ function getChainVolume({ }; }; } +function getChainVolume2({ + graphUrls, + totalVolume = { + factory: DEFAULT_TOTAL_VOLUME_FACTORY, + field: DEFAULT_TOTAL_VOLUME_FIELD, + }, + hasTotalVolume = true, + getCustomBlock = undefined, +}: IGetChainVolumeParams) { + const totalVolumeQuery = gql` + ${totalVolume.factory}( + block: { number: $block } + ) { + ${totalVolume.field} + } + `; + + const graphQueryTotalVolume = gql`query get_total_volume($block: Int) { ${totalVolumeQuery} }` + + return (chain: Chain) => { + return async (options: FetchOptions) => { + const { endTimestamp, startTimestamp, getEndBlock, getStartBlock } = options; + + const endBlock = (await (getCustomBlock ? getCustomBlock(endTimestamp) : getEndBlock()).catch((e: any) => + console.log(wrapGraphError(e).message), + )) ?? undefined; + const startBlock = (await (getCustomBlock ? getCustomBlock(startTimestamp) :getStartBlock()).catch((e: any) => + console.log(wrapGraphError(e).message), + )) ?? undefined; + + const graphResTotal = hasTotalVolume ? await request(graphUrls[chain], graphQueryTotalVolume, { block: endBlock }).catch(e => { + try { + return JSON.parse(e.response.error).data + } catch (error) { + console.error(`Failed to get total volume on ${chain} ${graphUrls[chain]}: ${wrapGraphError(e).message}`) + } + }) : undefined; + const total = graphResTotal ? graphResTotal[totalVolume.factory]?.reduce((total: number, factory: any) => total + Number(factory[totalVolume.field]), 0) : undefined; + const graphResPrevTotal = hasTotalVolume ? await request(graphUrls[chain], graphQueryTotalVolume, { block: startBlock }).catch(e => { + try { + return JSON.parse(e.response.error).data + } catch (error) { + console.error(`Failed to get total volume on ${chain} ${graphUrls[chain]}: ${wrapGraphError(e).message}`) + } + }) : undefined; + const prevTotal = graphResPrevTotal ? graphResPrevTotal[totalVolume.factory]?.reduce((total: number, factory: any) => total + Number(factory[totalVolume.field]), 0) : undefined; + + let dailyVolumeValue = total - prevTotal + + return { + block: endBlock, + totalVolume: total, + dailyVolume: dailyVolumeValue, + }; + }; + }; +} function getChainVolumeWithGasToken({ graphUrls, totalVolume = { @@ -155,14 +259,15 @@ function getChainVolumeWithGasToken({ }: IGetChainVolumeParams & {priceToken:string}) { const basic = getChainVolume({graphUrls, totalVolume, dailyVolume, customDailyVolume, hasDailyVolume, hasTotalVolume, getCustomBlock}) return (chain: Chain) => { - return async (timestamp: number, chainBlocks: ChainBlocks) => { + return async (_a: any, _b: any, options: FetchOptions) => { const { block, totalVolume, dailyVolume, - } = await basic(chain)(timestamp, chainBlocks); + } = await basic(chain)(_a, _b, options); - const balances = new Balances({ chain, timestamp}) + const timestamp = options.endTimestamp + const balances = new Balances({ chain, timestamp }) balances.add(priceToken, Number(dailyVolume).toFixed(0), { skipChain: true }) return { @@ -174,29 +279,106 @@ function getChainVolumeWithGasToken({ }; } +function getChainVolumeWithGasToken2({ + graphUrls, + totalVolume = { + factory: DEFAULT_TOTAL_VOLUME_FACTORY, + field: 'totalVolumeETH', + }, + getCustomBlock = undefined, + priceToken, +}: IGetChainVolumeParams & {priceToken:string}) { + const basic = getChainVolume2({graphUrls, totalVolume, getCustomBlock}) + return (chain: Chain) => { + return async (options: FetchOptions): Promise => { + const { + block, + dailyVolume, + totalVolume + } = await basic(chain)(options); + + const timestamp = options.endTimestamp + const balances = new Balances({ chain, timestamp }) + balances.add(priceToken, Number(dailyVolume).toFixed(0), { skipChain: true }) + + return { + block, + dailyVolume: await balances.getUSDString(), + totalVolume + } + }; + }; +} + function univ2Adapter(endpoints: { [chain: string]: string }, { factoriesName = DEFAULT_TOTAL_VOLUME_FACTORY, dayData = DEFAULT_DAILY_VOLUME_FACTORY, totalVolume = DEFAULT_TOTAL_VOLUME_FIELD, + totalVolumeFilterParams = undefined as IGetChainVolumeFilterParams[] | undefined, dailyVolume = DEFAULT_DAILY_VOLUME_FIELD, dailyVolumeTimestampField = DEFAULT_DATE_FIELD, hasTotalVolume = true, + hasDailyVolume = undefined as boolean|undefined, gasToken = null as string|null }) { - const graphs = (gasToken === null?getChainVolume:getChainVolumeWithGasToken as typeof getChainVolume)({ + const graphs = (gasToken === null ? getChainVolume : getChainVolumeWithGasToken as typeof getChainVolume)({ graphUrls: endpoints, hasTotalVolume, totalVolume: { factory: factoriesName, - field: totalVolume + field: totalVolume, + filterParams: totalVolumeFilterParams }, dailyVolume: { factory: dayData, field: dailyVolume, dateField: dailyVolumeTimestampField }, + hasDailyVolume, + priceToken: gasToken + } as any); + + const adapter: SimpleAdapter = { + adapter: Object.keys(endpoints).reduce((acc, chain) => { + return { + ...acc, + [chain]: { + fetch: graphs(chain as Chain), + start: getStartTimestamp({ + endpoints: endpoints, + chain, + volumeField: dailyVolume, + dailyDataField: dayData + "s", + dateField: dailyVolumeTimestampField + }), + } + } + }, {} as BaseAdapter), + version: 1 + }; + + return adapter; +} + + +function univ2Adapter2(endpoints: { + [chain: string]: string +}, { + factoriesName = DEFAULT_TOTAL_VOLUME_FACTORY, + dayData = DEFAULT_DAILY_VOLUME_FACTORY, + totalVolume = DEFAULT_TOTAL_VOLUME_FIELD, + dailyVolume = DEFAULT_DAILY_VOLUME_FIELD, + dailyVolumeTimestampField = DEFAULT_DATE_FIELD, + gasToken = null as string|null +}) { + const graphs = (gasToken === null ? getChainVolume2 : getChainVolumeWithGasToken2 as typeof getChainVolume2)({ + graphUrls: endpoints, + totalVolume: { + factory: factoriesName, + field: totalVolume + }, priceToken: gasToken } as any); @@ -215,7 +397,8 @@ function univ2Adapter(endpoints: { }), } } - }, {} as BaseAdapter) + }, {} as BaseAdapter), + version: 2 }; return adapter; @@ -224,8 +407,11 @@ function univ2Adapter(endpoints: { export { getUniqStartOfTodayTimestamp, getChainVolume, + getChainVolume2, getChainVolumeWithGasToken, + getChainVolumeWithGasToken2, univ2Adapter, + univ2Adapter2, DEFAULT_TOTAL_VOLUME_FACTORY, DEFAULT_TOTAL_VOLUME_FIELD, DEFAULT_DAILY_VOLUME_FACTORY, diff --git a/helpers/solidly.ts b/helpers/solidly.ts index bb685c2a46..f2b01076f0 100644 --- a/helpers/solidly.ts +++ b/helpers/solidly.ts @@ -1,5 +1,6 @@ import ADDRESSES from './coreAssets.json' -import { ChainBlocks, FetchOptions, FetchResultFees, } from "../adapters/types"; +import { FetchOptions, } from "../adapters/types"; +import { filterPools2 } from './uniswap'; const TOPIC_Notify = 'event NotifyReward(address indexed from, address indexed reward, uint indexed epoch, uint amount)'; @@ -19,27 +20,30 @@ const VOTER_ABI: TABI = { } export function getFeesExport({ VOTER_ADDRESS, FACTORY_ADDRESS, }: { VOTER_ADDRESS: string, FACTORY_ADDRESS: string }) { - return async (timestamp: number, _: ChainBlocks, { createBalances, api, getLogs, }: FetchOptions): Promise => { + return async (fetchOptions: FetchOptions) => { + const { api, getLogs, createBalances, } = fetchOptions const dailyFees = createBalances() const dailyRevenue = createBalances() const dailyBribesRevenue = createBalances() - const lpTokens = await api.fetchList({ lengthAbi: ABIs.allPairsLength, itemAbi: ABIs.allPairs, target: FACTORY_ADDRESS }); + let lpTokens = await api.fetchList({ lengthAbi: ABIs.allPairsLength, itemAbi: ABIs.allPairs, target: FACTORY_ADDRESS }); - const [tokens0, tokens1] = await Promise.all( + let [token0s, token1s] = await Promise.all( ['address:token0', 'address:token1'].map((method) => api.multiCall({ abi: method, calls: lpTokens, })) ); + const res = await filterPools2({ fetchOptions, pairs: lpTokens, token0s, token1s }) + lpTokens = res.pairs + token0s = res.token0s + token1s = res.token1s + const poolsGauges = await api.multiCall({ abi: VOTER_ABI.gauges, target: VOTER_ADDRESS, calls: lpTokens, }); const voterGauges = poolsGauges.filter((_vg: string) => _vg !== ADDRESSES.null); - const voterBribes = await api.multiCall({ - abi: VOTER_ABI.bribes, target: VOTER_ADDRESS, - calls: voterGauges, - }); + const voterBribes = await api.multiCall({ abi: VOTER_ABI.bribes, target: VOTER_ADDRESS, calls: voterGauges, }); const tradefeeLogs = await getLogs({ @@ -61,8 +65,8 @@ export function getFeesExport({ VOTER_ADDRESS, FACTORY_ADDRESS, }: { VOTER_ADDRE }) lpTokens.map((_: string, index: number) => { - const token0 = tokens0[index] - const token1 = tokens1[index] + const token0 = token0s[index] + const token1 = token1s[index] tradefeeLogs[index] .map((p: any) => { dailyFees.add(token0, p.amount0) @@ -70,6 +74,6 @@ export function getFeesExport({ VOTER_ADDRESS, FACTORY_ADDRESS, }: { VOTER_ADDRE }) }); - return { dailyFees, dailyRevenue: dailyRevenue, dailyHoldersRevenue: dailyRevenue, dailyBribesRevenue, timestamp, }; + return { dailyFees, dailyRevenue: dailyRevenue, dailyHoldersRevenue: dailyRevenue, dailyBribesRevenue, }; } } diff --git a/helpers/sui.ts b/helpers/sui.ts new file mode 100644 index 0000000000..00dfee928a --- /dev/null +++ b/helpers/sui.ts @@ -0,0 +1,44 @@ +const http = require('axios') +const { getEnv } = require('./env') + +// const endpoint = () => getEnv('SUI_RPC') +const endpoint = () => 'https://fullnode.mainnet.sui.io/' + +async function getObject(objectId:string) { + return (await call('sui_getObject', [objectId, { + "showType": true, + "showOwner": true, + "showContent": true, + }])).content +} + +export async function queryEvents({ eventType, options, transform = (i:any) => i }:any):Promise { + let filter:any = {} + if (eventType) filter.MoveEventType = eventType + const items:any[] = [] + let cursor = null + do { + const { data , nextCursor, hasNextPage } = await call('suix_queryEvents', [filter, cursor, 100, true], { withMetadata: true, }) + cursor = hasNextPage ? nextCursor : null + items.push(...data.filter((ev:any)=>{ + const ts = Number(ev.timestampMs)/1e3 + return options.startTimestamp < ts && ts < options.endTimestamp + })) + if(Number(data[data.length-1].timestampMs)/1e3 < options.startTimestamp){ + cursor = null + } + } while (cursor) + return items.map(i => i.parsedJson).map(transform) +} + +async function call(method:string, params:any, { withMetadata = false} = {}) { + if (!Array.isArray(params)) params = [params] + const { + data: {result} + } = await http.post(endpoint(), { jsonrpc: "2.0", id: 1, method, params, }) + return withMetadata ? result : result.data +} + +async function multiCall(calls:any[]) { + return Promise.all(calls.map(i => call(...(i as [any,any,any])))) +} \ No newline at end of file diff --git a/helpers/time-fun.ts b/helpers/time-fun.ts new file mode 100644 index 0000000000..af4e39ce70 --- /dev/null +++ b/helpers/time-fun.ts @@ -0,0 +1,35 @@ +import { FetchV2 } from "../adapters/types"; + +import ADDRESSES from "./coreAssets.json"; + +const abi = { + "SharesRedeemed": "event SharesRedeemed((address from, uint256 shares, uint256 totalCost, uint256 feeToApp, uint256 feeToCreator, uint256 feeToShareholders, uint256 feeToReferrer, address experienceCreator, uint256 totalSupplyExperience, address referrerAddress) event_)", + "SharesTraded": "event SharesTraded((address from, uint256 shares, bool isBuy, uint256 totalCost, uint256 feeToApp, uint256 feeToCreator, uint256 feeToShareholders, uint256 feeToReferrer, address experienceCreator, uint256 totalSupplyExperience, address referrerAddress) event_)", +} + +export function getFeesExport(contractAddress: string, { + token = ADDRESSES.null, +}: { token?: string } = {}) { + return (async ({ getLogs, createBalances, }) => { + const dailyFees = createBalances() + const dailyRevenue = createBalances() + const dailySupplySideRevenue = createBalances() + const tradeLogs = await getLogs({ target: contractAddress, eventAbi: abi.SharesTraded, topics: ['0x069a3131d4d72dbdcb40a0d8ff0aa58f71096c2726da05e3ed2608ddf1e93228'] }) + const redeemLogs = await getLogs({ target: contractAddress, eventAbi: abi.SharesRedeemed, topics: ['0x58d64bdf8bc9e2ab45691bd838283f536381da0d63e5370b131650a085f846c6'] }) + const addFees = ([e]: any) => { + + dailyFees.add(token, e.feeToApp) + dailyFees.add(token, e.feeToCreator) + dailyFees.add(token, e.feeToShareholders) + dailyFees.add(token, e.feeToReferrer) + + dailyRevenue.add(token, e.feeToApp) + dailySupplySideRevenue.add(token, e.feeToShareholders) + } + + tradeLogs.map(addFees) + redeemLogs.map(addFees) + + return { dailyFees, dailyRevenue, dailySupplySideRevenue, } + }) as FetchV2 +} \ No newline at end of file diff --git a/helpers/token.ts b/helpers/token.ts index e98aa7a73b..cc158173e7 100644 --- a/helpers/token.ts +++ b/helpers/token.ts @@ -6,6 +6,7 @@ import { getCache, setCache } from "./cache"; import { ethers } from "ethers"; import { getUniqueAddresses } from '@defillama/sdk/build/generalUtil'; import { getEnv } from './env'; +import { queryDuneSql } from './dune'; export const nullAddress = ADDRESSES.null @@ -16,21 +17,16 @@ export async function addGasTokensReceived(params: { balances?: sdk.Balances; }) { let { multisig, multisigs, options, balances } = params; + if (multisig) multisigs = [multisig] if (!balances) balances = options.createBalances() - if (multisigs?.length) { - const clonedOptions = { ...params } - delete clonedOptions.multisigs - clonedOptions.balances = balances - await Promise.all(multisigs.map(multisig => addGasTokensReceived({ ...clonedOptions, multisig }))) - return balances - } else if (!multisig) { + if (!multisigs?.length) { throw new Error('multisig or multisigs required') } const logs = await options.getLogs({ - target: multisig, + targets: multisigs, eventAbi: 'event SafeReceived (address indexed sender, uint256 value)' }) @@ -38,7 +34,8 @@ export async function addGasTokensReceived(params: { return balances } -export async function addTokensReceived(params: { +type AddTokensReceivedParams = { + fromAdddesses?: string[]; fromAddressFilter?: string | null; target?: string; targets?: string[]; @@ -49,13 +46,40 @@ export async function addTokensReceived(params: { tokenTransform?: (token: string) => string; fetchTokenList?: boolean; token?: string; -}) { - let { target, targets, options, balances, tokens, fromAddressFilter = null, tokenTransform = (i: string) => i, fetchTokenList = false, token } = params; + skipIndexer?: boolean; +} + +export async function addTokensReceived(params: AddTokensReceivedParams) { + + if (!params.skipIndexer) { + try { + const balances = await _addTokensReceivedIndexer(params) + return balances + } catch (e) { + console.error('Token transfers: Failed to use indexer, falling back to logs', (e as any)?.message) + } + } + + + + let { target, targets, options, balances, tokens, fromAddressFilter = null, tokenTransform = (i: string) => i, fetchTokenList = false, token, fromAdddesses, } = params; const { chain, createBalances, getLogs, } = options - if (!tokens && token) tokens = [token] if (!balances) balances = createBalances() + if (fromAdddesses && fromAdddesses.length) { + if (fromAdddesses.length === 1) fromAddressFilter = fromAdddesses[0] + else { + const clonedOptions = { ...params, balances, skipIndexer: true } + delete clonedOptions.fromAdddesses + await Promise.all(fromAdddesses.map(fromAddressFilter => addTokensReceived({ ...clonedOptions, fromAddressFilter }))) + return balances + } + } + + if (!tokens && token) tokens = [token] + + if (targets?.length) { const clonedOptions = { ...params } delete clonedOptions.targets @@ -66,19 +90,23 @@ export async function addTokensReceived(params: { throw new Error('target/fromAddressFilter or targets required') } + const toAddressFilter = target ? ethers.zeroPadValue(target, 32) : null + if (fromAddressFilter) fromAddressFilter = ethers.zeroPadValue(fromAddressFilter, 32) - if (!tokens && target && fetchTokenList) { - if (!ankrChainMapping[chain]) throw new Error('Chain Not supported: ' + chain) - const ankrTokens = await ankrGetTokens(target, { onlyWhitelisted: true }) - tokens = ankrTokens[ankrChainMapping[chain]] ?? [] + if (!tokens && target) { + if (fetchTokenList) { + if (!ankrChainMapping[chain]) throw new Error('Chain Not supported: ' + chain) + const ankrTokens = await ankrGetTokens(target, { onlyWhitelisted: true }) + tokens = ankrTokens[ankrChainMapping[chain]] ?? [] + } else { + return getAllTransfers(fromAddressFilter, toAddressFilter, balances, tokenTransform, options) + } } if (!tokens?.length) return balances tokens = getUniqueAddresses(tokens.filter(i => !!i), options.chain) - const toAddressFilter = target ? ethers.zeroPadValue(target, 32) : null - if (fromAddressFilter) fromAddressFilter = ethers.zeroPadValue(fromAddressFilter, 32) const logs = await getLogs({ targets: tokens, flatten: false, @@ -93,6 +121,26 @@ export async function addTokensReceived(params: { return balances } +async function _addTokensReceivedIndexer(params: AddTokensReceivedParams) { + let { balances, fromAddressFilter, target, targets, options, fromAdddesses, tokenTransform = (i: string) => i, tokens } = params + const { createBalances, chain, getFromBlock, getToBlock } = options + if (!balances) balances = createBalances() + if (fromAdddesses && fromAdddesses.length) (fromAddressFilter as any) = fromAdddesses + const logs = await sdk.indexer.getTokenTransfers({ + fromBlock: await getFromBlock(), + toBlock: await getToBlock(), + chain, + target, targets, + fromAddressFilter: fromAddressFilter as any, + tokens, + }) + logs.forEach((i: any) => { + balances!.add(tokenTransform(i.token), i.value) + }) + + return balances +} + const ankrTokenCalls: any = {} const ankrChainMapping: { @@ -174,6 +222,24 @@ async function ankrGetTokens(address: string, { onlyWhitelisted = true }: { } } +async function getAllTransfers(fromAddressFilter: string | null, toAddressFilter: string | null, + balances: sdk.Balances, tokenTransform: (token: string) => string, options: FetchOptions) { + const logs = await options.getLogs({ + topics: [ + "0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef", // Transfer(address,address,uint256) + fromAddressFilter as any, + toAddressFilter as any + ], + eventAbi: 'event Transfer (address indexed from, address indexed to, uint256 value)', + entireLog: true, + }) + + logs.forEach((log) => { + balances!.add(tokenTransform(log.address), log.data) + }) + return balances +} + export async function getTokenDiff(params: { target?: string; targets?: string[]; @@ -222,3 +288,21 @@ export async function getTokenDiff(params: { return balances } + + +export const evmReceivedGasAndTokens = (receiverWallet: string, tokens: string[]) => + async (options: FetchOptions) => { + let dailyFees = options.createBalances() + if (tokens.length > 0) { + dailyFees = await addTokensReceived({ options, tokens: tokens, target: receiverWallet }) + } + const nativeTransfers = await queryDuneSql(options, `select sum(value) as received from CHAIN.traces + where to = ${receiverWallet} AND tx_success = TRUE + AND TIME_RANGE`) + dailyFees.add(nullAddress, nativeTransfers[0].received) + + return { + dailyFees, + dailyRevenue: dailyFees, + } + } \ No newline at end of file diff --git a/helpers/uniswap.ts b/helpers/uniswap.ts index 7bd94d823c..2b5e42d698 100644 --- a/helpers/uniswap.ts +++ b/helpers/uniswap.ts @@ -4,10 +4,11 @@ import { BaseAdapter, FetchV2, IJSON, SimpleAdapter } from "../adapters/types"; import { addOneToken } from "./prices"; import { ethers } from "ethers"; +const ZERO_ADDRESS = "0x0000000000000000000000000000000000000000"; -export async function filterPools({ api, pairs, createBalances }: { api: ChainApi, pairs: IJSON, createBalances: any }): Promise> { +export async function filterPools({ api, pairs, createBalances, maxPairSize = 42, minUSDValue = 300 }: { api: ChainApi, pairs: IJSON, createBalances: any, maxPairSize?: number, minUSDValue?: number }): Promise> { const balanceCalls = Object.entries(pairs).map(([pair, tokens]) => tokens.map(i => ({ target: i, params: pair }))).flat() - const res = await api.multiCall({ abi: 'erc20:balanceOf', calls: balanceCalls }) + const res = await api.multiCall({ abi: 'erc20:balanceOf', calls: balanceCalls, permitFailure: true, }) const balances: Balances = createBalances() const pairBalances: IJSON = {} res.forEach((bal, i) => { @@ -15,71 +16,102 @@ export async function filterPools({ api, pairs, createBalances }: { api: ChainAp if (!pairBalances[balanceCalls[i].params]) { pairBalances[balanceCalls[i].params] = createBalances() } - pairBalances[balanceCalls[i].params].add(balanceCalls[i].target, bal) + pairBalances[balanceCalls[i].params].add(balanceCalls[i].target, bal ?? 0) }) - // we do this to cache price results + // we do this to cache price results await balances.getUSDValue() const filteredPairs: IJSON = {} for (const pair of Object.keys(pairs)) { const pooledValue = await pairBalances[pair].getUSDValue() - if (pooledValue < 1000) + if (pooledValue < minUSDValue) continue; filteredPairs[pair] = pooledValue } - if (Object.keys(filteredPairs).length < 42) + if (Object.keys(filteredPairs).length < maxPairSize) return filteredPairs - // if there are more than 42 pools, we need to filter out the ones with the lowest value - const sortedPairs = Object.entries(filteredPairs).sort((a, b) => b[1] - a[1]).slice(0, 42) + // if there are more than 21 pools, we need to filter out the ones with the lowest value + const sortedPairs = Object.entries(filteredPairs).sort((a, b) => b[1] - a[1]).slice(0, maxPairSize) return Object.fromEntries(sortedPairs) } const defaultV2SwapEvent = 'event Swap(address indexed sender, uint amount0In, uint amount1In, uint amount0Out, uint amount1Out, address indexed to)' +const notifyRewardEvent = 'event NotifyReward(address indexed from,address indexed reward,uint256 indexed epoch,uint256 amount)'; -export const getUniV2LogAdapter: any = ({ factory, fees = 0.003, swapEvent = defaultV2SwapEvent, }: UniV2Config): FetchV2 => { - const fetch: FetchV2 = async ({ createBalances, getLogs, chain, api }) => { +export const getUniV2LogAdapter: any = ({ factory, fees = 0.003, swapEvent = defaultV2SwapEvent, stableFees = 1 / 10000, voter, maxPairSize, customLogic, }: UniV2Config): FetchV2 => { + const fetch: FetchV2 = async (fetchOptions) => { + const { createBalances, getLogs, chain, api } = fetchOptions factory = factory.toLowerCase() const cacheKey = `tvl-adapter-cache/cache/uniswap-forks/${factory}-${chain}.json` - const { pairs, token0s, token1s } = await cache.readCache(cacheKey) + const { pairs, token0s, token1s } = await cache.readCache(cacheKey, { readFromR2Cache: true }) if (!pairs?.length) throw new Error('No pairs found, is there TVL adapter for this already?') const pairObject: IJSON = {} pairs.forEach((pair: string, i: number) => { pairObject[pair] = [token0s[i], token1s[i]] }) const dailyVolume = createBalances() - const filteredPairs = await filterPools({ api, pairs: pairObject, createBalances }) - await Promise.all(Object.keys(filteredPairs).map(async (pair) => { + const dailyFees = createBalances() + const filteredPairs = await filterPools({ api, pairs: pairObject, createBalances, maxPairSize }) + const pairIds = Object.keys(filteredPairs) + api.log(`uniV2RunLog: Filtered to ${pairIds.length}/${pairs.length} pairs Factory: ${factory} Chain: ${chain}`) + const isStablePair = await api.multiCall({ abi: 'bool:stable', calls: pairIds, permitFailure: true }) + await Promise.all(pairIds.map(async (pair, index) => { + let _fees = isStablePair[index] ? stableFees : fees const [token0, token1] = pairObject[pair] const logs = await getLogs({ target: pair, eventAbi: swapEvent }) logs.forEach(log => { addOneToken({ chain, balances: dailyVolume, token0, token1, amount0: log.amount0In, amount1: log.amount1In }) addOneToken({ chain, balances: dailyVolume, token0, token1, amount0: log.amount0Out, amount1: log.amount1Out }) + addOneToken({ chain, balances: dailyFees, token0, token1, amount0: Number(log.amount0In) * _fees, amount1: Number(log.amount1In) * _fees }) + addOneToken({ chain, balances: dailyFees, token0, token1, amount0: Number(log.amount0Out) * _fees, amount1: Number(log.amount1Out) * _fees }) }) })) + if (customLogic) + return customLogic({ pairObject, dailyVolume, dailyFees, filteredPairs, fetchOptions }) + + + if (voter) { + const dailyBribesRevenue = createBalances() + const bribeContracts: string[] = await api.multiCall({ abi: 'function gauges(address) view returns (address)', calls: pairIds, target: voter }) + let feesVotingReward: string[] = await api.multiCall({ abi: 'address:feesVotingReward', calls: bribeContracts, permitFailure: true }) + if (feesVotingReward.filter((e: any) => e).length === 0) { + api.log('No feesVotingReward found, trying bribes') + feesVotingReward = bribeContracts + } + api.log(bribeContracts.length, 'bribes contracts found') + + const logs = await getLogs({ targets: feesVotingReward.filter(i => i !== ZERO_ADDRESS), eventAbi: notifyRewardEvent, }) + + logs.map((e: any) => { + dailyBribesRevenue.add(e.reward, e.amount) + }) - return { dailyVolume, dailyFees: dailyVolume.clone(fees) } + return { dailyVolume, dailyFees, dailyRevenue: dailyFees, dailyHoldersRevenue: dailyFees, dailyBribesRevenue } + } + + return { dailyVolume, dailyFees, } } return fetch } const defaultV3SwapEvent = 'event Swap(address indexed sender, address indexed recipient, int256 amount0, int256 amount1, uint160 sqrtPriceX96, uint128 liquidity, int24 tick)' const defaultPoolCreatedEvent = 'event PoolCreated(address indexed token0, address indexed token1, uint24 indexed fee, int24 tickSpacing, address pool)' -export const getUniV3LogAdapter: any = ({ factory, poolCreatedEvent = defaultPoolCreatedEvent, swapEvent = defaultV3SwapEvent, }: UniV3Config): FetchV2 => { - const fetch: FetchV2 = async ({ createBalances, getLogs, chain, api }) => { +export const getUniV3LogAdapter: any = ({ factory, poolCreatedEvent = defaultPoolCreatedEvent, swapEvent = defaultV3SwapEvent, customLogic }: UniV3Config): FetchV2 => { + const fetch: FetchV2 = async (fetchOptions) => { + const { createBalances, getLogs, chain, api } = fetchOptions factory = factory.toLowerCase() const cacheKey = `tvl-adapter-cache/cache/logs/${chain}/${factory}.json` const iface = new ethers.Interface([poolCreatedEvent]) - - let { logs } = await cache.readCache(cacheKey) + let { logs } = await cache.readCache(cacheKey, { readFromR2Cache: true }) if (!logs?.length) throw new Error('No pairs found, is there TVL adapter for this already?') logs = logs.map((log: any) => iface.parseLog(log)?.args) const pairObject: IJSON = {} const fees: any = {} logs.forEach((log: any) => { pairObject[log.pool] = [log.token0, log.token1] - fees[log.pool] = log.fee.toString() / 1e6 + fees[log.pool] = (log.fee?.toString() || 0) / 1e6 // seem some protocol v3 forks does not have fee in the log when not use defaultPoolCreatedEvent }) const filteredPairs = await filterPools({ api, pairs: pairObject, createBalances }) const dailyVolume = createBalances() @@ -94,6 +126,10 @@ export const getUniV3LogAdapter: any = ({ factory, poolCreatedEvent = defaultPoo addOneToken({ chain, balances: dailyFees, token0, token1, amount0: log.amount0.toString() * fee, amount1: log.amount1.toString() * fee }) }) })) + + if (customLogic) { + return customLogic({ pairObject, dailyVolume, dailyFees, filteredPairs, fetchOptions }) + } return { dailyVolume, dailyFees } } return fetch @@ -103,12 +139,17 @@ type UniV2Config = { factory: string, fees?: number, swapEvent?: string, + stableFees?: number, + voter?: string, + maxPairSize?: number, + customLogic?: any, } type UniV3Config = { factory: string, poolCreatedEvent?: string, swapEvent?: string, + customLogic?: any, } export function uniV2Exports(config: IJSON) { @@ -131,4 +172,23 @@ export function uniV3Exports(config: IJSON) { } }) return { adapter: exportObject, version: 2 } as SimpleAdapter +} + + +export async function filterPools2({ fetchOptions, pairs, token0s, token1s, minUSDValue, maxPairSize }: any) { + const pairObject: IJSON = {} + pairs.forEach((pair: string, i: number) => { + pairObject[pair] = [token0s[i], token1s[i]] + }) + const res = await filterPools({ ...fetchOptions, pairs: pairObject, minUSDValue, maxPairSize }) + pairs = [] + token0s = [] + token1s = [] + Object.keys(res).forEach((pair: any) => { + pairs.push(pair) + const [token0, token1] = pairObject[pair] + token0s.push(token0) + token1s.push(token1) + }) + return { pairs, token0s, token1s, pairObject, } } \ No newline at end of file diff --git a/options/aevo/index.ts b/options/aevo/index.ts index a747307653..7e66b4ae80 100644 --- a/options/aevo/index.ts +++ b/options/aevo/index.ts @@ -1,6 +1,7 @@ import { SimpleAdapter } from "../../adapters/types"; import fetchURL from "../../utils/fetchURL"; import { CHAIN } from "../../helpers/chains"; +import { getTimestampAtStartOfNextDayUTC } from "../../utils/date"; interface IAevoVolumeResponse { daily_volume: string; @@ -27,7 +28,8 @@ export async function fetchAevoVolumeData( /** Timestamp representing the end of the 24 hour period */ timestamp: number ) { - const timestampInNanoSeconds = timestamp * 1e9 + const dayTimestamp = getTimestampAtStartOfNextDayUTC(timestamp); + const timestampInNanoSeconds = dayTimestamp * 1e9 const aevoVolumeData = await getAevoVolumeData(aevoVolumeEndpoint(timestampInNanoSeconds)); const dailyNotionalVolume = Number(aevoVolumeData.daily_volume).toFixed(2); diff --git a/options/arrow-markets/index.ts b/options/arrow-markets/index.ts new file mode 100644 index 0000000000..f3d67bf4b6 --- /dev/null +++ b/options/arrow-markets/index.ts @@ -0,0 +1,48 @@ +import { FetchOptions, SimpleAdapter } from "../../adapters/types"; +import fetchURL from "../../utils/fetchURL"; +import { CHAIN } from "../../helpers/chains"; + +interface ArrowMarketsVolumeResponse { + daily_notional_volume: string; + daily_premium_volume: string; + total_notional_volume: string; +} + +// endTime is in ms +export const arrowMarketsVolumeEndpoint = "https://api-rfq-testnet.prd.arrowmarkets.delivery/admin/volume" + +export const v2_adapter: SimpleAdapter = { + adapter: { + [CHAIN.AVAX]: { + fetch: fetchArrowMarketsVolumeData, + start: 1707350400 + }, + }, +}; + +export async function fetchArrowMarketsVolumeData( + /** Timestamp representing the end of the 24 hour period */ + timestamp: number, + _t: any, + options: FetchOptions +) { + const ArrowMarketsVolumeData = await getArrowMarketsVolumeData(arrowMarketsVolumeEndpoint, options.startOfDay); + + const dailyPremiumVolume = Number(ArrowMarketsVolumeData.daily_premium_volume).toFixed(2); + const dailyNotionalVolume = Number(ArrowMarketsVolumeData.daily_notional_volume).toFixed(2); + const totalNotionalVolume = Number(ArrowMarketsVolumeData.total_notional_volume).toFixed(2); + + return { + timestamp, + dailyNotionalVolume, + dailyPremiumVolume, + totalNotionalVolume, + }; +} + +async function getArrowMarketsVolumeData(endpoint: string, timestamp: number): Promise { + const url = `${endpoint}?timestamp=${timestamp}`; + return fetchURL(url) +} + +export default v2_adapter; diff --git a/options/ithaca/index.ts b/options/ithaca/index.ts new file mode 100644 index 0000000000..dea243eed5 --- /dev/null +++ b/options/ithaca/index.ts @@ -0,0 +1,56 @@ +import { SimpleAdapter } from "../../adapters/types"; +import fetchURL, { httpGet } from "../../utils/fetchURL"; +import { CHAIN } from "../../helpers/chains"; +import { Balances } from "@defillama/sdk"; +import { parseUnits } from "ethers"; + +const WETH_CONTRACT = '0x82aF49447D8a07e3bd95BD0d56f35241523fBab1'; +const USDC_CONTRACT = '0xaf88d065e77c8cC2239327C5EDb3A432268e5831'; + +interface IIthacaStatsResponse { + "response": { + "daily_fees": number, + "total_fees": number, + "daily_premium": number, + "total_premium": number, + "daily_volume_numeraire": number, + "daily_volume_underlier": number, + "total_volume_numeraire": number, + "total_volume_underlier": number + } +} + +const adapter: SimpleAdapter = { + adapter: { + [CHAIN.ARBITRUM]: { + fetch: fetchIthacaVolumeData, + start: 1713205800, + }, + }, +}; + +export async function fetchIthacaVolumeData( + timestamp: number +) { + const { response: ithacaStats } = await httpGet(`https://app.ithacaprotocol.io/api/v1/analytics/WETH/USDC/stats`) as IIthacaStatsResponse; + + const dailyNotionalVolume = new Balances({ chain: CHAIN.ARBITRUM }) + dailyNotionalVolume.addToken(USDC_CONTRACT, parseUnits(ithacaStats.daily_volume_numeraire.toFixed(6), 6)) + dailyNotionalVolume.addToken(WETH_CONTRACT, parseUnits(`${ithacaStats.daily_volume_underlier}`, 18)) + + const totalNotionalVolume = new Balances({ chain: CHAIN.ARBITRUM }) + totalNotionalVolume.addToken(USDC_CONTRACT, parseUnits(ithacaStats.total_volume_numeraire.toFixed(6), 6)) + totalNotionalVolume.addToken(WETH_CONTRACT, parseUnits(`${ithacaStats.total_volume_underlier}`, 18)) + + return { + timestamp, + dailyFees: ithacaStats.daily_fees, + totalFees: ithacaStats.total_fees, + dailyPremiumVolume: ithacaStats.daily_premium, + totalPremiumVolume: ithacaStats.total_premium, + dailyNotionalVolume, + totalNotionalVolume, + }; +} + +export default adapter; diff --git a/options/jaspervault/index.ts b/options/jaspervault/index.ts new file mode 100644 index 0000000000..1f3f4f915a --- /dev/null +++ b/options/jaspervault/index.ts @@ -0,0 +1,283 @@ +import { Adapter, FetchOptions, } from "../../adapters/types"; +import { CHAIN } from "../../helpers/chains"; +import { GraphQLClient, gql } from 'graphql-request'; +import { Balances } from "@defillama/sdk"; +import { Chain } from "@defillama/sdk/build/general"; +import BigNumber from "bignumber.js"; +import ADDRESSES from '../../helpers/coreAssets.json' +type TokenContracts = { + [key in Chain]: string[][]; +}; +const contracts: TokenContracts = { + [CHAIN.ARBITRUM]: [ + [ADDRESSES.arbitrum.WETH], + [ADDRESSES.arbitrum.WBTC], + [ADDRESSES.arbitrum.USDC], + [ADDRESSES.arbitrum.USDT], + ], +} +let tokenDecimals = {} +const subgraphEndpoint = "https://gateway-arbitrum.network.thegraph.com/api/7ca317c1d6347234f75513585a71157c/subgraphs/id/HkE4i846HyUEbmBg7cTawRqbTXQZnJ8VGwMfgVjdH19F" +const client = new GraphQLClient(subgraphEndpoint); + +function getDecimals(token_address: string) { + let decimalPlaces = 0; + if (token_address == "0xeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee") { + decimalPlaces = 18 + } + else { + if (tokenDecimals[token_address.toLowerCase()] != undefined) { + decimalPlaces = tokenDecimals[token_address.toLowerCase()] + } + else { + return 0; + } + } + return decimalPlaces; +} +// event logs can be found here: https://github.com/DefiLlama/dimension-adapters/pull/1492#issuecomment-2118112517 +function calculateNotionalVolume(balances: Balances, orders: any[]) { + for (const order of orders) { + let orderDetails = order.callOrder || order.putOrder; + if (!orderDetails) { + console.error("No order details found"); + continue; + } + //v1 orders + if (!orderDetails.quantity) { + if (order.callOrder) { + let decimals_strikeAsset: number = getDecimals(orderDetails.strikeAsset); + if (decimals_strikeAsset == 0) { + console.error("No decimals data found for strikeAsset"); + continue; + } + let decimals_underlyingAsset = getDecimals(orderDetails.underlyingAsset); + if (decimals_underlyingAsset == 0) { + console.error("No decimals data found for underlyingAsset"); + continue; + } + let notionalValue = new BigNumber(orderDetails.strikeAmount).dividedBy(new BigNumber(10).pow(decimals_strikeAsset)).multipliedBy(new BigNumber(orderDetails.underlyingAmount).dividedBy(new BigNumber(10).pow(decimals_underlyingAsset))) + notionalValue = notionalValue.decimalPlaces(Number(decimals_strikeAsset)).multipliedBy(new BigNumber(10).pow(decimals_strikeAsset)); + balances.add(orderDetails.strikeAsset, notionalValue); + //console.log(`notionalValue:${notionalValue} strikeAsset: ${orderDetails.strikeAsset}, strikeAmount : ${orderDetails.strikeAmount} underlyingAmount:${orderDetails.underlyingAmount},orderId: ${order.orderId} ,transactionHash: ${order.transactionHash} `) + } + else if (order.putOrder) { + balances.add(orderDetails.underlyingAsset, orderDetails.underlyingAmount) + } + } + //v2 orders + else { + if (order.callOrder) { + let decimals_strikeAsset: number = getDecimals(orderDetails.strikeAsset); + if (decimals_strikeAsset == 0) { + console.error("No decimals data found for strikeAsset"); + continue; + } + let notionalValue = new BigNumber(orderDetails.strikeAmount).dividedBy(new BigNumber(10).pow(decimals_strikeAsset)).multipliedBy(new BigNumber(orderDetails.quantity).dividedBy(new BigNumber(10).pow(18))) + notionalValue = notionalValue.decimalPlaces(Number(decimals_strikeAsset)).multipliedBy(new BigNumber(10).pow(decimals_strikeAsset)); + balances.add(orderDetails.strikeAsset, notionalValue); + //console.log(`notionalValue:${notionalValue} strikeAsset: ${orderDetails.strikeAsset}, strikeAmount : ${orderDetails.strikeAmount} quantity:${orderDetails.quantity},orderId: ${order.orderId} ,transactionHash: ${order.transactionHash} `) + } + else if (order.putOrder) { + let decimals_lockAsset: number = getDecimals(orderDetails.lockAsset); + if (decimals_lockAsset == 0) { + console.error("No decimals data found for lockAsset"); + continue; + } + let notionalValue = new BigNumber(orderDetails.lockAmount).dividedBy(new BigNumber(10).pow(decimals_lockAsset)).multipliedBy(new BigNumber(orderDetails.quantity).dividedBy(new BigNumber(10).pow(18))) + notionalValue = notionalValue.decimalPlaces(Number(decimals_lockAsset)).multipliedBy(new BigNumber(10).pow(decimals_lockAsset)); + balances.add(orderDetails.lockAsset, notionalValue); + //console.log(`notionalValue:${notionalValue} lockAsset: ${orderDetails.lockAsset}, lockAmount : ${orderDetails.lockAmount} quantity:${orderDetails.quantity},orderId: ${order.orderId} ,transactionHash: ${order.transactionHash} `) + } + + } + } +} + +function calculatePremiumVolume(balances: Balances, optionPremiums: any[]) { + for (const premium of optionPremiums) { + //The premium data for these orders during this period is incorrect, so we should ignore the premium data for this batch of orders. + if (premium.orderID <= 4309 || premium.orderID >= 4343) { + balances.add(premium.premiumAsset, premium.amount) + } + } +} + +async function fetchCallOrder(client: GraphQLClient, start: number, end: number | null, pageSize: number = 100) { + let skip = 0; + let allData = { callOrderEntities: [] }; + let hasMore = true; + while (hasMore) { + const query = gql` + { + callOrderEntities(where: { timestamp_gte: ${start}, timestamp_lte: ${end}}, first: ${pageSize}, skip: ${skip}) { + callOrder { + underlyingAsset + underlyingAmount + strikeAsset + strikeAmount + } + orderId + transactionHash + } + } + `; + const result = await client.request(query); + allData.callOrderEntities.push(...result.callOrderEntities as never[]); + skip += pageSize; + hasMore = result.callOrderEntities.length === pageSize; + } + return allData; +} +async function fetchCallOrderV2(client: GraphQLClient, start: number, end: number | null, pageSize: number = 100) { + let skip = 0; + let allData = { callOrderEntities: [] }; + let hasMore = true; + while (hasMore) { + const query = gql` + { + callOrderEntityV2S(where: { timestamp_gte: ${start}, timestamp_lte: ${end}}, first: ${pageSize}, skip: ${skip}) { + callOrder { + underlyingAsset + quantity + strikeAsset + strikeAmount + } + orderId + transactionHash + } + }` + const result = await client.request(query); + allData.callOrderEntities.push(...result.callOrderEntityV2S as never[]); + skip += pageSize; + hasMore = result.callOrderEntityV2S.length === pageSize; + } + return allData; +} +async function fetchPutOrder(client: GraphQLClient, start: number, end: number | null, pageSize: number = 100) { + let skip = 0; + let allData = { putOrderEntities: [] }; + let hasMore = true; + while (hasMore) { + const query = gql` + { + putOrderEntities(where: { timestamp_gte: ${start}, timestamp_lte: ${end}}, first: ${pageSize}, skip: ${skip}) { + putOrder { + underlyingAsset + underlyingAmount + strikeAsset + strikeAmount + } + orderId + transactionHash + } + }` + const result = await client.request(query); + allData.putOrderEntities.push(...result.putOrderEntities as never[]); + skip += pageSize; + hasMore = result.putOrderEntities.length === pageSize; + } + return allData; +} +async function fetchPutOrderV2(client: GraphQLClient, start: number, end: number | null, pageSize: number = 100) { + let skip = 0; + let allData = { putOrderEntities: [] }; + let hasMore = true; + while (hasMore) { + const query = gql` + { + putOrderEntityV2S(where: { timestamp_gte: ${start}, timestamp_lte: ${end}}, first: ${pageSize}, skip: ${skip}) { + putOrder { + underlyingAsset + lockAsset + lockAmount + quantity + strikeAsset + strikeAmount + } + orderId + transactionHash + } + }` + const result = await client.request(query); + allData.putOrderEntities.push(...result.putOrderEntityV2S as never[]); + skip += pageSize; + hasMore = result.putOrderEntityV2S.length === pageSize; + } + return allData; +} +async function fetchOptionPremiums(client: GraphQLClient, start: number, end: number | null, pageSize: number = 100) { + let skip = 0; + let allData = { optionPremiums: [] }; + let hasMore = true; + while (hasMore) { + const query = gql` + { + optionPremiums(where: { timestamp_gte: ${start}, timestamp_lte: ${end}}, first: ${pageSize}, skip: ${skip}) { + amount + premiumAsset + orderID + transactionHash + } + } + `; + const result = await client.request(query); + allData.optionPremiums.push(...result.optionPremiums as never[]); + skip += pageSize; + hasMore = result.optionPremiums.length === pageSize; + } + return allData; +} + +export async function fetchSubgraphData({ createBalances, startTimestamp, endTimestamp, chain, api }: FetchOptions) { + const now = endTimestamp; + const startOfDay = startTimestamp; + const tokens = contracts[chain].map(i => i[0]); + const decimals = await api.multiCall({ abi: 'erc20:decimals', calls: tokens }) + tokenDecimals = tokens.reduce((obj, token, index) => { + obj[token] = decimals[index]; + return obj; + }, {}); + const [ + dailyCallData, dailyCallDataV2, dailyPutData, dailyPutDataV2, dailyPremiumData, + // totalCallData, totalPutData, totalPremiumData + ] = await Promise.all([ + fetchCallOrder(client, startOfDay, now), + fetchCallOrderV2(client, startOfDay, now), + fetchPutOrder(client, startOfDay, now), + fetchPutOrderV2(client, startOfDay, now), + fetchOptionPremiums(client, startOfDay, now), + // fetchCallOrder(client, start, now), + // fetchPutOrder(client, start, now), + // fetchOptionPremiums(client, start, now) + ]); + const dailyNotionalVolume = createBalances() + const dailyPremiumVolume = createBalances() + // const totalNotionalVolume = createBalances() + // const totalPremiumVolume = createBalances() + + calculateNotionalVolume(dailyNotionalVolume, [...dailyCallData.callOrderEntities, ...dailyCallDataV2.callOrderEntities, ...dailyPutData.putOrderEntities, ...dailyPutDataV2.putOrderEntities]); + calculatePremiumVolume(dailyPremiumVolume, dailyPremiumData.optionPremiums); + // calculateNotionalVolume(totalNotionalVolume, [...totalCallData.callOrderEntities, ...totalPutData.putOrderEntities]); + // calculatePremiumVolume(totalPremiumVolume, totalPremiumData.optionPremiums); + + return { + dailyNotionalVolume, + dailyPremiumVolume, + // totalNotionalVolume, + // totalPremiumVolume, + } +} + +const start = 1715175000 + +const adapter: Adapter = { + version: 2, + adapter: { + [CHAIN.ARBITRUM]: { + fetch: fetchSubgraphData, + start: start, + }, + } +} +export default adapter; diff --git a/options/lyra-v2/index.ts b/options/lyra-v2/index.ts index 866c4f1e2a..d79dbd33f5 100644 --- a/options/lyra-v2/index.ts +++ b/options/lyra-v2/index.ts @@ -16,7 +16,7 @@ export const lyraVolumeEndpoint = (endTime: number) => { export const v2_adapter: SimpleAdapter = { adapter: { - [CHAIN.ETHEREUM]: { + [CHAIN.LYRA]: { fetch: fetchLyraVolumeData, start: 1702630075 }, diff --git a/options/lyra/index.ts b/options/lyra/index.ts index 26e5224d05..ade2020a01 100644 --- a/options/lyra/index.ts +++ b/options/lyra/index.ts @@ -14,6 +14,7 @@ const subgraph = getChainVolume({ }); const adapters: SimpleAdapter = { + version: 2, adapter: Object.keys(endpoints).reduce((acc, chain) => { return { ...acc, diff --git a/options/moby/index.ts b/options/moby/index.ts new file mode 100644 index 0000000000..055745f83d --- /dev/null +++ b/options/moby/index.ts @@ -0,0 +1,53 @@ +import { SimpleAdapter } from "../../adapters/types"; +import fetchURL from "../../utils/fetchURL"; +import { CHAIN } from "../../helpers/chains"; + +interface IMobyVolumeResponse { + daily_notional_volume: string; + daily_premium_volume: string; + total_notional_volume: string; + total_premium_volume: string; +} + +// endTime is in ms +export const mobyVolumeEndpoint = (endTime: number) => { + return `https://u63601xvgc.execute-api.ap-northeast-2.amazonaws.com/prod/getVolumeData?end_time=${endTime}`; +} + +export const moby_adapter: SimpleAdapter = { + adapter: { + [CHAIN.ARBITRUM]: { + fetch: fetchMobyVolumeData, + start: 1712102400 + }, + }, +}; + +export async function fetchMobyVolumeData( + /** Timestamp representing the end of the 24 hour period */ + timestamp: number +) { + let timestamp_in_ms = timestamp * 1000 + const mobyVolumeData = await getMobyVolumeData(mobyVolumeEndpoint(timestamp_in_ms)); + + const dailyNotionalVolume = Number(mobyVolumeData.daily_notional_volume).toFixed(2); + const dailyPremiumVolume = Number(mobyVolumeData.daily_premium_volume).toFixed(2); + const totalNotionalVolume = Number(mobyVolumeData.total_notional_volume).toFixed(2); + const totalPremiumVolume = Number(mobyVolumeData.total_premium_volume).toFixed(2); + + return { + timestamp, + dailyNotionalVolume, + dailyPremiumVolume, + totalNotionalVolume, + totalPremiumVolume, + }; +} + +async function getMobyVolumeData(endpoint: string): Promise { + const results = await fetchURL(endpoint) + + return results.result; +} + +export default moby_adapter; diff --git a/options/optionBlitz/index.ts b/options/optionBlitz/index.ts new file mode 100644 index 0000000000..5bde00e5af --- /dev/null +++ b/options/optionBlitz/index.ts @@ -0,0 +1,78 @@ +import ADDRESSES from "../../helpers/coreAssets.json"; +import { FetchResult, SimpleAdapter } from "../../adapters/types"; +import { CHAIN } from "../../helpers/chains"; +import { gql, request } from "graphql-request"; +import * as sdk from "@defillama/sdk"; +import { get } from "http"; +import { getCurrentUnixTimestamp, getTimestampAtStartOfDay } from "../../utils/date"; + +interface IDayDataGraph { + id: string; + volumeUsdc: string; +} +interface ITotalDataGraph { + id: string; + totalVolumeUsdc: string; + timestamp: string; +} + +const URL = sdk.graph.modifyEndpoint('5m8N5qAkDWTf2hhMFhJJJDsWWF5b9J7bzFbXwPnZHJQQ'); + +const fetch = async (timestamp: number): Promise => { + const dayTimestamp = getTimestampAtStartOfDay(timestamp); + const chain = CHAIN.ARBITRUM; + const balances = new sdk.Balances({ chain }); + const balances1 = new sdk.Balances({ chain }); + + const dayDataQuery = gql` + { + dayData(id: ${dayTimestamp * 1000}) { + id + volumeUsdc + } + }`; + + const totalDataQuery = gql` + { + totalDatas { + id + totalVolumeUsdc + timestamp + } + }` + + const dayDataResponse: IDayDataGraph = (await request(URL, dayDataQuery)).dayData; + const totalDataResponse: ITotalDataGraph[] = (await request(URL, totalDataQuery)).totalDatas; + + let dailyVolume = Number(0); + let totalVolume = Number(0); + + if (dayDataResponse) { + dailyVolume = Number(dayDataResponse.volumeUsdc) / 1000; + } + + if (totalDataResponse.length > 0) { + totalVolume = Number(totalDataResponse[0].totalVolumeUsdc) / 1000; + } + + balances.add(ADDRESSES.arbitrum.USDC_CIRCLE, dailyVolume); + balances1.add(ADDRESSES.arbitrum.USDC_CIRCLE, totalVolume); + + return { + timestamp: dayTimestamp, + dailyNotionalVolume: 0, + dailyPremiumVolume: await balances.getUSDString(), + totalNotionalVolume: 0, + totalPremiumVolume: await balances1.getUSDString(), + }; +}; + +const adapters: SimpleAdapter = { + adapter: { + [CHAIN.ARBITRUM]: { + fetch: fetch as any, + start: 194784191, + }, + }, +}; +export default adapters; diff --git a/options/opyn/index.ts b/options/opyn/index.ts index eab6ce4954..fa58a9496a 100644 --- a/options/opyn/index.ts +++ b/options/opyn/index.ts @@ -55,7 +55,7 @@ query trades($timestampFrom: Int!, $timestampTo: Int!) { ` const endpoints = { - [CHAIN.ETHEREUM]: "https://api.thegraph.com/subgraphs/name/opynfinance/gamma-mainnet", + [CHAIN.ETHEREUM]: sdk.graph.modifyEndpoint('6CYUucsekksXD3BRvwz9MPgLcytmrJEKFi9bhRT3trnt'), }; const fetch: Fetch = async (timestamp) => { diff --git a/options/pancakeswap-options/index.ts b/options/pancakeswap-options/index.ts new file mode 100644 index 0000000000..d144427c0b --- /dev/null +++ b/options/pancakeswap-options/index.ts @@ -0,0 +1,49 @@ +import request, { gql } from "graphql-request"; +import { CHAIN } from "../../helpers/chains"; +import { FetchOptions, SimpleAdapter } from "../../adapters/types"; + +const url: { [s: string]: string } = { + [CHAIN.ARBITRUM]: "https://api.0xgraph.xyz/api/public/e2146f32-5728-4755-b1d1-84d17708c119/subgraphs/dopex-v2-clamm-public/-/gn" +} + +const query = gql` + query getVolume($startTimestamp: BigInt!, $endTimestamp: BigInt!) { + optionMarketDailyStats(where: { startTimestamp_gte: $startTimestamp, startTimestamp_lte: $endTimestamp }) { + startTimestamp + volume + premium + fees + } + } +` +interface IData { + optionMarketDailyStats:Array<{ + startTimestamp: number; + volume: string; + premium: string; + fees: string; + }> +} +const fetchOptions = async (fetchOptions: FetchOptions): Promise => { + const today = fetchOptions.startOfDay; + const end = today + 86400; + const data: IData = await request(url[fetchOptions.chain], query, { startTimestamp: today, endTimestamp: end }); + const daily_premium = data.optionMarketDailyStats.reduce((acc, { premium }) => acc + Number(premium), 0); + const daily_volume = data.optionMarketDailyStats.reduce((acc, { volume }) => acc + Number(volume), 0); + return { + dailyNotionalVolume: daily_volume, + dailyPremiumVolume: daily_premium, + } +} + +const adapter: SimpleAdapter = { + version: 2, + adapter: { + [CHAIN.ARBITRUM]: { + fetch: fetchOptions, + start: 1699660800, + }, + } +} + +export default adapter; diff --git a/options/premia/index.ts b/options/premia/index.ts index 965db7ce59..e664006145 100644 --- a/options/premia/index.ts +++ b/options/premia/index.ts @@ -1,3 +1,4 @@ +import * as sdk from "@defillama/sdk"; import { CHAIN } from "../../helpers/chains" import { BreakdownAdapter, ChainEndpoints } from "../../adapters/types" @@ -6,13 +7,13 @@ import getV3Data from "./v3" const v2Endpoints: ChainEndpoints = { [CHAIN.ETHEREUM]: - "https://api.thegraph.com/subgraphs/name/premiafinance/premiav2", + sdk.graph.modifyEndpoint('CqWfkgRsJRrQ5vWq9tkEr68F5nvbAg63ati5SVJQLjK8'), [CHAIN.ARBITRUM]: - "https://api.thegraph.com/subgraphs/name/premiafinance/premia-arbitrum", + sdk.graph.modifyEndpoint('3o6rxHKuXZdy8jFifV99gMUe8FaVUL8w8bDTNdc4zyYg'), [CHAIN.FANTOM]: - "https://api.thegraph.com/subgraphs/name/premiafinance/premia-fantom", + sdk.graph.modifyEndpoint('5ahtXN7DVTwnPuDhWqgJWvEeAEP3JD7h2kD1Kpe67VuW'), [CHAIN.OPTIMISM]: - "https://api.thegraph.com/subgraphs/name/premiafinance/premia-optimism", + sdk.graph.modifyEndpoint('8wMexS8BB1cXWYu2V8cPHURGXSRGDBhshnU9nTiSkXQ7'), } const v2StartTimes: { [chain: string]: number } = { diff --git a/options/smilee-finance/index.ts b/options/smilee-finance/index.ts new file mode 100644 index 0000000000..779ec4cb99 --- /dev/null +++ b/options/smilee-finance/index.ts @@ -0,0 +1,85 @@ +import { gql, request } from "graphql-request"; +import { Fetch, FetchOptions, FetchResultOptions } from "../../adapters/types"; +import { CHAIN } from "../../helpers/chains"; +import * as sdk from "@defillama/sdk"; + +interface Trade { + notionalUp: string; + notionalDown: string; + premium: string; +} + +interface CumulativeData { + cumulativeVolume: string; + cumulativePremium: string; +} + +const BASE_TOKEN = "0xaf88d065e77c8cc2239327c5edb3a432268e5831"; +const SUBGRAPH_URL = "https://api.studio.thegraph.com/proxy/64770/smilee-finance/version/latest"; + +const tradeQuery = gql` + query trades($timestampFrom: Int!, $timestampTo: Int!) { + trades(where: {timestamp_gt: $timestampFrom, timestamp_lte: $timestampTo}) { + notionalUp + notionalDown + premium + } + }`; + +const cumulativeStatsQuery = gql` + query trades { + protocolStatistics { + cumulativeVolume + cumulativePremium + } + }`; + +const fetch: Fetch = async (timestamp, _: any, options: FetchOptions) => { + + const tradedNotional = new sdk.Balances({ chain: CHAIN.ARBITRUM, timestamp }); + const tradedPremium = new sdk.Balances({ chain: CHAIN.ARBITRUM, timestamp }); + // const totalTradedNotional = new sdk.Balances({ chain: CHAIN.ARBITRUM }); + // const totalTradedPremium = new sdk.Balances({ chain: CHAIN.ARBITRUM }); + + // Fetching daily trades + const tradeResponse = await request(SUBGRAPH_URL, tradeQuery, { + timestampFrom: options.fromTimestamp, + timestampTo: options.toTimestamp, + }) as { trades: Trade[] }; + + tradeResponse.trades + .filter((i) => Number(i.notionalUp)/1e6 < 10_000_000) + .filter((i) => Number(i.notionalDown)/1e6 < 10_000_000) + .filter((i) => Number(i.premium)/1e6 < 10_000_000) + .forEach((trade: Trade) => { + tradedNotional.add('usd', (Number(trade.notionalUp) + Number(trade.notionalDown)) / 1e6, { skipChain: true }); + tradedPremium.add('usd', Number(trade.premium) / 1e6, { skipChain: true }); + }); + + // Fetching cumulative statistics + // const statsResponse = await request(SUBGRAPH_URL, cumulativeStatsQuery) as { protocolStatistics: CumulativeData }; + // totalTradedNotional.add('usd', Number() / 1e6); + // totalTradedPremium.add('usd', Number(statsResponse.protocolStatistics.cumulativePremium) / 1e6); + + // Building fetch result + const fetchResult: FetchResultOptions = { + timestamp: options.toTimestamp, + dailyNotionalVolume: await tradedNotional.getUSDString(), + dailyPremiumVolume: await tradedPremium.getUSDString(), + // totalNotionalVolume: BigInt.(statsResponse.protocolStatistics.cumulativeVolume) / 1e6, + // totalPremiumVolume: Number(statsResponse.protocolStatistics.cumulativePremium) / 1e6 + }; + + return fetchResult; +}; + +const adapter = { + adapter: { + [CHAIN.ARBITRUM]: { + fetch, + start: 1710440552 + }, + } +}; + +export default adapter; diff --git a/options/thales/getChainData.ts b/options/thales/getChainData.ts index 340b8912e9..ca4a729c03 100644 --- a/options/thales/getChainData.ts +++ b/options/thales/getChainData.ts @@ -1,8 +1,9 @@ +import * as sdk from "@defillama/sdk"; import { request, gql } from "graphql-request"; export const MIN_TIMESTAMP = 1640217600; const SPORT_MIN_TIMESTAMP = 1659312000; -const SPORT_ENDPOINT = "https://api.thegraph.com/subgraphs/name/thales-markets/sport-markets-optimism"; +const SPORT_ENDPOINT = sdk.graph.modifyEndpoint('GNVg7vqPeoaqDARvssvwCUaLfizACsrmeFFCpZd4VBDq'); type Volume = { timestamp: number diff --git a/options/thales/index.ts b/options/thales/index.ts index 353385672a..cad31f745c 100644 --- a/options/thales/index.ts +++ b/options/thales/index.ts @@ -1,12 +1,13 @@ +import * as sdk from "@defillama/sdk"; import { ChainEndpoints, SimpleAdapter } from "../../adapters/types"; import { CHAIN } from "../../helpers/chains"; import getChainData, { MIN_TIMESTAMP } from "./getChainData"; const endpoints: ChainEndpoints = { - [CHAIN.OPTIMISM]: "https://api.thegraph.com/subgraphs/name/thales-markets/thales-markets", - [CHAIN.POLYGON]: "https://api.thegraph.com/subgraphs/name/thales-markets/thales-polygon", - [CHAIN.ARBITRUM]: "https://api.thegraph.com/subgraphs/name/thales-markets/thales-arbitrum", - [CHAIN.BSC]: "https://api.thegraph.com/subgraphs/name/thales-markets/thales-bsc", + [CHAIN.OPTIMISM]: sdk.graph.modifyEndpoint('GADfDRePpbqyjK2Y3JkQTBPBVQj98imhgKo7oRWW7RqQ'), + [CHAIN.POLYGON]: sdk.graph.modifyEndpoint('G7wi71W3PdtYYidKy5pEmJvJ1Xpop25ogynstRjPdyPG'), + [CHAIN.ARBITRUM]: sdk.graph.modifyEndpoint('FZH9ySiLCdqKrwefaospe6seSqV1ZoW4FvPQUGP7MFob'), + [CHAIN.BSC]: sdk.graph.modifyEndpoint('FrSU8JkxyoGiLyj1b5X8jATrNBYPts7h64rd5HZSCqAb'), }; const adapter: SimpleAdapter = { diff --git a/options/ton-hedge.ts b/options/ton-hedge.ts new file mode 100644 index 0000000000..72a5f4cbef --- /dev/null +++ b/options/ton-hedge.ts @@ -0,0 +1,29 @@ +// import { Chain } from "@defillama/sdk/build/general"; +import { FetchOptions, SimpleAdapter } from "../adapters/types"; +import { CHAIN } from "../helpers/chains"; +import fetchURL from "../utils/fetchURL"; + + +const adapter: SimpleAdapter = { + adapter: { + [CHAIN.TON]: { + fetch: async (timestamp: number, _t: any, options: FetchOptions) => { + const result = await fetchURL( + `https://tonhedge.com/api/metrics?timestamp=${options.startOfDay * 1000}` + ) + return { + ...result, + timestamp + } + }, + start: 1719847914, + meta: { + methodology: { + Volume: "Total costs + payouts", + } + } + }, + }, +}; + +export default adapter; diff --git a/options/typus/getChainData.ts b/options/typus/getChainData.ts index 467782e345..c5eaf4ed6d 100644 --- a/options/typus/getChainData.ts +++ b/options/typus/getChainData.ts @@ -1,152 +1,47 @@ -import * as sdk from "@defillama/sdk"; -import { httpPost } from "../../utils/fetchURL"; +import { queryEvents } from "../../helpers/sui"; +import { FetchOptions, FetchResultV2 } from "../../adapters/types"; -interface ChainData { - totalPremiumVolume: { [key: string]: number }; - dailyPremiumVolume: { [key: string]: number }; - totalNotionalVolume: { [key: string]: number }; - dailyNotionalVolume: { [key: string]: number }; - timestamp: string; -} async function getChainData( - timestamp: string, - backFillTimestamp: string | undefined = undefined -): Promise { - let end_timestamp = Number(timestamp); - let start_timestamp = end_timestamp - 24 * 60 * 60; - - var response = await httpPost( - "https://fullnode.mainnet.sui.io:443", - { - jsonrpc: "2.0", - id: 1, - method: "suix_queryEvents", - params: { - query: { - MoveEventType: - "0x321848bf1ae327a9e022ccb3701940191e02fa193ab160d9c0e49cd3c003de3a::typus_dov_single::DeliveryEvent", - }, - descending_order: true, - }, - }, - { - headers: { - "Content-Type": "application/json", - }, - } - ); - - var data = response.result.data; - - if (backFillTimestamp) { - while (response.result.hasNextPage) { - response = await httpPost( - "https://fullnode.mainnet.sui.io:443", - { - jsonrpc: "2.0", - id: 1, - method: "suix_queryEvents", - params: { - query: { - MoveEventType: - "0x321848bf1ae327a9e022ccb3701940191e02fa193ab160d9c0e49cd3c003de3a::typus_dov_single::DeliveryEvent", - }, - descending_order: true, - cursor: response.result.nextCursor, - }, - }, - { - headers: { - "Content-Type": "application/json", - }, - } - ); - data = data.concat(response.result.data); - - const timestamp = Number(data.at(-1).timestampMs) / 1000; - if (timestamp <= Number(backFillTimestamp)) { - break; - } - } - } - - const acc: ChainData = { - timestamp, - totalNotionalVolume: {}, - dailyNotionalVolume: {}, - totalPremiumVolume: {}, - dailyPremiumVolume: {}, - }; - - for (const curr of data) { - const parsedJson = curr.parsedJson; - - let o_token_name: string; - let dailyNotionalVolume: number; - + options: FetchOptions, +): Promise { + const events = await queryEvents({eventType:"0x321848bf1ae327a9e022ccb3701940191e02fa193ab160d9c0e49cd3c003de3a::typus_dov_single::DeliveryEvent", options}) + const dailyNotionalVolume = options.createBalances(); + const dailyPremiumVolume = options.createBalances(); + for (const curr of events) { + const parsedJson = curr; if (parsedJson.o_token.name.endsWith("MFUD")) { - o_token_name = "sui:0x76cb819b01abed502bee8a702b4c2d547532c12f25001c9dea795a5e631c26f1::fud::FUD"; - dailyNotionalVolume = Number(parsedJson.delivery_size) * 10 ** 5; + const o_token_name = "0x76cb819b01abed502bee8a702b4c2d547532c12f25001c9dea795a5e631c26f1::fud::FUD"; + dailyNotionalVolume.add(o_token_name, Number(parsedJson.delivery_size) * 10 ** 5); } else { - o_token_name = "sui:0x" + parsedJson.o_token.name; - dailyNotionalVolume = Number(parsedJson.delivery_size); + const o_token_name = "0x" + parsedJson.o_token.name; + dailyNotionalVolume.add(o_token_name, Number(parsedJson.delivery_size)); } - let b_token_name: string; - let dailyPremiumVolume: number; - if (parsedJson.b_token.name.endsWith("MFUD")) { - b_token_name = "sui:0x76cb819b01abed502bee8a702b4c2d547532c12f25001c9dea795a5e631c26f1::fud::FUD"; - dailyPremiumVolume = + const b_token_name = "0x76cb819b01abed502bee8a702b4c2d547532c12f25001c9dea795a5e631c26f1::fud::FUD"; + const _dailyPremiumVolume = (Number(parsedJson.bidder_bid_value) + Number(parsedJson.bidder_fee) + Number(parsedJson.incentive_bid_value) + Number(parsedJson.incentive_fee)) * 10 ** 5; + dailyPremiumVolume.add(b_token_name, _dailyPremiumVolume); } else { - b_token_name = "sui:0x" + parsedJson.b_token.name; - dailyPremiumVolume = + const b_token_name = "0x" + parsedJson.b_token.name; + const _dailyPremiumVolume = Number(parsedJson.bidder_bid_value) + Number(parsedJson.bidder_fee) + Number(parsedJson.incentive_bid_value) + Number(parsedJson.incentive_fee); - } - - if (o_token_name in acc.totalNotionalVolume) { - acc.totalNotionalVolume[o_token_name] += dailyNotionalVolume; - } else { - acc.totalNotionalVolume[o_token_name] = dailyNotionalVolume; - } - - if (b_token_name in acc.totalPremiumVolume) { - acc.totalPremiumVolume[b_token_name] += dailyPremiumVolume; - } else { - acc.totalPremiumVolume[b_token_name] = dailyPremiumVolume; - } - - const timestamp = Number(curr.timestampMs) / 1000; - if (timestamp > start_timestamp && timestamp <= end_timestamp) { - if (o_token_name in acc.dailyNotionalVolume) { - acc.dailyNotionalVolume[o_token_name] += dailyNotionalVolume; - } else { - acc.dailyNotionalVolume[o_token_name] = dailyNotionalVolume; - } - - if (b_token_name in acc.dailyPremiumVolume) { - acc.dailyPremiumVolume[b_token_name] += dailyPremiumVolume; - } else { - acc.dailyPremiumVolume[b_token_name] = dailyPremiumVolume; - } + dailyPremiumVolume.add(b_token_name, _dailyPremiumVolume); } } - acc.dailyNotionalVolume = (await sdk.Balances.getUSDString(acc.dailyNotionalVolume, end_timestamp)) as any; - acc.dailyPremiumVolume = (await sdk.Balances.getUSDString(acc.dailyPremiumVolume, end_timestamp)) as any; - acc.totalPremiumVolume = (await sdk.Balances.getUSDString(acc.totalPremiumVolume, end_timestamp)) as any; - acc.totalNotionalVolume = (await sdk.Balances.getUSDString(acc.totalNotionalVolume, end_timestamp)) as any; - - return acc; + return { + dailyNotionalVolume, + dailyPremiumVolume, + }; } export default getChainData; diff --git a/options/typus/index.ts b/options/typus/index.ts index 84820c806b..1db21660ff 100644 --- a/options/typus/index.ts +++ b/options/typus/index.ts @@ -1,24 +1,15 @@ import { CHAIN } from "../../helpers/chains"; -import { SimpleAdapter, ChainEndpoints } from "../../adapters/types"; +import { SimpleAdapter } from "../../adapters/types"; import getChainData from "./getChainData"; -const endpoints: ChainEndpoints = { - [CHAIN.SUI]: - "https://us-central1-aqueous-freedom-378103.cloudfunctions.net/mongodb", -}; - const adapter: SimpleAdapter = { - adapter: Object.keys(endpoints).reduce((acc, chain) => { - return { - ...acc, - [chain]: { - fetch: async (ts: string) => await getChainData(ts), - start: 1697700660, - customBackfill: async (ts: string) => - await getChainData(ts, "1697700660"), - }, - }; - }, {}), -}; + adapter: { + [CHAIN.SUI]: { + fetch: getChainData, + start: 1697700660, + } + }, + version: 2, +} export default adapter; diff --git a/options/umoja/constants.ts b/options/umoja/constants.ts new file mode 100644 index 0000000000..9b54e28e78 --- /dev/null +++ b/options/umoja/constants.ts @@ -0,0 +1,9 @@ +const get_timestamp = (date: string) => new Date(date).getTime() / 1000; + +export const min_start_date = "2024-02-05"; +export const base_endpoint = "https://api.protocol.umoja.xyz"; +export const hallmarks: [[number, string]] = [[get_timestamp("2024-02-05"), "Beta Launch"]]; +export const methodology = { + Revenue: "All revenue generated comes from user fees.", + Fees: "All fees comes from synthetic option activation, which are about 1% of the notional value of option.", +}; diff --git a/options/umoja/index.ts b/options/umoja/index.ts new file mode 100644 index 0000000000..5f728109f0 --- /dev/null +++ b/options/umoja/index.ts @@ -0,0 +1,34 @@ +import * as Fetch from "../../utils/fetchURL"; +import * as Chains from "../../helpers/chains"; +import * as Adapters from "../../adapters/types"; +import * as C from "./constants"; + +const get_data = async (timestamp: number) => { + const url = `${C.base_endpoint}/tokens/performance/d-llama`; + const date = new Date(timestamp * 1000).toISOString(); + const params = { date: date, range: 24 * 60 * 60, token: "*" }; + const result = await Fetch.httpGet(url, { params: params }, { withMetadata: false }); + + return { + timestamp: timestamp, + totalPremiumVolume: result.fees_to_date, + totalNotionalVolume: result.notional_to_date, + dailyPremiumVolume: result.fees, + dailyNotionalVolume: result.notional, + }; +}; + +const adapter: Adapters.SimpleAdapter = { + adapter: { + [Chains.ARBITRUM]: { + fetch: get_data, + start: async () => new Date(C.min_start_date).getTime() / 1000, + meta: { + methodology: C.methodology, + hallmarks: C.hallmarks, + }, + }, + }, +}; + +export default adapter; diff --git a/package-lock.json b/package-lock.json index 8daf9bca71..3e87d23b18 100644 --- a/package-lock.json +++ b/package-lock.json @@ -33,734 +33,886 @@ } }, "node_modules/@adraffy/ens-normalize": { - "version": "1.10.0", - "resolved": "https://registry.npmjs.org/@adraffy/ens-normalize/-/ens-normalize-1.10.0.tgz", - "integrity": "sha512-nA9XHtlAkYfJxY7bce8DcN7eKxWWCWkU+1GR9d+U6MbNpfwQp8TI7vqOsBsMcHoT4mBu2kypKoSKnghEzOOq5Q==" + "version": "1.10.1", + "resolved": "https://registry.npmjs.org/@adraffy/ens-normalize/-/ens-normalize-1.10.1.tgz", + "integrity": "sha512-96Z2IP3mYmF1Xg2cDm8f1gWGf/HUVedQ3FMifV4kG/PQ4yEP51xDtRAEfhVNt5f/uzpNkZHwWQuUcu6D6K+Ekw==", + "license": "MIT" }, "node_modules/@aws-crypto/crc32": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/@aws-crypto/crc32/-/crc32-3.0.0.tgz", - "integrity": "sha512-IzSgsrxUcsrejQbPVilIKy16kAT52EwB6zSaI+M3xxIhKh5+aldEyvI+z6erM7TCLB2BJsFrtHjp6/4/sr+3dA==", + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/@aws-crypto/crc32/-/crc32-5.2.0.tgz", + "integrity": "sha512-nLbCWqQNgUiwwtFsen1AdzAtvuLRsQS8rYgMuxCrdKf9kOssamGLuPwyTY9wyYblNr9+1XM8v6zoDTPPSIeANg==", + "license": "Apache-2.0", "dependencies": { - "@aws-crypto/util": "^3.0.0", + "@aws-crypto/util": "^5.2.0", "@aws-sdk/types": "^3.222.0", - "tslib": "^1.11.1" + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" } }, - "node_modules/@aws-crypto/crc32/node_modules/tslib": { - "version": "1.14.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", - "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==" - }, "node_modules/@aws-crypto/crc32c": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/@aws-crypto/crc32c/-/crc32c-3.0.0.tgz", - "integrity": "sha512-ENNPPManmnVJ4BTXlOjAgD7URidbAznURqD0KvfREyc4o20DPYdEldU1f5cQ7Jbj0CJJSPaMIk/9ZshdB3210w==", + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/@aws-crypto/crc32c/-/crc32c-5.2.0.tgz", + "integrity": "sha512-+iWb8qaHLYKrNvGRbiYRHSdKRWhto5XlZUEBwDjYNf+ly5SVYG6zEoYIdxvf5R3zyeP16w4PLBn3rH1xc74Rag==", + "license": "Apache-2.0", "dependencies": { - "@aws-crypto/util": "^3.0.0", + "@aws-crypto/util": "^5.2.0", "@aws-sdk/types": "^3.222.0", - "tslib": "^1.11.1" + "tslib": "^2.6.2" } }, - "node_modules/@aws-crypto/crc32c/node_modules/tslib": { - "version": "1.14.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", - "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==" - }, - "node_modules/@aws-crypto/ie11-detection": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/@aws-crypto/ie11-detection/-/ie11-detection-3.0.0.tgz", - "integrity": "sha512-341lBBkiY1DfDNKai/wXM3aujNBkXR7tq1URPQDL9wi3AUbI80NR74uF1TXHMm7po1AcnFk8iu2S2IeU/+/A+Q==", + "node_modules/@aws-crypto/sha1-browser": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/@aws-crypto/sha1-browser/-/sha1-browser-5.2.0.tgz", + "integrity": "sha512-OH6lveCFfcDjX4dbAvCFSYUjJZjDr/3XJ3xHtjn3Oj5b9RjojQo8npoLeA/bNwkOkrSQ0wgrHzXk4tDRxGKJeg==", + "license": "Apache-2.0", "dependencies": { - "tslib": "^1.11.1" + "@aws-crypto/supports-web-crypto": "^5.2.0", + "@aws-crypto/util": "^5.2.0", + "@aws-sdk/types": "^3.222.0", + "@aws-sdk/util-locate-window": "^3.0.0", + "@smithy/util-utf8": "^2.0.0", + "tslib": "^2.6.2" } }, - "node_modules/@aws-crypto/ie11-detection/node_modules/tslib": { - "version": "1.14.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", - "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==" + "node_modules/@aws-crypto/sha1-browser/node_modules/@smithy/is-array-buffer": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/@smithy/is-array-buffer/-/is-array-buffer-2.2.0.tgz", + "integrity": "sha512-GGP3O9QFD24uGeAXYUjwSTXARoqpZykHadOmA8G5vfJPK0/DC67qa//0qvqrJzL1xc8WQWX7/yc7fwudjPHPhA==", + "license": "Apache-2.0", + "dependencies": { + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=14.0.0" + } }, - "node_modules/@aws-crypto/sha1-browser": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/@aws-crypto/sha1-browser/-/sha1-browser-3.0.0.tgz", - "integrity": "sha512-NJth5c997GLHs6nOYTzFKTbYdMNA6/1XlKVgnZoaZcQ7z7UJlOgj2JdbHE8tiYLS3fzXNCguct77SPGat2raSw==", + "node_modules/@aws-crypto/sha1-browser/node_modules/@smithy/util-buffer-from": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/@smithy/util-buffer-from/-/util-buffer-from-2.2.0.tgz", + "integrity": "sha512-IJdWBbTcMQ6DA0gdNhh/BwrLkDR+ADW5Kr1aZmd4k3DIF6ezMV4R2NIAmT08wQJ3yUK82thHWmC/TnK/wpMMIA==", + "license": "Apache-2.0", "dependencies": { - "@aws-crypto/ie11-detection": "^3.0.0", - "@aws-crypto/supports-web-crypto": "^3.0.0", - "@aws-crypto/util": "^3.0.0", - "@aws-sdk/types": "^3.222.0", - "@aws-sdk/util-locate-window": "^3.0.0", - "@aws-sdk/util-utf8-browser": "^3.0.0", - "tslib": "^1.11.1" + "@smithy/is-array-buffer": "^2.2.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=14.0.0" } }, - "node_modules/@aws-crypto/sha1-browser/node_modules/tslib": { - "version": "1.14.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", - "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==" + "node_modules/@aws-crypto/sha1-browser/node_modules/@smithy/util-utf8": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/@smithy/util-utf8/-/util-utf8-2.3.0.tgz", + "integrity": "sha512-R8Rdn8Hy72KKcebgLiv8jQcQkXoLMOGGv5uI1/k0l+snqkOzQ1R0ChUBCxWMlBsFMekWjq0wRudIweFs7sKT5A==", + "license": "Apache-2.0", + "dependencies": { + "@smithy/util-buffer-from": "^2.2.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=14.0.0" + } }, "node_modules/@aws-crypto/sha256-browser": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/@aws-crypto/sha256-browser/-/sha256-browser-3.0.0.tgz", - "integrity": "sha512-8VLmW2B+gjFbU5uMeqtQM6Nj0/F1bro80xQXCW6CQBWgosFWXTx77aeOF5CAIAmbOK64SdMBJdNr6J41yP5mvQ==", + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/@aws-crypto/sha256-browser/-/sha256-browser-5.2.0.tgz", + "integrity": "sha512-AXfN/lGotSQwu6HNcEsIASo7kWXZ5HYWvfOmSNKDsEqC4OashTp8alTmaz+F7TC2L083SFv5RdB+qU3Vs1kZqw==", + "license": "Apache-2.0", "dependencies": { - "@aws-crypto/ie11-detection": "^3.0.0", - "@aws-crypto/sha256-js": "^3.0.0", - "@aws-crypto/supports-web-crypto": "^3.0.0", - "@aws-crypto/util": "^3.0.0", + "@aws-crypto/sha256-js": "^5.2.0", + "@aws-crypto/supports-web-crypto": "^5.2.0", + "@aws-crypto/util": "^5.2.0", "@aws-sdk/types": "^3.222.0", "@aws-sdk/util-locate-window": "^3.0.0", - "@aws-sdk/util-utf8-browser": "^3.0.0", - "tslib": "^1.11.1" + "@smithy/util-utf8": "^2.0.0", + "tslib": "^2.6.2" } }, - "node_modules/@aws-crypto/sha256-browser/node_modules/tslib": { - "version": "1.14.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", - "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==" + "node_modules/@aws-crypto/sha256-browser/node_modules/@smithy/is-array-buffer": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/@smithy/is-array-buffer/-/is-array-buffer-2.2.0.tgz", + "integrity": "sha512-GGP3O9QFD24uGeAXYUjwSTXARoqpZykHadOmA8G5vfJPK0/DC67qa//0qvqrJzL1xc8WQWX7/yc7fwudjPHPhA==", + "license": "Apache-2.0", + "dependencies": { + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@aws-crypto/sha256-browser/node_modules/@smithy/util-buffer-from": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/@smithy/util-buffer-from/-/util-buffer-from-2.2.0.tgz", + "integrity": "sha512-IJdWBbTcMQ6DA0gdNhh/BwrLkDR+ADW5Kr1aZmd4k3DIF6ezMV4R2NIAmT08wQJ3yUK82thHWmC/TnK/wpMMIA==", + "license": "Apache-2.0", + "dependencies": { + "@smithy/is-array-buffer": "^2.2.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@aws-crypto/sha256-browser/node_modules/@smithy/util-utf8": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/@smithy/util-utf8/-/util-utf8-2.3.0.tgz", + "integrity": "sha512-R8Rdn8Hy72KKcebgLiv8jQcQkXoLMOGGv5uI1/k0l+snqkOzQ1R0ChUBCxWMlBsFMekWjq0wRudIweFs7sKT5A==", + "license": "Apache-2.0", + "dependencies": { + "@smithy/util-buffer-from": "^2.2.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=14.0.0" + } }, "node_modules/@aws-crypto/sha256-js": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/@aws-crypto/sha256-js/-/sha256-js-3.0.0.tgz", - "integrity": "sha512-PnNN7os0+yd1XvXAy23CFOmTbMaDxgxXtTKHybrJ39Y8kGzBATgBFibWJKH6BhytLI/Zyszs87xCOBNyBig6vQ==", + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/@aws-crypto/sha256-js/-/sha256-js-5.2.0.tgz", + "integrity": "sha512-FFQQyu7edu4ufvIZ+OadFpHHOt+eSTBaYaki44c+akjg7qZg9oOQeLlk77F6tSYqjDAFClrHJk9tMf0HdVyOvA==", + "license": "Apache-2.0", "dependencies": { - "@aws-crypto/util": "^3.0.0", + "@aws-crypto/util": "^5.2.0", "@aws-sdk/types": "^3.222.0", - "tslib": "^1.11.1" + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" } }, - "node_modules/@aws-crypto/sha256-js/node_modules/tslib": { - "version": "1.14.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", - "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==" - }, "node_modules/@aws-crypto/supports-web-crypto": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/@aws-crypto/supports-web-crypto/-/supports-web-crypto-3.0.0.tgz", - "integrity": "sha512-06hBdMwUAb2WFTuGG73LSC0wfPu93xWwo5vL2et9eymgmu3Id5vFAHBbajVWiGhPO37qcsdCap/FqXvJGJWPIg==", + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/@aws-crypto/supports-web-crypto/-/supports-web-crypto-5.2.0.tgz", + "integrity": "sha512-iAvUotm021kM33eCdNfwIN//F77/IADDSs58i+MDaOqFrVjZo9bAal0NK7HurRuWLLpF1iLX7gbWrjHjeo+YFg==", + "license": "Apache-2.0", "dependencies": { - "tslib": "^1.11.1" + "tslib": "^2.6.2" } }, - "node_modules/@aws-crypto/supports-web-crypto/node_modules/tslib": { - "version": "1.14.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", - "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==" - }, "node_modules/@aws-crypto/util": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/@aws-crypto/util/-/util-3.0.0.tgz", - "integrity": "sha512-2OJlpeJpCR48CC8r+uKVChzs9Iungj9wkZrl8Z041DWEWvyIHILYKCPNzJghKsivj+S3mLo6BVc7mBNzdxA46w==", + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/@aws-crypto/util/-/util-5.2.0.tgz", + "integrity": "sha512-4RkU9EsI6ZpBve5fseQlGNUWKMa1RLPQ1dnjnQoe07ldfIzcsGb5hC5W0Dm7u423KWzawlrpbjXBrXCEv9zazQ==", + "license": "Apache-2.0", "dependencies": { "@aws-sdk/types": "^3.222.0", - "@aws-sdk/util-utf8-browser": "^3.0.0", - "tslib": "^1.11.1" + "@smithy/util-utf8": "^2.0.0", + "tslib": "^2.6.2" } }, - "node_modules/@aws-crypto/util/node_modules/tslib": { - "version": "1.14.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", - "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==" - }, - "node_modules/@aws-sdk/client-s3": { - "version": "3.499.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/client-s3/-/client-s3-3.499.0.tgz", - "integrity": "sha512-4ssQqde/iY5fTJbWuFPzPuECtihdCAA9tfluv6fXYCJS3wMLf9x21qp6b7fIbUf6vjOJ2edmYd+DXk+0CMnTFg==", - "dependencies": { - "@aws-crypto/sha1-browser": "3.0.0", - "@aws-crypto/sha256-browser": "3.0.0", - "@aws-crypto/sha256-js": "3.0.0", - "@aws-sdk/client-sts": "3.499.0", - "@aws-sdk/core": "3.496.0", - "@aws-sdk/credential-provider-node": "3.499.0", - "@aws-sdk/middleware-bucket-endpoint": "3.496.0", - "@aws-sdk/middleware-expect-continue": "3.496.0", - "@aws-sdk/middleware-flexible-checksums": "3.496.0", - "@aws-sdk/middleware-host-header": "3.496.0", - "@aws-sdk/middleware-location-constraint": "3.496.0", - "@aws-sdk/middleware-logger": "3.496.0", - "@aws-sdk/middleware-recursion-detection": "3.496.0", - "@aws-sdk/middleware-sdk-s3": "3.499.0", - "@aws-sdk/middleware-signing": "3.496.0", - "@aws-sdk/middleware-ssec": "3.498.0", - "@aws-sdk/middleware-user-agent": "3.496.0", - "@aws-sdk/region-config-resolver": "3.496.0", - "@aws-sdk/signature-v4-multi-region": "3.499.0", - "@aws-sdk/types": "3.496.0", - "@aws-sdk/util-endpoints": "3.496.0", - "@aws-sdk/util-user-agent-browser": "3.496.0", - "@aws-sdk/util-user-agent-node": "3.496.0", - "@aws-sdk/xml-builder": "3.496.0", - "@smithy/config-resolver": "^2.1.1", - "@smithy/core": "^1.3.1", - "@smithy/eventstream-serde-browser": "^2.1.1", - "@smithy/eventstream-serde-config-resolver": "^2.1.1", - "@smithy/eventstream-serde-node": "^2.1.1", - "@smithy/fetch-http-handler": "^2.4.1", - "@smithy/hash-blob-browser": "^2.1.1", - "@smithy/hash-node": "^2.1.1", - "@smithy/hash-stream-node": "^2.1.1", - "@smithy/invalid-dependency": "^2.1.1", - "@smithy/md5-js": "^2.1.1", - "@smithy/middleware-content-length": "^2.1.1", - "@smithy/middleware-endpoint": "^2.4.1", - "@smithy/middleware-retry": "^2.1.1", - "@smithy/middleware-serde": "^2.1.1", - "@smithy/middleware-stack": "^2.1.1", - "@smithy/node-config-provider": "^2.2.1", - "@smithy/node-http-handler": "^2.3.1", - "@smithy/protocol-http": "^3.1.1", - "@smithy/smithy-client": "^2.3.1", - "@smithy/types": "^2.9.1", - "@smithy/url-parser": "^2.1.1", - "@smithy/util-base64": "^2.1.1", - "@smithy/util-body-length-browser": "^2.1.1", - "@smithy/util-body-length-node": "^2.2.1", - "@smithy/util-defaults-mode-browser": "^2.1.1", - "@smithy/util-defaults-mode-node": "^2.1.1", - "@smithy/util-endpoints": "^1.1.1", - "@smithy/util-retry": "^2.1.1", - "@smithy/util-stream": "^2.1.1", - "@smithy/util-utf8": "^2.1.1", - "@smithy/util-waiter": "^2.1.1", - "fast-xml-parser": "4.2.5", - "tslib": "^2.5.0" + "node_modules/@aws-crypto/util/node_modules/@smithy/is-array-buffer": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/@smithy/is-array-buffer/-/is-array-buffer-2.2.0.tgz", + "integrity": "sha512-GGP3O9QFD24uGeAXYUjwSTXARoqpZykHadOmA8G5vfJPK0/DC67qa//0qvqrJzL1xc8WQWX7/yc7fwudjPHPhA==", + "license": "Apache-2.0", + "dependencies": { + "tslib": "^2.6.2" }, "engines": { "node": ">=14.0.0" } }, - "node_modules/@aws-sdk/client-sso": { - "version": "3.496.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/client-sso/-/client-sso-3.496.0.tgz", - "integrity": "sha512-fuaMuxKg7CMUsP9l3kxYWCOxFsBjdA0xj5nlikaDm1661/gB4KkAiGqRY8LsQkpNXvXU8Nj+f7oCFADFyGYzyw==", - "dependencies": { - "@aws-crypto/sha256-browser": "3.0.0", - "@aws-crypto/sha256-js": "3.0.0", - "@aws-sdk/core": "3.496.0", - "@aws-sdk/middleware-host-header": "3.496.0", - "@aws-sdk/middleware-logger": "3.496.0", - "@aws-sdk/middleware-recursion-detection": "3.496.0", - "@aws-sdk/middleware-user-agent": "3.496.0", - "@aws-sdk/region-config-resolver": "3.496.0", - "@aws-sdk/types": "3.496.0", - "@aws-sdk/util-endpoints": "3.496.0", - "@aws-sdk/util-user-agent-browser": "3.496.0", - "@aws-sdk/util-user-agent-node": "3.496.0", - "@smithy/config-resolver": "^2.1.1", - "@smithy/core": "^1.3.1", - "@smithy/fetch-http-handler": "^2.4.1", - "@smithy/hash-node": "^2.1.1", - "@smithy/invalid-dependency": "^2.1.1", - "@smithy/middleware-content-length": "^2.1.1", - "@smithy/middleware-endpoint": "^2.4.1", - "@smithy/middleware-retry": "^2.1.1", - "@smithy/middleware-serde": "^2.1.1", - "@smithy/middleware-stack": "^2.1.1", - "@smithy/node-config-provider": "^2.2.1", - "@smithy/node-http-handler": "^2.3.1", - "@smithy/protocol-http": "^3.1.1", - "@smithy/smithy-client": "^2.3.1", - "@smithy/types": "^2.9.1", - "@smithy/url-parser": "^2.1.1", - "@smithy/util-base64": "^2.1.1", - "@smithy/util-body-length-browser": "^2.1.1", - "@smithy/util-body-length-node": "^2.2.1", - "@smithy/util-defaults-mode-browser": "^2.1.1", - "@smithy/util-defaults-mode-node": "^2.1.1", - "@smithy/util-endpoints": "^1.1.1", - "@smithy/util-retry": "^2.1.1", - "@smithy/util-utf8": "^2.1.1", - "tslib": "^2.5.0" + "node_modules/@aws-crypto/util/node_modules/@smithy/util-buffer-from": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/@smithy/util-buffer-from/-/util-buffer-from-2.2.0.tgz", + "integrity": "sha512-IJdWBbTcMQ6DA0gdNhh/BwrLkDR+ADW5Kr1aZmd4k3DIF6ezMV4R2NIAmT08wQJ3yUK82thHWmC/TnK/wpMMIA==", + "license": "Apache-2.0", + "dependencies": { + "@smithy/is-array-buffer": "^2.2.0", + "tslib": "^2.6.2" }, "engines": { "node": ">=14.0.0" } }, - "node_modules/@aws-sdk/client-sts": { - "version": "3.499.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/client-sts/-/client-sts-3.499.0.tgz", - "integrity": "sha512-Eyj9STw2DXMtXL5V/v0HYHO6+JjGPi257M5IYyxwqlvRchq6jbOsedobfxclB/gBUyBRtZdnyAIS8uCKjb4kpA==", - "dependencies": { - "@aws-crypto/sha256-browser": "3.0.0", - "@aws-crypto/sha256-js": "3.0.0", - "@aws-sdk/core": "3.496.0", - "@aws-sdk/credential-provider-node": "3.499.0", - "@aws-sdk/middleware-host-header": "3.496.0", - "@aws-sdk/middleware-logger": "3.496.0", - "@aws-sdk/middleware-recursion-detection": "3.496.0", - "@aws-sdk/middleware-user-agent": "3.496.0", - "@aws-sdk/region-config-resolver": "3.496.0", - "@aws-sdk/types": "3.496.0", - "@aws-sdk/util-endpoints": "3.496.0", - "@aws-sdk/util-user-agent-browser": "3.496.0", - "@aws-sdk/util-user-agent-node": "3.496.0", - "@smithy/config-resolver": "^2.1.1", - "@smithy/core": "^1.3.1", - "@smithy/fetch-http-handler": "^2.4.1", - "@smithy/hash-node": "^2.1.1", - "@smithy/invalid-dependency": "^2.1.1", - "@smithy/middleware-content-length": "^2.1.1", - "@smithy/middleware-endpoint": "^2.4.1", - "@smithy/middleware-retry": "^2.1.1", - "@smithy/middleware-serde": "^2.1.1", - "@smithy/middleware-stack": "^2.1.1", - "@smithy/node-config-provider": "^2.2.1", - "@smithy/node-http-handler": "^2.3.1", - "@smithy/protocol-http": "^3.1.1", - "@smithy/smithy-client": "^2.3.1", - "@smithy/types": "^2.9.1", - "@smithy/url-parser": "^2.1.1", - "@smithy/util-base64": "^2.1.1", - "@smithy/util-body-length-browser": "^2.1.1", - "@smithy/util-body-length-node": "^2.2.1", - "@smithy/util-defaults-mode-browser": "^2.1.1", - "@smithy/util-defaults-mode-node": "^2.1.1", - "@smithy/util-endpoints": "^1.1.1", - "@smithy/util-middleware": "^2.1.1", - "@smithy/util-retry": "^2.1.1", - "@smithy/util-utf8": "^2.1.1", - "fast-xml-parser": "4.2.5", - "tslib": "^2.5.0" + "node_modules/@aws-crypto/util/node_modules/@smithy/util-utf8": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/@smithy/util-utf8/-/util-utf8-2.3.0.tgz", + "integrity": "sha512-R8Rdn8Hy72KKcebgLiv8jQcQkXoLMOGGv5uI1/k0l+snqkOzQ1R0ChUBCxWMlBsFMekWjq0wRudIweFs7sKT5A==", + "license": "Apache-2.0", + "dependencies": { + "@smithy/util-buffer-from": "^2.2.0", + "tslib": "^2.6.2" }, "engines": { "node": ">=14.0.0" } }, + "node_modules/@aws-sdk/client-s3": { + "version": "3.645.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/client-s3/-/client-s3-3.645.0.tgz", + "integrity": "sha512-RjT/mfNv4yr1uv/+aEXgSIxC5EB+yHPSU7hH0KZOZrvZEFASLl0i4FeoHzbMEOH5KdKGAi0uu3zRP3D1y45sKg==", + "license": "Apache-2.0", + "dependencies": { + "@aws-crypto/sha1-browser": "5.2.0", + "@aws-crypto/sha256-browser": "5.2.0", + "@aws-crypto/sha256-js": "5.2.0", + "@aws-sdk/client-sso-oidc": "3.645.0", + "@aws-sdk/client-sts": "3.645.0", + "@aws-sdk/core": "3.635.0", + "@aws-sdk/credential-provider-node": "3.645.0", + "@aws-sdk/middleware-bucket-endpoint": "3.620.0", + "@aws-sdk/middleware-expect-continue": "3.620.0", + "@aws-sdk/middleware-flexible-checksums": "3.620.0", + "@aws-sdk/middleware-host-header": "3.620.0", + "@aws-sdk/middleware-location-constraint": "3.609.0", + "@aws-sdk/middleware-logger": "3.609.0", + "@aws-sdk/middleware-recursion-detection": "3.620.0", + "@aws-sdk/middleware-sdk-s3": "3.635.0", + "@aws-sdk/middleware-ssec": "3.609.0", + "@aws-sdk/middleware-user-agent": "3.645.0", + "@aws-sdk/region-config-resolver": "3.614.0", + "@aws-sdk/signature-v4-multi-region": "3.635.0", + "@aws-sdk/types": "3.609.0", + "@aws-sdk/util-endpoints": "3.645.0", + "@aws-sdk/util-user-agent-browser": "3.609.0", + "@aws-sdk/util-user-agent-node": "3.614.0", + "@aws-sdk/xml-builder": "3.609.0", + "@smithy/config-resolver": "^3.0.5", + "@smithy/core": "^2.4.0", + "@smithy/eventstream-serde-browser": "^3.0.6", + "@smithy/eventstream-serde-config-resolver": "^3.0.3", + "@smithy/eventstream-serde-node": "^3.0.5", + "@smithy/fetch-http-handler": "^3.2.4", + "@smithy/hash-blob-browser": "^3.1.2", + "@smithy/hash-node": "^3.0.3", + "@smithy/hash-stream-node": "^3.1.2", + "@smithy/invalid-dependency": "^3.0.3", + "@smithy/md5-js": "^3.0.3", + "@smithy/middleware-content-length": "^3.0.5", + "@smithy/middleware-endpoint": "^3.1.0", + "@smithy/middleware-retry": "^3.0.15", + "@smithy/middleware-serde": "^3.0.3", + "@smithy/middleware-stack": "^3.0.3", + "@smithy/node-config-provider": "^3.1.4", + "@smithy/node-http-handler": "^3.1.4", + "@smithy/protocol-http": "^4.1.0", + "@smithy/smithy-client": "^3.2.0", + "@smithy/types": "^3.3.0", + "@smithy/url-parser": "^3.0.3", + "@smithy/util-base64": "^3.0.0", + "@smithy/util-body-length-browser": "^3.0.0", + "@smithy/util-body-length-node": "^3.0.0", + "@smithy/util-defaults-mode-browser": "^3.0.15", + "@smithy/util-defaults-mode-node": "^3.0.15", + "@smithy/util-endpoints": "^2.0.5", + "@smithy/util-middleware": "^3.0.3", + "@smithy/util-retry": "^3.0.3", + "@smithy/util-stream": "^3.1.3", + "@smithy/util-utf8": "^3.0.0", + "@smithy/util-waiter": "^3.1.2", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@aws-sdk/client-sso": { + "version": "3.645.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/client-sso/-/client-sso-3.645.0.tgz", + "integrity": "sha512-2rc8TjnsNddOeKQ/pfNN7deNvGLXAeKeYtHtGDAiM2qfTKxd2sNcAsZ+JCDLyshuD4xLM5fpUyR0X8As9EAouQ==", + "license": "Apache-2.0", + "dependencies": { + "@aws-crypto/sha256-browser": "5.2.0", + "@aws-crypto/sha256-js": "5.2.0", + "@aws-sdk/core": "3.635.0", + "@aws-sdk/middleware-host-header": "3.620.0", + "@aws-sdk/middleware-logger": "3.609.0", + "@aws-sdk/middleware-recursion-detection": "3.620.0", + "@aws-sdk/middleware-user-agent": "3.645.0", + "@aws-sdk/region-config-resolver": "3.614.0", + "@aws-sdk/types": "3.609.0", + "@aws-sdk/util-endpoints": "3.645.0", + "@aws-sdk/util-user-agent-browser": "3.609.0", + "@aws-sdk/util-user-agent-node": "3.614.0", + "@smithy/config-resolver": "^3.0.5", + "@smithy/core": "^2.4.0", + "@smithy/fetch-http-handler": "^3.2.4", + "@smithy/hash-node": "^3.0.3", + "@smithy/invalid-dependency": "^3.0.3", + "@smithy/middleware-content-length": "^3.0.5", + "@smithy/middleware-endpoint": "^3.1.0", + "@smithy/middleware-retry": "^3.0.15", + "@smithy/middleware-serde": "^3.0.3", + "@smithy/middleware-stack": "^3.0.3", + "@smithy/node-config-provider": "^3.1.4", + "@smithy/node-http-handler": "^3.1.4", + "@smithy/protocol-http": "^4.1.0", + "@smithy/smithy-client": "^3.2.0", + "@smithy/types": "^3.3.0", + "@smithy/url-parser": "^3.0.3", + "@smithy/util-base64": "^3.0.0", + "@smithy/util-body-length-browser": "^3.0.0", + "@smithy/util-body-length-node": "^3.0.0", + "@smithy/util-defaults-mode-browser": "^3.0.15", + "@smithy/util-defaults-mode-node": "^3.0.15", + "@smithy/util-endpoints": "^2.0.5", + "@smithy/util-middleware": "^3.0.3", + "@smithy/util-retry": "^3.0.3", + "@smithy/util-utf8": "^3.0.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@aws-sdk/client-sso-oidc": { + "version": "3.645.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/client-sso-oidc/-/client-sso-oidc-3.645.0.tgz", + "integrity": "sha512-X9ULtdk3cO+1ysurEkJ1MSnu6U00qodXx+IVual+1jXX4RYY1WmQmfo7uDKf6FFkz7wW1DAqU+GJIBNQr0YH8A==", + "license": "Apache-2.0", + "dependencies": { + "@aws-crypto/sha256-browser": "5.2.0", + "@aws-crypto/sha256-js": "5.2.0", + "@aws-sdk/core": "3.635.0", + "@aws-sdk/credential-provider-node": "3.645.0", + "@aws-sdk/middleware-host-header": "3.620.0", + "@aws-sdk/middleware-logger": "3.609.0", + "@aws-sdk/middleware-recursion-detection": "3.620.0", + "@aws-sdk/middleware-user-agent": "3.645.0", + "@aws-sdk/region-config-resolver": "3.614.0", + "@aws-sdk/types": "3.609.0", + "@aws-sdk/util-endpoints": "3.645.0", + "@aws-sdk/util-user-agent-browser": "3.609.0", + "@aws-sdk/util-user-agent-node": "3.614.0", + "@smithy/config-resolver": "^3.0.5", + "@smithy/core": "^2.4.0", + "@smithy/fetch-http-handler": "^3.2.4", + "@smithy/hash-node": "^3.0.3", + "@smithy/invalid-dependency": "^3.0.3", + "@smithy/middleware-content-length": "^3.0.5", + "@smithy/middleware-endpoint": "^3.1.0", + "@smithy/middleware-retry": "^3.0.15", + "@smithy/middleware-serde": "^3.0.3", + "@smithy/middleware-stack": "^3.0.3", + "@smithy/node-config-provider": "^3.1.4", + "@smithy/node-http-handler": "^3.1.4", + "@smithy/protocol-http": "^4.1.0", + "@smithy/smithy-client": "^3.2.0", + "@smithy/types": "^3.3.0", + "@smithy/url-parser": "^3.0.3", + "@smithy/util-base64": "^3.0.0", + "@smithy/util-body-length-browser": "^3.0.0", + "@smithy/util-body-length-node": "^3.0.0", + "@smithy/util-defaults-mode-browser": "^3.0.15", + "@smithy/util-defaults-mode-node": "^3.0.15", + "@smithy/util-endpoints": "^2.0.5", + "@smithy/util-middleware": "^3.0.3", + "@smithy/util-retry": "^3.0.3", + "@smithy/util-utf8": "^3.0.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" + }, + "peerDependencies": { + "@aws-sdk/client-sts": "^3.645.0" + } + }, + "node_modules/@aws-sdk/client-sts": { + "version": "3.645.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/client-sts/-/client-sts-3.645.0.tgz", + "integrity": "sha512-6azXYtvtnAsPf2ShN9vKynIYVcJOpo6IoVmoMAVgNaBJyllP+s/RORzranYZzckqfmrudSxtct4rVapjLWuAMg==", + "license": "Apache-2.0", + "dependencies": { + "@aws-crypto/sha256-browser": "5.2.0", + "@aws-crypto/sha256-js": "5.2.0", + "@aws-sdk/client-sso-oidc": "3.645.0", + "@aws-sdk/core": "3.635.0", + "@aws-sdk/credential-provider-node": "3.645.0", + "@aws-sdk/middleware-host-header": "3.620.0", + "@aws-sdk/middleware-logger": "3.609.0", + "@aws-sdk/middleware-recursion-detection": "3.620.0", + "@aws-sdk/middleware-user-agent": "3.645.0", + "@aws-sdk/region-config-resolver": "3.614.0", + "@aws-sdk/types": "3.609.0", + "@aws-sdk/util-endpoints": "3.645.0", + "@aws-sdk/util-user-agent-browser": "3.609.0", + "@aws-sdk/util-user-agent-node": "3.614.0", + "@smithy/config-resolver": "^3.0.5", + "@smithy/core": "^2.4.0", + "@smithy/fetch-http-handler": "^3.2.4", + "@smithy/hash-node": "^3.0.3", + "@smithy/invalid-dependency": "^3.0.3", + "@smithy/middleware-content-length": "^3.0.5", + "@smithy/middleware-endpoint": "^3.1.0", + "@smithy/middleware-retry": "^3.0.15", + "@smithy/middleware-serde": "^3.0.3", + "@smithy/middleware-stack": "^3.0.3", + "@smithy/node-config-provider": "^3.1.4", + "@smithy/node-http-handler": "^3.1.4", + "@smithy/protocol-http": "^4.1.0", + "@smithy/smithy-client": "^3.2.0", + "@smithy/types": "^3.3.0", + "@smithy/url-parser": "^3.0.3", + "@smithy/util-base64": "^3.0.0", + "@smithy/util-body-length-browser": "^3.0.0", + "@smithy/util-body-length-node": "^3.0.0", + "@smithy/util-defaults-mode-browser": "^3.0.15", + "@smithy/util-defaults-mode-node": "^3.0.15", + "@smithy/util-endpoints": "^2.0.5", + "@smithy/util-middleware": "^3.0.3", + "@smithy/util-retry": "^3.0.3", + "@smithy/util-utf8": "^3.0.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" + } + }, "node_modules/@aws-sdk/core": { - "version": "3.496.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/core/-/core-3.496.0.tgz", - "integrity": "sha512-yT+ug7Cw/3eJi7x2es0+46x12+cIJm5Xv+GPWsrTFD1TKgqO/VPEgfDtHFagDNbFmjNQA65Ygc/kEdIX9ICX/A==", + "version": "3.635.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/core/-/core-3.635.0.tgz", + "integrity": "sha512-i1x/E/sgA+liUE1XJ7rj1dhyXpAKO1UKFUcTTHXok2ARjWTvszHnSXMOsB77aPbmn0fUp1JTx2kHUAZ1LVt5Bg==", + "license": "Apache-2.0", "dependencies": { - "@smithy/core": "^1.3.1", - "@smithy/protocol-http": "^3.1.1", - "@smithy/signature-v4": "^2.1.1", - "@smithy/smithy-client": "^2.3.1", - "@smithy/types": "^2.9.1", - "tslib": "^2.5.0" + "@smithy/core": "^2.4.0", + "@smithy/node-config-provider": "^3.1.4", + "@smithy/property-provider": "^3.1.3", + "@smithy/protocol-http": "^4.1.0", + "@smithy/signature-v4": "^4.1.0", + "@smithy/smithy-client": "^3.2.0", + "@smithy/types": "^3.3.0", + "@smithy/util-middleware": "^3.0.3", + "fast-xml-parser": "4.4.1", + "tslib": "^2.6.2" }, "engines": { - "node": ">=14.0.0" + "node": ">=16.0.0" } }, "node_modules/@aws-sdk/credential-provider-env": { - "version": "3.496.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-env/-/credential-provider-env-3.496.0.tgz", - "integrity": "sha512-lukQMJ8SWWP5RqkRNOHi/H+WMhRvSWa3Fc5Jf/VP6xHiPLfF1XafcvthtV91e0VwPCiseI+HqChrcGq8pvnxHw==", + "version": "3.620.1", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-env/-/credential-provider-env-3.620.1.tgz", + "integrity": "sha512-ExuILJ2qLW5ZO+rgkNRj0xiAipKT16Rk77buvPP8csR7kkCflT/gXTyzRe/uzIiETTxM7tr8xuO9MP/DQXqkfg==", + "license": "Apache-2.0", "dependencies": { - "@aws-sdk/types": "3.496.0", - "@smithy/property-provider": "^2.1.1", - "@smithy/types": "^2.9.1", - "tslib": "^2.5.0" + "@aws-sdk/types": "3.609.0", + "@smithy/property-provider": "^3.1.3", + "@smithy/types": "^3.3.0", + "tslib": "^2.6.2" }, "engines": { - "node": ">=14.0.0" + "node": ">=16.0.0" } }, - "node_modules/@aws-sdk/credential-provider-ini": { - "version": "3.496.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-ini/-/credential-provider-ini-3.496.0.tgz", - "integrity": "sha512-2nD1jp1sIwcQaWK1y/9ruQOkW16RUxZpzgjbW/gnK3iiUXwx+/FNQWxshud+GTSx3Q4x6eIhqsbjtP4VVPPuUA==", - "dependencies": { - "@aws-sdk/credential-provider-env": "3.496.0", - "@aws-sdk/credential-provider-process": "3.496.0", - "@aws-sdk/credential-provider-sso": "3.496.0", - "@aws-sdk/credential-provider-web-identity": "3.496.0", - "@aws-sdk/types": "3.496.0", - "@smithy/credential-provider-imds": "^2.2.1", - "@smithy/property-provider": "^2.1.1", - "@smithy/shared-ini-file-loader": "^2.3.1", - "@smithy/types": "^2.9.1", - "tslib": "^2.5.0" + "node_modules/@aws-sdk/credential-provider-http": { + "version": "3.635.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-http/-/credential-provider-http-3.635.0.tgz", + "integrity": "sha512-iJyRgEjOCQlBMXqtwPLIKYc7Bsc6nqjrZybdMDenPDa+kmLg7xh8LxHsu9088e+2/wtLicE34FsJJIfzu3L82g==", + "license": "Apache-2.0", + "dependencies": { + "@aws-sdk/types": "3.609.0", + "@smithy/fetch-http-handler": "^3.2.4", + "@smithy/node-http-handler": "^3.1.4", + "@smithy/property-provider": "^3.1.3", + "@smithy/protocol-http": "^4.1.0", + "@smithy/smithy-client": "^3.2.0", + "@smithy/types": "^3.3.0", + "@smithy/util-stream": "^3.1.3", + "tslib": "^2.6.2" }, "engines": { - "node": ">=14.0.0" + "node": ">=16.0.0" + } + }, + "node_modules/@aws-sdk/credential-provider-ini": { + "version": "3.645.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-ini/-/credential-provider-ini-3.645.0.tgz", + "integrity": "sha512-LlZW0qwUwNlTaAIDCNpLbPsyXvS42pRIwF92fgtCQedmdnpN3XRUC6hcwSYI7Xru3GGKp3RnceOvsdOaRJORsw==", + "license": "Apache-2.0", + "dependencies": { + "@aws-sdk/credential-provider-env": "3.620.1", + "@aws-sdk/credential-provider-http": "3.635.0", + "@aws-sdk/credential-provider-process": "3.620.1", + "@aws-sdk/credential-provider-sso": "3.645.0", + "@aws-sdk/credential-provider-web-identity": "3.621.0", + "@aws-sdk/types": "3.609.0", + "@smithy/credential-provider-imds": "^3.2.0", + "@smithy/property-provider": "^3.1.3", + "@smithy/shared-ini-file-loader": "^3.1.4", + "@smithy/types": "^3.3.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" + }, + "peerDependencies": { + "@aws-sdk/client-sts": "^3.645.0" } }, "node_modules/@aws-sdk/credential-provider-node": { - "version": "3.499.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-node/-/credential-provider-node-3.499.0.tgz", - "integrity": "sha512-EsiSevVmcVSMIq7D9siSH/XVc5I0vMntg1rx6KQdng1Fq8X/RBL5t9wSWEwOl7KFo5HlEsWrLWIpo1WHuzIL/w==", - "dependencies": { - "@aws-sdk/credential-provider-env": "3.496.0", - "@aws-sdk/credential-provider-ini": "3.496.0", - "@aws-sdk/credential-provider-process": "3.496.0", - "@aws-sdk/credential-provider-sso": "3.496.0", - "@aws-sdk/credential-provider-web-identity": "3.496.0", - "@aws-sdk/types": "3.496.0", - "@smithy/credential-provider-imds": "^2.2.1", - "@smithy/property-provider": "^2.1.1", - "@smithy/shared-ini-file-loader": "^2.3.1", - "@smithy/types": "^2.9.1", - "tslib": "^2.5.0" + "version": "3.645.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-node/-/credential-provider-node-3.645.0.tgz", + "integrity": "sha512-eGFFuNvLeXjCJf5OCIuSEflxUowmK+bCS+lK4M8ofsYOEGAivdx7C0UPxNjHpvM8wKd8vpMl5phTeS9BWX5jMQ==", + "license": "Apache-2.0", + "dependencies": { + "@aws-sdk/credential-provider-env": "3.620.1", + "@aws-sdk/credential-provider-http": "3.635.0", + "@aws-sdk/credential-provider-ini": "3.645.0", + "@aws-sdk/credential-provider-process": "3.620.1", + "@aws-sdk/credential-provider-sso": "3.645.0", + "@aws-sdk/credential-provider-web-identity": "3.621.0", + "@aws-sdk/types": "3.609.0", + "@smithy/credential-provider-imds": "^3.2.0", + "@smithy/property-provider": "^3.1.3", + "@smithy/shared-ini-file-loader": "^3.1.4", + "@smithy/types": "^3.3.0", + "tslib": "^2.6.2" }, "engines": { - "node": ">=14.0.0" + "node": ">=16.0.0" } }, "node_modules/@aws-sdk/credential-provider-process": { - "version": "3.496.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-process/-/credential-provider-process-3.496.0.tgz", - "integrity": "sha512-/YZscCTGOKVmGr916Th4XF8Sz6JDtZ/n2loHG9exok9iy/qIbACsTRNLP9zexPxhPoue/oZqecY5xbVljfY34A==", + "version": "3.620.1", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-process/-/credential-provider-process-3.620.1.tgz", + "integrity": "sha512-hWqFMidqLAkaV9G460+1at6qa9vySbjQKKc04p59OT7lZ5cO5VH5S4aI05e+m4j364MBROjjk2ugNvfNf/8ILg==", + "license": "Apache-2.0", "dependencies": { - "@aws-sdk/types": "3.496.0", - "@smithy/property-provider": "^2.1.1", - "@smithy/shared-ini-file-loader": "^2.3.1", - "@smithy/types": "^2.9.1", - "tslib": "^2.5.0" + "@aws-sdk/types": "3.609.0", + "@smithy/property-provider": "^3.1.3", + "@smithy/shared-ini-file-loader": "^3.1.4", + "@smithy/types": "^3.3.0", + "tslib": "^2.6.2" }, "engines": { - "node": ">=14.0.0" + "node": ">=16.0.0" } }, "node_modules/@aws-sdk/credential-provider-sso": { - "version": "3.496.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-sso/-/credential-provider-sso-3.496.0.tgz", - "integrity": "sha512-eP7GxpT2QYubSDG7uk1GJW4eNymZCq65IxDyEFCXOP/kfqkxriCY+iVEFG6/Mo3LxvgrgHXU4jxrCAXMAWN43g==", + "version": "3.645.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-sso/-/credential-provider-sso-3.645.0.tgz", + "integrity": "sha512-d6XuChAl5NCsCrUexc6AFb4efPmb9+66iwPylKG+iMTMYgO1ackfy1Q2/f35jdn0jolkPkzKsVyfzsEVoID6ew==", + "license": "Apache-2.0", "dependencies": { - "@aws-sdk/client-sso": "3.496.0", - "@aws-sdk/token-providers": "3.496.0", - "@aws-sdk/types": "3.496.0", - "@smithy/property-provider": "^2.1.1", - "@smithy/shared-ini-file-loader": "^2.3.1", - "@smithy/types": "^2.9.1", - "tslib": "^2.5.0" + "@aws-sdk/client-sso": "3.645.0", + "@aws-sdk/token-providers": "3.614.0", + "@aws-sdk/types": "3.609.0", + "@smithy/property-provider": "^3.1.3", + "@smithy/shared-ini-file-loader": "^3.1.4", + "@smithy/types": "^3.3.0", + "tslib": "^2.6.2" }, "engines": { - "node": ">=14.0.0" + "node": ">=16.0.0" } }, "node_modules/@aws-sdk/credential-provider-web-identity": { - "version": "3.496.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-web-identity/-/credential-provider-web-identity-3.496.0.tgz", - "integrity": "sha512-IbP+qLlvJSpNPj+zW6TtFuLRTK5Tf0hW+2pom4vFyi5YSH4pn8UOC136UdewX8vhXGS9BJQ5zBDMasIyl5VeGQ==", + "version": "3.621.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-web-identity/-/credential-provider-web-identity-3.621.0.tgz", + "integrity": "sha512-w7ASSyfNvcx7+bYGep3VBgC3K6vEdLmlpjT7nSIHxxQf+WSdvy+HynwJosrpZax0sK5q0D1Jpn/5q+r5lwwW6w==", + "license": "Apache-2.0", "dependencies": { - "@aws-sdk/types": "3.496.0", - "@smithy/property-provider": "^2.1.1", - "@smithy/types": "^2.9.1", - "tslib": "^2.5.0" + "@aws-sdk/types": "3.609.0", + "@smithy/property-provider": "^3.1.3", + "@smithy/types": "^3.3.0", + "tslib": "^2.6.2" }, "engines": { - "node": ">=14.0.0" + "node": ">=16.0.0" + }, + "peerDependencies": { + "@aws-sdk/client-sts": "^3.621.0" } }, "node_modules/@aws-sdk/middleware-bucket-endpoint": { - "version": "3.496.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-bucket-endpoint/-/middleware-bucket-endpoint-3.496.0.tgz", - "integrity": "sha512-B+ilBMSs3+LJuo2bl2KB8GFdu+8PPVtYEWtwhNkmnaU8iMisgMBp5uuM8sUDvJX7I4iSF0WbgnhguX4cJqfAew==", + "version": "3.620.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-bucket-endpoint/-/middleware-bucket-endpoint-3.620.0.tgz", + "integrity": "sha512-eGLL0W6L3HDb3OACyetZYOWpHJ+gLo0TehQKeQyy2G8vTYXqNTeqYhuI6up9HVjBzU9eQiULVQETmgQs7TFaRg==", + "license": "Apache-2.0", "dependencies": { - "@aws-sdk/types": "3.496.0", - "@aws-sdk/util-arn-parser": "3.495.0", - "@smithy/node-config-provider": "^2.2.1", - "@smithy/protocol-http": "^3.1.1", - "@smithy/types": "^2.9.1", - "@smithy/util-config-provider": "^2.2.1", - "tslib": "^2.5.0" + "@aws-sdk/types": "3.609.0", + "@aws-sdk/util-arn-parser": "3.568.0", + "@smithy/node-config-provider": "^3.1.4", + "@smithy/protocol-http": "^4.1.0", + "@smithy/types": "^3.3.0", + "@smithy/util-config-provider": "^3.0.0", + "tslib": "^2.6.2" }, "engines": { - "node": ">=14.0.0" + "node": ">=16.0.0" } }, "node_modules/@aws-sdk/middleware-expect-continue": { - "version": "3.496.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-expect-continue/-/middleware-expect-continue-3.496.0.tgz", - "integrity": "sha512-+exo5DVc+BeDus2iI6Fz1thefHGDXxUhHZ+4VHQ6HkStMy3Y22HugyEGHSQZmtRL86Hjr7dFbEWFsC47a2ItGA==", + "version": "3.620.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-expect-continue/-/middleware-expect-continue-3.620.0.tgz", + "integrity": "sha512-QXeRFMLfyQ31nAHLbiTLtk0oHzG9QLMaof5jIfqcUwnOkO8YnQdeqzakrg1Alpy/VQ7aqzIi8qypkBe2KXZz0A==", + "license": "Apache-2.0", "dependencies": { - "@aws-sdk/types": "3.496.0", - "@smithy/protocol-http": "^3.1.1", - "@smithy/types": "^2.9.1", - "tslib": "^2.5.0" + "@aws-sdk/types": "3.609.0", + "@smithy/protocol-http": "^4.1.0", + "@smithy/types": "^3.3.0", + "tslib": "^2.6.2" }, "engines": { - "node": ">=14.0.0" + "node": ">=16.0.0" } }, "node_modules/@aws-sdk/middleware-flexible-checksums": { - "version": "3.496.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-flexible-checksums/-/middleware-flexible-checksums-3.496.0.tgz", - "integrity": "sha512-yQIWfjEMvgsAJ7ku224vXDjXPD+f9zfKZFialJva8VUlEr7hQp4CQ0rxV3YThSaixKEDDs5k6kOjWAd2BPGr2A==", + "version": "3.620.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-flexible-checksums/-/middleware-flexible-checksums-3.620.0.tgz", + "integrity": "sha512-ftz+NW7qka2sVuwnnO1IzBku5ccP+s5qZGeRTPgrKB7OzRW85gthvIo1vQR2w+OwHFk7WJbbhhWwbCbktnP4UA==", + "license": "Apache-2.0", "dependencies": { - "@aws-crypto/crc32": "3.0.0", - "@aws-crypto/crc32c": "3.0.0", - "@aws-sdk/types": "3.496.0", - "@smithy/is-array-buffer": "^2.1.1", - "@smithy/protocol-http": "^3.1.1", - "@smithy/types": "^2.9.1", - "@smithy/util-utf8": "^2.1.1", - "tslib": "^2.5.0" + "@aws-crypto/crc32": "5.2.0", + "@aws-crypto/crc32c": "5.2.0", + "@aws-sdk/types": "3.609.0", + "@smithy/is-array-buffer": "^3.0.0", + "@smithy/protocol-http": "^4.1.0", + "@smithy/types": "^3.3.0", + "@smithy/util-utf8": "^3.0.0", + "tslib": "^2.6.2" }, "engines": { - "node": ">=14.0.0" + "node": ">=16.0.0" } }, "node_modules/@aws-sdk/middleware-host-header": { - "version": "3.496.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-host-header/-/middleware-host-header-3.496.0.tgz", - "integrity": "sha512-jUdPpSJeqCYXf6hSjfwsfHway7peIV8Vz51w/BN91bF4vB/bYwAC5o9/iJiK/EoByp5asxA8fg9wFOyGjzdbLg==", + "version": "3.620.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-host-header/-/middleware-host-header-3.620.0.tgz", + "integrity": "sha512-VMtPEZwqYrII/oUkffYsNWY9PZ9xpNJpMgmyU0rlDQ25O1c0Hk3fJmZRe6pEkAJ0omD7kLrqGl1DUjQVxpd/Rg==", + "license": "Apache-2.0", "dependencies": { - "@aws-sdk/types": "3.496.0", - "@smithy/protocol-http": "^3.1.1", - "@smithy/types": "^2.9.1", - "tslib": "^2.5.0" + "@aws-sdk/types": "3.609.0", + "@smithy/protocol-http": "^4.1.0", + "@smithy/types": "^3.3.0", + "tslib": "^2.6.2" }, "engines": { - "node": ">=14.0.0" + "node": ">=16.0.0" } }, "node_modules/@aws-sdk/middleware-location-constraint": { - "version": "3.496.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-location-constraint/-/middleware-location-constraint-3.496.0.tgz", - "integrity": "sha512-i4ocJ2Zs86OtPREbB18InFukhqg2qtBxb5gywv79IHDPVmpOYE4m/3v3yGUrkjfF2GTlUL0k5FskNNqw41yfng==", + "version": "3.609.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-location-constraint/-/middleware-location-constraint-3.609.0.tgz", + "integrity": "sha512-xzsdoTkszGVqGVPjUmgoP7TORiByLueMHieI1fhQL888WPdqctwAx3ES6d/bA9Q/i8jnc6hs+Fjhy8UvBTkE9A==", + "license": "Apache-2.0", "dependencies": { - "@aws-sdk/types": "3.496.0", - "@smithy/types": "^2.9.1", - "tslib": "^2.5.0" + "@aws-sdk/types": "3.609.0", + "@smithy/types": "^3.3.0", + "tslib": "^2.6.2" }, "engines": { - "node": ">=14.0.0" + "node": ">=16.0.0" } }, "node_modules/@aws-sdk/middleware-logger": { - "version": "3.496.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-logger/-/middleware-logger-3.496.0.tgz", - "integrity": "sha512-EwMVSY6iBMeGbVnvwdaFl/ClMS/YWtxCAo+bcEtgk8ltRuo7qgbJem8Km/fvWC1vdWvIbe4ArdJ8iGzq62ffAw==", + "version": "3.609.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-logger/-/middleware-logger-3.609.0.tgz", + "integrity": "sha512-S62U2dy4jMDhDFDK5gZ4VxFdWzCtLzwbYyFZx2uvPYTECkepLUfzLic2BHg2Qvtu4QjX+oGE3P/7fwaGIsGNuQ==", + "license": "Apache-2.0", "dependencies": { - "@aws-sdk/types": "3.496.0", - "@smithy/types": "^2.9.1", - "tslib": "^2.5.0" + "@aws-sdk/types": "3.609.0", + "@smithy/types": "^3.3.0", + "tslib": "^2.6.2" }, "engines": { - "node": ">=14.0.0" + "node": ">=16.0.0" } }, "node_modules/@aws-sdk/middleware-recursion-detection": { - "version": "3.496.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-recursion-detection/-/middleware-recursion-detection-3.496.0.tgz", - "integrity": "sha512-+IuOcFsfqg2WAnaEzH6KhVbicqCxtOq9w3DH2jwTpddRlCx2Kqf6wCzg8luhHRGyjBZdsbIS+OXwyMevoppawA==", + "version": "3.620.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-recursion-detection/-/middleware-recursion-detection-3.620.0.tgz", + "integrity": "sha512-nh91S7aGK3e/o1ck64sA/CyoFw+gAYj2BDOnoNa6ouyCrVJED96ZXWbhye/fz9SgmNUZR2g7GdVpiLpMKZoI5w==", + "license": "Apache-2.0", "dependencies": { - "@aws-sdk/types": "3.496.0", - "@smithy/protocol-http": "^3.1.1", - "@smithy/types": "^2.9.1", - "tslib": "^2.5.0" + "@aws-sdk/types": "3.609.0", + "@smithy/protocol-http": "^4.1.0", + "@smithy/types": "^3.3.0", + "tslib": "^2.6.2" }, "engines": { - "node": ">=14.0.0" + "node": ">=16.0.0" } }, "node_modules/@aws-sdk/middleware-sdk-s3": { - "version": "3.499.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-sdk-s3/-/middleware-sdk-s3-3.499.0.tgz", - "integrity": "sha512-thTb47U1hYHk5ei+yO0D0aehbgQXeAcgvyyxOID9/HDuRfWuTvKdclWh/goIeDfvSS87VBukEAjnCa5JYBwzug==", - "dependencies": { - "@aws-sdk/types": "3.496.0", - "@aws-sdk/util-arn-parser": "3.495.0", - "@smithy/node-config-provider": "^2.2.1", - "@smithy/protocol-http": "^3.1.1", - "@smithy/signature-v4": "^2.1.1", - "@smithy/smithy-client": "^2.3.1", - "@smithy/types": "^2.9.1", - "@smithy/util-config-provider": "^2.2.1", - "tslib": "^2.5.0" - }, - "engines": { - "node": ">=14.0.0" - } - }, - "node_modules/@aws-sdk/middleware-signing": { - "version": "3.496.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-signing/-/middleware-signing-3.496.0.tgz", - "integrity": "sha512-Oq73Brs4IConvWnRlh8jM1V7LHoTw9SVQklu/QW2FPlNrB3B8fuTdWHHYIWv7ybw1bykXoCY99v865Mmq/Or/g==", - "dependencies": { - "@aws-sdk/types": "3.496.0", - "@smithy/property-provider": "^2.1.1", - "@smithy/protocol-http": "^3.1.1", - "@smithy/signature-v4": "^2.1.1", - "@smithy/types": "^2.9.1", - "@smithy/util-middleware": "^2.1.1", - "tslib": "^2.5.0" - }, - "engines": { - "node": ">=14.0.0" + "version": "3.635.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-sdk-s3/-/middleware-sdk-s3-3.635.0.tgz", + "integrity": "sha512-RLdYJPEV4JL/7NBoFUs7VlP90X++5FlJdxHz0DzCjmiD3qCviKy+Cym3qg1gBgHwucs5XisuClxDrGokhAdTQw==", + "license": "Apache-2.0", + "dependencies": { + "@aws-sdk/core": "3.635.0", + "@aws-sdk/types": "3.609.0", + "@aws-sdk/util-arn-parser": "3.568.0", + "@smithy/core": "^2.4.0", + "@smithy/node-config-provider": "^3.1.4", + "@smithy/protocol-http": "^4.1.0", + "@smithy/signature-v4": "^4.1.0", + "@smithy/smithy-client": "^3.2.0", + "@smithy/types": "^3.3.0", + "@smithy/util-config-provider": "^3.0.0", + "@smithy/util-middleware": "^3.0.3", + "@smithy/util-stream": "^3.1.3", + "@smithy/util-utf8": "^3.0.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" } }, "node_modules/@aws-sdk/middleware-ssec": { - "version": "3.498.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-ssec/-/middleware-ssec-3.498.0.tgz", - "integrity": "sha512-sWujXgzeTqMZzj/pRYEnnEbSzhBosqw9DXHOY1Mg2igI9NEfGlB7lPARp6aKmCaYlP3Bcj2X86vKCqF53mbyig==", + "version": "3.609.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-ssec/-/middleware-ssec-3.609.0.tgz", + "integrity": "sha512-GZSD1s7+JswWOTamVap79QiDaIV7byJFssBW68GYjyRS5EBjNfwA/8s+6uE6g39R3ojyTbYOmvcANoZEhSULXg==", + "license": "Apache-2.0", "dependencies": { - "@aws-sdk/types": "3.496.0", - "@smithy/types": "^2.9.1", - "tslib": "^2.5.0" + "@aws-sdk/types": "3.609.0", + "@smithy/types": "^3.3.0", + "tslib": "^2.6.2" }, "engines": { - "node": ">=14.0.0" + "node": ">=16.0.0" } }, "node_modules/@aws-sdk/middleware-user-agent": { - "version": "3.496.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-user-agent/-/middleware-user-agent-3.496.0.tgz", - "integrity": "sha512-+iMtRxFk0GmFWNUF4ilxylOQd9PZdR4ZC9jkcPIh1PZlvKtpCyFywKlk5RRZKklSoJ/CttcqwhMvOXTNbWm/0w==", + "version": "3.645.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-user-agent/-/middleware-user-agent-3.645.0.tgz", + "integrity": "sha512-NpTAtqWK+49lRuxfz7st9for80r4NriCMK0RfdJSoPFVntjsSQiQ7+2nW2XL05uVY633e9DvCAw8YatX3zd1mw==", + "license": "Apache-2.0", "dependencies": { - "@aws-sdk/types": "3.496.0", - "@aws-sdk/util-endpoints": "3.496.0", - "@smithy/protocol-http": "^3.1.1", - "@smithy/types": "^2.9.1", - "tslib": "^2.5.0" + "@aws-sdk/types": "3.609.0", + "@aws-sdk/util-endpoints": "3.645.0", + "@smithy/protocol-http": "^4.1.0", + "@smithy/types": "^3.3.0", + "tslib": "^2.6.2" }, "engines": { - "node": ">=14.0.0" + "node": ">=16.0.0" } }, "node_modules/@aws-sdk/region-config-resolver": { - "version": "3.496.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/region-config-resolver/-/region-config-resolver-3.496.0.tgz", - "integrity": "sha512-URrNVOPHPgEDm6QFu6lDC2cUFs+Jx23mA3jEwCvoKlXiEY/ZoWjH8wlX3OMUlLrF1qoUTuD03jjrJzF6zoCgug==", + "version": "3.614.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/region-config-resolver/-/region-config-resolver-3.614.0.tgz", + "integrity": "sha512-vDCeMXvic/LU0KFIUjpC3RiSTIkkvESsEfbVHiHH0YINfl8HnEqR5rj+L8+phsCeVg2+LmYwYxd5NRz4PHxt5g==", + "license": "Apache-2.0", "dependencies": { - "@aws-sdk/types": "3.496.0", - "@smithy/node-config-provider": "^2.2.1", - "@smithy/types": "^2.9.1", - "@smithy/util-config-provider": "^2.2.1", - "@smithy/util-middleware": "^2.1.1", - "tslib": "^2.5.0" + "@aws-sdk/types": "3.609.0", + "@smithy/node-config-provider": "^3.1.4", + "@smithy/types": "^3.3.0", + "@smithy/util-config-provider": "^3.0.0", + "@smithy/util-middleware": "^3.0.3", + "tslib": "^2.6.2" }, "engines": { - "node": ">=14.0.0" + "node": ">=16.0.0" } }, "node_modules/@aws-sdk/signature-v4-multi-region": { - "version": "3.499.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/signature-v4-multi-region/-/signature-v4-multi-region-3.499.0.tgz", - "integrity": "sha512-8HSFnZErRm7lAfk+Epxrf4QNdQEamg1CnbLybtKQQEjmvxLuXYvj16KlpYEZIwEENOMEvnCqMc7syTPkmjVhJA==", + "version": "3.635.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/signature-v4-multi-region/-/signature-v4-multi-region-3.635.0.tgz", + "integrity": "sha512-J6QY4/invOkpogCHjSaDON1hF03viPpOnsrzVuCvJMmclS/iG62R4EY0wq1alYll0YmSdmKlpJwHMWwGtqK63Q==", + "license": "Apache-2.0", "dependencies": { - "@aws-sdk/middleware-sdk-s3": "3.499.0", - "@aws-sdk/types": "3.496.0", - "@smithy/protocol-http": "^3.1.1", - "@smithy/signature-v4": "^2.1.1", - "@smithy/types": "^2.9.1", - "tslib": "^2.5.0" + "@aws-sdk/middleware-sdk-s3": "3.635.0", + "@aws-sdk/types": "3.609.0", + "@smithy/protocol-http": "^4.1.0", + "@smithy/signature-v4": "^4.1.0", + "@smithy/types": "^3.3.0", + "tslib": "^2.6.2" }, "engines": { - "node": ">=14.0.0" + "node": ">=16.0.0" } }, "node_modules/@aws-sdk/token-providers": { - "version": "3.496.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/token-providers/-/token-providers-3.496.0.tgz", - "integrity": "sha512-fyi8RcObEa1jNETJdc2H6q9VHrrdKCj/b6+fbLvymb7mUVRd0aWUn+24SNUImnSOnrwYnwaMfyyEC388X4MbFQ==", - "dependencies": { - "@aws-crypto/sha256-browser": "3.0.0", - "@aws-crypto/sha256-js": "3.0.0", - "@aws-sdk/middleware-host-header": "3.496.0", - "@aws-sdk/middleware-logger": "3.496.0", - "@aws-sdk/middleware-recursion-detection": "3.496.0", - "@aws-sdk/middleware-user-agent": "3.496.0", - "@aws-sdk/region-config-resolver": "3.496.0", - "@aws-sdk/types": "3.496.0", - "@aws-sdk/util-endpoints": "3.496.0", - "@aws-sdk/util-user-agent-browser": "3.496.0", - "@aws-sdk/util-user-agent-node": "3.496.0", - "@smithy/config-resolver": "^2.1.1", - "@smithy/fetch-http-handler": "^2.4.1", - "@smithy/hash-node": "^2.1.1", - "@smithy/invalid-dependency": "^2.1.1", - "@smithy/middleware-content-length": "^2.1.1", - "@smithy/middleware-endpoint": "^2.4.1", - "@smithy/middleware-retry": "^2.1.1", - "@smithy/middleware-serde": "^2.1.1", - "@smithy/middleware-stack": "^2.1.1", - "@smithy/node-config-provider": "^2.2.1", - "@smithy/node-http-handler": "^2.3.1", - "@smithy/property-provider": "^2.1.1", - "@smithy/protocol-http": "^3.1.1", - "@smithy/shared-ini-file-loader": "^2.3.1", - "@smithy/smithy-client": "^2.3.1", - "@smithy/types": "^2.9.1", - "@smithy/url-parser": "^2.1.1", - "@smithy/util-base64": "^2.1.1", - "@smithy/util-body-length-browser": "^2.1.1", - "@smithy/util-body-length-node": "^2.2.1", - "@smithy/util-defaults-mode-browser": "^2.1.1", - "@smithy/util-defaults-mode-node": "^2.1.1", - "@smithy/util-endpoints": "^1.1.1", - "@smithy/util-retry": "^2.1.1", - "@smithy/util-utf8": "^2.1.1", - "tslib": "^2.5.0" + "version": "3.614.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/token-providers/-/token-providers-3.614.0.tgz", + "integrity": "sha512-okItqyY6L9IHdxqs+Z116y5/nda7rHxLvROxtAJdLavWTYDydxrZstImNgGWTeVdmc0xX2gJCI77UYUTQWnhRw==", + "license": "Apache-2.0", + "dependencies": { + "@aws-sdk/types": "3.609.0", + "@smithy/property-provider": "^3.1.3", + "@smithy/shared-ini-file-loader": "^3.1.4", + "@smithy/types": "^3.3.0", + "tslib": "^2.6.2" }, "engines": { - "node": ">=14.0.0" + "node": ">=16.0.0" + }, + "peerDependencies": { + "@aws-sdk/client-sso-oidc": "^3.614.0" } }, "node_modules/@aws-sdk/types": { - "version": "3.496.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/types/-/types-3.496.0.tgz", - "integrity": "sha512-umkGadK4QuNQaMoDICMm7NKRI/mYSXiyPjcn3d53BhsuArYU/52CebGQKdt4At7SwwsiVJZw9RNBHyN5Mm0HVw==", + "version": "3.609.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/types/-/types-3.609.0.tgz", + "integrity": "sha512-+Tqnh9w0h2LcrUsdXyT1F8mNhXz+tVYBtP19LpeEGntmvHwa2XzvLUCWpoIAIVsHp5+HdB2X9Sn0KAtmbFXc2Q==", + "license": "Apache-2.0", "dependencies": { - "@smithy/types": "^2.9.1", - "tslib": "^2.5.0" + "@smithy/types": "^3.3.0", + "tslib": "^2.6.2" }, "engines": { - "node": ">=14.0.0" + "node": ">=16.0.0" } }, "node_modules/@aws-sdk/util-arn-parser": { - "version": "3.495.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/util-arn-parser/-/util-arn-parser-3.495.0.tgz", - "integrity": "sha512-hwdA3XAippSEUxs7jpznwD63YYFR+LtQvlEcebPTgWR9oQgG9TfS+39PUfbnEeje1ICuOrN3lrFqFbmP9uzbMg==", + "version": "3.568.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/util-arn-parser/-/util-arn-parser-3.568.0.tgz", + "integrity": "sha512-XUKJWWo+KOB7fbnPP0+g/o5Ulku/X53t7i/h+sPHr5xxYTJJ9CYnbToo95mzxe7xWvkLrsNtJ8L+MnNn9INs2w==", + "license": "Apache-2.0", "dependencies": { - "tslib": "^2.5.0" + "tslib": "^2.6.2" }, "engines": { - "node": ">=14.0.0" + "node": ">=16.0.0" } }, "node_modules/@aws-sdk/util-endpoints": { - "version": "3.496.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/util-endpoints/-/util-endpoints-3.496.0.tgz", - "integrity": "sha512-1QzOiWHi383ZwqSi/R2KgKCd7M+6DxkxI5acqLPm8mvDRDP2jRjrnVaC0g9/tlttWousGEemDUWStwrD2mVYSw==", + "version": "3.645.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/util-endpoints/-/util-endpoints-3.645.0.tgz", + "integrity": "sha512-Oe+xaU4ic4PB1k3pb5VTC1/MWES13IlgpaQw01bVHGfwP6Yv6zZOxizRzca2Y3E+AyR+nKD7vXtHRY+w3bi4bg==", + "license": "Apache-2.0", "dependencies": { - "@aws-sdk/types": "3.496.0", - "@smithy/types": "^2.9.1", - "@smithy/util-endpoints": "^1.1.1", - "tslib": "^2.5.0" + "@aws-sdk/types": "3.609.0", + "@smithy/types": "^3.3.0", + "@smithy/util-endpoints": "^2.0.5", + "tslib": "^2.6.2" }, "engines": { - "node": ">=14.0.0" + "node": ">=16.0.0" } }, "node_modules/@aws-sdk/util-locate-window": { - "version": "3.495.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/util-locate-window/-/util-locate-window-3.495.0.tgz", - "integrity": "sha512-MfaPXT0kLX2tQaR90saBT9fWQq2DHqSSJRzW+MZWsmF+y5LGCOhO22ac/2o6TKSQm7h0HRc2GaADqYYYor62yg==", + "version": "3.568.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/util-locate-window/-/util-locate-window-3.568.0.tgz", + "integrity": "sha512-3nh4TINkXYr+H41QaPelCceEB2FXP3fxp93YZXB/kqJvX0U9j0N0Uk45gvsjmEPzG8XxkPEeLIfT2I1M7A6Lig==", + "license": "Apache-2.0", "dependencies": { - "tslib": "^2.5.0" + "tslib": "^2.6.2" }, "engines": { - "node": ">=14.0.0" + "node": ">=16.0.0" } }, "node_modules/@aws-sdk/util-user-agent-browser": { - "version": "3.496.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/util-user-agent-browser/-/util-user-agent-browser-3.496.0.tgz", - "integrity": "sha512-4j2spN+h0I0qfSMsGvJXTfQBu1e18rPdekKvzsGJxhaAE1tNgUfUT4nbvc5uVn0sNjZmirskmJ3kfbzVOrqIFg==", + "version": "3.609.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/util-user-agent-browser/-/util-user-agent-browser-3.609.0.tgz", + "integrity": "sha512-fojPU+mNahzQ0YHYBsx0ZIhmMA96H+ZIZ665ObU9tl+SGdbLneVZVikGve+NmHTQwHzwkFsZYYnVKAkreJLAtA==", + "license": "Apache-2.0", "dependencies": { - "@aws-sdk/types": "3.496.0", - "@smithy/types": "^2.9.1", + "@aws-sdk/types": "3.609.0", + "@smithy/types": "^3.3.0", "bowser": "^2.11.0", - "tslib": "^2.5.0" + "tslib": "^2.6.2" } }, "node_modules/@aws-sdk/util-user-agent-node": { - "version": "3.496.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/util-user-agent-node/-/util-user-agent-node-3.496.0.tgz", - "integrity": "sha512-h0Ax0jlDc7UIo3KoSI4C4tVLBFoiAdx3+DhTVfgLS7x93d41dMlziPoBX2RgdcFn37qnzw6AQKTVTMwDbRCGpg==", + "version": "3.614.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/util-user-agent-node/-/util-user-agent-node-3.614.0.tgz", + "integrity": "sha512-15ElZT88peoHnq5TEoEtZwoXTXRxNrk60TZNdpl/TUBJ5oNJ9Dqb5Z4ryb8ofN6nm9aFf59GVAerFDz8iUoHBA==", + "license": "Apache-2.0", "dependencies": { - "@aws-sdk/types": "3.496.0", - "@smithy/node-config-provider": "^2.2.1", - "@smithy/types": "^2.9.1", - "tslib": "^2.5.0" + "@aws-sdk/types": "3.609.0", + "@smithy/node-config-provider": "^3.1.4", + "@smithy/types": "^3.3.0", + "tslib": "^2.6.2" }, "engines": { - "node": ">=14.0.0" + "node": ">=16.0.0" }, "peerDependencies": { "aws-crt": ">=1.0.0" @@ -771,24 +923,17 @@ } } }, - "node_modules/@aws-sdk/util-utf8-browser": { - "version": "3.259.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/util-utf8-browser/-/util-utf8-browser-3.259.0.tgz", - "integrity": "sha512-UvFa/vR+e19XookZF8RzFZBrw2EUkQWxiBW0yYQAhvk3C+QVGl0H3ouca8LDBlBfQKXwmW3huo/59H8rwb1wJw==", - "dependencies": { - "tslib": "^2.3.1" - } - }, "node_modules/@aws-sdk/xml-builder": { - "version": "3.496.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/xml-builder/-/xml-builder-3.496.0.tgz", - "integrity": "sha512-GvEjh537IIeOw1ZkZuB37sV12u+ipS5Z1dwjEC/HAvhl5ac23ULtTr1/n+U1gLNN+BAKSWjKiQ2ksj8DiUzeyw==", + "version": "3.609.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/xml-builder/-/xml-builder-3.609.0.tgz", + "integrity": "sha512-l9XxNcA4HX98rwCC2/KoiWcmEiRfZe4G+mYwDbCFT87JIMj6GBhLDkAzr/W8KAaA2IDr8Vc6J8fZPgVulxxfMA==", + "license": "Apache-2.0", "dependencies": { - "@smithy/types": "^2.9.1", - "tslib": "^2.5.0" + "@smithy/types": "^3.3.0", + "tslib": "^2.6.2" }, "engines": { - "node": ">=14.0.0" + "node": ">=16.0.0" } }, "node_modules/@cspotcode/source-map-support": { @@ -804,11 +949,12 @@ } }, "node_modules/@defillama/sdk": { - "version": "5.0.35", - "resolved": "https://registry.npmjs.org/@defillama/sdk/-/sdk-5.0.35.tgz", - "integrity": "sha512-+180AooJyM7VlVpFyp/9fYXjcumKHIRuxEOQ4DOSNhqv3SdkpQrlzCnSfI6DrQ36turqNWPBl6AQxrqskns55A==", + "version": "5.0.92", + "resolved": "https://registry.npmjs.org/@defillama/sdk/-/sdk-5.0.92.tgz", + "integrity": "sha512-t6A4qSX9y1VPIaiVE7/O1UPrkDmljjiGv8DrtKZuzuCpwMsL2uMDNIn5a8WLnQizft8mUV3YY4aojx6WC7L7Sw==", "dependencies": { "@aws-sdk/client-s3": "^3.400.0", + "@elastic/elasticsearch": "^8.13.1", "@supercharge/promise-pool": "^2.1.0", "axios": "^1.6.5", "ethers": "^6.0.0", @@ -824,6 +970,47 @@ "node": ">=8" } }, + "node_modules/@elastic/elasticsearch": { + "version": "8.13.1", + "resolved": "https://registry.npmjs.org/@elastic/elasticsearch/-/elasticsearch-8.13.1.tgz", + "integrity": "sha512-2G4Vu6OHw4+XTrp7AGIcOEezpPEoVrWg2JTK1v/exEKSLYquZkUdd+m4yOL3/UZ6bTj7hmXwrmYzW76BnLCkJQ==", + "dependencies": { + "@elastic/transport": "~8.4.1", + "tslib": "^2.4.0" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/@elastic/transport": { + "version": "8.4.1", + "resolved": "https://registry.npmjs.org/@elastic/transport/-/transport-8.4.1.tgz", + "integrity": "sha512-/SXVuVnuU5b4dq8OFY4izG+dmGla185PcoqgK6+AJMpmOeY1QYVNbWtCwvSvoAANN5D/wV+EBU8+x7Vf9EphbA==", + "dependencies": { + "debug": "^4.3.4", + "hpagent": "^1.0.0", + "ms": "^2.1.3", + "secure-json-parse": "^2.4.0", + "tslib": "^2.4.0", + "undici": "^5.22.1" + }, + "engines": { + "node": ">=16" + } + }, + "node_modules/@elastic/transport/node_modules/ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==" + }, + "node_modules/@fastify/busboy": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/@fastify/busboy/-/busboy-2.1.1.tgz", + "integrity": "sha512-vBZP4NlzfOlerQTnba4aqZoMhE/a9HY7HRqoOPaETQcSQuWEIyZMHGfVu6w9wGtGK5fED5qRs2DteVCjOH60sA==", + "engines": { + "node": ">=14" + } + }, "node_modules/@graphql-typed-document-node/core": { "version": "3.2.0", "resolved": "https://registry.npmjs.org/@graphql-typed-document-node/core/-/core-3.2.0.tgz", @@ -986,640 +1173,706 @@ } }, "node_modules/@smithy/abort-controller": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/@smithy/abort-controller/-/abort-controller-2.1.1.tgz", - "integrity": "sha512-1+qdrUqLhaALYL0iOcN43EP6yAXXQ2wWZ6taf4S2pNGowmOc5gx+iMQv+E42JizNJjB0+gEadOXeV1Bf7JWL1Q==", + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/@smithy/abort-controller/-/abort-controller-3.1.2.tgz", + "integrity": "sha512-b5g+PNujlfqIib9BjkNB108NyO5aZM/RXjfOCXRCqXQ1oPnIkfvdORrztbGgCZdPe/BN/MKDlrGA7PafKPM2jw==", + "license": "Apache-2.0", "dependencies": { - "@smithy/types": "^2.9.1", - "tslib": "^2.5.0" + "@smithy/types": "^3.4.0", + "tslib": "^2.6.2" }, "engines": { - "node": ">=14.0.0" + "node": ">=16.0.0" } }, "node_modules/@smithy/chunked-blob-reader": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/@smithy/chunked-blob-reader/-/chunked-blob-reader-2.1.1.tgz", - "integrity": "sha512-NjNFCKxC4jVvn+lUr3Yo4/PmUJj3tbyqH6GNHueyTGS5Q27vlEJ1MkNhUDV8QGxJI7Bodnc2pD18lU2zRfhHlQ==", + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@smithy/chunked-blob-reader/-/chunked-blob-reader-3.0.0.tgz", + "integrity": "sha512-sbnURCwjF0gSToGlsBiAmd1lRCmSn72nu9axfJu5lIx6RUEgHu6GwTMbqCdhQSi0Pumcm5vFxsi9XWXb2mTaoA==", + "license": "Apache-2.0", "dependencies": { - "tslib": "^2.5.0" + "tslib": "^2.6.2" } }, "node_modules/@smithy/chunked-blob-reader-native": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/@smithy/chunked-blob-reader-native/-/chunked-blob-reader-native-2.1.1.tgz", - "integrity": "sha512-zNW+43dltfNMUrBEYLMWgI8lQr0uhtTcUyxkgC9EP4j17WREzgSFMPUFVrVV6Rc2+QtWERYjb4tzZnQGa7R9fQ==", + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@smithy/chunked-blob-reader-native/-/chunked-blob-reader-native-3.0.0.tgz", + "integrity": "sha512-VDkpCYW+peSuM4zJip5WDfqvg2Mo/e8yxOv3VF1m11y7B8KKMKVFtmZWDe36Fvk8rGuWrPZHHXZ7rR7uM5yWyg==", + "license": "Apache-2.0", "dependencies": { - "@smithy/util-base64": "^2.1.1", - "tslib": "^2.5.0" + "@smithy/util-base64": "^3.0.0", + "tslib": "^2.6.2" } }, "node_modules/@smithy/config-resolver": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/@smithy/config-resolver/-/config-resolver-2.1.1.tgz", - "integrity": "sha512-lxfLDpZm+AWAHPFZps5JfDoO9Ux1764fOgvRUBpHIO8HWHcSN1dkgsago1qLRVgm1BZ8RCm8cgv99QvtaOWIhw==", + "version": "3.0.6", + "resolved": "https://registry.npmjs.org/@smithy/config-resolver/-/config-resolver-3.0.6.tgz", + "integrity": "sha512-j7HuVNoRd8EhcFp0MzcUb4fG40C7BcyshH+fAd3Jhd8bINNFvEQYBrZoS/SK6Pun9WPlfoI8uuU2SMz8DsEGlA==", + "license": "Apache-2.0", "dependencies": { - "@smithy/node-config-provider": "^2.2.1", - "@smithy/types": "^2.9.1", - "@smithy/util-config-provider": "^2.2.1", - "@smithy/util-middleware": "^2.1.1", - "tslib": "^2.5.0" + "@smithy/node-config-provider": "^3.1.5", + "@smithy/types": "^3.4.0", + "@smithy/util-config-provider": "^3.0.0", + "@smithy/util-middleware": "^3.0.4", + "tslib": "^2.6.2" }, "engines": { - "node": ">=14.0.0" + "node": ">=16.0.0" } }, "node_modules/@smithy/core": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/@smithy/core/-/core-1.3.1.tgz", - "integrity": "sha512-tf+NIu9FkOh312b6M9G4D68is4Xr7qptzaZGZUREELF8ysE1yLKphqt7nsomjKZVwW7WE5pDDex9idowNGRQ/Q==", + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/@smithy/core/-/core-2.4.1.tgz", + "integrity": "sha512-7cts7/Oni7aCHebHGiBeWoz5z+vmH+Vx2Z/UW3XtXMslcxI3PEwBZxNinepwZjixS3n12fPc247PHWmjU7ndsQ==", + "license": "Apache-2.0", "dependencies": { - "@smithy/middleware-endpoint": "^2.4.1", - "@smithy/middleware-retry": "^2.1.1", - "@smithy/middleware-serde": "^2.1.1", - "@smithy/protocol-http": "^3.1.1", - "@smithy/smithy-client": "^2.3.1", - "@smithy/types": "^2.9.1", - "@smithy/util-middleware": "^2.1.1", - "tslib": "^2.5.0" + "@smithy/middleware-endpoint": "^3.1.1", + "@smithy/middleware-retry": "^3.0.16", + "@smithy/middleware-serde": "^3.0.4", + "@smithy/protocol-http": "^4.1.1", + "@smithy/smithy-client": "^3.3.0", + "@smithy/types": "^3.4.0", + "@smithy/util-body-length-browser": "^3.0.0", + "@smithy/util-middleware": "^3.0.4", + "@smithy/util-utf8": "^3.0.0", + "tslib": "^2.6.2" }, "engines": { - "node": ">=14.0.0" + "node": ">=16.0.0" } }, "node_modules/@smithy/credential-provider-imds": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/@smithy/credential-provider-imds/-/credential-provider-imds-2.2.1.tgz", - "integrity": "sha512-7XHjZUxmZYnONheVQL7j5zvZXga+EWNgwEAP6OPZTi7l8J4JTeNh9aIOfE5fKHZ/ee2IeNOh54ZrSna+Vc6TFA==", + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/@smithy/credential-provider-imds/-/credential-provider-imds-3.2.1.tgz", + "integrity": "sha512-4z/oTWpRF2TqQI3aCM89/PWu3kim58XU4kOCTtuTJnoaS4KT95cPWMxbQfTN2vzcOe96SOKO8QouQW/+ESB1fQ==", + "license": "Apache-2.0", "dependencies": { - "@smithy/node-config-provider": "^2.2.1", - "@smithy/property-provider": "^2.1.1", - "@smithy/types": "^2.9.1", - "@smithy/url-parser": "^2.1.1", - "tslib": "^2.5.0" + "@smithy/node-config-provider": "^3.1.5", + "@smithy/property-provider": "^3.1.4", + "@smithy/types": "^3.4.0", + "@smithy/url-parser": "^3.0.4", + "tslib": "^2.6.2" }, "engines": { - "node": ">=14.0.0" + "node": ">=16.0.0" } }, "node_modules/@smithy/eventstream-codec": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/@smithy/eventstream-codec/-/eventstream-codec-2.1.1.tgz", - "integrity": "sha512-E8KYBxBIuU4c+zrpR22VsVrOPoEDzk35bQR3E+xm4k6Pa6JqzkDOdMyf9Atac5GPNKHJBdVaQ4JtjdWX2rl/nw==", + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/@smithy/eventstream-codec/-/eventstream-codec-3.1.3.tgz", + "integrity": "sha512-mKBrmhg6Zd3j07G9dkKTGmrU7pdJGTNz8LbZtIOR3QoodS5yDNqEqoXU4Eg38snZcnCAh7NPBsw5ndxtJPLiCg==", + "license": "Apache-2.0", "dependencies": { - "@aws-crypto/crc32": "3.0.0", - "@smithy/types": "^2.9.1", - "@smithy/util-hex-encoding": "^2.1.1", - "tslib": "^2.5.0" + "@aws-crypto/crc32": "5.2.0", + "@smithy/types": "^3.4.0", + "@smithy/util-hex-encoding": "^3.0.0", + "tslib": "^2.6.2" } }, "node_modules/@smithy/eventstream-serde-browser": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/@smithy/eventstream-serde-browser/-/eventstream-serde-browser-2.1.1.tgz", - "integrity": "sha512-JvEdCmGlZUay5VtlT8/kdR6FlvqTDUiJecMjXsBb0+k1H/qc9ME5n2XKPo8q/MZwEIA1GmGgYMokKGjVvMiDow==", + "version": "3.0.7", + "resolved": "https://registry.npmjs.org/@smithy/eventstream-serde-browser/-/eventstream-serde-browser-3.0.7.tgz", + "integrity": "sha512-UC4RQqyM8B0g5cX/xmWtsNgSBmZ13HrzCqoe5Ulcz6R462/egbIdfTXnayik7jkjvwOrCPL1N11Q9S+n68jPLA==", + "license": "Apache-2.0", "dependencies": { - "@smithy/eventstream-serde-universal": "^2.1.1", - "@smithy/types": "^2.9.1", - "tslib": "^2.5.0" + "@smithy/eventstream-serde-universal": "^3.0.6", + "@smithy/types": "^3.4.0", + "tslib": "^2.6.2" }, "engines": { - "node": ">=14.0.0" + "node": ">=16.0.0" } }, "node_modules/@smithy/eventstream-serde-config-resolver": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/@smithy/eventstream-serde-config-resolver/-/eventstream-serde-config-resolver-2.1.1.tgz", - "integrity": "sha512-EqNqXYp3+dk//NmW3NAgQr9bEQ7fsu/CcxQmTiq07JlaIcne/CBWpMZETyXm9w5LXkhduBsdXdlMscfDUDn2fA==", + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/@smithy/eventstream-serde-config-resolver/-/eventstream-serde-config-resolver-3.0.4.tgz", + "integrity": "sha512-saIs5rtAMpifqL7u7nc5YeE/6gkenzXpSz5NwEyhIesRWtHK+zEuYn9KY8SArZEbPSHyGxvvgKk1z86VzfUGHw==", + "license": "Apache-2.0", "dependencies": { - "@smithy/types": "^2.9.1", - "tslib": "^2.5.0" + "@smithy/types": "^3.4.0", + "tslib": "^2.6.2" }, "engines": { - "node": ">=14.0.0" + "node": ">=16.0.0" } }, "node_modules/@smithy/eventstream-serde-node": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/@smithy/eventstream-serde-node/-/eventstream-serde-node-2.1.1.tgz", - "integrity": "sha512-LF882q/aFidFNDX7uROAGxq3H0B7rjyPkV6QDn6/KDQ+CG7AFkRccjxRf1xqajq/Pe4bMGGr+VKAaoF6lELIQw==", + "version": "3.0.6", + "resolved": "https://registry.npmjs.org/@smithy/eventstream-serde-node/-/eventstream-serde-node-3.0.6.tgz", + "integrity": "sha512-gRKGBdZah3EjZZgWcsTpShq4cZ4Q4JTTe1OPob+jrftmbYj6CvpeydZbH0roO5SvBG8SI3aBZIet9TGN3zUxUw==", + "license": "Apache-2.0", "dependencies": { - "@smithy/eventstream-serde-universal": "^2.1.1", - "@smithy/types": "^2.9.1", - "tslib": "^2.5.0" + "@smithy/eventstream-serde-universal": "^3.0.6", + "@smithy/types": "^3.4.0", + "tslib": "^2.6.2" }, "engines": { - "node": ">=14.0.0" + "node": ">=16.0.0" } }, "node_modules/@smithy/eventstream-serde-universal": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/@smithy/eventstream-serde-universal/-/eventstream-serde-universal-2.1.1.tgz", - "integrity": "sha512-LR0mMT+XIYTxk4k2fIxEA1BPtW3685QlqufUEUAX1AJcfFfxNDKEvuCRZbO8ntJb10DrIFVJR9vb0MhDCi0sAQ==", + "version": "3.0.6", + "resolved": "https://registry.npmjs.org/@smithy/eventstream-serde-universal/-/eventstream-serde-universal-3.0.6.tgz", + "integrity": "sha512-1jvXd4sFG+zKaL6WqrJXpL6E+oAMafuM5GPd4qF0+ccenZTX3DZugoCCjlooQyTh+TZho2FpdVYUf5J/bB/j6Q==", + "license": "Apache-2.0", "dependencies": { - "@smithy/eventstream-codec": "^2.1.1", - "@smithy/types": "^2.9.1", - "tslib": "^2.5.0" + "@smithy/eventstream-codec": "^3.1.3", + "@smithy/types": "^3.4.0", + "tslib": "^2.6.2" }, "engines": { - "node": ">=14.0.0" + "node": ">=16.0.0" } }, "node_modules/@smithy/fetch-http-handler": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/@smithy/fetch-http-handler/-/fetch-http-handler-2.4.1.tgz", - "integrity": "sha512-VYGLinPsFqH68lxfRhjQaSkjXM7JysUOJDTNjHBuN/ykyRb2f1gyavN9+VhhPTWCy32L4yZ2fdhpCs/nStEicg==", + "version": "3.2.5", + "resolved": "https://registry.npmjs.org/@smithy/fetch-http-handler/-/fetch-http-handler-3.2.5.tgz", + "integrity": "sha512-DjRtGmK8pKQMIo9+JlAKUt14Z448bg8nAN04yKIvlrrpmpRSG57s5d2Y83npks1r4gPtTRNbAFdQCoj9l3P2KQ==", + "license": "Apache-2.0", "dependencies": { - "@smithy/protocol-http": "^3.1.1", - "@smithy/querystring-builder": "^2.1.1", - "@smithy/types": "^2.9.1", - "@smithy/util-base64": "^2.1.1", - "tslib": "^2.5.0" + "@smithy/protocol-http": "^4.1.1", + "@smithy/querystring-builder": "^3.0.4", + "@smithy/types": "^3.4.0", + "@smithy/util-base64": "^3.0.0", + "tslib": "^2.6.2" } }, "node_modules/@smithy/hash-blob-browser": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/@smithy/hash-blob-browser/-/hash-blob-browser-2.1.1.tgz", - "integrity": "sha512-jizu1+2PAUjiGIfRtlPEU8Yo6zn+d78ti/ZHDesdf1SUn2BuZW433JlPoCOLH3dBoEEvTgLvQ8tUGSoTTALA+A==", + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/@smithy/hash-blob-browser/-/hash-blob-browser-3.1.3.tgz", + "integrity": "sha512-im9wAU9mANWW0OP0YGqwX3lw0nXG0ngyIcKQ8V/MUz1r7A6uO2lpPqKmAsH4VPGNLP2JPUhj4aW/m5UKkxX/IA==", + "license": "Apache-2.0", "dependencies": { - "@smithy/chunked-blob-reader": "^2.1.1", - "@smithy/chunked-blob-reader-native": "^2.1.1", - "@smithy/types": "^2.9.1", - "tslib": "^2.5.0" + "@smithy/chunked-blob-reader": "^3.0.0", + "@smithy/chunked-blob-reader-native": "^3.0.0", + "@smithy/types": "^3.4.0", + "tslib": "^2.6.2" } }, "node_modules/@smithy/hash-node": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/@smithy/hash-node/-/hash-node-2.1.1.tgz", - "integrity": "sha512-Qhoq0N8f2OtCnvUpCf+g1vSyhYQrZjhSwvJ9qvR8BUGOtTXiyv2x1OD2e6jVGmlpC4E4ax1USHoyGfV9JFsACg==", + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/@smithy/hash-node/-/hash-node-3.0.4.tgz", + "integrity": "sha512-6FgTVqEfCr9z/7+Em8BwSkJKA2y3krf1em134x3yr2NHWVCo2KYI8tcA53cjeO47y41jwF84ntsEE0Pe6pNKlg==", + "license": "Apache-2.0", "dependencies": { - "@smithy/types": "^2.9.1", - "@smithy/util-buffer-from": "^2.1.1", - "@smithy/util-utf8": "^2.1.1", - "tslib": "^2.5.0" + "@smithy/types": "^3.4.0", + "@smithy/util-buffer-from": "^3.0.0", + "@smithy/util-utf8": "^3.0.0", + "tslib": "^2.6.2" }, "engines": { - "node": ">=14.0.0" + "node": ">=16.0.0" } }, "node_modules/@smithy/hash-stream-node": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/@smithy/hash-stream-node/-/hash-stream-node-2.1.1.tgz", - "integrity": "sha512-VgDaKcfCy0iHcmtAZgZ3Yw9g37Gkn2JsQiMtFQXUh8Wmo3GfNgDwLOtdhJ272pOT7DStzpe9cNr+eV5Au8KfQA==", + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/@smithy/hash-stream-node/-/hash-stream-node-3.1.3.tgz", + "integrity": "sha512-Tz/eTlo1ffqYn+19VaMjDDbmEWqYe4DW1PAWaS8HvgRdO6/k9hxNPt8Wv5laXoilxE20YzKugiHvxHyO6J7kGA==", + "license": "Apache-2.0", "dependencies": { - "@smithy/types": "^2.9.1", - "@smithy/util-utf8": "^2.1.1", - "tslib": "^2.5.0" + "@smithy/types": "^3.4.0", + "@smithy/util-utf8": "^3.0.0", + "tslib": "^2.6.2" }, "engines": { - "node": ">=14.0.0" + "node": ">=16.0.0" } }, "node_modules/@smithy/invalid-dependency": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/@smithy/invalid-dependency/-/invalid-dependency-2.1.1.tgz", - "integrity": "sha512-7WTgnKw+VPg8fxu2v9AlNOQ5yaz6RA54zOVB4f6vQuR0xFKd+RzlCpt0WidYTsye7F+FYDIaS/RnJW4pxjNInw==", + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/@smithy/invalid-dependency/-/invalid-dependency-3.0.4.tgz", + "integrity": "sha512-MJBUrojC4SEXi9aJcnNOE3oNAuYNphgCGFXscaCj2TA/59BTcXhzHACP8jnnEU3n4yir/NSLKzxqez0T4x4tjA==", + "license": "Apache-2.0", "dependencies": { - "@smithy/types": "^2.9.1", - "tslib": "^2.5.0" + "@smithy/types": "^3.4.0", + "tslib": "^2.6.2" } }, "node_modules/@smithy/is-array-buffer": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/@smithy/is-array-buffer/-/is-array-buffer-2.1.1.tgz", - "integrity": "sha512-xozSQrcUinPpNPNPds4S7z/FakDTh1MZWtRP/2vQtYB/u3HYrX2UXuZs+VhaKBd6Vc7g2XPr2ZtwGBNDN6fNKQ==", + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@smithy/is-array-buffer/-/is-array-buffer-3.0.0.tgz", + "integrity": "sha512-+Fsu6Q6C4RSJiy81Y8eApjEB5gVtM+oFKTffg+jSuwtvomJJrhUJBu2zS8wjXSgH/g1MKEWrzyChTBe6clb5FQ==", + "license": "Apache-2.0", "dependencies": { - "tslib": "^2.5.0" + "tslib": "^2.6.2" }, "engines": { - "node": ">=14.0.0" + "node": ">=16.0.0" } }, "node_modules/@smithy/md5-js": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/@smithy/md5-js/-/md5-js-2.1.1.tgz", - "integrity": "sha512-L3MbIYBIdLlT+MWTYrdVSv/dow1+6iZ1Ad7xS0OHxTTs17d753ZcpOV4Ro7M7tRAVWML/sg2IAp/zzCb6aAttg==", + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/@smithy/md5-js/-/md5-js-3.0.4.tgz", + "integrity": "sha512-qSlqr/+hybufIJgxQW2gYzGE6ywfOxkjjJVojbbmv4MtxfdDFfzRew+NOIOXcYgazW0f8OYBTIKsmNsjxpvnng==", + "license": "Apache-2.0", "dependencies": { - "@smithy/types": "^2.9.1", - "@smithy/util-utf8": "^2.1.1", - "tslib": "^2.5.0" + "@smithy/types": "^3.4.0", + "@smithy/util-utf8": "^3.0.0", + "tslib": "^2.6.2" } }, "node_modules/@smithy/middleware-content-length": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/@smithy/middleware-content-length/-/middleware-content-length-2.1.1.tgz", - "integrity": "sha512-rSr9ezUl9qMgiJR0UVtVOGEZElMdGFyl8FzWEF5iEKTlcWxGr2wTqGfDwtH3LAB7h+FPkxqv4ZU4cpuCN9Kf/g==", + "version": "3.0.6", + "resolved": "https://registry.npmjs.org/@smithy/middleware-content-length/-/middleware-content-length-3.0.6.tgz", + "integrity": "sha512-AFyHCfe8rumkJkz+hCOVJmBagNBj05KypyDwDElA4TgMSA4eYDZRjVePFZuyABrJZFDc7uVj3dpFIDCEhf59SA==", + "license": "Apache-2.0", "dependencies": { - "@smithy/protocol-http": "^3.1.1", - "@smithy/types": "^2.9.1", - "tslib": "^2.5.0" + "@smithy/protocol-http": "^4.1.1", + "@smithy/types": "^3.4.0", + "tslib": "^2.6.2" }, "engines": { - "node": ">=14.0.0" + "node": ">=16.0.0" } }, "node_modules/@smithy/middleware-endpoint": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/@smithy/middleware-endpoint/-/middleware-endpoint-2.4.1.tgz", - "integrity": "sha512-XPZTb1E2Oav60Ven3n2PFx+rX9EDsU/jSTA8VDamt7FXks67ekjPY/XrmmPDQaFJOTUHJNKjd8+kZxVO5Ael4Q==", + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/@smithy/middleware-endpoint/-/middleware-endpoint-3.1.1.tgz", + "integrity": "sha512-Irv+soW8NKluAtFSEsF8O3iGyLxa5oOevJb/e1yNacV9H7JP/yHyJuKST5YY2ORS1+W34VR8EuUrOF+K29Pl4g==", + "license": "Apache-2.0", "dependencies": { - "@smithy/middleware-serde": "^2.1.1", - "@smithy/node-config-provider": "^2.2.1", - "@smithy/shared-ini-file-loader": "^2.3.1", - "@smithy/types": "^2.9.1", - "@smithy/url-parser": "^2.1.1", - "@smithy/util-middleware": "^2.1.1", - "tslib": "^2.5.0" + "@smithy/middleware-serde": "^3.0.4", + "@smithy/node-config-provider": "^3.1.5", + "@smithy/shared-ini-file-loader": "^3.1.5", + "@smithy/types": "^3.4.0", + "@smithy/url-parser": "^3.0.4", + "@smithy/util-middleware": "^3.0.4", + "tslib": "^2.6.2" }, "engines": { - "node": ">=14.0.0" + "node": ">=16.0.0" } }, "node_modules/@smithy/middleware-retry": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/@smithy/middleware-retry/-/middleware-retry-2.1.1.tgz", - "integrity": "sha512-eMIHOBTXro6JZ+WWzZWd/8fS8ht5nS5KDQjzhNMHNRcG5FkNTqcKpYhw7TETMYzbLfhO5FYghHy1vqDWM4FLDA==", + "version": "3.0.16", + "resolved": "https://registry.npmjs.org/@smithy/middleware-retry/-/middleware-retry-3.0.16.tgz", + "integrity": "sha512-08kI36p1yB4CWO3Qi+UQxjzobt8iQJpnruF0K5BkbZmA/N/sJ51A1JJGJ36GgcbFyPfWw2FU48S5ZoqXt0h0jw==", + "license": "Apache-2.0", "dependencies": { - "@smithy/node-config-provider": "^2.2.1", - "@smithy/protocol-http": "^3.1.1", - "@smithy/service-error-classification": "^2.1.1", - "@smithy/smithy-client": "^2.3.1", - "@smithy/types": "^2.9.1", - "@smithy/util-middleware": "^2.1.1", - "@smithy/util-retry": "^2.1.1", - "tslib": "^2.5.0", - "uuid": "^8.3.2" + "@smithy/node-config-provider": "^3.1.5", + "@smithy/protocol-http": "^4.1.1", + "@smithy/service-error-classification": "^3.0.4", + "@smithy/smithy-client": "^3.3.0", + "@smithy/types": "^3.4.0", + "@smithy/util-middleware": "^3.0.4", + "@smithy/util-retry": "^3.0.4", + "tslib": "^2.6.2", + "uuid": "^9.0.1" }, "engines": { - "node": ">=14.0.0" + "node": ">=16.0.0" + } + }, + "node_modules/@smithy/middleware-retry/node_modules/uuid": { + "version": "9.0.1", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-9.0.1.tgz", + "integrity": "sha512-b+1eJOlsR9K8HJpow9Ok3fiWOWSIcIzXodvv0rQjVoOVNpWMpxf1wZNpt4y9h10odCNrqnYp1OBzRktckBe3sA==", + "funding": [ + "https://github.com/sponsors/broofa", + "https://github.com/sponsors/ctavan" + ], + "license": "MIT", + "bin": { + "uuid": "dist/bin/uuid" } }, "node_modules/@smithy/middleware-serde": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/@smithy/middleware-serde/-/middleware-serde-2.1.1.tgz", - "integrity": "sha512-D8Gq0aQBeE1pxf3cjWVkRr2W54t+cdM2zx78tNrVhqrDykRA7asq8yVJij1u5NDtKzKqzBSPYh7iW0svUKg76g==", + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/@smithy/middleware-serde/-/middleware-serde-3.0.4.tgz", + "integrity": "sha512-1lPDB2O6IJ50Ucxgn7XrvZXbbuI48HmPCcMTuSoXT1lDzuTUfIuBjgAjpD8YLVMfnrjdepi/q45556LA51Pubw==", + "license": "Apache-2.0", "dependencies": { - "@smithy/types": "^2.9.1", - "tslib": "^2.5.0" + "@smithy/types": "^3.4.0", + "tslib": "^2.6.2" }, "engines": { - "node": ">=14.0.0" + "node": ">=16.0.0" } }, "node_modules/@smithy/middleware-stack": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/@smithy/middleware-stack/-/middleware-stack-2.1.1.tgz", - "integrity": "sha512-KPJhRlhsl8CjgGXK/DoDcrFGfAqoqvuwlbxy+uOO4g2Azn1dhH+GVfC3RAp+6PoL5PWPb+vt6Z23FP+Mr6qeCw==", + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/@smithy/middleware-stack/-/middleware-stack-3.0.4.tgz", + "integrity": "sha512-sLMRjtMCqtVcrOqaOZ10SUnlFE25BSlmLsi4bRSGFD7dgR54eqBjfqkVkPBQyrKBortfGM0+2DJoUPcGECR+nQ==", + "license": "Apache-2.0", "dependencies": { - "@smithy/types": "^2.9.1", - "tslib": "^2.5.0" + "@smithy/types": "^3.4.0", + "tslib": "^2.6.2" }, "engines": { - "node": ">=14.0.0" + "node": ">=16.0.0" } }, "node_modules/@smithy/node-config-provider": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/@smithy/node-config-provider/-/node-config-provider-2.2.1.tgz", - "integrity": "sha512-epzK3x1xNxA9oJgHQ5nz+2j6DsJKdHfieb+YgJ7ATWxzNcB7Hc+Uya2TUck5MicOPhDV8HZImND7ZOecVr+OWg==", + "version": "3.1.5", + "resolved": "https://registry.npmjs.org/@smithy/node-config-provider/-/node-config-provider-3.1.5.tgz", + "integrity": "sha512-dq/oR3/LxgCgizVk7in7FGTm0w9a3qM4mg3IIXLTCHeW3fV+ipssSvBZ2bvEx1+asfQJTyCnVLeYf7JKfd9v3Q==", + "license": "Apache-2.0", "dependencies": { - "@smithy/property-provider": "^2.1.1", - "@smithy/shared-ini-file-loader": "^2.3.1", - "@smithy/types": "^2.9.1", - "tslib": "^2.5.0" + "@smithy/property-provider": "^3.1.4", + "@smithy/shared-ini-file-loader": "^3.1.5", + "@smithy/types": "^3.4.0", + "tslib": "^2.6.2" }, "engines": { - "node": ">=14.0.0" + "node": ">=16.0.0" } }, "node_modules/@smithy/node-http-handler": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/@smithy/node-http-handler/-/node-http-handler-2.3.1.tgz", - "integrity": "sha512-gLA8qK2nL9J0Rk/WEZSvgin4AppvuCYRYg61dcUo/uKxvMZsMInL5I5ZdJTogOvdfVug3N2dgI5ffcUfS4S9PA==", + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/@smithy/node-http-handler/-/node-http-handler-3.2.0.tgz", + "integrity": "sha512-5TFqaABbiY7uJMKbqR4OARjwI/l4TRoysDJ75pLpVQyO3EcmeloKYwDGyCtgB9WJniFx3BMkmGCB9+j+QiB+Ww==", + "license": "Apache-2.0", "dependencies": { - "@smithy/abort-controller": "^2.1.1", - "@smithy/protocol-http": "^3.1.1", - "@smithy/querystring-builder": "^2.1.1", - "@smithy/types": "^2.9.1", - "tslib": "^2.5.0" + "@smithy/abort-controller": "^3.1.2", + "@smithy/protocol-http": "^4.1.1", + "@smithy/querystring-builder": "^3.0.4", + "@smithy/types": "^3.4.0", + "tslib": "^2.6.2" }, "engines": { - "node": ">=14.0.0" + "node": ">=16.0.0" } }, "node_modules/@smithy/property-provider": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/@smithy/property-provider/-/property-provider-2.1.1.tgz", - "integrity": "sha512-FX7JhhD/o5HwSwg6GLK9zxrMUrGnb3PzNBrcthqHKBc3dH0UfgEAU24xnJ8F0uow5mj17UeBEOI6o3CF2k7Mhw==", + "version": "3.1.4", + "resolved": "https://registry.npmjs.org/@smithy/property-provider/-/property-provider-3.1.4.tgz", + "integrity": "sha512-BmhefQbfkSl9DeU0/e6k9N4sT5bya5etv2epvqLUz3eGyfRBhtQq60nDkc1WPp4c+KWrzK721cUc/3y0f2psPQ==", + "license": "Apache-2.0", "dependencies": { - "@smithy/types": "^2.9.1", - "tslib": "^2.5.0" + "@smithy/types": "^3.4.0", + "tslib": "^2.6.2" }, "engines": { - "node": ">=14.0.0" + "node": ">=16.0.0" } }, "node_modules/@smithy/protocol-http": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/@smithy/protocol-http/-/protocol-http-3.1.1.tgz", - "integrity": "sha512-6ZRTSsaXuSL9++qEwH851hJjUA0OgXdQFCs+VDw4tGH256jQ3TjYY/i34N4vd24RV3nrjNsgd1yhb57uMoKbzQ==", + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/@smithy/protocol-http/-/protocol-http-4.1.1.tgz", + "integrity": "sha512-Fm5+8LkeIus83Y8jTL1XHsBGP8sPvE1rEVyKf/87kbOPTbzEDMcgOlzcmYXat2h+nC3wwPtRy8hFqtJS71+Wow==", + "license": "Apache-2.0", "dependencies": { - "@smithy/types": "^2.9.1", - "tslib": "^2.5.0" + "@smithy/types": "^3.4.0", + "tslib": "^2.6.2" }, "engines": { - "node": ">=14.0.0" + "node": ">=16.0.0" } }, "node_modules/@smithy/querystring-builder": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/@smithy/querystring-builder/-/querystring-builder-2.1.1.tgz", - "integrity": "sha512-C/ko/CeEa8jdYE4gt6nHO5XDrlSJ3vdCG0ZAc6nD5ZIE7LBp0jCx4qoqp7eoutBu7VrGMXERSRoPqwi1WjCPbg==", + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/@smithy/querystring-builder/-/querystring-builder-3.0.4.tgz", + "integrity": "sha512-NEoPAsZPdpfVbF98qm8i5k1XMaRKeEnO47CaL5ja6Y1Z2DgJdwIJuJkTJypKm/IKfp8gc0uimIFLwhml8+/pAw==", + "license": "Apache-2.0", "dependencies": { - "@smithy/types": "^2.9.1", - "@smithy/util-uri-escape": "^2.1.1", - "tslib": "^2.5.0" + "@smithy/types": "^3.4.0", + "@smithy/util-uri-escape": "^3.0.0", + "tslib": "^2.6.2" }, "engines": { - "node": ">=14.0.0" + "node": ">=16.0.0" } }, "node_modules/@smithy/querystring-parser": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/@smithy/querystring-parser/-/querystring-parser-2.1.1.tgz", - "integrity": "sha512-H4+6jKGVhG1W4CIxfBaSsbm98lOO88tpDWmZLgkJpt8Zkk/+uG0FmmqMuCAc3HNM2ZDV+JbErxr0l5BcuIf/XQ==", + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/@smithy/querystring-parser/-/querystring-parser-3.0.4.tgz", + "integrity": "sha512-7CHPXffFcakFzhO0OZs/rn6fXlTHrSDdLhIT6/JIk1u2bvwguTL3fMCc1+CfcbXA7TOhjWXu3TcB1EGMqJQwHg==", + "license": "Apache-2.0", "dependencies": { - "@smithy/types": "^2.9.1", - "tslib": "^2.5.0" + "@smithy/types": "^3.4.0", + "tslib": "^2.6.2" }, "engines": { - "node": ">=14.0.0" + "node": ">=16.0.0" } }, "node_modules/@smithy/service-error-classification": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/@smithy/service-error-classification/-/service-error-classification-2.1.1.tgz", - "integrity": "sha512-txEdZxPUgM1PwGvDvHzqhXisrc5LlRWYCf2yyHfvITWioAKat7srQvpjMAvgzf0t6t7j8yHrryXU9xt7RZqFpw==", + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/@smithy/service-error-classification/-/service-error-classification-3.0.4.tgz", + "integrity": "sha512-KciDHHKFVTb9A1KlJHBt2F26PBaDtoE23uTZy5qRvPzHPqrooXFi6fmx98lJb3Jl38PuUTqIuCUmmY3pacuMBQ==", + "license": "Apache-2.0", "dependencies": { - "@smithy/types": "^2.9.1" + "@smithy/types": "^3.4.0" }, "engines": { - "node": ">=14.0.0" + "node": ">=16.0.0" } }, "node_modules/@smithy/shared-ini-file-loader": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/@smithy/shared-ini-file-loader/-/shared-ini-file-loader-2.3.1.tgz", - "integrity": "sha512-2E2kh24igmIznHLB6H05Na4OgIEilRu0oQpYXo3LCNRrawHAcfDKq9004zJs+sAMt2X5AbY87CUCJ7IpqpSgdw==", + "version": "3.1.5", + "resolved": "https://registry.npmjs.org/@smithy/shared-ini-file-loader/-/shared-ini-file-loader-3.1.5.tgz", + "integrity": "sha512-6jxsJ4NOmY5Du4FD0enYegNJl4zTSuKLiChIMqIkh+LapxiP7lmz5lYUNLE9/4cvA65mbBmtdzZ8yxmcqM5igg==", + "license": "Apache-2.0", "dependencies": { - "@smithy/types": "^2.9.1", - "tslib": "^2.5.0" + "@smithy/types": "^3.4.0", + "tslib": "^2.6.2" }, "engines": { - "node": ">=14.0.0" + "node": ">=16.0.0" } }, "node_modules/@smithy/signature-v4": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/@smithy/signature-v4/-/signature-v4-2.1.1.tgz", - "integrity": "sha512-Hb7xub0NHuvvQD3YwDSdanBmYukoEkhqBjqoxo+bSdC0ryV9cTfgmNjuAQhTPYB6yeU7hTR+sPRiFMlxqv6kmg==", + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/@smithy/signature-v4/-/signature-v4-4.1.1.tgz", + "integrity": "sha512-SH9J9be81TMBNGCmjhrgMWu4YSpQ3uP1L06u/K9SDrE2YibUix1qxedPCxEQu02At0P0SrYDjvz+y91vLG0KRQ==", + "license": "Apache-2.0", "dependencies": { - "@smithy/eventstream-codec": "^2.1.1", - "@smithy/is-array-buffer": "^2.1.1", - "@smithy/types": "^2.9.1", - "@smithy/util-hex-encoding": "^2.1.1", - "@smithy/util-middleware": "^2.1.1", - "@smithy/util-uri-escape": "^2.1.1", - "@smithy/util-utf8": "^2.1.1", - "tslib": "^2.5.0" + "@smithy/is-array-buffer": "^3.0.0", + "@smithy/protocol-http": "^4.1.1", + "@smithy/types": "^3.4.0", + "@smithy/util-hex-encoding": "^3.0.0", + "@smithy/util-middleware": "^3.0.4", + "@smithy/util-uri-escape": "^3.0.0", + "@smithy/util-utf8": "^3.0.0", + "tslib": "^2.6.2" }, "engines": { - "node": ">=14.0.0" + "node": ">=16.0.0" } }, "node_modules/@smithy/smithy-client": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/@smithy/smithy-client/-/smithy-client-2.3.1.tgz", - "integrity": "sha512-YsTdU8xVD64r2pLEwmltrNvZV6XIAC50LN6ivDopdt+YiF/jGH6PY9zUOu0CXD/d8GMB8gbhnpPsdrjAXHS9QA==", + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/@smithy/smithy-client/-/smithy-client-3.3.0.tgz", + "integrity": "sha512-H32nVo8tIX82kB0xI2LBrIcj8jx/3/ITotNLbeG1UL0b3b440YPR/hUvqjFJiaB24pQrMjRbU8CugqH5sV0hkw==", + "license": "Apache-2.0", "dependencies": { - "@smithy/middleware-endpoint": "^2.4.1", - "@smithy/middleware-stack": "^2.1.1", - "@smithy/protocol-http": "^3.1.1", - "@smithy/types": "^2.9.1", - "@smithy/util-stream": "^2.1.1", - "tslib": "^2.5.0" + "@smithy/middleware-endpoint": "^3.1.1", + "@smithy/middleware-stack": "^3.0.4", + "@smithy/protocol-http": "^4.1.1", + "@smithy/types": "^3.4.0", + "@smithy/util-stream": "^3.1.4", + "tslib": "^2.6.2" }, "engines": { - "node": ">=14.0.0" + "node": ">=16.0.0" } }, "node_modules/@smithy/types": { - "version": "2.9.1", - "resolved": "https://registry.npmjs.org/@smithy/types/-/types-2.9.1.tgz", - "integrity": "sha512-vjXlKNXyprDYDuJ7UW5iobdmyDm6g8dDG+BFUncAg/3XJaN45Gy5RWWWUVgrzIK7S4R1KWgIX5LeJcfvSI24bw==", + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/@smithy/types/-/types-3.4.0.tgz", + "integrity": "sha512-0shOWSg/pnFXPcsSU8ZbaJ4JBHZJPPzLCJxafJvbMVFo9l1w81CqpgUqjlKGNHVrVB7fhIs+WS82JDTyzaLyLA==", + "license": "Apache-2.0", "dependencies": { - "tslib": "^2.5.0" + "tslib": "^2.6.2" }, "engines": { - "node": ">=14.0.0" + "node": ">=16.0.0" } }, "node_modules/@smithy/url-parser": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/@smithy/url-parser/-/url-parser-2.1.1.tgz", - "integrity": "sha512-qC9Bv8f/vvFIEkHsiNrUKYNl8uKQnn4BdhXl7VzQRP774AwIjiSMMwkbT+L7Fk8W8rzYVifzJNYxv1HwvfBo3Q==", + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/@smithy/url-parser/-/url-parser-3.0.4.tgz", + "integrity": "sha512-XdXfObA8WrloavJYtDuzoDhJAYc5rOt+FirFmKBRKaihu7QtU/METAxJgSo7uMK6hUkx0vFnqxV75urtRaLkLg==", + "license": "Apache-2.0", "dependencies": { - "@smithy/querystring-parser": "^2.1.1", - "@smithy/types": "^2.9.1", - "tslib": "^2.5.0" + "@smithy/querystring-parser": "^3.0.4", + "@smithy/types": "^3.4.0", + "tslib": "^2.6.2" } }, "node_modules/@smithy/util-base64": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/@smithy/util-base64/-/util-base64-2.1.1.tgz", - "integrity": "sha512-UfHVpY7qfF/MrgndI5PexSKVTxSZIdz9InghTFa49QOvuu9I52zLPLUHXvHpNuMb1iD2vmc6R+zbv/bdMipR/g==", + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@smithy/util-base64/-/util-base64-3.0.0.tgz", + "integrity": "sha512-Kxvoh5Qtt0CDsfajiZOCpJxgtPHXOKwmM+Zy4waD43UoEMA+qPxxa98aE/7ZhdnBFZFXMOiBR5xbcaMhLtznQQ==", + "license": "Apache-2.0", "dependencies": { - "@smithy/util-buffer-from": "^2.1.1", - "tslib": "^2.5.0" + "@smithy/util-buffer-from": "^3.0.0", + "@smithy/util-utf8": "^3.0.0", + "tslib": "^2.6.2" }, "engines": { - "node": ">=14.0.0" + "node": ">=16.0.0" } }, "node_modules/@smithy/util-body-length-browser": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/@smithy/util-body-length-browser/-/util-body-length-browser-2.1.1.tgz", - "integrity": "sha512-ekOGBLvs1VS2d1zM2ER4JEeBWAvIOUKeaFch29UjjJsxmZ/f0L3K3x0dEETgh3Q9bkZNHgT+rkdl/J/VUqSRag==", + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@smithy/util-body-length-browser/-/util-body-length-browser-3.0.0.tgz", + "integrity": "sha512-cbjJs2A1mLYmqmyVl80uoLTJhAcfzMOyPgjwAYusWKMdLeNtzmMz9YxNl3/jRLoxSS3wkqkf0jwNdtXWtyEBaQ==", + "license": "Apache-2.0", "dependencies": { - "tslib": "^2.5.0" + "tslib": "^2.6.2" } }, "node_modules/@smithy/util-body-length-node": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/@smithy/util-body-length-node/-/util-body-length-node-2.2.1.tgz", - "integrity": "sha512-/ggJG+ta3IDtpNVq4ktmEUtOkH1LW64RHB5B0hcr5ZaWBmo96UX2cIOVbjCqqDickTXqBWZ4ZO0APuaPrD7Abg==", + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@smithy/util-body-length-node/-/util-body-length-node-3.0.0.tgz", + "integrity": "sha512-Tj7pZ4bUloNUP6PzwhN7K386tmSmEET9QtQg0TgdNOnxhZvCssHji+oZTUIuzxECRfG8rdm2PMw2WCFs6eIYkA==", + "license": "Apache-2.0", "dependencies": { - "tslib": "^2.5.0" + "tslib": "^2.6.2" }, "engines": { - "node": ">=14.0.0" + "node": ">=16.0.0" } }, "node_modules/@smithy/util-buffer-from": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/@smithy/util-buffer-from/-/util-buffer-from-2.1.1.tgz", - "integrity": "sha512-clhNjbyfqIv9Md2Mg6FffGVrJxw7bgK7s3Iax36xnfVj6cg0fUG7I4RH0XgXJF8bxi+saY5HR21g2UPKSxVCXg==", + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@smithy/util-buffer-from/-/util-buffer-from-3.0.0.tgz", + "integrity": "sha512-aEOHCgq5RWFbP+UDPvPot26EJHjOC+bRgse5A8V3FSShqd5E5UN4qc7zkwsvJPPAVsf73QwYcHN1/gt/rtLwQA==", + "license": "Apache-2.0", "dependencies": { - "@smithy/is-array-buffer": "^2.1.1", - "tslib": "^2.5.0" + "@smithy/is-array-buffer": "^3.0.0", + "tslib": "^2.6.2" }, "engines": { - "node": ">=14.0.0" + "node": ">=16.0.0" } }, "node_modules/@smithy/util-config-provider": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/@smithy/util-config-provider/-/util-config-provider-2.2.1.tgz", - "integrity": "sha512-50VL/tx9oYYcjJn/qKqNy7sCtpD0+s8XEBamIFo4mFFTclKMNp+rsnymD796uybjiIquB7VCB/DeafduL0y2kw==", + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@smithy/util-config-provider/-/util-config-provider-3.0.0.tgz", + "integrity": "sha512-pbjk4s0fwq3Di/ANL+rCvJMKM5bzAQdE5S/6RL5NXgMExFAi6UgQMPOm5yPaIWPpr+EOXKXRonJ3FoxKf4mCJQ==", + "license": "Apache-2.0", "dependencies": { - "tslib": "^2.5.0" + "tslib": "^2.6.2" }, "engines": { - "node": ">=14.0.0" + "node": ">=16.0.0" } }, "node_modules/@smithy/util-defaults-mode-browser": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/@smithy/util-defaults-mode-browser/-/util-defaults-mode-browser-2.1.1.tgz", - "integrity": "sha512-lqLz/9aWRO6mosnXkArtRuQqqZBhNpgI65YDpww4rVQBuUT7qzKbDLG5AmnQTCiU4rOquaZO/Kt0J7q9Uic7MA==", - "dependencies": { - "@smithy/property-provider": "^2.1.1", - "@smithy/smithy-client": "^2.3.1", - "@smithy/types": "^2.9.1", + "version": "3.0.16", + "resolved": "https://registry.npmjs.org/@smithy/util-defaults-mode-browser/-/util-defaults-mode-browser-3.0.16.tgz", + "integrity": "sha512-Os8ddfNBe7hmc5UMWZxygIHCyAqY0aWR8Wnp/aKbti3f8Df/r0J9ttMZIxeMjsFgtVjEryB0q7SGcwBsHk8WEw==", + "license": "Apache-2.0", + "dependencies": { + "@smithy/property-provider": "^3.1.4", + "@smithy/smithy-client": "^3.3.0", + "@smithy/types": "^3.4.0", "bowser": "^2.11.0", - "tslib": "^2.5.0" + "tslib": "^2.6.2" }, "engines": { "node": ">= 10.0.0" } }, "node_modules/@smithy/util-defaults-mode-node": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/@smithy/util-defaults-mode-node/-/util-defaults-mode-node-2.1.1.tgz", - "integrity": "sha512-tYVrc+w+jSBfBd267KDnvSGOh4NMz+wVH7v4CClDbkdPfnjvImBZsOURncT5jsFwR9KCuDyPoSZq4Pa6+eCUrA==", + "version": "3.0.16", + "resolved": "https://registry.npmjs.org/@smithy/util-defaults-mode-node/-/util-defaults-mode-node-3.0.16.tgz", + "integrity": "sha512-rNhFIYRtrOrrhRlj6RL8jWA6/dcwrbGYAmy8+OAHjjzQ6zdzUBB1P+3IuJAgwWN6Y5GxI+mVXlM/pOjaoIgHow==", + "license": "Apache-2.0", "dependencies": { - "@smithy/config-resolver": "^2.1.1", - "@smithy/credential-provider-imds": "^2.2.1", - "@smithy/node-config-provider": "^2.2.1", - "@smithy/property-provider": "^2.1.1", - "@smithy/smithy-client": "^2.3.1", - "@smithy/types": "^2.9.1", - "tslib": "^2.5.0" + "@smithy/config-resolver": "^3.0.6", + "@smithy/credential-provider-imds": "^3.2.1", + "@smithy/node-config-provider": "^3.1.5", + "@smithy/property-provider": "^3.1.4", + "@smithy/smithy-client": "^3.3.0", + "@smithy/types": "^3.4.0", + "tslib": "^2.6.2" }, "engines": { "node": ">= 10.0.0" } }, "node_modules/@smithy/util-endpoints": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/@smithy/util-endpoints/-/util-endpoints-1.1.1.tgz", - "integrity": "sha512-sI4d9rjoaekSGEtq3xSb2nMjHMx8QXcz2cexnVyRWsy4yQ9z3kbDpX+7fN0jnbdOp0b3KSTZJZ2Yb92JWSanLw==", + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/@smithy/util-endpoints/-/util-endpoints-2.1.0.tgz", + "integrity": "sha512-ilS7/0jcbS2ELdg0fM/4GVvOiuk8/U3bIFXUW25xE1Vh1Ol4DP6vVHQKqM40rCMizCLmJ9UxK+NeJrKlhI3HVA==", + "license": "Apache-2.0", "dependencies": { - "@smithy/node-config-provider": "^2.2.1", - "@smithy/types": "^2.9.1", - "tslib": "^2.5.0" + "@smithy/node-config-provider": "^3.1.5", + "@smithy/types": "^3.4.0", + "tslib": "^2.6.2" }, "engines": { - "node": ">= 14.0.0" + "node": ">=16.0.0" } }, "node_modules/@smithy/util-hex-encoding": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/@smithy/util-hex-encoding/-/util-hex-encoding-2.1.1.tgz", - "integrity": "sha512-3UNdP2pkYUUBGEXzQI9ODTDK+Tcu1BlCyDBaRHwyxhA+8xLP8agEKQq4MGmpjqb4VQAjq9TwlCQX0kP6XDKYLg==", + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@smithy/util-hex-encoding/-/util-hex-encoding-3.0.0.tgz", + "integrity": "sha512-eFndh1WEK5YMUYvy3lPlVmYY/fZcQE1D8oSf41Id2vCeIkKJXPcYDCZD+4+xViI6b1XSd7tE+s5AmXzz5ilabQ==", + "license": "Apache-2.0", "dependencies": { - "tslib": "^2.5.0" + "tslib": "^2.6.2" }, "engines": { - "node": ">=14.0.0" + "node": ">=16.0.0" } }, "node_modules/@smithy/util-middleware": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/@smithy/util-middleware/-/util-middleware-2.1.1.tgz", - "integrity": "sha512-mKNrk8oz5zqkNcbcgAAepeJbmfUW6ogrT2Z2gDbIUzVzNAHKJQTYmH9jcy0jbWb+m7ubrvXKb6uMjkSgAqqsFA==", + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/@smithy/util-middleware/-/util-middleware-3.0.4.tgz", + "integrity": "sha512-uSXHTBhstb1c4nHdmQEdkNMv9LiRNaJ/lWV2U/GO+5F236YFpdPw+hyWI9Zc0Rp9XKzwD9kVZvhZmEgp0UCVnA==", + "license": "Apache-2.0", "dependencies": { - "@smithy/types": "^2.9.1", - "tslib": "^2.5.0" + "@smithy/types": "^3.4.0", + "tslib": "^2.6.2" }, "engines": { - "node": ">=14.0.0" + "node": ">=16.0.0" } }, "node_modules/@smithy/util-retry": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/@smithy/util-retry/-/util-retry-2.1.1.tgz", - "integrity": "sha512-Mg+xxWPTeSPrthpC5WAamJ6PW4Kbo01Fm7lWM1jmGRvmrRdsd3192Gz2fBXAMURyXpaNxyZf6Hr/nQ4q70oVEA==", + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/@smithy/util-retry/-/util-retry-3.0.4.tgz", + "integrity": "sha512-JJr6g0tO1qO2tCQyK+n3J18r34ZpvatlFN5ULcLranFIBZPxqoivb77EPyNTVwTGMEvvq2qMnyjm4jMIxjdLFg==", + "license": "Apache-2.0", "dependencies": { - "@smithy/service-error-classification": "^2.1.1", - "@smithy/types": "^2.9.1", - "tslib": "^2.5.0" + "@smithy/service-error-classification": "^3.0.4", + "@smithy/types": "^3.4.0", + "tslib": "^2.6.2" }, "engines": { - "node": ">= 14.0.0" + "node": ">=16.0.0" } }, "node_modules/@smithy/util-stream": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/@smithy/util-stream/-/util-stream-2.1.1.tgz", - "integrity": "sha512-J7SMIpUYvU4DQN55KmBtvaMc7NM3CZ2iWICdcgaovtLzseVhAqFRYqloT3mh0esrFw+3VEK6nQFteFsTqZSECQ==", + "version": "3.1.4", + "resolved": "https://registry.npmjs.org/@smithy/util-stream/-/util-stream-3.1.4.tgz", + "integrity": "sha512-txU3EIDLhrBZdGfon6E9V6sZz/irYnKFMblz4TLVjyq8hObNHNS2n9a2t7GIrl7d85zgEPhwLE0gANpZsvpsKg==", + "license": "Apache-2.0", "dependencies": { - "@smithy/fetch-http-handler": "^2.4.1", - "@smithy/node-http-handler": "^2.3.1", - "@smithy/types": "^2.9.1", - "@smithy/util-base64": "^2.1.1", - "@smithy/util-buffer-from": "^2.1.1", - "@smithy/util-hex-encoding": "^2.1.1", - "@smithy/util-utf8": "^2.1.1", - "tslib": "^2.5.0" + "@smithy/fetch-http-handler": "^3.2.5", + "@smithy/node-http-handler": "^3.2.0", + "@smithy/types": "^3.4.0", + "@smithy/util-base64": "^3.0.0", + "@smithy/util-buffer-from": "^3.0.0", + "@smithy/util-hex-encoding": "^3.0.0", + "@smithy/util-utf8": "^3.0.0", + "tslib": "^2.6.2" }, "engines": { - "node": ">=14.0.0" + "node": ">=16.0.0" } }, "node_modules/@smithy/util-uri-escape": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/@smithy/util-uri-escape/-/util-uri-escape-2.1.1.tgz", - "integrity": "sha512-saVzI1h6iRBUVSqtnlOnc9ssU09ypo7n+shdQ8hBTZno/9rZ3AuRYvoHInV57VF7Qn7B+pFJG7qTzFiHxWlWBw==", + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@smithy/util-uri-escape/-/util-uri-escape-3.0.0.tgz", + "integrity": "sha512-LqR7qYLgZTD7nWLBecUi4aqolw8Mhza9ArpNEQ881MJJIU2sE5iHCK6TdyqqzcDLy0OPe10IY4T8ctVdtynubg==", + "license": "Apache-2.0", "dependencies": { - "tslib": "^2.5.0" + "tslib": "^2.6.2" }, "engines": { - "node": ">=14.0.0" + "node": ">=16.0.0" } }, "node_modules/@smithy/util-utf8": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/@smithy/util-utf8/-/util-utf8-2.1.1.tgz", - "integrity": "sha512-BqTpzYEcUMDwAKr7/mVRUtHDhs6ZoXDi9NypMvMfOr/+u1NW7JgqodPDECiiLboEm6bobcPcECxzjtQh865e9A==", + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@smithy/util-utf8/-/util-utf8-3.0.0.tgz", + "integrity": "sha512-rUeT12bxFnplYDe815GXbq/oixEGHfRFFtcTF3YdDi/JaENIM6aSYYLJydG83UNzLXeRI5K8abYd/8Sp/QM0kA==", + "license": "Apache-2.0", "dependencies": { - "@smithy/util-buffer-from": "^2.1.1", - "tslib": "^2.5.0" + "@smithy/util-buffer-from": "^3.0.0", + "tslib": "^2.6.2" }, "engines": { - "node": ">=14.0.0" + "node": ">=16.0.0" } }, "node_modules/@smithy/util-waiter": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/@smithy/util-waiter/-/util-waiter-2.1.1.tgz", - "integrity": "sha512-kYy6BLJJNif+uqNENtJqWdXcpqo1LS+nj1AfXcDhOpqpSHJSAkVySLyZV9fkmuVO21lzGoxjvd1imGGJHph/IA==", + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/@smithy/util-waiter/-/util-waiter-3.1.3.tgz", + "integrity": "sha512-OU0YllH51/CxD8iyr3UHSMwYqTGTyuxFdCMH/0F978t+iDmJseC/ttrWPb22zmYkhkrjqtipzC1xaMuax5QKIA==", + "license": "Apache-2.0", "dependencies": { - "@smithy/abort-controller": "^2.1.1", - "@smithy/types": "^2.9.1", - "tslib": "^2.5.0" + "@smithy/abort-controller": "^3.1.2", + "@smithy/types": "^3.4.0", + "tslib": "^2.6.2" }, "engines": { - "node": ">=14.0.0" + "node": ">=16.0.0" } }, "node_modules/@supercharge/promise-pool": { @@ -1778,11 +2031,12 @@ "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==" }, "node_modules/axios": { - "version": "1.6.7", - "resolved": "https://registry.npmjs.org/axios/-/axios-1.6.7.tgz", - "integrity": "sha512-/hDJGff6/c7u0hDkvkGxR/oy6CbCs8ziCsC7SqmhjfozqiJGc8Z11wrv9z9lYfY4K8l+H9TpjcMDX0xOZmx+RA==", + "version": "1.7.7", + "resolved": "https://registry.npmjs.org/axios/-/axios-1.7.7.tgz", + "integrity": "sha512-S4kL7XrjgBmvdGut0sN3yJxqYzrDOnivkBiN0OFs6hLiUam3UPvswUo0kqGyhqUZGEOytHyumEdXsAkgCOUf3Q==", + "license": "MIT", "dependencies": { - "follow-redirects": "^1.15.4", + "follow-redirects": "^1.15.6", "form-data": "^4.0.0", "proxy-from-env": "^1.1.0" } @@ -1835,7 +2089,8 @@ "node_modules/bowser": { "version": "2.11.0", "resolved": "https://registry.npmjs.org/bowser/-/bowser-2.11.0.tgz", - "integrity": "sha512-AlcaJBi/pqqJBIQ8U9Mcpc9i8Aqxn88Skv5d+xBX006BY5u8N3mGLHa5Lgppa7L/HfwgwLgZ6NYs+Ag6uUmJRA==" + "integrity": "sha512-AlcaJBi/pqqJBIQ8U9Mcpc9i8Aqxn88Skv5d+xBX006BY5u8N3mGLHa5Lgppa7L/HfwgwLgZ6NYs+Ag6uUmJRA==", + "license": "MIT" }, "node_modules/brace-expansion": { "version": "2.0.1", @@ -2082,9 +2337,9 @@ } }, "node_modules/ethers": { - "version": "6.10.0", - "resolved": "https://registry.npmjs.org/ethers/-/ethers-6.10.0.tgz", - "integrity": "sha512-nMNwYHzs6V1FR3Y4cdfxSQmNgZsRj1RiTU25JwvnJLmyzw9z3SKxNc2XKDuiXXo/v9ds5Mp9m6HBabgYQQ26tA==", + "version": "6.13.2", + "resolved": "https://registry.npmjs.org/ethers/-/ethers-6.13.2.tgz", + "integrity": "sha512-9VkriTTed+/27BGuY1s0hf441kqwHJ1wtN2edksEtiRvXx+soxRX3iSXTfFqq2+YwrOqbDoTHjIhQnjJRlzKmg==", "funding": [ { "type": "individual", @@ -2095,14 +2350,15 @@ "url": "https://www.buymeacoffee.com/ricmoo" } ], + "license": "MIT", "dependencies": { - "@adraffy/ens-normalize": "1.10.0", + "@adraffy/ens-normalize": "1.10.1", "@noble/curves": "1.2.0", "@noble/hashes": "1.3.2", "@types/node": "18.15.13", "aes-js": "4.0.0-beta.5", "tslib": "2.4.0", - "ws": "8.5.0" + "ws": "8.17.1" }, "engines": { "node": ">=14.0.0" @@ -2144,19 +2400,20 @@ } }, "node_modules/fast-xml-parser": { - "version": "4.2.5", - "resolved": "https://registry.npmjs.org/fast-xml-parser/-/fast-xml-parser-4.2.5.tgz", - "integrity": "sha512-B9/wizE4WngqQftFPmdaMYlXoJlJOYxGQOanC77fq9k8+Z0v5dDSVh+3glErdIROP//s/jgb7ZuxKfB8nVyo0g==", + "version": "4.4.1", + "resolved": "https://registry.npmjs.org/fast-xml-parser/-/fast-xml-parser-4.4.1.tgz", + "integrity": "sha512-xkjOecfnKGkSsOwtZ5Pz7Us/T6mrbPQrq0nh+aCO5V9nk5NLWmasAHumTKjiPJPWANe+kAZ84Jc8ooJkzZ88Sw==", "funding": [ - { - "type": "paypal", - "url": "https://paypal.me/naturalintelligence" - }, { "type": "github", "url": "https://github.com/sponsors/NaturalIntelligence" + }, + { + "type": "paypal", + "url": "https://paypal.me/naturalintelligence" } ], + "license": "MIT", "dependencies": { "strnum": "^1.0.5" }, @@ -2180,9 +2437,9 @@ } }, "node_modules/follow-redirects": { - "version": "1.15.5", - "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.5.tgz", - "integrity": "sha512-vSFWUON1B+yAw1VN4xMfxgn5fTUiaOzAJCKBwIIgT/+7CuGy9+r+5gITvP62j3RmaD5Ph65UaERdOSRGUzZtgw==", + "version": "1.15.6", + "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.6.tgz", + "integrity": "sha512-wWN62YITEaOpSK584EZXJafH1AGpO8RVgElfkuXbTOrPX4fIfOyEpW/CsiNd8JdYrAoOvafRTOEnvsO++qCqFA==", "funding": [ { "type": "individual", @@ -2314,6 +2571,14 @@ "node": ">=8" } }, + "node_modules/hpagent": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/hpagent/-/hpagent-1.2.0.tgz", + "integrity": "sha512-A91dYTeIB6NoXG+PxTQpCCDDnfHsW9kc06Lvpu1TEe9gnd6ZFeiBoRO9JvzEv6xK7EX97/dUE8g/vBMTqTS3CA==", + "engines": { + "node": ">=14" + } + }, "node_modules/iconv-lite": { "version": "0.4.24", "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", @@ -3186,6 +3451,11 @@ "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", "dev": true }, + "node_modules/secure-json-parse": { + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/secure-json-parse/-/secure-json-parse-2.7.0.tgz", + "integrity": "sha512-6aU+Rwsezw7VR8/nyvKTx8QpWH9FrcYiXXlqC4z5d5XQBDRqtbfsRjnwGyqbi3gddNtWHuEk9OANUotL26qKUw==" + }, "node_modules/semver": { "version": "7.6.0", "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.0.tgz", @@ -3370,7 +3640,8 @@ "node_modules/strnum": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/strnum/-/strnum-1.0.5.tgz", - "integrity": "sha512-J8bbNyKKXl5qYcR36TIO8W3mVGVHrmmxsd5PAItGkmyzwJvybiw2IVq5nqd0i4LSNSkB/sx9VHllbfFdr9k1JA==" + "integrity": "sha512-J8bbNyKKXl5qYcR36TIO8W3mVGVHrmmxsd5PAItGkmyzwJvybiw2IVq5nqd0i4LSNSkB/sx9VHllbfFdr9k1JA==", + "license": "MIT" }, "node_modules/supports-color": { "version": "7.2.0", @@ -3490,6 +3761,17 @@ "node": ">=14.17" } }, + "node_modules/undici": { + "version": "5.28.4", + "resolved": "https://registry.npmjs.org/undici/-/undici-5.28.4.tgz", + "integrity": "sha512-72RFADWFqKmUb2hmmvNODKL3p9hcB6Gt2DOQMis1SEBaV6a4MH8soBvzg+95CYhCKPFedut2JY9bMfrDl9D23g==", + "dependencies": { + "@fastify/busboy": "^2.0.0" + }, + "engines": { + "node": ">=14.0" + } + }, "node_modules/undici-types": { "version": "5.26.5", "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-5.26.5.tgz", @@ -3602,15 +3884,16 @@ } }, "node_modules/ws": { - "version": "8.5.0", - "resolved": "https://registry.npmjs.org/ws/-/ws-8.5.0.tgz", - "integrity": "sha512-BWX0SWVgLPzYwF8lTzEy1egjhS4S4OEAHfsO8o65WOVsrnSRGaSiUaa9e0ggGlkMTtBlmOpEXiie9RUcBO86qg==", + "version": "8.17.1", + "resolved": "https://registry.npmjs.org/ws/-/ws-8.17.1.tgz", + "integrity": "sha512-6XQFvXTkbfUOZOKKILFG1PDK2NDQs4azKQl26T0YS5CxqWLgXajbPZ+h4gZekJyRqFU8pvnbAbbs/3TgRPy+GQ==", + "license": "MIT", "engines": { "node": ">=10.0.0" }, "peerDependencies": { "bufferutil": "^4.0.1", - "utf-8-validate": "^5.0.2" + "utf-8-validate": ">=5.0.2" }, "peerDependenciesMeta": { "bufferutil": { diff --git a/package.json b/package.json index b224fae1d1..d8e3955e9d 100644 --- a/package.json +++ b/package.json @@ -4,10 +4,9 @@ "description": "", "main": "index.js", "scripts": { - "update-submodules": "git submodule update --init --recursive --remote --merge", - "test": "yarn run update-submodules && ts-node --transpile-only cli/testAdapter.ts", - "ts-check": "yarn run update-submodules && tsc --project tsconfig.json", - "ts-check-cli": "yarn run update-submodules && tsc --project tsconfig.cli.json", + "test": "ts-node --transpile-only cli/testAdapter.ts", + "ts-check": "tsc --project tsconfig.json", + "ts-check-cli": "tsc --project tsconfig.cli.json", "use-token-labels": "node helpers/useTokenLabels.js", "interactive": "node cli/interactive.js" }, diff --git a/protocols/alita-finance/index.ts b/protocols/alita-finance/index.ts index e254015c94..15a38b9a56 100644 --- a/protocols/alita-finance/index.ts +++ b/protocols/alita-finance/index.ts @@ -1,10 +1,10 @@ -import { univ2Adapter } from "../../helpers/getUniSubgraphVolume"; +import { graph } from "@defillama/sdk"; import { CHAIN } from "../../helpers/chains"; -import { univ2DimensionAdapter } from "../../helpers/getUniSubgraph"; +import { univ2DimensionAdapter2 } from "../../helpers/getUniSubgraph"; -const adapter = univ2DimensionAdapter({ +const adapter = univ2DimensionAdapter2({ graphUrls: { - [CHAIN.BSC]: "https://api.thegraph.com/subgraphs/name/alita-finance/exchangev2" + [CHAIN.BSC]: graph.modifyEndpoint('FBPHPJNE1jX18Lz8rgscvsigfxAUXakUC8w9KMid4dDz') }, feesPercent: { type: "volume", @@ -24,5 +24,6 @@ const adapter = univ2DimensionAdapter({ } }); + adapter.adapter.bsc.start = 1629947542; export default adapter; diff --git a/protocols/apertureSwap.ts b/protocols/apertureSwap.ts new file mode 100644 index 0000000000..515df56a44 --- /dev/null +++ b/protocols/apertureSwap.ts @@ -0,0 +1,7 @@ +import { uniV3Exports } from "../helpers/uniswap"; + +export default uniV3Exports({ + manta: { + factory: '0x5bd1F6735B80e58aAC88B8A94836854d3068a13a', + } +}) \ No newline at end of file diff --git a/protocols/arthswap-v3.ts b/protocols/arthswap-v3.ts new file mode 100644 index 0000000000..360ad2833c --- /dev/null +++ b/protocols/arthswap-v3.ts @@ -0,0 +1,10 @@ +import { uniV3Exports } from "../helpers/uniswap"; + +export default uniV3Exports({ + astar: { + factory: '0x69E92b56e4BF4C0FFa2cFB087c7EA47E846a7244', + }, + astrzk: { + factory: '0xAeaaf0e2c81Af264101B9129C00F4440cCF0F720', + } +}) \ No newline at end of file diff --git a/protocols/bitgenie-amm.ts b/protocols/bitgenie-amm.ts new file mode 100644 index 0000000000..d9bee6741e --- /dev/null +++ b/protocols/bitgenie-amm.ts @@ -0,0 +1,7 @@ +import { uniV2Exports } from "../helpers/uniswap"; + +export default uniV2Exports({ + merlin: { + factory: '0xEa51E2E458aE7Cb921d47fC463Ac4fED7ae65a41', + } +}) \ No newline at end of file diff --git a/protocols/blasterswap-v3.ts b/protocols/blasterswap-v3.ts new file mode 100644 index 0000000000..33a62fd19f --- /dev/null +++ b/protocols/blasterswap-v3.ts @@ -0,0 +1,7 @@ +import { uniV3Exports } from "../helpers/uniswap"; + +export default uniV3Exports({ + blast: { + factory: '0x1A8027625C830aAC43aD82a3f7cD6D5fdCE89d78', + } +}) diff --git a/protocols/blasterswap.ts b/protocols/blasterswap.ts new file mode 100644 index 0000000000..922652a0c2 --- /dev/null +++ b/protocols/blasterswap.ts @@ -0,0 +1,7 @@ +import { uniV2Exports } from "../helpers/uniswap"; + +export default uniV2Exports({ + blast: { + factory: '0x9CC1599D4378Ea41d444642D18AA9Be44f709ffD', + } +}) \ No newline at end of file diff --git a/protocols/cleopatra-v2.ts b/protocols/cleopatra-v2.ts new file mode 100644 index 0000000000..a9b0d96935 --- /dev/null +++ b/protocols/cleopatra-v2.ts @@ -0,0 +1,7 @@ +import { uniV2Exports } from "../helpers/uniswap"; + +export default uniV2Exports({ + mantle: { + factory: '0xAAA16c016BF556fcD620328f0759252E29b1AB57', + } +}) \ No newline at end of file diff --git a/protocols/dtx-v3.ts b/protocols/dtx-v3.ts new file mode 100644 index 0000000000..8e089679e1 --- /dev/null +++ b/protocols/dtx-v3.ts @@ -0,0 +1,7 @@ +import { uniV3Exports } from "../helpers/uniswap"; + +export default uniV3Exports({ + taiko: { + factory: '0xfCA1AEf282A99390B62Ca8416a68F5747716260c', + } +}) \ No newline at end of file diff --git a/protocols/eddyfinance-v2.ts b/protocols/eddyfinance-v2.ts new file mode 100644 index 0000000000..419127fca9 --- /dev/null +++ b/protocols/eddyfinance-v2.ts @@ -0,0 +1,7 @@ +import { uniV2Exports } from "../helpers/uniswap"; + +export default uniV2Exports({ + zeta: { + factory: '0x9fd96203f7b22bCF72d9DCb40ff98302376cE09c', + } +}) \ No newline at end of file diff --git a/protocols/infusion.ts b/protocols/infusion.ts new file mode 100644 index 0000000000..bf9540c161 --- /dev/null +++ b/protocols/infusion.ts @@ -0,0 +1,7 @@ +import { uniV2Exports } from "../helpers/uniswap"; + +export default uniV2Exports({ + base: { + factory: '0x2D9A3a2bd6400eE28d770c7254cA840c82faf23f', + } +}) \ No newline at end of file diff --git a/protocols/kim-exchange-v2.ts b/protocols/kim-exchange-v2.ts new file mode 100644 index 0000000000..322837e43d --- /dev/null +++ b/protocols/kim-exchange-v2.ts @@ -0,0 +1,7 @@ +import { uniV2Exports } from "../helpers/uniswap"; + +export default uniV2Exports({ + mode: { + factory: '0xc02155946dd8C89D3D3238A6c8A64D04E2CD4500', + } +}) \ No newline at end of file diff --git a/protocols/kim-exchange-v3.ts b/protocols/kim-exchange-v3.ts new file mode 100644 index 0000000000..0bf5f3410e --- /dev/null +++ b/protocols/kim-exchange-v3.ts @@ -0,0 +1,9 @@ +import { uniV3Exports } from "../helpers/uniswap"; + +const poolEvent = 'event Pool(address indexed token0,address indexed token1,address pool)' +export default uniV3Exports({ + mode: { + poolCreatedEvent: poolEvent, + factory: '0xB5F00c2C5f8821155D8ed27E31932CFD9DB3C5D5', + }, +}) diff --git a/protocols/magicsea-lb/index.ts b/protocols/magicsea-lb/index.ts new file mode 100644 index 0000000000..1c7170f16b --- /dev/null +++ b/protocols/magicsea-lb/index.ts @@ -0,0 +1,61 @@ +import { ChainBlocks, FetchOptions, IJSON, SimpleAdapter } from "../../adapters/types"; +import { CHAIN } from "../../helpers/chains"; +import { addOneToken } from "../../helpers/prices"; +import { filterPools } from "../../helpers/uniswap"; + +const event_swap = 'event Swap(address indexed sender, address indexed to, uint24 id, bytes32 amountsIn, bytes32 amountsOut, uint24 volatilityAccumulator, bytes32 totalFees, bytes32 protocolFees)'; +const FACTORY_ADDRESS = '0x8Cce20D17aB9C6F60574e678ca96711D907fD08c'; + +type TABI = { + [k: string]: string; +} +const ABIs: TABI = { + "getNumberOfLBPairs": "uint256:getNumberOfLBPairs", + "getLBPairAtIndex": "function getLBPairAtIndex(uint256 index) view returns (address lbPair)" +} + +const fetch: any = async (timestamp: number, _: ChainBlocks, { getLogs, api, createBalances }: FetchOptions) => { + const dailyVolume = createBalances(); + const dailyFees = createBalances(); + const dailyRevenue = createBalances(); + const lpTokens = await api.fetchList({ lengthAbi: ABIs.getNumberOfLBPairs, itemAbi: ABIs.getLBPairAtIndex, target: FACTORY_ADDRESS }) + const [tokens0, tokens1] = await Promise.all(['address:getTokenX', 'address:getTokenY'].map((abi: string) => api.multiCall({ abi, calls: lpTokens }))); + + + const pairObject: IJSON = {} + lpTokens.forEach((pair: string, i: number) => { + pairObject[pair] = [tokens0[i], tokens1[i]] + }) + + // filter out the pairs with less than 1000 USD pooled value + const filteredPairs = await filterPools({ api: api, pairs: pairObject, createBalances: createBalances }) + await Promise.all(Object.keys(filteredPairs).map(async (pair) => { + const [token0, token1] = pairObject[pair] + const logs = await getLogs({ target: pair, eventAbi: event_swap }) + logs.forEach(log => { + const amountInX = Number('0x' + '0'.repeat(32) + log.amountsOut.replace('0x', '').slice(0, 32)) + const amountInY = Number('0x' + '0'.repeat(32) + log.amountsOut.replace('0x', '').slice(32, 64)) + dailyVolume.add(token1, amountInX); + dailyVolume.add(token0, amountInY); + + const protocolFeesY = Number('0x' + log.protocolFees.replace('0x', '').slice(0, 32)) + const protocolFeesX = Number('0x' + log.protocolFees.replace('0x', '').slice(32, 64)) + const totalFeesY = Number('0x' + log.totalFees.replace('0x', '').slice(0, 32)); + const totalFeesX = Number('0x' + log.totalFees.replace('0x', '').slice(32, 64)); + dailyFees.add(token0, totalFeesX ) + dailyFees.add(token1, totalFeesY ) + dailyRevenue.add(token0, protocolFeesX) + dailyRevenue.add(token1, protocolFeesY) + }) + })) + + return { dailyVolume, dailyFees, dailyRevenue, timestamp }; +} + +const adapter: SimpleAdapter = { + adapter: { + [CHAIN.IOTAEVM]: { fetch, start: 1681130543, }, + } +}; + +export default adapter; diff --git a/protocols/mare-finance-v2.ts b/protocols/mare-finance-v2.ts new file mode 100644 index 0000000000..923812e8b0 --- /dev/null +++ b/protocols/mare-finance-v2.ts @@ -0,0 +1,5 @@ +import { compoundV2Export } from "../helpers/compoundV2" + +export default compoundV2Export({ + kava: "0xFcD7D41D5cfF03C7f6D573c9732B0506C72f5C72", +}) \ No newline at end of file diff --git a/protocols/merchant-moe-liquidity-book/index.ts b/protocols/merchant-moe-liquidity-book/index.ts new file mode 100644 index 0000000000..318e2b691f --- /dev/null +++ b/protocols/merchant-moe-liquidity-book/index.ts @@ -0,0 +1,47 @@ +import { ChainBlocks, FetchOptions, FetchResult, SimpleAdapter } from "../../adapters/types"; +import { getTimestampAtStartOfDayUTC } from "../../utils/date"; +import { CHAIN } from "../../helpers/chains"; +import { httpGet } from "../../utils/fetchURL"; + +const endpointsV2 = { + [CHAIN.MANTLE]: "https://barn.merchantmoe.com/v1/lb/dex/analytics/mantle?startTime=1711929600&aggregateBy=daily" +} + +interface IData { + feesUsd: number; + protocolFeesUsd: number; + volumeUsd: number; + timestamp: number; +} + +const graph = async (timestamp: number, _c: ChainBlocks, { chain, startOfDay }: FetchOptions): Promise => { + const dayTimestamp = getTimestampAtStartOfDayUTC(startOfDay) + const historical: IData[] = (await httpGet(endpointsV2[chain])); + const dailyFees = historical + .find(dayItem => dayItem.timestamp === dayTimestamp)?.feesUsd || 0 + const dailyRevenue = historical + .find(dayItem => dayItem.timestamp === dayTimestamp)?.protocolFeesUsd || 0 + const dailyVolume = historical + .find(dayItem => dayItem.timestamp === dayTimestamp)?.volumeUsd || 0 + return { + dailyVolume:`${dailyVolume}`, + dailyUserFees: `${dailyFees}`, + dailyFees: `${dailyFees}`, + dailyRevenue: `${dailyRevenue}`, + dailyHoldersRevenue: `${dailyRevenue}`, + dailySupplySideRevenue: dailyFees ? `${(dailyFees || 0) - (dailyRevenue || 0)}` : undefined, + dailyProtocolRevenue: `${dailyRevenue}`, + timestamp + } + +} + +const adapter: SimpleAdapter = { + adapter: { + [CHAIN.MANTLE]: { + fetch: graph, + start: 1711929600 + } + } +} +export default adapter diff --git a/protocols/moraswap-v3.ts b/protocols/moraswap-v3.ts new file mode 100644 index 0000000000..9011475b04 --- /dev/null +++ b/protocols/moraswap-v3.ts @@ -0,0 +1,7 @@ +import { uniV3Exports } from "../helpers/uniswap"; + +export default uniV3Exports({ + neon_evm: { + factory: '0x58122246F7e33669cde3486Dd72f95c2e886E375', + } +}) diff --git a/protocols/omax-swap.ts b/protocols/omax-swap.ts new file mode 100644 index 0000000000..09b3b08b2f --- /dev/null +++ b/protocols/omax-swap.ts @@ -0,0 +1,7 @@ +import { uniV2Exports } from "../helpers/uniswap"; + +export default uniV2Exports({ + omax: { + factory: '0x441b9333D1D1ccAd27f2755e69d24E60c9d8F9CF', + } +}) \ No newline at end of file diff --git a/protocols/pancakeswap/index.ts b/protocols/pancakeswap/index.ts index 13a73de495..dd0fbc8c97 100644 --- a/protocols/pancakeswap/index.ts +++ b/protocols/pancakeswap/index.ts @@ -1,42 +1,40 @@ -import { Chain } from "@defillama/sdk/build/general"; -import { BaseAdapter, BreakdownAdapter, DISABLED_ADAPTER_KEY, FetchResultVolume, IJSON } from "../../adapters/types"; +import { BaseAdapter, BreakdownAdapter, DISABLED_ADAPTER_KEY, FetchOptions, FetchV2, IJSON } from "../../adapters/types"; import { CHAIN } from "../../helpers/chains"; import disabledAdapter from "../../helpers/disabledAdapter"; - -import { getGraphDimensions } from "../../helpers/getUniSubgraph" +import { getGraphDimensions2 } from "../../helpers/getUniSubgraph" import * as sdk from "@defillama/sdk"; import { httpGet } from "../../utils/fetchURL"; import { getEnv } from "../../helpers/env"; const endpoints = { [CHAIN.BSC]: "https://proxy-worker.pancake-swap.workers.dev/bsc-exchange", - [CHAIN.ETHEREUM]: "https://api.thegraph.com/subgraphs/name/pancakeswap/exhange-eth", - [CHAIN.POLYGON_ZKEVM]: "https://api.studio.thegraph.com/query/45376/exchange-v2-polygon-zkevm/version/latest", + [CHAIN.ETHEREUM]: sdk.graph.modifyEndpoint('9opY17WnEPD4REcC43yHycQthSeUMQE26wyoeMjZTLEx'), + // [CHAIN.POLYGON_ZKEVM]: "https://api.studio.thegraph.com/query/45376/exchange-v2-polygon-zkevm/version/latest", [CHAIN.ERA]: "https://api.studio.thegraph.com/query/45376/exchange-v2-zksync/version/latest", - [CHAIN.ARBITRUM]: "https://api.thegraph.com/subgraphs/name/pancakeswap/exchange-v2-arb", + [CHAIN.ARBITRUM]: sdk.graph.modifyEndpoint('EsL7geTRcA3LaLLM9EcMFzYbUgnvf8RixoEEGErrodB3'), [CHAIN.LINEA]: "https://graph-query.linea.build/subgraphs/name/pancakeswap/exhange-v2", [CHAIN.BASE]: "https://api.studio.thegraph.com/query/45376/exchange-v2-base/version/latest", [CHAIN.OP_BNB]: `${getEnv('PANCAKESWAP_OPBNB_SUBGRAPH')}/subgraphs/name/pancakeswap/exchange-v2` }; const stablesSwapEndpoints = { - [CHAIN.BSC]: "https://api.thegraph.com/subgraphs/name/pancakeswap/exchange-stableswap" + [CHAIN.BSC]: sdk.graph.modifyEndpoint('C5EuiZwWkCge7edveeMcvDmdr7jjc1zG4vgn8uucLdfz'), + [CHAIN.ETHEREUM]: sdk.graph.modifyEndpoint('CoKbk4ey7JFGodyx1psQ21ojW4UhSoWBVcCTxTwEuJUj'), + [CHAIN.ARBITRUM]: sdk.graph.modifyEndpoint('y7G5NUSq5ngsLH2jBGQajjxuLgW1bcqWiBqKmBk3MWM') } const v3Endpoint = { - [CHAIN.BSC]: "https://api.thegraph.com/subgraphs/name/pancakeswap/exchange-v3-bsc", - [CHAIN.ETHEREUM]: "https://api.thegraph.com/subgraphs/name/pancakeswap/exchange-v3-eth", - [CHAIN.POLYGON_ZKEVM]: "https://api.studio.thegraph.com/query/45376/exchange-v3-polygon-zkevm/version/latest", + [CHAIN.BSC]: sdk.graph.modifyEndpoint('Hv1GncLY5docZoGtXjo4kwbTvxm3MAhVZqBZE4sUT9eZ'), + [CHAIN.ETHEREUM]: sdk.graph.modifyEndpoint('CJYGNhb7RvnhfBDjqpRnD3oxgyhibzc7fkAMa38YV3oS'), + // [CHAIN.POLYGON_ZKEVM]: "https://api.studio.thegraph.com/query/45376/exchange-v3-polygon-zkevm/version/latest", [CHAIN.ERA]: "https://api.studio.thegraph.com/query/45376/exchange-v3-zksync/version/latest", - [CHAIN.ARBITRUM]: "https://api.thegraph.com/subgraphs/name/pancakeswap/exchange-v3-arb", + [CHAIN.ARBITRUM]: sdk.graph.modifyEndpoint('251MHFNN1rwjErXD2efWMpNS73SANZN8Ua192zw6iXve'), [CHAIN.LINEA]: "https://graph-query.linea.build/subgraphs/name/pancakeswap/exchange-v3-linea", [CHAIN.BASE]: "https://api.studio.thegraph.com/query/45376/exchange-v3-base/version/latest", [CHAIN.OP_BNB]: `${getEnv('PANCAKESWAP_OPBNB_SUBGRAPH')}/subgraphs/name/pancakeswap/exchange-v3` } -const VOLUME_USD = "volumeUSD"; - -const graphs = getGraphDimensions({ +const graphs = getGraphDimensions2({ graphUrls: endpoints, graphRequestHeaders: { [CHAIN.BSC]: { @@ -46,9 +44,6 @@ const graphs = getGraphDimensions({ totalVolume: { factory: "pancakeFactories" }, - dailyVolume: { - factory: "pancakeDayData" - }, feesPercent: { type: "volume", Fees: 0.25, @@ -60,14 +55,11 @@ const graphs = getGraphDimensions({ } }); -const graphsStableSwap = getGraphDimensions({ +const graphsStableSwap = getGraphDimensions2({ graphUrls: stablesSwapEndpoints, totalVolume: { factory: "factories" }, - dailyVolume: { - factory: "pancakeDayData" - }, feesPercent: { type: "volume", Fees: 0.25, // 0.25% volume @@ -79,23 +71,14 @@ const graphsStableSwap = getGraphDimensions({ } }); -const v3Graph = getGraphDimensions({ +const v3Graph = getGraphDimensions2({ graphUrls: v3Endpoint, totalVolume: { factory: "factories", - - }, - dailyVolume: { - factory: "pancakeDayData", - field: VOLUME_USD }, totalFees: { factory: "factories", }, - dailyFees: { - factory: "pancakeDayData", - field: "feesUSD" - }, }); const startTimes = { @@ -110,7 +93,9 @@ const startTimes = { } as IJSON const stableTimes = { - [CHAIN.BSC]: 1663718400 + [CHAIN.ETHEREUM]: 1705363200, + [CHAIN.BSC]: 1663718400, + [CHAIN.ARBITRUM]: 1705363200 } as IJSON const v3StartTimes = { @@ -161,9 +146,7 @@ const getResources = async (account: string): Promise => { return data } -const fetchVolume = async (timestamp: number) => { - const fromTimestamp = timestamp - 86400; - const toTimestamp = timestamp; +const fetchVolume: FetchV2 = async ({ fromTimestamp, toTimestamp, createBalances }) => { const account_resource: any[] = (await getResources(account)) const pools = account_resource.filter(e => e.type?.includes('swap::PairEventHolder')) .map((e: any) => { @@ -192,7 +175,7 @@ const fetchVolume = async (timestamp: number) => { numberOfTrade[e]['count'] = 0; numberOfTrade[e]['volume'] = 0; }) - const balances = new sdk.Balances({ chain: CHAIN.APTOS, timestamp }) + const balances: sdk.Balances = createBalances() logs_swap.map((e: ISwapEventData) => { const [token0, token1] = getToken(e.type); balances.add(token0, e.amount_x_out) @@ -200,7 +183,6 @@ const fetchVolume = async (timestamp: number) => { }) return { - timestamp, dailyVolume: await balances.getUSDString(), dailyFees: "0", } @@ -247,15 +229,16 @@ const getSwapEvent = async (pool: any, fromTimestamp: number, toTimestamp: numbe const toUnixTime = (timestamp: string) => Number((Number(timestamp) / 1e6).toString().split('.')[0]) const adapter: BreakdownAdapter = { + version: 2, breakdown: { v1: { [DISABLED_ADAPTER_KEY]: disabledAdapter, [CHAIN.BSC]: { - fetch: async (timestamp: number) => { + fetch: async ({ startTimestamp }) => { const totalVolume = 103394400000; return { totalVolume: `${totalVolume}`, - timestamp: timestamp + timestamp: startTimestamp } }, start: 1680307200, @@ -263,7 +246,7 @@ const adapter: BreakdownAdapter = { }, v2: Object.keys(endpoints).reduce((acc, chain) => { acc[chain] = { - fetch: graphs(chain as Chain), + fetch: graphs(chain), start: startTimes[chain], meta: { methodology @@ -273,14 +256,10 @@ const adapter: BreakdownAdapter = { }, {} as BaseAdapter), v3: Object.keys(v3Endpoint).reduce((acc, chain) => { acc[chain] = { - fetch: async (timestamp: number) => { - const v3stats = await v3Graph(chain)(timestamp, {}) + fetch: async (options: FetchOptions) => { + const v3stats = await v3Graph(chain)(options) if (chain === CHAIN.ETHEREUM) v3stats.totalVolume = (Number(v3stats.totalVolume) - 7385565913).toString() - return { - ...v3stats, - timestamp - } - + return v3stats }, start: v3StartTimes[chain], } @@ -288,7 +267,7 @@ const adapter: BreakdownAdapter = { }, {} as BaseAdapter), stableswap: Object.keys(stablesSwapEndpoints).reduce((acc, chain) => { acc[chain] = { - fetch: graphsStableSwap(chain as Chain), + fetch: graphsStableSwap(chain), start: stableTimes[chain], meta: { methodology: { diff --git a/protocols/pharaoh-v2.ts b/protocols/pharaoh-v2.ts new file mode 100644 index 0000000000..69110e7854 --- /dev/null +++ b/protocols/pharaoh-v2.ts @@ -0,0 +1,7 @@ +import { uniV2Exports } from "../helpers/uniswap"; + +export default uniV2Exports({ + avax: { + factory: '0xAAA16c016BF556fcD620328f0759252E29b1AB57', + } +}) \ No newline at end of file diff --git a/protocols/scribe-exchange-v4.ts b/protocols/scribe-exchange-v4.ts new file mode 100644 index 0000000000..a262364174 --- /dev/null +++ b/protocols/scribe-exchange-v4.ts @@ -0,0 +1,10 @@ +import { uniV3Exports } from '../helpers/uniswap'; + +const poolEvent = + 'event Pool(address indexed token0,address indexed token1,address pool)'; +export default uniV3Exports({ + scroll: { + poolCreatedEvent: poolEvent, + factory: '0xDc62aCDF75cc7EA4D93C69B2866d9642E79d5e2e', + }, +}); diff --git a/protocols/smbswap/index.ts b/protocols/smbswap/index.ts index 4b0ed19bd1..5c49110140 100644 --- a/protocols/smbswap/index.ts +++ b/protocols/smbswap/index.ts @@ -1,30 +1,29 @@ +import * as sdk from "@defillama/sdk"; import { Chain } from "@defillama/sdk/build/general"; -import { BaseAdapter, BreakdownAdapter, DISABLED_ADAPTER_KEY, IJSON } from "../../adapters/types"; +import { BaseAdapter, BreakdownAdapter, DISABLED_ADAPTER_KEY, FetchOptions, IJSON } from "../../adapters/types"; import { CHAIN } from "../../helpers/chains"; import disabledAdapter from "../../helpers/disabledAdapter"; - -import { getGraphDimensions } from "../../helpers/getUniSubgraph" +import { getGraphDimensions2 } from "../../helpers/getUniSubgraph" const endpoints = { - [CHAIN.BSC]: "https://api.thegraph.com/subgraphs/name/cr3k/exchange" + [CHAIN.BSC]: sdk.graph.modifyEndpoint('9BtGwsWynjj21VyrAtNfeKG5kMhcZ7Z12T53wo7PBTLj') }; const stablesSwapEndpoints = { - [CHAIN.BSC]: "https://api.thegraph.com/subgraphs/name/cr3k/exchange-stableswap" + [CHAIN.BSC]: sdk.graph.modifyEndpoint('8o2ZdXbsnHapQvT9Jh8NXLivnLSYVGQXsgVfBzfckLiW') } const v3Endpoint = { - [CHAIN.BSC]: "https://api.thegraph.com/subgraphs/name/cr3k/exchange-v3-bsc" + [CHAIN.BSC]: sdk.graph.modifyEndpoint('8XiGZs3G3dDL3YQJx7CsMGXdn3CUBBC9CVpCe1xrsSA7') } -const VOLUME_USD = "volumeUSD"; const blackListedPairs = { [CHAIN.BSC]: [ "0x609f59c97ddf58475c7d3f3fc829c3ff9fc4f76f" ] } -const graphs = getGraphDimensions({ +const graphs = getGraphDimensions2({ graphUrls: endpoints, graphRequestHeaders: { [CHAIN.BSC]: { @@ -34,9 +33,6 @@ const graphs = getGraphDimensions({ totalVolume: { factory: "smbfactories" }, - dailyVolume: { - factory: "smbdayData" - }, feesPercent: { type: "volume", Fees: 0.25, @@ -49,14 +45,11 @@ const graphs = getGraphDimensions({ blacklistTokens: blackListedPairs }); -const graphsStableSwap = getGraphDimensions({ +const graphsStableSwap = getGraphDimensions2({ graphUrls: stablesSwapEndpoints, totalVolume: { factory: "factories" }, - dailyVolume: { - factory: "smbdayData" - }, feesPercent: { type: "volume", Fees: 0.25, // 0.25% volume @@ -68,23 +61,14 @@ const graphsStableSwap = getGraphDimensions({ } }); -const v3Graph = getGraphDimensions({ +const v3Graph = getGraphDimensions2({ graphUrls: v3Endpoint, totalVolume: { factory: "factories", - - }, - dailyVolume: { - factory: "smbdayData", - field: VOLUME_USD }, totalFees:{ factory: "factories", }, - dailyFees: { - factory: "smbdayData", - field: "feesUSD" - }, }); const startTimes = { @@ -109,6 +93,7 @@ const methodology = { } const adapter: BreakdownAdapter = { + version: 2, breakdown: { v1: { [DISABLED_ADAPTER_KEY]: disabledAdapter, @@ -116,10 +101,9 @@ const adapter: BreakdownAdapter = { }, v2: { [CHAIN.BSC]: { - fetch: async (timestamp: number) => { - const volume = await graphs(CHAIN.BSC)(timestamp, {}) + fetch: async (options: FetchOptions) => { + const volume = await graphs(CHAIN.BSC)(options) return { - timestamp, dailyFees: volume.dailyFees, dailyVolume: volume.dailyVolume, } diff --git a/protocols/swapmode-v2.ts b/protocols/swapmode-v2.ts new file mode 100644 index 0000000000..d1127d48a1 --- /dev/null +++ b/protocols/swapmode-v2.ts @@ -0,0 +1,7 @@ +import { uniV2Exports } from "../helpers/uniswap"; + +export default uniV2Exports({ + mode: { + factory: '0xfb926356BAf861c93C3557D7327Dbe8734A71891', + } +}) \ No newline at end of file diff --git a/protocols/thruster-v2.ts b/protocols/thruster-v2.ts new file mode 100644 index 0000000000..6196692d8d --- /dev/null +++ b/protocols/thruster-v2.ts @@ -0,0 +1,7 @@ +import { uniV2Exports } from "../helpers/uniswap"; + +export default uniV2Exports({ + blast: { + factory: '0xb4A7D971D0ADea1c73198C97d7ab3f9CE4aaFA13', + } +}) \ No newline at end of file diff --git a/protocols/thruster-v3.ts b/protocols/thruster-v3.ts new file mode 100644 index 0000000000..8dbd378a74 --- /dev/null +++ b/protocols/thruster-v3.ts @@ -0,0 +1,7 @@ +import { uniV3Exports } from "../helpers/uniswap"; + +export default uniV3Exports({ + blast: { + factory: '0x71b08f13B3c3aF35aAdEb3949AFEb1ded1016127', + } +}) diff --git a/protocols/uniswap/index.ts b/protocols/uniswap/index.ts index 6318300f7e..559a4ef56b 100644 --- a/protocols/uniswap/index.ts +++ b/protocols/uniswap/index.ts @@ -1,22 +1,19 @@ -import ADDRESSES from '../../helpers/coreAssets.json' +import * as sdk from "@defillama/sdk"; import { Chain } from "@defillama/sdk/build/general"; -import { BreakdownAdapter, FetchResultGeneric, BaseAdapter } from "../../adapters/types"; +import request, { gql } from 'graphql-request'; +import { BaseAdapter, BreakdownAdapter, FetchOptions, FetchResultGeneric } from "../../adapters/types"; import { CHAIN } from "../../helpers/chains"; +import ADDRESSES from '../../helpers/coreAssets.json'; import { getStartTimestamp } from "../../helpers/getStartTimestamp"; -import * as sdk from "@defillama/sdk"; - -import { - getGraphDimensions, - DEFAULT_DAILY_VOLUME_FACTORY, - DEFAULT_TOTAL_VOLUME_FIELD, -} from "../../helpers/getUniSubgraph" +import { DEFAULT_TOTAL_VOLUME_FIELD, getGraphDimensions2 } from "../../helpers/getUniSubgraph"; +import { httpPost } from '../../utils/fetchURL'; const v1Endpoints = { - [CHAIN.ETHEREUM]: "https://api.thegraph.com/subgraphs/name/ianlapham/uniswap", + [CHAIN.ETHEREUM]: sdk.graph.modifyEndpoint('ESnjgAG9NjfmHypk4Huu4PVvz55fUwpyrRqHF21thoLJ'), }; const v2Endpoints = { - [CHAIN.ETHEREUM]: "https://api.thegraph.com/subgraphs/name/ianlapham/uniswap-v2-dev", + [CHAIN.ETHEREUM]: sdk.graph.modifyEndpoint('A3Np3RQbaBA6oKJgiwDJeo5T3zrYfGHPWFYayMwtNDum'), }; const blacklisted = { @@ -60,17 +57,15 @@ const blacklisted = { ] } -const KEY = 'a265c39f5a123ab2d40b25dc352adc22' - const v3Endpoints = { - [CHAIN.ETHEREUM]: "https://api.thegraph.com/subgraphs/name/uniswap/uniswap-v3", - [CHAIN.OPTIMISM]: "https://api.thegraph.com/subgraphs/name/ianlapham/uniswap-optmism-regen", + [CHAIN.ETHEREUM]: sdk.graph.modifyEndpoint('5AXe97hGLfjgFAc6Xvg6uDpsD5hqpxrxcma9MoxG7j7h'), + [CHAIN.OPTIMISM]: sdk.graph.modifyEndpoint('Jhu62RoQqrrWoxUUhWFkiMHDrqsTe7hTGb3NGiHPuf9'), [CHAIN.ARBITRUM]: "https://api.thegraph.com/subgraphs/id/QmZ5uwhnwsJXAQGYEF8qKPQ85iVhYAcVZcZAPfrF7ZNb9z", - [CHAIN.POLYGON]: "https://gateway-arbitrum.network.thegraph.com/api/"+KEY+"/subgraphs/id/3hCPRGf4z88VC5rsBKU5AA9FBBq5nF3jbKJG7VZCbhjm", - [CHAIN.CELO]: "https://api.thegraph.com/subgraphs/name/jesse-sawa/uniswap-celo", - [CHAIN.BSC]: "https://api.thegraph.com/subgraphs/name/ianlapham/uniswap-v3-bsc", - [CHAIN.AVAX]: "https://api.thegraph.com/subgraphs/name/lynnshaoyu/uniswap-v3-avax", - [CHAIN.BASE]: "https://api.thegraph.com/subgraphs/name/lynnshaoyu/uniswap-v3-base", + [CHAIN.POLYGON]: sdk.graph.modifyEndpoint('3hCPRGf4z88VC5rsBKU5AA9FBBq5nF3jbKJG7VZCbhjm'), + // [CHAIN.CELO]: sdk.graph.modifyEndpoint('ESdrTJ3twMwWVoQ1hUE2u7PugEHX3QkenudD6aXCkDQ4'), + [CHAIN.BSC]: sdk.graph.modifyEndpoint('F85MNzUGYqgSHSHRGgeVMNsdnW1KtZSVgFULumXRZTw2'), + // [CHAIN.AVAX]: sdk.graph.modifyEndpoint('4gTHdWa9PbqUugt9vsMmpzUowmjb6eRiFRnUSrYLeSJF'), + [CHAIN.BASE]: sdk.graph.modifyEndpoint('GqzP4Xaehti8KSfQmv3ZctFSjnSUYZ4En5NRsiTbvZpz'), [CHAIN.ERA]: "https://api.thegraph.com/subgraphs/name/freakyfractal/uniswap-v3-zksync-era" }; @@ -78,18 +73,11 @@ const VOLUME_USD = "volumeUSD"; // fees results are in eth, needs to be converted to a balances objects const ETH_ADDRESS = "ethereum:" + ADDRESSES.null; -const v1Graph = getGraphDimensions({ +const v1Graph = getGraphDimensions2({ graphUrls: v1Endpoints, totalVolume: { factory: "uniswaps", }, - dailyVolume: { - field: "dailyVolumeInUSD", - }, - dailyFees: { - factory: "exchangeHistoricalData", - field: "feeInEth" - }, feesPercent: { type: "fees", UserFees: 100, @@ -101,7 +89,7 @@ const v1Graph = getGraphDimensions({ } }); -const v2Graph = getGraphDimensions({ +const v2Graph = getGraphDimensions2({ graphUrls: v2Endpoints, feesPercent: { type: "volume", @@ -115,16 +103,12 @@ const v2Graph = getGraphDimensions({ blacklistTokens: blacklisted }); -const v3Graphs = getGraphDimensions({ +const v3Graphs = getGraphDimensions2({ graphUrls: v3Endpoints, totalVolume: { factory: "factories", field: DEFAULT_TOTAL_VOLUME_FIELD, }, - dailyVolume: { - factory: DEFAULT_DAILY_VOLUME_FACTORY, - field: VOLUME_USD, - }, feesPercent: { type: "fees", ProtocolRevenue: 0, @@ -156,18 +140,81 @@ const startTimeV3:TStartTime = { [CHAIN.BASE]: 1691280000, [CHAIN.ERA]: 1693440000 } + +const chainv2mapping: any = { + [CHAIN.ARBITRUM]: "ARBITRUM", + [CHAIN.ETHEREUM]: "ETHEREUM", + // [CHAIN.OPTIMISM]: "OPTIMISM", + [CHAIN.POLYGON]: "POLYGON", + [CHAIN.BASE]: "BASE", + [CHAIN.BSC]: "BNB", +} + +const fetchV2 = async (options: FetchOptions) => { + interface IGraphResponse { + v2HistoricalProtocolVolume: Array<{ + id: string + timestamp: number + value: string + __typename: string + }> + } + const url = 'https://interface.gateway.uniswap.org/v1/graphql'; + const query = gql`query getVolume($chain: Chain!, $duration: HistoryDuration!) { + v2HistoricalProtocolVolume: historicalProtocolVolume( + chain: $chain + version: V2 + duration: $duration + ) { + id + timestamp + value + __typename + } + }`; + try { + const response:IGraphResponse = await request(url, query, { chain: chainv2mapping[options.chain], duration: "MONTH" }, { + 'accept': '*/*', + 'accept-language': 'th,en-US;q=0.9,en;q=0.8', + 'cache-control': 'no-cache', + 'content-type': 'application/json', + 'origin': 'https://app.uniswap.org', + 'pragma': 'no-cache', + 'priority': 'u=1, i', + 'referer': 'https://app.uniswap.org/', + 'sec-ch-ua': '"Chromium";v="124", "Google Chrome";v="124", "Not-A.Brand";v="99"', + 'sec-ch-ua-mobile': '?0', + 'user-agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/124.0.0.0 Safari/537.36' + }); + const dailyVolume = response.v2HistoricalProtocolVolume.find((item) => item.timestamp === options.startOfDay)?.value; + return {dailyVolume: dailyVolume} + } catch (e) { + console.error(e) + return { + dailyVolume: "0" + } + } +} + + const adapter: BreakdownAdapter = { + version: 2, breakdown: { v1: { [CHAIN.ETHEREUM]: { - fetch: async (timestamp, chainBlocks) => { - const response = await v1Graph(CHAIN.ETHEREUM)(timestamp, chainBlocks) - const keys = ["dailyUserFees", "dailyProtocolRevenue", "dailySupplySideRevenue", "dailyHoldersRevenue", "dailyRevenue", "dailyFees"] - for (const key of keys) { + fetch: async (options) => { + const response = await v1Graph(options.chain)(options); + const keys = { + "dailyUserFees": options.createBalances(), + "dailyProtocolRevenue": options.createBalances(), + "dailySupplySideRevenue": options.createBalances(), + "dailyHoldersRevenue": options.createBalances(), + "dailyRevenue": options.createBalances(), + "dailyFees": options.createBalances(), + }; + for (const key of Object.keys(keys)) { if (typeof response[key] === 'string') { - response[key] = await sdk.Balances.getUSDString({ - [ETH_ADDRESS]: response[key] - } as any) + keys[key].add(ETH_ADDRESS, Number(response[key]) * 1e18); } } return response as FetchResultGeneric @@ -180,9 +227,10 @@ const adapter: BreakdownAdapter = { }, v2: { [CHAIN.ETHEREUM]: { - fetch: async (timestamp, chainBlocks) => { - const response = await v2Graph(CHAIN.ETHEREUM)(timestamp, chainBlocks) - response.totalVolume = Number(response.dailyVolume) + 1079453198606.2229; + fetch: async (options) => { + const response = await v2Graph(options.chain)(options); + response.totalVolume = + Number(response.dailyVolume) + 1079453198606.2229; response.totalFees = Number(response.totalVolume) * 0.003; response.totalUserFees = Number(response.totalVolume) * 0.003; response.totalSupplySideRevenue = Number(response.totalVolume) * 0.003; @@ -198,10 +246,38 @@ const adapter: BreakdownAdapter = { methodology }, }, + ...Object.keys(chainv2mapping).reduce((acc, chain) => { + acc[chain] = { + fetch: fetchV2, + start: 0, + } + return acc + }, {}) }, v3: Object.keys(v3Endpoints).reduce((acc, chain) => { acc[chain] = { - fetch: v3Graphs(chain as Chain), + fetch: async (options: FetchOptions) => { + try { + const res = (await v3Graphs(chain as Chain)(options)) + return { + totalVolume: res?.totalVolume || 0, + dailyVolume: res?.dailyVolume || 0, + totalFees: res?.totalFees || 0, + totalUserFees: res?.totalUserFees || 0, + dailyFees: res?.dailyFees || 0, + dailyUserFees: res?.dailyUserFees || 0 + } + } catch { + return { + totalVolume: 0, + dailyVolume: 0, + totalFees: 0, + totalUserFees: 0, + dailyFees: 0, + dailyUserFees: 0 + } + } + }, start: startTimeV3[chain], meta: { methodology: { @@ -214,13 +290,124 @@ const adapter: BreakdownAdapter = { }, {} as BaseAdapter) } } -// adapter.breakdown.v3.bsc.fetch = async (timestamp, chainBlocks) => { -// const response = await v3Graphs(CHAIN.BSC)(timestamp, chainBlocks) -// const totalVolume = Number(response.totalVolume) - 10_000_000_000; -// return { -// ...response, -// totalVolume -// } as FetchResultGeneric -// } + +interface ISeiResponse { + volume: number; + fees: number; +} +const fetchSei = async (options: FetchOptions) => { + try { + const url = `https://omni.icarus.tools/${mappingChain(options.chain)}/cush/analyticsProtocolHistoric`; + const body = { + "params": [ + options.startTimestamp * 1000, //start + options.endTimestamp * 1000, //end + 3600000 //interval + ] + } + const response: ISeiResponse[] = (await httpPost(url, body)).result + const dailyVolume = response.reduce((acc, item) => acc + item.volume, 0); + const dailyFees = response.reduce((acc, item) => acc + item.fees, 0); + return { + dailyVolume, + dailyFees, + } + } catch (e) { + console.error(e) + return {} + } +} +const mappingChain = (chain: string) => { + if (chain === CHAIN.ERA) return "zksync" + if (chain === CHAIN.ROOTSTOCK) return "rootstock" + return chain +} + +adapter.breakdown.v3[CHAIN.SEI] = { + fetch: fetchSei, + start: 0, + meta: { + methodology + } +} +adapter.breakdown.v3[CHAIN.ERA] = { + fetch: fetchSei, + start: 0, + meta: { + methodology + } +} + +adapter.breakdown.v3[CHAIN.TAIKO] = { + fetch: fetchSei, + start: 0, + meta: { + methodology + } +} + +adapter.breakdown.v3[CHAIN.SCROLL] = { + fetch: fetchSei, + start: 0, + meta: { + methodology + } +} + +adapter.breakdown.v3[CHAIN.ROOTSTOCK] = { + fetch: fetchSei, + start: 0, + meta: { + methodology + } +} + +adapter.breakdown.v3[CHAIN.FILECOIN] = { + fetch: fetchSei, + start: 0, + meta: { + methodology + } +} + +adapter.breakdown.v3[CHAIN.BOBA] = { + fetch: fetchSei, + start: 0, + meta: { + methodology + } +} + +adapter.breakdown.v3[CHAIN.MOONBEAM] = { + fetch: fetchSei, + start: 0, + meta: { + methodology + } +} + +adapter.breakdown.v3[CHAIN.MANTA] = { + fetch: fetchSei, + start: 0, + meta: { + methodology + } +} + +adapter.breakdown.v3[CHAIN.MANTLE] = { + fetch: fetchSei, + start: 0, + meta: { + methodology + } +} + +adapter.breakdown.v3[CHAIN.LINEA] = { + fetch: fetchSei, + start: 0, + meta: { + methodology + } +} export default adapter; diff --git a/protocols/vanillaswap-v2.ts b/protocols/vanillaswap-v2.ts new file mode 100644 index 0000000000..92c8d6fb21 --- /dev/null +++ b/protocols/vanillaswap-v2.ts @@ -0,0 +1,7 @@ +import { uniV2Exports } from "../helpers/uniswap"; + +export default uniV2Exports({ + defichain_evm: { + factory: '0x79Ea1b897deeF37e3e42cDB66ca35DaA799E93a3', + } +}) diff --git a/protocols/vanillaswap-v3.ts b/protocols/vanillaswap-v3.ts new file mode 100644 index 0000000000..9da5e9d359 --- /dev/null +++ b/protocols/vanillaswap-v3.ts @@ -0,0 +1,7 @@ +import { uniV3Exports } from "../helpers/uniswap"; + +export default uniV3Exports({ + defichain_evm: { + factory: '0x9C444DD15Fb0Ac0bA8E9fbB9dA7b9015F43b4Dc1', + } +}) diff --git a/protocols/xtrade/index.ts b/protocols/xtrade/index.ts new file mode 100644 index 0000000000..6fd277379e --- /dev/null +++ b/protocols/xtrade/index.ts @@ -0,0 +1,9 @@ +import { uniV3Exports } from '../../helpers/uniswap' + +const poolEvent = 'event Pool(address indexed token0,address indexed token1,address pool)' +export default uniV3Exports({ + xlayer: { + poolCreatedEvent: poolEvent, + factory: '0x612D9EA08be59479B112D8d400C7F0A2E4aD4172', + }, +}) diff --git a/users/list.ts b/users/list.ts index 6018988e1b..fa8de602f7 100644 --- a/users/list.ts +++ b/users/list.ts @@ -1,9 +1,9 @@ import chains from "./chains" -import routers from "./routers/uniswap-v2" +import routers from "./routers/index" import protocolAddresses from "./routers/routerAddresses"; import compoundV2, {addresses as compoundAddresses} from "./compound-v2"; import { ExtraProtocolAddresses } from "./utils/types"; export default routers.concat(chains as any[]).concat(compoundV2 as any[]) -export const addressList = (protocolAddresses as ExtraProtocolAddresses[]).concat(compoundAddresses) +export const addressList = (protocolAddresses as ExtraProtocolAddresses[]).concat(compoundAddresses) \ No newline at end of file diff --git a/users/routers/uniswap-v2.ts b/users/routers/index.ts similarity index 100% rename from users/routers/uniswap-v2.ts rename to users/routers/index.ts diff --git a/users/routers/routerAddresses.ts b/users/routers/routerAddresses.ts index 99e9d778c7..ec15ec95da 100644 --- a/users/routers/routerAddresses.ts +++ b/users/routers/routerAddresses.ts @@ -1,359 +1,282 @@ -import ADDRESSES from '../../helpers/coreAssets.json' +import ADDRESSES from "../../helpers/coreAssets.json"; import { isAddressesUsable } from "../utils/countUsers"; import { ProtocolAddresses } from "../utils/types"; -export default ([ - { - "id":"3429", - "name":"YFX", - "addresses":{ - "arbitrum":[ - "0xebb4871d1be1262C8bd1aa7dfc4C047483f02028" - ] - } - }, - { - "id":"parent#uniswap", - "name":"Uniswap", - "addresses":{ - "ethereum":[ - // v2 - "0x7a250d5630B4cF539739dF2C5dAcb4c659F2488D", - "0xf164fc0ec4e93095b804a4795bbe1e041497b92a", - //v3 - "0xE592427A0AEce92De3Edee1F18E0157C05861564", - "0x075B36dE1Bd11cb361c5B3B1E80A9ab0e7aa8a60", - "0x68b3465833fb72A70ecDF485E0e4C7bD8665Fc45", - "0x4C60051384bd2d3C01bfc845Cf5F4b44bcbE9de5",//universalrouter - "0xEf1c6E67703c7BD7107eed8303Fbe6EC2554BF6B",//universalrouter - ], - "bsc":[ - "0x5Dc88340E1c5c6366864Ee415d6034cadd1A9897" - ], - "celo":[ - "0xC73d61d192FB994157168Fb56730FdEc64C9Cb8F", - // v3 - "0x5615CDAb10dc425a742d643d949a7F474C01abc4" - ], - "polygon":[ - "0x4C60051384bd2d3C01bfc845Cf5F4b44bcbE9de5",//universalrouter - "0xE592427A0AEce92De3Edee1F18E0157C05861564", //v3 - "0x68b3465833fb72A70ecDF485E0e4C7bD8665Fc45",//v3 - "0xEf1c6E67703c7BD7107eed8303Fbe6EC2554BF6B",//universalrouter2 - ], - "arbitrum":[ - "0xE592427A0AEce92De3Edee1F18E0157C05861564",//v3 - "0x075B36dE1Bd11cb361c5B3B1E80A9ab0e7aa8a60",//v3 - "0x4C60051384bd2d3C01bfc845Cf5F4b44bcbE9de5", - "0x68b3465833fb72A70ecDF485E0e4C7bD8665Fc45",//v3 - "0xEf1c6E67703c7BD7107eed8303Fbe6EC2554BF6B",//universalrouter - ], - "optimism":[ - "0xE592427A0AEce92De3Edee1F18E0157C05861564", //v3 - "0x075B36dE1Bd11cb361c5B3B1E80A9ab0e7aa8a60",//v3 - "0x68b3465833fb72A70ecDF485E0e4C7bD8665Fc45",//v3 - "0xb555edF5dcF85f42cEeF1f3630a52A108E55A654",//universalrouter - "0xEf1c6E67703c7BD7107eed8303Fbe6EC2554BF6B",//universalrouter - "0x560DA69Ef841e1272C65eF9ebA538870F8C0c484",//universalrouter - ] - } - }, - { - "id":"parent#sushi", - "name":"Sushiswap", - "addresses":{ - "ethereum":[ - "0xd9e1ce17f2641f24ae83637ab66a2cca9c378b9f", - "0xf5bce5077908a1b7370b9ae04adc565ebd643966", - "0xF70c086618dcf2b1A461311275e00D6B722ef914", - "0x044b75f554b886A065b9567891e45c79542d7357", - "0x7af71799C40F952237eAA4D81A77C1af49125113", - "0xDdC1b5920723F774d2Ec2C3c9355251A20819776" - ], - "arbitrum":[ - "0x1b02dA8Cb0d097eB8D57A175b88c7D8b47997506", - "0x74c764d41b77dbbb4fe771dab1939b00b146894a", - "0x9c6522117e2ed1fE5bdb72bb0eD5E3f2bdE7DBe0", - "0x9f18658f7206EaA8D885bBfBb95aB6D9f6c6C12F", - "0xD9988b4B5bBC53A794240496cfA9Bf5b1F8E0523" - ], - "optimism":[ - "0xF0cBce1942A68BEB3d1b73F0dd86C8DCc363eF49", - "0x96E04591579f298681361C6122Dc4Ef405c19385", - "0xD9988b4B5bBC53A794240496cfA9Bf5b1F8E0523", - "0xc35DADB65012eC5796536bD9864eD8773aBc74C4", - "0xE52180815c81D7711B83412e53259bed6a3aB70a" - ], - "avax":[ - "0x1b02dA8Cb0d097eB8D57A175b88c7D8b47997506", - "0x0711B6026068f736bae6B213031fCE978D48E026", - "0xD75F5369724b513b497101fb15211160c1d96550", - "0xbACEB8eC6b9355Dfc0269C18bac9d6E2Bdc29C4F", - "0x400d75dAb26bBc18D163AEA3e83D9Ea68F6c1804", - "0xF70c086618dcf2b1A461311275e00D6B722ef914" - ], - "polygon":[ - "0x1b02dA8Cb0d097eB8D57A175b88c7D8b47997506", - "0x0319000133d3AdA02600f0875d2cf03D442C3367", - "0x0dc8E47a1196bcB590485eE8bF832c5c68A52f4B", - "0x5097CBB61D3C75907656DC4e3bbA892Ff136649a", - "0x1A52AfDd24994704e61fEC49924d6c5388Ae47fD", - "0x7CD29170e8fA3fE5204624deDE5A66F4e8161741", - "0x7A250C60Cde7A5Ca7B667209beAB5eA4E16eed67" - ], - "fantom":[ - "0x1b02dA8Cb0d097eB8D57A175b88c7D8b47997506", - "0x3e603C14aF37EBdaD31709C4f848Fc6aD5BEc715", - "0x3D2f8ae0344d38525d2AE96Ab750B83480c0844F", - "0x9e4791ad13f14783C7B2A6A7bD8D6DDD1DC95847", - "0x7cf167390E2526Bc03F3CF6852A7AF1CEC3e243d" - ], - "bsc":[ - "0x1b02dA8Cb0d097eB8D57A175b88c7D8b47997506", - "0xF5BCE5077908a1b7370B9ae04AdC565EBd643966", - "0xD75F5369724b513b497101fb15211160c1d96550", - "0x7cf167390E2526Bc03F3CF6852A7AF1CEC3e243d", - "0x97a32B4f8486735075f2cBEcff64208fBF2e610A" - ], - "xdai":[ - "0x1b02dA8Cb0d097eB8D57A175b88c7D8b47997506", - "0xCaAbdD9Cf4b61813D4a52f980d6BC1B713FE66F5" - ], - "arbitrum-nova":[ - "0x1b02dA8Cb0d097eB8D57A175b88c7D8b47997506", - "0xbE811A0D44E2553d25d11CB8DC0d3F0D0E6430E6" - ], - "boba-avax":[ - "0x1b02dA8Cb0d097eB8D57A175b88c7D8b47997506", - "0x0769fd68dFb93167989C6f7254cd0D766Fb2841F" - ], - "boba-bnb":[ - "0x1b02dA8Cb0d097eB8D57A175b88c7D8b47997506", - "0x0769fd68dFb93167989C6f7254cd0D766Fb2841F" - ], - "boba":[ - "0x1b02dA8Cb0d097eB8D57A175b88c7D8b47997506", - "0x0769fd68dFb93167989C6f7254cd0D766Fb2841F" - ], - "celo":[ - "0x1421bDe4B10e8dd459b3BCb598810B1337D56842", - "0x0711B6026068f736bae6B213031fCE978D48E026" - ], - "fuse":[ - "0xF4d73326C13a4Fc5FD7A064217e12780e9Bd62c3", - "0x0BE808376Ecb75a5CF9bB6D237d16cd37893d904" - ], - "goerli":[ - "0x1b02dA8Cb0d097eB8D57A175b88c7D8b47997506", - "0xF5BCE5077908a1b7370B9ae04AdC565EBd643966" - ], - "harmony":[ - "0x1b02dA8Cb0d097eB8D57A175b88c7D8b47997506", - "0x6b2A3FF504798886862Ca5ce501e080947A506A2" - ], - "heco":[ - "0x1b02dA8Cb0d097eB8D57A175b88c7D8b47997506", - "0xF5BCE5077908a1b7370B9ae04AdC565EBd643966" - ], - "moonbeam":[ - "0x1b02dA8Cb0d097eB8D57A175b88c7D8b47997506", - "0x80C7DD17B01855a6D2347444a0FCC36136a314de" - ], - "moonriver":[ - "0x1b02dA8Cb0d097eB8D57A175b88c7D8b47997506", - "0x145d82bCa93cCa2AE057D1c6f26245d1b9522E6F" - ], - "okexchain":[ - "0x1b02dA8Cb0d097eB8D57A175b88c7D8b47997506" - ], - "palm":[ - "0x1b02dA8Cb0d097eB8D57A175b88c7D8b47997506" - ], - "telos":[ - "0x1b02dA8Cb0d097eB8D57A175b88c7D8b47997506" - ], - "kava":[ - "0xc35DADB65012eC5796536bD9864eD8773aBc74C4", - "0xbE811A0D44E2553d25d11CB8DC0d3F0D0E6430E6" - ], - "metis":[ - "0xc35DADB65012eC5796536bD9864eD8773aBc74C4", - "0xaB235da7f52d35fb4551AfBa11BFB56e18774A65" - ], - "bittorrent":[ - "0xeae23C766a1B25481025a02B2d82a1DB3FC130Ca" - ], - } - }, - { - "id":"2190", - "name":"Sushi BentoBox", - "addresses":{ - "ethereum":[ - "0xf5bce5077908a1b7370b9ae04adc565ebd643966", - "0xF70c086618dcf2b1A461311275e00D6B722ef914", - "0x044b75f554b886A065b9567891e45c79542d7357", - "0x7af71799C40F952237eAA4D81A77C1af49125113" - ], - "arbitrum":[ - "0x74c764d41b77dbbb4fe771dab1939b00b146894a", - "0x9c6522117e2ed1fE5bdb72bb0eD5E3f2bdE7DBe0", - "0x9f18658f7206EaA8D885bBfBb95aB6D9f6c6C12F" - ], - "optimism":[ - "0xF0cBce1942A68BEB3d1b73F0dd86C8DCc363eF49", - "0x96E04591579f298681361C6122Dc4Ef405c19385", - "0xD9988b4B5bBC53A794240496cfA9Bf5b1F8E0523", - "0xc35DADB65012eC5796536bD9864eD8773aBc74C4" - ], - "polygon":[ - "0x0319000133d3AdA02600f0875d2cf03D442C3367", - "0x0dc8E47a1196bcB590485eE8bF832c5c68A52f4B", - "0x5097CBB61D3C75907656DC4e3bbA892Ff136649a", - "0x1A52AfDd24994704e61fEC49924d6c5388Ae47fD", - "0x7CD29170e8fA3fE5204624deDE5A66F4e8161741" - ], - "avax":[ - "0x0711B6026068f736bae6B213031fCE978D48E026", - "0xD75F5369724b513b497101fb15211160c1d96550", - "0xbACEB8eC6b9355Dfc0269C18bac9d6E2Bdc29C4F", - "0x400d75dAb26bBc18D163AEA3e83D9Ea68F6c1804" - ], - "bsc":[ - "0xF5BCE5077908a1b7370B9ae04AdC565EBd643966", - "0xD75F5369724b513b497101fb15211160c1d96550", - "0x7cf167390E2526Bc03F3CF6852A7AF1CEC3e243d", - ], - "fantom":[ - "0x3e603C14aF37EBdaD31709C4f848Fc6aD5BEc715", - "0x3D2f8ae0344d38525d2AE96Ab750B83480c0844F", - "0x9e4791ad13f14783C7B2A6A7bD8D6DDD1DC95847" - ], - "arbitrum-nova":[ - "0xbE811A0D44E2553d25d11CB8DC0d3F0D0E6430E6" - ], - "boba-avax":[ - "0x0769fd68dFb93167989C6f7254cd0D766Fb2841F" - ], - "boba-bnb":[ - "0x0769fd68dFb93167989C6f7254cd0D766Fb2841F" - ], - "boba":[ - "0x0769fd68dFb93167989C6f7254cd0D766Fb2841F" - ], - "bittorrent":[ - "0x8dacffa7F69Ce572992132697252E16254225D38" - ], - "celo":[ - "0x0711B6026068f736bae6B213031fCE978D48E026" - ], - "fuse":[ - "0x0BE808376Ecb75a5CF9bB6D237d16cd37893d904" - ], - "xdai":[ - "0xE2d7F5dd869Fc7c126D21b13a9080e75a4bDb324" - ], - "goerli":[ - "0xF5BCE5077908a1b7370B9ae04AdC565EBd643966" - ], - "harmony":[ - "0x6b2A3FF504798886862Ca5ce501e080947A506A2" - ], - "heco":[ - "0xF5BCE5077908a1b7370B9ae04AdC565EBd643966" - ], - "kava":[ - "0xc35DADB65012eC5796536bD9864eD8773aBc74C4" - ], - "metis":[ - "0xc35DADB65012eC5796536bD9864eD8773aBc74C4" - ], - "moonbeam":[ - "0x80C7DD17B01855a6D2347444a0FCC36136a314de" - ], - "moonriver":[ - "0x145d82bCa93cCa2AE057D1c6f26245d1b9522E6F" - ] - } - }, - { - "id":"397", - "name":"Shibaswap", - "addresses":{ - "ethereum":["0x03f7724180aa6b939894b5ca4314783b0b36b329"] - } - }, - { - "id":"221", - "name":"Defi Swap", - "addresses":{ - "ethereum":[ - "0xceb90e4c17d626be0facd78b79c9c87d7ca181b3" - ] - } - }, - { - "id":"parent#pancakeswap", - "name":"Pancakeswap", - "addresses":{ - "ethereum":[ - "0x13f4EA83D0bd40E75C8222255bc855a974568Dd4", // v3 - "0xEfF92A263d31888d860bD50809A8D171709b7b1c" - ], - "bsc":[ - "0x13f4EA83D0bd40E75C8222255bc855a974568Dd4", // v3 - "0x10ED43C718714eb63d5aA57B78B54704E256024E", - "0x05fF2B0DB69458A0750badebc4f9e13aDd608C7F", - "0x749fc0E64A3680531d31ACC1dAa8dda0bE438B02" - ], - "aptos":[ - "0xc7efb4076dbe143cbcd98cfaaa929ecfc8f299203dfff63b95ccb6bfe19850fa" - ], - "base":[ - "0x678Aa4bF4E210cf2166753e054d5b7c31cc7fa86", // smartrouter - ] - } - }, - { - "id":"179", - "name":"Varen", - "addresses":{ - "ethereum":[ - "0xa7ece0911fe8c60bff9e99f8fafcdbe56e07aff1", - "0x6C0899D124146256a382a9eeB7C8Aca363BcCf46", - "0x8C8FF722DD407bC5e10c098F97DDdAD390f03D58" - ] - } - }, - { - "id":"324", - "name":"Unicly", - "addresses":{ - "ethereum":["0xe6e90bc9f3b95cdb69f48c7bfdd0ede1386b135a"], - "arbitrum":[ - "0xE6E90bC9F3b95cdB69F48c7bFdd0edE1386b135a" - ] - } - }, - { - "id":"707", - "name":"Luaswap", - "addresses":{ - "ethereum":[ - "0x1d5c6f1607a171ad52efb270121331b3039dd83e" - ], - "tomochain":[] - } - }, - { - "id":"580", - "name":"Sashimiswap", - "addresses":{ - "ethereum":[ - "0xe4fe6a45f354e845f954cddee6084603cedb9410" - ] - } - },/* +export default ( + [ + { + "id":"4674", + "name":"YFX V4", + "addresses":{ + "arbitrum":[ + "0x5aCf0eBC782c9845b7E74367B14D3B867360efD2", // router + "0xA1dBE14b978541b24C4E88489b8e463094F88dEB" // rewardRouter + ], + "base": [ + "0xbb1ACaA188337Fb662aE0631B2C537f29D4F9C85", // router + ] + } + }, + { + id: "3429", + name: "YFX", + addresses: { + arbitrum: [ + "0xebb4871d1be1262C8bd1aa7dfc4C047483f02028", // yfx-v3 + "0xcC619251bB94b7605A7Ea7391fEB7D18C32552D5", // yfx-v4 + ], + }, + }, + { + id: "parent#uniswap", + name: "Uniswap", + addresses: { + ethereum: [ + // v2 + "0x7a250d5630B4cF539739dF2C5dAcb4c659F2488D", + "0xf164fc0ec4e93095b804a4795bbe1e041497b92a", + //v3 + "0xE592427A0AEce92De3Edee1F18E0157C05861564", + "0x075B36dE1Bd11cb361c5B3B1E80A9ab0e7aa8a60", + "0x68b3465833fb72A70ecDF485E0e4C7bD8665Fc45", + "0x4C60051384bd2d3C01bfc845Cf5F4b44bcbE9de5", //universalrouter + "0xEf1c6E67703c7BD7107eed8303Fbe6EC2554BF6B", //universalrouter + ], + bsc: ["0x5Dc88340E1c5c6366864Ee415d6034cadd1A9897"], + celo: [ + "0xC73d61d192FB994157168Fb56730FdEc64C9Cb8F", + // v3 + "0x5615CDAb10dc425a742d643d949a7F474C01abc4", + ], + polygon: [ + "0x4C60051384bd2d3C01bfc845Cf5F4b44bcbE9de5", //universalrouter + "0xE592427A0AEce92De3Edee1F18E0157C05861564", //v3 + "0x68b3465833fb72A70ecDF485E0e4C7bD8665Fc45", //v3 + "0xEf1c6E67703c7BD7107eed8303Fbe6EC2554BF6B", //universalrouter2 + ], + arbitrum: [ + "0xE592427A0AEce92De3Edee1F18E0157C05861564", //v3 + "0x075B36dE1Bd11cb361c5B3B1E80A9ab0e7aa8a60", //v3 + "0x4C60051384bd2d3C01bfc845Cf5F4b44bcbE9de5", + "0x68b3465833fb72A70ecDF485E0e4C7bD8665Fc45", //v3 + "0xEf1c6E67703c7BD7107eed8303Fbe6EC2554BF6B", //universalrouter + ], + optimism: [ + "0xE592427A0AEce92De3Edee1F18E0157C05861564", //v3 + "0x075B36dE1Bd11cb361c5B3B1E80A9ab0e7aa8a60", //v3 + "0x68b3465833fb72A70ecDF485E0e4C7bD8665Fc45", //v3 + "0xb555edF5dcF85f42cEeF1f3630a52A108E55A654", //universalrouter + "0xEf1c6E67703c7BD7107eed8303Fbe6EC2554BF6B", //universalrouter + "0x560DA69Ef841e1272C65eF9ebA538870F8C0c484", //universalrouter + ], + }, + }, + { + id: "parent#sushi", + name: "Sushiswap", + addresses: { + "ethereum": [ + "0xd9e1ce17f2641f24ae83637ab66a2cca9c378b9f", + "0xf5bce5077908a1b7370b9ae04adc565ebd643966", + "0xF70c086618dcf2b1A461311275e00D6B722ef914", + "0x044b75f554b886A065b9567891e45c79542d7357", + "0x7af71799C40F952237eAA4D81A77C1af49125113", + "0xDdC1b5920723F774d2Ec2C3c9355251A20819776", + ], + "arbitrum": [ + "0x1b02dA8Cb0d097eB8D57A175b88c7D8b47997506", + "0x74c764d41b77dbbb4fe771dab1939b00b146894a", + "0x9c6522117e2ed1fE5bdb72bb0eD5E3f2bdE7DBe0", + "0x9f18658f7206EaA8D885bBfBb95aB6D9f6c6C12F", + "0xD9988b4B5bBC53A794240496cfA9Bf5b1F8E0523", + ], + "optimism": [ + "0xF0cBce1942A68BEB3d1b73F0dd86C8DCc363eF49", + "0x96E04591579f298681361C6122Dc4Ef405c19385", + "0xD9988b4B5bBC53A794240496cfA9Bf5b1F8E0523", + "0xc35DADB65012eC5796536bD9864eD8773aBc74C4", + "0xE52180815c81D7711B83412e53259bed6a3aB70a", + ], + "avax": [ + "0x1b02dA8Cb0d097eB8D57A175b88c7D8b47997506", + "0x0711B6026068f736bae6B213031fCE978D48E026", + "0xD75F5369724b513b497101fb15211160c1d96550", + "0xbACEB8eC6b9355Dfc0269C18bac9d6E2Bdc29C4F", + "0x400d75dAb26bBc18D163AEA3e83D9Ea68F6c1804", + "0xF70c086618dcf2b1A461311275e00D6B722ef914", + ], + "polygon": [ + "0x1b02dA8Cb0d097eB8D57A175b88c7D8b47997506", + "0x0319000133d3AdA02600f0875d2cf03D442C3367", + "0x0dc8E47a1196bcB590485eE8bF832c5c68A52f4B", + "0x5097CBB61D3C75907656DC4e3bbA892Ff136649a", + "0x1A52AfDd24994704e61fEC49924d6c5388Ae47fD", + "0x7CD29170e8fA3fE5204624deDE5A66F4e8161741", + "0x7A250C60Cde7A5Ca7B667209beAB5eA4E16eed67", + ], + "fantom": [ + "0x1b02dA8Cb0d097eB8D57A175b88c7D8b47997506", + "0x3e603C14aF37EBdaD31709C4f848Fc6aD5BEc715", + "0x3D2f8ae0344d38525d2AE96Ab750B83480c0844F", + "0x9e4791ad13f14783C7B2A6A7bD8D6DDD1DC95847", + "0x7cf167390E2526Bc03F3CF6852A7AF1CEC3e243d", + ], + "bsc": [ + "0x1b02dA8Cb0d097eB8D57A175b88c7D8b47997506", + "0xF5BCE5077908a1b7370B9ae04AdC565EBd643966", + "0xD75F5369724b513b497101fb15211160c1d96550", + "0x7cf167390E2526Bc03F3CF6852A7AF1CEC3e243d", + "0x97a32B4f8486735075f2cBEcff64208fBF2e610A", + ], + "xdai": ["0x1b02dA8Cb0d097eB8D57A175b88c7D8b47997506", "0xCaAbdD9Cf4b61813D4a52f980d6BC1B713FE66F5"], + "arbitrum-nova": ["0x1b02dA8Cb0d097eB8D57A175b88c7D8b47997506", "0xbE811A0D44E2553d25d11CB8DC0d3F0D0E6430E6"], + "boba-avax": ["0x1b02dA8Cb0d097eB8D57A175b88c7D8b47997506", "0x0769fd68dFb93167989C6f7254cd0D766Fb2841F"], + "boba-bnb": ["0x1b02dA8Cb0d097eB8D57A175b88c7D8b47997506", "0x0769fd68dFb93167989C6f7254cd0D766Fb2841F"], + "boba": ["0x1b02dA8Cb0d097eB8D57A175b88c7D8b47997506", "0x0769fd68dFb93167989C6f7254cd0D766Fb2841F"], + "celo": ["0x1421bDe4B10e8dd459b3BCb598810B1337D56842", "0x0711B6026068f736bae6B213031fCE978D48E026"], + "fuse": ["0xF4d73326C13a4Fc5FD7A064217e12780e9Bd62c3", "0x0BE808376Ecb75a5CF9bB6D237d16cd37893d904"], + "goerli": ["0x1b02dA8Cb0d097eB8D57A175b88c7D8b47997506", "0xF5BCE5077908a1b7370B9ae04AdC565EBd643966"], + "harmony": ["0x1b02dA8Cb0d097eB8D57A175b88c7D8b47997506", "0x6b2A3FF504798886862Ca5ce501e080947A506A2"], + "heco": ["0x1b02dA8Cb0d097eB8D57A175b88c7D8b47997506", "0xF5BCE5077908a1b7370B9ae04AdC565EBd643966"], + "moonbeam": ["0x1b02dA8Cb0d097eB8D57A175b88c7D8b47997506", "0x80C7DD17B01855a6D2347444a0FCC36136a314de"], + "moonriver": ["0x1b02dA8Cb0d097eB8D57A175b88c7D8b47997506", "0x145d82bCa93cCa2AE057D1c6f26245d1b9522E6F"], + "okexchain": ["0x1b02dA8Cb0d097eB8D57A175b88c7D8b47997506"], + "palm": ["0x1b02dA8Cb0d097eB8D57A175b88c7D8b47997506"], + "telos": ["0x1b02dA8Cb0d097eB8D57A175b88c7D8b47997506"], + "kava": ["0xc35DADB65012eC5796536bD9864eD8773aBc74C4", "0xbE811A0D44E2553d25d11CB8DC0d3F0D0E6430E6"], + "metis": ["0xc35DADB65012eC5796536bD9864eD8773aBc74C4", "0xaB235da7f52d35fb4551AfBa11BFB56e18774A65"], + "bittorrent": ["0xeae23C766a1B25481025a02B2d82a1DB3FC130Ca"], + }, + }, + { + id: "2190", + name: "Sushi BentoBox", + addresses: { + "ethereum": [ + "0xf5bce5077908a1b7370b9ae04adc565ebd643966", + "0xF70c086618dcf2b1A461311275e00D6B722ef914", + "0x044b75f554b886A065b9567891e45c79542d7357", + "0x7af71799C40F952237eAA4D81A77C1af49125113", + ], + "arbitrum": [ + "0x74c764d41b77dbbb4fe771dab1939b00b146894a", + "0x9c6522117e2ed1fE5bdb72bb0eD5E3f2bdE7DBe0", + "0x9f18658f7206EaA8D885bBfBb95aB6D9f6c6C12F", + ], + "optimism": [ + "0xF0cBce1942A68BEB3d1b73F0dd86C8DCc363eF49", + "0x96E04591579f298681361C6122Dc4Ef405c19385", + "0xD9988b4B5bBC53A794240496cfA9Bf5b1F8E0523", + "0xc35DADB65012eC5796536bD9864eD8773aBc74C4", + ], + "polygon": [ + "0x0319000133d3AdA02600f0875d2cf03D442C3367", + "0x0dc8E47a1196bcB590485eE8bF832c5c68A52f4B", + "0x5097CBB61D3C75907656DC4e3bbA892Ff136649a", + "0x1A52AfDd24994704e61fEC49924d6c5388Ae47fD", + "0x7CD29170e8fA3fE5204624deDE5A66F4e8161741", + ], + "avax": [ + "0x0711B6026068f736bae6B213031fCE978D48E026", + "0xD75F5369724b513b497101fb15211160c1d96550", + "0xbACEB8eC6b9355Dfc0269C18bac9d6E2Bdc29C4F", + "0x400d75dAb26bBc18D163AEA3e83D9Ea68F6c1804", + ], + "bsc": [ + "0xF5BCE5077908a1b7370B9ae04AdC565EBd643966", + "0xD75F5369724b513b497101fb15211160c1d96550", + "0x7cf167390E2526Bc03F3CF6852A7AF1CEC3e243d", + ], + "fantom": [ + "0x3e603C14aF37EBdaD31709C4f848Fc6aD5BEc715", + "0x3D2f8ae0344d38525d2AE96Ab750B83480c0844F", + "0x9e4791ad13f14783C7B2A6A7bD8D6DDD1DC95847", + ], + "arbitrum-nova": ["0xbE811A0D44E2553d25d11CB8DC0d3F0D0E6430E6"], + "boba-avax": ["0x0769fd68dFb93167989C6f7254cd0D766Fb2841F"], + "boba-bnb": ["0x0769fd68dFb93167989C6f7254cd0D766Fb2841F"], + "boba": ["0x0769fd68dFb93167989C6f7254cd0D766Fb2841F"], + "bittorrent": ["0x8dacffa7F69Ce572992132697252E16254225D38"], + "celo": ["0x0711B6026068f736bae6B213031fCE978D48E026"], + "fuse": ["0x0BE808376Ecb75a5CF9bB6D237d16cd37893d904"], + "xdai": ["0xE2d7F5dd869Fc7c126D21b13a9080e75a4bDb324"], + "goerli": ["0xF5BCE5077908a1b7370B9ae04AdC565EBd643966"], + "harmony": ["0x6b2A3FF504798886862Ca5ce501e080947A506A2"], + "heco": ["0xF5BCE5077908a1b7370B9ae04AdC565EBd643966"], + "kava": ["0xc35DADB65012eC5796536bD9864eD8773aBc74C4"], + "metis": ["0xc35DADB65012eC5796536bD9864eD8773aBc74C4"], + "moonbeam": ["0x80C7DD17B01855a6D2347444a0FCC36136a314de"], + "moonriver": ["0x145d82bCa93cCa2AE057D1c6f26245d1b9522E6F"], + }, + }, + { + id: "397", + name: "Shibaswap", + addresses: { + ethereum: ["0x03f7724180aa6b939894b5ca4314783b0b36b329"], + }, + }, + { + id: "221", + name: "Defi Swap", + addresses: { + ethereum: ["0xceb90e4c17d626be0facd78b79c9c87d7ca181b3"], + }, + }, + { + id: "parent#pancakeswap", + name: "Pancakeswap", + addresses: { + ethereum: [ + "0x13f4EA83D0bd40E75C8222255bc855a974568Dd4", // v3 + "0xEfF92A263d31888d860bD50809A8D171709b7b1c", + ], + bsc: [ + "0x13f4EA83D0bd40E75C8222255bc855a974568Dd4", // v3 + "0x10ED43C718714eb63d5aA57B78B54704E256024E", + "0x05fF2B0DB69458A0750badebc4f9e13aDd608C7F", + "0x749fc0E64A3680531d31ACC1dAa8dda0bE438B02", + ], + aptos: ["0xc7efb4076dbe143cbcd98cfaaa929ecfc8f299203dfff63b95ccb6bfe19850fa"], + base: [ + "0x678Aa4bF4E210cf2166753e054d5b7c31cc7fa86", // smartrouter + ], + }, + }, + { + id: "179", + name: "Varen", + addresses: { + ethereum: [ + "0xa7ece0911fe8c60bff9e99f8fafcdbe56e07aff1", + "0x6C0899D124146256a382a9eeB7C8Aca363BcCf46", + "0x8C8FF722DD407bC5e10c098F97DDdAD390f03D58", + ], + }, + }, + { + id: "324", + name: "Unicly", + addresses: { + ethereum: ["0xe6e90bc9f3b95cdb69f48c7bfdd0ede1386b135a"], + arbitrum: ["0xE6E90bC9F3b95cdB69F48c7bFdd0edE1386b135a"], + }, + }, + { + id: "707", + name: "Luaswap", + addresses: { + ethereum: ["0x1d5c6f1607a171ad52efb270121331b3039dd83e"], + tomochain: [], + }, + }, + { + id: "580", + name: "Sashimiswap", + addresses: { + ethereum: ["0xe4fe6a45f354e845f954cddee6084603cedb9410"], + }, + } /* {//added to compoundv2 file "id":"parent#quickswap", "name":"Quickswap", @@ -363,94 +286,78 @@ export default ([ //"Paraswap v5: Augustus Swapper:0xDEF171Fe48CF0115B1d80b88dc8eAB59176FEe57" ] } - },*/ - { - "id":"parent#kyberswap", - "name":"KyberSwap", - "addresses":{ - "ethereum":[ - "0x617Dee16B86534a5d792A4d7A62FB491B544111E", //Meta Aggregation Router - "0x6131B5fae19EA4f9D964eAc0408E4408b66337b5", //Meta Aggregation Router v2 - "0xC1e7dFE73E1598E3910EF4C7845B68A9Ab6F4c83" //Elastic Router - ], - "polygon":[ - "0x617Dee16B86534a5d792A4d7A62FB491B544111E", //Meta Aggregation Router - "0x6131B5fae19EA4f9D964eAc0408E4408b66337b5", //Meta Aggregation Router v2 - "0xC1e7dFE73E1598E3910EF4C7845B68A9Ab6F4c83" //Elastic Router - ], - "avax":[ - "0x617Dee16B86534a5d792A4d7A62FB491B544111E", //Meta Aggregation Router - "0x6131B5fae19EA4f9D964eAc0408E4408b66337b5", //Meta Aggregation Router v2 - "0xC1e7dFE73E1598E3910EF4C7845B68A9Ab6F4c83" //Elastic Router - ], - "bsc":[ - "0x617Dee16B86534a5d792A4d7A62FB491B544111E", //Meta Aggregation Router - "0x6131B5fae19EA4f9D964eAc0408E4408b66337b5", //Meta Aggregation Router v2 - "0xC1e7dFE73E1598E3910EF4C7845B68A9Ab6F4c83" //Elastic Router - ], - "arbitrum":[ - "0x617Dee16B86534a5d792A4d7A62FB491B544111E", //Meta Aggregation Router - "0x6131B5fae19EA4f9D964eAc0408E4408b66337b5", //Meta Aggregation Router v2 - "0xC1e7dFE73E1598E3910EF4C7845B68A9Ab6F4c83" //Elastic Router - ], - "optimism":[ - "0x617Dee16B86534a5d792A4d7A62FB491B544111E", //Meta Aggregation Router - "0x6131B5fae19EA4f9D964eAc0408E4408b66337b5", //Meta Aggregation Router v2 - "0xC1e7dFE73E1598E3910EF4C7845B68A9Ab6F4c83" //Elastic Router - ], - "fantom":[ - "0x617Dee16B86534a5d792A4d7A62FB491B544111E", //Meta Aggregation Router - "0x6131B5fae19EA4f9D964eAc0408E4408b66337b5", //Meta Aggregation Router v2 - "0xC1e7dFE73E1598E3910EF4C7845B68A9Ab6F4c83" //Elastic Router - ], - "cronos":[ - "0x617Dee16B86534a5d792A4d7A62FB491B544111E", //Meta Aggregation Router - "0x6131B5fae19EA4f9D964eAc0408E4408b66337b5", //Meta Aggregation Router v2 - "0xC1e7dFE73E1598E3910EF4C7845B68A9Ab6F4c83" //Elastic Router - ] - - } - }, - { - "id":"parent#balancer", - "name":"Balancer", - "addresses":{ - "ethereum":[ - "0xBA12222222228d8Ba445958a75a0704d566BF2C8" - ], - "arbitrum":[ - "0xBA12222222228d8Ba445958a75a0704d566BF2C8" - ], - "polygon":[ - "0xBA12222222228d8Ba445958a75a0704d566BF2C8" - ], - "xdai":[ - "0xBA12222222228d8Ba445958a75a0704d566BF2C8" - ], - "base":[ - "0xBA12222222228d8Ba445958a75a0704d566BF2C8" - ] - } - }, - { - "id":"1799", - "name":"Velodrome", - "addresses":{ - "optimism":[ - "0x9c12939390052919aF3155f41Bf4160Fd3666A6f", - "0xa132DAB612dB5cB9fC9Ac426A0Cc215A3423F9c9" - ] - } - }, - { - "id":"2685", - "name":"Arbitrum Exchange", - "addresses":{ - "arbitrum":[ - "0x3E48298A5Fe88E4d62985DFf65Dee39a25914975" - ] - } - },/* + },*/, + { + id: "parent#kyberswap", + name: "KyberSwap", + addresses: { + ethereum: [ + "0x617Dee16B86534a5d792A4d7A62FB491B544111E", //Meta Aggregation Router + "0x6131B5fae19EA4f9D964eAc0408E4408b66337b5", //Meta Aggregation Router v2 + "0xC1e7dFE73E1598E3910EF4C7845B68A9Ab6F4c83", //Elastic Router + ], + polygon: [ + "0x617Dee16B86534a5d792A4d7A62FB491B544111E", //Meta Aggregation Router + "0x6131B5fae19EA4f9D964eAc0408E4408b66337b5", //Meta Aggregation Router v2 + "0xC1e7dFE73E1598E3910EF4C7845B68A9Ab6F4c83", //Elastic Router + ], + avax: [ + "0x617Dee16B86534a5d792A4d7A62FB491B544111E", //Meta Aggregation Router + "0x6131B5fae19EA4f9D964eAc0408E4408b66337b5", //Meta Aggregation Router v2 + "0xC1e7dFE73E1598E3910EF4C7845B68A9Ab6F4c83", //Elastic Router + ], + bsc: [ + "0x617Dee16B86534a5d792A4d7A62FB491B544111E", //Meta Aggregation Router + "0x6131B5fae19EA4f9D964eAc0408E4408b66337b5", //Meta Aggregation Router v2 + "0xC1e7dFE73E1598E3910EF4C7845B68A9Ab6F4c83", //Elastic Router + ], + arbitrum: [ + "0x617Dee16B86534a5d792A4d7A62FB491B544111E", //Meta Aggregation Router + "0x6131B5fae19EA4f9D964eAc0408E4408b66337b5", //Meta Aggregation Router v2 + "0xC1e7dFE73E1598E3910EF4C7845B68A9Ab6F4c83", //Elastic Router + ], + optimism: [ + "0x617Dee16B86534a5d792A4d7A62FB491B544111E", //Meta Aggregation Router + "0x6131B5fae19EA4f9D964eAc0408E4408b66337b5", //Meta Aggregation Router v2 + "0xC1e7dFE73E1598E3910EF4C7845B68A9Ab6F4c83", //Elastic Router + ], + fantom: [ + "0x617Dee16B86534a5d792A4d7A62FB491B544111E", //Meta Aggregation Router + "0x6131B5fae19EA4f9D964eAc0408E4408b66337b5", //Meta Aggregation Router v2 + "0xC1e7dFE73E1598E3910EF4C7845B68A9Ab6F4c83", //Elastic Router + ], + cronos: [ + "0x617Dee16B86534a5d792A4d7A62FB491B544111E", //Meta Aggregation Router + "0x6131B5fae19EA4f9D964eAc0408E4408b66337b5", //Meta Aggregation Router v2 + "0xC1e7dFE73E1598E3910EF4C7845B68A9Ab6F4c83", //Elastic Router + ], + }, + }, + { + id: "parent#balancer", + name: "Balancer", + addresses: { + ethereum: ["0xBA12222222228d8Ba445958a75a0704d566BF2C8"], + arbitrum: ["0xBA12222222228d8Ba445958a75a0704d566BF2C8"], + polygon: ["0xBA12222222228d8Ba445958a75a0704d566BF2C8"], + xdai: ["0xBA12222222228d8Ba445958a75a0704d566BF2C8"], + base: ["0xBA12222222228d8Ba445958a75a0704d566BF2C8"], + }, + }, + { + id: "1799", + name: "Velodrome", + addresses: { + optimism: ["0x9c12939390052919aF3155f41Bf4160Fd3666A6f", "0xa132DAB612dB5cB9fC9Ac426A0Cc215A3423F9c9"], + }, + }, + { + id: "2685", + name: "Arbitrum Exchange", + addresses: { + arbitrum: ["0x3E48298A5Fe88E4d62985DFf65Dee39a25914975"], + }, + } /* { "id":"parent#trader-joe", "name":"Trader Joe", @@ -459,2374 +366,2058 @@ export default ([ "0x7BFd7192E76D950832c77BB412aaE841049D8D9B" ], "avax":[ - "0xE3Ffc583dC176575eEA7FD9dF2A7c65F7E23f4C3", - ], - "bsc":[ - "0xb66A2704a0dabC1660941628BE987B4418f7a9E8", - ], - "ethereum":[ - "0x9A93a421b74F1c5755b83dD2C211614dC419C44b"//Lbrouter - ] - } - },*/ - { - "id":"2307", - "name":"Camelot", - "addresses":{ - "arbitrum":[ - "0xc873fEcbd354f5A56E00E710B90EF4201db2448d" - ] - } - }, - { - "id":"parent#thena", - "name":"Thena", - "addresses":{ - "bsc":[ - "0xd4ae6eCA985340Dd434D38F470aCCce4DC78D109", - "0x8f097E07a07Bf2F031E5513f764DaFC6Df58e818" - ] - } - }, - { - "id":"parent#bancor", - "name":"Bancor", - "addresses":{ - "ethereum":[ - "0x2F9EC37d6CcFFf1caB21733BdaDEdE11c823cCB0" - ] - } - }, - { - "id":"302", - "name":"SpookySwap", - "addresses":{ - "fantom":[ - "0x31F63A33141fFee63D4B26755430a390ACdD8a4d" - ] - } - }, - { - "id":"654", - "name":"Beethoven X", - "addresses":{ - "optimism":[ - "0xBA12222222228d8Ba445958a75a0704d566BF2C8" //Vault - ], - "fantom":[ - "0x20dd72Ed959b6147912C2e529F0a0C651c33c9ce" - ] - } - }, - { - "id":"2121", - "name":"Frax Swap", - "addresses":{ - "arbitrum":[ - "0x16e71B13fE6079B4312063F7E81F76d165Ad32Ad" - ], - "ethereum":[ - "0xC14d550632db8592D1243Edc8B95b0Ad06703867" - ], - "optimism":[ - "0xB9A55F455e46e8D717eEA5E47D2c449416A0437F" - ], - "bsc":[ - "0x67F755137E0AE2a2aa0323c047715Bf6523116E5" - ], - "polygon":[ - "0x67F755137E0AE2a2aa0323c047715Bf6523116E5" - ], - "avax":[ - "0x5977b16AA9aBC4D1281058C73B789C65Bf9ab3d3" - ], - "fantom":[ - "0x7D21C651Dd333306B35F2FeAC2a19FA1e1241545" - ], - "boba":[ - "" - ], - "harmony":[ - "" - ], - "aurora":[ - "" - ], - "evmos":[ - "" - ], - "moonbeam":[ - "" - ], - "dogechain":[ - "" - ], - "moonriver":[ - "" - ] - - } - }, - { - "id":"2169", - "name":"BabyDogeSwap", - "addresses":{ - "bsc":[ - "0xC9a0F685F39d05D835c369036251ee3aEaaF3c47" - ] - } - }, - { - "id":"parent#zyberswap", - "name":"Zyberswap", - "addresses":{ - "arbitrum":[ - "0xFa58b8024B49836772180f2Df902f231ba712F72", - "0x16e71B13fE6079B4312063F7E81F76d165Ad32Ad" - ] - } - }, - { - "id":"246", - "name":"Pangolin", - "addresses":{ - "avax":[ - "0xE54Ca86531e17Ef3616d22Ca28b0D458b6C89106" - ] - } - }, - { - "id":"1883", - "name":"iziSwap", - "addresses":{ - "arbitrum":[ - "0x1CB60033F61e4fc171c963f0d2d3F63Ece24319c" - ], - "polygon":[ - "0x879bF5D67fAB468879618AcD69E85C02E33b1c0B" - ], - "bsc":[ - "0xBd3bd95529e0784aD973FD14928eEDF3678cfad8" - ], - "aurora":[ - "" - ], - "telos":[ - "" - ], - "era":[ - "" - ], - "ethereumclassic":[ - "" - ], - "meter":[ - "" - ], - "cronos":[ - "" - ] - } - }, - { - "id":"1700", - "name":"Wombat Exchange", - "addresses":{ - "bsc":[ - "0x19609B03C976CCA288fbDae5c21d4290e9a4aDD7", - "0x312Bc7eAAF93f1C60Dc5AfC115FcCDE161055fb0", - "0xE2C07d20AF0Fb50CAE6cDD615CA44AbaAA31F9c8", - "0x489833311676B566f888119c29bd997Dc6C95830", - "0x04D4e1C1F3D6539071b6D3849fDaED04d48D563d" - ], - "arbitrum":[ - "0xc4B2F992496376C6127e73F1211450322E580668", - "0x9da4edBed6068666ea8EF6505C909e1ff8eA5725", - "0x62A83C6791A3d7950D823BB71a38e47252b6b6F4", - "0x3f90a5a47364c0467031fB00246192d40E3D2D9D" - ], - } - }, - { - "id":"2675", - "name":"Ramses Exchange", - "addresses":{ - "arbitrum":[ - "0xAAA87963EFeB6f7E0a2711F397663105Acb1805e" - ] - } - },/* - { - "id":"parent#apeswap", - "name":"ApeSwap", - "addresses":{ - "ethereum":[ - "0x5f509a3C3F16dF2Fba7bF84dEE1eFbce6BB85587" - ], - "polygon":[ - "0xcF0feBd3f17CEf5b47b0cD257aCf6025c5BFf3b7" - ], - "bsc":[ - "0xcF0feBd3f17CEf5b47b0cD257aCf6025c5BFf3b7", - ], - "arbitrum":[ - "0x7d13268144adcdbEBDf94F654085CC15502849Ff" - ], - "telos":[ - "0xb9667Cf9A495A123b0C43B924f6c2244f42817BE" - ] - } - },*/ - { - "id":"2332", - "name":"Equalizer Exchange", - "addresses":{ - "fantom":[ - "0x1A05EB736873485655F29a37DEf8a0AA87F5a447" - ] - } - }, - { - "id":"2528", - "name":"SolidLizard", - "addresses":{ - "arbitrum":[ - "0xF26515D5482e2C2FD237149bF6A653dA4794b3D0" - ] - } - }, - { - "id":"944", - "name":"Platypus Finance", - "addresses":{ - "avax":[ - "0x7d7E30E269b7C7b447312d3FDE52e6f118F8e39e", - "0x73256EC7575D999C360c1EeC118ECbEFd8DA7D12", - "0x6f6FCbcc00f9AFBD2C266631087798740c685C3B" - ] - } - }, - { - "id":"334", - "name":"MDEX", - "addresses":{ - "bsc":[ - "0x7DAe51BD3E3376B8c7c4900E9107f12Be3AF1bA8", - "0x62c1A0d92B09D0912F7BB9c96C5ecdC7F2b87059", - "0x0384E9ad329396C3A6A401243Ca71633B2bC4333", - "0x518a6e9FB2832aDA41415775E5c45dE6EfCF1A3C", - ], - "heco":[""] - } - }, - { - "id":"2108", - "name":"W3swap", - "addresses":{ - "bsc":[ - "0xF29acE1FE5f36389d0dDe450a0195A30c3770245" - ] - } - },/* - { - "id":"238", - "name":"Ellipsis Finance", - "addresses":{ - "bsc":[ - "0xE014A89c9788dAfdE603a13F2f01390610382471" - ] - } - },*/ - { - "id":"1726", - "name":"Meshswap", - "addresses":{ - "polygon":[ - "0x10f4A785F458Bc144e3706575924889954946639" - ] - } - }, - { - "id":"2695", - "name":"SmarDex", - "addresses":{ - "ethereum":[ - "0x9a5132e149c547F254C73226DA7f770d43D9EA44" - ], - "base":[ - "0x5C622Dcc96b6D96ac6c154f99CF081815094CBC9", //SmardexRouter - ], - "arbitrum":[ - "0xdd4536dD9636564D891c919416880a3e250f975A", //SmardexRouter - ], - "polygon":[ - "0xA8EF6FEa013034E62E2C4A9Ec1CDb059fE23Af33", //SmardexRouter - ], - "bsc":[ - "0x391BeCc8DAaf32b9ba8e602e9527Bf9DA04C8deb", //SmardexRouter - ] - } - }, - { - "id":"318", - "name":"Dfyn Network", - "addresses":{ - "polygon":[ - "0x5ac32A20a5BB6B87AC91E51cA5b7bba9B8846803", - "0xA102072A4C07F06EC3B4900FDC4C7B80b6c57429", - "0x712B5c4CEe26c679F3Ddbb9855369B13aA8F3Dec" - ], - "fantom":[ - "0x2724B9497b2cF3325C6BE3ea430b3cec34B5Ef2d" - ], - "okexchain":[ - "" - ] - } - },/* - { - "id":"133", - "name":"Shell Protocol", - "addresses":{ - "arbitrum":[ - "0xC32eB36f886F638fffD836DF44C124074cFe3584" - ] - } - },*/ - { - "id":"2644", - "name":"Maverick Protocol", - "addresses":{ - "ethereum":[ - "0x001903de96a72d11d27cd8c2bee003a730e032a8", - "0x050853d20d1b4f5529cd8dec986b752e7c9d95f7", - "0x0ce176e1b11a8f88a4ba2535de80e81f88592bad", - "0x0eb1c92f9f5ec9d817968afddb4b46c564cdedbe", - "0x11a653ddfbb61e0feff5484919f06d9d254bf65f", - "0x12378796271f2c5fb1a3206525c4b49a204a8487", - "0x14b0fdd73e47fac12d98182c0fd1054f362262a6", - "0x1970523c241756e24d546dc4bfffc1f436ab9671", - "0x1db8784119dcfe4213a0ceb2c55b07e81c72b475", - "0x1dc08fb758c89db0d81da0924ea4ba884b68564c", - "0x20ee9efe1b85b3077c53d648b17936d4ddb4e407", - "0x214b0b7d3c925b7710601e437aec942b5cbd8d48", - "0x23f6b8a4093d740a5f39d20a1f543e4b26b7791a", - "0x257b0a09d1f4b5913f9c813c43dcd0d0115af2f2", - "0x25f159fd4b15a2a7a9703ca83d0e63df9eeb0a65", - "0x2ebe19aa2e29c8acadb14be3e7de153b0141e2aa", - "0x2f3e9cd12dc8eee8c7fea0383ab877b6bead56ab", - "0x352b186090068eb35d532428676ce510e17ab581", - "0x3fd899eaf2dda35cf2c7bfcdb27a23d727d9a67c", - "0x43a81f1e714f12147e5e865c152c6aac14c80bff", - "0x43c014e1e6afeb8a76fde2420a0b65e1ca06c9bf", - "0x44f0f76cfbafc2b9b3ad000d588897d1e5381068", - "0x46557085e28bcc6d8f653a9ee84c6c9b67642b93", - "0x4789fad0cf791fec659256900074b80c89c47edd", - "0x48e236fa378ffeaf86443b6a304ce5670c3cd9ab", - "0x496d3fe47211521eca1fff521d1f8022b0287c9f", - "0x4a94f0a97615f0bccbc09968b1c49c9ae1eb38a8", - "0x4efec7ada76685a521278407d9fcf58b8c6e8774", - "0x52de4ebf8bfb4048f412bcb415a52cb98651f9ed", - "0x53dc703b78794b61281812f3a901918253beefee", - "0x55095300bdcb3026b48b4ad05a5feaaba801aac9", - "0x5cb98367c32d8a1d910461c572c558d57ca68d25", - "0x5eef9ab433f598d408ec30adf58d182a07a1189d", - "0x6b04ce6e4d728a97bafd1c78f8ea46b73ada552d", - "0x6c6fc818b25df89a8ada8da5a43669023bad1f4c", - "0x7064a1ea78961ef05a510e86540235a4a2e64ca4", - "0x7174c5aadc47e0b706c333467d2a3b126eb6ed15", - "0x73ee7d74a1fe9d768112ba40549bc9c2003f9b63", - "0x757caf1bd60b4e16d6b91f03169a66149306de7a", - "0x7a2b6d8325c3912939229272256769b06cedb1b2", - "0x7fafd253ea3f8351e02135b8f0d4ed31a6e7a59d", - "0x857d1b4f80ecb6ad7e4e7d120ffc1292ee8ddafc", - "0x85dd09159b42417c1e0782fa2c6ba3b790be9ead", - "0x87da68bfbaf58ba6a29fed851f0411e7c989b68b", - "0x991322ee666ec384eeb31bbd97b4dc0c2df14ce1", - "0x99903bb64e9c1e54a10723afa7f9a094c9f783c8", - "0xa2cc3e531f49e6e1b0e360f371e6171f5aeaec91", - "0xa495a38ea3728ac29096c86ca30127003f33af28", - "0xa53620f536e2c06d18f02791f1c1178c1d51f955", - "0xa7b1d843ae0c0e5e561149d7624f9e469fcacf4d", - "0xab1e2d29699146a2e07c3a1c8ad8cb914a536f7a", - "0xaf29b974b47d900bc6746bf9979be8edc8790a20", - "0xb04f13750cd764eeceb07e19254564787c9c72bf", - "0xba7f8b8cf0f13f8d90d4e364d43a3ddd57f39da0", - "0xbe633b67d7d4197b798179066b503ecd9c04d05b", - "0xbfe59fd293c4c19487a20178f384be62867bf875", - "0xc27f074873af25378270cc50b9854cf7a013eab6", - "0xcb2e6adc815195069977692de2f6e22e920a6b1b", - "0xccb606939387c0274aaa2426517da315c1154e50", - "0xcf4595ae4e43bc8c7be90849babc1da27e47813c", - "0xd1e50b60287faada2a7d5ea5632df78f7f2f0cb8", - "0xddcd60dcc952023ec4bcd27788384f06e901e61e", - "0xe1f9a04aeaf788b1494721317c812145dcef2359", - "0xe870c025ede621834f538468034398cff26ac926", - "0xe8d7a52aabe8a0569314f28e90fdb8544860a424", - "0xe94f1ec6aaaba70e109535f88d0c836ce044fd16", - "0xeab253203605d0b2ca7bde2157009d121cffdd27", - "0xeb061a4e1ad3f1983655281cb8019ebbf8b30b29", - "0xeb0f2c77ee979adb69f718b4027d3783b27b0f9e", - "0xebac4a08dbe9b33320f73b7bc8c3559ff042a9d9", - "0xedf1335a6f016d7e2c0d80082688cd582e48a6fc", - "0xf4b0e6fad7443fbb7bbfea7dc1cbe7bf7e574b03", - "0xf59ce000475cc3962cd366ce05ea2fd6fea5b8aa", - "0xf7c3d9615221dfa89a835ec5d56dea2990eae54a", - "0xf7c8ab6912894393e6ee9c0222c672a4441dfea2", - "0xf8fb2d6bb43f6a422bc1e2a15b0f85afce7e7f05", - "0xfc0c52a2b66a19b39efbe4332bc42186ada1ee45", - "0xff3074fd3bccc15b54d2c7fbfe48108a6116a321" - ], - "era":[ - "0x39E098A153Ad69834a9Dac32f0FCa92066aD03f4", - "0x02E3B9d5462e84518E309116D547c8C772a1C852" - ] - } - }, - { - "id":"597", - "name":"BabySwap", - "addresses":{ - "bsc":[ - "0x325E343f1dE602396E256B67eFd1F61C3A6B38Bd" - ] - } - }, - { - "id":"parent#mm-finance", - "name":"MM Finance", - "addresses":{ - "cronos":[ - "" - ], - "polygon":[ - "0x7E5E5957De93D00c352dF75159FbC37d5935f8bF" - ], - "arbitrum":[ - "0x4F879a9d95e01041dDAA607A65F04e0EDbD04139", - "0x20AB386813F59B92e1C4596f22591bEe92935d83",//v3smartrouter - "0x611c9F2f536E087BE7d0F02D9F99e5CE9b7E175B" - ] - } - }, - { - "id":"2400", - "name":"Solidly V2", - "addresses":{ - "ethereum":[ - "0x77784f96C936042A3ADB1dD29C91a55EB2A4219f" - ] - } - }, - { - "id":"622", - "name":"Clipper", - "addresses":{ - "ethereum":[ - "0xE7b0CE0526fbE3969035a145C9e9691d4d9D216c" - ], - "arbitrum":[ - "0xE7b0CE0526fbE3969035a145C9e9691d4d9D216c", - "0x9E233DD6a90678BaaCd89c05ce5C48f43fCc106E" - ], - "optimism":[ - "0x5130f6cE257B8F9bF7fac0A0b519Bd588120ed40", //ClipperPackedVerifiedExchange - "0xF33141BC4E9D1d92a2Adba2fa27A09c2DA2AF3eB" //ClipperPermitRouter - ], - "polygon":[ - "0x6Bfce69d1Df30FD2B2C8e478EDEC9dAa643Ae3B8", - "0xF33141BC4E9D1d92a2Adba2fa27A09c2DA2AF3eB" //ClipperPermitRouter - ], - "moonbeam":[ - "0xCE37051a3e60587157DC4c0391B4C555c6E68255" - ], - "mantle":[ - "0x769728b5298445BA2828c0f3F5384227fbF590C5" //ClipperPackedVerifiedExchange - ] - } - }, - { - "id":"1732", - "name":"Verse", - "addresses":{ - "ethereum":[ - "0xB4B0ea46Fe0E9e8EAB4aFb765b527739F2718671" - ], - "smartbch":[ - "" - ] - } - }, - { - "id":"2283", - "name":"3xcalibur", - "addresses":{ - "arbitrum":[ - "0x8e72bf5A45F800E182362bDF906DFB13d5D5cb5d" - ] - } - }, - { - "id":"311", - "name":"SpiritSwap AMM", - "addresses":{ - "fantom":[ - "0x16327E3FbDaCA3bcF7E38F5Af2599D2DDc33aE52" - ] - } - }, - { - "id":"602", - "name":"BakerySwap", - "addresses":{ - "bsc":[ - "0xCDe540d7eAFE93aC5fE6233Bee57E1270D3E330F" - ] - } - }, - { - "id":"942", - "name":"KnightSwap Finance", - "addresses":{ - "bsc":[ - "0x05E61E0cDcD2170a76F9568a110CEe3AFdD6c46f" - ], - "fantom":[ - "0x045312C737a6b7a115906Be0aD0ef53A6AA38106" - ] - } - }, - { - "id":"1461", - "name":"WOOFi Swap", - "addresses":{ - "fantom":[ - "0x382A9b0bC5D29e96c3a0b81cE9c64d6C8F150Efb" - ], - "avax":[ - "0xC22FBb3133dF781E6C25ea6acebe2D2Bb8CeA2f9" - ], - "arbitrum":[ - "0x9aEd3A8896A85FE9a8CAc52C9B402D092B629a30" - ], - "bsc":[ - "0xC90bFE9951a4Efbf20aCa5ECd9966b2bF8A01294" - ], - "optimism":[ - "0xEAf1Ac8E89EA0aE13E0f03634A4FF23502527024" - ], - "polygon":[ - "0x817Eb46D60762442Da3D931Ff51a30334CA39B74" - ], - "ethereum":[ - "0x9D1A92e601db0901e69bd810029F2C14bCCA3128" - ] - } - }, - { - "id":"863", - "name":"Yoshi Exchange", - "addresses":{ - "bsc":[ - "0x3a547932e0818403b39fD2453AE74c9004FB902E" - ], - "fantom":[ - "0xE4a4642B19C4d0CBA965673cd51422b1EDA0a78d" - ], - "ethereum":[ - "0x3aB65d9C1616FF780e1853330a219497CF5D9B67" - ] - } - }, - { - "id":"271", - "name":"Honeyswap", - "addresses":{ - "polygon":[ - "0xaD340d0CD0B117B0140671E7cB39770e7675C848" - ], - "xdai":[ - "" - ] - } - }, - { - "id":"2129", - "name":"Tomb Swap", - "addresses":{ - "fantom":[ - "0x6D0176C5ea1e44b08D3dd001b0784cE42F47a3A7" - ] - } - }, - { - "id":"1351", - "name":"WigoSwap", - "addresses":{ - "bsc":[ - "0x5023882f4D1EC10544FCB2066abE9C1645E95AA0" - ] - } - }, - { - "id":"2603", - "name":"AlienFi", - "addresses":{ - "arbitrum":[ - "0x863e9610E9E0C3986DCc6fb2cD335e11D88f7D5f", - "0xB8ca857dCd90AfBeD93B30DdCd4E4CC1327c9e5c", - "0xbd796fac59914dB9A7CBC21f1053c7DC1b900fEA",//masterchef - "0x8923d3EFEE38e7bb1E8988B024D5169C962CFB73",//masterchef - "0x4Ad7C3F11ec54d7D066dd114ac403022d3F97E6F",//masterchef - ] - } - }, - { - "id":"373", - "name":"BiSwap", - "addresses":{ - "bsc":[ - "0x3a6d8cA21D1CF76F653A67577FA0D27453350dD8" - ] - } - }, - { - "id":"1823", - "name":"Nomiswap", - "addresses":{ - "bsc":[ - "0xD486D0846812266D21e1Ab6c57FCF202DF836dc8", - "0xD654953D746f0b114d1F85332Dc43446ac79413d", - "0x9D15d0d737e06a875F3d46621fB52fe79ffA6136", - "0x4eC3432d9443f05022e2Ff4E54fC7514BE2359e0", - "0xbF4c0d66Db59Ae8276e0cB7E1Ed36fC4Ac8C1d68" - ] - } - }, - { - "id":"1295", - "name":"BurgerSwap", - "addresses":{ - "bsc":[ - "0xe08Ab553720a46C071475838a6cC8D98D1Afb891", - "0xEfC254D0cdb1924149382d404A2133532D46A777", - "0xfa9cCB91d28d35E12216e43d8990D31595783600", - "0xE3F08e81Ec8533D6CD7784B672e4237087b2A7c8" - ] - } - }, - { - "id":"2102", - "name":"Titano Swych", - "addresses":{ - "bsc":[ - "0x2Bf55D1596786F1AE8160e997D655DbE6d9Bca7A" - ] - } - }, - { - "id":"parent#arbswap", - "name":"Arbswap", - "addresses":{ - "arbitrum":[ - "0xD01319f4b65b79124549dE409D36F25e04B3e551" - ], - "arbitrum_nova":[] - } - }, - { - "id":"parent#polycat-finance", - "name":"Polycat Finance", - "addresses":{ - "polygon":[ - "0x94930a328162957FF1dd48900aF67B5439336cBD", - "0xfDC8579B2E19B489c4086eDE85A2D71949138be5",//tankchef - "0xfaBC099AD582072d26375F65d659A3792D1740fB",//tankchef - ] - } - }, - { - "id":"2384", - "name":"OreoSwap", - "addresses":{ - "arbitrum":[ - "0x38eEd6a71A4ddA9d7f776946e3cfa4ec43781AE6" - ] - } - }, - { - "id":"1824", - "name":"Swapsicle", - "addresses":{ - "arbitrum":[ - "0x3D42A6B7cD504cA2283Bc8F37fea859a11Ca89fb" - ], - "ethereum":[ - "0x3D42A6B7cD504cA2283Bc8F37fea859a11Ca89fb" - ], - "avax":[ - "0xC7f372c62238f6a5b79136A9e5D16A2FD7A3f0F5" - ], - "polygon":[ - "0x0427B42bb6ae94B488dcf549B390A368F8F69058" - ], - "bsc":[ - "0x63530632e8fE40aCf8f1f4324f7645256263b64f" - ], - "optimism":[ - "0x3D42A6B7cD504cA2283Bc8F37fea859a11Ca89fb" - ], - "fantom":[ - "0x422770Fcf2217AF03b4832e9f1F4Bd23946F828b" - ], - "telos":[ - "0x9b1adec00a25fffd87a5bb17f61916e1c26f6844" - ] - } - }, - { - "id":"2350", - "name":"KyotoSwap", - "addresses":{ - "bsc":[ - "0x9fd7764e2303E7748736D115304350eC64E403B2" - ] - } - }, - { - "id":"2101", - "name":"FstSwap", - "addresses":{ - "bsc":[ - "0xB3ca4D73b1e0EA2c53B42173388cC01e1c226F40" - ] - } - }, - { - "id":"2751", - "name":"LFGSwap", - "addresses":{ - "arbitrum":[ - "0xF83675ac64a142D92234681B7AfB6Ba00fa38dFF" - ], - "ethpow":[], - "core":[] - } - }, - { - "id":"2166", - "name":"LFGSwap EthereumPoW", - "addresses":{ - "ethpow":[] - } - }, - { - "id":"2647", - "name":"LFGSwap Core", - "addresses":{ - "core":[] - } - },/* - {//listed on compound-v2 users file - "id":"387", - "name":"Bearn", - "addresses":{ - "bsc":[ - "0xC6747954a9B3A074d8E4168B444d7F397FeE76AA", - "0x3d695c1607a085773547e07dEf1aD3CE3f518Edb",//bearnchef - ] - } - },*/ - { - "id":"659", - "name":"JetSwap", - "addresses":{ - "bsc":[ - "0xBe65b8f75B9F20f4C522e0067a3887FADa714800" - ] - } - }, - { - "id":"2749", - "name":"Antfarm finance", - "addresses":{ - "ethereum":[ - "0x6d9f0eb21d77c6d24be49a579508471e937d5418" - ], - "arbitrum":[ - "0x1272ba8c0bd855ff15c4b29bad660e6f154fca28" - ], - "polygon_zkevm":[ - "0x61f4ECD130291e5D5D7809A112f9F9081b8Ed3A5" - ] - } - }, - { - "id":"2763", - "name":"Dove Swap", - "addresses":{ - "polygon_zkevm":[ - "0xc4212b4f901C8Afac75A27C8E8be7b9fa82D74d8" - ] - } - }, - { - "id":"2762", - "name":"Dove Swap", - "addresses":{ - "polygon_zkevm":[ - "0xc4212b4f901C8Afac75A27C8E8be7b9fa82D74d8" - ] - } - }, - { - "id":"561", - "name":"Alita Finance", - "addresses":{ - "bsc":[ - "0x730aCC3bBf2443f2EaEaCFc7ac7b4d8DC9E32dB8", - "0x4f7b2Be2bc3C61009e9aE520CCfc830612A10694", - "0x28162cda1E767663F68B759AF47801171Aa58815",//incentive - "0x8ED5fABddb6f899f7FaCf461587f4dAd065AAae7",//masterchef - ] - } - }, - { - "id":"2333", - "name":"Alita Finance", - "addresses":{ - "bsc":[ - "0xbd67d157502A23309Db761c41965600c2Ec788b2" - ] - } - }, - { - "id":"2118", - "name":"WinerySwap", - "addresses":{ - "bsc":[ - "0xB115C8392C4C416b227e98d9bbb394bFD03BE965", - "0x8B07c6CB1b2edA3942369EEC9DF8e12213f99181", - "0x8bfFB5562ff30f555894E101E6DAD31D271EEd5a", - "0xBd27399a5aA720250b37b6864F293A27F3D2A043",//masterchef - "0x21694642bea2D2E0B0f5129a25D753dd9fB9623A",//masterchef - ] - } - }, - { - "id":"317", - "name":"HyperJump", - "addresses":{ - "bsc":[ - "0x3bc677674df90A9e5D741f28f6CA303357D0E4Ec" - ], - "fantom":[ - "0x53c153a0df7E050BbEFbb70eE9632061f12795fB" - ], - "metis":[ - "0xd96aeE439e6e5B4f3544bF105eb78F3b8B6CD774" - ] - } - }, - { - "id":"2429", - "name":"Paraluni Dex", - "addresses":{ - "bsc":[ - "0xb3ca41D538998f884D9f8cE33703A7f49F112E98" - ] - } - }, - { - "id":"575", - "name":"Coinswap Space", - "addresses":{ - "bsc":[ - "0x34DBe8E5faefaBF5018c16822e4d86F02d57Ec27" - ] - } - }, - { - "id":"544", - "name":"SoulSwap", - "addresses":{ - "fantom":[ - "0x6b3d631B87FE27aF29efeC61d2ab8CE4d621cCBF", - "0x994889A5a2BcfAB67e5242996e1331b74d777834", - "0x2CDa3B64Da9c1b7F18891E1567bc43eD558D089b" - ], - "avax":[ - "0xa4594460A9d3D41e8B85542D34E23AdAbc3c86Ef", - "0xE15d319896038aB76f2bc7cE15CBc2689b498570" - ] - } - }, - { - "id":"695", - "name":"Dinosaur Eggs", - "addresses":{ - "bsc":[ - "0xE9C7650b97712C0Ec958FF270FBF4189fB99C071" - ] - } - }, - { - "id":"1306", - "name":"ProtoFi", - "addresses":{ - "fantom":[ - "0xF4C587a0972Ac2039BFF67Bc44574bB403eF5235" - ] - } - }, - { - "id":"1893", - "name":"MIND Games", - "addresses":{ - "arbitrum":[ - "0x750eD5cF0f5278be9C6562399f0791dD221C4f83" - ] - } - }, - { - "id":"595", - "name":"Convergence", - "addresses":{ - "ethereum":[ - "0x8Cda39226daf33ae1Aba0C92C34d1a1982Cf0210", - "0x37c7C2ae51E968CEfB82cFF2102727256D36D6eE" - ], - "moonbeam":[] - } - }, - { - "id":"367", - "name":"PinkSwap", - "addresses":{ - "bsc":[ - "0x319EF69a98c8E8aAB36Aea561Daba0Bf3D0fa3ac" - ] - } - }, - { - "id":"867", - "name":"GIBXSwap", - "addresses":{ - "bsc":[ - "0x2fB9Cee9d580cD12E671b8789F2f9fb228A5d2bc" - ] - } - }, - { - "id":"2577", - "name":"Sharky Swap", - "addresses":{ - "arbitrum":[ - "0x29631E68d81b0e02a507f54a799402E8Cfa6a4d8" - ] - } - }, - { - "id":"2203", - "name":"Tetu Swap", - "addresses":{ - "polygon":[ - "0xBCA055F25c3670fE0b1463e8d470585Fe15Ca819" - ] - } - }, - { - "id":"384", - "name":"Firebird", - "addresses":{ - "polygon":[ - "0xb31D1B1eA48cE4Bf10ed697d44B747287E785Ad4" - ], - "avax":[ - "0xe0C38b2a8D09aAD53f1C67734B9A95E43d5981c0" - ], - "arbitrum":[ - "0x0c6134Abc08A1EafC3E2Dc9A5AD023Bb08Da86C3" - ], - "dogechain":[ - "0xe0C38b2a8D09aAD53f1C67734B9A95E43d5981c0" - ], - "bsc":[ - "0x92e4F29Be975C1B1eB72E77De24Dccf11432a5bd" - ], - "cronos":[ - "0x4A5a7331dA84d3834C030a9b8d4f3d687A3b788b" - ], - "ethereum":[ - "0xe0C38b2a8D09aAD53f1C67734B9A95E43d5981c0" - ], - "fantom":[ - "0xe0C38b2a8D09aAD53f1C67734B9A95E43d5981c0" - ], - "optimism":[ - "0x0c6134Abc08A1EafC3E2Dc9A5AD023Bb08Da86C3" - ] - } - }, - { - "id":"421", - "name":"Paint Swap", - "addresses":{ - "fantom":[ - "0xfD000ddCEa75a2E23059881c3589F6425bFf1AbB" - ] - } - }, - { - "id":"1349", - "name":"Degen Haus", - "addresses":{ - "fantom":[ - "0xC681174dc7639305d762E016cD3aFf93219D6cc1" - ] - } - }, - { - "id":"473", - "name":"Baguette", - "addresses":{ - "avax":[ - "0xF7b1e993d1b4F7348D64Aa55A294E4B74512F7f2" - ] - } - }, - { - "id":"429", - "name":"BambooDeFi", - "addresses":{ - "bsc":[ - "0xBA9DF2c143C502A433d6A876C1a291C9FC940cf9" - ] - } - }, - { - "id":"978", - "name":"ChickenSwap", - "addresses":{ - "ethereum":[ - "0xB72F87Df6B5C004227B6a045fD451cb716669150" - ] - } - }, - { - "id":"976", - "name":"WingSwap", - "addresses":{ - "fantom":[ - "0x2b660040b289B1B570E053b21dd9A6F1067AD7F5" - ] - } - }, - { - "id":"692", - "name":"HurricaneSwap", - "addresses":{ - "avax":[ - "0xb9a9BB6CC39387548BAA7185fbFf51d47eef8771", - "0xB6559dD3cBec057078fBd9477e676a24cCEA0609", - "0x010D464fE46ABA2FB468a4BB251248d669C67c72" - ] - } - }, - { - "id":"293", - "name":"Lydia", - "addresses":{ - "avax":[ - "0xA52aBE4676dbfd04Df42eF7755F01A3c41f28D27" - ] - } - }, - { - "id":"2687", - "name":"OpenXswap", - "addresses":{ - "optimism":[ - "0x744776F27080b584D447A780ba260c435f3aE7d5", - "0x6e0CEf87B1D55ec54d657f0aDA04AE2c90A470bA" - ] - } - }, - { - "id":"815", - "name":"PureSwap", - "addresses":{ - "bsc":[ - "0x3e8743B5453A348606111AB0a4dEe7F70A87f305" - ] - } - }, - { - "id":"391", - "name":"PantherSwap", - "addresses":{ - "bsc":[ - "0xf5048C225a0D220cd784D81f4e07F137fAf35FF8", - "0x24f7C33ae5f77e2A9ECeed7EA858B4ca2fa1B7eC" - ] - } - }, - { - "id":"396", - "name":"Polydex", - "addresses":{ - "polygon":[ - "0xC60aE14F2568b102F8Ca6266e8799112846DD088", - "0x5a56cB06d143a7cC0597c4804D5D76f2d5c2be81", - "0x512Ff58276046636590767B88f418DD84E47ce78", - "0x56A0b8BA16A84959541CcB3F42E7A9a9d16428F4" - ] - } - }, - { - "id":"1871", - "name":"HunnySwap", - "addresses":{ - "avax":[ - "0x8685aBD6959745E41D64194F42e21bbD25Fd57B3" - ] - } - }, - { - "id":"289", - "name":"YetiSwap", - "addresses":{ - "avax":[ - "0x262DcFB36766C88E6A7a2953c16F8defc40c378A" - ] - } - }, - { - "id":"287", - "name":"0.exchange", - "addresses":{ - "avax":[ - "0x85995d5f8ee9645cA855e92de16FA62D26398060" - ], - "bsc":[ - "0xba79bf6D52934D3b55FE0c14565A083c74FBD224" - ], - "polygon":[ - "0x9894B0F28CcfA0F5c5F74EAC88f161110C5F8027" - ] - } - }, - { - "id":"2098", - "name":"Muffin", - "addresses":{ - "ethereum":[ - "0xded07E2da859714F69d93f9794344606Ed67907E" - ] - } - }, - { - "id":"532", - "name":"Twindex", - "addresses":{ - "bsc":[ - "0x6B011d0d53b0Da6ace2a3F436Fd197A4E35f47EF", - "0xBCB41906bE2C2724A8CD0dec87512B2463535586", - "0xdd3565Bd68ef6882657fB17BCD66b436f819eBF3" - ] - } - }, - { - "id":"471", - "name":"Complus Network", - "addresses":{ - "avax":[ - "0x78c18E6BE20df11f1f41b9635F3A18B8AD82dDD1" - ], - "bsc":[ - "0x07DC75E8bc57A21A183129Ec29bbCC232d79eE56" - ], - "polygon":[ - "0x07DC75E8bc57A21A183129Ec29bbCC232d79eE56" - ], - "heco":[] - } - }, - { - "id":"2779", - "name":"ZenithSwap", - "addresses":{ - "arbitrum":[ - "0x8CA9EF098F84ceDa319Ec12B9d21EeF50AA3624C" - ] - } - }, - { - "id":"2863", - "name":"SaitaSwap", - "addresses":{ - "ethereum":[ - "0x0c17e776CD218252ADFca8D4e761D3fe757e9778", - "0x744A4c9c9F40A443ac2A5747D4f3b773e5d86763" - ], - "bsc":[ - "0x744A4c9c9F40A443ac2A5747D4f3b773e5d86763" - ] - } - }, - { - "id":"parent#skullswap", - "name":"SkullSwap", - "addresses":{ - "fantom":[ - "0x0A239A1fC3Bb5abc6F06ad950e52996308E8E925", - "0xe8E357B75823D1Cc133ED7265a27BC2D9237527c", - "0xA4C5457Eca4E36db9062871631351eF627146044", - "0x6d6E00B42c599ad8F70b2C006ad5135bF93Eb396" - ] - } - }, - { - "id":"2846", - "name":"Solisnek Finance", - "addresses":{ - "avax":[ - "0xeeee17b45E4d127cFaAAD14e2710489523ADB4d8" - ] - } - }, - { - "id":"2803", - "name":"Native", - "addresses":{ - "ethereum":[ - "0x7A27BBD83b5065eEFf85411DFE048Eaac9be2A9D", - "0xF1aF55CC38A92A3b072D05e146E27c2E75bB8F2D" - ], - "bsc":[ - "0x7A27BBD83b5065eEFf85411DFE048Eaac9be2A9D", - "0x83B9fcea670d66626d9db79Af00fc718014C3de8" - ] - } - }, - { - "id":"2821", - "name":"Hamburger Finance", - "addresses":{ - "arbitrum":[ - "0xE5e5Cd7685755BF4c82137639d75b068ed657384" - ] - } - }, - { - "id":"2812", - "name":"Forge SX Trade", - "addresses":{ - "arbitrum":[ - "0xE5e5Cd7685755BF4c82137639d75b068ed657384" - ] - } - }, - { - "id":"2806", - "name":"AstroFi", - "addresses":{ - "ethereum":[ - "0x42c76F3BBC2E4d505420fE5bda4C316fA5234624" - ] - } - }, - { - "id":"2773", - "name":"Auragi Finance", - "addresses":{ - "arbitrum":[ - "0x0FaE1e44655ab06825966a8fCE87b9e988AB6170" - ] - } - }, - { - "id":"2757", - "name":"Glacier Finance", - "addresses":{ - "avax":[ - "0xC5B8Ce3C8C171d506DEb069a6136a351Ee1629DC" - ] - } - }, - { - "id":"2731", - "name":"Swapline", - "addresses":{ - "fantom":[ - "0xb2755FeEc193a718f6135351057a63b2F7B95cef", - "0xFC33f3cac9f6d1713a4B7787dF6a9a33bAD244d6", - "0x795bF60522F36244E4e51ed5522fE83Df4D3Bf9a" - ] - } - }, - { - "id":"2721", - "name":"Flair Dex", - "addresses":{ - "avax":[ - "0xd79eE05678241C16e6195b9FC0bCc778A02d4324", - "0xBfC8f125CFce29789500987A9553395E84bDfDD2" - ] - } - }, - /* - { //uses firebird router to swap - "id":"2720", - "name":"Satin Exchange", - "addresses":{ - "polygon":[ - "0xb31D1B1eA48cE4Bf10ed697d44B747287E785Ad4"//firebird router - ] - } - },*/ - /*{ // commented due to inactive project/returning error - "id":"392", - "name":"WardenSwap", - "addresses":{ - "bsc":[ - "0x451ef8D6B645a60115EB8b8bEa76B39C0C761004", - "0x71ac17934b60A4610dc58b715B61e45DCBdE4054", - ], - "ethereum":[ - "0x39f97198c5DbC193EB962c4B3B7e447091A18eAB" - ], - "avax":[ - "0x5EF960Eb78B8CFc11e654D03BeEB313BaDF5C7C0" - ], - "arbitrum":[ - "0x79A556ef2c5b613dB3DFa8797E6772c5AAF86834" - ], - "optimism":[ - "0x7EA8c22E6Dcd7bd69eb180664Da68e1f1F11D696" - ], - } - },*/ - { - "id":"351", - "name":"Gravity Finance", - "addresses":{ - "polygon":[ - "0x57dE98135e8287F163c59cA4fF45f1341b680248", - "0xF2e6b6d7F3b62449260ac87B66cEf9e2664C26d7", - "0xb4A1F1Dd67e129190feeB4bcADB5298D434d54f2", - "0x57dE98135e8287F163c59cA4fF45f1341b680248", - "0xEbe141dE74F1E6377f53551C275568d7bcBC4119" - ] - } - }, - { - "id":"1296", - "name":"ZipSwap", - "addresses":{ - "arbitrum":[ - "0x4D70D768f5E1e6a7062973aFB0c7FBDa9bBb42b3" - ], - "optimism":[ - "0xE6Df0BB08e5A97b40B21950a0A51b94c4DbA0Ff6", - "0x00000000000013adDDC0919642d45f5d9Df09502" - ] - } - }, - { - "id":"1364", - "name":"Narwhalswap", - "addresses":{ - "bsc":[ - "0x849B7b4541CDE9cBE41cfd064d9d7fF459b9cEa4" - ] - } - }, - { - "id":"1074", - "name":"AutoShark", - "addresses":{ - "bsc":[ - "0xB0EeB0632bAB15F120735e5838908378936bd484" - ] - } - }, - { - "id":"883", - "name":"SmartDEX", - "addresses":{ - "polygon":[ - "0x6f5fE5Fef0186f7B27424679cbb17e45df6e2118" - ] - } - }, - { - "id":"2331", - "name":"SwapFish", - "addresses":{ - "arbitrum":[ - "0xcDAeC65495Fa5c0545c5a405224214e3594f30d8" - ], - "bsc":[ - "0xcDAeC65495Fa5c0545c5a405224214e3594f30d8" - ] - } - }, - { - "id":"409", - "name":"CafeSwap", - "addresses":{ - "polygon":[ - "0x9055682E58C74fc8DdBFC55Ad2428aB1F96098Fc" - ], - "bsc":[ - "0x933DAea3a5995Fb94b14A7696a5F3ffD7B1E385A" - ] - } - }, - { - "id":"1530", - "name":"Excalibur", - "addresses":{ - "fantom":[ - "0xc8Fe105cEB91e485fb0AC338F2994Ea655C78691" - ] - } - }, - { - "id":"1359", - "name":"CapitalDEX", - "addresses":{ - "ethereum":[ - "0xDc6844cED486Ec04803f02F2Ee40BBDBEf615f21" - ] - } - }, - { - "id":"1253", - "name":"HakuSwap", - "addresses":{ - "avax":[ - "0xE6e79A66cB32c53A9d56B18FA737fb5D72c71475", - "0x5F1FdcA239362c5b8A8Ada26a256ac5626CC33E0" - ] - } - }, - { - "id":"455", - "name":"ZooCoin", - "addresses":{ - "fantom":[ - "0x40b12a3E261416fF0035586ff96e23c2894560f2", - "0xA7843036252e79fBc495814e714F1439dF8Dc8a4" - ] - } - }, - { - "id":"1750", - "name":"CryptoSwap", - "addresses":{ - "bsc":[ - "0xe4964c56f46063F25f2a77269B36a773140Ab325" - ] - } - }, - { - "id":"2865", - "name":"Moonbase Alpha", - "addresses":{ - "arbitrum":[ - "0x88FcF70243B4BCC0325060805b7bE9b3DA984805", - "0x5cb6600359Cd392A6Ffea69781d1C6db6A25A18F",//masterchef - ] - } - }, - { - "id":"1150", - "name":"WraithSwap", - "addresses":{ - "fantom":[ - "0x8C9E059a729C17fB294cd782eB66Df3871D29173", - "0x37b106f101a63D9d06e53140E52Eb6F8A3aC5bBc",//masterchef - ] - } - }, - { - "id":"920", - "name":"Raven", - "addresses":{ - "fantom":[ - "0xbCEf0849DDd928835A6Aa130aE527C2703CD832C",//masterchef - "0x2639779d6CA9091483a2A7b9A1FE77Ab83b90281",//masterchef - ] - } - }, - { - "id":"737", - "name":"Dino.Exchange", - "addresses":{ - "bsc":[ - "0xe12405F0A569A9402fF563FB923A96DC2525D3Eb", - "0xc2a88eCE6B6321819D947c9EadEABBa699c16349", - ] - } - }, - { - "id":"1363", - "name":"Oni Exchange", - "addresses":{ - "bsc":[ - "0x3f49193f91a07bb87102e5768fa7a61692EA4D9c", - "0x974A8959c52f6109C59d0A6D63D4eA4CC522DfA2", - "0x09a8521FC838D795555113Fcb5b8fC8C267783F9",//masterchef - "0xE93fC7e6103EF86F3329635B8197D462B74F0cb8",//masterchef - ] - } - }, - { - "id":"1857", - "name":"FATExFi", - "addresses":{ - "polygon":[ - "0x8863f716706e9e4f13A52601A129DD1E1c3fA08B" - ] - } - }, - { - "id":"1859", - "name":"AuraSwap", - "addresses":{ - "polygon":[ - "0x09Fd8B8ed6E30e583379Dc73b9261dF5E1A28b6F", - "0x44Bb1a3E56Cb12b7B1a8E925f09A170e3646346d",//masterchef - ] - } - }, - { - "id":"1018", - "name":"Gains Network", - "addresses":{ - "polygon":[ - "0x91993f2101cc758D0dEB7279d41e880F7dEFe827",//gdai - "0xFb06a737f549Eb2512Eb6082A808fc7F16C0819D",//staking - "0x4ba64a81ca50D8B66684C664d75b55eaCcFaCAEb",//trading - "0x8103C0665A544201BBF606d90845d1B2D8005F1c",//nftrewards - "0xd285f881886505b9Ef6684E1aaa7949a56B0C7Da",//gnsmigration - "0xa33f7069f075A54481868e4C0b8D26925A218362",//lockingbridge - "0xDF774A4F3EA5095535f5B8f5b9149caF90FF75Bd",//erc20bridge - "0x2D266A94469d05C9e06D52A4D0d9C23b157767c2",//GFarmNft5 - "0x02e2c5825C1a3b69C0417706DbE1327C2Af3e6C2",//GFarmNft4 - "0x3378AD81D09DE23725Ee9B9270635c97Ed601921",//GFarmNft3 - "0x77cd42B925e1A82f41d852D6BE727CFc88fddBbC",//GFarmNft2 - "0x7075cAB6bCCA06613e2d071bd918D1a0241379E2",//GFarm2Token(old) - "0xF9A4c522E327935BD1F5a338c121E14e4cc1f898",//GFarmNft1 - ], - "arbitrum":[ - "0xd85E038593d7A098614721EaE955EC2022B9B91B",//gdai - "0x6B8D3C08072a020aC065c467ce922e3A36D3F9d6",//staking - "0x4ba64a81ca50D8B66684C664d75b55eaCcFaCAEb",//trading - "0x8103C0665A544201BBF606d90845d1B2D8005F1c",//nftrewards - "0xd285f881886505b9Ef6684E1aaa7949a56B0C7Da",//gnsmigration - "0x0F9E4375facBeB90DAA850f677819b438ce50827",//ERC721MintingBridge - "0x01cAaaA682Ceba8cd6c02f93BB1393fB415fA5e2",//erc20bridge - "0x5e3b541Ad6AcC4381C110247946C863e05ffc9BE",//GFarmNft5 - "0x40F0AeaB6383Be2f254cE40B79089070Fa1a21A1",//GFarmNft4 - "0x9834159EAF9811cf4C568294D5C7C9158F84b384",//GFarmNft3 - "0xD1F024ba4Dbb1593B486cB5031b3AC5aC28e8A4e",//GFarmNft2 - "0x75cbcc5414C539C2B302A5fA60E30B949D2D6F89",//GFarmNft1 - ], - "ethereum":[ - "0x14e2f9B0381Af4227D26BEE7d8E4D424466A7F3F",//GFarmNftSwap - "0x151757c2E830C467B28Fe6C09c3174b6c76aA0c5",//GNSPoolV5 - "0x1E887E7115321B4ee5d58DD446eC09e12B45d81B",//GFarm - "0x5cA058C1c9E0Bea6b9b5366ADf73BC7f63aDc2d7",//GFarmNFTExchange - ] - } - }, - { - "id":"337", - "name":"GMX", - "addresses":{ - "arbitrum":[ - "0x489ee077994B6658eAfA855C308275EAd8097C4A",//Vault - "0xaBBc5F99639c9B6bCb58544ddf04EFA6802F4064",//Router - "0xb87a436B93fFE9D75c5cFA7bAcFff96430b09868",//PositionRouter - "0x09f77E8A13De9a35a7231028187e9fD5DB8a2ACB",//OrderBook - "0x5402B5F40310bDED796c7D0F3FF6683f5C0cFfdf",//StakedGlp - "0xA906F338CB21815cBc4Bc87ace9e68c87eF8d8F1",//RewardRouterV2 - ], - "avax":[ - "0x9ab2De34A33fB459b538c43f251eB825645e8595",//Vault - "0x5F719c2F1095F7B9fc68a68e35B51194f4b6abe8",//Router - "0xffF6D276Bc37c61A23f06410Dce4A400f66420f8",//PositionRouter - "0x4296e307f108B2f583FF2F7B7270ee7831574Ae5",//OrderBook - "0xaE64d55a6f09E4263421737397D1fdFA71896a69",//StakedGlp - "0x82147C5A7E850eA4E28155DF107F2590fD4ba327",//RewardRouterV2 - ] - } - }, - { - "id":"2254", - "name":"MUX Protocol", - "addresses":{ - "arbitrum":[ - "0x917952280770Daa800E1B4912Ea08450Bf71d57e",//Vault - "0x3e0199792Ce69DC29A0a36146bFa68bd7C8D6633",//liquiditypool - "0x02FAe054ACD7FB1615471319c4E3029DFbC2B23C",//liquiditymanager - "0xa19fD5aB6C8DCffa2A295F78a5Bb4aC543AAF5e3",//OrderBook - "0xaf9C4F6A0ceB02d4217Ff73f3C95BbC8c7320ceE",//RewardRouter - ], - "bsc":[ - "0x8D751570BA1Fd8a8ae89E4B27d18bf6C321Aab0a",//Vault - "0x855E99F768FaD76DD0d3EB7c446C0b759C96D520",//liquiditypool - "0xee85CDdCe0CF068091081eA0fcd53f279aa3B09F",//liquiditymanager - "0xa67aA293642C4e02D1b9F360b007C0dBDc451A08",//OrderBook - ], - "avax":[ - "0x29a28cC3FdC128693ef6a596eF45c43ff63B7062",//Vault - "0x0bA2e492e8427fAd51692EE8958eBf936bEE1d84",//liquiditypool - "0x28f16eB86481066Bf63BcBEB05C8474f7120A36C",//liquiditymanager - "0x5898c3E218a8501533d771C86e2fA37743ea2aDd",//OrderBook - ], - "optimism":[ - "0x39d653884B611E0A8dbdb9720Ad5D75642fd544b",//Vault - "0xc6BD76FA1E9e789345e003B361e4A0037DFb7260",//liquiditypool - "0xFEc3704f4A02cB0EE6C7d52Cbf72b11E0441E9d5",//liquiditymanager - "0x6Fde9892Fd5302ac3c68688085BD5b031A63BC9D",//OrderBook - ], - "fantom":[ - "0xdAF2064F52F123EE1D410e97C2df549c23a99683",//Vault - "0x2e81F443A11a943196c88afcB5A0D807721A88E6",//liquiditypool - "0x5898c3E218a8501533d771C86e2fA37743ea2aDd",//liquiditymanager - "0x0c30b10462CdED51C3CA31e7C51019b7d25a965B",//OrderBook - ], - } - }, - { - "id":"2395", - "name":"Level Finance", - "addresses":{ - "bsc":[ - "0xA5aBFB56a78D2BD4689b25B8A77fd49Bb0675874",//LiquidityPool - "0xB5C42F84Ab3f786bCA9761240546AA9cEC1f8821",//seniorLLP - "0x4265af66537F7BE1Ca60Ca6070D97531EC571BDd",//MezzanineLLP - "0xcC5368f152453D497061CB1fB578D2d3C54bD0A0",//Junior LLP - "0x1Ab33A7454427814a71F128109fE5B498Aa21E5d",//LevelMaster (old farming contract) - "0x5aE081b6647aEF897dEc738642089D4BDa93C0e7",//LevelMasterV2 (farming contract) - "0xf584A17dF21Afd9de84F47842ECEAF6042b1Bb5b",//OrderManager - ], - } - }, - { - "id":"2116", - "name":"0x", - "addresses":{ - "ethereum":[ - "0xdef1c0ded9bec7f1a1670819833240f027b25eff", - "0x61935CbDd02287B511119DDb11Aeb42F1593b7Ef",//Exchangev3 - "0x12459C951127e0c374FF9105DdA097662A027093",//Exchangev1 - "0x080bf510FCbF18b91105470639e9561022937712",//Exchangev2.1 - "0xa26e80e7Dea86279c6d778D702Cc413E6CFfA777",//StakingProxyv3 - ], - "bsc":[ - "0xdef1c0ded9bec7f1a1670819833240f027b25eff", - ], - "polygon":[ - "0xdef1c0ded9bec7f1a1670819833240f027b25eff", - ], - "avax":[ - "0xdef1c0ded9bec7f1a1670819833240f027b25eff", - ], - "fantom":[ - "0xdef189deaef76e379df891899eb5a00a94cbc250", - ], - "celo":[ - "0xdef1c0ded9bec7f1a1670819833240f027b25eff", - ], - "optimism":[ - "0xdef1abe32c034e558cdd535791643c58a13acc10", - ], - "arbitrum":[ - "0xdef1c0ded9bec7f1a1670819833240f027b25eff", - ], - } - }, - { - "id":"2899", - "name":"Vertex Protocol", - "addresses":{ - "arbitrum":[ - "0xbbee07b3e8121227afcfe1e2b82772246226128e", // endpoint - ], - } - }, - { - "id":"1917", - "name":"Sudoswap", - "addresses":{ - "ethereum":[ - "0x2b2e8cda09bba9660dca5cb6233787738ad68329", - "0xb16c1342e617a5b6e4b631eb114483fdb289c0a4", - ], - } - }, - { - "id":"340", - "name":"Olympus DAO", - "addresses":{ - "ethereum":[ - "0x007fe7c498a2cf30971ad8f2cbc36bd14ac51156", - "0x0b7ffc1f4ad541a4ed16b40d8c37f0929158d101", - "0x73D7e4BDdEcAd7379d679e60f22788E501493896", - "0xf577c77ee3578c7f216327f41b5d7221ead2b2a3", - "0xB63cac384247597756545b500253ff8E607a8020", - "0x007F7735baF391e207E3aA380bb53c4Bd9a5Fed6", - ], - } - }, - { - "id":"2907", - "name":"Chronos V1", - "addresses":{ - "arbitrum":[ - "0xE708aA9E887980750C040a6A2Cb901c37Aa34f3b",//routerv2 - "0x5D9dBA2D0ec06F44Da7e234cBB0d7BA921834AE8",//masterchef - "0xC72b5C6D2C33063E89a50B2F77C99193aE6cEe6c",//voter - - ], - } - }, - { - "id":"2903", - "name":"Swaprum", - "addresses":{ - "arbitrum":[ - "0x1342a24347532DE79372283B3A29c63C31Dd7711",//v2router - "0xEE6cbC97781ff3De7a068D2a6A2dec8CE3a05624",//SwaprumWithdrawals - ], - } - }, - { - "id":"2911", - "name":"Aboard Exchange", - "addresses":{ - "arbitrum":[ - "0x7a08b29A7Ad4A19A5ECa0c82F5F082872488D135",//PerpetualProxy - ], - } - }, - { - "id":"2902", - "name":"DAMX", - "addresses":{ - "fantom":[ - "0xD093eeE7c968CEef2df96cA9949eba1a1A9b2306",//Vault - "0xeD077045f38f864fba8aD9bdbF1CE8F108e5ddb9",//OrderBook - "0xECef79f974182f4E9c168E751101F23686Bdc6dF",//staking - ], - } - }, - { - "id":"2900", - "name":"Wasabi", - "addresses":{ - "ethereum":[ - "0xFc68f2130e094C95B6C4F5494158cbeB172e18a0",//Wasabi Option NFTs (WASAB) - "0xF29A66E420C240EbD23F775b93619C8F3cfFf856",//WasabiConduit - "0x8E2b50413a53F50E2a059142a9be060294961e40",//WasabiPoolFactory - ], - } - }, - { - "id":"2898", - "name":"LionDEX", - "addresses":{ - "arbitrum":[ - "0x8eF99304eb88Af9BDe85d58a35339Cb0e2a557B6",//vault - "0x154E2b1dBE9F493fF7938E5d686366138ddCE017",//staking - "0xFeb9Cc52aB4cb153FF1558F587e444Ac3DC2Ea82",//Escrowed LionDEX Token (esLION) - ], - } - }, - { - "id":"parent#smbswap", - "name":"SMBSwap", - "addresses":{ + "0xE3Ffc583dC176575eEA7FD9dF2A7c65F7E23f4C3", + ], "bsc":[ - "0xBDC5104a3C52A3f49f0324696f9Bb77E41516De7",//MasterChef - "0x009d611490eCfED2dC3F306231Bba7e7F3E9196E",//SMBRouter - "0x63C737E5BD543ECC0A02d91BfCb50845e1be31cF",//SMBRouter - "0x9D4823aa89Dc33ED53d930CB554AFFc58B0c9852",//SMBSwapLottery - "0x85C6129843D120454848F1Da39233AC4fcb50Cb4",//MasterChefV3 - "0x92D118350CAD5EbA374486dbe3d16A9FE66DaeBe",// SmartRouter + "0xb66A2704a0dabC1660941628BE987B4418f7a9E8", ], + "ethereum":[ + "0x9A93a421b74F1c5755b83dD2C211614dC419C44b"//Lbrouter + ] } - }, + },*/, + { + id: "2307", + name: "Camelot", + addresses: { + arbitrum: ["0xc873fEcbd354f5A56E00E710B90EF4201db2448d"], + }, + }, + { + id: "4372", + name: "Hercules", + addresses: { + metis: ["0x14679D1Da243B8c7d1A4c6d0523A2Ce614Ef027C"], + }, + }, + { + id: "parent#thena", + name: "Thena", + addresses: { + bsc: ["0xd4ae6eCA985340Dd434D38F470aCCce4DC78D109", "0x8f097E07a07Bf2F031E5513f764DaFC6Df58e818"], + }, + }, + { + id: "parent#bancor", + name: "Bancor", + addresses: { + ethereum: ["0x2F9EC37d6CcFFf1caB21733BdaDEdE11c823cCB0"], + }, + }, + { + id: "302", + name: "SpookySwap", + addresses: { + fantom: ["0x31F63A33141fFee63D4B26755430a390ACdD8a4d"], + }, + }, + { + id: "654", + name: "Beethoven X", + addresses: { + optimism: [ + "0xBA12222222228d8Ba445958a75a0704d566BF2C8", //Vault + ], + fantom: ["0x20dd72Ed959b6147912C2e529F0a0C651c33c9ce"], + }, + }, + { + id: "2121", + name: "Frax Swap", + addresses: { + arbitrum: ["0x16e71B13fE6079B4312063F7E81F76d165Ad32Ad"], + ethereum: ["0xC14d550632db8592D1243Edc8B95b0Ad06703867"], + optimism: ["0xB9A55F455e46e8D717eEA5E47D2c449416A0437F"], + bsc: ["0x67F755137E0AE2a2aa0323c047715Bf6523116E5"], + polygon: ["0x67F755137E0AE2a2aa0323c047715Bf6523116E5"], + avax: ["0x5977b16AA9aBC4D1281058C73B789C65Bf9ab3d3"], + fantom: ["0x7D21C651Dd333306B35F2FeAC2a19FA1e1241545"], + boba: [""], + harmony: [""], + aurora: [""], + evmos: [""], + moonbeam: [""], + dogechain: [""], + moonriver: [""], + }, + }, + { + id: "2169", + name: "BabyDogeSwap", + addresses: { + bsc: ["0xC9a0F685F39d05D835c369036251ee3aEaaF3c47"], + }, + }, + { + id: "parent#zyberswap", + name: "Zyberswap", + addresses: { + arbitrum: ["0xFa58b8024B49836772180f2Df902f231ba712F72", "0x16e71B13fE6079B4312063F7E81F76d165Ad32Ad"], + }, + }, + { + id: "246", + name: "Pangolin", + addresses: { + avax: ["0xE54Ca86531e17Ef3616d22Ca28b0D458b6C89106"], + }, + }, + { + id: "1883", + name: "iziSwap", + addresses: { + arbitrum: ["0x1CB60033F61e4fc171c963f0d2d3F63Ece24319c"], + polygon: ["0x879bF5D67fAB468879618AcD69E85C02E33b1c0B"], + bsc: ["0xBd3bd95529e0784aD973FD14928eEDF3678cfad8"], + aurora: [""], + telos: [""], + era: [""], + ethereumclassic: [""], + meter: [""], + cronos: [""], + }, + }, + { + id: "1700", + name: "Wombat Exchange", + addresses: { + bsc: [ + "0x19609B03C976CCA288fbDae5c21d4290e9a4aDD7", + "0x312Bc7eAAF93f1C60Dc5AfC115FcCDE161055fb0", + "0xE2C07d20AF0Fb50CAE6cDD615CA44AbaAA31F9c8", + "0x489833311676B566f888119c29bd997Dc6C95830", + "0x04D4e1C1F3D6539071b6D3849fDaED04d48D563d", + ], + arbitrum: [ + "0xc4B2F992496376C6127e73F1211450322E580668", + "0x9da4edBed6068666ea8EF6505C909e1ff8eA5725", + "0x62A83C6791A3d7950D823BB71a38e47252b6b6F4", + "0x3f90a5a47364c0467031fB00246192d40E3D2D9D", + ], + }, + }, + { + id: "2675", + name: "Ramses Exchange", + addresses: { + arbitrum: ["0xAAA87963EFeB6f7E0a2711F397663105Acb1805e"], + }, + } /* { - "id":"2886", - "name":"RabbitX", + "id":"parent#apeswap", + "name":"ApeSwap", "addresses":{ "ethereum":[ - "0xFc7f884DE22a59c0009C91733196b012Aecb8F41",//Rabbit - "0x4973710327eDc6f8238DD2d73cf0B2e081e1B351",//RabbitDeposit + "0x5f509a3C3F16dF2Fba7bF84dEE1eFbce6BB85587" ], - } - }, - { - "id":"2883", - "name":"Purple Bridge DEX", - "addresses":{ "polygon":[ - "0x1e2441Fd53C51d9CD1696BE2871eE672A0A01933", + "0xcF0feBd3f17CEf5b47b0cD257aCf6025c5BFf3b7" + ], + "bsc":[ + "0xcF0feBd3f17CEf5b47b0cD257aCf6025c5BFf3b7", + ], + "arbitrum":[ + "0x7d13268144adcdbEBDf94F654085CC15502849Ff" ], + "telos":[ + "0xb9667Cf9A495A123b0C43B924f6c2244f42817BE" + ] } + },*/, + { + id: "2332", + name: "Equalizer Exchange", + addresses: { + fantom: ["0x1A05EB736873485655F29a37DEf8a0AA87F5a447"], + }, }, { - "id":"2872", - "name":"printyfinance", - "addresses":{ - "avax":[ - "0x6A8f98d7e34Fd214B428BFc68c9309Ea3C4Fc7F1",//BaseV1Router01 - "0xDc72882909252E133a4A46eFB135b3B145366eba",//PrintyV1Router - "0x6902a8ecF99a732e5a73491Afc14e5E135eE4234",//BaseV2 - ], - } + id: "2528", + name: "SolidLizard", + addresses: { + arbitrum: ["0xF26515D5482e2C2FD237149bF6A653dA4794b3D0"], + }, }, { - "id":"parent#blur", - "name":"Blur", - "addresses":{ - "ethereum":[ - "0x29469395eAf6f95920E59F858042f0e28D98a20B",//ERC1967Proxy - "0x0000000000A39bb272e79075ade125fd351887Ac",//Blur bidding - ], - } + id: "944", + name: "Platypus Finance", + addresses: { + avax: [ + "0x7d7E30E269b7C7b447312d3FDE52e6f118F8e39e", + "0x73256EC7575D999C360c1EeC118ECbEFd8DA7D12", + "0x6f6FCbcc00f9AFBD2C266631087798740c685C3B", + ], + }, }, { - "id":"2919", - "name":"Backed", - "addresses":{ - "ethereum":[ - "0xF4d4e4ae7fd9CbAfc24b9B0Da2596260c8368314",//paprcontroller - "0x3b29c19ff2fcEa0Ff98D0ef5B184354D74eA74b0",//paprcontroller - ], - } + id: "334", + name: "MDEX", + addresses: { + bsc: [ + "0x7DAe51BD3E3376B8c7c4900E9107f12Be3AF1bA8", + "0x62c1A0d92B09D0912F7BB9c96C5ecdC7F2b87059", + "0x0384E9ad329396C3A6A401243Ca71633B2bC4333", + "0x518a6e9FB2832aDA41415775E5c45dE6EfCF1A3C", + ], + heco: [""], + }, }, { - "id":"2918", - "name":"DebtDAO", + id: "2108", + name: "W3swap", + addresses: { + bsc: ["0xF29acE1FE5f36389d0dDe450a0195A30c3770245"], + }, + } /* + { + "id":"238", + "name":"Ellipsis Finance", "addresses":{ - "ethereum":[ - "0xc9eF6509A09b92043cedce689DfAA760048aBd7F",//LineFactory - ], + "bsc":[ + "0xE014A89c9788dAfdE603a13F2f01390610382471" + ] } - }, + },*/, + { + id: "1726", + name: "Meshswap", + addresses: { + polygon: ["0x10f4A785F458Bc144e3706575924889954946639"], + }, + }, + { + id: "2695", + name: "SmarDex", + addresses: { + ethereum: ["0x9a5132e149c547F254C73226DA7f770d43D9EA44"], + base: [ + "0x5C622Dcc96b6D96ac6c154f99CF081815094CBC9", //SmardexRouter + ], + arbitrum: [ + "0xdd4536dD9636564D891c919416880a3e250f975A", //SmardexRouter + ], + polygon: [ + "0xA8EF6FEa013034E62E2C4A9Ec1CDb059fE23Af33", //SmardexRouter + ], + bsc: [ + "0x391BeCc8DAaf32b9ba8e602e9527Bf9DA04C8deb", //SmardexRouter + ], + }, + }, + { + id: "318", + name: "Dfyn Network", + addresses: { + polygon: [ + "0x5ac32A20a5BB6B87AC91E51cA5b7bba9B8846803", + "0xA102072A4C07F06EC3B4900FDC4C7B80b6c57429", + "0x712B5c4CEe26c679F3Ddbb9855369B13aA8F3Dec", + ], + fantom: ["0x2724B9497b2cF3325C6BE3ea430b3cec34B5Ef2d"], + okexchain: [""], + }, + } /* { - "id":"2862", - "name":"Hyperliquid", + "id":"133", + "name":"Shell Protocol", "addresses":{ "arbitrum":[ - "0xC67E9Efdb8a66A4B91b1f3731C75F500130373A4", - "0x2df1c51e09aecf9cacb7bc98cb1742757f163df7 " - ], + "0xC32eB36f886F638fffD836DF44C124074cFe3584" + ] } - }, - { - "id":"319", - "name":"Convex Finance", + },*/, + { + id: "2644", + name: "Maverick Protocol", + addresses: { + ethereum: [ + "0x001903de96a72d11d27cd8c2bee003a730e032a8", + "0x050853d20d1b4f5529cd8dec986b752e7c9d95f7", + "0x0ce176e1b11a8f88a4ba2535de80e81f88592bad", + "0x0eb1c92f9f5ec9d817968afddb4b46c564cdedbe", + "0x11a653ddfbb61e0feff5484919f06d9d254bf65f", + "0x12378796271f2c5fb1a3206525c4b49a204a8487", + "0x14b0fdd73e47fac12d98182c0fd1054f362262a6", + "0x1970523c241756e24d546dc4bfffc1f436ab9671", + "0x1db8784119dcfe4213a0ceb2c55b07e81c72b475", + "0x1dc08fb758c89db0d81da0924ea4ba884b68564c", + "0x20ee9efe1b85b3077c53d648b17936d4ddb4e407", + "0x214b0b7d3c925b7710601e437aec942b5cbd8d48", + "0x23f6b8a4093d740a5f39d20a1f543e4b26b7791a", + "0x257b0a09d1f4b5913f9c813c43dcd0d0115af2f2", + "0x25f159fd4b15a2a7a9703ca83d0e63df9eeb0a65", + "0x2ebe19aa2e29c8acadb14be3e7de153b0141e2aa", + "0x2f3e9cd12dc8eee8c7fea0383ab877b6bead56ab", + "0x352b186090068eb35d532428676ce510e17ab581", + "0x3fd899eaf2dda35cf2c7bfcdb27a23d727d9a67c", + "0x43a81f1e714f12147e5e865c152c6aac14c80bff", + "0x43c014e1e6afeb8a76fde2420a0b65e1ca06c9bf", + "0x44f0f76cfbafc2b9b3ad000d588897d1e5381068", + "0x46557085e28bcc6d8f653a9ee84c6c9b67642b93", + "0x4789fad0cf791fec659256900074b80c89c47edd", + "0x48e236fa378ffeaf86443b6a304ce5670c3cd9ab", + "0x496d3fe47211521eca1fff521d1f8022b0287c9f", + "0x4a94f0a97615f0bccbc09968b1c49c9ae1eb38a8", + "0x4efec7ada76685a521278407d9fcf58b8c6e8774", + "0x52de4ebf8bfb4048f412bcb415a52cb98651f9ed", + "0x53dc703b78794b61281812f3a901918253beefee", + "0x55095300bdcb3026b48b4ad05a5feaaba801aac9", + "0x5cb98367c32d8a1d910461c572c558d57ca68d25", + "0x5eef9ab433f598d408ec30adf58d182a07a1189d", + "0x6b04ce6e4d728a97bafd1c78f8ea46b73ada552d", + "0x6c6fc818b25df89a8ada8da5a43669023bad1f4c", + "0x7064a1ea78961ef05a510e86540235a4a2e64ca4", + "0x7174c5aadc47e0b706c333467d2a3b126eb6ed15", + "0x73ee7d74a1fe9d768112ba40549bc9c2003f9b63", + "0x757caf1bd60b4e16d6b91f03169a66149306de7a", + "0x7a2b6d8325c3912939229272256769b06cedb1b2", + "0x7fafd253ea3f8351e02135b8f0d4ed31a6e7a59d", + "0x857d1b4f80ecb6ad7e4e7d120ffc1292ee8ddafc", + "0x85dd09159b42417c1e0782fa2c6ba3b790be9ead", + "0x87da68bfbaf58ba6a29fed851f0411e7c989b68b", + "0x991322ee666ec384eeb31bbd97b4dc0c2df14ce1", + "0x99903bb64e9c1e54a10723afa7f9a094c9f783c8", + "0xa2cc3e531f49e6e1b0e360f371e6171f5aeaec91", + "0xa495a38ea3728ac29096c86ca30127003f33af28", + "0xa53620f536e2c06d18f02791f1c1178c1d51f955", + "0xa7b1d843ae0c0e5e561149d7624f9e469fcacf4d", + "0xab1e2d29699146a2e07c3a1c8ad8cb914a536f7a", + "0xaf29b974b47d900bc6746bf9979be8edc8790a20", + "0xb04f13750cd764eeceb07e19254564787c9c72bf", + "0xba7f8b8cf0f13f8d90d4e364d43a3ddd57f39da0", + "0xbe633b67d7d4197b798179066b503ecd9c04d05b", + "0xbfe59fd293c4c19487a20178f384be62867bf875", + "0xc27f074873af25378270cc50b9854cf7a013eab6", + "0xcb2e6adc815195069977692de2f6e22e920a6b1b", + "0xccb606939387c0274aaa2426517da315c1154e50", + "0xcf4595ae4e43bc8c7be90849babc1da27e47813c", + "0xd1e50b60287faada2a7d5ea5632df78f7f2f0cb8", + "0xddcd60dcc952023ec4bcd27788384f06e901e61e", + "0xe1f9a04aeaf788b1494721317c812145dcef2359", + "0xe870c025ede621834f538468034398cff26ac926", + "0xe8d7a52aabe8a0569314f28e90fdb8544860a424", + "0xe94f1ec6aaaba70e109535f88d0c836ce044fd16", + "0xeab253203605d0b2ca7bde2157009d121cffdd27", + "0xeb061a4e1ad3f1983655281cb8019ebbf8b30b29", + "0xeb0f2c77ee979adb69f718b4027d3783b27b0f9e", + "0xebac4a08dbe9b33320f73b7bc8c3559ff042a9d9", + "0xedf1335a6f016d7e2c0d80082688cd582e48a6fc", + "0xf4b0e6fad7443fbb7bbfea7dc1cbe7bf7e574b03", + "0xf59ce000475cc3962cd366ce05ea2fd6fea5b8aa", + "0xf7c3d9615221dfa89a835ec5d56dea2990eae54a", + "0xf7c8ab6912894393e6ee9c0222c672a4441dfea2", + "0xf8fb2d6bb43f6a422bc1e2a15b0f85afce7e7f05", + "0xfc0c52a2b66a19b39efbe4332bc42186ada1ee45", + "0xff3074fd3bccc15b54d2c7fbfe48108a6116a321", + ], + era: ["0x39E098A153Ad69834a9Dac32f0FCa92066aD03f4", "0x02E3B9d5462e84518E309116D547c8C772a1C852"], + }, + }, + { + id: "597", + name: "BabySwap", + addresses: { + bsc: ["0x325E343f1dE602396E256B67eFd1F61C3A6B38Bd"], + }, + }, + { + id: "parent#mm-finance", + name: "MM Finance", + addresses: { + cronos: [""], + polygon: ["0x7E5E5957De93D00c352dF75159FbC37d5935f8bF"], + arbitrum: [ + "0x4F879a9d95e01041dDAA607A65F04e0EDbD04139", + "0x20AB386813F59B92e1C4596f22591bEe92935d83", //v3smartrouter + "0x611c9F2f536E087BE7d0F02D9F99e5CE9b7E175B", + ], + }, + }, + { + id: "2400", + name: "Solidly V2", + addresses: { + ethereum: ["0x77784f96C936042A3ADB1dD29C91a55EB2A4219f"], + }, + }, + { + id: "622", + name: "Clipper", + addresses: { + ethereum: ["0xE7b0CE0526fbE3969035a145C9e9691d4d9D216c"], + arbitrum: ["0xE7b0CE0526fbE3969035a145C9e9691d4d9D216c", "0x9E233DD6a90678BaaCd89c05ce5C48f43fCc106E"], + optimism: [ + "0x5130f6cE257B8F9bF7fac0A0b519Bd588120ed40", //ClipperPackedVerifiedExchange + "0xF33141BC4E9D1d92a2Adba2fa27A09c2DA2AF3eB", //ClipperPermitRouter + ], + polygon: [ + "0x6Bfce69d1Df30FD2B2C8e478EDEC9dAa643Ae3B8", + "0xF33141BC4E9D1d92a2Adba2fa27A09c2DA2AF3eB", //ClipperPermitRouter + ], + moonbeam: ["0xCE37051a3e60587157DC4c0391B4C555c6E68255"], + mantle: [ + "0x769728b5298445BA2828c0f3F5384227fbF590C5", //ClipperPackedVerifiedExchange + ], + }, + }, + { + id: "1732", + name: "Verse", + addresses: { + ethereum: ["0xB4B0ea46Fe0E9e8EAB4aFb765b527739F2718671"], + smartbch: [""], + }, + }, + { + id: "2283", + name: "3xcalibur", + addresses: { + arbitrum: ["0x8e72bf5A45F800E182362bDF906DFB13d5D5cb5d"], + }, + }, + { + id: "311", + name: "SpiritSwap AMM", + addresses: { + fantom: ["0x16327E3FbDaCA3bcF7E38F5Af2599D2DDc33aE52"], + }, + }, + { + id: "602", + name: "BakerySwap", + addresses: { + bsc: ["0xCDe540d7eAFE93aC5fE6233Bee57E1270D3E330F"], + }, + }, + { + id: "942", + name: "KnightSwap Finance", + addresses: { + bsc: ["0x05E61E0cDcD2170a76F9568a110CEe3AFdD6c46f"], + fantom: ["0x045312C737a6b7a115906Be0aD0ef53A6AA38106"], + }, + }, + { + id: "1461", + name: "WOOFi Swap", + addresses: { + fantom: ["0x382A9b0bC5D29e96c3a0b81cE9c64d6C8F150Efb"], + avax: ["0xC22FBb3133dF781E6C25ea6acebe2D2Bb8CeA2f9"], + arbitrum: ["0x9aEd3A8896A85FE9a8CAc52C9B402D092B629a30"], + bsc: ["0xC90bFE9951a4Efbf20aCa5ECd9966b2bF8A01294"], + optimism: ["0xEAf1Ac8E89EA0aE13E0f03634A4FF23502527024"], + polygon: ["0x817Eb46D60762442Da3D931Ff51a30334CA39B74"], + ethereum: ["0x9D1A92e601db0901e69bd810029F2C14bCCA3128"], + }, + }, + { + id: "863", + name: "Yoshi Exchange", + addresses: { + bsc: ["0x3a547932e0818403b39fD2453AE74c9004FB902E"], + fantom: ["0xE4a4642B19C4d0CBA965673cd51422b1EDA0a78d"], + ethereum: ["0x3aB65d9C1616FF780e1853330a219497CF5D9B67"], + }, + }, + { + id: "271", + name: "Honeyswap", + addresses: { + polygon: ["0xaD340d0CD0B117B0140671E7cB39770e7675C848"], + xdai: [""], + }, + }, + { + id: "2129", + name: "Tomb Swap", + addresses: { + fantom: ["0x6D0176C5ea1e44b08D3dd001b0784cE42F47a3A7"], + }, + }, + { + id: "1351", + name: "WigoSwap", + addresses: { + bsc: ["0x5023882f4D1EC10544FCB2066abE9C1645E95AA0"], + }, + }, + { + id: "2603", + name: "AlienFi", + addresses: { + arbitrum: [ + "0x863e9610E9E0C3986DCc6fb2cD335e11D88f7D5f", + "0xB8ca857dCd90AfBeD93B30DdCd4E4CC1327c9e5c", + "0xbd796fac59914dB9A7CBC21f1053c7DC1b900fEA", //masterchef + "0x8923d3EFEE38e7bb1E8988B024D5169C962CFB73", //masterchef + "0x4Ad7C3F11ec54d7D066dd114ac403022d3F97E6F", //masterchef + ], + }, + }, + { + id: "373", + name: "BiSwap", + addresses: { + bsc: ["0x3a6d8cA21D1CF76F653A67577FA0D27453350dD8"], + }, + }, + { + id: "1823", + name: "Nomiswap", + addresses: { + bsc: [ + "0xD486D0846812266D21e1Ab6c57FCF202DF836dc8", + "0xD654953D746f0b114d1F85332Dc43446ac79413d", + "0x9D15d0d737e06a875F3d46621fB52fe79ffA6136", + "0x4eC3432d9443f05022e2Ff4E54fC7514BE2359e0", + "0xbF4c0d66Db59Ae8276e0cB7E1Ed36fC4Ac8C1d68", + ], + }, + }, + { + id: "1295", + name: "BurgerSwap", + addresses: { + bsc: [ + "0xe08Ab553720a46C071475838a6cC8D98D1Afb891", + "0xEfC254D0cdb1924149382d404A2133532D46A777", + "0xfa9cCB91d28d35E12216e43d8990D31595783600", + "0xE3F08e81Ec8533D6CD7784B672e4237087b2A7c8", + ], + }, + }, + { + id: "2102", + name: "Titano Swych", + addresses: { + bsc: ["0x2Bf55D1596786F1AE8160e997D655DbE6d9Bca7A"], + }, + }, + { + id: "parent#arbswap", + name: "Arbswap", + addresses: { + arbitrum: ["0xD01319f4b65b79124549dE409D36F25e04B3e551"], + arbitrum_nova: [], + }, + }, + { + id: "parent#polycat-finance", + name: "Polycat Finance", + addresses: { + polygon: [ + "0x94930a328162957FF1dd48900aF67B5439336cBD", + "0xfDC8579B2E19B489c4086eDE85A2D71949138be5", //tankchef + "0xfaBC099AD582072d26375F65d659A3792D1740fB", //tankchef + ], + }, + }, + { + id: "2384", + name: "OreoSwap", + addresses: { + arbitrum: ["0x38eEd6a71A4ddA9d7f776946e3cfa4ec43781AE6"], + }, + }, + { + id: "1824", + name: "Swapsicle", + addresses: { + arbitrum: ["0x3D42A6B7cD504cA2283Bc8F37fea859a11Ca89fb"], + ethereum: ["0x3D42A6B7cD504cA2283Bc8F37fea859a11Ca89fb"], + avax: ["0xC7f372c62238f6a5b79136A9e5D16A2FD7A3f0F5"], + polygon: ["0x0427B42bb6ae94B488dcf549B390A368F8F69058"], + bsc: ["0x63530632e8fE40aCf8f1f4324f7645256263b64f"], + optimism: ["0x3D42A6B7cD504cA2283Bc8F37fea859a11Ca89fb"], + fantom: ["0x422770Fcf2217AF03b4832e9f1F4Bd23946F828b"], + telos: ["0x9b1adec00a25fffd87a5bb17f61916e1c26f6844"], + }, + }, + { + id: "2350", + name: "KyotoSwap", + addresses: { + bsc: ["0x9fd7764e2303E7748736D115304350eC64E403B2"], + }, + }, + { + id: "2101", + name: "FstSwap", + addresses: { + bsc: ["0xB3ca4D73b1e0EA2c53B42173388cC01e1c226F40"], + }, + }, + { + id: "2751", + name: "LFGSwap", + addresses: { + arbitrum: ["0xF83675ac64a142D92234681B7AfB6Ba00fa38dFF"], + ethpow: [], + core: [], + }, + }, + { + id: "2166", + name: "LFGSwap EthereumPoW", + addresses: { + ethpow: [], + }, + }, + { + id: "2647", + name: "LFGSwap Core", + addresses: { + core: [], + }, + } /* + {//listed on compound-v2 users file + "id":"387", + "name":"Bearn", "addresses":{ - "ethereum":[ - "0xf403c135812408bfbe8713b5a23a04b3d48aae31", - ADDRESSES.ethereum.vlCVX, - ], + "bsc":[ + "0xC6747954a9B3A074d8E4168B444d7F397FeE76AA", + "0x3d695c1607a085773547e07dEf1aD3CE3f518Edb",//bearnchef + ] } + },*/, + { + id: "659", + name: "JetSwap", + addresses: { + bsc: ["0xBe65b8f75B9F20f4C522e0067a3887FADa714800"], + }, }, { - "id":"270", - "name":"Liquity", - "addresses":{ - "ethereum":[ - "0x4f9fbb3f1e99b56e0fe2892e623ed36a76fc605d",//staking - "0x66017d22b0f8556afdd19fc67041899eb65a21bb",//stabilitypool - "0x24179cd81c9e782a4096035f7ec97fb8b783e007" - ], - } + id: "2749", + name: "Antfarm finance", + addresses: { + ethereum: ["0x6d9f0eb21d77c6d24be49a579508471e937d5418"], + arbitrum: ["0x1272ba8c0bd855ff15c4b29bad660e6f154fca28"], + polygon_zkevm: ["0x61f4ECD130291e5D5D7809A112f9F9081b8Ed3A5"], + }, + }, + { + id: "2763", + name: "Dove Swap", + addresses: { + polygon_zkevm: ["0xc4212b4f901C8Afac75A27C8E8be7b9fa82D74d8"], + }, }, - /* - Only bridge addresses, not actual users { - "id":"144", - "name":"dYdX", - "addresses":{ - "ethereum":[ - "0xd54f502e184b6b739d7d27a6410a67dc462d69c8", - "0x8e8bd01b5a9eb272cc3892a2e40e64a716aa2a40", - "0x0fd829c3365a225fb9226e75c97c3a114bd3199e", - "0x5aa653a076c1dbb47cec8c1b4d152444cad91941" - ], - } + id: "2762", + name: "Dove Swap", + addresses: { + polygon_zkevm: ["0xc4212b4f901C8Afac75A27C8E8be7b9fa82D74d8"], + }, }, - */ { - "id":"parent#radiant", - "name":"Radiant", - "addresses":{ - "arbitrum":[ - "0x8991c4c347420e476f1cf09c03aba224a76e2997", - "0x196bf3a63c50bca1eff5a5809b72dfc58f0c2c1a", - "0xebc85d44cefb1293707b11f707bd3cec34b4d5fa", - "0x2032b9a8e9f7e76768ca9271003d3e43e1616b1f", - "0x5682a39078edce41a65f1bd8733bf9ca2bbe3b1b", - "0xc963ef7d977ecb0ab71d835c4cb1bf737f28d010" - ], - "bsc":[ - "0x13ef2a9e127ae8d9e9b863c7e375ba68e1a42ac6", - "0xd50cf00b6e600dd036ba8ef475677d816d6c4281", - "0x7c16abb090d3fb266e9d17f60174b632f4229933", - ] - } + id: "561", + name: "Alita Finance", + addresses: { + bsc: [ + "0x730aCC3bBf2443f2EaEaCFc7ac7b4d8DC9E32dB8", + "0x4f7b2Be2bc3C61009e9aE520CCfc830612A10694", + "0x28162cda1E767663F68B759AF47801171Aa58815", //incentive + "0x8ED5fABddb6f899f7FaCf461587f4dAd065AAae7", //masterchef + ], + }, }, { - "id":"parent#paraspace", - "name":"ParaSpace", - "addresses":{ - "ethereum":[ - "0x638a98bbb92a7582d07c52ff407d49664dc8b3ee", - "0x59b72fdb45b3182c8502cc297167fe4f821f332d", - "0xf090eb4c2b63e7b26e8bb09e6fc0cc3a7586263b", - "0xc5c9fb6223a989208df27dcee33fc59ff5c26fff" - ], - } + id: "2333", + name: "Alita Finance", + addresses: { + bsc: ["0xbd67d157502A23309Db761c41965600c2Ec788b2"], + }, }, { - "id":"438", - "name":"Tokemak", - "addresses":{ - "ethereum":[ - "0x04bda0cf6ad025948af830e75228ed420b0e860d", - "0xd3d13a578a53685b4ac36a1bab31912d2b2a2f36", - "0x8858a739ea1dd3d80fe577ef4e0d03e88561faa3", - "0x41f6a95bacf9bc43704c4a4902ba5473a8b00263" - ], - } + id: "2118", + name: "WinerySwap", + addresses: { + bsc: [ + "0xB115C8392C4C416b227e98d9bbb394bFD03BE965", + "0x8B07c6CB1b2edA3942369EEC9DF8e12213f99181", + "0x8bfFB5562ff30f555894E101E6DAD31D271EEd5a", + "0xBd27399a5aA720250b37b6864F293A27F3D2A043", //masterchef + "0x21694642bea2D2E0B0f5129a25D753dd9fB9623A", //masterchef + ], + }, }, { - "id":"636", - "name":"Keep3r Network", - "addresses":{ - "ethereum":[ - "0x02777053d6764996e594c3e88af1d58d5363a2e6", - "0x1ceb5cb57c4d4e2b2433641b95dd330a33185a44", - "0xb9d18ab94cf61bb2bcebe6ac8ba8c19ff0cdb0ca", - ], - } + id: "317", + name: "HyperJump", + addresses: { + bsc: ["0x3bc677674df90A9e5D741f28f6CA303357D0E4Ec"], + fantom: ["0x53c153a0df7E050BbEFbb70eE9632061f12795fB"], + metis: ["0xd96aeE439e6e5B4f3544bF105eb78F3b8B6CD774"], + }, }, { - "id":"2255", - "name":"NFTfi", - "addresses":{ - "ethereum":[ - "0xe52cec0e90115abeb3304baa36bc2655731f7934", - "0x8252df1d8b29057d1afe3062bf5a64d503152bc8", - ], - } + id: "2429", + name: "Paraluni Dex", + addresses: { + bsc: ["0xb3ca41D538998f884D9f8cE33703A7f49F112E98"], + }, }, { - "id":"483", - "name":"NFTX", - "addresses":{ - "ethereum":[ - "0x941a6d105802cccaa06de58a13a6f49ebdcd481c", - "0xdc774d5260ec66e5dd4627e1dd800eff3911345c", - "0x688c3e4658b5367da06fd629e41879beab538e37", - "0x3e135c3e981fae3383a5ae0d323860a34cfab893" - ], - } + id: "575", + name: "Coinswap Space", + addresses: { + bsc: ["0x34DBe8E5faefaBF5018c16822e4d86F02d57Ec27"], + }, }, { - "id":"2086", - "name":"Rage Trade", - "addresses":{ - "arbitrum":[ - "0x1d42783E7eeacae12EbC315D1D2D0E3C6230a068",//Curve Yield Strategy - "0x4b928aFd7CA775C7f4ECdf2c00B7e608962AbbDc",//Rage Trade: Vault Periphery - ], - } + id: "544", + name: "SoulSwap", + addresses: { + fantom: [ + "0x6b3d631B87FE27aF29efeC61d2ab8CE4d621cCBF", + "0x994889A5a2BcfAB67e5242996e1331b74d777834", + "0x2CDa3B64Da9c1b7F18891E1567bc43eD558D089b", + ], + avax: ["0xa4594460A9d3D41e8B85542D34E23AdAbc3c86Ef", "0xE15d319896038aB76f2bc7cE15CBc2689b498570"], + }, }, { - "id":"2192", - "name":"PlutusDAO", - "addresses":{ - "arbitrum":[ - "0x35cD01AaA22Ccae7839dFabE8C6Db2f8e5A7B2E0",//PlutusPrivateTGE - "0x195B6eA50150900A25FA0928b8B65B03C7666D10",//TGEController - "0xc1D8f4109eC84db9b607e2705779142eC8F9534a",//Plutus DAO: TGE Vault ETH - "0xF4790fc873351C624d225269d4d21cF591e441b2",//Plutus DAO: TGE Vault DPX - "0xd6c9fe8dbc50c620222e8679CFf0461994b532DA",//Plutus DAO: TGE Vault JONES - "0x27Aaa9D562237BF8E024F9b21DE177e20ae50c05",//Plutus DAO: 1 Month Plutus Epoch Staking - "0xE59DADf5F7a9decB8337402Ccdf06abE5c0B2B3E",//Plutus DAO: 3 Month Plutus Epoch Staking - "0xBEB981021ed9c85AA51d96C0c2edA10ee4404A2e",//Plutus DAO: 6 Month Plutus Epoch Staking - "0x5593473e318F0314Eb2518239c474e183c4cBED5",//Plutus DAO: MasterChef - "0x66Cd8Cb1bA49f1A07703fa6E5BFE2BEB2eC8c706",//PlutusDAO: Plutus JONES Depositor - "0x4D56D5A417269A5bFa909cc0f67DFFE992272606",//Plutus DAO: Dpx Depositor - "0x20DF4953BA19c74B2A46B6873803F28Bf640c1B5",//PlutusDAO: Old plsDPX Farm - "0x23B87748b615096d1A0F48870daee203A720723D",//PlutusDAO: plsJONES - Plutus Chef - "0x6CCD4CFaF4bDa43c09682B3e588B4bd18BFFd603",//PrivateTgeRewards - "0x548C30b0af3CE6D96F1A63AfC05F0fb66495179F",//PlutusDAO: DPX Depositor - "0x75c143460F6E3e22F439dFf947E25C9CcB72d2e8",//PlutusDAO: plsDPX Farm - "0x04B724389Dd28Ffc9a3A91Ab4149a77530282f04",//PrivateTgeVester - "0xA61f0d1d831BA4Be2ae253c13ff906d9463299c2",//PlutusChef - "0xb059Fc19371691aa7A3EC66dD80684FFE17A7D5c",//PlutusChef - ADDRESSES.arbitrum.plvGLP,//PlvGlpToken - "0x4E5Cf54FdE5E1237e80E87fcbA555d829e1307CE",//PlutusDAO: plvGLP Farm - "0x8c12e3C9b26Ee2e43A1a71cd974e6bF250472129",//SpaDepositor - "0x73e7c78E8a85C074733920f185d1c78163b555C8",// - "0x9F07B8D6DDA7E68260Add1e38447D0Caa6F1BA0d",//PlutusChef - "0xbe68e51f75F34D8BC06D422056af117b8c23fd54",// - "0x13794D30D01c96D6595d1D956f3dd70AEc2C238B",//ArbDepositor - "0xCfc273D86333bF453b847d4D8cb7958307D85196",// - "0x4C2C41cFfC920CA9dD5F13E88DcF5062ceF37455",// - ], - } + id: "695", + name: "Dinosaur Eggs", + addresses: { + bsc: ["0xE9C7650b97712C0Ec958FF270FBF4189fB99C071"], + }, + }, + { + id: "1306", + name: "ProtoFi", + addresses: { + fantom: ["0xF4C587a0972Ac2039BFF67Bc44574bB403eF5235"], + }, + }, + { + id: "1893", + name: "MIND Games", + addresses: { + arbitrum: ["0x750eD5cF0f5278be9C6562399f0791dD221C4f83"], + }, + }, + { + id: "595", + name: "Convergence", + addresses: { + ethereum: ["0x8Cda39226daf33ae1Aba0C92C34d1a1982Cf0210", "0x37c7C2ae51E968CEfB82cFF2102727256D36D6eE"], + moonbeam: [], + }, + }, + { + id: "367", + name: "PinkSwap", + addresses: { + bsc: ["0x319EF69a98c8E8aAB36Aea561Daba0Bf3D0fa3ac"], + }, + }, + { + id: "867", + name: "GIBXSwap", + addresses: { + bsc: ["0x2fB9Cee9d580cD12E671b8789F2f9fb228A5d2bc"], + }, }, { - "id":"916", - "name":"Pika Protocol", - "addresses":{ - "optimism":[ - "0x365324E5045df8c886EBe6AD5449F5CeB5881A40",//PikaPerpV2 - "0x58488bB666d2da33F8E8938Dbdd582D2481D4183",//VaultFeeReward - "0x2FaE8C7Edd26213cA1A88fC57B65352dbe353698",//Pika Protocol: Perpetual V2 - "0x8123DCe565111F64c01864B2ae0F35e3181A0A02",//PositionManager - "0xf9B19D0e62278ec9CBBaD5CcA5e7A270979bEa4E",//OrderBook - "0xD5A8f233CBdDb40368D55C3320644Fb36e597002",//PikaPerpV3 - "0x939c11c596B851447e5220584d37F12854bA02ae",//VaultFeeReward - "0x78136EF4BDcbdABb8D7aa09a33C3c16Ca6381910",//VaultTokenReward - ], - } + id: "2577", + name: "Sharky Swap", + addresses: { + arbitrum: ["0x29631E68d81b0e02a507f54a799402E8Cfa6a4d8"], + }, }, { - "id":"2618", - "name":"OasisSwap", - "addresses":{ - "arbitrum":[ - "0xe805977D5Fa2f05e2175507a1f8E44Cd3F22972c", - "0x5bf51bf7af925306866d6cf87b4b85189df67970", - ] - } + id: "2203", + name: "Tetu Swap", + addresses: { + polygon: ["0xBCA055F25c3670fE0b1463e8d470585Fe15Ca819"], + }, }, { - "id":"1521", - "name":"Horizon Protocol", - "addresses":{ - "bsc":[ - "0xFCF3afa6cdA14B438AeEb8FfEd433D196Cd1367F", - "0x9657a0FD98e88464E1159d98b517A4945dbFBFC8",//DelegateApprovals - "0xadA58Cf32276CCD03a1C155688eFF8B3BC282285",//PhbStaking - "0xa1771DCfb7822C8853D7E64B86E58f7f1eB5e33E",//StakingRewards - "0xE21e39c383ABDce3edf13b7233Ad1ad5FEE42099",//RewardEscrowV2 - ] - } + id: "384", + name: "Firebird", + addresses: { + polygon: ["0xb31D1B1eA48cE4Bf10ed697d44B747287E785Ad4"], + avax: ["0xe0C38b2a8D09aAD53f1C67734B9A95E43d5981c0"], + arbitrum: ["0x0c6134Abc08A1EafC3E2Dc9A5AD023Bb08Da86C3"], + dogechain: ["0xe0C38b2a8D09aAD53f1C67734B9A95E43d5981c0"], + bsc: ["0x92e4F29Be975C1B1eB72E77De24Dccf11432a5bd"], + cronos: ["0x4A5a7331dA84d3834C030a9b8d4f3d687A3b788b"], + ethereum: ["0xe0C38b2a8D09aAD53f1C67734B9A95E43d5981c0"], + fantom: ["0xe0C38b2a8D09aAD53f1C67734B9A95E43d5981c0"], + optimism: ["0x0c6134Abc08A1EafC3E2Dc9A5AD023Bb08Da86C3"], + }, }, { - "id":"2970", - "name":"Beluga Dex", - "addresses":{ - "arbitrum":[ - "0x7668bcBf650AE69297E411d2A8Ec91e07dd91c0B", - "0x48945A091108bBbd54829B632B1dF94BB50F81D7" - ] - } + id: "421", + name: "Paint Swap", + addresses: { + fantom: ["0xfD000ddCEa75a2E23059881c3589F6425bFf1AbB"], + }, }, { - "id":"2968", - "name":"GND Protocol", - "addresses":{ - "arbitrum":[ - "0xd8769d8826149B137AF488b1e9Ac0e3AFdbC058a",//UniswapV3LP - ] - } + id: "1349", + name: "Degen Haus", + addresses: { + fantom: ["0xC681174dc7639305d762E016cD3aFf93219D6cc1"], + }, }, { - "id":"2957", - "name":"Seashell", - "addresses":{ - "arbitrum":[ - "0x5BAC5eEfA13696Cf815388021235b215587263Ea",//Blueberry GLP Compounder LP Token (Blueberry...) - ] - } + id: "473", + name: "Baguette", + addresses: { + avax: ["0xF7b1e993d1b4F7348D64Aa55A294E4B74512F7f2"], + }, }, { - "id":"2586", - "name":"Equilibre", - "addresses":{ - "kava":[ - "0xA7544C409d772944017BB95B99484B6E0d7B6388",//router2 - "0xa337E9426d080970b026caFfb4a83D185b85A124",//GaugeFactory - "0x7B14b7288D50810a6982149B107238065AA7fcb7",//BribeFactory - "0x35361C9c2a324F5FB8f3aed2d7bA91CE1410893A",//VotingEscrow - "0x553796D20BB387E9b3F91Aa35fD289B753D63baF",//VeArtProxy - "0x8825be873e6578F1703628281600d5887C41C55A",//RewardsDistributor - ] - } + id: "429", + name: "BambooDeFi", + addresses: { + bsc: ["0xBA9DF2c143C502A433d6A876C1a291C9FC940cf9"], + }, }, { - "id":"1765", - "name":"Unicrypt", - "addresses":{ - "ethereum":[ - "0x663a5c229c09b049e36dcc11a9b0d4a8eb9db214",//univ2locker - "0xdba68f07d1b7ca219f78ae8582c213d975c25caf",//tokenvesting - "0x17e00383a843a9922bca3b280c0ade9f8ba48449",//pollocker - "0xed9180976c2a4742c7a57354fd39d8bec6cbd8ab",//sushilocker - ], - "bsc":[ - "0xeaed594b5926a7d5fbbc61985390baaf936a6b8d",//TokenVestingBSC - "0xc765bddb93b0d1c1a88282ba0fa6b2d00e3e0c83",//UniswapV2Locker - "0xc765bddb93b0d1c1a88282ba0fa6b2d00e3e0c83",//pancakev2locker - "0xc8B839b9226965caf1d9fC1551588AaF553a7BE6",//pancakev1locker - "0x74dee1a3e2b83e1d1f144af2b741bbaffd7305e1",//biswaplocker - "0x1391b48c996ba2f4f38aee07e369a8f28d38220e",//safeswaplocker - "0x1f23742D882ace96baCE4658e0947cCCc07B6a75",//julswaplocker - "0xb89a15a4f3518c14c21be04b55546162b0cb39f0",//babydogeswaplocker - ], - "polygon":[ - "0xadb2437e6f65682b85f814fbc12fec0508a7b1d0",//quickswaplocker - ], - "avax":[ - "0xa9f6aefa5d56db1205f36c34e6482a6d4979b3bb",//traderjoelocker - ], - "xdai":[ - "0xe3D32266974f1E8f8549cAf9F54977040e7D1c07",//honeyswaplocker - ] - } + id: "978", + name: "ChickenSwap", + addresses: { + ethereum: ["0xB72F87Df6B5C004227B6a045fD451cb716669150"], + }, }, { - "id":"2397", - "name":"Gyroscope Protocol", - "addresses":{ - "polygon":[ - "0x37b8E1152fB90A867F3dccA6e8d537681B04705E",//Proto Gyro Dollar (p-GYD) - "0x68BDeE1bF95AD730F379A05eB8c51fb5dFA07748",//FreezableTransparentUpgradeableProxy - ] - } + id: "976", + name: "WingSwap", + addresses: { + fantom: ["0x2b660040b289B1B570E053b21dd9A6F1067AD7F5"], + }, + }, + { + id: "692", + name: "HurricaneSwap", + addresses: { + avax: [ + "0xb9a9BB6CC39387548BAA7185fbFf51d47eef8771", + "0xB6559dD3cBec057078fBd9477e676a24cCEA0609", + "0x010D464fE46ABA2FB468a4BB251248d669C67c72", + ], + }, }, { - "id":"3093", - "name":"eZKalibur", - "addresses":{ - "era":[ - "0x498f7bB59c61307De7dEA005877220e4406470e9",//router - ] - } + id: "293", + name: "Lydia", + addresses: { + avax: ["0xA52aBE4676dbfd04Df42eF7755F01A3c41f28D27"], + }, }, { - "id":"2952", - "name":"Archi Finance", - "addresses":{ - "arbitrum":[ - "0x7674Ccf6cAE51F20d376644C42cd69EC7d4324f4",//WETHVaultProxy - "0x179bD8d1d654DB8aa1603f232E284FF8d53a0688",//USDTVaultProxy - "0xa7490e0828Ed39DF886b9032ebBF98851193D79c",//USDCVaultProxy - "0xee54A31e9759B0F7FDbF48221b72CD9F3aEA00AB",//WBTCVaultProxy - ] - } + id: "2687", + name: "OpenXswap", + addresses: { + optimism: ["0x744776F27080b584D447A780ba260c435f3aE7d5", "0x6e0CEf87B1D55ec54d657f0aDA04AE2c90A470bA"], + }, + }, + { + id: "815", + name: "PureSwap", + addresses: { + bsc: ["0x3e8743B5453A348606111AB0a4dEe7F70A87f305"], + }, + }, + { + id: "391", + name: "PantherSwap", + addresses: { + bsc: ["0xf5048C225a0D220cd784D81f4e07F137fAf35FF8", "0x24f7C33ae5f77e2A9ECeed7EA858B4ca2fa1B7eC"], + }, + }, + { + id: "396", + name: "Polydex", + addresses: { + polygon: [ + "0xC60aE14F2568b102F8Ca6266e8799112846DD088", + "0x5a56cB06d143a7cC0597c4804D5D76f2d5c2be81", + "0x512Ff58276046636590767B88f418DD84E47ce78", + "0x56A0b8BA16A84959541CcB3F42E7A9a9d16428F4", + ], + }, + }, + { + id: "1871", + name: "HunnySwap", + addresses: { + avax: ["0x8685aBD6959745E41D64194F42e21bbD25Fd57B3"], + }, }, { - "id":"3173", - "name":"Equity", - "addresses":{ - "fantom":[ - "0x9e4105F9E2284532474f69e65680e440F4C91cb8",//Vault - "0xe8ca91bAe8AA0E9229F6E78f8976B837134b60E8",//ShortsTracker - "0xA83F31aF44e812d2EdF0536516e7D274cd7301B8",//OrderBook - "0xd311Fd89e8403c2E90593457543E99cECc70D511",//Router - "0xf2BfB9cA6e21b30034b9d56Cb4735d2c180cC7e1",//PositionRouter - "0xfb0c0cE1d43B373b7535Ef556e1D55D285156887",//RewardRouter - "0x8f02357cb55DbAd26DF5a7558CD810D5D0f05f43",//OrderBookReader - "0x3e8B14B5534333A2B83a31d778ec3bCd9dc946f4",//RewardReader - "0x8F6666bd81C4811F433B8232a1c7D4383f11b2dC",//Timelock - "0xBF65ca2747a1EeebF8a1b0d119De8BE0540c57Cb",//StakedEquity - "0x88171375F6236885f463341d001B419D477eDB74",//Reader - ] - } + id: "289", + name: "YetiSwap", + addresses: { + avax: ["0x262DcFB36766C88E6A7a2953c16F8defc40c378A"], + }, }, { - "id":"3345", - "name":"DackieSwap", - "addresses":{ - "base":[ - "0x195FBc5B8Fbd5Ac739C1BA57D4Ef6D5a704F34f7",//smartrouter - "0xCfB05AB06D338FD85BBF4486e69809D96A906b77",//nftmanager - "0xd592e2C815E0cf4B62169e09934FaAB28299708e",//v3lmpooldeployer - ] - } + id: "287", + name: "0.exchange", + addresses: { + avax: ["0x85995d5f8ee9645cA855e92de16FA62D26398060"], + bsc: ["0xba79bf6D52934D3b55FE0c14565A083c74FBD224"], + polygon: ["0x9894B0F28CcfA0F5c5F74EAC88f161110C5F8027"], + }, }, { - "id":"3341", - "name":"Chronos V2", - "addresses":{ - "arbitrum":[ - //univ3 fork - "0xE0aBdFD837D451640CF43cB1Ec4eE87976eFbb41",//swapRouter - "0x9aAb66944D66516FEFa26D27267E02af03d17c02",//nftDescriptor - "0x5e74e05771f0d1222834e66DE5326C82a2C852e0",//nonfungibleTokenPositionDescriptor - "0x520CAF43e3C6481b71DB95711802ED9179ccA403",//nonfungiblePositionManager - ] - } + id: "2098", + name: "Muffin", + addresses: { + ethereum: ["0xded07E2da859714F69d93f9794344606Ed67907E"], + }, }, { - "id":"3450", - "name":"Aerodrome", - "addresses":{ - "base":[ - //velodrome v2 fork - "0xeBf418Fe2512e7E6bd9b87a8F0f294aCDC67e6B4",//VotingEscrow - "0x16613524e02ad97eDfeF371bC883F2F5d6C480A5",//Voter - "0xcF77a3Ba9A5CA399B7c97c74d54e5b1Beb874E43",//Router - ] - } + id: "532", + name: "Twindex", + addresses: { + bsc: [ + "0x6B011d0d53b0Da6ace2a3F436Fd197A4E35f47EF", + "0xBCB41906bE2C2724A8CD0dec87512B2463535586", + "0xdd3565Bd68ef6882657fB17BCD66b436f819eBF3", + ], + }, }, { - "id":"3377", - "name":"Friend.tech", - "addresses":{ - "base":[ - "0xcf205808ed36593aa40a44f10c7f7c2f67d4a4d4" - ] - } - }, + id: "471", + name: "Complus Network", + addresses: { + avax: ["0x78c18E6BE20df11f1f41b9635F3A18B8AD82dDD1"], + bsc: ["0x07DC75E8bc57A21A183129Ec29bbCC232d79eE56"], + polygon: ["0x07DC75E8bc57A21A183129Ec29bbCC232d79eE56"], + heco: [], + }, + }, + { + id: "2779", + name: "ZenithSwap", + addresses: { + arbitrum: ["0x8CA9EF098F84ceDa319Ec12B9d21EeF50AA3624C"], + }, + }, { - "id":"970", - "name": "Drift", - "addresses":{ - "solana":[ - "dRiftyHA39MWEi3m9aunc5MzRF1JYuBsbn6VPcn33UH", // dex program id - "VAULtLeTwwUxpwAw98E6XmgaDeQucKgV5UaiAuQ655D", // vaults program id - ] - } + id: "2863", + name: "SaitaSwap", + addresses: { + ethereum: ["0x0c17e776CD218252ADFca8D4e761D3fe757e9778", "0x744A4c9c9F40A443ac2A5747D4f3b773e5d86763"], + bsc: ["0x744A4c9c9F40A443ac2A5747D4f3b773e5d86763"], + }, }, { - "id":"parent#baseswap", - "name": "BaseSwap", - "addresses":{ - "base":[ - "0x327Df1E6de05895d2ab08513aaDD9313Fe505d86", // router - "0xc102505248c36f933934d4B2d7579D962a342eBC", - "0x2B0A43DCcBD7d42c18F6A83F86D1a19fA58d541A", - "0xDe151D5c92BfAA288Db4B67c21CD55d5826bCc93", // NonfungiblePositionManager - ] - } + id: "parent#skullswap", + name: "SkullSwap", + addresses: { + fantom: [ + "0x0A239A1fC3Bb5abc6F06ad950e52996308E8E925", + "0xe8E357B75823D1Cc133ED7265a27BC2D9237527c", + "0xA4C5457Eca4E36db9062871631351eF627146044", + "0x6d6E00B42c599ad8F70b2C006ad5135bF93Eb396", + ], + }, + }, + { + id: "2846", + name: "Solisnek Finance", + addresses: { + avax: ["0xeeee17b45E4d127cFaAAD14e2710489523ADB4d8"], + }, + }, + { + id: "2803", + name: "Native", + addresses: { + ethereum: ["0x7A27BBD83b5065eEFf85411DFE048Eaac9be2A9D", "0xF1aF55CC38A92A3b072D05e146E27c2E75bB8F2D"], + bsc: ["0x7A27BBD83b5065eEFf85411DFE048Eaac9be2A9D", "0x83B9fcea670d66626d9db79Af00fc718014C3de8"], + }, + }, + { + id: "2821", + name: "Hamburger Finance", + addresses: { + arbitrum: ["0xE5e5Cd7685755BF4c82137639d75b068ed657384"], + }, }, { - "id":"3575", - "name": "Scale", - "addresses":{ - "base":[ - "0x5E9d25014D01323d6F8c0C6640572e4444d11C94", // router - "0x3f0458FfB6D106d2F5CdeC9CEdc9054A69275489", - "0x2F87Bf58D5A9b2eFadE55Cdbd46153a0902be6FA" - ] - } + id: "2812", + name: "Forge SX Trade", + addresses: { + arbitrum: ["0xE5e5Cd7685755BF4c82137639d75b068ed657384"], + }, }, { - "id":"parent#swapbased", - "name": "SwapBased", - "addresses":{ - "base":[ - "0xaaa3b1F1bd7BCc97fD1917c18ADE665C5D31F066", // router - "0xcb9665E990027e115ccF22230b042e4E7eaBFDB2", // SingleStakingRewardsBase - "0xE39226E0864252E0fC9bD668FB796FD63a1B75A4", // SingleStakingRewardsBase - "0x2168eb98C6D416Afb85E7beef5abDc4FB4177dfE", // BlpToken - "0x265a30f14E34248567B5B0a83978C38dF38D0C60", // RewardRouter - "0xEfE632dB3A07FeBcEc04f76Ea54D9d49f27bCd57", // SingleStakingRewardsXBase - "0x272A9acB288915Bb52A0659c8F9f7bFeBA06fae5", // SingleStakingRewardsOtherTokens - "0x86dAbE269B1c5Ff7fCFf1eA32545489DF66C29EA", // SingleStakingRewardsOtherTokens - ] - } + id: "2806", + name: "AstroFi", + addresses: { + ethereum: ["0x42c76F3BBC2E4d505420fE5bda4C316fA5234624"], + }, + }, + { + id: "2773", + name: "Auragi Finance", + addresses: { + arbitrum: ["0x0FaE1e44655ab06825966a8fCE87b9e988AB6170"], + }, }, { - "id":"parent#alien-base", - "name": "Alien Base", - "addresses":{ - "base":[ - "0x52eaeCAC2402633d98b95213d0b473E069D86590", // BasedDistributorV2 - "0x7f2ff89d3C45010c976Ea6bb7715DC7098AF786E", // UniswapV2Router02 - "0x927860797d07b1C46fbBe7f6f73D45C7E1BFBb27", // SwapFlashLoan - "0x8c1A3cF8f83074169FE5D7aD50B978e1cD6b37c7", // UniswapV2Router02 - "0x3485F8E155973cC247CBEa9E77C0dBBB4BBb79E7", // UniswapV2Router02 - "0xe0808b8e2bDD70D70e540f977cF40E26e5811054", // AlienbaseZapV1 - "0xFBE87Ee1Ee62244A2dF80a8093Eab829C52863e8", // PredictionETH - ] - } + id: "2757", + name: "Glacier Finance", + addresses: { + avax: ["0xC5B8Ce3C8C171d506DEb069a6136a351Ee1629DC"], + }, }, { - "id":"3348", - "name": "Soswap", - "addresses":{ - "base":[ - "0x53BAE026d9a503d46a58aF4b65FCcbb7B904A911", // SOFIProxy - "0xBC097E42BF1E6531C32C5cEe945E0c014fA21964", // PortfolioFactory - "0x1e6Dbd0E827cd243d458ed73B9Ae1a6Db89B8668", // PortfolioModule - "0x4E69553b0aEf0949Fd38Bbf3EbeD866B431C9E68", // ManagerModule - "0x73Ada4aE37Ba1DF45Ba12c4478a27029e24cF2d7", // SOFITrading - ] - } + id: "2731", + name: "Swapline", + addresses: { + fantom: [ + "0xb2755FeEc193a718f6135351057a63b2F7B95cef", + "0xFC33f3cac9f6d1713a4B7787dF6a9a33bAD244d6", + "0x795bF60522F36244E4e51ed5522fE83Df4D3Bf9a", + ], + }, }, { - "id":"3314", - "name": "RocketSwap Base", + id: "2721", + name: "Flair Dex", + addresses: { + avax: ["0xd79eE05678241C16e6195b9FC0bCc778A02d4324", "0xBfC8f125CFce29789500987A9553395E84bDfDD2"], + }, + }, + /* + { //uses firebird router to swap + "id":"2720", + "name":"Satin Exchange", "addresses":{ - "base":[ - "0x4cf76043B3f97ba06917cBd90F9e3A2AAC1B306e", // UniswapV2Router02 - "0x234Ccb5c64FDB3958C47E8efBe122b2d54633a96", // RcktLocker - "0x32C9ACE2d1eB47C3968660De9eF20569f850814D", // - "0xE20d24cf9fAF458b98B6F34e5346361e6492aA5F", - "0x304063953727b53048500dfd877A17d1C4f6EaFf", // RcktMasterChef - "0x2ec62d08277FfC42eB5af71c7595C1a9f9458A3c", // RcktVault + "polygon":[ + "0xb31D1B1eA48cE4Bf10ed697d44B747287E785Ad4"//firebird router ] } - }, - { - "id":"3540", - "name": "MoonBase", + },*/ + /*{ // commented due to inactive project/returning error + "id":"392", + "name":"WardenSwap", "addresses":{ - "base":[ - "0x99554FA8B48F735D4Ccce5E077742cF2D084b258", // MoonChef - "0x4617695387bE48c3202a0A9165549c790C4A08Af", // UniswapRouter - ] + "bsc":[ + "0x451ef8D6B645a60115EB8b8bEa76B39C0C761004", + "0x71ac17934b60A4610dc58b715B61e45DCBdE4054", + ], + "ethereum":[ + "0x39f97198c5DbC193EB962c4B3B7e447091A18eAB" + ], + "avax":[ + "0x5EF960Eb78B8CFc11e654D03BeEB313BaDF5C7C0" + ], + "arbitrum":[ + "0x79A556ef2c5b613dB3DFa8797E6772c5AAF86834" + ], + "optimism":[ + "0x7EA8c22E6Dcd7bd69eb180664Da68e1f1F11D696" + ], } + },*/ + { + id: "351", + name: "Gravity Finance", + addresses: { + polygon: [ + "0x57dE98135e8287F163c59cA4fF45f1341b680248", + "0xF2e6b6d7F3b62449260ac87B66cEf9e2664C26d7", + "0xb4A1F1Dd67e129190feeB4bcADB5298D434d54f2", + "0x57dE98135e8287F163c59cA4fF45f1341b680248", + "0xEbe141dE74F1E6377f53551C275568d7bcBC4119", + ], + }, }, { - "id":"3380", - "name": "Baso Finance", - "addresses":{ - "base":[ - "0x5568e4F19B9063E0e0386bF66B3eeF2b65327486", // Router - "0x84B5897A23B067D87Be550e440a3436f6d149fe2", // VotingEscrow - "0xf11432A2754fCf7BFA1725d37e65840776e39ec7", // RewardsDistributor - "0xb670568C84C541eacBee2EF7209A6Ba2Ab349BEC", // Voter - "0xF0FfC7cd3C15EF94C7c5CAE3F39d53206170Fc01", // BasoStaking - ] - } + id: "1296", + name: "ZipSwap", + addresses: { + arbitrum: ["0x4D70D768f5E1e6a7062973aFB0c7FBDa9bBb42b3"], + optimism: ["0xE6Df0BB08e5A97b40B21950a0A51b94c4DbA0Ff6", "0x00000000000013adDDC0919642d45f5d9Df09502"], + }, + }, + { + id: "1364", + name: "Narwhalswap", + addresses: { + bsc: ["0x849B7b4541CDE9cBE41cfd064d9d7fF459b9cEa4"], + }, + }, + { + id: "1074", + name: "AutoShark", + addresses: { + bsc: ["0xB0EeB0632bAB15F120735e5838908378936bd484"], + }, + }, + { + id: "883", + name: "SmartDEX", + addresses: { + polygon: ["0x6f5fE5Fef0186f7B27424679cbb17e45df6e2118"], + }, }, { - "id":"parent#canary", - "name":"Canary", - "addresses":{ - "avax":[ - "0x06f8ED60393AC6A4B16900273C9313222dfe9940" - ] - } + id: "2331", + name: "SwapFish", + addresses: { + arbitrum: ["0xcDAeC65495Fa5c0545c5a405224214e3594f30d8"], + bsc: ["0xcDAeC65495Fa5c0545c5a405224214e3594f30d8"], + }, + }, + { + id: "409", + name: "CafeSwap", + addresses: { + polygon: ["0x9055682E58C74fc8DdBFC55Ad2428aB1F96098Fc"], + bsc: ["0x933DAea3a5995Fb94b14A7696a5F3ffD7B1E385A"], + }, + }, + { + id: "1530", + name: "Excalibur", + addresses: { + fantom: ["0xc8Fe105cEB91e485fb0AC338F2994Ea655C78691"], + }, + }, + { + id: "1359", + name: "CapitalDEX", + addresses: { + ethereum: ["0xDc6844cED486Ec04803f02F2Ee40BBDBEf615f21"], + }, + }, + { + id: "1253", + name: "HakuSwap", + addresses: { + avax: ["0xE6e79A66cB32c53A9d56B18FA737fb5D72c71475", "0x5F1FdcA239362c5b8A8Ada26a256ac5626CC33E0"], + }, + }, + { + id: "455", + name: "ZooCoin", + addresses: { + fantom: ["0x40b12a3E261416fF0035586ff96e23c2894560f2", "0xA7843036252e79fBc495814e714F1439dF8Dc8a4"], + }, + }, + { + id: "1750", + name: "CryptoSwap", + addresses: { + bsc: ["0xe4964c56f46063F25f2a77269B36a773140Ab325"], + }, + }, + { + id: "2865", + name: "Moonbase Alpha", + addresses: { + arbitrum: [ + "0x88FcF70243B4BCC0325060805b7bE9b3DA984805", + "0x5cb6600359Cd392A6Ffea69781d1C6db6A25A18F", //masterchef + ], + }, + }, + { + id: "1150", + name: "WraithSwap", + addresses: { + fantom: [ + "0x8C9E059a729C17fB294cd782eB66Df3871D29173", + "0x37b106f101a63D9d06e53140E52Eb6F8A3aC5bBc", //masterchef + ], + }, + }, + { + id: "920", + name: "Raven", + addresses: { + fantom: [ + "0xbCEf0849DDd928835A6Aa130aE527C2703CD832C", //masterchef + "0x2639779d6CA9091483a2A7b9A1FE77Ab83b90281", //masterchef + ], + }, + }, + { + id: "737", + name: "Dino.Exchange", + addresses: { + bsc: ["0xe12405F0A569A9402fF563FB923A96DC2525D3Eb", "0xc2a88eCE6B6321819D947c9EadEABBa699c16349"], + }, + }, + { + id: "1363", + name: "Oni Exchange", + addresses: { + bsc: [ + "0x3f49193f91a07bb87102e5768fa7a61692EA4D9c", + "0x974A8959c52f6109C59d0A6D63D4eA4CC522DfA2", + "0x09a8521FC838D795555113Fcb5b8fC8C267783F9", //masterchef + "0xE93fC7e6103EF86F3329635B8197D462B74F0cb8", //masterchef + ], + }, + }, + { + id: "1857", + name: "FATExFi", + addresses: { + polygon: ["0x8863f716706e9e4f13A52601A129DD1E1c3fA08B"], + }, + }, + { + id: "1859", + name: "AuraSwap", + addresses: { + polygon: [ + "0x09Fd8B8ed6E30e583379Dc73b9261dF5E1A28b6F", + "0x44Bb1a3E56Cb12b7B1a8E925f09A170e3646346d", //masterchef + ], + }, + }, + { + id: "1018", + name: "Gains Network", + addresses: { + polygon: [ + "0x91993f2101cc758D0dEB7279d41e880F7dEFe827", //gdai + "0xFb06a737f549Eb2512Eb6082A808fc7F16C0819D", //staking + "0x4ba64a81ca50D8B66684C664d75b55eaCcFaCAEb", //trading + "0x8103C0665A544201BBF606d90845d1B2D8005F1c", //nftrewards + "0xd285f881886505b9Ef6684E1aaa7949a56B0C7Da", //gnsmigration + "0xa33f7069f075A54481868e4C0b8D26925A218362", //lockingbridge + "0xDF774A4F3EA5095535f5B8f5b9149caF90FF75Bd", //erc20bridge + "0x2D266A94469d05C9e06D52A4D0d9C23b157767c2", //GFarmNft5 + "0x02e2c5825C1a3b69C0417706DbE1327C2Af3e6C2", //GFarmNft4 + "0x3378AD81D09DE23725Ee9B9270635c97Ed601921", //GFarmNft3 + "0x77cd42B925e1A82f41d852D6BE727CFc88fddBbC", //GFarmNft2 + "0x7075cAB6bCCA06613e2d071bd918D1a0241379E2", //GFarm2Token(old) + "0xF9A4c522E327935BD1F5a338c121E14e4cc1f898", //GFarmNft1 + ], + arbitrum: [ + "0xd85E038593d7A098614721EaE955EC2022B9B91B", //gdai + "0x6B8D3C08072a020aC065c467ce922e3A36D3F9d6", //staking + "0x4ba64a81ca50D8B66684C664d75b55eaCcFaCAEb", //trading + "0x8103C0665A544201BBF606d90845d1B2D8005F1c", //nftrewards + "0xd285f881886505b9Ef6684E1aaa7949a56B0C7Da", //gnsmigration + "0x0F9E4375facBeB90DAA850f677819b438ce50827", //ERC721MintingBridge + "0x01cAaaA682Ceba8cd6c02f93BB1393fB415fA5e2", //erc20bridge + "0x5e3b541Ad6AcC4381C110247946C863e05ffc9BE", //GFarmNft5 + "0x40F0AeaB6383Be2f254cE40B79089070Fa1a21A1", //GFarmNft4 + "0x9834159EAF9811cf4C568294D5C7C9158F84b384", //GFarmNft3 + "0xD1F024ba4Dbb1593B486cB5031b3AC5aC28e8A4e", //GFarmNft2 + "0x75cbcc5414C539C2B302A5fA60E30B949D2D6F89", //GFarmNft1 + ], + ethereum: [ + "0x14e2f9B0381Af4227D26BEE7d8E4D424466A7F3F", //GFarmNftSwap + "0x151757c2E830C467B28Fe6C09c3174b6c76aA0c5", //GNSPoolV5 + "0x1E887E7115321B4ee5d58DD446eC09e12B45d81B", //GFarm + "0x5cA058C1c9E0Bea6b9b5366ADf73BC7f63aDc2d7", //GFarmNFTExchange + ], + }, + }, + { + id: "337", + name: "GMX", + addresses: { + arbitrum: [ + "0x489ee077994B6658eAfA855C308275EAd8097C4A", //Vault + "0xaBBc5F99639c9B6bCb58544ddf04EFA6802F4064", //Router + "0xb87a436B93fFE9D75c5cFA7bAcFff96430b09868", //PositionRouter + "0x09f77E8A13De9a35a7231028187e9fD5DB8a2ACB", //OrderBook + "0x5402B5F40310bDED796c7D0F3FF6683f5C0cFfdf", //StakedGlp + "0xA906F338CB21815cBc4Bc87ace9e68c87eF8d8F1", //RewardRouterV2 + ], + avax: [ + "0x9ab2De34A33fB459b538c43f251eB825645e8595", //Vault + "0x5F719c2F1095F7B9fc68a68e35B51194f4b6abe8", //Router + "0xffF6D276Bc37c61A23f06410Dce4A400f66420f8", //PositionRouter + "0x4296e307f108B2f583FF2F7B7270ee7831574Ae5", //OrderBook + "0xaE64d55a6f09E4263421737397D1fdFA71896a69", //StakedGlp + "0x82147C5A7E850eA4E28155DF107F2590fD4ba327", //RewardRouterV2 + ], + }, + }, + { + id: "2254", + name: "MUX Protocol", + addresses: { + arbitrum: [ + "0x917952280770Daa800E1B4912Ea08450Bf71d57e", //Vault + "0x3e0199792Ce69DC29A0a36146bFa68bd7C8D6633", //liquiditypool + "0x02FAe054ACD7FB1615471319c4E3029DFbC2B23C", //liquiditymanager + "0xa19fD5aB6C8DCffa2A295F78a5Bb4aC543AAF5e3", //OrderBook + "0xaf9C4F6A0ceB02d4217Ff73f3C95BbC8c7320ceE", //RewardRouter + ], + bsc: [ + "0x8D751570BA1Fd8a8ae89E4B27d18bf6C321Aab0a", //Vault + "0x855E99F768FaD76DD0d3EB7c446C0b759C96D520", //liquiditypool + "0xee85CDdCe0CF068091081eA0fcd53f279aa3B09F", //liquiditymanager + "0xa67aA293642C4e02D1b9F360b007C0dBDc451A08", //OrderBook + ], + avax: [ + "0x29a28cC3FdC128693ef6a596eF45c43ff63B7062", //Vault + "0x0bA2e492e8427fAd51692EE8958eBf936bEE1d84", //liquiditypool + "0x28f16eB86481066Bf63BcBEB05C8474f7120A36C", //liquiditymanager + "0x5898c3E218a8501533d771C86e2fA37743ea2aDd", //OrderBook + ], + optimism: [ + "0x39d653884B611E0A8dbdb9720Ad5D75642fd544b", //Vault + "0xc6BD76FA1E9e789345e003B361e4A0037DFb7260", //liquiditypool + "0xFEc3704f4A02cB0EE6C7d52Cbf72b11E0441E9d5", //liquiditymanager + "0x6Fde9892Fd5302ac3c68688085BD5b031A63BC9D", //OrderBook + ], + fantom: [ + "0xdAF2064F52F123EE1D410e97C2df549c23a99683", //Vault + "0x2e81F443A11a943196c88afcB5A0D807721A88E6", //liquiditypool + "0x5898c3E218a8501533d771C86e2fA37743ea2aDd", //liquiditymanager + "0x0c30b10462CdED51C3CA31e7C51019b7d25a965B", //OrderBook + ], + }, + }, + { + id: "2395", + name: "Level Finance", + addresses: { + bsc: [ + "0xA5aBFB56a78D2BD4689b25B8A77fd49Bb0675874", //LiquidityPool + "0xB5C42F84Ab3f786bCA9761240546AA9cEC1f8821", //seniorLLP + "0x4265af66537F7BE1Ca60Ca6070D97531EC571BDd", //MezzanineLLP + "0xcC5368f152453D497061CB1fB578D2d3C54bD0A0", //Junior LLP + "0x1Ab33A7454427814a71F128109fE5B498Aa21E5d", //LevelMaster (old farming contract) + "0x5aE081b6647aEF897dEc738642089D4BDa93C0e7", //LevelMasterV2 (farming contract) + "0xf584A17dF21Afd9de84F47842ECEAF6042b1Bb5b", //OrderManager + ], + }, + }, + { + id: "2116", + name: "0x", + addresses: { + ethereum: [ + "0xdef1c0ded9bec7f1a1670819833240f027b25eff", + "0x61935CbDd02287B511119DDb11Aeb42F1593b7Ef", //Exchangev3 + "0x12459C951127e0c374FF9105DdA097662A027093", //Exchangev1 + "0x080bf510FCbF18b91105470639e9561022937712", //Exchangev2.1 + "0xa26e80e7Dea86279c6d778D702Cc413E6CFfA777", //StakingProxyv3 + ], + bsc: ["0xdef1c0ded9bec7f1a1670819833240f027b25eff"], + polygon: ["0xdef1c0ded9bec7f1a1670819833240f027b25eff"], + avax: ["0xdef1c0ded9bec7f1a1670819833240f027b25eff"], + fantom: ["0xdef189deaef76e379df891899eb5a00a94cbc250"], + celo: ["0xdef1c0ded9bec7f1a1670819833240f027b25eff"], + optimism: ["0xdef1abe32c034e558cdd535791643c58a13acc10"], + arbitrum: ["0xdef1c0ded9bec7f1a1670819833240f027b25eff"], + }, + }, + { + id: "2899", + name: "Vertex", + addresses: { + arbitrum: [ + "0xbbee07b3e8121227afcfe1e2b82772246226128e", // endpoint + ], + }, + }, + { + id: "1917", + name: "Sudoswap", + addresses: { + ethereum: ["0x2b2e8cda09bba9660dca5cb6233787738ad68329", "0xb16c1342e617a5b6e4b631eb114483fdb289c0a4"], + }, + }, + { + id: "340", + name: "Olympus DAO", + addresses: { + ethereum: [ + "0x007fe7c498a2cf30971ad8f2cbc36bd14ac51156", + "0x0b7ffc1f4ad541a4ed16b40d8c37f0929158d101", + "0x73D7e4BDdEcAd7379d679e60f22788E501493896", + "0xf577c77ee3578c7f216327f41b5d7221ead2b2a3", + "0xB63cac384247597756545b500253ff8E607a8020", + "0x007F7735baF391e207E3aA380bb53c4Bd9a5Fed6", + ], + }, + }, + { + id: "2907", + name: "Chronos V1", + addresses: { + arbitrum: [ + "0xE708aA9E887980750C040a6A2Cb901c37Aa34f3b", //routerv2 + "0x5D9dBA2D0ec06F44Da7e234cBB0d7BA921834AE8", //masterchef + "0xC72b5C6D2C33063E89a50B2F77C99193aE6cEe6c", //voter + ], + }, + }, + { + id: "2903", + name: "Swaprum", + addresses: { + arbitrum: [ + "0x1342a24347532DE79372283B3A29c63C31Dd7711", //v2router + "0xEE6cbC97781ff3De7a068D2a6A2dec8CE3a05624", //SwaprumWithdrawals + ], + }, + }, + { + id: "2911", + name: "Aboard Exchange", + addresses: { + arbitrum: [ + "0x7a08b29A7Ad4A19A5ECa0c82F5F082872488D135", //PerpetualProxy + ], + }, + }, + { + id: "2902", + name: "DAMX", + addresses: { + fantom: [ + "0xD093eeE7c968CEef2df96cA9949eba1a1A9b2306", //Vault + "0xeD077045f38f864fba8aD9bdbF1CE8F108e5ddb9", //OrderBook + "0xECef79f974182f4E9c168E751101F23686Bdc6dF", //staking + ], + }, + }, + { + id: "2900", + name: "Wasabi", + addresses: { + ethereum: [ + "0xFc68f2130e094C95B6C4F5494158cbeB172e18a0", //Wasabi Option NFTs (WASAB) + "0xF29A66E420C240EbD23F775b93619C8F3cfFf856", //WasabiConduit + "0x8E2b50413a53F50E2a059142a9be060294961e40", //WasabiPoolFactory + ], + }, + }, + { + id: "2898", + name: "LionDEX", + addresses: { + arbitrum: [ + "0x8eF99304eb88Af9BDe85d58a35339Cb0e2a557B6", //vault + "0x154E2b1dBE9F493fF7938E5d686366138ddCE017", //staking + "0xFeb9Cc52aB4cb153FF1558F587e444Ac3DC2Ea82", //Escrowed LionDEX Token (esLION) + ], + }, + }, + { + id: "parent#smbswap", + name: "SMBSwap", + addresses: { + bsc: [ + "0xBDC5104a3C52A3f49f0324696f9Bb77E41516De7", //MasterChef + "0x009d611490eCfED2dC3F306231Bba7e7F3E9196E", //SMBRouter + "0x63C737E5BD543ECC0A02d91BfCb50845e1be31cF", //SMBRouter + "0x9D4823aa89Dc33ED53d930CB554AFFc58B0c9852", //SMBSwapLottery + "0x85C6129843D120454848F1Da39233AC4fcb50Cb4", //MasterChefV3 + "0x92D118350CAD5EbA374486dbe3d16A9FE66DaeBe", // SmartRouter + ], + }, + }, + { + id: "2886", + name: "RabbitX", + addresses: { + ethereum: [ + "0xFc7f884DE22a59c0009C91733196b012Aecb8F41", //Rabbit + "0x4973710327eDc6f8238DD2d73cf0B2e081e1B351", //RabbitDeposit + ], + }, + }, + { + id: "2883", + name: "Purple Bridge DEX", + addresses: { + polygon: ["0x1e2441Fd53C51d9CD1696BE2871eE672A0A01933"], + }, + }, + { + id: "2872", + name: "printyfinance", + addresses: { + avax: [ + "0x6A8f98d7e34Fd214B428BFc68c9309Ea3C4Fc7F1", //BaseV1Router01 + "0xDc72882909252E133a4A46eFB135b3B145366eba", //PrintyV1Router + "0x6902a8ecF99a732e5a73491Afc14e5E135eE4234", //BaseV2 + ], + }, + }, + { + id: "parent#blur", + name: "Blur", + addresses: { + ethereum: [ + "0x29469395eAf6f95920E59F858042f0e28D98a20B", //ERC1967Proxy + "0x0000000000A39bb272e79075ade125fd351887Ac", //Blur bidding + ], + }, + }, + { + id: "2919", + name: "Backed", + addresses: { + ethereum: [ + "0xF4d4e4ae7fd9CbAfc24b9B0Da2596260c8368314", //paprcontroller + "0x3b29c19ff2fcEa0Ff98D0ef5B184354D74eA74b0", //paprcontroller + ], + }, + }, + { + id: "2918", + name: "DebtDAO", + addresses: { + ethereum: [ + "0xc9eF6509A09b92043cedce689DfAA760048aBd7F", //LineFactory + ], + }, + }, + { + id: "2862", + name: "Hyperliquid", + addresses: { + arbitrum: ["0xC67E9Efdb8a66A4B91b1f3731C75F500130373A4", "0x2df1c51e09aecf9cacb7bc98cb1742757f163df7 "], + }, + }, + { + id: "319", + name: "Convex Finance", + addresses: { + ethereum: ["0xf403c135812408bfbe8713b5a23a04b3d48aae31", ADDRESSES.ethereum.vlCVX], + }, + }, + { + id: "270", + name: "Liquity", + addresses: { + ethereum: [ + "0x4f9fbb3f1e99b56e0fe2892e623ed36a76fc605d", //staking + "0x66017d22b0f8556afdd19fc67041899eb65a21bb", //stabilitypool + "0x24179cd81c9e782a4096035f7ec97fb8b783e007", + ], + }, }, + /* + Only bridge addresses, not actual users { - "id":"3977", - "name": "SquaDeFi", + "id":"144", + "name":"dYdX", "addresses":{ - "base":[ - "0xfad362E479AA318F2De7b2c8a1993Df9BB2B3b1f", // KeyManager - ] + "ethereum":[ + "0xd54f502e184b6b739d7d27a6410a67dc462d69c8", + "0x8e8bd01b5a9eb272cc3892a2e40e64a716aa2a40", + "0x0fd829c3365a225fb9226e75c97c3a114bd3199e", + "0x5aa653a076c1dbb47cec8c1b4d152444cad91941" + ], } }, - -] as ProtocolAddresses[]).filter(isAddressesUsable) + */ + { + id: "parent#radiant", + name: "Radiant", + addresses: { + arbitrum: [ + "0x8991c4c347420e476f1cf09c03aba224a76e2997", + "0x196bf3a63c50bca1eff5a5809b72dfc58f0c2c1a", + "0xebc85d44cefb1293707b11f707bd3cec34b4d5fa", + "0x2032b9a8e9f7e76768ca9271003d3e43e1616b1f", + "0x5682a39078edce41a65f1bd8733bf9ca2bbe3b1b", + "0xc963ef7d977ecb0ab71d835c4cb1bf737f28d010", + ], + bsc: [ + "0x13ef2a9e127ae8d9e9b863c7e375ba68e1a42ac6", + "0xd50cf00b6e600dd036ba8ef475677d816d6c4281", + "0x7c16abb090d3fb266e9d17f60174b632f4229933", + ], + }, + }, + { + id: "parent#paraspace", + name: "ParaSpace", + addresses: { + ethereum: [ + "0x638a98bbb92a7582d07c52ff407d49664dc8b3ee", + "0x59b72fdb45b3182c8502cc297167fe4f821f332d", + "0xf090eb4c2b63e7b26e8bb09e6fc0cc3a7586263b", + "0xc5c9fb6223a989208df27dcee33fc59ff5c26fff", + ], + }, + }, + { + id: "438", + name: "Tokemak", + addresses: { + ethereum: [ + "0x04bda0cf6ad025948af830e75228ed420b0e860d", + "0xd3d13a578a53685b4ac36a1bab31912d2b2a2f36", + "0x8858a739ea1dd3d80fe577ef4e0d03e88561faa3", + "0x41f6a95bacf9bc43704c4a4902ba5473a8b00263", + ], + }, + }, + { + id: "636", + name: "Keep3r Network", + addresses: { + ethereum: [ + "0x02777053d6764996e594c3e88af1d58d5363a2e6", + "0x1ceb5cb57c4d4e2b2433641b95dd330a33185a44", + "0xb9d18ab94cf61bb2bcebe6ac8ba8c19ff0cdb0ca", + ], + }, + }, + { + id: "2255", + name: "NFTfi", + addresses: { + ethereum: ["0xe52cec0e90115abeb3304baa36bc2655731f7934", "0x8252df1d8b29057d1afe3062bf5a64d503152bc8"], + }, + }, + { + id: "483", + name: "NFTX", + addresses: { + ethereum: [ + "0x941a6d105802cccaa06de58a13a6f49ebdcd481c", + "0xdc774d5260ec66e5dd4627e1dd800eff3911345c", + "0x688c3e4658b5367da06fd629e41879beab538e37", + "0x3e135c3e981fae3383a5ae0d323860a34cfab893", + ], + }, + }, + { + id: "2086", + name: "Rage Trade", + addresses: { + arbitrum: [ + "0x1d42783E7eeacae12EbC315D1D2D0E3C6230a068", //Curve Yield Strategy + "0x4b928aFd7CA775C7f4ECdf2c00B7e608962AbbDc", //Rage Trade: Vault Periphery + ], + }, + }, + { + id: "2192", + name: "PlutusDAO", + addresses: { + arbitrum: [ + "0x35cD01AaA22Ccae7839dFabE8C6Db2f8e5A7B2E0", //PlutusPrivateTGE + "0x195B6eA50150900A25FA0928b8B65B03C7666D10", //TGEController + "0xc1D8f4109eC84db9b607e2705779142eC8F9534a", //Plutus DAO: TGE Vault ETH + "0xF4790fc873351C624d225269d4d21cF591e441b2", //Plutus DAO: TGE Vault DPX + "0xd6c9fe8dbc50c620222e8679CFf0461994b532DA", //Plutus DAO: TGE Vault JONES + "0x27Aaa9D562237BF8E024F9b21DE177e20ae50c05", //Plutus DAO: 1 Month Plutus Epoch Staking + "0xE59DADf5F7a9decB8337402Ccdf06abE5c0B2B3E", //Plutus DAO: 3 Month Plutus Epoch Staking + "0xBEB981021ed9c85AA51d96C0c2edA10ee4404A2e", //Plutus DAO: 6 Month Plutus Epoch Staking + "0x5593473e318F0314Eb2518239c474e183c4cBED5", //Plutus DAO: MasterChef + "0x66Cd8Cb1bA49f1A07703fa6E5BFE2BEB2eC8c706", //PlutusDAO: Plutus JONES Depositor + "0x4D56D5A417269A5bFa909cc0f67DFFE992272606", //Plutus DAO: Dpx Depositor + "0x20DF4953BA19c74B2A46B6873803F28Bf640c1B5", //PlutusDAO: Old plsDPX Farm + "0x23B87748b615096d1A0F48870daee203A720723D", //PlutusDAO: plsJONES - Plutus Chef + "0x6CCD4CFaF4bDa43c09682B3e588B4bd18BFFd603", //PrivateTgeRewards + "0x548C30b0af3CE6D96F1A63AfC05F0fb66495179F", //PlutusDAO: DPX Depositor + "0x75c143460F6E3e22F439dFf947E25C9CcB72d2e8", //PlutusDAO: plsDPX Farm + "0x04B724389Dd28Ffc9a3A91Ab4149a77530282f04", //PrivateTgeVester + "0xA61f0d1d831BA4Be2ae253c13ff906d9463299c2", //PlutusChef + "0xb059Fc19371691aa7A3EC66dD80684FFE17A7D5c", //PlutusChef + ADDRESSES.arbitrum.plvGLP, //PlvGlpToken + "0x4E5Cf54FdE5E1237e80E87fcbA555d829e1307CE", //PlutusDAO: plvGLP Farm + "0x8c12e3C9b26Ee2e43A1a71cd974e6bF250472129", //SpaDepositor + "0x73e7c78E8a85C074733920f185d1c78163b555C8", // + "0x9F07B8D6DDA7E68260Add1e38447D0Caa6F1BA0d", //PlutusChef + "0xbe68e51f75F34D8BC06D422056af117b8c23fd54", // + "0x13794D30D01c96D6595d1D956f3dd70AEc2C238B", //ArbDepositor + "0xCfc273D86333bF453b847d4D8cb7958307D85196", // + "0x4C2C41cFfC920CA9dD5F13E88DcF5062ceF37455", // + ], + }, + }, + { + id: "916", + name: "Pika Protocol", + addresses: { + optimism: [ + "0x365324E5045df8c886EBe6AD5449F5CeB5881A40", //PikaPerpV2 + "0x58488bB666d2da33F8E8938Dbdd582D2481D4183", //VaultFeeReward + "0x2FaE8C7Edd26213cA1A88fC57B65352dbe353698", //Pika Protocol: Perpetual V2 + "0x8123DCe565111F64c01864B2ae0F35e3181A0A02", //PositionManager + "0xf9B19D0e62278ec9CBBaD5CcA5e7A270979bEa4E", //OrderBook + "0xD5A8f233CBdDb40368D55C3320644Fb36e597002", //PikaPerpV3 + "0x939c11c596B851447e5220584d37F12854bA02ae", //VaultFeeReward + "0x78136EF4BDcbdABb8D7aa09a33C3c16Ca6381910", //VaultTokenReward + ], + }, + }, + { + id: "2618", + name: "OasisSwap", + addresses: { + arbitrum: ["0xe805977D5Fa2f05e2175507a1f8E44Cd3F22972c", "0x5bf51bf7af925306866d6cf87b4b85189df67970"], + }, + }, + { + id: "1521", + name: "Horizon Protocol", + addresses: { + bsc: [ + "0xFCF3afa6cdA14B438AeEb8FfEd433D196Cd1367F", + "0x9657a0FD98e88464E1159d98b517A4945dbFBFC8", //DelegateApprovals + "0xadA58Cf32276CCD03a1C155688eFF8B3BC282285", //PhbStaking + "0xa1771DCfb7822C8853D7E64B86E58f7f1eB5e33E", //StakingRewards + "0xE21e39c383ABDce3edf13b7233Ad1ad5FEE42099", //RewardEscrowV2 + ], + }, + }, + { + id: "2970", + name: "Beluga Dex", + addresses: { + arbitrum: ["0x7668bcBf650AE69297E411d2A8Ec91e07dd91c0B", "0x48945A091108bBbd54829B632B1dF94BB50F81D7"], + }, + }, + { + id: "2968", + name: "GND Protocol", + addresses: { + arbitrum: [ + "0xd8769d8826149B137AF488b1e9Ac0e3AFdbC058a", //UniswapV3LP + ], + }, + }, + { + id: "2957", + name: "Seashell", + addresses: { + arbitrum: [ + "0x5BAC5eEfA13696Cf815388021235b215587263Ea", //Blueberry GLP Compounder LP Token (Blueberry...) + ], + }, + }, + { + id: "2586", + name: "Equilibre", + addresses: { + kava: [ + "0xA7544C409d772944017BB95B99484B6E0d7B6388", //router2 + "0xa337E9426d080970b026caFfb4a83D185b85A124", //GaugeFactory + "0x7B14b7288D50810a6982149B107238065AA7fcb7", //BribeFactory + "0x35361C9c2a324F5FB8f3aed2d7bA91CE1410893A", //VotingEscrow + "0x553796D20BB387E9b3F91Aa35fD289B753D63baF", //VeArtProxy + "0x8825be873e6578F1703628281600d5887C41C55A", //RewardsDistributor + ], + }, + }, + { + id: "1765", + name: "Unicrypt", + addresses: { + ethereum: [ + "0x663a5c229c09b049e36dcc11a9b0d4a8eb9db214", //univ2locker + "0xdba68f07d1b7ca219f78ae8582c213d975c25caf", //tokenvesting + "0x17e00383a843a9922bca3b280c0ade9f8ba48449", //pollocker + "0xed9180976c2a4742c7a57354fd39d8bec6cbd8ab", //sushilocker + ], + bsc: [ + "0xeaed594b5926a7d5fbbc61985390baaf936a6b8d", //TokenVestingBSC + "0xc765bddb93b0d1c1a88282ba0fa6b2d00e3e0c83", //UniswapV2Locker + "0xc765bddb93b0d1c1a88282ba0fa6b2d00e3e0c83", //pancakev2locker + "0xc8B839b9226965caf1d9fC1551588AaF553a7BE6", //pancakev1locker + "0x74dee1a3e2b83e1d1f144af2b741bbaffd7305e1", //biswaplocker + "0x1391b48c996ba2f4f38aee07e369a8f28d38220e", //safeswaplocker + "0x1f23742D882ace96baCE4658e0947cCCc07B6a75", //julswaplocker + "0xb89a15a4f3518c14c21be04b55546162b0cb39f0", //babydogeswaplocker + ], + polygon: [ + "0xadb2437e6f65682b85f814fbc12fec0508a7b1d0", //quickswaplocker + ], + avax: [ + "0xa9f6aefa5d56db1205f36c34e6482a6d4979b3bb", //traderjoelocker + ], + xdai: [ + "0xe3D32266974f1E8f8549cAf9F54977040e7D1c07", //honeyswaplocker + ], + }, + }, + { + id: "2397", + name: "Gyroscope Protocol", + addresses: { + polygon: [ + "0x37b8E1152fB90A867F3dccA6e8d537681B04705E", //Proto Gyro Dollar (p-GYD) + "0x68BDeE1bF95AD730F379A05eB8c51fb5dFA07748", //FreezableTransparentUpgradeableProxy + ], + }, + }, + { + id: "3093", + name: "eZKalibur", + addresses: { + era: [ + "0x498f7bB59c61307De7dEA005877220e4406470e9", //router + ], + }, + }, + { + id: "2952", + name: "Archi Finance", + addresses: { + arbitrum: [ + "0x7674Ccf6cAE51F20d376644C42cd69EC7d4324f4", //WETHVaultProxy + "0x179bD8d1d654DB8aa1603f232E284FF8d53a0688", //USDTVaultProxy + "0xa7490e0828Ed39DF886b9032ebBF98851193D79c", //USDCVaultProxy + "0xee54A31e9759B0F7FDbF48221b72CD9F3aEA00AB", //WBTCVaultProxy + ], + }, + }, + { + id: "3173", + name: "Equity", + addresses: { + fantom: [ + "0x9e4105F9E2284532474f69e65680e440F4C91cb8", //Vault + "0xe8ca91bAe8AA0E9229F6E78f8976B837134b60E8", //ShortsTracker + "0xA83F31aF44e812d2EdF0536516e7D274cd7301B8", //OrderBook + "0xd311Fd89e8403c2E90593457543E99cECc70D511", //Router + "0xf2BfB9cA6e21b30034b9d56Cb4735d2c180cC7e1", //PositionRouter + "0xfb0c0cE1d43B373b7535Ef556e1D55D285156887", //RewardRouter + "0x8f02357cb55DbAd26DF5a7558CD810D5D0f05f43", //OrderBookReader + "0x3e8B14B5534333A2B83a31d778ec3bCd9dc946f4", //RewardReader + "0x8F6666bd81C4811F433B8232a1c7D4383f11b2dC", //Timelock + "0xBF65ca2747a1EeebF8a1b0d119De8BE0540c57Cb", //StakedEquity + "0x88171375F6236885f463341d001B419D477eDB74", //Reader + ], + }, + }, + { + id: "3345", + name: "DackieSwap", + addresses: { + base: [ + "0x195FBc5B8Fbd5Ac739C1BA57D4Ef6D5a704F34f7", //smartrouter + "0xCfB05AB06D338FD85BBF4486e69809D96A906b77", //nftmanager + "0xd592e2C815E0cf4B62169e09934FaAB28299708e", //v3lmpooldeployer + ], + }, + }, + { + id: "3341", + name: "Chronos V2", + addresses: { + arbitrum: [ + //univ3 fork + "0xE0aBdFD837D451640CF43cB1Ec4eE87976eFbb41", //swapRouter + "0x9aAb66944D66516FEFa26D27267E02af03d17c02", //nftDescriptor + "0x5e74e05771f0d1222834e66DE5326C82a2C852e0", //nonfungibleTokenPositionDescriptor + "0x520CAF43e3C6481b71DB95711802ED9179ccA403", //nonfungiblePositionManager + ], + }, + }, + { + id: "3450", + name: "Aerodrome", + addresses: { + base: [ + //velodrome v2 fork + "0xeBf418Fe2512e7E6bd9b87a8F0f294aCDC67e6B4", //VotingEscrow + "0x16613524e02ad97eDfeF371bC883F2F5d6C480A5", //Voter + "0xcF77a3Ba9A5CA399B7c97c74d54e5b1Beb874E43", //Router + ], + }, + }, + { + id: "3377", + name: "Friend.tech", + addresses: { + base: ["0xcf205808ed36593aa40a44f10c7f7c2f67d4a4d4"], + }, + }, + { + id: "3733", + name: "Chat3", + addresses: { + mantle: ["0xAd3dbD09835CF15c543Bc59d31865D659b71060e"], + }, + }, + { + id: "970", + name: "Drift", + addresses: { + solana: [ + "dRiftyHA39MWEi3m9aunc5MzRF1JYuBsbn6VPcn33UH", // dex program id + "VAULtLeTwwUxpwAw98E6XmgaDeQucKgV5UaiAuQ655D", // vaults program id + ], + }, + }, + { + id: "parent#baseswap", + name: "BaseSwap", + addresses: { + base: [ + "0x327Df1E6de05895d2ab08513aaDD9313Fe505d86", // router + "0xc102505248c36f933934d4B2d7579D962a342eBC", + "0x2B0A43DCcBD7d42c18F6A83F86D1a19fA58d541A", + "0xDe151D5c92BfAA288Db4B67c21CD55d5826bCc93", // NonfungiblePositionManager + ], + }, + }, + { + id: "3575", + name: "Scale", + addresses: { + base: [ + "0x5E9d25014D01323d6F8c0C6640572e4444d11C94", // router + "0x3f0458FfB6D106d2F5CdeC9CEdc9054A69275489", + "0x2F87Bf58D5A9b2eFadE55Cdbd46153a0902be6FA", + ], + }, + }, + { + id: "parent#swapbased", + name: "SwapBased", + addresses: { + base: [ + "0xaaa3b1F1bd7BCc97fD1917c18ADE665C5D31F066", // router + "0xcb9665E990027e115ccF22230b042e4E7eaBFDB2", // SingleStakingRewardsBase + "0xE39226E0864252E0fC9bD668FB796FD63a1B75A4", // SingleStakingRewardsBase + "0x2168eb98C6D416Afb85E7beef5abDc4FB4177dfE", // BlpToken + "0x265a30f14E34248567B5B0a83978C38dF38D0C60", // RewardRouter + "0xEfE632dB3A07FeBcEc04f76Ea54D9d49f27bCd57", // SingleStakingRewardsXBase + "0x272A9acB288915Bb52A0659c8F9f7bFeBA06fae5", // SingleStakingRewardsOtherTokens + "0x86dAbE269B1c5Ff7fCFf1eA32545489DF66C29EA", // SingleStakingRewardsOtherTokens + ], + }, + }, + { + id: "parent#alien-base", + name: "Alien Base", + addresses: { + base: [ + "0x52eaeCAC2402633d98b95213d0b473E069D86590", // BasedDistributorV2 + "0x7f2ff89d3C45010c976Ea6bb7715DC7098AF786E", // UniswapV2Router02 + "0x927860797d07b1C46fbBe7f6f73D45C7E1BFBb27", // SwapFlashLoan + "0x8c1A3cF8f83074169FE5D7aD50B978e1cD6b37c7", // UniswapV2Router02 + "0x3485F8E155973cC247CBEa9E77C0dBBB4BBb79E7", // UniswapV2Router02 + "0xe0808b8e2bDD70D70e540f977cF40E26e5811054", // AlienbaseZapV1 + "0xFBE87Ee1Ee62244A2dF80a8093Eab829C52863e8", // PredictionETH + ], + }, + }, + { + id: "3348", + name: "Soswap", + addresses: { + base: [ + "0x53BAE026d9a503d46a58aF4b65FCcbb7B904A911", // SOFIProxy + "0xBC097E42BF1E6531C32C5cEe945E0c014fA21964", // PortfolioFactory + "0x1e6Dbd0E827cd243d458ed73B9Ae1a6Db89B8668", // PortfolioModule + "0x4E69553b0aEf0949Fd38Bbf3EbeD866B431C9E68", // ManagerModule + "0x73Ada4aE37Ba1DF45Ba12c4478a27029e24cF2d7", // SOFITrading + ], + }, + }, + { + id: "3314", + name: "RocketSwap Base", + addresses: { + base: [ + "0x4cf76043B3f97ba06917cBd90F9e3A2AAC1B306e", // UniswapV2Router02 + "0x234Ccb5c64FDB3958C47E8efBe122b2d54633a96", // RcktLocker + "0x32C9ACE2d1eB47C3968660De9eF20569f850814D", // + "0xE20d24cf9fAF458b98B6F34e5346361e6492aA5F", + "0x304063953727b53048500dfd877A17d1C4f6EaFf", // RcktMasterChef + "0x2ec62d08277FfC42eB5af71c7595C1a9f9458A3c", // RcktVault + ], + }, + }, + { + id: "3540", + name: "MoonBase", + addresses: { + base: [ + "0x99554FA8B48F735D4Ccce5E077742cF2D084b258", // MoonChef + "0x4617695387bE48c3202a0A9165549c790C4A08Af", // UniswapRouter + ], + }, + }, + { + id: "3380", + name: "Baso Finance", + addresses: { + base: [ + "0x5568e4F19B9063E0e0386bF66B3eeF2b65327486", // Router + "0x84B5897A23B067D87Be550e440a3436f6d149fe2", // VotingEscrow + "0xf11432A2754fCf7BFA1725d37e65840776e39ec7", // RewardsDistributor + "0xb670568C84C541eacBee2EF7209A6Ba2Ab349BEC", // Voter + "0xF0FfC7cd3C15EF94C7c5CAE3F39d53206170Fc01", // BasoStaking + ], + }, + }, + { + id: "parent#canary", + name: "Canary", + addresses: { + avax: ["0x06f8ED60393AC6A4B16900273C9313222dfe9940"], + }, + }, + { + id: "3977", + name: "SquaDeFi", + addresses: { + base: [ + "0xfad362E479AA318F2De7b2c8a1993Df9BB2B3b1f", // KeyManager + ], + }, + }, + { + id: "3107", + name: "EigenLayer", + addresses: { + ethereum: ["0x858646372cc42e1a627fce94aa7a7033e7cf075a"], + }, + }, + { + id: "1004", + name: "Colony", + addresses: { + avax: [ + "0xA2e7ab89A2C59818E1ecD925E718a9d63889A131", // Router + "0x2aC45f92EABaa8DCB2eA1807A659a1393C3947d0", // Masterchef + "0x3Db497a9783eBbEda6950d4f1911B3a27D79C071", // AntTiers + "0x62685d3EAacE96D6145D35f3B7540d35f482DE5b", // StakingV3 + "0x62B38293896e040e36fE5345F9D30DbFd75C04B9", // EarlyStageManager + "0x17CE2A490CB260b48891aDE019a86f4B4a5520d4", // Comments + "0xac59c21ADfdDb1E56A959dD60a08c07AaED2F3Ba", // Upvotes + "0xd071AA359ed1b7776A12c8329f2C337aBED157D7", // Analysis + ], + }, + }, + { + "id":"382", + "name": "Pendle", + "addresses":{ + // routers + ethereum: ["0x888888888889758F76e7103c6CbF23ABbF58F946"], + arbitrum: ["0x888888888889758F76e7103c6CbF23ABbF58F946"], + optimism: ["0x888888888889758F76e7103c6CbF23ABbF58F946"], + mantle: ["0x888888888889758F76e7103c6CbF23ABbF58F946"], + bsc: ["0x888888888889758F76e7103c6CbF23ABbF58F946"], + } + }, + { + id: "5157", + name: "Yellow", + addresses: { + ethereum: ["0x2A8B51821884CF9A7ea1A24C72E46Ff52dCb4F16"], + bsc: ["0x2A8B51821884CF9A7ea1A24C72E46Ff52dCb4F16"], + polygon: ["0x2A8B51821884CF9A7ea1A24C72E46Ff52dCb4F16"], + base: ["0x2A8B51821884CF9A7ea1A24C72E46Ff52dCb4F16"], + arbitrum: ["0x2A8B51821884CF9A7ea1A24C72E46Ff52dCb4F16"], + }, + }, + ] as ProtocolAddresses[] +).filter(isAddressesUsable); diff --git a/utils/fetchURL.ts b/utils/fetchURL.ts index b5d6a31f4d..bc6dcb302a 100644 --- a/utils/fetchURL.ts +++ b/utils/fetchURL.ts @@ -10,12 +10,12 @@ export default async function fetchURL(url: string, retries = 3) { } } -export async function postURL(url: string, data: any, retries = 3) { +export async function postURL(url: string, data: any, retries = 3, options?: AxiosRequestConfig) { try { - const res = await httpPost(url, data) + const res = await httpPost(url, data, options) return res } catch (error) { - if (retries > 0) return postURL(url, data, retries - 1) + if (retries > 0) return postURL(url, data, retries - 1, options) throw error } } @@ -43,13 +43,14 @@ export async function httpGet(url: string, options?: AxiosRequestConfig, { withM } } -export async function httpPost(url: string, data: any, options?: AxiosRequestConfig) { +export async function httpPost(url: string, data: any, options?: AxiosRequestConfig, { withMetadata = false } = {}) { try { const res = await axios.post(url, data, options) if (!successCodes.includes(res.status)) throw new Error(`Error fetching ${url}: ${res.status} ${res.statusText}`) if (!res.data) throw new Error(`Error fetching ${url}: no data`) return res.data } catch (error) { + if (withMetadata) throw error throw formAxiosError(url, error, { method: 'POST' }) } }