From a7238d0fdb302d7062f3f63c3119910286f992c5 Mon Sep 17 00:00:00 2001 From: Brandon Millman Date: Wed, 18 Jul 2018 16:21:24 -0700 Subject: Implement initial forwarder wrapper --- packages/contract-wrappers/package.json | 4 +- packages/contract-wrappers/src/artifacts.ts | 2 + .../contract-wrappers/src/contract_wrappers.ts | 7 + .../src/contract_wrappers/forwarder_wrapper.ts | 170 +++++++++++++++++++++ packages/contract-wrappers/src/index.ts | 1 + packages/contract-wrappers/src/types.ts | 2 + packages/contract-wrappers/src/utils/constants.ts | 1 + .../test/forwarder_wrapper_test.ts | 57 +++++++ 8 files changed, 242 insertions(+), 2 deletions(-) create mode 100644 packages/contract-wrappers/src/contract_wrappers/forwarder_wrapper.ts create mode 100644 packages/contract-wrappers/test/forwarder_wrapper_test.ts (limited to 'packages/contract-wrappers') diff --git a/packages/contract-wrappers/package.json b/packages/contract-wrappers/package.json index ed0278caa..f27afaba9 100644 --- a/packages/contract-wrappers/package.json +++ b/packages/contract-wrappers/package.json @@ -14,7 +14,7 @@ "watch_without_deps": "yarn pre_build && tsc -w", "build": "yarn pre_build && tsc && copyfiles -u 3 './lib/src/monorepo_scripts/**/*' ./scripts", "pre_build": "run-s update_artifacts_v2_beta update_artifacts_v2 generate_contract_wrappers copy_artifacts", - "generate_contract_wrappers": "abi-gen --abis 'src/artifacts/@(Exchange|DummyERC20Token|DummyERC721Token|ZRXToken|ERC20Token|ERC721Token|WETH9|ERC20Proxy|ERC721Proxy).json' --template ../contract_templates/contract.handlebars --partials '../contract_templates/partials/**/*.handlebars' --output src/contract_wrappers/generated --backend ethers", + "generate_contract_wrappers": "abi-gen --abis 'src/artifacts/@(Exchange|DummyERC20Token|DummyERC721Token|ZRXToken|ERC20Token|ERC721Token|WETH9|ERC20Proxy|ERC721Proxy|Forwarder).json' --template ../contract_templates/contract.handlebars --partials '../contract_templates/partials/**/*.handlebars' --output src/contract_wrappers/generated --backend ethers", "lint": "tslint --project . --exclude **/src/contract_wrappers/**/* --exclude **/lib/**/*", "test:circleci": "run-s test:coverage", "test": "yarn run_mocha", @@ -29,7 +29,7 @@ "manual:postpublish": "yarn build; node ./scripts/postpublish.js" }, "config": { - "contracts_v2_beta": "Exchange ERC20Proxy ERC20Token ERC721Proxy ERC721Token WETH9 ZRXToken", + "contracts_v2_beta": "Exchange ERC20Proxy ERC20Token ERC721Proxy ERC721Token WETH9 ZRXToken Forwarder", "contracts_v2": "DummyERC20Token DummyERC721Token" }, "repository": { diff --git a/packages/contract-wrappers/src/artifacts.ts b/packages/contract-wrappers/src/artifacts.ts index 742d0e1b2..2481b311a 100644 --- a/packages/contract-wrappers/src/artifacts.ts +++ b/packages/contract-wrappers/src/artifacts.ts @@ -7,6 +7,7 @@ import * as ERC20Token from './artifacts/ERC20Token.json'; import * as ERC721Proxy from './artifacts/ERC721Proxy.json'; import * as ERC721Token from './artifacts/ERC721Token.json'; import * as Exchange from './artifacts/Exchange.json'; +import * as Forwarder from './artifacts/Forwarder.json'; import * as EtherToken from './artifacts/WETH9.json'; import * as ZRXToken from './artifacts/ZRXToken.json'; @@ -20,4 +21,5 @@ export const artifacts = { EtherToken: (EtherToken as any) as ContractArtifact, ERC20Proxy: (ERC20Proxy as any) as ContractArtifact, ERC721Proxy: (ERC721Proxy as any) as ContractArtifact, + Forwarder: (Forwarder as any) as ContractArtifact, }; diff --git a/packages/contract-wrappers/src/contract_wrappers.ts b/packages/contract-wrappers/src/contract_wrappers.ts index 8010242c5..76aefbdcf 100644 --- a/packages/contract-wrappers/src/contract_wrappers.ts +++ b/packages/contract-wrappers/src/contract_wrappers.ts @@ -11,6 +11,7 @@ import { ERC721ProxyWrapper } from './contract_wrappers/erc721_proxy_wrapper'; import { ERC721TokenWrapper } from './contract_wrappers/erc721_token_wrapper'; import { EtherTokenWrapper } from './contract_wrappers/ether_token_wrapper'; import { ExchangeWrapper } from './contract_wrappers/exchange_wrapper'; +import { ForwarderWrapper } from './contract_wrappers/forwarder_wrapper'; import { ContractWrappersConfigSchema } from './schemas/contract_wrappers_config_schema'; import { contractWrappersPrivateNetworkConfigSchema } from './schemas/contract_wrappers_private_network_config_schema'; import { contractWrappersPublicNetworkConfigSchema } from './schemas/contract_wrappers_public_network_config_schema'; @@ -47,6 +48,11 @@ export class ContractWrappers { * erc721Proxy smart contract. */ public erc721Proxy: ERC721ProxyWrapper; + /** + * An instance of the ForwarderWrapper class containing methods for interacting with any Forwarder smart contract. + */ + public forwarder: ForwarderWrapper; + private _web3Wrapper: Web3Wrapper; /** * Instantiates a new ContractWrappers instance. @@ -104,6 +110,7 @@ export class ContractWrappers { config.zrxContractAddress, blockPollingIntervalMs, ); + this.forwarder = new ForwarderWrapper(this._web3Wrapper, config.networkId, config.forwarderContractAddress); } /** * Sets a new web3 provider for 0x.js. Updating the provider will stop all diff --git a/packages/contract-wrappers/src/contract_wrappers/forwarder_wrapper.ts b/packages/contract-wrappers/src/contract_wrappers/forwarder_wrapper.ts new file mode 100644 index 000000000..56533fb78 --- /dev/null +++ b/packages/contract-wrappers/src/contract_wrappers/forwarder_wrapper.ts @@ -0,0 +1,170 @@ +import { schemas } from '@0xproject/json-schemas'; +import { AssetProxyId, SignedOrder } from '@0xproject/types'; +import { BigNumber } from '@0xproject/utils'; +import { Web3Wrapper } from '@0xproject/web3-wrapper'; +import { ContractAbi } from 'ethereum-types'; +import * as _ from 'lodash'; + +import { artifacts } from '../artifacts'; +import { orderTxOptsSchema } from '../schemas/order_tx_opts_schema'; +import { txOptsSchema } from '../schemas/tx_opts_schema'; +import { TransactionOpts } from '../types'; +import { assert } from '../utils/assert'; +import { constants } from '../utils/constants'; + +import { ContractWrapper } from './contract_wrapper'; +import { ForwarderContract } from './generated/forwarder'; + +/** + * This class includes the functionality related to interacting with the Forwarder contract. + */ +export class ForwarderWrapper extends ContractWrapper { + public abi: ContractAbi = artifacts.Forwarder.compilerOutput.abi; + private _forwarderContractIfExists?: ForwarderContract; + private _contractAddressIfExists?: string; + constructor(web3Wrapper: Web3Wrapper, networkId: number, contractAddressIfExists?: string) { + super(web3Wrapper, networkId); + this._contractAddressIfExists = contractAddressIfExists; + } + /** + * Purchases as much of orders' makerAssets as possible by selling up to 95% of transaction's ETH value. + * Any ZRX required to pay fees for primary orders will automatically be purchased by this contract. + * 5% of ETH value is reserved for paying fees to order feeRecipients (in ZRX) and forwarding contract feeRecipient (in ETH). + * Any ETH not spent will be refunded to sender. + * @param signedOrders An array of objects that conform to the SignedOrder interface. All orders must specify the same makerAsset. + * All orders must specify WETH as the takerAsset + * @param takerAddress The user Ethereum address who would like to fill this order. Must be available via the supplied + * Provider provided at instantiation. + * @param ethAmount The amount of eth to send with the transaction + * @param signedFeeOrders An array of objects that conform to the SignedOrder interface. All orders must specify ZRX as makerAsset and WETH as takerAsset. + * Used to purchase ZRX for primary order fees. + * @param feePercentage The percentage of WETH sold that will payed as fee to forwarding contract feeRecipient. + * Defaults to 0. + * @param feeRecipientAddress The address that will receive ETH when signedFeeOrders are filled. + * @param txOpts Transaction parameters. + * @return Transaction hash. + */ + public async marketSellOrdersWithEthAsync( + signedOrders: SignedOrder[], + takerAddress: string, + ethAmount: BigNumber, + signedFeeOrders: SignedOrder[] = [], + feePercentage: BigNumber = constants.ZERO_AMOUNT, + feeRecipientAddress: string = constants.NULL_ADDRESS, + txOpts: TransactionOpts = {}, + ): Promise { + assert.doesConformToSchema('signedOrders', signedOrders, schemas.signedOrdersSchema); + await assert.isSenderAddressAsync('takerAddress', takerAddress, this._web3Wrapper); + assert.isBigNumber('ethAmount', ethAmount); + assert.doesConformToSchema('signedFeeOrders', signedFeeOrders, schemas.signedOrdersSchema); + assert.isBigNumber('feePercentage', feePercentage); + assert.isETHAddressHex('feeRecipientAddress', feeRecipientAddress); + assert.doesConformToSchema('txOpts', txOpts, txOptsSchema); + const normalizedTakerAddress = takerAddress.toLowerCase(); + const normalizedFeeRecipientAddress = feeRecipientAddress.toLowerCase(); + const ForwarderContractInstance = await this._getForwarderContractAsync(); + const txHash = await ForwarderContractInstance.marketSellOrdersWithEth.sendTransactionAsync( + signedOrders, + _.map(signedOrders, order => order.signature), + signedFeeOrders, + _.map(signedFeeOrders, order => order.signature), + feePercentage, + feeRecipientAddress, + { + value: ethAmount, + from: normalizedTakerAddress, + gas: txOpts.gasLimit, + gasPrice: txOpts.gasPrice, + }, + ); + return txHash; + } + /** + * Attempt to purchase makerAssetFillAmount of makerAsset by selling ethAmount provided with transaction. + * Any ZRX required to pay fees for primary orders will automatically be purchased by the contract. + * Any ETH not spent will be refunded to sender. + * @param signedOrders An array of objects that conform to the SignedOrder interface. All orders must specify the same makerAsset. + * All orders must specify WETH as the takerAsset + * @param makerAssetFillAmount The amount of the order (in taker asset baseUnits) that you wish to fill. + * @param takerAddress The user Ethereum address who would like to fill this order. Must be available via the supplied + * Provider provided at instantiation. + * @param ethAmount The amount of eth to send with the transaction + * @param signedFeeOrders An array of objects that conform to the SignedOrder interface. All orders must specify ZRX as makerAsset and WETH as takerAsset. + * Used to purchase ZRX for primary order fees. + * @param feePercentage The percentage of WETH sold that will payed as fee to forwarding contract feeRecipient. + * Defaults to 0. + * @param feeRecipientAddress The address that will receive ETH when signedFeeOrders are filled. + * @param txOpts Transaction parameters. + * @return Transaction hash. + */ + public async marketBuyOrdersWithEthAsync( + signedOrders: SignedOrder[], + makerAssetFillAmount: BigNumber, + takerAddress: string, + ethAmount: BigNumber, + signedFeeOrders: SignedOrder[] = [], + feePercentage: BigNumber = constants.ZERO_AMOUNT, + feeRecipientAddress: string = constants.NULL_ADDRESS, + txOpts: TransactionOpts = {}, + ): Promise { + assert.doesConformToSchema('signedOrders', signedOrders, schemas.signedOrdersSchema); + assert.isBigNumber('makerAssetFillAmount', makerAssetFillAmount); + await assert.isSenderAddressAsync('takerAddress', takerAddress, this._web3Wrapper); + assert.isBigNumber('ethAmount', ethAmount); + assert.doesConformToSchema('signedFeeOrders', signedFeeOrders, schemas.signedOrdersSchema); + assert.isBigNumber('feePercentage', feePercentage); + assert.isETHAddressHex('feeRecipientAddress', feeRecipientAddress); + assert.doesConformToSchema('txOpts', txOpts, txOptsSchema); + const normalizedTakerAddress = takerAddress.toLowerCase(); + const normalizedFeeRecipientAddress = feeRecipientAddress.toLowerCase(); + const ForwarderContractInstance = await this._getForwarderContractAsync(); + const txHash = await ForwarderContractInstance.marketBuyOrdersWithEth.sendTransactionAsync( + signedOrders, + makerAssetFillAmount, + _.map(signedOrders, order => order.signature), + signedFeeOrders, + _.map(signedFeeOrders, order => order.signature), + feePercentage, + feeRecipientAddress, + { + value: ethAmount, + from: normalizedTakerAddress, + gas: txOpts.gasLimit, + gasPrice: txOpts.gasPrice, + }, + ); + return txHash; + } + /** + * Retrieves the Ethereum address of the Forwarder contract deployed on the network + * that the user-passed web3 provider is connected to. + * @returns The Ethereum address of the Forwarder contract being used. + */ + public getContractAddress(): string { + const contractAddress = this._getContractAddress(artifacts.Forwarder, this._contractAddressIfExists); + return contractAddress; + } + // HACK: We don't want this method to be visible to the other units within that package but not to the end user. + // TS doesn't give that possibility and therefore we make it private and access it over an any cast. Because of that tslint sees it as unused. + // tslint:disable-next-line:no-unused-variable + private _invalidateContractInstance(): void { + delete this._forwarderContractIfExists; + } + private async _getForwarderContractAsync(): Promise { + if (!_.isUndefined(this._forwarderContractIfExists)) { + return this._forwarderContractIfExists; + } + const [abi, address] = await this._getContractAbiAndAddressFromArtifactsAsync( + artifacts.Forwarder, + this._contractAddressIfExists, + ); + const contractInstance = new ForwarderContract( + abi, + address, + this._web3Wrapper.getProvider(), + this._web3Wrapper.getContractDefaults(), + ); + this._forwarderContractIfExists = contractInstance; + return this._forwarderContractIfExists; + } +} diff --git a/packages/contract-wrappers/src/index.ts b/packages/contract-wrappers/src/index.ts index e5485d7a6..1986e0004 100644 --- a/packages/contract-wrappers/src/index.ts +++ b/packages/contract-wrappers/src/index.ts @@ -5,6 +5,7 @@ export { EtherTokenWrapper } from './contract_wrappers/ether_token_wrapper'; export { ExchangeWrapper } from './contract_wrappers/exchange_wrapper'; export { ERC20ProxyWrapper } from './contract_wrappers/erc20_proxy_wrapper'; export { ERC721ProxyWrapper } from './contract_wrappers/erc721_proxy_wrapper'; +export { ForwarderWrapper } from './contract_wrappers/forwarder_wrapper'; export { ContractWrappersError, diff --git a/packages/contract-wrappers/src/types.ts b/packages/contract-wrappers/src/types.ts index f9d7a6b9f..887d09c80 100644 --- a/packages/contract-wrappers/src/types.ts +++ b/packages/contract-wrappers/src/types.ts @@ -109,6 +109,7 @@ export type SyncMethod = (...args: any[]) => any; * zrxContractAddress: The address of the ZRX contract to use * erc20ProxyContractAddress: The address of the erc20 token transfer proxy contract to use * erc721ProxyContractAddress: The address of the erc721 token transfer proxy contract to use + * forwarderContractAddress: The address of the forwarder contract to use * orderWatcherConfig: All the configs related to the orderWatcher * blockPollingIntervalMs: The interval to use for block polling in event watching methods (defaults to 1000) */ @@ -119,6 +120,7 @@ export interface ContractWrappersConfig { zrxContractAddress?: string; erc20ProxyContractAddress?: string; erc721ProxyContractAddress?: string; + forwarderContractAddress?: string; blockPollingIntervalMs?: number; } diff --git a/packages/contract-wrappers/src/utils/constants.ts b/packages/contract-wrappers/src/utils/constants.ts index 039475b7f..d436efefc 100644 --- a/packages/contract-wrappers/src/utils/constants.ts +++ b/packages/contract-wrappers/src/utils/constants.ts @@ -10,4 +10,5 @@ export const constants = { // tslint:disable-next-line:custom-no-magic-numbers UNLIMITED_ALLOWANCE_IN_BASE_UNITS: new BigNumber(2).pow(256).minus(1), DEFAULT_BLOCK_POLLING_INTERVAL: 1000, + ZERO_AMOUNT: new BigNumber(0), }; diff --git a/packages/contract-wrappers/test/forwarder_wrapper_test.ts b/packages/contract-wrappers/test/forwarder_wrapper_test.ts new file mode 100644 index 000000000..61a21a0d7 --- /dev/null +++ b/packages/contract-wrappers/test/forwarder_wrapper_test.ts @@ -0,0 +1,57 @@ +import { BlockchainLifecycle, callbackErrorReporter } from '@0xproject/dev-utils'; +import { FillScenarios } from '@0xproject/fill-scenarios'; +import { assetDataUtils, orderHashUtils } from '@0xproject/order-utils'; +import { DoneCallback, SignedOrder } from '@0xproject/types'; +import { BigNumber } from '@0xproject/utils'; +import * as chai from 'chai'; +import { BlockParamLiteral } from 'ethereum-types'; +import 'mocha'; + +import { + ContractWrappers, + DecodedLogEvent, + ExchangeCancelEventArgs, + ExchangeEvents, + ExchangeFillEventArgs, + OrderStatus, +} from '../src'; + +import { chaiSetup } from './utils/chai_setup'; +import { constants } from './utils/constants'; +import { tokenUtils } from './utils/token_utils'; +import { provider, web3Wrapper } from './utils/web3_wrapper'; + +chaiSetup.configure(); +const expect = chai.expect; +const blockchainLifecycle = new BlockchainLifecycle(web3Wrapper); + +describe('ForwarderWrapper', () => { + let contractWrappers: ContractWrappers; + let forwarderContractAddress: string; + let userAddresses: string[]; + const config = { + networkId: constants.TESTRPC_NETWORK_ID, + blockPollingIntervalMs: 0, + }; + before(async () => { + await blockchainLifecycle.startAsync(); + contractWrappers = new ContractWrappers(provider, config); + forwarderContractAddress = contractWrappers.exchange.getContractAddress(); + userAddresses = await web3Wrapper.getAvailableAddressesAsync(); + }); + after(async () => { + await blockchainLifecycle.revertAsync(); + }); + beforeEach(async () => { + await blockchainLifecycle.startAsync(); + }); + afterEach(async () => { + await blockchainLifecycle.revertAsync(); + }); + // describe('#fillOrderAsync', () => { + // it('should fill a valid order', async () => { + // // txHash = await contractWrappers.exchange.fillOrderAsync(signedOrder, takerTokenFillAmount, takerAddress); + // // await web3Wrapper.awaitTransactionSuccessAsync(txHash, constants.AWAIT_TRANSACTION_MINED_MS); + // }); + // }); +}); -- cgit v1.2.3 From 045751a430c512d94bf7e515d7531bac68dc2179 Mon Sep 17 00:00:00 2001 From: Brandon Millman Date: Mon, 30 Jul 2018 17:43:02 -0700 Subject: Add getOrdersInfo to exchange_wrapper --- .../src/contract_wrappers/exchange_wrapper.ts | 22 +++++++++++++++++++++- packages/contract-wrappers/src/types.ts | 4 ++-- .../test/exchange_wrapper_test.ts | 9 +++++++++ 3 files changed, 32 insertions(+), 3 deletions(-) (limited to 'packages/contract-wrappers') diff --git a/packages/contract-wrappers/src/contract_wrappers/exchange_wrapper.ts b/packages/contract-wrappers/src/contract_wrappers/exchange_wrapper.ts index 3e7619228..48bd00f90 100644 --- a/packages/contract-wrappers/src/contract_wrappers/exchange_wrapper.ts +++ b/packages/contract-wrappers/src/contract_wrappers/exchange_wrapper.ts @@ -869,15 +869,35 @@ export class ExchangeWrapper extends ContractWrapper { */ @decorators.asyncZeroExErrorHandler public async getOrderInfoAsync(order: Order | SignedOrder, methodOpts: MethodOpts = {}): Promise { + assert.doesConformToSchema('order', order, schemas.orderSchema); if (!_.isUndefined(methodOpts)) { assert.doesConformToSchema('methodOpts', methodOpts, methodOptsSchema); } const exchangeInstance = await this._getExchangeContractAsync(); - const txData = {}; const orderInfo = await exchangeInstance.getOrderInfo.callAsync(order, txData, methodOpts.defaultBlock); return orderInfo; } + /** + * Get order info for multiple orders + * @param orders Orders + * @param methodOpts Optional arguments this method accepts. + * @returns Array of Order infos + */ + @decorators.asyncZeroExErrorHandler + public async getOrdersInfoAsync( + orders: Array, + methodOpts: MethodOpts = {}, + ): Promise { + assert.doesConformToSchema('orders', orders, schemas.ordersSchema); + if (!_.isUndefined(methodOpts)) { + assert.doesConformToSchema('methodOpts', methodOpts, methodOptsSchema); + } + const exchangeInstance = await this._getExchangeContractAsync(); + const txData = {}; + const ordersInfo = await exchangeInstance.getOrdersInfo.callAsync(orders, txData, methodOpts.defaultBlock); + return ordersInfo; + } /** * Cancel a given order. * @param order An object that conforms to the Order or SignedOrder interface. The order you would like to cancel. diff --git a/packages/contract-wrappers/src/types.ts b/packages/contract-wrappers/src/types.ts index 887d09c80..2b3cdc591 100644 --- a/packages/contract-wrappers/src/types.ts +++ b/packages/contract-wrappers/src/types.ts @@ -174,13 +174,13 @@ export enum TransferType { export type OnOrderStateChangeCallback = (err: Error | null, orderState?: OrderState) => void; export interface OrderInfo { - orderStatus: number; + orderStatus: OrderStatus; orderHash: string; orderTakerAssetFilledAmount: BigNumber; } export enum OrderStatus { - INVALID, + INVALID = 0, INVALID_MAKER_ASSET_AMOUNT, INVALID_TAKER_ASSET_AMOUNT, FILLABLE, diff --git a/packages/contract-wrappers/test/exchange_wrapper_test.ts b/packages/contract-wrappers/test/exchange_wrapper_test.ts index dca212f65..e468187f2 100644 --- a/packages/contract-wrappers/test/exchange_wrapper_test.ts +++ b/packages/contract-wrappers/test/exchange_wrapper_test.ts @@ -277,6 +277,15 @@ describe('ExchangeWrapper', () => { expect(orderInfo.orderHash).to.be.equal(orderHash); }); }); + describe('#getOrdersInfoAsync', () => { + it('should get the orders info', async () => { + const ordersInfo = await contractWrappers.exchange.getOrdersInfoAsync([signedOrder, anotherSignedOrder]); + const orderHash = orderHashUtils.getOrderHashHex(signedOrder); + expect(ordersInfo[0].orderHash).to.be.equal(orderHash); + const anotherOrderHash = orderHashUtils.getOrderHashHex(anotherSignedOrder); + expect(ordersInfo[1].orderHash).to.be.equal(anotherOrderHash); + }); + }); describe('#isValidSignature', () => { it('should check if the signature is valid', async () => { const orderHash = orderHashUtils.getOrderHashHex(signedOrder); -- cgit v1.2.3 From 44498f2263ccfec805a6815a1ab673e2dd423e8d Mon Sep 17 00:00:00 2001 From: Brandon Millman Date: Mon, 30 Jul 2018 17:51:02 -0700 Subject: Fix spelling error in exchange wrapper tests --- packages/contract-wrappers/test/exchange_wrapper_test.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'packages/contract-wrappers') diff --git a/packages/contract-wrappers/test/exchange_wrapper_test.ts b/packages/contract-wrappers/test/exchange_wrapper_test.ts index e468187f2..fa3b49eb9 100644 --- a/packages/contract-wrappers/test/exchange_wrapper_test.ts +++ b/packages/contract-wrappers/test/exchange_wrapper_test.ts @@ -304,7 +304,7 @@ describe('ExchangeWrapper', () => { }); }); describe('#isAllowedValidatorAsync', () => { - it('should check if the validator is alllowed', async () => { + it('should check if the validator is allowed', async () => { const signerAddress = makerAddress; const validatorAddress = constants.NULL_ADDRESS; const isAllowed = await contractWrappers.exchange.isAllowedValidatorAsync(signerAddress, validatorAddress); -- cgit v1.2.3 From bc93ff0cb5c846fcb534f90b93e54bba0747f562 Mon Sep 17 00:00:00 2001 From: Brandon Millman Date: Mon, 30 Jul 2018 19:43:44 -0700 Subject: Write initial test for forwarder_wrapper --- .../src/contract_wrappers/forwarder_wrapper.ts | 8 +-- .../test/forwarder_wrapper_test.ts | 81 ++++++++++++++++++---- 2 files changed, 73 insertions(+), 16 deletions(-) (limited to 'packages/contract-wrappers') diff --git a/packages/contract-wrappers/src/contract_wrappers/forwarder_wrapper.ts b/packages/contract-wrappers/src/contract_wrappers/forwarder_wrapper.ts index 56533fb78..db1e5390a 100644 --- a/packages/contract-wrappers/src/contract_wrappers/forwarder_wrapper.ts +++ b/packages/contract-wrappers/src/contract_wrappers/forwarder_wrapper.ts @@ -62,8 +62,8 @@ export class ForwarderWrapper extends ContractWrapper { assert.doesConformToSchema('txOpts', txOpts, txOptsSchema); const normalizedTakerAddress = takerAddress.toLowerCase(); const normalizedFeeRecipientAddress = feeRecipientAddress.toLowerCase(); - const ForwarderContractInstance = await this._getForwarderContractAsync(); - const txHash = await ForwarderContractInstance.marketSellOrdersWithEth.sendTransactionAsync( + const forwarderContractInstance = await this._getForwarderContractAsync(); + const txHash = await forwarderContractInstance.marketSellOrdersWithEth.sendTransactionAsync( signedOrders, _.map(signedOrders, order => order.signature), signedFeeOrders, @@ -117,8 +117,8 @@ export class ForwarderWrapper extends ContractWrapper { assert.doesConformToSchema('txOpts', txOpts, txOptsSchema); const normalizedTakerAddress = takerAddress.toLowerCase(); const normalizedFeeRecipientAddress = feeRecipientAddress.toLowerCase(); - const ForwarderContractInstance = await this._getForwarderContractAsync(); - const txHash = await ForwarderContractInstance.marketBuyOrdersWithEth.sendTransactionAsync( + const forwarderContractInstance = await this._getForwarderContractAsync(); + const txHash = await forwarderContractInstance.marketBuyOrdersWithEth.sendTransactionAsync( signedOrders, makerAssetFillAmount, _.map(signedOrders, order => order.signature), diff --git a/packages/contract-wrappers/test/forwarder_wrapper_test.ts b/packages/contract-wrappers/test/forwarder_wrapper_test.ts index 61a21a0d7..0fb695b9e 100644 --- a/packages/contract-wrappers/test/forwarder_wrapper_test.ts +++ b/packages/contract-wrappers/test/forwarder_wrapper_test.ts @@ -26,18 +26,65 @@ const expect = chai.expect; const blockchainLifecycle = new BlockchainLifecycle(web3Wrapper); describe('ForwarderWrapper', () => { - let contractWrappers: ContractWrappers; - let forwarderContractAddress: string; - let userAddresses: string[]; - const config = { + const contractWrappersConfig = { networkId: constants.TESTRPC_NETWORK_ID, blockPollingIntervalMs: 0, }; + const fillableAmount = new BigNumber(5); + const takerTokenFillAmount = new BigNumber(5); + let contractWrappers: ContractWrappers; + let fillScenarios: FillScenarios; + let forwarderContractAddress: string; + let exchangeContractAddress: string; + let zrxTokenAddress: string; + let userAddresses: string[]; + let coinbase: string; + let makerAddress: string; + let takerAddress: string; + let feeRecipient: string; + let anotherMakerAddress: string; + let makerTokenAddress: string; + let takerTokenAddress: string; + let makerAssetData: string; + let takerAssetData: string; + let signedOrder: SignedOrder; + let anotherSignedOrder: SignedOrder; before(async () => { await blockchainLifecycle.startAsync(); - contractWrappers = new ContractWrappers(provider, config); - forwarderContractAddress = contractWrappers.exchange.getContractAddress(); + contractWrappers = new ContractWrappers(provider, contractWrappersConfig); + forwarderContractAddress = contractWrappers.forwarder.getContractAddress(); + exchangeContractAddress = contractWrappers.exchange.getContractAddress(); userAddresses = await web3Wrapper.getAvailableAddressesAsync(); + zrxTokenAddress = tokenUtils.getProtocolTokenAddress(); + fillScenarios = new FillScenarios( + provider, + userAddresses, + zrxTokenAddress, + exchangeContractAddress, + contractWrappers.erc20Proxy.getContractAddress(), + contractWrappers.erc721Proxy.getContractAddress(), + ); + [coinbase, makerAddress, takerAddress, feeRecipient, anotherMakerAddress] = userAddresses; + [makerTokenAddress] = tokenUtils.getDummyERC20TokenAddresses(); + takerTokenAddress = tokenUtils.getWethTokenAddress(); + [makerAssetData, takerAssetData] = [ + assetDataUtils.encodeERC20AssetData(makerTokenAddress), + assetDataUtils.encodeERC20AssetData(takerTokenAddress), + ]; + signedOrder = await fillScenarios.createFillableSignedOrderAsync( + makerAssetData, + takerAssetData, + makerAddress, + constants.NULL_ADDRESS, + fillableAmount, + ); + anotherSignedOrder = await fillScenarios.createFillableSignedOrderAsync( + makerAssetData, + takerAssetData, + makerAddress, + constants.NULL_ADDRESS, + fillableAmount, + ); }); after(async () => { await blockchainLifecycle.revertAsync(); @@ -48,10 +95,20 @@ describe('ForwarderWrapper', () => { afterEach(async () => { await blockchainLifecycle.revertAsync(); }); - // describe('#fillOrderAsync', () => { - // it('should fill a valid order', async () => { - // // txHash = await contractWrappers.exchange.fillOrderAsync(signedOrder, takerTokenFillAmount, takerAddress); - // // await web3Wrapper.awaitTransactionSuccessAsync(txHash, constants.AWAIT_TRANSACTION_MINED_MS); - // }); - // }); + describe('#marketBuyOrdersWithEthAsync', () => { + it('should market buy orders with eth', async () => { + const signedOrders = [signedOrder, anotherSignedOrder]; + const makerAssetFillAmount = signedOrder.makerAssetAmount.plus(anotherSignedOrder.makerAssetAmount); + const txHash = await contractWrappers.forwarder.marketBuyOrdersWithEthAsync( + signedOrders, + makerAssetFillAmount, + takerAddress, + makerAssetFillAmount, + ); + await web3Wrapper.awaitTransactionSuccessAsync(txHash, constants.AWAIT_TRANSACTION_MINED_MS); + const ordersInfo = await contractWrappers.exchange.getOrdersInfoAsync([signedOrder, anotherSignedOrder]); + expect(ordersInfo[0].orderStatus).to.be.equal(OrderStatus.FULLY_FILLED); + expect(ordersInfo[1].orderStatus).to.be.equal(OrderStatus.FULLY_FILLED); + }); + }); }); -- cgit v1.2.3 From 8ed3d59f969c2f07e34739c5a08c69de583cef88 Mon Sep 17 00:00:00 2001 From: Brandon Millman Date: Mon, 30 Jul 2018 22:14:07 -0700 Subject: Add more assertions --- .../contract-wrappers/src/contract_wrappers.ts | 7 ++- .../src/contract_wrappers/forwarder_wrapper.ts | 41 ++++++++++++++- packages/contract-wrappers/src/utils/assert.ts | 60 ++++++++++++++++++++-- 3 files changed, 102 insertions(+), 6 deletions(-) (limited to 'packages/contract-wrappers') diff --git a/packages/contract-wrappers/src/contract_wrappers.ts b/packages/contract-wrappers/src/contract_wrappers.ts index 76aefbdcf..4277a0746 100644 --- a/packages/contract-wrappers/src/contract_wrappers.ts +++ b/packages/contract-wrappers/src/contract_wrappers.ts @@ -110,7 +110,12 @@ export class ContractWrappers { config.zrxContractAddress, blockPollingIntervalMs, ); - this.forwarder = new ForwarderWrapper(this._web3Wrapper, config.networkId, config.forwarderContractAddress); + this.forwarder = new ForwarderWrapper( + this._web3Wrapper, + config.networkId, + config.forwarderContractAddress, + config.zrxContractAddress, + ); } /** * Sets a new web3 provider for 0x.js. Updating the provider will stop all diff --git a/packages/contract-wrappers/src/contract_wrappers/forwarder_wrapper.ts b/packages/contract-wrappers/src/contract_wrappers/forwarder_wrapper.ts index db1e5390a..beb2d1c81 100644 --- a/packages/contract-wrappers/src/contract_wrappers/forwarder_wrapper.ts +++ b/packages/contract-wrappers/src/contract_wrappers/forwarder_wrapper.ts @@ -22,9 +22,16 @@ export class ForwarderWrapper extends ContractWrapper { public abi: ContractAbi = artifacts.Forwarder.compilerOutput.abi; private _forwarderContractIfExists?: ForwarderContract; private _contractAddressIfExists?: string; - constructor(web3Wrapper: Web3Wrapper, networkId: number, contractAddressIfExists?: string) { + private _zrxContractAddressIfExists?: string; + constructor( + web3Wrapper: Web3Wrapper, + networkId: number, + contractAddressIfExists?: string, + zrxContractAddressIfExists?: string, + ) { super(web3Wrapper, networkId); this._contractAddressIfExists = contractAddressIfExists; + this._zrxContractAddressIfExists = zrxContractAddressIfExists; } /** * Purchases as much of orders' makerAssets as possible by selling up to 95% of transaction's ETH value. @@ -53,6 +60,7 @@ export class ForwarderWrapper extends ContractWrapper { feeRecipientAddress: string = constants.NULL_ADDRESS, txOpts: TransactionOpts = {}, ): Promise { + // type assertions assert.doesConformToSchema('signedOrders', signedOrders, schemas.signedOrdersSchema); await assert.isSenderAddressAsync('takerAddress', takerAddress, this._web3Wrapper); assert.isBigNumber('ethAmount', ethAmount); @@ -60,6 +68,13 @@ export class ForwarderWrapper extends ContractWrapper { assert.isBigNumber('feePercentage', feePercentage); assert.isETHAddressHex('feeRecipientAddress', feeRecipientAddress); assert.doesConformToSchema('txOpts', txOpts, txOptsSchema); + // other assertions + assert.ordersCanBeUsedForForwarderContract(signedOrders, this.getEtherTokenAddress()); + assert.feeOrdersCanBeUsedForForwarderContract( + signedFeeOrders, + this.getZRXTokenAddress(), + this.getEtherTokenAddress(), + ); const normalizedTakerAddress = takerAddress.toLowerCase(); const normalizedFeeRecipientAddress = feeRecipientAddress.toLowerCase(); const forwarderContractInstance = await this._getForwarderContractAsync(); @@ -107,6 +122,7 @@ export class ForwarderWrapper extends ContractWrapper { feeRecipientAddress: string = constants.NULL_ADDRESS, txOpts: TransactionOpts = {}, ): Promise { + // type assertions assert.doesConformToSchema('signedOrders', signedOrders, schemas.signedOrdersSchema); assert.isBigNumber('makerAssetFillAmount', makerAssetFillAmount); await assert.isSenderAddressAsync('takerAddress', takerAddress, this._web3Wrapper); @@ -115,6 +131,13 @@ export class ForwarderWrapper extends ContractWrapper { assert.isBigNumber('feePercentage', feePercentage); assert.isETHAddressHex('feeRecipientAddress', feeRecipientAddress); assert.doesConformToSchema('txOpts', txOpts, txOptsSchema); + // other assertions + assert.ordersCanBeUsedForForwarderContract(signedOrders, this.getEtherTokenAddress()); + assert.feeOrdersCanBeUsedForForwarderContract( + signedFeeOrders, + this.getZRXTokenAddress(), + this.getEtherTokenAddress(), + ); const normalizedTakerAddress = takerAddress.toLowerCase(); const normalizedFeeRecipientAddress = feeRecipientAddress.toLowerCase(); const forwarderContractInstance = await this._getForwarderContractAsync(); @@ -144,6 +167,22 @@ export class ForwarderWrapper extends ContractWrapper { const contractAddress = this._getContractAddress(artifacts.Forwarder, this._contractAddressIfExists); return contractAddress; } + /** + * Returns the ZRX token address used by the forwarder contract. + * @return Address of ZRX token + */ + public getZRXTokenAddress(): string { + const contractAddress = this._getContractAddress(artifacts.ZRXToken, this._zrxContractAddressIfExists); + return contractAddress; + } + /** + * Returns the Ether token address used by the forwarder contract. + * @return Address of Ether token + */ + public getEtherTokenAddress(): string { + const contractAddress = this._getContractAddress(artifacts.EtherToken); + return contractAddress; + } // HACK: We don't want this method to be visible to the other units within that package but not to the end user. // TS doesn't give that possibility and therefore we make it private and access it over an any cast. Because of that tslint sees it as unused. // tslint:disable-next-line:no-unused-variable diff --git a/packages/contract-wrappers/src/utils/assert.ts b/packages/contract-wrappers/src/utils/assert.ts index 842b16fa0..183642170 100644 --- a/packages/contract-wrappers/src/utils/assert.ts +++ b/packages/contract-wrappers/src/utils/assert.ts @@ -1,11 +1,14 @@ import { assert as sharedAssert } from '@0xproject/assert'; // HACK: We need those two unused imports because they're actually used by sharedAssert which gets injected here import { Schema } from '@0xproject/json-schemas'; // tslint:disable-line:no-unused-variable -import { isValidSignatureAsync } from '@0xproject/order-utils'; -import { ECSignature } from '@0xproject/types'; // tslint:disable-line:no-unused-variable +import { assetDataUtils, isValidSignatureAsync } from '@0xproject/order-utils'; +import { ECSignature, Order } from '@0xproject/types'; // tslint:disable-line:no-unused-variable import { BigNumber } from '@0xproject/utils'; // tslint:disable-line:no-unused-variable import { Web3Wrapper } from '@0xproject/web3-wrapper'; import { Provider } from 'ethereum-types'; +import * as _ from 'lodash'; + +import { constants } from './constants'; export const assert = { ...sharedAssert, @@ -16,12 +19,12 @@ export const assert = { signerAddress: string, ): Promise { const isValid = await isValidSignatureAsync(provider, orderHash, signature, signerAddress); - this.assert(isValid, `Expected order with hash '${orderHash}' to have a valid signature`); + sharedAssert.assert(isValid, `Expected order with hash '${orderHash}' to have a valid signature`); }, isValidSubscriptionToken(variableName: string, subscriptionToken: string): void { const uuidRegex = new RegExp('^[a-fA-F0-9]{8}-[a-fA-F0-9]{4}-[a-fA-F0-9]{4}-[a-fA-F0-9]{4}-[a-fA-F0-9]{12}$'); const isValid = uuidRegex.test(subscriptionToken); - this.assert(isValid, `Expected ${variableName} to be a valid subscription token`); + sharedAssert.assert(isValid, `Expected ${variableName} to be a valid subscription token`); }, async isSenderAddressAsync( variableName: string, @@ -35,4 +38,53 @@ export const assert = { `Specified ${variableName} ${senderAddressHex} isn't available through the supplied web3 provider`, ); }, + ordersCanBeUsedForForwarderContract(orders: Order[], etherTokenAddress: string): void { + sharedAssert.assert(!_.isEmpty(orders), 'Expected at least 1 signed order. Found no orders'); + assert.ordersHaveAtMostOneUniqueValueForProperty(orders, 'makerAssetData'); + assert.allTakerAssetDatasAreErc20Token(orders, etherTokenAddress); + assert.allTakerAddressesAreNull(orders); + }, + feeOrdersCanBeUsedForForwarderContract(orders: Order[], zrxTokenAddress: string, etherTokenAddress: string): void { + if (!_.isEmpty(orders)) { + assert.allMakerAssetDatasAreErc20Token(orders, zrxTokenAddress); + assert.allTakerAssetDatasAreErc20Token(orders, etherTokenAddress); + } + }, + allTakerAddressesAreNull(orders: Order[]): void { + assert.ordersHaveAtMostOneUniqueValueForProperty(orders, 'takerAddress', constants.NULL_ADDRESS); + }, + allMakerAssetDatasAreErc20Token(orders: Order[], tokenAddress: string): void { + assert.ordersHaveAtMostOneUniqueValueForProperty( + orders, + 'makerAssetData', + assetDataUtils.encodeERC20AssetData(tokenAddress), + ); + }, + allTakerAssetDatasAreErc20Token(orders: Order[], tokenAddress: string): void { + assert.ordersHaveAtMostOneUniqueValueForProperty( + orders, + 'takerAssetData', + assetDataUtils.encodeERC20AssetData(tokenAddress), + ); + }, + /* + * Asserts that all the orders have the same value for the provided propertyName + * If the value parameter is provided, this asserts that all orders have the prope + */ + ordersHaveAtMostOneUniqueValueForProperty(orders: Order[], propertyName: string, value?: any): void { + const allValues = _.map(orders, order => _.get(order, propertyName)); + sharedAssert.hasAtMostOneUniqueValue( + allValues, + `Expected all orders to have the same ${propertyName} field. Found the following ${propertyName} values: ${JSON.stringify( + allValues, + )}`, + ); + if (!_.isUndefined(value)) { + const firstValue = _.head(allValues); + sharedAssert.assert( + firstValue === value, + `Expected all orders to have a ${propertyName} field with value: ${value}. Found: ${firstValue}`, + ); + } + }, }; -- cgit v1.2.3 From 5d44a67e62eb47ba4a8664e83ed46568df5eb78f Mon Sep 17 00:00:00 2001 From: Brandon Millman Date: Tue, 31 Jul 2018 00:10:58 -0700 Subject: Update forwarder_wrapper_test --- .../contract-wrappers/test/forwarder_wrapper_test.ts | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) (limited to 'packages/contract-wrappers') diff --git a/packages/contract-wrappers/test/forwarder_wrapper_test.ts b/packages/contract-wrappers/test/forwarder_wrapper_test.ts index 0fb695b9e..3f3b40e0b 100644 --- a/packages/contract-wrappers/test/forwarder_wrapper_test.ts +++ b/packages/contract-wrappers/test/forwarder_wrapper_test.ts @@ -111,4 +111,20 @@ describe('ForwarderWrapper', () => { expect(ordersInfo[1].orderStatus).to.be.equal(OrderStatus.FULLY_FILLED); }); }); + describe('#marketSellOrdersWithEthAsync', () => { + it('should market sell orders with eth', async () => { + const signedOrders = [signedOrder, anotherSignedOrder]; + const makerAssetFillAmount = signedOrder.makerAssetAmount.plus(anotherSignedOrder.makerAssetAmount); + const txHash = await contractWrappers.forwarder.marketSellOrdersWithEthAsync( + signedOrders, + takerAddress, + makerAssetFillAmount, + ); + await web3Wrapper.awaitTransactionSuccessAsync(txHash, constants.AWAIT_TRANSACTION_MINED_MS); + const ordersInfo = await contractWrappers.exchange.getOrdersInfoAsync([signedOrder, anotherSignedOrder]); + expect(ordersInfo[0].orderStatus).to.be.equal(OrderStatus.FULLY_FILLED); + expect(ordersInfo[1].orderStatus).to.be.equal(OrderStatus.FILLABLE); + expect(ordersInfo[1].orderTakerAssetFilledAmount).to.be.bignumber.equal(new BigNumber(4)); // only 95% of ETH is sold + }); + }); }); -- cgit v1.2.3 From ca1f926d6d137f9523a9765c047430ec39d45d86 Mon Sep 17 00:00:00 2001 From: Brandon Millman Date: Tue, 31 Jul 2018 00:26:53 -0700 Subject: Clarify ethAmount is in wei --- packages/contract-wrappers/src/contract_wrappers/forwarder_wrapper.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'packages/contract-wrappers') diff --git a/packages/contract-wrappers/src/contract_wrappers/forwarder_wrapper.ts b/packages/contract-wrappers/src/contract_wrappers/forwarder_wrapper.ts index beb2d1c81..90cfbe2af 100644 --- a/packages/contract-wrappers/src/contract_wrappers/forwarder_wrapper.ts +++ b/packages/contract-wrappers/src/contract_wrappers/forwarder_wrapper.ts @@ -42,7 +42,7 @@ export class ForwarderWrapper extends ContractWrapper { * All orders must specify WETH as the takerAsset * @param takerAddress The user Ethereum address who would like to fill this order. Must be available via the supplied * Provider provided at instantiation. - * @param ethAmount The amount of eth to send with the transaction + * @param ethAmount The amount of eth to send with the transaction (in wei). * @param signedFeeOrders An array of objects that conform to the SignedOrder interface. All orders must specify ZRX as makerAsset and WETH as takerAsset. * Used to purchase ZRX for primary order fees. * @param feePercentage The percentage of WETH sold that will payed as fee to forwarding contract feeRecipient. @@ -103,7 +103,7 @@ export class ForwarderWrapper extends ContractWrapper { * @param makerAssetFillAmount The amount of the order (in taker asset baseUnits) that you wish to fill. * @param takerAddress The user Ethereum address who would like to fill this order. Must be available via the supplied * Provider provided at instantiation. - * @param ethAmount The amount of eth to send with the transaction + * @param ethAmount The amount of eth to send with the transaction (in wei). * @param signedFeeOrders An array of objects that conform to the SignedOrder interface. All orders must specify ZRX as makerAsset and WETH as takerAsset. * Used to purchase ZRX for primary order fees. * @param feePercentage The percentage of WETH sold that will payed as fee to forwarding contract feeRecipient. -- cgit v1.2.3 From 9f7f61085c1a6989b79df575beb0b5d8f2b3652d Mon Sep 17 00:00:00 2001 From: Brandon Millman Date: Wed, 1 Aug 2018 15:29:47 -0700 Subject: Update contract-wrappers CHANGELOG.json --- packages/contract-wrappers/CHANGELOG.json | 9 +++++++++ 1 file changed, 9 insertions(+) (limited to 'packages/contract-wrappers') diff --git a/packages/contract-wrappers/CHANGELOG.json b/packages/contract-wrappers/CHANGELOG.json index d9eef089f..8fa31052c 100644 --- a/packages/contract-wrappers/CHANGELOG.json +++ b/packages/contract-wrappers/CHANGELOG.json @@ -1,4 +1,13 @@ [ + { + "version": "1.1.0-rc.2", + "changes": [ + { + "note": "Add ForwarderWrapper", + "pr": 934 + } + ] + }, { "version": "1.0.1-rc.2", "changes": [ -- cgit v1.2.3 From 4f006fdc5c3cc24bb5d008f4c363d5225fe6728a Mon Sep 17 00:00:00 2001 From: Brandon Millman Date: Wed, 1 Aug 2018 14:27:17 -0700 Subject: Create marketBuyOrdersOptimizations --- .../src/contract_wrappers/forwarder_wrapper.ts | 27 ++++++++++---- packages/contract-wrappers/src/utils/constants.ts | 1 + .../src/utils/market_orders_optimization_utils.ts | 43 ++++++++++++++++++++++ 3 files changed, 63 insertions(+), 8 deletions(-) create mode 100644 packages/contract-wrappers/src/utils/market_orders_optimization_utils.ts (limited to 'packages/contract-wrappers') diff --git a/packages/contract-wrappers/src/contract_wrappers/forwarder_wrapper.ts b/packages/contract-wrappers/src/contract_wrappers/forwarder_wrapper.ts index 90cfbe2af..7d51889cf 100644 --- a/packages/contract-wrappers/src/contract_wrappers/forwarder_wrapper.ts +++ b/packages/contract-wrappers/src/contract_wrappers/forwarder_wrapper.ts @@ -11,6 +11,7 @@ import { txOptsSchema } from '../schemas/tx_opts_schema'; import { TransactionOpts } from '../types'; import { assert } from '../utils/assert'; import { constants } from '../utils/constants'; +import { marketOrdersOptimizationUtils } from '../utils/market_orders_optimization_utils'; import { ContractWrapper } from './contract_wrapper'; import { ForwarderContract } from './generated/forwarder'; @@ -75,14 +76,19 @@ export class ForwarderWrapper extends ContractWrapper { this.getZRXTokenAddress(), this.getEtherTokenAddress(), ); + // lowercase input addresses const normalizedTakerAddress = takerAddress.toLowerCase(); const normalizedFeeRecipientAddress = feeRecipientAddress.toLowerCase(); + // optimize orders + const optimizedMarketOrders = marketOrdersOptimizationUtils.optimizeMarketOrders(signedOrders); + const optimizedFeeOrders = marketOrdersOptimizationUtils.optimizeFeeOrders(signedFeeOrders); + // send transaction const forwarderContractInstance = await this._getForwarderContractAsync(); const txHash = await forwarderContractInstance.marketSellOrdersWithEth.sendTransactionAsync( - signedOrders, - _.map(signedOrders, order => order.signature), - signedFeeOrders, - _.map(signedFeeOrders, order => order.signature), + optimizedMarketOrders, + _.map(optimizedMarketOrders, order => order.signature), + optimizedFeeOrders, + _.map(optimizedFeeOrders, order => order.signature), feePercentage, feeRecipientAddress, { @@ -138,15 +144,20 @@ export class ForwarderWrapper extends ContractWrapper { this.getZRXTokenAddress(), this.getEtherTokenAddress(), ); + // lowercase input addresses const normalizedTakerAddress = takerAddress.toLowerCase(); const normalizedFeeRecipientAddress = feeRecipientAddress.toLowerCase(); + // optimize orders + const optimizedMarketOrders = marketOrdersOptimizationUtils.optimizeMarketOrders(signedOrders); + const optimizedFeeOrders = marketOrdersOptimizationUtils.optimizeFeeOrders(signedFeeOrders); + // send transaction const forwarderContractInstance = await this._getForwarderContractAsync(); const txHash = await forwarderContractInstance.marketBuyOrdersWithEth.sendTransactionAsync( - signedOrders, + optimizedMarketOrders, makerAssetFillAmount, - _.map(signedOrders, order => order.signature), - signedFeeOrders, - _.map(signedFeeOrders, order => order.signature), + _.map(optimizedMarketOrders, order => order.signature), + optimizedFeeOrders, + _.map(optimizedFeeOrders, order => order.signature), feePercentage, feeRecipientAddress, { diff --git a/packages/contract-wrappers/src/utils/constants.ts b/packages/contract-wrappers/src/utils/constants.ts index d436efefc..2df11538c 100644 --- a/packages/contract-wrappers/src/utils/constants.ts +++ b/packages/contract-wrappers/src/utils/constants.ts @@ -2,6 +2,7 @@ import { BigNumber } from '@0xproject/utils'; export const constants = { NULL_ADDRESS: '0x0000000000000000000000000000000000000000', + NULL_BYTES: '0x', TESTRPC_NETWORK_ID: 50, INVALID_JUMP_PATTERN: 'invalid JUMP at', REVERT: 'revert', diff --git a/packages/contract-wrappers/src/utils/market_orders_optimization_utils.ts b/packages/contract-wrappers/src/utils/market_orders_optimization_utils.ts new file mode 100644 index 000000000..0041f1a64 --- /dev/null +++ b/packages/contract-wrappers/src/utils/market_orders_optimization_utils.ts @@ -0,0 +1,43 @@ +import { SignedOrder } from '@0xproject/types'; +import * as _ from 'lodash'; + +import { constants } from './constants'; + +export const marketOrdersOptimizationUtils = { + /** + * Takes an array of orders and outputs an array of equivalent orders where all takerAssetData are '0x' and + * all makerAssetData are '0x' except for that of the first order, which retains its original value + * @param orders An array of SignedOrder objects + * @returns optimized orders + */ + optimizeMarketOrders(orders: SignedOrder[]): SignedOrder[] { + const optimizedOrders = _.map(orders, (order, index) => { + const makerAssetData = index === 0 ? order.makerAssetData : constants.NULL_BYTES; + const takerAssetData = constants.NULL_BYTES; + return { + ...order, + makerAssetData, + takerAssetData, + }; + }); + return optimizedOrders; + }, + /** + * Takes an array of orders and outputs an array of equivalent orders where all takerAssetData are '0x' and + * all makerAssetData are '0x' + * @param orders An array of SignedOrder objects + * @returns optimized orders + */ + optimizeFeeOrders(orders: SignedOrder[]): SignedOrder[] { + const optimizedOrders = _.map(orders, order => { + const makerAssetData = constants.NULL_BYTES; + const takerAssetData = constants.NULL_BYTES; + return { + ...order, + makerAssetData, + takerAssetData, + }; + }); + return optimizedOrders; + }, +}; -- cgit v1.2.3 From 30c6fe08ec5f67fa3679c0043a24ffc420974964 Mon Sep 17 00:00:00 2001 From: Brandon Millman Date: Wed, 1 Aug 2018 15:08:34 -0700 Subject: Add tests --- .../src/utils/market_orders_optimization_utils.ts | 37 ++++++------ .../test/market_orders_optimization_utils_test.ts | 66 ++++++++++++++++++++++ 2 files changed, 85 insertions(+), 18 deletions(-) create mode 100644 packages/contract-wrappers/test/market_orders_optimization_utils_test.ts (limited to 'packages/contract-wrappers') diff --git a/packages/contract-wrappers/src/utils/market_orders_optimization_utils.ts b/packages/contract-wrappers/src/utils/market_orders_optimization_utils.ts index 0041f1a64..e35b2eadc 100644 --- a/packages/contract-wrappers/src/utils/market_orders_optimization_utils.ts +++ b/packages/contract-wrappers/src/utils/market_orders_optimization_utils.ts @@ -11,15 +11,12 @@ export const marketOrdersOptimizationUtils = { * @returns optimized orders */ optimizeMarketOrders(orders: SignedOrder[]): SignedOrder[] { - const optimizedOrders = _.map(orders, (order, index) => { - const makerAssetData = index === 0 ? order.makerAssetData : constants.NULL_BYTES; - const takerAssetData = constants.NULL_BYTES; - return { - ...order, - makerAssetData, - takerAssetData, - }; - }); + const optimizedOrders = _.map(orders, (order, index) => + transformOrder(order, { + makerAssetData: index === 0 ? order.makerAssetData : constants.NULL_BYTES, + takerAssetData: constants.NULL_BYTES, + }), + ); return optimizedOrders; }, /** @@ -29,15 +26,19 @@ export const marketOrdersOptimizationUtils = { * @returns optimized orders */ optimizeFeeOrders(orders: SignedOrder[]): SignedOrder[] { - const optimizedOrders = _.map(orders, order => { - const makerAssetData = constants.NULL_BYTES; - const takerAssetData = constants.NULL_BYTES; - return { - ...order, - makerAssetData, - takerAssetData, - }; - }); + const optimizedOrders = _.map(orders, (order, index) => + transformOrder(order, { + makerAssetData: constants.NULL_BYTES, + takerAssetData: constants.NULL_BYTES, + }), + ); return optimizedOrders; }, }; + +const transformOrder = (order: SignedOrder, partialOrder: Partial) => { + return { + ...order, + ...partialOrder, + }; +}; diff --git a/packages/contract-wrappers/test/market_orders_optimization_utils_test.ts b/packages/contract-wrappers/test/market_orders_optimization_utils_test.ts new file mode 100644 index 000000000..742294df2 --- /dev/null +++ b/packages/contract-wrappers/test/market_orders_optimization_utils_test.ts @@ -0,0 +1,66 @@ +import { orderFactory } from '@0xproject/order-utils'; +import * as chai from 'chai'; +import * as _ from 'lodash'; +import 'mocha'; + +import { constants } from '../src/utils/constants'; +import { marketOrdersOptimizationUtils } from '../src/utils/market_orders_optimization_utils'; + +import { chaiSetup } from './utils/chai_setup'; +import { assert } from '../src/utils/assert'; +import { NULL_BYTES } from '@0xproject/utils'; + +chaiSetup.configure(); +const expect = chai.expect; + +// utility for generating a set of order objects with mostly NULL values +// except for a specified makerAssetData and takerAssetData +const FAKE_ORDERS_COUNT = 5; +const generateFakeOrders = (makerAssetData: string, takerAssetData: string) => + _.map(_.range(FAKE_ORDERS_COUNT), index => { + const order = orderFactory.createOrder( + constants.NULL_ADDRESS, + constants.NULL_ADDRESS, + constants.NULL_ADDRESS, + constants.ZERO_AMOUNT, + constants.ZERO_AMOUNT, + constants.ZERO_AMOUNT, + makerAssetData, + constants.ZERO_AMOUNT, + takerAssetData, + constants.NULL_ADDRESS, + constants.NULL_ADDRESS, + ); + return { + ...order, + signature: 'dummy signature', + }; + }); + +describe('marketOrdersOptimizationUtils', () => { + const fakeMakerAssetData = 'fakeMakerAssetData'; + const fakeTakerAssetData = 'fakeTakerAssetData'; + const orders = generateFakeOrders(fakeMakerAssetData, fakeTakerAssetData); + describe('#optimizeMarketOrders', () => { + it('should make makerAssetData `0x` unless first order', () => { + const optimizedOrders = marketOrdersOptimizationUtils.optimizeMarketOrders(orders); + expect(optimizedOrders[0].makerAssetData).to.equal(fakeMakerAssetData); + const ordersWithoutHead = _.slice(optimizedOrders, 1); + _.forEach(ordersWithoutHead, order => expect(order.makerAssetData).to.equal(constants.NULL_BYTES)); + }); + it('should make all takerAssetData `0x`', () => { + const optimizedOrders = marketOrdersOptimizationUtils.optimizeMarketOrders(orders); + _.forEach(optimizedOrders, order => expect(order.takerAssetData).to.equal(constants.NULL_BYTES)); + }); + }); + describe('#optimizeFeeOrders', () => { + it('should make all makerAssetData `0x`', () => { + const optimizedOrders = marketOrdersOptimizationUtils.optimizeFeeOrders(orders); + _.forEach(optimizedOrders, order => expect(order.makerAssetData).to.equal(constants.NULL_BYTES)); + }); + it('should make all takerAssetData `0x`', () => { + const optimizedOrders = marketOrdersOptimizationUtils.optimizeFeeOrders(orders); + _.forEach(optimizedOrders, order => expect(order.takerAssetData).to.equal(constants.NULL_BYTES)); + }); + }); +}); -- cgit v1.2.3 From 6e74896620137b462b78a9493278a30efd016c44 Mon Sep 17 00:00:00 2001 From: Brandon Millman Date: Wed, 1 Aug 2018 20:49:10 -0700 Subject: CHANGELOG --- packages/contract-wrappers/CHANGELOG.json | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'packages/contract-wrappers') diff --git a/packages/contract-wrappers/CHANGELOG.json b/packages/contract-wrappers/CHANGELOG.json index 8fa31052c..cf10751d4 100644 --- a/packages/contract-wrappers/CHANGELOG.json +++ b/packages/contract-wrappers/CHANGELOG.json @@ -5,6 +5,10 @@ { "note": "Add ForwarderWrapper", "pr": 934 + }, + { + "note": "Optimize orders in ForwarderWrapper", + "pr": 935 } ] }, -- cgit v1.2.3 From c3e6be7956adf4fabcc8dfffe081515562a1dde0 Mon Sep 17 00:00:00 2001 From: Brandon Millman Date: Thu, 2 Aug 2018 15:53:02 -0700 Subject: Add missing PR numbers --- packages/contract-wrappers/CHANGELOG.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'packages/contract-wrappers') diff --git a/packages/contract-wrappers/CHANGELOG.json b/packages/contract-wrappers/CHANGELOG.json index cf10751d4..d95c99a25 100644 --- a/packages/contract-wrappers/CHANGELOG.json +++ b/packages/contract-wrappers/CHANGELOG.json @@ -8,7 +8,7 @@ }, { "note": "Optimize orders in ForwarderWrapper", - "pr": 935 + "pr": 936 } ] }, -- cgit v1.2.3 From 82092ab50a73e15e167f387380cd75ac52581e88 Mon Sep 17 00:00:00 2001 From: Brandon Millman Date: Thu, 2 Aug 2018 16:02:58 -0700 Subject: Rename to calldata utils --- .../src/contract_wrappers/forwarder_wrapper.ts | 10 ++-- .../src/utils/calldata_optimization_utils.ts | 44 +++++++++++++++ .../src/utils/market_orders_optimization_utils.ts | 44 --------------- .../test/calldata_optimization_utils_test.ts | 66 ++++++++++++++++++++++ .../test/market_orders_optimization_utils_test.ts | 66 ---------------------- 5 files changed, 115 insertions(+), 115 deletions(-) create mode 100644 packages/contract-wrappers/src/utils/calldata_optimization_utils.ts delete mode 100644 packages/contract-wrappers/src/utils/market_orders_optimization_utils.ts create mode 100644 packages/contract-wrappers/test/calldata_optimization_utils_test.ts delete mode 100644 packages/contract-wrappers/test/market_orders_optimization_utils_test.ts (limited to 'packages/contract-wrappers') diff --git a/packages/contract-wrappers/src/contract_wrappers/forwarder_wrapper.ts b/packages/contract-wrappers/src/contract_wrappers/forwarder_wrapper.ts index 7d51889cf..13ef0fe01 100644 --- a/packages/contract-wrappers/src/contract_wrappers/forwarder_wrapper.ts +++ b/packages/contract-wrappers/src/contract_wrappers/forwarder_wrapper.ts @@ -10,8 +10,8 @@ import { orderTxOptsSchema } from '../schemas/order_tx_opts_schema'; import { txOptsSchema } from '../schemas/tx_opts_schema'; import { TransactionOpts } from '../types'; import { assert } from '../utils/assert'; +import { calldataOptimizationUtils } from '../utils/calldata_optimization_utils'; import { constants } from '../utils/constants'; -import { marketOrdersOptimizationUtils } from '../utils/market_orders_optimization_utils'; import { ContractWrapper } from './contract_wrapper'; import { ForwarderContract } from './generated/forwarder'; @@ -80,8 +80,8 @@ export class ForwarderWrapper extends ContractWrapper { const normalizedTakerAddress = takerAddress.toLowerCase(); const normalizedFeeRecipientAddress = feeRecipientAddress.toLowerCase(); // optimize orders - const optimizedMarketOrders = marketOrdersOptimizationUtils.optimizeMarketOrders(signedOrders); - const optimizedFeeOrders = marketOrdersOptimizationUtils.optimizeFeeOrders(signedFeeOrders); + const optimizedMarketOrders = calldataOptimizationUtils.optimizeForwarderOrders(signedOrders); + const optimizedFeeOrders = calldataOptimizationUtils.optimizeForwarderFeeOrders(signedFeeOrders); // send transaction const forwarderContractInstance = await this._getForwarderContractAsync(); const txHash = await forwarderContractInstance.marketSellOrdersWithEth.sendTransactionAsync( @@ -148,8 +148,8 @@ export class ForwarderWrapper extends ContractWrapper { const normalizedTakerAddress = takerAddress.toLowerCase(); const normalizedFeeRecipientAddress = feeRecipientAddress.toLowerCase(); // optimize orders - const optimizedMarketOrders = marketOrdersOptimizationUtils.optimizeMarketOrders(signedOrders); - const optimizedFeeOrders = marketOrdersOptimizationUtils.optimizeFeeOrders(signedFeeOrders); + const optimizedMarketOrders = calldataOptimizationUtils.optimizeForwarderOrders(signedOrders); + const optimizedFeeOrders = calldataOptimizationUtils.optimizeForwarderFeeOrders(signedFeeOrders); // send transaction const forwarderContractInstance = await this._getForwarderContractAsync(); const txHash = await forwarderContractInstance.marketBuyOrdersWithEth.sendTransactionAsync( diff --git a/packages/contract-wrappers/src/utils/calldata_optimization_utils.ts b/packages/contract-wrappers/src/utils/calldata_optimization_utils.ts new file mode 100644 index 000000000..3172cf531 --- /dev/null +++ b/packages/contract-wrappers/src/utils/calldata_optimization_utils.ts @@ -0,0 +1,44 @@ +import { SignedOrder } from '@0xproject/types'; +import * as _ from 'lodash'; + +import { constants } from './constants'; + +export const calldataOptimizationUtils = { + /** + * Takes an array of orders and outputs an array of equivalent orders where all takerAssetData are '0x' and + * all makerAssetData are '0x' except for that of the first order, which retains its original value + * @param orders An array of SignedOrder objects + * @returns optimized orders + */ + optimizeForwarderOrders(orders: SignedOrder[]): SignedOrder[] { + const optimizedOrders = _.map(orders, (order, index) => + transformOrder(order, { + makerAssetData: index === 0 ? order.makerAssetData : constants.NULL_BYTES, + takerAssetData: constants.NULL_BYTES, + }), + ); + return optimizedOrders; + }, + /** + * Takes an array of orders and outputs an array of equivalent orders where all takerAssetData are '0x' and + * all makerAssetData are '0x' + * @param orders An array of SignedOrder objects + * @returns optimized orders + */ + optimizeForwarderFeeOrders(orders: SignedOrder[]): SignedOrder[] { + const optimizedOrders = _.map(orders, (order, index) => + transformOrder(order, { + makerAssetData: constants.NULL_BYTES, + takerAssetData: constants.NULL_BYTES, + }), + ); + return optimizedOrders; + }, +}; + +const transformOrder = (order: SignedOrder, partialOrder: Partial) => { + return { + ...order, + ...partialOrder, + }; +}; diff --git a/packages/contract-wrappers/src/utils/market_orders_optimization_utils.ts b/packages/contract-wrappers/src/utils/market_orders_optimization_utils.ts deleted file mode 100644 index e35b2eadc..000000000 --- a/packages/contract-wrappers/src/utils/market_orders_optimization_utils.ts +++ /dev/null @@ -1,44 +0,0 @@ -import { SignedOrder } from '@0xproject/types'; -import * as _ from 'lodash'; - -import { constants } from './constants'; - -export const marketOrdersOptimizationUtils = { - /** - * Takes an array of orders and outputs an array of equivalent orders where all takerAssetData are '0x' and - * all makerAssetData are '0x' except for that of the first order, which retains its original value - * @param orders An array of SignedOrder objects - * @returns optimized orders - */ - optimizeMarketOrders(orders: SignedOrder[]): SignedOrder[] { - const optimizedOrders = _.map(orders, (order, index) => - transformOrder(order, { - makerAssetData: index === 0 ? order.makerAssetData : constants.NULL_BYTES, - takerAssetData: constants.NULL_BYTES, - }), - ); - return optimizedOrders; - }, - /** - * Takes an array of orders and outputs an array of equivalent orders where all takerAssetData are '0x' and - * all makerAssetData are '0x' - * @param orders An array of SignedOrder objects - * @returns optimized orders - */ - optimizeFeeOrders(orders: SignedOrder[]): SignedOrder[] { - const optimizedOrders = _.map(orders, (order, index) => - transformOrder(order, { - makerAssetData: constants.NULL_BYTES, - takerAssetData: constants.NULL_BYTES, - }), - ); - return optimizedOrders; - }, -}; - -const transformOrder = (order: SignedOrder, partialOrder: Partial) => { - return { - ...order, - ...partialOrder, - }; -}; diff --git a/packages/contract-wrappers/test/calldata_optimization_utils_test.ts b/packages/contract-wrappers/test/calldata_optimization_utils_test.ts new file mode 100644 index 000000000..107d913ba --- /dev/null +++ b/packages/contract-wrappers/test/calldata_optimization_utils_test.ts @@ -0,0 +1,66 @@ +import { orderFactory } from '@0xproject/order-utils'; +import * as chai from 'chai'; +import * as _ from 'lodash'; +import 'mocha'; + +import { constants } from '../src/utils/constants'; +import { calldataOptimizationUtils } from '../src/utils/calldata_optimization_utils'; + +import { chaiSetup } from './utils/chai_setup'; +import { assert } from '../src/utils/assert'; +import { NULL_BYTES } from '@0xproject/utils'; + +chaiSetup.configure(); +const expect = chai.expect; + +// utility for generating a set of order objects with mostly NULL values +// except for a specified makerAssetData and takerAssetData +const FAKE_ORDERS_COUNT = 5; +const generateFakeOrders = (makerAssetData: string, takerAssetData: string) => + _.map(_.range(FAKE_ORDERS_COUNT), index => { + const order = orderFactory.createOrder( + constants.NULL_ADDRESS, + constants.NULL_ADDRESS, + constants.NULL_ADDRESS, + constants.ZERO_AMOUNT, + constants.ZERO_AMOUNT, + constants.ZERO_AMOUNT, + makerAssetData, + constants.ZERO_AMOUNT, + takerAssetData, + constants.NULL_ADDRESS, + constants.NULL_ADDRESS, + ); + return { + ...order, + signature: 'dummy signature', + }; + }); + +describe('calldataOptimizationUtils', () => { + const fakeMakerAssetData = 'fakeMakerAssetData'; + const fakeTakerAssetData = 'fakeTakerAssetData'; + const orders = generateFakeOrders(fakeMakerAssetData, fakeTakerAssetData); + describe('#optimizeForwarderOrders', () => { + it('should make makerAssetData `0x` unless first order', () => { + const optimizedOrders = calldataOptimizationUtils.optimizeForwarderOrders(orders); + expect(optimizedOrders[0].makerAssetData).to.equal(fakeMakerAssetData); + const ordersWithoutHead = _.slice(optimizedOrders, 1); + _.forEach(ordersWithoutHead, order => expect(order.makerAssetData).to.equal(constants.NULL_BYTES)); + }); + it('should make all takerAssetData `0x`', () => { + const optimizedOrders = calldataOptimizationUtils.optimizeForwarderOrders(orders); + _.forEach(optimizedOrders, order => expect(order.takerAssetData).to.equal(constants.NULL_BYTES)); + }); + }); + describe('#optimizeForwarderFeeOrders', () => { + it('should make all makerAssetData `0x`', () => { + const optimizedOrders = calldataOptimizationUtils.optimizeForwarderFeeOrders(orders); + _.forEach(optimizedOrders, order => expect(order.makerAssetData).to.equal(constants.NULL_BYTES)); + }); + it('should make all takerAssetData `0x`', () => { + const optimizedOrders = calldataOptimizationUtils.optimizeForwarderFeeOrders(orders); + _.forEach(optimizedOrders, order => expect(order.takerAssetData).to.equal(constants.NULL_BYTES)); + }); + }); +}); diff --git a/packages/contract-wrappers/test/market_orders_optimization_utils_test.ts b/packages/contract-wrappers/test/market_orders_optimization_utils_test.ts deleted file mode 100644 index 742294df2..000000000 --- a/packages/contract-wrappers/test/market_orders_optimization_utils_test.ts +++ /dev/null @@ -1,66 +0,0 @@ -import { orderFactory } from '@0xproject/order-utils'; -import * as chai from 'chai'; -import * as _ from 'lodash'; -import 'mocha'; - -import { constants } from '../src/utils/constants'; -import { marketOrdersOptimizationUtils } from '../src/utils/market_orders_optimization_utils'; - -import { chaiSetup } from './utils/chai_setup'; -import { assert } from '../src/utils/assert'; -import { NULL_BYTES } from '@0xproject/utils'; - -chaiSetup.configure(); -const expect = chai.expect; - -// utility for generating a set of order objects with mostly NULL values -// except for a specified makerAssetData and takerAssetData -const FAKE_ORDERS_COUNT = 5; -const generateFakeOrders = (makerAssetData: string, takerAssetData: string) => - _.map(_.range(FAKE_ORDERS_COUNT), index => { - const order = orderFactory.createOrder( - constants.NULL_ADDRESS, - constants.NULL_ADDRESS, - constants.NULL_ADDRESS, - constants.ZERO_AMOUNT, - constants.ZERO_AMOUNT, - constants.ZERO_AMOUNT, - makerAssetData, - constants.ZERO_AMOUNT, - takerAssetData, - constants.NULL_ADDRESS, - constants.NULL_ADDRESS, - ); - return { - ...order, - signature: 'dummy signature', - }; - }); - -describe('marketOrdersOptimizationUtils', () => { - const fakeMakerAssetData = 'fakeMakerAssetData'; - const fakeTakerAssetData = 'fakeTakerAssetData'; - const orders = generateFakeOrders(fakeMakerAssetData, fakeTakerAssetData); - describe('#optimizeMarketOrders', () => { - it('should make makerAssetData `0x` unless first order', () => { - const optimizedOrders = marketOrdersOptimizationUtils.optimizeMarketOrders(orders); - expect(optimizedOrders[0].makerAssetData).to.equal(fakeMakerAssetData); - const ordersWithoutHead = _.slice(optimizedOrders, 1); - _.forEach(ordersWithoutHead, order => expect(order.makerAssetData).to.equal(constants.NULL_BYTES)); - }); - it('should make all takerAssetData `0x`', () => { - const optimizedOrders = marketOrdersOptimizationUtils.optimizeMarketOrders(orders); - _.forEach(optimizedOrders, order => expect(order.takerAssetData).to.equal(constants.NULL_BYTES)); - }); - }); - describe('#optimizeFeeOrders', () => { - it('should make all makerAssetData `0x`', () => { - const optimizedOrders = marketOrdersOptimizationUtils.optimizeFeeOrders(orders); - _.forEach(optimizedOrders, order => expect(order.makerAssetData).to.equal(constants.NULL_BYTES)); - }); - it('should make all takerAssetData `0x`', () => { - const optimizedOrders = marketOrdersOptimizationUtils.optimizeFeeOrders(orders); - _.forEach(optimizedOrders, order => expect(order.takerAssetData).to.equal(constants.NULL_BYTES)); - }); - }); -}); -- cgit v1.2.3 From 4f381ca1d9b6f8ecc232d0481d86f8ba695f7601 Mon Sep 17 00:00:00 2001 From: Brandon Millman Date: Fri, 3 Aug 2018 15:47:19 -0400 Subject: Update orderFactory interface --- .../contract-wrappers/test/calldata_optimization_utils_test.ts | 10 ++-------- 1 file changed, 2 insertions(+), 8 deletions(-) (limited to 'packages/contract-wrappers') diff --git a/packages/contract-wrappers/test/calldata_optimization_utils_test.ts b/packages/contract-wrappers/test/calldata_optimization_utils_test.ts index 107d913ba..a4cea772f 100644 --- a/packages/contract-wrappers/test/calldata_optimization_utils_test.ts +++ b/packages/contract-wrappers/test/calldata_optimization_utils_test.ts @@ -3,12 +3,11 @@ import * as chai from 'chai'; import * as _ from 'lodash'; import 'mocha'; -import { constants } from '../src/utils/constants'; +import { assert } from '../src/utils/assert'; import { calldataOptimizationUtils } from '../src/utils/calldata_optimization_utils'; +import { constants } from '../src/utils/constants'; import { chaiSetup } from './utils/chai_setup'; -import { assert } from '../src/utils/assert'; -import { NULL_BYTES } from '@0xproject/utils'; chaiSetup.configure(); const expect = chai.expect; @@ -20,16 +19,11 @@ const generateFakeOrders = (makerAssetData: string, takerAssetData: string) => _.map(_.range(FAKE_ORDERS_COUNT), index => { const order = orderFactory.createOrder( constants.NULL_ADDRESS, - constants.NULL_ADDRESS, - constants.NULL_ADDRESS, - constants.ZERO_AMOUNT, - constants.ZERO_AMOUNT, constants.ZERO_AMOUNT, makerAssetData, constants.ZERO_AMOUNT, takerAssetData, constants.NULL_ADDRESS, - constants.NULL_ADDRESS, ); return { ...order, -- cgit v1.2.3 From d00ee5df0d861e15e258e6747bec4af3284205b2 Mon Sep 17 00:00:00 2001 From: Brandon Millman Date: Fri, 3 Aug 2018 15:58:17 -0400 Subject: Fix CHANGELOGs --- packages/contract-wrappers/CHANGELOG.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'packages/contract-wrappers') diff --git a/packages/contract-wrappers/CHANGELOG.json b/packages/contract-wrappers/CHANGELOG.json index d95c99a25..02e1acf91 100644 --- a/packages/contract-wrappers/CHANGELOG.json +++ b/packages/contract-wrappers/CHANGELOG.json @@ -1,6 +1,6 @@ [ { - "version": "1.1.0-rc.2", + "version": "1.0.1-rc.3", "changes": [ { "note": "Add ForwarderWrapper", -- cgit v1.2.3 From 6e2e658162a5a128b722ba105f92fa5267c4bd62 Mon Sep 17 00:00:00 2001 From: Alex Browne Date: Wed, 8 Aug 2018 11:27:38 -0700 Subject: Update TypeScript to version 2.9.2 --- packages/contract-wrappers/package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'packages/contract-wrappers') diff --git a/packages/contract-wrappers/package.json b/packages/contract-wrappers/package.json index f27afaba9..64de5b0c2 100644 --- a/packages/contract-wrappers/package.json +++ b/packages/contract-wrappers/package.json @@ -68,7 +68,7 @@ "sinon": "^4.0.0", "source-map-support": "^0.5.0", "tslint": "5.11.0", - "typescript": "2.7.1", + "typescript": "2.9.2", "web3-provider-engine": "14.0.6" }, "dependencies": { -- cgit v1.2.3 From 44d909c0c789a5b3fba2393746593d39c0ed1df7 Mon Sep 17 00:00:00 2001 From: Alex Browne Date: Wed, 8 Aug 2018 14:54:35 -0700 Subject: Update CHANGELOG.json for contract-wrappers --- packages/contract-wrappers/CHANGELOG.json | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'packages/contract-wrappers') diff --git a/packages/contract-wrappers/CHANGELOG.json b/packages/contract-wrappers/CHANGELOG.json index 02e1acf91..fb077ce73 100644 --- a/packages/contract-wrappers/CHANGELOG.json +++ b/packages/contract-wrappers/CHANGELOG.json @@ -2,6 +2,10 @@ { "version": "1.0.1-rc.3", "changes": [ + { + "pr": 915, + "note": "Added strict encoding/decoding checks for sendTransaction and call" + }, { "note": "Add ForwarderWrapper", "pr": 934 -- cgit v1.2.3 From f3761af5678503320b7a3e989a743b847ef4245f Mon Sep 17 00:00:00 2001 From: Alex Browne Date: Thu, 9 Aug 2018 11:33:32 -0700 Subject: fix: Update dependencies --- packages/contract-wrappers/package.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'packages/contract-wrappers') diff --git a/packages/contract-wrappers/package.json b/packages/contract-wrappers/package.json index 64de5b0c2..b9ce21552 100644 --- a/packages/contract-wrappers/package.json +++ b/packages/contract-wrappers/package.json @@ -60,7 +60,7 @@ "copyfiles": "^1.2.0", "dirty-chai": "^2.0.1", "make-promises-safe": "^1.1.0", - "mocha": "^4.0.1", + "mocha": "^4.1.0", "npm-run-all": "^4.1.2", "nyc": "^11.0.1", "opn-cli": "^3.1.0", @@ -86,7 +86,7 @@ "ethereumjs-util": "^5.1.1", "ethers": "3.0.22", "js-sha3": "^0.7.0", - "lodash": "^4.17.4", + "lodash": "^4.17.5", "uuid": "^3.1.0" }, "publishConfig": { -- cgit v1.2.3 From 713f285f37a8d897d87b8a5ed835d25d7c4d6fe5 Mon Sep 17 00:00:00 2001 From: fragosti Date: Thu, 9 Aug 2018 16:22:20 -0700 Subject: fix contract-wrappers json-schemas --- .../schemas/contract_wrappers_private_network_config_schema.ts | 10 +++++----- .../schemas/contract_wrappers_public_network_config_schema.ts | 10 +++++----- packages/contract-wrappers/src/schemas/method_opts_schema.ts | 2 +- packages/contract-wrappers/src/schemas/tx_opts_schema.ts | 2 +- 4 files changed, 12 insertions(+), 12 deletions(-) (limited to 'packages/contract-wrappers') diff --git a/packages/contract-wrappers/src/schemas/contract_wrappers_private_network_config_schema.ts b/packages/contract-wrappers/src/schemas/contract_wrappers_private_network_config_schema.ts index 7e2eca61c..904690ae7 100644 --- a/packages/contract-wrappers/src/schemas/contract_wrappers_private_network_config_schema.ts +++ b/packages/contract-wrappers/src/schemas/contract_wrappers_private_network_config_schema.ts @@ -5,11 +5,11 @@ export const contractWrappersPrivateNetworkConfigSchema = { type: 'number', minimum: 1, }, - gasPrice: { $ref: '/Number' }, - zrxContractAddress: { $ref: '/Address' }, - exchangeContractAddress: { $ref: '/Address' }, - erc20ProxyContractAddress: { $ref: '/Address' }, - erc721ProxyContractAddress: { $ref: '/Address' }, + gasPrice: { $ref: '/numberSchema' }, + zrxContractAddress: { $ref: '/addressSchema' }, + exchangeContractAddress: { $ref: '/addressSchema' }, + erc20ProxyContractAddress: { $ref: '/addressSchema' }, + erc721ProxyContractAddress: { $ref: '/addressSchema' }, blockPollingIntervalMs: { type: 'number' }, orderWatcherConfig: { type: 'object', diff --git a/packages/contract-wrappers/src/schemas/contract_wrappers_public_network_config_schema.ts b/packages/contract-wrappers/src/schemas/contract_wrappers_public_network_config_schema.ts index b80e04310..5cd008ae0 100644 --- a/packages/contract-wrappers/src/schemas/contract_wrappers_public_network_config_schema.ts +++ b/packages/contract-wrappers/src/schemas/contract_wrappers_public_network_config_schema.ts @@ -19,11 +19,11 @@ export const contractWrappersPublicNetworkConfigSchema = { networkNameToId.ganache, ], }, - gasPrice: { $ref: '/Number' }, - zrxContractAddress: { $ref: '/Address' }, - exchangeContractAddress: { $ref: '/Address' }, - erc20ProxyContractAddress: { $ref: '/Address' }, - erc721ProxyContractAddress: { $ref: '/Address' }, + gasPrice: { $ref: '/numberSchema' }, + zrxContractAddress: { $ref: '/addressSchema' }, + exchangeContractAddress: { $ref: '/addressSchema' }, + erc20ProxyContractAddress: { $ref: '/addressSchema' }, + erc721ProxyContractAddress: { $ref: '/addressSchema' }, blockPollingIntervalMs: { type: 'number' }, orderWatcherConfig: { type: 'object', diff --git a/packages/contract-wrappers/src/schemas/method_opts_schema.ts b/packages/contract-wrappers/src/schemas/method_opts_schema.ts index ef434070a..83003f818 100644 --- a/packages/contract-wrappers/src/schemas/method_opts_schema.ts +++ b/packages/contract-wrappers/src/schemas/method_opts_schema.ts @@ -1,7 +1,7 @@ export const methodOptsSchema = { id: '/MethodOpts', properties: { - defaultBlock: { $ref: '/BlockParam' }, + defaultBlock: { $ref: '/blockParamSchema' }, }, type: 'object', }; diff --git a/packages/contract-wrappers/src/schemas/tx_opts_schema.ts b/packages/contract-wrappers/src/schemas/tx_opts_schema.ts index bddc33b6c..83c819be2 100644 --- a/packages/contract-wrappers/src/schemas/tx_opts_schema.ts +++ b/packages/contract-wrappers/src/schemas/tx_opts_schema.ts @@ -1,7 +1,7 @@ export const txOptsSchema = { id: '/TxOpts', properties: { - gasPrice: { $ref: '/Number' }, + gasPrice: { $ref: '/numberSchema' }, gasLimit: { type: 'number' }, }, type: 'object', -- cgit v1.2.3 From 7c8a7a24209ae518d7a7d3c45829d75d224ce3a3 Mon Sep 17 00:00:00 2001 From: Alex Browne Date: Mon, 13 Aug 2018 18:34:37 -0700 Subject: Updated CHANGELOGS --- packages/contract-wrappers/CHANGELOG.json | 3 ++- packages/contract-wrappers/CHANGELOG.md | 8 +++++++- 2 files changed, 9 insertions(+), 2 deletions(-) (limited to 'packages/contract-wrappers') diff --git a/packages/contract-wrappers/CHANGELOG.json b/packages/contract-wrappers/CHANGELOG.json index fb077ce73..fdf779338 100644 --- a/packages/contract-wrappers/CHANGELOG.json +++ b/packages/contract-wrappers/CHANGELOG.json @@ -14,7 +14,8 @@ "note": "Optimize orders in ForwarderWrapper", "pr": 936 } - ] + ], + "timestamp": 1534210131 }, { "version": "1.0.1-rc.2", diff --git a/packages/contract-wrappers/CHANGELOG.md b/packages/contract-wrappers/CHANGELOG.md index 8a981d371..c2ad7218e 100644 --- a/packages/contract-wrappers/CHANGELOG.md +++ b/packages/contract-wrappers/CHANGELOG.md @@ -5,6 +5,12 @@ Edit the package's CHANGELOG.json file only. CHANGELOG +## v1.0.1-rc.3 - _August 13, 2018_ + + * Added strict encoding/decoding checks for sendTransaction and call (#915) + * Add ForwarderWrapper (#934) + * Optimize orders in ForwarderWrapper (#936) + ## v1.0.1-rc.2 - _July 26, 2018_ * Fixed bug caused by importing non-existent dep @@ -17,7 +23,7 @@ CHANGELOG * Dependencies updated -## v1.0.0-rc.1 - _July 20, 2018_ +## v1.0.0-rc.1 - _July 19, 2018_ * Update blockstream to v5.0 and propogate up caught errors to active subscriptions (#815) * Update to v2 of 0x rpotocol (#822) -- cgit v1.2.3 From fadd292ecf367e42154856509d0ea0c20b23f2f1 Mon Sep 17 00:00:00 2001 From: Alex Browne Date: Mon, 13 Aug 2018 18:34:51 -0700 Subject: Publish - 0x.js@1.0.1-rc.3 - @0xproject/abi-gen@1.0.5 - @0xproject/assert@1.0.5 - @0xproject/base-contract@2.0.0-rc.1 - @0xproject/connect@1.0.5 - @0xproject/contract-wrappers@1.0.1-rc.3 - contracts@2.1.40 - @0xproject/dev-utils@1.0.4 - ethereum-types@1.0.4 - @0xproject/fill-scenarios@1.0.1-rc.3 - @0xproject/json-schemas@1.0.1-rc.4 - @0xproject/metacoin@0.0.15 - @0xproject/migrations@1.0.4 - @0xproject/monorepo-scripts@1.0.5 - @0xproject/order-utils@1.0.1-rc.3 - @0xproject/order-watcher@1.0.1-rc.3 - @0xproject/react-docs@1.0.5 - @0xproject/react-docs-example@0.0.20 - @0xproject/react-shared@1.0.6 - @0xproject/sol-compiler@1.0.5 - @0xproject/sol-cov@2.0.0 - @0xproject/sol-resolver@1.0.5 - @0xproject/sra-api@1.0.1-rc.4 - @0xproject/sra-report@1.0.5 - @0xproject/subproviders@1.0.5 - @0xproject/testnet-faucets@1.0.41 - @0xproject/tslint-config@1.0.5 - @0xproject/types@1.0.1-rc.4 - @0xproject/typescript-typings@1.0.4 - @0xproject/utils@1.0.5 - @0xproject/web3-wrapper@1.2.0 - @0xproject/website@0.0.44 --- packages/contract-wrappers/package.json | 36 ++++++++++++++++----------------- 1 file changed, 18 insertions(+), 18 deletions(-) (limited to 'packages/contract-wrappers') diff --git a/packages/contract-wrappers/package.json b/packages/contract-wrappers/package.json index b9ce21552..7667b5b7f 100644 --- a/packages/contract-wrappers/package.json +++ b/packages/contract-wrappers/package.json @@ -1,6 +1,6 @@ { "name": "@0xproject/contract-wrappers", - "version": "1.0.1-rc.2", + "version": "1.0.1-rc.3", "description": "Smart TS wrappers for 0x smart contracts", "keywords": [ "0xproject", @@ -41,13 +41,13 @@ "node": ">=6.0.0" }, "devDependencies": { - "@0xproject/abi-gen": "^1.0.4", - "@0xproject/dev-utils": "^1.0.3", - "@0xproject/migrations": "^1.0.3", - "@0xproject/monorepo-scripts": "^1.0.4", - "@0xproject/sol-compiler": "^1.0.4", - "@0xproject/subproviders": "^1.0.4", - "@0xproject/tslint-config": "^1.0.4", + "@0xproject/abi-gen": "^1.0.5", + "@0xproject/dev-utils": "^1.0.4", + "@0xproject/migrations": "^1.0.4", + "@0xproject/monorepo-scripts": "^1.0.5", + "@0xproject/sol-compiler": "^1.0.5", + "@0xproject/subproviders": "^1.0.5", + "@0xproject/tslint-config": "^1.0.5", "@types/lodash": "4.14.104", "@types/mocha": "^2.2.42", "@types/node": "^8.0.53", @@ -72,16 +72,16 @@ "web3-provider-engine": "14.0.6" }, "dependencies": { - "@0xproject/assert": "^1.0.4", - "@0xproject/base-contract": "^1.0.4", - "@0xproject/fill-scenarios": "^1.0.1-rc.2", - "@0xproject/json-schemas": "^1.0.1-rc.3", - "@0xproject/order-utils": "^1.0.1-rc.2", - "@0xproject/types": "^1.0.1-rc.3", - "@0xproject/typescript-typings": "^1.0.3", - "@0xproject/utils": "^1.0.4", - "@0xproject/web3-wrapper": "^1.1.2", - "ethereum-types": "^1.0.3", + "@0xproject/assert": "^1.0.5", + "@0xproject/base-contract": "^2.0.0-rc.1", + "@0xproject/fill-scenarios": "^1.0.1-rc.3", + "@0xproject/json-schemas": "^1.0.1-rc.4", + "@0xproject/order-utils": "^1.0.1-rc.3", + "@0xproject/types": "^1.0.1-rc.4", + "@0xproject/typescript-typings": "^1.0.4", + "@0xproject/utils": "^1.0.5", + "@0xproject/web3-wrapper": "^1.2.0", + "ethereum-types": "^1.0.4", "ethereumjs-blockstream": "5.0.0", "ethereumjs-util": "^5.1.1", "ethers": "3.0.22", -- cgit v1.2.3