@merkl/api 0.20.40 → 0.20.42

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.
@@ -156,6 +156,7 @@ export declare const TokenController: Elysia<"/tokens", false, {
156
156
  isNative?: boolean | undefined;
157
157
  test?: boolean | undefined;
158
158
  missingIcons?: boolean | undefined;
159
+ missingPrice?: boolean | undefined;
159
160
  };
160
161
  headers: unknown;
161
162
  response: {
@@ -193,6 +194,7 @@ export declare const TokenController: Elysia<"/tokens", false, {
193
194
  isNative?: boolean | undefined;
194
195
  test?: boolean | undefined;
195
196
  missingIcons?: boolean | undefined;
197
+ missingPrice?: boolean | undefined;
196
198
  };
197
199
  headers: unknown;
198
200
  response: {
@@ -230,7 +232,7 @@ export declare const TokenController: Elysia<"/tokens", false, {
230
232
  isPoint: boolean;
231
233
  isNative: boolean;
232
234
  price: number | null;
233
- } | undefined;
235
+ };
234
236
  };
235
237
  };
236
238
  };
@@ -271,20 +273,6 @@ export declare const TokenController: Elysia<"/tokens", false, {
271
273
  };
272
274
  };
273
275
  };
274
- } & {
275
- icons: {
276
- post: {
277
- body: unknown;
278
- params: {};
279
- query: unknown;
280
- headers: {
281
- authorization: string;
282
- };
283
- response: {
284
- 200: void;
285
- };
286
- };
287
- };
288
276
  } & {
289
277
  webhooks: {
290
278
  notion: {
@@ -92,11 +92,6 @@ export const TokenController = new Elysia({ prefix: "/tokens", detail: { tags: [
92
92
  headers: AuthorizationHeadersDto,
93
93
  beforeHandle: BackOfficeGuard,
94
94
  detail: { hide: true },
95
- })
96
- .post("/icons", async () => await TokenService.tryToFillWithCoingeckoIcons(), {
97
- headers: AuthorizationHeadersDto,
98
- beforeHandle: BackOfficeGuard,
99
- detail: { hide: true },
100
95
  })
101
96
  .group("/webhooks", app => {
102
97
  return app.post("/notion", async ({ body }) => TokenService.notionWebhook(body), {
@@ -42,6 +42,7 @@ export declare const GetTokenQueryDto: import("@sinclair/typebox").TObject<{
42
42
  verified: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TBoolean>;
43
43
  test: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TBoolean>;
44
44
  missingIcons: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TBoolean>;
45
+ missingPrice: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TBoolean>;
45
46
  }>;
46
47
  export declare const TokenDto: import("@sinclair/typebox").TObject<{
47
48
  address: import("@sinclair/typebox").TString;
@@ -31,6 +31,7 @@ export const GetTokenQueryDto = t.Object({
31
31
  verified: t.Optional(t.Boolean()),
32
32
  test: t.Optional(t.Boolean()),
33
33
  missingIcons: t.Optional(t.Boolean()),
34
+ missingPrice: t.Optional(t.Boolean()),
34
35
  });
35
36
  export const TokenDto = t.Object({
36
37
  address: t.String(),
@@ -30,6 +30,7 @@ export class TokenRepository {
30
30
  verified: query.verified ? { equals: query.verified } : undefined,
31
31
  isTest: query.test ? { equals: query.test } : undefined,
32
32
  icon: query.missingIcons ? { equals: "" } : undefined,
33
+ price: query.missingPrice ? { equals: null } : undefined,
33
34
  },
34
35
  };
35
36
  }
@@ -56,7 +56,6 @@ export declare abstract class TokenService {
56
56
  balance: bigint;
57
57
  })[]>;
58
58
  static fetchOnChain(token: TokenModel): Promise<Omit<Token["model"], "id">>;
59
- static tryToFillWithCoingeckoIcons(): Promise<void>;
60
59
  static fetchManyOnChain(chainId: ChainId, addresses: string[]): Promise<{
61
60
  [address: string]: Omit<{
62
61
  symbol: string;
@@ -256,7 +255,7 @@ export declare abstract class TokenService {
256
255
  isPoint: boolean;
257
256
  isNative: boolean;
258
257
  price: number | null;
259
- } | undefined>;
258
+ }>;
260
259
  /**
261
260
  * @deprecated Should be useless now that the token list is not used anymore
262
261
  * Get all tokens from https://github.com/AngleProtocol/angle-token-list and override icons from it
@@ -10,6 +10,7 @@ import { apiDbClient } from "@db";
10
10
  import { Prisma } from "@db/api";
11
11
  import { ChainInteractionService, DistributionCreatorService, NETWORK_LABELS, bigIntToNumber, } from "@sdk";
12
12
  import { getAddress, parseUnits } from "viem";
13
+ import { CoingeckoService } from "../coingecko/coingecko.service";
13
14
  import { TokenRepository } from "./token.repository";
14
15
  export class TokenService {
15
16
  static hashId(token) {
@@ -93,33 +94,6 @@ export class TokenService {
93
94
  }, onchainData),
94
95
  };
95
96
  }
96
- static async tryToFillWithCoingeckoIcons() {
97
- // 1 - Find coingecko price sources
98
- let priceSources = await PriceService.findManyPriceSources({ method: "COINGECKO" });
99
- // 2 - Find tokens with missing logos
100
- const missingIcons = await TokenService.findMany({ missingIcons: true });
101
- // 3 - Do the intersection of both
102
- priceSources = priceSources.filter(p => !!missingIcons.find(t => t.symbol === p.symbol));
103
- log.info(`found ${priceSources.length} tokens with missing icons on coingecko.`);
104
- // 4 - Loop through each and try to get the icon
105
- for (const priceSource of priceSources) {
106
- const coingeckoTicker = priceSource.args?.ticker;
107
- if (!!coingeckoTicker) {
108
- try {
109
- const icon = await TokenRepository.fetchIconFromCoingeckoTicker(coingeckoTicker);
110
- if (icon.length > 0) {
111
- const res = await TokenRepository.updateMissingIconsPerSymbol(priceSource.symbol, icon);
112
- log.info(`updated ${res.count} tokens with icon ${icon} ${priceSource.symbol}`);
113
- }
114
- }
115
- catch (e) {
116
- console.error(e);
117
- }
118
- // Avoid rate limits, wait 1 min
119
- await new Promise(resolve => setTimeout(resolve, 60_000));
120
- }
121
- }
122
- }
123
97
  static async fetchManyOnChain(chainId, addresses) {
124
98
  const tokens = {};
125
99
  // Batch onchain calls together when multiples
@@ -259,11 +233,11 @@ export class TokenService {
259
233
  }
260
234
  catch (err) {
261
235
  if (err instanceof Prisma.PrismaClientKnownRequestError && err.code === "P2025") {
262
- const newToken = Object.assign(await TokenService.fetchOnChain(token), { id });
263
- if (!newToken) {
264
- throw new HttpError(`Failed to fetch on-chain data for token ${token.address} on chain ${token.chainId}).`);
265
- }
266
- return TokenService.format(await TokenRepository.upsert(newToken));
236
+ return TokenService.format(await TokenService.fillAndCreate({
237
+ ...token,
238
+ verified: false,
239
+ icon: "",
240
+ }));
267
241
  }
268
242
  }
269
243
  throw new HttpError(`Failed to fetch or create token ${token.address} on chain ${token.chainId}.`);
@@ -340,14 +314,24 @@ export class TokenService {
340
314
  * @param address
341
315
  */
342
316
  static async fillAndCreate(token) {
317
+ const id = TokenService.hashId(token);
318
+ const filledData = await TokenService.fetchOnChain({ address: token.address, chainId: token.chainId });
343
319
  try {
344
- const id = TokenService.hashId(token);
345
- const filledData = await TokenService.fetchOnChain({ address: token.address, chainId: token.chainId });
346
- return await TokenRepository.upsert({ ...filledData, ...token, id });
320
+ const coingeckoToken = await CoingeckoService.findList();
321
+ const coingeckoTokenData = coingeckoToken.find(t => t.symbol === filledData.symbol && t.name === filledData.name);
322
+ if (!!coingeckoTokenData) {
323
+ await CoingeckoService.createPriceSourceForSymbolIfMissing(filledData.symbol, coingeckoTokenData.id);
324
+ if (!token.icon || token.icon === "") {
325
+ const coingeckoIcon = (await CoingeckoService.findMarkets([coingeckoTokenData.id]))[0].image;
326
+ token.icon = coingeckoIcon;
327
+ log.info(`completed with coingecko icon: ${coingeckoIcon}`);
328
+ }
329
+ }
347
330
  }
348
- catch (e) {
349
- console.error(e);
331
+ catch {
332
+ log.warn("coingecko token autocompletion failed");
350
333
  }
334
+ return await TokenRepository.upsert({ ...filledData, ...token, id });
351
335
  }
352
336
  /**
353
337
  * @deprecated Should be useless now that the token list is not used anymore
@@ -13,21 +13,19 @@ export declare const UniswapController: Elysia<"uniswap", false, {
13
13
  macroFn: {};
14
14
  }, {
15
15
  uniswap: {
16
- v3: {
17
- reward: {
18
- get: {
19
- body: unknown;
20
- params: {};
21
- query: {
22
- poolAddress?: string | undefined;
23
- positionId?: string | undefined;
24
- address: string;
25
- };
26
- headers: unknown;
27
- response: {
28
- 200: {
29
- [x: string]: Record<string, any[]>;
30
- };
16
+ reward: {
17
+ get: {
18
+ body: unknown;
19
+ params: {};
20
+ query: {
21
+ poolAddress?: string | undefined;
22
+ positionId?: string | undefined;
23
+ address: string;
24
+ };
25
+ headers: unknown;
26
+ response: {
27
+ 200: {
28
+ [x: string]: Record<string, any[]>;
31
29
  };
32
30
  };
33
31
  };
@@ -6,8 +6,8 @@ export const UniswapController = new Elysia({
6
6
  prefix: "uniswap",
7
7
  detail: { tags: ["Uniswap"] },
8
8
  })
9
- .group("/v3", app => {
10
- return app.get("/reward", async ({ query }) => {
9
+ .group("/reward", app => {
10
+ return app.get("", async ({ query }) => {
11
11
  return await UniswapService.findV3RewardsPerPosition(query);
12
12
  }, {
13
13
  query: RewardsPerV3PositionDto,
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,3 @@
1
+ import { CoingeckoService } from "@/modules/v4/coingecko/coingecko.service";
2
+ await CoingeckoService.fillTokensWithCoingeckoData();
3
+ process.exit(0);