@orderly.network/hooks 2.3.2 → 2.4.0

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.js CHANGED
@@ -61,9 +61,9 @@ var __export = (target, all) => {
61
61
  // src/version.ts
62
62
  if (typeof window !== "undefined") {
63
63
  window.__ORDERLY_VERSION__ = window.__ORDERLY_VERSION__ || {};
64
- window.__ORDERLY_VERSION__["@orderly.network/hooks"] = "2.3.2";
64
+ window.__ORDERLY_VERSION__["@orderly.network/hooks"] = "2.4.0";
65
65
  }
66
- var version_default = "2.3.2";
66
+ var version_default = "2.4.0";
67
67
  var fetcher = (url, init2 = {}, queryOptions) => net.get(url, init2, queryOptions?.formatter);
68
68
  var OrderlyContext = React.createContext({
69
69
  // configStore: new MemoryConfigStore(),
@@ -268,7 +268,8 @@ var useTrack = () => {
268
268
  page_title: title,
269
269
  page_url: url,
270
270
  page_domain: origin,
271
- user_agent: userAgent
271
+ user_agent: userAgent,
272
+ sdk_version: window?.__ORDERLY_VERSION__?.["@orderly.network/net"] ?? ""
272
273
  });
273
274
  if (eventName === types.TrackerEventName.placeOrderSuccess) {
274
275
  Object.assign(params, {
@@ -4200,7 +4201,7 @@ function fillChainsInfo(chains, filter, chainInfos) {
4200
4201
  return _chains;
4201
4202
  }
4202
4203
  function filterAndUpdateChains(chains, chainInfos, filter, isTestNet) {
4203
- const filterChains = [];
4204
+ const chainsMap = /* @__PURE__ */ new Map();
4204
4205
  chains.forEach((chain) => {
4205
4206
  const _chain = { ...chain };
4206
4207
  const networkInfo = chainInfos?.find(
@@ -4225,10 +4226,10 @@ function filterAndUpdateChains(chains, chainInfos, filter, isTestNet) {
4225
4226
  return;
4226
4227
  }
4227
4228
  if (networkInfo) {
4228
- filterChains.push(_chain);
4229
+ chainsMap.set(chain.network_infos.chain_id, _chain);
4229
4230
  }
4230
4231
  });
4231
- return filterChains;
4232
+ return Array.from(chainsMap.values());
4232
4233
  }
4233
4234
  function filterByAllowedChains(chains, allowedChains) {
4234
4235
  if (!allowedChains) {
@@ -4912,12 +4913,11 @@ var useSymbolPriceRange = (symbol, side, price) => {
4912
4913
  };
4913
4914
  function getMinNotional(props) {
4914
4915
  const { price, base_tick, qty, min_notional, base_dp, quote_dp, quote_tick } = props;
4915
- if (price !== void 0 && qty !== void 0 && min_notional !== void 0) {
4916
+ if (price && qty && min_notional) {
4916
4917
  try {
4917
- const calcNotional = new utils.Decimal(price).mul(new utils.Decimal(qty)).toNumber();
4918
- const notional = Number.parseFloat(`${min_notional}`);
4919
- if (calcNotional < notional) {
4920
- let minQty = new utils.Decimal(notional).div(price).toDecimalPlaces(base_dp, utils.Decimal.ROUND_DOWN).add(base_tick ?? 0);
4918
+ const calcMinNotional = new utils.Decimal(price).mul(new utils.Decimal(qty));
4919
+ if (calcMinNotional.lt(min_notional)) {
4920
+ let minQty = new utils.Decimal(min_notional).div(price).toDecimalPlaces(base_dp, utils.Decimal.ROUND_DOWN).add(base_tick ?? 0);
4921
4921
  if (base_tick && base_tick > 0) {
4922
4922
  minQty = new utils.Decimal(
4923
4923
  getRoundedDownDivision(minQty.toNumber(), base_tick)
@@ -4975,6 +4975,14 @@ var OrderValidation = class {
4975
4975
  return "TP price";
4976
4976
  case "sl_trigger_price":
4977
4977
  return "SL price";
4978
+ case "max_price":
4979
+ return "Upper price";
4980
+ case "min_price":
4981
+ return "Lower price";
4982
+ case "total_orders":
4983
+ return "Total orders";
4984
+ case "skew":
4985
+ return "Skew";
4978
4986
  default:
4979
4987
  return key;
4980
4988
  }
@@ -4999,6 +5007,14 @@ var OrderValidation = class {
4999
5007
  value
5000
5008
  };
5001
5009
  }
5010
+ static range(key, min3, max3) {
5011
+ return {
5012
+ type: "range",
5013
+ message: `${this.getLabel(key)} must be in the range of ${min3} to ${max3}`,
5014
+ min: min3,
5015
+ max: max3
5016
+ };
5017
+ }
5002
5018
  };
5003
5019
 
5004
5020
  // src/services/orderCreator/baseCreator.ts
@@ -5201,33 +5217,33 @@ var BaseOrderCreator = class {
5201
5217
  }
5202
5218
  };
5203
5219
 
5204
- // src/services/orderCreator/marketOrderCreator.ts
5205
- var MarketOrderCreator = class extends BaseOrderCreator {
5220
+ // src/services/orderCreator/bboOrderCreator.ts
5221
+ var BBOOrderCreator = class extends BaseOrderCreator {
5222
+ constructor() {
5223
+ super(...arguments);
5224
+ this.orderType = types.OrderType.LIMIT;
5225
+ }
5206
5226
  create(values2) {
5207
- const data = this.baseOrder(values2);
5208
- delete data["order_price"];
5209
- delete data["total"];
5210
- delete data["trigger_price"];
5211
- delete data["isStopOrder"];
5212
- return {
5213
- ...data
5227
+ const order = {
5228
+ ...this.baseOrder(values2),
5229
+ level: values2.level
5214
5230
  };
5231
+ return ramda.pick(
5232
+ [
5233
+ "symbol",
5234
+ "order_quantity",
5235
+ "visible_quantity",
5236
+ "reduce_only",
5237
+ "side",
5238
+ "order_type",
5239
+ "level"
5240
+ ],
5241
+ order
5242
+ );
5215
5243
  }
5216
- validate(values2, configs) {
5217
- return this.baseValidate(values2, configs).then((result) => {
5218
- const slippage = Number(values2.slippage);
5219
- const estSlippage = Number.isNaN(configs.estSlippage) ? 0 : Number(configs.estSlippage) * 100;
5220
- if (!isNaN(slippage) && estSlippage > slippage) {
5221
- return {
5222
- ...result,
5223
- slippage: {
5224
- type: "max",
5225
- message: "Estimated slippage exceeds your maximum allowed slippage.",
5226
- value: estSlippage
5227
- }
5228
- };
5229
- }
5230
- return result;
5244
+ async validate(values2, configs) {
5245
+ return this.baseValidate(values2, configs).then((errors) => {
5246
+ return errors;
5231
5247
  });
5232
5248
  }
5233
5249
  };
@@ -5306,124 +5322,791 @@ var LimitOrderCreator = class extends BaseOrderCreator {
5306
5322
  });
5307
5323
  }
5308
5324
  };
5309
- var { maxPrice: maxPrice2, minPrice: minPrice2, scopePrice: scopePrice2 } = perp.order;
5310
- var StopLimitOrderCreator = class extends BaseOrderCreator {
5311
- constructor() {
5312
- super(...arguments);
5313
- this.orderType = types.OrderType.STOP_LIMIT;
5325
+ async function bracketOrderValidator(values2, config) {
5326
+ const result = /* @__PURE__ */ Object.create(null);
5327
+ await Promise.resolve();
5328
+ const { tp_trigger_price, sl_trigger_price, side } = values2;
5329
+ const qty = Number(values2.quantity);
5330
+ const maxQty = config.maxQty;
5331
+ const type = values2.order_type;
5332
+ const { quote_max, quote_min, price_scope, quote_dp } = config.symbol ?? {};
5333
+ const mark_price = type === types.OrderType.MARKET ? config.markPrice : values2.order_price ? Number(values2.order_price) : void 0;
5334
+ if (!isNaN(qty) && qty > maxQty) {
5335
+ result.quantity = OrderValidation.max("quantity", config.maxQty);
5314
5336
  }
5315
- create(values2, config) {
5316
- this.totalToQuantity(values2, config);
5317
- const order = {
5318
- ...this.baseOrder(values2),
5319
- trigger_price: values2.trigger_price,
5320
- algo_type: types.AlgoOrderRootType.STOP,
5321
- type: types.OrderType.LIMIT,
5322
- quantity: values2["order_quantity"],
5323
- price: values2["order_price"],
5324
- trigger_price_type: types.TriggerPriceType.MARK_PRICE
5325
- };
5326
- return ramda.pick(
5327
- [
5328
- "symbol",
5329
- "trigger_price",
5330
- "algo_type",
5331
- "type",
5332
- "quantity",
5333
- "price",
5334
- "trigger_price_type",
5335
- "side",
5336
- "reduce_only",
5337
- "visible_quantity"
5338
- ],
5339
- order
5340
- );
5337
+ if (Number(tp_trigger_price) < 0) {
5338
+ result.tp_trigger_price = OrderValidation.min("tp_trigger_price", 0);
5341
5339
  }
5342
- validate(values2, config) {
5343
- return this.baseValidate(values2, config).then((errors) => {
5344
- const { order_price, trigger_price, side } = values2;
5345
- const { symbol } = config;
5346
- const { price_range, price_scope, quote_max, quote_min } = symbol;
5347
- if (!trigger_price) {
5348
- errors.trigger_price = OrderValidation.required("trigger_price");
5349
- }
5350
- if (!order_price) {
5351
- errors.order_price = OrderValidation.required("order_price");
5352
- }
5353
- if (trigger_price > quote_max) {
5354
- errors.trigger_price = OrderValidation.max("trigger_price", quote_max);
5355
- } else if (trigger_price < quote_min) {
5356
- errors.trigger_price = OrderValidation.min("trigger_price", quote_min);
5357
- } else {
5358
- if (trigger_price && order_price) {
5359
- const price = new utils.Decimal(order_price);
5360
- const maxPriceNumber = maxPrice2(trigger_price, price_range);
5361
- const minPriceNumber = minPrice2(trigger_price, price_range);
5362
- const scropePriceNumbere = scopePrice2(
5363
- trigger_price,
5364
- price_scope,
5365
- side
5366
- );
5367
- const priceRange = side === "BUY" ? {
5368
- min: scropePriceNumbere,
5369
- max: maxPriceNumber
5370
- } : {
5371
- min: minPriceNumber,
5372
- max: scropePriceNumbere
5373
- };
5374
- if (price.gt(quote_max)) {
5375
- errors.order_price = OrderValidation.max("order_price", quote_max);
5376
- } else {
5377
- if (price.gt(priceRange?.max)) {
5378
- errors.order_price = OrderValidation.max(
5379
- "order_price",
5380
- new utils.Decimal(priceRange.max).todp(symbol.quote_dp).toString()
5381
- );
5382
- }
5383
- }
5384
- if (price.lt(quote_min)) {
5385
- errors.order_price = OrderValidation.min("order_price", quote_min);
5386
- } else {
5387
- if (price.lt(priceRange?.min)) {
5388
- errors.order_price = OrderValidation.min(
5389
- "order_price",
5390
- new utils.Decimal(priceRange.min).todp(symbol.quote_dp).toString()
5391
- );
5392
- }
5393
- }
5394
- }
5395
- }
5396
- return errors;
5397
- });
5340
+ if (Number(sl_trigger_price) < 0) {
5341
+ result.sl_trigger_price = OrderValidation.min("sl_trigger_price", 0);
5398
5342
  }
5399
- };
5343
+ if (side === types.OrderSide.BUY && mark_price) {
5344
+ const slTriggerPriceScope = new utils.Decimal(mark_price * (1 - price_scope)).toDecimalPlaces(quote_dp, utils.Decimal.ROUND_DOWN).toNumber();
5345
+ if (!!sl_trigger_price && Number(sl_trigger_price) < slTriggerPriceScope) {
5346
+ result.sl_trigger_price = OrderValidation.min(
5347
+ "sl_trigger_price",
5348
+ slTriggerPriceScope
5349
+ );
5350
+ }
5351
+ if (!!tp_trigger_price && Number(tp_trigger_price) <= mark_price) {
5352
+ result.tp_trigger_price = OrderValidation.min(
5353
+ "tp_trigger_price",
5354
+ mark_price
5355
+ );
5356
+ }
5357
+ if (!!tp_trigger_price && Number(tp_trigger_price) > quote_max) {
5358
+ result.tp_trigger_price = OrderValidation.max(
5359
+ "tp_trigger_price",
5360
+ quote_max
5361
+ );
5362
+ }
5363
+ if (!!sl_trigger_price && Number(sl_trigger_price) < quote_min) {
5364
+ result.sl_trigger_price = OrderValidation.min(
5365
+ "sl_trigger_price",
5366
+ quote_min
5367
+ );
5368
+ }
5369
+ }
5370
+ if (side === types.OrderSide.SELL && mark_price) {
5371
+ const slTriggerPriceScope = new utils.Decimal(mark_price * (1 + price_scope)).toDecimalPlaces(quote_dp, utils.Decimal.ROUND_DOWN).toNumber();
5372
+ if (!!sl_trigger_price && Number(sl_trigger_price) > slTriggerPriceScope) {
5373
+ result.sl_trigger_price = OrderValidation.max(
5374
+ "sl_trigger_price",
5375
+ slTriggerPriceScope
5376
+ );
5377
+ }
5378
+ if (!!tp_trigger_price && Number(tp_trigger_price) >= mark_price) {
5379
+ result.tp_trigger_price = OrderValidation.max(
5380
+ "tp_trigger_price",
5381
+ mark_price
5382
+ );
5383
+ }
5384
+ if (!!tp_trigger_price && Number(tp_trigger_price) > quote_max) {
5385
+ result.tp_trigger_price = OrderValidation.max(
5386
+ "tp_trigger_price",
5387
+ quote_max
5388
+ );
5389
+ }
5390
+ if (!!sl_trigger_price && Number(sl_trigger_price) < quote_min) {
5391
+ result.sl_trigger_price = OrderValidation.min(
5392
+ "sl_trigger_price",
5393
+ quote_min
5394
+ );
5395
+ }
5396
+ }
5397
+ return Object.keys(result).length > 0 ? result : null;
5398
+ }
5400
5399
 
5401
- // src/services/orderCreator/generalCreator.ts
5402
- var GeneralOrderCreator = class extends BaseOrderCreator {
5403
- create(data) {
5400
+ // src/services/orderCreator/bracketLimitOrderCreator.ts
5401
+ var BracketLimitOrderCreator = class extends LimitOrderCreator {
5402
+ // orderType: OrderType;
5403
+ create(values2, config) {
5404
+ const order = super.create(values2, config);
5404
5405
  return {
5405
- ...this.baseOrder(data),
5406
- order_price: data.order_price,
5407
- order_quantity: data.order_quantity
5406
+ ...order,
5407
+ quantity: order.order_quantity,
5408
+ type: order.order_type,
5409
+ price: order.order_price
5408
5410
  };
5409
5411
  }
5410
- validate(values2, configs) {
5411
- return super.baseValidate(values2, configs);
5412
+ async validate(values2, config) {
5413
+ const value = await super.validate(values2, config);
5414
+ const bracketData = await bracketOrderValidator(values2, config);
5415
+ return { ...value, ...bracketData };
5412
5416
  }
5413
5417
  };
5414
- var StopMarketOrderCreator = class extends BaseOrderCreator {
5418
+
5419
+ // src/services/orderCreator/marketOrderCreator.ts
5420
+ var MarketOrderCreator = class extends BaseOrderCreator {
5415
5421
  create(values2) {
5416
- const order = {
5417
- ...this.baseOrder(values2),
5418
- // order_price: values.order_price,
5419
- trigger_price: values2.trigger_price,
5420
- algo_type: types.AlgoOrderRootType.STOP,
5421
- type: types.OrderType.MARKET,
5422
- quantity: values2["order_quantity"],
5423
- // price: values["order_price"],
5424
- trigger_price_type: types.TriggerPriceType.MARK_PRICE
5422
+ const data = this.baseOrder(values2);
5423
+ delete data["order_price"];
5424
+ delete data["total"];
5425
+ delete data["trigger_price"];
5426
+ delete data["isStopOrder"];
5427
+ return {
5428
+ ...data
5425
5429
  };
5426
- return ramda.pick(
5430
+ }
5431
+ validate(values2, configs) {
5432
+ return this.baseValidate(values2, configs).then((result) => {
5433
+ const slippage = Number(values2.slippage);
5434
+ const estSlippage = Number.isNaN(configs.estSlippage) ? 0 : Number(configs.estSlippage) * 100;
5435
+ if (!isNaN(slippage) && estSlippage > slippage) {
5436
+ return {
5437
+ ...result,
5438
+ slippage: {
5439
+ type: "max",
5440
+ message: "Estimated slippage exceeds your maximum allowed slippage.",
5441
+ value: estSlippage
5442
+ }
5443
+ };
5444
+ }
5445
+ return result;
5446
+ });
5447
+ }
5448
+ };
5449
+
5450
+ // src/services/orderCreator/bracketMarketOrderCreator.ts
5451
+ var BracketMarketOrderCreator = class extends MarketOrderCreator {
5452
+ constructor() {
5453
+ super(...arguments);
5454
+ this.orderType = types.OrderType.MARKET;
5455
+ }
5456
+ create(values2) {
5457
+ const order = super.create(values2);
5458
+ return {
5459
+ ...order,
5460
+ quantity: order.order_quantity,
5461
+ type: order.order_type,
5462
+ price: order.order_price
5463
+ };
5464
+ }
5465
+ async validate(values2, config) {
5466
+ const value = await super.validate(values2, config);
5467
+ const bracketData = await bracketOrderValidator(values2, config);
5468
+ return { ...value, ...bracketData };
5469
+ }
5470
+ };
5471
+
5472
+ // src/services/orderCreator/fokCreator.ts
5473
+ var FOKOrderCreator = class extends LimitOrderCreator {
5474
+ };
5475
+
5476
+ // src/services/orderCreator/generalCreator.ts
5477
+ var GeneralOrderCreator = class extends BaseOrderCreator {
5478
+ create(data) {
5479
+ return {
5480
+ ...this.baseOrder(data),
5481
+ order_price: data.order_price,
5482
+ order_quantity: data.order_quantity
5483
+ };
5484
+ }
5485
+ validate(values2, configs) {
5486
+ return super.baseValidate(values2, configs);
5487
+ }
5488
+ };
5489
+
5490
+ // src/services/orderCreator/iocCreator.ts
5491
+ var IOCOrderCreator = class extends LimitOrderCreator {
5492
+ };
5493
+
5494
+ // src/services/orderCreator/postOnlyCreator.ts
5495
+ var PostOnlyOrderCreator = class extends LimitOrderCreator {
5496
+ };
5497
+ var getCreateOrderUrl = (order) => {
5498
+ const isAlgoOrder = order?.order_type === types.OrderType.STOP_LIMIT || order?.order_type === types.OrderType.STOP_MARKET || order?.order_type === types.OrderType.CLOSE_POSITION || order.algo_type && order.algo_type === types.AlgoOrderRootType.BRACKET || isBracketOrder(order);
5499
+ if (order.order_type === types.OrderType.SCALED) {
5500
+ return "/v1/batch-order";
5501
+ }
5502
+ return isAlgoOrder ? "/v1/algo/order" : "/v1/order";
5503
+ };
5504
+ var getOrderCreator = (order) => {
5505
+ let type;
5506
+ if (isBracketOrder(order)) {
5507
+ type = `${types.AlgoOrderRootType.BRACKET}:${order.order_type}`;
5508
+ } else if (order.order_type === types.OrderType.LIMIT) {
5509
+ type = order.order_type_ext || order.order_type;
5510
+ } else {
5511
+ type = order.order_type;
5512
+ }
5513
+ return OrderFactory.create(type);
5514
+ };
5515
+ var tpslFields = [
5516
+ "tp_trigger_price",
5517
+ "sl_trigger_price",
5518
+ "tp_pnl",
5519
+ "sl_pnl",
5520
+ "tp_offset",
5521
+ "sl_offset",
5522
+ "tp_offset_percentage",
5523
+ "sl_offset_percentage"
5524
+ ];
5525
+ var isBracketOrder = (order) => {
5526
+ return !!order.tp_trigger_price || !!order.sl_trigger_price;
5527
+ };
5528
+ var hasTPSL = (order) => {
5529
+ return tpslFields.some((field) => !!order[field]);
5530
+ };
5531
+ function getOrderPrice(order, askAndBid) {
5532
+ const orderPrice = Number(order.order_price);
5533
+ if (order.order_type === types.OrderType.MARKET || order.order_type === types.OrderType.STOP_MARKET) {
5534
+ if (order.side === types.OrderSide.BUY) {
5535
+ return askAndBid[0];
5536
+ } else {
5537
+ return askAndBid[1];
5538
+ }
5539
+ } else {
5540
+ if (order.side === types.OrderSide.BUY) {
5541
+ if (orderPrice >= askAndBid[0]) {
5542
+ return askAndBid[0];
5543
+ } else {
5544
+ return orderPrice;
5545
+ }
5546
+ } else {
5547
+ if (orderPrice <= askAndBid[1]) {
5548
+ return askAndBid[1];
5549
+ } else {
5550
+ return orderPrice;
5551
+ }
5552
+ }
5553
+ }
5554
+ }
5555
+ var getPriceAndQty = (order, symbolInfo, askAndBid) => {
5556
+ let quantity = Number(order.order_quantity);
5557
+ const orderPrice = Number(order.order_price);
5558
+ if (isNaN(quantity) || quantity <= 0) {
5559
+ return null;
5560
+ }
5561
+ if (askAndBid.length === 0) {
5562
+ return null;
5563
+ }
5564
+ if ((order.order_type === types.OrderType.LIMIT || order.order_type === types.OrderType.STOP_LIMIT) && isNaN(orderPrice)) {
5565
+ return null;
5566
+ }
5567
+ let price;
5568
+ if (order.order_type === types.OrderType.SCALED) {
5569
+ price = calcScaledOrderAvgOrderPrice(order, symbolInfo, askAndBid);
5570
+ const orders = calcScaledOrderBatchBody(order, symbolInfo);
5571
+ const sumQtys = orders.reduce((acc, order2) => {
5572
+ return acc.plus(new utils.Decimal(order2.order_quantity));
5573
+ }, utils.zero);
5574
+ quantity = sumQtys.todp(symbolInfo.base_dp).toNumber();
5575
+ if (!quantity || isNaN(quantity)) {
5576
+ return null;
5577
+ }
5578
+ } else {
5579
+ price = getOrderPrice(order, askAndBid);
5580
+ }
5581
+ if (!price || isNaN(price)) {
5582
+ return null;
5583
+ }
5584
+ if (order.side === types.OrderSide.SELL) {
5585
+ quantity = -quantity;
5586
+ }
5587
+ return { price, quantity };
5588
+ };
5589
+ var calcEstLiqPrice = (order, askAndBid, inputs) => {
5590
+ const { symbolInfo } = inputs;
5591
+ const result = getPriceAndQty(order, symbolInfo, askAndBid);
5592
+ if (!result)
5593
+ return null;
5594
+ const { price, quantity } = result;
5595
+ if (!price || !quantity)
5596
+ return null;
5597
+ const {
5598
+ symbol,
5599
+ imr_factor,
5600
+ markPrice,
5601
+ totalCollateral,
5602
+ futures_taker_fee_rate,
5603
+ positions: positions3
5604
+ } = inputs;
5605
+ const orderFee = perp.order.orderFee({
5606
+ qty: quantity,
5607
+ price,
5608
+ futuresTakeFeeRate: Number(futures_taker_fee_rate) / 1e4
5609
+ });
5610
+ const liqPrice = perp.order.estLiqPrice({
5611
+ markPrice,
5612
+ baseIMR: symbolInfo.base_imr,
5613
+ baseMMR: symbolInfo.base_mmr,
5614
+ totalCollateral,
5615
+ positions: positions3 == null ? [] : positions3,
5616
+ IMR_Factor: imr_factor,
5617
+ orderFee,
5618
+ newOrder: {
5619
+ qty: quantity,
5620
+ price,
5621
+ symbol
5622
+ }
5623
+ });
5624
+ if (liqPrice <= 0)
5625
+ return null;
5626
+ return liqPrice;
5627
+ };
5628
+ var calcEstLeverage = (order, askAndBid, inputs) => {
5629
+ const { totalCollateral, positions: positions3, symbol, symbolInfo } = inputs;
5630
+ const result = getPriceAndQty(order, symbolInfo, askAndBid);
5631
+ if (!result)
5632
+ return null;
5633
+ const { price, quantity } = result;
5634
+ if (!price || !quantity)
5635
+ return null;
5636
+ return perp.order.estLeverage({
5637
+ totalCollateral,
5638
+ positions: positions3,
5639
+ newOrder: {
5640
+ symbol,
5641
+ qty: result.quantity,
5642
+ price: result.price
5643
+ }
5644
+ });
5645
+ };
5646
+ function isBBOOrder(options) {
5647
+ const { order_type, order_type_ext } = options;
5648
+ return order_type === types.OrderType.LIMIT && [types.OrderType.ASK, types.OrderType.BID].includes(order_type_ext);
5649
+ }
5650
+ function calcScaledOrderPrices(inputs) {
5651
+ const { min_price, max_price, total_orders, quote_dp } = inputs;
5652
+ if (!min_price || !max_price || !total_orders) {
5653
+ return [];
5654
+ }
5655
+ const minPrice3 = new utils.Decimal(min_price);
5656
+ const maxPrice3 = new utils.Decimal(max_price);
5657
+ const totalOrders = Number(total_orders);
5658
+ const priceStep = maxPrice3.minus(minPrice3).div(totalOrders - 1);
5659
+ const prices = [];
5660
+ for (let i = 0; i < totalOrders; i++) {
5661
+ prices[i] = minPrice3.plus(priceStep.mul(i)).todp(quote_dp).toString();
5662
+ }
5663
+ return prices;
5664
+ }
5665
+ function getScaledOrderSkew(inputs) {
5666
+ const { skew, distribution_type, total_orders } = inputs;
5667
+ if (distribution_type === types.DistributionType.FLAT) {
5668
+ return 1;
5669
+ } else if (distribution_type === types.DistributionType.ASCENDING) {
5670
+ return total_orders;
5671
+ } else if (distribution_type === types.DistributionType.DESCENDING) {
5672
+ return 1 / total_orders;
5673
+ }
5674
+ return skew;
5675
+ }
5676
+ function calcScaledOrderWeights(inputs) {
5677
+ const { total_orders, distribution_type, skew } = inputs;
5678
+ const weights = [];
5679
+ if (!total_orders || !distribution_type || distribution_type === types.DistributionType.CUSTOM && (!skew || skew <= 0 || skew > 100)) {
5680
+ return {
5681
+ weights: [],
5682
+ sumWeights: 0,
5683
+ minWeight: 0
5684
+ };
5685
+ }
5686
+ const totalOrders = Number(total_orders);
5687
+ const skewNum = getScaledOrderSkew({
5688
+ skew,
5689
+ distribution_type,
5690
+ total_orders: totalOrders
5691
+ });
5692
+ for (let i = 0; i < totalOrders; i++) {
5693
+ weights[i] = 1 + (skewNum - 1) * i / (totalOrders - 1);
5694
+ }
5695
+ const sumWeights = weights.reduce((acc, cur) => acc + cur, 0);
5696
+ const minWeight = weights.reduce(
5697
+ (min3, current) => current < min3 ? current : min3,
5698
+ weights?.[0]
5699
+ );
5700
+ return {
5701
+ weights,
5702
+ sumWeights,
5703
+ minWeight
5704
+ };
5705
+ }
5706
+ function calcScaledOrderQtys(inputs) {
5707
+ const {
5708
+ order_quantity = 0,
5709
+ total_orders = 0,
5710
+ distribution_type,
5711
+ skew,
5712
+ base_dp,
5713
+ base_tick
5714
+ } = inputs;
5715
+ const qtys = [];
5716
+ if (!order_quantity || !total_orders) {
5717
+ return [];
5718
+ }
5719
+ const { weights, sumWeights } = calcScaledOrderWeights({
5720
+ total_orders,
5721
+ distribution_type,
5722
+ skew
5723
+ });
5724
+ for (let i = 0; i < total_orders; i++) {
5725
+ let qty = new utils.Decimal(order_quantity).mul(weights[i]).div(sumWeights);
5726
+ if (base_tick > 1) {
5727
+ qty = qty.div(base_tick).todp(0, utils.Decimal.ROUND_DOWN).mul(base_tick);
5728
+ } else {
5729
+ qty = qty.todp(base_dp);
5730
+ }
5731
+ qtys[i] = qty.toString();
5732
+ }
5733
+ return qtys;
5734
+ }
5735
+ function calcScaledOrderBatchBody(order, symbolInfo) {
5736
+ if (!validateScaledOrderInput(order)) {
5737
+ return [];
5738
+ }
5739
+ try {
5740
+ const { base_dp, quote_dp, base_tick } = symbolInfo;
5741
+ const {
5742
+ symbol,
5743
+ side,
5744
+ order_quantity,
5745
+ min_price,
5746
+ max_price,
5747
+ total_orders,
5748
+ distribution_type,
5749
+ skew,
5750
+ reduce_only,
5751
+ visible_quantity
5752
+ } = order;
5753
+ const prices = calcScaledOrderPrices({
5754
+ min_price,
5755
+ max_price,
5756
+ total_orders,
5757
+ quote_dp
5758
+ });
5759
+ const qtys = calcScaledOrderQtys({
5760
+ side,
5761
+ order_quantity,
5762
+ total_orders,
5763
+ distribution_type,
5764
+ skew,
5765
+ base_dp,
5766
+ base_tick
5767
+ });
5768
+ const now = Date.now();
5769
+ const orders = prices.map((price, index) => {
5770
+ const subOrder = {
5771
+ symbol,
5772
+ side,
5773
+ // this order type is scaled order, so we need to set the order type to limit
5774
+ order_type: types.OrderType.LIMIT,
5775
+ order_quantity: qtys[index],
5776
+ order_price: price,
5777
+ reduce_only,
5778
+ // it will be used for identify the scaled order from ws
5779
+ client_order_id: `scaled_${index}_${now}`
5780
+ };
5781
+ if (visible_quantity === 0) {
5782
+ subOrder.visible_quantity = visible_quantity;
5783
+ }
5784
+ return subOrder;
5785
+ });
5786
+ return orders;
5787
+ } catch (error) {
5788
+ return [];
5789
+ }
5790
+ }
5791
+ function calcScaledOrderAvgOrderPrice(order, symbolInfo, askAndBid) {
5792
+ if (!validateScaledOrderInput(order)) {
5793
+ return null;
5794
+ }
5795
+ try {
5796
+ const orders = calcScaledOrderBatchBody(order, symbolInfo);
5797
+ const sumQtys = orders.reduce((acc, order2) => {
5798
+ return acc.plus(new utils.Decimal(order2.order_quantity));
5799
+ }, utils.zero);
5800
+ const totalNational = orders.reduce((acc, order2) => {
5801
+ const orderPrice = getOrderPrice(order2, askAndBid);
5802
+ return acc.plus(new utils.Decimal(orderPrice).mul(order2.order_quantity));
5803
+ }, utils.zero);
5804
+ return totalNational.div(sumQtys).todp(symbolInfo.quote_dp).toNumber();
5805
+ } catch (error) {
5806
+ return null;
5807
+ }
5808
+ }
5809
+ function validateScaledOrderInput(order) {
5810
+ const {
5811
+ min_price,
5812
+ max_price,
5813
+ order_quantity,
5814
+ total_orders,
5815
+ distribution_type,
5816
+ skew
5817
+ } = order;
5818
+ if (!min_price || !max_price || !order_quantity || !total_orders || !distribution_type || distribution_type === types.DistributionType.CUSTOM && (!skew || skew <= 0 || skew > 100) || total_orders < 2 || total_orders > 20) {
5819
+ return false;
5820
+ }
5821
+ return true;
5822
+ }
5823
+ function calcScaledOrderMinTotalAmount(order, symbolInfo, askAndBid) {
5824
+ try {
5825
+ const minTotalAmount_baseMin = calcScaledOrderMinTotalAmountByBaseMin(
5826
+ order,
5827
+ symbolInfo
5828
+ );
5829
+ const minTotalAmount_minNotional = calcScaledOrderMinTotalAmountByMinNotional(order, symbolInfo, askAndBid);
5830
+ const minTotalAmount = Math.max(
5831
+ minTotalAmount_baseMin,
5832
+ minTotalAmount_minNotional
5833
+ );
5834
+ return minTotalAmount;
5835
+ } catch (error) {
5836
+ return null;
5837
+ }
5838
+ }
5839
+ function calcScaledOrderMinTotalAmountByBaseMin(order, symbolInfo) {
5840
+ const { total_orders, distribution_type, skew } = order;
5841
+ const { base_min, base_dp } = symbolInfo;
5842
+ const { sumWeights, minWeight } = calcScaledOrderWeights({
5843
+ total_orders,
5844
+ distribution_type,
5845
+ skew
5846
+ });
5847
+ const minTotalAmount = new utils.Decimal(base_min).mul(new utils.Decimal(sumWeights).div(minWeight)).todp(base_dp, utils.Decimal.ROUND_UP).toNumber();
5848
+ return minTotalAmount;
5849
+ }
5850
+ function calcScaledOrderMinTotalAmountByMinNotional(order, symbolInfo, askAndBid) {
5851
+ const { base_dp, min_notional } = symbolInfo;
5852
+ const orders = calcScaledOrderBatchBody(order, symbolInfo);
5853
+ const { total_orders, distribution_type, skew } = order;
5854
+ const { weights, sumWeights } = calcScaledOrderWeights({
5855
+ total_orders,
5856
+ distribution_type,
5857
+ skew
5858
+ });
5859
+ const minQtys = orders.map((order2, i) => {
5860
+ const orderPrice = getOrderPrice(order2, askAndBid);
5861
+ return new utils.Decimal(min_notional).mul(sumWeights).div(new utils.Decimal(weights[i]).mul(orderPrice));
5862
+ });
5863
+ const max_minQty = minQtys.reduce(
5864
+ (max3, current) => current.gt(max3) ? current : max3,
5865
+ minQtys?.[0]
5866
+ );
5867
+ return max_minQty.todp(base_dp, utils.Decimal.ROUND_UP).toNumber();
5868
+ }
5869
+
5870
+ // src/services/orderCreator/scaledOrderCreator.ts
5871
+ var ScaledOrderCreator = class extends BaseOrderCreator {
5872
+ constructor() {
5873
+ super(...arguments);
5874
+ this.orderType = types.OrderType.SCALED;
5875
+ }
5876
+ create(values2, config) {
5877
+ const orders = calcScaledOrderBatchBody(values2, config.symbol);
5878
+ const { total_orders, distribution_type, skew } = values2;
5879
+ const order = {
5880
+ ...this.baseOrder(values2),
5881
+ total_orders,
5882
+ distribution_type,
5883
+ skew,
5884
+ orders
5885
+ };
5886
+ return ramda.pick(
5887
+ [
5888
+ "symbol",
5889
+ "order_quantity",
5890
+ "visible_quantity",
5891
+ "reduce_only",
5892
+ "side",
5893
+ "order_type",
5894
+ "orders",
5895
+ "total_orders",
5896
+ "distribution_type",
5897
+ "skew"
5898
+ ],
5899
+ order
5900
+ );
5901
+ }
5902
+ validatePrice(values2, config) {
5903
+ const errors = {};
5904
+ const { side, min_price, max_price } = values2;
5905
+ const { price_range, price_scope, quote_max, quote_min, quote_dp } = config.symbol;
5906
+ const maxPriceNumber = perp.order.maxPrice(config.markPrice, price_range);
5907
+ const minPriceNumber = perp.order.minPrice(config.markPrice, price_range);
5908
+ const scopePriceNumber = perp.order.scopePrice(
5909
+ config.markPrice,
5910
+ price_scope,
5911
+ side
5912
+ );
5913
+ const priceRange = side === types.OrderSide.BUY ? {
5914
+ min: scopePriceNumber,
5915
+ max: maxPriceNumber
5916
+ } : {
5917
+ min: minPriceNumber,
5918
+ max: scopePriceNumber
5919
+ };
5920
+ const minPrice3 = Number(min_price || 0);
5921
+ const maxPrice3 = Number(max_price || 0);
5922
+ if (!min_price) {
5923
+ errors.min_price = OrderValidation.required("min_price");
5924
+ } else {
5925
+ if (minPrice3 < priceRange?.min) {
5926
+ errors.min_price = OrderValidation.min(
5927
+ "min_price",
5928
+ new utils.Decimal(priceRange.min).todp(quote_dp).toString()
5929
+ );
5930
+ } else if (minPrice3 < quote_min) {
5931
+ errors.min_price = OrderValidation.min("min_price", quote_min);
5932
+ } else if (minPrice3 > maxPrice3) {
5933
+ errors.min_price = OrderValidation.max("min_price", max_price);
5934
+ }
5935
+ }
5936
+ if (!max_price) {
5937
+ errors.max_price = OrderValidation.required("max_price");
5938
+ } else {
5939
+ if (maxPrice3 < priceRange?.min) {
5940
+ errors.max_price = OrderValidation.min(
5941
+ "max_price",
5942
+ new utils.Decimal(priceRange.min).todp(quote_dp).toString()
5943
+ );
5944
+ } else if (maxPrice3 > priceRange?.max) {
5945
+ errors.max_price = OrderValidation.max(
5946
+ "max_price",
5947
+ new utils.Decimal(priceRange.max).todp(quote_dp).toString()
5948
+ );
5949
+ } else if (maxPrice3 > quote_max) {
5950
+ errors.max_price = OrderValidation.max("max_price", quote_max);
5951
+ }
5952
+ }
5953
+ return errors;
5954
+ }
5955
+ async validate(values2, config) {
5956
+ const { base_dp } = config.symbol;
5957
+ const { maxQty, askAndBid } = config;
5958
+ const { order_quantity, total_orders, distribution_type, skew } = values2;
5959
+ const errors = this.validatePrice(values2, config);
5960
+ if (!total_orders) {
5961
+ errors.total_orders = OrderValidation.required("total_orders");
5962
+ } else {
5963
+ const totalOrdersNum = Number(total_orders);
5964
+ if (totalOrdersNum < 2 || totalOrdersNum > 20) {
5965
+ errors.total_orders = OrderValidation.range("total_orders", 2, 20);
5966
+ }
5967
+ }
5968
+ if (distribution_type === types.DistributionType.CUSTOM) {
5969
+ if (!skew) {
5970
+ errors.skew = OrderValidation.required("skew");
5971
+ } else {
5972
+ const skewNum = Number(skew);
5973
+ if (skewNum <= 0) {
5974
+ errors.skew = OrderValidation.min("skew", 0);
5975
+ } else if (skewNum > 100) {
5976
+ errors.skew = OrderValidation.max("skew", 100);
5977
+ }
5978
+ }
5979
+ }
5980
+ if (!order_quantity) {
5981
+ errors.order_quantity = OrderValidation.required("order_quantity");
5982
+ } else {
5983
+ const qty = new utils.Decimal(order_quantity);
5984
+ if (qty.gt(maxQty)) {
5985
+ errors.order_quantity = OrderValidation.max(
5986
+ "order_quantity",
5987
+ new utils.Decimal(maxQty).todp(base_dp).toString()
5988
+ );
5989
+ } else if (!errors.skew && !errors.total_orders) {
5990
+ const minTotalAmount = calcScaledOrderMinTotalAmount(
5991
+ values2,
5992
+ config.symbol,
5993
+ askAndBid
5994
+ );
5995
+ if (minTotalAmount && qty.lt(minTotalAmount)) {
5996
+ errors.order_quantity = OrderValidation.min(
5997
+ "order_quantity",
5998
+ minTotalAmount
5999
+ );
6000
+ }
6001
+ }
6002
+ }
6003
+ return errors;
6004
+ }
6005
+ };
6006
+ var { maxPrice: maxPrice2, minPrice: minPrice2, scopePrice: scopePrice2 } = perp.order;
6007
+ var StopLimitOrderCreator = class extends BaseOrderCreator {
6008
+ constructor() {
6009
+ super(...arguments);
6010
+ this.orderType = types.OrderType.STOP_LIMIT;
6011
+ }
6012
+ create(values2, config) {
6013
+ this.totalToQuantity(values2, config);
6014
+ const order = {
6015
+ ...this.baseOrder(values2),
6016
+ trigger_price: values2.trigger_price,
6017
+ algo_type: types.AlgoOrderRootType.STOP,
6018
+ type: types.OrderType.LIMIT,
6019
+ quantity: values2["order_quantity"],
6020
+ price: values2["order_price"],
6021
+ trigger_price_type: types.TriggerPriceType.MARK_PRICE
6022
+ };
6023
+ return ramda.pick(
6024
+ [
6025
+ "symbol",
6026
+ "trigger_price",
6027
+ "algo_type",
6028
+ "type",
6029
+ "quantity",
6030
+ "price",
6031
+ "trigger_price_type",
6032
+ "side",
6033
+ "reduce_only",
6034
+ "visible_quantity"
6035
+ ],
6036
+ order
6037
+ );
6038
+ }
6039
+ validate(values2, config) {
6040
+ return this.baseValidate(values2, config).then((errors) => {
6041
+ const { order_price, trigger_price, side } = values2;
6042
+ const { symbol } = config;
6043
+ const { price_range, price_scope, quote_max, quote_min } = symbol;
6044
+ if (!trigger_price) {
6045
+ errors.trigger_price = OrderValidation.required("trigger_price");
6046
+ }
6047
+ if (!order_price) {
6048
+ errors.order_price = OrderValidation.required("order_price");
6049
+ }
6050
+ if (trigger_price > quote_max) {
6051
+ errors.trigger_price = OrderValidation.max("trigger_price", quote_max);
6052
+ } else if (trigger_price < quote_min) {
6053
+ errors.trigger_price = OrderValidation.min("trigger_price", quote_min);
6054
+ } else {
6055
+ if (trigger_price && order_price) {
6056
+ const price = new utils.Decimal(order_price);
6057
+ const maxPriceNumber = maxPrice2(trigger_price, price_range);
6058
+ const minPriceNumber = minPrice2(trigger_price, price_range);
6059
+ const scropePriceNumbere = scopePrice2(
6060
+ trigger_price,
6061
+ price_scope,
6062
+ side
6063
+ );
6064
+ const priceRange = side === "BUY" ? {
6065
+ min: scropePriceNumbere,
6066
+ max: maxPriceNumber
6067
+ } : {
6068
+ min: minPriceNumber,
6069
+ max: scropePriceNumbere
6070
+ };
6071
+ if (price.gt(quote_max)) {
6072
+ errors.order_price = OrderValidation.max("order_price", quote_max);
6073
+ } else {
6074
+ if (price.gt(priceRange?.max)) {
6075
+ errors.order_price = OrderValidation.max(
6076
+ "order_price",
6077
+ new utils.Decimal(priceRange.max).todp(symbol.quote_dp).toString()
6078
+ );
6079
+ }
6080
+ }
6081
+ if (price.lt(quote_min)) {
6082
+ errors.order_price = OrderValidation.min("order_price", quote_min);
6083
+ } else {
6084
+ if (price.lt(priceRange?.min)) {
6085
+ errors.order_price = OrderValidation.min(
6086
+ "order_price",
6087
+ new utils.Decimal(priceRange.min).todp(symbol.quote_dp).toString()
6088
+ );
6089
+ }
6090
+ }
6091
+ }
6092
+ }
6093
+ return errors;
6094
+ });
6095
+ }
6096
+ };
6097
+ var StopMarketOrderCreator = class extends BaseOrderCreator {
6098
+ create(values2) {
6099
+ const order = {
6100
+ ...this.baseOrder(values2),
6101
+ // order_price: values.order_price,
6102
+ trigger_price: values2.trigger_price,
6103
+ algo_type: types.AlgoOrderRootType.STOP,
6104
+ type: types.OrderType.MARKET,
6105
+ quantity: values2["order_quantity"],
6106
+ // price: values["order_price"],
6107
+ trigger_price_type: types.TriggerPriceType.MARK_PRICE
6108
+ };
6109
+ return ramda.pick(
5427
6110
  [
5428
6111
  "symbol",
5429
6112
  "trigger_price",
@@ -5456,18 +6139,6 @@ var StopMarketOrderCreator = class extends BaseOrderCreator {
5456
6139
  });
5457
6140
  }
5458
6141
  };
5459
-
5460
- // src/services/orderCreator/postOnlyCreator.ts
5461
- var PostOnlyOrderCreator = class extends LimitOrderCreator {
5462
- };
5463
-
5464
- // src/services/orderCreator/fokCreator.ts
5465
- var FOKOrderCreator = class extends LimitOrderCreator {
5466
- };
5467
-
5468
- // src/services/orderCreator/iocCreator.ts
5469
- var IOCOrderCreator = class extends LimitOrderCreator {
5470
- };
5471
6142
  var BaseAlgoOrderCreator = class {
5472
6143
  /**
5473
6144
  * base validate
@@ -5671,216 +6342,58 @@ var TPSLPositionOrderCreator = class extends BaseAlgoOrderCreator {
5671
6342
  type: types.OrderType.CLOSE_POSITION,
5672
6343
  trigger_price: tp_trigger_price,
5673
6344
  trigger_price_type: types.TriggerPriceType.MARK_PRICE,
5674
- symbol: values2.symbol,
5675
- is_activated: !!values2.tp_trigger_price
5676
- });
5677
- }
5678
- if (typeof values2.sl_trigger_price !== "undefined") {
5679
- const sl_trigger_price = !!values2.sl_trigger_price ? new utils.Decimal(values2.sl_trigger_price).todp(config.symbol.quote_dp).toNumber() : values2.sl_trigger_price;
5680
- child_orders.push({
5681
- algo_type: types.AlgoOrderType.STOP_LOSS,
5682
- reduce_only: true,
5683
- side,
5684
- type: types.OrderType.CLOSE_POSITION,
5685
- trigger_price: sl_trigger_price,
5686
- trigger_price_type: types.TriggerPriceType.MARK_PRICE,
5687
- symbol: values2.symbol,
5688
- is_activated: !!values2.sl_trigger_price
5689
- });
5690
- }
5691
- return {
5692
- algo_type: types.AlgoOrderRootType.POSITIONAL_TP_SL,
5693
- trigger_price_type: types.TriggerPriceType.MARK_PRICE,
5694
- // reduce_only: true,
5695
- symbol: values2.symbol,
5696
- child_orders
5697
- };
5698
- }
5699
- crateUpdateOrder(values2, oldValue, config) {
5700
- const data = this.create(values2, config);
5701
- const newData = [];
5702
- data.child_orders.forEach((order) => {
5703
- const oldOrder = oldValue.child_orders?.find(
5704
- (oldOrder2) => oldOrder2.algo_type === order.algo_type
5705
- );
5706
- if (oldOrder) {
5707
- if (!order.is_activated) {
5708
- newData.push({
5709
- is_activated: false,
5710
- order_id: Number(oldOrder.algo_order_id)
5711
- });
5712
- } else if (oldOrder.trigger_price !== order.trigger_price) {
5713
- newData.push({
5714
- trigger_price: order.trigger_price,
5715
- order_id: Number(oldOrder.algo_order_id)
5716
- });
5717
- }
5718
- }
5719
- });
5720
- return [
5721
- {
5722
- child_orders: newData
5723
- },
5724
- data
5725
- ];
5726
- }
5727
- };
5728
- async function bracketOrderValidator(values2, config) {
5729
- const result = /* @__PURE__ */ Object.create(null);
5730
- await Promise.resolve();
5731
- const { tp_trigger_price, sl_trigger_price, side } = values2;
5732
- const qty = Number(values2.quantity);
5733
- const maxQty = config.maxQty;
5734
- const type = values2.order_type;
5735
- const { quote_max, quote_min, price_scope, quote_dp } = config.symbol ?? {};
5736
- const mark_price = type === types.OrderType.MARKET ? config.markPrice : values2.order_price ? Number(values2.order_price) : void 0;
5737
- if (!isNaN(qty) && qty > maxQty) {
5738
- result.quantity = OrderValidation.max("quantity", config.maxQty);
5739
- }
5740
- if (Number(tp_trigger_price) < 0) {
5741
- result.tp_trigger_price = OrderValidation.min("tp_trigger_price", 0);
5742
- }
5743
- if (Number(sl_trigger_price) < 0) {
5744
- result.sl_trigger_price = OrderValidation.min("sl_trigger_price", 0);
5745
- }
5746
- if (side === types.OrderSide.BUY && mark_price) {
5747
- const slTriggerPriceScope = new utils.Decimal(mark_price * (1 - price_scope)).toDecimalPlaces(quote_dp, utils.Decimal.ROUND_DOWN).toNumber();
5748
- if (!!sl_trigger_price && Number(sl_trigger_price) < slTriggerPriceScope) {
5749
- result.sl_trigger_price = OrderValidation.min(
5750
- "sl_trigger_price",
5751
- slTriggerPriceScope
5752
- );
5753
- }
5754
- if (!!tp_trigger_price && Number(tp_trigger_price) <= mark_price) {
5755
- result.tp_trigger_price = OrderValidation.min(
5756
- "tp_trigger_price",
5757
- mark_price
5758
- );
5759
- }
5760
- if (!!tp_trigger_price && Number(tp_trigger_price) > quote_max) {
5761
- result.tp_trigger_price = OrderValidation.max(
5762
- "tp_trigger_price",
5763
- quote_max
5764
- );
5765
- }
5766
- if (!!sl_trigger_price && Number(sl_trigger_price) < quote_min) {
5767
- result.sl_trigger_price = OrderValidation.min(
5768
- "sl_trigger_price",
5769
- quote_min
5770
- );
5771
- }
5772
- }
5773
- if (side === types.OrderSide.SELL && mark_price) {
5774
- const slTriggerPriceScope = new utils.Decimal(mark_price * (1 + price_scope)).toDecimalPlaces(quote_dp, utils.Decimal.ROUND_DOWN).toNumber();
5775
- if (!!sl_trigger_price && Number(sl_trigger_price) > slTriggerPriceScope) {
5776
- result.sl_trigger_price = OrderValidation.max(
5777
- "sl_trigger_price",
5778
- slTriggerPriceScope
5779
- );
5780
- }
5781
- if (!!tp_trigger_price && Number(tp_trigger_price) >= mark_price) {
5782
- result.tp_trigger_price = OrderValidation.max(
5783
- "tp_trigger_price",
5784
- mark_price
5785
- );
5786
- }
5787
- if (!!tp_trigger_price && Number(tp_trigger_price) > quote_max) {
5788
- result.tp_trigger_price = OrderValidation.max(
5789
- "tp_trigger_price",
5790
- quote_max
5791
- );
5792
- }
5793
- if (!!sl_trigger_price && Number(sl_trigger_price) < quote_min) {
5794
- result.sl_trigger_price = OrderValidation.min(
5795
- "sl_trigger_price",
5796
- quote_min
5797
- );
5798
- }
5799
- }
5800
- return Object.keys(result).length > 0 ? result : null;
5801
- }
5802
-
5803
- // src/services/orderCreator/bracketLimitOrderCreator.ts
5804
- var BracketLimitOrderCreator = class extends LimitOrderCreator {
5805
- // orderType: OrderType;
5806
- create(values2, config) {
5807
- const order = super.create(values2, config);
5808
- return {
5809
- ...order,
5810
- quantity: order.order_quantity,
5811
- type: order.order_type,
5812
- price: order.order_price
5813
- };
5814
- }
5815
- async validate(values2, config) {
5816
- const value = await super.validate(values2, config);
5817
- const bracketData = await bracketOrderValidator(values2, config);
5818
- return { ...value, ...bracketData };
5819
- }
5820
- };
5821
- var BracketMarketOrderCreator = class extends MarketOrderCreator {
5822
- constructor() {
5823
- super(...arguments);
5824
- this.orderType = types.OrderType.MARKET;
5825
- }
5826
- create(values2) {
5827
- const order = super.create(values2);
6345
+ symbol: values2.symbol,
6346
+ is_activated: !!values2.tp_trigger_price
6347
+ });
6348
+ }
6349
+ if (typeof values2.sl_trigger_price !== "undefined") {
6350
+ const sl_trigger_price = !!values2.sl_trigger_price ? new utils.Decimal(values2.sl_trigger_price).todp(config.symbol.quote_dp).toNumber() : values2.sl_trigger_price;
6351
+ child_orders.push({
6352
+ algo_type: types.AlgoOrderType.STOP_LOSS,
6353
+ reduce_only: true,
6354
+ side,
6355
+ type: types.OrderType.CLOSE_POSITION,
6356
+ trigger_price: sl_trigger_price,
6357
+ trigger_price_type: types.TriggerPriceType.MARK_PRICE,
6358
+ symbol: values2.symbol,
6359
+ is_activated: !!values2.sl_trigger_price
6360
+ });
6361
+ }
5828
6362
  return {
5829
- ...order,
5830
- quantity: order.order_quantity,
5831
- type: order.order_type,
5832
- price: order.order_price
5833
- };
5834
- }
5835
- async validate(values2, config) {
5836
- const value = await super.validate(values2, config);
5837
- const bracketData = await bracketOrderValidator(values2, config);
5838
- return { ...value, ...bracketData };
5839
- }
5840
- };
5841
- var BBOOrderCreator = class extends BaseOrderCreator {
5842
- create(values2) {
5843
- const order = {
5844
- ...this.baseOrder(values2),
5845
- level: values2.level
6363
+ algo_type: types.AlgoOrderRootType.POSITIONAL_TP_SL,
6364
+ trigger_price_type: types.TriggerPriceType.MARK_PRICE,
6365
+ // reduce_only: true,
6366
+ symbol: values2.symbol,
6367
+ child_orders
5846
6368
  };
5847
- return ramda.pick(
5848
- [
5849
- "symbol",
5850
- "order_quantity",
5851
- "visible_quantity",
5852
- "reduce_only",
5853
- "side",
5854
- "order_type",
5855
- "level"
5856
- ],
5857
- order
5858
- );
5859
6369
  }
5860
- async validate(values2, configs) {
5861
- return this.baseValidate(values2, configs).then((errors) => {
5862
- delete errors["total"];
5863
- let { order_quantity, order_price, reduce_only, level } = values2;
5864
- const { symbol } = configs;
5865
- const { min_notional, base_tick, quote_dp, quote_tick, base_dp } = symbol || {};
5866
- const minNotional = getMinNotional({
5867
- base_tick,
5868
- quote_tick,
5869
- price: order_price,
5870
- qty: order_quantity,
5871
- min_notional,
5872
- quote_dp,
5873
- base_dp
5874
- });
5875
- if (minNotional !== void 0 && !reduce_only) {
5876
- errors.total = {
5877
- type: "min",
5878
- message: `The order value should be greater or equal to ${minNotional} USDC`,
5879
- value: minNotional
5880
- };
6370
+ crateUpdateOrder(values2, oldValue, config) {
6371
+ const data = this.create(values2, config);
6372
+ const newData = [];
6373
+ data.child_orders.forEach((order) => {
6374
+ const oldOrder = oldValue.child_orders?.find(
6375
+ (oldOrder2) => oldOrder2.algo_type === order.algo_type
6376
+ );
6377
+ if (oldOrder) {
6378
+ if (!order.is_activated) {
6379
+ newData.push({
6380
+ is_activated: false,
6381
+ order_id: Number(oldOrder.algo_order_id)
6382
+ });
6383
+ } else if (oldOrder.trigger_price !== order.trigger_price) {
6384
+ newData.push({
6385
+ trigger_price: order.trigger_price,
6386
+ order_id: Number(oldOrder.algo_order_id)
6387
+ });
6388
+ }
5881
6389
  }
5882
- return errors;
5883
6390
  });
6391
+ return [
6392
+ {
6393
+ child_orders: newData
6394
+ },
6395
+ data
6396
+ ];
5884
6397
  }
5885
6398
  };
5886
6399
 
@@ -5909,6 +6422,8 @@ var OrderFactory = class {
5909
6422
  return new StopLimitOrderCreator();
5910
6423
  case types.OrderType.STOP_MARKET:
5911
6424
  return new StopMarketOrderCreator();
6425
+ case types.OrderType.SCALED:
6426
+ return new ScaledOrderCreator();
5912
6427
  case types.AlgoOrderRootType.TP_SL:
5913
6428
  return new TPSLOrderCreator();
5914
6429
  case types.AlgoOrderRootType.POSITIONAL_TP_SL:
@@ -7172,6 +7687,9 @@ var usePrivateDataObserver = (options) => {
7172
7687
  return () => unsubscribe?.();
7173
7688
  }, [account7.accountId]);
7174
7689
  const isHoldingInit = React.useRef(false);
7690
+ React.useEffect(() => {
7691
+ isHoldingInit.current = false;
7692
+ }, [state.accountId]);
7175
7693
  React.useEffect(() => {
7176
7694
  if (!holding) {
7177
7695
  return;
@@ -14531,137 +15049,6 @@ function getQueryParamsFromObject(obj) {
14531
15049
  }
14532
15050
  return queryParams.toString();
14533
15051
  }
14534
- var getCreateOrderUrl = (order) => {
14535
- const isAlgoOrder = order?.order_type === types.OrderType.STOP_LIMIT || order?.order_type === types.OrderType.STOP_MARKET || order?.order_type === types.OrderType.CLOSE_POSITION || order.algo_type && order.algo_type === types.AlgoOrderRootType.BRACKET || isBracketOrder(order);
14536
- return isAlgoOrder ? "/v1/algo/order" : "/v1/order";
14537
- };
14538
- var getOrderCreator = (order) => {
14539
- let type;
14540
- if (isBracketOrder(order)) {
14541
- type = `${types.AlgoOrderRootType.BRACKET}:${order.order_type}`;
14542
- } else if (order.order_type === types.OrderType.LIMIT) {
14543
- type = order.order_type_ext || order.order_type;
14544
- } else {
14545
- type = order.order_type;
14546
- }
14547
- return OrderFactory.create(type);
14548
- };
14549
- var tpslFields = [
14550
- "tp_trigger_price",
14551
- "sl_trigger_price",
14552
- "tp_pnl",
14553
- "sl_pnl",
14554
- "tp_offset",
14555
- "sl_offset",
14556
- "tp_offset_percentage",
14557
- "sl_offset_percentage"
14558
- ];
14559
- var isBracketOrder = (order) => {
14560
- return !!order.tp_trigger_price || !!order.sl_trigger_price;
14561
- };
14562
- var hasTPSL = (order) => {
14563
- return tpslFields.some((field) => !!order[field]);
14564
- };
14565
- var getPriceAndQty = (symbolOrOrder, askAndBid) => {
14566
- let quantity = Number(symbolOrOrder.order_quantity);
14567
- const orderPrice = Number(symbolOrOrder.order_price);
14568
- if (isNaN(quantity) || quantity <= 0) {
14569
- return null;
14570
- }
14571
- if (askAndBid.length === 0) {
14572
- return null;
14573
- }
14574
- if ((symbolOrOrder.order_type === types.OrderType.LIMIT || symbolOrOrder.order_type === types.OrderType.STOP_LIMIT) && isNaN(orderPrice))
14575
- return null;
14576
- let price;
14577
- if (symbolOrOrder.order_type === types.OrderType.MARKET || symbolOrOrder.order_type === types.OrderType.STOP_MARKET) {
14578
- if (symbolOrOrder.side === types.OrderSide.BUY) {
14579
- price = askAndBid[0];
14580
- } else {
14581
- price = askAndBid[1];
14582
- }
14583
- } else {
14584
- if (symbolOrOrder.side === types.OrderSide.BUY) {
14585
- if (orderPrice >= askAndBid[0]) {
14586
- price = askAndBid[0];
14587
- } else {
14588
- price = orderPrice;
14589
- }
14590
- } else {
14591
- if (orderPrice <= askAndBid[1]) {
14592
- price = askAndBid[1];
14593
- } else {
14594
- price = orderPrice;
14595
- }
14596
- }
14597
- }
14598
- if (symbolOrOrder.side === types.OrderSide.SELL) {
14599
- quantity = -quantity;
14600
- }
14601
- return { price, quantity };
14602
- };
14603
- var calcEstLiqPrice = (order, askAndBid, inputs) => {
14604
- const result = getPriceAndQty(order, askAndBid);
14605
- if (!result)
14606
- return null;
14607
- const { price, quantity } = result;
14608
- if (!price || !quantity)
14609
- return null;
14610
- const {
14611
- symbol,
14612
- baseIMR,
14613
- baseMMR,
14614
- imr_factor,
14615
- markPrice,
14616
- totalCollateral,
14617
- futures_taker_fee_rate,
14618
- positions: positions3
14619
- } = inputs;
14620
- const orderFee = perp.order.orderFee({
14621
- qty: quantity,
14622
- price,
14623
- futuresTakeFeeRate: Number(futures_taker_fee_rate) / 1e4
14624
- });
14625
- const liqPrice = perp.order.estLiqPrice({
14626
- markPrice,
14627
- baseIMR,
14628
- baseMMR,
14629
- totalCollateral,
14630
- positions: positions3 == null ? [] : positions3,
14631
- IMR_Factor: imr_factor,
14632
- orderFee,
14633
- newOrder: {
14634
- qty: quantity,
14635
- price,
14636
- symbol
14637
- }
14638
- });
14639
- if (liqPrice <= 0)
14640
- return null;
14641
- return liqPrice;
14642
- };
14643
- var calcEstLeverage = (order, askAndBid, inputs) => {
14644
- const result = getPriceAndQty(order, askAndBid);
14645
- const { totalCollateral, positions: positions3, symbol } = inputs;
14646
- if (!result)
14647
- return null;
14648
- const { price, quantity } = result;
14649
- if (!price || !quantity)
14650
- return null;
14651
- return perp.order.estLeverage({
14652
- totalCollateral,
14653
- positions: positions3,
14654
- newOrder: {
14655
- symbol,
14656
- qty: result.quantity,
14657
- price: result.price
14658
- }
14659
- });
14660
- };
14661
- function isBBOOrder(options) {
14662
- const { order_type, order_type_ext } = options;
14663
- return order_type === types.OrderType.LIMIT && [types.OrderType.ASK, types.OrderType.BID].includes(order_type_ext);
14664
- }
14665
15052
  var initialOrderState = {
14666
15053
  order_price: "",
14667
15054
  order_quantity: "",
@@ -14674,7 +15061,12 @@ var initialOrderState = {
14674
15061
  sl_offset_percentage: "",
14675
15062
  tp_offset: "",
14676
15063
  sl_offset: "",
14677
- total: ""
15064
+ total: "",
15065
+ min_price: "",
15066
+ max_price: "",
15067
+ totalOrders: "",
15068
+ distribution_type: "",
15069
+ skew: ""
14678
15070
  // symbol: "",
14679
15071
  };
14680
15072
  var useOrderStore = (initialOrder) => {
@@ -14911,12 +15303,9 @@ var useOrderEntryNextInternal = (symbol, options = {}) => {
14911
15303
  [calculate2, options.symbolInfo, orderEntity, orderEntryActions]
14912
15304
  );
14913
15305
  const validate = (order, creator, options2) => {
14914
- const { markPrice, maxQty, estSlippage } = options2;
14915
15306
  return creator?.validate(order, {
14916
- symbol: symbolInfo,
14917
- maxQty,
14918
- markPrice,
14919
- estSlippage
15307
+ ...options2,
15308
+ symbol: symbolInfo
14920
15309
  });
14921
15310
  };
14922
15311
  const generateOrder = (creator, options2) => {
@@ -15098,7 +15487,8 @@ var useOrderEntry2 = (symbol, options = {}) => {
15098
15487
  return {
15099
15488
  markPrice: actions.getMarkPriceBySymbol(symbol),
15100
15489
  maxQty,
15101
- estSlippage
15490
+ estSlippage,
15491
+ askAndBid: askAndBid.current?.[0] || []
15102
15492
  };
15103
15493
  }, [maxQty, symbol, estSlippage]);
15104
15494
  const interactiveValidate = (order) => {
@@ -15198,25 +15588,36 @@ var useOrderEntry2 = (symbol, options = {}) => {
15198
15588
  const { freeCollateral, totalCollateral } = useCollateral();
15199
15589
  const estLiqPrice = React.useMemo(() => {
15200
15590
  const markPrice2 = actions.getMarkPriceBySymbol(symbol);
15201
- if (!markPrice2 || !accountInfo)
15591
+ if (!markPrice2 || !accountInfo || !symbolInfo) {
15202
15592
  return null;
15593
+ }
15203
15594
  const orderQuantity = Number(formattedOrder.order_quantity);
15204
15595
  if (orderQuantity === 0 || orderQuantity > maxQty) {
15205
15596
  return null;
15206
15597
  }
15207
15598
  const estLiqPrice2 = calcEstLiqPrice(formattedOrder, askAndBid.current[0], {
15208
- baseIMR: symbolInfo?.base_imr,
15209
- baseMMR: symbolInfo?.base_mmr,
15210
15599
  markPrice: markPrice2,
15211
15600
  totalCollateral,
15212
15601
  futures_taker_fee_rate: accountInfo.futures_taker_fee_rate,
15213
15602
  imr_factor: accountInfo.imr_factor[symbol],
15214
15603
  symbol,
15215
- positions: positions3
15604
+ positions: positions3,
15605
+ symbolInfo
15216
15606
  });
15217
15607
  return estLiqPrice2;
15218
- }, [formattedOrder, accountInfo, positions3, totalCollateral, symbol, maxQty]);
15608
+ }, [
15609
+ formattedOrder,
15610
+ accountInfo,
15611
+ positions3,
15612
+ totalCollateral,
15613
+ symbol,
15614
+ maxQty,
15615
+ symbolInfo
15616
+ ]);
15219
15617
  const estLeverage = React.useMemo(() => {
15618
+ if (!symbolInfo) {
15619
+ return null;
15620
+ }
15220
15621
  const orderQuantity = Number(formattedOrder.order_quantity);
15221
15622
  if (orderQuantity === 0 || orderQuantity > maxQty) {
15222
15623
  return null;
@@ -15224,9 +15625,18 @@ var useOrderEntry2 = (symbol, options = {}) => {
15224
15625
  return calcEstLeverage(formattedOrder, askAndBid.current[0], {
15225
15626
  totalCollateral,
15226
15627
  positions: positions3,
15227
- symbol
15628
+ symbol,
15629
+ symbolInfo
15228
15630
  });
15229
- }, [formattedOrder, accountInfo, positions3, totalCollateral, symbol, maxQty]);
15631
+ }, [
15632
+ formattedOrder,
15633
+ accountInfo,
15634
+ positions3,
15635
+ totalCollateral,
15636
+ symbol,
15637
+ maxQty,
15638
+ symbolInfo
15639
+ ]);
15230
15640
  const resetErrors = () => {
15231
15641
  setMeta(
15232
15642
  immer$1.produce((draft) => {
@@ -15263,14 +15673,31 @@ var useOrderEntry2 = (symbol, options = {}) => {
15263
15673
  throw new types.SDKError("Order validation failed");
15264
15674
  }
15265
15675
  const order = generateOrder(creator, prepareData());
15266
- const result = await doCreateOrder(order);
15676
+ const isScaledOrder = order.order_type === types.OrderType.SCALED;
15677
+ const params = isScaledOrder ? { orders: order.orders } : order;
15678
+ const result = await doCreateOrder(params);
15267
15679
  if (result.success) {
15268
- track2(types.TrackerEventName.placeOrderSuccess, {
15680
+ let trackParams = {
15269
15681
  side: order.side,
15270
15682
  order_type: order.order_type,
15271
15683
  tp_sl: hasTPSL(formattedOrder),
15272
15684
  symbol: order.symbol
15273
- });
15685
+ };
15686
+ if (isScaledOrder) {
15687
+ const skew = getScaledOrderSkew({
15688
+ skew: order.skew,
15689
+ distribution_type: order.distribution_type,
15690
+ total_orders: order.total_orders
15691
+ });
15692
+ trackParams = {
15693
+ ...trackParams,
15694
+ order_type: "scaled",
15695
+ distribution_type: order.distribution_type,
15696
+ skew: new utils.Decimal(skew).todp(2).toNumber(),
15697
+ total_orders: order.total_orders
15698
+ };
15699
+ }
15700
+ track2(types.TrackerEventName.placeOrderSuccess, trackParams);
15274
15701
  }
15275
15702
  if (result.success && resetOnSuccess) {
15276
15703
  reset();
@@ -15455,6 +15882,7 @@ var useOrderEntity = (order, options) => {
15455
15882
  symbolInfo
15456
15883
  };
15457
15884
  };
15885
+ var canUnblockRegions = ["United States"];
15458
15886
  var useRestrictedInfo = (options) => {
15459
15887
  const {
15460
15888
  enableDefault = false,
@@ -15462,63 +15890,70 @@ var useRestrictedInfo = (options) => {
15462
15890
  customRestrictedRegions = [],
15463
15891
  content
15464
15892
  } = options || {};
15465
- const apiBaseUrl = useConfig("apiBaseUrl");
15466
- const [invalidWebCity, setInvalidWebCity] = React.useState([]);
15467
- const [invalidWebCountry, setInvalidWebCountry] = React.useState([]);
15468
- const [invalidRegions, setInvalidRegions] = React.useState([]);
15469
- const [allInvalidAreas, setAllInvalidAreas] = React.useState([]);
15470
- const [city, setCity] = React.useState("");
15471
- const [region, setRegion] = React.useState("");
15472
15893
  const [ip, setIp] = React.useState("");
15894
+ const [allInvalidAreas, setAllInvalidAreas] = React.useState([]);
15473
15895
  const [restrictedOpen, setRestrictedOpen] = React.useState(false);
15896
+ const [canUnblock, setCanUnblock] = React.useState(false);
15897
+ const [accessRestricted, setAccessRestricted] = useLocalStorage("orderly_access_restricted", void 0);
15898
+ const { data: ipInfo } = useQuery("/v1/ip_info");
15899
+ const { data: restrictedAreas } = useQuery(
15900
+ "/v1/restricted_areas"
15901
+ );
15474
15902
  React.useEffect(() => {
15475
- const fetchData = async () => {
15476
- try {
15477
- const areaRes = await fetch(`${apiBaseUrl}/v1/restricted_areas`);
15478
- const areaResdata = await areaRes.json();
15479
- const ipRes = await fetch(`${apiBaseUrl}/v1/ip_info`);
15480
- const ipData = await ipRes.json();
15481
- if (areaResdata.success && ipData.success) {
15482
- const invalidCountries = areaResdata?.data?.invalid_web_country?.toLocaleLowerCase()?.replace(/\s+/g, "").split(",");
15483
- const invalidCities = areaResdata?.data?.invalid_web_city?.toLocaleLowerCase()?.replace(/\s+/g, "").split(",");
15484
- const combinedInvalidRegions = (enableDefault ? invalidCities.concat(invalidCountries) : []).concat(
15485
- customRestrictedRegions?.map(
15486
- (item) => item?.replace(/\s+/g, "")?.toLocaleLowerCase()
15487
- )
15488
- );
15489
- const allInvalidAreas2 = [
15490
- enableDefault ? areaResdata?.data?.invalid_web_country : "",
15491
- enableDefault ? areaResdata?.data?.invalid_web_city : "",
15492
- customRestrictedRegions?.join(", ")
15493
- ].filter((item) => !!item);
15494
- setInvalidWebCity(invalidCities);
15495
- setInvalidWebCountry(invalidCountries);
15496
- setInvalidRegions(combinedInvalidRegions);
15497
- setAllInvalidAreas(allInvalidAreas2);
15498
- const { city: city2, region: region2, ip: ip2 } = ipData.data;
15499
- setCity(city2);
15500
- setRegion(region2);
15501
- setIp(ip2);
15502
- if (combinedInvalidRegions.includes(
15503
- ipData?.data?.city?.replace(/\s+/g, "").toLocaleLowerCase()
15504
- ) || combinedInvalidRegions.includes(
15505
- ipData?.data?.region?.replace(/\s+/g, "").toLocaleLowerCase()
15506
- ) || customRestrictedIps.includes(ipData?.data?.ip)) {
15507
- setRestrictedOpen(true);
15508
- }
15903
+ if (!restrictedAreas || !ipInfo) {
15904
+ return;
15905
+ }
15906
+ try {
15907
+ const { invalid_web_country, invalid_web_city } = restrictedAreas;
15908
+ const invalidCountries = invalid_web_country?.toLowerCase().replace(/\s+/g, "").split(",");
15909
+ const invalidCities = invalid_web_city?.toLowerCase().replace(/\s+/g, "").split(",");
15910
+ const formattedCustomRegions = customRestrictedRegions?.map(
15911
+ (item) => formatRegion(item)
15912
+ );
15913
+ const combinedInvalidRegions = [
15914
+ ...formattedCustomRegions,
15915
+ ...enableDefault ? [...invalidCountries, ...invalidCities] : []
15916
+ ];
15917
+ const allInvalidAreas2 = [
15918
+ enableDefault ? invalid_web_country : "",
15919
+ enableDefault ? invalid_web_city : "",
15920
+ customRestrictedRegions?.join(", ")
15921
+ ].filter((item) => !!item);
15922
+ const { city, region, ip: ip2 } = ipInfo;
15923
+ const formattedCity = formatRegion(city);
15924
+ const formattedRegion = formatRegion(region);
15925
+ const showRestricted = accessRestricted && (combinedInvalidRegions.includes(formattedCity) || combinedInvalidRegions.includes(formattedRegion) || customRestrictedIps.includes(ip2));
15926
+ for (const item of canUnblockRegions) {
15927
+ if (formatRegion(item) === formatRegion(region)) {
15928
+ setCanUnblock(true);
15509
15929
  }
15510
- } catch (error) {
15511
15930
  }
15512
- };
15513
- fetchData();
15514
- }, [apiBaseUrl]);
15931
+ setIp(ip2);
15932
+ setAllInvalidAreas(allInvalidAreas2);
15933
+ setRestrictedOpen(showRestricted);
15934
+ } catch (error) {
15935
+ }
15936
+ }, [
15937
+ ipInfo,
15938
+ restrictedAreas,
15939
+ enableDefault,
15940
+ customRestrictedIps,
15941
+ customRestrictedRegions,
15942
+ accessRestricted
15943
+ ]);
15515
15944
  return {
15516
15945
  ip,
15517
15946
  invalidRegions: allInvalidAreas,
15518
15947
  restrictedOpen,
15519
- content
15948
+ content,
15949
+ canUnblock,
15950
+ accessRestricted,
15951
+ setAccessRestricted
15520
15952
  };
15521
15953
  };
15954
+ function formatRegion(region) {
15955
+ return region?.replace(/\s+/g, "").toLowerCase();
15956
+ }
15522
15957
  var usePositionClose = (options) => {
15523
15958
  const { position, order: initialOrder } = options;
15524
15959
  const { type, quantity, price } = initialOrder;
@@ -15526,6 +15961,10 @@ var usePositionClose = (options) => {
15526
15961
  const [errors, setErrors] = React.useState(null);
15527
15962
  const symbolsInfo = useSymbolsInfo();
15528
15963
  const { data: markPrices } = useMarkPricesStream();
15964
+ const markPricesRef = React.useRef(markPrices);
15965
+ React.useEffect(() => {
15966
+ markPricesRef.current = markPrices;
15967
+ }, [markPrices]);
15529
15968
  const [doCreateOrder, { isMutating }] = useSubAccountMutation(
15530
15969
  "/v1/order",
15531
15970
  "POST",
@@ -15574,11 +16013,12 @@ var usePositionClose = (options) => {
15574
16013
  const errors2 = await creator.validate(data, {
15575
16014
  symbol: symbolsInfo[symbol](),
15576
16015
  maxQty,
15577
- markPrice: markPrices[symbol]
16016
+ // use ref to avoid re-render when markPrices change
16017
+ markPrice: markPricesRef.current[symbol]
15578
16018
  });
15579
16019
  return errors2;
15580
16020
  },
15581
- [markPrices, maxQty, symbol, symbolsInfo]
16021
+ [maxQty, symbol, symbolsInfo]
15582
16022
  );
15583
16023
  React.useEffect(() => {
15584
16024
  validate(closeOrderData).then((errors2) => {