@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.
- package/dist/src/eden/index.d.ts +1758 -1351
- package/dist/src/engine/deprecated/erc20SubTypeProcessors/helpers/factoryFinder.js +1 -0
- package/dist/src/engine/implementations/Erc20/subTypes/detect.js +108 -97
- package/dist/src/engine/implementations/Erc20/subTypes/factories.js +8 -0
- package/dist/src/engine/implementations/Erc20/subTypes/implementations/aave/metadata.d.ts +1 -1
- package/dist/src/engine/implementations/Erc20/subTypes/implementations/pino/metadata.d.ts +17 -0
- package/dist/src/engine/implementations/Erc20/subTypes/implementations/pino/metadata.js +38 -0
- package/dist/src/engine/implementations/Erc20/subTypes/implementations/pino/tvl.d.ts +6 -0
- package/dist/src/engine/implementations/Erc20/subTypes/implementations/pino/tvl.js +83 -0
- package/dist/src/engine/implementations/Erc20/subTypes/implementations/uniswapV2/metadata.d.ts +30 -0
- package/dist/src/engine/implementations/Erc20/subTypes/implementations/uniswapV2/metadata.js +65 -0
- package/dist/src/engine/implementations/Erc20/subTypes/implementations/uniswapV2/tvl.d.ts +6 -0
- package/dist/src/engine/implementations/Erc20/subTypes/implementations/uniswapV2/tvl.js +94 -0
- package/dist/src/engine/implementations/Erc20/subTypes/index.d.ts +2 -1
- package/dist/src/engine/implementations/Erc20/subTypes/index.js +1 -0
- package/dist/src/engine/implementations/JsonAirdrop/metadata.d.ts +2 -2
- package/dist/src/index.d.ts +545 -396
- package/dist/src/modules/v4/campaign/campaign.controller.d.ts +1 -1
- package/dist/src/modules/v4/campaign/campaign.service.d.ts +5 -1
- package/dist/src/modules/v4/campaign/campaign.service.js +41 -2
- package/dist/src/modules/v4/campaign/campaign.test.controller.d.ts +385 -240
- package/dist/src/modules/v4/campaign/campaign.test.controller.js +41 -15
- package/dist/src/modules/v4/creator/creator.controller.d.ts +157 -153
- package/dist/src/modules/v4/creator/creator.controller.js +11 -11
- package/dist/src/modules/v4/creator/creator.model.d.ts +2 -2
- package/dist/src/modules/v4/creator/creator.model.js +2 -2
- package/dist/src/modules/v4/opportunity/opportunity.controller.d.ts +2 -2
- package/dist/src/modules/v4/opportunity/opportunity.service.d.ts +3 -3
- package/dist/src/modules/v4/opportunity/opportunity.service.js +1 -1
- package/dist/src/modules/v4/protocol/protocol.model.d.ts +1 -1
- package/dist/src/modules/v4/protocol/protocol.model.js +1 -0
- package/dist/src/modules/v4/reward/reward.repository.js +1 -1
- package/dist/src/modules/v4/router.d.ts +545 -396
- package/dist/tsconfig.package.tsbuildinfo +1 -1
- 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
|
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
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
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
|
-
|
63
|
-
const
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
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
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
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
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
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
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
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
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
|
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
|
-
|
134
|
-
decodeReturnValue(values.poolId, "getPoolId");
|
146
|
+
if (!!poolId) {
|
135
147
|
res.push(Erc20SubType.balancerPool);
|
136
148
|
continue;
|
137
149
|
}
|
138
|
-
|
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
|
-
|
147
|
-
|
148
|
-
|
149
|
-
|
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
|
+
}
|
package/dist/src/engine/implementations/Erc20/subTypes/implementations/uniswapV2/metadata.d.ts
ADDED
@@ -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
|
+
}
|