@merkl/api 0.17.22 → 0.17.24

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 (36) hide show
  1. package/dist/database/api/.generated/drizzle/schema.d.ts +46 -0
  2. package/dist/database/api/.generated/drizzle/schema.js +5 -1
  3. package/dist/database/api/.generated/drizzle/schema.ts +8 -1
  4. package/dist/database/api/.generated/edge.js +26 -4
  5. package/dist/database/api/.generated/index-browser.js +7 -1
  6. package/dist/database/api/.generated/index.d.ts +149 -2
  7. package/dist/database/api/.generated/index.js +26 -4
  8. package/dist/database/api/.generated/package.json +1 -1
  9. package/dist/database/api/.generated/schema.prisma +29 -8
  10. package/dist/database/api/.generated/wasm.js +7 -1
  11. package/dist/src/eden/index.d.ts +190 -8
  12. package/dist/src/index.d.ts +44 -2
  13. package/dist/src/libs/campaigns/utils/getDolomiteMarkets.d.ts +3 -2
  14. package/dist/src/libs/campaigns/utils/getDolomiteMarkets.js +10 -7
  15. package/dist/src/modules/v4/campaign/campaign.controller.d.ts +40 -1
  16. package/dist/src/modules/v4/campaign/campaign.controller.js +16 -1
  17. package/dist/src/modules/v4/campaign/campaign.model.d.ts +14 -1
  18. package/dist/src/modules/v4/campaign/campaign.model.js +11 -1
  19. package/dist/src/modules/v4/campaign/campaign.repository.d.ts +64 -32
  20. package/dist/src/modules/v4/campaign/campaign.repository.js +84 -122
  21. package/dist/src/modules/v4/campaign/campaign.service.d.ts +61 -19
  22. package/dist/src/modules/v4/campaign/campaign.service.js +51 -63
  23. package/dist/src/modules/v4/opportunity/opportunity.controller.d.ts +1 -0
  24. package/dist/src/modules/v4/opportunity/opportunity.repository.d.ts +5 -0
  25. package/dist/src/modules/v4/opportunity/opportunity.service.d.ts +3 -0
  26. package/dist/src/modules/v4/programPayload/programPayload.repository.js +6 -6
  27. package/dist/src/modules/v4/protocol/protocol.repository.d.ts +1 -0
  28. package/dist/src/modules/v4/router.d.ts +41 -1
  29. package/dist/src/modules/v4/status/status.service.js +1 -1
  30. package/dist/src/routes/v3/dolomite.d.ts +6 -1
  31. package/dist/src/routes/v3/dolomite.js +6 -3
  32. package/dist/src/routes/v3/router.d.ts +3 -1
  33. package/dist/src/utils/error.d.ts +6 -0
  34. package/dist/src/utils/error.js +12 -0
  35. package/dist/tsconfig.package.tsbuildinfo +1 -1
  36. package/package.json +1 -1
@@ -1,19 +1,22 @@
1
1
  import { Redis } from "../../../cache";
2
- import { DOLOMITE_CHAINID, DOLOMITE_MARGIN, DolomiteInterface, DolomiteMargin__factory, ERC20Interface } from "@sdk";
2
+ import { DOLOMITE_MARGIN_MAPPING, DolomiteInterface, DolomiteMargin__factory, ERC20Interface } from "@sdk";
3
3
  import { batchMulticallCallWithRetry } from "../../../utils/generic";
4
4
  import { providers } from "../../../utils/providers";
