@kodiak-finance/orderly-hooks 2.9.2 → 2.9.4

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.d.mts CHANGED
@@ -2412,6 +2412,7 @@ type PosterLayoutConfig = {
2412
2412
  updateTime?: layoutInfo;
2413
2413
  };
2414
2414
  type DrawOptions = {
2415
+ direction?: "ltr" | "rtl";
2415
2416
  /**
2416
2417
  * Color of common text
2417
2418
  */
package/dist/index.d.ts CHANGED
@@ -2412,6 +2412,7 @@ type PosterLayoutConfig = {
2412
2412
  updateTime?: layoutInfo;
2413
2413
  };
2414
2414
  type DrawOptions = {
2415
+ direction?: "ltr" | "rtl";
2415
2416
  /**
2416
2417
  * Color of common text
2417
2418
  */
package/dist/index.js CHANGED
@@ -7484,6 +7484,7 @@ var useLeverageBySymbol = (symbol, marginMode) => {
7484
7484
  function useMaxQty(symbol, side, reduceOnlyOrOptions, marginMode) {
7485
7485
  const reduceOnly = typeof reduceOnlyOrOptions === "object" && reduceOnlyOrOptions !== null ? reduceOnlyOrOptions.reduceOnly ?? false : reduceOnlyOrOptions ?? false;
7486
7486
  const finalMarginMode = typeof reduceOnlyOrOptions === "object" && reduceOnlyOrOptions !== null ? reduceOnlyOrOptions.marginMode ?? orderlyTypes.MarginMode.CROSS : marginMode ?? orderlyTypes.MarginMode.CROSS;
7487
+ const currentOrderReferencePrice = typeof reduceOnlyOrOptions === "object" && reduceOnlyOrOptions !== null && typeof reduceOnlyOrOptions.currentOrderReferencePrice === "number" && reduceOnlyOrOptions.currentOrderReferencePrice > 0 ? reduceOnlyOrOptions.currentOrderReferencePrice : void 0;
7487
7488
  const positions3 = usePositions();
7488
7489
  const accountInfo = useAccountInfo();
7489
7490
  const symbolInfo = useSymbolsInfo();
@@ -7524,18 +7525,18 @@ function useMaxQty(symbol, side, reduceOnlyOrOptions, marginMode) {
7524
7525
  const pendingLongOrders = buyOrdersQty > 0 ? [{ referencePrice: markPrice, quantity: buyOrdersQty }] : [];
7525
7526
  const pendingSellOrders = sellOrdersQty > 0 ? [{ referencePrice: markPrice, quantity: sellOrdersQty }] : [];
7526
7527
  const markPriceDecimal = new orderlyUtils.Decimal(markPrice);
7527
- const leverageDecimal = new orderlyUtils.Decimal(leverage);
7528
- const isoOrderFrozenLong = buyOrdersQty > 0 ? markPriceDecimal.mul(buyOrdersQty).div(leverageDecimal).toNumber() : 0;
7529
- const isoOrderFrozenShort = sellOrdersQty > 0 ? markPriceDecimal.mul(sellOrdersQty).div(leverageDecimal).toNumber() : 0;
7528
+ const marginRate = orderlyPerp.account.isolatedMarginRate({ leverage });
7529
+ const isoOrderFrozenLong = buyOrdersQty > 0 ? markPriceDecimal.mul(buyOrdersQty).mul(marginRate).toNumber() : 0;
7530
+ const isoOrderFrozenShort = sellOrdersQty > 0 ? markPriceDecimal.mul(sellOrdersQty).mul(marginRate).toNumber() : 0;
7530
7531
  const symbolMaxNotional = accountInfo.max_notional?.[symbol] ?? orderlyPerp.positions.maxPositionNotional({
7531
7532
  leverage,
7532
7533
  IMRFactor: IMR_Factor
7533
7534
  });
7534
- const currentOrderReferencePrice = typeof reduceOnlyOrOptions === "object" && reduceOnlyOrOptions !== null && typeof reduceOnlyOrOptions.currentOrderReferencePrice === "number" && reduceOnlyOrOptions.currentOrderReferencePrice > 0 ? reduceOnlyOrOptions.currentOrderReferencePrice : markPrice;
7535
+ const effectiveOrderReferencePrice = currentOrderReferencePrice ?? markPrice;
7535
7536
  return orderlyPerp.account.maxQtyForIsolatedMargin({
7536
7537
  symbol,
7537
7538
  orderSide: side,
7538
- currentOrderReferencePrice,
7539
+ currentOrderReferencePrice: effectiveOrderReferencePrice,
7539
7540
  availableBalance,
7540
7541
  leverage,
7541
7542
  baseIMR,
@@ -7578,8 +7579,10 @@ function useMaxQty(symbol, side, reduceOnlyOrOptions, marginMode) {
7578
7579
  symbolInfo,
7579
7580
  side,
7580
7581
  totalCollateral,
7582
+ freeCollateralUSDCOnly,
7581
7583
  finalMarginMode,
7582
- symbolLeverage
7584
+ symbolLeverage,
7585
+ currentOrderReferencePrice
7583
7586
  ]);
7584
7587
  return Math.max(maxQty, 0);
7585
7588
  }
@@ -12878,15 +12881,17 @@ var BackgroundPaint = class extends BasePaint {
12878
12881
  );
12879
12882
  }
12880
12883
  async _drawImage(options) {
12884
+ const width = this.painter.width * this.painter.ratio;
12885
+ const height = this.painter.height * this.painter.ratio;
12881
12886
  return this.loadImg(options.backgroundImg).then((img) => {
12882
12887
  this.img = img;
12883
- this.ctx.drawImage(
12884
- this.img,
12885
- 0,
12886
- 0,
12887
- this.painter.width * this.painter.ratio,
12888
- this.painter.height * this.painter.ratio
12889
- );
12888
+ this.ctx.save();
12889
+ if (options.direction === "rtl") {
12890
+ this.ctx.translate(width, 0);
12891
+ this.ctx.scale(-1, 1);
12892
+ }
12893
+ this.ctx.drawImage(this.img, 0, 0, width, height);
12894
+ this.ctx.restore();
12890
12895
  });
12891
12896
  }
12892
12897
  loadImg(url) {
@@ -12949,6 +12954,7 @@ var DataPaint = class extends BasePaint {
12949
12954
  this.BROKER_BADGE_HEIGHT = 18;
12950
12955
  this.BROKER_BADGE_PADDING_X = 8;
12951
12956
  this.BROKER_BADGE_RADIUS = 4;
12957
+ this.ITEM_GAP = 7;
12952
12958
  }
12953
12959
  formatMarginMode(marginMode) {
12954
12960
  return marginMode === orderlyTypes.MarginMode.ISOLATED ? "Isolated" : "Cross";
@@ -12996,7 +13002,9 @@ var DataPaint = class extends BasePaint {
12996
13002
  color: layout.color,
12997
13003
  fontSize: this._ratio(layout.fontSize),
12998
13004
  top: this._ratio(position.top),
12999
- left: this._ratio(position.left),
13005
+ left: this.inlineStart(options, position.left),
13006
+ textAlign: this.inlineStartAlign(options),
13007
+ direction: this.textDirection(options),
13000
13008
  textBaseline: "top",
13001
13009
  fontFamily: options.fontFamily
13002
13010
  });
@@ -13007,126 +13015,63 @@ var DataPaint = class extends BasePaint {
13007
13015
  options
13008
13016
  );
13009
13017
  const { position, fontSize = 14 } = layout;
13010
- let left = this._ratio(position.left);
13018
+ let cursor = this.inlineStart(options, position.left);
13011
13019
  const top = layout.position.top + offsetTop + this.transformTop;
13012
- let prevElementBoundingBox = {};
13020
+ const items = [];
13013
13021
  if (typeof options.data?.position.side !== "undefined") {
13014
- prevElementBoundingBox = this._drawText(options.data.position.side, {
13022
+ items.push({
13023
+ kind: "text",
13024
+ text: options.data.position.side,
13015
13025
  color: options.data?.position.side.toUpperCase() === "LONG" ? options.profitColor || this.DEFAULT_PROFIT_COLOR : options.lossColor || this.DEFAULT_LOSS_COLOR,
13016
- left,
13017
- top: this._ratio(top),
13018
- fontSize: this._ratio(fontSize),
13019
- fontFamily: options.fontFamily
13026
+ fontSize: this._ratio(fontSize)
13020
13027
  });
13021
13028
  }
13022
13029
  if (typeof options.data?.position.symbol !== "undefined") {
13023
- left += (prevElementBoundingBox.width ?? 0) + this._ratio(7);
13024
- if (prevElementBoundingBox.width) {
13025
- prevElementBoundingBox = this._drawText("|", {
13026
- color: "rgba(255,255,255,0.2)",
13027
- left,
13028
- top: this._ratio(top),
13029
- fontSize: this._ratio(fontSize),
13030
- fontFamily: options.fontFamily
13031
- });
13032
- }
13033
- left += (prevElementBoundingBox.width ?? 0) + this._ratio(7);
13034
- prevElementBoundingBox = this._drawText(options.data?.position.symbol, {
13030
+ items.push({
13031
+ kind: "text",
13032
+ text: options.data.position.symbol,
13035
13033
  color: layout.color,
13036
- left,
13037
- top: this._ratio(top),
13038
- fontSize: this._ratio(fontSize),
13039
- fontFamily: options.fontFamily
13034
+ fontSize: this._ratio(fontSize)
13035
+ });
13036
+ }
13037
+ const brokerName = options.data?.position.brokerName?.trim();
13038
+ if (brokerName) {
13039
+ items.push({
13040
+ kind: "badge",
13041
+ text: brokerName,
13042
+ fontSize: this._ratio(12),
13043
+ fontWeight: 600
13040
13044
  });
13041
- const brokerName = options.data?.position.brokerName?.trim();
13042
- if (brokerName) {
13043
- left += (prevElementBoundingBox.width ?? 0) + this._ratio(10);
13044
- const badgeHeight = this._ratio(this.BROKER_BADGE_HEIGHT);
13045
- const badgePaddingX = this._ratio(this.BROKER_BADGE_PADDING_X);
13046
- const badgeRadius = this._ratio(this.BROKER_BADGE_RADIUS);
13047
- const badgeFontSize = this._ratio(12);
13048
- const badgeFontWeight = 600;
13049
- const textMetrics = this._drawText(
13050
- brokerName,
13051
- {
13052
- left: 0,
13053
- top: 0,
13054
- fontSize: badgeFontSize,
13055
- fontWeight: badgeFontWeight,
13056
- fontFamily: options.fontFamily
13057
- },
13058
- true
13059
- );
13060
- const badgeWidth = (textMetrics.width ?? 0) + badgePaddingX * 2;
13061
- const badgeTop = this._ratio(top) - badgeHeight / 2;
13062
- this._fillRoundedRect(
13063
- left,
13064
- badgeTop,
13065
- badgeWidth,
13066
- badgeHeight,
13067
- badgeRadius,
13068
- "rgba(255,255,255,0.06)"
13069
- );
13070
- this._drawText(brokerName, {
13071
- color: "rgba(255,255,255,0.36)",
13072
- left: left + badgePaddingX,
13073
- top: badgeTop + badgeHeight / 2,
13074
- fontSize: badgeFontSize,
13075
- fontWeight: badgeFontWeight,
13076
- fontFamily: options.fontFamily,
13077
- textBaseline: "middle"
13078
- });
13079
- prevElementBoundingBox = {
13080
- ...prevElementBoundingBox,
13081
- width: badgeWidth
13082
- };
13083
- }
13084
13045
  }
13085
13046
  const marginMode = options.data?.position.marginMode;
13086
13047
  if (marginMode) {
13087
- left += (prevElementBoundingBox.width ?? 0) + this._ratio(7);
13088
- if (prevElementBoundingBox.width) {
13089
- prevElementBoundingBox = this._drawText("|", {
13090
- color: "rgba(255,255,255,0.2)",
13091
- left,
13092
- top: this._ratio(top),
13093
- fontSize: this._ratio(fontSize),
13094
- fontFamily: options.fontFamily
13095
- });
13096
- }
13097
- left += (prevElementBoundingBox.width ?? 0) + this._ratio(7);
13098
- const marginModeText = this.formatMarginMode(marginMode);
13099
- prevElementBoundingBox = this._drawText(marginModeText, {
13048
+ items.push({
13049
+ kind: "text",
13050
+ text: this.formatMarginMode(marginMode),
13100
13051
  color: layout.color,
13101
- left,
13102
- top: this._ratio(top),
13103
- fontSize: this._ratio(fontSize),
13104
- fontFamily: options.fontFamily
13052
+ fontSize: this._ratio(fontSize)
13105
13053
  });
13106
13054
  }
13107
13055
  if (typeof options.data?.position.leverage !== "undefined") {
13108
- left += (prevElementBoundingBox.width ?? 0) + this._ratio(7);
13109
- if (prevElementBoundingBox.width) {
13110
- prevElementBoundingBox = this._drawText("|", {
13111
- color: "rgba(255,255,255,0.2)",
13112
- left,
13113
- top: this._ratio(top),
13114
- fontSize: this._ratio(fontSize),
13115
- fontFamily: options.fontFamily
13116
- });
13117
- }
13118
- left += (prevElementBoundingBox.width ?? 0) + this._ratio(7);
13119
- prevElementBoundingBox = this._drawText(
13120
- `${options.data?.position.leverage}X`,
13121
- {
13122
- color: layout.color,
13123
- left,
13124
- top: this._ratio(top),
13125
- fontSize: this._ratio(fontSize),
13126
- fontFamily: options.fontFamily
13127
- }
13128
- );
13056
+ items.push({
13057
+ kind: "text",
13058
+ text: `${options.data.position.leverage}X`,
13059
+ color: layout.color,
13060
+ fontSize: this._ratio(fontSize)
13061
+ });
13129
13062
  }
13063
+ const topPx = this._ratio(top);
13064
+ items.forEach((item, index) => {
13065
+ cursor = this.drawInlineItem(options, item, cursor, topPx);
13066
+ if (index < items.length - 1) {
13067
+ cursor = this.drawInlineSeparator(
13068
+ options,
13069
+ cursor,
13070
+ topPx,
13071
+ this._ratio(fontSize)
13072
+ );
13073
+ }
13074
+ });
13130
13075
  }
13131
13076
  _fillRoundedRect(x, y, width, height, radius, color) {
13132
13077
  const r = Math.min(radius, width / 2, height / 2);
@@ -13148,7 +13093,7 @@ var DataPaint = class extends BasePaint {
13148
13093
  options
13149
13094
  );
13150
13095
  const { position } = layout;
13151
- let left = this._ratio(position.left);
13096
+ let cursor = this.inlineStart(options, position.left);
13152
13097
  let prevElementBoundingBox = {};
13153
13098
  const top = (position.top ?? 0) + offsetTop + this.transformTop;
13154
13099
  if (typeof options.data?.position.ROI !== "undefined") {
@@ -13157,11 +13102,13 @@ var DataPaint = class extends BasePaint {
13157
13102
  `${prefix}${orderlyUtils.commify(options.data?.position.ROI)}%`,
13158
13103
  {
13159
13104
  color: prefix === "+" ? options.profitColor || this.DEFAULT_PROFIT_COLOR : options.lossColor || this.DEFAULT_LOSS_COLOR,
13160
- left,
13105
+ left: cursor,
13161
13106
  top: this._ratio(top),
13162
13107
  fontSize: this._ratio(layout.fontSize),
13163
13108
  fontWeight: 700,
13164
- fontFamily: options.fontFamily
13109
+ fontFamily: options.fontFamily,
13110
+ textAlign: this.inlineStartAlign(options),
13111
+ direction: this.textDirection(options)
13165
13112
  }
13166
13113
  );
13167
13114
  }
@@ -13170,21 +13117,27 @@ var DataPaint = class extends BasePaint {
13170
13117
  let text = `${prefix}${orderlyUtils.commify(options.data?.position.pnl)} ${options.data?.position.currency}`;
13171
13118
  let fontWeight = 600;
13172
13119
  if (prevElementBoundingBox.width) {
13173
- left += (prevElementBoundingBox.width ?? 0) + this._ratio(8);
13120
+ cursor = this.advanceCursor(
13121
+ options,
13122
+ cursor,
13123
+ (prevElementBoundingBox.width ?? 0) + this._ratio(8)
13124
+ );
13174
13125
  text = `(${text})`;
13175
13126
  } else {
13176
- left = this._ratio(position.left);
13127
+ cursor = this.inlineStart(options, position.left);
13177
13128
  fontWeight = 700;
13178
13129
  }
13179
13130
  const color = typeof options.data.position.ROI === "undefined" ? prefix === "+" ? options.profitColor || this.DEFAULT_PROFIT_COLOR : options.lossColor || this.DEFAULT_LOSS_COLOR : layout.secondaryColor;
13180
13131
  const fontSize = typeof options.data.position.ROI === "undefined" ? this._ratio(layout.fontSize) : this._ratio(layout.secondaryFontSize);
13181
13132
  prevElementBoundingBox = this._drawText(text, {
13182
13133
  color,
13183
- left,
13134
+ left: cursor,
13184
13135
  top: this._ratio(top),
13185
13136
  fontSize,
13186
13137
  fontWeight,
13187
- fontFamily: options.fontFamily
13138
+ fontFamily: options.fontFamily,
13139
+ textAlign: this.inlineStartAlign(options),
13140
+ direction: this.textDirection(options)
13188
13141
  });
13189
13142
  }
13190
13143
  }
@@ -13198,22 +13151,27 @@ var DataPaint = class extends BasePaint {
13198
13151
  (options.data?.position.informations.length ?? 0) === 2;
13199
13152
  const col = informations.length > 4 ? 3 : 2;
13200
13153
  informations.forEach((info, index) => {
13201
- const left = position.left + index % col * this.positionInfoCellWidth;
13154
+ const colIndex = index % col;
13155
+ const inlineOffset = position.left + colIndex * this.positionInfoCellWidth;
13202
13156
  const top = position.top + Math.floor(index / col) * 38 + this.transformTop;
13203
13157
  this._drawText(info.title, {
13204
- left: this._ratio(left),
13158
+ left: this.inlineStart(options, inlineOffset),
13205
13159
  top: this._ratio(top),
13206
13160
  fontSize: this._ratio(10),
13207
13161
  color: layout.labelColor,
13208
- fontFamily: options.fontFamily
13162
+ fontFamily: options.fontFamily,
13163
+ textAlign: this.inlineStartAlign(options),
13164
+ direction: this.textDirection(options)
13209
13165
  });
13210
13166
  this._drawText(info.value, {
13211
- left: this._ratio(left),
13167
+ left: this.inlineStart(options, inlineOffset),
13212
13168
  top: this._ratio(top + 17),
13213
13169
  fontSize: this._ratio(layout.fontSize),
13214
13170
  fontWeight: 500,
13215
13171
  color: layout.color,
13216
- fontFamily: options.fontFamily
13172
+ fontFamily: options.fontFamily,
13173
+ textAlign: this.inlineStartAlign(options),
13174
+ direction: this.textDirection(options)
13217
13175
  });
13218
13176
  });
13219
13177
  }
@@ -13228,13 +13186,14 @@ var DataPaint = class extends BasePaint {
13228
13186
  return this._drawText(
13229
13187
  options.data?.domain,
13230
13188
  {
13231
- left: !hasReferral ? this._ratio(position.left) : this._ratio(this.painter.width - 20),
13189
+ left: !hasReferral ? this.inlineStart(options, position.left) : this.inlineEnd(options, 20),
13232
13190
  top: !hasReferral ? this._ratio(top) : this._ratio(this.painter.height - 16),
13233
13191
  fontSize: this._ratio(layout.fontSize),
13234
13192
  color: options.brandColor ?? this.DEFAULT_PROFIT_COLOR,
13235
13193
  fontFamily: options.fontFamily,
13236
13194
  textBaseline: layout.textBaseline,
13237
- textAlign: !hasReferral ? layout.textAlign : "end",
13195
+ textAlign: !hasReferral ? this.inlineStartAlign(options) : this.inlineEndAlign(options),
13196
+ direction: this.textDirection(options),
13238
13197
  fontWeight: 600
13239
13198
  },
13240
13199
  onlyMeasure
@@ -13248,10 +13207,10 @@ var DataPaint = class extends BasePaint {
13248
13207
  const { position } = layout;
13249
13208
  const hasReferral = this.hasReferral(options);
13250
13209
  let top = this.painter.height - position.bottom;
13251
- let left = this._ratio(position.left);
13210
+ let left = this.inlineStart(options, position.left);
13252
13211
  if (hasReferral) {
13253
13212
  const metrics = this.drawDomainUrl(options, true);
13254
- left = this._ratio(this.painter.width) - metrics.width - this._ratio(8 + position.left);
13213
+ left = this.inlineStart(options, position.left + 8) + (this.isRTL(options) ? metrics.width : -metrics.width);
13255
13214
  top = this.painter.height - position.bottom;
13256
13215
  }
13257
13216
  this._drawText(
@@ -13263,9 +13222,10 @@ var DataPaint = class extends BasePaint {
13263
13222
  fontSize: this._ratio(layout.fontSize),
13264
13223
  color: layout.color,
13265
13224
  // color: "red",
13266
- textAlign: !hasReferral ? layout.textAlign : "end",
13225
+ textAlign: !hasReferral ? this.inlineStartAlign(options) : this.inlineEndAlign(options),
13267
13226
  fontFamily: options.fontFamily,
13268
- textBaseline: layout.textBaseline
13227
+ textBaseline: layout.textBaseline,
13228
+ direction: this.textDirection(options)
13269
13229
  }
13270
13230
  );
13271
13231
  }
@@ -13287,36 +13247,44 @@ var DataPaint = class extends BasePaint {
13287
13247
  const searchParams = url.searchParams;
13288
13248
  searchParams.append("ref", options.data.referral.code);
13289
13249
  url.search = searchParams.toString();
13250
+ const qrSize = this._ratio(this.QRCODE_SIZE);
13251
+ const qrLeft = this.isRTL(options) ? this.inlineStart(options, position.left) - qrSize : this.inlineStart(options, position.left);
13290
13252
  qrPaint(this.ctx, {
13291
13253
  size: this._ratio(this.QRCODE_SIZE),
13292
13254
  padding: this._ratio(2),
13293
- left: this._ratio(position.left),
13255
+ left: qrLeft,
13294
13256
  top: this._ratio(top - this.QRCODE_SIZE),
13295
13257
  data: `${url.toString()}`
13296
13258
  });
13297
13259
  this._drawText(options.data.referral.slogan, {
13298
- left: this._ratio(position.left + 66),
13260
+ left: this.inlineStart(options, position.left + 66),
13299
13261
  top: this._ratio(top - this.QRCODE_SIZE),
13300
13262
  fontSize: this._ratio(14),
13301
13263
  color: options.brandColor ?? this.DEFAULT_PROFIT_COLOR,
13302
13264
  fontFamily: options.fontFamily,
13303
- textBaseline: "top"
13265
+ textBaseline: "top",
13266
+ textAlign: this.inlineStartAlign(options),
13267
+ direction: this.textDirection(options)
13304
13268
  });
13305
13269
  this._drawText("Referral Code", {
13306
- left: this._ratio(position.left + 66),
13270
+ left: this.inlineStart(options, position.left + 66),
13307
13271
  top: this._ratio(top - 29),
13308
13272
  fontSize: this._ratio(12),
13309
13273
  color: layout.color,
13310
13274
  fontFamily: options.fontFamily,
13311
- textBaseline: "middle"
13275
+ textBaseline: "middle",
13276
+ textAlign: this.inlineStartAlign(options),
13277
+ direction: this.textDirection(options)
13312
13278
  });
13313
13279
  this._drawText(options.data.referral.code, {
13314
- left: this._ratio(position.left + 66),
13280
+ left: this.inlineStart(options, position.left + 66),
13315
13281
  top: this._ratio(top),
13316
13282
  fontSize: this._ratio(16),
13317
13283
  color: messageLayout.color,
13318
13284
  fontFamily: options.fontFamily,
13319
- textBaseline: "bottom"
13285
+ textBaseline: "bottom",
13286
+ textAlign: this.inlineStartAlign(options),
13287
+ direction: this.textDirection(options)
13320
13288
  });
13321
13289
  }
13322
13290
  _drawText(str, options, onlyMeasure = false) {
@@ -13328,13 +13296,15 @@ var DataPaint = class extends BasePaint {
13328
13296
  fontWeight = 500,
13329
13297
  color = "black",
13330
13298
  textBaseline = "middle",
13331
- textAlign = "start"
13299
+ textAlign = "start",
13300
+ direction = "ltr"
13332
13301
  } = options ?? {};
13333
13302
  this.ctx.save();
13334
13303
  this.ctx.font = `${fontWeight} ${fontSize}px ${options?.fontFamily}`;
13335
13304
  this.ctx.fillStyle = color;
13336
13305
  this.ctx.textBaseline = textBaseline;
13337
13306
  this.ctx.textAlign = textAlign;
13307
+ this.ctx.direction = direction;
13338
13308
  boundingBox = this.ctx.measureText(str);
13339
13309
  if (!onlyMeasure) {
13340
13310
  this.ctx.fillText(str, left, top);
@@ -13348,6 +13318,98 @@ var DataPaint = class extends BasePaint {
13348
13318
  _ratio(num) {
13349
13319
  return num * this.painter.ratio;
13350
13320
  }
13321
+ canvasWidth() {
13322
+ return this._ratio(this.painter.width);
13323
+ }
13324
+ textDirection(options) {
13325
+ return this.isRTL(options) ? "rtl" : "ltr";
13326
+ }
13327
+ isRTL(options) {
13328
+ return options.direction === "rtl";
13329
+ }
13330
+ inlineStart(options, value) {
13331
+ return this.isRTL(options) ? this.canvasWidth() - this._ratio(value) : this._ratio(value);
13332
+ }
13333
+ inlineEnd(options, value) {
13334
+ return this.isRTL(options) ? this._ratio(value) : this.canvasWidth() - this._ratio(value);
13335
+ }
13336
+ inlineStartAlign(options) {
13337
+ return this.isRTL(options) ? "right" : "left";
13338
+ }
13339
+ inlineEndAlign(options) {
13340
+ return this.isRTL(options) ? "left" : "right";
13341
+ }
13342
+ advanceCursor(options, cursor, width) {
13343
+ return this.isRTL(options) ? cursor - width : cursor + width;
13344
+ }
13345
+ drawInlineSeparator(options, cursor, top, fontSize) {
13346
+ const gap = this._ratio(this.ITEM_GAP);
13347
+ const separatorMetrics = this._drawText("|", {
13348
+ color: "rgba(255,255,255,0.2)",
13349
+ left: this.advanceCursor(options, cursor, gap),
13350
+ top,
13351
+ fontSize,
13352
+ fontFamily: options.fontFamily,
13353
+ textAlign: this.inlineStartAlign(options),
13354
+ direction: this.textDirection(options)
13355
+ });
13356
+ return this.advanceCursor(
13357
+ options,
13358
+ this.advanceCursor(options, cursor, gap),
13359
+ (separatorMetrics.width ?? 0) + gap
13360
+ );
13361
+ }
13362
+ drawInlineItem(options, item, cursor, top) {
13363
+ if (item.kind === "text") {
13364
+ const metrics = this._drawText(item.text, {
13365
+ color: item.color,
13366
+ left: cursor,
13367
+ top,
13368
+ fontSize: item.fontSize,
13369
+ fontWeight: item.fontWeight,
13370
+ fontFamily: options.fontFamily,
13371
+ textAlign: this.inlineStartAlign(options),
13372
+ direction: this.textDirection(options)
13373
+ });
13374
+ return this.advanceCursor(options, cursor, metrics.width ?? 0);
13375
+ }
13376
+ const badgeHeight = this._ratio(this.BROKER_BADGE_HEIGHT);
13377
+ const badgePaddingX = this._ratio(this.BROKER_BADGE_PADDING_X);
13378
+ const badgeRadius = this._ratio(this.BROKER_BADGE_RADIUS);
13379
+ const textMetrics = this._drawText(
13380
+ item.text,
13381
+ {
13382
+ left: 0,
13383
+ top: 0,
13384
+ fontSize: item.fontSize,
13385
+ fontWeight: item.fontWeight ?? 600,
13386
+ direction: this.textDirection(options)
13387
+ },
13388
+ true
13389
+ );
13390
+ const badgeWidth = (textMetrics.width ?? 0) + badgePaddingX * 2;
13391
+ const badgeTop = top - badgeHeight / 2;
13392
+ const badgeLeft = this.isRTL(options) ? cursor - badgeWidth : cursor;
13393
+ this._fillRoundedRect(
13394
+ badgeLeft,
13395
+ badgeTop,
13396
+ badgeWidth,
13397
+ badgeHeight,
13398
+ badgeRadius,
13399
+ "rgba(255,255,255,0.06)"
13400
+ );
13401
+ this._drawText(item.text, {
13402
+ color: "rgba(255,255,255,0.36)",
13403
+ left: this.isRTL(options) ? badgeLeft + badgeWidth - badgePaddingX : badgeLeft + badgePaddingX,
13404
+ top: badgeTop + badgeHeight / 2,
13405
+ fontSize: item.fontSize,
13406
+ fontWeight: item.fontWeight ?? 600,
13407
+ textBaseline: "middle",
13408
+ textAlign: this.inlineStartAlign(options),
13409
+ direction: this.textDirection(options)
13410
+ });
13411
+ return this.advanceCursor(options, cursor, badgeWidth);
13412
+ }
13351
13413
  };
13352
13414
 
13353
13415
  // src/services/painter/painter.ts
@@ -19136,20 +19198,39 @@ var useOrderEntry2 = (symbol, options = {}) => {
19136
19198
  symbolLeverage
19137
19199
  });
19138
19200
  const [estSlippage, setEstSlippage] = React.useState(null);
19201
+ const [bestAskBidSnapshot, setBestAskBidSnapshot] = React.useState([]);
19139
19202
  const [doCreateOrder, { isMutating }] = useMutation(
19140
19203
  getCreateOrderUrl(formattedOrder)
19141
19204
  );
19142
- const bestAskBid = askAndBid.current?.[0] || [];
19143
- const referencePriceFromOrder = bestAskBid.length >= 2 && formattedOrder.order_type && formattedOrder.side ? getOrderReferencePriceFromOrder(formattedOrder, bestAskBid) : null;
19205
+ const bestAskBid = bestAskBidSnapshot;
19206
+ const getReferencePriceForSide = (side) => {
19207
+ if (bestAskBid.length < 2 || !formattedOrder.order_type) {
19208
+ return null;
19209
+ }
19210
+ const referencePrice = getOrderReferencePriceFromOrder(
19211
+ {
19212
+ ...formattedOrder,
19213
+ side
19214
+ },
19215
+ bestAskBid
19216
+ );
19217
+ const slippage = Number(formattedOrder.slippage);
19218
+ if (effectiveMarginMode !== orderlyTypes.MarginMode.ISOLATED || side !== orderlyTypes.OrderSide.BUY || formattedOrder.order_type !== orderlyTypes.OrderType.MARKET || !referencePrice || !Number.isFinite(slippage) || slippage <= 0) {
19219
+ return referencePrice;
19220
+ }
19221
+ return new orderlyUtils.Decimal(referencePrice).mul(new orderlyUtils.Decimal(1).add(new orderlyUtils.Decimal(slippage).div(100))).toNumber();
19222
+ };
19223
+ const buyReferencePriceFromOrder = getReferencePriceForSide(orderlyTypes.OrderSide.BUY);
19224
+ const sellReferencePriceFromOrder = getReferencePriceForSide(orderlyTypes.OrderSide.SELL);
19144
19225
  const maxBuyQtyValue = useMaxQty(symbol, orderlyTypes.OrderSide.BUY, {
19145
19226
  reduceOnly: formattedOrder.reduce_only,
19146
19227
  marginMode: effectiveMarginMode,
19147
- currentOrderReferencePrice: referencePriceFromOrder && referencePriceFromOrder > 0 ? referencePriceFromOrder : void 0
19228
+ currentOrderReferencePrice: buyReferencePriceFromOrder && buyReferencePriceFromOrder > 0 ? buyReferencePriceFromOrder : void 0
19148
19229
  });
19149
19230
  const maxSellQtyValue = useMaxQty(symbol, orderlyTypes.OrderSide.SELL, {
19150
19231
  reduceOnly: formattedOrder.reduce_only,
19151
19232
  marginMode: effectiveMarginMode,
19152
- currentOrderReferencePrice: referencePriceFromOrder && referencePriceFromOrder > 0 ? referencePriceFromOrder : void 0
19233
+ currentOrderReferencePrice: sellReferencePriceFromOrder && sellReferencePriceFromOrder > 0 ? sellReferencePriceFromOrder : void 0
19153
19234
  });
19154
19235
  const maxQtyValue = formattedOrder.side === orderlyTypes.OrderSide.BUY ? maxBuyQtyValue : maxSellQtyValue;
19155
19236
  const maxQty = options.maxQty ?? maxQtyValue;
@@ -19241,6 +19322,10 @@ var useOrderEntry2 = (symbol, options = {}) => {
19241
19322
  React.useEffect(() => {
19242
19323
  updateOrderPrice();
19243
19324
  }, [formattedOrder.order_type_ext, formattedOrder.level]);
19325
+ React.useEffect(() => {
19326
+ askAndBid.current = [[]];
19327
+ setBestAskBidSnapshot([]);
19328
+ }, [symbol]);
19244
19329
  const onOrderBookUpdate = useDebounce.useDebouncedCallback((data) => {
19245
19330
  const parsedData = [
19246
19331
  [data.asks?.[data.asks.length - 1]?.[0], data.bids?.[0]?.[0]],
@@ -19250,6 +19335,10 @@ var useOrderEntry2 = (symbol, options = {}) => {
19250
19335
  [data.asks?.[data.asks.length - 5]?.[0], data.bids?.[4]?.[0]]
19251
19336
  ];
19252
19337
  askAndBid.current = parsedData;
19338
+ const nextBestAskBid = parsedData[0] || [];
19339
+ setBestAskBidSnapshot(
19340
+ (prev) => prev[0] === nextBestAskBid[0] && prev[1] === nextBestAskBid[1] ? prev : nextBestAskBid
19341
+ );
19253
19342
  updateOrderPriceByOrderBook();
19254
19343
  updateEstSlippage(data);
19255
19344
  }, 200);