@kodiak-finance/orderly-hooks 2.9.2 → 2.9.3

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.mjs CHANGED
@@ -7458,6 +7458,7 @@ var useLeverageBySymbol = (symbol, marginMode) => {
7458
7458
  function useMaxQty(symbol, side, reduceOnlyOrOptions, marginMode) {
7459
7459
  const reduceOnly = typeof reduceOnlyOrOptions === "object" && reduceOnlyOrOptions !== null ? reduceOnlyOrOptions.reduceOnly ?? false : reduceOnlyOrOptions ?? false;
7460
7460
  const finalMarginMode = typeof reduceOnlyOrOptions === "object" && reduceOnlyOrOptions !== null ? reduceOnlyOrOptions.marginMode ?? MarginMode.CROSS : marginMode ?? MarginMode.CROSS;
7461
+ const currentOrderReferencePrice = typeof reduceOnlyOrOptions === "object" && reduceOnlyOrOptions !== null && typeof reduceOnlyOrOptions.currentOrderReferencePrice === "number" && reduceOnlyOrOptions.currentOrderReferencePrice > 0 ? reduceOnlyOrOptions.currentOrderReferencePrice : void 0;
7461
7462
  const positions3 = usePositions();
7462
7463
  const accountInfo = useAccountInfo();
7463
7464
  const symbolInfo = useSymbolsInfo();
@@ -7498,18 +7499,18 @@ function useMaxQty(symbol, side, reduceOnlyOrOptions, marginMode) {
7498
7499
  const pendingLongOrders = buyOrdersQty > 0 ? [{ referencePrice: markPrice, quantity: buyOrdersQty }] : [];
7499
7500
  const pendingSellOrders = sellOrdersQty > 0 ? [{ referencePrice: markPrice, quantity: sellOrdersQty }] : [];
7500
7501
  const markPriceDecimal = new Decimal(markPrice);
7501
- const leverageDecimal = new Decimal(leverage);
7502
- const isoOrderFrozenLong = buyOrdersQty > 0 ? markPriceDecimal.mul(buyOrdersQty).div(leverageDecimal).toNumber() : 0;
7503
- const isoOrderFrozenShort = sellOrdersQty > 0 ? markPriceDecimal.mul(sellOrdersQty).div(leverageDecimal).toNumber() : 0;
7502
+ const marginRate = account.isolatedMarginRate({ leverage });
7503
+ const isoOrderFrozenLong = buyOrdersQty > 0 ? markPriceDecimal.mul(buyOrdersQty).mul(marginRate).toNumber() : 0;
7504
+ const isoOrderFrozenShort = sellOrdersQty > 0 ? markPriceDecimal.mul(sellOrdersQty).mul(marginRate).toNumber() : 0;
7504
7505
  const symbolMaxNotional = accountInfo.max_notional?.[symbol] ?? positions.maxPositionNotional({
7505
7506
  leverage,
7506
7507
  IMRFactor: IMR_Factor
7507
7508
  });
7508
- const currentOrderReferencePrice = typeof reduceOnlyOrOptions === "object" && reduceOnlyOrOptions !== null && typeof reduceOnlyOrOptions.currentOrderReferencePrice === "number" && reduceOnlyOrOptions.currentOrderReferencePrice > 0 ? reduceOnlyOrOptions.currentOrderReferencePrice : markPrice;
7509
+ const effectiveOrderReferencePrice = currentOrderReferencePrice ?? markPrice;
7509
7510
  return account.maxQtyForIsolatedMargin({
7510
7511
  symbol,
7511
7512
  orderSide: side,
7512
- currentOrderReferencePrice,
7513
+ currentOrderReferencePrice: effectiveOrderReferencePrice,
7513
7514
  availableBalance,
7514
7515
  leverage,
7515
7516
  baseIMR,
@@ -7552,8 +7553,10 @@ function useMaxQty(symbol, side, reduceOnlyOrOptions, marginMode) {
7552
7553
  symbolInfo,
7553
7554
  side,
7554
7555
  totalCollateral,
7556
+ freeCollateralUSDCOnly,
7555
7557
  finalMarginMode,
7556
- symbolLeverage
7558
+ symbolLeverage,
7559
+ currentOrderReferencePrice
7557
7560
  ]);
7558
7561
  return Math.max(maxQty, 0);
7559
7562
  }
@@ -12852,15 +12855,17 @@ var BackgroundPaint = class extends BasePaint {
12852
12855
  );
12853
12856
  }
12854
12857
  async _drawImage(options) {
12858
+ const width = this.painter.width * this.painter.ratio;
12859
+ const height = this.painter.height * this.painter.ratio;
12855
12860
  return this.loadImg(options.backgroundImg).then((img) => {
12856
12861
  this.img = img;
12857
- this.ctx.drawImage(
12858
- this.img,
12859
- 0,
12860
- 0,
12861
- this.painter.width * this.painter.ratio,
12862
- this.painter.height * this.painter.ratio
12863
- );
12862
+ this.ctx.save();
12863
+ if (options.direction === "rtl") {
12864
+ this.ctx.translate(width, 0);
12865
+ this.ctx.scale(-1, 1);
12866
+ }
12867
+ this.ctx.drawImage(this.img, 0, 0, width, height);
12868
+ this.ctx.restore();
12864
12869
  });
12865
12870
  }
12866
12871
  loadImg(url) {
@@ -12923,6 +12928,7 @@ var DataPaint = class extends BasePaint {
12923
12928
  this.BROKER_BADGE_HEIGHT = 18;
12924
12929
  this.BROKER_BADGE_PADDING_X = 8;
12925
12930
  this.BROKER_BADGE_RADIUS = 4;
12931
+ this.ITEM_GAP = 7;
12926
12932
  }
12927
12933
  formatMarginMode(marginMode) {
12928
12934
  return marginMode === MarginMode.ISOLATED ? "Isolated" : "Cross";
@@ -12970,7 +12976,9 @@ var DataPaint = class extends BasePaint {
12970
12976
  color: layout.color,
12971
12977
  fontSize: this._ratio(layout.fontSize),
12972
12978
  top: this._ratio(position.top),
12973
- left: this._ratio(position.left),
12979
+ left: this.inlineStart(options, position.left),
12980
+ textAlign: this.inlineStartAlign(options),
12981
+ direction: this.textDirection(options),
12974
12982
  textBaseline: "top",
12975
12983
  fontFamily: options.fontFamily
12976
12984
  });
@@ -12981,126 +12989,63 @@ var DataPaint = class extends BasePaint {
12981
12989
  options
12982
12990
  );
12983
12991
  const { position, fontSize = 14 } = layout;
12984
- let left = this._ratio(position.left);
12992
+ let cursor = this.inlineStart(options, position.left);
12985
12993
  const top = layout.position.top + offsetTop + this.transformTop;
12986
- let prevElementBoundingBox = {};
12994
+ const items = [];
12987
12995
  if (typeof options.data?.position.side !== "undefined") {
12988
- prevElementBoundingBox = this._drawText(options.data.position.side, {
12996
+ items.push({
12997
+ kind: "text",
12998
+ text: options.data.position.side,
12989
12999
  color: options.data?.position.side.toUpperCase() === "LONG" ? options.profitColor || this.DEFAULT_PROFIT_COLOR : options.lossColor || this.DEFAULT_LOSS_COLOR,
12990
- left,
12991
- top: this._ratio(top),
12992
- fontSize: this._ratio(fontSize),
12993
- fontFamily: options.fontFamily
13000
+ fontSize: this._ratio(fontSize)
12994
13001
  });
12995
13002
  }
12996
13003
  if (typeof options.data?.position.symbol !== "undefined") {
12997
- left += (prevElementBoundingBox.width ?? 0) + this._ratio(7);
12998
- if (prevElementBoundingBox.width) {
12999
- prevElementBoundingBox = this._drawText("|", {
13000
- color: "rgba(255,255,255,0.2)",
13001
- left,
13002
- top: this._ratio(top),
13003
- fontSize: this._ratio(fontSize),
13004
- fontFamily: options.fontFamily
13005
- });
13006
- }
13007
- left += (prevElementBoundingBox.width ?? 0) + this._ratio(7);
13008
- prevElementBoundingBox = this._drawText(options.data?.position.symbol, {
13004
+ items.push({
13005
+ kind: "text",
13006
+ text: options.data.position.symbol,
13009
13007
  color: layout.color,
13010
- left,
13011
- top: this._ratio(top),
13012
- fontSize: this._ratio(fontSize),
13013
- fontFamily: options.fontFamily
13008
+ fontSize: this._ratio(fontSize)
13009
+ });
13010
+ }
13011
+ const brokerName = options.data?.position.brokerName?.trim();
13012
+ if (brokerName) {
13013
+ items.push({
13014
+ kind: "badge",
13015
+ text: brokerName,
13016
+ fontSize: this._ratio(12),
13017
+ fontWeight: 600
13014
13018
  });
13015
- const brokerName = options.data?.position.brokerName?.trim();
13016
- if (brokerName) {
13017
- left += (prevElementBoundingBox.width ?? 0) + this._ratio(10);
13018
- const badgeHeight = this._ratio(this.BROKER_BADGE_HEIGHT);
13019
- const badgePaddingX = this._ratio(this.BROKER_BADGE_PADDING_X);
13020
- const badgeRadius = this._ratio(this.BROKER_BADGE_RADIUS);
13021
- const badgeFontSize = this._ratio(12);
13022
- const badgeFontWeight = 600;
13023
- const textMetrics = this._drawText(
13024
- brokerName,
13025
- {
13026
- left: 0,
13027
- top: 0,
13028
- fontSize: badgeFontSize,
13029
- fontWeight: badgeFontWeight,
13030
- fontFamily: options.fontFamily
13031
- },
13032
- true
13033
- );
13034
- const badgeWidth = (textMetrics.width ?? 0) + badgePaddingX * 2;
13035
- const badgeTop = this._ratio(top) - badgeHeight / 2;
13036
- this._fillRoundedRect(
13037
- left,
13038
- badgeTop,
13039
- badgeWidth,
13040
- badgeHeight,
13041
- badgeRadius,
13042
- "rgba(255,255,255,0.06)"
13043
- );
13044
- this._drawText(brokerName, {
13045
- color: "rgba(255,255,255,0.36)",
13046
- left: left + badgePaddingX,
13047
- top: badgeTop + badgeHeight / 2,
13048
- fontSize: badgeFontSize,
13049
- fontWeight: badgeFontWeight,
13050
- fontFamily: options.fontFamily,
13051
- textBaseline: "middle"
13052
- });
13053
- prevElementBoundingBox = {
13054
- ...prevElementBoundingBox,
13055
- width: badgeWidth
13056
- };
13057
- }
13058
13019
  }
13059
13020
  const marginMode = options.data?.position.marginMode;
13060
13021
  if (marginMode) {
13061
- left += (prevElementBoundingBox.width ?? 0) + this._ratio(7);
13062
- if (prevElementBoundingBox.width) {
13063
- prevElementBoundingBox = this._drawText("|", {
13064
- color: "rgba(255,255,255,0.2)",
13065
- left,
13066
- top: this._ratio(top),
13067
- fontSize: this._ratio(fontSize),
13068
- fontFamily: options.fontFamily
13069
- });
13070
- }
13071
- left += (prevElementBoundingBox.width ?? 0) + this._ratio(7);
13072
- const marginModeText = this.formatMarginMode(marginMode);
13073
- prevElementBoundingBox = this._drawText(marginModeText, {
13022
+ items.push({
13023
+ kind: "text",
13024
+ text: this.formatMarginMode(marginMode),
13074
13025
  color: layout.color,
13075
- left,
13076
- top: this._ratio(top),
13077
- fontSize: this._ratio(fontSize),
13078
- fontFamily: options.fontFamily
13026
+ fontSize: this._ratio(fontSize)
13079
13027
  });
13080
13028
  }
13081
13029
  if (typeof options.data?.position.leverage !== "undefined") {
13082
- left += (prevElementBoundingBox.width ?? 0) + this._ratio(7);
13083
- if (prevElementBoundingBox.width) {
13084
- prevElementBoundingBox = this._drawText("|", {
13085
- color: "rgba(255,255,255,0.2)",
13086
- left,
13087
- top: this._ratio(top),
13088
- fontSize: this._ratio(fontSize),
13089
- fontFamily: options.fontFamily
13090
- });
13091
- }
13092
- left += (prevElementBoundingBox.width ?? 0) + this._ratio(7);
13093
- prevElementBoundingBox = this._drawText(
13094
- `${options.data?.position.leverage}X`,
13095
- {
13096
- color: layout.color,
13097
- left,
13098
- top: this._ratio(top),
13099
- fontSize: this._ratio(fontSize),
13100
- fontFamily: options.fontFamily
13101
- }
13102
- );
13030
+ items.push({
13031
+ kind: "text",
13032
+ text: `${options.data.position.leverage}X`,
13033
+ color: layout.color,
13034
+ fontSize: this._ratio(fontSize)
13035
+ });
13103
13036
  }
13037
+ const topPx = this._ratio(top);
13038
+ items.forEach((item, index) => {
13039
+ cursor = this.drawInlineItem(options, item, cursor, topPx);
13040
+ if (index < items.length - 1) {
13041
+ cursor = this.drawInlineSeparator(
13042
+ options,
13043
+ cursor,
13044
+ topPx,
13045
+ this._ratio(fontSize)
13046
+ );
13047
+ }
13048
+ });
13104
13049
  }
13105
13050
  _fillRoundedRect(x, y, width, height, radius, color) {
13106
13051
  const r = Math.min(radius, width / 2, height / 2);
@@ -13122,7 +13067,7 @@ var DataPaint = class extends BasePaint {
13122
13067
  options
13123
13068
  );
13124
13069
  const { position } = layout;
13125
- let left = this._ratio(position.left);
13070
+ let cursor = this.inlineStart(options, position.left);
13126
13071
  let prevElementBoundingBox = {};
13127
13072
  const top = (position.top ?? 0) + offsetTop + this.transformTop;
13128
13073
  if (typeof options.data?.position.ROI !== "undefined") {
@@ -13131,11 +13076,13 @@ var DataPaint = class extends BasePaint {
13131
13076
  `${prefix}${commify(options.data?.position.ROI)}%`,
13132
13077
  {
13133
13078
  color: prefix === "+" ? options.profitColor || this.DEFAULT_PROFIT_COLOR : options.lossColor || this.DEFAULT_LOSS_COLOR,
13134
- left,
13079
+ left: cursor,
13135
13080
  top: this._ratio(top),
13136
13081
  fontSize: this._ratio(layout.fontSize),
13137
13082
  fontWeight: 700,
13138
- fontFamily: options.fontFamily
13083
+ fontFamily: options.fontFamily,
13084
+ textAlign: this.inlineStartAlign(options),
13085
+ direction: this.textDirection(options)
13139
13086
  }
13140
13087
  );
13141
13088
  }
@@ -13144,21 +13091,27 @@ var DataPaint = class extends BasePaint {
13144
13091
  let text = `${prefix}${commify(options.data?.position.pnl)} ${options.data?.position.currency}`;
13145
13092
  let fontWeight = 600;
13146
13093
  if (prevElementBoundingBox.width) {
13147
- left += (prevElementBoundingBox.width ?? 0) + this._ratio(8);
13094
+ cursor = this.advanceCursor(
13095
+ options,
13096
+ cursor,
13097
+ (prevElementBoundingBox.width ?? 0) + this._ratio(8)
13098
+ );
13148
13099
  text = `(${text})`;
13149
13100
  } else {
13150
- left = this._ratio(position.left);
13101
+ cursor = this.inlineStart(options, position.left);
13151
13102
  fontWeight = 700;
13152
13103
  }
13153
13104
  const color = typeof options.data.position.ROI === "undefined" ? prefix === "+" ? options.profitColor || this.DEFAULT_PROFIT_COLOR : options.lossColor || this.DEFAULT_LOSS_COLOR : layout.secondaryColor;
13154
13105
  const fontSize = typeof options.data.position.ROI === "undefined" ? this._ratio(layout.fontSize) : this._ratio(layout.secondaryFontSize);
13155
13106
  prevElementBoundingBox = this._drawText(text, {
13156
13107
  color,
13157
- left,
13108
+ left: cursor,
13158
13109
  top: this._ratio(top),
13159
13110
  fontSize,
13160
13111
  fontWeight,
13161
- fontFamily: options.fontFamily
13112
+ fontFamily: options.fontFamily,
13113
+ textAlign: this.inlineStartAlign(options),
13114
+ direction: this.textDirection(options)
13162
13115
  });
13163
13116
  }
13164
13117
  }
@@ -13172,22 +13125,27 @@ var DataPaint = class extends BasePaint {
13172
13125
  (options.data?.position.informations.length ?? 0) === 2;
13173
13126
  const col = informations.length > 4 ? 3 : 2;
13174
13127
  informations.forEach((info, index) => {
13175
- const left = position.left + index % col * this.positionInfoCellWidth;
13128
+ const colIndex = index % col;
13129
+ const inlineOffset = position.left + colIndex * this.positionInfoCellWidth;
13176
13130
  const top = position.top + Math.floor(index / col) * 38 + this.transformTop;
13177
13131
  this._drawText(info.title, {
13178
- left: this._ratio(left),
13132
+ left: this.inlineStart(options, inlineOffset),
13179
13133
  top: this._ratio(top),
13180
13134
  fontSize: this._ratio(10),
13181
13135
  color: layout.labelColor,
13182
- fontFamily: options.fontFamily
13136
+ fontFamily: options.fontFamily,
13137
+ textAlign: this.inlineStartAlign(options),
13138
+ direction: this.textDirection(options)
13183
13139
  });
13184
13140
  this._drawText(info.value, {
13185
- left: this._ratio(left),
13141
+ left: this.inlineStart(options, inlineOffset),
13186
13142
  top: this._ratio(top + 17),
13187
13143
  fontSize: this._ratio(layout.fontSize),
13188
13144
  fontWeight: 500,
13189
13145
  color: layout.color,
13190
- fontFamily: options.fontFamily
13146
+ fontFamily: options.fontFamily,
13147
+ textAlign: this.inlineStartAlign(options),
13148
+ direction: this.textDirection(options)
13191
13149
  });
13192
13150
  });
13193
13151
  }
@@ -13202,13 +13160,14 @@ var DataPaint = class extends BasePaint {
13202
13160
  return this._drawText(
13203
13161
  options.data?.domain,
13204
13162
  {
13205
- left: !hasReferral ? this._ratio(position.left) : this._ratio(this.painter.width - 20),
13163
+ left: !hasReferral ? this.inlineStart(options, position.left) : this.inlineEnd(options, 20),
13206
13164
  top: !hasReferral ? this._ratio(top) : this._ratio(this.painter.height - 16),
13207
13165
  fontSize: this._ratio(layout.fontSize),
13208
13166
  color: options.brandColor ?? this.DEFAULT_PROFIT_COLOR,
13209
13167
  fontFamily: options.fontFamily,
13210
13168
  textBaseline: layout.textBaseline,
13211
- textAlign: !hasReferral ? layout.textAlign : "end",
13169
+ textAlign: !hasReferral ? this.inlineStartAlign(options) : this.inlineEndAlign(options),
13170
+ direction: this.textDirection(options),
13212
13171
  fontWeight: 600
13213
13172
  },
13214
13173
  onlyMeasure
@@ -13222,10 +13181,10 @@ var DataPaint = class extends BasePaint {
13222
13181
  const { position } = layout;
13223
13182
  const hasReferral = this.hasReferral(options);
13224
13183
  let top = this.painter.height - position.bottom;
13225
- let left = this._ratio(position.left);
13184
+ let left = this.inlineStart(options, position.left);
13226
13185
  if (hasReferral) {
13227
13186
  const metrics = this.drawDomainUrl(options, true);
13228
- left = this._ratio(this.painter.width) - metrics.width - this._ratio(8 + position.left);
13187
+ left = this.inlineStart(options, position.left + 8) + (this.isRTL(options) ? metrics.width : -metrics.width);
13229
13188
  top = this.painter.height - position.bottom;
13230
13189
  }
13231
13190
  this._drawText(
@@ -13237,9 +13196,10 @@ var DataPaint = class extends BasePaint {
13237
13196
  fontSize: this._ratio(layout.fontSize),
13238
13197
  color: layout.color,
13239
13198
  // color: "red",
13240
- textAlign: !hasReferral ? layout.textAlign : "end",
13199
+ textAlign: !hasReferral ? this.inlineStartAlign(options) : this.inlineEndAlign(options),
13241
13200
  fontFamily: options.fontFamily,
13242
- textBaseline: layout.textBaseline
13201
+ textBaseline: layout.textBaseline,
13202
+ direction: this.textDirection(options)
13243
13203
  }
13244
13204
  );
13245
13205
  }
@@ -13261,36 +13221,44 @@ var DataPaint = class extends BasePaint {
13261
13221
  const searchParams = url.searchParams;
13262
13222
  searchParams.append("ref", options.data.referral.code);
13263
13223
  url.search = searchParams.toString();
13224
+ const qrSize = this._ratio(this.QRCODE_SIZE);
13225
+ const qrLeft = this.isRTL(options) ? this.inlineStart(options, position.left) - qrSize : this.inlineStart(options, position.left);
13264
13226
  qrPaint(this.ctx, {
13265
13227
  size: this._ratio(this.QRCODE_SIZE),
13266
13228
  padding: this._ratio(2),
13267
- left: this._ratio(position.left),
13229
+ left: qrLeft,
13268
13230
  top: this._ratio(top - this.QRCODE_SIZE),
13269
13231
  data: `${url.toString()}`
13270
13232
  });
13271
13233
  this._drawText(options.data.referral.slogan, {
13272
- left: this._ratio(position.left + 66),
13234
+ left: this.inlineStart(options, position.left + 66),
13273
13235
  top: this._ratio(top - this.QRCODE_SIZE),
13274
13236
  fontSize: this._ratio(14),
13275
13237
  color: options.brandColor ?? this.DEFAULT_PROFIT_COLOR,
13276
13238
  fontFamily: options.fontFamily,
13277
- textBaseline: "top"
13239
+ textBaseline: "top",
13240
+ textAlign: this.inlineStartAlign(options),
13241
+ direction: this.textDirection(options)
13278
13242
  });
13279
13243
  this._drawText("Referral Code", {
13280
- left: this._ratio(position.left + 66),
13244
+ left: this.inlineStart(options, position.left + 66),
13281
13245
  top: this._ratio(top - 29),
13282
13246
  fontSize: this._ratio(12),
13283
13247
  color: layout.color,
13284
13248
  fontFamily: options.fontFamily,
13285
- textBaseline: "middle"
13249
+ textBaseline: "middle",
13250
+ textAlign: this.inlineStartAlign(options),
13251
+ direction: this.textDirection(options)
13286
13252
  });
13287
13253
  this._drawText(options.data.referral.code, {
13288
- left: this._ratio(position.left + 66),
13254
+ left: this.inlineStart(options, position.left + 66),
13289
13255
  top: this._ratio(top),
13290
13256
  fontSize: this._ratio(16),
13291
13257
  color: messageLayout.color,
13292
13258
  fontFamily: options.fontFamily,
13293
- textBaseline: "bottom"
13259
+ textBaseline: "bottom",
13260
+ textAlign: this.inlineStartAlign(options),
13261
+ direction: this.textDirection(options)
13294
13262
  });
13295
13263
  }
13296
13264
  _drawText(str, options, onlyMeasure = false) {
@@ -13302,13 +13270,15 @@ var DataPaint = class extends BasePaint {
13302
13270
  fontWeight = 500,
13303
13271
  color = "black",
13304
13272
  textBaseline = "middle",
13305
- textAlign = "start"
13273
+ textAlign = "start",
13274
+ direction = "ltr"
13306
13275
  } = options ?? {};
13307
13276
  this.ctx.save();
13308
13277
  this.ctx.font = `${fontWeight} ${fontSize}px ${options?.fontFamily}`;
13309
13278
  this.ctx.fillStyle = color;
13310
13279
  this.ctx.textBaseline = textBaseline;
13311
13280
  this.ctx.textAlign = textAlign;
13281
+ this.ctx.direction = direction;
13312
13282
  boundingBox = this.ctx.measureText(str);
13313
13283
  if (!onlyMeasure) {
13314
13284
  this.ctx.fillText(str, left, top);
@@ -13322,6 +13292,98 @@ var DataPaint = class extends BasePaint {
13322
13292
  _ratio(num) {
13323
13293
  return num * this.painter.ratio;
13324
13294
  }
13295
+ canvasWidth() {
13296
+ return this._ratio(this.painter.width);
13297
+ }
13298
+ textDirection(options) {
13299
+ return this.isRTL(options) ? "rtl" : "ltr";
13300
+ }
13301
+ isRTL(options) {
13302
+ return options.direction === "rtl";
13303
+ }
13304
+ inlineStart(options, value) {
13305
+ return this.isRTL(options) ? this.canvasWidth() - this._ratio(value) : this._ratio(value);
13306
+ }
13307
+ inlineEnd(options, value) {
13308
+ return this.isRTL(options) ? this._ratio(value) : this.canvasWidth() - this._ratio(value);
13309
+ }
13310
+ inlineStartAlign(options) {
13311
+ return this.isRTL(options) ? "right" : "left";
13312
+ }
13313
+ inlineEndAlign(options) {
13314
+ return this.isRTL(options) ? "left" : "right";
13315
+ }
13316
+ advanceCursor(options, cursor, width) {
13317
+ return this.isRTL(options) ? cursor - width : cursor + width;
13318
+ }
13319
+ drawInlineSeparator(options, cursor, top, fontSize) {
13320
+ const gap = this._ratio(this.ITEM_GAP);
13321
+ const separatorMetrics = this._drawText("|", {
13322
+ color: "rgba(255,255,255,0.2)",
13323
+ left: this.advanceCursor(options, cursor, gap),
13324
+ top,
13325
+ fontSize,
13326
+ fontFamily: options.fontFamily,
13327
+ textAlign: this.inlineStartAlign(options),
13328
+ direction: this.textDirection(options)
13329
+ });
13330
+ return this.advanceCursor(
13331
+ options,
13332
+ this.advanceCursor(options, cursor, gap),
13333
+ (separatorMetrics.width ?? 0) + gap
13334
+ );
13335
+ }
13336
+ drawInlineItem(options, item, cursor, top) {
13337
+ if (item.kind === "text") {
13338
+ const metrics = this._drawText(item.text, {
13339
+ color: item.color,
13340
+ left: cursor,
13341
+ top,
13342
+ fontSize: item.fontSize,
13343
+ fontWeight: item.fontWeight,
13344
+ fontFamily: options.fontFamily,
13345
+ textAlign: this.inlineStartAlign(options),
13346
+ direction: this.textDirection(options)
13347
+ });
13348
+ return this.advanceCursor(options, cursor, metrics.width ?? 0);
13349
+ }
13350
+ const badgeHeight = this._ratio(this.BROKER_BADGE_HEIGHT);
13351
+ const badgePaddingX = this._ratio(this.BROKER_BADGE_PADDING_X);
13352
+ const badgeRadius = this._ratio(this.BROKER_BADGE_RADIUS);
13353
+ const textMetrics = this._drawText(
13354
+ item.text,
13355
+ {
13356
+ left: 0,
13357
+ top: 0,
13358
+ fontSize: item.fontSize,
13359
+ fontWeight: item.fontWeight ?? 600,
13360
+ direction: this.textDirection(options)
13361
+ },
13362
+ true
13363
+ );
13364
+ const badgeWidth = (textMetrics.width ?? 0) + badgePaddingX * 2;
13365
+ const badgeTop = top - badgeHeight / 2;
13366
+ const badgeLeft = this.isRTL(options) ? cursor - badgeWidth : cursor;
13367
+ this._fillRoundedRect(
13368
+ badgeLeft,
13369
+ badgeTop,
13370
+ badgeWidth,
13371
+ badgeHeight,
13372
+ badgeRadius,
13373
+ "rgba(255,255,255,0.06)"
13374
+ );
13375
+ this._drawText(item.text, {
13376
+ color: "rgba(255,255,255,0.36)",
13377
+ left: this.isRTL(options) ? badgeLeft + badgeWidth - badgePaddingX : badgeLeft + badgePaddingX,
13378
+ top: badgeTop + badgeHeight / 2,
13379
+ fontSize: item.fontSize,
13380
+ fontWeight: item.fontWeight ?? 600,
13381
+ textBaseline: "middle",
13382
+ textAlign: this.inlineStartAlign(options),
13383
+ direction: this.textDirection(options)
13384
+ });
13385
+ return this.advanceCursor(options, cursor, badgeWidth);
13386
+ }
13325
13387
  };
13326
13388
 
13327
13389
  // src/services/painter/painter.ts
@@ -19110,20 +19172,39 @@ var useOrderEntry2 = (symbol, options = {}) => {
19110
19172
  symbolLeverage
19111
19173
  });
19112
19174
  const [estSlippage, setEstSlippage] = useState(null);
19175
+ const [bestAskBidSnapshot, setBestAskBidSnapshot] = useState([]);
19113
19176
  const [doCreateOrder, { isMutating }] = useMutation(
19114
19177
  getCreateOrderUrl(formattedOrder)
19115
19178
  );
19116
- const bestAskBid = askAndBid.current?.[0] || [];
19117
- const referencePriceFromOrder = bestAskBid.length >= 2 && formattedOrder.order_type && formattedOrder.side ? getOrderReferencePriceFromOrder(formattedOrder, bestAskBid) : null;
19179
+ const bestAskBid = bestAskBidSnapshot;
19180
+ const getReferencePriceForSide = (side) => {
19181
+ if (bestAskBid.length < 2 || !formattedOrder.order_type) {
19182
+ return null;
19183
+ }
19184
+ const referencePrice = getOrderReferencePriceFromOrder(
19185
+ {
19186
+ ...formattedOrder,
19187
+ side
19188
+ },
19189
+ bestAskBid
19190
+ );
19191
+ const slippage = Number(formattedOrder.slippage);
19192
+ if (effectiveMarginMode !== MarginMode.ISOLATED || side !== OrderSide.BUY || formattedOrder.order_type !== OrderType.MARKET || !referencePrice || !Number.isFinite(slippage) || slippage <= 0) {
19193
+ return referencePrice;
19194
+ }
19195
+ return new Decimal(referencePrice).mul(new Decimal(1).add(new Decimal(slippage).div(100))).toNumber();
19196
+ };
19197
+ const buyReferencePriceFromOrder = getReferencePriceForSide(OrderSide.BUY);
19198
+ const sellReferencePriceFromOrder = getReferencePriceForSide(OrderSide.SELL);
19118
19199
  const maxBuyQtyValue = useMaxQty(symbol, OrderSide.BUY, {
19119
19200
  reduceOnly: formattedOrder.reduce_only,
19120
19201
  marginMode: effectiveMarginMode,
19121
- currentOrderReferencePrice: referencePriceFromOrder && referencePriceFromOrder > 0 ? referencePriceFromOrder : void 0
19202
+ currentOrderReferencePrice: buyReferencePriceFromOrder && buyReferencePriceFromOrder > 0 ? buyReferencePriceFromOrder : void 0
19122
19203
  });
19123
19204
  const maxSellQtyValue = useMaxQty(symbol, OrderSide.SELL, {
19124
19205
  reduceOnly: formattedOrder.reduce_only,
19125
19206
  marginMode: effectiveMarginMode,
19126
- currentOrderReferencePrice: referencePriceFromOrder && referencePriceFromOrder > 0 ? referencePriceFromOrder : void 0
19207
+ currentOrderReferencePrice: sellReferencePriceFromOrder && sellReferencePriceFromOrder > 0 ? sellReferencePriceFromOrder : void 0
19127
19208
  });
19128
19209
  const maxQtyValue = formattedOrder.side === OrderSide.BUY ? maxBuyQtyValue : maxSellQtyValue;
19129
19210
  const maxQty = options.maxQty ?? maxQtyValue;
@@ -19215,6 +19296,10 @@ var useOrderEntry2 = (symbol, options = {}) => {
19215
19296
  useEffect(() => {
19216
19297
  updateOrderPrice();
19217
19298
  }, [formattedOrder.order_type_ext, formattedOrder.level]);
19299
+ useEffect(() => {
19300
+ askAndBid.current = [[]];
19301
+ setBestAskBidSnapshot([]);
19302
+ }, [symbol]);
19218
19303
  const onOrderBookUpdate = useDebouncedCallback((data) => {
19219
19304
  const parsedData = [
19220
19305
  [data.asks?.[data.asks.length - 1]?.[0], data.bids?.[0]?.[0]],
@@ -19224,6 +19309,10 @@ var useOrderEntry2 = (symbol, options = {}) => {
19224
19309
  [data.asks?.[data.asks.length - 5]?.[0], data.bids?.[4]?.[0]]
19225
19310
  ];
19226
19311
  askAndBid.current = parsedData;
19312
+ const nextBestAskBid = parsedData[0] || [];
19313
+ setBestAskBidSnapshot(
19314
+ (prev) => prev[0] === nextBestAskBid[0] && prev[1] === nextBestAskBid[1] ? prev : nextBestAskBid
19315
+ );
19227
19316
  updateOrderPriceByOrderBook();
19228
19317
  updateEstSlippage(data);
19229
19318
  }, 200);