Fix prettier

This commit is contained in:
Fabio Berger
2018-01-30 13:21:01 +01:00
parent 4242176d29
commit 93a5b3f457
379 changed files with 33806 additions and 33826 deletions

View File

@@ -1,69 +1,64 @@
{
"name": "@0xproject/connect",
"version": "0.5.2",
"description": "A javascript library for interacting with the standard relayer api",
"keywords": [
"connect",
"0xproject",
"ethereum",
"tokens",
"exchange"
],
"main": "lib/src/index.js",
"types": "lib/src/index.d.ts",
"scripts": {
"build": "tsc",
"clean": "shx rm -rf _bundles lib test_temp",
"docs:json": "typedoc --excludePrivate --excludeExternals --target ES5 --json $JSON_FILE_PATH $PROJECT_DIR",
"upload_docs_json": "aws s3 cp generated_docs/index.json $S3_URL --profile 0xproject --grants read=uri=http://acs.amazonaws.com/groups/global/AllUsers --content-type application/json",
"copy_test_fixtures": "copyfiles -u 2 './test/fixtures/**/*.json' ./lib/test/fixtures",
"lint": "tslint --project . 'src/**/*.ts' 'test/**/*.ts'",
"run_mocha": "mocha lib/test/**/*_test.js",
"test": "run-s clean build copy_test_fixtures run_mocha",
"test:circleci": "yarn test"
},
"repository": {
"type": "git",
"url": "https://github.com/0xProject/0x.js.git"
},
"author": "Brandon Millman",
"license": "Apache-2.0",
"engines": {
"node": ">=6.0.0"
},
"bugs": {
"url": "https://github.com/0xProject/0x.js/issues"
},
"homepage": "https://github.com/0xProject/0x.js/packages/connect/README.md",
"dependencies": {
"@0xproject/assert": "^0.0.13",
"@0xproject/json-schemas": "^0.7.5",
"@0xproject/utils": "^0.2.2",
"isomorphic-fetch": "^2.2.1",
"lodash": "^4.17.4",
"query-string": "^5.0.1",
"websocket": "^1.0.25"
},
"devDependencies": {
"@0xproject/tslint-config": "^0.4.4",
"@types/fetch-mock": "^5.12.1",
"@types/lodash": "^4.14.86",
"@types/mocha": "^2.2.42",
"@types/query-string": "^5.0.1",
"@types/websocket": "^0.0.34",
"chai": "^4.0.1",
"chai-as-promised": "^7.1.0",
"chai-as-promised-typescript-typings": "^0.0.6",
"chai-typescript-typings": "^0.0.2",
"copyfiles": "^1.2.0",
"dirty-chai": "^2.0.1",
"fetch-mock": "^5.13.1",
"mocha": "^4.0.1",
"npm-run-all": "^4.1.2",
"shx": "^0.2.2",
"tslint": "5.8.0",
"typedoc": "~0.8.0",
"typescript": "~2.6.1",
"web3-typescript-typings": "^0.9.6"
}
"name": "@0xproject/connect",
"version": "0.5.2",
"description": "A javascript library for interacting with the standard relayer api",
"keywords": ["connect", "0xproject", "ethereum", "tokens", "exchange"],
"main": "lib/src/index.js",
"types": "lib/src/index.d.ts",
"scripts": {
"build": "tsc",
"clean": "shx rm -rf _bundles lib test_temp",
"docs:json": "typedoc --excludePrivate --excludeExternals --target ES5 --json $JSON_FILE_PATH $PROJECT_DIR",
"upload_docs_json":
"aws s3 cp generated_docs/index.json $S3_URL --profile 0xproject --grants read=uri=http://acs.amazonaws.com/groups/global/AllUsers --content-type application/json",
"copy_test_fixtures": "copyfiles -u 2 './test/fixtures/**/*.json' ./lib/test/fixtures",
"lint": "tslint --project . 'src/**/*.ts' 'test/**/*.ts'",
"run_mocha": "mocha lib/test/**/*_test.js",
"test": "run-s clean build copy_test_fixtures run_mocha",
"test:circleci": "yarn test"
},
"repository": {
"type": "git",
"url": "https://github.com/0xProject/0x.js.git"
},
"author": "Brandon Millman",
"license": "Apache-2.0",
"engines": {
"node": ">=6.0.0"
},
"bugs": {
"url": "https://github.com/0xProject/0x.js/issues"
},
"homepage": "https://github.com/0xProject/0x.js/packages/connect/README.md",
"dependencies": {
"@0xproject/assert": "^0.0.13",
"@0xproject/json-schemas": "^0.7.5",
"@0xproject/utils": "^0.2.2",
"isomorphic-fetch": "^2.2.1",
"lodash": "^4.17.4",
"query-string": "^5.0.1",
"websocket": "^1.0.25"
},
"devDependencies": {
"@0xproject/tslint-config": "^0.4.4",
"@types/fetch-mock": "^5.12.1",
"@types/lodash": "^4.14.86",
"@types/mocha": "^2.2.42",
"@types/query-string": "^5.0.1",
"@types/websocket": "^0.0.34",
"chai": "^4.0.1",
"chai-as-promised": "^7.1.0",
"chai-as-promised-typescript-typings": "^0.0.6",
"chai-typescript-typings": "^0.0.2",
"copyfiles": "^1.2.0",
"dirty-chai": "^2.0.1",
"fetch-mock": "^5.13.1",
"mocha": "^4.0.1",
"npm-run-all": "^4.1.2",
"shx": "^0.2.2",
"tslint": "5.8.0",
"typedoc": "~0.8.0",
"typescript": "~2.6.1",
"web3-typescript-typings": "^0.9.6"
}
}

View File

@@ -1,6 +1,6 @@
declare module 'dirty-chai';
declare module '*.json' {
const value: any;
export default value;
const value: any;
export default value;
}

View File

