@merkl/api 0.20.85 → 0.20.86

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.
@@ -6,6 +6,8 @@ import { ClammDynamicData } from "./implementations/Clamm";
6
6
  import { CompoundDynamicData } from "./implementations/Compound";
7
7
  import { CompoundV3DynamicData } from "./implementations/CompoundV3";
8
8
  import { DolomiteDynamicData } from "./implementations/Dolomite";
9
+ import { ERC721DynamicData } from "./implementations/ERC721";
10
+ import { ERCMultiTokenDynamicData } from "./implementations/ERCMultiToken";
9
11
  import { EigenLayerDynamicData } from "./implementations/EigenLayer";
10
12
  import { EncompassingDynamicData } from "./implementations/Encompassing";
11
13
  import { Erc20DynamicData } from "./implementations/Erc20";
@@ -54,11 +56,11 @@ const map = {
54
56
  [Campaign.MORPHOSUPPLY]: new DefaultDynamicData(), // TODO
55
57
  [Campaign.SYNCSWAP_VAULT]: new DefaultDynamicData(), // TODO
56
58
  [Campaign.MAVERICK_BP]: new DefaultDynamicData(), // TODO
57
- [Campaign.ERC6909]: new DefaultDynamicData(), // TODO
58
- [Campaign.ERC6909FIXAPR]: new DefaultDynamicData(), // TODO
59
- [Campaign.ERC1155]: new DefaultDynamicData(), // TODO
60
- [Campaign.ERC1155FIXAPR]: new DefaultDynamicData(), // TODO
61
- [Campaign.ERC721]: new DefaultDynamicData(), // TODO
62
- [Campaign.ERC721FIXAPR]: new DefaultDynamicData(), // TODO
59
+ [Campaign.ERC6909]: new ERCMultiTokenDynamicData(),
60
+ [Campaign.ERC6909FIXAPR]: new ERCMultiTokenDynamicData(),
61
+ [Campaign.ERC1155]: new ERCMultiTokenDynamicData(),
62
+ [Campaign.ERC1155FIXAPR]: new ERCMultiTokenDynamicData(),
63
+ [Campaign.ERC721]: new ERC721DynamicData(),
64
+ [Campaign.ERC721FIXAPR]: new ERC721DynamicData(),
63
65
  };
64
66
  export const dynamicDataBuilderFactory = (campaignType) => map[campaignType];
