Compare commits

..

84 Commits

Author SHA1 Message Date
Leonid Logvinov
3fc99dbad5 Updated CHANGELOGS 2018-05-04 12:16:11 +02:00
Leonid Logvinov
01dd84dced Add order utils docs to the menu 2018-05-04 12:09:46 +02:00
Brandon Millman
6b92ef733c Open relayer app when clicking on grid tile 2018-05-03 13:59:08 -07:00
Brandon Millman
fe0f4ae257 Add header images to relayer grid tiles 2018-05-03 13:59:00 -07:00
Fabio Berger
cf9555debc Fix logo left padding on mobile 2018-05-03 12:35:21 +02:00
Fabio Berger
528008b1a9 Add new section to homepage 2018-05-03 12:35:07 +02:00
Brandon Millman
5e3576ed69 Remove id property from WebsiteBackendRelayerInfo 2018-05-02 17:03:59 -07:00
Leonid Logvinov
28ee9e247e Add order-utils to monorepo-scripts 2018-05-02 20:00:06 +03:00
Leonid Logvinov
a054b485d0 Merge pull request #559 from 0xProject/feature/order-utils
Move order utils to @0xproject/order-utils
2018-05-02 19:42:59 +03:00
Leonid Logvinov
3585326d7e Fix signature utils tests 2018-05-02 19:30:32 +03:00
Leonid Logvinov
a6046af024 Stop exporting assertions from order-utils 2018-05-02 18:38:50 +03:00
Leonid Logvinov
adaff92c92 Create wrapper functions so that docs render properly 2018-05-02 16:01:01 +03:00
Leonid Logvinov
0499541e11 Move order utils to @0xproject/order-utils 2018-05-02 15:10:24 +03:00
Brandon Millman
f08738e133 Add Greg and Remco to the about page 2018-05-01 17:11:06 -07:00
Brandon Millman
1fbdc14734 Merge pull request #550 from 0xProject/feature/website/crypto-compare-prices
Grab wallet price information by token symbol
2018-05-01 10:09:04 -07:00
Jacob Evans
3e683162e9 Merge pull request #568 from 0xProject/bug/0x.js/trade-simulator-trading-zrx
Execute Taker side in trade simulation
2018-05-01 21:55:49 +10:00
Jacob Evans
8e7937bdb6 Update comment to be more descriptive of null address in exchange simulator 2018-05-01 19:06:17 +10:00
Jacob Evans
b36587fac8 Execute taker side in trade simulation
Fill if the taker address is open
2018-05-01 14:43:47 +10:00
Brandon Millman
3a1f9d01e8 Remove WETH special case, website backend handles this now 2018-04-30 16:49:47 -07:00
Brandon Millman
1131d66b3d Hit website backend for price information 2018-04-30 16:40:02 -07:00
Brandon Millman
7104ae4752 Merge pull request #564 from 0xProject/add-code-of-conduct-1
Create CODE_OF_CONDUCT.md
2018-04-30 09:47:33 -07:00
Brandon Millman
2403323463 Style suggestions 2018-04-27 15:05:23 -07:00
Brandon Millman
feb7dfffa1 Move quote currency string into config 2018-04-27 15:05:23 -07:00
Brandon Millman
005e633e2a yarn.lock 2018-04-27 15:05:00 -07:00
Brandon Millman
127fe971e9 Prettier 2018-04-27 14:50:04 -07:00
Brandon Millman
3c4bde6ea1 Create CODE_OF_CONDUCT.md 2018-04-27 14:09:25 -07:00
Brandon Millman
dc19690863 Merge branch 'development' into feature/website/crypto-compare-prices
* development:
  Fix react type versions to avoid minor version bumps with breaking changes
  Update Web3 Provider Engine to 14.0.4
  Remove auto-assignment of everyone to PR's
  Check for Yarn instead of npm
  Add hack comment about the use of sudo
  Fix lazy load component name
  Rename Portal and PortalMenu components to LegacyPortal and LegacyPortalMenu
  Remove unnecessary additional params
  Remove outside declaration
  Capitalize yarn
  Use path for platform independence
  Consolidate github personal access token env to one place: constants.ts
  Use methods moved to utils since now shared by multiple scripts
  Add comment
  Improve comments
  Add checks for the required local setup before running the publish script
  Add descriptions for all commands in monorepo-scripts
  Add removeGitTags script that can be run after a failed Lerna publish
