@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.
- package/dist/src/eden/index.d.ts +84 -142
- package/dist/src/index.d.ts +16 -30
- package/dist/src/modules/v4/coingecko/coingecko.model.d.ts +0 -0
- package/dist/src/modules/v4/coingecko/coingecko.model.js +1 -0
- package/dist/src/modules/v4/coingecko/coingecko.repository.d.ts +14 -0
- package/dist/src/modules/v4/coingecko/coingecko.repository.js +9 -0
- package/dist/src/modules/v4/coingecko/coingecko.service.d.ts +16 -0
- package/dist/src/modules/v4/coingecko/coingecko.service.js +65 -0
- package/dist/src/modules/v4/router.d.ts +16 -30
- package/dist/src/modules/v4/token/token.controller.d.ts +3 -15
- package/dist/src/modules/v4/token/token.controller.js +0 -5
- package/dist/src/modules/v4/token/token.model.d.ts +1 -0
- package/dist/src/modules/v4/token/token.model.js +1 -0
- package/dist/src/modules/v4/token/token.repository.js +1 -0
- package/dist/src/modules/v4/token/token.service.d.ts +1 -2
- package/dist/src/modules/v4/token/token.service.js +21 -37
- package/dist/src/modules/v4/uniswap/uniswap.controller.d.ts +13 -15
- package/dist/src/modules/v4/uniswap/uniswap.controller.js +2 -2
- package/dist/src/scripts/fill-coingecko-data.d.ts +1 -0
- package/dist/src/scripts/fill-coingecko-data.js +3 -0
- package/dist/tsconfig.package.tsbuildinfo +1 -1
- package/package.json +1 -1
@@ -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
|
-
}
|
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
|
-
}
|
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
|
-
|
263
|
-
|
264
|
-
|
265
|
-
|
266
|
-
|
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
|
345
|
-
const
|
346
|
-
|
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
|
349
|
-
|
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
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
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("/
|
10
|
-
return app.get("
|
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 {};
|