@@ -0,0 +1,7 @@
1
+ import { type Campaign, type CampaignParameters, type MerklChainId } from "@sdk";
2
+ import type { DynamicDataBuilder } from "../interface";
3
+ type campaignType = Campaign.ERC721 | Campaign.ERC721FIXAPR;
4
+ export declare class ERC721DynamicData implements DynamicDataBuilder<campaignType> {
5
+ build(chainId: MerklChainId, campaigns: CampaignParameters<campaignType>[]): Promise<ERC721CampaignDynamicData[]>;
6
+ }
7
+ export {};
@@ -0,0 +1,85 @@
1
+ import { TokenService } from "@/modules/v4/token/token.service";
2
+ import { AragornEscrowInterface, BN2Number, ChainInteractionService, ERC20Interface, YEAR, } from "@sdk";
3
+ import { ERC721SubCampaignType } from "libs/sdk/src/types/merkl/campaignTypes/erc721";
4
+ import { log } from "../../../utils/logger";
5
+ import { Pricer } from "../../../utils/pricer";
6
+ import { getFixedApr, hasFixedAprConfig } from "../utils/getFixedApr";
7
+ export class ERC721DynamicData {
8
+ async build(chainId, campaigns) {
9
+ const pricer = await Pricer.load();
10
+ const calls = [];
11
+ for (const campaign of campaigns) {
12
+ if (campaign.campaignSubType === ERC721SubCampaignType.VOTING_POWER) {
13
+ calls.push({
14
+ allowFailure: true,
15
+ callData: AragornEscrowInterface.encodeFunctionData("totalLocked"),
16
+ target: campaign.campaignParameters.extraContracts[0],
17
+ });
18
+ }
19
+ else {
20
+ calls.push({
21
+ allowFailure: true,
22
+ callData: ERC20Interface.encodeFunctionData("totalSupply"), // TODO do not fit global interface
23
+ target: campaign.campaignParameters.targetToken,
24
+ });
25
+ }
26
+ }
27
+ const result = await ChainInteractionService(chainId).fetchState(calls);
28
+ let i = 0;
29
+ const dynamicData = [];
30
+ for (const campaign of campaigns) {
31
+ let totalSupply;
32
+ let symbolToken = campaign.campaignParameters.symbolTargetToken;
33
+ let token = campaign.campaignParameters.targetToken;
34
+ if (campaign.campaignSubType === ERC721SubCampaignType.VOTING_POWER) {
35
+ symbolToken = campaign.campaignParameters.symbolUnderlyingToken;
36
+ token = campaign.campaignParameters.extraContracts[1];
37
+ try {
38
+ totalSupply = BN2Number(AragornEscrowInterface.decodeFunctionResult("totalLocked", result[i].returnData)[0], campaign.campaignParameters.decimalsTargetToken);
39
+ }
40
+ catch {
41
+ log.warn(`Error getting totalSupply for campaign ${campaign.campaignId} and token ${campaign.campaignParameters.targetToken}`);
42
+ totalSupply = 0.0000001;
43
+ }
44
+ }
45
+ else {
46
+ try {
47
+ totalSupply = BN2Number(ERC20Interface.decodeFunctionResult("totalSupply", result[i].returnData)[0], campaign.campaignParameters.decimalsTargetToken);
48
+ }
49
+ catch {
50
+ log.warn(`Error getting totalSupply for campaign ${campaign.campaignId} and token ${campaign.campaignParameters.targetToken}`);
51
+ totalSupply = 0.0000001;
52
+ }
53
+ }
54
+ i++;
55
+ const priceRewardToken = await TokenService.getRewardTokenPrice(campaign);
56
+ const priceTargetToken = (await pricer.get({
57
+ address: token,
58
+ chainId: campaign.computeChainId,
59
+ // Remove the `c` at the beginning of the symbol and the `v3` at the end
60
+ symbol: symbolToken,
61
+ })) ?? 0;
62
+ let apr = (priceRewardToken * BN2Number(campaign.amount, campaign.campaignParameters.decimalsRewardToken) * YEAR * 100) /
63
+ campaign.campaignParameters.duration /
64
+ (totalSupply * priceTargetToken);
65
+ const rewardTokens = await TokenService.findManyOrCreate([
66
+ { chainId: campaign.chainId, address: campaign.rewardToken },
67
+ ]);
68
+ const rewardToken = rewardTokens[0];
69
+ if (rewardToken.isPoint) {
70
+ apr = apr / 365 / 100;
71
+ }
72
+ else if (hasFixedAprConfig(campaign.campaignParameters)) {
73
+ apr = getFixedApr(campaign, priceRewardToken, priceTargetToken);
74
+ }
75
+ dynamicData.push({
76
+ ...campaign,
77
+ apr,
78
+ totalSupplyTargetToken: totalSupply,
79
+ tvl: totalSupply * priceTargetToken,
80
+ priceRewardToken: priceRewardToken,
81
+ });
82
+ }
83
+ return dynamicData;
84
+ }
85
+ }
@@ -0,0 +1,7 @@
1
+ import { type Campaign, type CampaignParameters, type MerklChainId } from "@sdk";
2
+ import type { DynamicDataBuilder } from "../interface";
3
+ type campaignType = Campaign.ERC6909 | Campaign.ERC6909FIXAPR | Campaign.ERC1155 | Campaign.ERC1155FIXAPR;
4
+ export declare class ERCMultiTokenDynamicData implements DynamicDataBuilder<campaignType> {
5
+ build(chainId: MerklChainId, campaigns: CampaignParameters<campaignType>[]): Promise<ERC6909CampaignDynamicData[]>;
6
+ }
7
+ export {};
@@ -0,0 +1,159 @@
1
+ import { TokenService } from "@/modules/v4/token/token.service";
2
+ import { BN2Number, ChainInteractionService, CloberBookManagerInterface, CloberPoolInterface, ERC20Interface, ERC6909Interface, YEAR, } from "@sdk";
3
+ import { log } from "../../../utils/logger";
4
+ import { Pricer } from "../../../utils/pricer";
5
+ import { getFixedApr, hasFixedAprConfig } from "../utils/getFixedApr";
6
+ export class ERCMultiTokenDynamicData {
7
+ async build(chainId, campaigns) {
8
+ const pricer = await Pricer.load();
9
+ const calls = [];
10
+ for (const campaign of campaigns) {
11
+ calls.push({
12
+ allowFailure: true,
13
+ callData: ERC6909Interface.encodeFunctionData("totalSupply", [campaign.campaignParameters.tokenId]),
14
+ target: campaign.campaignParameters.targetToken,
15
+ });
16
+ calls.push({
17
+ allowFailure: true,
18
+ callData: CloberPoolInterface.encodeFunctionData("bookManager"),
19
+ target: campaign.campaignParameters.targetToken,
20
+ });
21
+ calls.push({
22
+ allowFailure: true,
23
+ callData: CloberPoolInterface.encodeFunctionData("getBookPairs", [campaign.campaignParameters.tokenId]),
24
+ target: campaign.campaignParameters.targetToken,
25
+ });
26
+ calls.push({
27
+ allowFailure: true,
28
+ callData: CloberPoolInterface.encodeFunctionData("getLiquidity", [campaign.campaignParameters.tokenId]),
29
+ target: campaign.campaignParameters.targetToken,
30
+ });
31
+ }
32
+ const result = await ChainInteractionService(chainId).fetchState(calls);
33
+ let i = 0;
34
+ const dynamicData = [];
35
+ for (const campaign of campaigns) {
36
+ let totalSupply;
37
+ let tvl;
38
+ let priceTargetToken;
39
+ try {
40
+ totalSupply = BN2Number(ERC6909Interface.decodeFunctionResult("totalSupply", result[i].returnData)[0], campaign.campaignParameters.decimalsTargetToken);
41
+ }
42
+ catch {
43
+ log.warn(`Error getting totalSupply for campaign ${campaign.campaignId} and token ${campaign.campaignParameters.targetToken}`);
44
+ totalSupply = 0.0000001;
45
+ }
46
+ i++;
47
+ // Specific to Clober so far
48
+ try {
49
+ const bookManager = CloberPoolInterface.decodeFunctionResult("bookManager", result[i + 1].returnData)[0];
50
+ const bookPairs = CloberPoolInterface.decodeFunctionResult("getBookPairs", result[i + 2].returnData);
51
+ const liquidity = CloberPoolInterface.decodeFunctionResult("getLiquidity", result[i + 3].returnData);
52
+ const liquidityToken0 = BigInt(liquidity[0].reserve) + BigInt(liquidity[0].cancelable) + BigInt(liquidity[0].claimable);
53
+ const liquidityToken1 = BigInt(liquidity[1].reserve) + BigInt(liquidity[1].cancelable) + BigInt(liquidity[1].claimable);
54
+ const bookPair0 = bookPairs[0] < bookPairs[1] ? bookPairs[0] : bookPairs[1];
55
+ const bookPair1 = bookPairs[0] < bookPairs[1] ? bookPairs[1] : bookPairs[0];
56
+ let token0;
57
+ let token1;
58
+ let symbol0;
59
+ let symbol1;
60
+ let decimals0;
61
+ let decimals1;
62
+ {
63
+ const bookManagerCalls = [
64
+ {
65
+ allowFailure: true,
66
+ callData: CloberBookManagerInterface.encodeFunctionData("getBookKey", [bookPair0]),
67
+ target: bookManager,
68
+ },
69
+ {
70
+ allowFailure: true,
71
+ callData: CloberBookManagerInterface.encodeFunctionData("getBookKey", [bookPair1]),
72
+ target: bookManager,
73
+ },
74
+ ];
75
+ const resultBookManager = await ChainInteractionService(chainId).fetchState(bookManagerCalls);
76
+ let j = 0;
77
+ const bookKey0 = CloberBookManagerInterface.decodeFunctionResult("getBookKey", resultBookManager[j++].returnData)[0];
78
+ const bookKey1 = CloberBookManagerInterface.decodeFunctionResult("getBookKey", resultBookManager[j++].returnData)[0];
79
+ token0 = bookKey0[0];
80
+ token1 = bookKey1[0];
81
+ }
82
+ {
83
+ const tokenCalls = [
84
+ {
85
+ allowFailure: true,
86
+ callData: ERC20Interface.encodeFunctionData("symbol"),
87
+ target: token0,
88
+ },
89
+ {
90
+ allowFailure: true,
91
+ callData: ERC20Interface.encodeFunctionData("symbol"),
92
+ target: token1,
93
+ },
94
+ {
95
+ allowFailure: true,
96
+ callData: ERC20Interface.encodeFunctionData("decimals"),
97
+ target: token0,
98
+ },
99
+ {
100
+ allowFailure: true,
101
+ callData: ERC20Interface.encodeFunctionData("decimals"),
102
+ target: token1,
103
+ },
104
+ ];
105
+ const resultTokens = await ChainInteractionService(chainId).fetchState(tokenCalls);
106
+ let j = 0;
107
+ symbol0 = ERC20Interface.decodeFunctionResult("symbol", resultTokens[j++].returnData)[0];
108
+ symbol1 = ERC20Interface.decodeFunctionResult("symbol", resultTokens[j++].returnData)[0];
109
+ decimals0 = ERC20Interface.decodeFunctionResult("decimals", resultTokens[j++].returnData)[0];
110
+ decimals1 = ERC20Interface.decodeFunctionResult("decimals", resultTokens[j++].returnData)[0];
111
+ }
112
+ const priceToken0 = (await pricer.get({
113
+ address: token0,
114
+ chainId: campaign.computeChainId,
115
+ symbol: symbol0,
116
+ })) ?? 0;
117
+ const priceToken1 = (await pricer.get({
118
+ address: token1,
119
+ chainId: campaign.computeChainId,
120
+ symbol: symbol1,
121
+ })) ?? 0;
122
+ tvl = priceToken0 * BN2Number(liquidityToken0, decimals0) + priceToken1 * BN2Number(liquidityToken1, decimals1);
123
+ priceTargetToken = tvl / totalSupply;
124
+ }
125
+ catch {
126
+ priceTargetToken =
127
+ (await pricer.get({
128
+ address: campaign.campaignParameters.targetToken,
129
+ chainId: campaign.computeChainId,
130
+ symbol: campaign.campaignParameters.symbolTargetToken,
131
+ })) ?? 0;
132
+ tvl = totalSupply * priceTargetToken;
133
+ }
134
+ i += 4;
135
+ const priceRewardToken = await TokenService.getRewardTokenPrice(campaign);
136
+ const rewardTokens = await TokenService.findManyOrCreate([
137
+ { chainId: campaign.chainId, address: campaign.rewardToken },
138
+ ]);
139
+ const rewardToken = rewardTokens[0];
140
+ let apr = (priceRewardToken * BN2Number(campaign.amount, campaign.campaignParameters.decimalsRewardToken) * YEAR * 100) /
141
+ campaign.campaignParameters.duration /
142
+ tvl;
143
+ if (rewardToken.isPoint) {
144
+ apr = apr / 365 / 100;
145
+ }
146
+ else if (hasFixedAprConfig(campaign.campaignParameters)) {
147
+ apr = getFixedApr(campaign, priceRewardToken, priceTargetToken);
148
+ }
149
+ dynamicData.push({
150
+ ...campaign,
151
+ apr,
152
+ totalSupplyTargetToken: totalSupply,
153
+ tvl,
154
+ priceRewardToken: priceRewardToken,
155
+ });
156
+ }
157
+ return dynamicData;
158
+ }
159
+ }
@@ -4,6 +4,6 @@ export type BaseFixAPRConfig = {
4
4
  targetTokenPricing: boolean;
5
5
  rewardTokenPricing: boolean;
6
6
  };
