@gbozee/ultimate 0.0.2-192 → 0.0.2-194
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/frontend-index.d.ts +5 -0
- package/dist/frontend-index.js +3 -0
- package/dist/index.cjs +373 -185
- package/dist/index.d.ts +3 -98
- package/dist/index.js +373 -185
- package/dist/mcp-server.cjs +332 -147
- package/dist/mcp-server.js +332 -147
- package/package.json +1 -1
package/dist/mcp-server.js
CHANGED
|
@@ -61468,35 +61468,6 @@ class AppDatabase {
|
|
|
61468
61468
|
}
|
|
61469
61469
|
return null;
|
|
61470
61470
|
}
|
|
61471
|
-
async getRunningInstanceFromDB(account, symbol, options) {
|
|
61472
|
-
const { delay = 60 * 1000 } = options || {
|
|
61473
|
-
delay: 60 * 1000
|
|
61474
|
-
};
|
|
61475
|
-
const running_instance = await this.pb.collection("trade_block_tracking").getFirstListItem(`account.owner = "${account.owner}" && account.exchange = "${account.exchange}" && symbol = "${symbol}"`, {
|
|
61476
|
-
expand: "account"
|
|
61477
|
-
});
|
|
61478
|
-
if (!running_instance) {
|
|
61479
|
-
let account_instance = await this.pb.collection("exchange_accounts").getFirstListItem(`owner = "${account.owner}" && exchange = "${account.exchange}"`);
|
|
61480
|
-
return await this.pb.collection("trade_block_tracking").create({
|
|
61481
|
-
account: account_instance.id,
|
|
61482
|
-
symbol,
|
|
61483
|
-
running: false
|
|
61484
|
-
});
|
|
61485
|
-
}
|
|
61486
|
-
const updatedAt = new Date(running_instance.updated);
|
|
61487
|
-
const now = new Date;
|
|
61488
|
-
const diffInMinutes = (now.getTime() - updatedAt.getTime()) / delay;
|
|
61489
|
-
if (diffInMinutes >= 1) {
|
|
61490
|
-
await this.updateRunningInstance(running_instance.id, false);
|
|
61491
|
-
running_instance.running = false;
|
|
61492
|
-
}
|
|
61493
|
-
return running_instance;
|
|
61494
|
-
}
|
|
61495
|
-
async updateRunningInstance(id, running) {
|
|
61496
|
-
return await this.pb.collection("trade_block_tracking").update(id, {
|
|
61497
|
-
running
|
|
61498
|
-
});
|
|
61499
|
-
}
|
|
61500
61471
|
async getOrders(account, options) {
|
|
61501
61472
|
const { symbol, kind } = options;
|
|
61502
61473
|
const db_orders = await this.pb.collection("orders").getFullList({
|
|
@@ -61807,110 +61778,6 @@ class AppDatabase {
|
|
|
61807
61778
|
}
|
|
61808
61779
|
return null;
|
|
61809
61780
|
}
|
|
61810
|
-
async getBotViewInstance(payload) {
|
|
61811
|
-
const { asset, main_account } = payload;
|
|
61812
|
-
const bot_instances = await this.pb.collection("bot_view").getFullList({
|
|
61813
|
-
filter: `asset:lower="${asset.toLowerCase()}" && main_account.owner:lower="${main_account.owner.toLowerCase()}" && main_account.exchange:lower="${main_account.exchange.toLowerCase()}"`,
|
|
61814
|
-
expand: "main_account,secondary_account,main_long_strategy,main_short_strategy,secondary_long_strategy,secondary_short_strategy"
|
|
61815
|
-
});
|
|
61816
|
-
if (bot_instances.length > 0) {
|
|
61817
|
-
const instance = bot_instances[0];
|
|
61818
|
-
const {
|
|
61819
|
-
main_account: main_account2,
|
|
61820
|
-
secondary_account,
|
|
61821
|
-
main_long_strategy,
|
|
61822
|
-
main_short_strategy,
|
|
61823
|
-
secondary_long_strategy,
|
|
61824
|
-
secondary_short_strategy
|
|
61825
|
-
} = instance.expand;
|
|
61826
|
-
const update_boolean = (value) => {
|
|
61827
|
-
if (!value) {
|
|
61828
|
-
return value;
|
|
61829
|
-
}
|
|
61830
|
-
return {
|
|
61831
|
-
...value,
|
|
61832
|
-
follow: Boolean(value.follow),
|
|
61833
|
-
place_tp: Boolean(value.place_tp),
|
|
61834
|
-
pause_tp: Boolean(value.pause_tp)
|
|
61835
|
-
};
|
|
61836
|
-
};
|
|
61837
|
-
return {
|
|
61838
|
-
...instance,
|
|
61839
|
-
main: {
|
|
61840
|
-
account: main_account2,
|
|
61841
|
-
symbol: instance.main_symbol,
|
|
61842
|
-
strategy: {
|
|
61843
|
-
long: main_long_strategy,
|
|
61844
|
-
short: main_short_strategy
|
|
61845
|
-
},
|
|
61846
|
-
position: {
|
|
61847
|
-
long: instance.main_long_position,
|
|
61848
|
-
short: instance.main_short_position
|
|
61849
|
-
},
|
|
61850
|
-
config: {
|
|
61851
|
-
long: update_boolean(instance.main_long_config),
|
|
61852
|
-
short: update_boolean(instance.main_short_config)
|
|
61853
|
-
}
|
|
61854
|
-
},
|
|
61855
|
-
secondary: {
|
|
61856
|
-
account: secondary_account,
|
|
61857
|
-
symbol: instance.secondary_symbol,
|
|
61858
|
-
strategy: {
|
|
61859
|
-
long: secondary_long_strategy,
|
|
61860
|
-
short: secondary_short_strategy
|
|
61861
|
-
},
|
|
61862
|
-
position: {
|
|
61863
|
-
long: instance.secondary_long_position,
|
|
61864
|
-
short: instance.secondary_short_position
|
|
61865
|
-
},
|
|
61866
|
-
config: {
|
|
61867
|
-
long: update_boolean(instance.secondary_long_config),
|
|
61868
|
-
short: update_boolean(instance.secondary_short_config)
|
|
61869
|
-
}
|
|
61870
|
-
}
|
|
61871
|
-
};
|
|
61872
|
-
}
|
|
61873
|
-
return null;
|
|
61874
|
-
}
|
|
61875
|
-
async getBotInstance(payload) {
|
|
61876
|
-
const { asset, main_account } = payload;
|
|
61877
|
-
const bot_instances = await this.pb.collection("bot_instances").getFullList({
|
|
61878
|
-
filter: `asset:lower="${asset.toLowerCase()}" && main_account.owner:lower="${main_account.owner.toLowerCase()}" && main_account.exchange:lower="${main_account.exchange.toLowerCase()}"`
|
|
61879
|
-
});
|
|
61880
|
-
if (bot_instances.length > 0) {
|
|
61881
|
-
return bot_instances[0];
|
|
61882
|
-
}
|
|
61883
|
-
return null;
|
|
61884
|
-
}
|
|
61885
|
-
async getBotState(payload) {
|
|
61886
|
-
const { asset, main_account, running } = payload;
|
|
61887
|
-
let filter = `bot.asset:lower="${asset.toLowerCase()}" && bot.main_account.owner:lower="${main_account.owner.toLowerCase()}" && bot.main_account.exchange:lower="${main_account.exchange.toLowerCase()}"`;
|
|
61888
|
-
if (running !== undefined) {
|
|
61889
|
-
filter += ` && running=${running}`;
|
|
61890
|
-
}
|
|
61891
|
-
const bot_states = await this.pb.collection("bot_states").getFullList({
|
|
61892
|
-
filter
|
|
61893
|
-
});
|
|
61894
|
-
return bot_states;
|
|
61895
|
-
}
|
|
61896
|
-
async getBotOrderHistories(payload) {
|
|
61897
|
-
const { asset, main_account, symbol, kind, type } = payload;
|
|
61898
|
-
let filter = `field.bot.asset:lower="${asset.toLowerCase()}" && field.bot.main_account.owner:lower="${main_account.owner.toLowerCase()}" && field.bot.main_account.exchange:lower="${main_account.exchange.toLowerCase()}"`;
|
|
61899
|
-
if (symbol) {
|
|
61900
|
-
filter += ` && symbol:lower="${symbol.toLowerCase()}"`;
|
|
61901
|
-
}
|
|
61902
|
-
if (kind) {
|
|
61903
|
-
filter += ` && kind="${kind}"`;
|
|
61904
|
-
}
|
|
61905
|
-
if (type) {
|
|
61906
|
-
filter += ` && type="${type}"`;
|
|
61907
|
-
}
|
|
61908
|
-
const bot_order_histories = await this.pb.collection("bot_order_history").getFullList({
|
|
61909
|
-
filter,
|
|
61910
|
-
sort: "-created"
|
|
61911
|
-
});
|
|
61912
|
-
return bot_order_histories;
|
|
61913
|
-
}
|
|
61914
61781
|
async createOrUpdateWindingDownMarket(payload) {
|
|
61915
61782
|
const { symbol, risk_reward = 30 } = payload;
|
|
61916
61783
|
const existing_winding_down_market = await this.pb.collection("winding_down_markets").getFullList({
|
|
@@ -66600,6 +66467,171 @@ class BinanceExchange extends BaseExchange {
|
|
|
66600
66467
|
async forceClosePosition(symbol, options) {
|
|
66601
66468
|
return await forceClosePosition(this.client, symbol, options);
|
|
66602
66469
|
}
|
|
66470
|
+
async getTransferableAmount(options) {
|
|
66471
|
+
const { asset, maxTransferLimit } = options;
|
|
66472
|
+
try {
|
|
66473
|
+
const futuresBalance = await getWalletBalance(this.client, asset);
|
|
66474
|
+
const allPositions = await this.client.getPositionsV3();
|
|
66475
|
+
const activePositions = allPositions.filter((pos) => Math.abs(pos.positionAmt) > 0);
|
|
66476
|
+
let totalMarginUsed = 0;
|
|
66477
|
+
let totalUnrealizedPnl = 0;
|
|
66478
|
+
for (const position2 of activePositions) {
|
|
66479
|
+
const positionValue = Math.abs(position2.positionAmt) * position2.markPrice;
|
|
66480
|
+
const leverage = await getLeverage(this.client, position2.symbol);
|
|
66481
|
+
const marginForPosition = positionValue / (leverage || 1);
|
|
66482
|
+
console.log({ leverage });
|
|
66483
|
+
totalMarginUsed += marginForPosition;
|
|
66484
|
+
totalUnrealizedPnl += position2.unRealizedProfit || 0;
|
|
66485
|
+
}
|
|
66486
|
+
const safetyMarginPercent = 0.2;
|
|
66487
|
+
const requiredMargin = totalMarginUsed * (1 + safetyMarginPercent);
|
|
66488
|
+
const adjustedBalance = futuresBalance + totalUnrealizedPnl;
|
|
66489
|
+
const availableForTransfer = Math.max(0, adjustedBalance - requiredMargin);
|
|
66490
|
+
let maxTransferableAmount = availableForTransfer;
|
|
66491
|
+
let appliedLimit;
|
|
66492
|
+
if (maxTransferLimit && maxTransferLimit > 0) {
|
|
66493
|
+
maxTransferableAmount = Math.min(availableForTransfer, maxTransferLimit);
|
|
66494
|
+
appliedLimit = maxTransferLimit;
|
|
66495
|
+
}
|
|
66496
|
+
const recommendedTransferAmount = maxTransferableAmount * 0.8;
|
|
66497
|
+
const marginUtilization = adjustedBalance > 0 ? requiredMargin / adjustedBalance * 100 : 0;
|
|
66498
|
+
return {
|
|
66499
|
+
asset,
|
|
66500
|
+
totalBalance: futuresBalance,
|
|
66501
|
+
availableForTransfer,
|
|
66502
|
+
reservedForMargin: requiredMargin,
|
|
66503
|
+
maxTransferableAmount,
|
|
66504
|
+
appliedLimit,
|
|
66505
|
+
recommendedTransferAmount,
|
|
66506
|
+
marginUtilization,
|
|
66507
|
+
safetyMargin: safetyMarginPercent * 100
|
|
66508
|
+
};
|
|
66509
|
+
} catch (error) {
|
|
66510
|
+
console.error(`Error analyzing transferable amount for ${asset}:`, error);
|
|
66511
|
+
throw new Error(`Failed to analyze transferable funds: ${error instanceof Error ? error.message : error}`);
|
|
66512
|
+
}
|
|
66513
|
+
}
|
|
66514
|
+
async previewTransfer(options) {
|
|
66515
|
+
const { asset, amount } = options;
|
|
66516
|
+
const warnings = [];
|
|
66517
|
+
const errors = [];
|
|
66518
|
+
try {
|
|
66519
|
+
const analysis = await this.getTransferableAmount({ asset });
|
|
66520
|
+
let isValid3 = true;
|
|
66521
|
+
if (amount <= 0) {
|
|
66522
|
+
errors.push("Transfer amount must be greater than zero");
|
|
66523
|
+
isValid3 = false;
|
|
66524
|
+
}
|
|
66525
|
+
if (amount > analysis.maxTransferableAmount) {
|
|
66526
|
+
errors.push(`Transfer amount (${amount}) exceeds maximum transferable amount (${analysis.maxTransferableAmount})`);
|
|
66527
|
+
isValid3 = false;
|
|
66528
|
+
}
|
|
66529
|
+
if (amount > analysis.recommendedTransferAmount) {
|
|
66530
|
+
warnings.push(`Transfer amount exceeds recommended amount (${analysis.recommendedTransferAmount.toFixed(4)}). Consider transferring a smaller amount for safety.`);
|
|
66531
|
+
}
|
|
66532
|
+
if (analysis.marginUtilization > 70) {
|
|
66533
|
+
warnings.push(`High margin utilization (${analysis.marginUtilization.toFixed(1)}%). Transferring funds may increase liquidation risk.`);
|
|
66534
|
+
}
|
|
66535
|
+
const balanceAfterTransfer = analysis.totalBalance - amount;
|
|
66536
|
+
const marginRequirementAfterTransfer = analysis.reservedForMargin;
|
|
66537
|
+
if (isValid3 && balanceAfterTransfer < marginRequirementAfterTransfer) {
|
|
66538
|
+
errors.push("Transfer would result in insufficient margin for existing positions");
|
|
66539
|
+
isValid3 = false;
|
|
66540
|
+
}
|
|
66541
|
+
return {
|
|
66542
|
+
asset,
|
|
66543
|
+
requestedAmount: amount,
|
|
66544
|
+
isValid: isValid3,
|
|
66545
|
+
balanceAfterTransfer,
|
|
66546
|
+
marginRequirementAfterTransfer,
|
|
66547
|
+
warnings,
|
|
66548
|
+
errors
|
|
66549
|
+
};
|
|
66550
|
+
} catch (error) {
|
|
66551
|
+
console.error(`Error previewing transfer for ${asset}:`, error);
|
|
66552
|
+
return {
|
|
66553
|
+
asset,
|
|
66554
|
+
requestedAmount: amount,
|
|
66555
|
+
isValid: false,
|
|
66556
|
+
balanceAfterTransfer: 0,
|
|
66557
|
+
marginRequirementAfterTransfer: 0,
|
|
66558
|
+
warnings,
|
|
66559
|
+
errors: [`Failed to preview transfer: ${error instanceof Error ? error.message : error}`]
|
|
66560
|
+
};
|
|
66561
|
+
}
|
|
66562
|
+
}
|
|
66563
|
+
async executeFutureToSpotTransfer(options) {
|
|
66564
|
+
const { asset, amount, confirm, symbol = "BTCUSDT" } = options;
|
|
66565
|
+
try {
|
|
66566
|
+
if (!confirm) {
|
|
66567
|
+
return {
|
|
66568
|
+
success: false,
|
|
66569
|
+
asset,
|
|
66570
|
+
amount,
|
|
66571
|
+
fromWallet: "futures",
|
|
66572
|
+
toWallet: "spot",
|
|
66573
|
+
balanceAfterTransfer: 0,
|
|
66574
|
+
timestamp: new Date().toISOString(),
|
|
66575
|
+
error: "Transfer not confirmed. Set confirm: true to execute transfer."
|
|
66576
|
+
};
|
|
66577
|
+
}
|
|
66578
|
+
const preview = await this.previewTransfer({ asset, amount });
|
|
66579
|
+
if (!preview.isValid) {
|
|
66580
|
+
return {
|
|
66581
|
+
success: false,
|
|
66582
|
+
asset,
|
|
66583
|
+
amount,
|
|
66584
|
+
fromWallet: "futures",
|
|
66585
|
+
toWallet: "spot",
|
|
66586
|
+
balanceAfterTransfer: 0,
|
|
66587
|
+
timestamp: new Date().toISOString(),
|
|
66588
|
+
error: `Transfer validation failed: ${preview.errors.join("; ")}`
|
|
66589
|
+
};
|
|
66590
|
+
}
|
|
66591
|
+
const is_coin = !["USDT", "USDC", "BUSD"].includes(asset.toUpperCase());
|
|
66592
|
+
const transferType = is_coin ? CONSTANTS.COIN_FUTURE_TO_SPOT : CONSTANTS.USDT_FUTURE_TO_SPOT;
|
|
66593
|
+
if (!this.main_client) {
|
|
66594
|
+
throw new Error("Main client not available for transfers");
|
|
66595
|
+
}
|
|
66596
|
+
const transferClient = this.main_client;
|
|
66597
|
+
const transferResult = await transferClient.submitUniversalTransfer({
|
|
66598
|
+
asset: asset.toUpperCase(),
|
|
66599
|
+
amount,
|
|
66600
|
+
type: transferType,
|
|
66601
|
+
fromSymbol: symbol,
|
|
66602
|
+
toSymbol: symbol
|
|
66603
|
+
});
|
|
66604
|
+
const balanceAfterTransfer = await getWalletBalance(this.client, asset);
|
|
66605
|
+
return {
|
|
66606
|
+
success: true,
|
|
66607
|
+
transactionId: transferResult.tranId?.toString(),
|
|
66608
|
+
asset,
|
|
66609
|
+
amount,
|
|
66610
|
+
fromWallet: "futures",
|
|
66611
|
+
toWallet: "spot",
|
|
66612
|
+
balanceAfterTransfer,
|
|
66613
|
+
timestamp: new Date().toISOString()
|
|
66614
|
+
};
|
|
66615
|
+
} catch (error) {
|
|
66616
|
+
console.error(`Error executing transfer for ${asset}:`, error);
|
|
66617
|
+
let currentBalance = 0;
|
|
66618
|
+
try {
|
|
66619
|
+
currentBalance = await getWalletBalance(this.client, asset);
|
|
66620
|
+
} catch (balanceError) {
|
|
66621
|
+
console.warn("Could not fetch balance for error response:", balanceError);
|
|
66622
|
+
}
|
|
66623
|
+
return {
|
|
66624
|
+
success: false,
|
|
66625
|
+
asset,
|
|
66626
|
+
amount,
|
|
66627
|
+
fromWallet: "futures",
|
|
66628
|
+
toWallet: "spot",
|
|
66629
|
+
balanceAfterTransfer: currentBalance,
|
|
66630
|
+
timestamp: new Date().toISOString(),
|
|
66631
|
+
error: `Transfer execution failed: ${error instanceof Error ? error.message : error}`
|
|
66632
|
+
};
|
|
66633
|
+
}
|
|
66634
|
+
}
|
|
66603
66635
|
}
|
|
66604
66636
|
function getPricePlaces(target) {
|
|
66605
66637
|
const numStr = target.toString();
|
|
@@ -66925,6 +66957,11 @@ async function placeStopOrder2(client, payload) {
|
|
|
66925
66957
|
stop: payload.final_stop,
|
|
66926
66958
|
is_market: !payload.is_limit
|
|
66927
66959
|
};
|
|
66960
|
+
if (payload.hedge) {
|
|
66961
|
+
let reverse_kind = payload.kind === "long" ? "short" : "long";
|
|
66962
|
+
order.kind = reverse_kind;
|
|
66963
|
+
order.is_market = false;
|
|
66964
|
+
}
|
|
66928
66965
|
return createLimitPurchaseOrders(client, symbol, price_places, decimal_places, [order]);
|
|
66929
66966
|
}
|
|
66930
66967
|
async function getOpenOrders2(client, symbol, type) {
|
|
@@ -67321,6 +67358,168 @@ class BybitExchange extends BaseExchange {
|
|
|
67321
67358
|
return getOpenOrders2(this.client, payload.symbol);
|
|
67322
67359
|
}
|
|
67323
67360
|
async placeBadStopEntry(payload) {}
|
|
67361
|
+
async getTransferableAmount(options) {
|
|
67362
|
+
const { asset, maxTransferLimit } = options;
|
|
67363
|
+
try {
|
|
67364
|
+
const unifiedBalance = await getWalletBalance2(this.client, asset);
|
|
67365
|
+
const allPositions = await this.client.getPositionInfo({
|
|
67366
|
+
category: "linear",
|
|
67367
|
+
settleCoin: asset
|
|
67368
|
+
});
|
|
67369
|
+
const activePositions = (allPositions.result.list || []).filter((pos) => Math.abs(parseFloat(pos.size || "0")) > 0);
|
|
67370
|
+
let totalMarginUsed = 0;
|
|
67371
|
+
let totalUnrealizedPnl = 0;
|
|
67372
|
+
for (const position2 of activePositions) {
|
|
67373
|
+
const positionSize = Math.abs(parseFloat(position2.size || "0"));
|
|
67374
|
+
const markPrice = parseFloat(position2.markPrice || "0");
|
|
67375
|
+
const leverage = parseFloat(position2.leverage || "1");
|
|
67376
|
+
const positionValue = positionSize * markPrice;
|
|
67377
|
+
const marginForPosition = positionValue / leverage;
|
|
67378
|
+
totalMarginUsed += marginForPosition;
|
|
67379
|
+
totalUnrealizedPnl += parseFloat(position2.unrealisedPnl || "0");
|
|
67380
|
+
}
|
|
67381
|
+
const safetyMarginPercent = 0.2;
|
|
67382
|
+
const requiredMargin = totalMarginUsed * (1 + safetyMarginPercent);
|
|
67383
|
+
const adjustedBalance = unifiedBalance + totalUnrealizedPnl;
|
|
67384
|
+
const availableForTransfer = Math.max(0, adjustedBalance - requiredMargin);
|
|
67385
|
+
let maxTransferableAmount = availableForTransfer;
|
|
67386
|
+
let appliedLimit;
|
|
67387
|
+
if (maxTransferLimit && maxTransferLimit > 0) {
|
|
67388
|
+
maxTransferableAmount = Math.min(availableForTransfer, maxTransferLimit);
|
|
67389
|
+
appliedLimit = maxTransferLimit;
|
|
67390
|
+
}
|
|
67391
|
+
const recommendedTransferAmount = maxTransferableAmount * 0.8;
|
|
67392
|
+
const marginUtilization = adjustedBalance > 0 ? requiredMargin / adjustedBalance * 100 : 0;
|
|
67393
|
+
return {
|
|
67394
|
+
asset,
|
|
67395
|
+
totalBalance: unifiedBalance,
|
|
67396
|
+
availableForTransfer,
|
|
67397
|
+
reservedForMargin: requiredMargin,
|
|
67398
|
+
maxTransferableAmount,
|
|
67399
|
+
appliedLimit,
|
|
67400
|
+
recommendedTransferAmount,
|
|
67401
|
+
marginUtilization,
|
|
67402
|
+
safetyMargin: safetyMarginPercent * 100
|
|
67403
|
+
};
|
|
67404
|
+
} catch (error) {
|
|
67405
|
+
console.error(`Error analyzing transferable amount for ${asset}:`, error);
|
|
67406
|
+
throw new Error(`Failed to analyze transferable funds: ${error instanceof Error ? error.message : error}`);
|
|
67407
|
+
}
|
|
67408
|
+
}
|
|
67409
|
+
async previewTransfer(options) {
|
|
67410
|
+
const { asset, amount } = options;
|
|
67411
|
+
const warnings = [];
|
|
67412
|
+
const errors = [];
|
|
67413
|
+
try {
|
|
67414
|
+
const analysis = await this.getTransferableAmount({ asset });
|
|
67415
|
+
let isValid3 = true;
|
|
67416
|
+
if (amount <= 0) {
|
|
67417
|
+
errors.push("Transfer amount must be greater than zero");
|
|
67418
|
+
isValid3 = false;
|
|
67419
|
+
}
|
|
67420
|
+
if (amount > analysis.maxTransferableAmount) {
|
|
67421
|
+
errors.push(`Transfer amount (${amount}) exceeds maximum transferable amount (${analysis.maxTransferableAmount})`);
|
|
67422
|
+
isValid3 = false;
|
|
67423
|
+
}
|
|
67424
|
+
if (amount > analysis.recommendedTransferAmount) {
|
|
67425
|
+
warnings.push(`Transfer amount exceeds recommended amount (${analysis.recommendedTransferAmount.toFixed(4)}). Consider transferring a smaller amount for safety.`);
|
|
67426
|
+
}
|
|
67427
|
+
if (analysis.marginUtilization > 70) {
|
|
67428
|
+
warnings.push(`High margin utilization (${analysis.marginUtilization.toFixed(1)}%). Transferring funds may increase liquidation risk.`);
|
|
67429
|
+
}
|
|
67430
|
+
const balanceAfterTransfer = analysis.totalBalance - amount;
|
|
67431
|
+
const marginRequirementAfterTransfer = analysis.reservedForMargin;
|
|
67432
|
+
if (isValid3 && balanceAfterTransfer < marginRequirementAfterTransfer) {
|
|
67433
|
+
errors.push("Transfer would result in insufficient margin for existing positions");
|
|
67434
|
+
isValid3 = false;
|
|
67435
|
+
}
|
|
67436
|
+
return {
|
|
67437
|
+
asset,
|
|
67438
|
+
requestedAmount: amount,
|
|
67439
|
+
isValid: isValid3,
|
|
67440
|
+
balanceAfterTransfer,
|
|
67441
|
+
marginRequirementAfterTransfer,
|
|
67442
|
+
warnings,
|
|
67443
|
+
errors
|
|
67444
|
+
};
|
|
67445
|
+
} catch (error) {
|
|
67446
|
+
console.error(`Error previewing transfer for ${asset}:`, error);
|
|
67447
|
+
return {
|
|
67448
|
+
asset,
|
|
67449
|
+
requestedAmount: amount,
|
|
67450
|
+
isValid: false,
|
|
67451
|
+
balanceAfterTransfer: 0,
|
|
67452
|
+
marginRequirementAfterTransfer: 0,
|
|
67453
|
+
warnings,
|
|
67454
|
+
errors: [
|
|
67455
|
+
`Failed to preview transfer: ${error instanceof Error ? error.message : error}`
|
|
67456
|
+
]
|
|
67457
|
+
};
|
|
67458
|
+
}
|
|
67459
|
+
}
|
|
67460
|
+
async executeUnifiedToFundingTransfer(options) {
|
|
67461
|
+
const { asset, amount, confirm } = options;
|
|
67462
|
+
try {
|
|
67463
|
+
if (!confirm) {
|
|
67464
|
+
return {
|
|
67465
|
+
success: false,
|
|
67466
|
+
asset,
|
|
67467
|
+
amount,
|
|
67468
|
+
fromWallet: "unified",
|
|
67469
|
+
toWallet: "funding",
|
|
67470
|
+
balanceAfterTransfer: 0,
|
|
67471
|
+
timestamp: new Date().toISOString(),
|
|
67472
|
+
error: "Transfer not confirmed. Set confirm: true to execute transfer."
|
|
67473
|
+
};
|
|
67474
|
+
}
|
|
67475
|
+
const preview = await this.previewTransfer({ asset, amount });
|
|
67476
|
+
if (!preview.isValid) {
|
|
67477
|
+
return {
|
|
67478
|
+
success: false,
|
|
67479
|
+
asset,
|
|
67480
|
+
amount,
|
|
67481
|
+
fromWallet: "unified",
|
|
67482
|
+
toWallet: "funding",
|
|
67483
|
+
balanceAfterTransfer: 0,
|
|
67484
|
+
timestamp: new Date().toISOString(),
|
|
67485
|
+
error: `Transfer validation failed: ${preview.errors.join("; ")}`
|
|
67486
|
+
};
|
|
67487
|
+
}
|
|
67488
|
+
const transferResult = await this.client.createInternalTransfer(`bybit_transfer_${Date.now()}`, asset.toUpperCase(), amount.toString(), "UNIFIED", "FUND");
|
|
67489
|
+
if (transferResult.retCode !== 0) {
|
|
67490
|
+
throw new Error(`Bybit transfer failed: ${transferResult.retMsg} (code: ${transferResult.retCode})`);
|
|
67491
|
+
}
|
|
67492
|
+
const balanceAfterTransfer = await getWalletBalance2(this.client, asset);
|
|
67493
|
+
return {
|
|
67494
|
+
success: true,
|
|
67495
|
+
transactionId: transferResult.result?.transferId,
|
|
67496
|
+
asset,
|
|
67497
|
+
amount,
|
|
67498
|
+
fromWallet: "unified",
|
|
67499
|
+
toWallet: "funding",
|
|
67500
|
+
balanceAfterTransfer,
|
|
67501
|
+
timestamp: new Date().toISOString()
|
|
67502
|
+
};
|
|
67503
|
+
} catch (error) {
|
|
67504
|
+
console.error(`Error executing transfer for ${asset}:`, error);
|
|
67505
|
+
let currentBalance = 0;
|
|
67506
|
+
try {
|
|
67507
|
+
currentBalance = await getWalletBalance2(this.client, asset);
|
|
67508
|
+
} catch (balanceError) {
|
|
67509
|
+
console.warn("Could not fetch balance for error response:", balanceError);
|
|
67510
|
+
}
|
|
67511
|
+
return {
|
|
67512
|
+
success: false,
|
|
67513
|
+
asset,
|
|
67514
|
+
amount,
|
|
67515
|
+
fromWallet: "unified",
|
|
67516
|
+
toWallet: "funding",
|
|
67517
|
+
balanceAfterTransfer: currentBalance,
|
|
67518
|
+
timestamp: new Date().toISOString(),
|
|
67519
|
+
error: `Transfer execution failed: ${error instanceof Error ? error.message : error}`
|
|
67520
|
+
};
|
|
67521
|
+
}
|
|
67522
|
+
}
|
|
67324
67523
|
}
|
|
67325
67524
|
|
|
67326
67525
|
// src/helpers/accounts.ts
|
|
@@ -69029,9 +69228,6 @@ class ExchangeAccount {
|
|
|
69029
69228
|
}
|
|
69030
69229
|
return db_positions;
|
|
69031
69230
|
}
|
|
69032
|
-
async getRunningInstanceFromDB(symbol) {
|
|
69033
|
-
return await this.app_db.getRunningInstanceFromDB(this.instance, symbol);
|
|
69034
|
-
}
|
|
69035
69231
|
async syncOrders(options) {
|
|
69036
69232
|
const { symbol, update = false, kind } = options;
|
|
69037
69233
|
if (!update && kind) {
|
|
@@ -70680,22 +70876,11 @@ class App {
|
|
|
70680
70876
|
}
|
|
70681
70877
|
async syncOrders(payload) {
|
|
70682
70878
|
const exchange_account = await this.getExchangeAccount(payload.account);
|
|
70683
|
-
const db_running_instance = await exchange_account.getRunningInstanceFromDB(payload.symbol);
|
|
70684
|
-
if (db_running_instance.running) {
|
|
70685
|
-
return {
|
|
70686
|
-
new_config: null,
|
|
70687
|
-
position: null,
|
|
70688
|
-
config: null,
|
|
70689
|
-
error: "Already running"
|
|
70690
|
-
};
|
|
70691
|
-
}
|
|
70692
|
-
await this.app_db.updateRunningInstance(db_running_instance.id, true);
|
|
70693
70879
|
await exchange_account.syncAccount({
|
|
70694
70880
|
symbol: payload.symbol,
|
|
70695
70881
|
kind: payload.kind,
|
|
70696
70882
|
update: true
|
|
70697
70883
|
});
|
|
70698
|
-
await this.app_db.updateRunningInstance(db_running_instance.id, false);
|
|
70699
70884
|
return true;
|
|
70700
70885
|
}
|
|
70701
70886
|
async cancelOrders(payload) {
|