@merkl/api 0.20.110 → 0.20.112
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.
- package/dist/src/eden/index.d.ts +42 -0
- package/dist/src/engine/implementations/Erc20/tvl.js +2 -1
- package/dist/src/engine/tvl/factory.js +4 -0
- package/dist/src/index.d.ts +20 -0
- package/dist/src/modules/v4/dynamicData/dynamicData.service.js +7 -3
- package/dist/src/modules/v4/router.d.ts +20 -0
- package/dist/src/modules/v4/user/user.controller.d.ts +20 -0
- package/dist/src/modules/v4/user/user.controller.js +8 -1
- package/dist/src/modules/v4/user/user.model.d.ts +3 -0
- package/dist/src/modules/v4/user/user.model.js +3 -0
- package/dist/src/modules/v4/user/user.service.d.ts +1 -0
- package/dist/src/modules/v4/user/user.service.js +32 -0
- package/dist/tsconfig.package.tsbuildinfo +1 -1
- package/package.json +1 -1
package/dist/src/eden/index.d.ts
CHANGED
@@ -3162,6 +3162,17 @@ declare const eden: {
|
|
3162
3162
|
})[];
|
3163
3163
|
}>>;
|
3164
3164
|
};
|
3165
|
+
terms: {
|
3166
|
+
get: (options: {
|
3167
|
+
headers?: Record<string, unknown> | undefined;
|
3168
|
+
query: {
|
3169
|
+
chainId: number;
|
3170
|
+
};
|
3171
|
+
fetch?: RequestInit | undefined;
|
3172
|
+
}) => Promise<import("@elysiajs/eden").Treaty.TreatyResponse<{
|
3173
|
+
200: boolean;
|
3174
|
+
}>>;
|
3175
|
+
};
|
3165
3176
|
tags: {
|
3166
3177
|
patch: (body: {
|
3167
3178
|
tags: string[];
|
@@ -8887,6 +8898,26 @@ export declare const MerklApi: (domain: string | import("elysia").default<"", fa
|
|
8887
8898
|
};
|
8888
8899
|
};
|
8889
8900
|
};
|
8901
|
+
} & {
|
8902
|
+
users: {
|
8903
|
+
":address": {
|
8904
|
+
terms: {
|
8905
|
+
get: {
|
8906
|
+
body: unknown;
|
8907
|
+
params: {
|
8908
|
+
address: string;
|
8909
|
+
};
|
8910
|
+
query: {
|
8911
|
+
chainId: number;
|
8912
|
+
};
|
8913
|
+
headers: unknown;
|
8914
|
+
response: {
|
8915
|
+
200: boolean;
|
8916
|
+
};
|
8917
|
+
};
|
8918
|
+
};
|
8919
|
+
};
|
8920
|
+
};
|
8890
8921
|
} & {
|
8891
8922
|
users: {
|
8892
8923
|
":address": {
|
@@ -14289,6 +14320,17 @@ export declare const MerklApi: (domain: string | import("elysia").default<"", fa
|
|
14289
14320
|
})[];
|
14290
14321
|
}>>;
|
14291
14322
|
};
|
14323
|
+
terms: {
|
14324
|
+
get: (options: {
|
14325
|
+
headers?: Record<string, unknown> | undefined;
|
14326
|
+
query: {
|
14327
|
+
chainId: number;
|
14328
|
+
};
|
14329
|
+
fetch?: RequestInit | undefined;
|
14330
|
+
}) => Promise<import("@elysiajs/eden").Treaty.TreatyResponse<{
|
14331
|
+
200: boolean;
|
14332
|
+
}>>;
|
14333
|
+
};
|
14292
14334
|
tags: {
|
14293
14335
|
patch: (body: {
|
14294
14336
|
tags: string[];
|
@@ -12,7 +12,7 @@ export class Erc20TVLBuilder {
|
|
12
12
|
const builder = erc20SubTypeTVLBuilderFactory(subType);
|
13
13
|
const campaignsOfSubType = campaigns.filter((_campaign, index) => subTypes[index] === subType);
|
14
14
|
if (!!builder) {
|
15
|
-
log.
|
15
|
+
log.local(`building TVLs for subtype ${subType}`);
|
16
16
|
const subTypeTVLs = await builder.build(computeChainId, campaignsOfSubType);
|
17
17
|
// Impact blacklist or whitelist
|
18
18
|
const calls = [];
|
@@ -51,6 +51,7 @@ export class Erc20TVLBuilder {
|
|
51
51
|
const result = await ChainInteractionService(computeChainId).fetchState(calls);
|
52
52
|
let index = 0;
|
53
53
|
for (const [i, { campaign }] of subTypeTVLs.entries()) {
|
54
|
+
log.local(`building TVLs for subtype ${subType} using deprecated code`);
|
54
55
|
const { campaignParameters } = campaign;
|
55
56
|
const { whitelist, blacklist } = campaignParameters;
|
56
57
|
if (whitelist?.length > 0) {
|
@@ -14,6 +14,10 @@ const map = {
|
|
14
14
|
[Campaign.AMBIENTPROCESSOR]: new AmbiantTVLBuilder(),
|
15
15
|
[Campaign.UNISWAP_V4]: new UniswapV4TVLBuilder(),
|
16
16
|
[Campaign.ERC20]: new Erc20TVLBuilder(),
|
17
|
+
[Campaign.ERC20LOGPROCESSOR]: new Erc20TVLBuilder(),
|
18
|
+
[Campaign.ERC20REBASEFIXAPR]: new Erc20TVLBuilder(),
|
19
|
+
[Campaign.ERC20_FIX_APR]: new Erc20TVLBuilder(),
|
20
|
+
[Campaign.EULER]: new Erc20TVLBuilder(),
|
17
21
|
};
|
18
22
|
export const campaignTVLBuilderFactory = (campaignType) => {
|
19
23
|
if (!map[campaignType]) {
|
package/dist/src/index.d.ts
CHANGED
@@ -3932,6 +3932,26 @@ declare const app: Elysia<"", false, {
|
|
3932
3932
|
};
|
3933
3933
|
};
|
3934
3934
|
};
|
3935
|
+
} & {
|
3936
|
+
users: {
|
3937
|
+
":address": {
|
3938
|
+
terms: {
|
3939
|
+
get: {
|
3940
|
+
body: unknown;
|
3941
|
+
params: {
|
3942
|
+
address: string;
|
3943
|
+
};
|
3944
|
+
query: {
|
3945
|
+
chainId: number;
|
3946
|
+
};
|
3947
|
+
headers: unknown;
|
3948
|
+
response: {
|
3949
|
+
200: boolean;
|
3950
|
+
};
|
3951
|
+
};
|
3952
|
+
};
|
3953
|
+
};
|
3954
|
+
};
|
3935
3955
|
} & {
|
3936
3956
|
users: {
|
3937
3957
|
":address": {
|
@@ -10,7 +10,7 @@ import { TvlService } from "@/modules/v4/tvl/tvl.service";
|
|
10
10
|
import bigintToString from "@/utils/bigintToString";
|
11
11
|
import { log } from "@/utils/logger";
|
12
12
|
import { AprType } from "@db/api";
|
13
|
-
import { Campaign as CampaignEnum, DAY, NETWORK_LABELS, } from "@sdk";
|
13
|
+
import { Campaign as CampaignEnum, DAY, NETWORK_LABELS, bigIntToNumber, } from "@sdk";
|
14
14
|
import moment from "moment";
|
15
15
|
import { AprService } from "../apr";
|
16
16
|
import { CampaignService } from "../campaign";
|
@@ -96,6 +96,7 @@ export class DynamicDataService {
|
|
96
96
|
let campaignDailyValue = await TokenService.getValueByTokenId(TokenService.hashId({ address: rewardTokenAddress, chainId: record.campaign.chainId }), dailyAmount);
|
97
97
|
// Fixed APR campaigns
|
98
98
|
if (hasFixedAprConfig(campaignParameters)) {
|
99
|
+
log.local(`[${NETWORK_LABELS[chainId]}][${CampaignEnum[type]}] calculating fixed APR for ${record.campaign.campaignId}`);
|
99
100
|
const { targetTokenPricing, rewardTokenPricing, apr: fixedApr } = campaignParameters;
|
100
101
|
const targetApr = Number(fixedApr);
|
101
102
|
if (targetTokenPricing && rewardTokenPricing) {
|
@@ -106,8 +107,11 @@ export class DynamicDataService {
|
|
106
107
|
if (targetTokenPricing && !rewardTokenPricing) {
|
107
108
|
// Case 2: Fixed # amount of reward per $ of liquidity
|
108
109
|
// Return 0 if reward token price is invalid
|
109
|
-
|
110
|
-
dailyAmount =
|
110
|
+
// targetApr represents a yearly # amount of reward per $ of liquidity
|
111
|
+
dailyAmount =
|
112
|
+
(BigInt(Math.floor((targetApr * tvl.total * 10 ** 6) / 365)) * 10n ** BigInt(rewardToken.decimals)) /
|
113
|
+
10n ** 6n;
|
114
|
+
campaignDailyValue = bigIntToNumber(dailyAmount, rewardToken.decimals) * (rewardToken.price ?? 1);
|
111
115
|
}
|
112
116
|
}
|
113
117
|
dailyRewards.total += campaignDailyValue;
|
@@ -3802,6 +3802,26 @@ export declare const v4: Elysia<"/v4", false, {
|
|
3802
3802
|
};
|
3803
3803
|
};
|
3804
3804
|
};
|
3805
|
+
} & {
|
3806
|
+
users: {
|
3807
|
+
":address": {
|
3808
|
+
terms: {
|
3809
|
+
get: {
|
3810
|
+
body: unknown;
|
3811
|
+
params: {
|
3812
|
+
address: string;
|
3813
|
+
};
|
3814
|
+
query: {
|
3815
|
+
chainId: number;
|
3816
|
+
};
|
3817
|
+
headers: unknown;
|
3818
|
+
response: {
|
3819
|
+
200: boolean;
|
3820
|
+
};
|
3821
|
+
};
|
3822
|
+
};
|
3823
|
+
};
|
3824
|
+
};
|
3805
3825
|
} & {
|
3806
3826
|
users: {
|
3807
3827
|
":address": {
|
@@ -379,6 +379,26 @@ export declare const UserController: Elysia<"/users", false, {
|
|
379
379
|
};
|
380
380
|
};
|
381
381
|
};
|
382
|
+
} & {
|
383
|
+
users: {
|
384
|
+
":address": {
|
385
|
+
terms: {
|
386
|
+
get: {
|
387
|
+
body: unknown;
|
388
|
+
params: {
|
389
|
+
address: string;
|
390
|
+
};
|
391
|
+
query: {
|
392
|
+
chainId: number;
|
393
|
+
};
|
394
|
+
headers: unknown;
|
395
|
+
response: {
|
396
|
+
200: boolean;
|
397
|
+
};
|
398
|
+
};
|
399
|
+
};
|
400
|
+
};
|
401
|
+
};
|
382
402
|
} & {
|
383
403
|
users: {
|
384
404
|
":address": {
|
@@ -3,7 +3,7 @@ import { throwOnInvalidRequiredAddress, throwOnUnsupportedChainId } from "@/util
|
|
3
3
|
import { Elysia, t } from "elysia";
|
4
4
|
import { CreatorService } from "../creator";
|
5
5
|
import { RewardService } from "../reward";
|
6
|
-
import { GetManyUserQuery, OptionalChainIdDto, UpdateUserTagsDto, UserDto, UserRewardRouteDto, UserRewardsResourceDto, UserUniqueDto, } from "./user.model";
|
6
|
+
import { CheckTerms, GetManyUserQuery, OptionalChainIdDto, UpdateUserTagsDto, UserDto, UserRewardRouteDto, UserRewardsResourceDto, UserUniqueDto, } 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"] } })
|
@@ -78,6 +78,13 @@ export const UserController = new Elysia({ prefix: "/users", detail: { tags: ["U
|
|
78
78
|
headers: AuthorizationHeadersDto,
|
79
79
|
beforeHandle: BackOfficeGuard,
|
80
80
|
detail: { hide: true },
|
81
|
+
})
|
82
|
+
// ─── Check if user has signed terms ─────────────────────────────────
|
83
|
+
.get("/:address/terms", async ({ query, params }) => await UserService.checkTerms(params?.address, query?.chainId), {
|
84
|
+
query: CheckTerms,
|
85
|
+
detail: {
|
86
|
+
description: "Check if a user address has signed Merkl's terms.",
|
87
|
+
},
|
81
88
|
})
|
82
89
|
// ─── Update User's Tags ──────────────────────────────────────────────
|
83
90
|
.patch("/:address/tags", async ({ params, body }) => UserService.updateTags(params.address, body.tags), {
|
@@ -63,6 +63,9 @@ export declare const GetManyUserQuery: import("@sinclair/typebox").TObject<{
|
|
63
63
|
page: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TNumber>;
|
64
64
|
items: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TNumber>;
|
65
65
|
}>;
|
66
|
+
export declare const CheckTerms: import("@sinclair/typebox").TObject<{
|
67
|
+
chainId: import("@sinclair/typebox").TNumber;
|
68
|
+
}>;
|
66
69
|
export declare const UpdateUserTagsDto: import("@sinclair/typebox").TObject<{
|
67
70
|
tags: import("@sinclair/typebox").TArray<import("@sinclair/typebox").TString>;
|
68
71
|
}>;
|
@@ -64,6 +64,9 @@ export const GetManyUserQuery = t.Object({
|
|
64
64
|
page: t.Optional(t.Number()),
|
65
65
|
items: t.Optional(t.Number()),
|
66
66
|
});
|
67
|
+
export const CheckTerms = t.Object({
|
68
|
+
chainId: t.Numeric(),
|
69
|
+
});
|
67
70
|
export const UpdateUserTagsDto = t.Object({
|
68
71
|
tags: t.Array(t.String()),
|
69
72
|
});
|
@@ -26,6 +26,7 @@ export declare abstract class UserService {
|
|
26
26
|
address: string;
|
27
27
|
creatorId: string | null;
|
28
28
|
}>;
|
29
|
+
static checkTerms(userAddress: string, chainId: number): Promise<boolean>;
|
29
30
|
static syncTags(): Promise<void>;
|
30
31
|
static syncOpportunityTags(): Promise<void>;
|
31
32
|
}
|
@@ -1,5 +1,6 @@
|
|
1
1
|
import { log } from "@/utils/logger";
|
2
2
|
import { engineDbClient } from "@db";
|
3
|
+
import { ChainInteractionService, DistributionCreatorInterface, registry } from "@sdk";
|
3
4
|
import { OpportunityService } from "../opportunity";
|
4
5
|
import { UserRepository } from "./user.repository";
|
5
6
|
// ─── Users Services ──────────────────────────────────────────────────────────
|
@@ -25,6 +26,37 @@ export class UserService {
|
|
25
26
|
}
|
26
27
|
return await UserRepository.updateTags(user, tags);
|
27
28
|
}
|
29
|
+
static async checkTerms(userAddress, chainId) {
|
30
|
+
const distributorAddress = registry(chainId)?.Merkl?.DistributionCreator;
|
31
|
+
if (!distributorAddress)
|
32
|
+
throw new Error(`Distributor address not found for chainId ${chainId}`);
|
33
|
+
const calls = [
|
34
|
+
{
|
35
|
+
callData: DistributionCreatorInterface.encodeFunctionData("userSignatureWhitelist", [userAddress]),
|
36
|
+
target: distributorAddress,
|
37
|
+
allowFailure: false,
|
38
|
+
},
|
39
|
+
{
|
40
|
+
callData: DistributionCreatorInterface.encodeFunctionData("userSignatures", [userAddress]),
|
41
|
+
target: distributorAddress,
|
42
|
+
allowFailure: false,
|
43
|
+
},
|
44
|
+
{
|
45
|
+
callData: DistributionCreatorInterface.encodeFunctionData("messageHash"),
|
46
|
+
target: distributorAddress,
|
47
|
+
allowFailure: false,
|
48
|
+
},
|
49
|
+
];
|
50
|
+
const decoders = (r) => [
|
51
|
+
DistributionCreatorInterface.decodeFunctionResult("userSignatureWhitelist", r[0].returnData)[0].toString(),
|
52
|
+
DistributionCreatorInterface.decodeFunctionResult("userSignatures", r[1].returnData)[0].toString(),
|
53
|
+
DistributionCreatorInterface.decodeFunctionResult("messageHash", r[2].returnData)[0].toString(),
|
54
|
+
];
|
55
|
+
const result = await ChainInteractionService(chainId).fetchAndDecodeMultiple(calls, decoders);
|
56
|
+
const [signatureWhitelist, userSignature, messageHash] = result;
|
57
|
+
const hasNotSigned = signatureWhitelist === "0" && userSignature !== messageHash;
|
58
|
+
return !hasNotSigned;
|
59
|
+
}
|
28
60
|
static async syncTags() {
|
29
61
|
// 1 - engine -> api db
|
30
62
|
const creatorTags = await engineDbClient.campaignCreators.findMany();
|