@merkl/api 0.15.40 → 0.15.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.
@@ -1739,6 +1739,28 @@ declare const eden: {
1739
1739
  }[];
1740
1740
  }[];
1741
1741
  }>>;
1742
+ post: (body: {
1743
+ name: string;
1744
+ id: number;
1745
+ icon: string;
1746
+ explorerType: "ETHERSCAN" | "BLOCKSCOUT";
1747
+ explorerUrl: string;
1748
+ }, options: {
1749
+ headers: {
1750
+ authorization: string;
1751
+ };
1752
+ query?: Record<string, unknown> | undefined;
1753
+ fetch?: RequestInit | undefined;
1754
+ }) => Promise<import("@elysiajs/eden").Treaty.TreatyResponse<{
1755
+ 200: {
1756
+ Explorer: {
1757
+ type: import("../../database/api/.generated").$Enums.ExplorerType;
1758
+ url: string;
1759
+ id: string;
1760
+ chainId: number;
1761
+ }[];
1762
+ };
1763
+ }>>;
1742
1764
  };
1743
1765
  count: {
1744
1766
  get: (options: {
@@ -4839,6 +4861,28 @@ declare const eden: {
4839
4861
  }[];
4840
4862
  }[];
4841
4863
  }>>;
4864
+ post: (body: {
4865
+ name: string;
4866
+ id: number;
4867
+ icon: string;
4868
+ explorerType: "ETHERSCAN" | "BLOCKSCOUT";
4869
+ explorerUrl: string;
4870
+ }, options: {
4871
+ headers: {
4872
+ authorization: string;
4873
+ };
4874
+ query?: Record<string, unknown> | undefined;
4875
+ fetch?: RequestInit | undefined;
4876
+ }) => Promise<import("@elysiajs/eden").Treaty.TreatyResponse<{
4877
+ 200: {
4878
+ Explorer: {
4879
+ type: import("../../database/api/.generated").$Enums.ExplorerType;
4880
+ url: string;
4881
+ id: string;
4882
+ chainId: number;
4883
+ }[];
4884
+ };
4885
+ }>>;
4842
4886
  };
4843
4887
  count: {
4844
4888
  get: (options: {
@@ -9006,6 +9050,35 @@ export declare const MerklApi: (domain: string | import("elysia").default<"", fa
9006
9050
  };
9007
9051
  };
9008
9052
  };
9053
+ } & {
9054
+ chains: {
9055
+ index: {
9056
+ post: {
9057
+ body: {
9058
+ name: string;
9059
+ id: number;
9060
+ icon: string;
9061
+ explorerType: "ETHERSCAN" | "BLOCKSCOUT";
9062
+ explorerUrl: string;
9063
+ };
9064
+ params: {};
9065
+ query: unknown;
9066
+ headers: {
9067
+ authorization: string;
9068
+ };
9069
+ response: {
9070
+ 200: {
9071
+ Explorer: {
9072
+ type: import("../../database/api/.generated").$Enums.ExplorerType;
9073
+ url: string;
9074
+ id: string;
9075
+ chainId: number;
9076
+ }[];
9077
+ };
9078
+ };
9079
+ };
9080
+ };
9081
+ };
9009
9082
  };
9010
9083
  } & {
9011
9084
  v4: {
@@ -13388,6 +13461,28 @@ export declare const MerklApi: (domain: string | import("elysia").default<"", fa
13388
13461
  }[];
13389
13462
  }[];
13390
13463
  }>>;
13464
+ post: (body: {
13465
+ name: string;
13466
+ id: number;
13467
+ icon: string;
13468
+ explorerType: "ETHERSCAN" | "BLOCKSCOUT";
13469
+ explorerUrl: string;
13470
+ }, options: {
13471
+ headers: {
13472
+ authorization: string;
13473
+ };
13474
+ query?: Record<string, unknown> | undefined;
13475
+ fetch?: RequestInit | undefined;
13476
+ }) => Promise<import("@elysiajs/eden").Treaty.TreatyResponse<{
13477
+ 200: {
13478
+ Explorer: {
13479
+ type: import("../../database/api/.generated").$Enums.ExplorerType;
13480
+ url: string;
13481
+ id: string;
13482
+ chainId: number;
13483
+ }[];
13484
+ };
13485
+ }>>;
13391
13486
  };
