aboutsummaryrefslogtreecommitdiffstats
path: root/packages/contracts/src/utils
diff options
context:
space:
mode:
authorAmir Bandeali <abandeali1@gmail.com>2018-02-09 09:09:34 +0800
committerAmir Bandeali <abandeali1@gmail.com>2018-04-21 04:56:16 +0800
commit7201a74aeaa6b646e97d7c9c2c4cc979ace5f4f7 (patch)
treef0cd69fbe346bc6e7fcd8cb1a4f010e8d4513804 /packages/contracts/src/utils
parent9e2f8bead9a51a4c30b77781ae3b39bed31c36ee (diff)
downloaddexon-0x-contracts-7201a74aeaa6b646e97d7c9c2c4cc979ace5f4f7.tar.gz
dexon-0x-contracts-7201a74aeaa6b646e97d7c9c2c4cc979ace5f4f7.tar.zst
dexon-0x-contracts-7201a74aeaa6b646e97d7c9c2c4cc979ace5f4f7.zip
Move utils dir into src
Diffstat (limited to 'packages/contracts/src/utils')
-rw-r--r--packages/contracts/src/utils/artifacts.ts25
-rw-r--r--packages/contracts/src/utils/balances.ts30
-rw-r--r--packages/contracts/src/utils/constants.ts14
-rw-r--r--packages/contracts/src/utils/crypto.ts43
-rw-r--r--packages/contracts/src/utils/exchange_wrapper.ts204
-rw-r--r--packages/contracts/src/utils/formatters.ts107
-rw-r--r--packages/contracts/src/utils/multi_sig_wrapper.ts43
-rw-r--r--packages/contracts/src/utils/order_factory.ts37
-rw-r--r--packages/contracts/src/utils/token_registry_wrapper.ts60
-rw-r--r--packages/contracts/src/utils/types.ts116
10 files changed, 679 insertions, 0 deletions
diff --git a/packages/contracts/src/utils/artifacts.ts b/packages/contracts/src/utils/artifacts.ts
new file mode 100644
index 000000000..fd9380d1d
--- /dev/null
+++ b/packages/contracts/src/utils/artifacts.ts
@@ -0,0 +1,25 @@
+import * as DummyTokenArtifact from '../artifacts/DummyToken.json';
+import * as ExchangeArtifact from '../artifacts/Exchange.json';
+import * as MaliciousTokenArtifact from '../artifacts/MaliciousToken.json';
+import * as MultiSigWalletWithTimeLockArtifact from '../artifacts/MultiSigWalletWithTimeLock.json';
+import * as MultiSigWalletWithTimeLockExceptRemoveAuthorizedAddressArtifact from '../artifacts/MultiSigWalletWithTimeLockExceptRemoveAuthorizedAddress.json';
+import * as TokenArtifact from '../artifacts/Token.json';
+import * as TokenRegistryArtifact from '../artifacts/TokenRegistry.json';
+import * as TokenTransferProxyArtifact from '../artifacts/TokenTransferProxy.json';
+import * as EtherTokenArtifact from '../artifacts/WETH9.json';
+import * as ZRXArtifact from '../artifacts/ZRXToken.json';
+
+import { Artifact } from './types';
+
+export const artifacts = {
+ ZRXArtifact: (ZRXArtifact as any) as Artifact,
+ DummyTokenArtifact: (DummyTokenArtifact as any) as Artifact,
+ TokenArtifact: (TokenArtifact as any) as Artifact,
+ ExchangeArtifact: (ExchangeArtifact as any) as Artifact,
+ EtherTokenArtifact: (EtherTokenArtifact as any) as Artifact,
+ TokenRegistryArtifact: (TokenRegistryArtifact as any) as Artifact,
+ MaliciousTokenArtifact: (MaliciousTokenArtifact as any) as Artifact,
+ TokenTransferProxyArtifact: (TokenTransferProxyArtifact as any) as Artifact,
+ MultiSigWalletWithTimeLockArtifact: (MultiSigWalletWithTimeLockArtifact as any) as Artifact,
+ MultiSigWalletWithTimeLockExceptRemoveAuthorizedAddressArtifact: (MultiSigWalletWithTimeLockExceptRemoveAuthorizedAddressArtifact as any) as Artifact,
+};
diff --git a/packages/contracts/src/utils/balances.ts b/packages/contracts/src/utils/balances.ts
new file mode 100644
index 000000000..2ebc10313
--- /dev/null
+++ b/packages/contracts/src/utils/balances.ts
@@ -0,0 +1,30 @@
+import { BigNumber } from '@0xproject/utils';
+import * as _ from 'lodash';
+import * as Web3 from 'web3';
+
+import { DummyTokenContract } from '../contract_wrappers/generated/dummy_token';
+
+import { BalancesByOwner } from './types';
+
+export class Balances {
+ private _tokenContractInstances: DummyTokenContract[];
+ private _ownerAddresses: string[];
+ constructor(tokenContractInstances: DummyTokenContract[], ownerAddresses: string[]) {
+ this._tokenContractInstances = tokenContractInstances;
+ this._ownerAddresses = ownerAddresses;
+ }
+ public async getAsync(): Promise<BalancesByOwner> {
+ const balancesByOwner: BalancesByOwner = {};
+ for (const tokenContractInstance of this._tokenContractInstances) {
+ for (const ownerAddress of this._ownerAddresses) {
+ let balance = await tokenContractInstance.balanceOf.callAsync(ownerAddress);
+ balance = new BigNumber(balance);
+ if (_.isUndefined(balancesByOwner[ownerAddress])) {
+ balancesByOwner[ownerAddress] = {};
+ }
+ balancesByOwner[ownerAddress][tokenContractInstance.address] = balance;
+ }
+ }
+ return balancesByOwner;
+ }
+}
diff --git a/packages/contracts/src/utils/constants.ts b/packages/contracts/src/utils/constants.ts
new file mode 100644
index 000000000..d1152e683
--- /dev/null
+++ b/packages/contracts/src/utils/constants.ts
@@ -0,0 +1,14 @@
+const DUMMY_TOKEN_NAME = '';
+const DUMMY_TOKEN_SYMBOL = '';
+const DUMMY_TOKEN_DECIMALS = 18;
+const DUMMY_TOKEN_TOTAL_SUPPLY = 0;
+
+export const constants = {
+ INVALID_OPCODE: 'invalid opcode',
+ REVERT: 'revert',
+ TESTRPC_NETWORK_ID: 50,
+ MAX_ETHERTOKEN_WITHDRAW_GAS: 43000,
+ MAX_TOKEN_TRANSFERFROM_GAS: 80000,
+ MAX_TOKEN_APPROVE_GAS: 60000,
+ DUMMY_TOKEN_ARGS: [DUMMY_TOKEN_NAME, DUMMY_TOKEN_SYMBOL, DUMMY_TOKEN_DECIMALS, DUMMY_TOKEN_TOTAL_SUPPLY],
+};
diff --git a/packages/contracts/src/utils/crypto.ts b/packages/contracts/src/utils/crypto.ts
new file mode 100644
index 000000000..810072d2f
--- /dev/null
+++ b/packages/contracts/src/utils/crypto.ts
@@ -0,0 +1,43 @@
+import BN = require('bn.js');
+import ABI = require('ethereumjs-abi');
+import ethUtil = require('ethereumjs-util');
+import * as _ from 'lodash';
+
+export const crypto = {
+ /**
+ * We convert types from JS to Solidity as follows:
+ * BigNumber -> uint256
+ * number -> uint8
+ * string -> string
+ * boolean -> bool
+ * valid Ethereum address -> address
+ */
+ solSHA3(args: any[]): Buffer {
+ return crypto._solHash(args, ABI.soliditySHA3);
+ },
+ solSHA256(args: any[]): Buffer {
+ return crypto._solHash(args, ABI.soliditySHA256);
+ },
+ _solHash(args: any[], hashFunction: (types: string[], values: any[]) => Buffer) {
+ const argTypes: string[] = [];
+ _.each(args, (arg, i) => {
+ const isNumber = _.isFinite(arg);
+ if (isNumber) {
+ argTypes.push('uint8');
+ } else if (arg.isBigNumber) {
+ argTypes.push('uint256');
+ args[i] = new BN(arg.toString(10), 10);
+ } else if (ethUtil.isValidAddress(arg)) {
+ argTypes.push('address');
+ } else if (_.isString(arg)) {
+ argTypes.push('string');
+ } else if (_.isBoolean(arg)) {
+ argTypes.push('bool');
+ } else {
+ throw new Error(`Unable to guess arg type: ${arg}`);
+ }
+ });
+ const hash = hashFunction(argTypes, args);
+ return hash;
+ },
+};
diff --git a/packages/contracts/src/utils/exchange_wrapper.ts b/packages/contracts/src/utils/exchange_wrapper.ts
new file mode 100644
index 000000000..75b452b04
--- /dev/null
+++ b/packages/contracts/src/utils/exchange_wrapper.ts
@@ -0,0 +1,204 @@
+import { SignedOrder, TransactionReceiptWithDecodedLogs, ZeroEx } from '0x.js';
+import { BigNumber } from '@0xproject/utils';
+import * as _ from 'lodash';
+import * as Web3 from 'web3';
+
+import { ExchangeContract } from '../contract_wrappers/generated/exchange';
+
+import { formatters } from './formatters';
+import { signedOrderUtils } from './signed_order_utils';
+
+export class ExchangeWrapper {
+ private _exchange: ExchangeContract;
+ private _zeroEx: ZeroEx;
+ constructor(exchangeContract: ExchangeContract, zeroEx: ZeroEx) {
+ this._exchange = exchangeContract;
+ this._zeroEx = zeroEx;
+ }
+ public async fillOrderAsync(
+ signedOrder: SignedOrder,
+ from: string,
+ opts: { takerTokenFillAmount?: BigNumber } = {},
+ ): Promise<TransactionReceiptWithDecodedLogs> {
+ const params = signedOrderUtils.createFill(
+ signedOrder,
+ opts.takerTokenFillAmount,
+ );
+ const txHash = await this._exchange.fillOrder.sendTransactionAsync(
+ params.orderAddresses,
+ params.orderValues,
+ params.takerTokenFillAmount,
+ params.v,
+ params.r,
+ params.s,
+ { from },
+ );
+ const tx = await this._zeroEx.awaitTransactionMinedAsync(txHash);
+ tx.logs = _.filter(tx.logs, log => log.address === this._exchange.address);
+ _.each(tx.logs, log => wrapLogBigNumbers(log));
+ return tx;
+ }
+ public async cancelOrderAsync(
+ signedOrder: SignedOrder,
+ from: string,
+ opts: { takerTokenCancelAmount?: BigNumber } = {},
+ ): Promise<TransactionReceiptWithDecodedLogs> {
+ const params = signedOrderUtils.createCancel(signedOrder, opts.takerTokenCancelAmount);
+ const txHash = await this._exchange.cancelOrder.sendTransactionAsync(
+ params.orderAddresses,
+ params.orderValues,
+ params.takerTokenCancelAmount,
+ { from },
+ );
+ const tx = await this._zeroEx.awaitTransactionMinedAsync(txHash);
+ tx.logs = _.filter(tx.logs, log => log.address === this._exchange.address);
+ _.each(tx.logs, log => wrapLogBigNumbers(log));
+ return tx;
+ }
+ public async fillOrKillOrderAsync(
+ signedOrder: SignedOrder,
+ from: string,
+ opts: { takerTokenFillAmount?: BigNumber } = {},
+ ): Promise<TransactionReceiptWithDecodedLogs> {
+ const params = signedOrderUtils.createFill(
+ signedOrder,
+ opts.takerTokenFillAmount,
+ );
+ const txHash = await this._exchange.fillOrKillOrder.sendTransactionAsync(
+ params.orderAddresses,
+ params.orderValues,
+ params.takerTokenFillAmount,
+ params.v,
+ params.r,
+ params.s,
+ { from },
+ );
+ const tx = await this._zeroEx.awaitTransactionMinedAsync(txHash);
+ tx.logs = _.filter(tx.logs, log => log.address === this._exchange.address);
+ _.each(tx.logs, log => wrapLogBigNumbers(log));
+ return tx;
+ }
+ public async batchFillOrdersAsync(
+ orders: SignedOrder[],
+ from: string,
+ opts: {
+ takerTokenFillAmounts?: BigNumber[];
+ shouldThrowOnInsufficientBalanceOrAllowance?: boolean;
+ } = {},
+ ): Promise<TransactionReceiptWithDecodedLogs> {
+ const params = formatters.createBatchFill(orders, opts.takerTokenFillAmounts);
+ const txHash = await this._exchange.batchFillOrders.sendTransactionAsync(
+ params.orderAddresses,
+ params.orderValues,
+ params.takerTokenFillAmounts,
+ params.v,
+ params.r,
+ params.s,
+ { from },
+ );
+ const tx = await this._zeroEx.awaitTransactionMinedAsync(txHash);
+ tx.logs = _.filter(tx.logs, log => log.address === this._exchange.address);
+ _.each(tx.logs, log => wrapLogBigNumbers(log));
+ return tx;
+ }
+ public async batchFillOrKillOrdersAsync(
+ orders: SignedOrder[],
+ from: string,
+ opts: { takerTokenFillAmounts?: BigNumber[] } = {},
+ ): Promise<TransactionReceiptWithDecodedLogs> {
+ const params = formatters.createBatchFill(orders, opts.takerTokenFillAmounts);
+ const txHash = await this._exchange.batchFillOrKillOrders.sendTransactionAsync(
+ params.orderAddresses,
+ params.orderValues,
+ params.takerTokenFillAmounts,
+ params.v,
+ params.r,
+ params.s,
+ { from },
+ );
+ const tx = await this._zeroEx.awaitTransactionMinedAsync(txHash);
+ tx.logs = _.filter(tx.logs, log => log.address === this._exchange.address);
+ _.each(tx.logs, log => wrapLogBigNumbers(log));
+ return tx;
+ }
+ public async marketFillOrdersAsync(
+ orders: SignedOrder[],
+ from: string,
+ opts: { takerTokenFillAmount: BigNumber },
+ ): Promise<TransactionReceiptWithDecodedLogs> {
+ const params = formatters.createMarketFillOrders(orders, opts.takerTokenFillAmount);
+ const txHash = await this._exchange.marketFillOrders.sendTransactionAsync(
+ params.orderAddresses,
+ params.orderValues,
+ params.takerTokenFillAmount,
+ params.v,
+ params.r,
+ params.s,
+ { from },
+ );
+ const tx = await this._zeroEx.awaitTransactionMinedAsync(txHash);
+ tx.logs = _.filter(tx.logs, log => log.address === this._exchange.address);
+ _.each(tx.logs, log => wrapLogBigNumbers(log));
+ return tx;
+ }
+ public async batchCancelOrdersAsync(
+ orders: SignedOrder[],
+ from: string,
+ opts: { takerTokenCancelAmounts?: BigNumber[] } = {},
+ ): Promise<TransactionReceiptWithDecodedLogs> {
+ const params = formatters.createBatchCancel(orders, opts.takerTokenCancelAmounts);
+ const txHash = await this._exchange.batchCancelOrders.sendTransactionAsync(
+ params.orderAddresses,
+ params.orderValues,
+ params.takerTokenCancelAmounts,
+ { from },
+ );
+ const tx = await this._zeroEx.awaitTransactionMinedAsync(txHash);
+ tx.logs = _.filter(tx.logs, log => log.address === this._exchange.address);
+ _.each(tx.logs, log => wrapLogBigNumbers(log));
+ return tx;
+ }
+ public async getOrderHashAsync(signedOrder: SignedOrder): Promise<string> {
+ const params = signedOrderUtils.getOrderAddressesAndValues(signedOrder);
+ const orderHash = await this._exchange.getOrderHash.callAsync(params.orderAddresses, params.orderValues);
+ return orderHash;
+ }
+ public async isValidSignatureAsync(signedOrder: SignedOrder): Promise<boolean> {
+ const isValidSignature = await this._exchange.isValidSignature.callAsync(
+ signedOrder.maker,
+ ZeroEx.getOrderHashHex(signedOrder),
+ signedOrder.ecSignature.v,
+ signedOrder.ecSignature.r,
+ signedOrder.ecSignature.s,
+ );
+ return isValidSignature;
+ }
+ public async isRoundingErrorAsync(
+ numerator: BigNumber,
+ denominator: BigNumber,
+ target: BigNumber,
+ ): Promise<boolean> {
+ const isRoundingError = await this._exchange.isRoundingError.callAsync(numerator, denominator, target);
+ return isRoundingError;
+ }
+ public async getPartialAmountAsync(
+ numerator: BigNumber,
+ denominator: BigNumber,
+ target: BigNumber,
+ ): Promise<BigNumber> {
+ const partialAmount = new BigNumber(
+ await this._exchange.getPartialAmount.callAsync(numerator, denominator, target),
+ );
+ return partialAmount;
+ }
+}
+
+function wrapLogBigNumbers(log: any): any {
+ const argNames = _.keys(log.args);
+ for (const argName of argNames) {
+ const isWeb3BigNumber = _.startsWith(log.args[argName].constructor.toString(), 'function BigNumber(');
+ if (isWeb3BigNumber) {
+ log.args[argName] = new BigNumber(log.args[argName]);
+ }
+ }
+}
diff --git a/packages/contracts/src/utils/formatters.ts b/packages/contracts/src/utils/formatters.ts
new file mode 100644
index 000000000..88e12a6b4
--- /dev/null
+++ b/packages/contracts/src/utils/formatters.ts
@@ -0,0 +1,107 @@
+import { SignedOrder } from '0x.js';
+import { BigNumber } from '@0xproject/utils';
+import * as _ from 'lodash';
+
+import { BatchCancelOrders, BatchFillOrders, MarketFillOrders } from './types';
+
+export const formatters = {
+ createBatchFill(
+ signedOrders: SignedOrder[],
+ takerTokenFillAmounts: BigNumber[] = [],
+ ) {
+ const batchFill: BatchFillOrders = {
+ orderAddresses: [],
+ orderValues: [],
+ takerTokenFillAmounts,
+ v: [],
+ r: [],
+ s: [],
+ };
+ _.forEach(signedOrders, signedOrder => {
+ batchFill.orderAddresses.push([
+ signedOrder.maker,
+ signedOrder.taker,
+ signedOrder.makerTokenAddress,
+ signedOrder.takerTokenAddress,
+ signedOrder.feeRecipient,
+ ]);
+ batchFill.orderValues.push([
+ signedOrder.makerTokenAmount,
+ signedOrder.takerTokenAmount,
+ signedOrder.makerFee,
+ signedOrder.takerFee,
+ signedOrder.expirationUnixTimestampSec,
+ signedOrder.salt,
+ ]);
+ batchFill.v.push(signedOrder.ecSignature.v);
+ batchFill.r.push(signedOrder.ecSignature.r);
+ batchFill.s.push(signedOrder.ecSignature.s);
+ if (takerTokenFillAmounts.length < signedOrders.length) {
+ batchFill.takerTokenFillAmounts.push(signedOrder.takerTokenAmount);
+ }
+ });
+ return batchFill;
+ },
+ createMarketFillOrders(
+ signedOrders: SignedOrder[],
+ takerTokenFillAmount: BigNumber,
+ ) {
+ const marketFillOrders: MarketFillOrders = {
+ orderAddresses: [],
+ orderValues: [],
+ takerTokenFillAmount,
+ v: [],
+ r: [],
+ s: [],
+ };
+ signedOrders.forEach(signedOrder => {
+ marketFillOrders.orderAddresses.push([
+ signedOrder.maker,
+ signedOrder.taker,
+ signedOrder.makerTokenAddress,
+ signedOrder.takerTokenAddress,
+ signedOrder.feeRecipient,
+ ]);
+ marketFillOrders.orderValues.push([
+ signedOrder.makerTokenAmount,
+ signedOrder.takerTokenAmount,
+ signedOrder.makerFee,
+ signedOrder.takerFee,
+ signedOrder.expirationUnixTimestampSec,
+ signedOrder.salt,
+ ]);
+ marketFillOrders.v.push(signedOrder.ecSignature.v);
+ marketFillOrders.r.push(signedOrder.ecSignature.r);
+ marketFillOrders.s.push(signedOrder.ecSignature.s);
+ });
+ return marketFillOrders;
+ },
+ createBatchCancel(signedOrders: SignedOrder[], takerTokenCancelAmounts: BigNumber[] = []) {
+ const batchCancel: BatchCancelOrders = {
+ orderAddresses: [],
+ orderValues: [],
+ takerTokenCancelAmounts,
+ };
+ signedOrders.forEach(signedOrder => {
+ batchCancel.orderAddresses.push([
+ signedOrder.maker,
+ signedOrder.taker,
+ signedOrder.makerTokenAddress,
+ signedOrder.takerTokenAddress,
+ signedOrder.feeRecipient,
+ ]);
+ batchCancel.orderValues.push([
+ signedOrder.makerTokenAmount,
+ signedOrder.takerTokenAmount,
+ signedOrder.makerFee,
+ signedOrder.takerFee,
+ signedOrder.expirationUnixTimestampSec,
+ signedOrder.salt,
+ ]);
+ if (takerTokenCancelAmounts.length < signedOrders.length) {
+ batchCancel.takerTokenCancelAmounts.push(signedOrder.takerTokenAmount);
+ }
+ });
+ return batchCancel;
+ },
+};
diff --git a/packages/contracts/src/utils/multi_sig_wrapper.ts b/packages/contracts/src/utils/multi_sig_wrapper.ts
new file mode 100644
index 000000000..84fed7944
--- /dev/null
+++ b/packages/contracts/src/utils/multi_sig_wrapper.ts
@@ -0,0 +1,43 @@
+import { AbiDefinition, MethodAbi } from '@0xproject/types';
+import { BigNumber } from '@0xproject/utils';
+import ABI = require('ethereumjs-abi');
+import ethUtil = require('ethereumjs-util');
+import * as _ from 'lodash';
+import * as Web3 from 'web3';
+
+import { MultiSigWalletContract } from '../contract_wrappers/generated/multi_sig_wallet';
+
+import { TransactionDataParams } from './types';
+
+export class MultiSigWrapper {
+ private _multiSig: MultiSigWalletContract;
+ public static encodeFnArgs(name: string, abi: AbiDefinition[], args: any[]) {
+ const abiEntity = _.find(abi, { name }) as MethodAbi;
+ if (_.isUndefined(abiEntity)) {
+ throw new Error(`Did not find abi entry for name: ${name}`);
+ }
+ const types = _.map(abiEntity.inputs, input => input.type);
+ const funcSig = ethUtil.bufferToHex(ABI.methodID(name, types));
+ const argsData = _.map(args, arg => {
+ const target = _.isBoolean(arg) ? +arg : arg;
+ const targetBuff = ethUtil.toBuffer(target);
+ return ethUtil.setLengthLeft(targetBuff, 32).toString('hex');
+ });
+ return funcSig + argsData.join('');
+ }
+ constructor(multiSigContract: MultiSigWalletContract) {
+ this._multiSig = multiSigContract;
+ }
+ public async submitTransactionAsync(
+ destination: string,
+ from: string,
+ dataParams: TransactionDataParams,
+ value: BigNumber = new BigNumber(0),
+ ) {
+ const { name, abi, args = [] } = dataParams;
+ const encoded = MultiSigWrapper.encodeFnArgs(name, abi, args);
+ return this._multiSig.submitTransaction.sendTransactionAsync(destination, value, encoded, {
+ from,
+ });
+ }
+}
diff --git a/packages/contracts/src/utils/order_factory.ts b/packages/contracts/src/utils/order_factory.ts
new file mode 100644
index 000000000..8ba5df24a
--- /dev/null
+++ b/packages/contracts/src/utils/order_factory.ts
@@ -0,0 +1,37 @@
+import { Order, SignedOrder, ZeroEx } from '0x.js';
+import { BigNumber } from '@0xproject/utils';
+import { Web3Wrapper } from '@0xproject/web3-wrapper';
+import * as _ from 'lodash';
+
+import { DefaultOrderParams } from './types';
+
+export class OrderFactory {
+ private _defaultOrderParams: Partial<Order>;
+ private _zeroEx: ZeroEx;
+ constructor(zeroEx: ZeroEx, defaultOrderParams: Partial<Order>) {
+ this._defaultOrderParams = defaultOrderParams;
+ this._zeroEx = zeroEx;
+ }
+ public async newSignedOrderAsync(customOrderParams: Partial<Order> = {}): Promise<SignedOrder> {
+ const randomExpiration = new BigNumber(Math.floor((Date.now() + Math.random() * 100000000000) / 1000));
+ const order = ({
+ expirationUnixTimestampSec: randomExpiration,
+ salt: ZeroEx.generatePseudoRandomSalt(),
+ taker: ZeroEx.NULL_ADDRESS,
+ ...this._defaultOrderParams,
+ ...customOrderParams,
+ } as any) as Order;
+ const orderHashHex = ZeroEx.getOrderHashHex(order);
+ const shouldAddPersonalMessagePrefix = false;
+ const ecSignature = await this._zeroEx.signOrderHashAsync(
+ orderHashHex,
+ order.maker,
+ shouldAddPersonalMessagePrefix,
+ );
+ const signedOrder = {
+ ...order,
+ ecSignature,
+ };
+ return signedOrder;
+ }
+}
diff --git a/packages/contracts/src/utils/token_registry_wrapper.ts b/packages/contracts/src/utils/token_registry_wrapper.ts
new file mode 100644
index 000000000..91bd5503d
--- /dev/null
+++ b/packages/contracts/src/utils/token_registry_wrapper.ts
@@ -0,0 +1,60 @@
+import * as Web3 from 'web3';
+
+import { TokenRegistryContract } from '../contract_wrappers/generated/token_registry';
+
+import { Token } from './types';
+
+export class TokenRegWrapper {
+ private _tokenReg: TokenRegistryContract;
+ constructor(tokenRegContract: TokenRegistryContract) {
+ this._tokenReg = tokenRegContract;
+ }
+ public async addTokenAsync(token: Token, from: string) {
+ const tx = this._tokenReg.addToken.sendTransactionAsync(
+ token.address as string,
+ token.name,
+ token.symbol,
+ token.decimals,
+ token.ipfsHash,
+ token.swarmHash,
+ { from },
+ );
+ return tx;
+ }
+ public async getTokenMetaDataAsync(tokenAddress: string) {
+ const data = await this._tokenReg.getTokenMetaData.callAsync(tokenAddress);
+ const token: Token = {
+ address: data[0],
+ name: data[1],
+ symbol: data[2],
+ decimals: data[3],
+ ipfsHash: data[4],
+ swarmHash: data[5],
+ };
+ return token;
+ }
+ public async getTokenByNameAsync(tokenName: string) {
+ const data = await this._tokenReg.getTokenByName.callAsync(tokenName);
+ const token: Token = {
+ address: data[0],
+ name: data[1],
+ symbol: data[2],
+ decimals: data[3],
+ ipfsHash: data[4],
+ swarmHash: data[5],
+ };
+ return token;
+ }
+ public async getTokenBySymbolAsync(tokenSymbol: string) {
+ const data = await this._tokenReg.getTokenBySymbol.callAsync(tokenSymbol);
+ const token: Token = {
+ address: data[0],
+ name: data[1],
+ symbol: data[2],
+ decimals: data[3],
+ ipfsHash: data[4],
+ swarmHash: data[5],
+ };
+ return token;
+ }
+}
diff --git a/packages/contracts/src/utils/types.ts b/packages/contracts/src/utils/types.ts
new file mode 100644
index 000000000..2ffc84f04
--- /dev/null
+++ b/packages/contracts/src/utils/types.ts
@@ -0,0 +1,116 @@
+import { AbiDefinition, ContractAbi } from '@0xproject/types';
+import { BigNumber } from '@0xproject/utils';
+
+export interface BalancesByOwner {
+ [ownerAddress: string]: {
+ [tokenAddress: string]: BigNumber;
+ };
+}
+
+export interface SubmissionContractEventArgs {
+ transactionId: BigNumber;
+}
+
+export interface BatchFillOrders {
+ orderAddresses: string[][];
+ orderValues: BigNumber[][];
+ takerTokenFillAmounts: BigNumber[];
+ v: number[];
+ r: string[];
+ s: string[];
+}
+
+export interface MarketFillOrders {
+ orderAddresses: string[][];
+ orderValues: BigNumber[][];
+ takerTokenFillAmount: BigNumber;
+ v: number[];
+ r: string[];
+ s: string[];
+}
+
+export interface BatchCancelOrders {
+ orderAddresses: string[][];
+ orderValues: BigNumber[][];
+ takerTokenCancelAmounts: BigNumber[];
+}
+
+export interface DefaultOrderParams {
+ exchangeContractAddress: string;
+ maker: string;
+ feeRecipient: string;
+ makerTokenAddress: string;
+ takerTokenAddress: string;
+ makerTokenAmount: BigNumber;
+ takerTokenAmount: BigNumber;
+ makerFee: BigNumber;
+ takerFee: BigNumber;
+}
+
+export interface TransactionDataParams {
+ name: string;
+ abi: AbiDefinition[];
+ args: any[];
+}
+
+export interface MultiSigConfig {
+ owners: string[];
+ confirmationsRequired: number;
+ secondsRequired: number;
+}
+
+export interface MultiSigConfigByNetwork {
+ [networkName: string]: MultiSigConfig;
+}
+
+export interface Token {
+ address?: string;
+ name: string;
+ symbol: string;
+ decimals: number;
+ ipfsHash: string;
+ swarmHash: string;
+}
+
+export interface TokenInfoByNetwork {
+ development: Token[];
+ live: Token[];
+}
+
+export enum ExchangeContractErrs {
+ ERROR_ORDER_EXPIRED,
+ ERROR_ORDER_FULLY_FILLED_OR_CANCELLED,
+ ERROR_ROUNDING_ERROR_TOO_LARGE,
+ ERROR_INSUFFICIENT_BALANCE_OR_ALLOWANCE,
+}
+
+export enum ContractName {
+ TokenTransferProxy = 'TokenTransferProxy',
+ TokenRegistry = 'TokenRegistry',
+ MultiSigWalletWithTimeLock = 'MultiSigWalletWithTimeLock',
+ Exchange = 'Exchange',
+ ZRXToken = 'ZRXToken',
+ DummyToken = 'DummyToken',
+ EtherToken = 'WETH9',
+ MultiSigWalletWithTimeLockExceptRemoveAuthorizedAddress = 'MultiSigWalletWithTimeLockExceptRemoveAuthorizedAddress',
+ MaliciousToken = 'MaliciousToken',
+ AccountLevels = 'AccountLevels',
+ EtherDelta = 'EtherDelta',
+ Arbitrage = 'Arbitrage',
+}
+
+export interface Artifact {
+ contract_name: ContractName;
+ networks: {
+ [networkId: number]: {
+ abi: ContractAbi;
+ solc_version: string;
+ keccak256: string;
+ optimizer_enabled: number;
+ unlinked_binary: string;
+ updated_at: number;
+ address: string;
+ constructor_args: string;
+ };
+ };
+}