@strkfarm/sdk 2.0.0-dev.5 → 2.0.0-dev.7
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 +121 -61
- package/dist/index.browser.mjs +121 -61
- package/dist/index.d.ts +7 -1
- package/dist/index.js +121 -61
- package/dist/index.mjs +121 -61
- package/package.json +1 -1
- package/src/strategies/universal-adapters/avnu-adapter.ts +1 -1
- package/src/strategies/universal-adapters/extended-adapter.ts +157 -74
- package/src/strategies/universal-adapters/vesu-multiply-adapter.ts +3 -1
- package/src/strategies/universal-lst-muliplier-strategy.tsx +2 -1
- package/src/strategies/vesu-extended-strategy/utils/constants.ts +1 -1
- package/src/strategies/vesu-extended-strategy/utils/helper.ts +2 -4
- package/src/strategies/vesu-extended-strategy/vesu-extended-strategy.tsx +22 -16
|
@@ -1,4 +1,9 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import {
|
|
2
|
+
BaseAdapter,
|
|
3
|
+
DepositParams,
|
|
4
|
+
WithdrawParams,
|
|
5
|
+
BaseAdapterConfig,
|
|
6
|
+
} from "./baseAdapter";
|
|
2
7
|
import { Protocols } from "@/interfaces";
|
|
3
8
|
import { SupportedPosition } from "./baseAdapter";
|
|
4
9
|
import { PositionAPY, APYType, PositionAmount } from "./baseAdapter";
|
|
@@ -11,7 +16,12 @@ import { StandardMerkleTree } from "@/utils";
|
|
|
11
16
|
import { hash, uint256 } from "starknet";
|
|
12
17
|
import { Global } from "@/global";
|
|
13
18
|
import { AdapterLeafType, GenerateCallFn } from "./baseAdapter";
|
|
14
|
-
import {
|
|
19
|
+
import {
|
|
20
|
+
AVNU_LEGACY_SANITIZER,
|
|
21
|
+
EXTENDED_SANITIZER,
|
|
22
|
+
SIMPLE_SANITIZER,
|
|
23
|
+
toBigInt,
|
|
24
|
+
} from "./adapter-utils";
|
|
15
25
|
import ExtendedWrapper, {
|
|
16
26
|
AssetOperationStatus,
|
|
17
27
|
AssetOperationType,
|
|
@@ -35,6 +45,8 @@ export interface ExtendedAdapterConfig extends BaseAdapterConfig {
|
|
|
35
45
|
extendedMarketName: string;
|
|
36
46
|
extendedPrecision: number;
|
|
37
47
|
avnuAdapter: AvnuAdapter;
|
|
48
|
+
retryDelayForOrderStatus: number;
|
|
49
|
+
minimumExtendedMovementAmount: number;
|
|
38
50
|
}
|
|
39
51
|
|
|
40
52
|
export class ExtendedAdapter extends BaseAdapter<
|
|
@@ -43,6 +55,8 @@ export class ExtendedAdapter extends BaseAdapter<
|
|
|
43
55
|
> {
|
|
44
56
|
readonly config: ExtendedAdapterConfig;
|
|
45
57
|
readonly client: ExtendedWrapper;
|
|
58
|
+
readonly retryDelayForOrderStatus: number;
|
|
59
|
+
readonly minimumExtendedMovementAmount: number;
|
|
46
60
|
|
|
47
61
|
constructor(config: ExtendedAdapterConfig) {
|
|
48
62
|
super(config, ExtendedAdapter.name, Protocols.EXTENDED);
|
|
@@ -53,7 +67,9 @@ export class ExtendedAdapter extends BaseAdapter<
|
|
|
53
67
|
timeout: this.config.extendedTimeout,
|
|
54
68
|
retries: this.config.extendedRetries,
|
|
55
69
|
});
|
|
70
|
+
this.minimumExtendedMovementAmount = this.config.minimumExtendedMovementAmount ?? 5; //5 usdc
|
|
56
71
|
this.client = client;
|
|
72
|
+
this.retryDelayForOrderStatus = this.config.retryDelayForOrderStatus ?? 3000;
|
|
57
73
|
}
|
|
58
74
|
//abstract means the method has no implementation in this class; instead, child classes must implement it.
|
|
59
75
|
protected async getAPY(
|
|
@@ -61,12 +77,15 @@ export class ExtendedAdapter extends BaseAdapter<
|
|
|
61
77
|
): Promise<PositionAPY> {
|
|
62
78
|
/** Considering supportedPosiiton.isDebt as side parameter to get the funding rates */
|
|
63
79
|
const side = supportedPosition.isDebt ? "LONG" : "SHORT";
|
|
64
|
-
const fundingRates = await this.client.getFundingRates(
|
|
80
|
+
const fundingRates = await this.client.getFundingRates(
|
|
81
|
+
this.config.extendedMarketName,
|
|
82
|
+
side
|
|
83
|
+
);
|
|
65
84
|
if (fundingRates.status !== "OK") {
|
|
66
85
|
logger.error("error getting funding rates", fundingRates);
|
|
67
86
|
return { apy: 0, type: APYType.BASE };
|
|
68
87
|
}
|
|
69
|
-
const fundingRate:FundingRate = fundingRates.data[0];
|
|
88
|
+
const fundingRate: FundingRate = fundingRates.data[0];
|
|
70
89
|
const apy = Number(fundingRate.f) * 365 * 24;
|
|
71
90
|
return { apy: apy, type: APYType.BASE };
|
|
72
91
|
}
|
|
@@ -118,14 +137,14 @@ export class ExtendedAdapter extends BaseAdapter<
|
|
|
118
137
|
sanitizer: ContractAddr;
|
|
119
138
|
id: string;
|
|
120
139
|
}[] {
|
|
121
|
-
const usdceToken = Global.getDefaultTokens().find(
|
|
140
|
+
const usdceToken = Global.getDefaultTokens().find(
|
|
141
|
+
(token) => token.symbol === "USDCe"
|
|
142
|
+
);
|
|
122
143
|
return [
|
|
123
144
|
{
|
|
124
145
|
target: this.config.supportedPositions[0].asset.address,
|
|
125
146
|
method: "approve",
|
|
126
|
-
packedArguments: [
|
|
127
|
-
AVNU_EXCHANGE_FOR_LEGACY_USDC.toBigInt(),
|
|
128
|
-
],
|
|
147
|
+
packedArguments: [AVNU_EXCHANGE_FOR_LEGACY_USDC.toBigInt()],
|
|
129
148
|
id: `extended_approve_${this.config.supportedPositions[0].asset.symbol}`,
|
|
130
149
|
sanitizer: AVNU_LEGACY_SANITIZER,
|
|
131
150
|
},
|
|
@@ -155,19 +174,27 @@ export class ExtendedAdapter extends BaseAdapter<
|
|
|
155
174
|
|
|
156
175
|
getSwapFromLegacyLeaf(): AdapterLeafType<DepositParams> {
|
|
157
176
|
const leafConfigs = this._getSwapFromLegacyLeaf();
|
|
158
|
-
const leaves = leafConfigs.map(config => {
|
|
177
|
+
const leaves = leafConfigs.map((config) => {
|
|
159
178
|
const { target, method, packedArguments, sanitizer, id } = config;
|
|
160
|
-
const leaf = this.constructSimpleLeafData(
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
179
|
+
const leaf = this.constructSimpleLeafData(
|
|
180
|
+
{
|
|
181
|
+
id: id,
|
|
182
|
+
target,
|
|
183
|
+
method,
|
|
184
|
+
packedArguments,
|
|
185
|
+
},
|
|
186
|
+
sanitizer
|
|
187
|
+
);
|
|
166
188
|
return leaf;
|
|
167
189
|
});
|
|
168
|
-
return {
|
|
190
|
+
return {
|
|
191
|
+
leaves,
|
|
192
|
+
callConstructor: this.getSwapFromLegacyCall.bind(
|
|
193
|
+
this
|
|
194
|
+
) as unknown as GenerateCallFn<DepositParams>,
|
|
195
|
+
};
|
|
169
196
|
}
|
|
170
|
-
|
|
197
|
+
|
|
171
198
|
protected _getSwapFromLegacyLeaf(): {
|
|
172
199
|
target: ContractAddr;
|
|
173
200
|
method: string;
|
|
@@ -175,14 +202,14 @@ export class ExtendedAdapter extends BaseAdapter<
|
|
|
175
202
|
sanitizer: ContractAddr;
|
|
176
203
|
id: string;
|
|
177
204
|
}[] {
|
|
178
|
-
const usdceToken = Global.getDefaultTokens().find(
|
|
205
|
+
const usdceToken = Global.getDefaultTokens().find(
|
|
206
|
+
(token) => token.symbol === "USDCe"
|
|
207
|
+
);
|
|
179
208
|
return [
|
|
180
209
|
{
|
|
181
210
|
target: usdceToken!.address,
|
|
182
211
|
method: "approve",
|
|
183
|
-
packedArguments: [
|
|
184
|
-
AVNU_EXCHANGE_FOR_LEGACY_USDC.toBigInt(),
|
|
185
|
-
],
|
|
212
|
+
packedArguments: [AVNU_EXCHANGE_FOR_LEGACY_USDC.toBigInt()],
|
|
186
213
|
id: `extendedswaplegacyapprove_${usdceToken!.symbol}`,
|
|
187
214
|
sanitizer: AVNU_LEGACY_SANITIZER,
|
|
188
215
|
},
|
|
@@ -193,10 +220,9 @@ export class ExtendedAdapter extends BaseAdapter<
|
|
|
193
220
|
id: `extended_swap_to_new_${usdceToken!.symbol}`,
|
|
194
221
|
sanitizer: AVNU_LEGACY_SANITIZER,
|
|
195
222
|
},
|
|
196
|
-
]
|
|
223
|
+
];
|
|
197
224
|
}
|
|
198
225
|
|
|
199
|
-
|
|
200
226
|
protected _getWithdrawLeaf(): {
|
|
201
227
|
target: ContractAddr;
|
|
202
228
|
method: string;
|
|
@@ -213,12 +239,14 @@ export class ExtendedAdapter extends BaseAdapter<
|
|
|
213
239
|
async getDepositCall(params: DepositParams): Promise<ManageCall[]> {
|
|
214
240
|
try {
|
|
215
241
|
const usdcToken = this.config.supportedPositions[0].asset;
|
|
216
|
-
const usdceToken = Global.getDefaultTokens().find(
|
|
217
|
-
|
|
218
|
-
Math.random() * 10 ** usdcToken.decimals
|
|
242
|
+
const usdceToken = Global.getDefaultTokens().find(
|
|
243
|
+
(token) => token.symbol === "USDCe"
|
|
219
244
|
);
|
|
245
|
+
const salt = Math.floor(Math.random() * 10 ** usdcToken.decimals);
|
|
220
246
|
// Give approval for more amount than the required amount
|
|
221
|
-
const amount = uint256.bnToUint256(
|
|
247
|
+
const amount = uint256.bnToUint256(
|
|
248
|
+
params.amount.multipliedBy(10).toWei()
|
|
249
|
+
);
|
|
222
250
|
const quotes = await this.config.avnuAdapter.getQuotesAvnu(
|
|
223
251
|
usdcToken.address.toString(),
|
|
224
252
|
usdceToken!.address.toString(),
|
|
@@ -226,15 +254,17 @@ export class ExtendedAdapter extends BaseAdapter<
|
|
|
226
254
|
this.config.avnuAdapter.config.vaultAllocator.address.toString(),
|
|
227
255
|
usdceToken!.decimals,
|
|
228
256
|
false
|
|
229
|
-
)
|
|
257
|
+
);
|
|
230
258
|
|
|
231
259
|
if (!quotes) {
|
|
232
260
|
logger.error("error getting quotes from avnu");
|
|
233
261
|
return [];
|
|
234
262
|
}
|
|
235
|
-
const getCalldata = await this.config.avnuAdapter.getSwapCallData(
|
|
263
|
+
const getCalldata = await this.config.avnuAdapter.getSwapCallData(
|
|
264
|
+
quotes!
|
|
265
|
+
);
|
|
236
266
|
const swapCallData = getCalldata[0];
|
|
237
|
-
|
|
267
|
+
//change extended sanitizer here
|
|
238
268
|
return [
|
|
239
269
|
{
|
|
240
270
|
sanitizer: AVNU_LEGACY_SANITIZER,
|
|
@@ -287,35 +317,44 @@ export class ExtendedAdapter extends BaseAdapter<
|
|
|
287
317
|
}
|
|
288
318
|
}
|
|
289
319
|
|
|
290
|
-
getProofsForFromLegacySwap<T>(tree: StandardMerkleTree): {
|
|
320
|
+
getProofsForFromLegacySwap<T>(tree: StandardMerkleTree): {
|
|
321
|
+
proofs: string[][];
|
|
322
|
+
callConstructor:
|
|
323
|
+
| GenerateCallFn<DepositParams>
|
|
324
|
+
| GenerateCallFn<WithdrawParams>;
|
|
325
|
+
} {
|
|
291
326
|
let proofGroups: string[][] = [];
|
|
292
327
|
|
|
293
|
-
const ids = this.getSwapFromLegacyLeaf().leaves.map(l => l.readableId)
|
|
328
|
+
const ids = this.getSwapFromLegacyLeaf().leaves.map((l) => l.readableId);
|
|
294
329
|
// console.log(`${this.name}::getProofs ids: ${ids}`);
|
|
295
330
|
for (const [i, v] of tree.entries()) {
|
|
296
|
-
|
|
331
|
+
// console.log(`${this.name}::getProofs v: ${v.readableId}`);
|
|
297
332
|
if (ids.includes(v.readableId)) {
|
|
298
|
-
|
|
333
|
+
//console.log(`${this.name}::getProofs found id: ${v.readableId}`);
|
|
299
334
|
proofGroups.push(tree.getProof(i));
|
|
300
335
|
}
|
|
301
336
|
}
|
|
302
337
|
if (proofGroups.length != ids.length) {
|
|
303
|
-
throw new Error(`Not all proofs found for IDs: ${ids.join(
|
|
338
|
+
throw new Error(`Not all proofs found for IDs: ${ids.join(", ")}`);
|
|
304
339
|
}
|
|
305
340
|
|
|
306
341
|
// find leaf adapter
|
|
307
342
|
return {
|
|
308
343
|
proofs: proofGroups,
|
|
309
|
-
callConstructor: this.getSwapFromLegacyCall.bind(this)
|
|
310
|
-
|
|
311
|
-
|
|
344
|
+
callConstructor: this.getSwapFromLegacyCall.bind(this),
|
|
345
|
+
};
|
|
346
|
+
}
|
|
312
347
|
|
|
313
348
|
async getSwapFromLegacyCall(params: DepositParams): Promise<ManageCall[]> {
|
|
314
349
|
try {
|
|
315
350
|
const usdcToken = this.config.supportedPositions[0].asset;
|
|
316
|
-
const usdceToken = Global.getDefaultTokens().find(
|
|
351
|
+
const usdceToken = Global.getDefaultTokens().find(
|
|
352
|
+
(token) => token.symbol === "USDCe"
|
|
353
|
+
);
|
|
317
354
|
// Give approval for more amount than the required amount
|
|
318
|
-
const amount = uint256.bnToUint256(
|
|
355
|
+
const amount = uint256.bnToUint256(
|
|
356
|
+
params.amount.multipliedBy(10).toWei()
|
|
357
|
+
);
|
|
319
358
|
const quotes = await this.config.avnuAdapter.getQuotesAvnu(
|
|
320
359
|
usdceToken!.address.toString(),
|
|
321
360
|
usdcToken!.address.toString(),
|
|
@@ -323,15 +362,17 @@ export class ExtendedAdapter extends BaseAdapter<
|
|
|
323
362
|
this.config.avnuAdapter.config.vaultAllocator.address.toString(),
|
|
324
363
|
usdcToken!.decimals,
|
|
325
364
|
false
|
|
326
|
-
)
|
|
365
|
+
);
|
|
327
366
|
|
|
328
367
|
if (!quotes) {
|
|
329
368
|
logger.error("error getting quotes from avnu");
|
|
330
369
|
return [];
|
|
331
370
|
}
|
|
332
|
-
const getCalldata = await this.config.avnuAdapter.getSwapCallData(
|
|
371
|
+
const getCalldata = await this.config.avnuAdapter.getSwapCallData(
|
|
372
|
+
quotes!
|
|
373
|
+
);
|
|
333
374
|
const swapCallData = getCalldata[0];
|
|
334
|
-
|
|
375
|
+
//change extended sanitizer here
|
|
335
376
|
return [
|
|
336
377
|
{
|
|
337
378
|
sanitizer: AVNU_LEGACY_SANITIZER,
|
|
@@ -352,7 +393,7 @@ export class ExtendedAdapter extends BaseAdapter<
|
|
|
352
393
|
selector: hash.getSelectorFromName("swap_to_new"),
|
|
353
394
|
calldata: swapCallData,
|
|
354
395
|
},
|
|
355
|
-
}
|
|
396
|
+
},
|
|
356
397
|
];
|
|
357
398
|
} catch (error) {
|
|
358
399
|
logger.error(`Error creating Deposit Call: ${error}`);
|
|
@@ -377,9 +418,14 @@ export class ExtendedAdapter extends BaseAdapter<
|
|
|
377
418
|
if (!this.client) {
|
|
378
419
|
throw new Error("Client not initialized");
|
|
379
420
|
}
|
|
380
|
-
const withdrawalRequest = await this.client.withdrawUSDC(
|
|
421
|
+
const withdrawalRequest = await this.client.withdrawUSDC(
|
|
422
|
+
amount.toFixed(2)
|
|
423
|
+
);
|
|
381
424
|
if (withdrawalRequest.status === "OK") {
|
|
382
|
-
const withdrawalStatus = await this.getDepositOrWithdrawalStatus(
|
|
425
|
+
const withdrawalStatus = await this.getDepositOrWithdrawalStatus(
|
|
426
|
+
withdrawalRequest.data,
|
|
427
|
+
AssetOperationType.WITHDRAWAL
|
|
428
|
+
);
|
|
383
429
|
return withdrawalStatus;
|
|
384
430
|
}
|
|
385
431
|
return false;
|
|
@@ -461,21 +507,46 @@ export class ExtendedAdapter extends BaseAdapter<
|
|
|
461
507
|
logger.error("error initializing client");
|
|
462
508
|
return null;
|
|
463
509
|
}
|
|
464
|
-
|
|
465
|
-
const orderhistory = await this.getOrderHistory(marketName);
|
|
510
|
+
let orderhistory = await this.getOrderHistory(marketName);
|
|
466
511
|
|
|
467
512
|
if (!orderhistory || orderhistory.length === 0) {
|
|
468
|
-
logger.error(`error getting order: ${orderId}`);
|
|
469
|
-
|
|
513
|
+
logger.error(`error getting order history: ${orderId}`);
|
|
514
|
+
} else {
|
|
515
|
+
const order = orderhistory
|
|
516
|
+
.slice(0, 10)
|
|
517
|
+
.find((order) => order.id.toString() === orderId);
|
|
518
|
+
if (order) {
|
|
519
|
+
return order;
|
|
520
|
+
}
|
|
470
521
|
}
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
522
|
+
|
|
523
|
+
// Retry logic: 3 more attempts with 3 second delay each
|
|
524
|
+
for (let attempt = 1; attempt <= 5; attempt++) {
|
|
525
|
+
await new Promise((resolve) => setTimeout(resolve, this.retryDelayForOrderStatus));
|
|
526
|
+
orderhistory = await this.getOrderHistory(marketName);
|
|
527
|
+
|
|
528
|
+
if (!orderhistory || orderhistory.length === 0) {
|
|
529
|
+
logger.error(
|
|
530
|
+
`error getting order history on retry ${attempt}: ${orderId}`
|
|
531
|
+
);
|
|
532
|
+
continue;
|
|
533
|
+
}
|
|
534
|
+
|
|
535
|
+
const order = orderhistory
|
|
536
|
+
.slice(0, 5)
|
|
537
|
+
.find((order) => order.id.toString() === orderId);
|
|
538
|
+
|
|
539
|
+
if (order && order.status === OrderStatus.FILLED) {
|
|
540
|
+
return order;
|
|
541
|
+
}
|
|
542
|
+
|
|
543
|
+
logger.error(
|
|
544
|
+
`order not found in top 15 entries on retry ${attempt}: ${orderId}`
|
|
545
|
+
);
|
|
477
546
|
}
|
|
478
|
-
|
|
547
|
+
|
|
548
|
+
logger.error(`error getting order after all retries: ${orderId}`);
|
|
549
|
+
return null;
|
|
479
550
|
}
|
|
480
551
|
|
|
481
552
|
async fetchOrderBookBTCUSDC(): Promise<{
|
|
@@ -543,10 +614,10 @@ export class ExtendedAdapter extends BaseAdapter<
|
|
|
543
614
|
}
|
|
544
615
|
const { ask, bid } = await this.fetchOrderBookBTCUSDC();
|
|
545
616
|
const spread = ask.minus(bid);
|
|
546
|
-
let price = ask
|
|
547
|
-
|
|
548
|
-
.
|
|
549
|
-
|
|
617
|
+
let price = ask.plus(bid).div(2);
|
|
618
|
+
side === OrderSide.SELL
|
|
619
|
+
? (price = price.minus(spread.times(0.2 * attempt)))
|
|
620
|
+
: (price = price.plus(spread.times(0.2 * attempt)));
|
|
550
621
|
const amount_in_token = (btcAmount * parseInt(leverage)).toFixed(
|
|
551
622
|
this.config.extendedPrecision
|
|
552
623
|
); // gives the amount of wbtc
|
|
@@ -562,8 +633,11 @@ export class ExtendedAdapter extends BaseAdapter<
|
|
|
562
633
|
return null;
|
|
563
634
|
}
|
|
564
635
|
await new Promise((resolve) => setTimeout(resolve, 5000));
|
|
565
|
-
const openOrder = await this.getOrderStatus(
|
|
566
|
-
|
|
636
|
+
const openOrder = await this.getOrderStatus(
|
|
637
|
+
result.position_id,
|
|
638
|
+
this.config.extendedMarketName
|
|
639
|
+
);
|
|
640
|
+
if (!openOrder) {
|
|
567
641
|
if (attempt >= maxAttempts) {
|
|
568
642
|
logger.error("Max retries reached — could not verify open position");
|
|
569
643
|
return null;
|
|
@@ -585,7 +659,9 @@ export class ExtendedAdapter extends BaseAdapter<
|
|
|
585
659
|
};
|
|
586
660
|
}
|
|
587
661
|
} catch (err: any) {
|
|
588
|
-
logger.error(
|
|
662
|
+
logger.error(
|
|
663
|
+
`createShortOrder failed on attempt ${attempt}: ${err.message}`
|
|
664
|
+
);
|
|
589
665
|
|
|
590
666
|
if (attempt < maxAttempts) {
|
|
591
667
|
const backoff = 1200 * attempt;
|
|
@@ -635,26 +711,33 @@ export class ExtendedAdapter extends BaseAdapter<
|
|
|
635
711
|
}
|
|
636
712
|
}
|
|
637
713
|
|
|
638
|
-
async getDepositOrWithdrawalStatus(
|
|
639
|
-
|
|
714
|
+
async getDepositOrWithdrawalStatus(
|
|
715
|
+
orderId: number | string,
|
|
716
|
+
operationsType: AssetOperationType
|
|
717
|
+
): Promise<boolean> {
|
|
718
|
+
try {
|
|
640
719
|
let transferHistory = await this.client.getAssetOperations({
|
|
641
|
-
operationsType:[operationsType],
|
|
642
|
-
operationsStatus:[AssetOperationStatus.COMPLETED]
|
|
643
|
-
})
|
|
644
|
-
if(operationsType === AssetOperationType.DEPOSIT){
|
|
645
|
-
const myTransferStatus = transferHistory.data.find(
|
|
720
|
+
operationsType: [operationsType],
|
|
721
|
+
operationsStatus: [AssetOperationStatus.COMPLETED],
|
|
722
|
+
});
|
|
723
|
+
if (operationsType === AssetOperationType.DEPOSIT) {
|
|
724
|
+
const myTransferStatus = transferHistory.data.find(
|
|
725
|
+
(operation) => operation.transactionHash === orderId
|
|
726
|
+
);
|
|
646
727
|
if (!myTransferStatus) {
|
|
647
728
|
return true;
|
|
648
729
|
}
|
|
649
730
|
return true;
|
|
650
|
-
}else{
|
|
651
|
-
const myTransferStatus = transferHistory.data.find(
|
|
731
|
+
} else {
|
|
732
|
+
const myTransferStatus = transferHistory.data.find(
|
|
733
|
+
(operation) => operation.id.toString() === orderId.toString()
|
|
734
|
+
);
|
|
652
735
|
if (!myTransferStatus) {
|
|
653
736
|
return true;
|
|
654
737
|
}
|
|
655
738
|
return true;
|
|
656
739
|
}
|
|
657
|
-
}catch(err){
|
|
740
|
+
} catch (err) {
|
|
658
741
|
logger.error(`error getting deposit or withdrawal status: ${err}`);
|
|
659
742
|
return false;
|
|
660
743
|
}
|
|
@@ -50,6 +50,7 @@ export interface VesuMultiplyAdapterConfig extends BaseAdapterConfig {
|
|
|
50
50
|
targetHealthFactor: number;
|
|
51
51
|
minHealthFactor: number;
|
|
52
52
|
quoteAmountToFetchPrice: Web3Number;
|
|
53
|
+
minimumVesuMovementAmount: number;
|
|
53
54
|
}
|
|
54
55
|
|
|
55
56
|
export class VesuMultiplyAdapter extends BaseAdapter<
|
|
@@ -59,7 +60,7 @@ export class VesuMultiplyAdapter extends BaseAdapter<
|
|
|
59
60
|
readonly config: VesuMultiplyAdapterConfig;
|
|
60
61
|
readonly vesuAdapter: VesuAdapter;
|
|
61
62
|
readonly tokenMarketData: TokenMarketData;
|
|
62
|
-
|
|
63
|
+
readonly minimumVesuMovementAmount: number;
|
|
63
64
|
constructor(config: VesuMultiplyAdapterConfig) {
|
|
64
65
|
super(config, VesuMultiplyAdapter.name, Protocols.VESU);
|
|
65
66
|
this.config = config;
|
|
@@ -70,6 +71,7 @@ export class VesuMultiplyAdapter extends BaseAdapter<
|
|
|
70
71
|
vaultAllocator: config.vaultAllocator,
|
|
71
72
|
id: "",
|
|
72
73
|
});
|
|
74
|
+
this.minimumVesuMovementAmount = config.minimumVesuMovementAmount ?? 5; //5 usdc
|
|
73
75
|
this.tokenMarketData = new TokenMarketData(
|
|
74
76
|
this.config.pricer,
|
|
75
77
|
this.config.networkConfig
|
|
@@ -786,7 +786,8 @@ function getLooperSettings(
|
|
|
786
786
|
minHealthFactor: vaultSettings.minHealthFactor,
|
|
787
787
|
quoteAmountToFetchPrice: vaultSettings.quoteAmountToFetchPrice,
|
|
788
788
|
...baseAdapterConfig,
|
|
789
|
-
supportedPositions: [{asset: lstToken, isDebt: false}, {asset: Global.getDefaultTokens().find(token => token.symbol === position)!, isDebt: true}]
|
|
789
|
+
supportedPositions: [{asset: lstToken, isDebt: false}, {asset: Global.getDefaultTokens().find(token => token.symbol === position)!, isDebt: true}],
|
|
790
|
+
minimumVesuMovementAmount: 0
|
|
790
791
|
}));
|
|
791
792
|
|
|
792
793
|
const unusedBalanceAdapter = new UnusedBalanceAdapter({
|
|
@@ -22,7 +22,7 @@ export const STRK_API_RPC = process.env.STRK_API_RPC ?? "https://mainnet.starkne
|
|
|
22
22
|
export const MAX_RETRIES = Number(process.env.MAX_RETRIES ?? 3);
|
|
23
23
|
export const MAX_DELAY = Number(process.env.MAX_DELAY ?? 100);
|
|
24
24
|
export const EXTEND_MARKET_NAME = "BTC-USD";
|
|
25
|
-
export const LIMIT_BALANCE = Number(process.env.LIMIT_BALANCE ??
|
|
25
|
+
export const LIMIT_BALANCE = Number(process.env.LIMIT_BALANCE ?? 0.05);
|
|
26
26
|
export const REBALANCER_INTERVAL = Number(process.env.REBALANCER_INTERVAL ?? 180000); //3 mins
|
|
27
27
|
export const WITHDRAWAL_INTERVAL = Number(process.env.WITHDRAWAL_INTERVAL ?? 18000000); //5 hours
|
|
28
28
|
export const INVESTING_INTERVAL = Number(process.env.INVESTING_INTERVAL ?? 180000); //3 mins
|
|
@@ -66,12 +66,10 @@ export const calculateAmountDistribution = async (
|
|
|
66
66
|
vesu_leverage: 0,
|
|
67
67
|
};
|
|
68
68
|
}
|
|
69
|
-
const
|
|
69
|
+
const extendedExposureUSD =
|
|
70
70
|
extendedPosition.length > 0
|
|
71
|
-
? new Web3Number(extendedPosition[0].
|
|
71
|
+
? new Web3Number(extendedPosition[0].value, WBTC_TOKEN_DECIMALS)
|
|
72
72
|
: new Web3Number(0, WBTC_TOKEN_DECIMALS);
|
|
73
|
-
const extendedExposureUSD =
|
|
74
|
-
extendedBTCExposure.multipliedBy(collateralPrice);
|
|
75
73
|
const vesuBTCExposureUSD = collateralUnits.multipliedBy(collateralPrice);
|
|
76
74
|
const numerator1 = vesu_leverage * amount + vesuBTCExposureUSD.toNumber();
|
|
77
75
|
const numerator2 = extendedExposureUSD.toNumber();
|
|
@@ -71,7 +71,6 @@ export class VesuExtendedMultiplierStrategy<
|
|
|
71
71
|
>
|
|
72
72
|
extends SVKStrategy<S>
|
|
73
73
|
implements Operations {
|
|
74
|
-
|
|
75
74
|
constructor(
|
|
76
75
|
config: IConfig,
|
|
77
76
|
pricer: PricerBase,
|
|
@@ -108,7 +107,7 @@ export class VesuExtendedMultiplierStrategy<
|
|
|
108
107
|
debtPrice,
|
|
109
108
|
};
|
|
110
109
|
}
|
|
111
|
-
|
|
110
|
+
|
|
112
111
|
async getUnusedBalanceUSDCE(): Promise<SingleTokenInfo> {
|
|
113
112
|
const usdceToken = Global.getDefaultTokens().find(
|
|
114
113
|
(token) => token.symbol === "USDCe"
|
|
@@ -238,8 +237,8 @@ export class VesuExtendedMultiplierStrategy<
|
|
|
238
237
|
const balance = await this.getUnusedBalance();
|
|
239
238
|
const usdcBalanceOnExtended = await extendedAdapter.getExtendedDepositAmount();
|
|
240
239
|
/** The LIMIT_BALANCE is the bffer amount to keep in the investing Cycle */
|
|
241
|
-
const amountToInvest = balance.
|
|
242
|
-
|
|
240
|
+
const amountToInvest = new Web3Number(balance.usdValue, USDC_TOKEN_DECIMALS).plus(usdcBalanceOnExtended?.availableForWithdrawal ?? 0).multipliedBy(1 - LIMIT_BALANCE);
|
|
241
|
+
logger.info(`${VesuExtendedMultiplierStrategy.name}::shouldInvest amountToInvest: ${amountToInvest.toNumber()}`);
|
|
243
242
|
if (amountToInvest.lessThan(0)) {
|
|
244
243
|
return {
|
|
245
244
|
shouldInvest: false,
|
|
@@ -301,6 +300,7 @@ export class VesuExtendedMultiplierStrategy<
|
|
|
301
300
|
vesuLeverage: 0,
|
|
302
301
|
};
|
|
303
302
|
}
|
|
303
|
+
logger.info(`${VesuExtendedMultiplierStrategy.name}::shouldInvest vesu_amount: ${vesu_amount.toNumber()}, extended_amount: ${extended_amount.toNumber()}`);
|
|
304
304
|
return {
|
|
305
305
|
shouldInvest: true,
|
|
306
306
|
vesuAmount: vesu_amount,
|
|
@@ -335,7 +335,7 @@ export class VesuExtendedMultiplierStrategy<
|
|
|
335
335
|
);
|
|
336
336
|
return calls;
|
|
337
337
|
}
|
|
338
|
-
if (extendedAmount.
|
|
338
|
+
if (extendedAmount.isNegative() && extendedAmount.abs().greaterThan(extendedAdapter.minimumExtendedMovementAmount)) {
|
|
339
339
|
try {
|
|
340
340
|
const { calls: extendedCalls, status: extendedStatus } = await this.moveAssets(
|
|
341
341
|
{
|
|
@@ -357,7 +357,7 @@ export class VesuExtendedMultiplierStrategy<
|
|
|
357
357
|
}
|
|
358
358
|
}
|
|
359
359
|
|
|
360
|
-
if (vesuAmount.lessThan(
|
|
360
|
+
if (vesuAmount.isNegative() && vesuAmount.lessThan(vesuAdapter.minimumVesuMovementAmount)) {
|
|
361
361
|
try {
|
|
362
362
|
const { calls: vesuCalls, status: vesuStatus } = await this.moveAssets(
|
|
363
363
|
{
|
|
@@ -384,16 +384,16 @@ export class VesuExtendedMultiplierStrategy<
|
|
|
384
384
|
}
|
|
385
385
|
const usdcAmountInWallet = (await this.getUnusedBalance()).amount;
|
|
386
386
|
const usdcAmountOnExtended = parseFloat(
|
|
387
|
-
extendedHoldings.
|
|
387
|
+
extendedHoldings.availableForWithdrawal
|
|
388
388
|
);
|
|
389
|
-
if (extendedAmount.
|
|
389
|
+
if (extendedAmount.minus(usdcAmountOnExtended).greaterThan(extendedAdapter.minimumExtendedMovementAmount)) {
|
|
390
390
|
//move assets to extended
|
|
391
391
|
try {
|
|
392
392
|
const { calls: extendedCalls } = await this.moveAssets(
|
|
393
393
|
{
|
|
394
394
|
to: Protocols.EXTENDED.name,
|
|
395
395
|
from: Protocols.VAULT.name,
|
|
396
|
-
amount: extendedAmount.
|
|
396
|
+
amount: extendedAmount.minus(usdcAmountOnExtended),
|
|
397
397
|
},
|
|
398
398
|
extendedAdapter,
|
|
399
399
|
vesuAdapter
|
|
@@ -403,7 +403,7 @@ export class VesuExtendedMultiplierStrategy<
|
|
|
403
403
|
logger.error(`Failed moving assets to extended: ${err}`);
|
|
404
404
|
}
|
|
405
405
|
}
|
|
406
|
-
if (vesuAmount.minus(usdcAmountInWallet).greaterThan(
|
|
406
|
+
if (vesuAmount.minus(usdcAmountInWallet).greaterThan(vesuAdapter.minimumVesuMovementAmount)) {
|
|
407
407
|
//move assets to vesu
|
|
408
408
|
try {
|
|
409
409
|
const { calls: vesuCalls, status: vesuStatus } = await this.moveAssets(
|
|
@@ -659,7 +659,7 @@ export class VesuExtendedMultiplierStrategy<
|
|
|
659
659
|
};
|
|
660
660
|
}
|
|
661
661
|
const extendedHoldingAmount = new Web3Number(
|
|
662
|
-
extendedHoldings.
|
|
662
|
+
extendedHoldings.availableForWithdrawal,
|
|
663
663
|
USDC_TOKEN_DECIMALS
|
|
664
664
|
);
|
|
665
665
|
const {
|
|
@@ -719,7 +719,7 @@ export class VesuExtendedMultiplierStrategy<
|
|
|
719
719
|
return {
|
|
720
720
|
extendedAmountInBTC: new Web3Number(0, 0),
|
|
721
721
|
calls: [],
|
|
722
|
-
}
|
|
722
|
+
};
|
|
723
723
|
}
|
|
724
724
|
}
|
|
725
725
|
|
|
@@ -912,6 +912,9 @@ function getLooperSettings(
|
|
|
912
912
|
extendedBackendUrl: string,
|
|
913
913
|
extendedApiKey: string,
|
|
914
914
|
vaultIdExtended: number,
|
|
915
|
+
minimumExtendedMovementAmount: number,
|
|
916
|
+
minimumVesuMovementAmount: number,
|
|
917
|
+
minimumExtendedRetriesDelayForOrderStatus: number,
|
|
915
918
|
) {
|
|
916
919
|
vaultSettings.leafAdapters = [];
|
|
917
920
|
|
|
@@ -957,6 +960,8 @@ function getLooperSettings(
|
|
|
957
960
|
extendedMarketName: "BTC-USD",
|
|
958
961
|
extendedPrecision: 5,
|
|
959
962
|
avnuAdapter: avnuAdapter,
|
|
963
|
+
retryDelayForOrderStatus: minimumExtendedRetriesDelayForOrderStatus ?? 3000,
|
|
964
|
+
minimumExtendedMovementAmount: minimumExtendedMovementAmount ?? 5, //5 usdcs
|
|
960
965
|
});
|
|
961
966
|
|
|
962
967
|
const vesuMultiplyAdapter = new VesuMultiplyAdapter({
|
|
@@ -971,6 +976,7 @@ function getLooperSettings(
|
|
|
971
976
|
{ asset: wbtcToken, isDebt: false },
|
|
972
977
|
{ asset: usdcToken, isDebt: true },
|
|
973
978
|
],
|
|
979
|
+
minimumVesuMovementAmount: minimumVesuMovementAmount ?? 5, //5 usdc
|
|
974
980
|
});
|
|
975
981
|
|
|
976
982
|
const unusedBalanceAdapter = new UnusedBalanceAdapter({
|
|
@@ -1104,15 +1110,15 @@ const re7UsdcPrimeDevansh: VesuExtendedStrategySettings = {
|
|
|
1104
1110
|
minimumWBTCDifferenceForAvnuSwap: MINIMUM_WBTC_DIFFERENCE_FOR_AVNU_SWAP,
|
|
1105
1111
|
}
|
|
1106
1112
|
|
|
1107
|
-
export const VesuExtendedTestStrategies = (extendedBackendUrl: string, extendedApiKey: string, vaultIdExtended: number): IStrategyMetadata<VesuExtendedStrategySettings>[] => {
|
|
1113
|
+
export const VesuExtendedTestStrategies = (extendedBackendUrl: string, extendedApiKey: string, vaultIdExtended: number, minimumExtendedMovementAmount: number, minimumVesuMovementAmount: number, minimumExtendedRetriesDelayForOrderStatus: number): IStrategyMetadata<VesuExtendedStrategySettings>[] => {
|
|
1108
1114
|
return [
|
|
1109
|
-
getStrategySettingsVesuExtended('WBTC', 'USDC', re7UsdcPrimeDevansh, false, false, extendedBackendUrl, extendedApiKey, vaultIdExtended),
|
|
1115
|
+
getStrategySettingsVesuExtended('WBTC', 'USDC', re7UsdcPrimeDevansh, false, false, extendedBackendUrl, extendedApiKey, vaultIdExtended, minimumExtendedMovementAmount, minimumVesuMovementAmount, minimumExtendedRetriesDelayForOrderStatus),
|
|
1110
1116
|
]
|
|
1111
1117
|
}
|
|
1112
1118
|
|
|
1113
1119
|
|
|
1114
1120
|
|
|
1115
|
-
function getStrategySettingsVesuExtended(lstSymbol: string, underlyingSymbol: string, addresses: VesuExtendedStrategySettings, isPreview: boolean = false, isLST: boolean, extendedBackendUrl: string, extendedApiKey: string, vaultIdExtended: number): IStrategyMetadata<VesuExtendedStrategySettings> {
|
|
1121
|
+
function getStrategySettingsVesuExtended(lstSymbol: string, underlyingSymbol: string, addresses: VesuExtendedStrategySettings, isPreview: boolean = false, isLST: boolean, extendedBackendUrl: string, extendedApiKey: string, vaultIdExtended: number, minimumExtendedMovementAmount: number, minimumVesuMovementAmount: number, minimumExtendedRetriesDelayForOrderStatus: number): IStrategyMetadata<VesuExtendedStrategySettings> {
|
|
1116
1122
|
return {
|
|
1117
1123
|
name: `Extended Test ${underlyingSymbol}`,
|
|
1118
1124
|
description: getDescription(lstSymbol, underlyingSymbol),
|
|
@@ -1120,7 +1126,7 @@ function getStrategySettingsVesuExtended(lstSymbol: string, underlyingSymbol: st
|
|
|
1120
1126
|
launchBlock: 0,
|
|
1121
1127
|
type: 'Other',
|
|
1122
1128
|
depositTokens: [Global.getDefaultTokens().find(token => token.symbol === underlyingSymbol)!],
|
|
1123
|
-
additionalInfo: getLooperSettings(lstSymbol, underlyingSymbol, addresses, VesuPools.Re7USDCPrime, extendedBackendUrl, extendedApiKey, vaultIdExtended),
|
|
1129
|
+
additionalInfo: getLooperSettings(lstSymbol, underlyingSymbol, addresses, VesuPools.Re7USDCPrime, extendedBackendUrl, extendedApiKey, vaultIdExtended, minimumExtendedMovementAmount, minimumVesuMovementAmount, minimumExtendedRetriesDelayForOrderStatus),
|
|
1124
1130
|
risk: {
|
|
1125
1131
|
riskFactor: _riskFactor,
|
|
1126
1132
|
netRisk:
|