@merkl/api 0.19.49 → 0.20.0

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.
@@ -1893,11 +1893,15 @@ declare const eden: {
1893
1893
  data: {
1894
1894
  properties: {
1895
1895
  "Icon (Required)": {
1896
- files: {
1896
+ files: ({
1897
1897
  file: {
1898
1898
  url: string;
1899
1899
  };
1900
- }[];
1900
+ } | {
1901
+ external: {
1902
+ url: string;
1903
+ };
1904
+ })[];
1901
1905
  };
1902
1906
  "Address (in checksum format) (Required)": {
1903
1907
  rich_text: {
@@ -5631,11 +5635,15 @@ declare const eden: {
5631
5635
  data: {
5632
5636
  properties: {
5633
5637
  "Icon (Required)": {
5634
- files: {
5638
+ files: ({
5635
5639
  file: {
5636
5640
  url: string;
5637
5641
  };
5638
- }[];
5642
+ } | {
5643
+ external: {
5644
+ url: string;
5645
+ };
5646
+ })[];
5639
5647
  };
5640
5648
  "Address (in checksum format) (Required)": {
5641
5649
  rich_text: {
@@ -10435,11 +10443,15 @@ export declare const MerklApi: (domain: string | import("elysia").default<"", fa
10435
10443
  data: {
10436
10444
  properties: {
10437
10445
  "Icon (Required)": {
10438
- files: {
10446
+ files: ({
10439
10447
  file: {
10440
10448
  url: string;
10441
10449
  };
10442
- }[];
10450
+ } | {
10451
+ external: {
10452
+ url: string;
10453
+ };
10454
+ })[];
10443
10455
  };
10444
10456
  "Address (in checksum format) (Required)": {
10445
10457
  rich_text: {
@@ -15559,11 +15571,15 @@ export declare const MerklApi: (domain: string | import("elysia").default<"", fa
15559
15571
  data: {
15560
15572
  properties: {
15561
15573
  "Icon (Required)": {
15562
- files: {
15574
+ files: ({
15563
15575
  file: {
15564
15576
  url: string;
15565
15577
  };
15566
- }[];
15578
+ } | {
15579
+ external: {
15580
+ url: string;
15581
+ };
15582
+ })[];
15567
15583
  };
15568
15584
  "Address (in checksum format) (Required)": {
15569
15585
  rich_text: {
@@ -19297,11 +19313,15 @@ export declare const MerklApi: (domain: string | import("elysia").default<"", fa
19297
19313
  data: {
19298
19314
  properties: {
19299
19315
  "Icon (Required)": {
19300
- files: {
19316
+ files: ({
19301
19317
  file: {
19302
19318
  url: string;
19303
19319
  };
19304
- }[];
19320
+ } | {
19321
+ external: {
19322
+ url: string;
19323
+ };
19324
+ })[];
19305
19325
  };
19306
19326
  "Address (in checksum format) (Required)": {
19307
19327
  rich_text: {
@@ -2296,11 +2296,15 @@ declare const app: Elysia<"", false, {
2296
2296
  data: {
2297
2297
  properties: {
2298
2298
  "Icon (Required)": {
2299
- files: {
2299
+ files: ({
2300
2300
  file: {
2301
2301
  url: string;
2302
2302
  };
2303
- }[];
2303
+ } | {
2304
+ external: {
2305
+ url: string;
2306
+ };
2307
+ })[];
2304
2308
  };
2305
2309
  "Address (in checksum format) (Required)": {
2306
2310
  rich_text: {
@@ -152,4 +152,4 @@ export const main = async () => {
152
152
  // if (failedBatches.length === 0) await file.delete();
153
153
  process.exit(0);
154
154
  };
155
- main();
155
+ await main();
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,20 @@
1
+ import { CacheService } from "@/modules/v4/cache";
2
+ import { TTLPresets } from "@/modules/v4/cache/cache.model";
3
+ import { ChainService } from "@/modules/v4/chain/chain.service";
4
+ import { MerklRootRepository } from "@/modules/v4/merklRoot/merklRoot.repository";
5
+ import { NETWORK_LABELS, log } from "@sdk";
6
+ const main = async () => {
7
+ try {
8
+ const chains = await ChainService.getSupportedIds();
9
+ const promises = [];
10
+ for (const chain of chains)
11
+ promises.push(CacheService.set(TTLPresets.MIN_10, MerklRootRepository.fetch, chain).catch(_err => log.warn(`RPC calls cache update failed for ${NETWORK_LABELS[chain]}.`)));
12
+ await Promise.allSettled(promises);
13
+ process.exit(0);
14
+ }
15
+ catch (err) {
16
+ console.error(err);
17
+ process.exit(1);
18
+ }
19
+ };
20
+ await main();
@@ -19,6 +19,13 @@ export declare class MerklRootService {
19
19
  * @returns object with live and last tree roots
20
20
  */
21
21
  static fetch(chainId: ChainId): Promise<any>;
22
+ static fetchFromCache(chainId: ChainId): Promise<{
23
+ live: any;
24
+ tree: any;
25
+ lastTree: any;
26
+ endOfDisputePeriod: any;
27
+ disputer: any;
28
+ }>;
22
29
  /**
23
30
  * Fetch all roots for the provided chains
24
31
  * @param chainIds to fetch roots for
@@ -1,3 +1,4 @@
1
+ import { HttpError } from "@/errors";
1
2
  import { log } from "@/utils/logger";
2
3
  import { NETWORK_LABELS, withTimeout } from "@sdk";
3
4
  import { CacheService } from "../cache";
@@ -29,6 +30,19 @@ export class MerklRootService {
29
30
  throw e;
30
31
  }
31
32
  }
33
+ static async fetchFromCache(chainId) {
34
+ try {
35
+ const data = await CacheService.get(MerklRootRepository.fetch, [chainId]);
36
+ if (data === null)
37
+ throw new Error("DATA_NOT_FOUND");
38
+ return data;
39
+ }
40
+ catch (err) {
41
+ if (err && err instanceof Error && err.message === "DATA_NOT_FOUND")
42
+ throw new HttpError(`Failed to fetch data for chain ${chainId}.`, 500);
43
+ return await MerklRootRepository.fetch(chainId);
44
+ }
45
+ }
32
46
  /**
33
47
  * Fetch all roots for the provided chains
34
48
  * @param chainIds to fetch roots for
@@ -38,7 +52,7 @@ export class MerklRootService {
38
52
  return await CacheService.wrap(TTLPresets.MIN_1, async () => {
39
53
  let ids = chainIds ?? (await ChainService.getIds());
40
54
  /** Fetch current Merkle Roots */
41
- const merkleRootsPromises = await Promise.allSettled(ids.map(chainId => MerklRootService.fetch(chainId)));
55
+ const merkleRootsPromises = await Promise.allSettled(ids.map(chainId => MerklRootService.fetchFromCache(chainId)));
42
56
  /** Filter out unsuccessful chainIds */
43
57
  ids = ids.filter((_, index) => merkleRootsPromises[index].status === "fulfilled");
44
58
  const roots = merkleRootsPromises
@@ -237,7 +237,7 @@ export class RewardService {
237
237
  if (isBlacklisted)
238
238
  return res;
239
239
  /** Fetch current Merkle Roots */
240
- const merkleRootsPromises = await Promise.allSettled(chainIds.map(chainId => MerklRootService.fetch(chainId)));
240
+ const merkleRootsPromises = await Promise.allSettled(chainIds.map(chainId => MerklRootService.fetchFromCache(chainId)));
241
241
  /** Filter out unsuccessful chainIds */
242
242
  chainIds = chainIds.filter((_, index) => merkleRootsPromises[index].status === "fulfilled");
243
243
  const merkleRoots = merkleRootsPromises
@@ -288,7 +288,7 @@ export class RewardService {
288
288
  }
289
289
  }
290
290
  static async countOnChain(chainId) {
291
- const roots = await MerklRootService.fetch(chainId);
291
+ const roots = await MerklRootService.fetchFromCache(chainId);
292
292
  const promises = [
293
293
  RewardRepository.countRewardAndBreakdownOnChain(chainId, roots.tree),
294
294
  RewardRepository.countRewardAndBreakdownOnChain(chainId, roots.lastTree),
@@ -300,42 +300,42 @@ export class RewardService {
300
300
  };
301
301
  }
302
302
  static async breakdownForCampaign(query) {
303
- const root = await MerklRootService.fetch(query.chainId);
303
+ const root = await MerklRootService.fetchFromCache(query.chainId);
304
304
  const id = CampaignService.hashId({ distributionChain: query.chainId, campaignId: query.campaignId });
305
305
  return RewardRepository.breakdownForCampaign(root.live, id, query);
306
306
  }
307
307
  static async countForCampaign(query) {
308
- const root = await MerklRootService.fetch(query.chainId);
308
+ const root = await MerklRootService.fetchFromCache(query.chainId);
309
309
  const id = CampaignService.hashId({ distributionChain: query.chainId, campaignId: query.campaignId });
310
310
  return RewardRepository.countForCampaign(id, root.live);
311
311
  }
312
312
  static async totalForCampaign(query) {
313
- const root = await MerklRootService.fetch(query.chainId);
313
+ const root = await MerklRootService.fetchFromCache(query.chainId);
314
314
  return RewardRepository.totalForCampaign(CampaignService.hashId({ distributionChain: query.chainId, campaignId: query.campaignId }), root.live);
315
315
  }
316
316
  static async breakdownForToken(query) {
317
317
  return CacheService.wrap(TTLPresets.MIN_10, async (query) => {
318
- const root = await MerklRootService.fetch(query.chainId);
318
+ const root = await MerklRootService.fetchFromCache(query.chainId);
319
319
  const id = TokenService.hashId({ chainId: query.chainId, address: query.address });
320
320
  return RewardRepository.breakdownForToken(root.live, id, query);
321
321
  }, query);
322
322
  }
323
323
  static async countForToken(query) {
324
324
  return CacheService.wrap(TTLPresets.MIN_10, async (query) => {
325
- const root = await MerklRootService.fetch(query.chainId);
325
+ const root = await MerklRootService.fetchFromCache(query.chainId);
326
326
  const id = TokenService.hashId({ chainId: query.chainId, address: query.address });
327
327
  return RewardRepository.countForToken(id, root.live);
328
328
  }, query);
329
329
  }
330
330
  static async totalForToken(query) {
331
331
  return CacheService.wrap(TTLPresets.MIN_10, async (query) => {
332
- const root = await MerklRootService.fetch(query.chainId);
332
+ const root = await MerklRootService.fetchFromCache(query.chainId);
333
333
  const id = TokenService.hashId({ chainId: query.chainId, address: query.address });
334
334
  return RewardRepository.totalForToken(id, root.live);
335
335
  }, query);
336
336
  }
337
337
  static async getAmountAndClaimedForCampaigns(x) {
338
- const currentRoot = await MerklRootService.fetch(x.chainId);
338
+ const currentRoot = await MerklRootService.fetchFromCache(x.chainId);
339
339
  return await RewardRepository.getAmountAndClaimedForCampaigns(currentRoot.live, x);
340
340
  }
341
341
  static async getUnclaimed(x) {
@@ -2166,11 +2166,15 @@ export declare const v4: Elysia<"/v4", false, {
2166
2166
  data: {
2167
2167
  properties: {
2168
2168
  "Icon (Required)": {
2169
- files: {
2169
+ files: ({
2170
2170
  file: {
2171
2171
  url: string;
2172
2172
  };
2173
- }[];
2173
+ } | {
2174
+ external: {
2175
+ url: string;
2176
+ };
2177
+ })[];
2174
2178
  };
2175
2179
  "Address (in checksum format) (Required)": {
2176
2180
  rich_text: {
@@ -293,11 +293,15 @@ export declare const TokenController: Elysia<"/tokens", false, {
293
293
  data: {
294
294
  properties: {
295
295
  "Icon (Required)": {
296
- files: {
296
+ files: ({
297
297
  file: {
298
298
  url: string;
299
299
  };
300
- }[];
300
+ } | {
301
+ external: {
302
+ url: string;
303
+ };
304
+ })[];
301
305
  };
302
306
  "Address (in checksum format) (Required)": {
303
307
  rich_text: {
@@ -76,11 +76,15 @@ export declare const NotionWebhookDto: import("@sinclair/typebox").TObject<{
76
76
  data: import("@sinclair/typebox").TObject<{
77
77
  properties: import("@sinclair/typebox").TObject<{
78
78
  "Icon (Required)": import("@sinclair/typebox").TObject<{
79
- files: import("@sinclair/typebox").TArray<import("@sinclair/typebox").TObject<{
79
+ files: import("@sinclair/typebox").TArray<import("@sinclair/typebox").TUnion<[import("@sinclair/typebox").TObject<{
80
80
  file: import("@sinclair/typebox").TObject<{
81
81
  url: import("@sinclair/typebox").TString;
82
82
  }>;
83
- }>>;
83
+ }>, import("@sinclair/typebox").TObject<{
84
+ external: import("@sinclair/typebox").TObject<{
85
+ url: import("@sinclair/typebox").TString;
86
+ }>;
87
+ }>]>>;
84
88
  }>;
85
89
  "Address (in checksum format) (Required)": import("@sinclair/typebox").TObject<{
86
90
  rich_text: import("@sinclair/typebox").TArray<import("@sinclair/typebox").TObject<{
@@ -63,7 +63,12 @@ export const CreateTokenDto = t.Object({
63
63
  export const NotionWebhookDto = t.Object({
64
64
  data: t.Object({
65
65
  properties: t.Object({
66
- "Icon (Required)": t.Object({ files: t.Array(t.Object({ file: t.Object({ url: t.String() }) })) }),
66
+ "Icon (Required)": t.Object({
67
+ files: t.Array(t.Union([
68
+ t.Object({ file: t.Object({ url: t.String() }) }),
69
+ t.Object({ external: t.Object({ url: t.String() }) }),
70
+ ])),
71
+ }),
67
72
  "Address (in checksum format) (Required)": t.Object({
68
73
  rich_text: t.Array(t.Object({ plain_text: t.String() })),
69
74
  }),
@@ -290,7 +290,8 @@ export class TokenService {
290
290
  const env = process.env.ENV === "prod" ? "production" : process.env.ENV;
291
291
  const bucket = new BucketService(`merkl-${env}-tokens`, `angle-${env}-1`);
292
292
  const properties = body.data.properties;
293
- const icon = properties["Icon (Required)"].files?.[0]?.file.url;
293
+ const file = properties["Icon (Required)"].files[0];
294
+ const icon = "external" in file ? file.external.url : file.file.url;
294
295
  const iconFile = await fetch(icon);
295
296
  const mimeType = iconFile.headers.get("content-type");
296
297
  const extension = mimeType.split("/")[1].split("+")[0];