From b6daf5730069c4efb9adf4440fd41eb5889eaab2 Mon Sep 17 00:00:00 2001 From: gmbronco <83549293+gmbronco@users.noreply.github.com> Date: Wed, 4 Dec 2024 12:24:33 +0100 Subject: [PATCH] change 7 and 30 days swap apr to use snapshots --- .changeset/slow-windows-allow.md | 5 + apps/worker/job-handlers.ts | 46 +++--- modules/controllers/aprs-controller.ts | 12 ++ modules/network/arbitrum.ts | 8 +- modules/network/avalanche.ts | 9 +- modules/network/base.ts | 8 +- modules/network/fantom.ts | 8 +- modules/network/fraxtal.ts | 8 +- modules/network/gnosis.ts | 8 +- modules/network/mainnet.ts | 16 +- modules/network/mode.ts | 8 +- modules/network/optimism.ts | 8 +- modules/network/polygon.ts | 8 +- modules/network/sepolia.ts | 8 +- modules/network/zkevm.ts | 8 +- .../swap-fee-apr-from-snapshots.service.ts | 148 ++++++++++++++++++ .../apr-data-sources/swap-fee-apr.service.ts | 21 ++- tasks/index.ts | 2 + 18 files changed, 289 insertions(+), 50 deletions(-) create mode 100644 .changeset/slow-windows-allow.md create mode 100644 modules/pool/lib/apr-data-sources/swap-fee-apr-from-snapshots.service.ts diff --git a/.changeset/slow-windows-allow.md b/.changeset/slow-windows-allow.md new file mode 100644 index 000000000..9fe9f4670 --- /dev/null +++ b/.changeset/slow-windows-allow.md @@ -0,0 +1,5 @@ +--- +'backend': patch +--- + +change 7 and 30 days swap apr to use snapshots diff --git a/apps/worker/job-handlers.ts b/apps/worker/job-handlers.ts index 1dfaf2bdd..90d8542fc 100644 --- a/apps/worker/job-handlers.ts +++ b/apps/worker/job-handlers.ts @@ -153,18 +153,6 @@ const setupJobHandlers = async (name: string, chainId: string, res: any, next: N next, ); break; - case 'update-pool-apr': - await runIfNotAlreadyRunning( - name, - chainId, - () => { - const chain = chainIdToChain[chainId]; - return poolService.updatePoolAprs(chain); - }, - res, - next, - ); - break; case 'load-on-chain-data-for-pools-with-active-updates': await runIfNotAlreadyRunning( name, @@ -296,6 +284,34 @@ const setupJobHandlers = async (name: string, chainId: string, res: any, next: N next, ); break; + // APRs + case 'sync-merkl': + await runIfNotAlreadyRunning(name, chainId, () => AprsController().syncMerkl(), res, next); + break; + case 'update-7-30-days-swap-apr': + await runIfNotAlreadyRunning( + name, + chainId, + () => AprsController().update7And30DaysSwapAprs(chain), + res, + next, + ); + break; + case 'update-surplus-aprs': + await runIfNotAlreadyRunning(name, chainId, () => CowAmmController().updateSurplusAprs(), res, next); + break; + case 'update-pool-apr': + await runIfNotAlreadyRunning( + name, + chainId, + () => { + const chain = chainIdToChain[chainId]; + return poolService.updatePoolAprs(chain); + }, + res, + next, + ); + break; // V3 Jobs case 'add-pools-v3': await runIfNotAlreadyRunning(name, chainId, () => PoolController().addPoolsV3(chain), res, next); @@ -365,12 +381,6 @@ const setupJobHandlers = async (name: string, chainId: string, res: any, next: N case 'update-cow-amm-volume-and-fees': await runIfNotAlreadyRunning(name, chainId, () => CowAmmController().updateVolumeAndFees(chain), res, next); break; - case 'update-surplus-aprs': - await runIfNotAlreadyRunning(name, chainId, () => CowAmmController().updateSurplusAprs(), res, next); - break; - case 'sync-merkl': - await runIfNotAlreadyRunning(name, chainId, () => AprsController().syncMerkl(), res, next); - break; case 'sync-categories': await runIfNotAlreadyRunning(name, chainId, () => ContentController().syncCategories(), res, next); break; diff --git a/modules/controllers/aprs-controller.ts b/modules/controllers/aprs-controller.ts index 18b63bfa3..45877ed38 100644 --- a/modules/controllers/aprs-controller.ts +++ b/modules/controllers/aprs-controller.ts @@ -1,4 +1,7 @@ +import { Chain } from '@prisma/client'; import { syncMerklRewards } from '../actions/aprs/merkl'; +import { SwapFeeFromSnapshotsAprService } from '../pool/lib/apr-data-sources/swap-fee-apr-from-snapshots.service'; +import { prisma } from '../../prisma/prisma-client'; export function AprsController(tracer?: any) { // Setup tracing @@ -7,5 +10,14 @@ export function AprsController(tracer?: any) { async syncMerkl() { return await syncMerklRewards(); }, + async update7And30DaysSwapAprs(chain: Chain) { + const service = new SwapFeeFromSnapshotsAprService(); + const pools = await prisma.prismaPool.findMany({ + where: { chain }, + include: { tokens: true }, + }); + await service.updateAprForPools(pools); + return 'Done'; + }, }; } diff --git a/modules/network/arbitrum.ts b/modules/network/arbitrum.ts index 1502ecb04..a4eead7cf 100644 --- a/modules/network/arbitrum.ts +++ b/modules/network/arbitrum.ts @@ -2,7 +2,7 @@ import { ethers } from 'ethers'; import { DeploymentEnv, NetworkConfig } from './network-config-types'; import { tokenService } from '../token/token.service'; import { BoostedPoolAprService } from '../pool/lib/apr-data-sources/nested-pool-apr.service'; -import { SwapFeeFromEventsAprService } from '../pool/lib/apr-data-sources/'; +import { SwapFeeAprService } from '../pool/lib/apr-data-sources/'; import { GaugeAprService } from '../pool/lib/apr-data-sources/ve-bal-gauge-apr.service'; import { UserSyncGaugeBalanceService } from '../user/lib/user-sync-gauge-balance.service'; import { every } from '../../apps/scheduler/intervals'; @@ -22,7 +22,7 @@ export const arbitrumNetworkConfig: NetworkConfig = { poolAprServices: [ new YbTokensAprService(arbitrumNetworkData.ybAprConfig, arbitrumNetworkData.chain.prismaId), new BoostedPoolAprService(), - new SwapFeeFromEventsAprService(), + new SwapFeeAprService(), new GaugeAprService(tokenService, [arbitrumNetworkData.bal!.address]), ], userStakedBalanceServices: [new UserSyncGaugeBalanceService(), new UserSyncAuraBalanceService()], @@ -54,6 +54,10 @@ export const arbitrumNetworkConfig: NetworkConfig = { name: 'update-pool-apr', interval: (env.DEPLOYMENT_ENV as DeploymentEnv) === 'canary' ? every(6, 'minutes') : every(2, 'minutes'), }, + { + name: 'update-7-30-days-swap-apr', + interval: every(8, 'hours'), + }, { name: 'load-on-chain-data-for-pools-with-active-updates', interval: (env.DEPLOYMENT_ENV as DeploymentEnv) === 'canary' ? every(4, 'minutes') : every(1, 'minutes'), diff --git a/modules/network/avalanche.ts b/modules/network/avalanche.ts index e81f84e28..f1068c4d6 100644 --- a/modules/network/avalanche.ts +++ b/modules/network/avalanche.ts @@ -2,7 +2,7 @@ import { BigNumber, ethers } from 'ethers'; import { DeploymentEnv, NetworkConfig, NetworkData } from './network-config-types'; import { tokenService } from '../token/token.service'; import { BoostedPoolAprService } from '../pool/lib/apr-data-sources/nested-pool-apr.service'; -import { SwapFeeFromEventsAprService } from '../pool/lib/apr-data-sources/'; +import { SwapFeeAprService } from '../pool/lib/apr-data-sources/'; import { GaugeAprService } from '../pool/lib/apr-data-sources/ve-bal-gauge-apr.service'; import { UserSyncGaugeBalanceService } from '../user/lib/user-sync-gauge-balance.service'; import { every } from '../../apps/scheduler/intervals'; @@ -22,7 +22,7 @@ export const avalancheNetworkConfig: NetworkConfig = { poolAprServices: [ new YbTokensAprService(avalancheNetworkData.ybAprConfig, avalancheNetworkData.chain.prismaId), new BoostedPoolAprService(), - new SwapFeeFromEventsAprService(), + new SwapFeeAprService(), new GaugeAprService(tokenService, [avalancheNetworkData.bal!.address]), ], userStakedBalanceServices: [new UserSyncGaugeBalanceService(), new UserSyncAuraBalanceService()], @@ -54,6 +54,11 @@ export const avalancheNetworkConfig: NetworkConfig = { name: 'update-pool-apr', interval: (env.DEPLOYMENT_ENV as DeploymentEnv) === 'canary' ? every(6, 'minutes') : every(2, 'minutes'), }, + { + name: 'update-7-30-days-swap-apr', + interval: every(8, 'hours'), + }, + { name: 'load-on-chain-data-for-pools-with-active-updates', interval: (env.DEPLOYMENT_ENV as DeploymentEnv) === 'canary' ? every(4, 'minutes') : every(1, 'minutes'), diff --git a/modules/network/base.ts b/modules/network/base.ts index 3b49cc07e..f2020119f 100644 --- a/modules/network/base.ts +++ b/modules/network/base.ts @@ -2,7 +2,7 @@ import { ethers } from 'ethers'; import { DeploymentEnv, NetworkConfig, NetworkData } from './network-config-types'; import { tokenService } from '../token/token.service'; import { BoostedPoolAprService } from '../pool/lib/apr-data-sources/nested-pool-apr.service'; -import { SwapFeeFromEventsAprService } from '../pool/lib/apr-data-sources/'; +import { SwapFeeAprService } from '../pool/lib/apr-data-sources/'; import { GaugeAprService } from '../pool/lib/apr-data-sources/ve-bal-gauge-apr.service'; import { UserSyncGaugeBalanceService } from '../user/lib/user-sync-gauge-balance.service'; import { every } from '../../apps/scheduler/intervals'; @@ -22,7 +22,7 @@ export const baseNetworkConfig: NetworkConfig = { poolAprServices: [ new YbTokensAprService(baseNetworkData.ybAprConfig, baseNetworkData.chain.prismaId), new BoostedPoolAprService(), - new SwapFeeFromEventsAprService(), + new SwapFeeAprService(), new GaugeAprService(tokenService, [baseNetworkData.bal!.address]), ], userStakedBalanceServices: [new UserSyncGaugeBalanceService(), new UserSyncAuraBalanceService()], @@ -54,6 +54,10 @@ export const baseNetworkConfig: NetworkConfig = { name: 'update-pool-apr', interval: (env.DEPLOYMENT_ENV as DeploymentEnv) === 'canary' ? every(6, 'minutes') : every(2, 'minutes'), }, + { + name: 'update-7-30-days-swap-apr', + interval: every(8, 'hours'), + }, { name: 'load-on-chain-data-for-pools-with-active-updates', interval: (env.DEPLOYMENT_ENV as DeploymentEnv) === 'canary' ? every(4, 'minutes') : every(1, 'minutes'), diff --git a/modules/network/fantom.ts b/modules/network/fantom.ts index 8a4e7ae3b..5c322ff00 100644 --- a/modules/network/fantom.ts +++ b/modules/network/fantom.ts @@ -1,7 +1,7 @@ import { ethers } from 'ethers'; import { DeploymentEnv, NetworkConfig, NetworkData } from './network-config-types'; import { BoostedPoolAprService } from '../pool/lib/apr-data-sources/nested-pool-apr.service'; -import { SwapFeeFromEventsAprService } from '../pool/lib/apr-data-sources/'; +import { SwapFeeAprService } from '../pool/lib/apr-data-sources/'; import { MasterchefFarmAprService } from '../pool/lib/apr-data-sources/fantom/masterchef-farm-apr.service'; import { ReliquaryFarmAprService } from '../pool/lib/apr-data-sources/fantom/reliquary-farm-apr.service'; import { UserSyncMasterchefFarmBalanceService } from '../user/lib/user-sync-masterchef-farm-balance.service'; @@ -23,7 +23,7 @@ export const fantomNetworkConfig: NetworkConfig = { poolAprServices: [ new YbTokensAprService(fantomNetworkData.ybAprConfig, fantomNetworkData.chain.prismaId), new BoostedPoolAprService(), - new SwapFeeFromEventsAprService(), + new SwapFeeAprService(), new MasterchefFarmAprService(fantomNetworkData.beets!.address), new ReliquaryFarmAprService(fantomNetworkData.beets!.address), new BeetswarsGaugeVotingAprService(), @@ -65,6 +65,10 @@ export const fantomNetworkConfig: NetworkConfig = { name: 'update-pool-apr', interval: (env.DEPLOYMENT_ENV as DeploymentEnv) === 'canary' ? every(6, 'minutes') : every(2, 'minutes'), }, + { + name: 'update-7-30-days-swap-apr', + interval: every(8, 'hours'), + }, { name: 'load-on-chain-data-for-pools-with-active-updates', interval: (env.DEPLOYMENT_ENV as DeploymentEnv) === 'canary' ? every(4, 'minutes') : every(1, 'minutes'), diff --git a/modules/network/fraxtal.ts b/modules/network/fraxtal.ts index 29be5aca8..1d7366138 100644 --- a/modules/network/fraxtal.ts +++ b/modules/network/fraxtal.ts @@ -2,7 +2,7 @@ import { ethers } from 'ethers'; import { DeploymentEnv, NetworkConfig } from './network-config-types'; import { tokenService } from '../token/token.service'; import { BoostedPoolAprService } from '../pool/lib/apr-data-sources/nested-pool-apr.service'; -import { SwapFeeFromEventsAprService } from '../pool/lib/apr-data-sources/'; +import { SwapFeeAprService } from '../pool/lib/apr-data-sources/'; import { GaugeAprService } from '../pool/lib/apr-data-sources/ve-bal-gauge-apr.service'; import { UserSyncGaugeBalanceService } from '../user/lib/user-sync-gauge-balance.service'; import { every } from '../../apps/scheduler/intervals'; @@ -22,7 +22,7 @@ export const fraxtalNetworkConfig: NetworkConfig = { poolAprServices: [ new YbTokensAprService(fraxtalNetworkData.ybAprConfig, fraxtalNetworkData.chain.prismaId), new BoostedPoolAprService(), - new SwapFeeFromEventsAprService(), + new SwapFeeAprService(), new GaugeAprService(tokenService, [fraxtalNetworkData.bal!.address]), ], userStakedBalanceServices: [new UserSyncGaugeBalanceService(), new UserSyncAuraBalanceService()], @@ -54,6 +54,10 @@ export const fraxtalNetworkConfig: NetworkConfig = { name: 'update-pool-apr', interval: (env.DEPLOYMENT_ENV as DeploymentEnv) === 'canary' ? every(6, 'minutes') : every(2, 'minutes'), }, + { + name: 'update-7-30-days-swap-apr', + interval: every(8, 'hours'), + }, { name: 'load-on-chain-data-for-pools-with-active-updates', interval: (env.DEPLOYMENT_ENV as DeploymentEnv) === 'canary' ? every(4, 'minutes') : every(1, 'minutes'), diff --git a/modules/network/gnosis.ts b/modules/network/gnosis.ts index 5227279ac..e0957dbab 100644 --- a/modules/network/gnosis.ts +++ b/modules/network/gnosis.ts @@ -2,7 +2,7 @@ import { ethers } from 'ethers'; import { DeploymentEnv, NetworkConfig, NetworkData } from './network-config-types'; import { tokenService } from '../token/token.service'; import { BoostedPoolAprService } from '../pool/lib/apr-data-sources/nested-pool-apr.service'; -import { SwapFeeFromEventsAprService } from '../pool/lib/apr-data-sources/'; +import { SwapFeeAprService } from '../pool/lib/apr-data-sources/'; import { GaugeAprService } from '../pool/lib/apr-data-sources/ve-bal-gauge-apr.service'; import { UserSyncGaugeBalanceService } from '../user/lib/user-sync-gauge-balance.service'; import { every } from '../../apps/scheduler/intervals'; @@ -22,7 +22,7 @@ export const gnosisNetworkConfig: NetworkConfig = { poolAprServices: [ new YbTokensAprService(gnosisNetworkData.ybAprConfig, gnosisNetworkData.chain.prismaId), new BoostedPoolAprService(), - new SwapFeeFromEventsAprService(), + new SwapFeeAprService(), new GaugeAprService(tokenService, [gnosisNetworkData.bal!.address]), ], userStakedBalanceServices: [new UserSyncGaugeBalanceService(), new UserSyncAuraBalanceService()], @@ -54,6 +54,10 @@ export const gnosisNetworkConfig: NetworkConfig = { name: 'update-pool-apr', interval: (env.DEPLOYMENT_ENV as DeploymentEnv) === 'canary' ? every(6, 'minutes') : every(2, 'minutes'), }, + { + name: 'update-7-30-days-swap-apr', + interval: every(8, 'hours'), + }, { name: 'load-on-chain-data-for-pools-with-active-updates', interval: (env.DEPLOYMENT_ENV as DeploymentEnv) === 'canary' ? every(4, 'minutes') : every(1, 'minutes'), diff --git a/modules/network/mainnet.ts b/modules/network/mainnet.ts index 1a6e0cf8d..9713fd9e3 100644 --- a/modules/network/mainnet.ts +++ b/modules/network/mainnet.ts @@ -4,7 +4,6 @@ import { tokenService } from '../token/token.service'; import { BoostedPoolAprService, SwapFeeAprService, - SwapFeeFromEventsAprService, GaugeAprService, YbTokensAprService, VeBalProtocolAprService, @@ -28,7 +27,7 @@ export const mainnetNetworkConfig: NetworkConfig = { poolAprServices: [ new YbTokensAprService(data.ybAprConfig, data.chain.prismaId), new BoostedPoolAprService(), - new SwapFeeFromEventsAprService(), + new SwapFeeAprService(), new GaugeAprService(tokenService, [data.bal!.address]), new VeBalProtocolAprService(data.rpcUrl), new VeBalVotingAprService(), @@ -63,10 +62,6 @@ export const mainnetNetworkConfig: NetworkConfig = { name: 'update-liquidity-for-active-pools', interval: (env.DEPLOYMENT_ENV as DeploymentEnv) === 'canary' ? every(6, 'minutes') : every(2, 'minutes'), }, - { - name: 'update-pool-apr', - interval: (env.DEPLOYMENT_ENV as DeploymentEnv) === 'canary' ? every(6, 'minutes') : every(2, 'minutes'), - }, { name: 'load-on-chain-data-for-pools-with-active-updates', interval: (env.DEPLOYMENT_ENV as DeploymentEnv) === 'canary' ? every(4, 'minutes') : every(1, 'minutes'), @@ -163,6 +158,15 @@ export const mainnetNetworkConfig: NetworkConfig = { name: 'sync-erc4626-reviews', interval: every(1, 'hours'), }, + // APRs + { + name: 'update-pool-apr', + interval: (env.DEPLOYMENT_ENV as DeploymentEnv) === 'canary' ? every(6, 'minutes') : every(2, 'minutes'), + }, + { + name: 'update-7-30-days-swap-apr', + interval: every(8, 'hours'), + }, { name: 'update-surplus-aprs', interval: (env.DEPLOYMENT_ENV as DeploymentEnv) === 'canary' ? every(10, 'minutes') : every(1, 'minutes'), diff --git a/modules/network/mode.ts b/modules/network/mode.ts index f12a9d7a6..aa7270f91 100644 --- a/modules/network/mode.ts +++ b/modules/network/mode.ts @@ -2,7 +2,7 @@ import { ethers } from 'ethers'; import { DeploymentEnv, NetworkConfig } from './network-config-types'; import { tokenService } from '../token/token.service'; import { BoostedPoolAprService } from '../pool/lib/apr-data-sources/nested-pool-apr.service'; -import { SwapFeeFromEventsAprService } from '../pool/lib/apr-data-sources'; +import { SwapFeeAprService } from '../pool/lib/apr-data-sources'; import { GaugeAprService } from '../pool/lib/apr-data-sources/ve-bal-gauge-apr.service'; import { UserSyncGaugeBalanceService } from '../user/lib/user-sync-gauge-balance.service'; import { every } from '../../apps/scheduler/intervals'; @@ -21,7 +21,7 @@ export const modeNetworkConfig: NetworkConfig = { poolAprServices: [ new YbTokensAprService(modeNetworkData.ybAprConfig, modeNetworkData.chain.prismaId), new BoostedPoolAprService(), - new SwapFeeFromEventsAprService(), + new SwapFeeAprService(), new GaugeAprService(tokenService, [modeNetworkData.bal!.address]), ], userStakedBalanceServices: [new UserSyncGaugeBalanceService()], @@ -53,6 +53,10 @@ export const modeNetworkConfig: NetworkConfig = { name: 'update-pool-apr', interval: (env.DEPLOYMENT_ENV as DeploymentEnv) === 'canary' ? every(6, 'minutes') : every(2, 'minutes'), }, + { + name: 'update-7-30-days-swap-apr', + interval: every(8, 'hours'), + }, { name: 'load-on-chain-data-for-pools-with-active-updates', interval: (env.DEPLOYMENT_ENV as DeploymentEnv) === 'canary' ? every(4, 'minutes') : every(1, 'minutes'), diff --git a/modules/network/optimism.ts b/modules/network/optimism.ts index 11701563e..aafd063a4 100644 --- a/modules/network/optimism.ts +++ b/modules/network/optimism.ts @@ -2,7 +2,7 @@ import { ethers } from 'ethers'; import { DeploymentEnv, NetworkConfig, NetworkData } from './network-config-types'; import { tokenService } from '../token/token.service'; import { BoostedPoolAprService } from '../pool/lib/apr-data-sources/nested-pool-apr.service'; -import { SwapFeeFromEventsAprService } from '../pool/lib/apr-data-sources/'; +import { SwapFeeAprService } from '../pool/lib/apr-data-sources/'; import { GaugeAprService } from '../pool/lib/apr-data-sources/ve-bal-gauge-apr.service'; import { UserSyncGaugeBalanceService } from '../user/lib/user-sync-gauge-balance.service'; import { every } from '../../apps/scheduler/intervals'; @@ -22,7 +22,7 @@ export const optimismNetworkConfig: NetworkConfig = { poolAprServices: [ new YbTokensAprService(optimismNetworkData.ybAprConfig, optimismNetworkData.chain.prismaId), new BoostedPoolAprService(), - new SwapFeeFromEventsAprService(), + new SwapFeeAprService(), new GaugeAprService(tokenService, [optimismNetworkData.beets!.address, optimismNetworkData.bal!.address]), ], userStakedBalanceServices: [new UserSyncGaugeBalanceService(), new UserSyncAuraBalanceService()], @@ -54,6 +54,10 @@ export const optimismNetworkConfig: NetworkConfig = { name: 'update-pool-apr', interval: (env.DEPLOYMENT_ENV as DeploymentEnv) === 'canary' ? every(6, 'minutes') : every(2, 'minutes'), }, + { + name: 'update-7-30-days-swap-apr', + interval: every(8, 'hours'), + }, { name: 'load-on-chain-data-for-pools-with-active-updates', interval: (env.DEPLOYMENT_ENV as DeploymentEnv) === 'canary' ? every(4, 'minutes') : every(1, 'minutes'), diff --git a/modules/network/polygon.ts b/modules/network/polygon.ts index 426cb44d4..a39637933 100644 --- a/modules/network/polygon.ts +++ b/modules/network/polygon.ts @@ -2,7 +2,7 @@ import { ethers } from 'ethers'; import { DeploymentEnv, NetworkConfig, NetworkData } from './network-config-types'; import { tokenService } from '../token/token.service'; import { BoostedPoolAprService } from '../pool/lib/apr-data-sources/nested-pool-apr.service'; -import { SwapFeeFromEventsAprService } from '../pool/lib/apr-data-sources/'; +import { SwapFeeAprService } from '../pool/lib/apr-data-sources/'; import { GaugeAprService } from '../pool/lib/apr-data-sources/ve-bal-gauge-apr.service'; import { UserSyncGaugeBalanceService } from '../user/lib/user-sync-gauge-balance.service'; import { every } from '../../apps/scheduler/intervals'; @@ -22,7 +22,7 @@ export const polygonNetworkConfig: NetworkConfig = { poolAprServices: [ new YbTokensAprService(polygonNetworkData.ybAprConfig, polygonNetworkData.chain.prismaId), new BoostedPoolAprService(), - new SwapFeeFromEventsAprService(), + new SwapFeeAprService(), new GaugeAprService(tokenService, [polygonNetworkData.bal!.address]), ], userStakedBalanceServices: [new UserSyncGaugeBalanceService(), new UserSyncAuraBalanceService()], @@ -54,6 +54,10 @@ export const polygonNetworkConfig: NetworkConfig = { name: 'update-pool-apr', interval: (env.DEPLOYMENT_ENV as DeploymentEnv) === 'canary' ? every(6, 'minutes') : every(2, 'minutes'), }, + { + name: 'update-7-30-days-swap-apr', + interval: every(8, 'hours'), + }, { name: 'load-on-chain-data-for-pools-with-active-updates', interval: (env.DEPLOYMENT_ENV as DeploymentEnv) === 'canary' ? every(4, 'minutes') : every(1, 'minutes'), diff --git a/modules/network/sepolia.ts b/modules/network/sepolia.ts index 9b0b1d97f..76453a19f 100644 --- a/modules/network/sepolia.ts +++ b/modules/network/sepolia.ts @@ -2,7 +2,7 @@ import { ethers } from 'ethers'; import { DeploymentEnv, NetworkConfig } from './network-config-types'; import { tokenService } from '../token/token.service'; import { BoostedPoolAprService } from '../pool/lib/apr-data-sources/nested-pool-apr.service'; -import { SwapFeeFromEventsAprService } from '../pool/lib/apr-data-sources/'; +import { SwapFeeAprService } from '../pool/lib/apr-data-sources/'; import { GaugeAprService } from '../pool/lib/apr-data-sources/ve-bal-gauge-apr.service'; import { UserSyncGaugeBalanceService } from '../user/lib/user-sync-gauge-balance.service'; import { every } from '../../apps/scheduler/intervals'; @@ -21,7 +21,7 @@ export const sepoliaNetworkConfig: NetworkConfig = { poolAprServices: [ new YbTokensAprService(sepoliaNetworkData.ybAprConfig, sepoliaNetworkData.chain.prismaId), new BoostedPoolAprService(), - new SwapFeeFromEventsAprService(), + new SwapFeeAprService(), new GaugeAprService(tokenService, [sepoliaNetworkData.bal!.address]), ], userStakedBalanceServices: [new UserSyncGaugeBalanceService()], @@ -53,6 +53,10 @@ export const sepoliaNetworkConfig: NetworkConfig = { name: 'update-pool-apr', interval: every(2, 'minutes'), }, + { + name: 'update-7-30-days-swap-apr', + interval: every(8, 'hours'), + }, { name: 'load-on-chain-data-for-pools-with-active-updates', interval: every(1, 'minutes'), diff --git a/modules/network/zkevm.ts b/modules/network/zkevm.ts index b674f0bde..53fbcaf5a 100644 --- a/modules/network/zkevm.ts +++ b/modules/network/zkevm.ts @@ -2,7 +2,7 @@ import { ethers } from 'ethers'; import { DeploymentEnv, NetworkConfig, NetworkData } from './network-config-types'; import { tokenService } from '../token/token.service'; import { BoostedPoolAprService } from '../pool/lib/apr-data-sources/nested-pool-apr.service'; -import { SwapFeeFromEventsAprService } from '../pool/lib/apr-data-sources/'; +import { SwapFeeAprService } from '../pool/lib/apr-data-sources/'; import { GaugeAprService } from '../pool/lib/apr-data-sources/ve-bal-gauge-apr.service'; import { UserSyncGaugeBalanceService } from '../user/lib/user-sync-gauge-balance.service'; import { every } from '../../apps/scheduler/intervals'; @@ -22,7 +22,7 @@ export const zkevmNetworkConfig: NetworkConfig = { poolAprServices: [ new YbTokensAprService(zkevmNetworkData.ybAprConfig, zkevmNetworkData.chain.prismaId), new BoostedPoolAprService(), - new SwapFeeFromEventsAprService(), + new SwapFeeAprService(), new GaugeAprService(tokenService, [zkevmNetworkData.bal!.address]), ], userStakedBalanceServices: [new UserSyncGaugeBalanceService(), new UserSyncAuraBalanceService()], @@ -54,6 +54,10 @@ export const zkevmNetworkConfig: NetworkConfig = { name: 'update-pool-apr', interval: (env.DEPLOYMENT_ENV as DeploymentEnv) === 'canary' ? every(6, 'minutes') : every(2, 'minutes'), }, + { + name: 'update-7-30-days-swap-apr', + interval: every(8, 'hours'), + }, { name: 'load-on-chain-data-for-pools-with-active-updates', interval: (env.DEPLOYMENT_ENV as DeploymentEnv) === 'canary' ? every(4, 'minutes') : every(1, 'minutes'), diff --git a/modules/pool/lib/apr-data-sources/swap-fee-apr-from-snapshots.service.ts b/modules/pool/lib/apr-data-sources/swap-fee-apr-from-snapshots.service.ts new file mode 100644 index 000000000..2fa6d1d24 --- /dev/null +++ b/modules/pool/lib/apr-data-sources/swap-fee-apr-from-snapshots.service.ts @@ -0,0 +1,148 @@ +import { PoolAprService } from '../../pool-types'; +import { PrismaPoolWithTokens } from '../../../../prisma/prisma-types'; +import { prisma } from '../../../../prisma/prisma-client'; +import { prismaBulkExecuteOperations } from '../../../../prisma/prisma-util'; +import { Chain, PrismaPoolType } from '@prisma/client'; +import { daysAgo, roundToMidnight } from '../../../common/time'; +import _ from 'lodash'; + +type PoolSwapFeeData = { + poolId: string; + chain: Chain; + fees_30d: number; + fees_7d: number; +}; + +const fetchSwapFeeData = async (chain: Chain) => { + const [snapshots30d, snapshots7d] = await Promise.all([ + prisma.prismaPoolSnapshot.findMany({ + where: { + chain, + timestamp: roundToMidnight(daysAgo(30)), + }, + select: { + poolId: true, + totalSwapFee: true, + }, + }), + prisma.prismaPoolSnapshot.findMany({ + where: { + chain, + timestamp: roundToMidnight(daysAgo(7)), + }, + select: { + poolId: true, + totalSwapFee: true, + }, + }), + ]); + + const poolIds = _.uniq([ + ...snapshots30d.map((snapshot) => snapshot.poolId), + ...snapshots7d.map((snapshot) => snapshot.poolId), + ]); + + const swapFeeData: PoolSwapFeeData[] = poolIds.map((poolId) => { + const snapshot30d = snapshots30d.find((s) => s.poolId === poolId); + const snapshot7d = snapshots7d.find((s) => s.poolId === poolId); + + return { + poolId, + chain, + fees_30d: snapshot30d ? snapshot30d.totalSwapFee : 0, + fees_7d: snapshot7d ? snapshot7d.totalSwapFee : 0, + }; + }); + + return swapFeeData; +}; + +const MAX_DB_INT = 9223372036854775807; + +export class SwapFeeFromSnapshotsAprService implements PoolAprService { + public getAprServiceName(): string { + return 'SwapFeeAprService'; + } + + public async updateAprForPools(pools: PrismaPoolWithTokens[]): Promise { + const chain = pools[0].chain; + + const typeMap = pools.reduce((acc, pool) => { + acc[pool.id] = pool.type; + return acc; + }, {} as Record); + + const dynamicData = await prisma.prismaPoolDynamicData.findMany({ + where: { chain, poolId: { in: pools.map((pool) => pool.id) } }, + }); + + // Fetch the swap fees for the last 30 days + const swapFeeData = await fetchSwapFeeData(chain); + + // Map the swap fee data to the pool id + const swapFeeDataMap = swapFeeData.reduce((acc, data) => { + acc[data.poolId] = data; + return acc; + }, {} as Record); + + const operations = dynamicData.flatMap((pool) => { + let apr_7d = 0; + let apr_30d = 0; + + if (pool.totalLiquidity > 0 && swapFeeDataMap[pool.poolId]) { + apr_7d = (swapFeeDataMap[pool.poolId].fees_7d * 365) / 7 / pool.totalLiquidity; + apr_30d = (swapFeeDataMap[pool.poolId].fees_30d * 365) / 30 / pool.totalLiquidity; + } + + let protocolFee = parseFloat(pool.protocolSwapFee); + + if (typeMap[pool.poolId] === 'GYROE') { + // Gyro has custom protocol fee structure + protocolFee = parseFloat(pool.protocolYieldFee || '0'); + } + if (pool.isInRecoveryMode || typeMap[pool.poolId] === 'LIQUIDITY_BOOTSTRAPPING') { + // pool does not collect any protocol fees + protocolFee = 0; + } + + apr_7d = apr_7d * (1 - protocolFee); + apr_30d = apr_30d * (1 - protocolFee); + + if (apr_7d > MAX_DB_INT) { + apr_7d = 0; + } + if (apr_30d > MAX_DB_INT) { + apr_30d = 0; + } + + return [ + prisma.prismaPoolAprItem.upsert({ + where: { id_chain: { id: `${pool.poolId}-swap-apr-7d`, chain } }, + create: { + id: `${pool.poolId}-swap-apr-7d`, + chain, + poolId: pool.poolId, + title: 'Swap fees APR (7d)', + apr: apr_7d, + type: 'SWAP_FEE_7D', + }, + update: { apr: apr_7d }, + }), + prisma.prismaPoolAprItem.upsert({ + where: { id_chain: { id: `${pool.poolId}-swap-apr-30d`, chain } }, + create: { + id: `${pool.poolId}-swap-apr-30d`, + chain, + poolId: pool.poolId, + title: 'Swap fees APR (30d)', + apr: apr_30d, + type: 'SWAP_FEE_30D', + }, + update: { apr: apr_30d }, + }), + ]; + }); + + await prismaBulkExecuteOperations(operations); + } +} diff --git a/modules/pool/lib/apr-data-sources/swap-fee-apr.service.ts b/modules/pool/lib/apr-data-sources/swap-fee-apr.service.ts index ea155fdba..ffc621d01 100644 --- a/modules/pool/lib/apr-data-sources/swap-fee-apr.service.ts +++ b/modules/pool/lib/apr-data-sources/swap-fee-apr.service.ts @@ -2,19 +2,20 @@ import { PoolAprService } from '../../pool-types'; import { PrismaPoolWithTokens } from '../../../../prisma/prisma-types'; import { prisma } from '../../../../prisma/prisma-client'; import { prismaBulkExecuteOperations } from '../../../../prisma/prisma-util'; -import { networkContext } from '../../../network/network-context.service'; const MAX_DB_INT = 9223372036854775807; + export class SwapFeeAprService implements PoolAprService { public getAprServiceName(): string { return 'SwapFeeAprService'; } public async updateAprForPools(pools: PrismaPoolWithTokens[]): Promise { + const chain = pools[0].chain; const operations: any[] = []; const poolsExpanded = await prisma.prismaPool.findMany({ - where: { chain: networkContext.chain, id: { in: pools.map((pool) => pool.id) } }, + where: { chain, id: { in: pools.map((pool) => pool.id) } }, include: { dynamicData: true, }, @@ -46,10 +47,10 @@ export class SwapFeeAprService implements PoolAprService { operations.push( prisma.prismaPoolAprItem.upsert({ - where: { id_chain: { id: `${pool.id}-swap-apr`, chain: networkContext.chain } }, + where: { id_chain: { id: `${pool.id}-swap-apr`, chain } }, create: { id: `${pool.id}-swap-apr`, - chain: networkContext.chain, + chain, poolId: pool.id, title: 'Swap fees APR', apr: userApr, @@ -57,6 +58,18 @@ export class SwapFeeAprService implements PoolAprService { }, update: { apr: userApr }, }), + prisma.prismaPoolAprItem.upsert({ + where: { id_chain: { id: `${pool.id}-swap-apr-24h`, chain } }, + create: { + id: `${pool.id}-swap-apr-24h`, + chain, + poolId: pool.id, + title: 'Swap fees APR (24h)', + apr: userApr, + type: 'SWAP_FEE_24H', + }, + update: { apr: userApr }, + }), ); } } diff --git a/tasks/index.ts b/tasks/index.ts index cc9d3c658..22e7fa8a7 100644 --- a/tasks/index.ts +++ b/tasks/index.ts @@ -125,6 +125,8 @@ async function run(job: string = process.argv[2], chainId: string = process.argv return 'OK'; } else if (job === 'sync-merkl') { return AprsController().syncMerkl(); + } else if (job === 'update-7-30-days-swap-apr') { + return AprsController().update7And30DaysSwapAprs(chain); } else if (job === 'sync-rate-provider-reviews') { return ContentController().syncRateProviderReviews(); } else if (job === 'sync-hook-reviews') {