@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.
- package/dist/cli.js +190 -36
- package/dist/cli.mjs +188 -34
- package/dist/index.browser.global.js +79130 -49357
- package/dist/index.browser.mjs +18039 -11434
- package/dist/index.d.ts +2869 -898
- package/dist/index.js +19036 -12210
- package/dist/index.mjs +18942 -12161
- package/package.json +1 -1
- package/src/data/avnu.abi.json +840 -0
- package/src/data/ekubo-price-fethcer.abi.json +265 -0
- package/src/dataTypes/_bignumber.ts +13 -4
- package/src/dataTypes/index.ts +3 -2
- package/src/dataTypes/mynumber.ts +141 -0
- package/src/global.ts +76 -41
- package/src/index.browser.ts +2 -1
- package/src/interfaces/common.tsx +167 -2
- package/src/modules/ExtendedWrapperSDk/types.ts +26 -4
- package/src/modules/ExtendedWrapperSDk/wrapper.ts +110 -67
- package/src/modules/apollo-client-config.ts +28 -0
- package/src/modules/avnu.ts +4 -4
- package/src/modules/ekubo-pricer.ts +79 -0
- package/src/modules/ekubo-quoter.ts +46 -30
- package/src/modules/erc20.ts +17 -0
- package/src/modules/harvests.ts +43 -29
- package/src/modules/pragma.ts +23 -8
- package/src/modules/pricer-from-api.ts +156 -15
- package/src/modules/pricer-lst.ts +1 -1
- package/src/modules/pricer.ts +40 -4
- package/src/modules/pricerBase.ts +2 -1
- package/src/node/deployer.ts +36 -1
- package/src/node/pricer-redis.ts +2 -1
- package/src/strategies/base-strategy.ts +78 -10
- package/src/strategies/ekubo-cl-vault.tsx +906 -347
- package/src/strategies/factory.ts +159 -0
- package/src/strategies/index.ts +6 -1
- package/src/strategies/registry.ts +239 -0
- package/src/strategies/sensei.ts +335 -7
- package/src/strategies/svk-strategy.ts +97 -27
- package/src/strategies/types.ts +4 -0
- package/src/strategies/universal-adapters/adapter-utils.ts +2 -1
- package/src/strategies/universal-adapters/avnu-adapter.ts +177 -268
- package/src/strategies/universal-adapters/baseAdapter.ts +263 -251
- package/src/strategies/universal-adapters/common-adapter.ts +206 -203
- package/src/strategies/universal-adapters/extended-adapter.ts +155 -336
- package/src/strategies/universal-adapters/index.ts +9 -8
- package/src/strategies/universal-adapters/token-transfer-adapter.ts +200 -0
- package/src/strategies/universal-adapters/usdc<>usdce-adapter.ts +200 -0
- package/src/strategies/universal-adapters/vesu-adapter.ts +110 -75
- package/src/strategies/universal-adapters/vesu-modify-position-adapter.ts +476 -0
- package/src/strategies/universal-adapters/vesu-multiply-adapter.ts +762 -844
- package/src/strategies/universal-adapters/vesu-position-common.ts +251 -0
- package/src/strategies/universal-adapters/vesu-supply-only-adapter.ts +18 -3
- package/src/strategies/universal-lst-muliplier-strategy.tsx +396 -204
- package/src/strategies/universal-strategy.tsx +1426 -1178
- package/src/strategies/vesu-extended-strategy/services/executionService.ts +2251 -0
- package/src/strategies/vesu-extended-strategy/services/extended-vesu-state-manager.ts +2941 -0
- package/src/strategies/vesu-extended-strategy/services/operationService.ts +12 -1
- package/src/strategies/vesu-extended-strategy/types/transaction-metadata.ts +52 -0
- package/src/strategies/vesu-extended-strategy/utils/config.runtime.ts +1 -0
- package/src/strategies/vesu-extended-strategy/utils/constants.ts +2 -0
- package/src/strategies/vesu-extended-strategy/utils/helper.ts +158 -124
- package/src/strategies/vesu-extended-strategy/vesu-extended-strategy.tsx +377 -1788
- package/src/strategies/vesu-rebalance.tsx +255 -152
- package/src/utils/health-factor-math.ts +4 -1
- package/src/utils/index.ts +2 -1
- package/src/utils/logger.browser.ts +22 -4
- package/src/utils/logger.node.ts +259 -24
- package/src/utils/starknet-call-parser.ts +1036 -0
- package/src/utils/strategy-utils.ts +61 -0
- package/src/strategies/universal-adapters/unused-balance-adapter.ts +0 -109
|
@@ -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
|
-
|
|
69
|
-
|
|
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(
|
|
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
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
if (
|
|
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.
|
|
108
|
-
|
|
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.
|
|
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:
|
|
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:
|
|
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
|
|
261
|
-
const
|
|
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
|
-
|
|
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
|
|
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
|
-
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
|
|
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
|
-
|
|
550
|
-
|
|
551
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
|
598
|
-
|
|
599
|
-
|
|
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
|
|
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
|
-
|
|
614
|
-
|
|
615
|
-
|
|
616
|
-
|
|
617
|
-
|
|
618
|
-
|
|
619
|
-
|
|
620
|
-
|
|
621
|
-
|
|
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
|
|
448
|
+
const orderhistoryResponse =
|
|
449
|
+
await this.client.getOrderHistory(marketName);
|
|
635
450
|
|
|
636
|
-
if (
|
|
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
|
|
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:
|
|
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(`
|
|
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.
|
|
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) =>
|
|
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
|
}
|