@strkfarm/sdk 2.0.0-dev.27 → 2.0.0-dev.28

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 (70) hide show
  1. package/dist/cli.js +190 -36
  2. package/dist/cli.mjs +188 -34
  3. package/dist/index.browser.global.js +79130 -49357
  4. package/dist/index.browser.mjs +18039 -11434
  5. package/dist/index.d.ts +2869 -898
  6. package/dist/index.js +19036 -12210
  7. package/dist/index.mjs +18942 -12161
  8. package/package.json +1 -1
  9. package/src/data/avnu.abi.json +840 -0
  10. package/src/data/ekubo-price-fethcer.abi.json +265 -0
  11. package/src/dataTypes/_bignumber.ts +13 -4
  12. package/src/dataTypes/index.ts +3 -2
  13. package/src/dataTypes/mynumber.ts +141 -0
  14. package/src/global.ts +76 -41
  15. package/src/index.browser.ts +2 -1
  16. package/src/interfaces/common.tsx +167 -2
  17. package/src/modules/ExtendedWrapperSDk/types.ts +26 -4
  18. package/src/modules/ExtendedWrapperSDk/wrapper.ts +110 -67
  19. package/src/modules/apollo-client-config.ts +28 -0
  20. package/src/modules/avnu.ts +4 -4
  21. package/src/modules/ekubo-pricer.ts +79 -0
  22. package/src/modules/ekubo-quoter.ts +46 -30
  23. package/src/modules/erc20.ts +17 -0
  24. package/src/modules/harvests.ts +43 -29
  25. package/src/modules/pragma.ts +23 -8
  26. package/src/modules/pricer-from-api.ts +156 -15
  27. package/src/modules/pricer-lst.ts +1 -1
  28. package/src/modules/pricer.ts +40 -4
  29. package/src/modules/pricerBase.ts +2 -1
  30. package/src/node/deployer.ts +36 -1
  31. package/src/node/pricer-redis.ts +2 -1
  32. package/src/strategies/base-strategy.ts +78 -10
  33. package/src/strategies/ekubo-cl-vault.tsx +906 -347
  34. package/src/strategies/factory.ts +159 -0
  35. package/src/strategies/index.ts +6 -1
  36. package/src/strategies/registry.ts +239 -0
  37. package/src/strategies/sensei.ts +335 -7
  38. package/src/strategies/svk-strategy.ts +97 -27
  39. package/src/strategies/types.ts +4 -0
  40. package/src/strategies/universal-adapters/adapter-utils.ts +2 -1
  41. package/src/strategies/universal-adapters/avnu-adapter.ts +177 -268
  42. package/src/strategies/universal-adapters/baseAdapter.ts +263 -251
  43. package/src/strategies/universal-adapters/common-adapter.ts +206 -203
  44. package/src/strategies/universal-adapters/extended-adapter.ts +155 -336
  45. package/src/strategies/universal-adapters/index.ts +9 -8
  46. package/src/strategies/universal-adapters/token-transfer-adapter.ts +200 -0
  47. package/src/strategies/universal-adapters/usdc<>usdce-adapter.ts +200 -0
  48. package/src/strategies/universal-adapters/vesu-adapter.ts +110 -75
  49. package/src/strategies/universal-adapters/vesu-modify-position-adapter.ts +476 -0
  50. package/src/strategies/universal-adapters/vesu-multiply-adapter.ts +762 -844
  51. package/src/strategies/universal-adapters/vesu-position-common.ts +251 -0
  52. package/src/strategies/universal-adapters/vesu-supply-only-adapter.ts +18 -3
  53. package/src/strategies/universal-lst-muliplier-strategy.tsx +396 -204
  54. package/src/strategies/universal-strategy.tsx +1426 -1178
  55. package/src/strategies/vesu-extended-strategy/services/executionService.ts +2251 -0
  56. package/src/strategies/vesu-extended-strategy/services/extended-vesu-state-manager.ts +2941 -0
  57. package/src/strategies/vesu-extended-strategy/services/operationService.ts +12 -1
  58. package/src/strategies/vesu-extended-strategy/types/transaction-metadata.ts +52 -0
  59. package/src/strategies/vesu-extended-strategy/utils/config.runtime.ts +1 -0
  60. package/src/strategies/vesu-extended-strategy/utils/constants.ts +2 -0
  61. package/src/strategies/vesu-extended-strategy/utils/helper.ts +158 -124
  62. package/src/strategies/vesu-extended-strategy/vesu-extended-strategy.tsx +377 -1788
  63. package/src/strategies/vesu-rebalance.tsx +255 -152
  64. package/src/utils/health-factor-math.ts +4 -1
  65. package/src/utils/index.ts +2 -1
  66. package/src/utils/logger.browser.ts +22 -4
  67. package/src/utils/logger.node.ts +259 -24
  68. package/src/utils/starknet-call-parser.ts +1036 -0
  69. package/src/utils/strategy-utils.ts +61 -0
  70. package/src/strategies/universal-adapters/unused-balance-adapter.ts +0 -109
@@ -8,14 +8,12 @@ import { Protocols } from "@/interfaces";
8
8
  import { SupportedPosition } from "./baseAdapter";
9
9
  import { PositionAPY, APYType, PositionAmount } from "./baseAdapter";
10
10
  import { Web3Number } from "@/dataTypes";
11
- import { ApiResponse } from "@/modules/ExtendedWrapperSDk";
12
11
  import { PositionInfo } from "./baseAdapter";
13
12
  import { ManageCall } from "./baseAdapter";
14
13
  import { ContractAddr } from "@/dataTypes";
15
14
  import { AVNU_EXCHANGE_FOR_LEGACY_USDC } from "./adapter-utils";
16
15
  import { StandardMerkleTree } from "@/utils";
17
16
  import { hash, uint256 } from "starknet";
18
- import { Global } from "@/global";
19
17
  import { AdapterLeafType, GenerateCallFn } from "./baseAdapter";