2018-04-26 17:11:01 -07:00
Jacob Evans
47604384d4 Merge pull request #555 from 0xProject/feature/subproviders/upgrade-provider-engine
Update Web3 Provider Engine to 14.0.4
2018-04-26 15:44:55 +10:00
Fabio Berger
c69984e309 Fix react type versions to avoid minor version bumps with breaking changes 2018-04-24 20:06:09 +09:00
Jacob Evans
5682cd0048 Update Web3 Provider Engine to 14.0.4 2018-04-24 14:33:32 +10:00
Fabio Berger
2896110d4d Merge branch 'development' of github.com:0xProject/0x-monorepo into development
* 'development' of github.com:0xProject/0x-monorepo:
  Fix lazy load component name
  Rename Portal and PortalMenu components to LegacyPortal and LegacyPortalMenu
2018-04-24 13:01:15 +09:00
Fabio Berger
d05b175e04 Remove auto-assignment of everyone to PR's 2018-04-24 12:53:54 +09:00
Brandon Millman
10a379077c Merge pull request #552 from 0xProject/refactor/website/legacy-portal
Rename Portal component to LegacyPortal
2018-04-23 22:42:07 -04:00
Fabio Berger
ffd9b79100 Check for Yarn instead of npm 2018-04-24 10:43:44 +09:00
Fabio Berger
04c07d9006 Merge pull request #541 from 0xProject/improveMonorepoScripts
Improve Monorepo-scripts
2018-04-24 10:34:40 +09:00
Fabio Berger
a3cc5c1dd7 Add hack comment about the use of sudo 2018-04-24 10:32:44 +09:00
Brandon Millman
941342cc24 Fix lazy load component name 2018-04-23 16:49:53 -07:00
Brandon Millman
cc471dd127 Rename Portal and PortalMenu components to LegacyPortal and LegacyPortalMenu 2018-04-23 14:27:11 -07:00
Brandon Millman
9b535e3cec Rename baseCurrency to quoteCurrency 2018-04-22 14:20:42 -04:00
Brandon Millman
9656895726 Remove some unused imports 2018-04-22 14:17:34 -04:00
Brandon Millman
121b6949a1 Rate limit crypto compare calls 2018-04-22 14:05:03 -04:00
Brandon Millman
fb31c49317 Refactor common fetch logic into fetch_utils 2018-04-22 13:28:13 -04:00
Brandon Millman
e51f9b3593 Grab price information from crypto compare api 2018-04-22 13:10:58 -04:00
Amir Bandeali
d08bfbf705 Merge pull request #545 from 0xProject/feature/deployer/solidity-0.4.23
Feature/deployer/solidity 0.4.23
2018-04-20 13:55:49 -07:00
Amir Bandeali
a10e466fed Fix getABIEncodedTransactionData in contract templates 2018-04-20 13:54:33 -07:00
Amir Bandeali
35bb010c35 Add support for solidity 0.4.23 2018-04-20 13:54:28 -07:00
Brandon Millman
0046a0762c Merge pull request #543 from 0xProject/feature/website/integrate-relayer-info
Integrate relayer index with website backend
2018-04-20 15:37:41 -04:00
Brandon Millman
c453012a8e Add specific render path for error and loading 2018-04-20 15:36:40 -04:00
Fabio Berger
1f82c7eadf Remove unnecessary additional params 2018-04-20 10:04:22 +09:00
Fabio Berger
b6fb8dbb52 Remove outside declaration 2018-04-20 10:03:53 +09:00
Fabio Berger
30256cbe51 Capitalize yarn 2018-04-20 10:01:21 +09:00
Fabio Berger
7f46e9af2c Use path for platform independence 2018-04-20 10:00:37 +09:00
Fabio Berger
417cec9e04 Consolidate github personal access token env to one place: constants.ts 2018-04-20 09:36:03 +09:00
Jacob Evans
62a55c0135 Merge pull request #540 from 0xProject/feature/abi-gen/tuple-return-types
Support Tuples returned from functions
2018-04-20 08:49:23 +10:00
Jacob Evans
72336eb393 Remove ethers-contracts types 2018-04-20 08:26:10 +10:00
Brandon Millman
12d8c0b6af Integrate relayer index with website backend 2018-04-19 16:28:35 -04:00
Jacob Evans
5c232b6a8d Update CHANGELOGs 2018-04-19 17:16:05 +10:00
Fabio Berger
f6fd4281a4 Add ImToken to landing page 2018-04-19 15:35:12 +09:00
Jacob Evans
4bee63afc6 Interface for EventDescription renamed topics 2018-04-19 16:28:46 +10:00
Jacob Evans
d186f6148b Use ethers in abi_decoder utils 2018-04-19 15:25:04 +10:00
Fabio Berger
2b15c03b9a Use methods moved to utils since now shared by multiple scripts 2018-04-19 14:19:34 +09:00
Fabio Berger
60d879e045 Add comment 2018-04-19 14:16:11 +09:00
Fabio Berger
858d1768ce Improve comments 2018-04-19 14:14:10 +09:00
Fabio Berger
fc2b7f747b Add checks for the required local setup before running the publish script 2018-04-19 14:10:48 +09:00
Jacob Evans
207019c7f3 Add ethers to web3-wrapper 2018-04-19 14:59:10 +10:00
Jacob Evans
b264bbea84 Update 0x.js package json for ethers 2018-04-19 14:57:14 +10:00
Jacob Evans
32efb3e280 Update ethers in metacoin project 2018-04-19 13:44:14 +10:00
Fabio Berger
1a0d68d49a Add descriptions for all commands in monorepo-scripts 2018-04-19 11:56:41 +09:00
Fabio Berger
7dd3b2d38b Add removeGitTags script that can be run after a failed Lerna publish 2018-04-19 11:40:22 +09:00
Fabio Berger
4bc65faf1a Merge pull request #526 from 0xProject/fix/expiration-watcher
Fix expiration watcher comparator
2018-04-19 11:28:18 +09:00
Brandon Millman
8634551f53 Merge pull request #539 from 0xProject/feature/website/backend-client
Implement backendClient object to unify calls to the portal api
2018-04-18 22:25:03 -04:00
Brandon Millman
089663ccc1 Merge pull request #534 from 0xProject/feature/website/integrate-prices
Add price information to wallet
2018-04-18 22:20:03 -04:00
Fabio Berger
d1d26f8bf6 Merge branch 'development' into fix/expiration-watcher
* development:
  Publish
  Updated CHANGELOGS
  Move @0xproject/migrations to devDependencies
  Publish
  Updated CHANGELOGS
  Make @0xproject/migrations public

