@strkfarm/sdk 1.1.70 → 2.0.0-dev.2

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.
Files changed (53) hide show
  1. package/dist/cli.js +2 -2
  2. package/dist/cli.mjs +2 -2
  3. package/dist/index.browser.global.js +67016 -59681
  4. package/dist/index.browser.mjs +29832 -23221
  5. package/dist/index.d.ts +2006 -787
  6. package/dist/index.js +25403 -18769
  7. package/dist/index.mjs +25333 -18739
  8. package/package.json +80 -76
  9. package/src/data/extended-deposit.abi.json +3613 -0
  10. package/src/data/universal-vault.abi.json +135 -20
  11. package/src/dataTypes/address.ts +7 -0
  12. package/src/global.ts +240 -193
  13. package/src/interfaces/common.tsx +26 -2
  14. package/src/modules/ExtendedWrapperSDk/index.ts +62 -0
  15. package/src/modules/ExtendedWrapperSDk/types.ts +311 -0
  16. package/src/modules/ExtendedWrapperSDk/wrapper.ts +395 -0
  17. package/src/modules/avnu.ts +17 -4
  18. package/src/modules/ekubo-quoter.ts +99 -10
  19. package/src/modules/erc20.ts +67 -21
  20. package/src/modules/harvests.ts +16 -29
  21. package/src/modules/index.ts +5 -1
  22. package/src/modules/lst-apr.ts +36 -0
  23. package/src/modules/midas.ts +159 -0
  24. package/src/modules/pricer-from-api.ts +2 -2
  25. package/src/modules/pricer-lst.ts +1 -1
  26. package/src/modules/pricer.ts +3 -38
  27. package/src/modules/token-market-data.ts +202 -0
  28. package/src/node/deployer.ts +1 -36
  29. package/src/strategies/autoCompounderStrk.ts +1 -1
  30. package/src/strategies/base-strategy.ts +20 -3
  31. package/src/strategies/ekubo-cl-vault.tsx +123 -306
  32. package/src/strategies/index.ts +4 -1
  33. package/src/strategies/svk-strategy.ts +247 -0
  34. package/src/strategies/universal-adapters/adapter-optimizer.ts +65 -0
  35. package/src/strategies/universal-adapters/adapter-utils.ts +5 -1
  36. package/src/strategies/universal-adapters/avnu-adapter.ts +411 -0
  37. package/src/strategies/universal-adapters/baseAdapter.ts +181 -153
  38. package/src/strategies/universal-adapters/common-adapter.ts +98 -77
  39. package/src/strategies/universal-adapters/extended-adapter.ts +661 -0
  40. package/src/strategies/universal-adapters/index.ts +5 -1
  41. package/src/strategies/universal-adapters/unused-balance-adapter.ts +109 -0
  42. package/src/strategies/universal-adapters/vesu-adapter.ts +220 -218
  43. package/src/strategies/universal-adapters/vesu-multiply-adapter.ts +924 -0
  44. package/src/strategies/universal-adapters/vesu-supply-only-adapter.ts +58 -51
  45. package/src/strategies/universal-lst-muliplier-strategy.tsx +707 -774
  46. package/src/strategies/universal-strategy.tsx +1098 -1180
  47. package/src/strategies/vesu-extended-strategy/services/operationService.ts +34 -0
  48. package/src/strategies/vesu-extended-strategy/utils/config.runtime.ts +77 -0
  49. package/src/strategies/vesu-extended-strategy/utils/constants.ts +49 -0
  50. package/src/strategies/vesu-extended-strategy/utils/helper.ts +376 -0
  51. package/src/strategies/vesu-extended-strategy/vesu-extended-strategy.tsx +1134 -0
  52. package/src/strategies/vesu-rebalance.tsx +16 -19
  53. package/src/utils/health-factor-math.ts +11 -5
