Merge branch 'master' into wrap-log-bignumber

This commit is contained in:
Leonid
2017-07-03 14:31:40 -07:00
committed by GitHub
25 changed files with 685 additions and 244 deletions

View File

@@ -1,5 +1,10 @@
# CHANGELOG
v0.7.2 - _Jun. 26, 2017_
------------------------
* Add the ability to call methods on different authorized versions of the Exchange smart contract (#82)
* Update contract artifacts to reflect latest changes to the smart contracts (0xproject/contracts#59)
v0.7.1 - _Jun. 26, 2017_
------------------------
* Add the ability to convert Ether to wrapped Ether tokens and back via `zeroEx.etherToken.depostAsync` and `zeroEx.etherToken.withdrawAsync` (#81)

View File

@@ -8,7 +8,6 @@ test:
background: true
- git clone git@github.com:0xProject/contracts.git ../contracts
- cd ../contracts; git checkout cd04d7c; npm install && npm run migrate
- npm run update_contracts
- npm run test:coverage
- npm run report_test_coverage
- npm run test:umd

View File

@@ -32,7 +32,7 @@
"build:dev": "npm run clean && run-p build:*:dev",
"build:umd:dev": "webpack",
"build:umd:prod": "NODE_ENV=production webpack",
"build:commonjs:dev": "tsc; copyfiles -u 2 ./src/artifacts/*.json ../0x.js/lib/src/artifacts;",
"build:commonjs:dev": "tsc; copyfiles -u 2 './src/artifacts/**/*.json' ./lib/src/artifacts;",
"test:commonjs": "run-s build:commonjs:dev run_mocha",
"pretest:umd": "run-s clean build:*:dev",
"substitute_umd_bundle": "npm run remove_src_files_not_used_by_tests; shx mv _bundles/* lib/src",
@@ -61,14 +61,14 @@
"awesome-typescript-loader": "^3.1.3",
"bignumber.js": "^4.0.2",
"chai": "^4.0.1",
"chai-as-promised": "^6.0.0",
"chai-as-promised": "^7.1.0",
"chai-as-promised-typescript-typings": "0.0.3",
"chai-bignumber": "0xProject/chai-bignumber",
"chai-typescript-typings": "^0.0.0",
"copyfiles": "^1.2.0",
"coveralls": "^2.13.1",
"dirty-chai": "^1.2.2",
"ethereumjs-testrpc": "3.0.5",
"ethereumjs-testrpc": "4.0.1",
"json-loader": "^0.5.4",
"mocha": "^3.4.1",
"npm-run-all": "^4.0.2",

View File

@@ -15,8 +15,8 @@ import {TokenRegistryWrapper} from './contract_wrappers/token_registry_wrapper';
import {EtherTokenWrapper} from './contract_wrappers/ether_token_wrapper';
import {ecSignatureSchema} from './schemas/ec_signature_schema';
import {TokenWrapper} from './contract_wrappers/token_wrapper';
import {ProxyWrapper} from './contract_wrappers/proxy_wrapper';
import {ECSignature, ZeroExError, Order, SignedOrder, Web3Provider} from './types';
import * as ExchangeArtifacts from './artifacts/Exchange.json';
import {orderSchema} from './schemas/order_schemas';
// Customize our BigNumber instances
@@ -52,6 +52,7 @@ export class ZeroEx {
* wrapped ETH ERC20 token smart contract.
*/
public etherToken: EtherTokenWrapper;
private _proxyWrapper: ProxyWrapper;
private _web3Wrapper: Web3Wrapper;
/**
* Verifies that the elliptic curve signature `signature` was generated
@@ -149,7 +150,8 @@ export class ZeroEx {
constructor(provider: Web3Provider) {
this._web3Wrapper = new Web3Wrapper(provider);
this.token = new TokenWrapper(this._web3Wrapper);
this.exchange = new ExchangeWrapper(this._web3Wrapper, this.token);
this._proxyWrapper = new ProxyWrapper(this._web3Wrapper);
this.exchange = new ExchangeWrapper(this._web3Wrapper, this.token, this._proxyWrapper);
this.tokenRegistry = new TokenRegistryWrapper(this._web3Wrapper);
this.etherToken = new EtherTokenWrapper(this._web3Wrapper, this.token);
}
@@ -160,9 +162,10 @@ export class ZeroEx {
*/
public async setProviderAsync(provider: Web3Provider) {
this._web3Wrapper.setProvider(provider);
await this.exchange.invalidateContractInstanceAsync();
await this.exchange.invalidateContractInstancesAsync();
this.tokenRegistry.invalidateContractInstance();
this.token.invalidateContractInstances();
this._proxyWrapper.invalidateContractInstance();
}
/**
* Get user Ethereum addresses available through the supplied web3 instance available for sending transactions.
@@ -177,11 +180,9 @@ export class ZeroEx {
* @param order An object that conforms to the Order or SignedOrder interface definitions.
* @return The resulting orderHash from hashing the supplied order.
*/
public async getOrderHashHexAsync(order: Order|SignedOrder): Promise<string> {
public getOrderHashHex(order: Order|SignedOrder): string {
assert.doesConformToSchema('order', order, orderSchema);
const exchangeContractAddr = await this._getExchangeAddressAsync();
const orderHashHex = utils.getOrderHashHex(order, exchangeContractAddr);
const orderHashHex = utils.getOrderHashHex(order);
return orderHashHex;
}
/**
@@ -199,8 +200,9 @@ export class ZeroEx {
let msgHashHex;
const nodeVersion = await this._web3Wrapper.getNodeVersionAsync();
const isParityNode = utils.isParityNode(nodeVersion);
if (isParityNode) {
// Parity node adds the personalMessage prefix itself
const isTestRpc = utils.isTestRpc(nodeVersion);
if (isParityNode || isTestRpc) {
// Parity and TestRpc nodes add the personalMessage prefix itself
msgHashHex = orderHash;
} else {
const orderHashBuff = ethUtil.toBuffer(orderHash);
@@ -244,15 +246,4 @@ export class ZeroEx {
}
return ecSignature;
}
private async _getExchangeAddressAsync() {
const networkIdIfExists = await this._web3Wrapper.getNetworkIdIfExistsAsync();
const exchangeNetworkConfigsIfExists = _.isUndefined(networkIdIfExists) ?
undefined :
(ExchangeArtifacts as any).networks[networkIdIfExists];
if (_.isUndefined(exchangeNetworkConfigsIfExists)) {
throw new Error(ZeroExError.CONTRACT_NOT_DEPLOYED_ON_NETWORK);
}
const exchangeAddress = exchangeNetworkConfigsIfExists.address;
return exchangeAddress;
}
}

View File

@@ -229,7 +229,7 @@
"type": "event"
}
],
"unlinked_binary": "0x606060405234610000575b61072d806100196000396000f300606060405236156100935763ffffffff60e060020a60003504166306fdde038114610098578063095ea7b31461012557806318160ddd1461015557806323b872dd146101745780632e1a7d4d146101aa578063313ce567146101bc57806370a08231146101df57806395d89b411461020a578063a9059cbb14610297578063d0e30db0146102c7578063dd62ed3e146102d1575b610000565b34610000576100a5610302565b6040805160208082528351818301528351919283929083019185019080838382156100eb575b8051825260208311156100eb57601f1990920191602091820191016100cb565b505050905090810190601f1680156101175780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b3461000057610141600160a060020a0360043516602435610339565b604080519115158252519081900360200190f35b34610000576101626103a4565b60408051918252519081900360200190f35b3461000057610141600160a060020a03600435811690602435166044356103aa565b604080519115158252519081900360200190f35b34610000576101ba6004356104a7565b005b34610000576101c9610527565b6040805160ff9092168252519081900360200190f35b3461000057610162600160a060020a036004351661052c565b60408051918252519081900360200190f35b34610000576100a561054b565b6040805160208082528351818301528351919283929083019185019080838382156100eb575b8051825260208311156100eb57601f1990920191602091820191016100cb565b505050905090810190601f1680156101175780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b3461000057610141600160a060020a0360043516602435610582565b604080519115158252519081900360200190f35b6101ba610634565b005b3461000057610162600160a060020a0360043581169060243516610683565b60408051918252519081900360200190f35b60408051808201909152600b81527f457468657220546f6b656e000000000000000000000000000000000000000000602082015281565b600160a060020a03338116600081815260016020908152604080832094871680845294825280832086905580518681529051929493927f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925929181900390910190a35060015b92915050565b60025481565b600160a060020a0383166000908152602081905260408120546103cd90836106b0565b600160a060020a03808616600090815260208181526040808320949094556001815283822033909316825291909152205461040890836106b0565b600160a060020a0380861660009081526001602090815260408083203385168452825280832094909455918616815290819052205461044790836106c9565b600160a060020a038085166000818152602081815260409182902094909455805186815290519193928816927fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef92918290030190a35060015b9392505050565b600160a060020a0333166000908152602081905260409020546104ca90826106b0565b600160a060020a0333166000908152602081905260409020556002546104f090826106b0565b600255604051600160a060020a0333169082156108fc029083906000818181858888f19350505050151561052357610000565b5b50565b601281565b600160a060020a0381166000908152602081905260409020545b919050565b60408051808201909152600481527f5745544800000000000000000000000000000000000000000000000000000000602082015281565b600160a060020a0333166000908152602081905260408120546105a590836106b0565b600160a060020a0333811660009081526020819052604080822093909355908516815220546105d490836106c9565b600160a060020a03808516600081815260208181526040918290209490945580518681529051919333909316927fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef92918290030190a35060015b92915050565b600160a060020a03331660009081526020819052604090205461065790346106c9565b600160a060020a03331660009081526020819052604090205560025461067d90346106c9565b6002555b565b600160a060020a038083166000908152600160209081526040808320938516835292905220545b92915050565b60006106be838311156106f1565b508082035b92915050565b60008282016106e68482108015906106e15750838210155b6106f1565b8091505b5092915050565b80151561052357610000565b5b505600a165627a7a72305820c7cc457bf87c8b3047275eaa71935a1612af007e4bc77d832c588245805374480029",
"unlinked_binary": "0x6060604052341561000c57fe5b5b6107218061001c6000396000f300606060405236156100935763ffffffff60e060020a60003504166306fdde038114610095578063095ea7b31461012557806318160ddd1461015857806323b872dd1461017a5780632e1a7d4d146101b3578063313ce567146101c857806370a08231146101ee57806395d89b411461021c578063a9059cbb146102ac578063d0e30db0146102df578063dd62ed3e146102e9575bfe5b341561009d57fe5b6100a561031d565b6040805160208082528351818301528351919283929083019185019080838382156100eb575b8051825260208311156100eb57601f1990920191602091820191016100cb565b505050905090810190601f1680156101175780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b341561012d57fe5b610144600160a060020a0360043516602435610345565b604080519115158252519081900360200190f35b341561016057fe5b6101686103b0565b60408051918252519081900360200190f35b341561018257fe5b610144600160a060020a03600435811690602435166044356103b6565b604080519115158252519081900360200190f35b34156101bb57fe5b6101c66004356104a1565b005b34156101d057fe5b6101d8610522565b6040805160ff9092168252519081900360200190f35b34156101f657fe5b610168600160a060020a0360043516610527565b60408051918252519081900360200190f35b341561022457fe5b6100a5610546565b6040805160208082528351818301528351919283929083019185019080838382156100eb575b8051825260208311156100eb57601f1990920191602091820191016100cb565b505050905090810190601f1680156101175780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b34156102b457fe5b610144600160a060020a0360043516602435610567565b604080519115158252519081900360200190f35b6101c6610607565b005b34156102f157fe5b610168600160a060020a0360043581169060243516610656565b60408051918252519081900360200190f35b60408051808201909152600b815260a960020a6a22ba3432b9102a37b5b2b702602082015281565b600160a060020a03338116600081815260016020908152604080832094871680845294825280832086905580518681529051929493927f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925929181900390910190a35060015b92915050565b60025481565b600160a060020a0383166000908152602081905260408120546103d99083610683565b600160a060020a0380861660009081526020818152604080832094909455600181528382203390931682529190915220546104149083610683565b600160a060020a03808616600090815260016020908152604080832033851684528252808320949094559186168152908190522054610453908361069c565b600160a060020a038085166000818152602081815260409182902094909455805186815290519193928816926000805160206106d683398151915292918290030190a35060015b9392505050565b600160a060020a0333166000908152602081905260409020546104c49082610683565b600160a060020a0333166000908152602081905260409020556002546104ea9082610683565b600255604051600160a060020a0333169082156108fc029083906000818181858888f19350505050151561051e5760006000fd5b5b50565b601281565b600160a060020a0381166000908152602081905260409020545b919050565b604080518082019091526004815260e360020a630ae8aa8902602082015281565b600160a060020a03331660009081526020819052604081205461058a9083610683565b600160a060020a0333811660009081526020819052604080822093909355908516815220546105b9908361069c565b600160a060020a03808516600081815260208181526040918290209490945580518681529051919333909316926000805160206106d683398151915292918290030190a35060015b92915050565b600160a060020a03331660009081526020819052604090205461062a903461069c565b600160a060020a033316600090815260208190526040902055600254610650903461069c565b6002555b565b600160a060020a038083166000908152600160209081526040808320938516835292905220545b92915050565b6000610691838311156106c4565b508082035b92915050565b60008282016106b98482108015906106b45750838210155b6106c4565b8091505b5092915050565b80151561051e5760006000fd5b5b505600ddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3efa165627a7a72305820d39a3d758ea0042048564f60b0e39c59508468d4de91cd9b7b5f708b554f699c0029",
"networks": {
"42": {
"links": {},
@@ -330,10 +330,10 @@
"type": "event"
}
},
"updated_at": 1495030736786,
"updated_at": 1498588231356,
"address": "0x48bacb9266a570d521063ef5dd96e61686dbe788"
}
},
"schema_version": "0.0.5",
"updated_at": 1496294576956
"updated_at": 1498588231356
}

View File

@@ -182,8 +182,8 @@
"type": "event"
}
],
"unlinked_binary": "0x606060405234610000575b6104e7806100196000396000f300606060405236156100675763ffffffff60e060020a600035041663095ea7b3811461006c57806318160ddd1461009c57806323b872dd146100bb57806370a08231146100f1578063a0712d681461011c578063a9059cbb1461012e578063dd62ed3e1461015e575b610000565b3461000057610088600160a060020a036004351660243561018f565b604080519115158252519081900360200190f35b34610000576100a96101fa565b60408051918252519081900360200190f35b3461000057610088600160a060020a0360043581169060243516604435610200565b604080519115158252519081900360200190f35b34610000576100a9600160a060020a036004351661030d565b60408051918252519081900360200190f35b346100005761012c60043561032c565b005b3461000057610088600160a060020a0360043516602435610393565b604080519115158252519081900360200190f35b34610000576100a9600160a060020a0360043581169060243516610456565b60408051918252519081900360200190f35b600160a060020a03338116600081815260016020908152604080832094871680845294825280832086905580518681529051929493927f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925929181900390910190a35060015b92915050565b60025481565b600160a060020a0383166000908152602081905260408120548290108015906102505750600160a060020a0380851660009081526001602090815260408083203390941683529290522054829010155b80156102755750600160a060020a038316600090815260208190526040902054828101115b1561030157600160a060020a0380841660008181526020818152604080832080548801905588851680845281842080548990039055600183528184203390961684529482529182902080548790039055815186815291519293927fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef9281900390910190a3506001610305565b5060005b5b9392505050565b600160a060020a0381166000908152602081905260409020545b919050565b68056bc75e2d6310000081111561034257610000565b600160a060020a033316600090815260208190526040902054610366908290610483565b600160a060020a03331660009081526020819052604090205560025461038c9082610483565b6002555b50565b600160a060020a0333166000908152602081905260408120548290108015906103d55750600160a060020a038316600090815260208190526040902054828101115b1561044757600160a060020a0333811660008181526020818152604080832080548890039055938716808352918490208054870190558351868152935191937fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef929081900390910190a35060016101f4565b5060006101f4565b5b92915050565b600160a060020a038083166000908152600160209081526040808320938516835292905220545b92915050565b60008282016104a084821080159061049b5750838210155b6104ab565b8091505b5092915050565b80151561039057610000565b5b505600a165627a7a723058204789b7d0fd9aae8d16b771c1b12c5863cfa8aaef739d2d811f91e447ee450bce0029",
"unlinked_binary": "0x6060604052341561000c57fe5b5b6104f78061001c6000396000f300606060405236156100675763ffffffff60e060020a600035041663095ea7b3811461006957806318160ddd1461009c57806323b872dd146100be57806370a08231146100f7578063a0712d6814610125578063a9059cbb1461013a578063dd62ed3e1461016d575bfe5b341561007157fe5b610088600160a060020a03600435166024356101a1565b604080519115158252519081900360200190f35b34156100a457fe5b6100ac61020c565b60408051918252519081900360200190f35b34156100c657fe5b610088600160a060020a0360043581169060243516604435610212565b604080519115158252519081900360200190f35b34156100ff57fe5b6100ac600160a060020a036004351661030d565b60408051918252519081900360200190f35b341561012d57fe5b61013860043561032c565b005b341561014257fe5b610088600160a060020a0360043516602435610394565b604080519115158252519081900360200190f35b341561017557fe5b6100ac600160a060020a0360043581169060243516610445565b60408051918252519081900360200190f35b600160a060020a03338116600081815260016020908152604080832094871680845294825280832086905580518681529051929493927f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925929181900390910190a35060015b92915050565b60025481565b600160a060020a0383166000908152602081905260408120548290108015906102625750600160a060020a0380851660009081526001602090815260408083203390941683529290522054829010155b80156102875750600160a060020a038316600090815260208190526040902054828101115b1561030157600160a060020a0380841660008181526020818152604080832080548801905588851680845281842080548990039055600183528184203390961684529482529182902080548790039055815186815291519293926000805160206104ac8339815191529281900390910190a3506001610305565b5060005b5b9392505050565b600160a060020a0381166000908152602081905260409020545b919050565b68056bc75e2d631000008111156103435760006000fd5b600160a060020a033316600090815260208190526040902054610367908290610472565b600160a060020a03331660009081526020819052604090205560025461038d9082610472565b6002555b50565b600160a060020a0333166000908152602081905260408120548290108015906103d65750600160a060020a038316600090815260208190526040902054828101115b1561043657600160a060020a0333811660008181526020818152604080832080548890039055938716808352918490208054870190558351868152935191936000805160206104ac833981519152929081900390910190a3506001610206565b506000610206565b5b92915050565b600160a060020a038083166000908152600160209081526040808320938516835292905220545b92915050565b600082820161048f84821080159061048a5750838210155b61049a565b8091505b5092915050565b8015156103915760006000fd5b5b505600ddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3efa165627a7a7230582017b556a0dd152ca0b949c108d1e5479ccafa38c1a952572dde1d45dab72f113b0029",
"networks": {},
"schema_version": "0.0.5",
"updated_at": 1496294434244
"updated_at": 1498588228068
}

View File

@@ -177,7 +177,7 @@
"type": "event"
}
],
"unlinked_binary": "0x60606040525b60008054600160a060020a03191633600160a060020a03161790555b5b610701806100316000396000f300606060405236156100725763ffffffff60e060020a60003504166315dacbea811461007757806342f1181e146100b3578063494503d4146100e0578063707129391461010c5780638da5cb5b14610139578063b918161114610162578063d39de6e91461018f578063f2fde38b146101f7575b610000565b346100005761009f600160a060020a0360043581169060243581169060443516606435610212565b604080519115158252519081900360200190f35b346100005761009f600160a060020a03600435166102d8565b604080519115158252519081900360200190f35b34610000576100f06004356103f5565b60408051600160a060020a039092168252519081900360200190f35b346100005761009f600160a060020a0360043516610425565b604080519115158252519081900360200190f35b34610000576100f06105ee565b60408051600160a060020a039092168252519081900360200190f35b346100005761009f600160a060020a03600435166105fd565b604080519115158252519081900360200190f35b346100005761019c610612565b60408051602080825283518183015283519192839290830191858101910280838382156101e4575b8051825260208311156101e457601f1990920191602091820191016101c4565b5050509050019250505060405180910390f35b3461000057610210600160a060020a036004351661067d565b005b600160a060020a03331660009081526001602052604081205460ff16151561023957610000565b604080516000602091820181905282517f23b872dd000000000000000000000000000000000000000000000000000000008152600160a060020a0388811660048301528781166024830152604482018790529351938916936323b872dd9360648084019491938390030190829087803b156100005760325a03f11561000057505060405151151590506102cb57610000565b5060015b5b949350505050565b6000805433600160a060020a039081169116146102f457610000565b600160a060020a038216600090815260016020526040902054829060ff161561031c57610000565b600160a060020a0383166000908152600160208190526040909120805460ff191682179055600280549182018082559091908281838015829011610385576000838152602090206103859181019083015b80821115610381576000815560010161036d565b5090565b5b505050916000526020600020900160005b81546101009190910a600160a060020a0381810219909216878316918202179092556040513390911692507f94bb87f4c15c4587ff559a7584006fa01ddf9299359be6b512b94527aa961aca90600090a3600191505b5b505b919050565b600281815481101561000057906000526020600020900160005b915054906101000a9004600160a060020a031681565b60008054819033600160a060020a0390811691161461044357610000565b600160a060020a038316600090815260016020526040902054839060ff16151561046c57610000565b600160a060020a0384166000908152600160205260408120805460ff1916905591505b6002548210156105a75783600160a060020a0316600283815481101561000057906000526020600020900160005b9054906101000a9004600160a060020a0316600160a060020a0316141561059b576002805460001981019081101561000057906000526020600020900160005b9054906101000a9004600160a060020a0316600283815481101561000057906000526020600020900160005b6101000a815481600160a060020a030219169083600160a060020a031602179055506001600281818054905003915081815481835581811511610591576000838152602090206105919181019083015b80821115610381576000815560010161036d565b5090565b5b505050506105a7565b5b60019091019061048f565b604051600160a060020a0333811691908616907ff5b347a1e40749dd050f5f07fbdbeb7e3efa9756903044dd29401fd1d4bb4a1c90600090a3600192505b5b505b50919050565b600054600160a060020a031681565b60016020526000908152604090205460ff1681565b60408051602081810183526000825260028054845181840281018401909552808552929392909183018282801561067257602002820191906000526020600020905b8154600160a060020a03168152600190910190602001808311610654575b505050505090505b90565b60005433600160a060020a0390811691161461069857610000565b600160a060020a038116156106d0576000805473ffffffffffffffffffffffffffffffffffffffff1916600160a060020a0383161790555b5b5b505600a165627a7a72305820e094d2460f9f11db4e36cf6e7af1eb1f6fb883275fea375d814c23e81802753b0029",
"unlinked_binary": "0x60606040525b60008054600160a060020a03191633600160a060020a03161790555b5b610727806100316000396000f300606060405236156100725763ffffffff60e060020a60003504166315dacbea811461007457806342f1181e146100b3578063494503d4146100e357806370712939146101125780638da5cb5b14610142578063b91816111461016e578063d39de6e91461019e578063f2fde38b14610209575bfe5b341561007c57fe5b61009f600160a060020a0360043581169060243581169060443516606435610227565b604080519115158252519081900360200190f35b34156100bb57fe5b61009f600160a060020a03600435166102e0565b604080519115158252519081900360200190f35b34156100eb57fe5b6100f66004356103c9565b60408051600160a060020a039092168252519081900360200190f35b341561011a57fe5b61009f600160a060020a03600435166103fb565b604080519115158252519081900360200190f35b341561014a57fe5b6100f661059b565b60408051600160a060020a039092168252519081900360200190f35b341561017657fe5b61009f600160a060020a03600435166105aa565b604080519115158252519081900360200190f35b34156101a657fe5b6101ae6105bf565b60408051602080825283518183015283519192839290830191858101910280838382156101f6575b8051825260208311156101f657601f1990920191602091820191016101d6565b5050509050019250505060405180910390f35b341561021157fe5b610225600160a060020a0360043516610628565b005b600160a060020a03331660009081526001602052604081205460ff16151561024f5760006000fd5b6040805160006020918201819052825160e060020a6323b872dd028152600160a060020a0388811660048301528781166024830152604482018790529351938916936323b872dd9360648084019491938390030190829087803b15156102b157fe5b6102c65a03f115156102bf57fe5b505060405151151590506102d35760006000fd5b5060015b5b949350505050565b6000805433600160a060020a039081169116146102fd5760006000fd5b600160a060020a038216600090815260016020526040902054829060ff16156103265760006000fd5b600160a060020a0383166000908152600160208190526040909120805460ff191682179055600280549091810161035d8382610674565b916000526020600020900160005b81546101009190910a600160a060020a0381810219909216878316918202179092556040513390911692507f94bb87f4c15c4587ff559a7584006fa01ddf9299359be6b512b94527aa961aca90600090a3600191505b5b505b919050565b60028054829081106103d757fe5b906000526020600020900160005b915054906101000a9004600160a060020a031681565b60008054819033600160a060020a0390811691161461041a5760006000fd5b600160a060020a038316600090815260016020526040902054839060ff1615156104445760006000fd5b600160a060020a0384166000908152600160205260408120805460ff1916905591505b6002548210156105545783600160a060020a031660028381548110151561048a57fe5b906000526020600020900160005b9054906101000a9004600160a060020a0316600160a060020a03161415610548576002805460001981019081106104cb57fe5b906000526020600020900160005b9054906101000a9004600160a060020a03166002838154811015156104fa57fe5b906000526020600020900160005b6101000a815481600160a060020a030219169083600160a060020a0316021790555060016002818180549050039150816105429190610674565b50610554565b5b600190910190610467565b604051600160a060020a0333811691908616907ff5b347a1e40749dd050f5f07fbdbeb7e3efa9756903044dd29401fd1d4bb4a1c90600090a3600192505b5b505b50919050565b600054600160a060020a031681565b60016020526000908152604090205460ff1681565b6105c76106c8565b600280548060200260200160405190810160405280929190818152602001828054801561061d57602002820191906000526020600020905b8154600160a060020a031681526001909101906020018083116105ff575b505050505090505b90565b60005433600160a060020a039081169116146106445760006000fd5b600160a060020a0381161561066f5760008054600160a060020a031916600160a060020a0383161790555b5b5b50565b815481835581811511610698576000838152602090206106989181019083016106da565b5b505050565b815481835581811511610698576000838152602090206106989181019083016106da565b5b505050565b60408051602081019091526000815290565b61062591905b808211156106f457600081556001016106e0565b5090565b905600a165627a7a7230582021aadf834398ddc9f252eb0b3ab6ddea131aa7bca5d904d429a49ab48bcbe2910029",
"networks": {
"42": {
"links": {},
@@ -258,10 +258,10 @@
"type": "event"
}
},
"updated_at": 1495030736781,
"updated_at": 1498588231340,
"address": "0x871dd7c2b4b25e1aa18728e9d5f2af4c4e431f5c"
}
},
"schema_version": "0.0.5",
"updated_at": 1496294576942
"updated_at": 1498588231340
}

View File

@@ -169,8 +169,8 @@
"type": "event"
}
],
"unlinked_binary": "0x606060405234610000575b6101d1806100196000396000f3006060604052361561005c5763ffffffff60e060020a600035041663095ea7b3811461006157806318160ddd1461009157806323b872dd146100b057806370a08231146100e6578063a9059cbb14610061578063dd62ed3e14610141575b610000565b346100005761007d600160a060020a0360043516602435610172565b604080519115158252519081900360200190f35b346100005761009e61017b565b60408051918252519081900360200190f35b346100005761007d600160a060020a0360043581169060243516604435610181565b604080519115158252519081900360200190f35b346100005761009e600160a060020a036004351661018b565b60408051918252519081900360200190f35b346100005761007d600160a060020a0360043516602435610172565b604080519115158252519081900360200190f35b346100005761009e600160a060020a0360043581169060243516610172565b60408051918252519081900360200190f35b60005b92915050565b60005b90565b60005b9392505050565b60005b919050565b60005b92915050565b60005b929150505600a165627a7a7230582041bf388c3189085f6807945974edea68192611a83cc2920536293b220d1e7fcb0029",
"unlinked_binary": "0x6060604052341561000c57fe5b5b6101e08061001c6000396000f3006060604052361561005c5763ffffffff60e060020a600035041663095ea7b3811461005e57806318160ddd1461009157806323b872dd146100b357806370a08231146100ec578063a9059cbb1461005e578063dd62ed3e1461014d575bfe5b341561006657fe5b61007d600160a060020a0360043516602435610181565b604080519115158252519081900360200190f35b341561009957fe5b6100a161018a565b60408051918252519081900360200190f35b34156100bb57fe5b61007d600160a060020a0360043581169060243516604435610190565b604080519115158252519081900360200190f35b34156100f457fe5b6100a1600160a060020a036004351661019a565b60408051918252519081900360200190f35b341561006657fe5b61007d600160a060020a0360043516602435610181565b604080519115158252519081900360200190f35b341561015557fe5b6100a1600160a060020a0360043581169060243516610181565b60408051918252519081900360200190f35b60005b92915050565b60005b90565b60005b9392505050565b60005b919050565b60005b92915050565b60005b929150505600a165627a7a723058203c197cc1ab179269cf5d1ae1606a41063b723c0e550a2805382c9c4600ddc75e0029",
"networks": {},
"schema_version": "0.0.5",
"updated_at": 1496294434247
"updated_at": 1498588228068
}

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@@ -8,6 +8,7 @@ import {
ExchangeContract,
ExchangeContractErrCodes,
ExchangeContractErrs,
ZeroExError,
OrderValues,
OrderAddresses,
Order,
@@ -28,11 +29,14 @@ import {
LogCancelContractEventArgs,
EventCallback,
ContractEventArg,
ExchangeContractByAddress,
ContractArtifact,
} from '../types';
import {assert} from '../utils/assert';
import {utils} from '../utils/utils';
import {ContractWrapper} from './contract_wrapper';
import * as ExchangeArtifacts from '../artifacts/Exchange.json';
import {ProxyWrapper} from './proxy_wrapper';
import {ExchangeArtifactsByName} from '../exchange_artifacts_by_name';
import {ecSignatureSchema} from '../schemas/ec_signature_schema';
import {signedOrdersSchema} from '../schemas/signed_orders_schema';
import {orderFillRequestsSchema} from '../schemas/order_fill_requests_schema';
@@ -56,9 +60,10 @@ export class ExchangeWrapper extends ContractWrapper {
[ExchangeContractErrCodes.ERROR_FILL_TRUNCATION]: ExchangeContractErrs.ORDER_FILL_ROUNDING_ERROR,
[ExchangeContractErrCodes.ERROR_FILL_BALANCE_ALLOWANCE]: ExchangeContractErrs.FILL_BALANCE_ALLOWANCE_ERROR,
};
private _exchangeContractIfExists?: ExchangeContract;
private _exchangeContractByAddress: ExchangeContractByAddress;
private _exchangeLogEventEmitters: ContractEventEmitter[];
private _tokenWrapper: TokenWrapper;
private _proxyWrapper: ProxyWrapper;
private static _getOrderAddressesAndValues(order: Order): [OrderAddresses, OrderValues] {
const orderAddresses: OrderAddresses = [
order.maker,
@@ -77,27 +82,31 @@ export class ExchangeWrapper extends ContractWrapper {
];
return [orderAddresses, orderValues];
}
constructor(web3Wrapper: Web3Wrapper, tokenWrapper: TokenWrapper) {
constructor(web3Wrapper: Web3Wrapper, tokenWrapper: TokenWrapper, proxyWrapper: ProxyWrapper) {
super(web3Wrapper);
this._tokenWrapper = tokenWrapper;
this._proxyWrapper = proxyWrapper;
this._exchangeLogEventEmitters = [];
this._exchangeContractByAddress = {};
}
public async invalidateContractInstanceAsync(): Promise<void> {
public async invalidateContractInstancesAsync(): Promise<void> {
await this.stopWatchingAllEventsAsync();
delete this._exchangeContractIfExists;
this._exchangeContractByAddress = {};
}
/**
* Returns the unavailable takerAmount of an order. Unavailable amount is defined as the total
* amount that has been filled or cancelled. The remaining takerAmount can be calculated by
* subtracting the unavailable amount from the total order takerAmount.
* @param orderHash The hex encoded orderHash for which you would like to retrieve the
* unavailable takerAmount.
* @param orderHash The hex encoded orderHash for which you would like to retrieve the
* unavailable takerAmount.
* @param exchangeContractAddress The hex encoded address of the Exchange contract to use.
* @return The amount of the order (in taker tokens) that has either been filled or canceled.
*/
public async getUnavailableTakerAmountAsync(orderHash: string): Promise<BigNumber.BigNumber> {
public async getUnavailableTakerAmountAsync(orderHash: string,
exchangeContractAddress: string): Promise<BigNumber.BigNumber> {
assert.isValidOrderHash('orderHash', orderHash);
const exchangeContract = await this._getExchangeContractAsync();
const exchangeContract = await this._getExchangeContractAsync(exchangeContractAddress);
let unavailableAmountInBaseUnits = await exchangeContract.getUnavailableValueT.call(orderHash);
// Wrap BigNumbers returned from web3 with our own (later) version of BigNumber
unavailableAmountInBaseUnits = new BigNumber(unavailableAmountInBaseUnits);
@@ -106,12 +115,14 @@ export class ExchangeWrapper extends ContractWrapper {
/**
* Retrieve the takerAmount of an order that has already been filled.
* @param orderHash The hex encoded orderHash for which you would like to retrieve the filled takerAmount.
* @param exchangeContractAddress The hex encoded address of the Exchange contract to use.
* @return The amount of the order (in taker tokens) that has already been filled.
*/
public async getFilledTakerAmountAsync(orderHash: string): Promise<BigNumber.BigNumber> {
public async getFilledTakerAmountAsync(orderHash: string,
exchangeContractAddress: string): Promise<BigNumber.BigNumber> {
assert.isValidOrderHash('orderHash', orderHash);
const exchangeContract = await this._getExchangeContractAsync();
const exchangeContract = await this._getExchangeContractAsync(exchangeContractAddress);
let fillAmountInBaseUnits = await exchangeContract.filled.call(orderHash);
// Wrap BigNumbers returned from web3 with our own (later) version of BigNumber
fillAmountInBaseUnits = new BigNumber(fillAmountInBaseUnits);
@@ -121,12 +132,14 @@ export class ExchangeWrapper extends ContractWrapper {
* Retrieve the takerAmount of an order that has been cancelled.
* @param orderHash The hex encoded orderHash for which you would like to retrieve the
* cancelled takerAmount.
* @param exchangeContractAddress The hex encoded address of the Exchange contract to use.
* @return The amount of the order (in taker tokens) that has been cancelled.
*/
public async getCanceledTakerAmountAsync(orderHash: string): Promise<BigNumber.BigNumber> {
public async getCanceledTakerAmountAsync(orderHash: string,
exchangeContractAddress: string): Promise<BigNumber.BigNumber> {
assert.isValidOrderHash('orderHash', orderHash);
const exchangeContract = await this._getExchangeContractAsync();
const exchangeContract = await this._getExchangeContractAsync(exchangeContractAddress);
let cancelledAmountInBaseUnits = await exchangeContract.cancelled.call(orderHash);
// Wrap BigNumbers returned from web3 with our own (later) version of BigNumber
cancelledAmountInBaseUnits = new BigNumber(cancelledAmountInBaseUnits);
@@ -155,7 +168,7 @@ export class ExchangeWrapper extends ContractWrapper {
assert.isBoolean('shouldCheckTransfer', shouldCheckTransfer);
await assert.isSenderAddressAsync('takerAddress', takerAddress, this._web3Wrapper);
const exchangeInstance = await this._getExchangeContractAsync();
const exchangeInstance = await this._getExchangeContractAsync(signedOrder.exchangeContractAddress);
await this._validateFillOrderAndThrowIfInvalidAsync(signedOrder, takerTokenFillAmount, takerAddress);
const [orderAddresses, orderValues] = ExchangeWrapper._getOrderAddressesAndValues(signedOrder);
@@ -208,12 +221,15 @@ export class ExchangeWrapper extends ContractWrapper {
@decorators.contractCallErrorHandler
public async fillOrdersUpToAsync(signedOrders: SignedOrder[], takerTokenFillAmount: BigNumber.BigNumber,
shouldCheckTransfer: boolean, takerAddress: string): Promise<BigNumber.BigNumber> {
assert.doesConformToSchema('signedOrders', signedOrders, signedOrdersSchema);
const takerTokenAddresses = _.map(signedOrders, signedOrder => signedOrder.takerTokenAddress);
assert.hasAtMostOneUniqueValue(takerTokenAddresses,
ExchangeContractErrs.MULTIPLE_TAKER_TOKENS_IN_FILL_UP_TO_DISALLOWED);
ExchangeContractErrs.MULTIPLE_TAKER_TOKENS_IN_FILL_UP_TO_DISALLOWED);
const exchangeContractAddresses = _.map(signedOrders, signedOrder => signedOrder.exchangeContractAddress);
assert.hasAtMostOneUniqueValue(exchangeContractAddresses,
ExchangeContractErrs.BATCH_ORDERS_MUST_HAVE_SAME_EXCHANGE_ADDRESS);
assert.isBigNumber('takerTokenFillAmount', takerTokenFillAmount);
assert.isBoolean('shouldCheckTransfer', shouldCheckTransfer);
assert.doesConformToSchema('signedOrders', signedOrders, signedOrdersSchema);
await assert.isSenderAddressAsync('takerAddress', takerAddress, this._web3Wrapper);
for (const signedOrder of signedOrders) {
await this._validateFillOrderAndThrowIfInvalidAsync(
@@ -236,7 +252,7 @@ export class ExchangeWrapper extends ContractWrapper {
orderAddressesValuesAndSignatureArray,
);
const exchangeInstance = await this._getExchangeContractAsync();
const exchangeInstance = await this._getExchangeContractAsync(exchangeContractAddresses[0]);
const gas = await exchangeInstance.fillUpTo.estimateGas(
orderAddressesArray,
orderValuesArray,
@@ -285,9 +301,15 @@ export class ExchangeWrapper extends ContractWrapper {
@decorators.contractCallErrorHandler
public async batchFillOrderAsync(orderFillRequests: OrderFillRequest[],
shouldCheckTransfer: boolean, takerAddress: string): Promise<void> {
assert.doesConformToSchema('orderFillRequests', orderFillRequests, orderFillRequestsSchema);
const exchangeContractAddresses = _.map(
orderFillRequests,
orderFillRequest => orderFillRequest.signedOrder.exchangeContractAddress,
);
assert.hasAtMostOneUniqueValue(exchangeContractAddresses,
ExchangeContractErrs.BATCH_ORDERS_MUST_HAVE_SAME_EXCHANGE_ADDRESS);
assert.isBoolean('shouldCheckTransfer', shouldCheckTransfer);
await assert.isSenderAddressAsync('takerAddress', takerAddress, this._web3Wrapper);
assert.doesConformToSchema('orderFillRequests', orderFillRequests, orderFillRequestsSchema);
for (const orderFillRequest of orderFillRequests) {
await this._validateFillOrderAndThrowIfInvalidAsync(
orderFillRequest.signedOrder, orderFillRequest.takerTokenFillAmount, takerAddress);
@@ -310,7 +332,7 @@ export class ExchangeWrapper extends ContractWrapper {
orderAddressesValuesAmountsAndSignatureArray,
);
const exchangeInstance = await this._getExchangeContractAsync();
const exchangeInstance = await this._getExchangeContractAsync(exchangeContractAddresses[0]);
const gas = await exchangeInstance.batchFill.estimateGas(
orderAddressesArray,
orderValuesArray,
@@ -354,7 +376,7 @@ export class ExchangeWrapper extends ContractWrapper {
assert.isBigNumber('takerTokenFillAmount', takerTokenFillAmount);
await assert.isSenderAddressAsync('takerAddress', takerAddress, this._web3Wrapper);
const exchangeInstance = await this._getExchangeContractAsync();
const exchangeInstance = await this._getExchangeContractAsync(signedOrder.exchangeContractAddress);
await this._validateFillOrderAndThrowIfInvalidAsync(signedOrder, takerTokenFillAmount, takerAddress);
await this._validateFillOrKillOrderAndThrowIfInvalidAsync(signedOrder, exchangeInstance.address,
@@ -397,9 +419,18 @@ export class ExchangeWrapper extends ContractWrapper {
@decorators.contractCallErrorHandler
public async batchFillOrKillAsync(orderFillOrKillRequests: OrderFillOrKillRequest[],
takerAddress: string): Promise<void> {
await assert.isSenderAddressAsync('takerAddress', takerAddress, this._web3Wrapper);
assert.doesConformToSchema('orderFillOrKillRequests', orderFillOrKillRequests, orderFillOrKillRequestsSchema);
const exchangeInstance = await this._getExchangeContractAsync();
const exchangeContractAddresses = _.map(
orderFillOrKillRequests,
orderFillOrKillRequest => orderFillOrKillRequest.signedOrder.exchangeContractAddress,
);
assert.hasAtMostOneUniqueValue(exchangeContractAddresses,
ExchangeContractErrs.BATCH_ORDERS_MUST_HAVE_SAME_EXCHANGE_ADDRESS);
await assert.isSenderAddressAsync('takerAddress', takerAddress, this._web3Wrapper);
if (_.isEmpty(orderFillOrKillRequests)) {
return; // no-op
}
const exchangeInstance = await this._getExchangeContractAsync(exchangeContractAddresses[0]);
for (const request of orderFillOrKillRequests) {
await this._validateFillOrKillOrderAndThrowIfInvalidAsync(request.signedOrder, exchangeInstance.address,
request.fillTakerAmount);
@@ -458,7 +489,7 @@ export class ExchangeWrapper extends ContractWrapper {
assert.isBigNumber('takerTokenCancelAmount', takerTokenCancelAmount);
await assert.isSenderAddressAsync('order.maker', order.maker, this._web3Wrapper);
const exchangeInstance = await this._getExchangeContractAsync();
const exchangeInstance = await this._getExchangeContractAsync(order.exchangeContractAddress);
await this._validateCancelOrderAndThrowIfInvalidAsync(order, takerTokenCancelAmount);
const [orderAddresses, orderValues] = ExchangeWrapper._getOrderAddressesAndValues(order);
@@ -492,12 +523,18 @@ export class ExchangeWrapper extends ContractWrapper {
*/
@decorators.contractCallErrorHandler
public async batchCancelOrderAsync(orderCancellationRequests: OrderCancellationRequest[]): Promise<void> {
assert.doesConformToSchema('orderCancellationRequests', orderCancellationRequests,
orderCancellationRequestsSchema);
const exchangeContractAddresses = _.map(
orderCancellationRequests,
orderCancellationRequest => orderCancellationRequest.order.exchangeContractAddress,
);
assert.hasAtMostOneUniqueValue(exchangeContractAddresses,
ExchangeContractErrs.BATCH_ORDERS_MUST_HAVE_SAME_EXCHANGE_ADDRESS);
const makers = _.map(orderCancellationRequests, cancellationRequest => cancellationRequest.order.maker);
assert.hasAtMostOneUniqueValue(makers, ExchangeContractErrs.MULTIPLE_MAKERS_IN_SINGLE_CANCEL_BATCH_DISALLOWED);
const maker = makers[0];
await assert.isSenderAddressAsync('maker', maker, this._web3Wrapper);
assert.doesConformToSchema('orderCancellationRequests', orderCancellationRequests,
orderCancellationRequestsSchema);
for (const cancellationRequest of orderCancellationRequests) {
await this._validateCancelOrderAndThrowIfInvalidAsync(
cancellationRequest.order, cancellationRequest.takerTokenCancelAmount,
@@ -506,7 +543,7 @@ export class ExchangeWrapper extends ContractWrapper {
if (_.isEmpty(orderCancellationRequests)) {
return; // no-op
}
const exchangeInstance = await this._getExchangeContractAsync();
const exchangeInstance = await this._getExchangeContractAsync(exchangeContractAddresses[0]);
const orderAddressesValuesAndTakerTokenCancelAmounts = _.map(orderCancellationRequests, cancellationRequest => {
return [
...ExchangeWrapper._getOrderAddressesAndValues(cancellationRequest.order),
@@ -537,16 +574,17 @@ export class ExchangeWrapper extends ContractWrapper {
}
/**
* Subscribe to an event type emitted by the Exchange smart contract
* @param eventName The exchange contract event you would like to subscribe to.
* @param subscriptionOpts Subscriptions options that let you configure the subscription.
* @param indexFilterValues An object where the keys are indexed args returned by the event and
* the value is the value you are interested in. E.g `{maker: aUserAddressHex}`
* @param eventName The exchange contract event you would like to subscribe to.
* @param subscriptionOpts Subscriptions options that let you configure the subscription.
* @param indexFilterValues An object where the keys are indexed args returned by the event and
* the value is the value you are interested in. E.g `{maker: aUserAddressHex}`
* @param exchangeContractAddress The hex encoded address of the Exchange contract to use.
* @return ContractEventEmitter object
*/
public async subscribeAsync(eventName: ExchangeEvents, subscriptionOpts: SubscriptionOpts,
indexFilterValues: IndexedFilterValues):
indexFilterValues: IndexedFilterValues, exchangeContractAddress: string):
Promise<ContractEventEmitter> {
const exchangeContract = await this._getExchangeContractAsync();
const exchangeContract = await this._getExchangeContractAsync(exchangeContractAddress);
let createLogEvent: CreateContractEvent;
switch (eventName) {
case ExchangeEvents.LogFill:
@@ -568,13 +606,41 @@ export class ExchangeWrapper extends ContractWrapper {
return eventEmitter;
}
/**
* Returns the ethereum address of the current exchange contract
* Returns the ethereum addresses of all available exchange contracts
* on the network that the provided web3 instance is connected to
* @return The ethereum address of the current exchange contract.
* @return The ethereum addresses of all available exchange contracts.
*/
public async getContractAddressAsync(): Promise<string> {
const exchangeContract = await this._getExchangeContractAsync();
return exchangeContract.address;
public async getAvailableContractAddressesAsync(): Promise<string[]> {
const networkId = await this._web3Wrapper.getNetworkIdIfExistsAsync();
if (_.isUndefined(networkId)) {
return [];
} else {
const exchangeArtifacts = _.values(ExchangeArtifactsByName);
const networkSpecificExchangeArtifacts = _.compact(_.map(
exchangeArtifacts, exchangeArtifact => exchangeArtifact.networks[networkId]));
const exchangeAddresses = _.map(
networkSpecificExchangeArtifacts,
networkSpecificExchangeArtifact => networkSpecificExchangeArtifact.address,
);
return exchangeAddresses;
}
}
/**
* Returns the ethereum addresses of all available exchange contracts
* on the network that the provided web3 instance is connected to
* that are currently authorized on the Proxy contract
* @return The ethereum addresses of all available and authorized exchange contract.
*/
public async getProxyAuthorizedContractAddressesAsync(): Promise<string[]> {
const exchangeContractAddresses = await this.getAvailableContractAddressesAsync();
const proxyAuthorizedExchangeContractAddresses = [];
for (const exchangeContractAddress of exchangeContractAddresses) {
const isAuthorized = await this._isExchangeContractAddressProxyAuthorizedAsync(exchangeContractAddress);
if (isAuthorized) {
proxyAuthorizedExchangeContractAddresses.push(exchangeContractAddress);
}
}
return proxyAuthorizedExchangeContractAddresses;
}
/**
* Stops watching for all exchange events
@@ -585,6 +651,10 @@ export class ExchangeWrapper extends ContractWrapper {
await Promise.all(stopWatchingPromises);
this._exchangeLogEventEmitters = [];
}
private async _isExchangeContractAddressProxyAuthorizedAsync(exchangeContractAddress: string): Promise<boolean> {
const isAuthorized = await this._proxyWrapper.isAuthorizedAsync(exchangeContractAddress);
return isAuthorized;
}
private _wrapEventEmitter(event: ContractEventObj): ContractEventEmitter {
const watch = (eventCallback: EventCallback) => {
const bignumberWrappingEventCallback = this._wrapEventCallback(eventCallback);
@@ -617,12 +687,13 @@ export class ExchangeWrapper extends ContractWrapper {
return bignumberWrappingEventCallback;
}
private async _isValidSignatureUsingContractCallAsync(dataHex: string, ecSignature: ECSignature,
signerAddressHex: string): Promise<boolean> {
signerAddressHex: string,
exchangeContractAddress: string): Promise<boolean> {
assert.isHexString('dataHex', dataHex);
assert.doesConformToSchema('ecSignature', ecSignature, ecSignatureSchema);
assert.isETHAddressHex('signerAddressHex', signerAddressHex);
const exchangeInstance = await this._getExchangeContractAsync();
const exchangeInstance = await this._getExchangeContractAsync(exchangeContractAddress);
const isValidSignature = await exchangeInstance.isValidSignature.call(
signerAddressHex,
@@ -633,13 +704,8 @@ export class ExchangeWrapper extends ContractWrapper {
);
return isValidSignature;
}
private async _getOrderHashHexAsync(order: Order|SignedOrder): Promise<string> {
const exchangeInstance = await this._getExchangeContractAsync();
const orderHashHex = utils.getOrderHashHex(order, exchangeInstance.address);
return orderHashHex;
}
private async _getOrderHashHexUsingContractCallAsync(order: Order|SignedOrder): Promise<string> {
const exchangeInstance = await this._getExchangeContractAsync();
const exchangeInstance = await this._getExchangeContractAsync(order.exchangeContractAddress);
const [orderAddresses, orderValues] = ExchangeWrapper._getOrderAddressesAndValues(order);
const orderHashHex = await exchangeInstance.getOrderHash.call(orderAddresses, orderValues);
return orderHashHex;
@@ -657,12 +723,13 @@ export class ExchangeWrapper extends ContractWrapper {
if (signedOrder.expirationUnixTimestampSec.lessThan(currentUnixTimestampSec)) {
throw new Error(ExchangeContractErrs.ORDER_FILL_EXPIRED);
}
const zrxTokenAddress = await this._getZRXTokenAddressAsync();
const zrxTokenAddress = await this._getZRXTokenAddressAsync(signedOrder.exchangeContractAddress);
await this._validateFillOrderBalancesAndAllowancesAndThrowIfInvalidAsync(signedOrder, fillTakerAmount,
senderAddress, zrxTokenAddress);
const wouldRoundingErrorOccur = await this._isRoundingErrorAsync(
signedOrder.takerTokenAmount, fillTakerAmount, signedOrder.makerTokenAmount,
signedOrder.exchangeContractAddress,
);
if (wouldRoundingErrorOccur) {
throw new Error(ExchangeContractErrs.ORDER_FILL_ROUNDING_ERROR);
@@ -673,8 +740,8 @@ export class ExchangeWrapper extends ContractWrapper {
if (takerTokenCancelAmount.eq(0)) {
throw new Error(ExchangeContractErrs.ORDER_CANCEL_AMOUNT_ZERO);
}
const orderHash = await this._getOrderHashHexAsync(order);
const unavailableAmount = await this.getUnavailableTakerAmountAsync(orderHash);
const orderHash = utils.getOrderHashHex(order);
const unavailableAmount = await this.getUnavailableTakerAmountAsync(orderHash, order.exchangeContractAddress);
if (order.takerTokenAmount.minus(unavailableAmount).eq(0)) {
throw new Error(ExchangeContractErrs.ORDER_ALREADY_CANCELLED_OR_FILLED);
}
@@ -684,11 +751,11 @@ export class ExchangeWrapper extends ContractWrapper {
}
}
private async _validateFillOrKillOrderAndThrowIfInvalidAsync(signedOrder: SignedOrder,
exchangeAddress: string,
exchangeContractAddress: string,
fillTakerAmount: BigNumber.BigNumber) {
// Check that fillValue available >= fillTakerAmount
const orderHashHex = utils.getOrderHashHex(signedOrder, exchangeAddress);
const unavailableTakerAmount = await this.getUnavailableTakerAmountAsync(orderHashHex);
const orderHashHex = utils.getOrderHashHex(signedOrder);
const unavailableTakerAmount = await this.getUnavailableTakerAmountAsync(orderHashHex, exchangeContractAddress);
const remainingTakerAmount = signedOrder.takerTokenAmount.minus(unavailableTakerAmount);
if (remainingTakerAmount < fillTakerAmount) {
throw new Error(ExchangeContractErrs.INSUFFICIENT_REMAINING_FILL_AMOUNT);
@@ -765,24 +832,41 @@ export class ExchangeWrapper extends ContractWrapper {
}
private async _isRoundingErrorAsync(takerTokenAmount: BigNumber.BigNumber,
fillTakerAmount: BigNumber.BigNumber,
makerTokenAmount: BigNumber.BigNumber): Promise<boolean> {
makerTokenAmount: BigNumber.BigNumber,
exchangeContractAddress: string): Promise<boolean> {
await assert.isUserAddressAvailableAsync(this._web3Wrapper);
const exchangeInstance = await this._getExchangeContractAsync();
const exchangeInstance = await this._getExchangeContractAsync(exchangeContractAddress);
const isRoundingError = await exchangeInstance.isRoundingError.call(
takerTokenAmount, fillTakerAmount, makerTokenAmount,
);
return isRoundingError;
}
private async _getExchangeContractAsync(): Promise<ExchangeContract> {
if (!_.isUndefined(this._exchangeContractIfExists)) {
return this._exchangeContractIfExists;
private async _getExchangeContractAsync(exchangeContractAddress: string): Promise<ExchangeContract> {
if (!_.isUndefined(this._exchangeContractByAddress[exchangeContractAddress])) {
return this._exchangeContractByAddress[exchangeContractAddress];
}
const ExchangeArtifacts = this._getExchangeArtifactsByAddressOrThrow(exchangeContractAddress);
const contractInstance = await this._instantiateContractIfExistsAsync((ExchangeArtifacts as any));
this._exchangeContractIfExists = contractInstance as ExchangeContract;
return this._exchangeContractIfExists;
this._exchangeContractByAddress[exchangeContractAddress] = contractInstance as ExchangeContract;
return this._exchangeContractByAddress[exchangeContractAddress];
}
private async _getZRXTokenAddressAsync(): Promise<string> {
const exchangeInstance = await this._getExchangeContractAsync();
return exchangeInstance.ZRX.call();
private _getExchangeArtifactsByAddressOrThrow(exchangeContractAddress: string): ContractArtifact {
const exchangeArtifacts = _.values<ContractArtifact>(ExchangeArtifactsByName);
for (const exchangeArtifact of exchangeArtifacts) {
const networkSpecificExchangeArtifactValues = _.values(exchangeArtifact.networks);
const exchangeAddressesInArtifact = _.map(
networkSpecificExchangeArtifactValues,
networkSpecificExchangeArtifact => networkSpecificExchangeArtifact.address,
);
if (_.includes(exchangeAddressesInArtifact, exchangeContractAddress)) {
return exchangeArtifact;
}
}
throw new Error(ZeroExError.EXCHANGE_CONTRACT_DOES_NOT_EXIST);
}
private async _getZRXTokenAddressAsync(exchangeContractAddress: string): Promise<string> {
const exchangeInstance = await this._getExchangeContractAsync(exchangeContractAddress);
const ZRXtokenAddress = await exchangeInstance.ZRX.call();
return ZRXtokenAddress;
}
}

View File

@@ -0,0 +1,33 @@
import * as _ from 'lodash';
import {Web3Wrapper} from '../web3_wrapper';
import {ContractWrapper} from './contract_wrapper';
import * as ProxyArtifacts from '../artifacts/Proxy.json';
import {ProxyContract} from '../types';
/**
* This class includes the functionality related to interacting with the Proxy contract.
*/
export class ProxyWrapper extends ContractWrapper {
private _proxyContractIfExists?: ProxyContract;
public invalidateContractInstance(): void {
delete this._proxyContractIfExists;
}
/**
* Check if the Exchange contract address is authorized by the Proxy contract.
* @param exchangeContractAddress The hex encoded address of the Exchange contract to use.
* @return Whether the exchangeContractAddress is authorized.
*/
public async isAuthorizedAsync(exchangeContractAddress: string): Promise<boolean> {
const proxyContractInstance = await this._getProxyContractAsync();
const isAuthorized = await proxyContractInstance.authorized.call(exchangeContractAddress);
return isAuthorized;
}
private async _getProxyContractAsync(): Promise<ProxyContract> {
if (!_.isUndefined(this._proxyContractIfExists)) {
return this._proxyContractIfExists;
}
const contractInstance = await this._instantiateContractIfExistsAsync((ProxyArtifacts as any));
this._proxyContractIfExists = contractInstance as ProxyContract;
return this._proxyContractIfExists;
}
}

View File

@@ -0,0 +1,6 @@
import {ContractArtifact} from './types';
import * as Exchange_v1 from './artifacts/exchange/Exchange_v1.json';
export const ExchangeArtifactsByName = {
Exchange_v1: Exchange_v1 as any as ContractArtifact,
};

4
src/globals.d.ts vendored
View File

@@ -7,10 +7,6 @@ declare module 'request-promise-native';
declare module 'web3-provider-engine';
declare module 'web3-provider-engine/subproviders/rpc';
declare interface Schema {
id: string;
}
// HACK: In order to merge the bignumber declaration added by chai-bignumber to the chai Assertion
// interface we must use `namespace` as the Chai definitelyTyped definition does. Since we otherwise
// disallow `namespace`, we disable tslint for the following.

View File

@@ -12,6 +12,7 @@ function strEnum(values: string[]): {[key: string]: string} {
export const ZeroExError = strEnum([
'CONTRACT_DOES_NOT_EXIST',
'EXCHANGE_CONTRACT_DOES_NOT_EXIST',
'UNHANDLED_ERROR',
'USER_HAS_NO_ASSOCIATED_ADDRESSES',
'INVALID_SIGNATURE',
@@ -147,6 +148,12 @@ export interface EtherTokenContract extends ContractInstance {
withdraw: (amount: BigNumber.BigNumber, txOpts: TxOpts) => Promise<void>;
}
export interface ProxyContract extends ContractInstance {
authorized: {
call: (address: string) => Promise<boolean>;
};
}
export const SolidityTypes = strEnum([
'address',
'uint256',
@@ -182,6 +189,7 @@ export const ExchangeContractErrs = strEnum([
'MULTIPLE_MAKERS_IN_SINGLE_CANCEL_BATCH_DISALLOWED',
'INSUFFICIENT_REMAINING_FILL_AMOUNT',
'MULTIPLE_TAKER_TOKENS_IN_FILL_UP_TO_DISALLOWED',
'BATCH_ORDERS_MUST_HAVE_SAME_EXCHANGE_ADDRESS',
]);
export type ExchangeContractErrs = keyof typeof ExchangeContractErrs;
@@ -241,6 +249,7 @@ export interface Order {
makerTokenAddress: string;
takerTokenAddress: string;
salt: BigNumber.BigNumber;
exchangeContractAddress: string;
feeRecipient: string;
expirationUnixTimestampSec: BigNumber.BigNumber;
}
@@ -326,3 +335,15 @@ export interface ContractEventEmitter {
* It is however a `Web3` library type, not a native `0x.js` type.
*/
export type Web3Provider = Web3.Provider;
export interface ExchangeContractByAddress {
[address: string]: ExchangeContract;
}
export interface ContractArtifact {
networks: {
[networkId: number]: {
address: string;
};
};
}

View File

@@ -2,6 +2,7 @@ import * as _ from 'lodash';
import * as BigNumber from 'bignumber.js';
import * as Web3 from 'web3';
import {Web3Wrapper} from '../web3_wrapper';
import {Schema} from 'jsonschema';
import {SchemaValidator} from './schema_validator';
import {utils} from './utils';

View File

@@ -1,4 +1,4 @@
import {Validator, ValidatorResult} from 'jsonschema';
import {Validator, ValidatorResult, Schema} from 'jsonschema';
import {ecSignatureSchema, ecSignatureParameterSchema} from '../schemas/ec_signature_schema';
import {orderSchema, signedOrderSchema} from '../schemas/order_schemas';
import {addressSchema, numberSchema} from '../schemas/basic_type_schemas';

View File

@@ -22,6 +22,9 @@ export const utils = {
isParityNode(nodeVersion: string): boolean {
return _.includes(nodeVersion, 'Parity');
},
isTestRpc(nodeVersion: string): boolean {
return _.includes(nodeVersion, 'TestRPC');
},
isValidOrderHash(orderHashHex: string): boolean {
const isValid = /^0x[0-9A-F]{64}$/i.test(orderHashHex);
return isValid;
@@ -29,9 +32,9 @@ export const utils = {
spawnSwitchErr(name: string, value: any): Error {
return new Error(`Unexpected switch value: ${value} encountered for ${name}`);
},
getOrderHashHex(order: Order|SignedOrder, exchangeContractAddr: string): string {
getOrderHashHex(order: Order|SignedOrder): string {
const orderParts = [
{value: exchangeContractAddr, type: SolidityTypes.address},
{value: order.exchangeContractAddress, type: SolidityTypes.address},
{value: order.maker, type: SolidityTypes.address},
{value: order.taker, type: SolidityTypes.address},
{value: order.makerTokenAddress, type: SolidityTypes.address},

View File

@@ -16,10 +16,11 @@ describe('ZeroEx library', () => {
it('overrides provider in nested web3s and invalidates contractInstances', async () => {
const web3 = web3Factory.create();
const zeroEx = new ZeroEx(web3.currentProvider);
const [exchangeContractAddress] = await zeroEx.exchange.getAvailableContractAddressesAsync();
// Instantiate the contract instances with the current provider
await (zeroEx.exchange as any)._getExchangeContractAsync();
await (zeroEx.exchange as any)._getExchangeContractAsync(exchangeContractAddress);
await (zeroEx.tokenRegistry as any)._getTokenRegistryContractAsync();
expect((zeroEx.exchange as any)._exchangeContractIfExists).to.not.be.undefined();
expect((zeroEx.exchange as any)._exchangeContractByAddress[exchangeContractAddress]).to.not.be.undefined();
expect((zeroEx.tokenRegistry as any)._tokenRegistryContractIfExists).to.not.be.undefined();
const newProvider = web3Factory.getRpcProvider();
@@ -28,7 +29,7 @@ describe('ZeroEx library', () => {
await zeroEx.setProviderAsync(newProvider);
// Check that contractInstances with old provider are removed after provider update
expect((zeroEx.exchange as any)._exchangeContractIfExists).to.be.undefined();
expect((zeroEx.exchange as any)._exchangeContractByAddress[exchangeContractAddress]).to.be.undefined();
expect((zeroEx.tokenRegistry as any)._tokenRegistryContractIfExists).to.be.undefined();
// Check that all nested web3 instances return the updated provider
@@ -52,6 +53,10 @@ describe('ZeroEx library', () => {
const address = '0x5409ed021d9299bf6814279a6a1411a7e866a631';
const web3 = web3Factory.create();
const zeroEx = new ZeroEx(web3.currentProvider);
let exchangeContractAddress: string;
before(async () => {
[exchangeContractAddress] = await zeroEx.exchange.getAvailableContractAddressesAsync();
});
it('should return false if the data doesn\'t pertain to the signature & address', async () => {
expect(ZeroEx.isValidSignature('0x0', signature, address)).to.be.false();
return expect(
@@ -77,7 +82,7 @@ describe('ZeroEx library', () => {
const isValidSignatureLocal = ZeroEx.isValidSignature(dataHex, signature, address);
expect(isValidSignatureLocal).to.be.true();
const isValidSignatureOnContract = await (zeroEx.exchange as any)
._isValidSignatureUsingContractCallAsync(dataHex, signature, address);
._isValidSignatureUsingContractCallAsync(dataHex, signature, address, exchangeContractAddress);
return expect(isValidSignatureOnContract).to.be.true();
});
});
@@ -125,15 +130,16 @@ describe('ZeroEx library', () => {
expect(baseUnitAmount).to.be.bignumber.equal(expectedUnitAmount);
});
});
describe('#getOrderHashHexAsync', () => {
const exchangeContractAddress = constants.NULL_ADDRESS;
const expectedOrderHash = '0x103a5e97dab5dbeb8f385636f86a7d1e458a7ccbe1bd194727f0b2f85ab116c7';
describe('#getOrderHashHex', () => {
const expectedOrderHash = '0x39da987067a3c9e5f1617694f1301326ba8c8b0498ebef5df4863bed394e3c83';
const fakeExchangeContractAddress = '0xb69e673309512a9d726f87304c6984054f87a93b';
const order: Order = {
maker: constants.NULL_ADDRESS,
taker: constants.NULL_ADDRESS,
feeRecipient: constants.NULL_ADDRESS,
makerTokenAddress: constants.NULL_ADDRESS,
takerTokenAddress: constants.NULL_ADDRESS,
exchangeContractAddress: fakeExchangeContractAddress,
salt: new BigNumber(0),
makerFee: new BigNumber(0),
takerFee: new BigNumber(0),
@@ -141,22 +147,11 @@ describe('ZeroEx library', () => {
takerTokenAmount: new BigNumber(0),
expirationUnixTimestampSec: new BigNumber(0),
};
let stubs: Sinon.SinonStub[] = [];
afterEach(() => {
// clean up any stubs after the test has completed
_.each(stubs, s => s.restore());
stubs = [];
});
it('calculates the order hash', async () => {
const web3 = web3Factory.create();
const zeroEx = new ZeroEx(web3.currentProvider);
stubs = [
Sinon.stub((zeroEx as any), '_getExchangeAddressAsync')
.returns(Promise.resolve(exchangeContractAddress)),
];
const orderHash = await zeroEx.getOrderHashHexAsync(order);
const orderHash = zeroEx.getOrderHashHex(order);
expect(orderHash).to.be.equal(expectedOrderHash);
});
});

View File

@@ -1,9 +1,14 @@
import * as fs from 'fs';
import * as chai from 'chai';
import {chaiSetup} from './utils/chai_setup';
import HDWalletProvider = require('truffle-hdwallet-provider');
import {ZeroEx} from '../src';
import {web3Factory} from './utils/web3_factory';
import {constants} from './utils/constants';
chaiSetup.configure();
const expect = chai.expect;
// Those tests are slower cause they're talking to a remote node
const TIMEOUT = 10000;
@@ -22,7 +27,8 @@ describe('Artifacts', () => {
await (zeroEx.token as any)._getProxyAddressAsync();
}).timeout(TIMEOUT);
it('exchange contract is deployed', async () => {
await (zeroEx.exchange as any)._getExchangeContractAsync();
const exchangeContractAddresses = await zeroEx.exchange.getAvailableContractAddressesAsync();
expect(exchangeContractAddresses).to.have.lengthOf.above(0);
}).timeout(TIMEOUT);
});
});

View File

@@ -1,4 +1,5 @@
import 'mocha';
import * as _ from 'lodash';
import * as chai from 'chai';
import * as Web3 from 'web3';
import * as BigNumber from 'bignumber.js';
@@ -23,6 +24,7 @@ import {DoneCallback} from '../src/types';
import {FillScenarios} from './utils/fill_scenarios';
import {TokenUtils} from './utils/token_utils';
import {assert} from '../src/utils/assert';
import {ProxyWrapper} from '../src/contract_wrappers/proxy_wrapper';
chaiSetup.configure();
const expect = chai.expect;
@@ -38,14 +40,16 @@ describe('ExchangeWrapper', () => {
let userAddresses: string[];
let zrxTokenAddress: string;
let fillScenarios: FillScenarios;
let exchangeContractAddress: string;
before(async () => {
web3 = web3Factory.create();
zeroEx = new ZeroEx(web3.currentProvider);
[exchangeContractAddress] = await zeroEx.exchange.getAvailableContractAddressesAsync();
userAddresses = await promisify(web3.eth.getAccounts)();
tokens = await zeroEx.tokenRegistry.getTokensAsync();
tokenUtils = new TokenUtils(tokens);
zrxTokenAddress = tokenUtils.getProtocolTokenOrThrow().address;
fillScenarios = new FillScenarios(zeroEx, userAddresses, tokens, zrxTokenAddress);
fillScenarios = new FillScenarios(zeroEx, userAddresses, tokens, zrxTokenAddress, exchangeContractAddress);
});
beforeEach(async () => {
await blockchainLifecycle.startAsync();
@@ -392,11 +396,11 @@ describe('ExchangeWrapper', () => {
signedOrder = await fillScenarios.createFillableSignedOrderAsync(
makerTokenAddress, takerTokenAddress, makerAddress, takerAddress, fillableAmount,
);
signedOrderHashHex = await zeroEx.getOrderHashHexAsync(signedOrder);
signedOrderHashHex = zeroEx.getOrderHashHex(signedOrder);
anotherSignedOrder = await fillScenarios.createFillableSignedOrderAsync(
makerTokenAddress, takerTokenAddress, makerAddress, takerAddress, fillableAmount,
);
anotherOrderHashHex = await zeroEx.getOrderHashHexAsync(anotherSignedOrder);
anotherOrderHashHex = zeroEx.getOrderHashHex(anotherSignedOrder);
orderFillBatch = [
{
signedOrder,
@@ -414,8 +418,12 @@ describe('ExchangeWrapper', () => {
});
it('should successfully fill multiple orders', async () => {
await zeroEx.exchange.batchFillOrderAsync(orderFillBatch, shouldCheckTransfer, takerAddress);
const filledAmount = await zeroEx.exchange.getFilledTakerAmountAsync(signedOrderHashHex);
const anotherFilledAmount = await zeroEx.exchange.getFilledTakerAmountAsync(anotherOrderHashHex);
const filledAmount = await zeroEx.exchange.getFilledTakerAmountAsync(
signedOrderHashHex, exchangeContractAddress,
);
const anotherFilledAmount = await zeroEx.exchange.getFilledTakerAmountAsync(
anotherOrderHashHex, exchangeContractAddress,
);
expect(filledAmount).to.be.bignumber.equal(fillTakerAmount);
expect(anotherFilledAmount).to.be.bignumber.equal(fillTakerAmount);
});
@@ -432,11 +440,11 @@ describe('ExchangeWrapper', () => {
signedOrder = await fillScenarios.createFillableSignedOrderAsync(
makerTokenAddress, takerTokenAddress, makerAddress, takerAddress, fillableAmount,
);
signedOrderHashHex = await zeroEx.getOrderHashHexAsync(signedOrder);
signedOrderHashHex = zeroEx.getOrderHashHex(signedOrder);
anotherSignedOrder = await fillScenarios.createFillableSignedOrderAsync(
makerTokenAddress, takerTokenAddress, makerAddress, takerAddress, fillableAmount,
);
anotherOrderHashHex = await zeroEx.getOrderHashHexAsync(anotherSignedOrder);
anotherOrderHashHex = zeroEx.getOrderHashHex(anotherSignedOrder);
signedOrders = [signedOrder, anotherSignedOrder];
});
describe('successful batch fills', () => {
@@ -447,8 +455,12 @@ describe('ExchangeWrapper', () => {
await zeroEx.exchange.fillOrdersUpToAsync(
signedOrders, fillUpToAmount, shouldCheckTransfer, takerAddress,
);
const filledAmount = await zeroEx.exchange.getFilledTakerAmountAsync(signedOrderHashHex);
const anotherFilledAmount = await zeroEx.exchange.getFilledTakerAmountAsync(anotherOrderHashHex);
const filledAmount = await zeroEx.exchange.getFilledTakerAmountAsync(
signedOrderHashHex, exchangeContractAddress,
);
const anotherFilledAmount = await zeroEx.exchange.getFilledTakerAmountAsync(
anotherOrderHashHex, exchangeContractAddress,
);
expect(filledAmount).to.be.bignumber.equal(fillableAmount);
const remainingFillAmount = fillableAmount.minus(1);
expect(anotherFilledAmount).to.be.bignumber.equal(remainingFillAmount);
@@ -480,7 +492,7 @@ describe('ExchangeWrapper', () => {
signedOrder = await fillScenarios.createFillableSignedOrderAsync(
makerTokenAddress, takerTokenAddress, makerAddress, takerAddress, fillableAmount,
);
orderHashHex = await zeroEx.getOrderHashHexAsync(signedOrder);
orderHashHex = zeroEx.getOrderHashHex(signedOrder);
});
describe('#cancelOrderAsync', () => {
describe('failed cancels', () => {
@@ -495,7 +507,7 @@ describe('ExchangeWrapper', () => {
makerTokenAddress, takerTokenAddress, makerAddress, takerAddress,
fillableAmount, expirationInPast,
);
orderHashHex = await zeroEx.getOrderHashHexAsync(expiredSignedOrder);
orderHashHex = zeroEx.getOrderHashHex(expiredSignedOrder);
return expect(zeroEx.exchange.cancelOrderAsync(expiredSignedOrder, cancelAmount))
.to.be.rejectedWith(ExchangeContractErrs.ORDER_CANCEL_EXPIRED);
});
@@ -508,7 +520,9 @@ describe('ExchangeWrapper', () => {
describe('successful cancels', () => {
it('should cancel an order', async () => {
await zeroEx.exchange.cancelOrderAsync(signedOrder, cancelAmount);
const cancelledAmount = await zeroEx.exchange.getCanceledTakerAmountAsync(orderHashHex);
const cancelledAmount = await zeroEx.exchange.getCanceledTakerAmountAsync(
orderHashHex, exchangeContractAddress,
);
expect(cancelledAmount).to.be.bignumber.equal(cancelAmount);
});
it('should return cancelled amount', async () => {
@@ -525,7 +539,7 @@ describe('ExchangeWrapper', () => {
anotherSignedOrder = await fillScenarios.createFillableSignedOrderAsync(
makerTokenAddress, takerTokenAddress, makerAddress, takerAddress, fillableAmount,
);
anotherOrderHashHex = await zeroEx.getOrderHashHexAsync(anotherSignedOrder);
anotherOrderHashHex = zeroEx.getOrderHashHex(anotherSignedOrder);
cancelBatch = [
{
order: signedOrder,
@@ -554,9 +568,12 @@ describe('ExchangeWrapper', () => {
describe('successful batch cancels', () => {
it('should cancel a batch of orders', async () => {
await zeroEx.exchange.batchCancelOrderAsync(cancelBatch);
const cancelledAmount = await zeroEx.exchange.getCanceledTakerAmountAsync(orderHashHex);
const cancelledAmount = await zeroEx.exchange.getCanceledTakerAmountAsync(
orderHashHex, exchangeContractAddress,
);
const anotherCancelledAmount = await zeroEx.exchange.getCanceledTakerAmountAsync(
anotherOrderHashHex);
anotherOrderHashHex, exchangeContractAddress,
);
expect(cancelledAmount).to.be.bignumber.equal(cancelAmount);
expect(anotherCancelledAmount).to.be.bignumber.equal(cancelAmount);
});
@@ -583,53 +600,73 @@ describe('ExchangeWrapper', () => {
signedOrder = await fillScenarios.createPartiallyFilledSignedOrderAsync(
makerTokenAddress, takerTokenAddress, takerAddress, fillableAmount, partialFillAmount,
);
orderHash = await zeroEx.getOrderHashHexAsync(signedOrder);
orderHash = zeroEx.getOrderHashHex(signedOrder);
});
describe('#getUnavailableTakerAmountAsync', () => {
it ('should throw if passed an invalid orderHash', async () => {
const invalidOrderHashHex = '0x123';
return expect(zeroEx.exchange.getUnavailableTakerAmountAsync(invalidOrderHashHex)).to.be.rejected();
return expect(zeroEx.exchange.getUnavailableTakerAmountAsync(
invalidOrderHashHex, exchangeContractAddress,
)).to.be.rejected();
});
it ('should return zero if passed a valid but non-existent orderHash', async () => {
const unavailableValueT = await zeroEx.exchange.getUnavailableTakerAmountAsync(NON_EXISTENT_ORDER_HASH);
const unavailableValueT = await zeroEx.exchange.getUnavailableTakerAmountAsync(
NON_EXISTENT_ORDER_HASH, exchangeContractAddress,
);
expect(unavailableValueT).to.be.bignumber.equal(0);
});
it ('should return the unavailableValueT for a valid and partially filled orderHash', async () => {
const unavailableValueT = await zeroEx.exchange.getUnavailableTakerAmountAsync(orderHash);
const unavailableValueT = await zeroEx.exchange.getUnavailableTakerAmountAsync(
orderHash, exchangeContractAddress,
);
expect(unavailableValueT).to.be.bignumber.equal(partialFillAmount);
});
});
describe('#getFilledTakerAmountAsync', () => {
it ('should throw if passed an invalid orderHash', async () => {
const invalidOrderHashHex = '0x123';
return expect(zeroEx.exchange.getFilledTakerAmountAsync(invalidOrderHashHex)).to.be.rejected();
return expect(zeroEx.exchange.getFilledTakerAmountAsync(
invalidOrderHashHex, exchangeContractAddress,
)).to.be.rejected();
});
it ('should return zero if passed a valid but non-existent orderHash', async () => {
const filledValueT = await zeroEx.exchange.getFilledTakerAmountAsync(NON_EXISTENT_ORDER_HASH);
const filledValueT = await zeroEx.exchange.getFilledTakerAmountAsync(
NON_EXISTENT_ORDER_HASH, exchangeContractAddress,
);
expect(filledValueT).to.be.bignumber.equal(0);
});
it ('should return the filledValueT for a valid and partially filled orderHash', async () => {
const filledValueT = await zeroEx.exchange.getFilledTakerAmountAsync(orderHash);
const filledValueT = await zeroEx.exchange.getFilledTakerAmountAsync(
orderHash, exchangeContractAddress,
);
expect(filledValueT).to.be.bignumber.equal(partialFillAmount);
});
});
describe('#getCanceledTakerAmountAsync', () => {
it ('should throw if passed an invalid orderHash', async () => {
const invalidOrderHashHex = '0x123';
return expect(zeroEx.exchange.getCanceledTakerAmountAsync(invalidOrderHashHex)).to.be.rejected();
return expect(zeroEx.exchange.getCanceledTakerAmountAsync(
invalidOrderHashHex, exchangeContractAddress,
)).to.be.rejected();
});
it ('should return zero if passed a valid but non-existent orderHash', async () => {
const cancelledValueT = await zeroEx.exchange.getCanceledTakerAmountAsync(NON_EXISTENT_ORDER_HASH);
const cancelledValueT = await zeroEx.exchange.getCanceledTakerAmountAsync(
NON_EXISTENT_ORDER_HASH, exchangeContractAddress,
);
expect(cancelledValueT).to.be.bignumber.equal(0);
});
it ('should return the cancelledValueT for a valid and partially filled orderHash', async () => {
const cancelledValueT = await zeroEx.exchange.getCanceledTakerAmountAsync(orderHash);
const cancelledValueT = await zeroEx.exchange.getCanceledTakerAmountAsync(
orderHash, exchangeContractAddress,
);
expect(cancelledValueT).to.be.bignumber.equal(0);
});
it ('should return the cancelledValueT for a valid and cancelled orderHash', async () => {
const cancelAmount = fillableAmount.minus(partialFillAmount);
await zeroEx.exchange.cancelOrderAsync(signedOrder, cancelAmount);
const cancelledValueT = await zeroEx.exchange.getCanceledTakerAmountAsync(orderHash);
const cancelledValueT = await zeroEx.exchange.getCanceledTakerAmountAsync(
orderHash, exchangeContractAddress,
);
expect(cancelledValueT).to.be.bignumber.equal(cancelAmount);
});
});
@@ -672,11 +709,13 @@ describe('ExchangeWrapper', () => {
// Source: https://github.com/mochajs/mocha/issues/2407
it('Should receive the LogFill event when an order is filled', (done: DoneCallback) => {
(async () => {
const zeroExEvent = await zeroEx.exchange.subscribeAsync(ExchangeEvents.LogFill, subscriptionOpts,
indexFilterValues);
const zeroExEvent = await zeroEx.exchange.subscribeAsync(
ExchangeEvents.LogFill, subscriptionOpts, indexFilterValues, exchangeContractAddress,
);
zeroExEvent.watch((err: Error, event: ContractEvent) => {
expect(err).to.be.null();
expect(event).to.not.be.undefined();
expect(event.event).to.be.equal('LogFill');
done();
});
await zeroEx.exchange.fillOrderAsync(
@@ -686,11 +725,13 @@ describe('ExchangeWrapper', () => {
});
it('Should receive the LogCancel event when an order is cancelled', (done: DoneCallback) => {
(async () => {
const zeroExEvent = await zeroEx.exchange.subscribeAsync(ExchangeEvents.LogCancel, subscriptionOpts,
indexFilterValues);
const zeroExEvent = await zeroEx.exchange.subscribeAsync(
ExchangeEvents.LogCancel, subscriptionOpts, indexFilterValues, exchangeContractAddress,
);
zeroExEvent.watch((err: Error, event: ContractEvent) => {
expect(err).to.be.null();
expect(event).to.not.be.undefined();
expect(event.event).to.be.equal('LogCancel');
done();
});
await zeroEx.exchange.cancelOrderAsync(signedOrder, cancelTakerAmountInBaseUnits);
@@ -699,7 +740,7 @@ describe('ExchangeWrapper', () => {
it('Outstanding subscriptions are cancelled when zeroEx.setProviderAsync called', (done: DoneCallback) => {
(async () => {
const eventSubscriptionToBeCancelled = await zeroEx.exchange.subscribeAsync(
ExchangeEvents.LogFill, subscriptionOpts, indexFilterValues,
ExchangeEvents.LogFill, subscriptionOpts, indexFilterValues, exchangeContractAddress,
);
eventSubscriptionToBeCancelled.watch((err: Error, event: ContractEvent) => {
done(new Error('Expected this subscription to have been cancelled'));
@@ -709,11 +750,12 @@ describe('ExchangeWrapper', () => {
await zeroEx.setProviderAsync(newProvider);
const eventSubscriptionToStay = await zeroEx.exchange.subscribeAsync(
ExchangeEvents.LogFill, subscriptionOpts, indexFilterValues,
ExchangeEvents.LogFill, subscriptionOpts, indexFilterValues, exchangeContractAddress,
);
eventSubscriptionToStay.watch((err: Error, event: ContractEvent) => {
expect(err).to.be.null();
expect(event).to.not.be.undefined();
expect(event.event).to.be.equal('LogFill');
done();
});
await zeroEx.exchange.fillOrderAsync(
@@ -724,7 +766,7 @@ describe('ExchangeWrapper', () => {
it('Should stop watch for events when stopWatchingAsync called on the eventEmitter', (done: DoneCallback) => {
(async () => {
const eventSubscriptionToBeStopped = await zeroEx.exchange.subscribeAsync(
ExchangeEvents.LogFill, subscriptionOpts, indexFilterValues,
ExchangeEvents.LogFill, subscriptionOpts, indexFilterValues, exchangeContractAddress,
);
eventSubscriptionToBeStopped.watch((err: Error, event: ContractEvent) => {
done(new Error('Expected this subscription to have been stopped'));
@@ -770,16 +812,29 @@ describe('ExchangeWrapper', () => {
const signedOrder = await fillScenarios.createFillableSignedOrderAsync(
makerTokenAddress, takerTokenAddress, makerAddress, takerAddress, fillableAmount,
);
const orderHash = await zeroEx.getOrderHashHexAsync(signedOrder);
const orderHash = zeroEx.getOrderHashHex(signedOrder);
const orderHashFromContract = await (zeroEx.exchange as any)
._getOrderHashHexUsingContractCallAsync(signedOrder);
expect(orderHash).to.equal(orderHashFromContract);
});
});
describe('#getContractAddressAsync', () => {
it('returns the exchange contract address', async () => {
const exchangeAddress = await zeroEx.exchange.getContractAddressAsync();
assert.isETHAddressHex('exchangeAddress', exchangeAddress);
describe('#getAvailableContractAddressesAsync', () => {
it('returns the exchange contract addresses', async () => {
const exchangeAddresses = await zeroEx.exchange.getAvailableContractAddressesAsync();
_.map(exchangeAddresses, exchangeAddress => {
assert.isETHAddressHex('exchangeAddress', exchangeAddress);
});
});
});
describe('#getProxyAuthorizedContractAddressesAsync', () => {
it('returns the Proxy authorized exchange contract addresses', async () => {
const exchangeAddresses = await zeroEx.exchange.getProxyAuthorizedContractAddressesAsync();
for (const exchangeAddress of exchangeAddresses) {
assert.isETHAddressHex('exchangeAddress', exchangeAddress);
const proxyWrapper = (zeroEx as any)._proxyWrapper as ProxyWrapper;
const isAuthorized = await proxyWrapper.isAuthorizedAsync(exchangeAddress);
expect(isAuthorized).to.be.true();
}
});
});
});

View File

@@ -0,0 +1,23 @@
import * as chai from 'chai';
import {chaiSetup} from './utils/chai_setup';
import {web3Factory} from './utils/web3_factory';
import {ZeroEx} from '../src';
import {ProxyWrapper} from '../src/contract_wrappers/proxy_wrapper';
chaiSetup.configure();
const expect = chai.expect;
describe('ProxyWrapper', () => {
let zeroEx: ZeroEx;
before(async () => {
const web3 = web3Factory.create();
zeroEx = new ZeroEx(web3.currentProvider);
});
describe('#isAuthorizedAsync', () => {
it('should return false if the address is not authorized', async () => {
const proxyWrapper = (zeroEx as any)._proxyWrapper as ProxyWrapper;
const isAuthorized = await proxyWrapper.isAuthorizedAsync(ZeroEx.NULL_ADDRESS);
expect(isAuthorized).to.be.false();
});
});
});

View File

@@ -9,12 +9,15 @@ export class FillScenarios {
private tokens: Token[];
private coinbase: string;
private zrxTokenAddress: string;
constructor(zeroEx: ZeroEx, userAddresses: string[], tokens: Token[], zrxTokenAddress: string) {
private exchangeContractAddress: string;
constructor(zeroEx: ZeroEx, userAddresses: string[],
tokens: Token[], zrxTokenAddress: string, exchangeContractAddress: string) {
this.zeroEx = zeroEx;
this.userAddresses = userAddresses;
this.tokens = tokens;
this.coinbase = userAddresses[0];
this.zrxTokenAddress = zrxTokenAddress;
this.exchangeContractAddress = exchangeContractAddress;
}
public async createFillableSignedOrderAsync(makerTokenAddress: string, takerTokenAddress: string,
makerAddress: string, takerAddress: string,
@@ -103,7 +106,7 @@ export class FillScenarios {
const signedOrder = await orderFactory.createSignedOrderAsync(this.zeroEx,
makerAddress, takerAddress, makerFee, takerFee,
makerFillableAmount, makerTokenAddress, takerFillableAmount, takerTokenAddress,
feeRecepient, expirationUnixTimestampSec);
this.exchangeContractAddress, feeRecepient, expirationUnixTimestampSec);
return signedOrder;
}
}

View File

@@ -13,6 +13,7 @@ export const orderFactory = {
makerTokenAddress: string,
takerTokenAmount: BigNumber.BigNumber,
takerTokenAddress: string,
exchangeContractAddress: string,
feeRecipient: string,
expirationUnixTimestampSec?: BigNumber.BigNumber): Promise<SignedOrder> {
const defaultExpirationUnixTimestampSec = new BigNumber(2524604400); // Close to infinite
@@ -29,10 +30,11 @@ export const orderFactory = {
makerTokenAddress,
takerTokenAddress,
salt: ZeroEx.generatePseudoRandomSalt(),
exchangeContractAddress,
feeRecipient,
expirationUnixTimestampSec,
};
const orderHash = await zeroEx.getOrderHashHexAsync(order);
const orderHash = zeroEx.getOrderHashHex(order);
const ecSignature = await zeroEx.signOrderHashAsync(orderHash, maker);
const signedOrder: SignedOrder = _.assign(order, {ecSignature});
return signedOrder;

259
yarn.lock
View File

@@ -42,11 +42,7 @@
version "2.2.41"
resolved "https://registry.yarnpkg.com/@types/mocha/-/mocha-2.2.41.tgz#e27cf0817153eb9f2713b2d3f6c68f1e1c3ca608"
"@types/node@*":
version "7.0.23"
resolved "https://registry.yarnpkg.com/@types/node/-/node-7.0.23.tgz#ededfd92e61046c32fcad56ea7e1101733fad4a4"
"@types/node@^8.0.1":
"@types/node@*", "@types/node@^8.0.1":
version "8.0.1"
resolved "https://registry.yarnpkg.com/@types/node/-/node-8.0.1.tgz#89c271e0c3b9ebb6a3756dd601336970b6228b77"
@@ -92,6 +88,10 @@ ajv-keywords@^1.1.1:
version "1.5.1"
resolved "https://registry.yarnpkg.com/ajv-keywords/-/ajv-keywords-1.5.1.tgz#314dd0a4b3368fad3dfcdc54ede6171b886daf3c"
ajv-keywords@^2.0.0:
version "2.1.0"
resolved "https://registry.yarnpkg.com/ajv-keywords/-/ajv-keywords-2.1.0.tgz#a296e17f7bfae7c1ce4f7e0de53d29cb32162df0"
ajv@^4.7.0, ajv@^4.9.1:
version "4.11.8"
resolved "https://registry.yarnpkg.com/ajv/-/ajv-4.11.8.tgz#82ffb02b29e662ae53bdc20af15947706739c536"
@@ -99,6 +99,15 @@ ajv@^4.7.0, ajv@^4.9.1:
co "^4.6.0"
json-stable-stringify "^1.0.1"
ajv@^5.1.5:
version "5.2.0"
resolved "https://registry.yarnpkg.com/ajv/-/ajv-5.2.0.tgz#c1735024c5da2ef75cc190713073d44f098bf486"
dependencies:
co "^4.6.0"
fast-deep-equal "^0.1.0"
json-schema-traverse "^0.3.0"
json-stable-stringify "^1.0.1"
align-text@^0.1.1, align-text@^0.1.3:
version "0.1.4"
resolved "https://registry.yarnpkg.com/align-text/-/align-text-0.1.4.tgz#0cd90a561093f35d0a99256c22b7069433fad117"
@@ -239,7 +248,7 @@ async@^0.9.0:
version "0.9.2"
resolved "https://registry.yarnpkg.com/async/-/async-0.9.2.tgz#aea74d5e61c1f899613bf64bda66d4c78f2fd17d"
async@^1.4.0, async@^1.4.2, async@^1.5.2, async@~1.5.0:
async@^1.4.0, async@^1.4.2, async@^1.5.2:
version "1.5.2"
resolved "https://registry.yarnpkg.com/async/-/async-1.5.2.tgz#ec6a61ae56480c0c3cb241c95618e20892f9672a"
@@ -708,10 +717,6 @@ bignumber.js@^4.0.2:
version "2.0.7"
resolved "git+https://github.com/debris/bignumber.js#94d7146671b9719e00a09c29b01a691bc85048c2"
bignumber.js@~2.1.4:
version "2.1.4"
resolved "https://registry.yarnpkg.com/bignumber.js/-/bignumber.js-2.1.4.tgz#29b3bb693dbb238e88b72eac2fb89650888b2d59"
binary-extensions@^1.0.0:
version "1.8.0"
resolved "https://registry.yarnpkg.com/binary-extensions/-/binary-extensions-1.8.0.tgz#48ec8d16df4377eae5fa5884682480af4d95c774"
@@ -720,7 +725,7 @@ bindings@^1.2.1:
version "1.2.1"
resolved "https://registry.yarnpkg.com/bindings/-/bindings-1.2.1.tgz#14ad6113812d2d37d72e67b4cacb4bb726505f11"
bip39@^2.2.0, bip39@~2.2.0:
bip39@^2.2.0:
version "2.2.0"
resolved "https://registry.yarnpkg.com/bip39/-/bip39-2.2.0.tgz#40e73f70674c267f148cdbf8374f2a50be166b0d"
dependencies:
@@ -899,7 +904,7 @@ camelcase-keys@^2.0.0:
camelcase "^2.0.0"
map-obj "^1.0.0"
camelcase@^1.0.2, camelcase@^1.2.1:
camelcase@^1.0.2:
version "1.2.1"
resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-1.2.1.tgz#9bb5304d2e0b56698b2c758b08a3eaa9daa58a39"
@@ -1018,7 +1023,7 @@ cliui@^2.1.0:
right-align "^0.1.1"
wordwrap "0.0.2"
cliui@^3.0.3, cliui@^3.2.0:
cliui@^3.2.0:
version "3.2.0"
resolved "https://registry.yarnpkg.com/cliui/-/cliui-3.2.0.tgz#120601537a916d29940f934da3b48d585a39213d"
dependencies:
@@ -1197,6 +1202,12 @@ currently-unhandled@^0.4.1:
dependencies:
array-find-index "^1.0.1"
d@1:
version "1.0.0"
resolved "https://registry.yarnpkg.com/d/-/d-1.0.0.tgz#754bb5bfe55451da69a58b94d45f4c5b0462d58f"
dependencies:
es5-ext "^0.10.9"
dashdash@^1.12.0:
version "1.14.1"
resolved "https://registry.yarnpkg.com/dashdash/-/dashdash-1.14.1.tgz#853cfa0f7cbe2fed5de20326b8dd581035f6e2f0"
@@ -1403,6 +1414,32 @@ es-to-primitive@^1.1.1:
is-date-object "^1.0.1"
is-symbol "^1.0.1"
es5-ext@^0.10.14, es5-ext@^0.10.9, es5-ext@~0.10.14:
version "0.10.23"
resolved "https://registry.yarnpkg.com/es5-ext/-/es5-ext-0.10.23.tgz#7578b51be974207a5487821b56538c224e4e7b38"
dependencies:
es6-iterator "2"
es6-symbol "~3.1"
es6-iterator@2, es6-iterator@^2.0.1, es6-iterator@~2.0.1:
version "2.0.1"
resolved "https://registry.yarnpkg.com/es6-iterator/-/es6-iterator-2.0.1.tgz#8e319c9f0453bf575d374940a655920e59ca5512"
dependencies:
d "1"
es5-ext "^0.10.14"
es6-symbol "^3.1"
es6-map@^0.1.3:
version "0.1.5"
resolved "https://registry.yarnpkg.com/es6-map/-/es6-map-0.1.5.tgz#9136e0503dcc06a301690f0bb14ff4e364e949f0"
dependencies:
d "1"
es5-ext "~0.10.14"
es6-iterator "~2.0.1"
es6-set "~0.1.5"
es6-symbol "~3.1.1"
event-emitter "~0.3.5"
es6-object-assign@^1.0.3:
version "1.1.0"
resolved "https://registry.yarnpkg.com/es6-object-assign/-/es6-object-assign-1.1.0.tgz#c2c3582656247c39ea107cb1e6652b6f9f24523c"
@@ -1417,14 +1454,60 @@ es6-promisify@^5.0.0:
dependencies:
es6-promise "^4.0.3"
es6-set@~0.1.5:
version "0.1.5"
resolved "https://registry.yarnpkg.com/es6-set/-/es6-set-0.1.5.tgz#d2b3ec5d4d800ced818db538d28974db0a73ccb1"
dependencies:
d "1"
es5-ext "~0.10.14"
es6-iterator "~2.0.1"
es6-symbol "3.1.1"
event-emitter "~0.3.5"
es6-symbol@3.1.1, es6-symbol@^3.1, es6-symbol@^3.1.1, es6-symbol@~3.1, es6-symbol@~3.1.1:
version "3.1.1"
resolved "https://registry.yarnpkg.com/es6-symbol/-/es6-symbol-3.1.1.tgz#bf00ef4fdab6ba1b46ecb7b629b4c7ed5715cc77"
dependencies:
d "1"
es5-ext "~0.10.14"
es6-weak-map@^2.0.1:
version "2.0.2"
resolved "https://registry.yarnpkg.com/es6-weak-map/-/es6-weak-map-2.0.2.tgz#5e3ab32251ffd1538a1f8e5ffa1357772f92d96f"
dependencies:
d "1"
es5-ext "^0.10.14"
es6-iterator "^2.0.1"
es6-symbol "^3.1.1"
escape-string-regexp@1.0.5, escape-string-regexp@^1.0.2, escape-string-regexp@^1.0.5:
version "1.0.5"
resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz#1b61c0562190a8dff6ae3bb2cf0200ca130b86d4"
escope@^3.6.0:
version "3.6.0"
resolved "https://registry.yarnpkg.com/escope/-/escope-3.6.0.tgz#e01975e812781a163a6dadfdd80398dc64c889c3"
dependencies:
es6-map "^0.1.3"
es6-weak-map "^2.0.1"
esrecurse "^4.1.0"
estraverse "^4.1.1"
esprima@^2.6.0:
version "2.7.3"
resolved "https://registry.yarnpkg.com/esprima/-/esprima-2.7.3.tgz#96e3b70d5779f6ad49cd032673d1c312767ba581"
esrecurse@^4.1.0:
version "4.2.0"
resolved "https://registry.yarnpkg.com/esrecurse/-/esrecurse-4.2.0.tgz#fa9568d98d3823f9a41d91e902dcab9ea6e5b163"
dependencies:
estraverse "^4.1.0"
object-assign "^4.0.1"
estraverse@^4.1.0, estraverse@^4.1.1:
version "4.2.0"
resolved "https://registry.yarnpkg.com/estraverse/-/estraverse-4.2.0.tgz#0dee3fed31fcd469618ce7342099fc1afa0bdb13"
esutils@^2.0.2:
version "2.0.2"
resolved "https://registry.yarnpkg.com/esutils/-/esutils-2.0.2.tgz#0abf4f1caa5bcb1f7a9d8acc6dea4faaa04bac9b"
@@ -1468,14 +1551,14 @@ ethereumjs-abi@^0.6.4:
bn.js "^4.10.0"
ethereumjs-util "^4.3.0"
ethereumjs-account@^2.0.3, ethereumjs-account@~2.0.4:
ethereumjs-account@^2.0.3:
version "2.0.4"
resolved "https://registry.yarnpkg.com/ethereumjs-account/-/ethereumjs-account-2.0.4.tgz#f8c30231bcb707f4514d8a052c1f9da103624d47"
dependencies:
ethereumjs-util "^4.0.1"
rlp "^2.0.0"
ethereumjs-block@^1.2.2, ethereumjs-block@~1.2.2:
ethereumjs-block@^1.2.2:
version "1.2.2"
resolved "https://registry.yarnpkg.com/ethereumjs-block/-/ethereumjs-block-1.2.2.tgz#2ec7534a59021b8ec9b83c30e49690c6ebaedda1"
dependencies:
@@ -1485,37 +1568,20 @@ ethereumjs-block@^1.2.2, ethereumjs-block@~1.2.2:
ethereumjs-util "^4.0.1"
merkle-patricia-tree "^2.1.2"
ethereumjs-testrpc@3.0.5:
version "3.0.5"
resolved "https://registry.yarnpkg.com/ethereumjs-testrpc/-/ethereumjs-testrpc-3.0.5.tgz#0d5c5174d0f92278c7cc8785b85a5aafedd7513a"
ethereumjs-testrpc@4.0.1:
version "4.0.1"
resolved "https://registry.yarnpkg.com/ethereumjs-testrpc/-/ethereumjs-testrpc-4.0.1.tgz#af23babff4c36008418bc6de4c80f81606896cad"
dependencies:
async "~1.5.0"
bignumber.js "~2.1.4"
bip39 "~2.2.0"
ethereumjs-account "~2.0.4"
ethereumjs-block "~1.2.2"
ethereumjs-tx "^1.3.0"
ethereumjs-util "~4.5.0"
ethereumjs-vm "~2.0.1"
ethereumjs-wallet "~0.6.0"
fake-merkle-patricia-tree "~1.0.1"
heap "~0.2.6"
merkle-patricia-tree "~2.1.2"
seedrandom "~2.4.2"
shelljs "~0.6.0"
solc "0.4.6"
web3 "~0.16.0"
web3-provider-engine "~8.1.0"
yargs "~3.29.0"
webpack "^3.0.0"
ethereumjs-tx@^1.0.0, ethereumjs-tx@^1.2.0, ethereumjs-tx@^1.3.0:
ethereumjs-tx@^1.0.0, ethereumjs-tx@^1.2.0:
version "1.3.1"
resolved "https://registry.yarnpkg.com/ethereumjs-tx/-/ethereumjs-tx-1.3.1.tgz#d6909abcfb37da6404fc18124d351eda20047dac"
dependencies:
ethereum-common "^0.0.18"
ethereumjs-util "^5.0.0"
ethereumjs-util@^4.0.0, ethereumjs-util@^4.0.1, ethereumjs-util@^4.3.0, ethereumjs-util@^4.4.0, ethereumjs-util@~4.5.0:
ethereumjs-util@^4.0.0, ethereumjs-util@^4.0.1, ethereumjs-util@^4.3.0, ethereumjs-util@^4.4.0:
version "4.5.0"
resolved "https://registry.yarnpkg.com/ethereumjs-util/-/ethereumjs-util-4.5.0.tgz#3e9428b317eebda3d7260d854fddda954b1f1bc6"
dependencies:
@@ -1538,7 +1604,7 @@ ethereumjs-util@^5.0.0, ethereumjs-util@^5.0.1, ethereumjs-util@^5.1.1:
rlp "^2.0.0"
secp256k1 "^3.0.1"
ethereumjs-vm@^2.0.2, ethereumjs-vm@~2.0.1:
ethereumjs-vm@^2.0.2:
version "2.0.2"
resolved "https://registry.yarnpkg.com/ethereumjs-vm/-/ethereumjs-vm-2.0.2.tgz#84e2372a5715a80a62f7f2a312f8c64537e8a842"
dependencies:
@@ -1552,7 +1618,7 @@ ethereumjs-vm@^2.0.2, ethereumjs-vm@~2.0.1:
functional-red-black-tree "^1.0.1"
merkle-patricia-tree "^2.1.2"
ethereumjs-wallet@^0.6.0, ethereumjs-wallet@~0.6.0:
ethereumjs-wallet@^0.6.0:
version "0.6.0"
resolved "https://registry.yarnpkg.com/ethereumjs-wallet/-/ethereumjs-wallet-0.6.0.tgz#82763b1697ee7a796be7155da9dfb49b2f98cfdb"
dependencies:
@@ -1579,6 +1645,13 @@ ethjs-util@^0.1.3:
is-hex-prefixed "1.0.0"
strip-hex-prefix "1.0.0"
event-emitter@~0.3.5:
version "0.3.5"
resolved "https://registry.yarnpkg.com/event-emitter/-/event-emitter-0.3.5.tgz#df8c69eef1647923c7157b9ce83840610b02cc39"
dependencies:
d "1"
es5-ext "~0.10.14"
event-stream@~3.3.0:
version "3.3.4"
resolved "https://registry.yarnpkg.com/event-stream/-/event-stream-3.3.4.tgz#4ab4c9a0f5a54db9338b4c34d86bfce8f4b35571"
@@ -1643,12 +1716,16 @@ extsprintf@1.0.2:
version "1.0.2"
resolved "https://registry.yarnpkg.com/extsprintf/-/extsprintf-1.0.2.tgz#e1080e0658e300b06294990cc70e1502235fd550"
fake-merkle-patricia-tree@^1.0.1, fake-merkle-patricia-tree@~1.0.1:
fake-merkle-patricia-tree@^1.0.1:
version "1.0.1"
resolved "https://registry.yarnpkg.com/fake-merkle-patricia-tree/-/fake-merkle-patricia-tree-1.0.1.tgz#4b8c3acfb520afadf9860b1f14cd8ce3402cddd3"
dependencies:
checkpoint-store "^1.1.0"
fast-deep-equal@^0.1.0:
version "0.1.0"
resolved "https://registry.yarnpkg.com/fast-deep-equal/-/fast-deep-equal-0.1.0.tgz#5c6f4599aba6b333ee3342e2ed978672f1001f8d"
fetch-ponyfill@^4.0.0:
version "4.0.0"
resolved "https://registry.yarnpkg.com/fetch-ponyfill/-/fetch-ponyfill-4.0.0.tgz#18cfe38d69cde42aec71cb3ace79e1f2276293da"
@@ -2019,10 +2096,6 @@ hdkey@^0.7.0:
coinstring "^2.0.0"
secp256k1 "^3.0.1"
heap@~0.2.6:
version "0.2.6"
resolved "https://registry.yarnpkg.com/heap/-/heap-0.2.6.tgz#087e1f10b046932fc8594dd9e6d378afc9d1e5ac"
highlight.js@^9.0.0:
version "9.12.0"
resolved "https://registry.yarnpkg.com/highlight.js/-/highlight.js-9.12.0.tgz#e6d9dbe57cbefe60751f02af336195870c90c01e"
@@ -2401,6 +2474,10 @@ json-rpc-random-id@^1.0.0:
version "1.0.1"
resolved "https://registry.yarnpkg.com/json-rpc-random-id/-/json-rpc-random-id-1.0.1.tgz#ba49d96aded1444dbb8da3d203748acbbcdec8c8"
json-schema-traverse@^0.3.0:
version "0.3.1"
resolved "https://registry.yarnpkg.com/json-schema-traverse/-/json-schema-traverse-0.3.1.tgz#349a6d44c53a51de89b40805c5d5e59b417d3340"
json-schema@0.2.3:
version "0.2.3"
resolved "https://registry.yarnpkg.com/json-schema/-/json-schema-0.2.3.tgz#b480c892e59a2f05954ce727bd3f2a4e882f9e13"
@@ -2752,7 +2829,7 @@ merge-source-map@^1.0.2:
dependencies:
source-map "^0.5.3"
merkle-patricia-tree@^2.1.2, merkle-patricia-tree@~2.1.2:
merkle-patricia-tree@^2.1.2:
version "2.1.2"
resolved "https://registry.yarnpkg.com/merkle-patricia-tree/-/merkle-patricia-tree-2.1.2.tgz#724483d54b75631a48fedda55e114051706a7291"
dependencies:
@@ -3748,10 +3825,6 @@ secp256k1@^3.0.1:
nan "^2.2.1"
prebuild-install "^2.0.0"
seedrandom@~2.4.2:
version "2.4.3"
resolved "https://registry.yarnpkg.com/seedrandom/-/seedrandom-2.4.3.tgz#2438504dad33917314bff18ac4d794f16d6aaecc"
semaphore@>=1.0.1, semaphore@^1.0.3:
version "1.0.5"
resolved "https://registry.yarnpkg.com/semaphore/-/semaphore-1.0.5.tgz#b492576e66af193db95d65e25ec53f5f19798d60"
@@ -3819,10 +3892,6 @@ shelljs@^0.7.0, shelljs@^0.7.3:
interpret "^1.0.0"
rechoir "^0.6.2"
shelljs@~0.6.0:
version "0.6.1"
resolved "https://registry.yarnpkg.com/shelljs/-/shelljs-0.6.1.tgz#ec6211bed1920442088fe0f70b2837232ed2c8a8"
shx@^0.2.2:
version "0.2.2"
resolved "https://registry.yarnpkg.com/shx/-/shx-0.2.2.tgz#0a304d020b0edf1306ad81570e80f0346df58a39"
@@ -3874,7 +3943,7 @@ sntp@1.x.x:
dependencies:
hoek "2.x.x"
solc@0.4.6, solc@^0.4.2:
solc@^0.4.2:
version "0.4.6"
resolved "https://registry.yarnpkg.com/solc/-/solc-0.4.6.tgz#afa929a1ceafc0252cfbb4217c8e2b1dab139db7"
dependencies:
@@ -3887,6 +3956,10 @@ source-list-map@^1.1.1:
version "1.1.2"
resolved "https://registry.yarnpkg.com/source-list-map/-/source-list-map-1.1.2.tgz#9889019d1024cce55cdc069498337ef6186a11a1"
source-list-map@^2.0.0:
version "2.0.0"
resolved "https://registry.yarnpkg.com/source-list-map/-/source-list-map-2.0.0.tgz#aaa47403f7b245a92fbc97ea08f250d6087ed085"
source-map-support@^0.4.15, source-map-support@^0.4.2:
version "0.4.15"
resolved "https://registry.yarnpkg.com/source-map-support/-/source-map-support-0.4.15.tgz#03202df65c06d2bd8c7ec2362a193056fef8d3b1"
@@ -4361,10 +4434,27 @@ uglify-js@^2.6, uglify-js@^2.8.27:
optionalDependencies:
uglify-to-browserify "~1.0.0"
uglify-js@^2.8.29:
version "2.8.29"
resolved "https://registry.yarnpkg.com/uglify-js/-/uglify-js-2.8.29.tgz#29c5733148057bb4e1f75df35b7a9cb72e6a59dd"
dependencies:
source-map "~0.5.1"
yargs "~3.10.0"
optionalDependencies:
uglify-to-browserify "~1.0.0"
uglify-to-browserify@~1.0.0:
version "1.0.2"
resolved "https://registry.yarnpkg.com/uglify-to-browserify/-/uglify-to-browserify-1.0.2.tgz#6e0924d6bda6b5afe349e39a6d632850a0f882b7"
uglifyjs-webpack-plugin@^0.4.4:
version "0.4.6"
resolved "https://registry.yarnpkg.com/uglifyjs-webpack-plugin/-/uglifyjs-webpack-plugin-0.4.6.tgz#b951f4abb6bd617e66f63eb891498e391763e309"
dependencies:
source-map "^0.5.6"
uglify-js "^2.8.29"
webpack-sources "^1.0.1"
uid-number@^0.0.6:
version "0.0.6"
resolved "https://registry.yarnpkg.com/uid-number/-/uid-number-0.0.6.tgz#0ea10e8035e8eb5b8e4449f06da1c730663baa81"
@@ -4499,13 +4589,13 @@ web3-provider-engine@~8.1.0:
xhr "^2.2.0"
xtend "^4.0.1"
web3-typescript-typings@^0.0.9:
version "0.0.9"
resolved "https://registry.yarnpkg.com/web3-typescript-typings/-/web3-typescript-typings-0.0.9.tgz#f0c9e9bfcf0effaf16f3498b3d3883686451428b"
web3-typescript-typings@^0.0.10:
version "0.0.10"
resolved "https://registry.yarnpkg.com/web3-typescript-typings/-/web3-typescript-typings-0.0.10.tgz#8108c80f252fedb5c1670a547da4554112dbd44d"
dependencies:
bignumber.js "^4.0.2"
web3@^0.16.0, web3@~0.16.0:
web3@^0.16.0:
version "0.16.0"
resolved "https://registry.yarnpkg.com/web3/-/web3-0.16.0.tgz#a4554175cd462943035b1f1d39432f741c6b6019"
dependencies:
@@ -4541,6 +4631,13 @@ webpack-sources@^0.2.3:
source-list-map "^1.1.1"
source-map "~0.5.3"
webpack-sources@^1.0.1:
version "1.0.1"
resolved "https://registry.yarnpkg.com/webpack-sources/-/webpack-sources-1.0.1.tgz#c7356436a4d13123be2e2426a05d1dad9cbe65cf"
dependencies:
source-list-map "^2.0.0"
source-map "~0.5.3"
webpack@^2.6.0:
version "2.6.1"
resolved "https://registry.yarnpkg.com/webpack/-/webpack-2.6.1.tgz#2e0457f0abb1ac5df3ab106c69c672f236785f07"
@@ -4567,6 +4664,33 @@ webpack@^2.6.0:
webpack-sources "^0.2.3"
yargs "^6.0.0"
webpack@^3.0.0:
version "3.0.0"
resolved "https://registry.yarnpkg.com/webpack/-/webpack-3.0.0.tgz#ee9bcebf21247f7153cb410168cab45e3a59d4d7"
dependencies:
acorn "^5.0.0"
acorn-dynamic-import "^2.0.0"
ajv "^5.1.5"
ajv-keywords "^2.0.0"
async "^2.1.2"
enhanced-resolve "^3.0.0"
escope "^3.6.0"
interpret "^1.0.0"
json-loader "^0.5.4"
json5 "^0.5.1"
loader-runner "^2.3.0"
loader-utils "^1.1.0"
memory-fs "~0.4.1"
mkdirp "~0.5.0"
node-libs-browser "^2.0.0"
source-map "^0.5.3"
supports-color "^3.1.0"
tapable "~0.2.5"
uglifyjs-webpack-plugin "^0.4.4"
watchpack "^1.3.1"
webpack-sources "^1.0.1"
yargs "^6.0.0"
whatwg-fetch@>=0.10.0:
version "2.0.3"
resolved "https://registry.yarnpkg.com/whatwg-fetch/-/whatwg-fetch-2.0.3.tgz#9c84ec2dcf68187ff00bc64e1274b442176e1c84"
@@ -4595,10 +4719,6 @@ window-size@0.1.0:
version "0.1.0"
resolved "https://registry.yarnpkg.com/window-size/-/window-size-0.1.0.tgz#5438cd2ea93b202efa3a19fe8887aee7c94f9c9d"
window-size@^0.1.2:
version "0.1.4"
resolved "https://registry.yarnpkg.com/window-size/-/window-size-0.1.4.tgz#f8e1aa1ee5a53ec5bf151ffa09742a6ad7697876"
window-size@^0.2.0:
version "0.2.0"
resolved "https://registry.yarnpkg.com/window-size/-/window-size-0.2.0.tgz#b4315bb4214a3d7058ebeee892e13fa24d98b075"
@@ -4657,7 +4777,7 @@ xtend@~2.1.1:
dependencies:
object-keys "~0.4.0"
y18n@^3.2.0, y18n@^3.2.1:
y18n@^3.2.1:
version "3.2.1"
resolved "https://registry.yarnpkg.com/y18n/-/y18n-3.2.1.tgz#6d15fba884c08679c0d77e88e7759e811e07fa41"
@@ -4753,14 +4873,3 @@ yargs@~3.10.0:
cliui "^2.1.0"
decamelize "^1.0.0"
window-size "0.1.0"
yargs@~3.29.0:
version "3.29.0"
resolved "https://registry.yarnpkg.com/yargs/-/yargs-3.29.0.tgz#1aab9660eae79d8b8f675bcaeeab6ee34c2cf69c"
dependencies:
camelcase "^1.2.1"
cliui "^3.0.3"
decamelize "^1.0.0"
os-locale "^1.4.0"
window-size "^0.1.2"
y18n "^3.2.0"