@merkl/api 0.21.37 → 0.21.39
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 +562 -554
- package/dist/src/engine/deprecated/erc20SubTypeProcessors/helpers/factoryFinder.js +1 -0
- package/dist/src/engine/implementations/Erc20/subTypes/detect.js +4 -0
- package/dist/src/engine/implementations/Erc20/subTypes/factories.js +8 -0
- 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/index.d.ts +151 -147
- package/dist/src/modules/v4/campaign/campaign.test.controller.d.ts +2 -2
- package/dist/src/modules/v4/campaign/campaign.test.controller.js +2 -2
- package/dist/src/modules/v4/creator/creator.controller.d.ts +149 -145
- package/dist/src/modules/v4/creator/creator.controller.js +2 -2
- package/dist/src/modules/v4/dynamicData/dynamicData.service.js +1 -1
- package/dist/src/modules/v4/opportunity/opportunity.service.js +1 -1
- package/dist/src/modules/v4/router.d.ts +151 -147
- 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
|
@@ -72,6 +73,9 @@ export const detectSubType = async (chainId, campaigns) => {
|
|
72
73
|
},
|
73
74
|
];
|
74
75
|
}));
|
76
|
+
for (const key of Object.keys(detectionCalls)) {
|
77
|
+
log.local(`detection call ${key}: ${detectionCalls[key]}`);
|
78
|
+
}
|
75
79
|
// 2. Decode result from the multicalls and using try catch, try to interprete the result
|
76
80
|
const res = [];
|
77
81
|
for (const campaign of campaigns) {
|
@@ -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]) {
|
@@ -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
|
+
}
|
@@ -0,0 +1,94 @@
|
|
1
|
+
import { TokenService } from "@/modules/v4/token/token.service";
|
2
|
+
import { TvlType } from "@db/api";
|
3
|
+
import { ChainInteractionService, ERC20Interface, UniswapV2PoolInterface, bigIntToNumber, } from "@sdk";
|
4
|
+
export class UniswapV2TVLBuilder {
|
5
|
+
async build(computeChainId, campaigns) {
|
6
|
+
const tvls = [];
|
7
|
+
const firstRound = await ChainInteractionService(computeChainId).fetchAndDecodeObject(campaigns.flatMap(campaign => {
|
8
|
+
const { campaignId, campaignParameters } = campaign;
|
9
|
+
const { targetToken } = campaignParameters;
|
10
|
+
return [
|
11
|
+
{
|
12
|
+
callData: UniswapV2PoolInterface.encodeFunctionData("token0"),
|
13
|
+
target: targetToken,
|
14
|
+
key: `${campaignId}_token0`,
|
15
|
+
decoder: (data) => {
|
16
|
+
return UniswapV2PoolInterface.decodeFunctionResult("token0", data)[0];
|
17
|
+
},
|
18
|
+
},
|
19
|
+
{
|
20
|
+
callData: UniswapV2PoolInterface.encodeFunctionData("token1"),
|
21
|
+
target: targetToken,
|
22
|
+
key: `${campaignId}_token1`,
|
23
|
+
decoder: (data) => {
|
24
|
+
return UniswapV2PoolInterface.decodeFunctionResult("token1", data)[0];
|
25
|
+
},
|
26
|
+
},
|
27
|
+
];
|
28
|
+
}));
|
29
|
+
const secondRound = await ChainInteractionService(computeChainId).fetchAndDecodeObject(campaigns.flatMap(campaign => {
|
30
|
+
const { campaignId, campaignParameters } = campaign;
|
31
|
+
const { targetToken } = campaignParameters;
|
32
|
+
const token0Address = firstRound[`${campaignId}_token0`];
|
33
|
+
const token1Address = firstRound[`${campaignId}_token1`];
|
34
|
+
return [
|
35
|
+
{
|
36
|
+
callData: ERC20Interface.encodeFunctionData("balanceOf", [targetToken]),
|
37
|
+
target: token0Address,
|
38
|
+
key: `${campaignId}_token0`,
|
39
|
+
decoder: (data) => {
|
40
|
+
return ERC20Interface.decodeFunctionResult("balanceOf", data)[0];
|
41
|
+
},
|
42
|
+
},
|
43
|
+
{
|
44
|
+
callData: ERC20Interface.encodeFunctionData("balanceOf", [targetToken]),
|
45
|
+
target: token1Address,
|
46
|
+
key: `${campaignId}_token1`,
|
47
|
+
decoder: (data) => {
|
48
|
+
return ERC20Interface.decodeFunctionResult("balanceOf", data)[0];
|
49
|
+
},
|
50
|
+
},
|
51
|
+
];
|
52
|
+
}));
|
53
|
+
for (const campaign of campaigns) {
|
54
|
+
const { campaignId } = campaign;
|
55
|
+
const token0Address = firstRound[`${campaignId}_token0`];
|
56
|
+
const token1Address = firstRound[`${campaignId}_token1`];
|
57
|
+
const reserve0 = secondRound[`${campaignId}_token0`];
|
58
|
+
const reserve1 = secondRound[`${campaignId}_token1`];
|
59
|
+
// We don't fetch token data everytime, we use the database and the associated service
|
60
|
+
const token0 = await TokenService.findUniqueFillOrThrow({
|
61
|
+
chainId: computeChainId,
|
62
|
+
address: token0Address,
|
63
|
+
});
|
64
|
+
const token1 = await TokenService.findUniqueFillOrThrow({
|
65
|
+
chainId: computeChainId,
|
66
|
+
address: token1Address,
|
67
|
+
});
|
68
|
+
if (!token0.decimals || !token0.price) {
|
69
|
+
throw new Error(`Missing decimals or price for token ${token0.address}`);
|
70
|
+
}
|
71
|
+
if (!token1.decimals || !token1.price) {
|
72
|
+
throw new Error(`Missing decimals or price for token ${token1.address}`);
|
73
|
+
}
|
74
|
+
tvls.push({
|
75
|
+
campaign,
|
76
|
+
tvl: bigIntToNumber(reserve0, token0.decimals) * token0.price +
|
77
|
+
bigIntToNumber(reserve1, token1.decimals) * token1.price,
|
78
|
+
tvlBreakdown: [
|
79
|
+
{
|
80
|
+
identifier: token0.id,
|
81
|
+
type: TvlType.TOKEN,
|
82
|
+
value: bigIntToNumber(reserve0, token0.decimals),
|
83
|
+
},
|
84
|
+
{
|
85
|
+
identifier: token1.id,
|
86
|
+
type: TvlType.TOKEN,
|
87
|
+
value: bigIntToNumber(reserve1, token1.decimals),
|
88
|
+
},
|
89
|
+
],
|
90
|
+
});
|
91
|
+
}
|
92
|
+
return tvls;
|
93
|
+
}
|
94
|
+
}
|