@@ -6,17 +6,17 @@ import * as queryString from 'query-string';
import { schemas as clientSchemas } from './schemas/schemas';
import {
Client,
FeesRequest,
FeesResponse,
HttpRequestOptions,
HttpRequestType,
OrderbookRequest,
OrderbookResponse,
OrdersRequest,
SignedOrder,
TokenPairsItem,
TokenPairsRequest,
Client,
FeesRequest,
FeesResponse,
HttpRequestOptions,
HttpRequestType,
OrderbookRequest,
OrderbookResponse,
OrdersRequest,
SignedOrder,
TokenPairsItem,
TokenPairsRequest,
} from './types';
import { relayerResponseJsonParsers } from './utils/relayer_response_json_parsers';
@@ -26,127 +26,127 @@ const TRAILING_SLASHES_REGEX = /\/+$/;
* that implement the standard relayer API v0
*/
export class HttpClient implements Client {
private _apiEndpointUrl: string;
/**
* Instantiates a new HttpClient instance
* @param url The relayer API base HTTP url you would like to interact with
* @return An instance of HttpClient
*/
constructor(url: string) {
assert.isHttpUrl('url', url);
this._apiEndpointUrl = url.replace(TRAILING_SLASHES_REGEX, ''); // remove trailing slashes
}
/**
* Retrieve token pair info from the API
* @param request A TokenPairsRequest instance describing specific token information
* to retrieve
* @return The resulting TokenPairsItems that match the request
*/
public async getTokenPairsAsync(request?: TokenPairsRequest): Promise<TokenPairsItem[]> {
if (!_.isUndefined(request)) {
assert.doesConformToSchema('request', request, clientSchemas.relayerTokenPairsRequestSchema);
}
const requestOpts = {
params: request,
};
const responseJson = await this._requestAsync('/token_pairs', HttpRequestType.Get, requestOpts);
const tokenPairs = relayerResponseJsonParsers.parseTokenPairsJson(responseJson);
return tokenPairs;
}
/**
* Retrieve orders from the API
* @param request An OrdersRequest instance describing specific orders to retrieve
* @return The resulting SignedOrders that match the request
*/
public async getOrdersAsync(request?: OrdersRequest): Promise<SignedOrder[]> {
if (!_.isUndefined(request)) {
assert.doesConformToSchema('request', request, clientSchemas.relayerOrdersRequestSchema);
}
const requestOpts = {
params: request,
};
const responseJson = await this._requestAsync(`/orders`, HttpRequestType.Get, requestOpts);
const orders = relayerResponseJsonParsers.parseOrdersJson(responseJson);
return orders;
}
/**
* Retrieve a specific order from the API
* @param orderHash An orderHash generated from the desired order
* @return The SignedOrder that matches the supplied orderHash
*/
public async getOrderAsync(orderHash: string): Promise<SignedOrder> {
assert.doesConformToSchema('orderHash', orderHash, schemas.orderHashSchema);
const responseJson = await this._requestAsync(`/order/${orderHash}`, HttpRequestType.Get);
const order = relayerResponseJsonParsers.parseOrderJson(responseJson);
return order;
}
/**
* Retrieve an orderbook from the API
* @param request An OrderbookRequest instance describing the specific orderbook to retrieve
* @return The resulting OrderbookResponse that matches the request
*/
public async getOrderbookAsync(request: OrderbookRequest): Promise<OrderbookResponse> {
assert.doesConformToSchema('request', request, clientSchemas.relayerOrderBookRequestSchema);
const requestOpts = {
params: request,
};
const responseJson = await this._requestAsync('/orderbook', HttpRequestType.Get, requestOpts);
const orderbook = relayerResponseJsonParsers.parseOrderbookResponseJson(responseJson);
return orderbook;
}
/**
* Retrieve fee information from the API
* @param request A FeesRequest instance describing the specific fees to retrieve
* @return The resulting FeesResponse that matches the request
*/
public async getFeesAsync(request: FeesRequest): Promise<FeesResponse> {
assert.doesConformToSchema('request', request, schemas.relayerApiFeesPayloadSchema);
const requestOpts = {
payload: request,
};
const responseJson = await this._requestAsync('/fees', HttpRequestType.Post, requestOpts);
const fees = relayerResponseJsonParsers.parseFeesResponseJson(responseJson);
return fees;
}
/**
* Submit a signed order to the API
* @param signedOrder A SignedOrder instance to submit
*/
public async submitOrderAsync(signedOrder: SignedOrder): Promise<void> {
assert.doesConformToSchema('signedOrder', signedOrder, schemas.signedOrderSchema);
const requestOpts = {
payload: signedOrder,
};
await this._requestAsync('/order', HttpRequestType.Post, requestOpts);
}
private async _requestAsync(
path: string,
requestType: HttpRequestType,
requestOptions?: HttpRequestOptions,
): Promise<any> {
const params = _.get(requestOptions, 'params');
const payload = _.get(requestOptions, 'payload');
let query = '';
if (!_.isUndefined(params) && !_.isEmpty(params)) {
const stringifiedParams = queryString.stringify(params);
query = `?${stringifiedParams}`;
}
const url = `${this._apiEndpointUrl}${path}${query}`;
const headers = new Headers({
'content-type': 'application/json',
});
const response = await fetch(url, {
method: requestType,
body: JSON.stringify(payload),
headers,
});
const json = await response.json();
if (!response.ok) {
const errorString = `${response.status} - ${response.statusText}\n${requestType} ${url}\n${JSON.stringify(
json,
)}`;
throw Error(errorString);
}
return json;
}
private _apiEndpointUrl: string;
/**
* Instantiates a new HttpClient instance
* @param url The relayer API base HTTP url you would like to interact with
* @return An instance of HttpClient
*/
constructor(url: string) {
assert.isHttpUrl('url', url);
this._apiEndpointUrl = url.replace(TRAILING_SLASHES_REGEX, ''); // remove trailing slashes
}
/**
* Retrieve token pair info from the API
* @param request A TokenPairsRequest instance describing specific token information
* to retrieve
* @return The resulting TokenPairsItems that match the request
*/
public async getTokenPairsAsync(request?: TokenPairsRequest): Promise<TokenPairsItem[]> {
if (!_.isUndefined(request)) {
assert.doesConformToSchema('request', request, clientSchemas.relayerTokenPairsRequestSchema);
}
const requestOpts = {
params: request,
};
const responseJson = await this._requestAsync('/token_pairs', HttpRequestType.Get, requestOpts);
const tokenPairs = relayerResponseJsonParsers.parseTokenPairsJson(responseJson);
return tokenPairs;
}
/**
* Retrieve orders from the API
* @param request An OrdersRequest instance describing specific orders to retrieve
* @return The resulting SignedOrders that match the request
*/
public async getOrdersAsync(request?: OrdersRequest): Promise<SignedOrder[]> {
if (!_.isUndefined(request)) {
assert.doesConformToSchema('request', request, clientSchemas.relayerOrdersRequestSchema);
}
const requestOpts = {
params: request,
};
const responseJson = await this._requestAsync(`/orders`, HttpRequestType.Get, requestOpts);
const orders = relayerResponseJsonParsers.parseOrdersJson(responseJson);
return orders;
}
/**
* Retrieve a specific order from the API
* @param orderHash An orderHash generated from the desired order
* @return The SignedOrder that matches the supplied orderHash
*/
public async getOrderAsync(orderHash: string): Promise<SignedOrder> {
assert.doesConformToSchema('orderHash', orderHash, schemas.orderHashSchema);
const responseJson = await this._requestAsync(`/order/${orderHash}`, HttpRequestType.Get);
const order = relayerResponseJsonParsers.parseOrderJson(responseJson);
return order;
}
/**
* Retrieve an orderbook from the API
* @param request An OrderbookRequest instance describing the specific orderbook to retrieve
* @return The resulting OrderbookResponse that matches the request
*/
public async getOrderbookAsync(request: OrderbookRequest): Promise<OrderbookResponse> {
assert.doesConformToSchema('request', request, clientSchemas.relayerOrderBookRequestSchema);
const requestOpts = {
params: request,
};
const responseJson = await this._requestAsync('/orderbook', HttpRequestType.Get, requestOpts);
const orderbook = relayerResponseJsonParsers.parseOrderbookResponseJson(responseJson);
return orderbook;
}
/**
* Retrieve fee information from the API
* @param request A FeesRequest instance describing the specific fees to retrieve
* @return The resulting FeesResponse that matches the request
*/
public async getFeesAsync(request: FeesRequest): Promise<FeesResponse> {
assert.doesConformToSchema('request', request, schemas.relayerApiFeesPayloadSchema);
const requestOpts = {
payload: request,
};
const responseJson = await this._requestAsync('/fees', HttpRequestType.Post, requestOpts);
const fees = relayerResponseJsonParsers.parseFeesResponseJson(responseJson);
return fees;
}
/**
* Submit a signed order to the API
* @param signedOrder A SignedOrder instance to submit
*/
public async submitOrderAsync(signedOrder: SignedOrder): Promise<void> {
assert.doesConformToSchema('signedOrder', signedOrder, schemas.signedOrderSchema);
const requestOpts = {
payload: signedOrder,
};
await this._requestAsync('/order', HttpRequestType.Post, requestOpts);
}
private async _requestAsync(
path: string,
requestType: HttpRequestType,
requestOptions?: HttpRequestOptions,
): Promise<any> {
const params = _.get(requestOptions, 'params');
const payload = _.get(requestOptions, 'payload');
let query = '';
if (!_.isUndefined(params) && !_.isEmpty(params)) {
const stringifiedParams = queryString.stringify(params);
query = `?${stringifiedParams}`;
}
const url = `${this._apiEndpointUrl}${path}${query}`;
const headers = new Headers({
'content-type': 'application/json',
});
const response = await fetch(url, {
method: requestType,
body: JSON.stringify(payload),
headers,
});
const json = await response.json();
if (!response.ok) {
const errorString = `${response.status} - ${response.statusText}\n${requestType} ${url}\n${JSON.stringify(
json,
)}`;
throw Error(errorString);
}
return json;
}
}

View File

@@ -1,19 +1,19 @@
export { HttpClient } from './http_client';
export { WebSocketOrderbookChannel } from './ws_orderbook_channel';
export {
Client,
ECSignature,
FeesRequest,
FeesResponse,
Order,
OrderbookChannel,
OrderbookChannelHandler,
OrderbookChannelSubscriptionOpts,
OrderbookRequest,
OrderbookResponse,
OrdersRequest,
SignedOrder,
TokenPairsItem,
TokenPairsRequest,
TokenTradeInfo,
Client,
ECSignature,
FeesRequest,
FeesResponse,
Order,
OrderbookChannel,
OrderbookChannelHandler,
OrderbookChannelSubscriptionOpts,
OrderbookRequest,
OrderbookResponse,
OrdersRequest,
SignedOrder,
TokenPairsItem,
TokenPairsRequest,
TokenTradeInfo,
} from './types';

View File

@@ -1,8 +1,8 @@
export const relayerOrderBookRequestSchema = {
id: '/RelayerOrderBookRequest',
type: 'object',
properties: {
baseTokenAddress: { $ref: '/Address' },
quoteTokenAddress: { $ref: '/Address' },
},
id: '/RelayerOrderBookRequest',
type: 'object',
properties: {
baseTokenAddress: { $ref: '/Address' },
quoteTokenAddress: { $ref: '/Address' },
},
};

View File

@@ -1,8 +1,8 @@
export const relayerOrderBookRequestSchema = {
id: '/RelayerOrderBookRequest',
type: 'object',
properties: {
baseTokenAddress: { $ref: '/Address' },
quoteTokenAddress: { $ref: '/Address' },
},
id: '/RelayerOrderBookRequest',
type: 'object',
properties: {
baseTokenAddress: { $ref: '/Address' },
quoteTokenAddress: { $ref: '/Address' },
},
};

View File

