@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.d.mts +21 -3
- package/dist/index.d.ts +21 -3
- package/dist/index.js +995 -555
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +996 -556
- package/dist/index.mjs.map +1 -1
- package/package.json +10 -10
package/dist/index.mjs
CHANGED
|
@@ -3,7 +3,7 @@ import useSWR__default, { mutate } from 'swr';
|
|
|
3
3
|
import * as useSWR from 'swr';
|
|
4
4
|
export { useSWR as swr };
|
|
5
5
|
export { unstable_serialize, default as useSWR, useSWRConfig } from 'swr';
|
|
6
|
-
import { TesntTokenFallback, ArbitrumSepoliaTokenInfo, SolanaDevnetTokenInfo, OrderType, OrderSide, SDKError, TrackerEventName, AccountStatusEnum, AlgoOrderRootType, OrderStatus, ArbitrumSepoliaChainInfo, SolanaDevnetChainInfo, ARBITRUM_TESTNET_CHAINID, SOLANA_TESTNET_CHAINID, MONAD_TESTNET_CHAINID, ABSTRACT_TESTNET_CHAINID, BSC_TESTNET_CHAINID, nativeTokenAddress, ChainKey, chainsInfoMap, ARBITRUM_MAINNET_CHAINID, isNativeTokenChecker, ChainNamespace, MaxUint256, DEPOSIT_FEE_RATE, LedgerWalletKey, SolanaChains, AlgoOrderType, TriggerPriceType } from '@orderly.network/types';
|
|
6
|
+
import { TesntTokenFallback, ArbitrumSepoliaTokenInfo, SolanaDevnetTokenInfo, OrderType, OrderSide, SDKError, TrackerEventName, AccountStatusEnum, AlgoOrderRootType, OrderStatus, ArbitrumSepoliaChainInfo, SolanaDevnetChainInfo, ARBITRUM_TESTNET_CHAINID, SOLANA_TESTNET_CHAINID, MONAD_TESTNET_CHAINID, ABSTRACT_TESTNET_CHAINID, BSC_TESTNET_CHAINID, nativeTokenAddress, ChainKey, chainsInfoMap, ARBITRUM_MAINNET_CHAINID, isNativeTokenChecker, ChainNamespace, MaxUint256, DEPOSIT_FEE_RATE, LedgerWalletKey, SolanaChains, AlgoOrderType, DistributionType, TriggerPriceType } from '@orderly.network/types';
|
|
7
7
|
import React, { createContext, useContext, useCallback, useState, useEffect, useMemo, useRef, useId, useLayoutEffect } from 'react';
|
|
8
8
|
import useSWRMutation from 'swr/mutation';
|
|
9
9
|
import useConstant from 'use-constant';
|
|
@@ -36,9 +36,9 @@ var __export = (target, all) => {
|
|
|
36
36
|
// src/version.ts
|
|
37
37
|
if (typeof window !== "undefined") {
|
|
38
38
|
window.__ORDERLY_VERSION__ = window.__ORDERLY_VERSION__ || {};
|
|
39
|
-
window.__ORDERLY_VERSION__["@orderly.network/hooks"] = "2.
|
|
39
|
+
window.__ORDERLY_VERSION__["@orderly.network/hooks"] = "2.4.0";
|
|
40
40
|
}
|
|
41
|
-
var version_default = "2.
|
|
41
|
+
var version_default = "2.4.0";
|
|
42
42
|
var fetcher = (url, init2 = {}, queryOptions) => get(url, init2, queryOptions?.formatter);
|
|
43
43
|
var OrderlyContext = createContext({
|
|
44
44
|
// configStore: new MemoryConfigStore(),
|
|
@@ -243,7 +243,8 @@ var useTrack = () => {
|
|
|
243
243
|
page_title: title,
|
|
244
244
|
page_url: url,
|
|
245
245
|
page_domain: origin,
|
|
246
|
-
user_agent: userAgent
|
|
246
|
+
user_agent: userAgent,
|
|
247
|
+
sdk_version: window?.__ORDERLY_VERSION__?.["@orderly.network/net"] ?? ""
|
|
247
248
|
});
|
|
248
249
|
if (eventName === TrackerEventName.placeOrderSuccess) {
|
|
249
250
|
Object.assign(params, {
|
|
@@ -4175,7 +4176,7 @@ function fillChainsInfo(chains, filter, chainInfos) {
|
|
|
4175
4176
|
return _chains;
|
|
4176
4177
|
}
|
|
4177
4178
|
function filterAndUpdateChains(chains, chainInfos, filter, isTestNet) {
|
|
4178
|
-
const
|
|
4179
|
+
const chainsMap = /* @__PURE__ */ new Map();
|
|
4179
4180
|
chains.forEach((chain) => {
|
|
4180
4181
|
const _chain = { ...chain };
|
|
4181
4182
|
const networkInfo = chainInfos?.find(
|
|
@@ -4200,10 +4201,10 @@ function filterAndUpdateChains(chains, chainInfos, filter, isTestNet) {
|
|
|
4200
4201
|
return;
|
|
4201
4202
|
}
|
|
4202
4203
|
if (networkInfo) {
|
|
4203
|
-
|
|
4204
|
+
chainsMap.set(chain.network_infos.chain_id, _chain);
|
|
4204
4205
|
}
|
|
4205
4206
|
});
|
|
4206
|
-
return
|
|
4207
|
+
return Array.from(chainsMap.values());
|
|
4207
4208
|
}
|
|
4208
4209
|
function filterByAllowedChains(chains, allowedChains) {
|
|
4209
4210
|
if (!allowedChains) {
|
|
@@ -4887,12 +4888,11 @@ var useSymbolPriceRange = (symbol, side, price) => {
|
|
|
4887
4888
|
};
|
|
4888
4889
|
function getMinNotional(props) {
|
|
4889
4890
|
const { price, base_tick, qty, min_notional, base_dp, quote_dp, quote_tick } = props;
|
|
4890
|
-
if (price
|
|
4891
|
+
if (price && qty && min_notional) {
|
|
4891
4892
|
try {
|
|
4892
|
-
const
|
|
4893
|
-
|
|
4894
|
-
|
|
4895
|
-
let minQty = new Decimal(notional).div(price).toDecimalPlaces(base_dp, Decimal.ROUND_DOWN).add(base_tick ?? 0);
|
|
4893
|
+
const calcMinNotional = new Decimal(price).mul(new Decimal(qty));
|
|
4894
|
+
if (calcMinNotional.lt(min_notional)) {
|
|
4895
|
+
let minQty = new Decimal(min_notional).div(price).toDecimalPlaces(base_dp, Decimal.ROUND_DOWN).add(base_tick ?? 0);
|
|
4896
4896
|
if (base_tick && base_tick > 0) {
|
|
4897
4897
|
minQty = new Decimal(
|
|
4898
4898
|
getRoundedDownDivision(minQty.toNumber(), base_tick)
|
|
@@ -4950,6 +4950,14 @@ var OrderValidation = class {
|
|
|
4950
4950
|
return "TP price";
|
|
4951
4951
|
case "sl_trigger_price":
|
|
4952
4952
|
return "SL price";
|
|
4953
|
+
case "max_price":
|
|
4954
|
+
return "Upper price";
|
|
4955
|
+
case "min_price":
|
|
4956
|
+
return "Lower price";
|
|
4957
|
+
case "total_orders":
|
|
4958
|
+
return "Total orders";
|
|
4959
|
+
case "skew":
|
|
4960
|
+
return "Skew";
|
|
4953
4961
|
default:
|
|
4954
4962
|
return key;
|
|
4955
4963
|
}
|
|
@@ -4974,6 +4982,14 @@ var OrderValidation = class {
|
|
|
4974
4982
|
value
|
|
4975
4983
|
};
|
|
4976
4984
|
}
|
|
4985
|
+
static range(key, min3, max3) {
|
|
4986
|
+
return {
|
|
4987
|
+
type: "range",
|
|
4988
|
+
message: `${this.getLabel(key)} must be in the range of ${min3} to ${max3}`,
|
|
4989
|
+
min: min3,
|
|
4990
|
+
max: max3
|
|
4991
|
+
};
|
|
4992
|
+
}
|
|
4977
4993
|
};
|
|
4978
4994
|
|
|
4979
4995
|
// src/services/orderCreator/baseCreator.ts
|
|
@@ -5176,33 +5192,33 @@ var BaseOrderCreator = class {
|
|
|
5176
5192
|
}
|
|
5177
5193
|
};
|
|
5178
5194
|
|
|
5179
|
-
// src/services/orderCreator/
|
|
5180
|
-
var
|
|
5195
|
+
// src/services/orderCreator/bboOrderCreator.ts
|
|
5196
|
+
var BBOOrderCreator = class extends BaseOrderCreator {
|
|
5197
|
+
constructor() {
|
|
5198
|
+
super(...arguments);
|
|
5199
|
+
this.orderType = OrderType.LIMIT;
|
|
5200
|
+
}
|
|
5181
5201
|
create(values2) {
|
|
5182
|
-
const
|
|
5183
|
-
|
|
5184
|
-
|
|
5185
|
-
delete data["trigger_price"];
|
|
5186
|
-
delete data["isStopOrder"];
|
|
5187
|
-
return {
|
|
5188
|
-
...data
|
|
5202
|
+
const order = {
|
|
5203
|
+
...this.baseOrder(values2),
|
|
5204
|
+
level: values2.level
|
|
5189
5205
|
};
|
|
5206
|
+
return pick(
|
|
5207
|
+
[
|
|
5208
|
+
"symbol",
|
|
5209
|
+
"order_quantity",
|
|
5210
|
+
"visible_quantity",
|
|
5211
|
+
"reduce_only",
|
|
5212
|
+
"side",
|
|
5213
|
+
"order_type",
|
|
5214
|
+
"level"
|
|
5215
|
+
],
|
|
5216
|
+
order
|
|
5217
|
+
);
|
|
5190
5218
|
}
|
|
5191
|
-
validate(values2, configs) {
|
|
5192
|
-
return this.baseValidate(values2, configs).then((
|
|
5193
|
-
|
|
5194
|
-
const estSlippage = Number.isNaN(configs.estSlippage) ? 0 : Number(configs.estSlippage) * 100;
|
|
5195
|
-
if (!isNaN(slippage) && estSlippage > slippage) {
|
|
5196
|
-
return {
|
|
5197
|
-
...result,
|
|
5198
|
-
slippage: {
|
|
5199
|
-
type: "max",
|
|
5200
|
-
message: "Estimated slippage exceeds your maximum allowed slippage.",
|
|
5201
|
-
value: estSlippage
|
|
5202
|
-
}
|
|
5203
|
-
};
|
|
5204
|
-
}
|
|
5205
|
-
return result;
|
|
5219
|
+
async validate(values2, configs) {
|
|
5220
|
+
return this.baseValidate(values2, configs).then((errors) => {
|
|
5221
|
+
return errors;
|
|
5206
5222
|
});
|
|
5207
5223
|
}
|
|
5208
5224
|
};
|
|
@@ -5281,124 +5297,791 @@ var LimitOrderCreator = class extends BaseOrderCreator {
|
|
|
5281
5297
|
});
|
|
5282
5298
|
}
|
|
5283
5299
|
};
|
|
5284
|
-
|
|
5285
|
-
|
|
5286
|
-
|
|
5287
|
-
|
|
5288
|
-
|
|
5300
|
+
async function bracketOrderValidator(values2, config) {
|
|
5301
|
+
const result = /* @__PURE__ */ Object.create(null);
|
|
5302
|
+
await Promise.resolve();
|
|
5303
|
+
const { tp_trigger_price, sl_trigger_price, side } = values2;
|
|
5304
|
+
const qty = Number(values2.quantity);
|
|
5305
|
+
const maxQty = config.maxQty;
|
|
5306
|
+
const type = values2.order_type;
|
|
5307
|
+
const { quote_max, quote_min, price_scope, quote_dp } = config.symbol ?? {};
|
|
5308
|
+
const mark_price = type === OrderType.MARKET ? config.markPrice : values2.order_price ? Number(values2.order_price) : void 0;
|
|
5309
|
+
if (!isNaN(qty) && qty > maxQty) {
|
|
5310
|
+
result.quantity = OrderValidation.max("quantity", config.maxQty);
|
|
5289
5311
|
}
|
|
5290
|
-
|
|
5291
|
-
|
|
5292
|
-
const order = {
|
|
5293
|
-
...this.baseOrder(values2),
|
|
5294
|
-
trigger_price: values2.trigger_price,
|
|
5295
|
-
algo_type: AlgoOrderRootType.STOP,
|
|
5296
|
-
type: OrderType.LIMIT,
|
|
5297
|
-
quantity: values2["order_quantity"],
|
|
5298
|
-
price: values2["order_price"],
|
|
5299
|
-
trigger_price_type: TriggerPriceType.MARK_PRICE
|
|
5300
|
-
};
|
|
5301
|
-
return pick(
|
|
5302
|
-
[
|
|
5303
|
-
"symbol",
|
|
5304
|
-
"trigger_price",
|
|
5305
|
-
"algo_type",
|
|
5306
|
-
"type",
|
|
5307
|
-
"quantity",
|
|
5308
|
-
"price",
|
|
5309
|
-
"trigger_price_type",
|
|
5310
|
-
"side",
|
|
5311
|
-
"reduce_only",
|
|
5312
|
-
"visible_quantity"
|
|
5313
|
-
],
|
|
5314
|
-
order
|
|
5315
|
-
);
|
|
5312
|
+
if (Number(tp_trigger_price) < 0) {
|
|
5313
|
+
result.tp_trigger_price = OrderValidation.min("tp_trigger_price", 0);
|
|
5316
5314
|
}
|
|
5317
|
-
|
|
5318
|
-
|
|
5319
|
-
const { order_price, trigger_price, side } = values2;
|
|
5320
|
-
const { symbol } = config;
|
|
5321
|
-
const { price_range, price_scope, quote_max, quote_min } = symbol;
|
|
5322
|
-
if (!trigger_price) {
|
|
5323
|
-
errors.trigger_price = OrderValidation.required("trigger_price");
|
|
5324
|
-
}
|
|
5325
|
-
if (!order_price) {
|
|
5326
|
-
errors.order_price = OrderValidation.required("order_price");
|
|
5327
|
-
}
|
|
5328
|
-
if (trigger_price > quote_max) {
|
|
5329
|
-
errors.trigger_price = OrderValidation.max("trigger_price", quote_max);
|
|
5330
|
-
} else if (trigger_price < quote_min) {
|
|
5331
|
-
errors.trigger_price = OrderValidation.min("trigger_price", quote_min);
|
|
5332
|
-
} else {
|
|
5333
|
-
if (trigger_price && order_price) {
|
|
5334
|
-
const price = new Decimal(order_price);
|
|
5335
|
-
const maxPriceNumber = maxPrice2(trigger_price, price_range);
|
|
5336
|
-
const minPriceNumber = minPrice2(trigger_price, price_range);
|
|
5337
|
-
const scropePriceNumbere = scopePrice2(
|
|
5338
|
-
trigger_price,
|
|
5339
|
-
price_scope,
|
|
5340
|
-
side
|
|
5341
|
-
);
|
|
5342
|
-
const priceRange = side === "BUY" ? {
|
|
5343
|
-
min: scropePriceNumbere,
|
|
5344
|
-
max: maxPriceNumber
|
|
5345
|
-
} : {
|
|
5346
|
-
min: minPriceNumber,
|
|
5347
|
-
max: scropePriceNumbere
|
|
5348
|
-
};
|
|
5349
|
-
if (price.gt(quote_max)) {
|
|
5350
|
-
errors.order_price = OrderValidation.max("order_price", quote_max);
|
|
5351
|
-
} else {
|
|
5352
|
-
if (price.gt(priceRange?.max)) {
|
|
5353
|
-
errors.order_price = OrderValidation.max(
|
|
5354
|
-
"order_price",
|
|
5355
|
-
new Decimal(priceRange.max).todp(symbol.quote_dp).toString()
|
|
5356
|
-
);
|
|
5357
|
-
}
|
|
5358
|
-
}
|
|
5359
|
-
if (price.lt(quote_min)) {
|
|
5360
|
-
errors.order_price = OrderValidation.min("order_price", quote_min);
|
|
5361
|
-
} else {
|
|
5362
|
-
if (price.lt(priceRange?.min)) {
|
|
5363
|
-
errors.order_price = OrderValidation.min(
|
|
5364
|
-
"order_price",
|
|
5365
|
-
new Decimal(priceRange.min).todp(symbol.quote_dp).toString()
|
|
5366
|
-
);
|
|
5367
|
-
}
|
|
5368
|
-
}
|
|
5369
|
-
}
|
|
5370
|
-
}
|
|
5371
|
-
return errors;
|
|
5372
|
-
});
|
|
5315
|
+
if (Number(sl_trigger_price) < 0) {
|
|
5316
|
+
result.sl_trigger_price = OrderValidation.min("sl_trigger_price", 0);
|
|
5373
5317
|
}
|
|
5374
|
-
|
|
5318
|
+
if (side === OrderSide.BUY && mark_price) {
|
|
5319
|
+
const slTriggerPriceScope = new Decimal(mark_price * (1 - price_scope)).toDecimalPlaces(quote_dp, Decimal.ROUND_DOWN).toNumber();
|
|
5320
|
+
if (!!sl_trigger_price && Number(sl_trigger_price) < slTriggerPriceScope) {
|
|
5321
|
+
result.sl_trigger_price = OrderValidation.min(
|
|
5322
|
+
"sl_trigger_price",
|
|
5323
|
+
slTriggerPriceScope
|
|
5324
|
+
);
|
|
5325
|
+
}
|
|
5326
|
+
if (!!tp_trigger_price && Number(tp_trigger_price) <= mark_price) {
|
|
5327
|
+
result.tp_trigger_price = OrderValidation.min(
|
|
5328
|
+
"tp_trigger_price",
|
|
5329
|
+
mark_price
|
|
5330
|
+
);
|
|
5331
|
+
}
|
|
5332
|
+
if (!!tp_trigger_price && Number(tp_trigger_price) > quote_max) {
|
|
5333
|
+
result.tp_trigger_price = OrderValidation.max(
|
|
5334
|
+
"tp_trigger_price",
|
|
5335
|
+
quote_max
|
|
5336
|
+
);
|
|
5337
|
+
}
|
|
5338
|
+
if (!!sl_trigger_price && Number(sl_trigger_price) < quote_min) {
|
|
5339
|
+
result.sl_trigger_price = OrderValidation.min(
|
|
5340
|
+
"sl_trigger_price",
|
|
5341
|
+
quote_min
|
|
5342
|
+
);
|
|
5343
|
+
}
|
|
5344
|
+
}
|
|
5345
|
+
if (side === OrderSide.SELL && mark_price) {
|
|
5346
|
+
const slTriggerPriceScope = new Decimal(mark_price * (1 + price_scope)).toDecimalPlaces(quote_dp, Decimal.ROUND_DOWN).toNumber();
|
|
5347
|
+
if (!!sl_trigger_price && Number(sl_trigger_price) > slTriggerPriceScope) {
|
|
5348
|
+
result.sl_trigger_price = OrderValidation.max(
|
|
5349
|
+
"sl_trigger_price",
|
|
5350
|
+
slTriggerPriceScope
|
|
5351
|
+
);
|
|
5352
|
+
}
|
|
5353
|
+
if (!!tp_trigger_price && Number(tp_trigger_price) >= mark_price) {
|
|
5354
|
+
result.tp_trigger_price = OrderValidation.max(
|
|
5355
|
+
"tp_trigger_price",
|
|
5356
|
+
mark_price
|
|
5357
|
+
);
|
|
5358
|
+
}
|
|
5359
|
+
if (!!tp_trigger_price && Number(tp_trigger_price) > quote_max) {
|
|
5360
|
+
result.tp_trigger_price = OrderValidation.max(
|
|
5361
|
+
"tp_trigger_price",
|
|
5362
|
+
quote_max
|
|
5363
|
+
);
|
|
5364
|
+
}
|
|
5365
|
+
if (!!sl_trigger_price && Number(sl_trigger_price) < quote_min) {
|
|
5366
|
+
result.sl_trigger_price = OrderValidation.min(
|
|
5367
|
+
"sl_trigger_price",
|
|
5368
|
+
quote_min
|
|
5369
|
+
);
|
|
5370
|
+
}
|
|
5371
|
+
}
|
|
5372
|
+
return Object.keys(result).length > 0 ? result : null;
|
|
5373
|
+
}
|
|
5375
5374
|
|
|
5376
|
-
// src/services/orderCreator/
|
|
5377
|
-
var
|
|
5378
|
-
|
|
5375
|
+
// src/services/orderCreator/bracketLimitOrderCreator.ts
|
|
5376
|
+
var BracketLimitOrderCreator = class extends LimitOrderCreator {
|
|
5377
|
+
// orderType: OrderType;
|
|
5378
|
+
create(values2, config) {
|
|
5379
|
+
const order = super.create(values2, config);
|
|
5379
5380
|
return {
|
|
5380
|
-
...
|
|
5381
|
-
|
|
5382
|
-
|
|
5381
|
+
...order,
|
|
5382
|
+
quantity: order.order_quantity,
|
|
5383
|
+
type: order.order_type,
|
|
5384
|
+
price: order.order_price
|
|
5383
5385
|
};
|
|
5384
5386
|
}
|
|
5385
|
-
validate(values2,
|
|
5386
|
-
|
|
5387
|
+
async validate(values2, config) {
|
|
5388
|
+
const value = await super.validate(values2, config);
|
|
5389
|
+
const bracketData = await bracketOrderValidator(values2, config);
|
|
5390
|
+
return { ...value, ...bracketData };
|
|
5387
5391
|
}
|
|
5388
5392
|
};
|
|
5389
|
-
|
|
5393
|
+
|
|
5394
|
+
// src/services/orderCreator/marketOrderCreator.ts
|
|
5395
|
+
var MarketOrderCreator = class extends BaseOrderCreator {
|
|
5390
5396
|
create(values2) {
|
|
5391
|
-
const
|
|
5392
|
-
|
|
5393
|
-
|
|
5394
|
-
|
|
5395
|
-
|
|
5396
|
-
|
|
5397
|
-
|
|
5398
|
-
// price: values["order_price"],
|
|
5399
|
-
trigger_price_type: TriggerPriceType.MARK_PRICE
|
|
5397
|
+
const data = this.baseOrder(values2);
|
|
5398
|
+
delete data["order_price"];
|
|
5399
|
+
delete data["total"];
|
|
5400
|
+
delete data["trigger_price"];
|
|
5401
|
+
delete data["isStopOrder"];
|
|
5402
|
+
return {
|
|
5403
|
+
...data
|
|
5400
5404
|
};
|
|
5401
|
-
|
|
5405
|
+
}
|
|
5406
|
+
validate(values2, configs) {
|
|
5407
|
+
return this.baseValidate(values2, configs).then((result) => {
|
|
5408
|
+
const slippage = Number(values2.slippage);
|
|
5409
|
+
const estSlippage = Number.isNaN(configs.estSlippage) ? 0 : Number(configs.estSlippage) * 100;
|
|
5410
|
+
if (!isNaN(slippage) && estSlippage > slippage) {
|
|
5411
|
+
return {
|
|
5412
|
+
...result,
|
|
5413
|
+
slippage: {
|
|
5414
|
+
type: "max",
|
|
5415
|
+
message: "Estimated slippage exceeds your maximum allowed slippage.",
|
|
5416
|
+
value: estSlippage
|
|
5417
|
+
}
|
|
5418
|
+
};
|
|
5419
|
+
}
|
|
5420
|
+
return result;
|
|
5421
|
+
});
|
|
5422
|
+
}
|
|
5423
|
+
};
|
|
5424
|
+
|
|
5425
|
+
// src/services/orderCreator/bracketMarketOrderCreator.ts
|
|
5426
|
+
var BracketMarketOrderCreator = class extends MarketOrderCreator {
|
|
5427
|
+
constructor() {
|
|
5428
|
+
super(...arguments);
|
|
5429
|
+
this.orderType = OrderType.MARKET;
|
|
5430
|
+
}
|
|
5431
|
+
create(values2) {
|
|
5432
|
+
const order = super.create(values2);
|
|
5433
|
+
return {
|
|
5434
|
+
...order,
|
|
5435
|
+
quantity: order.order_quantity,
|
|
5436
|
+
type: order.order_type,
|
|
5437
|
+
price: order.order_price
|
|
5438
|
+
};
|
|
5439
|
+
}
|
|
5440
|
+
async validate(values2, config) {
|
|
5441
|
+
const value = await super.validate(values2, config);
|
|
5442
|
+
const bracketData = await bracketOrderValidator(values2, config);
|
|
5443
|
+
return { ...value, ...bracketData };
|
|
5444
|
+
}
|
|
5445
|
+
};
|
|
5446
|
+
|
|
5447
|
+
// src/services/orderCreator/fokCreator.ts
|
|
5448
|
+
var FOKOrderCreator = class extends LimitOrderCreator {
|
|
5449
|
+
};
|
|
5450
|
+
|
|
5451
|
+
// src/services/orderCreator/generalCreator.ts
|
|
5452
|
+
var GeneralOrderCreator = class extends BaseOrderCreator {
|
|
5453
|
+
create(data) {
|
|
5454
|
+
return {
|
|
5455
|
+
...this.baseOrder(data),
|
|
5456
|
+
order_price: data.order_price,
|
|
5457
|
+
order_quantity: data.order_quantity
|
|
5458
|
+
};
|
|
5459
|
+
}
|
|
5460
|
+
validate(values2, configs) {
|
|
5461
|
+
return super.baseValidate(values2, configs);
|
|
5462
|
+
}
|
|
5463
|
+
};
|
|
5464
|
+
|
|
5465
|
+
// src/services/orderCreator/iocCreator.ts
|
|
5466
|
+
var IOCOrderCreator = class extends LimitOrderCreator {
|
|
5467
|
+
};
|
|
5468
|
+
|
|
5469
|
+
// src/services/orderCreator/postOnlyCreator.ts
|
|
5470
|
+
var PostOnlyOrderCreator = class extends LimitOrderCreator {
|
|
5471
|
+
};
|
|
5472
|
+
var getCreateOrderUrl = (order) => {
|
|
5473
|
+
const isAlgoOrder = order?.order_type === OrderType.STOP_LIMIT || order?.order_type === OrderType.STOP_MARKET || order?.order_type === OrderType.CLOSE_POSITION || order.algo_type && order.algo_type === AlgoOrderRootType.BRACKET || isBracketOrder(order);
|
|
5474
|
+
if (order.order_type === OrderType.SCALED) {
|
|
5475
|
+
return "/v1/batch-order";
|
|
5476
|
+
}
|
|
5477
|
+
return isAlgoOrder ? "/v1/algo/order" : "/v1/order";
|
|
5478
|
+
};
|
|
5479
|
+
var getOrderCreator = (order) => {
|
|
5480
|
+
let type;
|
|
5481
|
+
if (isBracketOrder(order)) {
|
|
5482
|
+
type = `${AlgoOrderRootType.BRACKET}:${order.order_type}`;
|
|
5483
|
+
} else if (order.order_type === OrderType.LIMIT) {
|
|
5484
|
+
type = order.order_type_ext || order.order_type;
|
|
5485
|
+
} else {
|
|
5486
|
+
type = order.order_type;
|
|
5487
|
+
}
|
|
5488
|
+
return OrderFactory.create(type);
|
|
5489
|
+
};
|
|
5490
|
+
var tpslFields = [
|
|
5491
|
+
"tp_trigger_price",
|
|
5492
|
+
"sl_trigger_price",
|
|
5493
|
+
"tp_pnl",
|
|
5494
|
+
"sl_pnl",
|
|
5495
|
+
"tp_offset",
|
|
5496
|
+
"sl_offset",
|
|
5497
|
+
"tp_offset_percentage",
|
|
5498
|
+
"sl_offset_percentage"
|
|
5499
|
+
];
|
|
5500
|
+
var isBracketOrder = (order) => {
|
|
5501
|
+
return !!order.tp_trigger_price || !!order.sl_trigger_price;
|
|
5502
|
+
};
|
|
5503
|
+
var hasTPSL = (order) => {
|
|
5504
|
+
return tpslFields.some((field) => !!order[field]);
|
|
5505
|
+
};
|
|
5506
|
+
function getOrderPrice(order, askAndBid) {
|
|
5507
|
+
const orderPrice = Number(order.order_price);
|
|
5508
|
+
if (order.order_type === OrderType.MARKET || order.order_type === OrderType.STOP_MARKET) {
|
|
5509
|
+
if (order.side === OrderSide.BUY) {
|
|
5510
|
+
return askAndBid[0];
|
|
5511
|
+
} else {
|
|
5512
|
+
return askAndBid[1];
|
|
5513
|
+
}
|
|
5514
|
+
} else {
|
|
5515
|
+
if (order.side === OrderSide.BUY) {
|
|
5516
|
+
if (orderPrice >= askAndBid[0]) {
|
|
5517
|
+
return askAndBid[0];
|
|
5518
|
+
} else {
|
|
5519
|
+
return orderPrice;
|
|
5520
|
+
}
|
|
5521
|
+
} else {
|
|
5522
|
+
if (orderPrice <= askAndBid[1]) {
|
|
5523
|
+
return askAndBid[1];
|
|
5524
|
+
} else {
|
|
5525
|
+
return orderPrice;
|
|
5526
|
+
}
|
|
5527
|
+
}
|
|
5528
|
+
}
|
|
5529
|
+
}
|
|
5530
|
+
var getPriceAndQty = (order, symbolInfo, askAndBid) => {
|
|
5531
|
+
let quantity = Number(order.order_quantity);
|
|
5532
|
+
const orderPrice = Number(order.order_price);
|
|
5533
|
+
if (isNaN(quantity) || quantity <= 0) {
|
|
5534
|
+
return null;
|
|
5535
|
+
}
|
|
5536
|
+
if (askAndBid.length === 0) {
|
|
5537
|
+
return null;
|
|
5538
|
+
}
|
|
5539
|
+
if ((order.order_type === OrderType.LIMIT || order.order_type === OrderType.STOP_LIMIT) && isNaN(orderPrice)) {
|
|
5540
|
+
return null;
|
|
5541
|
+
}
|
|
5542
|
+
let price;
|
|
5543
|
+
if (order.order_type === OrderType.SCALED) {
|
|
5544
|
+
price = calcScaledOrderAvgOrderPrice(order, symbolInfo, askAndBid);
|
|
5545
|
+
const orders = calcScaledOrderBatchBody(order, symbolInfo);
|
|
5546
|
+
const sumQtys = orders.reduce((acc, order2) => {
|
|
5547
|
+
return acc.plus(new Decimal(order2.order_quantity));
|
|
5548
|
+
}, zero);
|
|
5549
|
+
quantity = sumQtys.todp(symbolInfo.base_dp).toNumber();
|
|
5550
|
+
if (!quantity || isNaN(quantity)) {
|
|
5551
|
+
return null;
|
|
5552
|
+
}
|
|
5553
|
+
} else {
|
|
5554
|
+
price = getOrderPrice(order, askAndBid);
|
|
5555
|
+
}
|
|
5556
|
+
if (!price || isNaN(price)) {
|
|
5557
|
+
return null;
|
|
5558
|
+
}
|
|
5559
|
+
if (order.side === OrderSide.SELL) {
|
|
5560
|
+
quantity = -quantity;
|
|
5561
|
+
}
|
|
5562
|
+
return { price, quantity };
|
|
5563
|
+
};
|
|
5564
|
+
var calcEstLiqPrice = (order$1, askAndBid, inputs) => {
|
|
5565
|
+
const { symbolInfo } = inputs;
|
|
5566
|
+
const result = getPriceAndQty(order$1, symbolInfo, askAndBid);
|
|
5567
|
+
if (!result)
|
|
5568
|
+
return null;
|
|
5569
|
+
const { price, quantity } = result;
|
|
5570
|
+
if (!price || !quantity)
|
|
5571
|
+
return null;
|
|
5572
|
+
const {
|
|
5573
|
+
symbol,
|
|
5574
|
+
imr_factor,
|
|
5575
|
+
markPrice,
|
|
5576
|
+
totalCollateral,
|
|
5577
|
+
futures_taker_fee_rate,
|
|
5578
|
+
positions: positions3
|
|
5579
|
+
} = inputs;
|
|
5580
|
+
const orderFee = order.orderFee({
|
|
5581
|
+
qty: quantity,
|
|
5582
|
+
price,
|
|
5583
|
+
futuresTakeFeeRate: Number(futures_taker_fee_rate) / 1e4
|
|
5584
|
+
});
|
|
5585
|
+
const liqPrice = order.estLiqPrice({
|
|
5586
|
+
markPrice,
|
|
5587
|
+
baseIMR: symbolInfo.base_imr,
|
|
5588
|
+
baseMMR: symbolInfo.base_mmr,
|
|
5589
|
+
totalCollateral,
|
|
5590
|
+
positions: positions3 == null ? [] : positions3,
|
|
5591
|
+
IMR_Factor: imr_factor,
|
|
5592
|
+
orderFee,
|
|
5593
|
+
newOrder: {
|
|
5594
|
+
qty: quantity,
|
|
5595
|
+
price,
|
|
5596
|
+
symbol
|
|
5597
|
+
}
|
|
5598
|
+
});
|
|
5599
|
+
if (liqPrice <= 0)
|
|
5600
|
+
return null;
|
|
5601
|
+
return liqPrice;
|
|
5602
|
+
};
|
|
5603
|
+
var calcEstLeverage = (order$1, askAndBid, inputs) => {
|
|
5604
|
+
const { totalCollateral, positions: positions3, symbol, symbolInfo } = inputs;
|
|
5605
|
+
const result = getPriceAndQty(order$1, symbolInfo, askAndBid);
|
|
5606
|
+
if (!result)
|
|
5607
|
+
return null;
|
|
5608
|
+
const { price, quantity } = result;
|
|
5609
|
+
if (!price || !quantity)
|
|
5610
|
+
return null;
|
|
5611
|
+
return order.estLeverage({
|
|
5612
|
+
totalCollateral,
|
|
5613
|
+
positions: positions3,
|
|
5614
|
+
newOrder: {
|
|
5615
|
+
symbol,
|
|
5616
|
+
qty: result.quantity,
|
|
5617
|
+
price: result.price
|
|
5618
|
+
}
|
|
5619
|
+
});
|
|
5620
|
+
};
|
|
5621
|
+
function isBBOOrder(options) {
|
|
5622
|
+
const { order_type, order_type_ext } = options;
|
|
5623
|
+
return order_type === OrderType.LIMIT && [OrderType.ASK, OrderType.BID].includes(order_type_ext);
|
|
5624
|
+
}
|
|
5625
|
+
function calcScaledOrderPrices(inputs) {
|
|
5626
|
+
const { min_price, max_price, total_orders, quote_dp } = inputs;
|
|
5627
|
+
if (!min_price || !max_price || !total_orders) {
|
|
5628
|
+
return [];
|
|
5629
|
+
}
|
|
5630
|
+
const minPrice3 = new Decimal(min_price);
|
|
5631
|
+
const maxPrice3 = new Decimal(max_price);
|
|
5632
|
+
const totalOrders = Number(total_orders);
|
|
5633
|
+
const priceStep = maxPrice3.minus(minPrice3).div(totalOrders - 1);
|
|
5634
|
+
const prices = [];
|
|
5635
|
+
for (let i = 0; i < totalOrders; i++) {
|
|
5636
|
+
prices[i] = minPrice3.plus(priceStep.mul(i)).todp(quote_dp).toString();
|
|
5637
|
+
}
|
|
5638
|
+
return prices;
|
|
5639
|
+
}
|
|
5640
|
+
function getScaledOrderSkew(inputs) {
|
|
5641
|
+
const { skew, distribution_type, total_orders } = inputs;
|
|
5642
|
+
if (distribution_type === DistributionType.FLAT) {
|
|
5643
|
+
return 1;
|
|
5644
|
+
} else if (distribution_type === DistributionType.ASCENDING) {
|
|
5645
|
+
return total_orders;
|
|
5646
|
+
} else if (distribution_type === DistributionType.DESCENDING) {
|
|
5647
|
+
return 1 / total_orders;
|
|
5648
|
+
}
|
|
5649
|
+
return skew;
|
|
5650
|
+
}
|
|
5651
|
+
function calcScaledOrderWeights(inputs) {
|
|
5652
|
+
const { total_orders, distribution_type, skew } = inputs;
|
|
5653
|
+
const weights = [];
|
|
5654
|
+
if (!total_orders || !distribution_type || distribution_type === DistributionType.CUSTOM && (!skew || skew <= 0 || skew > 100)) {
|
|
5655
|
+
return {
|
|
5656
|
+
weights: [],
|
|
5657
|
+
sumWeights: 0,
|
|
5658
|
+
minWeight: 0
|
|
5659
|
+
};
|
|
5660
|
+
}
|
|
5661
|
+
const totalOrders = Number(total_orders);
|
|
5662
|
+
const skewNum = getScaledOrderSkew({
|
|
5663
|
+
skew,
|
|
5664
|
+
distribution_type,
|
|
5665
|
+
total_orders: totalOrders
|
|
5666
|
+
});
|
|
5667
|
+
for (let i = 0; i < totalOrders; i++) {
|
|
5668
|
+
weights[i] = 1 + (skewNum - 1) * i / (totalOrders - 1);
|
|
5669
|
+
}
|
|
5670
|
+
const sumWeights = weights.reduce((acc, cur) => acc + cur, 0);
|
|
5671
|
+
const minWeight = weights.reduce(
|
|
5672
|
+
(min3, current) => current < min3 ? current : min3,
|
|
5673
|
+
weights?.[0]
|
|
5674
|
+
);
|
|
5675
|
+
return {
|
|
5676
|
+
weights,
|
|
5677
|
+
sumWeights,
|
|
5678
|
+
minWeight
|
|
5679
|
+
};
|
|
5680
|
+
}
|
|
5681
|
+
function calcScaledOrderQtys(inputs) {
|
|
5682
|
+
const {
|
|
5683
|
+
order_quantity = 0,
|
|
5684
|
+
total_orders = 0,
|
|
5685
|
+
distribution_type,
|
|
5686
|
+
skew,
|
|
5687
|
+
base_dp,
|
|
5688
|
+
base_tick
|
|
5689
|
+
} = inputs;
|
|
5690
|
+
const qtys = [];
|
|
5691
|
+
if (!order_quantity || !total_orders) {
|
|
5692
|
+
return [];
|
|
5693
|
+
}
|
|
5694
|
+
const { weights, sumWeights } = calcScaledOrderWeights({
|
|
5695
|
+
total_orders,
|
|
5696
|
+
distribution_type,
|
|
5697
|
+
skew
|
|
5698
|
+
});
|
|
5699
|
+
for (let i = 0; i < total_orders; i++) {
|
|
5700
|
+
let qty = new Decimal(order_quantity).mul(weights[i]).div(sumWeights);
|
|
5701
|
+
if (base_tick > 1) {
|
|
5702
|
+
qty = qty.div(base_tick).todp(0, Decimal.ROUND_DOWN).mul(base_tick);
|
|
5703
|
+
} else {
|
|
5704
|
+
qty = qty.todp(base_dp);
|
|
5705
|
+
}
|
|
5706
|
+
qtys[i] = qty.toString();
|
|
5707
|
+
}
|
|
5708
|
+
return qtys;
|
|
5709
|
+
}
|
|
5710
|
+
function calcScaledOrderBatchBody(order, symbolInfo) {
|
|
5711
|
+
if (!validateScaledOrderInput(order)) {
|
|
5712
|
+
return [];
|
|
5713
|
+
}
|
|
5714
|
+
try {
|
|
5715
|
+
const { base_dp, quote_dp, base_tick } = symbolInfo;
|
|
5716
|
+
const {
|
|
5717
|
+
symbol,
|
|
5718
|
+
side,
|
|
5719
|
+
order_quantity,
|
|
5720
|
+
min_price,
|
|
5721
|
+
max_price,
|
|
5722
|
+
total_orders,
|
|
5723
|
+
distribution_type,
|
|
5724
|
+
skew,
|
|
5725
|
+
reduce_only,
|
|
5726
|
+
visible_quantity
|
|
5727
|
+
} = order;
|
|
5728
|
+
const prices = calcScaledOrderPrices({
|
|
5729
|
+
min_price,
|
|
5730
|
+
max_price,
|
|
5731
|
+
total_orders,
|
|
5732
|
+
quote_dp
|
|
5733
|
+
});
|
|
5734
|
+
const qtys = calcScaledOrderQtys({
|
|
5735
|
+
side,
|
|
5736
|
+
order_quantity,
|
|
5737
|
+
total_orders,
|
|
5738
|
+
distribution_type,
|
|
5739
|
+
skew,
|
|
5740
|
+
base_dp,
|
|
5741
|
+
base_tick
|
|
5742
|
+
});
|
|
5743
|
+
const now = Date.now();
|
|
5744
|
+
const orders = prices.map((price, index) => {
|
|
5745
|
+
const subOrder = {
|
|
5746
|
+
symbol,
|
|
5747
|
+
side,
|
|
5748
|
+
// this order type is scaled order, so we need to set the order type to limit
|
|
5749
|
+
order_type: OrderType.LIMIT,
|
|
5750
|
+
order_quantity: qtys[index],
|
|
5751
|
+
order_price: price,
|
|
5752
|
+
reduce_only,
|
|
5753
|
+
// it will be used for identify the scaled order from ws
|
|
5754
|
+
client_order_id: `scaled_${index}_${now}`
|
|
5755
|
+
};
|
|
5756
|
+
if (visible_quantity === 0) {
|
|
5757
|
+
subOrder.visible_quantity = visible_quantity;
|
|
5758
|
+
}
|
|
5759
|
+
return subOrder;
|
|
5760
|
+
});
|
|
5761
|
+
return orders;
|
|
5762
|
+
} catch (error) {
|
|
5763
|
+
return [];
|
|
5764
|
+
}
|
|
5765
|
+
}
|
|
5766
|
+
function calcScaledOrderAvgOrderPrice(order, symbolInfo, askAndBid) {
|
|
5767
|
+
if (!validateScaledOrderInput(order)) {
|
|
5768
|
+
return null;
|
|
5769
|
+
}
|
|
5770
|
+
try {
|
|
5771
|
+
const orders = calcScaledOrderBatchBody(order, symbolInfo);
|
|
5772
|
+
const sumQtys = orders.reduce((acc, order2) => {
|
|
5773
|
+
return acc.plus(new Decimal(order2.order_quantity));
|
|
5774
|
+
}, zero);
|
|
5775
|
+
const totalNational = orders.reduce((acc, order2) => {
|
|
5776
|
+
const orderPrice = getOrderPrice(order2, askAndBid);
|
|
5777
|
+
return acc.plus(new Decimal(orderPrice).mul(order2.order_quantity));
|
|
5778
|
+
}, zero);
|
|
5779
|
+
return totalNational.div(sumQtys).todp(symbolInfo.quote_dp).toNumber();
|
|
5780
|
+
} catch (error) {
|
|
5781
|
+
return null;
|
|
5782
|
+
}
|
|
5783
|
+
}
|
|
5784
|
+
function validateScaledOrderInput(order) {
|
|
5785
|
+
const {
|
|
5786
|
+
min_price,
|
|
5787
|
+
max_price,
|
|
5788
|
+
order_quantity,
|
|
5789
|
+
total_orders,
|
|
5790
|
+
distribution_type,
|
|
5791
|
+
skew
|
|
5792
|
+
} = order;
|
|
5793
|
+
if (!min_price || !max_price || !order_quantity || !total_orders || !distribution_type || distribution_type === DistributionType.CUSTOM && (!skew || skew <= 0 || skew > 100) || total_orders < 2 || total_orders > 20) {
|
|
5794
|
+
return false;
|
|
5795
|
+
}
|
|
5796
|
+
return true;
|
|
5797
|
+
}
|
|
5798
|
+
function calcScaledOrderMinTotalAmount(order, symbolInfo, askAndBid) {
|
|
5799
|
+
try {
|
|
5800
|
+
const minTotalAmount_baseMin = calcScaledOrderMinTotalAmountByBaseMin(
|
|
5801
|
+
order,
|
|
5802
|
+
symbolInfo
|
|
5803
|
+
);
|
|
5804
|
+
const minTotalAmount_minNotional = calcScaledOrderMinTotalAmountByMinNotional(order, symbolInfo, askAndBid);
|
|
5805
|
+
const minTotalAmount = Math.max(
|
|
5806
|
+
minTotalAmount_baseMin,
|
|
5807
|
+
minTotalAmount_minNotional
|
|
5808
|
+
);
|
|
5809
|
+
return minTotalAmount;
|
|
5810
|
+
} catch (error) {
|
|
5811
|
+
return null;
|
|
5812
|
+
}
|
|
5813
|
+
}
|
|
5814
|
+
function calcScaledOrderMinTotalAmountByBaseMin(order, symbolInfo) {
|
|
5815
|
+
const { total_orders, distribution_type, skew } = order;
|
|
5816
|
+
const { base_min, base_dp } = symbolInfo;
|
|
5817
|
+
const { sumWeights, minWeight } = calcScaledOrderWeights({
|
|
5818
|
+
total_orders,
|
|
5819
|
+
distribution_type,
|
|
5820
|
+
skew
|
|
5821
|
+
});
|
|
5822
|
+
const minTotalAmount = new Decimal(base_min).mul(new Decimal(sumWeights).div(minWeight)).todp(base_dp, Decimal.ROUND_UP).toNumber();
|
|
5823
|
+
return minTotalAmount;
|
|
5824
|
+
}
|
|
5825
|
+
function calcScaledOrderMinTotalAmountByMinNotional(order, symbolInfo, askAndBid) {
|
|
5826
|
+
const { base_dp, min_notional } = symbolInfo;
|
|
5827
|
+
const orders = calcScaledOrderBatchBody(order, symbolInfo);
|
|
5828
|
+
const { total_orders, distribution_type, skew } = order;
|
|
5829
|
+
const { weights, sumWeights } = calcScaledOrderWeights({
|
|
5830
|
+
total_orders,
|
|
5831
|
+
distribution_type,
|
|
5832
|
+
skew
|
|
5833
|
+
});
|
|
5834
|
+
const minQtys = orders.map((order2, i) => {
|
|
5835
|
+
const orderPrice = getOrderPrice(order2, askAndBid);
|
|
5836
|
+
return new Decimal(min_notional).mul(sumWeights).div(new Decimal(weights[i]).mul(orderPrice));
|
|
5837
|
+
});
|
|
5838
|
+
const max_minQty = minQtys.reduce(
|
|
5839
|
+
(max3, current) => current.gt(max3) ? current : max3,
|
|
5840
|
+
minQtys?.[0]
|
|
5841
|
+
);
|
|
5842
|
+
return max_minQty.todp(base_dp, Decimal.ROUND_UP).toNumber();
|
|
5843
|
+
}
|
|
5844
|
+
|
|
5845
|
+
// src/services/orderCreator/scaledOrderCreator.ts
|
|
5846
|
+
var ScaledOrderCreator = class extends BaseOrderCreator {
|
|
5847
|
+
constructor() {
|
|
5848
|
+
super(...arguments);
|
|
5849
|
+
this.orderType = OrderType.SCALED;
|
|
5850
|
+
}
|
|
5851
|
+
create(values2, config) {
|
|
5852
|
+
const orders = calcScaledOrderBatchBody(values2, config.symbol);
|
|
5853
|
+
const { total_orders, distribution_type, skew } = values2;
|
|
5854
|
+
const order = {
|
|
5855
|
+
...this.baseOrder(values2),
|
|
5856
|
+
total_orders,
|
|
5857
|
+
distribution_type,
|
|
5858
|
+
skew,
|
|
5859
|
+
orders
|
|
5860
|
+
};
|
|
5861
|
+
return pick(
|
|
5862
|
+
[
|
|
5863
|
+
"symbol",
|
|
5864
|
+
"order_quantity",
|
|
5865
|
+
"visible_quantity",
|
|
5866
|
+
"reduce_only",
|
|
5867
|
+
"side",
|
|
5868
|
+
"order_type",
|
|
5869
|
+
"orders",
|
|
5870
|
+
"total_orders",
|
|
5871
|
+
"distribution_type",
|
|
5872
|
+
"skew"
|
|
5873
|
+
],
|
|
5874
|
+
order
|
|
5875
|
+
);
|
|
5876
|
+
}
|
|
5877
|
+
validatePrice(values2, config) {
|
|
5878
|
+
const errors = {};
|
|
5879
|
+
const { side, min_price, max_price } = values2;
|
|
5880
|
+
const { price_range, price_scope, quote_max, quote_min, quote_dp } = config.symbol;
|
|
5881
|
+
const maxPriceNumber = order.maxPrice(config.markPrice, price_range);
|
|
5882
|
+
const minPriceNumber = order.minPrice(config.markPrice, price_range);
|
|
5883
|
+
const scopePriceNumber = order.scopePrice(
|
|
5884
|
+
config.markPrice,
|
|
5885
|
+
price_scope,
|
|
5886
|
+
side
|
|
5887
|
+
);
|
|
5888
|
+
const priceRange = side === OrderSide.BUY ? {
|
|
5889
|
+
min: scopePriceNumber,
|
|
5890
|
+
max: maxPriceNumber
|
|
5891
|
+
} : {
|
|
5892
|
+
min: minPriceNumber,
|
|
5893
|
+
max: scopePriceNumber
|
|
5894
|
+
};
|
|
5895
|
+
const minPrice3 = Number(min_price || 0);
|
|
5896
|
+
const maxPrice3 = Number(max_price || 0);
|
|
5897
|
+
if (!min_price) {
|
|
5898
|
+
errors.min_price = OrderValidation.required("min_price");
|
|
5899
|
+
} else {
|
|
5900
|
+
if (minPrice3 < priceRange?.min) {
|
|
5901
|
+
errors.min_price = OrderValidation.min(
|
|
5902
|
+
"min_price",
|
|
5903
|
+
new Decimal(priceRange.min).todp(quote_dp).toString()
|
|
5904
|
+
);
|
|
5905
|
+
} else if (minPrice3 < quote_min) {
|
|
5906
|
+
errors.min_price = OrderValidation.min("min_price", quote_min);
|
|
5907
|
+
} else if (minPrice3 > maxPrice3) {
|
|
5908
|
+
errors.min_price = OrderValidation.max("min_price", max_price);
|
|
5909
|
+
}
|
|
5910
|
+
}
|
|
5911
|
+
if (!max_price) {
|
|
5912
|
+
errors.max_price = OrderValidation.required("max_price");
|
|
5913
|
+
} else {
|
|
5914
|
+
if (maxPrice3 < priceRange?.min) {
|
|
5915
|
+
errors.max_price = OrderValidation.min(
|
|
5916
|
+
"max_price",
|
|
5917
|
+
new Decimal(priceRange.min).todp(quote_dp).toString()
|
|
5918
|
+
);
|
|
5919
|
+
} else if (maxPrice3 > priceRange?.max) {
|
|
5920
|
+
errors.max_price = OrderValidation.max(
|
|
5921
|
+
"max_price",
|
|
5922
|
+
new Decimal(priceRange.max).todp(quote_dp).toString()
|
|
5923
|
+
);
|
|
5924
|
+
} else if (maxPrice3 > quote_max) {
|
|
5925
|
+
errors.max_price = OrderValidation.max("max_price", quote_max);
|
|
5926
|
+
}
|
|
5927
|
+
}
|
|
5928
|
+
return errors;
|
|
5929
|
+
}
|
|
5930
|
+
async validate(values2, config) {
|
|
5931
|
+
const { base_dp } = config.symbol;
|
|
5932
|
+
const { maxQty, askAndBid } = config;
|
|
5933
|
+
const { order_quantity, total_orders, distribution_type, skew } = values2;
|
|
5934
|
+
const errors = this.validatePrice(values2, config);
|
|
5935
|
+
if (!total_orders) {
|
|
5936
|
+
errors.total_orders = OrderValidation.required("total_orders");
|
|
5937
|
+
} else {
|
|
5938
|
+
const totalOrdersNum = Number(total_orders);
|
|
5939
|
+
if (totalOrdersNum < 2 || totalOrdersNum > 20) {
|
|
5940
|
+
errors.total_orders = OrderValidation.range("total_orders", 2, 20);
|
|
5941
|
+
}
|
|
5942
|
+
}
|
|
5943
|
+
if (distribution_type === DistributionType.CUSTOM) {
|
|
5944
|
+
if (!skew) {
|
|
5945
|
+
errors.skew = OrderValidation.required("skew");
|
|
5946
|
+
} else {
|
|
5947
|
+
const skewNum = Number(skew);
|
|
5948
|
+
if (skewNum <= 0) {
|
|
5949
|
+
errors.skew = OrderValidation.min("skew", 0);
|
|
5950
|
+
} else if (skewNum > 100) {
|
|
5951
|
+
errors.skew = OrderValidation.max("skew", 100);
|
|
5952
|
+
}
|
|
5953
|
+
}
|
|
5954
|
+
}
|
|
5955
|
+
if (!order_quantity) {
|
|
5956
|
+
errors.order_quantity = OrderValidation.required("order_quantity");
|
|
5957
|
+
} else {
|
|
5958
|
+
const qty = new Decimal(order_quantity);
|
|
5959
|
+
if (qty.gt(maxQty)) {
|
|
5960
|
+
errors.order_quantity = OrderValidation.max(
|
|
5961
|
+
"order_quantity",
|
|
5962
|
+
new Decimal(maxQty).todp(base_dp).toString()
|
|
5963
|
+
);
|
|
5964
|
+
} else if (!errors.skew && !errors.total_orders) {
|
|
5965
|
+
const minTotalAmount = calcScaledOrderMinTotalAmount(
|
|
5966
|
+
values2,
|
|
5967
|
+
config.symbol,
|
|
5968
|
+
askAndBid
|
|
5969
|
+
);
|
|
5970
|
+
if (minTotalAmount && qty.lt(minTotalAmount)) {
|
|
5971
|
+
errors.order_quantity = OrderValidation.min(
|
|
5972
|
+
"order_quantity",
|
|
5973
|
+
minTotalAmount
|
|
5974
|
+
);
|
|
5975
|
+
}
|
|
5976
|
+
}
|
|
5977
|
+
}
|
|
5978
|
+
return errors;
|
|
5979
|
+
}
|
|
5980
|
+
};
|
|
5981
|
+
var { maxPrice: maxPrice2, minPrice: minPrice2, scopePrice: scopePrice2 } = order;
|
|
5982
|
+
var StopLimitOrderCreator = class extends BaseOrderCreator {
|
|
5983
|
+
constructor() {
|
|
5984
|
+
super(...arguments);
|
|
5985
|
+
this.orderType = OrderType.STOP_LIMIT;
|
|
5986
|
+
}
|
|
5987
|
+
create(values2, config) {
|
|
5988
|
+
this.totalToQuantity(values2, config);
|
|
5989
|
+
const order = {
|
|
5990
|
+
...this.baseOrder(values2),
|
|
5991
|
+
trigger_price: values2.trigger_price,
|
|
5992
|
+
algo_type: AlgoOrderRootType.STOP,
|
|
5993
|
+
type: OrderType.LIMIT,
|
|
5994
|
+
quantity: values2["order_quantity"],
|
|
5995
|
+
price: values2["order_price"],
|
|
5996
|
+
trigger_price_type: TriggerPriceType.MARK_PRICE
|
|
5997
|
+
};
|
|
5998
|
+
return pick(
|
|
5999
|
+
[
|
|
6000
|
+
"symbol",
|
|
6001
|
+
"trigger_price",
|
|
6002
|
+
"algo_type",
|
|
6003
|
+
"type",
|
|
6004
|
+
"quantity",
|
|
6005
|
+
"price",
|
|
6006
|
+
"trigger_price_type",
|
|
6007
|
+
"side",
|
|
6008
|
+
"reduce_only",
|
|
6009
|
+
"visible_quantity"
|
|
6010
|
+
],
|
|
6011
|
+
order
|
|
6012
|
+
);
|
|
6013
|
+
}
|
|
6014
|
+
validate(values2, config) {
|
|
6015
|
+
return this.baseValidate(values2, config).then((errors) => {
|
|
6016
|
+
const { order_price, trigger_price, side } = values2;
|
|
6017
|
+
const { symbol } = config;
|
|
6018
|
+
const { price_range, price_scope, quote_max, quote_min } = symbol;
|
|
6019
|
+
if (!trigger_price) {
|
|
6020
|
+
errors.trigger_price = OrderValidation.required("trigger_price");
|
|
6021
|
+
}
|
|
6022
|
+
if (!order_price) {
|
|
6023
|
+
errors.order_price = OrderValidation.required("order_price");
|
|
6024
|
+
}
|
|
6025
|
+
if (trigger_price > quote_max) {
|
|
6026
|
+
errors.trigger_price = OrderValidation.max("trigger_price", quote_max);
|
|
6027
|
+
} else if (trigger_price < quote_min) {
|
|
6028
|
+
errors.trigger_price = OrderValidation.min("trigger_price", quote_min);
|
|
6029
|
+
} else {
|
|
6030
|
+
if (trigger_price && order_price) {
|
|
6031
|
+
const price = new Decimal(order_price);
|
|
6032
|
+
const maxPriceNumber = maxPrice2(trigger_price, price_range);
|
|
6033
|
+
const minPriceNumber = minPrice2(trigger_price, price_range);
|
|
6034
|
+
const scropePriceNumbere = scopePrice2(
|
|
6035
|
+
trigger_price,
|
|
6036
|
+
price_scope,
|
|
6037
|
+
side
|
|
6038
|
+
);
|
|
6039
|
+
const priceRange = side === "BUY" ? {
|
|
6040
|
+
min: scropePriceNumbere,
|
|
6041
|
+
max: maxPriceNumber
|
|
6042
|
+
} : {
|
|
6043
|
+
min: minPriceNumber,
|
|
6044
|
+
max: scropePriceNumbere
|
|
6045
|
+
};
|
|
6046
|
+
if (price.gt(quote_max)) {
|
|
6047
|
+
errors.order_price = OrderValidation.max("order_price", quote_max);
|
|
6048
|
+
} else {
|
|
6049
|
+
if (price.gt(priceRange?.max)) {
|
|
6050
|
+
errors.order_price = OrderValidation.max(
|
|
6051
|
+
"order_price",
|
|
6052
|
+
new Decimal(priceRange.max).todp(symbol.quote_dp).toString()
|
|
6053
|
+
);
|
|
6054
|
+
}
|
|
6055
|
+
}
|
|
6056
|
+
if (price.lt(quote_min)) {
|
|
6057
|
+
errors.order_price = OrderValidation.min("order_price", quote_min);
|
|
6058
|
+
} else {
|
|
6059
|
+
if (price.lt(priceRange?.min)) {
|
|
6060
|
+
errors.order_price = OrderValidation.min(
|
|
6061
|
+
"order_price",
|
|
6062
|
+
new Decimal(priceRange.min).todp(symbol.quote_dp).toString()
|
|
6063
|
+
);
|
|
6064
|
+
}
|
|
6065
|
+
}
|
|
6066
|
+
}
|
|
6067
|
+
}
|
|
6068
|
+
return errors;
|
|
6069
|
+
});
|
|
6070
|
+
}
|
|
6071
|
+
};
|
|
6072
|
+
var StopMarketOrderCreator = class extends BaseOrderCreator {
|
|
6073
|
+
create(values2) {
|
|
6074
|
+
const order = {
|
|
6075
|
+
...this.baseOrder(values2),
|
|
6076
|
+
// order_price: values.order_price,
|
|
6077
|
+
trigger_price: values2.trigger_price,
|
|
6078
|
+
algo_type: AlgoOrderRootType.STOP,
|
|
6079
|
+
type: OrderType.MARKET,
|
|
6080
|
+
quantity: values2["order_quantity"],
|
|
6081
|
+
// price: values["order_price"],
|
|
6082
|
+
trigger_price_type: TriggerPriceType.MARK_PRICE
|
|
6083
|
+
};
|
|
6084
|
+
return pick(
|
|
5402
6085
|
[
|
|
5403
6086
|
"symbol",
|
|
5404
6087
|
"trigger_price",
|
|
@@ -5431,18 +6114,6 @@ var StopMarketOrderCreator = class extends BaseOrderCreator {
|
|
|
5431
6114
|
});
|
|
5432
6115
|
}
|
|
5433
6116
|
};
|
|
5434
|
-
|
|
5435
|
-
// src/services/orderCreator/postOnlyCreator.ts
|
|
5436
|
-
var PostOnlyOrderCreator = class extends LimitOrderCreator {
|
|
5437
|
-
};
|
|
5438
|
-
|
|
5439
|
-
// src/services/orderCreator/fokCreator.ts
|
|
5440
|
-
var FOKOrderCreator = class extends LimitOrderCreator {
|
|
5441
|
-
};
|
|
5442
|
-
|
|
5443
|
-
// src/services/orderCreator/iocCreator.ts
|
|
5444
|
-
var IOCOrderCreator = class extends LimitOrderCreator {
|
|
5445
|
-
};
|
|
5446
6117
|
var BaseAlgoOrderCreator = class {
|
|
5447
6118
|
/**
|
|
5448
6119
|
* base validate
|
|
@@ -5646,216 +6317,58 @@ var TPSLPositionOrderCreator = class extends BaseAlgoOrderCreator {
|
|
|
5646
6317
|
type: OrderType.CLOSE_POSITION,
|
|
5647
6318
|
trigger_price: tp_trigger_price,
|
|
5648
6319
|
trigger_price_type: TriggerPriceType.MARK_PRICE,
|
|
5649
|
-
symbol: values2.symbol,
|
|
5650
|
-
is_activated: !!values2.tp_trigger_price
|
|
5651
|
-
});
|
|
5652
|
-
}
|
|
5653
|
-
if (typeof values2.sl_trigger_price !== "undefined") {
|
|
5654
|
-
const sl_trigger_price = !!values2.sl_trigger_price ? new Decimal(values2.sl_trigger_price).todp(config.symbol.quote_dp).toNumber() : values2.sl_trigger_price;
|
|
5655
|
-
child_orders.push({
|
|
5656
|
-
algo_type: AlgoOrderType.STOP_LOSS,
|
|
5657
|
-
reduce_only: true,
|
|
5658
|
-
side,
|
|
5659
|
-
type: OrderType.CLOSE_POSITION,
|
|
5660
|
-
trigger_price: sl_trigger_price,
|
|
5661
|
-
trigger_price_type: TriggerPriceType.MARK_PRICE,
|
|
5662
|
-
symbol: values2.symbol,
|
|
5663
|
-
is_activated: !!values2.sl_trigger_price
|
|
5664
|
-
});
|
|
5665
|
-
}
|
|
5666
|
-
return {
|
|
5667
|
-
algo_type: AlgoOrderRootType.POSITIONAL_TP_SL,
|
|
5668
|
-
trigger_price_type: TriggerPriceType.MARK_PRICE,
|
|
5669
|
-
// reduce_only: true,
|
|
5670
|
-
symbol: values2.symbol,
|
|
5671
|
-
child_orders
|
|
5672
|
-
};
|
|
5673
|
-
}
|
|
5674
|
-
crateUpdateOrder(values2, oldValue, config) {
|
|
5675
|
-
const data = this.create(values2, config);
|
|
5676
|
-
const newData = [];
|
|
5677
|
-
data.child_orders.forEach((order) => {
|
|
5678
|
-
const oldOrder = oldValue.child_orders?.find(
|
|
5679
|
-
(oldOrder2) => oldOrder2.algo_type === order.algo_type
|
|
5680
|
-
);
|
|
5681
|
-
if (oldOrder) {
|
|
5682
|
-
if (!order.is_activated) {
|
|
5683
|
-
newData.push({
|
|
5684
|
-
is_activated: false,
|
|
5685
|
-
order_id: Number(oldOrder.algo_order_id)
|
|
5686
|
-
});
|
|
5687
|
-
} else if (oldOrder.trigger_price !== order.trigger_price) {
|
|
5688
|
-
newData.push({
|
|
5689
|
-
trigger_price: order.trigger_price,
|
|
5690
|
-
order_id: Number(oldOrder.algo_order_id)
|
|
5691
|
-
});
|
|
5692
|
-
}
|
|
5693
|
-
}
|
|
5694
|
-
});
|
|
5695
|
-
return [
|
|
5696
|
-
{
|
|
5697
|
-
child_orders: newData
|
|
5698
|
-
},
|
|
5699
|
-
data
|
|
5700
|
-
];
|
|
5701
|
-
}
|
|
5702
|
-
};
|
|
5703
|
-
async function bracketOrderValidator(values2, config) {
|
|
5704
|
-
const result = /* @__PURE__ */ Object.create(null);
|
|
5705
|
-
await Promise.resolve();
|
|
5706
|
-
const { tp_trigger_price, sl_trigger_price, side } = values2;
|
|
5707
|
-
const qty = Number(values2.quantity);
|
|
5708
|
-
const maxQty = config.maxQty;
|
|
5709
|
-
const type = values2.order_type;
|
|
5710
|
-
const { quote_max, quote_min, price_scope, quote_dp } = config.symbol ?? {};
|
|
5711
|
-
const mark_price = type === OrderType.MARKET ? config.markPrice : values2.order_price ? Number(values2.order_price) : void 0;
|
|
5712
|
-
if (!isNaN(qty) && qty > maxQty) {
|
|
5713
|
-
result.quantity = OrderValidation.max("quantity", config.maxQty);
|
|
5714
|
-
}
|
|
5715
|
-
if (Number(tp_trigger_price) < 0) {
|
|
5716
|
-
result.tp_trigger_price = OrderValidation.min("tp_trigger_price", 0);
|
|
5717
|
-
}
|
|
5718
|
-
if (Number(sl_trigger_price) < 0) {
|
|
5719
|
-
result.sl_trigger_price = OrderValidation.min("sl_trigger_price", 0);
|
|
5720
|
-
}
|
|
5721
|
-
if (side === OrderSide.BUY && mark_price) {
|
|
5722
|
-
const slTriggerPriceScope = new Decimal(mark_price * (1 - price_scope)).toDecimalPlaces(quote_dp, Decimal.ROUND_DOWN).toNumber();
|
|
5723
|
-
if (!!sl_trigger_price && Number(sl_trigger_price) < slTriggerPriceScope) {
|
|
5724
|
-
result.sl_trigger_price = OrderValidation.min(
|
|
5725
|
-
"sl_trigger_price",
|
|
5726
|
-
slTriggerPriceScope
|
|
5727
|
-
);
|
|
5728
|
-
}
|
|
5729
|
-
if (!!tp_trigger_price && Number(tp_trigger_price) <= mark_price) {
|
|
5730
|
-
result.tp_trigger_price = OrderValidation.min(
|
|
5731
|
-
"tp_trigger_price",
|
|
5732
|
-
mark_price
|
|
5733
|
-
);
|
|
5734
|
-
}
|
|
5735
|
-
if (!!tp_trigger_price && Number(tp_trigger_price) > quote_max) {
|
|
5736
|
-
result.tp_trigger_price = OrderValidation.max(
|
|
5737
|
-
"tp_trigger_price",
|
|
5738
|
-
quote_max
|
|
5739
|
-
);
|
|
5740
|
-
}
|
|
5741
|
-
if (!!sl_trigger_price && Number(sl_trigger_price) < quote_min) {
|
|
5742
|
-
result.sl_trigger_price = OrderValidation.min(
|
|
5743
|
-
"sl_trigger_price",
|
|
5744
|
-
quote_min
|
|
5745
|
-
);
|
|
5746
|
-
}
|
|
5747
|
-
}
|
|
5748
|
-
if (side === OrderSide.SELL && mark_price) {
|
|
5749
|
-
const slTriggerPriceScope = new Decimal(mark_price * (1 + price_scope)).toDecimalPlaces(quote_dp, Decimal.ROUND_DOWN).toNumber();
|
|
5750
|
-
if (!!sl_trigger_price && Number(sl_trigger_price) > slTriggerPriceScope) {
|
|
5751
|
-
result.sl_trigger_price = OrderValidation.max(
|
|
5752
|
-
"sl_trigger_price",
|
|
5753
|
-
slTriggerPriceScope
|
|
5754
|
-
);
|
|
5755
|
-
}
|
|
5756
|
-
if (!!tp_trigger_price && Number(tp_trigger_price) >= mark_price) {
|
|
5757
|
-
result.tp_trigger_price = OrderValidation.max(
|
|
5758
|
-
"tp_trigger_price",
|
|
5759
|
-
mark_price
|
|
5760
|
-
);
|
|
5761
|
-
}
|
|
5762
|
-
if (!!tp_trigger_price && Number(tp_trigger_price) > quote_max) {
|
|
5763
|
-
result.tp_trigger_price = OrderValidation.max(
|
|
5764
|
-
"tp_trigger_price",
|
|
5765
|
-
quote_max
|
|
5766
|
-
);
|
|
5767
|
-
}
|
|
5768
|
-
if (!!sl_trigger_price && Number(sl_trigger_price) < quote_min) {
|
|
5769
|
-
result.sl_trigger_price = OrderValidation.min(
|
|
5770
|
-
"sl_trigger_price",
|
|
5771
|
-
quote_min
|
|
5772
|
-
);
|
|
5773
|
-
}
|
|
5774
|
-
}
|
|
5775
|
-
return Object.keys(result).length > 0 ? result : null;
|
|
5776
|
-
}
|
|
5777
|
-
|
|
5778
|
-
// src/services/orderCreator/bracketLimitOrderCreator.ts
|
|
5779
|
-
var BracketLimitOrderCreator = class extends LimitOrderCreator {
|
|
5780
|
-
// orderType: OrderType;
|
|
5781
|
-
create(values2, config) {
|
|
5782
|
-
const order = super.create(values2, config);
|
|
5783
|
-
return {
|
|
5784
|
-
...order,
|
|
5785
|
-
quantity: order.order_quantity,
|
|
5786
|
-
type: order.order_type,
|
|
5787
|
-
price: order.order_price
|
|
5788
|
-
};
|
|
5789
|
-
}
|
|
5790
|
-
async validate(values2, config) {
|
|
5791
|
-
const value = await super.validate(values2, config);
|
|
5792
|
-
const bracketData = await bracketOrderValidator(values2, config);
|
|
5793
|
-
return { ...value, ...bracketData };
|
|
5794
|
-
}
|
|
5795
|
-
};
|
|
5796
|
-
var BracketMarketOrderCreator = class extends MarketOrderCreator {
|
|
5797
|
-
constructor() {
|
|
5798
|
-
super(...arguments);
|
|
5799
|
-
this.orderType = OrderType.MARKET;
|
|
5800
|
-
}
|
|
5801
|
-
create(values2) {
|
|
5802
|
-
const order = super.create(values2);
|
|
6320
|
+
symbol: values2.symbol,
|
|
6321
|
+
is_activated: !!values2.tp_trigger_price
|
|
6322
|
+
});
|
|
6323
|
+
}
|
|
6324
|
+
if (typeof values2.sl_trigger_price !== "undefined") {
|
|
6325
|
+
const sl_trigger_price = !!values2.sl_trigger_price ? new Decimal(values2.sl_trigger_price).todp(config.symbol.quote_dp).toNumber() : values2.sl_trigger_price;
|
|
6326
|
+
child_orders.push({
|
|
6327
|
+
algo_type: AlgoOrderType.STOP_LOSS,
|
|
6328
|
+
reduce_only: true,
|
|
6329
|
+
side,
|
|
6330
|
+
type: OrderType.CLOSE_POSITION,
|
|
6331
|
+
trigger_price: sl_trigger_price,
|
|
6332
|
+
trigger_price_type: TriggerPriceType.MARK_PRICE,
|
|
6333
|
+
symbol: values2.symbol,
|
|
6334
|
+
is_activated: !!values2.sl_trigger_price
|
|
6335
|
+
});
|
|
6336
|
+
}
|
|
5803
6337
|
return {
|
|
5804
|
-
|
|
5805
|
-
|
|
5806
|
-
|
|
5807
|
-
|
|
5808
|
-
|
|
5809
|
-
}
|
|
5810
|
-
async validate(values2, config) {
|
|
5811
|
-
const value = await super.validate(values2, config);
|
|
5812
|
-
const bracketData = await bracketOrderValidator(values2, config);
|
|
5813
|
-
return { ...value, ...bracketData };
|
|
5814
|
-
}
|
|
5815
|
-
};
|
|
5816
|
-
var BBOOrderCreator = class extends BaseOrderCreator {
|
|
5817
|
-
create(values2) {
|
|
5818
|
-
const order = {
|
|
5819
|
-
...this.baseOrder(values2),
|
|
5820
|
-
level: values2.level
|
|
6338
|
+
algo_type: AlgoOrderRootType.POSITIONAL_TP_SL,
|
|
6339
|
+
trigger_price_type: TriggerPriceType.MARK_PRICE,
|
|
6340
|
+
// reduce_only: true,
|
|
6341
|
+
symbol: values2.symbol,
|
|
6342
|
+
child_orders
|
|
5821
6343
|
};
|
|
5822
|
-
return pick(
|
|
5823
|
-
[
|
|
5824
|
-
"symbol",
|
|
5825
|
-
"order_quantity",
|
|
5826
|
-
"visible_quantity",
|
|
5827
|
-
"reduce_only",
|
|
5828
|
-
"side",
|
|
5829
|
-
"order_type",
|
|
5830
|
-
"level"
|
|
5831
|
-
],
|
|
5832
|
-
order
|
|
5833
|
-
);
|
|
5834
6344
|
}
|
|
5835
|
-
|
|
5836
|
-
|
|
5837
|
-
|
|
5838
|
-
|
|
5839
|
-
const
|
|
5840
|
-
|
|
5841
|
-
|
|
5842
|
-
|
|
5843
|
-
|
|
5844
|
-
|
|
5845
|
-
|
|
5846
|
-
|
|
5847
|
-
|
|
5848
|
-
|
|
5849
|
-
|
|
5850
|
-
|
|
5851
|
-
|
|
5852
|
-
|
|
5853
|
-
|
|
5854
|
-
value: minNotional
|
|
5855
|
-
};
|
|
6345
|
+
crateUpdateOrder(values2, oldValue, config) {
|
|
6346
|
+
const data = this.create(values2, config);
|
|
6347
|
+
const newData = [];
|
|
6348
|
+
data.child_orders.forEach((order) => {
|
|
6349
|
+
const oldOrder = oldValue.child_orders?.find(
|
|
6350
|
+
(oldOrder2) => oldOrder2.algo_type === order.algo_type
|
|
6351
|
+
);
|
|
6352
|
+
if (oldOrder) {
|
|
6353
|
+
if (!order.is_activated) {
|
|
6354
|
+
newData.push({
|
|
6355
|
+
is_activated: false,
|
|
6356
|
+
order_id: Number(oldOrder.algo_order_id)
|
|
6357
|
+
});
|
|
6358
|
+
} else if (oldOrder.trigger_price !== order.trigger_price) {
|
|
6359
|
+
newData.push({
|
|
6360
|
+
trigger_price: order.trigger_price,
|
|
6361
|
+
order_id: Number(oldOrder.algo_order_id)
|
|
6362
|
+
});
|
|
6363
|
+
}
|
|
5856
6364
|
}
|
|
5857
|
-
return errors;
|
|
5858
6365
|
});
|
|
6366
|
+
return [
|
|
6367
|
+
{
|
|
6368
|
+
child_orders: newData
|
|
6369
|
+
},
|
|
6370
|
+
data
|
|
6371
|
+
];
|
|
5859
6372
|
}
|
|
5860
6373
|
};
|
|
5861
6374
|
|
|
@@ -5884,6 +6397,8 @@ var OrderFactory = class {
|
|
|
5884
6397
|
return new StopLimitOrderCreator();
|
|
5885
6398
|
case OrderType.STOP_MARKET:
|
|
5886
6399
|
return new StopMarketOrderCreator();
|
|
6400
|
+
case OrderType.SCALED:
|
|
6401
|
+
return new ScaledOrderCreator();
|
|
5887
6402
|
case AlgoOrderRootType.TP_SL:
|
|
5888
6403
|
return new TPSLOrderCreator();
|
|
5889
6404
|
case AlgoOrderRootType.POSITIONAL_TP_SL:
|
|
@@ -7147,6 +7662,9 @@ var usePrivateDataObserver = (options) => {
|
|
|
7147
7662
|
return () => unsubscribe?.();
|
|
7148
7663
|
}, [account7.accountId]);
|
|
7149
7664
|
const isHoldingInit = useRef(false);
|
|
7665
|
+
useEffect(() => {
|
|
7666
|
+
isHoldingInit.current = false;
|
|
7667
|
+
}, [state.accountId]);
|
|
7150
7668
|
useEffect(() => {
|
|
7151
7669
|
if (!holding) {
|
|
7152
7670
|
return;
|
|
@@ -14506,137 +15024,6 @@ function getQueryParamsFromObject(obj) {
|
|
|
14506
15024
|
}
|
|
14507
15025
|
return queryParams.toString();
|
|
14508
15026
|
}
|
|
14509
|
-
var getCreateOrderUrl = (order) => {
|
|
14510
|
-
const isAlgoOrder = order?.order_type === OrderType.STOP_LIMIT || order?.order_type === OrderType.STOP_MARKET || order?.order_type === OrderType.CLOSE_POSITION || order.algo_type && order.algo_type === AlgoOrderRootType.BRACKET || isBracketOrder(order);
|
|
14511
|
-
return isAlgoOrder ? "/v1/algo/order" : "/v1/order";
|
|
14512
|
-
};
|
|
14513
|
-
var getOrderCreator = (order) => {
|
|
14514
|
-
let type;
|
|
14515
|
-
if (isBracketOrder(order)) {
|
|
14516
|
-
type = `${AlgoOrderRootType.BRACKET}:${order.order_type}`;
|
|
14517
|
-
} else if (order.order_type === OrderType.LIMIT) {
|
|
14518
|
-
type = order.order_type_ext || order.order_type;
|
|
14519
|
-
} else {
|
|
14520
|
-
type = order.order_type;
|
|
14521
|
-
}
|
|
14522
|
-
return OrderFactory.create(type);
|
|
14523
|
-
};
|
|
14524
|
-
var tpslFields = [
|
|
14525
|
-
"tp_trigger_price",
|
|
14526
|
-
"sl_trigger_price",
|
|
14527
|
-
"tp_pnl",
|
|
14528
|
-
"sl_pnl",
|
|
14529
|
-
"tp_offset",
|
|
14530
|
-
"sl_offset",
|
|
14531
|
-
"tp_offset_percentage",
|
|
14532
|
-
"sl_offset_percentage"
|
|
14533
|
-
];
|
|
14534
|
-
var isBracketOrder = (order) => {
|
|
14535
|
-
return !!order.tp_trigger_price || !!order.sl_trigger_price;
|
|
14536
|
-
};
|
|
14537
|
-
var hasTPSL = (order) => {
|
|
14538
|
-
return tpslFields.some((field) => !!order[field]);
|
|
14539
|
-
};
|
|
14540
|
-
var getPriceAndQty = (symbolOrOrder, askAndBid) => {
|
|
14541
|
-
let quantity = Number(symbolOrOrder.order_quantity);
|
|
14542
|
-
const orderPrice = Number(symbolOrOrder.order_price);
|
|
14543
|
-
if (isNaN(quantity) || quantity <= 0) {
|
|
14544
|
-
return null;
|
|
14545
|
-
}
|
|
14546
|
-
if (askAndBid.length === 0) {
|
|
14547
|
-
return null;
|
|
14548
|
-
}
|
|
14549
|
-
if ((symbolOrOrder.order_type === OrderType.LIMIT || symbolOrOrder.order_type === OrderType.STOP_LIMIT) && isNaN(orderPrice))
|
|
14550
|
-
return null;
|
|
14551
|
-
let price;
|
|
14552
|
-
if (symbolOrOrder.order_type === OrderType.MARKET || symbolOrOrder.order_type === OrderType.STOP_MARKET) {
|
|
14553
|
-
if (symbolOrOrder.side === OrderSide.BUY) {
|
|
14554
|
-
price = askAndBid[0];
|
|
14555
|
-
} else {
|
|
14556
|
-
price = askAndBid[1];
|
|
14557
|
-
}
|
|
14558
|
-
} else {
|
|
14559
|
-
if (symbolOrOrder.side === OrderSide.BUY) {
|
|
14560
|
-
if (orderPrice >= askAndBid[0]) {
|
|
14561
|
-
price = askAndBid[0];
|
|
14562
|
-
} else {
|
|
14563
|
-
price = orderPrice;
|
|
14564
|
-
}
|
|
14565
|
-
} else {
|
|
14566
|
-
if (orderPrice <= askAndBid[1]) {
|
|
14567
|
-
price = askAndBid[1];
|
|
14568
|
-
} else {
|
|
14569
|
-
price = orderPrice;
|
|
14570
|
-
}
|
|
14571
|
-
}
|
|
14572
|
-
}
|
|
14573
|
-
if (symbolOrOrder.side === OrderSide.SELL) {
|
|
14574
|
-
quantity = -quantity;
|
|
14575
|
-
}
|
|
14576
|
-
return { price, quantity };
|
|
14577
|
-
};
|
|
14578
|
-
var calcEstLiqPrice = (order$1, askAndBid, inputs) => {
|
|
14579
|
-
const result = getPriceAndQty(order$1, askAndBid);
|
|
14580
|
-
if (!result)
|
|
14581
|
-
return null;
|
|
14582
|
-
const { price, quantity } = result;
|
|
14583
|
-
if (!price || !quantity)
|
|
14584
|
-
return null;
|
|
14585
|
-
const {
|
|
14586
|
-
symbol,
|
|
14587
|
-
baseIMR,
|
|
14588
|
-
baseMMR,
|
|
14589
|
-
imr_factor,
|
|
14590
|
-
markPrice,
|
|
14591
|
-
totalCollateral,
|
|
14592
|
-
futures_taker_fee_rate,
|
|
14593
|
-
positions: positions3
|
|
14594
|
-
} = inputs;
|
|
14595
|
-
const orderFee = order.orderFee({
|
|
14596
|
-
qty: quantity,
|
|
14597
|
-
price,
|
|
14598
|
-
futuresTakeFeeRate: Number(futures_taker_fee_rate) / 1e4
|
|
14599
|
-
});
|
|
14600
|
-
const liqPrice = order.estLiqPrice({
|
|
14601
|
-
markPrice,
|
|
14602
|
-
baseIMR,
|
|
14603
|
-
baseMMR,
|
|
14604
|
-
totalCollateral,
|
|
14605
|
-
positions: positions3 == null ? [] : positions3,
|
|
14606
|
-
IMR_Factor: imr_factor,
|
|
14607
|
-
orderFee,
|
|
14608
|
-
newOrder: {
|
|
14609
|
-
qty: quantity,
|
|
14610
|
-
price,
|
|
14611
|
-
symbol
|
|
14612
|
-
}
|
|
14613
|
-
});
|
|
14614
|
-
if (liqPrice <= 0)
|
|
14615
|
-
return null;
|
|
14616
|
-
return liqPrice;
|
|
14617
|
-
};
|
|
14618
|
-
var calcEstLeverage = (order$1, askAndBid, inputs) => {
|
|
14619
|
-
const result = getPriceAndQty(order$1, askAndBid);
|
|
14620
|
-
const { totalCollateral, positions: positions3, symbol } = inputs;
|
|
14621
|
-
if (!result)
|
|
14622
|
-
return null;
|
|
14623
|
-
const { price, quantity } = result;
|
|
14624
|
-
if (!price || !quantity)
|
|
14625
|
-
return null;
|
|
14626
|
-
return order.estLeverage({
|
|
14627
|
-
totalCollateral,
|
|
14628
|
-
positions: positions3,
|
|
14629
|
-
newOrder: {
|
|
14630
|
-
symbol,
|
|
14631
|
-
qty: result.quantity,
|
|
14632
|
-
price: result.price
|
|
14633
|
-
}
|
|
14634
|
-
});
|
|
14635
|
-
};
|
|
14636
|
-
function isBBOOrder(options) {
|
|
14637
|
-
const { order_type, order_type_ext } = options;
|
|
14638
|
-
return order_type === OrderType.LIMIT && [OrderType.ASK, OrderType.BID].includes(order_type_ext);
|
|
14639
|
-
}
|
|
14640
15027
|
var initialOrderState = {
|
|
14641
15028
|
order_price: "",
|
|
14642
15029
|
order_quantity: "",
|
|
@@ -14649,7 +15036,12 @@ var initialOrderState = {
|
|
|
14649
15036
|
sl_offset_percentage: "",
|
|
14650
15037
|
tp_offset: "",
|
|
14651
15038
|
sl_offset: "",
|
|
14652
|
-
total: ""
|
|
15039
|
+
total: "",
|
|
15040
|
+
min_price: "",
|
|
15041
|
+
max_price: "",
|
|
15042
|
+
totalOrders: "",
|
|
15043
|
+
distribution_type: "",
|
|
15044
|
+
skew: ""
|
|
14653
15045
|
// symbol: "",
|
|
14654
15046
|
};
|
|
14655
15047
|
var useOrderStore = (initialOrder) => {
|
|
@@ -14886,12 +15278,9 @@ var useOrderEntryNextInternal = (symbol, options = {}) => {
|
|
|
14886
15278
|
[calculate2, options.symbolInfo, orderEntity, orderEntryActions]
|
|
14887
15279
|
);
|
|
14888
15280
|
const validate = (order, creator, options2) => {
|
|
14889
|
-
const { markPrice, maxQty, estSlippage } = options2;
|
|
14890
15281
|
return creator?.validate(order, {
|
|
14891
|
-
|
|
14892
|
-
|
|
14893
|
-
markPrice,
|
|
14894
|
-
estSlippage
|
|
15282
|
+
...options2,
|
|
15283
|
+
symbol: symbolInfo
|
|
14895
15284
|
});
|
|
14896
15285
|
};
|
|
14897
15286
|
const generateOrder = (creator, options2) => {
|
|
@@ -15073,7 +15462,8 @@ var useOrderEntry2 = (symbol, options = {}) => {
|
|
|
15073
15462
|
return {
|
|
15074
15463
|
markPrice: actions.getMarkPriceBySymbol(symbol),
|
|
15075
15464
|
maxQty,
|
|
15076
|
-
estSlippage
|
|
15465
|
+
estSlippage,
|
|
15466
|
+
askAndBid: askAndBid.current?.[0] || []
|
|
15077
15467
|
};
|
|
15078
15468
|
}, [maxQty, symbol, estSlippage]);
|
|
15079
15469
|
const interactiveValidate = (order) => {
|
|
@@ -15173,25 +15563,36 @@ var useOrderEntry2 = (symbol, options = {}) => {
|
|
|
15173
15563
|
const { freeCollateral, totalCollateral } = useCollateral();
|
|
15174
15564
|
const estLiqPrice = useMemo(() => {
|
|
15175
15565
|
const markPrice2 = actions.getMarkPriceBySymbol(symbol);
|
|
15176
|
-
if (!markPrice2 || !accountInfo)
|
|
15566
|
+
if (!markPrice2 || !accountInfo || !symbolInfo) {
|
|
15177
15567
|
return null;
|
|
15568
|
+
}
|
|
15178
15569
|
const orderQuantity = Number(formattedOrder.order_quantity);
|
|
15179
15570
|
if (orderQuantity === 0 || orderQuantity > maxQty) {
|
|
15180
15571
|
return null;
|
|
15181
15572
|
}
|
|
15182
15573
|
const estLiqPrice2 = calcEstLiqPrice(formattedOrder, askAndBid.current[0], {
|
|
15183
|
-
baseIMR: symbolInfo?.base_imr,
|
|
15184
|
-
baseMMR: symbolInfo?.base_mmr,
|
|
15185
15574
|
markPrice: markPrice2,
|
|
15186
15575
|
totalCollateral,
|
|
15187
15576
|
futures_taker_fee_rate: accountInfo.futures_taker_fee_rate,
|
|
15188
15577
|
imr_factor: accountInfo.imr_factor[symbol],
|
|
15189
15578
|
symbol,
|
|
15190
|
-
positions: positions3
|
|
15579
|
+
positions: positions3,
|
|
15580
|
+
symbolInfo
|
|
15191
15581
|
});
|
|
15192
15582
|
return estLiqPrice2;
|
|
15193
|
-
}, [
|
|
15583
|
+
}, [
|
|
15584
|
+
formattedOrder,
|
|
15585
|
+
accountInfo,
|
|
15586
|
+
positions3,
|
|
15587
|
+
totalCollateral,
|
|
15588
|
+
symbol,
|
|
15589
|
+
maxQty,
|
|
15590
|
+
symbolInfo
|
|
15591
|
+
]);
|
|
15194
15592
|
const estLeverage = useMemo(() => {
|
|
15593
|
+
if (!symbolInfo) {
|
|
15594
|
+
return null;
|
|
15595
|
+
}
|
|
15195
15596
|
const orderQuantity = Number(formattedOrder.order_quantity);
|
|
15196
15597
|
if (orderQuantity === 0 || orderQuantity > maxQty) {
|
|
15197
15598
|
return null;
|
|
@@ -15199,9 +15600,18 @@ var useOrderEntry2 = (symbol, options = {}) => {
|
|
|
15199
15600
|
return calcEstLeverage(formattedOrder, askAndBid.current[0], {
|
|
15200
15601
|
totalCollateral,
|
|
15201
15602
|
positions: positions3,
|
|
15202
|
-
symbol
|
|
15603
|
+
symbol,
|
|
15604
|
+
symbolInfo
|
|
15203
15605
|
});
|
|
15204
|
-
}, [
|
|
15606
|
+
}, [
|
|
15607
|
+
formattedOrder,
|
|
15608
|
+
accountInfo,
|
|
15609
|
+
positions3,
|
|
15610
|
+
totalCollateral,
|
|
15611
|
+
symbol,
|
|
15612
|
+
maxQty,
|
|
15613
|
+
symbolInfo
|
|
15614
|
+
]);
|
|
15205
15615
|
const resetErrors = () => {
|
|
15206
15616
|
setMeta(
|
|
15207
15617
|
produce((draft) => {
|
|
@@ -15238,14 +15648,31 @@ var useOrderEntry2 = (symbol, options = {}) => {
|
|
|
15238
15648
|
throw new SDKError("Order validation failed");
|
|
15239
15649
|
}
|
|
15240
15650
|
const order = generateOrder(creator, prepareData());
|
|
15241
|
-
const
|
|
15651
|
+
const isScaledOrder = order.order_type === OrderType.SCALED;
|
|
15652
|
+
const params = isScaledOrder ? { orders: order.orders } : order;
|
|
15653
|
+
const result = await doCreateOrder(params);
|
|
15242
15654
|
if (result.success) {
|
|
15243
|
-
|
|
15655
|
+
let trackParams = {
|
|
15244
15656
|
side: order.side,
|
|
15245
15657
|
order_type: order.order_type,
|
|
15246
15658
|
tp_sl: hasTPSL(formattedOrder),
|
|
15247
15659
|
symbol: order.symbol
|
|
15248
|
-
}
|
|
15660
|
+
};
|
|
15661
|
+
if (isScaledOrder) {
|
|
15662
|
+
const skew = getScaledOrderSkew({
|
|
15663
|
+
skew: order.skew,
|
|
15664
|
+
distribution_type: order.distribution_type,
|
|
15665
|
+
total_orders: order.total_orders
|
|
15666
|
+
});
|
|
15667
|
+
trackParams = {
|
|
15668
|
+
...trackParams,
|
|
15669
|
+
order_type: "scaled",
|
|
15670
|
+
distribution_type: order.distribution_type,
|
|
15671
|
+
skew: new Decimal(skew).todp(2).toNumber(),
|
|
15672
|
+
total_orders: order.total_orders
|
|
15673
|
+
};
|
|
15674
|
+
}
|
|
15675
|
+
track2(TrackerEventName.placeOrderSuccess, trackParams);
|
|
15249
15676
|
}
|
|
15250
15677
|
if (result.success && resetOnSuccess) {
|
|
15251
15678
|
reset();
|
|
@@ -15430,6 +15857,7 @@ var useOrderEntity = (order, options) => {
|
|
|
15430
15857
|
symbolInfo
|
|
15431
15858
|
};
|
|
15432
15859
|
};
|
|
15860
|
+
var canUnblockRegions = ["United States"];
|
|
15433
15861
|
var useRestrictedInfo = (options) => {
|
|
15434
15862
|
const {
|
|
15435
15863
|
enableDefault = false,
|
|
@@ -15437,63 +15865,70 @@ var useRestrictedInfo = (options) => {
|
|
|
15437
15865
|
customRestrictedRegions = [],
|
|
15438
15866
|
content
|
|
15439
15867
|
} = options || {};
|
|
15440
|
-
const apiBaseUrl = useConfig("apiBaseUrl");
|
|
15441
|
-
const [invalidWebCity, setInvalidWebCity] = useState([]);
|
|
15442
|
-
const [invalidWebCountry, setInvalidWebCountry] = useState([]);
|
|
15443
|
-
const [invalidRegions, setInvalidRegions] = useState([]);
|
|
15444
|
-
const [allInvalidAreas, setAllInvalidAreas] = useState([]);
|
|
15445
|
-
const [city, setCity] = useState("");
|
|
15446
|
-
const [region, setRegion] = useState("");
|
|
15447
15868
|
const [ip, setIp] = useState("");
|
|
15869
|
+
const [allInvalidAreas, setAllInvalidAreas] = useState([]);
|
|
15448
15870
|
const [restrictedOpen, setRestrictedOpen] = useState(false);
|
|
15871
|
+
const [canUnblock, setCanUnblock] = useState(false);
|
|
15872
|
+
const [accessRestricted, setAccessRestricted] = useLocalStorage("orderly_access_restricted", void 0);
|
|
15873
|
+
const { data: ipInfo } = useQuery("/v1/ip_info");
|
|
15874
|
+
const { data: restrictedAreas } = useQuery(
|
|
15875
|
+
"/v1/restricted_areas"
|
|
15876
|
+
);
|
|
15449
15877
|
useEffect(() => {
|
|
15450
|
-
|
|
15451
|
-
|
|
15452
|
-
|
|
15453
|
-
|
|
15454
|
-
|
|
15455
|
-
|
|
15456
|
-
|
|
15457
|
-
|
|
15458
|
-
|
|
15459
|
-
|
|
15460
|
-
|
|
15461
|
-
|
|
15462
|
-
|
|
15463
|
-
|
|
15464
|
-
|
|
15465
|
-
|
|
15466
|
-
|
|
15467
|
-
|
|
15468
|
-
|
|
15469
|
-
|
|
15470
|
-
|
|
15471
|
-
|
|
15472
|
-
|
|
15473
|
-
|
|
15474
|
-
|
|
15475
|
-
|
|
15476
|
-
setIp(ip2);
|
|
15477
|
-
if (combinedInvalidRegions.includes(
|
|
15478
|
-
ipData?.data?.city?.replace(/\s+/g, "").toLocaleLowerCase()
|
|
15479
|
-
) || combinedInvalidRegions.includes(
|
|
15480
|
-
ipData?.data?.region?.replace(/\s+/g, "").toLocaleLowerCase()
|
|
15481
|
-
) || customRestrictedIps.includes(ipData?.data?.ip)) {
|
|
15482
|
-
setRestrictedOpen(true);
|
|
15483
|
-
}
|
|
15878
|
+
if (!restrictedAreas || !ipInfo) {
|
|
15879
|
+
return;
|
|
15880
|
+
}
|
|
15881
|
+
try {
|
|
15882
|
+
const { invalid_web_country, invalid_web_city } = restrictedAreas;
|
|
15883
|
+
const invalidCountries = invalid_web_country?.toLowerCase().replace(/\s+/g, "").split(",");
|
|
15884
|
+
const invalidCities = invalid_web_city?.toLowerCase().replace(/\s+/g, "").split(",");
|
|
15885
|
+
const formattedCustomRegions = customRestrictedRegions?.map(
|
|
15886
|
+
(item) => formatRegion(item)
|
|
15887
|
+
);
|
|
15888
|
+
const combinedInvalidRegions = [
|
|
15889
|
+
...formattedCustomRegions,
|
|
15890
|
+
...enableDefault ? [...invalidCountries, ...invalidCities] : []
|
|
15891
|
+
];
|
|
15892
|
+
const allInvalidAreas2 = [
|
|
15893
|
+
enableDefault ? invalid_web_country : "",
|
|
15894
|
+
enableDefault ? invalid_web_city : "",
|
|
15895
|
+
customRestrictedRegions?.join(", ")
|
|
15896
|
+
].filter((item) => !!item);
|
|
15897
|
+
const { city, region, ip: ip2 } = ipInfo;
|
|
15898
|
+
const formattedCity = formatRegion(city);
|
|
15899
|
+
const formattedRegion = formatRegion(region);
|
|
15900
|
+
const showRestricted = accessRestricted && (combinedInvalidRegions.includes(formattedCity) || combinedInvalidRegions.includes(formattedRegion) || customRestrictedIps.includes(ip2));
|
|
15901
|
+
for (const item of canUnblockRegions) {
|
|
15902
|
+
if (formatRegion(item) === formatRegion(region)) {
|
|
15903
|
+
setCanUnblock(true);
|
|
15484
15904
|
}
|
|
15485
|
-
} catch (error) {
|
|
15486
15905
|
}
|
|
15487
|
-
|
|
15488
|
-
|
|
15489
|
-
|
|
15906
|
+
setIp(ip2);
|
|
15907
|
+
setAllInvalidAreas(allInvalidAreas2);
|
|
15908
|
+
setRestrictedOpen(showRestricted);
|
|
15909
|
+
} catch (error) {
|
|
15910
|
+
}
|
|
15911
|
+
}, [
|
|
15912
|
+
ipInfo,
|
|
15913
|
+
restrictedAreas,
|
|
15914
|
+
enableDefault,
|
|
15915
|
+
customRestrictedIps,
|
|
15916
|
+
customRestrictedRegions,
|
|
15917
|
+
accessRestricted
|
|
15918
|
+
]);
|
|
15490
15919
|
return {
|
|
15491
15920
|
ip,
|
|
15492
15921
|
invalidRegions: allInvalidAreas,
|
|
15493
15922
|
restrictedOpen,
|
|
15494
|
-
content
|
|
15923
|
+
content,
|
|
15924
|
+
canUnblock,
|
|
15925
|
+
accessRestricted,
|
|
15926
|
+
setAccessRestricted
|
|
15495
15927
|
};
|
|
15496
15928
|
};
|
|
15929
|
+
function formatRegion(region) {
|
|
15930
|
+
return region?.replace(/\s+/g, "").toLowerCase();
|
|
15931
|
+
}
|
|
15497
15932
|
var usePositionClose = (options) => {
|
|
15498
15933
|
const { position, order: initialOrder } = options;
|
|
15499
15934
|
const { type, quantity, price } = initialOrder;
|
|
@@ -15501,6 +15936,10 @@ var usePositionClose = (options) => {
|
|
|
15501
15936
|
const [errors, setErrors] = useState(null);
|
|
15502
15937
|
const symbolsInfo = useSymbolsInfo();
|
|
15503
15938
|
const { data: markPrices } = useMarkPricesStream();
|
|
15939
|
+
const markPricesRef = useRef(markPrices);
|
|
15940
|
+
useEffect(() => {
|
|
15941
|
+
markPricesRef.current = markPrices;
|
|
15942
|
+
}, [markPrices]);
|
|
15504
15943
|
const [doCreateOrder, { isMutating }] = useSubAccountMutation(
|
|
15505
15944
|
"/v1/order",
|
|
15506
15945
|
"POST",
|
|
@@ -15549,11 +15988,12 @@ var usePositionClose = (options) => {
|
|
|
15549
15988
|
const errors2 = await creator.validate(data, {
|
|
15550
15989
|
symbol: symbolsInfo[symbol](),
|
|
15551
15990
|
maxQty,
|
|
15552
|
-
|
|
15991
|
+
// use ref to avoid re-render when markPrices change
|
|
15992
|
+
markPrice: markPricesRef.current[symbol]
|
|
15553
15993
|
});
|
|
15554
15994
|
return errors2;
|
|
15555
15995
|
},
|
|
15556
|
-
[
|
|
15996
|
+
[maxQty, symbol, symbolsInfo]
|
|
15557
15997
|
);
|
|
15558
15998
|
useEffect(() => {
|
|
15559
15999
|
validate(closeOrderData).then((errors2) => {
|