13392
13487
  count: {
13393
13488
  get: (options: {
@@ -16488,6 +16583,28 @@ export declare const MerklApi: (domain: string | import("elysia").default<"", fa
16488
16583
  }[];
16489
16584
  }[];
16490
16585
  }>>;
16586
+ post: (body: {
16587
+ name: string;
16588
+ id: number;
16589
+ icon: string;
16590
+ explorerType: "ETHERSCAN" | "BLOCKSCOUT";
16591
+ explorerUrl: string;
16592
+ }, options: {
16593
+ headers: {
16594
+ authorization: string;
16595
+ };
16596
+ query?: Record<string, unknown> | undefined;
16597
+ fetch?: RequestInit | undefined;
16598
+ }) => Promise<import("@elysiajs/eden").Treaty.TreatyResponse<{
16599
+ 200: {
16600
+ Explorer: {
16601
+ type: import("../../database/api/.generated").$Enums.ExplorerType;
16602
+ url: string;
16603
+ id: string;
16604
+ chainId: number;
16605
+ }[];
16606
+ };
16607
+ }>>;
16491
16608
  };
16492
16609
  count: {
16493
16610
  get: (options: {
@@ -2108,6 +2108,35 @@ declare const app: Elysia<"", false, {
2108
2108
  };
2109
2109
  };
2110
2110
  };
2111
+ } & {
2112
+ chains: {
2113
+ index: {
2114
+ post: {
2115
+ body: {
2116
+ name: string;
2117
+ id: number;
2118
+ icon: string;
2119
+ explorerType: "ETHERSCAN" | "BLOCKSCOUT";
2120
+ explorerUrl: string;
2121
+ };
2122
+ params: {};
2123
+ query: unknown;
2124
+ headers: {
2125
+ authorization: string;
2126
+ };
2127
+ response: {
2128
+ 200: {
2129
+ Explorer: {
2130
+ type: import("../database/api/.generated").$Enums.ExplorerType;
2131
+ url: string;
2132
+ id: string;
2133
+ chainId: number;
2134
+ }[];
2135
+ };
2136
+ };
2137
+ };
2138
+ };
2139
+ };
2111
2140
  };