20
18
  import {
21
19
  AVNU_LEGACY_SANITIZER,
@@ -35,7 +33,7 @@ import { Balance, OpenOrder, OrderStatus } from "@/modules/ExtendedWrapperSDk";
35
33
  import axios from "axios";
36
34
  import { AvnuAdapter } from "./avnu-adapter";
37
35
  import { logger } from "@/utils";
38
-
36
+ import { TokenInfo } from "@/interfaces";
39
37
 
40
38
  export interface ExtendedAdapterConfig extends BaseAdapterConfig {
41
39
  vaultIdExtended: number;
@@ -58,6 +56,7 @@ export class ExtendedAdapter extends BaseAdapter<
58
56
  > {
59
57
  readonly config: ExtendedAdapterConfig;
60
58
  readonly client: ExtendedWrapper;
59
+ readonly usdceToken: TokenInfo;
61
60
  readonly retryDelayForOrderStatus: number;
62
61
  readonly minimumExtendedMovementAmount: number;
63
62
 
@@ -65,8 +64,9 @@ export class ExtendedAdapter extends BaseAdapter<
65
64
  super(config, ExtendedAdapter.name, Protocols.EXTENDED);
66
65
  this.config = config as ExtendedAdapterConfig;
67
66
  const client = new ExtendedWrapper({
68
- baseUrl: this.config.extendedBackendWriteUrl,
69
- apiKey: "",
67
+ writeUrl: this.config.extendedBackendWriteUrl,
68
+ readUrl: this.config.extendedBackendReadUrl,
69
+ apiKey: "", // todo add auth
70
70
  timeout: this.config.extendedTimeout,
71
71
  retries: this.config.extendedRetries,
72
72
  });
@@ -75,10 +75,19 @@ export class ExtendedAdapter extends BaseAdapter<
75
75
  this.client = client;
76
76
  this.retryDelayForOrderStatus =
77
77
  this.config.retryDelayForOrderStatus ?? 3000;
78
+ this.usdceToken = this.config.supportedPositions[0].asset;
79
+ }
80
+
81
+ private _depositApproveProofReadableId(): string {
82
+ return `extended_approve_${this.usdceToken.symbol}`;
83
+ }
84
+
85
+ private _depositCallProofReadableId(): string {
86
+ return `extended_deposit_${this.usdceToken.symbol}`;
78
87
  }
79
88
  //abstract means the method has no implementation in this class; instead, child classes must implement it.
80
89
  protected async getAPY(
81
- supportedPosition: SupportedPosition
90
+ supportedPosition: SupportedPosition,
82
91
  ): Promise<PositionAPY> {
83
92
  /** Considering supportedPosiiton.isDebt as side parameter to get the funding rates */
84
93
  const side = supportedPosition.isDebt ? "LONG" : "SHORT";
@@ -92,20 +101,26 @@ export class ExtendedAdapter extends BaseAdapter<
92
101
  return { apy: apy, type: APYType.BASE };
93
102
  }
94
103
 
95
- public async getFundingRates(side: string, startTime?: number, endTime?: number): Promise<{ success: boolean, data: FundingRate[] }> {
104
+ public async getFundingRates(
105
+ side: string,
106
+ startTime?: number,
107
+ endTime?: number,
108
+ ): Promise<{ success: boolean; data: FundingRate[] }> {
96
109
  try {
97
- const response = await axios.get<ApiResponse<FundingRate[]>>(`${this.config.extendedBackendReadUrl}/fundingRates/${this.config.extendedMarketName}/${side}`, {
98
- params: {
99
- startTime: startTime ? startTime.toString() : undefined,
100
- endTime: endTime ? endTime.toString() : undefined,
101
- }
102
- });
103
- if (!response.data.success) {
110
+ const response = await this.client.getFundingRates(
111
+ this.config.extendedMarketName,
112
+ side,
113
+ startTime,
114
+ endTime,
115
+ );
116
+ if (response.status !== "OK") {
104
117
  logger.error("error getting funding rates", response.data);
105
118
  return { success: false, data: [] };
106
119
  }
107
- logger.info("success getting funding rates", response.data.data);
108
- return { success: true, data: response.data.data };
120
+ logger.debug(
121
+ `success getting funding rates market=${this.config.extendedMarketName} side=${side} count=${response.data.length}`,
122
+ );
123
+ return { success: true, data: response.data };
109
124
  } catch (err) {
110
125
  logger.error("error getting funding rates", err);
111
126
  return { success: false, data: [] };
@@ -113,9 +128,9 @@ export class ExtendedAdapter extends BaseAdapter<
113
128
  }
114
129
 
115
130
  protected async getPosition(
116
- supportedPosition: SupportedPosition
131
+ supportedPosition: SupportedPosition,
117
132
  ): Promise<PositionAmount> {
118
- const holdings = await this.getExtendedDepositAmount()
133
+ const holdings = await this.getExtendedDepositAmount();
119
134
  if (!holdings) {
120
135
  throw new Error("No position found");
121
136
  }
@@ -156,29 +171,12 @@ export class ExtendedAdapter extends BaseAdapter<
156
171
  sanitizer: ContractAddr;
157
172
  id: string;
158
173
  }[] {
159
- const usdceToken = Global.getDefaultTokens().find(
160
- (token) => token.symbol === "USDCe"
161
- );
162
174
  return [
163
175
  {
164
- target: this.config.supportedPositions[0].asset.address,
165
- method: "approve",
166
- packedArguments: [AVNU_EXCHANGE_FOR_LEGACY_USDC.toBigInt()],
167
- id: `extended_approve_${this.config.supportedPositions[0].asset.symbol}`,
168
- sanitizer: AVNU_LEGACY_SANITIZER,
169
- },
170
- {
171
- target: AVNU_EXCHANGE_FOR_LEGACY_USDC,
172
- method: "swap_to_legacy",
173
- packedArguments: [],
174
- id: `extended_swap_to_legacy_${this.config.supportedPositions[0].asset.symbol}`,
175
- sanitizer: AVNU_LEGACY_SANITIZER,
176
- },
177
- {
178
- target: usdceToken!.address,
176
+ target: this.usdceToken.address,
179
177
  method: "approve",
180
178
  packedArguments: [this.config.extendedContract.toBigInt()],
181
- id: `extended_approve_${usdceToken!.symbol}`,
179
+ id: this._depositApproveProofReadableId(),
182
180
  sanitizer: SIMPLE_SANITIZER,
183
181
  },
184
182
  {
@@ -186,58 +184,7 @@ export class ExtendedAdapter extends BaseAdapter<
186
184
  method: "deposit",
187
185
  packedArguments: [BigInt(this.config.vaultIdExtended)],
188
186
  sanitizer: EXTENDED_SANITIZER,
189
- id: `extended_deposit_${usdceToken!.symbol}`,
190
- },
191
- ];
192
- }
193
-
194
- getSwapFromLegacyLeaf(): AdapterLeafType<DepositParams> {
195
- const leafConfigs = this._getSwapFromLegacyLeaf();
196
- const leaves = leafConfigs.map((config) => {
197
- const { target, method, packedArguments, sanitizer, id } = config;
198
- const leaf = this.constructSimpleLeafData(
199
- {
200
- id: id,
201
- target,
202
- method,
203
- packedArguments,
204
- },
205
- sanitizer
206
- );
207
- return leaf;
208
- });
209
- return {
210
- leaves,
211
- callConstructor: this.getSwapFromLegacyCall.bind(
212
- this
213
- ) as unknown as GenerateCallFn<DepositParams>,
214
- };
215
- }
216
-
217
- protected _getSwapFromLegacyLeaf(): {
218
- target: ContractAddr;
219
- method: string;
220
- packedArguments: bigint[];
221
- sanitizer: ContractAddr;
222
- id: string;
223
- }[] {
224
- const usdceToken = Global.getDefaultTokens().find(
225
- (token) => token.symbol === "USDCe"
226
- );
227
- return [
228
- {
229
- target: usdceToken!.address,
230
- method: "approve",
231
- packedArguments: [AVNU_EXCHANGE_FOR_LEGACY_USDC.toBigInt()],
232
- id: `extendedswaplegacyapprove_${usdceToken!.symbol}`,
233
- sanitizer: AVNU_LEGACY_SANITIZER,
234
- },
235
- {
236
- target: AVNU_EXCHANGE_FOR_LEGACY_USDC,
237
- method: "swap_to_new",
238
- packedArguments: [],
239
- id: `extended_swap_to_new_${usdceToken!.symbol}`,
240
- sanitizer: AVNU_LEGACY_SANITIZER,
187
+ id: this._depositCallProofReadableId(),
241
188
  },
242
189
  ];
243
190
  }
@@ -257,58 +204,14 @@ export class ExtendedAdapter extends BaseAdapter<
257
204
 
258
205
  async getDepositCall(params: DepositParams): Promise<ManageCall[]> {
259
206
  try {
260
- const usdcToken = this.config.supportedPositions[0].asset;
261
- const usdceToken = Global.getDefaultTokens().find(
262
- (token) => token.symbol === "USDCe"
263
- );
264
- const salt = Math.floor(Math.random() * 10 ** usdcToken.decimals);
265
- // Give approval for more amount than the required amount
266
- const amount = uint256.bnToUint256(
267
- params.amount.multipliedBy(10).toWei()
268
- );
269
- const quotes = await this.config.avnuAdapter.getQuotesAvnu(
270
- usdcToken.address.toString(),
271
- usdceToken!.address.toString(),
272
- params.amount.toNumber(),
273
- this.config.avnuAdapter.config.vaultAllocator.address.toString(),
274
- usdceToken!.decimals,
275
- false
276
- );
277
-
278
- if (!quotes) {
279
- logger.error("error getting quotes from avnu");
280
- return [];
281
- }
282
- const getCalldata = await this.config.avnuAdapter.getSwapCallData(
283
- quotes!
284
- );
285
- const swapCallData = getCalldata[0];
286
- //change extended sanitizer here
207
+ const salt = Math.floor(Math.random() * 10 ** this.usdceToken.decimals);
208
+ const amount = uint256.bnToUint256(params.amount.toWei());
287
209
  return [
288
210
  {
289
- sanitizer: AVNU_LEGACY_SANITIZER,
290
- call: {
291
- contractAddress: usdcToken.address,
292
- selector: hash.getSelectorFromName("approve"),
293
- calldata: [
294
- AVNU_EXCHANGE_FOR_LEGACY_USDC.toBigInt(),
295
- toBigInt(amount.low.toString()), // amount low
296
- toBigInt(amount.high.toString()), // amount high
297
- ],
298
- },
299
- },
300
- {
301
- sanitizer: AVNU_LEGACY_SANITIZER,
302
- call: {
303
- contractAddress: AVNU_EXCHANGE_FOR_LEGACY_USDC,
304
- selector: hash.getSelectorFromName("swap_to_legacy"),
305
- calldata: swapCallData,
306
- },
307
- },
308
- {
211
+ proofReadableId: this._depositApproveProofReadableId(),
309
212
  sanitizer: SIMPLE_SANITIZER,
310
213
  call: {
311
- contractAddress: usdceToken!.address,
214
+ contractAddress: this.usdceToken.address,
312
215
  selector: hash.getSelectorFromName("approve"),
313
216
  calldata: [
314
217
  this.config.extendedContract.toBigInt(),
@@ -318,6 +221,7 @@ export class ExtendedAdapter extends BaseAdapter<
318
221
  },
319
222
  },
320
223
  {
224
+ proofReadableId: this._depositCallProofReadableId(),
321
225
  sanitizer: EXTENDED_SANITIZER,
322
226
  call: {
323
227
  contractAddress: this.config.extendedContract,
@@ -336,95 +240,8 @@ export class ExtendedAdapter extends BaseAdapter<
336
240
  }
337
241
  }
338
242
 
339
- getProofsForFromLegacySwap<T>(tree: StandardMerkleTree): {
340
- proofs: string[][];
341
- callConstructor:
342
- | GenerateCallFn<DepositParams>
343
- | GenerateCallFn<WithdrawParams>;
344
- } {
345
- let proofGroups: string[][] = [];
346
-
347
- const ids = this.getSwapFromLegacyLeaf().leaves.map((l) => l.readableId);
348
- // console.log(`${this.name}::getProofs ids: ${ids}`);
349
- for (const [i, v] of tree.entries()) {
350
- // console.log(`${this.name}::getProofs v: ${v.readableId}`);
351
- if (ids.includes(v.readableId)) {
352
- //console.log(`${this.name}::getProofs found id: ${v.readableId}`);
353
- proofGroups.push(tree.getProof(i));
354
- }
355
- }
356
- if (proofGroups.length != ids.length) {
357
- throw new Error(`Not all proofs found for IDs: ${ids.join(", ")}`);
358
- }
359
-
360
- // find leaf adapter
361
- return {
362
- proofs: proofGroups,
363
- callConstructor: this.getSwapFromLegacyCall.bind(this),
364
- };
365
- }
366
-
367
- async getSwapFromLegacyCall(params: DepositParams): Promise<ManageCall[]> {
368
- try {
369
- const usdcToken = this.config.supportedPositions[0].asset;
370
- const usdceToken = Global.getDefaultTokens().find(
371
- (token) => token.symbol === "USDCe"
372
- );
373
- // Give approval for more amount than the required amount
374
- const amount = uint256.bnToUint256(
375
- params.amount.multipliedBy(10).toWei()
376
- );
377
- const quotes = await this.config.avnuAdapter.getQuotesAvnu(
378
- usdceToken!.address.toString(),
379
- usdcToken!.address.toString(),
380
- params.amount.toNumber(),
381
- this.config.avnuAdapter.config.vaultAllocator.address.toString(),
382
- usdcToken!.decimals,
383
- false
384
- );
385
-
386
- if (!quotes) {
387
- logger.error("error getting quotes from avnu");
388
- return [];
389
- }
390
- const getCalldata = await this.config.avnuAdapter.getSwapCallData(
391
- quotes!
392
- );
393
- const swapCallData = getCalldata[0];
394
- //change extended sanitizer here
395
- return [
396
- {
397
- sanitizer: AVNU_LEGACY_SANITIZER,
398
- call: {
399
- contractAddress: usdceToken!.address,
400
- selector: hash.getSelectorFromName("approve"),
401
- calldata: [
402
- AVNU_EXCHANGE_FOR_LEGACY_USDC.toBigInt(),
403
- toBigInt(amount.low.toString()), // amount low
404
- toBigInt(amount.high.toString()), // amount high
405
- ],
406
- },
407
- },
408
- {
409
- sanitizer: AVNU_LEGACY_SANITIZER,
410
- call: {
411
- contractAddress: AVNU_EXCHANGE_FOR_LEGACY_USDC,
412
- selector: hash.getSelectorFromName("swap_to_new"),
413
- calldata: swapCallData,
414
- },
415
- },
416
- ];
417
- } catch (error) {
418
- logger.error(`Error creating Deposit Call: ${error}`);
419
- return [];
420
- }
421
- }
422
- //Swap wbtc to usdc
423
243
  async getWithdrawCall(params: WithdrawParams): Promise<ManageCall[]> {
424
244
  try {
425
- if (!this.client) {
426
- throw new Error("Client not initialized");
427
- }
428
245
  return [];
429
246
  } catch (error) {
430
247
  logger.error(`Error creating Withdraw Call: ${error}`);
@@ -442,95 +259,95 @@ export class ExtendedAdapter extends BaseAdapter<
442
259
  return {
443
260
  status: false,
444
261
  receivedTxnHash: false,
445
- }
262
+ };
446
263
  }
447
264
  if (amount.lessThanOrEqualTo(0)) {
448
265
  logger.error(
449
- `Invalid withdrawal amount: ${amount.toNumber()}. Amount must be positive.`
266
+ `Invalid withdrawal amount: ${amount.toNumber()}. Amount must be positive.`,
450
267
  );
451
268
  return {
452
269
  status: false,
453
270
  receivedTxnHash: false,
454
- }
271
+ };
455
272
  }
456
273
  if (amount.lessThanOrEqualTo(this.minimumExtendedMovementAmount)) {
457
274
  logger.warn(
458
- `Withdrawal amount ${amount.toNumber()} is below minimum Extended movement amount ${this.minimumExtendedMovementAmount}. Skipping withdrawal.`
275
+ `Withdrawal amount ${amount.toNumber()} is below minimum Extended movement amount ${this.minimumExtendedMovementAmount}. Skipping withdrawal.`,
459
276
  );
460
277
  return {
461
278
  status: false,
462
279
  receivedTxnHash: false,
463
- }
280
+ };
464
281
  }
465
282
  const holdings = await this.getExtendedDepositAmount();
466
283
  if (!holdings) {
467
284
  logger.error(
468
- "Cannot get holdings - unable to validate withdrawal amount"
285
+ "Cannot get holdings - unable to validate withdrawal amount",
469
286
  );
470
287
  return {
471
288
  status: false,
472
289
  receivedTxnHash: false,
473
- }
290
+ };
474
291
  }
475
292
 
476
293
  const availableForWithdrawal = parseFloat(
477
- holdings.availableForWithdrawal
294
+ holdings.availableForWithdrawal,
478
295
  );
479
296
  if (
480
297
  !Number.isFinite(availableForWithdrawal) ||
481
298
  availableForWithdrawal < 0
482
299
  ) {
483
300
  logger.error(
484
- `Invalid availableForWithdrawal: ${holdings.availableForWithdrawal}. Expected a finite, non-negative number.`
301
+ `Invalid availableForWithdrawal: ${holdings.availableForWithdrawal}. Expected a finite, non-negative number.`,
485
302
  );
486
303
  return {
487
304
  status: false,
488
305
  receivedTxnHash: false,
489
- }
306
+ };
490
307
  }
491
308
 
492
309
  const withdrawalAmount = amount.toNumber();
493
310
  if (withdrawalAmount > availableForWithdrawal) {
494
311
  logger.error(
495
- `Withdrawal amount ${withdrawalAmount} exceeds available balance ${availableForWithdrawal}`
312
+ `Withdrawal amount ${withdrawalAmount} exceeds available balance ${availableForWithdrawal}`,
496
313
  );
497
314
  return {
498
315
  status: false,
499
316
  receivedTxnHash: false,
500
- }
317
+ };
501
318
  }
502
319
 
503
320
  logger.info(
504
- `Withdrawing ${withdrawalAmount} from Extended. Available balance: ${availableForWithdrawal}`
321
+ `Withdrawing ${withdrawalAmount} from Extended. Available balance: ${availableForWithdrawal}`,
505
322
  );
506
323
 
507
324
  const withdrawalRequest = await this.client.withdrawUSDC(
508
- amount.toFixed(2)
325
+ amount.toFixed(2),
509
326
  );
510
327
 
511
328
  if (withdrawalRequest.status === "OK") {
512
329
  const withdrawalStatus = await this.getDepositOrWithdrawalStatus(
513
330
  withdrawalRequest.data,
514
- AssetOperationType.WITHDRAWAL
331
+ AssetOperationType.WITHDRAWAL,
515
332
  );
516
333
  return {
517
334
  status: true,
518
335
  receivedTxnHash: withdrawalStatus,
519
- }
336
+ };
520
337
  }
521
338
  logger.error(
522
- `Withdrawal request failed with status: ${withdrawalRequest.status}`
339
+ `Withdrawal request failed with status: ${withdrawalRequest.status}`,
523
340
  );
524
341
  return {
525
342
  status: false,
526
343
  receivedTxnHash: false,
527
- }
344
+ };
528
345
  } catch (error) {
529
346
  logger.error(`Error creating Withdraw Call: ${error}`);
530
347
  return {
531
348
  status: false,
532
349
  receivedTxnHash: false,
533
- }
350
+ };
534
351
  }