@@ -1,16 +1,16 @@
export const relayerOrdersRequestSchema = {
id: '/RelayerOrdersRequest',
type: 'object',
properties: {
exchangeContractAddress: { $ref: '/Address' },
tokenAddress: { $ref: '/Address' },
makerTokenAddress: { $ref: '/Address' },
takerTokenAddress: { $ref: '/Address' },
tokenA: { $ref: '/Address' },
tokenB: { $ref: '/Address' },
maker: { $ref: '/Address' },
taker: { $ref: '/Address' },
trader: { $ref: '/Address' },
feeRecipient: { $ref: '/Address' },
},
id: '/RelayerOrdersRequest',
type: 'object',
properties: {
exchangeContractAddress: { $ref: '/Address' },
tokenAddress: { $ref: '/Address' },
makerTokenAddress: { $ref: '/Address' },
takerTokenAddress: { $ref: '/Address' },
tokenA: { $ref: '/Address' },
tokenB: { $ref: '/Address' },
maker: { $ref: '/Address' },
taker: { $ref: '/Address' },
trader: { $ref: '/Address' },
feeRecipient: { $ref: '/Address' },
},
};

View File

@@ -1,8 +1,8 @@
export const relayerTokenPairsRequestSchema = {
id: '/RelayerTokenPairsRequest',
type: 'object',
properties: {
tokenA: { $ref: '/Address' },
tokenB: { $ref: '/Address' },
},
id: '/RelayerTokenPairsRequest',
type: 'object',
properties: {
tokenA: { $ref: '/Address' },
tokenB: { $ref: '/Address' },
},
};

View File

@@ -3,7 +3,7 @@ import { relayerOrdersRequestSchema } from './relayer_orders_request_schema';
import { relayerTokenPairsRequestSchema } from './relayer_token_pairs_request_schema';
export const schemas = {
relayerOrderBookRequestSchema,
relayerOrdersRequestSchema,
relayerTokenPairsRequestSchema,
relayerOrderBookRequestSchema,
relayerOrdersRequestSchema,
relayerTokenPairsRequestSchema,
};

View File

@@ -2,45 +2,45 @@ import { BigNumber } from '@0xproject/utils';
// TODO: Consolidate Order, SignedOrder and ECSignature into a shared package instead of duplicating them from 0x.js
export interface Order {
maker: string;
taker: string;
makerFee: BigNumber;
takerFee: BigNumber;
makerTokenAmount: BigNumber;
takerTokenAmount: BigNumber;
makerTokenAddress: string;
takerTokenAddress: string;
salt: BigNumber;
exchangeContractAddress: string;
feeRecipient: string;
expirationUnixTimestampSec: BigNumber;
maker: string;
taker: string;
makerFee: BigNumber;
takerFee: BigNumber;
makerTokenAmount: BigNumber;
takerTokenAmount: BigNumber;
makerTokenAddress: string;
takerTokenAddress: string;
salt: BigNumber;
exchangeContractAddress: string;
feeRecipient: string;
expirationUnixTimestampSec: BigNumber;
}
export interface SignedOrder extends Order {
ecSignature: ECSignature;
ecSignature: ECSignature;
}
/**
* Elliptic Curve signature
*/
export interface ECSignature {
v: number;
r: string;
s: string;
v: number;
r: string;
s: string;
}
export interface Client {
getTokenPairsAsync: (request?: TokenPairsRequest) => Promise<TokenPairsItem[]>;
getOrdersAsync: (request?: OrdersRequest) => Promise<SignedOrder[]>;
getOrderAsync: (orderHash: string) => Promise<SignedOrder>;
getOrderbookAsync: (request: OrderbookRequest) => Promise<OrderbookResponse>;
getFeesAsync: (request: FeesRequest) => Promise<FeesResponse>;
submitOrderAsync: (signedOrder: SignedOrder) => Promise<void>;
getTokenPairsAsync: (request?: TokenPairsRequest) => Promise<TokenPairsItem[]>;
getOrdersAsync: (request?: OrdersRequest) => Promise<SignedOrder[]>;
getOrderAsync: (orderHash: string) => Promise<SignedOrder>;
getOrderbookAsync: (request: OrderbookRequest) => Promise<OrderbookResponse>;
getFeesAsync: (request: FeesRequest) => Promise<FeesResponse>;
submitOrderAsync: (signedOrder: SignedOrder) => Promise<void>;
}
export interface OrderbookChannel {
subscribe: (subscriptionOpts: OrderbookChannelSubscriptionOpts, handler: OrderbookChannelHandler) => void;
close: () => void;
subscribe: (subscriptionOpts: OrderbookChannelSubscriptionOpts, handler: OrderbookChannelHandler) => void;
close: () => void;
}
/*
@@ -50,129 +50,129 @@ export interface OrderbookChannel {
* limit: Maximum number of bids and asks in orderbook snapshot
*/
export interface OrderbookChannelSubscriptionOpts {
baseTokenAddress: string;
quoteTokenAddress: string;
snapshot: boolean;
limit: number;
baseTokenAddress: string;
quoteTokenAddress: string;
snapshot: boolean;
limit: number;
}
export interface OrderbookChannelHandler {
onSnapshot: (
channel: OrderbookChannel,
subscriptionOpts: OrderbookChannelSubscriptionOpts,
snapshot: OrderbookResponse,
) => void;
onUpdate: (
channel: OrderbookChannel,
subscriptionOpts: OrderbookChannelSubscriptionOpts,
order: SignedOrder,
) => void;
onError: (channel: OrderbookChannel, subscriptionOpts: OrderbookChannelSubscriptionOpts, err: Error) => void;
onClose: (channel: OrderbookChannel, subscriptionOpts: OrderbookChannelSubscriptionOpts) => void;
onSnapshot: (
channel: OrderbookChannel,
subscriptionOpts: OrderbookChannelSubscriptionOpts,
snapshot: OrderbookResponse,
) => void;
onUpdate: (
channel: OrderbookChannel,
subscriptionOpts: OrderbookChannelSubscriptionOpts,
order: SignedOrder,
) => void;
onError: (channel: OrderbookChannel, subscriptionOpts: OrderbookChannelSubscriptionOpts, err: Error) => void;
onClose: (channel: OrderbookChannel, subscriptionOpts: OrderbookChannelSubscriptionOpts) => void;
}
export type OrderbookChannelMessage =
| SnapshotOrderbookChannelMessage
| UpdateOrderbookChannelMessage
| UnknownOrderbookChannelMessage;
| SnapshotOrderbookChannelMessage
| UpdateOrderbookChannelMessage
| UnknownOrderbookChannelMessage;
export enum OrderbookChannelMessageTypes {
Snapshot = 'snapshot',
Update = 'update',
Unknown = 'unknown',
Snapshot = 'snapshot',
Update = 'update',
Unknown = 'unknown',
}
export interface SnapshotOrderbookChannelMessage {
type: OrderbookChannelMessageTypes.Snapshot;
requestId: number;
payload: OrderbookResponse;
type: OrderbookChannelMessageTypes.Snapshot;
requestId: number;
payload: OrderbookResponse;
}
export interface UpdateOrderbookChannelMessage {
type: OrderbookChannelMessageTypes.Update;
requestId: number;
payload: SignedOrder;
type: OrderbookChannelMessageTypes.Update;
requestId: number;
payload: SignedOrder;
}
export interface UnknownOrderbookChannelMessage {
type: OrderbookChannelMessageTypes.Unknown;
requestId: number;
payload: undefined;
type: OrderbookChannelMessageTypes.Unknown;
requestId: number;
payload: undefined;
}
export enum WebsocketConnectionEventType {
Close = 'close',
Error = 'error',
Message = 'message',
Close = 'close',
Error = 'error',
Message = 'message',
}
export enum WebsocketClientEventType {
Connect = 'connect',
ConnectFailed = 'connectFailed',
Connect = 'connect',
ConnectFailed = 'connectFailed',
}
export interface TokenPairsRequest {
tokenA?: string;
tokenB?: string;
tokenA?: string;
tokenB?: string;
}
export interface TokenPairsItem {
tokenA: TokenTradeInfo;
tokenB: TokenTradeInfo;
tokenA: TokenTradeInfo;
tokenB: TokenTradeInfo;
}
export interface TokenTradeInfo {
address: string;
minAmount: BigNumber;
maxAmount: BigNumber;
precision: number;
address: string;
minAmount: BigNumber;
maxAmount: BigNumber;
precision: number;
}
export interface OrdersRequest {
exchangeContractAddress?: string;
tokenAddress?: string;
makerTokenAddress?: string;
takerTokenAddress?: string;
maker?: string;
taker?: string;
trader?: string;
feeRecipient?: string;
exchangeContractAddress?: string;
tokenAddress?: string;
makerTokenAddress?: string;
takerTokenAddress?: string;
maker?: string;
taker?: string;
trader?: string;
feeRecipient?: string;
}
export interface OrderbookRequest {
baseTokenAddress: string;
quoteTokenAddress: string;
baseTokenAddress: string;
quoteTokenAddress: string;
}
export interface OrderbookResponse {
bids: SignedOrder[];
asks: SignedOrder[];
bids: SignedOrder[];
asks: SignedOrder[];
}
export interface FeesRequest {
exchangeContractAddress: string;
maker: string;
taker: string;
makerTokenAddress: string;
takerTokenAddress: string;
makerTokenAmount: BigNumber;
takerTokenAmount: BigNumber;
expirationUnixTimestampSec: BigNumber;
salt: BigNumber;
exchangeContractAddress: string;
maker: string;
taker: string;
makerTokenAddress: string;
takerTokenAddress: string;
makerTokenAmount: BigNumber;
takerTokenAmount: BigNumber;
expirationUnixTimestampSec: BigNumber;
salt: BigNumber;
}
export interface FeesResponse {
feeRecipient: string;
makerFee: BigNumber;
takerFee: BigNumber;
feeRecipient: string;
makerFee: BigNumber;
takerFee: BigNumber;
}
export interface HttpRequestOptions {
params?: object;
payload?: object;
params?: object;
payload?: object;
}
export enum HttpRequestType {
Get = 'GET',
Post = 'POST',
Get = 'GET',
Post = 'POST',
}

