Skip to content

Commit

Permalink
add validations for batch cancel orders (#229)
Browse files Browse the repository at this point in the history
* add validations for batch cancel orders in v4-client-js

* add broadcast type field

* build and bump version
  • Loading branch information
aforaleka authored Aug 28, 2024
1 parent 84543fd commit 4227bd0
Show file tree
Hide file tree
Showing 9 changed files with 147 additions and 16 deletions.
40 changes: 31 additions & 9 deletions v4-client-js/__native__/__ios__/v4-native-client.js

Large diffs are not rendered by default.

12 changes: 12 additions & 0 deletions v4-client-js/__tests__/helpers/constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import {
IPlaceOrder,
Order_Side,
Order_TimeInForce,
IBatchCancelOrder,
} from '../../src/types';

export const TEST_ADDRESS: string = 'dydx1vl9h9nkmau4e9v7tm30wekespu3d2qhd9404wa';
Expand Down Expand Up @@ -45,6 +46,17 @@ export const defaultCancelOrder: ICancelOrder = {
goodTilBlock: 4250,
};

// BatchCancelOrder variables
export const defaultBatchCancelOrder: IBatchCancelOrder = {
shortTermOrders: [
{
clobPairId: ClobPairId.PERPETUAL_PAIR_BTC_USD,
clientIds: [generateRandomClientId(), generateRandomClientId()],
},
],
goodTilBlock: 4250,
};

// Transfer variables
export const defaultTransfer: Transfer = {
sender: {
Expand Down
50 changes: 49 additions & 1 deletion v4-client-js/__tests__/lib/validation.test.ts
Original file line number Diff line number Diff line change
@@ -1,15 +1,24 @@
import { ICancelOrder, IPlaceOrder, OrderFlags, Transfer } from '../../src/types';
import {
ClobPairId,
IBatchCancelOrder,
ICancelOrder,
IPlaceOrder,
OrderFlags,
Transfer,
} from '../../src/types';
import { MAX_SUBACCOUNT_NUMBER, MAX_UINT_32 } from '../../src/lib/constants';
import { UserError } from '../../src/lib/errors';
import {
isValidAddress,
validateBatchCancelOrderMessage,
validateCancelOrderMessage,
validatePlaceOrderMessage,
validateTransferMessage,
} from '../../src/lib/validation';
import {
TEST_ADDRESS,
defaultCancelOrder,
defaultBatchCancelOrder,
defaultOrder,
defaultTransfer,
} from '../helpers/constants';
Expand Down Expand Up @@ -150,6 +159,45 @@ describe('Validations', () => {
},
);

it.each([
['valid', defaultBatchCancelOrder, undefined],
[
'overflow clientId',
{
...defaultBatchCancelOrder,
shortTermOrders: [
...defaultBatchCancelOrder.shortTermOrders,
{
clobPairId: ClobPairId.PERPETUAL_PAIR_ETH_USD,
clientIds: [MAX_UINT_32_PLUS_1],
},
],
},
new UserError(`clientId: ${MAX_UINT_32_PLUS_1} is not a valid uint32`),
],
[
'underflow goodTilBlock',
{ ...defaultBatchCancelOrder, goodTilBlock: -1 },
new UserError(`goodTilBlock: ${-1} is not a valid uint32 or is 0`),
],
[
'overflow goodTilBlock',
{ ...defaultBatchCancelOrder, goodTilBlock: MAX_UINT_32_PLUS_1 },
new UserError(`goodTilBlock: ${MAX_UINT_32_PLUS_1} is not a valid uint32 or is 0`),
],
[
'0 goodTilBlock',
{ ...defaultBatchCancelOrder, goodTilBlock: 0 },
new UserError(`goodTilBlock: ${0} is not a valid uint32 or is 0`),
],
])(
'Validate batch cancel orders: %s',
(_name: string, orders: IBatchCancelOrder, expectedError: UserError | undefined) => {
const validationError: UserError | void = validateBatchCancelOrderMessage(0, orders);
expect(validationError).toEqual(expectedError);
},
);

it.each([
['valid', defaultTransfer, undefined],
[
Expand Down
4 changes: 2 additions & 2 deletions v4-client-js/package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion v4-client-js/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@dydxprotocol/v4-client-js",
"version": "1.2.0",
"version": "1.2.1",
"description": "General client library for the new dYdX system (v4 decentralized)",
"main": "build/src/index.js",
"scripts": {
Expand Down
4 changes: 4 additions & 0 deletions v4-client-js/src/clients/composite-client.ts
Original file line number Diff line number Diff line change
Expand Up @@ -714,6 +714,7 @@ async batchCancelShortTermOrdersWithMarketId(
subaccount: SubaccountInfo,
shortTermOrders: OrderBatchWithMarketId[],
goodTilBlock: number,
broadcastMode?: BroadcastMode,
): Promise<BroadcastTxAsyncResponse | BroadcastTxSyncResponse | IndexedTx> {
const orderBatches = await Promise.all(
shortTermOrders.map(async ({ marketId, clobPairId, clientIds }) => ({
Expand All @@ -728,6 +729,7 @@ async batchCancelShortTermOrdersWithMarketId(
subaccount,
orderBatches,
goodTilBlock,
broadcastMode
);
}

Expand All @@ -743,11 +745,13 @@ async batchCancelShortTermOrdersWithMarketId(
subaccount: SubaccountInfo,
shortTermOrders: OrderBatch[],
goodTilBlock: number,
broadcastMode?: BroadcastMode,
): Promise<BroadcastTxAsyncResponse | BroadcastTxSyncResponse | IndexedTx> {
return this.validatorClient.post.batchCancelShortTermOrders(
subaccount,
shortTermOrders,
goodTilBlock,
broadcastMode,
);
}

Expand Down
5 changes: 5 additions & 0 deletions v4-client-js/src/clients/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,11 @@ export interface IPlaceOrder extends IBasicOrder {

export interface ICancelOrder extends IBasicOrder {}

export interface IBatchCancelOrder {
shortTermOrders: { clobPairId: number; clientIds: number[] }[];
goodTilBlock: number;
}

// How long to wait and how often to check when calling Broadcast with
// Method.BroadcastTxCommit
export interface BroadcastOptions {
Expand Down
45 changes: 42 additions & 3 deletions v4-client-js/src/lib/validation.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,13 @@ import { decode } from 'bech32';
import Long from 'long';

import { MAX_SUBACCOUNT_NUMBER, MAX_UINT_32 } from '../clients/constants';
import { Transfer, OrderFlags, ICancelOrder, IPlaceOrder } from '../clients/types';
import {
Transfer,
OrderFlags,
ICancelOrder,
IPlaceOrder,
IBatchCancelOrder,
} from '../clients/types';
import { UserError } from './errors';

/**
Expand Down Expand Up @@ -77,19 +83,52 @@ export function validateCancelOrderMessage(
return undefined;
}

/**
* @describe validateBatchCancelOrderMessage validates that orders to batch cancel have fields that would be
* valid on-chain.
*/
export function validateBatchCancelOrderMessage(
subaccountNumber: number,
orders: IBatchCancelOrder,
): UserError | undefined {
for (const orderBatch of orders.shortTermOrders) {
for (const clientId of orderBatch.clientIds) {
if (!verifyNumberIsUint32(clientId)) {
return new UserError(`clientId: ${clientId} is not a valid uint32`);
}
}
}

if (!verifyGoodTilBlock(orders.goodTilBlock)) {
return new UserError(`goodTilBlock: ${orders.goodTilBlock} is not a valid uint32 or is 0`);
}

if (!verifySubaccountNumber(subaccountNumber)) {
return new UserError(
`subaccountNumber: ${subaccountNumber} cannot be < 0 or > ${MAX_SUBACCOUNT_NUMBER}`,
);
}

return undefined;
}

/**
* @describe validateTransferMessage validates that a transfer to place has fields that would be
* valid on-chain.
*/
export function validateTransferMessage(transfer: Transfer): UserError | undefined {
if (!verifySubaccountNumber(transfer.sender!!.number || 0)) {
return new UserError(
`senderSubaccountNumber: ${transfer.sender!!.number || 0} cannot be < 0 or > ${MAX_SUBACCOUNT_NUMBER}`,
`senderSubaccountNumber: ${
transfer.sender!!.number || 0
} cannot be < 0 or > ${MAX_SUBACCOUNT_NUMBER}`,
);
}
if (!verifySubaccountNumber(transfer.recipient!!.number || 0)) {
return new UserError(
`recipientSubaccountNumber: ${transfer.recipient!!.number || 0} cannot be < 0 or > ${MAX_SUBACCOUNT_NUMBER}`,
`recipientSubaccountNumber: ${
transfer.recipient!!.number || 0
} cannot be < 0 or > ${MAX_SUBACCOUNT_NUMBER}`,
);
}
if (transfer.assetId !== 0) {
Expand Down
1 change: 1 addition & 0 deletions v4-client-js/src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -40,4 +40,5 @@ export interface Options {

export enum ClobPairId {
PERPETUAL_PAIR_BTC_USD = 0,
PERPETUAL_PAIR_ETH_USD = 1,
}

0 comments on commit 4227bd0

Please sign in to comment.