@merkl/api 0.10.388 → 0.10.390

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.
@@ -2320,7 +2320,13 @@ declare const eden: {
2320
2320
  fetch?: RequestInit | undefined;
2321
2321
  }) => Promise<import("@elysiajs/eden").Treaty.TreatyResponse<{
2322
2322
  200: {
2323
- totalAmount: number;
2323
+ total: number;
2324
+ breakdown: {
2325
+ [key: number]: {
2326
+ chainAmount: number;
2327
+ percentage: number;
2328
+ };
2329
+ };
2324
2330
  };
2325
2331
  }>>;
2326
2332
  "per-month": ((params: {
@@ -3832,6 +3838,7 @@ export declare const MerklApi: (domain: string | import("elysia").default<"", fa
3832
3838
  post: {
3833
3839
  body: unknown;
3834
3840
  params: {
3841
+ campaignId?: string | undefined;
3835
3842
  id: string;
3836
3843
  };
3837
3844
  query: unknown;
@@ -6467,7 +6474,13 @@ export declare const MerklApi: (domain: string | import("elysia").default<"", fa
6467
6474
  };
6468
6475
  response: {
6469
6476
  200: {
6470
- totalAmount: number;
6477
+ total: number;
6478
+ breakdown: {
6479
+ [key: number]: {
6480
+ chainAmount: number;
6481
+ percentage: number;
6482
+ };
6483
+ };
6471
6484
  };
6472
6485
  };
6473
6486
  };
@@ -10495,7 +10508,13 @@ export declare const MerklApi: (domain: string | import("elysia").default<"", fa
10495
10508
  fetch?: RequestInit | undefined;
10496
10509
  }) => Promise<import("@elysiajs/eden").Treaty.TreatyResponse<{
10497
10510
  200: {
10498
- totalAmount: number;
10511
+ total: number;
10512
+ breakdown: {
10513
+ [key: number]: {
10514
+ chainAmount: number;
10515
+ percentage: number;
10516
+ };
10517
+ };
10499
10518
  };
10500
10519
  }>>;
10501
10520
  "per-month": ((params: {
@@ -193,6 +193,7 @@ declare const app: Elysia<"", false, {
193
193
  post: {
194
194
  body: unknown;
195
195
  params: {
196
+ campaignId?: string | undefined;
196
197
  id: string;
197
198
  };
198
199
  query: unknown;
@@ -2828,7 +2829,13 @@ declare const app: Elysia<"", false, {
2828
2829
  };
2829
2830
  response: {
2830
2831
  200: {
2831
- totalAmount: number;
2832
+ total: number;
2833
+ breakdown: {
2834
+ [key: number]: {
2835
+ chainAmount: number;
2836
+ percentage: number;
2837
+ };
2838
+ };
2832
2839
  };
2833
2840
  };
2834
2841
  };
@@ -599,16 +599,13 @@ export async function CLAMMDynamicData(chainId, campaigns) {
599
599
  blacklistedBalance1 = poolBalanceToken1;
600
600
  blacklistedLiquidity = poolTotalLiquidity;
601
601
  // Get all beefy staker is whitelisted, get a list of all senders
602
- const beefyStakerCount = almDetails.filter(a => a.type === ALM.BeefyStaker).length;
603
- const beefyCount = almDetails.filter(a => a.type === ALM.Beefy).length;
604
- if (c.campaignParameters.whitelist.length === beefyStakerCount + beefyCount ||
605
- c.campaignParameters.whitelist.length === beefyStakerCount) {
606
- let targetToMatch = "";
607
- for (const alm of almDetails.filter(a => a.type === ALM.BeefyStaker)) {
608
- if (alm.sender === c.campaignParameters.whitelist[0]) {
609
- targetToMatch = alm.target;
610
- }
602
+ let targetToMatch = "";
603
+ for (const alm of almDetails.filter(a => a.type === ALM.BeefyStaker)) {
604
+ if (c.campaignParameters.whitelist.includes(alm.sender)) {
605
+ targetToMatch = alm.target;
611
606
  }
607
+ }
608
+ if (targetToMatch !== "") {
612
609
  for (const alm of almDetails.filter(a => a.type === ALM.Beefy)) {
613
610
  if (targetToMatch === alm.sender.toLowerCase()) {
614
611
  c.campaignParameters.whitelist.push(alm.owner);
@@ -51,7 +51,13 @@ export declare const AccountingController: Elysia<"/accounting", false, {
51
51
  };
52
52
  response: {
53
53
  200: {
54
- totalAmount: number;
54
+ total: number;
55
+ breakdown: {
56
+ [key: number]: {
57
+ chainAmount: number;
58
+ percentage: number;
59
+ };
60
+ };
55
61
  };
56
62
  };
57
63
  };
@@ -12,7 +12,7 @@ export const AccountingController = new Elysia({ prefix: "/accounting", detail:
12
12
  })
13
13
  .group("/revenues", app => {
14
14
  return app
15
- .get("", async () => await AccountingService.getRevenue(), {
15
+ .get("", async () => await AccountingService.getAllRevenueBreakdownByChain(), {
16
16
  headers: AuthorizationHeadersDto,
17
17
  beforeHandle: async ({ headers }) => {
18
18
  await BackOfficeGuard({ headers });
@@ -1,5 +1,5 @@
1
1
  import type { GetTransactionsQueryModel } from "./";
2
- import type { ChainId } from "@sdk";
2
+ import { ChainId } from "@sdk";
3
3
  export declare class AccountingService {
4
4
  static hashId(chainId: ChainId, fromTokenId: string, toTokenId: string, timestamp: number): string;
5
5
  static getTokenId(chainId: number, address: string): string;
@@ -21,6 +21,15 @@ export declare class AccountingService {
21
21
  static getRevenueByChain(chainId: number): Promise<{
22
22
  totalAmount: number;
23
23
  }>;
24
+ static getAllRevenueBreakdownByChain(): Promise<{
25
+ total: number;
26
+ breakdown: {
27
+ [key: number]: {
28
+ chainAmount: number;
29
+ percentage: number;
30
+ };
31
+ };
32
+ }>;
24
33
  static getMonthlyRevenue(year: number, month: number): Promise<{
25
34
  totalAmount: number;
26
35
  from: string;
@@ -1,5 +1,6 @@
1
1
  import { AccountingRepository } from "./accounting.repository";
2
2
  import { TokenService } from "../token";
3
+ import { ChainId } from "@sdk";
3
4
  export class AccountingService {
4
5
  static hashId(chainId, fromTokenId, toTokenId, timestamp) {
5
6
  return Bun.hash(`${chainId}${fromTokenId}${toTokenId}${timestamp}`).toString();
@@ -26,6 +27,24 @@ export class AccountingService {
26
27
  }
27
28
  return { totalAmount };
28
29
  }
30
+ static async getAllRevenueBreakdownByChain() {
31
+ const breakdown = {};
32
+ let consolidatedAmount = 0;
33
+ for (const chainId of Object.values(ChainId).filter(id => typeof id === "number")) {
34
+ const data = await AccountingRepository.getForMultisigByChain(chainId);
35
+ let totalAmount = 0;
36
+ for (const tx of data) {
37
+ totalAmount += Number(tx.amountIn);
38
+ }
39
+ breakdown[chainId] = { chainAmount: totalAmount, percentage: 0 };
40
+ consolidatedAmount += totalAmount;
41
+ }
42
+ for (const chainId of Object.values(ChainId).filter(id => typeof id === "number")) {
43
+ const totalAmount = breakdown[chainId].chainAmount;
44
+ breakdown[chainId] = { chainAmount: totalAmount, percentage: (totalAmount * 100) / consolidatedAmount };
45
+ }
46
+ return { total: consolidatedAmount, breakdown };
47
+ }
29
48
  static async getMonthlyRevenue(year, month) {
30
49
  const startDate = new Date(year, month - 1, 1);
31
50
  const endDate = new Date(year, month, 0, 23, 59, 59);
@@ -92,6 +92,10 @@ export class CampaignService {
92
92
  await OpportunityService.createFromCampaign(campaign);
93
93
  campaignsToInsert.push({ id, ...campaign });
94
94
  }
95
+ // } else {
96
+ // console.log("Updating status from campaign");
97
+ // await OpportunityService.updateStatusFromCampaign(campaign);
98
+ // }
95
99
  }
96
100
  catch (err) {
97
101
  log.error(`Cannot get Opportunity metadata for campaign ${campaign.campaignId} of type ${campaign.type}`, err);
@@ -62,6 +62,7 @@ export declare const OpportunityController: Elysia<"/opportunities", false, {
62
62
  post: {
63
63
  body: unknown;
64
64
  params: {
65
+ campaignId?: string | undefined;
65
66
  id: string;
66
67
  };
67
68
  query: unknown;
@@ -3,7 +3,7 @@ import { BackOfficeGuard } from "../../../guards/BackOffice.guard";
3
3
  import { AuthorizationHeadersDto, TokenAuthGuard } from "../../../guards/TokenAuth.guard";
4
4
  import Elysia, { t } from "elysia";
5
5
  import { GetCampaignQueryDto } from "../campaign";
6
- import { CreateOpportunityDto, GetOpportunitiesQueryDto, GetOpportunityQueryDto, OpportunityAggregateFieldDto, OpportunityIdDto, OpportunityResourceDto, OpportunityUniqueDto, OpportunityWithCampaignsResourceDto, UpdateOpportunityDto, } from "./opportunity.model";
6
+ import { CreateOpportunityDto, GetOpportunitiesQueryDto, GetOpportunityQueryDto, OpportunityAggregateFieldDto, OpportunityIdDto, OpportunityResourceDto, OpportunityUniqueDto, OpportunityUniqueUpdateDto, OpportunityWithCampaignsResourceDto, UpdateOpportunityDto, } from "./opportunity.model";
7
7
  import { OpportunityService } from "./opportunity.service";
8
8
  import { transformId } from "./transform-id.pipe";
9
9
  import { validateId } from "./validate-id.pipe";
@@ -41,7 +41,7 @@ export const OpportunityController = new Elysia({
41
41
  }, {
42
42
  beforeHandle: BackOfficeGuard,
43
43
  headers: AuthorizationHeadersDto,
44
- params: OpportunityUniqueDto,
44
+ params: OpportunityUniqueUpdateDto,
45
45
  detail: { hide: true },
46
46
  })
47
47
  // ─── Get All Opportunities ───────────────────────────────────────────
@@ -272,6 +272,10 @@ export declare const OpportunityWithCampaignsResourceDto: import("@sinclair/type
272
272
  export declare const OpportunityUniqueDto: import("@sinclair/typebox").TObject<{
273
273
  id: import("@sinclair/typebox").TString;
274
274
  }>;
275
+ export declare const OpportunityUniqueUpdateDto: import("@sinclair/typebox").TObject<{
276
+ id: import("@sinclair/typebox").TString;
277
+ campaignId: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TString>;
278
+ }>;
275
279
  export declare const AggregationResourceDto: import("@sinclair/typebox").TObject<{
276
280
  sum: import("@sinclair/typebox").TNumber;
277
281
  }>;
@@ -38,6 +38,13 @@ export const OpportunityUniqueDto = t.Object({
38
38
  description: "The id of the opportunity. You can find opportunities including their id at [GET /v4/opportunities](#tag/opportunities/GET/v4/opportunities/)",
39
39
  }),
40
40
  });
41
+ export const OpportunityUniqueUpdateDto = t.Object({
42
+ id: t.String({
43
+ pattern: "(([0-9]*)-([0-9A-Z]*)-(0x([0-9A-Za-z])*))|([0-9]{1,20})",
44
+ description: "The id of the opportunity. You can find opportunities including their id at [GET /v4/opportunities](#tag/opportunities/GET/v4/opportunities/)",
45
+ }),
46
+ campaignId: t.Optional(t.String({ description: "The id of the campaign you want to reparse with" })),
47
+ });
41
48
  export const AggregationResourceDto = t.Object({
42
49
  sum: t.Number(),
43
50
  });
@@ -63,10 +63,34 @@ export declare abstract class OpportunityService {
63
63
  depositUrl: any;
64
64
  tags: string[];
65
65
  }>;
66
+ static updateStatusFromCampaign(campaign: Omit<CreateCampaignModel, "id">, upsert?: boolean): Promise<{
67
+ id: string;
68
+ chainId: number;
69
+ type: import("../../../../database/api/.generated").$Enums.CampaignType;
70
+ identifier: string;
71
+ name: string;
72
+ status: "PAST" | "LIVE" | "SOON";
73
+ action: import("../../../../database/api/.generated").$Enums.OpportunityAction;
74
+ tokens: {
75
+ price?: number | null | undefined;
76
+ symbol: string;
77
+ name: string | null;
78
+ id: string;
79
+ icon: string;
80
+ chainId: number;
81
+ address: string;
82
+ decimals: number;
83
+ verified: boolean;
84
+ isTest: boolean;
85
+ }[];
86
+ mainProtocol: "morpho" | "arthswap" | "baseswap" | "camelot" | "crust" | "fenix" | "horiza" | "izumi" | "kim" | "pancakeswap-v3" | "quickswap-algebra" | "quickswap-uni" | "ramses" | "retro" | "stryke" | "stryke-pcs" | "stryke-sushi" | "sushiswap-v3" | "swapr" | "thruster" | "uniswap-v3" | "voltage" | "zero" | "koi" | "supswap-v3" | "zkswap" | "thirdtrade" | "uniswap-v2" | "velodrome" | "aerodrome" | "balancer" | "curve" | "cross_curve" | "curveNPool" | "aura" | "akron" | "beefy" | "dragonswap" | "poolside" | "syncswap-v3" | "neptune" | "zkSwapThreePool" | "syncswap" | "rfx" | "radiant" | "aave" | "euler" | "gearbox" | "compound" | "sturdy" | "frax" | "ionic" | "moonwell" | "fluid" | "silo" | "coumpound" | "dolomite" | "badger" | "ajna" | "layerbank" | "ion" | "venus" | "woofi" | "reactor_fusion" | "eigenlayer" | "vest" | "zerolend" | "hyperdrive" | undefined;
87
+ depositUrl: string | undefined;
88
+ tags: string[];
89
+ }>;
66
90
  /**
67
91
  * deletes and recreates an opportunity with fresh data
68
92
  */
69
- static recreate(opportunityId: string | OpportunityUnique): Promise<{
93
+ static recreate(opportunityId: string | OpportunityUnique, campaignId?: string): Promise<{
70
94
  id: string;
71
95
  chainId: number;
72
96
  type: import("../../../../database/api/.generated").$Enums.CampaignType;
@@ -152,15 +152,45 @@ export class OpportunityService {
152
152
  await OpportunityRepository.create(opportunity, upsert);
153
153
  return opportunity;
154
154
  }
155
+ static async updateStatusFromCampaign(campaign, upsert = true) {
156
+ const campaignType = CampaignService.getTypeFromV3(campaign.type);
157
+ const metadata = await OpportunityService.#getMetadata(campaign);
158
+ const opportunityId = OpportunityService.hashId({
159
+ chainId: campaign.computeChainId,
160
+ identifier: campaign.opportunityIdentifier,
161
+ type: campaignType,
162
+ });
163
+ const currentOpportunity = await OpportunityService.getUniqueOrThrow(opportunityId, true);
164
+ const now = moment().unix();
165
+ const opportunity = {
166
+ id: opportunityId,
167
+ chainId: campaign.computeChainId,
168
+ type: campaignType,
169
+ identifier: campaign.opportunityIdentifier, // mainParameter
170
+ name: currentOpportunity.name,
171
+ status: now >= +campaign.startTimestamp && now < +campaign.endTimestamp
172
+ ? Status.LIVE
173
+ : now > +campaign.endTimestamp
174
+ ? Status.PAST
175
+ : Status.SOON,
176
+ action: metadata.action,
177
+ tokens: currentOpportunity.tokens,
178
+ mainProtocol: metadata.mainProtocol,
179
+ depositUrl: currentOpportunity.depositUrl,
180
+ tags: currentOpportunity.tags,
181
+ };
182
+ await OpportunityRepository.create(opportunity, upsert);
183
+ return opportunity;
184
+ }
155
185
  /**
156
186
  * deletes and recreates an opportunity with fresh data
157
187
  */
158
- static async recreate(opportunityId) {
188
+ static async recreate(opportunityId, campaignId) {
159
189
  const id = typeof opportunityId === "string" ? opportunityId : OpportunityService.hashId(opportunityId);
160
190
  const opportunity = await OpportunityRepository.findUnique(id);
161
191
  if (!opportunity)
162
192
  throw new NotFoundError();
163
- const firstCampaign = opportunity?.Campaigns[0];
193
+ const firstCampaign = opportunity?.Campaigns.filter(campaign => campaignId ? campaign.campaignId === campaignId : true)[0];
164
194
  return await OpportunityService.createFromCampaign({
165
195
  ...firstCampaign,
166
196
  type: campaignTypeToEnumMap[firstCampaign.type],
@@ -26,13 +26,13 @@ export const getClammMetadata = (chainId, params) => {
26
26
  if (params.whitelist.length > 0) {
27
27
  for (const whitelist of params.whitelist) {
28
28
  if (whitelistNameString.length > 0) {
29
- whitelistNameString += "or ";
29
+ whitelistNameString += "or";
30
30
  }
31
31
  const forwarder = params.forwarders.find(x => getAddress(x.sender) === getAddress(whitelist));
32
32
  const forwarderType = forwarder?.type;
33
33
  const forwarderName = !!forwarderType ? almName(forwarderType) : null;
34
34
  if (!!forwarderName) {
35
- whitelistNameString += ` ${forwarderName}`;
35
+ whitelistNameString += ` ${forwarderName} `;
36
36
  }
37
37
  }
38
38
  }
@@ -361,6 +361,8 @@ export class RewardService {
361
361
  return { timestamp, total: 0, breakdowns: [] };
362
362
  const breakdowns = [];
363
363
  for (const { amount, rewardToken: address, chainId, startTimestamp: start, endTimestamp: end, campaignId, } of dynamicData) {
364
+ if (end < moment().unix())
365
+ continue;
364
366
  const timespan = Math.abs(end - start);
365
367
  const isWithinTimespan = moment().unix() > start && moment().unix() < end;
366
368
  const dayspan = Math.max(1, Math.floor(timespan / DAY));
@@ -71,6 +71,7 @@ export declare const v4: Elysia<"/v4", false, {
71
71
  post: {
72
72
  body: unknown;
73
73
  params: {
74
+ campaignId?: string | undefined;
74
75
  id: string;
75
76
  };
76
77
  query: unknown;
@@ -2706,7 +2707,13 @@ export declare const v4: Elysia<"/v4", false, {
2706
2707
  };
2707
2708
  response: {
2708
2709
  200: {
2709
- totalAmount: number;
2710
+ total: number;
2711
+ breakdown: {
2712
+ [key: number]: {
2713
+ chainAmount: number;
2714
+ percentage: number;
2715
+ };
2716
+ };
2710
2717
  };
2711
2718
  };
2712
2719
  };
@@ -129,6 +129,14 @@ export function generateCardName(type, typeInfo, campaign, symbols = [""]) {
129
129
  case tokenType.cian:
130
130
  return `Deposit ${typeInfo.symbolAsset} into ${typeInfo.name.replace("Ether.Fi", "Veda")}`;
131
131
  default:
132
- return `Hold ${typeInfo.name} (${campaign.campaignParameters.symbolTargetToken})`;
132
+ // OVERRIDE
133
+ switch (typeInfo.tokenAddress) {
134
+ case "0x3a8099D8FE5C072bB035381003993393072D3ec7":
135
+ return `Hold pufETH on DeSyn (dpufETH)`;
136
+ case "0x1f2aa9680910aC5a4527FA72001dC249943f60b4 ":
137
+ return `Hold pufETH on Karak (pufETH)`;
138
+ default:
139
+ return `Hold ${typeInfo.name} (${campaign.campaignParameters.symbolTargetToken})`;
140
+ }
133
141
  }
134
142
  }