View File

@@ -7,31 +7,31 @@ import { OrderbookChannelMessage, OrderbookChannelMessageTypes } from '../types'
import { relayerResponseJsonParsers } from './relayer_response_json_parsers';
export const orderbookChannelMessageParser = {
parse(utf8Data: string): OrderbookChannelMessage {
const messageObj = JSON.parse(utf8Data);
const type: string = _.get(messageObj, 'type');
assert.assert(!_.isUndefined(type), `Message is missing a type parameter: ${utf8Data}`);
assert.isString('type', type);
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: 0,
payload: undefined,
};
}
}
},
parse(utf8Data: string): OrderbookChannelMessage {
const messageObj = JSON.parse(utf8Data);
const type: string = _.get(messageObj, 'type');
assert.assert(!_.isUndefined(type), `Message is missing a type parameter: ${utf8Data}`);
assert.isString('type', type);
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: 0,
payload: undefined,
};
}
}
},
};

View File

@@ -7,31 +7,31 @@ import { FeesResponse, OrderbookResponse, SignedOrder, TokenPairsItem } from '..
import { typeConverters } from './type_converters';
export const relayerResponseJsonParsers = {
parseTokenPairsJson(json: any): TokenPairsItem[] {
assert.doesConformToSchema('tokenPairs', json, schemas.relayerApiTokenPairsResponseSchema);
return json.map((tokenPair: any) => {
return typeConverters.convertStringsFieldsToBigNumbers(tokenPair, [
'tokenA.minAmount',
'tokenA.maxAmount',
'tokenB.minAmount',
'tokenB.maxAmount',
]);
});
},
parseOrdersJson(json: any): SignedOrder[] {
assert.doesConformToSchema('orders', json, schemas.signedOrdersSchema);
return json.map((order: object) => typeConverters.convertOrderStringFieldsToBigNumber(order));
},
parseOrderJson(json: any): SignedOrder {
assert.doesConformToSchema('order', json, schemas.signedOrderSchema);
return typeConverters.convertOrderStringFieldsToBigNumber(json);
},
parseOrderbookResponseJson(json: any): OrderbookResponse {
assert.doesConformToSchema('orderBook', json, schemas.relayerApiOrderBookResponseSchema);
return typeConverters.convertOrderbookStringFieldsToBigNumber(json);
},
parseFeesResponseJson(json: any): FeesResponse {
assert.doesConformToSchema('fees', json, schemas.relayerApiFeesResponseSchema);
return typeConverters.convertStringsFieldsToBigNumbers(json, ['makerFee', 'takerFee']);
},
parseTokenPairsJson(json: any): TokenPairsItem[] {
assert.doesConformToSchema('tokenPairs', json, schemas.relayerApiTokenPairsResponseSchema);
return json.map((tokenPair: any) => {
return typeConverters.convertStringsFieldsToBigNumbers(tokenPair, [
'tokenA.minAmount',
'tokenA.maxAmount',
'tokenB.minAmount',
'tokenB.maxAmount',
]);
});
},
parseOrdersJson(json: any): SignedOrder[] {
assert.doesConformToSchema('orders', json, schemas.signedOrdersSchema);
return json.map((order: object) => typeConverters.convertOrderStringFieldsToBigNumber(order));
},
parseOrderJson(json: any): SignedOrder {
assert.doesConformToSchema('order', json, schemas.signedOrderSchema);
return typeConverters.convertOrderStringFieldsToBigNumber(json);
},
parseOrderbookResponseJson(json: any): OrderbookResponse {
assert.doesConformToSchema('orderBook', json, schemas.relayerApiOrderBookResponseSchema);
return typeConverters.convertOrderbookStringFieldsToBigNumber(json);
},
parseFeesResponseJson(json: any): FeesResponse {
assert.doesConformToSchema('fees', json, schemas.relayerApiFeesResponseSchema);
return typeConverters.convertStringsFieldsToBigNumbers(json, ['makerFee', 'takerFee']);
},
};

View File

@@ -2,29 +2,29 @@ import { BigNumber } from '@0xproject/utils';
import * as _ from 'lodash';
export const typeConverters = {
convertOrderbookStringFieldsToBigNumber(orderbook: any): any {
const bids = _.get(orderbook, 'bids', []);
const asks = _.get(orderbook, 'asks', []);
return {
bids: bids.map((order: any) => this.convertOrderStringFieldsToBigNumber(order)),
asks: asks.map((order: any) => this.convertOrderStringFieldsToBigNumber(order)),
};
},
convertOrderStringFieldsToBigNumber(order: any): any {
return this.convertStringsFieldsToBigNumbers(order, [
'makerTokenAmount',
'takerTokenAmount',
'makerFee',
'takerFee',
'expirationUnixTimestampSec',
'salt',
]);
},
convertStringsFieldsToBigNumbers(obj: any, fields: string[]): any {
const result = _.assign({}, obj);
_.each(fields, field => {
_.update(result, field, (value: string) => new BigNumber(value));
});
return result;
},
convertOrderbookStringFieldsToBigNumber(orderbook: any): any {
const bids = _.get(orderbook, 'bids', []);
const asks = _.get(orderbook, 'asks', []);
return {
bids: bids.map((order: any) => this.convertOrderStringFieldsToBigNumber(order)),
asks: asks.map((order: any) => this.convertOrderStringFieldsToBigNumber(order)),
};
},
convertOrderStringFieldsToBigNumber(order: any): any {
return this.convertStringsFieldsToBigNumbers(order, [
'makerTokenAmount',
'takerTokenAmount',
'makerFee',
'takerFee',
'expirationUnixTimestampSec',
'salt',
]);
},
convertStringsFieldsToBigNumbers(obj: any, fields: string[]): any {
const result = _.assign({}, obj);
_.each(fields, field => {
_.update(result, field, (value: string) => new BigNumber(value));
});
return result;
},
};

View File

