diff --git a/modules/pool/lib/pool-creator.service.ts b/modules/pool/lib/pool-creator.service.ts index 3191eed58..b138ea03b 100644 --- a/modules/pool/lib/pool-creator.service.ts +++ b/modules/pool/lib/pool-creator.service.ts @@ -250,9 +250,21 @@ export class PoolCreatorService { return nestedPool.address === token.address; }); + let priceRateProvider; + if (pool.priceRateProviders) { + const data = pool.priceRateProviders.find( + (provider) => provider.token.address === token.address, + ); + priceRateProvider = data?.address; + } + return { id: token.id, address: token.address, + priceRateProvider, + exemptFromProtocolYieldFee: token.isExemptFromYieldProtocolFee + ? token.isExemptFromYieldProtocolFee + : false, nestedPoolId: nestedPool?.id, index: token.index || pool.tokensList.findIndex((address) => address === token.address), }; diff --git a/modules/pool/lib/pool-gql-loader.service.ts b/modules/pool/lib/pool-gql-loader.service.ts index 6c6cdcff9..2d5c1d2ce 100644 --- a/modules/pool/lib/pool-gql-loader.service.ts +++ b/modules/pool/lib/pool-gql-loader.service.ts @@ -1113,6 +1113,7 @@ export class PoolGqlLoaderService { ...poolToken.token, __typename: 'GqlPoolToken', priceRate: poolToken.dynamicData?.priceRate || '1.0', + priceRateProvider: poolToken.priceRateProvider, balance: poolToken.dynamicData?.balance || '0', index: poolToken.index, weight: poolToken.dynamicData?.weight, diff --git a/modules/pool/pool.gql b/modules/pool/pool.gql index c1136124d..83fa0b919 100644 --- a/modules/pool/pool.gql +++ b/modules/pool/pool.gql @@ -56,6 +56,8 @@ extend type Mutation { poolBlackListRemovePool(poolId: String!): String! poolDeletePool(poolId: String!): String! poolSyncAllPoolTypesVersions: String! + poolSyncPriceRateProviders: String! + poolSyncProtocolYieldFeeExemptions: String! poolInitOnChainDataForAllPools: String! } @@ -507,6 +509,7 @@ interface GqlPoolTokenBase { symbol: String! index: Int! priceRate: BigDecimal! + priceRateProvider: String weight: BigDecimal #the total balance in the pool, regardless of nesting totalBalance: BigDecimal! @@ -523,6 +526,7 @@ type GqlPoolToken implements GqlPoolTokenBase { #dynamic data balance: BigDecimal! priceRate: BigDecimal! + priceRateProvider: String weight: BigDecimal #the total balance in the pool, regardless of nesting totalBalance: BigDecimal! @@ -537,6 +541,7 @@ type GqlPoolTokenLinear implements GqlPoolTokenBase { symbol: String! index: Int! priceRate: BigDecimal! + priceRateProvider: String weight: BigDecimal pool: GqlPoolLinearNested! @@ -557,6 +562,7 @@ type GqlPoolTokenComposableStable implements GqlPoolTokenBase { symbol: String! index: Int! priceRate: BigDecimal! + priceRateProvider: String weight: BigDecimal #the total balance in the pool, regardless of nesting totalBalance: BigDecimal! @@ -669,21 +675,6 @@ enum GqlPoolFilterCategory { BLACK_LISTED } -# enum GqlPoolFilterType { -# WEIGHTED -# STABLE -# META_STABLE -# PHANTOM_STABLE -# ELEMENT -# LINEAR -# UNKNOWN -# LIQUIDITY_BOOTSTRAPPING -# INVESTMENT -# GYRO -# GYRO3 -# GYROE -# } - type GqlPoolTokenExpanded { id: ID! address: String! diff --git a/modules/pool/pool.prisma b/modules/pool/pool.prisma index c181de71a..9b16b15c2 100644 --- a/modules/pool/pool.prisma +++ b/modules/pool/pool.prisma @@ -200,17 +200,20 @@ model PrismaPoolLinearDynamicData { model PrismaPoolToken { @@id([id, chain]) - id String - poolId String - pool PrismaPool @relation(fields:[poolId, chain], references: [id, chain]) - chain Chain + id String + poolId String + pool PrismaPool @relation(fields:[poolId, chain], references: [id, chain]) + chain Chain - address String - token PrismaToken @relation(fields:[address, chain], references: [address, chain]) - index Int + address String + token PrismaToken @relation(fields:[address, chain], references: [address, chain]) + index Int - nestedPoolId String? - nestedPool PrismaPool? @relation(name: "PoolNestedInToken", fields:[nestedPoolId, chain], references: [id, chain]) + nestedPoolId String? + nestedPool PrismaPool? @relation(name: "PoolNestedInToken", fields:[nestedPoolId, chain], references: [id, chain]) + + priceRateProvider String? + exemptFromProtocolYieldFee Boolean @default(false) dynamicData PrismaPoolTokenDynamicData? } diff --git a/modules/pool/pool.resolvers.ts b/modules/pool/pool.resolvers.ts index 45a36ee00..90fcebff2 100644 --- a/modules/pool/pool.resolvers.ts +++ b/modules/pool/pool.resolvers.ts @@ -321,6 +321,20 @@ const balancerResolvers: Resolvers = { await poolService.syncPoolTypeAndVersionForAllPools(); + return 'success'; + }, + poolSyncPriceRateProviders: async (parent, {}, context) => { + isAdminRoute(context); + + await poolService.syncPriceRateProvidersForAllPools(); + + return 'success'; + }, + poolSyncProtocolYieldFeeExemptions: async (parent, {}, context) => { + isAdminRoute(context); + + await poolService.syncProtocolYieldFeeExemptionsForAllPools(); + return 'success'; }, }, diff --git a/modules/pool/pool.service.ts b/modules/pool/pool.service.ts index 83928c6cf..a19068e6c 100644 --- a/modules/pool/pool.service.ts +++ b/modules/pool/pool.service.ts @@ -361,6 +361,58 @@ export class PoolService { await this.poolCreatorService.updatePoolTypesAndVersionForAllPools(); } + public async syncProtocolYieldFeeExemptionsForAllPools() { + const subgraphPools = await this.balancerSubgraphService.getAllPools({}, false); + for (const subgraphPool of subgraphPools) { + const poolTokens = subgraphPool.tokens || []; + for (let i = 0; i < poolTokens.length; i++) { + const token = poolTokens[i]; + try { + await prisma.prismaPoolToken.update({ + where: { id_chain: { id: token.id, chain: networkContext.chain } }, + data: { + exemptFromProtocolYieldFee: token.isExemptFromYieldProtocolFee + ? token.isExemptFromYieldProtocolFee + : false, + }, + }); + } catch (e) { + console.error('Failed to update token ', token.id, ' error is: ', e); + } + } + } + } + + public async syncPriceRateProvidersForAllPools() { + const subgraphPools = await this.balancerSubgraphService.getAllPools({}, false); + for (const subgraphPool of subgraphPools) { + if (!subgraphPool.priceRateProviders || !subgraphPool.priceRateProviders.length) continue; + + const poolTokens = subgraphPool.tokens || []; + for (let i = 0; i < poolTokens.length; i++) { + const token = poolTokens[i]; + + let priceRateProvider; + const data = subgraphPool.priceRateProviders.find( + (provider) => provider.token.address === token.address, + ); + priceRateProvider = data?.address; + if (!priceRateProvider) continue; + + try { + await prisma.prismaPoolToken.update({ + where: { id_chain: { id: token.id, chain: networkContext.chain } }, + data: { + priceRateProvider, + }, + }); + } catch (e) { + console.error('Failed to update token ', token.id, ' error is: ', e); + } + } + } + } + public async addToBlackList(poolId: string) { const category = await prisma.prismaPoolCategory.findFirst({ where: { poolId, chain: this.chain, category: 'BLACK_LISTED' }, diff --git a/modules/subgraphs/balancer-subgraph/balancer-subgraph-queries.graphql b/modules/subgraphs/balancer-subgraph/balancer-subgraph-queries.graphql index bdf1a2171..5469dc094 100644 --- a/modules/subgraphs/balancer-subgraph/balancer-subgraph-queries.graphql +++ b/modules/subgraphs/balancer-subgraph/balancer-subgraph-queries.graphql @@ -198,6 +198,12 @@ fragment BalancerPool on Pool { w z dSq + priceRateProviders { + address + token { + address + } + } tokens { ...BalancerPoolToken @@ -213,6 +219,7 @@ fragment BalancerPoolToken on PoolToken { balance weight priceRate + isExemptFromYieldProtocolFee index token { latestFXPrice diff --git a/prisma/migrations/20231220162356_add_price_rate_and_exempt/migration.sql b/prisma/migrations/20231220162356_add_price_rate_and_exempt/migration.sql new file mode 100644 index 000000000..aa4f9a5a5 --- /dev/null +++ b/prisma/migrations/20231220162356_add_price_rate_and_exempt/migration.sql @@ -0,0 +1,3 @@ +-- AlterTable +ALTER TABLE "PrismaPoolToken" ADD COLUMN "exemptFromProtocolYieldFee" BOOLEAN NOT NULL DEFAULT false, +ADD COLUMN "priceRateProvider" TEXT; diff --git a/prisma/schema.prisma b/prisma/schema.prisma index db064d830..186f5c992 100644 --- a/prisma/schema.prisma +++ b/prisma/schema.prisma @@ -246,17 +246,20 @@ model PrismaPoolLinearDynamicData { model PrismaPoolToken { @@id([id, chain]) - id String - poolId String - pool PrismaPool @relation(fields:[poolId, chain], references: [id, chain]) - chain Chain + id String + poolId String + pool PrismaPool @relation(fields:[poolId, chain], references: [id, chain]) + chain Chain - address String - token PrismaToken @relation(fields:[address, chain], references: [address, chain]) - index Int + address String + token PrismaToken @relation(fields:[address, chain], references: [address, chain]) + index Int - nestedPoolId String? - nestedPool PrismaPool? @relation(name: "PoolNestedInToken", fields:[nestedPoolId, chain], references: [id, chain]) + nestedPoolId String? + nestedPool PrismaPool? @relation(name: "PoolNestedInToken", fields:[nestedPoolId, chain], references: [id, chain]) + + priceRateProvider String? + exemptFromProtocolYieldFee Boolean @default(false) dynamicData PrismaPoolTokenDynamicData? }