diff --git a/src/CBExchangeClient.ts b/src/CBExchangeClient.ts index 336281d..ffadf27 100644 --- a/src/CBExchangeClient.ts +++ b/src/CBExchangeClient.ts @@ -413,6 +413,7 @@ export class CBExchangeClient extends BaseRestClient { * Once an order is placed, your account funds will be put on hold for the duration of the order. */ submitOrder(params: SubmitCBExchOrderRequest): Promise { + this.validateOrderId(params, 'client_oid'); return this.postPrivate('/orders', { body: params }); } diff --git a/src/CBInternationalClient.ts b/src/CBInternationalClient.ts index a2c4b98..36e37d6 100644 --- a/src/CBInternationalClient.ts +++ b/src/CBInternationalClient.ts @@ -166,6 +166,7 @@ export class CBInternationalClient extends BaseRestClient { * Creates a new order. */ submitOrder(params: SubmitINTXOrderRequest): Promise { + this.validateOrderId(params, 'client_order_id'); return this.postPrivate('/api/v1/orders', { body: params }); } diff --git a/src/CBPrimeClient.ts b/src/CBPrimeClient.ts index 083c49a..47c33a6 100644 --- a/src/CBPrimeClient.ts +++ b/src/CBPrimeClient.ts @@ -393,6 +393,7 @@ export class CBPrimeClient extends BaseRestClient { * Create an order for a given portfolio. */ submitOrder(params: SubmitPrimeOrderRequest): Promise { + this.validateOrderId(params, 'client_order_id'); const { portfolio_id, ...body } = params; return this.postPrivate(`/v1/portfolios/${portfolio_id}/order`, { body: body, diff --git a/src/lib/BaseRestClient.ts b/src/lib/BaseRestClient.ts index 3777c37..988e4a8 100644 --- a/src/lib/BaseRestClient.ts +++ b/src/lib/BaseRestClient.ts @@ -7,6 +7,9 @@ import { CloseAdvTradePositionRequest, SubmitAdvTradeOrderRequest, } from '../types/request/advanced-trade-client.js'; +import { SubmitCBExchOrderRequest } from '../types/request/coinbase-exchange.js'; +import { SubmitINTXOrderRequest } from '../types/request/coinbase-international.js'; +import { SubmitPrimeOrderRequest } from '../types/request/coinbase-prime.js'; import { CustomOrderIdProperty } from '../types/shared.types.js'; import { signJWT } from './jwtNode.js'; import { neverGuard } from './misc-util.js'; @@ -264,31 +267,39 @@ export abstract class BaseRestClient { } public generateNewOrderId(): string { - return APIIDPrefix + nanoid(30); + return APIIDPrefix + nanoid(14); } /** - * Validate syntax meets requirements set by binance. Log warning if not. + * Validate syntax meets requirements set by coinbase. Log warning if not. */ protected validateOrderId( - params: SubmitAdvTradeOrderRequest | CloseAdvTradePositionRequest, + params: + | SubmitAdvTradeOrderRequest + | CloseAdvTradePositionRequest + | SubmitCBExchOrderRequest + | SubmitINTXOrderRequest + | SubmitPrimeOrderRequest, orderIdProperty: CustomOrderIdProperty, ): void { - if (!params[orderIdProperty]) { - params[orderIdProperty] = this.generateNewOrderId(); + // Not the cleanest but strict checks aren't quite necessary here either + const requestParams = params as any; + + if (!requestParams[orderIdProperty]) { + requestParams[orderIdProperty] = this.generateNewOrderId(); return; } - if (!params[orderIdProperty].startsWith(APIIDPrefix)) { + if (!requestParams[orderIdProperty].startsWith(APIIDPrefix)) { logInvalidOrderId(orderIdProperty, APIIDPrefix, params); - const previousValue = params[orderIdProperty]; - const newValue = APIIDPrefix + params[orderIdProperty]; + const previousValue = requestParams[orderIdProperty]; + const newValue = APIIDPrefix + requestParams[orderIdProperty]; console.warn( `WARNING: "${orderIdProperty}" was automatically prefixed. Changed from "${previousValue}" to "${newValue}". To avoid this, apply the prefix before submitting an order or use the client.generateNewOrderId() utility method.`, ); - params[orderIdProperty] = newValue; + requestParams[orderIdProperty] = newValue; } } diff --git a/src/types/request/coinbase-international.ts b/src/types/request/coinbase-international.ts index 967cad7..5a43d0d 100644 --- a/src/types/request/coinbase-international.ts +++ b/src/types/request/coinbase-international.ts @@ -37,7 +37,7 @@ export interface GetINTXAggregatedCandlesData { */ export interface SubmitINTXOrderRequest { - client_order_id: string; + client_order_id?: string; side: string; size: string; tif: string; diff --git a/src/types/request/coinbase-prime.ts b/src/types/request/coinbase-prime.ts index 7822a8d..6e1cbcc 100644 --- a/src/types/request/coinbase-prime.ts +++ b/src/types/request/coinbase-prime.ts @@ -172,7 +172,7 @@ export interface SubmitPrimeOrderRequest { portfolio_id: string; product_id: string; side: 'BUY' | 'SELL'; - client_order_id: string; + client_order_id?: string; type?: 'MARKET' | 'LIMIT' | 'TWAP' | 'VWAP' | 'STOP_LIMIT'; base_quantity?: string; quote_value?: string; diff --git a/src/types/shared.types.ts b/src/types/shared.types.ts index 86bf6bc..3f96b83 100644 --- a/src/types/shared.types.ts +++ b/src/types/shared.types.ts @@ -68,4 +68,4 @@ export interface OrderConfiguration { trigger_bracket_gtd?: TriggerBracketGTD; } -export type CustomOrderIdProperty = 'client_order_id'; +export type CustomOrderIdProperty = 'client_order_id' | 'client_oid';