diff options
Diffstat (limited to 'packages/connect/src/http_client.ts')
-rw-r--r-- | packages/connect/src/http_client.ts | 171 |
1 files changed, 171 insertions, 0 deletions
diff --git a/packages/connect/src/http_client.ts b/packages/connect/src/http_client.ts new file mode 100644 index 000000000..ab8c6bfa1 --- /dev/null +++ b/packages/connect/src/http_client.ts @@ -0,0 +1,171 @@ +import 'isomorphic-fetch'; +import * as _ from 'lodash'; +import {BigNumber} from 'bignumber.js'; +import * as queryString from 'query-string'; +import {assert} from '@0xproject/assert'; +import {schemas} from '@0xproject/json-schemas'; +import {SignedOrder} from '0x.js'; +import { + Client, + FeesRequest, + FeesResponse, + OrderbookRequest, + OrderbookResponse, + OrdersRequest, + TokenPairsItem, + TokenPairsRequest, +} from './types'; +import {schemas as clientSchemas} from './schemas/schemas'; +import {typeConverters} from './utils/type_converters'; + +interface RequestOptions { + params?: object; + payload?: object; +} + +enum RequestType { + Get = 'GET', + Post = 'POST', +} + +/** + * This class includes all the functionality related to interacting with a set of HTTP endpoints + * that implement the standard relayer API v0 + */ +export class HttpClient implements Client { + private apiEndpointUrl: string; + /** + * Instantiates a new HttpClient instance + * @param url The base url for making API calls + * @return An instance of HttpClient + */ + constructor(url: string) { + assert.isHttpUrl('url', url); + this.apiEndpointUrl = url; + } + /** + * 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 tokenPairs = await this._requestAsync('/token_pairs', RequestType.Get, requestOpts); + assert.doesConformToSchema( + 'tokenPairs', tokenPairs, schemas.relayerApiTokenPairsResponseSchema); + _.each(tokenPairs, (tokenPair: object) => { + typeConverters.convertStringsFieldsToBigNumbers(tokenPair, [ + 'tokenA.minAmount', + 'tokenA.maxAmount', + 'tokenB.minAmount', + 'tokenB.maxAmount', + ]); + }); + 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 orders = await this._requestAsync(`/orders`, RequestType.Get, requestOpts); + assert.doesConformToSchema('orders', orders, schemas.signedOrdersSchema); + _.each(orders, (order: object) => typeConverters.convertOrderStringFieldsToBigNumber(order)); + 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 order = await this._requestAsync(`/order/${orderHash}`, RequestType.Get); + assert.doesConformToSchema('order', order, schemas.signedOrderSchema); + typeConverters.convertOrderStringFieldsToBigNumber(order); + 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 orderBook = await this._requestAsync('/orderbook', RequestType.Get, requestOpts); + assert.doesConformToSchema('orderBook', orderBook, schemas.relayerApiOrderBookResponseSchema); + typeConverters.convertOrderbookStringFieldsToBigNumber(orderBook); + 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); + typeConverters.convertBigNumberFieldsToStrings(request, [ + 'makerTokenAmount', + 'takerTokenAmount', + 'expirationUnixTimestampSec', + 'salt', + ]); + const requestOpts = { + payload: request, + }; + const fees = await this._requestAsync('/fees', RequestType.Post, requestOpts); + assert.doesConformToSchema('fees', fees, schemas.relayerApiFeesResponseSchema); + typeConverters.convertStringsFieldsToBigNumbers(fees, ['makerFee', 'takerFee']); + 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', RequestType.Post, requestOpts); + } + private async _requestAsync(path: string, requestType: RequestType, requestOptions?: RequestOptions): 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}/v0${path}${query}`; + const headers = new Headers({ + 'content-type': 'application/json', + }); + const response = await fetch(url, { + method: requestType, + body: payload, + headers, + }); + if (!response.ok) { + throw Error(response.statusText); + } + const json = await response.json(); + return json; + } +} |