@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.browser.mjs
CHANGED
|
@@ -29919,8 +29919,47 @@ var ExtendedAdapter = class _ExtendedAdapter extends BaseAdapter {
|
|
|
29919
29919
|
async withdrawFromExtended(amount) {
|
|
29920
29920
|
try {
|
|
29921
29921
|
if (!this.client) {
|
|
29922
|
-
|
|
29922
|
+
logger.error("Client not initialized");
|
|
29923
|
+
return false;
|
|
29924
|
+
}
|
|
29925
|
+
if (amount.lessThanOrEqualTo(0)) {
|
|
29926
|
+
logger.error(
|
|
29927
|
+
`Invalid withdrawal amount: ${amount.toNumber()}. Amount must be positive.`
|
|
29928
|
+
);
|
|
29929
|
+
return false;
|
|
29930
|
+
}
|
|
29931
|
+
if (amount.lessThanOrEqualTo(this.minimumExtendedMovementAmount)) {
|
|
29932
|
+
logger.warn(
|
|
29933
|
+
`Withdrawal amount ${amount.toNumber()} is below minimum Extended movement amount ${this.minimumExtendedMovementAmount}. Skipping withdrawal.`
|
|
29934
|
+
);
|
|
29935
|
+
return false;
|
|
29936
|
+
}
|
|
29937
|
+
const holdings = await this.getExtendedDepositAmount();
|
|
29938
|
+
if (!holdings) {
|
|
29939
|
+
logger.error(
|
|
29940
|
+
"Cannot get holdings - unable to validate withdrawal amount"
|
|
29941
|
+
);
|
|
29942
|
+
return false;
|
|
29923
29943
|
}
|
|
29944
|
+
const availableForWithdrawal = parseFloat(
|
|
29945
|
+
holdings.availableForWithdrawal
|
|
29946
|
+
);
|
|
29947
|
+
if (!Number.isFinite(availableForWithdrawal) || availableForWithdrawal < 0) {
|
|
29948
|
+
logger.error(
|
|
29949
|
+
`Invalid availableForWithdrawal: ${holdings.availableForWithdrawal}. Expected a finite, non-negative number.`
|
|
29950
|
+
);
|
|
29951
|
+
return false;
|
|
29952
|
+
}
|
|
29953
|
+
const withdrawalAmount = amount.toNumber();
|
|
29954
|
+
if (withdrawalAmount > availableForWithdrawal) {
|
|
29955
|
+
logger.error(
|
|
29956
|
+
`Withdrawal amount ${withdrawalAmount} exceeds available balance ${availableForWithdrawal}`
|
|
29957
|
+
);
|
|
29958
|
+
return false;
|
|
29959
|
+
}
|
|
29960
|
+
logger.info(
|
|
29961
|
+
`Withdrawing ${withdrawalAmount} from Extended. Available balance: ${availableForWithdrawal}`
|
|
29962
|
+
);
|
|
29924
29963
|
const withdrawalRequest = await this.client.withdrawUSDC(
|
|
29925
29964
|
amount.toFixed(2)
|
|
29926
29965
|
);
|
|
@@ -29931,6 +29970,9 @@ var ExtendedAdapter = class _ExtendedAdapter extends BaseAdapter {
|
|
|
29931
29970
|
);
|
|
29932
29971
|
return withdrawalStatus;
|
|
29933
29972
|
}
|
|
29973
|
+
logger.error(
|
|
29974
|
+
`Withdrawal request failed with status: ${withdrawalRequest.status}`
|
|
29975
|
+
);
|
|
29934
29976
|
return false;
|
|
29935
29977
|
} catch (error) {
|
|
29936
29978
|
logger.error(`Error creating Withdraw Call: ${error}`);
|
|
@@ -29941,21 +29983,44 @@ var ExtendedAdapter = class _ExtendedAdapter extends BaseAdapter {
|
|
|
29941
29983
|
return Promise.resolve(1);
|
|
29942
29984
|
}
|
|
29943
29985
|
async getExtendedDepositAmount() {
|
|
29944
|
-
|
|
29945
|
-
|
|
29946
|
-
|
|
29947
|
-
|
|
29948
|
-
|
|
29949
|
-
|
|
29950
|
-
|
|
29951
|
-
|
|
29952
|
-
|
|
29953
|
-
|
|
29954
|
-
|
|
29955
|
-
|
|
29986
|
+
try {
|
|
29987
|
+
if (this.client === null) {
|
|
29988
|
+
logger.error("error initializing client - client is null");
|
|
29989
|
+
return void 0;
|
|
29990
|
+
}
|
|
29991
|
+
const result = await this.client.getHoldings();
|
|
29992
|
+
if (!result) {
|
|
29993
|
+
logger.error("error getting holdings - API returned null/undefined");
|
|
29994
|
+
return void 0;
|
|
29995
|
+
}
|
|
29996
|
+
if (result.status && result.status !== "OK") {
|
|
29997
|
+
logger.error(
|
|
29998
|
+
`error getting holdings - API returned status: ${result.status}`
|
|
29999
|
+
);
|
|
30000
|
+
return void 0;
|
|
30001
|
+
}
|
|
30002
|
+
const holdings = result.data;
|
|
30003
|
+
if (!holdings) {
|
|
30004
|
+
logger.warn(
|
|
30005
|
+
"holdings data is null/undefined - treating as zero balance"
|
|
30006
|
+
);
|
|
30007
|
+
return {
|
|
30008
|
+
collateral_name: "",
|
|
30009
|
+
balance: "0",
|
|
30010
|
+
equity: "0",
|
|
30011
|
+
availableForTrade: "0",
|
|
30012
|
+
availableForWithdrawal: "0",
|
|
30013
|
+
unrealisedPnl: "0",
|
|
30014
|
+
initialMargin: "0",
|
|
30015
|
+
marginRatio: "0",
|
|
30016
|
+
updatedTime: Date.now()
|
|
30017
|
+
};
|
|
30018
|
+
}
|
|
30019
|
+
return holdings;
|
|
30020
|
+
} catch (error) {
|
|
30021
|
+
logger.error(`error getting holdings - exception: ${error}`);
|
|
29956
30022
|
return void 0;
|
|
29957
30023
|
}
|
|
29958
|
-
return holdings;
|
|
29959
30024
|
}
|
|
29960
30025
|
async setLeverage(leverage, marketName) {
|
|
29961
30026
|
if (this.client === null) {
|
|
@@ -29997,38 +30062,24 @@ var ExtendedAdapter = class _ExtendedAdapter extends BaseAdapter {
|
|
|
29997
30062
|
return result.data;
|
|
29998
30063
|
}
|
|
29999
30064
|
async getOrderStatus(orderId, marketName) {
|
|
30000
|
-
|
|
30001
|
-
|
|
30002
|
-
|
|
30003
|
-
|
|
30004
|
-
let orderhistory = await this.getOrderHistory(marketName);
|
|
30005
|
-
if (!orderhistory || orderhistory.length === 0) {
|
|
30006
|
-
logger.error(`error getting order history: ${orderId}`);
|
|
30007
|
-
} else {
|
|
30008
|
-
const order = orderhistory.slice(0, 10).find((order2) => order2.id.toString() === orderId);
|
|
30009
|
-
if (order) {
|
|
30010
|
-
return order;
|
|
30065
|
+
try {
|
|
30066
|
+
if (this.client === null) {
|
|
30067
|
+
logger.error("error initializing client");
|
|
30068
|
+
return null;
|
|
30011
30069
|
}
|
|
30012
|
-
|
|
30013
|
-
for (let attempt = 1; attempt <= 5; attempt++) {
|
|
30014
|
-
await new Promise((resolve) => setTimeout(resolve, this.retryDelayForOrderStatus));
|
|
30015
|
-
orderhistory = await this.getOrderHistory(marketName);
|
|
30070
|
+
const orderhistory = await this.getOrderHistory(marketName);
|
|
30016
30071
|
if (!orderhistory || orderhistory.length === 0) {
|
|
30017
|
-
|
|
30018
|
-
`error getting order history on retry ${attempt}: ${orderId}`
|
|
30019
|
-
);
|
|
30020
|
-
continue;
|
|
30072
|
+
return null;
|
|
30021
30073
|
}
|
|
30022
|
-
const order = orderhistory.slice(0,
|
|
30023
|
-
if (order
|
|
30074
|
+
const order = orderhistory.slice(0, 20).find((order2) => order2.id.toString() === orderId);
|
|
30075
|
+
if (order) {
|
|
30024
30076
|
return order;
|
|
30025
30077
|
}
|
|
30026
|
-
|
|
30027
|
-
|
|
30028
|
-
);
|
|
30078
|
+
return null;
|
|
30079
|
+
} catch (error) {
|
|
30080
|
+
logger.error(`error getting order status: ${error}`);
|
|
30081
|
+
return null;
|
|
30029
30082
|
}
|
|
30030
|
-
logger.error(`error getting order after all retries: ${orderId}`);
|
|
30031
|
-
return null;
|
|
30032
30083
|
}
|
|
30033
30084
|
async fetchOrderBookBTCUSDC() {
|
|
30034
30085
|
try {
|
|
@@ -30079,14 +30130,40 @@ var ExtendedAdapter = class _ExtendedAdapter extends BaseAdapter {
|
|
|
30079
30130
|
logger.error("error depositing or setting leverage");
|
|
30080
30131
|
return null;
|
|
30081
30132
|
}
|
|
30082
|
-
const
|
|
30083
|
-
if (
|
|
30133
|
+
const { ask, bid } = await this.fetchOrderBookBTCUSDC();
|
|
30134
|
+
if (!ask || !bid || ask.lessThanOrEqualTo(0) || bid.lessThanOrEqualTo(0)) {
|
|
30135
|
+
logger.error(
|
|
30136
|
+
`Invalid orderbook prices: ask=${ask?.toNumber()}, bid=${bid?.toNumber()}`
|
|
30137
|
+
);
|
|
30084
30138
|
return null;
|
|
30085
30139
|
}
|
|
30086
|
-
const { ask, bid } = await this.fetchOrderBookBTCUSDC();
|
|
30087
30140
|
const spread = ask.minus(bid);
|
|
30088
|
-
|
|
30089
|
-
|
|
30141
|
+
const midPrice = ask.plus(bid).div(2);
|
|
30142
|
+
const MAX_PRICE_DEVIATION_MULTIPLIER = 0.5;
|
|
30143
|
+
const priceAdjustmentMultiplier = Math.min(
|
|
30144
|
+
0.2 * attempt,
|
|
30145
|
+
MAX_PRICE_DEVIATION_MULTIPLIER
|
|
30146
|
+
);
|
|
30147
|
+
const priceAdjustment = spread.times(priceAdjustmentMultiplier);
|
|
30148
|
+
let price = midPrice;
|
|
30149
|
+
if (side === "SELL" /* SELL */) {
|
|
30150
|
+
price = midPrice.minus(priceAdjustment);
|
|
30151
|
+
} else {
|
|
30152
|
+
price = midPrice.plus(priceAdjustment);
|
|
30153
|
+
}
|
|
30154
|
+
const maxDeviation = midPrice.times(0.5);
|
|
30155
|
+
if (price.minus(midPrice).abs().greaterThan(maxDeviation)) {
|
|
30156
|
+
logger.error(
|
|
30157
|
+
`Price deviation too large on attempt ${attempt}: price=${price.toNumber()}, midPrice=${midPrice.toNumber()}, deviation=${price.minus(midPrice).abs().toNumber()}`
|
|
30158
|
+
);
|
|
30159
|
+
if (attempt >= maxAttempts) {
|
|
30160
|
+
return null;
|
|
30161
|
+
}
|
|
30162
|
+
price = side === "SELL" /* SELL */ ? midPrice.minus(maxDeviation) : midPrice.plus(maxDeviation);
|
|
30163
|
+
}
|
|
30164
|
+
logger.info(
|
|
30165
|
+
`createOrder attempt ${attempt}/${maxAttempts}: side=${side}, midPrice=${midPrice.toNumber()}, adjustedPrice=${price.toNumber()}, adjustment=${priceAdjustmentMultiplier * 100}%`
|
|
30166
|
+
);
|
|
30090
30167
|
const amount_in_token = (btcAmount * parseInt(leverage)).toFixed(
|
|
30091
30168
|
this.config.extendedPrecision
|
|
30092
30169
|
);
|
|
@@ -30097,17 +30174,57 @@ var ExtendedAdapter = class _ExtendedAdapter extends BaseAdapter {
|
|
|
30097
30174
|
price.toFixed(0),
|
|
30098
30175
|
side
|
|
30099
30176
|
);
|
|
30100
|
-
if (!result) {
|
|
30177
|
+
if (!result || !result.position_id) {
|
|
30178
|
+
logger.error("Failed to create order - no position_id returned");
|
|
30101
30179
|
return null;
|
|
30102
30180
|
}
|
|
30103
|
-
|
|
30104
|
-
|
|
30105
|
-
|
|
30181
|
+
const positionId = result.position_id;
|
|
30182
|
+
logger.info(
|
|
30183
|
+
`Order created with position_id: ${positionId}. Waiting for API to update...`
|
|
30184
|
+
);
|
|
30185
|
+
let openOrder = await this.getOrderStatus(
|
|
30186
|
+
positionId,
|
|
30106
30187
|
this.config.extendedMarketName
|
|
30107
30188
|
);
|
|
30189
|
+
const maxStatusRetries = 3;
|
|
30190
|
+
const statusRetryDelay = 5e3;
|
|
30108
30191
|
if (!openOrder) {
|
|
30192
|
+
logger.warn(
|
|
30193
|
+
`Order ${positionId} not found in API yet. Retrying status fetch (max ${maxStatusRetries} times)...`
|
|
30194
|
+
);
|
|
30195
|
+
for (let statusRetry = 1; statusRetry <= maxStatusRetries; statusRetry++) {
|
|
30196
|
+
await new Promise((resolve) => setTimeout(resolve, statusRetryDelay));
|
|
30197
|
+
openOrder = await this.getOrderStatus(
|
|
30198
|
+
positionId,
|
|
30199
|
+
this.config.extendedMarketName
|
|
30200
|
+
);
|
|
30201
|
+
if (openOrder) {
|
|
30202
|
+
logger.info(
|
|
30203
|
+
`Order ${positionId} found after ${statusRetry} status retry(ies)`
|
|
30204
|
+
);
|
|
30205
|
+
break;
|
|
30206
|
+
}
|
|
30207
|
+
logger.warn(
|
|
30208
|
+
`Order ${positionId} still not found after ${statusRetry}/${maxStatusRetries} status retries`
|
|
30209
|
+
);
|
|
30210
|
+
}
|
|
30211
|
+
}
|
|
30212
|
+
if (openOrder && openOrder.status === "FILLED" /* FILLED */) {
|
|
30213
|
+
logger.info(
|
|
30214
|
+
`Order ${positionId} successfully filled with quantity ${openOrder.qty}`
|
|
30215
|
+
);
|
|
30216
|
+
return {
|
|
30217
|
+
position_id: positionId,
|
|
30218
|
+
btc_exposure: openOrder.qty
|
|
30219
|
+
};
|
|
30220
|
+
} else if (openOrder && openOrder.status !== "FILLED" /* FILLED */) {
|
|
30221
|
+
logger.warn(
|
|
30222
|
+
`Order ${positionId} found but status is ${openOrder.status}, not FILLED. Retrying order creation...`
|
|
30223
|
+
);
|
|
30109
30224
|
if (attempt >= maxAttempts) {
|
|
30110
|
-
logger.error(
|
|
30225
|
+
logger.error(
|
|
30226
|
+
`Max retries reached \u2014 order ${positionId} status is ${openOrder.status}, not FILLED`
|
|
30227
|
+
);
|
|
30111
30228
|
return null;
|
|
30112
30229
|
} else {
|
|
30113
30230
|
const backoff = 2e3 * attempt;
|
|
@@ -30121,9 +30238,12 @@ var ExtendedAdapter = class _ExtendedAdapter extends BaseAdapter {
|
|
|
30121
30238
|
);
|
|
30122
30239
|
}
|
|
30123
30240
|
} else {
|
|
30241
|
+
logger.warn(
|
|
30242
|
+
`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.`
|
|
30243
|
+
);
|
|
30124
30244
|
return {
|
|
30125
|
-
position_id:
|
|
30126
|
-
btc_exposure:
|
|
30245
|
+
position_id: positionId,
|
|
30246
|
+
btc_exposure: amount_in_token
|
|
30127
30247
|
};
|
|
30128
30248
|
}
|
|
30129
30249
|
} catch (err) {
|
|
@@ -30168,32 +30288,101 @@ var ExtendedAdapter = class _ExtendedAdapter extends BaseAdapter {
|
|
|
30168
30288
|
}
|
|
30169
30289
|
}
|
|
30170
30290
|
async getDepositOrWithdrawalStatus(orderId, operationsType) {
|
|
30171
|
-
|
|
30172
|
-
|
|
30173
|
-
|
|
30174
|
-
|
|
30175
|
-
|
|
30176
|
-
|
|
30177
|
-
|
|
30178
|
-
|
|
30179
|
-
)
|
|
30180
|
-
|
|
30181
|
-
|
|
30291
|
+
const maxAttempts = 5;
|
|
30292
|
+
const retryDelayMs = 3e4;
|
|
30293
|
+
for (let attempt = 1; attempt <= maxAttempts; attempt++) {
|
|
30294
|
+
try {
|
|
30295
|
+
let transferHistory = await this.client.getAssetOperations({
|
|
30296
|
+
operationsType: [operationsType],
|
|
30297
|
+
operationsStatus: ["COMPLETED" /* COMPLETED */]
|
|
30298
|
+
});
|
|
30299
|
+
if (operationsType === "DEPOSIT" /* DEPOSIT */) {
|
|
30300
|
+
const myTransferStatus = transferHistory.data.find(
|
|
30301
|
+
(operation) => operation.transactionHash === orderId
|
|
30302
|
+
);
|
|
30303
|
+
if (!myTransferStatus) {
|
|
30304
|
+
if (attempt < maxAttempts) {
|
|
30305
|
+
logger.info(
|
|
30306
|
+
`Deposit operation not found for transactionHash ${orderId}, retrying (attempt ${attempt}/${maxAttempts})...`
|
|
30307
|
+
);
|
|
30308
|
+
await new Promise((resolve) => setTimeout(resolve, retryDelayMs));
|
|
30309
|
+
continue;
|
|
30310
|
+
}
|
|
30311
|
+
logger.warn(
|
|
30312
|
+
`Deposit operation not found for transactionHash ${orderId} after ${maxAttempts} attempts`
|
|
30313
|
+
);
|
|
30314
|
+
return false;
|
|
30315
|
+
}
|
|
30316
|
+
if (myTransferStatus.status === "COMPLETED" /* COMPLETED */) {
|
|
30317
|
+
logger.info(
|
|
30318
|
+
`Deposit operation ${orderId} completed successfully`
|
|
30319
|
+
);
|
|
30320
|
+
return true;
|
|
30321
|
+
} else {
|
|
30322
|
+
if (attempt < maxAttempts) {
|
|
30323
|
+
logger.info(
|
|
30324
|
+
`Deposit operation ${orderId} found but status is ${myTransferStatus.status}, not COMPLETED. Retrying (attempt ${attempt}/${maxAttempts})...`
|
|
30325
|
+
);
|
|
30326
|
+
await new Promise((resolve) => setTimeout(resolve, retryDelayMs));
|
|
30327
|
+
continue;
|
|
30328
|
+
}
|
|
30329
|
+
logger.warn(
|
|
30330
|
+
`Deposit operation ${orderId} status is ${myTransferStatus.status} after ${maxAttempts} attempts, expected COMPLETED`
|
|
30331
|
+
);
|
|
30332
|
+
return false;
|
|
30333
|
+
}
|
|
30334
|
+
} else {
|
|
30335
|
+
const myTransferStatus = transferHistory.data.find(
|
|
30336
|
+
(operation) => operation.id.toString() === orderId.toString()
|
|
30337
|
+
);
|
|
30338
|
+
if (!myTransferStatus) {
|
|
30339
|
+
if (attempt < maxAttempts) {
|
|
30340
|
+
logger.info(
|
|
30341
|
+
`Withdrawal status not found for orderId ${orderId} in completed operations, retrying (attempt ${attempt}/${maxAttempts})...`
|
|
30342
|
+
);
|
|
30343
|
+
await new Promise((resolve) => setTimeout(resolve, retryDelayMs));
|
|
30344
|
+
continue;
|
|
30345
|
+
}
|
|
30346
|
+
logger.warn(
|
|
30347
|
+
`Withdrawal operation not found for orderId ${orderId} after ${maxAttempts} attempts`
|
|
30348
|
+
);
|
|
30349
|
+
return false;
|
|
30350
|
+
}
|
|
30351
|
+
if (myTransferStatus.status === "COMPLETED" /* COMPLETED */) {
|
|
30352
|
+
logger.info(
|
|
30353
|
+
`Withdrawal operation ${orderId} completed successfully`
|
|
30354
|
+
);
|
|
30355
|
+
return true;
|
|
30356
|
+
} else {
|
|
30357
|
+
if (attempt < maxAttempts) {
|
|
30358
|
+
logger.info(
|
|
30359
|
+
`Withdrawal operation ${orderId} found but status is ${myTransferStatus.status}, not COMPLETED. Retrying (attempt ${attempt}/${maxAttempts})...`
|
|
30360
|
+
);
|
|
30361
|
+
await new Promise((resolve) => setTimeout(resolve, retryDelayMs));
|
|
30362
|
+
continue;
|
|
30363
|
+
}
|
|
30364
|
+
logger.warn(
|
|
30365
|
+
`Withdrawal operation ${orderId} status is ${myTransferStatus.status} after ${maxAttempts} attempts, expected COMPLETED`
|
|
30366
|
+
);
|
|
30367
|
+
return false;
|
|
30368
|
+
}
|
|
30182
30369
|
}
|
|
30183
|
-
|
|
30184
|
-
|
|
30185
|
-
|
|
30186
|
-
(operation) => operation.id.toString() === orderId.toString()
|
|
30370
|
+
} catch (err) {
|
|
30371
|
+
logger.error(
|
|
30372
|
+
`error getting deposit or withdrawal status (attempt ${attempt}/${maxAttempts}): ${err}`
|
|
30187
30373
|
);
|
|
30188
|
-
if (
|
|
30189
|
-
|
|
30374
|
+
if (attempt < maxAttempts) {
|
|
30375
|
+
logger.info(`Retrying after ${retryDelayMs}ms...`);
|
|
30376
|
+
await new Promise((resolve) => setTimeout(resolve, retryDelayMs));
|
|
30377
|
+
continue;
|
|
30190
30378
|
}
|
|
30191
|
-
|
|
30379
|
+
logger.error(
|
|
30380
|
+
`Max retry attempts reached for getDepositOrWithdrawalStatus`
|
|
30381
|
+
);
|
|
30382
|
+
return false;
|
|
30192
30383
|
}
|
|
30193
|
-
} catch (err) {
|
|
30194
|
-
logger.error(`error getting deposit or withdrawal status: ${err}`);
|
|
30195
|
-
return false;
|
|
30196
30384
|
}
|
|
30385
|
+
return false;
|
|
30197
30386
|
}
|
|
30198
30387
|
};
|
|
30199
30388
|
|
|
@@ -34143,11 +34332,27 @@ var VesuExtendedMultiplierStrategy = class _VesuExtendedMultiplierStrategy exten
|
|
|
34143
34332
|
}
|
|
34144
34333
|
async shouldInvest() {
|
|
34145
34334
|
try {
|
|
34335
|
+
logger.info(`${_VesuExtendedMultiplierStrategy.name}::shouldInvest starting`);
|
|
34146
34336
|
const vesuAdapter = await this.getVesuAdapter();
|
|
34147
34337
|
const extendedAdapter = await this.getExtendedAdapter();
|
|
34148
|
-
|
|
34338
|
+
logger.info(`${_VesuExtendedMultiplierStrategy.name}::shouldInvest adapters fetched: vesuAdapter=${!!vesuAdapter}, extendedAdapter=${!!extendedAdapter}, extendedAdapter.client=${!!extendedAdapter?.client}`);
|
|
34339
|
+
if (!vesuAdapter) {
|
|
34149
34340
|
logger.error(
|
|
34150
|
-
`
|
|
34341
|
+
`Vesu adapter not configured in metadata. This is a configuration issue, not a temporary failure.`
|
|
34342
|
+
);
|
|
34343
|
+
return {
|
|
34344
|
+
shouldInvest: false,
|
|
34345
|
+
vesuAmount: new Web3Number(0, 0),
|
|
34346
|
+
extendedAmount: new Web3Number(0, 0),
|
|
34347
|
+
extendedLeverage: 0,
|
|
34348
|
+
collateralPrice: 0,
|
|
34349
|
+
debtPrice: 0,
|
|
34350
|
+
vesuLeverage: 0
|
|
34351
|
+
};
|
|
34352
|
+
}
|
|
34353
|
+
if (!extendedAdapter) {
|
|
34354
|
+
logger.error(
|
|
34355
|
+
`Extended adapter not configured in metadata. This is a configuration issue, not a temporary failure.`
|
|
34151
34356
|
);
|
|
34152
34357
|
return {
|
|
34153
34358
|
shouldInvest: false,
|
|
@@ -34159,10 +34364,72 @@ var VesuExtendedMultiplierStrategy = class _VesuExtendedMultiplierStrategy exten
|
|
|
34159
34364
|
vesuLeverage: 0
|
|
34160
34365
|
};
|
|
34161
34366
|
}
|
|
34367
|
+
if (!extendedAdapter.client) {
|
|
34368
|
+
logger.error(
|
|
34369
|
+
`Extended adapter client not initialized. This may be a temporary initialization failure - check network connectivity and API availability.`
|
|
34370
|
+
);
|
|
34371
|
+
return {
|
|
34372
|
+
shouldInvest: false,
|
|
34373
|
+
vesuAmount: new Web3Number(0, 0),
|
|
34374
|
+
extendedAmount: new Web3Number(0, 0),
|
|
34375
|
+
extendedLeverage: 0,
|
|
34376
|
+
collateralPrice: 0,
|
|
34377
|
+
debtPrice: 0,
|
|
34378
|
+
vesuLeverage: 0
|
|
34379
|
+
};
|
|
34380
|
+
}
|
|
34381
|
+
logger.info(`${_VesuExtendedMultiplierStrategy.name}::shouldInvest calling getUnusedBalance`);
|
|
34162
34382
|
const balance = await this.getUnusedBalance();
|
|
34383
|
+
if (!Number.isFinite(balance.usdValue) || balance.usdValue < 0) {
|
|
34384
|
+
logger.error(
|
|
34385
|
+
`Invalid balance.usdValue: ${balance.usdValue}. Expected a finite, non-negative number.`
|
|
34386
|
+
);
|
|
34387
|
+
return {
|
|
34388
|
+
shouldInvest: false,
|
|
34389
|
+
vesuAmount: new Web3Number(0, 0),
|
|
34390
|
+
extendedAmount: new Web3Number(0, 0),
|
|
34391
|
+
extendedLeverage: 0,
|
|
34392
|
+
collateralPrice: 0,
|
|
34393
|
+
debtPrice: 0,
|
|
34394
|
+
vesuLeverage: 0
|
|
34395
|
+
};
|
|
34396
|
+
}
|
|
34397
|
+
logger.info(`${_VesuExtendedMultiplierStrategy.name}::shouldInvest balance: ${balance.usdValue}`);
|
|
34163
34398
|
const usdcBalanceOnExtended = await extendedAdapter.getExtendedDepositAmount();
|
|
34399
|
+
if (usdcBalanceOnExtended) {
|
|
34400
|
+
const availableForWithdrawal = parseFloat(usdcBalanceOnExtended.availableForWithdrawal);
|
|
34401
|
+
if (!Number.isFinite(availableForWithdrawal) || availableForWithdrawal < 0) {
|
|
34402
|
+
logger.error(
|
|
34403
|
+
`Invalid usdcBalanceOnExtended.availableForWithdrawal: ${usdcBalanceOnExtended.availableForWithdrawal}. Expected a finite, non-negative number.`
|
|
34404
|
+
);
|
|
34405
|
+
return {
|
|
34406
|
+
shouldInvest: false,
|
|
34407
|
+
vesuAmount: new Web3Number(0, 0),
|
|
34408
|
+
extendedAmount: new Web3Number(0, 0),
|
|
34409
|
+
extendedLeverage: 0,
|
|
34410
|
+
collateralPrice: 0,
|
|
34411
|
+
debtPrice: 0,
|
|
34412
|
+
vesuLeverage: 0
|
|
34413
|
+
};
|
|
34414
|
+
}
|
|
34415
|
+
}
|
|
34164
34416
|
const amountToInvest = new Web3Number(balance.usdValue, USDC_TOKEN_DECIMALS).plus(usdcBalanceOnExtended?.availableForWithdrawal ?? 0).multipliedBy(1 - LIMIT_BALANCE);
|
|
34165
|
-
|
|
34417
|
+
const amountToInvestNumber = amountToInvest.toNumber();
|
|
34418
|
+
if (!Number.isFinite(amountToInvestNumber)) {
|
|
34419
|
+
logger.error(
|
|
34420
|
+
`Invalid amountToInvest calculation result: ${amountToInvestNumber}. Calculation may have produced NaN or Infinity.`
|
|
34421
|
+
);
|
|
34422
|
+
return {
|
|
34423
|
+
shouldInvest: false,
|
|
34424
|
+
vesuAmount: new Web3Number(0, 0),
|
|
34425
|
+
extendedAmount: new Web3Number(0, 0),
|
|
34426
|
+
extendedLeverage: 0,
|
|
34427
|
+
collateralPrice: 0,
|
|
34428
|
+
debtPrice: 0,
|
|
34429
|
+
vesuLeverage: 0
|
|
34430
|
+
};
|
|
34431
|
+
}
|
|
34432
|
+
logger.info(`${_VesuExtendedMultiplierStrategy.name}::shouldInvest amountToInvest: ${amountToInvestNumber}`);
|
|
34166
34433
|
if (amountToInvest.lessThan(0)) {
|
|
34167
34434
|
return {
|
|
34168
34435
|
shouldInvest: false,
|
|
@@ -34192,6 +34459,34 @@ var VesuExtendedMultiplierStrategy = class _VesuExtendedMultiplierStrategy exten
|
|
|
34192
34459
|
collateralPrice,
|
|
34193
34460
|
debtPrice
|
|
34194
34461
|
} = await this.getAssetPrices();
|
|
34462
|
+
if (!Number.isFinite(collateralPrice.price) || collateralPrice.price <= 0) {
|
|
34463
|
+
logger.error(
|
|
34464
|
+
`Invalid collateralPrice: ${collateralPrice.price}. Expected a finite, positive number.`
|
|
34465
|
+
);
|
|
34466
|
+
return {
|
|
34467
|
+
shouldInvest: false,
|
|
34468
|
+
vesuAmount: new Web3Number(0, 0),
|
|
34469
|
+
extendedAmount: new Web3Number(0, 0),
|
|
34470
|
+
extendedLeverage: 0,
|
|
34471
|
+
collateralPrice: 0,
|
|
34472
|
+
debtPrice: 0,
|
|
34473
|
+
vesuLeverage: 0
|
|
34474
|
+
};
|
|
34475
|
+
}
|
|
34476
|
+
if (!Number.isFinite(debtPrice.price) || debtPrice.price <= 0) {
|
|
34477
|
+
logger.error(
|
|
34478
|
+
`Invalid debtPrice: ${debtPrice.price}. Expected a finite, positive number.`
|
|
34479
|
+
);
|
|
34480
|
+
return {
|
|
34481
|
+
shouldInvest: false,
|
|
34482
|
+
vesuAmount: new Web3Number(0, 0),
|
|
34483
|
+
extendedAmount: new Web3Number(0, 0),
|
|
34484
|
+
extendedLeverage: 0,
|
|
34485
|
+
collateralPrice: 0,
|
|
34486
|
+
debtPrice: 0,
|
|
34487
|
+
vesuLeverage: 0
|
|
34488
|
+
};
|
|
34489
|
+
}
|
|
34195
34490
|
const { vesu_amount, extended_amount, extended_leverage, vesu_leverage } = await calculateAmountDistribution(
|
|
34196
34491
|
amountToInvest.toNumber(),
|
|
34197
34492
|
extendedAdapter.client,
|
|
@@ -34242,13 +34537,45 @@ var VesuExtendedMultiplierStrategy = class _VesuExtendedMultiplierStrategy exten
|
|
|
34242
34537
|
try {
|
|
34243
34538
|
const vesuAdapter = await this.getVesuAdapter();
|
|
34244
34539
|
const extendedAdapter = await this.getExtendedAdapter();
|
|
34245
|
-
let calls = [];
|
|
34246
34540
|
if (!vesuAdapter || !extendedAdapter || !extendedAdapter.client) {
|
|
34247
34541
|
logger.error(
|
|
34248
34542
|
`vesu or extended adapter not found: vesuAdapter=${vesuAdapter}, extendedAdapter=${extendedAdapter}`
|
|
34249
34543
|
);
|
|
34250
|
-
return
|
|
34544
|
+
return [];
|
|
34545
|
+
}
|
|
34546
|
+
const extendedHoldings = await extendedAdapter.getExtendedDepositAmount();
|
|
34547
|
+
if (!extendedHoldings) {
|
|
34548
|
+
logger.error(`error getting extended holdings: ${extendedHoldings}`);
|
|
34549
|
+
return [];
|
|
34251
34550
|
}
|
|
34551
|
+
const usdcAmountInWallet = (await this.getUnusedBalance()).amount;
|
|
34552
|
+
const usdcAmountOnExtendedAvailableForWithdrawal = parseFloat(
|
|
34553
|
+
extendedHoldings.availableForWithdrawal
|
|
34554
|
+
);
|
|
34555
|
+
logger.info(`${_VesuExtendedMultiplierStrategy.name}::shouldMoveAssets calculating movements - Extended current: ${usdcAmountOnExtendedAvailableForWithdrawal}, Wallet: ${usdcAmountInWallet.toNumber()}, Target Extended: ${extendedAmount.toNumber()}, Target Vesu: ${vesuAmount.toNumber()}`);
|
|
34556
|
+
let totalExtendedWithdrawal = new Web3Number(0, USDC_TOKEN_DECIMALS);
|
|
34557
|
+
let totalExtendedDeposit = new Web3Number(0, USDC_TOKEN_DECIMALS);
|
|
34558
|
+
if (extendedAmount.isNegative() && extendedAmount.abs().greaterThan(extendedAdapter.minimumExtendedMovementAmount)) {
|
|
34559
|
+
totalExtendedWithdrawal = totalExtendedWithdrawal.plus(extendedAmount.abs());
|
|
34560
|
+
}
|
|
34561
|
+
const extendedTargetAmount = extendedAmount.abs();
|
|
34562
|
+
let projectedExtendedBalance = usdcAmountOnExtendedAvailableForWithdrawal;
|
|
34563
|
+
if (extendedAmount.isNegative()) {
|
|
34564
|
+
projectedExtendedBalance = projectedExtendedBalance - extendedAmount.abs().toNumber();
|
|
34565
|
+
}
|
|
34566
|
+
const extendedAmountDifference = extendedTargetAmount.minus(projectedExtendedBalance);
|
|
34567
|
+
const extendedAmountDifferenceAbs = extendedAmountDifference.abs();
|
|
34568
|
+
if (extendedAmountDifference.lessThan(0)) {
|
|
34569
|
+
totalExtendedWithdrawal = totalExtendedWithdrawal.plus(extendedAmountDifferenceAbs);
|
|
34570
|
+
} else if (extendedAmountDifference.greaterThan(0)) {
|
|
34571
|
+
totalExtendedDeposit = totalExtendedDeposit.plus(extendedAmountDifference);
|
|
34572
|
+
}
|
|
34573
|
+
const vesuTargetAmount = vesuAmount.abs();
|
|
34574
|
+
const projectedWalletBalance = usdcAmountInWallet.plus(totalExtendedWithdrawal).minus(totalExtendedDeposit);
|
|
34575
|
+
let vesuAmountDifference = vesuTargetAmount.minus(projectedWalletBalance);
|
|
34576
|
+
const vesuAmountDifferenceAbs = vesuAmountDifference.abs();
|
|
34577
|
+
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()}`);
|
|
34578
|
+
let calls = [];
|
|
34252
34579
|
if (extendedAmount.isNegative() && extendedAmount.abs().greaterThan(extendedAdapter.minimumExtendedMovementAmount)) {
|
|
34253
34580
|
try {
|
|
34254
34581
|
const { calls: extendedCalls, status: extendedStatus } = await this.moveAssets(
|
|
@@ -34269,7 +34596,7 @@ var VesuExtendedMultiplierStrategy = class _VesuExtendedMultiplierStrategy exten
|
|
|
34269
34596
|
logger.error(`Failed moving assets to vault: ${err}`);
|
|
34270
34597
|
}
|
|
34271
34598
|
}
|
|
34272
|
-
if (vesuAmount.isNegative() && vesuAmount.
|
|
34599
|
+
if (vesuAmount.isNegative() && vesuAmount.abs().greaterThan(vesuAdapter.minimumVesuMovementAmount)) {
|
|
34273
34600
|
try {
|
|
34274
34601
|
const { calls: vesuCalls, status: vesuStatus } = await this.moveAssets(
|
|
34275
34602
|
{
|
|
@@ -34288,48 +34615,76 @@ var VesuExtendedMultiplierStrategy = class _VesuExtendedMultiplierStrategy exten
|
|
|
34288
34615
|
logger.error(`Failed moving assets to vault: ${err}`);
|
|
34289
34616
|
}
|
|
34290
34617
|
}
|
|
34291
|
-
|
|
34292
|
-
|
|
34293
|
-
|
|
34294
|
-
|
|
34295
|
-
|
|
34296
|
-
|
|
34297
|
-
|
|
34298
|
-
|
|
34299
|
-
|
|
34300
|
-
|
|
34301
|
-
|
|
34302
|
-
|
|
34303
|
-
{
|
|
34304
|
-
|
|
34305
|
-
|
|
34306
|
-
|
|
34307
|
-
|
|
34308
|
-
|
|
34309
|
-
|
|
34310
|
-
|
|
34311
|
-
|
|
34312
|
-
|
|
34313
|
-
|
|
34618
|
+
if (extendedAmountDifferenceAbs.greaterThan(extendedAdapter.minimumExtendedMovementAmount)) {
|
|
34619
|
+
if (extendedAmountDifference.greaterThan(0)) {
|
|
34620
|
+
try {
|
|
34621
|
+
const { calls: extendedCalls, status: extendedStatus } = await this.moveAssets(
|
|
34622
|
+
{
|
|
34623
|
+
to: Protocols.EXTENDED.name,
|
|
34624
|
+
from: Protocols.VAULT.name,
|
|
34625
|
+
amount: extendedAmountDifference
|
|
34626
|
+
},
|
|
34627
|
+
extendedAdapter,
|
|
34628
|
+
vesuAdapter
|
|
34629
|
+
);
|
|
34630
|
+
if (extendedStatus) {
|
|
34631
|
+
calls.push(...extendedCalls);
|
|
34632
|
+
} else {
|
|
34633
|
+
logger.error(`Failed to move assets to extended - operation returned false status`);
|
|
34634
|
+
return [];
|
|
34635
|
+
}
|
|
34636
|
+
} catch (err) {
|
|
34637
|
+
logger.error(`Failed moving assets to extended: ${err}`);
|
|
34638
|
+
return [];
|
|
34639
|
+
}
|
|
34640
|
+
} else if (extendedAmountDifference.lessThan(0)) {
|
|
34641
|
+
try {
|
|
34642
|
+
const { calls: extendedCalls, status: extendedStatus } = await this.moveAssets(
|
|
34643
|
+
{
|
|
34644
|
+
to: Protocols.VAULT.name,
|
|
34645
|
+
from: Protocols.EXTENDED.name,
|
|
34646
|
+
amount: extendedAmountDifferenceAbs
|
|
34647
|
+
},
|
|
34648
|
+
extendedAdapter,
|
|
34649
|
+
vesuAdapter
|
|
34650
|
+
);
|
|
34651
|
+
if (extendedStatus) {
|
|
34652
|
+
calls.push(...extendedCalls);
|
|
34653
|
+
} else {
|
|
34654
|
+
logger.error(`Failed to withdraw from extended - operation returned false status`);
|
|
34655
|
+
return [];
|
|
34656
|
+
}
|
|
34657
|
+
} catch (err) {
|
|
34658
|
+
logger.error(`Failed moving assets from extended to vault: ${err}`);
|
|
34659
|
+
return [];
|
|
34660
|
+
}
|
|
34314
34661
|
}
|
|
34315
34662
|
}
|
|
34316
|
-
if (
|
|
34317
|
-
|
|
34318
|
-
|
|
34319
|
-
{
|
|
34320
|
-
to: Protocols.VAULT.name,
|
|
34321
|
-
from: Protocols.EXTENDED.name,
|
|
34322
|
-
amount: vesuAmount.minus(usdcAmountInWallet)
|
|
34323
|
-
},
|
|
34324
|
-
extendedAdapter,
|
|
34325
|
-
vesuAdapter
|
|
34663
|
+
if (vesuAmountDifferenceAbs.greaterThan(vesuAdapter.minimumVesuMovementAmount)) {
|
|
34664
|
+
if (vesuAmountDifference.lessThanOrEqualTo(0)) {
|
|
34665
|
+
logger.warn(
|
|
34666
|
+
`Vesu amount difference is negative or zero: ${vesuAmountDifference.toNumber()}. Skipping operation.`
|
|
34326
34667
|
);
|
|
34327
|
-
|
|
34668
|
+
} else {
|
|
34669
|
+
try {
|
|
34670
|
+
const { calls: vesuCalls, status: vesuStatus } = await this.moveAssets(
|
|
34671
|
+
{
|
|
34672
|
+
to: Protocols.VAULT.name,
|
|
34673
|
+
from: Protocols.EXTENDED.name,
|
|
34674
|
+
amount: vesuAmountDifference
|
|
34675
|
+
},
|
|
34676
|
+
extendedAdapter,
|
|
34677
|
+
vesuAdapter
|
|
34678
|
+
);
|
|
34679
|
+
if (!vesuStatus) {
|
|
34680
|
+
logger.error(`Failed to move assets to vesu - operation returned false status`);
|
|
34681
|
+
return [];
|
|
34682
|
+
}
|
|
34683
|
+
calls.push(...vesuCalls);
|
|
34684
|
+
} catch (err) {
|
|
34685
|
+
logger.error(`Failed moving assets to vault: ${err}`);
|
|
34328
34686
|
return [];
|
|
34329
34687
|
}
|
|
34330
|
-
calls.push(...vesuCalls);
|
|
34331
|
-
} catch (err) {
|
|
34332
|
-
logger.error(`Failed moving assets to vault: ${err}`);
|
|
34333
34688
|
}
|
|
34334
34689
|
}
|
|
34335
34690
|
return calls;
|
|
@@ -34340,6 +34695,38 @@ var VesuExtendedMultiplierStrategy = class _VesuExtendedMultiplierStrategy exten
|
|
|
34340
34695
|
}
|
|
34341
34696
|
async moveAssets(params, extendedAdapter, vesuAdapter) {
|
|
34342
34697
|
try {
|
|
34698
|
+
if (params.amount.lessThanOrEqualTo(0)) {
|
|
34699
|
+
logger.error(
|
|
34700
|
+
`Invalid amount for moveAssets: ${params.amount.toNumber()}. Amount must be positive.`
|
|
34701
|
+
);
|
|
34702
|
+
return {
|
|
34703
|
+
calls: [],
|
|
34704
|
+
status: false
|
|
34705
|
+
};
|
|
34706
|
+
}
|
|
34707
|
+
const amountAbs = params.amount.abs();
|
|
34708
|
+
if (params.from === Protocols.EXTENDED.name || params.to === Protocols.EXTENDED.name) {
|
|
34709
|
+
if (amountAbs.lessThanOrEqualTo(extendedAdapter.minimumExtendedMovementAmount)) {
|
|
34710
|
+
logger.warn(
|
|
34711
|
+
`Amount ${amountAbs.toNumber()} is below minimum Extended movement amount ${extendedAdapter.minimumExtendedMovementAmount}. Skipping operation.`
|
|
34712
|
+
);
|
|
34713
|
+
return {
|
|
34714
|
+
calls: [],
|
|
34715
|
+
status: false
|
|
34716
|
+
};
|
|
34717
|
+
}
|
|
34718
|
+
}
|
|
34719
|
+
if (params.from === Protocols.VESU.name || params.to === Protocols.VESU.name) {
|
|
34720
|
+
if (amountAbs.lessThanOrEqualTo(vesuAdapter.minimumVesuMovementAmount)) {
|
|
34721
|
+
logger.warn(
|
|
34722
|
+
`Amount ${amountAbs.toNumber()} is below minimum Vesu movement amount ${vesuAdapter.minimumVesuMovementAmount}. Skipping operation.`
|
|
34723
|
+
);
|
|
34724
|
+
return {
|
|
34725
|
+
calls: [],
|
|
34726
|
+
status: false
|
|
34727
|
+
};
|
|
34728
|
+
}
|
|
34729
|
+
}
|
|
34343
34730
|
const avnuAdapter = await this.getAvnuAdapter();
|
|
34344
34731
|
if (!avnuAdapter) {
|
|
34345
34732
|
logger.error(`avnu adapter not found: ${avnuAdapter}`);
|
|
@@ -34400,18 +34787,18 @@ var VesuExtendedMultiplierStrategy = class _VesuExtendedMultiplierStrategy exten
|
|
|
34400
34787
|
);
|
|
34401
34788
|
if (!openLongPosition) {
|
|
34402
34789
|
logger.error(`error opening long position: ${openLongPosition}`);
|
|
34403
|
-
return {
|
|
34404
|
-
calls: [],
|
|
34405
|
-
status: false
|
|
34406
|
-
};
|
|
34407
34790
|
}
|
|
34408
|
-
|
|
34791
|
+
const updatedHoldings = await extendedAdapter.getExtendedDepositAmount();
|
|
34792
|
+
if (!updatedHoldings || new Web3Number(updatedHoldings.availableForWithdrawal, USDC_TOKEN_DECIMALS).lessThan(params.amount.abs())) {
|
|
34793
|
+
logger.error(`Insufficient balance after opening position. Available: ${updatedHoldings?.availableForWithdrawal}, Needed: ${params.amount.abs()}`);
|
|
34794
|
+
return { calls: [], status: false };
|
|
34795
|
+
}
|
|
34409
34796
|
}
|
|
34410
34797
|
const withdrawalFromExtended = await extendedAdapter.withdrawFromExtended(params.amount);
|
|
34411
34798
|
if (withdrawalFromExtended) {
|
|
34412
34799
|
const extendedHoldings2 = await extendedAdapter.getExtendedDepositAmount();
|
|
34413
34800
|
logger.info(`extendedHoldings after withdrawal ${extendedHoldings2?.availableForWithdrawal}`);
|
|
34414
|
-
await new Promise((resolve) => setTimeout(resolve,
|
|
34801
|
+
await new Promise((resolve) => setTimeout(resolve, 2e3));
|
|
34415
34802
|
const calls = await this.moveAssetsToVaultAllocator(params.amount, extendedAdapter);
|
|
34416
34803
|
if (calls.length > 0) {
|
|
34417
34804
|
return {
|