Skip to content

Commit

Permalink
Add chains to tokens and token prices queries (#483)
Browse files Browse the repository at this point in the history
* Add chains to tokens and token prices queries

* all chains as default

* falling back to the default chain for filtering

---------

Co-authored-by: gmbronco <[email protected]>
  • Loading branch information
danielmkm and gmbronco authored Oct 18, 2023
1 parent 3235797 commit 9fc299f
Show file tree
Hide file tree
Showing 6 changed files with 50 additions and 35 deletions.
4 changes: 2 additions & 2 deletions modules/coingecko/coingecko.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -109,7 +109,7 @@ export class CoingeckoService {
try {
if (addresses.length / addressesPerRequest > 10) throw new Error('Too many requests for rate limit.');

const tokenDefinitions = await tokenService.getTokenDefinitions();
const tokenDefinitions = await tokenService.getTokenDefinitions([networkContext.chain]);
const mapped = addresses.map((address) => this.getMappedTokenDetails(address, tokenDefinitions));
const groupedByPlatform = _.groupBy(mapped, 'platform');

Expand Down Expand Up @@ -144,7 +144,7 @@ export class CoingeckoService {
const now = Math.floor(Date.now() / 1000);
const end = now;
const start = end - days * twentyFourHoursInSecs;
const tokenDefinitions = await tokenService.getTokenDefinitions();
const tokenDefinitions = await tokenService.getTokenDefinitions([networkContext.chain]);
const mapped = this.getMappedTokenDetails(address, tokenDefinitions);

const endpoint = `/coins/${mapped.platform}/contract/${mapped.address}/market_chart/range?vs_currency=${this.fiatParam}&from=${start}&to=${end}`;
Expand Down
28 changes: 14 additions & 14 deletions modules/token/lib/token-price.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import { TokenPriceHandler, TokenPriceItem } from '../token-types';
import { prisma } from '../../../prisma/prisma-client';
import _ from 'lodash';
import { secondsPerDay, timestampRoundedUpToNearestHour } from '../../common/time';
import { PrismaTokenCurrentPrice, PrismaTokenPrice } from '@prisma/client';
import { Chain, PrismaTokenCurrentPrice, PrismaTokenPrice } from '@prisma/client';
import moment from 'moment-timezone';
import { GqlTokenChartDataRange } from '../../../schema';
import { Cache, CacheClass } from 'memory-cache';
Expand All @@ -23,27 +23,27 @@ export class TokenPriceService {
return networkContext.config.tokenPriceHandlers;
}

public async getWhiteListedCurrentTokenPrices(): Promise<PrismaTokenCurrentPrice[]> {
public async getWhiteListedCurrentTokenPrices(chains: Chain[]): Promise<PrismaTokenCurrentPrice[]> {
const tokenPrices = await prisma.prismaTokenCurrentPrice.findMany({
orderBy: { timestamp: 'desc' },
distinct: ['tokenAddress'],
where: {
chain: networkContext.chain,
token: {
types: { some: { type: 'WHITE_LISTED' } },
},
chain: { in: chains },
token: { types: { some: { type: 'WHITE_LISTED' } } },
},
});

const wethPrice = tokenPrices.find(
(tokenPrice) => tokenPrice.tokenAddress === networkContext.data.weth.address,
);
for (const chain of chains) {
const wethPrice = tokenPrices.find(
(tokenPrice) => tokenPrice.tokenAddress === AllNetworkConfigsKeyedOnChain[chain].data.weth.address,
);

if (wethPrice) {
tokenPrices.push({
...wethPrice,
tokenAddress: networkContext.data.eth.address,
});
if (wethPrice) {
tokenPrices.push({
...wethPrice,
tokenAddress: AllNetworkConfigsKeyedOnChain[chain].data.eth.address,
});
}
}

return tokenPrices;
Expand Down
2 changes: 2 additions & 0 deletions modules/token/token-types.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { PrismaTokenWithTypesAndPrices, PrismaTokenWithTypes } from '../../prisma/prisma-types';
import { Chain } from '@prisma/client';

export interface TokenPriceHandler {
exitIfFails: boolean;
Expand All @@ -24,6 +25,7 @@ export interface TokenDefinition {
symbol: string;
decimals: number;
chainId: number;
chain: Chain;
logoURI?: string | null;
priority: number;
coingeckoPlatformId?: string | null;
Expand Down
6 changes: 4 additions & 2 deletions modules/token/token.gql
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
extend type Query {
tokenGetTokens: [GqlToken!]!
tokenGetCurrentPrices: [GqlTokenPrice!]!
tokenGetTokens(chains: [GqlChain!]): [GqlToken!]!
tokenGetCurrentPrices(chains: [GqlChain!]): [GqlTokenPrice!]!
tokenGetHistoricalPrices(addresses: [String!]!): [GqlHistoricalTokenPrice!]!
tokenGetTokensDynamicData(addresses: [String!]!): [GqlTokenDynamicData!]!
tokenGetTokenDynamicData(address: String!): GqlTokenDynamicData
Expand Down Expand Up @@ -28,6 +28,7 @@ extend type Mutation {

type GqlTokenPrice {
address: String!
chain: GqlChain!
price: Float!
}

Expand Down Expand Up @@ -55,6 +56,7 @@ type GqlToken {
logoURI: String
priority: Int!
tradable: Boolean!
chain: GqlChain!
}

type GqlTokenDynamicData {
Expand Down
12 changes: 8 additions & 4 deletions modules/token/token.resolvers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,18 +2,22 @@ import { Resolvers } from '../../schema';
import _ from 'lodash';
import { isAdminRoute } from '../auth/auth-context';
import { tokenService } from './token.service';
import { networkContext } from '../network/network-context.service';

const resolvers: Resolvers = {
Query: {
tokenGetTokens: async () => {
return tokenService.getTokenDefinitions();
tokenGetTokens: async (parent, { chains }, context) => {
chains = chains && chains.length > 0 ? chains : [networkContext.chain];
return tokenService.getTokenDefinitions(chains);
},
tokenGetCurrentPrices: async (parent, {}, context) => {
const prices = await tokenService.getWhiteListedTokenPrices();
tokenGetCurrentPrices: async (parent, { chains }, context) => {
chains = chains && chains.length > 0 ? chains : [networkContext.chain];
const prices = await tokenService.getWhiteListedTokenPrices(chains);

return prices.map((price) => ({
address: price.tokenAddress,
price: price.price,
chain: price.chain,
}));
},
tokenGetHistoricalPrices: async (parent, { addresses }, context) => {
Expand Down
33 changes: 20 additions & 13 deletions modules/token/token.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import { GqlTokenChartDataRange, MutationTokenDeletePriceArgs, MutationTokenDele
import { coingeckoService } from '../coingecko/coingecko.service';
import { networkContext } from '../network/network-context.service';
import { Dictionary } from 'lodash';
import { AllNetworkConfigsKeyedOnChain } from '../network/network-config';

const TOKEN_PRICES_CACHE_KEY = `token:prices:current`;
const TOKEN_PRICES_24H_AGO_CACHE_KEY = `token:prices:24h-ago`;
Expand Down Expand Up @@ -49,27 +50,33 @@ export class TokenService {
return tokens;
}

public async getTokenDefinitions(): Promise<TokenDefinition[]> {
public async getTokenDefinitions(chains: Chain[]): Promise<TokenDefinition[]> {
const tokens = await prisma.prismaToken.findMany({
where: { types: { some: { type: 'WHITE_LISTED' } }, chain: networkContext.chain },
where: { types: { some: { type: 'WHITE_LISTED' } }, chain: { in: chains } },
include: { types: true },
orderBy: { priority: 'desc' },
});

const weth = tokens.find((token) => token.address === networkContext.data.weth.address);
for (const chain of chains) {
const weth = tokens.find(
(token) =>
token.chain === chain && token.address === AllNetworkConfigsKeyedOnChain[chain].data.weth.address,
);

if (weth) {
tokens.push({
...weth,
name: networkContext.data.eth.name,
address: networkContext.data.eth.address,
symbol: networkContext.data.eth.symbol,
});
if (weth) {
tokens.push({
...weth,
name: AllNetworkConfigsKeyedOnChain[chain].data.eth.name,
address: AllNetworkConfigsKeyedOnChain[chain].data.eth.address,
symbol: AllNetworkConfigsKeyedOnChain[chain].data.eth.symbol,
chain: AllNetworkConfigsKeyedOnChain[chain].data.chain.prismaId,
});
}
}

return tokens.map((token) => ({
...token,
chainId: networkContext.data.chain.id,
chainId: AllNetworkConfigsKeyedOnChain[token.chain].data.chain.id,
//TODO: some linear wrapped tokens are tradable. ie: xBOO
tradable: !token.types.find(
(type) => type.type === 'PHANTOM_BPT' || type.type === 'BPT' || type.type === 'LINEAR_WRAPPED_TOKEN',
Expand Down Expand Up @@ -100,7 +107,7 @@ export class TokenService {
return response;
}

public async getWhiteListedTokenPrices(): Promise<PrismaTokenCurrentPrice[]> {
public async getWhiteListedTokenPrices(chains: Chain[]): Promise<PrismaTokenCurrentPrice[]> {
/*const cached = this.cache.get(WHITE_LISTED_TOKEN_PRICES_CACHE_KEY) as PrismaTokenCurrentPrice[] | null;
if (cached) {
Expand All @@ -112,7 +119,7 @@ export class TokenService {
return tokenPrices;*/

return this.tokenPriceService.getWhiteListedCurrentTokenPrices();
return this.tokenPriceService.getWhiteListedCurrentTokenPrices(chains);
}

public async getProtocolTokenPrice(): Promise<string> {
Expand Down

0 comments on commit 9fc299f

Please sign in to comment.