@merkl/api 0.10.249 → 0.10.251

Sign up to get free protection for your applications and to get access to all the features.
@@ -406,6 +406,7 @@ declare const eden: {
406
406
  page?: number | undefined;
407
407
  chainId?: string | undefined;
408
408
  action?: string | undefined;
409
+ creatorAddress?: string | undefined;
409
410
  mainProtocolId?: string | undefined;
410
411
  order?: string | undefined;
411
412
  test?: boolean | undefined;
@@ -516,6 +517,7 @@ declare const eden: {
516
517
  page?: number | undefined;
517
518
  chainId?: string | undefined;
518
519
  action?: string | undefined;
520
+ creatorAddress?: string | undefined;
519
521
  mainProtocolId?: string | undefined;
520
522
  order?: string | undefined;
521
523
  test?: boolean | undefined;
@@ -541,6 +543,7 @@ declare const eden: {
541
543
  page?: number | undefined;
542
544
  chainId?: string | undefined;
543
545
  action?: string | undefined;
546
+ creatorAddress?: string | undefined;
544
547
  mainProtocolId?: string | undefined;
545
548
  order?: string | undefined;
546
549
  test?: boolean | undefined;
@@ -557,6 +560,7 @@ declare const eden: {
557
560
  campaigns: {
558
561
  index: {
559
562
  post: (body: {
563
+ tags?: string[] | undefined;
560
564
  identifier?: string | undefined;
561
565
  subType?: number | undefined;
562
566
  type: number;
@@ -2929,6 +2933,7 @@ export declare const MerklApi: (domain: string | import("elysia").default<"", fa
2929
2933
  page?: number | undefined;
2930
2934
  chainId?: string | undefined;
2931
2935
  action?: string | undefined;
2936
+ creatorAddress?: string | undefined;
2932
2937
  mainProtocolId?: string | undefined;
2933
2938
  order?: string | undefined;
2934
2939
  test?: boolean | undefined;
@@ -3044,6 +3049,7 @@ export declare const MerklApi: (domain: string | import("elysia").default<"", fa
3044
3049
  page?: number | undefined;
3045
3050
  chainId?: string | undefined;
3046
3051
  action?: string | undefined;
3052
+ creatorAddress?: string | undefined;
3047
3053
  mainProtocolId?: string | undefined;
3048
3054
  order?: string | undefined;
3049
3055
  test?: boolean | undefined;
@@ -3340,6 +3346,7 @@ export declare const MerklApi: (domain: string | import("elysia").default<"", fa
3340
3346
  page?: number | undefined;
3341
3347
  chainId?: string | undefined;
3342
3348
  action?: string | undefined;
3349
+ creatorAddress?: string | undefined;
3343
3350
  mainProtocolId?: string | undefined;
3344
3351
  order?: string | undefined;
3345
3352
  test?: boolean | undefined;
@@ -3397,6 +3404,7 @@ export declare const MerklApi: (domain: string | import("elysia").default<"", fa
3397
3404
  index: {
3398
3405
  post: {
3399
3406
  body: {
3407
+ tags?: string[] | undefined;
3400
3408
  identifier?: string | undefined;
3401
3409
  subType?: number | undefined;
3402
3410
  type: number;
@@ -6598,6 +6606,7 @@ export declare const MerklApi: (domain: string | import("elysia").default<"", fa
6598
6606
  page?: number | undefined;
6599
6607
  chainId?: string | undefined;
6600
6608
  action?: string | undefined;
6609
+ creatorAddress?: string | undefined;
6601
6610
  mainProtocolId?: string | undefined;
6602
6611
  order?: string | undefined;
6603
6612
  test?: boolean | undefined;
@@ -6708,6 +6717,7 @@ export declare const MerklApi: (domain: string | import("elysia").default<"", fa
6708
6717
  page?: number | undefined;
6709
6718
  chainId?: string | undefined;
6710
6719
  action?: string | undefined;
6720
+ creatorAddress?: string | undefined;
6711
6721
  mainProtocolId?: string | undefined;
6712
6722
  order?: string | undefined;
6713
6723
  test?: boolean | undefined;
@@ -6733,6 +6743,7 @@ export declare const MerklApi: (domain: string | import("elysia").default<"", fa
6733
6743
  page?: number | undefined;
6734
6744
  chainId?: string | undefined;
6735
6745
  action?: string | undefined;
6746
+ creatorAddress?: string | undefined;
6736
6747
  mainProtocolId?: string | undefined;
6737
6748
  order?: string | undefined;
6738
6749
  test?: boolean | undefined;
@@ -6749,6 +6760,7 @@ export declare const MerklApi: (domain: string | import("elysia").default<"", fa
6749
6760
  campaigns: {
6750
6761
  index: {
6751
6762
  post: (body: {
6763
+ tags?: string[] | undefined;
6752
6764
  identifier?: string | undefined;
6753
6765
  subType?: number | undefined;
6754
6766
  type: number;
@@ -187,6 +187,7 @@ declare const app: Elysia<"", false, {
187
187
  page?: number | undefined;
188
188
  chainId?: string | undefined;
189
189
  action?: string | undefined;
190
+ creatorAddress?: string | undefined;
190
191
  mainProtocolId?: string | undefined;
191
192
  order?: string | undefined;
192
193
  test?: boolean | undefined;
@@ -302,6 +303,7 @@ declare const app: Elysia<"", false, {
302
303
  page?: number | undefined;
303
304
  chainId?: string | undefined;
304
305
  action?: string | undefined;
306
+ creatorAddress?: string | undefined;
305
307
  mainProtocolId?: string | undefined;
306
308
  order?: string | undefined;
307
309
  test?: boolean | undefined;
@@ -598,6 +600,7 @@ declare const app: Elysia<"", false, {
598
600
  page?: number | undefined;
599
601
  chainId?: string | undefined;
600
602
  action?: string | undefined;
603
+ creatorAddress?: string | undefined;
601
604
  mainProtocolId?: string | undefined;
602
605
  order?: string | undefined;
603
606
  test?: boolean | undefined;
@@ -655,6 +658,7 @@ declare const app: Elysia<"", false, {
655
658
  index: {
656
659
  post: {
657
660
  body: {
661
+ tags?: string[] | undefined;
658
662
  identifier?: string | undefined;
659
663
  subType?: number | undefined;
660
664
  type: number;
@@ -16,6 +16,7 @@ export declare const CampaignController: Elysia<"/campaigns", false, {
16
16
  index: {
17
17
  post: {
18
18
  body: {
19
+ tags?: string[] | undefined;
19
20
  identifier?: string | undefined;
20
21
  subType?: number | undefined;
21
22
  type: number;
@@ -100,6 +100,7 @@ export declare const CreateCampaignDto: import("@sinclair/typebox").TObject<{
100
100
  startTimestamp: import("@sinclair/typebox").TString;
101
101
  endTimestamp: import("@sinclair/typebox").TString;
102
102
  params: import("@sinclair/typebox").TString;
103
+ tags: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TArray<import("@sinclair/typebox").TString>>;
103
104
  }>;
104
105
  export declare const GetCampaignQueryDto: import("@sinclair/typebox").TObject<{
105
106
  creatorTag: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TString>;
@@ -61,6 +61,7 @@ export const CreateCampaignDto = t.Object({
61
61
  startTimestamp: t.String(),
62
62
  endTimestamp: t.String(),
63
63
  params: t.String(),
64
+ tags: t.Optional(t.Array(t.String())),
64
65
  });
65
66
  export const GetCampaignQueryDto = t.Object({
66
67
  creatorTag: t.Optional(t.String({ description: "Filter campaigns created by a user who has a specific tag" })),
@@ -106,6 +106,7 @@ export class CampaignRepository {
106
106
  connect: metadata.mainProtocol && { id: metadata.mainProtocol },
107
107
  },
108
108
  depositUrl: !!params.url ? params.url : undefined,
109
+ tags: metadata.tags,
109
110
  },
110
111
  },
111
112
  },
@@ -188,6 +189,7 @@ export class CampaignRepository {
188
189
  id: campaignToOpp[campaign.id].mainProtocol,
189
190
  },
190
191
  },
192
+ tags: campaignToOpp[campaign.id].tags,
191
193
  },
192
194
  },
193
195
  },
@@ -9,6 +9,7 @@ import { NETWORK_LABELS } from "@sdk";
9
9
  import moment from "moment";
10
10
  import { StatusService } from "../status";
11
11
  import { TokenService } from "../token";
12
+ import { UserService } from "../user";
12
13
  export class CampaignService {
13
14
  static hashId(campaign) {
14
15
  return Bun.hash(`${campaign.distributionChain}${campaign.campaignId}`).toString();
@@ -19,6 +20,10 @@ export class CampaignService {
19
20
  id,
20
21
  ...campaign,
21
22
  });
23
+ opportunityMetadata.tags = [
24
+ ...((await UserService.findUnique(campaign.creator))?.tags ?? []),
25
+ ...(campaign?.tags ?? []),
26
+ ];
22
27
  return await CampaignRepository.upsert({ id, ...campaign }, opportunityMetadata);
23
28
  }
24
29
  static async createMany(campaigns) {
@@ -33,6 +38,10 @@ export class CampaignService {
33
38
  id,
34
39
  ...campaign,
35
40
  });
41
+ oppMetadata.tags = [
42
+ ...((await UserService.findUnique(campaign.creator))?.tags ?? []),
43
+ ...(campaign?.tags ?? []),
44
+ ];
36
45
  campaignToOppMetadata[id] = oppMetadata;
37
46
  campaignsToInsert.push({ id, ...campaign });
38
47
  }
@@ -5,7 +5,7 @@ export class ClaimService {
5
5
  // ─── Get Historical Claims ─────────────────────────────────────────────────
6
6
  static async getHistoricalClaims(params, chainFilter = []) {
7
7
  const roots = (await MerklRootService.fetchAll()).map(r => r.live);
8
- const rewards = await RewardService.getByRecipient(params.address, roots, true, chainFilter);
8
+ const rewards = await RewardService.getByRecipient(params.address, roots, true, true, chainFilter);
9
9
  const filteredRewards = chainFilter.length
10
10
  ? rewards.filter(reward => chainFilter.includes(reward.RewardToken.chainId))
11
11
  : rewards;
@@ -56,6 +56,7 @@ export declare const OpportunityController: Elysia<"/opportunities", false, {
56
56
  page?: number | undefined;
57
57
  chainId?: string | undefined;
58
58
  action?: string | undefined;
59
+ creatorAddress?: string | undefined;
59
60
  mainProtocolId?: string | undefined;
60
61
  order?: string | undefined;
61
62
  test?: boolean | undefined;
@@ -171,6 +172,7 @@ export declare const OpportunityController: Elysia<"/opportunities", false, {
171
172
  page?: number | undefined;
172
173
  chainId?: string | undefined;
173
174
  action?: string | undefined;
175
+ creatorAddress?: string | undefined;
174
176
  mainProtocolId?: string | undefined;
175
177
  order?: string | undefined;
176
178
  test?: boolean | undefined;
@@ -467,6 +469,7 @@ export declare const OpportunityController: Elysia<"/opportunities", false, {
467
469
  page?: number | undefined;
468
470
  chainId?: string | undefined;
469
471
  action?: string | undefined;
472
+ creatorAddress?: string | undefined;
470
473
  mainProtocolId?: string | undefined;
471
474
  order?: string | undefined;
472
475
  test?: boolean | undefined;
@@ -33,6 +33,7 @@ export type OpportunityMetadata = {
33
33
  address: string;
34
34
  }[];
35
35
  mainProtocol?: ProtocolId;
36
+ tags?: string[];
36
37
  };
37
38
  export type OpportunityUnique = {
38
39
  chainId: ChainId;
@@ -278,6 +279,7 @@ export declare const GetOpportunitiesQueryDto: import("@sinclair/typebox").TObje
278
279
  name: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TString>;
279
280
  chainId: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TRegExp>;
280
281
  action: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TRegExp>;
282
+ creatorAddress: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TString>;
281
283
  tags: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TString>;
282
284
  test: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TBoolean>;
283
285
  minimumTvl: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TNumber>;
@@ -51,6 +51,7 @@ export const GetOpportunitiesQueryDto = t.Object({
51
51
  action: t.Optional(t.RegExp(/^(POOL|HOLD|DROP|LEND|BORROW)(,(POOL|HOLD|DROP|LEND|BORROW)){0,4}$/, {
52
52
  description: "A comma seprated list actions. Legal values are: `POOL`, `HOLD`, `DROP`, `LEND`, `BORROW`",
53
53
  })),
54
+ creatorAddress: t.Optional(t.String({ description: "Filter by creator address" })),
54
55
  tags: t.Optional(t.String({ description: "Filter by tag" })),
55
56
  test: t.Optional(t.Boolean({ description: "Include opportunities with test campaigns" })),
56
57
  minimumTvl: t.Optional(t.Number({ description: "Minimum TVL threshhold in USD" })),
@@ -137,6 +137,7 @@ export class OpportunityRepository {
137
137
  const sort = (query.sort === "rewards" ? "dailyRewards" : query.sort) ?? "dailyRewards";
138
138
  const order = query.order ?? "desc";
139
139
  const test = query.test ?? false;
140
+ const creatorAddress = query.creatorAddress ?? null;
140
141
  const noFilters = Object.values(filters).every(v => v === undefined);
141
142
  const tokensFilters = tokens?.map(symbol => ({
142
143
  Tokens: { some: { symbol: { equals: symbol, mode: "insensitive" } } },
@@ -162,7 +163,16 @@ export class OpportunityRepository {
162
163
  status: !status ? undefined : { in: status },
163
164
  },
164
165
  { mainProtocolId: !protocols ? undefined : { in: protocols } },
165
- { Campaigns: test ? undefined : { some: { RewardToken: { isTest: false } } } },
166
+ {
167
+ Campaigns: test || !creatorAddress
168
+ ? undefined
169
+ : {
170
+ some: {
171
+ RewardToken: !test ? { isTest: false } : undefined,
172
+ creatorAddress: creatorAddress ? creatorAddress : undefined,
173
+ },
174
+ },
175
+ },
166
176
  ],
167
177
  },
168
178
  };
@@ -172,6 +182,7 @@ export class OpportunityRepository {
172
182
  const { page: _page, items: _items } = query;
173
183
  const page = _page ? _page : 0;
174
184
  const items = _items ? _items : 20;
185
+ const test = query.test ?? false;
175
186
  const args = OpportunityRepository.#transformQueryToPrismaFilters(query);
176
187
  return await apiDbClient.opportunity.findMany({
177
188
  take: items,
@@ -181,7 +192,9 @@ export class OpportunityRepository {
181
192
  MainProtocol: true,
182
193
  Chain: true,
183
194
  Protocols: true,
184
- Tokens: true,
195
+ Tokens: {
196
+ where: !test ? { isTest: false } : undefined,
197
+ },
185
198
  },
186
199
  ...args,
187
200
  });
@@ -65,6 +65,7 @@ export declare const v4: Elysia<"/v4", false, {
65
65
  page?: number | undefined;
66
66
  chainId?: string | undefined;
67
67
  action?: string | undefined;
68
+ creatorAddress?: string | undefined;
68
69
  mainProtocolId?: string | undefined;
69
70
  order?: string | undefined;
70
71
  test?: boolean | undefined;
@@ -180,6 +181,7 @@ export declare const v4: Elysia<"/v4", false, {
180
181
  page?: number | undefined;
181
182
  chainId?: string | undefined;
182
183
  action?: string | undefined;
184
+ creatorAddress?: string | undefined;
183
185
  mainProtocolId?: string | undefined;
184
186
  order?: string | undefined;
185
187
  test?: boolean | undefined;
@@ -476,6 +478,7 @@ export declare const v4: Elysia<"/v4", false, {
476
478
  page?: number | undefined;
477
479
  chainId?: string | undefined;
478
480
  action?: string | undefined;
481
+ creatorAddress?: string | undefined;
479
482
  mainProtocolId?: string | undefined;
480
483
  order?: string | undefined;
481
484
  test?: boolean | undefined;
@@ -533,6 +536,7 @@ export declare const v4: Elysia<"/v4", false, {
533
536
  index: {
534
537
  post: {
535
538
  body: {
539
+ tags?: string[] | undefined;
536
540
  identifier?: string | undefined;
537
541
  subType?: number | undefined;
538
542
  type: number;
@@ -64,7 +64,10 @@ export const UserController = new Elysia({ prefix: "/users", detail: { tags: ["U
64
64
  detail: { hide: true },
65
65
  })
66
66
  // ─── Sync Creator Tags with Engine DB ─────────────────────────────────
67
- .post("/sync", async () => await UserService.syncTags(), {
67
+ .post("/sync", async () => {
68
+ await UserService.syncTags();
69
+ await UserService.syncOpportunityTags();
70
+ }, {
68
71
  headers: AuthorizationHeadersDto,
69
72
  beforeHandle: BackOfficeGuard,
70
73
  detail: { hide: true },
@@ -22,4 +22,5 @@ export declare abstract class UserService {
22
22
  address: string;
23
23
  }>;
24
24
  static syncTags(): Promise<void>;
25
+ static syncOpportunityTags(): Promise<void>;
25
26
  }
@@ -1,5 +1,6 @@
1
1
  import { log } from "../../../utils/logger";
2
2
  import { engineDbClient } from "../../../utils/prisma";
3
+ import { OpportunityService } from "../opportunity";
3
4
  import { UserRepository } from "./user.repository";
4
5
  // ─── Users Services ──────────────────────────────────────────────────────────
5
6
  export class UserService {
@@ -19,6 +20,9 @@ export class UserService {
19
20
  return await UserRepository.createMany(users);
20
21
  }
21
22
  static async updateTags(user, tags) {
23
+ if (!(await UserRepository.findUnique(user))) {
24
+ await UserRepository.create({ address: user, tags: [] });
25
+ }
22
26
  return await UserRepository.updateTags(user, tags);
23
27
  }
24
28
  static async syncTags() {
@@ -47,4 +51,17 @@ export class UserService {
47
51
  }
48
52
  }
49
53
  }
54
+ static async syncOpportunityTags() {
55
+ const users = await UserRepository.findManyWithTags();
56
+ for (const user of users) {
57
+ const opportunities = await OpportunityService.getMany({ creatorAddress: user.address });
58
+ for (const opportunity of opportunities) {
59
+ if (!user.tags.every(tag => opportunity.tags.includes(tag))) {
60
+ log.local(`updating tags for opportunity ${opportunity.id}: adding ${user.tags.join(",")}`);
61
+ log.local(`opportunity tags: ${opportunity.tags.join(",")}`);
62
+ await OpportunityService.update(opportunity.id, { tags: [...opportunity.tags, ...user.tags] });
63
+ }
64
+ }
65
+ }
66
+ }
50
67
  }
@@ -27,7 +27,7 @@ export default (app) => app.use(checkQueryAddressValidity()).get("/rewards", asy
27
27
  }
28
28
  const user = query.user;
29
29
  // @Warning: this is not taking into account the creator tag filter
30
- const v4Res = await RewardService.getUserRewardsByChain(user, false, chainIds);
30
+ const v4Res = await RewardService.getUserRewardsByChain(user, false, chainIds, null, true);
31
31
  const v3Res = RewardConvertorService.convertV4toRewardV3(v4Res);
32
32
  return v3Res;
33
33
  }, { query, tags: ["Rewards"] });
@@ -45,7 +45,7 @@ export default (app) => app
45
45
  }
46
46
  }
47
47
  // @Warning: this is not taking into account the mainParameter filter
48
- const v4Res = await RewardService.getUserRewardsByChain(user, false, [chainId], query.reloadChainId ?? null);
48
+ const v4Res = await RewardService.getUserRewardsByChain(user, false, [chainId], query.reloadChainId ?? null, true);
49
49
  const v3Res = RewardConvertorService.convertV4toUserRewardV3(v4Res, proof);
50
50
  return v3Res;
51
51
  }, {