@@ -4,12 +4,12 @@ import * as _ from 'lodash';
import * as WebSocket from 'websocket';
import {
OrderbookChannel,
OrderbookChannelHandler,
OrderbookChannelMessageTypes,
OrderbookChannelSubscriptionOpts,
WebsocketClientEventType,
WebsocketConnectionEventType,
OrderbookChannel,
OrderbookChannelHandler,
OrderbookChannelMessageTypes,
OrderbookChannelSubscriptionOpts,
WebsocketClientEventType,
WebsocketConnectionEventType,
} from './types';
import { orderbookChannelMessageParser } from './utils/orderbook_channel_message_parser';
@@ -18,117 +18,117 @@ import { orderbookChannelMessageParser } from './utils/orderbook_channel_message
* that implements the standard relayer API v0
*/
export class WebSocketOrderbookChannel implements OrderbookChannel {
private _apiEndpointUrl: string;
private _client: WebSocket.client;
private _connectionIfExists?: WebSocket.connection;
private _subscriptionCounter = 0;
/**
* Instantiates a new WebSocketOrderbookChannel instance
* @param url The relayer API base WS url you would like to interact with
* @return An instance of WebSocketOrderbookChannel
*/
constructor(url: string) {
assert.isUri('url', url);
this._apiEndpointUrl = url;
this._client = new WebSocket.client();
}
/**
* Subscribe to orderbook snapshots and updates from the websocket
* @param subscriptionOpts An OrderbookChannelSubscriptionOpts instance describing which
* token pair to subscribe to
* @param handler An OrderbookChannelHandler instance that responds to various
* channel updates
*/
public subscribe(subscriptionOpts: OrderbookChannelSubscriptionOpts, handler: OrderbookChannelHandler): void {
assert.doesConformToSchema(
'subscriptionOpts',
subscriptionOpts,
schemas.relayerApiOrderbookChannelSubscribePayload,
);
assert.isFunction('handler.onSnapshot', _.get(handler, 'onSnapshot'));
assert.isFunction('handler.onUpdate', _.get(handler, 'onUpdate'));
assert.isFunction('handler.onError', _.get(handler, 'onError'));
assert.isFunction('handler.onClose', _.get(handler, 'onClose'));
this._subscriptionCounter += 1;
const subscribeMessage = {
type: 'subscribe',
channel: 'orderbook',
requestId: this._subscriptionCounter,
payload: subscriptionOpts,
};
this._getConnection((error, connection) => {
if (!_.isUndefined(error)) {
handler.onError(this, subscriptionOpts, error);
} else if (!_.isUndefined(connection) && connection.connected) {
connection.on(WebsocketConnectionEventType.Error, wsError => {
handler.onError(this, subscriptionOpts, wsError);
});
connection.on(WebsocketConnectionEventType.Close, () => {
handler.onClose(this, subscriptionOpts);
});
connection.on(WebsocketConnectionEventType.Message, message => {
this._handleWebSocketMessage(subscribeMessage.requestId, subscriptionOpts, message, handler);
});
connection.sendUTF(JSON.stringify(subscribeMessage));
}
});
}
/**
* Close the websocket and stop receiving updates
*/
public close() {
if (!_.isUndefined(this._connectionIfExists)) {
this._connectionIfExists.close();
}
}
private _getConnection(callback: (error?: Error, connection?: WebSocket.connection) => void) {
if (!_.isUndefined(this._connectionIfExists) && this._connectionIfExists.connected) {
callback(undefined, this._connectionIfExists);
} else {
this._client.on(WebsocketClientEventType.Connect, connection => {
this._connectionIfExists = connection;
callback(undefined, this._connectionIfExists);
});
this._client.on(WebsocketClientEventType.ConnectFailed, error => {
callback(error, undefined);
});
this._client.connect(this._apiEndpointUrl);
}
}
private _handleWebSocketMessage(
requestId: number,
subscriptionOpts: OrderbookChannelSubscriptionOpts,
message: WebSocket.IMessage,
handler: OrderbookChannelHandler,
): void {
if (!_.isUndefined(message.utf8Data)) {
try {
const utf8Data = message.utf8Data;
const parserResult = orderbookChannelMessageParser.parse(utf8Data);
if (parserResult.requestId === requestId) {
switch (parserResult.type) {
case OrderbookChannelMessageTypes.Snapshot: {
handler.onSnapshot(this, subscriptionOpts, parserResult.payload);
break;
}
case OrderbookChannelMessageTypes.Update: {
handler.onUpdate(this, subscriptionOpts, parserResult.payload);
break;
}
default: {
handler.onError(
this,
subscriptionOpts,
new Error(`Message has missing a type parameter: ${utf8Data}`),
);
}
}
}
} catch (error) {
handler.onError(this, subscriptionOpts, error);
}
} else {
handler.onError(this, subscriptionOpts, new Error(`Message does not contain utf8Data`));
}
}
private _apiEndpointUrl: string;
private _client: WebSocket.client;
private _connectionIfExists?: WebSocket.connection;
private _subscriptionCounter = 0;
/**
* Instantiates a new WebSocketOrderbookChannel instance
* @param url The relayer API base WS url you would like to interact with
* @return An instance of WebSocketOrderbookChannel
*/
constructor(url: string) {
assert.isUri('url', url);
this._apiEndpointUrl = url;
this._client = new WebSocket.client();
}
/**
* Subscribe to orderbook snapshots and updates from the websocket
* @param subscriptionOpts An OrderbookChannelSubscriptionOpts instance describing which
* token pair to subscribe to
* @param handler An OrderbookChannelHandler instance that responds to various
* channel updates
*/
public subscribe(subscriptionOpts: OrderbookChannelSubscriptionOpts, handler: OrderbookChannelHandler): void {
assert.doesConformToSchema(
'subscriptionOpts',
subscriptionOpts,
schemas.relayerApiOrderbookChannelSubscribePayload,
);
assert.isFunction('handler.onSnapshot', _.get(handler, 'onSnapshot'));
assert.isFunction('handler.onUpdate', _.get(handler, 'onUpdate'));
assert.isFunction('handler.onError', _.get(handler, 'onError'));
assert.isFunction('handler.onClose', _.get(handler, 'onClose'));
this._subscriptionCounter += 1;
const subscribeMessage = {
type: 'subscribe',
channel: 'orderbook',
requestId: this._subscriptionCounter,
payload: subscriptionOpts,
};
this._getConnection((error, connection) => {
if (!_.isUndefined(error)) {
handler.onError(this, subscriptionOpts, error);
} else if (!_.isUndefined(connection) && connection.connected) {
connection.on(WebsocketConnectionEventType.Error, wsError => {
handler.onError(this, subscriptionOpts, wsError);
});
connection.on(WebsocketConnectionEventType.Close, () => {
handler.onClose(this, subscriptionOpts);
});
connection.on(WebsocketConnectionEventType.Message, message => {
this._handleWebSocketMessage(subscribeMessage.requestId, subscriptionOpts, message, handler);
});
connection.sendUTF(JSON.stringify(subscribeMessage));
}
});
}
/**
* Close the websocket and stop receiving updates
*/
public close() {
if (!_.isUndefined(this._connectionIfExists)) {
this._connectionIfExists.close();
}
}
private _getConnection(callback: (error?: Error, connection?: WebSocket.connection) => void) {
if (!_.isUndefined(this._connectionIfExists) && this._connectionIfExists.connected) {
callback(undefined, this._connectionIfExists);
} else {
this._client.on(WebsocketClientEventType.Connect, connection => {
this._connectionIfExists = connection;
callback(undefined, this._connectionIfExists);
});
this._client.on(WebsocketClientEventType.ConnectFailed, error => {
callback(error, undefined);
});
this._client.connect(this._apiEndpointUrl);
}
}
private _handleWebSocketMessage(
requestId: number,
subscriptionOpts: OrderbookChannelSubscriptionOpts,
message: WebSocket.IMessage,
handler: OrderbookChannelHandler,
): void {
if (!_.isUndefined(message.utf8Data)) {
try {
const utf8Data = message.utf8Data;
const parserResult = orderbookChannelMessageParser.parse(utf8Data);
if (parserResult.requestId === requestId) {
switch (parserResult.type) {
case OrderbookChannelMessageTypes.Snapshot: {
handler.onSnapshot(this, subscriptionOpts, parserResult.payload);
break;
}
case OrderbookChannelMessageTypes.Update: {
handler.onUpdate(this, subscriptionOpts, parserResult.payload);
break;
}
default: {
handler.onError(
this,
subscriptionOpts,
new Error(`Message has missing a type parameter: ${utf8Data}`),
);
}
}
}
} catch (error) {
handler.onError(this, subscriptionOpts, error);
}
} else {
handler.onError(this, subscriptionOpts, new Error(`Message does not contain utf8Data`));
}
}
}

View File

@@ -1,5 +1,5 @@
{
"feeRecipient": "0x323b5d4c32345ced77393b3530b1eed0f346429d",
"makerFee": "10000000000000000",
"takerFee": "30000000000000000"
"feeRecipient": "0x323b5d4c32345ced77393b3530b1eed0f346429d",
"makerFee": "10000000000000000",
"takerFee": "30000000000000000"
}

View File

@@ -3,7 +3,7 @@ import { BigNumber } from '@0xproject/utils';
import { FeesResponse } from '../../../src/types';
export const feesResponse: FeesResponse = {
feeRecipient: '0x323b5d4c32345ced77393b3530b1eed0f346429d',
makerFee: new BigNumber('10000000000000000'),
takerFee: new BigNumber('30000000000000000'),
feeRecipient: '0x323b5d4c32345ced77393b3530b1eed0f346429d',
makerFee: new BigNumber('10000000000000000'),
takerFee: new BigNumber('30000000000000000'),
};

View File

@@ -1,19 +1,19 @@
{
"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"
}
"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"
}
}

View File

@@ -1,21 +1,21 @@
import { BigNumber } from '@0xproject/utils';
export const orderResponse = {
maker: '0x9e56625509c2f60af937f23b7b532600390e8c8b',
taker: '0xa2b31dacf30a9c50ca473337c01d8a201ae33e32',
makerFee: new BigNumber('100000000000000'),
takerFee: new BigNumber('200000000000000'),
makerTokenAmount: new BigNumber('10000000000000000'),
takerTokenAmount: new BigNumber('20000000000000000'),
makerTokenAddress: '0x323b5d4c32345ced77393b3530b1eed0f346429d',
takerTokenAddress: '0xef7fff64389b814a946f3e92105513705ca6b990',
salt: new BigNumber('256'),
feeRecipient: '0xb046140686d052fff581f63f8136cce132e857da',
exchangeContractAddress: '0x12459c951127e0c374ff9105dda097662a027093',
expirationUnixTimestampSec: new BigNumber('42'),
ecSignature: {
v: 27,
r: '0x61a3ed31b43c8780e905a260a35faefcc527be7516aa11c0256729b5b351bc33',
s: '0x40349190569279751135161d22529dc25add4f6069af05be04cacbda2ace2254',
},
maker: '0x9e56625509c2f60af937f23b7b532600390e8c8b',
taker: '0xa2b31dacf30a9c50ca473337c01d8a201ae33e32',
makerFee: new BigNumber('100000000000000'),
takerFee: new BigNumber('200000000000000'),
makerTokenAmount: new BigNumber('10000000000000000'),
takerTokenAmount: new BigNumber('20000000000000000'),
makerTokenAddress: '0x323b5d4c32345ced77393b3530b1eed0f346429d',
takerTokenAddress: '0xef7fff64389b814a946f3e92105513705ca6b990',
salt: new BigNumber('256'),
feeRecipient: '0xb046140686d052fff581f63f8136cce132e857da',
exchangeContractAddress: '0x12459c951127e0c374ff9105dda097662a027093',
expirationUnixTimestampSec: new BigNumber('42'),
ecSignature: {
v: 27,
r: '0x61a3ed31b43c8780e905a260a35faefcc527be7516aa11c0256729b5b351bc33',
s: '0x40349190569279751135161d22529dc25add4f6069af05be04cacbda2ace2254',
},
};

