aboutsummaryrefslogtreecommitdiffstats
path: root/packages
diff options
context:
space:
mode:
Diffstat (limited to 'packages')
-rw-r--r--packages/0x.js/CHANGELOG.md5
-rw-r--r--packages/0x.js/src/0x.ts43
-rw-r--r--packages/0x.js/src/contract_wrappers/contract_wrapper.ts24
-rw-r--r--packages/0x.js/src/order_watcher/event_watcher.ts6
-rw-r--r--packages/0x.js/src/order_watcher/expiration_watcher.ts5
-rw-r--r--packages/0x.js/src/order_watcher/order_state_watcher.ts18
-rw-r--r--packages/0x.js/src/types.ts4
-rw-r--r--packages/0x.js/test/event_watcher_test.ts11
-rw-r--r--packages/0x.js/test/order_state_watcher_test.ts32
-rw-r--r--packages/0x.js/test/utils/report_callback_errors.ts6
-rw-r--r--packages/connect/CHANGELOG.md6
-rw-r--r--packages/connect/src/http_client.ts13
-rw-r--r--packages/connect/test/http_client_test.ts21
-rw-r--r--packages/utils/CHANGELOG.md3
-rw-r--r--packages/utils/src/interval_utils.ts21
15 files changed, 145 insertions, 73 deletions
diff --git a/packages/0x.js/CHANGELOG.md b/packages/0x.js/CHANGELOG.md
index b969abfba..ab2537879 100644
--- a/packages/0x.js/CHANGELOG.md
+++ b/packages/0x.js/CHANGELOG.md
@@ -1,5 +1,10 @@
# CHANGELOG
+## v0.x.x - _TBD, 2018_
+
+ * Add an error parameter to the order watcher callback (#312)
+ * Fix the bug making it impossible to catch some errors from awaitTransactionMinedAsync (#312)
+
## v0.29.1 - _January 11, 2018_
* Fixed bignumber config issue #301 (#305)
diff --git a/packages/0x.js/src/0x.ts b/packages/0x.js/src/0x.ts
index 244b77a85..e1b0ef08e 100644
--- a/packages/0x.js/src/0x.ts
+++ b/packages/0x.js/src/0x.ts
@@ -302,26 +302,33 @@ export class ZeroEx {
const txReceiptPromise = new Promise(
(resolve: (receipt: TransactionReceiptWithDecodedLogs) => void, reject) => {
- const intervalId = intervalUtils.setAsyncExcludingInterval(async () => {
- if (timeoutExceeded) {
- intervalUtils.clearAsyncExcludingInterval(intervalId);
- return reject(ZeroExError.TransactionMiningTimeout);
- }
+ const intervalId = intervalUtils.setAsyncExcludingInterval(
+ async () => {
+ if (timeoutExceeded) {
+ intervalUtils.clearAsyncExcludingInterval(intervalId);
+ return reject(ZeroExError.TransactionMiningTimeout);
+ }
- const transactionReceipt = await this._web3Wrapper.getTransactionReceiptAsync(txHash);
- if (!_.isNull(transactionReceipt)) {
+ const transactionReceipt = await this._web3Wrapper.getTransactionReceiptAsync(txHash);
+ if (!_.isNull(transactionReceipt)) {
+ intervalUtils.clearAsyncExcludingInterval(intervalId);
+ const logsWithDecodedArgs = _.map(
+ transactionReceipt.logs,
+ this._abiDecoder.tryToDecodeLogOrNoop.bind(this._abiDecoder),
+ );
+ const transactionReceiptWithDecodedLogArgs: TransactionReceiptWithDecodedLogs = {
+ ...transactionReceipt,
+ logs: logsWithDecodedArgs,
+ };
+ resolve(transactionReceiptWithDecodedLogArgs);
+ }
+ },
+ pollingIntervalMs,
+ (err: Error) => {
intervalUtils.clearAsyncExcludingInterval(intervalId);
- const logsWithDecodedArgs = _.map(
- transactionReceipt.logs,
- this._abiDecoder.tryToDecodeLogOrNoop.bind(this._abiDecoder),
- );
- const transactionReceiptWithDecodedLogArgs: TransactionReceiptWithDecodedLogs = {
- ...transactionReceipt,
- logs: logsWithDecodedArgs,
- };
- resolve(transactionReceiptWithDecodedLogArgs);
- }
- }, pollingIntervalMs);
+ reject(err);
+ },
+ );
},
);
diff --git a/packages/0x.js/src/contract_wrappers/contract_wrapper.ts b/packages/0x.js/src/contract_wrappers/contract_wrapper.ts
index 9c4e5dfd3..27551c01d 100644
--- a/packages/0x.js/src/contract_wrappers/contract_wrapper.ts
+++ b/packages/0x.js/src/contract_wrappers/contract_wrapper.ts
@@ -167,6 +167,7 @@ export class ContractWrapper {
this._blockAndLogStreamInterval = intervalUtils.setAsyncExcludingInterval(
this._reconcileBlockAsync.bind(this),
constants.DEFAULT_BLOCK_POLLING_INTERVAL,
+ this._onReconcileBlockError.bind(this),
);
let isRemoved = false;
this._onLogAddedSubscriptionToken = this._blockAndLogStreamerIfExists.subscribeToOnLogAdded(
@@ -177,6 +178,12 @@ export class ContractWrapper {
this._onLogStateChanged.bind(this, isRemoved),
);
}
+ private _onReconcileBlockError(err: Error): void {
+ const filterTokens = _.keys(this._filterCallbacks);
+ _.each(filterTokens, filterToken => {
+ this._unsubscribe(filterToken, err);
+ });
+ }
private _setNetworkId(networkId: number): void {
this._networkId = networkId;
}
@@ -190,18 +197,11 @@ export class ContractWrapper {
delete this._blockAndLogStreamerIfExists;
}
private async _reconcileBlockAsync(): Promise<void> {
- try {
- const latestBlock = await this._web3Wrapper.getBlockAsync(BlockParamLiteral.Latest);
- // We need to coerce to Block type cause Web3.Block includes types for mempool blocks
- if (!_.isUndefined(this._blockAndLogStreamerIfExists)) {
- // If we clear the interval while fetching the block - this._blockAndLogStreamer will be undefined
- await this._blockAndLogStreamerIfExists.reconcileNewBlock((latestBlock as any) as Block);
- }
- } catch (err) {
- const filterTokens = _.keys(this._filterCallbacks);
- _.each(filterTokens, filterToken => {
- this._unsubscribe(filterToken, err);
- });
+ const latestBlock = await this._web3Wrapper.getBlockAsync(BlockParamLiteral.Latest);
+ // We need to coerce to Block type cause Web3.Block includes types for mempool blocks
+ if (!_.isUndefined(this._blockAndLogStreamerIfExists)) {
+ // If we clear the interval while fetching the block - this._blockAndLogStreamer will be undefined
+ await this._blockAndLogStreamerIfExists.reconcileNewBlock((latestBlock as any) as Block);
}
}
}
diff --git a/packages/0x.js/src/order_watcher/event_watcher.ts b/packages/0x.js/src/order_watcher/event_watcher.ts
index fc0b9264c..43a60957b 100644
--- a/packages/0x.js/src/order_watcher/event_watcher.ts
+++ b/packages/0x.js/src/order_watcher/event_watcher.ts
@@ -36,6 +36,10 @@ export class EventWatcher {
this._intervalIdIfExists = intervalUtils.setAsyncExcludingInterval(
this._pollForBlockchainEventsAsync.bind(this, callback),
this._pollingIntervalMs,
+ (err: Error) => {
+ this.unsubscribe();
+ callback(err);
+ },
);
}
public unsubscribe(): void {
@@ -78,7 +82,7 @@ export class EventWatcher {
...log,
};
if (!_.isUndefined(this._intervalIdIfExists)) {
- callback(logEvent);
+ callback(null, logEvent);
}
}
}
diff --git a/packages/0x.js/src/order_watcher/expiration_watcher.ts b/packages/0x.js/src/order_watcher/expiration_watcher.ts
index e7d085fc8..00b62162d 100644
--- a/packages/0x.js/src/order_watcher/expiration_watcher.ts
+++ b/packages/0x.js/src/order_watcher/expiration_watcher.ts
@@ -30,16 +30,17 @@ export class ExpirationWatcher {
if (!_.isUndefined(this._orderExpirationCheckingIntervalIdIfExists)) {
throw new Error(ZeroExError.SubscriptionAlreadyPresent);
}
- this._orderExpirationCheckingIntervalIdIfExists = intervalUtils.setAsyncExcludingInterval(
+ this._orderExpirationCheckingIntervalIdIfExists = intervalUtils.setInterval(
this._pruneExpiredOrders.bind(this, callback),
this._orderExpirationCheckingIntervalMs,
+ _.noop, // _pruneExpiredOrders never throws
);
}
public unsubscribe(): void {
if (_.isUndefined(this._orderExpirationCheckingIntervalIdIfExists)) {
throw new Error(ZeroExError.SubscriptionNotFound);
}
- intervalUtils.clearAsyncExcludingInterval(this._orderExpirationCheckingIntervalIdIfExists);
+ intervalUtils.clearInterval(this._orderExpirationCheckingIntervalIdIfExists);
delete this._orderExpirationCheckingIntervalIdIfExists;
}
public addOrder(orderHash: string, expirationUnixTimestampMs: BigNumber): void {
diff --git a/packages/0x.js/src/order_watcher/order_state_watcher.ts b/packages/0x.js/src/order_watcher/order_state_watcher.ts
index 9d7a733d8..12ac60960 100644
--- a/packages/0x.js/src/order_watcher/order_state_watcher.ts
+++ b/packages/0x.js/src/order_watcher/order_state_watcher.ts
@@ -155,6 +155,10 @@ export class OrderStateWatcher {
this._cleanupJobIntervalIdIfExists = intervalUtils.setAsyncExcludingInterval(
this._cleanupAsync.bind(this),
this._cleanupJobInterval,
+ (err: Error) => {
+ this.unsubscribe();
+ callback(err);
+ },
);
}
/**
@@ -207,11 +211,19 @@ export class OrderStateWatcher {
if (!_.isUndefined(this._orderByOrderHash[orderHash])) {
this.removeOrder(orderHash);
if (!_.isUndefined(this._callbackIfExists)) {
- this._callbackIfExists(orderState);
+ this._callbackIfExists(null, orderState);
}
}
}
- private async _onEventWatcherCallbackAsync(log: LogEvent): Promise<void> {
+ private async _onEventWatcherCallbackAsync(err: Error | null, logIfExists?: LogEvent): Promise<void> {
+ if (!_.isNull(err)) {
+ if (!_.isUndefined(this._callbackIfExists)) {
+ this._callbackIfExists(err);
+ this.unsubscribe();
+ }
+ return;
+ }
+ const log = logIfExists as LogEvent; // At this moment we are sure that no error occured and log is defined.
const maybeDecodedLog = this._abiDecoder.tryToDecodeLogOrNoop(log);
const isLogDecoded = !_.isUndefined((maybeDecodedLog as LogWithDecodedArgs<any>).event);
if (!isLogDecoded) {
@@ -332,7 +344,7 @@ export class OrderStateWatcher {
} else {
this._orderStateByOrderHashCache[orderHash] = orderState;
}
- this._callbackIfExists(orderState);
+ this._callbackIfExists(null, orderState);
}
}
private _addToDependentOrderHashes(signedOrder: SignedOrder, orderHash: string): void {
diff --git a/packages/0x.js/src/types.ts b/packages/0x.js/src/types.ts
index 44f8aa223..2decd92ba 100644
--- a/packages/0x.js/src/types.ts
+++ b/packages/0x.js/src/types.ts
@@ -51,7 +51,7 @@ export interface DecodedLogEvent<ArgsType> {
}
export type EventCallback<ArgsType> = (err: null | Error, log?: DecodedLogEvent<ArgsType>) => void;
-export type EventWatcherCallback = (log: LogEvent) => void;
+export type EventWatcherCallback = (err: null | Error, log?: LogEvent) => void;
export enum SolidityTypes {
Address = 'address',
@@ -406,5 +406,5 @@ export interface OrderStateInvalid {
export type OrderState = OrderStateValid | OrderStateInvalid;
-export type OnOrderStateChangeCallback = (orderState: OrderState) => void;
+export type OnOrderStateChangeCallback = (err: Error | null, orderState?: OrderState) => void;
// tslint:disable:max-file-line-count
diff --git a/packages/0x.js/test/event_watcher_test.ts b/packages/0x.js/test/event_watcher_test.ts
index ace1cd5d9..f92fb2b02 100644
--- a/packages/0x.js/test/event_watcher_test.ts
+++ b/packages/0x.js/test/event_watcher_test.ts
@@ -10,6 +10,7 @@ import { EventWatcher } from '../src/order_watcher/event_watcher';
import { DoneCallback } from '../src/types';
import { chaiSetup } from './utils/chai_setup';
+import { reportNodeCallbackErrors } from './utils/report_callback_errors';
import { web3Factory } from './utils/web3_factory';
chaiSetup.configure();
@@ -77,13 +78,14 @@ describe('EventWatcher', () => {
const getLogsStub = Sinon.stub(web3Wrapper, 'getLogsAsync');
getLogsStub.onCall(0).returns(logs);
stubs.push(getLogsStub);
- const callback = (event: LogEvent) => {
+ const expectedToBeCalledOnce = false;
+ const callback = reportNodeCallbackErrors(done, expectedToBeCalledOnce)((event: LogEvent) => {
const expectedLogEvent = expectedLogEvents.shift();
expect(event).to.be.deep.equal(expectedLogEvent);
if (_.isEmpty(expectedLogEvents)) {
done();
}
- };
+ });
eventWatcher.subscribe(callback);
});
it('correctly computes the difference and emits only changes', (done: DoneCallback) => {
@@ -111,13 +113,14 @@ describe('EventWatcher', () => {
getLogsStub.onCall(0).returns(initialLogs);
getLogsStub.onCall(1).returns(changedLogs);
stubs.push(getLogsStub);
- const callback = (event: LogEvent) => {
+ const expectedToBeCalledOnce = false;
+ const callback = reportNodeCallbackErrors(done, expectedToBeCalledOnce)((event: LogEvent) => {
const expectedLogEvent = expectedLogEvents.shift();
expect(event).to.be.deep.equal(expectedLogEvent);
if (_.isEmpty(expectedLogEvents)) {
done();
}
- };
+ });
eventWatcher.subscribe(callback);
});
});
diff --git a/packages/0x.js/test/order_state_watcher_test.ts b/packages/0x.js/test/order_state_watcher_test.ts
index 311752bd8..2e9202fe2 100644
--- a/packages/0x.js/test/order_state_watcher_test.ts
+++ b/packages/0x.js/test/order_state_watcher_test.ts
@@ -20,7 +20,7 @@ import { DoneCallback } from '../src/types';
import { chaiSetup } from './utils/chai_setup';
import { constants } from './utils/constants';
import { FillScenarios } from './utils/fill_scenarios';
-import { reportNoErrorCallbackErrors } from './utils/report_callback_errors';
+import { reportNodeCallbackErrors } from './utils/report_callback_errors';
import { TokenUtils } from './utils/token_utils';
import { web3Factory } from './utils/web3_factory';
@@ -134,7 +134,7 @@ describe('OrderStateWatcher', () => {
);
const orderHash = ZeroEx.getOrderHashHex(signedOrder);
zeroEx.orderStateWatcher.addOrder(signedOrder);
- const callback = reportNoErrorCallbackErrors(done)((orderState: OrderState) => {
+ const callback = reportNodeCallbackErrors(done)((orderState: OrderState) => {
expect(orderState.isValid).to.be.false();
const invalidOrderState = orderState as OrderStateInvalid;
expect(invalidOrderState.orderHash).to.be.equal(orderHash);
@@ -154,7 +154,7 @@ describe('OrderStateWatcher', () => {
fillableAmount,
);
zeroEx.orderStateWatcher.addOrder(signedOrder);
- const callback = reportNoErrorCallbackErrors(done)((orderState: OrderState) => {
+ const callback = reportNodeCallbackErrors(done)((orderState: OrderState) => {
throw new Error('OrderState callback fired for irrelevant order');
});
zeroEx.orderStateWatcher.subscribe(callback);
@@ -178,7 +178,7 @@ describe('OrderStateWatcher', () => {
);
const orderHash = ZeroEx.getOrderHashHex(signedOrder);
zeroEx.orderStateWatcher.addOrder(signedOrder);
- const callback = reportNoErrorCallbackErrors(done)((orderState: OrderState) => {
+ const callback = reportNodeCallbackErrors(done)((orderState: OrderState) => {
expect(orderState.isValid).to.be.false();
const invalidOrderState = orderState as OrderStateInvalid;
expect(invalidOrderState.orderHash).to.be.equal(orderHash);
@@ -202,7 +202,7 @@ describe('OrderStateWatcher', () => {
const orderHash = ZeroEx.getOrderHashHex(signedOrder);
zeroEx.orderStateWatcher.addOrder(signedOrder);
- const callback = reportNoErrorCallbackErrors(done)((orderState: OrderState) => {
+ const callback = reportNodeCallbackErrors(done)((orderState: OrderState) => {
expect(orderState.isValid).to.be.false();
const invalidOrderState = orderState as OrderStateInvalid;
expect(invalidOrderState.orderHash).to.be.equal(orderHash);
@@ -234,7 +234,7 @@ describe('OrderStateWatcher', () => {
const orderHash = ZeroEx.getOrderHashHex(signedOrder);
zeroEx.orderStateWatcher.addOrder(signedOrder);
- const callback = reportNoErrorCallbackErrors(done)((orderState: OrderState) => {
+ const callback = reportNodeCallbackErrors(done)((orderState: OrderState) => {
expect(orderState.isValid).to.be.true();
const validOrderState = orderState as OrderStateValid;
expect(validOrderState.orderHash).to.be.equal(orderHash);
@@ -273,7 +273,7 @@ describe('OrderStateWatcher', () => {
fillableAmount,
taker,
);
- const callback = reportNoErrorCallbackErrors(done)();
+ const callback = reportNodeCallbackErrors(done)();
zeroEx.orderStateWatcher.addOrder(signedOrder);
zeroEx.orderStateWatcher.subscribe(callback);
await zeroEx.token.setProxyAllowanceAsync(zrxTokenAddress, maker, new BigNumber(0));
@@ -295,7 +295,7 @@ describe('OrderStateWatcher', () => {
const fillAmountInBaseUnits = ZeroEx.toBaseUnitAmount(new BigNumber(2), decimals);
const orderHash = ZeroEx.getOrderHashHex(signedOrder);
zeroEx.orderStateWatcher.addOrder(signedOrder);
- const callback = reportNoErrorCallbackErrors(done)((orderState: OrderState) => {
+ const callback = reportNodeCallbackErrors(done)((orderState: OrderState) => {
expect(orderState.isValid).to.be.true();
const validOrderState = orderState as OrderStateValid;
expect(validOrderState.orderHash).to.be.equal(orderHash);
@@ -330,7 +330,7 @@ describe('OrderStateWatcher', () => {
const changedMakerApprovalAmount = ZeroEx.toBaseUnitAmount(new BigNumber(3), decimals);
zeroEx.orderStateWatcher.addOrder(signedOrder);
- const callback = reportNoErrorCallbackErrors(done)((orderState: OrderState) => {
+ const callback = reportNodeCallbackErrors(done)((orderState: OrderState) => {
const validOrderState = orderState as OrderStateValid;
const orderRelevantState = validOrderState.orderRelevantState;
expect(orderRelevantState.remainingFillableMakerTokenAmount).to.be.bignumber.equal(
@@ -360,7 +360,7 @@ describe('OrderStateWatcher', () => {
const transferAmount = makerBalance.sub(remainingAmount);
zeroEx.orderStateWatcher.addOrder(signedOrder);
- const callback = reportNoErrorCallbackErrors(done)((orderState: OrderState) => {
+ const callback = reportNodeCallbackErrors(done)((orderState: OrderState) => {
expect(orderState.isValid).to.be.true();
const validOrderState = orderState as OrderStateValid;
const orderRelevantState = validOrderState.orderRelevantState;
@@ -395,7 +395,7 @@ describe('OrderStateWatcher', () => {
const transferTokenAmount = makerFee.sub(remainingTokenAmount);
zeroEx.orderStateWatcher.addOrder(signedOrder);
- const callback = reportNoErrorCallbackErrors(done)((orderState: OrderState) => {
+ const callback = reportNodeCallbackErrors(done)((orderState: OrderState) => {
expect(orderState.isValid).to.be.true();
const validOrderState = orderState as OrderStateValid;
const orderRelevantState = validOrderState.orderRelevantState;
@@ -429,7 +429,7 @@ describe('OrderStateWatcher', () => {
const transferTokenAmount = makerFee.sub(remainingTokenAmount);
zeroEx.orderStateWatcher.addOrder(signedOrder);
- const callback = reportNoErrorCallbackErrors(done)((orderState: OrderState) => {
+ const callback = reportNodeCallbackErrors(done)((orderState: OrderState) => {
const validOrderState = orderState as OrderStateValid;
const orderRelevantState = validOrderState.orderRelevantState;
expect(orderRelevantState.remainingFillableMakerTokenAmount).to.be.bignumber.equal(
@@ -464,7 +464,7 @@ describe('OrderStateWatcher', () => {
zeroEx.orderStateWatcher.addOrder(signedOrder);
- const callback = reportNoErrorCallbackErrors(done)((orderState: OrderState) => {
+ const callback = reportNodeCallbackErrors(done)((orderState: OrderState) => {
const validOrderState = orderState as OrderStateValid;
const orderRelevantState = validOrderState.orderRelevantState;
expect(orderRelevantState.remainingFillableMakerTokenAmount).to.be.bignumber.equal(
@@ -492,7 +492,7 @@ describe('OrderStateWatcher', () => {
const orderHash = ZeroEx.getOrderHashHex(signedOrder);
zeroEx.orderStateWatcher.addOrder(signedOrder);
- const callback = reportNoErrorCallbackErrors(done)((orderState: OrderState) => {
+ const callback = reportNodeCallbackErrors(done)((orderState: OrderState) => {
expect(orderState.isValid).to.be.false();
const invalidOrderState = orderState as OrderStateInvalid;
expect(invalidOrderState.orderHash).to.be.equal(orderHash);
@@ -516,7 +516,7 @@ describe('OrderStateWatcher', () => {
const orderHash = ZeroEx.getOrderHashHex(signedOrder);
zeroEx.orderStateWatcher.addOrder(signedOrder);
- const callback = reportNoErrorCallbackErrors(done)((orderState: OrderState) => {
+ const callback = reportNodeCallbackErrors(done)((orderState: OrderState) => {
expect(orderState.isValid).to.be.false();
const invalidOrderState = orderState as OrderStateInvalid;
expect(invalidOrderState.orderHash).to.be.equal(orderHash);
@@ -543,7 +543,7 @@ describe('OrderStateWatcher', () => {
const orderHash = ZeroEx.getOrderHashHex(signedOrder);
zeroEx.orderStateWatcher.addOrder(signedOrder);
- const callback = reportNoErrorCallbackErrors(done)((orderState: OrderState) => {
+ const callback = reportNodeCallbackErrors(done)((orderState: OrderState) => {
expect(orderState.isValid).to.be.true();
const validOrderState = orderState as OrderStateValid;
expect(validOrderState.orderHash).to.be.equal(orderHash);
diff --git a/packages/0x.js/test/utils/report_callback_errors.ts b/packages/0x.js/test/utils/report_callback_errors.ts
index a7d9e61be..27c9745c9 100644
--- a/packages/0x.js/test/utils/report_callback_errors.ts
+++ b/packages/0x.js/test/utils/report_callback_errors.ts
@@ -25,7 +25,7 @@ export const reportNoErrorCallbackErrors = (done: DoneCallback, expectToBeCalled
};
};
-export const reportNodeCallbackErrors = (done: DoneCallback) => {
+export const reportNodeCallbackErrors = (done: DoneCallback, expectToBeCalledOnce = true) => {
return <T>(f?: (value: T) => void) => {
const wrapped = (error: Error | null, value: T | undefined) => {
if (!_.isNull(error)) {
@@ -37,7 +37,9 @@ export const reportNodeCallbackErrors = (done: DoneCallback) => {
}
try {
f(value as T);
- done();
+ if (expectToBeCalledOnce) {
+ done();
+ }
} catch (err) {
done(err);
}
diff --git a/packages/connect/CHANGELOG.md b/packages/connect/CHANGELOG.md
index 2d9e2d89f..d8e99b5d3 100644
--- a/packages/connect/CHANGELOG.md
+++ b/packages/connect/CHANGELOG.md
@@ -1,5 +1,11 @@
# CHANGELOG
+## v0.x.x - _TBD, 2017_
+
+ * Sanitize api endpoint url and remove trailing slashes (#318)
+ * Improve error message text in HttpClient (#318)
+ * Stop appending '/v0' to api endpoint url in HttpClient (#318)
+
## v0.4.0 - _January 11, 2017_
* Prevent getFeesAsync method on HttpClient from mutating input (#296)
diff --git a/packages/connect/src/http_client.ts b/packages/connect/src/http_client.ts
index 5604a9607..3df77b0f0 100644
--- a/packages/connect/src/http_client.ts
+++ b/packages/connect/src/http_client.ts
@@ -20,6 +20,7 @@ import {
} from './types';
import { relayerResponseJsonParsers } from './utils/relayer_response_json_parsers';
+const TRAILING_SLASHES_REGEX = /\/+$/;
/**
* This class includes all the functionality related to interacting with a set of HTTP endpoints
* that implement the standard relayer API v0
@@ -33,7 +34,7 @@ export class HttpClient implements Client {
*/
constructor(url: string) {
assert.isHttpUrl('url', url);
- this._apiEndpointUrl = url;
+ this._apiEndpointUrl = url.replace(TRAILING_SLASHES_REGEX, ''); // remove trailing slashes
}
/**
* Retrieve token pair info from the API
@@ -130,20 +131,22 @@ export class HttpClient implements Client {
const stringifiedParams = queryString.stringify(params);
query = `?${stringifiedParams}`;
}
- const url = `${this._apiEndpointUrl}/v0${path}${query}`;
+ 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) {
- throw Error(response.statusText);
+ const errorString = `${response.status} - ${response.statusText}\n${requestType} ${url}\n${JSON.stringify(
+ json,
+ )}`;
+ throw Error(errorString);
}
- const json = await response.json();
return json;
}
}
diff --git a/packages/connect/test/http_client_test.ts b/packages/connect/test/http_client_test.ts
index e7096edad..15759d911 100644
--- a/packages/connect/test/http_client_test.ts
+++ b/packages/connect/test/http_client_test.ts
@@ -29,14 +29,23 @@ describe('HttpClient', () => {
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}/v0/token_pairs`;
+ 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 specfic token pairs for request', async () => {
+ it('gets specific token pairs for request', async () => {
const tokenAddress = '0x323b5d4c32345ced77393b3530b1eed0f346429d';
const tokenPairsRequest = {
tokenA: tokenAddress,
@@ -52,7 +61,7 @@ describe('HttpClient', () => {
});
});
describe('#getOrdersAsync', () => {
- const url = `${relayUrl}/v0/orders`;
+ const url = `${relayUrl}/orders`;
it('gets orders', async () => {
fetchMock.get(url, ordersResponseJSON);
const orders = await relayerClient.getOrdersAsync();
@@ -75,7 +84,7 @@ describe('HttpClient', () => {
});
describe('#getOrderAsync', () => {
const orderHash = '0xabc67323774bdbd24d94f977fa9ac94a50f016026fd13f42990861238897721f';
- const url = `${relayUrl}/v0/order/${orderHash}`;
+ const url = `${relayUrl}/order/${orderHash}`;
it('gets order', async () => {
fetchMock.get(url, orderResponseJSON);
const order = await relayerClient.getOrderAsync(orderHash);
@@ -91,7 +100,7 @@ describe('HttpClient', () => {
baseTokenAddress: '0x323b5d4c32345ced77393b3530b1eed0f346429d',
quoteTokenAddress: '0xa2b31dacf30a9c50ca473337c01d8a201ae33e32',
};
- const url = `${relayUrl}/v0/orderbook?baseTokenAddress=${request.baseTokenAddress}&quoteTokenAddress=${
+ const url = `${relayUrl}/orderbook?baseTokenAddress=${request.baseTokenAddress}&quoteTokenAddress=${
request.quoteTokenAddress
}`;
it('gets order book', async () => {
@@ -116,7 +125,7 @@ describe('HttpClient', () => {
salt: new BigNumber('256'),
expirationUnixTimestampSec: new BigNumber('42'),
};
- const url = `${relayUrl}/v0/fees`;
+ const url = `${relayUrl}/fees`;
it('gets fees', async () => {
fetchMock.post(url, feesResponseJSON);
const fees = await relayerClient.getFeesAsync(request);
diff --git a/packages/utils/CHANGELOG.md b/packages/utils/CHANGELOG.md
index 899482c4c..e77a7fa03 100644
--- a/packages/utils/CHANGELOG.md
+++ b/packages/utils/CHANGELOG.md
@@ -1,3 +1,6 @@
# CHANGELOG
## vx.x.x
+
+* Add `onError` parameter to `intervalUtils.setAsyncExcludingInterval` (#312)
+* Add `intervalUtils.setInterval` (#312)
diff --git a/packages/utils/src/interval_utils.ts b/packages/utils/src/interval_utils.ts
index 62b79f2f5..ebecc7015 100644
--- a/packages/utils/src/interval_utils.ts
+++ b/packages/utils/src/interval_utils.ts
@@ -1,14 +1,18 @@
import * as _ from 'lodash';
export const intervalUtils = {
- setAsyncExcludingInterval(fn: () => Promise<void>, intervalMs: number) {
+ setAsyncExcludingInterval(fn: () => Promise<void>, intervalMs: number, onError: (err: Error) => void) {
let locked = false;
const intervalId = setInterval(async () => {
if (locked) {
return;
} else {
locked = true;
- await fn();
+ try {
+ await fn();
+ } catch (err) {
+ onError(err);
+ }
locked = false;
}
}, intervalMs);
@@ -17,4 +21,17 @@ export const intervalUtils = {
clearAsyncExcludingInterval(intervalId: NodeJS.Timer): void {
clearInterval(intervalId);
},
+ setInterval(fn: () => void, intervalMs: number, onError: (err: Error) => void) {
+ const intervalId = setInterval(() => {
+ try {
+ fn();
+ } catch (err) {
+ onError(err);
+ }
+ }, intervalMs);
+ return intervalId;
+ },
+ clearInterval(intervalId: NodeJS.Timer): void {
+ clearInterval(intervalId);
+ },
};