@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/index.cjs CHANGED
@@ -38677,20 +38677,20 @@ var require_axios2 = __commonJS((exports2, module2) => {
38677
38677
  var reduceDescriptors = (obj, reducer) => {
38678
38678
  const descriptors2 = Object.getOwnPropertyDescriptors(obj);
38679
38679
  const reducedDescriptors = {};
38680
- forEach2(descriptors2, (descriptor, name2) => {
38680
+ forEach2(descriptors2, (descriptor, name3) => {
38681
38681
  let ret;
38682
- if ((ret = reducer(descriptor, name2, obj)) !== false) {
38683
- reducedDescriptors[name2] = ret || descriptor;
38682
+ if ((ret = reducer(descriptor, name3, obj)) !== false) {
38683
+ reducedDescriptors[name3] = ret || descriptor;
38684
38684
  }
38685
38685
  });
38686
38686
  Object.defineProperties(obj, reducedDescriptors);
38687
38687
  };
38688
38688
  var freezeMethods = (obj) => {
38689
- reduceDescriptors(obj, (descriptor, name2) => {
38690
- if (isFunction(obj) && ["arguments", "caller", "callee"].indexOf(name2) !== -1) {
38689
+ reduceDescriptors(obj, (descriptor, name3) => {
38690
+ if (isFunction(obj) && ["arguments", "caller", "callee"].indexOf(name3) !== -1) {
38691
38691
  return false;
38692
38692
  }
38693
- const value2 = obj[name2];
38693
+ const value2 = obj[name3];
38694
38694
  if (!isFunction(value2))
38695
38695
  return;
38696
38696
  descriptor.enumerable = false;
@@ -38700,7 +38700,7 @@ var require_axios2 = __commonJS((exports2, module2) => {
38700
38700
  }
38701
38701
  if (!descriptor.set) {
38702
38702
  descriptor.set = () => {
38703
- throw Error("Can not rewrite read-only method '" + name2 + "'");
38703
+ throw Error("Can not rewrite read-only method '" + name3 + "'");
38704
38704
  };
38705
38705
  }
38706
38706
  });
@@ -39008,8 +39008,8 @@ var require_axios2 = __commonJS((exports2, module2) => {
39008
39008
  params && toFormData(params, this, options);
39009
39009
  }
39010
39010
  var prototype = AxiosURLSearchParams.prototype;
39011
- prototype.append = function append(name2, value2) {
39012
- this._pairs.push([name2, value2]);
39011
+ prototype.append = function append(name3, value2) {
39012
+ this._pairs.push([name3, value2]);
39013
39013
  };
39014
39014
  prototype.toString = function toString(encoder2) {
39015
39015
  const _encode = encoder2 ? function(value2) {
@@ -39145,8 +39145,8 @@ var require_axios2 = __commonJS((exports2, module2) => {
39145
39145
  }
39146
39146
  }, options));
39147
39147
  }
39148
- function parsePropPath(name2) {
39149
- return utils$1.matchAll(/\w+|\[(\w*)]/g, name2).map((match) => {
39148
+ function parsePropPath(name3) {
39149
+ return utils$1.matchAll(/\w+|\[(\w*)]/g, name3).map((match) => {
39150
39150
  return match[0] === "[]" ? "" : match[1] || match[0];
39151
39151
  });
39152
39152
  }
@@ -39164,33 +39164,33 @@ var require_axios2 = __commonJS((exports2, module2) => {
39164
39164
  }
39165
39165
  function formDataToJSON(formData) {
39166
39166
  function buildPath(path, value2, target, index) {
39167
- let name2 = path[index++];
39168
- if (name2 === "__proto__")
39167
+ let name3 = path[index++];
39168
+ if (name3 === "__proto__")
39169
39169
  return true;
39170
- const isNumericKey = Number.isFinite(+name2);
39170
+ const isNumericKey = Number.isFinite(+name3);
39171
39171
  const isLast = index >= path.length;
39172
- name2 = !name2 && utils$1.isArray(target) ? target.length : name2;
39172
+ name3 = !name3 && utils$1.isArray(target) ? target.length : name3;
39173
39173
  if (isLast) {
39174
- if (utils$1.hasOwnProp(target, name2)) {
39175
- target[name2] = [target[name2], value2];
39174
+ if (utils$1.hasOwnProp(target, name3)) {
39175
+ target[name3] = [target[name3], value2];
39176
39176
  } else {
39177
- target[name2] = value2;
39177
+ target[name3] = value2;
39178
39178
  }
39179
39179
  return !isNumericKey;
39180
39180
  }
39181
- if (!target[name2] || !utils$1.isObject(target[name2])) {
39182
- target[name2] = [];
39181
+ if (!target[name3] || !utils$1.isObject(target[name3])) {
39182
+ target[name3] = [];
39183
39183
  }
39184
- const result = buildPath(path, value2, target[name2], index);
39185
- if (result && utils$1.isArray(target[name2])) {
39186
- target[name2] = arrayToObject(target[name2]);
39184
+ const result = buildPath(path, value2, target[name3], index);
39185
+ if (result && utils$1.isArray(target[name3])) {
39186
+ target[name3] = arrayToObject(target[name3]);
39187
39187
  }
39188
39188
  return !isNumericKey;
39189
39189
  }
39190
39190
  if (utils$1.isFormData(formData) && utils$1.isFunction(formData.entries)) {
39191
39191
  const obj = {};
39192
- utils$1.forEachEntry(formData, (name2, value2) => {
39193
- buildPath(parsePropPath(name2), value2, obj, 0);
39192
+ utils$1.forEachEntry(formData, (name3, value2) => {
39193
+ buildPath(parsePropPath(name3), value2, obj, 0);
39194
39194
  });
39195
39195
  return obj;
39196
39196
  }
@@ -39769,10 +39769,10 @@ var require_axios2 = __commonJS((exports2, module2) => {
39769
39769
  var CRLF_BYTES_COUNT = 2;
39770
39770
 
39771
39771
  class FormDataPart {
39772
- constructor(name2, value2) {
39772
+ constructor(name3, value2) {
39773
39773
  const { escapeName } = this.constructor;
39774
39774
  const isStringValue = utils$1.isString(value2);
39775
- let headers = `Content-Disposition: form-data; name="${escapeName(name2)}"${!isStringValue && value2.name ? `; filename="${escapeName(value2.name)}"` : ""}${CRLF}`;
39775
+ let headers = `Content-Disposition: form-data; name="${escapeName(name3)}"${!isStringValue && value2.name ? `; filename="${escapeName(value2.name)}"` : ""}${CRLF}`;
39776
39776
  if (isStringValue) {
39777
39777
  value2 = textEncoder.encode(String(value2).replace(/\r?\n|\r\n?/g, CRLF));
39778
39778
  } else {
@@ -39781,7 +39781,7 @@ var require_axios2 = __commonJS((exports2, module2) => {
39781
39781
  this.headers = textEncoder.encode(headers + CRLF);
39782
39782
  this.contentLength = isStringValue ? value2.byteLength : value2.size;
39783
39783
  this.size = this.headers.byteLength + this.contentLength + CRLF_BYTES_COUNT;
39784
- this.name = name2;
39784
+ this.name = name3;
39785
39785
  this.value = value2;
39786
39786
  }
39787
39787
  async* encode() {
@@ -39794,8 +39794,8 @@ var require_axios2 = __commonJS((exports2, module2) => {
39794
39794
  }
39795
39795
  yield CRLF_BYTES;
39796
39796
  }
39797
- static escapeName(name2) {
39798
- return String(name2).replace(/[\r\n"]/g, (match) => ({
39797
+ static escapeName(name3) {
39798
+ return String(name3).replace(/[\r\n"]/g, (match) => ({
39799
39799
  "\r": "%0D",
39800
39800
  "\n": "%0A",
39801
39801
  '"': "%22"
@@ -39817,8 +39817,8 @@ var require_axios2 = __commonJS((exports2, module2) => {
39817
39817
  const boundaryBytes = textEncoder.encode("--" + boundary + CRLF);
39818
39818
  const footerBytes = textEncoder.encode("--" + boundary + "--" + CRLF + CRLF);
39819
39819
  let contentLength = footerBytes.byteLength;
39820
- const parts = Array.from(form.entries()).map(([name2, value2]) => {
39821
- const part = new FormDataPart(name2, value2);
39820
+ const parts = Array.from(form.entries()).map(([name3, value2]) => {
39821
+ const part = new FormDataPart(name3, value2);
39822
39822
  contentLength += part.size;
39823
39823
  return part;
39824
39824
  });
@@ -40426,20 +40426,20 @@ var require_axios2 = __commonJS((exports2, module2) => {
40426
40426
  return origin2.protocol === url2.protocol && origin2.host === url2.host && (isMSIE || origin2.port === url2.port);
40427
40427
  })(new URL(platform.origin), platform.navigator && /(msie|trident)/i.test(platform.navigator.userAgent)) : () => true;
40428
40428
  var cookies = platform.hasStandardBrowserEnv ? {
40429
- write(name2, value2, expires, path, domain, secure) {
40430
- const cookie = [name2 + "=" + encodeURIComponent(value2)];
40429
+ write(name3, value2, expires, path, domain, secure) {
40430
+ const cookie = [name3 + "=" + encodeURIComponent(value2)];
40431
40431
  utils$1.isNumber(expires) && cookie.push("expires=" + new Date(expires).toGMTString());
40432
40432
  utils$1.isString(path) && cookie.push("path=" + path);
40433
40433
  utils$1.isString(domain) && cookie.push("domain=" + domain);
40434
40434
  secure === true && cookie.push("secure");
40435
40435
  document.cookie = cookie.join("; ");
40436
40436
  },
40437
- read(name2) {
40438
- const match = document.cookie.match(new RegExp("(^|;\\s*)(" + name2 + ")=([^;]*)"));
40437
+ read(name3) {
40438
+ const match = document.cookie.match(new RegExp("(^|;\\s*)(" + name3 + ")=([^;]*)"));
40439
40439
  return match ? decodeURIComponent(match[3]) : null;
40440
40440
  },
40441
- remove(name2) {
40442
- this.write(name2, "", Date.now() - 86400000);
40441
+ remove(name3) {
40442
+ this.write(name3, "", Date.now() - 86400000);
40443
40443
  }
40444
40444
  } : {
40445
40445
  write() {},
@@ -44876,6 +44876,7 @@ var require_lib3 = __commonJS((exports2) => {
44876
44876
  var exports_src = {};
44877
44877
  __export(exports_src, {
44878
44878
  sortedBuildConfig: () => sortedBuildConfig,
44879
+ name: () => name2,
44879
44880
  initialize: () => initialize,
44880
44881
  initApp: () => initApp,
44881
44882
  get_app_config_and_max_size: () => get_app_config_and_max_size,
@@ -54801,35 +54802,6 @@ class AppDatabase {
54801
54802
  }
54802
54803
  return null;
54803
54804
  }
54804
- async getRunningInstanceFromDB(account, symbol, options) {
54805
- const { delay = 60 * 1000 } = options || {
54806
- delay: 60 * 1000
54807
- };
54808
- const running_instance = await this.pb.collection("trade_block_tracking").getFirstListItem(`account.owner = "${account.owner}" && account.exchange = "${account.exchange}" && symbol = "${symbol}"`, {
54809
- expand: "account"
54810
- });
54811
- if (!running_instance) {
54812
- let account_instance = await this.pb.collection("exchange_accounts").getFirstListItem(`owner = "${account.owner}" && exchange = "${account.exchange}"`);
54813
- return await this.pb.collection("trade_block_tracking").create({
54814
- account: account_instance.id,
54815
- symbol,
54816
- running: false
54817
- });
54818
- }
54819
- const updatedAt = new Date(running_instance.updated);
54820
- const now = new Date;
54821
- const diffInMinutes = (now.getTime() - updatedAt.getTime()) / delay;
54822
- if (diffInMinutes >= 1) {
54823
- await this.updateRunningInstance(running_instance.id, false);
54824
- running_instance.running = false;
54825
- }
54826
- return running_instance;
54827
- }
54828
- async updateRunningInstance(id, running) {
54829
- return await this.pb.collection("trade_block_tracking").update(id, {
54830
- running
54831
- });
54832
- }
54833
54805
  async getOrders(account, options) {
54834
54806
  const { symbol, kind } = options;
54835
54807
  const db_orders = await this.pb.collection("orders").getFullList({
@@ -55140,110 +55112,6 @@ class AppDatabase {
55140
55112
  }
55141
55113
  return null;
55142
55114
  }
55143
- async getBotViewInstance(payload) {
55144
- const { asset, main_account } = payload;
55145
- const bot_instances = await this.pb.collection("bot_view").getFullList({
55146
- filter: `asset:lower="${asset.toLowerCase()}" && main_account.owner:lower="${main_account.owner.toLowerCase()}" && main_account.exchange:lower="${main_account.exchange.toLowerCase()}"`,
55147
- expand: "main_account,secondary_account,main_long_strategy,main_short_strategy,secondary_long_strategy,secondary_short_strategy"
55148
- });
55149
- if (bot_instances.length > 0) {
55150
- const instance = bot_instances[0];
55151
- const {
55152
- main_account: main_account2,
55153
- secondary_account,
55154
- main_long_strategy,
55155
- main_short_strategy,
55156
- secondary_long_strategy,
55157
- secondary_short_strategy
55158
- } = instance.expand;
55159
- const update_boolean = (value) => {
55160
- if (!value) {
55161
- return value;
55162
- }
55163
- return {
55164
- ...value,
55165
- follow: Boolean(value.follow),
55166
- place_tp: Boolean(value.place_tp),
55167
- pause_tp: Boolean(value.pause_tp)
55168
- };
55169
- };
55170
- return {
55171
- ...instance,
55172
- main: {
55173
- account: main_account2,
55174
- symbol: instance.main_symbol,
55175
- strategy: {
55176
- long: main_long_strategy,
55177
- short: main_short_strategy
55178
- },
55179
- position: {
55180
- long: instance.main_long_position,
55181
- short: instance.main_short_position
55182
- },
55183
- config: {
55184
- long: update_boolean(instance.main_long_config),
55185
- short: update_boolean(instance.main_short_config)
55186
- }
55187
- },
55188
- secondary: {
55189
- account: secondary_account,
55190
- symbol: instance.secondary_symbol,
55191
- strategy: {
55192
- long: secondary_long_strategy,
55193
- short: secondary_short_strategy
55194
- },
55195
- position: {
55196
- long: instance.secondary_long_position,
55197
- short: instance.secondary_short_position
55198
- },
55199
- config: {
55200
- long: update_boolean(instance.secondary_long_config),
55201
- short: update_boolean(instance.secondary_short_config)
55202
- }
55203
- }
55204
- };
55205
- }
55206
- return null;
55207
- }
55208
- async getBotInstance(payload) {
55209
- const { asset, main_account } = payload;
55210
- const bot_instances = await this.pb.collection("bot_instances").getFullList({
55211
- filter: `asset:lower="${asset.toLowerCase()}" && main_account.owner:lower="${main_account.owner.toLowerCase()}" && main_account.exchange:lower="${main_account.exchange.toLowerCase()}"`
55212
- });
55213
- if (bot_instances.length > 0) {
55214
- return bot_instances[0];
55215
- }
55216
- return null;
55217
- }
55218
- async getBotState(payload) {
55219
- const { asset, main_account, running } = payload;
55220
- 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()}"`;
55221
- if (running !== undefined) {
55222
- filter += ` && running=${running}`;
55223
- }
55224
- const bot_states = await this.pb.collection("bot_states").getFullList({
55225
- filter
55226
- });
55227
- return bot_states;
55228
- }
55229
- async getBotOrderHistories(payload) {
55230
- const { asset, main_account, symbol, kind, type } = payload;
55231
- 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()}"`;
55232
- if (symbol) {
55233
- filter += ` && symbol:lower="${symbol.toLowerCase()}"`;
55234
- }
55235
- if (kind) {
55236
- filter += ` && kind="${kind}"`;
55237
- }
55238
- if (type) {
55239
- filter += ` && type="${type}"`;
55240
- }
55241
- const bot_order_histories = await this.pb.collection("bot_order_history").getFullList({
55242
- filter,
55243
- sort: "-created"
55244
- });
55245
- return bot_order_histories;
55246
- }
55247
55115
  async createOrUpdateWindingDownMarket(payload) {
55248
55116
  const { symbol, risk_reward = 30 } = payload;
55249
55117
  const existing_winding_down_market = await this.pb.collection("winding_down_markets").getFullList({
@@ -58714,6 +58582,8 @@ class Strategy {
58714
58582
  };
58715
58583
  }
58716
58584
  }
58585
+ // src/helpers/compound.ts
58586
+ var name2 = "";
58717
58587
  // src/types/index.ts
58718
58588
  class BaseExchange {
58719
58589
  client;
@@ -60051,6 +59921,171 @@ class BinanceExchange extends BaseExchange {
60051
59921
  async forceClosePosition(symbol, options) {
60052
59922
  return await forceClosePosition(this.client, symbol, options);
60053
59923
  }
59924
+ async getTransferableAmount(options) {
59925
+ const { asset, maxTransferLimit } = options;
59926
+ try {
59927
+ const futuresBalance = await getWalletBalance(this.client, asset);
59928
+ const allPositions = await this.client.getPositionsV3();
59929
+ const activePositions = allPositions.filter((pos) => Math.abs(pos.positionAmt) > 0);
59930
+ let totalMarginUsed = 0;
59931
+ let totalUnrealizedPnl = 0;
59932
+ for (const position2 of activePositions) {
59933
+ const positionValue = Math.abs(position2.positionAmt) * position2.markPrice;
59934
+ const leverage = await getLeverage(this.client, position2.symbol);
59935
+ const marginForPosition = positionValue / (leverage || 1);
59936
+ console.log({ leverage });
59937
+ totalMarginUsed += marginForPosition;
59938
+ totalUnrealizedPnl += position2.unRealizedProfit || 0;
59939
+ }
59940
+ const safetyMarginPercent = 0.2;
59941
+ const requiredMargin = totalMarginUsed * (1 + safetyMarginPercent);
59942
+ const adjustedBalance = futuresBalance + totalUnrealizedPnl;
59943
+ const availableForTransfer = Math.max(0, adjustedBalance - requiredMargin);
59944
+ let maxTransferableAmount = availableForTransfer;
59945
+ let appliedLimit;
59946
+ if (maxTransferLimit && maxTransferLimit > 0) {
59947
+ maxTransferableAmount = Math.min(availableForTransfer, maxTransferLimit);
59948
+ appliedLimit = maxTransferLimit;
59949
+ }
59950
+ const recommendedTransferAmount = maxTransferableAmount * 0.8;
59951
+ const marginUtilization = adjustedBalance > 0 ? requiredMargin / adjustedBalance * 100 : 0;
59952
+ return {
59953
+ asset,
59954
+ totalBalance: futuresBalance,
59955
+ availableForTransfer,
59956
+ reservedForMargin: requiredMargin,
59957
+ maxTransferableAmount,
59958
+ appliedLimit,
59959
+ recommendedTransferAmount,
59960
+ marginUtilization,
59961
+ safetyMargin: safetyMarginPercent * 100
59962
+ };
59963
+ } catch (error) {
59964
+ console.error(`Error analyzing transferable amount for ${asset}:`, error);
59965
+ throw new Error(`Failed to analyze transferable funds: ${error instanceof Error ? error.message : error}`);
59966
+ }
59967
+ }
59968
+ async previewTransfer(options) {
59969
+ const { asset, amount } = options;
59970
+ const warnings = [];
59971
+ const errors = [];
59972
+ try {
59973
+ const analysis = await this.getTransferableAmount({ asset });
59974
+ let isValid2 = true;
59975
+ if (amount <= 0) {
59976
+ errors.push("Transfer amount must be greater than zero");
59977
+ isValid2 = false;
59978
+ }
59979
+ if (amount > analysis.maxTransferableAmount) {
59980
+ errors.push(`Transfer amount (${amount}) exceeds maximum transferable amount (${analysis.maxTransferableAmount})`);
59981
+ isValid2 = false;
59982
+ }
59983
+ if (amount > analysis.recommendedTransferAmount) {
59984
+ warnings.push(`Transfer amount exceeds recommended amount (${analysis.recommendedTransferAmount.toFixed(4)}). Consider transferring a smaller amount for safety.`);
59985
+ }
59986
+ if (analysis.marginUtilization > 70) {
59987
+ warnings.push(`High margin utilization (${analysis.marginUtilization.toFixed(1)}%). Transferring funds may increase liquidation risk.`);
59988
+ }
59989
+ const balanceAfterTransfer = analysis.totalBalance - amount;
59990
+ const marginRequirementAfterTransfer = analysis.reservedForMargin;
59991
+ if (isValid2 && balanceAfterTransfer < marginRequirementAfterTransfer) {
59992
+ errors.push("Transfer would result in insufficient margin for existing positions");
59993
+ isValid2 = false;
59994
+ }
59995
+ return {
59996
+ asset,
59997
+ requestedAmount: amount,
59998
+ isValid: isValid2,
59999
+ balanceAfterTransfer,
60000
+ marginRequirementAfterTransfer,
60001
+ warnings,
60002
+ errors
60003
+ };
60004
+ } catch (error) {
60005
+ console.error(`Error previewing transfer for ${asset}:`, error);
60006
+ return {
60007
+ asset,
60008
+ requestedAmount: amount,
60009
+ isValid: false,
60010
+ balanceAfterTransfer: 0,
60011
+ marginRequirementAfterTransfer: 0,
60012
+ warnings,
60013
+ errors: [`Failed to preview transfer: ${error instanceof Error ? error.message : error}`]
60014
+ };
60015
+ }
60016
+ }
60017
+ async executeFutureToSpotTransfer(options) {
60018
+ const { asset, amount, confirm, symbol = "BTCUSDT" } = options;
60019
+ try {
60020
+ if (!confirm) {
60021
+ return {
60022
+ success: false,
60023
+ asset,
60024
+ amount,
60025
+ fromWallet: "futures",
60026
+ toWallet: "spot",
60027
+ balanceAfterTransfer: 0,
60028
+ timestamp: new Date().toISOString(),
60029
+ error: "Transfer not confirmed. Set confirm: true to execute transfer."
60030
+ };
60031
+ }
60032
+ const preview = await this.previewTransfer({ asset, amount });
60033
+ if (!preview.isValid) {
60034
+ return {
60035
+ success: false,
60036
+ asset,
60037
+ amount,
60038
+ fromWallet: "futures",
60039
+ toWallet: "spot",
60040
+ balanceAfterTransfer: 0,
60041
+ timestamp: new Date().toISOString(),
60042
+ error: `Transfer validation failed: ${preview.errors.join("; ")}`
60043
+ };
60044
+ }
60045
+ const is_coin = !["USDT", "USDC", "BUSD"].includes(asset.toUpperCase());
60046
+ const transferType = is_coin ? CONSTANTS.COIN_FUTURE_TO_SPOT : CONSTANTS.USDT_FUTURE_TO_SPOT;
60047
+ if (!this.main_client) {
60048
+ throw new Error("Main client not available for transfers");
60049
+ }
60050
+ const transferClient = this.main_client;
60051
+ const transferResult = await transferClient.submitUniversalTransfer({
60052
+ asset: asset.toUpperCase(),
60053
+ amount,
60054
+ type: transferType,
60055
+ fromSymbol: symbol,
60056
+ toSymbol: symbol
60057
+ });
60058
+ const balanceAfterTransfer = await getWalletBalance(this.client, asset);
60059
+ return {
60060
+ success: true,
60061
+ transactionId: transferResult.tranId?.toString(),
60062
+ asset,
60063
+ amount,
60064
+ fromWallet: "futures",
60065
+ toWallet: "spot",
60066
+ balanceAfterTransfer,
60067
+ timestamp: new Date().toISOString()
60068
+ };
60069
+ } catch (error) {
60070
+ console.error(`Error executing transfer for ${asset}:`, error);
60071
+ let currentBalance = 0;
60072
+ try {
60073
+ currentBalance = await getWalletBalance(this.client, asset);
60074
+ } catch (balanceError) {
60075
+ console.warn("Could not fetch balance for error response:", balanceError);
60076
+ }
60077
+ return {
60078
+ success: false,
60079
+ asset,
60080
+ amount,
60081
+ fromWallet: "futures",
60082
+ toWallet: "spot",
60083
+ balanceAfterTransfer: currentBalance,
60084
+ timestamp: new Date().toISOString(),
60085
+ error: `Transfer execution failed: ${error instanceof Error ? error.message : error}`
60086
+ };
60087
+ }
60088
+ }
60054
60089
  }
60055
60090
  function getPricePlaces(target) {
60056
60091
  const numStr = target.toString();
@@ -60376,6 +60411,11 @@ async function placeStopOrder2(client, payload) {
60376
60411
  stop: payload.final_stop,
60377
60412
  is_market: !payload.is_limit
60378
60413
  };
60414
+ if (payload.hedge) {
60415
+ let reverse_kind = payload.kind === "long" ? "short" : "long";
60416
+ order.kind = reverse_kind;
60417
+ order.is_market = false;
60418
+ }
60379
60419
  return createLimitPurchaseOrders(client, symbol, price_places, decimal_places, [order]);
60380
60420
  }
60381
60421
  async function getOpenOrders2(client, symbol, type) {
@@ -60772,6 +60812,168 @@ class BybitExchange extends BaseExchange {
60772
60812
  return getOpenOrders2(this.client, payload.symbol);
60773
60813
  }
60774
60814
  async placeBadStopEntry(payload) {}
60815
+ async getTransferableAmount(options) {
60816
+ const { asset, maxTransferLimit } = options;
60817
+ try {
60818
+ const unifiedBalance = await getWalletBalance2(this.client, asset);
60819
+ const allPositions = await this.client.getPositionInfo({
60820
+ category: "linear",
60821
+ settleCoin: asset
60822
+ });
60823
+ const activePositions = (allPositions.result.list || []).filter((pos) => Math.abs(parseFloat(pos.size || "0")) > 0);
60824
+ let totalMarginUsed = 0;
60825
+ let totalUnrealizedPnl = 0;
60826
+ for (const position2 of activePositions) {
60827
+ const positionSize = Math.abs(parseFloat(position2.size || "0"));
60828
+ const markPrice = parseFloat(position2.markPrice || "0");
60829
+ const leverage = parseFloat(position2.leverage || "1");
60830
+ const positionValue = positionSize * markPrice;
60831
+ const marginForPosition = positionValue / leverage;
60832
+ totalMarginUsed += marginForPosition;
60833
+ totalUnrealizedPnl += parseFloat(position2.unrealisedPnl || "0");
60834
+ }
60835
+ const safetyMarginPercent = 0.2;
60836
+ const requiredMargin = totalMarginUsed * (1 + safetyMarginPercent);
60837
+ const adjustedBalance = unifiedBalance + totalUnrealizedPnl;
60838
+ const availableForTransfer = Math.max(0, adjustedBalance - requiredMargin);
60839
+ let maxTransferableAmount = availableForTransfer;
60840
+ let appliedLimit;
60841
+ if (maxTransferLimit && maxTransferLimit > 0) {
60842
+ maxTransferableAmount = Math.min(availableForTransfer, maxTransferLimit);
60843
+ appliedLimit = maxTransferLimit;
60844
+ }
60845
+ const recommendedTransferAmount = maxTransferableAmount * 0.8;
60846
+ const marginUtilization = adjustedBalance > 0 ? requiredMargin / adjustedBalance * 100 : 0;
60847
+ return {
60848
+ asset,
60849
+ totalBalance: unifiedBalance,
60850
+ availableForTransfer,
60851
+ reservedForMargin: requiredMargin,
60852
+ maxTransferableAmount,
60853
+ appliedLimit,
60854
+ recommendedTransferAmount,
60855
+ marginUtilization,
60856
+ safetyMargin: safetyMarginPercent * 100
60857
+ };
60858
+ } catch (error) {
60859
+ console.error(`Error analyzing transferable amount for ${asset}:`, error);
60860
+ throw new Error(`Failed to analyze transferable funds: ${error instanceof Error ? error.message : error}`);
60861
+ }
60862
+ }
60863
+ async previewTransfer(options) {
60864
+ const { asset, amount } = options;
60865
+ const warnings = [];
60866
+ const errors = [];
60867
+ try {
60868
+ const analysis = await this.getTransferableAmount({ asset });
60869
+ let isValid2 = true;
60870
+ if (amount <= 0) {
60871
+ errors.push("Transfer amount must be greater than zero");
60872
+ isValid2 = false;
60873
+ }
60874
+ if (amount > analysis.maxTransferableAmount) {
60875
+ errors.push(`Transfer amount (${amount}) exceeds maximum transferable amount (${analysis.maxTransferableAmount})`);
60876
+ isValid2 = false;
60877
+ }
60878
+ if (amount > analysis.recommendedTransferAmount) {
60879
+ warnings.push(`Transfer amount exceeds recommended amount (${analysis.recommendedTransferAmount.toFixed(4)}). Consider transferring a smaller amount for safety.`);
60880
+ }
60881
+ if (analysis.marginUtilization > 70) {
60882
+ warnings.push(`High margin utilization (${analysis.marginUtilization.toFixed(1)}%). Transferring funds may increase liquidation risk.`);
60883
+ }
60884
+ const balanceAfterTransfer = analysis.totalBalance - amount;
60885
+ const marginRequirementAfterTransfer = analysis.reservedForMargin;
60886
+ if (isValid2 && balanceAfterTransfer < marginRequirementAfterTransfer) {
60887
+ errors.push("Transfer would result in insufficient margin for existing positions");
60888
+ isValid2 = false;
60889
+ }
60890
+ return {
60891
+ asset,
60892
+ requestedAmount: amount,
60893
+ isValid: isValid2,
60894
+ balanceAfterTransfer,
60895
+ marginRequirementAfterTransfer,
60896
+ warnings,
60897
+ errors
60898
+ };
60899
+ } catch (error) {
60900
+ console.error(`Error previewing transfer for ${asset}:`, error);
60901
+ return {
60902
+ asset,
60903
+ requestedAmount: amount,
60904
+ isValid: false,
60905
+ balanceAfterTransfer: 0,
60906
+ marginRequirementAfterTransfer: 0,
60907
+ warnings,
60908
+ errors: [
60909
+ `Failed to preview transfer: ${error instanceof Error ? error.message : error}`
60910
+ ]
60911
+ };
60912
+ }
60913
+ }
60914
+ async executeUnifiedToFundingTransfer(options) {
60915
+ const { asset, amount, confirm } = options;
60916
+ try {
60917
+ if (!confirm) {
60918
+ return {
60919
+ success: false,
60920
+ asset,
60921
+ amount,
60922
+ fromWallet: "unified",
60923
+ toWallet: "funding",
60924
+ balanceAfterTransfer: 0,
60925
+ timestamp: new Date().toISOString(),
60926
+ error: "Transfer not confirmed. Set confirm: true to execute transfer."
60927
+ };
60928
+ }
60929
+ const preview = await this.previewTransfer({ asset, amount });
60930
+ if (!preview.isValid) {
60931
+ return {
60932
+ success: false,
60933
+ asset,
60934
+ amount,
60935
+ fromWallet: "unified",
60936
+ toWallet: "funding",
60937
+ balanceAfterTransfer: 0,
60938
+ timestamp: new Date().toISOString(),
60939
+ error: `Transfer validation failed: ${preview.errors.join("; ")}`
60940
+ };
60941
+ }
60942
+ const transferResult = await this.client.createInternalTransfer(`bybit_transfer_${Date.now()}`, asset.toUpperCase(), amount.toString(), "UNIFIED", "FUND");
60943
+ if (transferResult.retCode !== 0) {
60944
+ throw new Error(`Bybit transfer failed: ${transferResult.retMsg} (code: ${transferResult.retCode})`);
60945
+ }
60946
+ const balanceAfterTransfer = await getWalletBalance2(this.client, asset);
60947
+ return {
60948
+ success: true,
60949
+ transactionId: transferResult.result?.transferId,
60950
+ asset,
60951
+ amount,
60952
+ fromWallet: "unified",
60953
+ toWallet: "funding",
60954
+ balanceAfterTransfer,
60955
+ timestamp: new Date().toISOString()
60956
+ };
60957
+ } catch (error) {
60958
+ console.error(`Error executing transfer for ${asset}:`, error);
60959
+ let currentBalance = 0;
60960
+ try {
60961
+ currentBalance = await getWalletBalance2(this.client, asset);
60962
+ } catch (balanceError) {
60963
+ console.warn("Could not fetch balance for error response:", balanceError);
60964
+ }
60965
+ return {
60966
+ success: false,
60967
+ asset,
60968
+ amount,
60969
+ fromWallet: "unified",
60970
+ toWallet: "funding",
60971
+ balanceAfterTransfer: currentBalance,
60972
+ timestamp: new Date().toISOString(),
60973
+ error: `Transfer execution failed: ${error instanceof Error ? error.message : error}`
60974
+ };
60975
+ }
60976
+ }
60775
60977
  }
60776
60978
 
60777
60979
  // src/helpers/accounts.ts
@@ -62480,9 +62682,6 @@ class ExchangeAccount {
62480
62682
  }
62481
62683
  return db_positions;
62482
62684
  }
62483
- async getRunningInstanceFromDB(symbol) {
62484
- return await this.app_db.getRunningInstanceFromDB(this.instance, symbol);
62485
- }
62486
62685
  async syncOrders(options) {
62487
62686
  const { symbol, update = false, kind } = options;
62488
62687
  if (!update && kind) {
@@ -64131,22 +64330,11 @@ class App {
64131
64330
  }
64132
64331
  async syncOrders(payload) {
64133
64332
  const exchange_account = await this.getExchangeAccount(payload.account);
64134
- const db_running_instance = await exchange_account.getRunningInstanceFromDB(payload.symbol);
64135
- if (db_running_instance.running) {
64136
- return {
64137
- new_config: null,
64138
- position: null,
64139
- config: null,
64140
- error: "Already running"
64141
- };
64142
- }
64143
- await this.app_db.updateRunningInstance(db_running_instance.id, true);
64144
64333
  await exchange_account.syncAccount({
64145
64334
  symbol: payload.symbol,
64146
64335
  kind: payload.kind,
64147
64336
  update: true
64148
64337
  });
64149
- await this.app_db.updateRunningInstance(db_running_instance.id, false);
64150
64338
  return true;
64151
64339
  }
64152
64340
  async cancelOrders(payload) {