# Conflicts:
#	packages/0x.js/CHANGELOG.json
#	packages/0x.js/package.json
2018-04-19 10:38:43 +09:00
Fabio Berger
1ca86730fa Remove hack above migrations package 2018-04-19 10:37:13 +09:00
Jacob Evans
12ae7c009d Support Tuples from function returns 2018-04-19 11:21:32 +10:00
Brandon Millman
51b2fce8c1 Implement backendClient object to unify calls to the portal api 2018-04-18 20:12:38 -04:00
Leonid Logvinov
62fcb51e1a Publish
- 0x.js@0.36.3
 - contracts@2.1.25
 - @0xproject/sra-report@0.0.11
 - @0xproject/testnet-faucets@1.0.26
 - @0xproject/website@0.0.28
2018-04-18 21:30:28 +02:00
Leonid Logvinov
cbc55f2ef8 Updated CHANGELOGS 2018-04-18 21:30:20 +02:00
Leonid Logvinov
679f828e4e Move @0xproject/migrations to devDependencies 2018-04-18 21:18:18 +02:00
Leonid Logvinov
4a8b4e7398 Publish
- 0x.js@0.36.2
 - contracts@2.1.24
 - @0xproject/migrations@0.0.3
 - @0xproject/sra-report@0.0.10
 - @0xproject/testnet-faucets@1.0.25
 - @0xproject/website@0.0.27
