aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--packages/contracts/util/exchange_wrapper.ts59
-rw-r--r--packages/contracts/util/formatters.ts34
-rw-r--r--packages/contracts/util/order.ts105
-rw-r--r--packages/contracts/util/signed_order_utils.ts10
-rw-r--r--packages/contracts/util/types.ts8
5 files changed, 148 insertions, 68 deletions
diff --git a/packages/contracts/util/exchange_wrapper.ts b/packages/contracts/util/exchange_wrapper.ts
index f016067fe..14d603f58 100644
--- a/packages/contracts/util/exchange_wrapper.ts
+++ b/packages/contracts/util/exchange_wrapper.ts
@@ -18,22 +18,16 @@ export class ExchangeWrapper {
public async fillOrderAsync(
signedOrder: SignedOrder,
from: string,
- opts: {
- fillTakerTokenAmount?: BigNumber;
- shouldThrowOnInsufficientBalanceOrAllowance?: boolean;
- } = {},
+ opts: { takerTokenFillAmount?: BigNumber } = {},
): Promise<TransactionReceiptWithDecodedLogs> {
- const shouldThrowOnInsufficientBalanceOrAllowance = !!opts.shouldThrowOnInsufficientBalanceOrAllowance;
const params = signedOrderUtils.createFill(
signedOrder,
- shouldThrowOnInsufficientBalanceOrAllowance,
- opts.fillTakerTokenAmount,
+ opts.takerTokenFillAmount,
);
const txHash = await this._exchange.fillOrder.sendTransactionAsync(
params.orderAddresses,
params.orderValues,
- params.fillTakerTokenAmount,
- params.shouldThrowOnInsufficientBalanceOrAllowance,
+ params.takerTokenFillAmount,
params.v,
params.r,
params.s,
@@ -47,13 +41,13 @@ export class ExchangeWrapper {
public async cancelOrderAsync(
signedOrder: SignedOrder,
from: string,
- opts: { cancelTakerTokenAmount?: BigNumber } = {},
+ opts: { takerTokenCancelAmount?: BigNumber } = {},
): Promise<TransactionReceiptWithDecodedLogs> {
- const params = signedOrderUtils.createCancel(signedOrder, opts.cancelTakerTokenAmount);
+ const params = signedOrderUtils.createCancel(signedOrder, opts.takerTokenCancelAmount);
const txHash = await this._exchange.cancelOrder.sendTransactionAsync(
params.orderAddresses,
params.orderValues,
- params.cancelTakerTokenAmount,
+ params.takerTokenCancelAmount,
{ from },
);
const tx = await this._zeroEx.awaitTransactionMinedAsync(txHash);
@@ -64,18 +58,16 @@ export class ExchangeWrapper {
public async fillOrKillOrderAsync(
signedOrder: SignedOrder,
from: string,
- opts: { fillTakerTokenAmount?: BigNumber } = {},
+ opts: { takerTokenFillAmount?: BigNumber } = {},
): Promise<TransactionReceiptWithDecodedLogs> {
- const shouldThrowOnInsufficientBalanceOrAllowance = true;
const params = signedOrderUtils.createFill(
signedOrder,
- shouldThrowOnInsufficientBalanceOrAllowance,
- opts.fillTakerTokenAmount,
+ opts.takerTokenFillAmount,
);
const txHash = await this._exchange.fillOrKillOrder.sendTransactionAsync(
params.orderAddresses,
params.orderValues,
- params.fillTakerTokenAmount,
+ params.takerTokenFillAmount,
params.v,
params.r,
params.s,
@@ -90,21 +82,18 @@ export class ExchangeWrapper {
orders: SignedOrder[],
from: string,
opts: {
- fillTakerTokenAmounts?: BigNumber[];
+ takerTokenFillAmounts?: BigNumber[];
shouldThrowOnInsufficientBalanceOrAllowance?: boolean;
} = {},
): Promise<TransactionReceiptWithDecodedLogs> {
- const shouldThrowOnInsufficientBalanceOrAllowance = !!opts.shouldThrowOnInsufficientBalanceOrAllowance;
const params = formatters.createBatchFill(
orders,
- shouldThrowOnInsufficientBalanceOrAllowance,
- opts.fillTakerTokenAmounts,
+ opts.takerTokenFillAmounts,
);
const txHash = await this._exchange.batchFillOrders.sendTransactionAsync(
params.orderAddresses,
params.orderValues,
- params.fillTakerTokenAmounts,
- params.shouldThrowOnInsufficientBalanceOrAllowance,
+ params.takerTokenFillAmounts,
params.v,
params.r,
params.s,
@@ -118,18 +107,16 @@ export class ExchangeWrapper {
public async batchFillOrKillOrdersAsync(
orders: SignedOrder[],
from: string,
- opts: { fillTakerTokenAmounts?: BigNumber[]; shouldThrowOnInsufficientBalanceOrAllowance?: boolean } = {},
+ opts: { takerTokenFillAmounts?: BigNumber[] } = {},
): Promise<TransactionReceiptWithDecodedLogs> {
- const shouldThrowOnInsufficientBalanceOrAllowance = !!opts.shouldThrowOnInsufficientBalanceOrAllowance;
const params = formatters.createBatchFill(
orders,
- shouldThrowOnInsufficientBalanceOrAllowance,
- opts.fillTakerTokenAmounts,
+ opts.takerTokenFillAmounts,
);
const txHash = await this._exchange.batchFillOrKillOrders.sendTransactionAsync(
params.orderAddresses,
params.orderValues,
- params.fillTakerTokenAmounts,
+ params.takerTokenFillAmounts,
params.v,
params.r,
params.s,
@@ -140,22 +127,19 @@ export class ExchangeWrapper {
_.each(tx.logs, log => wrapLogBigNumbers(log));
return tx;
}
- public async fillOrdersUpToAsync(
+ public async marketFillOrdersAsync(
orders: SignedOrder[],
from: string,
- opts: { fillTakerTokenAmount: BigNumber; shouldThrowOnInsufficientBalanceOrAllowance?: boolean },
+ opts: { takerTokenFillAmount: BigNumber },
): Promise<TransactionReceiptWithDecodedLogs> {
- const shouldThrowOnInsufficientBalanceOrAllowance = !!opts.shouldThrowOnInsufficientBalanceOrAllowance;
- const params = formatters.createFillUpTo(
+ const params = formatters.createMarketFillOrders(
orders,
- shouldThrowOnInsufficientBalanceOrAllowance,
- opts.fillTakerTokenAmount,
+ opts.takerTokenFillAmount,
);
- const txHash = await this._exchange.fillOrdersUpTo.sendTransactionAsync(
+ const txHash = await this._exchange.marketFillOrders.sendTransactionAsync(
params.orderAddresses,
params.orderValues,
- params.fillTakerTokenAmount,
- params.shouldThrowOnInsufficientBalanceOrAllowance,
+ params.takerTokenFillAmount,
params.v,
params.r,
params.s,
@@ -184,7 +168,6 @@ export class ExchangeWrapper {
return tx;
}
public async getOrderHashAsync(signedOrder: SignedOrder): Promise<string> {
- const shouldThrowOnInsufficientBalanceOrAllowance = false;
const params = signedOrderUtils.getOrderAddressesAndValues(signedOrder);
const orderHash = await this._exchange.getOrderHash.callAsync(params.orderAddresses, params.orderValues);
return orderHash;
diff --git a/packages/contracts/util/formatters.ts b/packages/contracts/util/formatters.ts
index 8e0dfb09e..e3080af15 100644
--- a/packages/contracts/util/formatters.ts
+++ b/packages/contracts/util/formatters.ts
@@ -2,19 +2,17 @@ import { SignedOrder } from '0x.js';
import { BigNumber } from '@0xproject/utils';
import * as _ from 'lodash';
-import { BatchCancelOrders, BatchFillOrders, FillOrdersUpTo } from './types';
+import { BatchCancelOrders, BatchFillOrders, MarketFillOrders } from './types';
export const formatters = {
createBatchFill(
signedOrders: SignedOrder[],
- shouldThrowOnInsufficientBalanceOrAllowance: boolean,
- fillTakerTokenAmounts: BigNumber[] = [],
+ takerTokenFillAmounts: BigNumber[] = [],
) {
const batchFill: BatchFillOrders = {
orderAddresses: [],
orderValues: [],
- fillTakerTokenAmounts,
- shouldThrowOnInsufficientBalanceOrAllowance,
+ takerTokenFillAmounts,
v: [],
r: [],
s: [],
@@ -38,35 +36,33 @@ export const formatters = {
batchFill.v.push(signedOrder.ecSignature.v);
batchFill.r.push(signedOrder.ecSignature.r);
batchFill.s.push(signedOrder.ecSignature.s);
- if (fillTakerTokenAmounts.length < signedOrders.length) {
- batchFill.fillTakerTokenAmounts.push(signedOrder.takerTokenAmount);
+ if (takerTokenFillAmounts.length < signedOrders.length) {
+ batchFill.takerTokenFillAmounts.push(signedOrder.takerTokenAmount);
}
});
return batchFill;
},
- createFillUpTo(
+ createMarketFillOrders(
signedOrders: SignedOrder[],
- shouldThrowOnInsufficientBalanceOrAllowance: boolean,
- fillTakerTokenAmount: BigNumber,
+ takerTokenFillAmount: BigNumber,
) {
- const fillUpTo: FillOrdersUpTo = {
+ const marketFillOrders: MarketFillOrders = {
orderAddresses: [],
orderValues: [],
- fillTakerTokenAmount,
- shouldThrowOnInsufficientBalanceOrAllowance,
+ takerTokenFillAmount,
v: [],
r: [],
s: [],
};
signedOrders.forEach(signedOrder => {
- fillUpTo.orderAddresses.push([
+ marketFillOrders.orderAddresses.push([
signedOrder.maker,
signedOrder.taker,
signedOrder.makerTokenAddress,
signedOrder.takerTokenAddress,
signedOrder.feeRecipient,
]);
- fillUpTo.orderValues.push([
+ marketFillOrders.orderValues.push([
signedOrder.makerTokenAmount,
signedOrder.takerTokenAmount,
signedOrder.makerFee,
@@ -74,11 +70,11 @@ export const formatters = {
signedOrder.expirationUnixTimestampSec,
signedOrder.salt,
]);
- fillUpTo.v.push(signedOrder.ecSignature.v);
- fillUpTo.r.push(signedOrder.ecSignature.r);
- fillUpTo.s.push(signedOrder.ecSignature.s);
+ marketFillOrders.v.push(signedOrder.ecSignature.v);
+ marketFillOrders.r.push(signedOrder.ecSignature.r);
+ marketFillOrders.s.push(signedOrder.ecSignature.s);
});
- return fillUpTo;
+ return marketFillOrders;
},
createBatchCancel(signedOrders: SignedOrder[], cancelTakerTokenAmounts: BigNumber[] = []) {
const batchCancel: BatchCancelOrders = {
diff --git a/packages/contracts/util/order.ts b/packages/contracts/util/order.ts
new file mode 100644
index 000000000..b42149d38
--- /dev/null
+++ b/packages/contracts/util/order.ts
@@ -0,0 +1,105 @@
+import { BigNumber } from '@0xproject/utils';
+import { Web3Wrapper } from '@0xproject/web3-wrapper';
+import ethUtil = require('ethereumjs-util');
+import * as _ from 'lodash';
+
+import { crypto } from './crypto';
+import { OrderParams } from './types';
+
+export class Order {
+ public params: OrderParams;
+ private _web3Wrapper: Web3Wrapper;
+ constructor(web3Wrapper: Web3Wrapper, params: OrderParams) {
+ this.params = params;
+ this._web3Wrapper = web3Wrapper;
+ }
+ public isValidSignature() {
+ const { v, r, s } = this.params;
+ if (_.isUndefined(v) || _.isUndefined(r) || _.isUndefined(s)) {
+ throw new Error('Cannot call isValidSignature on unsigned order');
+ }
+ const orderHash = this._getOrderHash();
+ const msgHash = ethUtil.hashPersonalMessage(ethUtil.toBuffer(orderHash));
+ try {
+ const pubKey = ethUtil.ecrecover(msgHash, v, ethUtil.toBuffer(r), ethUtil.toBuffer(s));
+ const recoveredAddress = ethUtil.bufferToHex(ethUtil.pubToAddress(pubKey));
+ return recoveredAddress === this.params.maker;
+ } catch (err) {
+ return false;
+ }
+ }
+ public async signAsync() {
+ const orderHash = this._getOrderHash();
+ const signature = await this._web3Wrapper.signTransactionAsync(this.params.maker, orderHash);
+ const { v, r, s } = ethUtil.fromRpcSig(signature);
+ this.params = _.assign(this.params, {
+ orderHashHex: orderHash,
+ v,
+ r: ethUtil.bufferToHex(r),
+ s: ethUtil.bufferToHex(s),
+ });
+ }
+ public createFill(takerTokenFillAmount?: BigNumber) {
+ const fill = {
+ orderAddresses: [
+ this.params.maker,
+ this.params.taker,
+ this.params.makerToken,
+ this.params.takerToken,
+ this.params.feeRecipient,
+ ],
+ orderValues: [
+ this.params.makerTokenAmount,
+ this.params.takerTokenAmount,
+ this.params.makerFee,
+ this.params.takerFee,
+ this.params.expirationTimestampInSec,
+ this.params.salt,
+ ],
+ takerTokenFillAmount: takerTokenFillAmount || this.params.takerTokenAmount,
+ v: this.params.v,
+ r: this.params.r,
+ s: this.params.s,
+ };
+ return fill;
+ }
+ public createCancel(takerTokenCancelAmount?: BigNumber) {
+ const cancel = {
+ orderAddresses: [
+ this.params.maker,
+ this.params.taker,
+ this.params.makerToken,
+ this.params.takerToken,
+ this.params.feeRecipient,
+ ],
+ orderValues: [
+ this.params.makerTokenAmount,
+ this.params.takerTokenAmount,
+ this.params.makerFee,
+ this.params.takerFee,
+ this.params.expirationTimestampInSec,
+ this.params.salt,
+ ],
+ takerTokenCancelAmount: takerTokenCancelAmount || this.params.takerTokenAmount,
+ };
+ return cancel;
+ }
+ private _getOrderHash(): string {
+ const orderHash = crypto.solSHA3([
+ this.params.exchangeContractAddress,
+ this.params.maker,
+ this.params.taker,
+ this.params.makerToken,
+ this.params.takerToken,
+ this.params.feeRecipient,
+ this.params.makerTokenAmount,
+ this.params.takerTokenAmount,
+ this.params.makerFee,
+ this.params.takerFee,
+ this.params.expirationTimestampInSec,
+ this.params.salt,
+ ]);
+ const orderHashHex = ethUtil.bufferToHex(orderHash);
+ return orderHashHex;
+ }
+}
diff --git a/packages/contracts/util/signed_order_utils.ts b/packages/contracts/util/signed_order_utils.ts
index fc2f800cd..3e5d2f226 100644
--- a/packages/contracts/util/signed_order_utils.ts
+++ b/packages/contracts/util/signed_order_utils.ts
@@ -9,21 +9,19 @@ import { crypto } from './crypto';
export const signedOrderUtils = {
createFill: (
signedOrder: SignedOrder,
- shouldThrowOnInsufficientBalanceOrAllowance?: boolean,
- fillTakerTokenAmount?: BigNumber,
+ takerTokenFillAmount?: BigNumber,
) => {
const fill = {
...signedOrderUtils.getOrderAddressesAndValues(signedOrder),
- fillTakerTokenAmount: fillTakerTokenAmount || signedOrder.takerTokenAmount,
- shouldThrowOnInsufficientBalanceOrAllowance: !!shouldThrowOnInsufficientBalanceOrAllowance,
+ takerTokenFillAmount: takerTokenFillAmount || signedOrder.takerTokenAmount,
...signedOrder.ecSignature,
};
return fill;
},
- createCancel(signedOrder: SignedOrder, cancelTakerTokenAmount?: BigNumber) {
+ createCancel(signedOrder: SignedOrder, takerTokenCancelAmount?: BigNumber) {
const cancel = {
...signedOrderUtils.getOrderAddressesAndValues(signedOrder),
- cancelTakerTokenAmount: cancelTakerTokenAmount || signedOrder.takerTokenAmount,
+ takerTokenCancelAmount: takerTokenCancelAmount || signedOrder.takerTokenAmount,
};
return cancel;
},
diff --git a/packages/contracts/util/types.ts b/packages/contracts/util/types.ts
index 321084c42..a06e99532 100644
--- a/packages/contracts/util/types.ts
+++ b/packages/contracts/util/types.ts
@@ -14,18 +14,16 @@ export interface SubmissionContractEventArgs {
export interface BatchFillOrders {
orderAddresses: string[][];
orderValues: BigNumber[][];
- fillTakerTokenAmounts: BigNumber[];
- shouldThrowOnInsufficientBalanceOrAllowance: boolean;
+ takerTokenFillAmounts: BigNumber[];
v: number[];
r: string[];
s: string[];
}
-export interface FillOrdersUpTo {
+export interface MarketFillOrders {
orderAddresses: string[][];
orderValues: BigNumber[][];
- fillTakerTokenAmount: BigNumber;
- shouldThrowOnInsufficientBalanceOrAllowance: boolean;
+ takerTokenFillAmount: BigNumber;
v: number[];
r: string[];
s: string[];