@merkl/api 0.10.186 → 0.10.187

Sign up to get free protection for your applications and to get access to all the features.
@@ -1282,7 +1282,7 @@ declare const eden: {
1282
1282
  } | null;
1283
1283
  }>>;
1284
1284
  rewards: {
1285
- full: {
1285
+ breakdowns: {
1286
1286
  get: (options?: {
1287
1287
  headers?: Record<string, unknown> | undefined;
1288
1288
  query?: Record<string, unknown> | undefined;
@@ -3606,10 +3606,11 @@ export declare const MerklApi: (domain: string | import("elysia").default<"", fa
3606
3606
  users: {
3607
3607
  ":address": {
3608
3608
  rewards: {
3609
- full: {
3609
+ breakdowns: {
3610
3610
  get: {
3611
3611
  body: unknown;
3612
3612
  params: {
3613
+ chainId?: number | undefined;
3613
3614
  address: string;
3614
3615
  };
3615
3616
  query: unknown;
@@ -5716,7 +5717,7 @@ export declare const MerklApi: (domain: string | import("elysia").default<"", fa
5716
5717
  } | null;
5717
5718
  }>>;
5718
5719
  rewards: {
5719
- full: {
5720
+ breakdowns: {
5720
5721
  get: (options?: {
5721
5722
  headers?: Record<string, unknown> | undefined;
5722
5723
  query?: Record<string, unknown> | undefined;
@@ -1631,10 +1631,11 @@ declare const app: Elysia<"", false, {
1631
1631
  users: {
1632
1632
  ":address": {
1633
1633
  rewards: {
1634
- full: {
1634
+ breakdowns: {
1635
1635
  get: {
1636
1636
  body: unknown;
1637
1637
  params: {
1638
+ chainId?: number | undefined;
1638
1639
  address: string;
1639
1640
  };
1640
1641
  query: unknown;
@@ -1,6 +1,6 @@
1
1
  import type { CacheKeys } from "../../../cache/keys";
2
2
  import type { Chain } from "../../../../database/api/.generated";
3
- import { Campaign, type CampaignDynamicData, type ChainId } from "@sdk";
3
+ import { Campaign, type CampaignDynamicData, type ChainId, type MerklChainId } from "@sdk";
4
4
  import { type LightOpportunityFromDB, type Opportunity } from "../opportunity";
5
5
  import type { CampaignIdModel, CampaignIdWithoutPageModel, CreateManyBreakdownModel, CreateManyRewardModel, DailyRewardsRecord, RegisterClaimsModel, RewardBreakdown, UpdatePendingModel } from "./reward.model";
6
6
  import { RewardRepository } from "./reward.repository";
@@ -537,7 +537,7 @@ export declare abstract class RewardService {
537
537
  root: string;
538
538
  proofs: string[];
539
539
  })[]>;
540
- static getUserRewardsByChain(user: string, withToken: boolean, chainFilter?: ChainId[]): Promise<{
540
+ static getUserRewardsByChain(user: string, withToken: boolean, chainFilter?: ChainId[], connectedChainId?: MerklChainId | null): Promise<{
541
541
  chain: Chain;
542
542
  rewards: Awaited<ReturnType<(typeof RewardService)["format"]>>;
543
543
  }[]>;
@@ -1,5 +1,5 @@
1
1
  import { log } from "../../../utils/logger";
2
- import { Campaign, DistributorService, NETWORK_LABELS } from "@sdk";
2
+ import { Campaign, DistributorService, NETWORK_LABELS, } from "@sdk";
3
3
  import moment from "moment";
4
4
  import { BlacklistService } from "../blacklist";
5
5
  import { CacheService } from "../cache";
@@ -150,7 +150,10 @@ export class RewardService {
150
150
  // -> claim is on the current root (chainData.merklRoot) -> claimed === accumulated
151
151
  if (merklRootClaimedOn === roots.live) {
152
152
  for (const breakdown of reward.Breakdown) {
153
+ if (BigInt(breakdown.claimed) === BigInt(breakdown.amount))
154
+ continue;
153
155
  breakdown.claimed = breakdown.amount; // Set unclaim to 0
156
+ await RewardRepository.updateClaimed(user, TokenService.hashId(reward.RewardToken), reward.Breakdown[0].campaignId, reward.Breakdown[0].reason, reward.Breakdown[0].amount);
154
157
  }
155
158
  }
156
159
  // -> claim is on a tree we have in db -> claimed === accumulated of the rewards of lastTree
@@ -169,7 +172,7 @@ export class RewardService {
169
172
  }
170
173
  return rewards;
171
174
  }
172
- static async getUserRewardsByChain(user, withToken, chainFilter = []) {
175
+ static async getUserRewardsByChain(user, withToken, chainFilter = [], connectedChainId = null) {
173
176
  const chains = await ChainService.findMany();
174
177
  let chainIds = chains.map(({ id }) => id).filter(id => !chainFilter.length || chainFilter.includes(id));
175
178
  /** Check if the user is blacklisted */
@@ -193,8 +196,13 @@ export class RewardService {
193
196
  throw new Error(`Chain ${chainId} not found`);
194
197
  const chainRewards = rewards.filter(reward => reward.RewardToken.chainId === chainId);
195
198
  /** Check when the last claim happened */
196
- if (chainRewards.length > 0) {
197
- promises.push(RewardService.checkLastClaim(chainId, user, merkleRoots[index], chainRewards).then(r => res.push({ chain, rewards: RewardService.format(r) })));
199
+ if ((!connectedChainId || chain.id === connectedChainId) && chainRewards.length > 0) {
200
+ promises.push(RewardService.checkLastClaim(chainId, user, merkleRoots[index], chainRewards).then(r => {
201
+ return { chain, rewards: r };
202
+ }));
203
+ }
204
+ else {
205
+ promises.push(Promise.resolve({ chain, rewards: chainRewards }));
198
206
  }
199
207
  }
200
208
  const settledPromises = await Promise.allSettled(promises);
@@ -202,6 +210,9 @@ export class RewardService {
202
210
  if (promise.status === "rejected") {
203
211
  log.error("checkLastClaim failed", promise.reason);
204
212
  }
213
+ else {
214
+ res.push({ chain: promise.value.chain, rewards: RewardService.format(promise.value.rewards) });
215
+ }
205
216
  }
206
217
  return res;
207
218
  }
@@ -1613,10 +1613,11 @@ export declare const v4: Elysia<"/v4", false, {
1613
1613
  users: {
1614
1614
  ":address": {
1615
1615
  rewards: {
1616
- full: {
1616
+ breakdowns: {
1617
1617
  get: {
1618
1618
  body: unknown;
1619
1619
  params: {
1620
+ chainId?: number | undefined;
1620
1621
  address: string;
1621
1622
  };
1622
1623
  query: unknown;
@@ -76,10 +76,11 @@ export declare const UserController: Elysia<"/users", false, {
76
76
  users: {
77
77
  ":address": {
78
78
  rewards: {
79
- full: {
79
+ breakdowns: {
80
80
  get: {
81
81
  body: unknown;
82
82
  params: {
83
+ chainId?: number | undefined;
83
84
  address: string;
84
85
  };
85
86
  query: unknown;
@@ -3,7 +3,7 @@ import { throwOnInvalidRequiredAddress, throwOnUnsupportedChainId } from "../../
3
3
  import { Elysia } from "elysia";
4
4
  import { ChainArrayDto } from "../chain";
5
5
  import { RewardService } from "../reward";
6
- import { GetManyUserQuery, UpdateUserTagsDto, UserDto, UserUniqueDto } from "./user.model";
6
+ import { GetManyUserQuery, UpdateUserTagsDto, UserDto, UserUniqueDto, UserUniqueWithChainIdDto } from "./user.model";
7
7
  import { UserService } from "./user.service";
8
8
  // ─── Users Controller ────────────────────────────────────────────────────────
9
9
  export const UserController = new Elysia({ prefix: "/users", detail: { tags: ["Users"] } })
@@ -20,13 +20,11 @@ export const UserController = new Elysia({ prefix: "/users", detail: { tags: ["U
20
20
  return await UserService.findUnique(params.address);
21
21
  })
22
22
  // ─── Get User's Rewards With Breakdown And Details for our FE ────────
23
- .get(
24
- // TODO: redefine as /:address/rewards/breakdowns to follow REST standard (URI components should be nouns)
25
- "/:address/rewards/full", async ({ params }) => {
26
- const rewardsByChain = await RewardService.getUserRewardsByChain(params.address, true);
23
+ .get("/:address/rewards/breakdowns", async ({ params }) => {
24
+ const rewardsByChain = await RewardService.getUserRewardsByChain(params.address, true, [], params.chainId ?? null);
27
25
  return RewardService.splitRewardsBreakdownByOpportunity(rewardsByChain);
28
26
  }, {
29
- params: UserUniqueDto,
27
+ params: UserUniqueWithChainIdDto,
30
28
  beforeHandle: ({ params }) => {
31
29
  params.address = throwOnInvalidRequiredAddress(params.address);
32
30
  },
@@ -8,6 +8,10 @@ export type User = Resource<"User">;
8
8
  export declare const UserUniqueDto: import("@sinclair/typebox").TObject<{
9
9
  address: import("@sinclair/typebox").TString;
10
10
  }>;
11
+ export declare const UserUniqueWithChainIdDto: import("@sinclair/typebox").TObject<{
12
+ address: import("@sinclair/typebox").TString;
13
+ chainId: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TNumber>;
14
+ }>;
11
15
  export declare const UserDto: import("@sinclair/typebox").TObject<{
12
16
  address: import("@sinclair/typebox").TString;
13
17
  tags: import("@sinclair/typebox").TArray<import("@sinclair/typebox").TString>;
@@ -23,4 +27,5 @@ export declare const UpdateUserTagsDto: import("@sinclair/typebox").TObject<{
23
27
  }>;
24
28
  export type UserUniqueModel = typeof UserUniqueDto.static;
25
29
  export type UserModel = typeof UserDto.static;
30
+ export type UserWithChainIdModel = typeof UserUniqueWithChainIdDto.static;
26
31
  export type GetManyUserModel = typeof GetManyUserQuery.static;
@@ -3,6 +3,10 @@ import { t } from "elysia";
3
3
  export const UserUniqueDto = t.Object({
4
4
  address: t.String(),
5
5
  });
6
+ export const UserUniqueWithChainIdDto = t.Object({
7
+ address: t.String(),
8
+ chainId: t.Optional(t.Numeric()),
9
+ });
6
10
  export const UserDto = t.Object({
7
11
  address: t.String(),
8
12
  tags: t.Array(t.String()),
@@ -1637,10 +1637,11 @@ declare const _default: (app: App) => import("elysia").default<"", false, {
1637
1637
  users: {
1638
1638
  ":address": {
1639
1639
  rewards: {
1640
- full: {
1640
+ breakdowns: {
1641
1641
  get: {
1642
1642
  body: unknown;
1643
1643
  params: {
1644
+ chainId?: number | undefined;
1644
1645
  address: string;
1645
1646
  };
1646
1647
  query: unknown;
@@ -1640,10 +1640,11 @@ declare const _default: (app: App) => import("elysia").default<"", false, {
1640
1640
  users: {
1641
1641
  ":address": {
1642
1642
  rewards: {
1643
- full: {
1643
+ breakdowns: {
1644
1644
  get: {
1645
1645
  body: unknown;
1646
1646
  params: {
1647
+ chainId?: number | undefined;
1647
1648
  address: string;
1648
1649
  };
1649
1650
  query: unknown;
@@ -1631,10 +1631,11 @@ declare const _default: (app: App) => import("elysia").default<"", false, {
1631
1631
  users: {
1632
1632
  ":address": {
1633
1633
  rewards: {
1634
- full: {
1634
+ breakdowns: {
1635
1635
  get: {
1636
1636
  body: unknown;
1637
1637
  params: {
1638
+ chainId?: number | undefined;
1638
1639
  address: string;
1639
1640
  };
1640
1641
  query: unknown;
@@ -1636,10 +1636,11 @@ declare const _default: (app: App) => import("elysia").default<"", false, {
1636
1636
  users: {
1637
1637
  ":address": {
1638
1638
  rewards: {
1639
- full: {
1639
+ breakdowns: {
1640
1640
  get: {
1641
1641
  body: unknown;
1642
1642
  params: {
1643
+ chainId?: number | undefined;
1643
1644
  address: string;
1644
1645
  };
1645
1646
  query: unknown;
@@ -1654,10 +1654,11 @@ declare const _default: (app: App) => import("elysia").default<"", false, {
1654
1654
  users: {
1655
1655
  ":address": {
1656
1656
  rewards: {
1657
- full: {
1657
+ breakdowns: {
1658
1658
  get: {
1659
1659
  body: unknown;
1660
1660
  params: {
1661
+ chainId?: number | undefined;
1661
1662
  address: string;
1662
1663
  };
1663
1664
  query: unknown;
@@ -1655,10 +1655,11 @@ declare const _default: (app: App) => import("elysia").default<"", false, {
1655
1655
  users: {
1656
1656
  ":address": {
1657
1657
  rewards: {
1658
- full: {
1658
+ breakdowns: {
1659
1659
  get: {
1660
1660
  body: unknown;
1661
1661
  params: {
1662
+ chainId?: number | undefined;
1662
1663
  address: string;
1663
1664
  };
1664
1665
  query: unknown;
@@ -1637,10 +1637,11 @@ declare const _default: (app: App) => import("elysia").default<"", false, {
1637
1637
  users: {
1638
1638
  ":address": {
1639
1639
  rewards: {
1640
- full: {
1640
+ breakdowns: {
1641
1641
  get: {
1642
1642
  body: unknown;
1643
1643
  params: {
1644
+ chainId?: number | undefined;
1644
1645
  address: string;
1645
1646
  };
1646
1647
  query: unknown;
@@ -1638,10 +1638,11 @@ declare const _default: (app: App) => import("elysia").default<"", false, {
1638
1638
  users: {
1639
1639
  ":address": {
1640
1640
  rewards: {
1641
- full: {
1641
+ breakdowns: {
1642
1642
  get: {
1643
1643
  body: unknown;
1644
1644
  params: {
1645
+ chainId?: number | undefined;
1645
1646
  address: string;
1646
1647
  };
1647
1648
  query: unknown;
@@ -1640,10 +1640,11 @@ declare const _default: (app: App) => import("elysia").default<"", false, {
1640
1640
  users: {
1641
1641
  ":address": {
1642
1642
  rewards: {
1643
- full: {
1643
+ breakdowns: {
1644
1644
  get: {
1645
1645
  body: unknown;
1646
1646
  params: {
1647
+ chainId?: number | undefined;
1647
1648
  address: string;
1648
1649
  };
1649
1650
  query: unknown;