aboutsummaryrefslogtreecommitdiffstats
path: root/packages/order-utils/test
diff options
context:
space:
mode:
Diffstat (limited to 'packages/order-utils/test')
-rw-r--r--packages/order-utils/test/asset_data_utils_test.ts50
-rw-r--r--packages/order-utils/test/eip712_utils_test.ts44
-rw-r--r--packages/order-utils/test/exchange_transfer_simulator_test.ts12
-rw-r--r--packages/order-utils/test/market_utils_test.ts29
-rw-r--r--packages/order-utils/test/order_hash_test.ts22
-rw-r--r--packages/order-utils/test/order_state_utils_test.ts22
-rw-r--r--packages/order-utils/test/order_validation_utils_test.ts14
-rw-r--r--packages/order-utils/test/rate_utils_test.ts2
-rw-r--r--packages/order-utils/test/remaining_fillable_calculator_test.ts6
-rw-r--r--packages/order-utils/test/signature_utils_test.ts241
-rw-r--r--packages/order-utils/test/sorting_utils_test.ts2
-rw-r--r--packages/order-utils/test/utils/simple_erc20_balance_and_proxy_allowance_fetcher.ts5
-rw-r--r--packages/order-utils/test/utils/test_order_factory.ts5
-rw-r--r--packages/order-utils/test/utils/web3_wrapper.ts4
14 files changed, 329 insertions, 129 deletions
diff --git a/packages/order-utils/test/asset_data_utils_test.ts b/packages/order-utils/test/asset_data_utils_test.ts
new file mode 100644
index 000000000..f175b7a38
--- /dev/null
+++ b/packages/order-utils/test/asset_data_utils_test.ts
@@ -0,0 +1,50 @@
+import * as chai from 'chai';
+
+import { ERC20AssetData, ERC721AssetData } from '@0x/types';
+import { BigNumber } from '@0x/utils';
+
+import { assetDataUtils } from '../src/asset_data_utils';
+
+import { chaiSetup } from './utils/chai_setup';
+
+chaiSetup.configure();
+const expect = chai.expect;
+
+const KNOWN_ENCODINGS = [
+ {
+ address: '0x1dc4c1cefef38a777b15aa20260a54e584b16c48',
+ assetData: '0xf47261b00000000000000000000000001dc4c1cefef38a777b15aa20260a54e584b16c48',
+ },
+ {
+ address: '0x1dc4c1cefef38a777b15aa20260a54e584b16c48',
+ tokenId: new BigNumber(1),
+ assetData:
+ '0x025717920000000000000000000000001dc4c1cefef38a777b15aa20260a54e584b16c480000000000000000000000000000000000000000000000000000000000000001',
+ },
+];
+
+const ERC20_ASSET_PROXY_ID = '0xf47261b0';
+const ERC721_ASSET_PROXY_ID = '0x02571792';
+
+describe('assetDataUtils', () => {
+ it('should encode ERC20', () => {
+ const assetData = assetDataUtils.encodeERC20AssetData(KNOWN_ENCODINGS[0].address);
+ expect(assetData).to.equal(KNOWN_ENCODINGS[0].assetData);
+ });
+ it('should decode ERC20', () => {
+ const assetData: ERC20AssetData = assetDataUtils.decodeERC20AssetData(KNOWN_ENCODINGS[0].assetData);
+ expect(assetData.tokenAddress).to.equal(KNOWN_ENCODINGS[0].address);
+ expect(assetData.assetProxyId).to.equal(ERC20_ASSET_PROXY_ID);
+ });
+ it('should encode ERC721', () => {
+ const assetData = assetDataUtils.encodeERC721AssetData(KNOWN_ENCODINGS[1].address, KNOWN_ENCODINGS[1]
+ .tokenId as BigNumber);
+ expect(assetData).to.equal(KNOWN_ENCODINGS[1].assetData);
+ });
+ it('should decode ERC721', () => {
+ const assetData: ERC721AssetData = assetDataUtils.decodeERC721AssetData(KNOWN_ENCODINGS[1].assetData);
+ expect(assetData.tokenAddress).to.equal(KNOWN_ENCODINGS[1].address);
+ expect(assetData.assetProxyId).to.equal(ERC721_ASSET_PROXY_ID);
+ expect(assetData.tokenId).to.be.bignumber.equal(KNOWN_ENCODINGS[1].tokenId);
+ });
+});
diff --git a/packages/order-utils/test/eip712_utils_test.ts b/packages/order-utils/test/eip712_utils_test.ts
new file mode 100644
index 000000000..a54e49958
--- /dev/null
+++ b/packages/order-utils/test/eip712_utils_test.ts
@@ -0,0 +1,44 @@
+import { BigNumber } from '@0x/utils';
+import * as chai from 'chai';
+import 'mocha';
+
+import { constants } from '../src/constants';
+import { eip712Utils } from '../src/eip712_utils';
+
+import { chaiSetup } from './utils/chai_setup';
+
+chaiSetup.configure();
+const expect = chai.expect;
+
+describe('EIP712 Utils', () => {
+ describe('createTypedData', () => {
+ it('adds in the EIP712DomainSeparator', () => {
+ const primaryType = 'Test';
+ const typedData = eip712Utils.createTypedData(
+ primaryType,
+ { Test: [{ name: 'testValue', type: 'uint256' }] },
+ { testValue: '1' },
+ constants.NULL_ADDRESS,
+ );
+ expect(typedData.domain).to.not.be.undefined();
+ expect(typedData.types.EIP712Domain).to.not.be.undefined();
+ const domainObject = typedData.domain;
+ expect(domainObject.name).to.eq(constants.EIP712_DOMAIN_NAME);
+ expect(typedData.primaryType).to.eq(primaryType);
+ });
+ });
+ describe('createTypedData', () => {
+ it('adds in the EIP712DomainSeparator', () => {
+ const typedData = eip712Utils.createZeroExTransactionTypedData(
+ {
+ salt: new BigNumber('0'),
+ data: constants.NULL_BYTES,
+ signerAddress: constants.NULL_ADDRESS,
+ },
+ constants.NULL_ADDRESS,
+ );
+ expect(typedData.primaryType).to.eq(constants.EIP712_ZEROEX_TRANSACTION_SCHEMA.name);
+ expect(typedData.types.EIP712Domain).to.not.be.undefined();
+ });
+ });
+});
diff --git a/packages/order-utils/test/exchange_transfer_simulator_test.ts b/packages/order-utils/test/exchange_transfer_simulator_test.ts
index f5c18cdb9..c26eb1907 100644
--- a/packages/order-utils/test/exchange_transfer_simulator_test.ts
+++ b/packages/order-utils/test/exchange_transfer_simulator_test.ts
@@ -1,15 +1,13 @@
-import { BlockchainLifecycle, devConstants } from '@0xproject/dev-utils';
-import { ExchangeContractErrs } from '@0xproject/types';
-import { BigNumber } from '@0xproject/utils';
+import { DummyERC20TokenContract, ERC20ProxyContract, ERC20TokenContract } from '@0x/abi-gen-wrappers';
+import * as artifacts from '@0x/contract-artifacts';
+import { BlockchainLifecycle, devConstants } from '@0x/dev-utils';
+import { ExchangeContractErrs } from '@0x/types';
+import { BigNumber } from '@0x/utils';
import * as chai from 'chai';
-import { artifacts } from '../src/artifacts';
import { assetDataUtils } from '../src/asset_data_utils';
import { constants } from '../src/constants';
import { ExchangeTransferSimulator } from '../src/exchange_transfer_simulator';
-import { DummyERC20TokenContract } from '../src/generated_contract_wrappers/dummy_erc20_token';
-import { ERC20ProxyContract } from '../src/generated_contract_wrappers/erc20_proxy';
-import { ERC20TokenContract } from '../src/generated_contract_wrappers/erc20_token';
import { BalanceAndProxyAllowanceLazyStore } from '../src/store/balance_and_proxy_allowance_lazy_store';
import { TradeSide, TransferType } from '../src/types';
diff --git a/packages/order-utils/test/market_utils_test.ts b/packages/order-utils/test/market_utils_test.ts
index 109420a02..42ea195bb 100644
--- a/packages/order-utils/test/market_utils_test.ts
+++ b/packages/order-utils/test/market_utils_test.ts
@@ -1,8 +1,9 @@
-import { BigNumber } from '@0xproject/utils';
+import { BigNumber } from '@0x/utils';
import * as chai from 'chai';
import 'mocha';
-import { constants, marketUtils } from '../src';
+import { marketUtils } from '../src';
+import { constants } from '../src/constants';
import { chaiSetup } from './utils/chai_setup';
import { testOrderFactory } from './utils/test_order_factory';
@@ -139,11 +140,11 @@ describe('marketUtils', () => {
);
describe('no target orders', () => {
it('returns empty and zero remainingFeeAmount', async () => {
- const { resultOrders, remainingFeeAmount } = marketUtils.findFeeOrdersThatCoverFeesForTargetOrders(
+ const { resultFeeOrders, remainingFeeAmount } = marketUtils.findFeeOrdersThatCoverFeesForTargetOrders(
[],
inputFeeOrders,
);
- expect(resultOrders).to.be.empty;
+ expect(resultFeeOrders).to.be.empty;
expect(remainingFeeAmount).to.be.bignumber.equal(constants.ZERO_AMOUNT);
});
});
@@ -162,14 +163,14 @@ describe('marketUtils', () => {
// generate remainingFillableMakerAssetAmounts that equal the makerAssetAmount
const remainingFillableMakerAssetAmounts = [makerAssetAmount, makerAssetAmount, makerAssetAmount];
it('returns empty and non-zero remainingFeeAmount', async () => {
- const { resultOrders, remainingFeeAmount } = marketUtils.findFeeOrdersThatCoverFeesForTargetOrders(
+ const { resultFeeOrders, remainingFeeAmount } = marketUtils.findFeeOrdersThatCoverFeesForTargetOrders(
inputOrders,
[],
{
remainingFillableMakerAssetAmounts,
},
);
- expect(resultOrders).to.be.empty;
+ expect(resultFeeOrders).to.be.empty;
expect(remainingFeeAmount).to.be.bignumber.equal(new BigNumber(30));
});
});
@@ -183,11 +184,11 @@ describe('marketUtils', () => {
3,
);
it('returns empty and zero remainingFeeAmount', async () => {
- const { resultOrders, remainingFeeAmount } = marketUtils.findFeeOrdersThatCoverFeesForTargetOrders(
+ const { resultFeeOrders, remainingFeeAmount } = marketUtils.findFeeOrdersThatCoverFeesForTargetOrders(
inputOrders,
inputFeeOrders,
);
- expect(resultOrders).to.be.empty;
+ expect(resultFeeOrders).to.be.empty;
expect(remainingFeeAmount).to.be.bignumber.equal(constants.ZERO_AMOUNT);
});
});
@@ -204,11 +205,11 @@ describe('marketUtils', () => {
3,
);
it('returns input fee orders and zero remainingFeeAmount', async () => {
- const { resultOrders, remainingFeeAmount } = marketUtils.findFeeOrdersThatCoverFeesForTargetOrders(
+ const { resultFeeOrders, remainingFeeAmount } = marketUtils.findFeeOrdersThatCoverFeesForTargetOrders(
inputOrders,
inputFeeOrders,
);
- expect(resultOrders).to.be.deep.equal(inputFeeOrders);
+ expect(resultFeeOrders).to.be.deep.equal(inputFeeOrders);
expect(remainingFeeAmount).to.be.bignumber.equal(constants.ZERO_AMOUNT);
});
});
@@ -230,14 +231,14 @@ describe('marketUtils', () => {
// 3. order is completely fillable
const remainingFillableMakerAssetAmounts = [constants.ZERO_AMOUNT, new BigNumber(5), makerAssetAmount];
it('returns first two input fee orders and zero remainingFeeAmount', async () => {
- const { resultOrders, remainingFeeAmount } = marketUtils.findFeeOrdersThatCoverFeesForTargetOrders(
+ const { resultFeeOrders, remainingFeeAmount } = marketUtils.findFeeOrdersThatCoverFeesForTargetOrders(
inputOrders,
inputFeeOrders,
{
remainingFillableMakerAssetAmounts,
},
);
- expect(resultOrders).to.be.deep.equal([inputFeeOrders[0], inputFeeOrders[1]]);
+ expect(resultFeeOrders).to.be.deep.equal([inputFeeOrders[0], inputFeeOrders[1]]);
expect(remainingFeeAmount).to.be.bignumber.equal(constants.ZERO_AMOUNT);
});
});
@@ -254,11 +255,11 @@ describe('marketUtils', () => {
3,
);
it('returns input fee orders and non-zero remainingFeeAmount', async () => {
- const { resultOrders, remainingFeeAmount } = marketUtils.findFeeOrdersThatCoverFeesForTargetOrders(
+ const { resultFeeOrders, remainingFeeAmount } = marketUtils.findFeeOrdersThatCoverFeesForTargetOrders(
inputOrders,
inputFeeOrders,
);
- expect(resultOrders).to.be.deep.equal(inputFeeOrders);
+ expect(resultFeeOrders).to.be.deep.equal(inputFeeOrders);
expect(remainingFeeAmount).to.be.bignumber.equal(new BigNumber(30));
});
});
diff --git a/packages/order-utils/test/order_hash_test.ts b/packages/order-utils/test/order_hash_test.ts
index 0a6be83d0..a85d4c81a 100644
--- a/packages/order-utils/test/order_hash_test.ts
+++ b/packages/order-utils/test/order_hash_test.ts
@@ -1,9 +1,11 @@
-import { Order } from '@0xproject/types';
-import { BigNumber } from '@0xproject/utils';
+import { Order } from '@0x/types';
+import { BigNumber } from '@0x/utils';
import * as chai from 'chai';
import 'mocha';
-import { constants, orderHashUtils } from '../src';
+import { orderHashUtils } from '../src';
+
+import { constants } from '../src/constants';
import { chaiSetup } from './utils/chai_setup';
@@ -33,6 +35,20 @@ describe('Order hashing', () => {
const orderHash = orderHashUtils.getOrderHashHex(order);
expect(orderHash).to.be.equal(expectedOrderHash);
});
+ it('calculates the order hash if amounts are strings', async () => {
+ // It's common for developers using javascript to provide the amounts
+ // as strings. Since we eventually toString() the BigNumber
+ // before encoding we should result in the same orderHash in this scenario
+ // tslint:disable-next-line:no-unnecessary-type-assertion
+ const orderHash = orderHashUtils.getOrderHashHex({
+ ...order,
+ makerAssetAmount: '0',
+ takerAssetAmount: '0',
+ makerFee: '0',
+ takerFee: '0',
+ } as any);
+ expect(orderHash).to.be.equal(expectedOrderHash);
+ });
it('throws a readable error message if taker format is invalid', async () => {
const orderWithInvalidtakerFormat = {
...order,
diff --git a/packages/order-utils/test/order_state_utils_test.ts b/packages/order-utils/test/order_state_utils_test.ts
index 91ef23b69..39c4c362f 100644
--- a/packages/order-utils/test/order_state_utils_test.ts
+++ b/packages/order-utils/test/order_state_utils_test.ts
@@ -1,4 +1,4 @@
-import { BigNumber } from '@0xproject/utils';
+import { BigNumber } from '@0x/utils';
import * as chai from 'chai';
import 'mocha';
@@ -120,5 +120,25 @@ describe('OrderStateUtils', () => {
const orderState = await orderStateUtils.getOpenOrderStateAsync(signedOrder);
expect(orderState.isValid).to.eq(false);
});
+ it('should include the transactionHash in orderState if supplied in method invocation', async () => {
+ const makerAssetAmount = new BigNumber(10);
+ const takerAssetAmount = new BigNumber(10000000000000000);
+ const takerBalance = takerAssetAmount;
+ const orderFilledAmount = new BigNumber(0);
+ const mockBalanceFetcher = buildMockBalanceFetcher(takerBalance);
+ const mockOrderFilledFetcher = buildMockOrderFilledFetcher(orderFilledAmount);
+ const [signedOrder] = testOrderFactory.generateTestSignedOrders(
+ {
+ makerAssetAmount,
+ takerAssetAmount,
+ },
+ 1,
+ );
+
+ const orderStateUtils = new OrderStateUtils(mockBalanceFetcher, mockOrderFilledFetcher);
+ const transactionHash = '0xdeadbeef';
+ const orderState = await orderStateUtils.getOpenOrderStateAsync(signedOrder, transactionHash);
+ expect(orderState.transactionHash).to.eq(transactionHash);
+ });
});
});
diff --git a/packages/order-utils/test/order_validation_utils_test.ts b/packages/order-utils/test/order_validation_utils_test.ts
index d3ff867d7..d4d12a6a7 100644
--- a/packages/order-utils/test/order_validation_utils_test.ts
+++ b/packages/order-utils/test/order_validation_utils_test.ts
@@ -1,4 +1,4 @@
-import { BigNumber } from '@0xproject/utils';
+import { BigNumber } from '@0x/utils';
import * as chai from 'chai';
import 'mocha';
@@ -16,7 +16,7 @@ describe('OrderValidationUtils', () => {
const denominator = new BigNumber(999);
const target = new BigNumber(50);
// rounding error = ((20*50/999) - floor(20*50/999)) / (20*50/999) = 0.1%
- const isRoundingError = OrderValidationUtils.isRoundingError(numerator, denominator, target);
+ const isRoundingError = OrderValidationUtils.isRoundingErrorFloor(numerator, denominator, target);
expect(isRoundingError).to.be.false();
});
@@ -25,7 +25,7 @@ describe('OrderValidationUtils', () => {
const denominator = new BigNumber(9991);
const target = new BigNumber(500);
// rounding error = ((20*500/9991) - floor(20*500/9991)) / (20*500/9991) = 0.09%
- const isRoundingError = OrderValidationUtils.isRoundingError(numerator, denominator, target);
+ const isRoundingError = OrderValidationUtils.isRoundingErrorFloor(numerator, denominator, target);
expect(isRoundingError).to.be.false();
});
@@ -34,7 +34,7 @@ describe('OrderValidationUtils', () => {
const denominator = new BigNumber(9989);
const target = new BigNumber(500);
// rounding error = ((20*500/9989) - floor(20*500/9989)) / (20*500/9989) = 0.011%
- const isRoundingError = OrderValidationUtils.isRoundingError(numerator, denominator, target);
+ const isRoundingError = OrderValidationUtils.isRoundingErrorFloor(numerator, denominator, target);
expect(isRoundingError).to.be.true();
});
@@ -43,7 +43,7 @@ describe('OrderValidationUtils', () => {
const denominator = new BigNumber(7);
const target = new BigNumber(10);
// rounding error = ((3*10/7) - floor(3*10/7)) / (3*10/7) = 6.67%
- const isRoundingError = OrderValidationUtils.isRoundingError(numerator, denominator, target);
+ const isRoundingError = OrderValidationUtils.isRoundingErrorFloor(numerator, denominator, target);
expect(isRoundingError).to.be.true();
});
@@ -52,7 +52,7 @@ describe('OrderValidationUtils', () => {
const denominator = new BigNumber(2);
const target = new BigNumber(10);
- const isRoundingError = OrderValidationUtils.isRoundingError(numerator, denominator, target);
+ const isRoundingError = OrderValidationUtils.isRoundingErrorFloor(numerator, denominator, target);
expect(isRoundingError).to.be.false();
});
@@ -63,7 +63,7 @@ describe('OrderValidationUtils', () => {
const target = new BigNumber(105762562);
// rounding error = ((76564*105762562/676373677) - floor(76564*105762562/676373677)) /
// (76564*105762562/676373677) = 0.0007%
- const isRoundingError = OrderValidationUtils.isRoundingError(numerator, denominator, target);
+ const isRoundingError = OrderValidationUtils.isRoundingErrorFloor(numerator, denominator, target);
expect(isRoundingError).to.be.false();
});
});
diff --git a/packages/order-utils/test/rate_utils_test.ts b/packages/order-utils/test/rate_utils_test.ts
index 2e299c209..b13878bb5 100644
--- a/packages/order-utils/test/rate_utils_test.ts
+++ b/packages/order-utils/test/rate_utils_test.ts
@@ -1,4 +1,4 @@
-import { BigNumber } from '@0xproject/utils';
+import { BigNumber } from '@0x/utils';
import * as chai from 'chai';
import 'mocha';
diff --git a/packages/order-utils/test/remaining_fillable_calculator_test.ts b/packages/order-utils/test/remaining_fillable_calculator_test.ts
index a5a3b7fc6..c55a76def 100644
--- a/packages/order-utils/test/remaining_fillable_calculator_test.ts
+++ b/packages/order-utils/test/remaining_fillable_calculator_test.ts
@@ -1,6 +1,6 @@
-import { SignedOrder } from '@0xproject/types';
-import { BigNumber } from '@0xproject/utils';
-import { Web3Wrapper } from '@0xproject/web3-wrapper';
+import { SignedOrder } from '@0x/types';
+import { BigNumber } from '@0x/utils';
+import { Web3Wrapper } from '@0x/web3-wrapper';
import * as chai from 'chai';
import 'mocha';
diff --git a/packages/order-utils/test/signature_utils_test.ts b/packages/order-utils/test/signature_utils_test.ts
index a25d2afd6..84e5559a9 100644
--- a/packages/order-utils/test/signature_utils_test.ts
+++ b/packages/order-utils/test/signature_utils_test.ts
@@ -1,13 +1,14 @@
-import { SignerType } from '@0xproject/types';
-import { BigNumber } from '@0xproject/utils';
+import { Order, SignatureType } from '@0x/types';
+import { BigNumber } from '@0x/utils';
import * as chai from 'chai';
import { JSONRPCErrorCallback, JSONRPCRequestPayload } from 'ethereum-types';
+import * as ethUtil from 'ethereumjs-util';
import * as _ from 'lodash';
import 'mocha';
-import * as Sinon from 'sinon';
-import { ecSignOrderHashAsync, generatePseudoRandomSalt } from '../src';
-import { convertECSignatureToSignatureHex, isValidECSignature, isValidSignatureAsync } from '../src/signature_utils';
+import { generatePseudoRandomSalt, orderHashUtils } from '../src';
+import { constants } from '../src/constants';
+import { signatureUtils } from '../src/signature_utils';
import { chaiSetup } from './utils/chai_setup';
import { provider, web3Wrapper } from './utils/web3_wrapper';
@@ -16,7 +17,29 @@ chaiSetup.configure();
const expect = chai.expect;
describe('Signature utils', () => {
- describe('#isValidSignature', () => {
+ let makerAddress: string;
+ const fakeExchangeContractAddress = '0x1dc4c1cefef38a777b15aa20260a54e584b16c48';
+ let order: Order;
+ before(async () => {
+ const availableAddreses = await web3Wrapper.getAvailableAddressesAsync();
+ makerAddress = availableAddreses[0];
+ order = {
+ makerAddress,
+ takerAddress: constants.NULL_ADDRESS,
+ senderAddress: constants.NULL_ADDRESS,
+ feeRecipientAddress: constants.NULL_ADDRESS,
+ makerAssetData: constants.NULL_ADDRESS,
+ takerAssetData: constants.NULL_ADDRESS,
+ exchangeAddress: fakeExchangeContractAddress,
+ salt: new BigNumber(0),
+ makerFee: new BigNumber(0),
+ takerFee: new BigNumber(0),
+ makerAssetAmount: new BigNumber(0),
+ takerAssetAmount: new BigNumber(0),
+ expirationTimeSeconds: new BigNumber(0),
+ };
+ });
+ describe('#isValidSignatureAsync', () => {
let dataHex = '0x6927e990021d23b1eb7b8789f6a6feaf98fe104bb0cf8259421b79f9a34222b0';
const ethSignSignature =
'0x1B61a3ed31b43c8780e905a260a35faefcc527be7516aa11c0256729b5b351bc3340349190569279751135161d22529dc25add4f6069af05be04cacbda2ace225403';
@@ -24,12 +47,14 @@ describe('Signature utils', () => {
it("should return false if the data doesn't pertain to the signature & address", async () => {
const bytes32Zeros = '0x0000000000000000000000000000000000000000000000000000000000000000';
- expect(await isValidSignatureAsync(provider, bytes32Zeros, ethSignSignature, address)).to.be.false();
+ expect(
+ await signatureUtils.isValidSignatureAsync(provider, bytes32Zeros, ethSignSignature, address),
+ ).to.be.false();
});
it("should return false if the address doesn't pertain to the signature & data", async () => {
const validUnrelatedAddress = '0x8b0292b11a196601ed2ce54b665cafeca0347d42';
expect(
- await isValidSignatureAsync(provider, dataHex, ethSignSignature, validUnrelatedAddress),
+ await signatureUtils.isValidSignatureAsync(provider, dataHex, ethSignSignature, validUnrelatedAddress),
).to.be.false();
});
it("should return false if the signature doesn't pertain to the dataHex & address", async () => {
@@ -37,18 +62,27 @@ describe('Signature utils', () => {
// tslint:disable-next-line:custom-no-magic-numbers
signatureArray[5] = 'C'; // V = 28, instead of 27
const wrongSignature = signatureArray.join('');
- expect(await isValidSignatureAsync(provider, dataHex, wrongSignature, address)).to.be.false();
+ expect(
+ await signatureUtils.isValidSignatureAsync(provider, dataHex, wrongSignature, address),
+ ).to.be.false();
});
it('should throw if signatureType is invalid', () => {
const signatureArray = ethSignSignature.split('');
signatureArray[3] = '9'; // SignatureType w/ index 9 doesn't exist
const signatureWithInvalidType = signatureArray.join('');
- expect(isValidSignatureAsync(provider, dataHex, signatureWithInvalidType, address)).to.be.rejected();
+ expect(
+ signatureUtils.isValidSignatureAsync(provider, dataHex, signatureWithInvalidType, address),
+ ).to.be.rejected();
});
it('should return true for a valid Ecrecover (EthSign) signature', async () => {
- const isValidSignatureLocal = await isValidSignatureAsync(provider, dataHex, ethSignSignature, address);
+ const isValidSignatureLocal = await signatureUtils.isValidSignatureAsync(
+ provider,
+ dataHex,
+ ethSignSignature,
+ address,
+ );
expect(isValidSignatureLocal).to.be.true();
});
@@ -57,16 +91,12 @@ describe('Signature utils', () => {
address = '0x6ecbe1db9ef729cbe972c83fb886247691fb6beb';
const eip712Signature =
'0x1bdde07aac4bf12c12ddbb155919c43eba4146a2cfcf904a862950dbebe332554c6674975603eb5a4eaf8fd7f2e06350267e5b36cda9851a89f8bb49fe2fc9afe202';
- const isValidSignatureLocal = await isValidSignatureAsync(provider, dataHex, eip712Signature, address);
- expect(isValidSignatureLocal).to.be.true();
- });
-
- it('should return true for a valid Trezor signature', async () => {
- dataHex = '0xd0d994e31c88f33fd8a572552a70ed339de579e5ba49ee1d17cc978bbe1cdd21';
- address = '0x6ecbe1db9ef729cbe972c83fb886247691fb6beb';
- const trezorSignature =
- '0x1ce4760660e6495b5ae6723087bea073b3a99ce98ea81fdf00c240279c010e63d05b87bc34c4d67d4776e8d5aeb023a67484f4eaf0fd353b40893e5101e845cd9908';
- const isValidSignatureLocal = await isValidSignatureAsync(provider, dataHex, trezorSignature, address);
+ const isValidSignatureLocal = await signatureUtils.isValidSignatureAsync(
+ provider,
+ dataHex,
+ eip712Signature,
+ address,
+ );
expect(isValidSignatureLocal).to.be.true();
});
});
@@ -80,18 +110,18 @@ describe('Signature utils', () => {
const address = '0x0e5cb767cce09a7f3ca594df118aa519be5e2b5a';
it("should return false if the data doesn't pertain to the signature & address", async () => {
- expect(isValidECSignature('0x0', signature, address)).to.be.false();
+ expect(signatureUtils.isValidECSignature('0x0', signature, address)).to.be.false();
});
it("should return false if the address doesn't pertain to the signature & data", async () => {
const validUnrelatedAddress = '0x8b0292b11a196601ed2ce54b665cafeca0347d42';
- expect(isValidECSignature(data, signature, validUnrelatedAddress)).to.be.false();
+ expect(signatureUtils.isValidECSignature(data, signature, validUnrelatedAddress)).to.be.false();
});
it("should return false if the signature doesn't pertain to the data & address", async () => {
const wrongSignature = _.assign({}, signature, { v: 28 });
- expect(isValidECSignature(data, wrongSignature, address)).to.be.false();
+ expect(signatureUtils.isValidECSignature(data, wrongSignature, address)).to.be.false();
});
it('should return true if the signature does pertain to the data & address', async () => {
- const isValidSignatureLocal = isValidECSignature(data, signature, address);
+ const isValidSignatureLocal = signatureUtils.isValidECSignature(data, signature, address);
expect(isValidSignatureLocal).to.be.true();
});
});
@@ -108,23 +138,64 @@ describe('Signature utils', () => {
expect(salt.lessThan(twoPow256)).to.be.true();
});
});
- describe('#ecSignOrderHashAsync', () => {
- let stubs: Sinon.SinonStub[] = [];
- let makerAddress: string;
+ describe('#ecSignOrderAsync', () => {
+ it('should default to eth_sign if eth_signTypedData is unavailable', async () => {
+ const expectedSignature =
+ '0x1c3582f06356a1314dbf1c0e534c4d8e92e59b056ee607a7ff5a825f5f2cc5e6151c5cc7fdd420f5608e4d5bef108e42ad90c7a4b408caef32e24374cf387b0d7603';
+
+ const fakeProvider = {
+ async sendAsync(payload: JSONRPCRequestPayload, callback: JSONRPCErrorCallback): Promise<void> {
+ if (payload.method === 'eth_signTypedData') {
+ callback(new Error('Internal RPC Error'));
+ } else if (payload.method === 'eth_sign') {
+ const [address, message] = payload.params;
+ const signature = await web3Wrapper.signMessageAsync(address, message);
+ callback(null, {
+ id: 42,
+ jsonrpc: '2.0',
+ result: signature,
+ });
+ } else {
+ callback(null, { id: 42, jsonrpc: '2.0', result: [makerAddress] });
+ }
+ },
+ };
+ const signedOrder = await signatureUtils.ecSignOrderAsync(fakeProvider, order, makerAddress);
+ expect(signedOrder.signature).to.equal(expectedSignature);
+ });
+ it('should throw if the user denies the signing request', async () => {
+ const fakeProvider = {
+ async sendAsync(payload: JSONRPCRequestPayload, callback: JSONRPCErrorCallback): Promise<void> {
+ if (payload.method === 'eth_signTypedData') {
+ callback(new Error('User denied message signature'));
+ } else if (payload.method === 'eth_sign') {
+ const [address, message] = payload.params;
+ const signature = await web3Wrapper.signMessageAsync(address, message);
+ callback(null, {
+ id: 42,
+ jsonrpc: '2.0',
+ result: signature,
+ });
+ } else {
+ callback(null, { id: 42, jsonrpc: '2.0', result: [makerAddress] });
+ }
+ },
+ };
+ expect(signatureUtils.ecSignOrderAsync(fakeProvider, order, makerAddress)).to.to.be.rejectedWith(
+ 'User denied message signature',
+ );
+ });
+ });
+ describe('#ecSignHashAsync', () => {
before(async () => {
const availableAddreses = await web3Wrapper.getAvailableAddressesAsync();
makerAddress = availableAddreses[0];
});
- afterEach(() => {
- // clean up any stubs after the test has completed
- _.each(stubs, s => s.restore());
- stubs = [];
- });
- it('Should return the correct Signature', async () => {
+ it('should return the correct Signature', async () => {
const orderHash = '0x6927e990021d23b1eb7b8789f6a6feaf98fe104bb0cf8259421b79f9a34222b0';
const expectedSignature =
'0x1b61a3ed31b43c8780e905a260a35faefcc527be7516aa11c0256729b5b351bc3340349190569279751135161d22529dc25add4f6069af05be04cacbda2ace225403';
- const ecSignature = await ecSignOrderHashAsync(provider, orderHash, makerAddress, SignerType.Default);
+ const ecSignature = await signatureUtils.ecSignHashAsync(provider, orderHash, makerAddress);
expect(ecSignature).to.equal(expectedSignature);
});
it('should return the correct Signature for signatureHex concatenated as R + S + V', async () => {
@@ -150,7 +221,7 @@ describe('Signature utils', () => {
}
},
};
- const ecSignature = await ecSignOrderHashAsync(fakeProvider, orderHash, makerAddress, SignerType.Default);
+ const ecSignature = await signatureUtils.ecSignHashAsync(fakeProvider, orderHash, makerAddress);
expect(ecSignature).to.equal(expectedSignature);
});
it('should return the correct Signature for signatureHex concatenated as V + R + S', async () => {
@@ -173,44 +244,68 @@ describe('Signature utils', () => {
},
};
- const ecSignature = await ecSignOrderHashAsync(fakeProvider, orderHash, makerAddress, SignerType.Default);
+ const ecSignature = await signatureUtils.ecSignHashAsync(fakeProvider, orderHash, makerAddress);
expect(ecSignature).to.equal(expectedSignature);
});
- // Note this is due to a bug in Metamask where it does not prefix before signing, this is a known issue and is to be fixed in the future
- // Source: https://github.com/MetaMask/metamask-extension/commit/a9d36860bec424dcee8db043d3e7da6a5ff5672e
- it('should receive a payload modified with a prefix when Metamask is SignerType', async () => {
+ it('should return a valid signature', async () => {
const orderHash = '0x34decbedc118904df65f379a175bb39ca18209d6ce41d5ed549d54e6e0a95004';
- const orderHashPrefixed = '0xae70f31d26096291aa681b26cb7574563956221d0b4213631e1ef9df675d4cba';
+ const ecSignature = await signatureUtils.ecSignHashAsync(provider, orderHash, makerAddress);
+
+ const isValidSignature = await signatureUtils.isValidSignatureAsync(
+ provider,
+ orderHash,
+ ecSignature,
+ makerAddress,
+ );
+ expect(isValidSignature).to.be.true();
+ });
+ });
+ describe('#ecSignTypedDataOrderAsync', () => {
+ it('should result in the same signature as signing the order hash without an ethereum message prefix', async () => {
+ // Note: Since order hash is an EIP712 hash the result of a valid EIP712 signature
+ // of order hash is the same as signing the order without the Ethereum Message prefix.
+ const orderHashHex = orderHashUtils.getOrderHashHex(order);
+ const sig = ethUtil.ecsign(
+ ethUtil.toBuffer(orderHashHex),
+ Buffer.from('F2F48EE19680706196E2E339E5DA3491186E0C4C5030670656B0E0164837257D', 'hex'),
+ );
+ const signatureBuffer = Buffer.concat([
+ ethUtil.toBuffer(sig.v),
+ ethUtil.toBuffer(sig.r),
+ ethUtil.toBuffer(sig.s),
+ ethUtil.toBuffer(SignatureType.EIP712),
+ ]);
+ const signatureHex = `0x${signatureBuffer.toString('hex')}`;
+ const signedOrder = await signatureUtils.ecSignTypedDataOrderAsync(provider, order, makerAddress);
+ const isValidSignature = await signatureUtils.isValidSignatureAsync(
+ provider,
+ orderHashHex,
+ signedOrder.signature,
+ makerAddress,
+ );
+ expect(signatureHex).to.eq(signedOrder.signature);
+ expect(isValidSignature).to.eq(true);
+ });
+ it('should return the correct Signature for signatureHex concatenated as R + S + V', async () => {
const expectedSignature =
- '0x1b117902c86dfb95fe0d1badd983ee166ad259b27acb220174cbb4460d872871137feabdfe76e05924b484789f79af4ee7fa29ec006cedce1bbf369320d034e10b03';
- // Generated from a MM eth_sign request from 0x5409ed021d9299bf6814279a6a1411a7e866a631 signing 0xae70f31d26096291aa681b26cb7574563956221d0b4213631e1ef9df675d4cba
- const metamaskSignature =
- '0x117902c86dfb95fe0d1badd983ee166ad259b27acb220174cbb4460d872871137feabdfe76e05924b484789f79af4ee7fa29ec006cedce1bbf369320d034e10b1b';
+ '0x1cd472c439833774b55d248c31b6585f21aea1b9363ebb4ec58549e46b62eb5a6f696f5781f62de008ee7f77650ef940d99c97ec1dee67b3f5cea1bbfdfeb2eba602';
const fakeProvider = {
async sendAsync(payload: JSONRPCRequestPayload, callback: JSONRPCErrorCallback): Promise<void> {
- if (payload.method === 'eth_sign') {
- const [, message] = payload.params;
- expect(message).to.equal(orderHashPrefixed);
+ if (payload.method === 'eth_signTypedData') {
+ const [address, typedData] = payload.params;
+ const signature = await web3Wrapper.signTypedDataAsync(address, typedData);
callback(null, {
id: 42,
jsonrpc: '2.0',
- result: metamaskSignature,
+ result: signature,
});
} else {
callback(null, { id: 42, jsonrpc: '2.0', result: [makerAddress] });
}
},
};
-
- const ecSignature = await ecSignOrderHashAsync(fakeProvider, orderHash, makerAddress, SignerType.Metamask);
- expect(ecSignature).to.equal(expectedSignature);
- });
- it('should return a valid signature', async () => {
- const orderHash = '0x34decbedc118904df65f379a175bb39ca18209d6ce41d5ed549d54e6e0a95004';
- const ecSignature = await ecSignOrderHashAsync(provider, orderHash, makerAddress, SignerType.Default);
-
- const isValidSignature = await isValidSignatureAsync(provider, orderHash, ecSignature, makerAddress);
- expect(isValidSignature).to.be.true();
+ const signedOrder = await signatureUtils.ecSignTypedDataOrderAsync(fakeProvider, order, makerAddress);
+ expect(signedOrder.signature).to.equal(expectedSignature);
});
});
describe('#convertECSignatureToSignatureHex', () => {
@@ -219,35 +314,11 @@ describe('Signature utils', () => {
r: '0xaca7da997ad177f040240cdccf6905b71ab16b74434388c3a72f34fd25d64393',
s: '0x46b2bac274ff29b48b3ea6e2d04c1336eaceafda3c53ab483fc3ff12fac3ebf2',
};
- it('should concatenate v,r,s and append the Trezor signature type', async () => {
- const expectedSignatureWithSignatureType =
- '0x1baca7da997ad177f040240cdccf6905b71ab16b74434388c3a72f34fd25d6439346b2bac274ff29b48b3ea6e2d04c1336eaceafda3c53ab483fc3ff12fac3ebf208';
- const signatureWithSignatureType = convertECSignatureToSignatureHex(ecSignature, SignerType.Trezor);
- expect(signatureWithSignatureType).to.equal(expectedSignatureWithSignatureType);
- });
- it('should concatenate v,r,s and append the EthSign signature type when SignerType is Default', async () => {
+ it('should concatenate v,r,s and append the EthSign signature type', async () => {
const expectedSignatureWithSignatureType =
'0x1baca7da997ad177f040240cdccf6905b71ab16b74434388c3a72f34fd25d6439346b2bac274ff29b48b3ea6e2d04c1336eaceafda3c53ab483fc3ff12fac3ebf203';
- const signatureWithSignatureType = convertECSignatureToSignatureHex(ecSignature, SignerType.Default);
+ const signatureWithSignatureType = signatureUtils.convertECSignatureToSignatureHex(ecSignature);
expect(signatureWithSignatureType).to.equal(expectedSignatureWithSignatureType);
});
- it('should concatenate v,r,s and append the EthSign signature type when SignerType is Ledger', async () => {
- const expectedSignatureWithSignatureType =
- '0x1baca7da997ad177f040240cdccf6905b71ab16b74434388c3a72f34fd25d6439346b2bac274ff29b48b3ea6e2d04c1336eaceafda3c53ab483fc3ff12fac3ebf203';
- const signatureWithSignatureType = convertECSignatureToSignatureHex(ecSignature, SignerType.Ledger);
- expect(signatureWithSignatureType).to.equal(expectedSignatureWithSignatureType);
- });
- it('should concatenate v,r,s and append the EthSign signature type when SignerType is Metamask', async () => {
- const expectedSignatureWithSignatureType =
- '0x1baca7da997ad177f040240cdccf6905b71ab16b74434388c3a72f34fd25d6439346b2bac274ff29b48b3ea6e2d04c1336eaceafda3c53ab483fc3ff12fac3ebf203';
- const signatureWithSignatureType = convertECSignatureToSignatureHex(ecSignature, SignerType.Metamask);
- expect(signatureWithSignatureType).to.equal(expectedSignatureWithSignatureType);
- });
- it('should throw if the SignerType is invalid', async () => {
- const expectedMessage = 'Unrecognized SignerType: INVALID_SIGNER';
- expect(() => convertECSignatureToSignatureHex(ecSignature, 'INVALID_SIGNER' as SignerType)).to.throw(
- expectedMessage,
- );
- });
});
});
diff --git a/packages/order-utils/test/sorting_utils_test.ts b/packages/order-utils/test/sorting_utils_test.ts
index 016432505..0b8757496 100644
--- a/packages/order-utils/test/sorting_utils_test.ts
+++ b/packages/order-utils/test/sorting_utils_test.ts
@@ -1,4 +1,4 @@
-import { BigNumber } from '@0xproject/utils';
+import { BigNumber } from '@0x/utils';
import * as chai from 'chai';
import 'mocha';
diff --git a/packages/order-utils/test/utils/simple_erc20_balance_and_proxy_allowance_fetcher.ts b/packages/order-utils/test/utils/simple_erc20_balance_and_proxy_allowance_fetcher.ts
index 279a5c0db..d3ea8b456 100644
--- a/packages/order-utils/test/utils/simple_erc20_balance_and_proxy_allowance_fetcher.ts
+++ b/packages/order-utils/test/utils/simple_erc20_balance_and_proxy_allowance_fetcher.ts
@@ -1,9 +1,8 @@
-import { BigNumber } from '@0xproject/utils';
+import { ERC20TokenContract } from '@0x/abi-gen-wrappers';
+import { BigNumber } from '@0x/utils';
import { AbstractBalanceAndProxyAllowanceFetcher } from '../../src/abstract/abstract_balance_and_proxy_allowance_fetcher';
-import { ERC20TokenContract } from '../../src/generated_contract_wrappers/erc20_token';
-
export class SimpleERC20BalanceAndProxyAllowanceFetcher implements AbstractBalanceAndProxyAllowanceFetcher {
private readonly _erc20TokenContract: ERC20TokenContract;
private readonly _erc20ProxyAddress: string;
diff --git a/packages/order-utils/test/utils/test_order_factory.ts b/packages/order-utils/test/utils/test_order_factory.ts
index 75dc6f1f2..145332674 100644
--- a/packages/order-utils/test/utils/test_order_factory.ts
+++ b/packages/order-utils/test/utils/test_order_factory.ts
@@ -1,7 +1,8 @@
-import { Order, SignedOrder } from '@0xproject/types';
+import { Order, SignedOrder } from '@0x/types';
import * as _ from 'lodash';
-import { constants, orderFactory } from '../../src';
+import { constants } from '../../src/constants';
+import { orderFactory } from '../../src/order_factory';
const BASE_TEST_ORDER: Order = orderFactory.createOrder(
constants.NULL_ADDRESS,
diff --git a/packages/order-utils/test/utils/web3_wrapper.ts b/packages/order-utils/test/utils/web3_wrapper.ts
index ab801fa7f..accfcb7fe 100644
--- a/packages/order-utils/test/utils/web3_wrapper.ts
+++ b/packages/order-utils/test/utils/web3_wrapper.ts
@@ -1,5 +1,5 @@
-import { web3Factory } from '@0xproject/dev-utils';
-import { Web3Wrapper } from '@0xproject/web3-wrapper';
+import { web3Factory } from '@0x/dev-utils';
+import { Web3Wrapper } from '@0x/web3-wrapper';
import { Provider } from 'ethereum-types';
const provider: Provider = web3Factory.getRpcProvider({ shouldUseInProcessGanache: true });