@strkfarm/sdk 1.0.55 → 1.0.56
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 +0 -0
- package/dist/cli.mjs +0 -0
- package/dist/index.browser.global.js +66535 -47529
- package/dist/index.browser.mjs +16343 -8966
- package/dist/index.d.ts +305 -11
- package/dist/index.js +15893 -8347
- package/dist/index.mjs +10440 -2901
- package/package.json +4 -3
- package/src/data/universal-vault.abi.json +1565 -0
- package/src/data/vault-manager.abi.json +634 -0
- package/src/data/vesu-singleton.abi.json +2247 -0
- package/src/dataTypes/address.ts +4 -0
- package/src/global.ts +30 -0
- package/src/interfaces/common.tsx +18 -1
- package/src/modules/pricer.ts +1 -1
- package/src/node/deployer.ts +219 -0
- package/src/node/index.ts +2 -1
- package/src/strategies/index.ts +3 -1
- package/src/strategies/universal-adapters/adapter-utils.ts +13 -0
- package/src/strategies/universal-adapters/baseAdapter.ts +40 -0
- package/src/strategies/universal-adapters/common-adapter.ts +96 -0
- package/src/strategies/universal-adapters/index.ts +3 -0
- package/src/strategies/universal-adapters/vesu-adapter.ts +274 -0
- package/src/strategies/universal-strategy.ts +543 -0
- package/src/utils/index.ts +1 -0
- package/src/utils/oz-merkle.ts +100 -0
|
@@ -0,0 +1,274 @@
|
|
|
1
|
+
import { LeafData, logger } from "@/utils"
|
|
2
|
+
import { CairoCustomEnum, Contract, hash, num, RpcProvider, shortString, uint256, Uint256 } from "starknet";
|
|
3
|
+
import { SIMPLE_SANITIZER, toBigInt } from "./adapter-utils";
|
|
4
|
+
import { ContractAddr, Web3Number } from "@/dataTypes";
|
|
5
|
+
import { AdapterLeafType, BaseAdapter, GenerateCallFn, ManageCall } from "./baseAdapter";
|
|
6
|
+
import VesuSingletonAbi from '../../data/vesu-singleton.abi.json';
|
|
7
|
+
import { IConfig, TokenInfo, VaultPosition } from "@/interfaces";
|
|
8
|
+
import { PricerBase } from "@/modules/pricerBase";
|
|
9
|
+
import VesuPoolIDs from "@/data/vesu_pools.json";
|
|
10
|
+
import { getAPIUsingHeadlessBrowser } from "@/node/headless";
|
|
11
|
+
import { Global } from "@/global";
|
|
12
|
+
|
|
13
|
+
interface VesuPoolsInfo { pools: any[]; isErrorPoolsAPI: boolean };
|
|
14
|
+
|
|
15
|
+
export enum VesuAmountType {
|
|
16
|
+
Delta,
|
|
17
|
+
Target
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
export enum VesuAmountDenomination {
|
|
21
|
+
Native,
|
|
22
|
+
Assets
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
export interface i257 {
|
|
26
|
+
abs: Web3Number,
|
|
27
|
+
is_negative: boolean,
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
export interface VesuAmount {
|
|
31
|
+
amount_type: VesuAmountType,
|
|
32
|
+
denomination: VesuAmountDenomination,
|
|
33
|
+
value: i257
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
export interface VesuModifyPositionCallParams {
|
|
37
|
+
collateralAmount: VesuAmount,
|
|
38
|
+
debtAmount: VesuAmount
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
export interface VesuAdapterConfig {
|
|
42
|
+
poolId: ContractAddr,
|
|
43
|
+
collateral: TokenInfo,
|
|
44
|
+
debt: TokenInfo,
|
|
45
|
+
vaultAllocator: ContractAddr,
|
|
46
|
+
id: string
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
export const VesuPools = {
|
|
50
|
+
Genesis: ContractAddr.from('0x4dc4f0ca6ea4961e4c8373265bfd5317678f4fe374d76f3fd7135f57763bf28')
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
export class VesuAdapter extends BaseAdapter {
|
|
54
|
+
VESU_SINGLETON = ContractAddr.from("0x000d8d6dfec4d33bfb6895de9f3852143a17c6f92fd2a21da3d6924d34870160");
|
|
55
|
+
config: VesuAdapterConfig;
|
|
56
|
+
networkConfig: IConfig | undefined;
|
|
57
|
+
pricer: PricerBase | undefined;
|
|
58
|
+
cache: Record<string, any> = {};
|
|
59
|
+
|
|
60
|
+
constructor(config: VesuAdapterConfig) {
|
|
61
|
+
super();
|
|
62
|
+
this.config = config;
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
getModifyPosition = (): AdapterLeafType<VesuModifyPositionCallParams> => {
|
|
66
|
+
const positionData: bigint[] = [0n];
|
|
67
|
+
const packedArguments: bigint[] = [
|
|
68
|
+
toBigInt(this.config.poolId.toString()), // pool id
|
|
69
|
+
toBigInt(this.config.collateral.address.toString()), // collateral
|
|
70
|
+
toBigInt(this.config.debt.address.toString()), // debt
|
|
71
|
+
toBigInt(this.config.vaultAllocator.toString()), // vault allocator
|
|
72
|
+
toBigInt(positionData.length),
|
|
73
|
+
...positionData
|
|
74
|
+
];
|
|
75
|
+
const output = this.constructSimpleLeafData({
|
|
76
|
+
id: this.config.id,
|
|
77
|
+
target: this.VESU_SINGLETON,
|
|
78
|
+
method: 'modify_position',
|
|
79
|
+
packedArguments
|
|
80
|
+
});
|
|
81
|
+
|
|
82
|
+
return { leaf: output, callConstructor: this.getModifyPositionCall.bind(this) };
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
static getDefaultModifyPositionCallParams(params: {
|
|
86
|
+
collateralAmount: Web3Number,
|
|
87
|
+
isAddCollateral: boolean,
|
|
88
|
+
debtAmount: Web3Number,
|
|
89
|
+
isBorrow: boolean
|
|
90
|
+
}) {
|
|
91
|
+
return {
|
|
92
|
+
collateralAmount: {
|
|
93
|
+
amount_type: VesuAmountType.Delta,
|
|
94
|
+
denomination: VesuAmountDenomination.Assets,
|
|
95
|
+
value: {
|
|
96
|
+
abs: params.collateralAmount,
|
|
97
|
+
is_negative: !params.isAddCollateral
|
|
98
|
+
}
|
|
99
|
+
},
|
|
100
|
+
debtAmount: {
|
|
101
|
+
amount_type: VesuAmountType.Delta,
|
|
102
|
+
denomination: VesuAmountDenomination.Assets,
|
|
103
|
+
value: {
|
|
104
|
+
abs: params.debtAmount,
|
|
105
|
+
is_negative: !params.isBorrow
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
getModifyPositionCall = (params: VesuModifyPositionCallParams): ManageCall => {
|
|
112
|
+
// pub pool_id: felt252,
|
|
113
|
+
// pub collateral_asset: ContractAddress,
|
|
114
|
+
// pub debt_asset: ContractAddress,
|
|
115
|
+
// pub user: ContractAddress,
|
|
116
|
+
// pub collateral: Amount,
|
|
117
|
+
// pub debt: Amount,
|
|
118
|
+
// pub data: Span<felt252>,
|
|
119
|
+
const _collateral = {
|
|
120
|
+
amount_type: this.formatAmountTypeEnum(params.collateralAmount.amount_type),
|
|
121
|
+
denomination: this.formatAmountDenominationEnum(params.collateralAmount.denomination),
|
|
122
|
+
value: {
|
|
123
|
+
abs: uint256.bnToUint256(params.collateralAmount.value.abs.toWei()),
|
|
124
|
+
is_negative: params.collateralAmount.value.is_negative
|
|
125
|
+
}
|
|
126
|
+
};
|
|
127
|
+
const _debt = {
|
|
128
|
+
amount_type: this.formatAmountTypeEnum(params.debtAmount.amount_type),
|
|
129
|
+
denomination: this.formatAmountDenominationEnum(params.debtAmount.denomination),
|
|
130
|
+
value: {
|
|
131
|
+
abs: uint256.bnToUint256(params.debtAmount.value.abs.toWei()),
|
|
132
|
+
is_negative: params.debtAmount.value.is_negative
|
|
133
|
+
}
|
|
134
|
+
};
|
|
135
|
+
const singletonContract = new Contract(VesuSingletonAbi, this.VESU_SINGLETON.toString(), new RpcProvider({nodeUrl: ''}));
|
|
136
|
+
const call = singletonContract.populate('modify_position', {
|
|
137
|
+
params: {
|
|
138
|
+
pool_id: this.config.poolId.toBigInt(),
|
|
139
|
+
collateral_asset: this.config.collateral.address.toBigInt(),
|
|
140
|
+
debt_asset: this.config.debt.address.toBigInt(),
|
|
141
|
+
user: this.config.vaultAllocator.toBigInt(),
|
|
142
|
+
collateral: _collateral,
|
|
143
|
+
debt: _debt,
|
|
144
|
+
data: [0]
|
|
145
|
+
}
|
|
146
|
+
});
|
|
147
|
+
return {
|
|
148
|
+
sanitizer: SIMPLE_SANITIZER,
|
|
149
|
+
call: {
|
|
150
|
+
contractAddress: this.VESU_SINGLETON,
|
|
151
|
+
selector: hash.getSelectorFromName('modify_position'),
|
|
152
|
+
calldata: [
|
|
153
|
+
...call.calldata as bigint[]
|
|
154
|
+
]
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
formatAmountTypeEnum(amountType: VesuAmountType) {
|
|
160
|
+
switch(amountType) {
|
|
161
|
+
case VesuAmountType.Delta:
|
|
162
|
+
return new CairoCustomEnum({ Delta: {} });
|
|
163
|
+
case VesuAmountType.Target:
|
|
164
|
+
return new CairoCustomEnum({ Target: {} });
|
|
165
|
+
}
|
|
166
|
+
throw new Error(`Unknown VesuAmountType: ${amountType}`);
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
formatAmountDenominationEnum(denomination: VesuAmountDenomination) {
|
|
170
|
+
switch(denomination) {
|
|
171
|
+
case VesuAmountDenomination.Native:
|
|
172
|
+
return new CairoCustomEnum({ Native: {} });
|
|
173
|
+
case VesuAmountDenomination.Assets:
|
|
174
|
+
return new CairoCustomEnum({ Assets: {} });
|
|
175
|
+
}
|
|
176
|
+
throw new Error(`Unknown VesuAmountDenomination: ${denomination}`);
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
getVesuSingletonContract(config: IConfig) {
|
|
180
|
+
return new Contract(VesuSingletonAbi, this.VESU_SINGLETON.address, config.provider);
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
async getLTVConfig(config: IConfig) {
|
|
184
|
+
const CACHE_KEY = 'ltv_config';
|
|
185
|
+
if (this.cache[CACHE_KEY]) {
|
|
186
|
+
return this.cache[CACHE_KEY] as number;
|
|
187
|
+
}
|
|
188
|
+
const output: any = await this.getVesuSingletonContract(config)
|
|
189
|
+
.call('ltv_config', [this.config.poolId.address, this.config.collateral.address.address, this.config.debt.address.address])
|
|
190
|
+
this.cache[CACHE_KEY] = Number(output.max_ltv) / 1e18;
|
|
191
|
+
return this.cache[CACHE_KEY] as number;
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
async getPositions(config: IConfig): Promise<VaultPosition[]> {
|
|
195
|
+
if (!this.pricer) {
|
|
196
|
+
throw new Error('Pricer is not initialized');
|
|
197
|
+
}
|
|
198
|
+
// { '0': { collateral_shares: 0n, nominal_debt: 0n }, '1': 0n, '2': 0n }
|
|
199
|
+
const CACHE_KEY = 'positions';
|
|
200
|
+
if (this.cache[CACHE_KEY]) {
|
|
201
|
+
return this.cache[CACHE_KEY];
|
|
202
|
+
}
|
|
203
|
+
const output: any = await this.getVesuSingletonContract(config)
|
|
204
|
+
.call('position_unsafe', [
|
|
205
|
+
this.config.poolId.address,
|
|
206
|
+
this.config.collateral.address.address,
|
|
207
|
+
this.config.debt.address.address,
|
|
208
|
+
this.config.vaultAllocator.address
|
|
209
|
+
]);
|
|
210
|
+
|
|
211
|
+
const token1Price = await this.pricer.getPrice(this.config.collateral.symbol);
|
|
212
|
+
const token2Price = await this.pricer.getPrice(this.config.debt.symbol);
|
|
213
|
+
|
|
214
|
+
const collateralAmount = Web3Number.fromWei(output['1'].toString(), this.config.collateral.decimals);
|
|
215
|
+
const debtAmount = Web3Number.fromWei(output['2'].toString(), this.config.debt.decimals);
|
|
216
|
+
const value = [{
|
|
217
|
+
amount: collateralAmount,
|
|
218
|
+
token: this.config.collateral,
|
|
219
|
+
usdValue: collateralAmount.multipliedBy(token1Price.price).toNumber(),
|
|
220
|
+
remarks: "Collateral"
|
|
221
|
+
}, {
|
|
222
|
+
amount: debtAmount,
|
|
223
|
+
token: this.config.debt,
|
|
224
|
+
usdValue: debtAmount.multipliedBy(token2Price.price).toNumber(),
|
|
225
|
+
remarks: "Debt"
|
|
226
|
+
}];
|
|
227
|
+
this.cache[CACHE_KEY] = value;
|
|
228
|
+
return value;
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
static async getVesuPools(
|
|
232
|
+
retry = 0
|
|
233
|
+
): Promise<VesuPoolsInfo> {
|
|
234
|
+
const CACHE_KEY = 'VESU_POOLS';
|
|
235
|
+
const cacheValue = Global.getGlobalCache<VesuPoolsInfo>(CACHE_KEY);
|
|
236
|
+
if (cacheValue) {
|
|
237
|
+
return cacheValue;
|
|
238
|
+
}
|
|
239
|
+
|
|
240
|
+
let isErrorPoolsAPI = false;
|
|
241
|
+
let pools: any[] = [];
|
|
242
|
+
try {
|
|
243
|
+
const data = await getAPIUsingHeadlessBrowser(
|
|
244
|
+
"https://api.vesu.xyz/pools"
|
|
245
|
+
);
|
|
246
|
+
pools = data.data;
|
|
247
|
+
|
|
248
|
+
// Vesu API is unstable sometimes, some Pools may be missing sometimes
|
|
249
|
+
for (const pool of VesuPoolIDs.data) {
|
|
250
|
+
const found = pools.find((d: any) => d.id === pool.id);
|
|
251
|
+
if (!found) {
|
|
252
|
+
logger.verbose(`VesuRebalance: pools: ${JSON.stringify(pools)}`);
|
|
253
|
+
logger.verbose(
|
|
254
|
+
`VesuRebalance: Pool ${pool.id} not found in Vesu API, using hardcoded data`
|
|
255
|
+
);
|
|
256
|
+
throw new Error(`pool not found [sanity check]: ${pool.id}`);
|
|
257
|
+
}
|
|
258
|
+
}
|
|
259
|
+
} catch (e) {
|
|
260
|
+
logger.error(
|
|
261
|
+
`${VesuAdapter.name}: Error fetching pools for retry ${retry}`,
|
|
262
|
+
e
|
|
263
|
+
);
|
|
264
|
+
isErrorPoolsAPI = true;
|
|
265
|
+
if (retry < 10) {
|
|
266
|
+
await new Promise((resolve) => setTimeout(resolve, 5000 * (retry + 1)));
|
|
267
|
+
return await this.getVesuPools(retry + 1);
|
|
268
|
+
}
|
|
269
|
+
}
|
|
270
|
+
|
|
271
|
+
Global.setGlobalCache(CACHE_KEY, { pools, isErrorPoolsAPI }, 300000); // cache for 5 minutes
|
|
272
|
+
return { pools, isErrorPoolsAPI };
|
|
273
|
+
}
|
|
274
|
+
}
|