@gbozee/ultimate 0.0.2-192 → 0.0.2-193

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.cjs CHANGED
@@ -60051,6 +60051,171 @@ class BinanceExchange extends BaseExchange {
60051
60051
  async forceClosePosition(symbol, options) {
60052
60052
  return await forceClosePosition(this.client, symbol, options);
60053
60053
  }
60054
+ async getTransferableAmount(options) {
60055
+ const { asset, maxTransferLimit } = options;
60056
+ try {
60057
+ const futuresBalance = await getWalletBalance(this.client, asset);
60058
+ const allPositions = await this.client.getPositionsV3();
60059
+ const activePositions = allPositions.filter((pos) => Math.abs(pos.positionAmt) > 0);
60060
+ let totalMarginUsed = 0;
60061
+ let totalUnrealizedPnl = 0;
60062
+ for (const position2 of activePositions) {
60063
+ const positionValue = Math.abs(position2.positionAmt) * position2.markPrice;
60064
+ const leverage = await getLeverage(this.client, position2.symbol);
60065
+ const marginForPosition = positionValue / (leverage || 1);
60066
+ console.log({ leverage });
60067
+ totalMarginUsed += marginForPosition;
60068
+ totalUnrealizedPnl += position2.unRealizedProfit || 0;
60069
+ }
60070
+ const safetyMarginPercent = 0.2;
60071
+ const requiredMargin = totalMarginUsed * (1 + safetyMarginPercent);
60072
+ const adjustedBalance = futuresBalance + totalUnrealizedPnl;
60073
+ const availableForTransfer = Math.max(0, adjustedBalance - requiredMargin);
60074
+ let maxTransferableAmount = availableForTransfer;
60075
+ let appliedLimit;
60076
+ if (maxTransferLimit && maxTransferLimit > 0) {
60077
+ maxTransferableAmount = Math.min(availableForTransfer, maxTransferLimit);
60078
+ appliedLimit = maxTransferLimit;
60079
+ }
60080
+ const recommendedTransferAmount = maxTransferableAmount * 0.8;
60081
+ const marginUtilization = adjustedBalance > 0 ? requiredMargin / adjustedBalance * 100 : 0;
60082
+ return {
60083
+ asset,
60084
+ totalBalance: futuresBalance,
60085
+ availableForTransfer,
60086
+ reservedForMargin: requiredMargin,
60087
+ maxTransferableAmount,
60088
+ appliedLimit,
60089
+ recommendedTransferAmount,
60090
+ marginUtilization,
60091
+ safetyMargin: safetyMarginPercent * 100
60092
+ };
60093
+ } catch (error) {
60094
+ console.error(`Error analyzing transferable amount for ${asset}:`, error);
60095
+ throw new Error(`Failed to analyze transferable funds: ${error instanceof Error ? error.message : error}`);
60096
+ }
60097
+ }
60098
+ async previewTransfer(options) {
60099
+ const { asset, amount } = options;
60100
+ const warnings = [];
60101
+ const errors = [];
60102
+ try {
60103
+ const analysis = await this.getTransferableAmount({ asset });
60104
+ let isValid2 = true;
60105
+ if (amount <= 0) {
60106
+ errors.push("Transfer amount must be greater than zero");
60107
+ isValid2 = false;
60108
+ }
60109
+ if (amount > analysis.maxTransferableAmount) {
60110
+ errors.push(`Transfer amount (${amount}) exceeds maximum transferable amount (${analysis.maxTransferableAmount})`);
60111
+ isValid2 = false;
60112
+ }
60113
+ if (amount > analysis.recommendedTransferAmount) {
60114
+ warnings.push(`Transfer amount exceeds recommended amount (${analysis.recommendedTransferAmount.toFixed(4)}). Consider transferring a smaller amount for safety.`);
60115
+ }
60116
+ if (analysis.marginUtilization > 70) {
60117
+ warnings.push(`High margin utilization (${analysis.marginUtilization.toFixed(1)}%). Transferring funds may increase liquidation risk.`);
60118
+ }
60119
+ const balanceAfterTransfer = analysis.totalBalance - amount;
60120
+ const marginRequirementAfterTransfer = analysis.reservedForMargin;
60121
+ if (isValid2 && balanceAfterTransfer < marginRequirementAfterTransfer) {
60122
+ errors.push("Transfer would result in insufficient margin for existing positions");
60123
+ isValid2 = false;
60124
+ }
60125
+ return {
60126
+ asset,
60127
+ requestedAmount: amount,
60128
+ isValid: isValid2,
60129
+ balanceAfterTransfer,
60130
+ marginRequirementAfterTransfer,
60131
+ warnings,
60132
+ errors
60133
+ };
60134
+ } catch (error) {
60135
+ console.error(`Error previewing transfer for ${asset}:`, error);
60136
+ return {
60137
+ asset,
60138
+ requestedAmount: amount,
60139
+ isValid: false,
60140
+ balanceAfterTransfer: 0,
60141
+ marginRequirementAfterTransfer: 0,
60142
+ warnings,
60143
+ errors: [`Failed to preview transfer: ${error instanceof Error ? error.message : error}`]
60144
+ };
60145
+ }
60146
+ }
60147
+ async executeFutureToSpotTransfer(options) {
60148
+ const { asset, amount, confirm, symbol = "BTCUSDT" } = options;
60149
+ try {
60150
+ if (!confirm) {
60151
+ return {
60152
+ success: false,
60153
+ asset,
60154
+ amount,
60155
+ fromWallet: "futures",
60156
+ toWallet: "spot",
60157
+ balanceAfterTransfer: 0,
60158
+ timestamp: new Date().toISOString(),
60159
+ error: "Transfer not confirmed. Set confirm: true to execute transfer."
60160
+ };
60161
+ }
60162
+ const preview = await this.previewTransfer({ asset, amount });
60163
+ if (!preview.isValid) {
60164
+ return {
60165
+ success: false,
60166
+ asset,
60167
+ amount,
60168
+ fromWallet: "futures",
60169
+ toWallet: "spot",
60170
+ balanceAfterTransfer: 0,
60171
+ timestamp: new Date().toISOString(),
60172
+ error: `Transfer validation failed: ${preview.errors.join("; ")}`
60173
+ };
60174
+ }
60175
+ const is_coin = !["USDT", "USDC", "BUSD"].includes(asset.toUpperCase());
60176
+ const transferType = is_coin ? CONSTANTS.COIN_FUTURE_TO_SPOT : CONSTANTS.USDT_FUTURE_TO_SPOT;
60177
+ if (!this.main_client) {
60178
+ throw new Error("Main client not available for transfers");
60179
+ }
60180
+ const transferClient = this.main_client;
60181
+ const transferResult = await transferClient.submitUniversalTransfer({
60182
+ asset: asset.toUpperCase(),
60183
+ amount,
60184
+ type: transferType,
60185
+ fromSymbol: symbol,
60186
+ toSymbol: symbol
60187
+ });
60188
+ const balanceAfterTransfer = await getWalletBalance(this.client, asset);
60189
+ return {
60190
+ success: true,
60191
+ transactionId: transferResult.tranId?.toString(),
60192
+ asset,
60193
+ amount,
60194
+ fromWallet: "futures",
60195
+ toWallet: "spot",
60196
+ balanceAfterTransfer,
60197
+ timestamp: new Date().toISOString()
60198
+ };
60199
+ } catch (error) {
60200
+ console.error(`Error executing transfer for ${asset}:`, error);
60201
+ let currentBalance = 0;
60202
+ try {
60203
+ currentBalance = await getWalletBalance(this.client, asset);
60204
+ } catch (balanceError) {
60205
+ console.warn("Could not fetch balance for error response:", balanceError);
60206
+ }
60207
+ return {
60208
+ success: false,
60209
+ asset,
60210
+ amount,
60211
+ fromWallet: "futures",
60212
+ toWallet: "spot",
60213
+ balanceAfterTransfer: currentBalance,
60214
+ timestamp: new Date().toISOString(),
60215
+ error: `Transfer execution failed: ${error instanceof Error ? error.message : error}`
60216
+ };
60217
+ }
60218
+ }
60054
60219
  }