7
- export type FixedAprCampaignType = Campaign.ERC20_FIX_APR | Campaign.HYPERDRIVELOGFIXPROCESSOR;
7
+ export type FixedAprCampaignType = Campaign.ERC20_FIX_APR | Campaign.HYPERDRIVELOGFIXPROCESSOR | Campaign.ERC6909FIXAPR | Campaign.ERC1155FIXAPR | Campaign.ERC721FIXAPR;
8
8
  export declare function hasFixedAprConfig<T>(params: T): params is T & BaseFixAPRConfig;
9
9
  export declare function getFixedApr(campaignParameters: CampaignParameters<FixedAprCampaignType>, priceRewardToken: number, priceTargetToken: number): number;
@@ -7,6 +7,8 @@ import { CompoundMetadata } from "./implementations/Compound";
7
7
  import { CompoundV3Metadata } from "./implementations/CompoundV3";
8
8
  import { DefaultMetadata } from "./implementations/Default";
9
9
  import { DolomiteMetadata } from "./implementations/Dolomite";
10
+ import { ERC721Metadata } from "./implementations/ERC721";
11
+ import { ERCMultiTokenMetadata } from "./implementations/ERCMultiToken";
10
12
  import { EigenLayerMetadata } from "./implementations/EigenLayer";
11
13
  import { EncompassingMetadata } from "./implementations/Encompassing";
