diff --git a/dexs/pika-protocol-v4/index.ts b/dexs/pika-protocol-v4/index.ts new file mode 100644 index 0000000000..1b2e5b0233 --- /dev/null +++ b/dexs/pika-protocol-v4/index.ts @@ -0,0 +1,68 @@ +import { Chain } from "@defillama/sdk/build/general"; +import BigNumber from "bignumber.js"; +import request, { gql } from "graphql-request"; +import { Adapter, FetchResultFees, FetchResultVolume } from "../../adapters/types"; +import { CHAIN } from "../../helpers/chains"; +import { getUniqStartOfTodayTimestamp } from "../../helpers/getUniSubgraphVolume"; +import { getTimestampAtStartOfDayUTC } from "../../utils/date"; +import { getBlock } from "../../helpers/getBlock"; + +interface IData { + date: number; + cumulativeVolume: string; +} + +type IURL = { + [l: string | Chain]: string; +} + +interface IValume { + vaultDayData: IData; + vaults: IData[]; +} + +const endpoints: IURL = { + [CHAIN.OPTIMISM]: "https://api.thegraph.com/subgraphs/name/ethandev0/pikaperpv4_optimism" +} + +const fetch = (chain: Chain) => { + return async (timestamp: number): Promise => { + const todayTimestamp = getUniqStartOfTodayTimestamp(new Date(timestamp * 1000)); + const dateId = Math.floor(getTimestampAtStartOfDayUTC(todayTimestamp) / 86400) + const block = (await getBlock(todayTimestamp, chain, {})); + const graphQuery = gql + ` + { + vaultDayData(id: ${dateId}) { + date + id + cumulativeVolume + } + vaults(block: { number: ${block} }) { + cumulativeVolume + } + } + `; + + 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; + + return { + timestamp, + dailyVolume: dailyVolume.toString(), + totalVolume: totalVolume.toString() + }; + } +} + +const adapter: Adapter = { + adapter: { + [CHAIN.OPTIMISM]: { + fetch: fetch(CHAIN.OPTIMISM), + start: async () => 1658534400, + }, + }, +}; + +export default adapter; diff --git a/fees/pika-protocol-v4.ts b/fees/pika-protocol-v4.ts new file mode 100644 index 0000000000..f86404ade0 --- /dev/null +++ b/fees/pika-protocol-v4.ts @@ -0,0 +1,129 @@ +import { Chain } from "@defillama/sdk/build/general"; +import BigNumber from "bignumber.js"; +import request, { gql } from "graphql-request"; +import { Adapter, FetchResultFees, FetchResultVolume } from "../adapters/types"; +import { CHAIN } from "../helpers/chains"; +import { getUniqStartOfTodayTimestamp } from "../helpers/getUniSubgraphVolume"; +import { getTimestampAtStartOfDayUTC } from "../utils/date"; +import { getBlock } from "../helpers/getBlock"; + +interface IVault { + txCount: number; +} + +interface ITransaction { + id: number; + timestamp: number; + tradeFee: number; + count: number; +} +interface ILiquidation { + timestamp: number; + remainingReward: number; +} + +type IURL = { + [l: string | Chain]: string; +} + +interface IFees { + vaults: IVault[]; +} +interface ITransactions { + transactions: ITransaction[] +} +interface ILiquidations { + liquidations: ILiquidation[] +} + +const endpoints: IURL = { + [CHAIN.OPTIMISM]: "https://api.thegraph.com/subgraphs/name/ethandev0/pikaperpv4_optimism" +} + +const fetch = (chain: Chain) => { + return async (): Promise => { + let todayLiquidationFee = 0; + let todayTradeFee = 0; + const timestamp = Math.floor(Date.now() / 1000 - 86400); + const graphQuery1 = gql + ` + { + vaults(first: 1) + { + txCount + } + } + `; + const res1: IFees = (await request(endpoints[chain], graphQuery1)); + const totalCount = res1.vaults[0].txCount + let skip = totalCount; + while(skip > totalCount - 3000) { + const graphQuery2 = gql + ` + { + transactions(first:1000, where: {count_lt: ${skip}}, orderBy: count, orderDirection: desc) + { + id + singleAmount + timestamp + tradeFee + count + } + } + `; + const res2: ITransactions = (await request(endpoints[chain], graphQuery2)); + + if (res2 !== undefined) { + let transactions = res2.transactions; + transactions.map((item: ITransaction) => { + if (item.timestamp > timestamp) { + todayTradeFee += item.tradeFee / 100000000 + } + }); + skip = transactions[transactions.length - 1].count * 1 + } + } + const graphQuery3 = gql + ` + { + liquidations(where: { + timestamp_gt: ${timestamp} + }) + { + id + remainingReward + timestamp + } + } + `; + const res3: ILiquidations = (await request(endpoints[chain], graphQuery3)); + let liquidations = res3.liquidations; + liquidations.map((item: ILiquidation) => { + if (item.timestamp > timestamp) { + todayLiquidationFee += item.remainingReward / 100000000; + } + }); + + const dailyFees = todayTradeFee + todayLiquidationFee; + const dailySupplySideRevenue = dailyFees * 0.5; + const dailyProtocolRevenue = dailyFees * 0.3; + return { + timestamp, + dailyFees: dailyFees.toString(), + dailyRevenue: dailyProtocolRevenue.toString(), + dailySupplySideRevenue: dailySupplySideRevenue.toString(), + dailyProtocolRevenue: dailyProtocolRevenue.toString(), + }; + } +} + +const adapter: Adapter = { + adapter: { + [CHAIN.OPTIMISM]: { + fetch: fetch(CHAIN.OPTIMISM), + start: async () => 1658534400, + }, + }, +}; + +export default adapter;