Compare commits
84 Commits
@0xproject
...
@0xproject
Author | SHA1 | Date | |
---|---|---|---|
|
3fc99dbad5 | ||
|
01dd84dced | ||
|
6b92ef733c | ||
|
fe0f4ae257 | ||
|
cf9555debc | ||
|
528008b1a9 | ||
|
5e3576ed69 | ||
|
28ee9e247e | ||
|
a054b485d0 | ||
|
3585326d7e | ||
|
a6046af024 | ||
|
adaff92c92 | ||
|
0499541e11 | ||
|
f08738e133 | ||
|
1fbdc14734 | ||
|
3e683162e9 | ||
|
8e7937bdb6 | ||
|
b36587fac8 | ||
|
3a1f9d01e8 | ||
|
1131d66b3d | ||
|
7104ae4752 | ||
|
2403323463 | ||
|
feb7dfffa1 | ||
|
005e633e2a | ||
|
127fe971e9 | ||
|
3c4bde6ea1 | ||
|
dc19690863 | ||
|
47604384d4 | ||
|
c69984e309 | ||
|
5682cd0048 | ||
|
2896110d4d | ||
|
d05b175e04 | ||
|
10a379077c | ||
|
ffd9b79100 | ||
|
04c07d9006 | ||
|
a3cc5c1dd7 | ||
|
941342cc24 | ||
|
cc471dd127 | ||
|
9b535e3cec | ||
|
9656895726 | ||
|
121b6949a1 | ||
|
fb31c49317 | ||
|
e51f9b3593 | ||
|
d08bfbf705 | ||
|
a10e466fed | ||
|
35bb010c35 | ||
|
0046a0762c | ||
|
c453012a8e | ||
|
1f82c7eadf | ||
|
b6fb8dbb52 | ||
|
30256cbe51 | ||
|
7f46e9af2c | ||
|
417cec9e04 | ||
|
62a55c0135 | ||
|
72336eb393 | ||
|
12d8c0b6af | ||
|
5c232b6a8d | ||
|
f6fd4281a4 | ||
|
4bee63afc6 | ||
|
d186f6148b | ||
|
2b15c03b9a | ||
|
60d879e045 | ||
|
858d1768ce | ||
|
fc2b7f747b | ||
|
207019c7f3 | ||
|
b264bbea84 | ||
|
32efb3e280 | ||
|
1a0d68d49a | ||
|
7dd3b2d38b | ||
|
4bc65faf1a | ||
|
8634551f53 | ||
|
089663ccc1 | ||
|
d1d26f8bf6 | ||
|
1ca86730fa | ||
|
12ae7c009d | ||
|
51b2fce8c1 | ||
|
62fcb51e1a | ||
|
cbc55f2ef8 | ||
|
679f828e4e | ||
|
4a8b4e7398 | ||
|
b6a11ca31e | ||
|
a30ccf2b25 | ||
|
2574405699 | ||
|
39c0064ffb |
@@ -1 +0,0 @@
|
||||
* @abandeali1 @BMillman19 @dekz @fabioberger @LogvinovLeon @Recmo
|
46
CODE_OF_CONDUCT.md
Normal file
46
CODE_OF_CONDUCT.md
Normal file
@@ -0,0 +1,46 @@
|
||||
# Contributor Covenant Code of Conduct
|
||||
|
||||
## Our Pledge
|
||||
|
||||
In the interest of fostering an open and welcoming environment, we as contributors and maintainers pledge to making participation in our project and our community a harassment-free experience for everyone, regardless of age, body size, disability, ethnicity, gender identity and expression, level of experience, nationality, personal appearance, race, religion, or sexual identity and orientation.
|
||||
|
||||
## Our Standards
|
||||
|
||||
Examples of behavior that contributes to creating a positive environment include:
|
||||
|
||||
* Using welcoming and inclusive language
|
||||
* Being respectful of differing viewpoints and experiences
|
||||
* Gracefully accepting constructive criticism
|
||||
* Focusing on what is best for the community
|
||||
* Showing empathy towards other community members
|
||||
|
||||
Examples of unacceptable behavior by participants include:
|
||||
|
||||
* The use of sexualized language or imagery and unwelcome sexual attention or advances
|
||||
* Trolling, insulting/derogatory comments, and personal or political attacks
|
||||
* Public or private harassment
|
||||
* Publishing others' private information, such as a physical or electronic address, without explicit permission
|
||||
* Other conduct which could reasonably be considered inappropriate in a professional setting
|
||||
|
||||
## Our Responsibilities
|
||||
|
||||
Project maintainers are responsible for clarifying the standards of acceptable behavior and are expected to take appropriate and fair corrective action in response to any instances of unacceptable behavior.
|
||||
|
||||
Project maintainers have the right and responsibility to remove, edit, or reject comments, commits, code, wiki edits, issues, and other contributions that are not aligned to this Code of Conduct, or to ban temporarily or permanently any contributor for other behaviors that they deem inappropriate, threatening, offensive, or harmful.
|
||||
|
||||
## Scope
|
||||
|
||||
This Code of Conduct applies both within project spaces and in public spaces when an individual is representing the project or its community. Examples of representing a project or community include using an official project e-mail address, posting via an official social media account, or acting as an appointed representative at an online or offline event. Representation of a project may be further defined and clarified by project maintainers.
|
||||
|
||||
## Enforcement
|
||||
|
||||
Instances of abusive, harassing, or otherwise unacceptable behavior may be reported by contacting the project team at team@0xproject.com. The project team will review and investigate all complaints, and will respond in a way that it deems appropriate to the circumstances. The project team is obligated to maintain confidentiality with regard to the reporter of an incident. Further details of specific enforcement policies may be posted separately.
|
||||
|
||||
Project maintainers who do not follow or enforce the Code of Conduct in good faith may face temporary or permanent repercussions as determined by other members of the project's leadership.
|
||||
|
||||
## Attribution
|
||||
|
||||
This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4, available at [http://contributor-covenant.org/version/1/4][version]
|
||||
|
||||
[homepage]: http://contributor-covenant.org
|
||||
[version]: http://contributor-covenant.org/version/1/4/
|
@@ -1,4 +1,44 @@
|
||||
[
|
||||
{
|
||||
"version": "0.37.0",
|
||||
"changes": [
|
||||
{
|
||||
"note": "Fixed expiration watcher comparator to handle orders with equal expiration times",
|
||||
"pr": 526
|
||||
},
|
||||
{
|
||||
"note": "Update Web3 Provider Engine to 14.0.4",
|
||||
"pr": 555
|
||||
},
|
||||
{
|
||||
"note": "Add `zeroEx.getProvider()`",
|
||||
"pr": 559
|
||||
},
|
||||
{
|
||||
"note": "Move `ZeroExError.InvalidSignature` to `@0xproject/order-utils` `OrderError.InvalidSignature`",
|
||||
"pr": 559
|
||||
}
|
||||
],
|
||||
"timestamp": 1525428773
|
||||
},
|
||||
{
|
||||
"version": "0.36.3",
|
||||
"changes": [
|
||||
{
|
||||
"note": "Move @0xproject/migrations to devDependencies"
|
||||
}
|
||||
],
|
||||
"timestamp": 1524079658
|
||||
},
|
||||
{
|
||||
"timestamp": 1524073495,
|
||||
"version": "0.36.2",
|
||||
"changes": [
|
||||
{
|
||||
"note": "Dependencies updated"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"version": "0.36.1",
|
||||
"changes": [
|
||||
|
@@ -5,12 +5,27 @@ Edit the package's CHANGELOG.json file only.
|
||||
|
||||
CHANGELOG
|
||||
|
||||
## v0.37.0 - _May 4, 2018_
|
||||
|
||||
* Fixed expiration watcher comparator to handle orders with equal expiration times (#526)
|
||||
* Update Web3 Provider Engine to 14.0.4 (#555)
|
||||
* Add `zeroEx.getProvider()` (#559)
|
||||
* Move `ZeroExError.InvalidSignature` to `@0xproject/order-utils` `OrderError.InvalidSignature` (#559)
|
||||
|
||||
## v0.36.3 - _April 18, 2018_
|
||||
|
||||
* Move @0xproject/migrations to devDependencies
|
||||
|
||||
## v0.36.2 - _April 18, 2018_
|
||||
|
||||
* Dependencies updated
|
||||
|
||||
## v0.36.1 - _April 18, 2018_
|
||||
|
||||
* Internal changes and refactoring
|
||||
* Fix redundant expired order removal bug (#527)
|
||||
|
||||
## v0.36.0 - _April 12, 2018_
|
||||
## v0.36.0 - _April 11, 2018_
|
||||
|
||||
* Moved Web3.Provider to `@0xproject/types:Provider` (#501)
|
||||
* Add `zeroEx.exchange.getOrderStateAsync` to allow obtaining current OrderState for a signedOrder (#510)
|
||||
@@ -26,16 +41,16 @@ CHANGELOG
|
||||
* Add `zeroEx.createOrderStateWatcher` to allow creating arbitrary number of OrderStateWatchers (#488)
|
||||
* Added `stateLayer` setting to `OrderStateWatcherConfig` so OrderStateWatcher can be set to monitor different blockchain state layers (#488)
|
||||
|
||||
## v0.33.2 - _March 18, 2018_
|
||||
## v0.33.2 - _March 17, 2018_
|
||||
|
||||
* Consolidate all `console.log` calls into `logUtils` in the `@0xproject/utils` package (#452)
|
||||
* Consolidate `Order`, `SignedOrder`, and `ECSignature` into the `@0xproject/types` package (#456)
|
||||
|
||||
## v0.33.1 - _March 8, 2018_
|
||||
## v0.33.1 - _March 7, 2018_
|
||||
|
||||
* Add missing EthersJs typescript typings as dependency
|
||||
|
||||
## v0.33.0 - _March 4, 2018_
|
||||
## v0.33.0 - _March 3, 2018_
|
||||
|
||||
* Validate and lowercase all addresses in public methods (#373)
|
||||
* Improve validation to force passing contract addresses on private networks (#385)
|
||||
@@ -43,54 +58,54 @@ CHANGELOG
|
||||
* Rename all public `_unsubscribeAll` methods to `unsubscribeAll` (#415)
|
||||
* Move web3 typings from devDep to dep since cannot use this package without it (#429)
|
||||
|
||||
## v0.32.2 - _February 9, 2018_
|
||||
## v0.32.2 - _February 8, 2018_
|
||||
|
||||
* Fix publishing issue where .npmignore was not properly excluding undesired content (#389)
|
||||
|
||||
## v0.32.1 - _February 7, 2018_
|
||||
## v0.32.1 - _February 6, 2018_
|
||||
|
||||
* Reorganized `BlockParamLiteral` export into `@0xproject/types` package (#355)
|
||||
* Now using `abi-gen` package to generate ContractEventArgs types (#371)
|
||||
|
||||
## v0.32.0 - _February 5, 2018_
|
||||
## v0.32.0 - _February 4, 2018_
|
||||
|
||||
* Add `zeroEx.etherToken.getContractAddressIfExists` (#350)
|
||||
* Fixed the bug causing order watcher to throw if there is an event with the same signature but different indexed fields (#366)
|
||||
|
||||
## v0.31.1 - _February 1, 2018_
|
||||
## v0.31.1 - _January 31, 2018_
|
||||
|
||||
* Fix the bug causing order watcher to throw if makerToken === zrx (#357)
|
||||
|
||||
## v0.31.0 - _January 30, 2018_
|
||||
## v0.31.0 - _January 29, 2018_
|
||||
|
||||
* Add the `shouldAddPersonalMessagePrefix` parameter to `signOrderHashAsync` so that the caller can decide on whether to add the personalMessage prefix before relaying the request to the signer. Parity Signer, Ledger and TestRPC add the prefix themselves, Metamask expects it to have already been added. (#349)
|
||||
|
||||
## v0.30.2 - _January 29, 2018_
|
||||
## v0.30.2 - _January 28, 2018_
|
||||
|
||||
* Add Rinkeby testnet addresses to artifacts (#337)
|
||||
* Move @0xproject/types to dependencies from devDependencies fixing missing type errors
|
||||
|
||||
## v0.30.1 - _January 24, 2018_
|
||||
## v0.30.1 - _January 23, 2018_
|
||||
|
||||
* Fix a bug allowing negative fill values (#212)
|
||||
* Fix a bug that made it impossible to pass a custom ZRX address (#341)
|
||||
|
||||
## v0.30.0 - _January 17, 2018_
|
||||
## v0.30.0 - _January 16, 2018_
|
||||
|
||||
* Add an error parameter to the order watcher callback (#312)
|
||||
* Fix a bug making it impossible to catch some errors from awaitTransactionMinedAsync (#312)
|
||||
* Fix a bug in fillOrdersUpTo validation making it impossible to fill up to if user doesn't have enough balance to fully fill all the orders (#321)
|
||||
|
||||
## v0.29.1 - _January 11, 2018_
|
||||
## v0.29.1 - _January 10, 2018_
|
||||
|
||||
* Fixed bignumber config issue #301 (#305)
|
||||
|
||||
## v0.29.0 - _December 28, 2017_
|
||||
## v0.29.0 - _December 27, 2017_
|
||||
|
||||
* Assert baseUnit amount supplied to `toUnitAmount` is integer amount. (#287)
|
||||
* `toBaseUnitAmount` throws if amount supplied has too many decimals (#287)
|
||||
|
||||
## v0.28.0 - _December 20, 2017_
|
||||
## v0.28.0 - _December 19, 2017_
|
||||
|
||||
* Add `etherTokenAddress` arg to `depositAsync` and `withdrawAsync` methods on `zeroEx.etherToken` (#267)
|
||||
* Removed accidentally included `unsubscribeAll` method from `zeroEx.proxy`, `zeroEx.etherToken` and `zeroEx.tokenRegistry` (#267)
|
||||
@@ -102,11 +117,11 @@ CHANGELOG
|
||||
* Support `Deposit` and `Withdraw` events on etherToken (#277)
|
||||
* Improve the error message when taker is not a string (#278)
|
||||
|
||||
## v0.27.1 - _November 28, 2017_
|
||||
## v0.27.1 - _November 27, 2017_
|
||||
|
||||
* Export `TransactionOpts` type
|
||||
|
||||
## v0.27.0 - _November 28, 2017_
|
||||
## v0.27.0 - _November 27, 2017_
|
||||
|
||||
* Make `ZeroExConfig` required parameter of `ZeroEx` constructor (#233)
|
||||
* Add a required property `networkId` to `ZeroExConfig` (#233)
|
||||
@@ -118,65 +133,65 @@ CHANGELOG
|
||||
* All transaction sending methods now call `estimateGas` if no gas amount was supplied (#235)
|
||||
* Modify order validation methods to validate against the `latest` block, not against the `pending` block (#236)
|
||||
|
||||
## v0.26.0 - _November 21, 2017_
|
||||
## v0.26.0 - _November 20, 2017_
|
||||
|
||||
* Add post-formatter for logs converting `blockNumber`, `logIndex`, `transactionIndex` from hexes to numbers (#231)
|
||||
* Remove support for Async callback types when used in Subscribe functions (#222)
|
||||
* In OrderWatcher subscribe to ZRX Token Transfer and Approval events when maker token is different (#225)
|
||||
|
||||
## v0.25.1 - _November 13, 2017_
|
||||
## v0.25.1 - _November 12, 2017_
|
||||
|
||||
* Standardise on Cancelled over Canceled (#217)
|
||||
* Add missing `DecodedLogEvent` type to exported types (#205)
|
||||
* Normalized the transactionReceipt status to be `null|0|1`, 1 meaning transaction execution successful, 0 unsuccessful and `null` if it is a pre-byzantinium transaction. (#200)
|
||||
|
||||
## v0.23.0 - _November 12, 2017_
|
||||
## v0.23.0 - _November 11, 2017_
|
||||
|
||||
* Fixed unhandled promise rejection error in subscribe methods (#209)
|
||||
* Subscribe callbacks now receive an error object as their first argument
|
||||
|
||||
## v0.22.6 - _November 10, 2017_
|
||||
## v0.22.6 - _November 9, 2017_
|
||||
|
||||
* Add a timeout parameter to transaction awaiting (#206)
|
||||
|
||||
## v0.22.5 - _November 7, 2017_
|
||||
## v0.22.5 - _November 6, 2017_
|
||||
|
||||
* Re-publish v0.22.4 to fix publishing issue
|
||||
|
||||
## v0.22.4 - _October 25, 2017_
|
||||
## v0.22.4 - _October 24, 2017_
|
||||
|
||||
* Upgraded bignumber.js to a new version that ships with native typings
|
||||
|
||||
## v0.22.3 - _October 25, 2017_
|
||||
## v0.22.3 - _October 24, 2017_
|
||||
|
||||
* Fixed an issue with new version of testrpc and unlimited proxy allowance (#199)
|
||||
|
||||
## v0.22.2 - _October 24, 2017_
|
||||
## v0.22.2 - _October 23, 2017_
|
||||
|
||||
* Fixed rounding of maker fill amount and incorrect validation of partial fees (#197)
|
||||
|
||||
## v0.22.0 - _October 16, 2017_
|
||||
## v0.22.0 - _October 15, 2017_
|
||||
|
||||
* Started using `OrderFillRequest` interface instead of `OrderFillOrKillRequest` interface for `zeroEx.exchange.batchFillOrKill` (#187)
|
||||
* Removed `OrderFillOrKillRequest` (#187)
|
||||
|
||||
## v0.21.4 - _October 13, 2017_
|
||||
## v0.21.4 - _October 12, 2017_
|
||||
|
||||
* Made 0x.js more type-safe by making `getLogsAsync` and `subscribe/subscribeAsync` generics parametrized with arg type (#194)
|
||||
|
||||
## v0.21.3 - _October 12, 2017_
|
||||
## v0.21.3 - _October 11, 2017_
|
||||
|
||||
* Fixed a bug causing order fills to throw `INSUFFICIENT_TAKER_ALLOWANCE` (#193)
|
||||
|
||||
## v0.21.2 - _October 11, 2017_
|
||||
## v0.21.2 - _October 10, 2017_
|
||||
|
||||
* Exported `ContractEventArg` as a public type (#190)
|
||||
|
||||
## v0.21.1 - _October 11, 2017_
|
||||
## v0.21.1 - _October 10, 2017_
|
||||
|
||||
* Fixed a bug in subscriptions (#189)
|
||||
|
||||
## v0.21.0 - _October 10, 2017_
|
||||
## v0.21.0 - _October 9, 2017_
|
||||
|
||||
* Complete rewrite of subscription logic (#182)
|
||||
* Subscriptions no longer return historical logs. If you want them - use `getLogsAsync`
|
||||
@@ -191,27 +206,27 @@ CHANGELOG
|
||||
* Renamed `zeroEx.token.stopWatchingAllEventsAsync` to `zeroEx.token.unsubscribeAll`
|
||||
* Fixed the batch fills validation by emulating all balance & proxy allowance changes (#185)
|
||||
|
||||
## v0.20.0 - _October 5, 2017_
|
||||
## v0.20.0 - _October 4, 2017_
|
||||
|
||||
* Add `zeroEx.token.getLogsAsync` (#178)
|
||||
* Add `zeroEx.exchange.getLogsAsync` (#178)
|
||||
* Fixed fees validation when one of the tokens transferred is ZRX (#181)
|
||||
|
||||
## v0.19.0 - _September 29, 2017_
|
||||
## v0.19.0 - _September 28, 2017_
|
||||
|
||||
* Made order validation optional (#172)
|
||||
* Added Ropsten testnet support (#173)
|
||||
* Fixed a bug causing awaitTransactionMinedAsync to DDos backend nodes (#175)
|
||||
|
||||
## v0.18.0 - _September 26, 2017_
|
||||
## v0.18.0 - _September 25, 2017_
|
||||
|
||||
* Added `zeroEx.exchange.validateOrderFillableOrThrowAsync` to simplify orderbook pruning (#170)
|
||||
|
||||
## v0.17.0 - _September 26, 2017_
|
||||
## v0.17.0 - _September 25, 2017_
|
||||
|
||||
* Made `zeroEx.exchange.getZRXTokenAddressAsync` public (#171)
|
||||
|
||||
## v0.16.0 - _September 20, 2017_
|
||||
## v0.16.0 - _September 19, 2017_
|
||||
|
||||
* Added the ability to specify custom contract addresses to be used with 0x.js (#165)
|
||||
* ZeroExConfig.exchangeContractAddress
|
||||
@@ -219,48 +234,48 @@ CHANGELOG
|
||||
* ZeroExConfig.etherTokenContractAddress
|
||||
* Added `zeroEx.tokenRegistry.getContractAddressAsync` (#165)
|
||||
|
||||
## v0.15.0 - _September 8, 2017_
|
||||
## v0.15.0 - _September 7, 2017_
|
||||
|
||||
* Added the ability to specify a historical `blockNumber` at which to query the blockchain's state when calling a token or exchange method (#161)
|
||||
|
||||
## v0.14.2 - _September 7, 2017_
|
||||
## v0.14.2 - _September 6, 2017_
|
||||
|
||||
* Fixed an issue with bignumber.js types not found (#160)
|
||||
|
||||
## v0.14.1 - _September 7, 2017_
|
||||
## v0.14.1 - _September 6, 2017_
|
||||
|
||||
* Fixed an issue with Artifact type not found (#159)
|
||||
|
||||
## v0.14.0 - _September 6, 2017_
|
||||
## v0.14.0 - _September 5, 2017_
|
||||
|
||||
* Added `zeroEx.exchange.throwLogErrorsAsErrors` method to public interface (#157)
|
||||
* Fixed an issue with overlapping async intervals in `zeroEx.awaitTransactionMinedAsync` (#157)
|
||||
* Fixed an issue with log decoder returning `BigNumber`s as `strings` (#157)
|
||||
|
||||
## v0.13.0 - _September 6, 2017_
|
||||
## v0.13.0 - _September 5, 2017_
|
||||
|
||||
* Made all the functions submitting transactions to the network to immediately return transaction hash (#151)
|
||||
* Added `zeroEx.awaitTransactionMinedAsync` (#151)
|
||||
* Added `TransactionReceiptWithDecodedLogs`, `LogWithDecodedArgs`, `DecodedLogArgs` to public types (#151)
|
||||
* Added signature validation to `validateFillOrderThrowIfInvalidAsync` (#152)
|
||||
|
||||
## v0.12.1 - _September 2, 2017_
|
||||
## v0.12.1 - _September 1, 2017_
|
||||
|
||||
* Added the support for web3@1.x.x provider (#142)
|
||||
* Added the optional `zeroExConfig` parameter to the constructor of `ZeroEx` (#139)
|
||||
* Added the ability to specify `gasPrice` when instantiating `ZeroEx` (#139)
|
||||
|
||||
## v0.11.0 - _August 24, 2017_
|
||||
## v0.11.0 - _August 23, 2017_
|
||||
|
||||
* Added `zeroEx.token.setUnlimitedProxyAllowanceAsync` (#137)
|
||||
* Added `zeroEx.token.setUnlimitedAllowanceAsync` (#137)
|
||||
* Added `zeroEx.token.UNLIMITED_ALLOWANCE_IN_BASE_UNITS` (#137)
|
||||
|
||||
## v0.10.4 - _August 24, 2017_
|
||||
## v0.10.4 - _August 23, 2017_
|
||||
|
||||
* Fixed a bug where checksummed addresses were being pulled from artifacts and not lower-cased. (#135)
|
||||
|
||||
## v0.10.1 - _August 24, 2017_
|
||||
## v0.10.1 - _August 23, 2017_
|
||||
|
||||
* Added `zeroEx.exchange.validateFillOrderThrowIfInvalidAsync` (#128)
|
||||
* Added `zeroEx.exchange.validateFillOrKillOrderThrowIfInvalidAsync` (#128)
|
||||
@@ -275,20 +290,20 @@ CHANGELOG
|
||||
* Added clear error message when checksummed address is passed to a public method (#124)
|
||||
* Fixes the description of `shouldThrowOnInsufficientBalanceOrAllowance` in docs (#127)
|
||||
|
||||
## v0.9.3 - _August 22, 2017_
|
||||
## v0.9.3 - _August 21, 2017_
|
||||
|
||||
* Update contract artifacts to include latest Kovan and Mainnet deploys (#118)
|
||||
|
||||
## v0.9.2 - _August 21, 2017_
|
||||
## v0.9.2 - _August 20, 2017_
|
||||
|
||||
* *This version was unpublished because of a publishing issue.*
|
||||
* Update contract artifacts to include latest Kovan and Mainnet deploys (#118)
|
||||
|
||||
## v0.9.1 - _August 16, 2017_
|
||||
## v0.9.1 - _August 15, 2017_
|
||||
|
||||
* Fixed the bug causing `zeroEx.token.getBalanceAsync()` to fail if no addresses available (#120)
|
||||
|
||||
## v0.9.0 - _July 26, 2017_
|
||||
## v0.9.0 - _July 25, 2017_
|
||||
|
||||
* Migrated to the new version of smart contracts (#101)
|
||||
* Removed the ability to call methods on multiple authorized Exchange smart contracts (#106)
|
||||
@@ -299,7 +314,7 @@ CHANGELOG
|
||||
* Updated to typescript v2.4 (#104)
|
||||
* Fixed an issue with incorrect balance/allowance validation when ZRX is one of the tokens traded (#109)
|
||||
|
||||
## v0.8.0 - _July 4, 2017_
|
||||
## v0.8.0 - _July 3, 2017_
|
||||
|
||||
* Added the ability to call methods on different authorized versions of the Exchange smart contract (#82)
|
||||
* Updated contract artifacts to reflect latest changes to the smart contracts (0xproject/contracts#59)
|
||||
@@ -312,35 +327,35 @@ CHANGELOG
|
||||
* `zeroEx.tokenRegistry.invalidateContractInstance`
|
||||
* Fixed the bug where `zeroEx.setProviderAsync` didn't invalidate etherToken contract's instance
|
||||
|
||||
## v0.7.1 - _June 26, 2017_
|
||||
## v0.7.1 - _June 25, 2017_
|
||||
|
||||
* Added the ability to convert Ether to wrapped Ether tokens and back via `zeroEx.etherToken.depostAsync` and `zeroEx.etherToken.withdrawAsync` (#81)
|
||||
|
||||
## v0.7.0 - _June 22, 2017_
|
||||
## v0.7.0 - _June 21, 2017_
|
||||
|
||||
* Added Kovan smart contract artifacts (#78)
|
||||
* Started returning fillAmount from `fillOrderAsync` and `fillUpToAsync` (#72)
|
||||
* Started returning cancelledAmount from `cancelOrderAsync` (#72)
|
||||
* Renamed type `LogCancelArgs` to `LogCancelContractEventArgs` and `LogFillArgs` to `LogFillContractEventArgs`
|
||||
|
||||
## v0.6.2 - _June 21, 2017_
|
||||
## v0.6.2 - _June 20, 2017_
|
||||
|
||||
* Reduced bundle size
|
||||
* Improved documentation
|
||||
|
||||
## v0.6.1 - _June 19, 2017_
|
||||
## v0.6.1 - _June 18, 2017_
|
||||
|
||||
* Improved documentation
|
||||
|
||||
## v0.6.0 - _June 19, 2017_
|
||||
## v0.6.0 - _June 18, 2017_
|
||||
|
||||
* Made `ZeroEx` class accept `Web3Provider` instance instead of `Web3` instance
|
||||
* Added types for contract event arguments
|
||||
|
||||
## v0.5.2 - _June 15, 2017_
|
||||
## v0.5.2 - _June 14, 2017_
|
||||
|
||||
* Fixed the bug in `postpublish` script that caused that only unminified UMD bundle was uploaded to release page
|
||||
|
||||
## v0.5.1 - _June 15, 2017_
|
||||
## v0.5.1 - _June 14, 2017_
|
||||
|
||||
* Added `postpublish` script to publish to Github Releases with assets.
|
||||
|
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "0x.js",
|
||||
"version": "0.36.1",
|
||||
"version": "0.36.3",
|
||||
"description": "A javascript library for interacting with the 0x protocol",
|
||||
"keywords": [
|
||||
"0x.js",
|
||||
@@ -26,7 +26,7 @@
|
||||
"build:umd:prod": "NODE_ENV=production webpack",
|
||||
"build:commonjs": "tsc && yarn update_artifacts && copyfiles -u 2 './src/compact_artifacts/**/*.json' ./lib/src/compact_artifacts && copyfiles -u 3 './lib/src/monorepo_scripts/**/*' ./scripts",
|
||||
"test:commonjs": "run-s build:commonjs run_mocha",
|
||||
"run_mocha": "mocha lib/test/**/*_test.js --timeout 10000 --bail --exit",
|
||||
"run_mocha": "mocha lib/test/**/*_test.js lib/test/global_hooks.js --timeout 10000 --bail --exit",
|
||||
"manual:postpublish": "yarn build; node ./scripts/postpublish.js",
|
||||
"docs:stage": "yarn build && node ./scripts/stage_docs.js",
|
||||
"docs:json": "typedoc --excludePrivate --excludeExternals --target ES5 --json $JSON_FILE_PATH $PROJECT_FILES",
|
||||
@@ -63,6 +63,7 @@
|
||||
"devDependencies": {
|
||||
"@0xproject/deployer": "^0.4.1",
|
||||
"@0xproject/dev-utils": "^0.3.6",
|
||||
"@0xproject/migrations": "^0.0.3",
|
||||
"@0xproject/monorepo-scripts": "^0.1.18",
|
||||
"@0xproject/subproviders": "^0.9.0",
|
||||
"@0xproject/tslint-config": "^0.4.16",
|
||||
@@ -92,7 +93,7 @@
|
||||
"tslint": "5.8.0",
|
||||
"typedoc": "0xProject/typedoc",
|
||||
"typescript": "2.7.1",
|
||||
"web3-provider-engine": "^13.0.1",
|
||||
"web3-provider-engine": "^14.0.4",
|
||||
"webpack": "^3.1.0"
|
||||
},
|
||||
"dependencies": {
|
||||
@@ -102,21 +103,19 @@
|
||||
"@0xproject/types": "^0.6.1",
|
||||
"@0xproject/typescript-typings": "^0.2.0",
|
||||
"@0xproject/utils": "^0.5.2",
|
||||
"@0xproject/order-utils": "^0.0.1",
|
||||
"@0xproject/web3-wrapper": "^0.6.1",
|
||||
"bintrees": "^1.0.2",
|
||||
"bn.js": "^4.11.8",
|
||||
"ethereumjs-abi": "^0.6.4",
|
||||
"ethereumjs-blockstream": "^2.0.6",
|
||||
"ethereumjs-util": "^5.1.1",
|
||||
"ethers-contracts": "^2.2.1",
|
||||
"ethers": "^3.0.15",
|
||||
"js-sha3": "^0.7.0",
|
||||
"lodash": "^4.17.4",
|
||||
"uuid": "^3.1.0",
|
||||
"web3": "^0.20.0"
|
||||
},
|
||||
"optionalDependencies": {
|
||||
"@0xproject/migrations": "^0.0.1"
|
||||
},
|
||||
"publishConfig": {
|
||||
"access": "public"
|
||||
}
|
||||
|
@@ -1,4 +1,11 @@
|
||||
import { schemas, SchemaValidator } from '@0xproject/json-schemas';
|
||||
import {
|
||||
generatePseudoRandomSalt,
|
||||
getOrderHashHex,
|
||||
isValidOrderHash,
|
||||
isValidSignature,
|
||||
signOrderHashAsync,
|
||||
} from '@0xproject/order-utils';
|
||||
import { ECSignature, Order, Provider, SignedOrder, TransactionReceiptWithDecodedLogs } from '@0xproject/types';
|
||||
import { AbiDecoder, BigNumber, intervalUtils } from '@0xproject/utils';
|
||||
import { Web3Wrapper } from '@0xproject/web3-wrapper';
|
||||
@@ -19,7 +26,6 @@ import { OrderStateWatcherConfig, ZeroExConfig, ZeroExError } from './types';
|
||||
import { assert } from './utils/assert';
|
||||
import { constants } from './utils/constants';
|
||||
import { decorators } from './utils/decorators';
|
||||
import { signatureUtils } from './utils/signature_utils';
|
||||
import { utils } from './utils/utils';
|
||||
|
||||
/**
|
||||
@@ -33,7 +39,6 @@ export class ZeroEx {
|
||||
* this constant for your convenience.
|
||||
*/
|
||||
public static NULL_ADDRESS = constants.NULL_ADDRESS;
|
||||
|
||||
/**
|
||||
* An instance of the ExchangeWrapper class containing methods for interacting with the 0x Exchange smart contract.
|
||||
*/
|
||||
@@ -58,6 +63,15 @@ export class ZeroEx {
|
||||
*/
|
||||
public proxy: TokenTransferProxyWrapper;
|
||||
private _web3Wrapper: Web3Wrapper;
|
||||
/**
|
||||
* Generates a pseudo-random 256-bit salt.
|
||||
* The salt can be included in a 0x order, ensuring that the order generates a unique orderHash
|
||||
* and will not collide with other outstanding orders that are identical in all other parameters.
|
||||
* @return A pseudo-random 256-bit number that can be used as a salt.
|
||||
*/
|
||||
public static generatePseudoRandomSalt(): BigNumber {
|
||||
return generatePseudoRandomSalt();
|
||||
}
|
||||
/**
|
||||
* Verifies that the elliptic curve signature `signature` was generated
|
||||
* by signing `data` with the private key corresponding to the `signerAddress` address.
|
||||
@@ -67,27 +81,15 @@ export class ZeroEx {
|
||||
* @return Whether the signature is valid for the supplied signerAddress and data.
|
||||
*/
|
||||
public static isValidSignature(data: string, signature: ECSignature, signerAddress: string): boolean {
|
||||
assert.isHexString('data', data);
|
||||
assert.doesConformToSchema('signature', signature, schemas.ecSignatureSchema);
|
||||
assert.isETHAddressHex('signerAddress', signerAddress);
|
||||
const normalizedSignerAddress = signerAddress.toLowerCase();
|
||||
|
||||
const isValidSignature = signatureUtils.isValidSignature(data, signature, normalizedSignerAddress);
|
||||
return isValidSignature;
|
||||
return isValidSignature(data, signature, signerAddress);
|
||||
}
|
||||
/**
|
||||
* Generates a pseudo-random 256-bit salt.
|
||||
* The salt can be included in a 0x order, ensuring that the order generates a unique orderHash
|
||||
* and will not collide with other outstanding orders that are identical in all other parameters.
|
||||
* @return A pseudo-random 256-bit number that can be used as a salt.
|
||||
* Computes the orderHash for a supplied order.
|
||||
* @param order An object that conforms to the Order or SignedOrder interface definitions.
|
||||
* @return The resulting orderHash from hashing the supplied order.
|
||||
*/
|
||||
public static generatePseudoRandomSalt(): BigNumber {
|
||||
// BigNumber.random returns a pseudo-random number between 0 & 1 with a passed in number of decimal places.
|
||||
// Source: https://mikemcl.github.io/bignumber.js/#random
|
||||
const randomNumber = BigNumber.random(constants.MAX_DIGITS_IN_UNSIGNED_256_INT);
|
||||
const factor = new BigNumber(10).pow(constants.MAX_DIGITS_IN_UNSIGNED_256_INT - 1);
|
||||
const salt = randomNumber.times(factor).round();
|
||||
return salt;
|
||||
public static getOrderHashHex(order: Order | SignedOrder): string {
|
||||
return getOrderHashHex(order);
|
||||
}
|
||||
/**
|
||||
* Checks if the supplied hex encoded order hash is valid.
|
||||
@@ -97,12 +99,7 @@ export class ZeroEx {
|
||||
* @return Whether the supplied orderHash has the expected format.
|
||||
*/
|
||||
public static isValidOrderHash(orderHash: string): boolean {
|
||||
// Since this method can be called to check if any arbitrary string conforms to an orderHash's
|
||||
// format, we only assert that we were indeed passed a string.
|
||||
assert.isString('orderHash', orderHash);
|
||||
const schemaValidator = new SchemaValidator();
|
||||
const isValidOrderHash = schemaValidator.validate(orderHash, schemas.orderHashSchema).valid;
|
||||
return isValidOrderHash;
|
||||
return isValidOrderHash(orderHash);
|
||||
}
|
||||
/**
|
||||
* A unit amount is defined as the amount of a token above the specified decimal places (integer part).
|
||||
@@ -132,17 +129,6 @@ export class ZeroEx {
|
||||
const baseUnitAmount = Web3Wrapper.toBaseUnitAmount(amount, decimals);
|
||||
return baseUnitAmount;
|
||||
}
|
||||
/**
|
||||
* Computes the orderHash for a supplied order.
|
||||
* @param order An object that conforms to the Order or SignedOrder interface definitions.
|
||||
* @return The resulting orderHash from hashing the supplied order.
|
||||
*/
|
||||
@decorators.syncZeroExErrorHandler
|
||||
public static getOrderHashHex(order: Order | SignedOrder): string {
|
||||
assert.doesConformToSchema('order', order, schemas.orderSchema);
|
||||
const orderHashHex = utils.getOrderHashHex(order);
|
||||
return orderHashHex;
|
||||
}
|
||||
/**
|
||||
* Instantiates a new ZeroEx instance that provides the public interface to the 0x.js library.
|
||||
* @param provider The Provider instance you would like the 0x.js library to use for interacting with
|
||||
@@ -204,6 +190,13 @@ export class ZeroEx {
|
||||
(this.etherToken as any)._invalidateContractInstance();
|
||||
(this.etherToken as any)._setNetworkId(networkId);
|
||||
}
|
||||
/**
|
||||
* Get the provider instance currently used by 0x.js
|
||||
* @return Web3 provider instance
|
||||
*/
|
||||
public getProvider(): Provider {
|
||||
return this._web3Wrapper.getProvider();
|
||||
}
|
||||
/**
|
||||
* Get user Ethereum addresses available through the supplied web3 provider available for sending transactions.
|
||||
* @return An array of available user Ethereum addresses.
|
||||
@@ -229,41 +222,12 @@ export class ZeroEx {
|
||||
signerAddress: string,
|
||||
shouldAddPersonalMessagePrefix: boolean,
|
||||
): Promise<ECSignature> {
|
||||
assert.isHexString('orderHash', orderHash);
|
||||
await assert.isSenderAddressAsync('signerAddress', signerAddress, this._web3Wrapper);
|
||||
const normalizedSignerAddress = signerAddress.toLowerCase();
|
||||
|
||||
let msgHashHex = orderHash;
|
||||
if (shouldAddPersonalMessagePrefix) {
|
||||
const orderHashBuff = ethUtil.toBuffer(orderHash);
|
||||
const msgHashBuff = ethUtil.hashPersonalMessage(orderHashBuff);
|
||||
msgHashHex = ethUtil.bufferToHex(msgHashBuff);
|
||||
}
|
||||
|
||||
const signature = await this._web3Wrapper.signMessageAsync(normalizedSignerAddress, msgHashHex);
|
||||
|
||||
// HACK: There is no consensus on whether the signatureHex string should be formatted as
|
||||
// v + r + s OR r + s + v, and different clients (even different versions of the same client)
|
||||
// return the signature params in different orders. In order to support all client implementations,
|
||||
// we parse the signature in both ways, and evaluate if either one is a valid signature.
|
||||
const validVParamValues = [27, 28];
|
||||
const ecSignatureVRS = signatureUtils.parseSignatureHexAsVRS(signature);
|
||||
if (_.includes(validVParamValues, ecSignatureVRS.v)) {
|
||||
const isValidVRSSignature = ZeroEx.isValidSignature(orderHash, ecSignatureVRS, normalizedSignerAddress);
|
||||
if (isValidVRSSignature) {
|
||||
return ecSignatureVRS;
|
||||
}
|
||||
}
|
||||
|
||||
const ecSignatureRSV = signatureUtils.parseSignatureHexAsRSV(signature);
|
||||
if (_.includes(validVParamValues, ecSignatureRSV.v)) {
|
||||
const isValidRSVSignature = ZeroEx.isValidSignature(orderHash, ecSignatureRSV, normalizedSignerAddress);
|
||||
if (isValidRSVSignature) {
|
||||
return ecSignatureRSV;
|
||||
}
|
||||
}
|
||||
|
||||
throw new Error(ZeroExError.InvalidSignature);
|
||||
return signOrderHashAsync(
|
||||
this._web3Wrapper.getProvider(),
|
||||
orderHash,
|
||||
signerAddress,
|
||||
shouldAddPersonalMessagePrefix,
|
||||
);
|
||||
}
|
||||
/**
|
||||
* Waits for a transaction to be mined and returns the transaction receipt.
|
||||
|
@@ -1,4 +1,5 @@
|
||||
import { schemas } from '@0xproject/json-schemas';
|
||||
import { getOrderHashHex } from '@0xproject/order-utils';
|
||||
import {
|
||||
BlockParamLiteral,
|
||||
DecodedLogArgs,
|
||||
@@ -570,7 +571,7 @@ export class ExchangeWrapper extends ContractWrapper {
|
||||
? SHOULD_VALIDATE_BY_DEFAULT
|
||||
: orderTransactionOpts.shouldValidate;
|
||||
if (shouldValidate) {
|
||||
const orderHash = utils.getOrderHashHex(order);
|
||||
const orderHash = getOrderHashHex(order);
|
||||
const unavailableTakerTokenAmount = await this.getUnavailableTakerAmountAsync(orderHash);
|
||||
OrderValidationUtils.validateCancelOrderThrowIfInvalid(
|
||||
order,
|
||||
@@ -629,7 +630,7 @@ export class ExchangeWrapper extends ContractWrapper {
|
||||
: orderTransactionOpts.shouldValidate;
|
||||
if (shouldValidate) {
|
||||
for (const orderCancellationRequest of orderCancellationRequests) {
|
||||
const orderHash = utils.getOrderHashHex(orderCancellationRequest.order);
|
||||
const orderHash = getOrderHashHex(orderCancellationRequest.order);
|
||||
const unavailableTakerTokenAmount = await this.getUnavailableTakerAmountAsync(orderHash);
|
||||
OrderValidationUtils.validateCancelOrderThrowIfInvalid(
|
||||
orderCancellationRequest.order,
|
||||
@@ -801,7 +802,7 @@ export class ExchangeWrapper extends ContractWrapper {
|
||||
): Promise<void> {
|
||||
assert.doesConformToSchema('order', order, schemas.orderSchema);
|
||||
assert.isValidBaseUnitAmount('cancelTakerTokenAmount', cancelTakerTokenAmount);
|
||||
const orderHash = utils.getOrderHashHex(order);
|
||||
const orderHash = getOrderHashHex(order);
|
||||
const unavailableTakerTokenAmount = await this.getUnavailableTakerAmountAsync(orderHash);
|
||||
OrderValidationUtils.validateCancelOrderThrowIfInvalid(
|
||||
order,
|
||||
|
@@ -22,8 +22,17 @@ export class ExpirationWatcher {
|
||||
this._expirationMarginMs = expirationMarginIfExistsMs || DEFAULT_EXPIRATION_MARGIN_MS;
|
||||
this._orderExpirationCheckingIntervalMs =
|
||||
expirationMarginIfExistsMs || DEFAULT_ORDER_EXPIRATION_CHECKING_INTERVAL_MS;
|
||||
const scoreFunction = (orderHash: string) => this._expiration[orderHash].toNumber();
|
||||
const comparator = (lhs: string, rhs: string) => scoreFunction(lhs) - scoreFunction(rhs);
|
||||
const comparator = (lhsOrderHash: string, rhsOrderHash: string) => {
|
||||
const lhsExpiration = this._expiration[lhsOrderHash].toNumber();
|
||||
const rhsExpiration = this._expiration[rhsOrderHash].toNumber();
|
||||
if (lhsExpiration !== rhsExpiration) {
|
||||
return lhsExpiration - rhsExpiration;
|
||||
} else {
|
||||
// HACK: If two orders have identical expirations, the order in which they are emitted by the
|
||||
// ExpirationWatcher does not matter, so we emit them in alphabetical order by orderHash.
|
||||
return lhsOrderHash.localeCompare(rhsOrderHash);
|
||||
}
|
||||
};
|
||||
this._orderHashByExpirationRBTree = new RBTree(comparator);
|
||||
}
|
||||
public subscribe(callback: (orderHash: string) => void): void {
|
||||
|
@@ -27,7 +27,6 @@ export enum ZeroExError {
|
||||
TokenContractDoesNotExist = 'TOKEN_CONTRACT_DOES_NOT_EXIST',
|
||||
UnhandledError = 'UNHANDLED_ERROR',
|
||||
UserHasNoAssociatedAddress = 'USER_HAS_NO_ASSOCIATED_ADDRESSES',
|
||||
InvalidSignature = 'INVALID_SIGNATURE',
|
||||
ContractNotDeployedOnNetwork = 'CONTRACT_NOT_DEPLOYED_ON_NETWORK',
|
||||
InsufficientAllowanceForTransfer = 'INSUFFICIENT_ALLOWANCE_FOR_TRANSFER',
|
||||
InsufficientBalanceForTransfer = 'INSUFFICIENT_BALANCE_FOR_TRANSFER',
|
||||
|
@@ -8,13 +8,13 @@ import { BigNumber } from '@0xproject/utils';
|
||||
import { Web3Wrapper } from '@0xproject/web3-wrapper';
|
||||
import * as _ from 'lodash';
|
||||
|
||||
import { signatureUtils } from '../utils/signature_utils';
|
||||
import { isValidSignature } from '@0xproject/order-utils';
|
||||
|
||||
export const assert = {
|
||||
...sharedAssert,
|
||||
isValidSignature(orderHash: string, ecSignature: ECSignature, signerAddress: string) {
|
||||
const isValidSignature = signatureUtils.isValidSignature(orderHash, ecSignature, signerAddress);
|
||||
this.assert(isValidSignature, `Expected order with hash '${orderHash}' to have a valid signature`);
|
||||
const isValid = isValidSignature(orderHash, ecSignature, signerAddress);
|
||||
this.assert(isValid, `Expected order with hash '${orderHash}' to have a valid signature`);
|
||||
},
|
||||
async isSenderAddressAsync(
|
||||
variableName: string,
|
||||
@@ -28,8 +28,4 @@ export const assert = {
|
||||
`Specified ${variableName} ${senderAddressHex} isn't available through the supplied web3 provider`,
|
||||
);
|
||||
},
|
||||
async isUserAddressAvailableAsync(web3Wrapper: Web3Wrapper): Promise<void> {
|
||||
const availableAddresses = await web3Wrapper.getAvailableAddressesAsync();
|
||||
this.assert(!_.isEmpty(availableAddresses), 'No addresses were available on the provided web3 provider');
|
||||
},
|
||||
};
|
||||
|
@@ -3,7 +3,6 @@ import { BigNumber } from '@0xproject/utils';
|
||||
export const constants = {
|
||||
NULL_ADDRESS: '0x0000000000000000000000000000000000000000',
|
||||
TESTRPC_NETWORK_ID: 50,
|
||||
MAX_DIGITS_IN_UNSIGNED_256_INT: 78,
|
||||
INVALID_JUMP_PATTERN: 'invalid JUMP at',
|
||||
OUT_OF_GAS_PATTERN: 'out of gas',
|
||||
INVALID_TAKER_FORMAT: 'instance.taker is not of a type(s) string',
|
||||
|
@@ -5,6 +5,7 @@ import * as _ from 'lodash';
|
||||
import { TokenWrapper } from '../contract_wrappers/token_wrapper';
|
||||
import { BalanceAndProxyAllowanceLazyStore } from '../stores/balance_proxy_allowance_lazy_store';
|
||||
import { ExchangeContractErrs, TradeSide, TransferType } from '../types';
|
||||
import { constants } from '../utils/constants';
|
||||
|
||||
enum FailureReason {
|
||||
Balance = 'balance',
|
||||
@@ -66,6 +67,13 @@ export class ExchangeTransferSimulator {
|
||||
tradeSide: TradeSide,
|
||||
transferType: TransferType,
|
||||
): Promise<void> {
|
||||
// HACK: When simulating an open order (e.g taker is NULL_ADDRESS), we don't want to adjust balances/
|
||||
// allowances for the taker. We do however, want to increase the balance of the maker since the maker
|
||||
// might be relying on those funds to fill subsequent orders or pay the order's fees.
|
||||
if (from === constants.NULL_ADDRESS && tradeSide === TradeSide.Taker) {
|
||||
await this._increaseBalanceAsync(tokenAddress, to, amountInBaseUnits);
|
||||
return;
|
||||
}
|
||||
const balance = await this._store.getBalanceAsync(tokenAddress, from);
|
||||
const proxyAllowance = await this._store.getProxyAllowanceAsync(tokenAddress, from);
|
||||
if (proxyAllowance.lessThan(amountInBaseUnits)) {
|
||||
|
@@ -1,3 +1,4 @@
|
||||
import { getOrderHashHex, OrderError } from '@0xproject/order-utils';
|
||||
import { Order, SignedOrder } from '@0xproject/types';
|
||||
import { BigNumber } from '@0xproject/utils';
|
||||
import * as _ from 'lodash';
|
||||
@@ -113,7 +114,7 @@ export class OrderValidationUtils {
|
||||
zrxTokenAddress: string,
|
||||
expectedFillTakerTokenAmount?: BigNumber,
|
||||
): Promise<void> {
|
||||
const orderHash = utils.getOrderHashHex(signedOrder);
|
||||
const orderHash = getOrderHashHex(signedOrder);
|
||||
const unavailableTakerTokenAmount = await this._exchangeWrapper.getUnavailableTakerAmountAsync(orderHash);
|
||||
OrderValidationUtils._validateRemainingFillAmountNotZeroOrThrow(
|
||||
signedOrder.takerTokenAmount,
|
||||
@@ -124,31 +125,12 @@ export class OrderValidationUtils {
|
||||
if (!_.isUndefined(expectedFillTakerTokenAmount)) {
|
||||
fillTakerTokenAmount = expectedFillTakerTokenAmount;
|
||||
}
|
||||
const fillMakerTokenAmount = OrderValidationUtils._getPartialAmount(
|
||||
await OrderValidationUtils.validateFillOrderBalancesAllowancesThrowIfInvalidAsync(
|
||||
exchangeTradeEmulator,
|
||||
signedOrder,
|
||||
fillTakerTokenAmount,
|
||||
signedOrder.takerTokenAmount,
|
||||
signedOrder.makerTokenAmount,
|
||||
);
|
||||
await exchangeTradeEmulator.transferFromAsync(
|
||||
signedOrder.makerTokenAddress,
|
||||
signedOrder.maker,
|
||||
signedOrder.taker,
|
||||
fillMakerTokenAmount,
|
||||
TradeSide.Maker,
|
||||
TransferType.Trade,
|
||||
);
|
||||
const makerFeeAmount = OrderValidationUtils._getPartialAmount(
|
||||
fillTakerTokenAmount,
|
||||
signedOrder.takerTokenAmount,
|
||||
signedOrder.makerFee,
|
||||
);
|
||||
await exchangeTradeEmulator.transferFromAsync(
|
||||
zrxTokenAddress,
|
||||
signedOrder.maker,
|
||||
signedOrder.feeRecipient,
|
||||
makerFeeAmount,
|
||||
TradeSide.Maker,
|
||||
TransferType.Fee,
|
||||
);
|
||||
}
|
||||
public async validateFillOrderThrowIfInvalidAsync(
|
||||
@@ -161,9 +143,9 @@ export class OrderValidationUtils {
|
||||
if (fillTakerTokenAmount.eq(0)) {
|
||||
throw new Error(ExchangeContractErrs.OrderFillAmountZero);
|
||||
}
|
||||
const orderHash = utils.getOrderHashHex(signedOrder);
|
||||
const orderHash = getOrderHashHex(signedOrder);
|
||||
if (!ZeroEx.isValidSignature(orderHash, signedOrder.ecSignature, signedOrder.maker)) {
|
||||
throw new Error(ZeroExError.InvalidSignature);
|
||||
throw new Error(OrderError.InvalidSignature);
|
||||
}
|
||||
const unavailableTakerTokenAmount = await this._exchangeWrapper.getUnavailableTakerAmountAsync(orderHash);
|
||||
OrderValidationUtils._validateRemainingFillAmountNotZeroOrThrow(
|
||||
|
@@ -1,45 +0,0 @@
|
||||
import { ECSignature } from '@0xproject/types';
|
||||
import * as ethUtil from 'ethereumjs-util';
|
||||
|
||||
export const signatureUtils = {
|
||||
isValidSignature(data: string, signature: ECSignature, signerAddress: string): boolean {
|
||||
const dataBuff = ethUtil.toBuffer(data);
|
||||
const msgHashBuff = ethUtil.hashPersonalMessage(dataBuff);
|
||||
try {
|
||||
const pubKey = ethUtil.ecrecover(
|
||||
msgHashBuff,
|
||||
signature.v,
|
||||
ethUtil.toBuffer(signature.r),
|
||||
ethUtil.toBuffer(signature.s),
|
||||
);
|
||||
const retrievedAddress = ethUtil.bufferToHex(ethUtil.pubToAddress(pubKey));
|
||||
return retrievedAddress === signerAddress;
|
||||
} catch (err) {
|
||||
return false;
|
||||
}
|
||||
},
|
||||
parseSignatureHexAsVRS(signatureHex: string): ECSignature {
|
||||
const signatureBuffer = ethUtil.toBuffer(signatureHex);
|
||||
let v = signatureBuffer[0];
|
||||
if (v < 27) {
|
||||
v += 27;
|
||||
}
|
||||
const r = signatureBuffer.slice(1, 33);
|
||||
const s = signatureBuffer.slice(33, 65);
|
||||
const ecSignature: ECSignature = {
|
||||
v,
|
||||
r: ethUtil.bufferToHex(r),
|
||||
s: ethUtil.bufferToHex(s),
|
||||
};
|
||||
return ecSignature;
|
||||
},
|
||||
parseSignatureHexAsRSV(signatureHex: string): ECSignature {
|
||||
const { v, r, s } = ethUtil.fromRpcSig(signatureHex);
|
||||
const ecSignature: ECSignature = {
|
||||
v,
|
||||
r: ethUtil.bufferToHex(r),
|
||||
s: ethUtil.bufferToHex(s),
|
||||
};
|
||||
return ecSignature;
|
||||
},
|
||||
};
|
@@ -1,59 +1,9 @@
|
||||
import { Order, SignedOrder, SolidityTypes } from '@0xproject/types';
|
||||
import { BigNumber } from '@0xproject/utils';
|
||||
import BN = require('bn.js');
|
||||
import * as ethABI from 'ethereumjs-abi';
|
||||
import * as ethUtil from 'ethereumjs-util';
|
||||
import * as _ from 'lodash';
|
||||
|
||||
export const utils = {
|
||||
/**
|
||||
* Converts BigNumber instance to BN
|
||||
* The only reason we convert to BN is to remain compatible with `ethABI. soliditySHA3` that
|
||||
* expects values of Solidity type `uint` to be passed as type `BN`.
|
||||
* We do not use BN anywhere else in the codebase.
|
||||
*/
|
||||
bigNumberToBN(value: BigNumber) {
|
||||
return new BN(value.toString(), 10);
|
||||
},
|
||||
spawnSwitchErr(name: string, value: any): Error {
|
||||
return new Error(`Unexpected switch value: ${value} encountered for ${name}`);
|
||||
},
|
||||
getOrderHashHex(order: Order | SignedOrder): string {
|
||||
const orderParts = [
|
||||
{ value: order.exchangeContractAddress, type: SolidityTypes.Address },
|
||||
{ value: order.maker, type: SolidityTypes.Address },
|
||||
{ value: order.taker, type: SolidityTypes.Address },
|
||||
{ value: order.makerTokenAddress, type: SolidityTypes.Address },
|
||||
{ value: order.takerTokenAddress, type: SolidityTypes.Address },
|
||||
{ value: order.feeRecipient, type: SolidityTypes.Address },
|
||||
{
|
||||
value: utils.bigNumberToBN(order.makerTokenAmount),
|
||||
type: SolidityTypes.Uint256,
|
||||
},
|
||||
{
|
||||
value: utils.bigNumberToBN(order.takerTokenAmount),
|
||||
type: SolidityTypes.Uint256,
|
||||
},
|
||||
{
|
||||
value: utils.bigNumberToBN(order.makerFee),
|
||||
type: SolidityTypes.Uint256,
|
||||
},
|
||||
{
|
||||
value: utils.bigNumberToBN(order.takerFee),
|
||||
type: SolidityTypes.Uint256,
|
||||
},
|
||||
{
|
||||
value: utils.bigNumberToBN(order.expirationUnixTimestampSec),
|
||||
type: SolidityTypes.Uint256,
|
||||
},
|
||||
{ value: utils.bigNumberToBN(order.salt), type: SolidityTypes.Uint256 },
|
||||
];
|
||||
const types = _.map(orderParts, o => o.type);
|
||||
const values = _.map(orderParts, o => o.value);
|
||||
const hashBuff = ethABI.soliditySHA3(types, values);
|
||||
const hashHex = ethUtil.bufferToHex(hashBuff);
|
||||
return hashHex;
|
||||
},
|
||||
getCurrentUnixTimestampSec(): BigNumber {
|
||||
return new BigNumber(Date.now() / 1000).round();
|
||||
},
|
||||
|
@@ -1,9 +1,4 @@
|
||||
import { Deployer } from '@0xproject/deployer';
|
||||
import { BlockchainLifecycle, devConstants, web3Factory } from '@0xproject/dev-utils';
|
||||
// HACK: This dependency is optional since it is only available when run from within
|
||||
// the monorepo. tslint doesn't handle optional dependencies
|
||||
// tslint:disable-next-line:no-implicit-dependencies
|
||||
import { runMigrationsAsync } from '@0xproject/migrations';
|
||||
import { BigNumber } from '@0xproject/utils';
|
||||
import * as chai from 'chai';
|
||||
import * as _ from 'lodash';
|
||||
@@ -15,7 +10,6 @@ import { ApprovalContractEventArgs, LogWithDecodedArgs, Order, TokenEvents, Zero
|
||||
|
||||
import { chaiSetup } from './utils/chai_setup';
|
||||
import { constants } from './utils/constants';
|
||||
import { deployer } from './utils/deployer';
|
||||
import { TokenUtils } from './utils/token_utils';
|
||||
import { provider, web3Wrapper } from './utils/web3_wrapper';
|
||||
|
||||
@@ -23,12 +17,9 @@ const blockchainLifecycle = new BlockchainLifecycle(web3Wrapper);
|
||||
chaiSetup.configure();
|
||||
const expect = chai.expect;
|
||||
|
||||
const SHOULD_ADD_PERSONAL_MESSAGE_PREFIX = false;
|
||||
|
||||
describe('ZeroEx library', () => {
|
||||
let zeroEx: ZeroEx;
|
||||
before(async () => {
|
||||
await runMigrationsAsync(deployer);
|
||||
const config = {
|
||||
networkId: constants.TESTRPC_NETWORK_ID,
|
||||
};
|
||||
@@ -70,14 +61,12 @@ describe('ZeroEx library', () => {
|
||||
};
|
||||
const address = '0x5409ed021d9299bf6814279a6a1411a7e866a631';
|
||||
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(
|
||||
(zeroEx.exchange as any)._isValidSignatureUsingContractCallAsync('0x0', signature, address),
|
||||
).to.become(false);
|
||||
});
|
||||
it("should return false if the address doesn't pertain to the signature & data", async () => {
|
||||
const validUnrelatedAddress = '0x8b0292b11a196601ed2ce54b665cafeca0347d42';
|
||||
expect(ZeroEx.isValidSignature(dataHex, signature, validUnrelatedAddress)).to.be.false();
|
||||
return expect(
|
||||
(zeroEx.exchange as any)._isValidSignatureUsingContractCallAsync(
|
||||
dataHex,
|
||||
@@ -88,45 +77,16 @@ describe('ZeroEx library', () => {
|
||||
});
|
||||
it("should return false if the signature doesn't pertain to the dataHex & address", async () => {
|
||||
const wrongSignature = _.assign({}, signature, { v: 28 });
|
||||
expect(ZeroEx.isValidSignature(dataHex, wrongSignature, address)).to.be.false();
|
||||
return expect(
|
||||
(zeroEx.exchange as any)._isValidSignatureUsingContractCallAsync(dataHex, wrongSignature, address),
|
||||
).to.become(false);
|
||||
});
|
||||
it('should return true if the signature does pertain to the dataHex & address', async () => {
|
||||
const isValidSignatureLocal = ZeroEx.isValidSignature(dataHex, signature, address);
|
||||
expect(isValidSignatureLocal).to.be.true();
|
||||
return expect(
|
||||
(zeroEx.exchange as any)._isValidSignatureUsingContractCallAsync(dataHex, signature, address),
|
||||
).to.become(true);
|
||||
});
|
||||
});
|
||||
describe('#generateSalt', () => {
|
||||
it('generates different salts', () => {
|
||||
const equal = ZeroEx.generatePseudoRandomSalt().eq(ZeroEx.generatePseudoRandomSalt());
|
||||
expect(equal).to.be.false();
|
||||
});
|
||||
it('generates salt in range [0..2^256)', () => {
|
||||
const salt = ZeroEx.generatePseudoRandomSalt();
|
||||
expect(salt.greaterThanOrEqualTo(0)).to.be.true();
|
||||
const twoPow256 = new BigNumber(2).pow(256);
|
||||
expect(salt.lessThan(twoPow256)).to.be.true();
|
||||
});
|
||||
});
|
||||
describe('#isValidOrderHash', () => {
|
||||
it('returns false if the value is not a hex string', () => {
|
||||
const isValid = ZeroEx.isValidOrderHash('not a hex');
|
||||
expect(isValid).to.be.false();
|
||||
});
|
||||
it('returns false if the length is wrong', () => {
|
||||
const isValid = ZeroEx.isValidOrderHash('0xdeadbeef');
|
||||
expect(isValid).to.be.false();
|
||||
});
|
||||
it('returns true if order hash is correct', () => {
|
||||
const isValid = ZeroEx.isValidOrderHash('0x' + Array(65).join('0'));
|
||||
expect(isValid).to.be.true();
|
||||
});
|
||||
});
|
||||
describe('#toUnitAmount', () => {
|
||||
it('should throw if invalid baseUnit amount supplied as argument', () => {
|
||||
const invalidBaseUnitAmount = new BigNumber(1000000000.4);
|
||||
@@ -159,106 +119,6 @@ describe('ZeroEx library', () => {
|
||||
);
|
||||
});
|
||||
});
|
||||
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),
|
||||
makerTokenAmount: new BigNumber(0),
|
||||
takerTokenAmount: new BigNumber(0),
|
||||
expirationUnixTimestampSec: new BigNumber(0),
|
||||
};
|
||||
it('calculates the order hash', async () => {
|
||||
const orderHash = ZeroEx.getOrderHashHex(order);
|
||||
expect(orderHash).to.be.equal(expectedOrderHash);
|
||||
});
|
||||
it('throws a readable error message if taker format is invalid', async () => {
|
||||
const orderWithInvalidtakerFormat = {
|
||||
...order,
|
||||
taker: (null as any) as string,
|
||||
};
|
||||
const expectedErrorMessage =
|
||||
'Order taker must be of type string. If you want anyone to be able to fill an order - pass ZeroEx.NULL_ADDRESS';
|
||||
expect(() => ZeroEx.getOrderHashHex(orderWithInvalidtakerFormat)).to.throw(expectedErrorMessage);
|
||||
});
|
||||
});
|
||||
describe('#signOrderHashAsync', () => {
|
||||
let stubs: Sinon.SinonStub[] = [];
|
||||
let makerAddress: string;
|
||||
before(async () => {
|
||||
const availableAddreses = await zeroEx.getAvailableAddressesAsync();
|
||||
makerAddress = availableAddreses[0];
|
||||
});
|
||||
afterEach(() => {
|
||||
// clean up any stubs after the test has completed
|
||||
_.each(stubs, s => s.restore());
|
||||
stubs = [];
|
||||
});
|
||||
it('Should return the correct ECSignature', async () => {
|
||||
const orderHash = '0x6927e990021d23b1eb7b8789f6a6feaf98fe104bb0cf8259421b79f9a34222b0';
|
||||
const expectedECSignature = {
|
||||
v: 27,
|
||||
r: '0x61a3ed31b43c8780e905a260a35faefcc527be7516aa11c0256729b5b351bc33',
|
||||
s: '0x40349190569279751135161d22529dc25add4f6069af05be04cacbda2ace2254',
|
||||
};
|
||||
const ecSignature = await zeroEx.signOrderHashAsync(
|
||||
orderHash,
|
||||
makerAddress,
|
||||
SHOULD_ADD_PERSONAL_MESSAGE_PREFIX,
|
||||
);
|
||||
expect(ecSignature).to.deep.equal(expectedECSignature);
|
||||
});
|
||||
it('should return the correct ECSignature for signatureHex concatenated as R + S + V', async () => {
|
||||
const orderHash = '0x34decbedc118904df65f379a175bb39ca18209d6ce41d5ed549d54e6e0a95004';
|
||||
const signature =
|
||||
'0x22109d11d79cb8bf96ed88625e1cd9558800c4073332a9a02857499883ee5ce3050aa3cc1f2c435e67e114cdce54b9527b4f50548342401bc5d2b77adbdacb021b';
|
||||
const expectedECSignature = {
|
||||
v: 27,
|
||||
r: '0x22109d11d79cb8bf96ed88625e1cd9558800c4073332a9a02857499883ee5ce3',
|
||||
s: '0x050aa3cc1f2c435e67e114cdce54b9527b4f50548342401bc5d2b77adbdacb02',
|
||||
};
|
||||
stubs = [
|
||||
Sinon.stub((zeroEx as any)._web3Wrapper, 'signMessageAsync').returns(Promise.resolve(signature)),
|
||||
Sinon.stub(ZeroEx, 'isValidSignature').returns(true),
|
||||
];
|
||||
|
||||
const ecSignature = await zeroEx.signOrderHashAsync(
|
||||
orderHash,
|
||||
makerAddress,
|
||||
SHOULD_ADD_PERSONAL_MESSAGE_PREFIX,
|
||||
);
|
||||
expect(ecSignature).to.deep.equal(expectedECSignature);
|
||||
});
|
||||
it('should return the correct ECSignature for signatureHex concatenated as V + R + S', async () => {
|
||||
const orderHash = '0xc793e33ffded933b76f2f48d9aa3339fc090399d5e7f5dec8d3660f5480793f7';
|
||||
const signature =
|
||||
'0x1bc80bedc6756722672753413efdd749b5adbd4fd552595f59c13427407ee9aee02dea66f25a608bbae457e020fb6decb763deb8b7192abab624997242da248960';
|
||||
const expectedECSignature = {
|
||||
v: 27,
|
||||
r: '0xc80bedc6756722672753413efdd749b5adbd4fd552595f59c13427407ee9aee0',
|
||||
s: '0x2dea66f25a608bbae457e020fb6decb763deb8b7192abab624997242da248960',
|
||||
};
|
||||
stubs = [
|
||||
Sinon.stub((zeroEx as any)._web3Wrapper, 'signMessageAsync').returns(Promise.resolve(signature)),
|
||||
Sinon.stub(ZeroEx, 'isValidSignature').returns(true),
|
||||
];
|
||||
|
||||
const ecSignature = await zeroEx.signOrderHashAsync(
|
||||
orderHash,
|
||||
makerAddress,
|
||||
SHOULD_ADD_PERSONAL_MESSAGE_PREFIX,
|
||||
);
|
||||
expect(ecSignature).to.deep.equal(expectedECSignature);
|
||||
});
|
||||
});
|
||||
describe('#awaitTransactionMinedAsync', () => {
|
||||
beforeEach(async () => {
|
||||
await blockchainLifecycle.startAsync();
|
||||
|
@@ -1,43 +0,0 @@
|
||||
import { web3Factory } from '@0xproject/dev-utils';
|
||||
import * as chai from 'chai';
|
||||
import 'mocha';
|
||||
|
||||
import { ZeroEx } from '../src';
|
||||
import { assert } from '../src/utils/assert';
|
||||
|
||||
import { constants } from './utils/constants';
|
||||
import { provider } from './utils/web3_wrapper';
|
||||
|
||||
const expect = chai.expect;
|
||||
|
||||
describe('Assertion library', () => {
|
||||
const config = {
|
||||
networkId: constants.TESTRPC_NETWORK_ID,
|
||||
};
|
||||
const zeroEx = new ZeroEx(provider, config);
|
||||
describe('#isSenderAddressHexAsync', () => {
|
||||
it('throws when address is invalid', async () => {
|
||||
const address = '0xdeadbeef';
|
||||
const varName = 'address';
|
||||
return expect(
|
||||
assert.isSenderAddressAsync(varName, address, (zeroEx as any)._web3Wrapper),
|
||||
).to.be.rejectedWith(`Expected ${varName} to be of type ETHAddressHex, encountered: ${address}`);
|
||||
});
|
||||
it('throws when address is unavailable', async () => {
|
||||
const validUnrelatedAddress = '0x8b0292b11a196601eddce54b665cafeca0347d42';
|
||||
const varName = 'address';
|
||||
return expect(
|
||||
assert.isSenderAddressAsync(varName, validUnrelatedAddress, (zeroEx as any)._web3Wrapper),
|
||||
).to.be.rejectedWith(
|
||||
`Specified ${varName} ${validUnrelatedAddress} isn't available through the supplied web3 provider`,
|
||||
);
|
||||
});
|
||||
it("doesn't throw if address is available", async () => {
|
||||
const availableAddress = (await zeroEx.getAvailableAddressesAsync())[0];
|
||||
const varName = 'address';
|
||||
return expect(
|
||||
assert.isSenderAddressAsync(varName, availableAddress, (zeroEx as any)._web3Wrapper),
|
||||
).to.become(undefined);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
@@ -153,4 +153,43 @@ describe('ExpirationWatcher', () => {
|
||||
timer.tick(order2Lifetime * 1000);
|
||||
})().catch(done);
|
||||
});
|
||||
it('emits events in correct order when expirations are equal', (done: DoneCallback) => {
|
||||
(async () => {
|
||||
const order1Lifetime = 60;
|
||||
const order2Lifetime = 60;
|
||||
const order1ExpirationUnixTimestampSec = currentUnixTimestampSec.plus(order1Lifetime);
|
||||
const order2ExpirationUnixTimestampSec = currentUnixTimestampSec.plus(order2Lifetime);
|
||||
const signedOrder1 = await fillScenarios.createFillableSignedOrderAsync(
|
||||
makerTokenAddress,
|
||||
takerTokenAddress,
|
||||
makerAddress,
|
||||
takerAddress,
|
||||
fillableAmount,
|
||||
order1ExpirationUnixTimestampSec,
|
||||
);
|
||||
const signedOrder2 = await fillScenarios.createFillableSignedOrderAsync(
|
||||
makerTokenAddress,
|
||||
takerTokenAddress,
|
||||
makerAddress,
|
||||
takerAddress,
|
||||
fillableAmount,
|
||||
order2ExpirationUnixTimestampSec,
|
||||
);
|
||||
const orderHash1 = ZeroEx.getOrderHashHex(signedOrder1);
|
||||
const orderHash2 = ZeroEx.getOrderHashHex(signedOrder2);
|
||||
expirationWatcher.addOrder(orderHash1, signedOrder1.expirationUnixTimestampSec.times(1000));
|
||||
expirationWatcher.addOrder(orderHash2, signedOrder2.expirationUnixTimestampSec.times(1000));
|
||||
const expirationOrder = orderHash1 < orderHash2 ? [orderHash1, orderHash2] : [orderHash2, orderHash1];
|
||||
const expectToBeCalledOnce = false;
|
||||
const callbackAsync = reportNoErrorCallbackErrors(done, expectToBeCalledOnce)((hash: string) => {
|
||||
const orderHash = expirationOrder.shift();
|
||||
expect(hash).to.be.equal(orderHash);
|
||||
if (_.isEmpty(expirationOrder)) {
|
||||
done();
|
||||
}
|
||||
});
|
||||
expirationWatcher.subscribe(callbackAsync);
|
||||
timer.tick(order2Lifetime * 1000);
|
||||
})().catch(done);
|
||||
});
|
||||
});
|
||||
|
7
packages/0x.js/test/global_hooks.ts
Normal file
7
packages/0x.js/test/global_hooks.ts
Normal file
@@ -0,0 +1,7 @@
|
||||
import { runMigrationsAsync } from '@0xproject/migrations';
|
||||
|
||||
import { deployer } from './utils/deployer';
|
||||
|
||||
before('migrate contracts', async () => {
|
||||
await runMigrationsAsync(deployer);
|
||||
});
|
@@ -1,4 +1,5 @@
|
||||
import { BlockchainLifecycle, devConstants } from '@0xproject/dev-utils';
|
||||
import { OrderError } from '@0xproject/order-utils';
|
||||
import { BlockParamLiteral } from '@0xproject/types';
|
||||
import { BigNumber } from '@0xproject/utils';
|
||||
import * as chai from 'chai';
|
||||
@@ -68,6 +69,40 @@ describe('OrderValidation', () => {
|
||||
);
|
||||
await zeroEx.exchange.validateOrderFillableOrThrowAsync(signedOrder);
|
||||
});
|
||||
it('should succeed if the maker is buying ZRX and has no ZRX balance', async () => {
|
||||
const makerFee = new BigNumber(2);
|
||||
const takerFee = new BigNumber(2);
|
||||
const signedOrder = await fillScenarios.createFillableSignedOrderWithFeesAsync(
|
||||
makerTokenAddress,
|
||||
zrxTokenAddress,
|
||||
makerFee,
|
||||
takerFee,
|
||||
makerAddress,
|
||||
takerAddress,
|
||||
fillableAmount,
|
||||
feeRecipient,
|
||||
);
|
||||
const zrxMakerBalance = await zeroEx.token.getBalanceAsync(zrxTokenAddress, makerAddress);
|
||||
await zeroEx.token.transferAsync(zrxTokenAddress, makerAddress, takerAddress, zrxMakerBalance);
|
||||
await zeroEx.exchange.validateOrderFillableOrThrowAsync(signedOrder);
|
||||
});
|
||||
it('should succeed if the maker is buying ZRX and has no ZRX balance and there is no specified taker', async () => {
|
||||
const makerFee = new BigNumber(2);
|
||||
const takerFee = new BigNumber(2);
|
||||
const signedOrder = await fillScenarios.createFillableSignedOrderWithFeesAsync(
|
||||
makerTokenAddress,
|
||||
zrxTokenAddress,
|
||||
makerFee,
|
||||
takerFee,
|
||||
makerAddress,
|
||||
constants.NULL_ADDRESS,
|
||||
fillableAmount,
|
||||
feeRecipient,
|
||||
);
|
||||
const zrxMakerBalance = await zeroEx.token.getBalanceAsync(zrxTokenAddress, makerAddress);
|
||||
await zeroEx.token.transferAsync(zrxTokenAddress, makerAddress, takerAddress, zrxMakerBalance);
|
||||
await zeroEx.exchange.validateOrderFillableOrThrowAsync(signedOrder);
|
||||
});
|
||||
it('should succeed if the order is asymmetric and fillable', async () => {
|
||||
const makerFillableAmount = fillableAmount;
|
||||
const takerFillableAmount = fillableAmount.minus(4);
|
||||
@@ -135,7 +170,7 @@ describe('OrderValidation', () => {
|
||||
signedOrder.ecSignature.v = 28 - signedOrder.ecSignature.v + 27;
|
||||
return expect(
|
||||
zeroEx.exchange.validateFillOrderThrowIfInvalidAsync(signedOrder, fillableAmount, takerAddress),
|
||||
).to.be.rejectedWith(ZeroExError.InvalidSignature);
|
||||
).to.be.rejectedWith(OrderError.InvalidSignature);
|
||||
});
|
||||
it('should throw when the order is fully filled or cancelled', async () => {
|
||||
const signedOrder = await fillScenarios.createFillableSignedOrderAsync(
|
||||
@@ -469,4 +504,4 @@ describe('OrderValidation', () => {
|
||||
expect(partialTakerFee).to.be.bignumber.equal(takerPartialFee);
|
||||
});
|
||||
});
|
||||
});
|
||||
}); // tslint:disable-line:max-file-line-count
|
||||
|
@@ -1,10 +1,10 @@
|
||||
import { orderFactory } from '@0xproject/order-utils';
|
||||
import { BigNumber } from '@0xproject/utils';
|
||||
import { Web3Wrapper } from '@0xproject/web3-wrapper';
|
||||
|
||||
import { SignedOrder, Token, ZeroEx } from '../../src';
|
||||
import { artifacts } from '../../src/artifacts';
|
||||
import { DummyTokenContract } from '../../src/contract_wrappers/generated/dummy_token';
|
||||
import { orderFactory } from '../utils/order_factory';
|
||||
|
||||
import { constants } from './constants';
|
||||
|
||||
@@ -164,7 +164,7 @@ export class FillScenarios {
|
||||
]);
|
||||
|
||||
const signedOrder = await orderFactory.createSignedOrderAsync(
|
||||
this._zeroEx,
|
||||
this._zeroEx.getProvider(),
|
||||
makerAddress,
|
||||
takerAddress,
|
||||
makerFee,
|
||||
|
@@ -1,9 +1,6 @@
|
||||
import { devConstants, web3Factory } from '@0xproject/dev-utils';
|
||||
import { Provider } from '@0xproject/types';
|
||||
import { Web3Wrapper } from '@0xproject/web3-wrapper';
|
||||
import * as Web3 from 'web3';
|
||||
|
||||
import { constants } from './constants';
|
||||
|
||||
const web3 = web3Factory.create({ shouldUseInProcessGanache: true });
|
||||
const provider: Provider = web3.currentProvider;
|
||||
|
@@ -1,4 +1,13 @@
|
||||
[
|
||||
{
|
||||
"timestamp": 1525428773,
|
||||
"version": "0.2.12",
|
||||
"changes": [
|
||||
{
|
||||
"note": "Dependencies updated"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"timestamp": 1524044013,
|
||||
"version": "0.2.11",
|
||||
|
@@ -5,11 +5,15 @@ Edit the package's CHANGELOG.json file only.
|
||||
|
||||
CHANGELOG
|
||||
|
||||
## v0.2.12 - _May 4, 2018_
|
||||
|
||||
* Dependencies updated
|
||||
|
||||
## v0.2.11 - _April 18, 2018_
|
||||
|
||||
* Dependencies updated
|
||||
|
||||
## v0.2.10 - _April 12, 2018_
|
||||
## v0.2.10 - _April 11, 2018_
|
||||
|
||||
* Dependencies updated
|
||||
|
||||
@@ -21,26 +25,26 @@ CHANGELOG
|
||||
|
||||
* Dependencies updated
|
||||
|
||||
## v0.2.5 - _March 18, 2018_
|
||||
## v0.2.5 - _March 17, 2018_
|
||||
|
||||
* Consolidate all `console.log` calls into `logUtils` in the `@0xproject/utils` package (#452)
|
||||
|
||||
## v0.2.4 - _March 4, 2018_
|
||||
## v0.2.4 - _March 3, 2018_
|
||||
|
||||
* Add a `backend` parameter that allows you to specify the Ethereum library you use in your templates (`web3` or `ethers`). Ethers auto-converts small ints to numbers whereas Web3 doesn't. Defaults to `web3` (#413)
|
||||
* Add support for [tuple types](https://solidity.readthedocs.io/en/develop/abi-spec.html#handling-tuple-types) (#413)
|
||||
* Add `hasReturnValue` to context data (#413)
|
||||
|
||||
## v0.2.1 - _February 9, 2018_
|
||||
## v0.2.1 - _February 8, 2018_
|
||||
|
||||
* Fix publishing issue where .npmignore was not properly excluding undesired content (#389)
|
||||
|
||||
## v0.2.0 - _February 7, 2018_
|
||||
## v0.2.0 - _February 6, 2018_
|
||||
|
||||
* Added CLI options for explicit specifying location of partials and main template (#346)
|
||||
* Added CLI option to specify networkId, adding support for the JSON artifact format found in @0xproject/contracts (#388)
|
||||
|
||||
## v0.1.0 - _January 11, 2018_
|
||||
## v0.1.0 - _January 10, 2018_
|
||||
|
||||
* Fixed array typings with union types (#295)
|
||||
* Add event ABIs to context data passed to templates (#302)
|
||||
|
@@ -1,4 +1,13 @@
|
||||
[
|
||||
{
|
||||
"timestamp": 1525428773,
|
||||
"version": "0.2.8",
|
||||
"changes": [
|
||||
{
|
||||
"note": "Dependencies updated"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"timestamp": 1524044013,
|
||||
"version": "0.2.7",
|
||||
|
@@ -5,11 +5,15 @@ Edit the package's CHANGELOG.json file only.
|
||||
|
||||
CHANGELOG
|
||||
|
||||
## v0.2.8 - _May 4, 2018_
|
||||
|
||||
* Dependencies updated
|
||||
|
||||
## v0.2.7 - _April 18, 2018_
|
||||
|
||||
* Dependencies updated
|
||||
|
||||
## v0.2.6 - _April 12, 2018_
|
||||
## v0.2.6 - _April 11, 2018_
|
||||
|
||||
* Dependencies updated
|
||||
|
||||
@@ -21,20 +25,20 @@ CHANGELOG
|
||||
|
||||
* Dependencies updated
|
||||
|
||||
## v0.2.0 - _March 8, 2018_
|
||||
## v0.2.0 - _March 7, 2018_
|
||||
|
||||
* Rename `isHttpUrl` to `isWebUri` (#412)
|
||||
|
||||
## v0.1.0 - _March 4, 2018_
|
||||
## v0.1.0 - _March 3, 2018_
|
||||
|
||||
* Remove isETHAddressHex checksum address check and assume address will be lowercased (#373)
|
||||
* Add an optional parameter `subSchemas` to `doesConformToSchema` method (#385)
|
||||
|
||||
## v0.0.18 - _February 9, 2017_
|
||||
## v0.0.18 - _February 8, 2017_
|
||||
|
||||
* Fix publishing issue where .npmignore was not properly excluding undesired content (#389)
|
||||
|
||||
## v0.0.4 - _November 14, 2017_
|
||||
## v0.0.4 - _November 13, 2017_
|
||||
|
||||
* Re-publish Assert previously published under NPM package @0xproject/0x-assert
|
||||
* Added assertion isValidBaseUnitAmount which checks both that the value is a valid bigNumber and that it does not contain decimals.
|
||||
|
@@ -1,4 +1,14 @@
|
||||
[
|
||||
{
|
||||
"version": "0.3.0",
|
||||
"changes": [
|
||||
{
|
||||
"note": "Update ethers-contracts to ethers.js",
|
||||
"pr": 540
|
||||
}
|
||||
],
|
||||
"timestamp": 1525428773
|
||||
},
|
||||
{
|
||||
"timestamp": 1524044013,
|
||||
"version": "0.2.1",
|
||||
|
@@ -5,11 +5,15 @@ Edit the package's CHANGELOG.json file only.
|
||||
|
||||
CHANGELOG
|
||||
|
||||
## v0.3.0 - _May 4, 2018_
|
||||
|
||||
* Update ethers-contracts to ethers.js (#540)
|
||||
|
||||
## v0.2.1 - _April 18, 2018_
|
||||
|
||||
* Dependencies updated
|
||||
|
||||
## v0.2.0 - _April 12, 2018_
|
||||
## v0.2.0 - _April 11, 2018_
|
||||
|
||||
* Contract wrappers now accept Provider and defaults instead of Web3Wrapper (#501)
|
||||
|
||||
@@ -23,6 +27,6 @@ CHANGELOG
|
||||
|
||||
* Dependencies updated
|
||||
|
||||
## v0.0.2 - _March 4, 2018_
|
||||
## v0.0.2 - _March 3, 2018_
|
||||
|
||||
* Initial release
|
||||
|
@@ -42,7 +42,7 @@
|
||||
"@0xproject/typescript-typings": "^0.2.0",
|
||||
"@0xproject/utils": "^0.5.2",
|
||||
"@0xproject/web3-wrapper": "^0.6.1",
|
||||
"ethers-contracts": "^2.2.1",
|
||||
"ethers": "^3.0.15",
|
||||
"lodash": "^4.17.4"
|
||||
},
|
||||
"publishConfig": {
|
||||
|
@@ -10,13 +10,13 @@ import {
|
||||
} from '@0xproject/types';
|
||||
import { abiUtils, BigNumber } from '@0xproject/utils';
|
||||
import { Web3Wrapper } from '@0xproject/web3-wrapper';
|
||||
import * as ethersContracts from 'ethers-contracts';
|
||||
import * as ethers from 'ethers';
|
||||
import * as _ from 'lodash';
|
||||
|
||||
import { formatABIDataItem } from './utils';
|
||||
|
||||
export interface EthersInterfaceByFunctionSignature {
|
||||
[key: string]: ethersContracts.Interface;
|
||||
[key: string]: ethers.Interface;
|
||||
}
|
||||
|
||||
export class BaseContract {
|
||||
@@ -62,7 +62,7 @@ export class BaseContract {
|
||||
}
|
||||
return txDataWithDefaults;
|
||||
}
|
||||
protected _lookupEthersInterface(functionSignature: string): ethersContracts.Interface {
|
||||
protected _lookupEthersInterface(functionSignature: string): ethers.Interface {
|
||||
const ethersInterface = this._ethersInterfacesByFunctionSignature[functionSignature];
|
||||
if (_.isUndefined(ethersInterface)) {
|
||||
throw new Error(`Failed to lookup method with function signature '${functionSignature}'`);
|
||||
@@ -92,7 +92,7 @@ export class BaseContract {
|
||||
this._ethersInterfacesByFunctionSignature = {};
|
||||
_.each(methodAbis, methodAbi => {
|
||||
const functionSignature = abiUtils.getFunctionSignature(methodAbi);
|
||||
this._ethersInterfacesByFunctionSignature[functionSignature] = new ethersContracts.Interface([methodAbi]);
|
||||
this._ethersInterfacesByFunctionSignature[functionSignature] = new ethers.Interface([methodAbi]);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
@@ -1,4 +1,13 @@
|
||||
[
|
||||
{
|
||||
"timestamp": 1525428773,
|
||||
"version": "0.6.11",
|
||||
"changes": [
|
||||
{
|
||||
"note": "Dependencies updated"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"timestamp": 1524044013,
|
||||
"version": "0.6.10",
|
||||
|
@@ -5,11 +5,15 @@ Edit the package's CHANGELOG.json file only.
|
||||
|
||||
CHANGELOG
|
||||
|
||||
## v0.6.11 - _May 4, 2018_
|
||||
|
||||
* Dependencies updated
|
||||
|
||||
## v0.6.10 - _April 18, 2018_
|
||||
|
||||
* Dependencies updated
|
||||
|
||||
## v0.6.9 - _April 12, 2018_
|
||||
## v0.6.9 - _April 11, 2018_
|
||||
|
||||
* Dependencies updated
|
||||
|
||||
@@ -21,44 +25,44 @@ CHANGELOG
|
||||
|
||||
* Dependencies updated
|
||||
|
||||
## v0.6.4 - _March 18, 2018_
|
||||
## v0.6.4 - _March 17, 2018_
|
||||
|
||||
* Consolidate `Order`, `SignedOrder`, and `ECSignature` into the `@0xproject/types` package (#456)
|
||||
|
||||
## v0.6.2 - _February 16, 2018_
|
||||
## v0.6.2 - _February 15, 2018_
|
||||
|
||||
* Fix JSON parse empty response (#407)
|
||||
|
||||
## v0.6.0 - _February 16, 2018_
|
||||
## v0.6.0 - _February 15, 2018_
|
||||
|
||||
* Add pagination options to HttpClient methods (#393)
|
||||
* Add heartbeat configuration to WebSocketOrderbookChannel constructor (#406)
|
||||
|
||||
## v0.5.7 - _February 9, 2018_
|
||||
## v0.5.7 - _February 8, 2018_
|
||||
|
||||
* Fix publishing issue where .npmignore was not properly excluding undesired content (#389)
|
||||
|
||||
## v0.5.0 - _January 17, 2018_
|
||||
## v0.5.0 - _January 16, 2018_
|
||||
|
||||
* Sanitize api endpoint url and remove trailing slashes (#318)
|
||||
* Improve error message text in HttpClient (#318)
|
||||
* Stop appending '/v0' to api endpoint url in HttpClient (#318)
|
||||
|
||||
## v0.4.0 - _January 11, 2018_
|
||||
## v0.4.0 - _January 10, 2018_
|
||||
|
||||
* Prevent getFeesAsync method on HttpClient from mutating input (#296)
|
||||
|
||||
## v0.3.0 - _December 8, 2017_
|
||||
## v0.3.0 - _December 7, 2017_
|
||||
|
||||
* Expose WebSocketOrderbookChannel and associated types to public interface (#251)
|
||||
* Remove tokenA and tokenB fields from OrdersRequest (#256)
|
||||
|
||||
## v0.2.0 - _November 29, 2017_
|
||||
## v0.2.0 - _November 28, 2017_
|
||||
|
||||
* Add SignedOrder and TokenTradeInfo to the public interface
|
||||
* Add ECSignature and Order to the public interface
|
||||
* Remove dependency on 0x.js
|
||||
|
||||
## v0.1.0 - _November 22, 2017_
|
||||
## v0.1.0 - _November 21, 2017_
|
||||
|
||||
* Provide a HttpClient class for interacting with standard relayer api compliant HTTP urls
|
||||
|
@@ -8,7 +8,7 @@ import { BaseContract } from '@0xproject/base-contract';
|
||||
import { BlockParam, BlockParamLiteral, CallData, ContractAbi, DataItem, MethodAbi, Provider, TxData, TxDataPayable } from '@0xproject/types';
|
||||
import { BigNumber, classUtils, promisify } from '@0xproject/utils';
|
||||
import { Web3Wrapper } from '@0xproject/web3-wrapper';
|
||||
import * as ethersContracts from 'ethers-contracts';
|
||||
import * as ethers from 'ethers';
|
||||
import * as _ from 'lodash';
|
||||
|
||||
{{#if events}}
|
||||
|
@@ -5,20 +5,21 @@ async callAsync(
|
||||
defaultBlock?: BlockParam,
|
||||
): Promise<{{> return_type outputs=outputs}}> {
|
||||
const self = this as any as {{contractName}}Contract;
|
||||
const inputAbi = self._lookupAbi('{{this.functionSignature}}').inputs;
|
||||
const functionSignature = '{{this.functionSignature}}';
|
||||
const inputAbi = self._lookupAbi(functionSignature).inputs;
|
||||
[{{> params inputs=inputs}}] = BaseContract._formatABIDataItemList(inputAbi, [{{> params inputs=inputs}}], BaseContract._bigNumberToString.bind(self));
|
||||
const encodedData = self._lookupEthersInterface('{{this.functionSignature}}').functions.{{this.name}}(
|
||||
const ethersFunction = self._lookupEthersInterface(functionSignature).functions.{{this.name}}(
|
||||
{{> params inputs=inputs}}
|
||||
).data;
|
||||
) as ethers.CallDescription;
|
||||
const encodedData = ethersFunction.data;
|
||||
const callDataWithDefaults = await self._applyDefaultsToTxDataAsync(
|
||||
{
|
||||
data: encodedData,
|
||||
}
|
||||
)
|
||||
const rawCallResult = await self._web3Wrapper.callAsync(callDataWithDefaults, defaultBlock);
|
||||
let resultArray = ethersFunction.parse(rawCallResult);
|
||||
const outputAbi = (_.find(self.abi, {name: '{{this.name}}'}) as MethodAbi).outputs;
|
||||
const outputParamsTypes = _.map(outputAbi, 'type');
|
||||
let resultArray = ethersContracts.Interface.decodeParams(outputParamsTypes, rawCallResult) as any;
|
||||
resultArray = BaseContract._formatABIDataItemList(outputAbi, resultArray, BaseContract._lowercaseAddress.bind(this));
|
||||
resultArray = BaseContract._formatABIDataItemList(outputAbi, resultArray, BaseContract._bnToBigNumber.bind(this));
|
||||
return resultArray{{#singleReturnValue}}[0]{{/singleReturnValue}};
|
||||
|
@@ -1,6 +1,6 @@
|
||||
{{#if outputs.length}}
|
||||
{{#singleReturnValue}}
|
||||
{{#returnType outputs.0.type components}}{{/returnType}}
|
||||
{{#returnType outputs.0.type outputs.0.components}}{{/returnType}}
|
||||
{{/singleReturnValue}}
|
||||
{{^singleReturnValue}}
|
||||
[{{#each outputs}}{{#returnType type components}}{{/returnType}}{{#unless @last}}, {{/unless}}{{/each}}]
|
||||
|
@@ -52,7 +52,7 @@ public {{this.tsName}} = {
|
||||
const self = this as any as {{contractName}}Contract;
|
||||
const inputAbi = self._lookupAbi('{{this.functionSignature}}').inputs;
|
||||
[{{> params inputs=inputs}}] = BaseContract._formatABIDataItemList(inputAbi, [{{> params inputs=inputs}}], BaseContract._bigNumberToString.bind(self));
|
||||
const abiEncodedTransactionData = self._lookupEthersInterface('{{this.name}}').functions.{{this.name}}(
|
||||
const abiEncodedTransactionData = self._lookupEthersInterface('{{this.functionSignature}}').functions.{{this.name}}(
|
||||
{{> params inputs=inputs}}
|
||||
).data;
|
||||
return abiEncodedTransactionData;
|
||||
|
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"private": true,
|
||||
"name": "contracts",
|
||||
"version": "2.1.23",
|
||||
"version": "2.1.25",
|
||||
"description": "Smart contract components of 0x protocol",
|
||||
"main": "index.js",
|
||||
"directories": {
|
||||
@@ -54,13 +54,13 @@
|
||||
"npm-run-all": "^4.1.2",
|
||||
"prettier": "^1.11.1",
|
||||
"shx": "^0.2.2",
|
||||
"solc": "^0.4.22",
|
||||
"solc": "^0.4.23",
|
||||
"tslint": "5.8.0",
|
||||
"typescript": "2.7.1",
|
||||
"yargs": "^10.0.3"
|
||||
},
|
||||
"dependencies": {
|
||||
"0x.js": "^0.36.1",
|
||||
"0x.js": "^0.36.3",
|
||||
"@0xproject/deployer": "^0.4.1",
|
||||
"@0xproject/types": "^0.6.1",
|
||||
"@0xproject/typescript-typings": "^0.2.0",
|
||||
|
@@ -1,4 +1,14 @@
|
||||
[
|
||||
{
|
||||
"version": "0.4.2",
|
||||
"changes": [
|
||||
{
|
||||
"note": "Add support for solidity 0.4.23",
|
||||
"pr": 545
|
||||
}
|
||||
],
|
||||
"timestamp": 1525428773
|
||||
},
|
||||
{
|
||||
"version": "0.4.1",
|
||||
"changes": [
|
||||
|
@@ -5,11 +5,15 @@ Edit the package's CHANGELOG.json file only.
|
||||
|
||||
CHANGELOG
|
||||
|
||||
## v0.4.2 - _May 4, 2018_
|
||||
|
||||
* Add support for solidity 0.4.23 (#545)
|
||||
|
||||
## v0.4.1 - _April 18, 2018_
|
||||
|
||||
* Add support for solidity 0.4.22 (#531)
|
||||
|
||||
## v0.4.0 - _April 12, 2018_
|
||||
## v0.4.0 - _April 11, 2018_
|
||||
|
||||
* Changed the config key `web3Provider` to `provider` to be consistent with other tools (#501)
|
||||
|
||||
@@ -21,11 +25,11 @@ CHANGELOG
|
||||
|
||||
* Create solc_bin directory if does not exist before attempting to compile (#491)
|
||||
|
||||
## v0.3.1 - _March 18, 2018_
|
||||
## v0.3.1 - _March 17, 2018_
|
||||
|
||||
* Add TS types for `yargs`
|
||||
|
||||
## v0.3.0 - _March 18, 2018_
|
||||
## v0.3.0 - _March 17, 2018_
|
||||
|
||||
* Add support for Solidity 0.4.20 and 0.4.21
|
||||
* Replace `jsonrpcPort` config with `jsonrpcUrl` (#426)
|
||||
@@ -38,15 +42,15 @@ CHANGELOG
|
||||
* Consolidate all `console.log` calls into `logUtils` in the `@0xproject/utils` package (#452)
|
||||
* Add `#!/usr/bin/env node` pragma above `cli.ts` script to fix command-line error.
|
||||
|
||||
## v0.2.0 - _March 4, 2018_
|
||||
## v0.2.0 - _March 3, 2018_
|
||||
|
||||
* Check dependencies when determining if contracts should be recompiled (#408)
|
||||
* Improve an error message for when deployer is supplied with an incorrect number of constructor arguments (#419)
|
||||
|
||||
## v0.1.0 - _February 16, 2018_
|
||||
## v0.1.0 - _February 15, 2018_
|
||||
|
||||
* Add the ability to pass in specific contracts to compile in CLI (#400)
|
||||
|
||||
## v0.0.8 - _February 9, 2018_
|
||||
## v0.0.8 - _February 8, 2018_
|
||||
|
||||
* Fix publishing issue where .npmignore was not properly excluding undesired content (#389)
|
||||
|
@@ -81,7 +81,7 @@
|
||||
"lodash": "^4.17.4",
|
||||
"require-from-string": "^2.0.1",
|
||||
"semver": "^5.5.0",
|
||||
"solc": "^0.4.22",
|
||||
"solc": "^0.4.23",
|
||||
"web3": "^0.20.0",
|
||||
"web3-eth-abi": "^1.0.0-beta.24",
|
||||
"yargs": "^10.0.3"
|
||||
|
@@ -16,4 +16,5 @@ export const binPaths: BinaryPaths = {
|
||||
'0.4.20': 'soljson-v0.4.20+commit.3155dd80.js',
|
||||
'0.4.21': 'soljson-v0.4.21+commit.dfe3193c.js',
|
||||
'0.4.22': 'soljson-v0.4.22+commit.4cb486ee.js',
|
||||
'0.4.23': 'soljson-v0.4.23+commit.124ca40d.js',
|
||||
};
|
||||
|
@@ -1,4 +1,14 @@
|
||||
[
|
||||
{
|
||||
"version": "0.4.0",
|
||||
"changes": [
|
||||
{
|
||||
"note": "Update web3 provider engine to 14.0.4",
|
||||
"pr": 555
|
||||
}
|
||||
],
|
||||
"timestamp": 1525428773
|
||||
},
|
||||
{
|
||||
"version": "0.3.6",
|
||||
"changes": [
|
||||
|
@@ -5,11 +5,15 @@ Edit the package's CHANGELOG.json file only.
|
||||
|
||||
CHANGELOG
|
||||
|
||||
## v0.4.0 - _May 4, 2018_
|
||||
|
||||
* Update web3 provider engine to 14.0.4 (#555)
|
||||
|
||||
## v0.3.6 - _April 18, 2018_
|
||||
|
||||
* Allow an rpcURL to be set in Web3Config (for testnet RPC endpoints) (#524)
|
||||
|
||||
## v0.3.5 - _April 12, 2018_
|
||||
## v0.3.5 - _April 11, 2018_
|
||||
|
||||
* Dependencies updated
|
||||
|
||||
@@ -21,25 +25,25 @@ CHANGELOG
|
||||
|
||||
* Dependencies updated
|
||||
|
||||
## v0.3.1 - _March 18, 2018_
|
||||
## v0.3.1 - _March 17, 2018_
|
||||
|
||||
* Reduce npm package size by adding an `.npmignore` file.
|
||||
* Move `@0xproject/web3-wrapper` to dependencies from devDependencies.
|
||||
|
||||
## v0.3.0 - _March 18, 2018_
|
||||
## v0.3.0 - _March 17, 2018_
|
||||
|
||||
* Add coverage subprovider if SOLIDITY_COVERAGE env variable is true (#426)
|
||||
* Refactor `BlockchainLifecycle` to work with in-process ganache (#426)
|
||||
* Remove `RPC` class and move it's logic to `Web3Wrapper` (#426)
|
||||
|
||||
## v0.2.0 - _February 16, 2018_
|
||||
## v0.2.0 - _February 15, 2018_
|
||||
|
||||
* Remove subproviders (#392)
|
||||
|
||||
## v0.0.12 - _February 9, 2018_
|
||||
## v0.0.12 - _February 8, 2018_
|
||||
|
||||
* Fix publishing issue where .npmignore was not properly excluding undesired content (#389)
|
||||
|
||||
## v0.0.11 - _February 7, 2018_
|
||||
## v0.0.11 - _February 6, 2018_
|
||||
|
||||
* Updated `types-ethereumjs-util` dev dependency (#352)
|
||||
|
@@ -47,7 +47,7 @@
|
||||
"@0xproject/web3-wrapper": "^0.6.1",
|
||||
"lodash": "^4.17.4",
|
||||
"web3": "^0.20.0",
|
||||
"web3-provider-engine": "^13.0.1"
|
||||
"web3-provider-engine": "^14.0.4"
|
||||
},
|
||||
"publishConfig": {
|
||||
"access": "public"
|
||||
|
@@ -1,4 +1,13 @@
|
||||
[
|
||||
{
|
||||
"timestamp": 1525428773,
|
||||
"version": "0.7.22",
|
||||
"changes": [
|
||||
{
|
||||
"note": "Dependencies updated"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"timestamp": 1524044013,
|
||||
"version": "0.7.21",
|
||||
|
@@ -5,11 +5,15 @@ Edit the package's CHANGELOG.json file only.
|
||||
|
||||
CHANGELOG
|
||||
|
||||
## v0.7.22 - _May 4, 2018_
|
||||
|
||||
* Dependencies updated
|
||||
|
||||
## v0.7.21 - _April 18, 2018_
|
||||
|
||||
* Dependencies updated
|
||||
|
||||
## v0.7.20 - _April 12, 2018_
|
||||
## v0.7.20 - _April 11, 2018_
|
||||
|
||||
* Dependencies updated
|
||||
|
||||
@@ -21,14 +25,14 @@ CHANGELOG
|
||||
|
||||
* Dependencies updated
|
||||
|
||||
## v0.7.13 - _February 9, 2018_
|
||||
## v0.7.13 - _February 8, 2018_
|
||||
|
||||
* Fix publishing issue where .npmignore was not properly excluding undesired content (#389)
|
||||
|
||||
## v0.7.0 - _December 20, 2017_
|
||||
## v0.7.0 - _December 19, 2017_
|
||||
|
||||
* Rename `subscriptionOptsSchema` to `blockRangeSchema` (#272)
|
||||
|
||||
## v0.6.7 - _November 14, 2017_
|
||||
## v0.6.7 - _November 13, 2017_
|
||||
|
||||
* Re-publish JSON-schema previously published under NPM package 0x-json-schemas
|
||||
|
@@ -32,9 +32,9 @@
|
||||
"@0xproject/types": "^0.6.1",
|
||||
"@0xproject/utils": "^0.5.2",
|
||||
"@0xproject/web3-wrapper": "^0.6.1",
|
||||
"ethers-contracts": "^2.2.1",
|
||||
"ethers": "^3.0.15",
|
||||
"lodash": "^4.17.4",
|
||||
"web3-provider-engine": "^13.0.1"
|
||||
"web3-provider-engine": "^14.0.4"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@0xproject/dev-utils": "^0.3.6",
|
||||
|
20
packages/migrations/CHANGELOG.json
Normal file
20
packages/migrations/CHANGELOG.json
Normal file
@@ -0,0 +1,20 @@
|
||||
[
|
||||
{
|
||||
"timestamp": 1525428773,
|
||||
"version": "0.0.4",
|
||||
"changes": [
|
||||
{
|
||||
"note": "Dependencies updated"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"timestamp": 1524073495,
|
||||
"version": "0.0.3",
|
||||
"changes": [
|
||||
{
|
||||
"note": "Dependencies updated"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
14
packages/migrations/CHANGELOG.md
Normal file
14
packages/migrations/CHANGELOG.md
Normal file
@@ -0,0 +1,14 @@
|
||||
<!--
|
||||
This file is auto-generated using the monorepo-scripts package. Don't edit directly.
|
||||
Edit the package's CHANGELOG.json file only.
|
||||
-->
|
||||
|
||||
CHANGELOG
|
||||
|
||||
## v0.0.4 - _May 4, 2018_
|
||||
|
||||
* Dependencies updated
|
||||
|
||||
## v0.0.3 - _April 18, 2018_
|
||||
|
||||
* Dependencies updated
|
@@ -1,7 +1,6 @@
|
||||
{
|
||||
"private": true,
|
||||
"name": "@0xproject/migrations",
|
||||
"version": "0.0.2",
|
||||
"version": "0.0.3",
|
||||
"description": "0x smart contract migrations",
|
||||
"main": "lib/index.js",
|
||||
"types": "lib/index.d.ts",
|
||||
@@ -32,5 +31,8 @@
|
||||
"@0xproject/utils": "^0.5.2",
|
||||
"@0xproject/web3-wrapper": "^0.6.1",
|
||||
"lodash": "^4.17.4"
|
||||
},
|
||||
"publishConfig": {
|
||||
"access": "public"
|
||||
}
|
||||
}
|
||||
|
@@ -69,7 +69,7 @@ export const runMigrationsAsync = async (deployer: Deployer) => {
|
||||
},
|
||||
);
|
||||
for (const token of tokenInfo) {
|
||||
const totalSupply = new BigNumber(0);
|
||||
const totalSupply = new BigNumber(100000000000000000000);
|
||||
const args = [token.name, token.symbol, token.decimals, totalSupply];
|
||||
const dummyToken = await deployer.deployAsync(ContractName.DummyToken, args);
|
||||
await tokenReg.addToken.sendTransactionAsync(
|
||||
|
@@ -1,4 +1,13 @@
|
||||
[
|
||||
{
|
||||
"timestamp": 1525428773,
|
||||
"version": "0.1.19",
|
||||
"changes": [
|
||||
{
|
||||
"note": "Dependencies updated"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"timestamp": 1524044013,
|
||||
"version": "0.1.18",
|
||||
|
@@ -5,11 +5,15 @@ Edit the package's CHANGELOG.json file only.
|
||||
|
||||
CHANGELOG
|
||||
|
||||
## v0.1.19 - _May 4, 2018_
|
||||
|
||||
* Dependencies updated
|
||||
|
||||
## v0.1.18 - _April 18, 2018_
|
||||
|
||||
* Dependencies updated
|
||||
|
||||
## v0.1.17 - _April 12, 2018_
|
||||
## v0.1.17 - _April 11, 2018_
|
||||
|
||||
* Dependencies updated
|
||||
|
||||
@@ -17,6 +21,6 @@ CHANGELOG
|
||||
|
||||
* Dependencies updated
|
||||
|
||||
## v0.1.13 - _March 18, 2018_
|
||||
## v0.1.13 - _March 17, 2018_
|
||||
|
||||
* Add postpublish utils
|
||||
|
@@ -2,6 +2,16 @@
|
||||
|
||||
This repository contains a few helpful scripts for working with this mono repo.
|
||||
|
||||
#### Scripts
|
||||
|
||||
**`yarn deps_versions`**: Since we use Lerna + Yarn workspaces, shared dependencies between packages in the monorepo get hoisted to a top-level `node_modules` directory. If two packages use different versions of the same dependency however, both get installed. To avoid having many versions of a dependency installed, we try to keep dependency versions the same across packages in the monorepo. This script will list any dependencies for which we have multiple versions installed. We can then go through them and try to consolidate to a single version where possible.
|
||||
|
||||
**`yarn find_unused_deps`**: Sometimes we accidentally leave dependencies listed in `package.json` that are no longer being used. This script finds potential dependencies that might no longer be in use. Please verify that it is no longer in use before removing, the `depcheck` package we use under-the-hood doesn't handle some TS quirks perfectly.
|
||||
|
||||
**`yarn remove_tags`**: Our publishing script calls `lerna publish` under-the-hood. If this command fails, it might have created new versioned git tags for each package. Removing these manually is tedious, so you can also run this command instead. Before doing so, check to see if `lerna` already created the publish commit. If so, first revert that with `git reset --hard HEAD~1`, then run this command.
|
||||
|
||||
**`yarn test:publish`**: Execute a test-run of the publish script. This dry run won't actually publish, nor will it commit/push anything to Github.
|
||||
|
||||
## Usage
|
||||
|
||||
#### Dependency versions
|
||||
|
@@ -11,9 +11,11 @@
|
||||
"build": "tsc",
|
||||
"test:publish": "run-s build script:publish",
|
||||
"find_unused_deps": "run-s build script:find_unused_deps",
|
||||
"remove_tags": "run-s build script:remove_tags",
|
||||
"script:deps_versions": "node ./lib/deps_versions.js",
|
||||
"script:publish": "IS_DRY_RUN=true node ./lib/publish.js",
|
||||
"script:find_unused_deps": "node ./lib/find_unused_dependencies.js"
|
||||
"script:find_unused_deps": "node ./lib/find_unused_dependencies.js",
|
||||
"script:remove_tags": "node ./lib/remove_tags.js"
|
||||
},
|
||||
"repository": {
|
||||
"type": "git",
|
||||
|
@@ -3,4 +3,6 @@ import * as path from 'path';
|
||||
export const constants = {
|
||||
monorepoRootPath: path.join(__dirname, '../../..'),
|
||||
stagingWebsite: 'http://staging-0xproject.s3-website-us-east-1.amazonaws.com',
|
||||
lernaExecutable: path.join('node_modules', 'lerna', 'bin', 'lerna.js'),
|
||||
githubPersonalAccessToken: process.env.GITHUB_PERSONAL_ACCESS_TOKEN_0X_JS,
|
||||
};
|
||||
|
@@ -10,7 +10,6 @@ import { constants } from './constants';
|
||||
import { utils } from './utils';
|
||||
|
||||
const publishReleaseAsync = promisify(publishRelease);
|
||||
const githubPersonalAccessToken = process.env.GITHUB_PERSONAL_ACCESS_TOKEN_0X_JS;
|
||||
const generatedDocsDirectoryName = 'generated_docs';
|
||||
|
||||
export interface PostpublishConfigs {
|
||||
@@ -97,7 +96,7 @@ export const postpublishUtils = {
|
||||
const finalAssets = this.adjustAssetPaths(cwd, assets);
|
||||
utils.log('POSTPUBLISH: Releasing ', releaseName, '...');
|
||||
const result = await publishReleaseAsync({
|
||||
token: githubPersonalAccessToken,
|
||||
token: constants.githubPersonalAccessToken,
|
||||
owner: '0xProject',
|
||||
repo: '0x-monorepo',
|
||||
tag,
|
||||
|
@@ -35,11 +35,18 @@ const packageNameToWebsitePath: { [name: string]: string } = {
|
||||
deployer: 'deployer',
|
||||
'sol-cov': 'sol-cov',
|
||||
subproviders: 'subproviders',
|
||||
'order-utils': 'order-utils',
|
||||
};
|
||||
|
||||
(async () => {
|
||||
const hasRequiredSetup = await checkPublishRequiredSetupAsync();
|
||||
if (!hasRequiredSetup) {
|
||||
return; // abort
|
||||
}
|
||||
|
||||
// Fetch public, updated Lerna packages
|
||||
const updatedPublicLernaPackages = await getUpdatedPublicLernaPackagesAsync();
|
||||
const shouldIncludePrivate = false;
|
||||
const updatedPublicLernaPackages = await utils.getUpdatedLernaPackagesAsync(shouldIncludePrivate);
|
||||
|
||||
await confirmDocPagesRenderAsync(updatedPublicLernaPackages);
|
||||
|
||||
@@ -107,6 +114,54 @@ package.ts. Please add an entry for it and try again.`,
|
||||
}
|
||||
}
|
||||
|
||||
async function checkPublishRequiredSetupAsync(): Promise<boolean> {
|
||||
// check to see if logged into npm before publishing
|
||||
try {
|
||||
// HACK: for some reason on some setups, the `npm whoami` will not recognize a logged-in user
|
||||
// unless run with `sudo` (i.e Fabio's NVM setup) but is fine for others (Jacob's N setup).
|
||||
await execAsync(`sudo npm whoami`);
|
||||
} catch (err) {
|
||||
utils.log('You must be logged into npm in the commandline to publish. Run `npm login` and try again.');
|
||||
return false;
|
||||
}
|
||||
|
||||
// Check to see if Git personal token setup
|
||||
if (_.isUndefined(constants.githubPersonalAccessToken)) {
|
||||
utils.log(
|
||||
'You must have a Github personal access token set to an envVar named `GITHUB_PERSONAL_ACCESS_TOKEN_0X_JS`. Add it then try again.',
|
||||
);
|
||||
return false;
|
||||
}
|
||||
|
||||
// Check Yarn version is 1.X
|
||||
const result = await execAsync(`yarn --version`);
|
||||
const version = result.stdout;
|
||||
const versionSegments = version.split('.');
|
||||
const majorVersion = _.parseInt(versionSegments[0]);
|
||||
if (majorVersion < 1) {
|
||||
utils.log('Your yarn version must be v1.x or higher. Upgrade yarn and try again.');
|
||||
return false;
|
||||
}
|
||||
|
||||
// Check that `aws` commandline tool is installed
|
||||
try {
|
||||
await execAsync(`aws help`);
|
||||
} catch (err) {
|
||||
utils.log('You must have `awscli` commandline tool installed. Install it and try again.');
|
||||
return false;
|
||||
}
|
||||
|
||||
// Check that `aws` credentials are setup
|
||||
try {
|
||||
await execAsync(`aws sts get-caller-identity`);
|
||||
} catch (err) {
|
||||
utils.log('You must setup your AWS credentials by running `aws configure`. Do this and try again.');
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
async function pushChangelogsToGithubAsync() {
|
||||
await execAsync(`git add . --all`, { cwd: constants.monorepoRootPath });
|
||||
await execAsync(`git commit -m "Updated CHANGELOGS"`, { cwd: constants.monorepoRootPath });
|
||||
@@ -114,23 +169,12 @@ async function pushChangelogsToGithubAsync() {
|
||||
utils.log(`Pushed CHANGELOG updates to Github`);
|
||||
}
|
||||
|
||||
async function getUpdatedPublicLernaPackagesAsync(): Promise<LernaPackage[]> {
|
||||
const updatedPublicPackages = await getPublicLernaUpdatedPackagesAsync();
|
||||
const updatedPackageNames = _.map(updatedPublicPackages, pkg => pkg.name);
|
||||
|
||||
const allLernaPackages = lernaGetPackages(constants.monorepoRootPath);
|
||||
const updatedPublicLernaPackages = _.filter(allLernaPackages, pkg => {
|
||||
return _.includes(updatedPackageNames, pkg.package.name);
|
||||
});
|
||||
return updatedPublicLernaPackages;
|
||||
}
|
||||
|
||||
async function updateChangeLogsAsync(updatedPublicLernaPackages: LernaPackage[]): Promise<PackageToVersionChange> {
|
||||
const packageToVersionChange: PackageToVersionChange = {};
|
||||
for (const lernaPackage of updatedPublicLernaPackages) {
|
||||
const packageName = lernaPackage.package.name;
|
||||
const changelogJSONPath = path.join(lernaPackage.location, 'CHANGELOG.json');
|
||||
const changelogJSON = getChangelogJSONOrCreateIfMissing(lernaPackage.package.name, changelogJSONPath);
|
||||
const changelogJSON = utils.getChangelogJSONOrCreateIfMissing(changelogJSONPath);
|
||||
let changelogs: Changelog[];
|
||||
try {
|
||||
changelogs = JSON.parse(changelogJSON);
|
||||
@@ -225,13 +269,6 @@ async function lernaPublishAsync(packageToVersionChange: { [name: string]: strin
|
||||
});
|
||||
}
|
||||
|
||||
async function getPublicLernaUpdatedPackagesAsync(): Promise<UpdatedPackage[]> {
|
||||
const result = await execAsync(`${LERNA_EXECUTABLE} updated --json`, { cwd: constants.monorepoRootPath });
|
||||
const updatedPackages = JSON.parse(result.stdout);
|
||||
const updatedPublicPackages = _.filter(updatedPackages, updatedPackage => !updatedPackage.private);
|
||||
return updatedPublicPackages;
|
||||
}
|
||||
|
||||
function updateVersionNumberIfNeeded(currentVersion: string, proposedNextVersion: string) {
|
||||
if (proposedNextVersion === currentVersion) {
|
||||
return utils.getNextPatchVersion(currentVersion);
|
||||
@@ -243,19 +280,6 @@ function updateVersionNumberIfNeeded(currentVersion: string, proposedNextVersion
|
||||
return proposedNextVersion;
|
||||
}
|
||||
|
||||
function getChangelogJSONOrCreateIfMissing(packageName: string, changelogPath: string): string {
|
||||
let changelogJSON: string;
|
||||
try {
|
||||
changelogJSON = fs.readFileSync(changelogPath, 'utf-8');
|
||||
return changelogJSON;
|
||||
} catch (err) {
|
||||
// If none exists, create new, empty one.
|
||||
const emptyChangelogJSON = JSON.stringify([], null, 4);
|
||||
fs.writeFileSync(changelogPath, emptyChangelogJSON);
|
||||
return emptyChangelogJSON;
|
||||
}
|
||||
}
|
||||
|
||||
function shouldAddNewChangelogEntry(currentVersion: string, changelogs: Changelog[]): boolean {
|
||||
if (_.isEmpty(changelogs)) {
|
||||
return true;
|
||||
|
58
packages/monorepo-scripts/src/remove_tags.ts
Normal file
58
packages/monorepo-scripts/src/remove_tags.ts
Normal file
@@ -0,0 +1,58 @@
|
||||
#!/usr/bin/env node
|
||||
|
||||
import lernaGetPackages = require('lerna-get-packages');
|
||||
import * as _ from 'lodash';
|
||||
import * as path from 'path';
|
||||
import { exec as execAsync } from 'promisify-child-process';
|
||||
import semverSort = require('semver-sort');
|
||||
|
||||
import { constants } from './constants';
|
||||
import { Changelog } from './types';
|
||||
import { utils } from './utils';
|
||||
|
||||
(async () => {
|
||||
const shouldIncludePrivate = true;
|
||||
const updatedPublicLernaPackages = await utils.getUpdatedLernaPackagesAsync(shouldIncludePrivate);
|
||||
|
||||
for (const lernaPackage of updatedPublicLernaPackages) {
|
||||
const packageName = lernaPackage.package.name;
|
||||
const currentVersion = lernaPackage.package.version;
|
||||
const changelogJSONPath = path.join(lernaPackage.location, 'CHANGELOG.json');
|
||||
// Private packages don't have changelogs, and their versions are always incremented
|
||||
// by a patch version.
|
||||
const changelogJSONIfExists = utils.getChangelogJSONIfExists(changelogJSONPath);
|
||||
|
||||
let latestChangelogVersion: string;
|
||||
if (!_.isUndefined(changelogJSONIfExists)) {
|
||||
let changelogs: Changelog[];
|
||||
try {
|
||||
changelogs = JSON.parse(changelogJSONIfExists);
|
||||
} catch (err) {
|
||||
throw new Error(
|
||||
`${lernaPackage.package.name}'s CHANGELOG.json contains invalid JSON. Please fix and try again.`,
|
||||
);
|
||||
}
|
||||
latestChangelogVersion = changelogs[0].version;
|
||||
} else {
|
||||
latestChangelogVersion = utils.getNextPatchVersion(currentVersion);
|
||||
}
|
||||
|
||||
const sortedVersions = semverSort.desc([latestChangelogVersion, currentVersion]);
|
||||
if (sortedVersions[0] === latestChangelogVersion && latestChangelogVersion !== currentVersion) {
|
||||
const tagName = `${packageName}@${latestChangelogVersion}`;
|
||||
try {
|
||||
await execAsync(`git tag -d ${tagName}`, { cwd: constants.monorepoRootPath });
|
||||
utils.log(`removed tag: ${tagName}`);
|
||||
} catch (err) {
|
||||
if (_.includes(err.message, 'not found')) {
|
||||
utils.log(`Could not find tag: ${tagName}`);
|
||||
} else {
|
||||
throw err;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
})().catch(err => {
|
||||
utils.log(err);
|
||||
process.exit(1);
|
||||
});
|
@@ -1,6 +1,11 @@
|
||||
import * as fs from 'fs';
|
||||
import lernaGetPackages = require('lerna-get-packages');
|
||||
import * as _ from 'lodash';
|
||||
import { exec as execAsync, spawn } from 'promisify-child-process';
|
||||
|
||||
import { constants } from './constants';
|
||||
import { UpdatedPackage } from './types';
|
||||
|
||||
export const utils = {
|
||||
log(...args: any[]): void {
|
||||
console.log(...args); // tslint:disable-line:no-console
|
||||
@@ -17,4 +22,43 @@ export const utils = {
|
||||
cwd,
|
||||
});
|
||||
},
|
||||
async getUpdatedLernaPackagesAsync(shouldIncludePrivate: boolean): Promise<LernaPackage[]> {
|
||||
const updatedPublicPackages = await this.getLernaUpdatedPackagesAsync(shouldIncludePrivate);
|
||||
const updatedPackageNames = _.map(updatedPublicPackages, pkg => pkg.name);
|
||||
|
||||
const allLernaPackages = lernaGetPackages(constants.monorepoRootPath);
|
||||
const updatedPublicLernaPackages = _.filter(allLernaPackages, pkg => {
|
||||
return _.includes(updatedPackageNames, pkg.package.name);
|
||||
});
|
||||
return updatedPublicLernaPackages;
|
||||
},
|
||||
async getLernaUpdatedPackagesAsync(shouldIncludePrivate: boolean): Promise<UpdatedPackage[]> {
|
||||
const result = await execAsync(`${constants.lernaExecutable} updated --json`, {
|
||||
cwd: constants.monorepoRootPath,
|
||||
});
|
||||
const updatedPackages = JSON.parse(result.stdout);
|
||||
if (!shouldIncludePrivate) {
|
||||
const updatedPublicPackages = _.filter(updatedPackages, updatedPackage => !updatedPackage.private);
|
||||
return updatedPublicPackages;
|
||||
}
|
||||
return updatedPackages;
|
||||
},
|
||||
getChangelogJSONIfExists(changelogPath: string) {
|
||||
try {
|
||||
const changelogJSON = fs.readFileSync(changelogPath, 'utf-8');
|
||||
return changelogJSON;
|
||||
} catch (err) {
|
||||
return undefined;
|
||||
}
|
||||
},
|
||||
getChangelogJSONOrCreateIfMissing(changelogPath: string): string {
|
||||
const changelogIfExists = this.getChangelogJSONIfExists(changelogPath);
|
||||
if (_.isUndefined(changelogIfExists)) {
|
||||
// If none exists, create new, empty one.
|
||||
const emptyChangelogJSON = JSON.stringify([]);
|
||||
fs.writeFileSync(changelogPath, emptyChangelogJSON);
|
||||
return emptyChangelogJSON;
|
||||
}
|
||||
return changelogIfExists;
|
||||
},
|
||||
};
|
||||
|
7
packages/order-utils/.npmignore
Normal file
7
packages/order-utils/.npmignore
Normal file
@@ -0,0 +1,7 @@
|
||||
.*
|
||||
yarn-error.log
|
||||
/scripts/
|
||||
/generated_docs/
|
||||
/src/
|
||||
tsconfig.json
|
||||
/lib/monorepo_scripts/
|
11
packages/order-utils/CHANGELOG.json
Normal file
11
packages/order-utils/CHANGELOG.json
Normal file
@@ -0,0 +1,11 @@
|
||||
[
|
||||
{
|
||||
"timestamp": 1525428773,
|
||||
"version": "0.0.2",
|
||||
"changes": [
|
||||
{
|
||||
"note": "Dependencies updated"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
10
packages/order-utils/CHANGELOG.md
Normal file
10
packages/order-utils/CHANGELOG.md
Normal file
@@ -0,0 +1,10 @@
|
||||
<!--
|
||||
This file is auto-generated using the monorepo-scripts package. Don't edit directly.
|
||||
Edit the package's CHANGELOG.json file only.
|
||||
-->
|
||||
|
||||
CHANGELOG
|
||||
|
||||
## v0.0.2 - _May 4, 2018_
|
||||
|
||||
* Dependencies updated
|
77
packages/order-utils/README.md
Normal file
77
packages/order-utils/README.md
Normal file
@@ -0,0 +1,77 @@
|
||||
## @0xproject/order-utils
|
||||
|
||||
0x order-related utilities for those developing on top of 0x protocol.
|
||||
|
||||
### Read the [Documentation](https://0xproject.com/docs/order-utils).
|
||||
|
||||
## Installation
|
||||
|
||||
```bash
|
||||
yarn add @0xproject/order-utils
|
||||
```
|
||||
|
||||
If your project is in [TypeScript](https://www.typescriptlang.org/), add the following to your `tsconfig.json`:
|
||||
|
||||
```json
|
||||
"compilerOptions": {
|
||||
"typeRoots": ["node_modules/@0xproject/typescript-typings/types", "node_modules/@types"],
|
||||
}
|
||||
```
|
||||
|
||||
## Contributing
|
||||
|
||||
We welcome improvements and fixes from the wider community! To report bugs within this package, please create an issue in this repository.
|
||||
|
||||
Please read our [contribution guidelines](../../CONTRIBUTING.md) before getting started.
|
||||
|
||||
### Install dependencies
|
||||
|
||||
If you don't have yarn workspaces enabled (Yarn < v1.0) - enable them:
|
||||
|
||||
```bash
|
||||
yarn config set workspaces-experimental true
|
||||
```
|
||||
|
||||
Then install dependencies
|
||||
|
||||
```bash
|
||||
yarn install
|
||||
```
|
||||
|
||||
### Build
|
||||
|
||||
If this is your **first** time building this package, you must first build **all** packages within the monorepo. This is because packages that depend on other packages located inside this monorepo are symlinked when run from **within** the monorepo. This allows you to make changes across multiple packages without first publishing dependent packages to NPM. To build all packages, run the following from the monorepo root directory:
|
||||
|
||||
```bash
|
||||
yarn lerna:rebuild
|
||||
```
|
||||
|
||||
Or continuously rebuild on change:
|
||||
|
||||
```bash
|
||||
yarn dev
|
||||
```
|
||||
|
||||
You can also build this specific package by running the following from within its directory:
|
||||
|
||||
```bash
|
||||
yarn build
|
||||
```
|
||||
|
||||
or continuously rebuild on change:
|
||||
|
||||
```bash
|
||||
yarn build:watch
|
||||
```
|
||||
|
||||
### Clean
|
||||
|
||||
```bash
|
||||
yarn clean
|
||||
```
|
||||
|
||||
### Lint
|
||||
|
||||
```bash
|
||||
yarn lint
|
||||
```
|
0
packages/order-utils/coverage/.gitkeep
Normal file
0
packages/order-utils/coverage/.gitkeep
Normal file
76
packages/order-utils/package.json
Normal file
76
packages/order-utils/package.json
Normal file
@@ -0,0 +1,76 @@
|
||||
{
|
||||
"name": "@0xproject/order-utils",
|
||||
"version": "0.0.1",
|
||||
"description": "0x order utils",
|
||||
"main": "lib/src/index.js",
|
||||
"types": "lib/src/index.d.ts",
|
||||
"scripts": {
|
||||
"build:watch": "tsc -w",
|
||||
"build": "tsc && copyfiles -u 3 './lib/src/monorepo_scripts/**/*' ./scripts",
|
||||
"test": "run-s clean build run_mocha",
|
||||
"test:circleci": "yarn test:coverage",
|
||||
"run_mocha": "mocha lib/test/**/*_test.js --bail --exit",
|
||||
"test:coverage": "nyc npm run test --all && yarn coverage:report:lcov",
|
||||
"coverage:report:lcov": "nyc report --reporter=text-lcov > coverage/lcov.info",
|
||||
"clean": "shx rm -rf lib scripts",
|
||||
"lint": "tslint --project .",
|
||||
"manual:postpublish": "yarn build; node ./scripts/postpublish.js",
|
||||
"docs:stage": "yarn build && node ./scripts/stage_docs.js",
|
||||
"docs:json": "typedoc --excludePrivate --excludeExternals --target ES5 --json $JSON_FILE_PATH $PROJECT_FILES",
|
||||
"upload_docs_json": "aws s3 cp generated_docs/index.json $S3_URL --profile 0xproject --grants read=uri=http://acs.amazonaws.com/groups/global/AllUsers --content-type application/json"
|
||||
},
|
||||
"config": {
|
||||
"postpublish": {
|
||||
"docPublishConfigs": {
|
||||
"extraFileIncludes": [
|
||||
"../types/src/index.ts"
|
||||
],
|
||||
"s3BucketPath": "s3://doc-jsons/order-utils/",
|
||||
"s3StagingBucketPath": "s3://staging-doc-jsons/order-utils/"
|
||||
}
|
||||
}
|
||||
},
|
||||
"license": "Apache-2.0",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/0xProject/0x-monorepo.git"
|
||||
},
|
||||
"bugs": {
|
||||
"url": "https://github.com/0xProject/0x-monorepo/issues"
|
||||
},
|
||||
"homepage": "https://github.com/0xProject/0x-monorepo/packages/order-utils/README.md",
|
||||
"devDependencies": {
|
||||
"@0xproject/monorepo-scripts": "^0.1.18",
|
||||
"@0xproject/dev-utils": "^0.3.6",
|
||||
"@0xproject/tslint-config": "^0.4.16",
|
||||
"@types/lodash": "4.14.104",
|
||||
"chai": "^4.0.1",
|
||||
"chai-as-promised": "^7.1.0",
|
||||
"chai-bignumber": "^2.0.1",
|
||||
"dirty-chai": "^2.0.1",
|
||||
"sinon": "^4.0.0",
|
||||
"mocha": "^4.0.1",
|
||||
"copyfiles": "^1.2.0",
|
||||
"npm-run-all": "^4.1.2",
|
||||
"typedoc": "0xProject/typedoc",
|
||||
"shx": "^0.2.2",
|
||||
"tslint": "5.8.0",
|
||||
"typescript": "2.7.1"
|
||||
},
|
||||
"dependencies": {
|
||||
"@0xproject/assert": "^0.2.7",
|
||||
"@0xproject/types": "^0.6.1",
|
||||
"@0xproject/json-schemas": "^0.7.21",
|
||||
"@0xproject/typescript-typings": "^0.2.0",
|
||||
"@0xproject/web3-wrapper": "^0.6.1",
|
||||
"@0xproject/utils": "^0.5.2",
|
||||
"@types/node": "^8.0.53",
|
||||
"bn.js": "^4.11.8",
|
||||
"lodash": "^4.17.4",
|
||||
"ethereumjs-abi": "^0.6.4",
|
||||
"ethereumjs-util": "^5.1.1"
|
||||
},
|
||||
"publishConfig": {
|
||||
"access": "public"
|
||||
}
|
||||
}
|
27
packages/order-utils/src/assert.ts
Normal file
27
packages/order-utils/src/assert.ts
Normal file
@@ -0,0 +1,27 @@
|
||||
import { assert as sharedAssert } from '@0xproject/assert';
|
||||
// We need those two unused imports because they're actually used by sharedAssert which gets injected here
|
||||
// tslint:disable-next-line:no-unused-variable
|
||||
import { Schema } from '@0xproject/json-schemas';
|
||||
// tslint:disable-next-line:no-unused-variable
|
||||
import { ECSignature } from '@0xproject/types';
|
||||
import { BigNumber } from '@0xproject/utils';
|
||||
import { Web3Wrapper } from '@0xproject/web3-wrapper';
|
||||
import * as _ from 'lodash';
|
||||
|
||||
import { isValidSignature } from './signature_utils';
|
||||
|
||||
export const assert = {
|
||||
...sharedAssert,
|
||||
async isSenderAddressAsync(
|
||||
variableName: string,
|
||||
senderAddressHex: string,
|
||||
web3Wrapper: Web3Wrapper,
|
||||
): Promise<void> {
|
||||
sharedAssert.isETHAddressHex(variableName, senderAddressHex);
|
||||
const isSenderAddressAvailable = await web3Wrapper.isSenderAddressAvailableAsync(senderAddressHex);
|
||||
sharedAssert.assert(
|
||||
isSenderAddressAvailable,
|
||||
`Specified ${variableName} ${senderAddressHex} isn't available through the supplied web3 provider`,
|
||||
);
|
||||
},
|
||||
};
|
3
packages/order-utils/src/constants.ts
Normal file
3
packages/order-utils/src/constants.ts
Normal file
@@ -0,0 +1,3 @@
|
||||
export const constants = {
|
||||
NULL_ADDRESS: '0x0000000000000000000000000000000000000000',
|
||||
};
|
6
packages/order-utils/src/globals.d.ts
vendored
Normal file
6
packages/order-utils/src/globals.d.ts
vendored
Normal file
@@ -0,0 +1,6 @@
|
||||
declare module '*.json' {
|
||||
const json: any;
|
||||
/* tslint:disable */
|
||||
export default json;
|
||||
/* tslint:enable */
|
||||
}
|
6
packages/order-utils/src/index.ts
Normal file
6
packages/order-utils/src/index.ts
Normal file
@@ -0,0 +1,6 @@
|
||||
export { getOrderHashHex, isValidOrderHash } from './order_hash';
|
||||
export { isValidSignature, signOrderHashAsync } from './signature_utils';
|
||||
export { orderFactory } from './order_factory';
|
||||
export { generatePseudoRandomSalt } from './salt';
|
||||
export { constants } from './constants';
|
||||
export { OrderError } from './types';
|
8
packages/order-utils/src/monorepo_scripts/postpublish.ts
Normal file
8
packages/order-utils/src/monorepo_scripts/postpublish.ts
Normal file
@@ -0,0 +1,8 @@
|
||||
import { postpublishUtils } from '@0xproject/monorepo-scripts';
|
||||
|
||||
import * as packageJSON from '../package.json';
|
||||
import * as tsConfigJSON from '../tsconfig.json';
|
||||
|
||||
const cwd = `${__dirname}/..`;
|
||||
// tslint:disable-next-line:no-floating-promises
|
||||
postpublishUtils.runAsync(packageJSON, tsConfigJSON, cwd);
|
8
packages/order-utils/src/monorepo_scripts/stage_docs.ts
Normal file
8
packages/order-utils/src/monorepo_scripts/stage_docs.ts
Normal file
@@ -0,0 +1,8 @@
|
||||
import { postpublishUtils } from '@0xproject/monorepo-scripts';
|
||||
|
||||
import * as packageJSON from '../package.json';
|
||||
import * as tsConfigJSON from '../tsconfig.json';
|
||||
|
||||
const cwd = `${__dirname}/..`;
|
||||
// tslint:disable-next-line:no-floating-promises
|
||||
postpublishUtils.publishDocsToStagingAsync(packageJSON, tsConfigJSON, cwd);
|
@@ -1,13 +1,16 @@
|
||||
import { Provider, SignedOrder } from '@0xproject/types';
|
||||
import { BigNumber } from '@0xproject/utils';
|
||||
import * as _ from 'lodash';
|
||||
|
||||
import { SignedOrder, ZeroEx } from '../../src';
|
||||
import { getOrderHashHex } from './order_hash';
|
||||
import { generatePseudoRandomSalt } from './salt';
|
||||
import { signOrderHashAsync } from './signature_utils';
|
||||
|
||||
const SHOULD_ADD_PERSONAL_MESSAGE_PREFIX = false;
|
||||
|
||||
export const orderFactory = {
|
||||
async createSignedOrderAsync(
|
||||
zeroEx: ZeroEx,
|
||||
provider: Provider,
|
||||
maker: string,
|
||||
taker: string,
|
||||
makerFee: BigNumber,
|
||||
@@ -33,13 +36,13 @@ export const orderFactory = {
|
||||
takerTokenAmount,
|
||||
makerTokenAddress,
|
||||
takerTokenAddress,
|
||||
salt: ZeroEx.generatePseudoRandomSalt(),
|
||||
salt: generatePseudoRandomSalt(),
|
||||
exchangeContractAddress,
|
||||
feeRecipient,
|
||||
expirationUnixTimestampSec,
|
||||
};
|
||||
const orderHash = ZeroEx.getOrderHashHex(order);
|
||||
const ecSignature = await zeroEx.signOrderHashAsync(orderHash, maker, SHOULD_ADD_PERSONAL_MESSAGE_PREFIX);
|
||||
const orderHash = getOrderHashHex(order);
|
||||
const ecSignature = await signOrderHashAsync(provider, orderHash, maker, SHOULD_ADD_PERSONAL_MESSAGE_PREFIX);
|
||||
const signedOrder: SignedOrder = _.assign(order, { ecSignature });
|
||||
return signedOrder;
|
||||
},
|
89
packages/order-utils/src/order_hash.ts
Normal file
89
packages/order-utils/src/order_hash.ts
Normal file
@@ -0,0 +1,89 @@
|
||||
import { schemas, SchemaValidator } from '@0xproject/json-schemas';
|
||||
import { Order, SignedOrder, SolidityTypes } from '@0xproject/types';
|
||||
import { BigNumber } from '@0xproject/utils';
|
||||
import BN = require('bn.js');
|
||||
import * as ethABI from 'ethereumjs-abi';
|
||||
import * as ethUtil from 'ethereumjs-util';
|
||||
import * as _ from 'lodash';
|
||||
|
||||
import { assert } from './assert';
|
||||
|
||||
const INVALID_TAKER_FORMAT = 'instance.taker is not of a type(s) string';
|
||||
|
||||
/**
|
||||
* Converts BigNumber instance to BN
|
||||
* The only reason we convert to BN is to remain compatible with `ethABI.soliditySHA3` that
|
||||
* expects values of Solidity type `uint` to be passed as type `BN`.
|
||||
* We do not use BN anywhere else in the codebase.
|
||||
*/
|
||||
function bigNumberToBN(value: BigNumber) {
|
||||
return new BN(value.toString(), 10);
|
||||
}
|
||||
|
||||
/**
|
||||
* Computes the orderHash for a supplied order.
|
||||
* @param order An object that conforms to the Order or SignedOrder interface definitions.
|
||||
* @return The resulting orderHash from hashing the supplied order.
|
||||
*/
|
||||
export function getOrderHashHex(order: Order | SignedOrder): string {
|
||||
try {
|
||||
assert.doesConformToSchema('order', order, schemas.orderSchema);
|
||||
} catch (error) {
|
||||
if (_.includes(error.message, INVALID_TAKER_FORMAT)) {
|
||||
const errMsg =
|
||||
'Order taker must be of type string. If you want anyone to be able to fill an order - pass ZeroEx.NULL_ADDRESS';
|
||||
throw new Error(errMsg);
|
||||
}
|
||||
throw error;
|
||||
}
|
||||
const orderParts = [
|
||||
{ value: order.exchangeContractAddress, type: SolidityTypes.Address },
|
||||
{ value: order.maker, type: SolidityTypes.Address },
|
||||
{ value: order.taker, type: SolidityTypes.Address },
|
||||
{ value: order.makerTokenAddress, type: SolidityTypes.Address },
|
||||
{ value: order.takerTokenAddress, type: SolidityTypes.Address },
|
||||
{ value: order.feeRecipient, type: SolidityTypes.Address },
|
||||
{
|
||||
value: bigNumberToBN(order.makerTokenAmount),
|
||||
type: SolidityTypes.Uint256,
|
||||
},
|
||||
{
|
||||
value: bigNumberToBN(order.takerTokenAmount),
|
||||
type: SolidityTypes.Uint256,
|
||||
},
|
||||
{
|
||||
value: bigNumberToBN(order.makerFee),
|
||||
type: SolidityTypes.Uint256,
|
||||
},
|
||||
{
|
||||
value: bigNumberToBN(order.takerFee),
|
||||
type: SolidityTypes.Uint256,
|
||||
},
|
||||
{
|
||||
value: bigNumberToBN(order.expirationUnixTimestampSec),
|
||||
type: SolidityTypes.Uint256,
|
||||
},
|
||||
{ value: bigNumberToBN(order.salt), type: SolidityTypes.Uint256 },
|
||||
];
|
||||
const types = _.map(orderParts, o => o.type);
|
||||
const values = _.map(orderParts, o => o.value);
|
||||
const hashBuff = ethABI.soliditySHA3(types, values);
|
||||
const hashHex = ethUtil.bufferToHex(hashBuff);
|
||||
return hashHex;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if the supplied hex encoded order hash is valid.
|
||||
* Note: Valid means it has the expected format, not that an order with the orderHash exists.
|
||||
* Use this method when processing orderHashes submitted as user input.
|
||||
* @param orderHash Hex encoded orderHash.
|
||||
* @return Whether the supplied orderHash has the expected format.
|
||||
*/
|
||||
export function isValidOrderHash(orderHash: string): boolean {
|
||||
// Since this method can be called to check if any arbitrary string conforms to an orderHash's
|
||||
// format, we only assert that we were indeed passed a string.
|
||||
assert.isString('orderHash', orderHash);
|
||||
const schemaValidator = new SchemaValidator();
|
||||
const isValid = schemaValidator.validate(orderHash, schemas.orderHashSchema).valid;
|
||||
return isValid;
|
||||
}
|
18
packages/order-utils/src/salt.ts
Normal file
18
packages/order-utils/src/salt.ts
Normal file
@@ -0,0 +1,18 @@
|
||||
import { BigNumber } from '@0xproject/utils';
|
||||
|
||||
const MAX_DIGITS_IN_UNSIGNED_256_INT = 78;
|
||||
|
||||
/**
|
||||
* Generates a pseudo-random 256-bit salt.
|
||||
* The salt can be included in a 0x order, ensuring that the order generates a unique orderHash
|
||||
* and will not collide with other outstanding orders that are identical in all other parameters.
|
||||
* @return A pseudo-random 256-bit number that can be used as a salt.
|
||||
*/
|
||||
export function generatePseudoRandomSalt(): BigNumber {
|
||||
// BigNumber.random returns a pseudo-random number between 0 & 1 with a passed in number of decimal places.
|
||||
// Source: https://mikemcl.github.io/bignumber.js/#random
|
||||
const randomNumber = BigNumber.random(MAX_DIGITS_IN_UNSIGNED_256_INT);
|
||||
const factor = new BigNumber(10).pow(MAX_DIGITS_IN_UNSIGNED_256_INT - 1);
|
||||
const salt = randomNumber.times(factor).round();
|
||||
return salt;
|
||||
}
|
119
packages/order-utils/src/signature_utils.ts
Normal file
119
packages/order-utils/src/signature_utils.ts
Normal file
@@ -0,0 +1,119 @@
|
||||
import { schemas } from '@0xproject/json-schemas';
|
||||
import { ECSignature, Provider } from '@0xproject/types';
|
||||
import { Web3Wrapper } from '@0xproject/web3-wrapper';
|
||||
import * as ethUtil from 'ethereumjs-util';
|
||||
import * as _ from 'lodash';
|
||||
|
||||
import { assert } from './assert';
|
||||
import { OrderError } from './types';
|
||||
|
||||
/**
|
||||
* Verifies that the elliptic curve signature `signature` was generated
|
||||
* by signing `data` with the private key corresponding to the `signerAddress` address.
|
||||
* @param data The hex encoded data signed by the supplied signature.
|
||||
* @param signature An object containing the elliptic curve signature parameters.
|
||||
* @param signerAddress The hex encoded address that signed the data, producing the supplied signature.
|
||||
* @return Whether the signature is valid for the supplied signerAddress and data.
|
||||
*/
|
||||
export function isValidSignature(data: string, signature: ECSignature, signerAddress: string): boolean {
|
||||
assert.isHexString('data', data);
|
||||
assert.doesConformToSchema('signature', signature, schemas.ecSignatureSchema);
|
||||
assert.isETHAddressHex('signerAddress', signerAddress);
|
||||
const normalizedSignerAddress = signerAddress.toLowerCase();
|
||||
|
||||
const dataBuff = ethUtil.toBuffer(data);
|
||||
const msgHashBuff = ethUtil.hashPersonalMessage(dataBuff);
|
||||
try {
|
||||
const pubKey = ethUtil.ecrecover(
|
||||
msgHashBuff,
|
||||
signature.v,
|
||||
ethUtil.toBuffer(signature.r),
|
||||
ethUtil.toBuffer(signature.s),
|
||||
);
|
||||
const retrievedAddress = ethUtil.bufferToHex(ethUtil.pubToAddress(pubKey));
|
||||
return retrievedAddress === signerAddress;
|
||||
} catch (err) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
/**
|
||||
* Signs an orderHash and returns it's elliptic curve signature.
|
||||
* This method currently supports TestRPC, Geth and Parity above and below V1.6.6
|
||||
* @param orderHash Hex encoded orderHash to sign.
|
||||
* @param signerAddress The hex encoded Ethereum address you wish to sign it with. This address
|
||||
* must be available via the Provider supplied to 0x.js.
|
||||
* @param shouldAddPersonalMessagePrefix Some signers add the personal message prefix `\x19Ethereum Signed Message`
|
||||
* themselves (e.g Parity Signer, Ledger, TestRPC) and others expect it to already be done by the client
|
||||
* (e.g Metamask). Depending on which signer this request is going to, decide on whether to add the prefix
|
||||
* before sending the request.
|
||||
* @return An object containing the Elliptic curve signature parameters generated by signing the orderHash.
|
||||
*/
|
||||
export async function signOrderHashAsync(
|
||||
provider: Provider,
|
||||
orderHash: string,
|
||||
signerAddress: string,
|
||||
shouldAddPersonalMessagePrefix: boolean,
|
||||
): Promise<ECSignature> {
|
||||
assert.isHexString('orderHash', orderHash);
|
||||
const web3Wrapper = new Web3Wrapper(provider);
|
||||
await assert.isSenderAddressAsync('signerAddress', signerAddress, web3Wrapper);
|
||||
const normalizedSignerAddress = signerAddress.toLowerCase();
|
||||
|
||||
let msgHashHex = orderHash;
|
||||
if (shouldAddPersonalMessagePrefix) {
|
||||
const orderHashBuff = ethUtil.toBuffer(orderHash);
|
||||
const msgHashBuff = ethUtil.hashPersonalMessage(orderHashBuff);
|
||||
msgHashHex = ethUtil.bufferToHex(msgHashBuff);
|
||||
}
|
||||
|
||||
const signature = await web3Wrapper.signMessageAsync(normalizedSignerAddress, msgHashHex);
|
||||
|
||||
// HACK: There is no consensus on whether the signatureHex string should be formatted as
|
||||
// v + r + s OR r + s + v, and different clients (even different versions of the same client)
|
||||
// return the signature params in different orders. In order to support all client implementations,
|
||||
// we parse the signature in both ways, and evaluate if either one is a valid signature.
|
||||
const validVParamValues = [27, 28];
|
||||
const ecSignatureVRS = parseSignatureHexAsVRS(signature);
|
||||
if (_.includes(validVParamValues, ecSignatureVRS.v)) {
|
||||
const isValidVRSSignature = isValidSignature(orderHash, ecSignatureVRS, normalizedSignerAddress);
|
||||
if (isValidVRSSignature) {
|
||||
return ecSignatureVRS;
|
||||
}
|
||||
}
|
||||
|
||||
const ecSignatureRSV = parseSignatureHexAsRSV(signature);
|
||||
if (_.includes(validVParamValues, ecSignatureRSV.v)) {
|
||||
const isValidRSVSignature = isValidSignature(orderHash, ecSignatureRSV, normalizedSignerAddress);
|
||||
if (isValidRSVSignature) {
|
||||
return ecSignatureRSV;
|
||||
}
|
||||
}
|
||||
|
||||
throw new Error(OrderError.InvalidSignature);
|
||||
}
|
||||
|
||||
function parseSignatureHexAsVRS(signatureHex: string): ECSignature {
|
||||
const signatureBuffer = ethUtil.toBuffer(signatureHex);
|
||||
let v = signatureBuffer[0];
|
||||
if (v < 27) {
|
||||
v += 27;
|
||||
}
|
||||
const r = signatureBuffer.slice(1, 33);
|
||||
const s = signatureBuffer.slice(33, 65);
|
||||
const ecSignature: ECSignature = {
|
||||
v,
|
||||
r: ethUtil.bufferToHex(r),
|
||||
s: ethUtil.bufferToHex(s),
|
||||
};
|
||||
return ecSignature;
|
||||
}
|
||||
|
||||
function parseSignatureHexAsRSV(signatureHex: string): ECSignature {
|
||||
const { v, r, s } = ethUtil.fromRpcSig(signatureHex);
|
||||
const ecSignature: ECSignature = {
|
||||
v,
|
||||
r: ethUtil.bufferToHex(r),
|
||||
s: ethUtil.bufferToHex(s),
|
||||
};
|
||||
return ecSignature;
|
||||
}
|
3
packages/order-utils/src/types.ts
Normal file
3
packages/order-utils/src/types.ts
Normal file
@@ -0,0 +1,3 @@
|
||||
export enum OrderError {
|
||||
InvalidSignature = 'INVALID_SIGNATURE',
|
||||
}
|
35
packages/order-utils/test/assert_test.ts
Normal file
35
packages/order-utils/test/assert_test.ts
Normal file
@@ -0,0 +1,35 @@
|
||||
import { web3Factory } from '@0xproject/dev-utils';
|
||||
import * as chai from 'chai';
|
||||
import 'mocha';
|
||||
|
||||
import { assert } from '../src/assert';
|
||||
|
||||
import { chaiSetup } from './utils/chai_setup';
|
||||
import { web3Wrapper } from './utils/web3_wrapper';
|
||||
|
||||
chaiSetup.configure();
|
||||
const expect = chai.expect;
|
||||
|
||||
describe('Assertion library', () => {
|
||||
describe('#isSenderAddressHexAsync', () => {
|
||||
it('throws when address is invalid', async () => {
|
||||
const address = '0xdeadbeef';
|
||||
const varName = 'address';
|
||||
return expect(assert.isSenderAddressAsync(varName, address, web3Wrapper)).to.be.rejectedWith(
|
||||
`Expected ${varName} to be of type ETHAddressHex, encountered: ${address}`,
|
||||
);
|
||||
});
|
||||
it('throws when address is unavailable', async () => {
|
||||
const validUnrelatedAddress = '0x8b0292b11a196601eddce54b665cafeca0347d42';
|
||||
const varName = 'address';
|
||||
return expect(assert.isSenderAddressAsync(varName, validUnrelatedAddress, web3Wrapper)).to.be.rejectedWith(
|
||||
`Specified ${varName} ${validUnrelatedAddress} isn't available through the supplied web3 provider`,
|
||||
);
|
||||
});
|
||||
it("doesn't throw if address is available", async () => {
|
||||
const availableAddress = (await web3Wrapper.getAvailableAddressesAsync())[0];
|
||||
const varName = 'address';
|
||||
return expect(assert.isSenderAddressAsync(varName, availableAddress, web3Wrapper)).to.become(undefined);
|
||||
});
|
||||
});
|
||||
});
|
46
packages/order-utils/test/order_hash_test.ts
Normal file
46
packages/order-utils/test/order_hash_test.ts
Normal file
@@ -0,0 +1,46 @@
|
||||
import { web3Factory } from '@0xproject/dev-utils';
|
||||
import { BigNumber } from '@0xproject/utils';
|
||||
import * as chai from 'chai';
|
||||
import 'mocha';
|
||||
|
||||
import { constants, getOrderHashHex } from '../src';
|
||||
|
||||
import { chaiSetup } from './utils/chai_setup';
|
||||
import { web3Wrapper } from './utils/web3_wrapper';
|
||||
|
||||
chaiSetup.configure();
|
||||
const expect = chai.expect;
|
||||
|
||||
describe('Order hashing', () => {
|
||||
describe('#getOrderHashHex', () => {
|
||||
const expectedOrderHash = '0x39da987067a3c9e5f1617694f1301326ba8c8b0498ebef5df4863bed394e3c83';
|
||||
const fakeExchangeContractAddress = '0xb69e673309512a9d726f87304c6984054f87a93b';
|
||||
const 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),
|
||||
makerTokenAmount: new BigNumber(0),
|
||||
takerTokenAmount: new BigNumber(0),
|
||||
expirationUnixTimestampSec: new BigNumber(0),
|
||||
};
|
||||
it('calculates the order hash', async () => {
|
||||
const orderHash = getOrderHashHex(order);
|
||||
expect(orderHash).to.be.equal(expectedOrderHash);
|
||||
});
|
||||
it('throws a readable error message if taker format is invalid', async () => {
|
||||
const orderWithInvalidtakerFormat = {
|
||||
...order,
|
||||
taker: (null as any) as string,
|
||||
};
|
||||
const expectedErrorMessage =
|
||||
'Order taker must be of type string. If you want anyone to be able to fill an order - pass ZeroEx.NULL_ADDRESS';
|
||||
expect(() => getOrderHashHex(orderWithInvalidtakerFormat)).to.throw(expectedErrorMessage);
|
||||
});
|
||||
});
|
||||
});
|
164
packages/order-utils/test/signature_utils_test.ts
Normal file
164
packages/order-utils/test/signature_utils_test.ts
Normal file
@@ -0,0 +1,164 @@
|
||||
import { web3Factory } from '@0xproject/dev-utils';
|
||||
import { JSONRPCErrorCallback, JSONRPCRequestPayload } from '@0xproject/types';
|
||||
import { BigNumber } from '@0xproject/utils';
|
||||
import * as chai from 'chai';
|
||||
import * as _ from 'lodash';
|
||||
import 'mocha';
|
||||
import * as Sinon from 'sinon';
|
||||
|
||||
import { generatePseudoRandomSalt, isValidOrderHash, isValidSignature, signOrderHashAsync } from '../src';
|
||||
import * as signatureUtils from '../src/signature_utils';
|
||||
|
||||
import { chaiSetup } from './utils/chai_setup';
|
||||
import { provider, web3Wrapper } from './utils/web3_wrapper';
|
||||
|
||||
chaiSetup.configure();
|
||||
const expect = chai.expect;
|
||||
|
||||
const SHOULD_ADD_PERSONAL_MESSAGE_PREFIX = false;
|
||||
|
||||
describe('Signature utils', () => {
|
||||
describe('#isValidSignature', () => {
|
||||
// The Exchange smart contract `isValidSignature` method only validates orderHashes and assumes
|
||||
// the length of the data is exactly 32 bytes. Thus for these tests, we use data of this size.
|
||||
const dataHex = '0x6927e990021d23b1eb7b8789f6a6feaf98fe104bb0cf8259421b79f9a34222b0';
|
||||
const signature = {
|
||||
v: 27,
|
||||
r: '0x61a3ed31b43c8780e905a260a35faefcc527be7516aa11c0256729b5b351bc33',
|
||||
s: '0x40349190569279751135161d22529dc25add4f6069af05be04cacbda2ace2254',
|
||||
};
|
||||
const address = '0x5409ed021d9299bf6814279a6a1411a7e866a631';
|
||||
it("should return false if the data doesn't pertain to the signature & address", async () => {
|
||||
expect(isValidSignature('0x0', signature, address)).to.be.false();
|
||||
});
|
||||
it("should return false if the address doesn't pertain to the signature & data", async () => {
|
||||
const validUnrelatedAddress = '0x8b0292b11a196601ed2ce54b665cafeca0347d42';
|
||||
expect(isValidSignature(dataHex, signature, validUnrelatedAddress)).to.be.false();
|
||||
});
|
||||
it("should return false if the signature doesn't pertain to the dataHex & address", async () => {
|
||||
const wrongSignature = _.assign({}, signature, { v: 28 });
|
||||
expect(isValidSignature(dataHex, wrongSignature, address)).to.be.false();
|
||||
});
|
||||
it('should return true if the signature does pertain to the dataHex & address', async () => {
|
||||
const isValidSignatureLocal = isValidSignature(dataHex, signature, address);
|
||||
expect(isValidSignatureLocal).to.be.true();
|
||||
});
|
||||
});
|
||||
describe('#generateSalt', () => {
|
||||
it('generates different salts', () => {
|
||||
const equal = generatePseudoRandomSalt().eq(generatePseudoRandomSalt());
|
||||
expect(equal).to.be.false();
|
||||
});
|
||||
it('generates salt in range [0..2^256)', () => {
|
||||
const salt = generatePseudoRandomSalt();
|
||||
expect(salt.greaterThanOrEqualTo(0)).to.be.true();
|
||||
const twoPow256 = new BigNumber(2).pow(256);
|
||||
expect(salt.lessThan(twoPow256)).to.be.true();
|
||||
});
|
||||
});
|
||||
describe('#isValidOrderHash', () => {
|
||||
it('returns false if the value is not a hex string', () => {
|
||||
const isValid = isValidOrderHash('not a hex');
|
||||
expect(isValid).to.be.false();
|
||||
});
|
||||
it('returns false if the length is wrong', () => {
|
||||
const isValid = isValidOrderHash('0xdeadbeef');
|
||||
expect(isValid).to.be.false();
|
||||
});
|
||||
it('returns true if order hash is correct', () => {
|
||||
const isValid = isValidOrderHash('0x' + Array(65).join('0'));
|
||||
expect(isValid).to.be.true();
|
||||
});
|
||||
});
|
||||
describe('#signOrderHashAsync', () => {
|
||||
let stubs: Sinon.SinonStub[] = [];
|
||||
let makerAddress: string;
|
||||
before(async () => {
|
||||
const availableAddreses = await web3Wrapper.getAvailableAddressesAsync();
|
||||
makerAddress = availableAddreses[0];
|
||||
});
|
||||
afterEach(() => {
|
||||
// clean up any stubs after the test has completed
|
||||
_.each(stubs, s => s.restore());
|
||||
stubs = [];
|
||||
});
|
||||
it('Should return the correct ECSignature', async () => {
|
||||
const orderHash = '0x6927e990021d23b1eb7b8789f6a6feaf98fe104bb0cf8259421b79f9a34222b0';
|
||||
const expectedECSignature = {
|
||||
v: 27,
|
||||
r: '0x61a3ed31b43c8780e905a260a35faefcc527be7516aa11c0256729b5b351bc33',
|
||||
s: '0x40349190569279751135161d22529dc25add4f6069af05be04cacbda2ace2254',
|
||||
};
|
||||
const ecSignature = await signOrderHashAsync(
|
||||
provider,
|
||||
orderHash,
|
||||
makerAddress,
|
||||
SHOULD_ADD_PERSONAL_MESSAGE_PREFIX,
|
||||
);
|
||||
expect(ecSignature).to.deep.equal(expectedECSignature);
|
||||
});
|
||||
it('should return the correct ECSignature for signatureHex concatenated as R + S + V', async () => {
|
||||
const orderHash = '0x34decbedc118904df65f379a175bb39ca18209d6ce41d5ed549d54e6e0a95004';
|
||||
const expectedECSignature = {
|
||||
v: 27,
|
||||
r: '0x117902c86dfb95fe0d1badd983ee166ad259b27acb220174cbb4460d87287113',
|
||||
s: '0x7feabdfe76e05924b484789f79af4ee7fa29ec006cedce1bbf369320d034e10b',
|
||||
};
|
||||
|
||||
const fakeProvider = {
|
||||
async sendAsync(payload: JSONRPCRequestPayload, callback: JSONRPCErrorCallback) {
|
||||
if (payload.method === 'eth_sign') {
|
||||
const [address, message] = payload.params;
|
||||
const signature = await web3Wrapper.signMessageAsync(address, message);
|
||||
callback(null, {
|
||||
id: 42,
|
||||
jsonrpc: '2.0',
|
||||
result: `0x${signature.substr(130)}${signature.substr(2, 128)}`,
|
||||
});
|
||||
} else {
|
||||
callback(null, { id: 42, jsonrpc: '2.0', result: [makerAddress] });
|
||||
}
|
||||
},
|
||||
};
|
||||
|
||||
const ecSignature = await signOrderHashAsync(
|
||||
fakeProvider,
|
||||
orderHash,
|
||||
makerAddress,
|
||||
SHOULD_ADD_PERSONAL_MESSAGE_PREFIX,
|
||||
);
|
||||
expect(ecSignature).to.deep.equal(expectedECSignature);
|
||||
});
|
||||
it('should return the correct ECSignature for signatureHex concatenated as V + R + S', async () => {
|
||||
const orderHash = '0x34decbedc118904df65f379a175bb39ca18209d6ce41d5ed549d54e6e0a95004';
|
||||
const expectedECSignature = {
|
||||
v: 27,
|
||||
r: '0x117902c86dfb95fe0d1badd983ee166ad259b27acb220174cbb4460d87287113',
|
||||
s: '0x7feabdfe76e05924b484789f79af4ee7fa29ec006cedce1bbf369320d034e10b',
|
||||
};
|
||||
const fakeProvider = {
|
||||
async sendAsync(payload: JSONRPCRequestPayload, callback: JSONRPCErrorCallback) {
|
||||
if (payload.method === 'eth_sign') {
|
||||
const [address, message] = payload.params;
|
||||
const signature = await web3Wrapper.signMessageAsync(address, message);
|
||||
callback(null, {
|
||||
id: 42,
|
||||
jsonrpc: '2.0',
|
||||
result: signature,
|
||||
});
|
||||
} else {
|
||||
callback(null, { id: 42, jsonrpc: '2.0', result: [makerAddress] });
|
||||
}
|
||||
},
|
||||
};
|
||||
|
||||
const ecSignature = await signOrderHashAsync(
|
||||
fakeProvider,
|
||||
orderHash,
|
||||
makerAddress,
|
||||
SHOULD_ADD_PERSONAL_MESSAGE_PREFIX,
|
||||
);
|
||||
expect(ecSignature).to.deep.equal(expectedECSignature);
|
||||
});
|
||||
});
|
||||
});
|
13
packages/order-utils/test/utils/chai_setup.ts
Normal file
13
packages/order-utils/test/utils/chai_setup.ts
Normal file
@@ -0,0 +1,13 @@
|
||||
import * as chai from 'chai';
|
||||
import chaiAsPromised = require('chai-as-promised');
|
||||
import ChaiBigNumber = require('chai-bignumber');
|
||||
import * as dirtyChai from 'dirty-chai';
|
||||
|
||||
export const chaiSetup = {
|
||||
configure() {
|
||||
chai.config.includeStack = true;
|
||||
chai.use(ChaiBigNumber());
|
||||
chai.use(dirtyChai);
|
||||
chai.use(chaiAsPromised);
|
||||
},
|
||||
};
|
9
packages/order-utils/test/utils/web3_wrapper.ts
Normal file
9
packages/order-utils/test/utils/web3_wrapper.ts
Normal file
@@ -0,0 +1,9 @@
|
||||
import { devConstants, web3Factory } from '@0xproject/dev-utils';
|
||||
import { Provider } from '@0xproject/types';
|
||||
import { Web3Wrapper } from '@0xproject/web3-wrapper';
|
||||
|
||||
const web3 = web3Factory.create({ shouldUseInProcessGanache: true });
|
||||
const provider: Provider = web3.currentProvider;
|
||||
const web3Wrapper = new Web3Wrapper(web3.currentProvider);
|
||||
|
||||
export { provider, web3Wrapper };
|
7
packages/order-utils/tsconfig.json
Normal file
7
packages/order-utils/tsconfig.json
Normal file
@@ -0,0 +1,7 @@
|
||||
{
|
||||
"extends": "../../tsconfig",
|
||||
"compilerOptions": {
|
||||
"outDir": "lib"
|
||||
},
|
||||
"include": ["src/**/*", "test/**/*"]
|
||||
}
|
3
packages/order-utils/tslint.json
Normal file
3
packages/order-utils/tslint.json
Normal file
@@ -0,0 +1,3 @@
|
||||
{
|
||||
"extends": ["@0xproject/tslint-config"]
|
||||
}
|
@@ -27,7 +27,7 @@
|
||||
"@types/lodash": "4.14.104",
|
||||
"@types/material-ui": "0.18.0",
|
||||
"@types/node": "^8.0.53",
|
||||
"@types/react": "^16.0.34",
|
||||
"@types/react": "16.0.41",
|
||||
"@types/react-dom": "^16.0.3",
|
||||
"@types/react-tap-event-plugin": "0.0.30",
|
||||
"awesome-typescript-loader": "^3.1.3",
|
||||
|
@@ -1,4 +1,13 @@
|
||||
[
|
||||
{
|
||||
"timestamp": 1525428773,
|
||||
"version": "0.0.9",
|
||||
"changes": [
|
||||
{
|
||||
"note": "Dependencies updated"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"version": "0.0.8",
|
||||
"changes": [
|
||||
|
@@ -5,13 +5,17 @@ Edit the package's CHANGELOG.json file only.
|
||||
|
||||
CHANGELOG
|
||||
|
||||
## v0.0.9 - _May 4, 2018_
|
||||
|
||||
* Dependencies updated
|
||||
|
||||
## v0.0.8 - _April 18, 2018_
|
||||
|
||||
* Added support for rendering default param values (#519)
|
||||
* Added support for rendering nested function types within interface types (#519)
|
||||
* Improve type comment rendering (#535)
|
||||
|
||||
## v0.0.7 - _April 12, 2018_
|
||||
## v0.0.7 - _April 11, 2018_
|
||||
|
||||
* Dependencies updated
|
||||
|
||||
@@ -26,11 +30,11 @@ CHANGELOG
|
||||
* Rename `MethodBlock` to `SignatureBlock` since it is not used to render method and function signature blocks. (#465)
|
||||
* Add support for documenting exported functions. (#465)
|
||||
|
||||
## v0.0.3 - _March 18, 2018_
|
||||
## v0.0.3 - _March 17, 2018_
|
||||
|
||||
* Move TS typings from devDependencies to dependencies since they are needed by the package user.
|
||||
|
||||
## v0.0.2 - _March 18, 2018_
|
||||
## v0.0.2 - _March 17, 2018_
|
||||
|
||||
* Move example out into a separate sub-package
|
||||
* Consolidate all `console.log` calls into `logUtils` in the `@0xproject/utils` package (#452)
|
||||
|
@@ -36,7 +36,7 @@
|
||||
"@types/lodash": "4.14.104",
|
||||
"@types/material-ui": "0.18.0",
|
||||
"@types/node": "^8.0.53",
|
||||
"@types/react": "^16.0.34",
|
||||
"@types/react": "16.0.41",
|
||||
"@types/react-dom": "^16.0.3",
|
||||
"@types/react-scroll": "0.0.31",
|
||||
"basscss": "^8.0.3",
|
||||
|
@@ -94,6 +94,7 @@ export enum KindString {
|
||||
Method = 'Method',
|
||||
Interface = 'Interface',
|
||||
TypeAlias = 'Type alias',
|
||||
ObjectLiteral = 'Object literal',
|
||||
Variable = 'Variable',
|
||||
Function = 'Function',
|
||||
Enumeration = 'Enumeration',
|
||||
|
@@ -93,10 +93,16 @@ export const typeDocUtils = {
|
||||
throw new Error('`react-docs` only supports projects with 1 exported class per file');
|
||||
}
|
||||
const isClassExport = packageDefinitionWithMergedChildren.children[0].kindString === KindString.Class;
|
||||
const isObjectLiteralExport =
|
||||
packageDefinitionWithMergedChildren.children[0].kindString === KindString.ObjectLiteral;
|
||||
if (isClassExport) {
|
||||
entities = packageDefinitionWithMergedChildren.children[0].children;
|
||||
const commentObj = packageDefinitionWithMergedChildren.children[0].comment;
|
||||
packageComment = !_.isUndefined(commentObj) ? commentObj.shortText : packageComment;
|
||||
} else if (isObjectLiteralExport) {
|
||||
entities = packageDefinitionWithMergedChildren.children[0].children;
|
||||
const commentObj = packageDefinitionWithMergedChildren.children[0].comment;
|
||||
packageComment = !_.isUndefined(commentObj) ? commentObj.shortText : packageComment;
|
||||
} else {
|
||||
entities = packageDefinitionWithMergedChildren.children;
|
||||
}
|
||||
|
@@ -1,4 +1,13 @@
|
||||
[
|
||||
{
|
||||
"timestamp": 1525428773,
|
||||
"version": "0.1.4",
|
||||
"changes": [
|
||||
{
|
||||
"note": "Dependencies updated"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"timestamp": 1524044013,
|
||||
"version": "0.1.3",
|
||||
|
@@ -5,11 +5,15 @@ Edit the package's CHANGELOG.json file only.
|
||||
|
||||
CHANGELOG
|
||||
|
||||
## v0.1.4 - _May 4, 2018_
|
||||
|
||||
* Dependencies updated
|
||||
|
||||
## v0.1.3 - _April 18, 2018_
|
||||
|
||||
* Dependencies updated
|
||||
|
||||
## v0.1.2 - _April 12, 2018_
|
||||
## v0.1.2 - _April 11, 2018_
|
||||
|
||||
* Dependencies updated
|
||||
|
||||
|
@@ -34,7 +34,7 @@
|
||||
"@types/lodash": "4.14.104",
|
||||
"@types/material-ui": "0.18.0",
|
||||
"@types/node": "^8.0.53",
|
||||
"@types/react": "^16.0.34",
|
||||
"@types/react": "16.0.41",
|
||||
"@types/react-dom": "^16.0.3",
|
||||
"@types/react-scroll": "0.0.31",
|
||||
"basscss": "^8.0.3",
|
||||
|
@@ -28,6 +28,7 @@ const baseColors = {
|
||||
linkBlue: '#1D5CDE',
|
||||
mediumBlue: '#488AEA',
|
||||
darkBlue: '#4D5481',
|
||||
lightTurquois: '#aefcdc',
|
||||
turquois: '#058789',
|
||||
lightPurple: '#A81CA6',
|
||||
purple: '#690596',
|
||||
|
@@ -1,4 +1,13 @@
|
||||
[
|
||||
{
|
||||
"timestamp": 1525428773,
|
||||
"version": "0.0.9",
|
||||
"changes": [
|
||||
{
|
||||
"note": "Dependencies updated"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"timestamp": 1524044013,
|
||||
"version": "0.0.8",
|
||||
|
@@ -5,11 +5,15 @@ Edit the package's CHANGELOG.json file only.
|
||||
|
||||
CHANGELOG
|
||||
|
||||
## v0.0.9 - _May 4, 2018_
|
||||
|
||||
* Dependencies updated
|
||||
|
||||
## v0.0.8 - _April 18, 2018_
|
||||
|
||||
* Dependencies updated
|
||||
|
||||
## v0.0.7 - _April 12, 2018_
|
||||
## v0.0.7 - _April 11, 2018_
|
||||
|
||||
* Dependencies updated
|
||||
|
||||
|
@@ -1,4 +1,13 @@
|
||||
[
|
||||
{
|
||||
"timestamp": 1525428773,
|
||||
"version": "0.0.3",
|
||||
"changes": [
|
||||
{
|
||||
"note": "Dependencies updated"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"timestamp": 1524044013,
|
||||
"version": "0.0.2",
|
||||
|
@@ -5,6 +5,10 @@ Edit the package's CHANGELOG.json file only.
|
||||
|
||||
CHANGELOG
|
||||
|
||||
## v0.0.3 - _May 4, 2018_
|
||||
|
||||
* Dependencies updated
|
||||
|
||||
## v0.0.2 - _April 18, 2018_
|
||||
|
||||
* Dependencies updated
|
||||
|
@@ -1,4 +1,31 @@
|
||||
[
|
||||
{
|
||||
"timestamp": 1525428773,
|
||||
"version": "0.0.12",
|
||||
"changes": [
|
||||
{
|
||||
"note": "Dependencies updated"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"timestamp": 1524079658,
|
||||
"version": "0.0.11",
|
||||
"changes": [
|
||||
{
|
||||
"note": "Dependencies updated"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"timestamp": 1524073495,
|
||||
"version": "0.0.10",
|
||||
"changes": [
|
||||
{
|
||||
"note": "Dependencies updated"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"timestamp": 1524044013,
|
||||
"version": "0.0.9",
|
||||
|
@@ -5,11 +5,23 @@ Edit the package's CHANGELOG.json file only.
|
||||
|
||||
CHANGELOG
|
||||
|
||||
## v0.0.12 - _May 4, 2018_
|
||||
|
||||
* Dependencies updated
|
||||
|
||||
## v0.0.11 - _April 18, 2018_
|
||||
|
||||
* Dependencies updated
|
||||
|
||||
## v0.0.10 - _April 18, 2018_
|
||||
|
||||
* Dependencies updated
|
||||
|
||||
## v0.0.9 - _April 18, 2018_
|
||||
|
||||
* Dependencies updated
|
||||
|
||||
## v0.0.8 - _April 12, 2018_
|
||||
## v0.0.8 - _April 11, 2018_
|
||||
|
||||
* Dependencies updated
|
||||
|
||||
@@ -21,8 +33,8 @@ CHANGELOG
|
||||
|
||||
* Added postman collection unit tests (#451)
|
||||
|
||||
## v0.0.2 - _March 18, 2018_
|
||||
## v0.0.2 - _March 17, 2018_
|
||||
|
||||
* Consolidate all `console.log` calls into `logUtils` in the `@0xproject/utils` package (#452)
|
||||
|
||||
## v0.0.1 - _March 8, 2018_
|
||||
## v0.0.1 - _March 7, 2018_
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user