View File

@@ -1,44 +1,44 @@
{
"bids": [
{
"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": [
{
"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"
}
}
]
"bids": [
{
"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": [
{
"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"
}
}
]
}

View File

@@ -1,46 +1,46 @@
import { BigNumber } from '@0xproject/utils';
export const orderbookResponse = {
bids: [
{
maker: '0x9e56625509c2f60af937f23b7b532600390e8c8b',
taker: '0xa2b31dacf30a9c50ca473337c01d8a201ae33e32',
makerFee: new BigNumber('100000000000000'),
takerFee: new BigNumber('200000000000000'),
makerTokenAmount: new BigNumber('10000000000000000'),
takerTokenAmount: new BigNumber('20000000000000000'),
makerTokenAddress: '0x323b5d4c32345ced77393b3530b1eed0f346429d',
takerTokenAddress: '0xef7fff64389b814a946f3e92105513705ca6b990',
salt: new BigNumber('256'),
feeRecipient: '0xb046140686d052fff581f63f8136cce132e857da',
exchangeContractAddress: '0x12459c951127e0c374ff9105dda097662a027093',
expirationUnixTimestampSec: new BigNumber('42'),
ecSignature: {
v: 27,
r: '0x61a3ed31b43c8780e905a260a35faefcc527be7516aa11c0256729b5b351bc33',
s: '0x40349190569279751135161d22529dc25add4f6069af05be04cacbda2ace2254',
},
},
],
asks: [
{
maker: '0x9e56625509c2f60af937f23b7b532600390e8c8b',
taker: '0xa2b31dacf30a9c50ca473337c01d8a201ae33e32',
makerFee: new BigNumber('100000000000000'),
takerFee: new BigNumber('200000000000000'),
makerTokenAmount: new BigNumber('10000000000000000'),
takerTokenAmount: new BigNumber('20000000000000000'),
makerTokenAddress: '0x323b5d4c32345ced77393b3530b1eed0f346429d',
takerTokenAddress: '0xef7fff64389b814a946f3e92105513705ca6b990',
salt: new BigNumber('256'),
feeRecipient: '0xb046140686d052fff581f63f8136cce132e857da',
exchangeContractAddress: '0x12459c951127e0c374ff9105dda097662a027093',
expirationUnixTimestampSec: new BigNumber('42'),
ecSignature: {
v: 27,
r: '0x61a3ed31b43c8780e905a260a35faefcc527be7516aa11c0256729b5b351bc33',
s: '0x40349190569279751135161d22529dc25add4f6069af05be04cacbda2ace2254',
},
},
],
bids: [
{
maker: '0x9e56625509c2f60af937f23b7b532600390e8c8b',
taker: '0xa2b31dacf30a9c50ca473337c01d8a201ae33e32',
makerFee: new BigNumber('100000000000000'),
takerFee: new BigNumber('200000000000000'),
makerTokenAmount: new BigNumber('10000000000000000'),
takerTokenAmount: new BigNumber('20000000000000000'),
makerTokenAddress: '0x323b5d4c32345ced77393b3530b1eed0f346429d',
takerTokenAddress: '0xef7fff64389b814a946f3e92105513705ca6b990',
salt: new BigNumber('256'),
feeRecipient: '0xb046140686d052fff581f63f8136cce132e857da',
exchangeContractAddress: '0x12459c951127e0c374ff9105dda097662a027093',
expirationUnixTimestampSec: new BigNumber('42'),
ecSignature: {
v: 27,
r: '0x61a3ed31b43c8780e905a260a35faefcc527be7516aa11c0256729b5b351bc33',
s: '0x40349190569279751135161d22529dc25add4f6069af05be04cacbda2ace2254',
},
},
],
asks: [
{
maker: '0x9e56625509c2f60af937f23b7b532600390e8c8b',
taker: '0xa2b31dacf30a9c50ca473337c01d8a201ae33e32',
makerFee: new BigNumber('100000000000000'),
takerFee: new BigNumber('200000000000000'),
makerTokenAmount: new BigNumber('10000000000000000'),
takerTokenAmount: new BigNumber('20000000000000000'),
makerTokenAddress: '0x323b5d4c32345ced77393b3530b1eed0f346429d',
takerTokenAddress: '0xef7fff64389b814a946f3e92105513705ca6b990',
salt: new BigNumber('256'),
feeRecipient: '0xb046140686d052fff581f63f8136cce132e857da',
exchangeContractAddress: '0x12459c951127e0c374ff9105dda097662a027093',
expirationUnixTimestampSec: new BigNumber('42'),
ecSignature: {
v: 27,
r: '0x61a3ed31b43c8780e905a260a35faefcc527be7516aa11c0256729b5b351bc33',
s: '0x40349190569279751135161d22529dc25add4f6069af05be04cacbda2ace2254',
},
},
],
};

View File

@@ -1,21 +1,21 @@
[
{
"maker": "0x9e56625509c2f60af937f23b7b532600390e8c8b",
"taker": "0xa2b31dacf30a9c50ca473337c01d8a201ae33e32",
"makerFee": "100000000000000",
"takerFee": "200000000000000",
"makerTokenAmount": "10000000000000000",
"takerTokenAmount": "20000000000000000",
"makerTokenAddress": "0x323b5d4c32345ced77393b3530b1eed0f346429d",
"takerTokenAddress": "0xef7fff64389b814a946f3e92105513705ca6b990",
"salt": "256",
"feeRecipient": "0x9e56625509c2f60af937f23b7b532600390e8c8b",
"exchangeContractAddress": "0x9e56625509c2f60af937f23b7b532600390e8c8b",
"expirationUnixTimestampSec": "42",
"ecSignature": {
"v": 27,
"r": "0x61a3ed31b43c8780e905a260a35faefcc527be7516aa11c0256729b5b351bc33",
"s": "0x40349190569279751135161d22529dc25add4f6069af05be04cacbda2ace2254"
}
}
{
"maker": "0x9e56625509c2f60af937f23b7b532600390e8c8b",
"taker": "0xa2b31dacf30a9c50ca473337c01d8a201ae33e32",
"makerFee": "100000000000000",
"takerFee": "200000000000000",
"makerTokenAmount": "10000000000000000",
"takerTokenAmount": "20000000000000000",
"makerTokenAddress": "0x323b5d4c32345ced77393b3530b1eed0f346429d",
"takerTokenAddress": "0xef7fff64389b814a946f3e92105513705ca6b990",
"salt": "256",
"feeRecipient": "0x9e56625509c2f60af937f23b7b532600390e8c8b",
"exchangeContractAddress": "0x9e56625509c2f60af937f23b7b532600390e8c8b",
"expirationUnixTimestampSec": "42",
"ecSignature": {
"v": 27,
"r": "0x61a3ed31b43c8780e905a260a35faefcc527be7516aa11c0256729b5b351bc33",
"s": "0x40349190569279751135161d22529dc25add4f6069af05be04cacbda2ace2254"
}
}
]

View File

@@ -1,23 +1,23 @@
import { BigNumber } from '@0xproject/utils';
export const ordersResponse = [
{
maker: '0x9e56625509c2f60af937f23b7b532600390e8c8b',
taker: '0xa2b31dacf30a9c50ca473337c01d8a201ae33e32',
makerFee: new BigNumber('100000000000000'),
takerFee: new BigNumber('200000000000000'),
makerTokenAmount: new BigNumber('10000000000000000'),
takerTokenAmount: new BigNumber('20000000000000000'),
makerTokenAddress: '0x323b5d4c32345ced77393b3530b1eed0f346429d',
takerTokenAddress: '0xef7fff64389b814a946f3e92105513705ca6b990',
salt: new BigNumber('256'),
feeRecipient: '0x9e56625509c2f60af937f23b7b532600390e8c8b',
exchangeContractAddress: '0x9e56625509c2f60af937f23b7b532600390e8c8b',
expirationUnixTimestampSec: new BigNumber('42'),
ecSignature: {
v: 27,
r: '0x61a3ed31b43c8780e905a260a35faefcc527be7516aa11c0256729b5b351bc33',
s: '0x40349190569279751135161d22529dc25add4f6069af05be04cacbda2ace2254',
},
},
{
maker: '0x9e56625509c2f60af937f23b7b532600390e8c8b',
taker: '0xa2b31dacf30a9c50ca473337c01d8a201ae33e32',
makerFee: new BigNumber('100000000000000'),
takerFee: new BigNumber('200000000000000'),
makerTokenAmount: new BigNumber('10000000000000000'),
takerTokenAmount: new BigNumber('20000000000000000'),
makerTokenAddress: '0x323b5d4c32345ced77393b3530b1eed0f346429d',
takerTokenAddress: '0xef7fff64389b814a946f3e92105513705ca6b990',
salt: new BigNumber('256'),
feeRecipient: '0x9e56625509c2f60af937f23b7b532600390e8c8b',
exchangeContractAddress: '0x9e56625509c2f60af937f23b7b532600390e8c8b',
expirationUnixTimestampSec: new BigNumber('42'),
ecSignature: {
v: 27,
r: '0x61a3ed31b43c8780e905a260a35faefcc527be7516aa11c0256729b5b351bc33',
s: '0x40349190569279751135161d22529dc25add4f6069af05be04cacbda2ace2254',
},
},
];

View File

@@ -1,16 +1,16 @@
[
{
"tokenA": {
"address": "0x323b5d4c32345ced77393b3530b1eed0f346429d",
"minAmount": "0",
"maxAmount": "10000000000000000000",
"precision": 5
},
"tokenB": {
"address": "0xef7fff64389b814a946f3e92105513705ca6b990",
"minAmount": "0",
"maxAmount": "50000000000000000000",
"precision": 5
}
}
{
"tokenA": {
"address": "0x323b5d4c32345ced77393b3530b1eed0f346429d",
"minAmount": "0",
"maxAmount": "10000000000000000000",
"precision": 5
},
"tokenB": {
"address": "0xef7fff64389b814a946f3e92105513705ca6b990",
"minAmount": "0",
"maxAmount": "50000000000000000000",
"precision": 5
}
}
]

View File

@@ -3,18 +3,18 @@ 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,
},
},
{
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,
},
},
];

