@strkfarm/sdk 1.2.0 → 2.0.0-dev-strategy2.1
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/index.browser.global.js +76556 -66640
- package/dist/index.browser.mjs +34235 -24392
- package/dist/index.d.ts +2372 -793
- package/dist/index.js +31967 -22084
- package/dist/index.mjs +25545 -15719
- package/package.json +86 -76
- package/readme.md +56 -1
- package/src/data/extended-deposit.abi.json +3613 -0
- package/src/data/universal-vault.abi.json +135 -20
- package/src/dataTypes/_bignumber.ts +11 -0
- package/src/dataTypes/address.ts +7 -0
- package/src/global.ts +240 -193
- package/src/interfaces/common.tsx +26 -2
- package/src/modules/ExtendedWrapperSDk/index.ts +62 -0
- package/src/modules/ExtendedWrapperSDk/types.ts +311 -0
- package/src/modules/ExtendedWrapperSDk/wrapper.ts +448 -0
- package/src/modules/avnu.ts +17 -4
- package/src/modules/ekubo-quoter.ts +89 -10
- package/src/modules/erc20.ts +67 -21
- package/src/modules/harvests.ts +29 -43
- package/src/modules/index.ts +5 -1
- package/src/modules/lst-apr.ts +36 -0
- package/src/modules/midas.ts +159 -0
- package/src/modules/pricer-from-api.ts +2 -2
- package/src/modules/pricer-lst.ts +1 -1
- package/src/modules/pricer.ts +3 -38
- package/src/modules/token-market-data.ts +202 -0
- package/src/node/deployer.ts +1 -36
- package/src/strategies/autoCompounderStrk.ts +1 -1
- package/src/strategies/base-strategy.ts +20 -3
- package/src/strategies/btc-vesu-extended-strategy/core-strategy.tsx +1486 -0
- package/src/strategies/btc-vesu-extended-strategy/services/operationService.ts +32 -0
- package/src/strategies/btc-vesu-extended-strategy/utils/constants.ts +3 -0
- package/src/strategies/btc-vesu-extended-strategy/utils/helper.ts +396 -0
- package/src/strategies/btc-vesu-extended-strategy/utils/types.ts +5 -0
- package/src/strategies/ekubo-cl-vault.tsx +123 -306
- package/src/strategies/index.ts +7 -1
- package/src/strategies/svk-strategy.ts +247 -0
- package/src/strategies/universal-adapters/adapter-optimizer.ts +65 -0
- package/src/strategies/universal-adapters/adapter-utils.ts +5 -1
- package/src/strategies/universal-adapters/avnu-adapter.ts +432 -0
- package/src/strategies/universal-adapters/baseAdapter.ts +181 -153
- package/src/strategies/universal-adapters/common-adapter.ts +98 -77
- package/src/strategies/universal-adapters/extended-adapter.ts +976 -0
- package/src/strategies/universal-adapters/index.ts +7 -1
- package/src/strategies/universal-adapters/unused-balance-adapter.ts +109 -0
- package/src/strategies/universal-adapters/vesu-adapter.ts +230 -230
- package/src/strategies/universal-adapters/vesu-borrow-adapter.ts +1247 -0
- package/src/strategies/universal-adapters/vesu-multiply-adapter.ts +1306 -0
- package/src/strategies/universal-adapters/vesu-supply-only-adapter.ts +58 -51
- package/src/strategies/universal-lst-muliplier-strategy.tsx +716 -844
- package/src/strategies/universal-strategy.tsx +1103 -1181
- package/src/strategies/vesu-extended-strategy/services/operationService.ts +34 -0
- package/src/strategies/vesu-extended-strategy/types/transaction-metadata.ts +25 -0
- package/src/strategies/vesu-extended-strategy/utils/config.runtime.ts +77 -0
- package/src/strategies/vesu-extended-strategy/utils/constants.ts +50 -0
- package/src/strategies/vesu-extended-strategy/utils/helper.ts +367 -0
- package/src/strategies/vesu-extended-strategy/vesu-extended-strategy.tsx +1420 -0
- package/src/strategies/vesu-rebalance.tsx +16 -20
- package/src/utils/health-factor-math.ts +11 -5
|
@@ -0,0 +1,1247 @@
|
|
|
1
|
+
import {
|
|
2
|
+
BaseAdapterConfig,
|
|
3
|
+
BaseAdapter,
|
|
4
|
+
DepositParams,
|
|
5
|
+
WithdrawParams,
|
|
6
|
+
PositionInfo,
|
|
7
|
+
ManageCall,
|
|
8
|
+
AdapterLeafType,
|
|
9
|
+
GenerateCallFn,
|
|
10
|
+
} from "./baseAdapter";
|
|
11
|
+
import { num } from "starknet";
|
|
12
|
+
import { StandardMerkleTree } from "@/utils";
|
|
13
|
+
import VesuMultiplyAbi from "@/data/vesu-multiple.abi.json";
|
|
14
|
+
import { ContractAddr, Web3Number } from "@/dataTypes";
|
|
15
|
+
import { TokenInfo, VaultPosition } from "@/interfaces";
|
|
16
|
+
import {
|
|
17
|
+
DecreaseLeverParams,
|
|
18
|
+
IncreaseLeverParams,
|
|
19
|
+
Swap,
|
|
20
|
+
VesuAdapter,
|
|
21
|
+
} from "./vesu-adapter";
|
|
22
|
+
import { EkuboQuoter, TokenMarketData } from "@/modules";
|
|
23
|
+
import { Protocols } from "@/interfaces";
|
|
24
|
+
import { SupportedPosition, PositionAPY, APYType } from "./baseAdapter";
|
|
25
|
+
import {
|
|
26
|
+
SIMPLE_SANITIZER,
|
|
27
|
+
SIMPLE_SANITIZER_V2,
|
|
28
|
+
VESU_V2_MODIFY_POSITION_SANITIZER,
|
|
29
|
+
} from "./adapter-utils";
|
|
30
|
+
import { getVesuSingletonAddress } from "./vesu-adapter";
|
|
31
|
+
import { hash, Contract, CairoCustomEnum, Uint256 } from "starknet";
|
|
32
|
+
import VesuPoolV2Abi from "@/data/vesu-pool-v2.abi.json";
|
|
33
|
+
import { toBigInt } from "./adapter-utils";
|
|
34
|
+
import { logger } from "@/utils";
|
|
35
|
+
import { uint256 } from "starknet";
|
|
36
|
+
import { ExtendedAdapter, VesuMultiplyAdapter } from "../universal-adapters";
|
|
37
|
+
import { AvnuAdapter } from "./avnu-adapter";
|
|
38
|
+
import { DepositParamsForLendingBorrowing } from "../btc-vesu-extended-strategy/utils/types";
|
|
39
|
+
import { WBTC_TOKEN_DECIMALS } from "../vesu-extended-strategy/utils/constants";
|
|
40
|
+
|
|
41
|
+
export interface VesuBorrowSupplyAdapterConfig extends BaseAdapterConfig {
|
|
42
|
+
poolId: ContractAddr;
|
|
43
|
+
borrowToken: TokenInfo;
|
|
44
|
+
supplyToken: TokenInfo;
|
|
45
|
+
targetHealthFactor: number;
|
|
46
|
+
minHealthFactor: number;
|
|
47
|
+
quoteAmountToFetchPrice: Web3Number;
|
|
48
|
+
vaultIdExtended: number;
|
|
49
|
+
extendedContract: ContractAddr;
|
|
50
|
+
extendedBackendUrl: string;
|
|
51
|
+
extendedApiKey: string;
|
|
52
|
+
extendedTimeout: number;
|
|
53
|
+
extendedRetries: number;
|
|
54
|
+
extendedBaseUrl: string;
|
|
55
|
+
extendedMarketName: string;
|
|
56
|
+
extendedPrecision: number;
|
|
57
|
+
extendedAdapter: ExtendedAdapter;
|
|
58
|
+
avnuAdapter: AvnuAdapter;
|
|
59
|
+
retryDelayForOrderStatus: number;
|
|
60
|
+
minimumExtendedMovementAmount: number;
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
export class VesuBorrowSupplyAdapter extends BaseAdapter<
|
|
64
|
+
DepositParams,
|
|
65
|
+
WithdrawParams
|
|
66
|
+
> {
|
|
67
|
+
readonly config: VesuBorrowSupplyAdapterConfig;
|
|
68
|
+
readonly vesuAdapter: VesuAdapter;
|
|
69
|
+
readonly tokenMarketData: TokenMarketData;
|
|
70
|
+
protected extendedAdapter: ExtendedAdapter;
|
|
71
|
+
|
|
72
|
+
constructor(config: VesuBorrowSupplyAdapterConfig) {
|
|
73
|
+
super(config, VesuBorrowSupplyAdapter.name, Protocols.VESU);
|
|
74
|
+
this.config = config;
|
|
75
|
+
this.vesuAdapter = new VesuAdapter({
|
|
76
|
+
poolId: config.poolId,
|
|
77
|
+
collateral: config.supplyToken, //wbtc
|
|
78
|
+
debt: config.borrowToken, //usdc
|
|
79
|
+
vaultAllocator: config.vaultAllocator,
|
|
80
|
+
id: "",
|
|
81
|
+
});
|
|
82
|
+
this.tokenMarketData = new TokenMarketData(
|
|
83
|
+
this.config.pricer,
|
|
84
|
+
this.config.networkConfig
|
|
85
|
+
);
|
|
86
|
+
this.extendedAdapter = new ExtendedAdapter({
|
|
87
|
+
baseToken: this.config.baseToken,
|
|
88
|
+
supportedPositions: this.config.supportedPositions,
|
|
89
|
+
networkConfig: this.config.networkConfig,
|
|
90
|
+
pricer: this.config.pricer,
|
|
91
|
+
vaultAddress: this.config.vaultAddress,
|
|
92
|
+
vaultAllocator: this.config.vaultAllocator,
|
|
93
|
+
vaultIdExtended: this.config.vaultIdExtended,
|
|
94
|
+
extendedContract: this.config.extendedContract,
|
|
95
|
+
extendedBackendUrl: this.config.extendedBackendUrl,
|
|
96
|
+
extendedApiKey: this.config.extendedApiKey,
|
|
97
|
+
extendedTimeout: this.config.extendedTimeout,
|
|
98
|
+
extendedRetries: this.config.extendedRetries,
|
|
99
|
+
extendedBaseUrl: this.config.extendedBaseUrl,
|
|
100
|
+
extendedMarketName: this.config.extendedMarketName,
|
|
101
|
+
extendedPrecision: this.config.extendedPrecision,
|
|
102
|
+
avnuAdapter: this.config.avnuAdapter,
|
|
103
|
+
retryDelayForOrderStatus: this.config.retryDelayForOrderStatus,
|
|
104
|
+
minimumExtendedMovementAmount: this.config.minimumExtendedMovementAmount,
|
|
105
|
+
});
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
protected async getAPY(
|
|
109
|
+
supportedPosition: SupportedPosition
|
|
110
|
+
): Promise<PositionAPY> {
|
|
111
|
+
return {
|
|
112
|
+
apy: 0,
|
|
113
|
+
type: APYType.BASE,
|
|
114
|
+
};
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
protected async getPosition(
|
|
118
|
+
supportedPosition: SupportedPosition
|
|
119
|
+
): Promise<VaultPosition> {
|
|
120
|
+
return {} as VaultPosition;
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
async maxBorrowableAPY(): Promise<number> {
|
|
124
|
+
// get collateral APY
|
|
125
|
+
const collateralAPY = await this.getAPY({
|
|
126
|
+
asset: this.config.supplyToken,
|
|
127
|
+
isDebt: false,
|
|
128
|
+
});
|
|
129
|
+
const apy = collateralAPY.apy * 0.8;
|
|
130
|
+
return apy;
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
async maxDeposit(amount?: Web3Number): Promise<PositionInfo> {
|
|
134
|
+
return {
|
|
135
|
+
tokenInfo: this.config.supplyToken,
|
|
136
|
+
amount: new Web3Number(
|
|
137
|
+
"999999999999999999999999999",
|
|
138
|
+
this.config.supplyToken.decimals
|
|
139
|
+
),
|
|
140
|
+
usdValue: 999999999999999999999999999,
|
|
141
|
+
remarks: "Max deposit (infinity)",
|
|
142
|
+
apy: await this.getAPY({ asset: this.config.supplyToken, isDebt: false }),
|
|
143
|
+
protocol: this.protocol,
|
|
144
|
+
};
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
async maxWithdraw(): Promise<PositionInfo> {
|
|
148
|
+
return {
|
|
149
|
+
tokenInfo: this.config.borrowToken,
|
|
150
|
+
amount: new Web3Number(
|
|
151
|
+
"999999999999999999999999999",
|
|
152
|
+
this.config.borrowToken.decimals
|
|
153
|
+
),
|
|
154
|
+
usdValue: 999999999999999999999999999,
|
|
155
|
+
remarks: "Max withdraw (infinity)",
|
|
156
|
+
apy: await this.getAPY({ asset: this.config.borrowToken, isDebt: false }),
|
|
157
|
+
protocol: this.protocol,
|
|
158
|
+
};
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
protected _getDepositLeaf(): {
|
|
162
|
+
target: ContractAddr;
|
|
163
|
+
method: string;
|
|
164
|
+
packedArguments: bigint[];
|
|
165
|
+
sanitizer: ContractAddr;
|
|
166
|
+
id: string;
|
|
167
|
+
}[] {
|
|
168
|
+
const supplyToken = this.config.supplyToken; //wbtc
|
|
169
|
+
const borrowToken = this.config.borrowToken; //usdc
|
|
170
|
+
const { addr: vesuSingleton } = getVesuSingletonAddress(this.config.poolId);
|
|
171
|
+
return [
|
|
172
|
+
{
|
|
173
|
+
target: supplyToken.address,
|
|
174
|
+
method: "approve",
|
|
175
|
+
packedArguments: [
|
|
176
|
+
vesuSingleton.toBigInt(), // spender
|
|
177
|
+
],
|
|
178
|
+
sanitizer: SIMPLE_SANITIZER,
|
|
179
|
+
id: `approve_supply_${supplyToken.symbol}`,
|
|
180
|
+
},
|
|
181
|
+
{
|
|
182
|
+
target: vesuSingleton,
|
|
183
|
+
method: "modify_position",
|
|
184
|
+
packedArguments: [
|
|
185
|
+
supplyToken.address.toBigInt(),
|
|
186
|
+
borrowToken.address.toBigInt(),
|
|
187
|
+
this.config.vaultAllocator.toBigInt(),
|
|
188
|
+
],
|
|
189
|
+
sanitizer: VESU_V2_MODIFY_POSITION_SANITIZER,
|
|
190
|
+
id: `modify_position_supply_${supplyToken.symbol}`,
|
|
191
|
+
},
|
|
192
|
+
];
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
protected _getPayDebtLeaf(): {
|
|
196
|
+
target: ContractAddr;
|
|
197
|
+
method: string;
|
|
198
|
+
packedArguments: bigint[];
|
|
199
|
+
sanitizer: ContractAddr;
|
|
200
|
+
id: string;
|
|
201
|
+
}[] {
|
|
202
|
+
const supplyToken = this.config.supplyToken; //wbtc
|
|
203
|
+
const borrowToken = this.config.borrowToken; //usdc
|
|
204
|
+
const { addr: vesuSingleton } = getVesuSingletonAddress(this.config.poolId);
|
|
205
|
+
return [
|
|
206
|
+
{
|
|
207
|
+
target: borrowToken.address,
|
|
208
|
+
method: "approve",
|
|
209
|
+
packedArguments: [
|
|
210
|
+
vesuSingleton.toBigInt(), // spender
|
|
211
|
+
],
|
|
212
|
+
sanitizer: SIMPLE_SANITIZER,
|
|
213
|
+
id: `approve_borrow_${borrowToken.symbol}`,
|
|
214
|
+
},
|
|
215
|
+
{
|
|
216
|
+
target: vesuSingleton,
|
|
217
|
+
method: "modify_position",
|
|
218
|
+
packedArguments: [
|
|
219
|
+
supplyToken.address.toBigInt(),
|
|
220
|
+
borrowToken.address.toBigInt(),
|
|
221
|
+
this.config.vaultAllocator.toBigInt(),
|
|
222
|
+
],
|
|
223
|
+
sanitizer: VESU_V2_MODIFY_POSITION_SANITIZER,
|
|
224
|
+
id: `modify_position_borrow_${borrowToken.symbol}`,
|
|
225
|
+
},
|
|
226
|
+
];
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
protected _getBorrowLeaf(): {
|
|
230
|
+
target: ContractAddr;
|
|
231
|
+
method: string;
|
|
232
|
+
packedArguments: bigint[];
|
|
233
|
+
sanitizer: ContractAddr;
|
|
234
|
+
id: string;
|
|
235
|
+
}[] {
|
|
236
|
+
const supplyToken = this.config.supplyToken; //wbtc
|
|
237
|
+
const borrowToken = this.config.borrowToken; //usdc
|
|
238
|
+
const { addr: vesuSingleton } = getVesuSingletonAddress(this.config.poolId);
|
|
239
|
+
return [
|
|
240
|
+
{
|
|
241
|
+
target: supplyToken.address,
|
|
242
|
+
method: "approve",
|
|
243
|
+
packedArguments: [
|
|
244
|
+
vesuSingleton.toBigInt(), // spender
|
|
245
|
+
],
|
|
246
|
+
sanitizer: SIMPLE_SANITIZER,
|
|
247
|
+
id: `approval_supply_${supplyToken.symbol}`,
|
|
248
|
+
},
|
|
249
|
+
{
|
|
250
|
+
target: vesuSingleton,
|
|
251
|
+
method: "modify_position",
|
|
252
|
+
packedArguments: [
|
|
253
|
+
supplyToken.address.toBigInt(),
|
|
254
|
+
borrowToken.address.toBigInt(),
|
|
255
|
+
this.config.vaultAllocator.toBigInt(),
|
|
256
|
+
],
|
|
257
|
+
sanitizer: VESU_V2_MODIFY_POSITION_SANITIZER,
|
|
258
|
+
id: `modification_posn_sup_${supplyToken.symbol}`,
|
|
259
|
+
},
|
|
260
|
+
];
|
|
261
|
+
}
|
|
262
|
+
|
|
263
|
+
protected _getMultiplyLeaf(): {
|
|
264
|
+
target: ContractAddr;
|
|
265
|
+
method: string;
|
|
266
|
+
packedArguments: bigint[];
|
|
267
|
+
sanitizer: ContractAddr;
|
|
268
|
+
id: string;
|
|
269
|
+
}[] {
|
|
270
|
+
const collateral = this.config.supplyToken;
|
|
271
|
+
const debt = this.config.borrowToken;
|
|
272
|
+
const { addr: vesuSingleton, isV2 } = getVesuSingletonAddress(
|
|
273
|
+
this.config.poolId
|
|
274
|
+
);
|
|
275
|
+
const vesuMultiply = isV2
|
|
276
|
+
? this.vesuAdapter.VESU_MULTIPLY
|
|
277
|
+
: this.vesuAdapter.VESU_MULTIPLY_V1;
|
|
278
|
+
|
|
279
|
+
return [
|
|
280
|
+
// Approval step for collateral
|
|
281
|
+
{
|
|
282
|
+
target: collateral.address,
|
|
283
|
+
method: "approve",
|
|
284
|
+
packedArguments: [
|
|
285
|
+
vesuMultiply.toBigInt(), // spender
|
|
286
|
+
],
|
|
287
|
+
sanitizer: SIMPLE_SANITIZER,
|
|
288
|
+
// amc = approve multiply collateral
|
|
289
|
+
id: `amc_${this.config.poolId.shortString()}_${collateral.symbol}_supplyLend`,
|
|
290
|
+
},
|
|
291
|
+
// Switch delegation on
|
|
292
|
+
{
|
|
293
|
+
target: vesuSingleton,
|
|
294
|
+
method: "modify_delegation",
|
|
295
|
+
packedArguments: isV2
|
|
296
|
+
? [
|
|
297
|
+
vesuMultiply.toBigInt(), // delegatee
|
|
298
|
+
]
|
|
299
|
+
: [
|
|
300
|
+
this.config.poolId.toBigInt(),
|
|
301
|
+
vesuMultiply.toBigInt(), // delegatee
|
|
302
|
+
],
|
|
303
|
+
sanitizer: isV2 ? SIMPLE_SANITIZER_V2 : SIMPLE_SANITIZER,
|
|
304
|
+
// sd1 = switch delegation on
|
|
305
|
+
id: `sd1_${this.config.poolId.shortString()}_${collateral.symbol}_supplyLend`,
|
|
306
|
+
},
|
|
307
|
+
// Vesu multiply call
|
|
308
|
+
{
|
|
309
|
+
target: vesuMultiply,
|
|
310
|
+
method: "modify_lever",
|
|
311
|
+
packedArguments: [
|
|
312
|
+
this.config.poolId.toBigInt(),
|
|
313
|
+
collateral.address.toBigInt(),
|
|
314
|
+
debt.address.toBigInt(),
|
|
315
|
+
this.config.vaultAllocator.toBigInt(),
|
|
316
|
+
],
|
|
317
|
+
sanitizer: SIMPLE_SANITIZER_V2,
|
|
318
|
+
// vm = vesu multiply
|
|
319
|
+
id: `vm_${this.config.poolId.shortString()}_${collateral.symbol}_supplyLend`,
|
|
320
|
+
},
|
|
321
|
+
// Switch delegation off
|
|
322
|
+
{
|
|
323
|
+
target: vesuSingleton,
|
|
324
|
+
method: "modify_delegation",
|
|
325
|
+
packedArguments: isV2
|
|
326
|
+
? [
|
|
327
|
+
vesuMultiply.toBigInt(), // delegatee
|
|
328
|
+
]
|
|
329
|
+
: [
|
|
330
|
+
this.config.poolId.toBigInt(),
|
|
331
|
+
vesuMultiply.toBigInt(), // delegatee
|
|
332
|
+
],
|
|
333
|
+
sanitizer: isV2 ? SIMPLE_SANITIZER_V2 : SIMPLE_SANITIZER,
|
|
334
|
+
// sd2 = switch delegation off
|
|
335
|
+
id: `sd2_${this.config.poolId.shortString()}_${collateral.symbol}_supplyLend`,
|
|
336
|
+
},
|
|
337
|
+
];
|
|
338
|
+
}
|
|
339
|
+
|
|
340
|
+
protected _getWithdrawLeaf(): {
|
|
341
|
+
target: ContractAddr;
|
|
342
|
+
method: string;
|
|
343
|
+
packedArguments: bigint[];
|
|
344
|
+
sanitizer: ContractAddr;
|
|
345
|
+
id: string;
|
|
346
|
+
}[] {
|
|
347
|
+
// Withdraw supply token
|
|
348
|
+
const borrowToken = this.config.borrowToken;
|
|
349
|
+
const supplyToken = this.config.supplyToken;
|
|
350
|
+
const { addr: vesuSingleton } = getVesuSingletonAddress(this.config.poolId);
|
|
351
|
+
return [
|
|
352
|
+
{
|
|
353
|
+
target: supplyToken.address,
|
|
354
|
+
method: "approve",
|
|
355
|
+
packedArguments: [
|
|
356
|
+
vesuSingleton.toBigInt(), // spender
|
|
357
|
+
],
|
|
358
|
+
sanitizer: SIMPLE_SANITIZER,
|
|
359
|
+
id: `approve_supply_USDC`,
|
|
360
|
+
},
|
|
361
|
+
{
|
|
362
|
+
target: vesuSingleton,
|
|
363
|
+
method: "modify_position",
|
|
364
|
+
packedArguments: [
|
|
365
|
+
this.config.poolId.toBigInt(),
|
|
366
|
+
supplyToken.address.toBigInt(),
|
|
367
|
+
borrowToken.address.toBigInt(),
|
|
368
|
+
this.config.vaultAllocator.toBigInt(),
|
|
369
|
+
],
|
|
370
|
+
sanitizer: SIMPLE_SANITIZER,
|
|
371
|
+
id: `modify_position_supply_USDC`,
|
|
372
|
+
},
|
|
373
|
+
];
|
|
374
|
+
}
|
|
375
|
+
|
|
376
|
+
async getHealthFactor(): Promise<number> {
|
|
377
|
+
const healthFactor = await this.vesuAdapter.getHealthFactor();
|
|
378
|
+
return healthFactor;
|
|
379
|
+
}
|
|
380
|
+
|
|
381
|
+
getPayDebtLeaf(): AdapterLeafType<DepositParams> {
|
|
382
|
+
const leafConfigs = this._getPayDebtLeaf();
|
|
383
|
+
const leaves = leafConfigs.map((config) => {
|
|
384
|
+
const { target, method, packedArguments, sanitizer, id } = config;
|
|
385
|
+
const leaf = this.constructSimpleLeafData(
|
|
386
|
+
{
|
|
387
|
+
id: id,
|
|
388
|
+
target,
|
|
389
|
+
method,
|
|
390
|
+
packedArguments,
|
|
391
|
+
},
|
|
392
|
+
sanitizer
|
|
393
|
+
);
|
|
394
|
+
return leaf;
|
|
395
|
+
});
|
|
396
|
+
return {
|
|
397
|
+
leaves,
|
|
398
|
+
callConstructor: this.getPayDebtCall.bind(
|
|
399
|
+
this
|
|
400
|
+
) as unknown as GenerateCallFn<DepositParams>,
|
|
401
|
+
};
|
|
402
|
+
}
|
|
403
|
+
|
|
404
|
+
getMultiplyLeaf(): AdapterLeafType<DepositParams> {
|
|
405
|
+
const leafConfigs = this._getMultiplyLeaf();
|
|
406
|
+
const leaves = leafConfigs.map((config) => {
|
|
407
|
+
const { target, method, packedArguments, sanitizer, id } = config;
|
|
408
|
+
const leaf = this.constructSimpleLeafData(
|
|
409
|
+
{
|
|
410
|
+
id: id,
|
|
411
|
+
target,
|
|
412
|
+
method,
|
|
413
|
+
packedArguments,
|
|
414
|
+
},
|
|
415
|
+
sanitizer
|
|
416
|
+
);
|
|
417
|
+
return leaf;
|
|
418
|
+
});
|
|
419
|
+
return {
|
|
420
|
+
leaves,
|
|
421
|
+
callConstructor: this.getMultiplyCall.bind(
|
|
422
|
+
this
|
|
423
|
+
) as unknown as GenerateCallFn<DepositParams>,
|
|
424
|
+
};
|
|
425
|
+
}
|
|
426
|
+
|
|
427
|
+
getBorrowLeaf(): AdapterLeafType<DepositParams> {
|
|
428
|
+
const leafConfigs = this._getBorrowLeaf();
|
|
429
|
+
const leaves = leafConfigs.map((config) => {
|
|
430
|
+
const { target, method, packedArguments, sanitizer, id } = config;
|
|
431
|
+
const leaf = this.constructSimpleLeafData(
|
|
432
|
+
{ id: id, target, method, packedArguments },
|
|
433
|
+
sanitizer
|
|
434
|
+
);
|
|
435
|
+
return leaf;
|
|
436
|
+
});
|
|
437
|
+
return {
|
|
438
|
+
leaves,
|
|
439
|
+
callConstructor: this.getBorrowCall.bind(this) as unknown as GenerateCallFn<DepositParams>,
|
|
440
|
+
};
|
|
441
|
+
}
|
|
442
|
+
|
|
443
|
+
async getDepositCall(params: DepositParams): Promise<ManageCall[]> {
|
|
444
|
+
return [
|
|
445
|
+
];
|
|
446
|
+
}
|
|
447
|
+
|
|
448
|
+
|
|
449
|
+
|
|
450
|
+
async getWithdrawCall(params: WithdrawParams): Promise<ManageCall[]> {
|
|
451
|
+
return [
|
|
452
|
+
];
|
|
453
|
+
}
|
|
454
|
+
|
|
455
|
+
/**
|
|
456
|
+
* Pay the debt amount against the collateral amount
|
|
457
|
+
* @param params { supplyAmount: Web3Number; debtAmount: Web3Number; }
|
|
458
|
+
* @returns { ManageCall[] }
|
|
459
|
+
*/
|
|
460
|
+
async getPayDebtCall(params: {
|
|
461
|
+
supplyAmount: Web3Number;
|
|
462
|
+
debtAmount: Web3Number;
|
|
463
|
+
}): Promise<ManageCall[]> {
|
|
464
|
+
const borrowToken = this.config.borrowToken;
|
|
465
|
+
const { addr: vesuSingleton } = getVesuSingletonAddress(this.config.poolId);
|
|
466
|
+
const uint256MarginAmount = uint256.bnToUint256(params.debtAmount.toWei());
|
|
467
|
+
console.log(
|
|
468
|
+
"uint256MarginAmount",
|
|
469
|
+
uint256MarginAmount,
|
|
470
|
+
params.debtAmount.toWei()
|
|
471
|
+
);
|
|
472
|
+
return [
|
|
473
|
+
{
|
|
474
|
+
sanitizer: SIMPLE_SANITIZER,
|
|
475
|
+
call: {
|
|
476
|
+
contractAddress: borrowToken.address,
|
|
477
|
+
selector: hash.getSelectorFromName("approve"),
|
|
478
|
+
calldata: [
|
|
479
|
+
vesuSingleton.toBigInt(), // spender,
|
|
480
|
+
toBigInt(uint256MarginAmount.low.toString()), // amount low
|
|
481
|
+
toBigInt(uint256MarginAmount.high.toString()), // amount high
|
|
482
|
+
],
|
|
483
|
+
},
|
|
484
|
+
},
|
|
485
|
+
{
|
|
486
|
+
sanitizer: VESU_V2_MODIFY_POSITION_SANITIZER,
|
|
487
|
+
call: {
|
|
488
|
+
contractAddress: vesuSingleton,
|
|
489
|
+
selector: hash.getSelectorFromName("modify_position"),
|
|
490
|
+
/**
|
|
491
|
+
* In case of debt payment, just call this, the calldata is dynamic for both operations
|
|
492
|
+
*/
|
|
493
|
+
calldata: (await this.getDepositCalldata(
|
|
494
|
+
params.supplyAmount,
|
|
495
|
+
params.debtAmount,
|
|
496
|
+
|
|
497
|
+
)) as bigint[],
|
|
498
|
+
},
|
|
499
|
+
},
|
|
500
|
+
];
|
|
501
|
+
}
|
|
502
|
+
|
|
503
|
+
/**
|
|
504
|
+
* Increase the debt amount against the collateral amount
|
|
505
|
+
* @param params { supplyAmount: Web3Number; debtAmount: Web3Number; }
|
|
506
|
+
* @returns { ManageCall[] }
|
|
507
|
+
*/
|
|
508
|
+
async getBorrowCall(params: {
|
|
509
|
+
supplyAmount: Web3Number;
|
|
510
|
+
debtAmount: Web3Number;
|
|
511
|
+
}): Promise<ManageCall[]> {
|
|
512
|
+
const supplyToken = this.config.supplyToken;
|
|
513
|
+
const { addr: vesuSingleton } = getVesuSingletonAddress(this.config.poolId);
|
|
514
|
+
const uint256MarginAmount = uint256.bnToUint256(params.supplyAmount.toWei());
|
|
515
|
+
console.log(
|
|
516
|
+
"Supply token uint256MarginAmount",
|
|
517
|
+
uint256MarginAmount,
|
|
518
|
+
params.supplyAmount.toWei()
|
|
519
|
+
);
|
|
520
|
+
const uint256DebtAmount = uint256.bnToUint256(params.debtAmount.toWei());
|
|
521
|
+
console.log(
|
|
522
|
+
"Debt token uint256MarginAmount",
|
|
523
|
+
uint256DebtAmount,
|
|
524
|
+
params.debtAmount.toWei()
|
|
525
|
+
);
|
|
526
|
+
return [
|
|
527
|
+
{
|
|
528
|
+
sanitizer: SIMPLE_SANITIZER,
|
|
529
|
+
call: {
|
|
530
|
+
contractAddress: supplyToken.address,
|
|
531
|
+
selector: hash.getSelectorFromName("approve"),
|
|
532
|
+
calldata: [
|
|
533
|
+
vesuSingleton.toBigInt(), // spender,
|
|
534
|
+
toBigInt(uint256MarginAmount.low.toString()), // amount low
|
|
535
|
+
toBigInt(uint256MarginAmount.high.toString()), // amount high
|
|
536
|
+
],
|
|
537
|
+
},
|
|
538
|
+
},
|
|
539
|
+
{
|
|
540
|
+
sanitizer: VESU_V2_MODIFY_POSITION_SANITIZER,
|
|
541
|
+
call: {
|
|
542
|
+
contractAddress: vesuSingleton,
|
|
543
|
+
selector: hash.getSelectorFromName("modify_position"),
|
|
544
|
+
/**
|
|
545
|
+
* In case of debt payment, just call this, the calldata is dynamic for both operations
|
|
546
|
+
*/
|
|
547
|
+
calldata: (await this.getDepositCalldata(
|
|
548
|
+
params.debtAmount,
|
|
549
|
+
params.supplyAmount,
|
|
550
|
+
)) as bigint[],
|
|
551
|
+
},
|
|
552
|
+
},
|
|
553
|
+
];
|
|
554
|
+
}
|
|
555
|
+
|
|
556
|
+
private async getMultiplyCall({
|
|
557
|
+
amount,
|
|
558
|
+
debtAmount,
|
|
559
|
+
isWithdraw,
|
|
560
|
+
closePosition
|
|
561
|
+
}: {
|
|
562
|
+
amount: Web3Number;
|
|
563
|
+
debtAmount: Web3Number;
|
|
564
|
+
isWithdraw: boolean;
|
|
565
|
+
closePosition: boolean;
|
|
566
|
+
}): Promise<ManageCall[]> {
|
|
567
|
+
const collateralToken = this.config.supplyToken;
|
|
568
|
+
const { addr: vesuSingleton, isV2 } = getVesuSingletonAddress(
|
|
569
|
+
this.config.poolId
|
|
570
|
+
);
|
|
571
|
+
const vesuMultiply = isV2
|
|
572
|
+
? this.vesuAdapter.VESU_MULTIPLY
|
|
573
|
+
: this.vesuAdapter.VESU_MULTIPLY_V1;
|
|
574
|
+
|
|
575
|
+
logger.info(`amount: ${amount} isWithdraw: ${isWithdraw}`);
|
|
576
|
+
const uint256MarginAmount = uint256.bnToUint256(amount.abs().toWei());
|
|
577
|
+
logger.info(`uint256MarginAmount: ${uint256MarginAmount} amount: ${amount.abs().toWei()}`);
|
|
578
|
+
return [
|
|
579
|
+
{
|
|
580
|
+
sanitizer: SIMPLE_SANITIZER,
|
|
581
|
+
call: {
|
|
582
|
+
contractAddress: collateralToken.address,
|
|
583
|
+
selector: hash.getSelectorFromName("approve"),
|
|
584
|
+
calldata: [
|
|
585
|
+
vesuMultiply.toBigInt(), // spender
|
|
586
|
+
toBigInt(uint256MarginAmount.low.toString()), // amount low
|
|
587
|
+
toBigInt(uint256MarginAmount.high.toString()), // amount high
|
|
588
|
+
],
|
|
589
|
+
},
|
|
590
|
+
},
|
|
591
|
+
// Switch delegation on
|
|
592
|
+
{
|
|
593
|
+
sanitizer: isV2 ? SIMPLE_SANITIZER_V2 : SIMPLE_SANITIZER,
|
|
594
|
+
call: {
|
|
595
|
+
contractAddress: vesuSingleton,
|
|
596
|
+
selector: hash.getSelectorFromName("modify_delegation"),
|
|
597
|
+
calldata: isV2
|
|
598
|
+
? [
|
|
599
|
+
vesuMultiply.toBigInt(), // delegatee
|
|
600
|
+
BigInt(1), // delegation: true
|
|
601
|
+
]
|
|
602
|
+
: [
|
|
603
|
+
this.config.poolId.toBigInt(),
|
|
604
|
+
vesuMultiply.toBigInt(), // delegatee
|
|
605
|
+
BigInt(1), // delegation: true
|
|
606
|
+
],
|
|
607
|
+
},
|
|
608
|
+
},
|
|
609
|
+
{
|
|
610
|
+
sanitizer: SIMPLE_SANITIZER_V2,
|
|
611
|
+
call: {
|
|
612
|
+
contractAddress: vesuMultiply,
|
|
613
|
+
selector: hash.getSelectorFromName("modify_lever"),
|
|
614
|
+
calldata: !isWithdraw ? await this.getMultiplyCallCalldata(
|
|
615
|
+
amount,
|
|
616
|
+
debtAmount,
|
|
617
|
+
) : closePosition ? await this.getClosePositionCalldata(amount, debtAmount) : await this.getWithdrawalMultiplyCalldata(amount, debtAmount),
|
|
618
|
+
},
|
|
619
|
+
},
|
|
620
|
+
{
|
|
621
|
+
sanitizer: isV2 ? SIMPLE_SANITIZER_V2 : SIMPLE_SANITIZER,
|
|
622
|
+
call: {
|
|
623
|
+
contractAddress: vesuSingleton,
|
|
624
|
+
selector: hash.getSelectorFromName("modify_delegation"),
|
|
625
|
+
calldata: isV2
|
|
626
|
+
? [
|
|
627
|
+
vesuMultiply.toBigInt(), // delegatee
|
|
628
|
+
BigInt(0), // delegation: false
|
|
629
|
+
]
|
|
630
|
+
: [
|
|
631
|
+
this.config.poolId.toBigInt(),
|
|
632
|
+
vesuMultiply.toBigInt(), // delegatee
|
|
633
|
+
BigInt(0), // delegation: false
|
|
634
|
+
],
|
|
635
|
+
},
|
|
636
|
+
},
|
|
637
|
+
];
|
|
638
|
+
}
|
|
639
|
+
|
|
640
|
+
private async getMultiplyCallCalldata(
|
|
641
|
+
params: Web3Number,
|
|
642
|
+
debtAmount: Web3Number,
|
|
643
|
+
): Promise<bigint[]> {
|
|
644
|
+
const collateralToken = this.config.supplyToken;
|
|
645
|
+
const debtToken = this.config.borrowToken;
|
|
646
|
+
const { isV2 } = getVesuSingletonAddress(this.config.poolId);
|
|
647
|
+
const vesuMultiply = isV2
|
|
648
|
+
? this.vesuAdapter.VESU_MULTIPLY
|
|
649
|
+
: this.vesuAdapter.VESU_MULTIPLY_V1;
|
|
650
|
+
|
|
651
|
+
const multiplyContract = new Contract({
|
|
652
|
+
abi: VesuMultiplyAbi,
|
|
653
|
+
address: vesuMultiply.address,
|
|
654
|
+
providerOrAccount: this.config.networkConfig.provider,
|
|
655
|
+
});
|
|
656
|
+
let leverSwap: Swap[] = [];
|
|
657
|
+
let leverSwapLimitAmount = Web3Number.fromWei(
|
|
658
|
+
0,
|
|
659
|
+
this.config.borrowToken.decimals
|
|
660
|
+
);
|
|
661
|
+
const collateralPrice = (
|
|
662
|
+
await this.config.pricer.getPrice(collateralToken.symbol)
|
|
663
|
+
).price;
|
|
664
|
+
const debtPrice = (await this.config.pricer.getPrice(debtToken.symbol))
|
|
665
|
+
.price;
|
|
666
|
+
const ekuboQuoter = new EkuboQuoter(
|
|
667
|
+
this.config.networkConfig,
|
|
668
|
+
this.config.pricer
|
|
669
|
+
);
|
|
670
|
+
const debtAmountInCollateralUnits = new Web3Number(
|
|
671
|
+
debtAmount
|
|
672
|
+
.multipliedBy(debtPrice)
|
|
673
|
+
.dividedBy(collateralPrice)
|
|
674
|
+
.multipliedBy(10 ** collateralToken.decimals)
|
|
675
|
+
.toFixed(0),
|
|
676
|
+
collateralToken.decimals
|
|
677
|
+
);
|
|
678
|
+
logger.info(`debtAmount: ${debtAmount}`);
|
|
679
|
+
logger.info(`debtPrice: ${debtPrice}`);
|
|
680
|
+
logger.info(`collateralPrice: ${collateralPrice}`);
|
|
681
|
+
logger.info(`debtAmountInCollateralUnits: ${debtAmountInCollateralUnits}`);
|
|
682
|
+
// increase multiply lever or not
|
|
683
|
+
const isIncrease = debtAmount.greaterThanOrEqualTo(0);
|
|
684
|
+
|
|
685
|
+
// due to directional limitations in multiply contract
|
|
686
|
+
if (isIncrease && debtAmount.lessThan(0)) {
|
|
687
|
+
// we are increasing lever but math says reduce debt
|
|
688
|
+
// - this is ok
|
|
689
|
+
} else if (!isIncrease && debtAmount.greaterThan(0)) {
|
|
690
|
+
// we are decreasing level but math says increase debt
|
|
691
|
+
// - such actions must be done with zero margin amount
|
|
692
|
+
// - so just set debt 0
|
|
693
|
+
debtAmount = Web3Number.fromWei(0, debtToken.decimals);
|
|
694
|
+
}
|
|
695
|
+
logger.verbose(
|
|
696
|
+
`${VesuMultiplyAdapter.name}::getVesuMultiplyCall debtAmount: ${debtAmount}`
|
|
697
|
+
);
|
|
698
|
+
if (!debtAmount.isZero()) {
|
|
699
|
+
// Get swap quote for leverage operation
|
|
700
|
+
// Determine swap direction based on operation type
|
|
701
|
+
|
|
702
|
+
try {
|
|
703
|
+
console.log("debtAmountInCollateralUnits", debtAmountInCollateralUnits);
|
|
704
|
+
console.log("debtToken.address.address", debtToken.address.address);
|
|
705
|
+
console.log("collateralToken.address.address", collateralToken.address.address);
|
|
706
|
+
const swapQuote = await ekuboQuoter.getQuote(
|
|
707
|
+
collateralToken.address.address,
|
|
708
|
+
debtToken.address.address,
|
|
709
|
+
debtAmountInCollateralUnits.multipliedBy(-1) // negative for exact amount out
|
|
710
|
+
);
|
|
711
|
+
|
|
712
|
+
// todo add better slip checks
|
|
713
|
+
// Check price impact
|
|
714
|
+
if (swapQuote.price_impact < 0.01) {
|
|
715
|
+
// 1% max price impact
|
|
716
|
+
// from and toToken param position reversed, to fetch the required quote and keep things generalised
|
|
717
|
+
|
|
718
|
+
leverSwap = debtAmount.isNegative()
|
|
719
|
+
? ekuboQuoter.getVesuMultiplyQuote(
|
|
720
|
+
swapQuote,
|
|
721
|
+
collateralToken,
|
|
722
|
+
debtToken
|
|
723
|
+
)
|
|
724
|
+
: ekuboQuoter.getVesuMultiplyQuote(
|
|
725
|
+
swapQuote,
|
|
726
|
+
debtToken,
|
|
727
|
+
collateralToken
|
|
728
|
+
);
|
|
729
|
+
//console.log(JSON.stringify(leverSwap));
|
|
730
|
+
// Calculate limit amount with slippage protection
|
|
731
|
+
const MAX_SLIPPAGE = 0.002; // 0.2% slippage
|
|
732
|
+
if (debtAmount.greaterThan(0)) {
|
|
733
|
+
// For increase: minimum amount of collateral received
|
|
734
|
+
// from debt token to collateral token
|
|
735
|
+
//console.log("debtAmountInCollateralUnits", debtAmountInCollateralUnits.toNumber());
|
|
736
|
+
//leverSwapLimitAmount = await ekuboQuoter.getSwapLimitAmount(debtToken, collateralToken, debtAmount, MAX_SLIPPAGE);
|
|
737
|
+
leverSwapLimitAmount = debtAmount.multipliedBy(1 + MAX_SLIPPAGE);
|
|
738
|
+
//console.log("anotherleverSwapLimitAmount", anotherleverSwapLimitAmount, leverSwapLimitAmount);
|
|
739
|
+
} else if (debtAmount.lessThan(0)) {
|
|
740
|
+
// For decrease: maximum amount of collateral used
|
|
741
|
+
// from collateral token to debt token
|
|
742
|
+
//leverSwapLimitAmount = await ekuboQuoter.getSwapLimitAmount(collateralToken, debtToken, debtAmountInCollateralUnits.multipliedBy(-1), MAX_SLIPPAGE);
|
|
743
|
+
leverSwapLimitAmount = debtAmount
|
|
744
|
+
.abs()
|
|
745
|
+
.multipliedBy(1 - MAX_SLIPPAGE);
|
|
746
|
+
//console.log("anotherleverSwapLimitAmount", anotherleverSwapLimitAmount, leverSwapLimitAmount);
|
|
747
|
+
} else {
|
|
748
|
+
leverSwapLimitAmount = Web3Number.fromWei(0, debtToken.decimals);
|
|
749
|
+
}
|
|
750
|
+
await new Promise((resolve) => setTimeout(resolve, 1000));
|
|
751
|
+
//console.log("leverSwapLimitAmount", leverSwapLimitAmount);
|
|
752
|
+
} else {
|
|
753
|
+
throw new Error(
|
|
754
|
+
`VesuMultiplyAdapter: Price impact too high (${swapQuote.price_impact}), skipping swap`
|
|
755
|
+
);
|
|
756
|
+
}
|
|
757
|
+
} catch (error) {
|
|
758
|
+
throw new Error(
|
|
759
|
+
`VesuMultiplyAdapter: Failed to get swap quote: ${error}`
|
|
760
|
+
);
|
|
761
|
+
}
|
|
762
|
+
}
|
|
763
|
+
|
|
764
|
+
logger.info(`leverSwapLimitAmount: ${leverSwapLimitAmount} debtAmount: ${debtAmount} isIncrease: ${isIncrease}`);
|
|
765
|
+
const multiplyParams = await this.getLeverParams(
|
|
766
|
+
isIncrease,
|
|
767
|
+
params,
|
|
768
|
+
leverSwap,
|
|
769
|
+
leverSwapLimitAmount
|
|
770
|
+
);
|
|
771
|
+
|
|
772
|
+
const call = multiplyContract.populate("modify_lever", {
|
|
773
|
+
modify_lever_params: this.formatMultiplyParams(
|
|
774
|
+
isIncrease,
|
|
775
|
+
multiplyParams
|
|
776
|
+
),
|
|
777
|
+
});
|
|
778
|
+
const calldata = call.calldata as bigint[];
|
|
779
|
+
if (calldata) {
|
|
780
|
+
console.log("calldata", calldata);
|
|
781
|
+
}
|
|
782
|
+
return calldata;
|
|
783
|
+
}
|
|
784
|
+
|
|
785
|
+
private async getWithdrawalMultiplyCalldata(
|
|
786
|
+
params: Web3Number,
|
|
787
|
+
debtAmount: Web3Number,
|
|
788
|
+
): Promise<bigint[]> {
|
|
789
|
+
//params.amount must be in btc here
|
|
790
|
+
const { isV2 } = getVesuSingletonAddress(this.config.poolId);
|
|
791
|
+
const vesuMultiply = isV2
|
|
792
|
+
? this.vesuAdapter.VESU_MULTIPLY
|
|
793
|
+
: this.vesuAdapter.VESU_MULTIPLY_V1;
|
|
794
|
+
const multiplyContract = new Contract({
|
|
795
|
+
abi: VesuMultiplyAbi,
|
|
796
|
+
address: vesuMultiply.address,
|
|
797
|
+
providerOrAccount: this.config.networkConfig.provider,
|
|
798
|
+
});
|
|
799
|
+
let leverSwap: Swap[] = [];
|
|
800
|
+
let leverSwapLimitAmount = Web3Number.fromWei(0, this.config.borrowToken.decimals);
|
|
801
|
+
const collateralToken = this.config.supplyToken;
|
|
802
|
+
const debtToken = this.config.borrowToken;
|
|
803
|
+
const debtPrice = await this.config.pricer.getPrice(debtToken.symbol);
|
|
804
|
+
// the debt amount is negative as we are reducing debt to withdraw
|
|
805
|
+
//console.log("debtAmountToRepay", debtAmountToRepay);
|
|
806
|
+
const ekuboQuoter = new EkuboQuoter(
|
|
807
|
+
this.config.networkConfig,
|
|
808
|
+
this.config.pricer
|
|
809
|
+
);
|
|
810
|
+
const debtInDebtUnits = debtAmount
|
|
811
|
+
.dividedBy(debtPrice.price)
|
|
812
|
+
.multipliedBy(10 ** debtToken.decimals);
|
|
813
|
+
const swapQuote = await ekuboQuoter.getQuote(
|
|
814
|
+
debtToken.address.address,
|
|
815
|
+
collateralToken.address.address,
|
|
816
|
+
debtInDebtUnits
|
|
817
|
+
);
|
|
818
|
+
const MAX_SLIPPAGE = 0.002; // 0.2% slippag
|
|
819
|
+
// const debtInCollateralUnits = new Web3Number(existingDebtInfo.amount.dividedBy(collateralPrice.price).multipliedBy(debtPrice.price).toFixed(WBTC_TOKEN_DECIMALS), collateralToken.decimals);
|
|
820
|
+
// console.log("debtInCollateralUnits", debtInCollateralUnits, existingDebtInfo.amount, collateralPrice.price, debtPrice.price, WBTC_TOKEN_DECIMALS);
|
|
821
|
+
if (swapQuote.price_impact < 0.0025) {
|
|
822
|
+
leverSwap = ekuboQuoter.getVesuMultiplyQuote(
|
|
823
|
+
swapQuote,
|
|
824
|
+
collateralToken,
|
|
825
|
+
debtToken
|
|
826
|
+
);
|
|
827
|
+
} else {
|
|
828
|
+
logger.error(
|
|
829
|
+
`VesuMultiplyAdapter: Price impact too high (${swapQuote.price_impact}), skipping swap`
|
|
830
|
+
);
|
|
831
|
+
}
|
|
832
|
+
|
|
833
|
+
leverSwapLimitAmount = debtAmount
|
|
834
|
+
.abs()
|
|
835
|
+
.multipliedBy(1 + MAX_SLIPPAGE);
|
|
836
|
+
|
|
837
|
+
// leverSwapLimitAmount = debtInCollateralUnits; this is used when closing position
|
|
838
|
+
console.log("leverSwapLimitAmount", leverSwapLimitAmount);
|
|
839
|
+
//leverSwapLimitAmount = await ekuboQuoter.getSwapLimitAmount(debtToken, collateralToken, debtInCollateralUnits, MAX_SLIPPAGE);
|
|
840
|
+
const multiplyParams = await this.getLeverParams(
|
|
841
|
+
false,
|
|
842
|
+
params,
|
|
843
|
+
leverSwap,
|
|
844
|
+
leverSwapLimitAmount
|
|
845
|
+
);
|
|
846
|
+
const call = multiplyContract.populate("modify_lever", {
|
|
847
|
+
modify_lever_params: this.formatMultiplyParams(false, multiplyParams),
|
|
848
|
+
});
|
|
849
|
+
console.log("call", call.calldata);
|
|
850
|
+
return call.calldata as bigint[];
|
|
851
|
+
}
|
|
852
|
+
|
|
853
|
+
formatMultiplyParams(
|
|
854
|
+
isIncrease: boolean,
|
|
855
|
+
params: IncreaseLeverParams | DecreaseLeverParams
|
|
856
|
+
) {
|
|
857
|
+
if (isIncrease) {
|
|
858
|
+
const _params = params as IncreaseLeverParams;
|
|
859
|
+
return {
|
|
860
|
+
action: new CairoCustomEnum({
|
|
861
|
+
IncreaseLever: {
|
|
862
|
+
pool_id: _params.pool_id.toBigInt(),
|
|
863
|
+
collateral_asset: _params.collateral_asset.toBigInt(),
|
|
864
|
+
debt_asset: _params.debt_asset.toBigInt(),
|
|
865
|
+
user: _params.user.toBigInt(),
|
|
866
|
+
add_margin: BigInt(_params.add_margin.toWei()),
|
|
867
|
+
margin_swap: _params.margin_swap.map((swap) => ({
|
|
868
|
+
route: swap.route.map((route) => ({
|
|
869
|
+
pool_key: {
|
|
870
|
+
token0: route.pool_key.token0.toBigInt(),
|
|
871
|
+
token1: route.pool_key.token1.toBigInt(),
|
|
872
|
+
fee: route.pool_key.fee,
|
|
873
|
+
tick_spacing: route.pool_key.tick_spacing,
|
|
874
|
+
extension: BigInt(
|
|
875
|
+
num.hexToDecimalString(route.pool_key.extension)
|
|
876
|
+
),
|
|
877
|
+
},
|
|
878
|
+
sqrt_ratio_limit: uint256.bnToUint256(
|
|
879
|
+
route.sqrt_ratio_limit.toWei()
|
|
880
|
+
),
|
|
881
|
+
skip_ahead: BigInt(100),
|
|
882
|
+
})),
|
|
883
|
+
token_amount: {
|
|
884
|
+
token: swap.token_amount.token.toBigInt(),
|
|
885
|
+
amount: swap.token_amount.amount.toI129(),
|
|
886
|
+
},
|
|
887
|
+
})),
|
|
888
|
+
margin_swap_limit_amount: BigInt(
|
|
889
|
+
_params.margin_swap_limit_amount.toWei()
|
|
890
|
+
),
|
|
891
|
+
lever_swap: _params.lever_swap.map((swap) => ({
|
|
892
|
+
route: swap.route.map((route) => ({
|
|
893
|
+
pool_key: {
|
|
894
|
+
token0: route.pool_key.token0.toBigInt(),
|
|
895
|
+
token1: route.pool_key.token1.toBigInt(),
|
|
896
|
+
fee: route.pool_key.fee,
|
|
897
|
+
tick_spacing: route.pool_key.tick_spacing,
|
|
898
|
+
extension: ContractAddr.from(
|
|
899
|
+
route.pool_key.extension
|
|
900
|
+
).toBigInt(),
|
|
901
|
+
},
|
|
902
|
+
sqrt_ratio_limit: uint256.bnToUint256(
|
|
903
|
+
route.sqrt_ratio_limit.toWei()
|
|
904
|
+
),
|
|
905
|
+
skip_ahead: BigInt(route.skip_ahead.toWei()),
|
|
906
|
+
})),
|
|
907
|
+
token_amount: {
|
|
908
|
+
token: swap.token_amount.token.toBigInt(),
|
|
909
|
+
amount: swap.token_amount.amount.toI129(),
|
|
910
|
+
},
|
|
911
|
+
})),
|
|
912
|
+
lever_swap_limit_amount: BigInt(
|
|
913
|
+
_params.lever_swap_limit_amount.toWei()
|
|
914
|
+
),
|
|
915
|
+
},
|
|
916
|
+
}),
|
|
917
|
+
};
|
|
918
|
+
}
|
|
919
|
+
|
|
920
|
+
const _params = params as DecreaseLeverParams;
|
|
921
|
+
return {
|
|
922
|
+
action: new CairoCustomEnum({
|
|
923
|
+
DecreaseLever: {
|
|
924
|
+
pool_id: _params.pool_id.toBigInt(),
|
|
925
|
+
collateral_asset: _params.collateral_asset.toBigInt(),
|
|
926
|
+
debt_asset: _params.debt_asset.toBigInt(),
|
|
927
|
+
user: _params.user.toBigInt(),
|
|
928
|
+
sub_margin: BigInt(_params.sub_margin.toWei()),
|
|
929
|
+
recipient: _params.recipient.toBigInt(),
|
|
930
|
+
lever_swap: _params.lever_swap.map((swap) => ({
|
|
931
|
+
route: swap.route.map((route) => ({
|
|
932
|
+
pool_key: {
|
|
933
|
+
token0: route.pool_key.token0.toBigInt(),
|
|
934
|
+
token1: route.pool_key.token1.toBigInt(),
|
|
935
|
+
fee: route.pool_key.fee,
|
|
936
|
+
tick_spacing: route.pool_key.tick_spacing,
|
|
937
|
+
extension: ContractAddr.from(
|
|
938
|
+
route.pool_key.extension
|
|
939
|
+
).toBigInt(),
|
|
940
|
+
},
|
|
941
|
+
sqrt_ratio_limit: uint256.bnToUint256(
|
|
942
|
+
route.sqrt_ratio_limit.toWei()
|
|
943
|
+
),
|
|
944
|
+
skip_ahead: BigInt(route.skip_ahead.toWei()),
|
|
945
|
+
})),
|
|
946
|
+
token_amount: {
|
|
947
|
+
token: swap.token_amount.token.toBigInt(),
|
|
948
|
+
amount: swap.token_amount.amount.toI129(),
|
|
949
|
+
},
|
|
950
|
+
})),
|
|
951
|
+
lever_swap_limit_amount: BigInt(
|
|
952
|
+
_params.lever_swap_limit_amount.toWei()
|
|
953
|
+
),
|
|
954
|
+
lever_swap_weights: _params.lever_swap_weights.map((weight) =>
|
|
955
|
+
BigInt(weight.toWei())
|
|
956
|
+
),
|
|
957
|
+
withdraw_swap: _params.withdraw_swap.map((swap) => ({
|
|
958
|
+
route: swap.route.map((route) => ({
|
|
959
|
+
pool_key: {
|
|
960
|
+
token0: route.pool_key.token0.toBigInt(),
|
|
961
|
+
token1: route.pool_key.token1.toBigInt(),
|
|
962
|
+
fee: route.pool_key.fee,
|
|
963
|
+
tick_spacing: route.pool_key.tick_spacing,
|
|
964
|
+
extension: ContractAddr.from(
|
|
965
|
+
route.pool_key.extension
|
|
966
|
+
).toBigInt(),
|
|
967
|
+
},
|
|
968
|
+
sqrt_ratio_limit: uint256.bnToUint256(
|
|
969
|
+
route.sqrt_ratio_limit.toWei()
|
|
970
|
+
),
|
|
971
|
+
skip_ahead: BigInt(route.skip_ahead.toWei()),
|
|
972
|
+
})),
|
|
973
|
+
token_amount: {
|
|
974
|
+
token: swap.token_amount.token.toBigInt(),
|
|
975
|
+
amount: swap.token_amount.amount.toI129(),
|
|
976
|
+
},
|
|
977
|
+
})),
|
|
978
|
+
withdraw_swap_limit_amount: BigInt(
|
|
979
|
+
_params.withdraw_swap_limit_amount.toWei()
|
|
980
|
+
),
|
|
981
|
+
withdraw_swap_weights: _params.withdraw_swap_weights.map((weight) =>
|
|
982
|
+
BigInt(weight.toWei())
|
|
983
|
+
),
|
|
984
|
+
close_position: _params.close_position,
|
|
985
|
+
},
|
|
986
|
+
}),
|
|
987
|
+
};
|
|
988
|
+
}
|
|
989
|
+
|
|
990
|
+
private async getLeverParams(
|
|
991
|
+
isIncrease: boolean,
|
|
992
|
+
params: Web3Number,
|
|
993
|
+
leverSwap: Swap[],
|
|
994
|
+
leverSwapLimitAmount: Web3Number,
|
|
995
|
+
closePosition?: boolean
|
|
996
|
+
): Promise<IncreaseLeverParams | DecreaseLeverParams> {
|
|
997
|
+
logger.info(`isIncrease: ${isIncrease} params: ${JSON.stringify(params)} leverSwap: ${JSON.stringify(leverSwap)} leverSwapLimitAmount: ${leverSwapLimitAmount} closePosition: ${closePosition}`);
|
|
998
|
+
const multiplyParams: IncreaseLeverParams | DecreaseLeverParams = isIncrease
|
|
999
|
+
? {
|
|
1000
|
+
user: this.config.vaultAllocator,
|
|
1001
|
+
pool_id: this.config.poolId,
|
|
1002
|
+
collateral_asset: this.config.supplyToken.address,
|
|
1003
|
+
debt_asset: this.config.borrowToken.address,
|
|
1004
|
+
recipient: this.config.vaultAllocator,
|
|
1005
|
+
add_margin: params, // multiplied by collateral decimals in format
|
|
1006
|
+
margin_swap: [],
|
|
1007
|
+
margin_swap_limit_amount: Web3Number.fromWei(
|
|
1008
|
+
0,
|
|
1009
|
+
this.config.supplyToken.decimals
|
|
1010
|
+
),
|
|
1011
|
+
lever_swap: leverSwap,
|
|
1012
|
+
lever_swap_limit_amount: leverSwapLimitAmount,
|
|
1013
|
+
}
|
|
1014
|
+
: {
|
|
1015
|
+
user: this.config.vaultAllocator,
|
|
1016
|
+
pool_id: this.config.poolId,
|
|
1017
|
+
collateral_asset: this.config.supplyToken.address,
|
|
1018
|
+
debt_asset: this.config.borrowToken.address,
|
|
1019
|
+
recipient: this.config.vaultAllocator,
|
|
1020
|
+
sub_margin: params,
|
|
1021
|
+
lever_swap: leverSwap,
|
|
1022
|
+
lever_swap_limit_amount: leverSwapLimitAmount,
|
|
1023
|
+
lever_swap_weights: [],
|
|
1024
|
+
withdraw_swap: [],
|
|
1025
|
+
withdraw_swap_limit_amount: Web3Number.fromWei(
|
|
1026
|
+
0,
|
|
1027
|
+
this.config.supplyToken.decimals
|
|
1028
|
+
),
|
|
1029
|
+
withdraw_swap_weights: [],
|
|
1030
|
+
close_position: closePosition ?? false,
|
|
1031
|
+
};
|
|
1032
|
+
return multiplyParams;
|
|
1033
|
+
}
|
|
1034
|
+
|
|
1035
|
+
//params amount must be in usdc
|
|
1036
|
+
/**
|
|
1037
|
+
* The amount for debt payment or taken is already calculated and sent here, in
|
|
1038
|
+
* In case of debt payment, amount is the debtToBe Repaid
|
|
1039
|
+
* In case of debt taken, amount is the added collateral
|
|
1040
|
+
* @returns
|
|
1041
|
+
*/
|
|
1042
|
+
private async getDepositCalldata(
|
|
1043
|
+
debtAmount: Web3Number,
|
|
1044
|
+
supplyAmount: Web3Number,
|
|
1045
|
+
): Promise<bigint[]> {
|
|
1046
|
+
try {
|
|
1047
|
+
const supplyToken = this.config.supplyToken;
|
|
1048
|
+
const borrowToken = this.config.borrowToken;
|
|
1049
|
+
let supplyAmountInI257: { mag: Uint256; sign: 0 | 1 };
|
|
1050
|
+
let debtAmountInI257: { mag: Uint256; sign: 0 | 1 };
|
|
1051
|
+
const { addr: vesuSingleton } = getVesuSingletonAddress(
|
|
1052
|
+
this.config.poolId
|
|
1053
|
+
);
|
|
1054
|
+
const multiplyContract = new Contract({
|
|
1055
|
+
abi: VesuPoolV2Abi,
|
|
1056
|
+
address: vesuSingleton.address,
|
|
1057
|
+
providerOrAccount: this.config.networkConfig.provider,
|
|
1058
|
+
});
|
|
1059
|
+
|
|
1060
|
+
/**
|
|
1061
|
+
* The amount that is borrowed is slightly more than 60%, in order to trasnfer proper funds to extended and vesu
|
|
1062
|
+
*/
|
|
1063
|
+
supplyAmountInI257 = supplyAmount.toI257();
|
|
1064
|
+
debtAmountInI257 = debtAmount.toI257();
|
|
1065
|
+
logger.info(`debtAmountInI257: ${debtAmountInI257}`);
|
|
1066
|
+
|
|
1067
|
+
|
|
1068
|
+
const depositParams = multiplyContract.populate("modify_position", {
|
|
1069
|
+
params: {
|
|
1070
|
+
collateral_asset: supplyToken.address.toBigInt(),
|
|
1071
|
+
debt_asset: borrowToken.address.toBigInt(),
|
|
1072
|
+
user: this.config.vaultAllocator.toBigInt(),
|
|
1073
|
+
collateral: {
|
|
1074
|
+
denomination: new CairoCustomEnum({ Assets: {} }),
|
|
1075
|
+
value: {
|
|
1076
|
+
abs: supplyAmountInI257.mag,
|
|
1077
|
+
is_negative: supplyAmountInI257.sign === 1,
|
|
1078
|
+
},
|
|
1079
|
+
},
|
|
1080
|
+
debt: {
|
|
1081
|
+
denomination: new CairoCustomEnum({ Assets: {} }),
|
|
1082
|
+
value: {
|
|
1083
|
+
abs: debtAmountInI257.mag,
|
|
1084
|
+
is_negative: debtAmountInI257.sign === 1,
|
|
1085
|
+
},
|
|
1086
|
+
},
|
|
1087
|
+
},
|
|
1088
|
+
});
|
|
1089
|
+
console.log("depositParams.calldata", depositParams.calldata);
|
|
1090
|
+
return depositParams.calldata as bigint[];
|
|
1091
|
+
} catch (err) {
|
|
1092
|
+
console.log("error getting deposit calldata", err);
|
|
1093
|
+
return [];
|
|
1094
|
+
}
|
|
1095
|
+
}
|
|
1096
|
+
|
|
1097
|
+
private async getClosePositionCalldata(
|
|
1098
|
+
debtAmount: Web3Number,
|
|
1099
|
+
supplyAmount: Web3Number,
|
|
1100
|
+
): Promise<bigint[]> {
|
|
1101
|
+
try {
|
|
1102
|
+
const { isV2 } = getVesuSingletonAddress(this.config.poolId);
|
|
1103
|
+
const vesuMultiply = isV2
|
|
1104
|
+
? this.vesuAdapter.VESU_MULTIPLY
|
|
1105
|
+
: this.vesuAdapter.VESU_MULTIPLY_V1;
|
|
1106
|
+
const multiplyContract = new Contract({
|
|
1107
|
+
abi: VesuMultiplyAbi,
|
|
1108
|
+
address: vesuMultiply.address,
|
|
1109
|
+
providerOrAccount: this.config.networkConfig.provider,
|
|
1110
|
+
});
|
|
1111
|
+
let leverSwap: Swap[] = [];
|
|
1112
|
+
let leverSwapLimitAmount = Web3Number.fromWei(0, this.config.borrowToken.decimals);
|
|
1113
|
+
const collateralToken = this.config.supplyToken;
|
|
1114
|
+
const debtToken = this.config.borrowToken;
|
|
1115
|
+
const debtPrice = await this.config.pricer.getPrice(debtToken.symbol);
|
|
1116
|
+
const collateralPrice = await this.config.pricer.getPrice(collateralToken.symbol);
|
|
1117
|
+
// the debt amount is negative as we are reducing debt to withdraw
|
|
1118
|
+
//console.log("debtAmountToRepay", debtAmountToRepay);
|
|
1119
|
+
const ekuboQuoter = new EkuboQuoter(
|
|
1120
|
+
this.config.networkConfig,
|
|
1121
|
+
this.config.pricer
|
|
1122
|
+
);
|
|
1123
|
+
const debtInCollateralUnits = new Web3Number(debtAmount.dividedBy(collateralPrice.price).multipliedBy(debtPrice.price).toFixed(WBTC_TOKEN_DECIMALS), collateralToken.decimals);
|
|
1124
|
+
console.log("debtInCollateralUnits", debtInCollateralUnits, collateralPrice.price, debtPrice.price, WBTC_TOKEN_DECIMALS);
|
|
1125
|
+
const swapQuote = await ekuboQuoter.getQuote(
|
|
1126
|
+
collateralToken.address.address,
|
|
1127
|
+
debtToken.address.address,
|
|
1128
|
+
debtInCollateralUnits.multipliedBy(10 ** 8)
|
|
1129
|
+
);
|
|
1130
|
+
console.log("swapQuote", swapQuote);
|
|
1131
|
+
const MAX_SLIPPAGE = 0.002; // 0.2% slippag
|
|
1132
|
+
|
|
1133
|
+
// if (swapQuote.price_impact < 0.0025) {
|
|
1134
|
+
leverSwap = ekuboQuoter.getVesuMultiplyQuote(
|
|
1135
|
+
swapQuote,
|
|
1136
|
+
debtToken,
|
|
1137
|
+
collateralToken
|
|
1138
|
+
);
|
|
1139
|
+
leverSwapLimitAmount = debtInCollateralUnits.multipliedBy(1 + MAX_SLIPPAGE); //this is used when closing position
|
|
1140
|
+
console.log("leverSwapLimitAmount", leverSwapLimitAmount);
|
|
1141
|
+
//leverSwapLimitAmount = await ekuboQuoter.getSwapLimitAmount(debtToken, collateralToken, debtInCollateralUnits, MAX_SLIPPAGE);
|
|
1142
|
+
const multiplyParams = await this.getLeverParams(
|
|
1143
|
+
false,
|
|
1144
|
+
supplyAmount,
|
|
1145
|
+
leverSwap,
|
|
1146
|
+
leverSwapLimitAmount,
|
|
1147
|
+
true
|
|
1148
|
+
);
|
|
1149
|
+
const call = multiplyContract.populate("modify_lever", {
|
|
1150
|
+
modify_lever_params: this.formatMultiplyParams(false, multiplyParams),
|
|
1151
|
+
});
|
|
1152
|
+
console.log("call", call.calldata);
|
|
1153
|
+
return call.calldata as bigint[];
|
|
1154
|
+
} catch (err) {
|
|
1155
|
+
console.log("error getting close position calldata", err);
|
|
1156
|
+
return [];
|
|
1157
|
+
}
|
|
1158
|
+
}
|
|
1159
|
+
|
|
1160
|
+
getProofsForDebtPayment<T>(tree: StandardMerkleTree): {
|
|
1161
|
+
proofs: string[][];
|
|
1162
|
+
callConstructor:
|
|
1163
|
+
GenerateCallFn<DepositParamsForLendingBorrowing>
|
|
1164
|
+
} {
|
|
1165
|
+
let proofGroups: string[][] = [];
|
|
1166
|
+
|
|
1167
|
+
const ids = this.getPayDebtLeaf().leaves.map((l) => l.readableId);
|
|
1168
|
+
// console.log(`${this.name}::getProofs ids: ${ids}`);
|
|
1169
|
+
for (const [i, v] of tree.entries()) {
|
|
1170
|
+
// console.log(`${this.name}::getProofs v: ${v.readableId}`);
|
|
1171
|
+
if (ids.includes(v.readableId)) {
|
|
1172
|
+
//console.log(`${this.name}::getProofs found id: ${v.readableId}`);
|
|
1173
|
+
proofGroups.push(tree.getProof(i));
|
|
1174
|
+
}
|
|
1175
|
+
}
|
|
1176
|
+
if (proofGroups.length != ids.length) {
|
|
1177
|
+
throw new Error(`Not all proofs found for IDs: ${ids.join(", ")}`);
|
|
1178
|
+
}
|
|
1179
|
+
|
|
1180
|
+
// find leaf adapter
|
|
1181
|
+
return {
|
|
1182
|
+
proofs: proofGroups,
|
|
1183
|
+
callConstructor: this.getPayDebtCall.bind(this),
|
|
1184
|
+
};
|
|
1185
|
+
}
|
|
1186
|
+
|
|
1187
|
+
getProofsForBorrowing<T>(tree: StandardMerkleTree): {
|
|
1188
|
+
proofs: string[][];
|
|
1189
|
+
callConstructor:
|
|
1190
|
+
GenerateCallFn<DepositParamsForLendingBorrowing>;
|
|
1191
|
+
} {
|
|
1192
|
+
let proofGroups: string[][] = [];
|
|
1193
|
+
|
|
1194
|
+
const ids = this.getBorrowLeaf().leaves.map((l) => l.readableId);
|
|
1195
|
+
// console.log(`${this.name}::getProofs ids: ${ids}`);
|
|
1196
|
+
for (const [i, v] of tree.entries()) {
|
|
1197
|
+
// console.log(`${this.name}::getProofs v: ${v.readableId}`);
|
|
1198
|
+
if (ids.includes(v.readableId)) {
|
|
1199
|
+
console.log(`${this.name}::getProofs found id: ${v.readableId}`);
|
|
1200
|
+
proofGroups.push(tree.getProof(i));
|
|
1201
|
+
}
|
|
1202
|
+
}
|
|
1203
|
+
if (proofGroups.length != ids.length) {
|
|
1204
|
+
throw new Error(`Not all proofs found for IDs: ${ids.join(", ")}`);
|
|
1205
|
+
}
|
|
1206
|
+
|
|
1207
|
+
// find leaf adapter
|
|
1208
|
+
return {
|
|
1209
|
+
proofs: proofGroups,
|
|
1210
|
+
callConstructor: this.getBorrowCall.bind(this),
|
|
1211
|
+
};
|
|
1212
|
+
}
|
|
1213
|
+
|
|
1214
|
+
getProofsForMultiply(tree: StandardMerkleTree): {
|
|
1215
|
+
proofs: string[][];
|
|
1216
|
+
callConstructor:
|
|
1217
|
+
GenerateCallFn<({
|
|
1218
|
+
amount: Web3Number;
|
|
1219
|
+
debtAmount: Web3Number;
|
|
1220
|
+
isWithdraw: boolean;
|
|
1221
|
+
closePosition: boolean;
|
|
1222
|
+
})>;
|
|
1223
|
+
} {
|
|
1224
|
+
let proofGroups: string[][] = [];
|
|
1225
|
+
|
|
1226
|
+
const ids = this.getMultiplyLeaf().leaves.map((l) => l.readableId);
|
|
1227
|
+
logger.verbose(`${this.name}::getProofsForMultiply searching for IDs: ${ids.join(", ")}`);
|
|
1228
|
+
const treeIds: string[] = [];
|
|
1229
|
+
for (const [i, v] of tree.entries()) {
|
|
1230
|
+
// console.log(`${this.name}::getProofs v: ${v.readableId}`);
|
|
1231
|
+
if (ids.includes(v.readableId)) {
|
|
1232
|
+
logger.verbose(`${this.name}::getProofsForMultiply found id: ${v.readableId}`);
|
|
1233
|
+
proofGroups.push(tree.getProof(i));
|
|
1234
|
+
}
|
|
1235
|
+
}
|
|
1236
|
+
if (proofGroups.length != ids.length) {
|
|
1237
|
+
throw new Error(`Not all proofs found for IDs: ${ids.join(", ")}`);
|
|
1238
|
+
}
|
|
1239
|
+
|
|
1240
|
+
// find leaf adapter
|
|
1241
|
+
return {
|
|
1242
|
+
proofs: proofGroups,
|
|
1243
|
+
callConstructor: this.getMultiplyCall.bind(this),
|
|
1244
|
+
};
|
|
1245
|
+
}
|
|
1246
|
+
|
|
1247
|
+
}
|