@@ -0,0 +1,661 @@
1
+ import { BaseAdapter, DepositParams, WithdrawParams, BaseAdapterConfig } from "./baseAdapter";
2
+ import { Protocols } from "@/interfaces";
3
+ import { SupportedPosition } from "./baseAdapter";
4
+ import { PositionAPY, APYType, PositionAmount } from "./baseAdapter";
5
+ import { Web3Number } from "@/dataTypes";
6
+ import { PositionInfo } from "./baseAdapter";
7
+ import { ManageCall } from "./baseAdapter";
8
+ import { ContractAddr } from "@/dataTypes";
9
+ import { AVNU_EXCHANGE_FOR_LEGACY_USDC } from "./adapter-utils";
10
+ import { StandardMerkleTree } from "@/utils";
11
+ import { hash, uint256 } from "starknet";
12
+ import { Global } from "@/global";
13
+ import { AdapterLeafType, GenerateCallFn } from "./baseAdapter";
14
+ import { AVNU_LEGACY_SANITIZER, EXTENDED_SANITIZER, SIMPLE_SANITIZER, toBigInt } from "./adapter-utils";
15
+ import ExtendedWrapper, {
16
+ AssetOperationStatus,
17
+ AssetOperationType,
18
+ FundingRate,
19
+ OrderSide,
20
+ Position,
21
+ TimeInForce,
22
+ } from "@/modules/ExtendedWrapperSDk";
23
+ import { Balance, OpenOrder, OrderStatus } from "@/modules/ExtendedWrapperSDk";
24
+ import axios from "axios";
25
+ import { AvnuAdapter } from "./avnu-adapter";
26
+ import { logger } from "@/utils";
27
+ export interface ExtendedAdapterConfig extends BaseAdapterConfig {
28
+ vaultIdExtended: number;
29
+ extendedContract: ContractAddr; //0x04270219d365d6b017231b52e92b3fb5d7c8378b05e9abc97724537a80e93b0f
30
+ extendedBackendUrl: string;
31
+ extendedApiKey: string;
32
+ extendedTimeout: number;
33
+ extendedRetries: number;
34
+ extendedBaseUrl: string;
35
+ extendedMarketName: string;
36
+ extendedPrecision: number;
37
+ avnuAdapter: AvnuAdapter;
38
+ }
39
+
40
+ export class ExtendedAdapter extends BaseAdapter<
41
+ DepositParams,
42
+ WithdrawParams
43
+ > {
44
+ readonly config: ExtendedAdapterConfig;
45
+ readonly client: ExtendedWrapper;
46
+
47
+ constructor(config: ExtendedAdapterConfig) {
48
+ super(config, ExtendedAdapter.name, Protocols.EXTENDED);
49
+ this.config = config as ExtendedAdapterConfig;
50
+ const client = new ExtendedWrapper({
51
+ baseUrl: this.config.extendedBackendUrl,
52
+ apiKey: this.config.extendedApiKey,
53
+ timeout: this.config.extendedTimeout,
54
+ retries: this.config.extendedRetries,
55
+ });
56
+ this.client = client;
57
+ }
58
+ //abstract means the method has no implementation in this class; instead, child classes must implement it.
59
+ protected async getAPY(
60
+ supportedPosition: SupportedPosition
61
+ ): Promise<PositionAPY> {
62
+ /** Considering supportedPosiiton.isDebt as side parameter to get the funding rates */
63
+ const side = supportedPosition.isDebt ? "LONG" : "SHORT";
64
+ const fundingRates = await this.client.getFundingRates(this.config.extendedMarketName, side);
65
+ if (fundingRates.status !== "OK") {
66
+ logger.error("error getting funding rates", fundingRates);
67
+ return { apy: 0, type: APYType.BASE };
68
+ }
69
+ const fundingRate:FundingRate = fundingRates.data[0];
70
+ const apy = Number(fundingRate.f) * 365 * 24;
71
+ return { apy: apy, type: APYType.BASE };
72
+ }
73
+
74
+ protected async getPosition(
75
+ supportedPosition: SupportedPosition
76
+ ): Promise<PositionAmount> {
77
+ if (!this.client) {
78
+ throw new Error("Client not initialized");
79
+ }
80
+ const holdings = await this.getExtendedDepositAmount();
81
+ if (!holdings) {
82
+ throw new Error("No position found");
83
+ }
84
+ // equity is the total amount on extended
85
+ const amount = holdings.equity;
86
+ return Promise.resolve({
87
+ amount: new Web3Number(amount, 0),
88
+ remarks: `${holdings.availableForWithdrawal} ${holdings.equity}`,
89
+ });
90
+ }
91
+
92
+ async maxDeposit(amount?: Web3Number): Promise<PositionInfo> {
93
+ return Promise.resolve({
94
+ tokenInfo: this.config.baseToken,
95
+ amount: new Web3Number(0, 0),
96
+ usdValue: 0,
97
+ apy: { apy: 0, type: APYType.BASE },
98
+ protocol: Protocols.EXTENDED,
99
+ remarks: "",
100
+ });
101
+ }
102
+
103
+ async maxWithdraw(): Promise<PositionInfo> {
104
+ return Promise.resolve({
105
+ tokenInfo: this.config.baseToken,
106
+ amount: new Web3Number(0, 0),
107
+ usdValue: 0,
108
+ apy: { apy: 0, type: APYType.BASE },
109
+ protocol: Protocols.EXTENDED,
110
+ remarks: "",
111
+ });
112
+ }
113
+
114
+ protected _getDepositLeaf(): {
115
+ target: ContractAddr;
116
+ method: string;
117
+ packedArguments: bigint[];
118
+ sanitizer: ContractAddr;
119
+ id: string;
120
+ }[] {
121
+ const usdceToken = Global.getDefaultTokens().find(token => token.symbol === "USDCe");
122
+ return [
123
+ {
124
+ target: this.config.supportedPositions[0].asset.address,
125
+ method: "approve",
126
+ packedArguments: [
127
+ AVNU_EXCHANGE_FOR_LEGACY_USDC.toBigInt(),
128
+ ],
129
+ id: `extended_approve_${this.config.supportedPositions[0].asset.symbol}`,
130
+ sanitizer: AVNU_LEGACY_SANITIZER,
131
+ },
132
+ {
133
+ target: AVNU_EXCHANGE_FOR_LEGACY_USDC,
134
+ method: "swap_to_legacy",
135
+ packedArguments: [],
136
+ id: `extended_swap_to_legacy_${this.config.supportedPositions[0].asset.symbol}`,
137
+ sanitizer: AVNU_LEGACY_SANITIZER,
138
+ },
139
+ {
140
+ target: usdceToken!.address,
141
+ method: "approve",
142
+ packedArguments: [this.config.extendedContract.toBigInt()],
143
+ id: `extended_approve_${usdceToken!.symbol}`,
144
+ sanitizer: SIMPLE_SANITIZER,
145
+ },
146
+ {
147
+ target: this.config.extendedContract,
148
+ method: "deposit",
149
+ packedArguments: [BigInt(this.config.vaultIdExtended)],
150
+ sanitizer: EXTENDED_SANITIZER,
151
+ id: `extended_deposit_${usdceToken!.symbol}`,
152
+ },
153
+ ];
154
+ }
155
+
156
+ getSwapFromLegacyLeaf(): AdapterLeafType<DepositParams> {
157
+ const leafConfigs = this._getSwapFromLegacyLeaf();
158
+ const leaves = leafConfigs.map(config => {
159
+ const { target, method, packedArguments, sanitizer, id } = config;
160
+ const leaf = this.constructSimpleLeafData({
161
+ id: id,
162
+ target,
163
+ method,
164
+ packedArguments
165
+ }, sanitizer);
166
+ return leaf;
167
+ });
168
+ return { leaves, callConstructor: this.getSwapFromLegacyCall.bind(this) as unknown as GenerateCallFn<DepositParams> };
169
+ }
170
+
171
+ protected _getSwapFromLegacyLeaf(): {
172
+ target: ContractAddr;
173
+ method: string;
174
+ packedArguments: bigint[];
175
+ sanitizer: ContractAddr;
176
+ id: string;
177
+ }[] {
178
+ const usdceToken = Global.getDefaultTokens().find(token => token.symbol === "USDCe");
179
+ return [
180
+ {
181
+ target: usdceToken!.address,
182
+ method: "approve",
183
+ packedArguments: [
184
+ AVNU_EXCHANGE_FOR_LEGACY_USDC.toBigInt(),
185
+ ],
186
+ id: `extendedswaplegacyapprove_${usdceToken!.symbol}`,
187
+ sanitizer: AVNU_LEGACY_SANITIZER,
188
+ },
189
+ {
190
+ target: AVNU_EXCHANGE_FOR_LEGACY_USDC,
191
+ method: "swap_to_new",
192
+ packedArguments: [],
193
+ id: `extended_swap_to_new_${usdceToken!.symbol}`,
194
+ sanitizer: AVNU_LEGACY_SANITIZER,
195
+ },
196
+ ]
197
+ }
198
+
199
+
200
+ protected _getWithdrawLeaf(): {
201
+ target: ContractAddr;
202
+ method: string;
203
+ packedArguments: bigint[];
204
+ sanitizer: ContractAddr;
205
+ id: string;
206
+ }[] {
207
+ /**
208
+ * Withdraw is done via extended wrapper
209
+ */
210
+ return [];
211
+ }
212
+
213
+ async getDepositCall(params: DepositParams): Promise<ManageCall[]> {
214
+ try {
215
+ const usdcToken = this.config.supportedPositions[0].asset;
216
+ const usdceToken = Global.getDefaultTokens().find(token => token.symbol === "USDCe");
217
+ const salt = Math.floor(
218
+ Math.random() * 10 ** usdcToken.decimals
219
+ );
220
+ // Give approval for more amount than the required amount
221
+ const amount = uint256.bnToUint256(params.amount.multipliedBy(10).toWei());
222
+ const quotes = await this.config.avnuAdapter.getQuotesAvnu(
223
+ usdcToken.address.toString(),
224
+ usdceToken!.address.toString(),
225
+ params.amount.toNumber(),
226
+ this.config.avnuAdapter.config.vaultAllocator.address.toString(),
227
+ usdceToken!.decimals,
228
+ false
229
+ )
230
+
231
+ if (!quotes) {
232
+ logger.error("error getting quotes from avnu");
233
+ return [];
234
+ }
235
+ const getCalldata = await this.config.avnuAdapter.getSwapCallData(quotes!);
236
+ const swapCallData = getCalldata[0];
237
+ //change extended sanitizer here
238
+ return [
239
+ {
240
+ sanitizer: AVNU_LEGACY_SANITIZER,
241
+ call: {
242
+ contractAddress: usdcToken.address,
243
+ selector: hash.getSelectorFromName("approve"),
244
+ calldata: [
245
+ AVNU_EXCHANGE_FOR_LEGACY_USDC.toBigInt(),
246
+ toBigInt(amount.low.toString()), // amount low
247
+ toBigInt(amount.high.toString()), // amount high
248
+ ],
249
+ },
250
+ },
251
+ {
252
+ sanitizer: AVNU_LEGACY_SANITIZER,
253
+ call: {
254
+ contractAddress: AVNU_EXCHANGE_FOR_LEGACY_USDC,
255
+ selector: hash.getSelectorFromName("swap_to_legacy"),
256
+ calldata: swapCallData,
257
+ },
258
+ },
259
+ {
260
+ sanitizer: SIMPLE_SANITIZER,
261
+ call: {
262
+ contractAddress: usdceToken!.address,
263
+ selector: hash.getSelectorFromName("approve"),
264
+ calldata: [
265
+ this.config.extendedContract.toBigInt(),
266
+ toBigInt(amount.low.toString()), // amount low
267
+ toBigInt(amount.high.toString()), // amount high
268
+ ],
269
+ },
270
+ },
271
+ {
272
+ sanitizer: EXTENDED_SANITIZER,
273
+ call: {
274
+ contractAddress: this.config.extendedContract,
275
+ selector: hash.getSelectorFromName("deposit"),
276
+ calldata: [
277
+ BigInt(this.config.vaultIdExtended),
278
+ BigInt(params.amount.toWei()),
279
+ BigInt(salt),
280
+ ],
281
+ },
282
+ },
283
+ ];
284
+ } catch (error) {
285
+ logger.error(`Error creating Deposit Call: ${error}`);
286
+ return [];
287
+ }
288
+ }
289
+
290
+ getProofsForFromLegacySwap<T>(tree: StandardMerkleTree): { proofs: string[][], callConstructor: GenerateCallFn<DepositParams> | GenerateCallFn<WithdrawParams> } {
291
+ let proofGroups: string[][] = [];
292
+
293
+ const ids = this.getSwapFromLegacyLeaf().leaves.map(l => l.readableId)
294
+ // console.log(`${this.name}::getProofs ids: ${ids}`);
295
+ for (const [i, v] of tree.entries()) {
296
+ // console.log(`${this.name}::getProofs v: ${v.readableId}`);
297
+ if (ids.includes(v.readableId)) {
298
+ //console.log(`${this.name}::getProofs found id: ${v.readableId}`);
299
+ proofGroups.push(tree.getProof(i));
300
+ }
301
+ }
302
+ if (proofGroups.length != ids.length) {
303
+ throw new Error(`Not all proofs found for IDs: ${ids.join(', ')}`);
304
+ }
305
+
306
+ // find leaf adapter
307
+ return {
308
+ proofs: proofGroups,
309
+ callConstructor: this.getSwapFromLegacyCall.bind(this)
310
+ };
311
+ }
312
+
313
+ async getSwapFromLegacyCall(params: DepositParams): Promise<ManageCall[]> {
314
+ try {
315
+ const usdcToken = this.config.supportedPositions[0].asset;
316
+ const usdceToken = Global.getDefaultTokens().find(token => token.symbol === "USDCe");
317
+ // Give approval for more amount than the required amount
318
+ const amount = uint256.bnToUint256(params.amount.multipliedBy(10).toWei());
319
+ const quotes = await this.config.avnuAdapter.getQuotesAvnu(
320
+ usdceToken!.address.toString(),
321
+ usdcToken!.address.toString(),
322
+ params.amount.toNumber(),
323
+ this.config.avnuAdapter.config.vaultAllocator.address.toString(),
324
+ usdcToken!.decimals,
325
+ false
326
+ )
327
+
328
+ if (!quotes) {
329
+ logger.error("error getting quotes from avnu");
330
+ return [];
331
+ }
332
+ const getCalldata = await this.config.avnuAdapter.getSwapCallData(quotes!);
333
+ const swapCallData = getCalldata[0];
334
+ //change extended sanitizer here
335
+ return [
336
+ {
337
+ sanitizer: AVNU_LEGACY_SANITIZER,
338
+ call: {
339
+ contractAddress: usdceToken!.address,
340
+ selector: hash.getSelectorFromName("approve"),
341
+ calldata: [
342
+ AVNU_EXCHANGE_FOR_LEGACY_USDC.toBigInt(),
343
+ toBigInt(amount.low.toString()), // amount low
344
+ toBigInt(amount.high.toString()), // amount high
345
+ ],
346
+ },
347
+ },
348
+ {
349
+ sanitizer: AVNU_LEGACY_SANITIZER,
350
+ call: {
351
+ contractAddress: AVNU_EXCHANGE_FOR_LEGACY_USDC,
352
+ selector: hash.getSelectorFromName("swap_to_new"),
353
+ calldata: swapCallData,
354
+ },
355
+ }
356
+ ];
357
+ } catch (error) {
358
+ logger.error(`Error creating Deposit Call: ${error}`);
359
+ return [];
360
+ }
361
+ }
362
+ //Swap wbtc to usdc
363
+ async getWithdrawCall(params: WithdrawParams): Promise<ManageCall[]> {
364
+ try {
365
+ if (!this.client) {
366
+ throw new Error("Client not initialized");
367
+ }
368
+ return [];
369
+ } catch (error) {
370
+ logger.error(`Error creating Withdraw Call: ${error}`);
371
+ return [];
372
+ }
373
+ }
374
+
375
+ async withdrawFromExtended(amount: Web3Number): Promise<boolean> {
376
+ try {
377
+ if (!this.client) {
378
+ throw new Error("Client not initialized");
379
+ }
380
+ const withdrawalRequest = await this.client.withdrawUSDC(amount.toFixed(2));
381
+ if (withdrawalRequest.status === "OK") {
382
+ const withdrawalStatus = await this.getDepositOrWithdrawalStatus(withdrawalRequest.data, AssetOperationType.WITHDRAWAL);
383
+ return withdrawalStatus;
384
+ }
385
+ return false;
386
+ } catch (error) {
387
+ logger.error(`Error creating Withdraw Call: ${error}`);
388
+ return false;
389
+ }
390
+ }
391
+
392
+ async getHealthFactor(): Promise<number> {
393
+ return Promise.resolve(1);
394
+ }
395
+
396
+ async getExtendedDepositAmount(): Promise<Balance | undefined> {
397
+ if (this.client === null) {
398
+ logger.error("error initializing client");
399
+ return undefined;
400
+ }
401
+ const result = await this.client.getHoldings();
402
+ if (!result) {
403
+ logger.error(`error getting holdings: ${result}`);
404
+ return undefined;
405
+ }
406
+ const holdings = result.data;
407
+ if (!holdings) {
408
+ logger.error(`error getting holdings: ${holdings}`);
409
+ return undefined;
410
+ }
411
+ return holdings;
412
+ }
413
+
414
+ async setLeverage(leverage: string, marketName: string): Promise<boolean> {
415
+ if (this.client === null) {
416
+ logger.error("error initializing client");
417
+ return false;
418
+ }
419
+ const res = await this.client.updateLeverage({
420
+ leverage: leverage,
421
+ market: marketName,
422
+ });
423
+ if (res.status === "OK") {
424
+ return true;
425
+ }
426
+ return false;
427
+ }
428
+
429
+ async getAllOpenPositions(): Promise<Position[] | null> {
430
+ if (this.client === null) {
431
+ logger.error("error initializing client");
432
+ return null;
433
+ }
434
+ const response = await this.client.getPositionsForMarket(
435
+ this.config.extendedMarketName
436
+ );
437
+ if (response.status === "OK") {
438
+ if (response.data.length === 0) {
439
+ return [];
440
+ } else {
441
+ return response.data;
442
+ }
443
+ }
444
+ return null;
445
+ }
446
+
447
+ async getOrderHistory(marketName: string): Promise<OpenOrder[] | null> {
448
+ if (this.client === null) {
449
+ logger.error("error initializing client");
450
+ return null;
451
+ }
452
+ const result = await this.client.getOrderHistory(marketName);
453
+ return result.data;
454
+ }
455
+
456
+ async getOrderStatus(
457
+ orderId: string,
458
+ marketName: string
459
+ ): Promise<OpenOrder | null> {
460
+ if (this.client === null) {
461
+ logger.error("error initializing client");
462
+ return null;
463
+ }
464
+ const orderhistory = await this.getOrderHistory(marketName);
465
+
466
+ if (!orderhistory || orderhistory.length === 0) {
467
+ logger.error(`error getting order: ${orderId}`);
468
+ return null;
469
+ }
470
+ const order = orderhistory
471
+ .slice(0, 3)
472
+ .find((order) => order.id.toString() === orderId);
473
+ if (!order) {
474
+ logger.error(`error getting order: ${order}`);
475
+ return null;
476
+ }
477
+ return order;
478
+ }
479
+
480
+ async fetchOrderBookBTCUSDC(): Promise<{
481
+ status: boolean;
482
+ bid: Web3Number;
483
+ ask: Web3Number;
484
+ }> {
485
+ try {
486
+ const res = await axios.get(
487
+ `${this.config.extendedBaseUrl}/api/v1/info/markets/${this.config.extendedMarketName}/orderbook`
488
+ );
489
+ let ask_price = new Web3Number(0, 0);
490
+ let bid_price = new Web3Number(0, 0);
491
+ if (res.data.status !== "OK") {
492
+ return {
493
+ status: false,
494
+ bid: bid_price,
495
+ ask: ask_price,
496
+ };
497
+ }
498
+ const data = res.data.data;
499
+ const bid = data.bid[0];
500
+ const ask = data.ask[0];
501
+ ask_price = new Web3Number(ask.price, 0);
502
+ bid_price = new Web3Number(bid.price, 0);
503
+
504
+ return {
505
+ status: false,
506
+ bid: bid_price, // check for quantity as well, not at the moment though
507
+ ask: ask_price, // check for quantity as well, not at the moment though
508
+ };
509
+ } catch (err) {
510
+ logger.error(`the err is: ${err}`);
511
+ return {
512
+ status: false,
513
+ bid: new Web3Number(0, 0),
514
+ ask: new Web3Number(0, 0),
515
+ };
516
+ }
517
+ }
518
+
519
+ async createOrder(
520
+ leverage: string,
521
+ btcAmount: number,
522
+ side: OrderSide,
523
+ attempt = 1,
524
+ maxAttempts = 5
525
+ ): Promise<{ position_id: string; btc_exposure: string } | null> {
526
+ try {
527
+ if (this.client === null) {
528
+ logger.error("error initializing client");
529
+ return null;
530
+ }
531
+ const setLeverage = await this.setLeverage(
532
+ leverage,
533
+ this.config.extendedMarketName
534
+ );
535
+ if (!setLeverage) {
536
+ logger.error("error depositing or setting leverage");
537
+ return null;
538
+ }
539
+ const positions = await this.getAllOpenPositions();
540
+ if (positions === null) {
541
+ return null;
542
+ }
543
+ const { ask, bid } = await this.fetchOrderBookBTCUSDC();
544
+ const spread = ask.minus(bid);
545
+ let price = ask
546
+ .plus(bid)
547
+ .div(2)
548
+ side === OrderSide.SELL ? price = price.minus(spread.times(0.2 * attempt)) : price = price.plus(spread.times(0.2 * attempt));
549
+ const amount_in_token = (btcAmount * parseInt(leverage)).toFixed(
550
+ this.config.extendedPrecision
551
+ ); // gives the amount of wbtc
552
+
553
+ const result = await this.createExtendedPositon(
554
+ this.client,
555
+ this.config.extendedMarketName,
556
+ amount_in_token,
557
+ price.toFixed(0),
558
+ side
559
+ );
560
+ if (!result) {
561
+ return null;
562
+ }
563
+ await new Promise((resolve) => setTimeout(resolve, 5000));
564
+ const openOrder = await this.getOrderStatus(result.position_id, this.config.extendedMarketName);
565
+ if (!openOrder || openOrder.status !== OrderStatus.FILLED) {
566
+ if (attempt >= maxAttempts) {
567
+ logger.error("Max retries reached — could not verify open position");
568
+ return null;
569
+ } else {
570
+ const backoff = 2000 * attempt;
571
+ await new Promise((resolve) => setTimeout(resolve, backoff));
572
+ return this.createOrder(
573
+ leverage,
574
+ btcAmount,
575
+ side,
576
+ attempt + 1,
577
+ maxAttempts
578
+ );
579
+ }
580
+ } else {
581
+ return {
582
+ position_id: result.position_id,
583
+ btc_exposure: openOrder.qty,
584
+ };
585
+ }
586
+ } catch (err: any) {
587
+ logger.error(`createShortOrder failed on attempt ${attempt}: ${err.message}`);
588
+
589
+ if (attempt < maxAttempts) {
590
+ const backoff = 1200 * attempt;
591
+ logger.info(`Retrying after ${backoff}ms...`);
592
+ await new Promise((resolve) => setTimeout(resolve, backoff));
593
+ return this.createOrder(
594
+ leverage,
595
+ btcAmount,
596
+ side,
597
+ attempt + 1,
598
+ maxAttempts
599
+ );
600
+ }
601
+ logger.error("Max retry attempts reached — aborting createShortOrder");
602
+ return null;
603
+ }
604
+ }
605
+
606
+ async createExtendedPositon(
607
+ client: ExtendedWrapper,
608
+ marketName: string,
609
+ amount: string,
610
+ price: string,
611
+ side: OrderSide
612
+ ) {
613
+ try {
614
+ const result =
615
+ side === OrderSide.SELL
616
+ ? await client.createSellOrder(marketName, amount, price, {
617
+ postOnly: false,
618
+ timeInForce: TimeInForce.IOC,
619
+ })
620
+ : await client.createBuyOrder(marketName, amount, price, {
621
+ postOnly: false,
622
+ timeInForce: TimeInForce.IOC,
623
+ });
624
+ if (result.data.id) {
625
+ const position_id = result.data.id.toString();
626
+ return {
627
+ position_id,
628
+ };
629
+ }
630
+ return null;
631
+ } catch (err) {
632
+ logger.error(`Error opening short extended position, ${err}`);
633
+ return null;
634
+ }
635
+ }
636
+
637
+ async getDepositOrWithdrawalStatus(orderId: number | string, operationsType: AssetOperationType): Promise<boolean> {
638
+ try{
639
+ let transferHistory = await this.client.getAssetOperations({
640
+ operationsType:[operationsType],
641
+ operationsStatus:[AssetOperationStatus.COMPLETED]
642
+ })
643
+ if(operationsType === AssetOperationType.DEPOSIT){
644
+ const myTransferStatus = transferHistory.data.find(operation => operation.transactionHash === orderId);
645
+ if (!myTransferStatus) {
646
+ return true;
647
+ }
648
+ return true;
649
+ }else{
650
+ const myTransferStatus = transferHistory.data.find(operation => operation.id.toString() === orderId.toString());
651
+ if (!myTransferStatus) {
652
+ return true;
653
+ }
654
+ return true;
655
+ }
656
+ }catch(err){
657
+ logger.error(`error getting deposit or withdrawal status: ${err}`);
658
+ return false;
659
+ }
660
+ }
661
+ }
@@ -1,4 +1,8 @@
1
1
  export * from "./baseAdapter";
2
2
  export * from "./common-adapter";
3
3
  export * from "./vesu-adapter";
4
- export * from "./adapter-utils";
4
+ export * from "./vesu-supply-only-adapter";
5
+ export * from "./vesu-multiply-adapter";
6
+ export * from "./extended-adapter";
7
+ export * from "./adapter-utils";
8
+ export * from "./unused-balance-adapter";