@merkl/api 0.18.5 → 0.18.7

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (30) hide show
  1. package/dist/src/eden/index.d.ts +39 -54
  2. package/dist/src/factories/opportunityMetadata/implementations/Ajna.js +1 -1
  3. package/dist/src/factories/opportunityMetadata/implementations/Badger.js +1 -1
  4. package/dist/src/index.d.ts +7 -10
  5. package/dist/src/modules/v4/campaign/campaign.repository.js +1 -1
  6. package/dist/src/modules/v4/enso/enso.service.js +5 -5
  7. package/dist/src/modules/v4/kyberzap/kyberzap.service.js +5 -5
  8. package/dist/src/modules/v4/opportunity/opportunity.controller.d.ts +0 -7
  9. package/dist/src/modules/v4/opportunity/opportunity.repository.d.ts +0 -7
  10. package/dist/src/modules/v4/opportunity/opportunity.service.d.ts +0 -28
  11. package/dist/src/modules/v4/opportunity/opportunity.service.js +1 -1
  12. package/dist/src/modules/v4/price/price.controller.js +1 -1
  13. package/dist/src/modules/v4/price/price.repository.d.ts +4 -1
  14. package/dist/src/modules/v4/price/price.repository.js +6 -2
  15. package/dist/src/modules/v4/price/price.service.d.ts +4 -1
  16. package/dist/src/modules/v4/price/price.service.js +2 -2
  17. package/dist/src/modules/v4/reward/reward.service.js +1 -1
  18. package/dist/src/modules/v4/router.d.ts +7 -10
  19. package/dist/src/modules/v4/token/token.controller.d.ts +7 -3
  20. package/dist/src/modules/v4/token/token.controller.js +5 -1
  21. package/dist/src/modules/v4/token/token.model.d.ts +1 -0
  22. package/dist/src/modules/v4/token/token.model.js +1 -0
  23. package/dist/src/modules/v4/token/token.repository.d.ts +2 -0
  24. package/dist/src/modules/v4/token/token.repository.js +42 -28
  25. package/dist/src/modules/v4/token/token.service.d.ts +29 -46
  26. package/dist/src/modules/v4/token/token.service.js +120 -106
  27. package/dist/src/routes/v3/app.js +1 -1
  28. package/dist/src/utils/prices/priceService.js +1 -1
  29. package/dist/tsconfig.package.tsbuildinfo +1 -1
  30. package/package.json +1 -1
