@strkfarm/sdk 2.0.0-dev.7 → 2.0.0-dev.9
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.browser.global.js +509 -122
- package/dist/index.browser.mjs +509 -122
- package/dist/index.d.ts +2 -1
- package/dist/index.js +509 -122
- package/dist/index.mjs +509 -122
- package/package.json +1 -1
- package/src/strategies/universal-adapters/avnu-adapter.ts +2 -3
- package/src/strategies/universal-adapters/extended-adapter.ts +312 -85
- package/src/strategies/vesu-extended-strategy/vesu-extended-strategy.tsx +285 -52
package/dist/index.js
CHANGED
|
@@ -30072,8 +30072,47 @@ var ExtendedAdapter = class _ExtendedAdapter extends BaseAdapter {
|
|
|
30072
30072
|
async withdrawFromExtended(amount) {
|
|
30073
30073
|
try {
|
|
30074
30074
|
if (!this.client) {
|
|
30075
|
-
|
|
30075
|
+
logger.error("Client not initialized");
|
|
30076
|
+
return false;
|
|
30077
|
+
}
|
|
30078
|
+
if (amount.lessThanOrEqualTo(0)) {
|
|
30079
|
+
logger.error(
|
|
30080
|
+
`Invalid withdrawal amount: ${amount.toNumber()}. Amount must be positive.`
|
|
30081
|
+
);
|
|
30082
|
+
return false;
|
|
30083
|
+
}
|
|
30084
|
+
if (amount.lessThanOrEqualTo(this.minimumExtendedMovementAmount)) {
|
|
30085
|
+
logger.warn(
|
|
30086
|
+
`Withdrawal amount ${amount.toNumber()} is below minimum Extended movement amount ${this.minimumExtendedMovementAmount}. Skipping withdrawal.`
|
|
30087
|
+
);
|
|
30088
|
+
return false;
|
|
30089
|
+
}
|
|
30090
|
+
const holdings = await this.getExtendedDepositAmount();
|
|
30091
|
+
if (!holdings) {
|
|
30092
|
+
logger.error(
|
|
30093
|
+
"Cannot get holdings - unable to validate withdrawal amount"
|
|
30094
|
+
);
|
|
30095
|
+
return false;
|
|
30076
30096
|
}
|
|
30097
|
+
const availableForWithdrawal = parseFloat(
|
|
30098
|
+
holdings.availableForWithdrawal
|
|
30099
|
+
);
|
|
30100
|
+
if (!Number.isFinite(availableForWithdrawal) || availableForWithdrawal < 0) {
|
|
30101
|
+
logger.error(
|
|
30102
|
+
`Invalid availableForWithdrawal: ${holdings.availableForWithdrawal}. Expected a finite, non-negative number.`
|
|
30103
|
+
);
|
|
30104
|
+
return false;
|
|
30105
|
+
}
|
|
30106
|
+
const withdrawalAmount = amount.toNumber();
|
|
30107
|
+
if (withdrawalAmount > availableForWithdrawal) {
|
|
30108
|
+
logger.error(
|
|
30109
|
+
`Withdrawal amount ${withdrawalAmount} exceeds available balance ${availableForWithdrawal}`
|
|
30110
|
+
);
|
|
30111
|
+
return false;
|
|
30112
|
+
}
|
|
30113
|
+
logger.info(
|
|
30114
|
+
`Withdrawing ${withdrawalAmount} from Extended. Available balance: ${availableForWithdrawal}`
|
|
30115
|
+
);
|
|
30077
30116
|
const withdrawalRequest = await this.client.withdrawUSDC(
|
|
30078
30117
|
amount.toFixed(2)
|
|
30079
30118
|
);
|
|
@@ -30084,6 +30123,9 @@ var ExtendedAdapter = class _ExtendedAdapter extends BaseAdapter {
|
|
|
30084
30123
|
);
|
|
30085
30124
|
return withdrawalStatus;
|
|
30086
30125
|
}
|
|
30126
|
+
logger.error(
|
|
30127
|
+
`Withdrawal request failed with status: ${withdrawalRequest.status}`
|
|
30128
|
+
);
|
|
30087
30129
|
return false;
|
|
30088
30130
|
} catch (error) {
|
|
30089
30131
|
logger.error(`Error creating Withdraw Call: ${error}`);
|
|
@@ -30094,21 +30136,44 @@ var ExtendedAdapter = class _ExtendedAdapter extends BaseAdapter {
|
|
|
30094
30136
|
return Promise.resolve(1);
|
|
30095
30137
|
}
|
|
30096
30138
|
async getExtendedDepositAmount() {
|
|
30097
|
-
|
|
30098
|
-
|
|
30099
|
-
|
|
30100
|
-
|
|
30101
|
-
|
|
30102
|
-
|
|
30103
|
-
|
|
30104
|
-
|
|
30105
|
-
|
|
30106
|
-
|
|
30107
|
-
|
|
30108
|
-
|
|
30139
|
+
try {
|
|
30140
|
+
if (this.client === null) {
|
|
30141
|
+
logger.error("error initializing client - client is null");
|
|
30142
|
+
return void 0;
|
|
30143
|
+
}
|
|
30144
|
+
const result = await this.client.getHoldings();
|
|
30145
|
+
if (!result) {
|
|
30146
|
+
logger.error("error getting holdings - API returned null/undefined");
|
|
30147
|
+
return void 0;
|
|
30148
|
+
}
|
|
30149
|
+
if (result.status && result.status !== "OK") {
|
|
30150
|
+
logger.error(
|
|
30151
|
+
`error getting holdings - API returned status: ${result.status}`
|
|
30152
|
+
);
|
|
30153
|
+
return void 0;
|
|
30154
|
+
}
|
|
30155
|
+
const holdings = result.data;
|
|
30156
|
+
if (!holdings) {
|
|
30157
|
+
logger.warn(
|
|
30158
|
+
"holdings data is null/undefined - treating as zero balance"
|
|
30159
|
+
);
|
|
30160
|
+
return {
|
|
30161
|
+
collateral_name: "",
|
|
30162
|
+
balance: "0",
|
|
30163
|
+
equity: "0",
|
|
30164
|
+
availableForTrade: "0",
|
|
30165
|
+
availableForWithdrawal: "0",
|
|
30166
|
+
unrealisedPnl: "0",
|
|
30167
|
+
initialMargin: "0",
|
|
30168
|
+
marginRatio: "0",
|
|
30169
|
+
updatedTime: Date.now()
|
|
30170
|
+
};
|
|
30171
|
+
}
|
|
30172
|
+
return holdings;
|
|
30173
|
+
} catch (error) {
|
|
30174
|
+
logger.error(`error getting holdings - exception: ${error}`);
|
|
30109
30175
|
return void 0;
|
|
30110
30176
|
}
|
|
30111
|
-
return holdings;
|
|
30112
30177
|
}
|
|
30113
30178
|
async setLeverage(leverage, marketName) {
|
|
30114
30179
|
if (this.client === null) {
|
|
@@ -30150,38 +30215,24 @@ var ExtendedAdapter = class _ExtendedAdapter extends BaseAdapter {
|
|
|
30150
30215
|
return result.data;
|
|
30151
30216
|
}
|
|
30152
30217
|
async getOrderStatus(orderId, marketName) {
|
|
30153
|
-
|
|
30154
|
-
|
|
30155
|
-
|
|
30156
|
-
|
|
30157
|
-
let orderhistory = await this.getOrderHistory(marketName);
|
|
30158
|
-
if (!orderhistory || orderhistory.length === 0) {
|
|
30159
|
-
logger.error(`error getting order history: ${orderId}`);
|
|
30160
|
-
} else {
|
|
30161
|
-
const order = orderhistory.slice(0, 10).find((order2) => order2.id.toString() === orderId);
|
|
30162
|
-
if (order) {
|
|
30163
|
-
return order;
|
|
30218
|
+
try {
|
|
30219
|
+
if (this.client === null) {
|
|
30220
|
+
logger.error("error initializing client");
|
|
30221
|
+
return null;
|
|
30164
30222
|
}
|
|
30165
|
-
|
|
30166
|
-
for (let attempt = 1; attempt <= 5; attempt++) {
|
|
30167
|
-
await new Promise((resolve) => setTimeout(resolve, this.retryDelayForOrderStatus));
|
|
30168
|
-
orderhistory = await this.getOrderHistory(marketName);
|
|
30223
|
+
const orderhistory = await this.getOrderHistory(marketName);
|
|
30169
30224
|
if (!orderhistory || orderhistory.length === 0) {
|
|
30170
|
-
|
|
30171
|
-
`error getting order history on retry ${attempt}: ${orderId}`
|
|
30172
|
-
);
|
|
30173
|
-
continue;
|
|
30225
|
+
return null;
|
|
30174
30226
|
}
|
|
30175
|
-
const order = orderhistory.slice(0,
|
|
30176
|
-
if (order
|
|
30227
|
+
const order = orderhistory.slice(0, 20).find((order2) => order2.id.toString() === orderId);
|
|
30228
|
+
if (order) {
|
|
30177
30229
|
return order;
|
|
30178
30230
|
}
|
|
30179
|
-
|
|
30180
|
-
|
|
30181
|
-
);
|
|
30231
|
+
return null;
|
|
30232
|
+
} catch (error) {
|
|
30233
|
+
logger.error(`error getting order status: ${error}`);
|
|
30234
|
+
return null;
|
|
30182
30235
|
}
|
|
30183
|
-
logger.error(`error getting order after all retries: ${orderId}`);
|
|
30184
|
-
return null;
|
|
30185
30236
|
}
|
|
30186
30237
|
async fetchOrderBookBTCUSDC() {
|
|
30187
30238
|
try {
|
|
@@ -30232,14 +30283,40 @@ var ExtendedAdapter = class _ExtendedAdapter extends BaseAdapter {
|
|
|
30232
30283
|
logger.error("error depositing or setting leverage");
|
|
30233
30284
|
return null;
|
|
30234
30285
|
}
|
|
30235
|
-
const
|
|
30236
|
-
if (
|
|
30286
|
+
const { ask, bid } = await this.fetchOrderBookBTCUSDC();
|
|
30287
|
+
if (!ask || !bid || ask.lessThanOrEqualTo(0) || bid.lessThanOrEqualTo(0)) {
|
|
30288
|
+
logger.error(
|
|
30289
|
+
`Invalid orderbook prices: ask=${ask?.toNumber()}, bid=${bid?.toNumber()}`
|
|
30290
|
+
);
|
|
30237
30291
|
return null;
|
|
30238
30292
|
}
|
|
30239
|
-
const { ask, bid } = await this.fetchOrderBookBTCUSDC();
|
|
30240
30293
|
const spread = ask.minus(bid);
|
|
30241
|
-
|
|
30242
|
-
|
|
30294
|
+
const midPrice = ask.plus(bid).div(2);
|
|
30295
|
+
const MAX_PRICE_DEVIATION_MULTIPLIER = 0.5;
|
|
30296
|
+
const priceAdjustmentMultiplier = Math.min(
|
|
30297
|
+
0.2 * attempt,
|
|
30298
|
+
MAX_PRICE_DEVIATION_MULTIPLIER
|
|
30299
|
+
);
|
|
30300
|
+
const priceAdjustment = spread.times(priceAdjustmentMultiplier);
|
|
30301
|
+
let price = midPrice;
|
|
30302
|
+
if (side === "SELL" /* SELL */) {
|
|
30303
|
+
price = midPrice.minus(priceAdjustment);
|
|
30304
|
+
} else {
|
|
30305
|
+
price = midPrice.plus(priceAdjustment);
|
|
30306
|
+
}
|
|
30307
|
+
const maxDeviation = midPrice.times(0.5);
|
|
30308
|
+
if (price.minus(midPrice).abs().greaterThan(maxDeviation)) {
|
|
30309
|
+
logger.error(
|
|
30310
|
+
`Price deviation too large on attempt ${attempt}: price=${price.toNumber()}, midPrice=${midPrice.toNumber()}, deviation=${price.minus(midPrice).abs().toNumber()}`
|
|
30311
|
+
);
|
|
30312
|
+
if (attempt >= maxAttempts) {
|
|
30313
|
+
return null;
|
|
30314
|
+
}
|
|
30315
|
+
price = side === "SELL" /* SELL */ ? midPrice.minus(maxDeviation) : midPrice.plus(maxDeviation);
|
|
30316
|
+
}
|
|
30317
|
+
logger.info(
|
|
30318
|
+
`createOrder attempt ${attempt}/${maxAttempts}: side=${side}, midPrice=${midPrice.toNumber()}, adjustedPrice=${price.toNumber()}, adjustment=${priceAdjustmentMultiplier * 100}%`
|
|
30319
|
+
);
|
|
30243
30320
|
const amount_in_token = (btcAmount * parseInt(leverage)).toFixed(
|
|
30244
30321
|
this.config.extendedPrecision
|
|
30245
30322
|
);
|
|
@@ -30250,17 +30327,57 @@ var ExtendedAdapter = class _ExtendedAdapter extends BaseAdapter {
|
|
|
30250
30327
|
price.toFixed(0),
|
|
30251
30328
|
side
|
|
30252
30329
|
);
|
|
30253
|
-
if (!result) {
|
|
30330
|
+
if (!result || !result.position_id) {
|
|
30331
|
+
logger.error("Failed to create order - no position_id returned");
|
|
30254
30332
|
return null;
|
|
30255
30333
|
}
|
|
30256
|
-
|
|
30257
|
-
|
|
30258
|
-
|
|
30334
|
+
const positionId = result.position_id;
|
|
30335
|
+
logger.info(
|
|
30336
|
+
`Order created with position_id: ${positionId}. Waiting for API to update...`
|
|
30337
|
+
);
|
|
30338
|
+
let openOrder = await this.getOrderStatus(
|
|
30339
|
+
positionId,
|
|
30259
30340
|
this.config.extendedMarketName
|
|
30260
30341
|
);
|
|
30342
|
+
const maxStatusRetries = 3;
|
|
30343
|
+
const statusRetryDelay = 5e3;
|
|
30261
30344
|
if (!openOrder) {
|
|
30345
|
+
logger.warn(
|
|
30346
|
+
`Order ${positionId} not found in API yet. Retrying status fetch (max ${maxStatusRetries} times)...`
|
|
30347
|
+
);
|
|
30348
|
+
for (let statusRetry = 1; statusRetry <= maxStatusRetries; statusRetry++) {
|
|
30349
|
+
await new Promise((resolve) => setTimeout(resolve, statusRetryDelay));
|
|
30350
|
+
openOrder = await this.getOrderStatus(
|
|
30351
|
+
positionId,
|
|
30352
|
+
this.config.extendedMarketName
|
|
30353
|
+
);
|
|
30354
|
+
if (openOrder) {
|
|
30355
|
+
logger.info(
|
|
30356
|
+
`Order ${positionId} found after ${statusRetry} status retry(ies)`
|
|
30357
|
+
);
|
|
30358
|
+
break;
|
|
30359
|
+
}
|
|
30360
|
+
logger.warn(
|
|
30361
|
+
`Order ${positionId} still not found after ${statusRetry}/${maxStatusRetries} status retries`
|
|
30362
|
+
);
|
|
30363
|
+
}
|
|
30364
|
+
}
|
|
30365
|
+
if (openOrder && openOrder.status === "FILLED" /* FILLED */) {
|
|
30366
|
+
logger.info(
|
|
30367
|
+
`Order ${positionId} successfully filled with quantity ${openOrder.qty}`
|
|
30368
|
+
);
|
|
30369
|
+
return {
|
|
30370
|
+
position_id: positionId,
|
|
30371
|
+
btc_exposure: openOrder.qty
|
|
30372
|
+
};
|
|
30373
|
+
} else if (openOrder && openOrder.status !== "FILLED" /* FILLED */) {
|
|
30374
|
+
logger.warn(
|
|
30375
|
+
`Order ${positionId} found but status is ${openOrder.status}, not FILLED. Retrying order creation...`
|
|
30376
|
+
);
|
|
30262
30377
|
if (attempt >= maxAttempts) {
|
|
30263
|
-
logger.error(
|
|
30378
|
+
logger.error(
|
|
30379
|
+
`Max retries reached \u2014 order ${positionId} status is ${openOrder.status}, not FILLED`
|
|
30380
|
+
);
|
|
30264
30381
|
return null;
|
|
30265
30382
|
} else {
|
|
30266
30383
|
const backoff = 2e3 * attempt;
|
|
@@ -30274,9 +30391,12 @@ var ExtendedAdapter = class _ExtendedAdapter extends BaseAdapter {
|
|
|
30274
30391
|
);
|
|
30275
30392
|
}
|
|
30276
30393
|
} else {
|
|
30394
|
+
logger.warn(
|
|
30395
|
+
`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.`
|
|
30396
|
+
);
|
|
30277
30397
|
return {
|
|
30278
|
-
position_id:
|
|
30279
|
-
btc_exposure:
|
|
30398
|
+
position_id: positionId,
|
|
30399
|
+
btc_exposure: amount_in_token
|
|
30280
30400
|
};
|
|
30281
30401
|
}
|
|
30282
30402
|
} catch (err) {
|
|
@@ -30321,32 +30441,101 @@ var ExtendedAdapter = class _ExtendedAdapter extends BaseAdapter {
|
|
|
30321
30441
|
}
|
|
30322
30442
|
}
|
|
30323
30443
|
async getDepositOrWithdrawalStatus(orderId, operationsType) {
|
|
30324
|
-
|
|
30325
|
-
|
|
30326
|
-
|
|
30327
|
-
|
|
30328
|
-
|
|
30329
|
-
|
|
30330
|
-
|
|
30331
|
-
|
|
30332
|
-
)
|
|
30333
|
-
|
|
30334
|
-
|
|
30444
|
+
const maxAttempts = 5;
|
|
30445
|
+
const retryDelayMs = 3e4;
|
|
30446
|
+
for (let attempt = 1; attempt <= maxAttempts; attempt++) {
|
|
30447
|
+
try {
|
|
30448
|
+
let transferHistory = await this.client.getAssetOperations({
|
|
30449
|
+
operationsType: [operationsType],
|
|
30450
|
+
operationsStatus: ["COMPLETED" /* COMPLETED */]
|
|
30451
|
+
});
|
|
30452
|
+
if (operationsType === "DEPOSIT" /* DEPOSIT */) {
|
|
30453
|
+
const myTransferStatus = transferHistory.data.find(
|
|
30454
|
+
(operation) => operation.transactionHash === orderId
|
|
30455
|
+
);
|
|
30456
|
+
if (!myTransferStatus) {
|
|
30457
|
+
if (attempt < maxAttempts) {
|
|
30458
|
+
logger.info(
|
|
30459
|
+
`Deposit operation not found for transactionHash ${orderId}, retrying (attempt ${attempt}/${maxAttempts})...`
|
|
30460
|
+
);
|
|
30461
|
+
await new Promise((resolve) => setTimeout(resolve, retryDelayMs));
|
|
30462
|
+
continue;
|
|
30463
|
+
}
|
|
30464
|
+
logger.warn(
|
|
30465
|
+
`Deposit operation not found for transactionHash ${orderId} after ${maxAttempts} attempts`
|
|
30466
|
+
);
|
|
30467
|
+
return false;
|
|
30468
|
+
}
|
|
30469
|
+
if (myTransferStatus.status === "COMPLETED" /* COMPLETED */) {
|
|
30470
|
+
logger.info(
|
|
30471
|
+
`Deposit operation ${orderId} completed successfully`
|
|
30472
|
+
);
|
|
30473
|
+
return true;
|
|
30474
|
+
} else {
|
|
30475
|
+
if (attempt < maxAttempts) {
|
|
30476
|
+
logger.info(
|
|
30477
|
+
`Deposit operation ${orderId} found but status is ${myTransferStatus.status}, not COMPLETED. Retrying (attempt ${attempt}/${maxAttempts})...`
|
|
30478
|
+
);
|
|
30479
|
+
await new Promise((resolve) => setTimeout(resolve, retryDelayMs));
|
|
30480
|
+
continue;
|
|
30481
|
+
}
|
|
30482
|
+
logger.warn(
|
|
30483
|
+
`Deposit operation ${orderId} status is ${myTransferStatus.status} after ${maxAttempts} attempts, expected COMPLETED`
|
|
30484
|
+
);
|
|
30485
|
+
return false;
|
|
30486
|
+
}
|
|
30487
|
+
} else {
|
|
30488
|
+
const myTransferStatus = transferHistory.data.find(
|
|
30489
|
+
(operation) => operation.id.toString() === orderId.toString()
|
|
30490
|
+
);
|
|
30491
|
+
if (!myTransferStatus) {
|
|
30492
|
+
if (attempt < maxAttempts) {
|
|
30493
|
+
logger.info(
|
|
30494
|
+
`Withdrawal status not found for orderId ${orderId} in completed operations, retrying (attempt ${attempt}/${maxAttempts})...`
|
|
30495
|
+
);
|
|
30496
|
+
await new Promise((resolve) => setTimeout(resolve, retryDelayMs));
|
|
30497
|
+
continue;
|
|
30498
|
+
}
|
|
30499
|
+
logger.warn(
|
|
30500
|
+
`Withdrawal operation not found for orderId ${orderId} after ${maxAttempts} attempts`
|
|
30501
|
+
);
|
|
30502
|
+
return false;
|
|
30503
|
+
}
|
|
30504
|
+
if (myTransferStatus.status === "COMPLETED" /* COMPLETED */) {
|
|
30505
|
+
logger.info(
|
|
30506
|
+
`Withdrawal operation ${orderId} completed successfully`
|
|
30507
|
+
);
|
|
30508
|
+
return true;
|
|
30509
|
+
} else {
|
|
30510
|
+
if (attempt < maxAttempts) {
|
|
30511
|
+
logger.info(
|
|
30512
|
+
`Withdrawal operation ${orderId} found but status is ${myTransferStatus.status}, not COMPLETED. Retrying (attempt ${attempt}/${maxAttempts})...`
|
|
30513
|
+
);
|
|
30514
|
+
await new Promise((resolve) => setTimeout(resolve, retryDelayMs));
|
|
30515
|
+
continue;
|
|
30516
|
+
}
|
|
30517
|
+
logger.warn(
|
|
30518
|
+
`Withdrawal operation ${orderId} status is ${myTransferStatus.status} after ${maxAttempts} attempts, expected COMPLETED`
|
|
30519
|
+
);
|
|
30520
|
+
return false;
|
|
30521
|
+
}
|
|
30335
30522
|
}
|
|
30336
|
-
|
|
30337
|
-
|
|
30338
|
-
|
|
30339
|
-
(operation) => operation.id.toString() === orderId.toString()
|
|
30523
|
+
} catch (err) {
|
|
30524
|
+
logger.error(
|
|
30525
|
+
`error getting deposit or withdrawal status (attempt ${attempt}/${maxAttempts}): ${err}`
|
|
30340
30526
|
);
|
|
30341
|
-
if (
|
|
30342
|
-
|
|
30527
|
+
if (attempt < maxAttempts) {
|
|
30528
|
+
logger.info(`Retrying after ${retryDelayMs}ms...`);
|
|
30529
|
+
await new Promise((resolve) => setTimeout(resolve, retryDelayMs));
|
|
30530
|
+
continue;
|
|
30343
30531
|
}
|
|
30344
|
-
|
|
30532
|
+
logger.error(
|
|
30533
|
+
`Max retry attempts reached for getDepositOrWithdrawalStatus`
|
|
30534
|
+
);
|
|
30535
|
+
return false;
|
|
30345
30536
|
}
|
|
30346
|
-
} catch (err) {
|
|
30347
|
-
logger.error(`error getting deposit or withdrawal status: ${err}`);
|
|
30348
|
-
return false;
|
|
30349
30537
|
}
|
|
30538
|
+
return false;
|
|
30350
30539
|
}
|
|
30351
30540
|
};
|
|
30352
30541
|
|
|
@@ -34296,11 +34485,27 @@ var VesuExtendedMultiplierStrategy = class _VesuExtendedMultiplierStrategy exten
|
|
|
34296
34485
|
}
|
|
34297
34486
|
async shouldInvest() {
|
|
34298
34487
|
try {
|
|
34488
|
+
logger.info(`${_VesuExtendedMultiplierStrategy.name}::shouldInvest starting`);
|
|
34299
34489
|
const vesuAdapter = await this.getVesuAdapter();
|
|
34300
34490
|
const extendedAdapter = await this.getExtendedAdapter();
|
|
34301
|
-
|
|
34491
|
+
logger.info(`${_VesuExtendedMultiplierStrategy.name}::shouldInvest adapters fetched: vesuAdapter=${!!vesuAdapter}, extendedAdapter=${!!extendedAdapter}, extendedAdapter.client=${!!extendedAdapter?.client}`);
|
|
34492
|
+
if (!vesuAdapter) {
|
|
34302
34493
|
logger.error(
|
|
34303
|
-
`
|
|
34494
|
+
`Vesu adapter not configured in metadata. This is a configuration issue, not a temporary failure.`
|
|
34495
|
+
);
|
|
34496
|
+
return {
|
|
34497
|
+
shouldInvest: false,
|
|
34498
|
+
vesuAmount: new Web3Number(0, 0),
|
|
34499
|
+
extendedAmount: new Web3Number(0, 0),
|
|
34500
|
+
extendedLeverage: 0,
|
|
34501
|
+
collateralPrice: 0,
|
|
34502
|
+
debtPrice: 0,
|
|
34503
|
+
vesuLeverage: 0
|
|
34504
|
+
};
|
|
34505
|
+
}
|
|
34506
|
+
if (!extendedAdapter) {
|
|
34507
|
+
logger.error(
|
|
34508
|
+
`Extended adapter not configured in metadata. This is a configuration issue, not a temporary failure.`
|
|
34304
34509
|
);
|
|
34305
34510
|
return {
|
|
34306
34511
|
shouldInvest: false,
|
|
@@ -34312,10 +34517,72 @@ var VesuExtendedMultiplierStrategy = class _VesuExtendedMultiplierStrategy exten
|
|
|
34312
34517
|
vesuLeverage: 0
|
|
34313
34518
|
};
|
|
34314
34519
|
}
|
|
34520
|
+
if (!extendedAdapter.client) {
|
|
34521
|
+
logger.error(
|
|
34522
|
+
`Extended adapter client not initialized. This may be a temporary initialization failure - check network connectivity and API availability.`
|
|
34523
|
+
);
|
|
34524
|
+
return {
|
|
34525
|
+
shouldInvest: false,
|
|
34526
|
+
vesuAmount: new Web3Number(0, 0),
|
|
34527
|
+
extendedAmount: new Web3Number(0, 0),
|
|
34528
|
+
extendedLeverage: 0,
|
|
34529
|
+
collateralPrice: 0,
|
|
34530
|
+
debtPrice: 0,
|
|
34531
|
+
vesuLeverage: 0
|
|
34532
|
+
};
|
|
34533
|
+
}
|
|
34534
|
+
logger.info(`${_VesuExtendedMultiplierStrategy.name}::shouldInvest calling getUnusedBalance`);
|
|
34315
34535
|
const balance = await this.getUnusedBalance();
|
|
34536
|
+
if (!Number.isFinite(balance.usdValue) || balance.usdValue < 0) {
|
|
34537
|
+
logger.error(
|
|
34538
|
+
`Invalid balance.usdValue: ${balance.usdValue}. Expected a finite, non-negative number.`
|
|
34539
|
+
);
|
|
34540
|
+
return {
|
|
34541
|
+
shouldInvest: false,
|
|
34542
|
+
vesuAmount: new Web3Number(0, 0),
|
|
34543
|
+
extendedAmount: new Web3Number(0, 0),
|
|
34544
|
+
extendedLeverage: 0,
|
|
34545
|
+
collateralPrice: 0,
|
|
34546
|
+
debtPrice: 0,
|
|
34547
|
+
vesuLeverage: 0
|
|
34548
|
+
};
|
|
34549
|
+
}
|
|
34550
|
+
logger.info(`${_VesuExtendedMultiplierStrategy.name}::shouldInvest balance: ${balance.usdValue}`);
|
|
34316
34551
|
const usdcBalanceOnExtended = await extendedAdapter.getExtendedDepositAmount();
|
|
34552
|
+
if (usdcBalanceOnExtended) {
|
|
34553
|
+
const availableForWithdrawal = parseFloat(usdcBalanceOnExtended.availableForWithdrawal);
|
|
34554
|
+
if (!Number.isFinite(availableForWithdrawal) || availableForWithdrawal < 0) {
|
|
34555
|
+
logger.error(
|
|
34556
|
+
`Invalid usdcBalanceOnExtended.availableForWithdrawal: ${usdcBalanceOnExtended.availableForWithdrawal}. Expected a finite, non-negative number.`
|
|
34557
|
+
);
|
|
34558
|
+
return {
|
|
34559
|
+
shouldInvest: false,
|
|
34560
|
+
vesuAmount: new Web3Number(0, 0),
|
|
34561
|
+
extendedAmount: new Web3Number(0, 0),
|
|
34562
|
+
extendedLeverage: 0,
|
|
34563
|
+
collateralPrice: 0,
|
|
34564
|
+
debtPrice: 0,
|
|
34565
|
+
vesuLeverage: 0
|
|
34566
|
+
};
|
|
34567
|
+
}
|
|
34568
|
+
}
|
|
34317
34569
|
const amountToInvest = new Web3Number(balance.usdValue, USDC_TOKEN_DECIMALS).plus(usdcBalanceOnExtended?.availableForWithdrawal ?? 0).multipliedBy(1 - LIMIT_BALANCE);
|
|
34318
|
-
|
|
34570
|
+
const amountToInvestNumber = amountToInvest.toNumber();
|
|
34571
|
+
if (!Number.isFinite(amountToInvestNumber)) {
|
|
34572
|
+
logger.error(
|
|
34573
|
+
`Invalid amountToInvest calculation result: ${amountToInvestNumber}. Calculation may have produced NaN or Infinity.`
|
|
34574
|
+
);
|
|
34575
|
+
return {
|
|
34576
|
+
shouldInvest: false,
|
|
34577
|
+
vesuAmount: new Web3Number(0, 0),
|
|
34578
|
+
extendedAmount: new Web3Number(0, 0),
|
|
34579
|
+
extendedLeverage: 0,
|
|
34580
|
+
collateralPrice: 0,
|
|
34581
|
+
debtPrice: 0,
|
|
34582
|
+
vesuLeverage: 0
|
|
34583
|
+
};
|
|
34584
|
+
}
|
|
34585
|
+
logger.info(`${_VesuExtendedMultiplierStrategy.name}::shouldInvest amountToInvest: ${amountToInvestNumber}`);
|
|
34319
34586
|
if (amountToInvest.lessThan(0)) {
|
|
34320
34587
|
return {
|
|
34321
34588
|
shouldInvest: false,
|
|
@@ -34345,6 +34612,34 @@ var VesuExtendedMultiplierStrategy = class _VesuExtendedMultiplierStrategy exten
|
|
|
34345
34612
|
collateralPrice,
|
|
34346
34613
|
debtPrice
|
|
34347
34614
|
} = await this.getAssetPrices();
|
|
34615
|
+
if (!Number.isFinite(collateralPrice.price) || collateralPrice.price <= 0) {
|
|
34616
|
+
logger.error(
|
|
34617
|
+
`Invalid collateralPrice: ${collateralPrice.price}. Expected a finite, positive number.`
|
|
34618
|
+
);
|
|
34619
|
+
return {
|
|
34620
|
+
shouldInvest: false,
|
|
34621
|
+
vesuAmount: new Web3Number(0, 0),
|
|
34622
|
+
extendedAmount: new Web3Number(0, 0),
|
|
34623
|
+
extendedLeverage: 0,
|
|
34624
|
+
collateralPrice: 0,
|
|
34625
|
+
debtPrice: 0,
|
|
34626
|
+
vesuLeverage: 0
|
|
34627
|
+
};
|
|
34628
|
+
}
|
|
34629
|
+
if (!Number.isFinite(debtPrice.price) || debtPrice.price <= 0) {
|
|
34630
|
+
logger.error(
|
|
34631
|
+
`Invalid debtPrice: ${debtPrice.price}. Expected a finite, positive number.`
|
|
34632
|
+
);
|
|
34633
|
+
return {
|
|
34634
|
+
shouldInvest: false,
|
|
34635
|
+
vesuAmount: new Web3Number(0, 0),
|
|
34636
|
+
extendedAmount: new Web3Number(0, 0),
|
|
34637
|
+
extendedLeverage: 0,
|
|
34638
|
+
collateralPrice: 0,
|
|
34639
|
+
debtPrice: 0,
|
|
34640
|
+
vesuLeverage: 0
|
|
34641
|
+
};
|
|
34642
|
+
}
|
|
34348
34643
|
const { vesu_amount, extended_amount, extended_leverage, vesu_leverage } = await calculateAmountDistribution(
|
|
34349
34644
|
amountToInvest.toNumber(),
|
|
34350
34645
|
extendedAdapter.client,
|
|
@@ -34395,13 +34690,45 @@ var VesuExtendedMultiplierStrategy = class _VesuExtendedMultiplierStrategy exten
|
|
|
34395
34690
|
try {
|
|
34396
34691
|
const vesuAdapter = await this.getVesuAdapter();
|
|
34397
34692
|
const extendedAdapter = await this.getExtendedAdapter();
|
|
34398
|
-
let calls = [];
|
|
34399
34693
|
if (!vesuAdapter || !extendedAdapter || !extendedAdapter.client) {
|
|
34400
34694
|
logger.error(
|
|
34401
34695
|
`vesu or extended adapter not found: vesuAdapter=${vesuAdapter}, extendedAdapter=${extendedAdapter}`
|
|
34402
34696
|
);
|
|
34403
|
-
return
|
|
34697
|
+
return [];
|
|
34698
|
+
}
|
|
34699
|
+
const extendedHoldings = await extendedAdapter.getExtendedDepositAmount();
|
|
34700
|
+
if (!extendedHoldings) {
|
|
34701
|
+
logger.error(`error getting extended holdings: ${extendedHoldings}`);
|
|
34702
|
+
return [];
|
|
34404
34703
|
}
|
|
34704
|
+
const usdcAmountInWallet = (await this.getUnusedBalance()).amount;
|
|
34705
|
+
const usdcAmountOnExtendedAvailableForWithdrawal = parseFloat(
|
|
34706
|
+
extendedHoldings.availableForWithdrawal
|
|
34707
|
+
);
|
|
34708
|
+
logger.info(`${_VesuExtendedMultiplierStrategy.name}::shouldMoveAssets calculating movements - Extended current: ${usdcAmountOnExtendedAvailableForWithdrawal}, Wallet: ${usdcAmountInWallet.toNumber()}, Target Extended: ${extendedAmount.toNumber()}, Target Vesu: ${vesuAmount.toNumber()}`);
|
|
34709
|
+
let totalExtendedWithdrawal = new Web3Number(0, USDC_TOKEN_DECIMALS);
|
|
34710
|
+
let totalExtendedDeposit = new Web3Number(0, USDC_TOKEN_DECIMALS);
|
|
34711
|
+
if (extendedAmount.isNegative() && extendedAmount.abs().greaterThan(extendedAdapter.minimumExtendedMovementAmount)) {
|
|
34712
|
+
totalExtendedWithdrawal = totalExtendedWithdrawal.plus(extendedAmount.abs());
|
|
34713
|
+
}
|
|
34714
|
+
const extendedTargetAmount = extendedAmount.abs();
|
|
34715
|
+
let projectedExtendedBalance = usdcAmountOnExtendedAvailableForWithdrawal;
|
|
34716
|
+
if (extendedAmount.isNegative()) {
|
|
34717
|
+
projectedExtendedBalance = projectedExtendedBalance - extendedAmount.abs().toNumber();
|
|
34718
|
+
}
|
|
34719
|
+
const extendedAmountDifference = extendedTargetAmount.minus(projectedExtendedBalance);
|
|
34720
|
+
const extendedAmountDifferenceAbs = extendedAmountDifference.abs();
|
|
34721
|
+
if (extendedAmountDifference.lessThan(0)) {
|
|
34722
|
+
totalExtendedWithdrawal = totalExtendedWithdrawal.plus(extendedAmountDifferenceAbs);
|
|
34723
|
+
} else if (extendedAmountDifference.greaterThan(0)) {
|
|
34724
|
+
totalExtendedDeposit = totalExtendedDeposit.plus(extendedAmountDifference);
|
|
34725
|
+
}
|
|
34726
|
+
const vesuTargetAmount = vesuAmount.abs();
|
|
34727
|
+
const projectedWalletBalance = usdcAmountInWallet.plus(totalExtendedWithdrawal).minus(totalExtendedDeposit);
|
|
34728
|
+
let vesuAmountDifference = vesuTargetAmount.minus(projectedWalletBalance);
|
|
34729
|
+
const vesuAmountDifferenceAbs = vesuAmountDifference.abs();
|
|
34730
|
+
logger.info(`${_VesuExtendedMultiplierStrategy.name}::shouldMoveAssets calculated movements - Extended withdrawal: ${totalExtendedWithdrawal.toNumber()}, Extended deposit: ${totalExtendedDeposit.toNumber()}, Extended diff: ${extendedAmountDifference.toNumber()}, Projected wallet: ${projectedWalletBalance.toNumber()}, Vesu diff: ${vesuAmountDifference.toNumber()}`);
|
|
34731
|
+
let calls = [];
|
|
34405
34732
|
if (extendedAmount.isNegative() && extendedAmount.abs().greaterThan(extendedAdapter.minimumExtendedMovementAmount)) {
|
|
34406
34733
|
try {
|
|
34407
34734
|
const { calls: extendedCalls, status: extendedStatus } = await this.moveAssets(
|
|
@@ -34422,7 +34749,7 @@ var VesuExtendedMultiplierStrategy = class _VesuExtendedMultiplierStrategy exten
|
|
|
34422
34749
|
logger.error(`Failed moving assets to vault: ${err}`);
|
|
34423
34750
|
}
|
|
34424
34751
|
}
|
|
34425
|
-
if (vesuAmount.isNegative() && vesuAmount.
|
|
34752
|
+
if (vesuAmount.isNegative() && vesuAmount.abs().greaterThan(vesuAdapter.minimumVesuMovementAmount)) {
|
|
34426
34753
|
try {
|
|
34427
34754
|
const { calls: vesuCalls, status: vesuStatus } = await this.moveAssets(
|
|
34428
34755
|
{
|
|
@@ -34441,48 +34768,76 @@ var VesuExtendedMultiplierStrategy = class _VesuExtendedMultiplierStrategy exten
|
|
|
34441
34768
|
logger.error(`Failed moving assets to vault: ${err}`);
|
|
34442
34769
|
}
|
|
34443
34770
|
}
|
|
34444
|
-
|
|
34445
|
-
|
|
34446
|
-
|
|
34447
|
-
|
|
34448
|
-
|
|
34449
|
-
|
|
34450
|
-
|
|
34451
|
-
|
|
34452
|
-
|
|
34453
|
-
|
|
34454
|
-
|
|
34455
|
-
|
|
34456
|
-
{
|
|
34457
|
-
|
|
34458
|
-
|
|
34459
|
-
|
|
34460
|
-
|
|
34461
|
-
|
|
34462
|
-
|
|
34463
|
-
|
|
34464
|
-
|
|
34465
|
-
|
|
34466
|
-
|
|
34771
|
+
if (extendedAmountDifferenceAbs.greaterThan(extendedAdapter.minimumExtendedMovementAmount)) {
|
|
34772
|
+
if (extendedAmountDifference.greaterThan(0)) {
|
|
34773
|
+
try {
|
|
34774
|
+
const { calls: extendedCalls, status: extendedStatus } = await this.moveAssets(
|
|
34775
|
+
{
|
|
34776
|
+
to: Protocols.EXTENDED.name,
|
|
34777
|
+
from: Protocols.VAULT.name,
|
|
34778
|
+
amount: extendedAmountDifference
|
|
34779
|
+
},
|
|
34780
|
+
extendedAdapter,
|
|
34781
|
+
vesuAdapter
|
|
34782
|
+
);
|
|
34783
|
+
if (extendedStatus) {
|
|
34784
|
+
calls.push(...extendedCalls);
|
|
34785
|
+
} else {
|
|
34786
|
+
logger.error(`Failed to move assets to extended - operation returned false status`);
|
|
34787
|
+
return [];
|
|
34788
|
+
}
|
|
34789
|
+
} catch (err) {
|
|
34790
|
+
logger.error(`Failed moving assets to extended: ${err}`);
|
|
34791
|
+
return [];
|
|
34792
|
+
}
|
|
34793
|
+
} else if (extendedAmountDifference.lessThan(0)) {
|
|
34794
|
+
try {
|
|
34795
|
+
const { calls: extendedCalls, status: extendedStatus } = await this.moveAssets(
|
|
34796
|
+
{
|
|
34797
|
+
to: Protocols.VAULT.name,
|
|
34798
|
+
from: Protocols.EXTENDED.name,
|
|
34799
|
+
amount: extendedAmountDifferenceAbs
|
|
34800
|
+
},
|
|
34801
|
+
extendedAdapter,
|
|
34802
|
+
vesuAdapter
|
|
34803
|
+
);
|
|
34804
|
+
if (extendedStatus) {
|
|
34805
|
+
calls.push(...extendedCalls);
|
|
34806
|
+
} else {
|
|
34807
|
+
logger.error(`Failed to withdraw from extended - operation returned false status`);
|
|
34808
|
+
return [];
|
|
34809
|
+
}
|
|
34810
|
+
} catch (err) {
|
|
34811
|
+
logger.error(`Failed moving assets from extended to vault: ${err}`);
|
|
34812
|
+
return [];
|
|
34813
|
+
}
|
|
34467
34814
|
}
|
|
34468
34815
|
}
|
|
34469
|
-
if (
|
|
34470
|
-
|
|
34471
|
-
|
|
34472
|
-
{
|
|
34473
|
-
to: Protocols.VAULT.name,
|
|
34474
|
-
from: Protocols.EXTENDED.name,
|
|
34475
|
-
amount: vesuAmount.minus(usdcAmountInWallet)
|
|
34476
|
-
},
|
|
34477
|
-
extendedAdapter,
|
|
34478
|
-
vesuAdapter
|
|
34816
|
+
if (vesuAmountDifferenceAbs.greaterThan(vesuAdapter.minimumVesuMovementAmount)) {
|
|
34817
|
+
if (vesuAmountDifference.lessThanOrEqualTo(0)) {
|
|
34818
|
+
logger.warn(
|
|
34819
|
+
`Vesu amount difference is negative or zero: ${vesuAmountDifference.toNumber()}. Skipping operation.`
|
|
34479
34820
|
);
|
|
34480
|
-
|
|
34821
|
+
} else {
|
|
34822
|
+
try {
|
|
34823
|
+
const { calls: vesuCalls, status: vesuStatus } = await this.moveAssets(
|
|
34824
|
+
{
|
|
34825
|
+
to: Protocols.VAULT.name,
|
|
34826
|
+
from: Protocols.EXTENDED.name,
|
|
34827
|
+
amount: vesuAmountDifference
|
|
34828
|
+
},
|
|
34829
|
+
extendedAdapter,
|
|
34830
|
+
vesuAdapter
|
|
34831
|
+
);
|
|
34832
|
+
if (!vesuStatus) {
|
|
34833
|
+
logger.error(`Failed to move assets to vesu - operation returned false status`);
|
|
34834
|
+
return [];
|
|
34835
|
+
}
|
|
34836
|
+
calls.push(...vesuCalls);
|
|
34837
|
+
} catch (err) {
|
|
34838
|
+
logger.error(`Failed moving assets to vault: ${err}`);
|
|
34481
34839
|
return [];
|
|
34482
34840
|
}
|
|
34483
|
-
calls.push(...vesuCalls);
|
|
34484
|
-
} catch (err) {
|
|
34485
|
-
logger.error(`Failed moving assets to vault: ${err}`);
|
|
34486
34841
|
}
|
|
34487
34842
|
}
|
|
34488
34843
|
return calls;
|
|
@@ -34493,6 +34848,38 @@ var VesuExtendedMultiplierStrategy = class _VesuExtendedMultiplierStrategy exten
|
|
|
34493
34848
|
}
|
|
34494
34849
|
async moveAssets(params, extendedAdapter, vesuAdapter) {
|
|
34495
34850
|
try {
|
|
34851
|
+
if (params.amount.lessThanOrEqualTo(0)) {
|
|
34852
|
+
logger.error(
|
|
34853
|
+
`Invalid amount for moveAssets: ${params.amount.toNumber()}. Amount must be positive.`
|
|
34854
|
+
);
|
|
34855
|
+
return {
|
|
34856
|
+
calls: [],
|
|
34857
|
+
status: false
|
|
34858
|
+
};
|
|
34859
|
+
}
|
|
34860
|
+
const amountAbs = params.amount.abs();
|
|
34861
|
+
if (params.from === Protocols.EXTENDED.name || params.to === Protocols.EXTENDED.name) {
|
|
34862
|
+
if (amountAbs.lessThanOrEqualTo(extendedAdapter.minimumExtendedMovementAmount)) {
|
|
34863
|
+
logger.warn(
|
|
34864
|
+
`Amount ${amountAbs.toNumber()} is below minimum Extended movement amount ${extendedAdapter.minimumExtendedMovementAmount}. Skipping operation.`
|
|
34865
|
+
);
|
|
34866
|
+
return {
|
|
34867
|
+
calls: [],
|
|
34868
|
+
status: false
|
|
34869
|
+
};
|
|
34870
|
+
}
|
|
34871
|
+
}
|
|
34872
|
+
if (params.from === Protocols.VESU.name || params.to === Protocols.VESU.name) {
|
|
34873
|
+
if (amountAbs.lessThanOrEqualTo(vesuAdapter.minimumVesuMovementAmount)) {
|
|
34874
|
+
logger.warn(
|
|
34875
|
+
`Amount ${amountAbs.toNumber()} is below minimum Vesu movement amount ${vesuAdapter.minimumVesuMovementAmount}. Skipping operation.`
|
|
34876
|
+
);
|
|
34877
|
+
return {
|
|
34878
|
+
calls: [],
|
|
34879
|
+
status: false
|
|
34880
|
+
};
|
|
34881
|
+
}
|
|
34882
|
+
}
|
|
34496
34883
|
const avnuAdapter = await this.getAvnuAdapter();
|
|
34497
34884
|
if (!avnuAdapter) {
|
|
34498
34885
|
logger.error(`avnu adapter not found: ${avnuAdapter}`);
|
|
@@ -34553,18 +34940,18 @@ var VesuExtendedMultiplierStrategy = class _VesuExtendedMultiplierStrategy exten
|
|
|
34553
34940
|
);
|
|
34554
34941
|
if (!openLongPosition) {
|
|
34555
34942
|
logger.error(`error opening long position: ${openLongPosition}`);
|
|
34556
|
-
return {
|
|
34557
|
-
calls: [],
|
|
34558
|
-
status: false
|
|
34559
|
-
};
|
|
34560
34943
|
}
|
|
34561
|
-
|
|
34944
|
+
const updatedHoldings = await extendedAdapter.getExtendedDepositAmount();
|
|
34945
|
+
if (!updatedHoldings || new Web3Number(updatedHoldings.availableForWithdrawal, USDC_TOKEN_DECIMALS).lessThan(params.amount.abs())) {
|
|
34946
|
+
logger.error(`Insufficient balance after opening position. Available: ${updatedHoldings?.availableForWithdrawal}, Needed: ${params.amount.abs()}`);
|
|
34947
|
+
return { calls: [], status: false };
|
|
34948
|
+
}
|
|
34562
34949
|
}
|
|
34563
34950
|
const withdrawalFromExtended = await extendedAdapter.withdrawFromExtended(params.amount);
|
|
34564
34951
|
if (withdrawalFromExtended) {
|
|
34565
34952
|
const extendedHoldings2 = await extendedAdapter.getExtendedDepositAmount();
|
|
34566
34953
|
logger.info(`extendedHoldings after withdrawal ${extendedHoldings2?.availableForWithdrawal}`);
|
|
34567
|
-
await new Promise((resolve) => setTimeout(resolve,
|
|
34954
|
+
await new Promise((resolve) => setTimeout(resolve, 2e3));
|
|
34568
34955
|
const calls = await this.moveAssetsToVaultAllocator(params.amount, extendedAdapter);
|
|
34569
34956
|
if (calls.length > 0) {
|
|
34570
34957
|
return {
|