5
- export const getDomiteMarkets = async () => {
6
- const dolomiteMarginContract = await DolomiteMargin__factory.connect(DOLOMITE_MARGIN, providers[DOLOMITE_CHAINID]);
5
+ export const getDomiteMarkets = async (chainId) => {
6
+ if (!DOLOMITE_MARGIN_MAPPING[chainId]) {
7
+ throw "Dolomite is not supported on this chain";
8
+ }
9
+ const dolomiteMarginContract = await DolomiteMargin__factory.connect(DOLOMITE_MARGIN_MAPPING[chainId], providers[chainId]);
7
10
  const numMarkets = (await dolomiteMarginContract.getNumMarkets()).toNumber();
8
11
  const calls = [];
9
12
  for (let index = 0; index < numMarkets; index++) {
10
13
  calls.push({
11
14
  allowFailure: true,
12
15
  callData: DolomiteInterface.encodeFunctionData("getMarket", [index]),
13
- target: DOLOMITE_MARGIN,
16
+ target: DOLOMITE_MARGIN_MAPPING[chainId],
14
17
  });
15
18
  }
16
- const res = await batchMulticallCallWithRetry(DOLOMITE_CHAINID, {
19
+ const res = await batchMulticallCallWithRetry(chainId, {
17
20
  calls,
18
21
  });
19
22
  if (!res.every(r => r.success)) {
@@ -29,7 +32,7 @@ export const getDomiteMarkets = async () => {
29
32
  target: token,
30
33
  });
31
34
  }
32
- const secondRes = await batchMulticallCallWithRetry(DOLOMITE_CHAINID, {
35
+ const secondRes = await batchMulticallCallWithRetry(chainId, {
33
36
  calls: secondCalls,
34
37
  });
35
38
  for (let index = 0; index < numMarkets; index++) {
@@ -47,4 +50,4 @@ export const getDomiteMarkets = async () => {
47
50
  }
48
51
  return markets;
49
52
  };
50
- export const getDolomiteMarketWithCache = async () => await Redis.getOrSet("DolomiteMarkets", getDomiteMarkets);
53
+ export const getDolomiteMarketWithCache = async (chainId) => await Redis.getOrSet("DolomiteMarkets", getDomiteMarkets, chainId);
@@ -51,6 +51,7 @@ export declare const CampaignController: Elysia<"/campaigns", false, {
51
51
  amount: string;
52
52
  opportunityId: string;
53
53
  creatorAddress: string;
54
+ manualOverrides: import("../../../../database/api/.generated").$Enums.CampaignManualOverride[];
54
55
  } | undefined;
55
56
  };
56
57
  };
@@ -59,7 +60,6 @@ export declare const CampaignController: Elysia<"/campaigns", false, {
59
60
  opportunity: {
60
61
  patch: {
61
62
  body: {
62
- tags?: string[] | undefined;
63
63
  opportunityIdentifier?: string | undefined;
64
64
  campaignId: string;
65
65
  distributionChain: number;
@@ -74,6 +74,42 @@ export declare const CampaignController: Elysia<"/campaigns", false, {
74
74
  };
75
75
  };
76
76
  };
77
+ } & {
78
+ creator: {
79
+ patch: {
80
+ body: {
81
+ campaignId: string;
82
+ creatorAddress: string;
83
+ distributionChain: number;
84
+ };
85
+ params: {};
86
+ query: unknown;
87
+ headers: {
88
+ authorization: string;
89
+ };
90
+ response: {
91
+ 200: void;
92
+ };
93
+ };
94
+ };
95
+ } & {
96
+ "remove-override": {
97
+ patch: {
98
+ body: {
99
+ campaignId: string;
100
+ field: "opportunityId" | "creatorAddress";
101
+ distributionChain: number;
102
+ };
103
+ params: {};
104
+ query: unknown;
105
+ headers: {
106
+ authorization: string;
107
+ };
108
+ response: {
109
+ 200: void;
110
+ };
111
+ };
112
+ };
77
113
  } & {
78
114
  metadata: {
79
115
  patch: {
@@ -102,6 +138,7 @@ export declare const CampaignController: Elysia<"/campaigns", false, {
102
138
  amount: string;
103
139
  opportunityId: string;
104
140
  creatorAddress: string;
141
+ manualOverrides: import("../../../../database/api/.generated").$Enums.CampaignManualOverride[];
105
142
  };
106
143
  };
107
144
  };
@@ -199,6 +236,7 @@ export declare const CampaignController: Elysia<"/campaigns", false, {
199
236
  rewardTokenId: string;
200
237
  amount: string;
201
238
  opportunityId: string;
239
+ manualOverrides: import("../../../../database/api/.generated").$Enums.CampaignManualOverride[];
202
240
  }[];
203
241
  };
204
242
  };
@@ -263,6 +301,7 @@ export declare const CampaignController: Elysia<"/campaigns", false, {
263
301
  rewardTokenId: string;
264
302
  amount: string;
265
303
  opportunityId: string;
304
+ manualOverrides: import("../../../../database/api/.generated").$Enums.CampaignManualOverride[];
266
305
  };
267
306
  };
268
307
  };
@@ -6,7 +6,7 @@ import { Campaign } from "@sdk";
6
6
  import Elysia, { t } from "elysia";
7
7
  import { throwOnUnsupportedChainId } from "src/utils/throw";
8
8
  import { DynamicDataService } from "../dynamicData/dynamicData.service";
9
- import { CampaignResourceDto, CreateCampaignDto, GetCampaignQueryDto, UpdateCampaignDto, UpdateMetaDataCampaignDto, } from "./campaign.model";
9
+ import { CampaignResourceDto, CreateCampaignDto, GetCampaignQueryDto, RemoveManualOverrideDto, UpdateCampaignCreatorDto, UpdateCampaignDto, UpdateMetaDataCampaignDto, } from "./campaign.model";
10
10
  import { CampaignService } from "./campaign.service";
11
11
  // ─── Campaigns Controller ────────────────────────────────────────────────────
12
12
  export const CampaignController = new Elysia({ prefix: "/campaigns", detail: { tags: ["Campaigns"] } })
@@ -22,6 +22,21 @@ export const CampaignController = new Elysia({ prefix: "/campaigns", detail: { t
22
22
  headers: AuthorizationHeadersDto,
23
23
  body: UpdateCampaignDto,
24
24
  detail: { hide: true },
25
+ })
26
+ .patch("/creator", async ({ body }) => await CampaignService.updateCreator(body), {
27
+ beforeHandle: BackOfficeGuard,
28
+ headers: AuthorizationHeadersDto,
29
+ body: UpdateCampaignCreatorDto,
30
+ detail: { hide: true },
31
+ })
32
+ .patch("/remove-override", async ({ body }) => await CampaignService.removeManualOverride({
33
+ distributionChain: body.distributionChain,
34
+ campaignId: body.campaignId,
35
+ }, body.field), {
36
+ beforeHandle: BackOfficeGuard,
37
+ headers: AuthorizationHeadersDto,
38
+ body: RemoveManualOverrideDto,
39
+ detail: { hide: true },
25
40
  })
26
41
  .patch("/metadata", async ({ body }) => await CampaignService.updateMetaData(body), {
27
42
  beforeHandle: BackOfficeGuard,
@@ -98,7 +98,19 @@ export declare const UpdateCampaignDto: import("@sinclair/typebox").TObject<{
98
98
  distributionChain: import("@sinclair/typebox").TNumber;
99
99
  campaignId: import("@sinclair/typebox").TString;
100
100
  opportunityIdentifier: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TString>;
101
- tags: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TArray<import("@sinclair/typebox").TString>>;
101
+ }>;
102
+ export declare const UpdateCampaignCreatorDto: import("@sinclair/typebox").TObject<{
103
+ distributionChain: import("@sinclair/typebox").TNumber;
104
+ campaignId: import("@sinclair/typebox").TString;
105
+ creatorAddress: import("@sinclair/typebox").TString;
106
+ }>;
107
+ export declare const RemoveManualOverrideDto: import("@sinclair/typebox").TObject<{
108
+ distributionChain: import("@sinclair/typebox").TNumber;
109
+ campaignId: import("@sinclair/typebox").TString;
110
+ field: import("@sinclair/typebox").TEnum<{
111
+ opportunityId: "opportunityId";
112
+ creatorAddress: "creatorAddress";
113
+ }>;
102
114
  }>;
103
115
  export declare const UpdateMetaDataCampaignDto: import("@sinclair/typebox").TObject<{
104
116
  distributionChain: import("@sinclair/typebox").TNumber;
@@ -130,6 +142,7 @@ export type CreateCampaignModel = typeof CreateCampaignDto.static & {
130
142
  export type UpdateCampaignModel = typeof UpdateCampaignDto.static & {
131
143
  id: string;
132
144
  };
145
+ export type UpdateCampaignCreatorModel = typeof UpdateCampaignCreatorDto.static;
133
146
  export type UpdateMetaDataCampaignModel = typeof UpdateMetaDataCampaignDto.static & {
134
147
  url: string;
135
148
  };
@@ -1,4 +1,5 @@
1
1
  import { TokenResourceDto } from "../token/token.model";
2
+ import { CampaignManualOverride } from "../../../../database/api/.generated";
2
3
  import { t } from "elysia";
3
4
  import { ChainResourceDto } from "../chain/chain.model";
4
5
  import { CampaignStatusResourceDto } from "../status/status.model";
@@ -51,7 +52,16 @@ export const UpdateCampaignDto = t.Object({
51
52
  distributionChain: t.Numeric(),
52
53
  campaignId: t.String(),
53
54
  opportunityIdentifier: t.Optional(t.String()),
54
- tags: t.Optional(t.Array(t.String())),
55
+ });
56
+ export const UpdateCampaignCreatorDto = t.Object({
57
+ distributionChain: t.Numeric(),
58
+ campaignId: t.String(),
59
+ creatorAddress: t.String(),
60
+ });
61
+ export const RemoveManualOverrideDto = t.Object({
62
+ distributionChain: t.Numeric(),
63
+ campaignId: t.String(),
64
+ field: t.Enum(CampaignManualOverride),
55
65
  });
56
66
  export const UpdateMetaDataCampaignDto = t.Object({
57
67
  distributionChain: t.Numeric(),
@@ -1,5 +1,5 @@
1
1
  import type { CampaignUnique, CreateCampaignModel, GetCampaignQueryModel, extendedUpdateCampaignModel } from "./";
2
- import { Prisma } from "../../../../database/api/.generated";
2
+ import { type CampaignManualOverride, Prisma } from "../../../../database/api/.generated";
3
3
  import { type ChainId } from "@sdk";
4
4
  export declare abstract class CampaignRepository {
5
5
  static transformQueryToPrismaFilters(query: GetCampaignQueryModel): {
@@ -107,6 +107,7 @@ export declare abstract class CampaignRepository {
107
107
  amount: string;
108
108
  opportunityId: string;
109
109
  creatorAddress: string;
110
+ manualOverrides: import("../../../../database/api/.generated").$Enums.CampaignManualOverride[];
110
111
  })[]>;
111
112
  /**
112
113
  * Retrieves all past campaigns from the database.
@@ -149,6 +150,7 @@ export declare abstract class CampaignRepository {
149
150
  amount: string;
150
151
  opportunityId: string;
151
152
  creatorAddress: string;
153
+ manualOverrides: import("../../../../database/api/.generated").$Enums.CampaignManualOverride[];
152
154
  })[]>;
153
155
  /**
154
156
  * Retrieves all live campaigns from the database.
@@ -159,6 +161,7 @@ export declare abstract class CampaignRepository {
159
161
  * @dev Excludes test campaigns
160
162
  */
161
163
  static getLiveCampaigns(query?: {
164
+ distributionChainId?: number;
162
165
  computeChainId?: number;
163
166
  type?: string;
164
167
  }): Promise<({
@@ -191,7 +194,13 @@ export declare abstract class CampaignRepository {
191
194
  amount: string;
192
195
  opportunityId: string;
193
196
  creatorAddress: string;
197
+ manualOverrides: import("../../../../database/api/.generated").$Enums.CampaignManualOverride[];
194
198
  })[]>;
199
+ static countLives(query?: {
200
+ distributionChainId?: number;
201
+ computeChainId?: number;
202
+ type?: string;
203
+ }): Promise<number>;
195
204
  /**
196
205
  * Upserts a campaign in the database. If the campaign already exists, it updates the existing record;
197
206
  * otherwise, it creates a new one.
@@ -199,6 +208,8 @@ export declare abstract class CampaignRepository {
199
208
  * @param {CreateCampaignModel} campaign - The campaign data to be upserted.
200
209
  * @returns The upserted campaign record.
201
210
  *
211
+ * @dev Should be the only way of creating campaigns in the database.
212
+ *
202
213
  * @throws {Error} If unable to fetch data for the reward token.
203
214
  *
204
215
  * @remarks
@@ -225,18 +236,14 @@ export declare abstract class CampaignRepository {
225
236
  amount: string;
226
237
  opportunityId: string;
227
238
  creatorAddress: string;
239
+ manualOverrides: import("../../../../database/api/.generated").$Enums.CampaignManualOverride[];
228
240
  } | undefined>;
229
- static upsertMany(campaigns: CreateCampaignModel[]): Promise<{
230
- success: number;
231
- fail: number;
232
- }>;
233
241
  /**
234
- * Fetches the campaign data for a v3 campaign in database
235
- * @param chainId
236
- * @param timestamp from which campaigns endTimestamp are filtered
237
- * @returns
242
+ * Retrieves a campaign from the engine database by its chain and campaign id.
243
+ * @dev Types are different from the API database.
244
+ * @dev IDs are different from the API database.
245
+ * id in the engine database = campaignId in the API database
238
246
  */
239
- static getFromEngineDb(chainId: number, timestamp: number): Promise<CampaignParameters<CampaignV3>[]>;
240
247
  static getFromEngineDbWithId(campaignIds: CampaignUnique[]): Promise<{
241
248
  index: number;
242
249
  creator: string;
@@ -252,8 +259,44 @@ export declare abstract class CampaignRepository {
252
259
  mainParameter: string;
253
260
  campaignParameters: import("database/engine/.generated/runtime/library").JsonValue;
254
261
  }[]>;
255
- static checkIfExist(id: string): Promise<boolean>;
256
- static findUnique(id: string): Promise<{
262
+ static findUnique(id: string): Promise<({
263
+ ComputeChain: {
264
+ name: string;
265
+ id: number;
266
+ icon: string;
267
+ };
268
+ DistributionChain: {
269
+ name: string;
270
+ id: number;
271
+ icon: string;
272
+ };
273
+ RewardToken: {
274
+ symbol: string;
275
+ name: string | null;
276
+ id: string;
277
+ icon: string;
278
+ chainId: number;
279
+ address: string;
280
+ decimals: number;
281
+ displaySymbol: string;
282
+ verified: boolean;
283
+ isTest: boolean;
284
+ price: number | null;
285
+ };
286
+ Creator: {
287
+ tags: string[];
288
+ address: string;
289
+ creatorId: string | null;
290
+ };
291
+ CampaignStatus: {
292
+ error: string;
293
+ details: Prisma.JsonValue;
294
+ status: import("../../../../database/api/.generated").$Enums.RunStatus;
295
+ campaignId: string;
296
+ computedUntil: bigint;
297
+ processingStarted: bigint;
298
+ }[];
299
+ } & {
257
300
  type: string;
258
301
  id: string;
259
302
  params: Prisma.JsonValue;
@@ -267,7 +310,8 @@ export declare abstract class CampaignRepository {
267
310
  amount: string;
268
311
  opportunityId: string;
269
312
  creatorAddress: string;
270
- } | null>;
313
+ manualOverrides: import("../../../../database/api/.generated").$Enums.CampaignManualOverride[];
314
+ }) | null>;
271
315
  static findUniqueOrThrow(id: string, withOpportunity: boolean): Promise<{
272
316
  ComputeChain: {
273
317
  name: string;
@@ -334,6 +378,7 @@ export declare abstract class CampaignRepository {
334
378
  amount: string;
335
379
  opportunityId: string;
336
380
  creatorAddress: string;
381
+ manualOverrides: import("../../../../database/api/.generated").$Enums.CampaignManualOverride[];
337
382
  }>;
338
383
  static findCampaignsToProcess(distributionChainId: ChainId): Promise<{
339
384
  endTimestamp: bigint;
@@ -395,28 +440,14 @@ export declare abstract class CampaignRepository {
395
440
  amount: string;
396
441
  opportunityId: string;
397
442
  creatorAddress: string;
443
+ manualOverrides: import("../../../../database/api/.generated").$Enums.CampaignManualOverride[];
398
444
  })[]>;
399
445
  static countMany(query: GetCampaignQueryModel): Promise<number>;
400
- static countLives(chainId: number): Promise<number>;
401
- static findManyCampaignId(chainId: ChainId): Promise<{
402
- campaignId: string;
403
- }[]>;
404
446
  static findChains(): Promise<Record<string, ChainId>>;
405
- static updateOpportunity(id: string, data: extendedUpdateCampaignModel): Promise<{
406
- type: string;
407
- id: string;
408
- params: Prisma.JsonValue;
409
- subType: number | null;
410
- startTimestamp: bigint;
411
- endTimestamp: bigint;
412
- computeChainId: number;
413
- distributionChainId: number;
414
- campaignId: string;
415
- rewardTokenId: string;
416
- amount: string;
417
- opportunityId: string;
418
- creatorAddress: string;
419
- }>;
447
+ static addManualOverride(id: string, field: CampaignManualOverride): Promise<void>;
448
+ static removeManualOverride(id: string, field: CampaignManualOverride): Promise<void>;
449
+ static updateOpportunity(id: string, data: extendedUpdateCampaignModel): Promise<void>;
450
+ static updateCreator(id: string, creatorAddress: string): Promise<void>;
420
451
  static updateMetaData(id: string, params: string): Promise<{
421
452
  type: string;
422
453
  id: string;
@@ -431,5 +462,6 @@ export declare abstract class CampaignRepository {
431
462
  amount: string;
432
463
  opportunityId: string;
433
464
  creatorAddress: string;
465
+ manualOverrides: import("../../../../database/api/.generated").$Enums.CampaignManualOverride[];
434
466
  }>;
435
467
  }
@@ -2,7 +2,6 @@ import { CampaignService } from "./campaign.service";
2
2
  import { TokenService } from "../token/token.service";
3
3
  import { log } from "../../../utils/logger";
4
4
  import { apiDbClient, engineDbClient } from "../../../utils/prisma";
5
- import { ALL_CAMPAIGNS_FOR_CHAIN_AFTER } from "../../../utils/queries/allCampaigns";
6
5
  import { Prisma, RunStatus } from "../../../../database/api/.generated";
7
6
  import { MAX_COMPUTE_JOB_TIME } from "@sdk";
8
7
  import moment from "moment";
@@ -126,6 +125,17 @@ export class CampaignRepository {
126
125
  },
127
126
  });
128
127
  }
128
+ static async countLives(query) {
129
+ const now = moment().unix();
130
+ const where = {
131
+ ...query,
132
+ endTimestamp: { gte: now },
133
+ startTimestamp: { lte: now },
134
+ };
135
+ return await apiDbClient.campaign.count({
136
+ where,
137
+ });
138
+ }
129
139
  /**
130
140
  * Upserts a campaign in the database. If the campaign already exists, it updates the existing record;
131
141
  * otherwise, it creates a new one.
@@ -133,6 +143,8 @@ export class CampaignRepository {
133
143
  * @param {CreateCampaignModel} campaign - The campaign data to be upserted.
134
144
  * @returns The upserted campaign record.
135
145
  *
146
+ * @dev Should be the only way of creating campaigns in the database.
147
+ *
136
148
  * @throws {Error} If unable to fetch data for the reward token.
137
149
  *
138
150
  * @remarks
@@ -154,12 +166,18 @@ export class CampaignRepository {
154
166
  if (!rewardToken) {
155
167
  throw new Error(`unable to fetch data for token ${campaign.rewardTokenAddress}`);
156
168
  }
169
+ const previousCampaign = await CampaignRepository.findUnique(campaign.id);
170
+ const creatorAddress = previousCampaign?.manualOverrides?.includes("creatorAddress")
171
+ ? previousCampaign.creatorAddress
172
+ : campaign.creator;
157
173
  const params = JSON.parse(campaign.params);
158
- const opportunityId = OpportunityService.hashId({
159
- chainId: campaign.computeChainId,
160
- identifier: campaign.opportunityIdentifier,
161
- type: campaignType,
162
- });
174
+ const opportunityId = previousCampaign?.manualOverrides?.includes("opportunityId")
175
+ ? previousCampaign.opportunityId
176
+ : OpportunityService.hashId({
177
+ chainId: campaign.computeChainId,
178
+ identifier: campaign.opportunityIdentifier,
179
+ type: campaignType,
180
+ });
163
181
  const data = {
164
182
  id: campaign.id,
165
183
  amount: campaign.amount,
@@ -175,9 +193,9 @@ export class CampaignRepository {
175
193
  },
176
194
  Creator: {
177
195
  connectOrCreate: {
178
- where: { address: campaign.creator },
196
+ where: { address: creatorAddress },
179
197
  create: {
180
- address: campaign.creator,
198
+ address: creatorAddress,
181
199
  },
182
200
  },
183
201
  },
@@ -202,83 +220,12 @@ export class CampaignRepository {
202
220
  log.error(`Failed to upsert campaign ${campaign.campaignId}`, err);
203
221
  }
204
222
  }
205
- static async upsertMany(campaigns) {
206
- if (!campaigns.length)
207
- return { success: 0, fail: 0 };
208
- const campaignType = CampaignService.getTypeFromV3(campaigns[0].type);
209
- const data = [];
210
- for (const campaign of campaigns) {
211
- const [rewardToken] = await TokenService.getManyOrCreate([
212
- { chainId: campaign.chainId, address: campaign.rewardTokenAddress },
213
- ]);
214
- const opportunityId = OpportunityService.hashId({
215
- chainId: campaign.computeChainId,
216
- identifier: campaign.opportunityIdentifier,
217
- type: campaignType,
218
- });
219
- data.push({
220
- id: campaign.id,
221
- amount: campaign.amount,
222
- campaignId: campaign.campaignId,
223
- endTimestamp: BigInt(campaign.endTimestamp),
224
- params: JSON.parse(campaign.params),
225
- startTimestamp: BigInt(campaign.startTimestamp),
226
- type: campaignType,
227
- ComputeChain: {
228
- connect: {
229
- id: campaign.computeChainId,
230
- },
231
- },
232
- Creator: {
233
- connectOrCreate: {
234
- where: { address: campaign.creator },
235
- create: { address: campaign.creator },
236
- },
237
- },
238
- Opportunity: {
239
- connect: { id: opportunityId },
240
- },
241
- RewardToken: {
242
- connect: rewardToken ? { id: TokenService.hashId(rewardToken) } : undefined,
243
- },
244
- subType: campaign.subType,
245
- DistributionChain: { connect: { id: campaign.chainId } },
246
- });
247
- }
248
- const failedCampaigns = [];
249
- const successCampaigns = [];
250
- for (const campaign of data) {
251
- try {
252
- await apiDbClient.campaign.upsert({
253
- where: {
254
- // TODO: use id
255
- id: CampaignService.hashId({
256
- campaignId: campaign.campaignId,
257
- distributionChain: campaign.DistributionChain.connect?.id,
258
- }),
259
- },
260
- create: campaign,
261
- update: campaign,
262
- });
263
- successCampaigns.push(campaign);
264
- }
265
- catch (err) {
266
- log.error(`Failed to upsert campaign ${campaign.campaignId}`, err);
267
- failedCampaigns.push(campaign);
268
- }
269
- }
270
- return { success: successCampaigns.length, fail: failedCampaigns.length };
271
- }
272
223
  /**
273
- * Fetches the campaign data for a v3 campaign in database
274
- * @param chainId
275
- * @param timestamp from which campaigns endTimestamp are filtered
276
- * @returns
224
+ * Retrieves a campaign from the engine database by its chain and campaign id.
225
+ * @dev Types are different from the API database.
226
+ * @dev IDs are different from the API database.
227
+ * id in the engine database = campaignId in the API database
277
228
  */
278
- static async getFromEngineDb(chainId, timestamp) {
279
- //TODO use a typesafe fetching methode (this one is from campaignUpdater)
280
- return (await engineDbClient.$queryRaw(ALL_CAMPAIGNS_FOR_CHAIN_AFTER(chainId, timestamp)));
281
- }
282
229
  static async getFromEngineDbWithId(campaignIds) {
283
230
  return await engineDbClient.campaigns.findMany({
284
231
  where: {
@@ -291,18 +238,15 @@ export class CampaignRepository {
291
238
  },
292
239
  });
293
240
  }
294
- static async checkIfExist(id) {
295
- return !!(await apiDbClient.campaign.findFirst({
296
- select: {
297
- id: true,
298
- },
299
- where: {
300
- id,
301
- },
302
- }));
303
- }
304
241
  static async findUnique(id) {
305
242
  return await apiDbClient.campaign.findUnique({
243
+ include: {
244
+ DistributionChain: true,
245
+ ComputeChain: true,
246
+ RewardToken: true,
247
+ CampaignStatus: true,
248
+ Creator: true,
249
+ },
306
250
  where: {
307
251
  id,
308
252
  },
@@ -410,30 +354,6 @@ export class CampaignRepository {
410
354
  const args = CampaignRepository.transformQueryToPrismaFilters(query);
411
355
  return await apiDbClient.campaign.count(args);
412
356
  }
413
- static async countLives(chainId) {
414
- const now = moment().unix();
415
- return await apiDbClient.campaign.count({
416
- where: {
417
- distributionChainId: chainId,
418
- endTimestamp: {
419
- gte: now,
420
- },
421
- startTimestamp: {
422
- lte: now,
423
- },
424
- },
425
- });
426
- }
427
- static async findManyCampaignId(chainId) {
428
- return await apiDbClient.campaign.findMany({
429
- select: {
430
- campaignId: true,
431
- },
432
- where: {
433
- distributionChainId: chainId,
434
- },
435
- });
436
- }
437
357
  static async findChains() {
438
358
  const campaigns = await apiDbClient.campaign.findMany({
439
359
  select: { distributionChainId: true, id: true },
@@ -443,13 +363,55 @@ export class CampaignRepository {
443
363
  return acc;
444
364
  }, {});
445
365
  }
366
+ static async addManualOverride(id, field) {
367
+ const manualOverrides = (await apiDbClient.campaign.findUnique({
368
+ where: { id },
369
+ select: { manualOverrides: true },
370
+ }))?.manualOverrides ?? [];
371
+ if (!manualOverrides?.includes(field))
372
+ manualOverrides?.push(field);
373
+ await apiDbClient.campaign.update({
374
+ where: { id },
375
+ data: {
376
+ manualOverrides: {
377
+ set: manualOverrides,
378
+ },
379
+ },
380
+ });
381
+ }
382
+ static async removeManualOverride(id, field) {
383
+ const manualOverrides = (await apiDbClient.campaign.findUnique({
384
+ where: { id },
385
+ select: { manualOverrides: true },
386
+ }))?.manualOverrides ?? [];
387
+ await apiDbClient.campaign.update({
388
+ where: { id },
389
+ data: {
390
+ manualOverrides: {
391
+ set: manualOverrides.filter(override => override !== field),
392
+ },
393
+ },
394
+ });
395
+ }
446
396
  static async updateOpportunity(id, data) {
447
- const updateData = {
448
- Opportunity: {
449
- connect: { id: data.opportunityId },
397
+ await apiDbClient.campaign.update({
398
+ where: { id },
399
+ data: {
400
+ Opportunity: {
401
+ connect: { id: data.opportunityId },
402
+ },
450
403
  },
451
- };
452
- return await apiDbClient.campaign.update({ where: { id }, data: updateData });
404
+ });
405
+ await CampaignRepository.addManualOverride(id, "opportunityId");
406
+ }
407
+ static async updateCreator(id, creatorAddress) {
408
+ await apiDbClient.campaign.update({
409
+ where: { id },
410
+ data: {
411
+ creatorAddress: creatorAddress,
412
+ },
413
+ });
414
+ await CampaignRepository.addManualOverride(id, "creatorAddress");
453
415
  }
454
416
  static async updateMetaData(id, params) {
455
417
  const updateData = {