12
14
  import { Erc20Metadata } from "./implementations/Erc20";
@@ -57,11 +59,11 @@ const map = {
57
59
  [Campaign.EVENT_BASED]: new EventBasedMetadata(),
58
60
  [Campaign.ERC20REBASEFIXAPR]: new Erc20Metadata(),
59
61
  [Campaign.MAVERICK_BP]: new DefaultMetadata(), // TODO
60
- [Campaign.ERC6909]: new DefaultMetadata(), // TODO
61
- [Campaign.ERC6909FIXAPR]: new DefaultMetadata(), // TODO
62
- [Campaign.ERC1155]: new DefaultMetadata(), // TODO
63
- [Campaign.ERC1155FIXAPR]: new DefaultMetadata(), // TODO
64
- [Campaign.ERC721]: new DefaultMetadata(), // TODO
65
- [Campaign.ERC721FIXAPR]: new DefaultMetadata(), // TODO
62
+ [Campaign.ERC6909]: new ERCMultiTokenMetadata(),
63
+ [Campaign.ERC6909FIXAPR]: new ERCMultiTokenMetadata(),
64
+ [Campaign.ERC1155]: new ERCMultiTokenMetadata(),
65
+ [Campaign.ERC1155FIXAPR]: new ERCMultiTokenMetadata(),
66
+ [Campaign.ERC721]: new ERC721Metadata(),
67
+ [Campaign.ERC721FIXAPR]: new ERC721Metadata(),
66
68
  };