60055
60220
  function getPricePlaces(target) {
60056
60221
  const numStr = target.toString();
@@ -60376,6 +60541,11 @@ async function placeStopOrder2(client, payload) {
60376
60541
  stop: payload.final_stop,
60377
60542
  is_market: !payload.is_limit
60378
60543
  };
60544
+ if (payload.hedge) {
60545
+ let reverse_kind = payload.kind === "long" ? "short" : "long";
60546
+ order.kind = reverse_kind;
60547
+ order.is_market = false;
60548
+ }
60379
60549
  return createLimitPurchaseOrders(client, symbol, price_places, decimal_places, [order]);
60380
60550
  }
60381
60551
  async function getOpenOrders2(client, symbol, type) {
@@ -60772,6 +60942,168 @@ class BybitExchange extends BaseExchange {
60772
60942
  return getOpenOrders2(this.client, payload.symbol);
60773
60943
  }
60774
60944
  async placeBadStopEntry(payload) {}
60945
+ async getTransferableAmount(options) {
60946
+ const { asset, maxTransferLimit } = options;
60947
+ try {
60948
+ const unifiedBalance = await getWalletBalance2(this.client, asset);
60949
+ const allPositions = await this.client.getPositionInfo({
60950
+ category: "linear",
60951
+ settleCoin: asset
60952
+ });
60953
+ const activePositions = (allPositions.result.list || []).filter((pos) => Math.abs(parseFloat(pos.size || "0")) > 0);
60954
+ let totalMarginUsed = 0;
60955
+ let totalUnrealizedPnl = 0;
60956
+ for (const position2 of activePositions) {
60957
+ const positionSize = Math.abs(parseFloat(position2.size || "0"));
60958
+ const markPrice = parseFloat(position2.markPrice || "0");
60959
+ const leverage = parseFloat(position2.leverage || "1");
60960
+ const positionValue = positionSize * markPrice;
60961
+ const marginForPosition = positionValue / leverage;
60962
+ totalMarginUsed += marginForPosition;
60963
+ totalUnrealizedPnl += parseFloat(position2.unrealisedPnl || "0");
60964
+ }
60965
+ const safetyMarginPercent = 0.2;
60966
+ const requiredMargin = totalMarginUsed * (1 + safetyMarginPercent);
60967
+ const adjustedBalance = unifiedBalance + totalUnrealizedPnl;
60968
+ const availableForTransfer = Math.max(0, adjustedBalance - requiredMargin);
60969
+ let maxTransferableAmount = availableForTransfer;
60970
+ let appliedLimit;
60971
+ if (maxTransferLimit && maxTransferLimit > 0) {
60972
+ maxTransferableAmount = Math.min(availableForTransfer, maxTransferLimit);
60973
+ appliedLimit = maxTransferLimit;
60974
+ }
60975
+ const recommendedTransferAmount = maxTransferableAmount * 0.8;
60976
+ const marginUtilization = adjustedBalance > 0 ? requiredMargin / adjustedBalance * 100 : 0;
60977
+ return {
60978
+ asset,
60979
+ totalBalance: unifiedBalance,
60980
+ availableForTransfer,
60981
+ reservedForMargin: requiredMargin,
60982
+ maxTransferableAmount,
60983
+ appliedLimit,
60984
+ recommendedTransferAmount,
60985
+ marginUtilization,
60986
+ safetyMargin: safetyMarginPercent * 100
60987
+ };
60988
+ } catch (error) {
60989
+ console.error(`Error analyzing transferable amount for ${asset}:`, error);
60990
+ throw new Error(`Failed to analyze transferable funds: ${error instanceof Error ? error.message : error}`);
60991
+ }
60992
+ }
60993
+ async previewTransfer(options) {
60994
+ const { asset, amount } = options;
60995
+ const warnings = [];
60996
+ const errors = [];
60997
+ try {
60998
+ const analysis = await this.getTransferableAmount({ asset });
60999
+ let isValid2 = true;
61000
+ if (amount <= 0) {
61001
+ errors.push("Transfer amount must be greater than zero");
61002
+ isValid2 = false;
61003
+ }
61004
+ if (amount > analysis.maxTransferableAmount) {
61005
+ errors.push(`Transfer amount (${amount}) exceeds maximum transferable amount (${analysis.maxTransferableAmount})`);
61006
+ isValid2 = false;
61007
+ }
61008
+ if (amount > analysis.recommendedTransferAmount) {
61009
+ warnings.push(`Transfer amount exceeds recommended amount (${analysis.recommendedTransferAmount.toFixed(4)}). Consider transferring a smaller amount for safety.`);
61010
+ }
61011
+ if (analysis.marginUtilization > 70) {
61012
+ warnings.push(`High margin utilization (${analysis.marginUtilization.toFixed(1)}%). Transferring funds may increase liquidation risk.`);
61013
+ }
61014
+ const balanceAfterTransfer = analysis.totalBalance - amount;
61015
+ const marginRequirementAfterTransfer = analysis.reservedForMargin;
61016
+ if (isValid2 && balanceAfterTransfer < marginRequirementAfterTransfer) {
61017
+ errors.push("Transfer would result in insufficient margin for existing positions");
61018
+ isValid2 = false;
61019
+ }
61020
+ return {
61021
+ asset,
61022
+ requestedAmount: amount,
61023
+ isValid: isValid2,
61024
+ balanceAfterTransfer,
61025
+ marginRequirementAfterTransfer,
61026
+ warnings,
61027
+ errors
61028
+ };
61029
+ } catch (error) {
61030
+ console.error(`Error previewing transfer for ${asset}:`, error);
61031
+ return {
61032
+ asset,
61033
+ requestedAmount: amount,
61034
+ isValid: false,
61035
+ balanceAfterTransfer: 0,
61036
+ marginRequirementAfterTransfer: 0,
61037
+ warnings,
61038
+ errors: [
61039
+ `Failed to preview transfer: ${error instanceof Error ? error.message : error}`
61040
+ ]
61041
+ };
61042
+ }
61043
+ }
61044
+ async executeUnifiedToFundingTransfer(options) {
61045
+ const { asset, amount, confirm } = options;
61046
+ try {
61047
+ if (!confirm) {
61048
+ return {
61049
+ success: false,
61050
+ asset,
61051
+ amount,
61052
+ fromWallet: "unified",
61053
+ toWallet: "funding",
61054
+ balanceAfterTransfer: 0,
61055
+ timestamp: new Date().toISOString(),
61056
+ error: "Transfer not confirmed. Set confirm: true to execute transfer."
61057
+ };
61058
+ }
61059
+ const preview = await this.previewTransfer({ asset, amount });
61060
+ if (!preview.isValid) {
61061
+ return {
61062
+ success: false,
61063
+ asset,
61064
+ amount,
61065
+ fromWallet: "unified",
61066
+ toWallet: "funding",
61067
+ balanceAfterTransfer: 0,
61068
+ timestamp: new Date().toISOString(),
61069
+ error: `Transfer validation failed: ${preview.errors.join("; ")}`
61070
+ };
61071
+ }
61072
+ const transferResult = await this.client.createInternalTransfer(`bybit_transfer_${Date.now()}`, asset.toUpperCase(), amount.toString(), "UNIFIED", "FUND");
61073
+ if (transferResult.retCode !== 0) {
61074
+ throw new Error(`Bybit transfer failed: ${transferResult.retMsg} (code: ${transferResult.retCode})`);
61075
+ }
61076
+ const balanceAfterTransfer = await getWalletBalance2(this.client, asset);
61077
+ return {
61078
+ success: true,
61079
+ transactionId: transferResult.result?.transferId,
61080
+ asset,
61081
+ amount,
61082
+ fromWallet: "unified",
61083
+ toWallet: "funding",
61084
+ balanceAfterTransfer,
61085
+ timestamp: new Date().toISOString()
61086
+ };
61087
+ } catch (error) {
61088
+ console.error(`Error executing transfer for ${asset}:`, error);
61089
+ let currentBalance = 0;
61090
+ try {
61091
+ currentBalance = await getWalletBalance2(this.client, asset);
61092
+ } catch (balanceError) {
61093
+ console.warn("Could not fetch balance for error response:", balanceError);
61094
+ }
61095
+ return {
61096
+ success: false,
61097
+ asset,
61098
+ amount,
61099
+ fromWallet: "unified",
61100
+ toWallet: "funding",
61101
+ balanceAfterTransfer: currentBalance,
61102
+ timestamp: new Date().toISOString(),
61103
+ error: `Transfer execution failed: ${error instanceof Error ? error.message : error}`
61104
+ };
61105
+ }
61106
+ }
60775
61107
  }
