refactor: extract shared order handler factory, deduplicate 8 order.ts files

Created src/exchanges/order-handlers.ts with createOrderHandlers() factory.
All 8 exchange order.ts files now use config-driven delegation instead of
duplicated ~80-line implementations. Shared applyCommonFields() logic
consolidated into the factory module.
This commit is contained in:
discountry
2026-04-06 18:24:42 +08:00
parent bc29b23027
commit d799cf79c2
9 changed files with 279 additions and 730 deletions
+14 -98
View File
@@ -1,101 +1,17 @@
import type { Order, CreateOrderParams } from "../types";
import type {
BaseOrderIntent,
ClosePositionIntent,
LimitOrderIntent,
MarketOrderIntent,
StopOrderIntent,
TrailingStopOrderIntent,
} from "../order-schema";
import { toStringBoolean } from "../order-schema";
import { createOrderHandlers } from "../order-handlers";
function applyCommonFields(params: CreateOrderParams, intent: BaseOrderIntent): CreateOrderParams {
if (params.quantity === undefined) {
params.quantity = intent.quantity;
}
if (params.timeInForce === undefined && intent.timeInForce) {
params.timeInForce = intent.timeInForce;
}
if (intent.reduceOnly !== undefined) {
params.reduceOnly = toStringBoolean(intent.reduceOnly);
}
if (intent.closePosition !== undefined) {
params.closePosition = toStringBoolean(intent.closePosition);
}
return params;
}
const handlers = createOrderHandlers({
exchangeName: "Aster",
defaultLimitTimeInForce: "GTX",
supportsTrailingStop: true,
supportsTriggerType: true,
});
export async function createLimitOrder(intent: LimitOrderIntent): Promise<Order> {
const params: CreateOrderParams = applyCommonFields(
{
symbol: intent.symbol,
side: intent.side,
type: "LIMIT",
quantity: intent.quantity,
price: intent.price,
timeInForce: intent.timeInForce ?? "GTX",
},
intent
);
return intent.adapter.createOrder(params);
}
export async function createMarketOrder(intent: MarketOrderIntent): Promise<Order> {
const params: CreateOrderParams = applyCommonFields(
{
symbol: intent.symbol,
side: intent.side,
type: "MARKET",
quantity: intent.quantity,
},
intent
);
return intent.adapter.createOrder(params);
}
export async function createStopOrder(intent: StopOrderIntent): Promise<Order> {
const params: CreateOrderParams = applyCommonFields(
{
symbol: intent.symbol,
side: intent.side,
type: "STOP_MARKET",
quantity: intent.quantity,
stopPrice: intent.stopPrice,
timeInForce: intent.timeInForce ?? "GTC",
triggerType: intent.triggerType,
},
intent
);
return intent.adapter.createOrder(params);
}
export async function createTrailingStopOrder(intent: TrailingStopOrderIntent): Promise<Order> {
const params: CreateOrderParams = applyCommonFields(
{
symbol: intent.symbol,
side: intent.side,
type: "TRAILING_STOP_MARKET",
quantity: intent.quantity,
activationPrice: intent.activationPrice,
callbackRate: intent.callbackRate,
timeInForce: intent.timeInForce ?? "GTC",
},
intent
);
return intent.adapter.createOrder(params);
}
export async function createClosePositionOrder(intent: ClosePositionIntent): Promise<Order> {
const params: CreateOrderParams = applyCommonFields(
{
symbol: intent.symbol,
side: intent.side,
type: "MARKET",
quantity: intent.quantity,
reduceOnly: "true",
},
intent
);
return intent.adapter.createOrder(params);
}
export const {
createLimitOrder,
createMarketOrder,
createStopOrder,
createTrailingStopOrder,
createClosePositionOrder,
} = handlers;
+14 -82
View File
@@ -1,84 +1,16 @@
import type { Order, CreateOrderParams } from "../types";
import type {
BaseOrderIntent,
ClosePositionIntent,
LimitOrderIntent,
MarketOrderIntent,
StopOrderIntent,
TrailingStopOrderIntent,
} from "../order-schema";
import { toStringBoolean } from "../order-schema";
import { createOrderHandlers } from "../order-handlers";
function applyCommonFields(params: CreateOrderParams, intent: BaseOrderIntent): CreateOrderParams {
if (params.quantity === undefined) {
params.quantity = intent.quantity;
}
if (params.timeInForce === undefined && intent.timeInForce) {
params.timeInForce = intent.timeInForce;
}
if (intent.reduceOnly !== undefined) {
params.reduceOnly = toStringBoolean(intent.reduceOnly);
}
return params;
}
const handlers = createOrderHandlers({
exchangeName: "Backpack",
defaultLimitTimeInForce: "GTX",
supportsTrailingStop: false,
supportsTriggerType: false,
});
export async function createLimitOrder(intent: LimitOrderIntent): Promise<Order> {
const params: CreateOrderParams = applyCommonFields(
{
symbol: intent.symbol,
side: intent.side,
type: "LIMIT",
quantity: intent.quantity,
price: intent.price,
timeInForce: intent.timeInForce ?? "GTX",
},
intent
);
return intent.adapter.createOrder(params);
}
export async function createMarketOrder(intent: MarketOrderIntent): Promise<Order> {
const params: CreateOrderParams = applyCommonFields(
{
symbol: intent.symbol,
side: intent.side,
type: "MARKET",
quantity: intent.quantity,
},
intent
);
return intent.adapter.createOrder(params);
}
export async function createStopOrder(intent: StopOrderIntent): Promise<Order> {
const params: CreateOrderParams = applyCommonFields(
{
symbol: intent.symbol,
side: intent.side,
type: "STOP_MARKET",
quantity: intent.quantity,
stopPrice: intent.stopPrice,
timeInForce: intent.timeInForce ?? "GTC",
},
intent
);
return intent.adapter.createOrder(params);
}
export async function createTrailingStopOrder(_intent: TrailingStopOrderIntent): Promise<Order> {
throw new Error("Backpack exchange does not support trailing stop orders");
}
export async function createClosePositionOrder(intent: ClosePositionIntent): Promise<Order> {
const params: CreateOrderParams = applyCommonFields(
{
symbol: intent.symbol,
side: intent.side,
type: "MARKET",
quantity: intent.quantity,
reduceOnly: "true",
},
intent
);
return intent.adapter.createOrder(params);
}
export const {
createLimitOrder,
createMarketOrder,
createStopOrder,
createTrailingStopOrder,
createClosePositionOrder,
} = handlers;
+14 -98
View File
@@ -1,100 +1,16 @@
import type { Order, CreateOrderParams } from "../types";
import type {
BaseOrderIntent,
ClosePositionIntent,
LimitOrderIntent,
MarketOrderIntent,
StopOrderIntent,
TrailingStopOrderIntent,
} from "../order-schema";
import { toStringBoolean } from "../order-schema";
import { createOrderHandlers } from "../order-handlers";
function applyCommonFields(params: CreateOrderParams, intent: BaseOrderIntent): CreateOrderParams {
if (params.quantity === undefined) {
params.quantity = intent.quantity;
}
if (params.timeInForce === undefined && intent.timeInForce) {
params.timeInForce = intent.timeInForce;
}
if (intent.reduceOnly !== undefined) {
params.reduceOnly = toStringBoolean(intent.reduceOnly);
}
if (intent.closePosition !== undefined) {
params.closePosition = toStringBoolean(intent.closePosition);
}
return params;
}
const handlers = createOrderHandlers({
exchangeName: "Binance",
defaultLimitTimeInForce: "GTX",
supportsTrailingStop: true,
supportsTriggerType: true,
});
export async function createLimitOrder(intent: LimitOrderIntent): Promise<Order> {
const params: CreateOrderParams = applyCommonFields(
{
symbol: intent.symbol,
side: intent.side,
type: "LIMIT",
quantity: intent.quantity,
price: intent.price,
timeInForce: intent.timeInForce ?? "GTX",
},
intent
);
return intent.adapter.createOrder(params);
}
export async function createMarketOrder(intent: MarketOrderIntent): Promise<Order> {
const params: CreateOrderParams = applyCommonFields(
{
symbol: intent.symbol,
side: intent.side,
type: "MARKET",
quantity: intent.quantity,
},
intent
);
return intent.adapter.createOrder(params);
}
export async function createStopOrder(intent: StopOrderIntent): Promise<Order> {
const params: CreateOrderParams = applyCommonFields(
{
symbol: intent.symbol,
side: intent.side,
type: "STOP_MARKET",
quantity: intent.quantity,
stopPrice: intent.stopPrice,
timeInForce: intent.timeInForce ?? "GTC",
triggerType: intent.triggerType,
},
intent
);
return intent.adapter.createOrder(params);
}
export async function createTrailingStopOrder(intent: TrailingStopOrderIntent): Promise<Order> {
const params: CreateOrderParams = applyCommonFields(
{
symbol: intent.symbol,
side: intent.side,
type: "TRAILING_STOP_MARKET",
quantity: intent.quantity,
activationPrice: intent.activationPrice,
callbackRate: intent.callbackRate,
timeInForce: intent.timeInForce ?? "GTC",
},
intent
);
return intent.adapter.createOrder(params);
}
export async function createClosePositionOrder(intent: ClosePositionIntent): Promise<Order> {
const params: CreateOrderParams = applyCommonFields(
{
symbol: intent.symbol,
side: intent.side,
type: "MARKET",
quantity: intent.quantity,
reduceOnly: "true",
},
intent
);
return intent.adapter.createOrder(params);
}
export const {
createLimitOrder,
createMarketOrder,
createStopOrder,
createTrailingStopOrder,
createClosePositionOrder,
} = handlers;
+18 -89
View File
@@ -1,92 +1,21 @@
import type { Order, CreateOrderParams } from "../types";
import type {
BaseOrderIntent,
ClosePositionIntent,
LimitOrderIntent,
MarketOrderIntent,
StopOrderIntent,
TrailingStopOrderIntent,
} from "../order-schema";
import { toStringBoolean } from "../order-schema";
import { createOrderHandlers } from "../order-handlers";
function applyCommonFields(params: CreateOrderParams, intent: BaseOrderIntent): CreateOrderParams {
if (params.quantity === undefined) {
params.quantity = intent.quantity;
}
if (params.timeInForce === undefined && intent.timeInForce) {
params.timeInForce = intent.timeInForce;
}
if (intent.reduceOnly !== undefined) {
params.reduceOnly = toStringBoolean(intent.reduceOnly);
}
if (intent.closePosition !== undefined) {
params.closePosition = toStringBoolean(intent.closePosition);
}
return params;
}
const handlers = createOrderHandlers({
exchangeName: "GRVT",
defaultLimitTimeInForce: "GTX",
supportsTrailingStop: false,
supportsTriggerType: true,
defaultStopTriggerType: "STOP_LOSS",
stopDefaultReduceOnly: true,
stopDefaultClosePosition: true,
closeDefaultClosePosition: true,
});
export async function createLimitOrder(intent: LimitOrderIntent): Promise<Order> {
const params: CreateOrderParams = applyCommonFields(
{
symbol: intent.symbol,
side: intent.side,
type: "LIMIT",
quantity: intent.quantity,
price: intent.price,
timeInForce: intent.timeInForce ?? "GTX",
},
intent
);
return intent.adapter.createOrder(params);
}
export async function createMarketOrder(intent: MarketOrderIntent): Promise<Order> {
const params: CreateOrderParams = applyCommonFields(
{
symbol: intent.symbol,
side: intent.side,
type: "MARKET",
quantity: intent.quantity,
},
intent
);
return intent.adapter.createOrder(params);
}
export async function createStopOrder(intent: StopOrderIntent): Promise<Order> {
const params: CreateOrderParams = applyCommonFields(
{
symbol: intent.symbol,
side: intent.side,
type: "STOP_MARKET",
quantity: intent.quantity,
stopPrice: intent.stopPrice,
timeInForce: intent.timeInForce ?? "GTC",
triggerType: intent.triggerType ?? "STOP_LOSS",
closePosition: toStringBoolean(intent.closePosition ?? true),
reduceOnly: toStringBoolean(intent.reduceOnly ?? true),
},
intent
);
return intent.adapter.createOrder(params);
}
export async function createTrailingStopOrder(_intent: TrailingStopOrderIntent): Promise<Order> {
throw new Error("GRVT exchange does not support trailing stop orders");
}
export async function createClosePositionOrder(intent: ClosePositionIntent): Promise<Order> {
const params: CreateOrderParams = applyCommonFields(
{
symbol: intent.symbol,
side: intent.side,
type: "MARKET",
quantity: intent.quantity,
reduceOnly: "true",
closePosition: toStringBoolean(intent.closePosition ?? true),
},
intent
);
return intent.adapter.createOrder(params);
}
export const {
createLimitOrder,
createMarketOrder,
createStopOrder,
createTrailingStopOrder,
createClosePositionOrder,
} = handlers;
+19 -90
View File
@@ -1,93 +1,22 @@
import type { Order, CreateOrderParams } from "../types";
import type {
BaseOrderIntent,
ClosePositionIntent,
LimitOrderIntent,
MarketOrderIntent,
StopOrderIntent,
TrailingStopOrderIntent,
} from "../order-schema";
import { toStringBoolean } from "../order-schema";
import { createOrderHandlers } from "../order-handlers";
function applyCommonFields(params: CreateOrderParams, intent: BaseOrderIntent): CreateOrderParams {
if (params.quantity === undefined) {
params.quantity = intent.quantity;
}
if (params.timeInForce === undefined && intent.timeInForce) {
params.timeInForce = intent.timeInForce;
}
if (intent.reduceOnly !== undefined) {
params.reduceOnly = toStringBoolean(intent.reduceOnly);
}
if (intent.closePosition !== undefined) {
params.closePosition = toStringBoolean(intent.closePosition);
}
return params;
}
const handlers = createOrderHandlers({
exchangeName: "Lighter",
defaultLimitTimeInForce: "GTC",
defaultMarketTimeInForce: "IOC",
defaultCloseTimeInForce: "IOC",
supportsTrailingStop: false,
supportsTriggerType: false,
stopDefaultReduceOnly: true,
stopDefaultClosePosition: true,
closeDefaultClosePosition: true,
});
export async function createLimitOrder(intent: LimitOrderIntent): Promise<Order> {
const params: CreateOrderParams = applyCommonFields(
{
symbol: intent.symbol,
side: intent.side,
type: "LIMIT",
quantity: intent.quantity,
price: intent.price,
timeInForce: intent.timeInForce ?? "GTC",
},
intent
);
return intent.adapter.createOrder(params);
}
export async function createMarketOrder(intent: MarketOrderIntent): Promise<Order> {
const params: CreateOrderParams = applyCommonFields(
{
symbol: intent.symbol,
side: intent.side,
type: "MARKET",
quantity: intent.quantity,
timeInForce: intent.timeInForce ?? "IOC",
},
intent
);
return intent.adapter.createOrder(params);
}
export async function createStopOrder(intent: StopOrderIntent): Promise<Order> {
const params: CreateOrderParams = applyCommonFields(
{
symbol: intent.symbol,
side: intent.side,
type: "STOP_MARKET",
quantity: intent.quantity,
stopPrice: intent.stopPrice,
timeInForce: intent.timeInForce ?? "GTC",
reduceOnly: toStringBoolean(intent.reduceOnly ?? true),
closePosition: toStringBoolean(intent.closePosition ?? true),
},
intent
);
return intent.adapter.createOrder(params);
}
export async function createTrailingStopOrder(_intent: TrailingStopOrderIntent): Promise<Order> {
throw new Error("Lighter exchange does not support trailing stop orders");
}
export async function createClosePositionOrder(intent: ClosePositionIntent): Promise<Order> {
const params: CreateOrderParams = applyCommonFields(
{
symbol: intent.symbol,
side: intent.side,
type: "MARKET",
quantity: intent.quantity,
reduceOnly: "true",
closePosition: toStringBoolean(intent.closePosition ?? true),
timeInForce: intent.timeInForce ?? "IOC",
},
intent
);
return intent.adapter.createOrder(params);
}
export const {
createLimitOrder,
createMarketOrder,
createStopOrder,
createTrailingStopOrder,
createClosePositionOrder,
} = handlers;
+19 -90
View File
@@ -1,93 +1,22 @@
import type { Order, CreateOrderParams } from "../types";
import type {
BaseOrderIntent,
ClosePositionIntent,
LimitOrderIntent,
MarketOrderIntent,
StopOrderIntent,
TrailingStopOrderIntent,
} from "../order-schema";
import { toStringBoolean } from "../order-schema";
import { createOrderHandlers } from "../order-handlers";
function applyCommonFields(params: CreateOrderParams, intent: BaseOrderIntent): CreateOrderParams {
if (params.quantity === undefined) {
params.quantity = intent.quantity;
}
if (params.timeInForce === undefined && intent.timeInForce) {
params.timeInForce = intent.timeInForce;
}
if (intent.reduceOnly !== undefined) {
params.reduceOnly = toStringBoolean(intent.reduceOnly);
}
if (intent.closePosition !== undefined) {
params.closePosition = toStringBoolean(intent.closePosition);
}
return params;
}
const handlers = createOrderHandlers({
exchangeName: "Nado",
defaultLimitTimeInForce: "GTC",
defaultMarketTimeInForce: "IOC",
defaultCloseTimeInForce: "IOC",
supportsTrailingStop: false,
supportsTriggerType: false,
stopDefaultReduceOnly: true,
stopDefaultClosePosition: true,
closeDefaultClosePosition: true,
});
export async function createLimitOrder(intent: LimitOrderIntent): Promise<Order> {
const params: CreateOrderParams = applyCommonFields(
{
symbol: intent.symbol,
side: intent.side,
type: "LIMIT",
quantity: intent.quantity,
price: intent.price,
timeInForce: intent.timeInForce ?? "GTC",
},
intent
);
return intent.adapter.createOrder(params);
}
export async function createMarketOrder(intent: MarketOrderIntent): Promise<Order> {
const params: CreateOrderParams = applyCommonFields(
{
symbol: intent.symbol,
side: intent.side,
type: "MARKET",
quantity: intent.quantity,
timeInForce: intent.timeInForce ?? "IOC",
},
intent
);
return intent.adapter.createOrder(params);
}
export async function createStopOrder(intent: StopOrderIntent): Promise<Order> {
const params: CreateOrderParams = applyCommonFields(
{
symbol: intent.symbol,
side: intent.side,
type: "STOP_MARKET",
quantity: intent.quantity,
stopPrice: intent.stopPrice,
timeInForce: intent.timeInForce ?? "GTC",
reduceOnly: toStringBoolean(intent.reduceOnly ?? true),
closePosition: toStringBoolean(intent.closePosition ?? true),
},
intent
);
return intent.adapter.createOrder(params);
}
export async function createTrailingStopOrder(_intent: TrailingStopOrderIntent): Promise<Order> {
throw new Error("Nado exchange does not support trailing stop orders");
}
export async function createClosePositionOrder(intent: ClosePositionIntent): Promise<Order> {
const params: CreateOrderParams = applyCommonFields(
{
symbol: intent.symbol,
side: intent.side,
type: "MARKET",
quantity: intent.quantity,
reduceOnly: "true",
closePosition: toStringBoolean(intent.closePosition ?? true),
timeInForce: intent.timeInForce ?? "IOC",
},
intent
);
return intent.adapter.createOrder(params);
}
export const {
createLimitOrder,
createMarketOrder,
createStopOrder,
createTrailingStopOrder,
createClosePositionOrder,
} = handlers;
+144
View File
@@ -0,0 +1,144 @@
import type { Order, CreateOrderParams, TimeInForce } from "./types";
import type {
BaseOrderIntent,
ClosePositionIntent,
LimitOrderIntent,
MarketOrderIntent,
StopOrderIntent,
TrailingStopOrderIntent,
} from "./order-schema";
import { toStringBoolean } from "./order-schema";
export interface OrderHandlerConfig {
exchangeName: string;
defaultLimitTimeInForce: TimeInForce | "GTX";
defaultMarketTimeInForce?: TimeInForce;
defaultCloseTimeInForce?: TimeInForce;
defaultStopTimeInForce?: TimeInForce;
defaultStopTriggerType?: "UNSPECIFIED" | "TAKE_PROFIT" | "STOP_LOSS";
supportsTrailingStop: boolean;
supportsTriggerType: boolean;
stopDefaultReduceOnly?: boolean;
stopDefaultClosePosition?: boolean;
closeDefaultClosePosition?: boolean;
stopPriceAsPrice?: boolean;
}
export interface OrderHandlers {
createLimitOrder(intent: LimitOrderIntent): Promise<Order>;
createMarketOrder(intent: MarketOrderIntent): Promise<Order>;
createStopOrder(intent: StopOrderIntent): Promise<Order>;
createTrailingStopOrder(intent: TrailingStopOrderIntent): Promise<Order>;
createClosePositionOrder(intent: ClosePositionIntent): Promise<Order>;
}
function applyCommonFields(params: CreateOrderParams, intent: BaseOrderIntent): CreateOrderParams {
if (params.quantity === undefined) {
params.quantity = intent.quantity;
}
if (params.timeInForce === undefined && intent.timeInForce) {
params.timeInForce = intent.timeInForce;
}
if (intent.reduceOnly !== undefined) {
params.reduceOnly = toStringBoolean(intent.reduceOnly);
}
if (intent.closePosition !== undefined) {
params.closePosition = toStringBoolean(intent.closePosition);
}
return params;
}
export function createOrderHandlers(config: OrderHandlerConfig): OrderHandlers {
return {
async createLimitOrder(intent: LimitOrderIntent): Promise<Order> {
const params: CreateOrderParams = applyCommonFields(
{
symbol: intent.symbol,
side: intent.side,
type: "LIMIT",
quantity: intent.quantity,
price: intent.price,
timeInForce: intent.timeInForce ?? config.defaultLimitTimeInForce,
slPrice: intent.slPrice,
tpPrice: intent.tpPrice,
},
intent,
);
return intent.adapter.createOrder(params);
},
async createMarketOrder(intent: MarketOrderIntent): Promise<Order> {
const params: CreateOrderParams = applyCommonFields(
{
symbol: intent.symbol,
side: intent.side,
type: "MARKET",
quantity: intent.quantity,
timeInForce: intent.timeInForce ?? config.defaultMarketTimeInForce,
},
intent,
);
return intent.adapter.createOrder(params);
},
async createStopOrder(intent: StopOrderIntent): Promise<Order> {
const params: CreateOrderParams = applyCommonFields(
{
symbol: intent.symbol,
side: intent.side,
type: "STOP_MARKET",
quantity: intent.quantity,
stopPrice: intent.stopPrice,
timeInForce: intent.timeInForce ?? (config.defaultStopTimeInForce ?? "GTC"),
triggerType: config.supportsTriggerType ? (intent.triggerType ?? config.defaultStopTriggerType) : undefined,
price: config.stopPriceAsPrice ? intent.stopPrice : undefined,
},
intent,
);
if (config.stopDefaultReduceOnly && intent.reduceOnly === undefined) {
params.reduceOnly = "true";
}
if (config.stopDefaultClosePosition && intent.closePosition === undefined) {
params.closePosition = "true";
}
return intent.adapter.createOrder(params);
},
async createTrailingStopOrder(intent: TrailingStopOrderIntent): Promise<Order> {
if (!config.supportsTrailingStop) {
throw new Error(`${config.exchangeName} does not support trailing stop orders`);
}
const params: CreateOrderParams = applyCommonFields(
{
symbol: intent.symbol,
side: intent.side,
type: "TRAILING_STOP_MARKET",
quantity: intent.quantity,
activationPrice: intent.activationPrice,
callbackRate: intent.callbackRate,
timeInForce: intent.timeInForce ?? "GTC",
},
intent,
);
return intent.adapter.createOrder(params);
},
async createClosePositionOrder(intent: ClosePositionIntent): Promise<Order> {
const params: CreateOrderParams = applyCommonFields(
{
symbol: intent.symbol,
side: intent.side,
type: "MARKET",
quantity: intent.quantity,
reduceOnly: "true",
timeInForce: intent.timeInForce ?? config.defaultCloseTimeInForce,
},
intent,
);
if (config.closeDefaultClosePosition && intent.closePosition === undefined) {
params.closePosition = "true";
}
return intent.adapter.createOrder(params);
},
};
}
+18 -91
View File
@@ -1,93 +1,20 @@
import type { Order, CreateOrderParams } from "../types";
import type {
BaseOrderIntent,
ClosePositionIntent,
LimitOrderIntent,
MarketOrderIntent,
StopOrderIntent,
TrailingStopOrderIntent,
} from "../order-schema";
import { toStringBoolean } from "../order-schema";
import { createOrderHandlers } from "../order-handlers";
function applyCommonFields(params: CreateOrderParams, intent: BaseOrderIntent): CreateOrderParams {
if (params.quantity === undefined) {
params.quantity = intent.quantity;
}
if (params.timeInForce === undefined && intent.timeInForce) {
params.timeInForce = intent.timeInForce;
}
if (intent.reduceOnly !== undefined) {
params.reduceOnly = toStringBoolean(intent.reduceOnly);
}
if (intent.closePosition !== undefined) {
params.closePosition = toStringBoolean(intent.closePosition);
}
return params;
}
const handlers = createOrderHandlers({
exchangeName: "Paradex",
defaultLimitTimeInForce: "GTC",
supportsTrailingStop: false,
supportsTriggerType: false,
stopDefaultReduceOnly: true,
stopDefaultClosePosition: true,
stopPriceAsPrice: true,
closeDefaultClosePosition: true,
});
export async function createLimitOrder(intent: LimitOrderIntent): Promise<Order> {
const params: CreateOrderParams = applyCommonFields(
{
symbol: intent.symbol,
side: intent.side,
type: "LIMIT",
quantity: intent.quantity,
price: intent.price,
timeInForce: intent.timeInForce ?? "GTC",
},
intent
);
return intent.adapter.createOrder(params);
}
export async function createMarketOrder(intent: MarketOrderIntent): Promise<Order> {
const params: CreateOrderParams = applyCommonFields(
{
symbol: intent.symbol,
side: intent.side,
type: "MARKET",
quantity: intent.quantity,
timeInForce: intent.timeInForce,
},
intent
);
return intent.adapter.createOrder(params);
}
export async function createStopOrder(intent: StopOrderIntent): Promise<Order> {
const params: CreateOrderParams = applyCommonFields(
{
symbol: intent.symbol,
side: intent.side,
type: "STOP_MARKET",
quantity: intent.quantity,
stopPrice: intent.stopPrice,
price: intent.stopPrice,
timeInForce: intent.timeInForce ?? "GTC",
reduceOnly: toStringBoolean(intent.reduceOnly ?? true),
closePosition: toStringBoolean(intent.closePosition ?? true),
},
intent
);
return intent.adapter.createOrder(params);
}
export async function createTrailingStopOrder(_intent: TrailingStopOrderIntent): Promise<Order> {
throw new Error("Paradex exchange does not support trailing stop orders");
}
export async function createClosePositionOrder(intent: ClosePositionIntent): Promise<Order> {
const params: CreateOrderParams = applyCommonFields(
{
symbol: intent.symbol,
side: intent.side,
type: "MARKET",
quantity: intent.quantity,
reduceOnly: "true",
closePosition: toStringBoolean(intent.closePosition ?? true),
timeInForce: intent.timeInForce,
},
intent
);
return intent.adapter.createOrder(params);
}
export const {
createLimitOrder,
createMarketOrder,
createStopOrder,
createTrailingStopOrder,
createClosePositionOrder,
} = handlers;
+19 -92
View File
@@ -1,94 +1,21 @@
import type { Order, CreateOrderParams } from "../types";
import type {
BaseOrderIntent,
ClosePositionIntent,
LimitOrderIntent,
MarketOrderIntent,
StopOrderIntent,
TrailingStopOrderIntent,
} from "../order-schema";
import { toStringBoolean } from "../order-schema";
import { createOrderHandlers } from "../order-handlers";
function applyCommonFields(params: CreateOrderParams, intent: BaseOrderIntent): CreateOrderParams {
if (params.quantity === undefined) {
params.quantity = intent.quantity;
}
if (params.timeInForce === undefined && intent.timeInForce) {
params.timeInForce = intent.timeInForce;
}
if (intent.reduceOnly !== undefined) {
params.reduceOnly = toStringBoolean(intent.reduceOnly);
}
if (intent.closePosition !== undefined) {
params.closePosition = toStringBoolean(intent.closePosition);
}
return params;
}
const handlers = createOrderHandlers({
exchangeName: "StandX",
defaultLimitTimeInForce: "GTX",
defaultMarketTimeInForce: "IOC",
defaultCloseTimeInForce: "IOC",
supportsTrailingStop: false,
supportsTriggerType: false,
stopDefaultReduceOnly: true,
stopDefaultClosePosition: true,
closeDefaultClosePosition: true,
});
export async function createLimitOrder(intent: LimitOrderIntent): Promise<Order> {
const params: CreateOrderParams = applyCommonFields(
{
symbol: intent.symbol,
side: intent.side,
type: "LIMIT",
quantity: intent.quantity,
price: intent.price,
timeInForce: intent.timeInForce ?? "GTX",
slPrice: intent.slPrice,
tpPrice: intent.tpPrice,
},
intent
);
return intent.adapter.createOrder(params);
}
export async function createMarketOrder(intent: MarketOrderIntent): Promise<Order> {
const params: CreateOrderParams = applyCommonFields(
{
symbol: intent.symbol,
side: intent.side,
type: "MARKET",
quantity: intent.quantity,
timeInForce: intent.timeInForce ?? "IOC",
},
intent
);
return intent.adapter.createOrder(params);
}
export async function createStopOrder(intent: StopOrderIntent): Promise<Order> {
const params: CreateOrderParams = applyCommonFields(
{
symbol: intent.symbol,
side: intent.side,
type: "STOP_MARKET",
quantity: intent.quantity,
stopPrice: intent.stopPrice,
timeInForce: intent.timeInForce ?? "GTC",
reduceOnly: toStringBoolean(intent.reduceOnly ?? true),
closePosition: toStringBoolean(intent.closePosition ?? true),
},
intent
);
return intent.adapter.createOrder(params);
}
export async function createTrailingStopOrder(_intent: TrailingStopOrderIntent): Promise<Order> {
throw new Error("StandX exchange does not support trailing stop orders");
}
export async function createClosePositionOrder(intent: ClosePositionIntent): Promise<Order> {
const params: CreateOrderParams = applyCommonFields(
{
symbol: intent.symbol,
side: intent.side,
type: "MARKET",
quantity: intent.quantity,
reduceOnly: "true",
closePosition: toStringBoolean(intent.closePosition ?? true),
timeInForce: intent.timeInForce ?? "IOC",
},
intent
);
return intent.adapter.createOrder(params);
}
export const {
createLimitOrder,
createMarketOrder,
createStopOrder,
createTrailingStopOrder,
createClosePositionOrder,
} = handlers;