67
69
  export const metadataBuilderFactory = (campaignType) => map[campaignType];
@@ -0,0 +1,16 @@
1
+ import type { Campaign as CampaignEnum, CampaignParameters, ChainId } from "@sdk";
2
+ import type { MetadataBuilder } from "../interface";
3
+ type campaignType = CampaignEnum.ERC721 | CampaignEnum.ERC721FIXAPR;
4
+ export declare class ERC721Metadata implements MetadataBuilder<campaignType> {
5
+ build(computeChainId: ChainId, params: CampaignParameters<campaignType>["campaignParameters"]): Promise<{
6
+ action: "HOLD";
7
+ name: string;
8
+ tokens: {
9
+ chainId: ChainId;
10
+ address: any;
11
+ }[];
12
+ mainProtocol: undefined;
13
+ depositUrl: undefined;
14
+ }>;
15
+ }
16
+ export {};
@@ -0,0 +1,12 @@
1
+ import { OpportunityAction } from "@db/api";
2
+ export class ERC721Metadata {
3
+ async build(computeChainId, params) {
4
+ return {
5
+ action: OpportunityAction.HOLD,
6
+ name: `Hold ${params.symbolTargetToken}`,
7
+ tokens: [{ chainId: computeChainId, address: params.targetToken }],
8
+ mainProtocol: undefined,
9
+ depositUrl: undefined,
10
+ };
11
+ }
12
+ }
@@ -0,0 +1,16 @@
1
+ import type { Campaign as CampaignEnum, CampaignParameters, ChainId } from "@sdk";
2
+ import type { MetadataBuilder } from "../interface";
3
+ type campaignType = CampaignEnum.ERC1155 | CampaignEnum.ERC1155FIXAPR | CampaignEnum.ERC6909 | CampaignEnum.ERC6909FIXAPR;
4
+ export declare class ERCMultiTokenMetadata implements MetadataBuilder<campaignType> {
5
+ build(computeChainId: ChainId, params: CampaignParameters<campaignType>["campaignParameters"]): Promise<{
6
+ action: "HOLD";
7
+ name: string;
8
+ tokens: {
9
+ chainId: ChainId;
10
+ address: any;
11
+ }[];
12
+ mainProtocol: undefined;
13
+ depositUrl: undefined;
14
+ }>;
15
+ }
16
+ export {};
@@ -0,0 +1,12 @@
1
+ import { OpportunityAction } from "@db/api";
2
+ export class ERCMultiTokenMetadata {
3
+ async build(computeChainId, params) {
4
+ return {
5
+ action: OpportunityAction.HOLD,
6
+ name: `Hold ${params.symbolTargetToken} with token ID ${params.tokenId}`,
7
+ tokens: [{ chainId: computeChainId, address: params.targetToken }],
8
+ mainProtocol: undefined,
9
+ depositUrl: undefined,
10
+ };
11
+ }
12
+ }