60776
61108
 
60777
61109
  // src/helpers/accounts.ts
package/dist/index.js CHANGED
@@ -59989,6 +59989,171 @@ class BinanceExchange extends BaseExchange {
59989
59989
  async forceClosePosition(symbol, options) {
59990
59990
  return await forceClosePosition(this.client, symbol, options);
59991
59991
  }
59992
+ async getTransferableAmount(options) {
59993
+ const { asset, maxTransferLimit } = options;
59994
+ try {
59995
+ const futuresBalance = await getWalletBalance(this.client, asset);
59996
+ const allPositions = await this.client.getPositionsV3();
59997
+ const activePositions = allPositions.filter((pos) => Math.abs(pos.positionAmt) > 0);
59998
+ let totalMarginUsed = 0;
59999
+ let totalUnrealizedPnl = 0;
60000
+ for (const position2 of activePositions) {
60001
+ const positionValue = Math.abs(position2.positionAmt) * position2.markPrice;
60002
+ const leverage = await getLeverage(this.client, position2.symbol);
60003
+ const marginForPosition = positionValue / (leverage || 1);
60004
+ console.log({ leverage });
60005
+ totalMarginUsed += marginForPosition;
60006
+ totalUnrealizedPnl += position2.unRealizedProfit || 0;
60007
+ }
60008
+ const safetyMarginPercent = 0.2;
60009
+ const requiredMargin = totalMarginUsed * (1 + safetyMarginPercent);
60010
+ const adjustedBalance = futuresBalance + totalUnrealizedPnl;
60011
+ const availableForTransfer = Math.max(0, adjustedBalance - requiredMargin);
60012
+ let maxTransferableAmount = availableForTransfer;
60013
+ let appliedLimit;
60014
+ if (maxTransferLimit && maxTransferLimit > 0) {
60015
+ maxTransferableAmount = Math.min(availableForTransfer, maxTransferLimit);
60016
+ appliedLimit = maxTransferLimit;
60017
+ }
60018
+ const recommendedTransferAmount = maxTransferableAmount * 0.8;
60019
+ const marginUtilization = adjustedBalance > 0 ? requiredMargin / adjustedBalance * 100 : 0;
60020
+ return {
60021
+ asset,
60022
+ totalBalance: futuresBalance,
60023
+ availableForTransfer,
60024
+ reservedForMargin: requiredMargin,
60025
+ maxTransferableAmount,
60026
+ appliedLimit,
60027
+ recommendedTransferAmount,
60028
+ marginUtilization,
60029
+ safetyMargin: safetyMarginPercent * 100
60030
+ };
60031
+ } catch (error) {
60032
+ console.error(`Error analyzing transferable amount for ${asset}:`, error);
60033
+ throw new Error(`Failed to analyze transferable funds: ${error instanceof Error ? error.message : error}`);
60034
+ }
60035
+ }
60036
+ async previewTransfer(options) {
60037
+ const { asset, amount } = options;
60038
+ const warnings = [];
60039
+ const errors = [];
60040
+ try {
60041
+ const analysis = await this.getTransferableAmount({ asset });
60042
+ let isValid2 = true;
60043
+ if (amount <= 0) {
60044
+ errors.push("Transfer amount must be greater than zero");
60045
+ isValid2 = false;
60046
+ }
60047
+ if (amount > analysis.maxTransferableAmount) {
60048
+ errors.push(`Transfer amount (${amount}) exceeds maximum transferable amount (${analysis.maxTransferableAmount})`);
60049
+ isValid2 = false;
60050
+ }
60051
+ if (amount > analysis.recommendedTransferAmount) {
60052
+ warnings.push(`Transfer amount exceeds recommended amount (${analysis.recommendedTransferAmount.toFixed(4)}). Consider transferring a smaller amount for safety.`);
60053
+ }
60054
+ if (analysis.marginUtilization > 70) {
60055
+ warnings.push(`High margin utilization (${analysis.marginUtilization.toFixed(1)}%). Transferring funds may increase liquidation risk.`);
60056
+ }
60057
+ const balanceAfterTransfer = analysis.totalBalance - amount;
60058
+ const marginRequirementAfterTransfer = analysis.reservedForMargin;
60059
+ if (isValid2 && balanceAfterTransfer < marginRequirementAfterTransfer) {
60060
+ errors.push("Transfer would result in insufficient margin for existing positions");
60061
+ isValid2 = false;
60062
+ }
60063
+ return {
60064
+ asset,
60065
+ requestedAmount: amount,
60066
+ isValid: isValid2,
60067
+ balanceAfterTransfer,
60068
+ marginRequirementAfterTransfer,
60069
+ warnings,
60070
+ errors
60071
+ };
60072
+ } catch (error) {
60073
+ console.error(`Error previewing transfer for ${asset}:`, error);
60074
+ return {
60075
+ asset,
60076
+ requestedAmount: amount,
60077
+ isValid: false,
60078
+ balanceAfterTransfer: 0,
60079
+ marginRequirementAfterTransfer: 0,
60080
+ warnings,
60081
+ errors: [`Failed to preview transfer: ${error instanceof Error ? error.message : error}`]
60082
+ };
60083
+ }
60084
+ }
60085
+ async executeFutureToSpotTransfer(options) {
60086
+ const { asset, amount, confirm, symbol = "BTCUSDT" } = options;
60087
+ try {
60088
+ if (!confirm) {
60089
+ return {
60090
+ success: false,
60091
+ asset,
60092
+ amount,
60093
+ fromWallet: "futures",
60094
+ toWallet: "spot",
60095
+ balanceAfterTransfer: 0,
60096
+ timestamp: new Date().toISOString(),
60097
+ error: "Transfer not confirmed. Set confirm: true to execute transfer."
60098
+ };
60099
+ }
60100
+ const preview = await this.previewTransfer({ asset, amount });
60101
+ if (!preview.isValid) {
60102
+ return {
60103
+ success: false,
60104
+ asset,
60105
+ amount,
60106
+ fromWallet: "futures",
60107
+ toWallet: "spot",
60108
+ balanceAfterTransfer: 0,
60109
+ timestamp: new Date().toISOString(),
60110
+ error: `Transfer validation failed: ${preview.errors.join("; ")}`
60111
+ };
60112
+ }
60113
+ const is_coin = !["USDT", "USDC", "BUSD"].includes(asset.toUpperCase());
60114
+ const transferType = is_coin ? CONSTANTS.COIN_FUTURE_TO_SPOT : CONSTANTS.USDT_FUTURE_TO_SPOT;
60115
+ if (!this.main_client) {
60116
+ throw new Error("Main client not available for transfers");
60117
+ }
60118
+ const transferClient = this.main_client;
60119
+ const transferResult = await transferClient.submitUniversalTransfer({
60120
+ asset: asset.toUpperCase(),
60121
+ amount,
60122
+ type: transferType,
60123
+ fromSymbol: symbol,
60124
+ toSymbol: symbol
60125
+ });
60126
+ const balanceAfterTransfer = await getWalletBalance(this.client, asset);
60127
+ return {
60128
+ success: true,
60129
+ transactionId: transferResult.tranId?.toString(),
60130
+ asset,
60131
+ amount,
60132
+ fromWallet: "futures",
60133
+ toWallet: "spot",
60134
+ balanceAfterTransfer,
60135
+ timestamp: new Date().toISOString()
60136
+ };
60137
+ } catch (error) {
60138
+ console.error(`Error executing transfer for ${asset}:`, error);
60139
+ let currentBalance = 0;
60140
+ try {
60141
+ currentBalance = await getWalletBalance(this.client, asset);
60142
+ } catch (balanceError) {
60143
+ console.warn("Could not fetch balance for error response:", balanceError);
60144
+ }
60145
+ return {
60146
+ success: false,
60147
+ asset,
60148
+ amount,
60149
+ fromWallet: "futures",
60150
+ toWallet: "spot",
60151
+ balanceAfterTransfer: currentBalance,
60152
+ timestamp: new Date().toISOString(),
60153
+ error: `Transfer execution failed: ${error instanceof Error ? error.message : error}`
60154
+ };
60155
+ }
60156
+ }
59992
60157
  }