535
352
  }
536
353
 
@@ -539,41 +356,36 @@ export class ExtendedAdapter extends BaseAdapter<
539
356
  }
540
357
 
541
358
  async getExtendedDepositAmount(): Promise<Balance | undefined> {
542
- try {
543
- const result = await axios.get<ApiResponse<Balance>>(`${this.config.extendedBackendReadUrl}/holdings`);
544
- if (!result.data) {
545
- logger.error("error getting holdings - API returned null/undefined");
546
- return undefined;
547
- }
359
+ const failResult = {
360
+ collateral_name: "",
361
+ balance: "0",
362
+ equity: "0",
363
+ availableForTrade: "0",
364
+ availableForWithdrawal: "0",
365
+ unrealisedPnl: "0",
366
+ initialMargin: "0",
367
+ marginRatio: "0",
368
+ updatedTime: Date.now(),
369
+ };
370
+ const fail = (message: string) => {
371
+ logger.error(message);
372
+ return failResult;
373
+ };
548
374
 
549
- if (!result.data.success) {
550
- logger.error(
551
- `error getting holdings - API returned status: ${result.status}`
552
- );
553
- return undefined;
375
+ try {
376
+ const result = await this.client.getHoldings();
377
+ if (result.status !== "OK") {
378
+ return fail("error getting holdings - API returned null/undefined");
554
379
  }
555
-
556
- const holdings = result.data.data;
380
+ const holdings = result.data;
557
381
  if (!holdings) {
558
- logger.warn(
559
- "holdings data is null/undefined - treating as zero balance"
382
+ return fail(
383
+ "holdings data is null/undefined - treating as zero balance",
560
384
  );
561
- return {
562
- collateral_name: "",
563
- balance: "0",
564
- equity: "0",
565
- availableForTrade: "0",
566
- availableForWithdrawal: "0",
567
- unrealisedPnl: "0",
568
- initialMargin: "0",
569
- marginRatio: "0",
570
- updatedTime: Date.now(),
571
- };
572
385
  }
573
386
  return holdings;
574
387
  } catch (error) {
575
- logger.error(`error getting holdings - exception: ${error}`);
576
- return undefined;
388
+ return fail(`error getting holdings - exception: ${error}`);
577
389
  }
578
390
  }
579
391
 
@@ -594,12 +406,14 @@ export class ExtendedAdapter extends BaseAdapter<
594
406
 
595
407
  async getAllOpenPositions(): Promise<Position[] | null> {
596
408
  try {
597
- const response = await axios.get<ApiResponse<Position[]>>(`${this.config.extendedBackendReadUrl}/positions`);
598
- if (response.data.success) {
599
- if (response.data.data.length === 0) {
409
+ const response = await this.client.getPositions(
410
+ this.config.extendedMarketName,
411
+ );
412
+ if (response.status === "OK") {
413
+ if (response.data.length === 0) {
600
414
  return [];
601
415
  } else {
602
- return response.data.data;
416
+ return response.data;
603
417
  }
604
418
  }
605
419
  return null;
@@ -609,41 +423,44 @@ export class ExtendedAdapter extends BaseAdapter<
609
423
  }
610
424
  }
611
425
 
612
- async getOrderHistory(marketName: string): Promise<OpenOrder[] | null> {
613
- try {
614
- const result = await axios.get<ApiResponse<OpenOrder[]>>(`${this.config.extendedBackendReadUrl}/marketOrders/${marketName}`);
615
- if (!result.data.success) {
616
- return null;
617
- }
618
- return result.data.data;
619
- } catch (err) {
620
- logger.error("error getting order history", err);
621
- return null;
622
- }
623
- }
426
+ // async getOrderHistory(marketName: string): Promise<OpenOrder[] | null> {
427
+ // try {
428
+ // const result = await axios.get<ApiResponse<OpenOrder[]>>(`${this.config.extendedBackendReadUrl}/marketOrders/${marketName}`);
429
+ // if (!result.data.success) {
430
+ // return null;
431
+ // }
432
+ // return result.data.data;
433
+ // } catch (err) {
434
+ // logger.error("error getting order history", err);
435
+ // return null;
436
+ // }
437
+ // }
624
438
 
625
439
  async getOrderStatus(
626
440
  orderId: string,
627
- marketName: string
441
+ marketName: string,
628
442
  ): Promise<OpenOrder | null> {
629
443
  try {
630
444
  if (this.client === null) {
631
445
  logger.error("error initializing client");
632
446
  return null;
633
447
  }
634
- const orderhistory = await this.getOrderHistory(marketName);
448
+ const orderhistoryResponse =
449
+ await this.client.getOrderHistory(marketName);
635
450
 
636
- if (!orderhistory || orderhistory.length === 0) {
451
+ if (
452
+ orderhistoryResponse.status !== "OK" ||
453
+ orderhistoryResponse.data.length === 0
454
+ ) {
637
455
  return null;
638
456
  }
457
+ const orderhistory = orderhistoryResponse.data;
639
458
  const order = orderhistory
640
459
  .slice(0, 20)
641
460
  .find((order) => order.id.toString() === orderId);
642
-
643
461
  if (order) {
644
462
  return order;
645
463
  }
646
-
647
464
  return null; // Order not found
648
465
  } catch (error) {
649
466
  logger.error(`error getting order status: ${error}`);
@@ -651,14 +468,14 @@ export class ExtendedAdapter extends BaseAdapter<
651
468
  }
652
469
  }
653
470
 
654
- async fetchOrderBookBTCUSDC(): Promise<{
471
+ async fetchOrderBookFromExtended(): Promise<{
655
472
  status: boolean;
656
473
  bid: Web3Number;
657
474
  ask: Web3Number;
658
475
  }> {
659
476
  try {
660
477
  const res = await axios.get(
661
- `${this.config.extendedBaseUrl}/api/v1/info/markets/${this.config.extendedMarketName}/orderbook`
478
+ `${this.config.extendedBaseUrl}/api/v1/info/markets/${this.config.extendedMarketName}/orderbook`,
662
479
  );
663
480
  let ask_price = new Web3Number(0, 0);
664
481
  let bid_price = new Web3Number(0, 0);
@@ -676,12 +493,12 @@ export class ExtendedAdapter extends BaseAdapter<
676
493
  bid_price = new Web3Number(bid.price, 0);
677
494
 
678
495
  return {
679
- status: false,
496
+ status: true,
680
497
  bid: bid_price, // check for quantity as well, not at the moment though
681
498
  ask: ask_price, // check for quantity as well, not at the moment though
682
499
  };
683
500
  } catch (err) {
684
- logger.error(`the err is: ${err}`);
501
+ logger.error(`extended orderbook fetch failed: ${err}`);
685
502
  return {
686
503
  status: false,
687
504
  bid: new Web3Number(0, 0),
@@ -695,7 +512,7 @@ export class ExtendedAdapter extends BaseAdapter<
695
512
  btcAmount: number,
696
513
  side: OrderSide,
697
514
  attempt = 1,
698
- maxAttempts = 5
515
+ maxAttempts = 5,
699
516
  ): Promise<{ position_id: string; btc_exposure: string } | null> {
700
517
  try {
701
518
  if (this.client === null) {
@@ -704,13 +521,13 @@ export class ExtendedAdapter extends BaseAdapter<
704
521
  }
705
522
  const setLeverage = await this.setLeverage(
706
523
  leverage,
707
- this.config.extendedMarketName
524
+ this.config.extendedMarketName,
708
525
  );
709
526
  if (!setLeverage) {
710
527
  logger.error("error depositing or setting leverage");
711
528
  return null;
712
529
  }
713
- const { ask, bid } = await this.fetchOrderBookBTCUSDC();
530
+ const { ask, bid } = await this.fetchOrderBookFromExtended();
714
531
  if (
715
532
  !ask ||
716
533
  !bid ||
@@ -718,7 +535,7 @@ export class ExtendedAdapter extends BaseAdapter<
718
535
  bid.lessThanOrEqualTo(0)
719
536
  ) {
720
537
  logger.error(
721
- `Invalid orderbook prices: ask=${ask?.toNumber()}, bid=${bid?.toNumber()}`
538
+ `Invalid orderbook prices: ask=${ask?.toNumber()}, bid=${bid?.toNumber()}`,
722
539
  );
723
540
  return null;
724
541
  }
@@ -729,7 +546,7 @@ export class ExtendedAdapter extends BaseAdapter<
729
546
  const MAX_PRICE_DEVIATION_MULTIPLIER = 0.5;
730
547
  const priceAdjustmentMultiplier = Math.min(
731
548
  0.2 * attempt,
732
- MAX_PRICE_DEVIATION_MULTIPLIER
549
+ MAX_PRICE_DEVIATION_MULTIPLIER,
733
550
  );
734
551
  const priceAdjustment = spread.times(priceAdjustmentMultiplier);
735
552
 
@@ -747,7 +564,7 @@ export class ExtendedAdapter extends BaseAdapter<
747
564
  `Price deviation too large on attempt ${attempt}: price=${price.toNumber()}, midPrice=${midPrice.toNumber()}, deviation=${price
748
565
  .minus(midPrice)
749
566
  .abs()
750
- .toNumber()}`
567
+ .toNumber()}`,
751
568
  );
752
569
  if (attempt >= maxAttempts) {
753
570
  return null;
@@ -760,11 +577,11 @@ export class ExtendedAdapter extends BaseAdapter<
760
577
 
761
578
  logger.info(
762
579
  `createOrder attempt ${attempt}/${maxAttempts}: side=${side}, midPrice=${midPrice.toNumber()}, adjustedPrice=${price.toNumber()}, adjustment=${priceAdjustmentMultiplier * 100
763
- }%`
580
+ }%`,
764
581
  );
765
582
 
766
583
  const amount_in_token = (btcAmount * parseInt(leverage)).toFixed(
767
- this.config.extendedPrecision
584
+ this.config.extendedPrecision,
768
585
  ); // gives the amount of wbtc
769
586
 
770
587
  const result = await this.createExtendedPositon(
@@ -772,7 +589,7 @@ export class ExtendedAdapter extends BaseAdapter<
772
589
  this.config.extendedMarketName,
773
590
  amount_in_token,
774
591
  price.toFixed(0),
775
- side
592
+ side,
776
593
  );
777
594
  if (!result || !result.position_id) {
778
595
  logger.error("Failed to create order - no position_id returned");
@@ -781,19 +598,19 @@ export class ExtendedAdapter extends BaseAdapter<
781
598
 
782
599
  const positionId = result.position_id;
783
600
  logger.info(
784
- `Order created with position_id: ${positionId}. Waiting for API to update...`
601
+ `Order created with position_id: ${positionId}. Waiting for API to update...`,
785
602
  );
786
603
 
787
604
  let openOrder = await this.getOrderStatus(
788
605
  positionId,
789
- this.config.extendedMarketName
606
+ this.config.extendedMarketName,
790
607
  );
791
608
  const maxStatusRetries = 3;
792
609
  const statusRetryDelay = 5000;
793
610
 
794
611
  if (!openOrder) {
795
612
  logger.warn(
796
- `Order ${positionId} not found in API yet. Retrying status fetch (max ${maxStatusRetries} times)...`
613
+ `Order ${positionId} not found in API yet. Retrying status fetch (max ${maxStatusRetries} times)...`,
797
614
  );
798
615
  for (
799
616
  let statusRetry = 1;
@@ -803,23 +620,23 @@ export class ExtendedAdapter extends BaseAdapter<
803
620
  await new Promise((resolve) => setTimeout(resolve, statusRetryDelay));
804
621
  openOrder = await this.getOrderStatus(
805
622
  positionId,
806
- this.config.extendedMarketName
623
+ this.config.extendedMarketName,
807
624
  );
808
625
  if (openOrder) {
809
626
  logger.info(
810
- `Order ${positionId} found after ${statusRetry} status retry(ies)`
627
+ `Order ${positionId} found after ${statusRetry} status retry(ies)`,
811
628
  );
812
629
  break;
813
630
  }
814
631
  logger.warn(
815
- `Order ${positionId} still not found after ${statusRetry}/${maxStatusRetries} status retries`
632
+ `Order ${positionId} still not found after ${statusRetry}/${maxStatusRetries} status retries`,
816
633
  );
817
634
  }
818
635
  }
819
636
 
820
637
  if (openOrder && openOrder.status === OrderStatus.FILLED) {
821
638
  logger.info(
822
- `Order ${positionId} successfully filled with quantity ${openOrder.qty}`
639
+ `Order ${positionId} successfully filled with quantity ${openOrder.qty}`,
823
640
  );
824
641
  return {
825
642
  position_id: positionId,
@@ -828,11 +645,11 @@ export class ExtendedAdapter extends BaseAdapter<
828
645
  } else if (openOrder && openOrder.status !== OrderStatus.FILLED) {
829
646
  // Order found but NOT FILLED - retry (recreate)
830
647
  logger.warn(
831
- `Order ${positionId} found but status is ${openOrder.status}, not FILLED. Retrying order creation...`
648
+ `Order ${positionId} found but status is ${openOrder.status}, not FILLED. Retrying order creation...`,
832
649
  );
833
650
  if (attempt >= maxAttempts) {
834
651
  logger.error(
835
- `Max retries reached — order ${positionId} status is ${openOrder.status}, not FILLED`
652
+ `Max retries reached — order ${positionId} status is ${openOrder.status}, not FILLED`,
836
653
  );
837
654
  return null;
838
655
  } else {
@@ -843,12 +660,12 @@ export class ExtendedAdapter extends BaseAdapter<
843
660
  btcAmount,
844
661
  side,
845
662
  attempt + 1,
846
- maxAttempts
663
+ maxAttempts,
847
664
  );
848
665
  }
849
666
  } else {
850
667
  logger.warn(
851
- `Order ${positionId} not found in API after ${maxStatusRetries} status retries (API update delayed ~30s). We got position_id from creation, so order exists. Returning position_id - status will be checked in next loop iteration.`
668
+ `Order ${positionId} not found in API after ${maxStatusRetries} status retries (API update delayed ~30s). We got position_id from creation, so order exists. Returning position_id - status will be checked in next loop iteration.`,
852
669
  );
853
670
  return {
854
671
  position_id: positionId,
@@ -857,7 +674,7 @@ export class ExtendedAdapter extends BaseAdapter<
857
674
  }
858
675
  } catch (err: any) {
859
676
  logger.error(
860
- `createShortOrder failed on attempt ${attempt}: ${err.message}`
677
+ `createShortOrder failed on attempt ${attempt}: ${err.message}`,
861
678
  );
862
679
 
863
680
  if (attempt < maxAttempts) {
@@ -869,7 +686,7 @@ export class ExtendedAdapter extends BaseAdapter<
869
686
  btcAmount,
870
687
  side,
871
688
  attempt + 1,
872
- maxAttempts
689
+ maxAttempts,
873
690
  );
874
691
  }
875
692
  logger.error("Max retry attempts reached — aborting createShortOrder");
@@ -882,17 +699,19 @@ export class ExtendedAdapter extends BaseAdapter<
882
699
  marketName: string,
883
700
  amount: string,
884
701
  price: string,
885
- side: OrderSide
702
+ side: OrderSide,
886
703
  ) {
887
704
  try {
888
705
  const result =
889
706
  side === OrderSide.SELL
890
707
  ? await client.createSellOrder(marketName, amount, price, {
891
708
  postOnly: false,
709
+ reduceOnly: false,
892
710
  timeInForce: TimeInForce.IOC,
893
711
  })
894
712
  : await client.createBuyOrder(marketName, amount, price, {
895
713
  postOnly: false,
714
+ reduceOnly: true,
896
715
  timeInForce: TimeInForce.IOC,
897
716
  });
898
717
  if (result.data.id) {
@@ -910,7 +729,7 @@ export class ExtendedAdapter extends BaseAdapter<
910
729
 
911
730
  async getDepositOrWithdrawalStatus(
912
731
  orderId: number | string, // for deposits, send txn hash as string
913
- operationsType: AssetOperationType
732
+ operationsType: AssetOperationType,
914
733
  ): Promise<boolean> {
915
734
  const maxAttempts = 15;
916
735
  const retryDelayMs = 30000; // 60 seconds
@@ -923,80 +742,80 @@ export class ExtendedAdapter extends BaseAdapter<
923
742
  });
924
743
  if (operationsType === AssetOperationType.DEPOSIT) {
925
744
  const myTransferStatus = transferHistory.data.find(
926
- (operation) => operation.transactionHash?.toLowerCase() === orderId.toString().toLowerCase()
745
+ (operation) =>
746
+ operation.transactionHash?.toLowerCase() ===
747
+ orderId.toString().toLowerCase(),
927
748
  );
928
749
  if (!myTransferStatus) {
929
750
  if (attempt < maxAttempts) {
930
751
  logger.info(
931
- `Deposit operation not found for transactionHash ${orderId}, retrying (attempt ${attempt}/${maxAttempts})...`
752
+ `Deposit operation not found for transactionHash ${orderId}, retrying (attempt ${attempt}/${maxAttempts})...`,
932
753
  );
933
754
  await new Promise((resolve) => setTimeout(resolve, retryDelayMs));
934
755
  continue;
935
756
  }
936
757
  logger.warn(
937
- `Deposit operation not found for transactionHash ${orderId} after ${maxAttempts} attempts`
758
+ `Deposit operation not found for transactionHash ${orderId} after ${maxAttempts} attempts`,
938
759
  );
939
760
  return false;
940
761
  }
941
762
  // Check if status is COMPLETED
942
763
  if (myTransferStatus.status === AssetOperationStatus.COMPLETED) {
943
- logger.info(
944
- `Deposit operation ${orderId} completed successfully`
945
- );
764
+ logger.info(`Deposit operation ${orderId} completed successfully`);
946
765
  return true;
947
766
  } else {
948
767
  if (attempt < maxAttempts) {
949
768
  logger.info(
950
- `Deposit operation ${orderId} found but status is ${myTransferStatus.status}, not COMPLETED. Retrying (attempt ${attempt}/${maxAttempts})...`
769
+ `Deposit operation ${orderId} found but status is ${myTransferStatus.status}, not COMPLETED. Retrying (attempt ${attempt}/${maxAttempts})...`,
951
770
  );
952
771
  await new Promise((resolve) => setTimeout(resolve, retryDelayMs));
953
772
  continue;
954
773
  }
955
774
  logger.warn(
956
- `Deposit operation ${orderId} status is ${myTransferStatus.status} after ${maxAttempts} attempts, expected COMPLETED`
775
+ `Deposit operation ${orderId} status is ${myTransferStatus.status} after ${maxAttempts} attempts, expected COMPLETED`,
957
776
  );
958
777
  return false;
959
778
  }
960
779
  } else {
961
780
  const myTransferStatus = transferHistory.data.find(
962
- (operation) => operation.id === orderId.toString()
781
+ (operation) => operation.id === orderId.toString(),
963
782
  );
964
783
  if (!myTransferStatus) {
965
784
  if (attempt < maxAttempts) {
966
785
  logger.info(
967
- `Withdrawal status not found for orderId ${orderId} in completed operations, retrying (attempt ${attempt}/${maxAttempts})...`
786
+ `Withdrawal status not found for orderId ${orderId} in completed operations, retrying (attempt ${attempt}/${maxAttempts})...`,
968
787
  );
969
788
  await new Promise((resolve) => setTimeout(resolve, retryDelayMs));
970
789
  continue;
971
790
  }
972
791
  logger.warn(
973
- `Withdrawal operation not found for orderId ${orderId} after ${maxAttempts} attempts`
792
+ `Withdrawal operation not found for orderId ${orderId} after ${maxAttempts} attempts`,
974
793
  );
975
794
  return false;
976
795
  }
977
796
  // Check if status is COMPLETED
978
797
  if (myTransferStatus.status === AssetOperationStatus.COMPLETED) {
979
798
  logger.info(
980
- `Withdrawal operation ${orderId} completed successfully`
799
+ `Withdrawal operation ${orderId} completed successfully`,
981
800
  );
982
801
  return true;
983
802
  } else {
984
803
  if (attempt < maxAttempts) {
985
804
  logger.info(
986
- `Withdrawal operation ${orderId} found but status is ${myTransferStatus.status}, not COMPLETED. Retrying (attempt ${attempt}/${maxAttempts})...`
805
+ `Withdrawal operation ${orderId} found but status is ${myTransferStatus.status}, not COMPLETED. Retrying (attempt ${attempt}/${maxAttempts})...`,
987
806
  );
988
807
  await new Promise((resolve) => setTimeout(resolve, retryDelayMs));
989
808
  continue;
990
809
  }
991
810
  logger.warn(
992
- `Withdrawal operation ${orderId} status is ${myTransferStatus.status} after ${maxAttempts} attempts, expected COMPLETED`
811
+ `Withdrawal operation ${orderId} status is ${myTransferStatus.status} after ${maxAttempts} attempts, expected COMPLETED`,
993
812
  );
994
813
  return false;
995
814
  }
996
815
  }
997
816
  } catch (err) {
998
817
  logger.error(
999
- `error getting deposit or withdrawal status (attempt ${attempt}/${maxAttempts}): ${err}`
818
+ `error getting deposit or withdrawal status (attempt ${attempt}/${maxAttempts}): ${err}`,
1000
819
  );
1001
820
  if (attempt < maxAttempts) {
1002
821
  logger.info(`Retrying after ${retryDelayMs}ms...`);
@@ -1004,7 +823,7 @@ export class ExtendedAdapter extends BaseAdapter<
1004
823
  continue;
1005
824
  }
1006
825
  logger.error(
1007
- `Max retry attempts reached for getDepositOrWithdrawalStatus`
826
+ `Max retry attempts reached for getDepositOrWithdrawalStatus`,
1008
827
  );
1009
828
  return false;
1010
829
  }