@merkl/api 0.21.36 → 0.21.38

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.
Files changed (35) hide show
  1. package/dist/src/eden/index.d.ts +1758 -1351
  2. package/dist/src/engine/deprecated/erc20SubTypeProcessors/helpers/factoryFinder.js +1 -0
  3. package/dist/src/engine/implementations/Erc20/subTypes/detect.js +108 -97
  4. package/dist/src/engine/implementations/Erc20/subTypes/factories.js +8 -0
  5. package/dist/src/engine/implementations/Erc20/subTypes/implementations/aave/metadata.d.ts +1 -1
  6. package/dist/src/engine/implementations/Erc20/subTypes/implementations/pino/metadata.d.ts +17 -0
  7. package/dist/src/engine/implementations/Erc20/subTypes/implementations/pino/metadata.js +38 -0
  8. package/dist/src/engine/implementations/Erc20/subTypes/implementations/pino/tvl.d.ts +6 -0
  9. package/dist/src/engine/implementations/Erc20/subTypes/implementations/pino/tvl.js +83 -0
  10. package/dist/src/engine/implementations/Erc20/subTypes/implementations/uniswapV2/metadata.d.ts +30 -0
  11. package/dist/src/engine/implementations/Erc20/subTypes/implementations/uniswapV2/metadata.js +65 -0
  12. package/dist/src/engine/implementations/Erc20/subTypes/implementations/uniswapV2/tvl.d.ts +6 -0
  13. package/dist/src/engine/implementations/Erc20/subTypes/implementations/uniswapV2/tvl.js +94 -0
  14. package/dist/src/engine/implementations/Erc20/subTypes/index.d.ts +2 -1
  15. package/dist/src/engine/implementations/Erc20/subTypes/index.js +1 -0
  16. package/dist/src/engine/implementations/JsonAirdrop/metadata.d.ts +2 -2
  17. package/dist/src/index.d.ts +545 -396
  18. package/dist/src/modules/v4/campaign/campaign.controller.d.ts +1 -1
  19. package/dist/src/modules/v4/campaign/campaign.service.d.ts +5 -1
  20. package/dist/src/modules/v4/campaign/campaign.service.js +41 -2
  21. package/dist/src/modules/v4/campaign/campaign.test.controller.d.ts +385 -240
  22. package/dist/src/modules/v4/campaign/campaign.test.controller.js +41 -15
  23. package/dist/src/modules/v4/creator/creator.controller.d.ts +157 -153
  24. package/dist/src/modules/v4/creator/creator.controller.js +11 -11
  25. package/dist/src/modules/v4/creator/creator.model.d.ts +2 -2
  26. package/dist/src/modules/v4/creator/creator.model.js +2 -2
  27. package/dist/src/modules/v4/opportunity/opportunity.controller.d.ts +2 -2
  28. package/dist/src/modules/v4/opportunity/opportunity.service.d.ts +3 -3
  29. package/dist/src/modules/v4/opportunity/opportunity.service.js +1 -1
  30. package/dist/src/modules/v4/protocol/protocol.model.d.ts +1 -1
  31. package/dist/src/modules/v4/protocol/protocol.model.js +1 -0
  32. package/dist/src/modules/v4/reward/reward.repository.js +1 -1
  33. package/dist/src/modules/v4/router.d.ts +545 -396
  34. package/dist/tsconfig.package.tsbuildinfo +1 -1
  35. package/package.json +1 -1
@@ -32,6 +32,7 @@ const factoryAddresses = {
32
32
  "0x29372c22459a4e373851798bFd6808e71EA34A71": Erc20SubType.punchswap, // Punchswap Flow EVM
33
33
  "0x724412C00059bf7d6ee7d4a1d0D5cd4de3ea1C48": Erc20SubType.hyperswap, // Hyperswap Factory HyperEVM
34
34
  "0x8909Dc15e40173Ff4699343b6eB8132c65e18eC6": Erc20SubType.uniswapv2, // Uniswap Factory Base
35
+ "0xBA51AA60B3b8d9A36cc748a62Aa56801060183f8": Erc20SubType.pinto, // Pinto Factory on Base
35
36
  };