59993
60158
  function getPricePlaces(target) {
59994
60159
  const numStr = target.toString();
@@ -60314,6 +60479,11 @@ async function placeStopOrder2(client, payload) {
60314
60479
  stop: payload.final_stop,
60315
60480
  is_market: !payload.is_limit
60316
60481
  };
60482
+ if (payload.hedge) {
60483
+ let reverse_kind = payload.kind === "long" ? "short" : "long";
60484
+ order.kind = reverse_kind;
60485
+ order.is_market = false;
60486
+ }
60317
60487
  return createLimitPurchaseOrders(client, symbol, price_places, decimal_places, [order]);
60318
60488
  }
60319
60489
  async function getOpenOrders2(client, symbol, type) {
@@ -60710,6 +60880,168 @@ class BybitExchange extends BaseExchange {
60710
60880
  return getOpenOrders2(this.client, payload.symbol);
60711
60881
  }
60712
60882
  async placeBadStopEntry(payload) {}
60883
+ async getTransferableAmount(options) {
60884
+ const { asset, maxTransferLimit } = options;
60885
+ try {
60886
+ const unifiedBalance = await getWalletBalance2(this.client, asset);
60887
+ const allPositions = await this.client.getPositionInfo({
60888
+ category: "linear",
60889
+ settleCoin: asset
60890
+ });
60891
+ const activePositions = (allPositions.result.list || []).filter((pos) => Math.abs(parseFloat(pos.size || "0")) > 0);
60892
+ let totalMarginUsed = 0;
60893
+ let totalUnrealizedPnl = 0;
60894
+ for (const position2 of activePositions) {
60895
+ const positionSize = Math.abs(parseFloat(position2.size || "0"));
60896
+ const markPrice = parseFloat(position2.markPrice || "0");
60897
+ const leverage = parseFloat(position2.leverage || "1");
60898
+ const positionValue = positionSize * markPrice;
60899
+ const marginForPosition = positionValue / leverage;
60900
+ totalMarginUsed += marginForPosition;
60901
+ totalUnrealizedPnl += parseFloat(position2.unrealisedPnl || "0");
60902
+ }
60903
+ const safetyMarginPercent = 0.2;
60904
+ const requiredMargin = totalMarginUsed * (1 + safetyMarginPercent);
60905
+ const adjustedBalance = unifiedBalance + totalUnrealizedPnl;
60906
+ const availableForTransfer = Math.max(0, adjustedBalance - requiredMargin);
60907
+ let maxTransferableAmount = availableForTransfer;
60908
+ let appliedLimit;
60909
+ if (maxTransferLimit && maxTransferLimit > 0) {
60910
+ maxTransferableAmount = Math.min(availableForTransfer, maxTransferLimit);
60911
+ appliedLimit = maxTransferLimit;
60912
+ }
60913
+ const recommendedTransferAmount = maxTransferableAmount * 0.8;
60914
+ const marginUtilization = adjustedBalance > 0 ? requiredMargin / adjustedBalance * 100 : 0;
60915
+ return {
60916
+ asset,
60917
+ totalBalance: unifiedBalance,
60918
+ availableForTransfer,
60919
+ reservedForMargin: requiredMargin,
60920
+ maxTransferableAmount,
60921
+ appliedLimit,
60922
+ recommendedTransferAmount,
60923
+ marginUtilization,
60924
+ safetyMargin: safetyMarginPercent * 100
60925
+ };
60926
+ } catch (error) {
60927
+ console.error(`Error analyzing transferable amount for ${asset}:`, error);
60928
+ throw new Error(`Failed to analyze transferable funds: ${error instanceof Error ? error.message : error}`);
60929
+ }
60930
+ }
60931
+ async previewTransfer(options) {
60932
+ const { asset, amount } = options;
60933
+ const warnings = [];
60934
+ const errors = [];
60935
+ try {
60936
+ const analysis = await this.getTransferableAmount({ asset });
60937
+ let isValid2 = true;
60938
+ if (amount <= 0) {
60939
+ errors.push("Transfer amount must be greater than zero");
60940
+ isValid2 = false;
60941
+ }
60942
+ if (amount > analysis.maxTransferableAmount) {
60943
+ errors.push(`Transfer amount (${amount}) exceeds maximum transferable amount (${analysis.maxTransferableAmount})`);
60944
+ isValid2 = false;
60945
+ }
60946
+ if (amount > analysis.recommendedTransferAmount) {
60947
+ warnings.push(`Transfer amount exceeds recommended amount (${analysis.recommendedTransferAmount.toFixed(4)}). Consider transferring a smaller amount for safety.`);
60948
+ }
60949
+ if (analysis.marginUtilization > 70) {
60950
+ warnings.push(`High margin utilization (${analysis.marginUtilization.toFixed(1)}%). Transferring funds may increase liquidation risk.`);
60951
+ }
60952
+ const balanceAfterTransfer = analysis.totalBalance - amount;
60953
+ const marginRequirementAfterTransfer = analysis.reservedForMargin;
60954
+ if (isValid2 && balanceAfterTransfer < marginRequirementAfterTransfer) {
60955
+ errors.push("Transfer would result in insufficient margin for existing positions");
60956
+ isValid2 = false;
60957
+ }
60958
+ return {
60959
+ asset,
60960
+ requestedAmount: amount,
60961
+ isValid: isValid2,
60962
+ balanceAfterTransfer,
60963
+ marginRequirementAfterTransfer,
60964
+ warnings,
60965
+ errors
60966
+ };
60967
+ } catch (error) {
60968
+ console.error(`Error previewing transfer for ${asset}:`, error);
60969
+ return {
60970
+ asset,
60971
+ requestedAmount: amount,
60972
+ isValid: false,
60973
+ balanceAfterTransfer: 0,
60974
+ marginRequirementAfterTransfer: 0,
60975
+ warnings,
60976
+ errors: [
60977
+ `Failed to preview transfer: ${error instanceof Error ? error.message : error}`
60978
+ ]
60979
+ };
60980
+ }
60981
+ }
60982
+ async executeUnifiedToFundingTransfer(options) {
60983
+ const { asset, amount, confirm } = options;
60984
+ try {
60985
+ if (!confirm) {
60986
+ return {
60987
+ success: false,
60988
+ asset,
60989
+ amount,
60990
+ fromWallet: "unified",
60991
+ toWallet: "funding",
60992
+ balanceAfterTransfer: 0,
60993
+ timestamp: new Date().toISOString(),
60994
+ error: "Transfer not confirmed. Set confirm: true to execute transfer."
60995
+ };
60996
+ }
60997
+ const preview = await this.previewTransfer({ asset, amount });
60998
+ if (!preview.isValid) {
60999
+ return {
61000
+ success: false,
61001
+ asset,
61002
+ amount,
61003
+ fromWallet: "unified",
61004
+ toWallet: "funding",
61005
+ balanceAfterTransfer: 0,
61006
+ timestamp: new Date().toISOString(),
61007
+ error: `Transfer validation failed: ${preview.errors.join("; ")}`
61008
+ };
61009
+ }
61010
+ const transferResult = await this.client.createInternalTransfer(`bybit_transfer_${Date.now()}`, asset.toUpperCase(), amount.toString(), "UNIFIED", "FUND");
61011
+ if (transferResult.retCode !== 0) {
61012
+ throw new Error(`Bybit transfer failed: ${transferResult.retMsg} (code: ${transferResult.retCode})`);
61013
+ }
61014
+ const balanceAfterTransfer = await getWalletBalance2(this.client, asset);
61015
+ return {
61016
+ success: true,
61017
+ transactionId: transferResult.result?.transferId,
61018
+ asset,
61019
+ amount,
61020
+ fromWallet: "unified",
61021
+ toWallet: "funding",
61022
+ balanceAfterTransfer,
61023
+ timestamp: new Date().toISOString()
61024
+ };
61025
+ } catch (error) {
61026
+ console.error(`Error executing transfer for ${asset}:`, error);
61027
+ let currentBalance = 0;
61028
+ try {
61029
+ currentBalance = await getWalletBalance2(this.client, asset);
61030
+ } catch (balanceError) {
61031
+ console.warn("Could not fetch balance for error response:", balanceError);
61032
+ }
61033
+ return {
61034
+ success: false,
61035
+ asset,
61036
+ amount,
61037
+ fromWallet: "unified",
61038
+ toWallet: "funding",
61039
+ balanceAfterTransfer: currentBalance,
61040
+ timestamp: new Date().toISOString(),
61041
+ error: `Transfer execution failed: ${error instanceof Error ? error.message : error}`
61042
+ };
61043
+ }
61044
+ }
60713
61045
  }
60714
61046
 
60715
61047
  // src/helpers/accounts.ts