diff options
Diffstat (limited to 'packages/json-schemas')
26 files changed, 1274 insertions, 1274 deletions
diff --git a/packages/json-schemas/package.json b/packages/json-schemas/package.json index 30cccb12f..d67cb64f7 100644 --- a/packages/json-schemas/package.json +++ b/packages/json-schemas/package.json @@ -1,45 +1,45 @@ { - "name": "@0xproject/json-schemas", - "version": "0.7.5", - "description": "0x-related json schemas", - "main": "lib/src/index.js", - "types": "lib/src/index.d.ts", - "scripts": { - "lint": "tslint --project . 'src/**/*.ts' 'test/**/*.ts'", - "test": "run-s clean build run_mocha", - "test:circleci": "yarn test", - "run_mocha": "mocha lib/test/**/*_test.js", - "clean": "shx rm -rf _bundles lib test_temp", - "build": "tsc" - }, - "repository": { - "type": "git", - "url": "https://github.com/0xProject/0x.js.git" - }, - "author": "", - "license": "Apache-2.0", - "bugs": { - "url": "https://github.com/0xProject/0x.js/issues" - }, - "homepage": "https://github.com/0xProject/0x.js/packages/json-schemas/README.md", - "dependencies": { - "jsonschema": "^1.2.0", - "lodash.values": "^4.3.0" - }, - "devDependencies": { - "@0xproject/tslint-config": "^0.4.4", - "@0xproject/utils": "^0.2.2", - "@types/lodash.foreach": "^4.5.3", - "@types/lodash.values": "^4.3.3", - "@types/mocha": "^2.2.42", - "chai": "^4.0.1", - "chai-typescript-typings": "^0.0.2", - "dirty-chai": "^2.0.1", - "lodash.foreach": "^4.5.0", - "mocha": "^4.0.1", - "npm-run-all": "^4.1.2", - "shx": "^0.2.2", - "tslint": "5.8.0", - "typescript": "~2.6.1" - } + "name": "@0xproject/json-schemas", + "version": "0.7.5", + "description": "0x-related json schemas", + "main": "lib/src/index.js", + "types": "lib/src/index.d.ts", + "scripts": { + "lint": "tslint --project . 'src/**/*.ts' 'test/**/*.ts'", + "test": "run-s clean build run_mocha", + "test:circleci": "yarn test", + "run_mocha": "mocha lib/test/**/*_test.js", + "clean": "shx rm -rf _bundles lib test_temp", + "build": "tsc" + }, + "repository": { + "type": "git", + "url": "https://github.com/0xProject/0x.js.git" + }, + "author": "", + "license": "Apache-2.0", + "bugs": { + "url": "https://github.com/0xProject/0x.js/issues" + }, + "homepage": "https://github.com/0xProject/0x.js/packages/json-schemas/README.md", + "dependencies": { + "jsonschema": "^1.2.0", + "lodash.values": "^4.3.0" + }, + "devDependencies": { + "@0xproject/tslint-config": "^0.4.4", + "@0xproject/utils": "^0.2.2", + "@types/lodash.foreach": "^4.5.3", + "@types/lodash.values": "^4.3.3", + "@types/mocha": "^2.2.42", + "chai": "^4.0.1", + "chai-typescript-typings": "^0.0.2", + "dirty-chai": "^2.0.1", + "lodash.foreach": "^4.5.0", + "mocha": "^4.0.1", + "npm-run-all": "^4.1.2", + "shx": "^0.2.2", + "tslint": "5.8.0", + "typescript": "~2.6.1" + } } diff --git a/packages/json-schemas/schemas/basic_type_schemas.ts b/packages/json-schemas/schemas/basic_type_schemas.ts index aa2eea867..9d81ff333 100644 --- a/packages/json-schemas/schemas/basic_type_schemas.ts +++ b/packages/json-schemas/schemas/basic_type_schemas.ts @@ -1,11 +1,11 @@ export const addressSchema = { - id: '/Address', - type: 'string', - pattern: '^0x[0-9a-f]{40}$', + id: '/Address', + type: 'string', + pattern: '^0x[0-9a-f]{40}$', }; export const numberSchema = { - id: '/Number', - type: 'string', - pattern: '^\\d+(\\.\\d+)?$', + id: '/Number', + type: 'string', + pattern: '^\\d+(\\.\\d+)?$', }; diff --git a/packages/json-schemas/schemas/block_range_schema.ts b/packages/json-schemas/schemas/block_range_schema.ts index 8697bba96..1f6a63151 100644 --- a/packages/json-schemas/schemas/block_range_schema.ts +++ b/packages/json-schemas/schemas/block_range_schema.ts @@ -1,20 +1,20 @@ export const blockParamSchema = { - id: '/BlockParam', - oneOf: [ - { - type: 'number', - }, - { - enum: ['latest', 'earliest', 'pending'], - }, - ], + id: '/BlockParam', + oneOf: [ + { + type: 'number', + }, + { + enum: ['latest', 'earliest', 'pending'], + }, + ], }; export const blockRangeSchema = { - id: '/BlockRange', - properties: { - fromBlock: { $ref: '/BlockParam' }, - toBlock: { $ref: '/BlockParam' }, - }, - type: 'object', + id: '/BlockRange', + properties: { + fromBlock: { $ref: '/BlockParam' }, + toBlock: { $ref: '/BlockParam' }, + }, + type: 'object', }; diff --git a/packages/json-schemas/schemas/ec_signature_schema.ts b/packages/json-schemas/schemas/ec_signature_schema.ts index 299ca283b..71b840dd8 100644 --- a/packages/json-schemas/schemas/ec_signature_schema.ts +++ b/packages/json-schemas/schemas/ec_signature_schema.ts @@ -1,20 +1,20 @@ export const ecSignatureParameterSchema = { - id: '/ECSignatureParameter', - type: 'string', - pattern: '^0[xX][0-9A-Fa-f]{64}$', + id: '/ECSignatureParameter', + type: 'string', + pattern: '^0[xX][0-9A-Fa-f]{64}$', }; export const ecSignatureSchema = { - id: '/ECSignature', - properties: { - v: { - type: 'number', - minimum: 27, - maximum: 28, - }, - r: { $ref: '/ECSignatureParameter' }, - s: { $ref: '/ECSignatureParameter' }, - }, - required: ['v', 'r', 's'], - type: 'object', + id: '/ECSignature', + properties: { + v: { + type: 'number', + minimum: 27, + maximum: 28, + }, + r: { $ref: '/ECSignatureParameter' }, + s: { $ref: '/ECSignatureParameter' }, + }, + required: ['v', 'r', 's'], + type: 'object', }; diff --git a/packages/json-schemas/schemas/index_filter_values_schema.ts b/packages/json-schemas/schemas/index_filter_values_schema.ts index 6e9f36c54..3374d63e0 100644 --- a/packages/json-schemas/schemas/index_filter_values_schema.ts +++ b/packages/json-schemas/schemas/index_filter_values_schema.ts @@ -1,7 +1,7 @@ export const indexFilterValuesSchema = { - id: '/IndexFilterValues', - additionalProperties: { - oneOf: [{ $ref: '/Number' }, { $ref: '/Address' }, { $ref: '/OrderHashSchema' }], - }, - type: 'object', + id: '/IndexFilterValues', + additionalProperties: { + oneOf: [{ $ref: '/Number' }, { $ref: '/Address' }, { $ref: '/OrderHashSchema' }], + }, + type: 'object', }; diff --git a/packages/json-schemas/schemas/order_cancel_schema.ts b/packages/json-schemas/schemas/order_cancel_schema.ts index f2aa80e7a..ad23d01cc 100644 --- a/packages/json-schemas/schemas/order_cancel_schema.ts +++ b/packages/json-schemas/schemas/order_cancel_schema.ts @@ -1,12 +1,12 @@ export const orderCancellationRequestsSchema = { - id: '/OrderCancellationRequests', - type: 'array', - items: { - properties: { - order: { $ref: '/Order' }, - takerTokenCancelAmount: { $ref: '/Number' }, - }, - required: ['order', 'takerTokenCancelAmount'], - type: 'object', - }, + id: '/OrderCancellationRequests', + type: 'array', + items: { + properties: { + order: { $ref: '/Order' }, + takerTokenCancelAmount: { $ref: '/Number' }, + }, + required: ['order', 'takerTokenCancelAmount'], + type: 'object', + }, }; diff --git a/packages/json-schemas/schemas/order_fill_or_kill_requests_schema.ts b/packages/json-schemas/schemas/order_fill_or_kill_requests_schema.ts index f13bc9cc3..61f2c8849 100644 --- a/packages/json-schemas/schemas/order_fill_or_kill_requests_schema.ts +++ b/packages/json-schemas/schemas/order_fill_or_kill_requests_schema.ts @@ -1,12 +1,12 @@ export const orderFillOrKillRequestsSchema = { - id: '/OrderFillOrKillRequests', - type: 'array', - items: { - properties: { - signedOrder: { $ref: '/SignedOrder' }, - fillTakerAmount: { $ref: '/Number' }, - }, - required: ['signedOrder', 'fillTakerAmount'], - type: 'object', - }, + id: '/OrderFillOrKillRequests', + type: 'array', + items: { + properties: { + signedOrder: { $ref: '/SignedOrder' }, + fillTakerAmount: { $ref: '/Number' }, + }, + required: ['signedOrder', 'fillTakerAmount'], + type: 'object', + }, }; diff --git a/packages/json-schemas/schemas/order_fill_requests_schema.ts b/packages/json-schemas/schemas/order_fill_requests_schema.ts index 45cd927be..419d0670f 100644 --- a/packages/json-schemas/schemas/order_fill_requests_schema.ts +++ b/packages/json-schemas/schemas/order_fill_requests_schema.ts @@ -1,12 +1,12 @@ export const orderFillRequestsSchema = { - id: '/OrderFillRequests', - type: 'array', - items: { - properties: { - signedOrder: { $ref: '/SignedOrder' }, - takerTokenFillAmount: { $ref: '/Number' }, - }, - required: ['signedOrder', 'takerTokenFillAmount'], - type: 'object', - }, + id: '/OrderFillRequests', + type: 'array', + items: { + properties: { + signedOrder: { $ref: '/SignedOrder' }, + takerTokenFillAmount: { $ref: '/Number' }, + }, + required: ['signedOrder', 'takerTokenFillAmount'], + type: 'object', + }, }; diff --git a/packages/json-schemas/schemas/order_hash_schema.ts b/packages/json-schemas/schemas/order_hash_schema.ts index 5eed112ca..6af06927f 100644 --- a/packages/json-schemas/schemas/order_hash_schema.ts +++ b/packages/json-schemas/schemas/order_hash_schema.ts @@ -1,5 +1,5 @@ export const orderHashSchema = { - id: '/OrderHashSchema', - type: 'string', - pattern: '^0x[0-9a-fA-F]{64}$', + id: '/OrderHashSchema', + type: 'string', + pattern: '^0x[0-9a-fA-F]{64}$', }; diff --git a/packages/json-schemas/schemas/order_schemas.ts b/packages/json-schemas/schemas/order_schemas.ts index ee5f2c137..6f17224ad 100644 --- a/packages/json-schemas/schemas/order_schemas.ts +++ b/packages/json-schemas/schemas/order_schemas.ts @@ -1,43 +1,43 @@ export const orderSchema = { - id: '/Order', - properties: { - maker: { $ref: '/Address' }, - taker: { $ref: '/Address' }, - makerFee: { $ref: '/Number' }, - takerFee: { $ref: '/Number' }, - makerTokenAmount: { $ref: '/Number' }, - takerTokenAmount: { $ref: '/Number' }, - makerTokenAddress: { $ref: '/Address' }, - takerTokenAddress: { $ref: '/Address' }, - salt: { $ref: '/Number' }, - feeRecipient: { $ref: '/Address' }, - expirationUnixTimestampSec: { $ref: '/Number' }, - exchangeContractAddress: { $ref: '/Address' }, - }, - required: [ - 'maker', - 'taker', - 'makerFee', - 'takerFee', - 'makerTokenAmount', - 'takerTokenAmount', - 'salt', - 'feeRecipient', - 'expirationUnixTimestampSec', - 'exchangeContractAddress', - ], - type: 'object', + id: '/Order', + properties: { + maker: { $ref: '/Address' }, + taker: { $ref: '/Address' }, + makerFee: { $ref: '/Number' }, + takerFee: { $ref: '/Number' }, + makerTokenAmount: { $ref: '/Number' }, + takerTokenAmount: { $ref: '/Number' }, + makerTokenAddress: { $ref: '/Address' }, + takerTokenAddress: { $ref: '/Address' }, + salt: { $ref: '/Number' }, + feeRecipient: { $ref: '/Address' }, + expirationUnixTimestampSec: { $ref: '/Number' }, + exchangeContractAddress: { $ref: '/Address' }, + }, + required: [ + 'maker', + 'taker', + 'makerFee', + 'takerFee', + 'makerTokenAmount', + 'takerTokenAmount', + 'salt', + 'feeRecipient', + 'expirationUnixTimestampSec', + 'exchangeContractAddress', + ], + type: 'object', }; export const signedOrderSchema = { - id: '/SignedOrder', - allOf: [ - { $ref: '/Order' }, - { - properties: { - ecSignature: { $ref: '/ECSignature' }, - }, - required: ['ecSignature'], - }, - ], + id: '/SignedOrder', + allOf: [ + { $ref: '/Order' }, + { + properties: { + ecSignature: { $ref: '/ECSignature' }, + }, + required: ['ecSignature'], + }, + ], }; diff --git a/packages/json-schemas/schemas/relayer_api_error_response_schema.ts b/packages/json-schemas/schemas/relayer_api_error_response_schema.ts index 3d3a96364..27fdb166f 100644 --- a/packages/json-schemas/schemas/relayer_api_error_response_schema.ts +++ b/packages/json-schemas/schemas/relayer_api_error_response_schema.ts @@ -1,21 +1,21 @@ export const relayerApiErrorResponseSchema = { - id: '/RelayerApiErrorResponse', - type: 'object', - properties: { - code: { type: 'number' }, - reason: { type: 'string' }, - validationErrors: { - type: 'array', - items: { - type: 'object', - properties: { - field: { type: 'string' }, - code: { type: 'number' }, - reason: { type: 'string' }, - }, - required: ['field', 'code', 'reason'], - }, - }, - }, - required: ['code', 'reason'], + id: '/RelayerApiErrorResponse', + type: 'object', + properties: { + code: { type: 'number' }, + reason: { type: 'string' }, + validationErrors: { + type: 'array', + items: { + type: 'object', + properties: { + field: { type: 'string' }, + code: { type: 'number' }, + reason: { type: 'string' }, + }, + required: ['field', 'code', 'reason'], + }, + }, + }, + required: ['code', 'reason'], }; diff --git a/packages/json-schemas/schemas/relayer_api_fees_payload_schema.ts b/packages/json-schemas/schemas/relayer_api_fees_payload_schema.ts index f79308594..eaaf777a1 100644 --- a/packages/json-schemas/schemas/relayer_api_fees_payload_schema.ts +++ b/packages/json-schemas/schemas/relayer_api_fees_payload_schema.ts @@ -1,24 +1,24 @@ export const relayerApiFeesPayloadSchema = { - id: '/RelayerApiFeesPayload', - type: 'object', - properties: { - exchangeContractAddress: { $ref: '/Address' }, - maker: { $ref: '/Address' }, - taker: { $ref: '/Address' }, - makerTokenAddress: { $ref: '/Address' }, - takerTokenAddress: { $ref: '/Address' }, - makerTokenAmount: { $ref: '/Number' }, - takerTokenAmount: { $ref: '/Number' }, - expirationUnixTimestampSec: { $ref: '/Number' }, - salt: { $ref: '/Number' }, - }, - required: [ - 'exchangeContractAddress', - 'maker', - 'taker', - 'makerTokenAddress', - 'takerTokenAddress', - 'expirationUnixTimestampSec', - 'salt', - ], + id: '/RelayerApiFeesPayload', + type: 'object', + properties: { + exchangeContractAddress: { $ref: '/Address' }, + maker: { $ref: '/Address' }, + taker: { $ref: '/Address' }, + makerTokenAddress: { $ref: '/Address' }, + takerTokenAddress: { $ref: '/Address' }, + makerTokenAmount: { $ref: '/Number' }, + takerTokenAmount: { $ref: '/Number' }, + expirationUnixTimestampSec: { $ref: '/Number' }, + salt: { $ref: '/Number' }, + }, + required: [ + 'exchangeContractAddress', + 'maker', + 'taker', + 'makerTokenAddress', + 'takerTokenAddress', + 'expirationUnixTimestampSec', + 'salt', + ], }; diff --git a/packages/json-schemas/schemas/relayer_api_fees_response_schema.ts b/packages/json-schemas/schemas/relayer_api_fees_response_schema.ts index d87c2fcdb..e7440613f 100644 --- a/packages/json-schemas/schemas/relayer_api_fees_response_schema.ts +++ b/packages/json-schemas/schemas/relayer_api_fees_response_schema.ts @@ -1,10 +1,10 @@ export const relayerApiFeesResponseSchema = { - id: '/RelayerApiFeesResponse', - type: 'object', - properties: { - makerFee: { $ref: '/Number' }, - takerFee: { $ref: '/Number' }, - feeRecipient: { $ref: '/Address' }, - }, - required: ['makerFee', 'takerFee', 'feeRecipient'], + id: '/RelayerApiFeesResponse', + type: 'object', + properties: { + makerFee: { $ref: '/Number' }, + takerFee: { $ref: '/Number' }, + feeRecipient: { $ref: '/Address' }, + }, + required: ['makerFee', 'takerFee', 'feeRecipient'], }; diff --git a/packages/json-schemas/schemas/relayer_api_orberbook_channel_subscribe_schema.ts b/packages/json-schemas/schemas/relayer_api_orberbook_channel_subscribe_schema.ts index 1d443c625..d93fa73d6 100644 --- a/packages/json-schemas/schemas/relayer_api_orberbook_channel_subscribe_schema.ts +++ b/packages/json-schemas/schemas/relayer_api_orberbook_channel_subscribe_schema.ts @@ -1,23 +1,23 @@ export const relayerApiOrderbookChannelSubscribeSchema = { - id: '/RelayerApiOrderbookChannelSubscribe', - type: 'object', - properties: { - type: { enum: ['subscribe'] }, - channel: { enum: ['orderbook'] }, - requestId: { type: 'number' }, - payload: { $ref: '/RelayerApiOrderbookChannelSubscribePayload' }, - }, - required: ['type', 'channel', 'requestId', 'payload'], + id: '/RelayerApiOrderbookChannelSubscribe', + type: 'object', + properties: { + type: { enum: ['subscribe'] }, + channel: { enum: ['orderbook'] }, + requestId: { type: 'number' }, + payload: { $ref: '/RelayerApiOrderbookChannelSubscribePayload' }, + }, + required: ['type', 'channel', 'requestId', 'payload'], }; export const relayerApiOrderbookChannelSubscribePayload = { - id: '/RelayerApiOrderbookChannelSubscribePayload', - type: 'object', - properties: { - baseTokenAddress: { $ref: '/Address' }, - quoteTokenAddress: { $ref: '/Address' }, - snapshot: { type: 'boolean' }, - limit: { type: 'number' }, - }, - required: ['baseTokenAddress', 'quoteTokenAddress'], + id: '/RelayerApiOrderbookChannelSubscribePayload', + type: 'object', + properties: { + baseTokenAddress: { $ref: '/Address' }, + quoteTokenAddress: { $ref: '/Address' }, + snapshot: { type: 'boolean' }, + limit: { type: 'number' }, + }, + required: ['baseTokenAddress', 'quoteTokenAddress'], }; diff --git a/packages/json-schemas/schemas/relayer_api_orderbook_channel_snapshot_schema.ts b/packages/json-schemas/schemas/relayer_api_orderbook_channel_snapshot_schema.ts index e954185a8..fe1510d5b 100644 --- a/packages/json-schemas/schemas/relayer_api_orderbook_channel_snapshot_schema.ts +++ b/packages/json-schemas/schemas/relayer_api_orderbook_channel_snapshot_schema.ts @@ -1,21 +1,21 @@ export const relayerApiOrderbookChannelSnapshotSchema = { - id: '/RelayerApiOrderbookChannelSnapshot', - type: 'object', - properties: { - type: { enum: ['snapshot'] }, - channel: { enum: ['orderbook'] }, - requestId: { type: 'number' }, - payload: { $ref: '/RelayerApiOrderbookChannelSnapshotPayload' }, - }, - required: ['type', 'channel', 'requestId', 'payload'], + id: '/RelayerApiOrderbookChannelSnapshot', + type: 'object', + properties: { + type: { enum: ['snapshot'] }, + channel: { enum: ['orderbook'] }, + requestId: { type: 'number' }, + payload: { $ref: '/RelayerApiOrderbookChannelSnapshotPayload' }, + }, + required: ['type', 'channel', 'requestId', 'payload'], }; export const relayerApiOrderbookChannelSnapshotPayload = { - id: '/RelayerApiOrderbookChannelSnapshotPayload', - type: 'object', - properties: { - bids: { $ref: '/signedOrdersSchema' }, - asks: { $ref: '/signedOrdersSchema' }, - }, - required: ['bids', 'asks'], + id: '/RelayerApiOrderbookChannelSnapshotPayload', + type: 'object', + properties: { + bids: { $ref: '/signedOrdersSchema' }, + asks: { $ref: '/signedOrdersSchema' }, + }, + required: ['bids', 'asks'], }; diff --git a/packages/json-schemas/schemas/relayer_api_orderbook_channel_update_response_schema.ts b/packages/json-schemas/schemas/relayer_api_orderbook_channel_update_response_schema.ts index 7c2ba6531..9a6d83d4c 100644 --- a/packages/json-schemas/schemas/relayer_api_orderbook_channel_update_response_schema.ts +++ b/packages/json-schemas/schemas/relayer_api_orderbook_channel_update_response_schema.ts @@ -1,11 +1,11 @@ export const relayerApiOrderbookChannelUpdateSchema = { - id: '/RelayerApiOrderbookChannelUpdate', - type: 'object', - properties: { - type: { enum: ['update'] }, - channel: { enum: ['orderbook'] }, - requestId: { type: 'number' }, - payload: { $ref: '/SignedOrder' }, - }, - required: ['type', 'channel', 'requestId', 'payload'], + id: '/RelayerApiOrderbookChannelUpdate', + type: 'object', + properties: { + type: { enum: ['update'] }, + channel: { enum: ['orderbook'] }, + requestId: { type: 'number' }, + payload: { $ref: '/SignedOrder' }, + }, + required: ['type', 'channel', 'requestId', 'payload'], }; diff --git a/packages/json-schemas/schemas/relayer_api_orderbook_response_schema.ts b/packages/json-schemas/schemas/relayer_api_orderbook_response_schema.ts index d9abfc77d..5c409c807 100644 --- a/packages/json-schemas/schemas/relayer_api_orderbook_response_schema.ts +++ b/packages/json-schemas/schemas/relayer_api_orderbook_response_schema.ts @@ -1,9 +1,9 @@ export const relayerApiOrderBookResponseSchema = { - id: '/RelayerApiOrderBookResponse', - type: 'object', - properties: { - bids: { $ref: '/signedOrdersSchema' }, - asks: { $ref: '/signedOrdersSchema' }, - }, - required: ['bids', 'asks'], + id: '/RelayerApiOrderBookResponse', + type: 'object', + properties: { + bids: { $ref: '/signedOrdersSchema' }, + asks: { $ref: '/signedOrdersSchema' }, + }, + required: ['bids', 'asks'], }; diff --git a/packages/json-schemas/schemas/relayer_api_token_pairs_response_schema.ts b/packages/json-schemas/schemas/relayer_api_token_pairs_response_schema.ts index 471bed7b4..5009c7955 100644 --- a/packages/json-schemas/schemas/relayer_api_token_pairs_response_schema.ts +++ b/packages/json-schemas/schemas/relayer_api_token_pairs_response_schema.ts @@ -1,24 +1,24 @@ export const relayerApiTokenPairsResponseSchema = { - id: '/RelayerApiTokenPairsResponse', - type: 'array', - items: { - properties: { - tokenA: { $ref: '/RelayerApiTokenTradeInfo' }, - tokenB: { $ref: '/RelayerApiTokenTradeInfo' }, - }, - required: ['tokenA', 'tokenB'], - type: 'object', - }, + id: '/RelayerApiTokenPairsResponse', + type: 'array', + items: { + properties: { + tokenA: { $ref: '/RelayerApiTokenTradeInfo' }, + tokenB: { $ref: '/RelayerApiTokenTradeInfo' }, + }, + required: ['tokenA', 'tokenB'], + type: 'object', + }, }; export const relayerApiTokenTradeInfoSchema = { - id: '/RelayerApiTokenTradeInfo', - type: 'object', - properties: { - address: { $ref: '/Address' }, - minAmount: { $ref: '/Number' }, - maxAmount: { $ref: '/Number' }, - precision: { type: 'number' }, - }, - required: ['address'], + id: '/RelayerApiTokenTradeInfo', + type: 'object', + properties: { + address: { $ref: '/Address' }, + minAmount: { $ref: '/Number' }, + maxAmount: { $ref: '/Number' }, + precision: { type: 'number' }, + }, + required: ['address'], }; diff --git a/packages/json-schemas/schemas/signed_orders_schema.ts b/packages/json-schemas/schemas/signed_orders_schema.ts index 7d66b7027..34d956836 100644 --- a/packages/json-schemas/schemas/signed_orders_schema.ts +++ b/packages/json-schemas/schemas/signed_orders_schema.ts @@ -1,5 +1,5 @@ export const signedOrdersSchema = { - id: '/signedOrdersSchema', - type: 'array', - items: { $ref: '/SignedOrder' }, + id: '/signedOrdersSchema', + type: 'array', + items: { $ref: '/SignedOrder' }, }; diff --git a/packages/json-schemas/schemas/token_schema.ts b/packages/json-schemas/schemas/token_schema.ts index d2bb10f09..e64565c8b 100644 --- a/packages/json-schemas/schemas/token_schema.ts +++ b/packages/json-schemas/schemas/token_schema.ts @@ -1,11 +1,11 @@ export const tokenSchema = { - id: '/Token', - properties: { - name: { type: 'string' }, - symbol: { type: 'string' }, - decimals: { type: 'number' }, - address: { $ref: '/Address' }, - }, - required: ['name', 'symbol', 'decimals', 'address'], - type: 'object', + id: '/Token', + properties: { + name: { type: 'string' }, + symbol: { type: 'string' }, + decimals: { type: 'number' }, + address: { $ref: '/Address' }, + }, + required: ['name', 'symbol', 'decimals', 'address'], + type: 'object', }; diff --git a/packages/json-schemas/schemas/tx_data_schema.ts b/packages/json-schemas/schemas/tx_data_schema.ts index 00c1d3e08..4274c553f 100644 --- a/packages/json-schemas/schemas/tx_data_schema.ts +++ b/packages/json-schemas/schemas/tx_data_schema.ts @@ -1,33 +1,33 @@ export const jsNumber = { - id: '/JsNumber', - type: 'number', - minimum: 0, + id: '/JsNumber', + type: 'number', + minimum: 0, }; export const txDataSchema = { - id: '/TxData', - properties: { - from: { $ref: '/Address' }, - to: { $ref: '/Address' }, - value: { - oneOf: [{ $ref: '/Number' }, { $ref: '/JsNumber' }], - }, - gas: { - oneOf: [{ $ref: '/Number' }, { $ref: '/JsNumber' }], - }, - gasPrice: { - oneOf: [{ $ref: '/Number' }, { $ref: '/JsNumber' }], - }, - data: { - type: 'string', - pattern: '^0x[0-9a-f]*$', - }, - nonce: { - type: 'number', - minimum: 0, - }, - }, - required: ['from'], - type: 'object', - additionalProperties: false, + id: '/TxData', + properties: { + from: { $ref: '/Address' }, + to: { $ref: '/Address' }, + value: { + oneOf: [{ $ref: '/Number' }, { $ref: '/JsNumber' }], + }, + gas: { + oneOf: [{ $ref: '/Number' }, { $ref: '/JsNumber' }], + }, + gasPrice: { + oneOf: [{ $ref: '/Number' }, { $ref: '/JsNumber' }], + }, + data: { + type: 'string', + pattern: '^0x[0-9a-f]*$', + }, + nonce: { + type: 'number', + minimum: 0, + }, + }, + required: ['from'], + type: 'object', + additionalProperties: false, }; diff --git a/packages/json-schemas/src/schema_validator.ts b/packages/json-schemas/src/schema_validator.ts index 686c38d17..e13326d2a 100644 --- a/packages/json-schemas/src/schema_validator.ts +++ b/packages/json-schemas/src/schema_validator.ts @@ -4,26 +4,26 @@ import values = require('lodash.values'); import { schemas } from './schemas'; export class SchemaValidator { - private _validator: Validator; - constructor() { - this._validator = new Validator(); - for (const schema of values(schemas)) { - this._validator.addSchema(schema, schema.id); - } - } - public addSchema(schema: Schema) { - this._validator.addSchema(schema, schema.id); - } - // In order to validate a complex JS object using jsonschema, we must replace any complex - // sub-types (e.g BigNumber) with a simpler string representation. Since BigNumber and other - // complex types implement the `toString` method, we can stringify the object and - // then parse it. The resultant object can then be checked using jsonschema. - public validate(instance: any, schema: Schema): ValidatorResult { - const jsonSchemaCompatibleObject = JSON.parse(JSON.stringify(instance)); - return this._validator.validate(jsonSchemaCompatibleObject, schema); - } - public isValid(instance: any, schema: Schema): boolean { - const isValid = this.validate(instance, schema).errors.length === 0; - return isValid; - } + private _validator: Validator; + constructor() { + this._validator = new Validator(); + for (const schema of values(schemas)) { + this._validator.addSchema(schema, schema.id); + } + } + public addSchema(schema: Schema) { + this._validator.addSchema(schema, schema.id); + } + // In order to validate a complex JS object using jsonschema, we must replace any complex + // sub-types (e.g BigNumber) with a simpler string representation. Since BigNumber and other + // complex types implement the `toString` method, we can stringify the object and + // then parse it. The resultant object can then be checked using jsonschema. + public validate(instance: any, schema: Schema): ValidatorResult { + const jsonSchemaCompatibleObject = JSON.parse(JSON.stringify(instance)); + return this._validator.validate(jsonSchemaCompatibleObject, schema); + } + public isValid(instance: any, schema: Schema): boolean { + const isValid = this.validate(instance, schema).errors.length === 0; + return isValid; + } } diff --git a/packages/json-schemas/src/schemas.ts b/packages/json-schemas/src/schemas.ts index bdc227aea..5cb07acfe 100644 --- a/packages/json-schemas/src/schemas.ts +++ b/packages/json-schemas/src/schemas.ts @@ -11,50 +11,50 @@ import { relayerApiErrorResponseSchema } from '../schemas/relayer_api_error_resp import { relayerApiFeesPayloadSchema } from '../schemas/relayer_api_fees_payload_schema'; import { relayerApiFeesResponseSchema } from '../schemas/relayer_api_fees_response_schema'; import { - relayerApiOrderbookChannelSubscribePayload, - relayerApiOrderbookChannelSubscribeSchema, + relayerApiOrderbookChannelSubscribePayload, + relayerApiOrderbookChannelSubscribeSchema, } from '../schemas/relayer_api_orberbook_channel_subscribe_schema'; import { - relayerApiOrderbookChannelSnapshotPayload, - relayerApiOrderbookChannelSnapshotSchema, + relayerApiOrderbookChannelSnapshotPayload, + relayerApiOrderbookChannelSnapshotSchema, } from '../schemas/relayer_api_orderbook_channel_snapshot_schema'; import { relayerApiOrderbookChannelUpdateSchema } from '../schemas/relayer_api_orderbook_channel_update_response_schema'; import { relayerApiOrderBookResponseSchema } from '../schemas/relayer_api_orderbook_response_schema'; import { - relayerApiTokenPairsResponseSchema, - relayerApiTokenTradeInfoSchema, + relayerApiTokenPairsResponseSchema, + relayerApiTokenTradeInfoSchema, } from '../schemas/relayer_api_token_pairs_response_schema'; import { signedOrdersSchema } from '../schemas/signed_orders_schema'; import { tokenSchema } from '../schemas/token_schema'; import { jsNumber, txDataSchema } from '../schemas/tx_data_schema'; export const schemas = { - numberSchema, - addressSchema, - ecSignatureSchema, - ecSignatureParameterSchema, - indexFilterValuesSchema, - orderCancellationRequestsSchema, - orderFillOrKillRequestsSchema, - orderFillRequestsSchema, - orderHashSchema, - orderSchema, - signedOrderSchema, - signedOrdersSchema, - blockParamSchema, - blockRangeSchema, - tokenSchema, - jsNumber, - txDataSchema, - relayerApiErrorResponseSchema, - relayerApiFeesPayloadSchema, - relayerApiFeesResponseSchema, - relayerApiOrderBookResponseSchema, - relayerApiTokenPairsResponseSchema, - relayerApiTokenTradeInfoSchema, - relayerApiOrderbookChannelSubscribeSchema, - relayerApiOrderbookChannelSubscribePayload, - relayerApiOrderbookChannelUpdateSchema, - relayerApiOrderbookChannelSnapshotSchema, - relayerApiOrderbookChannelSnapshotPayload, + numberSchema, + addressSchema, + ecSignatureSchema, + ecSignatureParameterSchema, + indexFilterValuesSchema, + orderCancellationRequestsSchema, + orderFillOrKillRequestsSchema, + orderFillRequestsSchema, + orderHashSchema, + orderSchema, + signedOrderSchema, + signedOrdersSchema, + blockParamSchema, + blockRangeSchema, + tokenSchema, + jsNumber, + txDataSchema, + relayerApiErrorResponseSchema, + relayerApiFeesPayloadSchema, + relayerApiFeesResponseSchema, + relayerApiOrderBookResponseSchema, + relayerApiTokenPairsResponseSchema, + relayerApiTokenTradeInfoSchema, + relayerApiOrderbookChannelSubscribeSchema, + relayerApiOrderbookChannelSubscribePayload, + relayerApiOrderbookChannelUpdateSchema, + relayerApiOrderbookChannelSnapshotSchema, + relayerApiOrderbookChannelSnapshotPayload, }; diff --git a/packages/json-schemas/test/schema_test.ts b/packages/json-schemas/test/schema_test.ts index a6162c8e3..7b058781d 100644 --- a/packages/json-schemas/test/schema_test.ts +++ b/packages/json-schemas/test/schema_test.ts @@ -11,906 +11,906 @@ chai.use(dirtyChai); const expect = chai.expect; const NULL_ADDRESS = '0x0000000000000000000000000000000000000000'; const { - numberSchema, - addressSchema, - ecSignatureSchema, - ecSignatureParameterSchema, - orderCancellationRequestsSchema, - orderFillOrKillRequestsSchema, - orderFillRequestsSchema, - orderHashSchema, - orderSchema, - signedOrderSchema, - signedOrdersSchema, - blockParamSchema, - blockRangeSchema, - tokenSchema, - jsNumber, - txDataSchema, - relayerApiErrorResponseSchema, - relayerApiOrderBookResponseSchema, - relayerApiTokenPairsResponseSchema, - relayerApiFeesPayloadSchema, - relayerApiFeesResponseSchema, - relayerApiOrderbookChannelSubscribeSchema, - relayerApiOrderbookChannelUpdateSchema, - relayerApiOrderbookChannelSnapshotSchema, + numberSchema, + addressSchema, + ecSignatureSchema, + ecSignatureParameterSchema, + orderCancellationRequestsSchema, + orderFillOrKillRequestsSchema, + orderFillRequestsSchema, + orderHashSchema, + orderSchema, + signedOrderSchema, + signedOrdersSchema, + blockParamSchema, + blockRangeSchema, + tokenSchema, + jsNumber, + txDataSchema, + relayerApiErrorResponseSchema, + relayerApiOrderBookResponseSchema, + relayerApiTokenPairsResponseSchema, + relayerApiFeesPayloadSchema, + relayerApiFeesResponseSchema, + relayerApiOrderbookChannelSubscribeSchema, + relayerApiOrderbookChannelUpdateSchema, + relayerApiOrderbookChannelSnapshotSchema, } = schemas; describe('Schema', () => { - const validator = new SchemaValidator(); - const validateAgainstSchema = (testCases: any[], schema: any, shouldFail = false) => { - forEach(testCases, (testCase: any) => { - const validationResult = validator.validate(testCase, schema); - const hasErrors = validationResult.errors.length !== 0; - if (shouldFail) { - if (!hasErrors) { - throw new Error( - `Expected testCase: ${JSON.stringify(testCase, null, '\t')} to fail and it didn't.`, - ); - } - } else { - if (hasErrors) { - throw new Error(JSON.stringify(validationResult.errors, null, '\t')); - } - } - }); - }; - describe('#numberSchema', () => { - it('should validate valid numbers', () => { - const testCases = ['42', '0', '1.3', '0.2', '00.00']; - validateAgainstSchema(testCases, numberSchema); - }); - it('should fail for invalid numbers', () => { - const testCases = ['.3', '1.', 'abacaba', 'и', '1..0']; - const shouldFail = true; - validateAgainstSchema(testCases, numberSchema, shouldFail); - }); - }); - describe('#addressSchema', () => { - it('should validate valid addresses', () => { - const testCases = ['0x8b0292b11a196601ed2ce54b665cafeca0347d42', NULL_ADDRESS]; - validateAgainstSchema(testCases, addressSchema); - }); - it('should fail for invalid addresses', () => { - const testCases = [ - '0x', - '0', - '0x00', - '0xzzzzzzB11a196601eD2ce54B665CaFEca0347D42', - '0x8b0292B11a196601eD2ce54B665CaFEca0347D42', - ]; - const shouldFail = true; - validateAgainstSchema(testCases, addressSchema, shouldFail); - }); - }); - describe('#ecSignatureParameterSchema', () => { - it('should validate valid parameters', () => { - const testCases = [ - '0x61a3ed31b43c8780e905a260a35faefcc527be7516aa11c0256729b5b351bc33', - '0X40349190569279751135161d22529dc25add4f6069af05be04cacbda2ace2254', - ]; - validateAgainstSchema(testCases, ecSignatureParameterSchema); - }); - it('should fail for invalid parameters', () => { - const testCases = [ - '0x61a3ed31b43c8780e905a260a35faefcc527be7516aa11c0256729b5b351bc3', // shorter - '0xzzzz9190569279751135161d22529dc25add4f6069af05be04cacbda2ace2254', // invalid characters - '40349190569279751135161d22529dc25add4f6069af05be04cacbda2ace2254', // no 0x - ]; - const shouldFail = true; - validateAgainstSchema(testCases, ecSignatureParameterSchema, shouldFail); - }); - }); - describe('#ecSignatureSchema', () => { - it('should validate valid signature', () => { - const signature = { - v: 27, - r: '0x61a3ed31b43c8780e905a260a35faefcc527be7516aa11c0256729b5b351bc33', - s: '0x40349190569279751135161d22529dc25add4f6069af05be04cacbda2ace2254', - }; - const testCases = [ - signature, - { - ...signature, - v: 28, - }, - ]; - validateAgainstSchema(testCases, ecSignatureSchema); - }); - it('should fail for invalid signature', () => { - const v = 27; - const r = '0x61a3ed31b43c8780e905a260a35faefcc527be7516aa11c0256729b5b351bc33'; - const s = '0x40349190569279751135161d22529dc25add4f6069af05be04cacbda2ace2254'; - const testCases = [{}, { v }, { r, s, v: 31 }]; - const shouldFail = true; - validateAgainstSchema(testCases, ecSignatureSchema, shouldFail); - }); - }); - describe('#orderHashSchema', () => { - it('should validate valid order hash', () => { - const testCases = [ - '0x61a3ed31B43c8780e905a260a35faefEc527be7516aa11c0256729b5b351bc33', - '0x40349190569279751135161d22529dc25add4f6069af05be04cacbda2ace2254', - ]; - validateAgainstSchema(testCases, orderHashSchema); - }); - it('should fail for invalid order hash', () => { - const testCases = [ - {}, - '0x', - '0x8b0292B11a196601eD2ce54B665CaFEca0347D42', - '61a3ed31B43c8780e905a260a35faefEc527be7516aa11c0256729b5b351bc33', - ]; - const shouldFail = true; - validateAgainstSchema(testCases, orderHashSchema, shouldFail); - }); - }); - describe('#blockParamSchema', () => { - it('should validate valid block param', () => { - const testCases = [42, 'latest', 'pending', 'earliest']; - validateAgainstSchema(testCases, blockParamSchema); - }); - it('should fail for invalid block param', () => { - const testCases = [{}, '42', 'pemding']; - const shouldFail = true; - validateAgainstSchema(testCases, blockParamSchema, shouldFail); - }); - }); - describe('#blockRangeSchema', () => { - it('should validate valid subscription opts', () => { - const testCases = [{ fromBlock: 42, toBlock: 'latest' }, { fromBlock: 42 }, {}]; - validateAgainstSchema(testCases, blockRangeSchema); - }); - it('should fail for invalid subscription opts', () => { - const testCases = [{ fromBlock: '42' }]; - const shouldFail = true; - validateAgainstSchema(testCases, blockRangeSchema, shouldFail); - }); - }); - describe('#tokenSchema', () => { - const token = { - name: 'Zero Ex', - symbol: 'ZRX', - decimals: 100500, - address: '0x8b0292b11a196601ed2ce54b665cafeca0347d42', - url: 'https://0xproject.com', - }; - it('should validate valid token', () => { - const testCases = [token]; - validateAgainstSchema(testCases, tokenSchema); - }); - it('should fail for invalid token', () => { - const testCases = [ - { - ...token, - address: null, - }, - { - ...token, - decimals: undefined, - }, - [], - 4, - ]; - const shouldFail = true; - validateAgainstSchema(testCases, tokenSchema, shouldFail); - }); - }); - describe('order including schemas', () => { - const order = { - maker: NULL_ADDRESS, - taker: NULL_ADDRESS, - makerFee: '1', - takerFee: '2', - makerTokenAmount: '1', - takerTokenAmount: '2', - makerTokenAddress: NULL_ADDRESS, - takerTokenAddress: NULL_ADDRESS, - salt: '67006738228878699843088602623665307406148487219438534730168799356281242528500', - feeRecipient: NULL_ADDRESS, - exchangeContractAddress: NULL_ADDRESS, - expirationUnixTimestampSec: '42', - }; - describe('#orderSchema', () => { - it('should validate valid order', () => { - const testCases = [order]; - validateAgainstSchema(testCases, orderSchema); - }); - it('should fail for invalid order', () => { - const testCases = [ - { - ...order, - salt: undefined, - }, - { - ...order, - salt: 'salt', - }, - 'order', - ]; - const shouldFail = true; - validateAgainstSchema(testCases, orderSchema, shouldFail); - }); - }); - describe('signed order including schemas', () => { - const signedOrder = { - ...order, - ecSignature: { - v: 27, - r: '0x61a3ed31b43c8780e905a260a35faefcc527be7516aa11c0256729b5b351bc33', - s: '0x40349190569279751135161d22529dc25add4f6069af05be04cacbda2ace2254', - }, - }; - describe('#signedOrdersSchema', () => { - it('should validate valid signed orders', () => { - const testCases = [[signedOrder], []]; - validateAgainstSchema(testCases, signedOrdersSchema); - }); - it('should fail for invalid signed orders', () => { - const testCases = [[signedOrder, 1]]; - const shouldFail = true; - validateAgainstSchema(testCases, signedOrdersSchema, shouldFail); - }); - }); - describe('#signedOrderSchema', () => { - it('should validate valid signed order', () => { - const testCases = [signedOrder]; - validateAgainstSchema(testCases, signedOrderSchema); - }); - it('should fail for invalid signed order', () => { - const testCases = [ - { - ...signedOrder, - ecSignature: undefined, - }, - ]; - const shouldFail = true; - validateAgainstSchema(testCases, signedOrderSchema, shouldFail); - }); - }); - describe('#orderFillOrKillRequestsSchema', () => { - const orderFillOrKillRequests = [ - { - signedOrder, - fillTakerAmount: '5', - }, - ]; - it('should validate valid order fill or kill requests', () => { - const testCases = [orderFillOrKillRequests]; - validateAgainstSchema(testCases, orderFillOrKillRequestsSchema); - }); - it('should fail for invalid order fill or kill requests', () => { - const testCases = [ - [ - { - ...orderFillOrKillRequests[0], - fillTakerAmount: undefined, - }, - ], - ]; - const shouldFail = true; - validateAgainstSchema(testCases, orderFillOrKillRequestsSchema, shouldFail); - }); - }); - describe('#orderCancellationRequestsSchema', () => { - const orderCancellationRequests = [ - { - order, - takerTokenCancelAmount: '5', - }, - ]; - it('should validate valid order cancellation requests', () => { - const testCases = [orderCancellationRequests]; - validateAgainstSchema(testCases, orderCancellationRequestsSchema); - }); - it('should fail for invalid order cancellation requests', () => { - const testCases = [ - [ - { - ...orderCancellationRequests[0], - takerTokenCancelAmount: undefined, - }, - ], - ]; - const shouldFail = true; - validateAgainstSchema(testCases, orderCancellationRequestsSchema, shouldFail); - }); - }); - describe('#orderFillRequestsSchema', () => { - const orderFillRequests = [ - { - signedOrder, - takerTokenFillAmount: '5', - }, - ]; - it('should validate valid order fill requests', () => { - const testCases = [orderFillRequests]; - validateAgainstSchema(testCases, orderFillRequestsSchema); - }); - it('should fail for invalid order fill requests', () => { - const testCases = [ - [ - { - ...orderFillRequests[0], - takerTokenFillAmount: undefined, - }, - ], - ]; - const shouldFail = true; - validateAgainstSchema(testCases, orderFillRequestsSchema, shouldFail); - }); - }); - describe('#relayerApiOrderBookResponseSchema', () => { - it('should validate valid order book responses', () => { - const testCases = [ - { - bids: [], - asks: [], - }, - { - bids: [signedOrder, signedOrder], - asks: [], - }, - { - bids: [], - asks: [signedOrder, signedOrder], - }, - { - bids: [signedOrder], - asks: [signedOrder, signedOrder], - }, - ]; - validateAgainstSchema(testCases, relayerApiOrderBookResponseSchema); - }); - it('should fail for invalid order fill requests', () => { - const testCases = [ - {}, - { - bids: [signedOrder, signedOrder], - }, - { - asks: [signedOrder, signedOrder], - }, - { - bids: signedOrder, - asks: [signedOrder, signedOrder], - }, - { - bids: [signedOrder], - asks: signedOrder, - }, - ]; - const shouldFail = true; - validateAgainstSchema(testCases, relayerApiOrderBookResponseSchema, shouldFail); - }); - }); - describe('#relayerApiOrderbookChannelSubscribeSchema', () => { - it('should validate valid orderbook channel websocket subscribe message', () => { - const testCases = [ - { - type: 'subscribe', - channel: 'orderbook', - requestId: 1, - payload: { - baseTokenAddress: '0x323b5d4c32345ced77393b3530b1eed0f346429d', - quoteTokenAddress: '0x323b5d4c32345ced77393b3530b1eed0f346429d', - snapshot: true, - limit: 100, - }, - }, - { - type: 'subscribe', - channel: 'orderbook', - requestId: 1, - payload: { - baseTokenAddress: '0x323b5d4c32345ced77393b3530b1eed0f346429d', - quoteTokenAddress: '0x323b5d4c32345ced77393b3530b1eed0f346429d', - }, - }, - ]; - validateAgainstSchema(testCases, relayerApiOrderbookChannelSubscribeSchema); - }); - it('should fail for invalid orderbook channel websocket subscribe message', () => { - const checksummedAddress = '0xA2b31daCf30a9C50ca473337c01d8A201ae33e32'; - const testCases = [ - { - type: 'subscribe', - channel: 'orderbook', - payload: { - baseTokenAddress: '0x323b5d4c32345ced77393b3530b1eed0f346429d', - quoteTokenAddress: '0x323b5d4c32345ced77393b3530b1eed0f346429d', - snapshot: true, - limit: 100, - }, - }, - { - type: 'foo', - channel: 'orderbook', - requestId: 1, - payload: { - baseTokenAddress: '0x323b5d4c32345ced77393b3530b1eed0f346429d', - quoteTokenAddress: '0x323b5d4c32345ced77393b3530b1eed0f346429d', - }, - }, - { - type: 'subscribe', - channel: 'bar', - requestId: 1, - payload: { - baseTokenAddress: '0x323b5d4c32345ced77393b3530b1eed0f346429d', - quoteTokenAddress: '0x323b5d4c32345ced77393b3530b1eed0f346429d', - }, - }, - { - type: 'subscribe', - channel: 'orderbook', - requestId: 1, - payload: { - baseTokenAddress: checksummedAddress, - quoteTokenAddress: '0x323b5d4c32345ced77393b3530b1eed0f346429d', - }, - }, - { - type: 'subscribe', - channel: 'orderbook', - requestId: 1, - payload: { - baseTokenAddress: '0x323b5d4c32345ced77393b3530b1eed0f346429d', - quoteTokenAddress: checksummedAddress, - }, - }, - { - type: 'subscribe', - channel: 'orderbook', - requestId: 1, - payload: { - quoteTokenAddress: '0x323b5d4c32345ced77393b3530b1eed0f346429d', - }, - }, - { - type: 'subscribe', - channel: 'orderbook', - requestId: 1, - payload: { - baseTokenAddress: '0x323b5d4c32345ced77393b3530b1eed0f346429d', - }, - }, - { - type: 'subscribe', - channel: 'orderbook', - requestId: 1, - payload: { - baseTokenAddress: '0x323b5d4c32345ced77393b3530b1eed0f346429d', - quoteTokenAddress: '0x323b5d4c32345ced77393b3530b1eed0f346429d', - snapshot: 'true', - limit: 100, - }, - }, - { - type: 'subscribe', - channel: 'orderbook', - requestId: 1, - payload: { - baseTokenAddress: '0x323b5d4c32345ced77393b3530b1eed0f346429d', - quoteTokenAddress: '0x323b5d4c32345ced77393b3530b1eed0f346429d', - snapshot: true, - limit: '100', - }, - }, - ]; - const shouldFail = true; - validateAgainstSchema(testCases, relayerApiOrderbookChannelSubscribeSchema, shouldFail); - }); - }); - describe('#relayerApiOrderbookChannelSnapshotSchema', () => { - it('should validate valid orderbook channel websocket snapshot message', () => { - const testCases = [ - { - type: 'snapshot', - channel: 'orderbook', - requestId: 2, - payload: { - bids: [], - asks: [], - }, - }, - { - type: 'snapshot', - channel: 'orderbook', - requestId: 2, - payload: { - bids: [signedOrder], - asks: [signedOrder], - }, - }, - ]; - validateAgainstSchema(testCases, relayerApiOrderbookChannelSnapshotSchema); - }); - it('should fail for invalid orderbook channel websocket snapshot message', () => { - const testCases = [ - { - type: 'foo', - channel: 'orderbook', - requestId: 2, - payload: { - bids: [signedOrder], - asks: [signedOrder], - }, - }, - { - type: 'snapshot', - channel: 'bar', - requestId: 2, - payload: { - bids: [signedOrder], - asks: [signedOrder], - }, - }, - { - type: 'snapshot', - channel: 'orderbook', - payload: { - bids: [signedOrder], - asks: [signedOrder], - }, - }, - { - type: 'snapshot', - channel: 'orderbook', - requestId: '2', - payload: { - bids: [signedOrder], - asks: [signedOrder], - }, - }, - { - type: 'snapshot', - channel: 'orderbook', - requestId: 2, - payload: { - bids: [signedOrder], - }, - }, - { - type: 'snapshot', - channel: 'orderbook', - requestId: 2, - payload: { - asks: [signedOrder], - }, - }, - { - type: 'snapshot', - channel: 'orderbook', - requestId: 2, - payload: { - bids: [signedOrder], - asks: [{}], - }, - }, - { - type: 'snapshot', - channel: 'orderbook', - requestId: 2, - payload: { - bids: [{}], - asks: [signedOrder], - }, - }, - ]; - const shouldFail = true; - validateAgainstSchema(testCases, relayerApiOrderbookChannelSnapshotSchema, shouldFail); - }); - }); - describe('#relayerApiOrderbookChannelUpdateSchema', () => { - it('should validate valid orderbook channel websocket update message', () => { - const testCases = [ - { - type: 'update', - channel: 'orderbook', - requestId: 2, - payload: signedOrder, - }, - ]; - validateAgainstSchema(testCases, relayerApiOrderbookChannelUpdateSchema); - }); - it('should fail for invalid orderbook channel websocket update message', () => { - const testCases = [ - { - type: 'foo', - channel: 'orderbook', - requestId: 2, - payload: signedOrder, - }, - { - type: 'update', - channel: 'bar', - requestId: 2, - payload: signedOrder, - }, - { - type: 'update', - channel: 'orderbook', - requestId: 2, - payload: {}, - }, - ]; - const shouldFail = true; - validateAgainstSchema(testCases, relayerApiOrderbookChannelUpdateSchema, shouldFail); - }); - }); - }); - }); - describe('BigNumber serialization', () => { - it('should correctly serialize BigNumbers', () => { - const testCases = { - '42': '42', - '0': '0', - '1.3': '1.3', - '0.2': '0.2', - '00.00': '0', - '.3': '0.3', - }; - forEach(testCases, (serialized: string, input: string) => { - expect(JSON.parse(JSON.stringify(new BigNumber(input)))).to.be.equal(serialized); - }); - }); - }); - describe('#relayerApiErrorResponseSchema', () => { - it('should validate valid errorResponse', () => { - const testCases = [ - { - code: 102, - reason: 'Order submission disabled', - }, - { - code: 101, - reason: 'Validation failed', - validationErrors: [ - { - field: 'maker', - code: 1002, - reason: 'Invalid address', - }, - ], - }, - ]; - validateAgainstSchema(testCases, relayerApiErrorResponseSchema); - }); - it('should fail for invalid error responses', () => { - const testCases = [ - {}, - { - code: 102, - }, - { - code: '102', - reason: 'Order submission disabled', - }, - { - reason: 'Order submission disabled', - }, - { - code: 101, - reason: 'Validation failed', - validationErrors: [ - { - field: 'maker', - reason: 'Invalid address', - }, - ], - }, - { - code: 101, - reason: 'Validation failed', - validationErrors: [ - { - field: 'maker', - code: '1002', - reason: 'Invalid address', - }, - ], - }, - ]; - const shouldFail = true; - validateAgainstSchema(testCases, relayerApiErrorResponseSchema, shouldFail); - }); - }); - describe('#relayerApiFeesPayloadSchema', () => { - it('should validate valid fees payloads', () => { - const testCases = [ - { - exchangeContractAddress: '0x323b5d4c32345ced77393b3530b1eed0f346429d', - maker: '0x323b5d4c32345ced77393b3530b1eed0f346429d', - taker: '0x323b5d4c32345ced77393b3530b1eed0f346429d', - makerTokenAddress: '0x323b5d4c32345ced77393b3530b1eed0f346429d', - takerTokenAddress: '0xef7fff64389b814a946f3e92105513705ca6b990', - makerTokenAmount: '10000000000000000000', - takerTokenAmount: '30000000000000000000', - expirationUnixTimestampSec: '42', - salt: '67006738228878699843088602623665307406148487219438534730168799356281242528500', - }, - ]; - validateAgainstSchema(testCases, relayerApiFeesPayloadSchema); - }); - it('should fail for invalid fees payloads', () => { - const checksummedAddress = '0xA2b31daCf30a9C50ca473337c01d8A201ae33e32'; - const testCases = [ - {}, - { - takerTokenAddress: '0xef7fff64389b814a946f3e92105513705ca6b990', - makerTokenAmount: '10000000000000000000', - takerTokenAmount: '30000000000000000000', - }, - { - taker: checksummedAddress, - makerTokenAddress: '0x323b5d4c32345ced77393b3530b1eed0f346429d', - takerTokenAddress: '0xef7fff64389b814a946f3e92105513705ca6b990', - makerTokenAmount: '10000000000000000000', - takerTokenAmount: '30000000000000000000', - }, - { - makerTokenAddress: '0x323b5d4c32345ced77393b3530b1eed0f346429d', - takerTokenAddress: '0xef7fff64389b814a946f3e92105513705ca6b990', - makerTokenAmount: 10000000000000000000, - takerTokenAmount: 30000000000000000000, - }, - ]; - const shouldFail = true; - validateAgainstSchema(testCases, relayerApiFeesPayloadSchema, shouldFail); - }); - }); - describe('#relayerApiFeesResponseSchema', () => { - it('should validate valid fees responses', () => { - const testCases = [ - { - makerFee: '10000000000000000', - takerFee: '30000000000000000', - feeRecipient: '0x323b5d4c32345ced77393b3530b1eed0f346429d', - }, - ]; - validateAgainstSchema(testCases, relayerApiFeesResponseSchema); - }); - it('should fail for invalid fees responses', () => { - const checksummedAddress = '0xA2b31daCf30a9C50ca473337c01d8A201ae33e32'; - const testCases = [ - {}, - { - makerFee: 10000000000000000, - takerFee: 30000000000000000, - }, - { - feeRecipient: checksummedAddress, - takerToSpecify: checksummedAddress, - makerFee: '10000000000000000', - takerFee: '30000000000000000', - }, - ]; - const shouldFail = true; - validateAgainstSchema(testCases, relayerApiFeesResponseSchema, shouldFail); - }); - }); - describe('#relayerApiTokenPairsResponseSchema', () => { - it('should validate valid tokenPairs response', () => { - const testCases = [ - [], - [ - { - tokenA: { - address: '0x323b5d4c32345ced77393b3530b1eed0f346429d', - minAmount: '0', - maxAmount: '10000000000000000000', - precision: 5, - }, - tokenB: { - address: '0xef7fff64389b814a946f3e92105513705ca6b990', - minAmount: '0', - maxAmount: '50000000000000000000', - precision: 5, - }, - }, - ], - [ - { - tokenA: { - address: '0x323b5d4c32345ced77393b3530b1eed0f346429d', - }, - tokenB: { - address: '0xef7fff64389b814a946f3e92105513705ca6b990', - }, - }, - ], - ]; - validateAgainstSchema(testCases, relayerApiTokenPairsResponseSchema); - }); - it('should fail for invalid tokenPairs responses', () => { - const checksummedAddress = '0xA2b31daCf30a9C50ca473337c01d8A201ae33e32'; - const testCases = [ - [ - { - tokenA: { - address: checksummedAddress, - }, - tokenB: { - address: checksummedAddress, - }, - }, - ], - [ - { - tokenA: { - address: '0x323b5d4c32345ced77393b3530b1eed0f346429d', - minAmount: 0, - maxAmount: 10000000000000000000, - }, - tokenB: { - address: '0xef7fff64389b814a946f3e92105513705ca6b990', - minAmount: 0, - maxAmount: 50000000000000000000, - }, - }, - ], - [ - { - tokenA: { - address: '0x323b5d4c32345ced77393b3530b1eed0f346429d', - precision: '5', - }, - tokenB: { - address: '0xef7fff64389b814a946f3e92105513705ca6b990', - precision: '5', - }, - }, - ], - ]; - const shouldFail = true; - validateAgainstSchema(testCases, relayerApiTokenPairsResponseSchema, shouldFail); - }); - }); - describe('#jsNumberSchema', () => { - it('should validate valid js number', () => { - const testCases = [1, 42]; - validateAgainstSchema(testCases, jsNumber); - }); - it('should fail for invalid js number', () => { - const testCases = [NaN, -1, new BigNumber(1)]; - const shouldFail = true; - validateAgainstSchema(testCases, jsNumber, shouldFail); - }); - }); - describe('#txDataSchema', () => { - it('should validate valid txData', () => { - const testCases = [ - { - from: NULL_ADDRESS, - }, - { - from: NULL_ADDRESS, - gas: new BigNumber(42), - }, - { - from: NULL_ADDRESS, - gas: 42, - }, - ]; - validateAgainstSchema(testCases, txDataSchema); - }); - it('should fail for invalid txData', () => { - const testCases = [ - { - gas: new BigNumber(42), - }, - { - from: NULL_ADDRESS, - unknownProp: 'here', - }, - {}, - [], - new BigNumber(1), - ]; - const shouldFail = true; - validateAgainstSchema(testCases, txDataSchema, shouldFail); - }); - }); + const validator = new SchemaValidator(); + const validateAgainstSchema = (testCases: any[], schema: any, shouldFail = false) => { + forEach(testCases, (testCase: any) => { + const validationResult = validator.validate(testCase, schema); + const hasErrors = validationResult.errors.length !== 0; + if (shouldFail) { + if (!hasErrors) { + throw new Error( + `Expected testCase: ${JSON.stringify(testCase, null, '\t')} to fail and it didn't.`, + ); + } + } else { + if (hasErrors) { + throw new Error(JSON.stringify(validationResult.errors, null, '\t')); + } + } + }); + }; + describe('#numberSchema', () => { + it('should validate valid numbers', () => { + const testCases = ['42', '0', '1.3', '0.2', '00.00']; + validateAgainstSchema(testCases, numberSchema); + }); + it('should fail for invalid numbers', () => { + const testCases = ['.3', '1.', 'abacaba', 'и', '1..0']; + const shouldFail = true; + validateAgainstSchema(testCases, numberSchema, shouldFail); + }); + }); + describe('#addressSchema', () => { + it('should validate valid addresses', () => { + const testCases = ['0x8b0292b11a196601ed2ce54b665cafeca0347d42', NULL_ADDRESS]; + validateAgainstSchema(testCases, addressSchema); + }); + it('should fail for invalid addresses', () => { + const testCases = [ + '0x', + '0', + '0x00', + '0xzzzzzzB11a196601eD2ce54B665CaFEca0347D42', + '0x8b0292B11a196601eD2ce54B665CaFEca0347D42', + ]; + const shouldFail = true; + validateAgainstSchema(testCases, addressSchema, shouldFail); + }); + }); + describe('#ecSignatureParameterSchema', () => { + it('should validate valid parameters', () => { + const testCases = [ + '0x61a3ed31b43c8780e905a260a35faefcc527be7516aa11c0256729b5b351bc33', + '0X40349190569279751135161d22529dc25add4f6069af05be04cacbda2ace2254', + ]; + validateAgainstSchema(testCases, ecSignatureParameterSchema); + }); + it('should fail for invalid parameters', () => { + const testCases = [ + '0x61a3ed31b43c8780e905a260a35faefcc527be7516aa11c0256729b5b351bc3', // shorter + '0xzzzz9190569279751135161d22529dc25add4f6069af05be04cacbda2ace2254', // invalid characters + '40349190569279751135161d22529dc25add4f6069af05be04cacbda2ace2254', // no 0x + ]; + const shouldFail = true; + validateAgainstSchema(testCases, ecSignatureParameterSchema, shouldFail); + }); + }); + describe('#ecSignatureSchema', () => { + it('should validate valid signature', () => { + const signature = { + v: 27, + r: '0x61a3ed31b43c8780e905a260a35faefcc527be7516aa11c0256729b5b351bc33', + s: '0x40349190569279751135161d22529dc25add4f6069af05be04cacbda2ace2254', + }; + const testCases = [ + signature, + { + ...signature, + v: 28, + }, + ]; + validateAgainstSchema(testCases, ecSignatureSchema); + }); + it('should fail for invalid signature', () => { + const v = 27; + const r = '0x61a3ed31b43c8780e905a260a35faefcc527be7516aa11c0256729b5b351bc33'; + const s = '0x40349190569279751135161d22529dc25add4f6069af05be04cacbda2ace2254'; + const testCases = [{}, { v }, { r, s, v: 31 }]; + const shouldFail = true; + validateAgainstSchema(testCases, ecSignatureSchema, shouldFail); + }); + }); + describe('#orderHashSchema', () => { + it('should validate valid order hash', () => { + const testCases = [ + '0x61a3ed31B43c8780e905a260a35faefEc527be7516aa11c0256729b5b351bc33', + '0x40349190569279751135161d22529dc25add4f6069af05be04cacbda2ace2254', + ]; + validateAgainstSchema(testCases, orderHashSchema); + }); + it('should fail for invalid order hash', () => { + const testCases = [ + {}, + '0x', + '0x8b0292B11a196601eD2ce54B665CaFEca0347D42', + '61a3ed31B43c8780e905a260a35faefEc527be7516aa11c0256729b5b351bc33', + ]; + const shouldFail = true; + validateAgainstSchema(testCases, orderHashSchema, shouldFail); + }); + }); + describe('#blockParamSchema', () => { + it('should validate valid block param', () => { + const testCases = [42, 'latest', 'pending', 'earliest']; + validateAgainstSchema(testCases, blockParamSchema); + }); + it('should fail for invalid block param', () => { + const testCases = [{}, '42', 'pemding']; + const shouldFail = true; + validateAgainstSchema(testCases, blockParamSchema, shouldFail); + }); + }); + describe('#blockRangeSchema', () => { + it('should validate valid subscription opts', () => { + const testCases = [{ fromBlock: 42, toBlock: 'latest' }, { fromBlock: 42 }, {}]; + validateAgainstSchema(testCases, blockRangeSchema); + }); + it('should fail for invalid subscription opts', () => { + const testCases = [{ fromBlock: '42' }]; + const shouldFail = true; + validateAgainstSchema(testCases, blockRangeSchema, shouldFail); + }); + }); + describe('#tokenSchema', () => { + const token = { + name: 'Zero Ex', + symbol: 'ZRX', + decimals: 100500, + address: '0x8b0292b11a196601ed2ce54b665cafeca0347d42', + url: 'https://0xproject.com', + }; + it('should validate valid token', () => { + const testCases = [token]; + validateAgainstSchema(testCases, tokenSchema); + }); + it('should fail for invalid token', () => { + const testCases = [ + { + ...token, + address: null, + }, + { + ...token, + decimals: undefined, + }, + [], + 4, + ]; + const shouldFail = true; + validateAgainstSchema(testCases, tokenSchema, shouldFail); + }); + }); + describe('order including schemas', () => { + const order = { + maker: NULL_ADDRESS, + taker: NULL_ADDRESS, + makerFee: '1', + takerFee: '2', + makerTokenAmount: '1', + takerTokenAmount: '2', + makerTokenAddress: NULL_ADDRESS, + takerTokenAddress: NULL_ADDRESS, + salt: '67006738228878699843088602623665307406148487219438534730168799356281242528500', + feeRecipient: NULL_ADDRESS, + exchangeContractAddress: NULL_ADDRESS, + expirationUnixTimestampSec: '42', + }; + describe('#orderSchema', () => { + it('should validate valid order', () => { + const testCases = [order]; + validateAgainstSchema(testCases, orderSchema); + }); + it('should fail for invalid order', () => { + const testCases = [ + { + ...order, + salt: undefined, + }, + { + ...order, + salt: 'salt', + }, + 'order', + ]; + const shouldFail = true; + validateAgainstSchema(testCases, orderSchema, shouldFail); + }); + }); + describe('signed order including schemas', () => { + const signedOrder = { + ...order, + ecSignature: { + v: 27, + r: '0x61a3ed31b43c8780e905a260a35faefcc527be7516aa11c0256729b5b351bc33', + s: '0x40349190569279751135161d22529dc25add4f6069af05be04cacbda2ace2254', + }, + }; + describe('#signedOrdersSchema', () => { + it('should validate valid signed orders', () => { + const testCases = [[signedOrder], []]; + validateAgainstSchema(testCases, signedOrdersSchema); + }); + it('should fail for invalid signed orders', () => { + const testCases = [[signedOrder, 1]]; + const shouldFail = true; + validateAgainstSchema(testCases, signedOrdersSchema, shouldFail); + }); + }); + describe('#signedOrderSchema', () => { + it('should validate valid signed order', () => { + const testCases = [signedOrder]; + validateAgainstSchema(testCases, signedOrderSchema); + }); + it('should fail for invalid signed order', () => { + const testCases = [ + { + ...signedOrder, + ecSignature: undefined, + }, + ]; + const shouldFail = true; + validateAgainstSchema(testCases, signedOrderSchema, shouldFail); + }); + }); + describe('#orderFillOrKillRequestsSchema', () => { + const orderFillOrKillRequests = [ + { + signedOrder, + fillTakerAmount: '5', + }, + ]; + it('should validate valid order fill or kill requests', () => { + const testCases = [orderFillOrKillRequests]; + validateAgainstSchema(testCases, orderFillOrKillRequestsSchema); + }); + it('should fail for invalid order fill or kill requests', () => { + const testCases = [ + [ + { + ...orderFillOrKillRequests[0], + fillTakerAmount: undefined, + }, + ], + ]; + const shouldFail = true; + validateAgainstSchema(testCases, orderFillOrKillRequestsSchema, shouldFail); + }); + }); + describe('#orderCancellationRequestsSchema', () => { + const orderCancellationRequests = [ + { + order, + takerTokenCancelAmount: '5', + }, + ]; + it('should validate valid order cancellation requests', () => { + const testCases = [orderCancellationRequests]; + validateAgainstSchema(testCases, orderCancellationRequestsSchema); + }); + it('should fail for invalid order cancellation requests', () => { + const testCases = [ + [ + { + ...orderCancellationRequests[0], + takerTokenCancelAmount: undefined, + }, + ], + ]; + const shouldFail = true; + validateAgainstSchema(testCases, orderCancellationRequestsSchema, shouldFail); + }); + }); + describe('#orderFillRequestsSchema', () => { + const orderFillRequests = [ + { + signedOrder, + takerTokenFillAmount: '5', + }, + ]; + it('should validate valid order fill requests', () => { + const testCases = [orderFillRequests]; + validateAgainstSchema(testCases, orderFillRequestsSchema); + }); + it('should fail for invalid order fill requests', () => { + const testCases = [ + [ + { + ...orderFillRequests[0], + takerTokenFillAmount: undefined, + }, + ], + ]; + const shouldFail = true; + validateAgainstSchema(testCases, orderFillRequestsSchema, shouldFail); + }); + }); + describe('#relayerApiOrderBookResponseSchema', () => { + it('should validate valid order book responses', () => { + const testCases = [ + { + bids: [], + asks: [], + }, + { + bids: [signedOrder, signedOrder], + asks: [], + }, + { + bids: [], + asks: [signedOrder, signedOrder], + }, + { + bids: [signedOrder], + asks: [signedOrder, signedOrder], + }, + ]; + validateAgainstSchema(testCases, relayerApiOrderBookResponseSchema); + }); + it('should fail for invalid order fill requests', () => { + const testCases = [ + {}, + { + bids: [signedOrder, signedOrder], + }, + { + asks: [signedOrder, signedOrder], + }, + { + bids: signedOrder, + asks: [signedOrder, signedOrder], + }, + { + bids: [signedOrder], + asks: signedOrder, + }, + ]; + const shouldFail = true; + validateAgainstSchema(testCases, relayerApiOrderBookResponseSchema, shouldFail); + }); + }); + describe('#relayerApiOrderbookChannelSubscribeSchema', () => { + it('should validate valid orderbook channel websocket subscribe message', () => { + const testCases = [ + { + type: 'subscribe', + channel: 'orderbook', + requestId: 1, + payload: { + baseTokenAddress: '0x323b5d4c32345ced77393b3530b1eed0f346429d', + quoteTokenAddress: '0x323b5d4c32345ced77393b3530b1eed0f346429d', + snapshot: true, + limit: 100, + }, + }, + { + type: 'subscribe', + channel: 'orderbook', + requestId: 1, + payload: { + baseTokenAddress: '0x323b5d4c32345ced77393b3530b1eed0f346429d', + quoteTokenAddress: '0x323b5d4c32345ced77393b3530b1eed0f346429d', + }, + }, + ]; + validateAgainstSchema(testCases, relayerApiOrderbookChannelSubscribeSchema); + }); + it('should fail for invalid orderbook channel websocket subscribe message', () => { + const checksummedAddress = '0xA2b31daCf30a9C50ca473337c01d8A201ae33e32'; + const testCases = [ + { + type: 'subscribe', + channel: 'orderbook', + payload: { + baseTokenAddress: '0x323b5d4c32345ced77393b3530b1eed0f346429d', + quoteTokenAddress: '0x323b5d4c32345ced77393b3530b1eed0f346429d', + snapshot: true, + limit: 100, + }, + }, + { + type: 'foo', + channel: 'orderbook', + requestId: 1, + payload: { + baseTokenAddress: '0x323b5d4c32345ced77393b3530b1eed0f346429d', + quoteTokenAddress: '0x323b5d4c32345ced77393b3530b1eed0f346429d', + }, + }, + { + type: 'subscribe', + channel: 'bar', + requestId: 1, + payload: { + baseTokenAddress: '0x323b5d4c32345ced77393b3530b1eed0f346429d', + quoteTokenAddress: '0x323b5d4c32345ced77393b3530b1eed0f346429d', + }, + }, + { + type: 'subscribe', + channel: 'orderbook', + requestId: 1, + payload: { + baseTokenAddress: checksummedAddress, + quoteTokenAddress: '0x323b5d4c32345ced77393b3530b1eed0f346429d', + }, + }, + { + type: 'subscribe', + channel: 'orderbook', + requestId: 1, + payload: { + baseTokenAddress: '0x323b5d4c32345ced77393b3530b1eed0f346429d', + quoteTokenAddress: checksummedAddress, + }, + }, + { + type: 'subscribe', + channel: 'orderbook', + requestId: 1, + payload: { + quoteTokenAddress: '0x323b5d4c32345ced77393b3530b1eed0f346429d', + }, + }, + { + type: 'subscribe', + channel: 'orderbook', + requestId: 1, + payload: { + baseTokenAddress: '0x323b5d4c32345ced77393b3530b1eed0f346429d', + }, + }, + { + type: 'subscribe', + channel: 'orderbook', + requestId: 1, + payload: { + baseTokenAddress: '0x323b5d4c32345ced77393b3530b1eed0f346429d', + quoteTokenAddress: '0x323b5d4c32345ced77393b3530b1eed0f346429d', + snapshot: 'true', + limit: 100, + }, + }, + { + type: 'subscribe', + channel: 'orderbook', + requestId: 1, + payload: { + baseTokenAddress: '0x323b5d4c32345ced77393b3530b1eed0f346429d', + quoteTokenAddress: '0x323b5d4c32345ced77393b3530b1eed0f346429d', + snapshot: true, + limit: '100', + }, + }, + ]; + const shouldFail = true; + validateAgainstSchema(testCases, relayerApiOrderbookChannelSubscribeSchema, shouldFail); + }); + }); + describe('#relayerApiOrderbookChannelSnapshotSchema', () => { + it('should validate valid orderbook channel websocket snapshot message', () => { + const testCases = [ + { + type: 'snapshot', + channel: 'orderbook', + requestId: 2, + payload: { + bids: [], + asks: [], + }, + }, + { + type: 'snapshot', + channel: 'orderbook', + requestId: 2, + payload: { + bids: [signedOrder], + asks: [signedOrder], + }, + }, + ]; + validateAgainstSchema(testCases, relayerApiOrderbookChannelSnapshotSchema); + }); + it('should fail for invalid orderbook channel websocket snapshot message', () => { + const testCases = [ + { + type: 'foo', + channel: 'orderbook', + requestId: 2, + payload: { + bids: [signedOrder], + asks: [signedOrder], + }, + }, + { + type: 'snapshot', + channel: 'bar', + requestId: 2, + payload: { + bids: [signedOrder], + asks: [signedOrder], + }, + }, + { + type: 'snapshot', + channel: 'orderbook', + payload: { + bids: [signedOrder], + asks: [signedOrder], + }, + }, + { + type: 'snapshot', + channel: 'orderbook', + requestId: '2', + payload: { + bids: [signedOrder], + asks: [signedOrder], + }, + }, + { + type: 'snapshot', + channel: 'orderbook', + requestId: 2, + payload: { + bids: [signedOrder], + }, + }, + { + type: 'snapshot', + channel: 'orderbook', + requestId: 2, + payload: { + asks: [signedOrder], + }, + }, + { + type: 'snapshot', + channel: 'orderbook', + requestId: 2, + payload: { + bids: [signedOrder], + asks: [{}], + }, + }, + { + type: 'snapshot', + channel: 'orderbook', + requestId: 2, + payload: { + bids: [{}], + asks: [signedOrder], + }, + }, + ]; + const shouldFail = true; + validateAgainstSchema(testCases, relayerApiOrderbookChannelSnapshotSchema, shouldFail); + }); + }); + describe('#relayerApiOrderbookChannelUpdateSchema', () => { + it('should validate valid orderbook channel websocket update message', () => { + const testCases = [ + { + type: 'update', + channel: 'orderbook', + requestId: 2, + payload: signedOrder, + }, + ]; + validateAgainstSchema(testCases, relayerApiOrderbookChannelUpdateSchema); + }); + it('should fail for invalid orderbook channel websocket update message', () => { + const testCases = [ + { + type: 'foo', + channel: 'orderbook', + requestId: 2, + payload: signedOrder, + }, + { + type: 'update', + channel: 'bar', + requestId: 2, + payload: signedOrder, + }, + { + type: 'update', + channel: 'orderbook', + requestId: 2, + payload: {}, + }, + ]; + const shouldFail = true; + validateAgainstSchema(testCases, relayerApiOrderbookChannelUpdateSchema, shouldFail); + }); + }); + }); + }); + describe('BigNumber serialization', () => { + it('should correctly serialize BigNumbers', () => { + const testCases = { + '42': '42', + '0': '0', + '1.3': '1.3', + '0.2': '0.2', + '00.00': '0', + '.3': '0.3', + }; + forEach(testCases, (serialized: string, input: string) => { + expect(JSON.parse(JSON.stringify(new BigNumber(input)))).to.be.equal(serialized); + }); + }); + }); + describe('#relayerApiErrorResponseSchema', () => { + it('should validate valid errorResponse', () => { + const testCases = [ + { + code: 102, + reason: 'Order submission disabled', + }, + { + code: 101, + reason: 'Validation failed', + validationErrors: [ + { + field: 'maker', + code: 1002, + reason: 'Invalid address', + }, + ], + }, + ]; + validateAgainstSchema(testCases, relayerApiErrorResponseSchema); + }); + it('should fail for invalid error responses', () => { + const testCases = [ + {}, + { + code: 102, + }, + { + code: '102', + reason: 'Order submission disabled', + }, + { + reason: 'Order submission disabled', + }, + { + code: 101, + reason: 'Validation failed', + validationErrors: [ + { + field: 'maker', + reason: 'Invalid address', + }, + ], + }, + { + code: 101, + reason: 'Validation failed', + validationErrors: [ + { + field: 'maker', + code: '1002', + reason: 'Invalid address', + }, + ], + }, + ]; + const shouldFail = true; + validateAgainstSchema(testCases, relayerApiErrorResponseSchema, shouldFail); + }); + }); + describe('#relayerApiFeesPayloadSchema', () => { + it('should validate valid fees payloads', () => { + const testCases = [ + { + exchangeContractAddress: '0x323b5d4c32345ced77393b3530b1eed0f346429d', + maker: '0x323b5d4c32345ced77393b3530b1eed0f346429d', + taker: '0x323b5d4c32345ced77393b3530b1eed0f346429d', + makerTokenAddress: '0x323b5d4c32345ced77393b3530b1eed0f346429d', + takerTokenAddress: '0xef7fff64389b814a946f3e92105513705ca6b990', + makerTokenAmount: '10000000000000000000', + takerTokenAmount: '30000000000000000000', + expirationUnixTimestampSec: '42', + salt: '67006738228878699843088602623665307406148487219438534730168799356281242528500', + }, + ]; + validateAgainstSchema(testCases, relayerApiFeesPayloadSchema); + }); + it('should fail for invalid fees payloads', () => { + const checksummedAddress = '0xA2b31daCf30a9C50ca473337c01d8A201ae33e32'; + const testCases = [ + {}, + { + takerTokenAddress: '0xef7fff64389b814a946f3e92105513705ca6b990', + makerTokenAmount: '10000000000000000000', + takerTokenAmount: '30000000000000000000', + }, + { + taker: checksummedAddress, + makerTokenAddress: '0x323b5d4c32345ced77393b3530b1eed0f346429d', + takerTokenAddress: '0xef7fff64389b814a946f3e92105513705ca6b990', + makerTokenAmount: '10000000000000000000', + takerTokenAmount: '30000000000000000000', + }, + { + makerTokenAddress: '0x323b5d4c32345ced77393b3530b1eed0f346429d', + takerTokenAddress: '0xef7fff64389b814a946f3e92105513705ca6b990', + makerTokenAmount: 10000000000000000000, + takerTokenAmount: 30000000000000000000, + }, + ]; + const shouldFail = true; + validateAgainstSchema(testCases, relayerApiFeesPayloadSchema, shouldFail); + }); + }); + describe('#relayerApiFeesResponseSchema', () => { + it('should validate valid fees responses', () => { + const testCases = [ + { + makerFee: '10000000000000000', + takerFee: '30000000000000000', + feeRecipient: '0x323b5d4c32345ced77393b3530b1eed0f346429d', + }, + ]; + validateAgainstSchema(testCases, relayerApiFeesResponseSchema); + }); + it('should fail for invalid fees responses', () => { + const checksummedAddress = '0xA2b31daCf30a9C50ca473337c01d8A201ae33e32'; + const testCases = [ + {}, + { + makerFee: 10000000000000000, + takerFee: 30000000000000000, + }, + { + feeRecipient: checksummedAddress, + takerToSpecify: checksummedAddress, + makerFee: '10000000000000000', + takerFee: '30000000000000000', + }, + ]; + const shouldFail = true; + validateAgainstSchema(testCases, relayerApiFeesResponseSchema, shouldFail); + }); + }); + describe('#relayerApiTokenPairsResponseSchema', () => { + it('should validate valid tokenPairs response', () => { + const testCases = [ + [], + [ + { + tokenA: { + address: '0x323b5d4c32345ced77393b3530b1eed0f346429d', + minAmount: '0', + maxAmount: '10000000000000000000', + precision: 5, + }, + tokenB: { + address: '0xef7fff64389b814a946f3e92105513705ca6b990', + minAmount: '0', + maxAmount: '50000000000000000000', + precision: 5, + }, + }, + ], + [ + { + tokenA: { + address: '0x323b5d4c32345ced77393b3530b1eed0f346429d', + }, + tokenB: { + address: '0xef7fff64389b814a946f3e92105513705ca6b990', + }, + }, + ], + ]; + validateAgainstSchema(testCases, relayerApiTokenPairsResponseSchema); + }); + it('should fail for invalid tokenPairs responses', () => { + const checksummedAddress = '0xA2b31daCf30a9C50ca473337c01d8A201ae33e32'; + const testCases = [ + [ + { + tokenA: { + address: checksummedAddress, + }, + tokenB: { + address: checksummedAddress, + }, + }, + ], + [ + { + tokenA: { + address: '0x323b5d4c32345ced77393b3530b1eed0f346429d', + minAmount: 0, + maxAmount: 10000000000000000000, + }, + tokenB: { + address: '0xef7fff64389b814a946f3e92105513705ca6b990', + minAmount: 0, + maxAmount: 50000000000000000000, + }, + }, + ], + [ + { + tokenA: { + address: '0x323b5d4c32345ced77393b3530b1eed0f346429d', + precision: '5', + }, + tokenB: { + address: '0xef7fff64389b814a946f3e92105513705ca6b990', + precision: '5', + }, + }, + ], + ]; + const shouldFail = true; + validateAgainstSchema(testCases, relayerApiTokenPairsResponseSchema, shouldFail); + }); + }); + describe('#jsNumberSchema', () => { + it('should validate valid js number', () => { + const testCases = [1, 42]; + validateAgainstSchema(testCases, jsNumber); + }); + it('should fail for invalid js number', () => { + const testCases = [NaN, -1, new BigNumber(1)]; + const shouldFail = true; + validateAgainstSchema(testCases, jsNumber, shouldFail); + }); + }); + describe('#txDataSchema', () => { + it('should validate valid txData', () => { + const testCases = [ + { + from: NULL_ADDRESS, + }, + { + from: NULL_ADDRESS, + gas: new BigNumber(42), + }, + { + from: NULL_ADDRESS, + gas: 42, + }, + ]; + validateAgainstSchema(testCases, txDataSchema); + }); + it('should fail for invalid txData', () => { + const testCases = [ + { + gas: new BigNumber(42), + }, + { + from: NULL_ADDRESS, + unknownProp: 'here', + }, + {}, + [], + new BigNumber(1), + ]; + const shouldFail = true; + validateAgainstSchema(testCases, txDataSchema, shouldFail); + }); + }); }); // tslint:disable:max-file-line-count diff --git a/packages/json-schemas/tsconfig.json b/packages/json-schemas/tsconfig.json index 8314a9459..88a467ccb 100644 --- a/packages/json-schemas/tsconfig.json +++ b/packages/json-schemas/tsconfig.json @@ -1,7 +1,7 @@ { - "extends": "../../tsconfig", - "compilerOptions": { - "outDir": "lib" - }, - "include": ["./src/**/*", "./test/**/*", "../../node_modules/chai-typescript-typings/index.d.ts"] + "extends": "../../tsconfig", + "compilerOptions": { + "outDir": "lib" + }, + "include": ["./src/**/*", "./test/**/*", "../../node_modules/chai-typescript-typings/index.d.ts"] } diff --git a/packages/json-schemas/tslint.json b/packages/json-schemas/tslint.json index e63054bfc..ffaefe83a 100644 --- a/packages/json-schemas/tslint.json +++ b/packages/json-schemas/tslint.json @@ -1,3 +1,3 @@ { - "extends": ["@0xproject/tslint-config"] + "extends": ["@0xproject/tslint-config"] } |