Skip to content

Commit

Permalink
make sanity multichain
Browse files Browse the repository at this point in the history
  • Loading branch information
franzns committed Dec 21, 2023
1 parent ea4a433 commit 576c1bb
Show file tree
Hide file tree
Showing 11 changed files with 106 additions and 105 deletions.
7 changes: 5 additions & 2 deletions modules/content/content-types.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
import { Chain } from '@prisma/client';
import { GqlChain } from '../../schema';

export interface ConfigHomeScreen {
featuredPoolGroups: HomeScreenFeaturedPoolGroup[];
newsItems: HomeScreenNewsItem[];
Expand All @@ -11,7 +14,7 @@ export interface HomeScreenFeaturedPoolGroup {
items: (HomeScreenFeaturedPoolGroupItemPoolId | HomeScreenFeaturedPoolGroupItemExternalLink)[];
title: string;
primary: boolean;
chainId: number;
chain: GqlChain;
}

interface HomeScreenFeaturedPoolGroupItemPoolId {
Expand Down Expand Up @@ -41,6 +44,6 @@ export interface HomeScreenNewsItem {
export interface ContentService {
syncTokenContentData(): Promise<void>;
syncPoolContentData(): Promise<void>;
getFeaturedPoolGroups(chainIds: string[]): Promise<HomeScreenFeaturedPoolGroup[]>;
getFeaturedPoolGroups(chains: Chain[]): Promise<HomeScreenFeaturedPoolGroup[]>;
getNewsItems(): Promise<HomeScreenNewsItem[]>;
}
12 changes: 7 additions & 5 deletions modules/content/github-content.service.ts
Original file line number Diff line number Diff line change
@@ -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';

Expand Down Expand Up @@ -164,12 +165,13 @@ export class GithubContentService implements ContentService {
await prisma.prismaTokenType.createMany({ skipDuplicates: true, data: types });
}
async syncPoolContentData(): Promise<void> {}
async getFeaturedPoolGroups(chainIds: string[]): Promise<HomeScreenFeaturedPoolGroup[]> {
async getFeaturedPoolGroups(chains: Chain[]): Promise<HomeScreenFeaturedPoolGroup[]> {
const { data } = await axios.get<FeaturedPoolMetadata[]>(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: '',
Expand All @@ -178,7 +180,7 @@ export class GithubContentService implements ContentService {
},
],
icon: imageUrl,
chainId: chainId,
chain: chainIdToChain[chainId],
primary: Boolean(primary),
})) as HomeScreenFeaturedPoolGroup[];
}
Expand Down
112 changes: 63 additions & 49 deletions modules/content/sanity-content.service.ts
Original file line number Diff line number Diff line change
@@ -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;
Expand Down Expand Up @@ -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<void> {
const sanityTokens = await getSanityClient().fetch<SanityToken[]>(`
*[_type=="${SANITY_TOKEN_TYPE_MAP[networkContext.chainId]}"] {
const sanityTokens = await this.getSanityClient().fetch<SanityToken[]>(`
*[_type=="${SANITY_TOKEN_TYPE_MAP[chainToIdMap[this.chain]]}"] {
name,
address,
symbol,
Expand Down Expand Up @@ -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,
Expand Down Expand Up @@ -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,
},
});

Expand All @@ -125,15 +131,15 @@ 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,
})),
skipDuplicates: true,
});

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();
Expand All @@ -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[] = [];

Expand All @@ -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,
});
Expand All @@ -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,
});
Expand All @@ -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,
});
Expand All @@ -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,
Expand All @@ -201,7 +207,9 @@ export class SanityContentService implements ContentService {
}

public async syncPoolContentData(): Promise<void> {
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,
}`);
Expand All @@ -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);

Expand All @@ -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);
Expand All @@ -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<HomeScreenFeaturedPoolGroup[]> {
// TODO: get featured pools by given chainIds instead of networkContext.chainId
const data = await getSanityClient().fetch<ConfigHomeScreen | null>(`
*[_type == "homeScreen" && chainId == ${networkContext.chainId}][0]{
...,
"featuredPoolGroups": featuredPoolGroups[]{
public async getFeaturedPoolGroups(chains: Chain[]): Promise<HomeScreenFeaturedPoolGroup[]> {
const featuredPoolGroups: HomeScreenFeaturedPoolGroup[] = [];
for (const chain of chains) {
const data = await this.getSanityClient().fetch<ConfigHomeScreen | null>(`
*[_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<HomeScreenNewsItem[]> {
const data = await getSanityClient().fetch<ConfigHomeScreen | null>(`
*[_type == "homeScreen" && chainId == ${networkContext.chainId}][0]{
const data = await this.getSanityClient().fetch<ConfigHomeScreen | null>(`
*[_type == "homeScreen" && chainId == ${chainToIdMap[this.chain]}][0]{
...,
"featuredPoolGroups": featuredPoolGroups[]{
...,
Expand All @@ -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,
});
}
}
31 changes: 4 additions & 27 deletions modules/context/header-chain.ts
Original file line number Diff line number Diff line change
@@ -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<string>('chainId');

if (chainId) {
return chainIdToChain[chainId];
}

return undefined;
}
};
4 changes: 0 additions & 4 deletions modules/network/base.ts
Original file line number Diff line number Diff line change
Expand Up @@ -56,10 +56,6 @@ const baseNetworkData: NetworkData = {
},
rpcUrl: 'https://base.gateway.tenderly.co/7mM7DbBouY1JjnQd9MMDsd',
rpcMaxBlockRange: 500,
sanity: {
projectId: '',
dataset: '',
},
protocolToken: 'bal',
bal: {
address: '0x4158734d47fc9692176b5085e0f52ee0da5d47f1',
Expand Down
6 changes: 1 addition & 5 deletions modules/network/fantom.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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',
Expand Down Expand Up @@ -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(
Expand Down
Loading

0 comments on commit 576c1bb

Please sign in to comment.