diff options
Diffstat (limited to 'packages')
-rw-r--r-- | packages/instant/src/index.umd.ts | 19 | ||||
-rw-r--r-- | packages/instant/src/util/maybe_big_number.ts | 11 | ||||
-rw-r--r-- | packages/instant/src/util/order_coercion.ts | 42 | ||||
-rw-r--r-- | packages/instant/test/util/maybe_big_number.test.ts | 65 | ||||
-rw-r--r-- | packages/instant/test/util/order_coercion.test.ts | 103 |
5 files changed, 235 insertions, 5 deletions
diff --git a/packages/instant/src/index.umd.ts b/packages/instant/src/index.umd.ts index 0acf3f2ad..243bb569b 100644 --- a/packages/instant/src/index.umd.ts +++ b/packages/instant/src/index.umd.ts @@ -17,6 +17,7 @@ import { ZeroExInstantOverlay, ZeroExInstantOverlayProps } from './index'; import { Network, OrderSource } from './types'; import { analytics } from './util/analytics'; import { assert } from './util/assert'; +import { orderCoercionUtil } from './util/order_coercion'; import { providerFactory } from './util/provider_factory'; import { util } from './util/util'; @@ -93,16 +94,24 @@ export interface ZeroExInstantConfig extends ZeroExInstantOverlayProps { } export const render = (config: ZeroExInstantConfig, selector: string = DEFAULT_ZERO_EX_CONTAINER_SELECTOR) => { - validateInstantRenderConfig(config, selector); - if (config.shouldDisablePushToHistory) { + // Coerces BigNumber provided in config to version utilized by 0x packages + const coercedConfig = _.assign({}, config, { + orderSource: _.isArray(config.orderSource) + ? orderCoercionUtil.coerceOrderArrayFieldsToBigNumber(config.orderSource) + : config.orderSource, + }); + + validateInstantRenderConfig(coercedConfig, selector); + + if (coercedConfig.shouldDisablePushToHistory) { if (!isInstantRendered()) { - renderInstant(config, selector); + renderInstant(coercedConfig, selector); } return; } // Before we render, push to history saying that instant is showing for this part of the history. window.history.pushState({ zeroExInstantShowing: true }, '0x Instant'); - let removeInstant = renderInstant(config, selector); + let removeInstant = renderInstant(coercedConfig, selector); // If the integrator defined a popstate handler, save it to __zeroExInstantIntegratorsPopStateHandler // unless we have already done so on a previous render. const anyWindow = window as any; @@ -116,7 +125,7 @@ export const render = (config: ZeroExInstantConfig, selector: string = DEFAULT_Z if (newState && newState.zeroExInstantShowing) { // We have returned to a history state that expects instant to be rendered. if (!isInstantRendered()) { - removeInstant = renderInstant(config, selector); + removeInstant = renderInstant(coercedConfig, selector); } } else { // History has changed to a different state. diff --git a/packages/instant/src/util/maybe_big_number.ts b/packages/instant/src/util/maybe_big_number.ts index f48473389..95fbd8695 100644 --- a/packages/instant/src/util/maybe_big_number.ts +++ b/packages/instant/src/util/maybe_big_number.ts @@ -22,4 +22,15 @@ export const maybeBigNumberUtil = { } return _.isUndefined(val1) && _.isUndefined(val2); }, + // converts a BigNumber or String to the BigNumber used by 0x libraries + toMaybeBigNumber: (value: any): Maybe<BigNumber> => { + if (_.isString(value)) { + return maybeBigNumberUtil.stringToMaybeBigNumber(value); + } + // checks for pre v8 bignumber with member variable + if (BigNumber.isBigNumber(value) || value.isBigNumber) { + return new BigNumber(value.toString()); + } + return undefined; + }, }; diff --git a/packages/instant/src/util/order_coercion.ts b/packages/instant/src/util/order_coercion.ts new file mode 100644 index 000000000..a1b468baf --- /dev/null +++ b/packages/instant/src/util/order_coercion.ts @@ -0,0 +1,42 @@ +import { BigNumber } from '@0x/utils'; +import * as _ from 'lodash'; + +import { maybeBigNumberUtil } from './maybe_big_number'; + +const coerceBigNumberOrString = (value: any): BigNumber => { + const bn = maybeBigNumberUtil.toMaybeBigNumber(value); + return !!bn ? bn : value; +}; + +// function implies that the signed order already has been validated +export const orderCoercionUtil = { + // coerces order big number values to the BigNumber version utilized by 0x + coerceFieldsToBigNumbers(obj: any, fields: string[]): any { + const result = _.assign({}, obj); + _.each(fields, field => { + _.update(result, field, (value: string) => { + if (_.isUndefined(value)) { + throw new Error(`Could not find field '${field}' while converting fields to BigNumber.`); + } + return coerceBigNumberOrString(value); + }); + }); + return result; + }, + + coerceOrderFieldsToBigNumber: (order: any): any => { + return orderCoercionUtil.coerceFieldsToBigNumbers(order, [ + 'makerFee', + 'takerFee', + 'makerAssetAmount', + 'takerAssetAmount', + 'salt', + 'expirationTimeSeconds', + ]); + }, + coerceOrderArrayFieldsToBigNumber: (orders: any[]): any[] => { + return _.map(orders, (value: any) => { + return orderCoercionUtil.coerceOrderFieldsToBigNumber(value); + }); + }, +}; diff --git a/packages/instant/test/util/maybe_big_number.test.ts b/packages/instant/test/util/maybe_big_number.test.ts new file mode 100644 index 000000000..508e8aaf0 --- /dev/null +++ b/packages/instant/test/util/maybe_big_number.test.ts @@ -0,0 +1,65 @@ +import { BigNumber } from '@0x/utils'; + +import { maybeBigNumberUtil } from '../../src/util/maybe_big_number'; + +const BIG_NUMBER_1 = new BigNumber('10.1'); +const BIG_NUMBER_2 = new BigNumber('10.1'); +const BIG_NUMBER_3 = new BigNumber('11.1'); + +describe('maybeBigNumberUtil', () => { + describe('stringToMaybeBigNumber', () => { + it('should return undefined if stringValue is NaN', () => { + expect(maybeBigNumberUtil.stringToMaybeBigNumber('NaN')).toEqual(undefined); + }); + it('should return bignumber constructed with stringValue', () => { + const bn = maybeBigNumberUtil.stringToMaybeBigNumber('10.1'); + if (!!bn) { + expect(bn.toString()).toEqual('10.1'); + } + }); + it('should return undefined if stringValue is not valid (i.e not numeric)', () => { + expect(maybeBigNumberUtil.stringToMaybeBigNumber('test')).toEqual(undefined); + }); + }); + + describe('areMaybeBigNumbersEqual', () => { + it('should return true if val1 and val2 are equivalent BigNumber values', () => { + expect(maybeBigNumberUtil.areMaybeBigNumbersEqual(BIG_NUMBER_1, BIG_NUMBER_2)).toEqual(true); + }); + it('should return true if val1 and val2 are both undefined', () => { + expect(maybeBigNumberUtil.areMaybeBigNumbersEqual(undefined, undefined)).toEqual(true); + }); + it('should return false if either one val1 or val2 is undefined', () => { + expect(maybeBigNumberUtil.areMaybeBigNumbersEqual(BIG_NUMBER_1, undefined)).toEqual(false); + }); + it('should return false if val1 and val2 are equivalent values BigNumber', () => { + expect(maybeBigNumberUtil.areMaybeBigNumbersEqual(BIG_NUMBER_1, BIG_NUMBER_3)).toEqual(false); + }); + }); + + // this doesn't test coercing a pre v8.0.0 version of big number to desired version + describe('toMaybeBigNumber', () => { + it('should return BigNumber (>=v8.0.0) constructed with value if type is string', () => { + const bn = maybeBigNumberUtil.toMaybeBigNumber('10.1'); + if (!!bn) { + expect(bn.toString()).toEqual('10.1'); + } + }); + it('should return undefined if value is NaN', () => { + expect(maybeBigNumberUtil.toMaybeBigNumber('NaN')).toEqual(undefined); + }); + it('should return undefined if value as string is not valid (i.e not numeric)', () => { + expect(maybeBigNumberUtil.toMaybeBigNumber('test')).toEqual(undefined); + }); + it('should return undefined if value as string is not valid (i.e not numeric)', () => { + expect(maybeBigNumberUtil.toMaybeBigNumber('test')).toEqual(undefined); + }); + it('should return BigNumber (>=v8.0.0) when passed a value as BigNumber (>=v8.0.0)', () => { + const bn = maybeBigNumberUtil.toMaybeBigNumber(BIG_NUMBER_1); + expect(BigNumber.isBigNumber(bn)).toEqual(true); + }); + it('should return undefined if value is not BigNumber or string', () => { + expect(maybeBigNumberUtil.toMaybeBigNumber(true)).toEqual(undefined); + }); + }); +}); diff --git a/packages/instant/test/util/order_coercion.test.ts b/packages/instant/test/util/order_coercion.test.ts new file mode 100644 index 000000000..f7a958c9d --- /dev/null +++ b/packages/instant/test/util/order_coercion.test.ts @@ -0,0 +1,103 @@ +import { BigNumber } from '@0x/utils'; + +import { orderCoercionUtil } from '../../src/util/order_coercion'; + +const ORDER = { + senderAddress: '0x0000000000000000000000000000000000000000', + makerAddress: '0x34a745008a643eebc58920eaa29fb1165b4a288e', + takerAddress: '0x0000000000000000000000000000000000000000', + makerFee: new BigNumber('0'), + takerFee: new BigNumber('0'), + makerAssetAmount: new BigNumber('200000000000000000000'), + takerAssetAmount: new BigNumber('10000000000000000000'), + makerAssetData: '0xf47261b00000000000000000000000008cb3971b8eb709c14616bd556ff6683019e90d9c', + takerAssetData: '0xf47261b0000000000000000000000000d0a1e359811322d97991e03f863a0c30c2cf029c', + expirationTimeSeconds: new BigNumber('1601535600'), + feeRecipientAddress: '0x0000000000000000000000000000000000000000', + salt: new BigNumber('3101985707338942582579795423923841749956600670712030922928319824580764688653'), + signature: + '0x1bd4d5686fea801fe33c68c4944356085e7e6cb553eb7073160abd815609f714e85fb47f44b7ffd0a2a1321ac40d72d55163869d0a50fdb5a402132150fe33a08403', + exchangeAddress: '0x35dd2932454449b14cee11a94d3674a936d5d7b2', +}; + +const STRING_ORDER = { + senderAddress: '0x0000000000000000000000000000000000000000', + makerAddress: '0x34a745008a643eebc58920eaa29fb1165b4a288e', + takerAddress: '0x0000000000000000000000000000000000000000', + makerFee: '0', + takerFee: '0', + makerAssetAmount: '300000000000000000000', + takerAssetAmount: '31000000000000000000', + makerAssetData: '0xf47261b00000000000000000000000002002d3812f58e35f0ea1ffbf80a75a38c32175fa', + takerAssetData: '0xf47261b0000000000000000000000000d0a1e359811322d97991e03f863a0c30c2cf029c', + expirationTimeSeconds: '2524636800', + feeRecipientAddress: '0x0000000000000000000000000000000000000000', + salt: '64592004666704945574675477805199411288137454783320798602050822322450089238268', + signature: + '0x1c13cacddca8d7d8248e91f412377e68f8f1f9891a59a6c1b2eea9f7b33558c30c4fb86a448e08ab7def40a28fb3a3062dcb33bb3c45302447fce5c4288b7c7f5b03', + exchangeAddress: '0x35dd2932454449b14cee11a94d3674a936d5d7b2', +}; + +const ORDERS = [ORDER, STRING_ORDER]; + +describe('orderCoercionUtil', () => { + describe('coerceFieldsToBigNumbers', () => { + it('should coerce all fields specified to a big number', () => { + const coercedOrder = orderCoercionUtil.coerceFieldsToBigNumbers(STRING_ORDER, ['makerFee', 'takerFee']); + expect(coercedOrder.makerFee.toString()).toEqual('0'); + expect(coercedOrder.takerFee.toString()).toEqual('0'); + }); + it("should throw if a field can't be found", () => { + expect(() => { + orderCoercionUtil.coerceFieldsToBigNumbers(ORDER, ['salty']); + }).toThrow("Could not find field 'salty' while converting fields to BigNumber."); + }); + it('should not change value if not numeric string or big number', () => { + const obj = { number: 'number' }; + const coercedObj = orderCoercionUtil.coerceFieldsToBigNumbers(obj, ['number']); + expect(coercedObj).toEqual({ + number: 'number', + }); + }); + }); + // Note: this doesn't test coercing pre v8.0.0 BigNumber versions to specified one used by 0x + describe('coerceOrderFieldsToBigNumber', () => { + it('should convert string values in order to big number', () => { + const coercedOrder = orderCoercionUtil.coerceOrderFieldsToBigNumber(STRING_ORDER); + expect(coercedOrder.makerFee.toString()).toEqual(STRING_ORDER.makerFee); + expect(coercedOrder.takerFee.toString()).toEqual(STRING_ORDER.takerFee); + expect(coercedOrder.takerAssetAmount.toString()).toEqual(STRING_ORDER.takerAssetAmount); + expect(coercedOrder.makerAssetAmount.toString()).toEqual(STRING_ORDER.makerAssetAmount); + expect(coercedOrder.salt.toString()).toEqual(STRING_ORDER.salt); + expect(coercedOrder.expirationTimeSeconds.toString()).toEqual(STRING_ORDER.expirationTimeSeconds); + }); + it('should convert big number values in order to big number', () => { + const coercedOrder = orderCoercionUtil.coerceOrderFieldsToBigNumber(ORDER); + expect(coercedOrder.makerFee).toEqual(ORDER.makerFee); + expect(coercedOrder.takerFee).toEqual(ORDER.takerFee); + expect(coercedOrder.takerAssetAmount).toEqual(ORDER.takerAssetAmount); + expect(coercedOrder.makerAssetAmount).toEqual(ORDER.makerAssetAmount); + expect(coercedOrder.salt).toEqual(ORDER.salt); + expect(coercedOrder.expirationTimeSeconds).toEqual(ORDER.expirationTimeSeconds); + }); + }); + // Note: this doesn't test coercing pre v8.0.0 BigNumber versions to specified one used by 0x + describe('coerceOrderArrayFieldsToBigNumber', () => { + it('should convert string values and big numbers in orders to big number', () => { + const coercedOrders = orderCoercionUtil.coerceOrderArrayFieldsToBigNumber(ORDERS); + expect(coercedOrders[0].makerFee).toEqual(ORDER.makerFee); + expect(coercedOrders[0].takerFee).toEqual(ORDER.takerFee); + expect(coercedOrders[0].takerAssetAmount).toEqual(ORDER.takerAssetAmount); + expect(coercedOrders[0].makerAssetAmount).toEqual(ORDER.makerAssetAmount); + expect(coercedOrders[0].salt).toEqual(ORDER.salt); + expect(coercedOrders[0].expirationTimeSeconds).toEqual(ORDER.expirationTimeSeconds); + + expect(coercedOrders[1].makerFee.toString()).toEqual(STRING_ORDER.makerFee); + expect(coercedOrders[1].takerFee.toString()).toEqual(STRING_ORDER.takerFee); + expect(coercedOrders[1].takerAssetAmount.toString()).toEqual(STRING_ORDER.takerAssetAmount); + expect(coercedOrders[1].makerAssetAmount.toString()).toEqual(STRING_ORDER.makerAssetAmount); + expect(coercedOrders[1].salt.toString()).toEqual(STRING_ORDER.salt); + expect(coercedOrders[1].expirationTimeSeconds.toString()).toEqual(STRING_ORDER.expirationTimeSeconds); + }); + }); +}); |