2018-04-18 19:57:42 +02:00
Leonid Logvinov
b6a11ca31e Updated CHANGELOGS 2018-04-18 19:57:36 +02:00
Leonid Logvinov
a30ccf2b25 Make @0xproject/migrations public 2018-04-18 19:32:53 +02:00
Leonid Logvinov
2574405699 Fix expiration watcher comparator 2018-04-18 13:45:04 +02:00
Brandon Millman
39c0064ffb Add price information to wallet 2018-04-18 00:30:52 -04:00
152 changed files with 2469 additions and 872 deletions

View File

@@ -1 +0,0 @@
* @abandeali1 @BMillman19 @dekz @fabioberger @LogvinovLeon @Recmo

46
CODE_OF_CONDUCT.md Normal file
View 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/

View File

@@ -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": [

View File

@@ -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.

View File

@@ -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"
}

View File

@@ -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.

View File

@@ -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,

View File

@@ -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 {

View File

@@ -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',

View File

@@ -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');
},
};

View File

@@ -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',

View File

@@ -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)) {

View File

@@ -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(

View File

@@ -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;
},
};

View File

@@ -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();
},

View File

@@ -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();

View File

@@ -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);
});
});
});

View File

@@ -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);
});
});

View File

@@ -0,0 +1,7 @@
import { runMigrationsAsync } from '@0xproject/migrations';
import { deployer } from './utils/deployer';
before('migrate contracts', async () => {
await runMigrationsAsync(deployer);
});

View File

@@ -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

View File

@@ -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,

View File

@@ -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;

View File

@@ -1,4 +1,13 @@
[
{
"timestamp": 1525428773,
"version": "0.2.12",
"changes": [
{
"note": "Dependencies updated"
}
]
},
{
"timestamp": 1524044013,
"version": "0.2.11",

View File

@@ -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)

View File

@@ -1,4 +1,13 @@
[
{
"timestamp": 1525428773,
"version": "0.2.8",
"changes": [
{
"note": "Dependencies updated"
}
]
},
{
"timestamp": 1524044013,
"version": "0.2.7",

View File

@@ -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.

View File

@@ -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",

View File

@@ -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

View File

@@ -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": {

View File

@@ -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]);
});
}
}

View File

@@ -1,4 +1,13 @@
[
{
"timestamp": 1525428773,
"version": "0.6.11",
"changes": [
{
"note": "Dependencies updated"
}
]
},
{
"timestamp": 1524044013,
"version": "0.6.10",

View File

@@ -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

View File

@@ -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}}

View File

@@ -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}};

View File

@@ -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}}]

View File

@@ -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;

View File

@@ -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",

View File

@@ -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": [

View File

@@ -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)

View File

@@ -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"

View File

@@ -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',
};

View File

@@ -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": [

View File

@@ -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)

View File

@@ -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"

View File

@@ -1,4 +1,13 @@
[
{
"timestamp": 1525428773,
"version": "0.7.22",
"changes": [
{
"note": "Dependencies updated"
}
]
},
{
"timestamp": 1524044013,
"version": "0.7.21",

View File

@@ -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

View File

@@ -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",

View 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"
}
]
}
]

