diff options
229 files changed, 2761 insertions, 1194 deletions
diff --git a/.circleci/config.yml b/.circleci/config.yml index 8e5fd969d..0398705b0 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -124,6 +124,10 @@ jobs: key: coverage-sol-cov-{{ .Environment.CIRCLE_SHA1 }} paths: - ~/repo/packages/sol-cov/coverage/lcov.info + - save_cache: + key: coverage-metacoin-{{ .Environment.CIRCLE_SHA1 }} + paths: + - ~/repo/packages/metacoin/coverage/lcov.info lint: working_directory: ~/repo docker: @@ -177,15 +181,18 @@ jobs: - restore_cache: keys: - coverage-0xjs-{{ .Environment.CIRCLE_SHA1 }} + - restore_cache: + keys: + - coverage-metacoin-{{ .Environment.CIRCLE_SHA1 }} - run: yarn report_coverage workflows: version: 2 main: jobs: - build - # - test-installation: - # requires: - # - build + - test-installation: + requires: + - build - test-0xjs: requires: - build diff --git a/.gitignore b/.gitignore index 4d315dc3a..83538fdca 100644 --- a/.gitignore +++ b/.gitignore @@ -74,7 +74,10 @@ packages/react-docs/example/public/bundle* bin/ # generated contract artifacts -packages/contracts/src/artifacts +packages/sol-cov/test/fixtures/artifacts +packages/metacoin/artifacts +packages/0x.js/test/artifacts +packages/migrations/src/artifacts # generated contract wrappers packages/0x.js/src/contract_wrappers/generated/ diff --git a/.prettierignore b/.prettierignore index 5b8003c95..024d0b548 100644 --- a/.prettierignore +++ b/.prettierignore @@ -1,5 +1,7 @@ lib .nyc_output /packages/contracts/src/artifacts +/packages/metacoin/artifacts +/packages/migrations/src/artifacts package.json scripts/postpublish_utils.js @@ -14,7 +14,6 @@ This repository is a monorepo including the 0x protocol smart contracts and nume [![Discord](https://img.shields.io/badge/chat-rocket.chat-yellow.svg?style=flat)](https://chat.0xproject.com) [![Join the chat at https://gitter.im/0xProject/Lobby](https://badges.gitter.im/0xProject/Lobby.svg)](https://gitter.im/0xProject/Lobby?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge) [![License](https://img.shields.io/badge/License-Apache%202.0-blue.svg)](https://opensource.org/licenses/Apache-2.0) -[![Greenkeeper badge](https://badges.greenkeeper.io/0xProject/0x-monorepo.svg?token=7c22e5c72acf39d3ead8d29c5d9bb38f9096df3e643024dcedd53ab732847be1&ts=1496426342666)](https://greenkeeper.io/) ### Published Packages @@ -32,7 +31,7 @@ This repository is a monorepo including the 0x protocol smart contracts and nume | [`@0xproject/react-docs`](/packages/react-docs) | [![npm](https://img.shields.io/npm/v/@0xproject/react-docs.svg)](https://www.npmjs.com/package/@0xproject/react-docs) | React documentation component for rendering TypeDoc & Doxity generated JSON | | [`@0xproject/react-shared`](/packages/react-shared) | [![npm](https://img.shields.io/npm/v/@0xproject/react-shared.svg)](https://www.npmjs.com/package/@0xproject/react-shared) | 0x shared react components | | [`@0xproject/sra-report`](/packages/sra-report) | [![npm](https://img.shields.io/npm/v/@0xproject/sra-report.svg)](https://www.npmjs.com/package/@0xproject/sra-report) | Generate reports for standard relayer API compliance | -| [`@0xproject/sol-cov`](/packages/sol-cov) | [![npm](https://img.shields.io/npm/v/@0xproject/sol-cov.svg)](https://www.npmjs.com/package/@0xproject/sol-cov) | Solidity test coverage tool tool | +| [`@0xproject/sol-cov`](/packages/sol-cov) | [![npm](https://img.shields.io/npm/v/@0xproject/sol-cov.svg)](https://www.npmjs.com/package/@0xproject/sol-cov) | Solidity test coverage tool | | [`@0xproject/subproviders`](/packages/subproviders) | [![npm](https://img.shields.io/npm/v/@0xproject/subproviders.svg)](https://www.npmjs.com/package/@0xproject/subproviders) | Useful web3 subproviders (e.g LedgerSubprovider) | | [`@0xproject/tslint-config`](/packages/tslint-config) | [![npm](https://img.shields.io/npm/v/@0xproject/tslint-config.svg)](https://www.npmjs.com/package/@0xproject/tslint-config) | Custom 0x development TSLint rules | | [`@0xproject/types`](/packages/types) | [![npm](https://img.shields.io/npm/v/@0xproject/types.svg)](https://www.npmjs.com/package/@0xproject/types) | Shared type declarations | @@ -74,7 +73,7 @@ You can include those by prepending @0xproject/typescript-typings package to you We strongly recommend that the community help us make improvements and determine the future direction of the protocol. To report bugs within this package, please create an issue in this repository. -Please read our [contribution guidelines](./CONTRIBUTING.md) before getting started. +#### Read our [contribution guidelines](./CONTRIBUTING.md). ### Install dependencies @@ -118,24 +117,6 @@ yarn lerna:run lint ### Run Tests -Before running the tests, you will need to spin up a [TestRPC](https://www.npmjs.com/package/ethereumjs-testrpc) instance and deploy all the 0x smart contracts. - -In a separate terminal, start TestRPC (a convenience command is provided as part of this repo) - -```bash -yarn testrpc -``` - -Then in your main terminal run - -``` -cd packages/contracts -yarn migrate -cd .. -``` - -And finally from the root project directory run - ```bash -yarn lerna:run test +yarn lerna:test ``` diff --git a/package.json b/package.json index b3b3e3bcc..3f2486656 100644 --- a/package.json +++ b/package.json @@ -13,11 +13,13 @@ "test:installation": "node ./packages/monorepo-scripts/lib/test_installation.js", "lerna:install": "yarn install", "lerna:run": "lerna run", + "lerna:test": "lerna run test", "lerna:clean": "lerna run clean", "lerna:build": "lerna run build", "lerna:rebuild": "run-s lerna:clean lerna:build", "lerna:publish": "run-s lerna:install lerna:rebuild script:publish", "lerna:publish:dry": "run-s lerna:install lerna:rebuild script:publish:dry", + "lerna:stage_docs": "lerna run docs:stage", "script:publish": "node ./packages/monorepo-scripts/lib/publish.js", "script:publish:dry": "IS_DRY_RUN=true yarn script:publish" }, diff --git a/packages/0x.js/CHANGELOG.json b/packages/0x.js/CHANGELOG.json index 91bd75f65..65228b183 100644 --- a/packages/0x.js/CHANGELOG.json +++ b/packages/0x.js/CHANGELOG.json @@ -1,5 +1,13 @@ [ { + "version": "0.36.1", + "changes": [ + { + "note": "Internal changes and refactoring" + } + ] + }, + { "version": "0.36.0", "changes": [ { @@ -10,14 +18,15 @@ "note": "Add `zeroEx.exchange.getOrderStateAsync` to allow obtaining current OrderState for a signedOrder", "pr": 510 } - ] + ], + "timestamp": 1523462196 }, { "version": "0.35.0", "changes": [ { "note": - "Removed `ZeroExError.TransactionMiningTimeout` and moved it to '@0xproject/web3_wrapper' `Web3WrapperErrors.TransactionMiningTimeout`", + "Removed `ZeroExError.TransactionMiningTimeout` and moved it to '@0xproject/web3-wrapper' `Web3WrapperErrors.TransactionMiningTimeout`", "pr": 485 } ], diff --git a/packages/0x.js/CHANGELOG.md b/packages/0x.js/CHANGELOG.md index c18915417..693b4f4b2 100644 --- a/packages/0x.js/CHANGELOG.md +++ b/packages/0x.js/CHANGELOG.md @@ -5,6 +5,10 @@ Edit the package's CHANGELOG.json file only. CHANGELOG +## v0.36.0 - _April 11, 2018_ + + * Moved Web3.Provider to `@0xproject/types:Provider` (#501) + ## v0.35.0 - _April 2, 2018_ * Removed `ZeroExError.TransactionMiningTimeout` and moved it to '@0xproject/web3_wrapper' `Web3WrapperErrors.TransactionMiningTimeout` (#485) diff --git a/packages/0x.js/README.md b/packages/0x.js/README.md index 46848cbdd..72e5cc5fd 100644 --- a/packages/0x.js/README.md +++ b/packages/0x.js/README.md @@ -2,7 +2,7 @@ A TypeScript/Javascript library for interacting with the 0x protocol. -### Read the [Documentation](0xproject.com/docs/0xjs). +### Read the [Documentation](https://0xproject.com/docs/0x.js). ## Installation diff --git a/packages/0x.js/package.json b/packages/0x.js/package.json index 882b40733..37a321dbd 100644 --- a/packages/0x.js/package.json +++ b/packages/0x.js/package.json @@ -1,6 +1,6 @@ { "name": "0x.js", - "version": "0.35.0", + "version": "0.36.0", "description": "A javascript library for interacting with the 0x protocol", "keywords": [ "0x.js", @@ -15,16 +15,16 @@ "build:watch": "tsc -w", "prebuild": "run-s clean generate_contract_wrappers", "build": "run-p build:umd:prod build:commonjs; exit 0;", - "generate_contract_wrappers": "node ../abi-gen/lib/index.js --abis 'src/artifacts/@(Exchange|Token|TokenTransferProxy|EtherToken|TokenRegistry|DummyToken).json' --template ../contract_templates/contract.handlebars --partials '../contract_templates/partials/**/*.handlebars' --output src/contract_wrappers/generated --backend ethers && prettier --write 'src/contract_wrappers/generated/**.ts'", + "generate_contract_wrappers": "node ../abi-gen/lib/index.js --abis 'src/compact_artifacts/@(Exchange|Token|TokenTransferProxy|EtherToken|TokenRegistry|DummyToken).json' --template ../contract_templates/contract.handlebars --partials '../contract_templates/partials/**/*.handlebars' --output src/contract_wrappers/generated --backend ethers && prettier --write 'src/contract_wrappers/generated/**.ts'", "lint": "tslint --project . 'src/**/*.ts' 'test/**/*.ts'", "test:circleci": "run-s test:coverage", "test": "run-s clean test:commonjs", "test:coverage": "nyc npm run test --all && yarn coverage:report:lcov", "coverage:report:lcov": "nyc report --reporter=text-lcov > coverage/lcov.info", - "update_contracts": "for i in ${npm_package_config_artifacts}; do copyfiles -u 4 ../contracts/build/contracts/$i.json ../0x.js/src/artifacts; done;", + "update_artifacts": "for i in ${npm_package_config_contracts}; do copyfiles -u 4 ../migrations/src/artifacts/$i.json test/artifacts; done;", "clean": "shx rm -rf _bundles lib test_temp scripts", "build:umd:prod": "NODE_ENV=production webpack", - "build:commonjs": "tsc && copyfiles -u 2 './src/artifacts/**/*.json' ./lib/src/artifacts && copyfiles -u 3 './lib/src/monorepo_scripts/**/*' ./scripts", + "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", "manual:postpublish": "yarn build; node ./scripts/postpublish.js", @@ -33,7 +33,8 @@ "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": { - "artifacts": "TokenTransferProxy Exchange TokenRegistry Token EtherToken", + "compact_artifacts": "Exchange DummyToken ZRXToken Token EtherToken TokenTransferProxy TokenRegistry", + "contracts": "Exchange DummyToken ZRXToken Token WETH9 TokenTransferProxy MultiSigWallet MultiSigWalletWithTimeLock MultiSigWalletWithTimeLockExceptRemoveAuthorizedAddress MaliciousToken TokenRegistry Arbitrage EtherDelta AccountLevels", "postpublish": { "assets": [ "packages/0x.js/_bundles/index.js", @@ -60,9 +61,11 @@ "node": ">=6.0.0" }, "devDependencies": { - "@0xproject/dev-utils": "^0.3.4", - "@0xproject/monorepo-scripts": "^0.1.16", - "@0xproject/tslint-config": "^0.4.14", + "@0xproject/deployer": "^0.4.0", + "@0xproject/dev-utils": "^0.3.5", + "@0xproject/monorepo-scripts": "^0.1.17", + "@0xproject/subproviders": "^0.8.4", + "@0xproject/tslint-config": "^0.4.15", "@types/bintrees": "^1.0.2", "@types/lodash": "4.14.104", "@types/mocha": "^2.2.42", @@ -86,20 +89,20 @@ "shx": "^0.2.2", "sinon": "^4.0.0", "source-map-support": "^0.5.0", - "truffle-hdwallet-provider": "^0.0.3", "tslint": "5.8.0", "typedoc": "0xProject/typedoc", "typescript": "2.7.1", + "web3-provider-engine": "^13.0.1", "webpack": "^3.1.0" }, "dependencies": { - "@0xproject/assert": "^0.2.5", - "@0xproject/base-contract": "^0.1.0", - "@0xproject/json-schemas": "^0.7.19", - "@0xproject/types": "^0.5.0", - "@0xproject/typescript-typings": "^0.0.3", - "@0xproject/utils": "^0.5.0", - "@0xproject/web3-wrapper": "^0.5.0", + "@0xproject/assert": "^0.2.6", + "@0xproject/base-contract": "^0.2.0", + "@0xproject/json-schemas": "^0.7.20", + "@0xproject/types": "^0.6.0", + "@0xproject/typescript-typings": "^0.1.0", + "@0xproject/utils": "^0.5.1", + "@0xproject/web3-wrapper": "^0.6.0", "bintrees": "^1.0.2", "bn.js": "^4.11.8", "ethereumjs-abi": "^0.6.4", @@ -111,6 +114,9 @@ "uuid": "^3.1.0", "web3": "^0.20.0" }, + "optionalDependencies": { + "@0xproject/migrations": "^0.0.1" + }, "publishConfig": { "access": "public" } diff --git a/packages/0x.js/src/artifacts.ts b/packages/0x.js/src/artifacts.ts index cbacd7d56..a91d9ae1f 100644 --- a/packages/0x.js/src/artifacts.ts +++ b/packages/0x.js/src/artifacts.ts @@ -1,10 +1,10 @@ -import * as DummyTokenArtifact from './artifacts/DummyToken.json'; -import * as EtherTokenArtifact from './artifacts/EtherToken.json'; -import * as ExchangeArtifact from './artifacts/Exchange.json'; -import * as TokenArtifact from './artifacts/Token.json'; -import * as TokenRegistryArtifact from './artifacts/TokenRegistry.json'; -import * as TokenTransferProxyArtifact from './artifacts/TokenTransferProxy.json'; -import * as ZRXArtifact from './artifacts/ZRX.json'; +import * as DummyTokenArtifact from './compact_artifacts/DummyToken.json'; +import * as EtherTokenArtifact from './compact_artifacts/EtherToken.json'; +import * as ExchangeArtifact from './compact_artifacts/Exchange.json'; +import * as TokenArtifact from './compact_artifacts/Token.json'; +import * as TokenRegistryArtifact from './compact_artifacts/TokenRegistry.json'; +import * as TokenTransferProxyArtifact from './compact_artifacts/TokenTransferProxy.json'; +import * as ZRXArtifact from './compact_artifacts/ZRX.json'; import { Artifact } from './types'; export const artifacts = { diff --git a/packages/0x.js/src/artifacts/DummyToken.json b/packages/0x.js/src/compact_artifacts/DummyToken.json index f64a8cd3d..f64a8cd3d 100644 --- a/packages/0x.js/src/artifacts/DummyToken.json +++ b/packages/0x.js/src/compact_artifacts/DummyToken.json diff --git a/packages/0x.js/src/artifacts/EtherToken.json b/packages/0x.js/src/compact_artifacts/EtherToken.json index 26cca57cd..26cca57cd 100644 --- a/packages/0x.js/src/artifacts/EtherToken.json +++ b/packages/0x.js/src/compact_artifacts/EtherToken.json diff --git a/packages/0x.js/src/artifacts/Exchange.json b/packages/0x.js/src/compact_artifacts/Exchange.json index af8db7360..af8db7360 100644 --- a/packages/0x.js/src/artifacts/Exchange.json +++ b/packages/0x.js/src/compact_artifacts/Exchange.json diff --git a/packages/0x.js/src/artifacts/Token.json b/packages/0x.js/src/compact_artifacts/Token.json index 3b5a86ae0..3b5a86ae0 100644 --- a/packages/0x.js/src/artifacts/Token.json +++ b/packages/0x.js/src/compact_artifacts/Token.json diff --git a/packages/0x.js/src/artifacts/TokenRegistry.json b/packages/0x.js/src/compact_artifacts/TokenRegistry.json index 0f583628c..0f583628c 100644 --- a/packages/0x.js/src/artifacts/TokenRegistry.json +++ b/packages/0x.js/src/compact_artifacts/TokenRegistry.json diff --git a/packages/0x.js/src/artifacts/TokenTransferProxy.json b/packages/0x.js/src/compact_artifacts/TokenTransferProxy.json index 8cf551ddb..8cf551ddb 100644 --- a/packages/0x.js/src/artifacts/TokenTransferProxy.json +++ b/packages/0x.js/src/compact_artifacts/TokenTransferProxy.json diff --git a/packages/0x.js/src/artifacts/ZRX.json b/packages/0x.js/src/compact_artifacts/ZRX.json index e40b8f268..e40b8f268 100644 --- a/packages/0x.js/src/artifacts/ZRX.json +++ b/packages/0x.js/src/compact_artifacts/ZRX.json diff --git a/packages/0x.js/test/0x.js_test.ts b/packages/0x.js/test/0x.js_test.ts index 70e85aa52..de5a6be58 100644 --- a/packages/0x.js/test/0x.js_test.ts +++ b/packages/0x.js/test/0x.js_test.ts @@ -1,16 +1,23 @@ +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'; import 'mocha'; +import * as path from 'path'; import * as Sinon from 'sinon'; import { ApprovalContractEventArgs, LogWithDecodedArgs, Order, TokenEvents, ZeroEx } from '../src'; import { chaiSetup } from './utils/chai_setup'; import { constants } from './utils/constants'; +import { deployer } from './utils/deployer'; import { TokenUtils } from './utils/token_utils'; -import { web3, web3Wrapper } from './utils/web3_wrapper'; +import { provider, web3Wrapper } from './utils/web3_wrapper'; const blockchainLifecycle = new BlockchainLifecycle(web3Wrapper); chaiSetup.configure(); @@ -19,10 +26,14 @@ const expect = chai.expect; const SHOULD_ADD_PERSONAL_MESSAGE_PREFIX = false; describe('ZeroEx library', () => { - const config = { - networkId: constants.TESTRPC_NETWORK_ID, - }; - const zeroEx = new ZeroEx(web3.currentProvider, config); + let zeroEx: ZeroEx; + before(async () => { + await runMigrationsAsync(deployer); + const config = { + networkId: constants.TESTRPC_NETWORK_ID, + }; + zeroEx = new ZeroEx(provider, config); + }); describe('#setProvider', () => { it('overrides provider in nested web3s and invalidates contractInstances', async () => { // Instantiate the contract instances with the current provider @@ -31,10 +42,9 @@ describe('ZeroEx library', () => { expect((zeroEx.exchange as any)._exchangeContractIfExists).to.not.be.undefined(); expect((zeroEx.tokenRegistry as any)._tokenRegistryContractIfExists).to.not.be.undefined(); - const newProvider = web3Factory.getRpcProvider(); // Add property to newProvider so that we can differentiate it from old provider - (newProvider as any).zeroExTestId = 1; - zeroEx.setProvider(newProvider, constants.TESTRPC_NETWORK_ID); + (provider as any).zeroExTestId = 1; + zeroEx.setProvider(provider, constants.TESTRPC_NETWORK_ID); // Check that contractInstances with old provider are removed after provider update expect((zeroEx.exchange as any)._exchangeContractIfExists).to.be.undefined(); @@ -278,7 +288,7 @@ describe('ZeroEx library', () => { exchangeContractAddress: ZeroEx.NULL_ADDRESS, networkId: constants.TESTRPC_NETWORK_ID, }; - const zeroExWithWrongExchangeAddress = new ZeroEx(web3.currentProvider, zeroExConfig); + const zeroExWithWrongExchangeAddress = new ZeroEx(provider, zeroExConfig); expect(zeroExWithWrongExchangeAddress.exchange.getContractAddress()).to.be.equal(ZeroEx.NULL_ADDRESS); }); it('allows to specify token registry token contract address', async () => { @@ -286,7 +296,7 @@ describe('ZeroEx library', () => { tokenRegistryContractAddress: ZeroEx.NULL_ADDRESS, networkId: constants.TESTRPC_NETWORK_ID, }; - const zeroExWithWrongTokenRegistryAddress = new ZeroEx(web3.currentProvider, zeroExConfig); + const zeroExWithWrongTokenRegistryAddress = new ZeroEx(provider, zeroExConfig); expect(zeroExWithWrongTokenRegistryAddress.tokenRegistry.getContractAddress()).to.be.equal( ZeroEx.NULL_ADDRESS, ); diff --git a/packages/0x.js/test/artifacts_test.ts b/packages/0x.js/test/artifacts_test.ts index e8ab9aa97..40c5983bd 100644 --- a/packages/0x.js/test/artifacts_test.ts +++ b/packages/0x.js/test/artifacts_test.ts @@ -1,5 +1,5 @@ +import { web3Factory } from '@0xproject/dev-utils'; import * as fs from 'fs'; -import HDWalletProvider = require('truffle-hdwallet-provider'); import { ZeroEx } from '../src'; @@ -14,14 +14,11 @@ const TIMEOUT = 10000; describe('Artifacts', () => { describe('contracts are deployed on kovan', () => { const kovanRpcUrl = constants.KOVAN_RPC_URL; - const packageJSONContent = fs.readFileSync('package.json', 'utf-8'); - const packageJSON = JSON.parse(packageJSONContent); - const mnemonic = packageJSON.config.mnemonic; - const web3Provider = new HDWalletProvider(mnemonic, kovanRpcUrl); + const provider = web3Factory.create({ rpcUrl: kovanRpcUrl }).currentProvider; const config = { networkId: constants.KOVAN_NETWORK_ID, }; - const zeroEx = new ZeroEx(web3Provider, config); + const zeroEx = new ZeroEx(provider, config); it('token registry contract is deployed', async () => { await (zeroEx.tokenRegistry as any)._getTokenRegistryContractAsync(); }).timeout(TIMEOUT); @@ -34,14 +31,11 @@ describe('Artifacts', () => { }); describe('contracts are deployed on ropsten', () => { const ropstenRpcUrl = constants.ROPSTEN_RPC_URL; - const packageJSONContent = fs.readFileSync('package.json', 'utf-8'); - const packageJSON = JSON.parse(packageJSONContent); - const mnemonic = packageJSON.config.mnemonic; - const web3Provider = new HDWalletProvider(mnemonic, ropstenRpcUrl); + const provider = web3Factory.create({ rpcUrl: ropstenRpcUrl }).currentProvider; const config = { networkId: constants.ROPSTEN_NETWORK_ID, }; - const zeroEx = new ZeroEx(web3Provider, config); + const zeroEx = new ZeroEx(provider, config); it('token registry contract is deployed', async () => { await (zeroEx.tokenRegistry as any)._getTokenRegistryContractAsync(); }).timeout(TIMEOUT); diff --git a/packages/0x.js/test/assert_test.ts b/packages/0x.js/test/assert_test.ts index c4451742f..b08f3e23b 100644 --- a/packages/0x.js/test/assert_test.ts +++ b/packages/0x.js/test/assert_test.ts @@ -6,15 +6,15 @@ 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 web3 = web3Factory.create(); const config = { networkId: constants.TESTRPC_NETWORK_ID, }; - const zeroEx = new ZeroEx(web3.currentProvider, config); + const zeroEx = new ZeroEx(provider, config); describe('#isSenderAddressHexAsync', () => { it('throws when address is invalid', async () => { const address = '0xdeadbeef'; diff --git a/packages/0x.js/test/ether_token_wrapper_test.ts b/packages/0x.js/test/ether_token_wrapper_test.ts index 644101dc7..99c42fe0b 100644 --- a/packages/0x.js/test/ether_token_wrapper_test.ts +++ b/packages/0x.js/test/ether_token_wrapper_test.ts @@ -3,7 +3,6 @@ import { BigNumber } from '@0xproject/utils'; import { Web3Wrapper } from '@0xproject/web3-wrapper'; import * as chai from 'chai'; import 'mocha'; -import * as Web3 from 'web3'; import { ApprovalContractEventArgs, @@ -24,7 +23,7 @@ import { chaiSetup } from './utils/chai_setup'; import { constants } from './utils/constants'; import { reportNodeCallbackErrors } from './utils/report_callback_errors'; import { TokenUtils } from './utils/token_utils'; -import { web3, web3Wrapper } from './utils/web3_wrapper'; +import { provider, web3Wrapper } from './utils/web3_wrapper'; chaiSetup.configure(); const expect = chai.expect; @@ -55,7 +54,7 @@ describe('EtherTokenWrapper', () => { const depositAmount = new BigNumber(42); const withdrawalAmount = new BigNumber(42); before(async () => { - zeroEx = new ZeroEx(web3.currentProvider, zeroExConfig); + zeroEx = new ZeroEx(provider, zeroExConfig); tokens = await zeroEx.tokenRegistry.getTokensAsync(); userAddresses = await zeroEx.getAvailableAddressesAsync(); addressWithETH = userAddresses[0]; @@ -79,7 +78,7 @@ describe('EtherTokenWrapper', () => { const UNKNOWN_NETWORK_NETWORK_ID = 10; expect( () => - new ZeroEx(web3.currentProvider, { + new ZeroEx(provider, { networkId: UNKNOWN_NETWORK_NETWORK_ID, } as any), ).to.throw(); @@ -261,8 +260,7 @@ describe('EtherTokenWrapper', () => { callbackNeverToBeCalled, ); const callbackToBeCalled = reportNodeCallbackErrors(done)(); - const newProvider = web3Factory.getRpcProvider(); - zeroEx.setProvider(newProvider, constants.TESTRPC_NETWORK_ID); + zeroEx.setProvider(provider, constants.TESTRPC_NETWORK_ID); await zeroEx.etherToken.depositAsync(etherTokenAddress, transferAmount, addressWithETH); zeroEx.etherToken.subscribe( etherTokenAddress, diff --git a/packages/0x.js/test/event_watcher_test.ts b/packages/0x.js/test/event_watcher_test.ts index 2fa6c0580..40ffcc2f6 100644 --- a/packages/0x.js/test/event_watcher_test.ts +++ b/packages/0x.js/test/event_watcher_test.ts @@ -5,7 +5,6 @@ import * as chai from 'chai'; import * as _ from 'lodash'; import 'mocha'; import * as Sinon from 'sinon'; -import * as Web3 from 'web3'; import { LogEvent } from '../src'; import { EventWatcher } from '../src/order_watcher/event_watcher'; @@ -13,12 +12,12 @@ import { DoneCallback } from '../src/types'; import { chaiSetup } from './utils/chai_setup'; import { reportNodeCallbackErrors } from './utils/report_callback_errors'; +import { provider } from './utils/web3_wrapper'; chaiSetup.configure(); const expect = chai.expect; describe('EventWatcher', () => { - let web3: Web3; let stubs: Sinon.SinonStub[] = []; let eventWatcher: EventWatcher; let web3Wrapper: Web3Wrapper; @@ -53,9 +52,8 @@ describe('EventWatcher', () => { transactionIndex: 0, }; before(async () => { - web3 = web3Factory.create(); const pollingIntervalMs = 10; - web3Wrapper = new Web3Wrapper(web3.currentProvider); + web3Wrapper = new Web3Wrapper(provider); eventWatcher = new EventWatcher(web3Wrapper, pollingIntervalMs); }); afterEach(() => { diff --git a/packages/0x.js/test/exchange_transfer_simulator_test.ts b/packages/0x.js/test/exchange_transfer_simulator_test.ts index 4447a61cb..cb976a0ae 100644 --- a/packages/0x.js/test/exchange_transfer_simulator_test.ts +++ b/packages/0x.js/test/exchange_transfer_simulator_test.ts @@ -9,7 +9,7 @@ import { ExchangeTransferSimulator } from '../src/utils/exchange_transfer_simula import { chaiSetup } from './utils/chai_setup'; import { constants } from './utils/constants'; -import { web3, web3Wrapper } from './utils/web3_wrapper'; +import { provider, web3Wrapper } from './utils/web3_wrapper'; chaiSetup.configure(); const expect = chai.expect; @@ -19,7 +19,7 @@ describe('ExchangeTransferSimulator', () => { const config = { networkId: constants.TESTRPC_NETWORK_ID, }; - const zeroEx = new ZeroEx(web3.currentProvider, config); + const zeroEx = new ZeroEx(provider, config); const transferAmount = new BigNumber(5); let userAddresses: string[]; let tokens: Token[]; diff --git a/packages/0x.js/test/exchange_wrapper_test.ts b/packages/0x.js/test/exchange_wrapper_test.ts index dd55d06a2..65f4e8251 100644 --- a/packages/0x.js/test/exchange_wrapper_test.ts +++ b/packages/0x.js/test/exchange_wrapper_test.ts @@ -4,7 +4,6 @@ import { BigNumber } from '@0xproject/utils'; import * as chai from 'chai'; import * as _ from 'lodash'; import 'mocha'; -import * as Web3 from 'web3'; import { BlockRange, @@ -27,7 +26,7 @@ import { constants } from './utils/constants'; import { FillScenarios } from './utils/fill_scenarios'; import { reportNodeCallbackErrors } from './utils/report_callback_errors'; import { TokenUtils } from './utils/token_utils'; -import { web3, web3Wrapper } from './utils/web3_wrapper'; +import { provider, web3Wrapper } from './utils/web3_wrapper'; chaiSetup.configure(); const expect = chai.expect; @@ -47,7 +46,7 @@ describe('ExchangeWrapper', () => { networkId: constants.TESTRPC_NETWORK_ID, }; before(async () => { - zeroEx = new ZeroEx(web3.currentProvider, config); + zeroEx = new ZeroEx(provider, config); exchangeContractAddress = zeroEx.exchange.getContractAddress(); userAddresses = await zeroEx.getAvailableAddressesAsync(); tokens = await zeroEx.tokenRegistry.getTokensAsync(); @@ -978,8 +977,7 @@ describe('ExchangeWrapper', () => { ); zeroEx.exchange.subscribe(ExchangeEvents.LogFill, indexFilterValues, callbackNeverToBeCalled); - const newProvider = web3Factory.getRpcProvider(); - zeroEx.setProvider(newProvider, constants.TESTRPC_NETWORK_ID); + zeroEx.setProvider(provider, constants.TESTRPC_NETWORK_ID); const callback = reportNodeCallbackErrors(done)( (logEvent: DecodedLogEvent<LogFillContractEventArgs>) => { diff --git a/packages/0x.js/test/expiration_watcher_test.ts b/packages/0x.js/test/expiration_watcher_test.ts index ed7a6e5e3..29b111fa3 100644 --- a/packages/0x.js/test/expiration_watcher_test.ts +++ b/packages/0x.js/test/expiration_watcher_test.ts @@ -4,7 +4,6 @@ import * as chai from 'chai'; import * as _ from 'lodash'; import 'mocha'; import * as Sinon from 'sinon'; -import * as Web3 from 'web3'; import { ZeroEx } from '../src/0x'; import { ExpirationWatcher } from '../src/order_watcher/expiration_watcher'; @@ -16,7 +15,7 @@ import { constants } from './utils/constants'; import { FillScenarios } from './utils/fill_scenarios'; import { reportNoErrorCallbackErrors } from './utils/report_callback_errors'; import { TokenUtils } from './utils/token_utils'; -import { web3, web3Wrapper } from './utils/web3_wrapper'; +import { provider, web3Wrapper } from './utils/web3_wrapper'; chaiSetup.configure(); const expect = chai.expect; @@ -44,7 +43,7 @@ describe('ExpirationWatcher', () => { const config = { networkId: constants.TESTRPC_NETWORK_ID, }; - zeroEx = new ZeroEx(web3.currentProvider, config); + zeroEx = new ZeroEx(provider, config); exchangeContractAddress = zeroEx.exchange.getContractAddress(); userAddresses = await zeroEx.getAvailableAddressesAsync(); tokens = await zeroEx.tokenRegistry.getTokensAsync(); diff --git a/packages/0x.js/test/order_state_watcher_test.ts b/packages/0x.js/test/order_state_watcher_test.ts index 4210e013f..45a292c8b 100644 --- a/packages/0x.js/test/order_state_watcher_test.ts +++ b/packages/0x.js/test/order_state_watcher_test.ts @@ -3,7 +3,6 @@ import { BigNumber } from '@0xproject/utils'; import * as chai from 'chai'; import * as _ from 'lodash'; import 'mocha'; -import * as Web3 from 'web3'; import { ExchangeContractErrs, @@ -23,7 +22,7 @@ import { constants } from './utils/constants'; import { FillScenarios } from './utils/fill_scenarios'; import { reportNodeCallbackErrors } from './utils/report_callback_errors'; import { TokenUtils } from './utils/token_utils'; -import { web3, web3Wrapper } from './utils/web3_wrapper'; +import { provider, web3Wrapper } from './utils/web3_wrapper'; const TIMEOUT_MS = 150; @@ -51,7 +50,7 @@ describe('OrderStateWatcher', () => { const decimals = constants.ZRX_DECIMALS; const fillableAmount = ZeroEx.toBaseUnitAmount(new BigNumber(5), decimals); before(async () => { - zeroEx = new ZeroEx(web3.currentProvider, config); + zeroEx = new ZeroEx(provider, config); orderStateWatcher = zeroEx.createOrderStateWatcher(); exchangeContractAddress = zeroEx.exchange.getContractAddress(); userAddresses = await zeroEx.getAvailableAddressesAsync(); diff --git a/packages/0x.js/test/order_validation_test.ts b/packages/0x.js/test/order_validation_test.ts index 5472ca8f6..c894774b8 100644 --- a/packages/0x.js/test/order_validation_test.ts +++ b/packages/0x.js/test/order_validation_test.ts @@ -3,7 +3,6 @@ import { BlockParamLiteral } from '@0xproject/types'; import { BigNumber } from '@0xproject/utils'; import * as chai from 'chai'; import * as Sinon from 'sinon'; -import * as Web3 from 'web3'; import { ExchangeContractErrs, SignedOrder, Token, ZeroEx, ZeroExError } from '../src'; import { TradeSide, TransferType } from '../src/types'; @@ -14,7 +13,7 @@ import { chaiSetup } from './utils/chai_setup'; import { constants } from './utils/constants'; import { FillScenarios } from './utils/fill_scenarios'; import { TokenUtils } from './utils/token_utils'; -import { web3, web3Wrapper } from './utils/web3_wrapper'; +import { provider, web3Wrapper } from './utils/web3_wrapper'; chaiSetup.configure(); const expect = chai.expect; @@ -40,7 +39,7 @@ describe('OrderValidation', () => { networkId: constants.TESTRPC_NETWORK_ID, }; before(async () => { - zeroEx = new ZeroEx(web3.currentProvider, config); + zeroEx = new ZeroEx(provider, config); exchangeContractAddress = zeroEx.exchange.getContractAddress(); userAddresses = await zeroEx.getAvailableAddressesAsync(); [coinbase, makerAddress, takerAddress, feeRecipient] = userAddresses; diff --git a/packages/0x.js/test/subscription_test.ts b/packages/0x.js/test/subscription_test.ts index 9b4751287..ed4f838c0 100644 --- a/packages/0x.js/test/subscription_test.ts +++ b/packages/0x.js/test/subscription_test.ts @@ -3,7 +3,6 @@ import { BigNumber } from '@0xproject/utils'; import * as _ from 'lodash'; import 'mocha'; import * as Sinon from 'sinon'; -import * as Web3 from 'web3'; import { ApprovalContractEventArgs, DecodedLogEvent, Token, TokenEvents, ZeroEx } from '../src'; import { DoneCallback } from '../src/types'; @@ -11,7 +10,7 @@ import { DoneCallback } from '../src/types'; import { chaiSetup } from './utils/chai_setup'; import { constants } from './utils/constants'; import { assertNodeCallbackError } from './utils/report_callback_errors'; -import { web3, web3Wrapper } from './utils/web3_wrapper'; +import { provider, web3Wrapper } from './utils/web3_wrapper'; chaiSetup.configure(); const blockchainLifecycle = new BlockchainLifecycle(web3Wrapper); @@ -26,7 +25,7 @@ describe('SubscriptionTest', () => { networkId: constants.TESTRPC_NETWORK_ID, }; before(async () => { - zeroEx = new ZeroEx(web3.currentProvider, config); + zeroEx = new ZeroEx(provider, config); userAddresses = await zeroEx.getAvailableAddressesAsync(); tokens = await zeroEx.tokenRegistry.getTokensAsync(); coinbase = userAddresses[0]; diff --git a/packages/0x.js/test/token_registry_wrapper_test.ts b/packages/0x.js/test/token_registry_wrapper_test.ts index 3b7ce46fb..19caa2ed4 100644 --- a/packages/0x.js/test/token_registry_wrapper_test.ts +++ b/packages/0x.js/test/token_registry_wrapper_test.ts @@ -8,7 +8,7 @@ import { Token, ZeroEx } from '../src'; import { chaiSetup } from './utils/chai_setup'; import { constants } from './utils/constants'; -import { web3, web3Wrapper } from './utils/web3_wrapper'; +import { provider, web3Wrapper } from './utils/web3_wrapper'; chaiSetup.configure(); const expect = chai.expect; @@ -31,7 +31,7 @@ describe('TokenRegistryWrapper', () => { networkId: constants.TESTRPC_NETWORK_ID, }; before(async () => { - zeroEx = new ZeroEx(web3.currentProvider, config); + zeroEx = new ZeroEx(provider, config); tokens = await zeroEx.tokenRegistry.getTokensAsync(); _.map(tokens, token => { tokenAddressBySymbol[token.symbol] = token.address; diff --git a/packages/0x.js/test/token_transfer_proxy_wrapper_test.ts b/packages/0x.js/test/token_transfer_proxy_wrapper_test.ts index fb003634a..9415d7c08 100644 --- a/packages/0x.js/test/token_transfer_proxy_wrapper_test.ts +++ b/packages/0x.js/test/token_transfer_proxy_wrapper_test.ts @@ -1,14 +1,13 @@ -import { web3Factory } from '@0xproject/dev-utils'; import * as chai from 'chai'; import { ZeroEx } from '../src'; import { chaiSetup } from './utils/chai_setup'; import { constants } from './utils/constants'; +import { provider } from './utils/web3_wrapper'; chaiSetup.configure(); const expect = chai.expect; -const web3 = web3Factory.create(); describe('TokenTransferProxyWrapper', () => { let zeroEx: ZeroEx; @@ -16,7 +15,7 @@ describe('TokenTransferProxyWrapper', () => { networkId: constants.TESTRPC_NETWORK_ID, }; before(async () => { - zeroEx = new ZeroEx(web3.currentProvider, config); + zeroEx = new ZeroEx(provider, config); }); describe('#isAuthorizedAsync', () => { it('should return false if the address is not authorized', async () => { diff --git a/packages/0x.js/test/token_wrapper_test.ts b/packages/0x.js/test/token_wrapper_test.ts index 0c6335d5e..04fd943aa 100644 --- a/packages/0x.js/test/token_wrapper_test.ts +++ b/packages/0x.js/test/token_wrapper_test.ts @@ -1,9 +1,10 @@ -import { BlockchainLifecycle, devConstants, web3Factory } from '@0xproject/dev-utils'; +import { BlockchainLifecycle, devConstants } from '@0xproject/dev-utils'; +import { EmptyWalletSubprovider } from '@0xproject/subproviders'; +import { Provider } from '@0xproject/types'; import { BigNumber } from '@0xproject/utils'; -import { Web3Wrapper } from '@0xproject/web3-wrapper'; import * as chai from 'chai'; import 'mocha'; -import * as Web3 from 'web3'; +import Web3ProviderEngine = require('web3-provider-engine'); import { ApprovalContractEventArgs, @@ -22,7 +23,7 @@ import { chaiSetup } from './utils/chai_setup'; import { constants } from './utils/constants'; import { reportNodeCallbackErrors } from './utils/report_callback_errors'; import { TokenUtils } from './utils/token_utils'; -import { web3, web3Wrapper } from './utils/web3_wrapper'; +import { provider, web3Wrapper } from './utils/web3_wrapper'; chaiSetup.configure(); const expect = chai.expect; @@ -39,7 +40,7 @@ describe('TokenWrapper', () => { networkId: constants.TESTRPC_NETWORK_ID, }; before(async () => { - zeroEx = new ZeroEx(web3.currentProvider, config); + zeroEx = new ZeroEx(provider, config); userAddresses = await zeroEx.getAvailableAddressesAsync(); tokens = await zeroEx.tokenRegistry.getTokensAsync(); tokenUtils = new TokenUtils(tokens); @@ -164,7 +165,7 @@ describe('TokenWrapper', () => { }); }); describe('#getBalanceAsync', () => { - describe('With web3 provider with accounts', () => { + describe('With provider with accounts', () => { it('should return the balance for an existing ERC20 token', async () => { const token = tokens[0]; const ownerAddress = coinbase; @@ -187,14 +188,14 @@ describe('TokenWrapper', () => { return expect(balance).to.be.bignumber.equal(expectedBalance); }); }); - describe('With web3 provider without accounts', () => { + describe('With provider without accounts', () => { let zeroExWithoutAccounts: ZeroEx; before(async () => { const hasAddresses = false; - const web3WithoutAccounts = web3Factory.create({ hasAddresses }); - zeroExWithoutAccounts = new ZeroEx(web3WithoutAccounts.currentProvider, config); + const emptyWalletProvider = addEmptyWalletSubprovider(provider); + zeroExWithoutAccounts = new ZeroEx(emptyWalletProvider, config); }); - it('should return balance even when called with Web3 provider instance without addresses', async () => { + it('should return balance even when called with provider instance without addresses', async () => { const token = tokens[0]; const ownerAddress = coinbase; const balance = await zeroExWithoutAccounts.token.getBalanceAsync(token.address, ownerAddress); @@ -277,7 +278,7 @@ describe('TokenWrapper', () => { }); }); describe('#getAllowanceAsync', () => { - describe('With web3 provider with accounts', () => { + describe('With provider with accounts', () => { it('should get the proxy allowance', async () => { const token = tokens[0]; const ownerAddress = coinbase; @@ -299,12 +300,12 @@ describe('TokenWrapper', () => { return expect(allowance).to.be.bignumber.equal(expectedAllowance); }); }); - describe('With web3 provider without accounts', () => { + describe('With provider without accounts', () => { let zeroExWithoutAccounts: ZeroEx; before(async () => { const hasAddresses = false; - const web3WithoutAccounts = web3Factory.create({ hasAddresses }); - zeroExWithoutAccounts = new ZeroEx(web3WithoutAccounts.currentProvider, config); + const emptyWalletProvider = addEmptyWalletSubprovider(provider); + zeroExWithoutAccounts = new ZeroEx(emptyWalletProvider, config); }); it('should get the proxy allowance', async () => { const token = tokens[0]; @@ -424,8 +425,7 @@ describe('TokenWrapper', () => { ); zeroEx.token.subscribe(tokenAddress, TokenEvents.Transfer, indexFilterValues, callbackNeverToBeCalled); const callbackToBeCalled = reportNodeCallbackErrors(done)(); - const newProvider = web3Factory.getRpcProvider(); - zeroEx.setProvider(newProvider, constants.TESTRPC_NETWORK_ID); + zeroEx.setProvider(provider, constants.TESTRPC_NETWORK_ID); zeroEx.token.subscribe(tokenAddress, TokenEvents.Transfer, indexFilterValues, callbackToBeCalled); await zeroEx.token.transferAsync(tokenAddress, coinbase, addressWithoutFunds, transferAmount); })().catch(done); @@ -515,3 +515,14 @@ describe('TokenWrapper', () => { }); }); // tslint:disable:max-file-line-count + +function addEmptyWalletSubprovider(p: Provider): Provider { + const providerEngine = new Web3ProviderEngine(); + providerEngine.addProvider(new EmptyWalletSubprovider()); + const currentSubproviders = (p as any)._providers; + for (const subprovider of currentSubproviders) { + providerEngine.addProvider(subprovider); + } + providerEngine.start(); + return providerEngine; +} diff --git a/packages/contracts/migrations/index.ts b/packages/0x.js/test/utils/deployer.ts index 47ae7044d..b092322e2 100644 --- a/packages/contracts/migrations/index.ts +++ b/packages/0x.js/test/utils/deployer.ts @@ -2,19 +2,17 @@ import { Deployer } from '@0xproject/deployer'; import { devConstants } from '@0xproject/dev-utils'; import * as path from 'path'; -import { constants } from '../util/constants'; +import { constants } from './constants'; -import { runMigrationsAsync } from './migrate'; +import { provider } from './web3_wrapper'; +const artifactsDir = path.resolve('test', 'artifacts'); const deployerOpts = { - artifactsDir: path.resolve('src', 'artifacts'), - jsonrpcUrl: devConstants.RPC_URL, + artifactsDir, + provider, networkId: constants.TESTRPC_NETWORK_ID, defaults: { gas: devConstants.GAS_ESTIMATE, }, }; - export const deployer = new Deployer(deployerOpts); - -runMigrationsAsync(deployer).catch(console.log); diff --git a/packages/0x.js/test/utils/web3_wrapper.ts b/packages/0x.js/test/utils/web3_wrapper.ts index 4b374fc7e..b7b3f0b7f 100644 --- a/packages/0x.js/test/utils/web3_wrapper.ts +++ b/packages/0x.js/test/utils/web3_wrapper.ts @@ -1,6 +1,12 @@ -import { web3Factory } from '@0xproject/dev-utils'; +import { devConstants, web3Factory } from '@0xproject/dev-utils'; +import { Provider } from '@0xproject/types'; import { Web3Wrapper } from '@0xproject/web3-wrapper'; import * as Web3 from 'web3'; -export const web3 = web3Factory.create(); -export const web3Wrapper = new Web3Wrapper(web3.currentProvider); +import { constants } from './constants'; + +const web3 = web3Factory.create({ shouldUseInProcessGanache: true }); +const provider: Provider = web3.currentProvider; +const web3Wrapper = new Web3Wrapper(web3.currentProvider); + +export { provider, web3Wrapper }; diff --git a/packages/abi-gen/CHANGELOG.json b/packages/abi-gen/CHANGELOG.json index e720cc04b..84f3e318c 100644 --- a/packages/abi-gen/CHANGELOG.json +++ b/packages/abi-gen/CHANGELOG.json @@ -1,5 +1,14 @@ [ { + "timestamp": 1523462196, + "version": "0.2.10", + "changes": [ + { + "note": "Dependencies updated" + } + ] + }, + { "timestamp": 1522673609, "version": "0.2.9", "changes": [ diff --git a/packages/abi-gen/CHANGELOG.md b/packages/abi-gen/CHANGELOG.md index 4b8158ebf..5b3b68af3 100644 --- a/packages/abi-gen/CHANGELOG.md +++ b/packages/abi-gen/CHANGELOG.md @@ -5,6 +5,10 @@ Edit the package's CHANGELOG.json file only. CHANGELOG +## v0.2.10 - _April 11, 2018_ + + * Dependencies updated + ## v0.2.9 - _April 2, 2018_ * Dependencies updated diff --git a/packages/abi-gen/package.json b/packages/abi-gen/package.json index f6252e5ef..6aabb054a 100644 --- a/packages/abi-gen/package.json +++ b/packages/abi-gen/package.json @@ -1,6 +1,6 @@ { "name": "@0xproject/abi-gen", - "version": "0.2.9", + "version": "0.2.10", "description": "Generate contract wrappers from ABI and handlebars templates", "main": "lib/index.js", "types": "lib/index.d.ts", @@ -24,9 +24,9 @@ }, "homepage": "https://github.com/0xProject/0x-monorepo/packages/abi-gen/README.md", "dependencies": { - "@0xproject/types": "^0.5.0", - "@0xproject/typescript-typings": "^0.0.3", - "@0xproject/utils": "^0.5.0", + "@0xproject/types": "^0.6.0", + "@0xproject/typescript-typings": "^0.1.0", + "@0xproject/utils": "^0.5.1", "chalk": "^2.3.0", "glob": "^7.1.2", "handlebars": "^4.0.11", @@ -36,8 +36,8 @@ "yargs": "^10.0.3" }, "devDependencies": { - "@0xproject/monorepo-scripts": "^0.1.16", - "@0xproject/tslint-config": "^0.4.14", + "@0xproject/monorepo-scripts": "^0.1.17", + "@0xproject/tslint-config": "^0.4.15", "@types/glob": "^5.0.33", "@types/handlebars": "^4.0.36", "@types/mkdirp": "^0.5.1", diff --git a/packages/abi-gen/src/index.ts b/packages/abi-gen/src/index.ts index 942bb12db..ecef33b16 100644 --- a/packages/abi-gen/src/index.ts +++ b/packages/abi-gen/src/index.ts @@ -1,7 +1,7 @@ #!/usr/bin/env node import { AbiDefinition, ConstructorAbi, EventAbi, MethodAbi } from '@0xproject/types'; -import { logUtils } from '@0xproject/utils'; +import { abiUtils, logUtils } from '@0xproject/utils'; import chalk from 'chalk'; import * as fs from 'fs'; import { sync as globSync } from 'glob'; @@ -12,7 +12,7 @@ import * as yargs from 'yargs'; import toSnakeCase = require('to-snake-case'); -import { ContextData, ContractsBackend, ParamKind } from './types'; +import { ContextData, ContractsBackend, Method, ParamKind } from './types'; import { utils } from './utils'; const ABI_TYPE_CONSTRUCTOR = 'constructor'; @@ -83,7 +83,6 @@ function writeOutputFile(name: string, renderedTsCode: string): void { Handlebars.registerHelper('parameterType', utils.solTypeToTsType.bind(utils, ParamKind.Input, args.backend)); Handlebars.registerHelper('returnType', utils.solTypeToTsType.bind(utils, ParamKind.Output, args.backend)); - if (args.partials) { registerPartials(args.partials); } @@ -126,11 +125,12 @@ for (const abiFileName of abiFileNames) { } const methodAbis = ABI.filter((abi: AbiDefinition) => abi.type === ABI_TYPE_METHOD) as MethodAbi[]; - const methodsData = _.map(methodAbis, methodAbi => { - _.map(methodAbi.inputs, (input, i: number) => { + const sanitizedMethodAbis = abiUtils.renameOverloadedMethods(methodAbis) as MethodAbi[]; + const methodsData = _.map(methodAbis, (methodAbi, methodAbiIndex: number) => { + _.forEach(methodAbi.inputs, (input, inputIndex: number) => { if (_.isEmpty(input.name)) { // Auto-generated getters don't have parameter names - input.name = `index_${i}`; + input.name = `index_${inputIndex}`; } }); // This will make templates simpler @@ -138,6 +138,8 @@ for (const abiFileName of abiFileNames) { ...methodAbi, singleReturnValue: methodAbi.outputs.length === 1, hasReturnValue: methodAbi.outputs.length !== 0, + tsName: sanitizedMethodAbis[methodAbiIndex].name, + functionSignature: abiUtils.getFunctionSignature(methodAbi), }; return methodData; }); diff --git a/packages/abi-gen/src/types.ts b/packages/abi-gen/src/types.ts index df5b1feaf..648281774 100644 --- a/packages/abi-gen/src/types.ts +++ b/packages/abi-gen/src/types.ts @@ -5,13 +5,6 @@ export enum ParamKind { Output = 'output', } -export enum AbiType { - Function = 'function', - Constructor = 'constructor', - Event = 'event', - Fallback = 'fallback', -} - export enum ContractsBackend { Web3 = 'web3', Ethers = 'ethers', @@ -20,6 +13,8 @@ export enum ContractsBackend { export interface Method extends MethodAbi { singleReturnValue: boolean; hasReturnValue: boolean; + tsName: string; + functionSignature: string; } export interface ContextData { diff --git a/packages/abi-gen/src/utils.ts b/packages/abi-gen/src/utils.ts index 755fbc71a..20b734959 100644 --- a/packages/abi-gen/src/utils.ts +++ b/packages/abi-gen/src/utils.ts @@ -1,9 +1,9 @@ -import { ConstructorAbi, DataItem } from '@0xproject/types'; +import { AbiType, ConstructorAbi, DataItem } from '@0xproject/types'; import * as fs from 'fs'; import * as _ from 'lodash'; import * as path from 'path'; -import { AbiType, ContractsBackend, ParamKind } from './types'; +import { ContractsBackend, ParamKind } from './types'; export const utils = { solTypeToTsType(paramKind: ParamKind, backend: ContractsBackend, solType: string, components?: DataItem[]): string { diff --git a/packages/assert/CHANGELOG.json b/packages/assert/CHANGELOG.json index 717b803af..9889d0efa 100644 --- a/packages/assert/CHANGELOG.json +++ b/packages/assert/CHANGELOG.json @@ -1,5 +1,14 @@ [ { + "timestamp": 1523462196, + "version": "0.2.6", + "changes": [ + { + "note": "Dependencies updated" + } + ] + }, + { "timestamp": 1522673609, "version": "0.2.5", "changes": [ diff --git a/packages/assert/CHANGELOG.md b/packages/assert/CHANGELOG.md index aeb6949ce..f482ba92b 100644 --- a/packages/assert/CHANGELOG.md +++ b/packages/assert/CHANGELOG.md @@ -5,6 +5,10 @@ Edit the package's CHANGELOG.json file only. CHANGELOG +## v0.2.6 - _April 11, 2018_ + + * Dependencies updated + ## v0.2.5 - _April 2, 2018_ * Dependencies updated diff --git a/packages/assert/package.json b/packages/assert/package.json index 4e495d05f..8ed287c25 100644 --- a/packages/assert/package.json +++ b/packages/assert/package.json @@ -1,6 +1,6 @@ { "name": "@0xproject/assert", - "version": "0.2.5", + "version": "0.2.6", "description": "Provides a standard way of performing type and schema validation across 0x projects", "main": "lib/src/index.js", "types": "lib/src/index.d.ts", @@ -9,7 +9,7 @@ "build": "tsc && copyfiles -u 3 './lib/src/monorepo_scripts/**/*' ./scripts", "clean": "shx rm -rf lib test_temp scripts", "lint": "tslint --project . 'src/**/*.ts' 'test/**/*.ts'", - "run_mocha": "mocha lib/test/**/*_test.js", + "run_mocha": "mocha lib/test/**/*_test.js --exit", "prepublishOnly": "run-p build", "test": "run-s clean build run_mocha", "test:coverage": "nyc npm run test --all && yarn coverage:report:lcov", @@ -27,8 +27,8 @@ }, "homepage": "https://github.com/0xProject/0x-monorepo/packages/assert/README.md", "devDependencies": { - "@0xproject/monorepo-scripts": "^0.1.16", - "@0xproject/tslint-config": "^0.4.14", + "@0xproject/monorepo-scripts": "^0.1.17", + "@0xproject/tslint-config": "^0.4.15", "@types/lodash": "4.14.104", "@types/mocha": "^2.2.42", "@types/valid-url": "^1.0.2", @@ -43,9 +43,9 @@ "typescript": "2.7.1" }, "dependencies": { - "@0xproject/json-schemas": "^0.7.19", - "@0xproject/typescript-typings": "^0.0.3", - "@0xproject/utils": "^0.5.0", + "@0xproject/json-schemas": "^0.7.20", + "@0xproject/typescript-typings": "^0.1.0", + "@0xproject/utils": "^0.5.1", "lodash": "^4.17.4", "valid-url": "^1.0.9" }, diff --git a/packages/base-contract/CHANGELOG.json b/packages/base-contract/CHANGELOG.json index da957ec83..ede16cdc4 100644 --- a/packages/base-contract/CHANGELOG.json +++ b/packages/base-contract/CHANGELOG.json @@ -6,7 +6,8 @@ "note": "Contract wrappers now accept Provider and defaults instead of Web3Wrapper", "pr": 501 } - ] + ], + "timestamp": 1523462196 }, { "version": "0.1.0", diff --git a/packages/base-contract/CHANGELOG.md b/packages/base-contract/CHANGELOG.md index aebb0a5d9..851df7b62 100644 --- a/packages/base-contract/CHANGELOG.md +++ b/packages/base-contract/CHANGELOG.md @@ -5,6 +5,10 @@ Edit the package's CHANGELOG.json file only. CHANGELOG +## v0.2.0 - _April 11, 2018_ + + * Contract wrappers now accept Provider and defaults instead of Web3Wrapper (#501) + ## v0.1.0 - _April 2, 2018_ * Add tests for traversing ABI tree (#485) diff --git a/packages/base-contract/package.json b/packages/base-contract/package.json index 449986119..5e14b7de5 100644 --- a/packages/base-contract/package.json +++ b/packages/base-contract/package.json @@ -1,6 +1,6 @@ { "name": "@0xproject/base-contract", - "version": "0.1.0", + "version": "0.2.0", "description": "0x Base TS contract", "main": "lib/src/index.js", "types": "lib/src/index.d.ts", @@ -26,8 +26,8 @@ }, "homepage": "https://github.com/0xProject/0x-monorepo/packages/base-contract/README.md", "devDependencies": { - "@0xproject/monorepo-scripts": "^0.1.16", - "@0xproject/tslint-config": "^0.4.14", + "@0xproject/monorepo-scripts": "^0.1.17", + "@0xproject/tslint-config": "^0.4.15", "@types/lodash": "4.14.104", "chai": "^4.0.1", "copyfiles": "^1.2.0", @@ -38,10 +38,10 @@ "typescript": "2.7.1" }, "dependencies": { - "@0xproject/types": "^0.5.0", - "@0xproject/typescript-typings": "^0.0.3", - "@0xproject/utils": "^0.5.0", - "@0xproject/web3-wrapper": "^0.5.0", + "@0xproject/types": "^0.6.0", + "@0xproject/typescript-typings": "^0.1.0", + "@0xproject/utils": "^0.5.1", + "@0xproject/web3-wrapper": "^0.6.0", "ethers-contracts": "^2.2.1", "lodash": "^4.17.4" }, diff --git a/packages/base-contract/src/index.ts b/packages/base-contract/src/index.ts index bba686f8b..bfa99fac1 100644 --- a/packages/base-contract/src/index.ts +++ b/packages/base-contract/src/index.ts @@ -1,13 +1,26 @@ -import { ContractAbi, DataItem, Provider, TxData, TxDataPayable } from '@0xproject/types'; -import { BigNumber } from '@0xproject/utils'; +import { + AbiDefinition, + AbiType, + ContractAbi, + DataItem, + MethodAbi, + Provider, + TxData, + TxDataPayable, +} from '@0xproject/types'; +import { abiUtils, BigNumber } from '@0xproject/utils'; import { Web3Wrapper } from '@0xproject/web3-wrapper'; import * as ethersContracts from 'ethers-contracts'; import * as _ from 'lodash'; import { formatABIDataItem } from './utils'; +export interface EthersInterfaceByFunctionSignature { + [key: string]: ethersContracts.Interface; +} + export class BaseContract { - protected _ethersInterface: ethersContracts.Interface; + protected _ethersInterfacesByFunctionSignature: EthersInterfaceByFunctionSignature; protected _web3Wrapper: Web3Wrapper; public abi: ContractAbi; public address: string; @@ -49,10 +62,37 @@ export class BaseContract { } return txDataWithDefaults; } + protected _lookupEthersInterface(functionSignature: string): ethersContracts.Interface { + const ethersInterface = this._ethersInterfacesByFunctionSignature[functionSignature]; + if (_.isUndefined(ethersInterface)) { + throw new Error(`Failed to lookup method with function signature '${functionSignature}'`); + } + return ethersInterface; + } + protected _lookupAbi(functionSignature: string): MethodAbi { + const methodAbi = _.find(this.abi, (abiDefinition: AbiDefinition) => { + if (abiDefinition.type !== AbiType.Function) { + return false; + } + const abiFunctionSignature = abiUtils.getFunctionSignature(abiDefinition); + if (abiFunctionSignature === functionSignature) { + return true; + } + return false; + }) as MethodAbi; + return methodAbi; + } constructor(abi: ContractAbi, address: string, provider: Provider, defaults?: Partial<TxData>) { this._web3Wrapper = new Web3Wrapper(provider, defaults); this.abi = abi; this.address = address; - this._ethersInterface = new ethersContracts.Interface(abi); + const methodAbis = this.abi.filter( + (abiDefinition: AbiDefinition) => abiDefinition.type === AbiType.Function, + ) as MethodAbi[]; + this._ethersInterfacesByFunctionSignature = {}; + _.each(methodAbis, methodAbi => { + const functionSignature = abiUtils.getFunctionSignature(methodAbi); + this._ethersInterfacesByFunctionSignature[functionSignature] = new ethersContracts.Interface([methodAbi]); + }); } } diff --git a/packages/connect/CHANGELOG.json b/packages/connect/CHANGELOG.json index 239dd23a4..a2b5c94d3 100644 --- a/packages/connect/CHANGELOG.json +++ b/packages/connect/CHANGELOG.json @@ -1,5 +1,14 @@ [ { + "timestamp": 1523462196, + "version": "0.6.9", + "changes": [ + { + "note": "Dependencies updated" + } + ] + }, + { "timestamp": 1522673609, "version": "0.6.8", "changes": [ diff --git a/packages/connect/CHANGELOG.md b/packages/connect/CHANGELOG.md index 2e50b9e2a..99b5746b5 100644 --- a/packages/connect/CHANGELOG.md +++ b/packages/connect/CHANGELOG.md @@ -5,6 +5,10 @@ Edit the package's CHANGELOG.json file only. CHANGELOG +## v0.6.9 - _April 11, 2018_ + + * Dependencies updated + ## v0.6.8 - _April 2, 2018_ * Dependencies updated diff --git a/packages/connect/package.json b/packages/connect/package.json index f0a01cff7..8fe29a1ad 100644 --- a/packages/connect/package.json +++ b/packages/connect/package.json @@ -1,6 +1,6 @@ { "name": "@0xproject/connect", - "version": "0.6.8", + "version": "0.6.9", "description": "A javascript library for interacting with the standard relayer api", "keywords": [ "connect", @@ -17,7 +17,7 @@ "clean": "shx rm -rf lib test_temp scripts", "copy_test_fixtures": "copyfiles -u 2 './test/fixtures/**/*.json' ./lib/test/fixtures", "lint": "tslint --project . 'src/**/*.ts' 'test/**/*.ts'", - "run_mocha": "mocha lib/test/**/*_test.js", + "run_mocha": "mocha lib/test/**/*_test.js --exit", "test": "run-s clean build copy_test_fixtures run_mocha", "test:coverage": "nyc npm run test --all && yarn coverage:report:lcov", "coverage:report:lcov": "nyc report --reporter=text-lcov > coverage/lcov.info", @@ -50,19 +50,19 @@ }, "homepage": "https://github.com/0xProject/0x-monorepo/packages/connect/README.md", "dependencies": { - "@0xproject/assert": "^0.2.5", - "@0xproject/json-schemas": "^0.7.19", - "@0xproject/types": "^0.5.0", - "@0xproject/typescript-typings": "^0.0.3", - "@0xproject/utils": "^0.5.0", + "@0xproject/assert": "^0.2.6", + "@0xproject/json-schemas": "^0.7.20", + "@0xproject/types": "^0.6.0", + "@0xproject/typescript-typings": "^0.1.0", + "@0xproject/utils": "^0.5.1", "isomorphic-fetch": "^2.2.1", "lodash": "^4.17.4", "query-string": "^5.0.1", "websocket": "^1.0.25" }, "devDependencies": { - "@0xproject/monorepo-scripts": "^0.1.16", - "@0xproject/tslint-config": "^0.4.14", + "@0xproject/monorepo-scripts": "^0.1.17", + "@0xproject/tslint-config": "^0.4.15", "@types/fetch-mock": "^5.12.1", "@types/lodash": "4.14.104", "@types/mocha": "^2.2.42", diff --git a/packages/contract_templates/contract.handlebars b/packages/contract_templates/contract.handlebars index 3e3f87f10..472452d74 100644 --- a/packages/contract_templates/contract.handlebars +++ b/packages/contract_templates/contract.handlebars @@ -41,6 +41,6 @@ export class {{contractName}}Contract extends BaseContract { {{/each}} constructor(abi: ContractAbi, address: string, provider: Provider, defaults?: Partial<TxData>) { super(abi, address, provider, defaults); - classUtils.bindAll(this, ['_ethersInterface', 'address', 'abi', '_web3Wrapper']); + classUtils.bindAll(this, ['_ethersInterfacesByFunctionSignature', 'address', 'abi', '_web3Wrapper']); } } // tslint:disable:max-file-line-count diff --git a/packages/contract_templates/partials/callAsync.handlebars b/packages/contract_templates/partials/callAsync.handlebars index 8de69203e..a6f4abdf2 100644 --- a/packages/contract_templates/partials/callAsync.handlebars +++ b/packages/contract_templates/partials/callAsync.handlebars @@ -5,9 +5,9 @@ async callAsync( defaultBlock?: BlockParam, ): Promise<{{> return_type outputs=outputs}}> { const self = this as any as {{contractName}}Contract; - const inputAbi = (_.find(self.abi, {name: '{{this.name}}'}) as MethodAbi).inputs; + const inputAbi = self._lookupAbi('{{this.functionSignature}}').inputs; [{{> params inputs=inputs}}] = BaseContract._formatABIDataItemList(inputAbi, [{{> params inputs=inputs}}], BaseContract._bigNumberToString.bind(self)); - const encodedData = self._ethersInterface.functions.{{this.name}}( + const encodedData = self._lookupEthersInterface('{{this.functionSignature}}').functions.{{this.name}}( {{> params inputs=inputs}} ).data; const callDataWithDefaults = await self._applyDefaultsToTxDataAsync( diff --git a/packages/contract_templates/partials/tx.handlebars b/packages/contract_templates/partials/tx.handlebars index 41ba6d3f7..22fe0c597 100644 --- a/packages/contract_templates/partials/tx.handlebars +++ b/packages/contract_templates/partials/tx.handlebars @@ -1,4 +1,4 @@ -public {{this.name}} = { +public {{this.tsName}} = { async sendTransactionAsync( {{> typed_params inputs=inputs}} {{#this.payable}} @@ -9,17 +9,17 @@ public {{this.name}} = { {{/this.payable}} ): Promise<string> { const self = this as any as {{contractName}}Contract; - const inputAbi = (_.find(self.abi, {name: '{{this.name}}'}) as MethodAbi).inputs; + const inputAbi = self._lookupAbi('{{this.functionSignature}}').inputs; [{{> params inputs=inputs}}] = BaseContract._formatABIDataItemList(inputAbi, [{{> params inputs=inputs}}], BaseContract._bigNumberToString.bind(self)); - const encodedData = self._ethersInterface.functions.{{this.name}}( + const encodedData = self._lookupEthersInterface('{{this.functionSignature}}').functions.{{this.name}}( {{> params inputs=inputs}} - ).data + ).data; const txDataWithDefaults = await self._applyDefaultsToTxDataAsync( { ...txData, data: encodedData, }, - self.{{this.name}}.estimateGasAsync.bind( + self.{{this.tsName}}.estimateGasAsync.bind( self, {{> params inputs=inputs}} ), @@ -32,11 +32,11 @@ public {{this.name}} = { txData: Partial<TxData> = {}, ): Promise<number> { const self = this as any as {{contractName}}Contract; - const inputAbi = (_.find(self.abi, {name: '{{this.name}}'}) as MethodAbi).inputs; + const inputAbi = self._lookupAbi('{{this.functionSignature}}').inputs; [{{> params inputs=inputs}}] = BaseContract._formatABIDataItemList(inputAbi, [{{> params inputs=inputs}}], BaseContract._bigNumberToString.bind(this)); - const encodedData = self._ethersInterface.functions.{{this.name}}( + const encodedData = self._lookupEthersInterface('{{this.functionSignature}}').functions.{{this.name}}( {{> params inputs=inputs}} - ).data + ).data; const txDataWithDefaults = await self._applyDefaultsToTxDataAsync( { ...txData, @@ -50,11 +50,11 @@ public {{this.name}} = { {{> typed_params inputs=inputs}} ): string { const self = this as any as {{contractName}}Contract; - const inputAbi = (_.find(self.abi, {name: '{{this.name}}'}) as MethodAbi).inputs; + const inputAbi = self._lookupAbi('{{this.functionSignature}}').inputs; [{{> params inputs=inputs}}] = BaseContract._formatABIDataItemList(inputAbi, [{{> params inputs=inputs}}], BaseContract._bigNumberToString.bind(self)); - const abiEncodedTransactionData = self._ethersInterface.functions.{{this.name}}( + const abiEncodedTransactionData = self._lookupEthersInterface('{{this.name}}').functions.{{this.name}}( {{> params inputs=inputs}} - ).data + ).data; return abiEncodedTransactionData; }, {{> callAsync}} diff --git a/packages/contracts/README.md b/packages/contracts/README.md index 286ef019c..16e253549 100644 --- a/packages/contracts/README.md +++ b/packages/contracts/README.md @@ -72,17 +72,6 @@ yarn lint ### Run Tests -Before running the tests, you will need to spin up a [TestRPC](https://www.npmjs.com/package/ethereumjs-testrpc) instance. - -In a separate terminal, start TestRPC (a convenience command is provided as part of the [0x.js monorepo](https://github.com/0xProject/0x-monorepo)) - -```bash -cd ../.. -yarn testrpc -``` - -Then in your main terminal run - ```bash yarn test ``` diff --git a/packages/contracts/migrations/config/multisig_sample.ts b/packages/contracts/migrations/config/multisig_sample.ts deleted file mode 100644 index bc2502fca..000000000 --- a/packages/contracts/migrations/config/multisig_sample.ts +++ /dev/null @@ -1,10 +0,0 @@ -import { MultiSigConfigByNetwork } from '../types'; - -// Make a copy of this file named `multisig.js` and input custom params as needed -export const multiSig: MultiSigConfigByNetwork = { - kovan: { - owners: [], - confirmationsRequired: 0, - secondsRequired: 0, - }, -}; diff --git a/packages/contracts/migrations/types.ts b/packages/contracts/migrations/types.ts deleted file mode 100644 index 58d1e5b4f..000000000 --- a/packages/contracts/migrations/types.ts +++ /dev/null @@ -1,23 +0,0 @@ -export interface MultiSigConfig { - owners: string[]; - confirmationsRequired: number; - secondsRequired: number; -} - -export interface MultiSigConfigByNetwork { - [networkName: string]: MultiSigConfig; -} - -export interface Token { - address?: string; - name: string; - symbol: string; - decimals: number; - ipfsHash: string; - swarmHash: string; -} - -export interface TokenInfoByNetwork { - development: Token[]; - live: Token[]; -} diff --git a/packages/contracts/package.json b/packages/contracts/package.json index 8152a9afe..eb1701a18 100644 --- a/packages/contracts/package.json +++ b/packages/contracts/package.json @@ -1,7 +1,7 @@ { "private": true, "name": "contracts", - "version": "2.1.21", + "version": "2.1.22", "description": "Smart contract components of 0x protocol", "main": "index.js", "directories": { @@ -10,16 +10,15 @@ "scripts": { "build:watch": "tsc -w", "prebuild": "run-s clean compile copy_artifacts generate_contract_wrappers", - "copy_artifacts": "copyfiles './src/artifacts/**/*' ./lib", + "copy_artifacts": "copyfiles -u 4 '../migrations/src/artifacts/**/*' ./lib/src/artifacts;", "build": "tsc", "test": "run-s build run_mocha", "test:coverage": "SOLIDITY_COVERAGE=true run-s build run_mocha coverage:report:text coverage:report:lcov", "run_mocha": "mocha 'lib/test/**/*.js' --timeout 100000 --bail --exit", "compile:comment": "Yarn workspaces do not link binaries correctly so we need to reference them directly https://github.com/yarnpkg/yarn/issues/3846", - "compile": "node ../deployer/lib/src/cli.js compile --contracts ${npm_package_config_contracts} --contracts-dir src/contracts --artifacts-dir src/artifacts", + "compile": "node ../deployer/lib/src/cli.js compile --contracts ${npm_package_config_contracts} --contracts-dir src/contracts --artifacts-dir ../migrations/src/artifacts", "clean": "shx rm -rf ./lib", "generate_contract_wrappers": "node ../abi-gen/lib/index.js --abis ${npm_package_config_abis} --template ../contract_templates/contract.handlebars --partials '../contract_templates/partials/**/*.handlebars' --output src/contract_wrappers/generated --backend ethers && prettier --write 'src/contract_wrappers/generated/**.ts'", - "migrate": "yarn build && yarn compile && node ./lib/migrations/index.js", "lint": "tslint --project . 'migrations/**/*.ts' 'test/**/*.ts' 'util/**/*.ts' 'deploy/**/*.ts'", "coverage:report:text": "istanbul report text", "coverage:report:html": "istanbul report html && open coverage/index.html", @@ -27,7 +26,7 @@ "test:circleci": "yarn test:coverage" }, "config": { - "abis": "src/artifacts/@(DummyToken|TokenTransferProxy|Exchange|TokenRegistry|MultiSigWallet|MultiSigWalletWithTimeLock|MultiSigWalletWithTimeLockExceptRemoveAuthorizedAddress|TokenRegistry|ZRXToken|Arbitrage|EtherDelta|AccountLevels).json", + "abis": "../migrations/src/artifacts/@(DummyToken|TokenTransferProxy|Exchange|TokenRegistry|MultiSigWallet|MultiSigWalletWithTimeLock|MultiSigWalletWithTimeLockExceptRemoveAuthorizedAddress|TokenRegistry|ZRXToken|Arbitrage|EtherDelta|AccountLevels).json", "contracts": "Exchange,DummyToken,ZRXToken,Token,WETH9,TokenTransferProxy,MultiSigWallet,MultiSigWalletWithTimeLock,MultiSigWalletWithTimeLockExceptRemoveAuthorizedAddress,MaliciousToken,TokenRegistry,Arbitrage,EtherDelta,AccountLevels" }, "repository": { @@ -41,8 +40,8 @@ }, "homepage": "https://github.com/0xProject/0x-monorepo/packages/contracts/README.md", "devDependencies": { - "@0xproject/dev-utils": "^0.3.4", - "@0xproject/tslint-config": "^0.4.14", + "@0xproject/dev-utils": "^0.3.5", + "@0xproject/tslint-config": "^0.4.15", "@types/lodash": "4.14.104", "@types/node": "^8.0.53", "@types/yargs": "^10.0.0", @@ -61,12 +60,12 @@ "yargs": "^10.0.3" }, "dependencies": { - "0x.js": "^0.35.0", - "@0xproject/deployer": "^0.3.5", - "@0xproject/types": "^0.5.0", - "@0xproject/typescript-typings": "^0.0.3", - "@0xproject/utils": "^0.5.0", - "@0xproject/web3-wrapper": "^0.5.0", + "0x.js": "^0.36.0", + "@0xproject/deployer": "^0.4.0", + "@0xproject/types": "^0.6.0", + "@0xproject/typescript-typings": "^0.1.0", + "@0xproject/utils": "^0.5.1", + "@0xproject/web3-wrapper": "^0.6.0", "bn.js": "^4.11.8", "ethereumjs-abi": "^0.6.4", "ethereumjs-util": "^5.1.1", diff --git a/packages/contracts/test/multi_sig_with_time_lock.ts b/packages/contracts/test/multi_sig_with_time_lock.ts index ea74d4c7f..b7604457f 100644 --- a/packages/contracts/test/multi_sig_with_time_lock.ts +++ b/packages/contracts/test/multi_sig_with_time_lock.ts @@ -46,7 +46,7 @@ describe('MultiSigWalletWithTimeLock', () => { describe('changeTimeLock', () => { describe('initially non-time-locked', async () => { - before('deploy a walet', async () => { + before('deploy a wallet', async () => { const multiSigInstance = await deployer.deployAsync(ContractName.MultiSigWalletWithTimeLock, [ owners, SIGNATURES_REQUIRED, @@ -143,7 +143,7 @@ describe('MultiSigWalletWithTimeLock', () => { }); }); describe('initially time-locked', async () => { - before('deploy a walet', async () => { + before('deploy a wallet', async () => { const multiSigInstance = await deployer.deployAsync(ContractName.MultiSigWalletWithTimeLock, [ owners, SIGNATURES_REQUIRED, diff --git a/packages/contracts/test/token_registry.ts b/packages/contracts/test/token_registry.ts index 12fc52dbc..4c404176b 100644 --- a/packages/contracts/test/token_registry.ts +++ b/packages/contracts/test/token_registry.ts @@ -1,6 +1,6 @@ import { ZeroEx } from '0x.js'; import { BlockchainLifecycle, devConstants, web3Factory } from '@0xproject/dev-utils'; -import { BigNumber } from '@0xproject/utils'; +import { BigNumber, NULL_BYTES } from '@0xproject/utils'; import { Web3Wrapper } from '@0xproject/web3-wrapper'; import * as chai from 'chai'; import ethUtil = require('ethereumjs-util'); @@ -66,8 +66,8 @@ describe('TokenRegistry', () => { name: '', symbol: '', decimals: 0, - ipfsHash: constants.NULL_BYTES, - swarmHash: constants.NULL_BYTES, + ipfsHash: NULL_BYTES, + swarmHash: NULL_BYTES, }; describe('addToken', () => { diff --git a/packages/contracts/test/utils/deployer.ts b/packages/contracts/test/utils/deployer.ts index 45f79a2a4..2f0951475 100644 --- a/packages/contracts/test/utils/deployer.ts +++ b/packages/contracts/test/utils/deployer.ts @@ -8,7 +8,7 @@ import { web3 } from './web3_wrapper'; const deployerOpts = { provider: web3.currentProvider, - artifactsDir: path.resolve('src', 'artifacts'), + artifactsDir: path.resolve('lib', 'src', 'artifacts'), networkId: constants.TESTRPC_NETWORK_ID, defaults: { gas: devConstants.GAS_ESTIMATE, diff --git a/packages/contracts/test/utils/web3_wrapper.ts b/packages/contracts/test/utils/web3_wrapper.ts index 1a711dad2..dd6f198c4 100644 --- a/packages/contracts/test/utils/web3_wrapper.ts +++ b/packages/contracts/test/utils/web3_wrapper.ts @@ -1,7 +1,8 @@ import { web3Factory } from '@0xproject/dev-utils'; +import { Provider } from '@0xproject/types'; import { Web3Wrapper } from '@0xproject/web3-wrapper'; -const web3ProviderConfig = { shouldUseInProcessGanache: true }; -export const web3 = web3Factory.create(web3ProviderConfig); +const providerConfigs = { shouldUseInProcessGanache: true }; +export const web3 = web3Factory.create(providerConfigs); export const provider = web3.currentProvider; export const web3Wrapper = new Web3Wrapper(provider); diff --git a/packages/contracts/util/constants.ts b/packages/contracts/util/constants.ts index 9bb090a2a..d1152e683 100644 --- a/packages/contracts/util/constants.ts +++ b/packages/contracts/util/constants.ts @@ -4,7 +4,6 @@ const DUMMY_TOKEN_DECIMALS = 18; const DUMMY_TOKEN_TOTAL_SUPPLY = 0; export const constants = { - NULL_BYTES: '0x', INVALID_OPCODE: 'invalid opcode', REVERT: 'revert', TESTRPC_NETWORK_ID: 50, diff --git a/packages/deployer/CHANGELOG.json b/packages/deployer/CHANGELOG.json index f9691466b..b130405dc 100644 --- a/packages/deployer/CHANGELOG.json +++ b/packages/deployer/CHANGELOG.json @@ -6,7 +6,8 @@ "note": "Changed the config key `web3Provider` to `provider` to be consistent with other tools", "pr": 501 } - ] + ], + "timestamp": 1523462196 }, { "version": "0.3.5", diff --git a/packages/deployer/CHANGELOG.md b/packages/deployer/CHANGELOG.md index b11aa988c..4b49092ae 100644 --- a/packages/deployer/CHANGELOG.md +++ b/packages/deployer/CHANGELOG.md @@ -5,6 +5,10 @@ Edit the package's CHANGELOG.json file only. CHANGELOG +## v0.4.0 - _April 11, 2018_ + + * Changed the config key `web3Provider` to `provider` to be consistent with other tools (#501) + ## v0.3.5 - _April 2, 2018_ * Don't try to write contract artifact if an error occured (#485) diff --git a/packages/deployer/README.md b/packages/deployer/README.md index d8b049bdf..ef0ddd59d 100644 --- a/packages/deployer/README.md +++ b/packages/deployer/README.md @@ -2,7 +2,7 @@ This repository contains a CLI tool that facilitates compiling and deployment of smart contracts. -### Read the [Documentation](0xproject.com/docs/deployer). +### Read the [Documentation](https://0xproject.com/docs/deployer). ## Installation diff --git a/packages/deployer/package.json b/packages/deployer/package.json index f6eff9973..d529382ac 100644 --- a/packages/deployer/package.json +++ b/packages/deployer/package.json @@ -1,6 +1,6 @@ { "name": "@0xproject/deployer", - "version": "0.3.5", + "version": "0.4.0", "description": "Smart contract deployer of 0x protocol", "main": "lib/src/index.js", "types": "lib/src/index.d.ts", @@ -8,7 +8,7 @@ "build:watch": "tsc -w", "build": "yarn clean && copyfiles 'test/fixtures/contracts/**/*' ./lib && tsc && copyfiles -u 3 './lib/src/monorepo_scripts/**/*' ./scripts", "test": "run-s build run_mocha", - "run_mocha": "mocha lib/test/*_test.js", + "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", "compile": "npm run build; node lib/src/cli.js compile", @@ -47,12 +47,13 @@ }, "homepage": "https://github.com/0xProject/0x-monorepo/packages/deployer/README.md", "devDependencies": { - "@0xproject/monorepo-scripts": "^0.1.16", - "@0xproject/tslint-config": "^0.4.14", + "@0xproject/dev-utils": "^0.3.4", + "@0xproject/monorepo-scripts": "^0.1.17", + "@0xproject/tslint-config": "^0.4.15", "@types/require-from-string": "^1.2.0", "@types/semver": "^5.5.0", - "@types/yargs": "^11.0.0", "chai": "^4.0.1", + "chai-as-promised": "^7.1.0", "copyfiles": "^1.2.0", "dirty-chai": "^2.0.1", "mocha": "^4.0.1", @@ -63,14 +64,18 @@ "typedoc": "0xProject/typedoc", "types-bn": "^0.0.1", "typescript": "2.7.1", - "web3-typescript-typings": "^0.10.2" + "web3-typescript-typings": "^0.10.2", + "zeppelin-solidity": "1.8.0" }, "dependencies": { - "@0xproject/json-schemas": "^0.7.19", - "@0xproject/types": "^0.5.0", - "@0xproject/typescript-typings": "^0.0.3", - "@0xproject/utils": "^0.5.0", - "@0xproject/web3-wrapper": "^0.5.0", + "@0xproject/sol-resolver": "^0.0.1", + "@0xproject/json-schemas": "^0.7.20", + "@0xproject/types": "^0.6.0", + "@0xproject/typescript-typings": "^0.1.0", + "@0xproject/utils": "^0.5.1", + "@0xproject/web3-wrapper": "^0.6.0", + "@types/yargs": "^11.0.0", + "chalk": "^2.3.0", "ethereumjs-util": "^5.1.1", "isomorphic-fetch": "^2.2.1", "lodash": "^4.17.4", diff --git a/packages/deployer/src/cli.ts b/packages/deployer/src/cli.ts index d1bd645b3..7f1ae708a 100644 --- a/packages/deployer/src/cli.ts +++ b/packages/deployer/src/cli.ts @@ -41,8 +41,8 @@ async function onCompileCommandAsync(argv: CliOptions): Promise<void> { */ async function onDeployCommandAsync(argv: CliOptions): Promise<void> { const url = argv.jsonrpcUrl; - const web3Provider = new Web3.providers.HttpProvider(url); - const web3Wrapper = new Web3Wrapper(web3Provider); + const provider = new Web3.providers.HttpProvider(url); + const web3Wrapper = new Web3Wrapper(provider); const networkId = await web3Wrapper.getNetworkIdAsync(); const compilerOpts: CompilerOptions = { contractsDir: argv.contractsDir, @@ -78,8 +78,7 @@ function getContractsSetFromList(contracts: string): Set<string> { } const contractsArray = contracts.split(','); _.forEach(contractsArray, contractName => { - const fileName = `${contractName}${constants.SOLIDITY_FILE_EXTENSION}`; - specifiedContracts.add(fileName); + specifiedContracts.add(contractName); }); return specifiedContracts; } diff --git a/packages/deployer/src/compiler.ts b/packages/deployer/src/compiler.ts index ba360cb57..a3c8004ec 100644 --- a/packages/deployer/src/compiler.ts +++ b/packages/deployer/src/compiler.ts @@ -1,5 +1,17 @@ +import { + ContractSource, + ContractSources, + EnumerableResolver, + FallthroughResolver, + FSResolver, + NameResolver, + NPMResolver, + Resolver, + URLResolver, +} from '@0xproject/sol-resolver'; import { ContractAbi } from '@0xproject/types'; import { logUtils, promisify } from '@0xproject/utils'; +import chalk from 'chalk'; import * as ethUtil from 'ethereumjs-util'; import * as fs from 'fs'; import 'isomorphic-fetch'; @@ -12,7 +24,6 @@ import solc = require('solc'); import { binPaths } from './solc/bin_paths'; import { createDirIfDoesNotExistAsync, - findImportIfExist, getContractArtifactIfExistsAsync, getNormalizedErrMsg, parseDependencies, @@ -26,7 +37,6 @@ import { ContractNetworkData, ContractNetworks, ContractSourceData, - ContractSources, ContractSpecificSourceData, } from './utils/types'; import { utils } from './utils/utils'; @@ -39,54 +49,13 @@ const SOLC_BIN_DIR = path.join(__dirname, '..', '..', 'solc_bin'); * to artifact files. */ export class Compiler { + private _resolver: Resolver; + private _nameResolver: NameResolver; private _contractsDir: string; private _networkId: number; private _optimizerEnabled: boolean; private _artifactsDir: string; - // This get's set in the beggining of `compileAsync` function. It's not called from a constructor, but it's the only public method of that class and could as well be. - private _contractSources!: ContractSources; private _specifiedContracts: Set<string> = new Set(); - private _contractSourceData: ContractSourceData = {}; - /** - * Recursively retrieves Solidity source code from directory. - * @param dirPath Directory to search. - * @return Mapping of contract fileName to contract source. - */ - private static async _getContractSourcesAsync(dirPath: string): Promise<ContractSources> { - let dirContents: string[] = []; - try { - dirContents = await fsWrapper.readdirAsync(dirPath); - } catch (err) { - throw new Error(`No directory found at ${dirPath}`); - } - let sources: ContractSources = {}; - for (const fileName of dirContents) { - const contentPath = `${dirPath}/${fileName}`; - if (path.extname(fileName) === constants.SOLIDITY_FILE_EXTENSION) { - try { - const opts = { - encoding: 'utf8', - }; - const source = await fsWrapper.readFileAsync(contentPath, opts); - sources[fileName] = source; - logUtils.log(`Reading ${fileName} source...`); - } catch (err) { - logUtils.log(`Could not find file at ${contentPath}`); - } - } else { - try { - const nestedSources = await Compiler._getContractSourcesAsync(contentPath); - sources = { - ...sources, - ...nestedSources, - }; - } catch (err) { - logUtils.log(`${contentPath} is not a directory or ${constants.SOLIDITY_FILE_EXTENSION} file`); - } - } - } - return sources; - } /** * Instantiates a new instance of the Compiler class. * @param opts Options specifying directories, network, and optimization settings. @@ -98,6 +67,14 @@ export class Compiler { this._optimizerEnabled = opts.optimizerEnabled; this._artifactsDir = opts.artifactsDir; this._specifiedContracts = opts.specifiedContracts; + this._nameResolver = new NameResolver(path.resolve(this._contractsDir)); + const resolver = new FallthroughResolver(); + resolver.appendResolver(new URLResolver()); + const packagePath = path.resolve(''); + resolver.appendResolver(new NPMResolver(packagePath)); + resolver.appendResolver(new FSResolver()); + resolver.appendResolver(this._nameResolver); + this._resolver = resolver; } /** * Compiles selected Solidity files found in `contractsDir` and writes JSON artifacts to `artifactsDir`. @@ -105,27 +82,27 @@ export class Compiler { public async compileAsync(): Promise<void> { await createDirIfDoesNotExistAsync(this._artifactsDir); await createDirIfDoesNotExistAsync(SOLC_BIN_DIR); - this._contractSources = await Compiler._getContractSourcesAsync(this._contractsDir); - _.forIn(this._contractSources, this._setContractSpecificSourceData.bind(this)); - const fileNames = this._specifiedContracts.has(ALL_CONTRACTS_IDENTIFIER) - ? _.keys(this._contractSources) - : Array.from(this._specifiedContracts.values()); - for (const fileName of fileNames) { - await this._compileContractAsync(fileName); + let contractNamesToCompile: string[] = []; + if (this._specifiedContracts.has(ALL_CONTRACTS_IDENTIFIER)) { + const allContracts = this._nameResolver.getAll(); + contractNamesToCompile = _.map(allContracts, contractSource => + path.basename(contractSource.path, constants.SOLIDITY_FILE_EXTENSION), + ); + } else { + contractNamesToCompile = Array.from(this._specifiedContracts.values()); + } + for (const contractNameToCompile of contractNamesToCompile) { + await this._compileContractAsync(contractNameToCompile); } } /** * Compiles contract and saves artifact to artifactsDir. * @param fileName Name of contract with '.sol' extension. */ - private async _compileContractAsync(fileName: string): Promise<void> { - if (_.isUndefined(this._contractSources)) { - throw new Error('Contract sources not yet initialized'); - } - const contractSpecificSourceData = this._contractSourceData[fileName]; - const currentArtifactIfExists = await getContractArtifactIfExistsAsync(this._artifactsDir, fileName); - const sourceHash = `0x${contractSpecificSourceData.sourceHash.toString('hex')}`; - const sourceTreeHash = `0x${contractSpecificSourceData.sourceTreeHash.toString('hex')}`; + private async _compileContractAsync(contractName: string): Promise<void> { + const contractSource = this._resolver.resolve(contractName); + const currentArtifactIfExists = await getContractArtifactIfExistsAsync(this._artifactsDir, contractName); + const sourceTreeHashHex = `0x${this._getSourceTreeHash(contractSource.path).toString('hex')}`; let shouldCompile = false; if (_.isUndefined(currentArtifactIfExists)) { @@ -134,16 +111,14 @@ export class Compiler { const currentArtifact = currentArtifactIfExists as ContractArtifact; shouldCompile = currentArtifact.networks[this._networkId].optimizer_enabled !== this._optimizerEnabled || - currentArtifact.networks[this._networkId].source_tree_hash !== sourceTreeHash; + currentArtifact.networks[this._networkId].source_tree_hash !== sourceTreeHashHex; } if (!shouldCompile) { return; } + const solcVersionRange = parseSolidityVersionRange(contractSource.source); const availableCompilerVersions = _.keys(binPaths); - const solcVersion = semver.maxSatisfying( - availableCompilerVersions, - contractSpecificSourceData.solcVersionRange, - ); + const solcVersion = semver.maxSatisfying(availableCompilerVersions, solcVersionRange); const fullSolcVersion = binPaths[solcVersion]; const compilerBinFilename = path.join(SOLC_BIN_DIR, fullSolcVersion); let solcjs: string; @@ -162,55 +137,77 @@ export class Compiler { } const solcInstance = solc.setupMethods(requireFromString(solcjs, compilerBinFilename)); - logUtils.log(`Compiling ${fileName} with Solidity v${solcVersion}...`); - const source = this._contractSources[fileName]; - const input = { - [fileName]: source, - }; - const sourcesToCompile = { - sources: input, + logUtils.log(`Compiling ${contractName} with Solidity v${solcVersion}...`); + const source = contractSource.source; + const absoluteFilePath = contractSource.path; + const standardInput: solc.StandardInput = { + language: 'Solidity', + sources: { + [absoluteFilePath]: { + urls: [`file://${absoluteFilePath}`], + }, + }, + settings: { + optimizer: { + enabled: this._optimizerEnabled, + }, + outputSelection: { + '*': { + '*': [ + 'abi', + 'evm.bytecode.object', + 'evm.bytecode.sourceMap', + 'evm.deployedBytecode.object', + 'evm.deployedBytecode.sourceMap', + ], + }, + }, + }, }; - const compiled = solcInstance.compile(sourcesToCompile, Number(this._optimizerEnabled), importPath => - findImportIfExist(this._contractSources, importPath), + const compiled: solc.StandardOutput = JSON.parse( + solcInstance.compileStandardWrapper(JSON.stringify(standardInput), importPath => { + const sourceCodeIfExists = this._resolver.resolve(importPath); + return { contents: sourceCodeIfExists.source }; + }), ); if (!_.isUndefined(compiled.errors)) { - const SOLIDITY_WARNING_PREFIX = 'Warning'; - const isError = (errorOrWarning: string) => !errorOrWarning.includes(SOLIDITY_WARNING_PREFIX); - const isWarning = (errorOrWarning: string) => errorOrWarning.includes(SOLIDITY_WARNING_PREFIX); - const errors = _.filter(compiled.errors, isError); - const warnings = _.filter(compiled.errors, isWarning); + const SOLIDITY_WARNING = 'warning'; + const errors = _.filter(compiled.errors, entry => entry.severity !== SOLIDITY_WARNING); + const warnings = _.filter(compiled.errors, entry => entry.severity === SOLIDITY_WARNING); if (!_.isEmpty(errors)) { - errors.forEach(errMsg => { - const normalizedErrMsg = getNormalizedErrMsg(errMsg); - logUtils.log(normalizedErrMsg); + errors.forEach(error => { + const normalizedErrMsg = getNormalizedErrMsg(error.formattedMessage || error.message); + logUtils.log(chalk.red(normalizedErrMsg)); }); process.exit(1); } else { - warnings.forEach(errMsg => { - const normalizedErrMsg = getNormalizedErrMsg(errMsg); - logUtils.log(normalizedErrMsg); + warnings.forEach(warning => { + const normalizedWarningMsg = getNormalizedErrMsg(warning.formattedMessage || warning.message); + logUtils.log(chalk.yellow(normalizedWarningMsg)); }); } } - const contractName = path.basename(fileName, constants.SOLIDITY_FILE_EXTENSION); - const contractIdentifier = `${fileName}:${contractName}`; - if (_.isUndefined(compiled.contracts[contractIdentifier])) { + const compiledData = compiled.contracts[absoluteFilePath][contractName]; + if (_.isUndefined(compiledData)) { throw new Error( - `Contract ${contractName} not found in ${fileName}. Please make sure your contract has the same name as it's file name`, + `Contract ${contractName} not found in ${absoluteFilePath}. Please make sure your contract has the same name as it's file name`, ); } - const abi: ContractAbi = JSON.parse(compiled.contracts[contractIdentifier].interface); - const bytecode = `0x${compiled.contracts[contractIdentifier].bytecode}`; - const runtimeBytecode = `0x${compiled.contracts[contractIdentifier].runtimeBytecode}`; - const sourceMap = compiled.contracts[contractIdentifier].srcmap; - const sourceMapRuntime = compiled.contracts[contractIdentifier].srcmapRuntime; - const sources = _.keys(compiled.sources); + const abi: ContractAbi = compiledData.abi; + const bytecode = `0x${compiledData.evm.bytecode.object}`; + const runtimeBytecode = `0x${compiledData.evm.deployedBytecode.object}`; + const sourceMap = compiledData.evm.bytecode.sourceMap; + const sourceMapRuntime = compiledData.evm.deployedBytecode.sourceMap; + const unresolvedSourcePaths = _.keys(compiled.sources); + const sources = _.map( + unresolvedSourcePaths, + unresolvedSourcePath => this._resolver.resolve(unresolvedSourcePath).path, + ); const updated_at = Date.now(); const contractNetworkData: ContractNetworkData = { solc_version: solcVersion, - keccak256: sourceHash, - source_tree_hash: sourceTreeHash, + source_tree_hash: sourceTreeHashHex, optimizer_enabled: this._optimizerEnabled, abi, bytecode, @@ -243,42 +240,22 @@ export class Compiler { const artifactString = utils.stringifyWithFormatting(newArtifact); const currentArtifactPath = `${this._artifactsDir}/${contractName}.json`; await fsWrapper.writeFileAsync(currentArtifactPath, artifactString); - logUtils.log(`${fileName} artifact saved!`); - } - /** - * Gets contract dependendencies and keccak256 hash from source. - * @param source Source code of contract. - * @return Object with contract dependencies and keccak256 hash of source. - */ - private _setContractSpecificSourceData(source: string, fileName: string): void { - if (!_.isUndefined(this._contractSourceData[fileName])) { - return; - } - const sourceHash = ethUtil.sha3(source); - const solcVersionRange = parseSolidityVersionRange(source); - const dependencies = parseDependencies(source); - const sourceTreeHash = this._getSourceTreeHash(fileName, sourceHash, dependencies); - this._contractSourceData[fileName] = { - dependencies, - solcVersionRange, - sourceHash, - sourceTreeHash, - }; + logUtils.log(`${contractName} artifact saved!`); } /** * Gets the source tree hash for a file and its dependencies. * @param fileName Name of contract file. */ - private _getSourceTreeHash(fileName: string, sourceHash: Buffer, dependencies: string[]): Buffer { + private _getSourceTreeHash(importPath: string): Buffer { + const contractSource = this._resolver.resolve(importPath); + const dependencies = parseDependencies(contractSource); + const sourceHash = ethUtil.sha3(contractSource.source); if (dependencies.length === 0) { return sourceHash; } else { - const dependencySourceTreeHashes = _.map(dependencies, dependency => { - const source = this._contractSources[dependency]; - this._setContractSpecificSourceData(source, dependency); - const sourceData = this._contractSourceData[dependency]; - return this._getSourceTreeHash(dependency, sourceData.sourceHash, sourceData.dependencies); - }); + const dependencySourceTreeHashes = _.map(dependencies, (dependency: string) => + this._getSourceTreeHash(dependency), + ); const sourceTreeHashesBuffer = Buffer.concat([sourceHash, ...dependencySourceTreeHashes]); const sourceTreeHash = ethUtil.sha3(sourceTreeHashesBuffer); return sourceTreeHash; diff --git a/packages/deployer/src/deployer.ts b/packages/deployer/src/deployer.ts index 84392997c..ad05417b1 100644 --- a/packages/deployer/src/deployer.ts +++ b/packages/deployer/src/deployer.ts @@ -38,17 +38,17 @@ export class Deployer { this._artifactsDir = opts.artifactsDir; this._networkId = opts.networkId; this._defaults = opts.defaults; - let web3Provider: Provider; + let provider: Provider; if (_.isUndefined((opts as ProviderDeployerOptions).provider)) { const jsonrpcUrl = (opts as UrlDeployerOptions).jsonrpcUrl; if (_.isUndefined(jsonrpcUrl)) { - throw new Error(`Deployer options don't contain web3Provider nor jsonrpcUrl. Please pass one of them`); + throw new Error(`Deployer options don't contain provider nor jsonrpcUrl. Please pass one of them`); } - web3Provider = new Web3.providers.HttpProvider(jsonrpcUrl); + provider = new Web3.providers.HttpProvider(jsonrpcUrl); } else { - web3Provider = (opts as ProviderDeployerOptions).provider; + provider = (opts as ProviderDeployerOptions).provider; } - this.web3Wrapper = new Web3Wrapper(web3Provider, this._defaults); + this.web3Wrapper = new Web3Wrapper(provider, this._defaults); } /** * Loads a contract's corresponding artifacts and deploys it with the supplied constructor arguments. @@ -170,7 +170,7 @@ export class Deployer { const contractArtifact: ContractArtifact = require(artifactPath); return contractArtifact; } catch (err) { - throw new Error(`Artifact not found for contract: ${contractName}`); + throw new Error(`Artifact not found for contract: ${contractName} at ${artifactPath}`); } } /** diff --git a/packages/deployer/src/utils/compiler.ts b/packages/deployer/src/utils/compiler.ts index d5137d394..c571b2581 100644 --- a/packages/deployer/src/utils/compiler.ts +++ b/packages/deployer/src/utils/compiler.ts @@ -1,3 +1,4 @@ +import { ContractSource, ContractSources } from '@0xproject/sol-resolver'; import { logUtils } from '@0xproject/utils'; import * as _ from 'lodash'; import * as path from 'path'; @@ -5,20 +6,19 @@ import * as solc from 'solc'; import { constants } from './constants'; import { fsWrapper } from './fs_wrapper'; -import { ContractArtifact, ContractSources } from './types'; +import { ContractArtifact } from './types'; /** * Gets contract data on network or returns if an artifact does not exist. * @param artifactsDir Path to the artifacts directory. - * @param fileName Name of contract file. + * @param contractName Name of contract. * @return Contract data on network or undefined. */ export async function getContractArtifactIfExistsAsync( artifactsDir: string, - fileName: string, + contractName: string, ): Promise<ContractArtifact | void> { let contractArtifact; - const contractName = path.basename(fileName, constants.SOLIDITY_FILE_EXTENSION); const currentArtifactPath = `${artifactsDir}/${contractName}.json`; try { const opts = { @@ -28,7 +28,7 @@ export async function getContractArtifactIfExistsAsync( contractArtifact = JSON.parse(contractArtifactString); return contractArtifact; } catch (err) { - logUtils.log(`Artifact for ${fileName} does not exist`); + logUtils.log(`Artifact for ${contractName} does not exist`); return undefined; } } @@ -84,8 +84,9 @@ export function getNormalizedErrMsg(errMsg: string): string { * @param source Contract source code * @return List of dependendencies */ -export function parseDependencies(source: string): string[] { +export function parseDependencies(contractSource: ContractSource): string[] { // TODO: Use a proper parser + const source = contractSource.source; const IMPORT_REGEX = /(import\s)/; const DEPENDENCY_PATH_REGEX = /"([^"]+)"/; // Source: https://github.com/BlockChainCompany/soljitsu/blob/master/lib/shared.js const dependencies: string[] = []; @@ -94,30 +95,13 @@ export function parseDependencies(source: string): string[] { if (!_.isNull(line.match(IMPORT_REGEX))) { const dependencyMatch = line.match(DEPENDENCY_PATH_REGEX); if (!_.isNull(dependencyMatch)) { - const dependencyPath = dependencyMatch[1]; - const basenName = path.basename(dependencyPath); - dependencies.push(basenName); + let dependencyPath = dependencyMatch[1]; + if (dependencyPath.startsWith('.')) { + dependencyPath = path.join(path.dirname(contractSource.path), dependencyPath); + } + dependencies.push(dependencyPath); } } }); return dependencies; } - -/** - * Callback to resolve dependencies with `solc.compile`. - * Throws error if contractSources not yet initialized. - * @param contractSources Source codes of contracts. - * @param importPath Path to an imported dependency. - * @return Import contents object containing source code of dependency. - */ -export function findImportIfExist(contractSources: ContractSources, importPath: string): solc.ImportContents { - const fileName = path.basename(importPath); - const source = contractSources[fileName]; - if (_.isUndefined(source)) { - throw new Error(`Contract source not found for ${fileName}`); - } - const importContents: solc.ImportContents = { - contents: source, - }; - return importContents; -} diff --git a/packages/deployer/src/utils/contract.ts b/packages/deployer/src/utils/contract.ts index 9b7baac11..e8dd5218a 100644 --- a/packages/deployer/src/utils/contract.ts +++ b/packages/deployer/src/utils/contract.ts @@ -1,11 +1,9 @@ import { schemas, SchemaValidator } from '@0xproject/json-schemas'; -import { ContractAbi, EventAbi, FunctionAbi, MethodAbi, TxData } from '@0xproject/types'; +import { AbiType, ContractAbi, EventAbi, FunctionAbi, MethodAbi, TxData } from '@0xproject/types'; import { promisify } from '@0xproject/utils'; import * as _ from 'lodash'; import * as Web3 from 'web3'; -import { AbiType } from './types'; - export class Contract implements Web3.ContractInstance { public address: string; public abi: ContractAbi; diff --git a/packages/deployer/src/utils/encoder.ts b/packages/deployer/src/utils/encoder.ts index 4f62662e1..806efbbca 100644 --- a/packages/deployer/src/utils/encoder.ts +++ b/packages/deployer/src/utils/encoder.ts @@ -1,9 +1,7 @@ -import { AbiDefinition, ContractAbi, DataItem } from '@0xproject/types'; +import { AbiDefinition, AbiType, ContractAbi, DataItem } from '@0xproject/types'; import * as _ from 'lodash'; import * as web3Abi from 'web3-eth-abi'; -import { AbiType } from './types'; - export const encoder = { encodeConstructorArgsFromAbi(args: any[], abi: ContractAbi): string { const constructorTypes: string[] = []; diff --git a/packages/deployer/src/utils/types.ts b/packages/deployer/src/utils/types.ts index 7d131f5ce..a20d0f627 100644 --- a/packages/deployer/src/utils/types.ts +++ b/packages/deployer/src/utils/types.ts @@ -21,7 +21,6 @@ export interface ContractNetworks { export interface ContractNetworkData { solc_version: string; optimizer_enabled: boolean; - keccak256: string; source_tree_hash: string; abi: ContractAbi; bytecode: string; @@ -74,16 +73,11 @@ export interface UrlDeployerOptions extends BaseDeployerOptions { export type DeployerOptions = UrlDeployerOptions | ProviderDeployerOptions; -export interface ContractSources { - [key: string]: string; -} - export interface ContractSourceData { - [key: string]: ContractSpecificSourceData; + [contractName: string]: ContractSpecificSourceData; } export interface ContractSpecificSourceData { - dependencies: string[]; solcVersionRange: string; sourceHash: Buffer; sourceTreeHash: Buffer; diff --git a/packages/deployer/test/compiler_utils_test.ts b/packages/deployer/test/compiler_utils_test.ts index 246304858..e2b95f289 100644 --- a/packages/deployer/test/compiler_utils_test.ts +++ b/packages/deployer/test/compiler_utils_test.ts @@ -47,28 +47,31 @@ describe('Compiler utils', () => { }); describe('#parseDependencies', () => { it('correctly parses Exchange dependencies', async () => { - const exchangeSource = await fsWrapper.readFileAsync(`${__dirname}/fixtures/contracts/Exchange.sol`, { + const path = `${__dirname}/fixtures/contracts/Exchange.sol`; + const source = await fsWrapper.readFileAsync(path, { encoding: 'utf8', }); - expect(parseDependencies(exchangeSource)).to.be.deep.equal([ - 'TokenTransferProxy.sol', - 'Token.sol', - 'SafeMath.sol', + expect(parseDependencies({ source, path })).to.be.deep.equal([ + 'zeppelin-solidity/contracts/token/ERC20/ERC20.sol', + '/home/circleci/repo/packages/deployer/lib/test/fixtures/contracts/TokenTransferProxy.sol', + '/home/circleci/repo/packages/deployer/lib/test/fixtures/contracts/base/SafeMath.sol', ]); }); it('correctly parses TokenTransferProxy dependencies', async () => { - const exchangeSource = await fsWrapper.readFileAsync( - `${__dirname}/fixtures/contracts/TokenTransferProxy.sol`, - { - encoding: 'utf8', - }, - ); - expect(parseDependencies(exchangeSource)).to.be.deep.equal(['Token.sol', 'Ownable.sol']); + const path = `${__dirname}/fixtures/contracts/TokenTransferProxy.sol`; + const source = await fsWrapper.readFileAsync(path, { + encoding: 'utf8', + }); + expect(parseDependencies({ source, path })).to.be.deep.equal([ + 'zeppelin-solidity/contracts/ownership/Ownable.sol', + 'zeppelin-solidity/contracts/token/ERC20/ERC20.sol', + ]); }); // TODO: For now that doesn't work. This will work after we switch to a grammar-based parser it.skip('correctly parses commented out dependencies', async () => { - const contractWithCommentedOutDependencies = `// import "./TokenTransferProxy.sol";`; - expect(parseDependencies(contractWithCommentedOutDependencies)).to.be.deep.equal([]); + const path = ''; + const source = `// import "./TokenTransferProxy.sol";`; + expect(parseDependencies({ path, source })).to.be.deep.equal([]); }); }); }); diff --git a/packages/deployer/test/deployer_test.ts b/packages/deployer/test/deployer_test.ts index 9c34d74aa..238624220 100644 --- a/packages/deployer/test/deployer_test.ts +++ b/packages/deployer/test/deployer_test.ts @@ -8,6 +8,7 @@ import { CompilerOptions, ContractArtifact, ContractNetworkData, DoneCallback } import { constructor_args, exchange_binary } from './fixtures/exchange_bin'; import { constants } from './util/constants'; +import { provider } from './util/provider'; const expect = chai.expect; @@ -26,7 +27,7 @@ describe('#Deployer', () => { const deployerOpts = { artifactsDir, networkId: constants.networkId, - jsonrpcUrl: constants.jsonrpcUrl, + provider, defaults: { gasPrice: constants.gasPrice, }, diff --git a/packages/deployer/test/fixtures/contracts/Exchange.sol b/packages/deployer/test/fixtures/contracts/Exchange.sol index 1b6819700..e3725335b 100644 --- a/packages/deployer/test/fixtures/contracts/Exchange.sol +++ b/packages/deployer/test/fixtures/contracts/Exchange.sol @@ -1,6 +1,6 @@ /* - Copyright 2017 ZeroEx Intl. + Copyright 2018 ZeroEx Intl. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. @@ -16,10 +16,11 @@ */ -pragma solidity 0.4.14; +pragma solidity ^0.4.14; + +import {ERC20 as Token} from "zeppelin-solidity/contracts/token/ERC20/ERC20.sol"; import "./TokenTransferProxy.sol"; -import "./base/Token.sol"; import "./base/SafeMath.sol"; /// @title Exchange - Facilitates exchange of ERC20 tokens. diff --git a/packages/deployer/test/fixtures/contracts/TokenTransferProxy.sol b/packages/deployer/test/fixtures/contracts/TokenTransferProxy.sol index 90c8e7d66..44570d459 100644 --- a/packages/deployer/test/fixtures/contracts/TokenTransferProxy.sol +++ b/packages/deployer/test/fixtures/contracts/TokenTransferProxy.sol @@ -1,6 +1,6 @@ /* - Copyright 2017 ZeroEx Intl. + Copyright 2018 ZeroEx Intl. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. @@ -16,10 +16,10 @@ */ -pragma solidity 0.4.14; +pragma solidity ^0.4.14; -import "./base/Token.sol"; -import "./base/Ownable.sol"; +import { Ownable } from "zeppelin-solidity/contracts/ownership/Ownable.sol"; +import { ERC20 as Token } from "zeppelin-solidity/contracts/token/ERC20/ERC20.sol"; /// @title TokenTransferProxy - Transfers tokens on behalf of contracts that have been approved via decentralized governance. /// @author Amir Bandeali - <amir@0xProject.com>, Will Warren - <will@0xProject.com> diff --git a/packages/deployer/test/fixtures/contracts/base/Ownable.sol b/packages/deployer/test/fixtures/contracts/base/Ownable.sol deleted file mode 100644 index 2a74c3717..000000000 --- a/packages/deployer/test/fixtures/contracts/base/Ownable.sol +++ /dev/null @@ -1,27 +0,0 @@ -pragma solidity 0.4.14; - -/* - * Ownable - * - * Base contract with an owner. - * Provides onlyOwner modifier, which prevents function from running if it is called by anyone other than the owner. - */ - -contract Ownable { - address public owner; - - function Ownable() { - owner = msg.sender; - } - - modifier onlyOwner() { - require(msg.sender == owner); - _; - } - - function transferOwnership(address newOwner) onlyOwner { - if (newOwner != address(0)) { - owner = newOwner; - } - } -} diff --git a/packages/deployer/test/fixtures/contracts/base/SafeMath.sol b/packages/deployer/test/fixtures/contracts/base/SafeMath.sol index 7414684a8..92ce11cde 100644 --- a/packages/deployer/test/fixtures/contracts/base/SafeMath.sol +++ b/packages/deployer/test/fixtures/contracts/base/SafeMath.sol @@ -1,4 +1,4 @@ -pragma solidity 0.4.14; +pragma solidity ^0.4.14; contract SafeMath { function safeMul(uint a, uint b) internal constant returns (uint256) { diff --git a/packages/deployer/test/fixtures/contracts/base/Token.sol b/packages/deployer/test/fixtures/contracts/base/Token.sol index c03f8c567..483010d7d 100644 --- a/packages/deployer/test/fixtures/contracts/base/Token.sol +++ b/packages/deployer/test/fixtures/contracts/base/Token.sol @@ -1,4 +1,4 @@ -pragma solidity 0.4.14; +pragma solidity ^0.4.14; contract Token { diff --git a/packages/deployer/test/fixtures/exchange_bin.ts b/packages/deployer/test/fixtures/exchange_bin.ts index a6eae515e..1bf1f3b38 100644 --- a/packages/deployer/test/fixtures/exchange_bin.ts +++ b/packages/deployer/test/fixtures/exchange_bin.ts @@ -1,4 +1,4 @@ export const constructor_args = '0x000000000000000000000000e41d2489571d322189246dafa5ebde1f4699f4980000000000000000000000008da0d80f5007ef1e431dd2127178d224e32c2ef4'; export const exchange_binary = - '0x6060604052341561000f57600080fd5b604051604080612c4d833981016040528080519060200190919080519060200190919050505b816000806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555080600160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055505b50505b612b84806100c96000396000f300606060405236156100fa576000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff16806314df96ee146100ff578063288cdc911461014c5780632ac1262214610187578063363349be146101c2578063394c21e7146103bc5780633b30ba591461044b5780634f150787146104a0578063741bcc93146106b25780637e9abb50146107535780638163681e1461078e57806398024a8b14610812578063add1cbc51461085b578063b7b2c7d6146108b0578063baa0181d14610acd578063bc61394a14610c1f578063cfc4d0ec14610cdf578063f06bbf7514610d6d578063ffa1ad7414610d9e575b600080fd5b341561010a57600080fd5b6101326004808035906020019091908035906020019091908035906020019091905050610e2d565b604051808215151515815260200191505060405180910390f35b341561015757600080fd5b610171600480803560001916906020019091905050610e7c565b6040518082815260200191505060405180910390f35b341561019257600080fd5b6101ac600480803560001916906020019091905050610e94565b6040518082815260200191505060405180910390f35b34156101cd57600080fd5b6103a660048080359060200190820180359060200190808060200260200160405190810160405280939291908181526020016000905b8282101561024857848483905060a002016005806020026040519081016040528092919082600560200280828437820191505050505081526020019060010190610203565b5050505050919080359060200190820180359060200190808060200260200160405190810160405280939291908181526020016000905b828210156102c457848483905060c00201600680602002604051908101604052809291908260066020028082843782019150505050508152602001906001019061027f565b5050505050919080359060200190919080351515906020019091908035906020019082018035906020019080806020026020016040519081016040528093929190818152602001838360200280828437820191505050505050919080359060200190820180359060200190808060200260200160405190810160405280939291908181526020018383602002808284378201915050505050509190803590602001908201803590602001908080602002602001604051908101604052809392919081815260200183836020028082843782019150505050505091905050610eac565b6040518082815260200191505060405180910390f35b34156103c757600080fd5b6104356004808060a001906005806020026040519081016040528092919082600560200280828437820191505050505091908060c001906006806020026040519081016040528092919082600660200280828437820191505050505091908035906020019091905050611013565b6040518082815260200191505060405180910390f35b341561045657600080fd5b61045e6114fb565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b34156104ab57600080fd5b6106b060048080359060200190820180359060200190808060200260200160405190810160405280939291908181526020016000905b8282101561052657848483905060a0020160058060200260405190810160405280929190826005602002808284378201915050505050815260200190600101906104e1565b5050505050919080359060200190820180359060200190808060200260200160405190810160405280939291908181526020016000905b828210156105a257848483905060c00201600680602002604051908101604052809291908260066020028082843782019150505050508152602001906001019061055d565b50505050509190803590602001908201803590602001908080602002602001604051908101604052809392919081815260200183836020028082843782019150505050505091908035906020019082018035906020019080806020026020016040519081016040528093929190818152602001838360200280828437820191505050505050919080359060200190820180359060200190808060200260200160405190810160405280939291908181526020018383602002808284378201915050505050509190803590602001908201803590602001908080602002602001604051908101604052809392919081815260200183836020028082843782019150505050505091905050611520565b005b34156106bd57600080fd5b6107516004808060a001906005806020026040519081016040528092919082600560200280828437820191505050505091908060c00190600680602002604051908101604052809291908260066020028082843782019150505050509190803590602001909190803560ff1690602001909190803560001916906020019091908035600019169060200190919050506115df565b005b341561075e57600080fd5b610778600480803560001916906020019091905050611605565b6040518082815260200191505060405180910390f35b341561079957600080fd5b6107f8600480803573ffffffffffffffffffffffffffffffffffffffff169060200190919080356000191690602001909190803560ff16906020019091908035600019169060200190919080356000191690602001909190505061164f565b604051808215151515815260200191505060405180910390f35b341561081d57600080fd5b6108456004808035906020019091908035906020019091908035906020019091905050611757565b6040518082815260200191505060405180910390f35b341561086657600080fd5b61086e611776565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b34156108bb57600080fd5b610acb60048080359060200190820180359060200190808060200260200160405190810160405280939291908181526020016000905b8282101561093657848483905060a0020160058060200260405190810160405280929190826005602002808284378201915050505050815260200190600101906108f1565b5050505050919080359060200190820180359060200190808060200260200160405190810160405280939291908181526020016000905b828210156109b257848483905060c00201600680602002604051908101604052809291908260066020028082843782019150505050508152602001906001019061096d565b50505050509190803590602001908201803590602001908080602002602001604051908101604052809392919081815260200183836020028082843782019150505050505091908035151590602001909190803590602001908201803590602001908080602002602001604051908101604052809392919081815260200183836020028082843782019150505050505091908035906020019082018035906020019080806020026020016040519081016040528093929190818152602001838360200280828437820191505050505050919080359060200190820180359060200190808060200260200160405190810160405280939291908181526020018383602002808284378201915050505050509190505061179c565b005b3415610ad857600080fd5b610c1d60048080359060200190820180359060200190808060200260200160405190810160405280939291908181526020016000905b82821015610b5357848483905060a002016005806020026040519081016040528092919082600560200280828437820191505050505081526020019060010190610b0e565b5050505050919080359060200190820180359060200190808060200260200160405190810160405280939291908181526020016000905b82821015610bcf57848483905060c002016006806020026040519081016040528092919082600660200280828437820191505050505081526020019060010190610b8a565b5050505050919080359060200190820180359060200190808060200260200160405190810160405280939291908181526020018383602002808284378201915050505050509190505061185e565b005b3415610c2a57600080fd5b610cc96004808060a001906005806020026040519081016040528092919082600560200280828437820191505050505091908060c001906006806020026040519081016040528092919082600660200280828437820191505050505091908035906020019091908035151590602001909190803560ff1690602001909190803560001916906020019091908035600019169060200190919050506118d3565b6040518082815260200191505060405180910390f35b3415610cea57600080fd5b610d4f6004808060a001906005806020026040519081016040528092919082600560200280828437820191505050505091908060c001906006806020026040519081016040528092919082600660200280828437820191505050505091905050612073565b60405180826000191660001916815260200191505060405180910390f35b3415610d7857600080fd5b610d8061231f565b604051808261ffff1661ffff16815260200191505060405180910390f35b3415610da957600080fd5b610db1612325565b6040518080602001828103825283818151815260200191508051906020019080838360005b83811015610df25780820151818401525b602081019050610dd6565b50505050905090810190601f168015610e1f5780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b60008060008486850991506000821415610e4a5760009250610e73565b610e69610e5a83620f424061235e565b610e64888761235e565b612392565b90506103e8811192505b50509392505050565b60026020528060005260406000206000915090505481565b60036020528060005260406000206000915090505481565b6000806000809150600090505b895181101561100257896000815181101515610ed157fe5b906020019060200201516003600581101515610ee957fe5b602002015173ffffffffffffffffffffffffffffffffffffffff168a82815181101515610f1257fe5b906020019060200201516003600581101515610f2a57fe5b602002015173ffffffffffffffffffffffffffffffffffffffff16141515610f5157600080fd5b610fe582610fe08c84815181101515610f6657fe5b906020019060200201518c85815181101515610f7e57fe5b90602001906020020151610f928d886123ae565b8c8c88815181101515610fa157fe5b906020019060200201518c89815181101515610fb957fe5b906020019060200201518c8a815181101515610fd157fe5b906020019060200201516118d3565b6123c8565b915087821415610ff457611002565b5b8080600101915050610eb9565b8192505b5050979650505050505050565b600061101d612a8c565b6000806101606040519081016040528088600060058110151561103c57fe5b602002015173ffffffffffffffffffffffffffffffffffffffff16815260200188600160058110151561106b57fe5b602002015173ffffffffffffffffffffffffffffffffffffffff16815260200188600260058110151561109a57fe5b602002015173ffffffffffffffffffffffffffffffffffffffff1681526020018860036005811015156110c957fe5b602002015173ffffffffffffffffffffffffffffffffffffffff1681526020018860046005811015156110f857fe5b602002015173ffffffffffffffffffffffffffffffffffffffff16815260200187600060068110151561112757fe5b6020020151815260200187600160068110151561114057fe5b6020020151815260200187600260068110151561115957fe5b6020020151815260200187600360068110151561117257fe5b6020020151815260200187600460068110151561118b57fe5b6020020151815260200161119f8989612073565b6000191681525092503373ffffffffffffffffffffffffffffffffffffffff16836000015173ffffffffffffffffffffffffffffffffffffffff161415156111e657600080fd5b60008360a001511180156111fe575060008360c00151115b801561120a5750600085115b151561121557600080fd5b8261012001514210151561127257826101400151600019166000600381111561123a57fe5b60ff167f36d86c59e00bd73dc19ba3adfe068e4b64ac7e92be35546adeddf1b956a87e9060405160405180910390a3600093506114f1565b61128d8360c00151611288856101400151611605565b6123ae565b915061129985836123e7565b905060008114156112f35782610140015160001916600160038111156112bb57fe5b60ff167f36d86c59e00bd73dc19ba3adfe068e4b64ac7e92be35546adeddf1b956a87e9060405160405180910390a3600093506114f1565b61131d600360008561014001516000191660001916815260200190815260200160002054826123c8565b60036000856101400151600019166000191681526020019081526020016000208190555082604001518360600151604051808373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166c010000000000000000000000000281526014018273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166c0100000000000000000000000002815260140192505050604051809103902060001916836080015173ffffffffffffffffffffffffffffffffffffffff16846000015173ffffffffffffffffffffffffffffffffffffffff167f67d66f160bc93d925d05dae1794c90d2d6d6688b29b84ff069398a9b0458713186604001518760600151611455878a60c001518b60a00151611757565b878a6101400151604051808673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020018573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200184815260200183815260200182600019166000191681526020019550505050505060405180910390a48093505b5050509392505050565b6000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b60008090505b86518110156115d5576115c7878281518110151561154057fe5b90602001906020020151878381518110151561155857fe5b90602001906020020151878481518110151561157057fe5b90602001906020020151878581518110151561158857fe5b9060200190602002015187868151811015156115a057fe5b9060200190602002015187878151811015156115b857fe5b906020019060200201516115df565b5b8080600101915050611526565b5b50505050505050565b836115f087878760008888886118d3565b1415156115fc57600080fd5b5b505050505050565b600061164760026000846000191660001916815260200190815260200160002054600360008560001916600019168152602001908152602001600020546123c8565b90505b919050565b600060018560405180807f19457468657265756d205369676e6564204d6573736167653a0a333200000000815250601c0182600019166000191681526020019150506040518091039020858585604051600081526020016040526000604051602001526040518085600019166000191681526020018460ff1660ff16815260200183600019166000191681526020018260001916600019168152602001945050505050602060405160208103908084039060008661646e5a03f1151561171457600080fd5b50506020604051035173ffffffffffffffffffffffffffffffffffffffff168673ffffffffffffffffffffffffffffffffffffffff161490505b95945050505050565b600061176c611766858461235e565b84612392565b90505b9392505050565b600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b60008090505b87518110156118535761184488828151811015156117bc57fe5b9060200190602002015188838151811015156117d457fe5b9060200190602002015188848151811015156117ec57fe5b9060200190602002015188888681518110151561180557fe5b90602001906020020151888781518110151561181d57fe5b90602001906020020151888881518110151561183557fe5b906020019060200201516118d3565b505b80806001019150506117a2565b5b5050505050505050565b60008090505b83518110156118cc576118bd848281518110151561187e57fe5b90602001906020020151848381518110151561189657fe5b9060200190602002015184848151811015156118ae57fe5b90602001906020020151611013565b505b8080600101915050611864565b5b50505050565b60006118dd612a8c565b600080600080610160604051908101604052808e60006005811015156118ff57fe5b602002015173ffffffffffffffffffffffffffffffffffffffff1681526020018e600160058110151561192e57fe5b602002015173ffffffffffffffffffffffffffffffffffffffff1681526020018e600260058110151561195d57fe5b602002015173ffffffffffffffffffffffffffffffffffffffff1681526020018e600360058110151561198c57fe5b602002015173ffffffffffffffffffffffffffffffffffffffff1681526020018e60046005811015156119bb57fe5b602002015173ffffffffffffffffffffffffffffffffffffffff1681526020018d60006006811015156119ea57fe5b602002015181526020018d6001600681101515611a0357fe5b602002015181526020018d6002600681101515611a1c57fe5b602002015181526020018d6003600681101515611a3557fe5b602002015181526020018d6004600681101515611a4e57fe5b60200201518152602001611a628f8f612073565b600019168152509450600073ffffffffffffffffffffffffffffffffffffffff16856020015173ffffffffffffffffffffffffffffffffffffffff161480611ad957503373ffffffffffffffffffffffffffffffffffffffff16856020015173ffffffffffffffffffffffffffffffffffffffff16145b1515611ae457600080fd5b60008560a00151118015611afc575060008560c00151115b8015611b08575060008b115b1515611b1357600080fd5b611b2985600001518661014001518b8b8b61164f565b1515611b3457600080fd5b84610120015142101515611b91578461014001516000191660006003811115611b5957fe5b60ff167f36d86c59e00bd73dc19ba3adfe068e4b64ac7e92be35546adeddf1b956a87e9060405160405180910390a360009550612063565b611bac8560c00151611ba7876101400151611605565b6123ae565b9350611bb88b856123e7565b95506000861415611c12578461014001516000191660016003811115611bda57fe5b60ff167f36d86c59e00bd73dc19ba3adfe068e4b64ac7e92be35546adeddf1b956a87e9060405160405180910390a360009550612063565b611c25868660c001518760a00151610e2d565b15611c79578461014001516000191660026003811115611c4157fe5b60ff167f36d86c59e00bd73dc19ba3adfe068e4b64ac7e92be35546adeddf1b956a87e9060405160405180910390a360009550612063565b89158015611c8e5750611c8c8587612401565b155b15611ce15784610140015160001916600380811115611ca957fe5b60ff167f36d86c59e00bd73dc19ba3adfe068e4b64ac7e92be35546adeddf1b956a87e9060405160405180910390a360009550612063565b611cf4868660c001518760a00151611757565b9250611d20600260008761014001516000191660001916815260200190815260200160002054876123c8565b600260008761014001516000191660001916815260200190815260200160002081905550611d58856040015186600001513386612751565b1515611d6357600080fd5b611d77856060015133876000015189612751565b1515611d8257600080fd5b600073ffffffffffffffffffffffffffffffffffffffff16856080015173ffffffffffffffffffffffffffffffffffffffff16141515611e815760008560e001511115611e1f57611ddc868660c001518760e00151611757565b9150611e136000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff168660000151876080015185612751565b1515611e1e57600080fd5b5b60008561010001511115611e8057611e41868660c00151876101000151611757565b9050611e746000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff1633876080015184612751565b1515611e7f57600080fd5b5b5b84604001518560600151604051808373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166c010000000000000000000000000281526014018273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166c0100000000000000000000000002815260140192505050604051809103902060001916856080015173ffffffffffffffffffffffffffffffffffffffff16866000015173ffffffffffffffffffffffffffffffffffffffff167f0d0b9391970d9a25552f37d436d2aae2925e2bfe1b2a923754bada030c498cb33389604001518a60600151898d8a8a8f6101400151604051808973ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020018873ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020018773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200186815260200185815260200184815260200183815260200182600019166000191681526020019850505050505050505060405180910390a48595505b5050505050979650505050505050565b60003083600060058110151561208557fe5b602002015184600160058110151561209957fe5b60200201518560026005811015156120ad57fe5b60200201518660036005811015156120c157fe5b60200201518760046005811015156120d557fe5b60200201518760006006811015156120e957fe5b60200201518860016006811015156120fd57fe5b602002015189600260068110151561211157fe5b60200201518a600360068110151561212557fe5b60200201518b600460068110151561213957fe5b60200201518c600560068110151561214d57fe5b6020020151604051808d73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166c010000000000000000000000000281526014018c73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166c010000000000000000000000000281526014018b73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166c010000000000000000000000000281526014018a73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166c010000000000000000000000000281526014018973ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166c010000000000000000000000000281526014018873ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166c010000000000000000000000000281526014018781526020018681526020018581526020018481526020018381526020018281526020019c50505050505050505050505050604051809103902090505b92915050565b61138781565b6040805190810160405280600581526020017f312e302e3000000000000000000000000000000000000000000000000000000081525081565b6000808284029050600084148061237f575082848281151561237c57fe5b04145b151561238757fe5b8091505b5092915050565b60008082848115156123a057fe5b0490508091505b5092915050565b60008282111515156123bc57fe5b81830390505b92915050565b60008082840190508381101515156123dc57fe5b8091505b5092915050565b60008183106123f657816123f8565b825b90505b92915050565b60008060008060008060008060003397506124258a8c60c001518d60a00151611757565b9650600073ffffffffffffffffffffffffffffffffffffffff168b6080015173ffffffffffffffffffffffffffffffffffffffff161415156126d2576000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168b6040015173ffffffffffffffffffffffffffffffffffffffff161495506000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168b6060015173ffffffffffffffffffffffffffffffffffffffff161494506125208a8c60c001518d60e00151611757565b93506125368a8c60c001518d6101000151611757565b925085612543578361254e565b61254d87856123c8565b5b91508461255b5782612566565b6125658a846123c8565b5b9050816125986000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff168d600001516128ae565b10806125d15750816125cf6000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff168d60000151612972565b105b806126055750806126036000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff168a6128ae565b105b806126395750806126376000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff168a612972565b105b156126475760009850612743565b851580156126805750866126638c604001518d600001516128ae565b108061267f57508661267d8c604001518d60000151612972565b105b5b1561268e5760009850612743565b841580156126bf5750896126a68c606001518a6128ae565b10806126be5750896126bc8c606001518a612972565b105b5b156126cd5760009850612743565b61273e565b866126e58c604001518d600001516128ae565b10806127015750866126ff8c604001518d60000151612972565b105b806127185750896127168c606001518a6128ae565b105b8061272f57508961272d8c606001518a612972565b105b1561273d5760009850612743565b5b600198505b505050505050505092915050565b6000600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166315dacbea868686866000604051602001526040518563ffffffff167c0100000000000000000000000000000000000000000000000000000000028152600401808573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020018473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020018373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001828152602001945050505050602060405180830381600087803b151561288857600080fd5b6102c65a03f1151561289957600080fd5b5050506040518051905090505b949350505050565b60008273ffffffffffffffffffffffffffffffffffffffff166370a0823161138761ffff16846040518363ffffffff167c0100000000000000000000000000000000000000000000000000000000028152600401808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001915050602060405180830381600088803b151561295157600080fd5b87f1151561295e57600080fd5b505050506040518051905090505b92915050565b60008273ffffffffffffffffffffffffffffffffffffffff1663dd62ed3e61138761ffff1684600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff166040518463ffffffff167c0100000000000000000000000000000000000000000000000000000000028152600401808373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020018273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200192505050602060405180830381600088803b1515612a6b57600080fd5b87f11515612a7857600080fd5b505050506040518051905090505b92915050565b61016060405190810160405280600073ffffffffffffffffffffffffffffffffffffffff168152602001600073ffffffffffffffffffffffffffffffffffffffff168152602001600073ffffffffffffffffffffffffffffffffffffffff168152602001600073ffffffffffffffffffffffffffffffffffffffff168152602001600073ffffffffffffffffffffffffffffffffffffffff16815260200160008152602001600081526020016000815260200160008152602001600081526020016000801916815250905600a165627a7a72305820df5cabdc3a116e993e10bfb14823d18d9b798038d4c463a1703f9a584c456b7e0029'; + '0x6060604052341561000f57600080fd5b604051604080612c2583398101604052808051906020019091908051906020019091905050816000806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555080600160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055505050612b5f806100c66000396000f3006060604052600436106100fc576000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff16806314df96ee14610101578063288cdc911461014e5780632ac1262214610189578063363349be146101c4578063394c21e7146103be5780633b30ba591461044d5780634f150787146104a2578063741bcc93146106b45780637e9abb50146107555780638163681e1461079057806398024a8b14610814578063add1cbc51461085d578063b7b2c7d6146108b2578063baa0181d14610acf578063bc61394a14610c21578063cfc4d0ec14610ce1578063f06bbf7514610d6f578063ffa1ad7414610da0575b600080fd5b341561010c57600080fd5b6101346004808035906020019091908035906020019091908035906020019091905050610e2e565b604051808215151515815260200191505060405180910390f35b341561015957600080fd5b610173600480803560001916906020019091905050610e86565b6040518082815260200191505060405180910390f35b341561019457600080fd5b6101ae600480803560001916906020019091905050610e9e565b6040518082815260200191505060405180910390f35b34156101cf57600080fd5b6103a860048080359060200190820180359060200190808060200260200160405190810160405280939291908181526020016000905b8282101561024a57848483905060a002016005806020026040519081016040528092919082600560200280828437820191505050505081526020019060010190610205565b5050505050919080359060200190820180359060200190808060200260200160405190810160405280939291908181526020016000905b828210156102c657848483905060c002016006806020026040519081016040528092919082600660200280828437820191505050505081526020019060010190610281565b5050505050919080359060200190919080351515906020019091908035906020019082018035906020019080806020026020016040519081016040528093929190818152602001838360200280828437820191505050505050919080359060200190820180359060200190808060200260200160405190810160405280939291908181526020018383602002808284378201915050505050509190803590602001908201803590602001908080602002602001604051908101604052809392919081815260200183836020028082843782019150505050505091905050610eb6565b6040518082815260200191505060405180910390f35b34156103c957600080fd5b6104376004808060a001906005806020026040519081016040528092919082600560200280828437820191505050505091908060c00190600680602002604051908101604052809291908260066020028082843782019150505050509190803590602001909190505061101b565b6040518082815260200191505060405180910390f35b341561045857600080fd5b610460611503565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b34156104ad57600080fd5b6106b260048080359060200190820180359060200190808060200260200160405190810160405280939291908181526020016000905b8282101561052857848483905060a0020160058060200260405190810160405280929190826005602002808284378201915050505050815260200190600101906104e3565b5050505050919080359060200190820180359060200190808060200260200160405190810160405280939291908181526020016000905b828210156105a457848483905060c00201600680602002604051908101604052809291908260066020028082843782019150505050508152602001906001019061055f565b50505050509190803590602001908201803590602001908080602002602001604051908101604052809392919081815260200183836020028082843782019150505050505091908035906020019082018035906020019080806020026020016040519081016040528093929190818152602001838360200280828437820191505050505050919080359060200190820180359060200190808060200260200160405190810160405280939291908181526020018383602002808284378201915050505050509190803590602001908201803590602001908080602002602001604051908101604052809392919081815260200183836020028082843782019150505050505091905050611528565b005b34156106bf57600080fd5b6107536004808060a001906005806020026040519081016040528092919082600560200280828437820191505050505091908060c00190600680602002604051908101604052809291908260066020028082843782019150505050509190803590602001909190803560ff1690602001909190803560001916906020019091908035600019169060200190919050506115e5565b005b341561076057600080fd5b61077a60048080356000191690602001909190505061160a565b6040518082815260200191505060405180910390f35b341561079b57600080fd5b6107fa600480803573ffffffffffffffffffffffffffffffffffffffff169060200190919080356000191690602001909190803560ff169060200190919080356000191690602001909190803560001916906020019091905050611653565b604051808215151515815260200191505060405180910390f35b341561081f57600080fd5b610847600480803590602001909190803590602001909190803590602001909190505061174d565b6040518082815260200191505060405180910390f35b341561086857600080fd5b61087061176b565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b34156108bd57600080fd5b610acd60048080359060200190820180359060200190808060200260200160405190810160405280939291908181526020016000905b8282101561093857848483905060a0020160058060200260405190810160405280929190826005602002808284378201915050505050815260200190600101906108f3565b5050505050919080359060200190820180359060200190808060200260200160405190810160405280939291908181526020016000905b828210156109b457848483905060c00201600680602002604051908101604052809291908260066020028082843782019150505050508152602001906001019061096f565b505050505091908035906020019082018035906020019080806020026020016040519081016040528093929190818152602001838360200280828437820191505050505050919080351515906020019091908035906020019082018035906020019080806020026020016040519081016040528093929190818152602001838360200280828437820191505050505050919080359060200190820180359060200190808060200260200160405190810160405280939291908181526020018383602002808284378201915050505050509190803590602001908201803590602001908080602002602001604051908101604052809392919081815260200183836020028082843782019150505050505091905050611791565b005b3415610ada57600080fd5b610c1f60048080359060200190820180359060200190808060200260200160405190810160405280939291908181526020016000905b82821015610b5557848483905060a002016005806020026040519081016040528092919082600560200280828437820191505050505081526020019060010190610b10565b5050505050919080359060200190820180359060200190808060200260200160405190810160405280939291908181526020016000905b82821015610bd157848483905060c002016006806020026040519081016040528092919082600660200280828437820191505050505081526020019060010190610b8c565b50505050509190803590602001908201803590602001908080602002602001604051908101604052809392919081815260200183836020028082843782019150505050505091905050611851565b005b3415610c2c57600080fd5b610ccb6004808060a001906005806020026040519081016040528092919082600560200280828437820191505050505091908060c001906006806020026040519081016040528092919082600660200280828437820191505050505091908035906020019091908035151590602001909190803560ff1690602001909190803560001916906020019091908035600019169060200190919050506118c4565b6040518082815260200191505060405180910390f35b3415610cec57600080fd5b610d516004808060a001906005806020026040519081016040528092919082600560200280828437820191505050505091908060c001906006806020026040519081016040528092919082600660200280828437820191505050505091905050612064565b60405180826000191660001916815260200191505060405180910390f35b3415610d7a57600080fd5b610d8261230f565b604051808261ffff1661ffff16815260200191505060405180910390f35b3415610dab57600080fd5b610db3612315565b6040518080602001828103825283818151815260200191508051906020019080838360005b83811015610df3578082015181840152602081019050610dd8565b50505050905090810190601f168015610e205780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b600080600084801515610e3d57fe5b86850991506000821415610e545760009250610e7d565b610e73610e6483620f424061234e565b610e6e888761234e565b612381565b90506103e8811192505b50509392505050565b60026020528060005260406000206000915090505481565b60036020528060005260406000206000915090505481565b6000806000809150600090505b895181101561100b57896000815181101515610edb57fe5b906020019060200201516003600581101515610ef357fe5b602002015173ffffffffffffffffffffffffffffffffffffffff168a82815181101515610f1c57fe5b906020019060200201516003600581101515610f3457fe5b602002015173ffffffffffffffffffffffffffffffffffffffff16141515610f5b57600080fd5b610fef82610fea8c84815181101515610f7057fe5b906020019060200201518c85815181101515610f8857fe5b90602001906020020151610f9c8d8861239c565b8c8c88815181101515610fab57fe5b906020019060200201518c89815181101515610fc357fe5b906020019060200201518c8a815181101515610fdb57fe5b906020019060200201516118c4565b6123b5565b915087821415610ffe5761100b565b8080600101915050610ec3565b8192505050979650505050505050565b6000611025612a67565b6000806101606040519081016040528088600060058110151561104457fe5b602002015173ffffffffffffffffffffffffffffffffffffffff16815260200188600160058110151561107357fe5b602002015173ffffffffffffffffffffffffffffffffffffffff1681526020018860026005811015156110a257fe5b602002015173ffffffffffffffffffffffffffffffffffffffff1681526020018860036005811015156110d157fe5b602002015173ffffffffffffffffffffffffffffffffffffffff16815260200188600460058110151561110057fe5b602002015173ffffffffffffffffffffffffffffffffffffffff16815260200187600060068110151561112f57fe5b6020020151815260200187600160068110151561114857fe5b6020020151815260200187600260068110151561116157fe5b6020020151815260200187600360068110151561117a57fe5b6020020151815260200187600460068110151561119357fe5b602002015181526020016111a78989612064565b6000191681525092503373ffffffffffffffffffffffffffffffffffffffff16836000015173ffffffffffffffffffffffffffffffffffffffff161415156111ee57600080fd5b60008360a00151118015611206575060008360c00151115b80156112125750600085115b151561121d57600080fd5b8261012001514210151561127a57826101400151600019166000600381111561124257fe5b60ff167f36d86c59e00bd73dc19ba3adfe068e4b64ac7e92be35546adeddf1b956a87e9060405160405180910390a3600093506114f9565b6112958360c0015161129085610140015161160a565b61239c565b91506112a185836123d3565b905060008114156112fb5782610140015160001916600160038111156112c357fe5b60ff167f36d86c59e00bd73dc19ba3adfe068e4b64ac7e92be35546adeddf1b956a87e9060405160405180910390a3600093506114f9565b611325600360008561014001516000191660001916815260200190815260200160002054826123b5565b60036000856101400151600019166000191681526020019081526020016000208190555082604001518360600151604051808373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166c010000000000000000000000000281526014018273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166c0100000000000000000000000002815260140192505050604051809103902060001916836080015173ffffffffffffffffffffffffffffffffffffffff16846000015173ffffffffffffffffffffffffffffffffffffffff167f67d66f160bc93d925d05dae1794c90d2d6d6688b29b84ff069398a9b045871318660400151876060015161145d878a60c001518b60a0015161174d565b878a6101400151604051808673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020018573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200184815260200183815260200182600019166000191681526020019550505050505060405180910390a48093505b5050509392505050565b6000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b60008090505b86518110156115dc576115cf878281518110151561154857fe5b90602001906020020151878381518110151561156057fe5b90602001906020020151878481518110151561157857fe5b90602001906020020151878581518110151561159057fe5b9060200190602002015187868151811015156115a857fe5b9060200190602002015187878151811015156115c057fe5b906020019060200201516115e5565b808060010191505061152e565b50505050505050565b836115f687878760008888886118c4565b14151561160257600080fd5b505050505050565b600061164c60026000846000191660001916815260200190815260200160002054600360008560001916600019168152602001908152602001600020546123b5565b9050919050565b600060018560405180807f19457468657265756d205369676e6564204d6573736167653a0a333200000000815250601c0182600019166000191681526020019150506040518091039020858585604051600081526020016040526040518085600019166000191681526020018460ff1660ff1681526020018360001916600019168152602001826000191660001916815260200194505050505060206040516020810390808403906000865af1151561170b57600080fd5b50506020604051035173ffffffffffffffffffffffffffffffffffffffff168673ffffffffffffffffffffffffffffffffffffffff1614905095945050505050565b600061176261175c858461234e565b84612381565b90509392505050565b600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b60008090505b87518110156118475761183988828151811015156117b157fe5b9060200190602002015188838151811015156117c957fe5b9060200190602002015188848151811015156117e157fe5b906020019060200201518888868151811015156117fa57fe5b90602001906020020151888781518110151561181257fe5b90602001906020020151888881518110151561182a57fe5b906020019060200201516118c4565b508080600101915050611797565b5050505050505050565b60008090505b83518110156118be576118b0848281518110151561187157fe5b90602001906020020151848381518110151561188957fe5b9060200190602002015184848151811015156118a157fe5b9060200190602002015161101b565b508080600101915050611857565b50505050565b60006118ce612a67565b600080600080610160604051908101604052808e60006005811015156118f057fe5b602002015173ffffffffffffffffffffffffffffffffffffffff1681526020018e600160058110151561191f57fe5b602002015173ffffffffffffffffffffffffffffffffffffffff1681526020018e600260058110151561194e57fe5b602002015173ffffffffffffffffffffffffffffffffffffffff1681526020018e600360058110151561197d57fe5b602002015173ffffffffffffffffffffffffffffffffffffffff1681526020018e60046005811015156119ac57fe5b602002015173ffffffffffffffffffffffffffffffffffffffff1681526020018d60006006811015156119db57fe5b602002015181526020018d60016006811015156119f457fe5b602002015181526020018d6002600681101515611a0d57fe5b602002015181526020018d6003600681101515611a2657fe5b602002015181526020018d6004600681101515611a3f57fe5b60200201518152602001611a538f8f612064565b600019168152509450600073ffffffffffffffffffffffffffffffffffffffff16856020015173ffffffffffffffffffffffffffffffffffffffff161480611aca57503373ffffffffffffffffffffffffffffffffffffffff16856020015173ffffffffffffffffffffffffffffffffffffffff16145b1515611ad557600080fd5b60008560a00151118015611aed575060008560c00151115b8015611af9575060008b115b1515611b0457600080fd5b611b1a85600001518661014001518b8b8b611653565b1515611b2557600080fd5b84610120015142101515611b82578461014001516000191660006003811115611b4a57fe5b60ff167f36d86c59e00bd73dc19ba3adfe068e4b64ac7e92be35546adeddf1b956a87e9060405160405180910390a360009550612054565b611b9d8560c00151611b9887610140015161160a565b61239c565b9350611ba98b856123d3565b95506000861415611c03578461014001516000191660016003811115611bcb57fe5b60ff167f36d86c59e00bd73dc19ba3adfe068e4b64ac7e92be35546adeddf1b956a87e9060405160405180910390a360009550612054565b611c16868660c001518760a00151610e2e565b15611c6a578461014001516000191660026003811115611c3257fe5b60ff167f36d86c59e00bd73dc19ba3adfe068e4b64ac7e92be35546adeddf1b956a87e9060405160405180910390a360009550612054565b89158015611c7f5750611c7d85876123ec565b155b15611cd25784610140015160001916600380811115611c9a57fe5b60ff167f36d86c59e00bd73dc19ba3adfe068e4b64ac7e92be35546adeddf1b956a87e9060405160405180910390a360009550612054565b611ce5868660c001518760a0015161174d565b9250611d11600260008761014001516000191660001916815260200190815260200160002054876123b5565b600260008761014001516000191660001916815260200190815260200160002081905550611d4985604001518660000151338661273c565b1515611d5457600080fd5b611d6885606001513387600001518961273c565b1515611d7357600080fd5b600073ffffffffffffffffffffffffffffffffffffffff16856080015173ffffffffffffffffffffffffffffffffffffffff16141515611e725760008560e001511115611e1057611dcd868660c001518760e0015161174d565b9150611e046000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff16866000015187608001518561273c565b1515611e0f57600080fd5b5b60008561010001511115611e7157611e32868660c0015187610100015161174d565b9050611e656000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff163387608001518461273c565b1515611e7057600080fd5b5b5b84604001518560600151604051808373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166c010000000000000000000000000281526014018273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166c0100000000000000000000000002815260140192505050604051809103902060001916856080015173ffffffffffffffffffffffffffffffffffffffff16866000015173ffffffffffffffffffffffffffffffffffffffff167f0d0b9391970d9a25552f37d436d2aae2925e2bfe1b2a923754bada030c498cb33389604001518a60600151898d8a8a8f6101400151604051808973ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020018873ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020018773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200186815260200185815260200184815260200183815260200182600019166000191681526020019850505050505050505060405180910390a48595505b5050505050979650505050505050565b60003083600060058110151561207657fe5b602002015184600160058110151561208a57fe5b602002015185600260058110151561209e57fe5b60200201518660036005811015156120b257fe5b60200201518760046005811015156120c657fe5b60200201518760006006811015156120da57fe5b60200201518860016006811015156120ee57fe5b602002015189600260068110151561210257fe5b60200201518a600360068110151561211657fe5b60200201518b600460068110151561212a57fe5b60200201518c600560068110151561213e57fe5b6020020151604051808d73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166c010000000000000000000000000281526014018c73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166c010000000000000000000000000281526014018b73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166c010000000000000000000000000281526014018a73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166c010000000000000000000000000281526014018973ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166c010000000000000000000000000281526014018873ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166c010000000000000000000000000281526014018781526020018681526020018581526020018481526020018381526020018281526020019c505050505050505050505050506040518091039020905092915050565b61138781565b6040805190810160405280600581526020017f312e302e3000000000000000000000000000000000000000000000000000000081525081565b6000808284029050600084148061236f575082848281151561236c57fe5b04145b151561237757fe5b8091505092915050565b600080828481151561238f57fe5b0490508091505092915050565b60008282111515156123aa57fe5b818303905092915050565b60008082840190508381101515156123c957fe5b8091505092915050565b60008183106123e257816123e4565b825b905092915050565b60008060008060008060008060003397506124108a8c60c001518d60a0015161174d565b9650600073ffffffffffffffffffffffffffffffffffffffff168b6080015173ffffffffffffffffffffffffffffffffffffffff161415156126bd576000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168b6040015173ffffffffffffffffffffffffffffffffffffffff161495506000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168b6060015173ffffffffffffffffffffffffffffffffffffffff1614945061250b8a8c60c001518d60e0015161174d565b93506125218a8c60c001518d610100015161174d565b92508561252e5783612539565b61253887856123b5565b5b9150846125465782612551565b6125508a846123b5565b5b9050816125836000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff168d6000015161288b565b10806125bc5750816125ba6000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff168d6000015161294e565b105b806125f05750806125ee6000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff168a61288b565b105b806126245750806126226000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff168a61294e565b105b15612632576000985061272e565b8515801561266b57508661264e8c604001518d6000015161288b565b108061266a5750866126688c604001518d6000015161294e565b105b5b15612679576000985061272e565b841580156126aa5750896126918c606001518a61288b565b10806126a95750896126a78c606001518a61294e565b105b5b156126b8576000985061272e565b612729565b866126d08c604001518d6000015161288b565b10806126ec5750866126ea8c604001518d6000015161294e565b105b806127035750896127018c606001518a61288b565b105b8061271a5750896127188c606001518a61294e565b105b15612728576000985061272e565b5b600198505b505050505050505092915050565b6000600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166315dacbea868686866040518563ffffffff167c0100000000000000000000000000000000000000000000000000000000028152600401808573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020018473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020018373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001828152602001945050505050602060405180830381600087803b151561286a57600080fd5b5af1151561287757600080fd5b505050604051805190509050949350505050565b60008273ffffffffffffffffffffffffffffffffffffffff166370a0823161138761ffff16846040518363ffffffff167c0100000000000000000000000000000000000000000000000000000000028152600401808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001915050602060405180830381600088803b151561292e57600080fd5b87f1151561293b57600080fd5b5050505060405180519050905092915050565b60008273ffffffffffffffffffffffffffffffffffffffff1663dd62ed3e61138761ffff1684600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff166040518463ffffffff167c0100000000000000000000000000000000000000000000000000000000028152600401808373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020018273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200192505050602060405180830381600088803b1515612a4757600080fd5b87f11515612a5457600080fd5b5050505060405180519050905092915050565b61016060405190810160405280600073ffffffffffffffffffffffffffffffffffffffff168152602001600073ffffffffffffffffffffffffffffffffffffffff168152602001600073ffffffffffffffffffffffffffffffffffffffff168152602001600073ffffffffffffffffffffffffffffffffffffffff168152602001600073ffffffffffffffffffffffffffffffffffffffff16815260200160008152602001600081526020016000815260200160008152602001600081526020016000801916815250905600a165627a7a72305820df5cabdc3a116e993e10bfb14823d18d9b798038d4c463a1703f9a584c456b7e0029'; diff --git a/packages/deployer/test/util/constants.ts b/packages/deployer/test/util/constants.ts index 5385b8d17..b93081a80 100644 --- a/packages/deployer/test/util/constants.ts +++ b/packages/deployer/test/util/constants.ts @@ -2,7 +2,6 @@ import { BigNumber } from '@0xproject/utils'; export const constants = { networkId: 0, - jsonrpcUrl: 'http://localhost:8545', optimizerEnabled: false, gasPrice: new BigNumber(20000000000), timeoutMs: 30000, diff --git a/packages/deployer/test/util/provider.ts b/packages/deployer/test/util/provider.ts new file mode 100644 index 000000000..e0fcb362a --- /dev/null +++ b/packages/deployer/test/util/provider.ts @@ -0,0 +1,9 @@ +import { web3Factory } from '@0xproject/dev-utils'; +import { Provider } from '@0xproject/types'; +import * as Web3 from 'web3'; + +const providerConfigs = { shouldUseInProcessGanache: true }; +const web3Instance = web3Factory.create(providerConfigs); +const provider: Provider = web3Instance.currentProvider; + +export { provider }; diff --git a/packages/dev-utils/CHANGELOG.json b/packages/dev-utils/CHANGELOG.json index 64ef4b000..8faf71d6a 100644 --- a/packages/dev-utils/CHANGELOG.json +++ b/packages/dev-utils/CHANGELOG.json @@ -1,5 +1,23 @@ [ { + "version": "0.3.6", + "changes": [ + { + "note": "Allow an rpcURL to be set in Web3Config (for testnet RPC endpoints)", + "pr": 524 + } + ] + }, + { + "timestamp": 1523462196, + "version": "0.3.5", + "changes": [ + { + "note": "Dependencies updated" + } + ] + }, + { "timestamp": 1522673609, "version": "0.3.4", "changes": [ @@ -24,7 +42,7 @@ "note": "Reduce npm package size by adding an `.npmignore` file." }, { - "note": "Move `@0xproject/web3_wrapper` to dependencies from devDependencies." + "note": "Move `@0xproject/web3-wrapper` to dependencies from devDependencies." } ], "timestamp": 1521298800 diff --git a/packages/dev-utils/CHANGELOG.md b/packages/dev-utils/CHANGELOG.md index 2e3953750..b63fad04c 100644 --- a/packages/dev-utils/CHANGELOG.md +++ b/packages/dev-utils/CHANGELOG.md @@ -5,6 +5,10 @@ Edit the package's CHANGELOG.json file only. CHANGELOG +## v0.3.5 - _April 11, 2018_ + + * Dependencies updated + ## v0.3.4 - _April 2, 2018_ * Dependencies updated @@ -16,7 +20,7 @@ CHANGELOG ## v0.3.1 - _March 17, 2018_ * Reduce npm package size by adding an `.npmignore` file. - * Move `@0xproject/web3_wrapper` to dependencies from devDependencies. + * Move `@0xproject/web3-wrapper` to dependencies from devDependencies. ## v0.3.0 - _March 17, 2018_ diff --git a/packages/dev-utils/package.json b/packages/dev-utils/package.json index dd7712065..5161e66e6 100644 --- a/packages/dev-utils/package.json +++ b/packages/dev-utils/package.json @@ -1,6 +1,6 @@ { "name": "@0xproject/dev-utils", - "version": "0.3.4", + "version": "0.3.5", "description": "0x dev TS utils", "main": "lib/src/index.js", "types": "lib/src/index.d.ts", @@ -26,8 +26,8 @@ }, "homepage": "https://github.com/0xProject/0x-monorepo/packages/dev-utils/README.md", "devDependencies": { - "@0xproject/monorepo-scripts": "^0.1.16", - "@0xproject/tslint-config": "^0.4.14", + "@0xproject/monorepo-scripts": "^0.1.17", + "@0xproject/tslint-config": "^0.4.15", "@types/lodash": "4.14.104", "@types/mocha": "^2.2.42", "chai": "^4.0.1", @@ -40,11 +40,11 @@ "typescript": "2.7.1" }, "dependencies": { - "@0xproject/sol-cov": "^0.0.6", - "@0xproject/subproviders": "^0.8.4", - "@0xproject/types": "^0.5.0", - "@0xproject/typescript-typings": "^0.0.3", - "@0xproject/web3-wrapper": "^0.5.0", + "@0xproject/sol-cov": "^0.0.7", + "@0xproject/subproviders": "^0.8.5", + "@0xproject/types": "^0.6.0", + "@0xproject/typescript-typings": "^0.1.0", + "@0xproject/web3-wrapper": "^0.6.0", "lodash": "^4.17.4", "web3": "^0.20.0", "web3-provider-engine": "^13.0.1" diff --git a/packages/dev-utils/src/coverage.ts b/packages/dev-utils/src/coverage.ts index 40bb47e2d..67c87ec30 100644 --- a/packages/dev-utils/src/coverage.ts +++ b/packages/dev-utils/src/coverage.ts @@ -13,8 +13,8 @@ export const coverage = { return coverageSubprovider; }, _getCoverageSubprovider(): CoverageSubprovider { - const artifactsPath = './src/artifacts'; - const contractsPath = './src/contracts'; + const artifactsPath = '../migrations/src/artifacts'; + const contractsPath = 'src/contracts'; const networkId = 50; const defaultFromAddress = constants.TESTRPC_FIRST_ADDRESS; return new CoverageSubprovider(artifactsPath, contractsPath, networkId, defaultFromAddress); diff --git a/packages/dev-utils/src/web3_factory.ts b/packages/dev-utils/src/web3_factory.ts index f45c36930..68348d671 100644 --- a/packages/dev-utils/src/web3_factory.ts +++ b/packages/dev-utils/src/web3_factory.ts @@ -26,6 +26,7 @@ import * as Web3 from 'web3'; export interface Web3Config { hasAddresses?: boolean; // default: true shouldUseInProcessGanache?: boolean; // default: false + rpcUrl?: string; // default: localhost:8545 } export const web3Factory = { @@ -53,6 +54,9 @@ export const web3Factory = { }; const shouldUseInProcessGanache = !!config.shouldUseInProcessGanache; if (shouldUseInProcessGanache) { + if (!_.isUndefined(config.rpcUrl)) { + throw new Error('Cannot use both GanacheSubrovider and RPCSubprovider'); + } provider.addProvider( new GanacheSubprovider({ logger, @@ -65,7 +69,7 @@ export const web3Factory = { } else { provider.addProvider( new RpcSubprovider({ - rpcUrl: constants.RPC_URL, + rpcUrl: config.rpcUrl || constants.RPC_URL, }), ); } diff --git a/packages/dev-utils/test/blockchain_lifecycle_test.ts b/packages/dev-utils/test/blockchain_lifecycle_test.ts index 5ed67e012..2cfad9644 100644 --- a/packages/dev-utils/test/blockchain_lifecycle_test.ts +++ b/packages/dev-utils/test/blockchain_lifecycle_test.ts @@ -8,8 +8,8 @@ import { BlockchainLifecycle, web3Factory } from '../src'; const expect = chai.expect; describe('BlockchainLifecycle tests', () => { - const web3Provider = web3Factory.getRpcProvider(); - const web3Wrapper = new Web3Wrapper(web3Provider); + const provider = web3Factory.getRpcProvider({ shouldUseInProcessGanache: true }); + const web3Wrapper = new Web3Wrapper(provider); const blockchainLifecycle = new BlockchainLifecycle(web3Wrapper); describe('#startAsync/revertAsync', () => { it('reverts changes in between', async () => { diff --git a/packages/dev-utils/test/rpc_test.ts b/packages/dev-utils/test/rpc_test.ts index 1bdea3613..b6998f604 100644 --- a/packages/dev-utils/test/rpc_test.ts +++ b/packages/dev-utils/test/rpc_test.ts @@ -8,8 +8,8 @@ import { web3Factory } from '../src'; const expect = chai.expect; describe('RPC tests', () => { - const web3Provider = web3Factory.getRpcProvider(); - const web3Wrapper = new Web3Wrapper(web3Provider); + const provider = web3Factory.getRpcProvider({ shouldUseInProcessGanache: true }); + const web3Wrapper = new Web3Wrapper(provider); describe('#mineBlockAsync', () => { it('increases block number when called', async () => { const blockNumberBefore = await web3Wrapper.getBlockNumberAsync(); diff --git a/packages/json-schemas/CHANGELOG.json b/packages/json-schemas/CHANGELOG.json index d6360f5d4..5e5d1ca54 100644 --- a/packages/json-schemas/CHANGELOG.json +++ b/packages/json-schemas/CHANGELOG.json @@ -1,5 +1,14 @@ [ { + "timestamp": 1523462196, + "version": "0.7.20", + "changes": [ + { + "note": "Dependencies updated" + } + ] + }, + { "timestamp": 1522673609, "version": "0.7.19", "changes": [ diff --git a/packages/json-schemas/CHANGELOG.md b/packages/json-schemas/CHANGELOG.md index 66943db57..10adc6c46 100644 --- a/packages/json-schemas/CHANGELOG.md +++ b/packages/json-schemas/CHANGELOG.md @@ -5,6 +5,10 @@ Edit the package's CHANGELOG.json file only. CHANGELOG +## v0.7.20 - _April 11, 2018_ + + * Dependencies updated + ## v0.7.19 - _April 2, 2018_ * Dependencies updated diff --git a/packages/json-schemas/README.md b/packages/json-schemas/README.md index e8cece63b..ffa8e947a 100644 --- a/packages/json-schemas/README.md +++ b/packages/json-schemas/README.md @@ -2,7 +2,7 @@ Contains 0x-related json schemas -### Read the [Documentation](0xproject.com/docs/json-schemas). +### Read the [Documentation](https://0xproject.com/docs/json-schemas). ## Installation diff --git a/packages/json-schemas/package.json b/packages/json-schemas/package.json index b7eb99aef..342d4e36c 100644 --- a/packages/json-schemas/package.json +++ b/packages/json-schemas/package.json @@ -1,6 +1,6 @@ { "name": "@0xproject/json-schemas", - "version": "0.7.19", + "version": "0.7.20", "description": "0x-related json schemas", "main": "lib/src/index.js", "types": "lib/src/index.d.ts", @@ -11,7 +11,7 @@ "test:coverage": "nyc npm run test --all && yarn coverage:report:lcov", "coverage:report:lcov": "nyc report --reporter=text-lcov > coverage/lcov.info", "test:circleci": "yarn test:coverage", - "run_mocha": "mocha lib/test/**/*_test.js", + "run_mocha": "mocha lib/test/**/*_test.js --exit", "clean": "shx rm -rf lib test_temp scripts", "build": "tsc && copyfiles -u 3 './lib/src/monorepo_scripts/**/*' ./scripts", "manual:postpublish": "yarn build; node ./scripts/postpublish.js", @@ -42,14 +42,15 @@ }, "homepage": "https://github.com/0xProject/0x-monorepo/packages/json-schemas/README.md", "dependencies": { - "@0xproject/typescript-typings": "^0.0.3", + "@0xproject/typescript-typings": "^0.1.0", + "@types/node": "^8.0.53", "jsonschema": "^1.2.0", "lodash.values": "^4.3.0" }, "devDependencies": { - "@0xproject/monorepo-scripts": "^0.1.16", - "@0xproject/tslint-config": "^0.4.14", - "@0xproject/utils": "^0.5.0", + "@0xproject/monorepo-scripts": "^0.1.17", + "@0xproject/tslint-config": "^0.4.15", + "@0xproject/utils": "^0.5.1", "@types/lodash.foreach": "^4.5.3", "@types/lodash.values": "^4.3.3", "@types/mocha": "^2.2.42", diff --git a/packages/metacoin/artifacts/Metacoin.json b/packages/metacoin/artifacts/Metacoin.json deleted file mode 100644 index 46c3ee71c..000000000 --- a/packages/metacoin/artifacts/Metacoin.json +++ /dev/null @@ -1,98 +0,0 @@ -{ - "contract_name": "Metacoin", - "networks": { - "50": { - "solc_version": "0.4.21", - "keccak256": "0x2c3aa2e9dbef58abf57cecc148464d0852a83d7f30bbd2066f2a13b8bd3b1dd0", - "source_tree_hash": "0x2c3aa2e9dbef58abf57cecc148464d0852a83d7f30bbd2066f2a13b8bd3b1dd0", - "optimizer_enabled": false, - "abi": [ - { - "constant": true, - "inputs": [ - { - "name": "", - "type": "address" - } - ], - "name": "balances", - "outputs": [ - { - "name": "", - "type": "uint256" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": false, - "inputs": [ - { - "components": [ - { - "name": "to", - "type": "address" - }, - { - "name": "amount", - "type": "uint256" - } - ], - "name": "transferData", - "type": "tuple" - } - ], - "name": "transfer", - "outputs": [ - { - "name": "success", - "type": "bool" - } - ], - "payable": false, - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "payable": false, - "stateMutability": "nonpayable", - "type": "constructor" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "name": "_from", - "type": "address" - }, - { - "indexed": true, - "name": "_to", - "type": "address" - }, - { - "indexed": false, - "name": "_value", - "type": "uint256" - } - ], - "name": "Transfer", - "type": "event" - } - ], - "bytecode": - "0x6060604052341561000f57600080fd5b6127106000803373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002081905550610406806100636000396000f30060606040526004361061004c576000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff16806327e235e3146100515780632bd14bb914610087575b600080fd5b341561005c57600080fd5b610071600461006c9036906102b9565b6100bd565b60405161007e9190610344565b60405180910390f35b341561009257600080fd5b6100a760046100a29036906102e2565b6100d5565b6040516100b49190610329565b60405180910390f35b60006020528060005260406000206000915090505481565b600081602001516000803373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054101561012a5760009050610240565b81602001516000803373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600082825403925050819055508160200151600080846000015173ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008282540192505081905550816000015173ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef84602001516040516102339190610344565b60405180910390a3600190505b919050565b600061025182356103a2565b905092915050565b60006040828403121561026b57600080fd5b610275604061035f565b9050600061028584828501610245565b6000830152506020610299848285016102a5565b60208301525092915050565b60006102b182356103c2565b905092915050565b6000602082840312156102cb57600080fd5b60006102d984828501610245565b91505092915050565b6000604082840312156102f457600080fd5b600061030284828501610259565b91505092915050565b6103148161038c565b82525050565b61032381610398565b82525050565b600060208201905061033e600083018461030b565b92915050565b6000602082019050610359600083018461031a565b92915050565b6000604051905081810181811067ffffffffffffffff8211171561038257600080fd5b8060405250919050565b60008115159050919050565b6000819050919050565b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b60008190509190505600a265627a7a72305820d15828219194e8ddaa624e10f9c8823c05268d79753b4c60ef401fb4fe5f09dc6c6578706572696d656e74616cf50037", - "runtime_bytecode": - "0x60606040526004361061004c576000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff16806327e235e3146100515780632bd14bb914610087575b600080fd5b341561005c57600080fd5b610071600461006c9036906102b9565b6100bd565b60405161007e9190610344565b60405180910390f35b341561009257600080fd5b6100a760046100a29036906102e2565b6100d5565b6040516100b49190610329565b60405180910390f35b60006020528060005260406000206000915090505481565b600081602001516000803373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054101561012a5760009050610240565b81602001516000803373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600082825403925050819055508160200151600080846000015173ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008282540192505081905550816000015173ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef84602001516040516102339190610344565b60405180910390a3600190505b919050565b600061025182356103a2565b905092915050565b60006040828403121561026b57600080fd5b610275604061035f565b9050600061028584828501610245565b6000830152506020610299848285016102a5565b60208301525092915050565b60006102b182356103c2565b905092915050565b6000602082840312156102cb57600080fd5b60006102d984828501610245565b91505092915050565b6000604082840312156102f457600080fd5b600061030284828501610259565b91505092915050565b6103148161038c565b82525050565b61032381610398565b82525050565b600060208201905061033e600083018461030b565b92915050565b6000602082019050610359600083018461031a565b92915050565b6000604051905081810181811067ffffffffffffffff8211171561038257600080fd5b8060405250919050565b60008115159050919050565b6000819050919050565b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b60008190509190505600a265627a7a72305820d15828219194e8ddaa624e10f9c8823c05268d79753b4c60ef401fb4fe5f09dc6c6578706572696d656e74616cf50037", - "updated_at": 1522318279735, - "source_map": "60:662:0:-;;;290:72;;;;;;;;350:5;327:8;:20;336:10;327:20;;;;;;;;;;;;;;;:28;;;;60:662;;;;;;", - "source_map_runtime": - "60:662:0:-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;84:41;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;368:352;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;84:41;;;;;;;;;;;;;;;;;:::o;368:352::-;429:12;480;:19;;;457:8;:20;466:10;457:20;;;;;;;;;;;;;;;;:42;453:60;;;508:5;501:12;;;;453:60;547:12;:19;;;523:8;:20;532:10;523:20;;;;;;;;;;;;;;;;:43;;;;;;;;;;;605:12;:19;;;576:8;:25;585:12;:15;;;576:25;;;;;;;;;;;;;;;;:48;;;;;;;;;;;655:12;:15;;;634:58;;643:10;634:58;;;672:12;:19;;;634:58;;;;;;;;;;;;;;;709:4;702:11;;368:352;;;;:::o;5:118:-1:-;;72:46;110:6;97:20;72:46;;;63:55;;57:66;;;;;165:469;;282:4;270:9;265:3;261:19;257:30;254:2;;;300:1;297;290:12;254:2;318:20;333:4;318:20;;;309:29;;386:1;417:49;462:3;453:6;442:9;438:22;417:49;;;411:3;404:5;400:15;393:74;348:130;530:2;563:49;608:3;599:6;588:9;584:22;563:49;;;556:4;549:5;545:16;538:75;488:136;248:386;;;;;641:118;;708:46;746:6;733:20;708:46;;;699:55;;693:66;;;;;766:241;;870:2;858:9;849:7;845:23;841:32;838:2;;;886:1;883;876:12;838:2;921:1;938:53;983:7;974:6;963:9;959:22;938:53;;;928:63;;900:97;832:175;;;;;1014:297;;1146:2;1134:9;1125:7;1121:23;1117:32;1114:2;;;1162:1;1159;1152:12;1114:2;1197:1;1214:81;1287:7;1278:6;1267:9;1263:22;1214:81;;;1204:91;;1176:125;1108:203;;;;;1318:101;1385:28;1407:5;1385:28;;;1380:3;1373:41;1367:52;;;1426:110;1499:31;1524:5;1499:31;;;1494:3;1487:44;1481:55;;;1543:181;;1645:2;1634:9;1630:18;1622:26;;1659:55;1711:1;1700:9;1696:17;1687:6;1659:55;;;1616:108;;;;;1731:193;;1839:2;1828:9;1824:18;1816:26;;1853:61;1911:1;1900:9;1896:17;1887:6;1853:61;;;1810:114;;;;;1931:256;;1993:2;1987:9;1977:19;;2031:4;2023:6;2019:17;2130:6;2118:10;2115:22;2094:18;2082:10;2079:34;2076:62;2073:2;;;2151:1;2148;2141:12;2073:2;2171:10;2167:2;2160:22;1971:216;;;;;2194:92;;2274:5;2267:13;2260:21;2249:32;;2243:43;;;;2293:79;;2362:5;2351:16;;2345:27;;;;2379:128;;2459:42;2452:5;2448:54;2437:65;;2431:76;;;;2514:79;;2583:5;2572:16;;2566:27;;;", - "sources": ["Metacoin.sol"] - } - } -} diff --git a/packages/metacoin/contracts/Metacoin.sol b/packages/metacoin/contracts/Metacoin.sol index 6b6814b21..ac212b32e 100644 --- a/packages/metacoin/contracts/Metacoin.sol +++ b/packages/metacoin/contracts/Metacoin.sol @@ -11,6 +11,11 @@ contract Metacoin { uint256 amount; } + struct NestedTransferData { + TransferData transferData; + uint32 callback; + } + function Metacoin() public { balances[msg.sender] = 10000; } @@ -22,4 +27,14 @@ contract Metacoin { Transfer(msg.sender, transferData.to, transferData.amount); return true; } + + function transfer(TransferData transferData, uint32 callback) public returns (int) { + transfer(transferData); + return callback; + } + + function transfer(NestedTransferData nestedTransferData) public returns (int) { + return transfer(nestedTransferData.transferData, nestedTransferData.callback); + } + } diff --git a/packages/metacoin/package.json b/packages/metacoin/package.json index 1177513a7..150a1bd51 100644 --- a/packages/metacoin/package.json +++ b/packages/metacoin/package.json @@ -1,18 +1,18 @@ { "name": "@0xproject/metacoin", - "version": "0.0.2", + "version": "0.0.3", "private": true, "description": "Example solidity project using 0x dev tools", "scripts": { "build:watch": "tsc -w", "lint": "tslint --project .", "clean": "shx rm -rf lib", - "prebuild": "run-s clean generate_contract_wrappers copy_artifacts", + "prebuild": "run-s clean compile generate_contract_wrappers copy_artifacts", "copy_artifacts": "copyfiles './artifacts/**/*' './contracts/**/*' ./lib", "build": "tsc", "test": "run-s build run_mocha", "test:coverage": "SOLIDITY_COVERAGE=true run-s build run_mocha coverage:report:text coverage:report:lcov", - "run_mocha": "mocha 'lib/test/**/*.js'", + "run_mocha": "mocha lib/test/**/*.js --bail --exit", "generate_contract_wrappers": "node ../abi-gen/lib/index.js --abis 'artifacts/Metacoin.json' --template ../contract_templates/contract.handlebars --partials '../contract_templates/partials/**/*.handlebars' --output src/contract_wrappers --backend ethers && prettier --write 'src/contract_wrappers/**.ts'", "coverage:report:text": "istanbul report text", "coverage:report:html": "istanbul report html && open coverage/index.html", @@ -23,21 +23,21 @@ "author": "", "license": "Apache-2.0", "dependencies": { - "@0xproject/abi-gen": "^0.2.9", - "@0xproject/base-contract": "^0.1.0", - "@0xproject/deployer": "^0.3.5", - "@0xproject/sol-cov": "^0.0.6", - "@0xproject/subproviders": "^0.8.4", - "@0xproject/tslint-config": "^0.4.14", - "@0xproject/types": "^0.5.0", - "@0xproject/utils": "^0.5.0", - "@0xproject/web3-wrapper": "^0.5.0", + "@0xproject/abi-gen": "^0.2.10", + "@0xproject/base-contract": "^0.2.0", + "@0xproject/deployer": "^0.4.0", + "@0xproject/sol-cov": "^0.0.7", + "@0xproject/subproviders": "^0.8.5", + "@0xproject/tslint-config": "^0.4.15", + "@0xproject/types": "^0.6.0", + "@0xproject/utils": "^0.5.1", + "@0xproject/web3-wrapper": "^0.6.0", "ethers-contracts": "^2.2.1", "lodash": "^4.17.4", "web3-provider-engine": "^13.0.1" }, "devDependencies": { - "@0xproject/dev-utils": "^0.3.4", + "@0xproject/dev-utils": "^0.3.5", "chai": "^4.0.1", "chai-as-promised": "^7.1.0", "chai-bignumber": "^2.0.1", diff --git a/packages/metacoin/test/metacoin_test.ts b/packages/metacoin/test/metacoin_test.ts index 73537d342..51830d1ef 100644 --- a/packages/metacoin/test/metacoin_test.ts +++ b/packages/metacoin/test/metacoin_test.ts @@ -36,12 +36,12 @@ describe('Metacoin', () => { }); }); describe('#transfer', () => { - it(`should successfully transfer tokens`, async () => { + it(`should successfully transfer tokens (via transfer1)`, async () => { const ZERO_ADDRESS = '0x0000000000000000000000000000000000000000'; const amount = INITIAL_BALANCE.div(2); const oldBalance = await metacoin.balances.callAsync(ZERO_ADDRESS); expect(oldBalance).to.be.bignumber.equal(0); - const txHash = await metacoin.transfer.sendTransactionAsync( + const txHash = await metacoin.transfer1.sendTransactionAsync( { to: ZERO_ADDRESS, amount, @@ -58,5 +58,57 @@ describe('Metacoin', () => { const newBalance = await metacoin.balances.callAsync(ZERO_ADDRESS); expect(newBalance).to.be.bignumber.equal(amount); }); + + it(`should successfully transfer tokens (via transfer2)`, async () => { + const ZERO_ADDRESS = '0x0000000000000000000000000000000000000000'; + const amount = INITIAL_BALANCE.div(2); + const oldBalance = await metacoin.balances.callAsync(ZERO_ADDRESS); + expect(oldBalance).to.be.bignumber.equal(0); + const callback = 59; + const txHash = await metacoin.transfer2.sendTransactionAsync( + { + to: ZERO_ADDRESS, + amount, + }, + callback, + { from: devConstants.TESTRPC_FIRST_ADDRESS }, + ); + const txReceipt = await web3Wrapper.awaitTransactionMinedAsync(txHash); + const transferLogs = txReceipt.logs[0] as LogWithDecodedArgs<TransferContractEventArgs>; + expect(transferLogs.args).to.be.deep.equal({ + _to: ZERO_ADDRESS, + _from: devConstants.TESTRPC_FIRST_ADDRESS, + _value: amount, + }); + const newBalance = await metacoin.balances.callAsync(ZERO_ADDRESS); + expect(newBalance).to.be.bignumber.equal(amount); + }); + + it(`should successfully transfer tokens (via transfer3)`, async () => { + const ZERO_ADDRESS = '0x0000000000000000000000000000000000000000'; + const amount = INITIAL_BALANCE.div(2); + const oldBalance = await metacoin.balances.callAsync(ZERO_ADDRESS); + expect(oldBalance).to.be.bignumber.equal(0); + const callback = 59; + const txHash = await metacoin.transfer3.sendTransactionAsync( + { + transferData: { + to: ZERO_ADDRESS, + amount, + }, + callback, + }, + { from: devConstants.TESTRPC_FIRST_ADDRESS }, + ); + const txReceipt = await web3Wrapper.awaitTransactionMinedAsync(txHash); + const transferLogs = txReceipt.logs[0] as LogWithDecodedArgs<TransferContractEventArgs>; + expect(transferLogs.args).to.be.deep.equal({ + _to: ZERO_ADDRESS, + _from: devConstants.TESTRPC_FIRST_ADDRESS, + _value: amount, + }); + const newBalance = await metacoin.balances.callAsync(ZERO_ADDRESS); + expect(newBalance).to.be.bignumber.equal(amount); + }); }); }); diff --git a/packages/migrations/README.md b/packages/migrations/README.md new file mode 100644 index 000000000..15129ae85 --- /dev/null +++ b/packages/migrations/README.md @@ -0,0 +1,69 @@ +## Migrations + +Migrate the 0x system of smart contracts on the network of your choice using these migrations. + +## 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 +``` + +### Migrate + +In order to migrate the 0x smart contracts to TestRPC/Ganache running at `http://localhost:8545`, run: + +```bash +yarn migrate +``` diff --git a/packages/migrations/package.json b/packages/migrations/package.json new file mode 100644 index 000000000..ce0fe7267 --- /dev/null +++ b/packages/migrations/package.json @@ -0,0 +1,36 @@ +{ + "private": true, + "name": "@0xproject/migrations", + "version": "0.0.1", + "description": "0x smart contract migrations", + "main": "lib/index.js", + "types": "lib/index.d.ts", + "scripts": { + "build:watch": "tsc -w", + "build": "tsc", + "clean": "shx rm -rf lib", + "lint": "tslint --project . 'src/**/*.ts'", + "migrate": "run-s build compile script:migrate", + "script:migrate": "node ./lib/migrate.js", + "copy_artifacts": "copyfiles 'src/artifacts/**/*' ./lib", + "compile": "node ../deployer/lib/src/cli.js compile --contracts ${npm_package_config_contracts} --contracts-dir ../contracts/src/contracts --artifacts-dir src/artifacts" + }, + "config": { + "contracts": "Exchange,DummyToken,ZRXToken,Token,WETH9,TokenTransferProxy,MultiSigWallet,MultiSigWalletWithTimeLock,MultiSigWalletWithTimeLockExceptRemoveAuthorizedAddress,MaliciousToken,TokenRegistry,Arbitrage,EtherDelta,AccountLevels" + }, + "license": "Apache-2.0", + "devDependencies": { + "@0xproject/tslint-config": "^0.4.14", + "@0xproject/dev-utils": "^0.3.4", + "npm-run-all": "^4.1.2", + "shx": "^0.2.2", + "tslint": "5.8.0", + "typescript": "2.7.1" + }, + "dependencies": { + "@0xproject/deployer": "^0.4.0", + "@0xproject/utils": "^0.5.0", + "@0xproject/web3-wrapper": "^0.6.0", + "lodash": "^4.17.4" + } +} diff --git a/packages/migrations/src/globals.d.ts b/packages/migrations/src/globals.d.ts new file mode 100644 index 000000000..94e63a32d --- /dev/null +++ b/packages/migrations/src/globals.d.ts @@ -0,0 +1,6 @@ +declare module '*.json' { + const json: any; + /* tslint:disable */ + export default json; + /* tslint:enable */ +} diff --git a/packages/migrations/src/index.ts b/packages/migrations/src/index.ts new file mode 100644 index 000000000..c342247a3 --- /dev/null +++ b/packages/migrations/src/index.ts @@ -0,0 +1 @@ +export { runMigrationsAsync } from './migration'; diff --git a/packages/migrations/src/migrate.ts b/packages/migrations/src/migrate.ts new file mode 100644 index 000000000..76dcbd847 --- /dev/null +++ b/packages/migrations/src/migrate.ts @@ -0,0 +1,25 @@ +#!/usr/bin/env node +import { Deployer } from '@0xproject/deployer'; +import { devConstants } from '@0xproject/dev-utils'; +import { logUtils } from '@0xproject/utils'; +import * as path from 'path'; + +import { runMigrationsAsync } from './migration'; + +(async () => { + const deployerOpts = { + jsonrpcUrl: 'http://localhost:8545', + artifactsDir: path.resolve('src', 'artifacts'), + networkId: 50, + defaults: { + gas: devConstants.GAS_ESTIMATE, + }, + }; + + const deployer = new Deployer(deployerOpts); + + await runMigrationsAsync(deployer); +})().catch(err => { + logUtils.log(err); + process.exit(1); +}); diff --git a/packages/contracts/migrations/migrate.ts b/packages/migrations/src/migration.ts index cff8af0ab..4827328fc 100644 --- a/packages/contracts/migrations/migrate.ts +++ b/packages/migrations/src/migration.ts @@ -1,12 +1,10 @@ import { Deployer } from '@0xproject/deployer'; -import { BigNumber } from '@0xproject/utils'; +import { BigNumber, NULL_BYTES } from '@0xproject/utils'; import { Web3Wrapper } from '@0xproject/web3-wrapper'; import * as _ from 'lodash'; -import { constants } from '../util/constants'; -import { ContractName } from '../util/types'; - -import { tokenInfo } from './config/token_info'; +import { ContractName } from './types'; +import { tokenInfo } from './utils/token_info'; /** * Custom migrations should be defined in this function. This will be called with the CLI 'migrate' command. @@ -20,7 +18,7 @@ export const runMigrationsAsync = async (deployer: Deployer) => { const tokenTransferProxy = await deployer.deployAndSaveAsync(ContractName.TokenTransferProxy); const zrxToken = await deployer.deployAndSaveAsync(ContractName.ZRXToken); - const etherToken = await deployer.deployAndSaveAsync(ContractName.EtherToken); + const etherToken = await deployer.deployAndSaveAsync(ContractName.WETH9); const tokenReg = await deployer.deployAndSaveAsync(ContractName.TokenRegistry); const exchangeArgs = [zrxToken.address, tokenTransferProxy.address]; @@ -51,8 +49,8 @@ export const runMigrationsAsync = async (deployer: Deployer) => { '0x Protocol Token', 'ZRX', 18, - constants.NULL_BYTES, - constants.NULL_BYTES, + NULL_BYTES, + NULL_BYTES, { from: owner, gas: addTokenGasEstimate, @@ -63,8 +61,8 @@ export const runMigrationsAsync = async (deployer: Deployer) => { 'Ether Token', 'WETH', 18, - constants.NULL_BYTES, - constants.NULL_BYTES, + NULL_BYTES, + NULL_BYTES, { from: owner, gas: addTokenGasEstimate, diff --git a/packages/migrations/src/types.ts b/packages/migrations/src/types.ts new file mode 100644 index 000000000..1887bfd96 --- /dev/null +++ b/packages/migrations/src/types.ts @@ -0,0 +1,38 @@ +export interface MultiSigConfig { + owners: string[]; + confirmationsRequired: number; + secondsRequired: number; +} + +export interface MultiSigConfigByNetwork { + [networkName: string]: MultiSigConfig; +} + +export interface Token { + address?: string; + name: string; + symbol: string; + decimals: number; + ipfsHash: string; + swarmHash: string; +} + +export interface TokenInfoByNetwork { + development: Token[]; + live: Token[]; +} + +export enum ContractName { + TokenTransferProxy = 'TokenTransferProxy', + TokenRegistry = 'TokenRegistry', + MultiSigWalletWithTimeLock = 'MultiSigWalletWithTimeLock', + Exchange = 'Exchange', + ZRXToken = 'ZRXToken', + DummyToken = 'DummyToken', + WETH9 = 'WETH9', + MultiSigWalletWithTimeLockExceptRemoveAuthorizedAddress = 'MultiSigWalletWithTimeLockExceptRemoveAuthorizedAddress', + MaliciousToken = 'MaliciousToken', + AccountLevels = 'AccountLevels', + EtherDelta = 'EtherDelta', + Arbitrage = 'Arbitrage', +} diff --git a/packages/contracts/migrations/config/token_info.ts b/packages/migrations/src/utils/token_info.ts index 5fd3db144..968665c7d 100644 --- a/packages/contracts/migrations/config/token_info.ts +++ b/packages/migrations/src/utils/token_info.ts @@ -1,4 +1,5 @@ -import { constants } from '../../util/constants'; +import { NULL_BYTES } from '@0xproject/utils'; + import { Token } from '../types'; export const tokenInfo: Token[] = [ @@ -6,35 +7,35 @@ export const tokenInfo: Token[] = [ name: 'Augur Reputation Token', symbol: 'REP', decimals: 18, - ipfsHash: constants.NULL_BYTES, - swarmHash: constants.NULL_BYTES, + ipfsHash: NULL_BYTES, + swarmHash: NULL_BYTES, }, { name: 'Digix DAO Token', symbol: 'DGD', decimals: 18, - ipfsHash: constants.NULL_BYTES, - swarmHash: constants.NULL_BYTES, + ipfsHash: NULL_BYTES, + swarmHash: NULL_BYTES, }, { name: 'Golem Network Token', symbol: 'GNT', decimals: 18, - ipfsHash: constants.NULL_BYTES, - swarmHash: constants.NULL_BYTES, + ipfsHash: NULL_BYTES, + swarmHash: NULL_BYTES, }, { name: 'MakerDAO', symbol: 'MKR', decimals: 18, - ipfsHash: constants.NULL_BYTES, - swarmHash: constants.NULL_BYTES, + ipfsHash: NULL_BYTES, + swarmHash: NULL_BYTES, }, { name: 'Melon Token', symbol: 'MLN', decimals: 18, - ipfsHash: constants.NULL_BYTES, - swarmHash: constants.NULL_BYTES, + ipfsHash: NULL_BYTES, + swarmHash: NULL_BYTES, }, ]; diff --git a/packages/migrations/tsconfig.json b/packages/migrations/tsconfig.json new file mode 100644 index 000000000..f5f4b37c2 --- /dev/null +++ b/packages/migrations/tsconfig.json @@ -0,0 +1,7 @@ +{ + "extends": "../../tsconfig", + "compilerOptions": { + "outDir": "lib" + }, + "include": ["src/**/*"] +} diff --git a/packages/migrations/tslint.json b/packages/migrations/tslint.json new file mode 100644 index 000000000..ffaefe83a --- /dev/null +++ b/packages/migrations/tslint.json @@ -0,0 +1,3 @@ +{ + "extends": ["@0xproject/tslint-config"] +} diff --git a/packages/monorepo-scripts/CHANGELOG.json b/packages/monorepo-scripts/CHANGELOG.json index 05e1ce2a2..431ae879b 100644 --- a/packages/monorepo-scripts/CHANGELOG.json +++ b/packages/monorepo-scripts/CHANGELOG.json @@ -1,5 +1,14 @@ [ { + "timestamp": 1523462196, + "version": "0.1.17", + "changes": [ + { + "note": "Dependencies updated" + } + ] + }, + { "timestamp": 1522658513, "version": "0.1.16", "changes": [ diff --git a/packages/monorepo-scripts/CHANGELOG.md b/packages/monorepo-scripts/CHANGELOG.md index 8734cb835..1942f03f3 100644 --- a/packages/monorepo-scripts/CHANGELOG.md +++ b/packages/monorepo-scripts/CHANGELOG.md @@ -5,6 +5,10 @@ Edit the package's CHANGELOG.json file only. CHANGELOG +## v0.1.17 - _April 11, 2018_ + + * Dependencies updated + ## v0.1.16 - _April 2, 2018_ * Dependencies updated diff --git a/packages/monorepo-scripts/package.json b/packages/monorepo-scripts/package.json index b113b4b39..ac21cabc4 100644 --- a/packages/monorepo-scripts/package.json +++ b/packages/monorepo-scripts/package.json @@ -1,6 +1,6 @@ { "name": "@0xproject/monorepo-scripts", - "version": "0.1.16", + "version": "0.1.17", "description": "Helper scripts for the monorepo", "main": "lib/index.js", "types": "lib/index.d.ts", @@ -29,6 +29,7 @@ "@0xproject/tslint-config": "0.4.13", "@types/glob": "^5.0.33", "@types/node": "^8.0.53", + "@types/opn": "^5.1.0", "@types/rimraf": "^2.0.2", "depcheck": "^0.6.9", "lerna-get-packages": "^1.0.0", @@ -45,7 +46,9 @@ "glob": "^7.1.2", "lodash": "^4.17.4", "moment": "2.21.0", + "opn": "^5.3.0", "promisify-child-process": "^1.0.5", + "prompt": "^1.0.0", "publish-release": "0xproject/publish-release", "rimraf": "^2.6.2", "semver-diff": "^2.1.0", diff --git a/packages/monorepo-scripts/src/constants.ts b/packages/monorepo-scripts/src/constants.ts index 74387a159..081a49332 100644 --- a/packages/monorepo-scripts/src/constants.ts +++ b/packages/monorepo-scripts/src/constants.ts @@ -2,4 +2,5 @@ import * as path from 'path'; export const constants = { monorepoRootPath: path.join(__dirname, '../../..'), + stagingWebsite: 'http://staging-0xproject.s3-website-us-east-1.amazonaws.com', }; diff --git a/packages/monorepo-scripts/src/globals.d.ts b/packages/monorepo-scripts/src/globals.d.ts index c5898d0f5..1693a6dbb 100644 --- a/packages/monorepo-scripts/src/globals.d.ts +++ b/packages/monorepo-scripts/src/globals.d.ts @@ -3,6 +3,11 @@ declare module 'publish-release'; declare module 'es6-promisify'; declare module 'semver-diff'; +declare module 'prompt' { + const start: () => void; + const get: (promptMessages: string[], callback: (err: Error, result: string) => void) => void; +} + // semver-sort declarations declare module 'semver-sort' { const desc: (versions: string[]) => string[]; @@ -15,6 +20,7 @@ declare interface LernaPackage { version: string; name: string; main?: string; + scripts?: { [command: string]: string }; config?: { additionalTsTypings?: string[]; }; diff --git a/packages/monorepo-scripts/src/publish.ts b/packages/monorepo-scripts/src/publish.ts index adc1de64a..21c8b72c9 100644 --- a/packages/monorepo-scripts/src/publish.ts +++ b/packages/monorepo-scripts/src/publish.ts @@ -1,18 +1,23 @@ #!/usr/bin/env node +import * as promisify from 'es6-promisify'; import * as fs from 'fs'; import lernaGetPackages = require('lerna-get-packages'); import * as _ from 'lodash'; import * as moment from 'moment'; +import opn = require('opn'); import * as path from 'path'; import { exec as execAsync, spawn } from 'promisify-child-process'; +import * as prompt from 'prompt'; import semverDiff = require('semver-diff'); import semverSort = require('semver-sort'); import { constants } from './constants'; -import { Changelog, Changes, SemVerIndex, UpdatedPackage } from './types'; +import { Changelog, Changes, PackageToVersionChange, SemVerIndex, UpdatedPackage } from './types'; import { utils } from './utils'; +const DOC_GEN_COMMAND = 'docs:json'; +const NPM_NAMESPACE = '@0xproject/'; const IS_DRY_RUN = process.env.IS_DRY_RUN === 'true'; const TODAYS_TIMESTAMP = moment().unix(); const LERNA_EXECUTABLE = './node_modules/lerna/bin/lerna.js'; @@ -21,8 +26,95 @@ const semverNameToIndex: { [semver: string]: number } = { minor: SemVerIndex.Minor, major: SemVerIndex.Major, }; +const packageNameToWebsitePath: { [name: string]: string } = { + '0x.js': '0xjs', + 'web3-wrapper': 'web3_wrapper', + contracts: 'contracts', + connect: 'connect', + 'json-schemas': 'json-schemas', + deployer: 'deployer', + 'sol-cov': 'sol-cov', + subproviders: 'subproviders', +}; (async () => { + // Fetch public, updated Lerna packages + const updatedPublicLernaPackages = await getUpdatedPublicLernaPackagesAsync(); + + await confirmDocPagesRenderAsync(updatedPublicLernaPackages); + + // Update CHANGELOGs + const updatedPublicLernaPackageNames = _.map(updatedPublicLernaPackages, pkg => pkg.package.name); + utils.log(`Will update CHANGELOGs and publish: \n${updatedPublicLernaPackageNames.join('\n')}\n`); + const packageToVersionChange = await updateChangeLogsAsync(updatedPublicLernaPackages); + + // Push changelog changes to Github + if (!IS_DRY_RUN) { + await pushChangelogsToGithubAsync(); + } + + // Call LernaPublish + utils.log('Version updates to apply:'); + _.each(packageToVersionChange, (versionChange: string, packageName: string) => { + utils.log(`${packageName} -> ${versionChange}`); + }); + utils.log(`Calling 'lerna publish'...`); + await lernaPublishAsync(packageToVersionChange); +})().catch(err => { + utils.log(err); + process.exit(1); +}); + +async function confirmDocPagesRenderAsync(packages: LernaPackage[]) { + // push docs to staging + utils.log("Upload all docJson's to S3 staging..."); + await execAsync(`yarn lerna:stage_docs`, { cwd: constants.monorepoRootPath }); + + // deploy website to staging + utils.log('Deploy website to staging...'); + const pathToWebsite = `${constants.monorepoRootPath}/packages/website`; + await execAsync(`yarn deploy_staging`, { cwd: pathToWebsite }); + + const packagesWithDocs = _.filter(packages, pkg => { + const scriptsIfExists = pkg.package.scripts; + if (_.isUndefined(scriptsIfExists)) { + throw new Error('Found a public package without any scripts in package.json'); + } + return !_.isUndefined(scriptsIfExists[DOC_GEN_COMMAND]); + }); + _.each(packagesWithDocs, pkg => { + const name = pkg.package.name; + const nameWithoutPrefix = _.startsWith(name, NPM_NAMESPACE) ? name.split('@0xproject/')[1] : name; + const docSegmentIfExists = packageNameToWebsitePath[nameWithoutPrefix]; + if (_.isUndefined(docSegmentIfExists)) { + throw new Error( + `Found package '${name}' with doc commands but no corresponding docSegment in monorepo_scripts +package.ts. Please add an entry for it and try again.`, + ); + } + const link = `${constants.stagingWebsite}/docs/${docSegmentIfExists}`; + // tslint:disable-next-line:no-floating-promises + opn(link); + }); + + prompt.start(); + const message = 'Do all the doc pages render properly? (yn)'; + const result = await promisify(prompt.get)([message]); + const didConfirm = result[message] === 'y'; + if (!didConfirm) { + utils.log('Publish process aborted.'); + process.exit(0); + } +} + +async function pushChangelogsToGithubAsync() { + await execAsync(`git add . --all`, { cwd: constants.monorepoRootPath }); + await execAsync(`git commit -m "Updated CHANGELOGS"`, { cwd: constants.monorepoRootPath }); + await execAsync(`git push`, { cwd: constants.monorepoRootPath }); + utils.log(`Pushed CHANGELOG updates to Github`); +} + +async function getUpdatedPublicLernaPackagesAsync(): Promise<LernaPackage[]> { const updatedPublicPackages = await getPublicLernaUpdatedPackagesAsync(); const updatedPackageNames = _.map(updatedPublicPackages, pkg => pkg.name); @@ -30,10 +122,11 @@ const semverNameToIndex: { [semver: string]: number } = { const updatedPublicLernaPackages = _.filter(allLernaPackages, pkg => { return _.includes(updatedPackageNames, pkg.package.name); }); - const updatedPublicLernaPackageNames = _.map(updatedPublicLernaPackages, pkg => pkg.package.name); - utils.log(`Will update CHANGELOGs and publish: \n${updatedPublicLernaPackageNames.join('\n')}\n`); + return updatedPublicLernaPackages; +} - const packageToVersionChange: { [name: string]: string } = {}; +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'); @@ -88,23 +181,8 @@ const semverNameToIndex: { [semver: string]: number } = { utils.log(`${packageName}: Updated CHANGELOG.md`); } - if (!IS_DRY_RUN) { - await execAsync(`git add . --all`, { cwd: constants.monorepoRootPath }); - await execAsync(`git commit -m "Updated CHANGELOGS"`, { cwd: constants.monorepoRootPath }); - await execAsync(`git push`, { cwd: constants.monorepoRootPath }); - utils.log(`Pushed CHANGELOG updates to Github`); - } - - utils.log('Version updates to apply:'); - _.each(packageToVersionChange, (versionChange: string, packageName: string) => { - utils.log(`${packageName} -> ${versionChange}`); - }); - utils.log(`Calling 'lerna publish'...`); - await lernaPublishAsync(packageToVersionChange); -})().catch(err => { - utils.log(err); - process.exit(1); -}); + return packageToVersionChange; +} async function lernaPublishAsync(packageToVersionChange: { [name: string]: string }) { // HACK: Lerna publish does not provide a way to specify multiple package versions via diff --git a/packages/monorepo-scripts/src/test_installation.ts b/packages/monorepo-scripts/src/test_installation.ts index 195b64b2a..78e0f0929 100644 --- a/packages/monorepo-scripts/src/test_installation.ts +++ b/packages/monorepo-scripts/src/test_installation.ts @@ -31,7 +31,7 @@ import { utils } from './utils'; utils.log(`Installing ${packedPackageFileName}`); result = await execAsync(`yarn add ${packagePath}/${packedPackageFileName}`, { cwd: testDirectory }); const indexFilePath = path.join(testDirectory, 'index.ts'); - fs.writeFileSync(indexFilePath, `import * as Package from '${packageName}'`); + fs.writeFileSync(indexFilePath, `import * as Package from '${packageName}';\n`); const tsConfig = { compilerOptions: { typeRoots: ['node_modules/@0xproject/typescript-typings/types', 'node_modules/@types'], @@ -48,11 +48,13 @@ import { utils } from './utils'; const tsconfigFilePath = path.join(testDirectory, 'tsconfig.json'); fs.writeFileSync(tsconfigFilePath, JSON.stringify(tsConfig, null, 4)); utils.log(`Compiling ${packageName}`); - await execAsync('../node_modules/typescript/bin/tsc', { cwd: testDirectory }); + const tscBinaryPath = path.join(monorepoRootPath, './node_modules/typescript/bin/tsc'); + await execAsync(tscBinaryPath, { cwd: testDirectory }); utils.log(`Successfully compiled with ${packageName} as a dependency`); rimraf.sync(testDirectory); } })().catch(err => { + utils.log(err.stderr); utils.log(err.stdout); process.exit(1); }); diff --git a/packages/monorepo-scripts/src/types.ts b/packages/monorepo-scripts/src/types.ts index 9e6edd186..28d00d710 100644 --- a/packages/monorepo-scripts/src/types.ts +++ b/packages/monorepo-scripts/src/types.ts @@ -21,3 +21,7 @@ export enum SemVerIndex { Minor, Major, } + +export interface PackageToVersionChange { + [name: string]: string; +} diff --git a/packages/monorepo-scripts/tsconfig.json b/packages/monorepo-scripts/tsconfig.json index 5ec2db5e0..332d3a5e1 100644 --- a/packages/monorepo-scripts/tsconfig.json +++ b/packages/monorepo-scripts/tsconfig.json @@ -1,7 +1,7 @@ { "extends": "../../tsconfig", "compilerOptions": { - "typeRoots": ["node_modules/@types"], + "typeRoots": ["../../node_modules/@types", "node_modules/@types"], "outDir": "lib" }, "include": ["./src/**/*"] diff --git a/packages/react-docs-example/package.json b/packages/react-docs-example/package.json index cad1d7556..95c23c226 100644 --- a/packages/react-docs-example/package.json +++ b/packages/react-docs-example/package.json @@ -1,7 +1,7 @@ { "private": true, "name": "@0xproject/react-docs-example", - "version": "0.0.6", + "version": "0.0.7", "description": "An example app using react-docs", "scripts": { "lint": "tslint --project . 'ts/**/*.ts' 'ts/**/*.tsx'", @@ -23,7 +23,7 @@ "url": "https://github.com/0xProject/0x-monorepo.git" }, "devDependencies": { - "@0xproject/tslint-config": "^0.4.14", + "@0xproject/tslint-config": "^0.4.15", "@types/lodash": "4.14.104", "@types/material-ui": "0.18.0", "@types/node": "^8.0.53", @@ -46,7 +46,7 @@ "webpack-dev-server": "^2.11.1" }, "dependencies": { - "@0xproject/react-docs": "^0.0.6", + "@0xproject/react-docs": "^0.0.7", "basscss": "^8.0.3", "lodash": "^4.17.4", "material-ui": "^0.17.1", diff --git a/packages/react-docs/CHANGELOG.json b/packages/react-docs/CHANGELOG.json index 0a85bb32d..951ed84e0 100644 --- a/packages/react-docs/CHANGELOG.json +++ b/packages/react-docs/CHANGELOG.json @@ -1,5 +1,27 @@ [ { + "version": "0.0.8", + "changes": [ + { + "note": "Added support for rendering default param values", + "pr": 519 + }, + { + "note": "Added support for rendering nested function types within interface types", + "pr": 519 + } + ] + }, + { + "timestamp": 1523462196, + "version": "0.0.7", + "changes": [ + { + "note": "Dependencies updated" + } + ] + }, + { "timestamp": 1522673609, "version": "0.0.6", "changes": [ diff --git a/packages/react-docs/CHANGELOG.md b/packages/react-docs/CHANGELOG.md index 3bb01feff..bb531f8b3 100644 --- a/packages/react-docs/CHANGELOG.md +++ b/packages/react-docs/CHANGELOG.md @@ -5,6 +5,10 @@ Edit the package's CHANGELOG.json file only. CHANGELOG +## v0.0.7 - _April 11, 2018_ + + * Dependencies updated + ## v0.0.6 - _April 2, 2018_ * Dependencies updated diff --git a/packages/react-docs/package.json b/packages/react-docs/package.json index 12f438f53..f2af1cb64 100644 --- a/packages/react-docs/package.json +++ b/packages/react-docs/package.json @@ -1,6 +1,6 @@ { "name": "@0xproject/react-docs", - "version": "0.0.6", + "version": "0.0.7", "description": "React documentation component for rendering TypeDoc & Doxity generated JSON", "main": "lib/index.js", "types": "lib/index.d.ts", @@ -22,17 +22,17 @@ "url": "https://github.com/0xProject/0x-monorepo.git" }, "devDependencies": { - "@0xproject/dev-utils": "^0.3.4", - "@0xproject/monorepo-scripts": "^0.1.16", - "@0xproject/tslint-config": "^0.4.14", + "@0xproject/dev-utils": "^0.3.5", + "@0xproject/monorepo-scripts": "^0.1.17", + "@0xproject/tslint-config": "^0.4.15", "copyfiles": "^1.2.0", "shx": "^0.2.2", "tslint": "^5.9.1", "typescript": "2.7.1" }, "dependencies": { - "@0xproject/react-shared": "^0.1.1", - "@0xproject/utils": "^0.5.0", + "@0xproject/react-shared": "^0.1.2", + "@0xproject/utils": "^0.5.1", "@types/lodash": "4.14.104", "@types/material-ui": "0.18.0", "@types/node": "^8.0.53", diff --git a/packages/react-docs/src/components/documentation.tsx b/packages/react-docs/src/components/documentation.tsx index 14fe175cf..800892dc8 100644 --- a/packages/react-docs/src/components/documentation.tsx +++ b/packages/react-docs/src/components/documentation.tsx @@ -337,7 +337,7 @@ export class Documentation extends React.Component<DocumentationProps, Documenta return ( <div key={`property-${property.name}-${property.type.name}`} className="pb3"> <code className={`hljs ${constants.TYPE_TO_SYNTAX[this.props.docsInfo.type]}`}> - {property.name}: + {property.name}:{' '} <Type type={property.type} sectionName={sectionName} docsInfo={this.props.docsInfo} /> </code> {property.source && ( diff --git a/packages/react-docs/src/components/interface.tsx b/packages/react-docs/src/components/interface.tsx index 541e164e3..bdfdf47c4 100644 --- a/packages/react-docs/src/components/interface.tsx +++ b/packages/react-docs/src/components/interface.tsx @@ -19,7 +19,7 @@ export function Interface(props: InterfaceProps) { return ( <span key={`property-${property.name}-${property.type}-${type.name}`}> {property.name}:{' '} - {property.type.typeDocType !== TypeDocTypes.Reflection ? ( + {property.type && property.type.typeDocType !== TypeDocTypes.Reflection ? ( <Type type={property.type} sectionName={props.sectionName} docsInfo={props.docsInfo} /> ) : ( <Signature @@ -27,7 +27,6 @@ export function Interface(props: InterfaceProps) { returnType={property.type.method.returnType} parameters={property.type.method.parameters} typeParameter={property.type.method.typeParameter} - callPath={property.type.method.callPath} sectionName={props.sectionName} shouldHideMethodName={true} shouldUseArrowSyntax={true} diff --git a/packages/react-docs/src/components/signature.tsx b/packages/react-docs/src/components/signature.tsx index 83fb1e246..1d3c90261 100644 --- a/packages/react-docs/src/components/signature.tsx +++ b/packages/react-docs/src/components/signature.tsx @@ -91,6 +91,7 @@ function renderParameters( ) { const params = _.map(parameters, (p: Parameter) => { const isOptional = p.isOptional; + const hasDefaultValue = !_.isUndefined(p.defaultValue); const type = ( <Type type={p.type} @@ -103,6 +104,7 @@ function renderParameters( <span key={`param-${p.type}-${p.name}`}> {p.name} {isOptional && '?'}: {type} + {hasDefaultValue && ` = ${p.defaultValue}`} </span> ); }); diff --git a/packages/react-docs/src/components/type.tsx b/packages/react-docs/src/components/type.tsx index fd4562ce3..2b7b49672 100644 --- a/packages/react-docs/src/components/type.tsx +++ b/packages/react-docs/src/components/type.tsx @@ -109,7 +109,6 @@ export function Type(props: TypeProps): any { returnType={type.method.returnType} parameters={type.method.parameters} typeParameter={type.method.typeParameter} - callPath={type.method.callPath} sectionName={props.sectionName} shouldHideMethodName={true} shouldUseArrowSyntax={true} diff --git a/packages/react-docs/src/types.ts b/packages/react-docs/src/types.ts index 2a300c164..3b4a57ad5 100644 --- a/packages/react-docs/src/types.ts +++ b/packages/react-docs/src/types.ts @@ -140,6 +140,7 @@ export interface Parameter { comment: string; isOptional: boolean; type: Type; + defaultValue?: string; } export interface TypeParameter { diff --git a/packages/react-docs/src/utils/typedoc_utils.ts b/packages/react-docs/src/utils/typedoc_utils.ts index 02f5b4049..9c89b135a 100644 --- a/packages/react-docs/src/utils/typedoc_utils.ts +++ b/packages/react-docs/src/utils/typedoc_utils.ts @@ -14,6 +14,7 @@ import { Type, TypeDocNode, TypeDocType, + TypeDocTypes, TypeParameter, TypescriptFunction, TypescriptMethod, @@ -221,9 +222,16 @@ export const typeDocUtils = { const childrenIfExist = !_.isUndefined(entity.children) ? _.map(entity.children, (child: TypeDocNode) => { - const childTypeIfExists = !_.isUndefined(child.type) + let childTypeIfExists = !_.isUndefined(child.type) ? typeDocUtils._convertType(child.type, sections, sectionName, docId) : undefined; + if (child.kindString === KindString.Method) { + childTypeIfExists = { + name: child.name, + typeDocType: TypeDocTypes.Reflection, + method: this._convertMethod(child, isConstructor, sections, sectionName, docId), + }; + } const c: CustomTypeChild = { name: child.name, type: childTypeIfExists, @@ -387,6 +395,7 @@ export const typeDocUtils = { name: entity.name, comment, isOptional, + defaultValue: entity.defaultValue, type, }; return parameter; diff --git a/packages/react-shared/CHANGELOG.json b/packages/react-shared/CHANGELOG.json index 858750253..737f46fd9 100644 --- a/packages/react-shared/CHANGELOG.json +++ b/packages/react-shared/CHANGELOG.json @@ -1,5 +1,14 @@ [ { + "timestamp": 1523462196, + "version": "0.1.2", + "changes": [ + { + "note": "Dependencies updated" + } + ] + }, + { "timestamp": 1522673609, "version": "0.1.1", "changes": [ diff --git a/packages/react-shared/CHANGELOG.md b/packages/react-shared/CHANGELOG.md index 6a2e7ec83..46119ad48 100644 --- a/packages/react-shared/CHANGELOG.md +++ b/packages/react-shared/CHANGELOG.md @@ -5,6 +5,10 @@ Edit the package's CHANGELOG.json file only. CHANGELOG +## v0.1.2 - _April 11, 2018_ + + * Dependencies updated + ## v0.1.1 - _April 2, 2018_ * Dependencies updated diff --git a/packages/react-shared/package.json b/packages/react-shared/package.json index 690da74fe..389052583 100644 --- a/packages/react-shared/package.json +++ b/packages/react-shared/package.json @@ -1,6 +1,6 @@ { "name": "@0xproject/react-shared", - "version": "0.1.1", + "version": "0.1.2", "description": "0x shared react components", "main": "lib/index.js", "types": "lib/index.d.ts", @@ -22,9 +22,9 @@ "url": "https://github.com/0xProject/0x-monorepo.git" }, "devDependencies": { - "@0xproject/dev-utils": "^0.3.4", - "@0xproject/monorepo-scripts": "^0.1.16", - "@0xproject/tslint-config": "^0.4.14", + "@0xproject/dev-utils": "^0.3.5", + "@0xproject/monorepo-scripts": "^0.1.17", + "@0xproject/tslint-config": "^0.4.15", "copyfiles": "^1.2.0", "shx": "^0.2.2", "tslint": "^5.9.1", diff --git a/packages/sol-cov/CHANGELOG.json b/packages/sol-cov/CHANGELOG.json index e24a264db..ca4c67f7e 100644 --- a/packages/sol-cov/CHANGELOG.json +++ b/packages/sol-cov/CHANGELOG.json @@ -1,5 +1,14 @@ [ { + "timestamp": 1523462196, + "version": "0.0.7", + "changes": [ + { + "note": "Dependencies updated" + } + ] + }, + { "timestamp": 1522673609, "version": "0.0.6", "changes": [ diff --git a/packages/sol-cov/CHANGELOG.md b/packages/sol-cov/CHANGELOG.md index e2e5d92ec..c55d751a8 100644 --- a/packages/sol-cov/CHANGELOG.md +++ b/packages/sol-cov/CHANGELOG.md @@ -5,6 +5,10 @@ Edit the package's CHANGELOG.json file only. CHANGELOG +## v0.0.7 - _April 11, 2018_ + + * Dependencies updated + ## v0.0.6 - _April 2, 2018_ * Dependencies updated diff --git a/packages/sol-cov/README.md b/packages/sol-cov/README.md index 8cc7dca6c..3a0377521 100644 --- a/packages/sol-cov/README.md +++ b/packages/sol-cov/README.md @@ -2,7 +2,7 @@ A Solidity code coverage tool. -### Read the [Documentation](0xproject.com/docs/sol-cov). +### Read the [Documentation](https://0xproject.com/docs/sol-cov). ## Installation diff --git a/packages/sol-cov/package.json b/packages/sol-cov/package.json index 6444fb876..277f40130 100644 --- a/packages/sol-cov/package.json +++ b/packages/sol-cov/package.json @@ -1,19 +1,20 @@ { "name": "@0xproject/sol-cov", - "version": "0.0.6", + "version": "0.0.7", "description": "Generate coverage reports for Solidity code", "main": "lib/src/index.js", "types": "lib/src/index.d.ts", "scripts": { "build:watch": "tsc -w", "lint": "tslint --project . 'src/**/*.ts'", - "test": "run-s clean build run_mocha", + "test": "run-s clean build compile_test run_mocha", "test:coverage": "nyc npm run test --all && yarn coverage:report:lcov", "coverage:report:lcov": "nyc report --reporter=text-lcov > coverage/lcov.info", "test:circleci": "yarn test:coverage", - "run_mocha": "mocha lib/test/**/*_test.js", + "run_mocha": "mocha lib/test/**/*_test.js --exit", "clean": "shx rm -rf lib scripts", "build": "copyfiles 'test/fixtures/**/*' ./lib && tsc && copyfiles -u 3 './lib/src/monorepo_scripts/**/*' ./scripts", + "compile_test": "node ../deployer/lib/src/cli.js compile --contracts SimpleStorage --contracts-dir test/fixtures/contracts --artifacts-dir test/fixtures/artifacts", "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", @@ -24,7 +25,8 @@ "assets": [], "docPublishConfigs": { "extraFileIncludes": [ - "../subproviders/src/types.ts" + "../subproviders/src/types.ts", + "../types/src/index.ts" ], "s3BucketPath": "s3://doc-jsons/sol-cov/", "s3StagingBucketPath": "s3://staging-doc-jsons/sol-cov/" @@ -41,9 +43,9 @@ }, "homepage": "https://github.com/0xProject/0x.js/packages/sol-cov/README.md", "dependencies": { - "@0xproject/subproviders": "^0.8.4", - "@0xproject/types": "^0.5.0", - "@0xproject/typescript-typings": "^0.0.3", + "@0xproject/subproviders": "^0.8.5", + "@0xproject/types": "^0.6.0", + "@0xproject/typescript-typings": "^0.1.0", "ethereumjs-util": "^5.1.1", "glob": "^7.1.2", "istanbul": "^0.4.5", @@ -52,8 +54,9 @@ "solidity-parser-antlr": "^0.2.8" }, "devDependencies": { - "@0xproject/monorepo-scripts": "^0.1.16", - "@0xproject/tslint-config": "^0.4.14", + "@0xproject/deployer": "^0.3.5", + "@0xproject/monorepo-scripts": "^0.1.17", + "@0xproject/tslint-config": "^0.4.15", "@types/istanbul": "^0.4.29", "@types/mocha": "^2.2.42", "@types/node": "^8.0.53", diff --git a/packages/sol-cov/src/collect_contract_data.ts b/packages/sol-cov/src/collect_contract_data.ts index a0ce2640f..1d8bc7178 100644 --- a/packages/sol-cov/src/collect_contract_data.ts +++ b/packages/sol-cov/src/collect_contract_data.ts @@ -6,30 +6,18 @@ import * as path from 'path'; import { ContractData } from './types'; export const collectContractsData = (artifactsPath: string, sourcesPath: string, networkId: number) => { - const sourcesGlob = `${sourcesPath}/**/*.sol`; - const sourceFileNames = glob.sync(sourcesGlob, { absolute: true }); - const contractsDataIfExists: Array<ContractData | {}> = _.map(sourceFileNames, sourceFileName => { - const baseName = path.basename(sourceFileName, '.sol'); - const artifactFileName = path.join(artifactsPath, `${baseName}.json`); - if (!fs.existsSync(artifactFileName)) { - // If the contract isn't directly compiled, but is imported as the part of the other contract - we don't - // have an artifact for it and therefore can't do anything useful with it - return {}; - } + const artifactsGlob = `${artifactsPath}/**/*.json`; + const artifactFileNames = glob.sync(artifactsGlob, { absolute: true }); + const contractsDataIfExists: Array<ContractData | {}> = _.map(artifactFileNames, artifactFileName => { const artifact = JSON.parse(fs.readFileSync(artifactFileName).toString()); - const sources = _.map(artifact.networks[networkId].sources, source => { - const includedFileName = glob.sync(`${sourcesPath}/**/${source}`, { absolute: true })[0]; - return includedFileName; - }); - const sourceCodes = _.map(sources, source => { - const includedSourceCode = fs.readFileSync(source).toString(); - return includedSourceCode; - }); + const sources = artifact.networks[networkId].sources; + const contractName = artifact.contract_name; + // We don't compute coverage for dependencies + const sourceCodes = _.map(sources, (source: string) => fs.readFileSync(source).toString()); if (_.isUndefined(artifact.networks[networkId])) { - throw new Error(`No ${baseName} artifacts found for networkId ${networkId}`); + throw new Error(`No ${contractName} artifacts found for networkId ${networkId}`); } const contractData = { - baseName, sourceCodes, sources, sourceMap: artifact.networks[networkId].source_map, diff --git a/packages/sol-cov/src/coverage_subprovider.ts b/packages/sol-cov/src/coverage_subprovider.ts index fc8b55188..6504d5a46 100644 --- a/packages/sol-cov/src/coverage_subprovider.ts +++ b/packages/sol-cov/src/coverage_subprovider.ts @@ -56,8 +56,8 @@ export class CoverageSubprovider extends Subprovider { * @param next Callback to call if this subprovider decides not to handle the request * @param end Callback to call if subprovider handled the request and wants to pass back the request. */ - // tslint:disable-next-line:prefer-function-over-method - public handleRequest(payload: JSONRPCRequestPayload, next: NextCallback, end: ErrorCallback) { + // tslint:disable-next-line:prefer-function-over-method async-suffix + public async handleRequest(payload: JSONRPCRequestPayload, next: NextCallback, end: ErrorCallback) { switch (payload.method) { case 'eth_sendTransaction': const txData = payload.params[0]; diff --git a/packages/sol-cov/src/types.ts b/packages/sol-cov/src/types.ts index d6491100b..01359d858 100644 --- a/packages/sol-cov/src/types.ts +++ b/packages/sol-cov/src/types.ts @@ -79,7 +79,6 @@ export interface ContractData { runtimeBytecode: string; sourceMapRuntime: string; sourceCodes: string[]; - baseName: string; sources: string[]; } diff --git a/packages/sol-cov/test/collect_contracts_data_test.ts b/packages/sol-cov/test/collect_contracts_data_test.ts index e793085e3..943a4a878 100644 --- a/packages/sol-cov/test/collect_contracts_data_test.ts +++ b/packages/sol-cov/test/collect_contracts_data_test.ts @@ -16,7 +16,6 @@ describe('Collect contracts data', () => { const contractsData = collectContractsData(artifactsPath, sourcesPath, networkId); _.forEach(contractsData, contractData => { expect(contractData).to.have.keys([ - 'baseName', 'sourceCodes', 'sources', 'sourceMap', diff --git a/packages/sol-cov/test/collect_coverage_entries_test.ts b/packages/sol-cov/test/collect_coverage_entries_test.ts index c7bc45bbf..c7b9d44b1 100644 --- a/packages/sol-cov/test/collect_coverage_entries_test.ts +++ b/packages/sol-cov/test/collect_coverage_entries_test.ts @@ -39,13 +39,13 @@ describe('Collect coverage entries', () => { const coverageEntries = collectCoverageEntries(simpleStorageContract); const fnIds = _.keys(coverageEntries.fnMap); expect(coverageEntries.fnMap[fnIds[0]].name).to.be.equal('set'); - expect(coverageEntries.fnMap[fnIds[0]].line).to.be.equal(3); + expect(coverageEntries.fnMap[fnIds[0]].line).to.be.equal(5); const setFunction = `function set(uint x) { storedData = x; }`; expect(getRange(simpleStorageContract, coverageEntries.fnMap[fnIds[0]].loc)).to.be.equal(setFunction); expect(coverageEntries.fnMap[fnIds[1]].name).to.be.equal('get'); - expect(coverageEntries.fnMap[fnIds[1]].line).to.be.equal(6); + expect(coverageEntries.fnMap[fnIds[1]].line).to.be.equal(8); const getFunction = `function get() constant returns (uint retVal) { return storedData; }`; diff --git a/packages/sol-cov/test/fixtures/artifacts/SimpleStorage.json b/packages/sol-cov/test/fixtures/artifacts/SimpleStorage.json deleted file mode 100644 index 416170ef2..000000000 --- a/packages/sol-cov/test/fixtures/artifacts/SimpleStorage.json +++ /dev/null @@ -1,64 +0,0 @@ -{ - "contract_name": "SimpleStorage", - "networks": { - "50": { - "solc_version": "0.4.21", - "keccak256": "0x18dc5b5a0e813c17e49936d2f2f7c07c51f050c09ba5e7206f17c855f23f4b6a", - "source_tree_hash": "0x18dc5b5a0e813c17e49936d2f2f7c07c51f050c09ba5e7206f17c855f23f4b6a", - "optimizer_enabled": 0, - "abi": [ - { - "constant": true, - "inputs": [], - "name": "storedData", - "outputs": [ - { - "name": "", - "type": "uint256" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": false, - "inputs": [ - { - "name": "x", - "type": "uint256" - } - ], - "name": "set", - "outputs": [], - "payable": false, - "stateMutability": "nonpayable", - "type": "function" - }, - { - "constant": true, - "inputs": [], - "name": "get", - "outputs": [ - { - "name": "retVal", - "type": "uint256" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - } - ], - "bytecode": - "0x6060604052341561000f57600080fd5b6101098061001e6000396000f3006060604052600436106053576000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff1680632a1afcd914605857806360fe47b114607e5780636d4ce63c14609e575b600080fd5b3415606257600080fd5b606860c4565b6040518082815260200191505060405180910390f35b3415608857600080fd5b609c600480803590602001909190505060ca565b005b341560a857600080fd5b60ae60d4565b6040518082815260200191505060405180910390f35b60005481565b8060008190555050565b600080549050905600a165627a7a723058207f743855fd0c71699620424a21a257cd197ed05032d6768eb9b874e4898f44c60029", - "runtime_bytecode": - "0x6060604052600436106053576000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff1680632a1afcd914605857806360fe47b114607e5780636d4ce63c14609e575b600080fd5b3415606257600080fd5b606860c4565b6040518082815260200191505060405180910390f35b3415608857600080fd5b609c600480803590602001909190505060ca565b005b341560a857600080fd5b60ae60d4565b6040518082815260200191505060405180910390f35b60005481565b8060008190555050565b600080549050905600a165627a7a723058207f743855fd0c71699620424a21a257cd197ed05032d6768eb9b874e4898f44c60029", - "updated_at": 1521118350895, - "source_map": "26:196:0:-;;;;;;;;;;;;;;;;;", - "source_map_runtime": - "26:196:0:-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;55:22;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;83:52;;;;;;;;;;;;;;;;;;;;;;;;;;140:80;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;55:22;;;;:::o;83:52::-;127:1;114:10;:14;;;;83:52;:::o;140:80::-;173:11;203:10;;196:17;;140:80;:::o", - "sources": ["SimpleStorage.sol"] - } - } -} diff --git a/packages/sol-cov/test/fixtures/artifacts/Simplest.json b/packages/sol-cov/test/fixtures/artifacts/Simplest.json deleted file mode 100644 index 8de60e481..000000000 --- a/packages/sol-cov/test/fixtures/artifacts/Simplest.json +++ /dev/null @@ -1,20 +0,0 @@ -{ - "contract_name": "Simplest", - "networks": { - "50": { - "solc_version": "0.4.21", - "keccak256": "0x8e7d62e19c7c7b8bf9a4a43749e111605950cc877574fb9640a1a07d1c3749f9", - "source_tree_hash": "0x8e7d62e19c7c7b8bf9a4a43749e111605950cc877574fb9640a1a07d1c3749f9", - "optimizer_enabled": 0, - "abi": [], - "bytecode": - "0x60606040523415600e57600080fd5b603580601b6000396000f3006060604052600080fd00a165627a7a7230582097cfe05b4d18d6ffb3a8d8fab0570cf09640d3131b9677ddb9be4e9fbcb65f010029", - "runtime_bytecode": - "0x6060604052600080fd00a165627a7a7230582097cfe05b4d18d6ffb3a8d8fab0570cf09640d3131b9677ddb9be4e9fbcb65f010029", - "updated_at": 1521118525393, - "source_map": "26:21:0:-;;;;;;;;;;;;;;;;;", - "source_map_runtime": "26:21:0:-;;;;;", - "sources": ["Simplest.sol"] - } - } -} diff --git a/packages/sol-cov/test/fixtures/contracts/SimpleStorage.sol b/packages/sol-cov/test/fixtures/contracts/SimpleStorage.sol index 178a52318..e4b4ac246 100644 --- a/packages/sol-cov/test/fixtures/contracts/SimpleStorage.sol +++ b/packages/sol-cov/test/fixtures/contracts/SimpleStorage.sol @@ -1,3 +1,5 @@ +pragma solidity ^0.4.21; + contract SimpleStorage { uint public storedData; function set(uint x) { diff --git a/packages/sol-resolver/package.json b/packages/sol-resolver/package.json new file mode 100644 index 000000000..ae1a94f3e --- /dev/null +++ b/packages/sol-resolver/package.json @@ -0,0 +1,39 @@ +{ + "name": "@0xproject/sol-resolver", + "version": "0.0.1", + "description": "Import resolver for smart contracts dependencies", + "main": "lib/index.js", + "types": "lib/index.d.ts", + "scripts": { + "build:watch": "tsc -w", + "build": "yarn clean && tsc && copyfiles -u 3 './lib/src/monorepo_scripts/**/*' ./scripts", + "clean": "shx rm -rf lib scripts", + "lint": "tslint --project .", + "manual:postpublish": "yarn build; node ./scripts/postpublish.js" + }, + "repository": { + "type": "git", + "url": "https://github.com/0xProject/0x-monorepo.git" + }, + "license": "Apache-2.0", + "bugs": { + "url": "https://github.com/0xProject/0x-monorepo/issues" + }, + "homepage": "https://github.com/0xProject/0x-monorepo/packages/resolver/README.md", + "devDependencies": { + "@0xproject/monorepo-scripts": "^0.1.16", + "@0xproject/tslint-config": "^0.4.14", + "copyfiles": "^1.2.0", + "shx": "^0.2.2", + "tslint": "5.8.0", + "typescript": "2.7.1" + }, + "dependencies": { + "@0xproject/typescript-typings": "^0.0.3", + "@0xproject/types": "^0.6.0", + "lodash": "^4.17.4" + }, + "publishConfig": { + "access": "public" + } +} diff --git a/packages/sol-resolver/src/index.ts b/packages/sol-resolver/src/index.ts new file mode 100644 index 000000000..cd6ec42ec --- /dev/null +++ b/packages/sol-resolver/src/index.ts @@ -0,0 +1,8 @@ +export { ContractSource, ContractSources } from './types'; +export { FallthroughResolver } from './resolvers/fallthrough_resolver'; +export { URLResolver } from './resolvers/url_resolver'; +export { NPMResolver } from './resolvers/npm_resolver'; +export { FSResolver } from './resolvers/fs_resolver'; +export { NameResolver } from './resolvers/name_resolver'; +export { EnumerableResolver } from './resolvers/enumerable_resolver'; +export { Resolver } from './resolvers/resolver'; diff --git a/packages/sol-resolver/src/resolvers/enumerable_resolver.ts b/packages/sol-resolver/src/resolvers/enumerable_resolver.ts new file mode 100644 index 000000000..0efa43e7c --- /dev/null +++ b/packages/sol-resolver/src/resolvers/enumerable_resolver.ts @@ -0,0 +1,7 @@ +import { ContractSource } from '../types'; + +import { Resolver } from './resolver'; + +export abstract class EnumerableResolver extends Resolver { + public abstract getAll(): ContractSource[]; +} diff --git a/packages/sol-resolver/src/resolvers/fallthrough_resolver.ts b/packages/sol-resolver/src/resolvers/fallthrough_resolver.ts new file mode 100644 index 000000000..8f6af9be0 --- /dev/null +++ b/packages/sol-resolver/src/resolvers/fallthrough_resolver.ts @@ -0,0 +1,21 @@ +import * as _ from 'lodash'; + +import { ContractSource } from '../types'; + +import { Resolver } from './resolver'; + +export class FallthroughResolver extends Resolver { + private _resolvers: Resolver[] = []; + public appendResolver(resolver: Resolver): void { + this._resolvers.push(resolver); + } + public resolveIfExists(importPath: string): ContractSource | undefined { + for (const resolver of this._resolvers) { + const contractSourceIfExists = resolver.resolveIfExists(importPath); + if (!_.isUndefined(contractSourceIfExists)) { + return contractSourceIfExists; + } + } + return undefined; + } +} diff --git a/packages/sol-resolver/src/resolvers/fs_resolver.ts b/packages/sol-resolver/src/resolvers/fs_resolver.ts new file mode 100644 index 000000000..4f05fba88 --- /dev/null +++ b/packages/sol-resolver/src/resolvers/fs_resolver.ts @@ -0,0 +1,19 @@ +import * as fs from 'fs'; + +import { ContractSource } from '../types'; + +import { Resolver } from './resolver'; + +export class FSResolver extends Resolver { + // tslint:disable-next-line:prefer-function-over-method + public resolveIfExists(importPath: string): ContractSource | undefined { + if (fs.existsSync(importPath)) { + const fileContent = fs.readFileSync(importPath).toString(); + return { + source: fileContent, + path: importPath, + }; + } + return undefined; + } +} diff --git a/packages/sol-resolver/src/resolvers/name_resolver.ts b/packages/sol-resolver/src/resolvers/name_resolver.ts new file mode 100644 index 000000000..6849b7610 --- /dev/null +++ b/packages/sol-resolver/src/resolvers/name_resolver.ts @@ -0,0 +1,66 @@ +import * as fs from 'fs'; +import * as _ from 'lodash'; +import * as path from 'path'; + +import { ContractSource } from '../types'; + +import { EnumerableResolver } from './enumerable_resolver'; + +export class NameResolver extends EnumerableResolver { + private _contractsDir: string; + constructor(contractsDir: string) { + super(); + this._contractsDir = contractsDir; + } + public resolveIfExists(lookupContractName: string): ContractSource | undefined { + const SOLIDITY_FILE_EXTENSION = '.sol'; + let contractSource: ContractSource | undefined; + const onFile = (filePath: string) => { + const contractName = path.basename(filePath, SOLIDITY_FILE_EXTENSION); + if (contractName === lookupContractName) { + const source = fs.readFileSync(filePath).toString(); + contractSource = { + source, + path: filePath, + }; + return true; + } + return undefined; + }; + this._traverseContractsDir(this._contractsDir, onFile); + return contractSource; + } + public getAll(): ContractSource[] { + const SOLIDITY_FILE_EXTENSION = '.sol'; + const contractSources: ContractSource[] = []; + const onFile = (filePath: string) => { + const contractName = path.basename(filePath, SOLIDITY_FILE_EXTENSION); + const source = fs.readFileSync(filePath).toString(); + const contractSource = { + source, + path: filePath, + }; + contractSources.push(contractSource); + }; + this._traverseContractsDir(this._contractsDir, onFile); + return contractSources; + } + // tslint:disable-next-line:prefer-function-over-method + private _traverseContractsDir(dirPath: string, onFile: (filePath: string) => true | void): boolean { + let dirContents: string[] = []; + try { + dirContents = fs.readdirSync(dirPath); + } catch (err) { + throw new Error(`No directory found at ${dirPath}`); + } + for (const fileName of dirContents) { + const entryPath = path.join(dirPath, fileName); + const isDirectory = fs.lstatSync(entryPath).isDirectory(); + const isComplete = isDirectory ? this._traverseContractsDir(entryPath, onFile) : onFile(entryPath); + if (isComplete) { + return isComplete; + } + } + return false; + } +} diff --git a/packages/sol-resolver/src/resolvers/npm_resolver.ts b/packages/sol-resolver/src/resolvers/npm_resolver.ts new file mode 100644 index 000000000..2c0a44aad --- /dev/null +++ b/packages/sol-resolver/src/resolvers/npm_resolver.ts @@ -0,0 +1,34 @@ +import * as fs from 'fs'; +import * as path from 'path'; + +import { ContractSource } from '../types'; + +import { Resolver } from './resolver'; + +export class NPMResolver extends Resolver { + private _packagePath: string; + constructor(packagePath: string) { + super(); + this._packagePath = packagePath; + } + public resolveIfExists(importPath: string): ContractSource | undefined { + if (!importPath.startsWith('/')) { + const [packageName, ...other] = importPath.split('/'); + const pathWithinPackage = path.join(...other); + let currentPath = this._packagePath; + const ROOT_PATH = '/'; + while (currentPath !== ROOT_PATH) { + const lookupPath = path.join(currentPath, 'node_modules', packageName, pathWithinPackage); + if (fs.existsSync(lookupPath)) { + const fileContent = fs.readFileSync(lookupPath).toString(); + return { + source: fileContent, + path: lookupPath, + }; + } + currentPath = path.dirname(currentPath); + } + } + return undefined; + } +} diff --git a/packages/sol-resolver/src/resolvers/resolver.ts b/packages/sol-resolver/src/resolvers/resolver.ts new file mode 100644 index 000000000..7edc9a85d --- /dev/null +++ b/packages/sol-resolver/src/resolvers/resolver.ts @@ -0,0 +1,14 @@ +import * as _ from 'lodash'; + +import { ContractSource } from '../types'; + +export abstract class Resolver { + public abstract resolveIfExists(importPath: string): ContractSource | undefined; + public resolve(importPath: string): ContractSource { + const contractSourceIfExists = this.resolveIfExists(importPath); + if (_.isUndefined(contractSourceIfExists)) { + throw new Error(`Failed to resolve ${importPath}`); + } + return contractSourceIfExists; + } +} diff --git a/packages/sol-resolver/src/resolvers/url_resolver.ts b/packages/sol-resolver/src/resolvers/url_resolver.ts new file mode 100644 index 000000000..180b0c9f6 --- /dev/null +++ b/packages/sol-resolver/src/resolvers/url_resolver.ts @@ -0,0 +1,21 @@ +import * as fs from 'fs'; + +import { ContractSource } from '../types'; + +import { Resolver } from './resolver'; + +export class URLResolver extends Resolver { + // tslint:disable-next-line:prefer-function-over-method + public resolveIfExists(importPath: string): ContractSource | undefined { + const FILE_URL_PREXIF = 'file://'; + if (importPath.startsWith(FILE_URL_PREXIF)) { + const filePath = importPath.substr(FILE_URL_PREXIF.length); + const fileContent = fs.readFileSync(filePath).toString(); + return { + source: fileContent, + path: importPath, + }; + } + return undefined; + } +} diff --git a/packages/sol-resolver/src/types.ts b/packages/sol-resolver/src/types.ts new file mode 100644 index 000000000..41492622d --- /dev/null +++ b/packages/sol-resolver/src/types.ts @@ -0,0 +1,8 @@ +export interface ContractSource { + source: string; + path: string; +} + +export interface ContractSources { + [key: string]: ContractSource; +} diff --git a/packages/sol-resolver/tsconfig.json b/packages/sol-resolver/tsconfig.json new file mode 100644 index 000000000..f5f4b37c2 --- /dev/null +++ b/packages/sol-resolver/tsconfig.json @@ -0,0 +1,7 @@ +{ + "extends": "../../tsconfig", + "compilerOptions": { + "outDir": "lib" + }, + "include": ["src/**/*"] +} diff --git a/packages/sol-resolver/tslint.json b/packages/sol-resolver/tslint.json new file mode 100644 index 000000000..ffaefe83a --- /dev/null +++ b/packages/sol-resolver/tslint.json @@ -0,0 +1,3 @@ +{ + "extends": ["@0xproject/tslint-config"] +} diff --git a/packages/sra-report/CHANGELOG.json b/packages/sra-report/CHANGELOG.json index 35c849e4e..d8200b0cd 100644 --- a/packages/sra-report/CHANGELOG.json +++ b/packages/sra-report/CHANGELOG.json @@ -1,5 +1,14 @@ [ { + "timestamp": 1523462196, + "version": "0.0.8", + "changes": [ + { + "note": "Dependencies updated" + } + ] + }, + { "timestamp": 1522673609, "version": "0.0.7", "changes": [ diff --git a/packages/sra-report/CHANGELOG.md b/packages/sra-report/CHANGELOG.md index eb45322b8..6dc4b3d2f 100644 --- a/packages/sra-report/CHANGELOG.md +++ b/packages/sra-report/CHANGELOG.md @@ -5,6 +5,10 @@ Edit the package's CHANGELOG.json file only. CHANGELOG +## v0.0.8 - _April 11, 2018_ + + * Dependencies updated + ## v0.0.7 - _April 2, 2018_ * Dependencies updated diff --git a/packages/sra-report/package.json b/packages/sra-report/package.json index 3c24ec312..578aea48f 100644 --- a/packages/sra-report/package.json +++ b/packages/sra-report/package.json @@ -1,22 +1,22 @@ { "name": "@0xproject/sra-report", - "version": "0.0.7", + "version": "0.0.8", "description": "Generate reports for standard relayer API compliance", - "main": "lib/index.js", - "types": "lib/index.d.ts", + "main": "lib/src/index.js", + "types": "lib/src/index.d.ts", "scripts": { "build:watch": "tsc -w", "clean": "shx rm -rf lib scripts", "build": "tsc && copyfiles -u 3 './lib/src/monorepo_scripts/**/*' ./scripts", - "lint": "tslint --project . 'src/**/*.ts' 'test/**/*.ts'", + "lint": "tslint --project .", "test": "run-s clean build copy_test_environments copy_test_fixtures run_mocha", "copy_test_fixtures": "copyfiles -u 2 './test/fixtures/**/*.json' ./lib/test/fixtures", "copy_test_environments": "copyfiles -u 2 './test/environments/**/*.json' ./lib/test/environments", - "run_mocha": "mocha lib/test/**/*_test.js", + "run_mocha": "mocha lib/test/**/*_test.js --exit", "manual:postpublish": "yarn build; node ./scripts/postpublish.js" }, "bin": { - "sra-report": "lib/index.js" + "sra-report": "lib/src/index.js" }, "repository": { "type": "git", @@ -28,20 +28,20 @@ }, "homepage": "https://github.com/0xProject/0x-monorepo/packages/sra-report/README.md", "dependencies": { - "0x.js": "^0.35.0", - "@0xproject/assert": "^0.2.5", - "@0xproject/connect": "^0.6.8", - "@0xproject/json-schemas": "^0.7.19", - "@0xproject/typescript-typings": "^0.0.3", - "@0xproject/utils": "^0.5.0", + "0x.js": "^0.36.0", + "@0xproject/assert": "^0.2.6", + "@0xproject/connect": "^0.6.9", + "@0xproject/json-schemas": "^0.7.20", + "@0xproject/typescript-typings": "^0.1.0", + "@0xproject/utils": "^0.5.1", "chalk": "^2.3.0", "lodash": "^4.17.4", "newman": "^3.9.3", "yargs": "^10.0.3" }, "devDependencies": { - "@0xproject/monorepo-scripts": "^0.1.16", - "@0xproject/tslint-config": "^0.4.14", + "@0xproject/monorepo-scripts": "^0.1.17", + "@0xproject/tslint-config": "^0.4.15", "@types/lodash": "4.14.104", "@types/mocha": "^2.2.48", "@types/nock": "^9.1.2", diff --git a/packages/subproviders/CHANGELOG.json b/packages/subproviders/CHANGELOG.json index f0702cd5d..d3ba7a928 100644 --- a/packages/subproviders/CHANGELOG.json +++ b/packages/subproviders/CHANGELOG.json @@ -1,12 +1,35 @@ [ { - "version": "0.8.5", + "version": "0.9.0", "changes": [ { - "note": "Add private key subprovider and refactor shared functionality into a base wallet subprovider", + "note": + "Refactor RedundantRPCSubprovider into RedundantSubprovider where it now accepts an array of subproviders rather then an array of RPC endpoints", + "pr": 500 + }, + { + "note": "Add PrivateKeySubprovider and refactor shared functionality into a base wallet subprovider", "pr": 506 + }, + { + "note": "Add MnemonicWalletsubprovider, deprecating our truffle-hdwallet-provider fork", + "pr": 507 + }, + { + "note": "Support multiple addresses in ledger and mnemonic wallets", + "pr": 507 + }, + { + "note": + "Refactors LedgerSubprovider such that explicitly setting the `pathIndex` is no longer required. Simply set the request `from` address as desired", + "pr": 507 + }, + { + "note": "Renamed derivationPath to baseDerivationPath.", + "pr": 507 } - ] + ], + "timestamp": 1523462196 }, { "timestamp": 1522673609, diff --git a/packages/subproviders/CHANGELOG.md b/packages/subproviders/CHANGELOG.md index 79711e7b7..85cd420dc 100644 --- a/packages/subproviders/CHANGELOG.md +++ b/packages/subproviders/CHANGELOG.md @@ -5,6 +5,10 @@ Edit the package's CHANGELOG.json file only. CHANGELOG +## v0.8.5 - _April 11, 2018_ + + * Add private key subprovider and refactor shared functionality into a base wallet subprovider (#506) + ## v0.8.4 - _April 2, 2018_ * Dependencies updated diff --git a/packages/subproviders/README.md b/packages/subproviders/README.md index 2936be545..8c8807895 100644 --- a/packages/subproviders/README.md +++ b/packages/subproviders/README.md @@ -4,7 +4,7 @@ A few useful web3 subproviders including a LedgerSubprovider useful for adding L We have written up a [Wiki](https://0xproject.com/wiki#Web3-Provider-Examples) article detailing some use cases of this subprovider package. -### Read the [Documentation](0xproject.com/docs/subproviders). +### Read the [Documentation](https://0xproject.com/docs/subproviders). ## Installation diff --git a/packages/subproviders/package.json b/packages/subproviders/package.json index cadbac0e8..c27b1d2fc 100644 --- a/packages/subproviders/package.json +++ b/packages/subproviders/package.json @@ -1,6 +1,6 @@ { "name": "@0xproject/subproviders", - "version": "0.8.4", + "version": "0.8.5", "main": "lib/src/index.js", "types": "lib/src/index.d.ts", "license": "Apache-2.0", @@ -21,31 +21,31 @@ "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" + "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": { "assets": [], "docPublishConfigs": { - "extraFileIncludes": [ - "../types/src/index.ts" - ], + "extraFileIncludes": ["../types/src/index.ts"], "s3BucketPath": "s3://doc-jsons/subproviders/", "s3StagingBucketPath": "s3://staging-doc-jsons/subproviders/" } } }, "dependencies": { - "@0xproject/assert": "^0.2.5", - "@0xproject/types": "^0.5.0", - "@0xproject/typescript-typings": "^0.0.3", - "@0xproject/utils": "^0.5.0", + "@0xproject/assert": "^0.2.6", + "@0xproject/types": "^0.6.0", + "@0xproject/typescript-typings": "^0.1.0", + "@0xproject/utils": "^0.5.1", "@ledgerhq/hw-app-eth": "^4.3.0", "@ledgerhq/hw-transport-u2f": "^4.3.0", "bn.js": "^4.11.8", "ethereumjs-tx": "^1.3.3", "ethereumjs-util": "^5.1.1", "ganache-core": "0xProject/ganache-core", + "bip39": "^2.5.0", "hdkey": "^0.7.1", "lodash": "^4.17.4", "semaphore-async-await": "^1.5.1", @@ -53,9 +53,10 @@ "web3-provider-engine": "^13.0.1" }, "devDependencies": { - "@0xproject/monorepo-scripts": "^0.1.16", - "@0xproject/tslint-config": "^0.4.14", - "@0xproject/utils": "^0.5.0", + "@0xproject/monorepo-scripts": "^0.1.17", + "@0xproject/tslint-config": "^0.4.15", + "@0xproject/utils": "^0.5.1", + "@types/bip39": "^2.4.0", "@types/lodash": "4.14.104", "@types/mocha": "^2.2.42", "@types/node": "^8.0.53", diff --git a/packages/subproviders/src/globals.d.ts b/packages/subproviders/src/globals.d.ts index c5ad26876..4b3ecdf3c 100644 --- a/packages/subproviders/src/globals.d.ts +++ b/packages/subproviders/src/globals.d.ts @@ -51,17 +51,6 @@ declare module '@ledgerhq/hw-transport-node-hid' { } } -// hdkey declarations -declare module 'hdkey' { - class HDNode { - public publicKey: Buffer; - public chainCode: Buffer; - public constructor(); - public derive(path: string): HDNode; - } - export = HDNode; -} - declare module '*.json' { const json: any; /* tslint:disable */ diff --git a/packages/subproviders/src/index.ts b/packages/subproviders/src/index.ts index dd553fde4..ff28b8a8d 100644 --- a/packages/subproviders/src/index.ts +++ b/packages/subproviders/src/index.ts @@ -7,17 +7,17 @@ import { LedgerEthereumClient } from './types'; export { EmptyWalletSubprovider } from './subproviders/empty_wallet_subprovider'; export { FakeGasEstimateSubprovider } from './subproviders/fake_gas_estimate_subprovider'; export { InjectedWeb3Subprovider } from './subproviders/injected_web3'; -export { RedundantRPCSubprovider } from './subproviders/redundant_rpc'; +export { RedundantSubprovider } from './subproviders/redundant_subprovider'; export { LedgerSubprovider } from './subproviders/ledger'; export { GanacheSubprovider } from './subproviders/ganache'; export { Subprovider } from './subproviders/subprovider'; export { NonceTrackerSubprovider } from './subproviders/nonce_tracker'; -export { PrivateKeyWalletSubprovider } from './subproviders/private_key_wallet_subprovider'; +export { PrivateKeyWalletSubprovider } from './subproviders/private_key_wallet'; +export { MnemonicWalletSubprovider } from './subproviders/mnemonic_wallet'; export { Callback, ErrorCallback, NextCallback, - LedgerWalletSubprovider, LedgerCommunicationClient, NonceSubproviderErrors, LedgerSubproviderConfigs, diff --git a/packages/subproviders/src/subproviders/base_wallet_subprovider.ts b/packages/subproviders/src/subproviders/base_wallet_subprovider.ts index 034f83e7f..0a9b99ae4 100644 --- a/packages/subproviders/src/subproviders/base_wallet_subprovider.ts +++ b/packages/subproviders/src/subproviders/base_wallet_subprovider.ts @@ -21,7 +21,7 @@ export abstract class BaseWalletSubprovider extends Subprovider { public abstract async getAccountsAsync(): Promise<string[]>; public abstract async signTransactionAsync(txParams: PartialTxParams): Promise<string>; - public abstract async signPersonalMessageAsync(data: string): Promise<string>; + public abstract async signPersonalMessageAsync(data: string, address: string): Promise<string>; /** * This method conforms to the web3-provider-engine interface. @@ -85,8 +85,9 @@ export abstract class BaseWalletSubprovider extends Subprovider { case 'eth_sign': case 'personal_sign': const data = payload.method === 'eth_sign' ? payload.params[1] : payload.params[0]; + const address = payload.method === 'eth_sign' ? payload.params[0] : payload.params[1]; try { - const ecSignatureHex = await this.signPersonalMessageAsync(data); + const ecSignatureHex = await this.signPersonalMessageAsync(data, address); end(null, ecSignatureHex); } catch (err) { end(err); diff --git a/packages/subproviders/src/subproviders/empty_wallet_subprovider.ts b/packages/subproviders/src/subproviders/empty_wallet_subprovider.ts index 595ec654d..8f152dc0a 100644 --- a/packages/subproviders/src/subproviders/empty_wallet_subprovider.ts +++ b/packages/subproviders/src/subproviders/empty_wallet_subprovider.ts @@ -17,8 +17,8 @@ export class EmptyWalletSubprovider extends Subprovider { * @param next Callback to call if this subprovider decides not to handle the request * @param end Callback to call if subprovider handled the request and wants to pass back the request. */ - // tslint:disable-next-line:prefer-function-over-method - public handleRequest(payload: JSONRPCRequestPayload, next: Callback, end: ErrorCallback) { + // tslint:disable-next-line:prefer-function-over-method async-suffix + public async handleRequest(payload: JSONRPCRequestPayload, next: Callback, end: ErrorCallback) { switch (payload.method) { case 'eth_accounts': end(null, []); diff --git a/packages/subproviders/src/subproviders/fake_gas_estimate_subprovider.ts b/packages/subproviders/src/subproviders/fake_gas_estimate_subprovider.ts index 966c37d8a..54fd7bcb9 100644 --- a/packages/subproviders/src/subproviders/fake_gas_estimate_subprovider.ts +++ b/packages/subproviders/src/subproviders/fake_gas_estimate_subprovider.ts @@ -31,8 +31,8 @@ export class FakeGasEstimateSubprovider extends Subprovider { * @param next Callback to call if this subprovider decides not to handle the request * @param end Callback to call if subprovider handled the request and wants to pass back the request. */ - // tslint:disable-next-line:prefer-function-over-method - public handleRequest(payload: JSONRPCRequestPayload, next: Callback, end: ErrorCallback) { + // tslint:disable-next-line:prefer-function-over-method async-suffix + public async handleRequest(payload: JSONRPCRequestPayload, next: Callback, end: ErrorCallback) { switch (payload.method) { case 'eth_estimateGas': end(null, this._constantGasAmount); diff --git a/packages/subproviders/src/subproviders/ganache.ts b/packages/subproviders/src/subproviders/ganache.ts index 8008d1b4b..debd7ecf0 100644 --- a/packages/subproviders/src/subproviders/ganache.ts +++ b/packages/subproviders/src/subproviders/ganache.ts @@ -27,8 +27,8 @@ export class GanacheSubprovider extends Subprovider { * @param next Callback to call if this subprovider decides not to handle the request * @param end Callback to call if subprovider handled the request and wants to pass back the request. */ - // tslint:disable-next-line:prefer-function-over-method - public handleRequest(payload: JSONRPCRequestPayload, next: Callback, end: ErrorCallback) { + // tslint:disable-next-line:prefer-function-over-method async-suffix + public async handleRequest(payload: JSONRPCRequestPayload, next: Callback, end: ErrorCallback) { this._ganacheProvider.sendAsync(payload, (err: Error | null, result: any) => { end(err, result && result.result); }); diff --git a/packages/subproviders/src/subproviders/injected_web3.ts b/packages/subproviders/src/subproviders/injected_web3.ts index 1d7b2ddfe..3ca0c4bd0 100644 --- a/packages/subproviders/src/subproviders/injected_web3.ts +++ b/packages/subproviders/src/subproviders/injected_web3.ts @@ -30,8 +30,8 @@ export class InjectedWeb3Subprovider extends Subprovider { * @param next Callback to call if this subprovider decides not to handle the request * @param end Callback to call if subprovider handled the request and wants to pass back the request. */ - // tslint:disable-next-line:prefer-function-over-method - public handleRequest(payload: JSONRPCRequestPayload, next: Callback, end: ErrorCallback) { + // tslint:disable-next-line:prefer-function-over-method async-suffix + public async handleRequest(payload: JSONRPCRequestPayload, next: Callback, end: ErrorCallback) { switch (payload.method) { case 'web3_clientVersion': this._injectedWeb3.version.getNode(end); diff --git a/packages/subproviders/src/subproviders/ledger.ts b/packages/subproviders/src/subproviders/ledger.ts index aa86bf6c0..563e5a56a 100644 --- a/packages/subproviders/src/subproviders/ledger.ts +++ b/packages/subproviders/src/subproviders/ledger.ts @@ -1,5 +1,4 @@ import { assert } from '@0xproject/assert'; -import { JSONRPCRequestPayload } from '@0xproject/types'; import { addressUtils } from '@0xproject/utils'; import EthereumTx = require('ethereumjs-tx'); import ethUtil = require('ethereumjs-util'); @@ -9,6 +8,7 @@ import { Lock } from 'semaphore-async-await'; import { Callback, + DerivedHDKeyInfo, LedgerEthereumClient, LedgerEthereumClientFactoryAsync, LedgerSubproviderConfigs, @@ -17,13 +17,15 @@ import { ResponseWithTxParams, WalletSubproviderErrors, } from '../types'; +import { walletUtils } from '../utils/wallet_utils'; import { BaseWalletSubprovider } from './base_wallet_subprovider'; -const DEFAULT_DERIVATION_PATH = `44'/60'/0'`; -const DEFAULT_NUM_ADDRESSES_TO_FETCH = 10; +const DEFAULT_BASE_DERIVATION_PATH = `44'/60'/0'`; const ASK_FOR_ON_DEVICE_CONFIRMATION = false; const SHOULD_GET_CHAIN_CODE = true; +const DEFAULT_NUM_ADDRESSES_TO_FETCH = 10; +const DEFAULT_ADDRESS_SEARCH_LIMIT = 1000; /** * Subprovider for interfacing with a user's [Ledger Nano S](https://www.ledgerwallet.com/products/ledger-nano-s). @@ -34,11 +36,11 @@ export class LedgerSubprovider extends BaseWalletSubprovider { private _nonceLock = new Lock(); private _connectionLock = new Lock(); private _networkId: number; - private _derivationPath: string; - private _derivationPathIndex: number; + private _baseDerivationPath: string; private _ledgerEthereumClientFactoryAsync: LedgerEthereumClientFactoryAsync; private _ledgerClientIfExists?: LedgerEthereumClient; private _shouldAlwaysAskForConfirmation: boolean; + private _addressSearchLimit: number; /** * Instantiates a LedgerSubprovider. Defaults to derivationPath set to `44'/60'/0'`. * TestRPC/Ganache defaults to `m/44'/60'/0'/0`, so set this in the configs if desired. @@ -49,40 +51,35 @@ export class LedgerSubprovider extends BaseWalletSubprovider { super(); this._networkId = config.networkId; this._ledgerEthereumClientFactoryAsync = config.ledgerEthereumClientFactoryAsync; - this._derivationPath = config.derivationPath || DEFAULT_DERIVATION_PATH; + this._baseDerivationPath = config.baseDerivationPath || DEFAULT_BASE_DERIVATION_PATH; this._shouldAlwaysAskForConfirmation = !_.isUndefined(config.accountFetchingConfigs) && !_.isUndefined(config.accountFetchingConfigs.shouldAskForOnDeviceConfirmation) ? config.accountFetchingConfigs.shouldAskForOnDeviceConfirmation : ASK_FOR_ON_DEVICE_CONFIRMATION; - this._derivationPathIndex = 0; + this._addressSearchLimit = + !_.isUndefined(config.accountFetchingConfigs) && + !_.isUndefined(config.accountFetchingConfigs.addressSearchLimit) + ? config.accountFetchingConfigs.addressSearchLimit + : DEFAULT_ADDRESS_SEARCH_LIMIT; } /** * Retrieve the set derivation path * @returns derivation path */ public getPath(): string { - return this._derivationPath; + return this._baseDerivationPath; } /** * Set a desired derivation path when computing the available user addresses - * @param derivationPath The desired derivation path (e.g `44'/60'/0'`) - */ - public setPath(derivationPath: string) { - this._derivationPath = derivationPath; - } - /** - * Set the final derivation path index. If a user wishes to sign a message with the - * 6th address in a derivation path, before calling `signPersonalMessageAsync`, you must - * call this method with pathIndex `6`. - * @param pathIndex Desired derivation path index + * @param basDerivationPath The desired derivation path (e.g `44'/60'/0'`) */ - public setPathIndex(pathIndex: number) { - this._derivationPathIndex = pathIndex; + public setPath(basDerivationPath: string) { + this._baseDerivationPath = basDerivationPath; } /** * Retrieve a users Ledger accounts. The accounts are derived from the derivationPath, - * master public key and chainCode. Because of this, you can request as many accounts + * master public key and chain code. Because of this, you can request as many accounts * as you wish and it only requires a single request to the Ledger device. This method * is automatically called when issuing a `eth_accounts` JSON RPC request via your providerEngine * instance. @@ -90,46 +87,27 @@ export class LedgerSubprovider extends BaseWalletSubprovider { * @return An array of accounts */ public async getAccountsAsync(numberOfAccounts: number = DEFAULT_NUM_ADDRESSES_TO_FETCH): Promise<string[]> { - this._ledgerClientIfExists = await this._createLedgerClientAsync(); - - let ledgerResponse; - try { - ledgerResponse = await this._ledgerClientIfExists.getAddress( - this._derivationPath, - this._shouldAlwaysAskForConfirmation, - SHOULD_GET_CHAIN_CODE, - ); - } finally { - await this._destroyLedgerClientAsync(); - } - - const hdKey = new HDNode(); - hdKey.publicKey = new Buffer(ledgerResponse.publicKey, 'hex'); - hdKey.chainCode = new Buffer(ledgerResponse.chainCode, 'hex'); - - const accounts: string[] = []; - for (let i = 0; i < numberOfAccounts; i++) { - const derivedHDNode = hdKey.derive(`m/${i + this._derivationPathIndex}`); - const derivedPublicKey = derivedHDNode.publicKey; - const shouldSanitizePublicKey = true; - const ethereumAddressUnprefixed = ethUtil - .publicToAddress(derivedPublicKey, shouldSanitizePublicKey) - .toString('hex'); - const ethereumAddressPrefixed = ethUtil.addHexPrefix(ethereumAddressUnprefixed); - accounts.push(ethereumAddressPrefixed.toLowerCase()); - } + const initialDerivedKeyInfo = await this._initialDerivedKeyInfoAsync(); + const derivedKeyInfos = walletUtils.calculateDerivedHDKeyInfos(initialDerivedKeyInfo, numberOfAccounts); + const accounts = _.map(derivedKeyInfos, k => k.address); return accounts; } /** - * Sign a transaction with the Ledger. If you've added the LedgerSubprovider to your - * app's provider, you can simply send an `eth_sendTransaction` JSON RPC request, and - * this method will be called auto-magically. If you are not using this via a ProviderEngine + * Signs a transaction on the Ledger with the account specificed by the `from` field in txParams. + * If you've added the LedgerSubprovider to your app's provider, you can simply send an `eth_sendTransaction` + * JSON RPC request, and this method will be called auto-magically. If you are not using this via a ProviderEngine * instance, you can call it directly. * @param txParams Parameters of the transaction to sign * @return Signed transaction hex string */ public async signTransactionAsync(txParams: PartialTxParams): Promise<string> { LedgerSubprovider._validateTxParams(txParams); + if (_.isUndefined(txParams.from) || !addressUtils.isAddress(txParams.from)) { + throw new Error(WalletSubproviderErrors.FromAddressMissingOrInvalid); + } + const initialDerivedKeyInfo = await this._initialDerivedKeyInfoAsync(); + const derivedKeyInfo = this._findDerivedKeyInfoForAddress(initialDerivedKeyInfo, txParams.from); + this._ledgerClientIfExists = await this._createLedgerClientAsync(); const tx = new EthereumTx(txParams); @@ -141,8 +119,8 @@ export class LedgerSubprovider extends BaseWalletSubprovider { const txHex = tx.serialize().toString('hex'); try { - const derivationPath = this._getDerivationPath(); - const result = await this._ledgerClientIfExists.signTransaction(derivationPath, txHex); + const fullDerivationPath = derivedKeyInfo.derivationPath; + const result = await this._ledgerClientIfExists.signTransaction(fullDerivationPath, txHex); // Store signature in transaction tx.r = Buffer.from(result.r, 'hex'); tx.s = Buffer.from(result.s, 'hex'); @@ -165,25 +143,30 @@ export class LedgerSubprovider extends BaseWalletSubprovider { } } /** - * Sign a personal Ethereum signed message. The signing address will be the one - * retrieved given a derivationPath and pathIndex set on the subprovider. + * Sign a personal Ethereum signed message. The signing account will be the account + * associated with the provided address. * The Ledger adds the Ethereum signed message prefix on-device. If you've added * the LedgerSubprovider to your app's provider, you can simply send an `eth_sign` * or `personal_sign` JSON RPC request, and this method will be called auto-magically. * If you are not using this via a ProviderEngine instance, you can call it directly. - * @param data Message to sign + * @param data Hex string message to sign + * @param address Address of the account to sign with * @return Signature hex string (order: rsv) */ - public async signPersonalMessageAsync(data: string): Promise<string> { + public async signPersonalMessageAsync(data: string, address: string): Promise<string> { if (_.isUndefined(data)) { throw new Error(WalletSubproviderErrors.DataMissingForSignPersonalMessage); } assert.isHexString('data', data); + assert.isETHAddressHex('address', address); + const initialDerivedKeyInfo = await this._initialDerivedKeyInfoAsync(); + const derivedKeyInfo = this._findDerivedKeyInfoForAddress(initialDerivedKeyInfo, address); + this._ledgerClientIfExists = await this._createLedgerClientAsync(); try { - const derivationPath = this._getDerivationPath(); + const fullDerivationPath = derivedKeyInfo.derivationPath; const result = await this._ledgerClientIfExists.signPersonalMessage( - derivationPath, + fullDerivationPath, ethUtil.stripHexPrefix(data), ); const v = result.v - 27; @@ -199,10 +182,6 @@ export class LedgerSubprovider extends BaseWalletSubprovider { throw err; } } - private _getDerivationPath() { - const derivationPath = `${this.getPath()}/${this._derivationPathIndex}`; - return derivationPath; - } private async _createLedgerClientAsync(): Promise<LedgerEthereumClient> { await this._connectionLock.acquire(); if (!_.isUndefined(this._ledgerClientIfExists)) { @@ -223,4 +202,41 @@ export class LedgerSubprovider extends BaseWalletSubprovider { this._ledgerClientIfExists = undefined; this._connectionLock.release(); } + private async _initialDerivedKeyInfoAsync(): Promise<DerivedHDKeyInfo> { + this._ledgerClientIfExists = await this._createLedgerClientAsync(); + + const parentKeyDerivationPath = `m/${this._baseDerivationPath}`; + let ledgerResponse; + try { + ledgerResponse = await this._ledgerClientIfExists.getAddress( + parentKeyDerivationPath, + this._shouldAlwaysAskForConfirmation, + SHOULD_GET_CHAIN_CODE, + ); + } finally { + await this._destroyLedgerClientAsync(); + } + const hdKey = new HDNode(); + hdKey.publicKey = new Buffer(ledgerResponse.publicKey, 'hex'); + hdKey.chainCode = new Buffer(ledgerResponse.chainCode, 'hex'); + const address = walletUtils.addressOfHDKey(hdKey); + const initialDerivedKeyInfo = { + hdKey, + address, + derivationPath: parentKeyDerivationPath, + baseDerivationPath: this._baseDerivationPath, + }; + return initialDerivedKeyInfo; + } + private _findDerivedKeyInfoForAddress(initalHDKey: DerivedHDKeyInfo, address: string): DerivedHDKeyInfo { + const matchedDerivedKeyInfo = walletUtils.findDerivedKeyInfoForAddressIfExists( + address, + initalHDKey, + this._addressSearchLimit, + ); + if (_.isUndefined(matchedDerivedKeyInfo)) { + throw new Error(`${WalletSubproviderErrors.AddressNotFound}: ${address}`); + } + return matchedDerivedKeyInfo; + } } diff --git a/packages/subproviders/src/subproviders/mnemonic_wallet.ts b/packages/subproviders/src/subproviders/mnemonic_wallet.ts new file mode 100644 index 000000000..080bfeb4c --- /dev/null +++ b/packages/subproviders/src/subproviders/mnemonic_wallet.ts @@ -0,0 +1,145 @@ +import { assert } from '@0xproject/assert'; +import { addressUtils } from '@0xproject/utils'; +import * as bip39 from 'bip39'; +import ethUtil = require('ethereumjs-util'); +import HDNode = require('hdkey'); +import * as _ from 'lodash'; + +import { DerivedHDKeyInfo, MnemonicWalletSubproviderConfigs, PartialTxParams, WalletSubproviderErrors } from '../types'; +import { walletUtils } from '../utils/wallet_utils'; + +import { BaseWalletSubprovider } from './base_wallet_subprovider'; +import { PrivateKeyWalletSubprovider } from './private_key_wallet'; + +const DEFAULT_BASE_DERIVATION_PATH = `44'/60'/0'/0`; +const DEFAULT_NUM_ADDRESSES_TO_FETCH = 10; +const DEFAULT_ADDRESS_SEARCH_LIMIT = 1000; + +/** + * This class implements the [web3-provider-engine](https://github.com/MetaMask/provider-engine) subprovider interface. + * This subprovider intercepts all account related RPC requests (e.g message/transaction signing, etc...) and handles + * all requests with accounts derived from the supplied mnemonic. + */ +export class MnemonicWalletSubprovider extends BaseWalletSubprovider { + private _addressSearchLimit: number; + private _baseDerivationPath: string; + private _derivedKeyInfo: DerivedHDKeyInfo; + private _mnemonic: string; + + /** + * Instantiates a MnemonicWalletSubprovider. Defaults to baseDerivationPath set to `44'/60'/0'/0`. + * This is the default in TestRPC/Ganache, it can be overridden if desired. + * @param config Configuration for the mnemonic wallet, must contain the mnemonic + * @return MnemonicWalletSubprovider instance + */ + constructor(config: MnemonicWalletSubproviderConfigs) { + assert.isString('mnemonic', config.mnemonic); + const baseDerivationPath = config.baseDerivationPath || DEFAULT_BASE_DERIVATION_PATH; + assert.isString('baseDerivationPath', baseDerivationPath); + const addressSearchLimit = config.addressSearchLimit || DEFAULT_ADDRESS_SEARCH_LIMIT; + assert.isNumber('addressSearchLimit', addressSearchLimit); + super(); + + this._mnemonic = config.mnemonic; + this._baseDerivationPath = baseDerivationPath; + this._addressSearchLimit = addressSearchLimit; + this._derivedKeyInfo = this._initialDerivedKeyInfo(this._baseDerivationPath); + } + /** + * Retrieve the set derivation path + * @returns derivation path + */ + public getPath(): string { + return this._baseDerivationPath; + } + /** + * Set a desired derivation path when computing the available user addresses + * @param baseDerivationPath The desired derivation path (e.g `44'/60'/0'`) + */ + public setPath(baseDerivationPath: string) { + this._baseDerivationPath = baseDerivationPath; + this._derivedKeyInfo = this._initialDerivedKeyInfo(this._baseDerivationPath); + } + /** + * Retrieve the accounts associated with the mnemonic. + * This method is implicitly called when issuing a `eth_accounts` JSON RPC request + * via your providerEngine instance. + * @param numberOfAccounts Number of accounts to retrieve (default: 10) + * @return An array of accounts + */ + public async getAccountsAsync(numberOfAccounts: number = DEFAULT_NUM_ADDRESSES_TO_FETCH): Promise<string[]> { + const derivedKeys = walletUtils.calculateDerivedHDKeyInfos(this._derivedKeyInfo, numberOfAccounts); + const accounts = _.map(derivedKeys, k => k.address); + return accounts; + } + + /** + * Signs a transaction with the account specificed by the `from` field in txParams. + * If you've added this Subprovider to your app's provider, you can simply send + * an `eth_sendTransaction` JSON RPC request, and this method will be called auto-magically. + * If you are not using this via a ProviderEngine instance, you can call it directly. + * @param txParams Parameters of the transaction to sign + * @return Signed transaction hex string + */ + public async signTransactionAsync(txParams: PartialTxParams): Promise<string> { + if (_.isUndefined(txParams.from) || !addressUtils.isAddress(txParams.from)) { + throw new Error(WalletSubproviderErrors.FromAddressMissingOrInvalid); + } + const privateKeyWallet = this._privateKeyWalletForAddress(txParams.from); + const signedTx = privateKeyWallet.signTransactionAsync(txParams); + return signedTx; + } + /** + * Sign a personal Ethereum signed message. The signing account will be the account + * associated with the provided address. + * If you've added the MnemonicWalletSubprovider to your app's provider, you can simply send an `eth_sign` + * or `personal_sign` JSON RPC request, and this method will be called auto-magically. + * If you are not using this via a ProviderEngine instance, you can call it directly. + * @param data Hex string message to sign + * @param address Address of the account to sign with + * @return Signature hex string (order: rsv) + */ + public async signPersonalMessageAsync(data: string, address: string): Promise<string> { + if (_.isUndefined(data)) { + throw new Error(WalletSubproviderErrors.DataMissingForSignPersonalMessage); + } + assert.isHexString('data', data); + assert.isETHAddressHex('address', address); + const privateKeyWallet = this._privateKeyWalletForAddress(address); + const sig = await privateKeyWallet.signPersonalMessageAsync(data, address); + return sig; + } + private _privateKeyWalletForAddress(address: string): PrivateKeyWalletSubprovider { + const derivedKeyInfo = this._findDerivedKeyInfoForAddress(address); + const privateKeyHex = derivedKeyInfo.hdKey.privateKey.toString('hex'); + const privateKeyWallet = new PrivateKeyWalletSubprovider(privateKeyHex); + return privateKeyWallet; + } + private _findDerivedKeyInfoForAddress(address: string): DerivedHDKeyInfo { + const matchedDerivedKeyInfo = walletUtils.findDerivedKeyInfoForAddressIfExists( + address, + this._derivedKeyInfo, + this._addressSearchLimit, + ); + if (_.isUndefined(matchedDerivedKeyInfo)) { + throw new Error(`${WalletSubproviderErrors.AddressNotFound}: ${address}`); + } + return matchedDerivedKeyInfo; + } + private _initialDerivedKeyInfo(baseDerivationPath: string): DerivedHDKeyInfo { + const seed = bip39.mnemonicToSeed(this._mnemonic); + const hdKey = HDNode.fromMasterSeed(seed); + // Walk down to base derivation level (i.e m/44'/60'/0') and create an initial key at that level + // all children will then be walked relative (i.e m/0) + const parentKeyDerivationPath = `m/${baseDerivationPath}`; + const parentHDKeyAtDerivationPath = hdKey.derive(parentKeyDerivationPath); + const address = walletUtils.addressOfHDKey(parentHDKeyAtDerivationPath); + const derivedKeyInfo = { + address, + baseDerivationPath, + derivationPath: parentKeyDerivationPath, + hdKey: parentHDKeyAtDerivationPath, + }; + return derivedKeyInfo; + } +} diff --git a/packages/subproviders/src/subproviders/private_key_wallet_subprovider.ts b/packages/subproviders/src/subproviders/private_key_wallet.ts index c3a53773a..b3f48fd90 100644 --- a/packages/subproviders/src/subproviders/private_key_wallet_subprovider.ts +++ b/packages/subproviders/src/subproviders/private_key_wallet.ts @@ -1,13 +1,11 @@ import { assert } from '@0xproject/assert'; -import { JSONRPCRequestPayload } from '@0xproject/types'; import EthereumTx = require('ethereumjs-tx'); import * as ethUtil from 'ethereumjs-util'; import * as _ from 'lodash'; -import { Callback, ErrorCallback, PartialTxParams, ResponseWithTxParams, WalletSubproviderErrors } from '../types'; +import { PartialTxParams, WalletSubproviderErrors } from '../types'; import { BaseWalletSubprovider } from './base_wallet_subprovider'; -import { Subprovider } from './subprovider'; /** * This class implements the [web3-provider-engine](https://github.com/MetaMask/provider-engine) subprovider interface. @@ -17,6 +15,11 @@ import { Subprovider } from './subprovider'; export class PrivateKeyWalletSubprovider extends BaseWalletSubprovider { private _address: string; private _privateKeyBuffer: Buffer; + /** + * Instantiates a PrivateKeyWalletSubprovider. + * @param privateKey The corresponding private key to an Ethereum address + * @return PrivateKeyWalletSubprovider instance + */ constructor(privateKey: string) { assert.isString('privateKey', privateKey); super(); @@ -42,26 +45,40 @@ export class PrivateKeyWalletSubprovider extends BaseWalletSubprovider { */ public async signTransactionAsync(txParams: PartialTxParams): Promise<string> { PrivateKeyWalletSubprovider._validateTxParams(txParams); + if (!_.isUndefined(txParams.from) && txParams.from !== this._address) { + throw new Error( + `Requested to sign transaction with address: ${txParams.from}, instantiated with address: ${ + this._address + }`, + ); + } const tx = new EthereumTx(txParams); tx.sign(this._privateKeyBuffer); const rawTx = `0x${tx.serialize().toString('hex')}`; return rawTx; } /** - * Sign a personal Ethereum signed message. The signing address will be - * calculated from the private key. - * If you've added the PKWalletSubprovider to your app's provider, you can simply send an `eth_sign` + * Sign a personal Ethereum signed message. The signing address will be calculated from the private key. + * The address must be provided it must match the address calculated from the private key. + * If you've added this Subprovider to your app's provider, you can simply send an `eth_sign` * or `personal_sign` JSON RPC request, and this method will be called auto-magically. * If you are not using this via a ProviderEngine instance, you can call it directly. - * @param data Message to sign + * @param data Hex string message to sign + * @param address Address of the account to sign with * @return Signature hex string (order: rsv) */ - public async signPersonalMessageAsync(dataIfExists: string): Promise<string> { - if (_.isUndefined(dataIfExists)) { + public async signPersonalMessageAsync(data: string, address: string): Promise<string> { + if (_.isUndefined(data)) { throw new Error(WalletSubproviderErrors.DataMissingForSignPersonalMessage); } - assert.isHexString('data', dataIfExists); - const dataBuff = ethUtil.toBuffer(dataIfExists); + assert.isHexString('data', data); + assert.isETHAddressHex('address', address); + if (address !== this._address) { + throw new Error( + `Requested to sign message with address: ${address}, instantiated with address: ${this._address}`, + ); + } + const dataBuff = ethUtil.toBuffer(data); const msgHashBuff = ethUtil.hashPersonalMessage(dataBuff); const sig = ethUtil.ecsign(msgHashBuff, this._privateKeyBuffer); const rpcSig = ethUtil.toRpcSig(sig.v, sig.r, sig.s); diff --git a/packages/subproviders/src/subproviders/redundant_rpc.ts b/packages/subproviders/src/subproviders/redundant_subprovider.ts index f8ff0915d..37c8bba5a 100644 --- a/packages/subproviders/src/subproviders/redundant_rpc.ts +++ b/packages/subproviders/src/subproviders/redundant_subprovider.ts @@ -1,7 +1,6 @@ import { JSONRPCRequestPayload } from '@0xproject/types'; import { promisify } from '@0xproject/utils'; import * as _ from 'lodash'; -import RpcSubprovider = require('web3-provider-engine/subproviders/rpc'); import { Callback } from '../types'; @@ -12,17 +11,17 @@ import { Subprovider } from './subprovider'; * It attempts to handle each JSON RPC request by sequentially attempting to receive a valid response from one of a * set of JSON RPC endpoints. */ -export class RedundantRPCSubprovider extends Subprovider { - private _rpcs: RpcSubprovider[]; +export class RedundantSubprovider extends Subprovider { + private _subproviders: Subprovider[]; private static async _firstSuccessAsync( - rpcs: RpcSubprovider[], + subproviders: Subprovider[], payload: JSONRPCRequestPayload, next: Callback, ): Promise<any> { let lastErr: Error | undefined; - for (const rpc of rpcs) { + for (const subprovider of subproviders) { try { - const data = await promisify(rpc.handleRequest.bind(rpc))(payload, next); + const data = await promisify(subprovider.handleRequest.bind(subprovider))(payload, next); return data; } catch (err) { lastErr = err; @@ -34,16 +33,12 @@ export class RedundantRPCSubprovider extends Subprovider { } } /** - * Instantiates a new RedundantRPCSubprovider + * Instantiates a new RedundantSubprovider * @param endpoints JSON RPC endpoints to attempt. Attempts are made in the order of the endpoints. */ - constructor(endpoints: string[]) { + constructor(subproviders: Subprovider[]) { super(); - this._rpcs = _.map(endpoints, endpoint => { - return new RpcSubprovider({ - rpcUrl: endpoint, - }); - }); + this._subproviders = subproviders; } /** * This method conforms to the web3-provider-engine interface. @@ -59,9 +54,9 @@ export class RedundantRPCSubprovider extends Subprovider { next: Callback, end: (err: Error | null, data?: any) => void, ): Promise<void> { - const rpcsCopy = this._rpcs.slice(); + const subprovidersCopy = this._subproviders.slice(); try { - const data = await RedundantRPCSubprovider._firstSuccessAsync(rpcsCopy, payload, next); + const data = await RedundantSubprovider._firstSuccessAsync(subprovidersCopy, payload, next); end(null, data); } catch (err) { end(err); diff --git a/packages/subproviders/src/subproviders/subprovider.ts b/packages/subproviders/src/subproviders/subprovider.ts index c51462f07..2118f52c8 100644 --- a/packages/subproviders/src/subproviders/subprovider.ts +++ b/packages/subproviders/src/subproviders/subprovider.ts @@ -2,13 +2,14 @@ import { JSONRPCRequestPayload, JSONRPCResponsePayload } from '@0xproject/types' import { promisify } from '@0xproject/utils'; import * as Web3 from 'web3'; -import { JSONRPCRequestPayloadWithMethod } from '../types'; +import { Callback, ErrorCallback, JSONRPCRequestPayloadWithMethod } from '../types'; /** * A altered version of the base class Subprovider found in [web3-provider-engine](https://github.com/MetaMask/provider-engine). * This one has an async/await `emitPayloadAsync` and also defined types. */ -export class Subprovider { - private _engine: any; +export abstract class Subprovider { + // tslint:disable-next-line:underscore-private-and-protected + private engine: any; // Ported from: https://github.com/MetaMask/provider-engine/blob/master/util/random-id.js private static _getRandomId() { const extraDigits = 3; @@ -31,6 +32,13 @@ export class Subprovider { }; return finalPayload; } + // tslint:disable-next-line:async-suffix + public abstract async handleRequest( + payload: JSONRPCRequestPayload, + next: Callback, + end: ErrorCallback, + ): Promise<void>; + /** * Emits a JSON RPC payload that will then be handled by the ProviderEngine instance * this subprovider is a part of. The payload will cascade down the subprovider middleware @@ -40,7 +48,7 @@ export class Subprovider { */ public async emitPayloadAsync(payload: Partial<JSONRPCRequestPayloadWithMethod>): Promise<JSONRPCResponsePayload> { const finalPayload = Subprovider._createFinalPayload(payload); - const response = await promisify<JSONRPCResponsePayload>(this._engine.sendAsync, this._engine)(finalPayload); + const response = await promisify<JSONRPCResponsePayload>(this.engine.sendAsync, this.engine)(finalPayload); return response; } /** @@ -49,6 +57,6 @@ export class Subprovider { * directly. */ public setEngine(engine: any): void { - this._engine = engine; + this.engine = engine; } } diff --git a/packages/subproviders/src/types.ts b/packages/subproviders/src/types.ts index bacb7091b..74ecec23b 100644 --- a/packages/subproviders/src/types.ts +++ b/packages/subproviders/src/types.ts @@ -1,4 +1,5 @@ import { ECSignature, JSONRPCRequestPayload } from '@0xproject/types'; +import HDNode = require('hdkey'); import * as _ from 'lodash'; export interface LedgerCommunicationClient { @@ -40,20 +41,33 @@ export type LedgerEthereumClientFactoryAsync = () => Promise<LedgerEthereumClien export interface LedgerSubproviderConfigs { networkId: number; ledgerEthereumClientFactoryAsync: LedgerEthereumClientFactoryAsync; - derivationPath?: string; + baseDerivationPath?: string; accountFetchingConfigs?: AccountFetchingConfigs; } /* + * addressSearchLimit: The maximum number of addresses to search through, defaults to 1000 * numAddressesToReturn: Number of addresses to return from 'eth_accounts' call * shouldAskForOnDeviceConfirmation: Whether you wish to prompt the user on their Ledger * before fetching their addresses */ export interface AccountFetchingConfigs { + addressSearchLimit?: number; numAddressesToReturn?: number; shouldAskForOnDeviceConfirmation?: boolean; } +/* + * mnemonic: The string mnemonic seed + * addressSearchLimit: The maximum number of addresses to search through, defaults to 1000 + * baseDerivationPath: The base derivation path (e.g 44'/60'/0'/0) + */ +export interface MnemonicWalletSubproviderConfigs { + mnemonic: string; + addressSearchLimit?: number; + baseDerivationPath?: string; +} + export interface SignatureData { hash: string; r: string; @@ -67,18 +81,12 @@ export interface LedgerGetAddressResult { chainCode: string; } -export interface LedgerWalletSubprovider { - getPath: () => string; - setPath: (path: string) => void; - setPathIndex: (pathIndex: number) => void; -} - export interface PartialTxParams { nonce: string; gasPrice?: string; gas: string; to: string; - from?: string; + from: string; value?: string; data?: string; chainId: number; // EIP 155 chainId - mainnet: 1, ropsten: 3 @@ -96,12 +104,13 @@ export interface ResponseWithTxParams { } export enum WalletSubproviderErrors { + AddressNotFound = 'ADDRESS_NOT_FOUND', DataMissingForSignPersonalMessage = 'DATA_MISSING_FOR_SIGN_PERSONAL_MESSAGE', SenderInvalidOrNotSupplied = 'SENDER_INVALID_OR_NOT_SUPPLIED', + FromAddressMissingOrInvalid = 'FROM_ADDRESS_MISSING_OR_INVALID', } export enum LedgerSubproviderErrors { TooOldLedgerFirmware = 'TOO_OLD_LEDGER_FIRMWARE', - FromAddressMissingOrInvalid = 'FROM_ADDRESS_MISSING_OR_INVALID', MultipleOpenConnectionsDisallowed = 'MULTIPLE_OPEN_CONNECTIONS_DISALLOWED', } @@ -109,6 +118,12 @@ export enum NonceSubproviderErrors { EmptyParametersFound = 'EMPTY_PARAMETERS_FOUND', CannotDetermineAddressFromPayload = 'CANNOT_DETERMINE_ADDRESS_FROM_PAYLOAD', } +export interface DerivedHDKeyInfo { + address: string; + baseDerivationPath: string; + derivationPath: string; + hdKey: HDNode; +} export type ErrorCallback = (err: Error | null, data?: any) => void; export type Callback = () => void; diff --git a/packages/subproviders/src/utils/wallet_utils.ts b/packages/subproviders/src/utils/wallet_utils.ts new file mode 100644 index 000000000..cd5cd9ba0 --- /dev/null +++ b/packages/subproviders/src/utils/wallet_utils.ts @@ -0,0 +1,79 @@ +import ethUtil = require('ethereumjs-util'); +import HDNode = require('hdkey'); +import * as _ from 'lodash'; + +import { DerivedHDKeyInfo, WalletSubproviderErrors } from '../types'; + +const DEFAULT_ADDRESS_SEARCH_LIMIT = 1000; + +class DerivedHDKeyInfoIterator implements IterableIterator<DerivedHDKeyInfo> { + private _parentDerivedKeyInfo: DerivedHDKeyInfo; + private _searchLimit: number; + private _index: number; + + constructor(initialDerivedKey: DerivedHDKeyInfo, searchLimit: number = DEFAULT_ADDRESS_SEARCH_LIMIT) { + this._searchLimit = searchLimit; + this._parentDerivedKeyInfo = initialDerivedKey; + this._index = 0; + } + + public next(): IteratorResult<DerivedHDKeyInfo> { + const baseDerivationPath = this._parentDerivedKeyInfo.baseDerivationPath; + const derivationIndex = this._index; + const fullDerivationPath = `m/${baseDerivationPath}/${derivationIndex}`; + const path = `m/${derivationIndex}`; + const hdKey = this._parentDerivedKeyInfo.hdKey.derive(path); + const address = walletUtils.addressOfHDKey(hdKey); + const derivedKey: DerivedHDKeyInfo = { + address, + hdKey, + baseDerivationPath, + derivationPath: fullDerivationPath, + }; + const done = this._index === this._searchLimit; + this._index++; + return { + done, + value: derivedKey, + }; + } + + public [Symbol.iterator](): IterableIterator<DerivedHDKeyInfo> { + return this; + } +} + +export const walletUtils = { + calculateDerivedHDKeyInfos(parentDerivedKeyInfo: DerivedHDKeyInfo, numberOfKeys: number): DerivedHDKeyInfo[] { + const derivedKeys: DerivedHDKeyInfo[] = []; + const derivedKeyIterator = new DerivedHDKeyInfoIterator(parentDerivedKeyInfo, numberOfKeys); + for (const key of derivedKeyIterator) { + derivedKeys.push(key); + } + return derivedKeys; + }, + findDerivedKeyInfoForAddressIfExists( + address: string, + parentDerivedKeyInfo: DerivedHDKeyInfo, + searchLimit: number, + ): DerivedHDKeyInfo | undefined { + let matchedKey: DerivedHDKeyInfo | undefined; + const derivedKeyIterator = new DerivedHDKeyInfoIterator(parentDerivedKeyInfo, searchLimit); + for (const key of derivedKeyIterator) { + if (key.address === address) { + matchedKey = key; + break; + } + } + return matchedKey; + }, + addressOfHDKey(hdKey: HDNode): string { + const shouldSanitizePublicKey = true; + const derivedPublicKey = hdKey.publicKey; + const ethereumAddressUnprefixed = ethUtil + .publicToAddress(derivedPublicKey, shouldSanitizePublicKey) + .toString('hex'); + const address = ethUtil.addHexPrefix(ethereumAddressUnprefixed).toLowerCase(); + return address; + }, +}; diff --git a/packages/subproviders/test/integration/ledger_subprovider_test.ts b/packages/subproviders/test/integration/ledger_subprovider_test.ts index 503618089..0d6e67bd1 100644 --- a/packages/subproviders/test/integration/ledger_subprovider_test.ts +++ b/packages/subproviders/test/integration/ledger_subprovider_test.ts @@ -1,7 +1,7 @@ import { JSONRPCResponsePayload } from '@0xproject/types'; import { promisify } from '@0xproject/utils'; import Eth from '@ledgerhq/hw-app-eth'; -// HACK: This depdency is optional and tslint skips optional depdencies +// HACK: This dependency is optional and tslint skips optional dependencies // tslint:disable-next-line:no-implicit-dependencies import TransportNodeHid from '@ledgerhq/hw-transport-node-hid'; import * as chai from 'chai'; @@ -33,7 +33,7 @@ describe('LedgerSubprovider', () => { ledgerSubprovider = new LedgerSubprovider({ networkId, ledgerEthereumClientFactoryAsync: ledgerEthereumNodeJsClientFactoryAsync, - derivationPath: fixtureData.TESTRPC_DERIVATION_PATH, + baseDerivationPath: fixtureData.TESTRPC_BASE_DERIVATION_PATH, }); }); describe('direct method calls', () => { @@ -42,9 +42,10 @@ describe('LedgerSubprovider', () => { expect(accounts[0]).to.not.be.an('undefined'); expect(accounts.length).to.be.equal(10); }); - it('returns the expected first account from a ledger set up with the test mnemonic', async () => { + it('returns the expected accounts from a ledger set up with the test mnemonic', async () => { const accounts = await ledgerSubprovider.getAccountsAsync(); expect(accounts[0]).to.be.equal(fixtureData.TEST_RPC_ACCOUNT_0); + expect(accounts[1]).to.be.equal(fixtureData.TEST_RPC_ACCOUNT_1); }); it('returns requested number of accounts', async () => { const numberOfAccounts = 20; @@ -54,14 +55,29 @@ describe('LedgerSubprovider', () => { }); it('signs a personal message', async () => { const data = ethUtils.bufferToHex(ethUtils.toBuffer(fixtureData.PERSONAL_MESSAGE_STRING)); - const ecSignatureHex = await ledgerSubprovider.signPersonalMessageAsync(data); - expect(ecSignatureHex.length).to.be.equal(132); + const ecSignatureHex = await ledgerSubprovider.signPersonalMessageAsync( + data, + fixtureData.TEST_RPC_ACCOUNT_0, + ); expect(ecSignatureHex).to.be.equal(fixtureData.PERSONAL_MESSAGE_SIGNED_RESULT); }); + it('signs a personal message with second address', async () => { + const data = ethUtils.bufferToHex(ethUtils.toBuffer(fixtureData.PERSONAL_MESSAGE_STRING)); + const ecSignatureHex = await ledgerSubprovider.signPersonalMessageAsync( + data, + fixtureData.TEST_RPC_ACCOUNT_1, + ); + expect(ecSignatureHex).to.be.equal(fixtureData.PERSONAL_MESSAGE_ACCOUNT_1_SIGNED_RESULT); + }); it('signs a transaction', async () => { const txHex = await ledgerSubprovider.signTransactionAsync(fixtureData.TX_DATA); expect(txHex).to.be.equal(fixtureData.TX_DATA_SIGNED_RESULT); }); + it('signs a transaction with the second address', async () => { + const txData = { ...fixtureData.TX_DATA, from: fixtureData.TEST_RPC_ACCOUNT_1 }; + const txHex = await ledgerSubprovider.signTransactionAsync(txData); + expect(txHex).to.be.equal(fixtureData.TX_DATA_ACCOUNT_1_SIGNED_RESULT); + }); }); describe('calls through a provider', () => { let defaultProvider: Web3ProviderEngine; diff --git a/packages/subproviders/test/unit/ledger_subprovider_test.ts b/packages/subproviders/test/unit/ledger_subprovider_test.ts index c18506681..892c2acd0 100644 --- a/packages/subproviders/test/unit/ledger_subprovider_test.ts +++ b/packages/subproviders/test/unit/ledger_subprovider_test.ts @@ -4,7 +4,6 @@ import * as ethUtils from 'ethereumjs-util'; import * as _ from 'lodash'; import Web3 = require('web3'); import Web3ProviderEngine = require('web3-provider-engine'); -import RpcSubprovider = require('web3-provider-engine/subproviders/rpc'); import { LedgerSubprovider } from '../../src'; import { @@ -15,6 +14,7 @@ import { } from '../../src/types'; import { chaiSetup } from '../chai_setup'; import { fixtureData } from '../utils/fixture_data'; +import { ganacheSubprovider } from '../utils/ganache_subprovider'; import { reportCallbackErrors } from '../utils/report_callback_errors'; chaiSetup.configure(); @@ -82,7 +82,7 @@ describe('LedgerSubprovider', () => { }); it('signs a personal message', async () => { const data = ethUtils.bufferToHex(ethUtils.toBuffer(fixtureData.PERSONAL_MESSAGE_STRING)); - const ecSignatureHex = await ledgerSubprovider.signPersonalMessageAsync(data); + const ecSignatureHex = await ledgerSubprovider.signPersonalMessageAsync(data, FAKE_ADDRESS); expect(ecSignatureHex).to.be.equal( '0xa6cc284bff14b42bdf5e9286730c152be91719d478605ec46b3bebcd0ae491480652a1a7b742ceb0213d1e744316e285f41f878d8af0b8e632cbca4c279132d001', ); @@ -94,7 +94,7 @@ describe('LedgerSubprovider', () => { return expect( Promise.all([ ledgerSubprovider.getAccountsAsync(), - ledgerSubprovider.signPersonalMessageAsync(data), + ledgerSubprovider.signPersonalMessageAsync(data, FAKE_ADDRESS), ]), ).to.be.rejectedWith(LedgerSubproviderErrors.MultipleOpenConnectionsDisallowed); }); @@ -105,10 +105,7 @@ describe('LedgerSubprovider', () => { before(() => { provider = new Web3ProviderEngine(); provider.addProvider(ledgerSubprovider); - const httpProvider = new RpcSubprovider({ - rpcUrl: 'http://localhost:8545', - }); - provider.addProvider(httpProvider); + provider.addProvider(ganacheSubprovider); provider.start(); }); describe('success cases', () => { @@ -132,7 +129,7 @@ describe('LedgerSubprovider', () => { const payload = { jsonrpc: '2.0', method: 'eth_sign', - params: ['0x0000000000000000000000000000000000000000', messageHex], + params: [FAKE_ADDRESS, messageHex], id: 1, }; const callback = reportCallbackErrors(done)((err: Error, response: JSONRPCResponsePayload) => { @@ -149,7 +146,7 @@ describe('LedgerSubprovider', () => { const payload = { jsonrpc: '2.0', method: 'personal_sign', - params: [messageHex, '0x0000000000000000000000000000000000000000'], + params: [messageHex, FAKE_ADDRESS], id: 1, }; const callback = reportCallbackErrors(done)((err: Error, response: JSONRPCResponsePayload) => { @@ -168,6 +165,7 @@ describe('LedgerSubprovider', () => { gasPrice: '0x00', nonce: '0x00', gas: '0x00', + from: FAKE_ADDRESS, }; const payload = { jsonrpc: '2.0', @@ -190,7 +188,7 @@ describe('LedgerSubprovider', () => { const payload = { jsonrpc: '2.0', method: 'eth_sign', - params: ['0x0000000000000000000000000000000000000000', nonHexMessage], + params: [FAKE_ADDRESS, nonHexMessage], id: 1, }; const callback = reportCallbackErrors(done)((err: Error, response: JSONRPCResponsePayload) => { @@ -205,7 +203,7 @@ describe('LedgerSubprovider', () => { const payload = { jsonrpc: '2.0', method: 'personal_sign', - params: [nonHexMessage, '0x0000000000000000000000000000000000000000'], + params: [nonHexMessage, FAKE_ADDRESS], id: 1, }; const callback = reportCallbackErrors(done)((err: Error, response: JSONRPCResponsePayload) => { diff --git a/packages/subproviders/test/unit/mnemonic_wallet_subprovider_test.ts b/packages/subproviders/test/unit/mnemonic_wallet_subprovider_test.ts new file mode 100644 index 000000000..93300f47d --- /dev/null +++ b/packages/subproviders/test/unit/mnemonic_wallet_subprovider_test.ts @@ -0,0 +1,215 @@ +import { JSONRPCResponsePayload } from '@0xproject/types'; +import * as chai from 'chai'; +import * as ethUtils from 'ethereumjs-util'; +import * as _ from 'lodash'; +import Web3ProviderEngine = require('web3-provider-engine'); + +import { GanacheSubprovider, MnemonicWalletSubprovider } from '../../src/'; +import { + DoneCallback, + LedgerCommunicationClient, + LedgerSubproviderErrors, + WalletSubproviderErrors, +} from '../../src/types'; +import { chaiSetup } from '../chai_setup'; +import { fixtureData } from '../utils/fixture_data'; +import { reportCallbackErrors } from '../utils/report_callback_errors'; + +chaiSetup.configure(); +const expect = chai.expect; + +describe('MnemonicWalletSubprovider', () => { + let subprovider: MnemonicWalletSubprovider; + before(async () => { + subprovider = new MnemonicWalletSubprovider({ + mnemonic: fixtureData.TEST_RPC_MNEMONIC, + baseDerivationPath: fixtureData.TEST_RPC_MNEMONIC_BASE_DERIVATION_PATH, + }); + }); + describe('direct method calls', () => { + describe('success cases', () => { + it('returns the accounts', async () => { + const accounts = await subprovider.getAccountsAsync(); + expect(accounts[0]).to.be.equal(fixtureData.TEST_RPC_ACCOUNT_0); + expect(accounts[1]).to.be.equal(fixtureData.TEST_RPC_ACCOUNT_1); + expect(accounts.length).to.be.equal(10); + }); + it('signs a personal message', async () => { + const data = ethUtils.bufferToHex(ethUtils.toBuffer(fixtureData.PERSONAL_MESSAGE_STRING)); + const ecSignatureHex = await subprovider.signPersonalMessageAsync(data, fixtureData.TEST_RPC_ACCOUNT_0); + expect(ecSignatureHex).to.be.equal(fixtureData.PERSONAL_MESSAGE_SIGNED_RESULT); + }); + it('signs a personal message with second address', async () => { + const data = ethUtils.bufferToHex(ethUtils.toBuffer(fixtureData.PERSONAL_MESSAGE_STRING)); + const ecSignatureHex = await subprovider.signPersonalMessageAsync(data, fixtureData.TEST_RPC_ACCOUNT_1); + expect(ecSignatureHex).to.be.equal(fixtureData.PERSONAL_MESSAGE_ACCOUNT_1_SIGNED_RESULT); + }); + it('signs a transaction', async () => { + const txHex = await subprovider.signTransactionAsync(fixtureData.TX_DATA); + expect(txHex).to.be.equal(fixtureData.TX_DATA_SIGNED_RESULT); + }); + it('signs a transaction with the second address', async () => { + const txData = { ...fixtureData.TX_DATA, from: fixtureData.TEST_RPC_ACCOUNT_1 }; + const txHex = await subprovider.signTransactionAsync(txData); + expect(txHex).to.be.equal(fixtureData.TX_DATA_ACCOUNT_1_SIGNED_RESULT); + }); + }); + describe('failure cases', () => { + it('throws an error if address is invalid ', async () => { + const txData = { ...fixtureData.TX_DATA, from: '0x0' }; + return expect(subprovider.signTransactionAsync(txData)).to.be.rejectedWith( + WalletSubproviderErrors.FromAddressMissingOrInvalid, + ); + }); + it('throws an error if address is valid format but not found', async () => { + const txData = { ...fixtureData.TX_DATA, from: fixtureData.NULL_ADDRESS }; + return expect(subprovider.signTransactionAsync(txData)).to.be.rejectedWith( + `${WalletSubproviderErrors.AddressNotFound}: ${fixtureData.NULL_ADDRESS}`, + ); + }); + }); + }); + describe('calls through a provider', () => { + let provider: Web3ProviderEngine; + before(() => { + provider = new Web3ProviderEngine(); + provider.addProvider(subprovider); + const ganacheSubprovider = new GanacheSubprovider({}); + provider.addProvider(ganacheSubprovider); + provider.start(); + }); + describe('success cases', () => { + it('returns a list of accounts', (done: DoneCallback) => { + const payload = { + jsonrpc: '2.0', + method: 'eth_accounts', + params: [], + id: 1, + }; + const callback = reportCallbackErrors(done)((err: Error, response: JSONRPCResponsePayload) => { + expect(err).to.be.a('null'); + expect(response.result[0]).to.be.equal(fixtureData.TEST_RPC_ACCOUNT_0); + expect(response.result.length).to.be.equal(10); + done(); + }); + provider.sendAsync(payload, callback); + }); + it('signs a personal message with eth_sign', (done: DoneCallback) => { + const messageHex = ethUtils.bufferToHex(ethUtils.toBuffer(fixtureData.PERSONAL_MESSAGE_STRING)); + const payload = { + jsonrpc: '2.0', + method: 'eth_sign', + params: [fixtureData.TEST_RPC_ACCOUNT_0, messageHex], + id: 1, + }; + const callback = reportCallbackErrors(done)((err: Error, response: JSONRPCResponsePayload) => { + expect(err).to.be.a('null'); + expect(response.result).to.be.equal(fixtureData.PERSONAL_MESSAGE_SIGNED_RESULT); + done(); + }); + provider.sendAsync(payload, callback); + }); + it('signs a personal message with personal_sign', (done: DoneCallback) => { + const messageHex = ethUtils.bufferToHex(ethUtils.toBuffer(fixtureData.PERSONAL_MESSAGE_STRING)); + const payload = { + jsonrpc: '2.0', + method: 'personal_sign', + params: [messageHex, fixtureData.TEST_RPC_ACCOUNT_0], + id: 1, + }; + const callback = reportCallbackErrors(done)((err: Error, response: JSONRPCResponsePayload) => { + expect(err).to.be.a('null'); + expect(response.result).to.be.equal(fixtureData.PERSONAL_MESSAGE_SIGNED_RESULT); + done(); + }); + provider.sendAsync(payload, callback); + }); + }); + describe('failure cases', () => { + it('should throw if `data` param not hex when calling eth_sign', (done: DoneCallback) => { + const nonHexMessage = 'hello world'; + const payload = { + jsonrpc: '2.0', + method: 'eth_sign', + params: [fixtureData.TEST_RPC_ACCOUNT_0, nonHexMessage], + id: 1, + }; + const callback = reportCallbackErrors(done)((err: Error, response: JSONRPCResponsePayload) => { + expect(err).to.not.be.a('null'); + expect(err.message).to.be.equal('Expected data to be of type HexString, encountered: hello world'); + done(); + }); + provider.sendAsync(payload, callback); + }); + it('should throw if `data` param not hex when calling personal_sign', (done: DoneCallback) => { + const nonHexMessage = 'hello world'; + const payload = { + jsonrpc: '2.0', + method: 'personal_sign', + params: [nonHexMessage, fixtureData.TEST_RPC_ACCOUNT_0], + id: 1, + }; + const callback = reportCallbackErrors(done)((err: Error, response: JSONRPCResponsePayload) => { + expect(err).to.not.be.a('null'); + expect(err.message).to.be.equal('Expected data to be of type HexString, encountered: hello world'); + done(); + }); + provider.sendAsync(payload, callback); + }); + it('should throw if `address` param not found when calling personal_sign', (done: DoneCallback) => { + const messageHex = ethUtils.bufferToHex(ethUtils.toBuffer(fixtureData.PERSONAL_MESSAGE_STRING)); + const payload = { + jsonrpc: '2.0', + method: 'personal_sign', + params: [messageHex, fixtureData.NULL_ADDRESS], + id: 1, + }; + const callback = reportCallbackErrors(done)((err: Error, response: JSONRPCResponsePayload) => { + expect(err).to.not.be.a('null'); + expect(err.message).to.be.equal( + `${WalletSubproviderErrors.AddressNotFound}: ${fixtureData.NULL_ADDRESS}`, + ); + done(); + }); + provider.sendAsync(payload, callback); + }); + it('should throw if `from` param missing when calling eth_sendTransaction', (done: DoneCallback) => { + const tx = { + to: '0xafa3f8684e54059998bc3a7b0d2b0da075154d66', + value: '0xde0b6b3a7640000', + }; + const payload = { + jsonrpc: '2.0', + method: 'eth_sendTransaction', + params: [tx], + id: 1, + }; + const callback = reportCallbackErrors(done)((err: Error, response: JSONRPCResponsePayload) => { + expect(err).to.not.be.a('null'); + expect(err.message).to.be.equal(WalletSubproviderErrors.SenderInvalidOrNotSupplied); + done(); + }); + provider.sendAsync(payload, callback); + }); + it('should throw if `from` param invalid address when calling eth_sendTransaction', (done: DoneCallback) => { + const tx = { + to: '0xafa3f8684e54059998bc3a7b0d2b0da075154d66', + from: '0xIncorrectEthereumAddress', + value: '0xde0b6b3a7640000', + }; + const payload = { + jsonrpc: '2.0', + method: 'eth_sendTransaction', + params: [tx], + id: 1, + }; + const callback = reportCallbackErrors(done)((err: Error, response: JSONRPCResponsePayload) => { + expect(err).to.not.be.a('null'); + expect(err.message).to.be.equal(WalletSubproviderErrors.SenderInvalidOrNotSupplied); + done(); + }); + provider.sendAsync(payload, callback); + }); + }); + }); +}); diff --git a/packages/subproviders/test/unit/private_key_wallet_subprovider_test.ts b/packages/subproviders/test/unit/private_key_wallet_subprovider_test.ts index ca0665871..5c1b5cd25 100644 --- a/packages/subproviders/test/unit/private_key_wallet_subprovider_test.ts +++ b/packages/subproviders/test/unit/private_key_wallet_subprovider_test.ts @@ -32,7 +32,7 @@ describe('PrivateKeyWalletSubprovider', () => { }); it('signs a personal message', async () => { const data = ethUtils.bufferToHex(ethUtils.toBuffer(fixtureData.PERSONAL_MESSAGE_STRING)); - const ecSignatureHex = await subprovider.signPersonalMessageAsync(data); + const ecSignatureHex = await subprovider.signPersonalMessageAsync(data, fixtureData.TEST_RPC_ACCOUNT_0); expect(ecSignatureHex).to.be.equal(fixtureData.PERSONAL_MESSAGE_SIGNED_RESULT); }); it('signs a transaction', async () => { @@ -71,7 +71,7 @@ describe('PrivateKeyWalletSubprovider', () => { const payload = { jsonrpc: '2.0', method: 'eth_sign', - params: ['0x0000000000000000000000000000000000000000', messageHex], + params: [fixtureData.TEST_RPC_ACCOUNT_0, messageHex], id: 1, }; const callback = reportCallbackErrors(done)((err: Error, response: JSONRPCResponsePayload) => { @@ -86,7 +86,7 @@ describe('PrivateKeyWalletSubprovider', () => { const payload = { jsonrpc: '2.0', method: 'personal_sign', - params: [messageHex, '0x0000000000000000000000000000000000000000'], + params: [messageHex, fixtureData.TEST_RPC_ACCOUNT_0], id: 1, }; const callback = reportCallbackErrors(done)((err: Error, response: JSONRPCResponsePayload) => { @@ -103,7 +103,7 @@ describe('PrivateKeyWalletSubprovider', () => { const payload = { jsonrpc: '2.0', method: 'eth_sign', - params: ['0x0000000000000000000000000000000000000000', nonHexMessage], + params: [fixtureData.TEST_RPC_ACCOUNT_0, nonHexMessage], id: 1, }; const callback = reportCallbackErrors(done)((err: Error, response: JSONRPCResponsePayload) => { @@ -118,7 +118,7 @@ describe('PrivateKeyWalletSubprovider', () => { const payload = { jsonrpc: '2.0', method: 'personal_sign', - params: [nonHexMessage, '0x0000000000000000000000000000000000000000'], + params: [nonHexMessage, fixtureData.TEST_RPC_ACCOUNT_0], id: 1, }; const callback = reportCallbackErrors(done)((err: Error, response: JSONRPCResponsePayload) => { @@ -128,6 +128,25 @@ describe('PrivateKeyWalletSubprovider', () => { }); provider.sendAsync(payload, callback); }); + it('should throw if `address` param is not the address from private key when calling personal_sign', (done: DoneCallback) => { + const messageHex = ethUtils.bufferToHex(ethUtils.toBuffer(fixtureData.PERSONAL_MESSAGE_STRING)); + const payload = { + jsonrpc: '2.0', + method: 'personal_sign', + params: [messageHex, fixtureData.TEST_RPC_ACCOUNT_1], + id: 1, + }; + const callback = reportCallbackErrors(done)((err: Error, response: JSONRPCResponsePayload) => { + expect(err).to.not.be.a('null'); + expect(err.message).to.be.equal( + `Requested to sign message with address: ${ + fixtureData.TEST_RPC_ACCOUNT_1 + }, instantiated with address: ${fixtureData.TEST_RPC_ACCOUNT_0}`, + ); + done(); + }); + provider.sendAsync(payload, callback); + }); it('should throw if `from` param missing when calling eth_sendTransaction', (done: DoneCallback) => { const tx = { to: '0xafa3f8684e54059998bc3a7b0d2b0da075154d66', @@ -165,6 +184,21 @@ describe('PrivateKeyWalletSubprovider', () => { }); provider.sendAsync(payload, callback); }); + it('should throw if `address` param not found when calling personal_sign', (done: DoneCallback) => { + const messageHex = ethUtils.bufferToHex(ethUtils.toBuffer(fixtureData.PERSONAL_MESSAGE_STRING)); + const payload = { + jsonrpc: '2.0', + method: 'personal_sign', + params: [messageHex, '0x0'], + id: 1, + }; + const callback = reportCallbackErrors(done)((err: Error, response: JSONRPCResponsePayload) => { + expect(err).to.not.be.a('null'); + expect(err.message).to.be.equal(`Expected address to be of type ETHAddressHex, encountered: 0x0`); + done(); + }); + provider.sendAsync(payload, callback); + }); }); }); }); diff --git a/packages/subproviders/test/unit/redundant_rpc_subprovider_test.ts b/packages/subproviders/test/unit/redundant_rpc_subprovider_test.ts index a347ab765..e25cb7eb7 100644 --- a/packages/subproviders/test/unit/redundant_rpc_subprovider_test.ts +++ b/packages/subproviders/test/unit/redundant_rpc_subprovider_test.ts @@ -3,21 +3,24 @@ import * as chai from 'chai'; import * as _ from 'lodash'; import Web3 = require('web3'); import Web3ProviderEngine = require('web3-provider-engine'); +import RpcSubprovider = require('web3-provider-engine/subproviders/rpc'); -import { RedundantRPCSubprovider } from '../../src'; +import { RedundantSubprovider } from '../../src'; +import { Subprovider } from '../../src/subproviders/subprovider'; import { DoneCallback } from '../../src/types'; import { chaiSetup } from '../chai_setup'; +import { ganacheSubprovider } from '../utils/ganache_subprovider'; import { reportCallbackErrors } from '../utils/report_callback_errors'; const expect = chai.expect; chaiSetup.configure(); -describe('RedundantRpcSubprovider', () => { +describe('RedundantSubprovider', () => { let provider: Web3ProviderEngine; it('succeeds when supplied a healthy endpoint', (done: DoneCallback) => { provider = new Web3ProviderEngine(); - const endpoints = ['http://localhost:8545']; - const redundantSubprovider = new RedundantRPCSubprovider(endpoints); + const subproviders = [ganacheSubprovider]; + const redundantSubprovider = new RedundantSubprovider(subproviders); provider.addProvider(redundantSubprovider); provider.start(); @@ -36,8 +39,11 @@ describe('RedundantRpcSubprovider', () => { }); it('succeeds when supplied at least one healthy endpoint', (done: DoneCallback) => { provider = new Web3ProviderEngine(); - const endpoints = ['http://does-not-exist:3000', 'http://localhost:8545']; - const redundantSubprovider = new RedundantRPCSubprovider(endpoints); + const nonExistentSubprovider = new RpcSubprovider({ + rpcUrl: 'http://does-not-exist:3000', + }); + const subproviders = [nonExistentSubprovider as Subprovider, ganacheSubprovider]; + const redundantSubprovider = new RedundantSubprovider(subproviders); provider.addProvider(redundantSubprovider); provider.start(); diff --git a/packages/subproviders/test/utils/configs.ts b/packages/subproviders/test/utils/configs.ts new file mode 100644 index 000000000..341037e4f --- /dev/null +++ b/packages/subproviders/test/utils/configs.ts @@ -0,0 +1,5 @@ +export const configs = { + port: 8545, + networkId: 50, + mnemonic: 'concert load couple harbor equip island argue ramp clarify fence smart topic', +}; diff --git a/packages/subproviders/test/utils/fixture_data.ts b/packages/subproviders/test/utils/fixture_data.ts index 890573d0d..3137e08b0 100644 --- a/packages/subproviders/test/utils/fixture_data.ts +++ b/packages/subproviders/test/utils/fixture_data.ts @@ -1,18 +1,26 @@ const TEST_RPC_ACCOUNT_0 = '0x5409ed021d9299bf6814279a6a1411a7e866a631'; +const TEST_RPC_ACCOUNT_1 = '0x6ecbe1db9ef729cbe972c83fb886247691fb6beb'; +const NULL_ADDRESS = '0x0000000000000000000000000000000000000000'; const networkId = 42; export const fixtureData = { + NULL_ADDRESS, TEST_RPC_ACCOUNT_0, TEST_RPC_ACCOUNT_0_ACCOUNT_PRIVATE_KEY: 'F2F48EE19680706196E2E339E5DA3491186E0C4C5030670656B0E0164837257D', + TEST_RPC_ACCOUNT_1, + TEST_RPC_MNEMONIC: 'concert load couple harbor equip island argue ramp clarify fence smart topic', + TEST_RPC_MNEMONIC_BASE_DERIVATION_PATH: `44'/60'/0'/0`, PERSONAL_MESSAGE_STRING: 'hello world', PERSONAL_MESSAGE_SIGNED_RESULT: '0x1b0ec5e2908e993d0c8ab6b46da46be2688fdf03c7ea6686075de37392e50a7d7fcc531446699132fbda915bd989882e0064d417018773a315fb8d43ed063c9b00', - TESTRPC_DERIVATION_PATH: `m/44'/60'/0'/0`, + PERSONAL_MESSAGE_ACCOUNT_1_SIGNED_RESULT: + '0xe7ae0c21d02eb38f2c2a20d9d7876a98cc7ef035b7a4559d49375e2ec735e06f0d0ab0ff92ee56c5ffc28d516e6ed0692d0270feae8796408dbef060c6c7100f01', + TESTRPC_BASE_DERIVATION_PATH: `m/44'/60'/0'/0`, NETWORK_ID: networkId, TX_DATA: { nonce: '0x00', gasPrice: '0x0', gas: '0x2710', - to: '0x0000000000000000000000000000000000000000', + to: NULL_ADDRESS, value: '0x00', chainId: networkId, from: TEST_RPC_ACCOUNT_0, @@ -20,4 +28,6 @@ export const fixtureData = { // This is the signed result of the abouve Transaction Data TX_DATA_SIGNED_RESULT: '0xf85f8080822710940000000000000000000000000000000000000000808078a0712854c73c69445cc1b22a7c3d7312ff9a97fe4ffba35fd636e8236b211b6e7ca0647cee031615e52d916c7c707025bc64ad525d8f1b9876c3435a863b42743178', + TX_DATA_ACCOUNT_1_SIGNED_RESULT: + '0xf85f8080822710940000000000000000000000000000000000000000808078a04b02af7ff3f18ce114b601542cc8ebdc50921354f75dd510d31793453a0710e6a0540082a01e475465801b8186a2edc79ec1a2dcf169b9781c25a58a417023c9ca', }; diff --git a/packages/subproviders/test/utils/ganache_subprovider.ts b/packages/subproviders/test/utils/ganache_subprovider.ts new file mode 100644 index 000000000..ac4a9325c --- /dev/null +++ b/packages/subproviders/test/utils/ganache_subprovider.ts @@ -0,0 +1,18 @@ +import * as fs from 'fs'; + +import { GanacheSubprovider } from '../../src/subproviders/ganache'; +import { configs } from '../utils/configs'; + +const logger = { + log: (arg: any) => { + fs.appendFileSync('ganache.log', `${arg}\n`); + }, +}; + +export const ganacheSubprovider = new GanacheSubprovider({ + logger, + verbose: false, + port: configs.port, + networkId: configs.networkId, + mnemonic: configs.mnemonic, +}); diff --git a/packages/subproviders/tsconfig.json b/packages/subproviders/tsconfig.json index e35816553..72dfee80b 100644 --- a/packages/subproviders/tsconfig.json +++ b/packages/subproviders/tsconfig.json @@ -1,7 +1,8 @@ { "extends": "../../tsconfig", "compilerOptions": { - "outDir": "lib" + "outDir": "lib", + "downlevelIteration": true }, "include": ["./src/**/*", "./test/**/*"] } diff --git a/packages/testnet-faucets/package.json b/packages/testnet-faucets/package.json index b0db99174..3d51e3e2b 100644 --- a/packages/testnet-faucets/package.json +++ b/packages/testnet-faucets/package.json @@ -1,7 +1,7 @@ { "private": true, "name": "@0xproject/testnet-faucets", - "version": "1.0.22", + "version": "1.0.23", "description": "A faucet micro-service that dispenses test ERC20 tokens or Ether", "main": "server.js", "scripts": { @@ -15,10 +15,10 @@ "author": "Fabio Berger", "license": "Apache-2.0", "dependencies": { - "0x.js": "^0.35.0", - "@0xproject/subproviders": "^0.8.4", - "@0xproject/typescript-typings": "^0.0.3", - "@0xproject/utils": "^0.5.0", + "0x.js": "^0.36.0", + "@0xproject/subproviders": "^0.8.5", + "@0xproject/typescript-typings": "^0.1.0", + "@0xproject/utils": "^0.5.1", "body-parser": "^1.17.1", "ethereumjs-tx": "^1.3.3", "ethereumjs-util": "^5.1.1", @@ -29,7 +29,7 @@ "web3-provider-engine": "^13.0.1" }, "devDependencies": { - "@0xproject/tslint-config": "^0.4.14", + "@0xproject/tslint-config": "^0.4.15", "@types/body-parser": "^1.16.1", "@types/express": "^4.0.35", "@types/lodash": "4.14.104", diff --git a/packages/tslint-config/CHANGELOG.json b/packages/tslint-config/CHANGELOG.json index 363fead6f..99e80a05b 100644 --- a/packages/tslint-config/CHANGELOG.json +++ b/packages/tslint-config/CHANGELOG.json @@ -1,5 +1,14 @@ [ { + "timestamp": 1523462196, + "version": "0.4.15", + "changes": [ + { + "note": "Dependencies updated" + } + ] + }, + { "timestamp": 1522673609, "version": "0.4.14", "changes": [ diff --git a/packages/tslint-config/CHANGELOG.md b/packages/tslint-config/CHANGELOG.md index 5b17ad9dc..d19f20d0f 100644 --- a/packages/tslint-config/CHANGELOG.md +++ b/packages/tslint-config/CHANGELOG.md @@ -5,6 +5,10 @@ Edit the package's CHANGELOG.json file only. CHANGELOG +## v0.4.15 - _April 11, 2018_ + + * Dependencies updated + ## v0.4.14 - _April 2, 2018_ * Dependencies updated diff --git a/packages/tslint-config/package.json b/packages/tslint-config/package.json index c0eb9087b..988380d85 100644 --- a/packages/tslint-config/package.json +++ b/packages/tslint-config/package.json @@ -1,6 +1,6 @@ { "name": "@0xproject/tslint-config", - "version": "0.4.14", + "version": "0.4.15", "description": "Lint rules related to 0xProject for TSLint", "main": "tslint.json", "scripts": { @@ -31,7 +31,7 @@ }, "homepage": "https://github.com/0xProject/0x-monorepo/packages/tslint-config/README.md", "devDependencies": { - "@0xproject/monorepo-scripts": "^0.1.16", + "@0xproject/monorepo-scripts": "^0.1.17", "@types/lodash": "4.14.104", "copyfiles": "^1.2.0", "shx": "^0.2.2", diff --git a/packages/tslint-config/tsconfig.json b/packages/tslint-config/tsconfig.json index fd9b23316..3f349e100 100644 --- a/packages/tslint-config/tsconfig.json +++ b/packages/tslint-config/tsconfig.json @@ -1,7 +1,7 @@ { "extends": "../../tsconfig", "compilerOptions": { - "typeRoots": ["node_modules/@types"], + "typeRoots": ["../../node_modules/@types", "node_modules/@types"], "outDir": "lib" }, "include": ["./rules/**/*", "./monorepo_scripts/**/*"] diff --git a/packages/types/CHANGELOG.json b/packages/types/CHANGELOG.json index 2e4c5f091..e0ff1e14d 100644 --- a/packages/types/CHANGELOG.json +++ b/packages/types/CHANGELOG.json @@ -6,7 +6,8 @@ "note": "Add Provider type", "pr": 501 } - ] + ], + "timestamp": 1523462196 }, { "version": "0.5.0", diff --git a/packages/types/CHANGELOG.md b/packages/types/CHANGELOG.md index 96a4df8b8..24ce3c30a 100644 --- a/packages/types/CHANGELOG.md +++ b/packages/types/CHANGELOG.md @@ -5,6 +5,10 @@ Edit the package's CHANGELOG.json file only. CHANGELOG +## v0.6.0 - _April 11, 2018_ + + * Add Provider type (#501) + ## v0.5.0 - _April 2, 2018_ * Make `DataItem.components` optional (#485) diff --git a/packages/types/package.json b/packages/types/package.json index edae406ae..c55c8376a 100644 --- a/packages/types/package.json +++ b/packages/types/package.json @@ -1,6 +1,6 @@ { "name": "@0xproject/types", - "version": "0.5.0", + "version": "0.6.0", "description": "0x types", "main": "lib/index.js", "types": "lib/index.d.ts", @@ -21,8 +21,8 @@ }, "homepage": "https://github.com/0xProject/0x-monorepo/packages/types/README.md", "devDependencies": { - "@0xproject/monorepo-scripts": "^0.1.16", - "@0xproject/tslint-config": "^0.4.14", + "@0xproject/monorepo-scripts": "^0.1.17", + "@0xproject/tslint-config": "^0.4.15", "@types/node": "^8.0.53", "copyfiles": "^1.2.0", "shx": "^0.2.2", diff --git a/packages/types/src/index.ts b/packages/types/src/index.ts index 442fbb2d6..044aae3c8 100644 --- a/packages/types/src/index.ts +++ b/packages/types/src/index.ts @@ -1,7 +1,13 @@ import { BigNumber } from 'bignumber.js'; +export type JSONRPCErrorCallback = (err: Error | null, result?: JSONRPCResponsePayload) => void; + +/** + * Do not create your own provider. Use an existing provider from a Web3 or ProviderEngine library + * Read more about Providers in the 0x wiki. + */ export interface Provider { - sendAsync(payload: JSONRPCRequestPayload, callback: (err: Error, result: JSONRPCResponsePayload) => void): void; + sendAsync(payload: JSONRPCRequestPayload, callback: JSONRPCErrorCallback): void; } export type ContractAbi = AbiDefinition[]; diff --git a/packages/types/tsconfig.json b/packages/types/tsconfig.json index 9f1937b22..ce916a635 100644 --- a/packages/types/tsconfig.json +++ b/packages/types/tsconfig.json @@ -1,7 +1,7 @@ { "extends": "../../tsconfig", "compilerOptions": { - "typeRoots": ["node_modules/@types"], + "typeRoots": ["../../node_modules/@types", "node_modules/@types"], "outDir": "lib" }, "include": ["src/**/*"] diff --git a/packages/typescript-typings/CHANGELOG.json b/packages/typescript-typings/CHANGELOG.json index 294d9ee9f..289422b97 100644 --- a/packages/typescript-typings/CHANGELOG.json +++ b/packages/typescript-typings/CHANGELOG.json @@ -1,12 +1,26 @@ [ { + "version": "0.2.0", + "changes": [ + { + "note": "Add types for `solc.compileStandardWrapper`", + "pr": 509 + } + ] + }, + { "version": "0.1.0", "changes": [ { "note": "Add types for more packages", "pr": 501 + }, + { + "note": "Add types for HDKey", + "pr": 507 } - ] + ], + "timestamp": 1523462196 }, { "timestamp": 1522673609, diff --git a/packages/typescript-typings/CHANGELOG.md b/packages/typescript-typings/CHANGELOG.md index ec7d90a86..d5a356918 100644 --- a/packages/typescript-typings/CHANGELOG.md +++ b/packages/typescript-typings/CHANGELOG.md @@ -5,6 +5,10 @@ Edit the package's CHANGELOG.json file only. CHANGELOG +## v0.1.0 - _April 11, 2018_ + + * Add types for more packages (#501) + ## v0.0.3 - _April 2, 2018_ * Dependencies updated diff --git a/packages/typescript-typings/package.json b/packages/typescript-typings/package.json index 2258a1f01..0d9aea63d 100644 --- a/packages/typescript-typings/package.json +++ b/packages/typescript-typings/package.json @@ -1,6 +1,6 @@ { "name": "@0xproject/typescript-typings", - "version": "0.0.3", + "version": "0.1.0", "description": "0x project typescript type definitions", "scripts": { "build": "tsc && copyfiles -u 1 './lib/**/*' ./scripts", @@ -21,11 +21,11 @@ }, "homepage": "https://github.com/0xProject/0x-monorepo/packages/typescript-typings#readme", "dependencies": { - "@0xproject/types": "^0.5.0", + "@0xproject/types": "^0.6.0", "bignumber.js": "~4.1.0" }, "devDependencies": { - "@0xproject/monorepo-scripts": "^0.1.16", + "@0xproject/monorepo-scripts": "^0.1.17", "copyfiles": "^1.2.0", "shx": "^0.2.2" }, diff --git a/packages/typescript-typings/types/ethereumjs-util/index.d.ts b/packages/typescript-typings/types/ethereumjs-util/index.d.ts index fae55c418..b1c521e18 100644 --- a/packages/typescript-typings/types/ethereumjs-util/index.d.ts +++ b/packages/typescript-typings/types/ethereumjs-util/index.d.ts @@ -1,5 +1,4 @@ declare module 'ethereumjs-util' { - import { Buffer } from 'buffer'; import BN = require('bn.js'); interface Signature { diff --git a/packages/typescript-typings/types/hdkey/index.d.ts b/packages/typescript-typings/types/hdkey/index.d.ts new file mode 100644 index 000000000..84b751bd7 --- /dev/null +++ b/packages/typescript-typings/types/hdkey/index.d.ts @@ -0,0 +1,11 @@ +declare module 'hdkey' { + class HDNode { + public static fromMasterSeed(seed: Buffer): HDNode; + public publicKey: Buffer; + public privateKey: Buffer; + public chainCode: Buffer; + public constructor(); + public derive(path: string): HDNode; + } + export = HDNode; +} diff --git a/packages/typescript-typings/types/solc/index.d.ts b/packages/typescript-typings/types/solc/index.d.ts index fcef24b9f..b20f9b2ff 100644 --- a/packages/typescript-typings/types/solc/index.d.ts +++ b/packages/typescript-typings/types/solc/index.d.ts @@ -26,12 +26,128 @@ declare module 'solc' { [fileName: string]: string; }; } + export interface BaseSource { + keccak256?: string; + } + export interface InMemorySource extends BaseSource { + content: string; + } + export interface UrlSource extends BaseSource { + urls: string[]; + } + export type Source = UrlSource | InMemorySource; + export type OutputField = + | '*' + | 'ast' + | 'legacyAST' + | 'abi' + | 'devdoc' + | 'userdoc' + | 'metadata' + | 'ir' + | 'evm.assembly' + | 'evm.legacyAssembly' + | 'evm.bytecode.object' + | 'evm.bytecode.opcodes' + | 'evm.bytecode.sourceMap' + | 'evm.bytecode.linkReferences' + | 'evm.deployedBytecode.object' + | 'evm.deployedBytecode.opcodes' + | 'evm.deployedBytecode.sourceMap' + | 'evm.deployedBytecode.linkReferences' + | 'evm.methodIdentifiers' + | 'evm.gasEstimates' + | 'ewasm.wast' + | 'ewasm.wasm'; + export interface StandardInput { + language: 'Solidity' | 'serpent' | 'lll' | 'assembly'; + sources: { + [fileName: string]: Source; + }; + settings: { + remappings?: string[]; + optimizer?: { + enabled: boolean; + runs?: number; + }; + evmVersion?: 'homestead' | 'tangerineWhistle' | 'spuriousDragon' | 'byzantium' | 'constantinople'; + metadata?: { + useLiteralContent: true; + }; + libraries?: { + [fileName: string]: { + [libName: string]: string; + }; + }; + outputSelection: { + [fileName: string]: { + [contractName: string]: OutputField[]; + }; + }; + }; + } + export type ErrorType = + | 'JSONError' + | 'IOError' + | 'ParserError' + | 'DocstringParsingError' + | 'SyntaxError' + | 'DeclarationError' + | 'TypeError' + | 'UnimplementedFeatureError' + | 'InternalCompilerError' + | 'Exception' + | 'CompilerError' + | 'FatalError' + | 'Warning'; + export type ErrorSeverity = 'error' | 'warning'; + export interface Error { + sourceLocation?: { + file: string; + start: number; + end: number; + }; + type: ErrorType; + component: 'general' | 'ewasm'; + severity: ErrorSeverity; + message: string; + formattedMessage?: string; + } + import { ContractAbi } from '@0xproject/types'; + export interface StandardOutput { + errors: Error[]; + sources: { + [fileName: string]: { + id: number; + ast?: object; + legacyAST?: object; + }; + }; + contracts: { + [fileName: string]: { + [contractName: string]: { + abi: ContractAbi; + evm: { + bytecode: { + object: string; + sourceMap: string; + }; + deployedBytecode: { + object: string; + sourceMap: string; + }; + }; + }; + }; + }; + } export interface SolcInstance { compile( sources: InputSources, optimizerEnabled: number, findImports: (importPath: string) => ImportContents, ): CompilationResult; + compileStandardWrapper(input: string, findImports: (importPath: string) => ImportContents): string; } export function loadRemoteVersion(versionName: string, cb: (err: Error | null, res?: SolcInstance) => void): void; export function setupMethods(solcBin: any): SolcInstance; diff --git a/packages/utils/CHANGELOG.json b/packages/utils/CHANGELOG.json index 0c71963c3..dada0eab3 100644 --- a/packages/utils/CHANGELOG.json +++ b/packages/utils/CHANGELOG.json @@ -1,5 +1,23 @@ [ { + "version": "0.5.2", + "changes": [ + { + "note": "Export NULL_BYTES constant", + "pr": 500 + } + ] + }, + { + "timestamp": 1523462196, + "version": "0.5.1", + "changes": [ + { + "note": "Dependencies updated" + } + ] + }, + { "version": "0.5.0", "changes": [ { diff --git a/packages/utils/CHANGELOG.md b/packages/utils/CHANGELOG.md index 018f19a15..2123d1097 100644 --- a/packages/utils/CHANGELOG.md +++ b/packages/utils/CHANGELOG.md @@ -5,6 +5,10 @@ Edit the package's CHANGELOG.json file only. CHANGELOG +## v0.5.1 - _April 11, 2018_ + + * Dependencies updated + ## v0.5.0 - _April 2, 2018_ * Make `AbiDecoder.addABI` public (#485) diff --git a/packages/utils/package.json b/packages/utils/package.json index 491fed040..f3cbdf14c 100644 --- a/packages/utils/package.json +++ b/packages/utils/package.json @@ -1,6 +1,6 @@ { "name": "@0xproject/utils", - "version": "0.5.0", + "version": "0.5.1", "description": "0x TS utils", "main": "lib/index.js", "types": "lib/index.d.ts", @@ -21,8 +21,8 @@ }, "homepage": "https://github.com/0xProject/0x-monorepo/packages/utils/README.md", "devDependencies": { - "@0xproject/monorepo-scripts": "^0.1.16", - "@0xproject/tslint-config": "^0.4.14", + "@0xproject/monorepo-scripts": "^0.1.17", + "@0xproject/tslint-config": "^0.4.15", "@types/lodash": "4.14.104", "copyfiles": "^1.2.0", "npm-run-all": "^4.1.2", @@ -31,8 +31,8 @@ "typescript": "2.7.1" }, "dependencies": { - "@0xproject/types": "^0.5.0", - "@0xproject/typescript-typings": "^0.0.3", + "@0xproject/types": "^0.6.0", + "@0xproject/typescript-typings": "^0.1.0", "@types/node": "^8.0.53", "bignumber.js": "~4.1.0", "ethers-contracts": "^2.2.1", diff --git a/packages/utils/src/abi_utils.ts b/packages/utils/src/abi_utils.ts new file mode 100644 index 000000000..c4533d42e --- /dev/null +++ b/packages/utils/src/abi_utils.ts @@ -0,0 +1,71 @@ +import { AbiDefinition, AbiType, ConstructorAbi, ContractAbi, DataItem, MethodAbi } from '@0xproject/types'; +import * as _ from 'lodash'; + +export const abiUtils = { + parseFunctionParam(param: DataItem): string { + if (param.type === 'tuple') { + // Parse out tuple types into {type_1, type_2, ..., type_N} + const tupleComponents = param.components; + const paramString = _.map(tupleComponents, component => this.parseFunctionParam(component)); + const tupleParamString = `{${paramString}}`; + return tupleParamString; + } + return param.type; + }, + getFunctionSignature(methodAbi: MethodAbi): string { + const functionName = methodAbi.name; + const parameterTypeList = _.map(methodAbi.inputs, (param: DataItem) => this.parseFunctionParam(param)); + const functionSignature = `${functionName}(${parameterTypeList})`; + return functionSignature; + }, + /** + * Solidity supports function overloading whereas TypeScript does not. + * See: https://solidity.readthedocs.io/en/v0.4.21/contracts.html?highlight=overload#function-overloading + * In order to support overloaded functions, we suffix overloaded function names with an index. + * This index should be deterministic, regardless of function ordering within the smart contract. To do so, + * we assign indexes based on the alphabetical order of function signatures. + * + * E.g + * ['f(uint)', 'f(uint,byte32)'] + * Should always be renamed to: + * ['f1(uint)', 'f2(uint,byte32)'] + * Regardless of the order in which these these overloaded functions are declared within the contract ABI. + */ + renameOverloadedMethods(inputContractAbi: ContractAbi): ContractAbi { + const contractAbi = _.cloneDeep(inputContractAbi); + const methodAbis = contractAbi.filter((abi: AbiDefinition) => abi.type === AbiType.Function) as MethodAbi[]; + // Sort method Abis into alphabetical order, by function signature + const methodAbisOrdered = _.sortBy(methodAbis, [ + (methodAbi: MethodAbi) => { + const functionSignature = this.getFunctionSignature(methodAbi); + return functionSignature; + }, + ]); + // Group method Abis by name (overloaded methods will be grouped together, in alphabetical order) + const methodAbisByName: { [key: string]: MethodAbi[] } = {}; + _.each(methodAbisOrdered, methodAbi => { + (methodAbisByName[methodAbi.name] || (methodAbisByName[methodAbi.name] = [])).push(methodAbi); + }); + // Rename overloaded methods to overloadedMethodName1, overloadedMethodName2, ... + _.each(methodAbisByName, methodAbisWithSameName => { + _.each(methodAbisWithSameName, (methodAbi, i: number) => { + if (methodAbisWithSameName.length > 1) { + const overloadedMethodId = i + 1; + const sanitizedMethodName = `${methodAbi.name}${overloadedMethodId}`; + const indexOfExistingAbiWithSanitizedMethodNameIfExists = _.findIndex( + methodAbis, + currentMethodAbi => currentMethodAbi.name === sanitizedMethodName, + ); + if (indexOfExistingAbiWithSanitizedMethodNameIfExists >= 0) { + const methodName = methodAbi.name; + throw new Error( + `Failed to rename overloaded method '${methodName}' to '${sanitizedMethodName}'. A method with this name already exists.`, + ); + } + methodAbi.name = sanitizedMethodName; + } + }); + }); + return contractAbi; + }, +}; diff --git a/packages/utils/src/constants.ts b/packages/utils/src/constants.ts new file mode 100644 index 000000000..2894d4747 --- /dev/null +++ b/packages/utils/src/constants.ts @@ -0,0 +1 @@ +export const NULL_BYTES = '0x'; diff --git a/packages/utils/src/index.ts b/packages/utils/src/index.ts index debcce746..709ec93b2 100644 --- a/packages/utils/src/index.ts +++ b/packages/utils/src/index.ts @@ -5,3 +5,5 @@ export { intervalUtils } from './interval_utils'; export { BigNumber } from './configured_bignumber'; export { AbiDecoder } from './abi_decoder'; export { logUtils } from './log_utils'; +export { abiUtils } from './abi_utils'; +export { NULL_BYTES } from './constants'; diff --git a/packages/web3-wrapper/CHANGELOG.json b/packages/web3-wrapper/CHANGELOG.json index 14e45dacb..473684087 100644 --- a/packages/web3-wrapper/CHANGELOG.json +++ b/packages/web3-wrapper/CHANGELOG.json @@ -10,7 +10,8 @@ "note": "Add static methods `toUnitAmount` and `toBaseUnitAmount`", "pr": 501 } - ] + ], + "timestamp": 1523462196 }, { "version": "0.5.0", diff --git a/packages/web3-wrapper/CHANGELOG.md b/packages/web3-wrapper/CHANGELOG.md index 3d498022a..8b0d4139b 100644 --- a/packages/web3-wrapper/CHANGELOG.md +++ b/packages/web3-wrapper/CHANGELOG.md @@ -5,6 +5,11 @@ Edit the package's CHANGELOG.json file only. CHANGELOG +## v0.6.0 - _April 11, 2018_ + + * Make `isAddress` and `toWei` static (#501) + * Add static methods `toUnitAmount` and `toBaseUnitAmount` (#501) + ## v0.5.0 - _April 2, 2018_ * Add `web3Wrapper.awaitTransactionMinedAsync` (#485) diff --git a/packages/web3-wrapper/README.md b/packages/web3-wrapper/README.md index 1ff85420a..d752a9de0 100644 --- a/packages/web3-wrapper/README.md +++ b/packages/web3-wrapper/README.md @@ -2,7 +2,7 @@ Wrapped version of web3 with a nicer interface that is used across 0x projects and packages. -### Read the [Documentation](0xproject.com/docs/web3_wrapper). +### Read the [Documentation](https://0xproject.com/docs/web3-wrapper). ## Installation diff --git a/packages/web3-wrapper/package.json b/packages/web3-wrapper/package.json index 910d4725e..5e6fc3618 100644 --- a/packages/web3-wrapper/package.json +++ b/packages/web3-wrapper/package.json @@ -1,12 +1,12 @@ { "name": "@0xproject/web3-wrapper", - "version": "0.5.0", + "version": "0.6.0", "description": "Wraps around web3 and gives a nicer interface", "main": "lib/src/index.js", "types": "lib/src/index.d.ts", "scripts": { "build:watch": "tsc -w", - "build": "tsc && copyfiles -u 2 './lib/monorepo_scripts/**/*' ./scripts", + "build": "tsc && copyfiles -u 3 './lib/src/monorepo_scripts/**/*' ./scripts", "clean": "shx rm -rf lib scripts", "lint": "tslint --project . 'src/**/*.ts'", "test": "run-s clean build run_mocha", @@ -40,27 +40,27 @@ }, "homepage": "https://github.com/0xProject/0x-monorepo/packages/web3-wrapper/README.md", "devDependencies": { - "@0xproject/monorepo-scripts": "^0.1.16", - "@0xproject/tslint-config": "^0.4.14", + "@0xproject/monorepo-scripts": "^0.1.17", + "@0xproject/tslint-config": "^0.4.15", "@types/lodash": "4.14.104", - "copyfiles": "^1.2.0", - "npm-run-all": "^4.1.2", - "shx": "^0.2.2", "chai": "^4.0.1", - "mocha": "^4.0.1", - "nyc": "^11.0.1", - "ganache-core": "0xProject/ganache-core", "chai-as-promised": "^7.1.0", "chai-bignumber": "^2.0.1", + "copyfiles": "^1.2.0", "dirty-chai": "^2.0.1", + "ganache-core": "0xProject/ganache-core", + "mocha": "^4.0.1", + "npm-run-all": "^4.1.2", + "nyc": "^11.0.1", + "shx": "^0.2.2", "tslint": "5.8.0", "typedoc": "0xProject/typedoc", "typescript": "2.7.1" }, "dependencies": { - "@0xproject/types": "^0.5.0", - "@0xproject/typescript-typings": "^0.0.3", - "@0xproject/utils": "^0.5.0", + "@0xproject/types": "^0.6.0", + "@0xproject/typescript-typings": "^0.1.0", + "@0xproject/utils": "^0.5.1", "ethers-contracts": "^2.2.1", "lodash": "^4.17.4", "web3": "^0.20.0" diff --git a/packages/website/package.json b/packages/website/package.json index 7d0c68b47..a8011dc8d 100644 --- a/packages/website/package.json +++ b/packages/website/package.json @@ -1,6 +1,6 @@ { "name": "@0xproject/website", - "version": "0.0.24", + "version": "0.0.25", "private": true, "description": "Website and 0x portal dapp", "scripts": { @@ -8,23 +8,19 @@ "clean": "shx rm -f public/bundle*", "lint": "tslint --project . 'ts/**/*.ts' 'ts/**/*.tsx'", "dev": "webpack-dev-server --content-base public --https", - "update_contracts": "for i in ${npm_package_config_artifacts}; do copyfiles -u 4 ../contracts/build/contracts/$i.json ../website/contracts; done;", "deploy_staging": "npm run build; aws s3 sync ./public/. s3://staging-0xproject --profile 0xproject --region us-east-1 --grants read=uri=http://acs.amazonaws.com/groups/global/AllUsers", "deploy_live": "npm run build; aws s3 sync ./public/. s3://0xproject.com --profile 0xproject --region us-east-1 --grants read=uri=http://acs.amazonaws.com/groups/global/AllUsers" }, - "config": { - "artifacts": "Mintable" - }, "author": "Fabio Berger", "license": "Apache-2.0", "dependencies": { - "0x.js": "^0.35.0", - "@0xproject/react-docs": "^0.0.6", - "@0xproject/react-shared": "^0.1.1", - "@0xproject/subproviders": "^0.8.4", - "@0xproject/typescript-typings": "^0.0.3", - "@0xproject/utils": "^0.5.0", - "@0xproject/web3-wrapper": "^0.5.0", + "0x.js": "^0.36.0", + "@0xproject/react-docs": "^0.0.7", + "@0xproject/react-shared": "^0.1.2", + "@0xproject/subproviders": "^0.8.5", + "@0xproject/typescript-typings": "^0.1.0", + "@0xproject/utils": "^0.5.1", + "@0xproject/web3-wrapper": "^0.6.0", "accounting": "^0.4.1", "basscss": "^8.0.3", "blockies": "^0.0.2", diff --git a/packages/website/ts/blockchain.ts b/packages/website/ts/blockchain.ts index fd34ab82d..3edc00644 100644 --- a/packages/website/ts/blockchain.ts +++ b/packages/website/ts/blockchain.ts @@ -20,8 +20,8 @@ import { InjectedWeb3Subprovider, ledgerEthereumBrowserClientFactoryAsync, LedgerSubprovider, - LedgerWalletSubprovider, - RedundantRPCSubprovider, + RedundantSubprovider, + Subprovider, } from '@0xproject/subproviders'; import { Provider } from '@0xproject/types'; import { BigNumber, intervalUtils, logUtils, promisify } from '@0xproject/utils'; @@ -54,6 +54,7 @@ import { utils } from 'ts/utils/utils'; import Web3 = require('web3'); import ProviderEngine = require('web3-provider-engine'); import FilterSubprovider = require('web3-provider-engine/subproviders/filters'); +import RpcSubprovider = require('web3-provider-engine/subproviders/rpc'); import * as MintableArtifacts from '../contracts/Mintable.json'; @@ -76,7 +77,7 @@ export class Blockchain { private _userAddressIfExists: string; private _cachedProvider: Provider; private _cachedProviderNetworkId: number; - private _ledgerSubprovider: LedgerWalletSubprovider; + private _ledgerSubprovider: LedgerSubprovider; private _defaultGasPrice: BigNumber; private static _getNameGivenProvider(provider: Provider): string { const providerType = utils.getProviderType(provider); @@ -98,7 +99,12 @@ export class Blockchain { provider = new ProviderEngine(); provider.addProvider(new InjectedWeb3Subprovider(injectedWeb3.currentProvider)); provider.addProvider(new FilterSubprovider()); - provider.addProvider(new RedundantRPCSubprovider(publicNodeUrlsIfExistsForNetworkId)); + const rpcSubproviders = _.map(publicNodeUrlsIfExistsForNetworkId, publicNodeUrl => { + return new RpcSubprovider({ + rpcUrl: publicNodeUrl, + }); + }); + provider.addProvider(new RedundantSubprovider(rpcSubproviders as Subprovider[])); provider.start(); } else if (doesInjectedWeb3Exist) { // Since no public node for this network, all requests go to injectedWeb3 instance @@ -110,7 +116,12 @@ export class Blockchain { provider = new ProviderEngine(); provider.addProvider(new FilterSubprovider()); const networkId = configs.IS_MAINNET_ENABLED ? constants.NETWORK_ID_MAINNET : constants.NETWORK_ID_KOVAN; - provider.addProvider(new RedundantRPCSubprovider(configs.PUBLIC_NODE_URLS_BY_NETWORK_ID[networkId])); + const rpcSubproviders = _.map(configs.PUBLIC_NODE_URLS_BY_NETWORK_ID[networkId], publicNodeUrl => { + return new RpcSubprovider({ + rpcUrl: publicNodeUrl, + }); + }); + provider.addProvider(new RedundantSubprovider(rpcSubproviders as Subprovider[])); provider.start(); } @@ -168,12 +179,6 @@ export class Blockchain { } this._ledgerSubprovider.setPath(path); } - public updateLedgerDerivationIndex(pathIndex: number) { - if (_.isUndefined(this._ledgerSubprovider)) { - return; // noop - } - this._ledgerSubprovider.setPathIndex(pathIndex); - } public async updateProviderToLedgerAsync(networkId: number) { utils.assert(!_.isUndefined(this._zeroEx), 'ZeroEx must be instantiated.'); @@ -201,7 +206,12 @@ export class Blockchain { this._ledgerSubprovider = new LedgerSubprovider(ledgerWalletConfigs); provider.addProvider(this._ledgerSubprovider); provider.addProvider(new FilterSubprovider()); - provider.addProvider(new RedundantRPCSubprovider(configs.PUBLIC_NODE_URLS_BY_NETWORK_ID[networkId])); + const rpcSubproviders = _.map(configs.PUBLIC_NODE_URLS_BY_NETWORK_ID[networkId], publicNodeUrl => { + return new RpcSubprovider({ + rpcUrl: publicNodeUrl, + }); + }); + provider.addProvider(new RedundantSubprovider(rpcSubproviders as Subprovider[])); provider.start(); this.networkId = networkId; this._dispatcher.updateNetworkId(this.networkId); diff --git a/packages/website/ts/components/dialogs/ledger_config_dialog.tsx b/packages/website/ts/components/dialogs/ledger_config_dialog.tsx index d7190c0bb..a72d33183 100644 --- a/packages/website/ts/components/dialogs/ledger_config_dialog.tsx +++ b/packages/website/ts/components/dialogs/ledger_config_dialog.tsx @@ -199,7 +199,6 @@ export class LedgerConfigDialog extends React.Component<LedgerConfigDialogProps, } private _onAddressSelected(selectedRowIndexes: number[]) { const selectedRowIndex = selectedRowIndexes[0]; - this.props.blockchain.updateLedgerDerivationIndex(selectedRowIndex); const selectedAddress = this.state.userAddresses[selectedRowIndex]; const selectAddressBalance = this.state.addressBalances[selectedRowIndex]; this.props.dispatcher.updateUserAddress(selectedAddress); diff --git a/packages/website/ts/components/footer.tsx b/packages/website/ts/components/footer.tsx index 6c0186ac0..487b039b2 100644 --- a/packages/website/ts/components/footer.tsx +++ b/packages/website/ts/components/footer.tsx @@ -114,8 +114,8 @@ export class Footer extends React.Component<FooterProps, FooterState> { }, { title: this.props.translate.get(Key.Careers, Deco.Cap), - isExternal: true, - path: constants.URL_ANGELLIST, + isExternal: false, + path: WebsitePaths.Jobs, }, { title: this.props.translate.get(Key.Contact, Deco.Cap), diff --git a/packages/website/ts/components/redirecter.tsx b/packages/website/ts/components/redirecter.tsx new file mode 100644 index 000000000..2e705af58 --- /dev/null +++ b/packages/website/ts/components/redirecter.tsx @@ -0,0 +1,10 @@ +import * as React from 'react'; +import { constants } from 'ts/utils/constants'; + +interface RedirecterProps { + location: string; +} + +export function Redirecter(props: RedirecterProps) { + window.location.href = constants.URL_ANGELLIST; +} diff --git a/packages/website/ts/components/top_bar/top_bar.tsx b/packages/website/ts/components/top_bar/top_bar.tsx index 4b2e82119..13351dcdc 100644 --- a/packages/website/ts/components/top_bar/top_bar.tsx +++ b/packages/website/ts/components/top_bar/top_bar.tsx @@ -15,7 +15,7 @@ import { TopBarMenuItem } from 'ts/components/top_bar/top_bar_menu_item'; import { DropDown } from 'ts/components/ui/drop_down'; import { Identicon } from 'ts/components/ui/identicon'; import { Dispatcher } from 'ts/redux/dispatcher'; -import { Deco, Key, ProviderType, WebsitePaths } from 'ts/types'; +import { Deco, Key, ProviderType, WebsiteLegacyPaths, WebsitePaths } from 'ts/types'; import { constants } from 'ts/utils/constants'; import { Translate } from 'ts/utils/translate'; @@ -462,7 +462,10 @@ export class TopBar extends React.Component<TopBarProps, TopBarState> { return _.includes(this.props.location.pathname, WebsitePaths.FAQ); } private _isViewing0xjsDocs() { - return _.includes(this.props.location.pathname, WebsitePaths.ZeroExJs); + return ( + _.includes(this.props.location.pathname, WebsitePaths.ZeroExJs) || + _.includes(this.props.location.pathname, WebsiteLegacyPaths.ZeroExJs) + ); } private _isViewingConnectDocs() { return _.includes(this.props.location.pathname, WebsitePaths.Connect); @@ -471,7 +474,10 @@ export class TopBar extends React.Component<TopBarProps, TopBarState> { return _.includes(this.props.location.pathname, WebsitePaths.SmartContracts); } private _isViewingWeb3WrapperDocs() { - return _.includes(this.props.location.pathname, WebsitePaths.Web3Wrapper); + return ( + _.includes(this.props.location.pathname, WebsitePaths.Web3Wrapper) || + _.includes(this.props.location.pathname, WebsiteLegacyPaths.Web3Wrapper) + ); } private _isViewingDeployerDocs() { return _.includes(this.props.location.pathname, WebsitePaths.Deployer); diff --git a/packages/website/ts/containers/connect_documentation.ts b/packages/website/ts/containers/connect_documentation.ts index bd6821d19..698d605c9 100644 --- a/packages/website/ts/containers/connect_documentation.ts +++ b/packages/website/ts/containers/connect_documentation.ts @@ -43,7 +43,7 @@ const docsInfoConfig: DocsInfoConfig = { sectionNameToModulePath: { [connectDocSections.httpClient]: ['"src/http_client"'], [connectDocSections.webSocketOrderbookChannel]: ['"src/ws_orderbook_channel"'], - [connectDocSections.types]: ['"src/types"'], + [connectDocSections.types]: ['"src/types"', '"types/src/index"'], }, menuSubsectionToVersionWhenIntroduced: {}, sections: connectDocSections, diff --git a/packages/website/ts/containers/deployer_documentation.ts b/packages/website/ts/containers/deployer_documentation.ts index 4e1c41f8c..e20cc195b 100644 --- a/packages/website/ts/containers/deployer_documentation.ts +++ b/packages/website/ts/containers/deployer_documentation.ts @@ -64,8 +64,8 @@ const docsInfoConfig: DocsInfoConfig = { 'TxData', ], typeNameToExternalLink: { - Web3: 'https://github.com/ethereum/wiki/wiki/JavaScript-API', - BigNumber: 'https://github.com/0xProject/web3-typescript-typings/blob/f5bcb96/index.d.ts#L127', + Web3: constants.URL_WEB3_DOCS, + BigNumber: constants.URL_BIGNUMBERJS_GITHUB, ContractInstance: 'https://github.com/0xProject/web3-typescript-typings/blob/f5bcb96/index.d.ts#L98', }, typeNameToPrefix: { diff --git a/packages/website/ts/containers/sol_cov_documentation.ts b/packages/website/ts/containers/sol_cov_documentation.ts index 2b901ec6f..58755c1e0 100644 --- a/packages/website/ts/containers/sol_cov_documentation.ts +++ b/packages/website/ts/containers/sol_cov_documentation.ts @@ -44,7 +44,7 @@ const docsInfoConfig: DocsInfoConfig = { }, sectionNameToModulePath: { [docSections.coverageSubprovider]: ['"sol-cov/src/coverage_subprovider"'], - [docSections.types]: ['"subproviders/src/types"'], + [docSections.types]: ['"subproviders/src/types"', '"types/src/index"'], }, menuSubsectionToVersionWhenIntroduced: {}, sections: docSections, @@ -52,11 +52,9 @@ const docsInfoConfig: DocsInfoConfig = { typeConfigs: { // Note: This needs to be kept in sync with the types exported in index.ts. Unfortunately there is // currently no way to extract the re-exported types from index.ts via TypeDoc :( - publicTypes: ['NextCallback', 'OnNextCompleted', 'ErrorCallback'], + publicTypes: ['NextCallback', 'OnNextCompleted', 'ErrorCallback', 'JSONRPCRequestPayload'], typeNameToExternalLink: {}, - typeNameToPrefix: { - JSONRPCRequestPayload: 'Web3', - }, + typeNameToPrefix: {}, typeNameToDocSection: {}, }, }; diff --git a/packages/website/ts/containers/subproviders_documentation.ts b/packages/website/ts/containers/subproviders_documentation.ts index 7aa05f9a5..a14d06a3f 100644 --- a/packages/website/ts/containers/subproviders_documentation.ts +++ b/packages/website/ts/containers/subproviders_documentation.ts @@ -30,6 +30,8 @@ const docSections = { redundantRPCSubprovider: 'redundantRPCSubprovider', ganacheSubprovider: 'ganacheSubprovider', nonceTrackerSubprovider: 'nonceTrackerSubprovider', + privateKeyWalletSubprovider: 'privateKeyWalletSubprovider', + mnemonicWalletSubprovider: 'mnemonicWalletSubprovider', types: docConstants.TYPES_SECTION_NAME, }; @@ -44,6 +46,8 @@ const docsInfoConfig: DocsInfoConfig = { subprovider: [docSections.subprovider], ['ledger-subprovider']: [docSections.ledgerSubprovider], ['ledger-node-hid-issue']: [docSections.ledgerNodeHid], + ['private-key-wallet-subprovider']: [docSections.privateKeyWalletSubprovider], + ['mnemonic-wallet-subprovider']: [docSections.mnemonicWalletSubprovider], ['factory-methods']: [docSections.factoryMethods], ['emptyWallet-subprovider']: [docSections.emptyWalletSubprovider], ['fakeGasEstimate-subprovider']: [docSections.fakeGasEstimateSubprovider], @@ -61,6 +65,8 @@ const docsInfoConfig: DocsInfoConfig = { sectionNameToModulePath: { [docSections.subprovider]: ['"subproviders/src/subproviders/subprovider"'], [docSections.ledgerSubprovider]: ['"subproviders/src/subproviders/ledger"'], + [docSections.privateKeyWalletSubprovider]: ['"subproviders/src/subproviders/private_key_wallet"'], + [docSections.mnemonicWalletSubprovider]: ['"subproviders/src/subproviders/mnemonic_wallet"'], [docSections.factoryMethods]: ['"subproviders/src/index"'], [docSections.emptyWalletSubprovider]: ['"subproviders/src/subproviders/empty_wallet_subprovider"'], [docSections.fakeGasEstimateSubprovider]: ['"subproviders/src/subproviders/fake_gas_estimate_subprovider"'], @@ -75,6 +81,8 @@ const docsInfoConfig: DocsInfoConfig = { visibleConstructors: [ docSections.subprovider, docSections.ledgerSubprovider, + docSections.privateKeyWalletSubprovider, + docSections.mnemonicWalletSubprovider, docSections.emptyWalletSubprovider, docSections.fakeGasEstimateSubprovider, docSections.injectedWeb3Subprovider, @@ -91,25 +99,22 @@ const docsInfoConfig: DocsInfoConfig = { 'ErrorCallback', 'ECSignature', 'JSONRPCRequestPayloadWithMethod', + 'JSONRPCRequestPayload', 'JSONRPCResponsePayload', 'AccountFetchingConfigs', 'LedgerEthereumClientFactoryAsync', 'PartialTxParams', 'LedgerEthereumClient', 'LedgerSubproviderConfigs', + 'MnemonicWalletSubproviderConfigs', + 'OnNextCompleted', + 'Provider', ], typeNameToExternalLink: { - Web3: 'https://github.com/ethereum/wiki/wiki/JavaScript-API', - BigNumber: 'https://github.com/0xProject/web3-typescript-typings/blob/f5bcb96/index.d.ts#L127', - JSONRPCRequestPayload: 'https://github.com/0xProject/web3-typescript-typings/blob/f5bcb96/index.d.ts#L137', - JSONRPCResponsePayload: 'https://github.com/0xProject/web3-typescript-typings/blob/f5bcb96/index.d.ts#L144', - Provider: 'https://github.com/0xProject/web3-typescript-typings/blob/f5bcb96/index.d.ts#L150', - }, - typeNameToPrefix: { - JSONRPCRequestPayload: 'Web3', - JSONRPCResponsePayload: 'Web3', - Provider: 'Web3', + Web3: constants.URL_WEB3_DOCS, + BigNumber: constants.URL_BIGNUMBERJS_GITHUB, }, + typeNameToPrefix: {}, }, }; const docsInfo = new DocsInfo(docsInfoConfig); diff --git a/packages/website/ts/containers/web3_wrapper_documentation.ts b/packages/website/ts/containers/web3_wrapper_documentation.ts index b0adad536..17754ca66 100644 --- a/packages/website/ts/containers/web3_wrapper_documentation.ts +++ b/packages/website/ts/containers/web3_wrapper_documentation.ts @@ -59,15 +59,36 @@ const docsInfoConfig: DocsInfoConfig = { 'BlockWithoutTransactionData', 'CallData', 'LogEntryEvent', + 'Provider', + 'AbiDefinition', + 'LogTopic', + 'JSONRPCRequestPayload', + 'JSONRPCResponsePayload', + 'BlockParamLiteral', + 'FunctionAbi', + 'EventAbi', + 'JSONRPCErrorCallback', + 'MethodAbi', + 'ConstructorAbi', + 'FallbackAbi', + 'EventParameter', + 'DataItem', + 'StateMutability', + 'Function', + 'Fallback', + 'Constructor', + 'Event', + 'ConstructorStateMutability', + 'TransactionReceiptWithDecodedLogs', + 'DecodedLogArgs', + 'LogWithDecodedArgs', + 'ContractEventArg', ], typeNameToExternalLink: { - Web3: 'https://github.com/ethereum/wiki/wiki/JavaScript-API', - Provider: 'https://github.com/0xProject/web3-typescript-typings/blob/f5bcb96/index.d.ts#L150', - BigNumber: 'http://mikemcl.github.io/bignumber.js', - }, - typeNameToPrefix: { - Provider: 'Web3', + Web3: constants.URL_WEB3_DOCS, + BigNumber: constants.URL_BIGNUMBERJS_GITHUB, }, + typeNameToPrefix: {}, typeNameToDocSection: { Web3Wrapper: docSections.web3Wrapper, }, diff --git a/packages/website/ts/containers/zero_ex_js_documentation.ts b/packages/website/ts/containers/zero_ex_js_documentation.ts index da8922e79..40853cb9e 100644 --- a/packages/website/ts/containers/zero_ex_js_documentation.ts +++ b/packages/website/ts/containers/zero_ex_js_documentation.ts @@ -168,21 +168,15 @@ const docsInfoConfig: DocsInfoConfig = { 'OrderStateWatcherConfig', 'FilterObject', 'OrderRelevantState', + 'JSONRPCRequestPayload', + 'JSONRPCResponsePayload', + 'JSONRPCErrorCallback', + 'LogEntryEvent', + 'LogEntry', ], - typeNameToPrefix: { - Provider: 'Web3', - DecodedLogEntryEvent: 'Web3', - LogEntryEvent: 'Web3', - CallData: 'Web3', - LogEntry: 'Web3', - }, + typeNameToPrefix: {}, typeNameToExternalLink: { - Web3: constants.URL_WEB3_DOCS, - Provider: constants.URL_WEB3_PROVIDER_DOCS, BigNumber: constants.URL_BIGNUMBERJS_GITHUB, - DecodedLogEntryEvent: constants.URL_WEB3_DECODED_LOG_ENTRY_EVENT, - LogEntryEvent: constants.URL_WEB3_LOG_ENTRY_EVENT, - LogEntry: 'https://github.com/0xProject/web3-typescript-typings/blob/f5bcb96/index.d.ts#L366', }, typeNameToDocSection: { ExchangeWrapper: 'exchange', diff --git a/packages/website/ts/index.tsx b/packages/website/ts/index.tsx index d542bd804..6b347145f 100644 --- a/packages/website/ts/index.tsx +++ b/packages/website/ts/index.tsx @@ -6,6 +6,7 @@ import { Provider } from 'react-redux'; import { BrowserRouter as Router, Redirect, Route, Switch } from 'react-router-dom'; import * as injectTapEventPlugin from 'react-tap-event-plugin'; import { createStore, Store as ReduxStore } from 'redux'; +import { Redirecter } from 'ts/components/redirecter'; import { About } from 'ts/containers/about'; import { FAQ } from 'ts/containers/faq'; import { Landing } from 'ts/containers/landing'; @@ -15,7 +16,7 @@ import { createLazyComponent } from 'ts/lazy_component'; import { trackedTokenStorage } from 'ts/local_storage/tracked_token_storage'; import { tradeHistoryStorage } from 'ts/local_storage/trade_history_storage'; import { reducer, State } from 'ts/redux/reducer'; -import { WebsitePaths } from 'ts/types'; +import { WebsiteLegacyPaths, WebsitePaths } from 'ts/types'; import { analytics } from 'ts/utils/analytics'; import { muiTheme } from 'ts/utils/mui_theme'; import { utils } from 'ts/utils/utils'; @@ -74,10 +75,12 @@ render( <Switch> <Route exact={true} path="/" component={Landing as any} /> <Redirect from="/otc" to={`${WebsitePaths.Portal}`} /> - <Route path={`${WebsitePaths.Portal}`} component={LazyPortal} /> - <Route path={`${WebsitePaths.FAQ}`} component={FAQ as any} /> - <Route path={`${WebsitePaths.About}`} component={About as any} /> - <Route path={`${WebsitePaths.Wiki}`} component={Wiki as any} /> + + <Route path={WebsitePaths.Jobs} component={Redirecter as any} /> + <Route path={WebsitePaths.Portal} component={LazyPortal} /> + <Route path={WebsitePaths.FAQ} component={FAQ as any} /> + <Route path={WebsitePaths.About} component={About as any} /> + <Route path={WebsitePaths.Wiki} component={Wiki as any} /> <Route path={`${WebsitePaths.ZeroExJs}/:version?`} component={LazyZeroExJSDocumentation} /> <Route path={`${WebsitePaths.Connect}/:version?`} component={LazyConnectDocumentation} /> <Route path={`${WebsitePaths.Deployer}/:version?`} component={LazyDeployerDocumentation} /> @@ -98,6 +101,17 @@ render( path={`${WebsitePaths.SmartContracts}/:version?`} component={LazySmartContractsDocumentation} /> + + {/* Legacy endpoints */} + <Route + path={`${WebsiteLegacyPaths.ZeroExJs}/:version?`} + component={LazyZeroExJSDocumentation} + /> + <Route + path={`${WebsiteLegacyPaths.Web3Wrapper}/:version?`} + component={LazyWeb3WrapperDocumentation} + /> + <Route component={NotFound as any} /> </Switch> </div> diff --git a/packages/website/ts/pages/about/about.tsx b/packages/website/ts/pages/about/about.tsx index 293580913..97be59526 100644 --- a/packages/website/ts/pages/about/about.tsx +++ b/packages/website/ts/pages/about/about.tsx @@ -2,11 +2,12 @@ import { colors, Styles } from '@0xproject/react-shared'; import * as _ from 'lodash'; import * as React from 'react'; import * as DocumentTitle from 'react-document-title'; +import { Link } from 'react-router-dom'; import { Footer } from 'ts/components/footer'; import { TopBar } from 'ts/components/top_bar/top_bar'; import { Profile } from 'ts/pages/about/profile'; import { Dispatcher } from 'ts/redux/dispatcher'; -import { ProfileInfo } from 'ts/types'; +import { ProfileInfo, WebsitePaths } from 'ts/types'; import { constants } from 'ts/utils/constants'; import { Translate } from 'ts/utils/translate'; import { utils } from 'ts/utils/utils'; @@ -250,9 +251,9 @@ export class About extends React.Component<AboutProps, AboutState> { }} > We are seeking outstanding candidates to{' '} - <a href={constants.URL_ANGELLIST} target="_blank" style={{ color: 'black' }}> + <Link to={WebsitePaths.Jobs} style={{ color: 'black' }}> join our team - </a> + </Link> . We value passion, diversity and unique perspectives. </div> </div> diff --git a/packages/website/ts/pages/documentation/doc_page.tsx b/packages/website/ts/pages/documentation/doc_page.tsx index 8ec1a023d..aca20447b 100644 --- a/packages/website/ts/pages/documentation/doc_page.tsx +++ b/packages/website/ts/pages/documentation/doc_page.tsx @@ -8,14 +8,14 @@ import semverSort = require('semver-sort'); import { SidebarHeader } from 'ts/components/sidebar_header'; import { TopBar } from 'ts/components/top_bar/top_bar'; import { Dispatcher } from 'ts/redux/dispatcher'; -import { DocPackages, Environments } from 'ts/types'; +import { DocPackages } from 'ts/types'; import { configs } from 'ts/utils/configs'; import { constants } from 'ts/utils/constants'; import { docUtils } from 'ts/utils/doc_utils'; import { Translate } from 'ts/utils/translate'; import { utils } from 'ts/utils/utils'; -const isDevelopment = configs.ENVIRONMENT === Environments.DEVELOPMENT; +const isDevelopmentOrStaging = utils.isDevelopment() || utils.isStaging(); const DEFAULT_ICON = 'docs.png'; const ZERO_EX_JS_VERSION_MISSING_TOPLEVEL_PATH = '0.32.4'; @@ -106,7 +106,9 @@ export class DocPage extends React.Component<DocPageProps, DocPageState> { } private async _fetchJSONDocsFireAndForgetAsync(preferredVersionIfExists?: string): Promise<void> { const folderName = docIdToSubpackageName[this.props.docsInfo.id]; - const docBucketRoot = isDevelopment ? constants.S3_STAGING_DOC_BUCKET_ROOT : constants.S3_DOC_BUCKET_ROOT; + const docBucketRoot = isDevelopmentOrStaging + ? constants.S3_STAGING_DOC_BUCKET_ROOT + : constants.S3_DOC_BUCKET_ROOT; const versionToFilePath = await docUtils.getVersionToFilePathAsync(docBucketRoot, folderName); const versions = _.keys(versionToFilePath); this.props.dispatcher.updateAvailableDocVersions(versions); diff --git a/packages/website/ts/pages/wiki/wiki.tsx b/packages/website/ts/pages/wiki/wiki.tsx index 23d1b52fb..1330cbf86 100644 --- a/packages/website/ts/pages/wiki/wiki.tsx +++ b/packages/website/ts/pages/wiki/wiki.tsx @@ -194,10 +194,7 @@ export class Wiki extends React.Component<WikiProps, WikiState> { ); }); return ( - <div key={`section-${sectionName}`} className="py2 md-px1 sm-px2"> - {/* <div className="pl2"> - <SectionHeader sectionName={sectionName} headerSize={HeaderSizes.H1} /> - </div> */} + <div key={`section-${sectionName}`} className="py2 md-px1 sm-px0"> {renderedArticles} </div> ); diff --git a/packages/website/ts/types.ts b/packages/website/ts/types.ts index dba59f704..2126c5c7b 100644 --- a/packages/website/ts/types.ts +++ b/packages/website/ts/types.ts @@ -341,21 +341,27 @@ export enum Docs { SmartContracts, } +export enum WebsiteLegacyPaths { + ZeroExJs = '/docs/0xjs', + Web3Wrapper = '/docs/web3_wrapper', +} + export enum WebsitePaths { Portal = '/portal', Wiki = '/wiki', - ZeroExJs = '/docs/0xjs', + ZeroExJs = '/docs/0x.js', Home = '/', FAQ = '/faq', About = '/about', Whitepaper = '/pdfs/0x_white_paper.pdf', SmartContracts = '/docs/contracts', Connect = '/docs/connect', - Web3Wrapper = '/docs/web3_wrapper', + Web3Wrapper = '/docs/web3-wrapper', Deployer = '/docs/deployer', JSONSchemas = '/docs/json-schemas', SolCov = '/docs/sol-cov', Subproviders = '/docs/subproviders', + Jobs = '/jobs', } export enum DocPackages { diff --git a/packages/website/ts/utils/mui_theme.ts b/packages/website/ts/utils/mui_theme.ts index d611f0895..f677b4625 100644 --- a/packages/website/ts/utils/mui_theme.ts +++ b/packages/website/ts/utils/mui_theme.ts @@ -17,7 +17,7 @@ export const muiTheme = getMuiTheme({ datePicker: { color: colors.grey700, textColor: colors.white, - calendarTextColor: colors.white, + calendarTextColor: colors.grey, selectColor: colors.darkestGrey, selectTextColor: colors.white, }, diff --git a/packages/website/ts/utils/utils.ts b/packages/website/ts/utils/utils.ts index afe159beb..53d60b3ce 100644 --- a/packages/website/ts/utils/utils.ts +++ b/packages/website/ts/utils/utils.ts @@ -5,7 +5,7 @@ import { BigNumber } from '@0xproject/utils'; import deepEqual = require('deep-equal'); import * as _ from 'lodash'; import * as moment from 'moment'; -import { Order, Providers, ScreenWidths, Side, SideToAssetToken, Token, TokenByAddress } from 'ts/types'; +import { Environments, Order, Providers, ScreenWidths, Side, SideToAssetToken, Token, TokenByAddress } from 'ts/types'; import { configs } from 'ts/utils/configs'; import { constants } from 'ts/utils/constants'; import * as u2f from 'ts/vendor/u2f_api'; @@ -292,4 +292,10 @@ export const utils = { } return parsedProviderName; }, + isDevelopment() { + return configs.ENVIRONMENT === Environments.DEVELOPMENT; + }, + isStaging() { + return _.includes(window.location.href, configs.DOMAIN_STAGING); + }, }; @@ -6,6 +6,25 @@ version "0.3.9" resolved "https://registry.yarnpkg.com/8fold-marked/-/8fold-marked-0.3.9.tgz#bb89c645612f8ccfaffac1ca6e3c11f168c9cf59" +"@0xproject/deployer@^0.3.5": + version "0.3.5" + resolved "https://registry.yarnpkg.com/@0xproject/deployer/-/deployer-0.3.5.tgz#3b4144ac62cfbbe4fc7174cbf92f29594f411973" + dependencies: + "@0xproject/json-schemas" "^0.7.19" + "@0xproject/types" "^0.5.0" + "@0xproject/typescript-typings" "^0.0.3" + "@0xproject/utils" "^0.5.0" + "@0xproject/web3-wrapper" "^0.5.0" + ethereumjs-util "^5.1.1" + isomorphic-fetch "^2.2.1" + lodash "^4.17.4" + require-from-string "^2.0.1" + semver "^5.5.0" + solc "^0.4.18" + web3 "^0.20.0" + web3-eth-abi "^1.0.0-beta.24" + yargs "^10.0.3" + "@0xproject/tslint-config@0.4.13": version "0.4.13" resolved "https://registry.yarnpkg.com/@0xproject/tslint-config/-/tslint-config-0.4.13.tgz#98c71c5ae5e80315a23eda0134cc9f6f4438cac2" @@ -15,6 +34,30 @@ tslint-eslint-rules "^4.1.1" tslint-react "^3.2.0" +"@0xproject/types@^0.5.0": + version "0.5.0" + resolved "https://registry.yarnpkg.com/@0xproject/types/-/types-0.5.0.tgz#ba3cfbc11a8c6344b57c9680aa7df2ea84b9bf05" + dependencies: + bignumber.js "~4.1.0" + +"@0xproject/typescript-typings@^0.0.3": + version "0.0.3" + resolved "https://registry.yarnpkg.com/@0xproject/typescript-typings/-/typescript-typings-0.0.3.tgz#3272080bde00ade0a970b0d236686b483b08a1d0" + dependencies: + "@0xproject/types" "^0.5.0" + bignumber.js "~4.1.0" + +"@0xproject/web3-wrapper@^0.5.0": + version "0.5.0" + resolved "https://registry.yarnpkg.com/@0xproject/web3-wrapper/-/web3-wrapper-0.5.0.tgz#99a1acea60a5c3163ac0be28f4c0577c3d43dec4" + dependencies: + "@0xproject/types" "^0.5.0" + "@0xproject/typescript-typings" "^0.0.3" + "@0xproject/utils" "^0.5.0" + ethers-contracts "^2.2.1" + lodash "^4.17.4" + web3 "^0.20.0" + "@ledgerhq/hw-app-eth@^4.3.0": version "4.7.3" resolved "https://registry.yarnpkg.com/@ledgerhq/hw-app-eth/-/hw-app-eth-4.7.3.tgz#d352e19658ae296532e522c53c8ec2a1a77b64e5" @@ -55,6 +98,12 @@ version "1.0.2" resolved "https://registry.yarnpkg.com/@types/bintrees/-/bintrees-1.0.2.tgz#0dfdce4eeebdf90427bd35b0e79dc248b3d157a6" +"@types/bip39@^2.4.0": + version "2.4.0" + resolved "https://registry.yarnpkg.com/@types/bip39/-/bip39-2.4.0.tgz#eee31a14abc8ebbb41a1ff14575c447b18346cbc" + dependencies: + "@types/node" "*" + "@types/body-parser@*", "@types/body-parser@^1.16.1": version "1.16.8" resolved "https://registry.yarnpkg.com/@types/body-parser/-/body-parser-1.16.8.tgz#687ec34140624a3bec2b1a8ea9268478ae8f3be3" @@ -220,6 +269,12 @@ version "8.10.0" resolved "https://registry.yarnpkg.com/@types/node/-/node-8.10.0.tgz#f5d649cc49af8ed6507d15dc6e9b43fe8b927540" +"@types/opn@^5.1.0": + version "5.1.0" + resolved "https://registry.yarnpkg.com/@types/opn/-/opn-5.1.0.tgz#bff7bc371677f4bdbb37884400e03fd81f743927" + dependencies: + "@types/node" "*" + "@types/query-string@^5.0.1": version "5.1.0" resolved "https://registry.yarnpkg.com/@types/query-string/-/query-string-5.1.0.tgz#7f40cdea49ddafa0ea4f3db35fb6c24d3bfd4dcc" @@ -734,10 +789,14 @@ async@2.6.0, async@^2.0.1, async@^2.1.2, async@^2.4.0, async@^2.5.0: dependencies: lodash "^4.14.0" -async@^0.9.0: +async@^0.9.0, async@~0.9.0: version "0.9.2" resolved "https://registry.yarnpkg.com/async/-/async-0.9.2.tgz#aea74d5e61c1f899613bf64bda66d4c78f2fd17d" +async@~1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/async/-/async-1.0.0.tgz#f8fc04ca3a13784ade9e1641af98578cfbd647a9" + async@~1.2.1: version "1.2.1" resolved "https://registry.yarnpkg.com/async/-/async-1.2.1.tgz#a4816a17cd5ff516dfa2c7698a453369b9790de0" @@ -1364,10 +1423,6 @@ big.js@^3.1.3: version "3.2.0" resolved "https://registry.yarnpkg.com/big.js/-/big.js-3.2.0.tgz#a5fc298b81b9e0dca2e458824784b65c52ba588e" -"bignumber.js@git+https://github.com/debris/bignumber.js#master": - version "2.0.7" - resolved "git+https://github.com/debris/bignumber.js#c7a38de919ed75e6fb6ba38051986e294b328df9" - "bignumber.js@git+https://github.com/debris/bignumber.js.git#94d7146671b9719e00a09c29b01a691bc85048c2": version "2.0.7" resolved "git+https://github.com/debris/bignumber.js.git#94d7146671b9719e00a09c29b01a691bc85048c2" @@ -1392,7 +1447,7 @@ bintrees@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/bintrees/-/bintrees-1.0.2.tgz#49f896d6e858a4a499df85c38fb399b9aff840f8" -bip39@^2.2.0: +bip39@^2.5.0: version "2.5.0" resolved "https://registry.yarnpkg.com/bip39/-/bip39-2.5.0.tgz#51cbd5179460504a63ea3c000db3f787ca051235" dependencies: @@ -2151,6 +2206,10 @@ colormin@^1.0.5: css-color-names "0.0.4" has "^1.0.1" +colors@1.0.x: + version "1.0.3" + resolved "https://registry.yarnpkg.com/colors/-/colors-1.0.3.tgz#0433f44d809680fdeb60ed260f1b0c262e82a40b" + colors@1.1.2, colors@~1.1.2: version "1.1.2" resolved "https://registry.yarnpkg.com/colors/-/colors-1.1.2.tgz#168a4701756b6a7f51a12ce0c97bfa28c084ed63" @@ -2741,6 +2800,10 @@ currently-unhandled@^0.4.1: dependencies: array-find-index "^1.0.1" +cycle@1.0.x: + version "1.0.3" + resolved "https://registry.yarnpkg.com/cycle/-/cycle-1.0.3.tgz#21e80b2be8580f98b468f379430662b046c34ad2" + cyclist@~0.2.2: version "0.2.2" resolved "https://registry.yarnpkg.com/cyclist/-/cyclist-0.2.2.tgz#1b33792e11e914a2fd6d6ed6447464444e5fa640" @@ -2906,6 +2969,10 @@ deep-equal@^1.0.0, deep-equal@^1.0.1, deep-equal@~1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/deep-equal/-/deep-equal-1.0.1.tgz#f5d260292b660e084eff4cdbc9f08ad3247448b5" +deep-equal@~0.2.1: + version "0.2.2" + resolved "https://registry.yarnpkg.com/deep-equal/-/deep-equal-0.2.2.tgz#84b745896f34c684e98f2ce0e42abaf43bba017d" + deep-extend@~0.4.0: version "0.4.2" resolved "https://registry.yarnpkg.com/deep-extend/-/deep-extend-0.4.2.tgz#48b699c27e334bf89f10892be432f6e4c7d34a7f" @@ -3163,6 +3230,10 @@ dot-prop@^4.1.0: dependencies: is-obj "^1.0.0" +dotenv@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/dotenv/-/dotenv-4.0.0.tgz#864ef1379aced55ce6f95debecdce179f7a0cd1d" + drbg.js@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/drbg.js/-/drbg.js-1.0.1.tgz#3e36b6c42b37043823cdbc332d58f31e2445480b" @@ -3562,7 +3633,7 @@ ethereumjs-util@^4.0.1, ethereumjs-util@^4.3.0, ethereumjs-util@^4.4.0: rlp "^2.0.0" secp256k1 "^3.0.1" -ethereumjs-util@^5.0.0, ethereumjs-util@^5.0.1, ethereumjs-util@^5.1.1, ethereumjs-util@^5.1.3, ethereumjs-util@^5.1.5: +ethereumjs-util@^5.0.0, ethereumjs-util@^5.1.1, ethereumjs-util@^5.1.3, ethereumjs-util@^5.1.5: version "5.1.5" resolved "https://registry.yarnpkg.com/ethereumjs-util/-/ethereumjs-util-5.1.5.tgz#2f02575852627d45622426f25ee4a0b5f377f27a" dependencies: @@ -3590,7 +3661,7 @@ ethereumjs-vm@2.3.3, ethereumjs-vm@^2.0.2: rustbn.js "~0.1.1" safe-buffer "^5.1.1" -ethereumjs-wallet@^0.6.0, ethereumjs-wallet@~0.6.0: +ethereumjs-wallet@~0.6.0: version "0.6.0" resolved "https://registry.yarnpkg.com/ethereumjs-wallet/-/ethereumjs-wallet-0.6.0.tgz#82763b1697ee7a796be7155da9dfb49b2f98cfdb" dependencies: @@ -3625,6 +3696,14 @@ ethjs-abi@0.1.8: js-sha3 "0.5.5" number-to-bn "1.7.0" +ethjs-abi@^0.2.1: + version "0.2.1" + resolved "https://registry.yarnpkg.com/ethjs-abi/-/ethjs-abi-0.2.1.tgz#e0a7a93a7e81163a94477bad56ede524ab6de533" + dependencies: + bn.js "4.11.6" + js-sha3 "0.5.5" + number-to-bn "1.7.0" + ethjs-unit@0.1.6: version "0.1.6" resolved "https://registry.yarnpkg.com/ethjs-unit/-/ethjs-unit-0.1.6.tgz#c665921e476e87bce2a9d588a6fe0405b2c41699" @@ -3847,6 +3926,10 @@ extsprintf@^1.2.0: version "1.4.0" resolved "https://registry.yarnpkg.com/extsprintf/-/extsprintf-1.4.0.tgz#e2689f8f356fad62cca65a3a91c5df5f9551692f" +eyes@0.1.x: + version "0.1.8" + resolved "https://registry.yarnpkg.com/eyes/-/eyes-0.1.8.tgz#62cf120234c683785d902348a800ef3e0cc20bc0" + fake-merkle-patricia-tree@^1.0.1, fake-merkle-patricia-tree@~1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/fake-merkle-patricia-tree/-/fake-merkle-patricia-tree-1.0.1.tgz#4b8c3acfb520afadf9860b1f14cd8ce3402cddd3" @@ -5034,6 +5117,10 @@ hyphenate-style-name@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/hyphenate-style-name/-/hyphenate-style-name-1.0.2.tgz#31160a36930adaf1fc04c6074f7eb41465d4ec4b" +i@0.3.x: + version "0.3.6" + resolved "https://registry.yarnpkg.com/i/-/i-0.3.6.tgz#d96c92732076f072711b6b10fd7d4f65ad8ee23d" + iconv-lite@0.4.19, iconv-lite@^0.4.17, iconv-lite@~0.4.13: version "0.4.19" resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.4.19.tgz#f7468f60135f5e5dad3399c0a81be9a1603a082b" @@ -5590,14 +5677,14 @@ isobject@^3.0.0, isobject@^3.0.1: version "3.0.1" resolved "https://registry.yarnpkg.com/isobject/-/isobject-3.0.1.tgz#4e431e92b11a9731636aa1f9c8d1ccbcfdab78df" -isomorphic-fetch@^2.1.1, isomorphic-fetch@^2.2.0, isomorphic-fetch@^2.2.1: +isomorphic-fetch@^2.1.1, isomorphic-fetch@^2.2.1: version "2.2.1" resolved "https://registry.yarnpkg.com/isomorphic-fetch/-/isomorphic-fetch-2.2.1.tgz#611ae1acf14f5e81f729507472819fe9733558a9" dependencies: node-fetch "^1.0.1" whatwg-fetch ">=0.10.0" -isstream@~0.1.2: +isstream@0.1.x, isstream@~0.1.2: version "0.1.2" resolved "https://registry.yarnpkg.com/isstream/-/isstream-0.1.2.tgz#47e63f7af55afa6f92e1500e690eb8b8529c099a" @@ -6771,7 +6858,7 @@ mkdirp-promise@^5.0.1: dependencies: mkdirp "*" -mkdirp@*, mkdirp@0.5.1, mkdirp@0.5.x, "mkdirp@>=0.5 0", mkdirp@^0.5.0, mkdirp@^0.5.1, mkdirp@~0.5.0, mkdirp@~0.5.1: +mkdirp@*, mkdirp@0.5.1, mkdirp@0.5.x, mkdirp@0.x.x, "mkdirp@>=0.5 0", mkdirp@^0.5.0, mkdirp@^0.5.1, mkdirp@~0.5.0, mkdirp@~0.5.1: version "0.5.1" resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-0.5.1.tgz#30057438eac6cf7f8c4767f38648d6697d75c903" dependencies: @@ -6909,6 +6996,10 @@ natives@^1.1.0: version "1.1.2" resolved "https://registry.yarnpkg.com/natives/-/natives-1.1.2.tgz#4437ca1ed8a7f047531ccdfaf2792853df4efa1c" +ncp@1.0.x: + version "1.0.1" + resolved "https://registry.yarnpkg.com/ncp/-/ncp-1.0.1.tgz#d15367e5cb87432ba117d2bf80fdf45aecfb4246" + negotiator@0.6.1: version "0.6.1" resolved "https://registry.yarnpkg.com/negotiator/-/negotiator-0.6.1.tgz#2b327184e8992101177b28563fb5e7102acd0ca9" @@ -7326,7 +7417,7 @@ opn@^4.0.0: object-assign "^4.0.1" pinkie-promise "^2.0.0" -opn@^5.1.0: +opn@^5.1.0, opn@^5.3.0: version "5.3.0" resolved "https://registry.yarnpkg.com/opn/-/opn-5.3.0.tgz#64871565c863875f052cfdf53d3e3cb5adb53b1c" dependencies: @@ -7683,10 +7774,14 @@ pkg-dir@^2.0.0: dependencies: find-up "^2.1.0" -pkginfo@^0.3.0: +pkginfo@0.3.x, pkginfo@^0.3.0: version "0.3.1" resolved "https://registry.yarnpkg.com/pkginfo/-/pkginfo-0.3.1.tgz#5b29f6a81f70717142e09e765bbeab97b4f81e21" +pkginfo@0.x.x: + version "0.4.1" + resolved "https://registry.yarnpkg.com/pkginfo/-/pkginfo-0.4.1.tgz#b5418ef0439de5425fc4995042dced14fb2a84ff" + plur@^2.1.2: version "2.1.2" resolved "https://registry.yarnpkg.com/plur/-/plur-2.1.2.tgz#7482452c1a0f508e3e344eaec312c91c29dc655a" @@ -8176,6 +8271,17 @@ promisify-child-process@^1.0.5: version "1.0.5" resolved "https://registry.yarnpkg.com/promisify-child-process/-/promisify-child-process-1.0.5.tgz#817ad1aec92c013d83bb37e1f143e9b4033d9669" +prompt@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/prompt/-/prompt-1.0.0.tgz#8e57123c396ab988897fb327fd3aedc3e735e4fe" + dependencies: + colors "^1.1.2" + pkginfo "0.x.x" + read "1.0.x" + revalidator "0.1.x" + utile "0.3.x" + winston "2.1.x" + prop-types@^15.5.10, prop-types@^15.5.4, prop-types@^15.5.6, prop-types@^15.5.7, prop-types@^15.5.8, prop-types@^15.6.0, prop-types@^15.6.1: version "15.6.1" resolved "https://registry.yarnpkg.com/prop-types/-/prop-types-15.6.1.tgz#36644453564255ddda391191fb3a125cbdf654ca" @@ -8648,7 +8754,7 @@ read-pkg@^3.0.0: normalize-package-data "^2.3.2" path-type "^3.0.0" -read@~1.0.5: +read@1.0.x, read@~1.0.5: version "1.0.7" resolved "https://registry.yarnpkg.com/read/-/read-1.0.7.tgz#b3da19bd052431a97671d44a42634adf710b40c4" dependencies: @@ -9014,13 +9120,17 @@ ret@~0.1.10: version "0.1.15" resolved "https://registry.yarnpkg.com/ret/-/ret-0.1.15.tgz#b8a4825d5bdb1fc3f6f53c2bc33f81388681c7bc" +revalidator@0.1.x: + version "0.1.8" + resolved "https://registry.yarnpkg.com/revalidator/-/revalidator-0.1.8.tgz#fece61bfa0c1b52a206bd6b18198184bdd523a3b" + right-align@^0.1.1: version "0.1.3" resolved "https://registry.yarnpkg.com/right-align/-/right-align-0.1.3.tgz#61339b722fe6a3515689210d24e14c96148613ef" dependencies: align-text "^0.1.1" -rimraf@2, rimraf@^2.2.8, rimraf@^2.5.1, rimraf@^2.5.4, rimraf@^2.6.1, rimraf@^2.6.2: +rimraf@2, rimraf@2.x.x, rimraf@^2.2.8, rimraf@^2.5.1, rimraf@^2.5.4, rimraf@^2.6.1, rimraf@^2.6.2: version "2.6.2" resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-2.6.2.tgz#2ed8150d24a16ea8651e6d6ef0f47c4158ce7a36" dependencies: @@ -9732,7 +9842,7 @@ stack-trace@0.0.9: version "0.0.9" resolved "https://registry.yarnpkg.com/stack-trace/-/stack-trace-0.0.9.tgz#a8f6eaeca90674c333e7c43953f275b451510695" -stack-trace@~0.0.9: +stack-trace@0.0.x, stack-trace@~0.0.9: version "0.0.10" resolved "https://registry.yarnpkg.com/stack-trace/-/stack-trace-0.0.10.tgz#547c70b347e8d32b4e108ea1a2a159e5fdde19c0" @@ -10382,15 +10492,6 @@ truffle-contract@2.0.1: truffle-contract-schema "0.0.5" web3 "^0.18.0" -truffle-hdwallet-provider@^0.0.3: - version "0.0.3" - resolved "https://registry.yarnpkg.com/truffle-hdwallet-provider/-/truffle-hdwallet-provider-0.0.3.tgz#0e1de02104b73d3875e1cf7093305b4ea8a2d843" - dependencies: - bip39 "^2.2.0" - ethereumjs-wallet "^0.6.0" - web3 "^0.18.2" - web3-provider-engine "^8.4.0" - tslib@^1.0.0, tslib@^1.7.1, tslib@^1.8.0, tslib@^1.8.1: version "1.9.0" resolved "https://registry.yarnpkg.com/tslib/-/tslib-1.9.0.tgz#e37a86fda8cbbaf23a057f473c9f4dc64e5fc2e8" @@ -10855,6 +10956,17 @@ util@0.10.3, util@^0.10.3: dependencies: inherits "2.0.1" +utile@0.3.x: + version "0.3.0" + resolved "https://registry.yarnpkg.com/utile/-/utile-0.3.0.tgz#1352c340eb820e4d8ddba039a4fbfaa32ed4ef3a" + dependencies: + async "~0.9.0" + deep-equal "~0.2.1" + i "0.3.x" + mkdirp "0.x.x" + ncp "1.0.x" + rimraf "2.x.x" + utils-merge@1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/utils-merge/-/utils-merge-1.0.1.tgz#9f95710f50a267947b2ccc124741c1028427e713" @@ -11216,25 +11328,6 @@ web3-provider-engine@^13.0.1, web3-provider-engine@^13.6.5: xhr "^2.2.0" xtend "^4.0.1" -web3-provider-engine@^8.4.0: - version "8.6.1" - resolved "https://registry.yarnpkg.com/web3-provider-engine/-/web3-provider-engine-8.6.1.tgz#4d86e19e30caaf97df351511ec0f60136e5b30eb" - dependencies: - async "^2.1.2" - clone "^2.0.0" - ethereumjs-block "^1.2.2" - ethereumjs-tx "^1.2.0" - ethereumjs-util "^5.0.1" - ethereumjs-vm "^2.0.2" - isomorphic-fetch "^2.2.0" - request "^2.67.0" - semaphore "^1.0.3" - solc "^0.4.2" - tape "^4.4.0" - web3 "^0.16.0" - xhr "^2.2.0" - xtend "^4.0.1" - web3-providers-http@1.0.0-beta.33: version "1.0.0-beta.33" resolved "https://registry.yarnpkg.com/web3-providers-http/-/web3-providers-http-1.0.0-beta.33.tgz#3b35ae00ee7df5b96b4934962ad4a86f2a5599c1" @@ -11285,16 +11378,7 @@ web3-utils@1.0.0-beta.33: underscore "1.8.3" utf8 "2.1.1" -web3@^0.16.0: - version "0.16.0" - resolved "https://registry.yarnpkg.com/web3/-/web3-0.16.0.tgz#a4554175cd462943035b1f1d39432f741c6b6019" - dependencies: - bignumber.js "git+https://github.com/debris/bignumber.js#master" - crypto-js "^3.1.4" - utf8 "^2.1.1" - xmlhttprequest "*" - -web3@^0.18.0, web3@^0.18.2: +web3@^0.18.0: version "0.18.4" resolved "https://registry.yarnpkg.com/web3/-/web3-0.18.4.tgz#81ec1784145491f2eaa8955b31c06049e07c5e7d" dependencies: @@ -11481,6 +11565,18 @@ window-size@^0.2.0: version "0.2.0" resolved "https://registry.yarnpkg.com/window-size/-/window-size-0.2.0.tgz#b4315bb4214a3d7058ebeee892e13fa24d98b075" +winston@2.1.x: + version "2.1.1" + resolved "https://registry.yarnpkg.com/winston/-/winston-2.1.1.tgz#3c9349d196207fd1bdff9d4bc43ef72510e3a12e" + dependencies: + async "~1.0.0" + colors "1.0.x" + cycle "1.0.x" + eyes "0.1.x" + isstream "0.1.x" + pkginfo "0.3.x" + stack-trace "0.0.x" + word-wrap@1.2.3: version "1.2.3" resolved "https://registry.yarnpkg.com/word-wrap/-/word-wrap-1.2.3.tgz#610636f6b1f703891bd34771ccb17fb93b47079c" @@ -11796,3 +11892,10 @@ yauzl@^2.4.2: dependencies: buffer-crc32 "~0.2.3" fd-slicer "~1.0.1" + +zeppelin-solidity@1.8.0: + version "1.8.0" + resolved "https://registry.yarnpkg.com/zeppelin-solidity/-/zeppelin-solidity-1.8.0.tgz#049fcde7daea9fc85210f8c6db9f8cd1ab8a853a" + dependencies: + dotenv "^4.0.0" + ethjs-abi "^0.2.1" |