@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.cjs
CHANGED
|
@@ -61495,35 +61495,6 @@ class AppDatabase {
|
|
|
61495
61495
|
}
|
|
61496
61496
|
return null;
|
|
61497
61497
|
}
|
|
61498
|
-
async getRunningInstanceFromDB(account, symbol, options) {
|
|
61499
|
-
const { delay = 60 * 1000 } = options || {
|
|
61500
|
-
delay: 60 * 1000
|
|
61501
|
-
};
|
|
61502
|
-
const running_instance = await this.pb.collection("trade_block_tracking").getFirstListItem(`account.owner = "${account.owner}" && account.exchange = "${account.exchange}" && symbol = "${symbol}"`, {
|
|
61503
|
-
expand: "account"
|
|
61504
|
-
});
|
|
61505
|
-
if (!running_instance) {
|
|
61506
|
-
let account_instance = await this.pb.collection("exchange_accounts").getFirstListItem(`owner = "${account.owner}" && exchange = "${account.exchange}"`);
|
|
61507
|
-
return await this.pb.collection("trade_block_tracking").create({
|
|
61508
|
-
account: account_instance.id,
|
|
61509
|
-
symbol,
|
|
61510
|
-
running: false
|
|
61511
|
-
});
|
|
61512
|
-
}
|
|
61513
|
-
const updatedAt = new Date(running_instance.updated);
|
|
61514
|
-
const now = new Date;
|
|
61515
|
-
const diffInMinutes = (now.getTime() - updatedAt.getTime()) / delay;
|
|
61516
|
-
if (diffInMinutes >= 1) {
|
|
61517
|
-
await this.updateRunningInstance(running_instance.id, false);
|
|
61518
|
-
running_instance.running = false;
|
|
61519
|
-
}
|
|
61520
|
-
return running_instance;
|
|
61521
|
-
}
|
|
61522
|
-
async updateRunningInstance(id, running) {
|
|
61523
|
-
return await this.pb.collection("trade_block_tracking").update(id, {
|
|
61524
|
-
running
|
|
61525
|
-
});
|
|
61526
|
-
}
|
|
61527
61498
|
async getOrders(account, options) {
|
|
61528
61499
|
const { symbol, kind } = options;
|
|
61529
61500
|
const db_orders = await this.pb.collection("orders").getFullList({
|
|
@@ -61834,110 +61805,6 @@ class AppDatabase {
|
|
|
61834
61805
|
}
|
|
61835
61806
|
return null;
|
|
61836
61807
|
}
|
|
61837
|
-
async getBotViewInstance(payload) {
|
|
61838
|
-
const { asset, main_account } = payload;
|
|
61839
|
-
const bot_instances = await this.pb.collection("bot_view").getFullList({
|
|
61840
|
-
filter: `asset:lower="${asset.toLowerCase()}" && main_account.owner:lower="${main_account.owner.toLowerCase()}" && main_account.exchange:lower="${main_account.exchange.toLowerCase()}"`,
|
|
61841
|
-
expand: "main_account,secondary_account,main_long_strategy,main_short_strategy,secondary_long_strategy,secondary_short_strategy"
|
|
61842
|
-
});
|
|
61843
|
-
if (bot_instances.length > 0) {
|
|
61844
|
-
const instance = bot_instances[0];
|
|
61845
|
-
const {
|
|
61846
|
-
main_account: main_account2,
|
|
61847
|
-
secondary_account,
|
|
61848
|
-
main_long_strategy,
|
|
61849
|
-
main_short_strategy,
|
|
61850
|
-
secondary_long_strategy,
|
|
61851
|
-
secondary_short_strategy
|
|
61852
|
-
} = instance.expand;
|
|
61853
|
-
const update_boolean = (value) => {
|
|
61854
|
-
if (!value) {
|
|
61855
|
-
return value;
|
|
61856
|
-
}
|
|
61857
|
-
return {
|
|
61858
|
-
...value,
|
|
61859
|
-
follow: Boolean(value.follow),
|
|
61860
|
-
place_tp: Boolean(value.place_tp),
|
|
61861
|
-
pause_tp: Boolean(value.pause_tp)
|
|
61862
|
-
};
|
|
61863
|
-
};
|
|
61864
|
-
return {
|
|
61865
|
-
...instance,
|
|
61866
|
-
main: {
|
|
61867
|
-
account: main_account2,
|
|
61868
|
-
symbol: instance.main_symbol,
|
|
61869
|
-
strategy: {
|
|
61870
|
-
long: main_long_strategy,
|
|
61871
|
-
short: main_short_strategy
|
|
61872
|
-
},
|
|
61873
|
-
position: {
|
|
61874
|
-
long: instance.main_long_position,
|
|
61875
|
-
short: instance.main_short_position
|
|
61876
|
-
},
|
|
61877
|
-
config: {
|
|
61878
|
-
long: update_boolean(instance.main_long_config),
|
|
61879
|
-
short: update_boolean(instance.main_short_config)
|
|
61880
|
-
}
|
|
61881
|
-
},
|
|
61882
|
-
secondary: {
|
|
61883
|
-
account: secondary_account,
|
|
61884
|
-
symbol: instance.secondary_symbol,
|
|
61885
|
-
strategy: {
|
|
61886
|
-
long: secondary_long_strategy,
|
|
61887
|
-
short: secondary_short_strategy
|
|
61888
|
-
},
|
|
61889
|
-
position: {
|
|
61890
|
-
long: instance.secondary_long_position,
|
|
61891
|
-
short: instance.secondary_short_position
|
|
61892
|
-
},
|
|
61893
|
-
config: {
|
|
61894
|
-
long: update_boolean(instance.secondary_long_config),
|
|
61895
|
-
short: update_boolean(instance.secondary_short_config)
|
|
61896
|
-
}
|
|
61897
|
-
}
|
|
61898
|
-
};
|
|
61899
|
-
}
|
|
61900
|
-
return null;
|
|
61901
|
-
}
|
|
61902
|
-
async getBotInstance(payload) {
|
|
61903
|
-
const { asset, main_account } = payload;
|
|
61904
|
-
const bot_instances = await this.pb.collection("bot_instances").getFullList({
|
|
61905
|
-
filter: `asset:lower="${asset.toLowerCase()}" && main_account.owner:lower="${main_account.owner.toLowerCase()}" && main_account.exchange:lower="${main_account.exchange.toLowerCase()}"`
|
|
61906
|
-
});
|
|
61907
|
-
if (bot_instances.length > 0) {
|
|
61908
|
-
return bot_instances[0];
|
|
61909
|
-
}
|
|
61910
|
-
return null;
|
|
61911
|
-
}
|
|
61912
|
-
async getBotState(payload) {
|
|
61913
|
-
const { asset, main_account, running } = payload;
|
|
61914
|
-
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()}"`;
|
|
61915
|
-
if (running !== undefined) {
|
|
61916
|
-
filter += ` && running=${running}`;
|
|
61917
|
-
}
|
|
61918
|
-
const bot_states = await this.pb.collection("bot_states").getFullList({
|
|
61919
|
-
filter
|
|
61920
|
-
});
|
|
61921
|
-
return bot_states;
|
|
61922
|
-
}
|
|
61923
|
-
async getBotOrderHistories(payload) {
|
|
61924
|
-
const { asset, main_account, symbol, kind, type } = payload;
|
|
61925
|
-
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()}"`;
|
|
61926
|
-
if (symbol) {
|
|
61927
|
-
filter += ` && symbol:lower="${symbol.toLowerCase()}"`;
|
|
61928
|
-
}
|
|
61929
|
-
if (kind) {
|
|
61930
|
-
filter += ` && kind="${kind}"`;
|
|
61931
|
-
}
|
|
61932
|
-
if (type) {
|
|
61933
|
-
filter += ` && type="${type}"`;
|
|
61934
|
-
}
|
|
61935
|
-
const bot_order_histories = await this.pb.collection("bot_order_history").getFullList({
|
|
61936
|
-
filter,
|
|
61937
|
-
sort: "-created"
|
|
61938
|
-
});
|
|
61939
|
-
return bot_order_histories;
|
|
61940
|
-
}
|
|
61941
61808
|
async createOrUpdateWindingDownMarket(payload) {
|
|
61942
61809
|
const { symbol, risk_reward = 30 } = payload;
|
|
61943
61810
|
const existing_winding_down_market = await this.pb.collection("winding_down_markets").getFullList({
|
|
@@ -66627,6 +66494,171 @@ class BinanceExchange extends BaseExchange {
|
|
|
66627
66494
|
async forceClosePosition(symbol, options) {
|
|
66628
66495
|
return await forceClosePosition(this.client, symbol, options);
|
|
66629
66496
|
}
|
|
66497
|
+
async getTransferableAmount(options) {
|
|
66498
|
+
const { asset, maxTransferLimit } = options;
|
|
66499
|
+
try {
|
|
66500
|
+
const futuresBalance = await getWalletBalance(this.client, asset);
|
|
66501
|
+
const allPositions = await this.client.getPositionsV3();
|
|
66502
|
+
const activePositions = allPositions.filter((pos) => Math.abs(pos.positionAmt) > 0);
|
|
66503
|
+
let totalMarginUsed = 0;
|
|
66504
|
+
let totalUnrealizedPnl = 0;
|
|
66505
|
+
for (const position2 of activePositions) {
|
|
66506
|
+
const positionValue = Math.abs(position2.positionAmt) * position2.markPrice;
|
|
66507
|
+
const leverage = await getLeverage(this.client, position2.symbol);
|
|
66508
|
+
const marginForPosition = positionValue / (leverage || 1);
|
|
66509
|
+
console.log({ leverage });
|
|
66510
|
+
totalMarginUsed += marginForPosition;
|
|
66511
|
+
totalUnrealizedPnl += position2.unRealizedProfit || 0;
|
|
66512
|
+
}
|
|
66513
|
+
const safetyMarginPercent = 0.2;
|
|
66514
|
+
const requiredMargin = totalMarginUsed * (1 + safetyMarginPercent);
|
|
66515
|
+
const adjustedBalance = futuresBalance + totalUnrealizedPnl;
|
|
66516
|
+
const availableForTransfer = Math.max(0, adjustedBalance - requiredMargin);
|
|
66517
|
+
let maxTransferableAmount = availableForTransfer;
|
|
66518
|
+
let appliedLimit;
|
|
66519
|
+
if (maxTransferLimit && maxTransferLimit > 0) {
|
|
66520
|
+
maxTransferableAmount = Math.min(availableForTransfer, maxTransferLimit);
|
|
66521
|
+
appliedLimit = maxTransferLimit;
|
|
66522
|
+
}
|
|
66523
|
+
const recommendedTransferAmount = maxTransferableAmount * 0.8;
|
|
66524
|
+
const marginUtilization = adjustedBalance > 0 ? requiredMargin / adjustedBalance * 100 : 0;
|
|
66525
|
+
return {
|
|
66526
|
+
asset,
|
|
66527
|
+
totalBalance: futuresBalance,
|
|
66528
|
+
availableForTransfer,
|
|
66529
|
+
reservedForMargin: requiredMargin,
|
|
66530
|
+
maxTransferableAmount,
|
|
66531
|
+
appliedLimit,
|
|
66532
|
+
recommendedTransferAmount,
|
|
66533
|
+
marginUtilization,
|
|
66534
|
+
safetyMargin: safetyMarginPercent * 100
|
|
66535
|
+
};
|
|
66536
|
+
} catch (error) {
|
|
66537
|
+
console.error(`Error analyzing transferable amount for ${asset}:`, error);
|
|
66538
|
+
throw new Error(`Failed to analyze transferable funds: ${error instanceof Error ? error.message : error}`);
|
|
66539
|
+
}
|
|
66540
|
+
}
|
|
66541
|
+
async previewTransfer(options) {
|
|
66542
|
+
const { asset, amount } = options;
|
|
66543
|
+
const warnings = [];
|
|
66544
|
+
const errors = [];
|
|
66545
|
+
try {
|
|
66546
|
+
const analysis = await this.getTransferableAmount({ asset });
|
|
66547
|
+
let isValid3 = true;
|
|
66548
|
+
if (amount <= 0) {
|
|
66549
|
+
errors.push("Transfer amount must be greater than zero");
|
|
66550
|
+
isValid3 = false;
|
|
66551
|
+
}
|
|
66552
|
+
if (amount > analysis.maxTransferableAmount) {
|
|
66553
|
+
errors.push(`Transfer amount (${amount}) exceeds maximum transferable amount (${analysis.maxTransferableAmount})`);
|
|
66554
|
+
isValid3 = false;
|
|
66555
|
+
}
|
|
66556
|
+
if (amount > analysis.recommendedTransferAmount) {
|
|
66557
|
+
warnings.push(`Transfer amount exceeds recommended amount (${analysis.recommendedTransferAmount.toFixed(4)}). Consider transferring a smaller amount for safety.`);
|
|
66558
|
+
}
|
|
66559
|
+
if (analysis.marginUtilization > 70) {
|
|
66560
|
+
warnings.push(`High margin utilization (${analysis.marginUtilization.toFixed(1)}%). Transferring funds may increase liquidation risk.`);
|
|
66561
|
+
}
|
|
66562
|
+
const balanceAfterTransfer = analysis.totalBalance - amount;
|
|
66563
|
+
const marginRequirementAfterTransfer = analysis.reservedForMargin;
|
|
66564
|
+
if (isValid3 && balanceAfterTransfer < marginRequirementAfterTransfer) {
|
|
66565
|
+
errors.push("Transfer would result in insufficient margin for existing positions");
|
|
66566
|
+
isValid3 = false;
|
|
66567
|
+
}
|
|
66568
|
+
return {
|
|
66569
|
+
asset,
|
|
66570
|
+
requestedAmount: amount,
|
|
66571
|
+
isValid: isValid3,
|
|
66572
|
+
balanceAfterTransfer,
|
|
66573
|
+
marginRequirementAfterTransfer,
|
|
66574
|
+
warnings,
|
|
66575
|
+
errors
|
|
66576
|
+
};
|
|
66577
|
+
} catch (error) {
|
|
66578
|
+
console.error(`Error previewing transfer for ${asset}:`, error);
|
|
66579
|
+
return {
|
|
66580
|
+
asset,
|
|
66581
|
+
requestedAmount: amount,
|
|
66582
|
+
isValid: false,
|
|
66583
|
+
balanceAfterTransfer: 0,
|
|
66584
|
+
marginRequirementAfterTransfer: 0,
|
|
66585
|
+
warnings,
|
|
66586
|
+
errors: [`Failed to preview transfer: ${error instanceof Error ? error.message : error}`]
|
|
66587
|
+
};
|
|
66588
|
+
}
|
|
66589
|
+
}
|
|
66590
|
+
async executeFutureToSpotTransfer(options) {
|
|
66591
|
+
const { asset, amount, confirm, symbol = "BTCUSDT" } = options;
|
|
66592
|
+
try {
|
|
66593
|
+
if (!confirm) {
|
|
66594
|
+
return {
|
|
66595
|
+
success: false,
|
|
66596
|
+
asset,
|
|
66597
|
+
amount,
|
|
66598
|
+
fromWallet: "futures",
|
|
66599
|
+
toWallet: "spot",
|
|
66600
|
+
balanceAfterTransfer: 0,
|
|
66601
|
+
timestamp: new Date().toISOString(),
|
|
66602
|
+
error: "Transfer not confirmed. Set confirm: true to execute transfer."
|
|
66603
|
+
};
|
|
66604
|
+
}
|
|
66605
|
+
const preview = await this.previewTransfer({ asset, amount });
|
|
66606
|
+
if (!preview.isValid) {
|
|
66607
|
+
return {
|
|
66608
|
+
success: false,
|
|
66609
|
+
asset,
|
|
66610
|
+
amount,
|
|
66611
|
+
fromWallet: "futures",
|
|
66612
|
+
toWallet: "spot",
|
|
66613
|
+
balanceAfterTransfer: 0,
|
|
66614
|
+
timestamp: new Date().toISOString(),
|
|
66615
|
+
error: `Transfer validation failed: ${preview.errors.join("; ")}`
|
|
66616
|
+
};
|
|
66617
|
+
}
|
|
66618
|
+
const is_coin = !["USDT", "USDC", "BUSD"].includes(asset.toUpperCase());
|
|
66619
|
+
const transferType = is_coin ? CONSTANTS.COIN_FUTURE_TO_SPOT : CONSTANTS.USDT_FUTURE_TO_SPOT;
|
|
66620
|
+
if (!this.main_client) {
|
|
66621
|
+
throw new Error("Main client not available for transfers");
|
|
66622
|
+
}
|
|
66623
|
+
const transferClient = this.main_client;
|
|
66624
|
+
const transferResult = await transferClient.submitUniversalTransfer({
|
|
66625
|
+
asset: asset.toUpperCase(),
|
|
66626
|
+
amount,
|
|
66627
|
+
type: transferType,
|
|
66628
|
+
fromSymbol: symbol,
|
|
66629
|
+
toSymbol: symbol
|
|
66630
|
+
});
|
|
66631
|
+
const balanceAfterTransfer = await getWalletBalance(this.client, asset);
|
|
66632
|
+
return {
|
|
66633
|
+
success: true,
|
|
66634
|
+
transactionId: transferResult.tranId?.toString(),
|
|
66635
|
+
asset,
|
|
66636
|
+
amount,
|
|
66637
|
+
fromWallet: "futures",
|
|
66638
|
+
toWallet: "spot",
|
|
66639
|
+
balanceAfterTransfer,
|
|
66640
|
+
timestamp: new Date().toISOString()
|
|
66641
|
+
};
|
|
66642
|
+
} catch (error) {
|
|
66643
|
+
console.error(`Error executing transfer for ${asset}:`, error);
|
|
66644
|
+
let currentBalance = 0;
|
|
66645
|
+
try {
|
|
66646
|
+
currentBalance = await getWalletBalance(this.client, asset);
|
|
66647
|
+
} catch (balanceError) {
|
|
66648
|
+
console.warn("Could not fetch balance for error response:", balanceError);
|
|
66649
|
+
}
|
|
66650
|
+
return {
|
|
66651
|
+
success: false,
|
|
66652
|
+
asset,
|
|
66653
|
+
amount,
|
|
66654
|
+
fromWallet: "futures",
|
|
66655
|
+
toWallet: "spot",
|
|
66656
|
+
balanceAfterTransfer: currentBalance,
|
|
66657
|
+
timestamp: new Date().toISOString(),
|
|
66658
|
+
error: `Transfer execution failed: ${error instanceof Error ? error.message : error}`
|
|
66659
|
+
};
|
|
66660
|
+
}
|
|
66661
|
+
}
|
|
66630
66662
|
}
|
|
66631
66663
|
function getPricePlaces(target) {
|
|
66632
66664
|
const numStr = target.toString();
|
|
@@ -66952,6 +66984,11 @@ async function placeStopOrder2(client, payload) {
|
|
|
66952
66984
|
stop: payload.final_stop,
|
|
66953
66985
|
is_market: !payload.is_limit
|
|
66954
66986
|
};
|
|
66987
|
+
if (payload.hedge) {
|
|
66988
|
+
let reverse_kind = payload.kind === "long" ? "short" : "long";
|
|
66989
|
+
order.kind = reverse_kind;
|
|
66990
|
+
order.is_market = false;
|
|
66991
|
+
}
|
|
66955
66992
|
return createLimitPurchaseOrders(client, symbol, price_places, decimal_places, [order]);
|
|
66956
66993
|
}
|
|
66957
66994
|
async function getOpenOrders2(client, symbol, type) {
|
|
@@ -67348,6 +67385,168 @@ class BybitExchange extends BaseExchange {
|
|
|
67348
67385
|
return getOpenOrders2(this.client, payload.symbol);
|
|
67349
67386
|
}
|
|
67350
67387
|
async placeBadStopEntry(payload) {}
|
|
67388
|
+
async getTransferableAmount(options) {
|
|
67389
|
+
const { asset, maxTransferLimit } = options;
|
|
67390
|
+
try {
|
|
67391
|
+
const unifiedBalance = await getWalletBalance2(this.client, asset);
|
|
67392
|
+
const allPositions = await this.client.getPositionInfo({
|
|
67393
|
+
category: "linear",
|
|
67394
|
+
settleCoin: asset
|
|
67395
|
+
});
|
|
67396
|
+
const activePositions = (allPositions.result.list || []).filter((pos) => Math.abs(parseFloat(pos.size || "0")) > 0);
|
|
67397
|
+
let totalMarginUsed = 0;
|
|
67398
|
+
let totalUnrealizedPnl = 0;
|
|
67399
|
+
for (const position2 of activePositions) {
|
|
67400
|
+
const positionSize = Math.abs(parseFloat(position2.size || "0"));
|
|
67401
|
+
const markPrice = parseFloat(position2.markPrice || "0");
|
|
67402
|
+
const leverage = parseFloat(position2.leverage || "1");
|
|
67403
|
+
const positionValue = positionSize * markPrice;
|
|
67404
|
+
const marginForPosition = positionValue / leverage;
|
|
67405
|
+
totalMarginUsed += marginForPosition;
|
|
67406
|
+
totalUnrealizedPnl += parseFloat(position2.unrealisedPnl || "0");
|
|
67407
|
+
}
|
|
67408
|
+
const safetyMarginPercent = 0.2;
|
|
67409
|
+
const requiredMargin = totalMarginUsed * (1 + safetyMarginPercent);
|
|
67410
|
+
const adjustedBalance = unifiedBalance + totalUnrealizedPnl;
|
|
67411
|
+
const availableForTransfer = Math.max(0, adjustedBalance - requiredMargin);
|
|
67412
|
+
let maxTransferableAmount = availableForTransfer;
|
|
67413
|
+
let appliedLimit;
|
|
67414
|
+
if (maxTransferLimit && maxTransferLimit > 0) {
|
|
67415
|
+
maxTransferableAmount = Math.min(availableForTransfer, maxTransferLimit);
|
|
67416
|
+
appliedLimit = maxTransferLimit;
|
|
67417
|
+
}
|
|
67418
|
+
const recommendedTransferAmount = maxTransferableAmount * 0.8;
|
|
67419
|
+
const marginUtilization = adjustedBalance > 0 ? requiredMargin / adjustedBalance * 100 : 0;
|
|
67420
|
+
return {
|
|
67421
|
+
asset,
|
|
67422
|
+
totalBalance: unifiedBalance,
|
|
67423
|
+
availableForTransfer,
|
|
67424
|
+
reservedForMargin: requiredMargin,
|
|
67425
|
+
maxTransferableAmount,
|
|
67426
|
+
appliedLimit,
|
|
67427
|
+
recommendedTransferAmount,
|
|
67428
|
+
marginUtilization,
|
|
67429
|
+
safetyMargin: safetyMarginPercent * 100
|
|
67430
|
+
};
|
|
67431
|
+
} catch (error) {
|
|
67432
|
+
console.error(`Error analyzing transferable amount for ${asset}:`, error);
|
|
67433
|
+
throw new Error(`Failed to analyze transferable funds: ${error instanceof Error ? error.message : error}`);
|
|
67434
|
+
}
|
|
67435
|
+
}
|
|
67436
|
+
async previewTransfer(options) {
|
|
67437
|
+
const { asset, amount } = options;
|
|
67438
|
+
const warnings = [];
|
|
67439
|
+
const errors = [];
|
|
67440
|
+
try {
|
|
67441
|
+
const analysis = await this.getTransferableAmount({ asset });
|
|
67442
|
+
let isValid3 = true;
|
|
67443
|
+
if (amount <= 0) {
|
|
67444
|
+
errors.push("Transfer amount must be greater than zero");
|
|
67445
|
+
isValid3 = false;
|
|
67446
|
+
}
|
|
67447
|
+
if (amount > analysis.maxTransferableAmount) {
|
|
67448
|
+
errors.push(`Transfer amount (${amount}) exceeds maximum transferable amount (${analysis.maxTransferableAmount})`);
|
|
67449
|
+
isValid3 = false;
|
|
67450
|
+
}
|
|
67451
|
+
if (amount > analysis.recommendedTransferAmount) {
|
|
67452
|
+
warnings.push(`Transfer amount exceeds recommended amount (${analysis.recommendedTransferAmount.toFixed(4)}). Consider transferring a smaller amount for safety.`);
|
|
67453
|
+
}
|
|
67454
|
+
if (analysis.marginUtilization > 70) {
|
|
67455
|
+
warnings.push(`High margin utilization (${analysis.marginUtilization.toFixed(1)}%). Transferring funds may increase liquidation risk.`);
|
|
67456
|
+
}
|
|
67457
|
+
const balanceAfterTransfer = analysis.totalBalance - amount;
|
|
67458
|
+
const marginRequirementAfterTransfer = analysis.reservedForMargin;
|
|
67459
|
+
if (isValid3 && balanceAfterTransfer < marginRequirementAfterTransfer) {
|
|
67460
|
+
errors.push("Transfer would result in insufficient margin for existing positions");
|
|
67461
|
+
isValid3 = false;
|
|
67462
|
+
}
|
|
67463
|
+
return {
|
|
67464
|
+
asset,
|
|
67465
|
+
requestedAmount: amount,
|
|
67466
|
+
isValid: isValid3,
|
|
67467
|
+
balanceAfterTransfer,
|
|
67468
|
+
marginRequirementAfterTransfer,
|
|
67469
|
+
warnings,
|
|
67470
|
+
errors
|
|
67471
|
+
};
|
|
67472
|
+
} catch (error) {
|
|
67473
|
+
console.error(`Error previewing transfer for ${asset}:`, error);
|
|
67474
|
+
return {
|
|
67475
|
+
asset,
|
|
67476
|
+
requestedAmount: amount,
|
|
67477
|
+
isValid: false,
|
|
67478
|
+
balanceAfterTransfer: 0,
|
|
67479
|
+
marginRequirementAfterTransfer: 0,
|
|
67480
|
+
warnings,
|
|
67481
|
+
errors: [
|
|
67482
|
+
`Failed to preview transfer: ${error instanceof Error ? error.message : error}`
|
|
67483
|
+
]
|
|
67484
|
+
};
|
|
67485
|
+
}
|
|
67486
|
+
}
|
|
67487
|
+
async executeUnifiedToFundingTransfer(options) {
|
|
67488
|
+
const { asset, amount, confirm } = options;
|
|
67489
|
+
try {
|
|
67490
|
+
if (!confirm) {
|
|
67491
|
+
return {
|
|
67492
|
+
success: false,
|
|
67493
|
+
asset,
|
|
67494
|
+
amount,
|
|
67495
|
+
fromWallet: "unified",
|
|
67496
|
+
toWallet: "funding",
|
|
67497
|
+
balanceAfterTransfer: 0,
|
|
67498
|
+
timestamp: new Date().toISOString(),
|
|
67499
|
+
error: "Transfer not confirmed. Set confirm: true to execute transfer."
|
|
67500
|
+
};
|
|
67501
|
+
}
|
|
67502
|
+
const preview = await this.previewTransfer({ asset, amount });
|
|
67503
|
+
if (!preview.isValid) {
|
|
67504
|
+
return {
|
|
67505
|
+
success: false,
|
|
67506
|
+
asset,
|
|
67507
|
+
amount,
|
|
67508
|
+
fromWallet: "unified",
|
|
67509
|
+
toWallet: "funding",
|
|
67510
|
+
balanceAfterTransfer: 0,
|
|
67511
|
+
timestamp: new Date().toISOString(),
|
|
67512
|
+
error: `Transfer validation failed: ${preview.errors.join("; ")}`
|
|
67513
|
+
};
|
|
67514
|
+
}
|
|
67515
|
+
const transferResult = await this.client.createInternalTransfer(`bybit_transfer_${Date.now()}`, asset.toUpperCase(), amount.toString(), "UNIFIED", "FUND");
|
|
67516
|
+
if (transferResult.retCode !== 0) {
|
|
67517
|
+
throw new Error(`Bybit transfer failed: ${transferResult.retMsg} (code: ${transferResult.retCode})`);
|
|
67518
|
+
}
|
|
67519
|
+
const balanceAfterTransfer = await getWalletBalance2(this.client, asset);
|
|
67520
|
+
return {
|
|
67521
|
+
success: true,
|
|
67522
|
+
transactionId: transferResult.result?.transferId,
|
|
67523
|
+
asset,
|
|
67524
|
+
amount,
|
|
67525
|
+
fromWallet: "unified",
|
|
67526
|
+
toWallet: "funding",
|
|
67527
|
+
balanceAfterTransfer,
|
|
67528
|
+
timestamp: new Date().toISOString()
|
|
67529
|
+
};
|
|
67530
|
+
} catch (error) {
|
|
67531
|
+
console.error(`Error executing transfer for ${asset}:`, error);
|
|
67532
|
+
let currentBalance = 0;
|
|
67533
|
+
try {
|
|
67534
|
+
currentBalance = await getWalletBalance2(this.client, asset);
|
|
67535
|
+
} catch (balanceError) {
|
|
67536
|
+
console.warn("Could not fetch balance for error response:", balanceError);
|
|
67537
|
+
}
|
|
67538
|
+
return {
|
|
67539
|
+
success: false,
|
|
67540
|
+
asset,
|
|
67541
|
+
amount,
|
|
67542
|
+
fromWallet: "unified",
|
|
67543
|
+
toWallet: "funding",
|
|
67544
|
+
balanceAfterTransfer: currentBalance,
|
|
67545
|
+
timestamp: new Date().toISOString(),
|
|
67546
|
+
error: `Transfer execution failed: ${error instanceof Error ? error.message : error}`
|
|
67547
|
+
};
|
|
67548
|
+
}
|
|
67549
|
+
}
|
|
67351
67550
|
}
|
|
67352
67551
|
|
|
67353
67552
|
// src/helpers/accounts.ts
|
|
@@ -69056,9 +69255,6 @@ class ExchangeAccount {
|
|
|
69056
69255
|
}
|
|
69057
69256
|
return db_positions;
|
|
69058
69257
|
}
|
|
69059
|
-
async getRunningInstanceFromDB(symbol) {
|
|
69060
|
-
return await this.app_db.getRunningInstanceFromDB(this.instance, symbol);
|
|
69061
|
-
}
|
|
69062
69258
|
async syncOrders(options) {
|
|
69063
69259
|
const { symbol, update = false, kind } = options;
|
|
69064
69260
|
if (!update && kind) {
|
|
@@ -70707,22 +70903,11 @@ class App {
|
|
|
70707
70903
|
}
|
|
70708
70904
|
async syncOrders(payload) {
|
|
70709
70905
|
const exchange_account = await this.getExchangeAccount(payload.account);
|
|
70710
|
-
const db_running_instance = await exchange_account.getRunningInstanceFromDB(payload.symbol);
|
|
70711
|
-
if (db_running_instance.running) {
|
|
70712
|
-
return {
|
|
70713
|
-
new_config: null,
|
|
70714
|
-
position: null,
|
|
70715
|
-
config: null,
|
|
70716
|
-
error: "Already running"
|
|
70717
|
-
};
|
|
70718
|
-
}
|
|
70719
|
-
await this.app_db.updateRunningInstance(db_running_instance.id, true);
|
|
70720
70906
|
await exchange_account.syncAccount({
|
|
70721
70907
|
symbol: payload.symbol,
|
|
70722
70908
|
kind: payload.kind,
|
|
70723
70909
|
update: true
|
|
70724
70910
|
});
|
|
70725
|
-
await this.app_db.updateRunningInstance(db_running_instance.id, false);
|
|
70726
70911
|
return true;
|
|
70727
70912
|
}
|
|
70728
70913
|
async cancelOrders(payload) {
|