aboutsummaryrefslogtreecommitdiffstats
path: root/test
diff options
context:
space:
mode:
Diffstat (limited to 'test')
-rw-r--r--test/0x.js_test.ts (renamed from test/0x.js.ts)5
-rw-r--r--test/contract_wrapper_test.ts98
-rw-r--r--test/utils/blockchain_lifecycle.ts20
-rw-r--r--test/utils/constants.ts5
-rw-r--r--test/utils/rpc.ts48
-rw-r--r--test/utils/web3_factory.ts23
6 files changed, 197 insertions, 2 deletions
diff --git a/test/0x.js.ts b/test/0x.js_test.ts
index d5b2015fb..9c61c3e10 100644
--- a/test/0x.js.ts
+++ b/test/0x.js_test.ts
@@ -1,8 +1,9 @@
-import {ZeroEx} from '../src/ts/0x.js';
+import * as _ from 'lodash';
import * as chai from 'chai';
import 'mocha';
import * as BigNumber from 'bignumber.js';
import ChaiBigNumber = require('chai-bignumber');
+import {ZeroEx} from '../src/ts/0x.js';
import {constants} from '../src/ts/utils/constants';
// Use BigNumber chai add-on
@@ -104,7 +105,7 @@ describe('ZeroEx library', () => {
expect(isValid).to.be.false;
});
it('should return false if the signature doesn\'t pertain to the data & address', () => {
- const wrongSignature = Object.assign({}, signature, {v: 28});
+ const wrongSignature = _.assign({}, signature, {v: 28});
const isValid = ZeroEx.isValidSignature(data, wrongSignature, address);
expect(isValid).to.be.false;
});
diff --git a/test/contract_wrapper_test.ts b/test/contract_wrapper_test.ts
new file mode 100644
index 000000000..67dae3a4e
--- /dev/null
+++ b/test/contract_wrapper_test.ts
@@ -0,0 +1,98 @@
+import 'mocha';
+import * as chai from 'chai';
+import chaiAsPromised = require('chai-as-promised');
+import * as Web3 from 'web3';
+import {web3Factory} from './utils/web3_factory';
+import {ExchangeWrapper} from '../src/ts/contract_wrappers/exchange_wrapper';
+import {BlockchainLifecycle} from './utils/blockchain_lifecycle';
+import {Web3Wrapper} from './../src/ts/web3_wrapper';
+
+const expect = chai.expect;
+chai.use(chaiAsPromised);
+const blockchainLifecycle = new BlockchainLifecycle();
+
+describe('ExchangeWrapper', () => {
+ let web3Wrapper: Web3Wrapper;
+ let exchangeWrapper: ExchangeWrapper;
+ before(async () => {
+ const web3 = web3Factory.create();
+ web3Wrapper = new Web3Wrapper(web3);
+ exchangeWrapper = new ExchangeWrapper(web3Wrapper);
+ });
+ beforeEach(async () => {
+ await blockchainLifecycle.startAsync();
+ });
+ afterEach(async () => {
+ await blockchainLifecycle.revertAsync();
+ });
+ describe('#isValidSignatureAsync', () => {
+ // The Exchange smart contract `isValidSignature` method only validates orderHashes and assumes
+ // the length of the data is exactly 32 bytes. Thus for these tests, we use data of this size.
+ const dataHex = '0x6927e990021d23b1eb7b8789f6a6feaf98fe104bb0cf8259421b79f9a34222b0';
+ const signature = {
+ v: 27,
+ r: '0x61a3ed31b43c8780e905a260a35faefcc527be7516aa11c0256729b5b351bc33',
+ s: '0x40349190569279751135161d22529dc25add4f6069af05be04cacbda2ace2254',
+ };
+ const address = '0x5409ed021d9299bf6814279a6a1411a7e866a631';
+ describe('should throw if passed a malformed signature', () => {
+ it('malformed v', async () => {
+ const malformedSignature = {
+ v: 34,
+ r: signature.r,
+ s: signature.s,
+ };
+ expect(exchangeWrapper.isValidSignatureAsync(dataHex, malformedSignature, address))
+ .to.be.rejected;
+ });
+ it('r lacks 0x prefix', () => {
+ const malformedR = signature.r.replace('0x', '');
+ const malformedSignature = {
+ v: signature.v,
+ r: malformedR,
+ s: signature.s,
+ };
+ expect(exchangeWrapper.isValidSignatureAsync(dataHex, malformedSignature, address))
+ .to.be.rejected;
+ });
+ it('r is too short', () => {
+ const malformedR = signature.r.substr(10);
+ const malformedSignature = {
+ v: signature.v,
+ r: malformedR,
+ s: signature.s.replace('0', 'z'),
+ };
+ expect(exchangeWrapper.isValidSignatureAsync(dataHex, malformedSignature, address))
+ .to.be.rejected;
+ });
+ it('s is not hex', () => {
+ const malformedS = signature.s.replace('0', 'z');
+ const malformedSignature = {
+ v: signature.v,
+ r: signature.r,
+ s: malformedS,
+ };
+ expect(exchangeWrapper.isValidSignatureAsync(dataHex, malformedSignature, address))
+ .to.be.rejected;
+ });
+ });
+ it('should return false if the data doesn\'t pertain to the signature & address', async () => {
+ const isValid = await exchangeWrapper.isValidSignatureAsync('0x0', signature, address);
+ expect(isValid).to.be.false;
+ });
+ it('should return false if the address doesn\'t pertain to the signature & dataHex', async () => {
+ const validUnrelatedAddress = '0x8b0292B11a196601eD2ce54B665CaFEca0347D42';
+ const isValid = await exchangeWrapper.isValidSignatureAsync(dataHex, signature, validUnrelatedAddress);
+ expect(isValid).to.be.false;
+ });
+ it('should return false if the signature doesn\'t pertain to the dataHex & address', async () => {
+ const wrongSignature = Object.assign({}, signature, {v: 28});
+ const isValid = await exchangeWrapper.isValidSignatureAsync(dataHex, wrongSignature, address);
+ expect(isValid).to.be.false;
+ });
+ it('should return true if the signature does pertain to the dataHex & address', async () => {
+ const isValid = await exchangeWrapper.isValidSignatureAsync(dataHex, signature, address);
+ expect(isValid).to.be.true;
+ });
+ });
+});
diff --git a/test/utils/blockchain_lifecycle.ts b/test/utils/blockchain_lifecycle.ts
new file mode 100644
index 000000000..68e169ac0
--- /dev/null
+++ b/test/utils/blockchain_lifecycle.ts
@@ -0,0 +1,20 @@
+import {RPC} from './rpc';
+
+export class BlockchainLifecycle {
+ private rpc: RPC;
+ private snapshotId: number;
+ constructor() {
+ this.rpc = new RPC();
+ }
+ // TODO: In order to run these tests on an actual node, we should check if we are running against
+ // TestRPC, if so, use snapshots, otherwise re-deploy contracts before every test
+ public async startAsync(): Promise<void> {
+ this.snapshotId = await this.rpc.takeSnapshotAsync();
+ }
+ public async revertAsync(): Promise<void> {
+ const didRevert = await this.rpc.revertSnapshotAsync(this.snapshotId);
+ if (!didRevert) {
+ throw new Error(`Snapshot with id #${this.snapshotId} failed to revert`);
+ }
+ }
+};
diff --git a/test/utils/constants.ts b/test/utils/constants.ts
new file mode 100644
index 000000000..aa1967f88
--- /dev/null
+++ b/test/utils/constants.ts
@@ -0,0 +1,5 @@
+export const constants = {
+ NULL_ADDRESS: '0x0000000000000000000000000000000000000000',
+ RPC_HOST: 'localhost',
+ RPC_PORT: 8545,
+};
diff --git a/test/utils/rpc.ts b/test/utils/rpc.ts
new file mode 100644
index 000000000..e331fa6d4
--- /dev/null
+++ b/test/utils/rpc.ts
@@ -0,0 +1,48 @@
+import * as ethUtil from 'ethereumjs-util';
+import * as request from 'request-promise-native';
+import {constants} from './constants';
+
+export class RPC {
+ private host: string;
+ private port: number;
+ private id: number;
+ constructor() {
+ this.host = constants.RPC_HOST;
+ this.port = constants.RPC_PORT;
+ this.id = 0;
+ }
+ public async takeSnapshotAsync(): Promise<number> {
+ const method = 'evm_snapshot';
+ const params: any[] = [];
+ const payload = this.toPayload(method, params);
+ const snapshotIdHex = await this.sendAsync(payload);
+ const snapshotId = ethUtil.bufferToInt(ethUtil.toBuffer(snapshotIdHex));
+ return snapshotId;
+ }
+ public async revertSnapshotAsync(snapshotId: number): Promise<boolean> {
+ const method = 'evm_revert';
+ const params = [snapshotId];
+ const payload = this.toPayload(method, params);
+ const didRevert = await this.sendAsync(payload);
+ return didRevert;
+ }
+ private toPayload(method: string, params: any[] = []): string {
+ const payload = JSON.stringify({
+ id: this.id,
+ method,
+ params,
+ });
+ this.id += 1;
+ return payload;
+ }
+ private async sendAsync(payload: string): Promise<any> {
+ const opts = {
+ method: 'POST',
+ uri: `http://${this.host}:${this.port}`,
+ body: payload,
+ };
+ const bodyString = await request(opts);
+ const body = JSON.parse(bodyString);
+ return body.result;
+ }
+}
diff --git a/test/utils/web3_factory.ts b/test/utils/web3_factory.ts
new file mode 100644
index 000000000..493fbc2df
--- /dev/null
+++ b/test/utils/web3_factory.ts
@@ -0,0 +1,23 @@
+// HACK: web3 injects XMLHttpRequest into the global scope and ProviderEngine checks XMLHttpRequest
+// to know whether it is running in a browser or node environment. We need it to be undefined since
+// we are not running in a browser env.
+// Filed issue: https://github.com/ethereum/web3.js/issues/844
+(global as any).XMLHttpRequest = undefined;
+import ProviderEngine = require('web3-provider-engine');
+import RpcSubprovider = require('web3-provider-engine/subproviders/rpc');
+import * as Web3 from 'web3';
+import {constants} from './constants';
+
+export const web3Factory = {
+ create(): Web3 {
+ const provider = new ProviderEngine();
+ const rpcUrl = `http://${constants.RPC_HOST}:${constants.RPC_PORT}`;
+ provider.addProvider(new RpcSubprovider({
+ rpcUrl,
+ }));
+ provider.start();
+ const web3 = new Web3();
+ web3.setProvider(provider);
+ return web3;
+ },
+};