merge development
This commit is contained in:
commit
61255309d2
@ -1,4 +1,13 @@
|
|||||||
[
|
[
|
||||||
|
{
|
||||||
|
"version": "2.0.0-rc.1",
|
||||||
|
"changes": [
|
||||||
|
{
|
||||||
|
"note": "Updated for SRA v2",
|
||||||
|
"pr": 974
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"timestamp": 1534210131,
|
"timestamp": 1534210131,
|
||||||
"version": "2.0.0",
|
"version": "2.0.0",
|
||||||
|
@ -44,14 +44,15 @@
|
|||||||
},
|
},
|
||||||
"homepage": "https://github.com/0xProject/0x-monorepo/packages/connect/README.md",
|
"homepage": "https://github.com/0xProject/0x-monorepo/packages/connect/README.md",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@0xproject/assert": "^0.2.14",
|
"@0xproject/assert": "^1.0.5",
|
||||||
"@0xproject/json-schemas": "^0.8.3",
|
"@0xproject/json-schemas": "^1.0.1-rc.4",
|
||||||
"@0xproject/types": "^0.8.2",
|
"@0xproject/types": "^1.0.1-rc.4",
|
||||||
"@0xproject/typescript-typings": "^1.0.4",
|
"@0xproject/typescript-typings": "^1.0.4",
|
||||||
"@0xproject/utils": "^1.0.5",
|
"@0xproject/utils": "^1.0.5",
|
||||||
"lodash": "^4.17.5",
|
"lodash": "^4.17.5",
|
||||||
"query-string": "^5.0.1",
|
"query-string": "^5.0.1",
|
||||||
"sinon": "^4.0.0",
|
"sinon": "^4.0.0",
|
||||||
|
"uuid": "^3.3.2",
|
||||||
"websocket": "^1.0.25"
|
"websocket": "^1.0.25"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
@ -61,6 +62,7 @@
|
|||||||
"@types/mocha": "^2.2.42",
|
"@types/mocha": "^2.2.42",
|
||||||
"@types/query-string": "^5.0.1",
|
"@types/query-string": "^5.0.1",
|
||||||
"@types/sinon": "^2.2.2",
|
"@types/sinon": "^2.2.2",
|
||||||
|
"@types/uuid": "^3.4.3",
|
||||||
"@types/websocket": "^0.0.39",
|
"@types/websocket": "^0.0.39",
|
||||||
"async-child-process": "^1.1.1",
|
"async-child-process": "^1.1.1",
|
||||||
"chai": "^4.0.1",
|
"chai": "^4.0.1",
|
||||||
|
@ -7,31 +7,25 @@ import * as queryString from 'query-string';
|
|||||||
|
|
||||||
import { schemas as clientSchemas } from './schemas/schemas';
|
import { schemas as clientSchemas } from './schemas/schemas';
|
||||||
import {
|
import {
|
||||||
|
APIOrder,
|
||||||
|
AssetPairsRequestOpts,
|
||||||
|
AssetPairsResponse,
|
||||||
Client,
|
Client,
|
||||||
FeesRequest,
|
FeeRecipientsResponse,
|
||||||
FeesResponse,
|
|
||||||
HttpRequestOptions,
|
HttpRequestOptions,
|
||||||
HttpRequestType,
|
HttpRequestType,
|
||||||
OrderbookRequest,
|
OrderbookRequest,
|
||||||
OrderbookResponse,
|
OrderbookResponse,
|
||||||
|
OrderConfigRequest,
|
||||||
|
OrderConfigResponse,
|
||||||
OrdersRequestOpts,
|
OrdersRequestOpts,
|
||||||
|
OrdersResponse,
|
||||||
PagedRequestOpts,
|
PagedRequestOpts,
|
||||||
TokenPairsItem,
|
RequestOpts,
|
||||||
TokenPairsRequestOpts,
|
|
||||||
} from './types';
|
} from './types';
|
||||||
import { relayerResponseJsonParsers } from './utils/relayer_response_json_parsers';
|
import { relayerResponseJsonParsers } from './utils/relayer_response_json_parsers';
|
||||||
|
|
||||||
const TRAILING_SLASHES_REGEX = /\/+$/;
|
const TRAILING_SLASHES_REGEX = /\/+$/;
|
||||||
const DEFAULT_PAGED_REQUEST_OPTS: PagedRequestOpts = {
|
|
||||||
page: 1,
|
|
||||||
perPage: 100,
|
|
||||||
};
|
|
||||||
/**
|
|
||||||
* This mapping defines how an option property name gets converted into an HTTP request query field
|
|
||||||
*/
|
|
||||||
const OPTS_TO_QUERY_FIELD_MAP = {
|
|
||||||
perPage: 'per_page',
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This class includes all the functionality related to interacting with a set of HTTP endpoints
|
* This class includes all the functionality related to interacting with a set of HTTP endpoints
|
||||||
@ -47,12 +41,8 @@ export class HttpClient implements Client {
|
|||||||
if (_.isUndefined(params) || _.isEmpty(params)) {
|
if (_.isUndefined(params) || _.isEmpty(params)) {
|
||||||
return '';
|
return '';
|
||||||
}
|
}
|
||||||
// format params into a form the api expects
|
|
||||||
const formattedParams = _.mapKeys(params, (_value: any, key: string) => {
|
|
||||||
return _.get(OPTS_TO_QUERY_FIELD_MAP, key, key);
|
|
||||||
});
|
|
||||||
// stringify the formatted object
|
// stringify the formatted object
|
||||||
const stringifiedParams = queryString.stringify(formattedParams);
|
const stringifiedParams = queryString.stringify(params);
|
||||||
return `?${stringifiedParams}`;
|
return `?${stringifiedParams}`;
|
||||||
}
|
}
|
||||||
/**
|
/**
|
||||||
@ -65,34 +55,40 @@ export class HttpClient implements Client {
|
|||||||
this._apiEndpointUrl = url.replace(TRAILING_SLASHES_REGEX, ''); // remove trailing slashes
|
this._apiEndpointUrl = url.replace(TRAILING_SLASHES_REGEX, ''); // remove trailing slashes
|
||||||
}
|
}
|
||||||
/**
|
/**
|
||||||
* Retrieve token pair info from the API
|
* Retrieve assetData pair info from the API
|
||||||
* @param requestOpts Options specifying token information to retrieve and page information, defaults to { page: 1, perPage: 100 }
|
* @param requestOpts Options specifying assetData information to retrieve, page information, and network id.
|
||||||
* @return The resulting TokenPairsItems that match the request
|
* @return The resulting AssetPairsResponse that match the request
|
||||||
*/
|
*/
|
||||||
public async getTokenPairsAsync(requestOpts?: TokenPairsRequestOpts & PagedRequestOpts): Promise<TokenPairsItem[]> {
|
public async getAssetPairsAsync(
|
||||||
|
requestOpts?: RequestOpts & AssetPairsRequestOpts & PagedRequestOpts,
|
||||||
|
): Promise<AssetPairsResponse> {
|
||||||
if (!_.isUndefined(requestOpts)) {
|
if (!_.isUndefined(requestOpts)) {
|
||||||
assert.doesConformToSchema('requestOpts', requestOpts, clientSchemas.tokenPairsRequestOptsSchema);
|
assert.doesConformToSchema('requestOpts', requestOpts, clientSchemas.assetPairsRequestOptsSchema);
|
||||||
assert.doesConformToSchema('requestOpts', requestOpts, clientSchemas.pagedRequestOptsSchema);
|
assert.doesConformToSchema('requestOpts', requestOpts, clientSchemas.pagedRequestOptsSchema);
|
||||||
|
assert.doesConformToSchema('requestOpts', requestOpts, clientSchemas.requestOptsSchema);
|
||||||
}
|
}
|
||||||
const httpRequestOpts = {
|
const httpRequestOpts = {
|
||||||
params: _.defaults({}, requestOpts, DEFAULT_PAGED_REQUEST_OPTS),
|
params: requestOpts,
|
||||||
};
|
};
|
||||||
const responseJson = await this._requestAsync('/token_pairs', HttpRequestType.Get, httpRequestOpts);
|
const responseJson = await this._requestAsync('/asset_pairs', HttpRequestType.Get, httpRequestOpts);
|
||||||
const tokenPairs = relayerResponseJsonParsers.parseTokenPairsJson(responseJson);
|
const assetDataPairs = relayerResponseJsonParsers.parseAssetDataPairsJson(responseJson);
|
||||||
return tokenPairs;
|
return assetDataPairs;
|
||||||
}
|
}
|
||||||
/**
|
/**
|
||||||
* Retrieve orders from the API
|
* Retrieve orders from the API
|
||||||
* @param requestOpts Options specifying orders to retrieve and page information, defaults to { page: 1, perPage: 100 }
|
* @param requestOpts Options specifying orders to retrieve and page information, page information, and network id.
|
||||||
* @return The resulting SignedOrders that match the request
|
* @return The resulting OrdersResponse that match the request
|
||||||
*/
|
*/
|
||||||
public async getOrdersAsync(requestOpts?: OrdersRequestOpts & PagedRequestOpts): Promise<SignedOrder[]> {
|
public async getOrdersAsync(
|
||||||
|
requestOpts?: RequestOpts & OrdersRequestOpts & PagedRequestOpts,
|
||||||
|
): Promise<OrdersResponse> {
|
||||||
if (!_.isUndefined(requestOpts)) {
|
if (!_.isUndefined(requestOpts)) {
|
||||||
assert.doesConformToSchema('requestOpts', requestOpts, clientSchemas.ordersRequestOptsSchema);
|
assert.doesConformToSchema('requestOpts', requestOpts, clientSchemas.ordersRequestOptsSchema);
|
||||||
assert.doesConformToSchema('requestOpts', requestOpts, clientSchemas.pagedRequestOptsSchema);
|
assert.doesConformToSchema('requestOpts', requestOpts, clientSchemas.pagedRequestOptsSchema);
|
||||||
|
assert.doesConformToSchema('requestOpts', requestOpts, clientSchemas.requestOptsSchema);
|
||||||
}
|
}
|
||||||
const httpRequestOpts = {
|
const httpRequestOpts = {
|
||||||
params: _.defaults({}, requestOpts, DEFAULT_PAGED_REQUEST_OPTS),
|
params: requestOpts,
|
||||||
};
|
};
|
||||||
const responseJson = await this._requestAsync(`/orders`, HttpRequestType.Get, httpRequestOpts);
|
const responseJson = await this._requestAsync(`/orders`, HttpRequestType.Get, httpRequestOpts);
|
||||||
const orders = relayerResponseJsonParsers.parseOrdersJson(responseJson);
|
const orders = relayerResponseJsonParsers.parseOrdersJson(responseJson);
|
||||||
@ -101,30 +97,37 @@ export class HttpClient implements Client {
|
|||||||
/**
|
/**
|
||||||
* Retrieve a specific order from the API
|
* Retrieve a specific order from the API
|
||||||
* @param orderHash An orderHash generated from the desired order
|
* @param orderHash An orderHash generated from the desired order
|
||||||
* @return The SignedOrder that matches the supplied orderHash
|
* @return The APIOrder that matches the supplied orderHash
|
||||||
*/
|
*/
|
||||||
public async getOrderAsync(orderHash: string): Promise<SignedOrder> {
|
public async getOrderAsync(orderHash: string, requestOpts?: RequestOpts): Promise<APIOrder> {
|
||||||
|
if (!_.isUndefined(requestOpts)) {
|
||||||
|
assert.doesConformToSchema('requestOpts', requestOpts, clientSchemas.requestOptsSchema);
|
||||||
|
}
|
||||||
assert.doesConformToSchema('orderHash', orderHash, schemas.orderHashSchema);
|
assert.doesConformToSchema('orderHash', orderHash, schemas.orderHashSchema);
|
||||||
const responseJson = await this._requestAsync(`/order/${orderHash}`, HttpRequestType.Get);
|
const httpRequestOpts = {
|
||||||
const order = relayerResponseJsonParsers.parseOrderJson(responseJson);
|
params: requestOpts,
|
||||||
|
};
|
||||||
|
const responseJson = await this._requestAsync(`/order/${orderHash}`, HttpRequestType.Get, httpRequestOpts);
|
||||||
|
const order = relayerResponseJsonParsers.parseAPIOrderJson(responseJson);
|
||||||
return order;
|
return order;
|
||||||
}
|
}
|
||||||
/**
|
/**
|
||||||
* Retrieve an orderbook from the API
|
* Retrieve an orderbook from the API
|
||||||
* @param request An OrderbookRequest instance describing the specific orderbook to retrieve
|
* @param request An OrderbookRequest instance describing the specific orderbook to retrieve
|
||||||
* @param requestOpts Options specifying page information, defaults to { page: 1, perPage: 100 }
|
* @param requestOpts Options specifying page information, and network id.
|
||||||
* @return The resulting OrderbookResponse that matches the request
|
* @return The resulting OrderbookResponse that matches the request
|
||||||
*/
|
*/
|
||||||
public async getOrderbookAsync(
|
public async getOrderbookAsync(
|
||||||
request: OrderbookRequest,
|
request: OrderbookRequest,
|
||||||
requestOpts?: PagedRequestOpts,
|
requestOpts?: RequestOpts & PagedRequestOpts,
|
||||||
): Promise<OrderbookResponse> {
|
): Promise<OrderbookResponse> {
|
||||||
assert.doesConformToSchema('request', request, clientSchemas.orderBookRequestSchema);
|
assert.doesConformToSchema('request', request, clientSchemas.orderBookRequestSchema);
|
||||||
if (!_.isUndefined(requestOpts)) {
|
if (!_.isUndefined(requestOpts)) {
|
||||||
assert.doesConformToSchema('requestOpts', requestOpts, clientSchemas.pagedRequestOptsSchema);
|
assert.doesConformToSchema('requestOpts', requestOpts, clientSchemas.pagedRequestOptsSchema);
|
||||||
|
assert.doesConformToSchema('requestOpts', requestOpts, clientSchemas.requestOptsSchema);
|
||||||
}
|
}
|
||||||
const httpRequestOpts = {
|
const httpRequestOpts = {
|
||||||
params: _.defaults({}, request, requestOpts, DEFAULT_PAGED_REQUEST_OPTS),
|
params: _.defaults({}, request, requestOpts),
|
||||||
};
|
};
|
||||||
const responseJson = await this._requestAsync('/orderbook', HttpRequestType.Get, httpRequestOpts);
|
const responseJson = await this._requestAsync('/orderbook', HttpRequestType.Get, httpRequestOpts);
|
||||||
const orderbook = relayerResponseJsonParsers.parseOrderbookResponseJson(responseJson);
|
const orderbook = relayerResponseJsonParsers.parseOrderbookResponseJson(responseJson);
|
||||||
@ -132,28 +135,55 @@ export class HttpClient implements Client {
|
|||||||
}
|
}
|
||||||
/**
|
/**
|
||||||
* Retrieve fee information from the API
|
* Retrieve fee information from the API
|
||||||
* @param request A FeesRequest instance describing the specific fees to retrieve
|
* @param request A OrderConfigRequest instance describing the specific fees to retrieve
|
||||||
* @return The resulting FeesResponse that matches the request
|
* @param requestOpts Options specifying network id.
|
||||||
|
* @return The resulting OrderConfigResponse that matches the request
|
||||||
*/
|
*/
|
||||||
public async getFeesAsync(request: FeesRequest): Promise<FeesResponse> {
|
public async getOrderConfigAsync(
|
||||||
assert.doesConformToSchema('request', request, clientSchemas.feesRequestSchema);
|
request: OrderConfigRequest,
|
||||||
|
requestOpts?: RequestOpts,
|
||||||
|
): Promise<OrderConfigResponse> {
|
||||||
|
if (!_.isUndefined(requestOpts)) {
|
||||||
|
assert.doesConformToSchema('requestOpts', requestOpts, clientSchemas.requestOptsSchema);
|
||||||
|
}
|
||||||
|
assert.doesConformToSchema('request', request, clientSchemas.orderConfigRequestSchema);
|
||||||
const httpRequestOpts = {
|
const httpRequestOpts = {
|
||||||
|
params: requestOpts,
|
||||||
payload: request,
|
payload: request,
|
||||||
};
|
};
|
||||||
const responseJson = await this._requestAsync('/fees', HttpRequestType.Post, httpRequestOpts);
|
const responseJson = await this._requestAsync('/order_config', HttpRequestType.Post, httpRequestOpts);
|
||||||
const fees = relayerResponseJsonParsers.parseFeesResponseJson(responseJson);
|
const fees = relayerResponseJsonParsers.parseOrderConfigResponseJson(responseJson);
|
||||||
return fees;
|
return fees;
|
||||||
}
|
}
|
||||||
|
/**
|
||||||
|
* Retrieve the list of fee recipient addresses used by the relayer.
|
||||||
|
* @param requestOpts Options specifying page information, and network id.
|
||||||
|
* @return The resulting FeeRecipientsResponse
|
||||||
|
*/
|
||||||
|
public async getFeeRecipientsAsync(requestOpts?: RequestOpts & PagedRequestOpts): Promise<FeeRecipientsResponse> {
|
||||||
|
if (!_.isUndefined(requestOpts)) {
|
||||||
|
assert.doesConformToSchema('requestOpts', requestOpts, clientSchemas.pagedRequestOptsSchema);
|
||||||
|
assert.doesConformToSchema('requestOpts', requestOpts, clientSchemas.requestOptsSchema);
|
||||||
|
}
|
||||||
|
const httpRequestOpts = {
|
||||||
|
params: requestOpts,
|
||||||
|
};
|
||||||
|
const feeRecipients = await this._requestAsync('/fee_recipients', HttpRequestType.Get, httpRequestOpts);
|
||||||
|
assert.doesConformToSchema('feeRecipients', feeRecipients, schemas.relayerApiFeeRecipientsResponseSchema);
|
||||||
|
return feeRecipients;
|
||||||
|
}
|
||||||
/**
|
/**
|
||||||
* Submit a signed order to the API
|
* Submit a signed order to the API
|
||||||
* @param signedOrder A SignedOrder instance to submit
|
* @param signedOrder A SignedOrder instance to submit
|
||||||
|
* @param requestOpts Options specifying network id.
|
||||||
*/
|
*/
|
||||||
public async submitOrderAsync(signedOrder: SignedOrder): Promise<void> {
|
public async submitOrderAsync(signedOrder: SignedOrder, requestOpts?: RequestOpts): Promise<void> {
|
||||||
assert.doesConformToSchema('signedOrder', signedOrder, schemas.signedOrderSchema);
|
assert.doesConformToSchema('signedOrder', signedOrder, schemas.signedOrderSchema);
|
||||||
const requestOpts = {
|
const httpRequestOpts = {
|
||||||
|
params: requestOpts,
|
||||||
payload: signedOrder,
|
payload: signedOrder,
|
||||||
};
|
};
|
||||||
await this._requestAsync('/order', HttpRequestType.Post, requestOpts);
|
await this._requestAsync('/order', HttpRequestType.Post, httpRequestOpts);
|
||||||
}
|
}
|
||||||
private async _requestAsync(
|
private async _requestAsync(
|
||||||
path: string,
|
path: string,
|
||||||
|
@ -1,19 +1,19 @@
|
|||||||
export { HttpClient } from './http_client';
|
export { HttpClient } from './http_client';
|
||||||
export { orderbookChannelFactory } from './orderbook_channel_factory';
|
export { ordersChannelFactory } from './orders_channel_factory';
|
||||||
export {
|
export {
|
||||||
Client,
|
Client,
|
||||||
FeesRequest,
|
OrderConfigRequest,
|
||||||
FeesResponse,
|
OrderConfigResponse,
|
||||||
OrderbookChannel,
|
OrdersChannel,
|
||||||
OrderbookChannelHandler,
|
OrdersChannelHandler,
|
||||||
OrderbookChannelSubscriptionOpts,
|
OrdersChannelSubscriptionOpts,
|
||||||
OrderbookRequest,
|
OrderbookRequest,
|
||||||
OrderbookResponse,
|
OrderbookResponse,
|
||||||
OrdersRequestOpts,
|
OrdersRequestOpts,
|
||||||
PagedRequestOpts,
|
PagedRequestOpts,
|
||||||
TokenPairsItem,
|
AssetPairsItem,
|
||||||
TokenPairsRequestOpts,
|
AssetPairsRequestOpts,
|
||||||
TokenTradeInfo,
|
Asset,
|
||||||
} from './types';
|
} from './types';
|
||||||
|
|
||||||
export { SignedOrder } from '@0xproject/types';
|
export { SignedOrder } from '@0xproject/types';
|
||||||
|
@ -1,32 +0,0 @@
|
|||||||
import * as WebSocket from 'websocket';
|
|
||||||
|
|
||||||
import { OrderbookChannel, OrderbookChannelHandler } from './types';
|
|
||||||
import { assert } from './utils/assert';
|
|
||||||
import { WebSocketOrderbookChannel } from './ws_orderbook_channel';
|
|
||||||
|
|
||||||
export const orderbookChannelFactory = {
|
|
||||||
/**
|
|
||||||
* Instantiates a new WebSocketOrderbookChannel instance
|
|
||||||
* @param url The relayer API base WS url you would like to interact with
|
|
||||||
* @param handler An OrderbookChannelHandler instance that responds to various
|
|
||||||
* channel updates
|
|
||||||
* @return An OrderbookChannel Promise
|
|
||||||
*/
|
|
||||||
async createWebSocketOrderbookChannelAsync(
|
|
||||||
url: string,
|
|
||||||
handler: OrderbookChannelHandler,
|
|
||||||
): Promise<OrderbookChannel> {
|
|
||||||
assert.isUri('url', url);
|
|
||||||
assert.isOrderbookChannelHandler('handler', handler);
|
|
||||||
return new Promise<OrderbookChannel>((resolve, reject) => {
|
|
||||||
const client = new WebSocket.w3cwebsocket(url);
|
|
||||||
client.onopen = () => {
|
|
||||||
const orderbookChannel = new WebSocketOrderbookChannel(client, handler);
|
|
||||||
resolve(orderbookChannel);
|
|
||||||
};
|
|
||||||
client.onerror = err => {
|
|
||||||
reject(err);
|
|
||||||
};
|
|
||||||
});
|
|
||||||
},
|
|
||||||
};
|
|
29
packages/connect/src/orders_channel_factory.ts
Normal file
29
packages/connect/src/orders_channel_factory.ts
Normal file
@ -0,0 +1,29 @@
|
|||||||
|
import * as WebSocket from 'websocket';
|
||||||
|
|
||||||
|
import { OrdersChannel, OrdersChannelHandler } from './types';
|
||||||
|
import { assert } from './utils/assert';
|
||||||
|
import { WebSocketOrdersChannel } from './ws_orders_channel';
|
||||||
|
|
||||||
|
export const ordersChannelFactory = {
|
||||||
|
/**
|
||||||
|
* Instantiates a new WebSocketOrdersChannel instance
|
||||||
|
* @param url The relayer API base WS url you would like to interact with
|
||||||
|
* @param handler An OrdersChannelHandler instance that responds to various
|
||||||
|
* channel updates
|
||||||
|
* @return An OrdersChannel Promise
|
||||||
|
*/
|
||||||
|
async createWebSocketOrdersChannelAsync(url: string, handler: OrdersChannelHandler): Promise<OrdersChannel> {
|
||||||
|
assert.isUri('url', url);
|
||||||
|
assert.isOrdersChannelHandler('handler', handler);
|
||||||
|
return new Promise<OrdersChannel>((resolve, reject) => {
|
||||||
|
const client = new WebSocket.w3cwebsocket(url);
|
||||||
|
client.onopen = () => {
|
||||||
|
const ordersChannel = new WebSocketOrdersChannel(client, handler);
|
||||||
|
resolve(ordersChannel);
|
||||||
|
};
|
||||||
|
client.onerror = err => {
|
||||||
|
reject(err);
|
||||||
|
};
|
||||||
|
});
|
||||||
|
},
|
||||||
|
};
|
@ -0,0 +1,8 @@
|
|||||||
|
export const assetPairsRequestOptsSchema = {
|
||||||
|
id: '/AssetPairsRequestOpts',
|
||||||
|
type: 'object',
|
||||||
|
properties: {
|
||||||
|
assetDataA: { $ref: '/hexSchema' },
|
||||||
|
assetDataB: { $ref: '/hexSchema' },
|
||||||
|
},
|
||||||
|
};
|
@ -1,26 +0,0 @@
|
|||||||
export const feesRequestSchema = {
|
|
||||||
id: '/FeesRequest',
|
|
||||||
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',
|
|
||||||
'makerTokenAmount',
|
|
||||||
'takerTokenAmount',
|
|
||||||
'expirationUnixTimestampSec',
|
|
||||||
'salt',
|
|
||||||
],
|
|
||||||
};
|
|
24
packages/connect/src/schemas/order_config_request_schema.ts
Normal file
24
packages/connect/src/schemas/order_config_request_schema.ts
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
export const orderConfigRequestSchema = {
|
||||||
|
id: '/OrderConfigRequest',
|
||||||
|
type: 'object',
|
||||||
|
properties: {
|
||||||
|
makerAddress: { $ref: '/addressSchema' },
|
||||||
|
takerAddress: { $ref: '/addressSchema' },
|
||||||
|
makerAssetAmount: { $ref: '/numberSchema' },
|
||||||
|
takerAssetAmount: { $ref: '/numberSchema' },
|
||||||
|
makerAssetData: { $ref: '/hexSchema' },
|
||||||
|
takerAssetData: { $ref: '/hexSchema' },
|
||||||
|
exchangeAddress: { $ref: '/addressSchema' },
|
||||||
|
expirationTimeSeconds: { $ref: '/numberSchema' },
|
||||||
|
},
|
||||||
|
required: [
|
||||||
|
'makerAddress',
|
||||||
|
'takerAddress',
|
||||||
|
'makerAssetAmount',
|
||||||
|
'takerAssetAmount',
|
||||||
|
'makerAssetData',
|
||||||
|
'takerAssetData',
|
||||||
|
'exchangeAddress',
|
||||||
|
'expirationTimeSeconds',
|
||||||
|
],
|
||||||
|
};
|
@ -2,8 +2,8 @@ export const orderBookRequestSchema = {
|
|||||||
id: '/OrderBookRequest',
|
id: '/OrderBookRequest',
|
||||||
type: 'object',
|
type: 'object',
|
||||||
properties: {
|
properties: {
|
||||||
baseTokenAddress: { $ref: '/Address' },
|
baseAssetData: { $ref: '/hexSchema' },
|
||||||
quoteTokenAddress: { $ref: '/Address' },
|
quoteAssetData: { $ref: '/hexSchema' },
|
||||||
},
|
},
|
||||||
required: ['baseTokenAddress', 'quoteTokenAddress'],
|
required: ['baseAssetData', 'quoteAssetData'],
|
||||||
};
|
};
|
||||||
|
@ -2,15 +2,18 @@ export const ordersRequestOptsSchema = {
|
|||||||
id: '/OrdersRequestOpts',
|
id: '/OrdersRequestOpts',
|
||||||
type: 'object',
|
type: 'object',
|
||||||
properties: {
|
properties: {
|
||||||
exchangeContractAddress: { $ref: '/Address' },
|
makerAssetProxyId: { $ref: '/hexSchema' },
|
||||||
tokenAddress: { $ref: '/Address' },
|
takerAssetProxyId: { $ref: '/hexSchema' },
|
||||||
makerTokenAddress: { $ref: '/Address' },
|
makerAssetAddress: { $ref: '/addressSchema' },
|
||||||
takerTokenAddress: { $ref: '/Address' },
|
takerAssetAddress: { $ref: '/addressSchema' },
|
||||||
tokenA: { $ref: '/Address' },
|
exchangeAddress: { $ref: '/addressSchema' },
|
||||||
tokenB: { $ref: '/Address' },
|
senderAddress: { $ref: '/addressSchema' },
|
||||||
maker: { $ref: '/Address' },
|
makerAssetData: { $ref: '/hexSchema' },
|
||||||
taker: { $ref: '/Address' },
|
takerAssetData: { $ref: '/hexSchema' },
|
||||||
trader: { $ref: '/Address' },
|
traderAssetData: { $ref: '/hexSchema' },
|
||||||
feeRecipient: { $ref: '/Address' },
|
makerAddress: { $ref: '/addressSchema' },
|
||||||
|
takerAddress: { $ref: '/addressSchema' },
|
||||||
|
traderAddress: { $ref: '/addressSchema' },
|
||||||
|
feeRecipientAddress: { $ref: '/addressSchema' },
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
7
packages/connect/src/schemas/request_opts_schema.ts
Normal file
7
packages/connect/src/schemas/request_opts_schema.ts
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
export const requestOptsSchema = {
|
||||||
|
id: '/RequestOpts',
|
||||||
|
type: 'object',
|
||||||
|
properties: {
|
||||||
|
networkId: { type: 'number' },
|
||||||
|
},
|
||||||
|
};
|
@ -1,13 +1,15 @@
|
|||||||
import { feesRequestSchema } from './fees_request_schema';
|
import { assetPairsRequestOptsSchema } from './asset_pairs_request_opts_schema';
|
||||||
|
import { orderConfigRequestSchema } from './order_config_request_schema';
|
||||||
import { orderBookRequestSchema } from './orderbook_request_schema';
|
import { orderBookRequestSchema } from './orderbook_request_schema';
|
||||||
import { ordersRequestOptsSchema } from './orders_request_opts_schema';
|
import { ordersRequestOptsSchema } from './orders_request_opts_schema';
|
||||||
import { pagedRequestOptsSchema } from './paged_request_opts_schema';
|
import { pagedRequestOptsSchema } from './paged_request_opts_schema';
|
||||||
import { tokenPairsRequestOptsSchema } from './token_pairs_request_opts_schema';
|
import { requestOptsSchema } from './request_opts_schema';
|
||||||
|
|
||||||
export const schemas = {
|
export const schemas = {
|
||||||
feesRequestSchema,
|
orderConfigRequestSchema,
|
||||||
orderBookRequestSchema,
|
orderBookRequestSchema,
|
||||||
ordersRequestOptsSchema,
|
ordersRequestOptsSchema,
|
||||||
pagedRequestOptsSchema,
|
pagedRequestOptsSchema,
|
||||||
tokenPairsRequestOptsSchema,
|
requestOptsSchema,
|
||||||
|
assetPairsRequestOptsSchema,
|
||||||
};
|
};
|
||||||
|
@ -1,8 +0,0 @@
|
|||||||
export const tokenPairsRequestOptsSchema = {
|
|
||||||
id: '/TokenPairsRequestOpts',
|
|
||||||
type: 'object',
|
|
||||||
properties: {
|
|
||||||
tokenA: { $ref: '/Address' },
|
|
||||||
tokenB: { $ref: '/Address' },
|
|
||||||
},
|
|
||||||
};
|
|
@ -2,73 +2,55 @@ import { SignedOrder } from '@0xproject/types';
|
|||||||
import { BigNumber } from '@0xproject/utils';
|
import { BigNumber } from '@0xproject/utils';
|
||||||
|
|
||||||
export interface Client {
|
export interface Client {
|
||||||
getTokenPairsAsync: (requestOpts?: TokenPairsRequestOpts & PagedRequestOpts) => Promise<TokenPairsItem[]>;
|
getAssetPairsAsync: (
|
||||||
getOrdersAsync: (requestOpts?: OrdersRequestOpts & PagedRequestOpts) => Promise<SignedOrder[]>;
|
requestOpts?: AssetPairsRequestOpts & PagedRequestOpts,
|
||||||
getOrderAsync: (orderHash: string) => Promise<SignedOrder>;
|
) => Promise<PaginatedCollection<AssetPairsItem>>;
|
||||||
|
getOrdersAsync: (requestOpts?: OrdersRequestOpts & PagedRequestOpts) => Promise<PaginatedCollection<APIOrder>>;
|
||||||
|
getOrderAsync: (orderHash: string) => Promise<APIOrder>;
|
||||||
getOrderbookAsync: (request: OrderbookRequest, requestOpts?: PagedRequestOpts) => Promise<OrderbookResponse>;
|
getOrderbookAsync: (request: OrderbookRequest, requestOpts?: PagedRequestOpts) => Promise<OrderbookResponse>;
|
||||||
getFeesAsync: (request: FeesRequest) => Promise<FeesResponse>;
|
getOrderConfigAsync: (request: OrderConfigRequest) => Promise<OrderConfigResponse>;
|
||||||
|
getFeeRecipientsAsync: (requestOpts?: PagedRequestOpts) => Promise<FeeRecipientsResponse>;
|
||||||
submitOrderAsync: (signedOrder: SignedOrder) => Promise<void>;
|
submitOrderAsync: (signedOrder: SignedOrder) => Promise<void>;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface OrderbookChannel {
|
export interface OrdersChannel {
|
||||||
subscribe: (subscriptionOpts: OrderbookChannelSubscriptionOpts) => void;
|
subscribe: (subscriptionOpts: OrdersChannelSubscriptionOpts) => void;
|
||||||
close: () => void;
|
close: () => void;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* baseTokenAddress: The address of token designated as the baseToken in the currency pair calculation of price
|
* baseAssetData: The address of assetData designated as the baseToken in the currency pair calculation of price
|
||||||
* quoteTokenAddress: The address of token designated as the quoteToken in the currency pair calculation of price
|
* quoteAssetData: The address of assetData designated as the quoteToken in the currency pair calculation of price
|
||||||
* snapshot: If true, a snapshot of the orderbook will be sent before the updates to the orderbook
|
|
||||||
* limit: Maximum number of bids and asks in orderbook snapshot
|
* limit: Maximum number of bids and asks in orderbook snapshot
|
||||||
*/
|
*/
|
||||||
export interface OrderbookChannelSubscriptionOpts {
|
export interface OrdersChannelSubscriptionOpts {
|
||||||
baseTokenAddress: string;
|
baseAssetData: string;
|
||||||
quoteTokenAddress: string;
|
quoteAssetData: string;
|
||||||
snapshot: boolean;
|
|
||||||
limit: number;
|
limit: number;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface OrderbookChannelHandler {
|
export interface OrdersChannelHandler {
|
||||||
onSnapshot: (
|
onUpdate: (channel: OrdersChannel, subscriptionOpts: OrdersChannelSubscriptionOpts, orders: APIOrder[]) => void;
|
||||||
channel: OrderbookChannel,
|
onError: (channel: OrdersChannel, err: Error, subscriptionOpts?: OrdersChannelSubscriptionOpts) => void;
|
||||||
subscriptionOpts: OrderbookChannelSubscriptionOpts,
|
onClose: (channel: OrdersChannel) => void;
|
||||||
snapshot: OrderbookResponse,
|
|
||||||
) => void;
|
|
||||||
onUpdate: (
|
|
||||||
channel: OrderbookChannel,
|
|
||||||
subscriptionOpts: OrderbookChannelSubscriptionOpts,
|
|
||||||
order: SignedOrder,
|
|
||||||
) => void;
|
|
||||||
onError: (channel: OrderbookChannel, err: Error, subscriptionOpts?: OrderbookChannelSubscriptionOpts) => void;
|
|
||||||
onClose: (channel: OrderbookChannel) => void;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export type OrderbookChannelMessage =
|
export type OrdersChannelMessage = UpdateOrdersChannelMessage | UnknownOrdersChannelMessage;
|
||||||
| SnapshotOrderbookChannelMessage
|
|
||||||
| UpdateOrderbookChannelMessage
|
|
||||||
| UnknownOrderbookChannelMessage;
|
|
||||||
|
|
||||||
export enum OrderbookChannelMessageTypes {
|
export enum OrdersChannelMessageTypes {
|
||||||
Snapshot = 'snapshot',
|
|
||||||
Update = 'update',
|
Update = 'update',
|
||||||
Unknown = 'unknown',
|
Unknown = 'unknown',
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface SnapshotOrderbookChannelMessage {
|
export interface UpdateOrdersChannelMessage {
|
||||||
type: OrderbookChannelMessageTypes.Snapshot;
|
type: OrdersChannelMessageTypes.Update;
|
||||||
requestId: number;
|
requestId: string;
|
||||||
payload: OrderbookResponse;
|
payload: APIOrder[];
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface UpdateOrderbookChannelMessage {
|
export interface UnknownOrdersChannelMessage {
|
||||||
type: OrderbookChannelMessageTypes.Update;
|
type: OrdersChannelMessageTypes.Unknown;
|
||||||
requestId: number;
|
requestId: string;
|
||||||
payload: SignedOrder;
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface UnknownOrderbookChannelMessage {
|
|
||||||
type: OrderbookChannelMessageTypes.Unknown;
|
|
||||||
requestId: number;
|
|
||||||
payload: undefined;
|
payload: undefined;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -83,60 +65,86 @@ export enum WebsocketClientEventType {
|
|||||||
ConnectFailed = 'connectFailed',
|
ConnectFailed = 'connectFailed',
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface TokenPairsRequestOpts {
|
export type OrdersResponse = PaginatedCollection<APIOrder>;
|
||||||
tokenA?: string;
|
|
||||||
tokenB?: string;
|
export interface APIOrder {
|
||||||
|
order: SignedOrder;
|
||||||
|
metaData: object;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface TokenPairsItem {
|
export interface AssetPairsRequestOpts {
|
||||||
tokenA: TokenTradeInfo;
|
assetDataA?: string;
|
||||||
tokenB: TokenTradeInfo;
|
assetDataB?: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface TokenTradeInfo {
|
export type AssetPairsResponse = PaginatedCollection<AssetPairsItem>;
|
||||||
address: string;
|
|
||||||
|
export interface AssetPairsItem {
|
||||||
|
assetDataA: Asset;
|
||||||
|
assetDataB: Asset;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface Asset {
|
||||||
|
assetData: string;
|
||||||
minAmount: BigNumber;
|
minAmount: BigNumber;
|
||||||
maxAmount: BigNumber;
|
maxAmount: BigNumber;
|
||||||
precision: number;
|
precision: number;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface OrdersRequestOpts {
|
export interface OrdersRequestOpts {
|
||||||
exchangeContractAddress?: string;
|
makerAssetProxyId?: string;
|
||||||
tokenAddress?: string;
|
takerAssetProxyId?: string;
|
||||||
makerTokenAddress?: string;
|
makerAssetAddress?: string;
|
||||||
takerTokenAddress?: string;
|
takerAssetAddress?: string;
|
||||||
maker?: string;
|
exchangeAddress?: string;
|
||||||
taker?: string;
|
senderAddress?: string;
|
||||||
trader?: string;
|
makerAssetData?: string;
|
||||||
feeRecipient?: string;
|
takerAssetData?: string;
|
||||||
|
makerAddress?: string;
|
||||||
|
takerAddress?: string;
|
||||||
|
traderAddress?: string;
|
||||||
|
feeRecipientAddress?: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface OrderbookRequest {
|
export interface OrderbookRequest {
|
||||||
baseTokenAddress: string;
|
baseAssetData: string;
|
||||||
quoteTokenAddress: string;
|
quoteAssetData: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface OrderbookResponse {
|
export interface OrderbookResponse {
|
||||||
bids: SignedOrder[];
|
bids: PaginatedCollection<APIOrder>;
|
||||||
asks: SignedOrder[];
|
asks: PaginatedCollection<APIOrder>;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface FeesRequest {
|
export interface PaginatedCollection<T> {
|
||||||
exchangeContractAddress: string;
|
total: number;
|
||||||
maker: string;
|
page: number;
|
||||||
taker: string;
|
perPage: number;
|
||||||
makerTokenAddress: string;
|
records: T[];
|
||||||
takerTokenAddress: string;
|
|
||||||
makerTokenAmount: BigNumber;
|
|
||||||
takerTokenAmount: BigNumber;
|
|
||||||
expirationUnixTimestampSec: BigNumber;
|
|
||||||
salt: BigNumber;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface FeesResponse {
|
export interface OrderConfigRequest {
|
||||||
feeRecipient: string;
|
makerAddress: string;
|
||||||
|
takerAddress: string;
|
||||||
|
makerAssetAmount: string;
|
||||||
|
takerAssetAmount: string;
|
||||||
|
makerAssetData: string;
|
||||||
|
takerAssetData: string;
|
||||||
|
exchangeAddress: string;
|
||||||
|
expirationTimeSeconds: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface OrderConfigResponse {
|
||||||
makerFee: BigNumber;
|
makerFee: BigNumber;
|
||||||
takerFee: BigNumber;
|
takerFee: BigNumber;
|
||||||
|
feeRecipientAddress: string;
|
||||||
|
senderAddress: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export type FeeRecipientsResponse = PaginatedCollection<string>;
|
||||||
|
|
||||||
|
export interface RequestOpts {
|
||||||
|
networkId?: number;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface PagedRequestOpts {
|
export interface PagedRequestOpts {
|
||||||
|
@ -10,15 +10,14 @@ import * as _ from 'lodash';
|
|||||||
|
|
||||||
export const assert = {
|
export const assert = {
|
||||||
...sharedAssert,
|
...sharedAssert,
|
||||||
isOrderbookChannelSubscriptionOpts(variableName: string, subscriptionOpts: any): void {
|
isOrdersChannelSubscriptionOpts(variableName: string, subscriptionOpts: any): void {
|
||||||
sharedAssert.doesConformToSchema(
|
sharedAssert.doesConformToSchema(
|
||||||
variableName,
|
variableName,
|
||||||
subscriptionOpts,
|
subscriptionOpts,
|
||||||
schemas.relayerApiOrderbookChannelSubscribePayload,
|
schemas.relayerApiOrdersChannelSubscribePayload,
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
isOrderbookChannelHandler(variableName: string, handler: any): void {
|
isOrdersChannelHandler(variableName: string, handler: any): void {
|
||||||
sharedAssert.isFunction(`${variableName}.onSnapshot`, _.get(handler, 'onSnapshot'));
|
|
||||||
sharedAssert.isFunction(`${variableName}.onUpdate`, _.get(handler, 'onUpdate'));
|
sharedAssert.isFunction(`${variableName}.onUpdate`, _.get(handler, 'onUpdate'));
|
||||||
sharedAssert.isFunction(`${variableName}.onError`, _.get(handler, 'onError'));
|
sharedAssert.isFunction(`${variableName}.onError`, _.get(handler, 'onError'));
|
||||||
sharedAssert.isFunction(`${variableName}.onClose`, _.get(handler, 'onClose'));
|
sharedAssert.isFunction(`${variableName}.onClose`, _.get(handler, 'onClose'));
|
||||||
|
@ -1,43 +0,0 @@
|
|||||||
import { assert } from '@0xproject/assert';
|
|
||||||
import { schemas } from '@0xproject/json-schemas';
|
|
||||||
import * as _ from 'lodash';
|
|
||||||
|
|
||||||
import { OrderbookChannelMessage, OrderbookChannelMessageTypes } from '../types';
|
|
||||||
|
|
||||||
import { relayerResponseJsonParsers } from './relayer_response_json_parsers';
|
|
||||||
|
|
||||||
export const orderbookChannelMessageParser = {
|
|
||||||
parse(utf8Data: string): OrderbookChannelMessage {
|
|
||||||
// parse the message
|
|
||||||
const messageObj = JSON.parse(utf8Data);
|
|
||||||
// ensure we have a type parameter to switch on
|
|
||||||
const type: string = _.get(messageObj, 'type');
|
|
||||||
assert.assert(!_.isUndefined(type), `Message is missing a type parameter: ${utf8Data}`);
|
|
||||||
assert.isString('type', type);
|
|
||||||
// ensure we have a request id for the resulting message
|
|
||||||
const requestId: number = _.get(messageObj, 'requestId');
|
|
||||||
assert.assert(!_.isUndefined(requestId), `Message is missing a requestId parameter: ${utf8Data}`);
|
|
||||||
assert.isNumber('requestId', requestId);
|
|
||||||
switch (type) {
|
|
||||||
case OrderbookChannelMessageTypes.Snapshot: {
|
|
||||||
assert.doesConformToSchema('message', messageObj, schemas.relayerApiOrderbookChannelSnapshotSchema);
|
|
||||||
const orderbookJson = messageObj.payload;
|
|
||||||
const orderbook = relayerResponseJsonParsers.parseOrderbookResponseJson(orderbookJson);
|
|
||||||
return _.assign(messageObj, { payload: orderbook });
|
|
||||||
}
|
|
||||||
case OrderbookChannelMessageTypes.Update: {
|
|
||||||
assert.doesConformToSchema('message', messageObj, schemas.relayerApiOrderbookChannelUpdateSchema);
|
|
||||||
const orderJson = messageObj.payload;
|
|
||||||
const order = relayerResponseJsonParsers.parseOrderJson(orderJson);
|
|
||||||
return _.assign(messageObj, { payload: order });
|
|
||||||
}
|
|
||||||
default: {
|
|
||||||
return {
|
|
||||||
type: OrderbookChannelMessageTypes.Unknown,
|
|
||||||
requestId,
|
|
||||||
payload: undefined,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
};
|
|
37
packages/connect/src/utils/orders_channel_message_parser.ts
Normal file
37
packages/connect/src/utils/orders_channel_message_parser.ts
Normal file
@ -0,0 +1,37 @@
|
|||||||
|
import { assert } from '@0xproject/assert';
|
||||||
|
import { schemas } from '@0xproject/json-schemas';
|
||||||
|
import * as _ from 'lodash';
|
||||||
|
|
||||||
|
import { OrdersChannelMessage, OrdersChannelMessageTypes } from '../types';
|
||||||
|
|
||||||
|
import { relayerResponseJsonParsers } from './relayer_response_json_parsers';
|
||||||
|
|
||||||
|
export const ordersChannelMessageParser = {
|
||||||
|
parse(utf8Data: string): OrdersChannelMessage {
|
||||||
|
// parse the message
|
||||||
|
const messageObj = JSON.parse(utf8Data);
|
||||||
|
// ensure we have a type parameter to switch on
|
||||||
|
const type: string = _.get(messageObj, 'type');
|
||||||
|
assert.assert(!_.isUndefined(type), `Message is missing a type parameter: ${utf8Data}`);
|
||||||
|
assert.isString('type', type);
|
||||||
|
// ensure we have a request id for the resulting message
|
||||||
|
const requestId: string = _.get(messageObj, 'requestId');
|
||||||
|
assert.assert(!_.isUndefined(requestId), `Message is missing a requestId parameter: ${utf8Data}`);
|
||||||
|
assert.isString('requestId', requestId);
|
||||||
|
switch (type) {
|
||||||
|
case OrdersChannelMessageTypes.Update: {
|
||||||
|
assert.doesConformToSchema('message', messageObj, schemas.relayerApiOrdersChannelUpdateSchema);
|
||||||
|
const ordersJson = messageObj.payload;
|
||||||
|
const orders = relayerResponseJsonParsers.parseAPIOrdersJson(ordersJson);
|
||||||
|
return _.assign(messageObj, { payload: orders });
|
||||||
|
}
|
||||||
|
default: {
|
||||||
|
return {
|
||||||
|
type: OrdersChannelMessageTypes.Unknown,
|
||||||
|
requestId,
|
||||||
|
payload: undefined,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
};
|
@ -1,37 +1,49 @@
|
|||||||
import { assert } from '@0xproject/assert';
|
import { assert } from '@0xproject/assert';
|
||||||
import { schemas } from '@0xproject/json-schemas';
|
import { schemas } from '@0xproject/json-schemas';
|
||||||
import { SignedOrder } from '@0xproject/types';
|
|
||||||
|
|
||||||
import { FeesResponse, OrderbookResponse, TokenPairsItem } from '../types';
|
import {
|
||||||
|
APIOrder,
|
||||||
|
AssetPairsItem,
|
||||||
|
AssetPairsResponse,
|
||||||
|
OrderbookResponse,
|
||||||
|
OrderConfigResponse,
|
||||||
|
OrdersResponse,
|
||||||
|
} from '../types';
|
||||||
|
|
||||||
import { typeConverters } from './type_converters';
|
import { typeConverters } from './type_converters';
|
||||||
|
|
||||||
export const relayerResponseJsonParsers = {
|
export const relayerResponseJsonParsers = {
|
||||||
parseTokenPairsJson(json: any): TokenPairsItem[] {
|
parseAssetDataPairsJson(json: any): AssetPairsResponse {
|
||||||
assert.doesConformToSchema('tokenPairs', json, schemas.relayerApiTokenPairsResponseSchema);
|
assert.doesConformToSchema('assetDataPairsResponse', json, schemas.relayerApiAssetDataPairsResponseSchema);
|
||||||
return json.map((tokenPair: any) => {
|
return { ...json, records: relayerResponseJsonParsers.parseAssetPairsItemsJson(json.records) };
|
||||||
return typeConverters.convertStringsFieldsToBigNumbers(tokenPair, [
|
},
|
||||||
'tokenA.minAmount',
|
parseAssetPairsItemsJson(json: any): AssetPairsItem[] {
|
||||||
'tokenA.maxAmount',
|
return json.map((assetDataPair: any) => {
|
||||||
'tokenB.minAmount',
|
return typeConverters.convertStringsFieldsToBigNumbers(assetDataPair, [
|
||||||
'tokenB.maxAmount',
|
'assetDataA.minAmount',
|
||||||
|
'assetDataA.maxAmount',
|
||||||
|
'assetDataB.minAmount',
|
||||||
|
'assetDataB.maxAmount',
|
||||||
]);
|
]);
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
parseOrdersJson(json: any): SignedOrder[] {
|
parseOrdersJson(json: any): OrdersResponse {
|
||||||
assert.doesConformToSchema('orders', json, schemas.signedOrdersSchema);
|
assert.doesConformToSchema('relayerApiOrdersResponse', json, schemas.relayerApiOrdersResponseSchema);
|
||||||
return json.map((order: object) => typeConverters.convertOrderStringFieldsToBigNumber(order));
|
return { ...json, records: relayerResponseJsonParsers.parseAPIOrdersJson(json.records) };
|
||||||
},
|
},
|
||||||
parseOrderJson(json: any): SignedOrder {
|
parseAPIOrdersJson(json: any): APIOrder[] {
|
||||||
assert.doesConformToSchema('order', json, schemas.signedOrderSchema);
|
return json.map(relayerResponseJsonParsers.parseAPIOrderJson.bind(relayerResponseJsonParsers));
|
||||||
return typeConverters.convertOrderStringFieldsToBigNumber(json);
|
},
|
||||||
|
parseAPIOrderJson(json: any): APIOrder {
|
||||||
|
assert.doesConformToSchema('relayerApiOrder', json, schemas.relayerApiOrderSchema);
|
||||||
|
return typeConverters.convertAPIOrderStringFieldsToBigNumber(json);
|
||||||
},
|
},
|
||||||
parseOrderbookResponseJson(json: any): OrderbookResponse {
|
parseOrderbookResponseJson(json: any): OrderbookResponse {
|
||||||
assert.doesConformToSchema('orderBook', json, schemas.relayerApiOrderBookResponseSchema);
|
assert.doesConformToSchema('orderBookResponse', json, schemas.relayerApiOrderbookResponseSchema);
|
||||||
return typeConverters.convertOrderbookStringFieldsToBigNumber(json);
|
return typeConverters.convertOrderbookStringFieldsToBigNumber(json);
|
||||||
},
|
},
|
||||||
parseFeesResponseJson(json: any): FeesResponse {
|
parseOrderConfigResponseJson(json: any): OrderConfigResponse {
|
||||||
assert.doesConformToSchema('fees', json, schemas.relayerApiFeesResponseSchema);
|
assert.doesConformToSchema('orderConfigResponse', json, schemas.relayerApiOrderConfigResponseSchema);
|
||||||
return typeConverters.convertStringsFieldsToBigNumbers(json, ['makerFee', 'takerFee']);
|
return typeConverters.convertStringsFieldsToBigNumbers(json, ['makerFee', 'takerFee']);
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
@ -1,29 +1,47 @@
|
|||||||
import { BigNumber } from '@0xproject/utils';
|
import { BigNumber } from '@0xproject/utils';
|
||||||
import * as _ from 'lodash';
|
import * as _ from 'lodash';
|
||||||
|
|
||||||
|
import { APIOrder } from '../types';
|
||||||
|
|
||||||
export const typeConverters = {
|
export const typeConverters = {
|
||||||
convertOrderbookStringFieldsToBigNumber(orderbook: any): any {
|
convertOrderbookStringFieldsToBigNumber(orderbook: any): any {
|
||||||
const bids = _.get(orderbook, 'bids', []);
|
const bids = _.get(orderbook, 'bids', []);
|
||||||
const asks = _.get(orderbook, 'asks', []);
|
const asks = _.get(orderbook, 'asks', []);
|
||||||
return {
|
const convertedBids = {
|
||||||
bids: bids.map((order: any) => typeConverters.convertOrderStringFieldsToBigNumber(order)),
|
...bids,
|
||||||
asks: asks.map((order: any) => typeConverters.convertOrderStringFieldsToBigNumber(order)),
|
records: bids.records.map((order: any) => typeConverters.convertAPIOrderStringFieldsToBigNumber(order)),
|
||||||
};
|
};
|
||||||
|
const convertedAsks = {
|
||||||
|
...asks,
|
||||||
|
records: asks.records.map((order: any) => typeConverters.convertAPIOrderStringFieldsToBigNumber(order)),
|
||||||
|
};
|
||||||
|
return {
|
||||||
|
bids: convertedBids,
|
||||||
|
asks: convertedAsks,
|
||||||
|
};
|
||||||
|
},
|
||||||
|
convertAPIOrderStringFieldsToBigNumber(apiOrder: any): APIOrder {
|
||||||
|
return { ...apiOrder, order: typeConverters.convertOrderStringFieldsToBigNumber(apiOrder.order) };
|
||||||
},
|
},
|
||||||
convertOrderStringFieldsToBigNumber(order: any): any {
|
convertOrderStringFieldsToBigNumber(order: any): any {
|
||||||
return typeConverters.convertStringsFieldsToBigNumbers(order, [
|
return typeConverters.convertStringsFieldsToBigNumbers(order, [
|
||||||
'makerTokenAmount',
|
'makerAssetAmount',
|
||||||
'takerTokenAmount',
|
'takerAssetAmount',
|
||||||
'makerFee',
|
'makerFee',
|
||||||
'takerFee',
|
'takerFee',
|
||||||
'expirationUnixTimestampSec',
|
'expirationTimeSeconds',
|
||||||
'salt',
|
'salt',
|
||||||
]);
|
]);
|
||||||
},
|
},
|
||||||
convertStringsFieldsToBigNumbers(obj: any, fields: string[]): any {
|
convertStringsFieldsToBigNumbers(obj: any, fields: string[]): any {
|
||||||
const result = _.assign({}, obj);
|
const result = _.assign({}, obj);
|
||||||
_.each(fields, field => {
|
_.each(fields, field => {
|
||||||
_.update(result, field, (value: string) => new BigNumber(value));
|
_.update(result, field, (value: string) => {
|
||||||
|
if (_.isUndefined(value)) {
|
||||||
|
throw new Error(`Could not find field '${field}' while converting string fields to BigNumber.`);
|
||||||
|
}
|
||||||
|
return new BigNumber(value);
|
||||||
|
});
|
||||||
});
|
});
|
||||||
return result;
|
return result;
|
||||||
},
|
},
|
||||||
|
@ -1,32 +1,32 @@
|
|||||||
import * as _ from 'lodash';
|
import * as _ from 'lodash';
|
||||||
|
import { v4 as uuid } from 'uuid';
|
||||||
import * as WebSocket from 'websocket';
|
import * as WebSocket from 'websocket';
|
||||||
|
|
||||||
import {
|
import { OrdersChannel, OrdersChannelHandler, OrdersChannelMessageTypes, OrdersChannelSubscriptionOpts } from './types';
|
||||||
OrderbookChannel,
|
|
||||||
OrderbookChannelHandler,
|
|
||||||
OrderbookChannelMessageTypes,
|
|
||||||
OrderbookChannelSubscriptionOpts,
|
|
||||||
} from './types';
|
|
||||||
import { assert } from './utils/assert';
|
import { assert } from './utils/assert';
|
||||||
import { orderbookChannelMessageParser } from './utils/orderbook_channel_message_parser';
|
import { ordersChannelMessageParser } from './utils/orders_channel_message_parser';
|
||||||
|
|
||||||
|
export interface OrdersChannelSubscriptionOptsMap {
|
||||||
|
[key: string]: OrdersChannelSubscriptionOpts;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This class includes all the functionality related to interacting with a websocket endpoint
|
* This class includes all the functionality related to interacting with a websocket endpoint
|
||||||
* that implements the standard relayer API v0
|
* that implements the standard relayer API v0
|
||||||
*/
|
*/
|
||||||
export class WebSocketOrderbookChannel implements OrderbookChannel {
|
export class WebSocketOrdersChannel implements OrdersChannel {
|
||||||
private readonly _client: WebSocket.w3cwebsocket;
|
private readonly _client: WebSocket.w3cwebsocket;
|
||||||
private readonly _handler: OrderbookChannelHandler;
|
private readonly _handler: OrdersChannelHandler;
|
||||||
private readonly _subscriptionOptsList: OrderbookChannelSubscriptionOpts[] = [];
|
private readonly _subscriptionOptsMap: OrdersChannelSubscriptionOptsMap = {};
|
||||||
/**
|
/**
|
||||||
* Instantiates a new WebSocketOrderbookChannel instance
|
* Instantiates a new WebSocketOrdersChannel instance
|
||||||
* @param client A WebSocket client
|
* @param client A WebSocket client
|
||||||
* @param handler An OrderbookChannelHandler instance that responds to various
|
* @param handler An OrdersChannelHandler instance that responds to various
|
||||||
* channel updates
|
* channel updates
|
||||||
* @return An instance of WebSocketOrderbookChannel
|
* @return An instance of WebSocketOrdersChannel
|
||||||
*/
|
*/
|
||||||
constructor(client: WebSocket.w3cwebsocket, handler: OrderbookChannelHandler) {
|
constructor(client: WebSocket.w3cwebsocket, handler: OrdersChannelHandler) {
|
||||||
assert.isOrderbookChannelHandler('handler', handler);
|
assert.isOrdersChannelHandler('handler', handler);
|
||||||
// set private members
|
// set private members
|
||||||
this._client = client;
|
this._client = client;
|
||||||
this._handler = handler;
|
this._handler = handler;
|
||||||
@ -43,18 +43,18 @@ export class WebSocketOrderbookChannel implements OrderbookChannel {
|
|||||||
}
|
}
|
||||||
/**
|
/**
|
||||||
* Subscribe to orderbook snapshots and updates from the websocket
|
* Subscribe to orderbook snapshots and updates from the websocket
|
||||||
* @param subscriptionOpts An OrderbookChannelSubscriptionOpts instance describing which
|
* @param subscriptionOpts An OrdersChannelSubscriptionOpts instance describing which
|
||||||
* token pair to subscribe to
|
* assetData pair to subscribe to
|
||||||
*/
|
*/
|
||||||
public subscribe(subscriptionOpts: OrderbookChannelSubscriptionOpts): void {
|
public subscribe(subscriptionOpts: OrdersChannelSubscriptionOpts): void {
|
||||||
assert.isOrderbookChannelSubscriptionOpts('subscriptionOpts', subscriptionOpts);
|
assert.isOrdersChannelSubscriptionOpts('subscriptionOpts', subscriptionOpts);
|
||||||
assert.assert(this._client.readyState === WebSocket.w3cwebsocket.OPEN, 'WebSocket connection is closed');
|
assert.assert(this._client.readyState === WebSocket.w3cwebsocket.OPEN, 'WebSocket connection is closed');
|
||||||
this._subscriptionOptsList.push(subscriptionOpts);
|
const requestId = uuid();
|
||||||
// TODO: update requestId management to use UUIDs for v2
|
this._subscriptionOptsMap[requestId] = subscriptionOpts;
|
||||||
const subscribeMessage = {
|
const subscribeMessage = {
|
||||||
type: 'subscribe',
|
type: 'subscribe',
|
||||||
channel: 'orderbook',
|
channel: 'orders',
|
||||||
requestId: this._subscriptionOptsList.length - 1,
|
requestId,
|
||||||
payload: subscriptionOpts,
|
payload: subscriptionOpts,
|
||||||
};
|
};
|
||||||
this._client.send(JSON.stringify(subscribeMessage));
|
this._client.send(JSON.stringify(subscribeMessage));
|
||||||
@ -72,8 +72,8 @@ export class WebSocketOrderbookChannel implements OrderbookChannel {
|
|||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
const data = message.data;
|
const data = message.data;
|
||||||
const parserResult = orderbookChannelMessageParser.parse(data);
|
const parserResult = ordersChannelMessageParser.parse(data);
|
||||||
const subscriptionOpts = this._subscriptionOptsList[parserResult.requestId];
|
const subscriptionOpts = this._subscriptionOptsMap[parserResult.requestId];
|
||||||
if (_.isUndefined(subscriptionOpts)) {
|
if (_.isUndefined(subscriptionOpts)) {
|
||||||
this._handler.onError(
|
this._handler.onError(
|
||||||
this,
|
this,
|
||||||
@ -82,11 +82,7 @@ export class WebSocketOrderbookChannel implements OrderbookChannel {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
switch (parserResult.type) {
|
switch (parserResult.type) {
|
||||||
case OrderbookChannelMessageTypes.Snapshot: {
|
case OrdersChannelMessageTypes.Update: {
|
||||||
this._handler.onSnapshot(this, subscriptionOpts, parserResult.payload);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case OrderbookChannelMessageTypes.Update: {
|
|
||||||
this._handler.onUpdate(this, subscriptionOpts, parserResult.payload);
|
this._handler.onUpdate(this, subscriptionOpts, parserResult.payload);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
21
packages/connect/test/fixtures/standard_relayer_api/asset_pairs.json
vendored
Normal file
21
packages/connect/test/fixtures/standard_relayer_api/asset_pairs.json
vendored
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
{
|
||||||
|
"total": 43,
|
||||||
|
"page": 1,
|
||||||
|
"perPage": 100,
|
||||||
|
"records": [
|
||||||
|
{
|
||||||
|
"assetDataA": {
|
||||||
|
"minAmount": "0",
|
||||||
|
"maxAmount": "10000000000000000000",
|
||||||
|
"precision": 5,
|
||||||
|
"assetData": "0xf47261b04c32345ced77393b3530b1eed0f346429d"
|
||||||
|
},
|
||||||
|
"assetDataB": {
|
||||||
|
"minAmount": "0",
|
||||||
|
"maxAmount": "50000000000000000000",
|
||||||
|
"precision": 5,
|
||||||
|
"assetData": "0x0257179264389b814a946f3e92105513705ca6b990"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
25
packages/connect/test/fixtures/standard_relayer_api/asset_pairs.ts
vendored
Normal file
25
packages/connect/test/fixtures/standard_relayer_api/asset_pairs.ts
vendored
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
import { BigNumber } from '@0xproject/utils';
|
||||||
|
|
||||||
|
import { AssetPairsResponse } from '../../../src/types';
|
||||||
|
|
||||||
|
export const assetDataPairsResponse: AssetPairsResponse = {
|
||||||
|
total: 43,
|
||||||
|
page: 1,
|
||||||
|
perPage: 100,
|
||||||
|
records: [
|
||||||
|
{
|
||||||
|
assetDataA: {
|
||||||
|
minAmount: new BigNumber('0'),
|
||||||
|
maxAmount: new BigNumber('10000000000000000000'),
|
||||||
|
precision: 5,
|
||||||
|
assetData: '0xf47261b04c32345ced77393b3530b1eed0f346429d',
|
||||||
|
},
|
||||||
|
assetDataB: {
|
||||||
|
minAmount: new BigNumber('0'),
|
||||||
|
maxAmount: new BigNumber('50000000000000000000'),
|
||||||
|
precision: 5,
|
||||||
|
assetData: '0x0257179264389b814a946f3e92105513705ca6b990',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
],
|
||||||
|
};
|
10
packages/connect/test/fixtures/standard_relayer_api/fee_recipients.json
vendored
Normal file
10
packages/connect/test/fixtures/standard_relayer_api/fee_recipients.json
vendored
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
{
|
||||||
|
"total": 3,
|
||||||
|
"page": 1,
|
||||||
|
"perPage": 10,
|
||||||
|
"records": [
|
||||||
|
"0x6ec92694ea172ebc430c30fa31de87620967a082",
|
||||||
|
"0x9e56625509c2f60af937f23b7b532600390e8c8b",
|
||||||
|
"0xa2b31dacf30a9c50ca473337c01d8a201ae33e32"
|
||||||
|
]
|
||||||
|
}
|
12
packages/connect/test/fixtures/standard_relayer_api/fee_recipients.ts
vendored
Normal file
12
packages/connect/test/fixtures/standard_relayer_api/fee_recipients.ts
vendored
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
import { FeeRecipientsResponse } from '../../../src/types';
|
||||||
|
|
||||||
|
export const feeRecipientsResponse: FeeRecipientsResponse = {
|
||||||
|
total: 3,
|
||||||
|
page: 1,
|
||||||
|
perPage: 10,
|
||||||
|
records: [
|
||||||
|
'0x6ec92694ea172ebc430c30fa31de87620967a082',
|
||||||
|
'0x9e56625509c2f60af937f23b7b532600390e8c8b',
|
||||||
|
'0xa2b31dacf30a9c50ca473337c01d8a201ae33e32',
|
||||||
|
],
|
||||||
|
};
|
@ -1,5 +0,0 @@
|
|||||||
{
|
|
||||||
"feeRecipient": "0x323b5d4c32345ced77393b3530b1eed0f346429d",
|
|
||||||
"makerFee": "10000000000000000",
|
|
||||||
"takerFee": "30000000000000000"
|
|
||||||
}
|
|
@ -1,9 +0,0 @@
|
|||||||
import { BigNumber } from '@0xproject/utils';
|
|
||||||
|
|
||||||
import { FeesResponse } from '../../../src/types';
|
|
||||||
|
|
||||||
export const feesResponse: FeesResponse = {
|
|
||||||
feeRecipient: '0x323b5d4c32345ced77393b3530b1eed0f346429d',
|
|
||||||
makerFee: new BigNumber('10000000000000000'),
|
|
||||||
takerFee: new BigNumber('30000000000000000'),
|
|
||||||
};
|
|
@ -1,19 +1,19 @@
|
|||||||
{
|
{
|
||||||
"maker": "0x9e56625509c2f60af937f23b7b532600390e8c8b",
|
"order": {
|
||||||
"taker": "0xa2b31dacf30a9c50ca473337c01d8a201ae33e32",
|
"makerAddress": "0x9e56625509c2f60af937f23b7b532600390e8c8b",
|
||||||
|
"takerAddress": "0xa2b31dacf30a9c50ca473337c01d8a201ae33e32",
|
||||||
|
"feeRecipientAddress": "0xb046140686d052fff581f63f8136cce132e857da",
|
||||||
|
"senderAddress": "0xa2b31dacf30a9c50ca473337c01d8a201ae33e32",
|
||||||
|
"makerAssetAmount": "10000000000000000",
|
||||||
|
"takerAssetAmount": "20000000000000000",
|
||||||
"makerFee": "100000000000000",
|
"makerFee": "100000000000000",
|
||||||
"takerFee": "200000000000000",
|
"takerFee": "200000000000000",
|
||||||
"makerTokenAmount": "10000000000000000",
|
"expirationTimeSeconds": "1532560590",
|
||||||
"takerTokenAmount": "20000000000000000",
|
"salt": "1532559225",
|
||||||
"makerTokenAddress": "0x323b5d4c32345ced77393b3530b1eed0f346429d",
|
"makerAssetData": "0xf47261b04c32345ced77393b3530b1eed0f346429d",
|
||||||
"takerTokenAddress": "0xef7fff64389b814a946f3e92105513705ca6b990",
|
"takerAssetData": "0x0257179264389b814a946f3e92105513705ca6b990",
|
||||||
"salt": "256",
|
"exchangeAddress": "0x12459c951127e0c374ff9105dda097662a027093",
|
||||||
"feeRecipient": "0xb046140686d052fff581f63f8136cce132e857da",
|
"signature": "0x012761a3ed31b43c8780e905a260a35faefcc527be7516aa11c0256729b5b351bc33"
|
||||||
"exchangeContractAddress": "0x12459c951127e0c374ff9105dda097662a027093",
|
},
|
||||||
"expirationUnixTimestampSec": "42",
|
"metaData": {}
|
||||||
"ecSignature": {
|
|
||||||
"v": 27,
|
|
||||||
"r": "0x61a3ed31b43c8780e905a260a35faefcc527be7516aa11c0256729b5b351bc33",
|
|
||||||
"s": "0x40349190569279751135161d22529dc25add4f6069af05be04cacbda2ace2254"
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -1,21 +1,21 @@
|
|||||||
import { BigNumber } from '@0xproject/utils';
|
import { BigNumber } from '@0xproject/utils';
|
||||||
|
|
||||||
export const orderResponse = {
|
export const orderResponse = {
|
||||||
maker: '0x9e56625509c2f60af937f23b7b532600390e8c8b',
|
order: {
|
||||||
taker: '0xa2b31dacf30a9c50ca473337c01d8a201ae33e32',
|
makerAddress: '0x9e56625509c2f60af937f23b7b532600390e8c8b',
|
||||||
|
takerAddress: '0xa2b31dacf30a9c50ca473337c01d8a201ae33e32',
|
||||||
|
feeRecipientAddress: '0xb046140686d052fff581f63f8136cce132e857da',
|
||||||
|
senderAddress: '0xa2b31dacf30a9c50ca473337c01d8a201ae33e32',
|
||||||
|
makerAssetAmount: new BigNumber('10000000000000000'),
|
||||||
|
takerAssetAmount: new BigNumber('20000000000000000'),
|
||||||
makerFee: new BigNumber('100000000000000'),
|
makerFee: new BigNumber('100000000000000'),
|
||||||
takerFee: new BigNumber('200000000000000'),
|
takerFee: new BigNumber('200000000000000'),
|
||||||
makerTokenAmount: new BigNumber('10000000000000000'),
|
expirationTimeSeconds: new BigNumber('1532560590'),
|
||||||
takerTokenAmount: new BigNumber('20000000000000000'),
|
salt: new BigNumber('1532559225'),
|
||||||
makerTokenAddress: '0x323b5d4c32345ced77393b3530b1eed0f346429d',
|
makerAssetData: '0xf47261b04c32345ced77393b3530b1eed0f346429d',
|
||||||
takerTokenAddress: '0xef7fff64389b814a946f3e92105513705ca6b990',
|
takerAssetData: '0x0257179264389b814a946f3e92105513705ca6b990',
|
||||||
salt: new BigNumber('256'),
|
exchangeAddress: '0x12459c951127e0c374ff9105dda097662a027093',
|
||||||
feeRecipient: '0xb046140686d052fff581f63f8136cce132e857da',
|
signature: '0x012761a3ed31b43c8780e905a260a35faefcc527be7516aa11c0256729b5b351bc33',
|
||||||
exchangeContractAddress: '0x12459c951127e0c374ff9105dda097662a027093',
|
|
||||||
expirationUnixTimestampSec: new BigNumber('42'),
|
|
||||||
ecSignature: {
|
|
||||||
v: 27,
|
|
||||||
r: '0x61a3ed31b43c8780e905a260a35faefcc527be7516aa11c0256729b5b351bc33',
|
|
||||||
s: '0x40349190569279751135161d22529dc25add4f6069af05be04cacbda2ace2254',
|
|
||||||
},
|
},
|
||||||
|
metaData: {},
|
||||||
};
|
};
|
||||||
|
6
packages/connect/test/fixtures/standard_relayer_api/order_config.json
vendored
Normal file
6
packages/connect/test/fixtures/standard_relayer_api/order_config.json
vendored
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
{
|
||||||
|
"senderAddress": "0xa2b31dacf30a9c50ca473337c01d8a201ae33e32",
|
||||||
|
"feeRecipientAddress": "0xb046140686d052fff581f63f8136cce132e857da",
|
||||||
|
"makerFee": "100000000000000",
|
||||||
|
"takerFee": "200000000000000"
|
||||||
|
}
|
10
packages/connect/test/fixtures/standard_relayer_api/order_config.ts
vendored
Normal file
10
packages/connect/test/fixtures/standard_relayer_api/order_config.ts
vendored
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
import { BigNumber } from '@0xproject/utils';
|
||||||
|
|
||||||
|
import { OrderConfigResponse } from '../../../src/types';
|
||||||
|
|
||||||
|
export const orderConfigResponse: OrderConfigResponse = {
|
||||||
|
senderAddress: '0xa2b31dacf30a9c50ca473337c01d8a201ae33e32',
|
||||||
|
feeRecipientAddress: '0xb046140686d052fff581f63f8136cce132e857da',
|
||||||
|
makerFee: new BigNumber('100000000000000'),
|
||||||
|
takerFee: new BigNumber('200000000000000'),
|
||||||
|
};
|
@ -1,44 +1,54 @@
|
|||||||
{
|
{
|
||||||
"bids": [
|
"bids": {
|
||||||
|
"total": 325,
|
||||||
|
"page": 2,
|
||||||
|
"perPage": 100,
|
||||||
|
"records": [
|
||||||
{
|
{
|
||||||
"maker": "0x9e56625509c2f60af937f23b7b532600390e8c8b",
|
"order": {
|
||||||
"taker": "0xa2b31dacf30a9c50ca473337c01d8a201ae33e32",
|
"makerAddress": "0x9e56625509c2f60af937f23b7b532600390e8c8b",
|
||||||
|
"takerAddress": "0xa2b31dacf30a9c50ca473337c01d8a201ae33e32",
|
||||||
|
"feeRecipientAddress": "0xb046140686d052fff581f63f8136cce132e857da",
|
||||||
|
"senderAddress": "0xa2b31dacf30a9c50ca473337c01d8a201ae33e32",
|
||||||
|
"makerAssetAmount": "10000000000000000",
|
||||||
|
"takerAssetAmount": "20000000000000000",
|
||||||
"makerFee": "100000000000000",
|
"makerFee": "100000000000000",
|
||||||
"takerFee": "200000000000000",
|
"takerFee": "200000000000000",
|
||||||
"makerTokenAmount": "10000000000000000",
|
"expirationTimeSeconds": "1532560590",
|
||||||
"takerTokenAmount": "20000000000000000",
|
"salt": "1532559225",
|
||||||
"makerTokenAddress": "0x323b5d4c32345ced77393b3530b1eed0f346429d",
|
"makerAssetData": "0xf47261b04c32345ced77393b3530b1eed0f346429d",
|
||||||
"takerTokenAddress": "0xef7fff64389b814a946f3e92105513705ca6b990",
|
"takerAssetData": "0x0257179264389b814a946f3e92105513705ca6b990",
|
||||||
"salt": "256",
|
"exchangeAddress": "0x12459c951127e0c374ff9105dda097662a027093",
|
||||||
"feeRecipient": "0xb046140686d052fff581f63f8136cce132e857da",
|
"signature": "0x012761a3ed31b43c8780e905a260a35faefcc527be7516aa11c0256729b5b351bc33"
|
||||||
"exchangeContractAddress": "0x12459c951127e0c374ff9105dda097662a027093",
|
},
|
||||||
"expirationUnixTimestampSec": "42",
|
"metaData": {}
|
||||||
"ecSignature": {
|
|
||||||
"v": 27,
|
|
||||||
"r": "0x61a3ed31b43c8780e905a260a35faefcc527be7516aa11c0256729b5b351bc33",
|
|
||||||
"s": "0x40349190569279751135161d22529dc25add4f6069af05be04cacbda2ace2254"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"asks": [
|
|
||||||
{
|
|
||||||
"maker": "0x9e56625509c2f60af937f23b7b532600390e8c8b",
|
|
||||||
"taker": "0xa2b31dacf30a9c50ca473337c01d8a201ae33e32",
|
|
||||||
"makerFee": "100000000000000",
|
|
||||||
"takerFee": "200000000000000",
|
|
||||||
"makerTokenAmount": "10000000000000000",
|
|
||||||
"takerTokenAmount": "20000000000000000",
|
|
||||||
"makerTokenAddress": "0x323b5d4c32345ced77393b3530b1eed0f346429d",
|
|
||||||
"takerTokenAddress": "0xef7fff64389b814a946f3e92105513705ca6b990",
|
|
||||||
"salt": "256",
|
|
||||||
"feeRecipient": "0xb046140686d052fff581f63f8136cce132e857da",
|
|
||||||
"exchangeContractAddress": "0x12459c951127e0c374ff9105dda097662a027093",
|
|
||||||
"expirationUnixTimestampSec": "42",
|
|
||||||
"ecSignature": {
|
|
||||||
"v": 27,
|
|
||||||
"r": "0x61a3ed31b43c8780e905a260a35faefcc527be7516aa11c0256729b5b351bc33",
|
|
||||||
"s": "0x40349190569279751135161d22529dc25add4f6069af05be04cacbda2ace2254"
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
},
|
||||||
|
"asks": {
|
||||||
|
"total": 500,
|
||||||
|
"page": 2,
|
||||||
|
"perPage": 100,
|
||||||
|
"records": [
|
||||||
|
{
|
||||||
|
"order": {
|
||||||
|
"makerAddress": "0xa2b31dacf30a9c50ca473337c01d8a201ae33e32",
|
||||||
|
"takerAddress": "0x9e56625509c2f60af937f23b7b532600390e8c8b",
|
||||||
|
"feeRecipientAddress": "0xb046140686d052fff581f63f8136cce132e857da",
|
||||||
|
"senderAddress": "0xa2b31dacf30a9c50ca473337c01d8a201ae33e32",
|
||||||
|
"makerAssetAmount": "20000000000000000",
|
||||||
|
"takerAssetAmount": "10000000000000000",
|
||||||
|
"makerFee": "200000000000000",
|
||||||
|
"takerFee": "100000000000000",
|
||||||
|
"expirationTimeSeconds": "1532560590",
|
||||||
|
"salt": "1532559225",
|
||||||
|
"makerAssetData": "0x0257179264389b814a946f3e92105513705ca6b990",
|
||||||
|
"takerAssetData": "0xf47261b04c32345ced77393b3530b1eed0f346429d",
|
||||||
|
"exchangeAddress": "0x12459c951127e0c374ff9105dda097662a027093",
|
||||||
|
"signature": "0x013842a3ed31b43c8780e905a260a35faefcc527be7516aa11c0256729b5b3518891"
|
||||||
|
},
|
||||||
|
"metaData": {}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,46 +1,58 @@
|
|||||||
import { BigNumber } from '@0xproject/utils';
|
import { BigNumber } from '@0xproject/utils';
|
||||||
|
|
||||||
export const orderbookResponse = {
|
import { OrderbookResponse } from '../../../src/types';
|
||||||
bids: [
|
|
||||||
|
export const orderbookResponse: OrderbookResponse = {
|
||||||
|
bids: {
|
||||||
|
total: 325,
|
||||||
|
page: 2,
|
||||||
|
perPage: 100,
|
||||||
|
records: [
|
||||||
{
|
{
|
||||||
maker: '0x9e56625509c2f60af937f23b7b532600390e8c8b',
|
order: {
|
||||||
taker: '0xa2b31dacf30a9c50ca473337c01d8a201ae33e32',
|
makerAddress: '0x9e56625509c2f60af937f23b7b532600390e8c8b',
|
||||||
|
takerAddress: '0xa2b31dacf30a9c50ca473337c01d8a201ae33e32',
|
||||||
|
feeRecipientAddress: '0xb046140686d052fff581f63f8136cce132e857da',
|
||||||
|
senderAddress: '0xa2b31dacf30a9c50ca473337c01d8a201ae33e32',
|
||||||
|
makerAssetAmount: new BigNumber('10000000000000000'),
|
||||||
|
takerAssetAmount: new BigNumber('20000000000000000'),
|
||||||
makerFee: new BigNumber('100000000000000'),
|
makerFee: new BigNumber('100000000000000'),
|
||||||
takerFee: new BigNumber('200000000000000'),
|
takerFee: new BigNumber('200000000000000'),
|
||||||
makerTokenAmount: new BigNumber('10000000000000000'),
|
expirationTimeSeconds: new BigNumber('1532560590'),
|
||||||
takerTokenAmount: new BigNumber('20000000000000000'),
|
salt: new BigNumber('1532559225'),
|
||||||
makerTokenAddress: '0x323b5d4c32345ced77393b3530b1eed0f346429d',
|
makerAssetData: '0xf47261b04c32345ced77393b3530b1eed0f346429d',
|
||||||
takerTokenAddress: '0xef7fff64389b814a946f3e92105513705ca6b990',
|
takerAssetData: '0x0257179264389b814a946f3e92105513705ca6b990',
|
||||||
salt: new BigNumber('256'),
|
exchangeAddress: '0x12459c951127e0c374ff9105dda097662a027093',
|
||||||
feeRecipient: '0xb046140686d052fff581f63f8136cce132e857da',
|
signature: '0x012761a3ed31b43c8780e905a260a35faefcc527be7516aa11c0256729b5b351bc33',
|
||||||
exchangeContractAddress: '0x12459c951127e0c374ff9105dda097662a027093',
|
|
||||||
expirationUnixTimestampSec: new BigNumber('42'),
|
|
||||||
ecSignature: {
|
|
||||||
v: 27,
|
|
||||||
r: '0x61a3ed31b43c8780e905a260a35faefcc527be7516aa11c0256729b5b351bc33',
|
|
||||||
s: '0x40349190569279751135161d22529dc25add4f6069af05be04cacbda2ace2254',
|
|
||||||
},
|
},
|
||||||
|
metaData: {},
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
asks: [
|
},
|
||||||
|
asks: {
|
||||||
|
total: 500,
|
||||||
|
page: 2,
|
||||||
|
perPage: 100,
|
||||||
|
records: [
|
||||||
{
|
{
|
||||||
maker: '0x9e56625509c2f60af937f23b7b532600390e8c8b',
|
order: {
|
||||||
taker: '0xa2b31dacf30a9c50ca473337c01d8a201ae33e32',
|
makerAddress: '0xa2b31dacf30a9c50ca473337c01d8a201ae33e32',
|
||||||
makerFee: new BigNumber('100000000000000'),
|
takerAddress: '0x9e56625509c2f60af937f23b7b532600390e8c8b',
|
||||||
takerFee: new BigNumber('200000000000000'),
|
feeRecipientAddress: '0xb046140686d052fff581f63f8136cce132e857da',
|
||||||
makerTokenAmount: new BigNumber('10000000000000000'),
|
senderAddress: '0xa2b31dacf30a9c50ca473337c01d8a201ae33e32',
|
||||||
takerTokenAmount: new BigNumber('20000000000000000'),
|
makerAssetAmount: new BigNumber('20000000000000000'),
|
||||||
makerTokenAddress: '0x323b5d4c32345ced77393b3530b1eed0f346429d',
|
takerAssetAmount: new BigNumber('10000000000000000'),
|
||||||
takerTokenAddress: '0xef7fff64389b814a946f3e92105513705ca6b990',
|
makerFee: new BigNumber('200000000000000'),
|
||||||
salt: new BigNumber('256'),
|
takerFee: new BigNumber('100000000000000'),
|
||||||
feeRecipient: '0xb046140686d052fff581f63f8136cce132e857da',
|
expirationTimeSeconds: new BigNumber('1532560590'),
|
||||||
exchangeContractAddress: '0x12459c951127e0c374ff9105dda097662a027093',
|
salt: new BigNumber('1532559225'),
|
||||||
expirationUnixTimestampSec: new BigNumber('42'),
|
makerAssetData: '0x0257179264389b814a946f3e92105513705ca6b990',
|
||||||
ecSignature: {
|
takerAssetData: '0xf47261b04c32345ced77393b3530b1eed0f346429d',
|
||||||
v: 27,
|
exchangeAddress: '0x12459c951127e0c374ff9105dda097662a027093',
|
||||||
r: '0x61a3ed31b43c8780e905a260a35faefcc527be7516aa11c0256729b5b351bc33',
|
signature: '0x013842a3ed31b43c8780e905a260a35faefcc527be7516aa11c0256729b5b3518891',
|
||||||
s: '0x40349190569279751135161d22529dc25add4f6069af05be04cacbda2ace2254',
|
|
||||||
},
|
},
|
||||||
|
metaData: {},
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
|
},
|
||||||
};
|
};
|
||||||
|
@ -1,21 +1,26 @@
|
|||||||
[
|
{
|
||||||
|
"total": 984,
|
||||||
|
"page": 1,
|
||||||
|
"perPage": 100,
|
||||||
|
"records": [
|
||||||
{
|
{
|
||||||
"maker": "0x9e56625509c2f60af937f23b7b532600390e8c8b",
|
"order": {
|
||||||
"taker": "0xa2b31dacf30a9c50ca473337c01d8a201ae33e32",
|
"makerAddress": "0x9e56625509c2f60af937f23b7b532600390e8c8b",
|
||||||
|
"takerAddress": "0xa2b31dacf30a9c50ca473337c01d8a201ae33e32",
|
||||||
|
"feeRecipientAddress": "0xb046140686d052fff581f63f8136cce132e857da",
|
||||||
|
"senderAddress": "0xa2b31dacf30a9c50ca473337c01d8a201ae33e32",
|
||||||
|
"makerAssetAmount": "10000000000000000",
|
||||||
|
"takerAssetAmount": "20000000000000000",
|
||||||
"makerFee": "100000000000000",
|
"makerFee": "100000000000000",
|
||||||
"takerFee": "200000000000000",
|
"takerFee": "200000000000000",
|
||||||
"makerTokenAmount": "10000000000000000",
|
"expirationTimeSeconds": "1532560590",
|
||||||
"takerTokenAmount": "20000000000000000",
|
"salt": "1532559225",
|
||||||
"makerTokenAddress": "0x323b5d4c32345ced77393b3530b1eed0f346429d",
|
"makerAssetData": "0xf47261b04c32345ced77393b3530b1eed0f346429d",
|
||||||
"takerTokenAddress": "0xef7fff64389b814a946f3e92105513705ca6b990",
|
"takerAssetData": "0x0257179264389b814a946f3e92105513705ca6b990",
|
||||||
"salt": "256",
|
"exchangeAddress": "0x12459c951127e0c374ff9105dda097662a027093",
|
||||||
"feeRecipient": "0x9e56625509c2f60af937f23b7b532600390e8c8b",
|
"signature": "0x012761a3ed31b43c8780e905a260a35faefcc527be7516aa11c0256729b5b351bc33"
|
||||||
"exchangeContractAddress": "0x9e56625509c2f60af937f23b7b532600390e8c8b",
|
},
|
||||||
"expirationUnixTimestampSec": "42",
|
"metaData": {}
|
||||||
"ecSignature": {
|
|
||||||
"v": 27,
|
|
||||||
"r": "0x61a3ed31b43c8780e905a260a35faefcc527be7516aa11c0256729b5b351bc33",
|
|
||||||
"s": "0x40349190569279751135161d22529dc25add4f6069af05be04cacbda2ace2254"
|
|
||||||
}
|
}
|
||||||
}
|
]
|
||||||
]
|
}
|
||||||
|
@ -1,23 +1,30 @@
|
|||||||
import { BigNumber } from '@0xproject/utils';
|
import { BigNumber } from '@0xproject/utils';
|
||||||
|
|
||||||
export const ordersResponse = [
|
import { OrdersResponse } from '../../../src/types';
|
||||||
|
|
||||||
|
export const ordersResponse: OrdersResponse = {
|
||||||
|
total: 984,
|
||||||
|
page: 1,
|
||||||
|
perPage: 100,
|
||||||
|
records: [
|
||||||
{
|
{
|
||||||
maker: '0x9e56625509c2f60af937f23b7b532600390e8c8b',
|
order: {
|
||||||
taker: '0xa2b31dacf30a9c50ca473337c01d8a201ae33e32',
|
makerAddress: '0x9e56625509c2f60af937f23b7b532600390e8c8b',
|
||||||
|
takerAddress: '0xa2b31dacf30a9c50ca473337c01d8a201ae33e32',
|
||||||
|
feeRecipientAddress: '0xb046140686d052fff581f63f8136cce132e857da',
|
||||||
|
senderAddress: '0xa2b31dacf30a9c50ca473337c01d8a201ae33e32',
|
||||||
|
makerAssetAmount: new BigNumber('10000000000000000'),
|
||||||
|
takerAssetAmount: new BigNumber('20000000000000000'),
|
||||||
makerFee: new BigNumber('100000000000000'),
|
makerFee: new BigNumber('100000000000000'),
|
||||||
takerFee: new BigNumber('200000000000000'),
|
takerFee: new BigNumber('200000000000000'),
|
||||||
makerTokenAmount: new BigNumber('10000000000000000'),
|
expirationTimeSeconds: new BigNumber('1532560590'),
|
||||||
takerTokenAmount: new BigNumber('20000000000000000'),
|
salt: new BigNumber('1532559225'),
|
||||||
makerTokenAddress: '0x323b5d4c32345ced77393b3530b1eed0f346429d',
|
makerAssetData: '0xf47261b04c32345ced77393b3530b1eed0f346429d',
|
||||||
takerTokenAddress: '0xef7fff64389b814a946f3e92105513705ca6b990',
|
takerAssetData: '0x0257179264389b814a946f3e92105513705ca6b990',
|
||||||
salt: new BigNumber('256'),
|
exchangeAddress: '0x12459c951127e0c374ff9105dda097662a027093',
|
||||||
feeRecipient: '0x9e56625509c2f60af937f23b7b532600390e8c8b',
|
signature: '0x012761a3ed31b43c8780e905a260a35faefcc527be7516aa11c0256729b5b351bc33',
|
||||||
exchangeContractAddress: '0x9e56625509c2f60af937f23b7b532600390e8c8b',
|
|
||||||
expirationUnixTimestampSec: new BigNumber('42'),
|
|
||||||
ecSignature: {
|
|
||||||
v: 27,
|
|
||||||
r: '0x61a3ed31b43c8780e905a260a35faefcc527be7516aa11c0256729b5b351bc33',
|
|
||||||
s: '0x40349190569279751135161d22529dc25add4f6069af05be04cacbda2ace2254',
|
|
||||||
},
|
},
|
||||||
|
metaData: {},
|
||||||
},
|
},
|
||||||
];
|
],
|
||||||
|
};
|
||||||
|
@ -1,17 +0,0 @@
|
|||||||
import * as orderbookJSON from './orderbook.json';
|
|
||||||
|
|
||||||
const orderbookJsonString = JSON.stringify(orderbookJSON);
|
|
||||||
|
|
||||||
export const snapshotOrderbookChannelMessage = `{
|
|
||||||
"type": "snapshot",
|
|
||||||
"channel": "orderbook",
|
|
||||||
"requestId": 1,
|
|
||||||
"payload": ${orderbookJsonString}
|
|
||||||
}`;
|
|
||||||
|
|
||||||
export const malformedSnapshotOrderbookChannelMessage = `{
|
|
||||||
"type": "snapshot",
|
|
||||||
"channel": "orderbook",
|
|
||||||
"requestId": 1,
|
|
||||||
"payload": {}
|
|
||||||
}`;
|
|
@ -1,16 +0,0 @@
|
|||||||
[
|
|
||||||
{
|
|
||||||
"tokenA": {
|
|
||||||
"address": "0x323b5d4c32345ced77393b3530b1eed0f346429d",
|
|
||||||
"minAmount": "0",
|
|
||||||
"maxAmount": "10000000000000000000",
|
|
||||||
"precision": 5
|
|
||||||
},
|
|
||||||
"tokenB": {
|
|
||||||
"address": "0xef7fff64389b814a946f3e92105513705ca6b990",
|
|
||||||
"minAmount": "0",
|
|
||||||
"maxAmount": "50000000000000000000",
|
|
||||||
"precision": 5
|
|
||||||
}
|
|
||||||
}
|
|
||||||
]
|
|
@ -1,20 +0,0 @@
|
|||||||
import { BigNumber } from '@0xproject/utils';
|
|
||||||
|
|
||||||
import { TokenPairsItem } from '../../../src/types';
|
|
||||||
|
|
||||||
export const tokenPairsResponse: TokenPairsItem[] = [
|
|
||||||
{
|
|
||||||
tokenA: {
|
|
||||||
address: '0x323b5d4c32345ced77393b3530b1eed0f346429d',
|
|
||||||
minAmount: new BigNumber(0),
|
|
||||||
maxAmount: new BigNumber('10000000000000000000'),
|
|
||||||
precision: 5,
|
|
||||||
},
|
|
||||||
tokenB: {
|
|
||||||
address: '0xef7fff64389b814a946f3e92105513705ca6b990',
|
|
||||||
minAmount: new BigNumber(0),
|
|
||||||
maxAmount: new BigNumber('50000000000000000000'),
|
|
||||||
precision: 5,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
];
|
|
@ -2,9 +2,9 @@ import * as orderResponseJSON from './order/0xabc67323774bdbd24d94f977fa9ac94a50
|
|||||||
|
|
||||||
const orderJSONString = JSON.stringify(orderResponseJSON);
|
const orderJSONString = JSON.stringify(orderResponseJSON);
|
||||||
|
|
||||||
export const unknownOrderbookChannelMessage = `{
|
export const unknownOrdersChannelMessage = `{
|
||||||
"type": "superGoodUpdate",
|
"type": "superGoodUpdate",
|
||||||
"channel": "orderbook",
|
"channel": "orderbook",
|
||||||
"requestId": 1,
|
"requestId": "6ce8c5a6-5c46-4027-a44a-51831c77b8a1",
|
||||||
"payload": ${orderJSONString}
|
"payload": [${orderJSONString}]
|
||||||
}`;
|
}`;
|
@ -1,17 +0,0 @@
|
|||||||
import * as orderResponseJSON from './order/0xabc67323774bdbd24d94f977fa9ac94a50f016026fd13f42990861238897721f.json';
|
|
||||||
|
|
||||||
const orderJSONString = JSON.stringify(orderResponseJSON);
|
|
||||||
|
|
||||||
export const updateOrderbookChannelMessage = `{
|
|
||||||
"type": "update",
|
|
||||||
"channel": "orderbook",
|
|
||||||
"requestId": 1,
|
|
||||||
"payload": ${orderJSONString}
|
|
||||||
}`;
|
|
||||||
|
|
||||||
export const malformedUpdateOrderbookChannelMessage = `{
|
|
||||||
"type": "update",
|
|
||||||
"channel": "orderbook",
|
|
||||||
"requestId": 1,
|
|
||||||
"payload": {}
|
|
||||||
}`;
|
|
17
packages/connect/test/fixtures/standard_relayer_api/update_orders_channel_message.ts
vendored
Normal file
17
packages/connect/test/fixtures/standard_relayer_api/update_orders_channel_message.ts
vendored
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
import * as apiOrderJSON from './order/0xabc67323774bdbd24d94f977fa9ac94a50f016026fd13f42990861238897721f.json';
|
||||||
|
|
||||||
|
const apiOrderJSONString = JSON.stringify(apiOrderJSON);
|
||||||
|
|
||||||
|
export const updateOrdersChannelMessage = `{
|
||||||
|
"type": "update",
|
||||||
|
"channel": "orders",
|
||||||
|
"requestId": "5a1ce3a2-22b9-41e6-a615-68077512e9e2",
|
||||||
|
"payload": [${apiOrderJSONString}]
|
||||||
|
}`;
|
||||||
|
|
||||||
|
export const malformedUpdateOrdersChannelMessage = `{
|
||||||
|
"type": "update",
|
||||||
|
"channel": "orders",
|
||||||
|
"requestId": "4d8efcee-adde-4475-9601-f0b30962ca2b",
|
||||||
|
"payload": {}
|
||||||
|
}`;
|
@ -1,4 +1,3 @@
|
|||||||
import { BigNumber } from '@0xproject/utils';
|
|
||||||
import * as chai from 'chai';
|
import * as chai from 'chai';
|
||||||
import * as chaiAsPromised from 'chai-as-promised';
|
import * as chaiAsPromised from 'chai-as-promised';
|
||||||
import * as dirtyChai from 'dirty-chai';
|
import * as dirtyChai from 'dirty-chai';
|
||||||
@ -7,16 +6,18 @@ import 'mocha';
|
|||||||
|
|
||||||
import { HttpClient } from '../src/index';
|
import { HttpClient } from '../src/index';
|
||||||
|
|
||||||
import { feesResponse } from './fixtures/standard_relayer_api/fees';
|
import { assetDataPairsResponse } from './fixtures/standard_relayer_api/asset_pairs';
|
||||||
import * as feesResponseJSON from './fixtures/standard_relayer_api/fees.json';
|
import * as assetDataPairsResponseJSON from './fixtures/standard_relayer_api/asset_pairs.json';
|
||||||
|
import { feeRecipientsResponse } from './fixtures/standard_relayer_api/fee_recipients';
|
||||||
|
import * as feeRecipientsResponseJSON from './fixtures/standard_relayer_api/fee_recipients.json';
|
||||||
import { orderResponse } from './fixtures/standard_relayer_api/order/0xabc67323774bdbd24d94f977fa9ac94a50f016026fd13f42990861238897721f';
|
import { orderResponse } from './fixtures/standard_relayer_api/order/0xabc67323774bdbd24d94f977fa9ac94a50f016026fd13f42990861238897721f';
|
||||||
import * as orderResponseJSON from './fixtures/standard_relayer_api/order/0xabc67323774bdbd24d94f977fa9ac94a50f016026fd13f42990861238897721f.json';
|
import * as orderResponseJSON from './fixtures/standard_relayer_api/order/0xabc67323774bdbd24d94f977fa9ac94a50f016026fd13f42990861238897721f.json';
|
||||||
|
import { orderConfigResponse } from './fixtures/standard_relayer_api/order_config';
|
||||||
|
import * as orderConfigResponseJSON from './fixtures/standard_relayer_api/order_config.json';
|
||||||
import { orderbookResponse } from './fixtures/standard_relayer_api/orderbook';
|
import { orderbookResponse } from './fixtures/standard_relayer_api/orderbook';
|
||||||
import * as orderbookJSON from './fixtures/standard_relayer_api/orderbook.json';
|
import * as orderbookJSON from './fixtures/standard_relayer_api/orderbook.json';
|
||||||
import { ordersResponse } from './fixtures/standard_relayer_api/orders';
|
import { ordersResponse } from './fixtures/standard_relayer_api/orders';
|
||||||
import * as ordersResponseJSON from './fixtures/standard_relayer_api/orders.json';
|
import * as ordersResponseJSON from './fixtures/standard_relayer_api/orders.json';
|
||||||
import { tokenPairsResponse } from './fixtures/standard_relayer_api/token_pairs';
|
|
||||||
import * as tokenPairsResponseJSON from './fixtures/standard_relayer_api/token_pairs.json';
|
|
||||||
|
|
||||||
chai.config.includeStack = true;
|
chai.config.includeStack = true;
|
||||||
chai.use(dirtyChai);
|
chai.use(dirtyChai);
|
||||||
@ -26,7 +27,7 @@ const expect = chai.expect;
|
|||||||
describe('HttpClient', () => {
|
describe('HttpClient', () => {
|
||||||
const relayUrl = 'https://example.com';
|
const relayUrl = 'https://example.com';
|
||||||
const relayerClient = new HttpClient(relayUrl);
|
const relayerClient = new HttpClient(relayUrl);
|
||||||
afterEach(() => {
|
beforeEach(() => {
|
||||||
fetchMock.restore();
|
fetchMock.restore();
|
||||||
});
|
});
|
||||||
describe('#constructor', () => {
|
describe('#constructor', () => {
|
||||||
@ -38,47 +39,47 @@ describe('HttpClient', () => {
|
|||||||
expect(sanitizedUrl).to.be.deep.equal(urlWithoutTrailingSlash);
|
expect(sanitizedUrl).to.be.deep.equal(urlWithoutTrailingSlash);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
describe('#getTokenPairsAsync', () => {
|
describe('#getAssetPairsAsync', () => {
|
||||||
const url = `${relayUrl}/token_pairs`;
|
const url = `${relayUrl}/asset_pairs`;
|
||||||
it('gets token pairs with default options when none are provided', async () => {
|
it('gets assetData pairs with default options when none are provided', async () => {
|
||||||
const urlWithQuery = `${url}?page=1&per_page=100`;
|
fetchMock.get(url, assetDataPairsResponseJSON);
|
||||||
fetchMock.get(urlWithQuery, tokenPairsResponseJSON);
|
const assetDataPairs = await relayerClient.getAssetPairsAsync();
|
||||||
const tokenPairs = await relayerClient.getTokenPairsAsync();
|
expect(assetDataPairs).to.be.deep.equal(assetDataPairsResponse);
|
||||||
expect(tokenPairs).to.be.deep.equal(tokenPairsResponse);
|
|
||||||
});
|
});
|
||||||
it('gets token pairs with specified request options', async () => {
|
it('gets assetData pairs with specified request options', async () => {
|
||||||
const tokenAddress = '0x323b5d4c32345ced77393b3530b1eed0f346429d';
|
const assetData = '0xf47261b04c32345ced77393b3530b1eed0f346429d';
|
||||||
const tokenPairsRequestOpts = {
|
const assetPairsRequestOpts = {
|
||||||
tokenA: tokenAddress,
|
assetDataA: assetData,
|
||||||
page: 3,
|
page: 3,
|
||||||
perPage: 50,
|
perPage: 50,
|
||||||
|
networkdId: 42,
|
||||||
};
|
};
|
||||||
const urlWithQuery = `${url}?page=3&per_page=50&tokenA=${tokenAddress}`;
|
const urlWithQuery = `${url}?assetDataA=${assetData}&networkdId=42&page=3&perPage=50`;
|
||||||
fetchMock.get(urlWithQuery, tokenPairsResponseJSON);
|
fetchMock.get(urlWithQuery, assetDataPairsResponseJSON);
|
||||||
const tokenPairs = await relayerClient.getTokenPairsAsync(tokenPairsRequestOpts);
|
const assetDataPairs = await relayerClient.getAssetPairsAsync(assetPairsRequestOpts);
|
||||||
expect(tokenPairs).to.be.deep.equal(tokenPairsResponse);
|
expect(assetDataPairs).to.be.deep.equal(assetDataPairsResponse);
|
||||||
});
|
});
|
||||||
it('throws an error for invalid JSON response', async () => {
|
it('throws an error for invalid JSON response', async () => {
|
||||||
fetchMock.get(url, { test: 'dummy' });
|
fetchMock.get(url, { test: 'dummy' });
|
||||||
expect(relayerClient.getTokenPairsAsync()).to.be.rejected();
|
expect(relayerClient.getAssetPairsAsync()).to.be.rejected();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
describe('#getOrdersAsync', () => {
|
describe('#getOrdersAsync', () => {
|
||||||
const url = `${relayUrl}/orders`;
|
const url = `${relayUrl}/orders`;
|
||||||
it('gets orders with default options when none are provided', async () => {
|
it('gets orders with default options when none are provided', async () => {
|
||||||
const urlWithQuery = `${url}?page=1&per_page=100`;
|
fetchMock.get(url, ordersResponseJSON);
|
||||||
fetchMock.get(urlWithQuery, ordersResponseJSON);
|
|
||||||
const orders = await relayerClient.getOrdersAsync();
|
const orders = await relayerClient.getOrdersAsync();
|
||||||
expect(orders).to.be.deep.equal(ordersResponse);
|
expect(orders).to.be.deep.equal(ordersResponse);
|
||||||
});
|
});
|
||||||
it('gets orders with specified request options', async () => {
|
it('gets orders with specified request options', async () => {
|
||||||
const tokenAddress = '0x323b5d4c32345ced77393b3530b1eed0f346429d';
|
const assetDataAddress = '0x323b5d4c32345ced77393b3530b1eed0f346429d';
|
||||||
const ordersRequest = {
|
const ordersRequest = {
|
||||||
tokenAddress,
|
assetDataAddress,
|
||||||
page: 3,
|
page: 3,
|
||||||
perPage: 50,
|
perPage: 50,
|
||||||
|
networkdId: 42,
|
||||||
};
|
};
|
||||||
const urlWithQuery = `${url}?page=3&per_page=50&tokenAddress=${tokenAddress}`;
|
const urlWithQuery = `${url}?assetDataAddress=${assetDataAddress}&networkdId=42&page=3&perPage=50`;
|
||||||
fetchMock.get(urlWithQuery, ordersResponseJSON);
|
fetchMock.get(urlWithQuery, ordersResponseJSON);
|
||||||
const orders = await relayerClient.getOrdersAsync(ordersRequest);
|
const orders = await relayerClient.getOrdersAsync(ordersRequest);
|
||||||
expect(orders).to.be.deep.equal(ordersResponse);
|
expect(orders).to.be.deep.equal(ordersResponse);
|
||||||
@ -103,26 +104,27 @@ describe('HttpClient', () => {
|
|||||||
});
|
});
|
||||||
describe('#getOrderBookAsync', () => {
|
describe('#getOrderBookAsync', () => {
|
||||||
const request = {
|
const request = {
|
||||||
baseTokenAddress: '0x323b5d4c32345ced77393b3530b1eed0f346429d',
|
baseAssetData: '0x323b5d4c32345ced77393b3530b1eed0f346429d',
|
||||||
quoteTokenAddress: '0xa2b31dacf30a9c50ca473337c01d8a201ae33e32',
|
quoteAssetData: '0xa2b31dacf30a9c50ca473337c01d8a201ae33e32',
|
||||||
};
|
};
|
||||||
const url = `${relayUrl}/orderbook`;
|
const url = `${relayUrl}/orderbook`;
|
||||||
it('gets orderbook with default page options when none are provided', async () => {
|
it('gets orderbook with default page options when none are provided', async () => {
|
||||||
const urlWithQuery = `${url}?baseTokenAddress=${
|
const urlWithQuery = `${url}?baseAssetData=${request.baseAssetData}"eAssetData=${
|
||||||
request.baseTokenAddress
|
request.quoteAssetData
|
||||||
}&page=1&per_page=100"eTokenAddress=${request.quoteTokenAddress}`;
|
}`;
|
||||||
fetchMock.get(urlWithQuery, orderbookJSON);
|
fetchMock.get(urlWithQuery, orderbookJSON);
|
||||||
const orderbook = await relayerClient.getOrderbookAsync(request);
|
const orderbook = await relayerClient.getOrderbookAsync(request);
|
||||||
expect(orderbook).to.be.deep.equal(orderbookResponse);
|
expect(orderbook).to.be.deep.equal(orderbookResponse);
|
||||||
});
|
});
|
||||||
it('gets orderbook with specified page options', async () => {
|
it('gets orderbook with specified page options', async () => {
|
||||||
const urlWithQuery = `${url}?baseTokenAddress=${
|
const urlWithQuery = `${url}?baseAssetData=${
|
||||||
request.baseTokenAddress
|
request.baseAssetData
|
||||||
}&page=3&per_page=50"eTokenAddress=${request.quoteTokenAddress}`;
|
}&networkId=42&page=3&perPage=50"eAssetData=${request.quoteAssetData}`;
|
||||||
fetchMock.get(urlWithQuery, orderbookJSON);
|
fetchMock.get(urlWithQuery, orderbookJSON);
|
||||||
const pagedRequestOptions = {
|
const pagedRequestOptions = {
|
||||||
page: 3,
|
page: 3,
|
||||||
perPage: 50,
|
perPage: 50,
|
||||||
|
networkId: 42,
|
||||||
};
|
};
|
||||||
const orderbook = await relayerClient.getOrderbookAsync(request, pagedRequestOptions);
|
const orderbook = await relayerClient.getOrderbookAsync(request, pagedRequestOptions);
|
||||||
expect(orderbook).to.be.deep.equal(orderbookResponse);
|
expect(orderbook).to.be.deep.equal(orderbookResponse);
|
||||||
@ -132,39 +134,59 @@ describe('HttpClient', () => {
|
|||||||
expect(relayerClient.getOrderbookAsync(request)).to.be.rejected();
|
expect(relayerClient.getOrderbookAsync(request)).to.be.rejected();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
describe('#getFeesAsync', () => {
|
describe('#getOrderConfigAsync', () => {
|
||||||
const request = {
|
const request = {
|
||||||
exchangeContractAddress: '0x12459c951127e0c374ff9105dda097662a027093',
|
makerAddress: '0x9e56625509c2f60af937f23b7b532600390e8c8b',
|
||||||
maker: '0x9e56625509c2f60af937f23b7b532600390e8c8b',
|
takerAddress: '0xa2b31dacf30a9c50ca473337c01d8a201ae33e32',
|
||||||
taker: '0xa2b31dacf30a9c50ca473337c01d8a201ae33e32',
|
makerAssetAmount: '10000000000000000',
|
||||||
makerTokenAddress: '0x323b5d4c32345ced77393b3530b1eed0f346429d',
|
takerAssetAmount: '20000000000000000',
|
||||||
takerTokenAddress: '0xef7fff64389b814a946f3e92105513705ca6b990',
|
expirationTimeSeconds: '1532560590',
|
||||||
makerTokenAmount: new BigNumber('10000000000000000000'),
|
makerAssetData: '0xf47261b04c32345ced77393b3530b1eed0f346429d',
|
||||||
takerTokenAmount: new BigNumber('30000000000000000000'),
|
takerAssetData: '0x0257179264389b814a946f3e92105513705ca6b990',
|
||||||
salt: new BigNumber('256'),
|
exchangeAddress: '0x12459c951127e0c374ff9105dda097662a027093',
|
||||||
expirationUnixTimestampSec: new BigNumber('42'),
|
|
||||||
};
|
};
|
||||||
const url = `${relayUrl}/fees`;
|
const url = `${relayUrl}/order_config`;
|
||||||
it('gets fees', async () => {
|
it('gets order config', async () => {
|
||||||
fetchMock.post(url, feesResponseJSON);
|
fetchMock.post(url, orderConfigResponseJSON);
|
||||||
const fees = await relayerClient.getFeesAsync(request);
|
const fees = await relayerClient.getOrderConfigAsync(request);
|
||||||
expect(fees).to.be.deep.equal(feesResponse);
|
expect(fees).to.be.deep.equal(orderConfigResponse);
|
||||||
});
|
});
|
||||||
it('does not mutate input', async () => {
|
it('does not mutate input', async () => {
|
||||||
fetchMock.post(url, feesResponseJSON);
|
fetchMock.post(url, orderConfigResponseJSON);
|
||||||
const makerTokenAmountBefore = new BigNumber(request.makerTokenAmount);
|
const makerAssetAmountBefore = request.makerAssetAmount;
|
||||||
const takerTokenAmountBefore = new BigNumber(request.takerTokenAmount);
|
const takerAssetAmountBefore = request.takerAssetAmount;
|
||||||
const saltBefore = new BigNumber(request.salt);
|
const expirationTimeSecondsBefore = request.expirationTimeSeconds;
|
||||||
const expirationUnixTimestampSecBefore = new BigNumber(request.expirationUnixTimestampSec);
|
await relayerClient.getOrderConfigAsync(request);
|
||||||
await relayerClient.getFeesAsync(request);
|
expect(makerAssetAmountBefore).to.be.deep.equal(request.makerAssetAmount);
|
||||||
expect(makerTokenAmountBefore).to.be.deep.equal(request.makerTokenAmount);
|
expect(takerAssetAmountBefore).to.be.deep.equal(request.takerAssetAmount);
|
||||||
expect(takerTokenAmountBefore).to.be.deep.equal(request.takerTokenAmount);
|
expect(expirationTimeSecondsBefore).to.be.deep.equal(request.expirationTimeSeconds);
|
||||||
expect(saltBefore).to.be.deep.equal(request.salt);
|
|
||||||
expect(expirationUnixTimestampSecBefore).to.be.deep.equal(request.expirationUnixTimestampSec);
|
|
||||||
});
|
});
|
||||||
it('throws an error for invalid JSON response', async () => {
|
it('throws an error for invalid JSON response', async () => {
|
||||||
fetchMock.post(url, { test: 'dummy' });
|
fetchMock.post(url, { test: 'dummy' });
|
||||||
expect(relayerClient.getFeesAsync(request)).to.be.rejected();
|
expect(relayerClient.getOrderConfigAsync(request)).to.be.rejected();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
describe('#getFeeRecipientsAsync', () => {
|
||||||
|
const url = `${relayUrl}/fee_recipients`;
|
||||||
|
it('gets fee recipients with default page options when none are provided', async () => {
|
||||||
|
fetchMock.get(url, feeRecipientsResponseJSON);
|
||||||
|
const feeRecipients = await relayerClient.getFeeRecipientsAsync();
|
||||||
|
expect(feeRecipients).to.be.deep.equal(feeRecipientsResponse);
|
||||||
|
});
|
||||||
|
it('gets fee recipient with specified page options', async () => {
|
||||||
|
const urlWithQuery = `${url}?networkId=42&page=3&perPage=50`;
|
||||||
|
fetchMock.get(urlWithQuery, feeRecipientsResponseJSON);
|
||||||
|
const pagedRequestOptions = {
|
||||||
|
page: 3,
|
||||||
|
perPage: 50,
|
||||||
|
networkId: 42,
|
||||||
|
};
|
||||||
|
const feeRecipients = await relayerClient.getFeeRecipientsAsync(pagedRequestOptions);
|
||||||
|
expect(feeRecipients).to.be.deep.equal(feeRecipientsResponse);
|
||||||
|
});
|
||||||
|
it('throws an error for invalid JSON response', async () => {
|
||||||
|
fetchMock.get(url, { test: 'dummy' });
|
||||||
|
expect(relayerClient.getFeeRecipientsAsync()).to.be.rejected();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
@ -1,45 +0,0 @@
|
|||||||
import * as chai from 'chai';
|
|
||||||
import * as dirtyChai from 'dirty-chai';
|
|
||||||
import * as _ from 'lodash';
|
|
||||||
import 'mocha';
|
|
||||||
|
|
||||||
import { orderbookChannelFactory } from '../src/orderbook_channel_factory';
|
|
||||||
|
|
||||||
chai.config.includeStack = true;
|
|
||||||
chai.use(dirtyChai);
|
|
||||||
const expect = chai.expect;
|
|
||||||
const emptyOrderbookChannelHandler = {
|
|
||||||
onSnapshot: () => {
|
|
||||||
_.noop();
|
|
||||||
},
|
|
||||||
onUpdate: () => {
|
|
||||||
_.noop();
|
|
||||||
},
|
|
||||||
onError: () => {
|
|
||||||
_.noop();
|
|
||||||
},
|
|
||||||
onClose: () => {
|
|
||||||
_.noop();
|
|
||||||
},
|
|
||||||
};
|
|
||||||
|
|
||||||
describe('orderbookChannelFactory', () => {
|
|
||||||
const websocketUrl = 'ws://localhost:8080';
|
|
||||||
describe('#createWebSocketOrderbookChannelAsync', () => {
|
|
||||||
it('throws when input is not a url', () => {
|
|
||||||
const badUrlInput = 54;
|
|
||||||
expect(
|
|
||||||
orderbookChannelFactory.createWebSocketOrderbookChannelAsync(
|
|
||||||
badUrlInput as any,
|
|
||||||
emptyOrderbookChannelHandler,
|
|
||||||
),
|
|
||||||
).to.be.rejected();
|
|
||||||
});
|
|
||||||
it('throws when handler has the incorrect members', () => {
|
|
||||||
const badHandlerInput = {};
|
|
||||||
expect(
|
|
||||||
orderbookChannelFactory.createWebSocketOrderbookChannelAsync(websocketUrl, badHandlerInput as any),
|
|
||||||
).to.be.rejected();
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
@ -1,76 +0,0 @@
|
|||||||
import * as chai from 'chai';
|
|
||||||
import * as dirtyChai from 'dirty-chai';
|
|
||||||
import 'mocha';
|
|
||||||
|
|
||||||
import { orderbookChannelMessageParser } from '../src/utils/orderbook_channel_message_parser';
|
|
||||||
|
|
||||||
import { orderResponse } from './fixtures/standard_relayer_api/order/0xabc67323774bdbd24d94f977fa9ac94a50f016026fd13f42990861238897721f';
|
|
||||||
import { orderbookResponse } from './fixtures/standard_relayer_api/orderbook';
|
|
||||||
import {
|
|
||||||
malformedSnapshotOrderbookChannelMessage,
|
|
||||||
snapshotOrderbookChannelMessage,
|
|
||||||
} from './fixtures/standard_relayer_api/snapshot_orderbook_channel_message';
|
|
||||||
import { unknownOrderbookChannelMessage } from './fixtures/standard_relayer_api/unknown_orderbook_channel_message';
|
|
||||||
import {
|
|
||||||
malformedUpdateOrderbookChannelMessage,
|
|
||||||
updateOrderbookChannelMessage,
|
|
||||||
} from './fixtures/standard_relayer_api/update_orderbook_channel_message';
|
|
||||||
|
|
||||||
chai.config.includeStack = true;
|
|
||||||
chai.use(dirtyChai);
|
|
||||||
const expect = chai.expect;
|
|
||||||
|
|
||||||
describe('orderbookChannelMessageParser', () => {
|
|
||||||
describe('#parser', () => {
|
|
||||||
it('parses snapshot messages', () => {
|
|
||||||
const snapshotMessage = orderbookChannelMessageParser.parse(snapshotOrderbookChannelMessage);
|
|
||||||
expect(snapshotMessage.type).to.be.equal('snapshot');
|
|
||||||
expect(snapshotMessage.payload).to.be.deep.equal(orderbookResponse);
|
|
||||||
});
|
|
||||||
it('parses update messages', () => {
|
|
||||||
const updateMessage = orderbookChannelMessageParser.parse(updateOrderbookChannelMessage);
|
|
||||||
expect(updateMessage.type).to.be.equal('update');
|
|
||||||
expect(updateMessage.payload).to.be.deep.equal(orderResponse);
|
|
||||||
});
|
|
||||||
it('returns unknown message for messages with unsupported types', () => {
|
|
||||||
const unknownMessage = orderbookChannelMessageParser.parse(unknownOrderbookChannelMessage);
|
|
||||||
expect(unknownMessage.type).to.be.equal('unknown');
|
|
||||||
expect(unknownMessage.payload).to.be.undefined();
|
|
||||||
});
|
|
||||||
it('throws when message does not include a type', () => {
|
|
||||||
const typelessMessage = `{
|
|
||||||
"channel": "orderbook",
|
|
||||||
"requestId": 1,
|
|
||||||
"payload": {}
|
|
||||||
}`;
|
|
||||||
const badCall = () => orderbookChannelMessageParser.parse(typelessMessage);
|
|
||||||
expect(badCall).throws(`Message is missing a type parameter: ${typelessMessage}`);
|
|
||||||
});
|
|
||||||
it('throws when type is not a string', () => {
|
|
||||||
const messageWithBadType = `{
|
|
||||||
"type": 1,
|
|
||||||
"channel": "orderbook",
|
|
||||||
"requestId": 1,
|
|
||||||
"payload": {}
|
|
||||||
}`;
|
|
||||||
const badCall = () => orderbookChannelMessageParser.parse(messageWithBadType);
|
|
||||||
expect(badCall).throws('Expected type to be of type string, encountered: 1');
|
|
||||||
});
|
|
||||||
it('throws when snapshot message has malformed payload', () => {
|
|
||||||
const badCall = () => orderbookChannelMessageParser.parse(malformedSnapshotOrderbookChannelMessage);
|
|
||||||
// tslint:disable-next-line:max-line-length
|
|
||||||
const errMsg =
|
|
||||||
'Validation errors: instance.payload requires property "bids", instance.payload requires property "asks"';
|
|
||||||
expect(badCall).throws(errMsg);
|
|
||||||
});
|
|
||||||
it('throws when update message has malformed payload', () => {
|
|
||||||
const badCall = () => orderbookChannelMessageParser.parse(malformedUpdateOrderbookChannelMessage);
|
|
||||||
expect(badCall).throws(/^Expected message to conform to schema/);
|
|
||||||
});
|
|
||||||
it('throws when input message is not valid JSON', () => {
|
|
||||||
const nonJsonString = 'h93b{sdfs9fsd f';
|
|
||||||
const badCall = () => orderbookChannelMessageParser.parse(nonJsonString);
|
|
||||||
expect(badCall).throws('Unexpected token h in JSON at position 0');
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
34
packages/connect/test/orders_channel_factory_test.ts
Normal file
34
packages/connect/test/orders_channel_factory_test.ts
Normal file
@ -0,0 +1,34 @@
|
|||||||
|
import * as chai from 'chai';
|
||||||
|
import * as dirtyChai from 'dirty-chai';
|
||||||
|
import * as _ from 'lodash';
|
||||||
|
|
||||||
|
import 'mocha';
|
||||||
|
|
||||||
|
import { ordersChannelFactory } from '../src/orders_channel_factory';
|
||||||
|
|
||||||
|
chai.config.includeStack = true;
|
||||||
|
chai.use(dirtyChai);
|
||||||
|
const expect = chai.expect;
|
||||||
|
const emptyOrdersChannelHandler = {
|
||||||
|
onUpdate: _.noop.bind(_),
|
||||||
|
onError: _.noop.bind(_),
|
||||||
|
onClose: _.noop.bind(_),
|
||||||
|
};
|
||||||
|
|
||||||
|
describe('ordersChannelFactory', () => {
|
||||||
|
const websocketUrl = 'ws://localhost:8080';
|
||||||
|
describe('#createWebSocketOrdersChannelAsync', () => {
|
||||||
|
it('throws when input is not a url', () => {
|
||||||
|
const badUrlInput = 54;
|
||||||
|
expect(
|
||||||
|
ordersChannelFactory.createWebSocketOrdersChannelAsync(badUrlInput as any, emptyOrdersChannelHandler),
|
||||||
|
).to.be.rejected();
|
||||||
|
});
|
||||||
|
it('throws when handler has the incorrect members', () => {
|
||||||
|
const badHandlerInput = {};
|
||||||
|
expect(
|
||||||
|
ordersChannelFactory.createWebSocketOrdersChannelAsync(websocketUrl, badHandlerInput as any),
|
||||||
|
).to.be.rejected();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
59
packages/connect/test/orders_channel_message_parsers_test.ts
Normal file
59
packages/connect/test/orders_channel_message_parsers_test.ts
Normal file
@ -0,0 +1,59 @@
|
|||||||
|
import * as chai from 'chai';
|
||||||
|
import * as dirtyChai from 'dirty-chai';
|
||||||
|
import 'mocha';
|
||||||
|
|
||||||
|
import { ordersChannelMessageParser } from '../src/utils/orders_channel_message_parser';
|
||||||
|
|
||||||
|
import { orderResponse } from './fixtures/standard_relayer_api/order/0xabc67323774bdbd24d94f977fa9ac94a50f016026fd13f42990861238897721f';
|
||||||
|
import { unknownOrdersChannelMessage } from './fixtures/standard_relayer_api/unknown_orders_channel_message';
|
||||||
|
import {
|
||||||
|
malformedUpdateOrdersChannelMessage,
|
||||||
|
updateOrdersChannelMessage,
|
||||||
|
} from './fixtures/standard_relayer_api/update_orders_channel_message';
|
||||||
|
|
||||||
|
chai.config.includeStack = true;
|
||||||
|
chai.use(dirtyChai);
|
||||||
|
const expect = chai.expect;
|
||||||
|
|
||||||
|
describe('ordersChannelMessageParser', () => {
|
||||||
|
describe('#parser', () => {
|
||||||
|
it('parses update messages', () => {
|
||||||
|
const updateMessage = ordersChannelMessageParser.parse(updateOrdersChannelMessage);
|
||||||
|
expect(updateMessage.type).to.be.equal('update');
|
||||||
|
expect(updateMessage.payload).to.be.deep.equal([orderResponse]);
|
||||||
|
});
|
||||||
|
it('returns unknown message for messages with unsupported types', () => {
|
||||||
|
const unknownMessage = ordersChannelMessageParser.parse(unknownOrdersChannelMessage);
|
||||||
|
expect(unknownMessage.type).to.be.equal('unknown');
|
||||||
|
expect(unknownMessage.payload).to.be.undefined();
|
||||||
|
});
|
||||||
|
it('throws when message does not include a type', () => {
|
||||||
|
const typelessMessage = `{
|
||||||
|
"channel": "orders",
|
||||||
|
"requestId": "4d8efcee-adde-4475-9601-f0b30962ca2b",
|
||||||
|
"payload": []
|
||||||
|
}`;
|
||||||
|
const badCall = () => ordersChannelMessageParser.parse(typelessMessage);
|
||||||
|
expect(badCall).throws(`Message is missing a type parameter: ${typelessMessage}`);
|
||||||
|
});
|
||||||
|
it('throws when type is not a string', () => {
|
||||||
|
const messageWithBadType = `{
|
||||||
|
"type": 1,
|
||||||
|
"channel": "orders",
|
||||||
|
"requestId": "4d8efcee-adde-4475-9601-f0b30962ca2b",
|
||||||
|
"payload": []
|
||||||
|
}`;
|
||||||
|
const badCall = () => ordersChannelMessageParser.parse(messageWithBadType);
|
||||||
|
expect(badCall).throws('Expected type to be of type string, encountered: 1');
|
||||||
|
});
|
||||||
|
it('throws when update message has malformed payload', () => {
|
||||||
|
const badCall = () => ordersChannelMessageParser.parse(malformedUpdateOrdersChannelMessage);
|
||||||
|
expect(badCall).throws(/^Expected message to conform to schema/);
|
||||||
|
});
|
||||||
|
it('throws when input message is not valid JSON', () => {
|
||||||
|
const nonJsonString = 'h93b{sdfs9fsd f';
|
||||||
|
const badCall = () => ordersChannelMessageParser.parse(nonJsonString);
|
||||||
|
expect(badCall).throws('Unexpected token h in JSON at position 0');
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
@ -1,59 +0,0 @@
|
|||||||
import * as chai from 'chai';
|
|
||||||
import * as dirtyChai from 'dirty-chai';
|
|
||||||
import * as _ from 'lodash';
|
|
||||||
import 'mocha';
|
|
||||||
import * as Sinon from 'sinon';
|
|
||||||
import * as WebSocket from 'websocket';
|
|
||||||
|
|
||||||
import { WebSocketOrderbookChannel } from '../src/ws_orderbook_channel';
|
|
||||||
|
|
||||||
chai.config.includeStack = true;
|
|
||||||
chai.use(dirtyChai);
|
|
||||||
const expect = chai.expect;
|
|
||||||
const emptyOrderbookChannelHandler = {
|
|
||||||
onSnapshot: () => {
|
|
||||||
_.noop();
|
|
||||||
},
|
|
||||||
onUpdate: () => {
|
|
||||||
_.noop();
|
|
||||||
},
|
|
||||||
onError: () => {
|
|
||||||
_.noop();
|
|
||||||
},
|
|
||||||
onClose: () => {
|
|
||||||
_.noop();
|
|
||||||
},
|
|
||||||
};
|
|
||||||
|
|
||||||
describe('WebSocketOrderbookChannel', () => {
|
|
||||||
const websocketUrl = 'ws://localhost:8080';
|
|
||||||
const openClient = new WebSocket.w3cwebsocket(websocketUrl);
|
|
||||||
Sinon.stub(openClient, 'readyState').get(() => WebSocket.w3cwebsocket.OPEN);
|
|
||||||
Sinon.stub(openClient, 'send').callsFake(_.noop.bind(_));
|
|
||||||
const openOrderbookChannel = new WebSocketOrderbookChannel(openClient, emptyOrderbookChannelHandler);
|
|
||||||
const subscriptionOpts = {
|
|
||||||
baseTokenAddress: '0x323b5d4c32345ced77393b3530b1eed0f346429d',
|
|
||||||
quoteTokenAddress: '0xef7fff64389b814a946f3e92105513705ca6b990',
|
|
||||||
snapshot: true,
|
|
||||||
limit: 100,
|
|
||||||
};
|
|
||||||
describe('#subscribe', () => {
|
|
||||||
it('throws when subscriptionOpts does not conform to schema', () => {
|
|
||||||
const badSubscribeCall = openOrderbookChannel.subscribe.bind(openOrderbookChannel, {});
|
|
||||||
expect(badSubscribeCall).throws(
|
|
||||||
'Expected subscriptionOpts to conform to schema /RelayerApiOrderbookChannelSubscribePayload\nEncountered: {}\nValidation errors: instance requires property "baseTokenAddress", instance requires property "quoteTokenAddress"',
|
|
||||||
);
|
|
||||||
});
|
|
||||||
it('does not throw when inputs are of correct types', () => {
|
|
||||||
const goodSubscribeCall = openOrderbookChannel.subscribe.bind(openOrderbookChannel, subscriptionOpts);
|
|
||||||
expect(goodSubscribeCall).to.not.throw();
|
|
||||||
});
|
|
||||||
it('throws when client is closed', () => {
|
|
||||||
const closedClient = new WebSocket.w3cwebsocket(websocketUrl);
|
|
||||||
Sinon.stub(closedClient, 'readyState').get(() => WebSocket.w3cwebsocket.CLOSED);
|
|
||||||
const closedOrderbookChannel = new WebSocketOrderbookChannel(closedClient, emptyOrderbookChannelHandler);
|
|
||||||
const badSubscribeCall = closedOrderbookChannel.subscribe.bind(closedOrderbookChannel, subscriptionOpts);
|
|
||||||
expect(badSubscribeCall).throws('WebSocket connection is closed');
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
49
packages/connect/test/ws_orders_channel_test.ts
Normal file
49
packages/connect/test/ws_orders_channel_test.ts
Normal file
@ -0,0 +1,49 @@
|
|||||||
|
import * as chai from 'chai';
|
||||||
|
import * as dirtyChai from 'dirty-chai';
|
||||||
|
import * as _ from 'lodash';
|
||||||
|
import 'mocha';
|
||||||
|
import * as Sinon from 'sinon';
|
||||||
|
import * as WebSocket from 'websocket';
|
||||||
|
|
||||||
|
import { WebSocketOrdersChannel } from '../src/ws_orders_channel';
|
||||||
|
|
||||||
|
chai.config.includeStack = true;
|
||||||
|
chai.use(dirtyChai);
|
||||||
|
const expect = chai.expect;
|
||||||
|
const emptyOrdersChannelHandler = {
|
||||||
|
onUpdate: _.noop.bind(_),
|
||||||
|
onError: _.noop.bind(_),
|
||||||
|
onClose: _.noop.bind(_),
|
||||||
|
};
|
||||||
|
|
||||||
|
describe('WebSocketOrdersChannel', () => {
|
||||||
|
const websocketUrl = 'ws://localhost:8080';
|
||||||
|
const openClient = new WebSocket.w3cwebsocket(websocketUrl);
|
||||||
|
Sinon.stub(openClient, 'readyState').get(() => WebSocket.w3cwebsocket.OPEN);
|
||||||
|
Sinon.stub(openClient, 'send').callsFake(_.noop.bind(_));
|
||||||
|
const openOrdersChannel = new WebSocketOrdersChannel(openClient, emptyOrdersChannelHandler);
|
||||||
|
const subscriptionOpts = {
|
||||||
|
baseAssetData: '0x323b5d4c32345ced77393b3530b1eed0f346429d',
|
||||||
|
quoteAssetData: '0xef7fff64389b814a946f3e92105513705ca6b990',
|
||||||
|
limit: 100,
|
||||||
|
};
|
||||||
|
describe('#subscribe', () => {
|
||||||
|
it('throws when subscriptionOpts does not conform to schema', () => {
|
||||||
|
const badSubscribeCall = openOrdersChannel.subscribe.bind(openOrdersChannel, {
|
||||||
|
makerAssetData: 5,
|
||||||
|
});
|
||||||
|
expect(badSubscribeCall).throws();
|
||||||
|
});
|
||||||
|
it('does not throw when inputs are of correct types', () => {
|
||||||
|
const goodSubscribeCall = openOrdersChannel.subscribe.bind(openOrdersChannel, subscriptionOpts);
|
||||||
|
expect(goodSubscribeCall).to.not.throw();
|
||||||
|
});
|
||||||
|
it('throws when client is closed', () => {
|
||||||
|
const closedClient = new WebSocket.w3cwebsocket(websocketUrl);
|
||||||
|
Sinon.stub(closedClient, 'readyState').get(() => WebSocket.w3cwebsocket.CLOSED);
|
||||||
|
const closedOrdersChannel = new WebSocketOrdersChannel(closedClient, emptyOrdersChannelHandler);
|
||||||
|
const badSubscribeCall = closedOrdersChannel.subscribe.bind(closedOrdersChannel, subscriptionOpts);
|
||||||
|
expect(badSubscribeCall).throws('WebSocket connection is closed');
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
@ -1,4 +1,13 @@
|
|||||||
[
|
[
|
||||||
|
{
|
||||||
|
"version": "1.0.1-rc.5",
|
||||||
|
"changes": [
|
||||||
|
{
|
||||||
|
"note": "Update incorrect relayer api fee recipients response schema",
|
||||||
|
"pr": 974
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"version": "1.0.1-rc.4",
|
"version": "1.0.1-rc.4",
|
||||||
"changes": [
|
"changes": [
|
||||||
|
@ -5,7 +5,11 @@ export const relayerApiFeeRecipientsResponseSchema = {
|
|||||||
{ $ref: '/paginatedCollectionSchema' },
|
{ $ref: '/paginatedCollectionSchema' },
|
||||||
{
|
{
|
||||||
properties: {
|
properties: {
|
||||||
records: { $ref: '/addressSchema' },
|
records: {
|
||||||
|
id: '/relayerApiFeeRecipientsSchema',
|
||||||
|
type: 'array',
|
||||||
|
items: { $ref: '/addressSchema' },
|
||||||
|
},
|
||||||
},
|
},
|
||||||
required: ['records'],
|
required: ['records'],
|
||||||
},
|
},
|
||||||
|
@ -1,4 +1,13 @@
|
|||||||
[
|
[
|
||||||
|
{
|
||||||
|
"version": "1.0.1-rc.5",
|
||||||
|
"changes": [
|
||||||
|
{
|
||||||
|
"note": "Add takerAddress to /orders parameters",
|
||||||
|
"pr": 974
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"version": "1.0.1-rc.4",
|
"version": "1.0.1-rc.4",
|
||||||
"changes": [
|
"changes": [
|
||||||
|
File diff suppressed because one or more lines are too long
@ -150,6 +150,15 @@ export const api: OpenApiSpec = {
|
|||||||
$ref: '#/components/schemas/addressSchema',
|
$ref: '#/components/schemas/addressSchema',
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
name: 'takerAddress',
|
||||||
|
in: 'query',
|
||||||
|
description: `Same as takerAddress in the [0x Protocol v2 Specification](https://github.com/0xProject/0x-protocol-specification/blob/master/v2/v2-specification.md#order-message-format)`,
|
||||||
|
example: '0xe41d2489571d322189246dafa5ebde1f4699f498',
|
||||||
|
schema: {
|
||||||
|
$ref: '#/components/schemas/addressSchema',
|
||||||
|
},
|
||||||
|
},
|
||||||
{
|
{
|
||||||
name: 'traderAddress',
|
name: 'traderAddress',
|
||||||
in: 'query',
|
in: 'query',
|
||||||
|
@ -35,7 +35,7 @@
|
|||||||
"homepage": "https://github.com/0xProject/0x-monorepo/packages/sra-report/README.md",
|
"homepage": "https://github.com/0xProject/0x-monorepo/packages/sra-report/README.md",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@0xproject/assert": "^1.0.5",
|
"@0xproject/assert": "^1.0.5",
|
||||||
"@0xproject/connect": "^1.0.5",
|
"@0xproject/connect": "1.0.4",
|
||||||
"@0xproject/json-schemas": "^0.8.3",
|
"@0xproject/json-schemas": "^0.8.3",
|
||||||
"@0xproject/order-utils": "^0.0.9",
|
"@0xproject/order-utils": "^0.0.9",
|
||||||
"@0xproject/types": "^0.8.2",
|
"@0xproject/types": "^0.8.2",
|
||||||
|
28
packages/website/md/docs/json_schemas/2.0.0/schemas.md
vendored
Normal file
28
packages/website/md/docs/json_schemas/2.0.0/schemas.md
vendored
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
0x Protocol Schemas
|
||||||
|
|
||||||
|
* [Basic types](https://github.com/0xProject/0x-monorepo/blob/development/packages/json-schemas/schemas/basic_type_schemas.ts) (e.g Ethereum address, number, hex)
|
||||||
|
* [Order/SignedOrder](https://github.com/0xProject/0x-monorepo/blob/development/packages/json-schemas/schemas/order_schemas.ts)
|
||||||
|
* [OrderHash](https://github.com/0xProject/0x-monorepo/blob/development/packages/json-schemas/schemas/order_hash_schema.ts)
|
||||||
|
|
||||||
|
0x.js Schemas
|
||||||
|
|
||||||
|
* [BlockRange](https://github.com/0xProject/0x-monorepo/blob/development/packages/json-schemas/schemas/block_range_schema.ts)
|
||||||
|
* [IndexFilter Values](https://github.com/0xProject/0x-monorepo/blob/development/packages/json-schemas/schemas/index_filter_values_schema.ts)
|
||||||
|
* [OrderFillRequests](https://github.com/0xProject/0x-monorepo/blob/development/packages/json-schemas/schemas/order_fill_requests_schema.ts)
|
||||||
|
* [OrderCancellationRequests](https://github.com/0xProject/0x-monorepo/blob/development/packages/json-schemas/schemas/order_cancel_schema.ts)
|
||||||
|
* [OrderFillOrKillRequests](https://github.com/0xProject/0x-monorepo/blob/development/packages/json-schemas/schemas/order_fill_or_kill_requests_schema.ts)
|
||||||
|
* [SignedOrders](https://github.com/0xProject/0x-monorepo/blob/development/packages/json-schemas/schemas/signed_orders_schema.ts)
|
||||||
|
* [Token](https://github.com/0xProject/0x-monorepo/blob/development/packages/json-schemas/schemas/token_schema.ts)
|
||||||
|
* [TxData](https://github.com/0xProject/0x-monorepo/blob/development/packages/json-schemas/schemas/tx_data_schema.ts)
|
||||||
|
|
||||||
|
Standard Relayer API Schemas
|
||||||
|
|
||||||
|
* [Paginated collection](https://github.com/0xProject/0x-monorepo/blob/development/packages/json-schemas/schemas/paginated_collection_schema.ts)
|
||||||
|
* [Error response](https://github.com/0xProject/0x-monorepo/blob/development/packages/json-schemas/schemas/relayer_api_error_response_schema.ts)
|
||||||
|
* [Order config payload](https://github.com/0xProject/0x-monorepo/blob/development/packages/json-schemas/schemas/relayer_api_order_config_payload_schema.ts)
|
||||||
|
* [Order config response](https://github.com/0xProject/0x-monorepo/blob/development/packages/json-schemas/schemas/relayer_api_order_config_response_schema.ts)
|
||||||
|
* [Orders channel subscribe](https://github.com/0xProject/0x-monorepo/blob/development/packages/json-schemas/schemas/relayer_api_orders_channel_subscribe_schema.ts)
|
||||||
|
* [Orders channel update](https://github.com/0xProject/0x-monorepo/blob/development/packages/json-schemas/schemas/relayer_api_orders_channel_update_response_schema.ts)
|
||||||
|
* [Orderbook response](https://github.com/0xProject/0x-monorepo/blob/development/packages/json-schemas/schemas/relayer_api_orderbook_response_schema.ts)
|
||||||
|
* [Asset pairs response](https://github.com/0xProject/0x-monorepo/blob/development/packages/json-schemas/schemas/relayer_api_asset_pairs_response_schema.ts)
|
||||||
|
* [Fee recipients response](https://github.com/0xProject/0x-monorepo/blob/development/packages/json-schemas/schemas/relayer_api_fee_recipients_response_schema.ts)
|
@ -13,6 +13,7 @@ const IntroMarkdownV1 = require('md/docs/json_schemas/1.0.0/introduction');
|
|||||||
const InstallationMarkdownV1 = require('md/docs/json_schemas/1.0.0/installation');
|
const InstallationMarkdownV1 = require('md/docs/json_schemas/1.0.0/installation');
|
||||||
const UsageMarkdownV1 = require('md/docs/json_schemas/1.0.0/usage');
|
const UsageMarkdownV1 = require('md/docs/json_schemas/1.0.0/usage');
|
||||||
const SchemasMarkdownV1 = require('md/docs/json_schemas/1.0.0/schemas');
|
const SchemasMarkdownV1 = require('md/docs/json_schemas/1.0.0/schemas');
|
||||||
|
const SchemasMarkdownV2 = require('md/docs/json_schemas/2.0.0/schemas');
|
||||||
/* tslint:enable:no-var-requires */
|
/* tslint:enable:no-var-requires */
|
||||||
|
|
||||||
const markdownSections = {
|
const markdownSections = {
|
||||||
@ -43,6 +44,12 @@ const docsInfoConfig: DocsInfoConfig = {
|
|||||||
[markdownSections.schemas]: SchemasMarkdownV1,
|
[markdownSections.schemas]: SchemasMarkdownV1,
|
||||||
[markdownSections.usage]: UsageMarkdownV1,
|
[markdownSections.usage]: UsageMarkdownV1,
|
||||||
},
|
},
|
||||||
|
'1.0.0': {
|
||||||
|
[markdownSections.introduction]: IntroMarkdownV1,
|
||||||
|
[markdownSections.installation]: InstallationMarkdownV1,
|
||||||
|
[markdownSections.schemas]: SchemasMarkdownV2,
|
||||||
|
[markdownSections.usage]: UsageMarkdownV1,
|
||||||
|
},
|
||||||
},
|
},
|
||||||
markdownSections,
|
markdownSections,
|
||||||
};
|
};
|
||||||
|
16
yarn.lock
16
yarn.lock
@ -524,6 +524,20 @@
|
|||||||
ethers "3.0.22"
|
ethers "3.0.22"
|
||||||
lodash "4.17.10"
|
lodash "4.17.10"
|
||||||
|
|
||||||
|
"@0xproject/connect@1.0.4":
|
||||||
|
version "1.0.4"
|
||||||
|
resolved "https://registry.npmjs.org/@0xproject/connect/-/connect-1.0.4.tgz#1d5f27f4aa69920dde50178ed7179240f81d1c54"
|
||||||
|
dependencies:
|
||||||
|
"@0xproject/assert" "^0.2.14"
|
||||||
|
"@0xproject/json-schemas" "^0.8.3"
|
||||||
|
"@0xproject/types" "^0.8.2"
|
||||||
|
"@0xproject/typescript-typings" "^1.0.3"
|
||||||
|
"@0xproject/utils" "^1.0.4"
|
||||||
|
lodash "^4.17.4"
|
||||||
|
query-string "^5.0.1"
|
||||||
|
sinon "^4.0.0"
|
||||||
|
websocket "^1.0.25"
|
||||||
|
|
||||||
"@0xproject/contract-wrappers@^0.0.5":
|
"@0xproject/contract-wrappers@^0.0.5":
|
||||||
version "0.0.5"
|
version "0.0.5"
|
||||||
resolved "https://registry.yarnpkg.com/@0xproject/contract-wrappers/-/contract-wrappers-0.0.5.tgz#36f91afb7de51478f9d2e4e0a3c4e685b3d18f28"
|
resolved "https://registry.yarnpkg.com/@0xproject/contract-wrappers/-/contract-wrappers-0.0.5.tgz#36f91afb7de51478f9d2e4e0a3c4e685b3d18f28"
|
||||||
@ -1237,7 +1251,7 @@
|
|||||||
version "0.0.33"
|
version "0.0.33"
|
||||||
resolved "https://registry.yarnpkg.com/@types/tmp/-/tmp-0.0.33.tgz#1073c4bc824754ae3d10cfab88ab0237ba964e4d"
|
resolved "https://registry.yarnpkg.com/@types/tmp/-/tmp-0.0.33.tgz#1073c4bc824754ae3d10cfab88ab0237ba964e4d"
|
||||||
|
|
||||||
"@types/uuid@^3.4.2":
|
"@types/uuid@^3.4.2", "@types/uuid@^3.4.3":
|
||||||
version "3.4.3"
|
version "3.4.3"
|
||||||
resolved "https://registry.yarnpkg.com/@types/uuid/-/uuid-3.4.3.tgz#121ace265f5569ce40f4f6d0ff78a338c732a754"
|
resolved "https://registry.yarnpkg.com/@types/uuid/-/uuid-3.4.3.tgz#121ace265f5569ce40f4f6d0ff78a338c732a754"
|
||||||
dependencies:
|
dependencies:
|
||||||
|
Loading…
x
Reference in New Issue
Block a user