View File

@@ -24,128 +24,128 @@ chai.use(chaiAsPromised);
const expect = chai.expect;
describe('HttpClient', () => {
const relayUrl = 'https://example.com';
const relayerClient = new HttpClient(relayUrl);
afterEach(() => {
fetchMock.restore();
});
describe('#constructor', () => {
it('should remove trailing slashes from api url', async () => {
const urlWithTrailingSlash = 'https://slash.com/';
const urlWithoutTrailingSlash = 'https://slash.com';
const client = new HttpClient(urlWithTrailingSlash);
const sanitizedUrl = (client as any)._apiEndpointUrl;
expect(sanitizedUrl).to.be.deep.equal(urlWithoutTrailingSlash);
});
});
describe('#getTokenPairsAsync', () => {
const url = `${relayUrl}/token_pairs`;
it('gets token pairs', async () => {
fetchMock.get(url, tokenPairsResponseJSON);
const tokenPairs = await relayerClient.getTokenPairsAsync();
expect(tokenPairs).to.be.deep.equal(tokenPairsResponse);
});
it('gets specific token pairs for request', async () => {
const tokenAddress = '0x323b5d4c32345ced77393b3530b1eed0f346429d';
const tokenPairsRequest = {
tokenA: tokenAddress,
};
const urlWithQuery = `${url}?tokenA=${tokenAddress}`;
fetchMock.get(urlWithQuery, tokenPairsResponseJSON);
const tokenPairs = await relayerClient.getTokenPairsAsync(tokenPairsRequest);
expect(tokenPairs).to.be.deep.equal(tokenPairsResponse);
});
it('throws an error for invalid JSON response', async () => {
fetchMock.get(url, { test: 'dummy' });
expect(relayerClient.getTokenPairsAsync()).to.be.rejected();
});
});
describe('#getOrdersAsync', () => {
const url = `${relayUrl}/orders`;
it('gets orders', async () => {
fetchMock.get(url, ordersResponseJSON);
const orders = await relayerClient.getOrdersAsync();
expect(orders).to.be.deep.equal(ordersResponse);
});
it('gets specific orders for request', async () => {
const tokenAddress = '0x323b5d4c32345ced77393b3530b1eed0f346429d';
const ordersRequest = {
tokenAddress,
};
const urlWithQuery = `${url}?tokenAddress=${tokenAddress}`;
fetchMock.get(urlWithQuery, ordersResponseJSON);
const orders = await relayerClient.getOrdersAsync(ordersRequest);
expect(orders).to.be.deep.equal(ordersResponse);
});
it('throws an error for invalid JSON response', async () => {
fetchMock.get(url, { test: 'dummy' });
expect(relayerClient.getOrdersAsync()).to.be.rejected();
});
});
describe('#getOrderAsync', () => {
const orderHash = '0xabc67323774bdbd24d94f977fa9ac94a50f016026fd13f42990861238897721f';
const url = `${relayUrl}/order/${orderHash}`;
it('gets order', async () => {
fetchMock.get(url, orderResponseJSON);
const order = await relayerClient.getOrderAsync(orderHash);
expect(order).to.be.deep.equal(orderResponse);
});
it('throws an error for invalid JSON response', async () => {
fetchMock.get(url, { test: 'dummy' });
expect(relayerClient.getOrderAsync(orderHash)).to.be.rejected();
});
});
describe('#getOrderBookAsync', () => {
const request = {
baseTokenAddress: '0x323b5d4c32345ced77393b3530b1eed0f346429d',
quoteTokenAddress: '0xa2b31dacf30a9c50ca473337c01d8a201ae33e32',
};
const url = `${relayUrl}/orderbook?baseTokenAddress=${request.baseTokenAddress}&quoteTokenAddress=${
request.quoteTokenAddress
}`;
it('gets order book', async () => {
fetchMock.get(url, orderbookJSON);
const orderbook = await relayerClient.getOrderbookAsync(request);
expect(orderbook).to.be.deep.equal(orderbookResponse);
});
it('throws an error for invalid JSON response', async () => {
fetchMock.get(url, { test: 'dummy' });
expect(relayerClient.getOrderbookAsync(request)).to.be.rejected();
});
});
describe('#getFeesAsync', () => {
const request = {
exchangeContractAddress: '0x12459c951127e0c374ff9105dda097662a027093',
maker: '0x9e56625509c2f60af937f23b7b532600390e8c8b',
taker: '0xa2b31dacf30a9c50ca473337c01d8a201ae33e32',
makerTokenAddress: '0x323b5d4c32345ced77393b3530b1eed0f346429d',
takerTokenAddress: '0xef7fff64389b814a946f3e92105513705ca6b990',
makerTokenAmount: new BigNumber('10000000000000000000'),
takerTokenAmount: new BigNumber('30000000000000000000'),
salt: new BigNumber('256'),
expirationUnixTimestampSec: new BigNumber('42'),
};
const url = `${relayUrl}/fees`;
it('gets fees', async () => {
fetchMock.post(url, feesResponseJSON);
const fees = await relayerClient.getFeesAsync(request);
expect(fees).to.be.deep.equal(feesResponse);
});
it('does not mutate input', async () => {
fetchMock.post(url, feesResponseJSON);
const makerTokenAmountBefore = new BigNumber(request.makerTokenAmount);
const takerTokenAmountBefore = new BigNumber(request.takerTokenAmount);
const saltBefore = new BigNumber(request.salt);
const expirationUnixTimestampSecBefore = new BigNumber(request.expirationUnixTimestampSec);
await relayerClient.getFeesAsync(request);
expect(makerTokenAmountBefore).to.be.deep.equal(request.makerTokenAmount);
expect(takerTokenAmountBefore).to.be.deep.equal(request.takerTokenAmount);
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 () => {
fetchMock.post(url, { test: 'dummy' });
expect(relayerClient.getFeesAsync(request)).to.be.rejected();
});
});
const relayUrl = 'https://example.com';
const relayerClient = new HttpClient(relayUrl);
afterEach(() => {
fetchMock.restore();
});
describe('#constructor', () => {
it('should remove trailing slashes from api url', async () => {
const urlWithTrailingSlash = 'https://slash.com/';
const urlWithoutTrailingSlash = 'https://slash.com';
const client = new HttpClient(urlWithTrailingSlash);
const sanitizedUrl = (client as any)._apiEndpointUrl;
expect(sanitizedUrl).to.be.deep.equal(urlWithoutTrailingSlash);
});
});
describe('#getTokenPairsAsync', () => {
const url = `${relayUrl}/token_pairs`;
it('gets token pairs', async () => {
fetchMock.get(url, tokenPairsResponseJSON);
const tokenPairs = await relayerClient.getTokenPairsAsync();
expect(tokenPairs).to.be.deep.equal(tokenPairsResponse);
});
it('gets specific token pairs for request', async () => {
const tokenAddress = '0x323b5d4c32345ced77393b3530b1eed0f346429d';
const tokenPairsRequest = {
tokenA: tokenAddress,
};
const urlWithQuery = `${url}?tokenA=${tokenAddress}`;
fetchMock.get(urlWithQuery, tokenPairsResponseJSON);
const tokenPairs = await relayerClient.getTokenPairsAsync(tokenPairsRequest);
expect(tokenPairs).to.be.deep.equal(tokenPairsResponse);
});
it('throws an error for invalid JSON response', async () => {
fetchMock.get(url, { test: 'dummy' });
expect(relayerClient.getTokenPairsAsync()).to.be.rejected();
});
});
describe('#getOrdersAsync', () => {
const url = `${relayUrl}/orders`;
it('gets orders', async () => {
fetchMock.get(url, ordersResponseJSON);
const orders = await relayerClient.getOrdersAsync();
expect(orders).to.be.deep.equal(ordersResponse);
});
it('gets specific orders for request', async () => {
const tokenAddress = '0x323b5d4c32345ced77393b3530b1eed0f346429d';
const ordersRequest = {
tokenAddress,
};
const urlWithQuery = `${url}?tokenAddress=${tokenAddress}`;
fetchMock.get(urlWithQuery, ordersResponseJSON);
const orders = await relayerClient.getOrdersAsync(ordersRequest);
expect(orders).to.be.deep.equal(ordersResponse);
});
it('throws an error for invalid JSON response', async () => {
fetchMock.get(url, { test: 'dummy' });
expect(relayerClient.getOrdersAsync()).to.be.rejected();
});
});
describe('#getOrderAsync', () => {
const orderHash = '0xabc67323774bdbd24d94f977fa9ac94a50f016026fd13f42990861238897721f';
const url = `${relayUrl}/order/${orderHash}`;
it('gets order', async () => {
fetchMock.get(url, orderResponseJSON);
const order = await relayerClient.getOrderAsync(orderHash);
expect(order).to.be.deep.equal(orderResponse);
});
it('throws an error for invalid JSON response', async () => {
fetchMock.get(url, { test: 'dummy' });
expect(relayerClient.getOrderAsync(orderHash)).to.be.rejected();
});
});
describe('#getOrderBookAsync', () => {
const request = {
baseTokenAddress: '0x323b5d4c32345ced77393b3530b1eed0f346429d',
quoteTokenAddress: '0xa2b31dacf30a9c50ca473337c01d8a201ae33e32',
};
const url = `${relayUrl}/orderbook?baseTokenAddress=${request.baseTokenAddress}&quoteTokenAddress=${
request.quoteTokenAddress
}`;
it('gets order book', async () => {
fetchMock.get(url, orderbookJSON);
const orderbook = await relayerClient.getOrderbookAsync(request);
expect(orderbook).to.be.deep.equal(orderbookResponse);
});
it('throws an error for invalid JSON response', async () => {
fetchMock.get(url, { test: 'dummy' });
expect(relayerClient.getOrderbookAsync(request)).to.be.rejected();
});
});
describe('#getFeesAsync', () => {
const request = {
exchangeContractAddress: '0x12459c951127e0c374ff9105dda097662a027093',
maker: '0x9e56625509c2f60af937f23b7b532600390e8c8b',
taker: '0xa2b31dacf30a9c50ca473337c01d8a201ae33e32',
makerTokenAddress: '0x323b5d4c32345ced77393b3530b1eed0f346429d',
takerTokenAddress: '0xef7fff64389b814a946f3e92105513705ca6b990',
makerTokenAmount: new BigNumber('10000000000000000000'),
takerTokenAmount: new BigNumber('30000000000000000000'),
salt: new BigNumber('256'),
expirationUnixTimestampSec: new BigNumber('42'),
};
const url = `${relayUrl}/fees`;
it('gets fees', async () => {
fetchMock.post(url, feesResponseJSON);
const fees = await relayerClient.getFeesAsync(request);
expect(fees).to.be.deep.equal(feesResponse);
});
it('does not mutate input', async () => {
fetchMock.post(url, feesResponseJSON);
const makerTokenAmountBefore = new BigNumber(request.makerTokenAmount);
const takerTokenAmountBefore = new BigNumber(request.takerTokenAmount);
const saltBefore = new BigNumber(request.salt);
const expirationUnixTimestampSecBefore = new BigNumber(request.expirationUnixTimestampSec);
await relayerClient.getFeesAsync(request);
expect(makerTokenAmountBefore).to.be.deep.equal(request.makerTokenAmount);
expect(takerTokenAmountBefore).to.be.deep.equal(request.takerTokenAmount);
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 () => {
fetchMock.post(url, { test: 'dummy' });
expect(relayerClient.getFeesAsync(request)).to.be.rejected();
});
});
});

View File

@@ -7,13 +7,13 @@ import { orderbookChannelMessageParser } from '../src/utils/orderbook_channel_me
import { orderResponse } from './fixtures/standard_relayer_api/order/0xabc67323774bdbd24d94f977fa9ac94a50f016026fd13f42990861238897721f';
import { orderbookResponse } from './fixtures/standard_relayer_api/orderbook';
import {
malformedSnapshotOrderbookChannelMessage,
snapshotOrderbookChannelMessage,
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,
malformedUpdateOrderbookChannelMessage,
updateOrderbookChannelMessage,
} from './fixtures/standard_relayer_api/update_orderbook_channel_message';
chai.config.includeStack = true;
@@ -21,56 +21,56 @@ 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 = `{
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 = `{
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');
});
});
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');
});
});
});

