Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add chains to tokens and token prices queries #483

Merged
merged 3 commits into from
Oct 18, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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