diff options
author | Fabio Berger <me@fabioberger.com> | 2018-08-19 03:23:16 +0800 |
---|---|---|
committer | GitHub <noreply@github.com> | 2018-08-19 03:23:16 +0800 |
commit | fae58ca69597a69ef8b27e3398fb7c8a60392eef (patch) | |
tree | 5c686d61e9cf48cef54e04dd7cde1d74a1becef9 /packages | |
parent | ddf85112d7e4eb1581e0d82ce6eedad429641106 (diff) | |
parent | 1c68057999ad9cb8be5018bffeeb6c1e45e645ad (diff) | |
download | dexon-0x-contracts-fae58ca69597a69ef8b27e3398fb7c8a60392eef.tar.gz dexon-0x-contracts-fae58ca69597a69ef8b27e3398fb7c8a60392eef.tar.zst dexon-0x-contracts-fae58ca69597a69ef8b27e3398fb7c8a60392eef.zip |
Merge pull request #975 from 0xProject/feature/contract-wrappers/executeTransaction
[Contract-wrappers] Exchange execute transaction encoder
Diffstat (limited to 'packages')
4 files changed, 524 insertions, 0 deletions
diff --git a/packages/contract-wrappers/CHANGELOG.json b/packages/contract-wrappers/CHANGELOG.json index fdf779338..d50043b0d 100644 --- a/packages/contract-wrappers/CHANGELOG.json +++ b/packages/contract-wrappers/CHANGELOG.json @@ -1,5 +1,14 @@ [ { + "version": "1.0.1-rc.4", + "changes": [ + { + "pr": 975, + "note": "Added Transaction Encoder for use with 0x Exchange executeTransaction" + } + ] + }, + { "version": "1.0.1-rc.3", "changes": [ { diff --git a/packages/contract-wrappers/src/contract_wrappers/exchange_wrapper.ts b/packages/contract-wrappers/src/contract_wrappers/exchange_wrapper.ts index 48bd00f90..5a4b40547 100644 --- a/packages/contract-wrappers/src/contract_wrappers/exchange_wrapper.ts +++ b/packages/contract-wrappers/src/contract_wrappers/exchange_wrapper.ts @@ -21,6 +21,7 @@ import { } from '../types'; import { assert } from '../utils/assert'; import { decorators } from '../utils/decorators'; +import { TransactionEncoder } from '../utils/transaction_encoder'; import { ContractWrapper } from './contract_wrapper'; import { ExchangeContract, ExchangeEventArgs, ExchangeEvents } from './generated/exchange'; @@ -1097,6 +1098,16 @@ export class ExchangeWrapper extends ContractWrapper { const zrxAssetData = assetDataUtils.encodeERC20AssetData(zrxTokenAddress); return zrxAssetData; } + /** + * Returns a Transaction Encoder. Transaction messages exist for the purpose of calling methods on the Exchange contract + * in the context of another address. + * @return TransactionEncoder + */ + public async transactionEncoderAsync(): Promise<TransactionEncoder> { + const exchangeInstance = await this._getExchangeContractAsync(); + const encoder = new TransactionEncoder(exchangeInstance); + return encoder; + } // tslint:disable:no-unused-variable private _invalidateContractInstances(): void { this.unsubscribeAll(); diff --git a/packages/contract-wrappers/src/utils/transaction_encoder.ts b/packages/contract-wrappers/src/utils/transaction_encoder.ts new file mode 100644 index 000000000..5c2a94b74 --- /dev/null +++ b/packages/contract-wrappers/src/utils/transaction_encoder.ts @@ -0,0 +1,293 @@ +import { schemas } from '@0xproject/json-schemas'; +import { EIP712Schema, EIP712Types, EIP712Utils } from '@0xproject/order-utils'; +import { Order, SignedOrder } from '@0xproject/types'; +import { BigNumber } from '@0xproject/utils'; +import _ = require('lodash'); + +import { ExchangeContract } from '../contract_wrappers/generated/exchange'; + +import { assert } from './assert'; + +const EIP712_ZEROEX_TRANSACTION_SCHEMA: EIP712Schema = { + name: 'ZeroExTransaction', + parameters: [ + { name: 'salt', type: EIP712Types.Uint256 }, + { name: 'signerAddress', type: EIP712Types.Address }, + { name: 'data', type: EIP712Types.Bytes }, + ], +}; + +/** + * Transaction Encoder. Transaction messages exist for the purpose of calling methods on the Exchange contract + * in the context of another address. For example, UserA can encode and sign a fillOrder transaction and UserB + * can submit this to the blockchain. The Exchange context executes as if UserA had directly submitted this transaction. + */ +export class TransactionEncoder { + private _exchangeInstance: ExchangeContract; + constructor(exchangeInstance: ExchangeContract) { + this._exchangeInstance = exchangeInstance; + } + /** + * Encodes the transaction data for use with the Exchange contract. + * @param data The ABI Encoded 0x Exchange method. I.e fillOrder + * @param salt A random value to provide uniqueness and prevent replay attacks. + * @param signerAddress The address which will sign this transaction. + * @return An unsigned hex encoded transaction for use in 0x Exchange executeTransaction. + */ + public getTransactionHex(data: string, salt: BigNumber, signerAddress: string): string { + const exchangeAddress = this._getExchangeContract().address; + const executeTransactionData = { + salt, + signerAddress, + data, + }; + const executeTransactionHashBuff = EIP712Utils.structHash( + EIP712_ZEROEX_TRANSACTION_SCHEMA, + executeTransactionData, + ); + const eip721MessageBuffer = EIP712Utils.createEIP712Message(executeTransactionHashBuff, exchangeAddress); + const messageHex = `0x${eip721MessageBuffer.toString('hex')}`; + return messageHex; + } + /** + * Encodes a fillOrder transaction. + * @param signedOrder An object that conforms to the SignedOrder interface. + * @param takerAssetFillAmount The amount of the order (in taker asset baseUnits) that you wish to fill. + * @return Hex encoded abi of the function call. + */ + public fillOrderTx(signedOrder: SignedOrder, takerAssetFillAmount: BigNumber): string { + assert.doesConformToSchema('signedOrder', signedOrder, schemas.signedOrderSchema); + assert.isValidBaseUnitAmount('takerAssetFillAmount', takerAssetFillAmount); + const abiEncodedData = this._getExchangeContract().fillOrder.getABIEncodedTransactionData( + signedOrder, + takerAssetFillAmount, + signedOrder.signature, + ); + return abiEncodedData; + } + /** + * Encodes a fillOrderNoThrow transaction. + * @param signedOrder An object that conforms to the SignedOrder interface. + * @param takerAssetFillAmount The amount of the order (in taker asset baseUnits) that you wish to fill. + * @return Hex encoded abi of the function call. + */ + public fillOrderNoThrowTx(signedOrder: SignedOrder, takerAssetFillAmount: BigNumber): string { + assert.doesConformToSchema('signedOrder', signedOrder, schemas.signedOrderSchema); + assert.isValidBaseUnitAmount('takerAssetFillAmount', takerAssetFillAmount); + const abiEncodedData = this._getExchangeContract().fillOrderNoThrow.getABIEncodedTransactionData( + signedOrder, + takerAssetFillAmount, + signedOrder.signature, + ); + return abiEncodedData; + } + /** + * Encodes a fillOrKillOrder transaction. + * @param signedOrder An object that conforms to the SignedOrder interface. + * @param takerAssetFillAmount The amount of the order (in taker asset baseUnits) that you wish to fill. + * @return Hex encoded abi of the function call. + */ + public fillOrKillOrderTx(signedOrder: SignedOrder, takerAssetFillAmount: BigNumber): string { + assert.doesConformToSchema('signedOrder', signedOrder, schemas.signedOrderSchema); + assert.isValidBaseUnitAmount('takerAssetFillAmount', takerAssetFillAmount); + const abiEncodedData = this._getExchangeContract().fillOrKillOrder.getABIEncodedTransactionData( + signedOrder, + takerAssetFillAmount, + signedOrder.signature, + ); + return abiEncodedData; + } + /** + * Encodes a batchFillOrders transaction. + * @param signedOrders An array of signed orders to fill. + * @param takerAssetFillAmounts The amounts of the orders (in taker asset baseUnits) that you wish to fill. + * @return Hex encoded abi of the function call. + */ + public batchFillOrdersTx(signedOrders: SignedOrder[], takerAssetFillAmounts: BigNumber[]): string { + assert.doesConformToSchema('signedOrders', signedOrders, schemas.signedOrdersSchema); + _.forEach(takerAssetFillAmounts, takerAssetFillAmount => + assert.isBigNumber('takerAssetFillAmount', takerAssetFillAmount), + ); + const signatures = _.map(signedOrders, signedOrder => signedOrder.signature); + const abiEncodedData = this._getExchangeContract().batchFillOrders.getABIEncodedTransactionData( + signedOrders, + takerAssetFillAmounts, + signatures, + ); + return abiEncodedData; + } + /** + * Encodes a batchFillOrKillOrders transaction. + * @param signedOrders An array of signed orders to fill. + * @param takerAssetFillAmounts The amounts of the orders (in taker asset baseUnits) that you wish to fill. + * @return Hex encoded abi of the function call. + */ + public batchFillOrKillOrdersTx(signedOrders: SignedOrder[], takerAssetFillAmounts: BigNumber[]): string { + assert.doesConformToSchema('signedOrders', signedOrders, schemas.signedOrdersSchema); + _.forEach(takerAssetFillAmounts, takerAssetFillAmount => + assert.isBigNumber('takerAssetFillAmount', takerAssetFillAmount), + ); + const signatures = _.map(signedOrders, signedOrder => signedOrder.signature); + const abiEncodedData = this._getExchangeContract().batchFillOrKillOrders.getABIEncodedTransactionData( + signedOrders, + takerAssetFillAmounts, + signatures, + ); + return abiEncodedData; + } + /** + * Encodes a batchFillOrdersNoThrow transaction. + * @param signedOrders An array of signed orders to fill. + * @param takerAssetFillAmounts The amounts of the orders (in taker asset baseUnits) that you wish to fill. + * @return Hex encoded abi of the function call. + */ + public batchFillOrdersNoThrowTx(signedOrders: SignedOrder[], takerAssetFillAmounts: BigNumber[]): string { + assert.doesConformToSchema('signedOrders', signedOrders, schemas.signedOrdersSchema); + _.forEach(takerAssetFillAmounts, takerAssetFillAmount => + assert.isBigNumber('takerAssetFillAmount', takerAssetFillAmount), + ); + const signatures = _.map(signedOrders, signedOrder => signedOrder.signature); + const abiEncodedData = this._getExchangeContract().batchFillOrdersNoThrow.getABIEncodedTransactionData( + signedOrders, + takerAssetFillAmounts, + signatures, + ); + return abiEncodedData; + } + /** + * Encodes a batchCancelOrders transaction. + * @param signedOrders An array of orders to cancel. + * @return Hex encoded abi of the function call. + */ + public batchCancelOrdersTx(signedOrders: SignedOrder[]): string { + assert.doesConformToSchema('signedOrders', signedOrders, schemas.signedOrdersSchema); + const abiEncodedData = this._getExchangeContract().batchCancelOrders.getABIEncodedTransactionData(signedOrders); + return abiEncodedData; + } + /** + * Encodes a cancelOrdersUpTo transaction. + * @param targetOrderEpoch Target order epoch. + * @return Hex encoded abi of the function call. + */ + public cancelOrdersUpToTx(targetOrderEpoch: BigNumber): string { + assert.isBigNumber('targetOrderEpoch', targetOrderEpoch); + const abiEncodedData = this._getExchangeContract().cancelOrdersUpTo.getABIEncodedTransactionData( + targetOrderEpoch, + ); + return abiEncodedData; + } + /** + * Encodes a cancelOrder transaction. + * @param order An object that conforms to the Order or SignedOrder interface. The order you would like to cancel. + * @return Hex encoded abi of the function call. + */ + public cancelOrderTx(order: Order | SignedOrder): string { + assert.doesConformToSchema('order', order, schemas.orderSchema); + const abiEncodedData = this._getExchangeContract().cancelOrder.getABIEncodedTransactionData(order); + return abiEncodedData; + } + /** + * Encodes a marketSellOrders transaction. + * @param signedOrders An array of signed orders to fill. + * @param takerAssetFillAmount Taker asset fill amount. + * @return Hex encoded abi of the function call. + */ + public marketSellOrdersTx(signedOrders: SignedOrder[], takerAssetFillAmount: BigNumber): string { + assert.doesConformToSchema('signedOrders', signedOrders, schemas.signedOrdersSchema); + assert.isBigNumber('takerAssetFillAmount', takerAssetFillAmount); + const signatures = _.map(signedOrders, signedOrder => signedOrder.signature); + const abiEncodedData = this._getExchangeContract().marketSellOrders.getABIEncodedTransactionData( + signedOrders, + takerAssetFillAmount, + signatures, + ); + return abiEncodedData; + } + /** + * Encodes a marketSellOrdersNoThrow transaction. + * @param signedOrders An array of signed orders to fill. + * @param takerAssetFillAmount Taker asset fill amount. + * @return Hex encoded abi of the function call. + */ + public marketSellOrdersNoThrowTx(signedOrders: SignedOrder[], takerAssetFillAmount: BigNumber): string { + assert.doesConformToSchema('signedOrders', signedOrders, schemas.signedOrdersSchema); + assert.isBigNumber('takerAssetFillAmount', takerAssetFillAmount); + const signatures = _.map(signedOrders, signedOrder => signedOrder.signature); + const abiEncodedData = this._getExchangeContract().marketSellOrdersNoThrow.getABIEncodedTransactionData( + signedOrders, + takerAssetFillAmount, + signatures, + ); + return abiEncodedData; + } + /** + * Encodes a maketBuyOrders transaction. + * @param signedOrders An array of signed orders to fill. + * @param makerAssetFillAmount Maker asset fill amount. + * @return Hex encoded abi of the function call. + */ + public marketBuyOrdersTx(signedOrders: SignedOrder[], makerAssetFillAmount: BigNumber): string { + assert.doesConformToSchema('signedOrders', signedOrders, schemas.signedOrdersSchema); + assert.isBigNumber('makerAssetFillAmount', makerAssetFillAmount); + const signatures = _.map(signedOrders, signedOrder => signedOrder.signature); + const abiEncodedData = this._getExchangeContract().marketBuyOrders.getABIEncodedTransactionData( + signedOrders, + makerAssetFillAmount, + signatures, + ); + return abiEncodedData; + } + /** + * Encodes a maketBuyOrdersNoThrow transaction. + * @param signedOrders An array of signed orders to fill. + * @param makerAssetFillAmount Maker asset fill amount. + * @return Hex encoded abi of the function call. + */ + public marketBuyOrdersNoThrowTx(signedOrders: SignedOrder[], makerAssetFillAmount: BigNumber): string { + assert.doesConformToSchema('signedOrders', signedOrders, schemas.signedOrdersSchema); + assert.isBigNumber('makerAssetFillAmount', makerAssetFillAmount); + const signatures = _.map(signedOrders, signedOrder => signedOrder.signature); + const abiEncodedData = this._getExchangeContract().marketBuyOrdersNoThrow.getABIEncodedTransactionData( + signedOrders, + makerAssetFillAmount, + signatures, + ); + return abiEncodedData; + } + /** + * Encodes a preSign transaction. + * @param hash Hash to pre-sign + * @param signerAddress Address that should have signed the given hash. + * @param signature Proof that the hash has been signed by signer. + * @return Hex encoded abi of the function call. + */ + public preSignTx(hash: string, signerAddress: string, signature: string): string { + assert.isHexString('hash', hash); + assert.isETHAddressHex('signerAddress', signerAddress); + assert.isHexString('signature', signature); + const abiEncodedData = this._getExchangeContract().preSign.getABIEncodedTransactionData( + hash, + signerAddress, + signature, + ); + return abiEncodedData; + } + /** + * Encodes a setSignatureValidatorApproval transaction. + * @param validatorAddress Validator contract address. + * @param isApproved Boolean value to set approval to. + * @return Hex encoded abi of the function call. + */ + public setSignatureValidatorApprovalTx(validatorAddress: string, isApproved: boolean): string { + assert.isETHAddressHex('validatorAddress', validatorAddress); + assert.isBoolean('isApproved', isApproved); + const abiEncodedData = this._getExchangeContract().setSignatureValidatorApproval.getABIEncodedTransactionData( + validatorAddress, + isApproved, + ); + return abiEncodedData; + } + private _getExchangeContract(): ExchangeContract { + return this._exchangeInstance; + } +} diff --git a/packages/contract-wrappers/test/transaction_encoder_test.ts b/packages/contract-wrappers/test/transaction_encoder_test.ts new file mode 100644 index 000000000..10222dbc1 --- /dev/null +++ b/packages/contract-wrappers/test/transaction_encoder_test.ts @@ -0,0 +1,211 @@ +import { BlockchainLifecycle } from '@0xproject/dev-utils'; +import { FillScenarios } from '@0xproject/fill-scenarios'; +import { assetDataUtils, ecSignOrderHashAsync, generatePseudoRandomSalt, orderHashUtils } from '@0xproject/order-utils'; +import { SignedOrder, SignerType } from '@0xproject/types'; +import { BigNumber } from '@0xproject/utils'; +import 'mocha'; + +import { ContractWrappers } from '../src'; +import { TransactionEncoder } from '../src/utils/transaction_encoder'; + +import { constants } from './utils/constants'; +import { tokenUtils } from './utils/token_utils'; +import { provider, web3Wrapper } from './utils/web3_wrapper'; + +const blockchainLifecycle = new BlockchainLifecycle(web3Wrapper); + +describe('TransactionEncoder', () => { + let contractWrappers: ContractWrappers; + let userAddresses: string[]; + let fillScenarios: FillScenarios; + let exchangeContractAddress: string; + let makerTokenAddress: string; + let takerTokenAddress: string; + let coinbase: string; + let makerAddress: string; + let senderAddress: string; + let takerAddress: string; + let makerAssetData: string; + let takerAssetData: string; + let txHash: string; + const fillableAmount = new BigNumber(5); + const takerTokenFillAmount = new BigNumber(5); + let signedOrder: SignedOrder; + const config = { + networkId: constants.TESTRPC_NETWORK_ID, + blockPollingIntervalMs: 0, + }; + before(async () => { + await blockchainLifecycle.startAsync(); + contractWrappers = new ContractWrappers(provider, config); + exchangeContractAddress = contractWrappers.exchange.getContractAddress(); + userAddresses = await web3Wrapper.getAvailableAddressesAsync(); + const zrxTokenAddress = tokenUtils.getProtocolTokenAddress(); + fillScenarios = new FillScenarios( + provider, + userAddresses, + zrxTokenAddress, + exchangeContractAddress, + contractWrappers.erc20Proxy.getContractAddress(), + contractWrappers.erc721Proxy.getContractAddress(), + ); + [coinbase, makerAddress, takerAddress, senderAddress] = userAddresses; + [makerTokenAddress, takerTokenAddress] = tokenUtils.getDummyERC20TokenAddresses(); + [makerAssetData, takerAssetData] = [ + assetDataUtils.encodeERC20AssetData(makerTokenAddress), + assetDataUtils.encodeERC20AssetData(takerTokenAddress), + ]; + signedOrder = await fillScenarios.createFillableSignedOrderAsync( + makerAssetData, + takerAssetData, + makerAddress, + takerAddress, + fillableAmount, + ); + }); + after(async () => { + await blockchainLifecycle.revertAsync(); + }); + beforeEach(async () => { + await blockchainLifecycle.startAsync(); + }); + afterEach(async () => { + await blockchainLifecycle.revertAsync(); + }); + describe('encode and executeTransaction', () => { + const executeTransactionOrThrowAsync = async ( + encoder: TransactionEncoder, + data: string, + signerAddress: string = takerAddress, + ): Promise<void> => { + const salt = generatePseudoRandomSalt(); + const encodedTransaction = encoder.getTransactionHex(data, salt, signerAddress); + const signature = await ecSignOrderHashAsync( + provider, + encodedTransaction, + signerAddress, + SignerType.Default, + ); + txHash = await contractWrappers.exchange.executeTransactionAsync( + salt, + signerAddress, + data, + signature, + senderAddress, + ); + await web3Wrapper.awaitTransactionSuccessAsync(txHash, constants.AWAIT_TRANSACTION_MINED_MS); + }; + describe('#fillOrderTx', () => { + it('should successfully execute the transaction', async () => { + const encoder = await contractWrappers.exchange.transactionEncoderAsync(); + const data = encoder.fillOrderTx(signedOrder, takerTokenFillAmount); + await executeTransactionOrThrowAsync(encoder, data); + }); + }); + describe('#fillOrderNoThrowTx', () => { + it('should successfully execute the transaction', async () => { + const encoder = await contractWrappers.exchange.transactionEncoderAsync(); + const data = encoder.fillOrderNoThrowTx(signedOrder, takerTokenFillAmount); + await executeTransactionOrThrowAsync(encoder, data); + }); + }); + describe('#fillOrKillOrderTx', () => { + it('should successfully execute the transaction', async () => { + const encoder = await contractWrappers.exchange.transactionEncoderAsync(); + const data = encoder.fillOrKillOrderTx(signedOrder, takerTokenFillAmount); + await executeTransactionOrThrowAsync(encoder, data); + }); + }); + describe('#marketSellOrdersTx', () => { + it('should successfully execute the transaction', async () => { + const encoder = await contractWrappers.exchange.transactionEncoderAsync(); + const data = encoder.marketSellOrdersTx([signedOrder], takerTokenFillAmount); + await executeTransactionOrThrowAsync(encoder, data); + }); + }); + describe('#marketSellOrdersNoThrowTx', () => { + it('should successfully execute the transaction', async () => { + const encoder = await contractWrappers.exchange.transactionEncoderAsync(); + const data = encoder.marketSellOrdersNoThrowTx([signedOrder], takerTokenFillAmount); + await executeTransactionOrThrowAsync(encoder, data); + }); + }); + describe('#marketBuyOrdersTx', () => { + it('should successfully execute the transaction', async () => { + const encoder = await contractWrappers.exchange.transactionEncoderAsync(); + const data = encoder.marketBuyOrdersTx([signedOrder], fillableAmount); + await executeTransactionOrThrowAsync(encoder, data); + }); + }); + describe('#marketBuyOrdersNoThrowTx', () => { + it('should successfully execute the transaction', async () => { + const encoder = await contractWrappers.exchange.transactionEncoderAsync(); + const data = encoder.marketBuyOrdersNoThrowTx([signedOrder], fillableAmount); + await executeTransactionOrThrowAsync(encoder, data); + }); + }); + describe('#preSignTx', () => { + it('should successfully execute the transaction', async () => { + const encoder = await contractWrappers.exchange.transactionEncoderAsync(); + const orderHash = orderHashUtils.getOrderHashHex(signedOrder); + const signature = signedOrder.signature; + const data = encoder.preSignTx(orderHash, makerAddress, signature); + await executeTransactionOrThrowAsync(encoder, data); + }); + }); + describe('#setSignatureValidatorApprovalTx', () => { + it('should successfully execute the transaction', async () => { + const encoder = await contractWrappers.exchange.transactionEncoderAsync(); + const isApproved = true; + const data = encoder.setSignatureValidatorApprovalTx(senderAddress, isApproved); + await executeTransactionOrThrowAsync(encoder, data); + }); + }); + describe('#batchFillOrdersTx', () => { + it('should successfully execute the transaction', async () => { + const encoder = await contractWrappers.exchange.transactionEncoderAsync(); + const data = encoder.batchFillOrdersTx([signedOrder], [takerTokenFillAmount]); + await executeTransactionOrThrowAsync(encoder, data); + }); + }); + describe('#batchFillOrKillOrdersTx', () => { + it('should successfully execute the transaction', async () => { + const encoder = await contractWrappers.exchange.transactionEncoderAsync(); + const data = encoder.batchFillOrKillOrdersTx([signedOrder], [takerTokenFillAmount]); + await executeTransactionOrThrowAsync(encoder, data); + }); + }); + describe('#batchFillOrdersNoThrowTx', () => { + it('should successfully execute the transaction', async () => { + const encoder = await contractWrappers.exchange.transactionEncoderAsync(); + const data = encoder.batchFillOrdersNoThrowTx([signedOrder], [takerTokenFillAmount]); + await executeTransactionOrThrowAsync(encoder, data); + }); + }); + describe('#batchCancelOrdersTx', () => { + it('should successfully execute the transaction', async () => { + const encoder = await contractWrappers.exchange.transactionEncoderAsync(); + const data = encoder.batchCancelOrdersTx([signedOrder]); + const signerAddress = makerAddress; + await executeTransactionOrThrowAsync(encoder, data, signerAddress); + }); + }); + describe('#cancelOrderTx', () => { + it('should successfully execute the transaction', async () => { + const encoder = await contractWrappers.exchange.transactionEncoderAsync(); + const data = encoder.cancelOrderTx(signedOrder); + const signerAddress = makerAddress; + await executeTransactionOrThrowAsync(encoder, data, signerAddress); + }); + }); + describe('#cancelOrdersUpToTx', () => { + it('should successfully execute the transaction', async () => { + const encoder = await contractWrappers.exchange.transactionEncoderAsync(); + const targetEpoch = signedOrder.salt; + const data = encoder.cancelOrdersUpToTx(targetEpoch); + const signerAddress = makerAddress; + await executeTransactionOrThrowAsync(encoder, data, signerAddress); + }); + }); + }); +}); |