@strkfarm/sdk 2.0.0-dev.3 → 2.0.0-dev.31
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/cli.js +190 -36
- package/dist/cli.mjs +188 -34
- package/dist/index.browser.global.js +78475 -45620
- package/dist/index.browser.mjs +19580 -9901
- package/dist/index.d.ts +3763 -1424
- package/dist/index.js +20977 -11063
- package/dist/index.mjs +20945 -11087
- package/package.json +1 -1
- package/src/data/avnu.abi.json +840 -0
- package/src/data/ekubo-price-fethcer.abi.json +265 -0
- package/src/dataTypes/_bignumber.ts +13 -4
- package/src/dataTypes/bignumber.browser.ts +6 -1
- package/src/dataTypes/bignumber.node.ts +5 -1
- package/src/dataTypes/index.ts +3 -2
- package/src/dataTypes/mynumber.ts +141 -0
- package/src/global.ts +76 -41
- package/src/index.browser.ts +2 -1
- package/src/interfaces/common.tsx +175 -3
- package/src/modules/ExtendedWrapperSDk/types.ts +28 -5
- package/src/modules/ExtendedWrapperSDk/wrapper.ts +275 -59
- package/src/modules/apollo-client-config.ts +28 -0
- package/src/modules/avnu.ts +4 -4
- package/src/modules/ekubo-pricer.ts +79 -0
- package/src/modules/ekubo-quoter.ts +48 -30
- package/src/modules/erc20.ts +17 -0
- package/src/modules/harvests.ts +43 -29
- package/src/modules/pragma.ts +23 -8
- package/src/modules/pricer-from-api.ts +156 -15
- package/src/modules/pricer-lst.ts +1 -1
- package/src/modules/pricer.ts +40 -4
- package/src/modules/pricerBase.ts +2 -1
- package/src/node/deployer.ts +36 -1
- package/src/node/pricer-redis.ts +2 -1
- package/src/strategies/base-strategy.ts +78 -10
- package/src/strategies/ekubo-cl-vault.tsx +906 -347
- package/src/strategies/factory.ts +159 -0
- package/src/strategies/index.ts +7 -1
- package/src/strategies/registry.ts +239 -0
- package/src/strategies/sensei.ts +335 -7
- package/src/strategies/svk-strategy.ts +97 -27
- package/src/strategies/types.ts +4 -0
- package/src/strategies/universal-adapters/adapter-utils.ts +2 -1
- package/src/strategies/universal-adapters/avnu-adapter.ts +180 -265
- package/src/strategies/universal-adapters/baseAdapter.ts +263 -251
- package/src/strategies/universal-adapters/common-adapter.ts +206 -203
- package/src/strategies/universal-adapters/extended-adapter.ts +490 -316
- package/src/strategies/universal-adapters/index.ts +11 -8
- package/src/strategies/universal-adapters/svk-troves-adapter.ts +364 -0
- package/src/strategies/universal-adapters/token-transfer-adapter.ts +200 -0
- package/src/strategies/universal-adapters/usdc<>usdce-adapter.ts +200 -0
- package/src/strategies/universal-adapters/vesu-adapter.ts +120 -82
- package/src/strategies/universal-adapters/vesu-modify-position-adapter.ts +476 -0
- package/src/strategies/universal-adapters/vesu-multiply-adapter.ts +1067 -704
- package/src/strategies/universal-adapters/vesu-position-common.ts +251 -0
- package/src/strategies/universal-adapters/vesu-supply-only-adapter.ts +18 -3
- package/src/strategies/universal-lst-muliplier-strategy.tsx +397 -204
- package/src/strategies/universal-strategy.tsx +1426 -1173
- package/src/strategies/vesu-extended-strategy/services/executionService.ts +2233 -0
- package/src/strategies/vesu-extended-strategy/services/extended-vesu-state-manager.ts +4087 -0
- package/src/strategies/vesu-extended-strategy/services/ltv-imbalance-rebalance-math.ts +783 -0
- package/src/strategies/vesu-extended-strategy/services/operationService.ts +38 -16
- package/src/strategies/vesu-extended-strategy/types/transaction-metadata.ts +88 -0
- package/src/strategies/vesu-extended-strategy/utils/config.runtime.ts +1 -0
- package/src/strategies/vesu-extended-strategy/utils/constants.ts +5 -6
- package/src/strategies/vesu-extended-strategy/utils/helper.ts +259 -103
- package/src/strategies/vesu-extended-strategy/vesu-extended-strategy.tsx +688 -817
- package/src/strategies/vesu-rebalance.tsx +255 -152
- package/src/utils/cacheClass.ts +11 -2
- package/src/utils/health-factor-math.ts +4 -1
- package/src/utils/index.ts +3 -1
- package/src/utils/logger.browser.ts +22 -4
- package/src/utils/logger.node.ts +259 -24
- package/src/utils/starknet-call-parser.ts +1036 -0
- package/src/utils/strategy-utils.ts +61 -0
- package/src/strategies/universal-adapters/unused-balance-adapter.ts +0 -109
|
@@ -0,0 +1,200 @@
|
|
|
1
|
+
import {
|
|
2
|
+
BaseAdapter,
|
|
3
|
+
DepositParams,
|
|
4
|
+
WithdrawParams,
|
|
5
|
+
BaseAdapterConfig,
|
|
6
|
+
} from "./baseAdapter";
|
|
7
|
+
import { toBigInt } from "./adapter-utils";
|
|
8
|
+
import { Protocols } from "@/interfaces";
|
|
9
|
+
import { SupportedPosition } from "./baseAdapter";
|
|
10
|
+
import { PositionAPY, APYType, PositionAmount } from "./baseAdapter";
|
|
11
|
+
import { Web3Number } from "@/dataTypes";
|
|
12
|
+
import { PositionInfo } from "./baseAdapter";
|
|
13
|
+
import { ManageCall } from "./baseAdapter";
|
|
14
|
+
import { ContractAddr } from "@/dataTypes";
|
|
15
|
+
import { AVNU_EXCHANGE } from "./adapter-utils";
|
|
16
|
+
import { hash, uint256 } from "starknet";
|
|
17
|
+
import { AVNU_EXCHANGE_FOR_LEGACY_USDC } from "./adapter-utils";
|
|
18
|
+
import { AVNU_LEGACY_SANITIZER } from "./adapter-utils";
|
|
19
|
+
import { assert, logger } from "@/utils";
|
|
20
|
+
import { ERC20 } from "@/modules";
|
|
21
|
+
|
|
22
|
+
export class UsdcToUsdceAdapter extends BaseAdapter<
|
|
23
|
+
DepositParams,
|
|
24
|
+
WithdrawParams
|
|
25
|
+
> {
|
|
26
|
+
readonly config: BaseAdapterConfig;
|
|
27
|
+
|
|
28
|
+
private _approveProofReadableId(usdcToUsdce: boolean): string {
|
|
29
|
+
const method = usdcToUsdce ? "swap_to_legacy" : "swap_to_new";
|
|
30
|
+
return `approve_${method}`;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
private _swapProofReadableId(usdcToUsdce: boolean): string {
|
|
34
|
+
const method = usdcToUsdce ? "swap_to_legacy" : "swap_to_new";
|
|
35
|
+
const target = usdcToUsdce
|
|
36
|
+
? this.config.supportedPositions[0].asset
|
|
37
|
+
: this.config.supportedPositions[1].asset;
|
|
38
|
+
return `${method}_${target.symbol}`;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
private buildSwapLeafConfigs(usdcToUsdce: boolean): {
|
|
42
|
+
target: ContractAddr;
|
|
43
|
+
method: string;
|
|
44
|
+
packedArguments: bigint[];
|
|
45
|
+
sanitizer: ContractAddr;
|
|
46
|
+
id: string;
|
|
47
|
+
}[] {
|
|
48
|
+
const method = usdcToUsdce ? "swap_to_legacy" : "swap_to_new";
|
|
49
|
+
const target = usdcToUsdce
|
|
50
|
+
? this.config.supportedPositions[0].asset
|
|
51
|
+
: this.config.supportedPositions[1].asset;
|
|
52
|
+
return [
|
|
53
|
+
{
|
|
54
|
+
target: target.address,
|
|
55
|
+
method: "approve",
|
|
56
|
+
packedArguments: [AVNU_EXCHANGE_FOR_LEGACY_USDC.toBigInt()],
|
|
57
|
+
id: this._approveProofReadableId(usdcToUsdce),
|
|
58
|
+
sanitizer: AVNU_LEGACY_SANITIZER,
|
|
59
|
+
},
|
|
60
|
+
{
|
|
61
|
+
target: AVNU_EXCHANGE_FOR_LEGACY_USDC,
|
|
62
|
+
method: method,
|
|
63
|
+
packedArguments: [],
|
|
64
|
+
id: this._swapProofReadableId(usdcToUsdce),
|
|
65
|
+
sanitizer: AVNU_LEGACY_SANITIZER,
|
|
66
|
+
},
|
|
67
|
+
];
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
private async buildSwapCalls(
|
|
71
|
+
params: DepositParams | WithdrawParams,
|
|
72
|
+
usdcToUsdce: boolean,
|
|
73
|
+
): Promise<ManageCall[]> {
|
|
74
|
+
const approveAmount = uint256.bnToUint256(params.amount.toWei());
|
|
75
|
+
const target = usdcToUsdce
|
|
76
|
+
? this.config.supportedPositions[0].asset
|
|
77
|
+
: this.config.supportedPositions[1].asset;
|
|
78
|
+
const method = usdcToUsdce ? "swap_to_legacy" : "swap_to_new";
|
|
79
|
+
return [
|
|
80
|
+
{
|
|
81
|
+
proofReadableId: this._approveProofReadableId(usdcToUsdce),
|
|
82
|
+
sanitizer: AVNU_LEGACY_SANITIZER,
|
|
83
|
+
call: {
|
|
84
|
+
contractAddress: target.address,
|
|
85
|
+
selector: hash.getSelectorFromName("approve"),
|
|
86
|
+
calldata: [
|
|
87
|
+
AVNU_EXCHANGE_FOR_LEGACY_USDC.toBigInt(),
|
|
88
|
+
toBigInt(approveAmount.low.toString()),
|
|
89
|
+
toBigInt(approveAmount.high.toString()),
|
|
90
|
+
],
|
|
91
|
+
},
|
|
92
|
+
},
|
|
93
|
+
{
|
|
94
|
+
proofReadableId: this._swapProofReadableId(usdcToUsdce),
|
|
95
|
+
sanitizer: AVNU_LEGACY_SANITIZER,
|
|
96
|
+
call: {
|
|
97
|
+
contractAddress: AVNU_EXCHANGE_FOR_LEGACY_USDC,
|
|
98
|
+
selector: hash.getSelectorFromName(method),
|
|
99
|
+
calldata: [
|
|
100
|
+
toBigInt(approveAmount.low.toString()), // amount low
|
|
101
|
+
toBigInt(approveAmount.high.toString()), // amount high
|
|
102
|
+
],
|
|
103
|
+
},
|
|
104
|
+
},
|
|
105
|
+
];
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
constructor(config: BaseAdapterConfig) {
|
|
109
|
+
super(config, UsdcToUsdceAdapter.name, Protocols.AVNU);
|
|
110
|
+
this.config = config as BaseAdapterConfig;
|
|
111
|
+
assert(this.config.supportedPositions.length === 2, "UsdcToUsdceAdapter must have 2 supported positions");
|
|
112
|
+
assert(this.config.supportedPositions[0].asset.symbol === "USDC", "UsdcToUsdceAdapter must have USDC as the first supported position");
|
|
113
|
+
assert(this.config.supportedPositions[1].asset.symbol === "USDC.e", "UsdcToUsdceAdapter must have USDCE as the second supported position");
|
|
114
|
+
}
|
|
115
|
+
//abstract means the method has no implementation in this class; instead, child classes must implement it.
|
|
116
|
+
protected async getAPY(
|
|
117
|
+
supportedPosition: SupportedPosition,
|
|
118
|
+
): Promise<PositionAPY> {
|
|
119
|
+
return Promise.resolve({ apy: 0, type: APYType.BASE });
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
protected async getPosition(
|
|
123
|
+
supportedPosition: SupportedPosition,
|
|
124
|
+
): Promise<PositionAmount | null> {
|
|
125
|
+
const toToken = this.config.supportedPositions[1].asset;
|
|
126
|
+
if (supportedPosition.asset.symbol != toToken.symbol) {
|
|
127
|
+
return null;
|
|
128
|
+
}
|
|
129
|
+
try {
|
|
130
|
+
// only measure balance of toToken, bcz from token usually gets trakced in unused balance or a previous avnu adapter
|
|
131
|
+
const balance = await new ERC20(this.config.networkConfig).balanceOf(
|
|
132
|
+
toToken.address,
|
|
133
|
+
this.config.vaultAllocator.address,
|
|
134
|
+
toToken.decimals,
|
|
135
|
+
);
|
|
136
|
+
return { amount: balance, remarks: `USDC.e unused balance (VA)` };
|
|
137
|
+
} catch (_e) {
|
|
138
|
+
logger.error(`${UsdcToUsdceAdapter.name}::getPosition: failed for ${toToken.symbol}`);
|
|
139
|
+
throw new Error(`${UsdcToUsdceAdapter.name}: failed to get balance for ${toToken.symbol}`);
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
async maxDeposit(amount?: Web3Number): Promise<PositionInfo> {
|
|
144
|
+
return Promise.resolve({
|
|
145
|
+
tokenInfo: this.config.baseToken,
|
|
146
|
+
amount: new Web3Number(0, 0),
|
|
147
|
+
usdValue: 0,
|
|
148
|
+
apy: { apy: 0, type: APYType.BASE },
|
|
149
|
+
protocol: Protocols.AVNU,
|
|
150
|
+
remarks: "",
|
|
151
|
+
});
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
async maxWithdraw(): Promise<PositionInfo> {
|
|
155
|
+
return Promise.resolve({
|
|
156
|
+
tokenInfo: this.config.baseToken,
|
|
157
|
+
amount: new Web3Number(0, 0),
|
|
158
|
+
usdValue: 0,
|
|
159
|
+
apy: { apy: 0, type: APYType.BASE },
|
|
160
|
+
protocol: Protocols.AVNU,
|
|
161
|
+
remarks: "",
|
|
162
|
+
});
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
protected _getDepositLeaf(): {
|
|
166
|
+
// considering deposit is converting usdc to usdce
|
|
167
|
+
target: ContractAddr;
|
|
168
|
+
method: string;
|
|
169
|
+
packedArguments: bigint[];
|
|
170
|
+
sanitizer: ContractAddr;
|
|
171
|
+
id: string;
|
|
172
|
+
}[] {
|
|
173
|
+
return this.buildSwapLeafConfigs(true);
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
protected _getWithdrawLeaf(): {
|
|
177
|
+
target: ContractAddr;
|
|
178
|
+
method: string;
|
|
179
|
+
packedArguments: bigint[];
|
|
180
|
+
sanitizer: ContractAddr;
|
|
181
|
+
id: string;
|
|
182
|
+
}[] {
|
|
183
|
+
return this.buildSwapLeafConfigs(false);
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
async getDepositCall(params: DepositParams): Promise<ManageCall[]> {
|
|
187
|
+
const calls = await this.buildSwapCalls(params, true);
|
|
188
|
+
return calls;
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
//Swap wbtc to usdc
|
|
192
|
+
async getWithdrawCall(params: WithdrawParams): Promise<ManageCall[]> {
|
|
193
|
+
const calls = await this.buildSwapCalls(params, false);
|
|
194
|
+
return calls;
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
async getHealthFactor(): Promise<number> {
|
|
198
|
+
return Promise.resolve(1);
|
|
199
|
+
}
|
|
200
|
+
}
|
|
@@ -16,6 +16,7 @@ import { EkuboPoolKey } from "../ekubo-cl-vault";
|
|
|
16
16
|
import VesuPoolV2Abi from '@/data/vesu-pool-v2.abi.json';
|
|
17
17
|
import VesuExtensionAbi from '@/data/vesu-extension.abi.json';
|
|
18
18
|
import { CacheClass } from "@/utils/cacheClass";
|
|
19
|
+
import { PricerFromApi } from "@/modules";
|
|
19
20
|
|
|
20
21
|
interface VesuPoolsInfo { pools: any[]; isErrorPoolsAPI: boolean };
|
|
21
22
|
|
|
@@ -178,7 +179,7 @@ function getVesuMultiplyParams(isIncrease: boolean, params: IncreaseLeverParams
|
|
|
178
179
|
}
|
|
179
180
|
}
|
|
180
181
|
|
|
181
|
-
const _params = params as DecreaseLeverParams;
|
|
182
|
+
const _params = params as DecreaseLeverParams;
|
|
182
183
|
return {
|
|
183
184
|
action: new CairoCustomEnum({ DecreaseLever: {
|
|
184
185
|
pool_id: _params.pool_id.toBigInt(),
|
|
@@ -235,6 +236,29 @@ export const VesuPools = {
|
|
|
235
236
|
Re7xSTRK: ContractAddr.from('0x052fb52363939c3aa848f8f4ac28f0a51379f8d1b971d8444de25fbd77d8f161'),
|
|
236
237
|
Re7xBTC: ContractAddr.from('0x3a8416bf20d036df5b1cf3447630a2e1cb04685f6b0c3a70ed7fb1473548ecf'),
|
|
237
238
|
Re7USDCPrime: ContractAddr.from('0x02eef0c13b10b487ea5916b54c0a7f98ec43fb3048f60fdeedaf5b08f6f88aaf'),
|
|
239
|
+
Prime: ContractAddr.from('0x451fe483d5921a2919ddd81d0de6696669bccdacd859f72a4fba7656b97c3b5'),
|
|
240
|
+
Re7STRK: ContractAddr.from('0x01fcdacc1d8184eca7b472b5acbaf1500cec9d5683ca95fede8128b46c8f9cc2'),
|
|
241
|
+
}
|
|
242
|
+
|
|
243
|
+
export const VesuPoolMetadata = {
|
|
244
|
+
[VesuPools.Genesis.address]: {
|
|
245
|
+
name: 'Genesis',
|
|
246
|
+
},
|
|
247
|
+
[VesuPools.Re7xSTRK.address]: {
|
|
248
|
+
name: 'Re7 xSTRK',
|
|
249
|
+
},
|
|
250
|
+
[VesuPools.Re7xBTC.address]: {
|
|
251
|
+
name: 'Re7 xBTC',
|
|
252
|
+
},
|
|
253
|
+
[VesuPools.Prime.address]: {
|
|
254
|
+
name: 'Prime',
|
|
255
|
+
},
|
|
256
|
+
[VesuPools.Re7STRK.address]: {
|
|
257
|
+
name: 'Re7 STRK',
|
|
258
|
+
},
|
|
259
|
+
[VesuPools.Re7USDCPrime.address]: {
|
|
260
|
+
name: 'Re7 USDC Prime',
|
|
261
|
+
},
|
|
238
262
|
}
|
|
239
263
|
|
|
240
264
|
export const extensionMap: {[key: string]: ContractAddr} = {};
|
|
@@ -251,6 +275,7 @@ export function getVesuSingletonAddress(vesuPool: ContractAddr) {
|
|
|
251
275
|
export class VesuAdapter extends CacheClass {
|
|
252
276
|
VESU_MULTIPLY_V1 = ContractAddr.from('0x3630f1f8e5b8f5c4c4ae9b6620f8a570ae55cddebc0276c37550e7c118edf67');
|
|
253
277
|
VESU_MULTIPLY = ContractAddr.from('0x027fef272d0a9a3844767c851a64b36fe4f0115141d81134baade95d2b27b781');
|
|
278
|
+
VESU_WITHDRAW_SWAP_FIXED_MULTIPLIER = ContractAddr.from('0xd2b0006de39992e78d457b7607a606c00bd6b601e9d9a77a8e1870c5e19e73');
|
|
254
279
|
config: VesuAdapterConfig;
|
|
255
280
|
networkConfig: IConfig | undefined;
|
|
256
281
|
pricer: PricerBase | undefined;
|
|
@@ -286,31 +311,31 @@ export class VesuAdapter extends CacheClass {
|
|
|
286
311
|
// return { leaf: output, callConstructor: this.getModifyPositionCall.bind(this) };
|
|
287
312
|
// }
|
|
288
313
|
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
+
static getDefaultModifyPositionCallParams(params: {
|
|
315
|
+
collateralAmount: Web3Number,
|
|
316
|
+
isAddCollateral: boolean,
|
|
317
|
+
debtAmount: Web3Number,
|
|
318
|
+
isBorrow: boolean
|
|
319
|
+
}) {
|
|
320
|
+
return {
|
|
321
|
+
collateralAmount: {
|
|
322
|
+
amount_type: VesuAmountType.Delta,
|
|
323
|
+
denomination: VesuAmountDenomination.Assets,
|
|
324
|
+
value: {
|
|
325
|
+
abs: params.collateralAmount,
|
|
326
|
+
is_negative: !params.isAddCollateral
|
|
327
|
+
}
|
|
328
|
+
},
|
|
329
|
+
debtAmount: {
|
|
330
|
+
amount_type: VesuAmountType.Delta,
|
|
331
|
+
denomination: VesuAmountDenomination.Assets,
|
|
332
|
+
value: {
|
|
333
|
+
abs: params.debtAmount,
|
|
334
|
+
is_negative: !params.isBorrow
|
|
335
|
+
}
|
|
336
|
+
}
|
|
337
|
+
}
|
|
338
|
+
}
|
|
314
339
|
|
|
315
340
|
// getModifyPositionCall = (params: VesuModifyPositionCallParams): ManageCall => {
|
|
316
341
|
// // pub pool_id: felt252,
|
|
@@ -439,29 +464,31 @@ export class VesuAdapter extends CacheClass {
|
|
|
439
464
|
// }
|
|
440
465
|
// }
|
|
441
466
|
|
|
442
|
-
getVesuModifyDelegationCall = (
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
467
|
+
getVesuModifyDelegationCall = (delegatee: ContractAddr) => {
|
|
468
|
+
return (params: VesuModifyDelegationCallParams) => {
|
|
469
|
+
const VESU_SINGLETON = getVesuSingletonAddress(this.config.poolId).addr;
|
|
470
|
+
const { contract, isV2 } = this.getVesuSingletonContract(getMainnetConfig(), this.config.poolId);
|
|
471
|
+
const call = contract.populate('modify_delegation', isV2 ? {
|
|
472
|
+
delegatee: delegatee.toBigInt(),
|
|
473
|
+
delegation: params.delegation,
|
|
474
|
+
} : {
|
|
475
|
+
pool_id: this.config.poolId.toBigInt(),
|
|
476
|
+
delegatee: delegatee.toBigInt(),
|
|
477
|
+
delegation: params.delegation,
|
|
478
|
+
});
|
|
479
|
+
return {
|
|
480
|
+
sanitizer: isV2 ? SIMPLE_SANITIZER_V2 : SIMPLE_SANITIZER_VESU_V1_DELEGATIONS,
|
|
481
|
+
call: {
|
|
482
|
+
contractAddress: VESU_SINGLETON,
|
|
483
|
+
selector: hash.getSelectorFromName('modify_delegation'),
|
|
484
|
+
calldata: [
|
|
485
|
+
...call.calldata as bigint[]
|
|
486
|
+
]
|
|
487
|
+
}
|
|
461
488
|
}
|
|
462
489
|
}
|
|
463
490
|
}
|
|
464
|
-
|
|
491
|
+
|
|
465
492
|
// getDefispringRewardsAdapter = (id: string): () => AdapterLeafType<VesuDefiSpringRewardsCallParams> => {
|
|
466
493
|
// return () => {
|
|
467
494
|
// const packedArguments: bigint[] = [];
|
|
@@ -538,7 +565,7 @@ export class VesuAdapter extends CacheClass {
|
|
|
538
565
|
}
|
|
539
566
|
const output: any = await contract.call('pair_config', [this.config.collateral.address.address, this.config.debt.address.address]);
|
|
540
567
|
logger.verbose(`${this.config.debt.symbol}::VesuAdapter::getDebtCap debt_cap: ${output.debt_cap.toString()}`);
|
|
541
|
-
|
|
568
|
+
|
|
542
569
|
if (!isV2) {
|
|
543
570
|
throw new Error('getDebtCap is not supported for v1');
|
|
544
571
|
}
|
|
@@ -568,7 +595,7 @@ export class VesuAdapter extends CacheClass {
|
|
|
568
595
|
|
|
569
596
|
}
|
|
570
597
|
const _interestRateConfig: any = await interestRateConfigContract.call(
|
|
571
|
-
'interest_rate_config',
|
|
598
|
+
'interest_rate_config',
|
|
572
599
|
isV2 ? [this.config.debt.address.address] : [this.config.poolId.address, this.config.debt.address.address]
|
|
573
600
|
);
|
|
574
601
|
const interestRateConfig: InterestRateConfig = {
|
|
@@ -581,24 +608,25 @@ export class VesuAdapter extends CacheClass {
|
|
|
581
608
|
min_full_utilization_rate: _interestRateConfig.min_full_utilization_rate,
|
|
582
609
|
max_full_utilization_rate: _interestRateConfig.max_full_utilization_rate,
|
|
583
610
|
};
|
|
584
|
-
|
|
611
|
+
|
|
585
612
|
const _assetConfig: any = await contract.call(
|
|
586
|
-
isV2 ? 'asset_config' : 'asset_config_unsafe',
|
|
613
|
+
isV2 ? 'asset_config' : 'asset_config_unsafe',
|
|
587
614
|
isV2 ? [asset.address.address] : [this.config.poolId.address, asset.address.address]
|
|
588
615
|
);
|
|
589
616
|
const assetConfig = isV2 ? _assetConfig : _assetConfig['0'];
|
|
590
617
|
const timeDelta = assetConfig.last_updated;
|
|
591
618
|
const lastFullUtilizationRate = assetConfig.last_full_utilization_rate;
|
|
592
|
-
const
|
|
619
|
+
const debtSharePrice = Web3Number.fromWei(assetConfig.last_rate_accumulator, 18);
|
|
620
|
+
const currentDebt = (new Web3Number((Number(assetConfig.total_nominal_debt) / 1e18).toFixed(9), asset.decimals)).multipliedBy(debtSharePrice);
|
|
593
621
|
const totalSupply = currentDebt.plus(Web3Number.fromWei(assetConfig.reserve, asset.decimals));
|
|
594
622
|
|
|
595
623
|
const ratePerSecond = BigInt(Math.round(maxBorrowAPY / 365 / 24 / 60 / 60 * Number(SCALE)));
|
|
596
624
|
const maxUtilisation = this.getMaxUtilizationGivenRatePerSecond(interestRateConfig, ratePerSecond, timeDelta, lastFullUtilizationRate);
|
|
597
625
|
logger.verbose(`${asset.symbol}::VesuAdapter::getMaxBorrowableByInterestRate maxUtilisation: ${Number(maxUtilisation) / 1e18}, totalSupply: ${totalSupply.toString()}`);
|
|
598
|
-
|
|
626
|
+
|
|
599
627
|
const maxDebtToHave = totalSupply.multipliedBy(Number(maxUtilisation) / 1e18);
|
|
600
628
|
logger.verbose(`${asset.symbol}::VesuAdapter::getMaxBorrowableByInterestRate currentDebt: ${currentDebt.toString()}, maxDebtToHave: ${maxDebtToHave.toString()}`);
|
|
601
|
-
return maxDebtToHave.minus(currentDebt);
|
|
629
|
+
return {maxDebtToHave: maxDebtToHave.minus(currentDebt), currentDebt: currentDebt, totalSupply: totalSupply};
|
|
602
630
|
}
|
|
603
631
|
|
|
604
632
|
async getLTVConfig(config: IConfig, blockNumber: BlockIdentifier = 'latest') {
|
|
@@ -620,7 +648,7 @@ export class VesuAdapter extends CacheClass {
|
|
|
620
648
|
throw new Error('LTV is 0');
|
|
621
649
|
}
|
|
622
650
|
this.setCache(CACHE_KEY, ltv, 300000); // ttl: 5min
|
|
623
|
-
return
|
|
651
|
+
return ltv;
|
|
624
652
|
}
|
|
625
653
|
|
|
626
654
|
async getPositions(config: IConfig, blockNumber: BlockIdentifier = 'latest'): Promise<VaultPosition[]> {
|
|
@@ -628,40 +656,39 @@ export class VesuAdapter extends CacheClass {
|
|
|
628
656
|
throw new Error('Pricer is not initialized');
|
|
629
657
|
}
|
|
630
658
|
// { '0': { collateral_shares: 0n, nominal_debt: 0n }, '1': 0n, '2': 0n }
|
|
631
|
-
const CACHE_KEY = `positions_${blockNumber}_${this.config.poolId.shortString()}_${this.config.collateral.symbol}_${this.config.debt.symbol}`;
|
|
632
|
-
const cacheData = this.getCache<VaultPosition[]>(CACHE_KEY);
|
|
633
|
-
if (cacheData) {
|
|
634
|
-
|
|
635
|
-
}
|
|
659
|
+
// const CACHE_KEY = `positions_${blockNumber}_${this.config.poolId.shortString()}_${this.config.collateral.symbol}_${this.config.debt.symbol}`;
|
|
660
|
+
// const cacheData = this.getCache<VaultPosition[]>(CACHE_KEY);
|
|
661
|
+
// if (cacheData) {
|
|
662
|
+
// return cacheData;
|
|
663
|
+
// }
|
|
636
664
|
|
|
637
665
|
const { contract, isV2} = this.getVesuSingletonContract(config, this.config.poolId);
|
|
638
666
|
const output: any = await contract
|
|
639
|
-
.call(isV2 ? 'position' : 'position_unsafe', [...(isV2 ?
|
|
667
|
+
.call(isV2 ? 'position' : 'position_unsafe', [...(isV2 ?
|
|
640
668
|
[]: [this.config.poolId.address]), // exclude pool id in v2
|
|
641
669
|
this.config.collateral.address.address,
|
|
642
670
|
this.config.debt.address.address,
|
|
643
671
|
this.config.vaultAllocator.address
|
|
644
672
|
], { blockIdentifier: blockNumber });
|
|
645
673
|
|
|
646
|
-
console.log(output)
|
|
647
674
|
const token1Price = await this.pricer.getPrice(this.config.collateral.symbol);
|
|
648
675
|
const token2Price = await this.pricer.getPrice(this.config.debt.symbol);
|
|
649
676
|
logger.verbose(`VesuAdapter::getPositions token1Price: ${token1Price.price}, token2Price: ${token2Price.price}`);
|
|
650
|
-
|
|
677
|
+
|
|
651
678
|
const collateralAmount = Web3Number.fromWei(output['1'].toString(), this.config.collateral.decimals);
|
|
652
679
|
const debtAmount = Web3Number.fromWei(output['2'].toString(), this.config.debt.decimals);
|
|
653
680
|
const value = [{
|
|
654
681
|
amount: collateralAmount,
|
|
655
682
|
token: this.config.collateral,
|
|
656
683
|
usdValue: collateralAmount.multipliedBy(token1Price.price).toNumber(),
|
|
657
|
-
remarks:
|
|
684
|
+
remarks: `Collateral - ${VesuPoolMetadata[this.config.poolId.address].name} pool`
|
|
658
685
|
}, {
|
|
659
686
|
amount: debtAmount,
|
|
660
687
|
token: this.config.debt,
|
|
661
688
|
usdValue: debtAmount.multipliedBy(token2Price.price).toNumber(),
|
|
662
|
-
remarks:
|
|
689
|
+
remarks: `Debt - ${VesuPoolMetadata[this.config.poolId.address].name} pool`
|
|
663
690
|
}];
|
|
664
|
-
this.setCache(CACHE_KEY, value, 60000); // ttl: 1min
|
|
691
|
+
// this.setCache(CACHE_KEY, value, 60000); // ttl: 1min
|
|
665
692
|
return value.map(v => ({ ...v, protocol: Protocols.VESU }));
|
|
666
693
|
}
|
|
667
694
|
|
|
@@ -678,7 +705,7 @@ export class VesuAdapter extends CacheClass {
|
|
|
678
705
|
const { contract, isV2 } = this.getVesuSingletonContract(config, this.config.poolId);
|
|
679
706
|
const output: any = await contract
|
|
680
707
|
.call(isV2 ? 'check_collateralization' : 'check_collateralization_unsafe', [
|
|
681
|
-
...(isV2 ?
|
|
708
|
+
...(isV2 ?
|
|
682
709
|
[]: [this.config.poolId.address]), // exclude pool id in v2
|
|
683
710
|
this.config.collateral.address.address,
|
|
684
711
|
this.config.debt.address.address,
|
|
@@ -711,12 +738,23 @@ export class VesuAdapter extends CacheClass {
|
|
|
711
738
|
|
|
712
739
|
const collateralTokenAmount = positions[0].amount;
|
|
713
740
|
const collateralUSDAmount = collateralization[0].usdValue;
|
|
714
|
-
|
|
741
|
+
let collateralPrice = collateralUSDAmount / collateralTokenAmount.toNumber();
|
|
715
742
|
|
|
716
743
|
const debtTokenAmount = positions[1].amount;
|
|
717
744
|
const debtUSDAmount = collateralization[1].usdValue;
|
|
718
|
-
|
|
719
|
-
|
|
745
|
+
let debtPrice = debtUSDAmount / debtTokenAmount.toNumber();
|
|
746
|
+
if (isNaN(collateralPrice)) {
|
|
747
|
+
const pricer = new PricerFromApi(this.networkConfig!, Global.getDefaultTokens())
|
|
748
|
+
collateralPrice = (await pricer.getPrice(this.config.collateral.priceProxySymbol || this.config.collateral.symbol)).price;
|
|
749
|
+
}
|
|
750
|
+
if (isNaN(debtPrice)) {
|
|
751
|
+
const pricer = new PricerFromApi(this.networkConfig!, Global.getDefaultTokens())
|
|
752
|
+
debtPrice = (await pricer.getPrice(this.config.debt.priceProxySymbol || this.config.debt.symbol)).price;
|
|
753
|
+
}
|
|
754
|
+
logger.verbose(`VesuAdapter::getAssetPrices collateralPrice: ${collateralPrice}, debtPrice: ${debtPrice}`);
|
|
755
|
+
if (isNaN(collateralPrice) || isNaN(debtPrice) || collateralPrice == 0 || debtPrice == 0) {
|
|
756
|
+
throw new Error(`VesuAdapter::getAssetPrices collateralPrice: ${collateralPrice}, debtPrice: ${debtPrice}`);
|
|
757
|
+
}
|
|
720
758
|
return {
|
|
721
759
|
collateralTokenAmount,
|
|
722
760
|
collateralUSDAmount,
|
|
@@ -747,7 +785,7 @@ export class VesuAdapter extends CacheClass {
|
|
|
747
785
|
let pools: any[] = [];
|
|
748
786
|
try {
|
|
749
787
|
const data = await getAPIUsingHeadlessBrowser(
|
|
750
|
-
`${ENDPOINTS.
|
|
788
|
+
`${ENDPOINTS.VESU_BASE}/pools`
|
|
751
789
|
);
|
|
752
790
|
pools = data.data;
|
|
753
791
|
|
|
@@ -792,11 +830,11 @@ export class VesuAdapter extends CacheClass {
|
|
|
792
830
|
min_full_utilization_rate,
|
|
793
831
|
max_full_utilization_rate,
|
|
794
832
|
} = interestRateConfig;
|
|
795
|
-
|
|
833
|
+
|
|
796
834
|
const halfLifeScaled = rate_half_life * SCALE;
|
|
797
|
-
|
|
835
|
+
|
|
798
836
|
let nextFullUtilizationRate: bigint;
|
|
799
|
-
|
|
837
|
+
|
|
800
838
|
if (utilization < min_target_utilization) {
|
|
801
839
|
const utilizationDelta =
|
|
802
840
|
((min_target_utilization - utilization) * SCALE) / min_target_utilization;
|
|
@@ -811,7 +849,7 @@ export class VesuAdapter extends CacheClass {
|
|
|
811
849
|
} else {
|
|
812
850
|
nextFullUtilizationRate = fullUtilizationRate;
|
|
813
851
|
}
|
|
814
|
-
|
|
852
|
+
|
|
815
853
|
if (nextFullUtilizationRate > max_full_utilization_rate) {
|
|
816
854
|
return max_full_utilization_rate;
|
|
817
855
|
} else if (nextFullUtilizationRate < min_full_utilization_rate) {
|
|
@@ -831,26 +869,26 @@ export class VesuAdapter extends CacheClass {
|
|
|
831
869
|
lastFullUtilizationRate: bigint
|
|
832
870
|
): { newRatePerSecond: bigint; nextFullUtilizationRate: bigint } {
|
|
833
871
|
const scaledUtilization = utilization / UTILIZATION_SCALE_TO_SCALE;
|
|
834
|
-
|
|
872
|
+
|
|
835
873
|
const {
|
|
836
874
|
target_utilization,
|
|
837
875
|
zero_utilization_rate,
|
|
838
876
|
target_rate_percent,
|
|
839
877
|
} = interestRateConfig;
|
|
840
|
-
|
|
878
|
+
|
|
841
879
|
const nextFullUtilizationRate = this.fullUtilizationRate(
|
|
842
880
|
interestRateConfig,
|
|
843
881
|
timeDelta,
|
|
844
882
|
scaledUtilization,
|
|
845
883
|
lastFullUtilizationRate
|
|
846
884
|
);
|
|
847
|
-
|
|
885
|
+
|
|
848
886
|
const targetRate =
|
|
849
887
|
(((nextFullUtilizationRate - zero_utilization_rate) * target_rate_percent) / SCALE) +
|
|
850
888
|
zero_utilization_rate;
|
|
851
|
-
|
|
889
|
+
|
|
852
890
|
let newRatePerSecond: bigint;
|
|
853
|
-
|
|
891
|
+
|
|
854
892
|
if (scaledUtilization < target_utilization) {
|
|
855
893
|
newRatePerSecond =
|
|
856
894
|
zero_utilization_rate +
|
|
@@ -863,10 +901,10 @@ export class VesuAdapter extends CacheClass {
|
|
|
863
901
|
(nextFullUtilizationRate - targetRate)) /
|
|
864
902
|
(UTILIZATION_SCALE - target_utilization);
|
|
865
903
|
}
|
|
866
|
-
|
|
904
|
+
|
|
867
905
|
return { newRatePerSecond, nextFullUtilizationRate };
|
|
868
906
|
}
|
|
869
|
-
|
|
907
|
+
|
|
870
908
|
/**
|
|
871
909
|
* Calculates utilization given a specific rate per second.
|
|
872
910
|
* This is an inverse function of the piecewise interest rate formula above.
|
|
@@ -893,4 +931,4 @@ export class VesuAdapter extends CacheClass {
|
|
|
893
931
|
}
|
|
894
932
|
throw new Error('Max utilization not found');
|
|
895
933
|
}
|
|
896
|
-
}
|
|
934
|
+
}
|