Wrappers for balance threshold filter + updated some tests to use the wrapper

This commit is contained in:
Greg Hysen 2018-12-06 18:00:53 -08:00
parent 7e7880aea0
commit d882133e44
3 changed files with 450 additions and 84 deletions

View File

@ -6,6 +6,7 @@ import { Web3Wrapper } from '@0x/web3-wrapper';
import * as chai from 'chai'; import * as chai from 'chai';
import * as ethUtil from 'ethereumjs-util'; import * as ethUtil from 'ethereumjs-util';
import * as _ from 'lodash'; import * as _ from 'lodash';
import { TransactionReceiptWithDecodedLogs } from 'ethereum-types';
import { DummyERC20TokenContract } from '../../generated-wrappers/dummy_erc20_token'; import { DummyERC20TokenContract } from '../../generated-wrappers/dummy_erc20_token';
import { ExchangeContract } from '../../generated-wrappers/exchange'; import { ExchangeContract } from '../../generated-wrappers/exchange';
@ -24,6 +25,7 @@ import { ExchangeWrapper } from '../utils/exchange_wrapper';
import { OrderFactory } from '../utils/order_factory'; import { OrderFactory } from '../utils/order_factory';
import { orderUtils } from '../utils/order_utils'; import { orderUtils } from '../utils/order_utils';
import { TransactionFactory } from '../utils/transaction_factory'; import { TransactionFactory } from '../utils/transaction_factory';
import { BalanceThresholdWrapper } from '../utils/balance_threshold_wrapper';
import { ContractName, ERC20BalancesByOwner, SignedTransaction } from '../utils/types'; import { ContractName, ERC20BalancesByOwner, SignedTransaction } from '../utils/types';
import { provider, txDefaults, web3Wrapper } from '../utils/web3_wrapper'; import { provider, txDefaults, web3Wrapper } from '../utils/web3_wrapper';
@ -37,6 +39,10 @@ const expect = chai.expect;
const blockchainLifecycle = new BlockchainLifecycle(web3Wrapper); const blockchainLifecycle = new BlockchainLifecycle(web3Wrapper);
const DECIMALS_DEFAULT = 18; const DECIMALS_DEFAULT = 18;
interface ValidatedAddressesLog {
args: {addresses: string[]}
}
describe.only(ContractName.BalanceThresholdFilter, () => { describe.only(ContractName.BalanceThresholdFilter, () => {
let compliantMakerAddress: string; let compliantMakerAddress: string;
let owner: string; let owner: string;
@ -53,18 +59,35 @@ describe.only(ContractName.BalanceThresholdFilter, () => {
let orderFactory: OrderFactory; let orderFactory: OrderFactory;
let erc20Wrapper: ERC20Wrapper; let erc20Wrapper: ERC20Wrapper;
let erc20Balances: ERC20BalancesByOwner; let erc20Balances: ERC20BalancesByOwner;
let balanceThresholdWrapper: BalanceThresholdWrapper;
let takerTransactionFactory: TransactionFactory; let takerTransactionFactory: TransactionFactory;
let compliantSignedOrder: SignedOrder; let compliantSignedOrder: SignedOrder;
let compliantSignedFillOrderTx: SignedTransaction; let compliantSignedFillOrderTx: SignedTransaction;
let noncompliantSignedFillOrderTx: SignedTransaction; let noncompliantSignedFillOrderTx: SignedTransaction;
let logDecoder: LogDecoder;
const takerAssetAmount = Web3Wrapper.toBaseUnitAmount(new BigNumber(500), DECIMALS_DEFAULT); const takerAssetAmount = Web3Wrapper.toBaseUnitAmount(new BigNumber(500), DECIMALS_DEFAULT);
const makerAssetAmount = Web3Wrapper.toBaseUnitAmount(new BigNumber(1000), DECIMALS_DEFAULT); const makerAssetAmount = Web3Wrapper.toBaseUnitAmount(new BigNumber(1000), DECIMALS_DEFAULT);
const takerAssetFillAmount = Web3Wrapper.toBaseUnitAmount(new BigNumber(250), DECIMALS_DEFAULT); const takerAssetFillAmount = Web3Wrapper.toBaseUnitAmount(new BigNumber(250), DECIMALS_DEFAULT);
let compliantForwarderInstance: BalanceThresholdFilterContract; let compliantForwarderInstance: BalanceThresholdFilterContract;
const assertValidatedAddressesLog = async (txReceipt: TransactionReceiptWithDecodedLogs, expectedValidatedAddresses: string[]) => {
expect(txReceipt.logs.length).to.be.gte(1);
const validatedAddressesLog = (txReceipt.logs[0] as any) as ValidatedAddressesLog;
const validatedAddresses = validatedAddressesLog.args.addresses;
// @HACK-hysz: Nested addresses are not translated to lower-case but this will change once
// the new ABI Encoder/Decoder is used by the contract templates.
let validatedAddressesNormalized: string[] = [];
_.each(validatedAddresses, (address) => {
const normalizedAddress = _.toLower(address);
validatedAddressesNormalized.push(normalizedAddress);
});
expect(validatedAddressesNormalized).to.be.deep.equal(expectedValidatedAddresses);
};
before(async () => { before(async () => {
// Create accounts // Create accounts
await blockchainLifecycle.startAsync(); await blockchainLifecycle.startAsync();
@ -190,17 +213,30 @@ describe.only(ContractName.BalanceThresholdFilter, () => {
compliantSignedOrderWithoutExchangeAddressData, compliantSignedOrderWithoutExchangeAddressData,
); );
/* generate selectors for every exchange method /*
_.each(exchangeInstance.abi, (abiDefinition: AbiDefinition) => { _.each(exchangeInstance.abi, (abiDefinition: AbiDefinition) => {
try { try {
const method = new Method(abiDefinition as MethodAbi); const method = new Method(abiDefinition as MethodAbi);
console.log('\n', `// ${method.getDataItem().name}`); console.log(method.getSignature());
console.log(`bytes4 constant ${method.getDataItem().name}Selector = ${method.getSelector()};`); if (!method.getSignature().startsWith('matchOrders')) {
console.log(`bytes4 constant ${method.getDataItem().name}SelectorGenerator = byes4(keccak256('${method.getSignature()}'));`); return;
}
console.log(`FOUND IT`);
const signedOrderWithoutExchangeAddress = orderUtils.getOrderWithoutExchangeAddress(
compliantSignedOrder,
);
const args = [signedOrderWithoutExchangeAddress, signedOrderWithoutExchangeAddress, compliantSignedOrder.signature, compliantSignedOrder.signature];
console.log(method.encode(args, {annotate: true}));
//console.log('\n', `// ${method.getDataItem().name}`);
//console.log(`bytes4 constant ${method.getDataItem().name}Selector = ${method.getSelector()};`);
//console.log(`bytes4 constant ${method.getDataItem().name}SelectorGenerator = byes4(keccak256('${method.getSignature()}'));`);
} catch(e) { } catch(e) {
_.noop(); console.log(`encoding failed: ${e}`);
} }
});*/ });
throw new Error(`w`);*/
logDecoder = new LogDecoder(web3Wrapper);
balanceThresholdWrapper = new BalanceThresholdWrapper(compliantForwarderInstance, exchangeInstance, new TransactionFactory(takerPrivateKey, exchangeInstance.address), provider);
}); });
beforeEach(async () => { beforeEach(async () => {
await blockchainLifecycle.startAsync(); await blockchainLifecycle.startAsync();
@ -208,54 +244,9 @@ describe.only(ContractName.BalanceThresholdFilter, () => {
afterEach(async () => { afterEach(async () => {
await blockchainLifecycle.revertAsync(); await blockchainLifecycle.revertAsync();
}); });
describe.only('fillOrder', () => {
beforeEach(async () => { describe('General Sanity Checks', () => {
erc20Balances = await erc20Wrapper.getBalancesAsync(); it('should revert if the signed transaction is not intended for supported', async () => {
});
it('should transfer the correct amounts when maker and taker are compliant', async () => {
const txHash = await compliantForwarderInstance.executeTransaction.sendTransactionAsync(
compliantSignedFillOrderTx.salt,
compliantSignedFillOrderTx.signerAddress,
compliantSignedFillOrderTx.data,
compliantSignedFillOrderTx.signature,
);
const decoder = new LogDecoder(web3Wrapper);
const tx = await decoder.getTxWithDecodedLogsAsync(txHash);
console.log(JSON.stringify(tx, null, 4));
console.log('****** MAKER ADDRESS = ', compliantSignedOrder.makerAddress);
const newBalances = await erc20Wrapper.getBalancesAsync();
const makerAssetFillAmount = takerAssetFillAmount
.times(compliantSignedOrder.makerAssetAmount)
.dividedToIntegerBy(compliantSignedOrder.takerAssetAmount);
const makerFeePaid = compliantSignedOrder.makerFee
.times(makerAssetFillAmount)
.dividedToIntegerBy(compliantSignedOrder.makerAssetAmount);
const takerFeePaid = compliantSignedOrder.takerFee
.times(makerAssetFillAmount)
.dividedToIntegerBy(compliantSignedOrder.makerAssetAmount);
expect(newBalances[compliantMakerAddress][defaultMakerAssetAddress]).to.be.bignumber.equal(
erc20Balances[compliantMakerAddress][defaultMakerAssetAddress].minus(makerAssetFillAmount),
);
expect(newBalances[compliantMakerAddress][defaultTakerAssetAddress]).to.be.bignumber.equal(
erc20Balances[compliantMakerAddress][defaultTakerAssetAddress].add(takerAssetFillAmount),
);
expect(newBalances[compliantMakerAddress][zrxToken.address]).to.be.bignumber.equal(
erc20Balances[compliantMakerAddress][zrxToken.address].minus(makerFeePaid),
);
expect(newBalances[compliantTakerAddress][defaultTakerAssetAddress]).to.be.bignumber.equal(
erc20Balances[compliantTakerAddress][defaultTakerAssetAddress].minus(takerAssetFillAmount),
);
expect(newBalances[compliantTakerAddress][defaultMakerAssetAddress]).to.be.bignumber.equal(
erc20Balances[compliantTakerAddress][defaultMakerAssetAddress].add(makerAssetFillAmount),
);
expect(newBalances[compliantTakerAddress][zrxToken.address]).to.be.bignumber.equal(
erc20Balances[compliantTakerAddress][zrxToken.address].minus(takerFeePaid),
);
expect(newBalances[feeRecipientAddress][zrxToken.address]).to.be.bignumber.equal(
erc20Balances[feeRecipientAddress][zrxToken.address].add(makerFeePaid.add(takerFeePaid)),
);
});
it('should revert if the signed transaction is not intended for fillOrder', async () => {
// Create signed order without the fillOrder function selector // Create signed order without the fillOrder function selector
const txDataBuf = ethUtil.toBuffer(compliantSignedFillOrderTx.data); const txDataBuf = ethUtil.toBuffer(compliantSignedFillOrderTx.data);
const selectorLengthInBytes = 4; const selectorLengthInBytes = 4;
@ -297,18 +288,90 @@ describe.only(ContractName.BalanceThresholdFilter, () => {
signedFillOrderTx.signature, signedFillOrderTx.signature,
)); ));
}); });
it('should revert if taker address is not compliant (does not hold a Yes Token)', async () => { // @TODO - greater than 1 balance
return expectTransactionFailedAsync( });
compliantForwarderInstance.executeTransaction.sendTransactionAsync(
compliantSignedFillOrderTx.salt,
nonCompliantAddress,
compliantSignedFillOrderTx.data, describe('batchFillOrders', () => {
compliantSignedFillOrderTx.signature, beforeEach(async () => {
), erc20Balances = await erc20Wrapper.getBalancesAsync();
RevertReason.AtLeastOneAddressDoesNotMeetBalanceThreshold });
it('should transfer the correct amounts when maker and taker are compliant', async () => {
let order2 = _.cloneDeep(compliantSignedOrder);
order2.makerAddress = `0x${_.reverse(compliantSignedOrder.makerAddress.slice(2).split('')).join('')}`;
const orders = [compliantSignedOrder, order2];
const fillAmounts = [new BigNumber(4), new BigNumber(4)];
const signatures = ["0xabcd", "0xabcd"];
const exchangeCalldata = exchangeInstance.batchFillOrders.getABIEncodedTransactionData(orders, fillAmounts, signatures);
console.log('*'.repeat(40), exchangeCalldata, '*'.repeat(40));
console.log('****** MAKER ADDRESS = ', compliantSignedOrder.makerAddress);
const txHash = await compliantForwarderInstance.executeTransaction.sendTransactionAsync(
compliantSignedFillOrderTx.salt,
compliantSignedFillOrderTx.signerAddress,
exchangeCalldata,
compliantSignedFillOrderTx.signature,
);
const decoder = new LogDecoder(web3Wrapper);
const tx = await decoder.getTxWithDecodedLogsAsync(txHash);
console.log(JSON.stringify(tx, null, 4));
});
});
describe('batchFillOrdersNoThrow', () => {
});
describe('batchFillOrKillOrders', () => {
});
describe('batchFillOrKillOrders', () => {
});
describe.only('fillOrder', () => {
beforeEach(async () => {
erc20Balances = await erc20Wrapper.getBalancesAsync();
});
it('should transfer the correct amounts and validate both maker/taker when both maker and taker meet the balance threshold', async () => {
// Execute a valid fill
const txReceipt = await balanceThresholdWrapper.fillOrderAsync(compliantSignedOrder, compliantSignedFillOrderTx.signerAddress, {takerAssetFillAmount});
// Assert validated addresses
const expectedValidatedAddresseses = [compliantSignedOrder.makerAddress, compliantSignedFillOrderTx.signerAddress];
assertValidatedAddressesLog(txReceipt, expectedValidatedAddresseses);
// Check balances
const newBalances = await erc20Wrapper.getBalancesAsync();
const makerAssetFillAmount = takerAssetFillAmount
.times(compliantSignedOrder.makerAssetAmount)
.dividedToIntegerBy(compliantSignedOrder.takerAssetAmount);
const makerFeePaid = compliantSignedOrder.makerFee
.times(makerAssetFillAmount)
.dividedToIntegerBy(compliantSignedOrder.makerAssetAmount);
const takerFeePaid = compliantSignedOrder.takerFee
.times(makerAssetFillAmount)
.dividedToIntegerBy(compliantSignedOrder.makerAssetAmount);
expect(newBalances[compliantMakerAddress][defaultMakerAssetAddress]).to.be.bignumber.equal(
erc20Balances[compliantMakerAddress][defaultMakerAssetAddress].minus(makerAssetFillAmount),
);
expect(newBalances[compliantMakerAddress][defaultTakerAssetAddress]).to.be.bignumber.equal(
erc20Balances[compliantMakerAddress][defaultTakerAssetAddress].add(takerAssetFillAmount),
);
expect(newBalances[compliantMakerAddress][zrxToken.address]).to.be.bignumber.equal(
erc20Balances[compliantMakerAddress][zrxToken.address].minus(makerFeePaid),
);
expect(newBalances[compliantTakerAddress][defaultTakerAssetAddress]).to.be.bignumber.equal(
erc20Balances[compliantTakerAddress][defaultTakerAssetAddress].minus(takerAssetFillAmount),
);
expect(newBalances[compliantTakerAddress][defaultMakerAssetAddress]).to.be.bignumber.equal(
erc20Balances[compliantTakerAddress][defaultMakerAssetAddress].add(makerAssetFillAmount),
);
expect(newBalances[compliantTakerAddress][zrxToken.address]).to.be.bignumber.equal(
erc20Balances[compliantTakerAddress][zrxToken.address].minus(takerFeePaid),
);
expect(newBalances[feeRecipientAddress][zrxToken.address]).to.be.bignumber.equal(
erc20Balances[feeRecipientAddress][zrxToken.address].add(makerFeePaid.add(takerFeePaid)),
); );
}); });
it('should revert if maker address is not compliant (does not hold a Yes Token)', async () => { it('should revert if maker does not meet the balance threshold', async () => {
// Create signed order with non-compliant maker address // Create signed order with non-compliant maker address
const signedOrderWithBadMakerAddress = await orderFactory.newSignedOrderAsync({ const signedOrderWithBadMakerAddress = await orderFactory.newSignedOrderAsync({
senderAddress: compliantForwarderInstance.address, senderAddress: compliantForwarderInstance.address,
@ -336,32 +399,92 @@ describe.only(ContractName.BalanceThresholdFilter, () => {
RevertReason.AtLeastOneAddressDoesNotMeetBalanceThreshold RevertReason.AtLeastOneAddressDoesNotMeetBalanceThreshold
); );
}); });
it('should revert if taker does not meet the balance threshold', async () => {
return expectTransactionFailedAsync(
compliantForwarderInstance.executeTransaction.sendTransactionAsync(
compliantSignedFillOrderTx.salt,
nonCompliantAddress,
compliantSignedFillOrderTx.data,
compliantSignedFillOrderTx.signature,
),
RevertReason.AtLeastOneAddressDoesNotMeetBalanceThreshold
);
});
}); });
describe('batchFillOrders', () => { describe('fillOrderNoThrow', () => {
beforeEach(async () => { beforeEach(async () => {
erc20Balances = await erc20Wrapper.getBalancesAsync(); erc20Balances = await erc20Wrapper.getBalancesAsync();
}); });
it('should transfer the correct amounts when maker and taker are compliant', async () => { it('should transfer the correct amounts and validate both maker/taker when both maker and taker meet the balance threshold', async () => {
let order2 = _.cloneDeep(compliantSignedOrder);
order2.makerAddress = `0x${_.reverse(compliantSignedOrder.makerAddress.slice(2).split('')).join('')}`;
const orders = [compliantSignedOrder, order2];
const fillAmounts = [new BigNumber(4), new BigNumber(4)];
const signatures = ["0xabcd", "0xabcd"];
const exchangeCalldata = exchangeInstance.batchFillOrders.getABIEncodedTransactionData(orders, fillAmounts, signatures);
console.log('*'.repeat(40), exchangeCalldata, '*'.repeat(40));
console.log('****** MAKER ADDRESS = ', compliantSignedOrder.makerAddress);
const txHash = await compliantForwarderInstance.executeTransaction.sendTransactionAsync(
compliantSignedFillOrderTx.salt,
compliantSignedFillOrderTx.signerAddress,
exchangeCalldata,
compliantSignedFillOrderTx.signature,
);
const decoder = new LogDecoder(web3Wrapper);
const tx = await decoder.getTxWithDecodedLogsAsync(txHash);
console.log(JSON.stringify(tx, null, 4));
}); });
it('should revert if maker does not meet the balance threshold', async () => {
// Create signed order with non-compliant maker address
const signedOrderWithBadMakerAddress = await orderFactory.newSignedOrderAsync({
senderAddress: compliantForwarderInstance.address,
makerAddress: nonCompliantAddress
});
const signedOrderWithoutExchangeAddress = orderUtils.getOrderWithoutExchangeAddress(
signedOrderWithBadMakerAddress,
);
const signedOrderWithoutExchangeAddressData = exchangeInstance.fillOrder.getABIEncodedTransactionData(
signedOrderWithoutExchangeAddress,
takerAssetFillAmount,
compliantSignedOrder.signature,
);
const signedFillOrderTx = takerTransactionFactory.newSignedTransaction(
signedOrderWithoutExchangeAddressData,
);
// Call compliant forwarder
return expectTransactionFailedAsync(
compliantForwarderInstance.executeTransaction.sendTransactionAsync(
signedFillOrderTx.salt,
signedFillOrderTx.signerAddress,
signedFillOrderTx.data,
signedFillOrderTx.signature,
),
RevertReason.AtLeastOneAddressDoesNotMeetBalanceThreshold
);
});
it('should revert if taker does not meet the balance threshold', async () => {
return expectTransactionFailedAsync(
compliantForwarderInstance.executeTransaction.sendTransactionAsync(
compliantSignedFillOrderTx.salt,
nonCompliantAddress,
compliantSignedFillOrderTx.data,
compliantSignedFillOrderTx.signature,
),
RevertReason.AtLeastOneAddressDoesNotMeetBalanceThreshold
);
});
});
describe('fillOrKillOrder', () => {
});
describe('marketBuyOrders', () => {
});
describe('marketBuyOrdersNoThrow', () => {
});
describe('marketSellOrders', () => {
});
describe('marketSellOrdersNoThrow', () => {
});
describe('matchOrders', () => {
});
describe('cancelOrder', () => {
});
describe('batchCancelOrders', () => {
});
describe('cancelOrdersUpTo', () => {
}); });
}); });
// tslint:disable:max-file-line-count // tslint:disable:max-file-line-count

View File

@ -0,0 +1,243 @@
import { SignedOrder } from '@0x/types';
import { BigNumber } from '@0x/utils';
import { Web3Wrapper } from '@0x/web3-wrapper';
import { Provider, TransactionReceiptWithDecodedLogs } from 'ethereum-types';
import * as _ from 'lodash';
import { ExchangeContract } from '../../generated-wrappers/exchange';
import { BalanceThresholdFilterContract } from '../../generated-wrappers/balance_threshold_filter';
import { formatters } from './formatters';
import { LogDecoder } from './log_decoder';
import { orderUtils } from './order_utils';
import { TransactionFactory } from '../utils/transaction_factory';
import { OrderInfo } from './types';
export class BalanceThresholdWrapper {
private readonly _balanceThresholdFilter: BalanceThresholdFilterContract;
private readonly _signerTransactionFactory: TransactionFactory;
private readonly _exchange: ExchangeContract;
private readonly _web3Wrapper: Web3Wrapper;
private readonly _logDecoder: LogDecoder;
constructor(balanceThresholdFilter: BalanceThresholdFilterContract, exchangeContract: ExchangeContract, signerTransactionFactory: TransactionFactory, provider: Provider) {
this._balanceThresholdFilter = balanceThresholdFilter;
this._exchange = exchangeContract;
this._signerTransactionFactory = signerTransactionFactory;
this._web3Wrapper = new Web3Wrapper(provider);
this._logDecoder = new LogDecoder(this._web3Wrapper);
}
public async fillOrderAsync(
signedOrder: SignedOrder,
from: string,
opts: { takerAssetFillAmount?: BigNumber } = {},
): Promise<TransactionReceiptWithDecodedLogs> {
const params = orderUtils.createFill(signedOrder, opts.takerAssetFillAmount);
const data = this._exchange.fillOrder.getABIEncodedTransactionData(
params.order,
params.takerAssetFillAmount,
params.signature,
);
const txReceipt = this._executeTransaction(data, from);
return txReceipt;
}
public async fillOrKillOrderAsync(
signedOrder: SignedOrder,
from: string,
opts: { takerAssetFillAmount?: BigNumber } = {},
): Promise<TransactionReceiptWithDecodedLogs> {
const params = orderUtils.createFill(signedOrder, opts.takerAssetFillAmount);
const data = this._exchange.fillOrKillOrder.getABIEncodedTransactionData(
params.order,
params.takerAssetFillAmount,
params.signature,
);
const txReceipt = this._executeTransaction(data, from);
return txReceipt;
}
public async fillOrderNoThrowAsync(
signedOrder: SignedOrder,
from: string,
opts: { takerAssetFillAmount?: BigNumber; gas?: number } = {},
): Promise<TransactionReceiptWithDecodedLogs> {
const params = orderUtils.createFill(signedOrder, opts.takerAssetFillAmount);
const data = this._exchange.fillOrderNoThrow.getABIEncodedTransactionData(
params.order,
params.takerAssetFillAmount,
params.signature,
);
const txReceipt = this._executeTransaction(data, from, opts.gas);
return txReceipt;
}
public async batchFillOrdersAsync(
orders: SignedOrder[],
from: string,
opts: { takerAssetFillAmounts?: BigNumber[] } = {},
): Promise<TransactionReceiptWithDecodedLogs> {
const params = formatters.createBatchFill(orders, opts.takerAssetFillAmounts);
const data = this._exchange.batchFillOrders.getABIEncodedTransactionData(
params.orders,
params.takerAssetFillAmounts,
params.signatures,
);
const txReceipt = this._executeTransaction(data, from);
return txReceipt;
}
public async batchFillOrKillOrdersAsync(
orders: SignedOrder[],
from: string,
opts: { takerAssetFillAmounts?: BigNumber[] } = {},
): Promise<TransactionReceiptWithDecodedLogs> {
const params = formatters.createBatchFill(orders, opts.takerAssetFillAmounts);
const data = this._exchange.batchFillOrKillOrders.getABIEncodedTransactionData(
params.orders,
params.takerAssetFillAmounts,
params.signatures,
);
const txReceipt = this._executeTransaction(data, from);
return txReceipt;
}
public async batchFillOrdersNoThrowAsync(
orders: SignedOrder[],
from: string,
opts: { takerAssetFillAmounts?: BigNumber[]; gas?: number } = {},
): Promise<TransactionReceiptWithDecodedLogs> {
const params = formatters.createBatchFill(orders, opts.takerAssetFillAmounts);
const data = this._exchange.batchFillOrKillOrders.getABIEncodedTransactionData(
params.orders,
params.takerAssetFillAmounts,
params.signatures,
);
const txReceipt = this._executeTransaction(data, from, opts.gas);
return txReceipt;
}
public async marketSellOrdersAsync(
orders: SignedOrder[],
from: string,
opts: { takerAssetFillAmount: BigNumber },
): Promise<TransactionReceiptWithDecodedLogs> {
const params = formatters.createMarketSellOrders(orders, opts.takerAssetFillAmount);
const data = this._exchange.marketSellOrders.getABIEncodedTransactionData(
params.orders,
params.takerAssetFillAmount,
params.signatures,
);
const txReceipt = this._executeTransaction(data, from);
return txReceipt;
}
public async marketSellOrdersNoThrowAsync(
orders: SignedOrder[],
from: string,
opts: { takerAssetFillAmount: BigNumber; gas?: number },
): Promise<TransactionReceiptWithDecodedLogs> {
const params = formatters.createMarketSellOrders(orders, opts.takerAssetFillAmount);
const data = this._exchange.marketSellOrdersNoThrow.getABIEncodedTransactionData(
params.orders,
params.takerAssetFillAmount,
params.signatures,
);
const txReceipt = this._executeTransaction(data, from, opts.gas);
return txReceipt;
}
public async marketBuyOrdersAsync(
orders: SignedOrder[],
from: string,
opts: { makerAssetFillAmount: BigNumber },
): Promise<TransactionReceiptWithDecodedLogs> {
const params = formatters.createMarketBuyOrders(orders, opts.makerAssetFillAmount);
const data = this._exchange.marketBuyOrders.getABIEncodedTransactionData(
params.orders,
params.makerAssetFillAmount,
params.signatures,
);
const txReceipt = this._executeTransaction(data, from);
return txReceipt;
}
public async marketBuyOrdersNoThrowAsync(
orders: SignedOrder[],
from: string,
opts: { makerAssetFillAmount: BigNumber; gas?: number },
): Promise<TransactionReceiptWithDecodedLogs> {
const params = formatters.createMarketBuyOrders(orders, opts.makerAssetFillAmount);
const data = this._exchange.marketBuyOrdersNoThrow.getABIEncodedTransactionData(
params.orders,
params.makerAssetFillAmount,
params.signatures,
);
const txReceipt = this._executeTransaction(data, from, opts.gas);
return txReceipt;
}
public async cancelOrderAsync(signedOrder: SignedOrder, from: string): Promise<TransactionReceiptWithDecodedLogs> {
const params = orderUtils.createCancel(signedOrder);
const data = this._exchange.cancelOrder.getABIEncodedTransactionData(params.order);
const txReceipt = this._executeTransaction(data, from);
return txReceipt;
}
public async batchCancelOrdersAsync(
orders: SignedOrder[],
from: string,
): Promise<TransactionReceiptWithDecodedLogs> {
const params = formatters.createBatchCancel(orders);
const data = this._exchange.batchCancelOrders.getABIEncodedTransactionData(params.orders);
const txReceipt = this._executeTransaction(data, from);
return txReceipt;
}
public async cancelOrdersUpToAsync(salt: BigNumber, from: string): Promise<TransactionReceiptWithDecodedLogs> {
const data = this._exchange.cancelOrdersUpTo.getABIEncodedTransactionData(salt);
const txReceipt = this._executeTransaction(data, from);
return txReceipt;
}
public async getTakerAssetFilledAmountAsync(orderHashHex: string): Promise<BigNumber> {
const filledAmount = await this._exchange.filled.callAsync(orderHashHex);
return filledAmount;
}
public async isCancelledAsync(orderHashHex: string): Promise<boolean> {
const isCancelled = await this._exchange.cancelled.callAsync(orderHashHex);
return isCancelled;
}
public async getOrderEpochAsync(makerAddress: string, senderAddress: string): Promise<BigNumber> {
const orderEpoch = await this._exchange.orderEpoch.callAsync(makerAddress, senderAddress);
return orderEpoch;
}
public async getOrderInfoAsync(signedOrder: SignedOrder): Promise<OrderInfo> {
const orderInfo = (await this._exchange.getOrderInfo.callAsync(signedOrder)) as OrderInfo;
return orderInfo;
}
public async getOrdersInfoAsync(signedOrders: SignedOrder[]): Promise<OrderInfo[]> {
const ordersInfo = (await this._exchange.getOrdersInfo.callAsync(signedOrders)) as OrderInfo[];
return ordersInfo;
}
public async matchOrdersAsync(
signedOrderLeft: SignedOrder,
signedOrderRight: SignedOrder,
from: string,
): Promise<TransactionReceiptWithDecodedLogs> {
const params = orderUtils.createMatchOrders(signedOrderLeft, signedOrderRight);
const data = await this._exchange.matchOrders.getABIEncodedTransactionData(
params.left,
params.right,
params.leftSignature,
params.rightSignature
);
const txReceipt = this._executeTransaction(data, from);
return txReceipt;
}
public getBalanceThresholdAddress(): string {
return this._balanceThresholdFilter.address;
}
public getExchangeAddress(): string {
return this._exchange.address;
}
private async _executeTransaction(abiEncodedExchangeTxData: string, from: string, gas?: number): Promise<TransactionReceiptWithDecodedLogs> {
const signedExchangeTx = this._signerTransactionFactory.newSignedTransaction(abiEncodedExchangeTxData);
const txOpts = _.isUndefined(gas) ? {from} : {from, gas};
const txHash = await this._balanceThresholdFilter.executeTransaction.sendTransactionAsync(
signedExchangeTx.salt,
signedExchangeTx.signerAddress,
signedExchangeTx.data,
signedExchangeTx.signature,
txOpts,
);
const txReceipt = await this._logDecoder.getTxWithDecodedLogsAsync(txHash);
return txReceipt;
}
}