From bd6ae084f2c5a9eda2063f3aaec29a5e4321ddb4 Mon Sep 17 00:00:00 2001 From: mendesfabio Date: Wed, 25 Oct 2023 09:45:47 -0300 Subject: [PATCH 01/11] add featured pools --- modules/pool/lib/pool-gql-loader.service.ts | 16 ++++++++++++++++ modules/pool/lib/pool-metadata.service.ts | 18 ++++++++++++++++++ modules/pool/pool.gql | 8 ++++++++ modules/pool/pool.resolvers.ts | 3 +++ modules/pool/pool.service.ts | 5 +++++ 5 files changed, 50 insertions(+) create mode 100644 modules/pool/lib/pool-metadata.service.ts diff --git a/modules/pool/lib/pool-gql-loader.service.ts b/modules/pool/lib/pool-gql-loader.service.ts index 302785ba7..6f77e59e4 100644 --- a/modules/pool/lib/pool-gql-loader.service.ts +++ b/modules/pool/lib/pool-gql-loader.service.ts @@ -11,6 +11,7 @@ import { import { GqlBalancePoolAprItem, GqlBalancePoolAprSubItem, + GqlFeaturedPool, GqlPoolDynamicData, GqlPoolFeaturedPoolGroup, GqlPoolInvestConfig, @@ -38,6 +39,7 @@ import { isWeightedPoolV2 } from './pool-utils'; import { oldBnum } from '../../big-number/old-big-number'; import { networkContext } from '../../network/network-context.service'; import { fixedNumber } from '../../view-helpers/fixed-number'; +import { poolMetadataService } from './pool-metadata.service'; export class PoolGqlLoaderService { public async getPool(id: string): Promise { @@ -66,6 +68,20 @@ export class PoolGqlLoaderService { return pools.map((pool) => this.mapToMinimalGqlPool(pool)); } + public async getFeaturedPools(): Promise { + const poolsMetadata = await poolMetadataService.getPoolsMetadata(); + const poolIds = poolsMetadata.map((pool) => pool.id); + + const pools = await this.getPools({ where: { idIn: poolIds } }); + + return poolsMetadata.map(({ id, imageUrl, primary }) => ({ + id, + imageUrl, + primary: Boolean(primary), + pool: pools.find((pool) => pool.id === id), + })) as GqlFeaturedPool[]; + } + public async getLinearPools(): Promise { const pools = await prisma.prismaPool.findMany({ where: { type: 'LINEAR', chain: networkContext.chain }, diff --git a/modules/pool/lib/pool-metadata.service.ts b/modules/pool/lib/pool-metadata.service.ts new file mode 100644 index 000000000..7e8d8b788 --- /dev/null +++ b/modules/pool/lib/pool-metadata.service.ts @@ -0,0 +1,18 @@ +import axios from "axios"; + +const POOLS_METADATA_URL = "https://raw.githubusercontent.com/balancer/metadata/main/pools/featured.json"; + +interface PoolMetadata { + id: string; + imageUrl: string; + primary: boolean; +} + +export class PoolMetadataService { + async getPoolsMetadata(): Promise { + const { data } = await axios.get(POOLS_METADATA_URL); + return data; + } +} + +export const poolMetadataService = new PoolMetadataService(); diff --git a/modules/pool/pool.gql b/modules/pool/pool.gql index 2d08af860..8bde3c41d 100644 --- a/modules/pool/pool.gql +++ b/modules/pool/pool.gql @@ -25,6 +25,7 @@ extend type Query { poolGetSnapshots(id: String!, range: GqlPoolSnapshotDataRange!): [GqlPoolSnapshot!]! poolGetAllPoolsSnapshots(range: GqlPoolSnapshotDataRange!): [GqlPoolSnapshot!]! poolGetLinearPools: [GqlPoolLinear!]! + poolGetFeaturedPools: [GqlFeaturedPool!]! } extend type Mutation { @@ -95,6 +96,13 @@ enum GqlPoolMinimalType { FX } +type GqlFeaturedPool { + id: ID! + primary: Boolean! + imageUrl: String! + pool: GqlPoolMinimal! +} + interface GqlPoolBase { #fields that never change after creation id: ID! diff --git a/modules/pool/pool.resolvers.ts b/modules/pool/pool.resolvers.ts index d958ca087..6d4f5effe 100644 --- a/modules/pool/pool.resolvers.ts +++ b/modules/pool/pool.resolvers.ts @@ -12,6 +12,9 @@ const balancerResolvers: Resolvers = { poolGetPools: async (parent, args, context) => { return poolService.getGqlPools(args); }, + poolGetFeaturedPools: async (parent, args, context) => { + return poolService.getGqlFeaturedPools(); + }, poolGetPoolsCount: async (parent, args, context) => { return poolService.getPoolsCount(args); }, diff --git a/modules/pool/pool.service.ts b/modules/pool/pool.service.ts index 852a03bc0..4d0a96f5f 100644 --- a/modules/pool/pool.service.ts +++ b/modules/pool/pool.service.ts @@ -4,6 +4,7 @@ import { Cache } from 'memory-cache'; import moment from 'moment-timezone'; import { prisma } from '../../prisma/prisma-client'; import { + GqlFeaturedPool, GqlPoolBatchSwap, GqlPoolFeaturedPoolGroup, GqlPoolJoinExit, @@ -69,6 +70,10 @@ export class PoolService { return this.poolGqlLoaderService.getPools(args); } + public async getGqlFeaturedPools(): Promise { + return this.poolGqlLoaderService.getFeaturedPools(); + } + public async getGqlLinearPools(): Promise { return this.poolGqlLoaderService.getLinearPools(); } From 3e769259ff120480b5817d8deeb362ba175e226a Mon Sep 17 00:00:00 2001 From: mendesfabio Date: Tue, 7 Nov 2023 09:31:54 -0300 Subject: [PATCH 02/11] integrate featured pools into content service --- modules/content/content-types.ts | 7 +++++++ modules/content/github-content.service.ts | 8 +++++++- modules/content/sanity-content.service.ts | 6 +++++- modules/pool/lib/pool-metadata.service.ts | 18 ------------------ 4 files changed, 19 insertions(+), 20 deletions(-) delete mode 100644 modules/pool/lib/pool-metadata.service.ts diff --git a/modules/content/content-types.ts b/modules/content/content-types.ts index ba72f5d8e..66a1ffa01 100644 --- a/modules/content/content-types.ts +++ b/modules/content/content-types.ts @@ -36,9 +36,16 @@ export interface HomeScreenNewsItem { image?: string; } +export interface FeaturedPoolMetadata { + id: string; + imageUrl: string; + primary: boolean; +} + export interface ContentService { syncTokenContentData(): Promise; syncPoolContentData(): Promise; getFeaturedPoolGroups(): Promise; + getBalancerFeaturedPools(): Promise; getNewsItems(): Promise; } diff --git a/modules/content/github-content.service.ts b/modules/content/github-content.service.ts index 85dec7166..d1d9987a5 100644 --- a/modules/content/github-content.service.ts +++ b/modules/content/github-content.service.ts @@ -3,7 +3,9 @@ import { Prisma } from '@prisma/client'; import axios from 'axios'; import { prisma } from '../../prisma/prisma-client'; import { networkContext } from '../network/network-context.service'; -import { ContentService, HomeScreenFeaturedPoolGroup, HomeScreenNewsItem } from './content-types'; +import { ContentService, FeaturedPoolMetadata, HomeScreenFeaturedPoolGroup, HomeScreenNewsItem } from './content-types'; + +const POOLS_METADATA_URL = "https://raw.githubusercontent.com/balancer/metadata/main/pools/featured.json"; const TOKEN_LIST_URL = 'https://raw.githubusercontent.com/balancer/tokenlists/main/generated/balancer.tokenlist.json'; @@ -161,6 +163,10 @@ export class GithubContentService implements ContentService { async getFeaturedPoolGroups(): Promise { return []; } + async getBalancerFeaturedPools(): Promise { + const { data } = await axios.get(POOLS_METADATA_URL); + return data; + } async getNewsItems(): Promise { return []; } diff --git a/modules/content/sanity-content.service.ts b/modules/content/sanity-content.service.ts index 00d6dd8b0..a47eaf39d 100644 --- a/modules/content/sanity-content.service.ts +++ b/modules/content/sanity-content.service.ts @@ -2,7 +2,7 @@ import { isSameAddress } from '@balancer-labs/sdk'; import { Prisma, PrismaPoolCategoryType } from '@prisma/client'; import { prisma } from '../../prisma/prisma-client'; import { networkContext } from '../network/network-context.service'; -import { ConfigHomeScreen, ContentService, HomeScreenFeaturedPoolGroup, HomeScreenNewsItem } from './content-types'; +import { ConfigHomeScreen, ContentService, FeaturedPoolMetadata, HomeScreenFeaturedPoolGroup, HomeScreenNewsItem } from './content-types'; import SanityClient from '@sanity/client'; import { env } from '../../app/env'; @@ -329,6 +329,10 @@ export class SanityContentService implements ContentService { } throw new Error(`No news items found for chain id ${networkContext.chainId}`); } + + public async getBalancerFeaturedPools(): Promise { + return []; + } } export function getSanityClient() { diff --git a/modules/pool/lib/pool-metadata.service.ts b/modules/pool/lib/pool-metadata.service.ts deleted file mode 100644 index 7e8d8b788..000000000 --- a/modules/pool/lib/pool-metadata.service.ts +++ /dev/null @@ -1,18 +0,0 @@ -import axios from "axios"; - -const POOLS_METADATA_URL = "https://raw.githubusercontent.com/balancer/metadata/main/pools/featured.json"; - -interface PoolMetadata { - id: string; - imageUrl: string; - primary: boolean; -} - -export class PoolMetadataService { - async getPoolsMetadata(): Promise { - const { data } = await axios.get(POOLS_METADATA_URL); - return data; - } -} - -export const poolMetadataService = new PoolMetadataService(); From 9b5f0f6b5f793991178215c93789c651c7996d7c Mon Sep 17 00:00:00 2001 From: mendesfabio Date: Tue, 7 Nov 2023 09:32:12 -0300 Subject: [PATCH 03/11] use content service and load pools from db --- modules/pool/lib/pool-gql-loader.service.ts | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/modules/pool/lib/pool-gql-loader.service.ts b/modules/pool/lib/pool-gql-loader.service.ts index 6f77e59e4..5411808d6 100644 --- a/modules/pool/lib/pool-gql-loader.service.ts +++ b/modules/pool/lib/pool-gql-loader.service.ts @@ -39,7 +39,6 @@ import { isWeightedPoolV2 } from './pool-utils'; import { oldBnum } from '../../big-number/old-big-number'; import { networkContext } from '../../network/network-context.service'; import { fixedNumber } from '../../view-helpers/fixed-number'; -import { poolMetadataService } from './pool-metadata.service'; export class PoolGqlLoaderService { public async getPool(id: string): Promise { @@ -69,11 +68,13 @@ export class PoolGqlLoaderService { } public async getFeaturedPools(): Promise { - const poolsMetadata = await poolMetadataService.getPoolsMetadata(); + const poolsMetadata = await networkContext.config.contentService.getBalancerFeaturedPools(); const poolIds = poolsMetadata.map((pool) => pool.id); - const pools = await this.getPools({ where: { idIn: poolIds } }); - + const pools = await prisma.prismaPool.findMany({ + where: { id: {in: poolIds }, chain: networkContext.chain }, + }); + return poolsMetadata.map(({ id, imageUrl, primary }) => ({ id, imageUrl, From 68f8abae1697ef355305016cb10cccb29daec84a Mon Sep 17 00:00:00 2001 From: mendesfabio Date: Wed, 29 Nov 2023 08:45:42 -0300 Subject: [PATCH 04/11] reuse featured pool groups logic --- modules/content/content-types.ts | 7 ------- modules/content/github-content.service.ts | 19 ++++++++++++++----- modules/content/sanity-content.service.ts | 6 +----- modules/pool/lib/pool-gql-loader.service.ts | 16 ---------------- modules/pool/pool.gql | 3 +-- modules/pool/pool.resolvers.ts | 3 --- modules/pool/pool.service.ts | 5 ----- 7 files changed, 16 insertions(+), 43 deletions(-) diff --git a/modules/content/content-types.ts b/modules/content/content-types.ts index 66a1ffa01..ba72f5d8e 100644 --- a/modules/content/content-types.ts +++ b/modules/content/content-types.ts @@ -36,16 +36,9 @@ export interface HomeScreenNewsItem { image?: string; } -export interface FeaturedPoolMetadata { - id: string; - imageUrl: string; - primary: boolean; -} - export interface ContentService { syncTokenContentData(): Promise; syncPoolContentData(): Promise; getFeaturedPoolGroups(): Promise; - getBalancerFeaturedPools(): Promise; getNewsItems(): Promise; } diff --git a/modules/content/github-content.service.ts b/modules/content/github-content.service.ts index d1d9987a5..7b5b6c008 100644 --- a/modules/content/github-content.service.ts +++ b/modules/content/github-content.service.ts @@ -3,12 +3,17 @@ import { Prisma } from '@prisma/client'; import axios from 'axios'; import { prisma } from '../../prisma/prisma-client'; import { networkContext } from '../network/network-context.service'; -import { ContentService, FeaturedPoolMetadata, HomeScreenFeaturedPoolGroup, HomeScreenNewsItem } from './content-types'; +import { ContentService, HomeScreenFeaturedPoolGroup, HomeScreenNewsItem } from './content-types'; const POOLS_METADATA_URL = "https://raw.githubusercontent.com/balancer/metadata/main/pools/featured.json"; const TOKEN_LIST_URL = 'https://raw.githubusercontent.com/balancer/tokenlists/main/generated/balancer.tokenlist.json'; +interface FeaturedPoolMetadata { + id: string; + imageUrl: string; + primary: boolean; +} interface WhitelistedTokenList { name: string; timestamp: string; @@ -161,11 +166,15 @@ export class GithubContentService implements ContentService { } async syncPoolContentData(): Promise {} async getFeaturedPoolGroups(): Promise { - return []; - } - async getBalancerFeaturedPools(): Promise { const { data } = await axios.get(POOLS_METADATA_URL); - return data; + return data.map(({ id, imageUrl, primary }) => ({ + _key: '', + _type: '', + id, + items: [], + icon: imageUrl, + title: '' + })) as HomeScreenFeaturedPoolGroup[]; } async getNewsItems(): Promise { return []; diff --git a/modules/content/sanity-content.service.ts b/modules/content/sanity-content.service.ts index a47eaf39d..00d6dd8b0 100644 --- a/modules/content/sanity-content.service.ts +++ b/modules/content/sanity-content.service.ts @@ -2,7 +2,7 @@ import { isSameAddress } from '@balancer-labs/sdk'; import { Prisma, PrismaPoolCategoryType } from '@prisma/client'; import { prisma } from '../../prisma/prisma-client'; import { networkContext } from '../network/network-context.service'; -import { ConfigHomeScreen, ContentService, FeaturedPoolMetadata, HomeScreenFeaturedPoolGroup, HomeScreenNewsItem } from './content-types'; +import { ConfigHomeScreen, ContentService, HomeScreenFeaturedPoolGroup, HomeScreenNewsItem } from './content-types'; import SanityClient from '@sanity/client'; import { env } from '../../app/env'; @@ -329,10 +329,6 @@ export class SanityContentService implements ContentService { } throw new Error(`No news items found for chain id ${networkContext.chainId}`); } - - public async getBalancerFeaturedPools(): Promise { - return []; - } } export function getSanityClient() { diff --git a/modules/pool/lib/pool-gql-loader.service.ts b/modules/pool/lib/pool-gql-loader.service.ts index 5411808d6..d0d4f363d 100644 --- a/modules/pool/lib/pool-gql-loader.service.ts +++ b/modules/pool/lib/pool-gql-loader.service.ts @@ -67,22 +67,6 @@ export class PoolGqlLoaderService { return pools.map((pool) => this.mapToMinimalGqlPool(pool)); } - public async getFeaturedPools(): Promise { - const poolsMetadata = await networkContext.config.contentService.getBalancerFeaturedPools(); - const poolIds = poolsMetadata.map((pool) => pool.id); - - const pools = await prisma.prismaPool.findMany({ - where: { id: {in: poolIds }, chain: networkContext.chain }, - }); - - return poolsMetadata.map(({ id, imageUrl, primary }) => ({ - id, - imageUrl, - primary: Boolean(primary), - pool: pools.find((pool) => pool.id === id), - })) as GqlFeaturedPool[]; - } - public async getLinearPools(): Promise { const pools = await prisma.prismaPool.findMany({ where: { type: 'LINEAR', chain: networkContext.chain }, diff --git a/modules/pool/pool.gql b/modules/pool/pool.gql index 8bde3c41d..30b7e4740 100644 --- a/modules/pool/pool.gql +++ b/modules/pool/pool.gql @@ -21,11 +21,10 @@ extend type Query { poolGetBatchSwaps(first: Int, skip: Int, where: GqlPoolSwapFilter): [GqlPoolBatchSwap!]! poolGetJoinExits(first: Int, skip: Int, where: GqlPoolJoinExitFilter): [GqlPoolJoinExit!]! poolGetUserSwapVolume(first: Int, skip: Int, where: GqlUserSwapVolumeFilter): [GqlPoolUserSwapVolume!]! - poolGetFeaturedPoolGroups: [GqlPoolFeaturedPoolGroup!]! + poolGetFeaturedPoolGroups(chains: [GqlChain!]!): [GqlPoolFeaturedPoolGroup!]! poolGetSnapshots(id: String!, range: GqlPoolSnapshotDataRange!): [GqlPoolSnapshot!]! poolGetAllPoolsSnapshots(range: GqlPoolSnapshotDataRange!): [GqlPoolSnapshot!]! poolGetLinearPools: [GqlPoolLinear!]! - poolGetFeaturedPools: [GqlFeaturedPool!]! } extend type Mutation { diff --git a/modules/pool/pool.resolvers.ts b/modules/pool/pool.resolvers.ts index 6d4f5effe..d958ca087 100644 --- a/modules/pool/pool.resolvers.ts +++ b/modules/pool/pool.resolvers.ts @@ -12,9 +12,6 @@ const balancerResolvers: Resolvers = { poolGetPools: async (parent, args, context) => { return poolService.getGqlPools(args); }, - poolGetFeaturedPools: async (parent, args, context) => { - return poolService.getGqlFeaturedPools(); - }, poolGetPoolsCount: async (parent, args, context) => { return poolService.getPoolsCount(args); }, diff --git a/modules/pool/pool.service.ts b/modules/pool/pool.service.ts index 4d0a96f5f..852a03bc0 100644 --- a/modules/pool/pool.service.ts +++ b/modules/pool/pool.service.ts @@ -4,7 +4,6 @@ import { Cache } from 'memory-cache'; import moment from 'moment-timezone'; import { prisma } from '../../prisma/prisma-client'; import { - GqlFeaturedPool, GqlPoolBatchSwap, GqlPoolFeaturedPoolGroup, GqlPoolJoinExit, @@ -70,10 +69,6 @@ export class PoolService { return this.poolGqlLoaderService.getPools(args); } - public async getGqlFeaturedPools(): Promise { - return this.poolGqlLoaderService.getFeaturedPools(); - } - public async getGqlLinearPools(): Promise { return this.poolGqlLoaderService.getLinearPools(); } From e23ec9f7ba6b7b159a266cd1bdf49355d1eec67a Mon Sep 17 00:00:00 2001 From: mendesfabio Date: Wed, 29 Nov 2023 08:51:11 -0300 Subject: [PATCH 05/11] remove unused code --- modules/pool/pool.gql | 8 -------- 1 file changed, 8 deletions(-) diff --git a/modules/pool/pool.gql b/modules/pool/pool.gql index 38a2b16a5..e0d43a86f 100644 --- a/modules/pool/pool.gql +++ b/modules/pool/pool.gql @@ -19,7 +19,6 @@ extend type Query { poolGetSwaps(first: Int, skip: Int, where: GqlPoolSwapFilter): [GqlPoolSwap!]! poolGetBatchSwaps(first: Int, skip: Int, where: GqlPoolSwapFilter): [GqlPoolBatchSwap!]! poolGetJoinExits(first: Int, skip: Int, where: GqlPoolJoinExitFilter): [GqlPoolJoinExit!]! - poolGetUserSwapVolume(first: Int, skip: Int, where: GqlUserSwapVolumeFilter): [GqlPoolUserSwapVolume!]! poolGetFeaturedPoolGroups(chains: [GqlChain!]!): [GqlPoolFeaturedPoolGroup!]! poolGetSnapshots(id: String!, chain: GqlChain, range: GqlPoolSnapshotDataRange!): [GqlPoolSnapshot!]! poolGetAllPoolsSnapshots(chains: [GqlChain!], range: GqlPoolSnapshotDataRange!): [GqlPoolSnapshot!]! @@ -94,13 +93,6 @@ enum GqlPoolMinimalType { FX } -type GqlFeaturedPool { - id: ID! - primary: Boolean! - imageUrl: String! - pool: GqlPoolMinimal! -} - interface GqlPoolBase { #fields that never change after creation id: ID! From f9dc003a97a1429a7b7c6d48d742c286e341321a Mon Sep 17 00:00:00 2001 From: mendesfabio Date: Wed, 29 Nov 2023 09:04:21 -0300 Subject: [PATCH 06/11] add chains args to functions --- modules/pool/pool.resolvers.ts | 4 ++-- modules/pool/pool.service.ts | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/modules/pool/pool.resolvers.ts b/modules/pool/pool.resolvers.ts index e9fe7431b..019c612e6 100644 --- a/modules/pool/pool.resolvers.ts +++ b/modules/pool/pool.resolvers.ts @@ -49,8 +49,8 @@ const balancerResolvers: Resolvers = { } return poolService.getPoolJoinExits(args); }, - poolGetFeaturedPoolGroups: async (parent, args, context) => { - return poolService.getFeaturedPoolGroups(); + poolGetFeaturedPoolGroups: async (parent, { chains }, context) => { + return poolService.getFeaturedPoolGroups(chains); }, poolGetSnapshots: async (parent, { id, chain, range }, context) => { const currentChain = headerChain(); diff --git a/modules/pool/pool.service.ts b/modules/pool/pool.service.ts index ae54c3e2b..7777febfc 100644 --- a/modules/pool/pool.service.ts +++ b/modules/pool/pool.service.ts @@ -114,7 +114,7 @@ export class PoolService { return this.poolSwapService.getJoinExits(args); } - public async getFeaturedPoolGroups(): Promise { + public async getFeaturedPoolGroups(chains: Chain[]): Promise { const cached: GqlPoolFeaturedPoolGroup[] = await this.cache.get( `${FEATURED_POOL_GROUPS_CACHE_KEY}:${this.chainId}`, ); From c220b5140ba94225f4ff31fee82f769dc883fbe2 Mon Sep 17 00:00:00 2001 From: mendesfabio Date: Wed, 20 Dec 2023 18:00:30 -0300 Subject: [PATCH 07/11] add primary attribute and filter by chain ids --- modules/content/content-types.ts | 3 ++- modules/content/github-content.service.ts | 21 ++++++++++++++------- modules/content/sanity-content.service.ts | 5 +++-- modules/context/header-chain.ts | 12 ++++++++++++ modules/pool/lib/pool-gql-loader.service.ts | 6 ++++-- modules/pool/pool.gql | 1 + 6 files changed, 36 insertions(+), 12 deletions(-) diff --git a/modules/content/content-types.ts b/modules/content/content-types.ts index ba72f5d8e..bf6da0e42 100644 --- a/modules/content/content-types.ts +++ b/modules/content/content-types.ts @@ -10,6 +10,7 @@ export interface HomeScreenFeaturedPoolGroup { id: string; items: (HomeScreenFeaturedPoolGroupItemPoolId | HomeScreenFeaturedPoolGroupItemExternalLink)[]; title: string; + primary: boolean; } interface HomeScreenFeaturedPoolGroupItemPoolId { @@ -39,6 +40,6 @@ export interface HomeScreenNewsItem { export interface ContentService { syncTokenContentData(): Promise; syncPoolContentData(): Promise; - getFeaturedPoolGroups(): Promise; + getFeaturedPoolGroups(chainIds: string[]): Promise; getNewsItems(): Promise; } diff --git a/modules/content/github-content.service.ts b/modules/content/github-content.service.ts index 7b5b6c008..50e8a0af0 100644 --- a/modules/content/github-content.service.ts +++ b/modules/content/github-content.service.ts @@ -5,7 +5,7 @@ import { prisma } from '../../prisma/prisma-client'; import { networkContext } from '../network/network-context.service'; import { ContentService, HomeScreenFeaturedPoolGroup, HomeScreenNewsItem } from './content-types'; -const POOLS_METADATA_URL = "https://raw.githubusercontent.com/balancer/metadata/main/pools/featured.json"; +const POOLS_METADATA_URL = "https://raw.githubusercontent.com/balancer/metadata/chains/pools/featured.json"; const TOKEN_LIST_URL = 'https://raw.githubusercontent.com/balancer/tokenlists/main/generated/balancer.tokenlist.json'; @@ -13,6 +13,7 @@ interface FeaturedPoolMetadata { id: string; imageUrl: string; primary: boolean; + chainId: number; } interface WhitelistedTokenList { name: string; @@ -165,15 +166,21 @@ export class GithubContentService implements ContentService { await prisma.prismaTokenType.createMany({ skipDuplicates: true, data: types }); } async syncPoolContentData(): Promise {} - async getFeaturedPoolGroups(): Promise { + async getFeaturedPoolGroups(chainIds: string[]): Promise { const { data } = await axios.get(POOLS_METADATA_URL); - return data.map(({ id, imageUrl, primary }) => ({ - _key: '', - _type: '', + const pools = data.filter((pool) => chainIds.includes(pool.chainId.toString())); + return pools.map(({ id, imageUrl, primary }) => ({ id, - items: [], + _type: 'homeScreenFeaturedPoolGroupPoolId', + items: [ + { + _key: '', + _type: 'homeScreenFeaturedPoolGroupPoolId', + poolId: id, + } + ], icon: imageUrl, - title: '' + primary: Boolean(primary), })) as HomeScreenFeaturedPoolGroup[]; } async getNewsItems(): Promise { diff --git a/modules/content/sanity-content.service.ts b/modules/content/sanity-content.service.ts index 67403a1f2..0a5006d86 100644 --- a/modules/content/sanity-content.service.ts +++ b/modules/content/sanity-content.service.ts @@ -1,5 +1,5 @@ import { isSameAddress } from '@balancer-labs/sdk'; -import { Prisma, PrismaPoolCategoryType } from '@prisma/client'; +import { Chain, Prisma, PrismaPoolCategoryType } from '@prisma/client'; import { prisma } from '../../prisma/prisma-client'; import { networkContext } from '../network/network-context.service'; import { ConfigHomeScreen, ContentService, HomeScreenFeaturedPoolGroup, HomeScreenNewsItem } from './content-types'; @@ -247,7 +247,8 @@ export class SanityContentService implements ContentService { ]); } - public async getFeaturedPoolGroups(): Promise { + public async getFeaturedPoolGroups(chainIds: string[]): Promise { + // TODO: get featured pools by given chainIds instead of networkContext.chainId const data = await getSanityClient().fetch(` *[_type == "homeScreen" && chainId == ${networkContext.chainId}][0]{ ..., diff --git a/modules/context/header-chain.ts b/modules/context/header-chain.ts index 4e4fe5f33..9833d874a 100644 --- a/modules/context/header-chain.ts +++ b/modules/context/header-chain.ts @@ -13,6 +13,18 @@ const chainIdToChain: { [id: string]: Chain } = { '43114': Chain.AVALANCHE, } +export const chainToChainId: { [chain: string]: string } = { + [Chain.MAINNET]: '1', + [Chain.OPTIMISM]: '10', + [Chain.GNOSIS]: '100', + [Chain.POLYGON]: '137', + [Chain.FANTOM]: '250', + [Chain.ZKEVM]: '1101', + [Chain.BASE]: '8453', + [Chain.ARBITRUM]: '42161', + [Chain.AVALANCHE]: '43114', +}; + /** * Setup to transition out from the old header-based chainIDs to the new required chain query filters. * diff --git a/modules/pool/lib/pool-gql-loader.service.ts b/modules/pool/lib/pool-gql-loader.service.ts index 4f6bfd9d2..aed23b552 100644 --- a/modules/pool/lib/pool-gql-loader.service.ts +++ b/modules/pool/lib/pool-gql-loader.service.ts @@ -38,6 +38,7 @@ import { isWeightedPoolV2 } from './pool-utils'; import { oldBnum } from '../../big-number/old-big-number'; import { networkContext } from '../../network/network-context.service'; import { fixedNumber } from '../../view-helpers/fixed-number'; +import { chainToChainId } from '../../context/header-chain'; export class PoolGqlLoaderService { public async getPool(id: string, chain: Chain): Promise { @@ -91,8 +92,9 @@ export class PoolGqlLoaderService { return prisma.prismaPool.count({ where: this.mapQueryArgsToPoolQuery(args).where }); } - public async getFeaturedPoolGroups(): Promise { - const featuredPoolGroups = await networkContext.config.contentService.getFeaturedPoolGroups(); + public async getFeaturedPoolGroups(chains: Chain[]): Promise { + const chainIds = chains.map((chain) => chainToChainId[chain]); + const featuredPoolGroups = await networkContext.config.contentService.getFeaturedPoolGroups(chainIds); const poolIds = featuredPoolGroups .map((group) => group.items diff --git a/modules/pool/pool.gql b/modules/pool/pool.gql index e0d43a86f..24f419fd3 100644 --- a/modules/pool/pool.gql +++ b/modules/pool/pool.gql @@ -784,6 +784,7 @@ type GqlPoolFeaturedPoolGroup { id: ID! title: String! icon: String! + primary: Boolean! items: [GqlPoolFeaturedPoolGroupItem!]! } From 6b8215e4d1e10ef0fcff185c4b6622fff69f9571 Mon Sep 17 00:00:00 2001 From: mendesfabio Date: Wed, 20 Dec 2023 18:01:01 -0300 Subject: [PATCH 08/11] support chain via headers --- modules/pool/pool.resolvers.ts | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/modules/pool/pool.resolvers.ts b/modules/pool/pool.resolvers.ts index 019c612e6..8ee97fe47 100644 --- a/modules/pool/pool.resolvers.ts +++ b/modules/pool/pool.resolvers.ts @@ -50,6 +50,12 @@ const balancerResolvers: Resolvers = { return poolService.getPoolJoinExits(args); }, poolGetFeaturedPoolGroups: async (parent, { chains }, context) => { + const currentChain = headerChain(); + if (!chains && currentChain) { + chains = [currentChain]; + } else if (!chains) { + throw new Error('poolGetFeaturedPoolGroups error: Provide "chains" param'); + } return poolService.getFeaturedPoolGroups(chains); }, poolGetSnapshots: async (parent, { id, chain, range }, context) => { From f5cf53a18ac2311509e7198194fb4c7c80462e63 Mon Sep 17 00:00:00 2001 From: mendesfabio Date: Wed, 20 Dec 2023 18:01:24 -0300 Subject: [PATCH 09/11] remove featured pools caching --- modules/pool/pool.service.ts | 16 +--------------- 1 file changed, 1 insertion(+), 15 deletions(-) diff --git a/modules/pool/pool.service.ts b/modules/pool/pool.service.ts index 7777febfc..6534636e7 100644 --- a/modules/pool/pool.service.ts +++ b/modules/pool/pool.service.ts @@ -36,8 +36,6 @@ import { reliquarySubgraphService } from '../subgraphs/reliquary-subgraph/reliqu import { ReliquarySnapshotService } from './lib/reliquary-snapshot.service'; import { ContentService } from '../content/content-types'; -const FEATURED_POOL_GROUPS_CACHE_KEY = `pool:featuredPoolGroups`; - export class PoolService { private cache = new Cache(); constructor( @@ -115,19 +113,7 @@ export class PoolService { } public async getFeaturedPoolGroups(chains: Chain[]): Promise { - const cached: GqlPoolFeaturedPoolGroup[] = await this.cache.get( - `${FEATURED_POOL_GROUPS_CACHE_KEY}:${this.chainId}`, - ); - - if (cached) { - return cached; - } - - const featuredPoolGroups = await this.poolGqlLoaderService.getFeaturedPoolGroups(); - - this.cache.put(`${FEATURED_POOL_GROUPS_CACHE_KEY}:${this.chainId}`, featuredPoolGroups, 60 * 5 * 1000); - - return featuredPoolGroups; + return this.poolGqlLoaderService.getFeaturedPoolGroups(chains); } public async getSnapshotsForAllPools(chains: Chain[], range: GqlPoolSnapshotDataRange) { From 9eb22e0258223dd395d5b63a60bb8a15961b7d75 Mon Sep 17 00:00:00 2001 From: franz Date: Thu, 21 Dec 2023 16:28:33 +0100 Subject: [PATCH 10/11] add chainId --- modules/content/content-types.ts | 1 + modules/content/github-content.service.ts | 43 +++++++++++------------ modules/pool/pool.gql | 3 +- 3 files changed, 24 insertions(+), 23 deletions(-) diff --git a/modules/content/content-types.ts b/modules/content/content-types.ts index bf6da0e42..5b8da9bc8 100644 --- a/modules/content/content-types.ts +++ b/modules/content/content-types.ts @@ -11,6 +11,7 @@ export interface HomeScreenFeaturedPoolGroup { items: (HomeScreenFeaturedPoolGroupItemPoolId | HomeScreenFeaturedPoolGroupItemExternalLink)[]; title: string; primary: boolean; + chainId: number; } interface HomeScreenFeaturedPoolGroupItemPoolId { diff --git a/modules/content/github-content.service.ts b/modules/content/github-content.service.ts index 50e8a0af0..a1767b4b0 100644 --- a/modules/content/github-content.service.ts +++ b/modules/content/github-content.service.ts @@ -5,7 +5,7 @@ import { prisma } from '../../prisma/prisma-client'; import { networkContext } from '../network/network-context.service'; import { ContentService, HomeScreenFeaturedPoolGroup, HomeScreenNewsItem } from './content-types'; -const POOLS_METADATA_URL = "https://raw.githubusercontent.com/balancer/metadata/chains/pools/featured.json"; +const POOLS_METADATA_URL = 'https://raw.githubusercontent.com/balancer/metadata/chains/pools/featured.json'; const TOKEN_LIST_URL = 'https://raw.githubusercontent.com/balancer/tokenlists/main/generated/balancer.tokenlist.json'; @@ -35,16 +35,14 @@ export class GithubContentService implements ContentService { async syncTokenContentData(): Promise { const { data: githubAllTokenList } = await axios.get(TOKEN_LIST_URL); - const filteredTokenList = githubAllTokenList.tokens.filter( - (token) => { - if (`${token.chainId}` !== networkContext.chainId) { - return false; - } - - const requiredKeys = ['chainId', 'address', 'name', 'symbol', 'decimals'] - return requiredKeys.every((key) => token?.[key as keyof WhitelistedToken] != null) + const filteredTokenList = githubAllTokenList.tokens.filter((token) => { + if (`${token.chainId}` !== networkContext.chainId) { + return false; } - ); + + const requiredKeys = ['chainId', 'address', 'name', 'symbol', 'decimals']; + return requiredKeys.every((key) => token?.[key as keyof WhitelistedToken] != null); + }); for (const githubToken of filteredTokenList) { const tokenAddress = githubToken.address.toLowerCase(); @@ -169,18 +167,19 @@ export class GithubContentService implements ContentService { async getFeaturedPoolGroups(chainIds: string[]): Promise { const { data } = await axios.get(POOLS_METADATA_URL); const pools = data.filter((pool) => chainIds.includes(pool.chainId.toString())); - return pools.map(({ id, imageUrl, primary }) => ({ - id, - _type: 'homeScreenFeaturedPoolGroupPoolId', - items: [ - { - _key: '', - _type: 'homeScreenFeaturedPoolGroupPoolId', - poolId: id, - } - ], - icon: imageUrl, - primary: Boolean(primary), + return pools.map(({ id, imageUrl, primary, chainId }) => ({ + id, + _type: 'homeScreenFeaturedPoolGroupPoolId', + items: [ + { + _key: '', + _type: 'homeScreenFeaturedPoolGroupPoolId', + poolId: id, + }, + ], + icon: imageUrl, + chainId: chainId, + primary: Boolean(primary), })) as HomeScreenFeaturedPoolGroup[]; } async getNewsItems(): Promise { diff --git a/modules/pool/pool.gql b/modules/pool/pool.gql index 24f419fd3..b186ad148 100644 --- a/modules/pool/pool.gql +++ b/modules/pool/pool.gql @@ -19,7 +19,7 @@ extend type Query { poolGetSwaps(first: Int, skip: Int, where: GqlPoolSwapFilter): [GqlPoolSwap!]! poolGetBatchSwaps(first: Int, skip: Int, where: GqlPoolSwapFilter): [GqlPoolBatchSwap!]! poolGetJoinExits(first: Int, skip: Int, where: GqlPoolJoinExitFilter): [GqlPoolJoinExit!]! - poolGetFeaturedPoolGroups(chains: [GqlChain!]!): [GqlPoolFeaturedPoolGroup!]! + poolGetFeaturedPoolGroups(chains: [GqlChain!]): [GqlPoolFeaturedPoolGroup!]! poolGetSnapshots(id: String!, chain: GqlChain, range: GqlPoolSnapshotDataRange!): [GqlPoolSnapshot!]! poolGetAllPoolsSnapshots(chains: [GqlChain!], range: GqlPoolSnapshotDataRange!): [GqlPoolSnapshot!]! poolGetLinearPools(chains: [GqlChain!]): [GqlPoolLinear!]! @@ -785,6 +785,7 @@ type GqlPoolFeaturedPoolGroup { title: String! icon: String! primary: Boolean! + chainId: Int! items: [GqlPoolFeaturedPoolGroupItem!]! } From 576c1bb65b5ceaa1bc938a3143c826fa756b3c32 Mon Sep 17 00:00:00 2001 From: franz Date: Thu, 21 Dec 2023 18:24:24 +0100 Subject: [PATCH 11/11] make sanity multichain --- modules/content/content-types.ts | 7 +- modules/content/github-content.service.ts | 12 ++- modules/content/sanity-content.service.ts | 112 +++++++++++--------- modules/context/header-chain.ts | 31 +----- modules/network/base.ts | 4 - modules/network/fantom.ts | 6 +- modules/network/network-config-types.ts | 4 - modules/network/network-config.ts | 12 +++ modules/network/optimism.ts | 6 +- modules/pool/lib/pool-gql-loader.service.ts | 15 ++- modules/pool/pool.gql | 2 +- 11 files changed, 106 insertions(+), 105 deletions(-) diff --git a/modules/content/content-types.ts b/modules/content/content-types.ts index 5b8da9bc8..4e4e65df7 100644 --- a/modules/content/content-types.ts +++ b/modules/content/content-types.ts @@ -1,3 +1,6 @@ +import { Chain } from '@prisma/client'; +import { GqlChain } from '../../schema'; + export interface ConfigHomeScreen { featuredPoolGroups: HomeScreenFeaturedPoolGroup[]; newsItems: HomeScreenNewsItem[]; @@ -11,7 +14,7 @@ export interface HomeScreenFeaturedPoolGroup { items: (HomeScreenFeaturedPoolGroupItemPoolId | HomeScreenFeaturedPoolGroupItemExternalLink)[]; title: string; primary: boolean; - chainId: number; + chain: GqlChain; } interface HomeScreenFeaturedPoolGroupItemPoolId { @@ -41,6 +44,6 @@ export interface HomeScreenNewsItem { export interface ContentService { syncTokenContentData(): Promise; syncPoolContentData(): Promise; - getFeaturedPoolGroups(chainIds: string[]): Promise; + getFeaturedPoolGroups(chains: Chain[]): Promise; getNewsItems(): Promise; } diff --git a/modules/content/github-content.service.ts b/modules/content/github-content.service.ts index a1767b4b0..546556782 100644 --- a/modules/content/github-content.service.ts +++ b/modules/content/github-content.service.ts @@ -1,11 +1,12 @@ import { isSameAddress } from '@balancer-labs/sdk'; -import { Prisma } from '@prisma/client'; +import { Chain, Prisma } from '@prisma/client'; import axios from 'axios'; import { prisma } from '../../prisma/prisma-client'; import { networkContext } from '../network/network-context.service'; import { ContentService, HomeScreenFeaturedPoolGroup, HomeScreenNewsItem } from './content-types'; +import { chainIdToChain } from '../network/network-config'; -const POOLS_METADATA_URL = 'https://raw.githubusercontent.com/balancer/metadata/chains/pools/featured.json'; +const POOLS_METADATA_URL = 'https://raw.githubusercontent.com/balancer/metadata/main/pools/featured.json'; const TOKEN_LIST_URL = 'https://raw.githubusercontent.com/balancer/tokenlists/main/generated/balancer.tokenlist.json'; @@ -164,12 +165,13 @@ export class GithubContentService implements ContentService { await prisma.prismaTokenType.createMany({ skipDuplicates: true, data: types }); } async syncPoolContentData(): Promise {} - async getFeaturedPoolGroups(chainIds: string[]): Promise { + async getFeaturedPoolGroups(chains: Chain[]): Promise { const { data } = await axios.get(POOLS_METADATA_URL); - const pools = data.filter((pool) => chainIds.includes(pool.chainId.toString())); + const pools = data.filter((pool) => chains.includes(chainIdToChain[pool.chainId])); return pools.map(({ id, imageUrl, primary, chainId }) => ({ id, _type: 'homeScreenFeaturedPoolGroupPoolId', + title: 'Popular pools', items: [ { _key: '', @@ -178,7 +180,7 @@ export class GithubContentService implements ContentService { }, ], icon: imageUrl, - chainId: chainId, + chain: chainIdToChain[chainId], primary: Boolean(primary), })) as HomeScreenFeaturedPoolGroup[]; } diff --git a/modules/content/sanity-content.service.ts b/modules/content/sanity-content.service.ts index 0a5006d86..9da7f2112 100644 --- a/modules/content/sanity-content.service.ts +++ b/modules/content/sanity-content.service.ts @@ -1,10 +1,10 @@ import { isSameAddress } from '@balancer-labs/sdk'; import { Chain, Prisma, PrismaPoolCategoryType } from '@prisma/client'; import { prisma } from '../../prisma/prisma-client'; -import { networkContext } from '../network/network-context.service'; import { ConfigHomeScreen, ContentService, HomeScreenFeaturedPoolGroup, HomeScreenNewsItem } from './content-types'; import SanityClient from '@sanity/client'; import { env } from '../../app/env'; +import { chainToIdMap } from '../network/network-config'; interface SanityToken { name: string; @@ -35,9 +35,15 @@ const SANITY_TOKEN_TYPE_MAP: { [key: string]: string } = { }; export class SanityContentService implements ContentService { + constructor( + private readonly chain: Chain, + private readonly projectId = '1g2ag2hb', + private readonly dataset = 'production', + ) {} + async syncTokenContentData(): Promise { - const sanityTokens = await getSanityClient().fetch(` - *[_type=="${SANITY_TOKEN_TYPE_MAP[networkContext.chainId]}"] { + const sanityTokens = await this.getSanityClient().fetch(` + *[_type=="${SANITY_TOKEN_TYPE_MAP[chainToIdMap[this.chain]]}"] { name, address, symbol, @@ -77,12 +83,12 @@ export class SanityContentService implements ContentService { await prisma.prismaToken.upsert({ where: { - address_chain: { address: tokenAddress, chain: networkContext.chain }, + address_chain: { address: tokenAddress, chain: this.chain }, }, create: { name: sanityToken.name, address: tokenAddress, - chain: networkContext.chain, + chain: this.chain, symbol: sanityToken.symbol, decimals: sanityToken.decimals, logoURI: sanityToken.logoURI, @@ -110,7 +116,7 @@ export class SanityContentService implements ContentService { const whiteListedTokens = await prisma.prismaTokenType.findMany({ where: { type: 'WHITE_LISTED', - chain: networkContext.chain, + chain: this.chain, }, }); @@ -125,7 +131,7 @@ export class SanityContentService implements ContentService { await prisma.prismaTokenType.createMany({ data: addToWhitelist.map((token) => ({ id: `${token.address}-white-listed`, - chain: networkContext.chain, + chain: this.chain, tokenAddress: token.address.toLowerCase(), type: 'WHITE_LISTED' as const, })), @@ -133,7 +139,7 @@ export class SanityContentService implements ContentService { }); await prisma.prismaTokenType.deleteMany({ - where: { id: { in: removeFromWhitelist.map((token) => token.id) }, chain: networkContext.chain }, + where: { id: { in: removeFromWhitelist.map((token) => token.id) }, chain: this.chain }, }); await this.syncTokenTypes(); @@ -143,7 +149,7 @@ export class SanityContentService implements ContentService { const pools = await this.loadPoolData(); const tokens = await prisma.prismaToken.findMany({ include: { types: true }, - where: { chain: networkContext.chain }, + where: { chain: this.chain }, }); const types: Prisma.PrismaTokenTypeCreateManyInput[] = []; @@ -154,7 +160,7 @@ export class SanityContentService implements ContentService { if (pool && !tokenTypes.includes('BPT')) { types.push({ id: `${token.address}-bpt`, - chain: networkContext.chain, + chain: this.chain, type: 'BPT', tokenAddress: token.address, }); @@ -163,7 +169,7 @@ export class SanityContentService implements ContentService { if ((pool?.type === 'PHANTOM_STABLE' || pool?.type === 'LINEAR') && !tokenTypes.includes('PHANTOM_BPT')) { types.push({ id: `${token.address}-phantom-bpt`, - chain: networkContext.chain, + chain: this.chain, type: 'PHANTOM_BPT', tokenAddress: token.address, }); @@ -176,7 +182,7 @@ export class SanityContentService implements ContentService { if (linearPool && !tokenTypes.includes('LINEAR_WRAPPED_TOKEN')) { types.push({ id: `${token.address}-linear-wrapped`, - chain: networkContext.chain, + chain: this.chain, type: 'LINEAR_WRAPPED_TOKEN', tokenAddress: token.address, }); @@ -188,7 +194,7 @@ export class SanityContentService implements ContentService { private async loadPoolData() { return prisma.prismaPool.findMany({ - where: { chain: networkContext.chain }, + where: { chain: this.chain }, select: { address: true, symbol: true, @@ -201,7 +207,9 @@ export class SanityContentService implements ContentService { } public async syncPoolContentData(): Promise { - const response = await getSanityClient().fetch(`*[_type == "config" && chainId == ${networkContext.chainId}][0]{ + const response = await this.getSanityClient().fetch(`*[_type == "config" && chainId == ${ + chainToIdMap[this.chain] + }][0]{ incentivizedPools, blacklistedPools, }`); @@ -211,7 +219,7 @@ export class SanityContentService implements ContentService { blacklistedPools: response?.blacklistedPools ?? [], }; - const categories = await prisma.prismaPoolCategory.findMany({ where: { chain: networkContext.chain } }); + const categories = await prisma.prismaPoolCategory.findMany({ where: { chain: this.chain } }); const incentivized = categories.filter((item) => item.category === 'INCENTIVIZED').map((item) => item.poolId); const blacklisted = categories.filter((item) => item.category === 'BLACK_LISTED').map((item) => item.poolId); @@ -225,7 +233,7 @@ export class SanityContentService implements ContentService { // make sure the pools really exist to prevent sanity mistakes from breaking the system const pools = await prisma.prismaPool.findMany({ - where: { id: { in: itemsToAdd }, chain: networkContext.chain }, + where: { id: { in: itemsToAdd }, chain: this.chain }, select: { id: true }, }); const poolIds = pools.map((pool) => pool.id); @@ -235,47 +243,53 @@ export class SanityContentService implements ContentService { prisma.prismaPoolCategory.createMany({ data: existingItemsToAdd.map((poolId) => ({ id: `${poolId}-${category}`, - chain: networkContext.chain, + chain: this.chain, category, poolId, })), skipDuplicates: true, }), prisma.prismaPoolCategory.deleteMany({ - where: { poolId: { in: itemsToRemove }, category, chain: networkContext.chain }, + where: { poolId: { in: itemsToRemove }, category, chain: this.chain }, }), ]); } - public async getFeaturedPoolGroups(chainIds: string[]): Promise { - // TODO: get featured pools by given chainIds instead of networkContext.chainId - const data = await getSanityClient().fetch(` - *[_type == "homeScreen" && chainId == ${networkContext.chainId}][0]{ - ..., - "featuredPoolGroups": featuredPoolGroups[]{ + public async getFeaturedPoolGroups(chains: Chain[]): Promise { + const featuredPoolGroups: HomeScreenFeaturedPoolGroup[] = []; + for (const chain of chains) { + const data = await this.getSanityClient().fetch(` + *[_type == "homeScreen" && chainId == ${chainToIdMap[chain]}][0]{ ..., - "icon": icon.asset->url + "?w=64", - "items": items[]{ + "featuredPoolGroups": featuredPoolGroups[]{ + ..., + "icon": icon.asset->url + "?w=64", + "items": items[]{ + ..., + "image": image.asset->url + "?w=600" + } + }, + "newsItems": newsItems[]{ ..., - "image": image.asset->url + "?w=600" + "image": image.asset->url + "?w=800" } - }, - "newsItems": newsItems[]{ - ..., - "image": image.asset->url + "?w=800" + } + `); + if (data) { + featuredPoolGroups.push( + ...data.featuredPoolGroups.map((pool) => ({ + ...pool, + chain: chain, + })), + ); } } - `); - - if (data?.featuredPoolGroups) { - return data.featuredPoolGroups; - } - throw new Error(`No featured pool groups found for chain id ${networkContext.chainId}`); + return featuredPoolGroups; } public async getNewsItems(): Promise { - const data = await getSanityClient().fetch(` - *[_type == "homeScreen" && chainId == ${networkContext.chainId}][0]{ + const data = await this.getSanityClient().fetch(` + *[_type == "homeScreen" && chainId == ${chainToIdMap[this.chain]}][0]{ ..., "featuredPoolGroups": featuredPoolGroups[]{ ..., @@ -295,16 +309,16 @@ export class SanityContentService implements ContentService { if (data?.newsItems) { return data.newsItems; } - throw new Error(`No news items found for chain id ${networkContext.chainId}`); + throw new Error(`No news items found for chain id ${this.chain}`); } -} -export function getSanityClient() { - return SanityClient({ - projectId: networkContext.data.sanity!.projectId, - dataset: networkContext.data.sanity!.dataset, - apiVersion: '2021-12-15', - token: env.SANITY_API_TOKEN, - useCdn: false, - }); + private getSanityClient() { + return SanityClient({ + projectId: this.projectId, + dataset: this.dataset, + apiVersion: '2021-12-15', + token: env.SANITY_API_TOKEN, + useCdn: false, + }); + } } diff --git a/modules/context/header-chain.ts b/modules/context/header-chain.ts index 9833d874a..799f9d097 100644 --- a/modules/context/header-chain.ts +++ b/modules/context/header-chain.ts @@ -1,41 +1,18 @@ import { getRequestScopeContextValue } from '../context/request-scoped-context'; import { Chain } from '@prisma/client'; - -const chainIdToChain: { [id: string]: Chain } = { - '1': Chain.MAINNET, - '10': Chain.OPTIMISM, - '100': Chain.GNOSIS, - '137': Chain.POLYGON, - '250': Chain.FANTOM, - '1101': Chain.ZKEVM, - '8453': Chain.BASE, - '42161': Chain.ARBITRUM, - '43114': Chain.AVALANCHE, -} - -export const chainToChainId: { [chain: string]: string } = { - [Chain.MAINNET]: '1', - [Chain.OPTIMISM]: '10', - [Chain.GNOSIS]: '100', - [Chain.POLYGON]: '137', - [Chain.FANTOM]: '250', - [Chain.ZKEVM]: '1101', - [Chain.BASE]: '8453', - [Chain.ARBITRUM]: '42161', - [Chain.AVALANCHE]: '43114', -}; +import { chainIdToChain } from '../network/network-config'; /** * Setup to transition out from the old header-based chainIDs to the new required chain query filters. - * + * * @returns The chain of the current request, if any. */ export const headerChain = (): Chain | undefined => { const chainId = getRequestScopeContextValue('chainId'); - + if (chainId) { return chainIdToChain[chainId]; } return undefined; -} +}; diff --git a/modules/network/base.ts b/modules/network/base.ts index bd45b9005..9bbea516f 100644 --- a/modules/network/base.ts +++ b/modules/network/base.ts @@ -56,10 +56,6 @@ const baseNetworkData: NetworkData = { }, rpcUrl: 'https://base.gateway.tenderly.co/7mM7DbBouY1JjnQd9MMDsd', rpcMaxBlockRange: 500, - sanity: { - projectId: '', - dataset: '', - }, protocolToken: 'bal', bal: { address: '0x4158734d47fc9692176b5085e0f52ee0da5d47f1', diff --git a/modules/network/fantom.ts b/modules/network/fantom.ts index 22727cf81..6391205c5 100644 --- a/modules/network/fantom.ts +++ b/modules/network/fantom.ts @@ -101,10 +101,6 @@ const fantomNetworkData: NetworkData = { ? `https://rpc.ankr.com/fantom` : `https://rpc.fantom.gateway.fm`, rpcMaxBlockRange: 1000, - sanity: { - projectId: '1g2ag2hb', - dataset: 'production', - }, protocolToken: 'beets', beets: { address: '0xf24bcf4d1e507740041c9cfd2dddb29585adce1e', @@ -298,7 +294,7 @@ const fantomNetworkData: NetworkData = { export const fantomNetworkConfig: NetworkConfig = { data: fantomNetworkData, - contentService: new SanityContentService(), + contentService: new SanityContentService(fantomNetworkData.chain.prismaId), provider: new ethers.providers.JsonRpcProvider({ url: fantomNetworkData.rpcUrl, timeout: 60000 }), poolAprServices: [ new IbTokensAprService( diff --git a/modules/network/network-config-types.ts b/modules/network/network-config-types.ts index 6bf9ffe5d..86982b656 100644 --- a/modules/network/network-config-types.ts +++ b/modules/network/network-config-types.ts @@ -77,10 +77,6 @@ export interface NetworkData { veBalLocks?: string; userBalances: string; }; - sanity?: { - projectId: string; - dataset: string; - }; protocolToken: 'beets' | 'bal'; beets?: { address: string; diff --git a/modules/network/network-config.ts b/modules/network/network-config.ts index 74ec636e3..35f86c2b2 100644 --- a/modules/network/network-config.ts +++ b/modules/network/network-config.ts @@ -34,6 +34,18 @@ export const AllNetworkConfigsKeyedOnChain: { [chain in Chain]: NetworkConfig } BASE: baseNetworkConfig, }; +export const chainIdToChain: { [id: string]: Chain } = { + '1': Chain.MAINNET, + '10': Chain.OPTIMISM, + '100': Chain.GNOSIS, + '137': Chain.POLYGON, + '250': Chain.FANTOM, + '1101': Chain.ZKEVM, + '8453': Chain.BASE, + '42161': Chain.ARBITRUM, + '43114': Chain.AVALANCHE, +}; + export const BalancerChainIds = ['1', '137', '42161', '100', '1101', '43114', '8453']; export const BeethovenChainIds = ['250', '10']; diff --git a/modules/network/optimism.ts b/modules/network/optimism.ts index ffe2b7a5c..1d2ee68a5 100644 --- a/modules/network/optimism.ts +++ b/modules/network/optimism.ts @@ -60,10 +60,6 @@ const optimismNetworkData: NetworkData = { ? `https://optimism-mainnet.infura.io/v3/${env.INFURA_API_KEY}` : 'https://mainnet.optimism.io', rpcMaxBlockRange: 2000, - sanity: { - projectId: '1g2ag2hb', - dataset: 'production', - }, protocolToken: 'beets', beets: { address: '0xb4bc46bc6cb217b59ea8f4530bae26bf69f677f0', @@ -257,7 +253,7 @@ const optimismNetworkData: NetworkData = { export const optimismNetworkConfig: NetworkConfig = { data: optimismNetworkData, - contentService: new SanityContentService(), + contentService: new SanityContentService(optimismNetworkData.chain.prismaId), provider: new ethers.providers.JsonRpcProvider({ url: optimismNetworkData.rpcUrl, timeout: 60000 }), poolAprServices: [ new IbTokensAprService( diff --git a/modules/pool/lib/pool-gql-loader.service.ts b/modules/pool/lib/pool-gql-loader.service.ts index c3757aab5..6b98fae01 100644 --- a/modules/pool/lib/pool-gql-loader.service.ts +++ b/modules/pool/lib/pool-gql-loader.service.ts @@ -42,7 +42,10 @@ import { networkContext } from '../../network/network-context.service'; import { fixedNumber } from '../../view-helpers/fixed-number'; import { parseUnits } from 'ethers/lib/utils'; import { formatFixed } from '@ethersproject/bignumber'; -import { chainToChainId } from '../../context/header-chain'; +import { BalancerChainIds, BeethovenChainIds, chainIdToChain, chainToIdMap } from '../../network/network-config'; +import { GithubContentService } from '../../content/github-content.service'; +import SanityClientConstructor from '@sanity/client'; +import { SanityContentService } from '../../content/sanity-content.service'; export class PoolGqlLoaderService { public async getPool(id: string, chain: Chain, userAddress?: string): Promise { @@ -156,8 +159,14 @@ export class PoolGqlLoaderService { } public async getFeaturedPoolGroups(chains: Chain[]): Promise { - const chainIds = chains.map((chain) => chainToChainId[chain]); - const featuredPoolGroups = await networkContext.config.contentService.getFeaturedPoolGroups(chainIds); + const featuredPoolGroups = []; + if (chains.some((chain) => BalancerChainIds.includes(chainToIdMap[chain]))) { + const githubContentService = new GithubContentService(); + featuredPoolGroups.push(...(await githubContentService.getFeaturedPoolGroups(chains))); + } else if (chains.some((chain) => BeethovenChainIds.includes(chainToIdMap[chain]))) { + const sanityContentService = new SanityContentService('FANTOM'); + featuredPoolGroups.push(...(await sanityContentService.getFeaturedPoolGroups(chains))); + } const poolIds = featuredPoolGroups .map((group) => group.items diff --git a/modules/pool/pool.gql b/modules/pool/pool.gql index e11c7ee2e..f7c6877f2 100644 --- a/modules/pool/pool.gql +++ b/modules/pool/pool.gql @@ -821,7 +821,7 @@ type GqlPoolFeaturedPoolGroup { title: String! icon: String! primary: Boolean! - chainId: Int! + chain: GqlChain! items: [GqlPoolFeaturedPoolGroupItem!]! }