@@ -93,7 +93,11 @@ export const TokenController = new Elysia({ prefix: "/tokens", detail: { tags: [
93
93
  beforeHandle: BackOfficeGuard,
94
94
  detail: { hide: true },
95
95
  })
96
- .get("/sync", async () => await TokenService.fillTokenAndIconsFromTokenList(), { detail: { hide: true } })
96
+ .post("/icons", async () => await TokenService.tryToFillWithCoingeckoIcons(), {
97
+ headers: AuthorizationHeadersDto,
98
+ beforeHandle: BackOfficeGuard,
99
+ detail: { hide: true },
100
+ })
97
101
  .group("/webhooks", app => {
98
102
  return app.post("/notion", async ({ body }) => TokenService.notionWebhook(body), {
99
103
  body: NotionWebhookDto,
@@ -41,6 +41,7 @@ export declare const GetTokenQueryDto: import("@sinclair/typebox").TObject<{
41
41
  name: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TString>;
42
42
  verified: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TBoolean>;
43
43
  test: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TBoolean>;
44
+ missingIcons: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TBoolean>;
44
45
  }>;
45
46
  export declare const TokenDto: import("@sinclair/typebox").TObject<{
46
47
  address: import("@sinclair/typebox").TString;
@@ -30,6 +30,7 @@ export const GetTokenQueryDto = t.Object({
30
30
  name: t.Optional(t.String()),
31
31
  verified: t.Optional(t.Boolean()),
32
32
  test: t.Optional(t.Boolean()),
33
+ missingIcons: t.Optional(t.Boolean()),
33
34
  });
34
35
  export const TokenDto = t.Object({
35
36
  address: t.String(),
@@ -77,6 +77,8 @@ export declare abstract class TokenRepository {
77
77
  * @param chainId
78
78
  */
79
79
  static updateAddressPrices(address: string, price: number, chainId?: number): Promise<import("database/api/.generated/runtime/library").GetBatchResult>;
80
+ static updateMissingIconsPerSymbol(symbol: string, icon: string): Promise<import("database/api/.generated/runtime/library").GetBatchResult>;
81
+ static fetchIconFromCoingeckoTicker(coingeckoTicker: string): Promise<any>;
80
82
  static findChains(): Promise<Record<string, ChainId>>;
81
83
  /**
82
84
  * create a token on database
@@ -2,35 +2,8 @@ import { getTokenInfo } from "@/libs/tokens/tokenInfo";
2
2
  import { executeSimple } from "@/utils/execute";
3
3
  import { apiDbClient } from "@/utils/prisma";
4
4
  import { NETWORK_LABELS } from "@sdk";
5
+ import axios from "axios";
5
6
  export class TokenRepository {
6
- /**
7
- * Fetch token metadata from onchain
8
- * @param chainId
9
- * @param address
10
- * @returns
11
- */
12
- static async getTokenInfo(token) {
13
- //TODO: replace with onchain module
14
- const calls = getTokenInfo(token.address);
15
- //TODO: replace with onchain module
16
- return executeSimple(token.chainId, calls);
17
- }
18
- /**
19
- * Read token from database
20
- * @param chainId
21
- * @param address
22
- */
23
- static async findUnique(id) {
24
- return (await apiDbClient.token.findUnique({ where: { id } })) ?? undefined;
25
- }
26
- /**
27
- * Read token from database
28
- * @param chainId
29
- * @param address
30
- */
31
- static async findUniqueOrThrow(id) {
32
- return await apiDbClient.token.findUniqueOrThrow({ where: { id } });
33
- }
34
7
  static #transformQueryToPrismaFilters(query) {
35
8
  const ids = query.id ? query.id.map(id => ({ id })) : [];
36
9
  return {
@@ -58,9 +31,38 @@ export class TokenRepository {
58
31
  name: query.name ? { contains: query.name, mode: "insensitive" } : undefined,
59
32
  verified: query.verified ? { equals: query.verified } : undefined,
60
33
  isTest: query.test ? { equals: query.test } : undefined,
34
+ icon: query.missingIcons ? { equals: "" } : undefined,
61
35
  },
62
36
  };
63
37
  }
38
+ /**
39
+ * Fetch token metadata from onchain
40
+ * @param chainId
41
+ * @param address
42
+ * @returns
43
+ */
44
+ static async getTokenInfo(token) {
45
+ //TODO: replace with onchain module
46
+ const calls = getTokenInfo(token.address);
47
+ //TODO: replace with onchain module
48
+ return executeSimple(token.chainId, calls);
49
+ }
50
+ /**
51
+ * Read token from database
52
+ * @param chainId
53
+ * @param address
54
+ */
55
+ static async findUnique(id) {
56
+ return (await apiDbClient.token.findUnique({ where: { id } })) ?? undefined;
57
+ }
58
+ /**
59
+ * Read token from database
60
+ * @param chainId
61
+ * @param address
62
+ */
63
+ static async findUniqueOrThrow(id) {
64
+ return await apiDbClient.token.findUniqueOrThrow({ where: { id } });
65
+ }
64
66
  /**
65
67
  * Read token from database by its symbol
66
68
  * @param symbol
@@ -128,6 +130,18 @@ export class TokenRepository {
128
130
  },
129
131
  });
130
132
  }
133
+ static async updateMissingIconsPerSymbol(symbol, icon) {
134
+ return await apiDbClient.token.updateMany({
135
+ data: { icon },
136
+ where: {
137
+ symbol: symbol,
138
+ icon: "",
139
+ },
140
+ });
141
+ }
142
+ static async fetchIconFromCoingeckoTicker(coingeckoTicker) {
143
+ return (await axios.get(`https://api.coingecko.com/api/v3/coins/${coingeckoTicker}`)).data.image.small;
144
+ }
131
145
  static async findChains() {
132
146
  const tokens = await apiDbClient.token.findMany({
133
147
  select: { chainId: true, id: true },
@@ -1,7 +1,7 @@
1
1
  import type { Pricer } from "@/utils/pricer";
2
2
  import { type ChainId } from "@sdk";
3
- import type { NotionWebhookModel } from "./token.model";
4
- import type { CreateTokenModel, GetTokenQueryModel, Token, TokenModel, TokenUnique, UpdateTokenModel } from "./token.model";
3
+ import type { CreateTokenModel, NotionWebhookModel } from "./token.model";
4
+ import type { GetTokenQueryModel, Token, TokenModel, TokenUnique, UpdateTokenModel } from "./token.model";
5
5
  import { TokenRepository } from "./token.repository";
6
6
  export declare abstract class TokenService {
7
7
  static hashId(token: TokenUnique): string;
@@ -54,6 +54,7 @@ export declare abstract class TokenService {
54
54
  balance: bigint;
55
55
  })[]>;
56
56
  static fetchOnChain(token: TokenModel): Promise<Omit<Token["model"], "id">>;
57
+ static tryToFillWithCoingeckoIcons(): Promise<void>;
57
58
  static fetchManyOnChain(chainId: ChainId, addresses: string[]): Promise<{
58
59
  [address: string]: Omit<{
59
60
  symbol: string;
@@ -91,49 +92,6 @@ export declare abstract class TokenService {
91
92
  * @param excludeAddresses to not update symbols that defined using addresses
92
93
  */
93
94
  static updatePrices(pricer: Pricer): Promise<void>;
94
- /**
95
- * Get all tokens from https://github.com/AngleProtocol/angle-token-list and override icons from it
96
- * TODO: use the bucket
97
- */
98
- static fillTokenAndIconsFromTokenList(): Promise<void>;
99
- /**
100
- * Create token on database
101
- * @param chainId
102
- * @param address
103
- */
104
- static create(token: Omit<Token["model"], "id">): Promise<({
105
- symbol: string;
106
- id: string;
107
- name: string | null;
108
- icon: string;
109
- chainId: number;
110
- address: string;
111
- decimals: number;
112
- verified: boolean;
113
- isTest: boolean;
114
- isNative: boolean;
115
- } & {
116
- price?: number | null | undefined;
117
- }) | undefined>;
118
- /**
119
- * Fetches symbol, address, decimals and creates token on database
120
- * @param chainId
121
- * @param address
122
- */
123
- static fillAndCreate(token: CreateTokenModel): Promise<({
124
- symbol: string;
125
- id: string;
126
- name: string | null;
127
- icon: string;
128
- chainId: number;
129
- address: string;
130
- decimals: number;
131
- verified: boolean;
132
- isTest: boolean;
133
- isNative: boolean;
134
- } & {
135
- price?: number | null | undefined;
136
- }) | undefined>;
137
95
  /**
138
96
  * Read token from database
139
97
  * @param chainId
@@ -210,7 +168,7 @@ export declare abstract class TokenService {
210
168
  * @param chainId
211
169
  * @param address
212
170
  */
213
- static getManyOrCreate(tokens: TokenModel[]): Promise<(Token["model"] | undefined)[]>;
171
+ static findManyOrCreate(tokens: TokenModel[]): Promise<(Token["model"] | undefined)[]>;
214
172
  static getValidRewardTokens(chainId: number): Promise<{
215
173
  minimumAmountPerHour: any;
216
174
  symbol: string;
@@ -254,4 +212,29 @@ export declare abstract class TokenService {
254
212
  isNative: boolean;
255
213
  price: number | null;
256
214
  }>;
215
+ /**
216
+ * Fetches symbol, address, decimals and creates token on database
217
+ * @param chainId
218
+ * @param address
219
+ */
220
+ static fillAndCreate(token: CreateTokenModel): Promise<({
221
+ symbol: string;
222
+ id: string;
223
+ name: string | null;
224
+ icon: string;
225
+ chainId: number;
226
+ address: string;
227
+ decimals: number;
228
+ verified: boolean;
229
+ isTest: boolean;
230
+ isNative: boolean;
231
+ } & {
232
+ price?: number | null | undefined;
233
+ }) | undefined>;
234
+ /**
235
+ * @deprecated Should be useless now that the token list is not used anymore
236
+ * Get all tokens from https://github.com/AngleProtocol/angle-token-list and override icons from it
237
+ * TODO: use the bucket
238
+ */
239
+ static fillTokenAndIconsFromTokenList(): Promise<void>;
257
240
  }
@@ -51,7 +51,7 @@ export class TokenService {
51
51
  * Fetches tokens and include balances
52
52
  */
53
53
  static async fetchTokensAndBalances(chainId, userAddress, addresses) {
54
- const tokens = await TokenService.getManyOrCreate(addresses?.map(address => ({ chainId, address })));
54
+ const tokens = await TokenService.findManyOrCreate(addresses?.map(address => ({ chainId, address })));
55
55
  return TokenService.fetchBalances(chainId, userAddress, tokens.filter(t => t !== undefined));
56
56
  }
57
57
  /**
@@ -63,7 +63,7 @@ export class TokenService {
63
63
  const verifiedTokens = await TokenService.findMany({ chainId: chainId, verified: true });
64
64
  const nativeTokens = await TokenService.findMany({ chainId: chainId, isNative: true });
65
65
  const additionalTokens = !!additionalTokenAddresses?.length
66
- ? await TokenService.getManyOrCreate(additionalTokenAddresses?.map(address => ({ chainId, address })))
66
+ ? await TokenService.findManyOrCreate(additionalTokenAddresses?.map(address => ({ chainId, address })))
67
67
  : [];
68
68
  const allTokens = verifiedTokens
69
69
  .concat(additionalTokens.filter(t => t !== undefined))
@@ -72,7 +72,6 @@ export class TokenService {
72
72
  }
73
73
  static async fetchOnChain(token) {
74
74
  const onchainData = await TokenRepository.getTokenInfo(token);
75
- //TODO: find a way to get the icon
76
75
  return {
77
76
  chainId: token.chainId,
78
77
  address: token.address,
@@ -80,9 +79,36 @@ export class TokenService {
80
79
  ...Object.assign({ name: "unknown", decimals: 18, symbol: "UNKNOWN", verified: false, isTest: false, isNative: false }, onchainData),
81
80
  };
82
81
  }
82
+ static async tryToFillWithCoingeckoIcons() {
83
+ // 1 - Find coingecko price sources
84
+ let priceSources = await PriceService.findManyPriceSources({ method: "COINGECKO" });
85
+ // 2 - Find tokens with missing logos
86
+ const missingIcons = await TokenService.findMany({ missingIcons: true });
87
+ // 3 - Do the intersection of both
88
+ priceSources = priceSources.filter(p => !!missingIcons.find(t => t.symbol === p.symbol));
89
+ log.info(`found ${priceSources.length} tokens with missing icons on coingecko.`);
90
+ // 4 - Loop through each and try to get the icon
91
+ for (const priceSource of priceSources) {
92
+ const coingeckoTicker = priceSource.args?.ticker;
93
+ if (!!coingeckoTicker) {
94
+ try {
95
+ const icon = await TokenRepository.fetchIconFromCoingeckoTicker(coingeckoTicker);
96
+ if (icon.length > 0) {
97
+ const res = await TokenRepository.updateMissingIconsPerSymbol(priceSource.symbol, icon);
98
+ log.info(`updated ${res.count} tokens with icon ${icon} ${priceSource.symbol}`);
99
+ }
100
+ }
101
+ catch (e) {
102
+ console.error(e);
103
+ }
104
+ // Avoid rate limits, wait 1 min
105
+ await new Promise(resolve => setTimeout(resolve, 60_000));
106
+ }
107
+ }
108
+ }
83
109
  static async fetchManyOnChain(chainId, addresses) {
84
110
  const tokens = {};
85
- //Batch onchain calls together when multiples
111
+ // Batch onchain calls together when multiples
86
112
  for (const address of addresses) {
87
113
  tokens[address] = await TokenService.fetchOnChain({ chainId, address });
88
114
  }
@@ -128,101 +154,6 @@ export class TokenService {
128
154
  await TokenService.updateAddressPrices(address, price);
129
155
  }
130
156
  }
131
- /**
132
- * Get all tokens from https://github.com/AngleProtocol/angle-token-list and override icons from it
133
- * TODO: use the bucket
134
- */
135
- static async fillTokenAndIconsFromTokenList() {
136
- const tokenList = await getTokensListWithCache();
137
- for (const chain of Object.keys(tokenList)) {
138
- for (const [symbol, token] of Object.entries(tokenList[chain])) {
139
- if (!(await TokenRepository.findUnique(TokenService.hashId({ chainId: Number.parseInt(chain), address: token.address })))) {
140
- try {
141
- const res = await TokenRepository.create({
142
- id: TokenService.hashId({ chainId: Number.parseInt(chain), address: token.address }),
143
- chainId: Number.parseInt(chain),
144
- address: token.address,
145
- name: token.name,
146
- symbol: token.symbol,
147
- verified: true,
148
- decimals: token.decimals,
149
- icon: token.logoURI,
150
- isTest: false,
151
- isNative: false,
152
- });
153
- log.local(`Token created: ${res?.symbol} on ${NETWORK_LABELS[Number.parseInt(chain)]}`);
154
- }
155
- catch (e) {
156
- console.error(e);
157
- }
158
- }
159
- try {
160
- await apiDbClient.token.update({
161
- data: {
162
- chainId: Number.parseInt(chain),
163
- address: token.address,
164
- name: token.name,
165
- symbol: token.symbol,
166
- verified: true,
167
- decimals: token.decimals,
168
- icon: token.logoURI,
169
- },
170
- where: {
171
- chainId_address: {
172
- chainId: Number.parseInt(chain),
173
- address: token.address,
174
- },
175
- },
176
- });
177
- }
178
- catch (e) {
179
- console.error(e);
180
- }
181
- try {
182
- const tokensWithSameSymbol = await apiDbClient.token.findMany({
183
- select: { chainId: true, address: true },
184
- where: { symbol: { equals: symbol, mode: "insensitive" } },
185
- });
186
- for (const dbToken of tokensWithSameSymbol) {
187
- await apiDbClient.token.update({
188
- data: { icon: token.logoURI },
189
- where: {
190
- chainId_address: {
191
- chainId: dbToken.chainId,
192
- address: dbToken.address,
193
- },
194
- },
195
- });
196
- }
197
- }
198
- catch (_err) { }
199
- }
200
- }
201
- }
202
- /**
203
- * Create token on database
204
- * @param chainId
205
- * @param address
206
- */
207
- static async create(token) {
208
- const id = TokenService.hashId(token);
209
- return TokenRepository.upsert({ ...token, id });
210
- }
211
- /**
212
- * Fetches symbol, address, decimals and creates token on database
213
- * @param chainId
214
- * @param address
215
- */
216
- static async fillAndCreate(token) {
217
- try {
218
- const id = TokenService.hashId(token);
219
- const filledData = await TokenService.fetchOnChain({ address: token.address, chainId: token.chainId });
220
- return await TokenRepository.upsert({ ...filledData, ...token, id });
221
- }
222
- catch (e) {
223
- console.error(e);
224
- }
225
- }
226
157
  /**
227
158
  * Read token from database
228
159
  * @param chainId
@@ -252,7 +183,7 @@ export class TokenService {
252
183
  * @returns the cumulated dollar value of all tokens
253
184
  */
254
185
  static async getValue(tokenAmounts) {
255
- const tokens = await TokenService.getManyOrCreate(tokenAmounts.map(({ address, chainId }) => ({ address, chainId })));
186
+ const tokens = await TokenService.findManyOrCreate(tokenAmounts.map(({ address, chainId }) => ({ address, chainId })));
256
187
  return tokenAmounts.reduce((sum, { amount, address, chainId }) => {
257
188
  const token = tokens
258
189
  .filter(t => t !== undefined)
@@ -290,7 +221,7 @@ export class TokenService {
290
221
  * @param chainId
291
222
  * @param address
292
223
  */
293
- static async getManyOrCreate(tokens) {
224
+ static async findManyOrCreate(tokens) {
294
225
  return await Promise.all(tokens.map(async (token) => {
295
226
  const id = TokenService.hashId(token);
296
227
  try {
@@ -321,10 +252,6 @@ export class TokenService {
321
252
  }, chainId);
322
253
  }
323
254
  static async update(id, data) {
324
- // let iconUri = data.icon;
325
- // if (data.iconFile) {
326
- // iconUri = await BucketService.upload("merkl-assets", `/tokens/${id}`, data.iconFile.stream(), true);
327
- // }
328
255
  return await TokenRepository.update(id, data);
329
256
  }
330
257
  static async notionWebhook(body) {
@@ -342,7 +269,7 @@ export class TokenService {
342
269
  const isVerified = properties.Verified.checkbox;
343
270
  const coingeckoApiId = properties["CoinGecko API ID"].rich_text[0].plain_text;
344
271
  const byteArray = await iconFile.bytes();
345
- const [token] = await TokenService.getManyOrCreate([
272
+ const [token] = await TokenService.findManyOrCreate([
346
273
  {
347
274
  chainId,
348
275
  address,
@@ -381,4 +308,91 @@ export class TokenService {
381
308
  verified: isVerified,
382
309
  });
383
310
  }
311
+ /**
312
+ * Fetches symbol, address, decimals and creates token on database
313
+ * @param chainId
314
+ * @param address
315
+ */
316
+ static async fillAndCreate(token) {
317
+ try {
318
+ const id = TokenService.hashId(token);
319
+ const filledData = await TokenService.fetchOnChain({ address: token.address, chainId: token.chainId });
320
+ return await TokenRepository.upsert({ ...filledData, ...token, id });
321
+ }
322
+ catch (e) {
323
+ console.error(e);
324
+ }
325
+ }
326
+ /**
327
+ * @deprecated Should be useless now that the token list is not used anymore
328
+ * Get all tokens from https://github.com/AngleProtocol/angle-token-list and override icons from it
329
+ * TODO: use the bucket
330
+ */
331
+ static async fillTokenAndIconsFromTokenList() {
332
+ const tokenList = await getTokensListWithCache();
333
+ for (const chain of Object.keys(tokenList)) {
334
+ for (const [symbol, token] of Object.entries(tokenList[chain])) {
335
+ if (!(await TokenRepository.findUnique(TokenService.hashId({ chainId: Number.parseInt(chain), address: token.address })))) {
336
+ try {
337
+ const res = await TokenRepository.create({
338
+ id: TokenService.hashId({ chainId: Number.parseInt(chain), address: token.address }),
339
+ chainId: Number.parseInt(chain),
340
+ address: token.address,
341
+ name: token.name,
342
+ symbol: token.symbol,
343
+ verified: true,
344
+ decimals: token.decimals,
345
+ icon: token.logoURI,
346
+ isTest: false,
347
+ isNative: false,
348
+ });
349
+ log.local(`Token created: ${res?.symbol} on ${NETWORK_LABELS[Number.parseInt(chain)]}`);
350
+ }
351
+ catch (e) {
352
+ console.error(e);
353
+ }
354
+ }
355
+ try {
356
+ await apiDbClient.token.update({
357
+ data: {
358
+ chainId: Number.parseInt(chain),
359
+ address: token.address,
360
+ name: token.name,
361
+ symbol: token.symbol,
362
+ verified: true,
363
+ decimals: token.decimals,
364
+ icon: token.logoURI,
365
+ },
366
+ where: {
367
+ chainId_address: {
368
+ chainId: Number.parseInt(chain),
369
+ address: token.address,
370
+ },
371
+ },
372
+ });
373
+ }
374
+ catch (e) {
375
+ console.error(e);
376
+ }
377
+ try {
378
+ const tokensWithSameSymbol = await apiDbClient.token.findMany({
379
+ select: { chainId: true, address: true },
380
+ where: { symbol: { equals: symbol, mode: "insensitive" } },
381
+ });
382
+ for (const dbToken of tokensWithSameSymbol) {
383
+ await apiDbClient.token.update({
384
+ data: { icon: token.logoURI },
385
+ where: {
386
+ chainId_address: {
387
+ chainId: dbToken.chainId,
388
+ address: dbToken.address,
389
+ },
390
+ },
391
+ });
392
+ }
393
+ }
394
+ catch (_err) { }
395
+ }
396
+ }
397
+ }
384
398
  }
@@ -19,7 +19,7 @@ export default (app) => app.get("/app", async () => {
19
19
  if (!json.tokens[token.chainId]) {
20
20
  json.tokens[token.chainId] = {};
21
21
  }
22
- if (!json.tokens[token.chainId][token.address]) {
22
+ if (!json.tokens[token.chainId][token.address] && token.icon?.length > 0) {
23
23
  json.tokens[token.chainId][token.address] = {
24
24
  address: token.address,
25
25
  chainId: token.chainId,
@@ -26,7 +26,7 @@ export default class PriceService {
26
26
  });
27
27
  };
28
28
  async fetchPrices() {
29
- const tokenPriceSources = await PriceSourceService.getManyPriceSources();
29
+ const tokenPriceSources = await PriceSourceService.findManyPriceSources();
30
30
  /**
31
31
  * @description Factory pricer's call to get prices from different sources
32
32
  */