2112
2141
  } & {
2113
2142
  v4: {
@@ -1,9 +1,9 @@
1
1
  // ─── Reward Breakdowns ETL ───────────────────────────────────────────────────
2
- if (!process.env.ENV || !process.env.CHAIN_ID || !process.env.ROOT)
2
+ if (!process.env.DATABASE_API_URL || !process.env.ENV || !process.env.CHAIN_ID || !process.env.ROOT)
3
3
  throw new Error("[ENV]: missing variable");
4
+ import { BucketService } from "../../modules/v4/bucket/bucket.service";
4
5
  import { log } from "../../utils/logger";
5
6
  import { apiDbClient } from "../../utils/prisma";
6
- import { withRetry } from "@sdk";
7
7
  import { S3Client } from "bun";
8
8
  import moment from "moment";
9
9
  // ─── Global Variables ────────────────────────────────────────
@@ -13,10 +13,9 @@ const gcsClient = new S3Client({
13
13
  endpoint: process.env.GCS_ENDPOINT,
14
14
  bucket: `merkl-rewards-lake-${process.env.ENV}`,
15
15
  });
16
- let file = gcsClient.file(`breakdowns/${process.env.CHAIN_ID}-${process.env.ROOT}`);
17
- if (!(await file.exists()))
18
- file = gcsClient.file(`breakdowns/${process.env.CHAIN_ID}-${process.env.ROOT}.gz`);
16
+ const file = gcsClient.file(`breakdowns/${process.env.CHAIN_ID}-${process.env.ROOT}`);
19
17
  const failedBatches = [];
18
+ const missingCampaigns = [];
20
19
  // ─── Extract ─────────────────────────────────────────────────────────────────
21
20
  const extract = async () => {
22
21
  if (!file.exists())
@@ -30,106 +29,115 @@ const extract = async () => {
30
29
  buffer += textDecoder.decode(chunk);
31
30
  const lines = buffer.split("\n");
32
31
  buffer = lines.pop() || "";
33
- for (const line of lines)
34
- if (line.trim()) {
32
+ for (const line of lines) {
33
+ if (line.trim())
35
34
  data.push(...(await transform(JSON.parse(line))));
36
- }
35
+ }
37
36
  if (data.length < 30_000)
38
37
  continue;
39
38
  try {
40
- count += await withRetry(load, [data], 5, 60_000);
39
+ count += await load(data);
41
40
  data = [];
42
41
  }
43
42
  catch (err) {
44
- console.error(`Failed to insert a batch, adding it to the fail queue.\n${err}`);
43
+ // log.error("Failed to insert a batch, adding it to the fail queue.", err);
45
44
  failedBatches.push(data);
46
45
  data = [];
47
46
  }
48
47
  }
49
48
  try {
50
- count += await withRetry(load, [data], 5, 60_000);
49
+ count += await load(data);
51
50
  data = [];
52
51
  }
53
52
  catch (err) {
54
- console.error(`Failed to insert a batch, adding it to the fail queue.\n${err}`);
53
+ // log.error("Failed to insert a batch, adding it to the fail queue.", err);
55
54
  failedBatches.push(data);
56
55
  data = [];
57
56
  }
58
57
  return count;
59
58
  };
60
59
  // ─── Transform ───────────────────────────────────────────────────────────────
61
- const transform = async (rewardBreakdowns) => {
62
- const transformedRewardBreakdowns = [];
63
- for (const rewardBreakdown of rewardBreakdowns) {
64
- const rewardTokenId = Bun.hash(`${process.env.CHAIN_ID}${rewardBreakdown.token}`).toString();
65
- const rewardId = Bun.hash(`${process.env.ROOT}${rewardBreakdown.recipient}${rewardTokenId}`).toString();
66
- transformedRewardBreakdowns.push({
60
+ const transform = (rewardBreakdowns) => {
61
+ const transformedBreakdowns = Array(rewardBreakdowns.length);
62
+ let i = 0;
63
+ for (i; i < rewardBreakdowns.length; i++) {
64
+ const rewardTokenId = Bun.hash(`${process.env.CHAIN_ID}${rewardBreakdowns[i].token}`).toString();
65
+ const rewardId = Bun.hash(`${process.env.ROOT}${rewardBreakdowns[i].recipient}${rewardTokenId}`).toString();
66
+ const campaignId = Bun.hash(`${process.env.CHAIN_ID}${rewardBreakdowns[i].campaignId}`).toString();
67
+ transformedBreakdowns[i] = {
67
68
  rewardId,
68
- protocolId: rewardBreakdown.protocolId ? rewardBreakdown.protocolId : undefined,
69
- campaignId: rewardBreakdown.campaignId,
70
- reason: rewardBreakdown.reason ? rewardBreakdown.reason : "",
71
- amount: rewardBreakdown.amount,
72
- claimed: rewardBreakdown.claimed,
73
- pending: rewardBreakdown.pending,
74
- });
69
+ protocolId: rewardBreakdowns[i].protocolId ? rewardBreakdowns[i].protocolId : undefined,
70
+ campaignId,
71
+ reason: rewardBreakdowns[i].reason ? rewardBreakdowns[i].reason : "",
72
+ amount: rewardBreakdowns[i].amount,
73
+ claimed: rewardBreakdowns[i].claimed,
74
+ pending: rewardBreakdowns[i].pending,
75
+ merklCampaignId: rewardBreakdowns[i].campaignId,
76
+ };
75
77
  }
76
- return transformedRewardBreakdowns;
78
+ return transformedBreakdowns;
77
79
  };
78
80
  // ─── Load ────────────────────────────────────────────────────────────────────
79
81
  const load = async (rewardBreakdowns) => {
80
- log.info(`pushing ${rewardBreakdowns.length} rewardBreakdowns`);
81
- // const missingCampaigns: string[] = [];
82
- // const foundCampaigns: string[] = [];
83
- // const campaigns = rewardBreakdowns.reduce(
84
- // (acc, x) => {
85
- // const campaignUnique = {
86
- // campaignId: x.campaignId,
87
- // distributionChain: Number.parseInt(process.env.CHAIN_ID!),
88
- // };
89
- // if (!Object.keys(acc).includes(CampaignService.hashId(campaignUnique)))
90
- // acc[CampaignService.hashId(campaignUnique)] = {
91
- // campaignId: x.campaignId,
92
- // distributionChain: Number.parseInt(process.env.CHAIN_ID!),
93
- // };
94
- // return acc;
95
- // },
96
- // {} as Record<string, CampaignUnique>
97
- // );
98
- // for (const campaign of Object.values(campaigns)) {
99
- // const campaignExists = await CampaignService.checkIfExist(campaign);
100
- // if (!campaignExists) {
101
- // const { success, fail } = await CampaignService.fill([campaign]);
102
- // if (fail === 1 || success !== 1) {
103
- // missingCampaigns.push(CampaignService.hashId(campaign));
104
- // log.warn(`createManyBreakdown - Missing campaign: ${campaign.campaignId}`);
105
- // continue;
106
- // }
107
- // }
108
- // foundCampaigns.push(CampaignService.hashId(campaign));
109
- // }
110
- // if (missingCampaigns.length !== 0) {
111
- // log.warn(`createManyBreakdown - Missing ${missingCampaigns.length} campaigns: ${missingCampaigns.join(", ")}`);
112
- // }
113
- return (await apiDbClient.rewardBreakdown.createMany({
114
- data: rewardBreakdowns.map(x => {
115
- const campaignId = Bun.hash(`${process.env.CHAIN_ID}${x.campaignId}`).toString();
116
- return { ...x, campaignId };
117
- }),
118
- // .filter(x => !missingCampaigns.includes(x.campaignId)),
82
+ const count = (await apiDbClient.rewardBreakdown.createMany({
83
+ data: rewardBreakdowns,
119
84
  skipDuplicates: true,
120
85
  })).count;
86
+ log.info(`Successfully inserted ${rewardBreakdowns.length} reward breakdown(s).`);
87
+ return count;
88
+ };
89
+ // ─── Retry ───────────────────────────────────────────────────────────────────
90
+ // Using binary search
91
+ const retry = async (batches) => {
92
+ log.info(`Retrying ${batches.length} batch(es)...`);
93
+ let inserted = 0;
94
+ while (batches.length > 0) {
95
+ const currentBatch = batches.shift();
96
+ const firstHalf = currentBatch.splice(0, Math.ceil(currentBatch.length / 2));
97
+ const secondHalf = currentBatch;
98
+ // Process first half
99
+ try {
100
+ inserted += await load(firstHalf);
101
+ }
102
+ catch (err) {
103
+ log.error(JSON.stringify(firstHalf), err);
104
+ if (firstHalf.length > 1)
105
+ batches.push(firstHalf);
106
+ else
107
+ missingCampaigns.push(firstHalf[0].merklCampaignId);
108
+ }
109
+ // Process second half
110
+ try {
111
+ inserted += await load(secondHalf);
112
+ }
113
+ catch (err) {
114
+ log.error(JSON.stringify(secondHalf), err);
115
+ if (secondHalf.length > 1)
116
+ batches.push(secondHalf);
117
+ else
118
+ missingCampaigns.push(secondHalf[0].merklCampaignId);
119
+ }
120
+ }
121
+ return inserted;
121
122
  };
122
123
  // ─── Main ────────────────────────────────────────────────────────────────────
123
124
  export const main = async () => {
124
125
  const start = moment().unix();
125
126
  const count = await extract();
126
- log.info(`✅ Successfully created ${count} new records for ${process.env.CHAIN_ID}-${process.env.ROOT} in ${moment().unix() - start} sec`);
127
+ log.info(`✅ Successfully created ${count} new record(s) for ${process.env.CHAIN_ID}-${process.env.ROOT} in ${moment().unix() - start} sec.`);
127
128
  if (failedBatches.length !== 0) {
128
- log.error("breakdowns", `${failedBatches.length} batches failed.`);
129
- process.exit(1);
130
- }
131
- if (failedBatches.length === 0) {
132
- // await file.delete();
129
+ const inserted = await retry(failedBatches);
130
+ log.info(`Successfully inserted ${inserted} record(s) after retrying.`);
131
+ if (inserted !== failedBatches.length) {
132
+ log.error("breakdowns", `${failedBatches.length} breakdown(s) failed to insert.`);
133
+ // ─── Push Missing Campaigns To Bucket ────────────────
134
+ const bucket = new BucketService(`merkl-campaigns-lake-${process.env.ENV}`, `merkl-data-${process.env.ENV}`);
135
+ await bucket.push(`${process.env.CHAIN_ID}_missing_campaigns`, JSON.stringify(missingCampaigns), {
136
+ type: "application/json",
137
+ });
138
+ process.exit(1);
139
+ }
133
140
  }
141
+ // if (failedBatches.length === 0) await file.delete();
134
142
  };
135
143
  main();
@@ -4,7 +4,7 @@ export declare class BucketService {
4
4
  defaultUploadOptions: UploadOptions<unknown>;
5
5
  constructor(bucket: string, projectId: string);
6
6
  pushArray<T>(filename: string, arr: T[], options?: UploadOptions<T>): Promise<number>;
7
- push(filename: string, text: string, options?: Omit<UploadOptions<never>, "transform">): Promise<number>;
7
+ push(filename: string, text: string, options?: Omit<UploadOptions<never>, "transform" | "separator">): Promise<number>;
8
8
  pullArray<T>(filename: string, callback: (elem: string) => T, separator?: string): Promise<T[]>;
9
9
  pull(filename: string): Promise<string>;
10
10
  }
@@ -103,6 +103,35 @@ export declare const ChainController: Elysia<"/chains", false, {
103
103
  };
104
104
  };
105
105
  };
106
+ } & {
107
+ chains: {
108
+ index: {
109
+ post: {
110
+ body: {
111
+ name: string;
112
+ id: number;
113
+ icon: string;
114
+ explorerType: "ETHERSCAN" | "BLOCKSCOUT";
115
+ explorerUrl: string;
116
+ };
117
+ params: {};
118
+ query: unknown;
119
+ headers: {
120
+ authorization: string;
121
+ };
122
+ response: {
123
+ 200: {
124
+ Explorer: {
125
+ type: import("../../../../database/api/.generated").$Enums.ExplorerType;
126
+ url: string;
127
+ id: string;
128
+ chainId: number;
129
+ }[];
130
+ };
131
+ };
132
+ };
133
+ };
134
+ };
106
135
  }, {
107
136
  derive: {};
108
137
  resolve: {};
@@ -1,6 +1,6 @@
1
1
  import { AuthorizationHeadersDto, BackOfficeGuard } from "../../../guards/BackOffice.guard";
2
2
  import Elysia, { t } from "elysia";
3
- import { ChainResourceDto, ChainUniqueDto, GetChainQueryDto, UpdateChainDto } from "./chain.model";
3
+ import { ChainResourceDto, ChainUniqueDto, CreateChainDto, GetChainQueryDto, UpdateChainDto, } from "./chain.model";
4
4
  import { ChainService } from "./chain.service";
5
5
  // ─── Chains Controller ───────────────────────────────────────────────────────
6
6
  export const ChainController = new Elysia({ prefix: "/chains", detail: { tags: ["Chains"] } })
@@ -35,4 +35,10 @@ export const ChainController = new Elysia({ prefix: "/chains", detail: { tags: [
35
35
  headers: AuthorizationHeadersDto,
36
36
  beforeHandle: BackOfficeGuard,
37
37
  detail: { hide: true },
38
+ })
39
+ .post("/", async ({ body }) => await ChainService.create(body), {
40
+ body: CreateChainDto,
41
+ headers: AuthorizationHeadersDto,
42
+ beforeHandle: BackOfficeGuard,
43
+ detail: { hide: true },
38
44
  });
@@ -25,6 +25,17 @@ export declare const ChainArrayOptionalDto: import("@sinclair/typebox").TObject<
25
25
  export declare const UpdateChainDto: import("@sinclair/typebox").TObject<{
26
26
  icon: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TString>;
27
27
  }>;
28
+ export declare const CreateChainDto: import("@sinclair/typebox").TObject<{
29
+ id: import("@sinclair/typebox").TNumber;
30
+ name: import("@sinclair/typebox").TString;
31
+ icon: import("@sinclair/typebox").TString;
32
+ explorerType: import("@sinclair/typebox").TEnum<{
33
+ ETHERSCAN: "ETHERSCAN";
34
+ BLOCKSCOUT: "BLOCKSCOUT";
35
+ }>;
36
+ explorerUrl: import("@sinclair/typebox").TString;
37
+ }>;
28
38
  export type ChainUniqueModel = typeof ChainUniqueDto.static;
29
39
  export type ChainSearchDto = typeof GetChainQueryDto.static;
30
40
  export type UpdateChainModel = typeof UpdateChainDto.static;
41
+ export type CreateChainModel = typeof CreateChainDto.static;
@@ -1,3 +1,4 @@
1
+ import { ExplorerType } from "../../../../database/api/.generated";
1
2
  import { t } from "elysia";
2
3
  // ─── DTOs ────────────────────────────────────────────────────────────────────
3
4
  export const ChainResourceDto = t.Object({
@@ -26,3 +27,10 @@ export const UpdateChainDto = t.Object({
26
27
  icon: t.Optional(t.String({ format: "uri" })),
27
28
  // iconFile: t.Optional(t.File()),
28
29
  });
30
+ export const CreateChainDto = t.Object({
31
+ id: t.Numeric(),
32
+ name: t.String(),
33
+ icon: t.String({ format: "uri" }),
34
+ explorerType: t.Enum(ExplorerType),
35
+ explorerUrl: t.String({ format: "uri" }),
36
+ });
@@ -1,5 +1,5 @@
1
1
  import type { Campaign, CampaignParameters } from "@sdk";
2
- import type { Chain, ChainSearchDto, UpdateChainModel } from "./chain.model";
2
+ import type { ChainSearchDto, CreateChainModel, UpdateChainModel } from "./chain.model";
3
3
  export declare abstract class ChainRepository {
4
4
  #private;
5
5
  /**
@@ -45,16 +45,27 @@ export declare abstract class ChainRepository {
45
45
  * @param template for chain creation
46
46
  * @returns
47
47
  */
48
- static create(template: Chain["action"]["create"]["args"]): Promise<{
49
- name: string;
50
- id: number;
51
- icon: string;
48
+ static create(data: CreateChainModel): Promise<{
49
+ Explorer: {
50
+ type: import("../../../../database/api/.generated").$Enums.ExplorerType;
51
+ url: string;
52
+ id: string;
53
+ chainId: number;
54
+ }[];
52
55
  }>;
53
56
  static findMany(): Promise<{
54
57
  name: string;
55
58
  id: number;
56
59
  icon: string;
57
60
  }[]>;
61
+ static findUniqueOrThrow(id: number): Promise<{
62
+ Explorer: {
63
+ type: import("../../../../database/api/.generated").$Enums.ExplorerType;
64
+ url: string;
65
+ id: string;
66
+ chainId: number;
67
+ }[];
68
+ }>;
58
69
  /**
59
70
  * Fetches the campaign dynamic data for a v3 campaign onchain
60
71
  * @param chainId
@@ -1,6 +1,7 @@
1
1
  import { campaignsDynamicData } from "../../../libs/campaigns/campaignsDynamicData";
2
2
  import { executeSimple } from "../../../utils/execute";
3
3
  import { apiDbClient } from "../../../utils/prisma";
4
+ import { ExplorerRepository } from "../explorer/explorer.repository";
4
5
  export class ChainRepository {
5
6
  /**
6
7
  * @param id ChainId
@@ -44,12 +45,30 @@ export class ChainRepository {
44
45
  * @param template for chain creation
45
46
  * @returns
46
47
  */
47
- static async create(template) {
48
- return apiDbClient.chain.create(template);
48
+ static async create(data) {
49
+ await apiDbClient.chain.create({
50
+ data: {
51
+ id: data.id,
52
+ icon: data.icon,
53
+ name: data.name,
54
+ },
55
+ });
56
+ await ExplorerRepository.create(data.id, data.explorerType, data.explorerUrl);
57
+ return await ChainRepository.findUniqueOrThrow(data.id);
49
58
  }
50
59
  static async findMany() {
51
60
  return apiDbClient.chain.findMany();
52
61
  }
62
+ static async findUniqueOrThrow(id) {
63
+ return apiDbClient.chain.findUniqueOrThrow({
64
+ where: {
65
+ id,
66
+ },
67
+ select: {
68
+ Explorer: true,
69
+ },
70
+ });
71
+ }
53
72
  /**
54
73
  * Fetches the campaign dynamic data for a v3 campaign onchain
55
74
  * @param chainId
@@ -1,4 +1,4 @@
1
- import type { ChainSearchDto, UpdateChainModel } from "./chain.model";
1
+ import type { ChainSearchDto, CreateChainModel, UpdateChainModel } from "./chain.model";
2
2
  export declare abstract class ChainService {
3
3
  static get(chainId: number): Promise<({
4
4
  Explorer: {
@@ -39,6 +39,14 @@ export declare abstract class ChainService {
39
39
  * @returns an array of chainId
40
40
  */
41
41
  static getSupportedIds(): Promise<number[]>;
42
+ static create(chain: CreateChainModel): Promise<{
43
+ Explorer: {
44
+ type: import("../../../../database/api/.generated").$Enums.ExplorerType;
45
+ url: string;
46
+ id: string;
47
+ chainId: number;
48
+ }[];
49
+ }>;
42
50
  static update(id: number, data: UpdateChainModel): Promise<{
43
51
  name: string;
44
52
  id: number;
@@ -39,11 +39,10 @@ export class ChainService {
39
39
  }
40
40
  return supportedIds;
41
41
  }
42
+ static async create(chain) {
43
+ return await ChainRepository.create(chain);
44
+ }
42
45
  static async update(id, data) {
43
- // let iconUri = data.icon;
44
- // if (data.iconFile) {
45
- // iconUri = await BucketService.upload("merkl-assets", `/chains/${id}`, data.iconFile.stream(), true);
46
- // }
47
46
  return await ChainRepository.update(id, data);
48
47
  }
49
48
  }
@@ -25,14 +25,46 @@ export declare abstract class ProtocolRepository {
25
25
  tags: string[];
26
26
  icon: string;
27
27
  }[]>;
28
- static findMany(query: GetProtocolsQueryModel): Promise<{
28
+ static findMany(query: GetProtocolsQueryModel): Promise<({
29
+ MainOpportunities: ({
30
+ Campaigns: {
31
+ type: import("../../../../database/api/.generated").$Enums.CampaignType;
32
+ id: string;
33
+ params: import("database/api/.generated/runtime/library").JsonValue;
34
+ subType: number | null;
35
+ startTimestamp: bigint;
36
+ endTimestamp: bigint;
37
+ computeChainId: number;
38
+ distributionChainId: number;
39
+ campaignId: string;
40
+ rewardTokenId: string;
41
+ amount: string;
42
+ opportunityId: string;
43
+ creatorAddress: string;
44
+ }[];
45
+ } & {
46
+ name: string;
47
+ type: import("../../../../database/api/.generated").$Enums.CampaignType;
48
+ id: string;
49
+ status: import("../../../../database/api/.generated").$Enums.Status;
50
+ tags: string[];
51
+ identifier: string;
52
+ chainId: number;
53
+ action: import("../../../../database/api/.generated").$Enums.OpportunityAction;
54
+ depositUrl: string | null;
55
+ mainProtocolId: string | null;
56
+ tvl: number;
57
+ apr: number;
58
+ dailyRewards: number;
59
+ })[];
60
+ } & {
29
61
  name: string;
30
62
  url: string;
31
63
  description: string;
32
64
  id: string;
33
65
  tags: string[];
34
66
  icon: string;
35
- }[]>;
67
+ })[]>;
36
68
  static countMany(query: GetProtocolsQueryModel): Promise<number>;
37
69
  static update(id: string, data: UpdateProtocolModel): Promise<{
38
70
  name: string;