36
37
  export function getTypeFromFactoryAddress(address) {
37
38
  if (factoryAddresses[address]) {
@@ -5,6 +5,7 @@ import { getTypeFromTreasuryAddress } from "@/engine/deprecated/erc20SubTypeProc
5
5
  import { processNamingConditionsInOrder } from "@/engine/deprecated/erc20SubTypeProcessors/subtypesRound1";
6
6
  import { Erc20SubType } from "@/engine/implementations/Erc20/subTypes";
7
7
  import { decodeReturnValue } from "@/utils/decodeCalls";
8
+ import { log } from "@/utils/logger";
8
9
  import { BalancerPoolInterface, BalancerV3StablePoolInterface, ChainInteractionService, ERC20Interface, EnzymeInterface, FactoryInterface, IonPoolInterface, LayerBankERC20Interface, MetamorphoInterface, } from "@sdk";
9
10
  /**
10
11
  * @notice Compute the subtypes of the campaigns
@@ -13,93 +14,114 @@ import { BalancerPoolInterface, BalancerV3StablePoolInterface, ChainInteractionS
13
14
  */
14
15
  export const detectSubType = async (chainId, campaigns) => {
15
16
  // 1. Do a generic multicall per campaign to see which functions are supported
16
- const callsPerCampaign = 8;
17
- const calls = [];
18
- for (const [index, campaign] of campaigns.entries()) {
17
+ const detectionCalls = await ChainInteractionService(chainId).fetchAndDecodeObject(campaigns.flatMap(campaign => {
19
18
  const { targetToken } = campaign.campaignParameters;
20
- calls.push({
21
- allowFailure: true,
22
- callData: FactoryInterface.encodeFunctionData("factory"),
23
- target: targetToken,
24
- }, {
25
- allowFailure: true,
26
- callData: MetamorphoInterface.encodeFunctionData("MORPHO"),
27
- target: targetToken,
28
- }, {
29
- allowFailure: true,
30
- callData: ERC20Interface.encodeFunctionData("name"),
31
- target: targetToken,
32
- }, {
33
- allowFailure: true,
34
- callData: BalancerPoolInterface.encodeFunctionData("getPoolId"),
35
- target: targetToken,
36
- }, {
37
- allowFailure: true,
38
- callData: EnzymeInterface.encodeFunctionData("getCreator"),
39
- target: targetToken,
40
- }, {
41
- allowFailure: true,
42
- callData: LayerBankERC20Interface.encodeFunctionData("owner"),
43
- target: targetToken,
44
- }, {
45
- allowFailure: true,
46
- callData: BalancerV3StablePoolInterface.encodeFunctionData("getVault"),
47
- target: targetToken,
48
- }, {
49
- allowFailure: true,
50
- callData: IonPoolInterface.encodeFunctionData("treasury"),
51
- target: targetToken,
52
- });
53
- if (calls.length !== callsPerCampaign * (index + 1))
54
- throw new Error("computeSubTypes: calls.length !== callsPerCampaign * index");
19
+ return [
20
+ {
21
+ callData: FactoryInterface.encodeFunctionData("factory"),
22
+ target: targetToken,
23
+ key: `${campaign.campaignId}_factory`,
24
+ decoder: (data) => FactoryInterface.decodeFunctionResult("factory", data)[0],
25
+ },
26
+ {
27
+ callData: MetamorphoInterface.encodeFunctionData("MORPHO"),
28
+ target: targetToken,
29
+ key: `${campaign.campaignId}_metamorpho`,
30
+ decoder: (data) => MetamorphoInterface.decodeFunctionResult("MORPHO", data)[0],
31
+ },
32
+ {
33
+ callData: ERC20Interface.encodeFunctionData("name"),
34
+ target: targetToken,
35
+ key: `${campaign.campaignId}_name`,
36
+ decoder: (data) => ERC20Interface.decodeFunctionResult("name", data)[0],
37
+ },
38
+ {
39
+ callData: BalancerPoolInterface.encodeFunctionData("getPoolId"),
40
+ target: targetToken,
41
+ key: `${campaign.campaignId}_getPoolId`,
42
+ decoder: (data) => BalancerPoolInterface.decodeFunctionResult("getPoolId", data)[0],
43
+ },
44
+ {
45
+ callData: EnzymeInterface.encodeFunctionData("getCreator"),
46
+ target: targetToken,
47
+ key: `${campaign.campaignId}_getCreator`,
48
+ decoder: (data) => EnzymeInterface.decodeFunctionResult("getCreator", data)[0],
49
+ },
50
+ {
51
+ callData: LayerBankERC20Interface.encodeFunctionData("owner"),
52
+ target: targetToken,
53
+ key: `${campaign.campaignId}_owner`,
54
+ decoder: (data) => LayerBankERC20Interface.decodeFunctionResult("owner", data)[0],
55
+ },
56
+ {
57
+ callData: BalancerV3StablePoolInterface.encodeFunctionData("getVault"),
58
+ target: targetToken,
59
+ key: `${campaign.campaignId}_getVault`,
60
+ decoder: (data) => BalancerV3StablePoolInterface.decodeFunctionResult("getVault", data)[0],
61
+ },
62
+ {
63
+ callData: IonPoolInterface.encodeFunctionData("treasury"),
64
+ target: targetToken,
65
+ key: `${campaign.campaignId}_treasury`,
66
+ decoder: (data) => IonPoolInterface.decodeFunctionResult("treasury", data)[0],
67
+ },
68
+ {
69
+ callData: "0x038f6f61", // Factory call for Pinto protocol
70
+ target: targetToken,
71
+ key: `${campaign.campaignId}_pinto`,
72
+ decoder: (data) => FactoryInterface.decodeFunctionResult("factory", data)[0],
73
+ },
74
+ ];
75
+ }));
76
+ for (const key of Object.keys(detectionCalls)) {
77
+ log.local(`detection call ${key}: ${detectionCalls[key]}`);
55
78
  }
56
- const callResult = await ChainInteractionService(chainId).fetchState(calls);
57
79
  // 2. Decode result from the multicalls and using try catch, try to interprete the result
58
80
  const res = [];
59
- let index = -callsPerCampaign;
60
81
  for (const campaign of campaigns) {
61
82
  const { targetToken } = campaign.campaignParameters;
62
- index += callsPerCampaign;
63
- const values = {
64
- factory: callResult[index].returnData,
65
- metamorpho: callResult[index + 1].returnData,
66
- name: callResult[index + 2].returnData,
67
- poolId: callResult[index + 3].returnData,
68
- creator: callResult[index + 4].returnData,
69
- owner: callResult[index + 5].returnData,
70
- vault: callResult[index + 6].returnData,
71
- treasury: callResult[index + 7].returnData,
72
- };
83
+ const factory = detectionCalls[`${campaign.campaignId}_factory`];
84
+ const metamorpho = detectionCalls[`${campaign.campaignId}_metamorpho`];
85
+ const name = detectionCalls[`${campaign.campaignId}_name`];
86
+ const poolId = detectionCalls[`${campaign.campaignId}_getPoolId`];
87
+ const vault = detectionCalls[`${campaign.campaignId}_getVault`];
88
+ const creator = detectionCalls[`${campaign.campaignId}_getCreator`];
89
+ const owner = detectionCalls[`${campaign.campaignId}_owner`];
90
+ const treasury = detectionCalls[`${campaign.campaignId}_treasury`];
91
+ const pintoFactory = detectionCalls[`${campaign.campaignId}_pinto`];
73
92
  // Get erc20SubType from factory address
74
- try {
75
- const factory = decodeReturnValue(values.factory, "factory");
76
- const type = getTypeFromFactoryAddress(factory);
77
- if (type !== Erc20SubType.unknown) {
78
- res.push(type);
79
- continue;
93
+ if (!!factory || !!creator || !!pintoFactory) {
94
+ try {
95
+ const type = getTypeFromFactoryAddress((factory ?? creator ?? pintoFactory));
96
+ if (type !== Erc20SubType.unknown) {
97
+ res.push(type);
98
+ continue;
99
+ }
80
100
  }
101
+ catch { }
81
102
  }
82
- catch { }
83
103
  // Get erc20SubType from treasury address
84
- try {
85
- const treasury = decodeReturnValue(values.treasury, "treasury");
86
- const type = getTypeFromTreasuryAddress(treasury);
87
- if (type !== Erc20SubType.unknown) {
88
- res.push(type);
89
- continue;
104
+ if (!!treasury) {
105
+ try {
106
+ const type = getTypeFromTreasuryAddress(treasury);
107
+ if (type !== Erc20SubType.unknown) {
108
+ res.push(type);
109
+ continue;
110
+ }
90
111
  }
112
+ catch { }
91
113
  }
92
- catch { }
93
114
  // Get erc20SubType from owner address
94
- try {
95
- const owner = decodeReturnValue(values.owner, "owner");
96
- const type = getTypeFromOwnerAddress(owner);
97
- if (type !== Erc20SubType.unknown) {
98
- res.push(type);
99
- continue;
115
+ if (!!owner) {
116
+ try {
117
+ const type = getTypeFromOwnerAddress(owner);
118
+ if (type !== Erc20SubType.unknown) {
119
+ res.push(type);
120
+ continue;
121
+ }
100
122
  }
123
+ catch { }
101
124
  }
102
- catch { }
103
125
  // Get erc20SubType from address
104
126
  try {
105
127
  const type = getTypeFromAddressChain(chainId, targetToken);
@@ -109,44 +131,33 @@ export const detectSubType = async (chainId, campaigns) => {
109
131
  }
110
132
  }
111
133
  catch { }
112
- // Get erc20SubType for enzyme (factory is replaced by dispatcher)
113
- try {
114
- const factory = decodeReturnValue(values.creator, "getCreator");
115
- const type = getTypeFromFactoryAddress(factory);
116
- if (type !== Erc20SubType.unknown) {
117
- res.push(type);
134
+ // Get erc20SubType for morpho
135
+ if (!!metamorpho) {
136
+ try {
137
+ decodeReturnValue(metamorpho, "MORPHO");
138
+ res.push(Erc20SubType.metamorpho);
118
139
  continue;
119
140
  }
141
+ catch { }
120
142
  }
121
- catch { }
122
- // Get erc20SubType for morpho
123
- try {
124
- decodeReturnValue(values.metamorpho, "MORPHO");
125
- res.push(Erc20SubType.metamorpho);
126
- continue;
127
- }
128
- catch { }
129
143
  // Starting from this point, assume the name is working
130
144
  try {
131
- const name = decodeReturnValue(values.name, "name");
132
145
  // Get erc20SubType for balancer
133
- try {
134
- decodeReturnValue(values.poolId, "getPoolId");
146
+ if (!!poolId) {
135
147
  res.push(Erc20SubType.balancerPool);
136
148
  continue;
137
149
  }
138
- catch { }
139
- try {
140
- decodeReturnValue(values.vault, "getVault");
150
+ if (!!vault) {
141
151
  res.push(Erc20SubType.balancerPool);
142
152
  continue;
143
153
  }
144
- catch { }
145
154
  // Get erc20SubType by parsing information from the erc20 name
146
- const typeInfoFromName = processNamingConditionsInOrder(name, targetToken, campaign);
147
- if (!!typeInfoFromName) {
148
- res.push(typeInfoFromName.type);
149
- continue;
155
+ if (!!name) {
156
+ const typeInfoFromName = processNamingConditionsInOrder(name, targetToken, campaign);
157
+ if (!!typeInfoFromName) {
158
+ res.push(typeInfoFromName.type);
159
+ continue;
160
+ }
150
161
  }
151
162
  }
152
163
  catch { }
@@ -7,8 +7,12 @@ import { GearboxMetadata } from "./implementations/gearbox/metadata";
7
7
  import { GearboxTVLBuilder } from "./implementations/gearbox/tvl";
8
8
  import { LendleMetadata } from "./implementations/lendleVaults/metadata";
9
9
  import { LendleTVLBuilder } from "./implementations/lendleVaults/tvl";
10
+ import { PinoMetadata } from "./implementations/pino/metadata";
11
+ import { PinoTVLBuilder } from "./implementations/pino/tvl";
10
12
  import { TermMaxMetadata } from "./implementations/termmax/metadata";
11
13
  import { TermMaxTVLBuilder } from "./implementations/termmax/tvl";
14
+ import { UniswapV2Metadata } from "./implementations/uniswapV2/metadata";
15
+ import { UniswapV2TVLBuilder } from "./implementations/uniswapV2/tvl";
12
16
  /**
13
17
  * @dev TYPE SAFETY DISABLED FOR NOW AS WE DON'T HAVE ALL THE CAMPAIGNS IMPLEMENTED
14
18
  *
@@ -25,6 +29,8 @@ const tvlMap = {
25
29
  [Erc20SubType.termmax]: new TermMaxTVLBuilder(),
26
30
  [Erc20SubType.dlend_lending]: new AaveTVLBuilder(),
27
31
  [Erc20SubType.dlend_borrowing]: new AaveTVLBuilder(),
32
+ [Erc20SubType.pinto]: new PinoTVLBuilder(),
33
+ [Erc20SubType.katana]: new UniswapV2TVLBuilder(),
28
34
  };
29
35
  export const erc20SubTypeTVLBuilderFactory = (erc20Subtype) => {
30
36
  if (!tvlMap[erc20Subtype]) {
@@ -48,6 +54,8 @@ const metadataMap = {
48
54
  [Erc20SubType.termmax]: new TermMaxMetadata(),
49
55
  [Erc20SubType.dlend_lending]: new AaveMetadata("dlend", "dTrinity dLend", (underlyingToken) => `https://app.dtrinity.org/dlend/reserve-overview/?underlyingAsset=${underlyingToken}`),
50
56
  [Erc20SubType.dlend_borrowing]: new AaveMetadata("dlend", "dTrinity dLend", (underlyingToken) => `https://app.dtrinity.org/dlend/reserve-overview/?underlyingAsset=${underlyingToken}`),
57
+ [Erc20SubType.pinto]: new PinoMetadata(),
58
+ [Erc20SubType.katana]: new UniswapV2Metadata("katana", "Katana"),
51
59
  };
52
60
  export const erc20SubTypeMetadataBuilderFactory = (erc20Subtype) => {
53
61
  if (!metadataMap[erc20Subtype]) {
@@ -18,7 +18,7 @@ export declare class AaveMetadata implements MetadataBuilder<Erc20LikeCampaignEn
18
18
  constructor(mainProtocol: ProtocolId, protocolName: string, depositUrl: (underlyingToken: string) => string);
19
19
  build(campaign: Omit<CampaignWithParams<Erc20LikeCampaignEnum>, "manualOverrides">, _opportunityIdentifier: string): Promise<{
20
20
  action: "LEND" | "BORROW";
21
- mainProtocol: "splice" | "reserve" | "morpho" | "quickswap" | "euler" | "uniswap" | "ambient" | "arthswap" | "base-swap" | "camelot" | "crust" | "fenix" | "horiza" | "izumi" | "kim" | "pancake-swap" | "ramses" | "retro" | "stryke" | "sushi-swap" | "swapr" | "thruster" | "voltage" | "zero" | "koi" | "supswap" | "zk-swap" | "thirdtrade" | "swap-x" | "velodrome" | "aerodrome" | "balancer" | "curve" | "cross_curve" | "curveNPool" | "aura" | "akron" | "beefy" | "dragonswap" | "poolside" | "syncswap" | "neptune" | "zkSwapThreePool" | "rfx" | "ra" | "maverick" | "trader-joe" | "hanji" | "radiant" | "aave" | "fraxlend" | "ironclad" | "gearbox" | "compound" | "sturdy" | "frax" | "ionic" | "moonwell" | "fluid" | "silo" | "dolomite" | "badger" | "ajna" | "layerbank" | "ion" | "venus" | "woofi" | "reactor_fusion" | "eigenlayer" | "vest" | "zerolend" | "lnd" | "dlend" | "hyperdrive" | "gamma" | "oku" | "hourglass" | "veda" | "kyo" | "sonex" | "lendle" | "tako-tako" | "equalizer" | "spectra" | "beraborrow" | "superlend" | "avalon" | "iguana" | "xlend" | "sake" | "sonicmarket" | "stability" | "angles" | "enzyme" | "toros" | "vicuna" | "bunni" | "beratrax" | "concrete" | "cian" | "pendle" | "yei" | "termmax" | "filament" | "gammaswap" | "maha" | "tempest" | "uranium" | "holdstation" | "katana" | "punchswap" | "satlayer" | "puffer";
21
+ mainProtocol: "splice" | "reserve" | "morpho" | "quickswap" | "euler" | "uniswap" | "ambient" | "arthswap" | "base-swap" | "camelot" | "crust" | "fenix" | "horiza" | "izumi" | "kim" | "pancake-swap" | "ramses" | "retro" | "stryke" | "sushi-swap" | "swapr" | "thruster" | "voltage" | "zero" | "koi" | "supswap" | "zk-swap" | "thirdtrade" | "swap-x" | "velodrome" | "aerodrome" | "balancer" | "curve" | "cross_curve" | "curveNPool" | "aura" | "akron" | "beefy" | "dragonswap" | "poolside" | "syncswap" | "neptune" | "zkSwapThreePool" | "rfx" | "ra" | "maverick" | "trader-joe" | "hanji" | "pinto" | "radiant" | "aave" | "fraxlend" | "ironclad" | "gearbox" | "compound" | "sturdy" | "frax" | "ionic" | "moonwell" | "fluid" | "silo" | "dolomite" | "badger" | "ajna" | "layerbank" | "ion" | "venus" | "woofi" | "reactor_fusion" | "eigenlayer" | "vest" | "zerolend" | "lnd" | "dlend" | "hyperdrive" | "gamma" | "oku" | "hourglass" | "veda" | "kyo" | "sonex" | "lendle" | "tako-tako" | "equalizer" | "spectra" | "beraborrow" | "superlend" | "avalon" | "iguana" | "xlend" | "sake" | "sonicmarket" | "stability" | "angles" | "enzyme" | "toros" | "vicuna" | "bunni" | "beratrax" | "concrete" | "cian" | "pendle" | "yei" | "termmax" | "filament" | "gammaswap" | "maha" | "tempest" | "uranium" | "holdstation" | "katana" | "punchswap" | "satlayer" | "puffer";
22
22
  name: string;
23
23
  tokens: {
24
24
  chainId: number;
@@ -0,0 +1,17 @@
1
+ import type { MetadataBuilder } from "@/engine/metadata/interface";
2
+ import type { CampaignWithParams } from "@/modules/v4/campaign/campaign.model";
3
+ import type { ProtocolId } from "@/modules/v4/protocol/protocol.model";
4
+ import type { Erc20LikeCampaignEnum } from "../..";
5
+ export declare class PinoMetadata implements MetadataBuilder<Erc20LikeCampaignEnum> {
6
+ build(campaign: Omit<CampaignWithParams<Erc20LikeCampaignEnum>, "manualOverrides">, _opportunityIdentifier: string): Promise<{
7
+ action: "POOL";
8
+ mainProtocol: ProtocolId;
9
+ name: string;
10
+ tokens: {
11
+ chainId: number;
12
+ address: string;
13
+ }[];
14
+ depositUrl: string;
15
+ explorerAddress: any;
16
+ }>;
17
+ }
@@ -0,0 +1,38 @@
1
+ import { TokenService } from "@/modules/v4/token/token.service";
2
+ import { OpportunityAction } from "@db/api";
3
+ import { ChainInteractionService } from "@sdk";
4
+ import { defaultAbiCoder } from "ethers/lib/utils.js";
5
+ export class PinoMetadata {
6
+ async build(campaign, _opportunityIdentifier) {
7
+ const { params, computeChainId, campaignId } = campaign;
8
+ const { targetToken } = params;
9
+ const firstRound = await ChainInteractionService(computeChainId).fetchAndDecodeObject([
10
+ {
11
+ callData: "0x9d63848a", // tokens()
12
+ target: targetToken,
13
+ key: `${campaignId}_tokens`,
14
+ decoder: (data) => defaultAbiCoder.decode(["address[]"], data)[0],
15
+ },
16
+ ]);
17
+ const [token0Address, token1Address] = firstRound[`${campaignId}_tokens`];
18
+ const token0 = await TokenService.findUniqueFillOrThrow({
19
+ chainId: computeChainId,
20
+ address: token0Address,
21
+ });
22
+ const token1 = await TokenService.findUniqueFillOrThrow({
23
+ chainId: computeChainId,
24
+ address: token1Address,
25
+ });
26
+ return {
27
+ action: OpportunityAction.POOL,
28
+ mainProtocol: "pinto",
29
+ name: `Provide Liquidity to Pinto ${token0.symbol}-${token1.symbol}`,
30
+ tokens: [
31
+ { chainId: computeChainId, address: token0Address },
32
+ { chainId: computeChainId, address: token1Address },
33
+ ],
34
+ depositUrl: `https://pinto.money/silo/${targetToken}`,
35
+ explorerAddress: params.targetToken,
36
+ };
37
+ }
38
+ }
@@ -0,0 +1,6 @@
1
+ import type { Erc20LikeCampaignEnum } from "@/engine/implementations/Erc20/subTypes";
2
+ import type { TVLBuilder, TVLData } from "@/engine/tvl/interface";
3
+ import { type CampaignParameters, type MerklChainId } from "@sdk";
4
+ export declare class PinoTVLBuilder implements TVLBuilder<Erc20LikeCampaignEnum> {
5
+ build(computeChainId: MerklChainId, campaigns: CampaignParameters<Erc20LikeCampaignEnum>[]): Promise<TVLData<any>>;
6
+ }
@@ -0,0 +1,83 @@
1
+ import { TokenService } from "@/modules/v4/token/token.service";
2
+ import { TvlType } from "@db/api";
3
+ import { ChainInteractionService, ERC20Interface, bigIntToNumber, } from "@sdk";
4
+ import { defaultAbiCoder } from "ethers/lib/utils.js";
5
+ export class PinoTVLBuilder {
6
+ async build(computeChainId, campaigns) {
7
+ const tvls = [];
8
+ const firstRound = await ChainInteractionService(computeChainId).fetchAndDecodeObject(campaigns.flatMap(campaign => {
9
+ const { campaignId, campaignParameters } = campaign;
10
+ const { targetToken } = campaignParameters;
11
+ return [
12
+ {
13
+ callData: "0x9d63848a", // tokens()
14
+ target: targetToken,
15
+ key: `${campaignId}_tokens`,
16
+ decoder: (data) => defaultAbiCoder.decode(["address[]"], data)[0],
17
+ },
18
+ ];
19
+ }));
20
+ const secondRound = await ChainInteractionService(computeChainId).fetchAndDecodeObject(campaigns.flatMap(campaign => {
21
+ const { campaignId, campaignParameters } = campaign;
22
+ const { targetToken } = campaignParameters;
23
+ const [token0Address, token1Address] = firstRound[`${campaigns[0].campaignId}_tokens`];
24
+ return [
25
+ {
26
+ callData: ERC20Interface.encodeFunctionData("balanceOf", [targetToken]),
27
+ target: token0Address,
28
+ key: `${campaignId}_token0`,
29
+ decoder: (data) => {
30
+ return ERC20Interface.decodeFunctionResult("balanceOf", data)[0];
31
+ },
32
+ },
33
+ {
34
+ callData: ERC20Interface.encodeFunctionData("balanceOf", [targetToken]),
35
+ target: token1Address,
36
+ key: `${campaignId}_token1`,
37
+ decoder: (data) => {
38
+ return ERC20Interface.decodeFunctionResult("balanceOf", data)[0];
39
+ },
40
+ },
41
+ ];
42
+ }));
43
+ for (const campaign of campaigns) {
44
+ const { campaignId } = campaign;
45
+ const [token0Address, token1Address] = firstRound[`${campaigns[0].campaignId}_tokens`];
46
+ const reserve0 = secondRound[`${campaignId}_token0`];
47
+ const reserve1 = secondRound[`${campaignId}_token1`];
48
+ // We don't fetch token data everytime, we use the database and the associated service
49
+ const token0 = await TokenService.findUniqueFillOrThrow({
50
+ chainId: computeChainId,
51
+ address: token0Address,
52
+ });
53
+ const token1 = await TokenService.findUniqueFillOrThrow({
54
+ chainId: computeChainId,
55
+ address: token1Address,
56
+ });
57
+ if (!token0.decimals || !token0.price) {
58
+ throw new Error(`Missing decimals or price for token ${token0.address}`);
59
+ }
60
+ if (!token1.decimals || !token1.price) {
61
+ throw new Error(`Missing decimals or price for token ${token1.address}`);
62
+ }
63
+ tvls.push({
64
+ campaign,
65
+ tvl: bigIntToNumber(reserve0, token0.decimals) * token0.price +
66
+ bigIntToNumber(reserve1, token1.decimals) * token1.price,
67
+ tvlBreakdown: [
68
+ {
69
+ identifier: token0.id,
70
+ type: TvlType.TOKEN,
71
+ value: bigIntToNumber(reserve0, token0.decimals),
72
+ },
73
+ {
74
+ identifier: token1.id,
75
+ type: TvlType.TOKEN,
76
+ value: bigIntToNumber(reserve1, token1.decimals),
77
+ },
78
+ ],
79
+ });
80
+ }
81
+ return tvls;
82
+ }
83
+ }
@@ -0,0 +1,30 @@
1
+ import type { MetadataBuilder } from "@/engine/metadata/interface";
2
+ import type { CampaignWithParams } from "@/modules/v4/campaign/campaign.model";
3
+ import type { ProtocolId } from "@/modules/v4/protocol/protocol.model";
4
+ import type { Erc20LikeCampaignEnum } from "../..";
5
+ export declare class UniswapV2Metadata implements MetadataBuilder<Erc20LikeCampaignEnum> {
6
+ /**
7
+ * @notice Protocol entity ID - must be defined in the corresponding file and created in DB
8
+ */
9
+ mainProtocol: ProtocolId;
10
+ /**
11
+ * @notice Protocol name - used to create the opportunity name
12
+ */
13
+ protocolName: string;
14
+ /**
15
+ * @notice Function to generate the deposit URL for the opportunity
16
+ */
17
+ depositUrl?: (underlyingToken: string) => string;
18
+ constructor(mainProtocol: ProtocolId, protocolName: string, depositUrl?: (underlyingToken: string) => string);
19
+ build(campaign: Omit<CampaignWithParams<Erc20LikeCampaignEnum>, "manualOverrides">, _opportunityIdentifier: string): Promise<{
20
+ action: "POOL";
21
+ mainProtocol: "splice" | "reserve" | "morpho" | "quickswap" | "euler" | "uniswap" | "ambient" | "arthswap" | "base-swap" | "camelot" | "crust" | "fenix" | "horiza" | "izumi" | "kim" | "pancake-swap" | "ramses" | "retro" | "stryke" | "sushi-swap" | "swapr" | "thruster" | "voltage" | "zero" | "koi" | "supswap" | "zk-swap" | "thirdtrade" | "swap-x" | "velodrome" | "aerodrome" | "balancer" | "curve" | "cross_curve" | "curveNPool" | "aura" | "akron" | "beefy" | "dragonswap" | "poolside" | "syncswap" | "neptune" | "zkSwapThreePool" | "rfx" | "ra" | "maverick" | "trader-joe" | "hanji" | "pinto" | "radiant" | "aave" | "fraxlend" | "ironclad" | "gearbox" | "compound" | "sturdy" | "frax" | "ionic" | "moonwell" | "fluid" | "silo" | "dolomite" | "badger" | "ajna" | "layerbank" | "ion" | "venus" | "woofi" | "reactor_fusion" | "eigenlayer" | "vest" | "zerolend" | "lnd" | "dlend" | "hyperdrive" | "gamma" | "oku" | "hourglass" | "veda" | "kyo" | "sonex" | "lendle" | "tako-tako" | "equalizer" | "spectra" | "beraborrow" | "superlend" | "avalon" | "iguana" | "xlend" | "sake" | "sonicmarket" | "stability" | "angles" | "enzyme" | "toros" | "vicuna" | "bunni" | "beratrax" | "concrete" | "cian" | "pendle" | "yei" | "termmax" | "filament" | "gammaswap" | "maha" | "tempest" | "uranium" | "holdstation" | "katana" | "punchswap" | "satlayer" | "puffer";
22
+ name: string;
23
+ tokens: {
24
+ chainId: number;
25
+ address: string;
26
+ }[];
27
+ depositUrl: string | undefined;
28
+ explorerAddress: any;
29
+ }>;
30
+ }
@@ -0,0 +1,65 @@
1
+ import { TokenService } from "@/modules/v4/token/token.service";
2
+ import { OpportunityAction } from "@db/api";
3
+ import { ChainInteractionService, UniswapV2PoolInterface } from "@sdk";
4
+ export class UniswapV2Metadata {
5
+ /**
6
+ * @notice Protocol entity ID - must be defined in the corresponding file and created in DB
7
+ */
8
+ mainProtocol;
9
+ /**
10
+ * @notice Protocol name - used to create the opportunity name
11
+ */
12
+ protocolName;
13
+ /**
14
+ * @notice Function to generate the deposit URL for the opportunity
15
+ */
16
+ depositUrl;
17
+ constructor(mainProtocol, protocolName, depositUrl) {
18
+ this.mainProtocol = mainProtocol;
19
+ this.protocolName = protocolName;
20
+ this.depositUrl = depositUrl ?? undefined;
21
+ }
22
+ async build(campaign, _opportunityIdentifier) {
23
+ const { params, computeChainId, campaignId } = campaign;
24
+ const { targetToken } = params;
25
+ const firstRound = await ChainInteractionService(computeChainId).fetchAndDecodeObject([
26
+ {
27
+ callData: UniswapV2PoolInterface.encodeFunctionData("token0"),
28
+ target: targetToken,
29
+ key: `${campaignId}_token0`,
30
+ decoder: (data) => {
31
+ return UniswapV2PoolInterface.decodeFunctionResult("token0", data)[0];
32
+ },
33
+ },
34
+ {
35
+ callData: UniswapV2PoolInterface.encodeFunctionData("token1"),
36
+ target: targetToken,
37
+ key: `${campaignId}_token1`,
38
+ decoder: (data) => {
39
+ return UniswapV2PoolInterface.decodeFunctionResult("token1", data)[0];
40
+ },
41
+ },
42
+ ]);
43
+ const token0Address = firstRound[`${campaignId}_token0`];
44
+ const token1Address = firstRound[`${campaignId}_token1`];
45
+ const token0 = await TokenService.findUniqueFillOrThrow({
46
+ chainId: computeChainId,
47
+ address: token0Address,
48
+ });
49
+ const token1 = await TokenService.findUniqueFillOrThrow({
50
+ chainId: computeChainId,
51
+ address: token1Address,
52
+ });
53
+ return {
54
+ action: OpportunityAction.POOL,
55
+ mainProtocol: this.mainProtocol,
56
+ name: `Provide Liquidity to ${this.protocolName} ${token0.symbol}-${token1.symbol}`,
57
+ tokens: [
58
+ { chainId: computeChainId, address: token0Address },
59
+ { chainId: computeChainId, address: token1Address },
60
+ ],
61
+ depositUrl: this.depositUrl ? this.depositUrl(targetToken) : undefined,
62
+ explorerAddress: params.targetToken,
63
+ };
64
+ }
65
+ }
@@ -0,0 +1,6 @@
1
+ import type { Erc20LikeCampaignEnum } from "@/engine/implementations/Erc20/subTypes";
2
+ import type { TVLBuilder, TVLData } from "@/engine/tvl/interface";
3
+ import { type CampaignParameters, type MerklChainId } from "@sdk";
4
+ export declare class UniswapV2TVLBuilder implements TVLBuilder<Erc20LikeCampaignEnum> {
5
+ build(computeChainId: MerklChainId, campaigns: CampaignParameters<Erc20LikeCampaignEnum>[]): Promise<TVLData<any>>;
6
+ }