View 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

View File

@@ -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"
}
}

View File

@@ -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(

View File

@@ -1,4 +1,13 @@
[
{
"timestamp": 1525428773,
"version": "0.1.19",
"changes": [
{
"note": "Dependencies updated"
}
]
},
{
"timestamp": 1524044013,
"version": "0.1.18",

View File

@@ -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

View File

@@ -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

View File

@@ -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",

View File

@@ -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,
};

View File

@@ -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,

View File

@@ -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;

View 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);
});

View File

@@ -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;
},
};

View File

@@ -0,0 +1,7 @@
.*
yarn-error.log
/scripts/
/generated_docs/
/src/
tsconfig.json
/lib/monorepo_scripts/

View File

@@ -0,0 +1,11 @@
[
{
"timestamp": 1525428773,
"version": "0.0.2",
"changes": [
{
"note": "Dependencies updated"
}
]
}
]

View 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

View 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
```

View File

View 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"
}
}

View 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`,
);
},
};

View File

@@ -0,0 +1,3 @@
export const constants = {
NULL_ADDRESS: '0x0000000000000000000000000000000000000000',
};

6
packages/order-utils/src/globals.d.ts vendored Normal file
View File

@@ -0,0 +1,6 @@
declare module '*.json' {
const json: any;
/* tslint:disable */
export default json;
/* tslint:enable */
}

View 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';

View 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);

View 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);

View File

@@ -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;
},

View 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;
}

View 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;
}

View 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;
}

View File

@@ -0,0 +1,3 @@
export enum OrderError {
InvalidSignature = 'INVALID_SIGNATURE',
}

View 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);
});
});
});

View 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);
});
});
});

View 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);
});
});
});

View 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);
},
};

View 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 };

View File

@@ -0,0 +1,7 @@
{
"extends": "../../tsconfig",
"compilerOptions": {
"outDir": "lib"
},
"include": ["src/**/*", "test/**/*"]
}

View File

@@ -0,0 +1,3 @@
{
"extends": ["@0xproject/tslint-config"]
}

View File

@@ -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",

View File

@@ -1,4 +1,13 @@
[
{
"timestamp": 1525428773,
"version": "0.0.9",
"changes": [
{
"note": "Dependencies updated"
}
]
},
{
"version": "0.0.8",
"changes": [

View File

@@ -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)

View File

@@ -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",

View File

@@ -94,6 +94,7 @@ export enum KindString {
Method = 'Method',
Interface = 'Interface',
TypeAlias = 'Type alias',
ObjectLiteral = 'Object literal',
Variable = 'Variable',
Function = 'Function',
Enumeration = 'Enumeration',

View File

@@ -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;
}

View File

@@ -1,4 +1,13 @@
[
{
"timestamp": 1525428773,
"version": "0.1.4",
"changes": [
{
"note": "Dependencies updated"
}
]
},
{
"timestamp": 1524044013,
"version": "0.1.3",

View File

@@ -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

View File

@@ -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",

View File

@@ -28,6 +28,7 @@ const baseColors = {
linkBlue: '#1D5CDE',
mediumBlue: '#488AEA',
darkBlue: '#4D5481',
lightTurquois: '#aefcdc',
turquois: '#058789',
lightPurple: '#A81CA6',
purple: '#690596',

View File

@@ -1,4 +1,13 @@
[
{
"timestamp": 1525428773,
"version": "0.0.9",
"changes": [
{
"note": "Dependencies updated"
}
]
},
{
"timestamp": 1524044013,
"version": "0.0.8",

View File

@@ -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

View File

@@ -1,4 +1,13 @@
[
{
"timestamp": 1525428773,
"version": "0.0.3",
"changes": [
{
"note": "Dependencies updated"
}
]
},
{
"timestamp": 1524044013,
"version": "0.0.2",

View File

@@ -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

View File

@@ -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",

View File

@@ -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