View File

@@ -10,52 +10,52 @@ chai.use(dirtyChai);
const expect = chai.expect;
describe('WebSocketOrderbookChannel', () => {
const websocketUrl = 'ws://localhost:8080';
const orderbookChannel = new WebSocketOrderbookChannel(websocketUrl);
const subscriptionOpts = {
baseTokenAddress: '0x323b5d4c32345ced77393b3530b1eed0f346429d',
quoteTokenAddress: '0xef7fff64389b814a946f3e92105513705ca6b990',
snapshot: true,
limit: 100,
};
const emptyOrderbookChannelHandler = {
onSnapshot: () => {
_.noop();
},
onUpdate: () => {
_.noop();
},
onError: () => {
_.noop();
},
onClose: () => {
_.noop();
},
};
describe('#subscribe', () => {
it('throws when subscriptionOpts does not conform to schema', () => {
const badSubscribeCall = orderbookChannel.subscribe.bind(
orderbookChannel,
{},
emptyOrderbookChannelHandler,
);
expect(badSubscribeCall).throws(
'Expected subscriptionOpts to conform to schema /RelayerApiOrderbookChannelSubscribePayload\nEncountered: {}\nValidation errors: instance requires property "baseTokenAddress", instance requires property "quoteTokenAddress"',
);
});
it('throws when handler has the incorrect members', () => {
const badSubscribeCall = orderbookChannel.subscribe.bind(orderbookChannel, subscriptionOpts, {});
expect(badSubscribeCall).throws(
'Expected handler.onSnapshot to be of type function, encountered: undefined',
);
});
it('does not throw when inputs are of correct types', () => {
const goodSubscribeCall = orderbookChannel.subscribe.bind(
orderbookChannel,
subscriptionOpts,
emptyOrderbookChannelHandler,
);
expect(goodSubscribeCall).to.not.throw();
});
});
const websocketUrl = 'ws://localhost:8080';
const orderbookChannel = new WebSocketOrderbookChannel(websocketUrl);
const subscriptionOpts = {
baseTokenAddress: '0x323b5d4c32345ced77393b3530b1eed0f346429d',
quoteTokenAddress: '0xef7fff64389b814a946f3e92105513705ca6b990',
snapshot: true,
limit: 100,
};
const emptyOrderbookChannelHandler = {
onSnapshot: () => {
_.noop();
},
onUpdate: () => {
_.noop();
},
onError: () => {
_.noop();
},
onClose: () => {
_.noop();
},
};
describe('#subscribe', () => {
it('throws when subscriptionOpts does not conform to schema', () => {
const badSubscribeCall = orderbookChannel.subscribe.bind(
orderbookChannel,
{},
emptyOrderbookChannelHandler,
);
expect(badSubscribeCall).throws(
'Expected subscriptionOpts to conform to schema /RelayerApiOrderbookChannelSubscribePayload\nEncountered: {}\nValidation errors: instance requires property "baseTokenAddress", instance requires property "quoteTokenAddress"',
);
});
it('throws when handler has the incorrect members', () => {
const badSubscribeCall = orderbookChannel.subscribe.bind(orderbookChannel, subscriptionOpts, {});
expect(badSubscribeCall).throws(
'Expected handler.onSnapshot to be of type function, encountered: undefined',
);
});
it('does not throw when inputs are of correct types', () => {
const goodSubscribeCall = orderbookChannel.subscribe.bind(
orderbookChannel,
subscriptionOpts,
emptyOrderbookChannelHandler,
);
expect(goodSubscribeCall).to.not.throw();
});
});
});

View File

@@ -1,12 +1,12 @@
{
"extends": "../../tsconfig",
"compilerOptions": {
"outDir": "lib"
},
"include": [
"./src/**/*",
"./test/**/*",
"../../node_modules/chai-as-promised-typescript-typings/index.d.ts",
"../../node_modules/chai-typescript-typings/index.d.ts"
]
"extends": "../../tsconfig",
"compilerOptions": {
"outDir": "lib"
},
"include": [
"./src/**/*",
"./test/**/*",
"../../node_modules/chai-as-promised-typescript-typings/index.d.ts",
"../../node_modules/chai-typescript-typings/index.d.ts"
]
}

View File

@@ -1,3 +1,3 @@
{
"extends": ["@0xproject/tslint-config"]
"extends": ["@0xproject/tslint-config"]
}